Modetc: Move your dotfiles from kernel space

44 points by todsacerdoti 16 hours ago on hackernews | 37 comments

Move your dotfiles from kernel space

modetc is a Linux kernel module that rewrites paths in file operations: it allows you to move files wherever you like, while still having programs finding them where they expected them to be.

The main application is to move the dotfiles of those stubborn programs that refuse to adopt the XDG basedir standard, away from the home directory. For example, you can rewrite the path ~/.ssh to ~/var/lib/ssh. Yes, this is the nuclear option.

Configuration

modetc is configured via module parameters that are set either when manually loading the module (eg. modprobe modetc homedir=...) or by adding a line to /etc/modprobe.conf. The parameters are:

Name Default value Description
homedir N/A Home directory where to rewrite paths
default_rule N/A The default replacement for all dotfiles
rules_file /etc/modetc.conf File containing the rewriting rules
debug 0 Turn on debugging for rewriting rules

Rewriting rules

modetc rules are pure text search and replace: single substitution per file path, no wildcards nor regular expresssions.

The rules are only applied to absolute path with the homedir prefix followed by ., or to any relative path with a leading . when the working directory is homedir. Rules are tested in the order in which they appear in the rules file and the first to match will be applied. If no specific rule matches, the leading . of the file path will be replaced with the value of default_rule.

The rules file consists of one or more lines with one rule per line of the following format

Note: whitespace is significant and match and replacement are separate by a tab character. On a given line, anything after a # character is treated as a comment. Empty lines are also ignored.

Note: the maximum number of rules supported is 16.

Example rules file:

Runtime commands

You can send modetc some commands like reloading the rules file or pausing the rewriting by writing them to /proc/modetc. For example

Use cat /proc/modetc to get a list of commands and what they do.

Building

If using Nix, to build the module simply run

in the project directory. Before actually loading the module, it is a good idea to test that it works correctly in a virtual machine, so run:

If the test passed, you can safely load the module with

Note: when using a custom or older kernel, you may have to change the linux argument in the Nix expression (default.nix) to match yours.

Otherwise, install a basic toolchain and linux kernel module and run make to build the module.

Installing

On NixOS, add the following to your configuration:

This installs modetc, loads it on boot and configures it.

On other distributions, after building the module run make install.

How it works

kprobes are a mechanism to insert breakpoints at arbitrary locations in the Linux kernel code; they are a performance or debugging tool, but can also be used to alter the kernel behaviour at runtime.

modetc inserts kprobes in a few functions of the Virtual File System (VFS) layer and system calls implementations (do_symlinkat, do_rmdir, etc.) that handle file paths. When any of these functions is called, a breakpoint is hit and a small piece of code is inserted that modifies in-place the file path argument, so the file operation is carried out on the replacement file.

Note that only the cache containing the kernel space copy of a userspace file path (names_cachep) is actually changed, so the process that invoked the system call is completely oblivious to any of this.

Comparison with alternatives

libetc was an earlier solution based on intercepting the libc wrapper functions of the system calls using the LD_PRELOAD mechanism. Unlike libetc, modetc

  • works for statically linked programs
  • works for programs not using libc to invoke the system calls (e.g. sqlite)
  • can be quickly toggled without restarting programs

rewritefs solves most of the issues of libetc by rewriting the paths at the filesystem level, using a special FUSE filesystem. However, it severely degrades the performance of any I/O operation under the home directory. In comparison, modetc

  • does not require to mount a file system
  • runs in the kernel, with very little overhead
  • does not support regular expressions
  • can be quickly toggled without logging out

Similarly to both method, modetc is Linux-specific.

License

Copyright (C) 2025 Michele Guerini Rocco

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.