Ejemplo n.º 1
0
static int init_capabilities(void)
{
    /* helper needs following capabilities only */
    cap_value_t cap_list[] = {
        CAP_CHOWN,
        CAP_DAC_OVERRIDE,
        CAP_FOWNER,
        CAP_FSETID,
        CAP_SETGID,
        CAP_MKNOD,
        CAP_SETUID,
    };
    return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 1);
}
/*
 * from man 7 capabilities, section
 * Effect of User ID Changes on Capabilities:
 * 4. If the file system user ID is changed from 0 to nonzero (see setfsuid(2))
 * then the following capabilities are cleared from the effective set:
 * CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH,  CAP_FOWNER, CAP_FSETID,
 * CAP_LINUX_IMMUTABLE  (since  Linux 2.2.30), CAP_MAC_OVERRIDE, and CAP_MKNOD
 * (since Linux 2.2.30). If the file system UID is changed from nonzero to 0,
 * then any of these capabilities that are enabled in the permitted set
 * are enabled in the effective set.
 */
static int setfsugid(int uid, int gid)
{
    /*
     * We still need DAC_OVERRIDE because  we don't change
     * supplementary group ids, and hence may be subjected DAC rules
     */
    cap_value_t cap_list[] = {
        CAP_DAC_OVERRIDE,
    };

    setfsgid(gid);
    setfsuid(uid);

    if (uid != 0 || gid != 0) {
        return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0);
    }
    return 0;
}
Ejemplo n.º 3
0
/*
 * from man 7 capabilities, section
 * Effect of User ID Changes on Capabilities:
 * If the effective user ID is changed from nonzero to 0, then the permitted
 * set is copied to the effective set.  If the effective user ID is changed
 * from 0 to nonzero, then all capabilities are are cleared from the effective
 * set.
 *
 * The setfsuid/setfsgid man pages warn that changing the effective user ID may
 * expose the program to unwanted signals, but this is not true anymore: for an
 * unprivileged (without CAP_KILL) program to send a signal, the real or
 * effective user ID of the sending process must equal the real or saved user
 * ID of the target process.  Even when dropping privileges, it is enough to
 * keep the saved UID to a "privileged" value and virtfs-proxy-helper won't
 * be exposed to signals.  So just use setresuid/setresgid.
 */
static int setugid(int uid, int gid, int *suid, int *sgid)
{
    int retval;

    /*
     * We still need DAC_OVERRIDE because we don't change
     * supplementary group ids, and hence may be subjected DAC rules
     */
    cap_value_t cap_list[] = {
        CAP_DAC_OVERRIDE,
    };

    *suid = geteuid();
    *sgid = getegid();

    if (setresgid(-1, gid, *sgid) == -1) {
        retval = -errno;
        goto err_out;
    }

    if (setresuid(-1, uid, *suid) == -1) {
        retval = -errno;
        goto err_sgid;
    }

    if (uid != 0 || gid != 0) {
        if (do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0) < 0) {
            retval = -errno;
            goto err_suid;
        }
    }
    return 0;

err_suid:
    if (setresuid(-1, *suid, *suid) == -1) {
        abort();
    }
err_sgid:
    if (setresgid(-1, *sgid, *sgid) == -1) {
        abort();
    }
err_out:
    return retval;
}