From: Kyle Ackerman Subject: imsg_get_data Question To: tech@openbsd.org Cc: claudio@openbsd.org Date: Sun, 16 Aug 2026 10:04:25 -0600 Hello, Recently, in order to access the data of an imsg, I have ran into an issue replacing a memcpy(3) call with a imsg_get_data(3) call, which turned out to not just be plug and play. The conditions needed for this are specifying a size in the imsg_get_data(3) that is less than the internally allocated buffer size. For example the specific situation I am working with is a struct of size 16 bytes that I am pulling out of a imsg with an internally allocated buffer of 64 bytes. imsg_get_data(struct imsg *imsg, void *data, size_t len) { if (len == 0) { errno = EINVAL; return (-1); } if (ibuf_size(imsg->buf) != len) { // Fails here errno = EBADMSG; return (-1); } return ibuf_get(imsg->buf, data, len); } I am not entirely sure why we have the constraint that requested length in the has to be exactly the size of the imsg->buf. Having to know the internally allocated buffer size in order to use the imsg_get_data IMO makes the imsg struct less opaque. Maybe there is a better way we can do this? I don't see the other imsg_get_* functions preforming this check. The above calls ibuf_get(3), which does the bounds checking: ibuf_get(struct ibuf *buf, void *data, size_t len) { if (ibuf_size(buf) < len) { errno = EBADMSG; return (-1); } memcpy(data, ibuf_data(buf), len); buf->rpos += len; return (0); } I propose this diff, which removes the check that the requested length of data is equal to the size of the allocated buffer. This would: rely on the bounds check preformed in the ibuf_get(3) functions, removes a ibuf_size(3) call, and allow the use of imsg_get_data(3) without really knowing anything about the imsg struct. diff /usr/src path + /usr/src commit - 63d30f6f93ff9faed796cfea1af89df9fa4894de blob - b8d93d4ece10b8ae89b8c469d17d179126f22b3b file + lib/libutil/imsg.c --- lib/libutil/imsg.c +++ lib/libutil/imsg.c @@ -194,10 +194,6 @@ imsg_get_data(struct imsg *imsg, void *data, size_t le errno = EINVAL; return (-1); } - if (ibuf_size(imsg->buf) != len) { - errno = EBADMSG; - return (-1); - } return ibuf_get(imsg->buf, data, len); } Thoughts/Comments/Suggestions? I can also share more about the specific use-case I am running into if that makes a difference.