diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2020-04-24 07:45:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-24 07:45:07 +0200 |
commit | 11f93798663009d3a83b60ce899c778d9c1f5180 (patch) | |
tree | 0fd5e3d69f60033f54075e2ecd4d5a907f250abc | |
parent | 41ab8c67ebfbbdc78cda473d81d392da912c17bc (diff) | |
parent | 371d72e05b7e2c2b7850cb04d8d4c18be1e60421 (diff) | |
download | systemd-11f93798663009d3a83b60ce899c778d9c1f5180.tar.gz |
Merge pull request #15570 from poettering/cmsg-find
CMSG_FIND_DATA() and cmsg_find() work
-rw-r--r-- | src/basic/socket-util.c | 13 | ||||
-rw-r--r-- | src/basic/socket-util.h | 8 | ||||
-rw-r--r-- | src/coredump/coredump.c | 12 | ||||
-rw-r--r-- | src/import/importd.c | 10 | ||||
-rw-r--r-- | src/journal/journald-stream.c | 26 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp-client.c | 14 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-socket.c | 22 | ||||
-rw-r--r-- | src/nspawn/nspawn.c | 13 | ||||
-rw-r--r-- | src/shared/ask-password-api.c | 7 | ||||
-rw-r--r-- | src/udev/udevd.c | 10 |
10 files changed, 40 insertions, 95 deletions
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index b797a52180..b502a62a24 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -887,7 +887,7 @@ ssize_t receive_one_fd_iov( .msg_iov = iov, .msg_iovlen = iovlen, }; - struct cmsghdr *cmsg, *found = NULL; + struct cmsghdr *found; ssize_t k; assert(transport_fd >= 0); @@ -905,16 +905,7 @@ ssize_t receive_one_fd_iov( if (k < 0) return k; - CMSG_FOREACH(cmsg, &mh) { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS && - cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { - assert(!found); - found = cmsg; - break; - } - } - + found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int))); if (!found) { cmsg_close_all(&mh); diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 95643135df..fba4efef81 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -158,6 +158,14 @@ int flush_accept(int fd); struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length); +/* Type-safe, dereferencing version of cmsg_find() */ +#define CMSG_FIND_DATA(mh, level, type, ctype) \ + ({ \ + struct cmsghdr *_found; \ + _found = cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))); \ + (ctype*) (_found ? CMSG_DATA(_found) : NULL); \ + }) + /* * Certain hardware address types (e.g Infiniband) do not fit into sll_addr * (8 bytes) and run over the structure. This macro returns the correct size that diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index e4266baa62..b88b284584 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -921,19 +921,11 @@ static int process_socket(int fd) { /* The final zero-length datagram carries the file descriptor and tells us * that we're done. */ if (n == 0) { - struct cmsghdr *cmsg, *found = NULL; + struct cmsghdr *found; free(iovec.iov_base); - CMSG_FOREACH(cmsg, &mh) { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS && - cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { - assert(!found); - found = cmsg; - } - } - + found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int))); if (!found) { cmsg_close_all(&mh); r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG), diff --git a/src/import/importd.c b/src/import/importd.c index 340b12ecd5..417e686bb9 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -557,9 +557,8 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void .msg_control = &control, .msg_controllen = sizeof(control), }; - struct ucred *ucred = NULL; + struct ucred *ucred; Manager *m = userdata; - struct cmsghdr *cmsg; char *p, *e; Transfer *t; Iterator i; @@ -574,17 +573,12 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void cmsg_close_all(&msghdr); - CMSG_FOREACH(cmsg, &msghdr) - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) - ucred = (struct ucred*) CMSG_DATA(cmsg); - if (msghdr.msg_flags & MSG_TRUNC) { log_warning("Got overly long notification datagram, ignoring."); return 0; } + ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred); if (!ucred || ucred->pid <= 0) { log_warning("Got notification datagram lacking credential information, ignoring."); return 0; diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index ec6dad62e8..202ac3cda2 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -491,8 +491,7 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) { static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; StdoutStream *s = userdata; - struct ucred *ucred = NULL; - struct cmsghdr *cmsg; + struct ucred *ucred; struct iovec iovec; size_t limit; ssize_t l; @@ -541,25 +540,14 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, goto terminate; } - CMSG_FOREACH(cmsg, &msghdr) - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - assert(!ucred); - ucred = (struct ucred *)CMSG_DATA(cmsg); - break; - } - - /* Invalidate the context if the pid of the sender changed. - * This happens when a forked process inherits stdout / stderr - * from a parent. In this case getpeercred returns the ucred - * of the parent, which can be invalid if the parent has exited - * in the meantime. + /* Invalidate the context if the pid of the sender changed. This happens when a forked process + * inherits stdout / stderr from a parent. In this case getpeercred returns the ucred of the parent, + * which can be invalid if the parent has exited in the meantime. */ + ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred); if (ucred && ucred->pid != s->ucred.pid) { - /* force out any previously half-written lines from a - * different process, before we switch to the new ucred - * structure for everything we just added */ + /* force out any previously half-written lines from a different process, before we switch to + * the new ucred structure for everything we just added */ r = stdout_stream_scan(s, true); if (r < 0) goto terminate; diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 31416c9f43..0cff6c4f33 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1937,15 +1937,11 @@ static int client_receive_message_raw( if ((size_t) len < sizeof(DHCPPacket)) return 0; - CMSG_FOREACH(cmsg, &msg) - if (cmsg->cmsg_level == SOL_PACKET && - cmsg->cmsg_type == PACKET_AUXDATA && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) { - struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg); - - checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); - break; - } + cmsg = cmsg_find(&msg, SOL_PACKET, PACKET_AUXDATA, CMSG_LEN(sizeof(struct tpacket_auxdata))); + if (cmsg) { + struct tpacket_auxdata *aux = (struct tpacket_auxdata*) CMSG_DATA(cmsg); + checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); + } r = dhcp_packet_verify_headers(packet, len, checksum, client->port); if (r < 0) diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c index 9401c43d05..aa3c6074cb 100644 --- a/src/libsystemd/sd-netlink/netlink-socket.c +++ b/src/libsystemd/sd-netlink/netlink-socket.c @@ -238,7 +238,7 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) { return k; } -static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) { +static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_group, bool peek) { union sockaddr_union sender; uint8_t cmsg_buffer[CMSG_SPACE(sizeof(struct nl_pktinfo))]; struct msghdr msg = { @@ -249,8 +249,6 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool .msg_control = cmsg_buffer, .msg_controllen = sizeof(cmsg_buffer), }; - struct cmsghdr *cmsg; - uint32_t group = 0; ssize_t n; assert(fd >= 0); @@ -281,20 +279,16 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool return 0; } - CMSG_FOREACH(cmsg, &msg) { - if (cmsg->cmsg_level == SOL_NETLINK && - cmsg->cmsg_type == NETLINK_PKTINFO && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) { - struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg); + if (ret_mcast_group) { + struct cmsghdr *cmsg; - /* multi-cast group */ - group = pktinfo->group; - } + cmsg = cmsg_find(&msg, SOL_NETLINK, NETLINK_PKTINFO, CMSG_LEN(sizeof(struct nl_pktinfo))); + if (ret_mcast_group) + *ret_mcast_group = ((struct nl_pktinfo*) CMSG_DATA(cmsg))->group; + else + *ret_mcast_group = 0; } - if (_group) - *_group = group; - return (int) n; } diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index cc2f1521ff..c2148596b7 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3698,8 +3698,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r .msg_control = &control, .msg_controllen = sizeof(control), }; - struct cmsghdr *cmsg; - struct ucred *ucred = NULL; + struct ucred *ucred; ssize_t n; pid_t inner_child_pid; _cleanup_strv_free_ char **tags = NULL; @@ -3721,15 +3720,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r cmsg_close_all(&msghdr); - CMSG_FOREACH(cmsg, &msghdr) { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - - ucred = (struct ucred*) CMSG_DATA(cmsg); - } - } - + ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred); if (!ucred || ucred->pid != inner_child_pid) { log_debug("Received notify message without valid credentials. Ignoring."); return 0; diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 4cec59087f..e690b0fa6e 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -940,15 +940,12 @@ int ask_password_agent( continue; } - if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) || - control.cmsghdr.cmsg_level != SOL_SOCKET || - control.cmsghdr.cmsg_type != SCM_CREDENTIALS || - control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) { + ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred); + if (!ucred) { log_debug("Received message without credentials. Ignoring."); continue; } - ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr); if (ucred->uid != 0) { log_debug("Got request from unprivileged user. Ignoring."); continue; diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 4b15159c5b..cfda47f849 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -916,9 +916,8 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat .msg_control = &control, .msg_controllen = sizeof(control), }; - struct cmsghdr *cmsg; ssize_t size; - struct ucred *ucred = NULL; + struct ucred *ucred; struct worker *worker; size = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT); @@ -937,12 +936,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat continue; } - CMSG_FOREACH(cmsg, &msghdr) - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) - ucred = (struct ucred*) CMSG_DATA(cmsg); - + ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred); if (!ucred || ucred->pid <= 0) { log_warning("Ignoring worker message without valid PID"); continue; |