Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(774)

Unified Diff: sandbox/linux/seccomp-bpf/demo.cc

Issue 12223109: SECCOMP-BPF: Refactor the BPF sandbox API to use fewer "static" fields and methods. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sandbox/linux/seccomp-bpf/codegen.cc ('k') | sandbox/linux/seccomp-bpf/die.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sandbox/linux/seccomp-bpf/demo.cc
diff --git a/sandbox/linux/seccomp-bpf/demo.cc b/sandbox/linux/seccomp-bpf/demo.cc
index fcae39936284d81d7669ee04c91a77c80fa74494..b2622ec452d9b29382249827d8e898bc773b6e9d 100644
--- a/sandbox/linux/seccomp-bpf/demo.cc
+++ b/sandbox/linux/seccomp-bpf/demo.cc
@@ -10,6 +10,7 @@
#include <netinet/udp.h>
#include <pthread.h>
#include <signal.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,12 +27,10 @@
#include <unistd.h>
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/seccomp-bpf/util.h"
using playground2::arch_seccomp_data;
using playground2::ErrorCode;
using playground2::Sandbox;
-using playground2::Util;
#define ERR EPERM
@@ -41,6 +40,106 @@ using playground2::Util;
// actually enforce restrictions in a meaningful way:
#define _exit(x) do { } while (0)
+namespace {
+
+bool SendFds(int transport, const void *buf, size_t len, ...) {
+ int count = 0;
+ va_list ap;
+ va_start(ap, len);
+ while (va_arg(ap, int) >= 0) {
+ ++count;
+ }
+ va_end(ap);
+ if (!count) {
+ return false;
+ }
+ char cmsg_buf[CMSG_SPACE(count*sizeof(int))];
+ memset(cmsg_buf, 0, sizeof(cmsg_buf));
+ struct iovec iov[2] = { { 0 } };
+ struct msghdr msg = { 0 };
+ int dummy = 0;
+ iov[0].iov_base = &dummy;
+ iov[0].iov_len = sizeof(dummy);
+ if (buf && len > 0) {
+ iov[1].iov_base = const_cast<void *>(buf);
+ iov[1].iov_len = len;
+ }
+ msg.msg_iov = iov;
+ msg.msg_iovlen = (buf && len > 0) ? 2 : 1;
+ msg.msg_control = cmsg_buf;
+ msg.msg_controllen = CMSG_LEN(count*sizeof(int));
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(count*sizeof(int));
+ va_start(ap, len);
+ for (int i = 0, fd; (fd = va_arg(ap, int)) >= 0; ++i) {
+ (reinterpret_cast<int *>(CMSG_DATA(cmsg)))[i] = fd;
+ }
+ return sendmsg(transport, &msg, 0) ==
+ static_cast<ssize_t>(sizeof(dummy) + ((buf && len > 0) ? len : 0));
+}
+
+bool GetFds(int transport, void *buf, size_t *len, ...) {
+ int count = 0;
+ va_list ap;
+ va_start(ap, len);
+ for (int *fd; (fd = va_arg(ap, int *)) != NULL; ++count) {
+ *fd = -1;
+ }
+ va_end(ap);
+ if (!count) {
+ return false;
+ }
+ char cmsg_buf[CMSG_SPACE(count*sizeof(int))];
+ memset(cmsg_buf, 0, sizeof(cmsg_buf));
+ struct iovec iov[2] = { { 0 } };
+ struct msghdr msg = { 0 };
+ int err;
+ iov[0].iov_base = &err;
+ iov[0].iov_len = sizeof(int);
+ if (buf && len && *len > 0) {
+ iov[1].iov_base = buf;
+ iov[1].iov_len = *len;
+ }
+ msg.msg_iov = iov;
+ msg.msg_iovlen = (buf && len && *len > 0) ? 2 : 1;
+ msg.msg_control = cmsg_buf;
+ msg.msg_controllen = CMSG_LEN(count*sizeof(int));
+ ssize_t bytes = recvmsg(transport, &msg, 0);
+ if (len) {
+ *len = bytes > static_cast<int>(sizeof(int)) ? bytes - sizeof(int) : 0;
+ }
+ if (bytes != static_cast<ssize_t>(sizeof(int) + iov[1].iov_len)) {
+ if (bytes >= 0) {
+ errno = 0;
+ }
+ return false;
+ }
+ if (err) {
+ // "err" is the first four bytes of the payload. If these are non-zero,
+ // the sender on the other side of the socketpair sent us an errno value.
+ // We don't expect to get any file handles in this case.
+ errno = err;
+ return false;
+ }
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ if ((msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) ||
+ !cmsg ||
+ cmsg->cmsg_level != SOL_SOCKET ||
+ cmsg->cmsg_type != SCM_RIGHTS ||
+ cmsg->cmsg_len != CMSG_LEN(count*sizeof(int))) {
+ errno = EBADF;
+ return false;
+ }
+ va_start(ap, len);
+ for (int *fd, i = 0; (fd = va_arg(ap, int *)) != NULL; ++i) {
+ *fd = (reinterpret_cast<int *>(CMSG_DATA(cmsg)))[i];
+ }
+ va_end(ap);
+ return true;
+}
+
// POSIX doesn't define any async-signal safe function for converting
// an integer to ASCII. We'll have to define our own version.
@@ -48,7 +147,7 @@ using playground2::Util;
// conversion was successful or NULL otherwise. It never writes more than "sz"
// bytes. Output will be truncated as needed, and a NUL character is always
// appended.
-static char *itoa_r(int i, char *buf, size_t sz) {
+char *itoa_r(int i, char *buf, size_t sz) {
// Make sure we can write at least one NUL byte.
size_t n = 1;
if (n > sz) {
@@ -116,8 +215,7 @@ static char *itoa_r(int i, char *buf, size_t sz) {
// might try to evaluate the system call in user-space, instead.
// The only notable complication is that this function must be async-signal
// safe. This restricts the libary functions that we can call.
-static intptr_t defaultHandler(const struct arch_seccomp_data& data,
- void *) {
+intptr_t DefaultHandler(const struct arch_seccomp_data& data, void *) {
static const char msg0[] = "Disallowed system call #";
static const char msg1[] = "\n";
char buf[sizeof(msg0) - 1 + 25 + sizeof(msg1)];
@@ -137,7 +235,7 @@ static intptr_t defaultHandler(const struct arch_seccomp_data& data,
return -ERR;
}
-static ErrorCode evaluator(int sysno, void *) {
+ErrorCode Evaluator(Sandbox *sandbox, int sysno, void *) {
switch (sysno) {
#if defined(__NR_accept)
case __NR_accept: case __NR_accept4:
@@ -226,13 +324,13 @@ static ErrorCode evaluator(int sysno, void *) {
case __NR_prctl:
// Allow PR_SET_DUMPABLE and PR_GET_DUMPABLE. Do not allow anything else.
- return Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ return sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
PR_SET_DUMPABLE,
ErrorCode(ErrorCode::ERR_ALLOWED),
- Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
PR_GET_DUMPABLE,
ErrorCode(ErrorCode::ERR_ALLOWED),
- Sandbox::Trap(defaultHandler, NULL)));
+ sandbox->Trap(DefaultHandler, NULL)));
// The following system calls are temporarily permitted. This must be
// tightened later. But we currently don't implement enough of the sandboxing
@@ -267,15 +365,15 @@ static ErrorCode evaluator(int sysno, void *) {
// Everything that isn't explicitly allowed is denied.
default:
- return Sandbox::Trap(defaultHandler, NULL);
+ return sandbox->Trap(DefaultHandler, NULL);
}
}
-static void *threadFnc(void *arg) {
+void *ThreadFnc(void *arg) {
return arg;
}
-static void *sendmsgStressThreadFnc(void *arg) {
+void *SendmsgStressThreadFnc(void *arg) {
if (arg) { }
static const int repetitions = 100;
static const int kNumFds = 3;
@@ -287,8 +385,8 @@ static void *sendmsgStressThreadFnc(void *arg) {
}
size_t len = 4;
char buf[4];
- if (!Util::SendFds(fds[0], "test", 4, fds[1], fds[1], fds[1], -1) ||
- !Util::GetFds(fds[1], buf, &len, fds+2, fds+3, fds+4, NULL) ||
+ if (!SendFds(fds[0], "test", 4, fds[1], fds[1], fds[1], -1) ||
+ !GetFds(fds[1], buf, &len, fds+2, fds+3, fds+4, NULL) ||
len != 4 ||
memcmp(buf, "test", len) ||
write(fds[2], "demo", 4) != 4 ||
@@ -307,6 +405,8 @@ static void *sendmsgStressThreadFnc(void *arg) {
return NULL;
}
+} // namespace
+
int main(int argc, char *argv[]) {
if (argc) { }
if (argv) { }
@@ -316,13 +416,14 @@ int main(int argc, char *argv[]) {
perror("sandbox");
_exit(1);
}
- Sandbox::set_proc_fd(proc_fd);
- Sandbox::SetSandboxPolicy(evaluator, NULL);
- Sandbox::StartSandbox();
+ Sandbox sandbox;
+ sandbox.set_proc_fd(proc_fd);
+ sandbox.SetSandboxPolicy(Evaluator, NULL);
+ sandbox.StartSandbox();
// Check that we can create threads
pthread_t thr;
- if (!pthread_create(&thr, NULL, threadFnc,
+ if (!pthread_create(&thr, NULL, ThreadFnc,
reinterpret_cast<void *>(0x1234))) {
void *ret;
pthread_join(thr, &ret);
@@ -376,8 +477,8 @@ int main(int argc, char *argv[]) {
}
size_t len = 4;
char buf[4];
- if (!Util::SendFds(fds[0], "test", 4, fds[1], -1) ||
- !Util::GetFds(fds[1], buf, &len, fds+2, NULL) ||
+ if (!SendFds(fds[0], "test", 4, fds[1], -1) ||
+ !GetFds(fds[1], buf, &len, fds+2, NULL) ||
len != 4 ||
memcmp(buf, "test", len) ||
write(fds[2], "demo", 4) != 4 ||
@@ -410,7 +511,7 @@ int main(int argc, char *argv[]) {
pthread_t sendmsgStressThreads[kSendmsgStressNumThreads];
for (int i = 0; i < kSendmsgStressNumThreads; ++i) {
if (pthread_create(sendmsgStressThreads + i, NULL,
- sendmsgStressThreadFnc, NULL)) {
+ SendmsgStressThreadFnc, NULL)) {
perror("pthread_create");
_exit(1);
}
« no previous file with comments | « sandbox/linux/seccomp-bpf/codegen.cc ('k') | sandbox/linux/seccomp-bpf/die.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698