From: Lennart Poettering Date: Tue, 27 Apr 2021 15:25:51 +0000 (+0200) Subject: nspawn: tighten userns UID shift/range checks X-Git-Tag: v249-rc1~269^2~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=58e13de5398c4b882e0dd45259d9d2d87adbcc5d;p=thirdparty%2Fsystemd.git nspawn: tighten userns UID shift/range checks Let's add a helper that ensures the UID shift/range parameters actually fit together. --- diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h index daa9accda37..39a6a46d1f9 100644 --- a/src/basic/namespace-util.h +++ b/src/basic/namespace-util.h @@ -9,3 +9,18 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int int fd_is_ns(int fd, unsigned long nsflag); int detach_mount_namespace(void); + +static inline bool userns_shift_range_valid(uid_t shift, uid_t range) { + /* Checks that the specified userns range makes sense, i.e. contains at least one UID, and the end + * doesn't overflow uid_t. */ + + assert_cc((uid_t) -1 > 0); /* verify that uid_t is unsigned */ + + if (range <= 0) + return false; + + if (shift > (uid_t) -1 - range) + return false; + + return true; +} diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c index ebd83ec2ec9..d5a0a675efd 100644 --- a/src/nspawn/nspawn-settings.c +++ b/src/nspawn/nspawn-settings.c @@ -5,6 +5,7 @@ #include "conf-parser.h" #include "cpu-set-util.h" #include "hostname-util.h" +#include "namespace-util.h" #include "nspawn-network.h" #include "nspawn-settings.h" #include "parse-util.h" @@ -611,7 +612,7 @@ int config_parse_private_users( range++; r = safe_atou32(range, &rn); - if (r < 0 || rn <= 0) { + if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "UID/GID range invalid, ignoring: %s", range); return 0; } @@ -626,6 +627,11 @@ int config_parse_private_users( return 0; } + if (!userns_shift_range_valid(sh, rn)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, "UID/GID shift and range combination invalid, ignoring: %s", range); + return 0; + } + settings->userns_mode = USER_NAMESPACE_FIXED; settings->uid_shift = sh; settings->uid_range = rn; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 38d6eeacc7e..b5e5474231e 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1259,11 +1259,10 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(r, "Failed to parse UID \"%s\": %m", optarg); arg_userns_mode = USER_NAMESPACE_FIXED; - } - if (arg_uid_range <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "UID range cannot be 0."); + if (!userns_shift_range_valid(arg_uid_shift, arg_uid_range)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "UID range cannot be empty or go beyond " UID_FMT ".", UID_INVALID); + } arg_settings_mask |= SETTING_USERNS; break; @@ -3068,9 +3067,8 @@ static int determine_uid_shift(const char *directory) { arg_uid_range = UINT32_C(0x10000); } - if (arg_uid_shift > UID_INVALID - arg_uid_range) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "UID base too high for UID range."); + if (!userns_shift_range_valid(arg_uid_shift, arg_uid_range)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "UID base too high for UID range."); return 0; }