1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-20 11:11:24 +00:00

Aquire GIANT in pf_proto_[un]register() before manipulating the protosw.

This commit is contained in:
Andre Oppermann 2004-10-23 18:52:06 +00:00
parent bf59255f44
commit 480fa3f985
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=136819

View File

@ -237,23 +237,36 @@ pf_proto_register(family, npr)
npr->pr_domain = dp;
fpr = NULL;
/*
* Protect us against races when two protocol registrations for
* the same protocol happen at the same time.
*/
mtx_lock(&Giant);
/* The new protocol must not yet exist. */
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
if ((pr->pr_type == npr->pr_type) &&
(pr->pr_protocol == npr->pr_protocol))
(pr->pr_protocol == npr->pr_protocol)) {
mtx_unlock(&Giant);
return (EEXIST); /* XXX: Check only protocol? */
}
/* While here, remember the first free spacer. */
if ((fpr == NULL) && (pr->pr_protocol == PROTO_SPACER))
fpr = pr;
}
/* If no free spacer is found we can't add the new protocol. */
if (fpr == NULL)
if (fpr == NULL) {
mtx_unlock(&Giant);
return (ENOMEM);
}
/* Copy the new struct protosw over the spacer. */
bcopy(npr, fpr, sizeof(*fpr));
/* Job is done, no more protection required. */
mtx_unlock(&Giant);
/* Initialize and activate the protocol. */
if (fpr->pr_init)
(fpr->pr_init)();
@ -291,19 +304,25 @@ pf_proto_unregister(family, protocol, type)
found:
dpr = NULL;
/* Lock out everyone else while we are manipulating the protosw. */
mtx_lock(&Giant);
/* The protocol must exist and only once. */
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
if ((pr->pr_type == type) && (pr->pr_protocol == protocol)) {
if (dpr != NULL)
if (dpr != NULL) {
mtx_unlock(&Giant);
return (EMLINK); /* Should not happen! */
else
} else
dpr = pr;
}
}
/* Protocol does not exist. */
if (dpr == NULL)
if (dpr == NULL) {
mtx_unlock(&Giant);
return (EPROTONOSUPPORT);
}
/* De-orbit the protocol and make the slot available again. */
dpr->pr_type = 0;
@ -321,6 +340,9 @@ pf_proto_unregister(family, protocol, type)
dpr->pr_drain = NULL;
dpr->pr_usrreqs = &nousrreqs;
/* Job is done, not more protection required. */
mtx_unlock(&Giant);
return (0);
}