diff options
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/capability-util.c | 5 | ||||
-rw-r--r-- | src/basic/socket-util.c | 17 | ||||
-rw-r--r-- | src/basic/socket-util.h | 2 | ||||
-rw-r--r-- | src/basic/user-util.c | 49 |
4 files changed, 50 insertions, 23 deletions
diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index f8db6e0212..c3de20a0e8 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -296,8 +296,9 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) { if (setresgid(gid, gid, gid) < 0) return log_error_errno(errno, "Failed to change group ID: %m"); - if (maybe_setgroups(0, NULL) < 0) - return log_error_errno(errno, "Failed to drop auxiliary groups list: %m"); + r = maybe_setgroups(0, NULL); + if (r < 0) + return log_error_errno(r, "Failed to drop auxiliary groups list: %m"); /* Ensure we keep the permitted caps across the setresuid() */ if (prctl(PR_SET_KEEPCAPS, 1) < 0) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 5c829e0e7e..1662c04705 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1060,3 +1060,20 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng return NULL; } + +int socket_ioctl_fd(void) { + int fd; + + /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for + * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not + * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more + * generic AF_NETLINK. */ + + fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) + fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC); + if (fd < 0) + return -errno; + + return fd; +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 2536b085f9..2ef572badb 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -154,3 +154,5 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \ strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \ }) + +int socket_ioctl_fd(void); diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 16496fccfa..de6c93056e 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -460,9 +460,11 @@ int get_shell(char **_s) { } int reset_uid_gid(void) { + int r; - if (maybe_setgroups(0, NULL) < 0) - return -errno; + r = maybe_setgroups(0, NULL); + if (r < 0) + return r; if (setresgid(0, 0, 0) < 0) return -errno; @@ -605,25 +607,30 @@ bool valid_home(const char *p) { } int maybe_setgroups(size_t size, const gid_t *list) { - static int cached_can_setgroups = -1; - /* check if setgroups is allowed before we try to drop all the auxiliary groups */ - if (size == 0) { - if (cached_can_setgroups < 0) { - _cleanup_free_ char *setgroups_content = NULL; - int r = read_one_line_file("/proc/self/setgroups", &setgroups_content); - if (r < 0 && errno != ENOENT) - return r; - if (r < 0) { - /* old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ - cached_can_setgroups = true; - } else { - cached_can_setgroups = streq(setgroups_content, "allow"); - if (!cached_can_setgroups) - log_debug("skip setgroups, /proc/self/setgroups is set to 'deny'"); - } - } - if (!cached_can_setgroups) + int r; + + /* Check if setgroups is allowed before we try to drop all the auxiliary groups */ + if (size == 0) { /* Dropping all aux groups? */ + _cleanup_free_ char *setgroups_content = NULL; + bool can_setgroups; + + r = read_one_line_file("/proc/self/setgroups", &setgroups_content); + if (r == -ENOENT) + /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ + can_setgroups = true; + else if (r < 0) + return r; + else + can_setgroups = streq(setgroups_content, "allow"); + + if (!can_setgroups) { + log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'"); return 0; + } } - return setgroups(size, list); + + if (setgroups(size, list) < 0) + return -errno; + + return 0; } |