sysusers: ensure GID in uid:gid syntax exists

Ensure that the GID already exists or is created when the new
"uid:gid" syntax is used. This ensures the behaviour is always
predictable.
This commit is contained in:
Michael Vogt 2018-01-25 12:50:14 +01:00
parent e2c2060f7b
commit 28e7fad73f
10 changed files with 44 additions and 10 deletions

View 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

View 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);

View File

@ -1,4 +1,4 @@
hoge:x:300:
baz:x:302:
foo:x:301:
ccc:x:306:
ccc:x:305:

View 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

View 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 - -

View File

@ -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 "$@"

View File

@ -0,0 +1 @@
Failed to parse UID: '9999999999': Numerical result out of range

View File

@ -0,0 +1 @@
u u1 9999999999 - -

View File

@ -0,0 +1 @@
Failed to create u1: please create GID 100

View File

@ -0,0 +1,2 @@
# it is not allowed to create groups implicitely in the uid:gid syntax
u u1 100:100 -