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