proc虚拟文件系统中的Linux挂载点?

proc虚拟文件系统中的Linux挂载点?

我被要求将这个问题从 stackoverflow 移到这里。

我fork了guitmz的memrun repo(用于asm和go)。
我确实在我的 fork 中为 C 提供了 memrun 和 memfd_create :
https://github.com/Hermann-SW/memrun?organization=Hermann-SW&organization=Hermann-SW#fork-mission-statement

memfd_create.c创建一个内存文件(/memfd:...)并返回进程 pid 和内存文件描述符:

pi@raspberrypi400:~/memrun/C $ gcc memfd_create.c -o memfd_create
pi@raspberrypi400:~/memrun/C $ ./memfd_create
1880 3
pi@raspberrypi400:~/memrun/C $ ls -l /proc/1880/fd
total 0
lrwx------ 1 pi pi 64 Oct  6 20:54 0 -> /dev/pts/0
lrwx------ 1 pi pi 64 Oct  6 20:54 1 -> /dev/pts/0
lrwx------ 1 pi pi 64 Oct  6 20:54 2 -> /dev/pts/0
lrwx------ 1 pi pi 64 Oct  6 20:54 3 -> '/memfd:rab.oof (deleted)'
pi@raspberrypi400:~/memrun/C $ 

在内存文件中创建 10MB 文件系统的工作原理:

pi@raspberrypi400:~/memrun/C $ dd if=/dev/zero of=/proc/1880/fd/3 bs=1024 count=10240 2> /dev/null
pi@raspberrypi400:~/memrun/C $ mkfs.ext2 /proc/1880/fd/3 > /dev/null
mke2fs 1.44.5 (15-Dec-2018)
pi@raspberrypi400:~/memrun/C $

在 32 位 Raspberry Pi OS (debian) 以及 64 位 Intel Ubuntu 上,在 /proc(!) 下安装该文件系统是可行的:

pi@raspberrypi400:~/memrun/C $ ls -l /proc/1880/fd
total 12
drwx------ 2 root root 12288 Oct  6 20:56 lost+found
pi@raspberrypi400:~/memrun/C $ 

/proc 下的相同挂载不适用于 Red Hat Enterprise Linux:

$ ./memfd_create
26611 3
$ ls -l /proc/26611/fd
total 0
lrwx------. 1 stammw stammw 64 Oct  6 21:00 0 -> /dev/pts/0
lrwx------. 1 stammw stammw 64 Oct  6 21:00 1 -> /dev/pts/0
lrwx------. 1 stammw stammw 64 Oct  6 21:00 2 -> /dev/pts/0
lrwx------. 1 stammw stammw 64 Oct  6 21:00 3 -> '/memfd:rab.oof (deleted)'
$ 
$ dd if=/dev/zero of=/proc/26611/fd/3 bs=1024 count=10240 2> /dev/null
$ mkfs.ext2 /proc/26611/fd/3 > /dev/null
mke2fs 1.45.6 (20-Mar-2020)
$ 
$ sudo mount /proc/26611/fd/3 /proc/26611/fd
[sudo] password for stammw: 
mount: /proc/26611/fd: cannot mount /dev/loop0 read-only.
$

在 /proc 下安装应该根本不起作用吗?
如果应该的话,需要什么才能在 RHEL 的 /proc 下成功挂载?

也许我这样做的原因是:tcc“-run”选项增强了 g++/gcc,所有 gcc/g++ 临时文件以及 RAM 中的可执行文件,并从 RAM 执行:

pi@raspberrypi400:~/memrun/C $ fortune -s | bin/g++ -run demo.cpp foo 123
bar foo
Sorry.  I forget what I was going to say.
pi@raspberrypi400:~/memrun/C $ 
pi@raspberrypi400:~/memrun/C $ cat demo.cpp 
/**
*/
#include <iostream>

int main(int argc, char *argv[])
{
  printf("bar %s\n", argc>1 ? argv[1] : "(undef)");

  for(char c; std::cin.read(&c, 1); )  { std::cout << c; }

  return 0;
}
pi@raspberrypi400:~/memrun/C $

来自其他线程的第一个答案:

