about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2019-09-23 11:26:29 +0200
committerLeah Neukirchen <leah@vuxu.org>2019-09-23 11:26:29 +0200
commit4986f27c25ac3d6b20df78f6b137a0b3839dbe3f (patch)
tree79284c409d41fd0d528468b87b82227eed05e67f
parent10e7856380fa97e470c77781efdd92ed110632c9 (diff)
downloadreap-4986f27c25ac3d6b20df78f6b137a0b3839dbe3f.tar.gz
reap-4986f27c25ac3d6b20df78f6b137a0b3839dbe3f.tar.xz
reap-4986f27c25ac3d6b20df78f6b137a0b3839dbe3f.zip
add -x to set PR_SET_NO_NEW_PRIVS for the children
-rw-r--r--README11
-rw-r--r--reap.114
-rw-r--r--reap.c14
3 files changed, 26 insertions, 13 deletions
diff --git a/README b/README
index d5c6af4..15b891f 100644
--- a/README
+++ b/README
@@ -4,7 +4,7 @@ NAME
      reap – run process until all its spawned processes are dead
 
 SYNOPSIS
-     reap [-vw] command line ...
+     reap [-vwx] command line ...
 
 DESCRIPTION
      The reap utility executes the given command line and ensures all spawned
@@ -19,9 +19,12 @@ DESCRIPTION
 
      The options are as follows:
 
+     -v      Verbose mode, report what reap is doing.
+
      -w      Wait for all spawned processes to finish.
 
-     -v      Verbose mode, report what reap is doing.
+     -x      Forbid execution of binaries we cannot kill (using
+             PR_SET_NO_NEW_PRIVS).
 
 EXIT STATUS
      The reap utility exits with the exit status of the spawned command.
@@ -34,7 +37,7 @@ ASSUMPTIONS
      enabled.
 
      reap can only work reliably when it has permission to kill all spawned
-     processes and they respect SIGTERM.
+     processes and they respect SIGTERM (see also -x).
 
 RATIONALE
      Keeping track of all spawned process is traditionally a hard problem on
@@ -55,4 +58,4 @@ LICENSE
 
      http://creativecommons.org/publicdomain/zero/1.0/
 
-Void Linux                      August 13, 2019                     Void Linux
+Void Linux                    September 23, 2019                    Void Linux
diff --git a/reap.1 b/reap.1
index 86cd2c9..fe51f96 100644
--- a/reap.1
+++ b/reap.1
@@ -1,4 +1,4 @@
-.Dd August 13, 2019
+.Dd September 23, 2019
 .Dt REAP 1
 .Os
 .Sh NAME
@@ -6,7 +6,7 @@
 .Nd run process until all its spawned processes are dead
 .Sh SYNOPSIS
 .Nm
-.Op Fl vw
+.Op Fl vwx
 .Ar command\ line ...
 .Sh DESCRIPTION
 The
@@ -31,12 +31,15 @@ will start slaying all children immediately.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
-.It Fl w
-Wait for all spawned processes to finish.
 .It Fl v
 Verbose mode, report what
 .Nm
 is doing.
+.It Fl w
+Wait for all spawned processes to finish.
+.It Fl x
+Forbid execution of binaries we cannot kill (using
+.Dv PR_SET_NO_NEW_PRIVS ) .
 .El
 .Sh EXIT STATUS
 The
@@ -57,7 +60,8 @@ is enabled.
 .Nm
 can only work reliably when it has permission to kill all spawned
 processes and they respect
-.Dv SIGTERM .
+.Dv SIGTERM
+.Pq see also Fl x .
 .Sh RATIONALE
 Keeping track of all spawned process is traditionally a hard problem
 on Unix systems, mainly due to daemonization by forking twice.
diff --git a/reap.c b/reap.c
index ce3016c..3700a29 100644
--- a/reap.c
+++ b/reap.c
@@ -24,6 +24,7 @@
 sig_atomic_t do_slay;
 int do_wait;
 int verbose;
+int no_new_privs;
 
 #define E(str, ...) do { fprintf(stderr, "reap: " str ": %s\n", ## __VA_ARGS__, strerror(errno)); } while (0)
 #define F(str, ...) do { E(str, ## __VA_ARGS__); exit(111); } while (0)
@@ -86,15 +87,17 @@ int
 main(int argc, char *argv[]) {
 
 	int c;
-        while ((c = getopt(argc, argv, "+vw")) != -1) {
+        while ((c = getopt(argc, argv, "+vwx")) != -1) {
 		switch (c) {
-		case 'w': do_wait = 1; break;
 		case 'v': verbose = 1; break;
+		case 'w': do_wait = 1; break;
+		case 'x': no_new_privs = 1; break;
 		default:
                         fprintf(stderr,
-"Usage: %s [-wv] COMMAND...\n"
+"Usage: %s [-vwx] COMMAND...\n"
+"\t-v\tverbose\n"
 "\t-w\twait for main command to finish (default: start reaping)\n"
-"\t-v\tverbose\n",
+"\t-x\tforbid execution of binaries we cannot kill\n",
                             argv[0]);
                         exit(1);
 		}
@@ -115,6 +118,9 @@ main(int argc, char *argv[]) {
 	pid = fork();
 	if (pid == 0) {  // in child
 		close(pipefd[0]);
+		if (no_new_privs)
+			if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0)
+				F("failed to SET_NO_NEW_PRIVS");
 		execvp(argv[optind], argv+optind);
 		unsigned char err = errno;
 		write(pipefd[1], &err, 1);