aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorge Lucangeli Obes <jorgelo@google.com>2016-09-29 20:25:27 -0400
committerJorge Lucangeli Obes <jorgelo@google.com>2016-09-30 14:25:44 -0400
commitf16d6d177fdbf41f6d4389436dbbe5d2b84cd519 (patch)
tree95f72902ee8914dce7f52799a8b5ecc1e8720f58
parent200299c81d043606bf1290408251c01d46c51baf (diff)
downloadminijail-f16d6d177fdbf41f6d4389436dbbe5d2b84cd519.tar.gz
Fix BPF instruction count bug.
We were accidentally capping the total number of BPF instructions at 256 when doing label fixup. Also add a simple binary to print a compiled policy. Bug: 31848734 Test: Policy attached to the bug works. Change-Id: I9df058e2f4888289db0219d65ca97851fac515d0
-rw-r--r--Makefile17
-rw-r--r--bpf.c38
-rw-r--r--bpf.h2
-rw-r--r--parse_seccomp_policy.cc44
4 files changed, 82 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index 4cbf0b6..42d9a05 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,8 @@ endif
all: CC_BINARY(minijail0) CC_LIBRARY(libminijail.so) \
CC_LIBRARY(libminijailpreload.so)
+parse_seccomp_policy: CXX_BINARY(parse_seccomp_policy)
+
# TODO(jorgelo): convert to TEST().
tests: CC_BINARY(libminijail_unittest) CC_BINARY(syscall_filter_unittest)
@@ -30,25 +32,30 @@ clean: CLEAN(minijail0)
CC_LIBRARY(libminijail.so): LDLIBS += -lcap
CC_LIBRARY(libminijail.so): libminijail.o syscall_filter.o signal_handler.o \
- bpf.o util.o syscall_wrapper.o libconstants.gen.o libsyscalls.gen.o
+ bpf.o util.o syscall_wrapper.o libconstants.gen.o \
+ libsyscalls.gen.o
clean: CLEAN(libminijail.so)
CC_BINARY(libminijail_unittest): LDLIBS += -lcap
CC_BINARY(libminijail_unittest): libminijail_unittest.o libminijail.o \
- syscall_filter.o signal_handler.o bpf.o util.o syscall_wrapper.o \
- libconstants.gen.o libsyscalls.gen.o
+ syscall_filter.o signal_handler.o bpf.o util.o \
+ syscall_wrapper.o libconstants.gen.o libsyscalls.gen.o
clean: CLEAN(libminijail_unittest)
CC_LIBRARY(libminijailpreload.so): LDLIBS += -lcap -ldl
CC_LIBRARY(libminijailpreload.so): libminijailpreload.o libminijail.o \
- libconstants.gen.o libsyscalls.gen.o syscall_filter.o signal_handler.o \
- bpf.o util.o syscall_wrapper.o
+ libconstants.gen.o libsyscalls.gen.o syscall_filter.o \
+ signal_handler.o bpf.o util.o syscall_wrapper.o
clean: CLEAN(libminijailpreload.so)
CC_BINARY(syscall_filter_unittest): syscall_filter_unittest.o syscall_filter.o \
bpf.o util.o libconstants.gen.o libsyscalls.gen.o
clean: CLEAN(syscall_filter_unittest)
+CXX_BINARY(parse_seccomp_policy): parse_seccomp_policy.o syscall_filter.o \
+ bpf.o util.o libconstants.gen.o libsyscalls.gen.o
+clean: CLEAN(parse_policy)
+
libsyscalls.gen.o: CPPFLAGS += -I$(SRC)
libsyscalls.gen.o.depends: libsyscalls.gen.c
diff --git a/bpf.c b/bpf.c
index 20f2ed0..f56bc11 100644
--- a/bpf.c
+++ b/bpf.c
@@ -172,8 +172,8 @@ void dump_bpf_filter(struct sock_filter *filter, unsigned short len)
printf("len == %d\n", len);
printf("filter:\n");
for (i = 0; i < len; i++) {
- printf("%d: \t{ code=%#x, jt=%u, jf=%u, k=%#x \t}\n",
- i, filter[i].code, filter[i].jt, filter[i].jf, filter[i].k);
+ printf("%d: \t{ code=%#x, jt=%u, jf=%u, k=%#x \t}\n", i,
+ filter[i].code, filter[i].jt, filter[i].jf, filter[i].k);
}
}
@@ -184,41 +184,48 @@ void dump_bpf_prog(struct sock_fprog *fprog)
dump_bpf_filter(filter, len);
}
-int bpf_resolve_jumps(struct bpf_labels *labels,
- struct sock_filter *filter, size_t count)
+int bpf_resolve_jumps(struct bpf_labels *labels, struct sock_filter *filter,
+ size_t len)
{
+ size_t insn;
struct sock_filter *begin = filter;
- __u8 insn = count - 1;
- if (count < 1)
+ /* This needs at least two instructions: one jump and one label. */
+ if (len < 2)
return -1;
+
+ if (len > BPF_MAXINSNS)
+ return -1;
+
+ insn = len - 1;
+
/*
* Walk it once, backwards, to build the label table and do fixups.
* Since backward jumps are disallowed by BPF, this is easy.
*/
for (filter += insn; filter >= begin; --insn, --filter) {
- if (filter->code != (BPF_JMP+BPF_JA))
+ if (filter->code != (BPF_JMP + BPF_JA))
continue;
- switch ((filter->jt<<8)|filter->jf) {
- case (JUMP_JT<<8)|JUMP_JF:
+ switch ((filter->jt << 8) | filter->jf) {
+ case (JUMP_JT << 8) | JUMP_JF:
if (labels->labels[filter->k].location == 0xffffffff) {
fprintf(stderr, "Unresolved label: '%s'\n",
labels->labels[filter->k].label);
return 1;
}
- filter->k = labels->labels[filter->k].location -
- (insn + 1);
+ filter->k =
+ labels->labels[filter->k].location - (insn + 1);
filter->jt = 0;
filter->jf = 0;
continue;
- case (LABEL_JT<<8)|LABEL_JF:
+ case (LABEL_JT << 8) | LABEL_JF:
if (labels->labels[filter->k].location != 0xffffffff) {
fprintf(stderr, "Duplicate label use: '%s'\n",
labels->labels[filter->k].label);
return 1;
}
labels->labels[filter->k].location = insn;
- filter->k = 0; /* fall through */
+ filter->k = 0; /* Fall through. */
filter->jt = 0;
filter->jf = 0;
continue;
@@ -246,6 +253,11 @@ int bpf_label_id(struct bpf_labels *labels, const char *label)
if (!strcmp(label, begin->label))
return id;
}
+
+ /* The label wasn't found. Insert it only if there's space. */
+ if (labels->count == BPF_LABELS_MAX) {
+ return -1;
+ }
begin->label = strndup(label, MAX_BPF_LABEL_LEN);
if (!begin->label) {
return -1;
diff --git a/bpf.h b/bpf.h
index e4897e2..60f4d7b 100644
--- a/bpf.h
+++ b/bpf.h
@@ -114,7 +114,7 @@ struct seccomp_data {
#define MAX_BPF_LABEL_LEN 32
-#define BPF_LABELS_MAX 256
+#define BPF_LABELS_MAX 512 /* Each syscall could have an argument block. */
struct bpf_labels {
int count;
struct __bpf_label {
diff --git a/parse_seccomp_policy.cc b/parse_seccomp_policy.cc
new file mode 100644
index 0000000..c50b79e
--- /dev/null
+++ b/parse_seccomp_policy.cc
@@ -0,0 +1,44 @@
+// parse_seccomp_policy.cc
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdio.h>
+
+#include "bpf.h"
+#include "syscall_filter.h"
+#include "util.h"
+
+/* TODO(jorgelo): Use libseccomp disassembler here. */
+int main(int argc, char **argv) {
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <policy file>\n", argv[0]);
+ return 1;
+ }
+
+ FILE *f = fopen(argv[1], "r");
+ if (!f) {
+ pdie("fopen(%s) failed", argv[1]);
+ }
+
+ struct sock_fprog fp;
+ int res = compile_filter(f, &fp, 0);
+ if (res != 0) {
+ die("compile_filter failed");
+ }
+ dump_bpf_prog(&fp);
+
+ free(fp.filter);
+ fclose(f);
+ return 0;
+}