summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--meson.build1
-rw-r--r--src/shared/user-record.c13
-rw-r--r--src/shared/user-record.h1
-rw-r--r--src/sysusers/sysusers.c22
-rw-r--r--src/test/test-user-record.c48
-rwxr-xr-xtest/test-sysusers.sh.in59
-rw-r--r--test/test-sysusers/test-10.expected-group2
-rw-r--r--test/test-sysusers/test-10.expected-passwd2
-rw-r--r--test/test-sysusers/test-13.expected-group2
-rw-r--r--test/test-sysusers/test-13.expected-passwd2
-rw-r--r--test/test-sysusers/test-14.expected-passwd2
-rw-r--r--test/test-sysusers/test-2.expected-group2
-rw-r--r--test/test-sysusers/test-2.expected-passwd2
-rw-r--r--test/test-sysusers/test-2.input2
-rw-r--r--test/test-sysusers/test-6.expected-group2
-rw-r--r--test/test-sysusers/test-6.expected-passwd2
-rw-r--r--test/test-sysusers/test-8.expected-passwd2
-rw-r--r--test/test-sysusers/test-9.expected-passwd2
18 files changed, 143 insertions, 25 deletions
diff --git a/meson.build b/meson.build
index 3bec86db81..23cf3e528a 100644
--- a/meson.build
+++ b/meson.build
@@ -1467,6 +1467,7 @@ foreach term : ['analyze',
have = get_option(term)
name = 'ENABLE_' + term.underscorify().to_upper()
conf.set10(name, have)
+ substs.set10(name, have)
endforeach
enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
diff --git a/src/shared/user-record.c b/src/shared/user-record.c
index 3ba78d455f..7e7b28eb55 100644
--- a/src/shared/user-record.c
+++ b/src/shared/user-record.c
@@ -37,21 +37,24 @@ static int parse_alloc_uid(const char *path, const char *name, const char *t, ui
*ret_uid = uid;
return 0;
}
+#endif
-static int read_login_defs(UGIDAllocationRange *ret_defs, const char *path) {
- _cleanup_fclose_ FILE *f = NULL;
+int read_login_defs(UGIDAllocationRange *ret_defs, const char *path, const char *root) {
UGIDAllocationRange defs = {
.system_alloc_uid_min = SYSTEM_ALLOC_UID_MIN,
.system_uid_max = SYSTEM_UID_MAX,
.system_alloc_gid_min = SYSTEM_ALLOC_GID_MIN,
.system_gid_max = SYSTEM_GID_MAX,
};
+
+#if ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES
+ _cleanup_fclose_ FILE *f = NULL;
int r;
if (!path)
path = "/etc/login.defs";
- r = fopen_unlocked(path, "re", &f);
+ r = chase_symlinks_and_fopen_unlocked(path, root, CHASE_PREFIX_ROOT, "re", &f, NULL);
if (r == -ENOENT)
goto assign;
if (r < 0)
@@ -88,11 +91,11 @@ static int read_login_defs(UGIDAllocationRange *ret_defs, const char *path) {
defs.system_alloc_gid_min = MIN(defs.system_gid_max - 1, (gid_t) SYSTEM_ALLOC_GID_MIN);
/* Look at sys_gid_max to make sure sys_gid_min..sys_gid_max remains a valid range. */
}
+#endif
*ret_defs = defs;
return 0;
}
-#endif
const UGIDAllocationRange *acquire_ugid_allocation_range(void) {
#if ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES
@@ -114,7 +117,7 @@ const UGIDAllocationRange *acquire_ugid_allocation_range(void) {
static thread_local bool initialized = false;
if (!initialized) {
- (void) read_login_defs(&defs, NULL);
+ (void) read_login_defs(&defs, NULL, NULL);
initialized = true;
}
#endif
diff --git a/src/shared/user-record.h b/src/shared/user-record.h
index 1f87eff6d5..2e74b910c2 100644
--- a/src/shared/user-record.h
+++ b/src/shared/user-record.h
@@ -43,6 +43,7 @@ typedef struct UGIDAllocationRange {
gid_t system_gid_max;
} UGIDAllocationRange;
+int read_login_defs(UGIDAllocationRange *ret_defs, const char *path, const char *root);
const UGIDAllocationRange *acquire_ugid_allocation_range(void);
typedef enum UserDisposition {
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 7349e9fcb9..987950d602 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -26,6 +26,7 @@
#include "strv.h"
#include "tmpfile-util-label.h"
#include "uid-range.h"
+#include "user-record.h"
#include "user-util.h"
#include "utf8.h"
#include "util.h"
@@ -1949,10 +1950,25 @@ static int run(int argc, char *argv[]) {
return log_error_errno(errno, "Failed to set SYSTEMD_NSS_BYPASS_SYNTHETIC environment variable: %m");
if (!uid_range) {
- /* Default to default range of 1..SYSTEM_UID_MAX */
- r = uid_range_add(&uid_range, &n_uid_range, 1, SYSTEM_UID_MAX);
+ /* Default to default range of SYSTEMD_UID_MIN..SYSTEM_UID_MAX. */
+ UGIDAllocationRange defs;
+
+ r = read_login_defs(&defs, NULL, arg_root);
if (r < 0)
- return log_oom();
+ return log_error_errno(r, "Failed to read %s%s: %m",
+ strempty(arg_root), "/etc/login.defs");
+
+ /* We pick a range that very conservative: we look at compiled-in maximum and the value in
+ * /etc/login.defs. That way the uids/gids which we allocate will be interpreted correctly,
+ * even if /etc/login.defs is removed later. (The bottom bound doesn't matter much, since
+ * it's only used during allocation, so we use the configured value directly). */
+ uid_t begin = defs.system_alloc_uid_min,
+ end = MIN3((uid_t) SYSTEM_UID_MAX, defs.system_uid_max, defs.system_gid_max);
+ if (begin < end) {
+ r = uid_range_add(&uid_range, &n_uid_range, begin, end - begin + 1);
+ if (r < 0)
+ return log_oom();
+ }
}
r = add_implicit();
diff --git a/src/test/test-user-record.c b/src/test/test-user-record.c
index fcab61d694..d623706648 100644
--- a/src/test/test-user-record.c
+++ b/src/test/test-user-record.c
@@ -3,10 +3,55 @@
#include <unistd.h>
#include <sys/types.h>
+#include "fd-util.h"
+#include "fileio.h"
#include "format-util.h"
+#include "fs-util.h"
+#include "tmpfile-util.h"
#include "tests.h"
#include "user-record.h"
+static void test_read_login_defs(const char *path) {
+ log_info("/* %s(\"%s\") */", __func__, path ?: "<custom>");
+
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-user-record.XXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
+ if (!path) {
+ assert_se(fmkostemp_safe(name, "r+", &f) == 0);
+ fprintf(f,
+ "SYS_UID_MIN "UID_FMT"\n"
+ "SYS_UID_MAX "UID_FMT"\n"
+ "SYS_GID_MIN "GID_FMT"\n"
+ "SYS_GID_MAX "GID_FMT"\n",
+ SYSTEM_ALLOC_UID_MIN + 5,
+ SYSTEM_UID_MAX + 5,
+ SYSTEM_ALLOC_GID_MIN + 5,
+ SYSTEM_GID_MAX + 5);
+ assert_se(fflush_and_check(f) >= 0);
+ }
+
+ UGIDAllocationRange defs;
+ assert_se(read_login_defs(&defs, path ?: name, NULL) >= 0);
+
+ log_info("system_alloc_uid_min="UID_FMT, defs.system_alloc_uid_min);
+ log_info("system_uid_max="UID_FMT, defs.system_uid_max);
+ log_info("system_alloc_gid_min="GID_FMT, defs.system_alloc_gid_min);
+ log_info("system_gid_max="GID_FMT, defs.system_gid_max);
+
+ if (!path) {
+ uid_t offset = ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES ? 5 : 0;
+ assert_se(defs.system_alloc_uid_min == SYSTEM_ALLOC_UID_MIN + offset);
+ assert_se(defs.system_uid_max == SYSTEM_UID_MAX + offset);
+ assert_se(defs.system_alloc_gid_min == SYSTEM_ALLOC_GID_MIN + offset);
+ assert_se(defs.system_gid_max == SYSTEM_GID_MAX + offset);
+ } else if (streq(path, "/dev/null")) {
+ assert_se(defs.system_alloc_uid_min == SYSTEM_ALLOC_UID_MIN);
+ assert_se(defs.system_uid_max == SYSTEM_UID_MAX);
+ assert_se(defs.system_alloc_gid_min == SYSTEM_ALLOC_GID_MIN);
+ assert_se(defs.system_gid_max == SYSTEM_GID_MAX);
+ }
+}
+
static void test_acquire_ugid_allocation_range(void) {
log_info("/* %s */", __func__);
@@ -48,6 +93,9 @@ static void test_gid_is_system(void) {
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
+ test_read_login_defs("/dev/null");
+ test_read_login_defs("/etc/login.defs");
+ test_read_login_defs(NULL);
test_acquire_ugid_allocation_range();
test_uid_is_system();
test_gid_is_system();
diff --git a/test/test-sysusers.sh.in b/test/test-sysusers.sh.in
index 39d238c1f7..6e133cc841 100755
--- a/test/test-sysusers.sh.in
+++ b/test/test-sysusers.sh.in
@@ -20,19 +20,22 @@ prepare_testdir() {
return 0
}
+[ @SYSTEM_UID_MAX@ -lt @SYSTEM_GID_MAX@ ] && system_guid_max=@SYSTEM_UID_MAX@ || system_guid_max=@SYSTEM_GID_MAX@
+
preprocess() {
- sed -e "s/SYSTEM_UID_MAX/@SYSTEM_UID_MAX@/g" \
- -e "s/SYSTEM_GID_MAX/@SYSTEM_GID_MAX@/g" \
- -e "s#NOLOGIN#@NOLOGIN@#g" "$1"
+ m=${2:-$system_guid_max}
+
+ sed -e "s/SYSTEM_UGID_MAX/$m/g;
+ s#NOLOGIN#@NOLOGIN@#g" "$1"
}
compare() {
- if ! diff -u $TESTDIR/etc/passwd <(preprocess $1.expected-passwd); then
+ if ! diff -u $TESTDIR/etc/passwd <(preprocess $1.expected-passwd $3); then
echo "**** Unexpected output for $f $2"
exit 1
fi
- if ! diff -u $TESTDIR/etc/group <(preprocess $1.expected-group); then
+ if ! diff -u $TESTDIR/etc/group <(preprocess $1.expected-group $3); then
echo "**** Unexpected output for $f $2"
exit 1
fi
@@ -97,6 +100,52 @@ compare $SOURCE/inline "(--inline --replace=…)"
rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
+cat >$TESTDIR/etc/login.defs <<EOF
+SYS_UID_MIN abcd
+SYS_UID_MAX abcd
+SYS_GID_MIN abcd
+SYS_GID_MAX abcd
+SYS_UID_MIN 401
+SYS_UID_MAX 555
+SYS_GID_MIN 405
+SYS_GID_MAX 666
+SYS_UID_MIN abcd
+SYS_UID_MAX abcd
+SYS_GID_MIN abcd
+SYS_GID_MAX abcd
+SYS_UID_MIN999
+SYS_UID_MAX999
+SYS_GID_MIN999
+SYS_GID_MAX999
+EOF
+
+for f in $(ls -1 $SOURCE/test-*.input | sort -V); do
+ echo "*** Running $f (with login.defs)"
+ prepare_testdir ${f%.input}
+ cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
+ $SYSUSERS --root=$TESTDIR
+
+ [ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
+ compare ${f%.*} "(with login.defs)" $bound
+done
+
+rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
+
+mv $TESTDIR/etc/login.defs $TESTDIR/etc/login.defs.moved
+ln -s ../../../../../etc/login.defs.moved $TESTDIR/etc/login.defs
+
+for f in $(ls -1 $SOURCE/test-*.input | sort -V); do
+ echo "*** Running $f (with login.defs symlinked)"
+ prepare_testdir ${f%.input}
+ cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
+ $SYSUSERS --root=$TESTDIR
+
+ [ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
+ compare ${f%.*} "(with login.defs symlinked)" $bound
+done
+
+rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/*
+
# tests for error conditions
for f in $(ls -1 $SOURCE/unhappy-*.input | sort -V); do
echo "*** Running test $f"
diff --git a/test/test-sysusers/test-10.expected-group b/test/test-sysusers/test-10.expected-group
index 1c92158720..c94a8322d2 100644
--- a/test/test-sysusers/test-10.expected-group
+++ b/test/test-sysusers/test-10.expected-group
@@ -1,2 +1,2 @@
u1:x:300:u2
-u2:x:SYSTEM_UID_MAX:
+u2:x:SYSTEM_UGID_MAX:
diff --git a/test/test-sysusers/test-10.expected-passwd b/test/test-sysusers/test-10.expected-passwd
index ca2d764ea0..e5f2a69993 100644
--- a/test/test-sysusers/test-10.expected-passwd
+++ b/test/test-sysusers/test-10.expected-passwd
@@ -1,2 +1,2 @@
u1:x:300:300::/:NOLOGIN
-u2:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX::/:NOLOGIN
+u2:x:SYSTEM_UGID_MAX:SYSTEM_UGID_MAX::/:NOLOGIN
diff --git a/test/test-sysusers/test-13.expected-group b/test/test-sysusers/test-13.expected-group
index c78ea54bd3..1677d41b45 100644
--- a/test/test-sysusers/test-13.expected-group
+++ b/test/test-sysusers/test-13.expected-group
@@ -1,5 +1,5 @@
hoge:x:300:
baz:x:302:
-yyy:x:SYSTEM_GID_MAX:
+yyy:x:SYSTEM_UGID_MAX:
foo:x:301:
ccc:x:305:
diff --git a/test/test-sysusers/test-13.expected-passwd b/test/test-sysusers/test-13.expected-passwd
index ffc20a8193..4a2c34b4cb 100644
--- a/test/test-sysusers/test-13.expected-passwd
+++ b/test/test-sysusers/test-13.expected-passwd
@@ -2,4 +2,4 @@ foo:x:301:301::/:NOLOGIN
aaa:x:303:302::/:NOLOGIN
bbb:x:304:302::/:NOLOGIN
ccc:x:305:305::/:NOLOGIN
-zzz:x:306:SYSTEM_GID_MAX::/:NOLOGIN
+zzz:x:306:SYSTEM_UGID_MAX::/:NOLOGIN
diff --git a/test/test-sysusers/test-14.expected-passwd b/test/test-sysusers/test-14.expected-passwd
index 62ed4f50af..3c3bef2c8e 100644
--- a/test/test-sysusers/test-14.expected-passwd
+++ b/test/test-sysusers/test-14.expected-passwd
@@ -1 +1 @@
-aaa:x:SYSTEM_UID_MAX:987::/:NOLOGIN
+aaa:x:SYSTEM_UGID_MAX:987::/:NOLOGIN
diff --git a/test/test-sysusers/test-2.expected-group b/test/test-sysusers/test-2.expected-group
index 8fcc03f4e9..fa216d79de 100644
--- a/test/test-sysusers/test-2.expected-group
+++ b/test/test-sysusers/test-2.expected-group
@@ -1,4 +1,4 @@
-u1:x:SYSTEM_UID_MAX:
+u1:x:SYSTEM_UGID_MAX:
u2:x:777:
u3:x:778:
u4:x:779:
diff --git a/test/test-sysusers/test-2.expected-passwd b/test/test-sysusers/test-2.expected-passwd
index af8068813b..ce49e84aad 100644
--- a/test/test-sysusers/test-2.expected-passwd
+++ b/test/test-sysusers/test-2.expected-passwd
@@ -1,4 +1,4 @@
-u1:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX:some gecos:/random/dir:NOLOGIN
+u1:x:SYSTEM_UGID_MAX:SYSTEM_UGID_MAX:some gecos:/random/dir:NOLOGIN
u2:x:777:777:some gecos:/random/dir:/bin/zsh
u3:x:778:778::/random/dir2:/bin/bash
u4:x:779:779::/:/bin/csh
diff --git a/test/test-sysusers/test-2.input b/test/test-sysusers/test-2.input
index cedea9e401..773d9e5da1 100644
--- a/test/test-sysusers/test-2.input
+++ b/test/test-sysusers/test-2.input
@@ -1,4 +1,4 @@
-# Test generation of ID dynamically based on SYSTEM_UID_MAX and
+# Test generation of ID dynamically based on SYSTEM_UGID_MAX and
# replacement of all fields up to the login shell.
#
#Type Name ID GECOS homedir shell
diff --git a/test/test-sysusers/test-6.expected-group b/test/test-sysusers/test-6.expected-group
index 499c9008ce..2ef661a4a1 100644
--- a/test/test-sysusers/test-6.expected-group
+++ b/test/test-sysusers/test-6.expected-group
@@ -1,2 +1,2 @@
g1:x:111:
-u1:x:SYSTEM_UID_MAX:
+u1:x:SYSTEM_UGID_MAX:
diff --git a/test/test-sysusers/test-6.expected-passwd b/test/test-sysusers/test-6.expected-passwd
index ba55a13e18..d589e2ede6 100644
--- a/test/test-sysusers/test-6.expected-passwd
+++ b/test/test-sysusers/test-6.expected-passwd
@@ -1 +1 @@
-u1:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX::/:NOLOGIN
+u1:x:SYSTEM_UGID_MAX:SYSTEM_UGID_MAX::/:NOLOGIN
diff --git a/test/test-sysusers/test-8.expected-passwd b/test/test-sysusers/test-8.expected-passwd
index 23e99f0513..b5b8fac437 100644
--- a/test/test-sysusers/test-8.expected-passwd
+++ b/test/test-sysusers/test-8.expected-passwd
@@ -1 +1 @@
-username:x:SYSTEM_UID_MAX:300::/:NOLOGIN
+username:x:SYSTEM_UGID_MAX:300::/:NOLOGIN
diff --git a/test/test-sysusers/test-9.expected-passwd b/test/test-sysusers/test-9.expected-passwd
index 0bffbcd9c7..fc2a060d69 100644
--- a/test/test-sysusers/test-9.expected-passwd
+++ b/test/test-sysusers/test-9.expected-passwd
@@ -1,2 +1,2 @@
user1:x:300:300::/:NOLOGIN
-user2:x:SYSTEM_UID_MAX:300::/:NOLOGIN
+user2:x:SYSTEM_UGID_MAX:300::/:NOLOGIN