From 309f631d41374ec8e724b1debdafd7ae40489b6e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2017 22:31:09 +0200 Subject: [PATCH] libudev: add missing errno initialization/error propagation (#6781) In libudev (which es much older code than the rest of systemd), we propagate errors in functions not returning an int, via (positive) errno (i.e. libc-style), and as negative Exyz values in those returning an int (much preferred, i.e. Linux kernel style). Let's fix up a few place, where this was incorrectly done, or not done at all. Fixes: #6613 --- src/libudev/libudev-enumerate.c | 8 +++++++- src/libudev/libudev-hwdb.c | 17 +++++++++++++---- src/libudev/libudev-monitor.c | 39 ++++++++++++++++++++++++++++++++------- src/libudev/libudev-queue.c | 13 ++++++++++--- src/libudev/libudev.c | 2 +- 5 files changed, 63 insertions(+), 16 deletions(-) diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c index 3b8abfb..ea80c75 100644 --- a/src/libudev/libudev-enumerate.c +++ b/src/libudev/libudev-enumerate.c @@ -159,6 +159,8 @@ _public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumer * Returns: a udev_list_entry. */ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) { + struct udev_list_entry *e; + assert_return_errno(udev_enumerate, NULL, EINVAL); if (!udev_enumerate->devices_uptodate) { @@ -182,7 +184,11 @@ _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enume udev_enumerate->devices_uptodate = true; } - return udev_list_get_entry(&udev_enumerate->devices_list); + e = udev_list_get_entry(&udev_enumerate->devices_list); + if (!e) + errno = ENODATA; + + return e; } /** diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c index a53f000..4bdc37d 100644 --- a/src/libudev/libudev-hwdb.c +++ b/src/libudev/libudev-hwdb.c @@ -57,15 +57,19 @@ _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) { struct udev_hwdb *hwdb; int r; - assert_return(udev, NULL); + assert_return_errno(udev, NULL, EINVAL); r = sd_hwdb_new(&hwdb_internal); - if (r < 0) + if (r < 0) { + errno = -r; return NULL; + } hwdb = new0(struct udev_hwdb, 1); - if (!hwdb) + if (!hwdb) { + errno = ENOMEM; return NULL; + } hwdb->refcount = 1; hwdb->hwdb = hwdb_internal; @@ -127,6 +131,7 @@ _public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) { */ _public_ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) { const char *key, *value; + struct udev_list_entry *e; if (!hwdb || !modalias) { errno = EINVAL; @@ -142,5 +147,9 @@ _public_ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev } } - return udev_list_get_entry(&hwdb->properties_list); + e = udev_list_get_entry(&hwdb->properties_list); + if (!e) + errno = ENODATA; + + return e; } diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c index 8287694..32f2154 100644 --- a/src/libudev/libudev-monitor.c +++ b/src/libudev/libudev-monitor.c @@ -100,8 +100,10 @@ static struct udev_monitor *udev_monitor_new(struct udev *udev) struct udev_monitor *udev_monitor; udev_monitor = new0(struct udev_monitor, 1); - if (udev_monitor == NULL) + if (udev_monitor == NULL) { + errno = ENOMEM; return NULL; + } udev_monitor->refcount = 1; udev_monitor->udev = udev; udev_list_init(udev, &udev_monitor->filter_subsystem_list, false); @@ -171,8 +173,10 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c struct udev_monitor *udev_monitor; unsigned int group; - if (udev == NULL) + if (udev == NULL) { + errno = EINVAL; return NULL; + } if (name == NULL) group = UDEV_MONITOR_NONE; @@ -196,8 +200,10 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c group = UDEV_MONITOR_UDEV; } else if (streq(name, "kernel")) group = UDEV_MONITOR_KERNEL; - else + else { + errno = EINVAL; return NULL; + } udev_monitor = udev_monitor_new(udev); if (udev_monitor == NULL) @@ -438,7 +444,10 @@ _public_ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_moni { if (udev_monitor == NULL) return -EINVAL; - return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size)); + if (setsockopt(udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size)) < 0) + return -errno; + + return 0; } int udev_monitor_disconnect(struct udev_monitor *udev_monitor) @@ -596,8 +605,10 @@ _public_ struct udev_device *udev_monitor_receive_device(struct udev_monitor *ud bool is_initialized = false; retry: - if (udev_monitor == NULL) + if (udev_monitor == NULL) { + errno = EINVAL; return NULL; + } iov.iov_base = &buf; iov.iov_len = sizeof(buf); memzero(&smsg, sizeof(struct msghdr)); @@ -617,6 +628,7 @@ retry: if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC)) { log_debug("invalid message length"); + errno = EINVAL; return NULL; } @@ -625,12 +637,14 @@ retry: if (udev_monitor->snl_trusted_sender.nl.nl_pid == 0 || snl.nl.nl_pid != udev_monitor->snl_trusted_sender.nl.nl_pid) { log_debug("unicast netlink message ignored"); + errno = EAGAIN; return NULL; } } else if (snl.nl.nl_groups == UDEV_MONITOR_KERNEL) { if (snl.nl.nl_pid > 0) { log_debug("multicast kernel netlink message from PID %"PRIu32" ignored", snl.nl.nl_pid); + errno = EAGAIN; return NULL; } } @@ -638,12 +652,14 @@ retry: cmsg = CMSG_FIRSTHDR(&smsg); if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { log_debug("no sender credentials received, message ignored"); + errno = EAGAIN; return NULL; } cred = (struct ucred *)CMSG_DATA(cmsg); if (cred->uid != 0) { log_debug("sender uid="UID_FMT", message ignored", cred->uid); + errno = EAGAIN; return NULL; } @@ -652,11 +668,13 @@ retry: if (buf.nlh.magic != htobe32(UDEV_MONITOR_MAGIC)) { log_debug("unrecognized message signature (%x != %x)", buf.nlh.magic, htobe32(UDEV_MONITOR_MAGIC)); + errno = EAGAIN; return NULL; } if (buf.nlh.properties_off+32 > (size_t)buflen) { log_debug("message smaller than expected (%u > %zd)", buf.nlh.properties_off+32, buflen); + errno = EAGAIN; return NULL; } @@ -669,12 +687,14 @@ retry: bufpos = strlen(buf.raw) + 1; if ((size_t)bufpos < sizeof("a@/d") || bufpos >= buflen) { log_debug("invalid message length"); + errno = EAGAIN; return NULL; } /* check message header */ if (strstr(buf.raw, "@/") == NULL) { log_debug("unrecognized message header"); + errno = EAGAIN; return NULL; } } @@ -701,6 +721,8 @@ retry: rc = poll(pfd, 1, 0); if (rc > 0) goto retry; + + errno = EAGAIN; return NULL; } @@ -837,8 +859,11 @@ _public_ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor */ _public_ int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) { - static struct sock_fprog filter = { 0, NULL }; + static const struct sock_fprog filter = { 0, NULL }; udev_list_cleanup(&udev_monitor->filter_subsystem_list); - return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); + if (setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) < 0) + return -errno; + + return 0; } diff --git a/src/libudev/libudev-queue.c b/src/libudev/libudev-queue.c index e3dffa6..f3143d4 100644 --- a/src/libudev/libudev-queue.c +++ b/src/libudev/libudev-queue.c @@ -60,12 +60,16 @@ _public_ struct udev_queue *udev_queue_new(struct udev *udev) { struct udev_queue *udev_queue; - if (udev == NULL) + if (udev == NULL) { + errno = EINVAL; return NULL; + } udev_queue = new0(struct udev_queue, 1); - if (udev_queue == NULL) + if (udev_queue == NULL) { + errno = ENOMEM; return NULL; + } udev_queue->refcount = 1; udev_queue->udev = udev; @@ -124,8 +128,10 @@ _public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue) **/ _public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) { - if (udev_queue == NULL) + if (udev_queue == NULL) { + errno = EINVAL; return NULL; + } return udev_queue->udev; } @@ -223,6 +229,7 @@ _public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, un **/ _public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) { + errno = ENODATA; return NULL; } diff --git a/src/libudev/libudev.c b/src/libudev/libudev.c index d7b82a7..ce8d5b5 100644 --- a/src/libudev/libudev.c +++ b/src/libudev/libudev.c @@ -97,7 +97,7 @@ _public_ struct udev *udev_new(void) { udev = new0(struct udev, 1); if (!udev) { - errno = -ENOMEM; + errno = ENOMEM; return NULL; } udev->refcount = 1; -- 2.7.4