您的 RHEL 输出显示一个 .在权限之后,意味着还有其他 SELinux 权限在起作用。你能看到它们是什么吗? – 另一个人

在 RHEL 上:

$ sudo ls -Z /proc/26611/fd
[sudo] password for stammw: 
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 0
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 1
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 3
$
$ ls -Z /proc/26611 | grep fd$
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 fd
$

答案1

/proc 下的相同挂载不适用于 Red Hat Enterprise Linux:
mount: /proc/26611/fd: cannot mount /dev/loop0 read-only.

您应该查看日志,并尝试其中的内容;-)

[root@rhel8 ~]# journalctl --no-pager -n1 | sed 's/^ *//'
-- Logs begin at Thu 2021-10-07 03:05:03 BST, end at Thu 2021-10-07 03:10:49 BST. --
Oct 07 03:06:54 rhel8.od platform-python[2154]: SELinux is preventing mount from mounton access on the directory /proc/<pid>/fd.

*****  Plugin catchall (100. confidence) suggests   **************************

If you believe that mount should be allowed mounton access on the fd directory by default.
Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# ausearch -c 'mount' --raw | audit2allow -M my-mount
# semodule -X 300 -i my-mount.pp

但我认为这不是一个好主意。最好保持原样并尝试其他方法,而不是将其安装在/proc/<pid>/fd.

tcc“-run”选项增强了 g++/gcc,所有 gcc/g++ 临时文件以及 RAM 中的可执行文件,并从 RAM 执行:

临时目录或 tmpfs 就可以了,你让自己变得过于复杂了。

答案2

安装在下面/proc根本不起作用吗?

不,下面的目录/proc在这方面与其他目录没有什么不同,只要没有其他限制(请参阅其他回答),你可以在那里安装任何东西。

路径的一个特殊性/proc/<pid>/*是此类目录上的任何挂载都将自动延迟卸载 [1]<pid>终止时。

您可以使用该功能创建一个临时目录,当您的进程终止时(无论它如何终止),通过在/proc/self.

示例脚本:

#! /bin/sh
set -e
mount -t tmpfs tmpfs /proc/$$/attr
cd /proc/$$/attr
bash

这将使您处于当前目录位于 的 shell 中/proc/$$/attr,您可以在其中创建其他文件和目录,一旦您退出 shell,这些文件和目录就会消失。

更好的选择是创建一个私有挂载命名空间,这将为您提供更多关于挂载位置的选项:

$ export T=$(mktemp -d)
$ unshare -Urm 
root# mount -t tmpfs t $T
root# echo > $T/somefile
root# ls $T
somefile
root# exit
$ ls $T
<nothing left>

注意:在某些类似 Debian 的系统上,您必须启用sysctl kernel.unprivileged_userns_clone=1(以 root 身份)才能以普通用户身份运行它;或者,取而代之的是cap_sys_admin+eip二进制包装器可以取消共享挂载命名空间,将其挂载传播设置为私有,执行 tmpfs 挂载(无需创建额外的用户命名空间),然后执行另一个程序或脚本。


[1] 延迟卸载的目录保持“浮动”状态,直到所有对其中文件和目录的引用都被关闭。这会产生一个奇怪的情况,您有一个独立的(但功能齐全的)文件系统,它没有出现在 中/proc/mounts,并且getcwd(2)系统调用返回一个以(unreachable)/( 必须在 glibc 的包装器中修补以匹配 POSIX 的定义,这需要getcwd()失败或返回绝对路径):

# sleep 2 & mount -t tmpfs t /proc/$!/attr; cd /proc/$!/attr
[1] 6585
/proc/6585/attr# 
[1]+  Done                    sleep 2  (wd: ~)
/proc/6585/attr# /bin/pwd
/bin/pwd: couldn't find directory entry in '..' with matching i-node
/proc/6585/attr# strace /bin/pwd 2>&1 | grep cwd
getcwd("(unreachable)/", 4096)          = 15
/proc/6585/attr# mkdir sub        # you can still use the dir normally

请注意,您还可以懒洋洋umount(MNT_DETACH)使用/显式卸载文件系统umount -l

相关内容