OLD | NEW |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include "util/posix/process_info.h" | 15 #include "util/posix/process_info.h" |
16 | 16 |
| 17 #include <signal.h> |
17 #include <time.h> | 18 #include <time.h> |
18 #include <stdio.h> | |
19 #include <unistd.h> | 19 #include <unistd.h> |
20 | 20 |
| 21 #include <algorithm> |
21 #include <set> | 22 #include <set> |
22 #include <string> | 23 #include <string> |
23 #include <vector> | 24 #include <vector> |
24 | 25 |
25 #include "base/files/scoped_file.h" | 26 #include "base/strings/stringprintf.h" |
26 #include "build/build_config.h" | 27 #include "build/build_config.h" |
27 #include "gtest/gtest.h" | 28 #include "gtest/gtest.h" |
28 #include "test/errors.h" | 29 #include "test/errors.h" |
| 30 #include "test/main_arguments.h" |
29 #include "util/misc/implicit_cast.h" | 31 #include "util/misc/implicit_cast.h" |
30 | 32 |
31 #if defined(OS_MACOSX) | |
32 #include <crt_externs.h> | |
33 #endif | |
34 | |
35 namespace crashpad { | 33 namespace crashpad { |
36 namespace test { | 34 namespace test { |
37 namespace { | 35 namespace { |
38 | 36 |
39 void TestSelfProcess(const ProcessInfo& process_info) { | 37 void TestProcessSelfOrClone(const ProcessInfo& process_info) { |
40 EXPECT_EQ(getpid(), process_info.ProcessID()); | |
41 EXPECT_EQ(getppid(), process_info.ParentProcessID()); | |
42 | |
43 // There’s no system call to obtain the saved set-user ID or saved set-group | 38 // There’s no system call to obtain the saved set-user ID or saved set-group |
44 // ID in an easy way. Normally, they are the same as the effective user ID and | 39 // ID in an easy way. Normally, they are the same as the effective user ID and |
45 // effective group ID, so just check against those. | 40 // effective group ID, so just check against those. |
46 EXPECT_EQ(getuid(), process_info.RealUserID()); | 41 EXPECT_EQ(getuid(), process_info.RealUserID()); |
47 const uid_t euid = geteuid(); | 42 const uid_t euid = geteuid(); |
48 EXPECT_EQ(euid, process_info.EffectiveUserID()); | 43 EXPECT_EQ(euid, process_info.EffectiveUserID()); |
49 EXPECT_EQ(euid, process_info.SavedUserID()); | 44 EXPECT_EQ(euid, process_info.SavedUserID()); |
| 45 |
50 const gid_t gid = getgid(); | 46 const gid_t gid = getgid(); |
51 EXPECT_EQ(gid, process_info.RealGroupID()); | 47 EXPECT_EQ(gid, process_info.RealGroupID()); |
52 const gid_t egid = getegid(); | 48 const gid_t egid = getegid(); |
53 EXPECT_EQ(egid, process_info.EffectiveGroupID()); | 49 EXPECT_EQ(egid, process_info.EffectiveGroupID()); |
54 EXPECT_EQ(egid, process_info.SavedGroupID()); | 50 EXPECT_EQ(egid, process_info.SavedGroupID()); |
55 | 51 |
56 // Test SupplementaryGroups(). | 52 // Test SupplementaryGroups(). |
57 int group_count = getgroups(0, nullptr); | 53 int group_count = getgroups(0, nullptr); |
58 ASSERT_GE(group_count, 0) << ErrnoMessage("getgroups"); | 54 ASSERT_GE(group_count, 0) << ErrnoMessage("getgroups"); |
59 | 55 |
(...skipping 11 matching lines...) Expand all Loading... |
71 // and saved set-group IDs. The effective and saved set-group IDs are expected | 67 // and saved set-group IDs. The effective and saved set-group IDs are expected |
72 // to be identical (see above). | 68 // to be identical (see above). |
73 group_set.insert(gid); | 69 group_set.insert(gid); |
74 group_set.insert(egid); | 70 group_set.insert(egid); |
75 | 71 |
76 EXPECT_EQ(group_set, process_info.AllGroups()); | 72 EXPECT_EQ(group_set, process_info.AllGroups()); |
77 | 73 |
78 // The test executable isn’t expected to change privileges. | 74 // The test executable isn’t expected to change privileges. |
79 EXPECT_FALSE(process_info.DidChangePrivileges()); | 75 EXPECT_FALSE(process_info.DidChangePrivileges()); |
80 | 76 |
| 77 bool is_64_bit; |
| 78 ASSERT_TRUE(process_info.Is64Bit(&is_64_bit)); |
81 #if defined(ARCH_CPU_64_BITS) | 79 #if defined(ARCH_CPU_64_BITS) |
82 EXPECT_TRUE(process_info.Is64Bit()); | 80 EXPECT_TRUE(is_64_bit); |
83 #else | 81 #else |
84 EXPECT_FALSE(process_info.Is64Bit()); | 82 EXPECT_FALSE(is_64_bit); |
85 #endif | 83 #endif |
86 | 84 |
87 // Test StartTime(). This program must have started at some time in the past. | 85 // Test StartTime(). This program must have started at some time in the past. |
88 timeval start_time; | 86 timeval start_time; |
89 process_info.StartTime(&start_time); | 87 ASSERT_TRUE(process_info.StartTime(&start_time)); |
| 88 EXPECT_FALSE(start_time.tv_sec == 0 && start_time.tv_usec == 0); |
90 time_t now; | 89 time_t now; |
91 time(&now); | 90 time(&now); |
92 EXPECT_LE(start_time.tv_sec, now); | 91 EXPECT_LE(start_time.tv_sec, now); |
93 | 92 |
94 std::vector<std::string> argv; | 93 std::vector<std::string> argv; |
95 ASSERT_TRUE(process_info.Arguments(&argv)); | 94 ASSERT_TRUE(process_info.Arguments(&argv)); |
96 | 95 |
97 // gtest argv processing scrambles argv, but it leaves argc and argv[0] | 96 const std::vector<std::string>& expect_argv = GetMainArguments(); |
98 // intact, so test those. | |
99 | 97 |
100 #if defined(OS_MACOSX) | 98 // expect_argv always contains the initial view of the arguments at the time |
101 int expect_argc = *_NSGetArgc(); | 99 // the program was invoked. argv may contain this view, or it may contain the |
102 char** expect_argv = *_NSGetArgv(); | 100 // current view of arguments after gtest argv processing. argv may be a subset |
103 #elif defined(OS_LINUX) || defined(OS_ANDROID) | 101 // of expect_argv. |
104 std::vector<std::string> expect_arg_vector; | 102 // |
105 { | 103 // gtest argv processing always leaves argv[0] intact, so this can be checked |
106 base::ScopedFILE cmdline(fopen("/proc/self/cmdline", "re")); | 104 // directly. |
107 ASSERT_NE(nullptr, cmdline.get()) << ErrnoMessage("fopen"); | 105 ASSERT_FALSE(expect_argv.empty()); |
| 106 ASSERT_FALSE(argv.empty()); |
| 107 EXPECT_EQ(expect_argv[0], argv[0]); |
108 | 108 |
109 int expect_arg_char; | 109 EXPECT_LE(argv.size(), expect_argv.size()); |
110 std::string expect_arg_string; | 110 |
111 while ((expect_arg_char = fgetc(cmdline.get())) != EOF) { | 111 // Everything else in argv should have a match in expect_argv too, but things |
112 if (expect_arg_char != '\0') { | 112 // may have moved around. |
113 expect_arg_string.append(1, expect_arg_char); | 113 for (size_t arg_index = 1; arg_index < argv.size(); ++arg_index) { |
114 } else { | 114 const std::string& arg = argv[arg_index]; |
115 expect_arg_vector.push_back(expect_arg_string); | 115 SCOPED_TRACE( |
116 expect_arg_string.clear(); | 116 base::StringPrintf("arg_index %zu, arg %s", arg_index, arg.c_str())); |
117 } | 117 EXPECT_NE(expect_argv.end(), std::find(argv.begin(), argv.end(), arg)); |
118 } | |
119 ASSERT_EQ(0, ferror(cmdline.get())) << ErrnoMessage("fgetc"); | |
120 ASSERT_TRUE(expect_arg_string.empty()); | |
121 } | 118 } |
122 | |
123 std::vector<const char*> expect_argv_storage; | |
124 for (const std::string& expect_arg_string : expect_arg_vector) { | |
125 expect_argv_storage.push_back(expect_arg_string.c_str()); | |
126 } | |
127 | |
128 int expect_argc = expect_argv_storage.size(); | |
129 const char* const* expect_argv = | |
130 !expect_argv_storage.empty() ? &expect_argv_storage[0] : nullptr; | |
131 #else | |
132 #error Obtain expect_argc and expect_argv correctly on your system. | |
133 #endif | |
134 | |
135 int argc = implicit_cast<int>(argv.size()); | |
136 EXPECT_EQ(expect_argc, argc); | |
137 | |
138 ASSERT_GE(expect_argc, 1); | |
139 ASSERT_GE(argc, 1); | |
140 | |
141 EXPECT_EQ(std::string(expect_argv[0]), argv[0]); | |
142 } | 119 } |
143 | 120 |
| 121 void TestSelfProcess(const ProcessInfo& process_info) { |
| 122 EXPECT_EQ(getpid(), process_info.ProcessID()); |
| 123 EXPECT_EQ(getppid(), process_info.ParentProcessID()); |
| 124 |
| 125 TestProcessSelfOrClone(process_info); |
| 126 } |
144 | 127 |
145 TEST(ProcessInfo, Self) { | 128 TEST(ProcessInfo, Self) { |
146 ProcessInfo process_info; | 129 ProcessInfo process_info; |
147 ASSERT_TRUE(process_info.Initialize(getpid())); | 130 ASSERT_TRUE(process_info.Initialize(getpid())); |
148 TestSelfProcess(process_info); | 131 TestSelfProcess(process_info); |
149 } | 132 } |
150 | 133 |
151 #if defined(OS_MACOSX) | 134 #if defined(OS_MACOSX) |
152 TEST(ProcessInfo, SelfTask) { | 135 TEST(ProcessInfo, SelfTask) { |
153 ProcessInfo process_info; | 136 ProcessInfo process_info; |
(...skipping 12 matching lines...) Expand all Loading... |
166 EXPECT_EQ(implicit_cast<pid_t>(0), process_info.ParentProcessID()); | 149 EXPECT_EQ(implicit_cast<pid_t>(0), process_info.ParentProcessID()); |
167 EXPECT_EQ(implicit_cast<uid_t>(0), process_info.RealUserID()); | 150 EXPECT_EQ(implicit_cast<uid_t>(0), process_info.RealUserID()); |
168 EXPECT_EQ(implicit_cast<uid_t>(0), process_info.EffectiveUserID()); | 151 EXPECT_EQ(implicit_cast<uid_t>(0), process_info.EffectiveUserID()); |
169 EXPECT_EQ(implicit_cast<uid_t>(0), process_info.SavedUserID()); | 152 EXPECT_EQ(implicit_cast<uid_t>(0), process_info.SavedUserID()); |
170 EXPECT_EQ(implicit_cast<gid_t>(0), process_info.RealGroupID()); | 153 EXPECT_EQ(implicit_cast<gid_t>(0), process_info.RealGroupID()); |
171 EXPECT_EQ(implicit_cast<gid_t>(0), process_info.EffectiveGroupID()); | 154 EXPECT_EQ(implicit_cast<gid_t>(0), process_info.EffectiveGroupID()); |
172 EXPECT_EQ(implicit_cast<gid_t>(0), process_info.SavedGroupID()); | 155 EXPECT_EQ(implicit_cast<gid_t>(0), process_info.SavedGroupID()); |
173 EXPECT_FALSE(process_info.AllGroups().empty()); | 156 EXPECT_FALSE(process_info.AllGroups().empty()); |
174 } | 157 } |
175 | 158 |
| 159 TEST(ProcessInfo, Forked) { |
| 160 pid_t pid = fork(); |
| 161 if (pid == 0) { |
| 162 raise(SIGSTOP); |
| 163 _exit(0); |
| 164 } |
| 165 ASSERT_GE(pid, 0) << ErrnoMessage("fork"); |
| 166 |
| 167 ProcessInfo process_info; |
| 168 ASSERT_TRUE(process_info.Initialize(pid)); |
| 169 |
| 170 EXPECT_EQ(pid, process_info.ProcessID()); |
| 171 EXPECT_EQ(getpid(), process_info.ParentProcessID()); |
| 172 |
| 173 TestProcessSelfOrClone(process_info); |
| 174 kill(pid, SIGKILL); |
| 175 } |
| 176 |
176 } // namespace | 177 } // namespace |
177 } // namespace test | 178 } // namespace test |
178 } // namespace crashpad | 179 } // namespace crashpad |
OLD | NEW |