Beispiel #1
0
int
sys_setregid(struct lwp *l, const struct sys_setregid_args *uap, register_t *retval)
{
	/* {
		syscallarg(gid_t) rgid;
		syscallarg(gid_t) egid;
	} */
	kauth_cred_t cred = l->l_cred;
	gid_t rgid, egid, svgid;

	rgid = SCARG(uap, rgid);
	egid = SCARG(uap, egid);

	if (rgid == -1)
		rgid = kauth_cred_getgid(cred);
	if (egid == -1)
		egid = kauth_cred_getegid(cred);

	/* Saved gid is set to the new egid if the rgid changed */
	svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid;

	return do_setresgid(l, rgid, egid, svgid,
			ID_R_EQ_R | ID_R_EQ_E |
			ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
			ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
}
Beispiel #2
0
/* ARGSUSED */
int
sys_setegid(struct lwp *l, const struct sys_setegid_args *uap, register_t *retval)
{
	/* {
		syscallarg(gid_t) egid;
	} */

	return do_setresgid(l, -1, SCARG(uap, egid), -1, ID_E_EQ_R | ID_E_EQ_S);
}
Beispiel #3
0
/* ARGSUSED */
int
sys_setgid(struct lwp *l, const struct sys_setgid_args *uap, register_t *retval)
{
	/* {
		syscallarg(gid_t) gid;
	} */
	gid_t gid = SCARG(uap, gid);

	return do_setresgid(l, gid, gid, gid,
			    ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
}
Beispiel #4
0
int main(int argc, char **argv)
{
    enum {
        NNP = CHAR_MAX + 1,
        RUID,
        EUID,
        RGID,
        EGID,
        REUID,
        REGID,
        CLEAR_GROUPS,
        KEEP_GROUPS,
        GROUPS,
        INHCAPS,
        LISTCAPS,
        CAPBSET,
        SECUREBITS,
        SELINUX_LABEL,
        APPARMOR_PROFILE
    };

    static const struct option longopts[] = {
        {"dump", no_argument, 0, 'd'},
        {"nnp", no_argument, 0, NNP},
        {"no-new-privs", no_argument, 0, NNP},
        {"inh-caps", required_argument, 0, INHCAPS},
        {"list-caps", no_argument, 0, LISTCAPS},
        {"ruid", required_argument, 0, RUID},
        {"euid", required_argument, 0, EUID},
        {"rgid", required_argument, 0, RGID},
        {"egid", required_argument, 0, EGID},
        {"reuid", required_argument, 0, REUID},
        {"regid", required_argument, 0, REGID},
        {"clear-groups", no_argument, 0, CLEAR_GROUPS},
        {"keep-groups", no_argument, 0, KEEP_GROUPS},
        {"groups", required_argument, 0, GROUPS},
        {"bounding-set", required_argument, 0, CAPBSET},
        {"securebits", required_argument, 0, SECUREBITS},
        {"selinux-label", required_argument, 0, SELINUX_LABEL},
        {"apparmor-profile", required_argument, 0, APPARMOR_PROFILE},
        {"help", no_argument, 0, 'h'},
        {"version", no_argument, 0, 'V'},
        {NULL, 0, 0, 0}
    };

    static const ul_excl_t excl[] = {
        /* keep in same order with enum definitions */
        {CLEAR_GROUPS, KEEP_GROUPS, GROUPS},
        {0}
    };
    int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;

    int c;
    struct privctx opts;
    int dumplevel = 0;
    int total_opts = 0;
    int list_caps = 0;

    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
    atexit(close_stdout);

    memset(&opts, 0, sizeof(opts));

    while ((c = getopt_long(argc, argv, "+dhV", longopts, NULL)) != -1) {
        err_exclusive_options(c, longopts, excl, excl_st);
        total_opts++;
        switch (c) {
        case 'd':
            dumplevel++;
            break;
        case NNP:
            if (opts.nnp)
                errx(EXIT_FAILURE,
                     _("duplicate --no-new-privs option"));
            opts.nnp = 1;
            break;
        case RUID:
            if (opts.have_ruid)
                errx(EXIT_FAILURE, _("duplicate ruid"));
            opts.have_ruid = 1;
            opts.ruid = get_user(optarg, _("failed to parse ruid"));
            break;
        case EUID:
            if (opts.have_euid)
                errx(EXIT_FAILURE, _("duplicate euid"));
            opts.have_euid = 1;
            opts.euid = get_user(optarg, _("failed to parse euid"));
            break;
        case REUID:
            if (opts.have_ruid || opts.have_euid)
                errx(EXIT_FAILURE, _("duplicate ruid or euid"));
            opts.have_ruid = opts.have_euid = 1;
            opts.ruid = opts.euid = get_user(optarg, _("failed to parse reuid"));
            break;
        case RGID:
            if (opts.have_rgid)
                errx(EXIT_FAILURE, _("duplicate rgid"));
            opts.have_rgid = 1;
            opts.rgid = get_group(optarg, _("failed to parse rgid"));
            break;
        case EGID:
            if (opts.have_egid)
                errx(EXIT_FAILURE, _("duplicate egid"));
            opts.have_egid = 1;
            opts.egid = get_group(optarg, _("failed to parse egid"));
            break;
        case REGID:
            if (opts.have_rgid || opts.have_egid)
                errx(EXIT_FAILURE, _("duplicate rgid or egid"));
            opts.have_rgid = opts.have_egid = 1;
            opts.rgid = opts.egid = get_group(optarg, _("failed to parse regid"));
            break;
        case CLEAR_GROUPS:
            if (opts.clear_groups)
                errx(EXIT_FAILURE,
                     _("duplicate --clear-groups option"));
            opts.clear_groups = 1;
            break;
        case KEEP_GROUPS:
            if (opts.keep_groups)
                errx(EXIT_FAILURE,
                     _("duplicate --keep-groups option"));
            opts.keep_groups = 1;
            break;
        case GROUPS:
            if (opts.have_groups)
                errx(EXIT_FAILURE,
                     _("duplicate --groups option"));
            parse_groups(&opts, optarg);
            break;
        case LISTCAPS:
            list_caps = 1;
            break;
        case INHCAPS:
            if (opts.caps_to_inherit)
                errx(EXIT_FAILURE,
                     _("duplicate --inh-caps option"));
            opts.caps_to_inherit = optarg;
            break;
        case CAPBSET:
            if (opts.bounding_set)
                errx(EXIT_FAILURE,
                     _("duplicate --bounding-set option"));
            opts.bounding_set = optarg;
            break;
        case SECUREBITS:
            if (opts.have_securebits)
                errx(EXIT_FAILURE,
                     _("duplicate --securebits option"));
            parse_securebits(&opts, optarg);
            break;
        case SELINUX_LABEL:
            if (opts.selinux_label)
                errx(EXIT_FAILURE,
                     _("duplicate --selinux-label option"));
            opts.selinux_label = optarg;
            break;
        case APPARMOR_PROFILE:
            if (opts.apparmor_profile)
                errx(EXIT_FAILURE,
                     _("duplicate --apparmor-profile option"));
            opts.apparmor_profile = optarg;
            break;
        case 'h':
            usage(stdout);
        case 'V':
            printf(UTIL_LINUX_VERSION);
            return EXIT_SUCCESS;
        case '?':
            usage(stderr);
        default:
            errx(EXIT_FAILURE, _("unrecognized option '%c'"), c);
        }
    }

    if (dumplevel) {
        if (total_opts != dumplevel || optind < argc)
            errx(EXIT_FAILURE,
                 _("--dump is incompatible with all other options"));
        dump(dumplevel);
        return EXIT_SUCCESS;
    }

    if (list_caps) {
        if (total_opts != 1 || optind < argc)
            errx(EXIT_FAILURE,
                 _("--list-caps must be specified alone"));
        list_known_caps();
        return EXIT_SUCCESS;
    }

    if (argc <= optind)
        errx(EXIT_FAILURE, _("No program specified"));

    if ((opts.have_rgid || opts.have_egid)
            && !opts.keep_groups && !opts.clear_groups && !opts.have_groups)
        errx(EXIT_FAILURE,
             _("--[re]gid requires --keep-groups, --clear-groups, or --groups"));

    if (opts.nnp)
        if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
            err(EXIT_FAILURE, _("disallow granting new privileges failed"));

    if (opts.selinux_label)
        do_selinux_label(opts.selinux_label);
    if (opts.apparmor_profile)
        do_apparmor_profile(opts.apparmor_profile);

    if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
        err(EXIT_FAILURE, _("keep process capabilities failed"));

    /* We're going to want CAP_SETPCAP, CAP_SETUID, and CAP_SETGID if
     * possible.  */
    bump_cap(CAP_SETPCAP);
    bump_cap(CAP_SETUID);
    bump_cap(CAP_SETGID);
    if (capng_apply(CAPNG_SELECT_CAPS) != 0)
        err(SETPRIV_EXIT_PRIVERR, _("activate capabilities"));

    if (opts.have_ruid || opts.have_euid) {
        do_setresuid(&opts);
        /* KEEPCAPS doesn't work for the effective mask. */
        if (capng_apply(CAPNG_SELECT_CAPS) != 0)
            err(SETPRIV_EXIT_PRIVERR, _("reactivate capabilities"));
    }

    if (opts.have_rgid || opts.have_egid)
        do_setresgid(&opts);

    if (opts.have_groups) {
        if (setgroups(opts.num_groups, opts.groups) != 0)
            err(SETPRIV_EXIT_PRIVERR, _("setgroups failed"));
    } else if (opts.clear_groups) {
        gid_t x = 0;
        if (setgroups(0, &x) != 0)
            err(SETPRIV_EXIT_PRIVERR, _("setgroups failed"));
    }

    if (opts.have_securebits)
        if (prctl(PR_SET_SECUREBITS, opts.securebits, 0, 0, 0) != 0)
            err(SETPRIV_EXIT_PRIVERR, _("set process securebits failed"));

    if (opts.bounding_set) {
        do_caps(CAPNG_BOUNDING_SET, opts.bounding_set);
        errno = EPERM;	/* capng doesn't set errno if we're missing CAP_SETPCAP */
        if (capng_apply(CAPNG_SELECT_BOUNDS) != 0)
            err(SETPRIV_EXIT_PRIVERR, _("apply bounding set"));
    }

    if (opts.caps_to_inherit) {
        do_caps(CAPNG_INHERITABLE, opts.caps_to_inherit);
        if (capng_apply(CAPNG_SELECT_CAPS) != 0)
            err(SETPRIV_EXIT_PRIVERR, _("apply capabilities"));
    }

    execvp(argv[optind], argv + optind);

    err(EXIT_FAILURE, _("cannot execute: %s"), argv[optind]);
}