Merge pull request #7846 from poettering/nobody-getenv

some assorted fixes and additions, in particular a way to turn off "nobody" synthesizing on a specific system
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2018-01-10 20:18:51 +01:00 committed by GitHub
commit a9883559e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 161 additions and 65 deletions

View file

@ -8,3 +8,41 @@ expression s;
@@
- s ? s : ""
+ strempty(s)
@@
expression s;
@@
- if (!s)
- s = "";
+ s = strempty(s);
@@
expression s;
@@
- s ?: "(null)"
+ strnull(s)
@@
expression s;
@@
- s ? s : "(null)"
+ strnull(s)
@@
expression s;
@@
- if (!s)
- s = "(null)";
+ s = strnull(s);
@@
expression s;
@@
- s ?: "n/a"
+ strna(s)
@@
expression s;
@@
- s ? s : "n/a"
+ strna(s)
@@
expression s;
@@
- if (!s)
- s = "n/a";
+ s = strna(s);

View file

@ -1225,8 +1225,7 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
if (!filename_is_valid(fn))
return -EINVAL;
if (!extra)
extra = "";
extra = strempty(extra);
t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
if (!t)
@ -1259,8 +1258,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
if (!filename_is_valid(fn))
return -EINVAL;
if (!extra)
extra = "";
extra = strempty(extra);
t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
if (!t)
@ -1300,8 +1298,7 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
return r;
}
if (!extra)
extra = "";
extra = strempty(extra);
t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
if (!t)

View file

@ -29,6 +29,7 @@
#include <unistd.h>
#include "time-util.h"
#include "util.h"
int unlink_noerrno(const char *path);
@ -89,13 +90,14 @@ int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flag
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
static inline void rmdir_and_free(char *p) {
PROTECT_ERRNO;
(void) rmdir(p);
free(p);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rmdir_and_free);
static inline void unlink_and_free(char *p) {
(void) unlink(p);
(void) unlink_noerrno(p);
free(p);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free);

View file

