Skip to content

Commit 0570129

Browse files
authored
Merge pull request TermonyHQ#107 from hackeris/vroot
vroot: emulate root user to geust to support ubuntu root filesystem
2 parents ac4a155 + 1714d21 commit 0570129

5 files changed

Lines changed: 303 additions & 2 deletions

File tree

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,12 @@ Terminal features:
9898
- Paste via context menu (right-click to activate)
9999
- Copy/paste in command line via pbcopy/pbpaste using OSC52 escape sequence
100100

101-
### Run in a new root file-system (Early experimental)
101+
### Run in a new root file-system
102102

103103
`qemu-vroot-aarch64` is a user mode qemu modified to to mimic proot behavior. It allows user to run linux binary(even for another CPU architecture) and switch to a new root-filesystem like chroot or proot.
104104

105+
#### Alpine Linux
106+
105107
For example, you can run into a alpine root-filesystem by following steps:
106108

107109
- Download alpine minimal root filesystem from https://alpinelinux.org/downloads/ (aarch64 or x64)
@@ -122,6 +124,28 @@ bin dev etc home lib media mnt opt proc root run sbi
122124
```
123125
- run `apk update`, the alpine package manager works fine, you can install packages by `apk`
124126

127+
#### Ubuntu
128+
129+
You can also use ubuntu root-filesystem by following steps:
130+
131+
- Download ubuntu base root filesystem from [Ubuntu Base 24.04](https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/) (ubuntu-base-24.04.3-base-arm64.tar.gz)
132+
- Extract downloaded rootfs tar.gz file, for better compatibility, `/data/storage/el2/base/files/ubuntu_rootfs` is recommended.
133+
```shell
134+
mkdir -p /data/storage/el2/base/files/ubuntu_rootfs
135+
tar xvf ubuntu-base-24.04.3-base-arm64.tar.gz -C /data/storage/el2/base/files/ubuntu_rootfs
136+
```
137+
- append `APT::Sandbox::User "root";` to `/etc/apt/apt.conf.d/01-vendor-ubuntu` file in ubuntu root filesyste
138+
```shell
139+
cd /data/storage/el2/base/files/ubuntu_rootfs
140+
echo 'APT::Sandbox::User "root";' > etc/apt/apt.conf.d/01-vendor-ubuntu
141+
```
142+
- Run `qemu-vroot-aarch64` to run bash shell in root-filesystem
143+
```shell
144+
cd /data/storage/el2/base/files/ubuntu_rootfs
145+
qemu-vroot-aarch64 -E PATH=/bin:/usr/bin:/sbin -E HOME=/root -L ./ ./bin/bash -c 'cd && bash'
146+
```
147+
- run `apt update`, the apt package manager works fine, you can install packages by `apt`
148+
125149
## Usage (if you are a Mac user):
126150

127151
1. Connect your MateBook Pro to Mac, and do the following steps on Mac

README_CN.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,12 @@ fi
9898
- 通过上下文菜单粘贴(右键单击激活)
9999
- 在命令行中通过 pbcopy/pbpaste 复制/粘贴(基于 OSC52 转义序列)
100100

101-
### 在新的根文件系统中运行(早期实验性)
101+
### 在新的根文件系统中运行
102102

103103
`qemu-vroot-aarch64` 是一个用户模式 qemu,修改后可以模拟 proot 行为。它允许用户运行 Linux 二进制文件(甚至是另一种 CPU 架构的),并像 chroot 或 proot 一样切换到新的根文件系统。
104104

105+
#### Alpine Linux
106+
105107
例如,你可以通过以下步骤运行 Alpine 根文件系统:
106108

107109
-[qemu_rootfs](https://gitee.com/nanqu_ait/termony-hnp/releases/tag/qemu_rootfs) 下载已经确认可以使用的最小根文件系统(aarch64 或 x64)
@@ -122,6 +124,28 @@ bin dev etc home lib media mnt opt proc root run sbi
122124
```
123125
- 运行 `apk update`,Alpine 包管理器运行良好,你可以通过 `apk` 安装包
124126

