commit 278c2ee8f22638aca522d05826589261d36409b8 from: Thomas Adam date: Wed Nov 27 20:52:08 2024 UTC portable: update imsg from libutil imsg in OpenBSD has undergone a lot of changes recently. This commit includes fixes to imsg on Linux and hopefully other non-BSD systems. commit - eaecb958183f6eb4fdb79b3258d465a4fd8cb72e commit + 278c2ee8f22638aca522d05826589261d36409b8 blob - eac3e6ce0d139fe8d66e270264e48b4d3230572f blob + fc8ef7dbd7609263755a10aec3f4dfb6ab8d94fb --- compat/imsg-buffer.c +++ compat/imsg-buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg-buffer.c,v 1.28 2024/11/21 13:03:21 claudio Exp $ */ +/* $OpenBSD: imsg-buffer.c,v 1.31 2024/11/26 13:57:31 claudio Exp $ */ /* * Copyright (c) 2023 Claudio Jeker @@ -38,7 +38,7 @@ struct msgbuf { uint32_t queued; char *rbuf; struct ibuf *rpmsg; - ssize_t (*readhdr)(struct ibuf *, void *); + struct ibuf *(*readhdr)(struct ibuf *, void *, int *); void *rarg; size_t roff; size_t hdrsize; @@ -574,8 +574,8 @@ msgbuf_new(void) } struct msgbuf * -msgbuf_new_reader(size_t hdrsz, ssize_t (*readhdr)(struct ibuf *, void *), - void *arg) +msgbuf_new_reader(size_t hdrsz, + struct ibuf *(*readhdr)(struct ibuf *, void *, int *), void *arg) { struct msgbuf *msgbuf; char *buf; @@ -605,8 +605,9 @@ msgbuf_new_reader(size_t hdrsz, ssize_t (*readhdr)(str void msgbuf_free(struct msgbuf *msgbuf) { - if (msgbuf != NULL) - msgbuf_clear(msgbuf); + if (msgbuf == NULL) + return; + msgbuf_clear(msgbuf); free(msgbuf->rbuf); free(msgbuf); } @@ -757,33 +758,16 @@ ibuf_read_process(struct msgbuf *msgbuf, int fd) ibuf_from_buffer(&rbuf, msgbuf->rbuf, msgbuf->roff); - /* fds must be passed at start of message of at least hdrsize bytes */ - if (msgbuf->rpmsg != NULL && fd != -1) { - close(fd); - fd = -1; - } - do { if (msgbuf->rpmsg == NULL) { - if (ibuf_size(&rbuf) < msgbuf->hdrsize) { - if (fd != -1) { - close(fd); - fd = -1; - } + if (ibuf_size(&rbuf) < msgbuf->hdrsize) break; - } /* get size from header */ ibuf_from_buffer(&msg, ibuf_data(&rbuf), msgbuf->hdrsize); - sz = msgbuf->readhdr(&msg, msgbuf->rarg); - if (sz == -1) + if ((msgbuf->rpmsg = msgbuf->readhdr(&msg, + msgbuf->rarg, &fd)) == NULL) goto fail; - if ((msgbuf->rpmsg = ibuf_open(sz)) == NULL) - goto fail; - if (fd != -1) { - ibuf_fd_set(msgbuf->rpmsg, fd); - fd = -1; - } } if (ibuf_left(msgbuf->rpmsg) <= ibuf_size(&rbuf)) @@ -806,10 +790,14 @@ ibuf_read_process(struct msgbuf *msgbuf, int fd) memmove(msgbuf->rbuf, ibuf_data(&rbuf), ibuf_size(&rbuf)); msgbuf->roff = ibuf_size(&rbuf); + if (fd != -1) + close(fd); return (1); fail: - /* XXX cleanup */ + /* XXX how to properly clean up is unclear */ + if (fd != -1) + close(fd); return (-1); } blob - ef796315dfbe8543a11eeff1b38a8d2b185ce7d3 blob + 89ac7fa4313e8d70079d81cc0f19f2ae2d8a02c3 --- compat/imsg.c +++ compat/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.36 2024/11/21 13:03:21 claudio Exp $ */ +/* $OpenBSD: imsg.c,v 1.37 2024/11/26 13:57:31 claudio Exp $ */ /* * Copyright (c) 2023 Claudio Jeker @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -31,8 +32,9 @@ #include "imsg.h" #define IMSG_ALLOW_FDPASS 0x01 +#define IMSG_FD_MARK 0x80000000U -static ssize_t imsg_parse_hdr(struct ibuf *, void *); +static struct ibuf *imsg_parse_hdr(struct ibuf *, void *, int *); int imsgbuf_init(struct imsgbuf *imsgbuf, int fd) @@ -54,12 +56,15 @@ imsgbuf_allow_fdpass(struct imsgbuf *imsgbuf) imsgbuf->flags |= IMSG_ALLOW_FDPASS; } -void +int imsgbuf_set_maxsize(struct imsgbuf *imsgbuf, uint32_t maxsize) { - if (maxsize < IMSG_HEADER_SIZE) - return; + if (maxsize < IMSG_HEADER_SIZE || maxsize & IMSG_FD_MARK) { + errno = EINVAL; + return (-1); + } imsgbuf->maxsize = maxsize; + return (0); } int @@ -120,6 +125,7 @@ imsg_get(struct imsgbuf *imsgbuf, struct imsg *imsg) else m.data = NULL; m.buf = buf; + m.hdr.len &= ~IMSG_FD_MARK; *imsg = m; return (ibuf_size(buf) + IMSG_HEADER_SIZE); @@ -268,7 +274,7 @@ int imsg_forward(struct imsgbuf *imsgbuf, struct imsg *msg) { struct ibuf *wbuf; - size_t len = 0; + size_t len; ibuf_rewind(msg->buf); ibuf_skip(msg->buf, sizeof(msg->hdr)); @@ -278,7 +284,7 @@ imsg_forward(struct imsgbuf *imsgbuf, struct imsg *msg msg->hdr.pid, len)) == NULL) return (-1); - if (msg->buf != NULL) { + if (len != 0) { if (ibuf_add_ibuf(wbuf, msg->buf) == -1) { ibuf_free(wbuf); return (-1); @@ -330,9 +336,12 @@ void imsg_close(struct imsgbuf *imsgbuf, struct ibuf *msg) { struct imsg_hdr *hdr; + uint32_t len; - hdr = (struct imsg_hdr *)msg->buf; - hdr->len = ibuf_size(msg); + len = ibuf_size(msg); + if (ibuf_fd_avail(msg)) + len |= IMSG_FD_MARK; + (void)ibuf_set_h32(msg, offsetof(struct imsg_hdr, len), len); ibuf_close(imsgbuf->w, msg); } @@ -342,18 +351,29 @@ imsg_free(struct imsg *imsg) ibuf_free(imsg->buf); } -static ssize_t -imsg_parse_hdr(struct ibuf *buf, void *arg) +static struct ibuf * +imsg_parse_hdr(struct ibuf *buf, void *arg, int *fd) { struct imsgbuf *imsgbuf = arg; struct imsg_hdr hdr; + struct ibuf *b; + uint32_t len; if (ibuf_get(buf, &hdr, sizeof(hdr)) == -1) - return -1; - if (hdr.len < IMSG_HEADER_SIZE || - hdr.len > imsgbuf->maxsize) { + return (NULL); + + len = hdr.len & ~IMSG_FD_MARK; + + if (len < IMSG_HEADER_SIZE || len > imsgbuf->maxsize) { errno = ERANGE; - return (-1); + return (NULL); } - return hdr.len; + if ((b = ibuf_open(len)) == NULL) + return (NULL); + if (hdr.len & IMSG_FD_MARK) { + ibuf_fd_set(b, *fd); + *fd = -1; + } + + return b; } blob - 8d78beb34ebecd8de026b31a3ac9e60c0f31edec blob + 462bfc97ffccdfc7bc6deae66c8b185c4ae1621d --- compat/imsg.h +++ compat/imsg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.h,v 1.18 2024/11/21 13:03:21 claudio Exp $ */ +/* $OpenBSD: imsg.h,v 1.19 2024/11/26 13:57:31 claudio Exp $ */ /* * Copyright (c) 2023 Claudio Jeker @@ -110,8 +110,8 @@ int ibuf_fd_avail(struct ibuf *); int ibuf_fd_get(struct ibuf *); void ibuf_fd_set(struct ibuf *, int); struct msgbuf *msgbuf_new(void); -struct msgbuf *msgbuf_new_reader(size_t, ssize_t (*)(struct ibuf *, void *), - void *); +struct msgbuf *msgbuf_new_reader(size_t, + struct ibuf *(*)(struct ibuf *, void *, int *), void *); void msgbuf_free(struct msgbuf *); void msgbuf_clear(struct msgbuf *); uint32_t msgbuf_queuelen(struct msgbuf *); @@ -124,7 +124,7 @@ struct ibuf *msgbuf_get(struct msgbuf *); /* imsg.c */ int imsgbuf_init(struct imsgbuf *, int); void imsgbuf_allow_fdpass(struct imsgbuf *imsgbuf); -void imsgbuf_set_maxsize(struct imsgbuf *, uint32_t); +int imsgbuf_set_maxsize(struct imsgbuf *, uint32_t); int imsgbuf_read(struct imsgbuf *); int imsgbuf_write(struct imsgbuf *); int imsgbuf_flush(struct imsgbuf *);