diff options
25 files changed, 136 insertions, 2334 deletions
@@ -84,7 +84,6 @@ LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-sysctlbyname.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-sysctl.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-sysctlnametomib.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-taskqueue.c -LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-thread0-ucred.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-thread.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-timesupport.c LIB_C_FILES += rtemsbsd/rtems/rtems-bsd-vm_glue.c @@ -137,7 +136,6 @@ LIB_C_FILES += freebsd/sys/kern/kern_module.c LIB_C_FILES += freebsd/sys/kern/kern_mtxpool.c LIB_C_FILES += freebsd/sys/kern/kern_ntptime.c LIB_C_FILES += freebsd/sys/kern/kern_proc.c -LIB_C_FILES += freebsd/sys/kern/kern_prot.c LIB_C_FILES += freebsd/sys/kern/kern_resource.c LIB_C_FILES += freebsd/sys/kern/kern_subr.c LIB_C_FILES += freebsd/sys/kern/kern_sysctl.c diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py index 488e5b8f..7055e5cb 100755 --- a/freebsd-to-rtems.py +++ b/freebsd-to-rtems.py @@ -641,7 +641,6 @@ rtems.addRTEMSSourceFiles( 'rtems/rtems-bsd-sysctl.c', 'rtems/rtems-bsd-sysctlnametomib.c', 'rtems/rtems-bsd-taskqueue.c', - 'rtems/rtems-bsd-thread0-ucred.c', 'rtems/rtems-bsd-thread.c', 'rtems/rtems-bsd-timesupport.c', 'rtems/rtems-bsd-vm_glue.c', @@ -796,7 +795,6 @@ base.addSourceFiles( 'sys/kern/kern_mtxpool.c', 'sys/kern/kern_ntptime.c', 'sys/kern/kern_proc.c', - 'sys/kern/kern_prot.c', 'sys/kern/kern_resource.c', 'sys/kern/kern_subr.c', 'sys/kern/kern_sysctl.c', diff --git a/freebsd/sys/contrib/pf/net/pf.c b/freebsd/sys/contrib/pf/net/pf.c index bad7a1cd..8070caa4 100644 --- a/freebsd/sys/contrib/pf/net/pf.c +++ b/freebsd/sys/contrib/pf/net/pf.c @@ -2987,8 +2987,13 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd) #ifdef __FreeBSD__ if (inp_arg != NULL) { INP_LOCK_ASSERT(inp_arg); +#ifndef __rtems__ pd->lookup.uid = inp_arg->inp_cred->cr_uid; pd->lookup.gid = inp_arg->inp_cred->cr_groups[0]; +#else /* __rtems__ */ + pd->lookup.uid = BSD_DEFAULT_UID; + pd->lookup.gid = BSD_DEFAULT_GID; +#endif /* __rtems__ */ return (1); } #endif @@ -3085,8 +3090,13 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd) return (-1); } #ifdef __FreeBSD__ +#ifndef __rtems__ pd->lookup.uid = inp->inp_cred->cr_uid; pd->lookup.gid = inp->inp_cred->cr_groups[0]; +#else /* __rtems__ */ + pd->lookup.uid = BSD_DEFAULT_UID; + pd->lookup.gid = BSD_DEFAULT_GID; +#endif /* __rtems__ */ INP_INFO_RUNLOCK(pi); #else pd->lookup.uid = inp->inp_socket->so_euid; diff --git a/freebsd/sys/contrib/pf/net/pf_ioctl.c b/freebsd/sys/contrib/pf/net/pf_ioctl.c index e1ef3fac..24f41d36 100644 --- a/freebsd/sys/contrib/pf/net/pf_ioctl.c +++ b/freebsd/sys/contrib/pf/net/pf_ioctl.c @@ -1489,10 +1489,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } bcopy(&pr->rule, rule, sizeof(struct pf_rule)); #ifdef __FreeBSD__ - rule->cuid = td->td_ucred->cr_ruid; #ifndef __rtems__ + rule->cuid = td->td_ucred->cr_ruid; rule->cpid = td->td_proc ? td->td_proc->p_pid : 0; #else /* __rtems__ */ + rule->cuid = BSD_DEFAULT_UID; rule->cpid = BSD_DEFAULT_PID; #endif /* __rtems__ */ #else @@ -1763,10 +1764,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); #ifdef __FreeBSD__ - newrule->cuid = td->td_ucred->cr_ruid; #ifndef __rtems__ + newrule->cuid = td->td_ucred->cr_ruid; newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0; #else /* __rtems__ */ + newrule->cuid = BSD_DEFAULT_UID; newrule->cpid = BSD_DEFAULT_PID; #endif /* __rtems__ */ #else diff --git a/freebsd/sys/kern/kern_intr.c b/freebsd/sys/kern/kern_intr.c index f86fa675..b23ce519 100644 --- a/freebsd/sys/kern/kern_intr.c +++ b/freebsd/sys/kern/kern_intr.c @@ -875,7 +875,9 @@ intr_event_schedule_thread(struct intr_event *ie) struct intr_thread *it; struct thread *td; struct thread *ctd; +#ifndef __rtems__ struct proc *p; +#endif /* __rtems__ */ /* * If no ithread or no handlers, then we have a stray interrupt. @@ -887,7 +889,9 @@ intr_event_schedule_thread(struct intr_event *ie) ctd = curthread; it = ie->ie_thread; td = it->it_thread; +#ifndef __rtems__ p = td->td_proc; +#endif /* __rtems__ */ /* * If any of the handlers for this ithread claim to be good @@ -1040,7 +1044,9 @@ intr_event_schedule_thread(struct intr_event *ie, struct intr_thread *it) struct intr_entropy entropy; struct thread *td; struct thread *ctd; +#ifndef __rtems__ struct proc *p; +#endif /* __rtems__ */ /* * If no ithread or no handlers, then we have a stray interrupt. @@ -1050,7 +1056,9 @@ intr_event_schedule_thread(struct intr_event *ie, struct intr_thread *it) ctd = curthread; td = it->it_thread; +#ifndef __rtems__ p = td->td_proc; +#endif /* __rtems__ */ /* * If any of the handlers for this ithread claim to be good @@ -1341,7 +1349,11 @@ ithread_loop(void *arg) struct proc *p; td = curthread; +#ifndef __rtems__ p = td->td_proc; +#else /* __rtems__ */ + p = NULL; +#endif /* __rtems__ */ ithd = (struct intr_thread *)arg; KASSERT(ithd->it_thread == td, ("%s: ithread and proc linkage out of sync", __func__)); diff --git a/freebsd/sys/kern/kern_prot.c b/freebsd/sys/kern/kern_prot.c deleted file mode 100644 index f9ea3f1e..00000000 --- a/freebsd/sys/kern/kern_prot.c +++ /dev/null @@ -1,2220 +0,0 @@ -#include <machine/rtems-bsd-config.h> - -/*- - * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 - * The Regents of the University of California. - * (c) UNIX System Laboratories, Inc. - * Copyright (c) 2000-2001 Robert N. M. Watson. - * All rights reserved. - * - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 - */ - -/* - * System calls related to processes and protection - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <rtems/bsd/local/opt_compat.h> -#include <rtems/bsd/local/opt_inet.h> -#include <rtems/bsd/local/opt_inet6.h> - -#include <rtems/bsd/sys/param.h> -#include <sys/systm.h> -#ifndef __rtems__ -#include <sys/acct.h> -#include <sys/kdb.h> -#endif /* __rtems__ */ -#include <sys/kernel.h> -#include <rtems/bsd/sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/refcount.h> -#include <sys/sx.h> -#include <sys/priv.h> -#include <sys/proc.h> -#include <sys/sysproto.h> -#include <sys/jail.h> -#ifndef __rtems__ -#include <sys/pioctl.h> -#endif /* __rtems__ */ -#include <sys/resourcevar.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/syscallsubr.h> -#include <sys/sysctl.h> - -#if defined(INET) || defined(INET6) -#include <netinet/in.h> -#include <netinet/in_pcb.h> -#endif - -#include <security/audit/audit.h> -#include <security/mac/mac_framework.h> - -static MALLOC_DEFINE(M_CRED, "cred", "credentials"); - -SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy"); - -static void crextend(struct ucred *cr, int n); -#ifndef __rtems__ -static void crsetgroups_locked(struct ucred *cr, int ngrp, - gid_t *groups); - -#ifndef _SYS_SYSPROTO_H_ -struct getpid_args { - int dummy; -}; -#endif -/* ARGSUSED */ -int -getpid(struct thread *td, struct getpid_args *uap) -{ - struct proc *p = td->td_proc; - - td->td_retval[0] = p->p_pid; -#if defined(COMPAT_43) - PROC_LOCK(p); - td->td_retval[1] = p->p_pptr->p_pid; - PROC_UNLOCK(p); -#endif - return (0); -} - -#ifndef _SYS_SYSPROTO_H_ -struct getppid_args { - int dummy; -}; -#endif -/* ARGSUSED */ -int -getppid(struct thread *td, struct getppid_args *uap) -{ - struct proc *p = td->td_proc; - - PROC_LOCK(p); - td->td_retval[0] = p->p_pptr->p_pid; - PROC_UNLOCK(p); - return (0); -} - -/* - * Get process group ID; note that POSIX getpgrp takes no parameter. - */ -#ifndef _SYS_SYSPROTO_H_ -struct getpgrp_args { - int dummy; -}; -#endif -int -getpgrp(struct thread *td, struct getpgrp_args *uap) -{ - struct proc *p = td->td_proc; - - PROC_LOCK(p); - td->td_retval[0] = p->p_pgrp->pg_id; - PROC_UNLOCK(p); - return (0); -} - -/* Get an arbitary pid's process group id */ -#ifndef _SYS_SYSPROTO_H_ -struct getpgid_args { - pid_t pid; -}; -#endif -int -getpgid(struct thread *td, struct getpgid_args *uap) -{ - struct proc *p; - int error; - - if (uap->pid == 0) { - p = td->td_proc; - PROC_LOCK(p); - } else { - p = pfind(uap->pid); - if (p == NULL) - return (ESRCH); - error = p_cansee(td, p); - if (error) { - PROC_UNLOCK(p); - return (error); - } - } - td->td_retval[0] = p->p_pgrp->pg_id; - PROC_UNLOCK(p); - return (0); -} - -/* - * Get an arbitary pid's session id. - */ -#ifndef _SYS_SYSPROTO_H_ -struct getsid_args { - pid_t pid; -}; -#endif -int -getsid(struct thread *td, struct getsid_args *uap) -{ - struct proc *p; - int error; - - if (uap->pid == 0) { - p = td->td_proc; - PROC_LOCK(p); - } else { - p = pfind(uap->pid); - if (p == NULL) - return (ESRCH); - error = p_cansee(td, p); - if (error) { - PROC_UNLOCK(p); - return (error); - } - } - td->td_retval[0] = p->p_session->s_sid; - PROC_UNLOCK(p); - return (0); -} - -#ifndef _SYS_SYSPROTO_H_ -struct getuid_args { - int dummy; -}; -#endif -/* ARGSUSED */ -int -getuid(struct thread *td, struct getuid_args *uap) -{ - - td->td_retval[0] = td->td_ucred->cr_ruid; -#if defined(COMPAT_43) - td->td_retval[1] = td->td_ucred->cr_uid; -#endif - return (0); -} - -#ifndef _SYS_SYSPROTO_H_ -struct geteuid_args { - int dummy; -}; -#endif -/* ARGSUSED */ -int -geteuid(struct thread *td, struct geteuid_args *uap) -{ - - td->td_retval[0] = td->td_ucred->cr_uid; - return (0); -} - -#ifndef _SYS_SYSPROTO_H_ -struct getgid_args { - int dummy; -}; -#endif -/* ARGSUSED */ -int -getgid(struct thread *td, struct getgid_args *uap) -{ - - td->td_retval[0] = td->td_ucred->cr_rgid; -#if defined(COMPAT_43) - td->td_retval[1] = td->td_ucred->cr_groups[0]; -#endif - return (0); -} - -/* - * Get effective group ID. The "egid" is groups[0], and could be obtained - * via getgroups. This syscall exists because it is somewhat painful to do - * correctly in a library function. - */ -#ifndef _SYS_SYSPROTO_H_ -struct getegid_args { - int dummy; -}; -#endif -/* ARGSUSED */ -int -getegid(struct thread *td, struct getegid_args *uap) -{ - - td->td_retval[0] = td->td_ucred->cr_groups[0]; - return (0); -} - -#ifndef _SYS_SYSPROTO_H_ -struct getgroups_args { - u_int gidsetsize; - gid_t *gidset; -}; -#endif -int -getgroups(struct thread *td, register struct getgroups_args *uap) -{ - gid_t *groups; - u_int ngrp; - int error; - - if (uap->gidsetsize < td->td_ucred->cr_ngroups) { - if (uap->gidsetsize == 0) - ngrp = 0; - else - return (EINVAL); - } else - ngrp = td->td_ucred->cr_ngroups; - groups = malloc(ngrp * sizeof(*groups), M_TEMP, M_WAITOK); - error = kern_getgroups(td, &ngrp, groups); - if (error) - goto out; - if (uap->gidsetsize > 0) - error = copyout(groups, uap->gidset, ngrp * sizeof(gid_t)); - if (error == 0) - td->td_retval[0] = ngrp; -out: - free(groups, M_TEMP); - return (error); -} - -int -kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups) -{ - struct ucred *cred; - - cred = td->td_ucred; - if (*ngrp == 0) { - *ngrp = cred->cr_ngroups; - return (0); - } - if (*ngrp < cred->cr_ngroups) - return (EINVAL); - *ngrp = cred->cr_ngroups; - bcopy(cred->cr_groups, groups, *ngrp * sizeof(gid_t)); - return (0); -} - -#ifndef _SYS_SYSPROTO_H_ -struct setsid_args { - int dummy; -}; -#endif -/* ARGSUSED */ -int -setsid(register struct thread *td, struct setsid_args *uap) -{ - struct pgrp *pgrp; - int error; - struct proc *p = td->td_proc; - struct pgrp *newpgrp; - struct session *newsess; - - error = 0; - pgrp = NULL; - - newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); - newsess = malloc(sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO); - - sx_xlock(&proctree_lock); - - if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) { - if (pgrp != NULL) - PGRP_UNLOCK(pgrp); - error = EPERM; - } else { - (void)enterpgrp(p, p->p_pid, newpgrp, newsess); - td->td_retval[0] = p->p_pid; - newpgrp = NULL; - newsess = NULL; - } - - sx_xunlock(&proctree_lock); - - if (newpgrp != NULL) - free(newpgrp, M_PGRP); - if (newsess != NULL) - free(newsess, M_SESSION); - - return (error); -} - -/* - * set process group (setpgid/old setpgrp) - * - * caller does setpgid(targpid, targpgid) - * - * pid must be caller or child of caller (ESRCH) - * if a child - * pid must be in same session (EPERM) - * pid can't have done an exec (EACCES) - * if pgid != pid - * there must exist some pid in same session having pgid (EPERM) - * pid must not be session leader (EPERM) - */ -#ifndef _SYS_SYSPROTO_H_ -struct setpgid_args { - int pid; /* target process id */ - int pgid; /* target pgrp id */ -}; -#endif -/* ARGSUSED */ -int -setpgid(struct thread *td, register struct setpgid_args *uap) -{ - struct proc *curp = td->td_proc; - register struct proc *targp; /* target process */ - register struct pgrp *pgrp; /* target pgrp */ - int error; - struct pgrp *newpgrp; - - if (uap->pgid < 0) - return (EINVAL); - - error = 0; - - newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO); - - sx_xlock(&proctree_lock); - if (uap->pid != 0 && uap->pid != curp->p_pid) { - if ((targp = pfind(uap->pid)) == NULL) { - error = ESRCH; - goto done; - } - if (!inferior(targp)) { - PROC_UNLOCK(targp); - error = ESRCH; - goto done; - } - if ((error = p_cansee(td, targp))) { - PROC_UNLOCK(targp); - goto done; - } - if (targp->p_pgrp == NULL || - targp->p_session != curp->p_session) { - PROC_UNLOCK(targp); - error = EPERM; - goto done; - } - if (targp->p_flag & P_EXEC) { - PROC_UNLOCK(targp); - error = EACCES; - goto done; - } - PROC_UNLOCK(targp); - } else - targp = curp; - if (SESS_LEADER(targp)) { - error = EPERM; - goto done; - } - if (uap->pgid == 0) - uap->pgid = targp->p_pid; - if ((pgrp = pgfind(uap->pgid)) == NULL) { - if (uap->pgid == targp->p_pid) { - error = enterpgrp(targp, uap->pgid, newpgrp, - NULL); - if (error == 0) - newpgrp = NULL; - } else - error = EPERM; - } else { - if (pgrp == targp->p_pgrp) { - PGRP_UNLOCK(pgrp); - goto done; - } - if (pgrp->pg_id != targp->p_pid && - pgrp->pg_session != curp->p_session) { - PGRP_UNLOCK(pgrp); - error = EPERM; - goto done; - } - PGRP_UNLOCK(pgrp); - error = enterthispgrp(targp, pgrp); - } -done: - sx_xunlock(&proctree_lock); - KASSERT((error == 0) || (newpgrp != NULL), - ("setpgid failed and newpgrp is NULL")); - if (newpgrp != NULL) - free(newpgrp, M_PGRP); - return (error); -} - -/* - * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD - * compatible. It says that setting the uid/gid to euid/egid is a special - * case of "appropriate privilege". Once the rules are expanded out, this - * basically means that setuid(nnn) sets all three id's, in all permitted - * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) - * does not set the saved id - this is dangerous for traditional BSD - * programs. For this reason, we *really* do not want to set - * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. - */ -#define POSIX_APPENDIX_B_4_2_2 - -#ifndef _SYS_SYSPROTO_H_ -struct setuid_args { - uid_t uid; -}; -#endif -/* ARGSUSED */ -int -setuid(struct thread *td, struct setuid_args *uap) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - uid_t uid; - struct uidinfo *uip; - int error; - - uid = uap->uid; - AUDIT_ARG_UID(uid); - newcred = crget(); - uip = uifind(uid); - PROC_LOCK(p); - /* - * Copy credentials so other references do not see our changes. - */ - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_setuid(oldcred, uid); - if (error) - goto fail; -#endif - - /* - * See if we have "permission" by POSIX 1003.1 rules. - * - * Note that setuid(geteuid()) is a special case of - * "appropriate privileges" in appendix B.4.2.2. We need - * to use this clause to be compatible with traditional BSD - * semantics. Basically, it means that "setuid(xx)" sets all - * three id's (assuming you have privs). - * - * Notes on the logic. We do things in three steps. - * 1: We determine if the euid is going to change, and do EPERM - * right away. We unconditionally change the euid later if this - * test is satisfied, simplifying that part of the logic. - * 2: We determine if the real and/or saved uids are going to - * change. Determined by compile options. - * 3: Change euid last. (after tests in #2 for "appropriate privs") - */ - if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ -#ifdef _POSIX_SAVED_IDS - uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ -#endif -#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ - uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ -#endif - (error = priv_check_cred(oldcred, PRIV_CRED_SETUID, 0)) != 0) - goto fail; - -#ifdef _POSIX_SAVED_IDS - /* - * Do we have "appropriate privileges" (are we root or uid == euid) - * If so, we are changing the real uid and/or saved uid. - */ - if ( -#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ - uid == oldcred->cr_uid || -#endif - /* We are using privs. */ - priv_check_cred(oldcred, PRIV_CRED_SETUID, 0) == 0) -#endif - { - /* - * Set the real uid and transfer proc count to new user. - */ - if (uid != oldcred->cr_ruid) { - change_ruid(newcred, uip); - setsugid(p); - } - /* - * Set saved uid - * - * XXX always set saved uid even if not _POSIX_SAVED_IDS, as - * the security of seteuid() depends on it. B.4.2.2 says it - * is important that we should do this. - */ - if (uid != oldcred->cr_svuid) { - change_svuid(newcred, uid); - setsugid(p); - } - } - - /* - * In all permitted cases, we are changing the euid. - */ - if (uid != oldcred->cr_uid) { - change_euid(newcred, uip); - setsugid(p); - } - p->p_ucred = newcred; - PROC_UNLOCK(p); - uifree(uip); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - uifree(uip); - crfree(newcred); - return (error); -} - -#ifndef _SYS_SYSPROTO_H_ -struct seteuid_args { - uid_t euid; -}; -#endif -/* ARGSUSED */ -int -seteuid(struct thread *td, struct seteuid_args *uap) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - uid_t euid; - struct uidinfo *euip; - int error; - - euid = uap->euid; - AUDIT_ARG_EUID(euid); - newcred = crget(); - euip = uifind(euid); - PROC_LOCK(p); - /* - * Copy credentials so other references do not see our changes. - */ - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_seteuid(oldcred, euid); - if (error) - goto fail; -#endif - - if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ - euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ - (error = priv_check_cred(oldcred, PRIV_CRED_SETEUID, 0)) != 0) - goto fail; - - /* - * Everything's okay, do it. - */ - if (oldcred->cr_uid != euid) { - change_euid(newcred, euip); - setsugid(p); - } - p->p_ucred = newcred; - PROC_UNLOCK(p); - uifree(euip); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - uifree(euip); - crfree(newcred); - return (error); -} - -#ifndef _SYS_SYSPROTO_H_ -struct setgid_args { - gid_t gid; -}; -#endif -/* ARGSUSED */ -int -setgid(struct thread *td, struct setgid_args *uap) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - gid_t gid; - int error; - - gid = uap->gid; - AUDIT_ARG_GID(gid); - newcred = crget(); - PROC_LOCK(p); - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_setgid(oldcred, gid); - if (error) - goto fail; -#endif - - /* - * See if we have "permission" by POSIX 1003.1 rules. - * - * Note that setgid(getegid()) is a special case of - * "appropriate privileges" in appendix B.4.2.2. We need - * to use this clause to be compatible with traditional BSD - * semantics. Basically, it means that "setgid(xx)" sets all - * three id's (assuming you have privs). - * - * For notes on the logic here, see setuid() above. - */ - if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ -#ifdef _POSIX_SAVED_IDS - gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ -#endif -#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ - gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ -#endif - (error = priv_check_cred(oldcred, PRIV_CRED_SETGID, 0)) != 0) - goto fail; - -#ifdef _POSIX_SAVED_IDS - /* - * Do we have "appropriate privileges" (are we root or gid == egid) - * If so, we are changing the real uid and saved gid. - */ - if ( -#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ - gid == oldcred->cr_groups[0] || -#endif - /* We are using privs. */ - priv_check_cred(oldcred, PRIV_CRED_SETGID, 0) == 0) -#endif - { - /* - * Set real gid - */ - if (oldcred->cr_rgid != gid) { - change_rgid(newcred, gid); - setsugid(p); - } - /* - * Set saved gid - * - * XXX always set saved gid even if not _POSIX_SAVED_IDS, as - * the security of setegid() depends on it. B.4.2.2 says it - * is important that we should do this. - */ - if (oldcred->cr_svgid != gid) { - change_svgid(newcred, gid); - setsugid(p); - } - } - /* - * In all cases permitted cases, we are changing the egid. - * Copy credentials so other references do not see our changes. - */ - if (oldcred->cr_groups[0] != gid) { - change_egid(newcred, gid); - setsugid(p); - } - p->p_ucred = newcred; - PROC_UNLOCK(p); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - crfree(newcred); - return (error); -} - -#ifndef _SYS_SYSPROTO_H_ -struct setegid_args { - gid_t egid; -}; -#endif -/* ARGSUSED */ -int -setegid(struct thread *td, struct setegid_args *uap) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - gid_t egid; - int error; - - egid = uap->egid; - AUDIT_ARG_EGID(egid); - newcred = crget(); - PROC_LOCK(p); - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_setegid(oldcred, egid); - if (error) - goto fail; -#endif - - if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ - egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ - (error = priv_check_cred(oldcred, PRIV_CRED_SETEGID, 0)) != 0) - goto fail; - - if (oldcred->cr_groups[0] != egid) { - change_egid(newcred, egid); - setsugid(p); - } - p->p_ucred = newcred; - PROC_UNLOCK(p); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - crfree(newcred); - return (error); -} - -#ifndef _SYS_SYSPROTO_H_ -struct setgroups_args { - u_int gidsetsize; - gid_t *gidset; -}; -#endif -/* ARGSUSED */ -int -setgroups(struct thread *td, struct setgroups_args *uap) -{ - gid_t *groups = NULL; - int error; - - if (uap->gidsetsize > ngroups_max + 1) - return (EINVAL); - groups = malloc(uap->gidsetsize * sizeof(gid_t), M_TEMP, M_WAITOK); - error = copyin(uap->gidset, groups, uap->gidsetsize * sizeof(gid_t)); - if (error) - goto out; - error = kern_setgroups(td, uap->gidsetsize, groups); -out: - free(groups, M_TEMP); - return (error); -} - -int -kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - int error; - - if (ngrp > ngroups_max + 1) - return (EINVAL); - AUDIT_ARG_GROUPSET(groups, ngrp); - newcred = crget(); - crextend(newcred, ngrp); - PROC_LOCK(p); - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_setgroups(oldcred, ngrp, groups); - if (error) - goto fail; -#endif - - error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0); - if (error) - goto fail; - - if (ngrp < 1) { - /* - * setgroups(0, NULL) is a legitimate way of clearing the - * groups vector on non-BSD systems (which generally do not - * have the egid in the groups[0]). We risk security holes - * when running non-BSD software if we do not do the same. - */ - newcred->cr_ngroups = 1; - } else { - crsetgroups_locked(newcred, ngrp, groups); - } - setsugid(p); - p->p_ucred = newcred; - PROC_UNLOCK(p); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - crfree(newcred); - return (error); -} - -#ifndef _SYS_SYSPROTO_H_ -struct setreuid_args { - uid_t ruid; - uid_t euid; -}; -#endif -/* ARGSUSED */ -int -setreuid(register struct thread *td, struct setreuid_args *uap) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - uid_t euid, ruid; - struct uidinfo *euip, *ruip; - int error; - - euid = uap->euid; - ruid = uap->ruid; - AUDIT_ARG_EUID(euid); - AUDIT_ARG_RUID(ruid); - newcred = crget(); - euip = uifind(euid); - ruip = uifind(ruid); - PROC_LOCK(p); - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_setreuid(oldcred, ruid, euid); - if (error) - goto fail; -#endif - - if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && - ruid != oldcred->cr_svuid) || - (euid != (uid_t)-1 && euid != oldcred->cr_uid && - euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && - (error = priv_check_cred(oldcred, PRIV_CRED_SETREUID, 0)) != 0) - goto fail; - - if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { - change_euid(newcred, euip); - setsugid(p); - } - if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { - change_ruid(newcred, ruip); - setsugid(p); - } - if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && - newcred->cr_svuid != newcred->cr_uid) { - change_svuid(newcred, newcred->cr_uid); - setsugid(p); - } - p->p_ucred = newcred; - PROC_UNLOCK(p); - uifree(ruip); - uifree(euip); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - uifree(ruip); - uifree(euip); - crfree(newcred); - return (error); -} - -#ifndef _SYS_SYSPROTO_H_ -struct setregid_args { - gid_t rgid; - gid_t egid; -}; -#endif -/* ARGSUSED */ -int -setregid(register struct thread *td, struct setregid_args *uap) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - gid_t egid, rgid; - int error; - - egid = uap->egid; - rgid = uap->rgid; - AUDIT_ARG_EGID(egid); - AUDIT_ARG_RGID(rgid); - newcred = crget(); - PROC_LOCK(p); - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_setregid(oldcred, rgid, egid); - if (error) - goto fail; -#endif - - if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && - rgid != oldcred->cr_svgid) || - (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && - egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && - (error = priv_check_cred(oldcred, PRIV_CRED_SETREGID, 0)) != 0) - goto fail; - - if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { - change_egid(newcred, egid); - setsugid(p); - } - if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { - change_rgid(newcred, rgid); - setsugid(p); - } - if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && - newcred->cr_svgid != newcred->cr_groups[0]) { - change_svgid(newcred, newcred->cr_groups[0]); - setsugid(p); - } - p->p_ucred = newcred; - PROC_UNLOCK(p); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - crfree(newcred); - return (error); -} - -/* - * setresuid(ruid, euid, suid) is like setreuid except control over the saved - * uid is explicit. - */ -#ifndef _SYS_SYSPROTO_H_ -struct setresuid_args { - uid_t ruid; - uid_t euid; - uid_t suid; -}; -#endif -/* ARGSUSED */ -int -setresuid(register struct thread *td, struct setresuid_args *uap) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - uid_t euid, ruid, suid; - struct uidinfo *euip, *ruip; - int error; - - euid = uap->euid; - ruid = uap->ruid; - suid = uap->suid; - AUDIT_ARG_EUID(euid); - AUDIT_ARG_RUID(ruid); - AUDIT_ARG_SUID(suid); - newcred = crget(); - euip = uifind(euid); - ruip = uifind(ruid); - PROC_LOCK(p); - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_setresuid(oldcred, ruid, euid, suid); - if (error) - goto fail; -#endif - - if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && - ruid != oldcred->cr_svuid && - ruid != oldcred->cr_uid) || - (euid != (uid_t)-1 && euid != oldcred->cr_ruid && - euid != oldcred->cr_svuid && - euid != oldcred->cr_uid) || - (suid != (uid_t)-1 && suid != oldcred->cr_ruid && - suid != oldcred->cr_svuid && - suid != oldcred->cr_uid)) && - (error = priv_check_cred(oldcred, PRIV_CRED_SETRESUID, 0)) != 0) - goto fail; - - if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { - change_euid(newcred, euip); - setsugid(p); - } - if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { - change_ruid(newcred, ruip); - setsugid(p); - } - if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { - change_svuid(newcred, suid); - setsugid(p); - } - p->p_ucred = newcred; - PROC_UNLOCK(p); - uifree(ruip); - uifree(euip); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - uifree(ruip); - uifree(euip); - crfree(newcred); - return (error); - -} - -/* - * setresgid(rgid, egid, sgid) is like setregid except control over the saved - * gid is explicit. - */ -#ifndef _SYS_SYSPROTO_H_ -struct setresgid_args { - gid_t rgid; - gid_t egid; - gid_t sgid; -}; -#endif -/* ARGSUSED */ -int -setresgid(register struct thread *td, struct setresgid_args *uap) -{ - struct proc *p = td->td_proc; - struct ucred *newcred, *oldcred; - gid_t egid, rgid, sgid; - int error; - - egid = uap->egid; - rgid = uap->rgid; - sgid = uap->sgid; - AUDIT_ARG_EGID(egid); - AUDIT_ARG_RGID(rgid); - AUDIT_ARG_SGID(sgid); - newcred = crget(); - PROC_LOCK(p); - oldcred = crcopysafe(p, newcred); - -#ifdef MAC - error = mac_cred_check_setresgid(oldcred, rgid, egid, sgid); - if (error) - goto fail; -#endif - - if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && - rgid != oldcred->cr_svgid && - rgid != oldcred->cr_groups[0]) || - (egid != (gid_t)-1 && egid != oldcred->cr_rgid && - egid != oldcred->cr_svgid && - egid != oldcred->cr_groups[0]) || - (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && - sgid != oldcred->cr_svgid && - sgid != oldcred->cr_groups[0])) && - (error = priv_check_cred(oldcred, PRIV_CRED_SETRESGID, 0)) != 0) - goto fail; - - if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { - change_egid(newcred, egid); - setsugid(p); - } - if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { - change_rgid(newcred, rgid); - setsugid(p); - } - if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { - change_svgid(newcred, sgid); - setsugid(p); - } - p->p_ucred = newcred; - PROC_UNLOCK(p); - crfree(oldcred); - return (0); - -fail: - PROC_UNLOCK(p); - crfree(newcred); - return (error); -} - -#ifndef _SYS_SYSPROTO_H_ -struct getresuid_args { - uid_t *ruid; - uid_t *euid; - uid_t *suid; -}; -#endif -/* ARGSUSED */ -int -getresuid(register struct thread *td, struct getresuid_args *uap) -{ - struct ucred *cred; - int error1 = 0, error2 = 0, error3 = 0; - - cred = td->td_ucred; - if (uap->ruid) - error1 = copyout(&cred->cr_ruid, - uap->ruid, sizeof(cred->cr_ruid)); - if (uap->euid) - error2 = copyout(&cred->cr_uid, - uap->euid, sizeof(cred->cr_uid)); - if (uap->suid) - error3 = copyout(&cred->cr_svuid, - uap->suid, sizeof(cred->cr_svuid)); - return (error1 ? error1 : error2 ? error2 : error3); -} - -#ifndef _SYS_SYSPROTO_H_ -struct getresgid_args { - gid_t *rgid; - gid_t *egid; - gid_t *sgid; -}; -#endif -/* ARGSUSED */ -int -getresgid(register struct thread *td, struct getresgid_args *uap) -{ - struct ucred *cred; - int error1 = 0, error2 = 0, error3 = 0; - - cred = td->td_ucred; - if (uap->rgid) - error1 = copyout(&cred->cr_rgid, - uap->rgid, sizeof(cred->cr_rgid)); - if (uap->egid) - error2 = copyout(&cred->cr_groups[0], - uap->egid, sizeof(cred->cr_groups[0])); - if (uap->sgid) - error3 = copyout(&cred->cr_svgid, - uap->sgid, sizeof(cred->cr_svgid)); - return (error1 ? error1 : error2 ? error2 : error3); -} - -#ifndef _SYS_SYSPROTO_H_ -struct issetugid_args { - int dummy; -}; -#endif -/* ARGSUSED */ -int -issetugid(register struct thread *td, struct issetugid_args *uap) -{ - struct proc *p = td->td_proc; - - /* - * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, - * we use P_SUGID because we consider changing the owners as - * "tainting" as well. - * This is significant for procs that start as root and "become" - * a user without an exec - programs cannot know *everything* - * that libc *might* have put in their data segment. - */ - PROC_LOCK(p); - td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; - PROC_UNLOCK(p); - return (0); -} - -int -__setugid(struct thread *td, struct __setugid_args *uap) -{ -#ifdef REGRESSION - struct proc *p; - - p = td->td_proc; - switch (uap->flag) { - case 0: - PROC_LOCK(p); - p->p_flag &= ~P_SUGID; - PROC_UNLOCK(p); - return (0); - case 1: - PROC_LOCK(p); - p->p_flag |= P_SUGID; - PROC_UNLOCK(p); - return (0); - default: - return (EINVAL); - } -#else /* !REGRESSION */ - - return (ENOSYS); -#endif /* REGRESSION */ -} -#endif /* __rtems__ */ - -/* - * Check if gid is a member of the group set. - */ -int -groupmember(gid_t gid, struct ucred *cred) -{ - int l; - int h; - int m; - - if (cred->cr_groups[0] == gid) - return(1); - - /* - * If gid was not our primary group, perform a binary search - * of the supplemental groups. This is possible because we - * sort the groups in crsetgroups(). - */ - l = 1; - h = cred->cr_ngroups; - while (l < h) { - m = l + ((h - l) / 2); - if (cred->cr_groups[m] < gid) - l = m + 1; - else - h = m; - } - if ((l < cred->cr_ngroups) && (cred->cr_groups[l] == gid)) - return (1); - - return (0); -} - -/* - * Test the active securelevel against a given level. securelevel_gt() - * implements (securelevel > level). securelevel_ge() implements - * (securelevel >= level). Note that the logic is inverted -- these - * functions return EPERM on "success" and 0 on "failure". - * - * Due to care taken when setting the securelevel, we know that no jail will - * be less secure that its parent (or the physical system), so it is sufficient - * to test the current jail only. - * - * XXXRW: Possibly since this has to do with privilege, it should move to - * kern_priv.c. - */ -int -securelevel_gt(struct ucred *cr, int level) -{ - - return (cr->cr_prison->pr_securelevel > level ? EPERM : 0); -} - -int -securelevel_ge(struct ucred *cr, int level) -{ - - return (cr->cr_prison->pr_securelevel >= level ? EPERM : 0); -} - -/* - * 'see_other_uids' determines whether or not visibility of processes - * and sockets with credentials holding different real uids is possible - * using a variety of system MIBs. - * XXX: data declarations should be together near the beginning of the file. - */ -static int see_other_uids = 1; -SYSCTL_INT(_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW, - &see_other_uids, 0, - "Unprivileged processes may see subjects/objects with different real uid"); - -/*- - * Determine if u1 "can see" the subject specified by u2, according to the - * 'see_other_uids' policy. - * Returns: 0 for permitted, ESRCH otherwise - * Locks: none - * References: *u1 and *u2 must not change during the call - * u1 may equal u2, in which case only one reference is required - */ -static int -cr_seeotheruids(struct ucred *u1, struct ucred *u2) -{ - - if (!see_other_uids && u1->cr_ruid != u2->cr_ruid) { - if (priv_check_cred(u1, PRIV_SEEOTHERUIDS, 0) != 0) - return (ESRCH); - } - return (0); -} - -/* - * 'see_other_gids' determines whether or not visibility of processes - * and sockets with credentials holding different real gids is possible - * using a variety of system MIBs. - * XXX: data declarations should be together near the beginning of the file. - */ -static int see_other_gids = 1; -SYSCTL_INT(_security_bsd, OID_AUTO, see_other_gids, CTLFLAG_RW, - &see_other_gids, 0, - "Unprivileged processes may see subjects/objects with different real gid"); - -/* - * Determine if u1 can "see" the subject specified by u2, according to the - * 'see_other_gids' policy. - * Returns: 0 for permitted, ESRCH otherwise - * Locks: none - * References: *u1 and *u2 must not change during the call - * u1 may equal u2, in which case only one reference is required - */ -static int -cr_seeothergids(struct ucred *u1, struct ucred *u2) -{ - int i, match; - - if (!see_other_gids) { - match = 0; - for (i = 0; i < u1->cr_ngroups; i++) { - if (groupmember(u1->cr_groups[i], u2)) - match = 1; - if (match) - break; - } - if (!match) { - if (priv_check_cred(u1, PRIV_SEEOTHERGIDS, 0) != 0) - return (ESRCH); - } - } - return (0); -} - -/*- - * Determine if u1 "can see" the subject specified by u2. - * Returns: 0 for permitted, an errno value otherwise - * Locks: none - * References: *u1 and *u2 must not change during the call - * u1 may equal u2, in which case only one reference is required - */ -int -cr_cansee(struct ucred *u1, struct ucred *u2) -{ - int error; - - if ((error = prison_check(u1, u2))) - return (error); -#ifdef MAC - if ((error = mac_cred_check_visible(u1, u2))) - return (error); -#endif - if ((error = cr_seeotheruids(u1, u2))) - return (error); - if ((error = cr_seeothergids(u1, u2))) - return (error); - return (0); -} - -#ifndef __rtems__ - -/*- - * Determine if td "can see" the subject specified by p. - * Returns: 0 for permitted, an errno value otherwise - * Locks: Sufficient locks to protect p->p_ucred must be held. td really - * should be curthread. - * References: td and p must be valid for the lifetime of the call - */ -int -p_cansee(struct thread *td, struct proc *p) -{ - - /* Wrap cr_cansee() for all functionality. */ - KASSERT(td == curthread, ("%s: td not curthread", __func__)); - PROC_LOCK_ASSERT(p, MA_OWNED); - return (cr_cansee(td->td_ucred, p->p_ucred)); -} - -/* - * 'conservative_signals' prevents the delivery of a broad class of - * signals by unprivileged processes to processes that have changed their - * credentials since the last invocation of execve(). This can prevent - * the leakage of cached information or retained privileges as a result - * of a common class of signal-related vulnerabilities. However, this - * may interfere with some applications that expect to be able to - * deliver these signals to peer processes after having given up - * privilege. - */ -static int conservative_signals = 1; -SYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW, - &conservative_signals, 0, "Unprivileged processes prevented from " - "sending certain signals to processes whose credentials have changed"); -/*- - * Determine whether cred may deliver the specified signal to proc. - * Returns: 0 for permitted, an errno value otherwise. - * Locks: A lock must be held for proc. - * References: cred and proc must be valid for the lifetime of the call. - */ -int -cr_cansignal(struct ucred *cred, struct proc *proc, int signum) -{ - int error; - - PROC_LOCK_ASSERT(proc, MA_OWNED); - /* - * Jail semantics limit the scope of signalling to proc in the - * same jail as cred, if cred is in jail. - */ - error = prison_check(cred, proc->p_ucred); - if (error) - return (error); -#ifdef MAC - if ((error = mac_proc_check_signal(cred, proc, signum))) - return (error); -#endif - if ((error = cr_seeotheruids(cred, proc->p_ucred))) - return (error); - if ((error = cr_seeothergids(cred, proc->p_ucred))) - return (error); - - /* - * UNIX signal semantics depend on the status of the P_SUGID - * bit on the target process. If the bit is set, then additional - * restrictions are placed on the set of available signals. - */ - if (conservative_signals && (proc->p_flag & P_SUGID)) { - switch (signum) { - case 0: - case SIGKILL: - case SIGINT: - case SIGTERM: - case SIGALRM: - case SIGSTOP: - case SIGTTIN: - case SIGTTOU: - case SIGTSTP: - case SIGHUP: - case SIGUSR1: - case SIGUSR2: - /* - * Generally, permit job and terminal control - * signals. - */ - break; - default: - /* Not permitted without privilege. */ - error = priv_check_cred(cred, PRIV_SIGNAL_SUGID, 0); - if (error) - return (error); - } - } - - /* - * Generally, the target credential's ruid or svuid must match the - * subject credential's ruid or euid. - */ - if (cred->cr_ruid != proc->p_ucred->cr_ruid && - cred->cr_ruid != proc->p_ucred->cr_svuid && - cred->cr_uid != proc->p_ucred->cr_ruid && - cred->cr_uid != proc->p_ucred->cr_svuid) { - error = priv_check_cred(cred, PRIV_SIGNAL_DIFFCRED, 0); - if (error) - return (error); - } - - return (0); -} - -/*- - * Determine whether td may deliver the specified signal to p. - * Returns: 0 for permitted, an errno value otherwise - * Locks: Sufficient locks to protect various components of td and p - * must be held. td must be curthread, and a lock must be - * held for p. - * References: td and p must be valid for the lifetime of the call - */ -int -p_cansignal(struct thread *td, struct proc *p, int signum) -{ - - KASSERT(td == curthread, ("%s: td not curthread", __func__)); - PROC_LOCK_ASSERT(p, MA_OWNED); - if (td->td_proc == p) - return (0); - - /* - * UNIX signalling semantics require that processes in the same - * session always be able to deliver SIGCONT to one another, - * overriding the remaining protections. - */ - /* XXX: This will require an additional lock of some sort. */ - if (signum == SIGCONT && td->td_proc->p_session == p->p_session) - return (0); - /* - * Some compat layers use SIGTHR and higher signals for - * communication between different kernel threads of the same - * process, so that they expect that it's always possible to - * deliver them, even for suid applications where cr_cansignal() can - * deny such ability for security consideration. It should be - * pretty safe to do since the only way to create two processes - * with the same p_leader is via rfork(2). - */ - if (td->td_proc->p_leader != NULL && signum >= SIGTHR && - signum < SIGTHR + 4 && td->td_proc->p_leader == p->p_leader) - return (0); - - return (cr_cansignal(td->td_ucred, p, signum)); -} - -/*- - * Determine whether td may reschedule p. - * Returns: 0 for permitted, an errno value otherwise - * Locks: Sufficient locks to protect various components of td and p - * must be held. td must be curthread, and a lock must - * be held for p. - * References: td and p must be valid for the lifetime of the call - */ -int -p_cansched(struct thread *td, struct proc *p) -{ - int error; - - KASSERT(td == curthread, ("%s: td not curthread", __func__)); - PROC_LOCK_ASSERT(p, MA_OWNED); - if (td->td_proc == p) - return (0); - if ((error = prison_check(td->td_ucred, p->p_ucred))) - return (error); -#ifdef MAC - if ((error = mac_proc_check_sched(td->td_ucred, p))) - return (error); -#endif - if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) - return (error); - if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) - return (error); - if (td->td_ucred->cr_ruid != p->p_ucred->cr_ruid && - td->td_ucred->cr_uid != p->p_ucred->cr_ruid) { - error = priv_check(td, PRIV_SCHED_DIFFCRED); - if (error) - return (error); - } - return (0); -} - -/* - * The 'unprivileged_proc_debug' flag may be used to disable a variety of - * unprivileged inter-process debugging services, including some procfs - * functionality, ptrace(), and ktrace(). In the past, inter-process - * debugging has been involved in a variety of security problems, and sites - * not requiring the service might choose to disable it when hardening - * systems. - * - * XXX: Should modifying and reading this variable require locking? - * XXX: data declarations should be together near the beginning of the file. - */ -static int unprivileged_proc_debug = 1; -SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW, - &unprivileged_proc_debug, 0, - "Unprivileged processes may use process debugging facilities"); - -/*- - * Determine whether td may debug p. - * Returns: 0 for permitted, an errno value otherwise - * Locks: Sufficient locks to protect various components of td and p - * must be held. td must be curthread, and a lock must - * be held for p. - * References: td and p must be valid for the lifetime of the call - */ -int -p_candebug(struct thread *td, struct proc *p) -{ - int credentialchanged, error, grpsubset, i, uidsubset; - - KASSERT(td == curthread, ("%s: td not curthread", __func__)); - PROC_LOCK_ASSERT(p, MA_OWNED); - if (!unprivileged_proc_debug) { - error = priv_check(td, PRIV_DEBUG_UNPRIV); - if (error) - return (error); - } - if (td->td_proc == p) - return (0); - if ((error = prison_check(td->td_ucred, p->p_ucred))) - return (error); -#ifdef MAC - if ((error = mac_proc_check_debug(td->td_ucred, p))) - return (error); -#endif - if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) - return (error); - if ((error = cr_seeothergids(td->td_ucred, p->p_ucred))) - return (error); - - /* - * Is p's group set a subset of td's effective group set? This - * includes p's egid, group access list, rgid, and svgid. - */ - grpsubset = 1; - for (i = 0; i < p->p_ucred->cr_ngroups; i++) { - if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) { - grpsubset = 0; - break; - } - } - grpsubset = grpsubset && - groupmember(p->p_ucred->cr_rgid, td->td_ucred) && - groupmember(p->p_ucred->cr_svgid, td->td_ucred); - - /* - * Are the uids present in p's credential equal to td's - * effective uid? This includes p's euid, svuid, and ruid. - */ - uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid && - td->td_ucred->cr_uid == p->p_ucred->cr_svuid && - td->td_ucred->cr_uid == p->p_ucred->cr_ruid); - - /* - * Has the credential of the process changed since the last exec()? - */ - credentialchanged = (p->p_flag & P_SUGID); - - /* - * If p's gids aren't a subset, or the uids aren't a subset, - * or the credential has changed, require appropriate privilege - * for td to debug p. - */ - if (!grpsubset || !uidsubset) { - error = priv_check(td, PRIV_DEBUG_DIFFCRED); - if (error) - return (error); - } - - if (credentialchanged) { - error = priv_check(td, PRIV_DEBUG_SUGID); - if (error) - return (error); - } - - /* Can't trace init when securelevel > 0. */ - if (p == initproc) { - error = securelevel_gt(td->td_ucred, 0); - if (error) - return (error); - } - - /* - * Can't trace a process that's currently exec'ing. - * - * XXX: Note, this is not a security policy decision, it's a - * basic correctness/functionality decision. Therefore, this check - * should be moved to the caller's of p_candebug(). - */ - if ((p->p_flag & P_INEXEC) != 0) - return (EBUSY); - - return (0); -} -#endif /* __rtems__ */ - -/*- - * Determine whether the subject represented by cred can "see" a socket. - * Returns: 0 for permitted, ENOENT otherwise. - */ -int -cr_canseesocket(struct ucred *cred, struct socket *so) -{ - int error; - - error = prison_check(cred, so->so_cred); - if (error) - return (ENOENT); -#ifdef MAC - error = mac_socket_check_visible(cred, so); - if (error) - return (error); -#endif - if (cr_seeotheruids(cred, so->so_cred)) - return (ENOENT); - if (cr_seeothergids(cred, so->so_cred)) - return (ENOENT); - - return (0); -} - -#if defined(INET) || defined(INET6) -/*- - * Determine whether the subject represented by cred can "see" a socket. - * Returns: 0 for permitted, ENOENT otherwise. - */ -int -cr_canseeinpcb(struct ucred *cred, struct inpcb *inp) -{ - int error; - - error = prison_check(cred, inp->inp_cred); - if (error) - return (ENOENT); -#ifdef MAC - INP_LOCK_ASSERT(inp); - error = mac_inpcb_check_visible(cred, inp); - if (error) - return (error); -#endif - if (cr_seeotheruids(cred, inp->inp_cred)) - return (ENOENT); - if (cr_seeothergids(cred, inp->inp_cred)) - return (ENOENT); - - return (0); -} -#endif - -#ifndef __rtems__ -/*- - * Determine whether td can wait for the exit of p. - * Returns: 0 for permitted, an errno value otherwise - * Locks: Sufficient locks to protect various components of td and p - * must be held. td must be curthread, and a lock must - * be held for p. - * References: td and p must be valid for the lifetime of the call - - */ -int -p_canwait(struct thread *td, struct proc *p) -{ - int error; - - KASSERT(td == curthread, ("%s: td not curthread", __func__)); - PROC_LOCK_ASSERT(p, MA_OWNED); - if ((error = prison_check(td->td_ucred, p->p_ucred))) - return (error); -#ifdef MAC - if ((error = mac_proc_check_wait(td->td_ucred, p))) - return (error); -#endif -#if 0 - /* XXXMAC: This could have odd effects on some shells. */ - if ((error = cr_seeotheruids(td->td_ucred, p->p_ucred))) - return (error); -#endif - - return (0); -} -#endif /* __rtems__ */ - -/* - * Allocate a zeroed cred structure. - */ -struct ucred * -crget(void) -{ - register struct ucred *cr; - - cr = malloc(sizeof(*cr), M_CRED, M_WAITOK | M_ZERO); - refcount_init(&cr->cr_ref, 1); -#ifdef AUDIT - audit_cred_init(cr); -#endif -#ifdef MAC - mac_cred_init(cr); -#endif - crextend(cr, XU_NGROUPS); - return (cr); -} - -/* - * Claim another reference to a ucred structure. - */ -struct ucred * -crhold(struct ucred *cr) -{ - - refcount_acquire(&cr->cr_ref); - return (cr); -} - -/* - * Free a cred structure. Throws away space when ref count gets to 0. - */ -void -crfree(struct ucred *cr) -{ - - KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); - KASSERT(cr->cr_ref != 0xdeadc0de, ("dangling reference to ucred")); - if (refcount_release(&cr->cr_ref)) { - /* - * Some callers of crget(), such as nfs_statfs(), - * allocate a temporary credential, but don't - * allocate a uidinfo structure. - */ - if (cr->cr_uidinfo != NULL) - uifree(cr->cr_uidinfo); - if (cr->cr_ruidinfo != NULL) - uifree(cr->cr_ruidinfo); - /* - * Free a prison, if any. - */ - if (cr->cr_prison != NULL) - prison_free(cr->cr_prison); -#ifdef AUDIT - audit_cred_destroy(cr); -#endif -#ifdef MAC - mac_cred_destroy(cr); -#endif - free(cr->cr_groups, M_CRED); - free(cr, M_CRED); - } -} - -#ifndef __rtems__ -/* - * Check to see if this ucred is shared. - */ -int -crshared(struct ucred *cr) -{ - - return (cr->cr_ref > 1); -} - -/* - * Copy a ucred's contents from a template. Does not block. - */ -void -crcopy(struct ucred *dest, struct ucred *src) -{ - - KASSERT(crshared(dest) == 0, ("crcopy of shared ucred")); - bcopy(&src->cr_startcopy, &dest->cr_startcopy, - (unsigned)((caddr_t)&src->cr_endcopy - - (caddr_t)&src->cr_startcopy)); - crsetgroups(dest, src->cr_ngroups, src->cr_groups); - uihold(dest->cr_uidinfo); - uihold(dest->cr_ruidinfo); - prison_hold(dest->cr_prison); -#ifdef AUDIT - audit_cred_copy(src, dest); -#endif -#ifdef MAC - mac_cred_copy(src, dest); -#endif -} - -/* - * Dup cred struct to a new held one. - */ -struct ucred * -crdup(struct ucred *cr) -{ - struct ucred *newcr; - - newcr = crget(); - crcopy(newcr, cr); - return (newcr); -} -#endif /* __rtems__ */ - -/* - * Fill in a struct xucred based on a struct ucred. - */ -void -cru2x(struct ucred *cr, struct xucred *xcr) -{ - int ngroups; - - bzero(xcr, sizeof(*xcr)); - xcr->cr_version = XUCRED_VERSION; - xcr->cr_uid = cr->cr_uid; - - ngroups = MIN(cr->cr_ngroups, XU_NGROUPS); - xcr->cr_ngroups = ngroups; - bcopy(cr->cr_groups, xcr->cr_groups, - ngroups * sizeof(*cr->cr_groups)); -} - -#ifndef __rtems__ -/* - * small routine to swap a thread's current ucred for the correct one taken - * from the process. - */ -void -cred_update_thread(struct thread *td) -{ - struct proc *p; - struct ucred *cred; - - p = td->td_proc; - cred = td->td_ucred; - PROC_LOCK(p); - td->td_ucred = crhold(p->p_ucred); - PROC_UNLOCK(p); - if (cred != NULL) - crfree(cred); -} - -struct ucred * -crcopysafe(struct proc *p, struct ucred *cr) -{ - struct ucred *oldcred; - int groups; - - PROC_LOCK_ASSERT(p, MA_OWNED); - - oldcred = p->p_ucred; - while (cr->cr_agroups < oldcred->cr_agroups) { - groups = oldcred->cr_agroups; - PROC_UNLOCK(p); - crextend(cr, groups); - PROC_LOCK(p); - oldcred = p->p_ucred; - } - crcopy(cr, oldcred); - - return (oldcred); -} -#endif /* __rtems__ */ - -/* - * Extend the passed in credential to hold n items. - */ -static void -crextend(struct ucred *cr, int n) -{ - int cnt; - - /* Truncate? */ - if (n <= cr->cr_agroups) - return; - - /* - * We extend by 2 each time since we're using a power of two - * allocator until we need enough groups to fill a page. - * Once we're allocating multiple pages, only allocate as many - * as we actually need. The case of processes needing a - * non-power of two number of pages seems more likely than - * a real world process that adds thousands of groups one at a - * time. - */ - if ( n < PAGE_SIZE / sizeof(gid_t) ) { - if (cr->cr_agroups == 0) - cnt = MINALLOCSIZE / sizeof(gid_t); - else - cnt = cr->cr_agroups * 2; - - while (cnt < n) - cnt *= 2; - } else - cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t)); - - /* Free the old array. */ - if (cr->cr_groups) - free(cr->cr_groups, M_CRED); - - cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); - cr->cr_agroups = cnt; -} - -#ifndef __rtems__ -/* - * Copy groups in to a credential, preserving any necessary invariants. - * Currently this includes the sorting of all supplemental gids. - * crextend() must have been called before hand to ensure sufficient - * space is available. - */ -static void -crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups) -{ - int i; - int j; - gid_t g; - - KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small")); - - bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); - cr->cr_ngroups = ngrp; - - /* - * Sort all groups except cr_groups[0] to allow groupmember to - * perform a binary search. - * - * XXX: If large numbers of groups become common this should - * be replaced with shell sort like linux uses or possibly - * heap sort. - */ - for (i = 2; i < ngrp; i++) { - g = cr->cr_groups[i]; - for (j = i-1; j >= 1 && g < cr->cr_groups[j]; j--) - cr->cr_groups[j + 1] = cr->cr_groups[j]; - cr->cr_groups[j + 1] = g; - } -} - -/* - * Copy groups in to a credential after expanding it if required. - * Truncate the list to (ngroups_max + 1) if it is too large. - */ -void -crsetgroups(struct ucred *cr, int ngrp, gid_t *groups) -{ - - if (ngrp > ngroups_max + 1) - ngrp = ngroups_max + 1; - - crextend(cr, ngrp); - crsetgroups_locked(cr, ngrp, groups); -} - -/* - * Get login name, if available. - */ -#ifndef _SYS_SYSPROTO_H_ -struct getlogin_args { - char *namebuf; - u_int namelen; -}; -#endif -/* ARGSUSED */ -int -getlogin(struct thread *td, struct getlogin_args *uap) -{ - int error; - char login[MAXLOGNAME]; - struct proc *p = td->td_proc; - - if (uap->namelen > MAXLOGNAME) - uap->namelen = MAXLOGNAME; - PROC_LOCK(p); - SESS_LOCK(p->p_session); - bcopy(p->p_session->s_login, login, uap->namelen); - SESS_UNLOCK(p->p_session); - PROC_UNLOCK(p); - error = copyout(login, uap->namebuf, uap->namelen); - return(error); -} - -/* - * Set login name. - */ -#ifndef _SYS_SYSPROTO_H_ -struct setlogin_args { - char *namebuf; -}; -#endif -/* ARGSUSED */ -int -setlogin(struct thread *td, struct setlogin_args *uap) -{ - struct proc *p = td->td_proc; - int error; - char logintmp[MAXLOGNAME]; - - error = priv_check(td, PRIV_PROC_SETLOGIN); - if (error) - return (error); - error = copyinstr(uap->namebuf, logintmp, sizeof(logintmp), NULL); - if (error == ENAMETOOLONG) - error = EINVAL; - else if (!error) { - PROC_LOCK(p); - SESS_LOCK(p->p_session); - (void) memcpy(p->p_session->s_login, logintmp, - sizeof(logintmp)); - SESS_UNLOCK(p->p_session); - PROC_UNLOCK(p); - } - return (error); -} - -void -setsugid(struct proc *p) -{ - - PROC_LOCK_ASSERT(p, MA_OWNED); - p->p_flag |= P_SUGID; - if (!(p->p_pfsflags & PF_ISUGID)) - p->p_stops = 0; -} - -/*- - * Change a process's effective uid. - * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. - * References: newcred must be an exclusive credential reference for the - * duration of the call. - */ -void -change_euid(struct ucred *newcred, struct uidinfo *euip) -{ - - newcred->cr_uid = euip->ui_uid; - uihold(euip); - uifree(newcred->cr_uidinfo); - newcred->cr_uidinfo = euip; -} - -/*- - * Change a process's effective gid. - * Side effects: newcred->cr_gid will be modified. - * References: newcred must be an exclusive credential reference for the - * duration of the call. - */ -void -change_egid(struct ucred *newcred, gid_t egid) -{ - - newcred->cr_groups[0] = egid; -} - -/*- - * Change a process's real uid. - * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo - * will be updated, and the old and new cr_ruidinfo proc - * counts will be updated. - * References: newcred must be an exclusive credential reference for the - * duration of the call. - */ -void -change_ruid(struct ucred *newcred, struct uidinfo *ruip) -{ - - (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); - newcred->cr_ruid = ruip->ui_uid; - uihold(ruip); - uifree(newcred->cr_ruidinfo); - newcred->cr_ruidinfo = ruip; - (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); -} - -/*- - * Change a process's real gid. - * Side effects: newcred->cr_rgid will be updated. - * References: newcred must be an exclusive credential reference for the - * duration of the call. - */ -void -change_rgid(struct ucred *newcred, gid_t rgid) -{ - - newcred->cr_rgid = rgid; -} - -/*- - * Change a process's saved uid. - * Side effects: newcred->cr_svuid will be updated. - * References: newcred must be an exclusive credential reference for the - * duration of the call. - */ -void -change_svuid(struct ucred *newcred, uid_t svuid) -{ - - newcred->cr_svuid = svuid; -} - -/*- - * Change a process's saved gid. - * Side effects: newcred->cr_svgid will be updated. - * References: newcred must be an exclusive credential reference for the - * duration of the call. - */ -void -change_svgid(struct ucred *newcred, gid_t svgid) -{ - - newcred->cr_svgid = svgid; -} -#endif /* __rtems__ */ diff --git a/freebsd/sys/kern/kern_resource.c b/freebsd/sys/kern/kern_resource.c index 909e9e6c..a0615235 100644 --- a/freebsd/sys/kern/kern_resource.c +++ b/freebsd/sys/kern/kern_resource.c @@ -1332,7 +1332,6 @@ chgproccnt(uip, diff, max) } return (1); } -#endif /* __rtems__ */ /* * Change the total socket buffer size a user has used. @@ -1361,7 +1360,6 @@ chgsbsize(uip, hiwat, to, max) return (1); } -#ifndef __rtems__ /* * Change the count associated with number of pseudo-terminals * a given user is using. When 'max' is 0, don't enforce a limit diff --git a/freebsd/sys/kern/uipc_socket.c b/freebsd/sys/kern/uipc_socket.c index 04770f27..9b8b77d1 100644 --- a/freebsd/sys/kern/uipc_socket.c +++ b/freebsd/sys/kern/uipc_socket.c @@ -3194,6 +3194,7 @@ filt_solisten(struct knote *kn, long hint) return (! TAILQ_EMPTY(&so->so_comp)); } +#ifndef __rtems__ int socheckuid(struct socket *so, uid_t uid) { @@ -3204,6 +3205,7 @@ socheckuid(struct socket *so, uid_t uid) return (EPERM); return (0); } +#endif /* __rtems__ */ static int sysctl_somaxconn(SYSCTL_HANDLER_ARGS) @@ -3446,7 +3448,11 @@ sotoxsocket(struct socket *so, struct xsocket *xso) xso->so_oobmark = so->so_oobmark; sbtoxsockbuf(&so->so_snd, &xso->so_snd); sbtoxsockbuf(&so->so_rcv, &xso->so_rcv); +#ifndef __rtems__ xso->so_uid = so->so_cred->cr_uid; +#else /* __rtems__ */ + xso->so_uid = BSD_DEFAULT_UID; +#endif /* __rtems__ */ } diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c index 9fd9536e..b336164b 100644 --- a/freebsd/sys/netinet/in_pcb.c +++ b/freebsd/sys/netinet/in_pcb.c @@ -385,8 +385,12 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, ntohl(t->inp_laddr.s_addr) != INADDR_ANY || (t->inp_socket->so_options & SO_REUSEPORT) == 0) && +#ifndef __rtems__ (inp->inp_cred->cr_uid != t->inp_cred->cr_uid)) +#else /* __rtems__ */ + 0) +#endif /* __rtems__ */ return (EADDRINUSE); } t = in_pcblookup_local(pcbinfo, sin->sin_addr, diff --git a/freebsd/sys/netinet/ipfw/ip_fw2.c b/freebsd/sys/netinet/ipfw/ip_fw2.c index dd0c2fea..4328c50e 100644 --- a/freebsd/sys/netinet/ipfw/ip_fw2.c +++ b/freebsd/sys/netinet/ipfw/ip_fw2.c @@ -717,11 +717,19 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, } } if (insn->o.opcode == O_UID) +#ifndef __rtems__ match = ((*uc)->cr_uid == (uid_t)insn->d[0]); +#else /* __rtems__ */ + match = (BSD_DEFAULT_UID == (uid_t)insn->d[0]); +#endif /* __rtems__ */ else if (insn->o.opcode == O_GID) match = groupmember((gid_t)insn->d[0], *uc); else if (insn->o.opcode == O_JAIL) +#ifndef __rtems__ match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]); +#else /* __rtems__ */ + match = (BSD_DEFAULT_PRISON->pr_id == (int)insn->d[0]); +#endif /* __rtems__ */ return match; #endif /* __FreeBSD__ */ } @@ -1389,9 +1397,17 @@ do { \ #ifdef __FreeBSD__ &ucred_cache, args->inp); if (v == 4 /* O_UID */) +#ifndef __rtems__ key = ucred_cache->cr_uid; +#else /* __rtems__ */ + key = BSD_DEFAULT_UID; +#endif /* __rtems__ */ else if (v == 5 /* O_JAIL */) +#ifndef __rtems__ key = ucred_cache->cr_prison->pr_id; +#else /* __rtems__ */ + key = BSD_DEFAULT_PRISON->pr_id; +#endif /* __rtems__ */ #else /* !__FreeBSD__ */ (void *)&ucred_cache, (struct inpcb *)args->m); diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c index 04f321ab..4dc1208f 100644 --- a/freebsd/sys/netinet/tcp_syncache.c +++ b/freebsd/sys/netinet/tcp_syncache.c @@ -735,7 +735,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) thread0.td_ucred)) != 0) { #else /* __rtems__ */ if ((error = in6_pcbconnect(inp, (struct sockaddr *)&sin6, - rtems_bsd_thread0_ucred)) != 0) { + NULL)) != 0) { #endif /* __rtems__ */ inp->in6p_laddr = laddr6; if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { @@ -775,7 +775,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) thread0.td_ucred)) != 0) { #else /* __rtems__ */ if ((error = in_pcbconnect(inp, (struct sockaddr *)&sin, - rtems_bsd_thread0_ucred)) != 0) { + NULL)) != 0) { #endif /* __rtems__ */ inp->inp_laddr = laddr; diff --git a/freebsd/sys/netinet6/icmp6.c b/freebsd/sys/netinet6/icmp6.c index 407e91d0..54758cd4 100644 --- a/freebsd/sys/netinet6/icmp6.c +++ b/freebsd/sys/netinet6/icmp6.c @@ -724,7 +724,11 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) n->m_pkthdr.rcvif = NULL; n->m_len = 0; maxhlen = M_TRAILINGSPACE(n) - maxlen; +#ifndef __rtems__ pr = curthread->td_ucred->cr_prison; +#else /* __rtems__ */ + pr = &prison0; +#endif /* __rtems__ */ mtx_lock(&pr->pr_mtx); hlen = strlen(pr->pr_hostname); if (maxhlen > hlen) @@ -1339,7 +1343,11 @@ ni6_input(struct mbuf *m, int off) * wildcard match, if gethostname(3) side has * truncated hostname. */ +#ifndef __rtems__ pr = curthread->td_ucred->cr_prison; +#else /* __rtems__ */ + pr = &prison0; +#endif /* __rtems__ */ mtx_lock(&pr->pr_mtx); n = ni6_nametodns(pr->pr_hostname, strlen(pr->pr_hostname), 0); @@ -1467,7 +1475,11 @@ ni6_input(struct mbuf *m, int off) /* * XXX do we really have FQDN in hostname? */ +#ifndef __rtems__ pr = curthread->td_ucred->cr_prison; +#else /* __rtems__ */ + pr = &prison0; +#endif /* __rtems__ */ mtx_lock(&pr->pr_mtx); n->m_next = ni6_nametodns(pr->pr_hostname, strlen(pr->pr_hostname), oldfqdn); diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c index 1063ed43..c2134c6f 100644 --- a/freebsd/sys/netinet6/in6_ifattach.c +++ b/freebsd/sys/netinet6/in6_ifattach.c @@ -118,7 +118,11 @@ get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6) u_int8_t digest[16]; int hostnamelen; +#ifndef __rtems__ pr = curthread->td_ucred->cr_prison; +#else /* __rtems__ */ + pr = &prison0; +#endif /* __rtems__ */ mtx_lock(&pr->pr_mtx); hostnamelen = strlen(pr->pr_hostname); #if 0 @@ -642,7 +646,11 @@ in6_nigroup(struct ifnet *ifp, const char *name, int namelen, * we try to do the hostname lookup ourselves. */ if (!name && namelen == -1) { +#ifndef __rtems__ pr = curthread->td_ucred->cr_prison; +#else /* __rtems__ */ + pr = &prison0; +#endif /* __rtems__ */ mtx_lock(&pr->pr_mtx); name = pr->pr_hostname; namelen = strlen(name); diff --git a/freebsd/sys/netinet6/in6_pcb.c b/freebsd/sys/netinet6/in6_pcb.c index a5475914..09b05f5a 100644 --- a/freebsd/sys/netinet6/in6_pcb.c +++ b/freebsd/sys/netinet6/in6_pcb.c @@ -205,8 +205,12 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam, (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) || (t->inp_socket->so_options & SO_REUSEPORT) +#ifndef __rtems__ == 0) && (inp->inp_cred->cr_uid != t->inp_cred->cr_uid)) +#else /* __rtems__ */ + == 0)) +#endif /* __rtems__ */ return (EADDRINUSE); if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { @@ -222,8 +226,12 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam, (so->so_type != SOCK_STREAM || ntohl(t->inp_faddr.s_addr) == INADDR_ANY) && +#ifndef __rtems__ (inp->inp_cred->cr_uid != t->inp_cred->cr_uid)) +#else /* __rtems__ */ + 0) +#endif /* __rtems__ */ return (EADDRINUSE); } } diff --git a/freebsd/sys/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c index 6cdd340e..16b9e4fd 100644 --- a/freebsd/sys/netinet6/sctp6_usrreq.c +++ b/freebsd/sys/netinet6/sctp6_usrreq.c @@ -559,6 +559,7 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d) } } +#ifndef __rtems__ /* * this routine can probably be collasped into the one in sctp_userreq.c * since they do the same thing and now we lookup with a sockaddr @@ -630,6 +631,7 @@ out: SYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW, 0, 0, sctp6_getcred, "S,ucred", "Get the ucred of a SCTP6 connection"); +#endif /* __rtems__ */ /* This is the same as the sctp_abort() could be made common */ diff --git a/freebsd/sys/sys/jail.h b/freebsd/sys/sys/jail.h index 2e259f24..4a0b82b3 100644 --- a/freebsd/sys/sys/jail.h +++ b/freebsd/sys/sys/jail.h @@ -361,14 +361,22 @@ void prison_hold_locked(struct prison *pr); void prison_proc_hold(struct prison *); void prison_proc_free(struct prison *); int prison_ischild(struct prison *, struct prison *); +#ifndef __rtems__ int prison_equal_ip4(struct prison *, struct prison *); +#else /* __rtems__ */ +#define prison_equal_ip4(p1, p2) 1 +#endif /* __rtems__ */ int prison_get_ip4(struct ucred *cred, struct in_addr *ia); int prison_local_ip4(struct ucred *cred, struct in_addr *ia); int prison_remote_ip4(struct ucred *cred, struct in_addr *ia); int prison_check_ip4(struct ucred *cred, struct in_addr *ia); int prison_saddrsel_ip4(struct ucred *, struct in_addr *); #ifdef INET6 +#ifndef __rtems__ int prison_equal_ip6(struct prison *, struct prison *); +#else /* __rtems__ */ +#define prison_equal_ip6(p1, p2) 1 +#endif /* __rtems__ */ int prison_get_ip6(struct ucred *, struct in6_addr *); int prison_local_ip6(struct ucred *, struct in6_addr *, int); int prison_remote_ip6(struct ucred *, struct in6_addr *); diff --git a/freebsd/sys/sys/proc.h b/freebsd/sys/sys/proc.h index 2c4970e9..5cd7b64c 100644 --- a/freebsd/sys/sys/proc.h +++ b/freebsd/sys/sys/proc.h @@ -205,9 +205,7 @@ struct thread { #endif /* __rtems__ */ #ifndef __rtems__ struct mtx *volatile td_lock; /* replaces sched lock */ -#endif /* __rtems__ */ struct proc *td_proc; /* (*) Associated process. */ -#ifndef __rtems__ TAILQ_ENTRY(thread) td_plist; /* (*) All threads in this proc. */ TAILQ_ENTRY(thread) td_runq; /* (t) Run queue. */ TAILQ_ENTRY(thread) td_slpq; /* (t) Sleep queue. */ @@ -574,8 +572,6 @@ struct proc { LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/ struct kdtrace_proc *p_dtrace; /* (*) DTrace-specific data. */ struct cv p_pwait; /* (*) wait cv for exit/exec */ -#else /* __rtems__ */ - struct ucred *p_ucred; /* (c) Process owner's identity. */ #endif /* __rtems__ */ }; @@ -796,11 +792,7 @@ extern struct sx allproc_lock; extern struct sx proctree_lock; extern struct mtx ppeers_lock; extern struct proc proc0; /* Process slot for swapper. */ -#ifndef __rtems__ extern struct thread thread0; /* Primary thread in proc0. */ -#else /* __rtems__ */ -extern struct ucred *rtems_bsd_thread0_ucred; -#endif /* __rtems__ */ extern struct vmspace vmspace0; /* VM space for proc0. */ extern int hogticks; /* Limit on kernel cpu hogs. */ extern int lastpid; diff --git a/freebsd/sys/sys/resourcevar.h b/freebsd/sys/sys/resourcevar.h index 688bc22d..07700598 100644 --- a/freebsd/sys/sys/resourcevar.h +++ b/freebsd/sys/sys/resourcevar.h @@ -111,8 +111,19 @@ void addupc_task(struct thread *td, uintfptr_t pc, u_int ticks); void calccru(struct proc *p, struct timeval *up, struct timeval *sp); void calcru(struct proc *p, struct timeval *up, struct timeval *sp); int chgproccnt(struct uidinfo *uip, int diff, rlim_t maxval); +#ifndef __rtems__ int chgsbsize(struct uidinfo *uip, u_int *hiwat, u_int to, rlim_t maxval); +#else /* __rtems__ */ +static inline int +rtems_bsd_chgsbsize(u_int *hiwat, u_int to) +{ + *hiwat = to; + + return (1); +} +#define chgsbsize(uip, hiwat, to, maxval) rtems_bsd_chgsbsize(hiwat, to) +#endif /* __rtems__ */ int chgptscnt(struct uidinfo *uip, int diff, rlim_t maxval); int fuswintr(void *base); struct plimit diff --git a/freebsd/sys/sys/systm.h b/freebsd/sys/sys/systm.h index 5e196a3c..1349e6d0 100644 --- a/freebsd/sys/sys/systm.h +++ b/freebsd/sys/sys/systm.h @@ -257,9 +257,15 @@ void stopprofclock(struct proc *); void cpu_startprofclock(void); void cpu_stopprofclock(void); +#ifndef __rtems__ int cr_cansee(struct ucred *u1, struct ucred *u2); int cr_canseesocket(struct ucred *cred, struct socket *so); int cr_canseeinpcb(struct ucred *cred, struct inpcb *inp); +#else /* __rtems__ */ +#define cr_cansee(u1, u2) 1 +#define cr_canseesocket(cred, so) 1 +#define cr_canseeinpcb(cred, inp) 1 +#endif /* __rtems__ */ char *getenv(const char *name); void freeenv(char *env); diff --git a/freebsd/sys/sys/ucred.h b/freebsd/sys/sys/ucred.h index a8934cec..e1de30d3 100644 --- a/freebsd/sys/sys/ucred.h +++ b/freebsd/sys/sys/ucred.h @@ -42,6 +42,7 @@ * priv(9) interface should be used to check for privilege. */ #if defined(_KERNEL) || defined(_WANT_UCRED) +#ifndef __rtems__ struct ucred { u_int cr_ref; /* reference count */ #define cr_startcopy cr_uid @@ -63,6 +64,9 @@ struct ucred { gid_t *cr_groups; /* groups */ int cr_agroups; /* Available groups */ }; +#else /* __rtems__ */ +struct ucred; +#endif /* __rtems__ */ #define NOCRED ((struct ucred *)0) /* no credential available */ #define FSCRED ((struct ucred *)-1) /* filesystem credential */ #endif /* _KERNEL || _WANT_UCRED */ @@ -73,11 +77,13 @@ struct ucred { * This is the external representation of struct ucred. */ struct xucred { +#ifndef __rtems__ u_int cr_version; /* structure layout version */ uid_t cr_uid; /* effective user id */ short cr_ngroups; /* number of groups */ gid_t cr_groups[XU_NGROUPS]; /* groups */ void *_cr_unused1; /* compatibility with old ucred */ +#endif /* __rtems__ */ }; #define XUCRED_VERSION 0 @@ -88,6 +94,7 @@ struct xucred { struct proc; struct thread; +#ifndef __rtems__ void change_egid(struct ucred *newcred, gid_t egid); void change_euid(struct ucred *newcred, struct uidinfo *euip); void change_rgid(struct ucred *newcred, gid_t rgid); @@ -105,6 +112,11 @@ int crshared(struct ucred *cr); void cru2x(struct ucred *cr, struct xucred *xcr); void crsetgroups(struct ucred *cr, int n, gid_t *groups); int groupmember(gid_t gid, struct ucred *cred); +#else /* __rtems__ */ +#define crfree(cr) do { } while (0) +#define crhold(cr) NULL +#define cru2x(cr, xcr) do { } while (0) +#endif /* __rtems__ */ #endif /* _KERNEL */ #endif /* !_SYS_UCRED_H_ */ @@ -56,6 +56,14 @@ the current Git submodule commit is this * Process identifiers are not supported. Every PID value is set to zero (= BSD_DEFAULT_PID). +* User credentials are not supported. The following functions allow the + operation for everyone + - prison_equal_ip4(), + - chgsbsize(), + - cr_cansee(), + - cr_canseesocket() and + - cr_canseeinpcb(). + * Sebastian Huber and Joel Sherrill discussed the need for a a basic USB functionality test that is known to work on qemu pc. diff --git a/rtemsbsd/include/machine/rtems-bsd-config.h.in b/rtemsbsd/include/machine/rtems-bsd-config.h.in index 0eeb0e0a..b6738991 100644 --- a/rtemsbsd/include/machine/rtems-bsd-config.h.in +++ b/rtemsbsd/include/machine/rtems-bsd-config.h.in @@ -140,6 +140,12 @@ void rtems_bsd_assert_func(const char *file, int line, const char *func, const c #define BSD_DEFAULT_PID 0 +#define BSD_DEFAULT_UID 0 + +#define BSD_DEFAULT_GID 0 + +#define BSD_DEFAULT_PRISON (&prison0) + extern rtems_chain_control rtems_bsd_lock_chain; extern rtems_chain_control rtems_bsd_mtx_chain; diff --git a/rtemsbsd/rtems/rtems-bsd-jail.c b/rtemsbsd/rtems/rtems-bsd-jail.c index d6e0c345..819d48d8 100644 --- a/rtemsbsd/rtems/rtems-bsd-jail.c +++ b/rtemsbsd/rtems/rtems-bsd-jail.c @@ -114,7 +114,7 @@ int prison_flag(struct ucred *cred, unsigned flag) { /* This is an atomic read, so no locking is necessary. */ - return (cred->cr_prison->pr_flags & flag); + return (prison0.pr_flags & flag); } void @@ -155,15 +155,6 @@ prison_saddrsel_ip6(struct ucred *cred, struct in6_addr *ia6) } /* - * Return true if pr1 and pr2 have the same IPv4 address restrictions. - */ -int -prison_equal_ip4(struct prison *pr1, struct prison *pr2) -{ - return 1; -} - -/* * Check if given address belongs to the jail referenced by cred/prison. * * Returns 0 if jail doesn't restrict IPv4 or if address belongs to jail, @@ -214,15 +205,6 @@ prison_remote_ip4(struct ucred *cred, struct in_addr *ia) } /* - * Return true if pr1 and pr2 have the same IPv6 address restrictions. - */ -int -prison_equal_ip6(struct prison *pr1, struct prison *pr2) -{ - return 1; -} - -/* * Make sure our (source) address is set to something meaningful to this jail. * * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0) diff --git a/rtemsbsd/rtems/rtems-bsd-thread.c b/rtemsbsd/rtems/rtems-bsd-thread.c index 545b3244..cbf33cf1 100644 --- a/rtemsbsd/rtems/rtems-bsd-thread.c +++ b/rtemsbsd/rtems/rtems-bsd-thread.c @@ -48,26 +48,12 @@ #include <sys/kthread.h> #include <sys/malloc.h> #include <sys/selinfo.h> -#include <sys/filedesc.h> -#include <sys/jail.h> -#include <sys/resourcevar.h> #include <rtems/score/threadimpl.h> #include <rtems/score/objectimpl.h> RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_thread_chain); -/* FIXME: What to do with the credentials? */ -static struct ucred FIXME_ucred = { - .cr_ref = 1 /* reference count */ -}; -static struct proc FIXME_proc = { - .p_ucred = NULL /* (c) Process owner's identity. */ -}; -static struct prison FIXME_prison = { - .pr_parent = NULL -}; - static size_t rtems_bsd_extension_index; struct thread * @@ -108,7 +94,6 @@ rtems_bsd_thread_create(Thread_Control *thread, int wait) if (td != NULL) { td->td_thread = thread; - td->td_proc = &FIXME_proc; } thread->extensions[rtems_bsd_extension_index] = td; @@ -207,15 +192,6 @@ rtems_bsd_threads_init(void *arg __unused) } rtems_bsd_extension_index = rtems_object_id_get_index(ext_id); - - mtx_init(&FIXME_prison.pr_mtx, "prison lock", NULL, MTX_DEF | MTX_DUPOK); - - FIXME_ucred.cr_prison = &FIXME_prison; /* jail(2) */ - FIXME_ucred.cr_uidinfo = uifind(0); - FIXME_ucred.cr_ruidinfo = uifind(0); - FIXME_ucred.cr_ngroups = 1; /* group 0 */ - - FIXME_proc.p_ucred = crhold(&FIXME_ucred); } SYSINIT(rtems_bsd_threads, SI_SUB_INTRINSIC, SI_ORDER_ANY, rtems_bsd_threads_init, NULL); diff --git a/rtemsbsd/rtems/rtems-bsd-thread0-ucred.c b/rtemsbsd/rtems/rtems-bsd-thread0-ucred.c deleted file mode 100644 index 095e360b..00000000 --- a/rtemsbsd/rtems/rtems-bsd-thread0-ucred.c +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file - * - * @ingroup rtems_bsd_rtems - */ - -/* - * Copyright (c) 2012 On-Line Applications Research Corporation (OAR). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <machine/rtems-bsd-config.h> - -#include <rtems/bsd/sys/param.h> -#include <rtems/bsd/sys/types.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/jail.h> -#include <sys/kernel.h> -#include <sys/resourcevar.h> - -struct ucred *rtems_bsd_thread0_ucred; - -static void rtems_bsd_thread0_ucred_init(void *arg) -{ - rtems_bsd_thread0_ucred = crget(); - rtems_bsd_thread0_ucred->cr_ngroups = 1; /* group 0 */ - rtems_bsd_thread0_ucred->cr_uidinfo = uifind(0); - rtems_bsd_thread0_ucred->cr_prison = &prison0; -} - -SYSINIT(cpu, SI_SUB_INTRINSIC, SI_ORDER_SECOND, rtems_bsd_thread0_ucred_init, NULL); |