tree-wide: ignore messages with too long control data

Apparently SELinux inserts control data into AF_UNIX datagrams where we
don't expect it, thus miscalculating the control data. This looks like
something to fix in SELinux, but we still should handle this gracefully
and just drop the offending datagram and continue.

recvmsg_safe() actually already drops the datagram, it's just a matter
of actually ignoring EXFULL (which it generates if control data is too
large) in the right places.

This does this wherever an AF_UNIX/SOCK_DGRAM socket is used with
recvmsg_safe() that is not just internal communication.

Fixes: #17795
Follow-up for: 3691bcf3c5
This commit is contained in:
Lennart Poettering
2021-01-19 21:34:20 +01:00
committed by Yu Watanabe
parent 6eab0c6dba
commit 741bfd7f4e
3 changed files with 12 additions and 0 deletions

View File

@@ -2387,6 +2387,10 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
if (IN_SET(n, -EAGAIN, -EINTR))
return 0; /* Spurious wakeup, try again */
if (n == -EXFULL) {
log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
return 0;
}
if (n < 0)
/* If this is any other, real error, then let's stop processing this socket. This of course
* means we won't take notification messages anymore, but that's still better than busy

View File

@@ -3995,6 +3995,10 @@ 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 (IN_SET(n, -EAGAIN, -EINTR))
return 0;
if (n == -EXFULL) {
log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
return 0;
}
if (n < 0)
return log_warning_errno(n, "Couldn't read notification socket: %m");

View File

@@ -943,6 +943,10 @@ int ask_password_agent(
n = recvmsg_safe(socket_fd, &msghdr, 0);
if (IN_SET(n, -EAGAIN, -EINTR))
continue;
if (n == -EXFULL) {
log_debug("Got message with truncated control data, ignoring.");
continue;
}
if (n < 0) {
r = (int) n;
goto finish;