diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2023-04-16 16:28:26 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-16 16:28:26 +0900 |
commit | d8e75260e9667225638e32cd1e4cf897cb7b7adb (patch) | |
tree | afdd17ba5403d479fed7f5187b3179406db18f2a /src/basic | |
parent | 23603bc67f86384a037b287f66b13db6482feafe (diff) | |
parent | b5d39bb3cae7e36c284fcfcc87a42ff8a2bae7f5 (diff) | |
download | systemd-d8e75260e9667225638e32cd1e4cf897cb7b7adb.tar.gz |
Merge pull request #27253 from yuwata/cmsg-find-and-copy-data
socket-util: introduce CMSG_FIND_AND_COPY_DATA()
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/socket-util.c | 18 | ||||
-rw-r--r-- | src/basic/socket-util.h | 9 |
2 files changed, 25 insertions, 2 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 7d504319a8..b323b1b99f 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -183,17 +183,22 @@ int flush_accept(int fd); * riscv32. */ #define CMSG_TYPED_DATA(cmsg, type) \ ({ \ - struct cmsghdr *_cmsg = cmsg; \ - assert_cc(__alignof__(type) <= __alignof__(struct cmsghdr)); \ + struct cmsghdr *_cmsg = (cmsg); \ + assert_cc(alignof(type) <= alignof(struct cmsghdr)); \ _cmsg ? CAST_ALIGN_PTR(type, CMSG_DATA(_cmsg)) : (type*) NULL; \ }) 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. */ |