@ -796,6 +796,8 @@ void sigkill_wait(pid_t pid) {
}
void sigkill_waitp(pid_t *pid) {
PROTECT_ERRNO;
if (!pid)
return;
if (*pid <= 1)

View file

@ -22,6 +22,8 @@
#include <sys/stat.h>
#include "util.h"
typedef enum RemoveFlags {
REMOVE_ONLY_DIRECTORIES = 1,
REMOVE_ROOT = 2,
@ -34,6 +36,7 @@ int rm_rf(const char *path, RemoveFlags flags);
/* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */
static inline void rm_rf_physical_and_free(char *p) {
PROTECT_ERRNO;
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
free(p);
}

View file

@ -52,15 +52,15 @@ static inline bool streq_ptr(const char *a, const char *b) {
}
static inline const char* strempty(const char *s) {
return s ? s : "";
return s ?: "";
}
static inline const char* strnull(const char *s) {
return s ? s : "(null)";
return s ?: "(null)";
}
static inline const char *strna(const char *s) {
return s ? s : "n/a";
return s ?: "n/a";
}
static inline bool isempty(const char *p) {

View file

@ -137,7 +137,8 @@ int get_user_creds(
return 0;
}
if (STR_IN_SET(*username, NOBODY_USER_NAME, "65534")) {
if (synthesize_nobody() &&
STR_IN_SET(*username, NOBODY_USER_NAME, "65534")) {
*username = NOBODY_USER_NAME;
if (uid)
@ -243,7 +244,8 @@ int get_group_creds(const char **groupname, gid_t *gid) {
return 0;
}
if (STR_IN_SET(*groupname, NOBODY_GROUP_NAME, "65534")) {
if (synthesize_nobody() &&
STR_IN_SET(*groupname, NOBODY_GROUP_NAME, "65534")) {
*groupname = NOBODY_GROUP_NAME;
if (gid)
@ -283,7 +285,8 @@ char* uid_to_name(uid_t uid) {
/* Shortcut things to avoid NSS lookups */
if (uid == 0)
return strdup("root");
if (uid == UID_NOBODY)
if (synthesize_nobody() &&
uid == UID_NOBODY)
return strdup(NOBODY_USER_NAME);
if (uid_is_valid(uid)) {
@ -323,7 +326,8 @@ char* gid_to_name(gid_t gid) {
if (gid == 0)
return strdup("root");
if (gid == GID_NOBODY)
if (synthesize_nobody() &&
gid == GID_NOBODY)
return strdup(NOBODY_GROUP_NAME);
if (gid_is_valid(gid)) {
@ -427,7 +431,8 @@ int get_home_dir(char **_h) {
*_h = h;
return 0;
}
if (u == UID_NOBODY) {
if (synthesize_nobody() &&
u == UID_NOBODY) {
h = strdup("/");
if (!h)
return -ENOMEM;
@ -482,7 +487,8 @@ int get_shell(char **_s) {
*_s = s;
return 0;
}
if (u == UID_NOBODY) {
if (synthesize_nobody() &&
u == UID_NOBODY) {
s = strdup("/sbin/nologin");
if (!s)
return -ENOMEM;
@ -690,3 +696,24 @@ int maybe_setgroups(size_t size, const gid_t *list) {
return 0;
}
bool synthesize_nobody(void) {
#ifdef NOLEGACY
return true;
#else
/* Returns true when we shall synthesize the "nobody" user (which we do by default). This can be turned off by
* touching /etc/systemd/dont-synthesize-nobody in order to provide upgrade compatibility with legacy systems
* that used the "nobody" user name and group name for other UIDs/GIDs than 65534.
*
* Note that we do not employ any kind of synchronization on the following caching variable. If the variable is
* accessed in multi-threaded programs in the worst case it might happen that we initialize twice, but that
* shouldn't matter as each initialization should come to the same result. */
static int cache = -1;
if (cache < 0)
cache = access("/etc/systemd/dont-synthesize-nobody", F_OK) < 0;
return cache;
#endif
}

View file

@ -97,3 +97,5 @@ bool valid_gecos(const char *d);
bool valid_home(const char *p);
int maybe_setgroups(size_t size, const gid_t *list);
bool synthesize_nobody(void);

View file

@ -618,7 +618,13 @@ int str_verscmp(const char *s1, const char *s2) {
}
/* Turn off core dumps but only if we're running outside of a container. */
void disable_core_dumps(void) {
if (detect_container() <= 0)
(void) write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
void disable_coredumps(void) {
int r;
if (detect_container() > 0)
return;
r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
if (r < 0)
log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m");
}

View file

@ -192,4 +192,4 @@ int version(void);
int str_verscmp(const char *s1, const char *s2);
void disable_core_dumps(void);
void disable_coredumps(void);

View file

@ -306,8 +306,7 @@ void job_dump(Job *j, FILE*f, const char *prefix) {
assert(j);
assert(f);
if (!prefix)
prefix = "";
prefix = strempty(prefix);
fprintf(f,
"%s-> Job %u:\n"

View file

@ -34,8 +34,7 @@ void kill_context_init(KillContext *c) {
void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
assert(c);
if (!prefix)
prefix = "";
prefix = strempty(prefix);
fprintf(f,
"%sKillMode: %s\n"

View file

@ -1607,7 +1607,7 @@ static void initialize_coredump(bool skip_setup) {
/* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored
* until the systemd-coredump tool is enabled via sysctl. */
if (!skip_setup)
disable_core_dumps();
disable_coredumps();
}
static void do_reexecute(

View file

@ -513,23 +513,31 @@ static int manager_setup_signals(Manager *m) {
return 0;
}
static void manager_clean_environment(Manager *m) {
static void manager_sanitize_environment(Manager *m) {
assert(m);
/* Let's remove some environment variables that we
* need ourselves to communicate with our clients */
/* Let's remove some environment variables that we need ourselves to communicate with our clients */
strv_env_unset_many(
m->environment,
"NOTIFY_SOCKET",
"EXIT_CODE",
"EXIT_STATUS",
"INVOCATION_ID",
"JOURNAL_STREAM",
"LISTEN_FDNAMES",
"LISTEN_FDS",
"LISTEN_PID",
"MAINPID",
"MANAGERPID",
"LISTEN_PID",
"LISTEN_FDS",
"LISTEN_FDNAMES",
"NOTIFY_SOCKET",
"REMOTE_ADDR",
"REMOTE_PORT",
"SERVICE_RESULT",
"WATCHDOG_PID",
"WATCHDOG_USEC",
"INVOCATION_ID",
NULL);
/* Let's order the environment alphabetically, just to make it pretty */
strv_sort(m->environment);
}
static int manager_default_environment(Manager *m) {
@ -556,8 +564,7 @@ static int manager_default_environment(Manager *m) {
if (!m->environment)
return -ENOMEM;
manager_clean_environment(m);
strv_sort(m->environment);
manager_sanitize_environment(m);
return 0;
}
@ -3308,8 +3315,7 @@ int manager_environment_add(Manager *m, char **minus, char **plus) {
strv_free(b);
m->environment = l;
manager_clean_environment(m);
strv_sort(m->environment);
manager_sanitize_environment(m);
return 0;
}

View file

@ -333,8 +333,7 @@ int main(int argc, char *argv[]) {
if (!in_container)
sync_with_progress();
/* Prevent coredumps */
disable_core_dumps();
disable_coredumps();
log_info("Sending SIGTERM to remaining processes...");
broadcast_signal(SIGTERM, true, true, arg_timeout);

View file

@ -1126,7 +1126,7 @@ static int gather_pid_metadata(
/* If this is PID 1 disable coredump collection, we'll unlikely be able to process it later on. */
if (is_pid1_crash((const char**) context)) {
log_notice("Due to PID 1 having crashed coredump collection will now be turned off.");
disable_core_dumps();
disable_coredumps();
}
set_iovec_field(iovec, n_iovec, "COREDUMP_UNIT=", context[CONTEXT_UNIT]);

View file

@ -418,8 +418,7 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
fd_inc_sndbuf(fd, SNDBUF_SIZE);
if (!identifier)
identifier = "";
identifier = strempty(identifier);
l = strlen(identifier);
header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);

View file

@ -136,7 +136,8 @@ enum nss_status _nss_systemd_getpwnam_r(
*errnop = 0;
return NSS_STATUS_SUCCESS;
}
if (streq(name, nobody_passwd.pw_name)) {
if (synthesize_nobody() &&
streq(name, nobody_passwd.pw_name)) {
*pwd = nobody_passwd;
*errnop = 0;
return NSS_STATUS_SUCCESS;
@ -244,7 +245,8 @@ enum nss_status _nss_systemd_getpwuid_r(
*errnop = 0;
return NSS_STATUS_SUCCESS;
}
if (uid == nobody_passwd.pw_uid) {
if (synthesize_nobody() &&
uid == nobody_passwd.pw_uid) {
*pwd = nobody_passwd;
*errnop = 0;
return NSS_STATUS_SUCCESS;
@ -351,7 +353,8 @@ enum nss_status _nss_systemd_getgrnam_r(
*errnop = 0;
return NSS_STATUS_SUCCESS;
}
if (streq(name, nobody_group.gr_name)) {
if (synthesize_nobody() &&
streq(name, nobody_group.gr_name)) {
*gr = nobody_group;
*errnop = 0;
return NSS_STATUS_SUCCESS;
@ -456,7 +459,8 @@ enum nss_status _nss_systemd_getgrgid_r(
*errnop = 0;
return NSS_STATUS_SUCCESS;
}
if (gid == nobody_group.gr_gid) {
if (synthesize_nobody() &&
gid == nobody_group.gr_gid) {
*gr = nobody_group;
*errnop = 0;
return NSS_STATUS_SUCCESS;

View file

@ -653,8 +653,7 @@ void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_
assert(c);
assert(f);
if (!prefix)
prefix = "";
prefix = strempty(prefix);
fprintf(f,
"%s\t%s: %s%s%s %s\n",

View file

@ -375,35 +375,47 @@ static struct Item* find_glob(OrderedHashmap *h, const char *match) {
static void load_unix_sockets(void) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
int r;
if (unix_sockets)
return;
/* We maintain a cache of the sockets we found in
* /proc/net/unix to speed things up a little. */
/* We maintain a cache of the sockets we found in /proc/net/unix to speed things up a little. */
unix_sockets = set_new(&string_hash_ops);
if (!unix_sockets)
return;
f = fopen("/proc/net/unix", "re");
if (!f)
return;
if (!f) {
log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
"Failed to open /proc/net/unix, ignoring: %m");
goto fail;
}
/* Skip header */
if (!fgets(line, sizeof(line), f))
r = read_line(f, LONG_LINE_MAX, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to skip /proc/net/unix header line: %m");
goto fail;
}
if (r == 0) {
log_warning("Premature end of file reading /proc/net/unix.");
goto fail;
}
for (;;) {
_cleanup_free_ char *line = NULL;
char *p, *s;
int k;
if (!fgets(line, sizeof(line), f))
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0) {
log_warning_errno(r, "Failed to read /proc/net/unix line, ignoring: %m");
goto fail;
}
if (r == 0) /* EOF */
break;
truncate_nl(line);
p = strchr(line, ':');
if (!p)
continue;
@ -420,21 +432,24 @@ static void load_unix_sockets(void) {
continue;
s = strdup(p);
if (!s)
if (!s) {
log_oom();
goto fail;
}
path_kill_slashes(s);
k = set_consume(unix_sockets, s);
if (k < 0 && k != -EEXIST)
r = set_consume(unix_sockets, s);
if (r < 0 && r != -EEXIST) {
log_warning_errno(r, "Failed to add AF_UNIX socket to set, ignoring: %m");
goto fail;
}
}
return;
fail:
set_free_free(unix_sockets);
unix_sockets = NULL;
unix_sockets = set_free_free(unix_sockets);
}
static bool unix_socket_alive(const char *fn) {

View file

@ -102,8 +102,7 @@ static void get_cap_mask(struct udev_device *dev,
unsigned long val;
v = udev_device_get_sysattr_value(pdev, attr);
if (!v)
v = "";
v = strempty(v);
xsprintf(text, "%s", v);
log_debug("%s raw kernel attribute: %s", attr, text);