int device_monitor_get_address(sd_device_monitor *m, union sockaddr_union *ret);
int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor *sender);
int device_monitor_send(sd_device_monitor *m, const union sockaddr_union *destination, sd_device *device);
+
+#define UDEV_MONITOR_MAGIC 0xfeedcafe
+
+typedef struct monitor_netlink_header {
+ /* "libudev" prefix to distinguish libudev and kernel messages */
+ char prefix[8];
+ /* Magic to protect against daemon <-> Library message format mismatch
+ * Used in the kernel from socket filter rules; needs to be stored in network order */
+ unsigned magic;
+ /* Total length of header structure known to the sender */
+ unsigned header_size;
+ /* Properties string buffer */
+ unsigned properties_off;
+ unsigned properties_len;
+ /* Hashes of primary device properties strings, to let libudev subscribers
+ * use in-kernel socket filters; values need to be stored in network order */
+ unsigned filter_subsystem_hash;
+ unsigned filter_devtype_hash;
+ unsigned filter_tag_bloom_hi;
+ unsigned filter_tag_bloom_lo;
+} monitor_netlink_header;
void *userdata;
};
-#define UDEV_MONITOR_MAGIC 0xfeedcafe
-
-typedef struct monitor_netlink_header {
- /* "libudev" prefix to distinguish libudev and kernel messages */
- char prefix[8];
- /* Magic to protect against daemon <-> Library message format mismatch
- * Used in the kernel from socket filter rules; needs to be stored in network order */
- unsigned magic;
- /* Total length of header structure known to the sender */
- unsigned header_size;
- /* Properties string buffer */
- unsigned properties_off;
- unsigned properties_len;
- /* Hashes of primary device properties strings, to let libudev subscribers
- * use in-kernel socket filters; values need to be stored in network order */
- unsigned filter_subsystem_hash;
- unsigned filter_devtype_hash;
- unsigned filter_tag_bloom_hi;
- unsigned filter_tag_bloom_lo;
-} monitor_netlink_header;
-
static int monitor_set_nl_address(sd_device_monitor *m) {
union sockaddr_union snl;
socklen_t addrlen;
"Invalid message signature (%x != %x).",
message.nlh->magic, htobe32(UDEV_MONITOR_MAGIC));
- if (message.nlh->properties_off + 32 > (size_t) n)
+ if (message.nlh->properties_off > LESS_BY((size_t) n, 32u))
return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
- "Invalid offset for properties (%u > %zi).",
- message.nlh->properties_off + 32, n);
+ "Invalid properties offset (%u) for message of length %zi.",
+ message.nlh->properties_off, n);
offset = message.nlh->properties_off;
#include "device-private.h"
#include "device-util.h"
#include "io-util.h"
+#include "iovec-util.h"
#include "mountpoint-util.h"
#include "path-util.h"
#include "socket-util.h"
ASSERT_STREQ(s, syspath);
}
+TEST(sd_device_monitor_receive_bad_properties_off) {
+ _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
+ union sockaddr_union sa;
+
+ prepare_monitor(&monitor_server, &monitor_client, &sa);
+
+ monitor_netlink_header nlh = {
+ .prefix = "libudev",
+ .magic = htobe32(UDEV_MONITOR_MAGIC),
+ .header_size = sizeof nlh,
+ .properties_off = UINT32_MAX - 10,
+ };
+ struct iovec iov = IOVEC_MAKE(&nlh, sizeof nlh);
+ struct msghdr smsg = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_name = &sa,
+ .msg_namelen = sizeof(struct sockaddr_nl),
+ };
+ ASSERT_OK_ERRNO(sendmsg(sd_device_monitor_get_fd(monitor_server), &smsg, 0));
+
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+ ASSERT_ERROR(sd_device_monitor_receive(monitor_client, &dev), EAGAIN);
+}
+
static int intro(void) {
if (getuid() != 0)
return log_tests_skipped("not root");