1
0
mirror of https://github.com/systemd/systemd synced 2026-03-14 09:04:47 +01:00

Compare commits

...

24 Commits

Author SHA1 Message Date
Yu Watanabe
503a788332
Introduce name_to_handle_at_u64() helper function and use it for getting pidfd ID and cgroup ID (#40500) 2026-02-04 04:37:07 +09:00
Yu Watanabe
06432cca43
Portabled capsule fixes (#40427) 2026-02-04 02:53:16 +09:00
Yu Watanabe
ede1caeada cgroup-util: declare file_handle union in cg_cgroupid_open()
This also effectively reverts eb2e91b9815bcbc59997c1092d7b52fc18930bff,
as now the object is only used as input, and kernel would need to handle
input with only ID no matter whether the struct later gets extended.
2026-02-04 02:45:17 +09:00
Yu Watanabe
f37931bd78 tree-wide: replace cg_{fd,path}_get_cgroupid() with {fd,path}_to_handle_u64() 2026-02-04 02:45:17 +09:00
Yu Watanabe
2eab8fa1e4 pidfd-util: use fd_to_handle_u64() 2026-02-04 02:45:17 +09:00
Yu Watanabe
e7ce1e22b9 mountpoint-util: introduce name_to_handle_at_u64() and friends
They will be used later.
2026-02-04 02:45:06 +09:00
Yu Watanabe
09811ccaa1 mountpoint-util: make name_to_handle_at_loop() gracefully handle NULL path 2026-02-04 00:07:02 +09:00
Yu Watanabe
055ceec666
journal: avoid strjoina()/newa() (#40489)
Fixes #40456.
2026-02-03 23:42:23 +09:00
Yu Watanabe
f2a54dac72
vmspawn/firstboot/homectl: fixes for plymouth (#40558) 2026-02-03 23:38:38 +09:00
Yu Watanabe
50ddcf8554
udev: create /run/udev/queue file earlier (#40518)
When udevd received a uevent or inotify event, then we will queue
events. To minimize the race between processing these events by udevd
and user invocation of 'udevadm settle', let's create /run/udev/queue
file earlier.
On some errors, no event may be queued, but in that case, the file will
be removed by the post event source if nothing queued. See on_post().

Hopefully mitigate the issue #40499.
2026-02-03 23:36:28 +09:00
Daan De Meyer
ae6dcaff0d portable: Don't refuse copying out instance of template that exists
There's no reason to refuse copying out capsule@abc.service even if
capsule@.service already exists on the host, so let's optionally not
search for templates if we can't find an instance when looking up
units and use it in portabled.
2026-02-03 15:03:51 +01:00
Daan De Meyer
4d388536ee tree-wide: Allow running capsules as any user
For many use cases DynamicUser= just doesn't cut it. Specifically lots
of stuff wants to run as root. Let's support this use case by relaxing
our checks for capsules a bit.
2026-02-03 15:00:32 +01:00
Daan De Meyer
b231c4dcb4 core: Improve logging when we cannot create destination mountpoint
If we fail to create a parent directory, then the error from
make_mount_point_inode_from_path() will always be
"No such file or directory" which doesn't tell us anything. Add logging
for the mkdir_parents() call as well so we get a useful error.
2026-02-03 15:00:32 +01:00
Yu Watanabe
eb5b797d7c journal: check validity of PID field in syslog/kmsg earlier
Then, let's make syslog_parse_identifier() returns PID as pid_t, rather
than the string.

This also makes the function refuse ridiculously long identifier.

Fixes #40456.
Fixes oss-fuzz#477990732 (https://issues.oss-fuzz.com/issues/477990732).
2026-02-03 21:55:49 +09:00
Yu Watanabe
dd839b1463 parse-util: rename trivial argument for parse_pid()
The function parse_pid() trivially returns pid, hence it is not
necessary to name the argument for storing result as 'ret_pid'.
2026-02-03 21:43:17 +09:00
Yu Watanabe
7e81423fb8 journal: check the length of timestamp field in syslog message
No functional change. Just refactoring and adding assertion.
2026-02-03 21:43:17 +09:00
Yu Watanabe
8d607f93b7 journal: make security label always NUL-terminated
Then, we can drop label_len or label_size arguments at various places.

While doing this, SCM_SECURITY is now ignored when SELinux is disabled
or when it contains embedded NUL.
2026-02-03 21:43:17 +09:00
Yu Watanabe
0dcbb30f49 fuzz: assume all reproducers as binary
Even if parsers expect text data, reproducers may not be suitable
for being handled as a text file.
2026-02-03 21:43:17 +09:00
Yu Watanabe
dc709eff0b udev: create /run/udev/queue file earlier
When udevd received a uevent or inotify event, we will queue or trigger
synthesized events. To minimize the race between processing these events
by udevd and user invocation of 'udevadm settle', let's create /run/udev/queue
file earlier.
On some errors, no event may be queued, but in that case, the file will
be removed by the post event source if nothing queued. See on_post().

Hopefully mitigate the issue #40499.
2026-02-03 21:25:01 +09:00
Yu Watanabe
b7363d3330 udev: remember UUIDs of triggered events
Otherwise, /run/udev/queue file may be removed before udevd receives
the triggered uevents. This avoids the following race:

1. uevent A is being processed,
2. received an inotify event and trigger a synthesized uevent,
3. uevent A has been processed,
4. the uevent queue becomes empty, and /run/udev/queue is removed,
5. received and queued the synthesized uevent, and /run/udev/queue is recreated.

With this patch, /run/udev/queue is not removed in step 4. Hence,
'udevadm settle' will wait for the synthesized event being processed.

This is similar to waiting for child processes that reread partitions
(thus trigger synthetic events) being terminated, but for synthetic
events triggered by the manager.
2026-02-03 21:25:01 +09:00
Yu Watanabe
95b40e4cf3 udev/watch: drop redundant argument
The arguments dev and target are always same.
2026-02-03 21:25:01 +09:00
Luca Boccassi
75cb25c0b9 firstboot/homectl: hide plymouth splashscreen when asking questions
When plymouth is enabled, the screen gets all garbled when firstboot
runs and asks questions. Disable the splash screen, but only when
actually asking questions.
2026-02-03 13:21:03 +01:00
Luca Boccassi
7f7622285d homectl: trim some trailing whitespace 2026-02-03 12:47:12 +01:00
Luca Boccassi
610d8c3dfc vmspawn: do not pass console=hvc0 in GUI mode
This breaks when using qemu's GUI mode. Follow mkosi's example.

Follow-up for 773ca1def8f79a8509bf0846de9d75902ca31f79
2026-02-03 10:50:34 +01:00
41 changed files with 339 additions and 264 deletions

View File

@ -35,21 +35,6 @@
#include "user-util.h"
#include "xattr-util.h"
/* The structure to pass to name_to_handle_at() on cgroupfs2 */
typedef union {
struct file_handle file_handle;
uint8_t space[MAX_HANDLE_SZ];
} cg_file_handle;
#define CG_FILE_HANDLE_INIT \
(cg_file_handle) { \
.file_handle.handle_bytes = sizeof(uint64_t), \
.file_handle.handle_type = FILEID_KERNFS, \
}
/* The .f_handle field is not aligned to 64bit on some archs, hence read it via an unaligned accessor */
#define CG_FILE_HANDLE_CGROUPID(fh) unaligned_read_ne64(fh.file_handle.f_handle)
int cg_is_available(void) {
struct statfs fs;
@ -85,7 +70,14 @@ int cg_cgroupid_open(int cgroupfs_fd, uint64_t id) {
cgroupfs_fd = fsfd;
}
cg_file_handle fh = CG_FILE_HANDLE_INIT;
union {
struct file_handle file_handle;
uint8_t space[offsetof(struct file_handle, f_handle) + sizeof(uint64_t)];
} fh = {
.file_handle.handle_bytes = sizeof(uint64_t),
.file_handle.handle_type = FILEID_KERNFS,
};
unaligned_write_ne64(fh.file_handle.f_handle, id);
return RET_NERRNO(open_by_handle_at(cgroupfs_fd, &fh.file_handle, O_DIRECTORY|O_CLOEXEC));
@ -112,24 +104,6 @@ int cg_path_from_cgroupid(int cgroupfs_fd, uint64_t id, char **ret) {
return 0;
}
int cg_get_cgroupid_at(int dfd, const char *path, uint64_t *ret) {
cg_file_handle fh = CG_FILE_HANDLE_INIT;
int mnt_id;
assert(dfd >= 0 || (dfd == AT_FDCWD && path_is_absolute(path)));
assert(ret);
/* This is cgroupfs so we know the size of the handle, thus no need to loop around like
* name_to_handle_at_loop() does in mountpoint-util.c */
if (name_to_handle_at(dfd, strempty(path), &fh.file_handle, &mnt_id, isempty(path) ? AT_EMPTY_PATH : 0) < 0) {
assert(errno != EOVERFLOW);
return -errno;
}
*ret = CG_FILE_HANDLE_CGROUPID(fh);
return 0;
}
int cg_enumerate_processes(const char *path, FILE **ret) {
_cleanup_free_ char *fs = NULL;
FILE *f;

View File

@ -125,13 +125,6 @@ int cg_path_open(const char *path);
int cg_cgroupid_open(int cgroupfs_fd, uint64_t id);
int cg_path_from_cgroupid(int cgroupfs_fd, uint64_t id, char **ret);
int cg_get_cgroupid_at(int dfd, const char *path, uint64_t *ret);
static inline int cg_path_get_cgroupid(const char *path, uint64_t *ret) {
return cg_get_cgroupid_at(AT_FDCWD, path, ret);
}
static inline int cg_fd_get_cgroupid(int fd, uint64_t *ret) {
return cg_get_cgroupid_at(fd, NULL, ret);
}
typedef enum CGroupFlags {
CGROUP_SIGCONT = 1 << 0,

View File

@ -17,6 +17,7 @@
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "unaligned.h"
/* This is the original MAX_HANDLE_SZ definition from the kernel, when the API was introduced. We use that in place of
* any more currently defined value to future-proof things: if the size is increased in the API headers, and our code
@ -63,6 +64,11 @@ int name_to_handle_at_loop(
* This improves on raw name_to_handle_at() also in one other regard: ret_handle and ret_mnt_id can be passed
* as NULL if there's no interest in either. */
if (isempty(path)) {
flags |= AT_EMPTY_PATH;
path = "";
}
for (;;) {
_cleanup_free_ struct file_handle *h = NULL;
int mnt_id = -1;
@ -73,7 +79,7 @@ int name_to_handle_at_loop(
h->handle_bytes = n;
if (name_to_handle_at(fd, strempty(path), h, &mnt_id, flags) >= 0) {
if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) {
if (ret_handle)
*ret_handle = TAKE_PTR(h);
@ -133,6 +139,27 @@ int name_to_handle_at_try_fid(
return name_to_handle_at_loop(fd, path, ret_handle, ret_mnt_id, flags & ~AT_HANDLE_FID);
}
int name_to_handle_at_u64(int fd, const char *path, uint64_t *ret) {
_cleanup_free_ struct file_handle *h = NULL;
int r;
assert(fd >= 0 || fd == AT_FDCWD);
/* This provides the first 64bit of the file handle. */
r = name_to_handle_at_loop(fd, path, &h, /* ret_mnt_id= */ NULL, /* flags= */ 0);
if (r < 0)
return r;
if (h->handle_bytes < sizeof(uint64_t))
return -EBADMSG;
if (ret)
/* Note, "struct file_handle" is 32bit aligned usually, but we need to read a 64bit value from it */
*ret = unaligned_read_ne64(h->f_handle);
return 0;
}
bool file_handle_equal(const struct file_handle *a, const struct file_handle *b) {
if (a == b)
return true;

View File

@ -36,6 +36,13 @@ bool is_name_to_handle_at_fatal_error(int err);
int name_to_handle_at_loop(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags);
int name_to_handle_at_try_fid(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags);
int name_to_handle_at_u64(int fd, const char *path, uint64_t *ret);
static inline int path_to_handle_u64(const char *path, uint64_t *ret) {
return name_to_handle_at_u64(AT_FDCWD, path, ret);
}
static inline int fd_to_handle_u64(int fd, uint64_t *ret) {
return name_to_handle_at_u64(fd, NULL, ret);
}
bool file_handle_equal(const struct file_handle *a, const struct file_handle *b);

View File

@ -63,7 +63,7 @@ int parse_tristate_full(const char *v, const char *third, int *ret) {
return 0;
}
int parse_pid(const char *s, pid_t* ret_pid) {
int parse_pid(const char *s, pid_t *ret) {
unsigned long ul = 0;
pid_t pid;
int r;
@ -82,8 +82,8 @@ int parse_pid(const char *s, pid_t* ret_pid) {
if (!pid_is_valid(pid))
return -ERANGE;
if (ret_pid)
*ret_pid = pid;
if (ret)
*ret = pid;
return 0;
}

View File

@ -10,7 +10,7 @@ int parse_tristate_full(const char *v, const char *third, int *ret);
static inline int parse_tristate(const char *v, int *ret) {
return parse_tristate_full(v, NULL, ret);
}
int parse_pid(const char *s, pid_t* ret_pid);
int parse_pid(const char *s, pid_t *ret);
int parse_mode(const char *s, mode_t *ret);
int parse_ifindex(const char *s);
int parse_mtu(int family, const char *s, uint32_t *ret);

View File

@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/fs.h>
#include <linux/magic.h>
#include <sys/ioctl.h>
#include <threads.h>
@ -236,25 +235,10 @@ int pidfd_get_inode_id_impl(int fd, uint64_t *ret) {
assert(fd >= 0);
/* Since kernel 6.14 (b3caba8f7a34a2bbaf45ffc6ff3a49b70afeb192), we can use name_to_handle_at(). */
if (file_handle_supported) {
union {
struct file_handle file_handle;
uint8_t space[MAX_HANDLE_SZ];
} fh = {
.file_handle.handle_bytes = sizeof(uint64_t),
.file_handle.handle_type = FILEID_KERNFS,
};
int mnt_id;
r = RET_NERRNO(name_to_handle_at(fd, "", &fh.file_handle, &mnt_id, AT_EMPTY_PATH));
if (r >= 0) {
if (ret)
/* Note, "struct file_handle" is 32bit aligned usually, but we need to read a 64bit value from it */
*ret = unaligned_read_ne64(fh.file_handle.f_handle);
return 0;
}
assert(r != -EOVERFLOW);
if (is_name_to_handle_at_fatal_error(r))
r = fd_to_handle_u64(fd, ret);
if (r >= 0 || is_name_to_handle_at_fatal_error(r))
return r;
file_handle_supported = false;

View File

@ -34,6 +34,7 @@
#include "ip-protocol-list.h"
#include "limits-util.h"
#include "manager.h"
#include "mountpoint-util.h"
#include "netlink-internal.h"
#include "nulstr-util.h"
#include "parse-util.h"
@ -2069,13 +2070,14 @@ static int unit_update_cgroup(
uint64_t cgroup_id = 0;
r = cg_get_path(crt->cgroup_path, /* suffix= */ NULL, &cgroup_full_path);
if (r == 0) {
r = cg_path_get_cgroupid(cgroup_full_path, &cgroup_id);
if (r < 0)
log_unit_warning_errno(u, r, "Failed to get full cgroup path on cgroup %s, ignoring: %m", empty_to_root(crt->cgroup_path));
else {
r = path_to_handle_u64(cgroup_full_path, &cgroup_id);
if (r < 0)
log_unit_full_errno(u, ERRNO_IS_NOT_SUPPORTED(r) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to get cgroup ID of cgroup %s, ignoring: %m", cgroup_full_path);
} else
log_unit_warning_errno(u, r, "Failed to get full cgroup path on cgroup %s, ignoring: %m", empty_to_root(crt->cgroup_path));
}
crt->cgroup_id = cgroup_id;

View File

@ -2050,15 +2050,20 @@ static int apply_one_mount(
/* Hmm, either the source or the destination are missing. Let's see if we can create
the destination, then try again. */
(void) mkdir_parents(mount_entry_path(m), 0755);
q = make_mount_point_inode_from_path(what, mount_entry_path(m), 0755);
q = mkdir_parents(mount_entry_path(m), 0755);
if (q < 0 && q != -EEXIST)
// FIXME: this shouldn't be logged at LOG_WARNING, but be bubbled up, and logged there to avoid duplicate logging
log_warning_errno(q, "Failed to create destination mount point node '%s', ignoring: %m",
log_warning_errno(q, "Failed to create parent directories of destination mount point node '%s', ignoring: %m",
mount_entry_path(m));
else
try_again = true;
else {
q = make_mount_point_inode_from_path(what, mount_entry_path(m), 0755);
if (q < 0 && q != -EEXIST)
// FIXME: this shouldn't be logged at LOG_WARNING, but be bubbled up, and logged there to avoid duplicate logging
log_warning_errno(q, "Failed to create destination mount point node '%s', ignoring: %m",
mount_entry_path(m));
else
try_again = true;
}
}
if (try_again)

View File

@ -43,6 +43,7 @@
#include "parse-util.h"
#include "password-quality-util.h"
#include "path-util.h"
#include "plymouth-util.h"
#include "pretty-print.h"
#include "proc-cmdline.h"
#include "prompt-util.h"
@ -110,6 +111,10 @@ static void print_welcome(int rfd, sd_varlink **mute_console_link) {
assert(rfd >= 0);
assert(mute_console_link);
/* Needs to be called before mute_console or it will garble the screen */
if (arg_welcome)
(void) plymouth_hide_splash();
if (!*mute_console_link && arg_mute_console)
(void) mute_console(mute_console_link);

View File

@ -48,6 +48,7 @@
#include "percent-util.h"
#include "pidref.h"
#include "pkcs11-util.h"
#include "plymouth-util.h"
#include "polkit-agent.h"
#include "pretty-print.h"
#include "proc-cmdline.h"
@ -2891,6 +2892,9 @@ static int create_interactively(void) {
return 0;
}
/* Needs to be called before mute_console or it will garble the screen */
(void) plymouth_hide_splash();
_cleanup_(sd_varlink_flush_close_unrefp) sd_varlink *mute_console_link = NULL;
(void) mute_console(&mute_console_link);
@ -3265,17 +3269,17 @@ static int parse_size_field(sd_json_variant **identity, const char *field, const
static int parse_boolean_field(sd_json_variant **identity, const char *field, const char *arg) {
int r;
assert(identity);
assert(field);
if (isempty(arg))
return drop_from_identity(field);
r = parse_boolean(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse boolean parameter %s: %s", field, arg);
r = sd_json_variant_set_field_boolean(identity, field, r > 0);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);

View File

@ -14,8 +14,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
_cleanup_(manager_freep) Manager *m = NULL;
_cleanup_close_ int sealed_fd = -EBADF, unsealed_fd = -EBADF;
_cleanup_(unlink_tempfilep) char name[] = "/tmp/fuzz-journald-native-fd.XXXXXX";
char *label = NULL;
size_t label_len = 0;
struct ucred ucred;
struct timeval *tv = NULL;
@ -30,13 +28,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
.uid = geteuid(),
.gid = getegid(),
};
(void) manager_process_native_file(m, sealed_fd, &ucred, tv, label, label_len);
(void) manager_process_native_file(m, sealed_fd, &ucred, tv, /* label= */ NULL);
unsealed_fd = mkostemp_safe(name);
assert_se(unsealed_fd >= 0);
assert_se(write(unsealed_fd, data, size) == (ssize_t) size);
assert_se(lseek(unsealed_fd, 0, SEEK_SET) == 0);
(void) manager_process_native_file(m, unsealed_fd, &ucred, tv, label, label_len);
(void) manager_process_native_file(m, unsealed_fd, &ucred, tv, /* label= */ NULL);
return 0;
}

View File

@ -33,5 +33,5 @@ void fuzz_journald_processing_function(
_cleanup_(manager_freep) Manager *m = NULL;
dummy_manager_new(&m, data, size);
f(m, m->buffer, size, /* ucred= */ NULL, /* tv= */ NULL, /* label= */ NULL, /* label_len= */ 0);
f(m, m->buffer, size, /* ucred= */ NULL, /* tv= */ NULL, /* label= */ NULL);
}

View File

@ -9,8 +9,7 @@ typedef void (*journal_process_t)(
size_t raw_len,
const struct ucred *ucred,
const struct timeval *tv,
const char *label,
size_t label_len);
const char *label);
void dummy_manager_new(Manager **ret, const uint8_t *buffer, size_t size);

View File

@ -176,7 +176,6 @@ static void client_context_reset(Manager *m, ClientContext *c) {
c->invocation_id = SD_ID128_NULL;
c->label = mfree(c->label);
c->label_size = 0;
c->extra_fields_iovec = mfree(c->extra_fields_iovec);
c->extra_fields_n_iovec = 0;
@ -248,26 +247,21 @@ static void client_context_read_basic(ClientContext *c) {
static int client_context_read_label(
ClientContext *c,
const char *label, size_t label_size) {
const char *label) {
int r;
assert(c);
assert(pid_is_valid(c->pid));
assert(label_size == 0 || label);
if (!mac_selinux_use())
return 0;
if (label_size > 0) {
char *l;
if (label) {
/* If we got an SELinux label passed in it counts. */
l = newdup_suffix0(char, label, label_size);
if (!l)
r = free_and_strdup(&c->label, label);
if (r < 0)
return -ENOMEM;
free_and_replace(c->label, l);
c->label_size = label_size;
}
#if HAVE_SELINUX
else {
@ -275,10 +269,8 @@ static int client_context_read_label(
/* If we got no SELinux label passed in, let's try to acquire one */
if (sym_getpidcon_raw(c->pid, &con) >= 0 && con) {
if (sym_getpidcon_raw(c->pid, &con) >= 0 && con)
free_and_replace(c->label, con);
c->label_size = strlen(c->label);
}
}
#endif
@ -533,7 +525,7 @@ static void client_context_really_refresh(
Manager *m,
ClientContext *c,
const struct ucred *ucred,
const char *label, size_t label_size,
const char *label,
const char *unit_id,
usec_t timestamp) {
@ -546,7 +538,7 @@ static void client_context_really_refresh(
client_context_read_uid_gid(c, ucred);
client_context_read_basic(c);
(void) client_context_read_label(c, label, label_size);
(void) client_context_read_label(c, label);
(void) audit_session_from_pid(&PIDREF_MAKE_FROM_PID(c->pid), &c->auditid);
(void) audit_loginuid_from_pid(&PIDREF_MAKE_FROM_PID(c->pid), &c->loginuid);
@ -570,7 +562,7 @@ void client_context_maybe_refresh(
Manager *m,
ClientContext *c,
const struct ucred *ucred,
const char *label, size_t label_size,
const char *label,
const char *unit_id,
usec_t timestamp) {
@ -602,13 +594,13 @@ void client_context_maybe_refresh(
if (ucred && gid_is_valid(ucred->gid) && c->gid != ucred->gid)
goto refresh;
if (label_size > 0 && (label_size != c->label_size || memcmp(label, c->label, label_size) != 0))
if (label && !streq_ptr(label, c->label))
goto refresh;
return;
refresh:
client_context_really_refresh(m, c, ucred, label, label_size, unit_id, timestamp);
client_context_really_refresh(m, c, ucred, label, unit_id, timestamp);
}
static void client_context_refresh_on_reload(Manager *m, ClientContext *c) {
@ -710,7 +702,7 @@ static int client_context_get_internal(
Manager *m,
pid_t pid,
const struct ucred *ucred,
const char *label, size_t label_len,
const char *label,
const char *unit_id,
bool add_ref,
ClientContext **ret) {
@ -738,7 +730,7 @@ static int client_context_get_internal(
c->n_ref++;
}
client_context_maybe_refresh(m, c, ucred, label, label_len, unit_id, USEC_INFINITY);
client_context_maybe_refresh(m, c, ucred, label, unit_id, USEC_INFINITY);
*ret = c;
return 0;
@ -762,7 +754,7 @@ static int client_context_get_internal(
c->in_lru = true;
}
client_context_really_refresh(m, c, ucred, label, label_len, unit_id, USEC_INFINITY);
client_context_really_refresh(m, c, ucred, label, unit_id, USEC_INFINITY);
*ret = c;
return 0;
@ -772,22 +764,22 @@ int client_context_get(
Manager *m,
pid_t pid,
const struct ucred *ucred,
const char *label, size_t label_len,
const char *label,
const char *unit_id,
ClientContext **ret) {
return client_context_get_internal(m, pid, ucred, label, label_len, unit_id, false, ret);
return client_context_get_internal(m, pid, ucred, label, unit_id, /* add_ref= */ false, ret);
}
int client_context_acquire(
Manager *m,
pid_t pid,
const struct ucred *ucred,
const char *label, size_t label_len,
const char *label,
const char *unit_id,
ClientContext **ret) {
return client_context_get_internal(m, pid, ucred, label, label_len, unit_id, true, ret);
return client_context_get_internal(m, pid, ucred, label, unit_id, /* add_ref= */ true, ret);
};
ClientContext *client_context_release(Manager *m, ClientContext *c) {
@ -829,7 +821,7 @@ void client_context_acquire_default(Manager *m) {
.gid = getgid(),
};
r = client_context_acquire(m, ucred.pid, &ucred, NULL, 0, NULL, &m->my_context);
r = client_context_acquire(m, ucred.pid, &ucred, /* label= */ NULL, /* unit_id= */ NULL, &m->my_context);
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to acquire our own context, ignoring: %m");
@ -839,7 +831,7 @@ void client_context_acquire_default(Manager *m) {
/* Acquire PID1's context, but only if we are in non-namespaced mode, since PID 1 is only
* going to log to the non-namespaced journal instance. */
r = client_context_acquire(m, 1, NULL, NULL, 0, NULL, &m->pid1_context);
r = client_context_acquire(m, 1, /* ucred= */ NULL, /* label= */ NULL, /* unit_id= */ NULL, &m->pid1_context);
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to acquire PID1's context, ignoring: %m");

View File

@ -39,7 +39,6 @@ typedef struct ClientContext {
sd_id128_t invocation_id;
char *label;
size_t label_size;
int log_level_max;
@ -61,7 +60,7 @@ int client_context_get(
Manager *m,
pid_t pid,
const struct ucred *ucred,
const char *label, size_t label_len,
const char *label,
const char *unit_id,
ClientContext **ret);
@ -69,7 +68,7 @@ int client_context_acquire(
Manager *m,
pid_t pid,
const struct ucred *ucred,
const char *label, size_t label_len,
const char *label,
const char *unit_id,
ClientContext **ret);
@ -79,7 +78,7 @@ void client_context_maybe_refresh(
Manager *m,
ClientContext *c,
const struct ucred *ucred,
const char *label, size_t label_size,
const char *label,
const char *unit_id,
usec_t timestamp);

View File

@ -85,28 +85,23 @@ void manager_forward_kmsg(
log_debug_errno(errno, "Failed to write to /dev/kmsg for logging, ignoring: %m");
}
static bool is_us(const char *identifier, const char *pid) {
pid_t pid_num;
if (!identifier || !pid)
static bool is_us(const char *identifier, pid_t pid) {
if (!identifier || !pid_is_valid(pid))
return false;
if (parse_pid(pid, &pid_num) < 0)
return false;
return pid_num == getpid_cached() &&
return pid == getpid_cached() &&
streq(identifier, program_invocation_short_name);
}
void dev_kmsg_record(Manager *m, char *p, size_t l) {
_cleanup_free_ char *message = NULL, *syslog_pid = NULL, *syslog_identifier = NULL, *identifier = NULL, *pid = NULL;
_cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS];
char *kernel_device = NULL;
unsigned long long usec;
size_t n = 0, z = 0, j;
int priority, r;
char *e, *k;
char *e, *k, syslog_pid[STRLEN("SYSLOG_PID=") + DECIMAL_STR_MAX(pid_t)];
uint64_t serial;
size_t pl;
int saved_log_max_level = INT_MAX;
@ -284,6 +279,9 @@ void dev_kmsg_record(Manager *m, char *p, size_t l) {
if (LOG_FAC(priority) == LOG_KERN)
iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=kernel");
else {
_cleanup_free_ char *identifier = NULL;
pid_t pid;
pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid);
/* Avoid logging any new messages when we're processing messages generated by ourselves via
@ -303,10 +301,9 @@ void dev_kmsg_record(Manager *m, char *p, size_t l) {
iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier);
}
if (pid) {
syslog_pid = strjoin("SYSLOG_PID=", pid);
if (syslog_pid)
iovec[n++] = IOVEC_MAKE_STRING(syslog_pid);
if (pid_is_valid(pid)) {
xsprintf(syslog_pid, "SYSLOG_PID="PID_FMT, pid);
iovec[n++] = IOVEC_MAKE_STRING(syslog_pid);
}
}

View File

@ -56,6 +56,7 @@
#include "process-util.h"
#include "rm-rf.h"
#include "set.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "stdio-util.h"
@ -1058,14 +1059,6 @@ static void manager_write_to_journal(
iovec[n++] = IOVEC_MAKE_STRING(k); \
}
#define IOVEC_ADD_SIZED_FIELD(iovec, n, value, value_size, field) \
if (value_size > 0) { \
char *k; \
k = newa(char, STRLEN(field "=") + value_size + 1); \
*mempcpy_typesafe(stpcpy(k, field "="), value, value_size) = 0; \
iovec[n++] = IOVEC_MAKE_STRING(k); \
}
static void manager_dispatch_message_real(
Manager *m,
struct iovec *iovec, size_t n, size_t mm,
@ -1101,7 +1094,7 @@ static void manager_dispatch_message_real(
cmdline1 = set_iovec_string_field(iovec, &n, "_CMDLINE=", c->cmdline);
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->capability_quintet.effective, uint64_t, capability_is_set, "%" PRIx64, "_CAP_EFFECTIVE");
IOVEC_ADD_SIZED_FIELD(iovec, n, c->label, c->label_size, "_SELINUX_CONTEXT");
IOVEC_ADD_STRING_FIELD(iovec, n, c->label, "_SELINUX_CONTEXT");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "_AUDIT_SESSION");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->loginuid, uid_t, uid_is_valid, UID_FMT, "_AUDIT_LOGINUID");
@ -1123,7 +1116,7 @@ static void manager_dispatch_message_real(
assert(n <= mm);
if (pid_is_valid(object_pid) && client_context_get(m, object_pid, NULL, NULL, 0, NULL, &o) >= 0) {
if (pid_is_valid(object_pid) && client_context_get(m, object_pid, /* ucred= */ NULL, /* label= */ NULL, /* unit_id= */ NULL, &o) >= 0) {
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->pid, pid_t, pid_is_valid, PID_FMT, "OBJECT_PID");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->uid, uid_t, uid_is_valid, UID_FMT, "OBJECT_UID");
@ -1136,7 +1129,7 @@ static void manager_dispatch_message_real(
cmdline2 = set_iovec_string_field(iovec, &n, "OBJECT_CMDLINE=", o->cmdline);
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->capability_quintet.effective, uint64_t, capability_is_set, "%" PRIx64, "OBJECT_CAP_EFFECTIVE");
IOVEC_ADD_SIZED_FIELD(iovec, n, o->label, o->label_size, "OBJECT_SELINUX_CONTEXT");
IOVEC_ADD_STRING_FIELD(iovec, n, o->label, "OBJECT_SELINUX_CONTEXT");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "OBJECT_AUDIT_SESSION");
IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->loginuid, uid_t, uid_is_valid, UID_FMT, "OBJECT_AUDIT_LOGINUID");
@ -1482,12 +1475,12 @@ int manager_process_datagram(
uint32_t revents,
void *userdata) {
size_t label_len = 0, mm;
size_t mm;
Manager *m = ASSERT_PTR(userdata);
struct ucred *ucred = NULL;
struct timeval tv_buf, *tv = NULL;
struct cmsghdr *cmsg;
char *label = NULL;
_cleanup_free_ char *label = NULL;
struct iovec iovec;
ssize_t n;
int *fds = NULL, v = 0;
@ -1561,10 +1554,11 @@ int manager_process_datagram(
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
assert(!ucred);
ucred = CMSG_TYPED_DATA(cmsg, struct ucred);
} else if (cmsg->cmsg_type == SCM_SECURITY) {
} else if (cmsg->cmsg_type == SCM_SECURITY && mac_selinux_use()) {
assert(!label);
label = CMSG_TYPED_DATA(cmsg, char);
label_len = cmsg->cmsg_len - CMSG_LEN(0);
/* Here, we ignore any errors including OOM, as the field is optional. */
(void) make_cstring(CMSG_TYPED_DATA(cmsg, char), cmsg->cmsg_len - CMSG_LEN(0),
MAKE_CSTRING_ALLOW_TRAILING_NUL, &label);
} else if (cmsg->cmsg_type == SCM_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) {
assert(!tv);
@ -1581,7 +1575,7 @@ int manager_process_datagram(
if (fd == m->syslog_fd) {
if (n > 0 && n_fds == 0)
manager_process_syslog_message(m, m->buffer, n, ucred, tv, label, label_len);
manager_process_syslog_message(m, m->buffer, n, ucred, tv, label);
else if (n_fds > 0)
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
"Got file descriptors via syslog socket. Ignoring.");
@ -1591,9 +1585,9 @@ int manager_process_datagram(
} else if (fd == m->native_fd) {
if (n > 0 && n_fds == 0)
manager_process_native_message(m, m->buffer, n, ucred, tv, label, label_len);
manager_process_native_message(m, m->buffer, n, ucred, tv, label);
else if (n == 0 && n_fds == 1)
(void) manager_process_native_file(m, fds[0], ucred, tv, label, label_len);
(void) manager_process_native_file(m, fds[0], ucred, tv, label);
else if (n_fds > 0)
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
"Got too many file descriptors via native socket. Ignoring.");

View File

@ -98,7 +98,7 @@ static int manager_process_entry(
ClientContext *context,
const struct ucred *ucred,
const struct timeval *tv,
const char *label, size_t label_len) {
const char *label) {
/* Process a single entry from a native message. Returns 0 if nothing special happened and the message
* processing should continue, and a negative or positive value otherwise.
@ -304,7 +304,7 @@ void manager_process_native_message(
const char *buffer, size_t buffer_size,
const struct ucred *ucred,
const struct timeval *tv,
const char *label, size_t label_len) {
const char *label) {
size_t remaining = buffer_size;
ClientContext *context = NULL;
@ -314,7 +314,7 @@ void manager_process_native_message(
assert(buffer || buffer_size == 0);
if (ucred && pid_is_valid(ucred->pid)) {
r = client_context_get(m, ucred->pid, ucred, label, label_len, NULL, &context);
r = client_context_get(m, ucred->pid, ucred, label, /* unit_id= */ NULL, &context);
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m",
@ -324,7 +324,7 @@ void manager_process_native_message(
do {
r = manager_process_entry(m,
(const uint8_t*) buffer + (buffer_size - remaining), &remaining,
context, ucred, tv, label, label_len);
context, ucred, tv, label);
} while (r == 0);
}
@ -333,7 +333,7 @@ int manager_process_native_file(
int fd,
const struct ucred *ucred,
const struct timeval *tv,
const char *label, size_t label_len) {
const char *label) {
struct stat st;
bool sealed;
@ -410,7 +410,7 @@ int manager_process_native_file(
return log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT,
"Failed to map memfd: %m");
manager_process_native_message(m, p, st.st_size, ucred, tv, label, label_len);
manager_process_native_message(m, p, st.st_size, ucred, tv, label);
assert_se(munmap(p, ps) >= 0);
return 0;
@ -451,7 +451,7 @@ int manager_process_native_file(
return log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT,
"Failed to read file: %m");
if (n > 0)
manager_process_native_message(m, p, n, ucred, tv, label, label_len);
manager_process_native_message(m, p, n, ucred, tv, label);
return 0;
}

View File

@ -9,15 +9,13 @@ void manager_process_native_message(
size_t buffer_size,
const struct ucred *ucred,
const struct timeval *tv,
const char *label,
size_t label_len);
const char *label);
int manager_process_native_file(
Manager *m,
int fd,
const struct ucred *ucred,
const struct timeval *tv,
const char *label,
size_t label_len);
const char *label);
int manager_open_native_socket(Manager *m, const char *native_socket);

View File

@ -228,9 +228,9 @@ static int stdout_stream_log(
assert(line_break < _LINE_BREAK_MAX);
if (s->context)
client_context_maybe_refresh(s->manager, s->context, NULL, NULL, 0, NULL, USEC_INFINITY);
client_context_maybe_refresh(s->manager, s->context, /* ucred= */ NULL, /* label= */ NULL, /* unit_id= */ NULL, USEC_INFINITY);
else if (pid_is_valid(s->ucred.pid)) {
r = client_context_acquire(s->manager, s->ucred.pid, &s->ucred, s->label, strlen_ptr(s->label), s->unit_id, &s->context);
r = client_context_acquire(s->manager, s->ucred.pid, &s->ucred, s->label, s->unit_id, &s->context);
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to acquire client context, ignoring: %m");

View File

@ -21,6 +21,7 @@
#include "journald-wall.h"
#include "log.h"
#include "log-ratelimit.h"
#include "parse-util.h"
#include "process-util.h"
#include "selinux-util.h"
#include "socket-util.h"
@ -200,14 +201,14 @@ int syslog_fixup_facility(int priority) {
return priority;
}
size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) {
size_t syslog_parse_identifier(const char **buf, char **ret_identifier, pid_t *ret_pid) {
const char *p;
char *t;
size_t l, e;
pid_t pid = 0;
assert(buf);
assert(identifier);
assert(pid);
assert(ret_identifier);
assert(ret_pid);
p = *buf;
@ -215,8 +216,11 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
l = strcspn(p, WHITESPACE);
if (l <= 0 ||
p[l-1] != ':')
p[l-1] != ':') {
*ret_identifier = NULL;
*ret_pid = 0;
return 0;
}
e = l;
l--;
@ -227,9 +231,9 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
for (;;) {
if (p[k] == '[') {
t = strndup(p+k+1, l-k-2);
_cleanup_free_ char *t = strndup(p+k+1, l-k-2);
if (t)
*pid = t;
(void) parse_pid(t, &pid);
l = k;
break;
@ -242,9 +246,13 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
}
}
t = strndup(p, l);
if (t)
*identifier = t;
/* The syslog identifier should be short enough in most cases and NAME_MAX should be enough. Let's
* refuse ridiculously long identifier string as "no identifier string found", because if it is
* longer than some threshold then it is quite likely some misformatted data, and not a valid syslog
* message. Note. NAME_MAX is counted *without* the trailing NUL. */
_cleanup_free_ char *identifier = NULL;
if (l <= NAME_MAX)
identifier = strndup(p, l); /* ignore OOM here. */
/* Single space is used as separator */
if (p[e] != '\0' && strchr(WHITESPACE, p[e]))
@ -252,10 +260,12 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
l = (p - *buf) + e;
*buf = p + e;
*ret_identifier = TAKE_PTR(identifier);
*ret_pid = pid;
return l;
}
static int syslog_skip_timestamp(const char **buf) {
static size_t syslog_skip_timestamp(const char **buf) {
enum {
LETTER,
SPACE,
@ -275,8 +285,8 @@ static int syslog_skip_timestamp(const char **buf) {
SPACE
};
const char *p, *t;
unsigned i;
const char *p;
size_t i;
assert(buf);
assert(*buf);
@ -313,13 +323,15 @@ static int syslog_skip_timestamp(const char **buf) {
if (*p != ':')
return 0;
break;
}
}
t = *buf;
assert(p >= *buf);
size_t n = p - *buf;
assert(n <= ELEMENTSOF(sequence));
*buf = p;
return p - t;
return n;
}
void manager_process_syslog_message(
@ -328,14 +340,12 @@ void manager_process_syslog_message(
size_t raw_len,
const struct ucred *ucred,
const struct timeval *tv,
const char *label,
size_t label_len) {
const char *label) {
char *t, syslog_priority[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int)],
syslog_facility[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
const char *msg, *syslog_ts, *a;
_cleanup_free_ char *identifier = NULL, *pid = NULL,
*dummy = NULL, *msg_msg = NULL, *msg_raw = NULL;
_cleanup_free_ char *dummy = NULL, *msg_msg = NULL, *msg_raw = NULL;
int priority = LOG_USER | LOG_INFO, r;
ClientContext *context = NULL;
struct iovec *iovec;
@ -351,7 +361,7 @@ void manager_process_syslog_message(
assert(buf[raw_len] == '\0');
if (ucred && pid_is_valid(ucred->pid)) {
r = client_context_get(m, ucred->pid, ucred, label, label_len, NULL, &context);
r = client_context_get(m, ucred->pid, ucred, label, /* unit_id= */ NULL, &context);
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m",
@ -398,6 +408,8 @@ void manager_process_syslog_message(
/* We failed to parse the full timestamp, store the raw message too */
store_raw = true;
_cleanup_free_ char *identifier = NULL;
pid_t pid;
syslog_parse_identifier(&msg, &identifier, &pid);
if (client_context_check_keep_log(context, msg, strlen(msg)) <= 0)
@ -433,9 +445,10 @@ void manager_process_syslog_message(
iovec[n++] = IOVEC_MAKE_STRING(a);
}
if (pid) {
a = strjoina("SYSLOG_PID=", pid);
iovec[n++] = IOVEC_MAKE_STRING(a);
char syslog_pid[STRLEN("SYSLOG_PID=") + DECIMAL_STR_MAX(pid_t)];
if (pid_is_valid(pid)) {
xsprintf(syslog_pid, "SYSLOG_PID="PID_FMT, pid);
iovec[n++] = IOVEC_MAKE_STRING(syslog_pid);
}
if (syslog_ts_len > 0) {

View File

@ -5,11 +5,11 @@
int syslog_fixup_facility(int priority) _const_;
size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid);
size_t syslog_parse_identifier(const char **buf, char **ret_identifier, pid_t *ret_pid);
void manager_forward_syslog(Manager *m, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv);
void manager_process_syslog_message(Manager *m, const char *buf, size_t raw_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len);
void manager_process_syslog_message(Manager *m, const char *buf, size_t raw_len, const struct ucred *ucred, const struct timeval *tv, const char *label);
int manager_open_syslog_socket(Manager *m, const char *syslog_socket);
void manager_maybe_warn_forward_syslog_missed(Manager *m);

View File

@ -5,18 +5,24 @@
#include "syslog-util.h"
#include "tests.h"
static void test_syslog_parse_identifier_one(const char *str,
const char *ident, const char *pid, const char *rest, int ret) {
static void test_syslog_parse_identifier_one(
const char *str,
const char *ident,
pid_t pid,
const char *rest,
int ret) {
const char *buf = str;
_cleanup_free_ char *ident2 = NULL, *pid2 = NULL;
_cleanup_free_ char *ident2 = NULL;
pid_t pid2;
int ret2;
ret2 = syslog_parse_identifier(&buf, &ident2, &pid2);
assert_se(ret == ret2);
assert_se(ident == ident2 || streq_ptr(ident, ident2));
assert_se(pid == pid2 || streq_ptr(pid, pid2));
assert_se(streq(buf, rest));
ASSERT_EQ(ret, ret2);
ASSERT_STREQ(ident, ident2);
ASSERT_EQ(pid, pid2);
ASSERT_STREQ(buf, rest);
}
static void test_syslog_parse_priority_one(const char *str, bool with_facility, int priority, int ret) {
@ -30,20 +36,20 @@ static void test_syslog_parse_priority_one(const char *str, bool with_facility,
}
TEST(syslog_parse_identifier) {
test_syslog_parse_identifier_one("pidu[111]: xxx", "pidu", "111", "xxx", 11);
test_syslog_parse_identifier_one("pidu: xxx", "pidu", NULL, "xxx", 6);
test_syslog_parse_identifier_one("pidu: xxx", "pidu", NULL, " xxx", 6);
test_syslog_parse_identifier_one("pidu xxx", NULL, NULL, "pidu xxx", 0);
test_syslog_parse_identifier_one(" pidu xxx", NULL, NULL, " pidu xxx", 0);
test_syslog_parse_identifier_one("", NULL, NULL, "", 0);
test_syslog_parse_identifier_one(" ", NULL, NULL, " ", 0);
test_syslog_parse_identifier_one(":", "", NULL, "", 1);
test_syslog_parse_identifier_one(": ", "", NULL, " ", 2);
test_syslog_parse_identifier_one(" :", "", NULL, "", 2);
test_syslog_parse_identifier_one(" pidu:", "pidu", NULL, "", 8);
test_syslog_parse_identifier_one("pidu:", "pidu", NULL, "", 5);
test_syslog_parse_identifier_one("pidu: ", "pidu", NULL, "", 6);
test_syslog_parse_identifier_one("pidu : ", NULL, NULL, "pidu : ", 0);
test_syslog_parse_identifier_one("pidu[111]: xxx", "pidu", 111, "xxx", 11);
test_syslog_parse_identifier_one("pidu: xxx", "pidu", 0, "xxx", 6);
test_syslog_parse_identifier_one("pidu: xxx", "pidu", 0, " xxx", 6);
test_syslog_parse_identifier_one("pidu xxx", NULL, 0, "pidu xxx", 0);
test_syslog_parse_identifier_one(" pidu xxx", NULL, 0, " pidu xxx", 0);
test_syslog_parse_identifier_one("", NULL, 0, "", 0);
test_syslog_parse_identifier_one(" ", NULL, 0, " ", 0);
test_syslog_parse_identifier_one(":", "", 0, "", 1);
test_syslog_parse_identifier_one(": ", "", 0, " ", 2);
test_syslog_parse_identifier_one(" :", "", 0, "", 2);
test_syslog_parse_identifier_one(" pidu:", "pidu", 0, "", 8);
test_syslog_parse_identifier_one("pidu:", "pidu", 0, "", 5);
test_syslog_parse_identifier_one("pidu: ", "pidu", 0, "", 6);
test_syslog_parse_identifier_one("pidu : ", NULL, 0, "pidu : ", 0);
}
TEST(syslog_parse_priority) {

View File

@ -1354,7 +1354,7 @@ static int validate_cgroup(sd_varlink *link, int fd, uint64_t *ret_cgroup_id) {
if (r == 0)
return sd_varlink_error_invalid_parameter_name(link, "controlGroupFileDescriptor");
r = cg_fd_get_cgroupid(fd, ret_cgroup_id);
r = fd_to_handle_u64(fd, ret_cgroup_id);
if (r < 0)
return log_debug_errno(r, "Failed to read cgroup ID from cgroupfs: %m");

View File

@ -2047,7 +2047,7 @@ int portable_attach(
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && !FLAGS_SET(flags, PORTABLE_FORCE_ATTACH))
HASHMAP_FOREACH(item, unit_files) {
r = unit_file_exists(scope, &paths, item->name);
r = unit_file_exists_full(scope, &paths, SEARCH_IGNORE_TEMPLATE, item->name, /* ret_path= */ NULL);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name);
if (r > 0)

View File

@ -61,7 +61,6 @@
#include "strv.h"
#include "terminal-util.h"
#include "time-util.h"
#include "uid-classification.h"
#include "unit-def.h"
#include "unit-name.h"
#include "user-util.h"
@ -2248,9 +2247,6 @@ static int fchown_to_capsule(int fd, const char *capsule) {
if (r < 0)
return r;
if (uid_is_system(st.st_uid) || gid_is_system(st.st_gid)) /* paranoid safety check */
return -EPERM;
return fchmod_and_chown(fd, 0600, st.st_uid, st.st_gid);
}

View File

@ -35,7 +35,6 @@
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "uid-classification.h"
static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
sd_event *e = ASSERT_PTR(userdata);
@ -316,7 +315,7 @@ static int pin_capsule_socket(const char *capsule, const char *suffix, uid_t *re
if (!p)
return -ENOMEM;
/* We enter territory owned by the user, hence let's be paranoid about symlinks and ownership */
/* We enter territory owned by the user, hence let's be paranoid about symlinks */
r = chase(p, /* root= */ NULL, CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS, /* ret_path= */ NULL, &inode_fd);
if (r < 0)
return r;
@ -324,10 +323,6 @@ static int pin_capsule_socket(const char *capsule, const char *suffix, uid_t *re
if (fstat(inode_fd, &st) < 0)
return negative_errno();
/* Paranoid safety check */
if (uid_is_system(st.st_uid) || gid_is_system(st.st_gid))
return -EPERM;
*ret_uid = st.st_uid;
*ret_gid = st.st_gid;

View File

@ -18,6 +18,7 @@
#include "glyph-util.h"
#include "hostname-util.h"
#include "log.h"
#include "mountpoint-util.h"
#include "nulstr-util.h"
#include "output-mode.h"
#include "path-util.h"
@ -150,7 +151,7 @@ static int show_cgroup_name(
delegate = r > 0;
if (FLAGS_SET(flags, OUTPUT_CGROUP_ID)) {
r = cg_fd_get_cgroupid(fd, &cgroupid);
r = fd_to_handle_u64(fd, &cgroupid);
if (r < 0)
log_debug_errno(r, "Failed to determine cgroup ID of %s, ignoring: %m", path);
}

View File

@ -37,12 +37,6 @@
#define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
typedef enum SearchFlags {
SEARCH_LOAD = 1 << 0,
SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1,
SEARCH_DROPIN = 1 << 2,
} SearchFlags;
typedef struct {
RuntimeScope scope;
OrderedHashmap *will_process;
@ -1563,7 +1557,7 @@ static int unit_file_search(
assert(info->name);
if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
if (!FLAGS_SET(flags, SEARCH_IGNORE_TEMPLATE) && unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
r = unit_name_template(info->name, &template);
if (r < 0)
return r;
@ -3242,7 +3236,7 @@ int unit_file_get_state(
int unit_file_exists_full(
RuntimeScope scope,
const LookupPaths *lp,
bool follow,
SearchFlags flags,
const char *name,
char **ret_path) {
@ -3262,7 +3256,7 @@ int unit_file_exists_full(
&c,
lp,
name,
follow ? SEARCH_FOLLOW_CONFIG_SYMLINKS : 0,
flags,
ret_path ? &info : NULL,
/* changes= */ NULL,
/* n_changes= */ NULL);

View File

@ -39,6 +39,13 @@ typedef enum UnitFileFlags {
_UNIT_FILE_FLAGS_MASK_PUBLIC = UNIT_FILE_RUNTIME|UNIT_FILE_PORTABLE|UNIT_FILE_FORCE,
} UnitFileFlags;
typedef enum SearchFlags {
SEARCH_LOAD = 1 << 0,
SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1,
SEARCH_DROPIN = 1 << 2,
SEARCH_IGNORE_TEMPLATE = 1 << 3, /* Don't look up the template if the instance does not exist. */
} SearchFlags;
/* type can be either one of the INSTALL_CHANGE_SYMLINK, INSTALL_CHANGE_UNLINK, … listed above, or a negative
* errno value.
*
@ -184,12 +191,12 @@ int unit_file_get_state(RuntimeScope scope, const char *root_dir, const char *fi
int unit_file_exists_full(
RuntimeScope scope,
const LookupPaths *lp,
bool follow,
SearchFlags flags,
const char *name,
char **ret_path);
static inline int unit_file_exists(RuntimeScope scope, const LookupPaths *lp, const char *name) {
return unit_file_exists_full(scope, lp, false, name, NULL);
return unit_file_exists_full(scope, lp, 0, name, NULL);
}
int unit_file_get_list(RuntimeScope scope, const char *root_dir, char * const *states, char * const *patterns, Hashmap **ret);

View File

@ -56,3 +56,14 @@ int plymouth_send_msg(const char *text, bool pause_spinner) {
return 0;
}
int plymouth_hide_splash(void) {
int r;
r = plymouth_send_raw("H\0", 2, SOCK_NONBLOCK);
if (r < 0)
return log_full_errno(ERRNO_IS_NO_PLYMOUTH(r) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to communicate with plymouth: %m");
return 0;
}

View File

@ -7,6 +7,7 @@
int plymouth_connect(int flags);
int plymouth_send_raw(const void *raw, size_t size, int flags);
int plymouth_send_msg(const char *text, bool pause_spinner);
int plymouth_hide_splash(void);
static inline bool ERRNO_IS_NO_PLYMOUTH(int r) {
return IN_SET(ABS(r), EAGAIN, ENOENT) || ERRNO_IS_DISCONNECT(r);

View File

@ -474,7 +474,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
_cleanup_free_ char *found_sshd_template_unit = NULL;
r = unit_file_exists_full(RUNTIME_SCOPE_SYSTEM, &lp,
/* follow = */ true,
SEARCH_FOLLOW_CONFIG_SYMLINKS,
"sshd@.service",
&found_sshd_template_unit);
if (r < 0)

View File

@ -7,6 +7,7 @@
#include "errno-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "mountpoint-util.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
@ -493,7 +494,7 @@ TEST(cgroupid) {
ASSERT_OK(fd_get_path(fd, &p));
ASSERT_TRUE(path_equal(p, "/sys/fs/cgroup"));
ASSERT_OK(cg_fd_get_cgroupid(fd, &id));
ASSERT_OK(fd_to_handle_u64(fd, &id));
fd2 = cg_cgroupid_open(fd, id);
@ -509,7 +510,7 @@ TEST(cgroupid) {
ASSERT_OK(fd_get_path(fd2, &p2));
ASSERT_TRUE(path_equal(p2, "/sys/fs/cgroup"));
ASSERT_OK(cg_fd_get_cgroupid(fd2, &id2));
ASSERT_OK(fd_to_handle_u64(fd2, &id2));
ASSERT_EQ(id, id2);

View File

@ -218,6 +218,8 @@ Manager* manager_free(Manager *manager) {
sd_event_source_unref(manager->inotify_event);
set_free(manager->synthesize_change_child_event_sources);
set_free(manager->synthesized_events);
sd_event_source_unref(manager->synthesized_events_clear_event_source);
sd_event_source_unref(manager->kill_workers_event);
sd_event_unref(manager->event);
@ -895,6 +897,11 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
assert(manager);
assert(dev);
/* If the event is the one we triggered, remove the UUID from the list. */
sd_id128_t uuid;
if (sd_device_get_trigger_uuid(dev, &uuid) >= 0)
free(set_remove(manager->synthesized_events, &uuid));
/* We only accepts devices received by device monitor. */
r = sd_device_get_seqnum(dev, &seqnum);
if (r < 0)
@ -962,14 +969,6 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
TAKE_PTR(event);
log_device_uevent(dev, "Device is queued");
if (!manager->queue_file_created) {
r = touch("/run/udev/queue");
if (r < 0)
log_warning_errno(r, "Failed to touch /run/udev/queue, ignoring: %m");
else
manager->queue_file_created = true;
}
return 0;
}
@ -1068,6 +1067,9 @@ static int manager_deserialize_events(Manager *manager, int *fd) {
n++;
}
if (n > 0)
(void) manager_create_queue_file(manager);
log_debug("Deserialized %"PRIu64" events.", n);
return 0;
}
@ -1078,6 +1080,8 @@ static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata)
DEVICE_TRACE_POINT(kernel_uevent_received, dev);
(void) manager_create_queue_file(manager);
device_ensure_usec_initialized(dev, NULL);
r = event_queue_insert(manager, dev);
@ -1256,6 +1260,22 @@ static int on_sighup(sd_event_source *s, const struct signalfd_siginfo *si, void
return 1;
}
int manager_create_queue_file(Manager *manager) {
int r;
assert(manager);
if (manager->queue_file_created)
return 0;
r = touch("/run/udev/queue");
if (r < 0)
return log_warning_errno(r, "Failed to touch /run/udev/queue: %m");
manager->queue_file_created = true;
return 0;
}
static int manager_unlink_queue_file(Manager *manager) {
assert(manager);
@ -1265,6 +1285,9 @@ static int manager_unlink_queue_file(Manager *manager) {
if (!set_isempty(manager->synthesize_change_child_event_sources))
return 0; /* There are child processes that should trigger synthetic events. */
if (!set_isempty(manager->synthesized_events))
return 0; /* We have triggered synthesized change events. */
/* There are no queued events. Let's remove /run/udev/queue and clean up the idle processes. */
if (unlink("/run/udev/queue") < 0) {
if (errno != ENOENT)

View File

@ -54,6 +54,8 @@ typedef struct Manager {
int inotify_fd;
sd_event_source *inotify_event;
Set *synthesize_change_child_event_sources;
Set *synthesized_events;
sd_event_source *synthesized_events_clear_event_source;
sd_event_source *kill_workers_event;
@ -91,3 +93,5 @@ int manager_reset_kill_workers_timer(Manager *manager);
bool devpath_conflict(const char *a, const char *b);
int manager_requeue_locked_events_by_device(Manager *manager, sd_device *dev);
int manager_create_queue_file(Manager *manager);

View File

@ -18,6 +18,7 @@
#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
#include "id128-util.h"
#include "inotify-util.h"
#include "parse-util.h"
#include "pidref.h"
@ -28,6 +29,7 @@
#include "signal-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "time-util.h"
#include "udev-manager.h"
#include "udev-trace.h"
#include "udev-util.h"
@ -141,24 +143,70 @@ void udev_watch_dump(void) {
}
}
static int synthesize_change_one(sd_device *dev, sd_device *target) {
static int on_synthesized_events_clear(sd_event_source *s, uint64_t usec, void *userdata) {
Manager *manager = ASSERT_PTR(userdata);
for (;;) {
_cleanup_free_ sd_id128_t *uuid = set_steal_first(manager->synthesized_events);
if (!uuid)
return 0;
log_warning("Could not receive synthesized event with UUID %s, ignoring.",
SD_ID128_TO_STRING(*uuid));
}
}
static int synthesize_change_one(Manager *manager, sd_device *dev) {
int r;
assert(manager);
assert(dev);
assert(target);
if (DEBUG_LOGGING) {
const char *syspath = NULL;
(void) sd_device_get_syspath(target, &syspath);
(void) sd_device_get_syspath(dev, &syspath);
log_device_debug(dev, "device is closed, synthesising 'change' on %s", strna(syspath));
}
r = sd_device_trigger(target, SD_DEVICE_CHANGE);
sd_id128_t uuid;
r = sd_device_trigger_with_uuid(dev, SD_DEVICE_CHANGE, &uuid);
if (r < 0)
return log_device_debug_errno(target, r, "Failed to trigger 'change' uevent: %m");
return log_device_debug_errno(dev, r, "Failed to trigger 'change' uevent: %m");
DEVICE_TRACE_POINT(synthetic_change_event, dev);
/* Avoid /run/udev/queue file being removed by on_post(). */
sd_id128_t *copy = newdup(sd_id128_t, &uuid, 1);
if (!copy)
return log_oom_debug();
/* Let's not wait for too many events, to make not udevd consume huge amount of memory.
* Typically (but unfortunately, not always), the kernel provides events in the order we triggered.
* Hence, remembering the newest UUID should be mostly enough. */
while (set_size(manager->synthesized_events) >= 1024) {
_cleanup_free_ sd_id128_t *id = ASSERT_PTR(set_steal_first(manager->synthesized_events));
log_debug("Too many synthesized events are waiting, forgetting synthesized event with UUID %s.",
SD_ID128_TO_STRING(*id));
}
r = set_ensure_consume(&manager->synthesized_events, &id128_hash_ops_free, copy);
if (r < 0)
return log_oom_debug();
r = event_reset_time_relative(
manager->event,
&manager->synthesized_events_clear_event_source,
CLOCK_MONOTONIC,
1 * USEC_PER_MINUTE,
USEC_PER_SEC,
on_synthesized_events_clear,
manager,
SD_EVENT_PRIORITY_NORMAL,
"synthesized-events-clear",
/* force_reset= */ true);
if (r < 0)
log_debug_errno(r, "Failed to reset timer event source for clearling synthesized event UUIDs: %m");
return 0;
}
@ -180,13 +228,13 @@ static int synthesize_change(Manager *manager, sd_device *dev) {
if (r < 0)
return r;
if (r > 0)
return synthesize_change_one(dev, dev);
return synthesize_change_one(manager, dev);
r = block_device_is_whole_disk(dev);
if (r < 0)
return r;
if (r == 0)
return synthesize_change_one(dev, dev);
return synthesize_change_one(manager, dev);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork(
@ -242,6 +290,7 @@ static int manager_process_inotify(Manager *manager, const struct inotify_event
log_device_debug(dev, "Received inotify event of watch handle %i.", e->wd);
(void) manager_create_queue_file(manager);
(void) manager_requeue_locked_events_by_device(manager, dev);
(void) synthesize_change(manager, dev);
return 0;

View File

@ -2451,9 +2451,11 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
return log_oom();
}
r = strv_prepend(&arg_kernel_cmdline_extra, "console=hvc0");
if (r < 0)
return log_oom();
if (arg_console_mode != CONSOLE_GUI) {
r = strv_prepend(&arg_kernel_cmdline_extra, "console=hvc0");
if (r < 0)
return log_oom();
}
for (size_t j = 0; j < arg_runtime_mounts.n_mounts; j++) {
RuntimeMount *m = arg_runtime_mounts.mounts + j;

View File

@ -1,10 +1,3 @@
/*/* -whitespace
/fuzz-bus-match/* binary
/fuzz-compress/* binary
/fuzz-dhcp*/* binary
/fuzz-dns-packet/* binary
/fuzz-fido-id-desc/* binary
/fuzz-journald-audit/* binary
/fuzz-lldp-rx/* binary
/fuzz-ndisc-rs/* binary
/*/* binary
/*/* generated

File diff suppressed because one or more lines are too long