From dfb8aa55d370023baaaa03e66ae22d1011bac491 Mon Sep 17 00:00:00 2001 From: seanb Date: Sat, 30 Sep 2006 02:39:18 +0000 Subject: [PATCH] - 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(). --- sys/kern/kern_event.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 8e95a342e58e..b2f12d7ef685 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -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 @@ -29,7 +29,7 @@ */ #include -__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 #include @@ -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);