mirror of
https://github.com/systemd/systemd
synced 2026-03-14 17:14:49 +01:00
Compare commits
24 Commits
a40d934007
...
503a788332
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
503a788332 | ||
|
|
06432cca43 | ||
|
|
ede1caeada | ||
|
|
f37931bd78 | ||
|
|
2eab8fa1e4 | ||
|
|
e7ce1e22b9 | ||
|
|
09811ccaa1 | ||
|
|
055ceec666 | ||
|
|
f2a54dac72 | ||
|
|
50ddcf8554 | ||
|
|
ae6dcaff0d | ||
|
|
4d388536ee | ||
|
|
b231c4dcb4 | ||
|
|
eb5b797d7c | ||
|
|
dd839b1463 | ||
|
|
7e81423fb8 | ||
|
|
8d607f93b7 | ||
|
|
0dcbb30f49 | ||
|
|
dc709eff0b | ||
|
|
b7363d3330 | ||
|
|
95b40e4cf3 | ||
|
|
75cb25c0b9 | ||
|
|
7f7622285d | ||
|
|
610d8c3dfc |
@ -35,21 +35,6 @@
|
|||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
#include "xattr-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) {
|
int cg_is_available(void) {
|
||||||
struct statfs fs;
|
struct statfs fs;
|
||||||
|
|
||||||
@ -85,7 +70,14 @@ int cg_cgroupid_open(int cgroupfs_fd, uint64_t id) {
|
|||||||
cgroupfs_fd = fsfd;
|
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);
|
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));
|
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;
|
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) {
|
int cg_enumerate_processes(const char *path, FILE **ret) {
|
||||||
_cleanup_free_ char *fs = NULL;
|
_cleanup_free_ char *fs = NULL;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|||||||
@ -125,13 +125,6 @@ int cg_path_open(const char *path);
|
|||||||
int cg_cgroupid_open(int cgroupfs_fd, uint64_t id);
|
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_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 {
|
typedef enum CGroupFlags {
|
||||||
CGROUP_SIGCONT = 1 << 0,
|
CGROUP_SIGCONT = 1 << 0,
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.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
|
/* 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
|
* 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
|
* 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. */
|
* as NULL if there's no interest in either. */
|
||||||
|
|
||||||
|
if (isempty(path)) {
|
||||||
|
flags |= AT_EMPTY_PATH;
|
||||||
|
path = "";
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
_cleanup_free_ struct file_handle *h = NULL;
|
_cleanup_free_ struct file_handle *h = NULL;
|
||||||
int mnt_id = -1;
|
int mnt_id = -1;
|
||||||
@ -73,7 +79,7 @@ int name_to_handle_at_loop(
|
|||||||
|
|
||||||
h->handle_bytes = n;
|
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)
|
if (ret_handle)
|
||||||
*ret_handle = TAKE_PTR(h);
|
*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);
|
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) {
|
bool file_handle_equal(const struct file_handle *a, const struct file_handle *b) {
|
||||||
if (a == b)
|
if (a == b)
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -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_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_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);
|
bool file_handle_equal(const struct file_handle *a, const struct file_handle *b);
|
||||||
|
|
||||||
|
|||||||
@ -63,7 +63,7 @@ int parse_tristate_full(const char *v, const char *third, int *ret) {
|
|||||||
return 0;
|
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;
|
unsigned long ul = 0;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int r;
|
int r;
|
||||||
@ -82,8 +82,8 @@ int parse_pid(const char *s, pid_t* ret_pid) {
|
|||||||
if (!pid_is_valid(pid))
|
if (!pid_is_valid(pid))
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
if (ret_pid)
|
if (ret)
|
||||||
*ret_pid = pid;
|
*ret = pid;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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) {
|
static inline int parse_tristate(const char *v, int *ret) {
|
||||||
return parse_tristate_full(v, NULL, 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_mode(const char *s, mode_t *ret);
|
||||||
int parse_ifindex(const char *s);
|
int parse_ifindex(const char *s);
|
||||||
int parse_mtu(int family, const char *s, uint32_t *ret);
|
int parse_mtu(int family, const char *s, uint32_t *ret);
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <linux/magic.h>
|
#include <linux/magic.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <threads.h>
|
#include <threads.h>
|
||||||
@ -236,25 +235,10 @@ int pidfd_get_inode_id_impl(int fd, uint64_t *ret) {
|
|||||||
|
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
|
/* Since kernel 6.14 (b3caba8f7a34a2bbaf45ffc6ff3a49b70afeb192), we can use name_to_handle_at(). */
|
||||||
if (file_handle_supported) {
|
if (file_handle_supported) {
|
||||||
union {
|
r = fd_to_handle_u64(fd, ret);
|
||||||
struct file_handle file_handle;
|
if (r >= 0 || is_name_to_handle_at_fatal_error(r))
|
||||||
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))
|
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
file_handle_supported = false;
|
file_handle_supported = false;
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
#include "ip-protocol-list.h"
|
#include "ip-protocol-list.h"
|
||||||
#include "limits-util.h"
|
#include "limits-util.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
|
#include "mountpoint-util.h"
|
||||||
#include "netlink-internal.h"
|
#include "netlink-internal.h"
|
||||||
#include "nulstr-util.h"
|
#include "nulstr-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
@ -2069,13 +2070,14 @@ static int unit_update_cgroup(
|
|||||||
|
|
||||||
uint64_t cgroup_id = 0;
|
uint64_t cgroup_id = 0;
|
||||||
r = cg_get_path(crt->cgroup_path, /* suffix= */ NULL, &cgroup_full_path);
|
r = cg_get_path(crt->cgroup_path, /* suffix= */ NULL, &cgroup_full_path);
|
||||||
if (r == 0) {
|
if (r < 0)
|
||||||
r = cg_path_get_cgroupid(cgroup_full_path, &cgroup_id);
|
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)
|
if (r < 0)
|
||||||
log_unit_full_errno(u, ERRNO_IS_NOT_SUPPORTED(r) ? LOG_DEBUG : LOG_WARNING, r,
|
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);
|
"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;
|
crt->cgroup_id = cgroup_id;
|
||||||
|
|
||||||
|
|||||||
@ -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
|
/* Hmm, either the source or the destination are missing. Let's see if we can create
|
||||||
the destination, then try again. */
|
the destination, then try again. */
|
||||||
|
|
||||||
(void) mkdir_parents(mount_entry_path(m), 0755);
|
q = mkdir_parents(mount_entry_path(m), 0755);
|
||||||
|
|
||||||
q = make_mount_point_inode_from_path(what, mount_entry_path(m), 0755);
|
|
||||||
if (q < 0 && q != -EEXIST)
|
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
|
// 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));
|
mount_entry_path(m));
|
||||||
else
|
else {
|
||||||
try_again = true;
|
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)
|
if (try_again)
|
||||||
|
|||||||
@ -43,6 +43,7 @@
|
|||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "password-quality-util.h"
|
#include "password-quality-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
|
#include "plymouth-util.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
#include "prompt-util.h"
|
#include "prompt-util.h"
|
||||||
@ -110,6 +111,10 @@ static void print_welcome(int rfd, sd_varlink **mute_console_link) {
|
|||||||
assert(rfd >= 0);
|
assert(rfd >= 0);
|
||||||
assert(mute_console_link);
|
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)
|
if (!*mute_console_link && arg_mute_console)
|
||||||
(void) mute_console(mute_console_link);
|
(void) mute_console(mute_console_link);
|
||||||
|
|
||||||
|
|||||||
@ -48,6 +48,7 @@
|
|||||||
#include "percent-util.h"
|
#include "percent-util.h"
|
||||||
#include "pidref.h"
|
#include "pidref.h"
|
||||||
#include "pkcs11-util.h"
|
#include "pkcs11-util.h"
|
||||||
|
#include "plymouth-util.h"
|
||||||
#include "polkit-agent.h"
|
#include "polkit-agent.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
@ -2891,6 +2892,9 @@ static int create_interactively(void) {
|
|||||||
return 0;
|
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;
|
_cleanup_(sd_varlink_flush_close_unrefp) sd_varlink *mute_console_link = NULL;
|
||||||
(void) mute_console(&mute_console_link);
|
(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) {
|
static int parse_boolean_field(sd_json_variant **identity, const char *field, const char *arg) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(identity);
|
assert(identity);
|
||||||
assert(field);
|
assert(field);
|
||||||
|
|
||||||
if (isempty(arg))
|
if (isempty(arg))
|
||||||
return drop_from_identity(field);
|
return drop_from_identity(field);
|
||||||
|
|
||||||
r = parse_boolean(arg);
|
r = parse_boolean(arg);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to parse boolean parameter %s: %s", field, arg);
|
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);
|
r = sd_json_variant_set_field_boolean(identity, field, r > 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set %s field: %m", field);
|
return log_error_errno(r, "Failed to set %s field: %m", field);
|
||||||
|
|||||||
@ -14,8 +14,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
_cleanup_(manager_freep) Manager *m = NULL;
|
_cleanup_(manager_freep) Manager *m = NULL;
|
||||||
_cleanup_close_ int sealed_fd = -EBADF, unsealed_fd = -EBADF;
|
_cleanup_close_ int sealed_fd = -EBADF, unsealed_fd = -EBADF;
|
||||||
_cleanup_(unlink_tempfilep) char name[] = "/tmp/fuzz-journald-native-fd.XXXXXX";
|
_cleanup_(unlink_tempfilep) char name[] = "/tmp/fuzz-journald-native-fd.XXXXXX";
|
||||||
char *label = NULL;
|
|
||||||
size_t label_len = 0;
|
|
||||||
struct ucred ucred;
|
struct ucred ucred;
|
||||||
struct timeval *tv = NULL;
|
struct timeval *tv = NULL;
|
||||||
|
|
||||||
@ -30,13 +28,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
.uid = geteuid(),
|
.uid = geteuid(),
|
||||||
.gid = getegid(),
|
.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);
|
unsealed_fd = mkostemp_safe(name);
|
||||||
assert_se(unsealed_fd >= 0);
|
assert_se(unsealed_fd >= 0);
|
||||||
assert_se(write(unsealed_fd, data, size) == (ssize_t) size);
|
assert_se(write(unsealed_fd, data, size) == (ssize_t) size);
|
||||||
assert_se(lseek(unsealed_fd, 0, SEEK_SET) == 0);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,5 +33,5 @@ void fuzz_journald_processing_function(
|
|||||||
|
|
||||||
_cleanup_(manager_freep) Manager *m = NULL;
|
_cleanup_(manager_freep) Manager *m = NULL;
|
||||||
dummy_manager_new(&m, data, size);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,7 @@ typedef void (*journal_process_t)(
|
|||||||
size_t raw_len,
|
size_t raw_len,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const struct timeval *tv,
|
const struct timeval *tv,
|
||||||
const char *label,
|
const char *label);
|
||||||
size_t label_len);
|
|
||||||
|
|
||||||
void dummy_manager_new(Manager **ret, const uint8_t *buffer, size_t size);
|
void dummy_manager_new(Manager **ret, const uint8_t *buffer, size_t size);
|
||||||
|
|
||||||
|
|||||||
@ -176,7 +176,6 @@ static void client_context_reset(Manager *m, ClientContext *c) {
|
|||||||
c->invocation_id = SD_ID128_NULL;
|
c->invocation_id = SD_ID128_NULL;
|
||||||
|
|
||||||
c->label = mfree(c->label);
|
c->label = mfree(c->label);
|
||||||
c->label_size = 0;
|
|
||||||
|
|
||||||
c->extra_fields_iovec = mfree(c->extra_fields_iovec);
|
c->extra_fields_iovec = mfree(c->extra_fields_iovec);
|
||||||
c->extra_fields_n_iovec = 0;
|
c->extra_fields_n_iovec = 0;
|
||||||
@ -248,26 +247,21 @@ static void client_context_read_basic(ClientContext *c) {
|
|||||||
|
|
||||||
static int client_context_read_label(
|
static int client_context_read_label(
|
||||||
ClientContext *c,
|
ClientContext *c,
|
||||||
const char *label, size_t label_size) {
|
const char *label) {
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
assert(pid_is_valid(c->pid));
|
assert(pid_is_valid(c->pid));
|
||||||
assert(label_size == 0 || label);
|
|
||||||
|
|
||||||
if (!mac_selinux_use())
|
if (!mac_selinux_use())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (label_size > 0) {
|
if (label) {
|
||||||
char *l;
|
|
||||||
|
|
||||||
/* If we got an SELinux label passed in it counts. */
|
/* If we got an SELinux label passed in it counts. */
|
||||||
|
r = free_and_strdup(&c->label, label);
|
||||||
l = newdup_suffix0(char, label, label_size);
|
if (r < 0)
|
||||||
if (!l)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
free_and_replace(c->label, l);
|
|
||||||
c->label_size = label_size;
|
|
||||||
}
|
}
|
||||||
#if HAVE_SELINUX
|
#if HAVE_SELINUX
|
||||||
else {
|
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 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);
|
free_and_replace(c->label, con);
|
||||||
c->label_size = strlen(c->label);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -533,7 +525,7 @@ static void client_context_really_refresh(
|
|||||||
Manager *m,
|
Manager *m,
|
||||||
ClientContext *c,
|
ClientContext *c,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const char *label, size_t label_size,
|
const char *label,
|
||||||
const char *unit_id,
|
const char *unit_id,
|
||||||
usec_t timestamp) {
|
usec_t timestamp) {
|
||||||
|
|
||||||
@ -546,7 +538,7 @@ static void client_context_really_refresh(
|
|||||||
|
|
||||||
client_context_read_uid_gid(c, ucred);
|
client_context_read_uid_gid(c, ucred);
|
||||||
client_context_read_basic(c);
|
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_session_from_pid(&PIDREF_MAKE_FROM_PID(c->pid), &c->auditid);
|
||||||
(void) audit_loginuid_from_pid(&PIDREF_MAKE_FROM_PID(c->pid), &c->loginuid);
|
(void) audit_loginuid_from_pid(&PIDREF_MAKE_FROM_PID(c->pid), &c->loginuid);
|
||||||
@ -570,7 +562,7 @@ void client_context_maybe_refresh(
|
|||||||
Manager *m,
|
Manager *m,
|
||||||
ClientContext *c,
|
ClientContext *c,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const char *label, size_t label_size,
|
const char *label,
|
||||||
const char *unit_id,
|
const char *unit_id,
|
||||||
usec_t timestamp) {
|
usec_t timestamp) {
|
||||||
|
|
||||||
@ -602,13 +594,13 @@ void client_context_maybe_refresh(
|
|||||||
if (ucred && gid_is_valid(ucred->gid) && c->gid != ucred->gid)
|
if (ucred && gid_is_valid(ucred->gid) && c->gid != ucred->gid)
|
||||||
goto refresh;
|
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;
|
goto refresh;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
refresh:
|
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) {
|
static void client_context_refresh_on_reload(Manager *m, ClientContext *c) {
|
||||||
@ -710,7 +702,7 @@ static int client_context_get_internal(
|
|||||||
Manager *m,
|
Manager *m,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const char *label, size_t label_len,
|
const char *label,
|
||||||
const char *unit_id,
|
const char *unit_id,
|
||||||
bool add_ref,
|
bool add_ref,
|
||||||
ClientContext **ret) {
|
ClientContext **ret) {
|
||||||
@ -738,7 +730,7 @@ static int client_context_get_internal(
|
|||||||
c->n_ref++;
|
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;
|
*ret = c;
|
||||||
return 0;
|
return 0;
|
||||||
@ -762,7 +754,7 @@ static int client_context_get_internal(
|
|||||||
c->in_lru = true;
|
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;
|
*ret = c;
|
||||||
return 0;
|
return 0;
|
||||||
@ -772,22 +764,22 @@ int client_context_get(
|
|||||||
Manager *m,
|
Manager *m,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const char *label, size_t label_len,
|
const char *label,
|
||||||
const char *unit_id,
|
const char *unit_id,
|
||||||
ClientContext **ret) {
|
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(
|
int client_context_acquire(
|
||||||
Manager *m,
|
Manager *m,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const char *label, size_t label_len,
|
const char *label,
|
||||||
const char *unit_id,
|
const char *unit_id,
|
||||||
ClientContext **ret) {
|
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) {
|
ClientContext *client_context_release(Manager *m, ClientContext *c) {
|
||||||
@ -829,7 +821,7 @@ void client_context_acquire_default(Manager *m) {
|
|||||||
.gid = getgid(),
|
.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)
|
if (r < 0)
|
||||||
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
||||||
"Failed to acquire our own context, ignoring: %m");
|
"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
|
/* 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. */
|
* 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)
|
if (r < 0)
|
||||||
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
||||||
"Failed to acquire PID1's context, ignoring: %m");
|
"Failed to acquire PID1's context, ignoring: %m");
|
||||||
|
|||||||
@ -39,7 +39,6 @@ typedef struct ClientContext {
|
|||||||
sd_id128_t invocation_id;
|
sd_id128_t invocation_id;
|
||||||
|
|
||||||
char *label;
|
char *label;
|
||||||
size_t label_size;
|
|
||||||
|
|
||||||
int log_level_max;
|
int log_level_max;
|
||||||
|
|
||||||
@ -61,7 +60,7 @@ int client_context_get(
|
|||||||
Manager *m,
|
Manager *m,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const char *label, size_t label_len,
|
const char *label,
|
||||||
const char *unit_id,
|
const char *unit_id,
|
||||||
ClientContext **ret);
|
ClientContext **ret);
|
||||||
|
|
||||||
@ -69,7 +68,7 @@ int client_context_acquire(
|
|||||||
Manager *m,
|
Manager *m,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const char *label, size_t label_len,
|
const char *label,
|
||||||
const char *unit_id,
|
const char *unit_id,
|
||||||
ClientContext **ret);
|
ClientContext **ret);
|
||||||
|
|
||||||
@ -79,7 +78,7 @@ void client_context_maybe_refresh(
|
|||||||
Manager *m,
|
Manager *m,
|
||||||
ClientContext *c,
|
ClientContext *c,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const char *label, size_t label_size,
|
const char *label,
|
||||||
const char *unit_id,
|
const char *unit_id,
|
||||||
usec_t timestamp);
|
usec_t timestamp);
|
||||||
|
|
||||||
|
|||||||
@ -85,28 +85,23 @@ void manager_forward_kmsg(
|
|||||||
log_debug_errno(errno, "Failed to write to /dev/kmsg for logging, ignoring: %m");
|
log_debug_errno(errno, "Failed to write to /dev/kmsg for logging, ignoring: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_us(const char *identifier, const char *pid) {
|
static bool is_us(const char *identifier, pid_t pid) {
|
||||||
pid_t pid_num;
|
if (!identifier || !pid_is_valid(pid))
|
||||||
|
|
||||||
if (!identifier || !pid)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (parse_pid(pid, &pid_num) < 0)
|
return pid == getpid_cached() &&
|
||||||
return false;
|
|
||||||
|
|
||||||
return pid_num == getpid_cached() &&
|
|
||||||
streq(identifier, program_invocation_short_name);
|
streq(identifier, program_invocation_short_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dev_kmsg_record(Manager *m, char *p, size_t l) {
|
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];
|
struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS];
|
||||||
char *kernel_device = NULL;
|
char *kernel_device = NULL;
|
||||||
unsigned long long usec;
|
unsigned long long usec;
|
||||||
size_t n = 0, z = 0, j;
|
size_t n = 0, z = 0, j;
|
||||||
int priority, r;
|
int priority, r;
|
||||||
char *e, *k;
|
char *e, *k, syslog_pid[STRLEN("SYSLOG_PID=") + DECIMAL_STR_MAX(pid_t)];
|
||||||
uint64_t serial;
|
uint64_t serial;
|
||||||
size_t pl;
|
size_t pl;
|
||||||
int saved_log_max_level = INT_MAX;
|
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)
|
if (LOG_FAC(priority) == LOG_KERN)
|
||||||
iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=kernel");
|
iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=kernel");
|
||||||
else {
|
else {
|
||||||
|
_cleanup_free_ char *identifier = NULL;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid);
|
pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid);
|
||||||
|
|
||||||
/* Avoid logging any new messages when we're processing messages generated by ourselves via
|
/* 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);
|
iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid) {
|
if (pid_is_valid(pid)) {
|
||||||
syslog_pid = strjoin("SYSLOG_PID=", pid);
|
xsprintf(syslog_pid, "SYSLOG_PID="PID_FMT, pid);
|
||||||
if (syslog_pid)
|
iovec[n++] = IOVEC_MAKE_STRING(syslog_pid);
|
||||||
iovec[n++] = IOVEC_MAKE_STRING(syslog_pid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,7 @@
|
|||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
|
#include "selinux-util.h"
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
@ -1058,14 +1059,6 @@ static void manager_write_to_journal(
|
|||||||
iovec[n++] = IOVEC_MAKE_STRING(k); \
|
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(
|
static void manager_dispatch_message_real(
|
||||||
Manager *m,
|
Manager *m,
|
||||||
struct iovec *iovec, size_t n, size_t mm,
|
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);
|
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_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->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");
|
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);
|
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->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");
|
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);
|
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_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->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");
|
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,
|
uint32_t revents,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
size_t label_len = 0, mm;
|
size_t mm;
|
||||||
Manager *m = ASSERT_PTR(userdata);
|
Manager *m = ASSERT_PTR(userdata);
|
||||||
struct ucred *ucred = NULL;
|
struct ucred *ucred = NULL;
|
||||||
struct timeval tv_buf, *tv = NULL;
|
struct timeval tv_buf, *tv = NULL;
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
char *label = NULL;
|
_cleanup_free_ char *label = NULL;
|
||||||
struct iovec iovec;
|
struct iovec iovec;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
int *fds = NULL, v = 0;
|
int *fds = NULL, v = 0;
|
||||||
@ -1561,10 +1554,11 @@ int manager_process_datagram(
|
|||||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
|
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
|
||||||
assert(!ucred);
|
assert(!ucred);
|
||||||
ucred = CMSG_TYPED_DATA(cmsg, struct 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);
|
assert(!label);
|
||||||
label = CMSG_TYPED_DATA(cmsg, char);
|
/* Here, we ignore any errors including OOM, as the field is optional. */
|
||||||
label_len = cmsg->cmsg_len - CMSG_LEN(0);
|
(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 &&
|
} else if (cmsg->cmsg_type == SCM_TIMESTAMP &&
|
||||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) {
|
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) {
|
||||||
assert(!tv);
|
assert(!tv);
|
||||||
@ -1581,7 +1575,7 @@ int manager_process_datagram(
|
|||||||
|
|
||||||
if (fd == m->syslog_fd) {
|
if (fd == m->syslog_fd) {
|
||||||
if (n > 0 && n_fds == 0)
|
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)
|
else if (n_fds > 0)
|
||||||
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
|
||||||
"Got file descriptors via syslog socket. Ignoring.");
|
"Got file descriptors via syslog socket. Ignoring.");
|
||||||
@ -1591,9 +1585,9 @@ int manager_process_datagram(
|
|||||||
|
|
||||||
} else if (fd == m->native_fd) {
|
} else if (fd == m->native_fd) {
|
||||||
if (n > 0 && n_fds == 0)
|
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)
|
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)
|
else if (n_fds > 0)
|
||||||
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
|
||||||
"Got too many file descriptors via native socket. Ignoring.");
|
"Got too many file descriptors via native socket. Ignoring.");
|
||||||
|
|||||||
@ -98,7 +98,7 @@ static int manager_process_entry(
|
|||||||
ClientContext *context,
|
ClientContext *context,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const struct timeval *tv,
|
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
|
/* 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.
|
* 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 char *buffer, size_t buffer_size,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const struct timeval *tv,
|
const struct timeval *tv,
|
||||||
const char *label, size_t label_len) {
|
const char *label) {
|
||||||
|
|
||||||
size_t remaining = buffer_size;
|
size_t remaining = buffer_size;
|
||||||
ClientContext *context = NULL;
|
ClientContext *context = NULL;
|
||||||
@ -314,7 +314,7 @@ void manager_process_native_message(
|
|||||||
assert(buffer || buffer_size == 0);
|
assert(buffer || buffer_size == 0);
|
||||||
|
|
||||||
if (ucred && pid_is_valid(ucred->pid)) {
|
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)
|
if (r < 0)
|
||||||
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
||||||
"Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m",
|
"Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m",
|
||||||
@ -324,7 +324,7 @@ void manager_process_native_message(
|
|||||||
do {
|
do {
|
||||||
r = manager_process_entry(m,
|
r = manager_process_entry(m,
|
||||||
(const uint8_t*) buffer + (buffer_size - remaining), &remaining,
|
(const uint8_t*) buffer + (buffer_size - remaining), &remaining,
|
||||||
context, ucred, tv, label, label_len);
|
context, ucred, tv, label);
|
||||||
} while (r == 0);
|
} while (r == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ int manager_process_native_file(
|
|||||||
int fd,
|
int fd,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const struct timeval *tv,
|
const struct timeval *tv,
|
||||||
const char *label, size_t label_len) {
|
const char *label) {
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
bool sealed;
|
bool sealed;
|
||||||
@ -410,7 +410,7 @@ int manager_process_native_file(
|
|||||||
return log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT,
|
return log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT,
|
||||||
"Failed to map memfd: %m");
|
"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);
|
assert_se(munmap(p, ps) >= 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -451,7 +451,7 @@ int manager_process_native_file(
|
|||||||
return log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT,
|
return log_ratelimit_error_errno(errno, JOURNAL_LOG_RATELIMIT,
|
||||||
"Failed to read file: %m");
|
"Failed to read file: %m");
|
||||||
if (n > 0)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,15 +9,13 @@ void manager_process_native_message(
|
|||||||
size_t buffer_size,
|
size_t buffer_size,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const struct timeval *tv,
|
const struct timeval *tv,
|
||||||
const char *label,
|
const char *label);
|
||||||
size_t label_len);
|
|
||||||
|
|
||||||
int manager_process_native_file(
|
int manager_process_native_file(
|
||||||
Manager *m,
|
Manager *m,
|
||||||
int fd,
|
int fd,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const struct timeval *tv,
|
const struct timeval *tv,
|
||||||
const char *label,
|
const char *label);
|
||||||
size_t label_len);
|
|
||||||
|
|
||||||
int manager_open_native_socket(Manager *m, const char *native_socket);
|
int manager_open_native_socket(Manager *m, const char *native_socket);
|
||||||
|
|||||||
@ -228,9 +228,9 @@ static int stdout_stream_log(
|
|||||||
assert(line_break < _LINE_BREAK_MAX);
|
assert(line_break < _LINE_BREAK_MAX);
|
||||||
|
|
||||||
if (s->context)
|
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)) {
|
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)
|
if (r < 0)
|
||||||
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
||||||
"Failed to acquire client context, ignoring: %m");
|
"Failed to acquire client context, ignoring: %m");
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include "journald-wall.h"
|
#include "journald-wall.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "log-ratelimit.h"
|
#include "log-ratelimit.h"
|
||||||
|
#include "parse-util.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "selinux-util.h"
|
#include "selinux-util.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
@ -200,14 +201,14 @@ int syslog_fixup_facility(int priority) {
|
|||||||
return 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;
|
const char *p;
|
||||||
char *t;
|
|
||||||
size_t l, e;
|
size_t l, e;
|
||||||
|
pid_t pid = 0;
|
||||||
|
|
||||||
assert(buf);
|
assert(buf);
|
||||||
assert(identifier);
|
assert(ret_identifier);
|
||||||
assert(pid);
|
assert(ret_pid);
|
||||||
|
|
||||||
p = *buf;
|
p = *buf;
|
||||||
|
|
||||||
@ -215,8 +216,11 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
|
|||||||
l = strcspn(p, WHITESPACE);
|
l = strcspn(p, WHITESPACE);
|
||||||
|
|
||||||
if (l <= 0 ||
|
if (l <= 0 ||
|
||||||
p[l-1] != ':')
|
p[l-1] != ':') {
|
||||||
|
*ret_identifier = NULL;
|
||||||
|
*ret_pid = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
e = l;
|
e = l;
|
||||||
l--;
|
l--;
|
||||||
@ -227,9 +231,9 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
if (p[k] == '[') {
|
if (p[k] == '[') {
|
||||||
t = strndup(p+k+1, l-k-2);
|
_cleanup_free_ char *t = strndup(p+k+1, l-k-2);
|
||||||
if (t)
|
if (t)
|
||||||
*pid = t;
|
(void) parse_pid(t, &pid);
|
||||||
|
|
||||||
l = k;
|
l = k;
|
||||||
break;
|
break;
|
||||||
@ -242,9 +246,13 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t = strndup(p, l);
|
/* The syslog identifier should be short enough in most cases and NAME_MAX should be enough. Let's
|
||||||
if (t)
|
* refuse ridiculously long identifier string as "no identifier string found", because if it is
|
||||||
*identifier = t;
|
* 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 */
|
/* Single space is used as separator */
|
||||||
if (p[e] != '\0' && strchr(WHITESPACE, p[e]))
|
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;
|
l = (p - *buf) + e;
|
||||||
*buf = p + e;
|
*buf = p + e;
|
||||||
|
*ret_identifier = TAKE_PTR(identifier);
|
||||||
|
*ret_pid = pid;
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int syslog_skip_timestamp(const char **buf) {
|
static size_t syslog_skip_timestamp(const char **buf) {
|
||||||
enum {
|
enum {
|
||||||
LETTER,
|
LETTER,
|
||||||
SPACE,
|
SPACE,
|
||||||
@ -275,8 +285,8 @@ static int syslog_skip_timestamp(const char **buf) {
|
|||||||
SPACE
|
SPACE
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *p, *t;
|
const char *p;
|
||||||
unsigned i;
|
size_t i;
|
||||||
|
|
||||||
assert(buf);
|
assert(buf);
|
||||||
assert(*buf);
|
assert(*buf);
|
||||||
@ -313,13 +323,15 @@ static int syslog_skip_timestamp(const char **buf) {
|
|||||||
if (*p != ':')
|
if (*p != ':')
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t = *buf;
|
assert(p >= *buf);
|
||||||
|
size_t n = p - *buf;
|
||||||
|
assert(n <= ELEMENTSOF(sequence));
|
||||||
|
|
||||||
*buf = p;
|
*buf = p;
|
||||||
return p - t;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void manager_process_syslog_message(
|
void manager_process_syslog_message(
|
||||||
@ -328,14 +340,12 @@ void manager_process_syslog_message(
|
|||||||
size_t raw_len,
|
size_t raw_len,
|
||||||
const struct ucred *ucred,
|
const struct ucred *ucred,
|
||||||
const struct timeval *tv,
|
const struct timeval *tv,
|
||||||
const char *label,
|
const char *label) {
|
||||||
size_t label_len) {
|
|
||||||
|
|
||||||
char *t, syslog_priority[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int)],
|
char *t, syslog_priority[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int)],
|
||||||
syslog_facility[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
|
syslog_facility[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)];
|
||||||
const char *msg, *syslog_ts, *a;
|
const char *msg, *syslog_ts, *a;
|
||||||
_cleanup_free_ char *identifier = NULL, *pid = NULL,
|
_cleanup_free_ char *dummy = NULL, *msg_msg = NULL, *msg_raw = NULL;
|
||||||
*dummy = NULL, *msg_msg = NULL, *msg_raw = NULL;
|
|
||||||
int priority = LOG_USER | LOG_INFO, r;
|
int priority = LOG_USER | LOG_INFO, r;
|
||||||
ClientContext *context = NULL;
|
ClientContext *context = NULL;
|
||||||
struct iovec *iovec;
|
struct iovec *iovec;
|
||||||
@ -351,7 +361,7 @@ void manager_process_syslog_message(
|
|||||||
assert(buf[raw_len] == '\0');
|
assert(buf[raw_len] == '\0');
|
||||||
|
|
||||||
if (ucred && pid_is_valid(ucred->pid)) {
|
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)
|
if (r < 0)
|
||||||
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
|
||||||
"Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m",
|
"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 */
|
/* We failed to parse the full timestamp, store the raw message too */
|
||||||
store_raw = true;
|
store_raw = true;
|
||||||
|
|
||||||
|
_cleanup_free_ char *identifier = NULL;
|
||||||
|
pid_t pid;
|
||||||
syslog_parse_identifier(&msg, &identifier, &pid);
|
syslog_parse_identifier(&msg, &identifier, &pid);
|
||||||
|
|
||||||
if (client_context_check_keep_log(context, msg, strlen(msg)) <= 0)
|
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);
|
iovec[n++] = IOVEC_MAKE_STRING(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid) {
|
char syslog_pid[STRLEN("SYSLOG_PID=") + DECIMAL_STR_MAX(pid_t)];
|
||||||
a = strjoina("SYSLOG_PID=", pid);
|
if (pid_is_valid(pid)) {
|
||||||
iovec[n++] = IOVEC_MAKE_STRING(a);
|
xsprintf(syslog_pid, "SYSLOG_PID="PID_FMT, pid);
|
||||||
|
iovec[n++] = IOVEC_MAKE_STRING(syslog_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (syslog_ts_len > 0) {
|
if (syslog_ts_len > 0) {
|
||||||
|
|||||||
@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
int syslog_fixup_facility(int priority) _const_;
|
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_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);
|
int manager_open_syslog_socket(Manager *m, const char *syslog_socket);
|
||||||
|
|
||||||
void manager_maybe_warn_forward_syslog_missed(Manager *m);
|
void manager_maybe_warn_forward_syslog_missed(Manager *m);
|
||||||
|
|||||||
@ -5,18 +5,24 @@
|
|||||||
#include "syslog-util.h"
|
#include "syslog-util.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
|
||||||
static void test_syslog_parse_identifier_one(const char *str,
|
static void test_syslog_parse_identifier_one(
|
||||||
const char *ident, const char *pid, const char *rest, int ret) {
|
const char *str,
|
||||||
|
const char *ident,
|
||||||
|
pid_t pid,
|
||||||
|
const char *rest,
|
||||||
|
int ret) {
|
||||||
|
|
||||||
const char *buf = str;
|
const char *buf = str;
|
||||||
_cleanup_free_ char *ident2 = NULL, *pid2 = NULL;
|
_cleanup_free_ char *ident2 = NULL;
|
||||||
|
pid_t pid2;
|
||||||
int ret2;
|
int ret2;
|
||||||
|
|
||||||
ret2 = syslog_parse_identifier(&buf, &ident2, &pid2);
|
ret2 = syslog_parse_identifier(&buf, &ident2, &pid2);
|
||||||
|
|
||||||
assert_se(ret == ret2);
|
ASSERT_EQ(ret, ret2);
|
||||||
assert_se(ident == ident2 || streq_ptr(ident, ident2));
|
ASSERT_STREQ(ident, ident2);
|
||||||
assert_se(pid == pid2 || streq_ptr(pid, pid2));
|
ASSERT_EQ(pid, pid2);
|
||||||
assert_se(streq(buf, rest));
|
ASSERT_STREQ(buf, rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_syslog_parse_priority_one(const char *str, bool with_facility, int priority, int ret) {
|
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) {
|
||||||
test_syslog_parse_identifier_one("pidu[111]: xxx", "pidu", "111", "xxx", 11);
|
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", 0, "xxx", 6);
|
||||||
test_syslog_parse_identifier_one("pidu: xxx", "pidu", NULL, " xxx", 6);
|
test_syslog_parse_identifier_one("pidu: xxx", "pidu", 0, " xxx", 6);
|
||||||
test_syslog_parse_identifier_one("pidu xxx", NULL, NULL, "pidu xxx", 0);
|
test_syslog_parse_identifier_one("pidu xxx", NULL, 0, "pidu xxx", 0);
|
||||||
test_syslog_parse_identifier_one(" pidu xxx", NULL, NULL, " pidu xxx", 0);
|
test_syslog_parse_identifier_one(" pidu xxx", NULL, 0, " pidu xxx", 0);
|
||||||
test_syslog_parse_identifier_one("", NULL, NULL, "", 0);
|
test_syslog_parse_identifier_one("", NULL, 0, "", 0);
|
||||||
test_syslog_parse_identifier_one(" ", NULL, NULL, " ", 0);
|
test_syslog_parse_identifier_one(" ", NULL, 0, " ", 0);
|
||||||
test_syslog_parse_identifier_one(":", "", NULL, "", 1);
|
test_syslog_parse_identifier_one(":", "", 0, "", 1);
|
||||||
test_syslog_parse_identifier_one(": ", "", NULL, " ", 2);
|
test_syslog_parse_identifier_one(": ", "", 0, " ", 2);
|
||||||
test_syslog_parse_identifier_one(" :", "", NULL, "", 2);
|
test_syslog_parse_identifier_one(" :", "", 0, "", 2);
|
||||||
test_syslog_parse_identifier_one(" pidu:", "pidu", NULL, "", 8);
|
test_syslog_parse_identifier_one(" pidu:", "pidu", 0, "", 8);
|
||||||
test_syslog_parse_identifier_one("pidu:", "pidu", NULL, "", 5);
|
test_syslog_parse_identifier_one("pidu:", "pidu", 0, "", 5);
|
||||||
test_syslog_parse_identifier_one("pidu: ", "pidu", NULL, "", 6);
|
test_syslog_parse_identifier_one("pidu: ", "pidu", 0, "", 6);
|
||||||
test_syslog_parse_identifier_one("pidu : ", NULL, NULL, "pidu : ", 0);
|
test_syslog_parse_identifier_one("pidu : ", NULL, 0, "pidu : ", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(syslog_parse_priority) {
|
TEST(syslog_parse_priority) {
|
||||||
|
|||||||
@ -1354,7 +1354,7 @@ static int validate_cgroup(sd_varlink *link, int fd, uint64_t *ret_cgroup_id) {
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
return sd_varlink_error_invalid_parameter_name(link, "controlGroupFileDescriptor");
|
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)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to read cgroup ID from cgroupfs: %m");
|
return log_debug_errno(r, "Failed to read cgroup ID from cgroupfs: %m");
|
||||||
|
|
||||||
|
|||||||
@ -2047,7 +2047,7 @@ int portable_attach(
|
|||||||
|
|
||||||
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && !FLAGS_SET(flags, PORTABLE_FORCE_ATTACH))
|
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && !FLAGS_SET(flags, PORTABLE_FORCE_ATTACH))
|
||||||
HASHMAP_FOREACH(item, unit_files) {
|
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)
|
if (r < 0)
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name);
|
return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name);
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
|
|||||||
@ -61,7 +61,6 @@
|
|||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
#include "uid-classification.h"
|
|
||||||
#include "unit-def.h"
|
#include "unit-def.h"
|
||||||
#include "unit-name.h"
|
#include "unit-name.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
@ -2248,9 +2247,6 @@ static int fchown_to_capsule(int fd, const char *capsule) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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);
|
return fchmod_and_chown(fd, 0600, st.st_uid, st.st_gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,6 @@
|
|||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "time-util.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) {
|
static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *reterr_error) {
|
||||||
sd_event *e = ASSERT_PTR(userdata);
|
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)
|
if (!p)
|
||||||
return -ENOMEM;
|
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);
|
r = chase(p, /* root= */ NULL, CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS, /* ret_path= */ NULL, &inode_fd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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)
|
if (fstat(inode_fd, &st) < 0)
|
||||||
return negative_errno();
|
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_uid = st.st_uid;
|
||||||
*ret_gid = st.st_gid;
|
*ret_gid = st.st_gid;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
#include "glyph-util.h"
|
#include "glyph-util.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "mountpoint-util.h"
|
||||||
#include "nulstr-util.h"
|
#include "nulstr-util.h"
|
||||||
#include "output-mode.h"
|
#include "output-mode.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
@ -150,7 +151,7 @@ static int show_cgroup_name(
|
|||||||
delegate = r > 0;
|
delegate = r > 0;
|
||||||
|
|
||||||
if (FLAGS_SET(flags, OUTPUT_CGROUP_ID)) {
|
if (FLAGS_SET(flags, OUTPUT_CGROUP_ID)) {
|
||||||
r = cg_fd_get_cgroupid(fd, &cgroupid);
|
r = fd_to_handle_u64(fd, &cgroupid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug_errno(r, "Failed to determine cgroup ID of %s, ignoring: %m", path);
|
log_debug_errno(r, "Failed to determine cgroup ID of %s, ignoring: %m", path);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,12 +37,6 @@
|
|||||||
|
|
||||||
#define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
|
#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 {
|
typedef struct {
|
||||||
RuntimeScope scope;
|
RuntimeScope scope;
|
||||||
OrderedHashmap *will_process;
|
OrderedHashmap *will_process;
|
||||||
@ -1563,7 +1557,7 @@ static int unit_file_search(
|
|||||||
|
|
||||||
assert(info->name);
|
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);
|
r = unit_name_template(info->name, &template);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -3242,7 +3236,7 @@ int unit_file_get_state(
|
|||||||
int unit_file_exists_full(
|
int unit_file_exists_full(
|
||||||
RuntimeScope scope,
|
RuntimeScope scope,
|
||||||
const LookupPaths *lp,
|
const LookupPaths *lp,
|
||||||
bool follow,
|
SearchFlags flags,
|
||||||
const char *name,
|
const char *name,
|
||||||
char **ret_path) {
|
char **ret_path) {
|
||||||
|
|
||||||
@ -3262,7 +3256,7 @@ int unit_file_exists_full(
|
|||||||
&c,
|
&c,
|
||||||
lp,
|
lp,
|
||||||
name,
|
name,
|
||||||
follow ? SEARCH_FOLLOW_CONFIG_SYMLINKS : 0,
|
flags,
|
||||||
ret_path ? &info : NULL,
|
ret_path ? &info : NULL,
|
||||||
/* changes= */ NULL,
|
/* changes= */ NULL,
|
||||||
/* n_changes= */ NULL);
|
/* n_changes= */ NULL);
|
||||||
|
|||||||
@ -39,6 +39,13 @@ typedef enum UnitFileFlags {
|
|||||||
_UNIT_FILE_FLAGS_MASK_PUBLIC = UNIT_FILE_RUNTIME|UNIT_FILE_PORTABLE|UNIT_FILE_FORCE,
|
_UNIT_FILE_FLAGS_MASK_PUBLIC = UNIT_FILE_RUNTIME|UNIT_FILE_PORTABLE|UNIT_FILE_FORCE,
|
||||||
} UnitFileFlags;
|
} 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
|
/* type can be either one of the INSTALL_CHANGE_SYMLINK, INSTALL_CHANGE_UNLINK, … listed above, or a negative
|
||||||
* errno value.
|
* 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(
|
int unit_file_exists_full(
|
||||||
RuntimeScope scope,
|
RuntimeScope scope,
|
||||||
const LookupPaths *lp,
|
const LookupPaths *lp,
|
||||||
bool follow,
|
SearchFlags flags,
|
||||||
const char *name,
|
const char *name,
|
||||||
char **ret_path);
|
char **ret_path);
|
||||||
|
|
||||||
static inline int unit_file_exists(RuntimeScope scope, const LookupPaths *lp, const char *name) {
|
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);
|
int unit_file_get_list(RuntimeScope scope, const char *root_dir, char * const *states, char * const *patterns, Hashmap **ret);
|
||||||
|
|||||||
@ -56,3 +56,14 @@ int plymouth_send_msg(const char *text, bool pause_spinner) {
|
|||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
int plymouth_connect(int flags);
|
int plymouth_connect(int flags);
|
||||||
int plymouth_send_raw(const void *raw, size_t size, 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_send_msg(const char *text, bool pause_spinner);
|
||||||
|
int plymouth_hide_splash(void);
|
||||||
|
|
||||||
static inline bool ERRNO_IS_NO_PLYMOUTH(int r) {
|
static inline bool ERRNO_IS_NO_PLYMOUTH(int r) {
|
||||||
return IN_SET(ABS(r), EAGAIN, ENOENT) || ERRNO_IS_DISCONNECT(r);
|
return IN_SET(ABS(r), EAGAIN, ENOENT) || ERRNO_IS_DISCONNECT(r);
|
||||||
|
|||||||
@ -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;
|
_cleanup_free_ char *found_sshd_template_unit = NULL;
|
||||||
r = unit_file_exists_full(RUNTIME_SCOPE_SYSTEM, &lp,
|
r = unit_file_exists_full(RUNTIME_SCOPE_SYSTEM, &lp,
|
||||||
/* follow = */ true,
|
SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||||
"sshd@.service",
|
"sshd@.service",
|
||||||
&found_sshd_template_unit);
|
&found_sshd_template_unit);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
|
#include "mountpoint-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pidref.h"
|
#include "pidref.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
@ -493,7 +494,7 @@ TEST(cgroupid) {
|
|||||||
ASSERT_OK(fd_get_path(fd, &p));
|
ASSERT_OK(fd_get_path(fd, &p));
|
||||||
ASSERT_TRUE(path_equal(p, "/sys/fs/cgroup"));
|
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);
|
fd2 = cg_cgroupid_open(fd, id);
|
||||||
|
|
||||||
@ -509,7 +510,7 @@ TEST(cgroupid) {
|
|||||||
ASSERT_OK(fd_get_path(fd2, &p2));
|
ASSERT_OK(fd_get_path(fd2, &p2));
|
||||||
ASSERT_TRUE(path_equal(p2, "/sys/fs/cgroup"));
|
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);
|
ASSERT_EQ(id, id2);
|
||||||
|
|
||||||
|
|||||||
@ -218,6 +218,8 @@ Manager* manager_free(Manager *manager) {
|
|||||||
|
|
||||||
sd_event_source_unref(manager->inotify_event);
|
sd_event_source_unref(manager->inotify_event);
|
||||||
set_free(manager->synthesize_change_child_event_sources);
|
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_source_unref(manager->kill_workers_event);
|
||||||
sd_event_unref(manager->event);
|
sd_event_unref(manager->event);
|
||||||
|
|
||||||
@ -895,6 +897,11 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
|
|||||||
assert(manager);
|
assert(manager);
|
||||||
assert(dev);
|
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. */
|
/* We only accepts devices received by device monitor. */
|
||||||
r = sd_device_get_seqnum(dev, &seqnum);
|
r = sd_device_get_seqnum(dev, &seqnum);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -962,14 +969,6 @@ static int event_queue_insert(Manager *manager, sd_device *dev) {
|
|||||||
TAKE_PTR(event);
|
TAKE_PTR(event);
|
||||||
log_device_uevent(dev, "Device is queued");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1068,6 +1067,9 @@ static int manager_deserialize_events(Manager *manager, int *fd) {
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n > 0)
|
||||||
|
(void) manager_create_queue_file(manager);
|
||||||
|
|
||||||
log_debug("Deserialized %"PRIu64" events.", n);
|
log_debug("Deserialized %"PRIu64" events.", n);
|
||||||
return 0;
|
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);
|
DEVICE_TRACE_POINT(kernel_uevent_received, dev);
|
||||||
|
|
||||||
|
(void) manager_create_queue_file(manager);
|
||||||
|
|
||||||
device_ensure_usec_initialized(dev, NULL);
|
device_ensure_usec_initialized(dev, NULL);
|
||||||
|
|
||||||
r = event_queue_insert(manager, dev);
|
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;
|
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) {
|
static int manager_unlink_queue_file(Manager *manager) {
|
||||||
assert(manager);
|
assert(manager);
|
||||||
|
|
||||||
@ -1265,6 +1285,9 @@ static int manager_unlink_queue_file(Manager *manager) {
|
|||||||
if (!set_isempty(manager->synthesize_change_child_event_sources))
|
if (!set_isempty(manager->synthesize_change_child_event_sources))
|
||||||
return 0; /* There are child processes that should trigger synthetic events. */
|
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. */
|
/* There are no queued events. Let's remove /run/udev/queue and clean up the idle processes. */
|
||||||
if (unlink("/run/udev/queue") < 0) {
|
if (unlink("/run/udev/queue") < 0) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
|
|||||||
@ -54,6 +54,8 @@ typedef struct Manager {
|
|||||||
int inotify_fd;
|
int inotify_fd;
|
||||||
sd_event_source *inotify_event;
|
sd_event_source *inotify_event;
|
||||||
Set *synthesize_change_child_event_sources;
|
Set *synthesize_change_child_event_sources;
|
||||||
|
Set *synthesized_events;
|
||||||
|
sd_event_source *synthesized_events_clear_event_source;
|
||||||
|
|
||||||
sd_event_source *kill_workers_event;
|
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);
|
bool devpath_conflict(const char *a, const char *b);
|
||||||
|
|
||||||
int manager_requeue_locked_events_by_device(Manager *manager, sd_device *dev);
|
int manager_requeue_locked_events_by_device(Manager *manager, sd_device *dev);
|
||||||
|
|
||||||
|
int manager_create_queue_file(Manager *manager);
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
|
#include "id128-util.h"
|
||||||
#include "inotify-util.h"
|
#include "inotify-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "pidref.h"
|
#include "pidref.h"
|
||||||
@ -28,6 +29,7 @@
|
|||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
#include "time-util.h"
|
||||||
#include "udev-manager.h"
|
#include "udev-manager.h"
|
||||||
#include "udev-trace.h"
|
#include "udev-trace.h"
|
||||||
#include "udev-util.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;
|
int r;
|
||||||
|
|
||||||
|
assert(manager);
|
||||||
assert(dev);
|
assert(dev);
|
||||||
assert(target);
|
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
if (DEBUG_LOGGING) {
|
||||||
const char *syspath = NULL;
|
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));
|
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)
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,13 +228,13 @@ static int synthesize_change(Manager *manager, sd_device *dev) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
return synthesize_change_one(dev, dev);
|
return synthesize_change_one(manager, dev);
|
||||||
|
|
||||||
r = block_device_is_whole_disk(dev);
|
r = block_device_is_whole_disk(dev);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return synthesize_change_one(dev, dev);
|
return synthesize_change_one(manager, dev);
|
||||||
|
|
||||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||||
r = pidref_safe_fork(
|
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);
|
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) manager_requeue_locked_events_by_device(manager, dev);
|
||||||
(void) synthesize_change(manager, dev);
|
(void) synthesize_change(manager, dev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -2451,9 +2451,11 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
|
||||||
r = strv_prepend(&arg_kernel_cmdline_extra, "console=hvc0");
|
if (arg_console_mode != CONSOLE_GUI) {
|
||||||
if (r < 0)
|
r = strv_prepend(&arg_kernel_cmdline_extra, "console=hvc0");
|
||||||
return log_oom();
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t j = 0; j < arg_runtime_mounts.n_mounts; j++) {
|
for (size_t j = 0; j < arg_runtime_mounts.n_mounts; j++) {
|
||||||
RuntimeMount *m = arg_runtime_mounts.mounts + j;
|
RuntimeMount *m = arg_runtime_mounts.mounts + j;
|
||||||
|
|||||||
9
test/fuzz/.gitattributes
vendored
9
test/fuzz/.gitattributes
vendored
@ -1,10 +1,3 @@
|
|||||||
/*/* -whitespace
|
/*/* -whitespace
|
||||||
/fuzz-bus-match/* binary
|
/*/* 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
|
|
||||||
/*/* generated
|
/*/* generated
|
||||||
|
|||||||
1
test/fuzz/fuzz-journald-syslog/oss-fuzz-477990732
Normal file
1
test/fuzz/fuzz-journald-syslog/oss-fuzz-477990732
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user