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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <dirent.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdarg.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/socket.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14
15 #include "sandbox_bpf.h"
16 #include "util.h"
17
18 namespace playground2 {
19
20 bool Util::sendFds(int transport, const void *buf, size_t len, ...) {
21 int count = 0;
22 va_list ap;
23 va_start(ap, len);
24 while (va_arg(ap, int) >= 0) {
25 ++count;
26 }
27 va_end(ap);
28 if (!count) {
29 return false;
30 }
31 char cmsg_buf[CMSG_SPACE(count*sizeof(int))];
32 memset(cmsg_buf, 0, sizeof(cmsg_buf));
33 struct iovec iov[2] = { { 0 } };
34 struct msghdr msg = { 0 };
35 int dummy = 0;
36 iov[0].iov_base = &dummy;
37 iov[0].iov_len = sizeof(dummy);
38 if (buf && len > 0) {
39 iov[1].iov_base = const_cast<void *>(buf);
40 iov[1].iov_len = len;
41 }
42 msg.msg_iov = iov;
43 msg.msg_iovlen = (buf && len > 0) ? 2 : 1;
44 msg.msg_control = cmsg_buf;
45 msg.msg_controllen = CMSG_LEN(count*sizeof(int));
46 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
47 cmsg->cmsg_level = SOL_SOCKET;
48 cmsg->cmsg_type = SCM_RIGHTS;
49 cmsg->cmsg_len = CMSG_LEN(count*sizeof(int));
50 va_start(ap, len);
51 for (int i = 0, fd; (fd = va_arg(ap, int)) >= 0; ++i) {
52 ((int *)CMSG_DATA(cmsg))[i] = fd;
53 }
54 return sendmsg(transport, &msg, 0) ==
55 (ssize_t)(sizeof(dummy) + ((buf && len > 0) ? len : 0));
56 }
57
58 bool Util::getFds(int transport, void *buf, size_t *len, ...) {
59 int count = 0;
60 va_list ap;
61 va_start(ap, len);
62 for (int *fd; (fd = va_arg(ap, int *)) != NULL; ++count) {
63 *fd = -1;
64 }
65 va_end(ap);
66 if (!count) {
67 return false;
68 }
69 char cmsg_buf[CMSG_SPACE(count*sizeof(int))];
70 memset(cmsg_buf, 0, sizeof(cmsg_buf));
71 struct iovec iov[2] = { { 0 } };
72 struct msghdr msg = { 0 };
73 int err;
74 iov[0].iov_base = &err;
75 iov[0].iov_len = sizeof(int);
76 if (buf && len && *len > 0) {
77 iov[1].iov_base = buf;
78 iov[1].iov_len = *len;
79 }
80 msg.msg_iov = iov;
81 msg.msg_iovlen = (buf && len && *len > 0) ? 2 : 1;
82 msg.msg_control = cmsg_buf;
83 msg.msg_controllen = CMSG_LEN(count*sizeof(int));
84 ssize_t bytes = recvmsg(transport, &msg, 0);
85 if (len) {
86 *len = bytes > (int)sizeof(int) ? bytes - sizeof(int) : 0;
87 }
88 if (bytes != (ssize_t)(sizeof(int) + iov[1].iov_len)) {
89 if (bytes >= 0) {
90 errno = 0;
91 }
92 return false;
93 }
94 if (err) {
95 // "err" is the first four bytes of the payload. If these are non-zero,
96 // the sender on the other side of the socketpair sent us an errno value.
97 // We don't expect to get any file handles in this case.
98 errno = err;
99 return false;
100 }
101 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
102 if ((msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) ||
103 !cmsg ||
104 cmsg->cmsg_level != SOL_SOCKET ||
105 cmsg->cmsg_type != SCM_RIGHTS ||
106 cmsg->cmsg_len != CMSG_LEN(count*sizeof(int))) {
107 errno = EBADF;
108 return false;
109 }
110 va_start(ap, len);
111 for (int *fd, i = 0; (fd = va_arg(ap, int *)) != NULL; ++i) {
112 *fd = ((int *)CMSG_DATA(cmsg))[i];
113 }
114 va_end(ap);
115 return true;
116 }
117
118 void Util::closeAllBut(int fd, ...) {
119 int proc_fd;
120 int fdir;
121 if ((proc_fd = Sandbox::getProcFd()) < 0 ||
122 (fdir = openat(proc_fd, "self/fd", O_RDONLY|O_DIRECTORY)) < 0) {
123 Sandbox::die("Cannot access \"/proc/self/fd\"");
124 }
125 int dev_null = open("/dev/null", O_RDWR);
126 DIR *dir = fdopendir(fdir);
127 struct dirent de, *res;
128 while (!readdir_r(dir, &de, &res) && res) {
129 if (res->d_name[0] < '0') {
130 continue;
131 }
132 int i = atoi(res->d_name);
133 if (i >= 0 && i != dirfd(dir) && i != dev_null) {
134 va_list ap;
135 va_start(ap, fd);
136 for (int f = fd;; f = va_arg(ap, int)) {
137 if (f < 0) {
138 if (i <= 2) {
139 // Never ever close 0..2. If we cannot redirect to /dev/null,
140 // then we are better off leaving the standard descriptors open.
141 if (dev_null >= 0) {
142 TEMP_FAILURE_RETRY(dup2(dev_null, i));
143 }
144 } else {
145 TEMP_FAILURE_RETRY(close(i));
146 }
147 break;
148 } else if (i == f) {
149 break;
150 }
151 }
152 va_end(ap);
153 }
154 }
155 closedir(dir);
156 if (dev_null >= 0) {
157 TEMP_FAILURE_RETRY(close(dev_null));
158 }
159 return;
160 }
161
162 } // namespace
OLDNEW
« 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