⬢ DragonFlyBSD Kernel Audit
DF-2895 / kenv_set.c
← back to finding ↓ download raw
/* DF-2895: sys_kenv KENV_SET ignores ksetenv() failure.
 * A KENV name of exactly KENV_MNAMELEN(128) chars passes the syscall
 * copyinstr (129 cap) but is rejected inside ksetenv -> syscall returns
 * success while nothing was stored.
 *
 * expect (vulnerable): set rv=0, get ENOENT (silent drop)
 * expect (patched):    set rv=-1 EINVAL
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int kenv(int action, const char *name, char *value, int len);
#ifndef KENV_GET
#define KENV_GET	0
#define KENV_SET	1
#define KENV_UNSET	2
#endif

#ifndef KENV_MNAMELEN
#define KENV_MNAMELEN 128
#endif

int
main(void)
{
	char name[KENV_MNAMELEN + 1];
	char small[256];
	int rv, err;

	memset(name, 'D', KENV_MNAMELEN);
	name[KENV_MNAMELEN] = 0;

	errno = 0;
	rv = kenv(KENV_SET, name, "df2895value", 12);
	err = errno;
	printf("DF2895 KENV_SET(128-char name) rv=%d errno=%d (%s)\n",
	    rv, err, strerror(err));

	errno = 0;
	rv = kenv(KENV_GET, name, small, sizeof(small));
	err = errno;
	printf("DF2895 KENV_GET(same name)      rv=%d errno=%d (%s)\n",
	    rv, err, strerror(err));

	/* boundary control: 127-char name must work */
	name[KENV_MNAMELEN - 1] = 0;
	errno = 0;
	rv = kenv(KENV_SET, name, "df2895ok", 9);
	err = errno;
	printf("DF2895 KENV_SET(127-char name)  rv=%d errno=%d (control: works)\n",
	    rv, err);
	errno = 0;
	rv = kenv(KENV_GET, name, small, sizeof(small));
	printf("DF2895 KENV_GET(127-char name)  rv=%d value=%s\n", rv, rv > 0 ? small : "-");
	(void)kenv(KENV_UNSET, name, NULL, 0);

	return 0;
}