summaryrefslogtreecommitdiffstats
path: root/src/libsystemd/sd-device/device-monitor.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-09-06 21:43:18 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-09-08 04:08:43 +0200
commitc0aa23cf1ed4b3cbbcaf8b19d47e6e29dc28c9a0 (patch)
tree065926d60717e9e481eceda7c89155130a637c17 /src/libsystemd/sd-device/device-monitor.c
parentuid-range: move to src/basic/ (diff)
downloadsystemd-c0aa23cf1ed4b3cbbcaf8b19d47e6e29dc28c9a0.tar.xz
systemd-c0aa23cf1ed4b3cbbcaf8b19d47e6e29dc28c9a0.zip
sd-device-monitor: relax sender uid check when running in user namespace
If sd-device-monitor is running in a user namespace, the sender uid is not zero. Let's relax the verification in that case.
Diffstat (limited to '')
-rw-r--r--src/libsystemd/sd-device/device-monitor.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c
index ba997b7f2c..33723950a1 100644
--- a/src/libsystemd/sd-device/device-monitor.c
+++ b/src/libsystemd/sd-device/device-monitor.c
@@ -28,6 +28,7 @@
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "uid-range.h"
#define log_monitor(m, format, ...) \
log_debug("sd-device-monitor(%s): " format, strna(m ? m->description : NULL), ##__VA_ARGS__)
@@ -46,6 +47,9 @@ struct sd_device_monitor {
union sockaddr_union snl_trusted_sender;
bool bound;
+ UidRange *mapped_userns_uid_range;
+ size_t n_uid_range;
+
Hashmap *subsystem_filter;
Set *tag_filter;
Hashmap *match_sysattr_filter;
@@ -170,6 +174,7 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
.bound = fd >= 0,
.snl.nl.nl_family = AF_NETLINK,
.snl.nl.nl_groups = group,
+ .n_uid_range = SIZE_MAX,
};
if (fd >= 0) {
@@ -373,6 +378,7 @@ static sd_device_monitor *device_monitor_free(sd_device_monitor *m) {
(void) sd_device_monitor_detach_event(m);
+ free(m->mapped_userns_uid_range);
free(m->description);
hashmap_free(m->subsystem_filter);
set_free(m->tag_filter);
@@ -450,6 +456,34 @@ static int passes_filter(sd_device_monitor *m, sd_device *device) {
return device_match_parent(device, m->match_parent_filter, m->nomatch_parent_filter);
}
+static bool check_sender_uid(sd_device_monitor *m, uid_t uid) {
+ int r;
+
+ assert(m);
+
+ /* Always trust messages from uid 0. */
+ if (uid == 0)
+ return true;
+
+ /* Trust messages sent by the same UID we are running. Currently, such situation happens only for
+ * unicast messages. */
+ if (uid == getuid() || uid == geteuid())
+ return true;
+
+ if (m->n_uid_range == SIZE_MAX) {
+ r = uid_range_load_userns(&m->mapped_userns_uid_range, &m->n_uid_range, NULL);
+ if (r < 0)
+ log_monitor_errno(m, r, "Failed to load UID ranges mapped to the current user namespace, ignoring: %m");
+ }
+
+ /* Trust messages come from outside of the current user namespace. */
+ if (m->n_uid_range != SIZE_MAX && !uid_range_contains(m->mapped_userns_uid_range, m->n_uid_range, uid))
+ return true;
+
+ /* Otherwise, refuse messages. */
+ return false;
+}
+
int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
union {
@@ -509,7 +543,7 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
"No sender credentials received, ignoring message.");
cred = (struct ucred*) CMSG_DATA(cmsg);
- if (cred->uid != 0)
+ if (!check_sender_uid(m, cred->uid))
return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
"Sender uid="UID_FMT", message ignored.", cred->uid);