1
0
mirror of https://github.com/systemd/systemd synced 2026-03-23 15:24:54 +01:00

Compare commits

..

17 Commits

Author SHA1 Message Date
Frantisek Sumsal
f571d9d5f0 test: make sure we don't access an unbound variable
```
testsuite-60.sh[759]: + grep -q '(mount-monitor-dispatch) entered rate limit'
testsuite-60.sh[571]: + sleep 5
testsuite-60.sh[761]: ++ date -u +%s
testsuite-60.sh[571]: + [[ 1627037066 -le 1627037061 ]]
testsuite-60.sh[571]: /usr/lib/systemd/tests/testdata/units/testsuite-60.sh: line 41: entered_rl: unbound variable
```
2021-07-23 16:20:42 +01:00
Luca Boccassi
80362ec56f
Merge pull request #20288 from keszybz/freeze-no-malloc
Don't call malloc from freeze which is called in a signal handler
2021-07-23 15:35:34 +01:00
Luca Boccassi
a11e7c0b4c TODO: homed + user session namespace 2021-07-23 14:57:39 +01:00
ratijas
d2e84b6018 man: Fix incorrect EFI vendor UUID (last missing nibble) 2021-07-23 14:20:29 +02:00
Luca Boccassi
f6f4ec7951 discover-image: mount as read-only when extracting metadata
We don't need to modify the image, and the loopback device is already set to read-only.
2021-07-23 14:07:58 +02:00
Cristian Rodríguez
14f4b1b568 malloc() uses getrandom now
glibc master uses getrandom in malloc since https://sourceware.org/git/?p=glibc.git;a=commit;h=fc859c304898a5ec72e0ba5269ed136ed0ea10e1  ,  getrandom should be in the default set so to avoid all non trivial programs to fallback to a PRNG.
2021-07-23 12:24:57 +02:00
Franck Bui
878e32b614 logind: action* parameters can't be NULL in verify_shutdown_creds()
"action", "action_multiple_sessions" and "action_ignore_inhibit" can't be NULL
in practice so let's simplify a bit the code.

No functional change.
2021-07-23 12:10:04 +02:00
chlorophyll-zz
6999521ba9 Sensor Y Axis is inverted for TrekStor Surftab W1
IIO Sensor Y Axis is inverted for TrekStor Surftab W1.
When iio-sensor-proxy is running, up is down and down is up. 
This fixes the inversion.
2021-07-23 12:08:00 +02:00
Zbigniew Jędrzejewski-Szmek
cbcf371abc Add variant of close_all_fds() that does not allocate and use it in freeze()
Even though it's just a fallback path, let's not be sloppy and allocate in
the crash handler.

> The deadlock happens because systemd crash in malloc() then in signal
> handler, it calls malloc() (close_all_fds()-> opendir()-> __alloc_dir())
> again. malloc() is not a signal-safe function, maybe we should re-think
> the logic here.

Fixes #20266.
2021-07-23 11:39:45 +02:00
Zbigniew Jędrzejewski-Szmek
45a68ed307 Move freeze() into shared/
Library code should not call freeze(), this is something that should
only be done by "application code", so moving it into shared/ is appropriate.

The fallback to call _exit() is dropped: let's trust that the infinite loop
is infinite.
2021-07-23 11:39:45 +02:00
Zbigniew Jędrzejewski-Szmek
3e24e8cd64 Move fork_agent() into shared/
Currently it's only used in two places in src/shared/, so the function was
already included just once in compiled code. But it seems appropriate to
move it there anyway, because library code should have no need to fork
agents, so it doesn't belong in basic/.
2021-07-23 11:39:45 +02:00
Zbigniew Jędrzejewski-Szmek
3bd6a01c01 basic/process-util: use xsprintf() in one more place 2021-07-23 11:39:45 +02:00
Zbigniew Jędrzejewski-Szmek
6bf3c6c900 Make oom_score_adjust_is_valid() static
It has only one user and we don't need to put it in basic/.
2021-07-23 11:39:45 +02:00
Zbigniew Jędrzejewski-Szmek
9c46228b7d basic/fd-util: sort the 'except' array in place
We need a sorted list of fds to skip over when closing. We would allocate a
copy of the passed array to do the sort. But all callers construct a temporary
array to pass to us, so it is pointless to copy it again.

