diff --git a/compat.h b/compat.h index 39e784dc..e85536cb 100644 --- a/compat.h +++ b/compat.h @@ -51,13 +51,6 @@ #include <sys/filio.h> #endif -#ifndef HAVE_BSD_TYPES -typedef uint8_t u_int8_t; -typedef uint16_t u_int16_t; -typedef uint32_t u_int32_t; -typedef uint64_t u_int64_t; -#endif - #ifdef HAVE_ERR_H #include <err.h> #else @@ -217,6 +210,16 @@ void warnx(const char *, ...); #define flock(fd, op) (0) #endif +#ifndef HAVE_EXPLICIT_BZERO +/* explicit_bzero.c */ +void explicit_bzero(void *, size_t); +#endif + +#ifndef HAVE_GETDTABLECOUNT +/* getdtablecount.c */ +int getdtablecount(void); +#endif + #ifndef HAVE_CLOSEFROM /* closefrom.c */ void closefrom(int); @@ -317,6 +320,11 @@ void cfmakeraw(struct termios *); void *reallocarray(void *, size_t, size_t); #endif +#ifndef HAVE_RECALLOCARRAY +/* recallocarray.c */ +void *recallocarray(void *, size_t, size_t, size_t); +#endif + #ifdef HAVE_UTF8PROC /* utf8proc.c */ int utf8proc_wcwidth(wchar_t); diff --git a/compat/asprintf.c b/compat/asprintf.c index 2b53dbe2..95d78430 100644 --- a/compat/asprintf.c +++ b/compat/asprintf.c @@ -14,15 +14,14 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <sys/types.h> + #include <stdarg.h> #include <stdio.h> -#ifdef HAVE_STDINT_H -#include <stdint.h> -#else -#include <inttypes.h> -#endif #include <string.h> +#include "compat.h" + int asprintf(char **ret, const char *fmt, ...) { diff --git a/compat/explicit_bzero.c b/compat/explicit_bzero.c new file mode 100644 index 00000000..e8bc5b36 --- /dev/null +++ b/compat/explicit_bzero.c @@ -0,0 +1,15 @@ +/* $OpenBSD: explicit_bzero.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */ +/* + * Public domain. + * Written by Matthew Dempsky. + */ + +#include <string.h> + +#include "compat.h" + +void +explicit_bzero(void *buf, size_t len) +{ + memset(buf, 0, len); +} diff --git a/compat/getdtablecount.c b/compat/getdtablecount.c new file mode 100644 index 00000000..3ccab650 --- /dev/null +++ b/compat/getdtablecount.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <glob.h> +#include <unistd.h> + +#include "compat.h" + +void fatal(const char *, ...); +void fatalx(const char *, ...); + +#ifdef HAVE_PROC_PID +int +getdtablecount(void) +{ + char path[PATH_MAX]; + glob_t g; + int n; + + if (snprintf(path, sizeof path, "/proc/%ld/fd/*", (long)getpid()) < 0) + fatal("snprintf overflow"); + switch (glob(path, 0, NULL, &g)) { + case GLOB_NOMATCH: + return (0); + case 0: + break; + default: + fatal("glob(\"%s\") failed", path); + } + n = g.gl_pathc; + globfree(&g); + return (n); +} +#else +int +getdtablecount(void) +{ + return (0); +} +#endif diff --git a/compat/imsg-buffer.c b/compat/imsg-buffer.c index 4c8d5e2c..3576d5f0 100644 --- a/compat/imsg-buffer.c +++ b/compat/imsg-buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg-buffer.c,v 1.7 2015/07/12 18:40:49 nicm Exp $ */ +/* $OpenBSD: imsg-buffer.c,v 1.9 2017/03/17 14:51:26 deraadt Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -78,7 +78,7 @@ ibuf_realloc(struct ibuf *buf, size_t len) return (-1); } - b = realloc(buf->buf, buf->wpos + len); + b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1); if (b == NULL) return (-1); buf->buf = b; @@ -180,6 +180,8 @@ again: void ibuf_free(struct ibuf *buf) { + if (buf == NULL) + return; free(buf->buf); free(buf); } diff --git a/compat/imsg.c b/compat/imsg.c index 422f37ab..987284b3 100644 --- a/compat/imsg.c +++ b/compat/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.9 2015/07/12 18:40:49 nicm Exp $ */ +/* $OpenBSD: imsg.c,v 1.14 2017/03/24 09:34:12 nicm Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -32,40 +32,6 @@ int imsg_fd_overhead = 0; int imsg_get_fd(struct imsgbuf *); -int available_fds(unsigned int); - -/* - * The original code calls getdtablecount() which is OpenBSD specific. Use - * available_fds() from OpenSMTPD instead. - */ -int -available_fds(unsigned int n) -{ - unsigned int i; - int ret, fds[256]; - - if (n > (sizeof(fds)/sizeof(fds[0]))) - return (1); - - ret = 0; - for (i = 0; i < n; i++) { - fds[i] = -1; - if ((fds[i] = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) - fds[i] = socket(AF_INET6, SOCK_DGRAM, 0); - if (fds[i] < 0) { - ret = 1; - break; - } - } - } - - for (i = 0; i < n && fds[i] >= 0; i++) - close(fds[i]); - - return (ret); -} - void imsg_init(struct imsgbuf *ibuf, int fd) { @@ -105,19 +71,18 @@ imsg_read(struct imsgbuf *ibuf) return (-1); again: - if (available_fds(imsg_fd_overhead + - (CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))) { + if (getdtablecount() + imsg_fd_overhead + + (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int)) + >= getdtablesize()) { errno = EAGAIN; free(ifd); return (-1); } if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { - if (errno == EMSGSIZE) - goto fail; - if (errno != EINTR && errno != EAGAIN) - goto fail; - goto again; + if (errno == EINTR) + goto again; + goto fail; } ibuf->r.wpos += n; @@ -151,8 +116,7 @@ again: } fail: - if (ifd) - free(ifd); + free(ifd); return (n); } @@ -176,7 +140,9 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) return (0); datalen = imsg->hdr.len - IMSG_HEADER_SIZE; ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE; - if ((imsg->data = malloc(datalen)) == NULL) + if (datalen == 0) + imsg->data = NULL; + else if ((imsg->data = malloc(datalen)) == NULL) return (-1); if (imsg->hdr.flags & IMSGF_HASFD) @@ -197,8 +163,8 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) } int -imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, int fd, const void *data, u_int16_t datalen) +imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid, + int fd, const void *data, uint16_t datalen) { struct ibuf *wbuf; @@ -216,8 +182,8 @@ imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, } int -imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, int fd, const struct iovec *iov, int iovcnt) +imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid, + int fd, const struct iovec *iov, int iovcnt) { struct ibuf *wbuf; int i, datalen = 0; @@ -241,8 +207,8 @@ imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, /* ARGSUSED */ struct ibuf * -imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, u_int16_t datalen) +imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid, + uint16_t datalen) { struct ibuf *wbuf; struct imsg_hdr hdr; @@ -268,7 +234,7 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, } int -imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen) +imsg_add(struct ibuf *msg, const void *data, uint16_t datalen) { if (datalen) if (ibuf_add(msg, data, datalen) == -1) { @@ -289,7 +255,7 @@ imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) if (msg->fd != -1) hdr->flags |= IMSGF_HASFD; - hdr->len = (u_int16_t)msg->wpos; + hdr->len = (uint16_t)msg->wpos; ibuf_close(&ibuf->w, msg); } diff --git a/compat/imsg.h b/compat/imsg.h index 89946578..8bf94147 100644 --- a/compat/imsg.h +++ b/compat/imsg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.h,v 1.3 2013/12/26 17:32:33 eric Exp $ */ +/* $OpenBSD: imsg.h,v 1.4 2017/03/24 09:34:12 nicm Exp $ */ /* * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -37,7 +37,7 @@ struct ibuf { struct msgbuf { TAILQ_HEAD(, ibuf) bufs; - u_int32_t queued; + uint32_t queued; int fd; }; @@ -63,11 +63,11 @@ struct imsgbuf { #define IMSGF_HASFD 1 struct imsg_hdr { - u_int32_t type; - u_int16_t len; - u_int16_t flags; - u_int32_t peerid; - u_int32_t pid; + uint32_t type; + uint16_t len; + uint16_t flags; + uint32_t peerid; + uint32_t pid; }; struct imsg { @@ -97,13 +97,12 @@ void msgbuf_drain(struct msgbuf *, size_t); void imsg_init(struct imsgbuf *, int); ssize_t imsg_read(struct imsgbuf *); ssize_t imsg_get(struct imsgbuf *, struct imsg *); -int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, - int, const void *, u_int16_t); -int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, - int, const struct iovec *, int); -struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, - u_int16_t); -int imsg_add(struct ibuf *, const void *, u_int16_t); +int imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, + const void *, uint16_t); +int imsg_composev(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, + const struct iovec *, int); +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 *); void imsg_free(struct imsg *); int imsg_flush(struct imsgbuf *); diff --git a/compat/recallocarray.c b/compat/recallocarray.c new file mode 100644 index 00000000..74a919a1 --- /dev/null +++ b/compat/recallocarray.c @@ -0,0 +1,82 @@ +/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */ +/* + * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <errno.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include "compat.h" + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) +{ + size_t oldsize, newsize; + void *newptr; + + if (ptr == NULL) + return calloc(newnmemb, size); + + if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + newnmemb > 0 && SIZE_MAX / newnmemb < size) { + errno = ENOMEM; + return NULL; + } + newsize = newnmemb * size; + + if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + errno = EINVAL; + return NULL; + } + oldsize = oldnmemb * size; + + /* + * Don't bother too much if we're shrinking just a bit, + * we do not shrink for series of small steps, oh well. + */ + if (newsize <= oldsize) { + size_t d = oldsize - newsize; + + if (d < oldsize / 2 && d < (size_t)getpagesize()) { + memset((char *)ptr + newsize, 0, d); + return ptr; + } + } + + newptr = malloc(newsize); + if (newptr == NULL) + return NULL; + + if (newsize > oldsize) { + memcpy(newptr, ptr, oldsize); + memset((char *)newptr + oldsize, 0, newsize - oldsize); + } else + memcpy(newptr, ptr, newsize); + + explicit_bzero(ptr, oldsize); + free(ptr); + + return newptr; +} diff --git a/configure.ac b/configure.ac index db0baf1a..115dd1de 100644 --- a/configure.ac +++ b/configure.ac @@ -102,9 +102,12 @@ AC_REPLACE_FUNCS([ \ asprintf \ cfmakeraw \ closefrom \ + explicit_bzero \ fgetln \ fparseln \ + getdtablecount \ getprogname \ + recallocarray \ reallocarray \ setenv \ setproctitle \ @@ -457,23 +460,6 @@ if test "x$found_forkpty" = xyes; then fi AM_CONDITIONAL(NEED_FORKPTY, test "x$found_forkpty" = xno) -# Check for BSD-style integer types. -AC_MSG_CHECKING(for BSD-style unsigned types) -AC_COMPILE_IFELSE([AC_LANG_SOURCE( - [ - #include <sys/types.h> - #ifdef HAVE_STDINT_H - #include <stdint.h> - #else - #include <inttypes.h> - #endif - int main(void) - { u_int8_t u8; u_int16_t u16; u_int32_t u32; u_int64_t u64; } - ])], - [AC_DEFINE(HAVE_BSD_TYPES) AC_MSG_RESULT(yes)], - AC_MSG_RESULT(no) -) - # Look for a suitable queue.h. AC_CHECK_DECL( TAILQ_CONCAT,