diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml index a4083adb4f..c0d8a1682a 100644 --- a/man/sysusers.d.xml +++ b/man/sysusers.d.xml @@ -193,7 +193,7 @@ u root 0 "Superuser" /root match the owners of pre-existing files (such as SUID or SGID binaries). The syntax uid:gid is also supported to - allow creating user and group pairs with different numeric UID and GID values. If a group with the indicated GID already exists it is not created. + allow creating user and group pairs with different numeric UID and GID values. The group with the indicated GID must get created explicitly before or it must already exist. For m lines, this field should contain diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 66af3ff426..e06b4b6d5b 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -64,7 +64,7 @@ typedef struct Item { uid_t uid; bool gid_set:1; - bool gid_existing_ok:1; + bool gid_must_exist:1; bool uid_set:1; bool todo_user:1; @@ -1099,10 +1099,20 @@ static int add_group(Item *i) { r = gid_is_ok(i->gid); if (r < 0) return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); + if (i->gid_must_exist) { + /* If we require the gid to already exist we can return here: + * r > 0: means the gid does not exist -> fail + * r == 0: means the gid exists -> nothing more to do. + */ + if (r > 0) { + log_error("Failed to create %s: please create GID %d", i->name, i->gid); + return -EINVAL; + } + if (r == 0) + return 0; + } if (r == 0) { log_debug("Suggested group ID " GID_FMT " for %s already used.", i->gid, i->name); - if (i->gid_existing_ok) - return 0; i->gid_set = false; } } @@ -1538,7 +1548,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { if (r < 0) return log_error_errno(r, "Failed to parse GID: '%s': %m", id); i->gid_set = true; - i->gid_existing_ok = true; + i->gid_must_exist = true; free_and_replace(resolved_id, uid); } r = parse_uid(resolved_id, &i->uid); diff --git a/test/TEST-21-SYSUSERS/test-3.expected-group b/test/TEST-21-SYSUSERS/test-3.expected-group index 6ea8bce386..c3a63285c6 100644 --- a/test/TEST-21-SYSUSERS/test-3.expected-group +++ b/test/TEST-21-SYSUSERS/test-3.expected-group @@ -1,4 +1,4 @@ hoge:x:300: baz:x:302: foo:x:301: -ccc:x:306: +ccc:x:305: diff --git a/test/TEST-21-SYSUSERS/test-3.expected-passwd b/test/TEST-21-SYSUSERS/test-3.expected-passwd index c35e9abb82..a86954f8b3 100644 --- a/test/TEST-21-SYSUSERS/test-3.expected-passwd +++ b/test/TEST-21-SYSUSERS/test-3.expected-passwd @@ -1,4 +1,4 @@ foo:x:301:301::/:/sbin/nologin aaa:x:303:302::/:/sbin/nologin bbb:x:304:302::/:/sbin/nologin -ccc:x:305:306::/:/sbin/nologin +ccc:x:305:305::/:/sbin/nologin diff --git a/test/TEST-21-SYSUSERS/test-3.input b/test/TEST-21-SYSUSERS/test-3.input index 672c57bb93..b4f86a69f1 100644 --- a/test/TEST-21-SYSUSERS/test-3.input +++ b/test/TEST-21-SYSUSERS/test-3.input @@ -4,4 +4,4 @@ u foo 301 - - g baz 302 - - u aaa 303:302 - - u bbb 304:302 - - -u ccc 305:306 - - +u ccc 305 - - diff --git a/test/TEST-21-SYSUSERS/test.sh b/test/TEST-21-SYSUSERS/test.sh index a206fb7f3e..14f2b4ae07 100755 --- a/test/TEST-21-SYSUSERS/test.sh +++ b/test/TEST-21-SYSUSERS/test.sh @@ -11,11 +11,16 @@ test_setup() { } test_run() { + # ensure our build of systemd-sysusers is run + PATH=${BUILD_DIR}:$PATH + + # happy tests for f in test-*.input; do - echo "***** Running $f" + echo "*** Running $f" rm -f $TESTDIR/etc/* cp $f $TESTDIR/usr/lib/sysusers.d/test.conf - ${BUILD_DIR}/systemd-sysusers --root=$TESTDIR + systemd-sysusers --root=$TESTDIR + if ! diff -u $TESTDIR/etc/passwd ${f%.*}.expected-passwd; then echo "**** Unexpected output for $f" exit 1 @@ -25,6 +30,20 @@ test_run() { exit 1 fi done + + # tests for error conditions + for f in unhappy-*.input; do + echo "*** Running test $f" + rm -f $TESTDIR/etc/* + cp $f $TESTDIR/usr/lib/sysusers.d/test.conf + systemd-sysusers --root=$TESTDIR 2> /dev/null + journalctl -t systemd-sysusers -o cat | tail -n1 > $TESTDIR/tmp/err + if ! diff -u $TESTDIR/tmp/err ${f%.*}.expected-err; then + echo "**** Unexpected error output for $f" + cat $TESTDIR/tmp/err + exit 1 + fi + done } do_test "$@" diff --git a/test/TEST-21-SYSUSERS/unhappy-1.expected-err b/test/TEST-21-SYSUSERS/unhappy-1.expected-err new file mode 100644 index 0000000000..d3342402e9 --- /dev/null +++ b/test/TEST-21-SYSUSERS/unhappy-1.expected-err @@ -0,0 +1 @@ +Failed to parse UID: '9999999999': Numerical result out of range diff --git a/test/TEST-21-SYSUSERS/unhappy-1.input b/test/TEST-21-SYSUSERS/unhappy-1.input new file mode 100644 index 0000000000..77390371de --- /dev/null +++ b/test/TEST-21-SYSUSERS/unhappy-1.input @@ -0,0 +1 @@ +u u1 9999999999 - - \ No newline at end of file diff --git a/test/TEST-21-SYSUSERS/unhappy-2.expected-err b/test/TEST-21-SYSUSERS/unhappy-2.expected-err new file mode 100644 index 0000000000..5db5c20214 --- /dev/null +++ b/test/TEST-21-SYSUSERS/unhappy-2.expected-err @@ -0,0 +1 @@ +Failed to create u1: please create GID 100 diff --git a/test/TEST-21-SYSUSERS/unhappy-2.input b/test/TEST-21-SYSUSERS/unhappy-2.input new file mode 100644 index 0000000000..521c741cb5 --- /dev/null +++ b/test/TEST-21-SYSUSERS/unhappy-2.input @@ -0,0 +1,2 @@ +# it is not allowed to create groups implicitely in the uid:gid syntax +u u1 100:100 - \ No newline at end of file