Add a global mutex, accept_filter_mtx, to protect the global list of
accept filters and prevent read-modify-write races.
This commit is contained in:
parent
897ade31a2
commit
d087080c1f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=129920
@ -35,15 +35,23 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
static struct mtx accept_filter_mtx;
|
||||
MTX_SYSINIT(accept_filter, &accept_filter_mtx, "accept_filter_mtx",
|
||||
MTX_DEF);
|
||||
#define ACCEPT_FILTER_LOCK() mtx_lock(&accept_filter_mtx)
|
||||
#define ACCEPT_FILTER_UNLOCK() mtx_unlock(&accept_filter_mtx)
|
||||
|
||||
static SLIST_HEAD(, accept_filter) accept_filtlsthd =
|
||||
SLIST_HEAD_INITIALIZER(&accept_filtlsthd);
|
||||
|
||||
@ -67,12 +75,15 @@ accept_filt_add(struct accept_filter *filt)
|
||||
{
|
||||
struct accept_filter *p;
|
||||
|
||||
ACCEPT_FILTER_LOCK();
|
||||
SLIST_FOREACH(p, &accept_filtlsthd, accf_next)
|
||||
if (strcmp(p->accf_name, filt->accf_name) == 0) {
|
||||
if (p->accf_callback != NULL) {
|
||||
ACCEPT_FILTER_UNLOCK();
|
||||
return (EEXIST);
|
||||
} else {
|
||||
p->accf_callback = filt->accf_callback;
|
||||
ACCEPT_FILTER_UNLOCK();
|
||||
FREE(filt, M_ACCF);
|
||||
return (0);
|
||||
}
|
||||
@ -80,6 +91,7 @@ accept_filt_add(struct accept_filter *filt)
|
||||
|
||||
if (p == NULL)
|
||||
SLIST_INSERT_HEAD(&accept_filtlsthd, filt, accf_next);
|
||||
ACCEPT_FILTER_UNLOCK();
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -101,11 +113,13 @@ accept_filt_get(char *name)
|
||||
{
|
||||
struct accept_filter *p;
|
||||
|
||||
ACCEPT_FILTER_LOCK();
|
||||
SLIST_FOREACH(p, &accept_filtlsthd, accf_next)
|
||||
if (strcmp(p->accf_name, name) == 0)
|
||||
return (p);
|
||||
break;
|
||||
ACCEPT_FILTER_UNLOCK();
|
||||
|
||||
return (NULL);
|
||||
return (p);
|
||||
}
|
||||
|
||||
int
|
||||
@ -113,15 +127,13 @@ accept_filt_generic_mod_event(module_t mod, int event, void *data)
|
||||
{
|
||||
struct accept_filter *p;
|
||||
struct accept_filter *accfp = (struct accept_filter *) data;
|
||||
int s, error;
|
||||
int error;
|
||||
|
||||
switch (event) {
|
||||
case MOD_LOAD:
|
||||
MALLOC(p, struct accept_filter *, sizeof(*p), M_ACCF, M_WAITOK);
|
||||
bcopy(accfp, p, sizeof(*p));
|
||||
s = splnet();
|
||||
error = accept_filt_add(p);
|
||||
splx(s);
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
@ -132,9 +144,7 @@ accept_filt_generic_mod_event(module_t mod, int event, void *data)
|
||||
* in the struct accept_filter.
|
||||
*/
|
||||
if (unloadable != 0) {
|
||||
s = splnet();
|
||||
error = accept_filt_del(accfp->accf_name);
|
||||
splx(s);
|
||||
} else
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user