| 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 // The following is duplicated from base/linux_utils.cc. | 5 // The following is duplicated from base/linux_utils.cc. |
| 6 // We shouldn't link against C++ code in a setuid binary. | 6 // We shouldn't link against C++ code in a setuid binary. |
| 7 | 7 |
| 8 #include "sandbox/linux/suid/linux_util.h" |
| 9 |
| 8 #define _GNU_SOURCE // For O_DIRECTORY | 10 #define _GNU_SOURCE // For O_DIRECTORY |
| 9 #include "linux_util.h" | |
| 10 | 11 |
| 11 #include <dirent.h> | 12 #include <dirent.h> |
| 12 #include <errno.h> | 13 #include <errno.h> |
| 13 #include <fcntl.h> | 14 #include <fcntl.h> |
| 14 #include <limits.h> | 15 #include <limits.h> |
| 15 #include <stdio.h> | 16 #include <stdio.h> |
| 16 #include <stdlib.h> | 17 #include <stdlib.h> |
| 17 #include <string.h> | 18 #include <string.h> |
| 18 #include <sys/stat.h> | 19 #include <sys/stat.h> |
| 19 #include <sys/types.h> | 20 #include <sys/types.h> |
| 20 #include <unistd.h> | 21 #include <unistd.h> |
| 21 | 22 |
| 22 // expected prefix of the target of the /proc/self/fd/%d link for a socket | 23 // expected prefix of the target of the /proc/self/fd/%d link for a socket |
| 23 static const char kSocketLinkPrefix[] = "socket:["; | 24 static const char kSocketLinkPrefix[] = "socket:["; |
| 24 | 25 |
| 25 // Parse a symlink in /proc/pid/fd/$x and return the inode number of the | 26 // Parse a symlink in /proc/pid/fd/$x and return the inode number of the |
| 26 // socket. | 27 // socket. |
| 27 // inode_out: (output) set to the inode number on success | 28 // inode_out: (output) set to the inode number on success |
| 28 // path: e.g. /proc/1234/fd/5 (must be a UNIX domain socket descriptor) | 29 // path: e.g. /proc/1234/fd/5 (must be a UNIX domain socket descriptor) |
| 29 static bool ProcPathGetInodeAt(ino_t* inode_out, int base_dir_fd, | 30 static bool ProcPathGetInodeAt(ino_t* inode_out, |
| 31 int base_dir_fd, |
| 30 const char* path) { | 32 const char* path) { |
| 31 // We also check that the path is relative. | 33 // We also check that the path is relative. |
| 32 if (!inode_out || !path || *path == '/') | 34 if (!inode_out || !path || *path == '/') |
| 33 return false; | 35 return false; |
| 34 char buf[256]; | 36 char buf[256]; |
| 35 const ssize_t n = readlinkat(base_dir_fd, path, buf, sizeof(buf) - 1); | 37 const ssize_t n = readlinkat(base_dir_fd, path, buf, sizeof(buf) - 1); |
| 36 if (n < 0) | 38 if (n < 0) |
| 37 return false; | 39 return false; |
| 38 buf[n] = 0; | 40 buf[n] = 0; |
| 39 | 41 |
| 40 if (memcmp(kSocketLinkPrefix, buf, sizeof(kSocketLinkPrefix) - 1)) | 42 if (memcmp(kSocketLinkPrefix, buf, sizeof(kSocketLinkPrefix) - 1)) |
| 41 return false; | 43 return false; |
| 42 | 44 |
| 43 char *endptr = NULL; | 45 char* endptr = NULL; |
| 44 errno = 0; | 46 errno = 0; |
| 45 const unsigned long long int inode_ull = | 47 const unsigned long long int inode_ull = |
| 46 strtoull(buf + sizeof(kSocketLinkPrefix) - 1, &endptr, 10); | 48 strtoull(buf + sizeof(kSocketLinkPrefix) - 1, &endptr, 10); |
| 47 if (inode_ull == ULLONG_MAX || !endptr || *endptr != ']' || errno != 0) | 49 if (inode_ull == ULLONG_MAX || !endptr || *endptr != ']' || errno != 0) |
| 48 return false; | 50 return false; |
| 49 | 51 |
| 50 *inode_out = inode_ull; | 52 *inode_out = inode_ull; |
| 51 return true; | 53 return true; |
| 52 } | 54 } |
| 53 | 55 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 65 bool FindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode) { | 67 bool FindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode) { |
| 66 bool already_found = false; | 68 bool already_found = false; |
| 67 | 69 |
| 68 DIR* proc = opendir("/proc"); | 70 DIR* proc = opendir("/proc"); |
| 69 if (!proc) | 71 if (!proc) |
| 70 return false; | 72 return false; |
| 71 | 73 |
| 72 const uid_t uid = getuid(); | 74 const uid_t uid = getuid(); |
| 73 struct dirent* dent; | 75 struct dirent* dent; |
| 74 while ((dent = readdir(proc))) { | 76 while ((dent = readdir(proc))) { |
| 75 char *endptr = NULL; | 77 char* endptr = NULL; |
| 76 errno = 0; | 78 errno = 0; |
| 77 const unsigned long int pid_ul = strtoul(dent->d_name, &endptr, 10); | 79 const unsigned long int pid_ul = strtoul(dent->d_name, &endptr, 10); |
| 78 if (pid_ul == ULONG_MAX || !endptr || *endptr || errno != 0) | 80 if (pid_ul == ULONG_MAX || !endptr || *endptr || errno != 0) |
| 79 continue; | 81 continue; |
| 80 | 82 |
| 81 // We have this setuid code here because the zygote and its children have | 83 // We have this setuid code here because the zygote and its children have |
| 82 // /proc/$pid/fd owned by root. While scanning through /proc, we add this | 84 // /proc/$pid/fd owned by root. While scanning through /proc, we add this |
| 83 // extra check so users cannot accidentally gain information about other | 85 // extra check so users cannot accidentally gain information about other |
| 84 // users' processes. To determine process ownership, we use the property | 86 // users' processes. To determine process ownership, we use the property |
| 85 // that if user foo owns process N, then /proc/N is owned by foo. | 87 // that if user foo owns process N, then /proc/N is owned by foo. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 } | 128 } |
| 127 } | 129 } |
| 128 } | 130 } |
| 129 closedir(fd); | 131 closedir(fd); |
| 130 close(proc_pid_fd); | 132 close(proc_pid_fd); |
| 131 } | 133 } |
| 132 closedir(proc); | 134 closedir(proc); |
| 133 | 135 |
| 134 return already_found; | 136 return already_found; |
| 135 } | 137 } |
| OLD | NEW |