From: Claudio Jeker Subject: Re: httpd: convert imsg handling to imsg_get_ and remove IMSG_SIZE_CHECK macro To: Rafael Sadowski Cc: tech@openbsd.org Date: Fri, 18 Sep 2026 17:02:44 +0200 On Fri, Sep 18, 2026 at 04:57:32PM +0200, Rafael Sadowski wrote: > This is a fist diff on a longer imsg journey in httpd. The goal is to > remove IMSG_SIZE_CHECK(). Hell yes. this is lovely. Comments below. > commit e08b6a50c4d986afa2b3eda5fb7661fcf7ed90f3 > Author: Rafael Sadowski > Date: Sun Aug 30 08:50:26 2026 +0200 > > httpd: convert imsg handling to imsg_get_ and remove IMSG_SIZE_CHECK macro > > diff --git a/config.c b/config.c > index ecaa59a..4001d86 100644 > --- a/config.c > +++ b/config.c > @@ -130,8 +130,8 @@ config_getreset(struct httpd *env, struct imsg *imsg) > { > unsigned int mode; > > - IMSG_SIZE_CHECK(imsg, &mode); > - memcpy(&mode, imsg->data, sizeof(mode)); > + if (imsg_get_data(imsg, &mode, sizeof(mode)) == -1) > + fatalx("%s: imsg_get_data", __func__); > > config_purge(env, mode); > > @@ -621,8 +621,11 @@ config_getserver_config(struct httpd *env, struct server *srv, > if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL) > return (-1); > > - IMSG_SIZE_CHECK(imsg, srv_conf); > - memcpy(srv_conf, p, sizeof(*srv_conf)); > + if (imsg_get_data(imsg, srv_conf, sizeof(*srv_conf)) == -1) { > + free(srv_conf); > + fatalx("%s: imsg_get_data", __func__); fatalx is terminal. So no need to free() something before. > + } > + > s = sizeof(*srv_conf); > > /* Reset these variables to avoid free'ing invalid pointers */ > @@ -804,8 +807,9 @@ config_getserver(struct httpd *env, struct imsg *imsg) > size_t s; > int fd; > > - IMSG_SIZE_CHECK(imsg, &srv_conf); > - memcpy(&srv_conf, p, sizeof(srv_conf)); > + if (imsg_get_data(imsg, &srv_conf, sizeof(srv_conf)) == -1) > + fatalx("%s: imsg_get_data", __func__); > + > s = sizeof(srv_conf); > > /* Reset these variables to avoid free'ing invalid pointers */ > @@ -928,22 +932,27 @@ config_gettls(struct httpd *env, struct server_config *srv_conf, > int > config_getserver_tls(struct httpd *env, struct imsg *imsg) > { > + struct ibuf ibuf; > struct server_config *srv_conf = NULL; > struct tls_config tls_conf; > - uint8_t *p = imsg->data; > + uint8_t *data; > size_t len; > > - IMSG_SIZE_CHECK(imsg, &tls_conf); > - memcpy(&tls_conf, p, sizeof(tls_conf)); > + if (imsg_get_ibuf(imsg, &ibuf) == -1) { > + log_warn("%s: imsg_get_ibuf", __func__); > + return (-1); > + } > > - len = tls_conf.tls_chunk_len; > + if (ibuf_get(&ibuf, &tls_conf, sizeof(tls_conf)) == -1) > + fatalx("%s: ibuf_get", __func__); > > - if ((IMSG_DATA_SIZE(imsg) - sizeof(tls_conf)) < len) { > + if (ibuf_size(&ibuf) != tls_conf.tls_chunk_len) { > log_debug("%s: invalid message length", __func__); > goto fail; > } > > - p += sizeof(tls_conf); > + data = ibuf_data(&ibuf); > + len = tls_conf.tls_chunk_len; > > if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) { > log_debug("%s: server not found", __func__); > @@ -952,32 +961,32 @@ config_getserver_tls(struct httpd *env, struct imsg *imsg) > > switch (tls_conf.tls_type) { > case TLS_CFG_CA: > - if (config_gettls(env, srv_conf, &tls_conf, "ca", p, len, > + if (config_gettls(env, srv_conf, &tls_conf, "ca", data, len, > &srv_conf->tls_ca, &srv_conf->tls_ca_len) != 0) > goto fail; > break; > > case TLS_CFG_CERT: > - if (config_gettls(env, srv_conf, &tls_conf, "cert", p, len, > + if (config_gettls(env, srv_conf, &tls_conf, "cert", data, len, > &srv_conf->tls_cert, &srv_conf->tls_cert_len) != 0) > goto fail; > break; > > case TLS_CFG_CRL: > - if (config_gettls(env, srv_conf, &tls_conf, "crl", p, len, > + if (config_gettls(env, srv_conf, &tls_conf, "crl", data, len, > &srv_conf->tls_crl, &srv_conf->tls_crl_len) != 0) > goto fail; > break; > > case TLS_CFG_KEY: > - if (config_gettls(env, srv_conf, &tls_conf, "key", p, len, > + if (config_gettls(env, srv_conf, &tls_conf, "key", data, len, > &srv_conf->tls_key, &srv_conf->tls_key_len) != 0) > goto fail; > break; > > case TLS_CFG_OCSP_STAPLE: > if (config_gettls(env, srv_conf, &tls_conf, "ocsp staple", > - p, len, &srv_conf->tls_ocsp_staple, > + data, len, &srv_conf->tls_ocsp_staple, > &srv_conf->tls_ocsp_staple_len) != 0) > goto fail; > break; > @@ -1029,10 +1038,9 @@ config_getmedia(struct httpd *env, struct imsg *imsg) > struct privsep *ps = env->sc_ps; > #endif > struct media_type media; > - uint8_t *p = imsg->data; > > - IMSG_SIZE_CHECK(imsg, &media); > - memcpy(&media, p, sizeof(media)); > + if (imsg_get_data(imsg, &media, sizeof(media)) == -1) > + fatalx("%s: imsg_get_data", __func__); > > if (media_add(env->sc_mediatypes, &media) == NULL) { > log_debug("%s: failed to add media \"%s\"", > @@ -1085,10 +1093,9 @@ config_getauth(struct httpd *env, struct imsg *imsg) > struct privsep *ps = env->sc_ps; > #endif > struct auth auth; > - uint8_t *p = imsg->data; > > - IMSG_SIZE_CHECK(imsg, &auth); > - memcpy(&auth, p, sizeof(auth)); > + if (imsg_get_data(imsg, &auth, sizeof(auth)) == -1) > + fatalx("%s: imsg_get_data", __func__); > > if (auth_add(env->sc_auth, &auth) == NULL) { > log_debug("%s: failed to add auth \"%s[%u]\"", > diff --git a/httpd.c b/httpd.c > index 6d8d031..4b2303b 100644 > --- a/httpd.c > +++ b/httpd.c > @@ -430,8 +430,8 @@ parent_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg) > > switch (imsg->hdr.type) { > case IMSG_CTL_RESET: > - IMSG_SIZE_CHECK(imsg, &v); > - memcpy(&v, imsg->data, sizeof(v)); > + if (imsg_get_data(imsg, &v, sizeof(v)) == -1) > + fatalx("%s: imsg_get_data", __func__); > parent_reload(env, v, NULL); > break; > case IMSG_CTL_RELOAD: > diff --git a/httpd.h b/httpd.h > index 71377cf..99631ee 100644 > --- a/httpd.h > +++ b/httpd.h > @@ -164,10 +164,6 @@ struct imsgev { > short events; > }; > > -#define IMSG_SIZE_CHECK(imsg, p) do { \ > - if (IMSG_DATA_SIZE(imsg) < sizeof(*p)) \ > - fatalx("bad length imsg received"); \ > -} while (0) > #define IMSG_DATA_SIZE(imsg) ((imsg)->hdr.len - IMSG_HEADER_SIZE) > #define MAX_IMSG_DATA_SIZE (MAX_IMSGSIZE - IMSG_HEADER_SIZE) > > diff --git a/logger.c b/logger.c > index c2eae70..049a5b1 100644 > --- a/logger.c > +++ b/logger.c > @@ -140,8 +140,8 @@ logger_open_fd(struct imsg *imsg) > struct log_file *log; > uint32_t id; > > - IMSG_SIZE_CHECK(imsg, &id); > - memcpy(&id, imsg->data, sizeof(id)); > + if (imsg_get_data(imsg, &id, sizeof(id)) == -1) > + fatalx("%s: imsg_get_data", __func__); > > TAILQ_FOREACH(log, &log_files, log_entry) { > if (log->log_id == id) { > @@ -158,19 +158,37 @@ logger_open_fd(struct imsg *imsg) > int > logger_open_priv(struct imsg *imsg) > { > + struct ibuf ibuf; > char path[PATH_MAX]; > char name[PATH_MAX], *p; > + char *filename = NULL; > uint32_t id; > size_t len; > - int fd; > + int fd, ret; > + > + if (imsg_get_ibuf(imsg, &ibuf) == -1) { > + log_warn("%s: imsg_get_ibuf", __func__); > + return (-1); > + } > > /* called from the privileged process */ > - IMSG_SIZE_CHECK(imsg, &id); > - memcpy(&id, imsg->data, sizeof(id)); > - p = (char *)imsg->data + sizeof(id); > + if (ibuf_get(&ibuf, &id, sizeof(id)) == -1) > + fatalx("%s: ibuf_get", __func__); > > - if ((size_t)snprintf(name, sizeof(name), "/%s", p) >= sizeof(name)) > + if ((len = ibuf_size(&ibuf)) == 0) { > + log_debug("%s: invalid message length", __func__); > return (-1); > + } > + > + if ((filename = ibuf_get_string(&ibuf, len)) == NULL) { > + log_warn("%s: ibuf_get_string", __func__); > + return (-1); > + } > + ret = snprintf(name, sizeof(name), "/%s", filename); > + free(filename); > + if (ret < 0 || (size_t)ret >= sizeof(name)) > + return (-1); > + > if ((len = strlcpy(path, httpd_env->sc_logdir, sizeof(path))) >= > sizeof(path)) > return (-1); > @@ -243,13 +261,20 @@ logger_start(void) > int > logger_log(struct imsg *imsg) > { > + struct ibuf ibuf; > char *logline; > uint32_t id; > struct server_config *srv_conf; > struct log_file *log; > > - IMSG_SIZE_CHECK(imsg, &id); > - memcpy(&id, imsg->data, sizeof(id)); > + if (imsg_get_ibuf(imsg, &ibuf) == -1) { > + log_warn("%s: imsg_get_ibuf", __func__); > + return (-1); > + } > + > + /* called from the privileged process */ > + if (ibuf_get(&ibuf, &id, sizeof(id)) == -1) > + fatalx("%s: ibuf_get", __func__); > > if ((srv_conf = serverconfig_byid(id)) == NULL) > fatalx("invalid logging requestr"); > @@ -265,7 +290,7 @@ logger_log(struct imsg *imsg) > } > > /* XXX get_string() would sanitize the string, but add a malloc */ > - logline = (char *)imsg->data + sizeof(id); > + logline = ibuf_data(&ibuf); > > /* For debug output */ > log_debug("%s", logline); > diff --git a/server.c b/server.c > index bc96722..f3cbb7c 100644 > --- a/server.c > +++ b/server.c > @@ -1408,8 +1408,8 @@ server_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) > return (-1); > break; > case IMSG_TLSTICKET_REKEY: > - IMSG_SIZE_CHECK(imsg, (&key)); > - memcpy(&key, imsg->data, sizeof(key)); > + if (imsg_get_data(imsg, &key, sizeof(key)) == -1) > + fatalx("%s: imsg_get_data", __func__); > /* apply to the right server */ > if ((srv = server_byid(key.tt_id)) == NULL) { > log_debug("%s: invalid sever id", __func__); > Rest look OK. -- :wq Claudio