]> git.proxmox.com Git - mirror_lxcfs.git/commitdiff
cpuview: paththrough personality when reading cpuinfo
authorAlexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Mon, 28 Nov 2022 13:54:56 +0000 (14:54 +0100)
committerAlexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Wed, 30 Nov 2022 23:01:35 +0000 (00:01 +0100)
Let's change processing thread personality if caller personality
is different. It allows to read /proc/cpuinfo properly in
some cases (arm64 rely on current->personality inside Linux kernel).

https://github.com/lxc/lxcfs/issues/553

Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
src/bindings.c
src/bindings.h
src/proc_fuse.c

index fee7ede0dab672cf2a844fe3f0ccf3974f2f4b26..bbde48b2322350ca5e74fd59c7d3093616eb96ba 100644 (file)
@@ -45,6 +45,7 @@ static bool can_use_swap;
 static bool can_use_sys_cpu;
 static bool has_versioned_opts;
 static bool memory_is_cgroupv2;
+static __u32 host_personality;
 
 static volatile sig_atomic_t reload_successful;
 
@@ -73,6 +74,11 @@ bool liblxcfs_memory_is_cgroupv2(void)
        return memory_is_cgroupv2;
 }
 
+__u32 liblxcfs_personality(void)
+{
+       return host_personality;
+}
+
 /* Define pivot_root() if missing from the C library */
 #ifndef HAVE_PIVOT_ROOT
 static int pivot_root(const char *new_root, const char *put_old)
@@ -919,6 +925,11 @@ static void __attribute__((constructor)) lxcfs_init(void)
                goto broken_upgrade;
        }
 
+       if (get_task_personality(getpid(), &host_personality) < 0) {
+               lxcfs_info("Failed to retrieve host personality");
+               goto broken_upgrade;
+       }
+
        reload_successful = 1;
        return;
 
index e35423ac5da32fce9cbca29758232b0b05383a08..1624784e2870e3f2527afdfd53b5c0bc7a169c52 100644 (file)
@@ -107,6 +107,7 @@ extern bool liblxcfs_can_use_swap(void);
 extern bool liblxcfs_memory_is_cgroupv2(void);
 extern bool liblxcfs_can_use_sys_cpu(void);
 extern bool liblxcfs_has_versioned_opts(void);
+extern __u32 liblxcfs_personality(void);
 
 static inline bool lxcfs_has_opt(struct lxcfs_opts *opts, lxcfs_opt_t opt)
 {
index 29fbed53b3356412ab2daab5dbc6b703416c1ed8..00c5513d30de10ae1074d69b71e961c0d323f1c4 100644 (file)
@@ -24,6 +24,7 @@
 #include <sys/mman.h>
 #include <sys/mount.h>
 #include <sys/param.h>
+#include <sys/personality.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/sysinfo.h>
@@ -1500,6 +1501,46 @@ static int proc_slabinfo_read(char *buf, size_t size, off_t offset,
        return total_len;
 }
 
+static int proc_read_with_personality(int (*do_proc_read)(char *, size_t, off_t,
+                            struct fuse_file_info *), char *buf, size_t size, off_t offset,
+                            struct fuse_file_info *fi)
+{
+       struct fuse_context *fc = fuse_get_context();
+       __u32 host_personality = liblxcfs_personality(), caller_personality;
+       bool change_personality;
+       int ret, read_ret;
+
+       if (get_task_personality(fc->pid, &caller_personality) < 0)
+               return log_error(0, "Failed to get caller process (pid: %d) personality", fc->pid);
+
+       /* do we need to change thread personality? */
+       change_personality = host_personality != caller_personality;
+
+       if (change_personality) {
+               ret = personality(caller_personality);
+               if (ret == -1)
+                       return log_error(0, "Call to personality(%d) failed: %s\n",
+                               caller_personality, strerror(errno));
+
+               lxcfs_debug("task (tid: %d) personality was changed %d -> %d\n",
+                               (int)syscall(SYS_gettid), ret, caller_personality);
+       }
+
+       read_ret = do_proc_read(buf, size, offset, fi);
+
+       if (change_personality) {
+               ret = personality(host_personality);
+               if (ret == -1)
+                       return log_error(0, "Call to personality(%d) failed: %s\n",
+                               host_personality, strerror(errno));
+
+               lxcfs_debug("task (tid: %d) personality was restored %d -> %d\n",
+                               (int)syscall(SYS_gettid), ret, host_personality);
+       }
+
+       return read_ret;
+}
+
 __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
                               off_t offset, struct fuse_file_info *fi)
 {
@@ -1514,7 +1555,7 @@ __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
                                                  buf, size, offset, f);
        case LXC_TYPE_PROC_CPUINFO:
                if (liblxcfs_functional())
-                       return proc_cpuinfo_read(buf, size, offset, fi);
+                       return proc_read_with_personality(&proc_cpuinfo_read, buf, size, offset, fi);
 
                return read_file_fuse_with_offset(LXC_TYPE_PROC_CPUINFO_PATH,
                                                  buf, size, offset, f);