Esempio n. 1
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;
	int retval;

	retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
	if (retval)
		return retval;

	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;

	key_fsgid_changed(current);
	return 0;
}
Esempio n. 2
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;
	int retval;

	retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
	if (retval)
		return retval;

	if (capable(CAP_SETGID)) {
		if (old_egid != gid) {
			set_dumpable(current->mm, suid_dumpable);
			smp_wmb();
		}
		current->gid = current->egid = current->sgid = current->fsgid = gid;
	} else if ((gid == current->gid) || (gid == current->sgid)) {
		if (old_egid != gid) {
			set_dumpable(current->mm, suid_dumpable);
			smp_wmb();
		}
		current->egid = current->fsgid = gid;
	}
	else
		return -EPERM;

	key_fsgid_changed(current);
	proc_id_connector(current, PROC_EVENT_GID);
	return 0;
}
Esempio n. 3
0
/*
 * Same as above, but for rgid, egid, sgid.
 */
asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
{
	int retval;

	retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
	if (retval)
		return retval;

	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 = current->egid;
	if (rgid != (gid_t) -1)
		current->gid = rgid;
	if (sgid != (gid_t) -1)
		current->sgid = sgid;
	return 0;
}
Esempio n. 4
0
/*
 * 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;
    int retval;

    retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
    if (retval)
        return retval;

    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 = suid_dumpable;
        smp_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;
    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    return 0;
}
Esempio n. 5
0
/*
 * 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;
	int retval;

	retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
	if (retval)
		return retval;

	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;
}
Esempio n. 6
0
/*
 * Samma på svenska..
 */
asmlinkage long sys_setfsgid(gid_t gid)
{
	int old_fsgid;

	old_fsgid = current->fsgid;
	if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
		return old_fsgid;

	if (gid == current->gid || gid == current->egid ||
	    gid == current->sgid || gid == current->fsgid || 
	    capable(CAP_SETGID)) {
		if (gid != old_fsgid) {
			set_dumpable(current->mm, suid_dumpable);
			smp_wmb();
		}
		current->fsgid = gid;
		key_fsgid_changed(current);
		proc_id_connector(current, PROC_EVENT_GID);
	}
	return old_fsgid;
}
Esempio n. 7
0
/*
 * Samma på svenska..
 */
asmlinkage long sys_setfsgid(gid_t gid)
{
	int old_fsgid;

	old_fsgid = current->fsgid;
	if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
		return old_fsgid;

	if (gid == current->gid || gid == current->egid ||
	    gid == current->sgid || gid == current->fsgid || 
	    capable(CAP_SETGID))
	{
		if (gid != old_fsgid)
		{
			current->mm->dumpable = 0;
			wmb();
		}
		current->fsgid = gid;
	}
	return old_fsgid;
}
Esempio n. 8
0
/*
 * Same as above, but for rgid, egid, sgid.
 */
asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
{
    int retval;

    retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
    if (retval)
        return retval;

    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 = suid_dumpable;
            smp_wmb();
        }
        current->egid = egid;
    }
    current->fsgid = current->egid;
    if (rgid != (gid_t) -1)
        current->gid = rgid;
    if (sgid != (gid_t) -1)
        current->sgid = sgid;

    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    return 0;
}