?? sys.c
字號(hào):
if (capable(CAP_SETGID))
current->gid = current->egid = current->sgid = current->fsgid = gid;
else if ((gid == current->gid) || (gid == current->sgid))
current->egid = current->fsgid = gid;
else
return -EPERM;
if (current->egid != old_egid)
current->dumpable = 0;
return 0;
}
/*
* cap_emulate_setxuid() fixes the effective / permitted capabilities of
* a process after a call to setuid, setreuid, or setresuid.
*
* 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
* {r,e,s}uid != 0, the permitted and effective capabilities are
* cleared.
*
* 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
* capabilities of the process are cleared.
*
* 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
* capabilities are set to the permitted capabilities.
*
* fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
* never happen.
*
* -astor
*/
extern inline void cap_emulate_setxuid(int old_ruid, int old_euid,
int old_suid)
{
if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
(current->uid != 0 && current->euid != 0 && current->suid != 0)) {
cap_clear(current->cap_permitted);
cap_clear(current->cap_effective);
}
if (old_euid == 0 && current->euid != 0) {
cap_clear(current->cap_effective);
}
if (old_euid != 0 && current->euid == 0) {
current->cap_effective = current->cap_permitted;
}
}
/*
* Unprivileged users may change the real uid to the effective uid
* or vice versa. (BSD-style)
*
* If you set the real uid at all, or set the effective uid to a value not
* equal to the real uid, then the saved uid is set to the new effective uid.
*
* This makes it possible for a setuid program to completely drop its
* privileges, which is often a useful assertion to make when you are doing
* a security audit over a program.
*
* The general idea is that a program which uses just setreuid() will be
* 100% compatible with BSD. A program which uses just setuid() will be
* 100% compatible with POSIX with saved IDs.
*/
asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
{
int old_ruid, old_euid, old_suid, new_ruid;
new_ruid = old_ruid = current->uid;
old_euid = current->euid;
old_suid = current->suid;
if (ruid != (uid_t) -1) {
if ((old_ruid == ruid) ||
(current->euid==ruid) ||
capable(CAP_SETUID))
new_ruid = ruid;
else
return -EPERM;
}
if (euid != (uid_t) -1) {
if ((old_ruid == euid) ||
(current->euid == euid) ||
(current->suid == euid) ||
capable(CAP_SETUID))
current->fsuid = current->euid = euid;
else
return -EPERM;
}
if (ruid != (uid_t) -1 ||
(euid != (uid_t) -1 && euid != old_ruid))
current->suid = current->euid;
current->fsuid = current->euid;
if (current->euid != old_euid)
current->dumpable = 0;
if(new_ruid != old_ruid) {
/* What if a process setreuid()'s and this brings the
* new uid over his NPROC rlimit? We can check this now
* cheaply with the new uid cache, so if it matters
* we should be checking for it. -DaveM
*/
free_uid(current);
current->uid = new_ruid;
alloc_uid(current);
}
if (!issecure(SECURE_NO_SETUID_FIXUP)) {
cap_emulate_setxuid(old_ruid, old_euid, old_suid);
}
return 0;
}
/*
* setuid() is implemented like SysV with SAVED_IDS
*
* Note that SAVED_ID's is deficient in that a setuid root program
* like sendmail, for example, cannot set its uid to be a normal
* user and then switch back, because if you're root, setuid() sets
* the saved uid too. If you don't like this, blame the bright people
* in the POSIX committee and/or USG. Note that the BSD-style setreuid()
* will allow a root program to temporarily drop privileges and be able to
* regain them by swapping the real and effective uid.
*/
asmlinkage int sys_setuid(uid_t uid)
{
int old_euid = current->euid;
int old_ruid, old_suid, new_ruid;
old_ruid = new_ruid = current->uid;
old_suid = current->suid;
if (capable(CAP_SETUID))
new_ruid = current->euid = current->suid = current->fsuid = uid;
else if ((uid == current->uid) || (uid == current->suid))
current->fsuid = current->euid = uid;
else
return -EPERM;
if (current->euid != old_euid)
current->dumpable = 0;
if (new_ruid != old_ruid) {
/* See comment above about NPROC rlimit issues... */
free_uid(current);
current->uid = new_ruid;
alloc_uid(current);
}
if (!issecure(SECURE_NO_SETUID_FIXUP)) {
cap_emulate_setxuid(old_ruid, old_euid, old_suid);
}
return 0;
}
/*
* This function implements a generic ability to update ruid, euid,
* and suid. This allows you to implement the 4.4 compatible seteuid().
*/
asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
{
int old_ruid = current->uid;
int old_euid = current->euid;
int old_suid = current->suid;
if (!capable(CAP_SETUID)) {
if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
(ruid != current->euid) && (ruid != current->suid))
return -EPERM;
if ((euid != (uid_t) -1) && (euid != current->uid) &&
(euid != current->euid) && (euid != current->suid))
return -EPERM;
if ((suid != (uid_t) -1) && (suid != current->uid) &&
(suid != current->euid) && (suid != current->suid))
return -EPERM;
}
if (ruid != (uid_t) -1) {
/* See above commentary about NPROC rlimit issues here. */
free_uid(current);
current->uid = ruid;
alloc_uid(current);
}
if (euid != (uid_t) -1) {
if (euid != current->euid)
current->dumpable = 0;
current->euid = euid;
current->fsuid = euid;
}
if (suid != (uid_t) -1)
current->suid = suid;
if (!issecure(SECURE_NO_SETUID_FIXUP)) {
cap_emulate_setxuid(old_ruid, old_euid, old_suid);
}
return 0;
}
asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
{
int retval;
if (!(retval = put_user(current->uid, ruid)) &&
!(retval = put_user(current->euid, euid)))
retval = put_user(current->suid, suid);
return retval;
}
/*
* Same as above, but for rgid, egid, sgid.
*/
asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
{
if (!capable(CAP_SETGID)) {
if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
(rgid != current->egid) && (rgid != current->sgid))
return -EPERM;
if ((egid != (gid_t) -1) && (egid != current->gid) &&
(egid != current->egid) && (egid != current->sgid))
return -EPERM;
if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
(sgid != current->egid) && (sgid != current->sgid))
return -EPERM;
}
if (rgid != (gid_t) -1)
current->gid = rgid;
if (egid != (gid_t) -1) {
if (egid != current->egid)
current->dumpable = 0;
current->egid = egid;
current->fsgid = egid;
}
if (sgid != (gid_t) -1)
current->sgid = sgid;
return 0;
}
asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
{
int retval;
if (!(retval = put_user(current->gid, rgid)) &&
!(retval = put_user(current->egid, egid)))
retval = put_user(current->sgid, sgid);
return retval;
}
/*
* "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
* is used for "access()" and for the NFS daemon (letting nfsd stay at
* whatever uid it wants to). It normally shadows "euid", except when
* explicitly set by setfsuid() or for access..
*/
asmlinkage int sys_setfsuid(uid_t uid)
{
int old_fsuid;
old_fsuid = current->fsuid;
if (uid == current->uid || uid == current->euid ||
uid == current->suid || uid == current->fsuid ||
capable(CAP_SETUID))
current->fsuid = uid;
if (current->fsuid != old_fsuid)
current->dumpable = 0;
/* We emulate fsuid by essentially doing a scaled-down version
* of what we did in setresuid and friends. However, we only
* operate on the fs-specific bits of the process' effective
* capabilities
*
* FIXME - is fsuser used for all CAP_FS_MASK capabilities?
* if not, we might be a bit too harsh here.
*/
if (!issecure(SECURE_NO_SETUID_FIXUP)) {
if (old_fsuid == 0 && current->fsuid != 0) {
cap_t(current->cap_effective) &= ~CAP_FS_MASK;
}
if (old_fsuid != 0 && current->fsuid == 0) {
cap_t(current->cap_effective) |=
(cap_t(current->cap_permitted) & CAP_FS_MASK);
}
}
return old_fsuid;
}
/*
* Samma p
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -