Page MenuHomeFreeBSD

D59748.diff
No OneTemporary

D59748.diff

diff --git a/sbin/init/init.c b/sbin/init/init.c
--- a/sbin/init/init.c
+++ b/sbin/init/init.c
@@ -193,9 +193,10 @@
{
state_t initial_transition = runcom;
char kenv_value[PATH_MAX];
- int c, error;
+ int c, error, jailed;
struct sigaction sa;
sigset_t mask;
+ size_t len;
/* Dispose of random users. */
if (getuid() != 0)
@@ -254,10 +255,14 @@
*/
openlog("init", LOG_CONS, LOG_AUTH);
+ /* Are we running insude a jail? */
+ len = sizeof(jailed);
+ (void)sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0);
+
/*
* Create an initial session.
*/
- if (setsid() < 0 && (errno != EPERM || getsid(0) != 1))
+ if (setsid() < 0 && (errno != EPERM || (!jailed && getsid(0) != 1)))
warning("initial setsid() failed: %m");
/*
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -509,7 +509,8 @@
error = EINVAL;
break;
}
- error = pget(id, PGET_CANSEE | PGET_NOTWEXIT | PGET_NOTID, &p);
+ error = pget_cred(id, PGET_CANSEE | PGET_NOTWEXIT | PGET_NOTID,
+ td->td_ucred, &p);
if (error != 0)
break;
switch (com) {
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -961,7 +961,7 @@
startcode = 0;
startdata = 0;
}
- sbuf_printf(sb, "%d", p->p_pid);
+ sbuf_printf(sb, "%d", prison_pid(p, td->td_ucred));
#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
PS_ADD("comm", "(%s)", p->p_comm);
if (kp.ki_stat > sizeof(linux_state)) {
@@ -975,7 +975,8 @@
} else
state = linux_state[kp.ki_stat - 1];
PS_ADD("state", "%c", state);
- PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
+ PS_ADD("ppid", "%d", p->p_pptr ? prison_pid(p->p_pptr,
+ td->td_ucred) : 0);
PS_ADD("pgrp", "%d", p->p_pgid);
PS_ADD("session", "%d", p->p_session->s_sid);
PROC_UNLOCK(p);
@@ -1065,6 +1066,7 @@
struct thread *td2;
struct sigacts *ps;
l_sigset_t siglist, sigignore, sigcatch;
+ pid_t pid;
int i;
sx_slock(&proctree_lock);
@@ -1114,8 +1116,9 @@
/*
* Credentials
*/
- sbuf_printf(sb, "Tgid:\t%d\n", p->p_pid);
- sbuf_printf(sb, "Pid:\t%d\n", p->p_pid);
+ pid = prison_pid(p, td->td_ucred);
+ sbuf_printf(sb, "Tgid:\t%d\n", pid);
+ sbuf_printf(sb, "Pid:\t%d\n", pid);
sbuf_printf(sb, "PPid:\t%d\n", kp.ki_ppid );
sbuf_printf(sb, "TracerPid:\t%d\n", kp.ki_tracer );
sbuf_printf(sb, "Uid:\t%d\t%d\t%d\t%d\n", p->p_ucred->cr_ruid,
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1474,7 +1474,7 @@
linux_getpid(struct thread *td, struct linux_getpid_args *args)
{
- td->td_retval[0] = td->td_proc->p_pid;
+ td->td_retval[0] = prison_pid(td->td_proc, td->td_ucred);
return (0);
}
@@ -2098,7 +2098,7 @@
p = td->td_proc;
PHOLD(p);
} else {
- error = pget(args->pid, flags, &p);
+ error = pget_cred(args->pid, flags, td->td_ucred, &p);
if (error != 0)
return (error);
exec_blocked = true;
@@ -2445,7 +2445,7 @@
tdt = NULL;
if (tid == 0 || tid == td->td_tid) {
- if (pid != -1 && td->td_proc->p_pid != pid)
+ if (pid != -1 && prison_pid(td->td_proc, td->td_ucred) != pid)
return (NULL);
PROC_LOCK(td->td_proc);
return (td);
@@ -2455,7 +2455,7 @@
/*
* Initial thread where the tid equal to the pid.
*/
- p = pfind(tid);
+ p = pfind_cred(tid, td->td_ucred);
if (p != NULL) {
if (SV_PROC_ABI(p) != SV_ABI_LINUX ||
(pid != -1 && tid != pid)) {
@@ -2838,7 +2838,7 @@
if (td1 != NULL)
p = td1->td_proc;
} else
- p = pfind(args->who);
+ p = pfind_cred(args->who, td->td_ucred);
if (p == NULL)
return (ESRCH);
if ((error = p_cansee(td, p))) {
@@ -2942,7 +2942,7 @@
if (td1 != NULL)
p = td1->td_proc;
} else
- p = pfind(args->who);
+ p = pfind_cred(args->who, td->td_ucred);
if (p == NULL)
return (ESRCH);
if ((error = p_cansched(td, p))) {
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
--- a/sys/compat/linux/linux_signal.c
+++ b/sys/compat/linux/linux_signal.c
@@ -29,6 +29,7 @@
#include "opt_ktrace.h"
#include <sys/param.h>
+#include <sys/jail.h>
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -808,7 +809,7 @@
}
si->si_signo = sig;
- si->si_pid = td->td_proc->p_pid;
+ si->si_pid = prison_pid(td->td_proc, td->td_ucred);
si->si_uid = td->td_ucred->cr_ruid;
si->si_value.sival_ptr = PTRIN(lsi->lsi_value.sival_ptr);
return (0);
@@ -919,7 +920,7 @@
ksiginfo_init(&ksi);
ksi.ksi_signo = sig;
ksi.ksi_code = SI_LWP;
- ksi.ksi_pid = td->td_proc->p_pid;
+ ksi.ksi_pid = prison_pid(td->td_proc, td->td_ucred);
ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
return (linux_tdksignal(td, tid, tgid, sig, &ksi));
}
@@ -959,7 +960,7 @@
ksiginfo_init(&ksi);
ksi.ksi_signo = sig;
ksi.ksi_code = SI_LWP;
- ksi.ksi_pid = td->td_proc->p_pid;
+ ksi.ksi_pid = prison_pid(td->td_proc, td->td_ucred);
ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
return (linux_pksignal(td, pid, sig, &ksi));
}
diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c
--- a/sys/compat/linux/linux_time.c
+++ b/sys/compat/linux/linux_time.c
@@ -367,7 +367,7 @@
p = td->td_proc;
PROC_LOCK(p);
} else {
- error = pget(pid, PGET_CANSEE, &p);
+ error = pget_cred(pid, PGET_CANSEE, td->td_ucred, &p);
if (error != 0)
return (EINVAL);
}
@@ -584,7 +584,8 @@
case CLOCK_PROCESS_CPUTIME_ID:
pid = LINUX_CPUCLOCK_ID(which);
if (pid != 0) {
- error = pget(pid, PGET_CANSEE, &p);
+ error = pget_cred(pid, PGET_CANSEE,
+ td->td_ucred, &p);
if (error != 0)
return (EINVAL);
PROC_UNLOCK(p);
diff --git a/sys/fs/procfs/procfs.c b/sys/fs/procfs/procfs.c
--- a/sys/fs/procfs/procfs.c
+++ b/sys/fs/procfs/procfs.c
@@ -41,6 +41,7 @@
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/exec.h>
+#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
@@ -85,7 +86,7 @@
int
procfs_docurproc(PFS_FILL_ARGS)
{
- sbuf_printf(sb, "%ld", (long)td->td_proc->p_pid);
+ sbuf_printf(sb, "%ld", (long)prison_pid(td->td_proc, td->td_ucred));
return (0);
}
diff --git a/sys/i386/linux/linux_ptrace_machdep.c b/sys/i386/linux/linux_ptrace_machdep.c
--- a/sys/i386/linux/linux_ptrace_machdep.c
+++ b/sys/i386/linux/linux_ptrace_machdep.c
@@ -338,7 +338,7 @@
break;
}
- if ((p = pfind(uap->pid)) == NULL) {
+ if ((p = pfind_cred(uap->pid, td->td_ucred)) == NULL) {
error = ESRCH;
break;
}
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -702,14 +702,23 @@
/*
* List of paths to try when searching for "init".
*/
-static char init_path[MAXPATHLEN] =
-#ifdef INIT_PATH
- __XSTRING(INIT_PATH);
-#else
- "/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init";
-#endif
-SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0,
- "Path used to search for the init binary");
+static int
+sysctl_init_path(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ char tmppath[MAXPATHLEN];
+
+ pr = req->td->td_ucred->cr_prison;
+ mtx_lock(&pr->pr_mtx);
+ bcopy(pr->pr_init_path, tmppath, sizeof(tmppath));
+ mtx_unlock(&pr->pr_mtx);
+
+ return (sysctl_handle_string(oidp, tmppath, sizeof(tmppath), req));
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, init_path,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_CAPRD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_init_path, "A", "Path used to search for the init binary");
/*
* Shutdown timeout of init(8).
@@ -718,70 +727,124 @@
#ifndef INIT_SHUTDOWN_TIMEOUT
#define INIT_SHUTDOWN_TIMEOUT 120
#endif
-static int init_shutdown_timeout = INIT_SHUTDOWN_TIMEOUT;
-SYSCTL_INT(_kern, OID_AUTO, init_shutdown_timeout,
- CTLFLAG_RW, &init_shutdown_timeout, 0, "Shutdown timeout of init(8). "
+static int
+sysctl_init_shutdown_timeout(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int timeout;
+ int error;
+
+ pr = req->td->td_ucred->cr_prison;
+ mtx_lock(&pr->pr_mtx);
+ timeout = pr->pr_init_shutdown_timeout;
+ mtx_unlock(&pr->pr_mtx);
+
+ error = sysctl_handle_int(oidp, &timeout, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ sx_slock(&allprison_lock);
+ if (pr->pr_initproc == NULL)
+ error = EPERM;
+ else {
+ mtx_lock(&pr->pr_mtx);
+ pr->pr_init_shutdown_timeout = timeout;
+ mtx_unlock(&pr->pr_mtx);
+ }
+ sx_sunlock(&allprison_lock);
+ return (error);
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, init_shutdown_timeout, CTLTYPE_INT | CTLFLAG_RW |
+ CTLFLAG_PRISON | CTLFLAG_MPSAFE | CTLFLAG_CAPRD, NULL, 0,
+ sysctl_init_shutdown_timeout, "I", "Shutdown timeout of init(8). "
"Unused within kernel, but used to control init(8)");
/*
* Start the initial user process; try exec'ing each pathname in init_path.
* The program is invoked with one argument containing the boot flags.
*/
-static void
-start_init(void *dummy)
+void
+start_init(void *vpr)
{
struct image_args args;
int error;
- char *var, *path;
+ char *var, *path, *panicstr;
char *free_init_path, *tmp_init_path;
struct thread *td;
+ struct prison *pr;
struct proc *p;
struct vmspace *oldvmspace;
- TSENTER(); /* Here so we don't overlap with mi_startup. */
+ pr = vpr;
+ KASSERT(pr != &prison0, ("start_init(prison0)"));
+ if (pr == NULL)
+ TSENTER(); /* Here so we don't overlap with mi_startup. */
td = curthread;
p = td->td_proc;
- vfs_mountroot();
+ if (pr == NULL) {
+ vfs_mountroot();
- /* Wipe GELI passphrase from the environment. */
- kern_unsetenv("kern.geom.eli.passphrase");
+ /* Wipe GELI passphrase from the environment. */
+ kern_unsetenv("kern.geom.eli.passphrase");
- /* For Multicons, report which console is primary to both */
- if (boothowto & RB_MULTIPLE) {
- if (boothowto & RB_SERIAL)
- printf("Dual Console: Serial Primary, Video Secondary\n");
- else
- printf("Dual Console: Video Primary, Serial Secondary\n");
- }
+ /* For Multicons, report which console is primary to both */
+ if (boothowto & RB_MULTIPLE) {
+ if (boothowto & RB_SERIAL)
+ printf("Dual Console: Serial Primary, "
+ "Video Secondary\n");
+ else
+ printf("Dual Console: Video Primary, "
+ "Serial Secondary\n");
+ }
- if ((var = kern_getenv("init_path")) != NULL) {
- strlcpy(init_path, var, sizeof(init_path));
- freeenv(var);
- }
- free_init_path = tmp_init_path = strdup(init_path, M_TEMP);
+ if ((var = kern_getenv("init_path")) != NULL) {
+ strlcpy(prison0.pr_init_path, var,
+ sizeof(prison0.pr_init_path));
+ freeenv(var);
+ }
+ free_init_path = strdup(prison0.pr_init_path, M_TEMP);
+ } else
+ free_init_path = strdup(pr->pr_init_path, M_TEMP);
+ tmp_init_path = free_init_path;
while ((path = strsep(&tmp_init_path, ":")) != NULL) {
- if (bootverbose)
+ if (bootverbose && pr == NULL)
printf("start_init: trying %s\n", path);
memset(&args, 0, sizeof(args));
error = exec_alloc_args(&args);
- if (error != 0)
- panic("%s: Can't allocate space for init arguments %d",
- __func__, error);
-
+ if (error != 0) {
+ panicstr =
+ "%s: Can't allocate space for init arguments %d%s";
+ panic_or_exit:
+ /* Errors are fatal, but not for prisons. */
+ if (pr == NULL)
+ panic(panicstr, __func__, error, "");
+ else {
+ free(free_init_path, M_TEMP);
+ uprintf(panicstr, pr->pr_name, error, "\n");
+ exit1(td, error, 0);
+ }
+ }
error = exec_args_add_fname(&args, path, UIO_SYSSPACE);
- if (error != 0)
- panic("%s: Can't add fname %d", __func__, error);
+ if (error != 0) {
+ panicstr = "%s: Can't add fname %d%s";
+ goto panic_or_exit;
+ }
error = exec_args_add_arg(&args, path, UIO_SYSSPACE);
- if (error != 0)
- panic("%s: Can't add argv[0] %d", __func__, error);
+ if (error != 0) {
+ panicstr = "%s: Can't add argv[0] %d%s";
+ goto panic_or_exit;
+ }
if (boothowto & RB_SINGLE)
error = exec_args_add_arg(&args, "-s", UIO_SYSSPACE);
- if (error != 0)
- panic("%s: Can't add argv[0] %d", __func__, error);
+ if (error != 0) {
+ panicstr = "%s: Can't add argv[0] %d%s";
+ goto panic_or_exit;
+ }
/*
* Now try to exec the program. If can't for any reason
@@ -800,15 +863,27 @@
if (error == EJUSTRETURN) {
exec_cleanup(td, oldvmspace);
free(free_init_path, M_TEMP);
- TSEXIT();
+ if (pr == NULL)
+ TSEXIT();
return;
}
- if (error != ENOENT)
- printf("exec %s: error %d\n", path, error);
+ if (error != ENOENT) {
+ if (pr == NULL)
+ printf("exec %s: error %d\n", path, error);
+ else
+ uprintf("%s: exec %s: error %d\n",
+ pr->pr_name, path, error);
+ }
}
free(free_init_path, M_TEMP);
- printf("init: not found in path %s\n", init_path);
- panic("no init");
+ if (pr == NULL) {
+ printf("init: not found in path %s\n", prison0.pr_init_path);
+ panic("no init");
+ } else {
+ uprintf("%s: init: not found in path %s\n",
+ pr->pr_name, pr->pr_init_path);
+ exit1(td, ENOENT, 0);
+ }
}
/*
@@ -831,6 +906,15 @@
if (error)
panic("cannot fork init: %d\n", error);
KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
+ prison0.pr_initproc = initproc;
+ prison0.pr_init_shutdown_timeout = INIT_SHUTDOWN_TIMEOUT;
+ strlcpy(prison0.pr_init_path,
+#ifdef INIT_PATH
+ __XSTRING(INIT_PATH),
+#else
+ "/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init",
+#endif
+ sizeof(prison0.pr_init_path));
/* divorce init's credentials from the kernel's */
newcred = crget();
sx_xlock(&proctree_lock);
diff --git a/sys/kern/kern_cpuset.c b/sys/kern/kern_cpuset.c
--- a/sys/kern/kern_cpuset.c
+++ b/sys/kern/kern_cpuset.c
@@ -149,7 +149,7 @@
cpuset_t cpuset_domain[MAXMEMDOM];
static int cpuset_which2(cpuwhich_t *, id_t, struct proc **, struct thread **,
- struct cpuset **);
+ struct cpuset **, struct ucred *);
static int domainset_valid(const struct domainset *, const struct domainset *);
/*
@@ -895,7 +895,7 @@
*/
int
cpuset_which(cpuwhich_t which, id_t id, struct proc **pp, struct thread **tdp,
- struct cpuset **setp)
+ struct cpuset **setp, struct ucred *cred)
{
struct cpuset *set;
struct thread *td;
@@ -912,7 +912,7 @@
p = curproc;
break;
}
- if ((p = pfind(id)) == NULL)
+ if ((p = pfind_cred(id, cred)) == NULL)
return (ESRCH);
break;
case CPU_WHICH_TID:
@@ -938,7 +938,7 @@
return (ESRCH);
p = td->td_proc;
} else {
- p = pfind(id);
+ p = pfind_cred(id, cred);
if (p == NULL)
return (ESRCH);
}
@@ -990,7 +990,7 @@
static int
cpuset_which2(cpuwhich_t *which, id_t id, struct proc **pp, struct thread **tdp,
- struct cpuset **setp)
+ struct cpuset **setp, struct ucred *cred)
{
if (*which == CPU_WHICH_TIDPID) {
@@ -999,7 +999,7 @@
else
*which = CPU_WHICH_PID;
}
- return (cpuset_which(*which, id, pp, tdp, setp));
+ return (cpuset_which(*which, id, pp, tdp, setp, cred));
}
static int
@@ -1241,7 +1241,7 @@
*/
static int
cpuset_setproc(pid_t pid, struct cpuset *set, cpuset_t *mask,
- struct domainset *domain, bool rebase)
+ struct domainset *domain, struct ucred* cred, bool rebase)
{
struct setlist freelist;
struct setlist droplist;
@@ -1270,7 +1270,7 @@
if (set != NULL)
nroot = cpuset_getroot(set);
for (;;) {
- error = cpuset_which(CPU_WHICH_PID, pid, &p, &td, &nset);
+ error = cpuset_which(CPU_WHICH_PID, pid, &p, &td, &nset, cred);
if (error)
goto out;
tdroot = cpuset_getroot(td->td_cpuset);
@@ -1515,7 +1515,7 @@
cpuset_freelist_init(&cpusets, 1);
domainset_freelist_init(&domainlist, domain != NULL);
- error = cpuset_which(CPU_WHICH_TID, id, &p, &td, &set);
+ error = cpuset_which(CPU_WHICH_TID, id, &p, &td, &set, NULL);
if (error)
goto out;
set = NULL;
@@ -1751,7 +1751,7 @@
KASSERT(set != NULL, ("[%s:%d] invalid set", __func__, __LINE__));
cpuset_ref(set);
- error = cpuset_setproc(p->p_pid, set, NULL, NULL, true);
+ error = cpuset_setproc(p->p_pid, set, NULL, NULL, NULL, true);
if (error)
return (error);
cpuset_rel(set);
@@ -1858,7 +1858,7 @@
return (error);
error = copyout(&set->cs_id, uap->setid, sizeof(set->cs_id));
if (error == 0)
- error = cpuset_setproc(-1, set, NULL, NULL, false);
+ error = cpuset_setproc(-1, set, NULL, NULL, NULL, false);
cpuset_rel(set);
return (error);
}
@@ -1892,7 +1892,7 @@
set = cpuset_lookup(setid, td);
if (set == NULL)
return (ESRCH);
- error = cpuset_setproc(id, set, NULL, NULL, false);
+ error = cpuset_setproc(id, set, NULL, NULL, td->td_ucred, false);
cpuset_rel(set);
return (error);
}
@@ -1926,7 +1926,7 @@
if (level == CPU_LEVEL_WHICH && which != CPU_WHICH_CPUSET)
return (EINVAL);
- error = cpuset_which(which, id, &p, &ttd, &set);
+ error = cpuset_which(which, id, &p, &ttd, &set, td->td_ucred);
if (error)
return (error);
switch (which) {
@@ -1994,7 +1994,7 @@
error = cpuset_check_capabilities(td, level, which, id);
if (error != 0)
return (error);
- error = cpuset_which2(&which, id, &p, &ttd, &set);
+ error = cpuset_which2(&which, id, &p, &ttd, &set, td->td_ucred);
if (error != 0)
return (error);
switch (level) {
@@ -2150,7 +2150,7 @@
switch (level) {
case CPU_LEVEL_ROOT:
case CPU_LEVEL_CPUSET:
- error = cpuset_which(which, id, &p, &ttd, &set);
+ error = cpuset_which(which, id, &p, &ttd, &set, td->td_ucred);
if (error)
break;
switch (which) {
@@ -2185,18 +2185,20 @@
error = cpuset_setthread(id, mask);
break;
case CPU_WHICH_PID:
- error = cpuset_setproc(id, NULL, mask, NULL, false);
+ error = cpuset_setproc(id, NULL, mask, NULL,
+ td->td_ucred, false);
break;
case CPU_WHICH_TIDPID:
if (id > PID_MAX || id == -1)
error = cpuset_setthread(id, mask);
else
error = cpuset_setproc(id, NULL, mask, NULL,
- false);
+ td->td_ucred, false);
break;
case CPU_WHICH_CPUSET:
case CPU_WHICH_JAIL:
- error = cpuset_which(which, id, &p, &ttd, &set);
+ error = cpuset_which(which, id, &p, &ttd, &set,
+ td->td_ucred);
if (error == 0) {
error = cpuset_modify(set, mask);
cpuset_rel(set);
@@ -2302,7 +2304,7 @@
return (error);
mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO);
bzero(&outset, sizeof(outset));
- error = cpuset_which2(&which, id, &p, &ttd, &set);
+ error = cpuset_which2(&which, id, &p, &ttd, &set, td->td_ucred);
if (error)
goto out;
switch (level) {
@@ -2498,7 +2500,7 @@
switch (level) {
case CPU_LEVEL_ROOT:
case CPU_LEVEL_CPUSET:
- error = cpuset_which(which, id, &p, &ttd, &set);
+ error = cpuset_which(which, id, &p, &ttd, &set, td->td_ucred);
if (error)
break;
switch (which) {
@@ -2534,18 +2536,20 @@
error = _cpuset_setthread(id, NULL, &domain);
break;
case CPU_WHICH_PID:
- error = cpuset_setproc(id, NULL, NULL, &domain, false);
+ error = cpuset_setproc(id, NULL, NULL, &domain,
+ td->td_ucred, false);
break;
case CPU_WHICH_TIDPID:
if (id > PID_MAX || id == -1)
error = _cpuset_setthread(id, NULL, &domain);
else
error = cpuset_setproc(id, NULL, NULL, &domain,
- false);
+ td->td_ucred, false);
break;
case CPU_WHICH_CPUSET:
case CPU_WHICH_JAIL:
- error = cpuset_which(which, id, &p, &ttd, &set);
+ error = cpuset_which(which, id, &p, &ttd, &set,
+ td->td_ucred);
if (error == 0) {
error = cpuset_modify_domain(set, &domain);
cpuset_rel(set);
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1320,7 +1320,8 @@
ret = 0;
if (pgid > 0) {
- ret = pget(pgid, PGET_NOTWEXIT | PGET_NOTID | PGET_HOLD, &proc);
+ ret = pget_cred(pgid, PGET_NOTWEXIT | PGET_NOTID | PGET_HOLD,
+ sigio->sio_ucred, &proc);
SIGIO_LOCK();
osigio = funsetown_locked(*sigiop);
if (ret == 0) {
@@ -4716,7 +4717,7 @@
PROC_UNLOCK(p);
continue;
}
- xf.xf_pid = p->p_pid;
+ xf.xf_pid = prison_pid(p, req->td->td_ucred);
xf.xf_uid = p->p_ucred->cr_uid;
fdp = fdhold(p);
PROC_UNLOCK(p);
@@ -5056,7 +5057,8 @@
sbuf_new_for_sysctl(&sb, NULL, FILEDESC_SBUF_SIZE, req);
sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
- error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT,
+ req->td->td_ucred, &p);
if (error != 0) {
sbuf_delete(&sb);
return (error);
@@ -5139,7 +5141,8 @@
return (EINVAL);
name = (int *)arg1;
- error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT,
+ req->td->td_ucred, &p);
if (error != 0)
return (error);
fdp = fdhold(p);
@@ -5292,7 +5295,8 @@
sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_file), req);
sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
- error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT,
+ req->td->td_ucred, &p);
if (error != 0) {
sbuf_delete(&sb);
return (error);
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -454,9 +454,9 @@
exiting = immediate = false;
if (kn->kn_sfflags & (NOTE_EXIT | NOTE_REAP))
- p = pfind_any(kn->kn_id);
+ p = pfind_any_cred(kn->kn_id, curthread->td_ucred);
else
- p = pfind(kn->kn_id);
+ p = pfind_cred(kn->kn_id, curthread->td_ucred);
if (p == NULL)
return (ESRCH);
if (p->p_flag & P_WEXIT)
@@ -3451,7 +3451,7 @@
compat32 = false;
#endif
- error = pget((pid_t)name[0], PGET_NOTWEXIT, &p);
+ error = pget_cred((pid_t)name[0], PGET_NOTWEXIT, td->td_ucred, &p);
if (error != 0)
return (error);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1157,7 +1157,9 @@
siginfo->si_status = p->p_xexit;
}
- siginfo->si_pid = p->p_pid;
+ // XXX p->p_ucred seems wrong, butt what else is there?
+ // Or maybe I need to massage it somewhere else.
+ siginfo->si_pid = prison_pid(p, p->p_ucred);
siginfo->si_uid = p->p_ucred->cr_uid;
/*
@@ -1207,7 +1209,7 @@
PROC_UNLOCK(p);
return (0);
case P_PID:
- if (p->p_pid != (pid_t)id) {
+ if (prison_pid(p, td->td_ucred) != (pid_t)id) {
PROC_UNLOCK(p);
return (0);
}
@@ -1480,7 +1482,7 @@
loop_locked:
nfound = 0;
LIST_FOREACH(p, &q->p_children, p_sibling) {
- pid = p->p_pid;
+ pid = prison_pid(p, td->td_ucred);
ret = proc_to_reap(td, p, idtype, id, status, options,
wrusage, siginfo, false);
if (ret == 0)
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -514,7 +514,8 @@
} else {
id = ie->ie_thread->it_thread->td_tid;
mtx_unlock(&ie->ie_lock);
- error = cpuset_which(CPU_WHICH_TID, id, &p, &td, NULL);
+ error = cpuset_which(CPU_WHICH_TID, id, &p, &td, NULL,
+ NULL);
if (error != 0)
return (error);
CPU_COPY(&td->td_cpuset->cs_mask, mask);
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -58,15 +58,19 @@
#include <sys/mutex.h>
#include <sys/racct.h>
#include <sys/rctl.h>
+#include <sys/reboot.h>
#include <sys/refcount.h>
#include <sys/sx.h>
#include <sys/sysent.h>
#include <sys/namei.h>
#include <sys/mount.h>
#include <sys/queue.h>
+#include <sys/sched.h>
#include <sys/socket.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
+#include <sys/unistd.h>
+#include <sys/user.h>
#include <sys/uuid.h>
#include <sys/vnode.h>
@@ -203,6 +207,7 @@
#ifdef INET6
{"ip6.saddrsel", "ip6.nosaddrsel", PR_IP6_SADDRSEL},
#endif
+ {"init", "noinit", PR_INIT},
};
const size_t pr_flag_bool_size = sizeof(pr_flag_bool);
@@ -1023,7 +1028,7 @@
struct ucred *jdcred;
struct vnode *root;
char *domain, *errmsg, *host, *name, *namelc, *p, *path, *uuid;
- char *g_path, *osrelstr;
+ char *g_path, *init_path, *osrelstr;
struct bool_flags *bf;
struct jailsys_flags *jsf;
#if defined(INET) || defined(INET6)
@@ -1037,9 +1042,9 @@
#endif
int created, cuflags, descend, drflags, enforce;
int error, errmsg_len, errmsg_pos;
- int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel;
+ int gotchildmax, gotenforce, gotinitto, gothid, gotrsnum, gotslevel;
int deadid, jfd_in, jfd_out, jfd_pos, jid, jsys, len, level;
- int childmax, osreldt, rsnum, slevel;
+ int childmax, initto, osreldt, rsnum, slevel;
#ifdef INET
int ip4s;
bool redo_ip4;
@@ -1241,11 +1246,16 @@
ch_flags |= jsf->new | jsf->disable;
}
if ((flags & (JAIL_CREATE | JAIL_ATTACH)) == JAIL_CREATE
- && !(pr_flags & PR_PERSIST)) {
+ && !(pr_flags & (PR_PERSIST | PR_INIT))) {
error = EINVAL;
vfs_opterror(opts, "new jail must persist or attach");
goto done_errmsg;
}
+ if ((flags & JAIL_ATTACH) && (ch_flags & PR_INIT)) {
+ error = EINVAL;
+ vfs_opterror(opts, "cannot both attach and set init");
+ goto done_errmsg;
+ }
#ifdef VIMAGE
if ((flags & JAIL_UPDATE) && (ch_flags & PR_VNET)) {
error = EINVAL;
@@ -1527,6 +1537,34 @@
VOP_UNLOCK(root);
}
+ error = vfs_getopt(opts, "init.path", (void **)&init_path, &len);
+ if (error == ENOENT)
+ init_path = NULL;
+ else if (error != 0)
+ goto done_free;
+ else {
+ if (len == 0 || init_path[len - 1] != '\0') {
+ error = EINVAL;
+ goto done_free;
+ }
+ if (len >= MAXPATHLEN) {
+ error = ENAMETOOLONG;
+ vfs_opterror(opts,
+ "init.path string must be 1-%d bytes long",
+ MAXPATHLEN - 1);
+ goto done_errmsg;
+ }
+ }
+
+ error =
+ vfs_copyopt(opts, "init.shutdown_timeout", &initto, sizeof(initto));
+ if (error == ENOENT)
+ gotinitto = 0;
+ else if (error != 0)
+ goto done_free;
+ else
+ gotinitto = 1;
+
/*
* Find the specified jail, or at least its parent.
* This abuses the file error codes ENOENT and EEXIST.
@@ -2189,6 +2227,25 @@
}
}
}
+ if (init_path != NULL)
+ strlcpy(pr->pr_init_path, init_path, sizeof(pr->pr_init_path));
+ if (gotinitto)
+ pr->pr_init_shutdown_timeout = initto;
+ if ((pr_flags & PR_INIT) != 0 && (pr->pr_init_path[0] == '\0' ||
+ pr->pr_init_shutdown_timeout == 0)) {
+ /* Pull default init parameters from an ancestor with init. */
+ for (tpr = ppr; tpr != NULL; tpr = tpr->pr_parent)
+ if (tpr->pr_initproc != NULL) {
+ if (pr->pr_init_path[0] == '\0')
+ strlcpy(pr->pr_init_path,
+ tpr->pr_init_path,
+ sizeof(pr->pr_init_path));
+ if (pr->pr_init_shutdown_timeout == 0)
+ pr->pr_init_shutdown_timeout =
+ tpr->pr_init_shutdown_timeout;
+ break;
+ }
+ }
pr->pr_allow = (pr->pr_allow & ~ch_allow) | pr_allow;
if ((tallow = ch_allow & ~pr_allow))
prison_set_allow_locked(pr, tallow, 0);
@@ -2309,6 +2366,26 @@
pr->pr_state = PRISON_STATE_ALIVE;
}
+ /*
+ * If the prison has (or had) its own init, virtually reboot
+ * (or halt) it. This will unlock allprison_lock, meaning
+ * changes are now user-visible.
+ */
+ if (ch_flags & PR_INIT) {
+ if (!(drflags & PD_LOCKED)) {
+ mtx_lock(&pr->pr_mtx);
+ drflags |= PD_LOCKED;
+ }
+ if (((pr->pr_flags & PR_INIT) != 0) ^
+ (pr->pr_initproc != NULL)) {
+ sx_xunlock(&allprison_lock);
+ drflags &= ~PD_LIST_XLOCKED;
+ prison_boot(td, pr, pr->pr_initproc == NULL ?
+ RB_AUTOBOOT : RB_HALT);
+ drflags &= ~PD_LOCKED;
+ }
+ }
+
/*
* Attach this process to the prison if requested. This will
* unlock allprison_lock, meaning changes are now user-visible.
@@ -2884,6 +2961,19 @@
error = vfs_setopts(opts, "osrelease", pr->pr_osrelease);
if (error != 0 && error != ENOENT)
goto done;
+ error = vfs_setopts(opts, "init.path", pr->pr_init_path);
+ if (error != 0 && error != ENOENT)
+ goto done;
+ error = vfs_setopt(opts, "init.pid",
+ pr->pr_initproc ? &pr->pr_initproc->p_pid : &proc0.p_pid,
+ sizeof(proc0.p_pid));
+ if (error != 0 && error != ENOENT)
+ goto done;
+ error = vfs_setopt(opts, "init.shutdown_timeout",
+ &pr->pr_init_shutdown_timeout,
+ sizeof(pr->pr_init_shutdown_timeout));
+ if (error != 0 && error != ENOENT)
+ goto done;
#ifdef MAC
/*
@@ -3567,6 +3657,12 @@
sx_assert(&allproc_lock, SA_XLOCKED);
LIST_REMOVE(p, p_jaillist);
+ if (p == pr->pr_initproc) {
+ mtx_lock(&pr->pr_mtx);
+ if (p == pr->pr_initproc)
+ pr->pr_initproc = NULL;
+ mtx_unlock(&pr->pr_mtx);
+ }
}
static void
@@ -4009,6 +4105,136 @@
}
}
+/*
+ * Start and/or stop an init process inside a prison. The prison
+ * should be locked, and will be unlocked on return.
+ */
+int
+prison_boot(struct thread *td, struct prison *pr, int howto)
+{
+ struct fork_req fr;
+ struct proc *p, *prip;
+ struct thread *prit;
+ int drflags, error;
+ bool had_init;
+
+ mtx_assert(&pr->pr_mtx, MA_OWNED);
+ /* Make sure only one prison reboot happens at a time. */
+ if (pr->pr_flags & PR_REBOOT) {
+ mtx_unlock(&pr->pr_mtx);
+ if (td->td_ucred->cr_prison == pr) {
+ /*
+ * This comes from reboot(2), which means the
+ * prison was already running an init process,
+ * which in turn means the other should kill
+ * this thread. Kill it here just to be sure.
+ */
+ PROC_LOCK(td->td_proc);
+ kern_psignal(td->td_proc, SIGKILL);
+ PROC_UNLOCK(td->td_proc);
+ return (EPERM);
+ } else {
+ /*
+ * The operation we want is either already
+ * being done by another process, or there's
+ * more than a two-way race and the desired
+ * operation no longer applies. Either way,
+ * there's nothing to do, so report success.
+ */
+ return (0);
+ }
+ }
+ pr->pr_flags |= PR_REBOOT;
+ had_init = pr->pr_initproc != NULL;
+ pr->pr_initproc = NULL;
+ prison_hold(pr);
+ mtx_unlock(&pr->pr_mtx);
+ if (had_init) {
+ /*
+ * Kill processes belonging to this prison. The old
+ * init process is no longer special and dies with the
+ * rest. But keep the caller alive for now.
+ */
+ sx_slock(&allproc_lock);
+ LIST_FOREACH(p, &pr->pr_proclist, p_jaillist)
+ if (p != td->td_proc && p->p_state != PRS_NEW) {
+ PROC_LOCK(p);
+ kern_psignal(p, SIGKILL);
+ PROC_UNLOCK(p);
+ }
+ sx_sunlock(&allproc_lock);
+ /* Let modules clean up their environment. */
+ sx_slock(&allprison_lock);
+ shm_remove_prison(pr);
+ (void)osd_jail_call(pr, PR_METHOD_REBOOT, &howto);
+ sx_sunlock(&allprison_lock);
+ }
+ /* Create the init process, similar to create_init. */
+ error = 0;
+ prip = NULL;
+ if (!(howto & RB_HALT)) {
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFPROC | RFSTOPPED | RFNOWAIT | RFCFDG;
+ fr.fr_procp = &prip;
+ error = fork1(td, &fr);
+ if (error == 0) {
+ prit = FIRST_THREAD_IN_PROC(prip);
+ /* Atttach init to its prison. */
+ if (prit->td_ucred->cr_prison != pr) {
+ sx_slock(&allprison_lock);
+ drflags = PD_LIST_SLOCKED;
+ error = do_jail_attach(prit, pr, &drflags);
+ }
+ /* Make init special. */
+ PROC_LOCK(prip);
+ if (error == 0) {
+ pr->pr_initproc = prip;
+ prip->p_flag |= P_INMEM | P_PROTECTED;
+ prip->p_treeflag |= P_TREE_REAPER;
+ } else
+ // XXX Test if I can do this before it runs.
+ kern_psignal(prip, SIGKILL);
+ PROC_UNLOCK(prip);
+ /* Start init running. */
+ cpu_fork_kthread_handler(prit, start_init, pr);
+ thread_lock(prit);
+ TD_SET_CAN_RUN(prit);
+ sched_add(prit, SRQ_BORING);
+ }
+ }
+ /* Now the caller can safely die. */
+ if (had_init && td->td_ucred->cr_prison == pr) {
+ p = td->td_proc;
+ PROC_LOCK(p);
+ kern_psignal(p, SIGKILL);
+ PROC_UNLOCK(p);
+ }
+ mtx_lock(&pr->pr_mtx);
+ pr->pr_flags &= ~PR_REBOOT;
+ mtx_unlock(&pr->pr_mtx);
+ prison_free(pr);
+ return error;
+}
+
+/*
+ * Return a process' apparent pid, which is possibly 1 for jailed init
+ * or 0 for its parent.
+ */
+pid_t
+prison_pid(struct proc *p, struct ucred *cred)
+{
+ struct proc *prip;
+
+ prip = cred->cr_prison->pr_initproc;
+ if (prip != NULL) {
+ if (p == prip)
+ return 1;
+ if (p == prip->p_pptr)
+ return 0;
+ }
+ return p->p_pid;
+}
+
/*
* Check if a jail supports the given address family.
*
@@ -4819,6 +5045,12 @@
*/
return (0);
+ case PRIV_REBOOT:
+ /* Jailed init implies a prison reboot, not a real one. */
+ if (cred->cr_prison->pr_initproc != NULL)
+ return (0);
+ return (EPERM);
+
default:
/*
* In all remaining cases, deny the privilege request. This
@@ -5263,6 +5495,16 @@
"primary jail IPv6 address.");
#endif
+SYSCTL_JAIL_PARAM_NODE(init, "Jailed init process");
+SYSCTL_JAIL_PARAM(_init, , CTLTYPE_INT | CTLFLAG_RW,
+ "B", "Jailed init process");
+SYSCTL_JAIL_PARAM(_init, pid, CTLTYPE_INT | CTLFLAG_RD,
+ "I", "Jailed init process id");
+SYSCTL_JAIL_PARAM_STRING(_init, path, CTLFLAG_RW, MAXPATHLEN,
+ "Path to find jailed init");
+SYSCTL_JAIL_PARAM(_init, shutdown_timeout, CTLTYPE_INT | CTLFLAG_RW,
+ "I", "Jailed init shutdown timeout");
+
SYSCTL_JAIL_PARAM_NODE(allow, "Jail permission flags");
SYSCTL_JAIL_PARAM(_allow, set_hostname, CTLTYPE_INT | CTLFLAG_RW,
"B", "Jail may set hostname");
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -1201,7 +1201,7 @@
/*
* by pid
*/
- p = pfind(uap->pid);
+ p = pfind_cred(uap->pid, td->td_ucred);
if (p == NULL) {
error = ESRCH;
sx_sunlock(&proctree_lock);
@@ -1360,6 +1360,7 @@
static void
ktr_writerequest(struct thread *td, struct ktr_request *req)
{
+ // XXX This might be the right place and context to convert ktr_pid.
struct ktr_io_params *kiop, *kiop1;
struct ktr_header *kth;
struct vnode *vp;
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -442,8 +442,9 @@
* testing for that condition to avoid dereferencing p_ucred, et al.
*/
static __always_inline struct proc *
-_pfind(pid_t pid, bool zombie)
+_pfind(pid_t pid, struct ucred *cred, bool zombie)
{
+ struct prison *pr;
struct proc *p;
p = curproc;
@@ -451,6 +452,15 @@
PROC_LOCK(p);
return (p);
}
+ if (pid == 1 && cred != NULL) {
+ pr = cred->cr_prison;
+ if (pr != &prison0 && pr->pr_initproc != NULL) {
+ prison_lock(pr);
+ if (pr->pr_initproc != NULL)
+ pid = pr->pr_initproc->p_pid;
+ prison_unlock(pr);
+ }
+ }
sx_slock(PIDHASHLOCK(pid));
LIST_FOREACH(p, PIDHASH(pid), p_hash) {
if (p->p_pid == pid) {
@@ -471,7 +481,7 @@
pfind(pid_t pid)
{
- return (_pfind(pid, false));
+ return (_pfind(pid, NULL, false));
}
/*
@@ -481,7 +491,24 @@
pfind_any(pid_t pid)
{
- return (_pfind(pid, true));
+ return (_pfind(pid, NULL, true));
+}
+
+/*
+ * Like pfind, but jailed creds can find a jailed init for pid 1.
+ */
+struct proc *
+pfind_cred(pid_t pid, struct ucred *cred)
+{
+
+ return (_pfind(pid, cred, false));
+}
+
+struct proc *
+pfind_any_cred(pid_t pid, struct ucred *cred)
+{
+
+ return (_pfind(pid, cred, true));
}
/*
@@ -508,7 +535,7 @@
* Locate process and do additional manipulations, depending on flags.
*/
int
-pget(pid_t pid, int flags, struct proc **pp)
+pget_cred(pid_t pid, int flags, struct ucred* cred, struct proc **pp)
{
struct proc *p;
struct thread *td1;
@@ -521,9 +548,9 @@
p = NULL;
if (pid <= PID_MAX) {
if ((flags & PGET_NOTWEXIT) == 0)
- p = pfind_any(pid);
+ p = pfind_any_cred(pid, cred);
else
- p = pfind(pid);
+ p = pfind_cred(pid, cred);
} else if ((flags & PGET_NOTID) == 0) {
td1 = tdfind(pid, -1);
if (td1 != NULL)
@@ -569,6 +596,12 @@
return (error);
}
+int
+pget(pid_t pid, int flags, struct proc **pp)
+{
+ return pget_cred(pid, flags, NULL, pp);
+}
+
/*
* Create a new process group.
* pgid must be equal to the pid of p.
@@ -582,6 +615,7 @@
sx_assert(&proctree_lock, SX_XLOCKED);
KASSERT(pgrp != NULL, ("enterpgrp: pgrp == NULL"));
+ // XXX Make sure jailed init doesn't need this to work for pgid 1.
KASSERT(p->p_pid == pgid,
("enterpgrp: new pgrp and pid != pgid"));
KASSERT(pgfind(pgid) == NULL,
@@ -1084,6 +1118,8 @@
{
struct thread *td0;
struct ucred *cred;
+ struct prison *pr;
+ struct proc *prip;
struct sigacts *ps;
struct timeval boottime;
@@ -1103,6 +1139,7 @@
kp->ki_vmspace = p->p_vmspace;
kp->ki_flag = p->p_flag;
kp->ki_flag2 = p->p_flag2;
+ prip = NULL;
cred = p->p_ucred;
if (cred) {
kp->ki_uid = cred->cr_uid;
@@ -1126,8 +1163,12 @@
if (jailed(cred)) {
kp->ki_flag |= P_JAILED;
/* If inside the jail, use 0 as a jail ID. */
- if (cred->cr_prison != curthread->td_ucred->cr_prison)
- kp->ki_jid = cred->cr_prison->pr_id;
+ pr = curthread->td_ucred->cr_prison;
+ if (cred->cr_prison != pr)
+ kp->ki_jid = pr->pr_id;
+ // XXX This looks like a case where I want to find
+ // an ancestor initproc.
+ prip = pr->pr_initproc;
}
strlcpy(kp->ki_loginclass, cred->cr_loginclass->lc_name,
sizeof(kp->ki_loginclass));
@@ -1157,7 +1198,7 @@
kp->ki_sflag = PS_INMEM;
/* Calculate legacy swtime as seconds since 'swtick'. */
kp->ki_swtime = (ticks - p->p_swtick) / hz;
- kp->ki_pid = p->p_pid;
+ kp->ki_pid = p == prip ? 1 : p->p_pid;
kp->ki_nice = p->p_nice;
kp->ki_fibnum = p->p_fibnum;
kp->ki_start = p->p_stats->p_start;
@@ -1186,7 +1227,8 @@
kp->ki_acflag = p->p_acflag;
kp->ki_lock = p->p_lock;
if (p->p_pptr) {
- kp->ki_ppid = p->p_oppid;
+ kp->ki_ppid = p == prip ? 0 :
+ prip != NULL && p->p_oppid == prip->p_pid ? 1 : p->p_oppid;
if (p->p_flag & P_TRACED)
kp->ki_tracer = p->p_pptr->p_pid;
}
@@ -1237,6 +1279,7 @@
kp->ki_tdev = NODEV;
kp->ki_tdev_freebsd11 = kp->ki_tdev; /* truncate */
}
+ // XXX I probably need to tweak this, but when and under what cred?
kp->ki_reaper = p->p_reaper->p_pid;
kp->ki_reapsubtree = p->p_reapsubtree;
}
@@ -1759,7 +1802,8 @@
if (error)
return (error);
sx_slock(&proctree_lock);
- error = pget((pid_t)name[0], PGET_CANSEE, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANSEE,
+ req->td->td_ucred, &p);
if (error == 0)
error = sysctl_out_proc(p, req, flags);
sx_sunlock(&proctree_lock);
@@ -2159,14 +2203,14 @@
* If the query is for this process and it is single-threaded, there
* is nobody to modify pargs, thus we can just read.
*/
- if (pid == p->p_pid && p->p_numthreads == 1 && req->newptr == NULL &&
- (pa = p->p_args) != NULL)
+ if (pid == prison_pid(p, p->p_ucred) && p->p_numthreads == 1 &&
+ req->newptr == NULL && (pa = p->p_args) != NULL)
return (SYSCTL_OUT(req, pa->ar_args, pa->ar_length));
flags = PGET_CANSEE;
if (req->newptr != NULL)
flags |= PGET_ISCURRENT;
- error = pget(pid, flags, &p);
+ error = pget_cred(pid, flags, p->p_ucred, &p);
if (error)
return (error);
@@ -2233,7 +2277,7 @@
if (namelen != 1)
return (EINVAL);
- error = pget((pid_t)name[0], PGET_WANTREAD, &p);
+ error = pget_cred((pid_t)name[0], PGET_WANTREAD, req->td->td_ucred, &p);
if (error != 0)
return (error);
if ((p->p_flag & P_SYSTEM) != 0) {
@@ -2266,7 +2310,7 @@
if (namelen != 1)
return (EINVAL);
- error = pget((pid_t)name[0], PGET_WANTREAD, &p);
+ error = pget_cred((pid_t)name[0], PGET_WANTREAD, req->td->td_ucred, &p);
if (error != 0)
return (error);
if ((p->p_flag & P_SYSTEM) != 0) {
@@ -2375,7 +2419,7 @@
p = req->td->td_proc;
PROC_LOCK(p);
} else {
- error = pget(*pidp, PGET_CANSEE, &p);
+ error = pget_cred(*pidp, PGET_CANSEE, req->td->td_ucred, &p);
}
if (error == 0)
@@ -2402,7 +2446,7 @@
return (EINVAL);
name = (int *)arg1;
- error = pget((pid_t)name[0], PGET_CANSEE, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANSEE, req->td->td_ucred, &p);
if (error != 0)
return (error);
sv_name = p->p_sysent->sv_name;
@@ -2437,7 +2481,7 @@
name = (int *)arg1;
td = curthread;
- error = pget((pid_t)name[0], PGET_WANTREAD, &p);
+ error = pget_cred((pid_t)name[0], PGET_WANTREAD, td->td_ucred, &p);
if (error != 0)
return (error);
error = proc_vmspace_ref(td, p, PRVM_CHECK_DEBUG, &vm);
@@ -2845,7 +2889,8 @@
name = (int *)arg1;
sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_vmentry), req);
sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
- error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT,
+ req->td->td_ucred, &p);
if (error != 0) {
sbuf_delete(&sb);
return (error);
@@ -2875,7 +2920,7 @@
name = (int *)arg1;
ctd = curthread;
- error = pget((pid_t)name[0], PGET_WANTREAD, &p);
+ error = pget_cred((pid_t)name[0], PGET_WANTREAD, ctd->td_ucred, &p);
if (error != 0)
return (error);
@@ -2967,7 +3012,7 @@
p = req->td->td_proc;
PROC_LOCK(p);
} else {
- error = pget(*pidp, PGET_CANSEE, &p);
+ error = pget_cred(*pidp, PGET_CANSEE, req->td->td_ucred, &p);
if (error != 0)
return (error);
}
@@ -3010,7 +3055,7 @@
return (EINVAL);
td = curthread;
- error = pget((pid_t)name[0], PGET_NOTWEXIT, &p);
+ error = pget_cred((pid_t)name[0], PGET_NOTWEXIT, td->td_ucred, &p);
if (error != 0)
return (error);
_PHOLD(p);
@@ -3068,7 +3113,7 @@
if (namelen != 1)
return (EINVAL);
- error = pget((pid_t)name[0], PGET_CANDEBUG, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANDEBUG, req->td->td_ucred, &p);
if (error != 0)
return (error);
#ifdef COMPAT_FREEBSD32
@@ -3108,12 +3153,12 @@
pid = (pid_t)name[0];
p = curproc;
- if (pid == p->p_pid || pid == 0) {
+ if (pid == prison_pid(p, p->p_ucred) || pid == 0) {
cmask = p->p_pd->pd_cmask;
goto out;
}
- error = pget(pid, PGET_WANTREAD, &p);
+ error = pget_cred(pid, PGET_WANTREAD, p->p_ucred, &p);
if (error != 0)
return (error);
@@ -3152,7 +3197,7 @@
} else {
flags |= PGET_CANSEE;
}
- error = pget((pid_t)name[0], flags, &p);
+ error = pget_cred((pid_t)name[0], flags, req->td->td_ucred, &p);
if (error != 0)
return (error);
if ((p->p_flag & P_INEXEC) != 0) {
@@ -3185,7 +3230,7 @@
if (namelen != 1)
return (EINVAL);
- error = pget((pid_t)name[0], PGET_CANDEBUG, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANDEBUG, req->td->td_ucred, &p);
if (error != 0)
return (error);
sv = p->p_sysent;
@@ -3244,7 +3289,8 @@
return (EINVAL);
pid = (pid_t)name[0];
- error = pget(pid, PGET_HOLD | PGET_NOTWEXIT | PGET_CANDEBUG, &p);
+ error = pget_cred(pid, PGET_HOLD | PGET_NOTWEXIT | PGET_CANDEBUG,
+ req->td->td_ucred, &p);
if (error != 0)
return (error);
@@ -3311,7 +3357,7 @@
return (EINVAL);
td = curthread;
- error = pget((pid_t)name[0], PGET_CANDEBUG, &p);
+ error = pget_cred((pid_t)name[0], PGET_CANDEBUG, td->td_ucred, &p);
if (error != 0)
return (error);
#ifdef COMPAT_FREEBSD32
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -33,6 +33,7 @@
#include <sys/_unrhdr.h>
#include <sys/systm.h>
#include <sys/capsicum.h>
+#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mman.h>
@@ -186,7 +187,7 @@
rs->rs_flags |= REAPER_STATUS_OWNED;
if (reap == initproc)
rs->rs_flags |= REAPER_STATUS_REALINIT;
- rs->rs_reaper = reap->p_pid;
+ rs->rs_reaper = prison_pid(reap, td->td_ucred);
rs->rs_descendants = 0;
rs->rs_children = 0;
if (!LIST_EMPTY(&reap->p_reaplist)) {
@@ -653,7 +654,7 @@
("%d traced but tracing disabled", p->p_pid));
*status = -1;
} else if ((p->p_flag & P_TRACED) != 0) {
- *status = p->p_pptr->p_pid;
+ *status = prison_pid(p->p_pptr, td->td_ucred);
} else {
*status = 0;
}
@@ -1260,7 +1261,7 @@
error = 0;
PROC_LOCK(p);
} else {
- p = pfind(id);
+ p = pfind_cred(id, td->td_ucred);
if (p == NULL) {
error = cmd_info->esrch_is_einval ?
EINVAL : ESRCH;
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -131,7 +131,7 @@
{
struct proc *p = td->td_proc;
- td->td_retval[0] = p->p_pid;
+ td->td_retval[0] = prison_pid(p, td->td_ucred);
#if defined(COMPAT_43)
if (SV_PROC_FLAG(p, SV_AOUT))
td->td_retval[1] = kern_getppid(td);
@@ -157,8 +157,10 @@
kern_getppid(struct thread *td)
{
struct proc *p = td->td_proc;
+ struct proc *prip = td->td_ucred->cr_prison->pr_initproc;
- return (p->p_oppid);
+ return (p == prip ? 0 :
+ prip && p->p_oppid == prip->p_pid ? 1 : p->p_oppid);
}
/*
@@ -196,7 +198,7 @@
p = td->td_proc;
PROC_LOCK(p);
} else {
- p = pfind_any(uap->pid);
+ p = pfind_any_cred(uap->pid, td->td_ucred);
if (p == NULL)
return (ESRCH);
error = p_cansee(td, p);
@@ -236,7 +238,7 @@
p = td->td_proc;
PROC_LOCK(p);
} else {
- p = pfind_any(pid);
+ p = pfind_any_cred(pid, td->td_ucred);
if (p == NULL)
return (ESRCH);
error = p_cansee(td, p);
@@ -405,6 +407,8 @@
PGRP_UNLOCK(pgrp);
error = EPERM;
} else {
+ // XXX Jailed init would get a non-1 sid, and return that.
+ // Can it handle that? Does it need to?
error = enterpgrp(p, p->p_pid, newpgrp, newsess);
if (error == ERESTART)
goto again;
@@ -460,8 +464,8 @@
error = 0;
sx_xlock(&proctree_lock);
- if (uap->pid != 0 && uap->pid != curp->p_pid) {
- if ((targp = pfind(uap->pid)) == NULL) {
+ if (uap->pid != 0 && uap->pid != prison_pid(curp, td->td_ucred)) {
+ if ((targp = pfind_cred(uap->pid, td->td_ucred)) == NULL) {
error = ESRCH;
goto done;
}
@@ -493,6 +497,10 @@
goto done;
}
if (uap->pgid == 0)
+ // XXX By this point, I assume target is a descendant,
+ // and thus prison_pid is unnecessary. If target
+ // can be self, it might be best to handle that
+ // in its own block.
uap->pgid = targp->p_pid;
if ((pgrp = pgfind(uap->pgid)) == NULL) {
if (uap->pgid == targp->p_pid) {
@@ -2367,7 +2375,7 @@
return (error);
/* Can't trace init when securelevel > 0. */
- if (p == initproc) {
+ if (p == td->td_ucred->cr_prison->pr_initproc) {
error = securelevel_gt(td->td_ucred, 0);
if (error)
return (error);
@@ -2778,7 +2786,7 @@
{
cru2x(td->td_ucred, xcr);
- xcr->cr_pid = td->td_proc->p_pid;
+ xcr->cr_pid = prison_pid(td->td_proc, td->td_ucred);
}
/*
diff --git a/sys/kern/kern_rctl.c b/sys/kern/kern_rctl.c
--- a/sys/kern/kern_rctl.c
+++ b/sys/kern/kern_rctl.c
@@ -1139,7 +1139,7 @@
}
static int
-rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep)
+rctl_string_to_rule(struct thread* td, char *rulestr, struct rctl_rule **rulep)
{
struct rctl_rule *rule;
char *subjectstr, *subject_idstr, *resourcestr, *actionstr,
@@ -1181,7 +1181,7 @@
if (error != 0)
goto out;
sx_assert(&allproc_lock, SA_LOCKED);
- rule->rr_subject.rs_proc = pfind(id);
+ rule->rr_subject.rs_proc = pfind_cred(id, td->td_ucred);
if (rule->rr_subject.rs_proc == NULL) {
error = ESRCH;
goto out;
@@ -1629,7 +1629,7 @@
return (error);
sx_slock(&allproc_lock);
- error = rctl_string_to_rule(inputstr, &filter);
+ error = rctl_string_to_rule(td, inputstr, &filter);
free(inputstr, M_RCTL);
if (error != 0) {
sx_sunlock(&allproc_lock);
@@ -1724,7 +1724,7 @@
return (error);
sx_slock(&allproc_lock);
- error = rctl_string_to_rule(inputstr, &filter);
+ error = rctl_string_to_rule(td, inputstr, &filter);
free(inputstr, M_RCTL);
if (error != 0) {
sx_sunlock(&allproc_lock);
@@ -1809,7 +1809,7 @@
return (error);
sx_slock(&allproc_lock);
- error = rctl_string_to_rule(inputstr, &filter);
+ error = rctl_string_to_rule(td, inputstr, &filter);
free(inputstr, M_RCTL);
if (error != 0) {
sx_sunlock(&allproc_lock);
@@ -1889,7 +1889,7 @@
return (error);
sx_slock(&allproc_lock);
- error = rctl_string_to_rule(inputstr, &rule);
+ error = rctl_string_to_rule(td, inputstr, &rule);
free(inputstr, M_RCTL);
if (error != 0) {
sx_sunlock(&allproc_lock);
@@ -1934,7 +1934,7 @@
return (error);
sx_slock(&allproc_lock);
- error = rctl_string_to_rule(inputstr, &filter);
+ error = rctl_string_to_rule(td, inputstr, &filter);
free(inputstr, M_RCTL);
if (error != 0) {
sx_sunlock(&allproc_lock);
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -40,6 +40,7 @@
#include <sys/capsicum.h>
#include <sys/file.h>
#include <sys/filedesc.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -104,7 +105,7 @@
if (IN_CAPABILITY_MODE(td)) {
if (which != PRIO_PROCESS)
return (ECAPMODE);
- if (who != 0 && who != td->td_proc->p_pid)
+ if (who != 0 && who != prison_pid(td->td_proc, td->td_ucred))
return (ECAPMODE);
}
@@ -115,7 +116,7 @@
if (who == 0)
low = td->td_proc->p_nice;
else {
- p = pfind(who);
+ p = pfind_cred(who, td->td_ucred);
if (p == NULL)
break;
if (p_cansee(td, p) == 0)
@@ -202,7 +203,7 @@
if (IN_CAPABILITY_MODE(td)) {
if (which != PRIO_PROCESS)
return (ECAPMODE);
- if (who != 0 && who != curp->p_pid)
+ if (who != 0 && who != prison_pid(curp, td->td_ucred))
return (ECAPMODE);
}
@@ -213,7 +214,7 @@
error = donice(td, curp, prio);
PROC_UNLOCK(curp);
} else {
- p = pfind(who);
+ p = pfind_cred(who, td->td_ucred);
if (p == NULL)
break;
error = p_cansee(td, p);
@@ -410,7 +411,7 @@
p = td->td_proc;
PROC_LOCK(p);
} else {
- p = pfind(uap->pid);
+ p = pfind_cred(uap->pid, td->td_ucred);
if (p == NULL)
return (ESRCH);
}
@@ -1811,7 +1812,8 @@
return (EINVAL);
td = curthread;
- error = pget((pid_t)name[0], PGET_HOLD | PGET_NOTWEXIT, &p);
+ error = pget_cred((pid_t)name[0], PGET_HOLD | PGET_NOTWEXIT,
+ td->td_ucred, &p);
if (error != 0)
return (error);
error = proc_vmspace_ref(td, p, PRVM_BLOCK_EXEC |
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -293,6 +293,7 @@
int
sys_reboot(struct thread *td, struct reboot_args *uap)
{
+ struct prison *pr;
int error;
error = 0;
@@ -302,8 +303,19 @@
if (error == 0)
error = priv_check(td, PRIV_REBOOT);
if (error == 0) {
- if (uap->opt & RB_REROOT)
+ if (uap->opt & RB_REROOT) {
+ if (jailed(td->td_ucred))
+ return (EPERM);
error = kern_reroot();
+ } else if (jailed(td->td_ucred)) {
+ pr = td->td_ucred->cr_prison;
+ prison_lock(pr);
+ if (pr->pr_initproc == NULL) {
+ prison_unlock(pr);
+ return (EPERM);
+ }
+ error = prison_boot(td, pr, uap->opt);
+ }
else
kern_reboot(uap->opt);
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1808,6 +1808,7 @@
{
if (p->p_pid <= 1 || (p->p_flag & P_SYSTEM) != 0 ||
+ p == arg->td->td_ucred->cr_prison->pr_initproc ||
(notself && p == arg->td->td_proc) || p->p_state == PRS_NEW)
return;
@@ -1822,6 +1823,7 @@
struct killpg1_ctx *ctx = arg;
if (p->p_pid <= 1 || (p->p_flag & P_SYSTEM) != 0 ||
+ p == ctx->td->td_ucred->cr_prison->pr_initproc ||
(p == ctx->td->td_proc) || p->p_state == PRS_NEW)
return;
@@ -1905,6 +1907,7 @@
{
ksiginfo_t ksi;
struct proc *p;
+ pid_t pr_pid;
int error;
/*
@@ -1912,7 +1915,8 @@
* The main rationale behind this is that abort(3) is implemented as
* kill(getpid(), SIGABRT).
*/
- if (pid != td->td_proc->p_pid) {
+ pr_pid = prison_pid(td->td_proc, td->td_ucred);
+ if (pid != pr_pid) {
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SIGNAL, &signum);
if (IN_CAPABILITY_MODE(td))
@@ -1927,12 +1931,12 @@
ksiginfo_init(&ksi);
ksi.ksi_signo = signum;
ksi.ksi_code = SI_USER;
- ksi.ksi_pid = td->td_proc->p_pid;
+ ksi.ksi_pid = pr_pid;
ksi.ksi_uid = td->td_ucred->cr_ruid;
if (pid > 0) {
/* kill single process */
- if ((p = pfind_any(pid)) == NULL)
+ if ((p = pfind_any_cred(pid, td->td_ucred)) == NULL)
return (ESRCH);
AUDIT_ARG_PROCESS(p);
error = p_cansignal(td, p, signum);
@@ -2002,7 +2006,7 @@
ksiginfo_init(&ksi);
ksi.ksi_signo = uap->signum;
ksi.ksi_code = SI_USER;
- ksi.ksi_pid = td->td_proc->p_pid;
+ ksi.ksi_pid = prison_pid(td->td_proc, td->td_ucred);
ksi.ksi_uid = td->td_ucred->cr_ruid;
return (killpg1(td, uap->signum, uap->pgid, 0, &ksi));
}
@@ -2032,6 +2036,7 @@
struct proc *p;
struct thread *td2;
u_int signum;
+ pid_t pr_pid;
int error;
signum = signumf & ~__SIGQUEUE_TID;
@@ -2048,7 +2053,8 @@
/*
* A process in capability mode can send signals only to itself.
*/
- if (pid != td->td_proc->p_pid) {
+ pr_pid = prison_pid(td->td_proc, td->td_ucred);
+ if (pid != pr_pid) {
if (CAP_TRACING(td))
ktrcapfail(CAPFAIL_SIGNAL, &signum);
if (IN_CAPABILITY_MODE(td))
@@ -2056,7 +2062,7 @@
}
if ((signumf & __SIGQUEUE_TID) == 0) {
- if ((p = pfind_any(pid)) == NULL)
+ if ((p = pfind_any_cred(pid, td->td_ucred)) == NULL)
return (ESRCH);
td2 = NULL;
} else {
@@ -2072,7 +2078,7 @@
ksi.ksi_flags = KSI_SIGQ;
ksi.ksi_signo = signum;
ksi.ksi_code = SI_QUEUE;
- ksi.ksi_pid = td->td_proc->p_pid;
+ ksi.ksi_pid = pr_pid;
ksi.ksi_uid = td->td_ucred->cr_ruid;
ksi.ksi_value = *value;
error = tdsendsignal(p, td2, ksi.ksi_signo, &ksi);
@@ -3258,6 +3264,9 @@
/*
* Don't take default actions on system processes.
*/
+ // XXX This should be true for jailed init as well, but only
+ // for signals sent by that jail's process. Catch it
+ // wherever signals are sent.
if (p->p_pid <= 1) {
#ifdef DIAGNOSTIC
/*
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -31,6 +31,7 @@
#include "opt_hwpmc_hooks.h"
#include "opt_hwt_hooks.h"
#include <sys/systm.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#ifdef KTRACE
#include <sys/ktrace.h>
@@ -426,7 +427,7 @@
ksiginfo_init(&ksi);
ksi.ksi_signo = uap->sig;
ksi.ksi_code = SI_LWP;
- ksi.ksi_pid = p->p_pid;
+ ksi.ksi_pid = prison_pid(p, td->td_ucred);
ksi.ksi_uid = td->td_ucred->cr_ruid;
if (uap->id == -1) {
if (uap->sig != 0 && !_SIG_VALID(uap->sig)) {
@@ -446,7 +447,7 @@
}
} else {
error = 0;
- ttd = tdfind((lwpid_t)uap->id, p->p_pid);
+ ttd = tdfind((lwpid_t)uap->id, ksi.ksi_pid);
if (ttd == NULL)
return (ESRCH);
if (uap->sig == 0)
@@ -474,10 +475,10 @@
ksiginfo_init(&ksi);
ksi.ksi_signo = uap->sig;
ksi.ksi_code = SI_LWP;
- ksi.ksi_pid = td->td_proc->p_pid;
+ ksi.ksi_pid = prison_pid(td->td_proc, td->td_ucred);
ksi.ksi_uid = td->td_ucred->cr_ruid;
if (uap->id == -1) {
- if ((p = pfind(uap->pid)) == NULL)
+ if ((p = pfind_cred(uap->pid, td->td_ucred)) == NULL)
return (ESRCH);
AUDIT_ARG_PROCESS(p);
error = p_cansignal(td, p, uap->sig);
@@ -592,7 +593,7 @@
}
p = td->td_proc;
- ttd = tdfind((lwpid_t)uap->id, p->p_pid);
+ ttd = tdfind((lwpid_t)uap->id, prison_pid(p, td->td_ucred));
if (ttd == NULL)
return (ESRCH);
thread_lock(ttd);
@@ -623,7 +624,7 @@
return (error);
}
p = td->td_proc;
- ttd = tdfind((lwpid_t)uap->id, p->p_pid);
+ ttd = tdfind((lwpid_t)uap->id, prison_pid(p, td->td_ucred));
if (ttd == NULL)
return (ESRCH);
strcpy(ttd->td_name, name);
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -201,7 +201,8 @@
switch (which) {
case CPUCLOCK_WHICH_PID:
if (id != 0) {
- error = pget(id, PGET_CANSEE | PGET_NOTID, &p);
+ error = pget_cred(id, PGET_CANSEE | PGET_NOTID,
+ td->td_ucred, &p);
if (error != 0)
return (error);
PROC_UNLOCK(p);
@@ -305,7 +306,7 @@
PROC_UNLOCK(td2->td_proc);
} else {
pid = clock_id & CPUCLOCK_ID_MASK;
- error = pget(pid, PGET_CANSEE, &p2);
+ error = pget_cred(pid, PGET_CANSEE, td->td_ucred, &p2);
if (error != 0)
return (EINVAL);
kern_process_cputime(p2, ats);
diff --git a/sys/kern/p1003_1b.c b/sys/kern/p1003_1b.c
--- a/sys/kern/p1003_1b.c
+++ b/sys/kern/p1003_1b.c
@@ -123,7 +123,7 @@
targettd = td;
PROC_LOCK(targetp);
} else {
- targetp = pfind(uap->pid);
+ targetp = pfind_cred(uap->pid, td->td_ucred);
if (targetp == NULL)
return (ESRCH);
targettd = FIRST_THREAD_IN_PROC(targetp);
@@ -164,7 +164,7 @@
targettd = td;
PROC_LOCK(targetp);
} else {
- targetp = pfind(uap->pid);
+ targetp = pfind_cred(uap->pid, td->td_ucred);
if (targetp == NULL) {
return (ESRCH);
}
@@ -211,7 +211,7 @@
targettd = td;
PROC_LOCK(targetp);
} else {
- targetp = pfind(uap->pid);
+ targetp = pfind_cred(uap->pid, td->td_ucred);
if (targetp == NULL)
return (ESRCH);
targettd = FIRST_THREAD_IN_PROC(targetp);
@@ -257,7 +257,7 @@
targettd = td;
PROC_LOCK(targetp);
} else {
- targetp = pfind(uap->pid);
+ targetp = pfind_cred(uap->pid, td->td_ucred);
if (targetp == NULL)
return (ESRCH);
targettd = FIRST_THREAD_IN_PROC(targetp);
@@ -343,7 +343,7 @@
targetp = td->td_proc;
PROC_LOCK(targetp);
} else {
- targetp = pfind(pid);
+ targetp = pfind_cred(pid, td->td_ucred);
if (targetp == NULL)
return (ESRCH);
targettd = FIRST_THREAD_IN_PROC(targetp);
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -519,6 +519,7 @@
{ "pmc-sleep", &lock_class_mtx_sleep },
#endif
{ "process lock", &lock_class_mtx_sleep },
+ { "jail mutex", &lock_class_mtx_sleep },
{ "session", &lock_class_mtx_sleep },
{ "uidinfo hash", &lock_class_rw },
{ "time lock", &lock_class_mtx_sleep },
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -48,6 +48,7 @@
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/inotify.h>
+#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
@@ -2179,12 +2180,12 @@
{
int error;
- if (pid == td->td_proc->p_pid) {
+ if (pid == prison_pid(td->td_proc, td->td_ucred)) {
*pp = td->td_proc;
return (0);
}
- error = pget(pid, PGET_NOTID | PGET_CANDEBUG | PGET_NOTWEXIT |
- PGET_HOLD, pp);
+ error = pget_cred(pid, PGET_NOTID | PGET_CANDEBUG | PGET_NOTWEXIT |
+ PGET_HOLD, td->td_ucred, pp);
MPASS(*pp != td->td_proc);
return (error);
}
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -658,7 +658,7 @@
sx_assert(&proctree_lock, SX_XLOCKED);
- error = pget(pid, PGET_NOTID | PGET_CANDEBUG, &p);
+ error = pget_cred(pid, PGET_NOTID | PGET_CANDEBUG, td->td_ucred, &p);
if (error != 0)
return (error);
if ((p->p_flag & (P_SYSTEM | P_WEXIT)) != 0) {
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -35,6 +35,7 @@
#include <sys/caprights.h>
#include <sys/filedesc.h>
#include <sys/imgact.h>
+#include <sys/jail.h>
#include <sys/ktr.h>
#include <sys/limits.h>
#include <sys/lock.h>
@@ -1028,7 +1029,7 @@
PROC_UNLOCK(pp);
return (false);
}
- ptc->pid = pp->p_pid;
+ ptc->pid = prison_pid(pp, td->td_ucred);
if ((pp->p_flag & P_TRACED) != 0) {
ptc->flags |= PTCHLD_TRACED;
if (pp->p_pptr == td->td_proc)
@@ -1110,7 +1111,7 @@
PROC_LOCK(p);
} else {
if (pid <= PID_MAX) {
- if ((p = pfind(pid)) == NULL) {
+ if ((p = pfind_cred(pid, td->td_ucred)) == NULL) {
if (proctree_locked)
sx_xunlock(&proctree_lock);
return (ESRCH);
@@ -1174,7 +1175,7 @@
error = EBUSY;
goto fail;
}
- if (p->p_pptr == initproc) {
+ if (p->p_pptr == td->td_ucred->cr_prison->pr_initproc) {
error = EPERM;
goto fail;
}
@@ -1530,7 +1531,7 @@
pp = proc_realparent(p);
proc_reparent(p, pp, false);
- if (pp == initproc)
+ if (pp == td->td_ucred->cr_prison->pr_initproc)
p->p_sigparent = SIGCHLD;
CTR3(KTR_PTRACE,
"PT_DETACH: pid %d reparented to pid %d, sig %d",
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -217,6 +217,7 @@
[PR_METHOD_SET] = msg_prison_set,
[PR_METHOD_GET] = msg_prison_get,
[PR_METHOD_REMOVE] = msg_prison_remove,
+ [PR_METHOD_REBOOT] = msg_prison_remove,
};
msginfo.msgmax = msginfo.msgseg * msginfo.msgssz;
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -274,6 +274,7 @@
[PR_METHOD_SET] = sem_prison_set,
[PR_METHOD_GET] = sem_prison_get,
[PR_METHOD_REMOVE] = sem_prison_remove,
+ [PR_METHOD_REBOOT] = sem_prison_remove,
};
sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK);
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -956,6 +956,7 @@
[PR_METHOD_SET] = shm_prison_set,
[PR_METHOD_GET] = shm_prison_get,
[PR_METHOD_REMOVE] = shm_prison_remove,
+ [PR_METHOD_REBOOT] = shm_prison_remove,
};
#ifndef BURN_BRIDGES
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -662,6 +662,7 @@
struct mqfs_info *mi;
osd_method_t methods[PR_MAXMETHOD] = {
[PR_METHOD_REMOVE] = mqfs_prison_remove,
+ [PR_METHOD_REBOOT] = mqfs_prison_remove,
};
mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node),
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -172,7 +172,7 @@
if (error)
return (error);
- tproc = pfind(uap->pid);
+ tproc = pfind_cred(uap->pid, td->td_ucred);
if (tproc == NULL) {
error = ESRCH;
goto free_mac_and_exit;
diff --git a/sys/security/mac_grantbylabel/mac_grantbylabel.c b/sys/security/mac_grantbylabel/mac_grantbylabel.c
--- a/sys/security/mac_grantbylabel/mac_grantbylabel.c
+++ b/sys/security/mac_grantbylabel/mac_grantbylabel.c
@@ -406,7 +406,7 @@
|| gbl_args.u.pid == curproc->p_pid) {
proc = curproc;
} else {
- proc = pfind(gbl_args.u.pid);
+ proc = pfind_cred(gbl_args.u.pid, td->td_ucred);
if (proc == NULL)
return (EINVAL);
else if (proc->p_textvp == NULL) {
diff --git a/sys/security/mac_veriexec/mac_veriexec.c b/sys/security/mac_veriexec/mac_veriexec.c
--- a/sys/security/mac_veriexec/mac_veriexec.c
+++ b/sys/security/mac_veriexec/mac_veriexec.c
@@ -947,7 +947,7 @@
if (pargs.u.pid == 0 || pargs.u.pid == curproc->p_pid) {
proc = curproc;
} else {
- proc = pfind(pargs.u.pid);
+ proc = pfind_cred(pargs.u.pid, td->td_ucred);
if (proc == NULL)
return (EINVAL);
proc_locked = 1;
diff --git a/sys/sys/cpuset.h b/sys/sys/cpuset.h
--- a/sys/sys/cpuset.h
+++ b/sys/sys/cpuset.h
@@ -154,6 +154,7 @@
struct prison;
struct proc;
struct thread;
+struct ucred;
/*
* Callbacks for copying in/out a cpuset or domainset. Used for alternate
@@ -172,7 +173,7 @@
int cpuset_create_root(struct prison *, struct cpuset **);
int cpuset_setproc_update_set(struct proc *, struct cpuset *);
int cpuset_which(cpuwhich_t, id_t, struct proc **,
- struct thread **, struct cpuset **);
+ struct thread **, struct cpuset **, struct ucred*);
void cpuset_kernthread(struct thread *);
char *cpusetobj_strprint(char *, const cpuset_t *);
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -154,6 +154,7 @@
struct knlist;
struct racct;
struct prison_racct;
+struct proc;
typedef enum {
PR_INET = 0,
@@ -168,7 +169,6 @@
*
* Lock key:
* (a) allprison_lock
- * (A) allproc_lock
* (c) set only during creation before the structure is shared, no mutex
* required to read
* (m) locked by pr_mtx
@@ -200,7 +200,7 @@
struct knlist *pr_klist; /* (m) attached knotes */
struct label *pr_label; /* (m) MAC label */
LIST_HEAD(, jaildesc) pr_descs; /* (a) attached descriptors */
- void *pr_sparep;
+ struct proc *pr_initproc; /* (m) init process */
int pr_childcount; /* (a) number of child jails */
int pr_childmax; /* (p) maximum child jails */
unsigned pr_allow; /* (p) PR_ALLOW_* flags */
@@ -209,7 +209,7 @@
int pr_devfs_rsnum; /* (p) devfs ruleset */
enum prison_state pr_state; /* (q) state in life cycle */
volatile int pr_exportcnt; /* (r) count of mount exports */
- int pr_spare;
+ int pr_init_shutdown_timeout; /* (p) kern.init_shutdown_timeout value */
int pr_osreldate; /* (c) kern.osreldate value */
unsigned long pr_hostid; /* (p) jail hostid */
char pr_name[MAXHOSTNAMELEN]; /* (p) admin jail name */
@@ -218,6 +218,7 @@
char pr_domainname[MAXHOSTNAMELEN]; /* (p) jail domainname */
char pr_hostuuid[HOSTUUIDLEN]; /* (p) jail hostuuid */
char pr_osrelease[OSRELEASELEN]; /* (c) kern.osrelease value */
+ char pr_init_path[MAXPATHLEN]; /* (p) paths to search for init */
};
struct prison_racct {
@@ -235,6 +236,8 @@
#define PR_IP4_USER 0x00000004 /* Restrict IPv4 addresses */
#define PR_IP6_USER 0x00000008 /* Restrict IPv6 addresses */
#define PR_VNET 0x00000010 /* Virtual network stack */
+#define PR_INIT 0x00000020 /* Will run an init process */
+#define PR_REBOOT 0x00000040 /* Init process is starting/stopping */
#define PR_IP4_SADDRSEL 0x00000080 /* Do IPv4 src addr sel. or use the */
/* primary jail address. */
#define PR_IP6_SADDRSEL 0x00000100 /* Do IPv6 src addr sel. or use the */
@@ -308,7 +311,8 @@
#define PR_METHOD_CHECK 3
#define PR_METHOD_ATTACH 4
#define PR_METHOD_REMOVE 5
-#define PR_MAXMETHOD 6
+#define PR_METHOD_REBOOT 6
+#define PR_MAXMETHOD 7
/*
* Lock/unlock a prison.
@@ -486,6 +490,8 @@
void prison_proc_iterate(struct prison *, void (*)(struct proc *, void *), void *);
void prison_remove(struct prison *);
void prison_set_allow(struct ucred *cred, unsigned flag, int enable);
+int prison_boot(struct thread *, struct prison *, int);
+pid_t prison_pid(struct proc *p, struct ucred *cred);
bool prison_ischild(struct prison *, struct prison *);
bool prison_isalive(const struct prison *);
bool prison_isvalid(struct prison *);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -184,6 +184,7 @@
struct kq_timer_cb_data;
struct mqueue_notifier;
struct p_sched;
+struct prison;
struct proc;
struct procdesc;
struct racct;
@@ -1122,6 +1123,8 @@
struct proc *pfind(pid_t); /* Find process by id. */
struct proc *pfind_any(pid_t); /* Find (zombie) process by id. */
struct proc *pfind_any_locked(pid_t pid); /* Find process by id, locked. */
+struct proc *pfind_cred(pid_t, struct ucred *); /* Find process by id, as seen by cred. */
+struct proc *pfind_any_cred(pid_t, struct ucred *);
struct pgrp *pgfind(pid_t); /* Find process group by id. */
void pidhash_slockall(void); /* Shared lock all pid hash lists. */
void pidhash_sunlockall(void); /* Shared unlock all pid hash lists. */
@@ -1154,6 +1157,7 @@
#define PGET_WANTREAD (PGET_HOLD | PGET_CANDEBUG | PGET_NOTWEXIT)
int pget(pid_t pid, int flags, struct proc **pp);
+int pget_cred(pid_t pid, int flags, struct ucred *cred, struct proc **pp);
/* ast_register() flags */
#define ASTR_ASTF_REQUIRED 0x0001 /* td_ast TDAI(TDA_X) flag set is
@@ -1233,6 +1237,7 @@
void setsugid(struct proc *p);
bool should_yield(void);
int sigonstack(size_t sp);
+void start_init(void *);
void stopevent(struct proc *, u_int, u_int);
struct thread *tdfind(lwpid_t, pid_t);
void threadinit(void);

File Metadata

Mime Type
text/plain
Expires
Fri, Sep 18, 12:45 PM (2 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39118362
Default Alt Text
D59748.diff (65 KB)

Event Timeline