• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "sandbox/linux/services/proc_util.h"
6 
7 #include <dirent.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 
14 #include <memory>
15 
16 #include "base/logging.h"
17 #include "base/posix/eintr_wrapper.h"
18 #include "base/strings/string_number_conversions.h"
19 
20 namespace sandbox {
21 namespace {
22 
23 struct DIRCloser {
operator ()sandbox::__anon7fa5a7a90111::DIRCloser24   void operator()(DIR* d) const {
25     DCHECK(d);
26     PCHECK(0 == closedir(d));
27   }
28 };
29 
30 typedef std::unique_ptr<DIR, DIRCloser> ScopedDIR;
31 
OpenDirectory(const char * path)32 base::ScopedFD OpenDirectory(const char* path) {
33   DCHECK(path);
34   base::ScopedFD directory_fd(
35       HANDLE_EINTR(open(path, O_RDONLY | O_DIRECTORY | O_CLOEXEC)));
36   PCHECK(directory_fd.is_valid());
37   return directory_fd;
38 }
39 
40 }  // namespace
41 
CountOpenFds(int proc_fd)42 int ProcUtil::CountOpenFds(int proc_fd) {
43   DCHECK_LE(0, proc_fd);
44   int proc_self_fd = HANDLE_EINTR(
45       openat(proc_fd, "self/fd/", O_DIRECTORY | O_RDONLY | O_CLOEXEC));
46   PCHECK(0 <= proc_self_fd);
47 
48   // Ownership of proc_self_fd is transferred here, it must not be closed
49   // or modified afterwards except via dir.
50   ScopedDIR dir(fdopendir(proc_self_fd));
51   CHECK(dir);
52 
53   int count = 0;
54   struct dirent e;
55   struct dirent* de;
56   while (!readdir_r(dir.get(), &e, &de) && de) {
57     if (strcmp(e.d_name, ".") == 0 || strcmp(e.d_name, "..") == 0) {
58       continue;
59     }
60 
61     int fd_num;
62     CHECK(base::StringToInt(e.d_name, &fd_num));
63     if (fd_num == proc_fd || fd_num == proc_self_fd) {
64       continue;
65     }
66 
67     ++count;
68   }
69   return count;
70 }
71 
HasOpenDirectory(int proc_fd)72 bool ProcUtil::HasOpenDirectory(int proc_fd) {
73   DCHECK_LE(0, proc_fd);
74   int proc_self_fd =
75       openat(proc_fd, "self/fd/", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
76 
77   PCHECK(0 <= proc_self_fd);
78 
79   // Ownership of proc_self_fd is transferred here, it must not be closed
80   // or modified afterwards except via dir.
81   ScopedDIR dir(fdopendir(proc_self_fd));
82   CHECK(dir);
83 
84   struct dirent e;
85   struct dirent* de;
86   while (!readdir_r(dir.get(), &e, &de) && de) {
87     if (strcmp(e.d_name, ".") == 0 || strcmp(e.d_name, "..") == 0) {
88       continue;
89     }
90 
91     int fd_num;
92     CHECK(base::StringToInt(e.d_name, &fd_num));
93     if (fd_num == proc_fd || fd_num == proc_self_fd) {
94       continue;
95     }
96 
97     struct stat s;
98     // It's OK to use proc_self_fd here, fstatat won't modify it.
99     CHECK(fstatat(proc_self_fd, e.d_name, &s, 0) == 0);
100     if (S_ISDIR(s.st_mode)) {
101       return true;
102     }
103   }
104 
105   // No open unmanaged directories found.
106   return false;
107 }
108 
HasOpenDirectory()109 bool ProcUtil::HasOpenDirectory() {
110   base::ScopedFD proc_fd(
111       HANDLE_EINTR(open("/proc/", O_DIRECTORY | O_RDONLY | O_CLOEXEC)));
112   return HasOpenDirectory(proc_fd.get());
113 }
114 
115 // static
OpenProc()116 base::ScopedFD ProcUtil::OpenProc() {
117   return OpenDirectory("/proc/");
118 }
119 
120 }  // namespace sandbox
121