commit f229e00955140395f8685f5812c064b7fa44090d from: Omar Polo date: Sun Jul 02 09:19:30 2023 UTC sync imsg commit - 90cee84d4c2eb546ed31ba65a01289429ea7f544 commit + f229e00955140395f8685f5812c064b7fa44090d blob - 7bd827d6354db030b1fbffc9a365200e017a557e blob + d3eb6036cea805e9b0c6fe5e8ba685cbda71c43b --- compat/imsg-buffer.c +++ compat/imsg-buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg-buffer.c,v 1.12 2019/01/20 02:50:03 bcook Exp $ */ +/* $OpenBSD: imsg-buffer.c,v 1.16 2023/06/19 17:19:50 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -33,15 +33,20 @@ static int ibuf_realloc(struct ibuf *, size_t); static void ibuf_enqueue(struct msgbuf *, struct ibuf *); static void ibuf_dequeue(struct msgbuf *, struct ibuf *); +static void msgbuf_drain(struct msgbuf *, size_t); struct ibuf * ibuf_open(size_t len) { struct ibuf *buf; + if (len == 0) { + errno = EINVAL; + return (NULL); + } if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) return (NULL); - if ((buf->buf = malloc(len)) == NULL) { + if ((buf->buf = calloc(len, 1)) == NULL) { free(buf); return (NULL); } @@ -56,15 +61,23 @@ ibuf_dynamic(size_t len, size_t max) { struct ibuf *buf; - if (max < len) + if (max < len) { + errno = EINVAL; return (NULL); + } - if ((buf = ibuf_open(len)) == NULL) + if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) return (NULL); + if (len > 0) { + if ((buf->buf = calloc(len, 1)) == NULL) { + free(buf); + return (NULL); + } + } + buf->size = len; + buf->max = max; + buf->fd = -1; - if (max > 0) - buf->max = max; - return (buf); } @@ -74,7 +87,7 @@ ibuf_realloc(struct ibuf *buf, size_t len) unsigned char *b; /* on static buffers max is eq size and so the following fails */ - if (buf->wpos + len > buf->max) { + if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) { errno = ERANGE; return (-1); } @@ -88,42 +101,176 @@ ibuf_realloc(struct ibuf *buf, size_t len) return (0); } -int -ibuf_add(struct ibuf *buf, const void *data, size_t len) -{ - if (buf->wpos + len > buf->size) - if (ibuf_realloc(buf, len) == -1) - return (-1); - - memcpy(buf->buf + buf->wpos, data, len); - buf->wpos += len; - return (0); -} - void * ibuf_reserve(struct ibuf *buf, size_t len) { void *b; + if (len > SIZE_MAX - buf->wpos) { + errno = ERANGE; + return (NULL); + } + if (buf->wpos + len > buf->size) if (ibuf_realloc(buf, len) == -1) return (NULL); b = buf->buf + buf->wpos; buf->wpos += len; + memset(b, 0, len); return (b); } +int +ibuf_add(struct ibuf *buf, const void *data, size_t len) +{ + void *b; + + if ((b = ibuf_reserve(buf, len)) == NULL) + return (-1); + + memcpy(b, data, len); + return (0); +} + +int +ibuf_add_buf(struct ibuf *buf, const struct ibuf *from) +{ + return ibuf_add(buf, from->buf, from->wpos); +} + +int +ibuf_add_n8(struct ibuf *buf, uint64_t value) +{ + uint8_t v; + + if (value > UINT8_MAX) { + errno = EINVAL; + return (-1); + } + v = value; + return ibuf_add(buf, &v, sizeof(v)); +} + +int +ibuf_add_n16(struct ibuf *buf, uint64_t value) +{ + uint16_t v; + + if (value > UINT16_MAX) { + errno = EINVAL; + return (-1); + } + v = htobe16(value); + return ibuf_add(buf, &v, sizeof(v)); +} + +int +ibuf_add_n32(struct ibuf *buf, uint64_t value) +{ + uint32_t v; + + if (value > UINT32_MAX) { + errno = EINVAL; + return (-1); + } + v = htobe32(value); + return ibuf_add(buf, &v, sizeof(v)); +} + +int +ibuf_add_n64(struct ibuf *buf, uint64_t value) +{ + value = htobe64(value); + return ibuf_add(buf, &value, sizeof(value)); +} + +int +ibuf_add_zero(struct ibuf *buf, size_t len) +{ + void *b; + + if ((b = ibuf_reserve(buf, len)) == NULL) + return (-1); + return (0); +} + void * ibuf_seek(struct ibuf *buf, size_t pos, size_t len) { /* only allowed to seek in already written parts */ - if (pos + len > buf->wpos) + if (len > SIZE_MAX - pos || pos + len > buf->wpos) { + errno = ERANGE; return (NULL); + } return (buf->buf + pos); } +int +ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len) +{ + void *b; + + if ((b = ibuf_seek(buf, pos, len)) == NULL) + return (-1); + + memcpy(b, data, len); + return (0); +} + +int +ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value) +{ + uint8_t v; + + if (value > UINT8_MAX) { + errno = EINVAL; + return (-1); + } + v = value; + return (ibuf_set(buf, pos, &v, sizeof(v))); +} + +int +ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value) +{ + uint16_t v; + + if (value > UINT16_MAX) { + errno = EINVAL; + return (-1); + } + v = htobe16(value); + return (ibuf_set(buf, pos, &v, sizeof(v))); +} + +int +ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value) +{ + uint32_t v; + + if (value > UINT32_MAX) { + errno = EINVAL; + return (-1); + } + v = htobe32(value); + return (ibuf_set(buf, pos, &v, sizeof(v))); +} + +int +ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value) +{ + value = htobe64(value); + return (ibuf_set(buf, pos, &value, sizeof(value))); +} + +void * +ibuf_data(struct ibuf *buf) +{ + return (buf->buf); +} + size_t ibuf_size(struct ibuf *buf) { @@ -142,7 +289,46 @@ ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) ibuf_enqueue(msgbuf, buf); } +void +ibuf_free(struct ibuf *buf) +{ + if (buf == NULL) + return; +#ifdef NOTYET + if (buf->fd != -1) + close(buf->fd); +#endif + freezero(buf->buf, buf->size); + free(buf); +} + int +ibuf_fd_avail(struct ibuf *buf) +{ + return (buf->fd != -1); +} + +int +ibuf_fd_get(struct ibuf *buf) +{ + int fd; + + fd = buf->fd; +#ifdef NOTYET + buf->fd = -1; +#endif + return (fd); +} + +void +ibuf_fd_set(struct ibuf *buf, int fd) +{ + if (buf->fd != -1) + close(buf->fd); + buf->fd = fd; +} + +int ibuf_write(struct msgbuf *msgbuf) { struct iovec iov[IOV_MAX]; @@ -179,15 +365,6 @@ again: } void -ibuf_free(struct ibuf *buf) -{ - if (buf == NULL) - return; - freezero(buf->buf, buf->size); - free(buf); -} - -void msgbuf_init(struct msgbuf *msgbuf) { msgbuf->queued = 0; @@ -195,7 +372,7 @@ msgbuf_init(struct msgbuf *msgbuf) TAILQ_INIT(&msgbuf->bufs); } -void +static void msgbuf_drain(struct msgbuf *msgbuf, size_t n) { struct ibuf *buf, *next; @@ -203,7 +380,7 @@ msgbuf_drain(struct msgbuf *msgbuf, size_t n) for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; buf = next) { next = TAILQ_NEXT(buf, entry); - if (buf->rpos + n >= buf->wpos) { + if (n >= buf->wpos - buf->rpos) { n -= buf->wpos - buf->rpos; ibuf_dequeue(msgbuf, buf); } else { @@ -226,7 +403,7 @@ int msgbuf_write(struct msgbuf *msgbuf) { struct iovec iov[IOV_MAX]; - struct ibuf *buf; + struct ibuf *buf, *buf0 = NULL; unsigned int i = 0; ssize_t n; struct msghdr msg; @@ -242,24 +419,26 @@ msgbuf_write(struct msgbuf *msgbuf) TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { if (i >= IOV_MAX) break; + if (i > 0 && buf->fd != -1) + break; iov[i].iov_base = buf->buf + buf->rpos; iov[i].iov_len = buf->wpos - buf->rpos; i++; if (buf->fd != -1) - break; + buf0 = buf; } msg.msg_iov = iov; msg.msg_iovlen = i; - if (buf != NULL && buf->fd != -1) { + if (buf0 != NULL) { msg.msg_control = (caddr_t)&cmsgbuf.buf; msg.msg_controllen = sizeof(cmsgbuf.buf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsg) = buf->fd; + *(int *)CMSG_DATA(cmsg) = buf0->fd; } again: @@ -280,9 +459,9 @@ again: * assumption: fd got sent if sendmsg sent anything * this works because fds are passed one at a time */ - if (buf != NULL && buf->fd != -1) { - close(buf->fd); - buf->fd = -1; + if (buf0 != NULL) { + close(buf0->fd); + buf0->fd = -1; } msgbuf_drain(msgbuf, n); @@ -302,8 +481,10 @@ ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) { TAILQ_REMOVE(&msgbuf->bufs, buf, entry); - if (buf->fd != -1) + if (buf->fd != -1) { close(buf->fd); + buf->fd = -1; + } msgbuf->queued--; ibuf_free(buf); blob - 59998a5321d7c7e0dc8c44be2e5371e1213a7371 blob + 5d5201ab369fc1a4016a84f7a33fe9e898332f76 --- compat/imsg.c +++ compat/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.17 2022/01/28 10:41:44 claudio Exp $ */ +/* $OpenBSD: imsg.c,v 1.19 2023/06/19 17:19:50 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -176,8 +176,7 @@ imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint if (imsg_add(wbuf, data, datalen) == -1) return (-1); - wbuf->fd = fd; - + ibuf_fd_set(wbuf, fd); imsg_close(ibuf, wbuf); return (1); @@ -200,14 +199,49 @@ imsg_composev(struct imsgbuf *ibuf, uint32_t type, uin if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1) return (-1); - wbuf->fd = fd; - + ibuf_fd_set(wbuf, fd); imsg_close(ibuf, wbuf); return (1); } -/* ARGSUSED */ +int +imsg_compose_ibuf(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, + pid_t pid, struct ibuf *buf) +{ + struct ibuf *wbuf = NULL; + struct imsg_hdr hdr; + int save_errno; + + if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) { + errno = ERANGE; + goto fail; + } + + hdr.type = type; + hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE; + hdr.flags = 0; + hdr.peerid = peerid; + if ((hdr.pid = pid) == 0) + hdr.pid = ibuf->pid; + + if ((wbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL) + goto fail; + if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) + goto fail; + + ibuf_close(&ibuf->w, wbuf); + ibuf_close(&ibuf->w, buf); + return (1); + + fail: + save_errno = errno; + ibuf_free(buf); + ibuf_free(wbuf); + errno = save_errno; + return (-1); +} + struct ibuf * imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid, uint16_t datalen) @@ -254,11 +288,10 @@ imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) hdr = (struct imsg_hdr *)msg->buf; hdr->flags &= ~IMSGF_HASFD; - if (msg->fd != -1) + if (ibuf_fd_avail(msg)) hdr->flags |= IMSGF_HASFD; + hdr->len = ibuf_size(msg); - hdr->len = (uint16_t)msg->wpos; - ibuf_close(&ibuf->w, msg); } blob - 5b092cfcfd53b5b09a2d5932010f421d6795e0aa blob + fb516e30287318ec10ccdddc451e5d8658db0a12 --- compat/imsg.h +++ compat/imsg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.h,v 1.5 2019/01/20 02:50:03 bcook Exp $ */ +/* $OpenBSD: imsg.h,v 1.7 2023/06/19 17:19:50 claudio Exp $ */ /* * Copyright (c) 2006, 2007 Pierre-Yves Ritschard @@ -78,22 +78,37 @@ struct imsg { void *data; }; +struct iovec; -/* buffer.c */ +/* imsg-buffer.c */ struct ibuf *ibuf_open(size_t); struct ibuf *ibuf_dynamic(size_t, size_t); int ibuf_add(struct ibuf *, const void *, size_t); +int ibuf_add_buf(struct ibuf *, const struct ibuf *); +int ibuf_add_zero(struct ibuf *, size_t); +int ibuf_add_n8(struct ibuf *, uint64_t); +int ibuf_add_n16(struct ibuf *, uint64_t); +int ibuf_add_n32(struct ibuf *, uint64_t); +int ibuf_add_n64(struct ibuf *, uint64_t); void *ibuf_reserve(struct ibuf *, size_t); void *ibuf_seek(struct ibuf *, size_t, size_t); +int ibuf_set(struct ibuf *, size_t, const void *, size_t); +int ibuf_set_n8(struct ibuf *, size_t, uint64_t); +int ibuf_set_n16(struct ibuf *, size_t, uint64_t); +int ibuf_set_n32(struct ibuf *, size_t, uint64_t); +int ibuf_set_n64(struct ibuf *, size_t, uint64_t); +void *ibuf_data(struct ibuf *); size_t ibuf_size(struct ibuf *); size_t ibuf_left(struct ibuf *); void ibuf_close(struct msgbuf *, struct ibuf *); -int ibuf_write(struct msgbuf *); void ibuf_free(struct ibuf *); +int ibuf_fd_avail(struct ibuf *); +int ibuf_fd_get(struct ibuf *); +void ibuf_fd_set(struct ibuf *, int); +int ibuf_write(struct msgbuf *); void msgbuf_init(struct msgbuf *); void msgbuf_clear(struct msgbuf *); int msgbuf_write(struct msgbuf *); -void msgbuf_drain(struct msgbuf *, size_t); /* imsg.c */ void imsg_init(struct imsgbuf *, int); @@ -103,6 +118,8 @@ int imsg_compose(struct imsgbuf *, uint32_t, uint32_t const void *, uint16_t); int imsg_composev(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, const struct iovec *, int); +int imsg_compose_ibuf(struct imsgbuf *, uint32_t, uint32_t, pid_t, + struct ibuf *); struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t); int imsg_add(struct ibuf *, const void *, uint16_t); void imsg_close(struct imsgbuf *, struct ibuf *);