Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F172292572
D59748.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
65 KB
Referenced Files
None
Subscribers
None
D59748.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D59748: Jail init process and virtual reboot
Attached
Detach File
Event Timeline
Log In to Comment