| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox | 5 // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox |
| 6 | 6 |
| 7 #include <asm/unistd.h> | 7 #include <asm/unistd.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <sched.h> | 10 #include <sched.h> |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 if (!temp_dir) | 71 if (!temp_dir) |
| 72 FatalError("Failed to create temp directory for chroot"); | 72 FatalError("Failed to create temp directory for chroot"); |
| 73 | 73 |
| 74 const int chroot_dir_fd = open(temp_dir, O_DIRECTORY | O_RDONLY); | 74 const int chroot_dir_fd = open(temp_dir, O_DIRECTORY | O_RDONLY); |
| 75 if (chroot_dir_fd < 0) { | 75 if (chroot_dir_fd < 0) { |
| 76 rmdir(temp_dir); | 76 rmdir(temp_dir); |
| 77 FatalError("Failed to open chroot temp directory"); | 77 FatalError("Failed to open chroot temp directory"); |
| 78 } | 78 } |
| 79 | 79 |
| 80 rmdir(temp_dir); | 80 rmdir(temp_dir); |
| 81 fchown(chroot_dir_fd, 0, 0); | 81 fchown(chroot_dir_fd, 0 /* root */, 0 /* root */); |
| 82 fchmod(chroot_dir_fd, 0555); | |
| 83 | 82 |
| 84 // We share our files structure with an untrusted process. As a security in | 83 // We share our files structure with an untrusted process. As a security in |
| 85 // depth measure, we make sure that we can't open anything by mistake. | 84 // depth measure, we make sure that we can't open anything by mistake. |
| 86 // TODO: drop CAP_SYS_RESOURCE | 85 // TODO: drop CAP_SYS_RESOURCE |
| 87 | 86 |
| 88 const struct rlimit nofile = {0, 0}; | 87 const struct rlimit nofile = {0, 0}; |
| 89 if (setrlimit(RLIMIT_NOFILE, &nofile)) | 88 if (setrlimit(RLIMIT_NOFILE, &nofile)) |
| 90 FatalError("Setting RLIMIT_NOFILE"); | 89 FatalError("Setting RLIMIT_NOFILE"); |
| 91 | 90 |
| 92 if (close(sv[1])) | 91 if (close(sv[1])) |
| 93 FatalError("close"); | 92 FatalError("close"); |
| 94 | 93 |
| 95 char msg; | 94 char msg; |
| 96 ssize_t bytes; | 95 ssize_t bytes; |
| 97 do { | 96 do { |
| 98 bytes = read(sv[0], &msg, 1); | 97 bytes = read(sv[0], &msg, 1); |
| 99 } while (bytes == -1 && errno == EINTR); | 98 } while (bytes == -1 && errno == EINTR); |
| 100 | 99 |
| 101 if (bytes == 0) | 100 if (bytes == 0) |
| 102 _exit(0); | 101 _exit(0); |
| 103 if (bytes != 1) | 102 if (bytes != 1) |
| 104 FatalError("read"); | 103 FatalError("read"); |
| 105 | 104 |
| 106 if (msg != kMsgChrootMe) | 105 if (msg != kMsgChrootMe) |
| 107 FatalError("Unknown message from sandboxed process"); | 106 FatalError("Unknown message from sandboxed process"); |
| 108 | 107 |
| 109 if (fchdir(chroot_dir_fd)) | 108 if (fchdir(chroot_dir_fd)) |
| 110 FatalError("Cannot chdir into chroot temp directory"); | 109 FatalError("Cannot chdir into chroot temp directory"); |
| 110 fchmod(chroot_dir_fd, 0000 /* no-access */); |
| 111 | 111 |
| 112 struct stat st; | 112 struct stat st; |
| 113 if (stat(".", &st)) | 113 if (stat(".", &st)) |
| 114 FatalError("stat"); | 114 FatalError("stat"); |
| 115 | 115 |
| 116 if (st.st_uid || st.st_gid || st.st_mode & S_IWOTH) | 116 if (st.st_uid || st.st_gid || st.st_mode & S_IWOTH) |
| 117 FatalError("Bad permissions on chroot temp directory"); | 117 FatalError("Bad permissions on chroot temp directory"); |
| 118 | 118 |
| 119 if (chroot(".")) | 119 if (chroot(".")) |
| 120 FatalError("Cannot chroot into temp directory"); | 120 FatalError("Cannot chroot into temp directory"); |
| 121 | 121 |
| 122 if (chdir("/")) | 122 if (chdir("/")) |
| 123 FatalError("Cannot chdir to / after chroot"); | 123 FatalError("Cannot chdir to / after chroot"); |
| 124 | 124 |
| 125 const char reply = kMsgChrootSuccessful; | 125 const char reply = kMsgChrootSuccessful; |
| 126 do { | 126 do { |
| 127 struct msghdr msg = {0}; | 127 bytes = write(sv[0], &reply, 1); |
| 128 struct iovec iov = {(char *) &reply, 1}; | |
| 129 | |
| 130 msg.msg_iov = &iov; | |
| 131 msg.msg_iovlen = 1; | |
| 132 | |
| 133 char control_buffer[CMSG_SPACE(sizeof(int))]; | |
| 134 msg.msg_control = control_buffer; | |
| 135 msg.msg_controllen = sizeof(control_buffer); | |
| 136 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); | |
| 137 cmsg->cmsg_level = SOL_SOCKET; | |
| 138 cmsg->cmsg_type = SCM_RIGHTS; | |
| 139 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); | |
| 140 memcpy(CMSG_DATA(cmsg), &chroot_dir_fd, sizeof(int)); | |
| 141 msg.msg_controllen = cmsg->cmsg_len; | |
| 142 | |
| 143 bytes = sendmsg(sv[0], &msg, 0); | |
| 144 } while (bytes == -1 && errno == EINTR); | 128 } while (bytes == -1 && errno == EINTR); |
| 145 | 129 |
| 146 if (bytes != 1) | 130 if (bytes != 1) |
| 147 FatalError("Writing reply"); | 131 FatalError("Writing reply"); |
| 148 | 132 |
| 149 _exit(0); | 133 _exit(0); |
| 150 } | 134 } |
| 151 | 135 |
| 152 if (close(sv[0])) { | 136 if (close(sv[0])) { |
| 153 close(sv[1]); | 137 close(sv[1]); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 if (!SpawnChrootHelper()) | 234 if (!SpawnChrootHelper()) |
| 251 return 1; | 235 return 1; |
| 252 if (!DropRoot()) | 236 if (!DropRoot()) |
| 253 return 1; | 237 return 1; |
| 254 | 238 |
| 255 execv(argv[1], &argv[1]); | 239 execv(argv[1], &argv[1]); |
| 256 FatalError("execv failed"); | 240 FatalError("execv failed"); |
| 257 | 241 |
| 258 return 1; | 242 return 1; |
| 259 } | 243 } |
| OLD | NEW |