]> git.proxmox.com Git - mirror_lxcfs.git/commitdiff
proc: Fix /proc/cpuinfo not respecting personality
authorMathias Gibbens <gibmat@debian.org>
Mon, 4 Sep 2023 00:13:57 +0000 (00:13 +0000)
committerMathias Gibbens <gibmat@debian.org>
Mon, 4 Sep 2023 00:13:57 +0000 (00:13 +0000)
It was found that the personality within the container was not being
properly respected, which for large numbers of CPUs would break
reporting of /proc/cpuinfo in arm32 containers running on an arm64 host.

Signed-off-by: Mathias Gibbens <gibmat@debian.org>
src/proc_fuse.c

index 25af10a1b4550b39b1d81f88574a6945e3d5262b..40eb26804253bbd6ede8666f280267cef151fe3d 100644 (file)
@@ -82,6 +82,45 @@ static off_t get_procfile_size(const char *path)
        return answer;
 }
 
+static off_t get_procfile_size_with_personality(const char *path)
+{
+       struct fuse_context *fc = fuse_get_context();
+       __u32 host_personality = liblxcfs_personality(), caller_personality;
+       bool change_personality;
+       int ret;
+       off_t procfile_size_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);
+       }
+
+       procfile_size_ret = get_procfile_size(path);
+
+       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 procfile_size_ret;
+}
+
 __lxcfs_fuse_ops int proc_getattr(const char *path, struct stat *sb)
 {
        struct timespec now;
@@ -106,7 +145,10 @@ __lxcfs_fuse_ops int proc_getattr(const char *path, struct stat *sb)
            strcmp(path, "/proc/swaps")         == 0 ||
            strcmp(path, "/proc/loadavg")       == 0 ||
            strcmp(path, "/proc/slabinfo")      == 0) {
-               sb->st_size = get_procfile_size(path);
+               if (liblxcfs_functional())
+                       sb->st_size = get_procfile_size_with_personality(path);
+               else
+                       sb->st_size = get_procfile_size(path);
                sb->st_mode = S_IFREG | 00444;
                sb->st_nlink = 1;
                return 0;
@@ -164,7 +206,10 @@ __lxcfs_fuse_ops int proc_open(const char *path, struct fuse_file_info *fi)
 
        info->type = type;
 
-       info->buflen = get_procfile_size(path) + BUF_RESERVE_SIZE;
+       if (liblxcfs_functional())
+               info->buflen = get_procfile_size_with_personality(path) + BUF_RESERVE_SIZE;
+       else
+               info->buflen = get_procfile_size(path) + BUF_RESERVE_SIZE;
 
        info->buf = zalloc(info->buflen);
        if (!info->buf)