close_all_fds/safe_fork_full/namespace_fork/fork_agent are changed to pass
a non-const int array. I checked all users, and all callers are fine with
the array being sorted.

The function was returning some number (sometimes 1, sometimes the extent
of the range passed over to close_range(), ???). Anyway, all callers only
check for error, so let's return 0 on success.
2021-07-23 11:37:44 +02:00
Zbigniew Jędrzejewski-Szmek
becbc6dfa8
Merge pull request #20103 from flokli/nsswitch-nss-myhostname
man: stop recommending putting myhostname after dns
2021-07-23 09:44:26 +02:00
Florian Klink
946f7ce32c man: document nss-{resolve,myhostname} resolving in the other direction, too 2021-07-23 01:56:07 +02:00
Florian Klink
ce266330fc man: stop recommending putting myhostname after dns
nss-resolve also looks in /etc/hosts, and has the same local hostname
resolving logic as nss-myhostname. We shouldn't recommend another order
than nss-resolve uses internally.

When nss-resolve is used, there's no possibility to override
nss-myhostname hosts via DNS *anyway*.

On top of that, it's not a good idea to allow DNS to override local
hostnames as all - at least not something we should advertise in the
docs.

Followup of f918c67d38ba6ccd4eb0dc657f3f3155e5010cae /
https://github.com/systemd/systemd/pull/16754.
2021-07-23 01:53:07 +02:00
20 changed files with 217 additions and 227 deletions

3
TODO
View File

