Linux 有没有什么工具或方法能实现用普通用户运行本来是需要用 root 用户才能执行的程序?

146 天前
 wniming

主要是想用普通用户执行 dnf --installroot=/path/to/fedora_rootfs 这个命令,这个命令如果不用 root 用户执行会有如下报错:

Error: This command has to be run with superuser privileges (under the root user on most systems).

这个命令可以在非特权的 docker 容器内用容器的 root 用户执行运行,这样是可以实现不使用 host 的 root 用户运行的需求,但依赖 docker ,不太方便,我想找到一种用 nsenter 或 unshare 之类的命令来运行的方法。

本质上是想使用 linux 的 user namespace 功能来造一个 root 用户,这个 root 用户映射到系统的普通用户,想用这个 root 用户执行 dnf --installroot=/path/to/fedora_rootfs 来从外部给 fedora 虚拟机安装 rpm 包(我的虚拟机的磁盘镜象是 ext4 文件系统,可以用 fuse2fs -o fakeroot ~/fedora.raw /path/to/fedora_rootfs 命令实现用普通用户挂载,而且可以用普通用户去读写磁盘镜象内属于 root 用户的文件, 如果能实现用普通用户运行 dnf --installroot=/path/to/fedora_rootfs 的话,我就可以避免用 host 的 root 用户来管理虚拟机的磁盘镜象 )。

4942 次点击
所在节点    Linux
34 条回复
xscit
146 天前
setuid
sduoduo233
146 天前
https://github.com/proot-me/proot 我没试过,不过应该可以。android termux 就用 proot 实现免 root 的 chroot
cccer
146 天前
你提到可以用 docker 里的 root 执行,可实际上 docker 容器本身就需要 root 来启动,将用户加到 docker 组里面就相当于给了 root 权限,后面的同理。
wniming
146 天前
@cccer 不是的,我用的 docker 是完全不需要 root 权限的:

https://docs.docker.com/engine/security/rootless/

docker 服务都是用普通用户来运行的:

d@develop:~$ systemctl --user start docker
d@develop:~$ systemctl --user status docker
● docker.service - Docker Application Container Engine (Rootless)
Loaded: loaded (/home/d/.config/systemd/user/docker.service; enabled; preset: disabled)
Drop-In: /usr/lib/systemd/user/service.d
└─10-timeout-abort.conf
Active: active (running) since Sat 2024-06-29 18:44:10 CST; 19h ago
Docs: https://docs.docker.com/go/rootless/
Main PID: 5727 (rootlesskit)
Tasks: 170
Memory: 912.4M (peak: 1006.0M)
CPU: 1min 17.179s
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/docker.service
wniming
146 天前
@xscit 能具体一些吗?我就是想当伸手党才来问的,哈哈
dhb233
146 天前
把 dnf 命令加到 sudo 列表里,普通用户用 sudo 运行
0o0O0o0O0o
146 天前
wniming
146 天前
@dhb233 不行的,因为我是用

fuse2fs -o fakeroot ~/fedora.raw /path/to/fedora_rootfs

这种方式来挂载虚拟机的磁盘镜像的,这种方式就只能用普通用户来读写挂载目录的文件,用 root 用户反而没有读写的权限(所以用 sudo 肯定也不行)。

我觉得用基于命名空间的 root 用户是可以读写的,因为我把/path/to/fedora_rootfs 目录共享给 docker ,在 docker 内能用 root 用户读写这个目录,docker 的 root 用户就是通过命名空间技术映射到 host 的普通用户的。
wniming
146 天前
@0o0O0o0O0o fakeroot 的不是基于命名空间技术实现的,虽然可以用这个命令来骗过 dnf 命令, 让 dnf 命令不报那个需要特权用户的错,但执行到一半还是会报错:

d@develop:~$ fakeroot dnf --installroot=/home/d/.local/mnt/0 --releasever=/ --config /etc/dnf/dnf.conf install tcpdump
Last metadata expiration check: 0:04:10 ago on Sun 30 Jun 2024 02:58:04 PM CST.
Dependencies resolved.
===================================================================================================================================================================================================================
Package Architecture Version Repository Size
===================================================================================================================================================================================================================
Installing:
tcpdump x86_64 14:4.99.4-6.fc40 fedora 501 k

Transaction Summary
===================================================================================================================================================================================================================
Install 1 Package

Total size: 501 k
Installed size: 1.2 M
Is this ok [y/N]: y
Downloading Packages:
[SKIPPED] tcpdump-4.99.4-6.fc40.x86_64.rpm: Already downloaded
Running transaction check
Transaction check succeeded.
Running transaction test
RPM: error: Unable to change root directory: Operation not permitted
The downloaded packages were saved in cache until the next successful transaction.
You can remove cached packages by executing 'dnf clean packages'.
Error: Transaction test error:
Errors occurred during test transaction.

d@develop:~$
wniming
146 天前
@sduoduo233 这个不提供 x86_64 架构下的安装包,而且我比较倾向于用 fedora 官方支持的工具来实现。
fugu37
146 天前
不想用 docker 就用 podman ,这个发行版仓库内就有
0o0O0o0O0o
146 天前
@wniming #9 只看了标题。。。那 bubblewrap ?不过可能需要调试出合适的参数

`bwrap --ro-bind / / --unshare-all --uid 0 id -u`
leonshaw
146 天前
user namespace 应该可以,但是你需要一个 owner 是这个用户的 dnf 。比如说先 unshare ,再另装一套 dnf ,但是这可能又需要 chroot 或者 mount namespace... 最后可能还不如用容器简单。
yanqiyu
146 天前
我一般就直接 podman unshare -- ... 来实现了,这样还能获得一个完整的 uid 命名空间,因为做镜像之类的时候搞不好要用到除了 0 之外的 uid
SenLief
146 天前
podman
wniming
146 天前
@yanqiyu 你的这种方法完美解决了我的问题:

podman unshare dnf --installroot=/home/d/.local/mnt/0/ --releasever=/ --config /etc/dnf/dnf.conf install tar
crazyliu
146 天前
setuid, 只要打上这个标记就行了
xscit
146 天前
@wniming chmod +s 就可以让其他用户执行 root 的东西,具体可以搜一下
0o0O0o0O0o
146 天前
#16 所以你接受依赖 podman ,但不接受依赖 docker rootless 吗…
wniming
146 天前
@0o0O0o0O0o #19 用 podman 比 docker rootless 更好,主要有以下 2 点

1 ,podman 的安装比 docker rootless 更方便,一条 dnf 命令搞定
2 ,docker 貌似没有类似 podman 的 unshare 子命令,用 docker 的话我就必须再依赖一个 fedora 的 container , 还要做个目录共享,例如:

docker run --name fedora4 -itd -p 2223:22 -v /home/d/.local/mnt/0/:/mnt/0 fedora:latest

然后用如下命令来实现:

docker exec -it fedora4 dnf --installroot=/mnt/0/ --releasever=/ --setopt=reposdir=/etc/yum.repos.d/ --setopt=cachedir=/var/cache/dnf --config /etc/dnf/dnf.conf install tar


如果用 bwrap 也能做到类似 podman unshare 的效果的话我也很乐意尝试一下,但暂时不打算研究了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1053687

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX