Skip to content

Commit

Permalink
Merge branch 'setpriv-ptracer' of https://github.com/geofft/util-linux
Browse files Browse the repository at this point in the history
* 'setpriv-ptracer' of https://github.com/geofft/util-linux:
  setpriv: Add --ptracer, which calls PR_SET_PTRACER
  • Loading branch information
karelzak committed Aug 14, 2024
2 parents e3df81c + 753c0c6 commit bfb62b6
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
3 changes: 3 additions & 0 deletions sys-utils/setpriv.1.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ Set or clear securebits. The argument is a comma-separated list. The valid secur
**--pdeathsig keep**|**clear**|*<signal>*::
Keep, clear or set the parent death signal. Some LSMs, most notably SELinux and AppArmor, clear the signal when the process' credentials change. Using *--pdeathsig keep* will restore the parent death signal after changing credentials to remedy that situation.

*--ptracer* _pid_|**any**|**none**::
When Yama's restricted ptrace mode is in effect (that is, when _/proc/sys/kernel/yama/ptrace_scope_ is set to 1), allow being traced via **ptrace**(2) by the process with the specified PID, or any process, or no process. See **PR_SET_PTRACER**(2const). (Note that this is not inherited by child processes, though it is preserved across **execve**(2).) This option has no effect when Yama is not enabled or is in a mode other than restricted ptrace.

*--selinux-label* _label_::
Request a particular SELinux transition (using a transition on exec, not dyntrans). This will fail and cause *setpriv* to abort if SELinux is not in use, and the transition may be ignored or cause *execve*(2) to fail at SELinux's whim. (In particular, this is unlikely to work in conjunction with _no_new_privs_.) This is similar to *runcon*(1).

Expand Down
33 changes: 32 additions & 1 deletion sys-utils/setpriv.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ struct privctx {
clear_groups:1, /* remove groups */
init_groups:1, /* initialize groups */
reset_env:1, /* reset environment */
have_securebits:1; /* remove groups */
have_securebits:1, /* remove groups */
have_ptracer:1; /* modify ptracer */

/* uids and gids */
uid_t ruid, euid;
Expand All @@ -110,6 +111,9 @@ struct privctx {
/* parent death signal (<0 clear, 0 nothing, >0 signal) */
int pdeathsig;

/* permitted ptracer under Yama mode 1 */
long ptracer;

/* LSMs */
const char *selinux_label;
const char *apparmor_profile;
Expand Down Expand Up @@ -146,6 +150,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" --securebits <bits> set securebits\n"), out);
fputs(_(" --pdeathsig keep|clear|<signame>\n"
" set or clear parent death signal\n"), out);
fputs(_(" --ptracer <pid>|any|none allow ptracing from the given process\n"), out);
fputs(_(" --selinux-label <label> set SELinux label\n"), out);
fputs(_(" --apparmor-profile <pr> set AppArmor profile\n"), out);
fputs(_(" --landlock-access <access> add Landlock access\n"), out);
Expand Down Expand Up @@ -459,6 +464,17 @@ static void parse_pdeathsig(struct privctx *opts, const char *str)
}
}

static void parse_ptracer(struct privctx *opts, const char *str)
{
if (!strcmp(str, "any")) {
opts->ptracer = PR_SET_PTRACER_ANY;
} else if (!strcmp(str, "none")) {
opts->ptracer = 0;
} else {
opts->ptracer = strtopid_or_err(str, _("failed to parse ptracer pid"));
}
}

static void do_setresuid(const struct privctx *opts)
{
uid_t ruid, euid, suid;
Expand Down Expand Up @@ -801,6 +817,7 @@ int main(int argc, char **argv)
CAPBSET,
SECUREBITS,
PDEATHSIG,
PTRACER,
SELINUX_LABEL,
APPARMOR_PROFILE,
LANDLOCK_ACCESS,
Expand Down Expand Up @@ -829,6 +846,7 @@ int main(int argc, char **argv)
{ "bounding-set", required_argument, NULL, CAPBSET },
{ "securebits", required_argument, NULL, SECUREBITS },
{ "pdeathsig", required_argument, NULL, PDEATHSIG, },
{ "ptracer", required_argument, NULL, PTRACER, },
{ "selinux-label", required_argument, NULL, SELINUX_LABEL },
{ "apparmor-profile", required_argument, NULL, APPARMOR_PROFILE },
{ "landlock-access", required_argument, NULL, LANDLOCK_ACCESS },
Expand Down Expand Up @@ -950,6 +968,13 @@ int main(int argc, char **argv)
_("duplicate --keep-pdeathsig option"));
parse_pdeathsig(&opts, optarg);
break;
case PTRACER:
if (opts.have_ptracer)
errx(EXIT_FAILURE,
_("duplicate --ptracer option"));
opts.have_ptracer = 1;
parse_ptracer(&opts, optarg);
break;
case LISTCAPS:
list_caps = 1;
break;
Expand Down Expand Up @@ -1126,6 +1151,12 @@ int main(int argc, char **argv)
if (opts.pdeathsig && prctl(PR_SET_PDEATHSIG, opts.pdeathsig < 0 ? 0 : opts.pdeathsig) != 0)
err(SETPRIV_EXIT_PRIVERR, _("set parent death signal failed"));

if (opts.have_ptracer) {
if (prctl(PR_SET_PTRACER, opts.ptracer) < 0) {
err(SETPRIV_EXIT_PRIVERR, _("set ptracer"));
}
}

do_landlock(&opts.landlock);

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

0 comments on commit bfb62b6

Please sign in to comment.