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

Unified Diff: sandbox/linux/seccomp_bpf/util.cc

Issue 10458040: Initial snapshot of the new BPF-enabled seccomp sandbox. This code is (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 6 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
Index: sandbox/linux/seccomp_bpf/util.cc
===================================================================
--- sandbox/linux/seccomp_bpf/util.cc (revision 0)
+++ sandbox/linux/seccomp_bpf/util.cc (revision 0)
@@ -0,0 +1,162 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sandbox/linux/seccomp_bpf/sandbox_bpf.h"
+#include "sandbox/linux/seccomp_bpf/util.h"
+
+namespace playground2 {
+
+bool Util::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 Util::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;
+}
+
+void Util::closeAllBut(int fd, ...) {
+ int proc_fd;
+ int fdir;
+ if ((proc_fd = Sandbox::getProcFd()) < 0 ||
+ (fdir = openat(proc_fd, "self/fd", O_RDONLY|O_DIRECTORY)) < 0) {
+ Sandbox::die("Cannot access \"/proc/self/fd\"");
+ }
+ int dev_null = open("/dev/null", O_RDWR);
+ DIR *dir = fdopendir(fdir);
+ struct dirent de, *res;
+ while (!readdir_r(dir, &de, &res) && res) {
+ if (res->d_name[0] < '0') {
+ continue;
+ }
+ int i = atoi(res->d_name);
+ if (i >= 0 && i != dirfd(dir) && i != dev_null) {
+ va_list ap;
+ va_start(ap, fd);
+ for (int f = fd;; f = va_arg(ap, int)) {
+ if (f < 0) {
+ if (i <= 2) {
+ // Never ever close 0..2. If we cannot redirect to /dev/null,
+ // then we are better off leaving the standard descriptors open.
+ if (dev_null >= 0) {
+ HANDLE_EINTR(dup2(dev_null, i));
+ }
+ } else {
+ HANDLE_EINTR(close(i));
+ }
+ break;
+ } else if (i == f) {
+ break;
+ }
+ }
+ va_end(ap);
+ }
+ }
+ closedir(dir);
+ if (dev_null >= 0) {
+ HANDLE_EINTR(close(dev_null));
+ }
+ return;
+}
+
+} // namespace
Property changes on: sandbox/linux/seccomp_bpf/util.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« sandbox/linux/seccomp_bpf/sandbox_bpf.cc ('K') | « sandbox/linux/seccomp_bpf/util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698