*/
fcntl (pipefd [1], F_SETFD, 0);
+ /*
+ * Prevent the child from receiving more privileges than the
+ * parent. This concerns mainly suid binaries.
+ */
+ errno = 0;
+ if ( flags & capture_flag::no_new_privs
+ && prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
+ {
+ (void)write (errfd [1], (char *)&errno, sizeof(errno));
+ exit (EXIT_FAILURE);
+ }
+
int save_errno = 0;
/*
#ifndef _PIPESTREAM
#define _PIPESTREAM
+#include <sys/prctl.h>
#include <stdio.h>
#include <cstring>
static const int collect_err = 1 << 1;
static const int search_path = 1 << 2;
static const int env_passthru = 1 << 3;
+ static const int no_new_privs = 1 << 4;
static const int dflt = collect_out;
static const int collect_any = collect_out | collect_err;
BOOST_AUTO_TEST_SUITE_END() /* [pipestream->env] */
+BOOST_AUTO_TEST_SUITE(privs)
+
+#define I2N_EXPECT_OUTPUT "the caged whale knows nothing of the mighty deeps"
+const char *const echo_argv [] = { "echo", I2N_EXPECT_OUTPUT, NULL };
+
+/*
+ * this is not as such a functionality test, in the sense that
+ * we can’t easily (let alone portably) test the behavior of suid
+ * binaries. thus we only check that the option is indeed accepted
+ * in a trivial case.
+ */
+BOOST_AUTO_TEST_CASE(no_new_privs)
+{
+ ExecResult exres = ExecResult ();
+
+ const std::string result = capture_exec (echo_argv, exres,
+ capture_flag::collect_out
+ | capture_flag::search_path
+ | capture_flag::no_new_privs);
+
+ BOOST_CHECK(exres.normal_exit);
+ BOOST_CHECK_EQUAL(exres.return_code, EXIT_SUCCESS);
+ BOOST_CHECK_EQUAL(result, (std::string)I2N_EXPECT_OUTPUT + "\n");
+}
+
+BOOST_AUTO_TEST_SUITE_END() /* [pipestream->privs] */
+
BOOST_AUTO_TEST_SUITE_END() /* [pipestream] */