commit - 25b639dfa175a8a6684ae2c8666a270fe682523a
commit + 9822808d41d777c56c4d846cd5c6dead306bcc4e
blob - fc8ef7dbd7609263755a10aec3f4dfb6ab8d94fb
blob + c3a15aeaba04a6f9a76cd10b8bae921f61396e63
--- compat/imsg-buffer.c
+++ compat/imsg-buffer.c
-/* $OpenBSD: imsg-buffer.c,v 1.31 2024/11/26 13:57:31 claudio Exp $ */
+/* $OpenBSD: imsg-buffer.c,v 1.36 2025/08/25 08:29:49 claudio Exp $ */
/*
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
#include "got_compat.h"
#include "imsg.h"
+struct ibufqueue {
+ TAILQ_HEAD(, ibuf) bufs;
+ uint32_t queued;
+};
+
struct msgbuf {
- TAILQ_HEAD(, ibuf) bufs;
- TAILQ_HEAD(, ibuf) rbufs;
- uint32_t queued;
+ struct ibufqueue bufs;
+ struct ibufqueue rbufs;
char *rbuf;
struct ibuf *rpmsg;
struct ibuf *(*readhdr)(struct ibuf *, void *, int *);
size_t hdrsize;
};
-static void msgbuf_read_enqueue(struct msgbuf *, struct ibuf *);
-static void msgbuf_enqueue(struct msgbuf *, struct ibuf *);
-static void msgbuf_dequeue(struct msgbuf *, struct ibuf *);
static void msgbuf_drain(struct msgbuf *, size_t);
+static void ibufq_init(struct ibufqueue *);
#define IBUF_FD_MARK_ON_STACK -2
{
void *b;
+ if (len == 0)
+ return (0);
+
if ((b = ibuf_reserve(buf, len)) == NULL)
return (-1);
{
void *b;
+ if (len == 0)
+ return (0);
+
if ((b = ibuf_reserve(buf, len)) == NULL)
return (-1);
memset(b, 0, len);
+ return (0);
+}
+
+int
+ibuf_add_strbuf(struct ibuf *buf, const char *str, size_t len)
+{
+ char *b;
+ size_t n;
+
+ if ((b = ibuf_reserve(buf, len)) == NULL)
+ return (-1);
+
+ n = strlcpy(b, str, len);
+ if (n >= len) {
+ /* also covers the case where len == 0 */
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ memset(b + n, 0, len - n);
return (0);
}
if ((b = ibuf_seek(buf, pos, len)) == NULL)
return (-1);
+ if (len == 0)
+ return (0);
memcpy(b, data, len);
return (0);
}
return (ibuf_set(buf, pos, &value, sizeof(value)));
}
+int
+ibuf_set_maxsize(struct ibuf *buf, size_t max)
+{
+ if (buf->fd == IBUF_FD_MARK_ON_STACK) {
+ /* can't fiddle with stack buffers */
+ errno = EINVAL;
+ return (-1);
+ }
+ if (max > buf->max) {
+ errno = ERANGE;
+ return (-1);
+ }
+ buf->max = max;
+ return (0);
+}
+
void *
ibuf_data(const struct ibuf *buf)
{
void
ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
{
- msgbuf_enqueue(msgbuf, buf);
+ ibufq_push(&msgbuf->bufs, buf);
}
void
}
int
+ibuf_get_strbuf(struct ibuf *buf, char *str, size_t len)
+{
+ if (len == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (ibuf_get(buf, str, len) == -1)
+ return -1;
+ if (str[len - 1] != '\0') {
+ str[len - 1] = '\0';
+ errno = EOVERFLOW;
+ return -1;
+ }
+ return 0;
+}
+
+int
ibuf_skip(struct ibuf *buf, size_t len)
{
if (ibuf_size(buf) < len) {
void
ibuf_free(struct ibuf *buf)
{
+ int save_errno = errno;
+
if (buf == NULL)
return;
/* if buf lives on the stack abort before causing more harm */
close(buf->fd);
freezero(buf->buf, buf->size);
free(buf);
+ errno = save_errno;
}
int
if ((msgbuf = calloc(1, sizeof(*msgbuf))) == NULL)
return (NULL);
- msgbuf->queued = 0;
- TAILQ_INIT(&msgbuf->bufs);
- TAILQ_INIT(&msgbuf->rbufs);
+ ibufq_init(&msgbuf->bufs);
+ ibufq_init(&msgbuf->rbufs);
return msgbuf;
}
uint32_t
msgbuf_queuelen(struct msgbuf *msgbuf)
{
- return (msgbuf->queued);
+ return ibufq_queuelen(&msgbuf->bufs);
}
void
msgbuf_clear(struct msgbuf *msgbuf)
{
- struct ibuf *buf;
-
/* write side */
- while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
- msgbuf_dequeue(msgbuf, buf);
- msgbuf->queued = 0;
+ ibufq_flush(&msgbuf->bufs);
/* read side */
- while ((buf = TAILQ_FIRST(&msgbuf->rbufs)) != NULL) {
- TAILQ_REMOVE(&msgbuf->rbufs, buf, entry);
- ibuf_free(buf);
- }
+ ibufq_flush(&msgbuf->rbufs);
msgbuf->roff = 0;
ibuf_free(msgbuf->rpmsg);
msgbuf->rpmsg = NULL;
struct ibuf *
msgbuf_get(struct msgbuf *msgbuf)
{
- struct ibuf *buf;
+ return ibufq_pop(&msgbuf->rbufs);
+}
- if ((buf = TAILQ_FIRST(&msgbuf->rbufs)) != NULL)
- TAILQ_REMOVE(&msgbuf->rbufs, buf, entry);
- return buf;
+void
+msgbuf_concat(struct msgbuf *msgbuf, struct ibufqueue *from)
+{
+ ibufq_concat(&msgbuf->bufs, from);
}
int
ssize_t n;
memset(&iov, 0, sizeof(iov));
- TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
+ TAILQ_FOREACH(buf, &msgbuf->bufs.bufs, entry) {
if (i >= IOV_MAX)
break;
iov[i].iov_base = ibuf_data(buf);
memset(&iov, 0, sizeof(iov));
memset(&msg, 0, sizeof(msg));
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
- TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
+ TAILQ_FOREACH(buf, &msgbuf->bufs.bufs, entry) {
if (i >= IOV_MAX)
break;
if (i > 0 && buf->fd != -1)
goto fail;
if (ibuf_left(msgbuf->rpmsg) == 0) {
- msgbuf_read_enqueue(msgbuf, msgbuf->rpmsg);
+ ibufq_push(&msgbuf->rbufs, msgbuf->rpmsg);
msgbuf->rpmsg = NULL;
}
} while (ibuf_size(&rbuf) > 0);
}
static void
-msgbuf_read_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
+msgbuf_drain(struct msgbuf *msgbuf, size_t n)
{
- /* if buf lives on the stack abort before causing more harm */
- if (buf->fd == IBUF_FD_MARK_ON_STACK)
- abort();
- TAILQ_INSERT_TAIL(&msgbuf->rbufs, buf, entry);
+ struct ibuf *buf;
+
+ while ((buf = TAILQ_FIRST(&msgbuf->bufs.bufs)) != NULL) {
+ if (n >= ibuf_size(buf)) {
+ n -= ibuf_size(buf);
+ TAILQ_REMOVE(&msgbuf->bufs.bufs, buf, entry);
+ msgbuf->bufs.queued--;
+ ibuf_free(buf);
+ } else {
+ buf->rpos += n;
+ return;
+ }
+ }
}
static void
-msgbuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
+ibufq_init(struct ibufqueue *bufq)
{
+ TAILQ_INIT(&bufq->bufs);
+ bufq->queued = 0;
+}
+
+struct ibufqueue *
+ibufq_new(void)
+{
+ struct ibufqueue *bufq;
+
+ if ((bufq = calloc(1, sizeof(*bufq))) == NULL)
+ return NULL;
+ ibufq_init(bufq);
+ return bufq;
+}
+
+void
+ibufq_free(struct ibufqueue *bufq)
+{
+ if (bufq == NULL)
+ return;
+ ibufq_flush(bufq);
+ free(bufq);
+}
+
+struct ibuf *
+ibufq_pop(struct ibufqueue *bufq)
+{
+ struct ibuf *buf;
+
+ if ((buf = TAILQ_FIRST(&bufq->bufs)) == NULL)
+ return NULL;
+ TAILQ_REMOVE(&bufq->bufs, buf, entry);
+ bufq->queued--;
+ return buf;
+}
+
+void
+ibufq_push(struct ibufqueue *bufq, struct ibuf *buf)
+{
/* if buf lives on the stack abort before causing more harm */
if (buf->fd == IBUF_FD_MARK_ON_STACK)
abort();
- TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
- msgbuf->queued++;
+ TAILQ_INSERT_TAIL(&bufq->bufs, buf, entry);
+ bufq->queued++;
}
-static void
-msgbuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
+uint32_t
+ibufq_queuelen(struct ibufqueue *bufq)
{
- TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
- msgbuf->queued--;
- ibuf_free(buf);
+ return (bufq->queued);
}
-static void
-msgbuf_drain(struct msgbuf *msgbuf, size_t n)
+void
+ibufq_concat(struct ibufqueue *to, struct ibufqueue *from)
{
- struct ibuf *buf, *next;
+ to->queued += from->queued;
+ TAILQ_CONCAT(&to->bufs, &from->bufs, entry);
+ from->queued = 0;
+}
- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
- buf = next) {
- next = TAILQ_NEXT(buf, entry);
- if (n >= ibuf_size(buf)) {
- n -= ibuf_size(buf);
- msgbuf_dequeue(msgbuf, buf);
- } else {
- buf->rpos += n;
- n = 0;
- }
+void
+ibufq_flush(struct ibufqueue *bufq)
+{
+ struct ibuf *buf;
+
+ while ((buf = TAILQ_FIRST(&bufq->bufs)) != NULL) {
+ TAILQ_REMOVE(&bufq->bufs, buf, entry);
+ ibuf_free(buf);
}
+ bufq->queued = 0;
}
blob - a0f242a4b0637ab5f82769ab8f97af05293cccb5
blob + 5be3d72bb78affb96bab7ff26b0cd4d892f0865b
--- compat/imsg.c
+++ compat/imsg.c
-/* $OpenBSD: imsg.c,v 1.38 2024/11/29 04:35:13 tb Exp $ */
+/* $OpenBSD: imsg.c,v 1.42 2025/06/16 13:56:11 claudio Exp $ */
/*
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
#include <errno.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
}
int
-imsgbuf_set_maxsize(struct imsgbuf *imsgbuf, uint32_t maxsize)
+imsgbuf_set_maxsize(struct imsgbuf *imsgbuf, uint32_t max)
{
- if (maxsize < IMSG_HEADER_SIZE || maxsize & IMSG_FD_MARK) {
+ if (max > UINT32_MAX - IMSG_HEADER_SIZE) {
+ errno = ERANGE;
+ return (-1);
+ }
+ max += IMSG_HEADER_SIZE;
+ if (max & IMSG_FD_MARK) {
errno = EINVAL;
return (-1);
}
- imsgbuf->maxsize = maxsize;
+ imsgbuf->maxsize = max;
return (0);
}
return msgbuf_queuelen(imsgbuf->w);
}
+int
+imsgbuf_get(struct imsgbuf *imsgbuf, struct imsg *imsg)
+{
+ struct imsg m;
+ struct ibuf *buf;
+
+ if ((buf = msgbuf_get(imsgbuf->w)) == NULL)
+ return (0);
+
+ if (ibuf_get(buf, &m.hdr, sizeof(m.hdr)) == -1)
+ return (-1);
+
+ if (ibuf_size(buf))
+ m.data = ibuf_data(buf);
+ else
+ m.data = NULL;
+ m.buf = buf;
+ m.hdr.len &= ~IMSG_FD_MARK;
+
+ *imsg = m;
+ return (1);
+}
+
ssize_t
imsg_get(struct imsgbuf *imsgbuf, struct imsg *imsg)
{
- struct imsg m;
- struct ibuf *buf;
+ int rv;
- if ((buf = msgbuf_get(imsgbuf->w)) == NULL)
+ if ((rv = imsgbuf_get(imsgbuf, imsg)) != 1)
+ return rv;
+ return (imsg_get_len(imsg) + IMSG_HEADER_SIZE);
+}
+
+int
+imsg_ibufq_pop(struct ibufqueue *bufq, struct imsg *imsg)
+{
+ struct imsg m;
+ struct ibuf *buf;
+
+ if ((buf = ibufq_pop(bufq)) == NULL)
return (0);
if (ibuf_get(buf, &m.hdr, sizeof(m.hdr)) == -1)
m.hdr.len &= ~IMSG_FD_MARK;
*imsg = m;
- return (ibuf_size(buf) + IMSG_HEADER_SIZE);
+ return (1);
}
+void
+imsg_ibufq_push(struct ibufqueue *bufq, struct imsg *imsg)
+{
+ ibuf_rewind(imsg->buf);
+ ibufq_push(bufq, imsg->buf);
+ memset(imsg, 0, sizeof(*imsg));
+}
+
int
imsg_get_ibuf(struct imsg *imsg, struct ibuf *ibuf)
{
errno = EBADMSG;
return (-1);
}
+ return ibuf_get(imsg->buf, data, len);
+}
+
+int
+imsg_get_buf(struct imsg *imsg, void *data, size_t len)
+{
return ibuf_get(imsg->buf, data, len);
}
int
+imsg_get_strbuf(struct imsg *imsg, char *str, size_t len)
+{
+ return ibuf_get_strbuf(imsg->buf, str, len);
+}
+
+int
imsg_get_fd(struct imsg *imsg)
{
return ibuf_fd_get(imsg->buf);
struct ibuf *wbuf;
if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
- return (-1);
+ goto fail;
- if (imsg_add(wbuf, data, datalen) == -1)
- return (-1);
+ if (ibuf_add(wbuf, data, datalen) == -1)
+ goto fail;
ibuf_fd_set(wbuf, fd);
imsg_close(imsgbuf, wbuf);
return (1);
+
+ fail:
+ ibuf_free(wbuf);
+ return (-1);
}
int
datalen += iov[i].iov_len;
if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
- return (-1);
+ goto fail;
for (i = 0; i < iovcnt; i++)
- if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
- return (-1);
+ if (ibuf_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
+ goto fail;
ibuf_fd_set(wbuf, fd);
imsg_close(imsgbuf, wbuf);
return (1);
+
+ fail:
+ ibuf_free(wbuf);
+ return (-1);
}
/*
{
struct ibuf *hdrbuf = NULL;
struct imsg_hdr hdr;
- int save_errno;
if (ibuf_size(buf) + IMSG_HEADER_SIZE > imsgbuf->maxsize) {
errno = ERANGE;
if ((hdrbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
goto fail;
- if (imsg_add(hdrbuf, &hdr, sizeof(hdr)) == -1)
+ if (ibuf_add(hdrbuf, &hdr, sizeof(hdr)) == -1)
goto fail;
ibuf_close(imsgbuf->w, hdrbuf);
return (1);
fail:
- save_errno = errno;
ibuf_free(buf);
ibuf_free(hdrbuf);
- errno = save_errno;
return (-1);
}
return (NULL);
}
+ hdr.len = 0;
hdr.type = type;
hdr.peerid = id;
if ((hdr.pid = pid) == 0)
hdr.pid = imsgbuf->pid;
- if ((wbuf = ibuf_dynamic(datalen, imsgbuf->maxsize)) == NULL) {
- return (NULL);
- }
- if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
- return (NULL);
+ if ((wbuf = ibuf_dynamic(datalen, imsgbuf->maxsize)) == NULL)
+ goto fail;
+ if (ibuf_add(wbuf, &hdr, sizeof(hdr)) == -1)
+ goto fail;
return (wbuf);
+
+ fail:
+ ibuf_free(wbuf);
+ return (NULL);
}
int
ibuf_free(imsg->buf);
}
+int
+imsg_set_maxsize(struct ibuf *msg, size_t max)
+{
+ if (max > UINT32_MAX - IMSG_HEADER_SIZE) {
+ errno = ERANGE;
+ return (-1);
+ }
+ return ibuf_set_maxsize(msg, max + IMSG_HEADER_SIZE);
+}
+
static struct ibuf *
imsg_parse_hdr(struct ibuf *buf, void *arg, int *fd)
{
blob - 462bfc97ffccdfc7bc6deae66c8b185c4ae1621d
blob + d18adb4939c2f344312f662508ce6a9a6ce67c86
--- compat/imsg.h
+++ compat/imsg.h
-/* $OpenBSD: imsg.h,v 1.19 2024/11/26 13:57:31 claudio Exp $ */
+/* $OpenBSD: imsg.h,v 1.24 2025/06/05 08:55:07 tb Exp $ */
/*
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
#define _IMSG_H_
#include <sys/types.h>
+#include <sys/queue.h>
+#include <stddef.h>
+#include <stdint.h>
#define IBUF_READ_SIZE 65535
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
int fd;
};
+struct ibufqueue;
struct msgbuf;
struct imsgbuf {
int ibuf_add_h16(struct ibuf *, uint64_t);
int ibuf_add_h32(struct ibuf *, uint64_t);
int ibuf_add_h64(struct ibuf *, uint64_t);
+int ibuf_add_strbuf(struct ibuf *, const char *, size_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_h16(struct ibuf *, size_t, uint64_t);
int ibuf_set_h32(struct ibuf *, size_t, uint64_t);
int ibuf_set_h64(struct ibuf *, size_t, uint64_t);
+int ibuf_set_maxsize(struct ibuf *, size_t);
void *ibuf_data(const struct ibuf *);
size_t ibuf_size(const struct ibuf *);
size_t ibuf_left(const struct ibuf *);
int ibuf_get_h32(struct ibuf *, uint32_t *);
int ibuf_get_h64(struct ibuf *, uint64_t *);
char *ibuf_get_string(struct ibuf *, size_t);
+int ibuf_get_strbuf(struct ibuf *, char *, size_t);
int ibuf_skip(struct ibuf *, size_t);
void ibuf_free(struct ibuf *);
int ibuf_fd_avail(struct ibuf *);
struct ibuf *(*)(struct ibuf *, void *, int *), void *);
void msgbuf_free(struct msgbuf *);
void msgbuf_clear(struct msgbuf *);
+void msgbuf_concat(struct msgbuf *, struct ibufqueue *);
uint32_t msgbuf_queuelen(struct msgbuf *);
int ibuf_write(int, struct msgbuf *);
int msgbuf_write(int, struct msgbuf *);
int msgbuf_read(int, struct msgbuf *);
struct ibuf *msgbuf_get(struct msgbuf *);
+struct ibufqueue *ibufq_new(void);
+void ibufq_free(struct ibufqueue *);
+struct ibuf *ibufq_pop(struct ibufqueue *bufq);
+void ibufq_push(struct ibufqueue *, struct ibuf *);
+uint32_t ibufq_queuelen(struct ibufqueue *);
+void ibufq_concat(struct ibufqueue *, struct ibufqueue *);
+void ibufq_flush(struct ibufqueue *);
+
/* imsg.c */
int imsgbuf_init(struct imsgbuf *, int);
void imsgbuf_allow_fdpass(struct imsgbuf *imsgbuf);
int imsgbuf_flush(struct imsgbuf *);
void imsgbuf_clear(struct imsgbuf *);
uint32_t imsgbuf_queuelen(struct imsgbuf *);
+int imsgbuf_get(struct imsgbuf *, struct imsg *);
ssize_t imsg_get(struct imsgbuf *, struct imsg *);
+int imsg_ibufq_pop(struct ibufqueue *, struct imsg *);
+void imsg_ibufq_push(struct ibufqueue *, struct imsg *);
int imsg_get_ibuf(struct imsg *, struct ibuf *);
int imsg_get_data(struct imsg *, void *, size_t);
+int imsg_get_buf(struct imsg *, void *, size_t);
+int imsg_get_strbuf(struct imsg *, char *, size_t);
int imsg_get_fd(struct imsg *);
uint32_t imsg_get_id(struct imsg *);
size_t imsg_get_len(struct imsg *);
int imsg_add(struct ibuf *, const void *, size_t);
void imsg_close(struct imsgbuf *, struct ibuf *);
void imsg_free(struct imsg *);
+int imsg_set_maxsize(struct ibuf *, size_t);
#endif