Merge pull request #8283 from poettering/nspawn-user-fix
some trivial nspawn related fixes
This commit is contained in:
commit
8c89cb5a50
36
coccinelle/close-above-stdio.cocci
Normal file
36
coccinelle/close-above-stdio.cocci
Normal file
|
@ -0,0 +1,36 @@
|
|||
@@
|
||||
expression fd;
|
||||
@@
|
||||
- if (fd > 2)
|
||||
- safe_close(fd);
|
||||
+ safe_close_above_stdio(fd);
|
||||
@@
|
||||
expression fd;
|
||||
@@
|
||||
- if (fd > 2)
|
||||
- fd = safe_close(fd);
|
||||
+ fd = safe_close_above_stdio(fd);
|
||||
@@
|
||||
expression fd;
|
||||
@@
|
||||
- if (fd >= 3)
|
||||
- safe_close(fd);
|
||||
+ safe_close_above_stdio(fd);
|
||||
@@
|
||||
expression fd;
|
||||
@@
|
||||
- if (fd >= 3)
|
||||
- fd = safe_close(fd);
|
||||
+ fd = safe_close_above_stdio(fd);
|
||||
@@
|
||||
expression fd;
|
||||
@@
|
||||
- if (fd > STDERR_FILENO)
|
||||
- safe_close(fd);
|
||||
+ safe_close_above_stdio(fd);
|
||||
@@
|
||||
expression fd;
|
||||
@@
|
||||
- if (fd > STDERR_FILENO)
|
||||
- fd = safe_close(fd);
|
||||
+ fd = safe_close_above_stdio(fd);
|
|
@ -1,10 +1,10 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
for SCRIPT in ${@-*.cocci} ; do
|
||||
echo "--x-- Processing $SCRIPT --x--"
|
||||
echo "--x-- Processing: spatch --sp-file $SCRIPT --dir $(pwd)/.. --x--"
|
||||
TMPFILE=`mktemp`
|
||||
spatch --sp-file $SCRIPT --dir $(pwd)/.. 2> "$TMPFILE" || cat "$TMPFILE"
|
||||
rm "$TMPFILE"
|
||||
echo "--x-- Processed $SCRIPT --x--"
|
||||
echo "--x-- Processed: spatch --sp-file $SCRIPT --dir $(pwd)/.. --x--"
|
||||
echo ""
|
||||
done
|
||||
|
|
|
@ -35,6 +35,13 @@ int close_nointr(int fd);
|
|||
int safe_close(int fd);
|
||||
void safe_close_pair(int p[]);
|
||||
|
||||
static inline int safe_close_above_stdio(int fd) {
|
||||
if (fd < 3) /* Don't close stdin/stdout/stderr, but still invalidate the fd by returning -1 */
|
||||
return -1;
|
||||
|
||||
return safe_close(fd);
|
||||
}
|
||||
|
||||
void close_many(const int fds[], unsigned n_fd);
|
||||
|
||||
int fclose_nointr(FILE *f);
|
||||
|
|
|
@ -94,14 +94,7 @@ static char *log_abort_msg = NULL;
|
|||
} while (false)
|
||||
|
||||
static void log_close_console(void) {
|
||||
|
||||
if (console_fd < 0)
|
||||
return;
|
||||
|
||||
if (console_fd >= 3)
|
||||
safe_close(console_fd);
|
||||
|
||||
console_fd = -1;
|
||||
console_fd = safe_close_above_stdio(console_fd);
|
||||
}
|
||||
|
||||
static int log_open_console(void) {
|
||||
|
|
|
@ -1166,6 +1166,7 @@ extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void
|
|||
extern void* __dso_handle __attribute__ ((__weak__));
|
||||
|
||||
pid_t getpid_cached(void) {
|
||||
static bool installed = false;
|
||||
pid_t current_value;
|
||||
|
||||
/* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
|
||||
|
@ -1186,10 +1187,18 @@ pid_t getpid_cached(void) {
|
|||
|
||||
new_pid = raw_getpid();
|
||||
|
||||
if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) {
|
||||
/* OOM? Let's try again later */
|
||||
cached_pid = CACHED_PID_UNSET;
|
||||
return new_pid;
|
||||
if (!installed) {
|
||||
/* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's
|
||||
* only half-documented (glibc doesn't document it but LSB does — though only superficially)
|
||||
* we'll check for errors only in the most generic fashion possible. */
|
||||
|
||||
if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) {
|
||||
/* OOM? Let's try again later */
|
||||
cached_pid = CACHED_PID_UNSET;
|
||||
return new_pid;
|
||||
}
|
||||
|
||||
installed = true;
|
||||
}
|
||||
|
||||
cached_pid = new_pid;
|
||||
|
@ -1428,8 +1437,7 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
|
|||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fd > STDERR_FILENO)
|
||||
close(fd);
|
||||
safe_close_above_stdio(fd);
|
||||
}
|
||||
|
||||
/* Count arguments */
|
||||
|
|
|
@ -917,8 +917,7 @@ int make_stdio(int fd) {
|
|||
if (dup2(fd, STDERR_FILENO) < 0 && r >= 0)
|
||||
r = -errno;
|
||||
|
||||
if (fd >= 3)
|
||||
safe_close(fd);
|
||||
safe_close_above_stdio(fd);
|
||||
|
||||
/* Explicitly unset O_CLOEXEC, since if fd was < 3, then dup2() was a NOP and the bit hence possibly set. */
|
||||
stdio_unset_cloexec();
|
||||
|
|
|
@ -141,9 +141,7 @@ int main(int argc, char *argv[]) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (fd >= 3)
|
||||
safe_close(fd);
|
||||
fd = -1;
|
||||
fd = safe_close_above_stdio(fd);
|
||||
|
||||
if (argc <= optind)
|
||||
(void) execl("/bin/cat", "/bin/cat", NULL);
|
||||
|
|
|
@ -23,13 +23,16 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "def.h"
|
||||
#include "errno.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "mkdir.h"
|
||||
#include "nspawn-setuid.h"
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -45,19 +48,19 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
|
|||
return log_error_errno(errno, "Failed to allocate pipe: %m");
|
||||
|
||||
r = safe_fork("(getent)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
safe_close_pair(pipe_fds);
|
||||
return r;
|
||||
}
|
||||
if (r == 0) {
|
||||
int nullfd;
|
||||
char *empty_env = NULL;
|
||||
int nullfd;
|
||||
|
||||
if (dup3(pipe_fds[1], STDOUT_FILENO, 0) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (pipe_fds[0] > 2)
|
||||
safe_close(pipe_fds[0]);
|
||||
if (pipe_fds[1] > 2)
|
||||
safe_close(pipe_fds[1]);
|
||||
safe_close_above_stdio(pipe_fds[0]);
|
||||
safe_close_above_stdio(pipe_fds[1]);
|
||||
|
||||
nullfd = open("/dev/null", O_RDWR);
|
||||
if (nullfd < 0)
|
||||
|
@ -69,8 +72,7 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
|
|||
if (dup3(nullfd, STDERR_FILENO, 0) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (nullfd > 2)
|
||||
safe_close(nullfd);
|
||||
safe_close_above_stdio(nullfd);
|
||||
|
||||
close_all_fds(NULL, 0);
|
||||
|
||||
|
@ -87,10 +89,10 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
|
|||
}
|
||||
|
||||
int change_uid_gid(const char *user, char **_home) {
|
||||
char line[LINE_MAX], *x, *u, *g, *h;
|
||||
char *x, *u, *g, *h;
|
||||
const char *word, *state;
|
||||
_cleanup_free_ uid_t *uids = NULL;
|
||||
_cleanup_free_ char *home = NULL;
|
||||
_cleanup_free_ char *home = NULL, *line = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
unsigned n_uids = 0;
|
||||
|
@ -102,7 +104,7 @@ int change_uid_gid(const char *user, char **_home) {
|
|||
|
||||
assert(_home);
|
||||
|
||||
if (!user || streq(user, "root") || streq(user, "0")) {
|
||||
if (!user || STR_IN_SET(user, "root", "0")) {
|
||||
/* Reset everything fully to 0, just in case */
|
||||
|
||||
r = reset_uid_gid();
|
||||
|
@ -118,21 +120,18 @@ int change_uid_gid(const char *user, char **_home) {
|
|||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
f = fdopen(fd, "r");
|
||||
f = fdopen(fd, "re");
|
||||
if (!f)
|
||||
return log_oom();
|
||||
fd = -1;
|
||||
|
||||
if (!fgets(line, sizeof(line), f)) {
|
||||
if (!ferror(f)) {
|
||||
log_error("Failed to resolve user %s.", user);
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
return log_error_errno(errno, "Failed to read from getent: %m");
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r == 0) {
|
||||
log_error("Failed to resolve user %s.", user);
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
truncate_nl(line);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read from getent: %m");
|
||||
|
||||
(void) wait_for_terminate_and_check("getent passwd", pid, WAIT_LOG);
|
||||
|
||||
|
@ -195,27 +194,26 @@ int change_uid_gid(const char *user, char **_home) {
|
|||
if (!home)
|
||||
return log_oom();
|
||||
|
||||
f = safe_fclose(f);
|
||||
line = mfree(line);
|
||||
|
||||
/* Second, get group memberships */
|
||||
fd = spawn_getent("initgroups", user, &pid);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
fclose(f);
|
||||
f = fdopen(fd, "r");
|
||||
f = fdopen(fd, "re");
|
||||
if (!f)
|
||||
return log_oom();
|
||||
fd = -1;
|
||||
|
||||
if (!fgets(line, sizeof(line), f)) {
|
||||
if (!ferror(f)) {
|
||||
log_error("Failed to resolve user %s.", user);
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
return log_error_errno(errno, "Failed to read from getent: %m");
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r == 0) {
|
||||
log_error("Failed to resolve user %s.", user);
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
truncate_nl(line);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read from getent: %m");
|
||||
|
||||
(void) wait_for_terminate_and_check("getent initgroups", pid, WAIT_LOG);
|
||||
|
||||
|
@ -234,10 +232,8 @@ int change_uid_gid(const char *user, char **_home) {
|
|||
return log_oom();
|
||||
|
||||
r = parse_uid(c, &uids[n_uids++]);
|
||||
if (r < 0) {
|
||||
log_error("Failed to parse group data from getent.");
|
||||
return -EIO;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse group data from getent: %m");
|
||||
}
|
||||
|
||||
r = mkdir_parents(home, 0775);
|
||||
|
|
Loading…
Reference in a new issue