Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150431376
D15865.1792378902.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
32 KB
Referenced Files
None
Subscribers
None
D15865.1792378902.diff
View Options
Index: sys/ddb/db_expr.c
===================================================================
--- sys/ddb/db_expr.c
+++ sys/ddb/db_expr.c
@@ -58,7 +58,8 @@
if (t == tIDENT) {
if (!db_value_of_name(db_tok_string, valuep) &&
!db_value_of_name_pcpu(db_tok_string, valuep) &&
- !db_value_of_name_vnet(db_tok_string, valuep)) {
+ !db_value_of_name_vnet(db_tok_string, valuep) &&
+ !db_value_of_name_vps(db_tok_string, valuep)) {
db_printf("Symbol '%s' not found\n", db_tok_string);
db_error(NULL);
/*NOTREACHED*/
Index: sys/ddb/db_ps.c
===================================================================
--- sys/ddb/db_ps.c
+++ sys/ddb/db_ps.c
@@ -398,6 +398,9 @@
db_printf(" last involuntary switch: %d ms ago\n",
1000 * delta / hz);
}
+#ifdef VIMAGE
+ db_printf(" vnet: %p vps: %p\n", td->td_vnet, td->td_vps);
+#endif
}
DB_SHOW_COMMAND(proc, db_show_proc)
Index: sys/ddb/db_sym.c
===================================================================
--- sys/ddb/db_sym.c
+++ sys/ddb/db_sym.c
@@ -37,8 +37,10 @@
#include <sys/param.h>
#include <sys/pcpu.h>
+#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/systm.h>
+#include <sys/vps.h>
#include <net/vnet.h>
@@ -69,6 +71,7 @@
#ifdef VIMAGE
static void *db_vnet = NULL;
+static void *db_vps = NULL;
#endif
/*
@@ -168,6 +171,53 @@
return (0);
}
}
+
+/*
+ * Validate the virtual process space pointer used to interpret per-vps global
+ * variable expansion. Right now we don't do much here, really we should
+ * walk the global vps list to check it's an OK pointer.
+ */
+int
+db_var_db_vps(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+
+ switch (op) {
+ case DB_VAR_GET:
+ *valuep = (db_expr_t)db_vps;
+ return (1);
+
+ case DB_VAR_SET:
+ db_vps = *(void **)valuep;
+ return (1);
+
+ default:
+ db_printf("db_var_db_vps: unknown operation\n");
+ return (0);
+ }
+}
+
+/*
+ * Read-only variable reporting the current vps, which is what we use when
+ * db_vps is set to NULL.
+ */
+int
+db_var_curvps(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+
+ switch (op) {
+ case DB_VAR_GET:
+ *valuep = (db_expr_t)curvps;
+ return (1);
+
+ case DB_VAR_SET:
+ db_printf("Read-only variable.\n");
+ return (0);
+
+ default:
+ db_printf("db_var_curvps: unknown operation\n");
+ return (0);
+ }
+}
#endif
/*
@@ -278,6 +328,33 @@
#endif
}
+bool
+db_value_of_name_vps(const char *name, db_expr_t *valuep)
+{
+#ifdef VIMAGE
+ static char tmp[256];
+ db_expr_t value;
+ c_db_sym_t sym;
+ struct vps *vps;
+
+ if (db_vps != NULL)
+ vps = db_vps;
+ else
+ vps = curvps;
+ snprintf(tmp, sizeof(tmp), "vps_entry_%s", name);
+ sym = db_lookup(tmp);
+ if (sym == C_DB_SYM_NULL)
+ return (false);
+ db_symbol_values(sym, &name, &value);
+ if (value < VPS_START || value >= VPS_STOP)
+ return (false);
+ *valuep = (db_expr_t)((uintptr_t)value + vps->vps_data_base);
+ return (true);
+#else
+ return (false);
+#endif
+}
+
/*
* Lookup a symbol.
* If the symbol has a qualifier (e.g., ux:vm_map),
Index: sys/ddb/db_variables.h
===================================================================
--- sys/ddb/db_variables.h
+++ sys/ddb/db_variables.h
@@ -56,8 +56,10 @@
extern db_varfcn_t db_var_curcpu; /* DPCPU default CPU */
extern db_varfcn_t db_var_curvnet; /* Default vnet */
+extern db_varfcn_t db_var_curvps; /* Default vps */
extern db_varfcn_t db_var_db_cpu; /* DPCPU active CPU */
extern db_varfcn_t db_var_db_vnet; /* Active vnet */
+extern db_varfcn_t db_var_db_vps; /* Active vps */
int db_read_variable(struct db_variable *, db_expr_t *);
int db_write_variable(struct db_variable *, db_expr_t);
Index: sys/ddb/db_variables.c
===================================================================
--- sys/ddb/db_variables.c
+++ sys/ddb/db_variables.c
@@ -53,6 +53,8 @@
#ifdef VIMAGE
{ "curvnet", NULL, db_var_curvnet },
{ "db_vnet", NULL, db_var_db_vnet },
+ { "curvps", NULL, db_var_curvps },
+ { "db_vps", NULL, db_var_db_vps },
#endif
};
static struct db_variable *db_evars = db_vars + nitems(db_vars);
Index: sys/ddb/ddb.h
===================================================================
--- sys/ddb/ddb.h
+++ sys/ddb/ddb.h
@@ -229,6 +229,7 @@
bool db_value_of_name(const char *name, db_expr_t *valuep);
bool db_value_of_name_pcpu(const char *name, db_expr_t *valuep);
bool db_value_of_name_vnet(const char *name, db_expr_t *valuep);
+bool db_value_of_name_vps(const char *name, db_expr_t *valuep);
int db_write_bytes(vm_offset_t addr, size_t size, char *data);
void db_command_register(struct command_table *, struct command *);
void db_command_unregister(struct command_table *, struct command *);
Index: sys/kern/init_main.c
===================================================================
--- sys/kern/init_main.c
+++ sys/kern/init_main.c
@@ -56,6 +56,7 @@
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/jail.h>
+#include <sys/kthread.h>
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/loginclass.h>
@@ -79,6 +80,7 @@
#include <sys/malloc.h>
#include <sys/conf.h>
#include <sys/cpuset.h>
+#include <sys/vps.h>
#include <machine/cpu.h>
@@ -106,6 +108,15 @@
VPS_DEFINE(struct proc *, initproc);
VPS_DEFINE(struct proc *, vproc0);
+#ifdef VIMAGE
+/*
+ * Initialize to -2; after kproc_create() our thread will still be
+ * forked from thread0 and in the wrong vps. Once that is fixed it will
+ * see the local copy and not the DEFAULT_VPS one. Make sure we have
+ * a value that we can spin on until this happens.
+ */
+VPS_DEFINE(int, vpsdying) = -2;
+#endif
#ifndef BOOTHOWTO
#define BOOTHOWTO 0
@@ -501,6 +512,9 @@
td->td_cpuset = cpuset_thread0();
td->td_domain.dr_policy = td->td_cpuset->cs_domain;
prison0_init();
+#ifdef VIMAGE
+ td->td_vps = vps0;
+#endif
p->p_peers = 0;
p->p_leader = p;
p->p_reaper = p;
@@ -603,7 +617,183 @@
racct_add_force(p, RACCT_NPROC, 1);
PROC_UNLOCK(p);
}
-SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL);
+SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_THIRD, proc0_init, NULL);
+
+#ifdef VIMAGE
+static void
+vps_swapper(void *dummy __unused)
+{
+
+ /*
+ * Make sure the surgical changes to V_vproc0 are done before
+ * entering the long-lasting loop. Otherwise we may start
+ * acquiring locks and accessing variables based on the wrong
+ * credential leading to, e.g., panics when trying to unlock a
+ * lock from a different context which may not be locked.
+ * When entering the function our credentials might still point
+ * to the DEFAULT_VPS; see comment for V_vpsdying declaration above.
+ */
+ while (V_vpsdying < 0)
+ pause("wswvps", hz/2);
+
+ /*
+ * Now hand over this thread to swapper.
+ */
+ swapper();
+
+ if (V_vpsdying < 1)
+ panic("%s: swapper curtd %p ended but V_vpsdying %d\n",
+ __func__, curthread, V_vpsdying);
+
+ kproc_exit(0);
+}
+
+static void
+proc0_init_vps(void *dummy __unused)
+{
+ struct ucred *newcred, *savecred;
+ struct thread *td;
+ struct prison *pr;
+ struct uidinfo tmpuinfo;
+ struct loginclass tmplc = {
+ .lc_name = "",
+ };
+ int error;
+
+ /* vps0 is handled normally in p0init. */
+ if (IS_DEFAULT_VPS(curvps))
+ return;
+
+ KASSERT((curvps->vps_pr != NULL && curvps != vps0),
+ ("%s: curvps %p has vps_pr %p or is vps0 %p\n",
+ __func__, curvps, curvps->vps_pr, vps0));
+ KASSERT((curvps == curvps->vps_pr->pr_vps),
+ ("%s: curvps %p != curvps->vps_pr %p ->pr_vps %p\n",
+ __func__, curvps, curvps->vps_pr, curvps->vps_pr->pr_vps));
+
+ /*
+ * Initialized the non-default VPS version to < 0 so vps_swapper()
+ * will spin once the credential is changed before all other surgery
+ * has happened.
+ */
+ V_vpsdying = -1;
+
+ /*
+ * Default is nprocs = 1 for vps0; need to set it to 0 here as our
+ * "proc0" and with that initproc are forked and not manually constructed.
+ */
+ V_nprocs = 0;
+
+ /*
+ * Set lastpid to -1 so that our swapper gets 0.
+ */
+ V_lastpid = -1;
+
+ error = kproc_create(vps_swapper, NULL, &V_vproc0, 0, 0, "vps%u",
+ curvps->vps_pr->pr_id);
+ if (error)
+ panic("%s: cannot create vps %p swapper: %d\n",
+ __func__, curvps, error);
+
+ /* Create credentials. Copied from proc0. Just using vps_pr. */
+ newcred = crget();
+ newcred->cr_ngroups = 1; /* group 0 */
+ /* A hack to prevent uifind from tripping over NULL pointers. */
+ savecred = curthread->td_ucred;
+ curthread->td_ucred = newcred;
+ tmpuinfo.ui_uid = 1;
+ newcred->cr_uidinfo = newcred->cr_ruidinfo = &tmpuinfo;
+ newcred->cr_uidinfo = uifind(0);
+ newcred->cr_ruidinfo = uifind(0);
+ newcred->cr_loginclass = &tmplc;
+ newcred->cr_loginclass = loginclass_find("default");
+ /* End hack. creds get properly set later with thread_cow_get_proc */
+ curthread->td_ucred = savecred;
+ PROC_LOCK(V_vproc0);
+ newcred->cr_prison = curvps->vps_pr;
+ prison_hold(newcred->cr_prison);
+ /* The kernel process was accounted to thread0's prison. */
+ prison_proc_hold(newcred->cr_prison);
+ prison_proc_free(savecred->cr_prison);
+ V_vproc0->p_treeflag |= P_TREE_REAPER;
+ savecred = proc_set_cred(V_vproc0, newcred);
+ PROC_UNLOCK(V_vproc0);
+#ifdef AUDIT
+ audit_cred_kproc0(newcred);
+#endif
+#ifdef MAC
+ mac_cred_create_swapper(newcred);
+#endif
+ crfree(savecred);
+
+ PROC_LOCK(V_vproc0);
+ td = FIRST_THREAD_IN_PROC(V_vproc0);
+ thread_cow_get_proc(td, V_vproc0);
+ PROC_UNLOCK(V_vproc0);
+ KASSERT(curvps->vps_pr ==
+ FIRST_THREAD_IN_PROC(V_vproc0)->td_ucred->cr_prison,
+ ("%s:%d: curvps %p vps_pr %p != FTIP(V_vproc0 %p)->td_ucred %p "
+ "cr_prison %p\n", __func__, __LINE__,
+ curvps, curvps->vps_pr, V_vproc0,
+ FIRST_THREAD_IN_PROC(V_vproc0)->td_ucred,
+ FIRST_THREAD_IN_PROC(V_vproc0)->td_ucred->cr_prison));
+ KASSERT(curvps == TD_TO_VPS(FIRST_THREAD_IN_PROC(V_vproc0)),
+ ("%s:%d: curvps %p != TD_TO_VPS(..(V_vproc0 %p)) %p\n",
+ __func__, __LINE__,
+ curvps, V_vproc0, TD_TO_VPS(FIRST_THREAD_IN_PROC(V_vproc0))));
+
+ /* Chroot it. */
+ td = FIRST_THREAD_IN_PROC(V_vproc0);
+ pr = curvps->vps_pr;
+ vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY);
+ if ((error = change_dir(pr->pr_root, td)) != 0) {
+ printf("%s: td %p change_dir %p failed: %d\n",
+ __func__, td, pr->pr_root, error);
+ goto err;
+ }
+#ifdef MAC
+ if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root))) {
+ printf("%s: td %p mac_vnode_check_chroot %p failed: %d\n",
+ __func__, td, pr->pr_root, error);
+ goto err;
+ }
+#endif
+ VOP_UNLOCK(pr->pr_root, 0);
+ if ((error = pwd_chroot(td, pr->pr_root))) {
+ printf("%s: td %p pwd_chroot %p failed: %d\n",
+ __func__, td, pr->pr_root, error);
+ goto err;
+ }
+
+ V_vpsdying = 0;
+ return;
+
+err:
+ /* XXX could panic or singal the jail to abort; cannot really stop. */
+ return;
+}
+VPS_SYSINIT(p0init_vps, SI_SUB_INTRINSIC, SI_ORDER_THIRD, proc0_init_vps, NULL);
+
+static void
+proc0_uninit_vps(void *dummy __unused)
+{
+
+ if (IS_DEFAULT_VPS(curvps))
+ return;
+
+ /*
+ * XXX ideally we want to get that state from elsewhere;
+ * neither prison, not vps state, .. lends itself though.
+ */
+ V_vpsdying = 1;
+ wakeup(V_vproc0);
+
+ while (V_vproc0 != NULL ||
+ !LIST_EMPTY(&V_zombproc) || !LIST_EMPTY(&V_allproc))
+ pause("p0uvps", hz/2);
+}
+VPS_SYSUNINIT(p0uninit_vps, SI_SUB_INTRINSIC, SI_ORDER_THIRD, proc0_uninit_vps, NULL);
+#endif
/* ARGSUSED*/
static void
@@ -712,7 +902,8 @@
td = curthread;
p = td->td_proc;
- vfs_mountroot();
+ if (IS_DEFAULT_VPS(curvps))
+ vfs_mountroot();
/* Wipe GELI passphrase from the environment. */
kern_unsetenv("kern.geom.eli.passphrase");
@@ -736,8 +927,8 @@
while ((path = strsep(&tmp_init_path, ":")) != NULL) {
pathlen = strlen(path) + 1;
if (bootverbose)
- printf("start_init: trying %s\n", path);
-
+ printf("%s: trying %s\n", __func__, path);
+
/*
* Move out the boot flag argument.
*/
@@ -822,39 +1013,60 @@
struct thread *td;
int error;
+ KASSERT(curvps == FIRST_THREAD_IN_PROC(V_vproc0)->td_vps,
+ ("%s: curvps %p != V_vproc0 %p first td %p td_vps %p\n",
+ __func__, curvps, V_vproc0, FIRST_THREAD_IN_PROC(V_vproc0),
+ FIRST_THREAD_IN_PROC(V_vproc0)->td_vps));
+ KASSERT(curvps == TD_TO_VPS(FIRST_THREAD_IN_PROC(V_vproc0)),
+ ("%s: curvps %p != TD_TO_VPS(..(V_vproc0 %p)) %p\n",
+ __func__, curvps, V_vproc0,
+ TD_TO_VPS(FIRST_THREAD_IN_PROC(V_vproc0))));
+
bzero(&fr, sizeof(fr));
fr.fr_flags = RFFDG | RFPROC | RFSTOPPED;
fr.fr_procp = &V_initproc;
- error = fork1(&thread0, &fr);
+ td = FIRST_THREAD_IN_PROC(V_vproc0);
+ error = fork1(td, &fr);
if (error)
panic("cannot fork init: %d\n", error);
- KASSERT(V_initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
+ KASSERT(V_initproc->p_pid == 1, ("%s: initproc->p_pid(%d) != 1",
+ __func__, V_initproc->p_pid));
+ KASSERT(curvps == FIRST_THREAD_IN_PROC(V_initproc)->td_vps,
+ ("%s: curvps %p != V_initproc %p first td %p td_vps %p\n",
+ __func__, curvps, V_initproc, FIRST_THREAD_IN_PROC(V_initproc),
+ FIRST_THREAD_IN_PROC(V_initproc)->td_vps));
+
/* divorce init's credentials from the kernel's */
newcred = crget();
sx_xlock(&V_proctree_lock);
PROC_LOCK(V_initproc);
V_initproc->p_flag |= P_SYSTEM | P_INMEM;
V_initproc->p_treeflag |= P_TREE_REAPER;
- LIST_INSERT_HEAD(&V_initproc->p_reaplist, V_vproc0, p_reapsibling);
oldcred = V_initproc->p_ucred;
crcopy(newcred, oldcred);
+#ifdef VIMAGE
+ /* Swap to the correct prison. */
+ /* XXX is this really needed or was this related to a V_vproc0 bug? */
+ prison_free(newcred->cr_prison);
+ newcred->cr_prison = curvps->vps_pr;
+ prison_hold(newcred->cr_prison);
+#endif
#ifdef MAC
mac_cred_create_init(newcred);
#endif
#ifdef AUDIT
audit_cred_proc1(newcred);
#endif
+ /* This will also update cowgen. */
proc_set_cred(V_initproc, newcred);
- td = FIRST_THREAD_IN_PROC(V_initproc);
- crfree(td->td_ucred);
- td->td_ucred = crhold(V_initproc->p_ucred);
PROC_UNLOCK(V_initproc);
sx_xunlock(&V_proctree_lock);
crfree(oldcred);
+
cpu_fork_kthread_handler(FIRST_THREAD_IN_PROC(V_initproc),
start_init, NULL);
}
-SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL);
+VPS_SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL);
/*
* Make it runnable now.
@@ -870,4 +1082,42 @@
sched_add(td, SRQ_BORING);
thread_unlock(td);
}
-SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_MIDDLE, kick_init, NULL);
+VPS_SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_MIDDLE, kick_init, NULL);
+
+#ifdef VIMAGE
+static void
+reapinit(void *ident __unused)
+{
+ struct proc *p, *p2;
+
+ while (V_nprocs > 2) {
+ sx_slock(&V_allproc_lock);
+ LIST_FOREACH(p, &V_allproc, p_list) {
+ if (p->p_pid <= 1)
+ continue;
+ PROC_LOCK(p);
+ kern_psignal(p, SIGKILL);
+ PROC_UNLOCK(p);
+ }
+ sx_sunlock(&V_allproc_lock);
+ pause("reapin1t", hz/2);
+ }
+
+ sx_xlock(&V_proctree_lock);
+ LIST_FOREACH_SAFE(p, &V_zombproc, p_list, p2) {
+ PROC_LOCK(p);
+ proc_reap(FIRST_THREAD_IN_PROC(V_vproc0), p, NULL, 0);
+ sx_xlock(&V_proctree_lock);
+ }
+ sx_xunlock(&V_proctree_lock);
+
+ while (V_nprocs > 1)
+ pause("reapinit", hz/2);
+
+ /* Only our "swapper" left. */
+ KASSERT(V_nprocs == 1, ("%s: vps %p V_nprocs %d != 1",
+ __func__, curvps, V_nprocs));
+}
+/* Run very first. */
+VPS_SYSUNINIT(reapinit, SI_SUB_VIMAGE_DONE, SI_ORDER_ANY, reapinit, NULL);
+#endif
Index: sys/kern/kern_clock.c
===================================================================
--- sys/kern/kern_clock.c
+++ sys/kern/kern_clock.c
@@ -194,6 +194,14 @@
tryl = 0;
for (;;) {
+#ifdef VIMAGE
+ VPS_ITERATOR_DECL(vps);
+
+ VPS_LIST_RLOCK();
+ VPS_FOREACH(vps) {
+again:
+ CURVPS_SET_QUIET(vps);
+#endif
blkticks = blktime_threshold * hz;
slpticks = slptime_threshold * hz;
@@ -204,11 +212,17 @@
*/
if (!sx_try_slock(&V_allproc_lock)) {
if (tryl > 100)
- panic("%s: possible deadlock detected on allproc_lock\n",
+ panic("%s: possible deadlock detected on allproc_lock\n",
__func__);
tryl++;
+ CURVPS_RESTORE();
+
pause("allproc", sleepfreq * hz);
+#ifdef VIMAGE
+ goto again;
+#else
continue;
+#endif
}
tryl = 0;
FOREACH_PROC_IN_SYSTEM(p) {
@@ -297,6 +311,12 @@
}
sx_sunlock(&V_allproc_lock);
+#ifdef VIMAGE
+ CURVPS_RESTORE();
+ }
+ VPS_LIST_RUNLOCK();
+#endif
+
/* Sleep for sleepfreq seconds. */
pause("-", sleepfreq * hz);
}
Index: sys/kern/kern_exit.c
===================================================================
--- sys/kern/kern_exit.c
+++ sys/kern/kern_exit.c
@@ -96,6 +96,11 @@
SDT_PROVIDER_DECLARE(proc);
SDT_PROBE_DEFINE1(proc, , , exit, "int");
+#ifdef VIMAGE
+VPS_DECLARE(int, vrebooting); /* kern_reboot() has been called. */
+#define V_vrebooting VPS(vrebooting)
+#endif
+
/* Hook for NFS teardown procedure. */
void (*nlminfo_release_p)(struct proc *p);
@@ -133,9 +138,15 @@
struct proc *p1, *p2, *ptmp;
sx_assert(&V_proctree_lock, SX_LOCKED);
- KASSERT(p != V_initproc, ("reaper_abandon_children for initproc"));
- if ((p->p_treeflag & P_TREE_REAPER) == 0)
+ /* init inside a vps may die on prison_remove. */
+ KASSERT(!IS_DEFAULT_VPS(curvps) || p != V_initproc,
+ ("%s: for initproc %p", __func__, p));
+ if ((p->p_treeflag & P_TREE_REAPER) == 0) {
+ KASSERT((p != V_initproc && p->p_pid != 1 && p->p_pid != 0),
+ ("%s:%d curvps %p p %p pid %d p_treeflag %#x",
+ __func__, __LINE__, curvps, p, p->p_pid, p->p_treeflag));
return;
+ }
p1 = p->p_reaper;
LIST_FOREACH_SAFE(p2, &p->p_reaplist, p_reapsibling, ptmp) {
LIST_REMOVE(p2, p_reapsibling);
@@ -148,7 +159,8 @@
PROC_UNLOCK(p2);
}
}
- KASSERT(LIST_EMPTY(&p->p_reaplist), ("p_reaplist not empty"));
+ KASSERT(LIST_EMPTY(&p->p_reaplist),
+ ("%s: p %p p_reaplist not empty", __func__, p));
p->p_treeflag &= ~P_TREE_REAPER;
}
@@ -203,9 +215,19 @@
* work around an unsolved stack overflow seen very late during
* shutdown on sparc64 when the gmirror worker process exists.
*/
- if (p == V_initproc && rebooting == 0) {
+ if (p == V_initproc && (rebooting == 0
+#ifdef VIMAGE
+ || V_vrebooting
+#endif
+ )) {
printf("init died (signal %d, exit %d)\n", signo, rval);
- panic("Going nowhere without my init!");
+#ifdef VIMAGE
+ if (!IS_DEFAULT_VPS(TD_TO_VPS(td)))
+ /* XXX-BZ make this jail go away. */ ;
+ else
+#endif
+ panic("%s: Going nowhere without my init! td %p",
+ __func__, td);
}
/*
@@ -829,7 +851,7 @@
sx_assert(&V_proctree_lock, SA_XLOCKED);
PROC_LOCK_ASSERT(p, MA_OWNED);
- KASSERT(p->p_state == PRS_ZOMBIE, ("proc_reap: !PRS_ZOMBIE"));
+ KASSERT(p->p_state == PRS_ZOMBIE, ("%s: !PRS_ZOMBIE", __func__));
mtx_spin_wait_unlocked(&p->p_slock);
@@ -953,7 +975,7 @@
#endif
KASSERT(FIRST_THREAD_IN_PROC(p),
- ("proc_reap: no residual thread!"));
+ ("%s: no residual thread!", __func__));
uma_zfree(proc_zone, p);
atomic_add_int(&V_nprocs, -1);
}
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c
+++ sys/kern/kern_fork.c
@@ -237,7 +237,7 @@
static VPS_DEFINE(int, pidchecked) = 0;
#define V_pidchecked VPS(pidchecked)
-static int
+int
fork_findpid(int flags)
{
struct proc *p;
@@ -494,6 +494,7 @@
td2->td_lend_user_pri = PRI_MAX;
#ifdef VIMAGE
+ td2->td_vps = TD_TO_VPS(td);
td2->td_vnet = NULL;
td2->td_vnet_lpush = NULL;
#endif
Index: sys/kern/kern_jail.c
===================================================================
--- sys/kern/kern_jail.c
+++ sys/kern/kern_jail.c
@@ -78,10 +78,6 @@
#include <security/mac/mac_framework.h>
-#ifdef VIMAGE
-FEATURE(vimage, "VIMAGE kernel virtualization");
-#endif
-
#define DEFAULT_HOSTUUID "00000000-0000-0000-0000-000000000000"
MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
@@ -179,9 +175,7 @@
{"host", 0, PR_HOST},
#ifdef VIMAGE
{"vnet", 0, PR_VNET},
-#ifdef ENABLE_VPS
- {"vps", 0, PR_VPS },
-#endif
+ {"vps", 0, PR_VPS},
#endif
#ifdef INET
{"ip4", PR_IP4_USER, PR_IP4_USER},
@@ -1819,11 +1813,7 @@
#ifdef VIMAGE
/* Allocate a new vps if specified. */
-#ifdef ENABLE_VPS
if (pr_flags & PR_VPS) {
-#else
- if (0) {
-#endif
vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY);
if ((error = change_dir(pr->pr_root, td)) != 0)
goto c_unlock;
@@ -2339,7 +2329,6 @@
* Kill all processes unfortunate enough to be attached to this prison.
*/
#ifdef VIMAGE
-#ifdef ENABLE_VPS
if (pr->pr_vps) {
/*
* Send signal to init and let init do it's job.
@@ -2357,7 +2346,6 @@
vps_destroy(pr->pr_vps);
CURVPS_RESTORE();
} else
-#endif
#endif
{
sx_slock(&V_allproc_lock);
@@ -2421,7 +2409,7 @@
* right, including a new pid, progress group, session, terminal,
* tracing is one thing (with a lot of work) and may break apps if the
* pid changes, the pgrp no longer has the same (p)id; getting things
- * restored to oriinal state and properly re-parented is virtually
+ * restored to original state and properly re-parented is virtually
* impossile. So do what we do on a normal machine, present a terminal
* to login to.
*/
@@ -2722,7 +2710,8 @@
#ifdef VIMAGE
if (pr->pr_vnet != ppr->pr_vnet)
vnet_destroy(pr->pr_vnet);
- KASSERT(pr->pr_vps == NULL, ("%s: pr %p pr_vps %p != NULL\n",
+ KASSERT((pr->pr_vps == ppr->pr_vps || pr->pr_vps == NULL),
+ ("%s: pr %p pr_vps %p != NULL\n",
__func__, pr, pr->pr_vps));
#endif
if (pr->pr_root != NULL)
@@ -3824,11 +3813,9 @@
#ifdef VIMAGE
SYSCTL_JAIL_PARAM(, vnet, CTLTYPE_INT | CTLFLAG_RDTUN,
"E,jailsys", "Virtual network stack");
-#ifdef ENABLE_VPS
SYSCTL_JAIL_PARAM(, vps, CTLTYPE_INT | CTLFLAG_RDTUN,
"E,jailsys", "Virtual process space");
#endif
-#endif
SYSCTL_JAIL_PARAM(, dying, CTLTYPE_INT | CTLFLAG_RD,
"B", "Jail is in the process of shutting down");
Index: sys/kern/kern_kthread.c
===================================================================
--- sys/kern/kern_kthread.c
+++ sys/kern/kern_kthread.c
@@ -32,6 +32,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/cpuset.h>
+#include <sys/jail.h>
#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -45,6 +46,8 @@
#include <sys/wait.h>
#include <sys/sched.h>
#include <sys/tslog.h>
+#include <sys/vps.h>
+
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -89,7 +92,7 @@
struct thread *td;
struct proc *p2;
- if (!V_vproc0->p_stats)
+ if (!proc0.p_stats)
panic("kproc_create called too soon");
bzero(&fr, sizeof(fr));
@@ -160,7 +163,26 @@
*/
sx_xlock(&V_proctree_lock);
PROC_LOCK(p);
- proc_reparent(p, V_initproc);
+#ifdef VIMAGE
+ /*
+ * In the VIMAGE case if the kproc is our virtual "swapper"
+ * do not reparent it to our init as otherwise it would create
+ * a circle and never go away. Let the parent vps reap it
+ * as it was setup. And it needs to be the init there and
+ * not the swapper(kernel).
+ */
+ if (!IS_DEFAULT_VPS(TD_TO_VPS(FIRST_THREAD_IN_PROC(p))) &&
+ p->p_pid == 0) {
+ struct proc *init0;
+
+ CURVPS_SET_QUIET(vps0)
+ init0 = V_initproc;
+ CURVPS_RESTORE();
+
+ proc_reparent(p, init0);
+ } else
+#endif
+ proc_reparent(p, V_initproc);
PROC_UNLOCK(p);
sx_xunlock(&V_proctree_lock);
@@ -260,7 +282,7 @@
va_list ap;
struct thread *newtd, *oldtd;
- if (!V_vproc0->p_stats)
+ if (!proc0.p_stats)
panic("kthread_add called too soon");
/* If no process supplied, put it on proc0 */
@@ -288,6 +310,9 @@
TSTHREAD(newtd, newtd->td_name);
newtd->td_proc = p; /* needed for cpu_copy_thread */
+#ifdef VIMAGE
+ newtd->td_vps = TD_TO_VPS(oldtd);
+#endif
/* might be further optimized for kthread */
cpu_copy_thread(newtd, oldtd);
/* put the designated function(arg) as the resume context */
Index: sys/kern/kern_proc.c
===================================================================
--- sys/kern/kern_proc.c
+++ sys/kern/kern_proc.c
@@ -196,12 +196,36 @@
LIST_INIT(&V_zombproc);
V_pidhashtbl = hashinit(maxproc / 4, M_PROC, &V_pidhash);
V_pgrphashtbl = hashinit(maxproc / 4, M_PROC, &V_pgrphash);
- proc_zone = uma_zcreate("PROC", sched_sizeof_proc(),
- proc_ctor, proc_dtor, proc_init, proc_fini,
- UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+ if (IS_DEFAULT_VPS(curvps)) {
+ proc_zone = uma_zcreate("PROC", sched_sizeof_proc(),
+ proc_ctor, proc_dtor, proc_init, proc_fini,
+ UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+ }
}
VPS_SYSINIT(procinit, SI_SUB_INTRINSIC, SI_ORDER_SECOND, procinit, NULL);
+#ifdef VIMAGE
+static void
+procdestroy(void *ident __unused)
+{
+
+ KASSERT((LIST_EMPTY(&V_allproc)), ("%s: list allproc %p not empty\n",
+ __func__, &V_allproc));
+ KASSERT((LIST_EMPTY(&V_zombproc)), ("%s: list zombproc %p not empty\n",
+ __func__, &V_zombproc));
+
+ /* proc_zone */
+ hashdestroy(V_pgrphashtbl, M_PROC, V_pgrphash);
+ hashdestroy(V_pidhashtbl, M_PROC, V_pidhash);
+
+ mtx_destroy(&V_ppeers_lock);
+ sx_destroy(&V_proctree_lock);
+ sx_destroy(&V_allproc_lock);
+}
+VPS_SYSUNINIT(procdestroy, SI_SUB_INTRINSIC, SI_ORDER_SECOND, procdestroy,
+ NULL);
+#endif
+
/*
* Prepare a proc for use.
*/
Index: sys/kern/kern_prot.c
===================================================================
--- sys/kern/kern_prot.c
+++ sys/kern/kern_prot.c
@@ -52,6 +52,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/acct.h>
+#include <sys/filedesc.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@@ -1860,8 +1861,10 @@
crfree(struct ucred *cr)
{
- KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
- KASSERT(cr->cr_ref != 0xdeadc0de, ("dangling reference to ucred"));
+ KASSERT(cr->cr_ref > 0, ("%s: bad ucred %p refcount: %d",
+ __func__, cr, cr->cr_ref));
+ KASSERT(cr->cr_ref != 0xdeadc0de,
+ ("%s: dangling reference to ucred %p", __func__, cr));
if (refcount_release(&cr->cr_ref)) {
/*
* Some callers of crget(), such as nfs_statfs(),
Index: sys/kern/kern_resource.c
===================================================================
--- sys/kern/kern_resource.c
+++ sys/kern/kern_resource.c
@@ -1236,6 +1236,27 @@
VPS_SYSINIT(uihashinit_vps, SI_SUB_INTRINSIC, SI_ORDER_SECOND, uihashinit_vps,
NULL);
+#ifdef VIMAGE
+static void
+uihashdestroy_vps(void *ident __unused)
+{
+ struct uidinfo *uip;
+ struct uihashhead *uih;
+ int i;
+
+ i = 0;
+ for (uih = &V_uihashtbl[V_uihash]; uih >= V_uihashtbl; uih--)
+ LIST_FOREACH(uip, uih, ui_hash)
+ i++;
+ if (i == 0)
+ hashdestroy(V_uihashtbl, M_UIDINFO, V_uihash);
+ else
+ printf("%s: leaking %d uihash entries\n", __func__, i);
+}
+VPS_SYSUNINIT(uihashdestroy_vps, SI_SUB_INTRINSIC, SI_ORDER_SECOND,
+ uihashdestroy_vps, NULL);
+#endif
+
/*
* Look up a uidinfo struct for the parameter uid.
* uihashtbl_lock must be locked.
@@ -1406,7 +1427,8 @@
return (0);
}
} else if (new < 0)
- printf("negative %s for uid = %d\n", name, uip->ui_uid);
+ printf("%s: curthread %p uip %p negative %s for uid = %d\n",
+ __func__, curthread, uip, name, uip->ui_uid);
return (1);
}
Index: sys/kern/kern_shutdown.c
===================================================================
--- sys/kern/kern_shutdown.c
+++ sys/kern/kern_shutdown.c
@@ -204,6 +204,10 @@
int dumping; /* system is dumping */
int rebooting; /* system is rebooting */
+#ifdef VIMAGE
+VPS_DEFINE(int, vrebooting); /* vps is rebooting */
+#define V_vrebooting VPS(vrebooting)
+#endif
static struct dumperinfo dumper; /* our selected dumper */
/* Context information for dump-debuggers. */
@@ -276,29 +280,42 @@
if (error == 0) {
if (uap->opt & RB_REROOT)
error = kern_reroot();
- else
+ else {
+#ifdef VIMAGE
+ /* XXX Can argue that we should never make it here. */
+ /* Init will want to _exit() in this case. */
+ if (!IS_DEFAULT_VPS(TD_TO_VPS(curthread))) {
+ V_vrebooting = 1;
+ return (error);
+ }
+#endif
kern_reboot(uap->opt);
+ }
}
return (error);
}
+static VPS_DEFINE(int, vhowto);
+#define V_vhowto VPS(vhowto)
+
static void
shutdown_nice_task_fn(void *arg, int pending __unused)
{
- int howto;
- howto = (uintptr_t)arg;
+ CURVPS_SET((struct vps *)arg);
/* Send a signal to init(8) and have it shutdown the world. */
PROC_LOCK(V_initproc);
- if (howto & RB_POWEROFF)
+ if (V_vhowto & RB_POWEROFF)
kern_psignal(V_initproc, SIGUSR2);
- else if (howto & RB_POWERCYCLE)
+ else if (V_vhowto & RB_POWERCYCLE)
kern_psignal(V_initproc, SIGWINCH);
- else if (howto & RB_HALT)
+ else if (V_vhowto & RB_HALT)
kern_psignal(V_initproc, SIGUSR1);
else
kern_psignal(V_initproc, SIGINT);
PROC_UNLOCK(V_initproc);
+ V_vhowto = 0;
+ CURVPS_RESTORE();
}
static struct task shutdown_nice_task = TASK_INITIALIZER(0,
@@ -312,9 +329,21 @@
{
if (V_initproc != NULL && !SCHEDULER_STOPPED()) {
- shutdown_nice_task.ta_context = (void *)(uintptr_t)howto;
+
+ KASSERT(V_vhowto == 0, ("%s: vps %p howto not 0: %d\n",
+ __func__, curvps, V_vhowto));
+ V_vhowto = howto;
+ shutdown_nice_task.ta_context = (void *)curvps;
taskqueue_enqueue(taskqueue_fast, &shutdown_nice_task);
} else {
+#ifdef VIMAGE
+ /* XXX Can argue that we should never make it here. */
+ /* Init will want to _exit() in this case. */
+ if (!IS_DEFAULT_VPS(TD_TO_VPS(curthread))) {
+ V_vrebooting = 1;
+ return;
+ }
+#endif
/*
* No init(8) running, or scheduler would not allow it
* to run, so simply reboot.
Index: sys/kern/kern_sysctl.c
===================================================================
--- sys/kern/kern_sysctl.c
+++ sys/kern/kern_sysctl.c
@@ -2130,6 +2130,7 @@
memlocked = 1;
sx_xlock(&sysctlmemlock);
}
+ CURVPS_SET(TD_TO_VPS(td));
CURVNET_SET(TD_TO_VNET(td));
for (;;) {
@@ -2142,6 +2143,7 @@
}
CURVNET_RESTORE();
+ CURVPS_RESTORE();
if (req.lock == REQ_WIRED && req.validlen > 0)
vsunlock(req.oldptr, req.validlen);
Index: sys/kern/kern_thr.c
===================================================================
--- sys/kern/kern_thr.c
+++ sys/kern/kern_thr.c
@@ -32,6 +32,7 @@
#include "opt_posix.h"
#include "opt_hwpmc_hooks.h"
#include <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -56,6 +57,7 @@
#include <sys/rtprio.h>
#include <sys/umtx.h>
#include <sys/limits.h>
+#include <sys/vps.h>
#ifdef HWPMC_HOOKS
#include <sys/pmckern.h>
#endif
@@ -238,6 +240,9 @@
bcopy(&td->td_startcopy, &newtd->td_startcopy,
__rangeof(struct thread, td_startcopy, td_endcopy));
newtd->td_proc = td->td_proc;
+#ifdef VIMAGE
+ newtd->td_vps = TD_TO_VPS(td);
+#endif
newtd->td_rb_list = newtd->td_rbp_list = newtd->td_rb_inact = 0;
thread_cow_get(newtd, td);
Index: sys/kern/kern_thread.c
===================================================================
--- sys/kern/kern_thread.c
+++ sys/kern/kern_thread.c
@@ -58,6 +58,9 @@
#ifdef HWPMC_HOOKS
#include <sys/pmckern.h>
#endif
+#ifdef VIMAGE
+#include <sys/jail.h>
+#endif
#include <security/audit/audit.h>
@@ -451,6 +454,10 @@
PROC_LOCK_ASSERT(p, MA_OWNED);
newtd->td_ucred = crhold(p->p_ucred);
+#ifdef VIMAGE
+ /* Make sure the cached vps stays correct. */
+ newtd->td_vps = p->p_ucred->cr_prison->pr_vps;
+#endif
newtd->td_limit = lim_hold(p->p_limit);
newtd->td_cowgen = p->p_cowgen;
}
@@ -460,6 +467,10 @@
{
newtd->td_ucred = crhold(td->td_ucred);
+#ifdef VIMAGE
+ /* Make sure to inherit the cached vps as well. */
+ newtd->td_vps = td->td_vps;
+#endif
newtd->td_limit = lim_hold(td->td_limit);
newtd->td_cowgen = td->td_cowgen;
}
@@ -489,6 +500,11 @@
oldcred = td->td_ucred;
td->td_ucred = crhold(p->p_ucred);
}
+#ifdef VIMAGE
+ /* Make sure the cached vps stays correct. */
+ if (td->td_vps != p->p_ucred->cr_prison->pr_vps)
+ td->td_vps = p->p_ucred->cr_prison->pr_vps;
+#endif
if (td->td_limit != p->p_limit) {
oldlimit = td->td_limit;
td->td_limit = lim_hold(p->p_limit);
Index: sys/kern/kern_vps.c
===================================================================
--- sys/kern/kern_vps.c
+++ sys/kern/kern_vps.c
@@ -276,7 +276,14 @@
SDT_PROBE2(vps, functions, vps_destroy, entry, __LINE__, vps);
VPS_LIST_WLOCK();
+ if (vps->vps_le.le_prev == NULL && vps->vps_le.le_next == NULL) {
+ VPS_LIST_WUNLOCK();
+ DELAY(10000);
+ return;
+ }
LIST_REMOVE(vps, vps_le);
+ vps->vps_le.le_prev = NULL;
+ vps->vps_le.le_next = NULL;
VPS_LIST_WUNLOCK();
CURVPS_SET_QUIET(vps);
Index: sys/kern/subr_pcpu.c
===================================================================
--- sys/kern/subr_pcpu.c
+++ sys/kern/subr_pcpu.c
@@ -378,6 +378,7 @@
#ifdef VIMAGE
db_printf("curvnet = %p\n", pc->pc_curthread->td_vnet);
+ db_printf("curvps = %p\n", pc->pc_curthread->td_vps);
#endif
#ifdef WITNESS
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -1065,6 +1065,7 @@
int fork1(struct thread *, struct fork_req *);
void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);
+int fork_findpid(int);
void fork_return(struct thread *, struct trapframe *);
int inferior(struct proc *p);
void kern_proc_vmmap_resident(struct vm_map *map, struct vm_map_entry *entry,
Index: sys/vm/vm_swapout.c
===================================================================
--- sys/vm/vm_swapout.c
+++ sys/vm/vm_swapout.c
@@ -656,6 +656,13 @@
int ppri, pri, slptime, swtime;
loop:
+#ifdef VIMAGE
+ if (!IS_DEFAULT_VPS(curvps) && V_vpsdying > 0) {
+ V_vproc0 = NULL;
+ return;
+ }
+#endif
+
if (vm_page_count_min()) {
vm_wait_min();
goto loop;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Oct 19, 3:01 AM (9 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30507266
Default Alt Text
D15865.1792378902.diff (32 KB)
Attached To
Mode
D15865: Provide process space virtualisation functionality for jails.
Attached
Detach File
Event Timeline
Log In to Comment