Exemple #1
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_suid;
	int retval;

	retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
	if (retval)
		return retval;

	old_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) {
		set_dumpable(current->mm, suid_dumpable);
		smp_wmb();
	}
	current->fsuid = current->euid = uid;
	current->suid = new_suid;

	key_fsuid_changed(current);
	proc_id_connector(current, PROC_EVENT_UID);

	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}
Exemple #2
0
/*
 * "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 (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))
		return old_fsuid;

	if (uid == current->uid || uid == current->euid ||
	    uid == current->suid || uid == current->fsuid || 
	    capable(CAP_SETUID)) {
		if (uid != old_fsuid) {
			set_dumpable(current->mm, suid_dumpable);
			smp_wmb();
		}
		current->fsuid = uid;
	}

	key_fsuid_changed(current);
	proc_id_connector(current, PROC_EVENT_UID);

	security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);

	return old_fsuid;
}
Exemple #3
0
/*
 * "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 (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))
		return old_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;
	}

	key_fsuid_changed(current);

	security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);

	return old_fsuid;
}
Exemple #4
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;
	int retval;

	retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
	if (retval)
		return retval;

	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;

	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}
/*
 * 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;
    int retval;

    retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
    if (retval)
        return retval;

    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 = suid_dumpable;
        smp_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;

    key_fsuid_changed(current);
    proc_id_connector(current, PROC_EVENT_UID);

    return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
}
/*
 * 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;
    int retval;

    retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
    if (retval)
        return retval;

    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 = suid_dumpable;
            smp_wmb();
        }
        current->euid = euid;
    }
    current->fsuid = current->euid;
    if (suid != (uid_t) -1)
        current->suid = suid;

    key_fsuid_changed(current);
    proc_id_connector(current, PROC_EVENT_UID);

    return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
}
Exemple #7
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;
	int retval;

	retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
	if (retval)
		return retval;

	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 = current->euid;
	if (suid != (uid_t) -1)
		current->suid = suid;

	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
}