summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/syscall/uid.c
diff options
context:
space:
mode:
authorcasper <none@none>2008-03-03 07:48:05 -0800
committercasper <none@none>2008-03-03 07:48:05 -0800
commitddf7fe95b8ad67aa16deb427a0b78f4dd4ff22b1 (patch)
treed61fb6e84331e6682c0c2fbd86826fc05b4edee1 /usr/src/uts/common/syscall/uid.c
parentea4b186bb8308ae1daf547212cb90881570ff943 (diff)
downloadillumos-gate-ddf7fe95b8ad67aa16deb427a0b78f4dd4ff22b1.tar.gz
PSARC 2008/109 Fine Grained Access Permissions (FGAP)
6664443 Implement PSARC/2008/109
Diffstat (limited to 'usr/src/uts/common/syscall/uid.c')
-rw-r--r--usr/src/uts/common/syscall/uid.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/usr/src/uts/common/syscall/uid.c b/usr/src/uts/common/syscall/uid.c
index 9973b17e43..967ebaf462 100644
--- a/usr/src/uts/common/syscall/uid.c
+++ b/usr/src/uts/common/syscall/uid.c
@@ -68,7 +68,9 @@ setuid(uid_t uid)
}
/*
* Need to pre-allocate the new cred structure before grabbing
- * the p_crlock mutex.
+ * the p_crlock mutex. We can't hold on to the p_crlock for most
+ * if this though, now that we allow kernel upcalls from the
+ * policy routines.
*/
newcr = cralloc_ksid();
@@ -76,16 +78,28 @@ setuid(uid_t uid)
retry:
mutex_enter(&p->p_crlock);
+retry_locked:
cr = p->p_cred;
+ crhold(cr);
+ mutex_exit(&p->p_crlock);
if ((uid == cr->cr_ruid || uid == cr->cr_suid) &&
secpolicy_allow_setid(cr, uid, B_TRUE) != 0) {
+ mutex_enter(&p->p_crlock);
+ crfree(cr);
+ if (cr != p->p_cred)
+ goto retry_locked;
error = 0;
crcopy_to(cr, newcr);
p->p_cred = newcr;
newcr->cr_uid = uid;
crsetsid(newcr, ksp, KSID_USER);
+ mutex_exit(&p->p_crlock);
} else if ((error = secpolicy_allow_setid(cr, uid, B_FALSE)) == 0) {
+ mutex_enter(&p->p_crlock);
+ crfree(cr);
+ if (cr != p->p_cred)
+ goto retry_locked;
if (!uidchge && uid != cr->cr_ruid) {
/*
* The ruid of the process is going to change. In order
@@ -123,14 +137,14 @@ retry:
newcr->cr_uid = uid;
crsetsid(newcr, ksp, KSID_USER);
ASSERT(uid != oldruid ? uidchge : 1);
+ mutex_exit(&p->p_crlock);
} else {
crfree(newcr);
+ crfree(cr);
if (ksp != NULL)
ksid_rele(ksp);
}
- mutex_exit(&p->p_crlock);
-
/*
* We decrement the number of processes associated with the oldruid
* to match the increment above, even if the ruid of the process
@@ -194,7 +208,9 @@ seteuid(uid_t uid)
newcr = cralloc_ksid();
p = ttoproc(curthread);
mutex_enter(&p->p_crlock);
- cr = p->p_cred;
+retry:
+ crhold(cr = p->p_cred);
+ mutex_exit(&p->p_crlock);
if (uid == cr->cr_ruid || uid == cr->cr_uid || uid == cr->cr_suid ||
(error = secpolicy_allow_setid(cr, uid, B_FALSE)) == 0) {
@@ -203,6 +219,10 @@ seteuid(uid_t uid)
* set-uid process must be marked to produce no core dump,
* if the effective uid did changed.
*/
+ mutex_enter(&p->p_crlock);
+ crfree(cr);
+ if (cr != p->p_cred)
+ goto retry;
if (cr->cr_uid != uid && error == 0)
do_nocd = 1;
error = 0;
@@ -210,15 +230,7 @@ seteuid(uid_t uid)
p->p_cred = newcr;
newcr->cr_uid = uid;
crsetsid(newcr, ksp, KSID_USER);
- } else {
- crfree(newcr);
- if (ksp != NULL)
- ksid_rele(ksp);
- }
-
- mutex_exit(&p->p_crlock);
-
- if (error == 0) {
+ mutex_exit(&p->p_crlock);
if (do_nocd) {
mutex_enter(&p->p_lock);
p->p_flag |= SNOCD;
@@ -227,6 +239,11 @@ seteuid(uid_t uid)
crset(p, newcr); /* broadcast to process threads */
return (0);
}
+
+ crfree(newcr);
+ crfree(cr);
+ if (ksp != NULL)
+ ksid_rele(ksp);
return (set_errno(error));
}
@@ -272,16 +289,30 @@ setreuid(uid_t ruid, uid_t euid)
retry:
mutex_enter(&p->p_crlock);
- cr = p->p_cred;
+retry_locked:
+ crhold(cr = p->p_cred);
+ mutex_exit(&p->p_crlock);
if (ruid != -1 && ruid != cr->cr_ruid && ruid != cr->cr_uid &&
secpolicy_allow_setid(cr, ruid, B_FALSE) != 0) {
+ mutex_enter(&p->p_crlock);
+ crfree(cr);
+ if (cr != p->p_cred)
+ goto retry_locked;
error = EPERM;
} else if (euid != -1 &&
euid != cr->cr_ruid && euid != cr->cr_uid &&
euid != cr->cr_suid && secpolicy_allow_setid(cr, euid, B_FALSE)) {
+ mutex_enter(&p->p_crlock);
+ crfree(cr);
+ if (cr != p->p_cred)
+ goto retry_locked;
error = EPERM;
} else {
+ mutex_enter(&p->p_crlock);
+ crfree(cr);
+ if (cr != p->p_cred)
+ goto retry_locked;
if (!uidchge && ruid != -1 && cr->cr_ruid != ruid) {
/*
* The ruid of the process is going to change. In order