Hi, this is of interest for amd64 and i386 only:
The bootarg code is a code collection to manage a bootarg_list, which can be assembled into contiguous code with makebootargs(). makebootargs takes two arguments: pointer and available space. Upon return, the available space variable will be overriden with actually consumed space. consumed space = previously added bootargs + size for terminating bootarg of type BOOTARG_END. If there are too many bootargs, they will be truncated. If DEBUG has been defined, a warning will give information about this situation. Unfortunately the code allows an overrun upon truncation. If truncation occurs, the for-loop of available bootargs will add as many bootargs as possible _ignoring the additional BOOTARG_END_, which will be added at the end. Therefore the fix is simple: consider space for additional bootarg. Additionally to this, bootarg_list can be static again, that was changed back in OpenBSD 2.3 times. Also, return the actually consumed space if truncation occurred, not simply available space. I wrote an example code + Makefile that triggers this overflow in userland: http://stoeckmann.org/openbsd/bootarg.tar.gz Two programs get created from main.c: - crash adds a bootarg in "perfect size" to let BOOTARG_END overflow into guard page on i386 - nocrash adds the largest allowed bootarg -- not crashing. Tobias Index: bootarg.c =================================================================== RCS file: /cvs/src/sys/stand/boot/bootarg.c,v retrieving revision 1.10 diff -u -p -u -p -r1.10 bootarg.c --- bootarg.c 11 Aug 2003 06:23:07 -0000 1.10 +++ bootarg.c 26 Jun 2014 21:22:18 -0000 @@ -30,7 +30,7 @@ #include <lib/libsa/stand.h> #include <stand/boot/bootarg.h> -bootarg_t *bootarg_list; +static bootarg_t *bootarg_list; void addbootarg(int t, size_t l, void *p) @@ -53,18 +53,20 @@ makebootargs(caddr_t v, size_t *lenp) /* get total size */ l = sizeof(*p); - for (p = bootarg_list; p != NULL; p = p->ba_next) + for (p = bootarg_list; p != NULL; p = p->ba_next) { l += p->ba_size; - if (*lenp < l) { + if (*lenp < l) { #ifdef DEBUG - printf("makebootargs: too many args\n"); + printf("makebootargs: too many args\n"); #endif - l = *lenp; + l -= p->ba_size; + break; + } } *lenp = l; /* copy them out */ for (p = bootarg_list, q = v; - p != NULL && ((q + p->ba_size) - (u_char *)v) < l; + p != NULL && ((q + p->ba_size) - (u_char *)v) <= l - sizeof(*p); q += p->ba_size, p = p->ba_next) { #ifdef DEBUG printf("%d,%d ", p->ba_type, p->ba_size);