svn commit: r194841 - head/sys/kern
Jamie Gritton
jamie at FreeBSD.org
Wed Jun 24 15:29:37 UTC 2009
Author: jamie
Date: Wed Jun 24 15:29:36 2009
New Revision: 194841
URL: http://svn.freebsd.org/changeset/base/194841
Log:
Fix a race in vi_if_move, where a vnet is used after the prison that
referred to it has been released.
Approved by: bz (mentor)
Modified:
head/sys/kern/kern_vimage.c
Modified: head/sys/kern/kern_vimage.c
==============================================================================
--- head/sys/kern/kern_vimage.c Wed Jun 24 15:24:51 2009 (r194840)
+++ head/sys/kern/kern_vimage.c Wed Jun 24 15:29:36 2009 (r194841)
@@ -117,9 +117,11 @@ vi_if_move(struct thread *td, struct ifn
struct prison *pr;
struct vimage *new_vip, *my_vip;
struct vnet *new_vnet;
+ int error;
if (vi_req != NULL) {
/* SIOCSIFVIMAGE */
+ pr = NULL;
/* Check for API / ABI version mismatch. */
if (vi_req->vi_api_cookie != VI_API_COOKIE)
return (EDOOFUS);
@@ -148,6 +150,7 @@ vi_if_move(struct thread *td, struct ifn
sx_sunlock(&allprison_lock);
if (pr == NULL)
return (ENXIO);
+ prison_hold_locked(pr);
mtx_unlock(&pr->pr_mtx);
if (ifp != NULL) {
/* SIOCSIFVNET */
@@ -158,31 +161,35 @@ vi_if_move(struct thread *td, struct ifn
CURVNET_SET(pr->pr_vnet);
ifp = ifunit(ifname);
CURVNET_RESTORE();
- if (ifp == NULL)
+ if (ifp == NULL) {
+ prison_free(pr);
return (ENXIO);
+ }
}
-
- /* No-op if the target jail has the same vnet. */
- if (new_vnet == ifp->if_vnet)
- return (0);
}
- /*
- * Check for naming clashes in target vnet. Not locked so races
- * are possible.
- */
- CURVNET_SET_QUIET(new_vnet);
- t_ifp = ifunit(ifname);
- CURVNET_RESTORE();
- if (t_ifp != NULL)
- return (EEXIST);
-
- /* Detach from curvnet and attach to new_vnet. */
- if_vmove(ifp, new_vnet);
+ error = 0;
+ if (new_vnet != ifp->if_vnet) {
+ /*
+ * Check for naming clashes in target vnet. Not locked so races
+ * are possible.
+ */
+ CURVNET_SET_QUIET(new_vnet);
+ t_ifp = ifunit(ifname);
+ CURVNET_RESTORE();
+ if (t_ifp != NULL)
+ error = EEXIST;
+ else {
+ /* Detach from curvnet and attach to new_vnet. */
+ if_vmove(ifp, new_vnet);
- /* Report the new if_xname back to the userland */
- sprintf(ifname, "%s", ifp->if_xname);
- return (0);
+ /* Report the new if_xname back to the userland */
+ sprintf(ifname, "%s", ifp->if_xname);
+ }
+ }
+ if (pr != NULL)
+ prison_free(pr);
+ return (error);
}
/*
More information about the svn-src-all
mailing list