127+
#### Ubuntu
128+
129+
你也可以按下列步骤使用 Ubuntu 根文件系统:
130+
131+
- 下载 ubuntu base 根文件系统,地址:[Ubuntu Base 24.04](https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/) (选择文件:ubuntu-base-24.04.3-base-arm64.tar.gz)
132+
- 解压下载后的 tar.gz 文件, 考虑到兼容性, 推荐解压到`/data/storage/el2/base/files/ubuntu_rootfs`
133+
```shell
134+
mkdir -p /data/storage/el2/base/files/ubuntu_rootfs
135+
tar xvf ubuntu-base-24.04.3-base-arm64.tar.gz -C /data/storage/el2/base/files/ubuntu_rootfs
136+
```
137+
-`APT::Sandbox::User "root";` 添加到 Ubuntu 根文件系统中的 `/etc/apt/apt.conf.d/01-vendor-ubuntu` 文件中
138+
```shell
139+
cd /data/storage/el2/base/files/ubuntu_rootfs
140+
echo 'APT::Sandbox::User "root";' > etc/apt/apt.conf.d/01-vendor-ubuntu
141+
```
142+
- 使用 `qemu-vroot-aarch64` 运行根文件系统中的 bash
143+
```shell
144+
cd /data/storage/el2/base/files/ubuntu_rootfs
145+
qemu-vroot-aarch64 -E PATH=/bin:/usr/bin:/sbin -E HOME=/root -L ./ ./bin/bash -c 'cd && bash'
146+
```
147+
- 运行 `apt update`, 可以看到 `apt` 已经成功运行。你可以通过 `apt` 安装各种软件包
148+
125149
## 使用方法(如果你是 Mac 用户):
126150

