Making mount system call from perl

How can I make the mount system call from perl? Following:

 $ret = syscall(&SYS_mount, "/proc", "/path/to/my/mount/point", 0, 0, 0); 

leads to:

 Modification of a read-only value attempted at ... 

I cannot call the mount program using system , because I need to make a mount() system call, which apparently does not support the mount program. In particular, I need to call:

 mount("/proc", "/path/to/my/mpoint/point", NULL, MS_REC|MS_PRIVATE|MS_BIND, NULL); 

But if I try to run the following with an unprivileged namespace without mounting mount:

 mount --make-rprivate --bind /proc /path/to/my/mountpoint 

Then I get the following error:

 mount: wrong fs type, bad option, bad superblock on /proc, missing codepage or helper program, or other error In some cases useful info is found in syslog - try dmesg | tail or so. 

Using strace shows that mount is actually making a call:

 mount("/proc", "/path/to/my/mountpoint", ..., MS_MGC_VAL|MS_BIND, NULL); mount("none", "/path/to/my/mointpoint", NULL, MS_REC|MS_PRIVATE, NULL); 

But this separation of options does not work. I need MS_BIND and MS_REC|MS_PRIVATE in one call to the mount system call so that it works in an unprivileged namespace without access.

So, how can I make my initial system call in perl without an error message about trying to change a read-only value?

change

Fortunately, ikegami quickly pointed out what I did wrong when I try to use the perl syscall function, but in case someone finds it when you are looking for how to associate a directory mount from an unprivileged mount namespace only with the mount command utility lines, here's how:

 mount --rbind /proc /path/to/my/mountpoint 

This, in turn, will cause the following system call internally:

 mount("proc", "/path/to/my/mountpoint", ..., MS_MGC_VAL|MS_BIND|MS_REC, 0); 

The MS_MGC_VAL flag MS_MGC_VAL to be for backward compatibility with kernel versions prior to 2.4. The important bits are MS_BIND (to complete the binding installation) and MS_REC (in order to do this recursively, so that directories whose contents were hidden by other mounts mounted on them do not display their contents in the mount namespace).

So now I have to decide whether I go with the perl system function call or just the mount system code, because both work just as well :)

+5
source share
2 answers

syscall refuses to pass a pointer to the string buffer of the constant, because it has no idea if the argument is char * or const char * .

You cannot use a string literal (or other read-only string) as an argument to syscall, because Perl must assume that any string pointer can be written via

The solution is simple. First copy the constant into the variable.

 my $ret = syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0); 

Test:

 $ perl -E' require "syscall.ph"; my $ret = syscall(&SYS_mount, "/proc", "/path/to/my/mount/point", 0, 0, 0); say $ret; ' Modification of a read-only value attempted at -e line 3. $ perl -E' require "syscall.ph"; my $ret = syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0); say $ret; ' -1 $ strace perl -e' require "syscall.ph"; syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0); ' 2>&1 | grep mount mount("/proc", "/path/to/my/mount/point", NULL, 0, NULL) = -1 ENOENT (No such file or directory) 
+8
source

Here you can find the full implementation in Perl: https://github.com/i-MSCP/imscp/blob/1.5.x/engine/PerlLib/iMSCP/Mount.pm

+1
source

Source: https://habr.com/ru/post/1234206/


All Articles