Hello community, here is the log from the commit of package lxcfs for openSUSE:Factory checked in at 2020-05-11 13:43:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/lxcfs (Old) and /work/SRC/openSUSE:Factory/.lxcfs.new.2738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "lxcfs" Mon May 11 13:43:27 2020 rev:13 rq:802545 version:4.0.3 Changes: -------- --- /work/SRC/openSUSE:Factory/lxcfs/lxcfs.changes 2020-04-27 23:42:28.388007241 +0200 +++ /work/SRC/openSUSE:Factory/.lxcfs.new.2738/lxcfs.changes 2020-05-11 13:43:34.821402967 +0200 @@ -1,0 +2,7 @@ +Sun May 10 05:58:58 UTC 2020 - Pavol Cupka <pal...@liguros.net> + +- update to LXCFS 4.0.3 (released on the 17th of April 2020) + detailed changelog: + https://discuss.linuxcontainers.org/t/lxcfs-4-0-3-lts-has-been-released/7470 + +------------------------------------------------------------------- Old: ---- lxcfs-4.0.1.tar.gz lxcfs-4.0.1.tar.gz.asc New: ---- lxcfs-4.0.3.tar.gz lxcfs-4.0.3.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ lxcfs.spec ++++++ --- /var/tmp/diff_new_pack.EwT0zv/_old 2020-05-11 13:43:36.313406133 +0200 +++ /var/tmp/diff_new_pack.EwT0zv/_new 2020-05-11 13:43:36.317406142 +0200 @@ -22,7 +22,7 @@ %endif Name: lxcfs -Version: 4.0.1 +Version: 4.0.3 Release: 0 Summary: FUSE filesystem for LXC License: Apache-2.0 ++++++ lxcfs-4.0.1.tar.gz -> lxcfs-4.0.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/config/init/systemd/Makefile.in new/lxcfs-4.0.3/config/init/systemd/Makefile.in --- old/lxcfs-4.0.1/config/init/systemd/Makefile.in 2020-03-19 15:21:45.000000000 +0100 +++ new/lxcfs-4.0.3/config/init/systemd/Makefile.in 2020-04-17 22:15:45.000000000 +0200 @@ -370,8 +370,8 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@INIT_SCRIPT_SYSTEMD_FALSE@uninstall-local: @INIT_SCRIPT_SYSTEMD_FALSE@install-data-local: +@INIT_SCRIPT_SYSTEMD_FALSE@uninstall-local: clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/config/init/upstart/Makefile.in new/lxcfs-4.0.3/config/init/upstart/Makefile.in --- old/lxcfs-4.0.1/config/init/upstart/Makefile.in 2020-03-19 15:21:45.000000000 +0100 +++ new/lxcfs-4.0.3/config/init/upstart/Makefile.in 2020-04-17 22:15:45.000000000 +0200 @@ -367,8 +367,8 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@INIT_SCRIPT_UPSTART_FALSE@install-data-local: @INIT_SCRIPT_UPSTART_FALSE@uninstall-local: +@INIT_SCRIPT_UPSTART_FALSE@install-data-local: clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/config/ltmain.sh new/lxcfs-4.0.3/config/ltmain.sh --- old/lxcfs-4.0.1/config/ltmain.sh 2020-02-16 13:06:34.000000000 +0100 +++ new/lxcfs-4.0.3/config/ltmain.sh 2020-03-02 10:35:42.000000000 +0100 @@ -31,7 +31,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.6 Debian-2.4.6-13" +VERSION="2.4.6 Debian-2.4.6-14" package_revision=2.4.6 @@ -2141,7 +2141,7 @@ compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) - version: $progname $scriptversion Debian-2.4.6-13 + version: $progname $scriptversion Debian-2.4.6-14 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/configure new/lxcfs-4.0.3/configure --- old/lxcfs-4.0.1/configure 2020-03-19 15:21:44.000000000 +0100 +++ new/lxcfs-4.0.3/configure 2020-04-17 22:15:44.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for lxcfs 4.0.1. +# Generated by GNU Autoconf 2.69 for lxcfs 4.0.3. # # Report bugs to <lxc-de...@lists.linuxcontainers.org>. # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='lxcfs' PACKAGE_TARNAME='lxcfs' -PACKAGE_VERSION='4.0.1' -PACKAGE_STRING='lxcfs 4.0.1' +PACKAGE_VERSION='4.0.3' +PACKAGE_STRING='lxcfs 4.0.3' PACKAGE_BUGREPORT='lxc-de...@lists.linuxcontainers.org' PACKAGE_URL='' @@ -1377,7 +1377,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures lxcfs 4.0.1 to adapt to many kinds of systems. +\`configure' configures lxcfs 4.0.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1448,7 +1448,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of lxcfs 4.0.1:";; + short | recursive ) echo "Configuration of lxcfs 4.0.3:";; esac cat <<\_ACEOF @@ -1576,7 +1576,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -lxcfs configure 4.0.1 +lxcfs configure 4.0.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1945,7 +1945,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by lxcfs $as_me 4.0.1, which was +It was created by lxcfs $as_me 4.0.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2938,7 +2938,7 @@ # Define the identity of the package. PACKAGE='lxcfs' - VERSION='4.0.1' + VERSION='4.0.3' cat >>confdefs.h <<_ACEOF @@ -14985,7 +14985,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by lxcfs $as_me 4.0.1, which was +This file was extended by lxcfs $as_me 4.0.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -15051,7 +15051,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -lxcfs config.status 4.0.1 +lxcfs config.status 4.0.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/configure.ac new/lxcfs-4.0.3/configure.ac --- old/lxcfs-4.0.1/configure.ac 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/configure.ac 2020-04-17 22:15:36.000000000 +0200 @@ -1,6 +1,6 @@ AC_PREREQ([2.69]) -AC_INIT([lxcfs], [4.0.1], [lxc-de...@lists.linuxcontainers.org]) +AC_INIT([lxcfs], [4.0.3], [lxc-de...@lists.linuxcontainers.org]) # We need pkg-config PKG_PROG_PKG_CONFIG diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/lxcfs.spec new/lxcfs-4.0.3/lxcfs.spec --- old/lxcfs-4.0.1/lxcfs.spec 2020-03-19 15:21:50.000000000 +0100 +++ new/lxcfs-4.0.3/lxcfs.spec 2020-04-17 22:15:51.000000000 +0200 @@ -20,7 +20,7 @@ Summary: Linux Containers File System Name: lxcfs -Version: 4.0.1 +Version: 4.0.3 Release: 1%{?dist} URL: https://linuxcontainers.org/lxcfs/downloads/ Source0: %{name}-%{version}.tar.gz diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/Makefile.am new/lxcfs-4.0.3/src/Makefile.am --- old/lxcfs-4.0.1/src/Makefile.am 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/Makefile.am 2020-04-17 22:15:36.000000000 +0200 @@ -20,6 +20,7 @@ proc_cpuview.c proc_cpuview.h \ proc_fuse.c proc_fuse.h \ proc_loadavg.c proc_loadavg.h \ + syscall_numbers.h \ sysfs_fuse.c sysfs_fuse.h \ utils.c utils.h liblxcfs_la_CFLAGS = $(AM_CFLAGS) @@ -48,6 +49,7 @@ proc_cpuview.c proc_cpuview.h \ proc_fuse.c proc_fuse.h \ proc_loadavg.c proc_loadavg.h \ + syscall_numbers.h \ sysfs_fuse.c sysfs_fuse.h \ utils.c utils.h liblxcfstest_la_CFLAGS = $(AM_CFLAGS) -DRELOADTEST @@ -75,6 +77,7 @@ proc_cpuview.h \ proc_fuse.h \ proc_loadavg.h \ + syscall_numbers.h \ sysfs_fuse.h \ utils.h diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/Makefile.in new/lxcfs-4.0.3/src/Makefile.in --- old/lxcfs-4.0.1/src/Makefile.in 2020-03-19 15:21:45.000000000 +0100 +++ new/lxcfs-4.0.3/src/Makefile.in 2020-04-17 22:15:45.000000000 +0200 @@ -424,6 +424,7 @@ proc_cpuview.c proc_cpuview.h \ proc_fuse.c proc_fuse.h \ proc_loadavg.c proc_loadavg.h \ + syscall_numbers.h \ sysfs_fuse.c sysfs_fuse.h \ utils.c utils.h @@ -442,6 +443,7 @@ proc_cpuview.c proc_cpuview.h \ proc_fuse.c proc_fuse.h \ proc_loadavg.c proc_loadavg.h \ + syscall_numbers.h \ sysfs_fuse.c sysfs_fuse.h \ utils.c utils.h @@ -460,6 +462,7 @@ proc_cpuview.h \ proc_fuse.h \ proc_loadavg.h \ + syscall_numbers.h \ sysfs_fuse.h \ utils.h diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/bindings.c new/lxcfs-4.0.3/src/bindings.c --- old/lxcfs-4.0.1/src/bindings.c 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/bindings.c 2020-04-17 22:15:36.000000000 +0200 @@ -46,6 +46,7 @@ #include "config.h" #include "memory_utils.h" #include "proc_cpuview.h" +#include "syscall_numbers.h" #include "utils.h" static bool can_use_pidfd; @@ -61,12 +62,7 @@ #ifndef HAVE_PIVOT_ROOT static int pivot_root(const char *new_root, const char *put_old) { -#ifdef __NR_pivot_root return syscall(__NR_pivot_root, new_root, put_old); -#else - errno = ENOSYS; - return -1; -#endif } #else extern int pivot_root(const char *new_root, const char *put_old); @@ -122,14 +118,17 @@ log_exit("%s - returned %d\n", strerror(ret), ret); } -static void store_lock(void) +static inline void unlock_mutex_function(pthread_mutex_t **mutex) { - lock_mutex(&pidns_store_mutex); + if (*mutex) + unlock_mutex(*mutex); } +#define __do_unlock call_cleaner(unlock_mutex) -static void store_unlock(void) +static pthread_mutex_t* __attribute__((warn_unused_result)) store_lock(void) { - unlock_mutex(&pidns_store_mutex); + lock_mutex(&pidns_store_mutex); + return &pidns_store_mutex; } /* /proc/ = 6 @@ -256,7 +255,7 @@ } /* Must be called under store_lock */ -static void save_initpid(struct stat *sb, pid_t pid) +static void save_initpid(ino_t pidns_inode, pid_t pid) { __do_free struct pidns_init_store *entry = NULL; __do_close int pidfd = -EBADF; @@ -275,13 +274,13 @@ if (stat(path, &st)) return; - entry = malloc(sizeof(*entry)); - if (entry) + entry = zalloc(sizeof(*entry)); + if (!entry) return; ino_hash = HASH(entry->ino); *entry = (struct pidns_init_store){ - .ino = sb->st_ino, + .ino = pidns_inode, .initpid = pid, .ctime = st.st_ctime, .next = pidns_hash_table[ino_hash], @@ -300,12 +299,12 @@ * otherwise. * Must be called under store_lock */ -static struct pidns_init_store *lookup_verify_initpid(struct stat *sb) +static struct pidns_init_store *lookup_verify_initpid(ino_t pidns_inode) { - struct pidns_init_store *entry = pidns_hash_table[HASH(sb->st_ino)]; + struct pidns_init_store *entry = pidns_hash_table[HASH(pidns_inode)]; while (entry) { - if (entry->ino == sb->st_ino) { + if (entry->ino == pidns_inode) { if (initpid_still_valid(entry)) { entry->lastcheck = time(NULL); return entry; @@ -338,7 +337,7 @@ * stack sizes: 8MB. */ #define __LXCFS_STACK_SIZE (8 * 1024 * 1024) -static pid_t lxcfs_clone(int (*fn)(void *), void *arg, int flags) +pid_t lxcfs_clone(int (*fn)(void *), void *arg, int flags) { pid_t ret; void *stack; @@ -399,9 +398,13 @@ { char v = '0'; pid_t pid_ret = -1; + struct ucred cred = { + .pid = -1, + .uid = -1, + .gid = -1, + }; pid_t pid; int sock[2]; - struct ucred cred; if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sock) < 0) return -1; @@ -432,6 +435,7 @@ pid_t lookup_initpid_in_store(pid_t pid) { + __do_unlock pthread_mutex_t *store_mutex = NULL; pid_t answer = 0; char path[LXCFS_PROC_PID_NS_LEN]; struct stat st; @@ -439,19 +443,24 @@ snprintf(path, sizeof(path), "/proc/%d/ns/pid", pid); - store_lock(); if (stat(path, &st)) goto out; - entry = lookup_verify_initpid(&st); + store_mutex = store_lock(); + + entry = lookup_verify_initpid(st.st_ino); if (entry) { answer = entry->initpid; goto out; } + /* release the mutex as the following call is expensive */ + unlock_mutex(move_ptr(store_mutex)); answer = get_init_pid_for_task(pid); + store_mutex = store_lock(); + if (answer > 0) - save_initpid(&st, answer); + save_initpid(st.st_ino, answer); out: /* @@ -460,8 +469,6 @@ */ prune_initpid_store(); - store_unlock(); - return answer; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/bindings.h new/lxcfs-4.0.3/src/bindings.h --- old/lxcfs-4.0.1/src/bindings.h 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/bindings.h 2020-04-17 22:15:36.000000000 +0200 @@ -103,4 +103,6 @@ return sigaction(signo, &action, NULL); } +extern pid_t lxcfs_clone(int (*fn)(void *), void *arg, int flags); + #endif /* __LXCFS_BINDINGS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/cgroup_fuse.c new/lxcfs-4.0.3/src/cgroup_fuse.c --- old/lxcfs-4.0.1/src/cgroup_fuse.c 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/cgroup_fuse.c 2020-04-17 22:15:36.000000000 +0200 @@ -62,7 +62,7 @@ static inline int get_cgroup_fd_handle_named(const char *controller) { - if (strcmp(controller, "systemd") == 0) + if (controller && strcmp(controller, "systemd") == 0) return get_cgroup_fd("name=systemd"); return get_cgroup_fd(controller); @@ -70,7 +70,7 @@ static char *get_pid_cgroup_handle_named(pid_t pid, const char *controller) { - if (strcmp(controller, "systemd") == 0) + if (controller && strcmp(controller, "systemd") == 0) return get_pid_cgroup(pid, "name=systemd"); return get_pid_cgroup(pid, controller); @@ -80,7 +80,7 @@ const char *controller, const char *cgroup, const char *file, char **value) { - if (strcmp(controller, "systemd") == 0) + if (controller && strcmp(controller, "systemd") == 0) return cgroup_ops->get(ops, "name=systemd", cgroup, file, value); return cgroup_ops->get(cgroup_ops, controller, cgroup, file, value); @@ -268,9 +268,10 @@ static bool caller_is_in_ancestor(pid_t pid, const char *contrl, const char *cg, char **nextcg) { bool answer = false; - char *c2 = get_pid_cgroup_handle_named(pid, contrl); + char *c2; char *linecmp; + c2 = get_pid_cgroup_handle_named(pid, contrl); if (!c2) return false; prune_init_slice(c2); @@ -745,22 +746,22 @@ static bool recursive_rmdir(const char *dirname, int fd, const int cfd) { - struct dirent *direntp; - DIR *dir; + __do_close int dupfd = -EBADF; + __do_closedir DIR *dir = NULL; bool ret = false; + struct dirent *direntp; char pathname[MAXPATHLEN]; - int dupfd; - dupfd = dup(fd); // fdopendir() does bad things once it uses an fd. + dupfd = dup(fd); if (dupfd < 0) return false; dir = fdopendir(dupfd); if (!dir) { lxcfs_debug("Failed to open %s: %s.\n", dirname, strerror(errno)); - close(dupfd); return false; } + move_fd(dupfd); while ((direntp = readdir(dir))) { struct stat mystat; @@ -787,18 +788,12 @@ } ret = true; - if (closedir(dir) < 0) { - lxcfs_error("Failed to close directory %s: %s\n", dirname, strerror(errno)); - ret = false; - } if (unlinkat(cfd, dirname, AT_REMOVEDIR) < 0) { lxcfs_debug("Failed to delete %s: %s.\n", dirname, strerror(errno)); ret = false; } - close(dupfd); - return ret; } @@ -1163,13 +1158,17 @@ static int pid_to_ns(int sock, pid_t tpid) { char v = '0'; - struct ucred cred; + struct ucred cred = { + .pid = -1, + .uid = -1, + .gid = -1, + }; while (recv_creds(sock, &cred, &v)) { if (v == '1') return 0; - if (write(sock, &cred.pid, sizeof(pid_t)) != sizeof(pid_t)) + if (write_nointr(sock, &cred.pid, sizeof(pid_t)) != sizeof(pid_t)) return 1; } @@ -1229,10 +1228,8 @@ .tpid = tpid, .wrapped = &pid_to_ns }; - size_t stack_size = sysconf(_SC_PAGESIZE); - void *stack = alloca(stack_size); - cpid = clone(pid_ns_clone_wrapper, stack + stack_size, SIGCHLD, &args); + cpid = lxcfs_clone(pid_ns_clone_wrapper, &args, 0); if (cpid < 0) _exit(1); @@ -1568,10 +1565,8 @@ .tpid = tpid, .wrapped = &pid_from_ns }; - size_t stack_size = sysconf(_SC_PAGESIZE); - void *stack = alloca(stack_size); - cpid = clone(pid_ns_clone_wrapper, stack + stack_size, SIGCHLD, &args); + cpid = lxcfs_clone(pid_ns_clone_wrapper, &args, 0); if (cpid < 0) _exit(1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/cgroups/cgfsng.c new/lxcfs-4.0.3/src/cgroups/cgfsng.c --- old/lxcfs-4.0.1/src/cgroups/cgfsng.c 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/cgroups/cgfsng.c 2020-04-17 22:15:36.000000000 +0200 @@ -547,7 +547,7 @@ { __do_free char *path = NULL; struct hierarchy *h; - int ret; + int cgroup2_root_fd, layout, ret; h = ops->get_hierarchy(ops, "memory"); if (!h) @@ -562,17 +562,24 @@ file = "memory.memsw.usage_in_bytes"; else if (strcmp(file, "memory.current") == 0) file = "memory.usage_in_bytes"; - ret = CGROUP_SUPER_MAGIC; + layout = CGROUP_SUPER_MAGIC; + cgroup2_root_fd = -EBADF; } else { - ret = CGROUP2_SUPER_MAGIC; + layout = CGROUP2_SUPER_MAGIC; + cgroup2_root_fd = ops->cgroup2_root_fd; } - path = must_make_path_relative(cgroup, file, NULL); - *value = readat_file(h->fd, path); - if (!*value) - ret = -1; + path = must_make_path_relative(cgroup, NULL); + ret = cgroup_walkup_to_root(cgroup2_root_fd, h->fd, path, file, value); + if (ret < 0) + return ret; + if (ret == 1) { + *value = strdup(""); + if (!*value) + return -ENOMEM; + } - return ret; + return layout; } static int cgfsng_get_memory_stats_fd(struct cgroup_ops *ops, const char *cgroup) @@ -918,6 +925,11 @@ ops->cgroup_layout = CGROUP_LAYOUT_UNIFIED; ops->unified = new; + + ops->cgroup2_root_fd = open(DEFAULT_CGROUP_MOUNTPOINT, O_DIRECTORY | O_PATH | O_CLOEXEC); + if (ops->cgroup2_root_fd < 0) + return -errno; + return CGROUP2_SUPER_MAGIC; } @@ -939,12 +951,13 @@ { __do_free struct cgroup_ops *cgfsng_ops = NULL; - cgfsng_ops = malloc(sizeof(struct cgroup_ops)); + cgfsng_ops = zalloc(sizeof(struct cgroup_ops)); if (!cgfsng_ops) return ret_set_errno(NULL, ENOMEM); - memset(cgfsng_ops, 0, sizeof(struct cgroup_ops)); cgfsng_ops->cgroup_layout = CGROUP_LAYOUT_UNKNOWN; + cgfsng_ops->mntns_fd = -EBADF; + cgfsng_ops->cgroup2_root_fd = -EBADF; if (cg_init(cgfsng_ops)) return NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/cgroups/cgroup.c new/lxcfs-4.0.3/src/cgroups/cgroup.c --- old/lxcfs-4.0.1/src/cgroups/cgroup.c 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/cgroups/cgroup.c 2020-04-17 22:15:36.000000000 +0200 @@ -72,6 +72,9 @@ if (ops->mntns_fd >= 0) close(ops->mntns_fd); + if (ops->cgroup2_root_fd >= 0) + close(ops->cgroup2_root_fd); + free(ops->hierarchies); free(ops); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/cgroups/cgroup.h new/lxcfs-4.0.3/src/cgroups/cgroup.h --- old/lxcfs-4.0.1/src/cgroups/cgroup.h 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/cgroups/cgroup.h 2020-04-17 22:15:36.000000000 +0200 @@ -91,6 +91,12 @@ */ int mntns_fd; + /* + * A file descriptor to the root of the cgroup tree if we're on a + * cgroup2 only system. + */ + int cgroup2_root_fd; + /* string constant */ const char *driver; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/cgroups/cgroup2_devices.h new/lxcfs-4.0.3/src/cgroups/cgroup2_devices.h --- old/lxcfs-4.0.1/src/cgroups/cgroup2_devices.h 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/cgroups/cgroup2_devices.h 2020-04-17 22:15:36.000000000 +0200 @@ -30,40 +30,15 @@ #include <linux/filter.h> #endif +#include "syscall_numbers.h" + #if !HAVE_BPF -#if !(defined __NR_bpf && __NR_bpf > 0) -#if defined __NR_bpf -#undef __NR_bpf -#endif -#if defined __i386__ -#define __NR_bpf 357 -#elif defined __x86_64__ -#define __NR_bpf 321 -#elif defined __aarch64__ -#define __NR_bpf 280 -#elif defined __arm__ -#define __NR_bpf 386 -#elif defined __sparc__ -#define __NR_bpf 349 -#elif defined __s390__ -#define __NR_bpf 351 -#elif defined __tilegx__ -#define __NR_bpf 280 -#else -#warning "__NR_bpf not defined for your architecture" -#endif -#endif union bpf_attr; static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) { -#ifdef __NR_bpf return (int)syscall(__NR_bpf, cmd, attr, size); -#else - errno = ENOSYS; - return -1; -#endif } #define bpf missing_bpf @@ -77,7 +52,7 @@ size_t n_instructions; #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX struct bpf_insn *instructions; -#endif +#endif /* HAVE_STRUCT_BPF_CGROUP_DEV_CTX */ char *attached_path; int attached_type; @@ -102,7 +77,7 @@ *prog = NULL; } } -#else +#else /* HAVE_STRUCT_BPF_CGROUP_DEV_CTX */ static inline struct bpf_program *bpf_program_new(uint32_t prog_type) { errno = ENOSYS; @@ -156,9 +131,8 @@ { } -#endif +#endif /* HAVE_BPF */ -#define __do_bpf_program_free \ - __attribute__((__cleanup__(__auto_bpf_program_free__))) +define_cleanup_function(struct bpf_program *, bpf_program_free); #endif /* __LXC_CGROUP2_DEVICES_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/cgroups/cgroup_utils.c new/lxcfs-4.0.3/src/cgroups/cgroup_utils.c --- old/lxcfs-4.0.1/src/cgroups/cgroup_utils.c 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/cgroups/cgroup_utils.c 2020-04-17 22:15:36.000000000 +0200 @@ -724,3 +724,102 @@ return true; } + +static bool same_file(int fd1, int fd2) +{ + struct stat st1, st2; + + if (fstat(fd1, &st1) < 0 || fstat(fd2, &st2) < 0) + return false; + + return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino); +} + +/** + * cgroup_walkup_to_root() - Walk upwards to cgroup root to find valid value + * + * @cgroup2_root_fd: File descriptor for the cgroup2 root mount point. + * @hierarchy_fd: File descriptor for the hierarchy. + * @cgroup: A cgroup directory relative to @hierarchy_fd. + * @file: The file in @cgroup from which to read a value. + * @value: Return argument to store value read from @file. + * + * This function tries to read a valid value from @file in @cgroup in + * @hierarchy_fd. If it is a legacy cgroup hierarchy and we fail to find a + * valid value we terminate early and report an error. + * The cgroup2 hierarchy however, has different semantics. In a few controller + * files it will show the value "max" or simply leave it completely empty + * thereby indicating that no limit has been set for this particular cgroup. + * However, that doesn't mean that there's no limit. A cgroup further up the + * hierarchy could have a limit set that also applies to the cgroup we are + * interested in. So for the unified cgroup hierarchy we need to keep walking + * towards the cgroup2 root cgroup and try to parse a valid value. + * + * Returns: 0 if a limit was found, 1 if no limit was set or "max" was set, + * -errno if an error occurred. + */ +int cgroup_walkup_to_root(int cgroup2_root_fd, int hierarchy_fd, + const char *cgroup, const char *file, char **value) +{ + __do_close int dir_fd = -EBADF; + __do_free char *val = NULL; + + /* Look in our current cgroup for a valid value. */ + dir_fd = openat(hierarchy_fd, cgroup, O_DIRECTORY | O_PATH | O_CLOEXEC); + if (dir_fd < 0) + return -errno; + + val = readat_file(dir_fd, file); + if (!is_empty_string(val) && strcmp(val, "max") != 0) { + *value = move_ptr(val); + return 0; + } + + /* + * Legacy cgroup hierarchies should always show a valid value in the + * file of the cgroup. So no need to do this upwards walking crap. + */ + if (cgroup2_root_fd < 0) + return -EINVAL; + else if (same_file(cgroup2_root_fd, dir_fd)) + return 1; + + free_disarm(val); + /* + * Set an arbitraty hard-coded limit to prevent us from ending + * up in an endless loop. There really shouldn't be any cgroup + * tree that is 1000 levels deep. That would be insane in + * principal and performance-wise. + */ + for (int i = 0; i < 1000; i++) { + __do_close int inner_fd = -EBADF; + __do_free char *new_val = NULL; + + inner_fd = move_fd(dir_fd); + dir_fd = openat(inner_fd, "..", O_DIRECTORY | O_PATH | O_CLOEXEC); + if (dir_fd < 0) + return -errno; + + /* + * We're at the root of the cgroup2 tree so stop walking + * upwards. + * Since we walked up the whole tree we haven't found an actual + * limit anywhere apparently. + * + * Note that we're not checking the root cgroup itself simply + * because a lot of the controllers don't expose files with + * limits to the root cgroup. + */ + if (same_file(cgroup2_root_fd, dir_fd)) + return 1; + + /* We found a valid value. Terminate walk. */ + new_val = readat_file(dir_fd, file); + if (!is_empty_string(new_val) && strcmp(new_val, "max") != 0) { + *value = move_ptr(new_val); + return 0; + } + } + + return log_error_errno(-ELOOP, ELOOP, "To many nested cgroups or invalid mount tree. Terminating walk"); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/cgroups/cgroup_utils.h new/lxcfs-4.0.3/src/cgroups/cgroup_utils.h --- old/lxcfs-4.0.1/src/cgroups/cgroup_utils.h 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/cgroups/cgroup_utils.h 2020-04-17 22:15:36.000000000 +0200 @@ -95,6 +95,10 @@ return openat(fd, path, O_DIRECTORY | O_RDONLY | O_CLOEXEC | O_NOFOLLOW); } +extern int cgroup_walkup_to_root(int cgroup2_root_fd, int hierarchy_fd, + const char *cgroup, const char *file, + char **value); + #define must_make_path_relative(__first__, ...) \ ({ \ char *__ptr__; \ @@ -105,4 +109,9 @@ __ptr__; \ }) +static inline bool is_empty_string(const char *s) +{ + return !s || strcmp(s, "") == 0; +} + #endif /* __LXC_CGROUP_UTILS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/lxcfs.c new/lxcfs-4.0.3/src/lxcfs.c --- old/lxcfs-4.0.1/src/lxcfs.c 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/lxcfs.c 2020-04-17 22:15:36.000000000 +0200 @@ -1029,10 +1029,10 @@ char buf[INTTYPE_TO_STRLEN(long)]; int ret; struct flock fl = { - fl.l_type = F_WRLCK, - fl.l_whence = SEEK_SET, - fl.l_start = 0, - fl.l_len = 0, + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, }; fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | O_CLOEXEC); @@ -1124,8 +1124,8 @@ } else if (strcmp(token, "nonempty") == 0) { nonempty = true; } else { - free(v); lxcfs_error("Warning: unexpected fuse option %s", v); + free(v); exit(EXIT_FAILURE); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/memory_utils.h new/lxcfs-4.0.3/src/memory_utils.h --- old/lxcfs-4.0.1/src/memory_utils.h 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/memory_utils.h 2020-04-17 22:15:36.000000000 +0200 @@ -31,12 +31,12 @@ } #define close_prot_errno_replace(fd, new_fd) \ - if (fd >= 0) { \ - int _e_ = errno; \ - close(fd); \ - errno = _e_; \ - fd = new_fd; \ - } + if (fd >= 0) { \ + int _e_ = errno; \ + close(fd); \ + errno = _e_; \ + fd = new_fd; \ + } static inline void close_prot_errno_disarm_function(int *fd) { @@ -50,10 +50,10 @@ define_cleanup_function(DIR *, closedir); #define __do_closedir call_cleaner(closedir) -#define free_disarm(ptr) \ - ({ \ - free(ptr); \ - move_ptr(ptr); \ +#define free_disarm(ptr) \ + ({ \ + free(ptr); \ + ptr = NULL; \ }) static inline void free_disarm_function(void *ptr) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/proc_fuse.c new/lxcfs-4.0.3/src/proc_fuse.c --- old/lxcfs-4.0.1/src/proc_fuse.c 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/proc_fuse.c 2020-04-17 22:15:36.000000000 +0200 @@ -203,19 +203,15 @@ static uint64_t get_memlimit(const char *cgroup, bool swap) { __do_free char *memlimit_str = NULL; - uint64_t memlimit = -1; - char *ptr; + uint64_t memlimit = 0; int ret; if (swap) ret = cgroup_ops->get_memory_swap_max(cgroup_ops, cgroup, &memlimit_str); else ret = cgroup_ops->get_memory_max(cgroup_ops, cgroup, &memlimit_str); - if (ret > 0) { - memlimit = strtoull(memlimit_str, &ptr, 10); - if (ptr == memlimit_str) - memlimit = -1; - } + if (ret > 0 && safe_uint64(memlimit_str, &memlimit, 10) < 0) + lxcfs_error("Failed to convert memlimit %s", memlimit_str); return memlimit; } @@ -223,23 +219,20 @@ static uint64_t get_min_memlimit(const char *cgroup, bool swap) { __do_free char *copy = NULL; - uint64_t memlimit = 0; - uint64_t retlimit; + uint64_t memlimit = 0, retlimit = 0; copy = strdup(cgroup); if (!copy) return log_error_errno(0, ENOMEM, "Failed to allocate memory"); retlimit = get_memlimit(copy, swap); - if (retlimit == -1) - retlimit = 0; while (strcmp(copy, "/") != 0) { char *it = copy; it = dirname(it); memlimit = get_memlimit(it, swap); - if (memlimit != -1 && memlimit < retlimit) + if (memlimit > 0 && memlimit < retlimit) retlimit = memlimit; }; @@ -296,14 +289,18 @@ if (ret < 0) return 0; - memusage = strtoull(memusage_str, NULL, 10); + if (safe_uint64(memusage_str, &memusage, 10) < 0) + lxcfs_error("Failed to convert memusage %s", memusage_str); ret = cgroup_ops->get_memory_swap_max(cgroup_ops, cg, &memswlimit_str); if (ret >= 0) ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cg, &memswusage_str); if (ret >= 0) { memswlimit = get_min_memlimit(cg, true); - memswusage = strtoull(memswusage_str, NULL, 10); + + if (safe_uint64(memswusage_str, &memswusage, 10) < 0) + lxcfs_error("Failed to convert memswusage %s", memswusage_str); + swap_total = (memswlimit - memlimit) / 1024; swap_free = (memswusage - memusage) / 1024; } @@ -524,7 +521,8 @@ } #endif -/* This function retrieves the busy time of a group of tasks by looking at +/* + * This function retrieves the busy time of a group of tasks by looking at * cpuacct.usage. Unfortunately, this only makes sense when the container has * been given it's own cpuacct cgroup. If not, this function will take the busy * time of all other taks that do not actually belong to the container into @@ -545,10 +543,13 @@ if (!cgroup) return 0; prune_init_slice(cgroup); + if (!cgroup_ops->get(cgroup_ops, "cpuacct", cgroup, "cpuacct.usage", &usage_str)) return 0; - usage = strtoull(usage_str, NULL, 10); + if (safe_uint64(usage_str, &usage, 10) < 0) + lxcfs_error("Failed to convert usage %s", usage_str); + return ((double)usage / 1000000000); } @@ -558,38 +559,21 @@ __do_fclose FILE *f = NULL; int ret; uint64_t starttime; - /* strlen("/proc/") = 6 - * + - * LXCFS_NUMSTRLEN64 - * + - * strlen("/stat") = 5 - * + - * \0 = 1 - * */ -#define __PROC_PID_STAT_LEN (6 + LXCFS_NUMSTRLEN64 + 5 + 1) - char path[__PROC_PID_STAT_LEN]; + char path[STRLITERALLEN("/proc/") + LXCFS_NUMSTRLEN64 + + STRLITERALLEN("/stat") + 1]; pid_t qpid; qpid = lookup_initpid_in_store(pid); - if (qpid <= 0) { - /* Caller can check for EINVAL on 0. */ - errno = EINVAL; - return 0; - } + if (qpid <= 0) + return ret_errno(EINVAL); - ret = snprintf(path, __PROC_PID_STAT_LEN, "/proc/%d/stat", qpid); - if (ret < 0 || ret >= __PROC_PID_STAT_LEN) { - /* Caller can check for EINVAL on 0. */ - errno = EINVAL; - return 0; - } + ret = snprintf(path, sizeof(path), "/proc/%d/stat", qpid); + if (ret < 0 || (size_t)ret >= sizeof(path)) + return ret_errno(EINVAL); f = fopen_cached(path, "re", &fopen_cache); - if (!f) { - /* Caller can check for EINVAL on 0. */ - errno = EINVAL; - return 0; - } + if (!f) + return ret_errno(EINVAL); /* Note that the *scanf() argument supression requires that length * modifiers such as "l" are omitted. Otherwise some compilers will yell @@ -620,7 +604,7 @@ "%" PRIu64, /* (22) starttime %llu */ &starttime); if (ret != 1) - return ret_set_errno(0, EINVAL); + return ret_errno(EINVAL); return ret_set_errno(starttime, 0); } @@ -632,11 +616,11 @@ double res = 0; clockticks = get_reaper_start_time(pid); - if (clockticks == 0 && errno == EINVAL) + if (clockticks <= 0) return log_debug(0, "Failed to retrieve start time of pid %d", pid); ret = sysconf(_SC_CLK_TCK); - if (ret < 0 && errno == EINVAL) + if (ret < 0) return log_debug(0, "Failed to determine number of clock ticks in a second"); ticks_per_sec = (uint64_t)ret; @@ -649,7 +633,8 @@ uint64_t uptime_ms; double procstart, procage; - /* We need to substract the time the process has started since system + /* + * We need to substract the time the process has started since system * boot minus the time when the system has started to get the actual * reaper age. */ @@ -663,11 +648,6 @@ if (ret < 0) return 0; - /* We could make this more precise here by using the tv_nsec - * field in the timespec struct and convert it to milliseconds - * and then create a double for the seconds and milliseconds but - * that seems more work than it is worth. - */ uptime_ms = (spec.tv_sec * 1000) + (spec.tv_nsec * 1e-6); procage = (uptime_ms - (procstart * 1000)) / 1000; } @@ -721,7 +701,7 @@ total_len = snprintf(d->buf, d->buflen, "%.2lf %.2lf\n", reaperage, idletime); if (total_len < 0 || total_len >= d->buflen) - return log_error(0, "Failed to write to cache"); + return read_file_fuse("/proc/uptime", buf, size, d); d->size = (int)total_len; d->cached = 1; @@ -730,6 +710,7 @@ total_len = size; memcpy(buf, d->buf, total_len); + return total_len; } @@ -1038,7 +1019,7 @@ struct lxcfs_opts *opts = (struct lxcfs_opts *)fuse_get_context()->private_data; struct file_info *d = INTTYPE_TO_PTR(fi->fh); uint64_t memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0, - hosttotal = 0; + hosttotal = 0, swtotal = 0; struct memory_stat mstat = {}; size_t linelen = 0, total_len = 0; char *cache = d->buf; @@ -1075,10 +1056,10 @@ ret = cgroup_ops->get_memory_current(cgroup_ops, cgroup, &memusage_str); if (ret < 0) - return 0; + return read_file_fuse("/proc/meminfo", buf, size, d); if (!cgroup_parse_memory_stat(cgroup, &mstat)) - return 0; + return read_file_fuse("/proc/meminfo", buf, size, d); /* * Following values are allowed to fail, because swapaccount might be @@ -1089,18 +1070,22 @@ ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str); if (ret >= 0) { memswlimit = get_min_memlimit(cgroup, true); - memswusage = strtoull(memswusage_str, NULL, 10); memswlimit = memswlimit / 1024; + + if (safe_uint64(memswusage_str, &memswusage, 10) < 0) + lxcfs_error("Failed to convert memswusage %s", memswusage_str); memswusage = memswusage / 1024; + swtotal = memswlimit; } - memusage = strtoull(memusage_str, NULL, 10); + if (safe_uint64(memusage_str, &memusage, 10) < 0) + lxcfs_error("Failed to convert memusage %s", memusage_str); memlimit /= 1024; memusage /= 1024; f = fopen_cached("/proc/meminfo", "re", &fopen_cache); if (!f) - return 0; + return read_file_fuse("/proc/meminfo", buf, size, d); while (getline(&line, &linelen, f) != -1) { ssize_t l; @@ -1109,6 +1094,9 @@ memset(lbuf, 0, 100); if (startswith(line, "MemTotal:")) { sscanf(line+sizeof("MemTotal:")-1, "%" PRIu64, &hosttotal); + if (memlimit == 0) + memlimit = hosttotal; + if (hosttotal < memlimit) memlimit = hosttotal; snprintf(lbuf, 100, "MemTotal: %8" PRIu64 " kB\n", memlimit); @@ -1119,24 +1107,29 @@ } else if (startswith(line, "MemAvailable:")) { snprintf(lbuf, 100, "MemAvailable: %8" PRIu64 " kB\n", memlimit - memusage + mstat.total_cache / 1024); printme = lbuf; - } else if (startswith(line, "SwapTotal:") && memswlimit > 0 && - opts && opts->swap_off == false) { - memswlimit -= memlimit; - snprintf(lbuf, 100, "SwapTotal: %8" PRIu64 " kB\n", memswlimit); + } else if (startswith(line, "SwapTotal:") && memswlimit > 0 && opts && opts->swap_off == false) { + uint64_t hostswtotal = 0; + + sscanf(line + STRLITERALLEN("SwapTotal:"), "%" PRIu64, &hostswtotal); + + /* Don't advertise more SWAP than the total memory allowed. */ + if (hostswtotal < swtotal) + swtotal = hostswtotal; + + snprintf(lbuf, 100, "SwapTotal: %8" PRIu64 " kB\n", swtotal); printme = lbuf; } else if (startswith(line, "SwapTotal:") && opts && opts->swap_off == true) { snprintf(lbuf, 100, "SwapTotal: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "SwapFree:") && memswlimit > 0 && - memswusage > 0 && opts && opts->swap_off == false) { - uint64_t swaptotal = memswlimit, - swapusage = memusage > memswusage - ? 0 - : memswusage - memusage, - swapfree = swapusage < swaptotal - ? swaptotal - swapusage - : 0; - snprintf(lbuf, 100, "SwapFree: %8" PRIu64 " kB\n", swapfree); + opts && opts->swap_off == false) { + uint64_t swfree = 0; + uint64_t swusage = 0; + + swusage = memswusage - memusage; + swfree = swtotal - swusage; + + snprintf(lbuf, 100, "SwapFree: %8" PRIu64 " kB\n", swfree); printme = lbuf; } else if (startswith(line, "SwapFree:") && opts && opts->swap_off == true) { snprintf(lbuf, 100, "SwapFree: %8" PRIu64 " kB\n", (uint64_t)0); @@ -1166,61 +1159,61 @@ mstat.total_inactive_file) / 1024); printme = lbuf; - } else if (startswith(line, "Active(anon)")) { + } else if (startswith(line, "Active(anon):")) { snprintf(lbuf, 100, "Active(anon): %8" PRIu64 " kB\n", mstat.total_active_anon / 1024); printme = lbuf; - } else if (startswith(line, "Inactive(anon)")) { + } else if (startswith(line, "Inactive(anon):")) { snprintf(lbuf, 100, "Inactive(anon): %8" PRIu64 " kB\n", mstat.total_inactive_anon / 1024); printme = lbuf; - } else if (startswith(line, "Active(file)")) { + } else if (startswith(line, "Active(file):")) { snprintf(lbuf, 100, "Active(file): %8" PRIu64 " kB\n", mstat.total_active_file / 1024); printme = lbuf; - } else if (startswith(line, "Inactive(file)")) { + } else if (startswith(line, "Inactive(file):")) { snprintf(lbuf, 100, "Inactive(file): %8" PRIu64 " kB\n", mstat.total_inactive_file / 1024); printme = lbuf; - } else if (startswith(line, "Unevictable")) { + } else if (startswith(line, "Unevictable:")) { snprintf(lbuf, 100, "Unevictable: %8" PRIu64 " kB\n", mstat.total_unevictable / 1024); printme = lbuf; - } else if (startswith(line, "Dirty")) { + } else if (startswith(line, "Dirty:")) { snprintf(lbuf, 100, "Dirty: %8" PRIu64 " kB\n", mstat.total_dirty / 1024); printme = lbuf; - } else if (startswith(line, "Writeback")) { + } else if (startswith(line, "Writeback:")) { snprintf(lbuf, 100, "Writeback: %8" PRIu64 " kB\n", mstat.total_writeback / 1024); printme = lbuf; - } else if (startswith(line, "AnonPages")) { + } else if (startswith(line, "AnonPages:")) { snprintf(lbuf, 100, "AnonPages: %8" PRIu64 " kB\n", (mstat.total_active_anon + mstat.total_inactive_anon - mstat.total_shmem) / 1024); printme = lbuf; - } else if (startswith(line, "Mapped")) { + } else if (startswith(line, "Mapped:")) { snprintf(lbuf, 100, "Mapped: %8" PRIu64 " kB\n", mstat.total_mapped_file / 1024); printme = lbuf; - } else if (startswith(line, "SReclaimable")) { + } else if (startswith(line, "SReclaimable:")) { snprintf(lbuf, 100, "SReclaimable: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; - } else if (startswith(line, "SUnreclaim")) { + } else if (startswith(line, "SUnreclaim:")) { snprintf(lbuf, 100, "SUnreclaim: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "Shmem:")) { snprintf(lbuf, 100, "Shmem: %8" PRIu64 " kB\n", mstat.total_shmem / 1024); printme = lbuf; - } else if (startswith(line, "ShmemHugePages")) { + } else if (startswith(line, "ShmemHugePages:")) { snprintf(lbuf, 100, "ShmemHugePages: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; - } else if (startswith(line, "ShmemPmdMapped")) { + } else if (startswith(line, "ShmemPmdMapped:")) { snprintf(lbuf, 100, "ShmemPmdMapped: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; - } else if (startswith(line, "AnonHugePages")) { + } else if (startswith(line, "AnonHugePages:")) { snprintf(lbuf, 100, "AnonHugePages: %8" PRIu64 " kB\n", mstat.total_rss_huge / 1024); printme = lbuf; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/syscall_numbers.h new/lxcfs-4.0.3/src/syscall_numbers.h --- old/lxcfs-4.0.1/src/syscall_numbers.h 1970-01-01 01:00:00.000000000 +0100 +++ new/lxcfs-4.0.3/src/syscall_numbers.h 2020-04-17 22:15:36.000000000 +0200 @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef __LXCFS_SYSCALL_NUMBERS_H +#define __LXCFS_SYSCALL_NUMBERS_H + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif +#include <asm/unistd.h> +#include <errno.h> +#include <sched.h> +#include <stdint.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <unistd.h> + +#ifndef __NR_pivot_root + #if defined __i386__ + #define __NR_pivot_root 217 + #elif defined __x86_64__ + #define __NR_pivot_root 155 + #elif defined __arm__ + #define __NR_pivot_root 218 + #elif defined __aarch64__ + #define __NR_pivot_root 218 + #elif defined __s390__ + #define __NR_pivot_root 217 + #elif defined __powerpc__ + #define __NR_pivot_root 203 + #elif defined __sparc__ + #define __NR_pivot_root 146 + #elif defined __ia64__ + #define __NR_pivot_root 183 + #elif defined _MIPS_SIM + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ + #define __NR_pivot_root 4216 + #endif + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ + #define __NR_pivot_root 6151 + #endif + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ + #define __NR_pivot_root 5151 + #endif + #else + #define -1 + #warning "__NR_pivot_root not defined for your architecture" + #endif +#endif + +#ifndef __NR_bpf + #if defined __i386__ + #define __NR_bpf 357 + #elif defined __x86_64__ + #define __NR_bpf 321 + #elif defined __arm__ + #define __NR_bpf 386 + #elif defined __aarch64__ + #define __NR_bpf 386 + #elif defined __s390__ + #define __NR_bpf 351 + #elif defined __powerpc__ + #define __NR_bpf 361 + #elif defined __sparc__ + #define __NR_bpf 349 + #elif defined __ia64__ + #define __NR_bpf 317 + #elif defined _MIPS_SIM + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ + #define __NR_bpf 4355 + #endif + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ + #define __NR_bpf 6319 + #endif + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ + #define __NR_bpf 5315 + #endif + #else + #define -1 + #warning "__NR_bpf not defined for your architecture" + #endif +#endif + +#ifndef __NR_pidfd_send_signal + #if defined __alpha__ + #define __NR_pidfd_send_signal 534 + #elif defined _MIPS_SIM + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ + #define __NR_pidfd_send_signal 4424 + #endif + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ + #define __NR_pidfd_send_signal 6424 + #endif + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ + #define __NR_pidfd_send_signal 5424 + #endif + #else + #define __NR_pidfd_send_signal 424 + #endif +#endif + +#ifndef __NR_pidfd_open + #if defined __alpha__ + #define __NR_pidfd_open 544 + #elif defined _MIPS_SIM + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ + #define __NR_pidfd_open 4434 + #endif + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ + #define __NR_pidfd_open 6434 + #endif + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ + #define __NR_pidfd_open 5434 + #endif + #else + #define __NR_pidfd_open 434 + #endif +#endif + +#endif /* __LXCFS_SYSCALL_NUMBERS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/utils.c new/lxcfs-4.0.3/src/utils.c --- old/lxcfs-4.0.1/src/utils.c 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/utils.c 2020-04-17 22:15:36.000000000 +0200 @@ -10,13 +10,13 @@ #define _FILE_OFFSET_BITS 64 +#include <ctype.h> #include <errno.h> #include <fcntl.h> #include <fuse.h> #include <inttypes.h> #include <sched.h> #include <stdarg.h> -#include <stdio.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> @@ -212,37 +212,34 @@ bool recv_creds(int sock, struct ucred *cred, char *v) { - struct msghdr msg = { 0 }; + struct msghdr msg = {}; struct iovec iov; struct cmsghdr *cmsg; - char cmsgbuf[CMSG_SPACE(sizeof(*cred))]; - char buf[1]; - int ret; + ssize_t ret; + char cmsgbuf[CMSG_SPACE(sizeof(*cred))] = {}; + char buf = '1'; int optval = 1; - *v = '1'; - - cred->pid = -1; - cred->uid = -1; - cred->gid = -1; - - if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) - return log_error(false, "Failed to set passcred: %s\n", strerror(errno)); - - buf[0] = '1'; - if (write(sock, buf, 1) != 1) - return log_error(false, "Failed to start write on scm fd: %s\n", strerror(errno)); - msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); - iov.iov_base = buf; + iov.iov_base = &buf; iov.iov_len = sizeof(buf); msg.msg_iov = &iov; msg.msg_iovlen = 1; + *v = buf; + + ret = setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)); + if (ret < 0) + return log_error(false, "Failed to set passcred: %s\n", strerror(errno)); + + ret = write_nointr(sock, &buf, sizeof(buf)); + if (ret != sizeof(buf)) + return log_error(false, "Failed to start write on scm fd: %s\n", strerror(errno)); + if (!wait_for_sock(sock, 2)) return log_error(false, "Timed out waiting for scm_cred: %s\n", strerror(errno)); @@ -252,12 +249,12 @@ cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)) && - cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS) { + if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(*cred)) && + cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS) { memcpy(cred, CMSG_DATA(cmsg), sizeof(*cred)); } - *v = buf[0]; + *v = buf; return true; } @@ -520,3 +517,26 @@ return ret; } + +int safe_uint64(const char *numstr, uint64_t *converted, int base) +{ + char *err = NULL; + uint64_t u; + + while (isspace(*numstr)) + numstr++; + + if (*numstr == '-') + return -EINVAL; + + errno = 0; + u = strtoull(numstr, &err, base); + if (errno == ERANGE && u == UINT64_MAX) + return -ERANGE; + + if (err == numstr || *err != '\0') + return -EINVAL; + + *converted = u; + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/src/utils.h new/lxcfs-4.0.3/src/utils.h --- old/lxcfs-4.0.1/src/utils.h 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/src/utils.h 2020-04-17 22:15:36.000000000 +0200 @@ -24,6 +24,7 @@ #include "config.h" #include "macro.h" +#include "syscall_numbers.h" /* Reserve buffer size to account for file size changes. */ #define BUF_RESERVE_SIZE 512 @@ -51,11 +52,7 @@ #ifndef HAVE_PIDFD_OPEN static inline int pidfd_open(pid_t pid, unsigned int flags) { -#ifdef __NR_pidfd_open return syscall(__NR_pidfd_open, pid, flags); -#else - return ret_errno(ENOSYS); -#endif } #endif @@ -63,11 +60,7 @@ static inline int pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) { -#ifdef __NR_pidfd_send_signal return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags); -#else - return ret_errno(ENOSYS); -#endif } #endif @@ -75,5 +68,6 @@ void **caller_freed_buffer); extern FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer); extern ssize_t write_nointr(int fd, const void *buf, size_t count); +extern int safe_uint64(const char *numstr, uint64_t *converted, int base); #endif /* __LXCFS_UTILS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/tests/test_readdir new/lxcfs-4.0.3/tests/test_readdir --- old/lxcfs-4.0.1/tests/test_readdir 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/tests/test_readdir 2020-04-17 22:15:36.000000000 +0200 @@ -20,10 +20,12 @@ exit 1 fi -echo "==> Checking for cpuset cgroups" -[ ! -d /sys/fs/cgroup/cpuset ] && exit 0 - TESTCASE="Stress readdir" -for i in `seq 1 1000`;do ls -al "${LXCFSDIR}/cgroup/cpuset" >/dev/null; done +echo "==> Checking for cpuset cgroups" +if [ -d /sys/fs/cgroup/cpuset ]; then + for i in `seq 1 1000`;do ls -al "${LXCFSDIR}/cgroup/cpuset" >/dev/null; done +else + echo "==> Skipping $TESTCASE" +fi PASS=1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-4.0.1/tests/test_reload.sh new/lxcfs-4.0.3/tests/test_reload.sh --- old/lxcfs-4.0.1/tests/test_reload.sh 2020-03-19 15:21:36.000000000 +0100 +++ new/lxcfs-4.0.3/tests/test_reload.sh 2020-04-17 22:15:36.000000000 +0200 @@ -13,7 +13,7 @@ testdir=`mktemp -t -d libs.XXX` installdir=`mktemp -t -d libs.XXX` pidfile=$(mktemp) -libdir=${installdir}/usr/lib/lxcfs +libdir=${installdir}/$(grep ^LIBDIR Makefile | awk '{print $NF}') bindir=${installdir}/usr/bin lxcfspid=-1 FAILED=1