Remove the interim vimage containers, struct vimage and struct procg,
and the ioctl-based interface that supported them. Approved by: re (kib), bz (mentor)
This commit is contained in:
parent
597df30e62
commit
7afcbc18b3
@ -74,7 +74,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/vimage.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
|
||||
@ -454,12 +453,6 @@ proc0_init(void *dummy __unused)
|
||||
p->p_ucred->cr_uidinfo = uifind(0);
|
||||
p->p_ucred->cr_ruidinfo = uifind(0);
|
||||
p->p_ucred->cr_prison = &prison0;
|
||||
#ifdef VIMAGE
|
||||
KASSERT(LIST_FIRST(&vimage_head) != NULL, ("vimage_head empty"));
|
||||
P_TO_VIMAGE(p) = LIST_FIRST(&vimage_head); /* set ucred->cr_vimage */
|
||||
refcount_acquire(&P_TO_VIMAGE(p)->vi_ucredrefc);
|
||||
LIST_FIRST(&vprocg_head)->nprocs++;
|
||||
#endif
|
||||
#ifdef AUDIT
|
||||
audit_cred_kproc0(p->p_ucred);
|
||||
#endif
|
||||
|
@ -69,7 +69,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sdt.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/vimage.h>
|
||||
#ifdef KTRACE
|
||||
#include <sys/ktrace.h>
|
||||
#endif
|
||||
@ -687,7 +686,6 @@ static void
|
||||
proc_reap(struct thread *td, struct proc *p, int *status, int options,
|
||||
struct rusage *rusage)
|
||||
{
|
||||
INIT_VPROCG(P_TO_VPROCG(p));
|
||||
struct proc *q, *t;
|
||||
|
||||
sx_assert(&proctree_lock, SA_XLOCKED);
|
||||
@ -791,9 +789,6 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options,
|
||||
uma_zfree(proc_zone, p);
|
||||
sx_xlock(&allproc_lock);
|
||||
nprocs--;
|
||||
#ifdef VIMAGE
|
||||
vprocg->nprocs--;
|
||||
#endif
|
||||
sx_xunlock(&allproc_lock);
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sdt.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/vimage.h>
|
||||
|
||||
#include <security/audit/audit.h>
|
||||
#include <security/mac/mac_framework.h>
|
||||
@ -363,9 +362,6 @@ fork1(td, flags, pages, procp)
|
||||
* are hard-limits as to the number of processes that can run.
|
||||
*/
|
||||
nprocs++;
|
||||
#ifdef VIMAGE
|
||||
P_TO_VPROCG(p1)->nprocs++;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find an unused process ID. We remember a range of unused IDs
|
||||
|
@ -3243,10 +3243,6 @@ int
|
||||
prison_check(struct ucred *cred1, struct ucred *cred2)
|
||||
{
|
||||
|
||||
#ifdef VIMAGE
|
||||
if (cred2->cr_vimage->v_procg != cred1->cr_vimage->v_procg)
|
||||
return (ESRCH);
|
||||
#endif
|
||||
return ((cred1->cr_prison == cred2->cr_prison ||
|
||||
prison_ischild(cred1->cr_prison, cred2->cr_prison)) ? 0 : ESRCH);
|
||||
}
|
||||
|
@ -992,12 +992,6 @@ kern_kldload(struct thread *td, const char *file, int *fileid)
|
||||
if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0)
|
||||
return (error);
|
||||
|
||||
#ifdef VIMAGE
|
||||
/* Only the default vimage is permitted to kldload modules. */
|
||||
if (!IS_DEFAULT_VIMAGE(TD_TO_VIMAGE(td)))
|
||||
return (EPERM);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* It is possible that kldloaded module will attach a new ifnet,
|
||||
* so vnet context must be set when this ocurs.
|
||||
@ -1069,12 +1063,6 @@ kern_kldunload(struct thread *td, int fileid, int flags)
|
||||
if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0)
|
||||
return (error);
|
||||
|
||||
#ifdef VIMAGE
|
||||
/* Only the default vimage is permitted to kldunload modules. */
|
||||
if (!IS_DEFAULT_VIMAGE(TD_TO_VIMAGE(td)))
|
||||
return (EPERM);
|
||||
#endif
|
||||
|
||||
CURVNET_SET(TD_TO_VNET(td));
|
||||
KLD_LOCK();
|
||||
lf = linker_find_file_by_id(fileid);
|
||||
|
@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/vimage.h>
|
||||
|
||||
#if defined(INET) || defined(INET6)
|
||||
#include <netinet/in.h>
|
||||
@ -1762,11 +1761,7 @@ p_canwait(struct thread *td, struct proc *p)
|
||||
|
||||
KASSERT(td == curthread, ("%s: td not curthread", __func__));
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
if (
|
||||
#ifdef VIMAGE /* XXX temporary until struct vimage goes away */
|
||||
!vi_child_of(TD_TO_VIMAGE(td), P_TO_VIMAGE(p)) &&
|
||||
#endif
|
||||
(error = prison_check(td->td_ucred, p->p_ucred)))
|
||||
if ((error = prison_check(td->td_ucred, p->p_ucred)))
|
||||
return (error);
|
||||
#ifdef MAC
|
||||
if ((error = mac_proc_check_wait(td->td_ucred, p)))
|
||||
@ -1836,11 +1831,6 @@ crfree(struct ucred *cr)
|
||||
*/
|
||||
if (cr->cr_prison != NULL)
|
||||
prison_free(cr->cr_prison);
|
||||
#ifdef VIMAGE
|
||||
/* XXX TODO: find out why and when cr_vimage can be NULL here! */
|
||||
if (cr->cr_vimage != NULL)
|
||||
refcount_release(&cr->cr_vimage->vi_ucredrefc);
|
||||
#endif
|
||||
#ifdef AUDIT
|
||||
audit_cred_destroy(cr);
|
||||
#endif
|
||||
@ -1877,10 +1867,6 @@ crcopy(struct ucred *dest, struct ucred *src)
|
||||
uihold(dest->cr_uidinfo);
|
||||
uihold(dest->cr_ruidinfo);
|
||||
prison_hold(dest->cr_prison);
|
||||
#ifdef VIMAGE
|
||||
KASSERT(src->cr_vimage != NULL, ("cr_vimage == NULL"));
|
||||
refcount_acquire(&dest->cr_vimage->vi_ucredrefc);
|
||||
#endif
|
||||
#ifdef AUDIT
|
||||
audit_cred_copy(src, dest);
|
||||
#endif
|
||||
|
@ -36,14 +36,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/refcount.h>
|
||||
#include <sys/vimage.h>
|
||||
#ifdef DDB
|
||||
#include <ddb/ddb.h>
|
||||
@ -53,9 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/route.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
MALLOC_DEFINE(M_VIMAGE, "vimage", "vimage resource container");
|
||||
MALLOC_DEFINE(M_VNET, "vnet", "network stack control block");
|
||||
MALLOC_DEFINE(M_VPROCG, "vprocg", "process group control block");
|
||||
|
||||
static TAILQ_HEAD(vnet_modlink_head, vnet_modlink) vnet_modlink_head;
|
||||
static TAILQ_HEAD(vnet_modpending_head, vnet_modlink) vnet_modpending_head;
|
||||
@ -63,12 +58,6 @@ static void vnet_mod_complete_registration(struct vnet_modlink *);
|
||||
static int vnet_mod_constructor(struct vnet_modlink *);
|
||||
static int vnet_mod_destructor(struct vnet_modlink *);
|
||||
|
||||
static struct vimage *vi_alloc(struct vimage *, char *);
|
||||
static int vi_destroy(struct vimage *);
|
||||
static struct vimage *vimage_get_next(struct vimage *, struct vimage *, int);
|
||||
static void vimage_relative_name(struct vimage *, struct vimage *,
|
||||
char *, int);
|
||||
|
||||
#define VNET_LIST_WLOCK() \
|
||||
mtx_lock(&vnet_list_refc_mtx); \
|
||||
while (vnet_list_refc != 0) \
|
||||
@ -77,82 +66,45 @@ static void vimage_relative_name(struct vimage *, struct vimage *,
|
||||
#define VNET_LIST_WUNLOCK() \
|
||||
mtx_unlock(&vnet_list_refc_mtx);
|
||||
|
||||
struct vimage_list_head vimage_head;
|
||||
struct vnet_list_head vnet_head;
|
||||
struct vprocg_list_head vprocg_head;
|
||||
struct vprocg vprocg_0;
|
||||
|
||||
struct cv vnet_list_condvar;
|
||||
struct mtx vnet_list_refc_mtx;
|
||||
int vnet_list_refc = 0;
|
||||
|
||||
static u_int last_vi_id = 0;
|
||||
static u_int last_vprocg_id = 0;
|
||||
|
||||
struct vnet *vnet0;
|
||||
|
||||
|
||||
/*
|
||||
* Move an ifnet to or from another vnet, specified by the jail id. If a
|
||||
* vi_req is passed in, it is used to find the interface and a vimage
|
||||
* containing the vnet (a vimage name of ".." stands for the parent vnet).
|
||||
* Move an ifnet to or from another vnet, specified by the jail id.
|
||||
*/
|
||||
int
|
||||
vi_if_move(struct thread *td, struct ifnet *ifp, char *ifname, int jid,
|
||||
struct vi_req *vi_req)
|
||||
vi_if_move(struct thread *td, struct ifnet *ifp, char *ifname, int jid)
|
||||
{
|
||||
struct ifnet *t_ifp;
|
||||
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);
|
||||
|
||||
/* Find the target vnet. */
|
||||
my_vip = TD_TO_VIMAGE(td);
|
||||
if (strcmp(vi_req->vi_name, "..") == 0) {
|
||||
if (IS_DEFAULT_VIMAGE(my_vip))
|
||||
return (ENXIO);
|
||||
new_vnet = my_vip->vi_parent->v_net;
|
||||
} else {
|
||||
new_vip = vimage_by_name(my_vip, vi_req->vi_name);
|
||||
if (new_vip == NULL)
|
||||
return (ENXIO);
|
||||
new_vnet = new_vip->v_net;
|
||||
}
|
||||
|
||||
/* Try to find the target ifnet by name. */
|
||||
ifname = vi_req->vi_if_xname;
|
||||
ifp = ifunit(ifname);
|
||||
if (ifp == NULL)
|
||||
return (ENXIO);
|
||||
sx_slock(&allprison_lock);
|
||||
pr = prison_find_child(td->td_ucred->cr_prison, jid);
|
||||
sx_sunlock(&allprison_lock);
|
||||
if (pr == NULL)
|
||||
return (ENXIO);
|
||||
prison_hold_locked(pr);
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
if (ifp != NULL) {
|
||||
/* SIOCSIFVNET */
|
||||
new_vnet = pr->pr_vnet;
|
||||
} else {
|
||||
sx_slock(&allprison_lock);
|
||||
pr = prison_find_child(td->td_ucred->cr_prison, jid);
|
||||
sx_sunlock(&allprison_lock);
|
||||
if (pr == NULL)
|
||||
/* SIOCSIFRVNET */
|
||||
new_vnet = TD_TO_VNET(td);
|
||||
CURVNET_SET(pr->pr_vnet);
|
||||
ifp = ifunit(ifname);
|
||||
CURVNET_RESTORE();
|
||||
if (ifp == NULL) {
|
||||
prison_free(pr);
|
||||
return (ENXIO);
|
||||
prison_hold_locked(pr);
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
if (ifp != NULL) {
|
||||
/* SIOCSIFVNET */
|
||||
new_vnet = pr->pr_vnet;
|
||||
} else {
|
||||
/* SIOCSIFRVNET */
|
||||
new_vnet = TD_TO_VNET(td);
|
||||
CURVNET_SET(pr->pr_vnet);
|
||||
ifp = ifunit(ifname);
|
||||
CURVNET_RESTORE();
|
||||
if (ifp == NULL) {
|
||||
prison_free(pr);
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,215 +127,10 @@ vi_if_move(struct thread *td, struct ifnet *ifp, char *ifname, int jid,
|
||||
sprintf(ifname, "%s", ifp->if_xname);
|
||||
}
|
||||
}
|
||||
if (pr != NULL)
|
||||
prison_free(pr);
|
||||
prison_free(pr);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interim userspace interface - will be replaced by jail soon.
|
||||
*/
|
||||
|
||||
int
|
||||
vi_td_ioctl(u_long cmd, struct vi_req *vi_req, struct thread *td)
|
||||
{
|
||||
int error = 0;
|
||||
struct vimage *vip = TD_TO_VIMAGE(td);
|
||||
struct vimage *vip_r = NULL;
|
||||
|
||||
/* Check for API / ABI version mismatch. */
|
||||
if (vi_req->vi_api_cookie != VI_API_COOKIE)
|
||||
return (EDOOFUS);
|
||||
|
||||
error = priv_check(td, PRIV_REBOOT); /* XXX temp. priv abuse */
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
vip_r = vimage_by_name(vip, vi_req->vi_name);
|
||||
if (vip_r == NULL && !(vi_req->vi_req_action & VI_CREATE))
|
||||
return (ESRCH);
|
||||
if (vip_r != NULL && vi_req->vi_req_action & VI_CREATE)
|
||||
return (EADDRINUSE);
|
||||
if (vi_req->vi_req_action == VI_GETNEXT) {
|
||||
vip_r = vimage_get_next(vip, vip_r, 0);
|
||||
if (vip_r == NULL)
|
||||
return (ESRCH);
|
||||
}
|
||||
if (vi_req->vi_req_action == VI_GETNEXT_RECURSE) {
|
||||
vip_r = vimage_get_next(vip, vip_r, 1);
|
||||
if (vip_r == NULL)
|
||||
return (ESRCH);
|
||||
}
|
||||
|
||||
if (vip_r && !vi_child_of(vip, vip_r) && /* XXX delete the rest? */
|
||||
vi_req->vi_req_action != VI_GET &&
|
||||
vi_req->vi_req_action != VI_GETNEXT)
|
||||
return (EPERM);
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case SIOCGPVIMAGE:
|
||||
vimage_relative_name(vip, vip_r, vi_req->vi_name,
|
||||
sizeof (vi_req->vi_name));
|
||||
vi_req->vi_proc_count = vip_r->v_procg->nprocs;
|
||||
vi_req->vi_if_count = vip_r->v_net->ifcnt;
|
||||
vi_req->vi_sock_count = vip_r->v_net->sockcnt;
|
||||
break;
|
||||
|
||||
case SIOCSPVIMAGE:
|
||||
if (vi_req->vi_req_action == VI_DESTROY) {
|
||||
error = vi_destroy(vip_r);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vi_req->vi_req_action == VI_SWITCHTO) {
|
||||
struct proc *p = td->td_proc;
|
||||
struct ucred *oldcred, *newcred;
|
||||
|
||||
/*
|
||||
* XXX priv_check()?
|
||||
* XXX allow only a single td per proc here?
|
||||
*/
|
||||
newcred = crget();
|
||||
PROC_LOCK(p);
|
||||
oldcred = p->p_ucred;
|
||||
setsugid(p);
|
||||
crcopy(newcred, oldcred);
|
||||
refcount_release(&newcred->cr_vimage->vi_ucredrefc);
|
||||
newcred->cr_vimage = vip_r;
|
||||
refcount_acquire(&newcred->cr_vimage->vi_ucredrefc);
|
||||
p->p_ucred = newcred;
|
||||
PROC_UNLOCK(p);
|
||||
sx_xlock(&allproc_lock);
|
||||
oldcred->cr_vimage->v_procg->nprocs--;
|
||||
refcount_release(&oldcred->cr_vimage->vi_ucredrefc);
|
||||
P_TO_VPROCG(p)->nprocs++;
|
||||
sx_xunlock(&allproc_lock);
|
||||
crfree(oldcred);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vi_req->vi_req_action & VI_CREATE) {
|
||||
char *dotpos;
|
||||
|
||||
dotpos = strrchr(vi_req->vi_name, '.');
|
||||
if (dotpos != NULL) {
|
||||
*dotpos = 0;
|
||||
vip = vimage_by_name(vip, vi_req->vi_name);
|
||||
if (vip == NULL)
|
||||
return (ESRCH);
|
||||
dotpos++;
|
||||
vip_r = vi_alloc(vip, dotpos);
|
||||
} else
|
||||
vip_r = vi_alloc(vip, vi_req->vi_name);
|
||||
if (vip_r == NULL)
|
||||
return (ENOMEM);
|
||||
}
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
vi_child_of(struct vimage *parent, struct vimage *child)
|
||||
{
|
||||
|
||||
if (child == parent)
|
||||
return (0);
|
||||
for (; child; child = child->vi_parent)
|
||||
if (child == parent)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct vimage *
|
||||
vimage_by_name(struct vimage *top, char *name)
|
||||
{
|
||||
struct vimage *vip;
|
||||
char *next_name;
|
||||
int namelen;
|
||||
|
||||
next_name = strchr(name, '.');
|
||||
if (next_name != NULL) {
|
||||
namelen = next_name - name;
|
||||
next_name++;
|
||||
if (namelen == 0) {
|
||||
if (strlen(next_name) == 0)
|
||||
return (top); /* '.' == this vimage */
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
} else
|
||||
namelen = strlen(name);
|
||||
if (namelen == 0)
|
||||
return (NULL);
|
||||
LIST_FOREACH(vip, &top->vi_child_head, vi_sibling) {
|
||||
if (strlen(vip->vi_name) == namelen &&
|
||||
strncmp(name, vip->vi_name, namelen) == 0) {
|
||||
if (next_name != NULL)
|
||||
return (vimage_by_name(vip, next_name));
|
||||
else
|
||||
return (vip);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
vimage_relative_name(struct vimage *top, struct vimage *where,
|
||||
char *buffer, int bufflen)
|
||||
{
|
||||
int used = 1;
|
||||
|
||||
if (where == top) {
|
||||
sprintf(buffer, ".");
|
||||
return;
|
||||
} else
|
||||
*buffer = 0;
|
||||
|
||||
do {
|
||||
int namelen = strlen(where->vi_name);
|
||||
|
||||
if (namelen + used + 1 >= bufflen)
|
||||
panic("buffer overflow");
|
||||
|
||||
if (used > 1) {
|
||||
bcopy(buffer, &buffer[namelen + 1], used);
|
||||
buffer[namelen] = '.';
|
||||
used++;
|
||||
} else
|
||||
bcopy(buffer, &buffer[namelen], used);
|
||||
bcopy(where->vi_name, buffer, namelen);
|
||||
used += namelen;
|
||||
where = where->vi_parent;
|
||||
} while (where != top);
|
||||
}
|
||||
|
||||
static struct vimage *
|
||||
vimage_get_next(struct vimage *top, struct vimage *where, int recurse)
|
||||
{
|
||||
struct vimage *next;
|
||||
|
||||
if (recurse) {
|
||||
/* Try to go deeper in the hierarchy */
|
||||
next = LIST_FIRST(&where->vi_child_head);
|
||||
if (next != NULL)
|
||||
return (next);
|
||||
}
|
||||
|
||||
do {
|
||||
/* Try to find next sibling */
|
||||
next = LIST_NEXT(where, vi_sibling);
|
||||
if (!recurse || next != NULL)
|
||||
return (next);
|
||||
|
||||
/* Nothing left on this level, go one level up */
|
||||
where = where->vi_parent;
|
||||
} while (where != top->vi_parent);
|
||||
|
||||
/* Nothing left to be visited, we are done */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Kernel interfaces and handlers.
|
||||
@ -409,7 +156,7 @@ vnet_mod_register_multi(const struct vnet_modinfo *vmi, void *iarg,
|
||||
if (vml_iter != NULL)
|
||||
panic("registering an already registered vnet module: %s",
|
||||
vml_iter->vml_modinfo->vmi_name);
|
||||
vml = malloc(sizeof(struct vnet_modlink), M_VIMAGE, M_NOWAIT);
|
||||
vml = malloc(sizeof(struct vnet_modlink), M_VNET, M_NOWAIT);
|
||||
|
||||
/*
|
||||
* XXX we support only statically assigned module IDs at the time.
|
||||
@ -513,7 +260,7 @@ vnet_mod_deregister_multi(const struct vnet_modinfo *vmi, void *iarg,
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&vnet_modlink_head, vml, vml_mod_le);
|
||||
free(vml, M_VIMAGE);
|
||||
free(vml, M_VNET);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -625,75 +372,6 @@ vnet_foreach(void (*vnet_foreach_fn)(struct vnet *, void *), void *arg)
|
||||
VNET_LIST_RUNLOCK();
|
||||
}
|
||||
|
||||
static struct vimage *
|
||||
vi_alloc(struct vimage *parent, char *name)
|
||||
{
|
||||
struct vimage *vip;
|
||||
struct vprocg *vprocg;
|
||||
|
||||
vip = malloc(sizeof(struct vimage), M_VIMAGE, M_NOWAIT | M_ZERO);
|
||||
if (vip == NULL)
|
||||
panic("vi_alloc: malloc failed for vimage \"%s\"\n", name);
|
||||
vip->vi_id = last_vi_id++;
|
||||
LIST_INIT(&vip->vi_child_head);
|
||||
sprintf(vip->vi_name, "%s", name);
|
||||
vip->vi_parent = parent;
|
||||
/* XXX locking */
|
||||
if (parent != NULL)
|
||||
LIST_INSERT_HEAD(&parent->vi_child_head, vip, vi_sibling);
|
||||
else if (!LIST_EMPTY(&vimage_head))
|
||||
panic("there can be only one default vimage!");
|
||||
LIST_INSERT_HEAD(&vimage_head, vip, vi_le);
|
||||
|
||||
vip->v_net = vnet_alloc();
|
||||
|
||||
vprocg = malloc(sizeof(struct vprocg), M_VPROCG, M_NOWAIT | M_ZERO);
|
||||
if (vprocg == NULL)
|
||||
panic("vi_alloc: malloc failed for vprocg \"%s\"\n", name);
|
||||
vip->v_procg = vprocg;
|
||||
vprocg->vprocg_id = last_vprocg_id++;
|
||||
|
||||
/* XXX locking */
|
||||
LIST_INSERT_HEAD(&vprocg_head, vprocg, vprocg_le);
|
||||
|
||||
return (vip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy a vnet - unlink all linked lists, hashtables etc., free all
|
||||
* the memory, stop all the timers...
|
||||
*/
|
||||
static int
|
||||
vi_destroy(struct vimage *vip)
|
||||
{
|
||||
struct vprocg *vprocg = vip->v_procg;
|
||||
|
||||
/* XXX Beware of races -> more locking to be done... */
|
||||
if (!LIST_EMPTY(&vip->vi_child_head))
|
||||
return (EBUSY);
|
||||
|
||||
if (vprocg->nprocs != 0)
|
||||
return (EBUSY);
|
||||
|
||||
#ifdef INVARIANTS
|
||||
if (vip->vi_ucredrefc != 0)
|
||||
printf("vi_destroy: %s ucredrefc %d\n",
|
||||
vip->vi_name, vip->vi_ucredrefc);
|
||||
#endif
|
||||
|
||||
/* Point with no return - cleanup MUST succeed! */
|
||||
vnet_destroy(vip->v_net);
|
||||
|
||||
LIST_REMOVE(vip, vi_le);
|
||||
LIST_REMOVE(vip, vi_sibling);
|
||||
LIST_REMOVE(vprocg, vprocg_le);
|
||||
|
||||
free(vprocg, M_VPROCG);
|
||||
free(vip, M_VIMAGE);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vi_init(void *unused)
|
||||
{
|
||||
@ -701,22 +379,17 @@ vi_init(void *unused)
|
||||
TAILQ_INIT(&vnet_modlink_head);
|
||||
TAILQ_INIT(&vnet_modpending_head);
|
||||
|
||||
LIST_INIT(&vimage_head);
|
||||
LIST_INIT(&vprocg_head);
|
||||
LIST_INIT(&vnet_head);
|
||||
|
||||
mtx_init(&vnet_list_refc_mtx, "vnet_list_refc_mtx", NULL, MTX_DEF);
|
||||
cv_init(&vnet_list_condvar, "vnet_list_condvar");
|
||||
|
||||
/* Default image has no parent and no name. */
|
||||
vi_alloc(NULL, "");
|
||||
|
||||
/*
|
||||
* We MUST clear curvnet in vi_init_done() before going SMP,
|
||||
* otherwise CURVNET_SET() macros would scream about unnecessary
|
||||
* curvnet recursions.
|
||||
*/
|
||||
curvnet = prison0.pr_vnet = vnet0 = LIST_FIRST(&vnet_head);
|
||||
curvnet = prison0.pr_vnet = vnet0 = vnet_alloc();
|
||||
}
|
||||
|
||||
static void
|
||||
|
17
sys/net/if.c
17
sys/net/if.c
@ -2008,7 +2008,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
|
||||
error = priv_check(td, PRIV_NET_SETIFVNET);
|
||||
if (error)
|
||||
return (error);
|
||||
error = vi_if_move(td, ifp, ifr->ifr_name, ifr->ifr_jid, NULL);
|
||||
error = vi_if_move(td, ifp, ifr->ifr_name, ifr->ifr_jid);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -2202,20 +2202,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
|
||||
error = priv_check(td, PRIV_NET_SETIFVNET);
|
||||
if (error)
|
||||
return (error);
|
||||
return (vi_if_move(td, NULL, ifr->ifr_name, ifr->ifr_jid,
|
||||
NULL));
|
||||
/*
|
||||
* XXX vnet creation will be implemented through the new jail
|
||||
* framework - this is just a temporary hack for testing the
|
||||
* vnet create / destroy mechanisms.
|
||||
*/
|
||||
case SIOCSIFVIMAGE:
|
||||
error = vi_if_move(td, NULL, NULL, 0, (struct vi_req *) data);
|
||||
return (error);
|
||||
case SIOCSPVIMAGE:
|
||||
case SIOCGPVIMAGE:
|
||||
error = vi_td_ioctl(cmd, (struct vi_req *) data, td);
|
||||
return (error);
|
||||
return (vi_if_move(td, NULL, ifr->ifr_name, ifr->ifr_jid));
|
||||
#endif
|
||||
case SIOCIFCREATE:
|
||||
case SIOCIFCREATE2:
|
||||
|
@ -111,10 +111,6 @@
|
||||
#define SIOCSIFVNET _IOWR('i', 90, struct ifreq) /* move IF jail/vnet */
|
||||
#define SIOCSIFRVNET _IOWR('i', 91, struct ifreq) /* reclaim vnet IF */
|
||||
|
||||
#define SIOCSPVIMAGE _IOW('i', 101, struct vi_req) /* set proc vimage */
|
||||
#define SIOCGPVIMAGE _IOWR('i', 102, struct vi_req) /* get proc vimage */
|
||||
#define SIOCSIFVIMAGE _IOWR('i', 103, struct vi_req) /* set ifc vi/net */
|
||||
|
||||
#define SIOCSDRVSPEC _IOW('i', 123, struct ifdrv) /* set driver-specific
|
||||
parameters */
|
||||
#define SIOCGDRVSPEC _IOWR('i', 123, struct ifdrv) /* get driver-specific
|
||||
|
@ -54,9 +54,9 @@ struct ucred {
|
||||
struct uidinfo *cr_uidinfo; /* per euid resource consumption */
|
||||
struct uidinfo *cr_ruidinfo; /* per ruid resource consumption */
|
||||
struct prison *cr_prison; /* jail(2) */
|
||||
struct vimage *cr_vimage; /* vimage */
|
||||
void *cr_pspare; /* general use */
|
||||
u_int cr_flags; /* credential flags */
|
||||
void *cr_pspare[2]; /* general use 2 */
|
||||
void *cr_pspare2[2]; /* general use 2 */
|
||||
#define cr_endcopy cr_label
|
||||
struct label *cr_label; /* MAC label */
|
||||
struct auditinfo_addr cr_audit; /* Audit properties. */
|
||||
|
@ -36,42 +36,14 @@
|
||||
#include <sys/proc.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
/* Interim userspace API. */
|
||||
struct vi_req {
|
||||
int vi_api_cookie; /* Catch API mismatch. */
|
||||
int vi_req_action; /* What to do with this request? */
|
||||
u_short vi_proc_count; /* Current number of processes. */
|
||||
int vi_if_count; /* Current number of ifnets. */
|
||||
int vi_sock_count;
|
||||
char vi_name[MAXPATHLEN];
|
||||
char vi_if_xname[MAXPATHLEN]; /* XXX should be IFNAMSIZ */
|
||||
};
|
||||
|
||||
#define VI_CREATE 0x00000001
|
||||
#define VI_DESTROY 0x00000002
|
||||
#define VI_SWITCHTO 0x00000008
|
||||
#define VI_IFACE 0x00000010
|
||||
#define VI_GET 0x00000100
|
||||
#define VI_GETNEXT 0x00000200
|
||||
#define VI_GETNEXT_RECURSE 0x00000300
|
||||
|
||||
#define VI_API_VERSION 1 /* Bump on struct changes. */
|
||||
|
||||
#define VI_API_COOKIE ((sizeof(struct vi_req) << 16) | VI_API_VERSION)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#ifdef INVARIANTS
|
||||
#define VNET_DEBUG
|
||||
#endif
|
||||
|
||||
struct vimage;
|
||||
struct vprocg;
|
||||
struct vnet;
|
||||
struct vi_req;
|
||||
struct ifnet;
|
||||
struct kld_sym_lookup;
|
||||
struct thread;
|
||||
|
||||
typedef int vnet_attach_fn(const void *);
|
||||
typedef int vnet_detach_fn(const void *);
|
||||
@ -128,16 +100,7 @@ struct vnet_modlink {
|
||||
#define VNET_MOD_DYNAMIC_START 32
|
||||
#define VNET_MOD_MAX 64
|
||||
|
||||
/* Major module IDs for vimage sysctl virtualization. */
|
||||
#define V_GLOBAL 0 /* global variable - no indirection */
|
||||
#define V_NET 1
|
||||
#define V_PROCG 2
|
||||
|
||||
int vi_td_ioctl(u_long, struct vi_req *, struct thread *);
|
||||
int vi_if_move(struct thread *, struct ifnet *, char *, int,
|
||||
struct vi_req *);
|
||||
int vi_child_of(struct vimage *, struct vimage *);
|
||||
struct vimage *vimage_by_name(struct vimage *, char *);
|
||||
int vi_if_move(struct thread *, struct ifnet *, char *, int);
|
||||
void vnet_mod_register(const struct vnet_modinfo *);
|
||||
void vnet_mod_register_multi(const struct vnet_modinfo *, void *, char *);
|
||||
void vnet_mod_deregister(const struct vnet_modinfo *);
|
||||
@ -149,18 +112,6 @@ void vnet_foreach(void (*vnet_foreach_fn)(struct vnet *, void *),
|
||||
|
||||
#endif /* VIMAGE */
|
||||
|
||||
struct vimage {
|
||||
LIST_ENTRY(vimage) vi_le; /* all vimage list */
|
||||
LIST_ENTRY(vimage) vi_sibling; /* vimages with same parent */
|
||||
LIST_HEAD(, vimage) vi_child_head; /* direct offspring list */
|
||||
struct vimage *vi_parent; /* ptr to parent vimage */
|
||||
u_int vi_id; /* ID num */
|
||||
volatile u_int vi_ucredrefc; /* # of ucreds pointing to us */
|
||||
char vi_name[MAXHOSTNAMELEN];
|
||||
struct vnet *v_net;
|
||||
struct vprocg *v_procg;
|
||||
};
|
||||
|
||||
struct vnet {
|
||||
LIST_ENTRY(vnet) vnet_le; /* all vnets list */
|
||||
u_int vnet_magic_n;
|
||||
@ -170,19 +121,6 @@ struct vnet {
|
||||
uintptr_t vnet_data_base;
|
||||
};
|
||||
|
||||
struct vprocg {
|
||||
LIST_ENTRY(vprocg) vprocg_le;
|
||||
u_int vprocg_id; /* ID num */
|
||||
u_int nprocs;
|
||||
};
|
||||
|
||||
#ifdef VIMAGE
|
||||
LIST_HEAD(vimage_list_head, vimage);
|
||||
extern struct vimage_list_head vimage_head;
|
||||
#else /* !VIMAGE */
|
||||
extern struct vprocg vprocg_0;
|
||||
#endif /* VIMAGE */
|
||||
|
||||
#define curvnet curthread->td_vnet
|
||||
|
||||
#define VNET_MAGIC_N 0x3e0d8f29
|
||||
@ -249,39 +187,19 @@ extern struct vnet *vnet0;
|
||||
#endif
|
||||
|
||||
#ifdef VIMAGE
|
||||
LIST_HEAD(vprocg_list_head, vprocg);
|
||||
extern struct vprocg_list_head vprocg_head;
|
||||
#define INIT_VPROCG(arg) struct vprocg *vprocg = (arg);
|
||||
#else
|
||||
#define INIT_VPROCG(arg)
|
||||
#endif
|
||||
|
||||
#ifdef VIMAGE
|
||||
#define IS_DEFAULT_VIMAGE(arg) ((arg)->vi_id == 0)
|
||||
#define IS_DEFAULT_VNET(arg) ((arg) == vnet0)
|
||||
#else
|
||||
#define IS_DEFAULT_VIMAGE(arg) 1
|
||||
#define IS_DEFAULT_VNET(arg) 1
|
||||
#endif
|
||||
|
||||
#ifdef VIMAGE
|
||||
#define CRED_TO_VNET(cr) \
|
||||
(IS_DEFAULT_VIMAGE((cr)->cr_vimage) ? (cr)->cr_prison->pr_vnet \
|
||||
: (cr)->cr_vimage->v_net)
|
||||
#define TD_TO_VIMAGE(td) (td)->td_ucred->cr_vimage
|
||||
#define CRED_TO_VNET(cr) (cr)->cr_prison->pr_vnet
|
||||
#define TD_TO_VNET(td) CRED_TO_VNET((td)->td_ucred)
|
||||
#define TD_TO_VPROCG(td) (td)->td_ucred->cr_vimage->v_procg
|
||||
#define P_TO_VIMAGE(p) (p)->p_ucred->cr_vimage
|
||||
#define P_TO_VNET(p) CRED_TO_VNET((p)->p_ucred)
|
||||
#define P_TO_VPROCG(p) (p)->p_ucred->cr_vimage->v_procg
|
||||
#else /* !VIMAGE */
|
||||
#define CRED_TO_VNET(cr) NULL
|
||||
#define TD_TO_VIMAGE(td) NULL
|
||||
#define TD_TO_VNET(td) NULL
|
||||
#define P_TO_VIMAGE(p) NULL
|
||||
#define P_TO_VNET(p) NULL
|
||||
#define TD_TO_VPROCG(td) &vprocg_0
|
||||
#define P_TO_VPROCG(p) &vprocg_0
|
||||
#endif /* VIMAGE */
|
||||
|
||||
/* Non-VIMAGE null-macros */
|
||||
|
@ -1,6 +1,8 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= vimage
|
||||
LDADD= -ljail
|
||||
DPADD= ${LIBJAIL}
|
||||
|
||||
WARNS?= 2
|
||||
CFLAGS+= -I../../../sys
|
||||
|
@ -27,122 +27,120 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/vimage.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <jail.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void
|
||||
vi_print(struct vi_req *vi_req)
|
||||
{
|
||||
#define VI_CREATE 0x00000001
|
||||
#define VI_DESTROY 0x00000002
|
||||
#define VI_SWITCHTO 0x00000008
|
||||
#define VI_IFACE 0x00000010
|
||||
#define VI_GET 0x00000100
|
||||
#define VI_GETNEXT 0x00000200
|
||||
|
||||
printf("\"%s\":\n", vi_req->vi_name);
|
||||
printf(" %d sockets, %d ifnets, %d processes\n",
|
||||
vi_req->vi_sock_count, vi_req->vi_if_count, vi_req->vi_proc_count);
|
||||
}
|
||||
static int getjail(char *name, int lastjid, int *vnet);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
char *shell;
|
||||
int cmd = VI_SWITCHTO;
|
||||
struct vi_req vi_req;
|
||||
int cmd;
|
||||
int jid, vnet;
|
||||
struct ifreq ifreq;
|
||||
char name[MAXHOSTNAMELEN];
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s == -1)
|
||||
goto abort;
|
||||
switch (argc) {
|
||||
|
||||
bzero(&vi_req, sizeof(vi_req));
|
||||
strcpy(vi_req.vi_name, "."); /* . = this vimage. */
|
||||
case 1:
|
||||
cmd = 0;
|
||||
break;
|
||||
|
||||
if (argc == 1)
|
||||
cmd = VI_GET;
|
||||
case 2:
|
||||
if (strcmp(argv[1], "-l") == 0)
|
||||
cmd = VI_GETNEXT;
|
||||
else if (strcmp(argv[1], "-lr") == 0)
|
||||
cmd = VI_GETNEXT;
|
||||
else {
|
||||
strcpy(name, argv[1]);
|
||||
cmd = VI_SWITCHTO;
|
||||
}
|
||||
break;
|
||||
|
||||
if (argc == 2 && strcmp(argv[1], "-l") == 0)
|
||||
cmd = VI_GETNEXT;
|
||||
|
||||
if (argc == 2 && strcmp(argv[1], "-lr") == 0)
|
||||
cmd = VI_GETNEXT_RECURSE;
|
||||
|
||||
if (argc == 3) {
|
||||
strcpy(vi_req.vi_name, argv[2]);
|
||||
case 3:
|
||||
strcpy(name, argv[2]);
|
||||
if (strcmp(argv[1], "-l") == 0)
|
||||
cmd = VI_GET;
|
||||
if (strcmp(argv[1], "-c") == 0)
|
||||
cmd = VI_CREATE;
|
||||
if (strcmp(argv[1], "-d") == 0)
|
||||
cmd = VI_DESTROY;
|
||||
}
|
||||
break;
|
||||
|
||||
if (argc >= 3) {
|
||||
strcpy(vi_req.vi_name, argv[2]);
|
||||
default:
|
||||
strcpy(name, argv[2]);
|
||||
if (strcmp(argv[1], "-c") == 0)
|
||||
cmd = VI_CREATE;
|
||||
if (strcmp(argv[1], "-i") == 0)
|
||||
cmd = VI_IFACE;
|
||||
}
|
||||
|
||||
vi_req.vi_api_cookie = VI_API_COOKIE;
|
||||
vi_req.vi_req_action = cmd;
|
||||
switch (cmd) {
|
||||
|
||||
case VI_GET:
|
||||
if (ioctl(s, SIOCGPVIMAGE, (caddr_t)&vi_req) < 0)
|
||||
jid = getjail(name, -1, &vnet);
|
||||
if (jid < 0)
|
||||
goto abort;
|
||||
if (argc == 1)
|
||||
printf("%s\n", vi_req.vi_name);
|
||||
else
|
||||
vi_print(&vi_req);
|
||||
printf("%d: %s%s\n", jid, name, vnet ? "" : " (no vnet)");
|
||||
exit(0);
|
||||
|
||||
case VI_GETNEXT:
|
||||
case VI_GETNEXT_RECURSE:
|
||||
vi_req.vi_req_action = VI_GET;
|
||||
if (ioctl(s, SIOCGPVIMAGE, (caddr_t)&vi_req) < 0)
|
||||
goto abort;
|
||||
vi_print(&vi_req);
|
||||
vi_req.vi_req_action = VI_GETNEXT_RECURSE;
|
||||
while (ioctl(s, SIOCGPVIMAGE, (caddr_t)&vi_req) == 0) {
|
||||
vi_print(&vi_req);
|
||||
vi_req.vi_req_action = cmd;
|
||||
}
|
||||
jid = 0;
|
||||
while ((jid = getjail(name, jid, &vnet)) > 0)
|
||||
printf("%d: %s%s\n", jid, name,
|
||||
vnet ? "" : " (no vnet)");
|
||||
exit(0);
|
||||
|
||||
case VI_IFACE:
|
||||
strncpy(vi_req.vi_if_xname, argv[3],
|
||||
sizeof(vi_req.vi_if_xname));
|
||||
if (ioctl(s, SIOCSIFVIMAGE, (caddr_t)&vi_req) < 0)
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s == -1)
|
||||
goto abort;
|
||||
printf("%s@%s\n", vi_req.vi_if_xname, vi_req.vi_name);
|
||||
jid = jail_getid(name);
|
||||
if (jid < 0)
|
||||
goto abort;
|
||||
ifreq.ifr_jid = jid;
|
||||
strncpy(ifreq.ifr_name, argv[3], sizeof(ifreq.ifr_name));
|
||||
if (ioctl(s, SIOCSIFVNET, (caddr_t)&ifreq) < 0)
|
||||
goto abort;
|
||||
printf("%s@%s\n", ifreq.ifr_name, name);
|
||||
exit(0);
|
||||
|
||||
case VI_CREATE:
|
||||
if (ioctl(s, SIOCSPVIMAGE, (caddr_t)&vi_req) < 0)
|
||||
if (jail_setv(JAIL_CREATE, "name", name, "vnet", NULL,
|
||||
"host", NULL, "persist", NULL, NULL) < 0)
|
||||
goto abort;
|
||||
exit(0);
|
||||
|
||||
case VI_SWITCHTO:
|
||||
strcpy(vi_req.vi_name, argv[1]);
|
||||
if (ioctl(s, SIOCSPVIMAGE, (caddr_t)&vi_req) < 0)
|
||||
jid = jail_getid(name);
|
||||
if (jid < 0)
|
||||
goto abort;
|
||||
|
||||
vi_req.vi_req_action = VI_GET;
|
||||
strcpy(vi_req.vi_name, ".");
|
||||
if (ioctl(s, SIOCGPVIMAGE, (caddr_t)&vi_req) < 0) {
|
||||
printf("XXX this should have not happened!\n");
|
||||
if (jail_attach(jid) < 0)
|
||||
goto abort;
|
||||
}
|
||||
close(s);
|
||||
|
||||
if (argc == 2) {
|
||||
printf("Switched to vimage %s\n", argv[1]);
|
||||
printf("Switched to jail %s\n", argv[1]);
|
||||
if ((shell = getenv("SHELL")) == NULL)
|
||||
execlp("/bin/sh", argv[0], NULL);
|
||||
else
|
||||
@ -152,7 +150,10 @@ main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case VI_DESTROY:
|
||||
if (ioctl(s, SIOCSPVIMAGE, (caddr_t)&vi_req) < 0)
|
||||
jid = jail_getid(name);
|
||||
if (jid < 0)
|
||||
goto abort;
|
||||
if (jail_remove(jid) < 0)
|
||||
goto abort;
|
||||
exit(0);
|
||||
|
||||
@ -163,6 +164,35 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
abort:
|
||||
perror("Error");
|
||||
if (jail_errmsg[0])
|
||||
fprintf(stderr, "Error: %s\n", jail_errmsg);
|
||||
else
|
||||
perror("Error");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
getjail(char *name, int lastjid, int *vnet)
|
||||
{
|
||||
struct jailparam params[3];
|
||||
int jid;
|
||||
|
||||
if (lastjid < 0) {
|
||||
jid = jail_getid(name);
|
||||
if (jid < 0)
|
||||
return (jid);
|
||||
jailparam_init(¶ms[0], "jid");
|
||||
jailparam_import_raw(¶ms[0], &jid, sizeof jid);
|
||||
} else {
|
||||
jailparam_init(¶ms[0], "lastjid");
|
||||
jailparam_import_raw(¶ms[0], &lastjid, sizeof lastjid);
|
||||
}
|
||||
jailparam_init(¶ms[1], "name");
|
||||
jailparam_import_raw(¶ms[1], name, MAXHOSTNAMELEN);
|
||||
name[0] = 0;
|
||||
jailparam_init(¶ms[2], "vnet");
|
||||
jailparam_import_raw(¶ms[2], vnet, sizeof(*vnet));
|
||||
jid = jailparam_get(params, 3, 0);
|
||||
jailparam_free(params, 3);
|
||||
return (jid);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user