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:
parent
666fd63da7
commit
91421ba234
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=72786
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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++;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 &&
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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]))
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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 *);
|
||||
|
@ -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_ */
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user