summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-04-13 18:00:41 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-04-16 13:26:55 +0900
commit4836f4c67d040f51b7d1aa45b73553eb0da26097 (patch)
tree3d915ffc81ad3d9ab83c8f112bc24489c8f40b3a /src
parent1113e50796315a2aaaf768a243e3788cdb4aac78 (diff)
downloadsystemd-4836f4c67d040f51b7d1aa45b73553eb0da26097.tar.gz
socket-util: introduce CMSG_FIND_AND_COPY_DATA()
The cmd(3) man page says about CMSG_DATA(): > The pointer returned cannot be assumed to be suitably aligned for > accessing arbitrary payload data types. Applications should not cast > it to a pointer type matching the payload, but should instead use > memcpy(3) to copy data to or from a suitably declared object. Hence, if we want to use unaligned data in cmsg, we need to copy it before use. That's typically important for reading timestamps in RISCV32, as the time_t is 64bit and size_t is 32bit on the system.
Diffstat (limited to 'src')
-rw-r--r--src/basic/socket-util.c18
-rw-r--r--src/basic/socket-util.h5
2 files changed, 23 insertions, 0 deletions
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index b35de4dad6..5b76948c06 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -1171,6 +1171,24 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
return NULL;
}
+void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf, size_t buf_len) {
+ struct cmsghdr *cmsg;
+
+ assert(mh);
+ assert(buf);
+ assert(buf_len > 0);
+
+ /* This is similar to cmsg_find_data(), but copy the found data to buf. This should be typically used
+ * when reading possibly unaligned data such as timestamp, as time_t is 64bit and size_t is 32bit on
+ * RISCV32. See issue #27241. */
+
+ cmsg = cmsg_find(mh, level, type, CMSG_LEN(buf_len));
+ if (!cmsg)
+ return NULL;
+
+ return memcpy_safe(buf, CMSG_DATA(cmsg), buf_len);
+}
+
int socket_ioctl_fd(void) {
int fd;
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index d6d63a4f33..b323b1b99f 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -189,11 +189,16 @@ int flush_accept(int fd);
})
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
+void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf, size_t buf_len);
/* Type-safe, dereferencing version of cmsg_find() */
#define CMSG_FIND_DATA(mh, level, type, ctype) \
CMSG_TYPED_DATA(cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))), ctype)
+/* Type-safe version of cmsg_find_and_copy_data() */
+#define CMSG_FIND_AND_COPY_DATA(mh, level, type, ctype) \
+ (ctype*) cmsg_find_and_copy_data(mh, level, type, &(ctype){}, sizeof(ctype))
+
/* Resolves to a type that can carry cmsghdr structures. Make sure things are properly aligned, i.e. the type
* itself is placed properly in memory and the size is also aligned to what's appropriate for "cmsghdr"
* structures. */