【问题标题】:Executing mount system call from perl从 perl 执行 mount 系统调用
【发布时间】:2016-01-20 16:45:09
【问题描述】:

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

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

结果:

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

我无法使用system 调用mount 程序,因为我需要进行mount() 系统调用,而mount 程序似乎无法做到。更具体地说,我需要调用:

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

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

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

然后我得到以下错误:

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.

使用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);

但是这种拆分选项是行不通的。我需要 MS_BINDMS_REC|MS_PRIVATE 在对 mount 系统调用的一次调用中才能在非特权非共享挂载命名空间中工作。

那么如何在 perl 中执行我的初始系统调用而不会出现有关尝试修改只读值的错误消息?

编辑

谢天谢地,ikegami 很快指出了我在尝试使用 perl 的 syscall 函数时做错了什么,但万一有人在搜索如何仅使用 mount 从非特权挂载命名空间中绑定挂载目录时发现这一点命令行实用程序,方法如下:

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

这又会在内部调用以下系统调用:

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

MS_MGC_VAL 标志似乎只是为了向后兼容 2.4 之前的内核版本。重要的位是MS_BIND(用于执行绑定安装本身)和MS_REC(用于递归执行,以便其内容被其他安装隐藏的目录不会在安装命名空间中暴露其内容) .

所以现在我必须决定是使用 perl system 函数调用还是只使用 mount 系统调用,因为两者都一样好用 :)

【问题讨论】:

    标签: linux perl system-calls mount


    【解决方案1】:

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

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

    解决方案很简单。只需先将常量复制到变量中即可。

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

    测试:

    $ 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)
    

    【讨论】:

    • 你先生/女士让我开心!我现在看到syscall 的文档说“你不能使用字符串文字(或其他只读字符串)作为参数”......愚蠢的我,我应该有 RTFM......不过,既然你只是让我省了很多麻烦,我希望你能多多支持:)
    【解决方案2】:

    您可以在此处找到 Perl 的完整实现:​​https://github.com/i-MSCP/imscp/blob/1.5.x/engine/PerlLib/iMSCP/Mount.pm

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多