@ -1189,6 +1189,9 @@ Features:
- introduce API for "making room", that grows/shrinks home directory - introduce API for "making room", that grows/shrinks home directory
according to elastic parameters, discards blocks, and removes additional snapshots. Call it according to elastic parameters, discards blocks, and removes additional snapshots. Call it
either from UI when disk space gets low 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, * homed: during login resize fs automatically towards size goal. Specifically,
resize to diskSize if possible, but leave a certain amount (configured by a resize to diskSize if possible, but leave a certain amount (configured by a

View File

@ -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*:pnPrimetabS11B:*
sensor:modalias:acpi:KIOX000A*:dmi:*:svnTREKSTOR:pnPrimetabT13B:* sensor:modalias:acpi:KIOX000A*:dmi:*:svnTREKSTOR:pnPrimetabT13B:*
sensor:modalias:acpi:BOSC0200*:dmi:*:svnTrekStor*:pnSurfTabtwin11.6:* 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 ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
# alternative version of Trekstor's SurfTab Twin 11.6 # alternative version of Trekstor's SurfTab Twin 11.6

View File

@ -73,13 +73,17 @@
<para>To activate the NSS modules, add <literal>myhostname</literal> to the line starting with <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> <literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>.</para>
<para>It is recommended to place <literal>myhostname</literal> either between <literal>resolve</literal> <para>It is recommended to place <literal>myhostname</literal> after <literal>file</literal> and before <literal>dns</literal>.
and "traditional" modules like <literal>dns</literal>, or after them. In the first version, well-known This resolves well-known hostnames like <literal>localhost</literal>
names like <literal>localhost</literal> and the machine hostname are given higher priority than the and the machine hostnames locally. It is consistent with the behaviour
external configuration. This is recommended when the external DNS servers and network are not absolutely of <command>nss-resolve</command>, and still allows overriding via
trusted. In the second version, external configuration is given higher priority and <filename>/etc/hosts</filename>.</para>
<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>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>
<refsect1> <refsect1>
@ -95,10 +99,7 @@ shadow: compat systemd
gshadow: files systemd gshadow: files systemd
# Either (untrusted network, see above):
hosts: mymachines resolve [!UNAVAIL=return] files <command>myhostname</command> dns 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 networks: files
protocols: db files protocols: db files

View File

@ -52,6 +52,12 @@
it is still recommended (see examples below) to keep <command>nss-myhostname</command> configured in 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 <filename>/etc/nsswitch.conf</filename>, to keep those names resolveable if
<command>systemd-resolved</command> is not running.</para> <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>
<refsect1> <refsect1>

View File

@ -294,7 +294,7 @@
<title>EFI Variables</title> <title>EFI Variables</title>
<para>The following EFI variables are defined, set and read by <command>systemd-boot</command>, under the vendor <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> loader:</para>
<variablelist class='efi-variables'> <variablelist class='efi-variables'>

View File

@ -208,10 +208,9 @@ static int get_max_fd(void) {
return (int) (m - 1); 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 */ static bool have_close_range = true; /* Assume we live in the future */
_cleanup_closedir_ DIR *d = NULL; _cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r = 0; int r = 0;
assert(n_except == 0 || except); assert(n_except == 0 || except);
@ -227,129 +226,104 @@ int close_all_fds(const int except[], size_t n_except) {
/* Close everything. Yay! */ /* Close everything. Yay! */
if (close_range(3, -1, 0) >= 0) 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; return -errno;
have_close_range = false;
} else { } else {
_cleanup_free_ int *sorted_malloc = NULL; typesafe_qsort(except, n_except, cmp_int);
size_t n_sorted;
int *sorted;
assert(n_except < SIZE_MAX); for (size_t i = 0; i < n_except; i++) {
n_sorted = n_except + 1; int start = i == 0 ? 2 : MAX(except[i-1], 2); /* The first three fds shall always remain open */
int end = MAX(except[i], 2);
if (n_sorted > 64) /* Use heap for large numbers of fds, stack otherwise */ assert(end >= start);
sorted = sorted_malloc = new(int, n_sorted);
else
sorted = newa(int, n_sorted);
if (sorted) { if (end - start <= 1)
int c = 0; continue;
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);
assert(end >= start);
if (end - start <= 1)
continue;
/* 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;
/* 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))
have_close_range = false; have_close_range = false;
break; else
}
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 (close_range(sorted[n_sorted-1] + 1, -1, 0) >= 0)
return c + 1;
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
return -errno; return -errno;
goto opendir_fallback;
have_close_range = false;
} }
} }
}
/* Fallback on OOM or if close_range() is not supported */ /* The loop succeeded. Let's now close everything beyond the end */
if (except[n_except-1] >= INT_MAX) /* Don't let the addition below overflow */
return 0;
int start = MAX(except[n_except-1], 2);
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;
}
} }
d = opendir("/proc/self/fd"); /* Fallback for when close_range() is not supported */
if (!d) { opendir_fallback:
int fd, max_fd; d = allow_alloc ? opendir("/proc/self/fd") : NULL;
if (d) {
struct dirent *de;
/* When /proc isn't available (for example in chroots) the fallback is brute forcing through FOREACH_DIRENT(de, d, return -errno) {
* the fd table */ int fd = -1, q;
max_fd = get_max_fd(); if (safe_atoi(de->d_name, &fd) < 0)
if (max_fd < 0) /* Let's better ignore this, just in case */
return max_fd; continue;
/* Refuse to do the loop over more too many elements. It's better to fail immediately than to if (fd < 3)
* spin the CPU for a long time. */ continue;
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) { if (fd == dirfd(d))
int q; continue;
if (fd_in_set(fd, except, n_except)) if (fd_in_set(fd, except, n_except))
continue; continue;
q = close_nointr(fd); q = close_nointr(fd);
if (q < 0 && q != -EBADF && r >= 0) if (q < 0 && q != -EBADF && r >= 0) /* Valgrind has its own FD and doesn't want to have it closed */
r = q; r = q;
} }
return r; return r;
} }
FOREACH_DIRENT(de, d, return -errno) { /* Fallback for when /proc isn't available (for example in chroots) or when we cannot allocate by
int fd = -1, q; * brute-forcing through the file descriptor table. */
if (safe_atoi(de->d_name, &fd) < 0) int max_fd = get_max_fd();
/* Let's better ignore this, just in case */ if (max_fd < 0)
continue; return max_fd;
if (fd < 3) /* Refuse to do the loop over more too many elements. It's better to fail immediately than to
continue; * 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);
if (fd == dirfd(d)) for (int fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
continue; int q;
if (fd_in_set(fd, except, n_except)) if (fd_in_set(fd, except, n_except))
continue; continue;
q = close_nointr(fd); q = close_nointr(fd);
if (q < 0 && q != -EBADF && r >= 0) /* Valgrind has its own FD and doesn't want to have it closed */ if (q < 0 && q != -EBADF && r >= 0)
r = q; r = q;
} }

