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:
parent
fcec7b25b8
commit
29b02909eb
@ -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:
|
||||
|
@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$");
|
||||
char hw_serial[11] = "0";
|
||||
|
||||
struct opensolaris_utsname utsname = {
|
||||
.nodename = hostname
|
||||
.nodename = "unset"
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) */
|
||||
|
@ -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); \
|
||||
} \
|
||||
|
@ -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 */
|
||||
|
110
sys/sys/vimage.h
110
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 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)
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user