summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/basic/audit-util.c7
-rw-r--r--src/basic/capability-util.c3
-rw-r--r--src/basic/user-util.c27
-rw-r--r--src/basic/user-util.h2
-rw-r--r--src/core/execute.c2
-rw-r--r--src/core/umount.c2
6 files changed, 37 insertions, 6 deletions
diff --git a/src/basic/audit-util.c b/src/basic/audit-util.c
index 5741fecdd6..d1c9695973 100644
--- a/src/basic/audit-util.c
+++ b/src/basic/audit-util.c
@@ -92,8 +92,11 @@ bool use_audit(void) {
int fd;
fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT);
- if (fd < 0)
- cached_use = errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT;
+ if (fd < 0) {
+ cached_use = !IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT, EPERM);
+ if (errno == EPERM)
+ log_debug_errno(errno, "Audit access prohibited, won't talk to audit");
+ }
else {
cached_use = true;
safe_close(fd);
diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c
index d4c5bd6937..f8db6e0212 100644
--- a/src/basic/capability-util.c
+++ b/src/basic/capability-util.c
@@ -31,6 +31,7 @@
#include "log.h"
#include "macro.h"
#include "parse-util.h"
+#include "user-util.h"
#include "util.h"
int have_effective_cap(int value) {
@@ -295,7 +296,7 @@ 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 (setgroups(0, NULL) < 0)
+ if (maybe_setgroups(0, NULL) < 0)
return log_error_errno(errno, "Failed to drop auxiliary groups list: %m");
/* Ensure we keep the permitted caps across the setresuid() */
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index 0522bce1d1..16496fccfa 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -33,6 +33,7 @@
#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "macro.h"
#include "missing.h"
@@ -460,7 +461,7 @@ int get_shell(char **_s) {
int reset_uid_gid(void) {
- if (setgroups(0, NULL) < 0)
+ if (maybe_setgroups(0, NULL) < 0)
return -errno;
if (setresgid(0, 0, 0) < 0)
@@ -602,3 +603,27 @@ bool valid_home(const char *p) {
return true;
}
+
+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)
+ return 0;
+ }
+ return setgroups(size, list);
+}
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
index 6c61f63cae..dfea561bde 100644
--- a/src/basic/user-util.h
+++ b/src/basic/user-util.h
@@ -86,3 +86,5 @@ bool valid_user_group_name(const char *u);
bool valid_user_group_name_or_id(const char *u);
bool valid_gecos(const char *d);
bool valid_home(const char *p);
+
+int maybe_setgroups(size_t size, const gid_t *list);
diff --git a/src/core/execute.c b/src/core/execute.c
index 82d8c978c1..019ff8490b 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -781,7 +781,7 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_
k++;
}
- if (setgroups(k, gids) < 0) {
+ if (maybe_setgroups(k, gids) < 0) {
free(gids);
return -errno;
}
diff --git a/src/core/umount.c b/src/core/umount.c
index c21a2be54e..1e5459ed80 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -375,7 +375,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
/* If we are in a container, don't attempt to
read-only mount anything as that brings no real
benefits, but might confuse the host, as we remount
- the superblock here, not the bind mound. */
+ the superblock here, not the bind mount. */
if (detect_container() <= 0) {
_cleanup_free_ char *options = NULL;
/* MS_REMOUNT requires that the data parameter