Writing linux mount utility

Intro

For long time wanted to understand how all stuff works on system level with linux. From one side mounting looked like some sort of magic. Decided to write my own mount utility. As its looks like only one syscall is needed to do that sys_mount. Other part of it is to see how to get all different file systems and find options that are possible to pass to mounted partition. All of this also preparations to write my own linux userspace and to have non-Linux distro. Main inspiration taken form arsv/minibase source code.

Syscalls

To implement mount there is enough just with one syscall mount. Its quite simple use case with just passing param to syscall is enough. There is more time spent to figure out with params are supported by each of filesystems.

int smount(
    const char *source, 
    const char *target,
    const char *filesystemtype,
    unsigned long mountflags,
    const void *data)
{
    int ret=-1;
    ret = syscall(SYS_mount,source,target,filesystemtype,mountflags,data);
    return ret;
}

Comparison to mount utility is straightforward.

mount arguments

Param Descriptio
source Source directory or file to mount
target Target directory where to mount
filesystemtype filesystem type
mountflags mount params
data specific to filesystem

Supported filesystems

Run command to find filesystems supported by currently running kernel

cat /proc/filesystems

Mount flags

Mount flags that can be passed when mounting filesystems, those are taken from kernel definition

#define _MS_RDONLY       (1<<0)
#define _MS_NOSUID       (1<<1)
#define _MS_NODEV        (1<<2)
#define _MS_NOEXEC       (1<<3)
#define _MS_SYNCHRONOUS  (1<<4)
#define _MS_REMOUNT      (1<<5)
#define _MS_MANDLOCK     (1<<6)
#define _MS_DIRSYNC      (1<<7)
#define _MS_NOATIME      (1<<10)
#define _MS_NODIRATIME   (1<<11)
#define _MS_BIND         (1<<12)
#define _MS_MOVE         (1<<13)
#define _MS_REC          (1<<14)
#define _MS_SILENT       (1<<15)
#define _MS_POSIXACL     (1<<16)
#define _MS_UNBINDABLE   (1<<17)
#define _MS_PRIVATE      (1<<18)
#define _MS_SLAVE        (1<<19)
#define _MS_SHARED       (1<<20)
#define _MS_RELATIME     (1<<21)
#define _MS_KERNMOUNT    (1<<22)
#define _MS_I_VERSION    (1<<23)
#define _MS_STRICTATIME  (1<<24)
#define _MS_LAZYTIME     (1<<25)

Kernel implementation

Latest linux kernel source code where mount syscall is define is
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/namespace.c

There are 2 definitions one for syscall and one for mount code

SYSCALL_DEFINE5(mount, char user *, dev_name, char user *, dir_name,
        char user *, type, unsigned long, flags, void user *, data)

long do_mount(
    const char *dev_name, 
    const char __user *dir_name,
    const char *type_page, 
    unsigned long flags, 
    void *data_page);

Filesystems

There is always a mystery where all parameters that are supported by particular filesystem comes from. I spent some time to find places where all params that are supported for procfs, devtmps and tempfs come from.

Procfs

Param Description
hidepid 0 - Everybody may access all proc, 1 - User can access only their own proc, not other /proc/[pid], 2 - As for mode 1, extra hides pid directories of others
gid usergroup who sees /proc in mode 0

Examples

Mount proc

nmount_static -t proc -d ma_proc -f hidepid=0 -v

Mount mqueue

nmount_static -t mqueue -d ma_quque -f noexec -v

Mount devtmpfs

mount_static -t devtmpfs -d mq_dev -f noexec -v

Mount tmpfs

nmount_static -t mqueue -d ma_ram -f noexec -v

Mount sysfs

nmount_static -t sysfs -d ma_sys -f silent -v

Links

http://git.main.lv/cgit.cgi/nmount.git/
https://man7.org/linux/man-pages/man7/signal.7.html
https://man7.org/linux/man-pages/man2/mount.2.html
https://github.com/arsv/minibase/blob/master/src/rootfs/kmount.c
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/namespace.c
[devtmpfs]
https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt
https://elixir.bootlin.com/linux/v4.14.184/source/drivers/base/devtmpfs.c
https://man7.org/linux/man-pages/man7/file-hierarchy.7.html
[procsf]
https://www.man7.org/linux/man-pages/man5/proc.5.html
https://elixir.bootlin.com/linux/v4.14.184/source/fs/proc/root.c#L33
https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt