Merge changes I6d73bcad,I41775eb1,I53342db7,Id8046a4f
* changes:
gen_constants: rewrite sed to be a bit more readable
gen_constants: combine sort|uniq
gen_constants: simplify grep by using ERE by default
gen_{constants,syscalls}: fix sed/grep locale issues
diff --git a/libminijail.c b/libminijail.c
index 2497115..a797823 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -869,22 +869,20 @@
* uncommon for that to be less (if an older kernel) or more (if a newer
* kernel). So suck up the answer via /proc.
*/
-static int run_cap_valid(unsigned int cap)
+static int get_last_valid_cap()
{
- static unsigned int last_cap;
+ const char cap_file[] = "/proc/sys/kernel/cap_last_cap";
+ FILE *fp = fopen(cap_file, "re");
+ int last_valid_cap;
- if (!last_cap) {
- const char cap_file[] = "/proc/sys/kernel/cap_last_cap";
- FILE *fp = fopen(cap_file, "re");
- if (fscanf(fp, "%u", &last_cap) != 1)
- pdie("fscanf(%s)", cap_file);
- fclose(fp);
- }
+ if (fscanf(fp, "%u", &last_valid_cap) != 1)
+ pdie("fscanf(%s)", cap_file);
+ fclose(fp);
- return cap <= last_cap;
+ return last_valid_cap;
}
-void drop_caps(const struct minijail *j)
+void drop_caps(const struct minijail *j, int last_valid_cap)
{
cap_t caps = cap_get_proc();
cap_value_t flag[1];
@@ -898,7 +896,7 @@
die("can't clear effective caps");
if (cap_clear_flag(caps, CAP_PERMITTED))
die("can't clear permitted caps");
- for (i = 0; i < sizeof(j->caps) * 8 && run_cap_valid(i); ++i) {
+ for (i = 0; i < sizeof(j->caps) * 8 && i <= last_valid_cap; ++i) {
/* Keep CAP_SETPCAP for dropping bounding set bits. */
if (i != CAP_SETPCAP && !(j->caps & (one << i)))
continue;
@@ -919,7 +917,7 @@
* have been used above to raise a capability that wasn't already
* present. This requires CAP_SETPCAP, so we raised/kept it above.
*/
- for (i = 0; i < sizeof(j->caps) * 8 && run_cap_valid(i); ++i) {
+ for (i = 0; i < sizeof(j->caps) * 8 && i <= last_valid_cap; ++i) {
if (j->caps & (one << i))
continue;
if (prctl(PR_CAPBSET_DROP, i))
@@ -980,6 +978,12 @@
void API minijail_enter(const struct minijail *j)
{
+ /*
+ * Get the last valid cap from /proc, since /proc can be unmounted
+ * before drop_caps().
+ */
+ int last_valid_cap = get_last_valid_cap();
+
if (j->flags.pids)
die("tried to enter a pid-namespaced jail;"
" try minijail_run()?");
@@ -1044,7 +1048,7 @@
if (j->flags.no_new_privs) {
drop_ugid(j);
if (j->flags.caps)
- drop_caps(j);
+ drop_caps(j, last_valid_cap);
set_seccomp_filter(j);
} else {
@@ -1059,7 +1063,7 @@
drop_ugid(j);
if (j->flags.caps)
- drop_caps(j);
+ drop_caps(j, last_valid_cap);
}
/*
@@ -1236,14 +1240,6 @@
NULL, NULL, true);
}
-int API minijail_run_pid_pipe(struct minijail *j, const char *filename,
- char *const argv[], pid_t *pchild_pid,
- int *pstdin_fd)
-{
- return minijail_run_internal(j, filename, argv, pchild_pid, pstdin_fd,
- NULL, NULL, true);
-}
-
int API minijail_run_pid_pipes(struct minijail *j, const char *filename,
char *const argv[], pid_t *pchild_pid,
int *pstdin_fd, int *pstdout_fd, int *pstderr_fd)
@@ -1259,6 +1255,14 @@
false);
}
+int API minijail_run_pid_pipes_no_preload(struct minijail *j,
+ const char *filename, char *const argv[],
+ pid_t *pchild_pid,
+ int *pstdin_fd, int *pstdout_fd, int *pstderr_fd) {
+ return minijail_run_internal(j, filename, argv, pchild_pid,
+ pstdin_fd, pstdout_fd, pstderr_fd, false);
+}
+
int minijail_run_internal(struct minijail *j, const char *filename,
char *const argv[], pid_t *pchild_pid,
int *pstdin_fd, int *pstdout_fd, int *pstderr_fd,
diff --git a/libminijail.h b/libminijail.h
index d6c3c42..62e4007 100644
--- a/libminijail.h
+++ b/libminijail.h
@@ -149,10 +149,14 @@
* Update |*pchild_pid| with the pid of the child.
* Update |*pstdin_fd| with a fd that allows writing to the child's
* standard input.
+ * Update |*pstdout_fd| with a fd that allows reading from the child's
+ * standard output.
+ * Update |*pstderr_fd| with a fd that allows reading from the child's
+ * standard error.
*/
-int minijail_run_pid_pipe(struct minijail *j, const char *filename,
- char *const argv[], pid_t *pchild_pid,
- int *pstdin_fd);
+int minijail_run_pid_pipes(struct minijail *j, const char *filename,
+ char *const argv[], pid_t *pchild_pid,
+ int *pstdin_fd, int *pstdout_fd, int *pstderr_fd);
/* Run the specified command in the given minijail, execve(2)-style.
* Update |*pchild_pid| with the pid of the child.
@@ -162,10 +166,11 @@
* standard output.
* Update |*pstderr_fd| with a fd that allows reading from the child's
* standard error.
+ * Used with static binaries, or on systems without support for LD_PRELOAD.
*/
-int minijail_run_pid_pipes(struct minijail *j, const char *filename,
- char *const argv[], pid_t *pchild_pid,
- int *pstdin_fd, int *pstdout_fd, int *pstderr_fd);
+int minijail_run_pid_pipes_no_preload(struct minijail *j, const char *filename,
+ char *const argv[], pid_t *pchild_pid,
+ int *pstdin_fd, int *pstdout_fd, int *pstderr_fd);
/* Kill the specified minijail. The minijail must have been created with pid
* namespacing; if it was, all processes inside it are atomically killed.
diff --git a/libminijail_unittest.c b/libminijail_unittest.c
index 011ce85..1a98741 100644
--- a/libminijail_unittest.c
+++ b/libminijail_unittest.c
@@ -145,30 +145,6 @@
/*
* TODO(jorgelo): rewrite these tests to not depend on libminijailpreload.so.
-TEST(test_minijail_run_pid_pipe) {
- pid_t pid;
- int child_stdin;
- int mj_run_ret;
- ssize_t write_ret;
- int status;
- char filename[] = "test/read_stdin";
- char *argv[2];
- argv[0] = filename;
- argv[1] = NULL;
-
- struct minijail *j = minijail_new();
- mj_run_ret = minijail_run_pid_pipe(j, argv[0], argv, &pid, &child_stdin);
- EXPECT_EQ(mj_run_ret, 0);
- write_ret = write(child_stdin, "test\n", strlen("test\n"));
- EXPECT_GT(write_ret, -1);
-
- waitpid(pid, &status, 0);
- ASSERT_TRUE(WIFEXITED(status));
- EXPECT_EQ(WEXITSTATUS(status), 0);
-
- minijail_destroy(j);
-}
-
TEST(test_minijail_run_pid_pipes) {
pid_t pid;
int child_stdin, child_stdout, child_stderr;