mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #34212 from YHNdnzj/recvmsg-safe-trunc
tree-wide: handle MSG_TRUNC with recvmsg_safe()
This commit is contained in:
commit
1306567a40
@ -99,7 +99,7 @@ static int try_audit_request(int fd) {
|
||||
|
||||
n = recvmsg_safe(fd, &mh, 0);
|
||||
if (n < 0)
|
||||
return -errno;
|
||||
return n;
|
||||
if (n != NLMSG_LENGTH(sizeof(struct nlmsgerr)))
|
||||
return -EIO;
|
||||
|
||||
|
@ -568,14 +568,21 @@ int same_fd(int a, int b) {
|
||||
}
|
||||
|
||||
void cmsg_close_all(struct msghdr *mh) {
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
assert(mh);
|
||||
|
||||
CMSG_FOREACH(cmsg, mh)
|
||||
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
|
||||
struct cmsghdr *cmsg;
|
||||
CMSG_FOREACH(cmsg, mh) {
|
||||
if (cmsg->cmsg_level != SOL_SOCKET)
|
||||
continue;
|
||||
|
||||
if (cmsg->cmsg_type == SCM_RIGHTS)
|
||||
close_many(CMSG_TYPED_DATA(cmsg, int),
|
||||
(cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
|
||||
else if (cmsg->cmsg_type == SCM_PIDFD) {
|
||||
assert(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
|
||||
safe_close(*CMSG_TYPED_DATA(cmsg, int));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool fdname_is_valid(const char *s) {
|
||||
|
@ -1447,18 +1447,22 @@ int socket_bind_to_ifindex(int fd, int ifindex) {
|
||||
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
|
||||
ssize_t n;
|
||||
|
||||
/* A wrapper around recvmsg() that checks for MSG_CTRUNC, and turns it into an error, in a reasonably
|
||||
* safe way, closing any SCM_RIGHTS fds in the error path.
|
||||
/* A wrapper around recvmsg() that checks for MSG_CTRUNC and MSG_TRUNC, and turns them into an error,
|
||||
* in a reasonably safe way, closing any received fds in the error path.
|
||||
*
|
||||
* Note that unlike our usual coding style this might modify *msg on failure. */
|
||||
|
||||
assert(sockfd >= 0);
|
||||
assert(msg);
|
||||
|
||||
n = recvmsg(sockfd, msg, flags);
|
||||
if (n < 0)
|
||||
return -errno;
|
||||
|
||||
if (FLAGS_SET(msg->msg_flags, MSG_CTRUNC)) {
|
||||
if (FLAGS_SET(msg->msg_flags, MSG_CTRUNC) ||
|
||||
(!FLAGS_SET(flags, MSG_PEEK) && FLAGS_SET(msg->msg_flags, MSG_TRUNC))) {
|
||||
cmsg_close_all(msg);
|
||||
return -EXFULL; /* a recognizable error code */
|
||||
return FLAGS_SET(msg->msg_flags, MSG_CTRUNC) ? -ECHRNG : -EXFULL;
|
||||
}
|
||||
|
||||
return n;
|
||||
|
@ -329,7 +329,7 @@ struct timespec_large {
|
||||
|
||||
/* glibc duplicates timespec/timeval on certain 32-bit arches, once in 32-bit and once in 64-bit.
|
||||
* See __convert_scm_timestamps() in glibc source code. Hence, we need additional buffer space for them
|
||||
* to prevent from recvmsg_safe() returning -EXFULL. */
|
||||
* to prevent truncating control msg (recvmsg() MSG_CTRUNC). */
|
||||
#define CMSG_SPACE_TIMEVAL \
|
||||
((sizeof(struct timeval) == sizeof(struct timeval_large)) ? \
|
||||
CMSG_SPACE(sizeof(struct timeval)) : \
|
||||
|
@ -2750,13 +2750,17 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
|
||||
n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
return 0; /* Spurious wakeup, try again */
|
||||
if (n == -EXFULL) {
|
||||
if (n == -ECHRNG) {
|
||||
log_warning_errno(n, "Got message with truncated control data (too many fds sent?), ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n == -EXFULL) {
|
||||
log_warning_errno(n, "Got message with truncated payload data, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n < 0)
|
||||
/* If this is any other, real error, then stop processing this socket. This of course means
|
||||
* we won't take notification messages anymore, but that's still better than busy looping:
|
||||
@ -2829,11 +2833,6 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t) n >= sizeof(buf) || (msghdr.msg_flags & MSG_TRUNC)) {
|
||||
log_warning("Received notify message exceeded maximum size. Ignoring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* As extra safety check, let's make sure the string we get doesn't contain embedded NUL bytes.
|
||||
* We permit one trailing NUL byte in the message, but don't expect it. */
|
||||
if (n > 1 && memchr(buf, 0, n-1)) {
|
||||
@ -4932,20 +4931,22 @@ static int manager_dispatch_handoff_timestamp_fd(sd_event_source *source, int fd
|
||||
|
||||
assert(source);
|
||||
|
||||
n = recvmsg_safe(m->handoff_timestamp_fds[0], &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
|
||||
n = recvmsg_safe(m->handoff_timestamp_fds[0], &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
return 0; /* Spurious wakeup, try again */
|
||||
if (n == -ECHRNG) {
|
||||
log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n == -EXFULL) {
|
||||
log_warning("Got message with truncated control, ignoring.");
|
||||
log_warning_errno(n, "Got message with truncated payload data, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n < 0)
|
||||
return log_error_errno(n, "Failed to receive handoff timestamp message: %m");
|
||||
|
||||
if (msghdr.msg_flags & MSG_TRUNC) {
|
||||
log_warning("Got truncated handoff timestamp message, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
cmsg_close_all(&msghdr);
|
||||
|
||||
if (n != sizeof(ts)) {
|
||||
log_warning("Got handoff timestamp message of unexpected size %zi (expected %zu), ignoring.", n, sizeof(ts));
|
||||
return 0;
|
||||
|
@ -633,7 +633,7 @@ static Manager *manager_unref(Manager *m) {
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
|
||||
|
||||
static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
char buf[NOTIFY_BUFFER_MAX+1];
|
||||
struct iovec iovec = {
|
||||
.iov_base = buf,
|
||||
@ -647,33 +647,32 @@ 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;
|
||||
Manager *m = userdata;
|
||||
Transfer *t;
|
||||
ssize_t n;
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
if (ERRNO_IS_TRANSIENT(n))
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
return 0;
|
||||
if (n == -ECHRNG) {
|
||||
log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
|
||||
return 0;
|
||||
return (int) n;
|
||||
}
|
||||
if (n == -EXFULL) {
|
||||
log_warning_errno(n, "Got message with truncated payload data, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n < 0)
|
||||
return (int) n;
|
||||
|
||||
cmsg_close_all(&msghdr);
|
||||
|
||||
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);
|
||||
struct ucred *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;
|
||||
}
|
||||
|
||||
Transfer *t;
|
||||
HASHMAP_FOREACH(t, m->transfers)
|
||||
if (ucred->pid == t->pidref.pid)
|
||||
break;
|
||||
@ -685,7 +684,7 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
|
||||
|
||||
buf[n] = 0;
|
||||
|
||||
p = find_line_startswith(buf, "X_IMPORT_PROGRESS=");
|
||||
char *p = find_line_startswith(buf, "X_IMPORT_PROGRESS=");
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
|
@ -1549,39 +1549,42 @@ int server_process_datagram(
|
||||
iovec = IOVEC_MAKE(s->buffer, MALLOC_ELEMENTSOF(s->buffer) - 1); /* Leave room for trailing NUL we add later */
|
||||
|
||||
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
if (ERRNO_IS_TRANSIENT(n))
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
return 0;
|
||||
if (n == -EXFULL) {
|
||||
log_ratelimit_warning(JOURNAL_LOG_RATELIMIT,
|
||||
if (n == -ECHRNG) {
|
||||
log_ratelimit_warning_errno(n, JOURNAL_LOG_RATELIMIT,
|
||||
"Got message with truncated control data (too many fds sent?), ignoring.");
|
||||
return 0;
|
||||
}
|
||||
return log_ratelimit_error_errno(n, JOURNAL_LOG_RATELIMIT, "recvmsg() failed: %m");
|
||||
if (n == -EXFULL) {
|
||||
log_ratelimit_warning_errno(n, JOURNAL_LOG_RATELIMIT, "Got message with truncated payload data, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n < 0)
|
||||
return log_ratelimit_error_errno(n, JOURNAL_LOG_RATELIMIT, "Failed to receive message: %m");
|
||||
|
||||
CMSG_FOREACH(cmsg, &msghdr)
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_CREDENTIALS &&
|
||||
CMSG_FOREACH(cmsg, &msghdr) {
|
||||
if (cmsg->cmsg_level != SOL_SOCKET)
|
||||
continue;
|
||||
|
||||
if (cmsg->cmsg_type == SCM_CREDENTIALS &&
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
|
||||
assert(!ucred);
|
||||
ucred = CMSG_TYPED_DATA(cmsg, struct ucred);
|
||||
} else if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_SECURITY) {
|
||||
} else if (cmsg->cmsg_type == SCM_SECURITY) {
|
||||
assert(!label);
|
||||
label = CMSG_TYPED_DATA(cmsg, char);
|
||||
label_len = cmsg->cmsg_len - CMSG_LEN(0);
|
||||
} else if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_TIMESTAMP &&
|
||||
} else if (cmsg->cmsg_type == SCM_TIMESTAMP &&
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) {
|
||||
assert(!tv);
|
||||
tv = memcpy(&tv_buf, CMSG_DATA(cmsg), sizeof(struct timeval));
|
||||
} else if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
} else if (cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
assert(!fds);
|
||||
fds = CMSG_TYPED_DATA(cmsg, int);
|
||||
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
|
||||
}
|
||||
}
|
||||
|
||||
/* And a trailing NUL, just in case */
|
||||
s->buffer[n] = 0;
|
||||
|
@ -600,16 +600,15 @@ _public_ int sd_device_monitor_receive(sd_device_monitor *m, sd_device **ret) {
|
||||
|
||||
iov = IOVEC_MAKE(message.buf, n);
|
||||
|
||||
n = recvmsg(m->sock, &smsg, 0);
|
||||
n = recvmsg_safe(m->sock, &smsg, 0);
|
||||
if (n < 0) {
|
||||
if (!ERRNO_IS_TRANSIENT(errno))
|
||||
log_monitor_errno(m, errno, "Failed to receive message: %m");
|
||||
return -errno;
|
||||
if (!ERRNO_IS_NEG_TRANSIENT(n))
|
||||
log_monitor_errno(m, n, "Failed to receive message: %s",
|
||||
n == -ECHRNG ? "got truncated control data" :
|
||||
n == -EXFULL ? "got truncated payload data" :
|
||||
STRERROR((int) n));
|
||||
return n;
|
||||
}
|
||||
|
||||
if (smsg.msg_flags & MSG_TRUNC)
|
||||
return log_monitor_errno(m, SYNTHETIC_ERRNO(EINVAL), "Received truncated message, ignoring message.");
|
||||
|
||||
if (n < 32)
|
||||
return log_monitor_errno(m, SYNTHETIC_ERRNO(EINVAL), "Invalid message length (%zi), ignoring message.", n);
|
||||
|
||||
|
@ -176,14 +176,19 @@ static int socket_recv_message(int fd, void *buf, size_t buf_size, uint32_t *ret
|
||||
assert(fd >= 0);
|
||||
assert(peek || (buf && buf_size > 0));
|
||||
|
||||
n = recvmsg_safe(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
|
||||
if (n == -ENOBUFS)
|
||||
return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun");
|
||||
else if (ERRNO_IS_NEG_TRANSIENT(n)) {
|
||||
n = recvmsg_safe(fd, &msg, peek ? (MSG_PEEK|MSG_TRUNC) : 0);
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n)) {
|
||||
if (ret_mcast_group)
|
||||
*ret_mcast_group = 0;
|
||||
return 0;
|
||||
} else if (n < 0)
|
||||
}
|
||||
if (n == -ENOBUFS)
|
||||
return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun");
|
||||
if (n == -ECHRNG)
|
||||
return log_debug_errno(n, "sd-netlink: got truncated control message");
|
||||
if (n == -EXFULL)
|
||||
return log_debug_errno(n, "sd-netlink: got truncated payload message");
|
||||
if (n < 0)
|
||||
return (int) n;
|
||||
|
||||
if (sender.nl.nl_pid != 0) {
|
||||
@ -202,9 +207,6 @@ static int socket_recv_message(int fd, void *buf, size_t buf_size, uint32_t *ret
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!peek && (size_t) n > buf_size) /* message did not fit in read buffer */
|
||||
return -EIO;
|
||||
|
||||
if (ret_mcast_group) {
|
||||
struct nl_pktinfo *pi;
|
||||
|
||||
|
@ -870,23 +870,25 @@ static int varlink_read(sd_varlink *v) {
|
||||
bool prefer_read = v->prefer_read;
|
||||
if (!prefer_read) {
|
||||
n = recv(v->input_fd, p, rs, MSG_DONTWAIT);
|
||||
if (n < 0 && errno == ENOTSOCK)
|
||||
if (n < 0)
|
||||
n = -errno;
|
||||
if (n == -ENOTSOCK)
|
||||
prefer_read = v->prefer_read = true;
|
||||
}
|
||||
if (prefer_read)
|
||||
if (prefer_read) {
|
||||
n = read(v->input_fd, p, rs);
|
||||
if (n < 0)
|
||||
n = -errno;
|
||||
}
|
||||
if (n < 0) {
|
||||
if (errno == EAGAIN)
|
||||
}
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
return 0;
|
||||
|
||||
if (ERRNO_IS_DISCONNECT(errno)) {
|
||||
if (ERRNO_IS_NEG_DISCONNECT(n)) {
|
||||
v->read_disconnected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -errno;
|
||||
}
|
||||
if (n < 0)
|
||||
return n;
|
||||
if (n == 0) { /* EOF */
|
||||
|
||||
if (v->allow_fd_passing_input)
|
||||
|
@ -215,21 +215,13 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
|
||||
|
||||
case MACHINE_CONTAINER: {
|
||||
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
|
||||
_cleanup_free_ char *us = NULL, *them = NULL;
|
||||
_cleanup_close_ int netns_fd = -EBADF;
|
||||
const char *p;
|
||||
pid_t child;
|
||||
|
||||
r = readlink_malloc("/proc/self/ns/net", &us);
|
||||
r = in_same_namespace(0, m->leader.pid, NAMESPACE_NET);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = procfs_file_alloca(m->leader.pid, "ns/net");
|
||||
r = readlink_malloc(p, &them);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (streq(us, them))
|
||||
if (r > 0)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);
|
||||
|
||||
r = pidref_namespace_open(&m->leader,
|
||||
@ -290,9 +282,9 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
|
||||
iov[0] = IOVEC_MAKE(&family, sizeof(family));
|
||||
iov[1] = IOVEC_MAKE(&in_addr, sizeof(in_addr));
|
||||
|
||||
n = recvmsg(pair[0], &mh, 0);
|
||||
n = recvmsg_safe(pair[0], &mh, 0);
|
||||
if (n < 0)
|
||||
return -errno;
|
||||
return n;
|
||||
if ((size_t) n < sizeof(family))
|
||||
break;
|
||||
|
||||
|
@ -4485,10 +4485,15 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
|
||||
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
return 0;
|
||||
else if (n == -EXFULL) {
|
||||
log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
|
||||
if (n == -ECHRNG) {
|
||||
log_warning_errno(n, "Got message with truncated control data (too many fds sent?), ignoring.");
|
||||
return 0;
|
||||
} else if (n < 0)
|
||||
}
|
||||
if (n == -EXFULL) {
|
||||
log_warning_errno(n, "Got message with truncated payload data, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n < 0)
|
||||
return log_warning_errno(n, "Couldn't read notification socket: %m");
|
||||
|
||||
cmsg_close_all(&msghdr);
|
||||
@ -4499,11 +4504,6 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t) n >= sizeof(buf)) {
|
||||
log_warning("Received notify message exceeded maximum size. Ignoring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[n] = 0;
|
||||
tags = strv_split(buf, "\n\r");
|
||||
if (!tags)
|
||||
|
@ -867,8 +867,6 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
|
||||
if (l <= 0)
|
||||
return l;
|
||||
|
||||
assert(!(mh.msg_flags & MSG_TRUNC));
|
||||
|
||||
p->size = (size_t) l;
|
||||
|
||||
p->family = sa.sa.sa_family;
|
||||
|
@ -53,8 +53,6 @@ static int server_recv(int fd, DnsPacket **ret) {
|
||||
if (l <= 0)
|
||||
return l;
|
||||
|
||||
assert(!(mh.msg_flags & MSG_TRUNC));
|
||||
|
||||
p->size = (size_t) l;
|
||||
|
||||
p->family = sa.sa.sa_family;
|
||||
|
@ -873,10 +873,15 @@ int ask_password_agent(
|
||||
n = recvmsg_safe(socket_fd, &msghdr, 0);
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
continue;
|
||||
else if (n == -EXFULL) {
|
||||
log_debug("Got message with truncated control data, ignoring.");
|
||||
if (n == -ECHRNG) {
|
||||
log_debug_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
|
||||
continue;
|
||||
} else if (n < 0) {
|
||||
}
|
||||
if (n == -EXFULL) {
|
||||
log_debug_errno(n, "Got message with truncated payload data, ignoring.");
|
||||
continue;
|
||||
}
|
||||
if (n < 0) {
|
||||
r = (int) n;
|
||||
goto finish;
|
||||
}
|
||||
|
@ -938,19 +938,21 @@ static int helper_on_notify(sd_event_source *s, int fd, uint32_t revents, void *
|
||||
int r;
|
||||
|
||||
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
if (ERRNO_IS_TRANSIENT(n))
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
return 0;
|
||||
if (n == -ECHRNG) {
|
||||
log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
|
||||
return 0;
|
||||
return (int) n;
|
||||
}
|
||||
if (n == -EXFULL) {
|
||||
log_warning_errno(n, "Got message with truncated payload data, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n < 0)
|
||||
return (int) n;
|
||||
|
||||
cmsg_close_all(&msghdr);
|
||||
|
||||
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.");
|
||||
|
@ -1460,19 +1460,21 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
|
||||
char *version, *progress, *errno_str, *ready;
|
||||
|
||||
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
if (ERRNO_IS_TRANSIENT(n))
|
||||
if (ERRNO_IS_NEG_TRANSIENT(n))
|
||||
return 0;
|
||||
if (n == -ECHRNG) {
|
||||
log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
|
||||
return 0;
|
||||
return (int) n;
|
||||
}
|
||||
if (n == -EXFULL) {
|
||||
log_warning_errno(n, "Got message with truncated payload data, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (n < 0)
|
||||
return (int) n;
|
||||
|
||||
cmsg_close_all(&msghdr);
|
||||
|
||||
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.");
|
||||
|
@ -423,15 +423,18 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
|
||||
}
|
||||
|
||||
len = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT);
|
||||
if (len == -EAGAIN)
|
||||
if (ERRNO_IS_NEG_TRANSIENT(len))
|
||||
return 0;
|
||||
if (len < 0) {
|
||||
log_warning_errno(len, "Error receiving message, disconnecting: %m");
|
||||
log_warning_errno(len, "Error receiving message, disconnecting: %s",
|
||||
len == -ECHRNG ? "got truncated control data" :
|
||||
len == -EXFULL ? "got truncated payload data" :
|
||||
STRERROR((int) len));
|
||||
return manager_connect(m);
|
||||
}
|
||||
|
||||
/* Too short or too long packet? */
|
||||
if (iov.iov_len < sizeof(struct ntp_msg) || (msghdr.msg_flags & MSG_TRUNC)) {
|
||||
/* Too short packet? */
|
||||
if (iov.iov_len < sizeof(struct ntp_msg)) {
|
||||
log_warning("Invalid response from server. Disconnecting.");
|
||||
return manager_connect(m);
|
||||
}
|
||||
|
@ -169,33 +169,40 @@ static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32
|
||||
* To avoid the object freed, let's increment the refcount. */
|
||||
uctrl = udev_ctrl_ref(userdata);
|
||||
|
||||
size = next_datagram_size_fd(fd);
|
||||
if (size < 0)
|
||||
return log_error_errno(size, "Failed to get size of message: %m");
|
||||
if (size == 0)
|
||||
return 0; /* Client disconnects? */
|
||||
|
||||
size = recvmsg_safe(fd, &smsg, 0);
|
||||
if (size == -EINTR)
|
||||
if (ERRNO_IS_NEG_TRANSIENT(size))
|
||||
return 0;
|
||||
if (size == -ECHRNG) {
|
||||
log_warning_errno(size, "Got message with truncated control data (unexpected fds sent?), ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (size == -EXFULL) {
|
||||
log_warning_errno(size, "Got message with truncated payload data, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
if (size < 0)
|
||||
return log_error_errno(size, "Failed to receive ctrl message: %m");
|
||||
|
||||
cmsg_close_all(&smsg);
|
||||
|
||||
if (size != sizeof(msg_wire)) {
|
||||
log_warning("Received message with invalid length, ignoring");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cred = CMSG_FIND_DATA(&smsg, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||
if (!cred) {
|
||||
log_error("No sender credentials received, ignoring message");
|
||||
log_warning("No sender credentials received, ignoring message");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cred->uid != 0) {
|
||||
log_error("Invalid sender uid "UID_FMT", ignoring message", cred->uid);
|
||||
log_warning("Invalid sender uid "UID_FMT", ignoring message", cred->uid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg_wire.magic != UDEV_CTRL_MAGIC) {
|
||||
log_error("Message magic 0x%08x doesn't match, ignoring message", msg_wire.magic);
|
||||
log_warning("Message magic 0x%08x doesn't match, ignoring message", msg_wire.magic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user