⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys.c

📁 在linux下使用c语言编写的一个文件拷贝的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Unprivileged users may change the real gid to the effective gid * or vice versa.  (BSD-style) * * If you set the real gid at all, or set the effective gid to a value not * equal to the real gid, then the saved gid is set to the new effective gid. * * This makes it possible for a setgid 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 setregid() will be * 100% compatible with BSD.  A program which uses just setgid() will be * 100% compatible with POSIX with saved IDs.  * * SMP: There are not races, the GIDs are checked only by filesystem *      operations (as far as semantic preservation is concerned). */asmlinkage long sys_setregid(gid_t rgid, gid_t egid){    int old_rgid = current->gid;    int old_egid = current->egid;    int new_rgid = old_rgid;    int new_egid = old_egid;    if (rgid != (gid_t) - 1) {	if ((old_rgid == rgid) ||	    (current->egid == rgid) || capable(CAP_SETGID))	    new_rgid = rgid;	else	    return -EPERM;    }    if (egid != (gid_t) - 1) {	if ((old_rgid == egid) ||	    (current->egid == egid) ||	    (current->sgid == egid) || capable(CAP_SETGID))	    new_egid = egid;	else {	    return -EPERM;	}    }    if (new_egid != old_egid) {	current->mm->dumpable = 0;	wmb();    }    if (rgid != (gid_t) - 1 || (egid != (gid_t) - 1 && egid != old_rgid))	current->sgid = new_egid;    current->fsgid = new_egid;    current->egid = new_egid;    current->gid = new_rgid;    return 0;}/* * setgid() is implemented like SysV w/ SAVED_IDS  * * SMP: Same implicit races as above. */asmlinkage long sys_setgid(gid_t gid){    int old_egid = current->egid;    if (capable(CAP_SETGID)) {	if (old_egid != gid) {	    current->mm->dumpable = 0;	    wmb();	}	current->gid = current->egid = current->sgid = current->fsgid =	    gid;    } else if ((gid == current->gid) || (gid == current->sgid)) {	if (old_egid != gid) {	    current->mm->dumpable = 0;	    wmb();	}	current->egid = current->fsgid = gid;    } else	return -EPERM;    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  * * cevans - New behaviour, Oct '99 * A process may, via prctl(), elect to keep its capabilities when it * calls setuid() and switches away from uid==0. Both permitted and * effective sets will be retained. * Without this change, it was impossible for a daemon to drop only some * of its privilege. The call to setuid(!=0) would drop all privileges! * Keeping uid 0 is not an option because uid 0 owns too many vital * files.. * Thanks to Olaf Kirch and Peter Benie for spotting this. */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) &&	!current->keep_capabilities) {	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;    }}static int set_user(uid_t new_ruid, int dumpclear){    struct user_struct *new_user, *old_user;    /* 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     */    new_user = alloc_uid(new_ruid);    if (!new_user)	return -EAGAIN;    old_user = current->user;    atomic_dec(&old_user->processes);    atomic_inc(&new_user->processes);    if (dumpclear) {	current->mm->dumpable = 0;	wmb();    }    current->uid = new_ruid;    current->user = new_user;    free_uid(old_user);    return 0;}/* * 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 long sys_setreuid(uid_t ruid, uid_t euid){    int old_ruid, old_euid, old_suid, new_ruid, new_euid;    new_ruid = old_ruid = current->uid;    new_euid = old_euid = current->euid;    old_suid = current->suid;    if (ruid != (uid_t) - 1) {	new_ruid = ruid;	if ((old_ruid != ruid) &&	    (current->euid != ruid) && !capable(CAP_SETUID))	    return -EPERM;    }    if (euid != (uid_t) - 1) {	new_euid = euid;	if ((old_ruid != euid) &&	    (current->euid != euid) &&	    (current->suid != euid) && !capable(CAP_SETUID))	    return -EPERM;    }    if (new_ruid != old_ruid	&& set_user(new_ruid, new_euid != old_euid) < 0)	return -EAGAIN;    if (new_euid != old_euid) {	current->mm->dumpable = 0;	wmb();    }    current->fsuid = current->euid = new_euid;    if (ruid != (uid_t) - 1 || (euid != (uid_t) - 1 && euid != old_ruid))	current->suid = current->euid;    current->fsuid = current->euid;    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 long sys_setuid(uid_t uid){    int old_euid = current->euid;    int old_ruid, old_suid, new_ruid, new_suid;    old_ruid = new_ruid = current->uid;    old_suid = current->suid;    new_suid = old_suid;    if (capable(CAP_SETUID)) {	if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)	    return -EAGAIN;	new_suid = uid;    } else if ((uid != current->uid) && (uid != new_suid))	return -EPERM;    if (old_euid != uid) {	current->mm->dumpable = 0;	wmb();    }    current->fsuid = current->euid = uid;    current->suid = new_suid;    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 long 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) {	if (ruid != current->uid	    && set_user(ruid, euid != current->euid) < 0)	    return -EAGAIN;    }    if (euid != (uid_t) - 1) {	if (euid != current->euid) {	    current->mm->dumpable = 0;	    wmb();	}	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 long 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 long 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 (egid != (gid_t) - 1) {	if (egid != current->egid) {	    current->mm->dumpable = 0;	    wmb();	}	current->egid = egid;	current->fsgid = egid;    }    if (rgid != (gid_t) - 1)	current->gid = rgid;    if (sgid != (gid_t) - 1)	current->sgid = sgid;    return 0;}asmlinkage long 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 long 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)) {	if (uid != old_fsuid) {	    current->mm->dumpable = 0;	    wmb();	}	current->fsuid = uid;    }    /* 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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -