diff options
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/log.c | 2 | ||||
-rw-r--r-- | src/basic/mount-util.c | 3 | ||||
-rw-r--r-- | src/basic/path-util.c | 10 | ||||
-rw-r--r-- | src/basic/special.h | 3 | ||||
-rw-r--r-- | src/basic/virt.c | 70 | ||||
-rw-r--r-- | src/basic/virt.h | 1 |
6 files changed, 87 insertions, 2 deletions
diff --git a/src/basic/log.c b/src/basic/log.c index 2ff70be255..4919d175da 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -782,7 +782,7 @@ static void log_assert( return; DISABLE_WARNING_FORMAT_NONLITERAL; - xsprintf(buffer, format, text, file, line, func); + snprintf(buffer, sizeof buffer, format, text, file, line, func); REENABLE_WARNING; log_abort_msg = buffer; diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index b221309a4d..5d37fb48be 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -162,7 +162,7 @@ int fd_is_mount_point(int fd, const char *filename, int flags) { fallback_fdinfo: r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); - if (r == -EOPNOTSUPP) + if (IN_SET(r, -EOPNOTSUPP, -EACCES)) goto fallback_fstat; if (r < 0) return r; @@ -525,6 +525,7 @@ bool fstype_is_network(const char *fstype) { "glusterfs\0" "pvfs2\0" /* OrangeFS */ "ocfs2\0" + "lustre\0" ; const char *x; diff --git a/src/basic/path-util.c b/src/basic/path-util.c index e438f27df5..5cdac50c68 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -354,6 +354,16 @@ char* path_startswith(const char *path, const char *prefix) { assert(path); assert(prefix); + /* Returns a pointer to the start of the first component after the parts matched by + * the prefix, iff + * - both paths are absolute or both paths are relative, + * and + * - each component in prefix in turn matches a component in path at the same position. + * An empty string will be returned when the prefix and path are equivalent. + * + * Returns NULL otherwise. + */ + if ((path[0] == '/') != (prefix[0] == '/')) return NULL; diff --git a/src/basic/special.h b/src/basic/special.h index 084d3dfa23..5276bcf598 100644 --- a/src/basic/special.h +++ b/src/basic/special.h @@ -117,3 +117,6 @@ /* The scope unit systemd itself lives in. */ #define SPECIAL_INIT_SCOPE "init.scope" + +/* The root directory. */ +#define SPECIAL_ROOT_MOUNT "-.mount" diff --git a/src/basic/virt.c b/src/basic/virt.c index 41012d52a0..69b0f96183 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -485,6 +485,76 @@ int detect_virtualization(void) { return r; } +static int userns_has_mapping(const char *name) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *buf = NULL; + size_t n_allocated = 0; + ssize_t n; + uint32_t a, b, c; + int r; + + f = fopen(name, "re"); + if (!f) { + log_debug_errno(errno, "Failed to open %s: %m", name); + return errno == -ENOENT ? false : -errno; + } + + n = getline(&buf, &n_allocated, f); + if (n < 0) { + if (feof(f)) { + log_debug("%s is empty, we're in an uninitialized user namespace", name); + return true; + } + + return log_debug_errno(errno, "Failed to read %s: %m", name); + } + + r = sscanf(buf, "%"PRIu32" %"PRIu32" %"PRIu32, &a, &b, &c); + if (r < 3) + return log_debug_errno(errno, "Failed to parse %s: %m", name); + + if (a == 0 && b == 0 && c == UINT32_MAX) { + /* The kernel calls mappings_overlap() and does not allow overlaps */ + log_debug("%s has a full 1:1 mapping", name); + return false; + } + + /* Anything else implies that we are in a user namespace */ + log_debug("Mapping found in %s, we're in a user namespace", name); + return true; +} + +int running_in_userns(void) { + _cleanup_free_ char *line = NULL; + int r; + + r = userns_has_mapping("/proc/self/uid_map"); + if (r != 0) + return r; + + r = userns_has_mapping("/proc/self/gid_map"); + if (r != 0) + return r; + + /* "setgroups" file was added in kernel v3.18-rc6-15-g9cc46516dd. It is also + * possible to compile a kernel without CONFIG_USER_NS, in which case "setgroups" + * also does not exist. We cannot distinguish those two cases, so assume that + * we're running on a stripped-down recent kernel, rather than on an old one, + * and if the file is not found, return false. + */ + r = read_one_line_file("/proc/self/setgroups", &line); + if (r < 0) { + log_debug_errno(r, "/proc/self/setgroups: %m"); + return r == -ENOENT ? false : r; + } + + truncate_nl(line); + r = streq(line, "deny"); + /* See user_namespaces(7) for a description of this "setgroups" contents. */ + log_debug("/proc/self/setgroups contains \"%s\", %s user namespace", line, r ? "in" : "not in"); + return r; +} + int running_in_chroot(void) { int ret; diff --git a/src/basic/virt.h b/src/basic/virt.h index bc5b3ae94d..7d15169112 100644 --- a/src/basic/virt.h +++ b/src/basic/virt.h @@ -67,6 +67,7 @@ int detect_vm(void); int detect_container(void); int detect_virtualization(void); +int running_in_userns(void); int running_in_chroot(void); const char *virtualization_to_string(int v) _const_; |