1
0
mirror of https://github.com/systemd/systemd synced 2026-03-19 19:44:48 +01:00

Compare commits

..

32 Commits

Author SHA1 Message Date
Frantisek Sumsal
eb70d9450c test: correctly mask supporting services in tests, take #2
Due to a little misunderstanding the last patch doesn't work as
expected, since test_create_image() is called only for the first image
(usually TEST-01-BASIC), and all subsequent images are then (possibly)
modified with test_append_files().

Follow-up to 179ca4d2b1b5579014773a128462475f99b7a91b.
2021-06-24 16:26:19 +01:00
Lennart Poettering
86e24d608a
Merge pull request #20001 from keszybz/test-path-simplify-less
Do not call path_simplify() when not needed
2021-06-24 15:33:09 +02:00
Lennart Poettering
6abd991c71 sd-journal: add missing bracket in journal verify log message 2021-06-24 15:25:29 +02:00
Luca Boccassi
5bf7d8f04d
Merge pull request #20000 from dtardon/replace-strtoul
replace strtoul by safe_ato*
2021-06-24 14:18:58 +01:00
David Tardon
04d54d5011 udev-builtin-keyboard: drop unnecessary {} 2021-06-24 15:12:34 +02:00
David Tardon
1001167ca5 udev: replace strtoul by safe_ato* 2021-06-24 15:12:29 +02:00
Zbigniew Jędrzejewski-Szmek
280e4b368e
Merge pull request #20004 from yuwata/readdir-ensure-type
dirent-util: introduce readdir_ensure_type()
2021-06-24 15:11:06 +02:00
Lennart Poettering
4ef65db34b openssl-util: include the headers the file actually uses definitions from 2021-06-24 15:09:14 +02:00
Zbigniew Jędrzejewski-Szmek
c1e4c62235
Merge pull request #19997 from keszybz/selinux-opt
Drop libselinux dependency from libsystemd
2021-06-24 15:07:29 +02:00
Lennart Poettering
b80ef40caf ask-password: add "-n" switch for disabling trailing newline
This is similar to the "-n" switch of the "echo" command.
2021-06-24 13:25:39 +02:00
Zbigniew Jędrzejewski-Szmek
ac19bdd04b core: avoid calling path_simplify() unnecessarilly for u.requires_mounts_for keys
We would always call path_simplify() before doing a lookup, which requires the
path key to be duplicated first. But the hashmap lookup doesn't require this…
So let's opportunistically skip the allocation if the key is already present.

Inspired by https://github.com/systemd/systemd/pull/19973.
2021-06-24 10:59:45 +02:00
Zbigniew Jędrzejewski-Szmek
0fb789af20 test-hash-funcs: add new file to test that path set ignores dot components 2021-06-24 10:59:45 +02:00
Zbigniew Jędrzejewski-Szmek
da90c261af gitignore: add jekyll cache directory
Follow-up for 2d4efd1dba568e59b149fbb82b51201951e8e178.
2021-06-24 10:20:29 +02:00
Zbigniew Jędrzejewski-Szmek
c3b8bacd7b shared/selinux-util: rework switching of the getenforce() function
The approach with function pointer was neat, but it gets in the way
when we want to resolve the symbol dynamically: static initialization
is not possible. It also makes the code more complicated than necessary.
In this case, a simple boolean is sufficient.
2021-06-24 10:20:29 +02:00
Zbigniew Jędrzejewski-Szmek
cd503dbb6b shared/dlfcn-util: add sentinel helper or for dlsym_many_or_warn()
I didn't do this before to avoid churn in all the users.
2021-06-24 10:20:29 +02:00
Zbigniew Jędrzejewski-Szmek
d32f7a8e9b shared/tpm2-util: simplify and convert to the new helper
The function would return 0 or 3. I don't think the return code was
used for anything, so let's avoid the explicit calculation and return
0 or 1.
2021-06-24 10:20:27 +02:00
Zbigniew Jędrzejewski-Szmek
1622ef77ee various: convert to the new dlopen_or_warn() helper 2021-06-24 10:16:46 +02:00
Zbigniew Jędrzejewski-Szmek
fff25ab22e dlfcn-util: invert function naming and add helper that does the whole job
We warn when the operation fails, not when it succeeds. Hence this should be
"<do>_or_<handle failure>", not "<do>_and_<handle failure>". We *could* use
whatever convention we want, but rust and perl are rather consistent in using
the logical convention. We don't care about perl that much, but having a naming
convention inverted wrt. rust would be rather confusing.

Also, pretty much every implementation does similar steps, so add a nice
wrapper which combines opening of the library and loading of the symbols.

Also add missing sentinel attribute in dlopen_or_warn().
2021-06-24 10:16:43 +02:00
Zbigniew Jędrzejewski-Szmek
87501ac0eb meson: drop libseccomp and libselinux from libbasic linkage
This means libsystemd.so is without them now. This is important
because countless programs link to libsystemd.so, and do not need
to pull in selinux now. And libselinux.so pulls in libpcre2, so
we trim a nice dependency tree.

I'm not sure why libseccomp was listed there. No code seems to
refer to it.

