Introduce a new virtualization container, provisionally named vprocg, to hold

virtualized instances of hostname and domainname, as well as a new top-level
virtualization struct vimage, which holds pointers to struct vnet and struct
vprocg.  Struct vprocg is likely to become replaced in the near future with
a new jail management API import.

As a consequence of this change, change struct ucred to point to a struct
vimage, instead of directly pointing to a vnet.

Merge vnet / vimage / ucred refcounting infrastructure from p4 / vimage
branch.

Permit kldload / kldunload operations to be executed only from the default
vimage context.

This change should have no functional impact on nooptions VIMAGE kernel
builds.

Reviewed by:	bz
Approved by:	julian (mentor)
This commit is contained in:
Marko Zec 2009-05-08 14:11:06 +00:00
parent fcec7b25b8
commit 29b02909eb
17 changed files with 166 additions and 33 deletions

View File

@ -32,8 +32,10 @@
#include <sys/cpuvar.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/misc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/vimage.h>
cpu_core_t cpu_core[MAXCPU];
kmutex_t cpu_lock;
@ -81,6 +83,7 @@ opensolaris_modevent(module_t mod __unused, int type, void *data __unused)
switch (type) {
case MOD_LOAD:
utsname.nodename = G_hostname;
break;
case MOD_UNLOAD:

View File

@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$");
char hw_serial[11] = "0";
struct opensolaris_utsname utsname = {
.nodename = hostname
.nodename = "unset"
};
int

View File

@ -412,6 +412,7 @@ svr4_sys_systeminfo(td, uap)
struct thread *td;
struct svr4_sys_systeminfo_args *uap;
{
INIT_VPROCG(TD_TO_VPROCG(td));
char *str = NULL;
int error = 0;
register_t *retval = td->td_retval;

View File

@ -174,6 +174,7 @@ ibcs2_setipdomainname(td, uap)
struct thread *td;
struct setipdomainname_args *uap;
{
INIT_VPROCG(TD_TO_VPROCG(td));
char hname[MAXHOSTNAMELEN], *ptr;
int error, sctl[2], hlen;

View File

@ -454,7 +454,10 @@ proc0_init(void *dummy __unused)
p->p_ucred->cr_ruidinfo = uifind(0);
p->p_ucred->cr_prison = NULL; /* Don't jail it. */
#ifdef VIMAGE
p->p_ucred->cr_vnet = LIST_FIRST(&vnet_head);
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);

View File

@ -70,6 +70,7 @@ __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
@ -737,6 +738,7 @@ loop:
nfound++;
PROC_SLOCK(p);
if (p->p_state == PRS_ZOMBIE) {
INIT_VPROCG(P_TO_VPROCG(p));
if (rusage) {
*rusage = p->p_ru;
calcru(p, &rusage->ru_utime, &rusage->ru_stime);
@ -837,6 +839,9 @@ loop:
uma_zfree(proc_zone, p);
sx_xlock(&allproc_lock);
nprocs--;
#ifdef VIMAGE
vprocg->nprocs--;
#endif
sx_xunlock(&allproc_lock);
return (0);
}

View File

@ -350,6 +350,9 @@ norfproc_fail:
* 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

View File

@ -2218,6 +2218,10 @@ prison_check(struct ucred *cred1, struct ucred *cred2)
if (cred2->cr_prison != cred1->cr_prison)
return (ESRCH);
}
#ifdef VIMAGE
if (cred2->cr_vimage->v_procg != cred1->cr_vimage->v_procg)
return (ESRCH);
#endif
return (0);
}

View File

@ -992,6 +992,12 @@ 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's possible that kldloaded module will attach a new ifnet,
* so vnet context must be set when this ocurs.
@ -1063,6 +1069,12 @@ 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);

View File

