Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_prot.c
Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
static MALLOC_DEFINE(M_CRED, "cred", "credentials"); | static MALLOC_DEFINE(M_CRED, "cred", "credentials"); | ||||
SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, | ||||
"BSD security policy"); | "BSD security policy"); | ||||
static void crfree_final(struct ucred *cr); | static void crfree_final(struct ucred *cr); | ||||
static void crsetgroups_locked(struct ucred *cr, int ngrp, | static void crsetgroups_locked(struct ucred *cr, int ngrp, | ||||
gid_t *groups); | gid_t *groups); | ||||
static void crsortgroups(struct ucred *cr); | |||||
static void crcopy_withoutgroups(struct ucred *dest, struct ucred *src); | |||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct getpid_args { | struct getpid_args { | ||||
int dummy; | int dummy; | ||||
}; | }; | ||||
#endif | #endif | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
int | int | ||||
▲ Show 20 Lines • Show All 727 Lines • ▼ Show 20 Lines | kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups) | ||||
struct ucred *newcred, *oldcred; | struct ucred *newcred, *oldcred; | ||||
int error; | int error; | ||||
MPASS(ngrp <= ngroups_max + 1); | MPASS(ngrp <= ngroups_max + 1); | ||||
AUDIT_ARG_GROUPSET(groups, ngrp); | AUDIT_ARG_GROUPSET(groups, ngrp); | ||||
newcred = crget(); | newcred = crget(); | ||||
crextend(newcred, ngrp); | crextend(newcred, ngrp); | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
oldcred = crcopysafe(p, newcred); | oldcred = p->p_ucred; | ||||
crcopy_withoutgroups(newcred, oldcred); | |||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_cred_check_setgroups(oldcred, ngrp, groups); | error = mac_cred_check_setgroups(oldcred, ngrp, groups); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
#endif | #endif | ||||
error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS); | error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
if (ngrp == 0) { | if (ngrp == 0) { | ||||
/* | /* | ||||
* setgroups(0, NULL) is a legitimate way of clearing the | * setgroups(0, NULL) is a legitimate way of clearing the | ||||
* groups vector on non-BSD systems (which generally do not | * groups vector on non-BSD systems (which generally do not | ||||
* have the egid in the groups[0]). We risk security holes | * have the egid in the groups[0]). We risk security holes | ||||
* when running non-BSD software if we do not do the same. | * when running non-BSD software if we do not do the same. | ||||
*/ | */ | ||||
newcred->cr_ngroups = 1; | newcred->cr_ngroups = 1; | ||||
} else { | } else { | ||||
crsetgroups_locked(newcred, ngrp, groups); | crsetgroups_locked(newcred, ngrp, groups); | ||||
crsortgroups(newcred); | |||||
} | } | ||||
setsugid(p); | setsugid(p); | ||||
proc_set_cred(p, newcred); | proc_set_cred(p, newcred); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
crfree(oldcred); | crfree(oldcred); | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
▲ Show 20 Lines • Show All 1,228 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Copy a ucred's contents from a template. Does not block. | * Copy a ucred's contents from a template. Does not block. | ||||
*/ | */ | ||||
void | void | ||||
crcopy(struct ucred *dest, struct ucred *src) | crcopy(struct ucred *dest, struct ucred *src) | ||||
{ | { | ||||
KASSERT(dest->cr_ref == 1, ("crcopy of shared ucred")); | KASSERT(dest->cr_ref == 1, ("crcopy of shared ucred")); | ||||
crextend(dest, src->cr_ngroups); | |||||
crcopy_withoutgroups(dest, src); | |||||
crsetgroups_locked(dest, src->cr_ngroups, src->cr_groups); | |||||
} | |||||
static void | |||||
crcopy_withoutgroups(struct ucred *dest, struct ucred *src) | |||||
{ | |||||
KASSERT(dest->cr_ref == 1, ("crcopy of shared ucred")); | |||||
bcopy(&src->cr_startcopy, &dest->cr_startcopy, | bcopy(&src->cr_startcopy, &dest->cr_startcopy, | ||||
(unsigned)((caddr_t)&src->cr_endcopy - | (unsigned)((caddr_t)&src->cr_endcopy - | ||||
(caddr_t)&src->cr_startcopy)); | (caddr_t)&src->cr_startcopy)); | ||||
crsetgroups(dest, src->cr_ngroups, src->cr_groups); | |||||
uihold(dest->cr_uidinfo); | uihold(dest->cr_uidinfo); | ||||
uihold(dest->cr_ruidinfo); | uihold(dest->cr_ruidinfo); | ||||
prison_hold(dest->cr_prison); | prison_hold(dest->cr_prison); | ||||
loginclass_hold(dest->cr_loginclass); | loginclass_hold(dest->cr_loginclass); | ||||
/* | |||||
* Preserve the egid | |||||
*/ | |||||
dest->cr_ngroups = 1; | |||||
dest->cr_groups[0] = src->cr_groups[0]; | |||||
#ifdef AUDIT | #ifdef AUDIT | ||||
audit_cred_copy(src, dest); | audit_cred_copy(src, dest); | ||||
#endif | #endif | ||||
#ifdef MAC | #ifdef MAC | ||||
mac_cred_copy(src, dest); | mac_cred_copy(src, dest); | ||||
#endif | #endif | ||||
} | } | ||||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | crextend(struct ucred *cr, int n) | ||||
if (cr->cr_groups != cr->cr_smallgroups) | if (cr->cr_groups != cr->cr_smallgroups) | ||||
free(cr->cr_groups, M_CRED); | free(cr->cr_groups, M_CRED); | ||||
cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); | cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); | ||||
cr->cr_agroups = cnt; | cr->cr_agroups = cnt; | ||||
} | } | ||||
/* | /* | ||||
* Copy groups in to a credential, preserving any necessary invariants. | * Copy groups in to a credential, _does_not_ preserve any invariants. | ||||
kib: This sentence sounds weird and probably useless. If function does not preserve any invariants… | |||||
* Currently this includes the sorting of all supplemental gids. | |||||
* crextend() must have been called before hand to ensure sufficient | * crextend() must have been called before hand to ensure sufficient | ||||
* space is available. | * space is available. | ||||
*/ | */ | ||||
static void | static void | ||||
crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups) | 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")); | KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small")); | ||||
bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); | bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); | ||||
cr->cr_ngroups = ngrp; | cr->cr_ngroups = ngrp; | ||||
} | |||||
/* | /* | ||||
* Sort all groups except cr_groups[0] to allow groupmember to | * Sort all groups except cr_groups[0] to allow groupmember to | ||||
* perform a binary search. | * perform a binary search. | ||||
* | */ | ||||
static void | |||||
crsortgroups(struct ucred *cr) | |||||
{ | |||||
int i; | |||||
int j; | |||||
gid_t g; | |||||
/* | |||||
* XXX: If large numbers of groups become common this should | * XXX: If large numbers of groups become common this should | ||||
* be replaced with shell sort like linux uses or possibly | * be replaced with shell sort like linux uses or possibly | ||||
* heap sort. | * heap sort. | ||||
*/ | */ | ||||
for (i = 2; i < ngrp; i++) { | for (i = 2; i < cr->cr_ngroups; i++) { | ||||
g = cr->cr_groups[i]; | g = cr->cr_groups[i]; | ||||
for (j = i-1; j >= 1 && g < cr->cr_groups[j]; j--) | 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] = cr->cr_groups[j]; | ||||
cr->cr_groups[j + 1] = g; | cr->cr_groups[j + 1] = g; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Copy groups in to a credential after expanding it if required. | * Copy groups in to a credential after expanding it if required, | ||||
* preserving any necessary invariants. | |||||
* Currently this includes the sorting of all supplemental gids. | |||||
* Truncate the list to (ngroups_max + 1) if it is too large. | * Truncate the list to (ngroups_max + 1) if it is too large. | ||||
*/ | */ | ||||
void | void | ||||
crsetgroups(struct ucred *cr, int ngrp, gid_t *groups) | crsetgroups(struct ucred *cr, int ngrp, gid_t *groups) | ||||
{ | { | ||||
if (ngrp > ngroups_max + 1) | if (ngrp > ngroups_max + 1) | ||||
ngrp = ngroups_max + 1; | ngrp = ngroups_max + 1; | ||||
crextend(cr, ngrp); | crextend(cr, ngrp); | ||||
crsetgroups_locked(cr, ngrp, groups); | crsetgroups_locked(cr, ngrp, groups); | ||||
crsortgroups(cr); | |||||
} | } | ||||
/* | /* | ||||
* Get login name, if available. | * Get login name, if available. | ||||
*/ | */ | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct getlogin_args { | struct getlogin_args { | ||||
char *namebuf; | char *namebuf; | ||||
▲ Show 20 Lines • Show All 154 Lines • Show Last 20 Lines |
This sentence sounds weird and probably useless. If function does not preserve any invariants, it cannot be used.
I suspect that you just want to say that no sorting is done, instead.