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.
This commit is contained in:
Yu Watanabe 2023-04-13 18:00:41 +09:00
parent 1113e50796
commit 4836f4c67d
2 changed files with 23 additions and 0 deletions

View file

@ -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;

View file

@ -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. */