- Avoid array overrun in kfilter_byname_user() when all user
kfilter slots are used: no guarantee previously that last slot had a NULL name. - Reuse previously deregistered user kfilter slots in kfilter_register().
This commit is contained in:
parent
18bbc9e1d3
commit
dfb8aa55d3
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_event.c,v 1.30 2006/07/23 22:06:11 ad Exp $ */
|
||||
/* $NetBSD: kern_event.c,v 1.31 2006/09/30 02:39:18 seanb Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
|
||||
|
@ -29,7 +29,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.30 2006/07/23 22:06:11 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.31 2006/09/30 02:39:18 seanb Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -173,12 +173,9 @@ kfilter_byname_user(const char *name)
|
|||
{
|
||||
int i;
|
||||
|
||||
/* user_kfilters[] could be NULL if no filters were registered */
|
||||
if (!user_kfilters)
|
||||
return (NULL);
|
||||
|
||||
for (i = 0; user_kfilters[i].name != NULL; i++) {
|
||||
if (user_kfilters[i].name != '\0' &&
|
||||
/* user filter slots have a NULL name if previously deregistered */
|
||||
for (i = 0; i < user_kfilterc ; i++) {
|
||||
if (user_kfilters[i].name != NULL &&
|
||||
strcmp(name, user_kfilters[i].name) == 0)
|
||||
return (&user_kfilters[i]);
|
||||
}
|
||||
|
@ -229,6 +226,7 @@ kfilter_register(const char *name, const struct filterops *filtops,
|
|||
struct kfilter *kfilter;
|
||||
void *space;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (name == NULL || name[0] == '\0' || filtops == NULL)
|
||||
return (EINVAL); /* invalid args */
|
||||
|
@ -237,6 +235,14 @@ kfilter_register(const char *name, const struct filterops *filtops,
|
|||
if (user_kfilterc > 0xffffffff - EVFILT_SYSCOUNT)
|
||||
return (EINVAL); /* too many */
|
||||
|
||||
for (i = 0; i < user_kfilterc; i++) {
|
||||
kfilter = &user_kfilters[i];
|
||||
if (kfilter->name == NULL) {
|
||||
/* Previously deregistered slot. Reuse. */
|
||||
goto reuse;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if need to grow user_kfilters */
|
||||
if (user_kfilterc + 1 > user_kfiltermaxc) {
|
||||
/*
|
||||
|
@ -261,21 +267,23 @@ kfilter_register(const char *name, const struct filterops *filtops,
|
|||
free(user_kfilters, M_KEVENT);
|
||||
user_kfilters = kfilter;
|
||||
}
|
||||
/* Adding new slot */
|
||||
kfilter = &user_kfilters[user_kfilterc++];
|
||||
reuse:
|
||||
len = strlen(name) + 1; /* copy name */
|
||||
space = malloc(len, M_KEVENT, M_WAITOK);
|
||||
memcpy(space, name, len);
|
||||
user_kfilters[user_kfilterc].name = space;
|
||||
kfilter->name = space;
|
||||
|
||||
user_kfilters[user_kfilterc].filter = user_kfilterc + EVFILT_SYSCOUNT;
|
||||
kfilter->filter = (kfilter - user_kfilters) + EVFILT_SYSCOUNT;
|
||||
|
||||
len = sizeof(struct filterops); /* copy filtops */
|
||||
space = malloc(len, M_KEVENT, M_WAITOK);
|
||||
memcpy(space, filtops, len);
|
||||
user_kfilters[user_kfilterc].filtops = space;
|
||||
kfilter->filtops = space;
|
||||
|
||||
if (retfilter != NULL)
|
||||
*retfilter = user_kfilters[user_kfilterc].filter;
|
||||
user_kfilterc++; /* finally, increment count */
|
||||
*retfilter = kfilter->filter;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -300,11 +308,10 @@ kfilter_unregister(const char *name)
|
|||
if (kfilter == NULL) /* not found */
|
||||
return (ENOENT);
|
||||
|
||||
if (kfilter->name[0] != '\0') {
|
||||
/* XXXUNCONST Cast away const (but we know it's safe. */
|
||||
free(__UNCONST(kfilter->name), M_KEVENT);
|
||||
kfilter->name = ""; /* mark as `not implemented' */
|
||||
}
|
||||
/* XXXUNCONST Cast away const (but we know it's safe. */
|
||||
free(__UNCONST(kfilter->name), M_KEVENT);
|
||||
kfilter->name = NULL; /* mark as `not implemented' */
|
||||
|
||||
if (kfilter->filtops != NULL) {
|
||||
/* XXXUNCONST Cast away const (but we know it's safe. */
|
||||
free(__UNCONST(kfilter->filtops), M_KEVENT);
|
||||
|
|
Loading…
Reference in New Issue