127151
1. 将你的 MateBook Pro 连接到 Mac,并在 Mac 上执行以下步骤
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
From 2c5d0fb67af88aaa8c12364e0d23c6e678fa42fc Mon Sep 17 00:00:00 2001
2+
From: hackeris <hackeris@qq.com>
3+
Date: Sat, 23 Aug 2025 09:22:29 +0800
4+
Subject: [PATCH 10/11] emulate root user to guest
5+
6+
---
7+
linux-user/syscall.c | 117 +++++++++++++++++++++++++------------------
8+
util/path.c | 1 -
9+
2 files changed, 68 insertions(+), 50 deletions(-)
10+
11+
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
12+
index 93212666364..d3ae503d758 100644
13+
--- a/linux-user/syscall.c
14+
+++ b/linux-user/syscall.c
15+
@@ -12194,24 +12194,30 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
16+
#endif
17+
#ifdef TARGET_NR_getuid
18+
case TARGET_NR_getuid:
19+
- return get_errno(high2lowuid(getuid()));
20+
+ // return get_errno(high2lowuid(getuid()));
21+
+ return 0;
22+
#endif
23+
#ifdef TARGET_NR_getgid
24+
case TARGET_NR_getgid:
25+
- return get_errno(high2lowgid(getgid()));
26+
+ // return get_errno(high2lowgid(getgid()));
27+
+ return 0;
28+
#endif
29+
#ifdef TARGET_NR_geteuid
30+
case TARGET_NR_geteuid:
31+
- return get_errno(high2lowuid(geteuid()));
32+
+ // return get_errno(high2lowuid(geteuid()));
33+
+ return 0;
34+
#endif
35+
#ifdef TARGET_NR_getegid
36+
case TARGET_NR_getegid:
37+
- return get_errno(high2lowgid(getegid()));
38+
+ // return get_errno(high2lowgid(getegid()));
39+
+ return 0;
40+
#endif
41+
case TARGET_NR_setreuid:
42+
- return get_errno(sys_setreuid(low2highuid(arg1), low2highuid(arg2)));
43+
+ // return get_errno(sys_setreuid(low2highuid(arg1), low2highuid(arg2)));
44+
+ return 0;
45+
case TARGET_NR_setregid:
46+
- return get_errno(sys_setregid(low2highgid(arg1), low2highgid(arg2)));
47+
+ // return get_errno(sys_setregid(low2highgid(arg1), low2highgid(arg2)));
48+
+ return 0;
49+
case TARGET_NR_getgroups:
50+
{ /* the same code as for TARGET_NR_getgroups32 */
51+
int gidsetsize = arg1;
52+
@@ -12228,7 +12234,13 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
53+
return -TARGET_ENOMEM;
54+
}
55+
}
56+
- ret = get_errno(getgroups(gidsetsize, grouplist));
57+
+ // ret = get_errno(getgroups(gidsetsize, grouplist));
58+
+ if (gidsetsize > 0) {
59+
+ grouplist[0] = 0;
60+
+ ret = 1;
61+
+ } else {
62+
+ ret = 0;
63+
+ }
64+
if (!is_error(ret) && gidsetsize > 0) {
65+
target_grouplist = lock_user(VERIFY_WRITE, arg2,
66+
gidsetsize * sizeof(target_id), 0);
67+
@@ -12245,54 +12257,59 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
68+
}
69+
case TARGET_NR_setgroups:
70+
{ /* the same code as for TARGET_NR_setgroups32 */
71+
- int gidsetsize = arg1;
72+
- target_id *target_grouplist;
73+
- g_autofree gid_t *grouplist = NULL;
74+
- int i;
75+
-
76+
- if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
77+
- return -TARGET_EINVAL;
78+
- }
79+
- if (gidsetsize > 0) {
80+
- grouplist = g_try_new(gid_t, gidsetsize);
81+
- if (!grouplist) {
82+
- return -TARGET_ENOMEM;
83+
- }
84+
- target_grouplist = lock_user(VERIFY_READ, arg2,
85+
- gidsetsize * sizeof(target_id), 1);
86+
- if (!target_grouplist) {
87+
- return -TARGET_EFAULT;
88+
- }
89+
- for (i = 0; i < gidsetsize; i++) {
90+
- grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
91+
- }
92+
- unlock_user(target_grouplist, arg2,
93+
- gidsetsize * sizeof(target_id));
94+
- }
95+
- return get_errno(sys_setgroups(gidsetsize, grouplist));
96+
+ // int gidsetsize = arg1;
97+
+ // target_id *target_grouplist;
98+
+ // g_autofree gid_t *grouplist = NULL;
99+
+ // int i;
100+
+ //
101+
+ // if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
102+
+ // return -TARGET_EINVAL;
103+
+ // }
104+
+ // if (gidsetsize > 0) {
105+
+ // grouplist = g_try_new(gid_t, gidsetsize);
106+
+ // if (!grouplist) {
107+
+ // return -TARGET_ENOMEM;
108+
+ // }
109+
+ // target_grouplist = lock_user(VERIFY_READ, arg2,
110+
+ // gidsetsize * sizeof(target_id), 1);
111+
+ // if (!target_grouplist) {
112+
+ // return -TARGET_EFAULT;
113+
+ // }
114+
+ // for (i = 0; i < gidsetsize; i++) {
115+
+ // grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
116+
+ // }
117+
+ // unlock_user(target_grouplist, arg2,
118+
+ // gidsetsize * sizeof(target_id));
119+
+ // }
120+
+ // return get_errno(sys_setgroups(gidsetsize, grouplist));
121+
+ return 0;
122+
}
123+
case TARGET_NR_fchown:
124+
- return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
125+
+ // return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
126+
+ return 0;
127+
#if defined(TARGET_NR_fchownat)
128+
case TARGET_NR_fchownat:
129+
- if (!(p = lock_user_string(arg2)))
130+
- return -TARGET_EFAULT;
131+
- ret = get_errno(fchownat(arg1, relocate_path_at(arg1, p, reloc, true), low2highuid(arg3),
132+
- low2highgid(arg4), arg5));
133+
- unlock_user(p, arg2, 0);
134+
- return ret;
135+
+ // if (!(p = lock_user_string(arg2)))
136+
+ // return -TARGET_EFAULT;
137+
+ // ret = get_errno(fchownat(arg1, relocate_path_at(arg1, p, reloc, true), low2highuid(arg3),
138+
+ // low2highgid(arg4), arg5));
139+
+ // unlock_user(p, arg2, 0);
140+
+ // return ret;
141+
+ return 0;
142+
#endif
143+
#ifdef TARGET_NR_setresuid
144+
case TARGET_NR_setresuid:
145+
- return get_errno(sys_setresuid(low2highuid(arg1),
146+
- low2highuid(arg2),
147+
- low2highuid(arg3)));
148+
+ // return get_errno(sys_setresuid(low2highuid(arg1),
149+
+ // low2highuid(arg2),
150+
+ // low2highuid(arg3)));
151+
+ return 0;
152+
#endif
153+
#ifdef TARGET_NR_getresuid
154+
case TARGET_NR_getresuid:
155+
{
156+
- uid_t ruid, euid, suid;
157+
- ret = get_errno(getresuid(&ruid, &euid, &suid));
158+
+ uid_t ruid = 0, euid = 0, suid = 0;
159+
+ // ret = get_errno(getresuid(&ruid, &euid, &suid));
160+
+ ret = 0;
161+
if (!is_error(ret)) {
162+
if (put_user_id(high2lowuid(ruid), arg1)
163+
|| put_user_id(high2lowuid(euid), arg2)
164+
@@ -12304,15 +12321,17 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
165+
#endif
166+
#ifdef TARGET_NR_getresgid
167+
case TARGET_NR_setresgid:
168+
- return get_errno(sys_setresgid(low2highgid(arg1),
169+
- low2highgid(arg2),
170+
- low2highgid(arg3)));
171+
+ // return get_errno(sys_setresgid(low2highgid(arg1),
172+
+ // low2highgid(arg2),
173+
+ // low2highgid(arg3)));
174+
+ return 0;
175+
#endif
176+
#ifdef TARGET_NR_getresgid
177+
case TARGET_NR_getresgid:
178+
{
179+
- gid_t rgid, egid, sgid;
180+
- ret = get_errno(getresgid(&rgid, &egid, &sgid));
181+
+ gid_t rgid = 0, egid = 0, sgid = 0;
182+
+ // ret = get_errno(getresgid(&rgid, &egid, &sgid));
183+
+ ret = 0;
184+
if (!is_error(ret)) {
185+
if (put_user_id(high2lowgid(rgid), arg1)
186+
|| put_user_id(high2lowgid(egid), arg2)
187+
diff --git a/util/path.c b/util/path.c
188+
index b8787076c32..acb6467aca0 100644
189+
--- a/util/path.c
190+
+++ b/util/path.c
191+
@@ -47,7 +47,6 @@ static bool skip_relocation(const char* name)
192+
|| strstr(name, "/sys/") == name
193+
|| strcmp(name, "/sys") == 0
194+
|| strcmp(name, "/etc/resolv.conf") == 0
195+
- || strcmp(name, "/etc/passwd") == 0
196+
|| strcmp(name, "/dev") == 0
197+
|| strstr(name, "/dev/") == name
198+
;
199+
--
200+
2.43.0
201+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
From 5e96a0b87e3c63d79f205220bde7bebe637fb910 Mon Sep 17 00:00:00 2001
2+
From: hackeris <hackeris@qq.com>
3+
Date: Sat, 23 Aug 2025 09:30:13 +0800
4+
Subject: [PATCH 11/11] restore path from host to guest
5+
6+
---
7+
linux-user/syscall.c | 20 ++++++++++++++++++++
8+
1 file changed, 20 insertions(+)
9+
10+
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
11+
index d3ae503d758..5d32a02030b 100644
12+
--- a/linux-user/syscall.c
13+
+++ b/linux-user/syscall.c
14+
@@ -8626,6 +8626,16 @@ ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz)
15+
} else {
16+
char reloc[PATH_MAX];
17+
ret = get_errno(readlink(relocate_path_at(AT_FDCWD, pathname, reloc, false), buf, bufsiz));
18+
+ if (ret > 0) {
19+
+ char tmp[PATH_MAX];
20+
+ memcpy(tmp, buf, ret);
21+
+ tmp[ret] = '\0';
22+
+
23+
+ restore_path(tmp, reloc);
24+
+
25+
+ snprintf(buf, bufsiz, "%s", reloc);
26+
+ ret = MIN(strlen(reloc), bufsiz);
27+
+ }
28+
}
29+
30+
return ret;
31+
@@ -10812,6 +10822,16 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
32+
memcpy(p2, user, ret);
33+
} else {
34+
ret = get_errno(readlinkat(arg1, relocate_path_at(arg1, p, reloc, false), p2, arg4));
35+
+ if (ret > 0) {
36+
+ char tmp[PATH_MAX];
37+
+ memcpy(tmp, p2, ret);
38+
+ tmp[ret] = '\0';
39+
+
40+
+ restore_path(tmp, reloc);
41+
+
42+
+ snprintf(p2, arg4, "%s", reloc);
43+
+ ret = MIN(strlen(reloc), arg4);
44+
+ }
45+
}
46+
unlock_user(p2, arg3, ret);
47+
unlock_user(p, arg2, 0);
48+
--
49+
2.43.0
50+

build-hnp/qemu-vroot/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ all: download/qemu-10
1313
cd temp/qemu-10 && git apply ../../0007-fix-jit-on-OHOS.patch
1414
cd temp/qemu-10 && git apply ../../0008-forward-dev-access-to-host.patch
1515
cd temp/qemu-10 && git apply ../../0009-support-mount-root-of-host-to-guest.patch
16+
cd temp/qemu-10 && git apply ../../0010-emulate-root-user-to-guest.patch
17+
cd temp/qemu-10 && git apply ../../0011-restore-path-from-host-to-guest.patch
1618
cd temp/qemu-10 && \
1719
PKG_CONFIG=$(shell which pkg-config) \
1820
PKG_CONFIG_PATH= \

0 commit comments

Comments
 (0)