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/strings/string_number_conversions.h"
22 void operator()(DIR* d
) const {
24 PCHECK(0 == closedir(d
));
28 typedef scoped_ptr
<DIR, DIRCloser
> ScopedDIR
;
32 int ProcUtil::CountOpenFds(int proc_fd
) {
33 DCHECK_LE(0, proc_fd
);
34 int proc_self_fd
= openat(proc_fd
, "self/fd", O_DIRECTORY
| O_RDONLY
);
35 PCHECK(0 <= proc_self_fd
);
37 // Ownership of proc_self_fd is transferred here, it must not be closed
38 // or modified afterwards except via dir.
39 ScopedDIR
dir(fdopendir(proc_self_fd
));
45 while (!readdir_r(dir
.get(), &e
, &de
) && de
) {
46 if (strcmp(e
.d_name
, ".") == 0 || strcmp(e
.d_name
, "..") == 0) {
51 CHECK(base::StringToInt(e
.d_name
, &fd_num
));
52 if (fd_num
== proc_fd
|| fd_num
== proc_self_fd
) {
61 bool ProcUtil::HasOpenDirectory(int proc_fd
) {
62 int proc_self_fd
= -1;
64 proc_self_fd
= openat(proc_fd
, "self/fd", O_DIRECTORY
| O_RDONLY
);
66 proc_self_fd
= openat(AT_FDCWD
, "/proc/self/fd", O_DIRECTORY
| O_RDONLY
);
67 if (proc_self_fd
< 0) {
68 // If this process has been chrooted (eg into /proc/self/fdinfo) then
69 // the new root dir will not have directory listing permissions for us
70 // (hence EACCES). And if we do have this permission, then /proc won't
71 // exist anyway (hence ENOENT).
72 DPCHECK(errno
== EACCES
|| errno
== ENOENT
)
73 << "Unexpected failure when trying to open /proc/self/fd: ("
74 << errno
<< ") " << strerror(errno
);
76 // If not available, guess false.
80 PCHECK(0 <= proc_self_fd
);
82 // Ownership of proc_self_fd is transferred here, it must not be closed
83 // or modified afterwards except via dir.
84 ScopedDIR
dir(fdopendir(proc_self_fd
));
89 while (!readdir_r(dir
.get(), &e
, &de
) && de
) {
90 if (strcmp(e
.d_name
, ".") == 0 || strcmp(e
.d_name
, "..") == 0) {
95 CHECK(base::StringToInt(e
.d_name
, &fd_num
));
96 if (fd_num
== proc_fd
|| fd_num
== proc_self_fd
) {
101 // It's OK to use proc_self_fd here, fstatat won't modify it.
102 CHECK(fstatat(proc_self_fd
, e
.d_name
, &s
, 0) == 0);
103 if (S_ISDIR(s
.st_mode
)) {
108 // No open unmanaged directories found.
112 } // namespace sandbox