mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-25 06:03:40 +03:00
Merge pull request #15570 from poettering/cmsg-find
CMSG_FIND_DATA() and cmsg_find() work
This commit is contained in:
commit
11f9379866
@ -887,7 +887,7 @@ ssize_t receive_one_fd_iov(
|
|||||||
.msg_iov = iov,
|
.msg_iov = iov,
|
||||||
.msg_iovlen = iovlen,
|
.msg_iovlen = iovlen,
|
||||||
};
|
};
|
||||||
struct cmsghdr *cmsg, *found = NULL;
|
struct cmsghdr *found;
|
||||||
ssize_t k;
|
ssize_t k;
|
||||||
|
|
||||||
assert(transport_fd >= 0);
|
assert(transport_fd >= 0);
|
||||||
@ -905,16 +905,7 @@ ssize_t receive_one_fd_iov(
|
|||||||
if (k < 0)
|
if (k < 0)
|
||||||
return k;
|
return k;
|
||||||
|
|
||||||
CMSG_FOREACH(cmsg, &mh) {
|
found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int)));
|
||||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
||||||
cmsg->cmsg_type == SCM_RIGHTS &&
|
|
||||||
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
|
|
||||||
assert(!found);
|
|
||||||
found = cmsg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
cmsg_close_all(&mh);
|
cmsg_close_all(&mh);
|
||||||
|
|
||||||
|
@ -158,6 +158,14 @@ int flush_accept(int fd);
|
|||||||
|
|
||||||
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
|
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
|
* 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
|
* (8 bytes) and run over the structure. This macro returns the correct size that
|
||||||
|
@ -921,19 +921,11 @@ static int process_socket(int fd) {
|
|||||||
/* The final zero-length datagram carries the file descriptor and tells us
|
/* The final zero-length datagram carries the file descriptor and tells us
|
||||||
* that we're done. */
|
* that we're done. */
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
struct cmsghdr *cmsg, *found = NULL;
|
struct cmsghdr *found;
|
||||||
|
|
||||||
free(iovec.iov_base);
|
free(iovec.iov_base);
|
||||||
|
|
||||||
CMSG_FOREACH(cmsg, &mh) {
|
found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int)));
|
||||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
||||||
cmsg->cmsg_type == SCM_RIGHTS &&
|
|
||||||
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
|
|
||||||
assert(!found);
|
|
||||||
found = cmsg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
cmsg_close_all(&mh);
|
cmsg_close_all(&mh);
|
||||||
r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
|
r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||||
|
@ -557,9 +557,8 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
|
|||||||
.msg_control = &control,
|
.msg_control = &control,
|
||||||
.msg_controllen = sizeof(control),
|
.msg_controllen = sizeof(control),
|
||||||
};
|
};
|
||||||
struct ucred *ucred = NULL;
|
struct ucred *ucred;
|
||||||
Manager *m = userdata;
|
Manager *m = userdata;
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
char *p, *e;
|
char *p, *e;
|
||||||
Transfer *t;
|
Transfer *t;
|
||||||
Iterator i;
|
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_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) {
|
if (msghdr.msg_flags & MSG_TRUNC) {
|
||||||
log_warning("Got overly long notification datagram, ignoring.");
|
log_warning("Got overly long notification datagram, ignoring.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||||
if (!ucred || ucred->pid <= 0) {
|
if (!ucred || ucred->pid <= 0) {
|
||||||
log_warning("Got notification datagram lacking credential information, ignoring.");
|
log_warning("Got notification datagram lacking credential information, ignoring.");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -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) {
|
static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
|
||||||
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
|
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
|
||||||
StdoutStream *s = userdata;
|
StdoutStream *s = userdata;
|
||||||
struct ucred *ucred = NULL;
|
struct ucred *ucred;
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
struct iovec iovec;
|
struct iovec iovec;
|
||||||
size_t limit;
|
size_t limit;
|
||||||
ssize_t l;
|
ssize_t l;
|
||||||
@ -541,25 +540,14 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
|
|||||||
goto terminate;
|
goto terminate;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMSG_FOREACH(cmsg, &msghdr)
|
/* Invalidate the context if the pid of the sender changed. This happens when a forked process
|
||||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
* inherits stdout / stderr from a parent. In this case getpeercred returns the ucred of the parent,
|
||||||
cmsg->cmsg_type == SCM_CREDENTIALS &&
|
* which can be invalid if the parent has exited in the meantime.
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
|
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||||
if (ucred && ucred->pid != s->ucred.pid) {
|
if (ucred && ucred->pid != s->ucred.pid) {
|
||||||
/* force out any previously half-written lines from a
|
/* force out any previously half-written lines from a different process, before we switch to
|
||||||
* different process, before we switch to the new ucred
|
* the new ucred structure for everything we just added */
|
||||||
* structure for everything we just added */
|
|
||||||
r = stdout_stream_scan(s, true);
|
r = stdout_stream_scan(s, true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto terminate;
|
goto terminate;
|
||||||
|
@ -1937,14 +1937,10 @@ static int client_receive_message_raw(
|
|||||||
if ((size_t) len < sizeof(DHCPPacket))
|
if ((size_t) len < sizeof(DHCPPacket))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CMSG_FOREACH(cmsg, &msg)
|
cmsg = cmsg_find(&msg, SOL_PACKET, PACKET_AUXDATA, CMSG_LEN(sizeof(struct tpacket_auxdata)));
|
||||||
if (cmsg->cmsg_level == SOL_PACKET &&
|
if (cmsg) {
|
||||||
cmsg->cmsg_type == PACKET_AUXDATA &&
|
|
||||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
|
|
||||||
struct tpacket_auxdata *aux = (struct tpacket_auxdata*) CMSG_DATA(cmsg);
|
struct tpacket_auxdata *aux = (struct tpacket_auxdata*) CMSG_DATA(cmsg);
|
||||||
|
|
||||||
checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
|
checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dhcp_packet_verify_headers(packet, len, checksum, client->port);
|
r = dhcp_packet_verify_headers(packet, len, checksum, client->port);
|
||||||
|
@ -238,7 +238,7 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
|
|||||||
return k;
|
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;
|
union sockaddr_union sender;
|
||||||
uint8_t cmsg_buffer[CMSG_SPACE(sizeof(struct nl_pktinfo))];
|
uint8_t cmsg_buffer[CMSG_SPACE(sizeof(struct nl_pktinfo))];
|
||||||
struct msghdr msg = {
|
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_control = cmsg_buffer,
|
||||||
.msg_controllen = sizeof(cmsg_buffer),
|
.msg_controllen = sizeof(cmsg_buffer),
|
||||||
};
|
};
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
uint32_t group = 0;
|
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
@ -281,19 +279,15 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMSG_FOREACH(cmsg, &msg) {
|
if (ret_mcast_group) {
|
||||||
if (cmsg->cmsg_level == SOL_NETLINK &&
|
struct cmsghdr *cmsg;
|
||||||
cmsg->cmsg_type == NETLINK_PKTINFO &&
|
|
||||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
|
|
||||||
struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
|
|
||||||
|
|
||||||
/* multi-cast group */
|
cmsg = cmsg_find(&msg, SOL_NETLINK, NETLINK_PKTINFO, CMSG_LEN(sizeof(struct nl_pktinfo)));
|
||||||
group = pktinfo->group;
|
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;
|
return (int) n;
|
||||||
}
|
}
|
||||||
|
@ -3698,8 +3698,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
|
|||||||
.msg_control = &control,
|
.msg_control = &control,
|
||||||
.msg_controllen = sizeof(control),
|
.msg_controllen = sizeof(control),
|
||||||
};
|
};
|
||||||
struct cmsghdr *cmsg;
|
struct ucred *ucred;
|
||||||
struct ucred *ucred = NULL;
|
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
pid_t inner_child_pid;
|
pid_t inner_child_pid;
|
||||||
_cleanup_strv_free_ char **tags = NULL;
|
_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_close_all(&msghdr);
|
||||||
|
|
||||||
CMSG_FOREACH(cmsg, &msghdr) {
|
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||||
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 (!ucred || ucred->pid != inner_child_pid) {
|
if (!ucred || ucred->pid != inner_child_pid) {
|
||||||
log_debug("Received notify message without valid credentials. Ignoring.");
|
log_debug("Received notify message without valid credentials. Ignoring.");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -940,15 +940,12 @@ int ask_password_agent(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
|
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||||
control.cmsghdr.cmsg_level != SOL_SOCKET ||
|
if (!ucred) {
|
||||||
control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
|
|
||||||
control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
|
|
||||||
log_debug("Received message without credentials. Ignoring.");
|
log_debug("Received message without credentials. Ignoring.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
|
|
||||||
if (ucred->uid != 0) {
|
if (ucred->uid != 0) {
|
||||||
log_debug("Got request from unprivileged user. Ignoring.");
|
log_debug("Got request from unprivileged user. Ignoring.");
|
||||||
continue;
|
continue;
|
||||||
|
@ -916,9 +916,8 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
|
|||||||
.msg_control = &control,
|
.msg_control = &control,
|
||||||
.msg_controllen = sizeof(control),
|
.msg_controllen = sizeof(control),
|
||||||
};
|
};
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
struct ucred *ucred = NULL;
|
struct ucred *ucred;
|
||||||
struct worker *worker;
|
struct worker *worker;
|
||||||
|
|
||||||
size = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMSG_FOREACH(cmsg, &msghdr)
|
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||||
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 (!ucred || ucred->pid <= 0) {
|
if (!ucred || ucred->pid <= 0) {
|
||||||
log_warning("Ignoring worker message without valid PID");
|
log_warning("Ignoring worker message without valid PID");
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user