summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2001-02-21 06:39:57 +0000
committerrwatson <rwatson@FreeBSD.org>2001-02-21 06:39:57 +0000
commitab5676fc870d2d819cf41120313443182db079cf (patch)
tree3ed13007d645ee25bab52d52b6aba08f7f0bcf1e /sys
parent17bdecb1829f632354d48f743f10ff707edded9c (diff)
downloadFreeBSD-src-ab5676fc870d2d819cf41120313443182db079cf.zip
FreeBSD-src-ab5676fc870d2d819cf41120313443182db079cf.tar.gz
o Move per-process jail pointer (p->pr_prison) to inside of the subject
credential structure, ucred (cr->cr_prison). o Allow jail inheritence to be a function of credential inheritence. o Abstract prison structure reference counting behind pr_hold() and pr_free(), invoked by the similarly named credential reference management functions, removing this code from per-ABI fork/exit code. o Modify various jail() functions to use struct ucred arguments instead of struct proc arguments. o Introduce jailed() function to determine if a credential is jailed, rather than directly checking pointers all over the place. o Convert PRISON_CHECK() macro to prison_check() function. o Move jail() function prototypes to jail.h. o Emulate the P_JAILED flag in fill_kinfo_proc() and no longer set the flag in the process flags field itself. o Eliminate that "const" qualifier from suser/p_can/etc to reflect mutex use. Notes: o Some further cleanup of the linux/jail code is still required. o It's now possible to consider resolving some of the process vs credential based permission checking confusion in the socket code. o Mutex protection of struct prison is still not present, and is required to protect the reference count plus some fields in the structure. Reviewed by: freebsd-arch Obtained from: TrustedBSD Project
Diffstat (limited to 'sys')
-rw-r--r--sys/compat/linprocfs/linprocfs.c2
-rw-r--r--sys/compat/linprocfs/linprocfs_misc.c2
-rw-r--r--sys/compat/linux/linux_mib.c11
-rw-r--r--sys/compat/svr4/svr4_misc.c9
-rw-r--r--sys/fs/procfs/procfs_status.c4
-rw-r--r--sys/kern/init_main.c4
-rw-r--r--sys/kern/kern_exit.c9
-rw-r--r--sys/kern/kern_fork.c5
-rw-r--r--sys/kern/kern_jail.c85
-rw-r--r--sys/kern/kern_ktrace.c4
-rw-r--r--sys/kern/kern_mib.c6
-rw-r--r--sys/kern/kern_proc.c4
-rw-r--r--sys/kern/kern_prot.c47
-rw-r--r--sys/kern/sysv_msg.c10
-rw-r--r--sys/kern/sysv_sem.c8
-rw-r--r--sys/kern/sysv_shm.c12
-rw-r--r--sys/kern/tty_pty.c4
-rw-r--r--sys/kern/uipc_socket.c2
-rw-r--r--sys/kern/uipc_usrreq.c3
-rw-r--r--sys/kern/vfs_extattr.c3
-rw-r--r--sys/kern/vfs_syscalls.c3
-rw-r--r--sys/miscfs/procfs/procfs_status.c4
-rw-r--r--sys/net/if.c4
-rw-r--r--sys/net/if.h2
-rw-r--r--sys/net/rtsock.c4
-rw-r--r--sys/netinet/in.h3
-rw-r--r--sys/netinet/in_pcb.c19
-rw-r--r--sys/netinet/tcp_usrreq.c5
-rw-r--r--sys/netinet/udp_usrreq.c7
-rw-r--r--sys/sys/capability.h2
-rw-r--r--sys/sys/jail.h18
-rw-r--r--sys/sys/proc.h3
-rw-r--r--sys/sys/systm.h5
-rw-r--r--sys/sys/ucred.h1
34 files changed, 190 insertions, 124 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 749d16a..8ba6c41 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -44,7 +44,6 @@
#include <sys/param.h>
#include <sys/blist.h>
#include <sys/dkstat.h>
-#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
@@ -52,6 +51,7 @@
#include <sys/systm.h>
#include <sys/tty.h>
#include <sys/vnode.h>
+#include <sys/jail.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/compat/linprocfs/linprocfs_misc.c b/sys/compat/linprocfs/linprocfs_misc.c
index 749d16a..8ba6c41 100644
--- a/sys/compat/linprocfs/linprocfs_misc.c
+++ b/sys/compat/linprocfs/linprocfs_misc.c
@@ -44,7 +44,6 @@
#include <sys/param.h>
#include <sys/blist.h>
#include <sys/dkstat.h>
-#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
@@ -52,6 +51,7 @@
#include <sys/systm.h>
#include <sys/tty.h>
#include <sys/vnode.h>
+#include <sys/jail.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
index 8482dd9..35d4a25 100644
--- a/sys/compat/linux/linux_mib.c
+++ b/sys/compat/linux/linux_mib.c
@@ -117,10 +117,11 @@ get_prison(struct proc *p)
register struct prison *pr;
register struct linux_prison *lpr;
- pr = p->p_prison;
- if (pr == NULL)
+ if (!jailed(p->p_ucred))
return (NULL);
+ pr = p->p_ucred->cr_prison;
+
if (pr->pr_linux == NULL) {
MALLOC(lpr, struct linux_prison *, sizeof *lpr,
M_PRISON, M_WAITOK|M_ZERO);
@@ -137,7 +138,7 @@ linux_get_osname(p)
register struct prison *pr;
register struct linux_prison *lpr;
- pr = p->p_prison;
+ pr = p->p_ucred->cr_prison;
if (pr != NULL && pr->pr_linux != NULL) {
lpr = pr->pr_linux;
if (lpr->pr_osname[0])
@@ -170,7 +171,7 @@ linux_get_osrelease(p)
register struct prison *pr;
register struct linux_prison *lpr;
- pr = p->p_prison;
+ pr = p->p_ucred->cr_prison;
if (pr != NULL && pr->pr_linux != NULL) {
lpr = pr->pr_linux;
if (lpr->pr_osrelease[0])
@@ -203,7 +204,7 @@ linux_get_oss_version(p)
register struct prison *pr;
register struct linux_prison *lpr;
- pr = p->p_prison;
+ pr = p->p_ucred->cr_prison;
if (pr != NULL && pr->pr_linux != NULL) {
lpr = pr->pr_linux;
if (lpr->pr_oss_version)
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index 680109b..3d40681 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -1299,15 +1299,6 @@ loop:
q->p_cred = NULL;
}
- /*
- * Destroy empty prisons
- */
- if (q->p_prison && !--q->p_prison->pr_ref) {
- if (q->p_prison->pr_linux != NULL)
- FREE(q->p_prison->pr_linux, M_PRISON);
- FREE(q->p_prison, M_PRISON);
- }
-
/*
* Remove unused arguments
*/
diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c
index 14c8fb4..7b2256c 100644
--- a/sys/fs/procfs/procfs_status.c
+++ b/sys/fs/procfs/procfs_status.c
@@ -163,9 +163,9 @@ procfs_dostatus(curp, p, pfs, uio)
DOCHECK();
}
- if (p->p_prison)
+ if (jailed(p->p_ucred))
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- " %s", p->p_prison->pr_host);
+ " %s", p->p_ucred->cr_prison->pr_host);
else
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -");
DOCHECK();
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 7f9a3f9..8eca076 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -324,9 +324,7 @@ proc0_init(void *dummy __unused)
p->p_ucred = crget();
p->p_ucred->cr_ngroups = 1; /* group 0 */
p->p_ucred->cr_uidinfo = uifind(0);
-
- /* Don't jail it */
- p->p_prison = 0;
+ p->p_ucred->cr_prison = NULL; /* Don't jail it. */
/* Create procsig. */
p->p_procsig = &procsig0;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 71e6288..440ee3a 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -528,15 +528,6 @@ loop:
}
/*
- * Destroy empty prisons
- */
- if (p->p_prison && !--p->p_prison->pr_ref) {
- if (p->p_prison->pr_linux != NULL)
- FREE(p->p_prison->pr_linux, M_PRISON);
- FREE(p->p_prison, M_PRISON);
- }
-
- /*
* Remove unused arguments
*/
if (p->p_args && --p->p_args->ar_ref == 0)
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index c754e5d..7f6be26 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -394,11 +394,6 @@ again:
crhold(p1->p_ucred);
uihold(p1->p_cred->p_uidinfo);
- if (p2->p_prison) {
- p2->p_prison->pr_ref++;
- p2->p_flag |= P_JAILED;
- }
-
if (p2->p_args)
p2->p_args->ar_ref++;
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 97bb2bb..c417667 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -46,16 +46,17 @@ SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
int
jail(p, uap)
- struct proc *p;
- struct jail_args /* {
- syscallarg(struct jail *) jail;
- } */ *uap;
+ struct proc *p;
+ struct jail_args /* {
+ syscallarg(struct jail *) jail;
+ } */ *uap;
{
int error;
struct prison *pr;
struct jail j;
struct chroot_args ca;
+ /* Implicitly fail if already in jail. */
error = suser(p);
if (error)
return (error);
@@ -75,9 +76,9 @@ jail(p, uap)
if (error)
goto bail;
- pr->pr_ref++;
- p->p_prison = pr;
- p->p_flag |= P_JAILED;
+ p->p_ucred = crcopy(p->p_ucred);
+ p->p_ucred->cr_prison = pr;
+ pr->pr_ref = 1;
return (0);
bail:
@@ -85,12 +86,31 @@ bail:
return (error);
}
+void
+prison_free(struct prison *pr)
+{
+
+ pr->pr_ref--;
+ if (pr->pr_ref == 0) {
+ if (pr->pr_linux != NULL)
+ FREE(pr->pr_linux, M_PRISON);
+ FREE(pr, M_PRISON);
+ }
+}
+
+void
+prison_hold(struct prison *pr)
+{
+
+ pr->pr_ref++;
+}
+
int
-prison_ip(struct proc *p, int flag, u_int32_t *ip)
+prison_ip(struct ucred *cred, int flag, u_int32_t *ip)
{
u_int32_t tmp;
- if (!p->p_prison)
+ if (!jailed(cred))
return (0);
if (flag)
tmp = *ip;
@@ -98,22 +118,22 @@ prison_ip(struct proc *p, int flag, u_int32_t *ip)
tmp = ntohl(*ip);
if (tmp == INADDR_ANY) {
if (flag)
- *ip = p->p_prison->pr_ip;
+ *ip = cred->cr_prison->pr_ip;
else
- *ip = htonl(p->p_prison->pr_ip);
+ *ip = htonl(cred->cr_prison->pr_ip);
return (0);
}
- if (p->p_prison->pr_ip != tmp)
+ if (cred->cr_prison->pr_ip != tmp)
return (1);
return (0);
}
void
-prison_remote_ip(struct proc *p, int flag, u_int32_t *ip)
+prison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip)
{
u_int32_t tmp;
- if (!p || !p->p_prison)
+ if (!jailed(cred))
return;
if (flag)
tmp = *ip;
@@ -121,16 +141,16 @@ prison_remote_ip(struct proc *p, int flag, u_int32_t *ip)
tmp = ntohl(*ip);
if (tmp == 0x7f000001) {
if (flag)
- *ip = p->p_prison->pr_ip;
+ *ip = cred->cr_prison->pr_ip;
else
- *ip = htonl(p->p_prison->pr_ip);
+ *ip = htonl(cred->cr_prison->pr_ip);
return;
}
return;
}
int
-prison_if(struct proc *p, struct sockaddr *sa)
+prison_if(struct ucred *cred, struct sockaddr *sa)
{
struct sockaddr_in *sai = (struct sockaddr_in*) sa;
int ok;
@@ -139,9 +159,38 @@ prison_if(struct proc *p, struct sockaddr *sa)
ok = 1;
else if (sai->sin_family != AF_INET)
ok = 0;
- else if (p->p_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
+ else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
ok = 1;
else
ok = 0;
return (ok);
}
+
+/*
+ * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
+ */
+int
+prison_check(cred1, cred2)
+ struct ucred *cred1, *cred2;
+{
+
+ if (jailed(cred1)) {
+ if (!jailed(cred2))
+ return (ESRCH);
+ if (cred2->cr_prison != cred1->cr_prison)
+ return (ESRCH);
+ }
+
+ return (0);
+}
+
+/*
+ * Return 1 if the passed credential is in a jail, otherwise 0.
+ */
+int
+jailed(cred)
+ struct ucred *cred;
+{
+
+ return (cred->cr_prison != NULL);
+}
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index ce408ca..149bc4c 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -48,6 +48,7 @@
#include <sys/ktrace.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
+#include <sys/jail.h>
static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE");
@@ -519,6 +520,7 @@ ktrwrite(vp, kth, uio)
* so, only root may further change it.
*
* XXX: These checks are stronger than for ptrace()
+ * XXX: This check should be p_can(... P_CAN_DEBUG ...);
*
* TODO: check groups. use caller effective gid.
*/
@@ -529,7 +531,7 @@ ktrcanset(callp, targetp)
register struct pcred *caller = callp->p_cred;
register struct pcred *target = targetp->p_cred;
- if (!PRISON_CHECK(callp, targetp))
+ if (prison_check(callp->p_ucred, targetp->p_ucred))
return (0);
if ((caller->pc_ucred->cr_uid == target->p_ruid &&
target->p_ruid == target->p_svuid &&
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index 0826ea0..bb9f640 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -146,12 +146,12 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS)
{
int error;
- if (req->p->p_prison) {
+ if (jailed(req->p->p_ucred)) {
if (!jail_set_hostname_allowed && req->newptr)
return(EPERM);
error = sysctl_handle_string(oidp,
- req->p->p_prison->pr_host,
- sizeof req->p->p_prison->pr_host, req);
+ req->p->p_ucred->cr_prison->pr_host,
+ sizeof req->p->p_ucred->cr_prison->pr_host, req);
} else
error = sysctl_handle_string(oidp,
hostname, sizeof hostname, req);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 0461e83..dc37bc7 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -49,6 +49,7 @@
#include <vm/vm_map.h>
#include <sys/user.h>
#include <vm/vm_zone.h>
+#include <sys/jail.h>
static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
MALLOC_DEFINE(M_SESSION, "session", "session header");
@@ -478,6 +479,9 @@ fill_kinfo_proc(p, kp)
kp->ki_xstat = p->p_xstat;
kp->ki_acflag = p->p_acflag;
kp->ki_flag = p->p_flag;
+ /* If jailed(p->p_ucred), emulate the old P_JAILED flag. */
+ if (jailed(p->p_ucred))
+ kp->ki_flag |= P_JAILED;
kp->ki_lock = p->p_lock;
PROC_UNLOCK(p);
PROCTREE_LOCK(PT_SHARED);
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 4d8c4e3..9d92ff7 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -56,6 +56,7 @@
#include <sys/pioctl.h>
#include <sys/resourcevar.h>
#include <sys/sysctl.h>
+#include <sys/jail.h>
static MALLOC_DEFINE(M_CRED, "cred", "credentials");
@@ -941,15 +942,15 @@ SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0,
*/
int
suser(p)
- const struct proc *p;
+ struct proc *p;
{
return suser_xxx(0, p, 0);
}
int
suser_xxx(cred, proc, flag)
- const struct ucred *cred;
- const struct proc *proc;
+ struct ucred *cred;
+ struct proc *proc;
int flag;
{
if (!suser_permitted)
@@ -962,20 +963,21 @@ suser_xxx(cred, proc, flag)
cred = proc->p_ucred;
if (cred->cr_uid != 0)
return (EPERM);
- if (proc && proc->p_prison && !(flag & PRISON_ROOT))
+ if (jailed(cred) && !(flag & PRISON_ROOT))
return (EPERM);
return (0);
}
static int
-p_cansee(const struct proc *p1, const struct proc *p2, int *privused)
+p_cansee(struct proc *p1, struct proc *p2, int *privused)
{
+ int error;
if (privused != NULL)
*privused = 0;
- if (!PRISON_CHECK(p1, p2))
- return (ESRCH);
+ if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
+ return (error);
if (!ps_showallprocs && p1->p_ucred->cr_uid != p2->p_ucred->cr_uid) {
if (suser_xxx(NULL, p1, PRISON_ROOT) == 0) {
@@ -990,8 +992,9 @@ p_cansee(const struct proc *p1, const struct proc *p2, int *privused)
}
static int
-p_cankill(const struct proc *p1, const struct proc *p2, int *privused)
+p_cankill(struct proc *p1, struct proc *p2, int *privused)
{
+ int error;
if (privused != NULL)
*privused = 0;
@@ -999,8 +1002,8 @@ p_cankill(const struct proc *p1, const struct proc *p2, int *privused)
if (p1 == p2)
return (0);
- if (!PRISON_CHECK(p1, p2))
- return (ESRCH);
+ if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
+ return (error);
if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
return (0);
@@ -1033,8 +1036,9 @@ p_cankill(const struct proc *p1, const struct proc *p2, int *privused)
}
static int
-p_cansched(const struct proc *p1, const struct proc *p2, int *privused)
+p_cansched(struct proc *p1, struct proc *p2, int *privused)
{
+ int error;
if (privused != NULL)
*privused = 0;
@@ -1042,8 +1046,8 @@ p_cansched(const struct proc *p1, const struct proc *p2, int *privused)
if (p1 == p2)
return (0);
- if (!PRISON_CHECK(p1, p2))
- return (ESRCH);
+ if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
+ return (error);
if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
return (0);
@@ -1076,9 +1080,9 @@ p_cansched(const struct proc *p1, const struct proc *p2, int *privused)
}
static int
-p_candebug(const struct proc *p1, const struct proc *p2, int *privused)
+p_candebug(struct proc *p1, struct proc *p2, int *privused)
{
- int error;
+ int error;
if (privused != NULL)
*privused = 0;
@@ -1087,8 +1091,8 @@ p_candebug(const struct proc *p1, const struct proc *p2, int *privused)
if (p1 == p2)
return (0);
- if (!PRISON_CHECK(p1, p2))
- return (ESRCH);
+ if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
+ return (error);
/* not owned by you, has done setuid (unless you're root) */
/* add a CAP_SYS_PTRACE here? */
@@ -1110,7 +1114,7 @@ p_candebug(const struct proc *p1, const struct proc *p2, int *privused)
}
int
-p_can(const struct proc *p1, const struct proc *p2, int operation,
+p_can(struct proc *p1, struct proc *p2, int operation,
int *privused)
{
@@ -1180,6 +1184,11 @@ crfree(cr)
*/
if (cr->cr_uidinfo != NULL)
uifree(cr->cr_uidinfo);
+ /*
+ * Free a prison, if any.
+ */
+ if (jailed(cr))
+ prison_free(cr->cr_prison);
FREE((caddr_t)cr, M_CRED);
} else {
mtx_unlock(&cr->cr_mtx);
@@ -1219,6 +1228,8 @@ crdup(cr)
*newcr = *cr;
mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF);
uihold(newcr->cr_uidinfo);
+ if (jailed(newcr))
+ prison_hold(newcr->cr_prison);
newcr->cr_ref = 1;
return (newcr);
}
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index db4a90a..f2b3ba7 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -278,7 +278,7 @@ msgsys(p, uap)
} */ *uap;
{
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0]))
@@ -334,7 +334,7 @@ msgctl(p, uap)
printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr);
#endif
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
msqid = IPCID_TO_IX(msqid);
@@ -473,7 +473,7 @@ msgget(p, uap)
printf("msgget(0x%x, 0%o)\n", key, msgflg);
#endif
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
if (key != IPC_PRIVATE) {
@@ -588,7 +588,7 @@ msgsnd(p, uap)
msgflg);
#endif
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
msqid = IPCID_TO_IX(msqid);
@@ -915,7 +915,7 @@ msgrcv(p, uap)
msgsz, msgtyp, msgflg);
#endif
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
msqid = IPCID_TO_IX(msqid);
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 3fab556..cc2f2d4 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -255,7 +255,7 @@ semsys(p, uap)
} */ *uap;
{
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0]))
@@ -464,7 +464,7 @@ __semctl(p, uap)
printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg);
#endif
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
semid = IPCID_TO_IX(semid);
@@ -627,7 +627,7 @@ semget(p, uap)
printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg);
#endif
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
if (key != IPC_PRIVATE) {
@@ -748,7 +748,7 @@ semop(p, uap)
printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops);
#endif
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index 19efaf9..3bfd49a 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -229,7 +229,7 @@ shmdt(p, uap)
struct shmmap_state *shmmap_s;
int i;
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
@@ -266,7 +266,7 @@ shmat(p, uap)
vm_size_t size;
int rv;
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
@@ -360,7 +360,7 @@ oshmctl(p, uap)
struct shmid_ds *shmseg;
struct oshmid_ds outbuf;
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
shmseg = shm_find_segment_by_shmid(uap->shmid);
@@ -411,7 +411,7 @@ shmctl(p, uap)
struct shmid_ds inbuf;
struct shmid_ds *shmseg;
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
shmseg = shm_find_segment_by_shmid(uap->shmid);
@@ -590,7 +590,7 @@ shmget(p, uap)
{
int segnum, mode, error;
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
mode = uap->shmflg & ACCESSPERMS;
@@ -621,7 +621,7 @@ shmsys(p, uap)
} */ *uap;
{
- if (!jail_sysvipc_allowed && p->p_prison != NULL)
+ if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0]))
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index b6063fc..501dde1 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -187,7 +187,7 @@ ptsopen(dev, flag, devtype, p)
tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
} else if (tp->t_state & TS_XCLUDE && suser(p)) {
return (EBUSY);
- } else if (pti->pt_prison != p->p_prison) {
+ } else if (pti->pt_prison != p->p_ucred->cr_prison) {
return (EBUSY);
}
if (tp->t_oproc) /* Ctrlr still around. */
@@ -348,7 +348,7 @@ ptcopen(dev, flag, devtype, p)
(void)(*linesw[tp->t_line].l_modem)(tp, 1);
tp->t_lflag &= ~EXTPROC;
pti = dev->si_drv1;
- pti->pt_prison = p->p_prison;
+ pti->pt_prison = p->p_ucred->cr_prison;
pti->pt_flags = 0;
pti->pt_send = 0;
pti->pt_ucntl = 0;
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 85667de..2f0cdd3 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -141,7 +141,7 @@ socreate(dom, aso, type, proto, p)
if (prp == 0 || prp->pr_usrreqs->pru_attach == 0)
return (EPROTONOSUPPORT);
- if (p->p_prison && jail_socket_unixiproute_only &&
+ if (jailed(p->p_ucred) && jail_socket_unixiproute_only &&
prp->pr_domain->dom_family != PF_LOCAL &&
prp->pr_domain->dom_family != PF_INET &&
prp->pr_domain->dom_family != PF_ROUTE) {
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 79477c9..de295b1 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -54,6 +54,7 @@
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/vnode.h>
+#include <sys/jail.h>
#include <vm/vm_zone.h>
@@ -725,7 +726,7 @@ unp_abort(unp)
static int
prison_unpcb(struct proc *p, struct unpcb *unp)
{
- if (!p->p_prison)
+ if (!jailed(p->p_ucred))
return (0);
if (p->p_fd->fd_rdir == unp->unp_rvnode)
return (0);
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 709736c..0651257 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -64,6 +64,7 @@
#include <sys/proc.h>
#include <sys/dirent.h>
#include <sys/extattr.h>
+#include <sys/jail.h>
#include <machine/limits.h>
#include <miscfs/union/union.h>
@@ -610,7 +611,7 @@ quotactl(p, uap)
int error;
struct nameidata nd;
- if (p->p_prison && !prison_quotas)
+ if (jailed(p->p_ucred) && !prison_quotas)
return (EPERM);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
if ((error = namei(&nd)) != 0)
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 709736c..0651257 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -64,6 +64,7 @@
#include <sys/proc.h>
#include <sys/dirent.h>
#include <sys/extattr.h>
+#include <sys/jail.h>
#include <machine/limits.h>
#include <miscfs/union/union.h>
@@ -610,7 +611,7 @@ quotactl(p, uap)
int error;
struct nameidata nd;
- if (p->p_prison && !prison_quotas)
+ if (jailed(p->p_ucred) && !prison_quotas)
return (EPERM);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
if ((error = namei(&nd)) != 0)
diff --git a/sys/miscfs/procfs/procfs_status.c b/sys/miscfs/procfs/procfs_status.c
index 14c8fb4..7b2256c 100644
--- a/sys/miscfs/procfs/procfs_status.c
+++ b/sys/miscfs/procfs/procfs_status.c
@@ -163,9 +163,9 @@ procfs_dostatus(curp, p, pfs, uio)
DOCHECK();
}
- if (p->p_prison)
+ if (jailed(p->p_ucred))
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- " %s", p->p_prison->pr_host);
+ " %s", p->p_ucred->cr_prison->pr_host);
else
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -");
DOCHECK();
diff --git a/sys/net/if.c b/sys/net/if.c
index dc434f3..2f06afd 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -50,6 +50,7 @@
#include <sys/sockio.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
+#include <sys/jail.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -1080,7 +1081,8 @@ ifconf(cmd, data)
for ( ; space > sizeof (ifr) && ifa;
ifa = TAILQ_NEXT(ifa, ifa_link)) {
register struct sockaddr *sa = ifa->ifa_addr;
- if (curproc->p_prison && prison_if(curproc, sa))
+ if (jailed(curproc->p_ucred) &&
+ prison_if(curproc->p_ucred, sa))
continue;
addrs++;
#ifdef COMPAT_43
diff --git a/sys/net/if.h b/sys/net/if.h
index bcc10ad..6cdaa53 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -265,8 +265,6 @@ __END_DECLS
#ifdef _KERNEL
struct proc;
-int prison_if __P((struct proc *p, struct sockaddr *sa));
-
/* XXX - this should go away soon. */
#include <net/if_var.h>
#endif
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 2dba7d9..dc4ae26 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -46,6 +46,7 @@
#include <sys/socketvar.h>
#include <sys/domain.h>
#include <sys/protosw.h>
+#include <sys/jail.h>
#include <net/if.h>
#include <net/route.h>
@@ -915,7 +916,8 @@ sysctl_iflist(af, w)
while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != 0) {
if (af && af != ifa->ifa_addr->sa_family)
continue;
- if (curproc->p_prison && prison_if(curproc, ifa->ifa_addr))
+ if (jailed(curproc->p_ucred) &&
+ prison_if(curproc->p_ucred, ifa->ifa_addr))
continue;
ifaaddr = ifa->ifa_addr;
netmask = ifa->ifa_netmask;
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 1ce8dfd..e7ab99f 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -487,9 +487,6 @@ int in_localaddr __P((struct in_addr));
char *inet_ntoa __P((struct in_addr)); /* in libkern */
char *inet_ntoa_r __P((struct in_addr ina, char *buf)); /* in libkern */
-int prison_ip __P((struct proc *p, int flag, u_int32_t *ip));
-void prison_remote_ip __P((struct proc *p, int flag, u_int32_t *ip));
-
#endif
#endif
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 7195be9..c114eca 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -199,7 +199,7 @@ in_pcbbind(inp, nam, p)
return (EAFNOSUPPORT);
#endif
if (sin->sin_addr.s_addr != INADDR_ANY)
- if (prison_ip(p, 0, &sin->sin_addr.s_addr))
+ if (prison_ip(p->p_ucred, 0, &sin->sin_addr.s_addr))
return(EINVAL);
lport = sin->sin_port;
if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
@@ -219,12 +219,11 @@ in_pcbbind(inp, nam, p)
}
if (lport) {
struct inpcb *t;
-
/* GROSS */
if (ntohs(lport) < IPPORT_RESERVED && p &&
suser_xxx(0, p, PRISON_ROOT))
return (EACCES);
- if (p && p->p_prison)
+ if (p && jailed(p->p_ucred))
prison = 1;
if (so->so_cred->cr_uid != 0 &&
!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
@@ -274,7 +273,7 @@ in_pcbbind(inp, nam, p)
int count;
if (inp->inp_laddr.s_addr != INADDR_ANY)
- if (prison_ip(p, 0, &inp->inp_laddr.s_addr ))
+ if (prison_ip(p->p_ucred, 0, &inp->inp_laddr.s_addr ))
return (EINVAL);
inp->inp_flags |= INP_ANONPORT;
@@ -345,7 +344,7 @@ in_pcbbind(inp, nam, p)
}
}
inp->inp_lport = lport;
- if (prison_ip(p, 0, &inp->inp_laddr.s_addr))
+ if (prison_ip(p->p_ucred, 0, &inp->inp_laddr.s_addr))
return(EINVAL);
if (in_pcbinshash(inp) != 0) {
inp->inp_laddr.s_addr = INADDR_ANY;
@@ -492,11 +491,13 @@ in_pcbconnect(inp, nam, p)
struct sockaddr_in *ifaddr;
struct sockaddr_in *sin = (struct sockaddr_in *)nam;
struct sockaddr_in sa;
+ struct ucred *cred;
int error;
- if (inp->inp_laddr.s_addr == INADDR_ANY && p->p_prison != NULL) {
+ cred = inp->inp_socket->so_cred;
+ if (inp->inp_laddr.s_addr == INADDR_ANY && jailed(cred)) {
bzero(&sa, sizeof (sa));
- sa.sin_addr.s_addr = htonl(p->p_prison->pr_ip);
+ sa.sin_addr.s_addr = htonl(cred->cr_prison->pr_ip);
sa.sin_len=sizeof (sa);
sa.sin_family = AF_INET;
error = in_pcbbind(inp, (struct sockaddr *)&sa, p);
@@ -1068,9 +1069,9 @@ in_pcbremlists(inp)
int
prison_xinpcb(struct proc *p, struct inpcb *inp)
{
- if (!p->p_prison)
+ if (!jailed(p->p_ucred))
return (0);
- if (ntohl(inp->inp_laddr.s_addr) == p->p_prison->pr_ip)
+ if (ntohl(inp->inp_laddr.s_addr) == p->p_ucred->cr_prison->pr_ip)
return (0);
return (1);
}
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index ac1eee9..1d64581 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -49,6 +49,8 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
+#include <sys/proc.h>
+#include <sys/jail.h>
#include <net/if.h>
#include <net/route.h>
@@ -328,7 +330,8 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
goto out;
}
- prison_remote_ip(p, 0, &sinp->sin_addr.s_addr);
+ if (p && jailed(p->p_ucred))
+ prison_remote_ip(p->p_ucred, 0, &sinp->sin_addr.s_addr);
if ((error = tcp_connect(tp, nam, p)) != 0)
goto out;
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 7edcfcd..60c80d2 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -49,6 +49,7 @@
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
+#include <sys/jail.h>
#include <vm/vm_zone.h>
@@ -675,7 +676,8 @@ udp_output(inp, m, addr, control, p)
if (addr) {
sin = (struct sockaddr_in *)addr;
- prison_remote_ip(p, 0, &sin->sin_addr.s_addr);
+ if (p && jailed(p->p_ucred))
+ prison_remote_ip(p->p_ucred, 0, &sin->sin_addr.s_addr);
laddr = inp->inp_laddr;
if (inp->inp_faddr.s_addr != INADDR_ANY) {
error = EISCONN;
@@ -848,7 +850,8 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
return EISCONN;
s = splnet();
sin = (struct sockaddr_in *)nam;
- prison_remote_ip(p, 0, &sin->sin_addr.s_addr);
+ if (p && jailed(p->p_ucred))
+ prison_remote_ip(p->p_ucred, 0, &sin->sin_addr.s_addr);
error = in_pcbconnect(inp, nam, p);
splx(s);
if (error == 0)
diff --git a/sys/sys/capability.h b/sys/sys/capability.h
index 4dc1fbc..cc56c58 100644
--- a/sys/sys/capability.h
+++ b/sys/sys/capability.h
@@ -167,7 +167,7 @@ typedef struct cap *cap_t;
struct proc;
struct ucred;
struct vnode;
-int cap_check(const struct ucred *, const struct proc *, cap_value_t, int);
+int cap_check(struct ucred *, struct proc *, cap_value_t, int);
int cap_change_on_inherit(struct cap *cap_p);
int cap_inherit(struct vnode *vp, struct proc *p);
void cap_init_proc0(struct cap *);
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index a4227d9..fcd1d13 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -32,8 +32,11 @@ MALLOC_DECLARE(M_PRISON);
/*
* This structure describes a prison. It is pointed to by all struct
- * proc's of the inmates. pr_ref keeps track of them and is used to
+ * ucreds's of the inmates. pr_ref keeps track of them and is used to
* delete the struture when the last inmate is dead.
+ *
+ * XXX: Note: this structure needs a mutex to protect the reference count
+ * and other mutable fields (pr_host, pr_linux).
*/
struct prison {
@@ -50,5 +53,18 @@ extern int jail_set_hostname_allowed;
extern int jail_socket_unixiproute_only;
extern int jail_sysvipc_allowed;
+/*
+ * Kernel support functions for jail().
+ */
+struct ucred;
+struct sockaddr;
+int jailed __P((struct ucred *cred));
+int prison_check __P((struct ucred *cred1, struct ucred *cred2));
+void prison_free __P((struct prison *pr));
+void prison_hold __P((struct prison *pr));
+int prison_if __P((struct ucred *cred, struct sockaddr *sa));
+int prison_ip __P((struct ucred *cred, int flag, u_int32_t *ip));
+void prison_remote_ip __P((struct ucred *cred, int flags, u_int32_t *ip));
+
#endif /* !_KERNEL */
#endif /* !_SYS_JAIL_H_ */
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 7880448..81b5551 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -258,7 +258,6 @@ struct proc {
struct pgrp *p_pgrp; /* (e?/c?) Pointer to process group. */
struct sysentvec *p_sysent; /* (b) System call dispatch information. */
- struct prison *p_prison; /* (b?) jail(4). */
struct pargs *p_args; /* (b?) Process arguments. */
/* End area that is copied on creation. */
@@ -539,7 +538,7 @@ void fork_return __P((struct proc *, struct trapframe *));
int inferior __P((struct proc *p));
int leavepgrp __P((struct proc *p));
void mi_switch __P((void));
-int p_can __P((const struct proc *p1, const struct proc *p2, int operation,
+int p_can __P((struct proc *p1, struct proc *p2, int operation,
int *privused));
int p_trespass __P((struct proc *p1, struct proc *p2));
void procinit __P((void));
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 54b303d..454f5ee 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -161,9 +161,8 @@ void setstatclockrate __P((int hzrate));
/* flags for suser_xxx() */
#define PRISON_ROOT 1
-int suser __P((const struct proc *));
-int suser_xxx __P((const struct ucred *cred, const struct proc *proc,
- int flag));
+int suser __P((struct proc *));
+int suser_xxx __P((struct ucred *cred, struct proc *proc, int flag));
char *getenv __P((char *name));
int getenv_int __P((char *name, int *data));
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index 63adce8..7735091 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -51,6 +51,7 @@ struct ucred {
short cr_ngroups; /* number of groups */
gid_t cr_groups[NGROUPS]; /* groups */
struct uidinfo *cr_uidinfo; /* per uid resource consumption */
+ struct prison *cr_prison; /* jail(4) */
struct mtx cr_mtx; /* protect refcount */
};
#define cr_gid cr_groups[0]
OpenPOWER on IntegriCloud