summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-04-14 13:49:04 +0900
committerGitHub <noreply@github.com>2023-04-14 13:49:04 +0900
commit13524b29a2833675518b5d5701344196429cb924 (patch)
tree2d77cfb4f9010b3c707dfc699a5b9b06043d8016 /src
parent2cba2fcd250b0afa543ae4d8869231d16bc28a87 (diff)
parentca918f63b7a98442d2925c0a668c911d8140215b (diff)
downloadsystemd-13524b29a2833675518b5d5701344196429cb924.tar.gz
Merge pull request #27254 from poettering/cmsg-align-check
socket-util: tighten CMSG_TYPED_DATA() alignment checks
Diffstat (limited to 'src')
-rw-r--r--src/basic/socket-util.c2
-rw-r--r--src/basic/socket-util.h7
-rw-r--r--src/core/manager.c4
-rw-r--r--src/coredump/coredump.c2
-rw-r--r--src/home/homed-manager.c4
-rw-r--r--src/journal/journald-server.c8
-rw-r--r--src/libsystemd-network/icmp6-util.c4
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c2
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c2
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c8
-rw-r--r--src/libsystemd/sd-device/device-monitor.c6
-rw-r--r--src/resolve/resolved-dns-stream.c8
-rw-r--r--src/resolve/resolved-manager.c12
-rw-r--r--src/udev/udev-ctrl.c8
14 files changed, 39 insertions, 38 deletions
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 43b292252c..b35de4dad6 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -1047,7 +1047,7 @@ ssize_t receive_one_fd_iov(
}
if (found)
- *ret_fd = *(int*) CMSG_DATA(found);
+ *ret_fd = *CMSG_TYPED_DATA(found, int);
else
*ret_fd = -EBADF;
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 0bfb29d417..7d504319a8 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -175,9 +175,16 @@ int flush_accept(int fd);
#define CMSG_FOREACH(cmsg, mh) \
for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
+/* Returns the cmsghdr's data pointer, but safely cast to the specified type. Does two alignment checks: one
+ * at compile time, that the requested type has a smaller or same alignment as 'struct cmsghdr', and one
+ * during runtime, that the actual pointer matches the alignment too. This is supposed to catch cases such as
+ * 'struct timeval' is embedded into 'struct cmsghdr' on architectures where the alignment of the former is 8
+ * bytes (because of a 64bit time_t), but of the latter is 4 bytes (because size_t is 32bit), such as
+ * riscv32. */
#define CMSG_TYPED_DATA(cmsg, type) \
({ \
struct cmsghdr *_cmsg = cmsg; \
+ assert_cc(__alignof__(type) <= __alignof__(struct cmsghdr)); \
_cmsg ? CAST_ALIGN_PTR(type, CMSG_DATA(_cmsg)) : (type*) NULL; \
})
diff --git a/src/core/manager.c b/src/core/manager.c
index a42cfdb8e4..805ee0a38c 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -2629,7 +2629,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
assert(!fd_array);
- fd_array = (int*) CMSG_DATA(cmsg);
+ fd_array = CMSG_TYPED_DATA(cmsg, int);
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
@@ -2637,7 +2637,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
assert(!ucred);
- ucred = (struct ucred*) CMSG_DATA(cmsg);
+ ucred = CMSG_TYPED_DATA(cmsg, struct ucred);
}
}
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index b7a62e72b0..5fdcfa7437 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -1094,7 +1094,7 @@ static int process_socket(int fd) {
}
assert(input_fd < 0);
- input_fd = *(int*) CMSG_DATA(found);
+ input_fd = *CMSG_TYPED_DATA(found, int);
break;
} else
cmsg_close_all(&mh);
diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c
index 258d2b16ed..92fe5a88b8 100644
--- a/src/home/homed-manager.c
+++ b/src/home/homed-manager.c
@@ -1096,7 +1096,7 @@ static ssize_t read_datagram(
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
assert(!sender);
- sender = (struct ucred*) CMSG_DATA(cmsg);
+ sender = CMSG_TYPED_DATA(cmsg, struct ucred);
}
if (cmsg->cmsg_level == SOL_SOCKET &&
@@ -1108,7 +1108,7 @@ static ssize_t read_datagram(
}
assert(passed_fd < 0);
- passed_fd = *(int*) CMSG_DATA(cmsg);
+ passed_fd = *CMSG_TYPED_DATA(cmsg, int);
}
}
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 4d1820f9b0..b952269e2e 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1486,21 +1486,21 @@ int server_process_datagram(
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
assert(!ucred);
- ucred = (struct ucred*) CMSG_DATA(cmsg);
+ ucred = CMSG_TYPED_DATA(cmsg, struct ucred);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_SECURITY) {
assert(!label);
- label = (char*) CMSG_DATA(cmsg);
+ label = CMSG_TYPED_DATA(cmsg, char);
label_len = cmsg->cmsg_len - CMSG_LEN(0);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) {
assert(!tv);
- tv = (struct timeval*) CMSG_DATA(cmsg);
+ tv = CMSG_TYPED_DATA(cmsg, struct timeval);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
assert(!fds);
- fds = (int*) CMSG_DATA(cmsg);
+ fds = CMSG_TYPED_DATA(cmsg, int);
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
}
diff --git a/src/libsystemd-network/icmp6-util.c b/src/libsystemd-network/icmp6-util.c
index 00a59291a1..fba5c3bd96 100644
--- a/src/libsystemd-network/icmp6-util.c
+++ b/src/libsystemd-network/icmp6-util.c
@@ -192,7 +192,7 @@ int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *ret_dst,
if (cmsg->cmsg_level == SOL_IPV6 &&
cmsg->cmsg_type == IPV6_HOPLIMIT &&
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
- int hops = *(int*) CMSG_DATA(cmsg);
+ int hops = *CMSG_TYPED_DATA(cmsg, int);
if (hops != 255)
return -EMULTIHOP;
@@ -201,7 +201,7 @@ int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *ret_dst,
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
- triple_timestamp_from_realtime(&t, timeval_load((struct timeval*) CMSG_DATA(cmsg)));
+ triple_timestamp_from_realtime(&t, timeval_load(CMSG_TYPED_DATA(cmsg, struct timeval)));
}
if (!triple_timestamp_is_set(&t))
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index cffe7ba917..f207cf0c1e 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1981,7 +1981,7 @@ static int client_receive_message_raw(
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);
+ struct tpacket_auxdata *aux = CMSG_TYPED_DATA(cmsg, struct tpacket_auxdata);
checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
}
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 5de230aaed..15a0145959 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -1310,7 +1310,7 @@ static int server_receive_message(sd_event_source *s, int fd,
if (cmsg->cmsg_level == IPPROTO_IP &&
cmsg->cmsg_type == IP_PKTINFO &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) {
- struct in_pktinfo *info = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ struct in_pktinfo *info = CMSG_TYPED_DATA(cmsg, struct in_pktinfo);
/* TODO figure out if this can be done as a filter on
* the socket, like for IPv6 */
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 33cfeebda7..ceda20f289 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -604,7 +604,7 @@ static int bus_socket_read_auth(sd_bus *b) {
* protocol? Somebody is playing games with
* us. Close them all, and fail */
j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
- close_many((int*) CMSG_DATA(cmsg), j);
+ close_many(CMSG_TYPED_DATA(cmsg, int), j);
return -EIO;
} else
log_debug("Got unexpected auxiliary data with level=%d and type=%d",
@@ -1268,18 +1268,18 @@ int bus_socket_read_message(sd_bus *bus) {
* isn't actually enabled? Close them,
* and fail */
- close_many((int*) CMSG_DATA(cmsg), n);
+ close_many(CMSG_TYPED_DATA(cmsg, int), n);
return -EIO;
}
f = reallocarray(bus->fds, bus->n_fds + n, sizeof(int));
if (!f) {
- close_many((int*) CMSG_DATA(cmsg), n);
+ close_many(CMSG_TYPED_DATA(cmsg, int), n);
return -ENOMEM;
}
for (i = 0; i < n; i++)
- f[bus->n_fds++] = fd_move_above_stdio(((int*) CMSG_DATA(cmsg))[i]);
+ f[bus->n_fds++] = fd_move_above_stdio(CMSG_TYPED_DATA(cmsg, int)[i]);
bus->fds = f;
} else
log_debug("Got unexpected auxiliary data with level=%d and type=%d",
diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c
index af093385da..a23b5e7847 100644
--- a/src/libsystemd/sd-device/device-monitor.c
+++ b/src/libsystemd/sd-device/device-monitor.c
@@ -503,7 +503,6 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
.msg_name = &snl,
.msg_namelen = sizeof(snl),
};
- struct cmsghdr *cmsg;
struct ucred *cred;
size_t offset;
ssize_t n;
@@ -559,12 +558,11 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
snl.nl.nl_pid);
}
- cmsg = CMSG_FIRSTHDR(&smsg);
- if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS)
+ cred = CMSG_FIND_DATA(&smsg, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
+ if (!cred)
return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
"No sender credentials received, ignoring message.");
- cred = (struct ucred*) CMSG_DATA(cmsg);
if (!check_sender_uid(m, cred->uid))
return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
"Sender uid="UID_FMT", message ignored.", cred->uid);
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index 0a10a0d17e..85e4762ba2 100644
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -147,7 +147,7 @@ static int dns_stream_identify(DnsStream *s) {
switch (cmsg->cmsg_type) {
case IPV6_PKTINFO: {
- struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
+ struct in6_pktinfo *i = CMSG_TYPED_DATA(cmsg, struct in6_pktinfo);
if (s->ifindex <= 0)
s->ifindex = i->ipi6_ifindex;
@@ -155,7 +155,7 @@ static int dns_stream_identify(DnsStream *s) {
}
case IPV6_HOPLIMIT:
- s->ttl = *(int *) CMSG_DATA(cmsg);
+ s->ttl = *CMSG_TYPED_DATA(cmsg, int);
break;
}
@@ -165,7 +165,7 @@ static int dns_stream_identify(DnsStream *s) {
switch (cmsg->cmsg_type) {
case IP_PKTINFO: {
- struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
+ struct in_pktinfo *i = CMSG_TYPED_DATA(cmsg, struct in_pktinfo);
if (s->ifindex <= 0)
s->ifindex = i->ipi_ifindex;
@@ -173,7 +173,7 @@ static int dns_stream_identify(DnsStream *s) {
}
case IP_TTL:
- s->ttl = *(int *) CMSG_DATA(cmsg);
+ s->ttl = *CMSG_TYPED_DATA(cmsg, int);
break;
}
}
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 57e26f4975..e5e1411a13 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -834,7 +834,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
switch (cmsg->cmsg_type) {
case IPV6_PKTINFO: {
- struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
+ struct in6_pktinfo *i = CMSG_TYPED_DATA(cmsg, struct in6_pktinfo);
if (p->ifindex <= 0)
p->ifindex = i->ipi6_ifindex;
@@ -844,11 +844,11 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
}
case IPV6_HOPLIMIT:
- p->ttl = *(int *) CMSG_DATA(cmsg);
+ p->ttl = *CMSG_TYPED_DATA(cmsg, int);
break;
case IPV6_RECVFRAGSIZE:
- p->fragsize = *(int *) CMSG_DATA(cmsg);
+ p->fragsize = *CMSG_TYPED_DATA(cmsg, int);
break;
}
} else if (cmsg->cmsg_level == IPPROTO_IP) {
@@ -857,7 +857,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
switch (cmsg->cmsg_type) {
case IP_PKTINFO: {
- struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
+ struct in_pktinfo *i = CMSG_TYPED_DATA(cmsg, struct in_pktinfo);
if (p->ifindex <= 0)
p->ifindex = i->ipi_ifindex;
@@ -867,11 +867,11 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
}
case IP_TTL:
- p->ttl = *(int *) CMSG_DATA(cmsg);
+ p->ttl = *CMSG_TYPED_DATA(cmsg, int);
break;
case IP_RECVFRAGSIZE:
- p->fragsize = *(int *) CMSG_DATA(cmsg);
+ p->fragsize = *CMSG_TYPED_DATA(cmsg, int);
break;
}
}
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index 24180f9418..7d9a8c018f 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -161,7 +161,6 @@ static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32
.msg_control = &control,
.msg_controllen = sizeof(control),
};
- struct cmsghdr *cmsg;
struct ucred *cred;
ssize_t size;
@@ -185,15 +184,12 @@ static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32
cmsg_close_all(&smsg);
- cmsg = CMSG_FIRSTHDR(&smsg);
-
- if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
+ cred = CMSG_FIND_DATA(&smsg, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
+ if (!cred) {
log_error("No sender credentials received, ignoring message");
return 0;
}
- cred = (struct ucred *) CMSG_DATA(cmsg);
-
if (cred->uid != 0) {
log_error("Invalid sender uid "UID_FMT", ignoring message", cred->uid);
return 0;