title:Writing linux mount utility keywords:c,linux,kernel,mount # 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. ```c 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 ```c #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 ```c 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 ```bash nmount_static -t proc -d ma_proc -f hidepid=0 -v ``` ### Mount mqueue ```bash nmount_static -t mqueue -d ma_quque -f noexec -v ``` ### Mount devtmpfs ```bash mount_static -t devtmpfs -d mq_dev -f noexec -v ``` ### Mount tmpfs ```bash nmount_static -t mqueue -d ma_ram -f noexec -v ``` ### Mount sysfs ```bash 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