$ diff -u <(ldd ../systemd/build/libsystemd.so|sed 's/0x.*/0x…/') <(ldd build/libsystemd.so|sed 's/0x.*/0x…/')
@@ -4,11 +4,9 @@
 	libzstd.so.1 => /lib64/libzstd.so.1 (0x…
 	liblz4.so.1 => /lib64/liblz4.so.1 (0x…
 	libcap.so.2 => /lib64/libcap.so.2 (0x…
-	libselinux.so.1 => /lib64/libselinux.so.1 (0x…
 	libgcrypt.so.20 => /lib64/libgcrypt.so.20 (0x…
 	libpthread.so.0 => /lib64/libpthread.so.0 (0x…
 	libc.so.6 => /lib64/libc.so.6 (0x…
 	/lib64/ld-linux-x86-64.so.2 (0x…
-	libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x…
 	libdl.so.2 => /lib64/libdl.so.2 (0x…
 	libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x…

$ diff -u <(ldd ../systemd/build/libudev.so|sed 's/0x.*/0x…/') <(ldd build/libudev.so|sed 's/0x.*/0x…/')
@@ -1,8 +1,5 @@
 	linux-vdso.so.1 (0x…
 	librt.so.1 => /lib64/librt.so.1 (0x…
-	libselinux.so.1 => /lib64/libselinux.so.1 (0x…
 	libpthread.so.0 => /lib64/libpthread.so.0 (0x…
 	libc.so.6 => /lib64/libc.so.6 (0x…
 	/lib64/ld-linux-x86-64.so.2 (0x…
-	libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x…
-	libdl.so.2 => /lib64/libdl.so.2 (0x…
2021-06-24 10:11:16 +02:00
Zbigniew Jędrzejewski-Szmek
b25a930f0e basic,shared: move a bunch of files to src/shared/
The goal is to move everything that requires selinux or smack
away from src/basic/. This means that src/basic/label.[ch] must move,
which implies btrfs-util.[ch], copy.[ch], and a bunch of other files
which form a cluster of internal use.

This is just moving text around, so there should be no functional difference.

test-blockdev-util is new, because path_is_encrypted() is moved to
blockdev-util.c, and so far we didn't have any tests for code there.
2021-06-24 10:11:00 +02:00
Zbigniew Jędrzejewski-Szmek
2d32453bc8 basic,shared: move dlopen helpers to shared/
This was added in 88d775b734644f26fb490836769c2bc275498fde,
with the apparent intent of using in shared/ and the rest of our code.
It doesn't matter much for our code, since libdl is part of glibc anyway,
but moving it removes one linkage from libsystemd. (libshared was already
linking to libdl explicitly).
2021-06-24 10:05:50 +02:00
Zbigniew Jędrzejewski-Szmek
6a818c3cb4 basic: move acquire_data_fd() and fd_duplicate_data_fd() to new data-fd-util.c
fd_duplicate_data_fd() is renamed to copy_data_fd(). This makes
the two functions have nicely similar names.

Now fd-util.[ch] is again about low-level file descriptor manipulations.
copy_data_fd() is a complex function that internally wraps the other
functions in copy.c. I want to move copy.c and the whole cluster of
related code from basic/ to shared/ later on, and this is a preparatory
step for that.
2021-06-24 10:05:22 +02:00
Zbigniew Jędrzejewski-Szmek
37350b81b5 Move hwdb creation code to src/shared/
hwdb_update() is the main entry point, and it is called from
"udevadm hwdb" and "systemd-hwdb", so it belongs in shared/.
2021-06-24 09:47:15 +02:00
Zbigniew Jędrzejewski-Szmek
2686114332 basic,shared: move quota-util.[ch] to src/shared/
No need for this to in basic/.
2021-06-24 09:47:15 +02:00
Zbigniew Jędrzejewski-Szmek
65ddc2c5ff basic: drop one btrfs-related function and move another
This will become useful later, it is the first step to moving btrfs-util.[ch]
out of src/basic/.
2021-06-24 09:42:08 +02:00
Yu Watanabe
f565b8676f dirent-util: use readdir_ensure_type() in readdir_no_dot() and FOREACH_DIRENT() 2021-06-24 04:29:40 +09:00
Yu Watanabe
98f7a4c8bb dirent-util: introduce readdir_ensure_type() 2021-06-24 04:19:38 +09:00
Zbigniew Jędrzejewski-Szmek
6d216bdd07 test-path-util: check that dot components are irrelevant for path comparisons 2021-06-23 18:11:49 +02:00
Zbigniew Jędrzejewski-Szmek
a79726113a TODO: elide initrd-parse-etc.service if possible 2021-06-23 18:11:49 +02:00
Zbigniew Jędrzejewski-Szmek
aa45911b79 man/50-xdg-data-dirs: add quotes as suggested by shellcheck 2021-06-23 18:11:49 +02:00
Zbigniew Jędrzejewski-Szmek
9c6535367d basic,shared: move make_mount_point_inode_*() to shared/
Those pull in selinux for labelling, and we should avoid selinux in basic/.
2021-06-23 10:34:58 +02:00
Zbigniew Jędrzejewski-Szmek
f69c2926f8 meson: sort file list
At least emacs thinks this is the right way.
2021-06-23 10:29:37 +02:00
100 changed files with 1257 additions and 1265 deletions

4
TODO
View File

@ -885,6 +885,10 @@ Features:
* fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline * fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline
* initrd-parse-etc.service: can we skip daemon-reload if /sysroot/etc/fstab is missing?
Note that we start initrd-fs.target and initrd-cleanup.target there, so a straightforward
ConditionPathExists= is not enough.
* docs: bring http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date * docs: bring http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date
* add a job mode that will fail if a transaction would mean stopping * add a job mode that will fail if a transaction would mean stopping

3
docs/.gitignore vendored
View File

@ -1 +1,2 @@
_site /_site/
/.jekyll-cache/

View File

@ -5,8 +5,8 @@ XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share}"
# add a directory if it exists # add a directory if it exists
if [[ -d /opt/foo/share ]]; then if [[ -d /opt/foo/share ]]; then
XDG_DATA_DIRS=/opt/foo/share:${XDG_DATA_DIRS} XDG_DATA_DIRS="/opt/foo/share:${XDG_DATA_DIRS}"
fi fi
# write our output # write our output
echo XDG_DATA_DIRS=$XDG_DATA_DIRS echo "XDG_DATA_DIRS=${XDG_DATA_DIRS}"

View File

@ -210,10 +210,19 @@
<varlistentry> <varlistentry>
<term><option>--no-output</option></term> <term><option>--no-output</option></term>
<listitem><para>Do not print passwords to standard output. <listitem><para>Do not print passwords to standard output. This is useful if you want to store a
This is useful if you want to store a password in kernel password in kernel keyring with <option>--keyname=</option> but do not want it to show up on screen
keyring with <option>--keyname</option> but do not want it or in logs.</para></listitem>
to show up on screen or in logs.</para></listitem> </varlistentry>
<varlistentry>
<term><option>-n</option></term>
<listitem><para>By default, when writing the acquired password to standard output it is suffixed by a
newline character. This may be turned off with the <option>-n</option> switch, similar to the switch
of the same name of the <citerefentry
project='man-pages'><refentrytitle>echo</refentrytitle><manvolnum>1</manvolnum></citerefentry>
command.</para></listitem>
</varlistentry> </varlistentry>
<xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="help" />

View File

@ -1707,7 +1707,6 @@ install_libsystemd_static = static_library(
libcap, libcap,
libblkid, libblkid,
libmount, libmount,
libselinux,
libgcrypt], libgcrypt],
c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC'])) c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC']))

View File

@ -24,6 +24,7 @@ static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
static bool arg_multiple = false; static bool arg_multiple = false;
static bool arg_no_output = false; static bool arg_no_output = false;
static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE; static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
static bool arg_newline = true;
STATIC_DESTRUCTOR_REGISTER(arg_message, freep); STATIC_DESTRUCTOR_REGISTER(arg_message, freep);
@ -54,6 +55,8 @@ static int help(void) {
" --accept-cached Accept cached passwords\n" " --accept-cached Accept cached passwords\n"
" --multiple List multiple passwords if available\n" " --multiple List multiple passwords if available\n"
" --no-output Do not print password to standard output\n" " --no-output Do not print password to standard output\n"
" -n Do not suffix password written to standard output with\n"
" newline\n"
"\nSee the %2$s for details.\n", "\nSee the %2$s for details.\n",
program_invocation_short_name, program_invocation_short_name,
link, link,
@ -104,7 +107,7 @@ static int parse_argv(int argc, char *argv[]) {
/* Note the asymmetry: the long option --echo= allows an optional argument, the short option does /* Note the asymmetry: the long option --echo= allows an optional argument, the short option does
* not. */ * not. */
while ((c = getopt_long(argc, argv, "+he", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "+hen", options, NULL)) >= 0)
switch (c) { switch (c) {
@ -177,6 +180,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_credential_name = optarg; arg_credential_name = optarg;
break; break;
case 'n':
arg_newline = false;
break;
case '?': case '?':
return -EINVAL; return -EINVAL;
@ -237,8 +244,14 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to query password: %m"); return log_error_errno(r, "Failed to query password: %m");
STRV_FOREACH(p, l) { STRV_FOREACH(p, l) {
if (!arg_no_output) if (!arg_no_output) {
puts(*p); if (arg_newline)
puts(*p);
else
fputs(*p, stdout);
}
fflush(stdout);
if (!arg_multiple) if (!arg_multiple)
break; break;

View File

@ -7,7 +7,7 @@
#include "path-util.h" #include "path-util.h"
#include "string-util.h" #include "string-util.h"
int dirent_ensure_type(DIR *d, struct dirent *de) { static int dirent_ensure_type(DIR *d, struct dirent *de) {
struct stat st; struct stat st;
assert(d); assert(d);
@ -59,11 +59,23 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
return endswith(de->d_name, suffix); return endswith(de->d_name, suffix);
} }
struct dirent* readdir_no_dot(DIR *dirp) { struct dirent *readdir_ensure_type(DIR *d) {
struct dirent* d; struct dirent *de;
assert(d);
errno = 0;
de = readdir(d);
if (de)
(void) dirent_ensure_type(d, de);
return de;
}
struct dirent *readdir_no_dot(DIR *dirp) {
struct dirent *d;
for (;;) { for (;;) {
d = readdir(dirp); d = readdir_ensure_type(dirp);
if (d && dot_or_dot_dot(d->d_name)) if (d && dot_or_dot_dot(d->d_name))
continue; continue;
return d; return d;

View File

@ -8,15 +8,14 @@
#include "macro.h" #include "macro.h"
#include "path-util.h" #include "path-util.h"
int dirent_ensure_type(DIR *d, struct dirent *de);
bool dirent_is_file(const struct dirent *de) _pure_; bool dirent_is_file(const struct dirent *de) _pure_;
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
struct dirent* readdir_no_dot(DIR *dirp); struct dirent *readdir_ensure_type(DIR *d);
struct dirent *readdir_no_dot(DIR *dirp);
#define FOREACH_DIRENT(de, d, on_error) \ #define FOREACH_DIRENT(de, d, on_error) \
for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ for (de = readdir_ensure_type(d);; de = readdir_ensure_type(d)) \
if (!de) { \ if (!de) { \
if (errno > 0) { \ if (errno > 0) { \
on_error; \ on_error; \
@ -27,7 +26,7 @@ struct dirent* readdir_no_dot(DIR *dirp);
else else
#define FOREACH_DIRENT_ALL(de, d, on_error) \ #define FOREACH_DIRENT_ALL(de, d, on_error) \
for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ for (de = readdir_ensure_type(d);; de = readdir_ensure_type(d)) \
if (!de) { \ if (!de) { \
if (errno > 0) { \ if (errno > 0) { \
on_error; \ on_error; \

View File

@ -1,40 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "dlfcn-util.h"
int dlsym_many_and_warn(void *dl, int level, ...) {
va_list ap;
int r;
/* Tries to resolve a bunch of function symbols, and logs errors about the ones it cannot
* resolve. Note that this function possibly modifies the supplied function pointers if the whole
* operation fails */
va_start(ap, level);
for (;;) {
void (**fn)(void);
void (*tfn)(void);
const char *symbol;
fn = va_arg(ap, typeof(fn));
if (!fn)
break;
symbol = va_arg(ap, typeof(symbol));
tfn = (typeof(tfn)) dlsym(dl, symbol);
if (!tfn) {
r = log_full_errno(level,
SYNTHETIC_ERRNO(ELIBBAD),
"Can't find symbol %s: %s", symbol, dlerror());
va_end(ap);
return r;
}
*fn = tfn;
}
va_end(ap);
return 0;
}

View File

@ -1,16 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <dlfcn.h>
#include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(void*, dlclose, NULL);
int dlsym_many_and_warn(void *dl, int level, ...);
/* Macro useful for putting together variable/symbol name pairs when calling dlsym_many_and_warn(). Assumes
* that each library symbol to resolve will be placed in a variable with the "sym_" prefix, i.e. a symbol
* "foobar" is loaded into a variable "sym_foobar". */
#define DLSYM_ARG(arg) \
&sym_##arg, STRINGIFY(arg)

View File

@ -2,19 +2,20 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/btrfs.h>
#include <linux/magic.h>
#include <sys/ioctl.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "copy.h"
#include "dirent-util.h" #include "dirent-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "io-util.h" #include "io-util.h"
#include "macro.h" #include "macro.h"
#include "memfd-util.h"
#include "missing_fcntl.h" #include "missing_fcntl.h"
#include "missing_syscall.h" #include "missing_syscall.h"
#include "parse-util.h" #include "parse-util.h"
@ -520,343 +521,6 @@ int move_fd(int from, int to, int cloexec) {
return to; return to;
} }
int acquire_data_fd(const void *data, size_t size, unsigned flags) {
_cleanup_close_pair_ int pipefds[2] = { -1, -1 };
char pattern[] = "/dev/shm/data-fd-XXXXXX";
_cleanup_close_ int fd = -1;
int isz = 0, r;
ssize_t n;
off_t f;
assert(data || size == 0);
/* Acquire a read-only file descriptor that when read from returns the specified data. This is much more
* complex than I wish it was. But here's why:
*
* a) First we try to use memfds. They are the best option, as we can seal them nicely to make them
* read-only. Unfortunately they require kernel 3.17, and at the time of writing we still support 3.14.
*
* b) Then, we try classic pipes. They are the second best options, as we can close the writing side, retaining
* a nicely read-only fd in the reading side. However, they are by default quite small, and unprivileged
* clients can only bump their size to a system-wide limit, which might be quite low.
*
* c) Then, we try an O_TMPFILE file in /dev/shm (that dir is the only suitable one known to exist from
* earliest boot on). To make it read-only we open the fd a second time with O_RDONLY via
* /proc/self/<fd>. Unfortunately O_TMPFILE is not available on older kernels on tmpfs.
*
* d) Finally, we try creating a regular file in /dev/shm, which we then delete.
*
* It sucks a bit that depending on the situation we return very different objects here, but that's Linux I
* figure. */
if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0)) {
/* As a special case, return /dev/null if we have been called for an empty data block */
r = open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (r < 0)
return -errno;
return r;
}
if ((flags & ACQUIRE_NO_MEMFD) == 0) {
fd = memfd_new("data-fd");
if (fd < 0)
goto try_pipe;
n = write(fd, data, size);
if (n < 0)
return -errno;
if ((size_t) n != size)
return -EIO;
f = lseek(fd, 0, SEEK_SET);
if (f != 0)
return -errno;
r = memfd_set_sealed(fd);
if (r < 0)
return r;
return TAKE_FD(fd);
}
try_pipe:
if ((flags & ACQUIRE_NO_PIPE) == 0) {
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
return -errno;
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
if (isz < 0)
return -errno;
if ((size_t) isz < size) {
isz = (int) size;
if (isz < 0 || (size_t) isz != size)
return -E2BIG;
/* Try to bump the pipe size */
(void) fcntl(pipefds[1], F_SETPIPE_SZ, isz);
/* See if that worked */
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
if (isz < 0)
return -errno;
if ((size_t) isz < size)
goto try_dev_shm;
}
n = write(pipefds[1], data, size);
if (n < 0)
return -errno;
if ((size_t) n != size)
return -EIO;
(void) fd_nonblock(pipefds[0], false);
return TAKE_FD(pipefds[0]);
}
try_dev_shm:
if ((flags & ACQUIRE_NO_TMPFILE) == 0) {
fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500);
if (fd < 0)
goto try_dev_shm_without_o_tmpfile;
n = write(fd, data, size);
if (n < 0)
return -errno;
if ((size_t) n != size)
return -EIO;
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
return fd_reopen(fd, O_RDONLY|O_CLOEXEC);
}
try_dev_shm_without_o_tmpfile:
if ((flags & ACQUIRE_NO_REGULAR) == 0) {
fd = mkostemp_safe(pattern);
if (fd < 0)
return fd;
n = write(fd, data, size);
if (n < 0) {
r = -errno;
goto unlink_and_return;
}
if ((size_t) n != size) {
r = -EIO;
goto unlink_and_return;
}
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
r = open(pattern, O_RDONLY|O_CLOEXEC);
if (r < 0)
r = -errno;
unlink_and_return:
(void) unlink(pattern);
return r;
}
return -EOPNOTSUPP;
}
/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */
#define DATA_FD_MEMORY_LIMIT (64U*1024U)
/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */
#define DATA_FD_TMP_LIMIT (1024U*1024U)
int fd_duplicate_data_fd(int fd) {
_cleanup_close_ int copy_fd = -1, tmp_fd = -1;
_cleanup_free_ void *remains = NULL;
size_t remains_size = 0;
const char *td;
struct stat st;
int r;
/* Creates a 'data' fd from the specified source fd, containing all the same data in a read-only fashion, but
* independent of it (i.e. the source fd can be closed and unmounted after this call succeeded). Tries to be
* somewhat smart about where to place the data. In the best case uses a memfd(). If memfd() are not supported
* uses a pipe instead. For larger data will use an unlinked file in /tmp, and for even larger data one in
* /var/tmp. */
if (fstat(fd, &st) < 0)
return -errno;
/* For now, let's only accept regular files, sockets, pipes and char devices */
if (S_ISDIR(st.st_mode))
return -EISDIR;
if (S_ISLNK(st.st_mode))
return -ELOOP;
if (!S_ISREG(st.st_mode) && !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode) && !S_ISCHR(st.st_mode))
return -EBADFD;
/* If we have reason to believe the data is bounded in size, then let's use memfds or pipes as backing fd. Note
* that we use the reported regular file size only as a hint, given that there are plenty special files in
* /proc and /sys which report a zero file size but can be read from. */
if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) {
/* Try a memfd first */
copy_fd = memfd_new("data-fd");
if (copy_fd >= 0) {
off_t f;
r = copy_bytes(fd, copy_fd, DATA_FD_MEMORY_LIMIT, 0);
if (r < 0)
return r;
f = lseek(copy_fd, 0, SEEK_SET);
if (f != 0)
return -errno;
if (r == 0) {
/* Did it fit into the limit? If so, we are done. */
r = memfd_set_sealed(copy_fd);
if (r < 0)
return r;
return TAKE_FD(copy_fd);
}
/* Hmm, pity, this didn't fit. Let's fall back to /tmp then, see below */
} else {
_cleanup_(close_pairp) int pipefds[2] = { -1, -1 };
int isz;
/* If memfds aren't available, use a pipe. Set O_NONBLOCK so that we will get EAGAIN rather
* then block indefinitely when we hit the pipe size limit */
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
return -errno;
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
if (isz < 0)
return -errno;
/* Try to enlarge the pipe size if necessary */
if ((size_t) isz < DATA_FD_MEMORY_LIMIT) {
(void) fcntl(pipefds[1], F_SETPIPE_SZ, DATA_FD_MEMORY_LIMIT);
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
if (isz < 0)
return -errno;
}
if ((size_t) isz >= DATA_FD_MEMORY_LIMIT) {
r = copy_bytes_full(fd, pipefds[1], DATA_FD_MEMORY_LIMIT, 0, &remains, &remains_size, NULL, NULL);
if (r < 0 && r != -EAGAIN)
return r; /* If we get EAGAIN it could be because of the source or because of
* the destination fd, we can't know, as sendfile() and friends won't
* tell us. Hence, treat this as reason to fall back, just to be
* sure. */
if (r == 0) {
/* Everything fit in, yay! */
(void) fd_nonblock(pipefds[0], false);
return TAKE_FD(pipefds[0]);
}
/* Things didn't fit in. But we read data into the pipe, let's remember that, so that
* when writing the new file we incorporate this first. */
copy_fd = TAKE_FD(pipefds[0]);
}
}
}
/* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */
if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) &&
(DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) {
off_t f;
tmp_fd = open_tmpfile_unlinkable(NULL /* NULL as directory means /tmp */, O_RDWR|O_CLOEXEC);
if (tmp_fd < 0)
return tmp_fd;
if (copy_fd >= 0) {
/* If we tried a memfd/pipe first and it ended up being too large, then copy this into the
* temporary file first. */
r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, 0);
if (r < 0)
return r;
assert(r == 0);
}
if (remains_size > 0) {
/* If there were remaining bytes (i.e. read into memory, but not written out yet) from the
* failed copy operation, let's flush them out next. */
r = loop_write(tmp_fd, remains, remains_size, false);
if (r < 0)
return r;
}
r = copy_bytes(fd, tmp_fd, DATA_FD_TMP_LIMIT - DATA_FD_MEMORY_LIMIT - remains_size, COPY_REFLINK);
if (r < 0)
return r;
if (r == 0)
goto finish; /* Yay, it fit in */
/* It didn't fit in. Let's not forget to use what we already used */
f = lseek(tmp_fd, 0, SEEK_SET);
if (f != 0)
return -errno;
CLOSE_AND_REPLACE(copy_fd, tmp_fd);
remains = mfree(remains);
remains_size = 0;
}
/* As last fallback use /var/tmp */
r = var_tmp_dir(&td);
if (r < 0)
return r;
tmp_fd = open_tmpfile_unlinkable(td, O_RDWR|O_CLOEXEC);
if (tmp_fd < 0)
return tmp_fd;
if (copy_fd >= 0) {
/* If we tried a memfd/pipe first, or a file in /tmp, and it ended up being too large, than copy this
* into the temporary file first. */
r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
if (r < 0)
return r;
assert(r == 0);
}
if (remains_size > 0) {
/* Then, copy in any read but not yet written bytes. */
r = loop_write(tmp_fd, remains, remains_size, false);
if (r < 0)
return r;
}
/* Copy in the rest */
r = copy_bytes(fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
if (r < 0)
return r;
assert(r == 0);
finish:
/* Now convert the O_RDWR file descriptor into an O_RDONLY one (and as side effect seek to the beginning of the
* file again */
return fd_reopen(tmp_fd, O_RDONLY|O_CLOEXEC);
}
int fd_move_above_stdio(int fd) { int fd_move_above_stdio(int fd) {
int flags, copy; int flags, copy;
PROTECT_ERRNO; PROTECT_ERRNO;
@ -1057,3 +721,20 @@ int read_nr_open(void) {
/* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */ /* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */
return 1024 * 1024; return 1024 * 1024;
} }
/* This is here because it's fd-related and is called from sd-journal code. Other btrfs-related utilities are
* in src/shared, but libsystemd must not link to libsystemd-shared, see docs/ARCHITECTURE.md. */
int btrfs_defrag_fd(int fd) {
int r;
assert(fd >= 0);
r = fd_verify_regular(fd);
if (r < 0)
return r;
if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0)
return -errno;
return 0;
}

View File

@ -76,10 +76,6 @@ enum {
ACQUIRE_NO_REGULAR = 1 << 4, ACQUIRE_NO_REGULAR = 1 << 4,
}; };
int acquire_data_fd(const void *data, size_t size, unsigned flags);
int fd_duplicate_data_fd(int fd);
int fd_move_above_stdio(int fd); int fd_move_above_stdio(int fd);
int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd); int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd);
@ -107,5 +103,5 @@ static inline int make_null_stdio(void) {
int fd_reopen(int fd, int flags); int fd_reopen(int fd, int flags);
int read_nr_open(void); int read_nr_open(void);
int btrfs_defrag_fd(int fd);

View File

@ -8,7 +8,6 @@
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "blockdev-util.h"
#include "dirent-util.h" #include "dirent-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
@ -581,8 +580,6 @@ int get_files_in_directory(const char *path, char ***list) {
return -errno; return -errno;
FOREACH_DIRENT_ALL(de, d, return -errno) { FOREACH_DIRENT_ALL(de, d, return -errno) {
dirent_ensure_type(d, de);
if (!dirent_is_file(de)) if (!dirent_is_file(de))
continue; continue;
@ -1504,91 +1501,6 @@ int open_parent(const char *path, int flags, mode_t mode) {
return fd; return fd;
} }
static int blockdev_is_encrypted(const char *sysfs_path, unsigned depth_left) {
_cleanup_free_ char *p = NULL, *uuids = NULL;
_cleanup_closedir_ DIR *d = NULL;
int r, found_encrypted = false;
assert(sysfs_path);
if (depth_left == 0)
return -EINVAL;
p = path_join(sysfs_path, "dm/uuid");
if (!p)
return -ENOMEM;
r = read_one_line_file(p, &uuids);
if (r != -ENOENT) {
if (r < 0)
return r;
/* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
if (startswith(uuids, "CRYPT-"))
return true;
}
/* Not a dm-crypt device itself. But maybe it is on top of one? Follow the links in the "slaves/"
* subdir. */
p = mfree(p);
p = path_join(sysfs_path, "slaves");
if (!p)
return -ENOMEM;
d = opendir(p);
if (!d) {
if (errno == ENOENT) /* Doesn't have underlying devices */
return false;
return -errno;
}
for (;;) {
_cleanup_free_ char *q = NULL;
struct dirent *de;
errno = 0;
de = readdir_no_dot(d);
if (!de) {
if (errno != 0)
return -errno;
break; /* No more underlying devices */
}
q = path_join(p, de->d_name);
if (!q)
return -ENOMEM;
r = blockdev_is_encrypted(q, depth_left - 1);
if (r < 0)
return r;
if (r == 0) /* we found one that is not encrypted? then propagate that immediately */
return false;
found_encrypted = true;
}
return found_encrypted;
}
int path_is_encrypted(const char *path) {
char p[SYS_BLOCK_PATH_MAX(NULL)];
dev_t devt;
int r;
r = get_block_device(path, &devt);
if (r < 0)
return r;
if (r == 0) /* doesn't have a block device */
return false;
xsprintf_sys_block_path(p, NULL, devt);
return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */);
}
int conservative_renameat( int conservative_renameat(
int olddirfd, const char *oldpath, int olddirfd, const char *oldpath,
int newdirfd, const char *newpath) { int newdirfd, const char *newpath) {

View File

@ -145,8 +145,6 @@ int syncfs_path(int atfd, const char *path);
int open_parent(const char *path, int flags, mode_t mode); int open_parent(const char *path, int flags, mode_t mode);
int path_is_encrypted(const char *path);
int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); int conservative_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
static inline int conservative_rename(const char *oldpath, const char *newpath) { static inline int conservative_rename(const char *oldpath, const char *newpath) {
return conservative_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath); return conservative_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath);

View File

@ -169,8 +169,6 @@ static int add_locales_from_libdir (Set *locales) {
FOREACH_DIRENT(entry, dir, return -errno) { FOREACH_DIRENT(entry, dir, return -errno) {
char *z; char *z;
dirent_ensure_type(dir, entry);
if (entry->d_type != DT_DIR) if (entry->d_type != DT_DIR)
continue; continue;

View File

@ -15,10 +15,6 @@ basic_sources = files('''
async.h async.h
audit-util.c audit-util.c
audit-util.h audit-util.h
blockdev-util.c
blockdev-util.h
btrfs-util.c
btrfs-util.h
build.c build.c
build.h build.h
bus-label.c bus-label.c
@ -33,15 +29,11 @@ basic_sources = files('''
chattr-util.h chattr-util.h
conf-files.c conf-files.c
conf-files.h conf-files.h
copy.c
copy.h
creds-util.c creds-util.c
creds-util.h creds-util.h
def.h def.h
dirent-util.c dirent-util.c
dirent-util.h dirent-util.h
dlfcn-util.c
dlfcn-util.h
dns-def.h dns-def.h
efivars.c efivars.c
efivars.h efivars.h
@ -85,8 +77,6 @@ basic_sources = files('''
ioprio.h ioprio.h
khash.c khash.c
khash.h khash.h
label.c
label.h
limits-util.c limits-util.c
limits-util.h limits-util.h
linux/btrfs.h linux/btrfs.h
@ -157,7 +147,6 @@ basic_sources = files('''
missing_syscall.h missing_syscall.h
missing_timerfd.h missing_timerfd.h
missing_type.h missing_type.h
mkdir-label.c
mkdir.c mkdir.c
mkdir.h mkdir.h
mountpoint-util.c mountpoint-util.c
@ -188,8 +177,6 @@ basic_sources = files('''
procfs-util.c procfs-util.c
procfs-util.h procfs-util.h
pthread-util.h pthread-util.h
quota-util.c
quota-util.h
random-util.c random-util.c
random-util.h random-util.h
ratelimit.c ratelimit.c
@ -202,10 +189,6 @@ basic_sources = files('''
replace-var.h replace-var.h
rlimit-util.c rlimit-util.c
rlimit-util.h rlimit-util.h
rm-rf.c
rm-rf.h
selinux-util.c
selinux-util.h
set.h set.h
sigbus.c sigbus.c
sigbus.h sigbus.h
@ -213,9 +196,6 @@ basic_sources = files('''
signal-util.h signal-util.h
siphash24.c siphash24.c
siphash24.h siphash24.h
smack-util.c
smack-util.h
socket-label.c
socket-util.c socket-util.c
socket-util.h socket-util.h
sort-util.c sort-util.c
@ -394,10 +374,7 @@ libbasic = static_library(
dependencies : [versiondep, dependencies : [versiondep,
threads, threads,
libcap, libcap,
libseccomp, libm],
libselinux,
libm,
libdl],
c_args : ['-fvisibility=default'], c_args : ['-fvisibility=default'],
install : false) install : false)

View File

@ -8,7 +8,6 @@
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "label.h"
#include "missing_stat.h" #include "missing_stat.h"
#include "missing_syscall.h" #include "missing_syscall.h"
#include "mkdir.h" #include "mkdir.h"
@ -510,25 +509,3 @@ int mount_propagation_flags_from_string(const char *name, unsigned long *ret) {
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode) {
assert(st);
assert(dest);
if (S_ISDIR(st->st_mode))
return mkdir_label(dest, mode);
else
return mknod(dest, S_IFREG|(mode & ~0111), 0);
}
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode) {
struct stat st;
assert(source);
assert(dest);
if (stat(source, &st) < 0)
return -errno;
return make_mount_point_inode_from_stat(&st, dest, mode);
}

View File

@ -23,7 +23,3 @@ int dev_is_devtmpfs(void);
const char *mount_propagation_flags_to_string(unsigned long flags); const char *mount_propagation_flags_to_string(unsigned long flags);
int mount_propagation_flags_from_string(const char *name, unsigned long *ret); int mount_propagation_flags_from_string(const char *name, unsigned long *ret);
/* Creates a mount point (not parents) based on the source path or stat - ie, a file or a directory */
int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode);
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode);

View File

@ -21,7 +21,6 @@
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "copy.h"
#include "def.h" #include "def.h"
#include "env-util.h" #include "env-util.h"
#include "fd-util.h" #include "fd-util.h"

View File

@ -321,7 +321,6 @@ int unit_file_build_name_map(
if (hashmap_contains(ids, de->d_name)) if (hashmap_contains(ids, de->d_name))
continue; continue;
dirent_ensure_type(d, de);
if (de->d_type == DT_LNK) { if (de->d_type == DT_LNK) {
/* We don't explicitly check for alias loops here. unit_ids_map_get() which /* We don't explicitly check for alias loops here. unit_ids_map_get() which
* limits the number of hops should be used to access the map. */ * limits the number of hops should be used to access the map. */

View File

@ -11,6 +11,7 @@
#include "bus-common-errors.h" #include "bus-common-errors.h"
#include "bus-get-properties.h" #include "bus-get-properties.h"
#include "bus-log-control-api.h" #include "bus-log-control-api.h"
#include "data-fd-util.h"
#include "dbus-cgroup.h" #include "dbus-cgroup.h"
#include "dbus-execute.h" #include "dbus-execute.h"
#include "dbus-job.h" #include "dbus-job.h"

View File

@ -46,6 +46,7 @@
#include "cgroup-setup.h" #include "cgroup-setup.h"
#include "chown-recursive.h" #include "chown-recursive.h"
#include "cpu-set-util.h" #include "cpu-set-util.h"
#include "data-fd-util.h"
#include "def.h" #include "def.h"
#include "env-file.h" #include "env-file.h"
#include "env-util.h" #include "env-util.h"

View File

@ -4511,16 +4511,14 @@ void manager_status_printf(Manager *m, StatusType type, const char *status, cons
va_end(ap); va_end(ap);
} }
Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { Set* manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
char p[strlen(path)+1];
assert(m); assert(m);
assert(path); assert(path);
strcpy(p, path); if (path_equal(path, "/"))
path_simplify(p); path = "";
return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p); return hashmap_get(m->units_requiring_mounts_for, path);
} }
int manager_update_failed_units(Manager *m, Unit *u, bool failed) { int manager_update_failed_units(Manager *m, Unit *u, bool failed) {

View File

@ -82,7 +82,6 @@ static int write_access2_rules(const char *srcdir) {
FOREACH_DIRENT(entry, dir, return 0) { FOREACH_DIRENT(entry, dir, return 0) {
_cleanup_fclose_ FILE *policy = NULL; _cleanup_fclose_ FILE *policy = NULL;
dirent_ensure_type(dir, entry);
if (!dirent_is_file(entry)) if (!dirent_is_file(entry))
continue; continue;
@ -149,7 +148,6 @@ static int write_cipso2_rules(const char *srcdir) {
FOREACH_DIRENT(entry, dir, return 0) { FOREACH_DIRENT(entry, dir, return 0) {
_cleanup_fclose_ FILE *policy = NULL; _cleanup_fclose_ FILE *policy = NULL;
dirent_ensure_type(dir, entry);
if (!dirent_is_file(entry)) if (!dirent_is_file(entry))
continue; continue;

View File

@ -4562,45 +4562,43 @@ int unit_kill_context(
} }
int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) { int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) {
_cleanup_free_ char *p = NULL;
UnitDependencyInfo di;
int r; int r;
assert(u); assert(u);
assert(path); assert(path);
/* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these paths in /* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these
* the unit (from the path to the UnitDependencyInfo structure indicating how to the dependency came to * paths in the unit (from the path to the UnitDependencyInfo structure indicating how to the
* be). However, we build a prefix table for all possible prefixes so that new appearing mount units can easily * dependency came to be). However, we build a prefix table for all possible prefixes so that new
* determine which units to make themselves a dependency of. */ * appearing mount units can easily determine which units to make themselves a dependency of. */
if (!path_is_absolute(path)) if (!path_is_absolute(path))
return -EINVAL; return -EINVAL;
r = hashmap_ensure_allocated(&u->requires_mounts_for, &path_hash_ops); if (hashmap_contains(u->requires_mounts_for, path)) /* Exit quickly if the path is already covered. */
if (r < 0) return 0;
return r;
p = strdup(path); _cleanup_free_ char *p = strdup(path);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
/* Use the canonical form of the path as the stored key. We call path_is_normalized()
* only after simplification, since path_is_normalized() rejects paths with '.'.
* path_is_normalized() also verifies that the path fits in PATH_MAX. */
path = path_simplify(p); path = path_simplify(p);
if (!path_is_normalized(path)) if (!path_is_normalized(path))
return -EPERM; return -EPERM;
if (hashmap_contains(u->requires_mounts_for, path)) UnitDependencyInfo di = {
return 0;
di = (UnitDependencyInfo) {
.origin_mask = mask .origin_mask = mask
}; };
r = hashmap_put(u->requires_mounts_for, path, di.data); r = hashmap_ensure_put(&u->requires_mounts_for, &path_hash_ops, p, di.data);
if (r < 0) if (r < 0)
return r; return r;
p = NULL; assert(r > 0);
TAKE_PTR(p); /* path remains a valid pointer to the string stored in the hashmap */
char prefix[strlen(path) + 1]; char prefix[strlen(path) + 1];
PATH_FOREACH_PREFIX_MORE(prefix, path) { PATH_FOREACH_PREFIX_MORE(prefix, path) {

View File

@ -311,8 +311,6 @@ static int enumerate_dir(
} }
FOREACH_DIRENT_ALL(de, d, return -errno) { FOREACH_DIRENT_ALL(de, d, return -errno) {
dirent_ensure_type(d, de);
if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d")) { if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d")) {
if (!GREEDY_REALLOC0(dirs, n_dirs + 2)) if (!GREEDY_REALLOC0(dirs, n_dirs + 2))
return -ENOMEM; return -ENOMEM;

View File

@ -11,6 +11,7 @@
#include "blockdev-util.h" #include "blockdev-util.h"
#include "btrfs-util.h" #include "btrfs-util.h"
#include "bus-common-errors.h" #include "bus-common-errors.h"
#include "data-fd-util.h"
#include "env-util.h" #include "env-util.h"
#include "errno-list.h" #include "errno-list.h"
#include "errno-util.h" #include "errno-util.h"

View File

@ -3,6 +3,7 @@
#include <stddef.h> #include <stddef.h>
#include <sys/mount.h> #include <sys/mount.h>
#include "blockdev-util.h"
#include "chown-recursive.h" #include "chown-recursive.h"
#include "copy.h" #include "copy.h"
#include "fd-util.h" #include "fd-util.h"

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "dlfcn-util.h" #include "dlfcn-util.h"
#include "log.h"
#include "pcre2-dlopen.h" #include "pcre2-dlopen.h"
#if HAVE_PCRE2 #if HAVE_PCRE2
@ -16,17 +16,6 @@ int (*sym_pcre2_match)(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, u
PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *); PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *);
int dlopen_pcre2(void) { int dlopen_pcre2(void) {
_cleanup_(dlclosep) void *dl = NULL;
int r;
if (pcre2_dl)
return 0; /* Already loaded */
dl = dlopen("libpcre2-8.so.0", RTLD_LAZY);
if (!dl)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"PCRE2 support is not installed: %s", dlerror());
/* So here's something weird: PCRE2 actually renames the symbols exported by the library via C /* So here's something weird: PCRE2 actually renames the symbols exported by the library via C
* macros, so that the exported symbols carry a suffix "_8" but when used from C the suffix is * macros, so that the exported symbols carry a suffix "_8" but when used from C the suffix is
* gone. In the argument list below we ignore this mangling. Surprisingly (at least to me), we * gone. In the argument list below we ignore this mangling. Surprisingly (at least to me), we
@ -35,25 +24,15 @@ int dlopen_pcre2(void) {
* string actually contains the "_8" suffix already due to that and we don't have to append it * string actually contains the "_8" suffix already due to that and we don't have to append it
* manually anymore. C is weird. 🤯 */ * manually anymore. C is weird. 🤯 */
r = dlsym_many_and_warn( return dlopen_many_sym_or_warn(
dl, &pcre2_dl, "libpcre2-8.so.0", LOG_ERR,
LOG_ERR,
DLSYM_ARG(pcre2_match_data_create), DLSYM_ARG(pcre2_match_data_create),
DLSYM_ARG(pcre2_match_data_free), DLSYM_ARG(pcre2_match_data_free),
DLSYM_ARG(pcre2_code_free), DLSYM_ARG(pcre2_code_free),
DLSYM_ARG(pcre2_compile), DLSYM_ARG(pcre2_compile),
DLSYM_ARG(pcre2_get_error_message), DLSYM_ARG(pcre2_get_error_message),
DLSYM_ARG(pcre2_match), DLSYM_ARG(pcre2_match),
DLSYM_ARG(pcre2_get_ovector_pointer), DLSYM_ARG(pcre2_get_ovector_pointer));
NULL);
if (r < 0)
return r;
/* Note that we never release the reference here, because there's no real reason to, after all this
* was traditionally a regular shared library dependency which lives forever too. */
pcre2_dl = TAKE_PTR(dl);
return 1;
} }
#else #else

View File

@ -131,8 +131,6 @@ libsystemd_sources = files('''
sd-device/device-util.h sd-device/device-util.h
sd-device/sd-device.c sd-device/sd-device.c
sd-hwdb/hwdb-internal.h sd-hwdb/hwdb-internal.h
sd-hwdb/hwdb-util.c
sd-hwdb/hwdb-util.h
sd-hwdb/sd-hwdb.c sd-hwdb/sd-hwdb.c
sd-netlink/generic-netlink.c sd-netlink/generic-netlink.c
sd-netlink/generic-netlink.h sd-netlink/generic-netlink.h

View File

@ -22,7 +22,6 @@
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
#include "rlimit-util.h" #include "rlimit-util.h"
#include "selinux-util.h"
#include "signal-util.h" #include "signal-util.h"
#include "stdio-util.h" #include "stdio-util.h"
#include "string-util.h" #include "string-util.h"

View File

@ -3,10 +3,27 @@
#include <stdint.h> #include <stdint.h>
#include "def.h"
#include "hashmap.h"
#include "sparse-endian.h" #include "sparse-endian.h"
#define HWDB_SIG { 'K', 'S', 'L', 'P', 'H', 'H', 'R', 'H' } #define HWDB_SIG { 'K', 'S', 'L', 'P', 'H', 'H', 'R', 'H' }
struct sd_hwdb {
unsigned n_ref;
FILE *f;
struct stat st;
union {
struct trie_header_f *head;
const char *map;
};
OrderedHashmap *properties;
Iterator properties_iterator;
bool properties_modified;
};
/* on-disk trie objects */ /* on-disk trie objects */
struct trie_header_f { struct trie_header_f {
uint8_t signature[8]; uint8_t signature[8];
@ -63,3 +80,10 @@ struct trie_value_entry2_f {
le16_t file_priority; le16_t file_priority;
le16_t padding; le16_t padding;
} _packed_; } _packed_;
#define hwdb_bin_paths \
"/etc/systemd/hwdb/hwdb.bin\0" \
"/etc/udev/hwdb.bin\0" \
"/usr/lib/systemd/hwdb/hwdb.bin\0" \
_CONF_PATHS_SPLIT_USR_NULSTR("systemd/hwdb/hwdb.bin") \
UDEVLIBEXECDIR "/hwdb.bin\0"

View File

@ -17,26 +17,10 @@
#include "fd-util.h" #include "fd-util.h"
#include "hashmap.h" #include "hashmap.h"
#include "hwdb-internal.h" #include "hwdb-internal.h"
#include "hwdb-util.h"
#include "nulstr-util.h" #include "nulstr-util.h"
#include "string-util.h" #include "string-util.h"
#include "time-util.h" #include "time-util.h"
struct sd_hwdb {
unsigned n_ref;
FILE *f;
struct stat st;
union {
struct trie_header_f *head;
const char *map;
};
OrderedHashmap *properties;
Iterator properties_iterator;
bool properties_modified;
};
struct linebuf { struct linebuf {
char bytes[LINE_MAX]; char bytes[LINE_MAX];
size_t size; size_t size;
@ -296,15 +280,6 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) {
return 0; return 0;
} }
static const char hwdb_bin_paths[] =
"/etc/systemd/hwdb/hwdb.bin\0"
"/etc/udev/hwdb.bin\0"
"/usr/lib/systemd/hwdb/hwdb.bin\0"
#if HAVE_SPLIT_USR
"/lib/systemd/hwdb/hwdb.bin\0"
#endif
UDEVLIBEXECDIR "/hwdb.bin\0";
_public_ int sd_hwdb_new(sd_hwdb **ret) { _public_ int sd_hwdb_new(sd_hwdb **ret) {
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
const char *hwdb_bin_path; const char *hwdb_bin_path;
@ -372,30 +347,6 @@ static sd_hwdb *hwdb_free(sd_hwdb *hwdb) {
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free) DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free)
bool hwdb_validate(sd_hwdb *hwdb) {
bool found = false;
const char* p;
struct stat st;
if (!hwdb)
return false;
if (!hwdb->f)
return false;
/* if hwdb.bin doesn't exist anywhere, we need to update */
NULSTR_FOREACH(p, hwdb_bin_paths)
if (stat(p, &st) >= 0) {
found = true;
break;
}
if (!found)
return true;
if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim))
return true;
return false;
}
static int properties_prepare(sd_hwdb *hwdb, const char *modalias) { static int properties_prepare(sd_hwdb *hwdb, const char *modalias) {
assert(hwdb); assert(hwdb);
assert(modalias); assert(modalias);

View File

@ -3,6 +3,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/magic.h>
#include <pthread.h> #include <pthread.h>
#include <stddef.h> #include <stddef.h>
#include <sys/mman.h> #include <sys/mman.h>
@ -13,7 +14,6 @@
#include "sd-event.h" #include "sd-event.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "btrfs-util.h"
#include "chattr-util.h" #include "chattr-util.h"
#include "compress.h" #include "compress.h"
#include "env-util.h" #include "env-util.h"
@ -3379,7 +3379,7 @@ static int journal_file_warn_btrfs(JournalFile *f) {
* expense of data integrity features (which shouldn't be too * expense of data integrity features (which shouldn't be too
* bad, given that we do our own checksumming). */ * bad, given that we do our own checksumming). */
r = btrfs_is_filesystem(f->fd); r = fd_is_fs_type(f->fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return log_warning_errno(r, "Failed to determine if journal is on btrfs: %m"); return log_warning_errno(r, "Failed to determine if journal is on btrfs: %m");
if (!r) if (!r)

View File

@ -170,7 +170,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
h2 = journal_file_hash_data(f, o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload)); h2 = journal_file_hash_data(f, o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
if (h1 != h2) { if (h1 != h2) {
error(offset, "Invalid hash (%08"PRIx64" vs. %08"PRIx64, h1, h2); error(offset, "Invalid hash (%08" PRIx64 " vs. %08" PRIx64 ")", h1, h2);
return -EBADMSG; return -EBADMSG;
} }

View File

@ -795,8 +795,6 @@ _public_ int sd_get_uids(uid_t **users) {
int k; int k;
uid_t uid; uid_t uid;
dirent_ensure_type(d, de);
if (!dirent_is_file(de)) if (!dirent_is_file(de))
continue; continue;

View File

@ -1374,7 +1374,6 @@ static int flush_devices(Manager *m) {
struct dirent *de; struct dirent *de;
FOREACH_DIRENT_ALL(de, d, break) { FOREACH_DIRENT_ALL(de, d, break) {
dirent_ensure_type(d, de);
if (!dirent_is_file(de)) if (!dirent_is_file(de))
continue; continue;

View File

@ -299,7 +299,6 @@ static int manager_enumerate_linger_users(Manager *m) {
FOREACH_DIRENT(de, d, return -errno) { FOREACH_DIRENT(de, d, return -errno) {
int k; int k;
dirent_ensure_type(d, de);
if (!dirent_is_file(de)) if (!dirent_is_file(de))
continue; continue;

View File

@ -787,8 +787,6 @@ static int find_loop_device(const char *backing_file, char **loop_dev) {
_cleanup_free_ char *sys = NULL, *fname = NULL; _cleanup_free_ char *sys = NULL, *fname = NULL;
int r; int r;
dirent_ensure_type(d, de);
if (de->d_type != DT_DIR) if (de->d_type != DT_DIR)
continue; continue;

View File

@ -4,6 +4,7 @@
#include "bus-common-errors.h" #include "bus-common-errors.h"
#include "bus-polkit.h" #include "bus-polkit.h"
#include "data-fd-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "oomd-manager-bus.h" #include "oomd-manager-bus.h"
#include "oomd-manager.h" #include "oomd-manager.h"

View File

@ -6,6 +6,7 @@
#include "bus-error.h" #include "bus-error.h"
#include "conf-files.h" #include "conf-files.h"
#include "copy.h" #include "copy.h"
#include "data-fd-util.h"
#include "def.h" #include "def.h"
#include "dirent-util.h" #include "dirent-util.h"
#include "discover-image.h" #include "discover-image.h"
@ -153,7 +154,7 @@ static int send_item(
assert(name); assert(name);
assert(fd >= 0); assert(fd >= 0);
data_fd = fd_duplicate_data_fd(fd); data_fd = copy_data_fd(fd);
if (data_fd < 0) if (data_fd < 0)
return data_fd; return data_fd;
@ -311,7 +312,6 @@ static int extract_now(
if (hashmap_get(unit_files, de->d_name)) if (hashmap_get(unit_files, de->d_name))
continue; continue;
dirent_ensure_type(d, de);
if (!IN_SET(de->d_type, DT_LNK, DT_REG)) if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue; continue;
@ -1396,7 +1396,6 @@ int portable_detach(
if (set_contains(unit_files, de->d_name)) if (set_contains(unit_files, de->d_name))
continue; continue;
dirent_ensure_type(d, de);
if (!IN_SET(de->d_type, DT_LNK, DT_REG)) if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue; continue;
@ -1569,7 +1568,6 @@ static int portable_get_state_internal(
if (set_contains(unit_files, de->d_name)) if (set_contains(unit_files, de->d_name))
continue; continue;
dirent_ensure_type(d, de);
if (!IN_SET(de->d_type, DT_LNK, DT_REG)) if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue; continue;

View File

@ -256,3 +256,88 @@ int blockdev_partscan_enabled(int fd) {
return !FLAGS_SET(ull, GENHD_FL_NO_PART_SCAN); return !FLAGS_SET(ull, GENHD_FL_NO_PART_SCAN);
} }
static int blockdev_is_encrypted(const char *sysfs_path, unsigned depth_left) {
_cleanup_free_ char *p = NULL, *uuids = NULL;
_cleanup_closedir_ DIR *d = NULL;
int r, found_encrypted = false;
assert(sysfs_path);
if (depth_left == 0)
return -EINVAL;
p = path_join(sysfs_path, "dm/uuid");
if (!p)
return -ENOMEM;
r = read_one_line_file(p, &uuids);
if (r != -ENOENT) {
if (r < 0)
return r;
/* The DM device's uuid attribute is prefixed with "CRYPT-" if this is a dm-crypt device. */
if (startswith(uuids, "CRYPT-"))
return true;
}
/* Not a dm-crypt device itself. But maybe it is on top of one? Follow the links in the "slaves/"
* subdir. */
p = mfree(p);
p = path_join(sysfs_path, "slaves");
if (!p)
return -ENOMEM;
d = opendir(p);
if (!d) {
if (errno == ENOENT) /* Doesn't have underlying devices */
return false;
return -errno;
}
for (;;) {
_cleanup_free_ char *q = NULL;
struct dirent *de;
errno = 0;
de = readdir_no_dot(d);
if (!de) {
if (errno != 0)
return -errno;
break; /* No more underlying devices */
}
q = path_join(p, de->d_name);
if (!q)
return -ENOMEM;
r = blockdev_is_encrypted(q, depth_left - 1);
if (r < 0)
return r;
if (r == 0) /* we found one that is not encrypted? then propagate that immediately */
return false;
found_encrypted = true;
}
return found_encrypted;
}
int path_is_encrypted(const char *path) {
char p[SYS_BLOCK_PATH_MAX(NULL)];
dev_t devt;
int r;
r = get_block_device(path, &devt);
if (r < 0)
return r;
if (r == 0) /* doesn't have a block device */
return false;
xsprintf_sys_block_path(p, NULL, devt);
return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */);
}

View File

@ -22,3 +22,5 @@ int get_block_device_harder(const char *path, dev_t *dev);
int lock_whole_block_device(dev_t devt, int operation); int lock_whole_block_device(dev_t devt, int operation);
int blockdev_partscan_enabled(int fd); int blockdev_partscan_enabled(int fd);
int path_is_encrypted(const char *path);

View File

@ -482,7 +482,6 @@ static int boot_entries_find_unified(
_cleanup_free_ char *j = NULL, *osrelease = NULL, *cmdline = NULL; _cleanup_free_ char *j = NULL, *osrelease = NULL, *cmdline = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
dirent_ensure_type(d, de);
if (!dirent_is_file(de)) if (!dirent_is_file(de))
continue; continue;

View File

@ -1,8 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "dlfcn-util.h" #include "dlfcn-util.h"
#include "bpf-dlopen.h" #include "bpf-dlopen.h"
#include "log.h"
#if HAVE_LIBBPF #if HAVE_LIBBPF
static void *bpf_dl = NULL; static void *bpf_dl = NULL;
@ -24,20 +24,8 @@ bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32);
const char* (*sym_bpf_program__name)(const struct bpf_program *); const char* (*sym_bpf_program__name)(const struct bpf_program *);
int dlopen_bpf(void) { int dlopen_bpf(void) {
_cleanup_(dlclosep) void *dl = NULL; return dlopen_many_sym_or_warn(
int r; &bpf_dl, "libbpf.so.0", LOG_DEBUG,
if (bpf_dl)
return 0; /* Already loaded */
dl = dlopen("libbpf.so.0", RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libbpf is not installed: %s", dlerror());
r = dlsym_many_and_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(bpf_link__destroy), DLSYM_ARG(bpf_link__destroy),
DLSYM_ARG(bpf_link__fd), DLSYM_ARG(bpf_link__fd),
DLSYM_ARG(bpf_map__fd), DLSYM_ARG(bpf_map__fd),
@ -52,15 +40,7 @@ int dlopen_bpf(void) {
DLSYM_ARG(bpf_probe_prog_type), DLSYM_ARG(bpf_probe_prog_type),
DLSYM_ARG(bpf_program__attach_cgroup), DLSYM_ARG(bpf_program__attach_cgroup),
DLSYM_ARG(bpf_program__name), DLSYM_ARG(bpf_program__name),
DLSYM_ARG(libbpf_get_error), DLSYM_ARG(libbpf_get_error));
NULL);
if (r < 0)
return r;
/* Note that we never release the reference here, because there's no real reason to, after all this
* was traditionally a regular shared library dependency which lives forever too. */
bpf_dl = TAKE_PTR(dl);
return 1;
} }
#else #else

View File

@ -69,17 +69,6 @@ static int extract_subvolume_name(const char *path, const char **subvolume) {
return 0; return 0;
} }
int btrfs_is_filesystem(int fd) {
struct statfs sfs;
assert(fd >= 0);
if (fstatfs(fd, &sfs) < 0)
return -errno;
return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
}
int btrfs_is_subvol_fd(int fd) { int btrfs_is_subvol_fd(int fd) {
struct stat st; struct stat st;
@ -93,7 +82,7 @@ int btrfs_is_subvol_fd(int fd) {
if (!btrfs_might_be_subvol(&st)) if (!btrfs_might_be_subvol(&st))
return 0; return 0;
return btrfs_is_filesystem(fd); return fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
} }
int btrfs_is_subvol(const char *path) { int btrfs_is_subvol(const char *path) {
@ -286,7 +275,7 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) {
assert(fd >= 0); assert(fd >= 0);
assert(dev); assert(dev);
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)
@ -361,7 +350,7 @@ int btrfs_subvol_get_id_fd(int fd, uint64_t *ret) {
assert(fd >= 0); assert(fd >= 0);
assert(ret); assert(ret);
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)
@ -481,7 +470,7 @@ int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) {
if (r < 0) if (r < 0)
return r; return r;
} else { } else {
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)
@ -575,7 +564,7 @@ int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
if (r < 0) if (r < 0)
return r; return r;
} else { } else {
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)
@ -762,21 +751,6 @@ int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQu
return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret); return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret);
} }
int btrfs_defrag_fd(int fd) {
int r;
assert(fd >= 0);
r = fd_verify_regular(fd);
if (r < 0)
return r;
if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0)
return -errno;
return 0;
}
int btrfs_defrag(const char *p) { int btrfs_defrag(const char *p) {
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
@ -795,7 +769,7 @@ int btrfs_quota_enable_fd(int fd, bool b) {
assert(fd >= 0); assert(fd >= 0);
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)
@ -832,7 +806,7 @@ int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max
if (r < 0) if (r < 0)
return r; return r;
} else { } else {
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)
@ -924,7 +898,7 @@ static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) {
}; };
int r; int r;
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) if (r == 0)
@ -1042,7 +1016,7 @@ static int qgroup_assign_or_unassign(int fd, bool b, uint64_t child, uint64_t pa
}; };
int r; int r;
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) if (r == 0)
@ -1269,7 +1243,7 @@ int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupi
int r; int r;
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)
@ -1738,7 +1712,7 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {
if (r < 0) if (r < 0)
return r; return r;
} else { } else {
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)
@ -1979,7 +1953,7 @@ int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) {
if (r < 0) if (r < 0)
return r; return r;
} else { } else {
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (!r) if (!r)

View File

@ -42,8 +42,6 @@ typedef enum BtrfsRemoveFlags {
BTRFS_REMOVE_QUOTA = 1 << 1, BTRFS_REMOVE_QUOTA = 1 << 1,
} BtrfsRemoveFlags; } BtrfsRemoveFlags;
int btrfs_is_filesystem(int fd);
int btrfs_is_subvol_fd(int fd); int btrfs_is_subvol_fd(int fd);
int btrfs_is_subvol(const char *path); int btrfs_is_subvol(const char *path);
@ -53,7 +51,6 @@ int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset
int btrfs_get_block_device_fd(int fd, dev_t *dev); int btrfs_get_block_device_fd(int fd, dev_t *dev);
int btrfs_get_block_device(const char *path, dev_t *dev); int btrfs_get_block_device(const char *path, dev_t *dev);
int btrfs_defrag_fd(int fd);
int btrfs_defrag(const char *p); int btrfs_defrag(const char *p);
int btrfs_quota_enable_fd(int fd, bool b); int btrfs_quota_enable_fd(int fd, bool b);

View File

@ -17,6 +17,7 @@
#include "apparmor-util.h" #include "apparmor-util.h"
#include "architecture.h" #include "architecture.h"
#include "audit-util.h" #include "audit-util.h"
#include "blockdev-util.h"
#include "cap-list.h" #include "cap-list.h"
#include "cgroup-util.h" #include "cgroup-util.h"
#include "condition.h" #include "condition.h"

View File

@ -51,20 +51,10 @@ crypt_token_info (*sym_crypt_token_status)(struct crypt_device *cd, int token, c
int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size); int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size);
int dlopen_cryptsetup(void) { int dlopen_cryptsetup(void) {
_cleanup_(dlclosep) void *dl = NULL;
int r; int r;
if (cryptsetup_dl) r = dlopen_many_sym_or_warn(
return 0; /* Already loaded */ &cryptsetup_dl, "libcryptsetup.so.12", LOG_DEBUG,
dl = dlopen("libcryptsetup.so.12", RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libcryptsetup support is not installed: %s", dlerror());
r = dlsym_many_and_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(crypt_activate_by_passphrase), DLSYM_ARG(crypt_activate_by_passphrase),
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY #if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
DLSYM_ARG(crypt_activate_by_signed_key), DLSYM_ARG(crypt_activate_by_signed_key),
@ -104,15 +94,10 @@ int dlopen_cryptsetup(void) {
DLSYM_ARG(crypt_token_max), DLSYM_ARG(crypt_token_max),
#endif #endif
DLSYM_ARG(crypt_token_status), DLSYM_ARG(crypt_token_status),
DLSYM_ARG(crypt_volume_key_get), DLSYM_ARG(crypt_volume_key_get));
NULL); if (r <= 0)
if (r < 0)
return r; return r;
/* Note that we never release the reference here, because there's no real reason to, after all this
* was traditionally a regular shared library dependency which lives forever too. */
cryptsetup_dl = TAKE_PTR(dl);
/* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that /* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that
* libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set * libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set
* whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some * whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some

350
src/shared/data-fd-util.c Normal file
View File

@ -0,0 +1,350 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "alloc-util.h"
#include "copy.h"
#include "data-fd-util.h"
#include "fd-util.h"
#include "fs-util.h"
#include "io-util.h"
#include "memfd-util.h"
#include "tmpfile-util.h"
/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */
#define DATA_FD_MEMORY_LIMIT (64U*1024U)
/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */
#define DATA_FD_TMP_LIMIT (1024U*1024U)
int acquire_data_fd(const void *data, size_t size, unsigned flags) {
_cleanup_close_pair_ int pipefds[2] = { -1, -1 };
char pattern[] = "/dev/shm/data-fd-XXXXXX";
_cleanup_close_ int fd = -1;
int isz = 0, r;
ssize_t n;
off_t f;
assert(data || size == 0);
/* Acquire a read-only file descriptor that when read from returns the specified data. This is much more
* complex than I wish it was. But here's why:
*
* a) First we try to use memfds. They are the best option, as we can seal them nicely to make them
* read-only. Unfortunately they require kernel 3.17, and at the time of writing we still support 3.14.
*
* b) Then, we try classic pipes. They are the second best options, as we can close the writing side, retaining
* a nicely read-only fd in the reading side. However, they are by default quite small, and unprivileged
* clients can only bump their size to a system-wide limit, which might be quite low.
*
* c) Then, we try an O_TMPFILE file in /dev/shm (that dir is the only suitable one known to exist from
* earliest boot on). To make it read-only we open the fd a second time with O_RDONLY via
* /proc/self/<fd>. Unfortunately O_TMPFILE is not available on older kernels on tmpfs.
*
* d) Finally, we try creating a regular file in /dev/shm, which we then delete.
*
* It sucks a bit that depending on the situation we return very different objects here, but that's Linux I
* figure. */
if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0)) {
/* As a special case, return /dev/null if we have been called for an empty data block */
r = open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (r < 0)
return -errno;
return r;
}
if ((flags & ACQUIRE_NO_MEMFD) == 0) {
fd = memfd_new("data-fd");
if (fd < 0)
goto try_pipe;
n = write(fd, data, size);
if (n < 0)
return -errno;
if ((size_t) n != size)
return -EIO;
f = lseek(fd, 0, SEEK_SET);
if (f != 0)
return -errno;
r = memfd_set_sealed(fd);
if (r < 0)
return r;
return TAKE_FD(fd);
}
try_pipe:
if ((flags & ACQUIRE_NO_PIPE) == 0) {
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
return -errno;
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
if (isz < 0)
return -errno;
if ((size_t) isz < size) {
isz = (int) size;
if (isz < 0 || (size_t) isz != size)
return -E2BIG;
/* Try to bump the pipe size */
(void) fcntl(pipefds[1], F_SETPIPE_SZ, isz);
/* See if that worked */
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
if (isz < 0)
return -errno;
if ((size_t) isz < size)
goto try_dev_shm;
}
n = write(pipefds[1], data, size);
if (n < 0)
return -errno;
if ((size_t) n != size)
return -EIO;
(void) fd_nonblock(pipefds[0], false);
return TAKE_FD(pipefds[0]);
}
try_dev_shm:
if ((flags & ACQUIRE_NO_TMPFILE) == 0) {
fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500);
if (fd < 0)
goto try_dev_shm_without_o_tmpfile;
n = write(fd, data, size);
if (n < 0)
return -errno;
if ((size_t) n != size)
return -EIO;
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
return fd_reopen(fd, O_RDONLY|O_CLOEXEC);
}
try_dev_shm_without_o_tmpfile:
if ((flags & ACQUIRE_NO_REGULAR) == 0) {
fd = mkostemp_safe(pattern);
if (fd < 0)
return fd;
n = write(fd, data, size);
if (n < 0) {
r = -errno;
goto unlink_and_return;
}
if ((size_t) n != size) {
r = -EIO;
goto unlink_and_return;
}
/* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */
r = open(pattern, O_RDONLY|O_CLOEXEC);
if (r < 0)
r = -errno;
unlink_and_return:
(void) unlink(pattern);
return r;
}
return -EOPNOTSUPP;
}
int copy_data_fd(int fd) {
_cleanup_close_ int copy_fd = -1, tmp_fd = -1;
_cleanup_free_ void *remains = NULL;
size_t remains_size = 0;
const char *td;
struct stat st;
int r;
/* Creates a 'data' fd from the specified source fd, containing all the same data in a read-only fashion, but
* independent of it (i.e. the source fd can be closed and unmounted after this call succeeded). Tries to be
* somewhat smart about where to place the data. In the best case uses a memfd(). If memfd() are not supported
* uses a pipe instead. For larger data will use an unlinked file in /tmp, and for even larger data one in
* /var/tmp. */
if (fstat(fd, &st) < 0)
return -errno;
/* For now, let's only accept regular files, sockets, pipes and char devices */
if (S_ISDIR(st.st_mode))
return -EISDIR;
if (S_ISLNK(st.st_mode))
return -ELOOP;
if (!S_ISREG(st.st_mode) && !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode) && !S_ISCHR(st.st_mode))
return -EBADFD;
/* If we have reason to believe the data is bounded in size, then let's use memfds or pipes as backing fd. Note
* that we use the reported regular file size only as a hint, given that there are plenty special files in
* /proc and /sys which report a zero file size but can be read from. */
if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) {
/* Try a memfd first */
copy_fd = memfd_new("data-fd");
if (copy_fd >= 0) {
off_t f;
r = copy_bytes(fd, copy_fd, DATA_FD_MEMORY_LIMIT, 0);
if (r < 0)
return r;
f = lseek(copy_fd, 0, SEEK_SET);
if (f != 0)
return -errno;
if (r == 0) {
/* Did it fit into the limit? If so, we are done. */
r = memfd_set_sealed(copy_fd);
if (r < 0)
return r;
return TAKE_FD(copy_fd);
}
/* Hmm, pity, this didn't fit. Let's fall back to /tmp then, see below */
} else {
_cleanup_(close_pairp) int pipefds[2] = { -1, -1 };
int isz;
/* If memfds aren't available, use a pipe. Set O_NONBLOCK so that we will get EAGAIN rather
* then block indefinitely when we hit the pipe size limit */
if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0)
return -errno;
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
if (isz < 0)
return -errno;
/* Try to enlarge the pipe size if necessary */
if ((size_t) isz < DATA_FD_MEMORY_LIMIT) {
(void) fcntl(pipefds[1], F_SETPIPE_SZ, DATA_FD_MEMORY_LIMIT);
isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0);
if (isz < 0)
return -errno;
}
if ((size_t) isz >= DATA_FD_MEMORY_LIMIT) {
r = copy_bytes_full(fd, pipefds[1], DATA_FD_MEMORY_LIMIT, 0, &remains, &remains_size, NULL, NULL);
if (r < 0 && r != -EAGAIN)
return r; /* If we get EAGAIN it could be because of the source or because of
* the destination fd, we can't know, as sendfile() and friends won't
* tell us. Hence, treat this as reason to fall back, just to be
* sure. */
if (r == 0) {
/* Everything fit in, yay! */
(void) fd_nonblock(pipefds[0], false);
return TAKE_FD(pipefds[0]);
}
/* Things didn't fit in. But we read data into the pipe, let's remember that, so that
* when writing the new file we incorporate this first. */
copy_fd = TAKE_FD(pipefds[0]);
}
}
}
/* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */
if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) &&
(DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) {
off_t f;
tmp_fd = open_tmpfile_unlinkable(NULL /* NULL as directory means /tmp */, O_RDWR|O_CLOEXEC);
if (tmp_fd < 0)
return tmp_fd;
if (copy_fd >= 0) {
/* If we tried a memfd/pipe first and it ended up being too large, then copy this into the
* temporary file first. */
r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, 0);
if (r < 0)
return r;
assert(r == 0);
}
if (remains_size > 0) {
/* If there were remaining bytes (i.e. read into memory, but not written out yet) from the
* failed copy operation, let's flush them out next. */
r = loop_write(tmp_fd, remains, remains_size, false);
if (r < 0)
return r;
}
r = copy_bytes(fd, tmp_fd, DATA_FD_TMP_LIMIT - DATA_FD_MEMORY_LIMIT - remains_size, COPY_REFLINK);
if (r < 0)
return r;
if (r == 0)
goto finish; /* Yay, it fit in */
/* It didn't fit in. Let's not forget to use what we already used */
f = lseek(tmp_fd, 0, SEEK_SET);
if (f != 0)
return -errno;
CLOSE_AND_REPLACE(copy_fd, tmp_fd);
remains = mfree(remains);
remains_size = 0;
}
/* As last fallback use /var/tmp */
r = var_tmp_dir(&td);
if (r < 0)
return r;
tmp_fd = open_tmpfile_unlinkable(td, O_RDWR|O_CLOEXEC);
if (tmp_fd < 0)
return tmp_fd;
if (copy_fd >= 0) {
/* If we tried a memfd/pipe first, or a file in /tmp, and it ended up being too large, than copy this
* into the temporary file first. */
r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
if (r < 0)
return r;
assert(r == 0);
}
if (remains_size > 0) {
/* Then, copy in any read but not yet written bytes. */
r = loop_write(tmp_fd, remains, remains_size, false);
if (r < 0)
return r;
}
/* Copy in the rest */
r = copy_bytes(fd, tmp_fd, UINT64_MAX, COPY_REFLINK);
if (r < 0)
return r;
assert(r == 0);
finish:
/* Now convert the O_RDWR file descriptor into an O_RDONLY one (and as side effect seek to the beginning of the
* file again */
return fd_reopen(tmp_fd, O_RDONLY|O_CLOEXEC);
}

View File

@ -0,0 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stddef.h>
int acquire_data_fd(const void *data, size_t size, unsigned flags);
int copy_data_fd(int fd);

View File

@ -4,6 +4,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/loop.h> #include <linux/loop.h>
#include <linux/magic.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/file.h> #include <sys/file.h>
@ -34,6 +35,7 @@
#include "os-util.h" #include "os-util.h"
#include "path-util.h" #include "path-util.h"
#include "rm-rf.h" #include "rm-rf.h"
#include "stat-util.h"
#include "string-table.h" #include "string-table.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
@ -262,7 +264,7 @@ static int image_make(
if (btrfs_might_be_subvol(st)) { if (btrfs_might_be_subvol(st)) {
r = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (r < 0) if (r < 0)
return r; return r;
if (r) { if (r) {

64
src/shared/dlfcn-util.c Normal file
View File

@ -0,0 +1,64 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "dlfcn-util.h"
static int dlsym_many_or_warnv(void *dl, int log_level, va_list ap) {
void (**fn)(void);
/* Tries to resolve a bunch of function symbols, and logs an error about if it cannot resolve one of
* them. Note that this function possibly modifies the supplied function pointers if the whole
* operation fails. */
while ((fn = va_arg(ap, typeof(fn)))) {
void (*tfn)(void);
const char *symbol;
symbol = va_arg(ap, typeof(symbol));
tfn = (typeof(tfn)) dlsym(dl, symbol);
if (!tfn)
return log_full_errno(log_level,
SYNTHETIC_ERRNO(ELIBBAD),
"Can't find symbol %s: %s", symbol, dlerror());
*fn = tfn;
}
return 0;
}
int dlsym_many_or_warn_sentinel(void *dl, int log_level, ...) {
va_list ap;
int r;
va_start(ap, log_level);
r = dlsym_many_or_warnv(dl, log_level, ap);
va_end(ap);
return r;
}
int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) {
_cleanup_(dlclosep) void *dl = NULL;
int r;
if (*dlp)
return 0; /* Already loaded */
dl = dlopen(filename, RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"%s is not installed: %s", filename, dlerror());
va_list ap;
va_start(ap, log_level);
r = dlsym_many_or_warnv(dl, log_level, ap);
va_end(ap);
if (r < 0)
return r;
/* Note that we never release the reference here, because there's no real reason to. After all this
* was traditionally a regular shared library dependency which lives forever too. */
*dlp = TAKE_PTR(dl);
return 1;
}

22
src/shared/dlfcn-util.h Normal file
View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <dlfcn.h>
#include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(void*, dlclose, NULL);
int dlsym_many_or_warn_sentinel(void *dl, int log_level, ...) _sentinel_;
int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) _sentinel_;
#define dlsym_many_or_warn(dl, log_level, ...) \
dlsym_many_or_warn_sentinel(dl, log_level, __VA_ARGS__, NULL)
#define dlopen_many_sym_or_warn(dlp, filename, log_level, ...) \
dlopen_many_sym_or_warn_sentinel(dlp, filename, log_level, __VA_ARGS__, NULL)
/* Macro useful for putting together variable/symbol name pairs when calling dlsym_many_or_warn(). Assumes
* that each library symbol to resolve will be placed in a variable with the "sym_" prefix, i.e. a symbol
* "foobar" is loaded into a variable "sym_foobar". */
#define DLSYM_ARG(arg) \
&sym_##arg, STRINGIFY(arg)

View File

@ -13,6 +13,7 @@
#include "hwdb-util.h" #include "hwdb-util.h"
#include "label.h" #include "label.h"
#include "mkdir.h" #include "mkdir.h"
#include "nulstr-util.h"
#include "path-util.h" #include "path-util.h"
#include "sort-util.h" #include "sort-util.h"
#include "strbuf.h" #include "strbuf.h"
@ -586,10 +587,10 @@ int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool co
uint16_t file_priority = 1; uint16_t file_priority = 1;
int r = 0, err; int r = 0, err;
/* The argument 'compat' controls the format version of database. If false, then hwdb.bin will be created with /* The argument 'compat' controls the format version of database. If false, then hwdb.bin will be
* additional information such that priority, line number, and filename of database source. If true, then hwdb.bin * created with additional information such that priority, line number, and filename of database
* will be created without the information. systemd-hwdb command should set the argument false, and 'udevadm hwdb' * source. If true, then hwdb.bin will be created without the information. systemd-hwdb command
* command should set it true. */ * should set the argument false, and 'udevadm hwdb' command should set it true. */
trie = new0(struct trie, 1); trie = new0(struct trie, 1);
if (!trie) if (!trie)
@ -666,3 +667,27 @@ int hwdb_query(const char *modalias) {
return 0; return 0;
} }
bool hwdb_validate(sd_hwdb *hwdb) {
bool found = false;
const char* p;
struct stat st;
if (!hwdb)
return false;
if (!hwdb->f)
return false;
/* if hwdb.bin doesn't exist anywhere, we need to update */
NULSTR_FOREACH(p, hwdb_bin_paths)
if (stat(p, &st) >= 0) {
found = true;
break;
}
if (!found)
return true;
if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim))
return true;
return false;
}

View File

@ -21,32 +21,11 @@ const char *(*sym_idn2_strerror)(int rc) = NULL;
int (*sym_idn2_to_unicode_8z8z)(const char * input, char ** output, int flags) = NULL; int (*sym_idn2_to_unicode_8z8z)(const char * input, char ** output, int flags) = NULL;
int dlopen_idn(void) { int dlopen_idn(void) {
_cleanup_(dlclosep) void *dl = NULL; return dlopen_many_sym_or_warn(
int r; &idn_dl, "libidn2.so.0", LOG_DEBUG,
if (idn_dl)
return 0; /* Already loaded */
dl = dlopen("libidn2.so.0", RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libidn2 support is not installed: %s", dlerror());
r = dlsym_many_and_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(idn2_lookup_u8), DLSYM_ARG(idn2_lookup_u8),
DLSYM_ARG(idn2_strerror), DLSYM_ARG(idn2_strerror),
DLSYM_ARG(idn2_to_unicode_8z8z), DLSYM_ARG(idn2_to_unicode_8z8z));
NULL);
if (r < 0)
return r;
/* Note that we never release the reference here, because there's no real reason to, after all this
* was traditionally a regular shared library dependency which lives forever too. */
idn_dl = TAKE_PTR(dl);
return 1;
} }
#endif #endif
@ -73,14 +52,13 @@ int dlopen_idn(void) {
"libidn support is not installed: %s", dlerror()); "libidn support is not installed: %s", dlerror());
} }
r = dlsym_many_and_warn( r = dlsym_many_or_warn(
dl, dl,
LOG_DEBUG, LOG_DEBUG,
DLSYM_ARG(idna_to_ascii_4i), DLSYM_ARG(idna_to_ascii_4i),
DLSYM_ARG(idna_to_unicode_44i), DLSYM_ARG(idna_to_unicode_44i),
DLSYM_ARG(stringprep_ucs4_to_utf8), DLSYM_ARG(stringprep_ucs4_to_utf8),
DLSYM_ARG(stringprep_utf8_to_ucs4), DLSYM_ARG(stringprep_utf8_to_ucs4));
NULL);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -568,8 +568,6 @@ static int remove_marked_symlinks_fd(
FOREACH_DIRENT(de, d, return -errno) { FOREACH_DIRENT(de, d, return -errno) {
dirent_ensure_type(d, de);
if (de->d_type == DT_DIR) { if (de->d_type == DT_DIR) {
_cleanup_free_ char *p = NULL; _cleanup_free_ char *p = NULL;
int nfd, q; int nfd, q;
@ -738,8 +736,6 @@ static int find_symlinks_in_directory(
bool found_path = false, found_dest, b = false; bool found_path = false, found_dest, b = false;
int q; int q;
dirent_ensure_type(dir, de);
if (de->d_type != DT_LNK) if (de->d_type != DT_LNK)
continue; continue;
@ -836,8 +832,6 @@ static int find_symlinks(
_cleanup_free_ const char *path = NULL; _cleanup_free_ const char *path = NULL;
_cleanup_closedir_ DIR *d = NULL; _cleanup_closedir_ DIR *d = NULL;
dirent_ensure_type(config_dir, de);
if (de->d_type != DT_DIR) if (de->d_type != DT_DIR)
continue; continue;
@ -3379,8 +3373,6 @@ int unit_file_preset_all(
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
continue; continue;
dirent_ensure_type(d, de);
if (!IN_SET(de->d_type, DT_LNK, DT_REG)) if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue; continue;
@ -3457,8 +3449,6 @@ int unit_file_get_list(
if (hashmap_get(h, de->d_name)) if (hashmap_get(h, de->d_name))
continue; continue;
dirent_ensure_type(d, de);
if (!IN_SET(de->d_type, DT_LNK, DT_REG)) if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue; continue;

View File

@ -61,20 +61,8 @@ int (*sym_fido_dev_open)(fido_dev_t *, const char *) = NULL;
const char* (*sym_fido_strerr)(int) = NULL; const char* (*sym_fido_strerr)(int) = NULL;
int dlopen_libfido2(void) { int dlopen_libfido2(void) {
_cleanup_(dlclosep) void *dl = NULL; return dlopen_many_sym_or_warn(
int r; &libfido2_dl, "libfido2.so.1", LOG_DEBUG,
if (libfido2_dl)
return 0; /* Already loaded */
dl = dlopen("libfido2.so.1", RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libfido2 support is not installed: %s", dlerror());
r = dlsym_many_and_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(fido_assert_allow_cred), DLSYM_ARG(fido_assert_allow_cred),
DLSYM_ARG(fido_assert_free), DLSYM_ARG(fido_assert_free),
DLSYM_ARG(fido_assert_hmac_secret_len), DLSYM_ARG(fido_assert_hmac_secret_len),
@ -118,15 +106,7 @@ int dlopen_libfido2(void) {
DLSYM_ARG(fido_dev_make_cred), DLSYM_ARG(fido_dev_make_cred),
DLSYM_ARG(fido_dev_new), DLSYM_ARG(fido_dev_new),
DLSYM_ARG(fido_dev_open), DLSYM_ARG(fido_dev_open),
DLSYM_ARG(fido_strerr), DLSYM_ARG(fido_strerr));
NULL);
if (r < 0)
return r;
/* Note that we never release the reference here, because there's no real reason to, after all this
* was traditionally a regular shared library dependency which lives forever too. */
libfido2_dl = TAKE_PTR(dl);
return 1;
} }
static int verify_features( static int verify_features(

View File

@ -17,6 +17,8 @@ shared_sources = files('''
bitmap.c bitmap.c
bitmap.h bitmap.h
blkid-util.h blkid-util.h
blockdev-util.c
blockdev-util.h
bond-util.c bond-util.c
bond-util.h bond-util.h
boot-timestamps.c boot-timestamps.c
@ -29,6 +31,8 @@ shared_sources = files('''
bpf-program.h bpf-program.h
bridge-util.c bridge-util.c
bridge-util.h bridge-util.h
btrfs-util.c
btrfs-util.h
bus-get-properties.c bus-get-properties.c
bus-get-properties.h bus-get-properties.h
bus-locator.c bus-locator.c
@ -71,6 +75,8 @@ shared_sources = files('''
condition.h condition.h
conf-parser.c conf-parser.c
conf-parser.h conf-parser.h
copy.c
copy.h
coredump-util.c coredump-util.c
coredump-util.h coredump-util.h
cpu-set-util.c cpu-set-util.c
@ -78,6 +84,8 @@ shared_sources = files('''
cryptsetup-util.c cryptsetup-util.c
cryptsetup-util.h cryptsetup-util.h
daemon-util.h daemon-util.h
data-fd-util.c
data-fd-util.h
dev-setup.c dev-setup.c
dev-setup.h dev-setup.h
device-nodes.c device-nodes.c
@ -87,6 +95,8 @@ shared_sources = files('''
discover-image.h discover-image.h
dissect-image.c dissect-image.c
dissect-image.h dissect-image.h
dlfcn-util.c
dlfcn-util.h
dm-util.c dm-util.c
dm-util.h dm-util.h
dns-domain.c dns-domain.c
@ -129,6 +139,8 @@ shared_sources = files('''
group-record.h group-record.h
hostname-setup.c hostname-setup.c
hostname-setup.h hostname-setup.h
hwdb-util.c
hwdb-util.h
id128-print.c id128-print.c
id128-print.h id128-print.h
idn-util.c idn-util.c
@ -142,10 +154,10 @@ shared_sources = files('''
install-printf.h install-printf.h
install.c install.c
install.h install.h
ipvlan-util.c
ipvlan-util.h
ip-protocol-list.c ip-protocol-list.c
ip-protocol-list.h ip-protocol-list.h
ipvlan-util.c
ipvlan-util.h
journal-importer.c journal-importer.c
journal-importer.h journal-importer.h
journal-util.c journal-util.c
@ -157,6 +169,8 @@ shared_sources = files('''
kbd-util.h kbd-util.h
killall.c killall.c
killall.h killall.h
label.c
label.h
libcrypt-util.c libcrypt-util.c
libcrypt-util.h libcrypt-util.h
libfido2-util.c libfido2-util.c
@ -186,6 +200,7 @@ shared_sources = files('''
macvlan-util.c macvlan-util.c
macvlan-util.h macvlan-util.h
main-func.h main-func.h
mkdir-label.c
mkfs-util.c mkfs-util.c
mkfs-util.h mkfs-util.h
module-util.h module-util.h
@ -223,21 +238,30 @@ shared_sources = files('''
pwquality-util.h pwquality-util.h
qrcode-util.c qrcode-util.c
qrcode-util.h qrcode-util.h
quota-util.c
quota-util.h
reboot-util.c reboot-util.c
reboot-util.h reboot-util.h
resize-fs.c resize-fs.c
resize-fs.h resize-fs.h
resolve-util.c resolve-util.c
resolve-util.h resolve-util.h
rm-rf.c
rm-rf.h
seccomp-util.h seccomp-util.h
securebits-util.c securebits-util.c
securebits-util.h securebits-util.h
selinux-util.c
selinux-util.h
serialize.c serialize.c
serialize.h serialize.h
service-util.c service-util.c
service-util.h service-util.h
sleep-config.c sleep-config.c
sleep-config.h sleep-config.h
smack-util.c
smack-util.h
socket-label.c
socket-netlink.c socket-netlink.c
socket-netlink.h socket-netlink.h
spawn-ask-password-agent.c spawn-ask-password-agent.c
@ -264,10 +288,10 @@ shared_sources = files('''
user-record-show.h user-record-show.h
user-record.c user-record.c
user-record.h user-record.h
userdb.c
userdb.h
userdb-dropin.c userdb-dropin.c
userdb-dropin.h userdb-dropin.h
userdb.c
userdb.h
utmp-wtmp.h utmp-wtmp.h
varlink.c varlink.c
varlink.h varlink.h

View File

@ -16,6 +16,7 @@
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "hashmap.h" #include "hashmap.h"
#include "label.h"
#include "libmount-util.h" #include "libmount-util.h"
#include "missing_mount.h" #include "missing_mount.h"
#include "missing_syscall.h" #include "missing_syscall.h"
@ -1071,3 +1072,25 @@ int remount_idmap(
return 0; return 0;
} }
int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode) {
assert(st);
assert(dest);
if (S_ISDIR(st->st_mode))
return mkdir_label(dest, mode);
else
return mknod(dest, S_IFREG|(mode & ~0111), 0);
}
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode) {
struct stat st;
assert(source);
assert(dest);
if (stat(source, &st) < 0)
return -errno;
return make_mount_point_inode_from_stat(&st, dest, mode);
}

View File

@ -3,6 +3,7 @@
#include <mntent.h> #include <mntent.h>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
@ -108,3 +109,7 @@ int mount_image_in_namespace(pid_t target, const char *propagate_path, const cha
int make_mount_point(const char *path); int make_mount_point(const char *path);
int remount_idmap(const char *p, uid_t uid_shift, uid_t uid_range); int remount_idmap(const char *p, uid_t uid_shift, uid_t uid_range);
/* Creates a mount point (not parents) based on the source path or stat - ie, a file or a directory */
int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode);
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode);

View File

@ -139,8 +139,6 @@ static int numa_max_node(void) {
int node; int node;
const char *n; const char *n;
(void) dirent_ensure_type(d, de);
if (de->d_type != DT_DIR) if (de->d_type != DT_DIR)
continue; continue;

View File

@ -4,7 +4,8 @@
#include "macro.h" #include "macro.h"
#if HAVE_OPENSSL #if HAVE_OPENSSL
# include <openssl/pem.h> # include <openssl/evp.h>
# include <openssl/x509.h>
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509_NAME*, X509_NAME_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509_NAME*, X509_NAME_free, NULL);

View File

@ -24,20 +24,8 @@ int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int v
const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror); const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror);
int dlopen_pwquality(void) { int dlopen_pwquality(void) {
_cleanup_(dlclosep) void *dl = NULL; return dlopen_many_sym_or_warn(
int r; &pwquality_dl, "libpwquality.so.1", LOG_DEBUG,
if (pwquality_dl)
return 0; /* Already loaded */
dl = dlopen("libpwquality.so.1", RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libpwquality support is not installed: %s", dlerror());
r = dlsym_many_and_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(pwquality_check), DLSYM_ARG(pwquality_check),
DLSYM_ARG(pwquality_default_settings), DLSYM_ARG(pwquality_default_settings),
DLSYM_ARG(pwquality_free_settings), DLSYM_ARG(pwquality_free_settings),
@ -45,15 +33,7 @@ int dlopen_pwquality(void) {
DLSYM_ARG(pwquality_get_str_value), DLSYM_ARG(pwquality_get_str_value),
DLSYM_ARG(pwquality_read_config), DLSYM_ARG(pwquality_read_config),
DLSYM_ARG(pwquality_set_int_value), DLSYM_ARG(pwquality_set_int_value),
DLSYM_ARG(pwquality_strerror), DLSYM_ARG(pwquality_strerror));
NULL);
if (r < 0)
return r;
/* Note that we never release the reference here, because there's no real reason to, after all this
* was traditionally a regular shared library dependency which lives forever too. */
pwquality_dl = TAKE_PTR(dl);
return 1;
} }
void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) { void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) {

View File

@ -5,9 +5,9 @@
#if HAVE_QRENCODE #if HAVE_QRENCODE
#include <qrencode.h> #include <qrencode.h>
#include "alloc-util.h"
#include "dlfcn-util.h" #include "dlfcn-util.h"
#include "locale-util.h" #include "locale-util.h"
#include "log.h"
#include "terminal-util.h" #include "terminal-util.h"
#define ANSI_WHITE_ON_BLACK "\033[40;37;1m" #define ANSI_WHITE_ON_BLACK "\033[40;37;1m"
@ -18,30 +18,10 @@ static QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecL
static void (*sym_QRcode_free)(QRcode *qrcode) = NULL; static void (*sym_QRcode_free)(QRcode *qrcode) = NULL;
int dlopen_qrencode(void) { int dlopen_qrencode(void) {
_cleanup_(dlclosep) void *dl = NULL; return dlopen_many_sym_or_warn(
int r; &qrcode_dl, "libqrencode.so.4", LOG_DEBUG,
if (qrcode_dl)
return 0; /* Already loaded */
dl = dlopen("libqrencode.so.4", RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"libqrcode support is not installed: %s", dlerror());
r = dlsym_many_and_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(QRcode_encodeString), DLSYM_ARG(QRcode_encodeString),
DLSYM_ARG(QRcode_free), DLSYM_ARG(QRcode_free));
NULL);
if (r < 0)
return r;
/* Note that we never release the reference here, because there's no real reason to, after all this
* was traditionally a regular shared library dependency which lives forever too. */
qrcode_dl = TAKE_PTR(dl);
return 1;
} }
static void print_border(FILE *output, unsigned width) { static void print_border(FILE *output, unsigned width) {

View File

@ -36,9 +36,9 @@ static int mac_selinux_reload(int seqno);
static int cached_use = -1; static int cached_use = -1;
static bool initialized = false; static bool initialized = false;
static int (*enforcing_status_func)(void) = security_getenforce;
static int last_policyload = 0; static int last_policyload = 0;
static struct selabel_handle *label_hnd = NULL; static struct selabel_handle *label_hnd = NULL;
static bool have_status_page = false;
#define log_enforcing(...) \ #define log_enforcing(...) \
log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__) log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__)
@ -70,11 +70,19 @@ bool mac_selinux_use(void) {
} }
bool mac_selinux_enforcing(void) { bool mac_selinux_enforcing(void) {
int r = 0;
#if HAVE_SELINUX #if HAVE_SELINUX
return enforcing_status_func() != 0;
#else /* If the SELinux status page has been successfully opened, retrieve the enforcing
return false; * status over it to avoid system calls in security_getenforce(). */
if (have_status_page)
r = selinux_status_getenforce();
else
r = security_getenforce();
#endif #endif
return r != 0;
} }
void mac_selinux_retest(void) { void mac_selinux_retest(void) {
@ -142,7 +150,6 @@ static int open_label_db(void) {
int mac_selinux_init(void) { int mac_selinux_init(void) {
#if HAVE_SELINUX #if HAVE_SELINUX
int r; int r;
bool have_status_page = false;
if (initialized) if (initialized)
return 0; return 0;
@ -170,11 +177,6 @@ int mac_selinux_init(void) {
* first call without any actual change. */ * first call without any actual change. */
last_policyload = selinux_status_policyload(); last_policyload = selinux_status_policyload();
if (have_status_page)
/* Now that the SELinux status page has been successfully opened, retrieve the enforcing
* status over it (to avoid system calls in security_getenforce()). */
enforcing_status_func = selinux_status_getenforce;
initialized = true; initialized = true;
#endif #endif
return 0; return 0;
@ -215,9 +217,8 @@ void mac_selinux_finish(void) {
label_hnd = NULL; label_hnd = NULL;
} }
enforcing_status_func = security_getenforce;
selinux_status_close(); selinux_status_close();
have_status_page = false;
initialized = false; initialized = false;
#endif #endif

View File

@ -6,6 +6,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/magic.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -28,6 +29,7 @@
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "sleep-config.h" #include "sleep-config.h"
#include "stat-util.h"
#include "stdio-util.h" #include "stdio-util.h"
#include "string-table.h" #include "string-table.h"
#include "string-util.h" #include "string-util.h"
@ -232,7 +234,7 @@ static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offse
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
_cleanup_free_ struct fiemap *fiemap = NULL; _cleanup_free_ struct fiemap *fiemap = NULL;
struct stat sb; struct stat sb;
int r, btrfs; int r;
assert(swap); assert(swap);
assert(swap->device); assert(swap->device);
@ -245,10 +247,10 @@ static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offse
if (fstat(fd, &sb) < 0) if (fstat(fd, &sb) < 0)
return log_debug_errno(errno, "Failed to stat %s: %m", swap->device); return log_debug_errno(errno, "Failed to stat %s: %m", swap->device);
btrfs = btrfs_is_filesystem(fd); r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
if (btrfs < 0) if (r < 0)
return log_debug_errno(btrfs, "Error checking %s for Btrfs filesystem: %m", swap->device); return log_debug_errno(r, "Error checking %s for Btrfs filesystem: %m", swap->device);
if (btrfs > 0) { if (r > 0) {
log_debug("%s: detection of swap file offset on Btrfs is not supported", swap->device); log_debug("%s: detection of swap file offset on Btrfs is not supported", swap->device);
*ret_offset = UINT64_MAX; *ret_offset = UINT64_MAX;
return 0; return 0;

View File

@ -42,84 +42,38 @@ TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Marshal)(TPM2B_PUBLIC const *src, uint8_t buf
TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL; TSS2_RC (*sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[], size_t buffer_size, size_t *offset, TPM2B_PUBLIC *dest) = NULL;
int dlopen_tpm2(void) { int dlopen_tpm2(void) {
int r, k = 0; int r;
if (!libtss2_esys_dl) { r = dlopen_many_sym_or_warn(
_cleanup_(dlclosep) void *dl = NULL; &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
DLSYM_ARG(Esys_Create),
DLSYM_ARG(Esys_CreatePrimary),
DLSYM_ARG(Esys_Finalize),
DLSYM_ARG(Esys_FlushContext),
DLSYM_ARG(Esys_Free),
DLSYM_ARG(Esys_GetRandom),
DLSYM_ARG(Esys_Initialize),
DLSYM_ARG(Esys_Load),
DLSYM_ARG(Esys_PolicyGetDigest),
DLSYM_ARG(Esys_PolicyPCR),
DLSYM_ARG(Esys_StartAuthSession),
DLSYM_ARG(Esys_Startup),
DLSYM_ARG(Esys_Unseal));
if (r < 0)
return r;
dl = dlopen("libtss2-esys.so.0", RTLD_LAZY); r = dlopen_many_sym_or_warn(
if (!dl) &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), DLSYM_ARG(Tss2_RC_Decode));
"TPM2 support is not installed: %s", dlerror()); if (r < 0)
return r;
r = dlsym_many_and_warn( return dlopen_many_sym_or_warn(
dl, &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
LOG_DEBUG, DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
DLSYM_ARG(Esys_Create), DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
DLSYM_ARG(Esys_CreatePrimary), DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
DLSYM_ARG(Esys_Finalize), DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal));
DLSYM_ARG(Esys_FlushContext),
DLSYM_ARG(Esys_Free),
DLSYM_ARG(Esys_GetRandom),
DLSYM_ARG(Esys_Initialize),
DLSYM_ARG(Esys_Load),
DLSYM_ARG(Esys_PolicyGetDigest),
DLSYM_ARG(Esys_PolicyPCR),
DLSYM_ARG(Esys_StartAuthSession),
DLSYM_ARG(Esys_Startup),
DLSYM_ARG(Esys_Unseal),
NULL);
if (r < 0)
return r;
libtss2_esys_dl = TAKE_PTR(dl);
k++;
}
if (!libtss2_rc_dl) {
_cleanup_(dlclosep) void *dl = NULL;
dl = dlopen("libtss2-rc.so.0", RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 support is not installed: %s", dlerror());
r = dlsym_many_and_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(Tss2_RC_Decode),
NULL);
if (r < 0)
return r;
libtss2_rc_dl = TAKE_PTR(dl);
k++;
}
if (!libtss2_mu_dl) {
_cleanup_(dlclosep) void *dl = NULL;
dl = dlopen("libtss2-mu.so.0", RTLD_LAZY);
if (!dl)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"TPM2 support is not installed: %s", dlerror());
r = dlsym_many_and_warn(
dl,
LOG_DEBUG,
DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Marshal),
DLSYM_ARG(Tss2_MU_TPM2B_PRIVATE_Unmarshal),
DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Marshal),
DLSYM_ARG(Tss2_MU_TPM2B_PUBLIC_Unmarshal),
NULL);
if (r < 0)
return r;
libtss2_mu_dl = TAKE_PTR(dl);
k++;
}
return k;
} }
struct tpm2_context { struct tpm2_context {

View File

@ -146,6 +146,8 @@ tests += [
[['src/test/test-utf8.c']], [['src/test/test-utf8.c']],
[['src/test/test-blockdev-util.c']],
[['src/test/test-dev-setup.c']], [['src/test/test-dev-setup.c']],
[['src/test/test-capability.c'], [['src/test/test-capability.c'],
@ -159,6 +161,8 @@ tests += [
[['src/test/test-copy.c']], [['src/test/test-copy.c']],
[['src/test/test-data-fd-util.c']],
[['src/test/test-static-destruct.c']], [['src/test/test-static-destruct.c']],
[['src/test/test-sigbus.c']], [['src/test/test-sigbus.c']],
@ -366,6 +370,8 @@ tests += [
[], [],
[threads]], [threads]],
[['src/test/test-hash-funcs.c']],
[['src/test/test-bitmap.c']], [['src/test/test-bitmap.c']],
[['src/test/test-xml.c']], [['src/test/test-xml.c']],

View File

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "blockdev-util.h"
#include "errno-util.h"
#include "tests.h"
static void test_path_is_encrypted_one(const char *p, int expect) {
int r;
r = path_is_encrypted(p);
if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* This might fail, if btrfs is used and we run in a
* container. In that case we cannot resolve the device node paths that
* BTRFS_IOC_DEV_INFO returns, because the device nodes are unlikely to exist in
* the container. But if we can't stat() them we cannot determine the dev_t of
* them, and thus cannot figure out if they are enrypted. Hence let's just ignore
* ENOENT here. Also skip the test if we lack privileges. */
return;
assert_se(r >= 0);
log_info("%s encrypted: %s", p, yes_no(r));
assert_se(expect < 0 || ((r > 0) == (expect > 0)));
}
static void test_path_is_encrypted(void) {
int booted = sd_booted(); /* If this is run in build environments such as koji, /dev might be a
* reguar fs. Don't assume too much if not running under systemd. */
log_info("/* %s (sd_booted=%d) */", __func__, booted);
test_path_is_encrypted_one("/home", -1);
test_path_is_encrypted_one("/var", -1);
test_path_is_encrypted_one("/", -1);
test_path_is_encrypted_one("/proc", false);
test_path_is_encrypted_one("/sys", false);
test_path_is_encrypted_one("/dev", booted > 0 ? false : -1);
}
int main(int argc, char **argv) {
test_setup_logging(LOG_INFO);
test_path_is_encrypted();
}

View File

@ -0,0 +1,154 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "data-fd-util.h"
#include "fd-util.h"
#include "memory-util.h"
#include "process-util.h"
#include "tests.h"
#include "random-util.h"
static void test_acquire_data_fd_one(unsigned flags) {
char wbuffer[196*1024 - 7];
char rbuffer[sizeof(wbuffer)];
int fd;
fd = acquire_data_fd("foo", 3, flags);
assert_se(fd >= 0);
zero(rbuffer);
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 3);
assert_se(streq(rbuffer, "foo"));
fd = safe_close(fd);
fd = acquire_data_fd("", 0, flags);
assert_se(fd >= 0);
zero(rbuffer);
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 0);
assert_se(streq(rbuffer, ""));
fd = safe_close(fd);
random_bytes(wbuffer, sizeof(wbuffer));
fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags);
assert_se(fd >= 0);
zero(rbuffer);
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == sizeof(rbuffer));
assert_se(memcmp(rbuffer, wbuffer, sizeof(rbuffer)) == 0);
fd = safe_close(fd);
}
static void test_acquire_data_fd(void) {
test_acquire_data_fd_one(0);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL);
test_acquire_data_fd_one(ACQUIRE_NO_MEMFD);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD);
test_acquire_data_fd_one(ACQUIRE_NO_PIPE);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_PIPE);
test_acquire_data_fd_one(ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE|ACQUIRE_NO_TMPFILE);
}
static void assert_equal_fd(int fd1, int fd2) {
for (;;) {
uint8_t a[4096], b[4096];
ssize_t x, y;
x = read(fd1, a, sizeof(a));
assert_se(x >= 0);
y = read(fd2, b, sizeof(b));
assert_se(y >= 0);
assert_se(x == y);
if (x == 0)
break;
assert_se(memcmp(a, b, x) == 0);
}
}
static void test_copy_data_fd(void) {
_cleanup_close_ int fd1 = -1, fd2 = -1;
_cleanup_(close_pairp) int sfd[2] = { -1, -1 };
_cleanup_(sigkill_waitp) pid_t pid = -1;
int r;
fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
if (fd1 >= 0) {
fd2 = copy_data_fd(fd1);
assert_se(fd2 >= 0);
assert_se(lseek(fd1, 0, SEEK_SET) == 0);
assert_equal_fd(fd1, fd2);
}
fd1 = safe_close(fd1);
fd2 = safe_close(fd2);
fd1 = acquire_data_fd("hallo", 6, 0);
assert_se(fd1 >= 0);
fd2 = copy_data_fd(fd1);
assert_se(fd2 >= 0);
safe_close(fd1);
fd1 = acquire_data_fd("hallo", 6, 0);
assert_se(fd1 >= 0);
assert_equal_fd(fd1, fd2);
fd1 = safe_close(fd1);
fd2 = safe_close(fd2);
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
/* child */
sfd[0] = safe_close(sfd[0]);
for (uint64_t i = 0; i < 1536*1024 / sizeof(uint64_t); i++)
assert_se(write(sfd[1], &i, sizeof(i)) == sizeof(i));
sfd[1] = safe_close(sfd[1]);
_exit(EXIT_SUCCESS);
}
sfd[1] = safe_close(sfd[1]);
fd2 = copy_data_fd(sfd[0]);
assert_se(fd2 >= 0);
uint64_t j;
for (uint64_t i = 0; i < 1536*1024 / sizeof(uint64_t); i++) {
assert_se(read(fd2, &j, sizeof(j)) == sizeof(j));
assert_se(i == j);
}
assert_se(read(fd2, &j, sizeof(j)) == 0);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_acquire_data_fd();
test_copy_data_fd();
return 0;
}

View File

@ -4,6 +4,7 @@
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "data-fd-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "macro.h" #include "macro.h"
@ -95,54 +96,6 @@ static void test_open_serialization_fd(void) {
assert_se(write(fd, "test\n", 5) == 5); assert_se(write(fd, "test\n", 5) == 5);
} }
static void test_acquire_data_fd_one(unsigned flags) {
char wbuffer[196*1024 - 7];
char rbuffer[sizeof(wbuffer)];
int fd;
fd = acquire_data_fd("foo", 3, flags);
assert_se(fd >= 0);
zero(rbuffer);
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 3);
assert_se(streq(rbuffer, "foo"));
fd = safe_close(fd);
fd = acquire_data_fd("", 0, flags);
assert_se(fd >= 0);
zero(rbuffer);
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 0);
assert_se(streq(rbuffer, ""));
fd = safe_close(fd);
random_bytes(wbuffer, sizeof(wbuffer));
fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags);
assert_se(fd >= 0);
zero(rbuffer);
assert_se(read(fd, rbuffer, sizeof(rbuffer)) == sizeof(rbuffer));
assert_se(memcmp(rbuffer, wbuffer, sizeof(rbuffer)) == 0);
fd = safe_close(fd);
}
static void test_acquire_data_fd(void) {
test_acquire_data_fd_one(0);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL);
test_acquire_data_fd_one(ACQUIRE_NO_MEMFD);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD);
test_acquire_data_fd_one(ACQUIRE_NO_PIPE);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_PIPE);
test_acquire_data_fd_one(ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE|ACQUIRE_NO_TMPFILE);
}
static void test_fd_move_above_stdio(void) { static void test_fd_move_above_stdio(void) {
int original_stdin, new_fd; int original_stdin, new_fd;
@ -227,93 +180,6 @@ static void test_rearrange_stdio(void) {
} }
} }
static void assert_equal_fd(int fd1, int fd2) {
for (;;) {
uint8_t a[4096], b[4096];
ssize_t x, y;
x = read(fd1, a, sizeof(a));
assert_se(x >= 0);
y = read(fd2, b, sizeof(b));
assert_se(y >= 0);
assert_se(x == y);
if (x == 0)
break;
assert_se(memcmp(a, b, x) == 0);
}
}
static void test_fd_duplicate_data_fd(void) {
_cleanup_close_ int fd1 = -1, fd2 = -1;
_cleanup_(close_pairp) int sfd[2] = { -1, -1 };
_cleanup_(sigkill_waitp) pid_t pid = -1;
uint64_t i, j;
int r;
fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
if (fd1 >= 0) {
fd2 = fd_duplicate_data_fd(fd1);
assert_se(fd2 >= 0);
assert_se(lseek(fd1, 0, SEEK_SET) == 0);
assert_equal_fd(fd1, fd2);
}
fd1 = safe_close(fd1);
fd2 = safe_close(fd2);
fd1 = acquire_data_fd("hallo", 6, 0);
assert_se(fd1 >= 0);
fd2 = fd_duplicate_data_fd(fd1);
assert_se(fd2 >= 0);
safe_close(fd1);
fd1 = acquire_data_fd("hallo", 6, 0);
assert_se(fd1 >= 0);
assert_equal_fd(fd1, fd2);
fd1 = safe_close(fd1);
fd2 = safe_close(fd2);
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
/* child */
sfd[0] = safe_close(sfd[0]);
for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++)
assert_se(write(sfd[1], &i, sizeof(i)) == sizeof(i));
sfd[1] = safe_close(sfd[1]);
_exit(EXIT_SUCCESS);
}
sfd[1] = safe_close(sfd[1]);
fd2 = fd_duplicate_data_fd(sfd[0]);
assert_se(fd2 >= 0);
for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++) {
assert_se(read(fd2, &j, sizeof(j)) == sizeof(j));
assert_se(i == j);
}
assert_se(read(fd2, &j, sizeof(j)) == 0);
}
static void test_read_nr_open(void) { static void test_read_nr_open(void) {
log_info("nr-open: %i", read_nr_open()); log_info("nr-open: %i", read_nr_open());
} }
@ -420,10 +286,8 @@ int main(int argc, char *argv[]) {
test_close_nointr(); test_close_nointr();
test_same_fd(); test_same_fd();
test_open_serialization_fd(); test_open_serialization_fd();
test_acquire_data_fd();
test_fd_move_above_stdio(); test_fd_move_above_stdio();
test_rearrange_stdio(); test_rearrange_stdio();
test_fd_duplicate_data_fd();
test_read_nr_open(); test_read_nr_open();
test_close_all_fds(); test_close_all_fds();

View File

@ -805,38 +805,6 @@ static void test_chmod_and_chown(void) {
assert_se(S_ISLNK(st.st_mode)); assert_se(S_ISLNK(st.st_mode));
} }
static void test_path_is_encrypted_one(const char *p, int expect) {
int r;
r = path_is_encrypted(p);
if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* This might fail, if btrfs is used and we run in a
* container. In that case we cannot resolve the device node paths that
* BTRFS_IOC_DEV_INFO returns, because the device nodes are unlikely to exist in
* the container. But if we can't stat() them we cannot determine the dev_t of
* them, and thus cannot figure out if they are enrypted. Hence let's just ignore
* ENOENT here. Also skip the test if we lack privileges. */
return;
assert_se(r >= 0);
log_info("%s encrypted: %s", p, yes_no(r));
assert_se(expect < 0 || ((r > 0) == (expect > 0)));
}
static void test_path_is_encrypted(void) {
int booted = sd_booted(); /* If this is run in build environments such as koji, /dev might be a
* reguar fs. Don't assume too much if not running under systemd. */
log_info("/* %s (sd_booted=%d) */", __func__, booted);
test_path_is_encrypted_one("/home", -1);
test_path_is_encrypted_one("/var", -1);
test_path_is_encrypted_one("/", -1);
test_path_is_encrypted_one("/proc", false);
test_path_is_encrypted_one("/sys", false);
test_path_is_encrypted_one("/dev", booted > 0 ? false : -1);
}
static void create_binary_file(const char *p, const void *data, size_t l) { static void create_binary_file(const char *p, const void *data, size_t l) {
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
@ -914,7 +882,6 @@ int main(int argc, char *argv[]) {
test_fsync_directory_of_file(); test_fsync_directory_of_file();
test_rename_noreplace(); test_rename_noreplace();
test_chmod_and_chown(); test_chmod_and_chown();
test_path_is_encrypted();
test_conservative_rename(); test_conservative_rename();
return 0; return 0;

View File

@ -0,0 +1,83 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "tests.h"
#include "hash-funcs.h"
#include "set.h"
static void test_path_hash_set(void) {
/* The goal is to make sure that non-simplified path are hashed as expected,
* and that we don't need to simplify them beforehand. */
log_info("/* %s */", __func__);
/* No freeing of keys, we operate on static strings here… */
_cleanup_set_free_ Set *set = NULL;
assert_se(set_isempty(set));
assert_se(set_ensure_put(&set, &path_hash_ops, "foo") == 1);
assert_se(set_ensure_put(&set, &path_hash_ops, "foo") == 0);
assert_se(set_ensure_put(&set, &path_hash_ops, "bar") == 1);
assert_se(set_ensure_put(&set, &path_hash_ops, "bar") == 0);
assert_se(set_ensure_put(&set, &path_hash_ops, "/foo") == 1);
assert_se(set_ensure_put(&set, &path_hash_ops, "/bar") == 1);
assert_se(set_ensure_put(&set, &path_hash_ops, "/foo/.") == 0);
assert_se(set_ensure_put(&set, &path_hash_ops, "/./bar/./.") == 0);
assert_se(set_contains(set, "foo"));
assert_se(set_contains(set, "bar"));
assert_se(set_contains(set, "./foo"));
assert_se(set_contains(set, "./foo/."));
assert_se(set_contains(set, "./bar"));
assert_se(set_contains(set, "./bar/."));
assert_se(set_contains(set, "/foo"));
assert_se(set_contains(set, "/bar"));
assert_se(set_contains(set, "//./foo"));
assert_se(set_contains(set, "///./foo/."));
assert_se(set_contains(set, "////./bar"));
assert_se(set_contains(set, "/////./bar/."));
assert_se(set_contains(set, "foo/"));
assert_se(set_contains(set, "bar/"));
assert_se(set_contains(set, "./foo/"));
assert_se(set_contains(set, "./foo/./"));
assert_se(set_contains(set, "./bar/"));
assert_se(set_contains(set, "./bar/./"));
assert_se(set_contains(set, "/foo/"));
assert_se(set_contains(set, "/bar/"));
assert_se(set_contains(set, "//./foo/"));
assert_se(set_contains(set, "///./foo/./"));
assert_se(set_contains(set, "////./bar/"));
assert_se(set_contains(set, "/////./bar/./"));
assert_se(!set_contains(set, "foo."));
assert_se(!set_contains(set, ".bar"));
assert_se(!set_contains(set, "./foo."));
assert_se(!set_contains(set, "./.foo/."));
assert_se(!set_contains(set, "../bar"));
assert_se(!set_contains(set, "./bar/.."));
assert_se(!set_contains(set, "./foo.."));
assert_se(!set_contains(set, "/..bar"));
assert_se(!set_contains(set, "//../foo"));
assert_se(!set_contains(set, "///../foo/."));
assert_se(!set_contains(set, "////../bar"));
assert_se(!set_contains(set, "/////../bar/."));
assert_se(!set_contains(set, "foo./"));
assert_se(!set_contains(set, ".bar/"));
assert_se(!set_contains(set, "./foo./"));
assert_se(!set_contains(set, "./.foo/./"));
assert_se(!set_contains(set, "../bar/"));
assert_se(!set_contains(set, "./bar/../"));
assert_se(!set_contains(set, "./foo../"));
assert_se(!set_contains(set, "/..bar/"));
assert_se(!set_contains(set, "//../foo/"));
assert_se(!set_contains(set, "///../foo/./"));
assert_se(!set_contains(set, "////../bar/"));
assert_se(!set_contains(set, "/////../bar/./"));
}
int main(int argc, char **argv) {
test_setup_logging(LOG_INFO);
test_path_hash_set();
}

View File

@ -7,7 +7,9 @@
#include "capability-util.h" #include "capability-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h"
#include "missing_mount.h" #include "missing_mount.h"
#include "mkdir.h"
#include "mount-util.h" #include "mount-util.h"
#include "namespace-util.h" #include "namespace-util.h"
#include "path-util.h" #include "path-util.h"
@ -217,6 +219,52 @@ static void test_bind_remount_one(void) {
assert_se(wait_for_terminate_and_check("test-remount-one", pid, WAIT_LOG) == EXIT_SUCCESS); assert_se(wait_for_terminate_and_check("test-remount-one", pid, WAIT_LOG) == EXIT_SUCCESS);
} }
static void test_make_mount_point_inode(void) {
_cleanup_(rm_rf_physical_and_freep) char *d = NULL;
const char *src_file, *src_dir, *dst_file, *dst_dir;
struct stat st;
log_info("/* %s */", __func__);
assert_se(mkdtemp_malloc(NULL, &d) >= 0);
src_file = strjoina(d, "/src/file");
src_dir = strjoina(d, "/src/dir");
dst_file = strjoina(d, "/dst/file");
dst_dir = strjoina(d, "/dst/dir");
assert_se(mkdir_p(src_dir, 0755) >= 0);
assert_se(mkdir_parents(dst_file, 0755) >= 0);
assert_se(touch(src_file) >= 0);
assert_se(make_mount_point_inode_from_path(src_file, dst_file, 0755) >= 0);
assert_se(make_mount_point_inode_from_path(src_dir, dst_dir, 0755) >= 0);
assert_se(stat(dst_dir, &st) == 0);
assert_se(S_ISDIR(st.st_mode));
assert_se(stat(dst_file, &st) == 0);
assert_se(S_ISREG(st.st_mode));
assert_se(!(S_IXUSR & st.st_mode));
assert_se(!(S_IXGRP & st.st_mode));
assert_se(!(S_IXOTH & st.st_mode));
assert_se(unlink(dst_file) == 0);
assert_se(rmdir(dst_dir) == 0);
assert_se(stat(src_file, &st) == 0);
assert_se(make_mount_point_inode_from_stat(&st, dst_file, 0755) >= 0);
assert_se(stat(src_dir, &st) == 0);
assert_se(make_mount_point_inode_from_stat(&st, dst_dir, 0755) >= 0);
assert_se(stat(dst_dir, &st) == 0);
assert_se(S_ISDIR(st.st_mode));
assert_se(stat(dst_file, &st) == 0);
assert_se(S_ISREG(st.st_mode));
assert_se(!(S_IXUSR & st.st_mode));
assert_se(!(S_IXGRP & st.st_mode));
assert_se(!(S_IXOTH & st.st_mode));
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG); test_setup_logging(LOG_DEBUG);
@ -224,6 +272,7 @@ int main(int argc, char *argv[]) {
test_mount_flags_to_string(); test_mount_flags_to_string();
test_bind_remount_recursive(); test_bind_remount_recursive();
test_bind_remount_one(); test_bind_remount_one();
test_make_mount_point_inode();
return 0; return 0;
} }

View File

@ -8,10 +8,8 @@
#include "def.h" #include "def.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h"
#include "hashmap.h" #include "hashmap.h"
#include "log.h" #include "log.h"
#include "mkdir.h"
#include "mountpoint-util.h" #include "mountpoint-util.h"
#include "path-util.h" #include "path-util.h"
#include "rm-rf.h" #include "rm-rf.h"
@ -290,52 +288,6 @@ static void test_fd_is_mount_point(void) {
assert_se(IN_SET(fd_is_mount_point(fd, "root/", 0), -ENOENT, 0)); assert_se(IN_SET(fd_is_mount_point(fd, "root/", 0), -ENOENT, 0));
} }
static void test_make_mount_point_inode(void) {
_cleanup_(rm_rf_physical_and_freep) char *d = NULL;
const char *src_file, *src_dir, *dst_file, *dst_dir;
struct stat st;
log_info("/* %s */", __func__);
assert_se(mkdtemp_malloc(NULL, &d) >= 0);
src_file = strjoina(d, "/src/file");
src_dir = strjoina(d, "/src/dir");
dst_file = strjoina(d, "/dst/file");
dst_dir = strjoina(d, "/dst/dir");
assert_se(mkdir_p(src_dir, 0755) >= 0);
assert_se(mkdir_parents(dst_file, 0755) >= 0);
assert_se(touch(src_file) >= 0);
assert_se(make_mount_point_inode_from_path(src_file, dst_file, 0755) >= 0);
assert_se(make_mount_point_inode_from_path(src_dir, dst_dir, 0755) >= 0);
assert_se(stat(dst_dir, &st) == 0);
assert_se(S_ISDIR(st.st_mode));
assert_se(stat(dst_file, &st) == 0);
assert_se(S_ISREG(st.st_mode));
assert_se(!(S_IXUSR & st.st_mode));
assert_se(!(S_IXGRP & st.st_mode));
assert_se(!(S_IXOTH & st.st_mode));
assert_se(unlink(dst_file) == 0);
assert_se(rmdir(dst_dir) == 0);
assert_se(stat(src_file, &st) == 0);
assert_se(make_mount_point_inode_from_stat(&st, dst_file, 0755) >= 0);
assert_se(stat(src_dir, &st) == 0);
assert_se(make_mount_point_inode_from_stat(&st, dst_dir, 0755) >= 0);
assert_se(stat(dst_dir, &st) == 0);
assert_se(S_ISDIR(st.st_mode));
assert_se(stat(dst_file, &st) == 0);
assert_se(S_ISREG(st.st_mode));
assert_se(!(S_IXUSR & st.st_mode));
assert_se(!(S_IXGRP & st.st_mode));
assert_se(!(S_IXOTH & st.st_mode));
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG); test_setup_logging(LOG_DEBUG);
@ -360,7 +312,6 @@ int main(int argc, char *argv[]) {
test_mnt_id(); test_mnt_id();
test_path_is_mount_point(); test_path_is_mount_point();
test_fd_is_mount_point(); test_fd_is_mount_point();
test_make_mount_point_inode();
return 0; return 0;
} }

View File

@ -126,6 +126,8 @@ static void test_path_compare_one(const char *a, const char *b, int expected) {
} }
static void test_path_compare(void) { static void test_path_compare(void) {
log_info("/* %s */", __func__);
test_path_compare_one("/goo", "/goo", 0); test_path_compare_one("/goo", "/goo", 0);
test_path_compare_one("/goo", "/goo", 0); test_path_compare_one("/goo", "/goo", 0);
test_path_compare_one("//goo", "/goo", 0); test_path_compare_one("//goo", "/goo", 0);
@ -138,6 +140,12 @@ static void test_path_compare(void) {
test_path_compare_one("/x", "x/", 1); test_path_compare_one("/x", "x/", 1);
test_path_compare_one("x/", "/", -1); test_path_compare_one("x/", "/", -1);
test_path_compare_one("/x/./y", "x/y", 1); test_path_compare_one("/x/./y", "x/y", 1);
test_path_compare_one("/x/./y", "/x/y", 0);
test_path_compare_one("/x/./././y", "/x/y/././.", 0);
test_path_compare_one("./x/./././y", "./x/y/././.", 0);
test_path_compare_one(".", "./.", 0);
test_path_compare_one(".", "././.", 0);
test_path_compare_one("./..", ".", 1);
test_path_compare_one("x/.y", "x/y", -1); test_path_compare_one("x/.y", "x/y", -1);
test_path_compare_one("foo", "/foo", -1); test_path_compare_one("foo", "/foo", -1);
test_path_compare_one("/foo", "/foo/bar", -1); test_path_compare_one("/foo", "/foo/bar", -1);

View File

@ -126,8 +126,6 @@ static void test_get_process_cmdline(void) {
FOREACH_DIRENT(de, d, return) { FOREACH_DIRENT(de, d, return) {
pid_t pid; pid_t pid;
dirent_ensure_type(d, de);
if (de->d_type != DT_DIR) if (de->d_type != DT_DIR)
continue; continue;

View File

@ -12,7 +12,6 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
@ -21,6 +20,7 @@
#include "extract-word.h" #include "extract-word.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "parse-util.h"
#include "scsi_id.h" #include "scsi_id.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
@ -58,12 +58,10 @@ static char revision_str[16];
static char type_str[16]; static char type_str[16];
static void set_type(const char *from, char *to, size_t len) { static void set_type(const char *from, char *to, size_t len) {
int type_num; unsigned type_num;
char *eptr;
const char *type = "generic"; const char *type = "generic";
type_num = strtoul(from, &eptr, 0); if (safe_atou_full(from, 16, &type_num) >= 0) {
if (eptr != from) {
switch (type_num) { switch (type_num) {
case 0: case 0:
type = "disk"; type = "disk";

View File

@ -9,7 +9,6 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <linux/limits.h> #include <linux/limits.h>
@ -83,6 +82,7 @@ static void get_cap_mask(sd_device *pdev, const char* attr,
unsigned i; unsigned i;
char* word; char* word;
unsigned long val; unsigned long val;
int r;
if (sd_device_get_sysattr_value(pdev, attr, &v) < 0) if (sd_device_get_sysattr_value(pdev, attr, &v) < 0)
v = ""; v = "";
@ -93,16 +93,20 @@ static void get_cap_mask(sd_device *pdev, const char* attr,
memzero(bitmask, bitmask_size); memzero(bitmask, bitmask_size);
i = 0; i = 0;
while ((word = strrchr(text, ' ')) != NULL) { while ((word = strrchr(text, ' ')) != NULL) {
val = strtoul(word+1, NULL, 16); r = safe_atolu_full(word+1, 16, &val);
if (i < bitmask_size / sizeof(unsigned long)) if (r < 0)
log_device_debug_errno(pdev, r, "Ignoring %s block which failed to parse: %m", attr);
else if (i < bitmask_size / sizeof(unsigned long))
bitmask[i] = val; bitmask[i] = val;
else else
log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val); log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val);
*word = '\0'; *word = '\0';
++i; ++i;
} }
val = strtoul (text, NULL, 16); r = safe_atolu_full(text, 16, &val);
if (i < bitmask_size / sizeof(unsigned long)) if (r < 0)
log_device_debug_errno(pdev, r, "Ignoring %s block which failed to parse: %m", attr);
else if (i < bitmask_size / sizeof(unsigned long))
bitmask[i] = val; bitmask[i] = val;
else else
log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val); log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val);

View File

@ -60,19 +60,19 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode
unsigned scan; unsigned scan;
unsigned key; unsigned key;
} map; } map;
char *endptr;
const struct key_name *k; const struct key_name *k;
unsigned keycode_num; unsigned keycode_num;
int r;
/* translate identifier to key code */ /* translate identifier to key code */
k = keyboard_lookup_key(keycode, strlen(keycode)); k = keyboard_lookup_key(keycode, strlen(keycode));
if (k) { if (k)
keycode_num = k->id; keycode_num = k->id;
} else { else {
/* check if it's a numeric code already */ /* check if it's a numeric code already */
keycode_num = strtoul(keycode, &endptr, 0); r = safe_atou(keycode, &keycode_num);
if (endptr[0] !='\0') if (r < 0)
return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse key identifier '%s'", keycode); return log_device_error_errno(dev, r, "Failed to parse key identifier '%s': %m", keycode);
} }
map.scan = scancode; map.scan = scancode;
@ -170,17 +170,15 @@ static int builtin_keyboard(sd_device *dev, int argc, char *argv[], bool test) {
if (r < 0) if (r < 0)
return log_device_error_errno(dev, r, "Failed to get device name: %m"); return log_device_error_errno(dev, r, "Failed to get device name: %m");
FOREACH_DEVICE_PROPERTY(dev, key, value) { FOREACH_DEVICE_PROPERTY(dev, key, value)
char *endptr;
if (startswith(key, "KEYBOARD_KEY_")) { if (startswith(key, "KEYBOARD_KEY_")) {
const char *keycode = value; const char *keycode = value;
unsigned scancode; unsigned scancode;
/* KEYBOARD_KEY_<hex scan code>=<key identifier string> */ /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
scancode = strtoul(key + 13, &endptr, 16); r = safe_atou_full(key + 13, 16, &scancode);
if (endptr[0] != '\0') { if (r < 0) {
log_device_warning(dev, "Failed to parse scan code from \"%s\", ignoring", key); log_device_warning_errno(dev, r, "Failed to parse scan code from \"%s\", ignoring: %m", key);
continue; continue;
} }
@ -207,9 +205,9 @@ static int builtin_keyboard(sd_device *dev, int argc, char *argv[], bool test) {
unsigned evcode; unsigned evcode;
/* EVDEV_ABS_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */ /* EVDEV_ABS_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */
evcode = strtoul(key + 10, &endptr, 16); r = safe_atou_full(key + 10, 16, &evcode);
if (endptr[0] != '\0') { if (r < 0) {
log_device_warning(dev, "Failed to parse EV_ABS code from \"%s\", ignoring", key); log_device_warning_errno(dev, r, "Failed to parse EV_ABS code from \"%s\", ignoring: %m", key);
continue; continue;
} }
@ -238,7 +236,6 @@ static int builtin_keyboard(sd_device *dev, int argc, char *argv[], bool test) {
(void) override_abs(dev, fd, evcode, value); (void) override_abs(dev, fd, evcode, value);
} else if (streq(key, "POINTINGSTICK_SENSITIVITY")) } else if (streq(key, "POINTINGSTICK_SENSITIVITY"))
(void) set_trackpoint_sensitivity(dev, value); (void) set_trackpoint_sensitivity(dev, value);
}
/* install list of force-release codes */ /* install list of force-release codes */
if (release_count > 0) if (release_count > 0)

View File

@ -17,7 +17,6 @@
#include <net/if.h> #include <net/if.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/pci_regs.h> #include <linux/pci_regs.h>
@ -199,8 +198,11 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
return -ENOENT; return -ENOENT;
/* kernel provided port index for multiple ports on a single PCI function */ /* kernel provided port index for multiple ports on a single PCI function */
if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
dev_port = strtoul(attr, NULL, 10); r = safe_atolu_full(attr, 10, &dev_port);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to parse dev_port, ignoring: %m");
}
/* kernel provided front panel port name for multiple port PCI device */ /* kernel provided front panel port name for multiple port PCI device */
(void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name); (void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
@ -341,7 +343,9 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
/* kernel provided port index for multiple ports on a single PCI function */ /* kernel provided port index for multiple ports on a single PCI function */
if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) { if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) {
dev_port = strtoul(attr, NULL, 10); r = safe_atolu_full(attr, 10, &dev_port);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to parse attribute dev_port, ignoring: %m");
/* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously /* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously
* provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port', * provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port',
* which thus stays initialized as 0. */ * which thus stays initialized as 0. */
@ -349,10 +353,15 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) {
sd_device_get_sysattr_value(dev, "type", &attr) >= 0) { sd_device_get_sysattr_value(dev, "type", &attr) >= 0) {
unsigned long type; unsigned long type;
type = strtoul(attr, NULL, 10); r = safe_atolu_full(attr, 10, &type);
if (type == ARPHRD_INFINIBAND && if (r < 0)
sd_device_get_sysattr_value(dev, "dev_id", &attr) >= 0) log_device_debug_errno(dev, r, "Failed to parse attribute type, ignoring: %m");
dev_port = strtoul(attr, NULL, 16); else if (type == ARPHRD_INFINIBAND &&
sd_device_get_sysattr_value(dev, "dev_id", &attr) >= 0) {
r = safe_atolu_full(attr, 10, &dev_port);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to parse attribute dev_id, ignoring: %m");
}
} }
} }
@ -765,7 +774,9 @@ static int names_mac(sd_device *dev, struct netnames *names) {
if (r < 0) if (r < 0)
return r; return r;
i = strtoul(s, NULL, 0); r = safe_atolu_full(s, 10, &i);
if (r < 0)
return r;
switch (i) { switch (i) {
/* The persistent part of a hardware address of an InfiniBand NIC /* The persistent part of a hardware address of an InfiniBand NIC
* is 8 bytes long. We cannot fit this much in an iface name. * is 8 bytes long. We cannot fit this much in an iface name.
@ -780,7 +791,9 @@ static int names_mac(sd_device *dev, struct netnames *names) {
r = sd_device_get_sysattr_value(dev, "addr_assign_type", &s); r = sd_device_get_sysattr_value(dev, "addr_assign_type", &s);
if (r < 0) if (r < 0)
return r; return r;
i = strtoul(s, NULL, 0); r = safe_atolu(s, &i);
if (r < 0)
return r;
if (i != 0) if (i != 0)
return 0; return 0;
@ -868,7 +881,9 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
if (r < 0) if (r < 0)
return r; return r;
i = strtoul(s, NULL, 0); r = safe_atolu_full(s, 10, &i);
if (r < 0)
return r;
switch (i) { switch (i) {
case ARPHRD_ETHER: case ARPHRD_ETHER:
prefix = "en"; prefix = "en";

View File

@ -11,12 +11,12 @@
#include <getopt.h> #include <getopt.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "dirent-util.h" #include "dirent-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "parse-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "sysexits.h" #include "sysexits.h"
@ -66,7 +66,9 @@ static int format_lun_number(sd_device *dev, char **path) {
if (!sysnum) if (!sysnum)
return -ENOENT; return -ENOENT;
lun = strtoul(sysnum, NULL, 10); r = safe_atolu_full(sysnum, 10, &lun);
if (r < 0)
return r;
if (lun < 256) if (lun < 256)
/* address method 0, peripheral device addressing with bus id of zero */ /* address method 0, peripheral device addressing with bus id of zero */
path_prepend(path, "lun-%lu", lun); path_prepend(path, "lun-%lu", lun);
@ -344,8 +346,7 @@ static sd_device *handle_scsi_default(sd_device *parent, char **path) {
return NULL; return NULL;
FOREACH_DIRENT_ALL(dent, dir, break) { FOREACH_DIRENT_ALL(dent, dir, break) {
char *rest; unsigned i;
int i;
if (dent->d_name[0] == '.') if (dent->d_name[0] == '.')
continue; continue;
@ -353,15 +354,14 @@ static sd_device *handle_scsi_default(sd_device *parent, char **path) {
continue; continue;
if (!startswith(dent->d_name, "host")) if (!startswith(dent->d_name, "host"))
continue; continue;
i = strtoul(&dent->d_name[4], &rest, 10); if (safe_atou_full(&dent->d_name[4], 10, &i) < 0)
if (rest[0] != '\0')
continue; continue;
/* /*
* find the smallest number; the host really needs to export its * find the smallest number; the host really needs to export its
* own instance number per parent device; relying on the global host * own instance number per parent device; relying on the global host
* enumeration and plainly rebasing the numbers sounds unreliable * enumeration and plainly rebasing the numbers sounds unreliable
*/ */
if (basenum == -1 || i < basenum) if (basenum == -1 || (int) i < basenum)
basenum = i; basenum = i;
} }
if (basenum == -1) if (basenum == -1)

View File

@ -11,13 +11,13 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "device-nodes.h" #include "device-nodes.h"
#include "device-util.h" #include "device-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "parse-util.h"
#include "string-util.h" #include "string-util.h"
#include "strxcpyx.h" #include "strxcpyx.h"
#include "udev-builtin.h" #include "udev-builtin.h"
@ -75,11 +75,9 @@ static void set_usb_iftype(char *to, int if_class_num, size_t len) {
static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) { static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) {
int type_num = 0; int type_num = 0;
char *eptr;
const char *type = "generic"; const char *type = "generic";
type_num = strtoul(from, &eptr, 0); if (safe_atoi(from, &type_num) >= 0) {
if (eptr != from) {
switch (type_num) { switch (type_num) {
case 1: /* RBC devices */ case 1: /* RBC devices */
type = "rbc"; type = "rbc";
@ -105,12 +103,10 @@ static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len
} }
static void set_scsi_type(char *to, const char *from, size_t len) { static void set_scsi_type(char *to, const char *from, size_t len) {
int type_num; unsigned type_num;
char *eptr;
const char *type = "generic"; const char *type = "generic";
type_num = strtoul(from, &eptr, 0); if (safe_atou(from, &type_num) >= 0) {
if (eptr != from) {
switch (type_num) { switch (type_num) {
case 0: case 0:
case 0xe: case 0xe:
@ -246,7 +242,7 @@ static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) {
sd_device *dev_interface, *dev_usb; sd_device *dev_interface, *dev_usb;
const char *if_class, *if_subclass; const char *if_class, *if_subclass;
int if_class_num; unsigned if_class_num;
int protocol = 0; int protocol = 0;
size_t l; size_t l;
char *s; char *s;
@ -286,7 +282,9 @@ static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) {
if (r < 0) if (r < 0)
return log_device_debug_errno(dev_interface, r, "Failed to get bInterfaceClass attribute: %m"); return log_device_debug_errno(dev_interface, r, "Failed to get bInterfaceClass attribute: %m");
if_class_num = strtoul(if_class, NULL, 16); r = safe_atou_full(if_class, 16, &if_class_num);
if (r < 0)
return log_device_debug_errno(dev_interface, r, "Failed to parse if_class: %m");
if (if_class_num == 8) { if (if_class_num == 8) {
/* mass storage */ /* mass storage */
if (sd_device_get_sysattr_value(dev_interface, "bInterfaceSubClass", &if_subclass) >= 0) if (sd_device_get_sysattr_value(dev_interface, "bInterfaceSubClass", &if_subclass) >= 0)

View File

@ -9,18 +9,6 @@ TEST_REQUIRE_INSTALL_TESTS=0
# shellcheck source=test/test-functions # shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions" . "${TEST_BASE_DIR:?}/test-functions"
# Explicitly override the default test_create_image() function to avoid the
# call to mask_supporting_services(), since we want to run them in TEST-01-BASIC
test_create_image() {
create_empty_image_rootdir
# Create what will eventually be our root filesystem onto an overlay
(
LOG_LEVEL=5
setup_basic_environment
)
}
test_append_files() { test_append_files() {
# install tests manually so the test is functional even when -Dinstall-tests=false # install tests manually so the test is functional even when -Dinstall-tests=false
local dst="${1:?}/usr/lib/systemd/tests/testdata/units/" local dst="${1:?}/usr/lib/systemd/tests/testdata/units/"

View File

@ -2416,7 +2416,6 @@ test_create_image() {
( (
LOG_LEVEL=5 LOG_LEVEL=5
setup_basic_environment setup_basic_environment
mask_supporting_services
) )
} }
@ -2467,6 +2466,13 @@ test_setup() {
fi fi
mount_initdir mount_initdir
# We want to test all services in TEST-01-BASIC, but mask them in
# all other tests
if [[ "${TESTID:?}" != "01" ]]; then
dinfo "Masking supporting services"
mask_supporting_services
fi
if [ "$hook_defined" -eq 0 ]; then if [ "$hook_defined" -eq 0 ]; then
test_append_files "${initdir:?}" test_append_files "${initdir:?}"
fi fi