]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
virt: Detect proot virtualisation by ptrace metadata
authorChris Down <chris@chrisdown.name>
Tue, 14 Apr 2020 17:15:04 +0000 (18:15 +0100)
committerChris Down <chris@chrisdown.name>
Wed, 15 Apr 2020 17:36:35 +0000 (18:36 +0100)
proot provides userspace-powered emulation of chroot and mount --bind,
lending it to be used on environments without unprivileged user
namespaces, or in otherwise restricted environments like Android.

In order to achieve this, proot makes use of the kernel's ptrace()
facility, which we can use in order to detect its presence. Since it
doesn't use any kind of namespacing, including PID namespacing, we don't
need to do any tricks when trying to get the tracer's metadata.

For our purposes, proot is listed as a "container", since we mostly use
this also as the bucket for non-container-but-container-like
technologies like WSL. As such, it seems like a good fit for this
section as well.

man/systemd-detect-virt.xml
man/systemd.unit.xml
src/basic/virt.c
src/basic/virt.h

index d599ac20f13f9deec96f970d2d355d25604633f8..77bdd80f32ab440e1a614fa58a7ee04ebb73e40b 100644 (file)
             <entry><varname>wsl</varname></entry>
             <entry><ulink url="https://docs.microsoft.com/en-us/windows/wsl/about">Windows Subsystem for Linux</ulink></entry>
           </row>
+
+          <row>
+            <entry><varname>proot</varname></entry>
+            <entry><ulink url="https://proot-me.github.io/">proot</ulink> userspace chroot/bind mount emulation</entry>
+          </row>
         </tbody>
       </tgroup>
     </table>
index d0de9aa5006fdb9e484969c5339446205f9e75c5..c26937e752f506428fe9c39658a028db36480019 100644 (file)
           <literal>podman</literal>,
           <literal>rkt</literal>,
           <literal>wsl</literal>,
+          <literal>proot</literal>,
           <literal>acrn</literal> to test
           against a specific implementation, or
           <literal>private-users</literal> to check whether we are running in a user namespace. See
index f567696265a0399f10f91567d85227d010941e76..c22bcf9aea7103da49a2535533faac4119e9426b 100644 (file)
@@ -441,6 +441,7 @@ static const char *const container_table[_VIRTUALIZATION_MAX] = {
         [VIRTUALIZATION_PODMAN]         = "podman",
         [VIRTUALIZATION_RKT]            = "rkt",
         [VIRTUALIZATION_WSL]            = "wsl",
+        [VIRTUALIZATION_PROOT]          = "proot",
 };
 
 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int);
@@ -449,6 +450,7 @@ int detect_container(void) {
         static thread_local int cached_found = _VIRTUALIZATION_INVALID;
         _cleanup_free_ char *m = NULL;
         _cleanup_free_ char *o = NULL;
+        _cleanup_free_ char *p = NULL;
         const char *e = NULL;
         int r;
 
@@ -472,6 +474,22 @@ int detect_container(void) {
                 goto finish;
         }
 
+        /* proot doesn't use PID namespacing, so we can just check if we have a matching tracer for this
+         * invocation without worrying about it being elsewhere.
+         */
+        r = get_proc_field("/proc/self/status", "TracerPid", WHITESPACE, &p);
+        if (r == 0 && !streq(p, "0")) {
+                pid_t ptrace_pid;
+                r = parse_pid(p, &ptrace_pid);
+                if (r == 0) {
+                        const char *pf = procfs_file_alloca(ptrace_pid, "comm");
+                        _cleanup_free_ char *ptrace_comm = NULL;
+                        r = read_one_line_file(pf, &ptrace_comm);
+                        if (r >= 0 && startswith(ptrace_comm, "proot"))
+                                return VIRTUALIZATION_PROOT;
+                }
+        }
+
         if (getpid_cached() == 1) {
                 /* If we are PID 1 we can just check our own environment variable, and that's authoritative.
                  * We distinguish three cases:
@@ -660,6 +678,7 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
         [VIRTUALIZATION_PODMAN] = "podman",
         [VIRTUALIZATION_RKT] = "rkt",
         [VIRTUALIZATION_WSL] = "wsl",
+        [VIRTUALIZATION_PROOT] = "proot",
         [VIRTUALIZATION_CONTAINER_OTHER] = "container-other",
 };
 
index 26f409afd018576f3ec17fdd6261fe900b6bf936..d58c582c912f11f27f84c6c9222e1bdea287585c 100644 (file)
@@ -34,6 +34,7 @@ enum {
         VIRTUALIZATION_PODMAN,
         VIRTUALIZATION_RKT,
         VIRTUALIZATION_WSL,
+        VIRTUALIZATION_PROOT,
         VIRTUALIZATION_CONTAINER_OTHER,
         VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER,