Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,12 @@ Terminal features:
- Paste via context menu (right-click to activate)
- Copy/paste in command line via pbcopy/pbpaste using OSC52 escape sequence

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

`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.

#### Alpine Linux

For example, you can run into a alpine root-filesystem by following steps:

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

#### Ubuntu

You can also use ubuntu root-filesystem by following steps:

- 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)
- Extract downloaded rootfs tar.gz file, for better compatibility, `/data/storage/el2/base/files/ubuntu_rootfs` is recommended.
```shell
mkdir -p /data/storage/el2/base/files/ubuntu_rootfs
tar xvf ubuntu-base-24.04.3-base-arm64.tar.gz -C /data/storage/el2/base/files/ubuntu_rootfs
```
- append `APT::Sandbox::User "root";` to `/etc/apt/apt.conf.d/01-vendor-ubuntu` file in ubuntu root filesyste
```shell
cd /data/storage/el2/base/files/ubuntu_rootfs
echo 'APT::Sandbox::User "root";' > etc/apt/apt.conf.d/01-vendor-ubuntu
```
- Run `qemu-vroot-aarch64` to run bash shell in root-filesystem
```shell
cd /data/storage/el2/base/files/ubuntu_rootfs
qemu-vroot-aarch64 -E PATH=/bin:/usr/bin:/sbin -E HOME=/root -L ./ ./bin/bash -c 'cd && bash'
```
- run `apt update`, the apt package manager works fine, you can install packages by `apt`

## Usage (if you are a Mac user):

1. Connect your MateBook Pro to Mac, and do the following steps on Mac
Expand Down
26 changes: 25 additions & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,12 @@ fi
- 通过上下文菜单粘贴(右键单击激活)
- 在命令行中通过 pbcopy/pbpaste 复制/粘贴(基于 OSC52 转义序列)

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

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

#### Alpine Linux

例如,你可以通过以下步骤运行 Alpine 根文件系统:

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

#### Ubuntu

你也可以按下列步骤使用 Ubuntu 根文件系统:

- 下载 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)
- 解压下载后的 tar.gz 文件, 考虑到兼容性, 推荐解压到`/data/storage/el2/base/files/ubuntu_rootfs`
```shell
mkdir -p /data/storage/el2/base/files/ubuntu_rootfs
tar xvf ubuntu-base-24.04.3-base-arm64.tar.gz -C /data/storage/el2/base/files/ubuntu_rootfs
```
- 将 `APT::Sandbox::User "root";` 添加到 Ubuntu 根文件系统中的 `/etc/apt/apt.conf.d/01-vendor-ubuntu` 文件中
```shell
cd /data/storage/el2/base/files/ubuntu_rootfs
echo 'APT::Sandbox::User "root";' > etc/apt/apt.conf.d/01-vendor-ubuntu
```
- 使用 `qemu-vroot-aarch64` 运行根文件系统中的 bash
```shell
cd /data/storage/el2/base/files/ubuntu_rootfs
qemu-vroot-aarch64 -E PATH=/bin:/usr/bin:/sbin -E HOME=/root -L ./ ./bin/bash -c 'cd && bash'
```
- 运行 `apt update`, 可以看到 `apt` 已经成功运行。你可以通过 `apt` 安装各种软件包

## 使用方法(如果你是 Mac 用户):

1. 将你的 MateBook Pro 连接到 Mac,并在 Mac 上执行以下步骤
Expand Down
201 changes: 201 additions & 0 deletions build-hnp/qemu-vroot/0010-emulate-root-user-to-guest.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
From 2c5d0fb67af88aaa8c12364e0d23c6e678fa42fc Mon Sep 17 00:00:00 2001
From: hackeris <hackeris@qq.com>
Date: Sat, 23 Aug 2025 09:22:29 +0800
Subject: [PATCH 10/11] emulate root user to guest

---
linux-user/syscall.c | 117 +++++++++++++++++++++++++------------------
util/path.c | 1 -
2 files changed, 68 insertions(+), 50 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 93212666364..d3ae503d758 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -12194,24 +12194,30 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_getuid
case TARGET_NR_getuid:
- return get_errno(high2lowuid(getuid()));
+ // return get_errno(high2lowuid(getuid()));
+ return 0;
#endif
#ifdef TARGET_NR_getgid
case TARGET_NR_getgid:
- return get_errno(high2lowgid(getgid()));
+ // return get_errno(high2lowgid(getgid()));
+ return 0;
#endif
#ifdef TARGET_NR_geteuid
case TARGET_NR_geteuid:
- return get_errno(high2lowuid(geteuid()));
+ // return get_errno(high2lowuid(geteuid()));
+ return 0;
#endif
#ifdef TARGET_NR_getegid
case TARGET_NR_getegid:
- return get_errno(high2lowgid(getegid()));
+ // return get_errno(high2lowgid(getegid()));
+ return 0;
#endif
case TARGET_NR_setreuid:
- return get_errno(sys_setreuid(low2highuid(arg1), low2highuid(arg2)));
+ // return get_errno(sys_setreuid(low2highuid(arg1), low2highuid(arg2)));
+ return 0;
case TARGET_NR_setregid:
- return get_errno(sys_setregid(low2highgid(arg1), low2highgid(arg2)));
+ // return get_errno(sys_setregid(low2highgid(arg1), low2highgid(arg2)));
+ return 0;
case TARGET_NR_getgroups:
{ /* the same code as for TARGET_NR_getgroups32 */
int gidsetsize = arg1;
@@ -12228,7 +12234,13 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
return -TARGET_ENOMEM;
}
}
- ret = get_errno(getgroups(gidsetsize, grouplist));
+ // ret = get_errno(getgroups(gidsetsize, grouplist));
+ if (gidsetsize > 0) {
+ grouplist[0] = 0;
+ ret = 1;
+ } else {
+ ret = 0;
+ }
if (!is_error(ret) && gidsetsize > 0) {
target_grouplist = lock_user(VERIFY_WRITE, arg2,
gidsetsize * sizeof(target_id), 0);
@@ -12245,54 +12257,59 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
}
case TARGET_NR_setgroups:
{ /* the same code as for TARGET_NR_setgroups32 */
- int gidsetsize = arg1;
- target_id *target_grouplist;
- g_autofree gid_t *grouplist = NULL;
- int i;
-
- if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
- return -TARGET_EINVAL;
- }
- if (gidsetsize > 0) {
- grouplist = g_try_new(gid_t, gidsetsize);
- if (!grouplist) {
- return -TARGET_ENOMEM;
- }
- target_grouplist = lock_user(VERIFY_READ, arg2,
- gidsetsize * sizeof(target_id), 1);
- if (!target_grouplist) {
- return -TARGET_EFAULT;
- }
- for (i = 0; i < gidsetsize; i++) {
- grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
- }
- unlock_user(target_grouplist, arg2,
- gidsetsize * sizeof(target_id));
- }
- return get_errno(sys_setgroups(gidsetsize, grouplist));
+ // int gidsetsize = arg1;
+ // target_id *target_grouplist;
+ // g_autofree gid_t *grouplist = NULL;
+ // int i;
+ //
+ // if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
+ // return -TARGET_EINVAL;
+ // }
+ // if (gidsetsize > 0) {
+ // grouplist = g_try_new(gid_t, gidsetsize);
+ // if (!grouplist) {
+ // return -TARGET_ENOMEM;
+ // }
+ // target_grouplist = lock_user(VERIFY_READ, arg2,
+ // gidsetsize * sizeof(target_id), 1);
+ // if (!target_grouplist) {
+ // return -TARGET_EFAULT;
+ // }
+ // for (i = 0; i < gidsetsize; i++) {
+ // grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
+ // }
+ // unlock_user(target_grouplist, arg2,
+ // gidsetsize * sizeof(target_id));
+ // }
+ // return get_errno(sys_setgroups(gidsetsize, grouplist));
+ return 0;
}
case TARGET_NR_fchown:
- return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
+ // return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
+ return 0;
#if defined(TARGET_NR_fchownat)
case TARGET_NR_fchownat:
- if (!(p = lock_user_string(arg2)))
- return -TARGET_EFAULT;
- ret = get_errno(fchownat(arg1, relocate_path_at(arg1, p, reloc, true), low2highuid(arg3),
- low2highgid(arg4), arg5));
- unlock_user(p, arg2, 0);
- return ret;
+ // if (!(p = lock_user_string(arg2)))
+ // return -TARGET_EFAULT;
+ // ret = get_errno(fchownat(arg1, relocate_path_at(arg1, p, reloc, true), low2highuid(arg3),
+ // low2highgid(arg4), arg5));
+ // unlock_user(p, arg2, 0);
+ // return ret;
+ return 0;
#endif
#ifdef TARGET_NR_setresuid
case TARGET_NR_setresuid:
- return get_errno(sys_setresuid(low2highuid(arg1),
- low2highuid(arg2),
- low2highuid(arg3)));
+ // return get_errno(sys_setresuid(low2highuid(arg1),
+ // low2highuid(arg2),
+ // low2highuid(arg3)));
+ return 0;
#endif
#ifdef TARGET_NR_getresuid
case TARGET_NR_getresuid:
{
- uid_t ruid, euid, suid;
- ret = get_errno(getresuid(&ruid, &euid, &suid));
+ uid_t ruid = 0, euid = 0, suid = 0;
+ // ret = get_errno(getresuid(&ruid, &euid, &suid));
+ ret = 0;
if (!is_error(ret)) {
if (put_user_id(high2lowuid(ruid), arg1)
|| put_user_id(high2lowuid(euid), arg2)
@@ -12304,15 +12321,17 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_getresgid
case TARGET_NR_setresgid:
- return get_errno(sys_setresgid(low2highgid(arg1),
- low2highgid(arg2),
- low2highgid(arg3)));
+ // return get_errno(sys_setresgid(low2highgid(arg1),
+ // low2highgid(arg2),
+ // low2highgid(arg3)));
+ return 0;
#endif
#ifdef TARGET_NR_getresgid
case TARGET_NR_getresgid:
{
- gid_t rgid, egid, sgid;
- ret = get_errno(getresgid(&rgid, &egid, &sgid));
+ gid_t rgid = 0, egid = 0, sgid = 0;
+ // ret = get_errno(getresgid(&rgid, &egid, &sgid));
+ ret = 0;
if (!is_error(ret)) {
if (put_user_id(high2lowgid(rgid), arg1)
|| put_user_id(high2lowgid(egid), arg2)
diff --git a/util/path.c b/util/path.c
index b8787076c32..acb6467aca0 100644
--- a/util/path.c
+++ b/util/path.c
@@ -47,7 +47,6 @@ static bool skip_relocation(const char* name)
|| strstr(name, "/sys/") == name
|| strcmp(name, "/sys") == 0
|| strcmp(name, "/etc/resolv.conf") == 0
- || strcmp(name, "/etc/passwd") == 0
|| strcmp(name, "/dev") == 0
|| strstr(name, "/dev/") == name
;
--
2.43.0

50 changes: 50 additions & 0 deletions build-hnp/qemu-vroot/0011-restore-path-from-host-to-guest.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
From 5e96a0b87e3c63d79f205220bde7bebe637fb910 Mon Sep 17 00:00:00 2001
From: hackeris <hackeris@qq.com>
Date: Sat, 23 Aug 2025 09:30:13 +0800
Subject: [PATCH 11/11] restore path from host to guest

---
linux-user/syscall.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d3ae503d758..5d32a02030b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8626,6 +8626,16 @@ ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz)
} else {
char reloc[PATH_MAX];
ret = get_errno(readlink(relocate_path_at(AT_FDCWD, pathname, reloc, false), buf, bufsiz));
+ if (ret > 0) {
+ char tmp[PATH_MAX];
+ memcpy(tmp, buf, ret);
+ tmp[ret] = '\0';
+
+ restore_path(tmp, reloc);
+
+ snprintf(buf, bufsiz, "%s", reloc);
+ ret = MIN(strlen(reloc), bufsiz);
+ }
}

return ret;
@@ -10812,6 +10822,16 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
memcpy(p2, user, ret);
} else {
ret = get_errno(readlinkat(arg1, relocate_path_at(arg1, p, reloc, false), p2, arg4));
+ if (ret > 0) {
+ char tmp[PATH_MAX];
+ memcpy(tmp, p2, ret);
+ tmp[ret] = '\0';
+
+ restore_path(tmp, reloc);
+
+ snprintf(p2, arg4, "%s", reloc);
+ ret = MIN(strlen(reloc), arg4);
+ }
}
unlock_user(p2, arg3, ret);
unlock_user(p, arg2, 0);
--
2.43.0

2 changes: 2 additions & 0 deletions build-hnp/qemu-vroot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ all: download/qemu-10
cd temp/qemu-10 && git apply ../../0007-fix-jit-on-OHOS.patch
cd temp/qemu-10 && git apply ../../0008-forward-dev-access-to-host.patch
cd temp/qemu-10 && git apply ../../0009-support-mount-root-of-host-to-guest.patch
cd temp/qemu-10 && git apply ../../0010-emulate-root-user-to-guest.patch
cd temp/qemu-10 && git apply ../../0011-restore-path-from-host-to-guest.patch
cd temp/qemu-10 && \
PKG_CONFIG=$(shell which pkg-config) \
PKG_CONFIG_PATH= \
Expand Down