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
This commit is contained in:
Robert Watson 2001-02-21 06:39:57 +00:00
parent 666fd63da7
commit 91421ba234
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=72786
34 changed files with 190 additions and 124 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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)

View File

@ -1299,15 +1299,6 @@ svr4_sys_waitsys(p, uap)
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
*/

View File

@ -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();

View File

@ -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;

View File

@ -527,15 +527,6 @@ wait1(q, uap, compat)
p->p_cred = NULL;
}
/*
* 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
*/

View File

@ -394,11 +394,6 @@ fork1(p1, flags, procp)
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++;

View File

@ -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 @@ jail(p, uap)
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);
}

View File

@ -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 &&

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -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]))

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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)

View File

@ -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 *);

View File

@ -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_ */

View File

@ -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));

View File

@ -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));

View File

@ -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]