commit - f590993607ab0af771f2b7dd8c3bfb5854e724c3
commit + 3ef3f36a26879f6f0dd1a0b1eb7d2a775ee45095
blob - 7ce1ea0274181877aed37f955f9319e6961f41c1
blob + 0f3c3c80933c50fabbd437990f8b128a778e9641
--- compat/imsg-buffer.c
+++ compat/imsg-buffer.c
-/* $OpenBSD: imsg-buffer.c,v 1.11 2017/12/14 09:27:44 kettenis Exp $ */
+/* $OpenBSD: imsg-buffer.c,v 1.16 2023/06/19 17:19:50 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
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);
}
{
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);
}
static int
ibuf_realloc(struct ibuf *buf, size_t len)
{
- u_char *b;
+ 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);
}
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)
{
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];
}
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;
TAILQ_INIT(&msgbuf->bufs);
}
-void
+static void
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
{
struct ibuf *buf, *next;
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 {
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;
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:
* 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);
{
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 - d76f4872c286711fa86a454e4b465ae4ceb051a0
blob + c2e106602ebfc5f584be2ce2788e6d102d5cecc8
--- compat/imsg.c
+++ compat/imsg.c
-/* $OpenBSD: imsg.c,v 1.16 2017/12/14 09:27:44 kettenis Exp $ */
+/* $OpenBSD: imsg.c,v 1.19 2023/06/19 17:19:50 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
else
imsg->fd = -1;
- memcpy(imsg->data, ibuf->r.rptr, datalen);
+ if (datalen != 0)
+ memcpy(imsg->data, ibuf->r.rptr, datalen);
if (imsg->hdr.len < av) {
left = av - imsg->hdr.len;
if (imsg_add(wbuf, data, datalen) == -1)
return (-1);
- wbuf->fd = fd;
-
+ ibuf_fd_set(wbuf, fd);
imsg_close(ibuf, wbuf);
return (1);
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)
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 - dab6b00d1883af65ccb962fb88ef793964ac2379
blob + fb516e30287318ec10ccdddc451e5d8658db0a12
--- compat/imsg.h
+++ compat/imsg.h
-/* $OpenBSD: imsg.h,v 1.4 2017/03/24 09:34:12 nicm Exp $ */
+/* $OpenBSD: imsg.h,v 1.7 2023/06/19 17:19:50 claudio Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
#ifndef _IMSG_H_
#define _IMSG_H_
+#include <stdint.h>
#define IBUF_READ_SIZE 65535
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
#define MAX_IMSGSIZE 16384
-#include <stdint.h>
-
struct ibuf {
TAILQ_ENTRY(ibuf) entry;
- u_char *buf;
+ unsigned char *buf;
size_t size;
size_t max;
size_t wpos;
};
struct ibuf_read {
- u_char buf[IBUF_READ_SIZE];
- u_char *rptr;
+ unsigned char buf[IBUF_READ_SIZE];
+ unsigned char *rptr;
size_t wpos;
};
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);
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 *);