mirror of
https://github.com/systemd/systemd
synced 2026-03-23 15:24:54 +01:00
Compare commits
17 Commits
d844b033a4
...
f571d9d5f0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f571d9d5f0 | ||
|
|
80362ec56f | ||
|
|
a11e7c0b4c | ||
|
|
d2e84b6018 | ||
|
|
f6f4ec7951 | ||
|
|
14f4b1b568 | ||
|
|
878e32b614 | ||
|
|
6999521ba9 | ||
|
|
cbcf371abc | ||
|
|
45a68ed307 | ||
|
|
3e24e8cd64 | ||
|
|
3bd6a01c01 | ||
|
|
6bf3c6c900 | ||
|
|
9c46228b7d | ||
|
|
becbc6dfa8 | ||
|
|
946f7ce32c | ||
|
|
ce266330fc |
3
TODO
3
TODO
@ -1189,6 +1189,9 @@ Features:
|
||||
- introduce API for "making room", that grows/shrinks home directory
|
||||
according to elastic parameters, discards blocks, and removes additional snapshots. Call it
|
||||
either from UI when disk space gets low
|
||||
- when homed is in use, maybe start the user session manager in a mount namespace with MS_SLAVE,
|
||||
so that mounts propagate down but not up - eg, user A setting up a backup volume
|
||||
doesn't mean user B sees it
|
||||
|
||||
* homed: during login resize fs automatically towards size goal. Specifically,
|
||||
resize to diskSize if possible, but leave a certain amount (configured by a
|
||||
|
||||
@ -847,6 +847,7 @@ sensor:modalias:acpi:KIOX000A*:dmi:*:svnTrekStor:pnSurfTabtwin10.1:*
|
||||
sensor:modalias:acpi:KIOX000A*:dmi:*:svnTREKSTOR*:pnPrimetabS11B:*
|
||||
sensor:modalias:acpi:KIOX000A*:dmi:*:svnTREKSTOR:pnPrimetabT13B:*
|
||||
sensor:modalias:acpi:BOSC0200*:dmi:*:svnTrekStor*:pnSurfTabtwin11.6:*
|
||||
sensor:modalias:acpi:BOSC0200*:dmi:*:svnTrekStor*:pnSurfTabduoW110.1(VT4):*
|
||||
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
|
||||
|
||||
# alternative version of Trekstor's SurfTab Twin 11.6
|
||||
|
||||
@ -73,13 +73,17 @@
|
||||
<para>To activate the NSS modules, add <literal>myhostname</literal> to the line starting with
|
||||
<literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>.</para>
|
||||
|
||||
<para>It is recommended to place <literal>myhostname</literal> either between <literal>resolve</literal>
|
||||
and "traditional" modules like <literal>dns</literal>, or after them. In the first version, well-known
|
||||
names like <literal>localhost</literal> and the machine hostname are given higher priority than the
|
||||
external configuration. This is recommended when the external DNS servers and network are not absolutely
|
||||
trusted. In the second version, external configuration is given higher priority and
|
||||
<command>nss-myhostname</command> only provides a fallback mechanism. This might be suitable in closely
|
||||
controlled networks, for example on a company LAN.</para>
|
||||
<para>It is recommended to place <literal>myhostname</literal> after <literal>file</literal> and before <literal>dns</literal>.
|
||||
This resolves well-known hostnames like <literal>localhost</literal>
|
||||
and the machine hostnames locally. It is consistent with the behaviour
|
||||
of <command>nss-resolve</command>, and still allows overriding via
|
||||
<filename>/etc/hosts</filename>.</para>
|
||||
|
||||
<para>Please keep in mind that <command>nss-myhostname</command> (and <command>nss-resolve</command>) also resolve
|
||||
in the other direction — from locally attached IP adresses to
|
||||
hostnames. If you rely on that lookup being provided by DNS, you might
|
||||
want to order things differently.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -95,10 +99,7 @@ shadow: compat systemd
|
||||
gshadow: files systemd
|
||||
|
||||
|
||||
# Either (untrusted network, see above):
|
||||
hosts: mymachines resolve [!UNAVAIL=return] files <command>myhostname</command> dns
|
||||
# Or (only trusted networks):
|
||||
hosts: mymachines resolve [!UNAVAIL=return] files dns <command>myhostname</command>
|
||||
networks: files
|
||||
|
||||
protocols: db files
|
||||
|
||||
@ -52,6 +52,12 @@
|
||||
it is still recommended (see examples below) to keep <command>nss-myhostname</command> configured in
|
||||
<filename>/etc/nsswitch.conf</filename>, to keep those names resolveable if
|
||||
<command>systemd-resolved</command> is not running.</para>
|
||||
|
||||
<para>Please keep in mind that <command>nss-myhostname</command> (and <command>nss-resolve</command>) also resolve
|
||||
in the other direction — from locally attached IP adresses to
|
||||
hostnames. If you rely on that lookup being provided by DNS, you might
|
||||
want to order things differently.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
@ -294,7 +294,7 @@
|
||||
<title>EFI Variables</title>
|
||||
|
||||
<para>The following EFI variables are defined, set and read by <command>systemd-boot</command>, under the vendor
|
||||
UUID <literal>4a67b082-0a4c-41cf-b6c7-440b29bb8c4</literal>, for communication between the OS and the boot
|
||||
UUID <literal>4a67b082-0a4c-41cf-b6c7-440b29bb8c4f</literal>, for communication between the OS and the boot
|
||||
loader:</para>
|
||||
|
||||
<variablelist class='efi-variables'>
|
||||
|
||||
@ -208,10 +208,9 @@ static int get_max_fd(void) {
|
||||
return (int) (m - 1);
|
||||
}
|
||||
|
||||
int close_all_fds(const int except[], size_t n_except) {
|
||||
int close_all_fds_full(int except[], size_t n_except, bool allow_alloc) {
|
||||
static bool have_close_range = true; /* Assume we live in the future */
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
int r = 0;
|
||||
|
||||
assert(n_except == 0 || except);
|
||||
@ -227,41 +226,19 @@ int close_all_fds(const int except[], size_t n_except) {
|
||||
/* Close everything. Yay! */
|
||||
|
||||
if (close_range(3, -1, 0) >= 0)
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
|
||||
if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno))
|
||||
have_close_range = false;
|
||||
else
|
||||
return -errno;
|
||||
|
||||
have_close_range = false;
|
||||
} else {
|
||||
_cleanup_free_ int *sorted_malloc = NULL;
|
||||
size_t n_sorted;
|
||||
int *sorted;
|
||||
typesafe_qsort(except, n_except, cmp_int);
|
||||
|
||||
assert(n_except < SIZE_MAX);
|
||||
n_sorted = n_except + 1;
|
||||
|
||||
if (n_sorted > 64) /* Use heap for large numbers of fds, stack otherwise */
|
||||
sorted = sorted_malloc = new(int, n_sorted);
|
||||
else
|
||||
sorted = newa(int, n_sorted);
|
||||
|
||||
if (sorted) {
|
||||
int c = 0;
|
||||
|
||||
memcpy(sorted, except, n_except * sizeof(int));
|
||||
|
||||
/* Let's add fd 2 to the list of fds, to simplify the loop below, as this
|
||||
* allows us to cover the head of the array the same way as the body */
|
||||
sorted[n_sorted-1] = 2;
|
||||
|
||||
typesafe_qsort(sorted, n_sorted, cmp_int);
|
||||
|
||||
for (size_t i = 0; i < n_sorted-1; i++) {
|
||||
int start, end;
|
||||
|
||||
start = MAX(sorted[i], 2); /* The first three fds shall always remain open */
|
||||
end = MAX(sorted[i+1], 2);
|
||||
for (size_t i = 0; i < n_except; i++) {
|
||||
int start = i == 0 ? 2 : MAX(except[i-1], 2); /* The first three fds shall always remain open */
|
||||
int end = MAX(except[i], 2);
|
||||
|
||||
assert(end >= start);
|
||||
|
||||
@ -270,67 +247,36 @@ int close_all_fds(const int except[], size_t n_except) {
|
||||
|
||||
/* Close everything between the start and end fds (both of which shall stay open) */
|
||||
if (close_range(start + 1, end - 1, 0) < 0) {
|
||||
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
|
||||
return -errno;
|
||||
|
||||
if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno))
|
||||
have_close_range = false;
|
||||
break;
|
||||
else
|
||||
return -errno;
|
||||
goto opendir_fallback;
|
||||
}
|
||||
}
|
||||
|
||||
c += end - start - 1;
|
||||
}
|
||||
|
||||
if (have_close_range) {
|
||||
/* The loop succeeded. Let's now close everything beyond the end */
|
||||
|
||||
if (sorted[n_sorted-1] >= INT_MAX) /* Dont let the addition below overflow */
|
||||
return c;
|
||||
if (except[n_except-1] >= INT_MAX) /* Don't let the addition below overflow */
|
||||
return 0;
|
||||
|
||||
if (close_range(sorted[n_sorted-1] + 1, -1, 0) >= 0)
|
||||
return c + 1;
|
||||
int start = MAX(except[n_except-1], 2);
|
||||
|
||||
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
|
||||
return -errno;
|
||||
if (close_range(start + 1, -1, 0) >= 0)
|
||||
return 0;
|
||||
|
||||
if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno))
|
||||
have_close_range = false;
|
||||
}
|
||||
else
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fallback on OOM or if close_range() is not supported */
|
||||
}
|
||||
|
||||
d = opendir("/proc/self/fd");
|
||||
if (!d) {
|
||||
int fd, max_fd;
|
||||
|
||||
/* When /proc isn't available (for example in chroots) the fallback is brute forcing through
|
||||
* the fd table */
|
||||
|
||||
max_fd = get_max_fd();
|
||||
if (max_fd < 0)
|
||||
return max_fd;
|
||||
|
||||
/* Refuse to do the loop over more too many elements. It's better to fail immediately than to
|
||||
* spin the CPU for a long time. */
|
||||
if (max_fd > MAX_FD_LOOP_LIMIT)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"/proc/self/fd is inaccessible. Refusing to loop over %d potential fds.",
|
||||
max_fd);
|
||||
|
||||
for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
|
||||
int q;
|
||||
|
||||
if (fd_in_set(fd, except, n_except))
|
||||
continue;
|
||||
|
||||
q = close_nointr(fd);
|
||||
if (q < 0 && q != -EBADF && r >= 0)
|
||||
r = q;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
/* Fallback for when close_range() is not supported */
|
||||
opendir_fallback:
|
||||
d = allow_alloc ? opendir("/proc/self/fd") : NULL;
|
||||
if (d) {
|
||||
struct dirent *de;
|
||||
|
||||
FOREACH_DIRENT(de, d, return -errno) {
|
||||
int fd = -1, q;
|
||||
@ -353,6 +299,34 @@ int close_all_fds(const int except[], size_t n_except) {
|
||||
r = q;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Fallback for when /proc isn't available (for example in chroots) or when we cannot allocate by
|
||||
* brute-forcing through the file descriptor table. */
|
||||
|
||||
int max_fd = get_max_fd();
|
||||
if (max_fd < 0)
|
||||
return max_fd;
|
||||
|
||||
/* Refuse to do the loop over more too many elements. It's better to fail immediately than to
|
||||
* spin the CPU for a long time. */
|
||||
if (max_fd > MAX_FD_LOOP_LIMIT)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"/proc/self/fd is inaccessible. Refusing to loop over %d potential fds.",
|
||||
max_fd);
|
||||
|
||||
for (int fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
|
||||
int q;
|
||||
|
||||
if (fd_in_set(fd, except, n_except))
|
||||
continue;
|
||||
|
||||
q = close_nointr(fd);
|
||||
if (q < 0 && q != -EBADF && r >= 0)
|
||||
r = q;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@ -56,7 +56,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
|
||||
int fd_nonblock(int fd, bool nonblock);
|
||||
int fd_cloexec(int fd, bool cloexec);
|
||||
|
||||
int close_all_fds(const int except[], size_t n_except);
|
||||
int close_all_fds_full(int except[], size_t n_except, bool allow_alloc);
|
||||
static inline int close_all_fds(int except[], size_t n_except) {
|
||||
return close_all_fds_full(except, n_except, true);
|
||||
}
|
||||
|
||||
int same_fd(int a, int b);
|
||||
|
||||
|
||||
@ -1037,34 +1037,6 @@ bool is_main_thread(void) {
|
||||
return cached > 0;
|
||||
}
|
||||
|
||||
_noreturn_ void freeze(void) {
|
||||
|
||||
log_close();
|
||||
|
||||
/* Make sure nobody waits for us on a socket anymore */
|
||||
(void) close_all_fds(NULL, 0);
|
||||
|
||||
sync();
|
||||
|
||||
/* Let's not freeze right away, but keep reaping zombies. */
|
||||
for (;;) {
|
||||
int r;
|
||||
siginfo_t si = {};
|
||||
|
||||
r = waitid(P_ALL, 0, &si, WEXITED);
|
||||
if (r < 0 && errno != EINTR)
|
||||
break;
|
||||
}
|
||||
|
||||
/* waitid() failed with an unexpected error, things are really borked. Freeze now! */
|
||||
for (;;)
|
||||
pause();
|
||||
}
|
||||
|
||||
bool oom_score_adjust_is_valid(int oa) {
|
||||
return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
|
||||
}
|
||||
|
||||
unsigned long personality_from_string(const char *p) {
|
||||
int architecture;
|
||||
|
||||
@ -1271,7 +1243,7 @@ static void restore_sigsetp(sigset_t **ssp) {
|
||||
|
||||
int safe_fork_full(
|
||||
const char *name,
|
||||
const int except_fds[],
|
||||
int except_fds[],
|
||||
size_t n_except_fds,
|
||||
ForkFlags flags,
|
||||
pid_t *ret_pid) {
|
||||
@ -1466,7 +1438,7 @@ int safe_fork_full(
|
||||
int namespace_fork(
|
||||
const char *outer_name,
|
||||
const char *inner_name,
|
||||
const int except_fds[],
|
||||
int except_fds[],
|
||||
size_t n_except_fds,
|
||||
ForkFlags flags,
|
||||
int pidns_fd,
|
||||
@ -1482,7 +1454,8 @@ int namespace_fork(
|
||||
* process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that
|
||||
* /proc/self/fd works correctly. */
|
||||
|
||||
r = safe_fork_full(outer_name, except_fds, n_except_fds, (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
|
||||
r = safe_fork_full(outer_name, except_fds, n_except_fds,
|
||||
(flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
@ -1517,86 +1490,10 @@ int namespace_fork(
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) {
|
||||
bool stdout_is_tty, stderr_is_tty;
|
||||
size_t n, i;
|
||||
va_list ap;
|
||||
char **l;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
/* Spawns a temporary TTY agent, making sure it goes away when we go away */
|
||||
|
||||
r = safe_fork_full(name,
|
||||
except,
|
||||
n_except,
|
||||
FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG,
|
||||
ret_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return 0;
|
||||
|
||||
/* In the child: */
|
||||
|
||||
stdout_is_tty = isatty(STDOUT_FILENO);
|
||||
stderr_is_tty = isatty(STDERR_FILENO);
|
||||
|
||||
if (!stdout_is_tty || !stderr_is_tty) {
|
||||
int fd;
|
||||
|
||||
/* Detach from stdout/stderr. and reopen
|
||||
* /dev/tty for them. This is important to
|
||||
* ensure that when systemctl is started via
|
||||
* popen() or a similar call that expects to
|
||||
* read EOF we actually do generate EOF and
|
||||
* not delay this indefinitely by because we
|
||||
* keep an unused copy of stdin around. */
|
||||
fd = open("/dev/tty", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
log_error_errno(errno, "Failed to open /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
|
||||
log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
|
||||
log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
safe_close_above_stdio(fd);
|
||||
}
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
/* Count arguments */
|
||||
va_start(ap, path);
|
||||
for (n = 0; va_arg(ap, char*); n++)
|
||||
;
|
||||
va_end(ap);
|
||||
|
||||
/* Allocate strv */
|
||||
l = newa(char*, n + 1);
|
||||
|
||||
/* Fill in arguments */
|
||||
va_start(ap, path);
|
||||
for (i = 0; i <= n; i++)
|
||||
l[i] = va_arg(ap, char*);
|
||||
va_end(ap);
|
||||
|
||||
execv(path, l);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int set_oom_score_adjust(int value) {
|
||||
char t[DECIMAL_STR_MAX(int)];
|
||||
|
||||
sprintf(t, "%i", value);
|
||||
xsprintf(t, "%i", value);
|
||||
|
||||
return write_string_file("/proc/self/oom_score_adj", t,
|
||||
WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
|
||||
|
||||
@ -82,10 +82,6 @@ int pid_from_same_root_fs(pid_t pid);
|
||||
|
||||
bool is_main_thread(void);
|
||||
|
||||
_noreturn_ void freeze(void);
|
||||
|
||||
bool oom_score_adjust_is_valid(int oa);
|
||||
|
||||
#ifndef PERSONALITY_INVALID
|
||||
/* personality(7) documents that 0xffffffffUL is used for querying the
|
||||
* current personality, hence let's use that here as error
|
||||
@ -168,15 +164,13 @@ typedef enum ForkFlags {
|
||||
FORK_NEW_USERNS = 1 << 13, /* Run child in its own user namespace */
|
||||
} ForkFlags;
|
||||
|
||||
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
|
||||
int safe_fork_full(const char *name, int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
|
||||
|
||||
static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
|
||||
return safe_fork_full(name, NULL, 0, flags, ret_pid);
|
||||
}
|
||||
|
||||
int namespace_fork(const char *outer_name, const char *inner_name, const int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid);
|
||||
|
||||
int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...) _sentinel_;
|
||||
int namespace_fork(const char *outer_name, const char *inner_name, int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid);
|
||||
|
||||
int set_oom_score_adjust(int value);
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/oom.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
@ -94,6 +95,10 @@ static int property_get_environment_files(
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static bool oom_score_adjust_is_valid(int oa) {
|
||||
return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
|
||||
}
|
||||
|
||||
static int property_get_oom_score_adjust(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "exec-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "log.h"
|
||||
|
||||
@ -1791,6 +1791,9 @@ static int verify_shutdown_creds(
|
||||
assert(message);
|
||||
assert(w >= 0);
|
||||
assert(w <= _INHIBIT_WHAT_MAX);
|
||||
assert(action);
|
||||
assert(action_multiple_sessions);
|
||||
assert(action_ignore_inhibit);
|
||||
|
||||
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
|
||||
if (r < 0)
|
||||
@ -1808,7 +1811,7 @@ static int verify_shutdown_creds(
|
||||
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
|
||||
interactive = flags & SD_LOGIND_INTERACTIVE;
|
||||
|
||||
if (multiple_sessions && action_multiple_sessions) {
|
||||
if (multiple_sessions) {
|
||||
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1822,16 +1825,14 @@ static int verify_shutdown_creds(
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED,
|
||||
"Access denied to root due to active block inhibitor");
|
||||
|
||||
if (action_ignore_inhibit) {
|
||||
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
}
|
||||
}
|
||||
|
||||
if (!multiple_sessions && !blocked && action) {
|
||||
if (!multiple_sessions && !blocked) {
|
||||
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1208,6 +1208,7 @@ int image_read_metadata(Image *i) {
|
||||
DISSECT_IMAGE_GENERIC_ROOT |
|
||||
DISSECT_IMAGE_REQUIRE_ROOT |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
DISSECT_IMAGE_READ_ONLY |
|
||||
DISSECT_IMAGE_USR_NO_ROOT,
|
||||
&m);
|
||||
if (r < 0)
|
||||
|
||||
@ -448,6 +448,29 @@ ExecCommandFlags exec_command_flags_from_string(const char *s) {
|
||||
return 1 << idx;
|
||||
}
|
||||
|
||||
_noreturn_ void freeze(void) {
|
||||
log_close();
|
||||
|
||||
/* Make sure nobody waits for us on a socket anymore */
|
||||
(void) close_all_fds_full(NULL, 0, false);
|
||||
|
||||
sync();
|
||||
|
||||
/* Let's not freeze right away, but keep reaping zombies. */
|
||||
for (;;) {
|
||||
int r;
|
||||
siginfo_t si = {};
|
||||
|
||||
r = waitid(P_ALL, 0, &si, WEXITED);
|
||||
if (r < 0 && errno != EINTR)
|
||||
break;
|
||||
}
|
||||
|
||||
/* waitid() failed with an unexpected error, things are really borked. Freeze now! */
|
||||
for (;;)
|
||||
pause();
|
||||
}
|
||||
|
||||
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]) {
|
||||
#if ENABLE_FEXECVE
|
||||
execveat(executable_fd, "", argv, envp, AT_EMPTY_PATH);
|
||||
@ -470,3 +493,76 @@ int fexecve_or_execve(int executable_fd, const char *executable, char *const arg
|
||||
execve(executable, argv, envp);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
int fork_agent(const char *name, int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) {
|
||||
bool stdout_is_tty, stderr_is_tty;
|
||||
size_t n, i;
|
||||
va_list ap;
|
||||
char **l;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
/* Spawns a temporary TTY agent, making sure it goes away when we go away */
|
||||
|
||||
r = safe_fork_full(name,
|
||||
except,
|
||||
n_except,
|
||||
FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG,
|
||||
ret_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return 0;
|
||||
|
||||
/* In the child: */
|
||||
|
||||
stdout_is_tty = isatty(STDOUT_FILENO);
|
||||
stderr_is_tty = isatty(STDERR_FILENO);
|
||||
|
||||
if (!stdout_is_tty || !stderr_is_tty) {
|
||||
int fd;
|
||||
|
||||
/* Detach from stdout/stderr and reopen /dev/tty for them. This is important to ensure that
|
||||
* when systemctl is started via popen() or a similar call that expects to read EOF we
|
||||
* actually do generate EOF and not delay this indefinitely by keeping an unused copy of
|
||||
* stdin around. */
|
||||
fd = open("/dev/tty", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
log_error_errno(errno, "Failed to open /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
|
||||
log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
|
||||
log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
safe_close_above_stdio(fd);
|
||||
}
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
/* Count arguments */
|
||||
va_start(ap, path);
|
||||
for (n = 0; va_arg(ap, char*); n++)
|
||||
;
|
||||
va_end(ap);
|
||||
|
||||
/* Allocate strv */
|
||||
l = newa(char*, n + 1);
|
||||
|
||||
/* Fill in arguments */
|
||||
va_start(ap, path);
|
||||
for (i = 0; i <= n; i++)
|
||||
l[i] = va_arg(ap, char*);
|
||||
va_end(ap);
|
||||
|
||||
execv(path, l);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -47,4 +47,8 @@ extern const gather_stdout_callback_t gather_environment[_STDOUT_CONSUME_MAX];
|
||||
const char* exec_command_flags_to_string(ExecCommandFlags i);
|
||||
ExecCommandFlags exec_command_flags_from_string(const char *s);
|
||||
|
||||
_noreturn_ void freeze(void);
|
||||
|
||||
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]);
|
||||
|
||||
int fork_agent(const char *name, int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) _sentinel_;
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dissect-image.h"
|
||||
#include "exec-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@ -1010,11 +1011,9 @@ static int make_userns(uid_t uid_shift, uid_t uid_range) {
|
||||
r = safe_fork("(sd-mkuserns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NEW_USERNS, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
if (r == 0)
|
||||
/* Child. We do nothing here, just freeze until somebody kills us. */
|
||||
freeze();
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
xsprintf(line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0, uid_shift, uid_range);
|
||||
|
||||
|
||||
@ -310,6 +310,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
|
||||
"getpgrp\0"
|
||||
"getpid\0"
|
||||
"getppid\0"
|
||||
"getrandom\0"
|
||||
"getresgid\0"
|
||||
"getresgid32\0"
|
||||
"getresuid\0"
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "exec-util.h"
|
||||
#include "log.h"
|
||||
#include "process-util.h"
|
||||
#include "spawn-ask-password-agent.h"
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "exec-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "io-util.h"
|
||||
#include "log.h"
|
||||
|
||||
@ -26,6 +26,7 @@ done
|
||||
|
||||
# figure out if we have entered the rate limit state
|
||||
|
||||
entered_rl=0
|
||||
exited_rl=0
|
||||
timeout="$(date -ud "2 minutes" +%s)"
|
||||
while [[ $(date -u +%s) -le ${timeout} ]]; do
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user