summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/systemd/systemd/27254.patch
blob: 3928088dc6aeb19b46606cbc12cb8dc0caadf69e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
From 79dec6f5cc0b72d43dfb0469fa68b5cd023fbaf9 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 13 Apr 2023 10:21:31 +0200
Subject: [PATCH 1/3] socket-util: tighten aignment check for CMSG_TYPED_DATA()

Apparently CMSG_DATA() alignment is very much undefined. Which is quite
an ABI fuck-up, but we need to deal with this. CMSG_TYPED_DATA() already
checks alignment of the specified pointer. Let's also check matching
alignment of the underlying structures, which we already can do at
compile-time.

See: #27241

(This does not fix #27241, but should catch such errors already at
compile-time instead of runtime)

Upstream-Status: Backport [https://github.com/systemd/systemd/pull/27254]
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
 src/basic/socket-util.h | 7 +++++++
 1 file changed, 7 insertions(+)

--- 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; \
         })
 
--- 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;
 
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -2503,7 +2503,7 @@ static int manager_dispatch_notify_fd(sd
                 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 &&
@@ -2511,7 +2511,7 @@ static int manager_dispatch_notify_fd(sd
                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
 
                         assert(!ucred);
-                        ucred = (struct ucred*) CMSG_DATA(cmsg);
+                        ucred = CMSG_TYPED_DATA(cmsg, struct ucred);
                 }
         }
 
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -1163,7 +1163,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);
--- a/src/home/homed-manager.c
+++ b/src/home/homed-manager.c
@@ -1086,7 +1086,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 &&
@@ -1098,7 +1098,7 @@ static ssize_t read_datagram(
                         }
 
                         assert(passed_fd < 0);
-                        passed_fd = *(int*) CMSG_DATA(cmsg);
+                        passed_fd = *CMSG_TYPED_DATA(cmsg, int);
                 }
         }
 
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1454,21 +1454,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);
                 }
 
--- 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,
                 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,
                 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))
--- 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);
         }
 
--- 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_eve
                 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 */
--- 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 *
                                  * 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",
@@ -1270,18 +1270,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",
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -147,7 +147,7 @@ static int dns_stream_identify(DnsStream
                         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
                         }
 
                         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
                         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
                         }
 
                         case IP_TTL:
-                                s->ttl = *(int *) CMSG_DATA(cmsg);
+                                s->ttl = *CMSG_TYPED_DATA(cmsg, int);
                                 break;
                         }
                 }
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -801,7 +801,7 @@ int manager_recv(Manager *m, int fd, Dns
                         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;
@@ -811,11 +811,11 @@ int manager_recv(Manager *m, int fd, Dns
                         }
 
                         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) {
@@ -824,7 +824,7 @@ int manager_recv(Manager *m, int fd, Dns
                         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;
@@ -834,11 +834,11 @@ int manager_recv(Manager *m, int fd, Dns
                         }
 
                         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;
                         }
                 }
--- 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_dev
                 .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_dev
                                                  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);
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -161,7 +161,6 @@ static int udev_ctrl_connection_event_ha
                 .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_ha
 
         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;