@ -208,8 +208,9 @@ static char machine_arch[] = MACHINE_ARCH;
SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD,
machine_arch, 0, "System architecture");
/* should become #ifndef VIMAGE */
#ifdef VIMAGE_GLOBALS
char hostname[MAXHOSTNAMELEN];
#endif
/*
* This mutex is used to protect the hostname and domainname variables, and
@ -348,12 +349,14 @@ SYSCTL_PROC(_kern, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RW,
0, 0, sysctl_kern_config, "", "Kernel configuration file");
#endif
/* should become #ifndef VIMAGE */
#ifdef VIMAGE_GLOBALS
char domainname[MAXHOSTNAMELEN]; /* Protected by hostname_mtx. */
#endif
static int
sysctl_domainname(SYSCTL_HANDLER_ARGS)
{
INIT_VPROCG(TD_TO_VPROCG(req->td));
char tmpdomainname[MAXHOSTNAMELEN];
int error;

View File

@ -69,6 +69,7 @@ __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>
@ -1824,6 +1825,11 @@ crfree(struct ucred *cr)
*/
if (jailed(cr))
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
@ -1859,6 +1865,10 @@ crcopy(struct ucred *dest, struct ucred *src)
uihold(dest->cr_ruidinfo);
if (jailed(dest))
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

View File

@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
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;
@ -56,7 +57,13 @@ static int vnet_mod_constructor(struct vnet_modlink *);
static int vnet_mod_destructor(struct vnet_modlink *);
#ifdef VIMAGE
struct vimage_list_head vimage_head;
struct vnet_list_head vnet_head;
struct vprocg_list_head vprocg_head;
#else
#ifndef VIMAGE_GLOBALS
struct vprocg vprocg_0;
#endif
#endif
void
@ -294,6 +301,8 @@ static void
vi_init(void *unused)
{
#ifdef VIMAGE
struct vimage *vip;
struct vprocg *vprocg;
struct vnet *vnet;
#endif
@ -301,13 +310,27 @@ vi_init(void *unused)
TAILQ_INIT(&vnet_modpending_head);
#ifdef VIMAGE
LIST_INIT(&vimage_head);
LIST_INIT(&vprocg_head);
LIST_INIT(&vnet_head);
vip = malloc(sizeof(struct vimage), M_VIMAGE, M_NOWAIT | M_ZERO);
if (vip == NULL)
panic("malloc failed for struct vimage");
LIST_INSERT_HEAD(&vimage_head, vip, vi_le);
vprocg = malloc(sizeof(struct vprocg), M_VPROCG, M_NOWAIT | M_ZERO);
if (vprocg == NULL)
panic("malloc failed for struct vprocg");
vip->v_procg = vprocg;
LIST_INSERT_HEAD(&vprocg_head, vprocg, vprocg_le);
vnet = malloc(sizeof(struct vnet), M_VNET, M_NOWAIT | M_ZERO);
if (vnet == NULL)
panic("vi_alloc: malloc failed");
LIST_INSERT_HEAD(&vnet_head, vnet, vnet_le);
vnet->vnet_magic_n = VNET_MAGIC_N;
vip->v_net = vnet;
/* We MUST clear curvnet in vi_init_done before going SMP. */
curvnet = LIST_FIRST(&vnet_head);

View File

@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/unistd.h>
#include <sys/vimage.h>
#include <sys/vnode.h>
#include <rpc/rpcclnt.h>
@ -1222,12 +1223,12 @@ nlm_init_lock(struct flock *fl, int flags, int svid,
}
mtx_lock(&hostname_mtx);
snprintf(oh_space, 32, "%d@%s", svid, hostname);
snprintf(oh_space, 32, "%d@%s", svid, G_hostname);
mtx_unlock(&hostname_mtx);
oh_len = strlen(oh_space);
memset(lock, 0, sizeof(*lock));
lock->caller_name = hostname;
lock->caller_name = G_hostname;
lock->fh.n_len = fhlen;
lock->fh.n_bytes = fh;
lock->oh.n_len = oh_len;

View File

@ -58,8 +58,10 @@
extern struct mtx hostname_mtx;
extern unsigned long hostid;
extern char hostuuid[64];
#ifdef VIMAGE_GLOBALS
extern char hostname[MAXHOSTNAMELEN];
extern char domainname[MAXHOSTNAMELEN];
#endif
extern char kernelname[MAXPATHLEN];
extern int tick; /* usec per tick (1000000 / hz) */

View File

@ -459,6 +459,10 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
TD_TO_VNET(curthread)->mod_data[oidp->oid_v_mod]; \
arg1 = cp + (size_t) arg1; \
break; \
case V_PROCG: \
cp = (char *) TD_TO_VPROCG(curthread); \
arg1 = cp + (size_t) arg1; \
break; \
default: \
panic("unsupported module id %d", oidp->oid_v_subs); \
} \

View File

@ -55,7 +55,7 @@ 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 vnet *cr_vnet; /* vimage / vnet */
struct vimage *cr_vimage; /* vimage */
void *cr_pspare[2]; /* general use 2 */
#define cr_endcopy cr_label
struct label *cr_label; /* MAC label */

View File

@ -44,13 +44,15 @@
#define VNET_DEBUG
#endif
struct vprocg;
struct vnet;
struct kld_sym_lookup;
typedef int vnet_attach_fn(const void *);
typedef int vnet_detach_fn(const void *);
#ifndef VIMAGE_GLOBALS
struct kld_sym_lookup;
struct vnet_symmap {
char *name;
size_t offset;
@ -111,6 +113,7 @@ struct vnet_modlink {
/* Major module IDs for vimage sysctl virtualization. */
#define V_GLOBAL 0 /* global variable - no indirection */
#define V_NET 1
#define V_PROCG 2
/* Name mappings for minor module IDs in vimage sysctl virtualization. */
#define V_MOD_vnet_net VNET_MOD_NET
@ -121,6 +124,8 @@ struct vnet_modlink {
#define V_MOD_vnet_pf VNET_MOD_PF
#define V_MOD_vnet_gif VNET_MOD_GIF
#define V_MOD_vnet_ipsec VNET_MOD_IPSEC
#define V_MOD_vprocg 0 /* no minor module ids like in vnet */
int vi_symlookup(struct kld_sym_lookup *, char *);
void vnet_mod_register(const struct vnet_modinfo *);
@ -157,21 +162,45 @@ void vnet_mod_deregister_multi(const struct vnet_modinfo *, void *, char *);
#define VNET_SYMMAP_END { NULL, 0 }
#endif /* !VIMAGE_GLOBALS */
#ifdef VIMAGE
struct vnet {
void *mod_data[VNET_MOD_MAX];
LIST_ENTRY(vnet) vnet_le; /* all vnets list */
u_int vnet_magic_n;
u_int ifccnt;
u_int sockcnt;
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 */
u_int vi_ucredrefc; /* # of ucreds pointing to us */
char vi_name[MAXHOSTNAMELEN];
struct vnet *v_net;
struct vprocg *v_procg;
};
#endif
struct vnet {
void *mod_data[VNET_MOD_MAX];
LIST_ENTRY(vnet) vnet_le; /* all vnets list */
u_int vnet_magic_n;
u_int vnet_id; /* ID num */
u_int ifccnt;
u_int sockcnt;
};
struct vprocg {
LIST_ENTRY(vprocg) vprocg_le;
u_int vprocg_id; /* ID num */
u_int nprocs;
char _hostname[MAXHOSTNAMELEN];
char _domainname[MAXHOSTNAMELEN];
};
#ifndef VIMAGE_GLOBALS
#ifdef VIMAGE
#define curvnet curthread->td_vnet
LIST_HEAD(vimage_list_head, vimage);
extern struct vimage_list_head vimage_head;
#else
#define curvnet NULL
extern struct vprocg vprocg_0;
#endif
#endif
#define curvnet curthread->td_vnet
#define VNET_MAGIC_N 0x3e0d8f29
@ -251,28 +280,57 @@ extern struct vnet_list_head vnet_head;
#define VNET_FOREACH(arg)
#endif
#define TD_TO_VNET(td) (td)->td_ucred->cr_vnet
#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)->vnet_id == 0)
#else
#define IS_DEFAULT_VIMAGE(arg) 1
#define IS_DEFAULT_VNET(arg) 1
#endif
#ifdef VIMAGE
#define TD_TO_VIMAGE(td) (td)->td_ucred->cr_vimage
#define TD_TO_VNET(td) (td)->td_ucred->cr_vimage->v_net
#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) (p)->p_ucred->cr_vimage->v_net
#define P_TO_VPROCG(p) (p)->p_ucred->cr_vimage->v_procg
#else
#define TD_TO_VIMAGE(td) NULL
#define TD_TO_VNET(td) NULL
#define P_TO_VIMAGE(p) NULL
#define P_TO_VNET(p) NULL
#ifdef VIMAGE_GLOBALS
#define TD_TO_VPROCG(td) NULL
#define P_TO_VPROCG(p) NULL
#else
#define TD_TO_VPROCG(td) &vprocg_0
#define P_TO_VPROCG(p) &vprocg_0
#endif
#endif
/* Non-VIMAGE null-macros */
#define IS_DEFAULT_VNET(arg) 1
#define VNET_LIST_RLOCK()
#define VNET_LIST_RUNLOCK()
#define INIT_VPROCG(arg)
#define INIT_VCPU(arg)
#define TD_TO_VIMAGE(td)
#define TD_TO_VPROCG(td)
#define TD_TO_VCPU(td)
#define P_TO_VIMAGE(p)
#define P_TO_VNET(p)
#define P_TO_VPROCG(p)
#define P_TO_VCPU(p)
/* XXX those defines bellow should probably go into vprocg.h and vcpu.h */
#define VPROCG(sym) (sym)
#define VCPU(sym) (sym)
#define VPROCG(sym) VSYM(vprocg, sym)
#ifdef VIMAGE
#define G_hostname TD_TO_VPROCG(&thread0)->_hostname
#else
#define G_hostname VPROCG(hostname)
#endif
#define V_hostname VPROCG(hostname)
#define G_hostname VPROCG(hostname) /* global hostname */
#define V_domainname VPROCG(domainname)
/*