从perl执行mount系统调用

jos*_*sch 5 linux perl mount system-calls

如何mount从perl完成系统调用?下列:

$ret = syscall(&SYS_mount, "/proc", "/path/to/my/mount/point", 0, 0, 0);
Run Code Online (Sandbox Code Playgroud)

结果是:

Modification of a read-only value attempted at ...
Run Code Online (Sandbox Code Playgroud)

我无法调用mount程序,system因为我需要进行程序似乎不具备的mount()系统调用mount.更具体地说,我需要打电话:

mount("/proc", "/path/to/my/mpoint/point", NULL, MS_REC|MS_PRIVATE|MS_BIND, NULL);
Run Code Online (Sandbox Code Playgroud)

但是如果我尝试使用非特权的非共享mount linux命名空间运行以下命令:

mount --make-rprivate --bind /proc /path/to/my/mountpoint
Run Code Online (Sandbox Code Playgroud)

然后我收到以下错误:

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.
Run Code Online (Sandbox Code Playgroud)

使用strace揭示mount程序实际执行的操作是:

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

但是这种选择的分裂是行不通的.我需要MS_BINDMS_REC|MS_PRIVATE在一次调用mount系统时调用它在非特权的非共享mount命名空间中工作.

那么如何在没有关于尝试修改只读值的错误消息的情况下在perl中进行初始系统调用?

编辑:

值得庆幸的是,ikegami很快指出我在尝试使用perl syscall函数时做错了什么,但是如果有人在搜索如何使用mount命令行实用程序从无特权的mount命名空间中绑定挂载目录时发现这一点,请按以下方式操作:

mount --rbind /proc /path/to/my/mountpoint
Run Code Online (Sandbox Code Playgroud)

这反过来将在内部调用以下系统调用:

mount("proc", "/path/to/my/mountpoint", ..., MS_MGC_VAL|MS_BIND|MS_REC, 0);
Run Code Online (Sandbox Code Playgroud)

MS_MGC_VAL标志似乎是为了向后兼容2.4之前的内核版本.重要的部分是MS_BIND(用于执行绑定安装本身)和MS_REC(用于递归执行,以便将其内容隐藏的目录放入其中的目录不会在mount命名空间中公开其内容).

所以现在我必须决定是使用perl system函数调用还是只执行系统调用,mount因为两者都可以正常工作:)

ike*_*ami 8

syscall拒绝将指针传递给常量的字符串缓冲区,因为它不知道参数是否为char *const char *.

你不能使用字符串文字(或其他只读字符串)作为syscall的参数,因为Perl必须假设任何字符串指针都可以写入

解决方案很简单.首先将常量复制到变量中.

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

测试:

$ 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)
Run Code Online (Sandbox Code Playgroud)