OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "sandbox/linux/services/proc_util.h" | 5 #include "sandbox/linux/services/proc_util.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <string.h> | 10 #include <string.h> |
(...skipping 10 matching lines...) Expand all Loading... |
21 | 21 |
22 struct DIRCloser { | 22 struct DIRCloser { |
23 void operator()(DIR* d) const { | 23 void operator()(DIR* d) const { |
24 DCHECK(d); | 24 DCHECK(d); |
25 PCHECK(0 == closedir(d)); | 25 PCHECK(0 == closedir(d)); |
26 } | 26 } |
27 }; | 27 }; |
28 | 28 |
29 typedef scoped_ptr<DIR, DIRCloser> ScopedDIR; | 29 typedef scoped_ptr<DIR, DIRCloser> ScopedDIR; |
30 | 30 |
| 31 base::ScopedFD OpenDirectory(const char* path) { |
| 32 DCHECK(path); |
| 33 base::ScopedFD directory_fd( |
| 34 HANDLE_EINTR(open(path, O_RDONLY | O_DIRECTORY | O_CLOEXEC))); |
| 35 PCHECK(directory_fd.is_valid()); |
| 36 return directory_fd.Pass(); |
| 37 } |
| 38 |
31 } // namespace | 39 } // namespace |
32 | 40 |
33 int ProcUtil::CountOpenFds(int proc_fd) { | 41 int ProcUtil::CountOpenFds(int proc_fd) { |
34 DCHECK_LE(0, proc_fd); | 42 DCHECK_LE(0, proc_fd); |
35 int proc_self_fd = HANDLE_EINTR( | 43 int proc_self_fd = HANDLE_EINTR( |
36 openat(proc_fd, "self/fd", O_DIRECTORY | O_RDONLY | O_CLOEXEC)); | 44 openat(proc_fd, "self/fd/", O_DIRECTORY | O_RDONLY | O_CLOEXEC)); |
37 PCHECK(0 <= proc_self_fd); | 45 PCHECK(0 <= proc_self_fd); |
38 | 46 |
39 // Ownership of proc_self_fd is transferred here, it must not be closed | 47 // Ownership of proc_self_fd is transferred here, it must not be closed |
40 // or modified afterwards except via dir. | 48 // or modified afterwards except via dir. |
41 ScopedDIR dir(fdopendir(proc_self_fd)); | 49 ScopedDIR dir(fdopendir(proc_self_fd)); |
42 CHECK(dir); | 50 CHECK(dir); |
43 | 51 |
44 int count = 0; | 52 int count = 0; |
45 struct dirent e; | 53 struct dirent e; |
46 struct dirent* de; | 54 struct dirent* de; |
47 while (!readdir_r(dir.get(), &e, &de) && de) { | 55 while (!readdir_r(dir.get(), &e, &de) && de) { |
48 if (strcmp(e.d_name, ".") == 0 || strcmp(e.d_name, "..") == 0) { | 56 if (strcmp(e.d_name, ".") == 0 || strcmp(e.d_name, "..") == 0) { |
49 continue; | 57 continue; |
50 } | 58 } |
51 | 59 |
52 int fd_num; | 60 int fd_num; |
53 CHECK(base::StringToInt(e.d_name, &fd_num)); | 61 CHECK(base::StringToInt(e.d_name, &fd_num)); |
54 if (fd_num == proc_fd || fd_num == proc_self_fd) { | 62 if (fd_num == proc_fd || fd_num == proc_self_fd) { |
55 continue; | 63 continue; |
56 } | 64 } |
57 | 65 |
58 ++count; | 66 ++count; |
59 } | 67 } |
60 return count; | 68 return count; |
61 } | 69 } |
62 | 70 |
63 bool ProcUtil::HasOpenDirectory(int proc_fd) { | 71 bool ProcUtil::HasOpenDirectory(int proc_fd) { |
64 int proc_self_fd = -1; | 72 DCHECK_LE(0, proc_fd); |
65 if (proc_fd >= 0) { | 73 int proc_self_fd = |
66 proc_self_fd = openat(proc_fd, "self/fd", O_DIRECTORY | O_RDONLY); | 74 openat(proc_fd, "self/fd/", O_DIRECTORY | O_RDONLY | O_CLOEXEC); |
67 } else { | |
68 proc_self_fd = openat(AT_FDCWD, "/proc/self/fd", O_DIRECTORY | O_RDONLY); | |
69 if (proc_self_fd < 0) { | |
70 // If this process has been chrooted (eg into /proc/self/fdinfo) then | |
71 // the new root dir will not have directory listing permissions for us | |
72 // (hence EACCES). And if we do have this permission, then /proc won't | |
73 // exist anyway (hence ENOENT). | |
74 DPCHECK(errno == EACCES || errno == ENOENT) | |
75 << "Unexpected failure when trying to open /proc/self/fd: (" | |
76 << errno << ") " << strerror(errno); | |
77 | 75 |
78 // If not available, guess false. | |
79 return false; | |
80 } | |
81 } | |
82 PCHECK(0 <= proc_self_fd); | 76 PCHECK(0 <= proc_self_fd); |
83 | 77 |
84 // Ownership of proc_self_fd is transferred here, it must not be closed | 78 // Ownership of proc_self_fd is transferred here, it must not be closed |
85 // or modified afterwards except via dir. | 79 // or modified afterwards except via dir. |
86 ScopedDIR dir(fdopendir(proc_self_fd)); | 80 ScopedDIR dir(fdopendir(proc_self_fd)); |
87 CHECK(dir); | 81 CHECK(dir); |
88 | 82 |
89 struct dirent e; | 83 struct dirent e; |
90 struct dirent* de; | 84 struct dirent* de; |
91 while (!readdir_r(dir.get(), &e, &de) && de) { | 85 while (!readdir_r(dir.get(), &e, &de) && de) { |
(...skipping 12 matching lines...) Expand all Loading... |
104 CHECK(fstatat(proc_self_fd, e.d_name, &s, 0) == 0); | 98 CHECK(fstatat(proc_self_fd, e.d_name, &s, 0) == 0); |
105 if (S_ISDIR(s.st_mode)) { | 99 if (S_ISDIR(s.st_mode)) { |
106 return true; | 100 return true; |
107 } | 101 } |
108 } | 102 } |
109 | 103 |
110 // No open unmanaged directories found. | 104 // No open unmanaged directories found. |
111 return false; | 105 return false; |
112 } | 106 } |
113 | 107 |
| 108 bool ProcUtil::HasOpenDirectory() { |
| 109 base::ScopedFD proc_fd( |
| 110 HANDLE_EINTR(open("/proc/", O_DIRECTORY | O_RDONLY | O_CLOEXEC))); |
| 111 return HasOpenDirectory(proc_fd.get()); |
| 112 } |
| 113 |
114 //static | 114 //static |
115 base::ScopedFD ProcUtil::OpenProcSelfTask() { | 115 base::ScopedFD ProcUtil::OpenProc() { |
116 base::ScopedFD proc_self_task( | 116 return OpenDirectory("/proc/"); |
117 HANDLE_EINTR( | |
118 open("/proc/self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC))); | |
119 PCHECK(proc_self_task.is_valid()); | |
120 return proc_self_task.Pass(); | |
121 } | 117 } |
122 | 118 |
123 } // namespace sandbox | 119 } // namespace sandbox |
OLD | NEW |