View File

@ -56,7 +56,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
int fd_nonblock(int fd, bool nonblock); int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec); 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); int same_fd(int a, int b);

View File

@ -1037,34 +1037,6 @@ bool is_main_thread(void) {
return cached > 0; 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) { unsigned long personality_from_string(const char *p) {
int architecture; int architecture;
@ -1271,7 +1243,7 @@ static void restore_sigsetp(sigset_t **ssp) {
int safe_fork_full( int safe_fork_full(
const char *name, const char *name,
const int except_fds[], int except_fds[],
size_t n_except_fds, size_t n_except_fds,
ForkFlags flags, ForkFlags flags,
pid_t *ret_pid) { pid_t *ret_pid) {
@ -1466,7 +1438,7 @@ int safe_fork_full(
int namespace_fork( int namespace_fork(
const char *outer_name, const char *outer_name,
const char *inner_name, const char *inner_name,
const int except_fds[], int except_fds[],
size_t n_except_fds, size_t n_except_fds,
ForkFlags flags, ForkFlags flags,
int pidns_fd, 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 * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that
* /proc/self/fd works correctly. */ * /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) if (r < 0)
return r; return r;
if (r == 0) { if (r == 0) {
@ -1517,86 +1490,10 @@ int namespace_fork(
return 1; 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) { int set_oom_score_adjust(int value) {
char t[DECIMAL_STR_MAX(int)]; char t[DECIMAL_STR_MAX(int)];
sprintf(t, "%i", value); xsprintf(t, "%i", value);
return write_string_file("/proc/self/oom_score_adj", t, return write_string_file("/proc/self/oom_score_adj", t,
WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER); WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);

View File

@ -82,10 +82,6 @@ int pid_from_same_root_fs(pid_t pid);
bool is_main_thread(void); bool is_main_thread(void);
_noreturn_ void freeze(void);
bool oom_score_adjust_is_valid(int oa);
#ifndef PERSONALITY_INVALID #ifndef PERSONALITY_INVALID
/* personality(7) documents that 0xffffffffUL is used for querying the /* personality(7) documents that 0xffffffffUL is used for querying the
* current personality, hence let's use that here as error * 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 */ FORK_NEW_USERNS = 1 << 13, /* Run child in its own user namespace */
} ForkFlags; } 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) { static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
return safe_fork_full(name, NULL, 0, flags, 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 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 fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...) _sentinel_;
int set_oom_score_adjust(int value); int set_oom_score_adjust(int value);

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/oom.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/prctl.h> #include <sys/prctl.h>
@ -94,6 +95,10 @@ static int property_get_environment_files(
return sd_bus_message_close_container(reply); 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( static int property_get_oom_score_adjust(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,

View File

@ -5,6 +5,7 @@
#include "sd-event.h" #include "sd-event.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "exec-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fs-util.h" #include "fs-util.h"
#include "log.h" #include "log.h"

View File

@ -1791,6 +1791,9 @@ static int verify_shutdown_creds(
assert(message); assert(message);
assert(w >= 0); assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX); 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); r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
if (r < 0) 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); blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
interactive = flags & SD_LOGIND_INTERACTIVE; 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); r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
if (r < 0) if (r < 0)
return r; return r;
@ -1822,16 +1825,14 @@ static int verify_shutdown_creds(
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED,
"Access denied to root due to active block inhibitor"); "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);
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error); if (r < 0)
if (r < 0) return r;
return r; if (r == 0)
if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
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); r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -1208,6 +1208,7 @@ int image_read_metadata(Image *i) {
DISSECT_IMAGE_GENERIC_ROOT | DISSECT_IMAGE_GENERIC_ROOT |
DISSECT_IMAGE_REQUIRE_ROOT | DISSECT_IMAGE_REQUIRE_ROOT |
DISSECT_IMAGE_RELAX_VAR_CHECK | DISSECT_IMAGE_RELAX_VAR_CHECK |
DISSECT_IMAGE_READ_ONLY |
DISSECT_IMAGE_USR_NO_ROOT, DISSECT_IMAGE_USR_NO_ROOT,
&m); &m);
if (r < 0) if (r < 0)

View File

@ -448,6 +448,29 @@ ExecCommandFlags exec_command_flags_from_string(const char *s) {
return 1 << idx; 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[]) { int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]) {
#if ENABLE_FEXECVE #if ENABLE_FEXECVE
execveat(executable_fd, "", argv, envp, AT_EMPTY_PATH); 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); execve(executable, argv, envp);
return -errno; 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);
}

View File

@ -47,4 +47,8 @@ extern const gather_stdout_callback_t gather_environment[_STDOUT_CONSUME_MAX];
const char* exec_command_flags_to_string(ExecCommandFlags i); const char* exec_command_flags_to_string(ExecCommandFlags i);
ExecCommandFlags exec_command_flags_from_string(const char *s); 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 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_;

View File

@ -11,6 +11,7 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "dissect-image.h" #include "dissect-image.h"
#include "exec-util.h"
#include "extract-word.h" #include "extract-word.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.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); r = safe_fork("(sd-mkuserns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NEW_USERNS, &pid);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) { if (r == 0)
/* Child. We do nothing here, just freeze until somebody kills us. */ /* Child. We do nothing here, just freeze until somebody kills us. */
freeze(); freeze();
_exit(EXIT_FAILURE);
}
xsprintf(line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0, uid_shift, uid_range); xsprintf(line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0, uid_shift, uid_range);

View File

@ -310,6 +310,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
"getpgrp\0" "getpgrp\0"
"getpid\0" "getpid\0"
"getppid\0" "getppid\0"
"getrandom\0"
"getresgid\0" "getresgid\0"
"getresgid32\0" "getresgid32\0"
"getresuid\0" "getresuid\0"

View File

@ -4,6 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "exec-util.h"
#include "log.h" #include "log.h"
#include "process-util.h" #include "process-util.h"
#include "spawn-ask-password-agent.h" #include "spawn-ask-password-agent.h"

View File

@ -6,6 +6,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "exec-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "io-util.h" #include "io-util.h"
#include "log.h" #include "log.h"

View File

@ -26,6 +26,7 @@ done
# figure out if we have entered the rate limit state # figure out if we have entered the rate limit state
entered_rl=0
exited_rl=0 exited_rl=0
timeout="$(date -ud "2 minutes" +%s)" timeout="$(date -ud "2 minutes" +%s)"
while [[ $(date -u +%s) -le ${timeout} ]]; do while [[ $(date -u +%s) -le ${timeout} ]]; do