summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzec <zec@FreeBSD.org>2009-05-08 14:11:06 +0000
committerzec <zec@FreeBSD.org>2009-05-08 14:11:06 +0000
commit639797b2e609797fdaf2c8e88b9203bfc7c70b7e (patch)
tree070fe9c96176ed914dfefc12a45fea29b98c4122
parentf851007175f37de5aec0c77eb852e3444150e653 (diff)
downloadFreeBSD-src-639797b2e609797fdaf2c8e88b9203bfc7c70b7e.zip
FreeBSD-src-639797b2e609797fdaf2c8e88b9203bfc7c70b7e.tar.gz
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)
-rw-r--r--sys/cddl/compat/opensolaris/kern/opensolaris.c3
-rw-r--r--sys/cddl/compat/opensolaris/kern/opensolaris_misc.c2
-rw-r--r--sys/compat/svr4/svr4_stat.c1
-rw-r--r--sys/i386/ibcs2/ibcs2_socksys.c1
-rw-r--r--sys/kern/init_main.c5
-rw-r--r--sys/kern/kern_exit.c5
-rw-r--r--sys/kern/kern_fork.c3
-rw-r--r--sys/kern/kern_jail.c4
-rw-r--r--sys/kern/kern_linker.c12
-rw-r--r--sys/kern/kern_mib.c7
-rw-r--r--sys/kern/kern_prot.c10
-rw-r--r--sys/kern/kern_vimage.c23
-rw-r--r--sys/nlm/nlm_advlock.c5
-rw-r--r--sys/sys/kernel.h2
-rw-r--r--sys/sys/sysctl.h4
-rw-r--r--sys/sys/ucred.h2
-rw-r--r--sys/sys/vimage.h108
17 files changed, 165 insertions, 32 deletions
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris.c b/sys/cddl/compat/opensolaris/kern/opensolaris.c
index f1f84fb..003120f 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris.c
@@ -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:
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_misc.c b/sys/cddl/compat/opensolaris/kern/opensolaris_misc.c
index 279ae4c..af98827 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris_misc.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris_misc.c
@@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$");
char hw_serial[11] = "0";
struct opensolaris_utsname utsname = {
- .nodename = hostname
+ .nodename = "unset"
};
int
diff --git a/sys/compat/svr4/svr4_stat.c b/sys/compat/svr4/svr4_stat.c
index 3492aa8..6ddac44 100644
--- a/sys/compat/svr4/svr4_stat.c
+++ b/sys/compat/svr4/svr4_stat.c
@@ -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;
diff --git a/sys/i386/ibcs2/ibcs2_socksys.c b/sys/i386/ibcs2/ibcs2_socksys.c
index f4eb97c..2dba77d 100644
--- a/sys/i386/ibcs2/ibcs2_socksys.c
+++ b/sys/i386/ibcs2/ibcs2_socksys.c
@@ -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;
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 96ebf36..97b7f0f 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -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);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index a10e915..89b92c6 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -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);
}
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 76695e7..4e8dbb1 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -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
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 069f1f0..3bc5c10 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -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);
}
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 2237107..4e0c5a3 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -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);
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index 05f9031..43fcfa4 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -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;
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 9f13644..b35f81f 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -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
diff --git a/sys/kern/kern_vimage.c b/sys/kern/kern_vimage.c
index 21d502e..e20b382 100644
--- a/sys/kern/kern_vimage.c
+++ b/sys/kern/kern_vimage.c
@@ -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);
diff --git a/sys/nlm/nlm_advlock.c b/sys/nlm/nlm_advlock.c
index 2c1f1a6..a2c62f0 100644
--- a/sys/nlm/nlm_advlock.c
+++ b/sys/nlm/nlm_advlock.c
@@ -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;
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index fa397c4..997e20d 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -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) */
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index c6da7b9..10fc0f0 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -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); \
} \
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index 338b056..bac4899 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -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 */
diff --git a/sys/sys/vimage.h b/sys/sys/vimage.h
index ccd0c73..8c107ea 100644
--- a/sys/sys/vimage.h
+++ b/sys/sys/vimage.h
@@ -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 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;
+};
+
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;
+ 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;
};
-#endif
+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)
/*
OpenPOWER on IntegriCloud