On musl, O_ACCMODE is defined as (03|O_SEARCH), unlike glibc which
defines it as (O_RDONLY|O_WRONLY|O_RDWR). Additionally, O_SEARCH is
simply defined as O_PATH.
This causes problems for systemd on musl, as it changes the
behaviour of open_mkdir_at_full() to return -EINVAL if O_PATH is
included in flags due to the fact that O_ACCMODE includes O_SEARCH
(i.e. O_PATH). Consequently, this makes the test-fs-util test fail.
Upstream musl seems content with this behaviour and doesn't seem
interested in matching glibc's behaviour due to that defining it this
way allows for O_SEARCH to match POSIX better by allowing it to open
directories where read permission is missing. Apparently musl does some
emulation in other places to make this work more consistently as well.
Initially I took the approach of working around this by redefining
O_SEARCH as O_RDONLY if O_SEARCH == O_PATH. This fixes the test and is
the approach taken by both XZ[1] and Gzip[2][3], but was not taken as
redefining system headers potentially could be problematic.
Instead, introduce O_ACCMODE_STRICT which just is a copy of glibc's
O_ACCMODE and use it everywhere. This way we don't have to deal with
unusual definitions of O_ACCMODE from C standard libraries other than
glibc.
[1]: https://git.tukaani.org/?p=xz.git;a=blob;f=src/xz/file_io.c;h=8c83269b13fa31284f7ea5f3627a1dfbce7d6e14;hb=HEAD#l72
[2]: https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/fcntl.in.h
(lines 380 and 396, commit d7f551b30f3f2a0fa57c1b10c12f4eea41a9b89e)
[3]: https://lists.gnu.org/archive/html/bug-gzip/2025-01/msg00000.html
- Rename to script_get_shebang_interpreter and return
-EMEDIUMTYPE if the executable is not a script.
We nowadays utilize the scheme of making ret param
of getters optional, and use them directly as checkers.
- Don't unnecessarily read the whole line, but check
only the shebang first.
Sometimes it makes sense to hard kill a client if we die. Let's hence
add a third FORK_DEATHSIG flag for this purpose: FORK_DEATHSIG_SIGKILL.
To make things less confusing this also renames FORK_DEATHSIG to
FORK_DEATHSIG_SIGTERM to make clear it sends SIGTERM. We already had
FORK_DEATHSIG_SIGINT, hence this makes things nicely symmetric.
A bunch of users are switched over for FORK_DEATHSIG_SIGKILL where we
know it's safe to abort things abruptly. This should make some kernel
cases more robust, since we cannot get confused by signal masks or such.
While we are at it, also fix a bunch of bugs where we didn't take
FORK_DEATHSIG_SIGINT into account in safe_fork()
This is preparation for #28891, which adds a bunch more helpers around
"struct iovec", at which point this really deserves its own .c/.h file.
The idea is that we sooner or later can consider "struct iovec" as an
entirely generic mechanism to reference some binary blob, and is the
go-to type for this purpose whenever we need one.
Let's modernize and clean up search_and_fopen a bit: let's add support
for regular open() (instead of fopen()), as well as access() (if caller
just wants to check if a file exists without opening it.
This unifies much of the code involved, which previously was duplicated
in search_and_fopen() and search_and_fopen_nulstr()
Given that ERRNO_IS_PRIVILEGE() also matches positive values,
make sure this macro is not called with arguments that do not have
errno semantics.
In this case the arguments passed to ERRNO_IS_PRIVILEGE() are the values
returned by read_one_line_file() which can legitimately return positive
values without errno semantics, so fix this by moving ERRNO_IS_PRIVILEGE()
invocations to the branches where the return values are known to be negative.
Recent gcc versions have started to trigger false positive
maybe-uninitialized warnings. Let's make sure we initialize
variables annotated with _cleanup_ to avoid these.
This is a combination of fdopen() and fd_reopen(). i.e. it first reopens
the fd, and then converts that into a FILE*.
We do this at various places already manually. let's move this into a
helper call of its own.
-1 was used everywhere, but -EBADF or -EBADFD started being used in various
places. Let's make things consistent in the new style.
Note that there are two candidates:
EBADF 9 Bad file descriptor
EBADFD 77 File descriptor in bad state
Since we're initializating the fd, we're just assigning a value that means
"no fd yet", so it's just a bad file descriptor, and the first errno fits
better. If instead we had a valid file descriptor that became invalid because
of some operation or state change, the other errno would fit better.
In some places, initialization is dropped if unnecessary.
The man page says nothing about "e". Glibc clearly accepts it without fuss, but
it is meaningless for a memory object (and probably doesn't work). This use is
not portable, so let's avoid it.
This way we can connect correctly to any AF_UNIX socket in the file
system, and even save some code. Yay!
This also adds some test code for this, that ensures read_file_full()
works correctly for AF_UNIX sockets that violate the 108 char limit.
Supporting sockets like this kinda matters I think, for the simple
reason that apps want to build socket paths via XDG_RUNTIME_DIR and
suchlike, and we should be able to connect to them, even via
non-normalized paths.
Some calls to lookup_path_init() were not followed by any log emission.
E.g.:
$ SYSTEMD_LOG_LEVEL=debug systemctl --root=/missing enable unit; echo $?
1
Let's add a helper function and use it in various places.
$ SYSTEMD_LOG_LEVEL=debug build/systemctl --root=/missing enable unit; echo $?
Failed to initialize unit search paths for root directory /missing: No such file or directory
1
$ SYSTEMCTL_SKIP_SYSV=1 build/systemctl --root=/missing enable unit; echo $?
Failed to initialize unit search paths for root directory /missing: No such file or directory
Failed to enable: No such file or directory.
1
The repeated error in the second case is not very nice, but this is a niche
case and I don't think it's worth the trouble to trying to avoid it.
Same idea as 03677889f0.
No functional change intended. The type of the iterator is generally changed to
be 'const char*' instead of 'char*'. Despite the type commonly used, modifying
the string was not allowed.
I adjusted the naming of some short variables for clarity and reduced the scope
of some variable declarations in code that was being touched anyway.
This converts to TEST macro where it is trivial.
Some additional notable changes:
- simplify HAVE_LIBIDN #ifdef in test-dns-domain.c
- use saved_argc/saved_argv in test-copy.c, test-path-util.c,
test-tmpfiles.c and test-unit-file.c
i.e. let's pick some files we know are too large, or where struct stat's
.st_size is zero even though non-empty, and test read_virtual_file()
with that, to ensure things are handled sensibly. Goal is to ensure all
three major codepaths in read_virtual_file() are tested.
Prompted-by: #20743
Previously we'd pass all return values of read_virtual_file() to
log_info_errno() as error, but that makes no sense, given that we
sometimes return positive one with means "not truncated" but we'd show
as "Permission denied. Let's fix this, and log differently for sucess
and error.
This beefs up the READ_FULL_FILE_CONNECT_SOCKET logic of
read_full_file_full() a bit: when used a sender socket name may be
specified. If specified as NULL behaviour is as before: the client
socket name is picked by the kernel. But if specified as non-NULL the
client can pick a socket name to use when connecting. This is useful to
communicate a minimal amount of metainformation from client to server,
outside of the transport payload.
Specifically, these beefs up the service credential logic to pass an
abstract AF_UNIX socket name as client socket name when connecting via
READ_FULL_FILE_CONNECT_SOCKET, that includes the requesting unit name
and the eventual credential name. This allows servers implementing the
trivial credential socket logic to distinguish clients: via a simple
getpeername() it can be determined which unit is requesting a
credential, and which credential specifically.
Example: with this patch in place, in a unit file "waldo.service" a
configuration line like the following:
LoadCredential=foo:/run/quux/creds.sock
will result in a connection to the AF_UNIX socket /run/quux/creds.sock,
originating from an abstract namespace AF_UNIX socket:
@$RANDOM/unit/waldo.service/foo
(The $RANDOM is replaced by some randomized string. This is included in
the socket name order to avoid namespace squatting issues: the abstract
socket namespace is open to unprivileged users after all, and care needs
to be taken not to use guessable names)
The services listening on the /run/quux/creds.sock socket may thus
easily retrieve the name of the unit the credential is requested for
plus the credential name, via a simpler getpeername(), discarding the
random preifx and the /unit/ string.
This logic uses "/" as separator between the fields, since both unit
names and credential names appear in the file system, and thus are
designed to use "/" as outer separators. Given that it's a good safe
choice to use as separators here, too avoid any conflicts.
This is a minimal patch only: the new logic is used only for the unit
file credential logic. For other places where we use
READ_FULL_FILE_CONNECT_SOCKET it is probably a good idea to use this
scheme too, but this should be done carefully in later patches, since
the socket names become API that way, and we should determine the right
amount of info to pass over.