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
3 // found in the LICENSE file.
5 #include "sandbox/linux/services/proc_util.h"
12 #include <sys/types.h>
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/posix/eintr_wrapper.h"
17 #include "base/strings/string_number_conversions.h"
23 void operator()(DIR* d
) const {
25 PCHECK(0 == closedir(d
));
29 typedef scoped_ptr
<DIR, DIRCloser
> ScopedDIR
;
33 int ProcUtil::CountOpenFds(int proc_fd
) {
34 DCHECK_LE(0, proc_fd
);
35 int proc_self_fd
= HANDLE_EINTR(
36 openat(proc_fd
, "self/fd", O_DIRECTORY
| O_RDONLY
| O_CLOEXEC
));
37 PCHECK(0 <= proc_self_fd
);
39 // Ownership of proc_self_fd is transferred here, it must not be closed
40 // or modified afterwards except via dir.
41 ScopedDIR
dir(fdopendir(proc_self_fd
));
47 while (!readdir_r(dir
.get(), &e
, &de
) && de
) {
48 if (strcmp(e
.d_name
, ".") == 0 || strcmp(e
.d_name
, "..") == 0) {
53 CHECK(base::StringToInt(e
.d_name
, &fd_num
));
54 if (fd_num
== proc_fd
|| fd_num
== proc_self_fd
) {
63 bool ProcUtil::HasOpenDirectory(int proc_fd
) {
64 int proc_self_fd
= -1;
66 proc_self_fd
= openat(proc_fd
, "self/fd", O_DIRECTORY
| O_RDONLY
);
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
);
78 // If not available, guess false.
82 PCHECK(0 <= proc_self_fd
);
84 // Ownership of proc_self_fd is transferred here, it must not be closed
85 // or modified afterwards except via dir.
86 ScopedDIR
dir(fdopendir(proc_self_fd
));
91 while (!readdir_r(dir
.get(), &e
, &de
) && de
) {
92 if (strcmp(e
.d_name
, ".") == 0 || strcmp(e
.d_name
, "..") == 0) {
97 CHECK(base::StringToInt(e
.d_name
, &fd_num
));
98 if (fd_num
== proc_fd
|| fd_num
== proc_self_fd
) {
103 // It's OK to use proc_self_fd here, fstatat won't modify it.
104 CHECK(fstatat(proc_self_fd
, e
.d_name
, &s
, 0) == 0);
105 if (S_ISDIR(s
.st_mode
)) {
110 // No open unmanaged directories found.
115 base::ScopedFD
ProcUtil::OpenProcSelfTask() {
116 base::ScopedFD
proc_self_task(
118 open("/proc/self/task/", O_RDONLY
| O_DIRECTORY
| O_CLOEXEC
)));
119 PCHECK(proc_self_task
.is_valid());
120 return proc_self_task
.Pass();
123 } // namespace sandbox