This corresponds nicely with the specifiers we already pass for
/var/lib, /var/cache, /run and so on.
This is particular useful to update the test-path service files to
operate without guessable files, thus allowing multiple parallel
test-path invocations to pass without issues (the idea is to set $TMPDIR
early on in the test to some private directory, and then only use the
new %T or %V specifier to refer to it).
Double newlines (i.e. one empty lines) are great to structure code. But
let's avoid triple newlines (i.e. two empty lines), quadruple newlines,
quintuple newlines, …, that's just spurious whitespace.
It's an easy way to drop 121 lines of code, and keeps the coding style
of our sources a bit tigther.
Files which are installed as-is (any .service and other unit files, .conf
files, .policy files, etc), are left as is. My assumption is that SPDX
identifiers are not yet that well known, so it's better to retain the
extended header to avoid any doubt.
I also kept any copyright lines. We can probably remove them, but it'd nice to
obtain explicit acks from all involved authors before doing that.
Commit 563dc6f8e2 added support for
/etc/{passwd,group} only but since nsswitch.conf(5) appears to document the NIS
entries also for shadow, let's support this case too.
The NIS-catchall entry switches from files to NIS lookup and never goes back,
so it must be the last entry in /etc/passwd (the other +/-{user,@netgroup}
entries don't have to be).
That's how the nss_compat mode for /etc/passwd (and /etc/group) traditionally
works.
It's age-old historic behaviour that the NIS entry must be the last one. It
doesn't seem to be specified somewhere, but it worked like this since very
early SunOS when NIS was first included.
Fixes: #8467
This PR implements the first part of RFE #8046. I.e. this allows to
write:
```
u username -:300
```
Where the uid is chosen automatically but the gid is fixed.
When used in a package installation script, we want to invoke systemd-sysusers
before that package is installed (so it can contain files owned by the newly
created user), so the configuration to use is specified on the command
line. This should be a copy of the configuration that will be installed as
/usr/lib/sysusers.d/package.conf. We still want to obey any overrides in
/etc/sysusers.d or /run/sysusers.d in the usual fashion. Otherwise, we'd get a
different result when systemd-sysusers is run with a copy of the new config on
the command line and when systemd-sysusers is run at boot after package
instalation. In the second case any files in /etc or /run have higher priority,
so the same should happen when the configuration is given on the command line.
More generally, we want the behaviour in this special case to be as close to
the case where the file is finally on disk as possible, so we have to read all
configuration files, since they all might contain overrides and additional
configuration that matters. Even files that have lower priority might specify
additional groups for the user we are creating. Thus, we need to read all
configuration, but insert our new configuration somewhere with the right
priority.
If --target=/path/to/file.conf is given on the command line, we gather the list
of files, and pretend that the command-line config is read from
/path/to/file.conf (doesn't matter if the file on disk actually exists or
not). All package scripts should use this option to obtain consistent and
idempotent behaviour.
The corner case when --target= is specified and there are no positional
arguments is disallowed.
v1:
- version with --config-name=
v2:
- disallow --config-name= and no positional args
v3:
- remove --config-name=
v4:
- add --target= and rework the code completely
v5:
- fix argcounting bug and add example in man page
v6:
- rename --target to --replace
If the configuration is included in a script, this is more convient.
I thought it would be possible to use this for rpm scriptlets with
'%pre -p systemd-sysuser "..."', but apparently there is no way to pass
arguments to the executable ($1 is used for the package installation count).
But this functionality seems generally useful, e.g. for testing and one-off
scripts, so let's keep it.
There's a slight change in behaviour when files are given on the command line:
if we cannot parse them, error out instead of ignoring the failure. When trying
to parse all configuration files, we don't want to fail even if some config
files are broken, but when parsing a list of items specified explicitly, we
should.
v2:
- rename --direct to --inline
This is the first error message when running unprivileged, and the message is
unspecific, so let's at least add some logging at debug level to make this less
confusing.
On Debian/Ubuntu systems the default passwd/group files use a
slightly strange mapping. E.g. in passwd:
```
man❌6:12::/var/cache/man:/sbin/nologin
```
and in group:
```
disk❌6:
man❌12:
```
This is not supported in systemd-sysusers right now because
sysusers will not re-use an existing uid/gid in its normal
mode of operation. Unfortunately this reuse is needed to
replicate the default Debian/Ubuntu users/groups.
This commit enforces reuse when the "uid:gid" syntax is used
to fix this.
I also added a test that replicates the Debian base-passwd
passwd/group file to ensure things are ok.
This means we have more predicable behavior for "u foo uid:gid" lines
and also makes the generated files appear in the same order as the
inputs. So e.g.
```
u root 0 - /root
u daemon 1 - /usr/sbin
u games 5:60 - /usr/games
```
will generate
```
root❌0:0::/root:/bin/sh
daemon❌1:1::/usr/sbin:/sbin/nologin
games❌5:60::/usr/games:/sbin/nologin
```
This PR allows to write sysuser.conf lines like:
```
u games 5:60 -
```
This will create an a "games" user with uid 5 and games group with
gid 60. This is arguable ugly, however it is required to represent
certain configurations like the default passwd file on Debian and
Ubuntu.
When the ":" syntax is used and there is a group with the given
gid already then no new group is created. This allows writing the
following:
```
g unrelated 60
u games 5:60 -
```
which will create a "games" user with the uid 5 and the primary
gid 60. No group games is created here (might be useful for [1]).
[1] https://pagure.io/packaging-committee/issue/442
The advantage is that is the name is mispellt, cpp will warn us.
$ git grep -Ee "conf.set\('(HAVE|ENABLE)_" -l|xargs sed -r -i "s/conf.set\('(HAVE|ENABLE)_/conf.set10('\1_/"
$ git grep -Ee '#ifn?def (HAVE|ENABLE)' -l|xargs sed -r -i 's/#ifdef (HAVE|ENABLE)/#if \1/; s/#ifndef (HAVE|ENABLE)/#if ! \1/;'
$ git grep -Ee 'if.*defined\(HAVE' -l|xargs sed -i -r 's/defined\((HAVE_[A-Z0-9_]*)\)/\1/g'
$ git grep -Ee 'if.*defined\(ENABLE' -l|xargs sed -i -r 's/defined\((ENABLE_[A-Z0-9_]*)\)/\1/g'
+ manual changes to meson.build
squash! build-sys: use #if Y instead of #ifdef Y everywhere
v2:
- fix incorrect setting of HAVE_LIBIDN2
In nss-systemd we synthesize user entries for "nobody" and "root", as
fallback if we boot up with an entirely empty /etc. This is supposed to
be a fallback only though, and it's intended that both users exists
regularly in /etc/passwd + /etc/group. Before this patch
systemd-sysusers would never create the entries however as it notices
the synthetic entries. Let's add a way how systemd-sysusers can tell
nss-systemd not to synthesize the entries for itself.
Fixes: #6808
For files which are vital to boot
1. Avoid opening any window where power loss will zero them out or worse.
I know app developers all coded to the ext3 implementation, but
the only formal documentation we have says we're broken if we actually
rely on it. E.g.
* `man mount`, search for `auto_da_alloc`.
* http://www.linux-mtd.infradead.org/faq/ubifs.html#L_atomic_change
* https://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/
2. If we tell the kernel we're interested in writing them to disk, it will
tell us if that fails. So at minimum, this means we play our part in
notifying the user about errors.
I refactored error-handling in `udevadm-hwdb` a little. It turns out I did
exactly the same as had already been done in the `systemd-hwdb` version,
i.e. commit d702dcd.
Some distros (openSUSE) don't have group shadow support enabled. This can lead
to the following error:
# systemd-sysusers
Creating group foofoo with gid 478.
# systemd-sysusers
# groupdel foofoo
# systemd-sysusers
Creating group foofoo with gid 478.
Failed to write files: File exists
This patch adds --disable-gshadow option to configure. If used,
systemd-sysvusers won't consider /etc/gshadow.
This patch extracts the code which is in charge to write the new users or
groups into temporary files and move it into 4 dedicated functions.
This part was previously inlined in makes_files() making this function quite
big and hard to read and maintain.
There should be no functional change.
This adds a unified "copy_flags" parameter to all copy_xyz() function
calls, replacing the various boolean flags so far used. This should make
many invocations more readable as it is clear what behaviour is
precisely requested. This also prepares ground for adding support for
more modes later on.
We don't have plural in the name of any other -util files and this
inconsistency trips me up every time I try to type this file name
from memory. "formats-util" is even hard to pronounce.
Fixes:
Oct 20 09:10:49 systemd-sysusers[144]: Direct leak of 20 byte(s) in 1 object(s) allocated from:
Oct 20 09:10:49 systemd-sysusers[144]: #0 0x7f3565a13e60 in malloc (/lib64/libasan.so.3+0xc6e60)
Oct 20 09:10:49 systemd-sysusers[144]: #1 0x7f3565526bd0 in malloc_multiply src/basic/alloc-util.h:70
Oct 20 09:10:49 systemd-sysusers[144]: #2 0x7f356552cb55 in tempfn_xxxxxx src/basic/fileio.c:1116
Oct 20 09:10:49 systemd-sysusers[144]: #3 0x7f356552c4f0 in fopen_temporary src/basic/fileio.c:1042
Oct 20 09:10:49 systemd-sysusers[144]: #4 0x7f356555e00e in fopen_temporary_label src/basic/fileio-label.c:63
Oct 20 09:10:49 systemd-sysusers[144]: #5 0x56197c4a1766 in make_backup src/sysusers/sysusers.c:209
Oct 20 09:10:49 systemd-sysusers[144]: #6 0x56197c4a6335 in write_files src/sysusers/sysusers.c:710
Oct 20 09:10:49 systemd-sysusers[144]: #7 0x56197c4ae571 in main src/sysusers/sysusers.c:1817
Oct 20 09:10:49 systemd-sysusers[144]: #8 0x7f3564dee730 in __libc_start_main (/lib64/libc.so.6+0x20730)
Fixes:
```
==28075== 64 bytes in 1 blocks are definitely lost in loss record 2 of 3
==28075== at 0x4C2BAEE: malloc (vg_replace_malloc.c:298)
==28075== by 0x4C2DCA1: realloc (vg_replace_malloc.c:785)
==28075== by 0x4ED40A2: greedy_realloc (alloc-util.c:57)
==28075== by 0x4E90F87: extract_first_word (extract-word.c:78)
==28075== by 0x4E91813: extract_many_words (extract-word.c:270)
==28075== by 0x10FE93: parse_line (sysusers.c:1325)
==28075== by 0x11198B: read_config_file (sysusers.c:1640)
==28075== by 0x111EB8: main (sysusers.c:1773)
==28075==
```
gcc is confused by the common idiom of
return errno ? -errno : -ESOMETHING
and thinks a positive value may be returned. Replace this condition
with errno > 0 to help gcc and avoid many spurious warnings. I filed
a gcc rfe a long time ago, but it hard to say if it will ever be
implemented [1].
Both conventions were used in the codebase, this change makes things
more consistent. This is a follow up to bcb161b023.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61846
The macro is generically useful for putting together search paths, hence
let's make it truly generic, by dropping the implicit ".d" appending it
does, and leave that to the caller. Also rename it from
CONF_DIRS_NULSTR() to CONF_PATHS_NULSTR(), since it's not strictly about
dirs that way, but any kind of file system path.
Also, mark CONF_DIR_SPLIT_USR() as internal macro by renaming it to
_CONF_PATHS_SPLIT_USR() so that the leading underscore indicates that
it's internal.
There are more than enough calls doing string manipulations to deserve
its own files, hence do something about it.
This patch also sorts the #include blocks of all files that needed to be
updated, according to the sorting suggestions from CODING_STYLE. Since
pretty much every file needs our string manipulation functions this
effectively means that most files have sorted #include blocks now.
Also touches a few unrelated include files.
get_current_dir_name() can return a variety of errors, not just ENOMEM,
hence don't blindly turn its errors to ENOMEM, but return correct errors
in path_make_absolute_cwd().
This trickles down into a couple of other functions, some of which
receive unrelated minor fixes too with this commit.
systemd-sysusers.service unit creates system users and groups and it
could update /etc/passwd, /etc/group, /etc/shadow and /etc/gshadow.
Those files should have '_' smack label because of accessibility.
However, if systemd has its own smack label using '--with-smack-run-label'
configuration, systemd-sysusers process spawned by systemd(pid:1) has
its parent smack label and eventually updated files also is set as its
parent smack label.
This patch fixes that bug by labeling updated files as '_' smack label
when --with-smack-run-label' is enabled.
This also allows us to drop build.h from a ton of files, hence do so.
Since we touched the #includes of those files, let's order them properly
according to CODING_STYLE.
off_t is a really weird type as it is usually 64bit these days (at least
in sane programs), but could theoretically be 32bit. We don't support
off_t as 32bit builds though, but still constantly deal with safely
converting from off_t to other types and back for no point.
Hence, never use the type anymore. Always use uint64_t instead. This has
various benefits, including that we can expose these values directly as
D-Bus properties, and also that the values parse the same in all cases.
This is so that, when called in a loop, unquote_first_word can
distinguish between reaching the end of a string because it has consumed
all the input before the end, and consuming all the input.
This is important because we later add a flag that allows
char *in = "";
char *out;
unquote_first_word(&in, &out, flags);
To put "" in out, and set in = NULL, so the trailing empty string of the
input can be consumed, and mark that the input has been consumed.
So far a number of utilities implemented their own calls for this, unify
them in prefix_root() and prefix_roota(). The former uses heap memory,
the latter allocates from the stack via alloca().
Port over most users of a --root= logic.
When parsing words from input files, optionally automatically unescape
the passed strings, controllable via a new flags parameter.
Make use of this in tmpfiles, and port everything else over, too.
This improves parsing quite a bit, since we no longer have to process the
same string multiple times with different calls, where an earlier call
might corrupt the input for a later call.
This is needed to interoperate firstboot and sysusers. The former one is started
first, and it writes only /etc/shadow when it is told to set the root password.
It's better to relax checks here than to duplicate functionality in firstboot.
This patch removes includes that are not used. The removals were found with
include-what-you-use which checks if any of the symbols from a header is
in use.
After all it is now much more like strjoin() than strappend(). At the
same time, add support for NULL sentinels, even if they are normally not
necessary.
If the format string contains %m, clearly errno must have a meaningful
value, so we might as well use log_*_errno to have ERRNO= logged.
Using:
find . -name '*.[ch]' | xargs sed -r -i -e \
's/log_(debug|info|notice|warning|error|emergency)\((".*%m.*")/log_\1_errno(errno, \2/'
Plus some whitespace, linewrap, and indent adjustments.
Using:
find . -name '*.[ch]' | while read f; do perl -i.mmm -e \
'local $/;
local $_=<>;
s/(if\s*\([^\n]+\))\s*{\n(\s*)(log_[a-z_]*_errno\(\s*([->a-zA-Z_]+)\s*,[^;]+);\s*return\s+\g4;\s+}/\1\n\2return \3;/msg;
print;'
$f
done
And a couple of manual whitespace fixups.
As a followup to 086891e5c1 "log: add an "error" parameter to all
low-level logging calls and intrdouce log_error_errno() as log calls
that take error numbers", use sed to convert the simple cases to use
the new macros:
find . -name '*.[ch]' | xargs sed -r -i -e \
's/log_(debug|info|notice|warning|error|emergency)\("(.*)%s"(.*), strerror\(-([a-zA-Z_]+)\)\);/log_\1_errno(-\4, "\2%m"\3);/'
Multi-line log_*() invocations are not covered.
And we also should add log_unit_*_errno().
Several different systemd tools define a nulstr containing a standard
series of configuration file directories, in /etc, /run, /usr/local/lib,
/usr/lib, and (#ifdef HAVE_SPLIT_USR) /lib. Factor that logic out into
a new helper macro, CONF_DIRS_NULSTR.
When running sysusers we would clobber file ownership and permissions
on the files /etc/passwd, /etc/group and /etc/[g]shadow.
This simply preserves the ownership and mode if existing files are
found.
It is redundant to store 'hash' and 'compare' function pointers in
struct Hashmap separately. The functions always comprise a pair.
Store a single pointer to struct hash_ops instead.
systemd keeps hundreds of hashmaps, so this saves a little bit of
memory.