sysusers: ensure GID in uid:gid syntax exists
authorMichael Vogt <mvo@ubuntu.com>
Thu, 25 Jan 2018 11:50:14 +0000 (12:50 +0100)
committerMichael Vogt <mvo@ubuntu.com>
Thu, 25 Jan 2018 16:43:08 +0000 (17:43 +0100)
Ensure that the GID already exists or is created when the new
"uid:gid" syntax is used. This ensures the behaviour is always
predictable.

man/sysusers.d.xml
src/sysusers/sysusers.c
test/TEST-21-SYSUSERS/test-3.expected-group
test/TEST-21-SYSUSERS/test-3.expected-passwd
test/TEST-21-SYSUSERS/test-3.input
test/TEST-21-SYSUSERS/test.sh
test/TEST-21-SYSUSERS/unhappy-1.expected-err [new file with mode: 0644]
test/TEST-21-SYSUSERS/unhappy-1.input [new file with mode: 0644]
test/TEST-21-SYSUSERS/unhappy-2.expected-err [new file with mode: 0644]
test/TEST-21-SYSUSERS/unhappy-2.input [new file with mode: 0644]

index a4083ad..c0d8a16 100644 (file)
@@ -193,7 +193,7 @@ u      root   0               "Superuser"           /root</programlisting>
       match the owners of pre-existing files (such as SUID or SGID
       binaries).
       The syntax <literal><replaceable>uid</replaceable>:<replaceable>gid</replaceable></literal> 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.
       </para>
 
       <para>For <varname>m</varname> lines, this field should contain
index 66af3ff..e06b4b6 100644 (file)
@@ -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);
index c35e9ab..a86954f 100644 (file)
@@ -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
index 672c57b..b4f86a6 100644 (file)
@@ -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     -            -
index a206fb7..14f2b4a 100755 (executable)
@@ -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 (file)
index 0000000..d334240
--- /dev/null
@@ -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 (file)
index 0000000..7739037
--- /dev/null
@@ -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 (file)
index 0000000..5db5c20
--- /dev/null
@@ -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 (file)
index 0000000..521c741
--- /dev/null
@@ -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