blob: cfd3c0915002856662db9998de35932c1d49be7d [file] [log] [blame]
Robert Sesek8225b7c2016-12-16 14:02:31 -05001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "fd_utils.h"
18
19#include <algorithm>
20
21#include <fcntl.h>
22#include <grp.h>
23#include <stdlib.h>
24#include <sys/socket.h>
25#include <sys/types.h>
26#include <sys/un.h>
27#include <unistd.h>
28
Narayan Kamath3879ecc2017-03-02 17:30:03 +000029#include <android-base/file.h>
Narayan Kamatha352d242017-03-02 14:44:45 +000030#include <android-base/logging.h>
Narayan Kamath3879ecc2017-03-02 17:30:03 +000031#include <android-base/stringprintf.h>
Robert Sesek8225b7c2016-12-16 14:02:31 -050032#include <android-base/strings.h>
Robert Sesek8225b7c2016-12-16 14:02:31 -050033
Robert Sesek54e387d2016-12-02 17:27:50 -050034// Static whitelist of open paths that the zygote is allowed to keep open.
Robert Sesek8225b7c2016-12-16 14:02:31 -050035static const char* kPathWhitelist[] = {
Anton Hansson5b972692020-01-08 09:48:18 +000036 "/apex/com.android.appsearch/javalib/framework-appsearch.jar",
37 "/apex/com.android.conscrypt/javalib/conscrypt.jar",
38 "/apex/com.android.ipsec/javalib/ike.jar",
39 "/apex/com.android.media/javalib/updatable-media.jar",
40 "/apex/com.android.mediaprovider/javalib/framework-mediaprovider.jar",
41 "/apex/com.android.os.statsd/javalib/framework-statsd.jar",
Hai Zhang82a62272020-01-14 21:56:34 -080042 "/apex/com.android.permission/javalib/framework-permission.jar",
Anton Hansson5b972692020-01-08 09:48:18 +000043 "/apex/com.android.sdkext/javalib/framework-sdkextensions.jar",
44 "/apex/com.android.wifi/javalib/framework-wifi.jar",
45 "/apex/com.android.tethering/javalib/framework-tethering.jar",
46 "/dev/null",
47 "/dev/socket/zygote",
48 "/dev/socket/zygote_secondary",
49 "/dev/socket/usap_pool_primary",
50 "/dev/socket/usap_pool_secondary",
51 "/dev/socket/webview_zygote",
52 "/dev/socket/heapprofd",
53 "/sys/kernel/debug/tracing/trace_marker",
Hridya Valsarajudc0c12e2020-01-30 17:47:21 -080054 "/sys/kernel/tracing/trace_marker",
Anton Hansson5b972692020-01-08 09:48:18 +000055 "/system/framework/framework-res.apk",
56 "/dev/urandom",
57 "/dev/ion",
58 "/dev/dri/renderD129", // Fixes b/31172436
Robert Sesek8225b7c2016-12-16 14:02:31 -050059};
60
61static const char kFdPath[] = "/proc/self/fd";
62
63// static
Robert Sesek54e387d2016-12-02 17:27:50 -050064FileDescriptorWhitelist* FileDescriptorWhitelist::Get() {
65 if (instance_ == nullptr) {
66 instance_ = new FileDescriptorWhitelist();
67 }
68 return instance_;
69}
70
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +000071static bool IsArtMemfd(const std::string& path) {
72 return android::base::StartsWith(path, "/memfd:/boot-image-methods.art");
Nicolas Geoffray813b9e82019-10-24 15:33:01 +010073}
74
Robert Sesek54e387d2016-12-02 17:27:50 -050075bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
76 // Check the static whitelist path.
77 for (const auto& whitelist_path : kPathWhitelist) {
78 if (path == whitelist_path)
79 return true;
80 }
81
82 // Check any paths added to the dynamic whitelist.
83 for (const auto& whitelist_path : whitelist_) {
84 if (path == whitelist_path)
85 return true;
86 }
87
Nicolas Geoffrayfca69e92019-01-22 20:56:44 +000088 // Framework jars are allowed.
Narayan Kamath3879ecc2017-03-02 17:30:03 +000089 static const char* kFrameworksPrefix = "/system/framework/";
90 static const char* kJarSuffix = ".jar";
91 if (android::base::StartsWith(path, kFrameworksPrefix)
92 && android::base::EndsWith(path, kJarSuffix)) {
Robert Sesek54e387d2016-12-02 17:27:50 -050093 return true;
94 }
95
Martin Stjernholm28f0a762019-07-17 22:10:40 +010096 // Jars from the ART APEX are allowed.
97 static const char* kArtApexPrefix = "/apex/com.android.art/javalib/";
98 if (android::base::StartsWith(path, kArtApexPrefix)
Nicolas Geoffrayfca69e92019-01-22 20:56:44 +000099 && android::base::EndsWith(path, kJarSuffix)) {
100 return true;
101 }
102
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +0000103 // the in-memory file created by ART through memfd_create is allowed.
104 if (IsArtMemfd(path)) {
Nicolas Geoffray813b9e82019-10-24 15:33:01 +0100105 return true;
106 }
107
Robert Sesek54e387d2016-12-02 17:27:50 -0500108 // Whitelist files needed for Runtime Resource Overlay, like these:
109 // /system/vendor/overlay/framework-res.apk
110 // /system/vendor/overlay-subdir/pg/framework-res.apk
111 // /vendor/overlay/framework-res.apk
112 // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
113 // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
114 // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
115 // See AssetManager.cpp for more details on overlay-subdir.
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000116 static const char* kOverlayDir = "/system/vendor/overlay/";
117 static const char* kVendorOverlayDir = "/vendor/overlay";
Mårten Kongstad06a1ac82018-09-20 13:09:47 +0200118 static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/";
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900119 static const char* kSystemProductOverlayDir = "/system/product/overlay/";
120 static const char* kProductOverlayDir = "/product/overlay";
Jeongik Cha3e725f22019-07-09 23:58:01 +0900121 static const char* kSystemSystemExtOverlayDir = "/system/system_ext/overlay/";
122 static const char* kSystemExtOverlayDir = "/system_ext/overlay";
Mårten Kongstad48c24cf2019-02-25 10:54:09 +0100123 static const char* kSystemOdmOverlayDir = "/system/odm/overlay";
124 static const char* kOdmOverlayDir = "/odm/overlay";
Mårten Kongstadeb8a5c02019-02-25 14:18:17 +0100125 static const char* kSystemOemOverlayDir = "/system/oem/overlay";
126 static const char* kOemOverlayDir = "/oem/overlay";
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000127 static const char* kApkSuffix = ".apk";
Robert Sesek54e387d2016-12-02 17:27:50 -0500128
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000129 if ((android::base::StartsWith(path, kOverlayDir)
Mårten Kongstad06a1ac82018-09-20 13:09:47 +0200130 || android::base::StartsWith(path, kVendorOverlaySubdir)
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900131 || android::base::StartsWith(path, kVendorOverlayDir)
132 || android::base::StartsWith(path, kSystemProductOverlayDir)
Dario Freni4ce46792018-06-01 14:02:08 +0100133 || android::base::StartsWith(path, kProductOverlayDir)
Jeongik Cha3e725f22019-07-09 23:58:01 +0900134 || android::base::StartsWith(path, kSystemSystemExtOverlayDir)
135 || android::base::StartsWith(path, kSystemExtOverlayDir)
Mårten Kongstad48c24cf2019-02-25 10:54:09 +0100136 || android::base::StartsWith(path, kSystemOdmOverlayDir)
Mårten Kongstadeb8a5c02019-02-25 14:18:17 +0100137 || android::base::StartsWith(path, kOdmOverlayDir)
138 || android::base::StartsWith(path, kSystemOemOverlayDir)
139 || android::base::StartsWith(path, kOemOverlayDir))
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000140 && android::base::EndsWith(path, kApkSuffix)
Robert Sesek54e387d2016-12-02 17:27:50 -0500141 && path.find("/../") == std::string::npos) {
142 return true;
143 }
144
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000145 static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
146 static const char* kOverlayIdmapSuffix = ".apk@idmap";
147 if (android::base::StartsWith(path, kOverlayIdmapPrefix)
148 && android::base::EndsWith(path, kOverlayIdmapSuffix)
Robert Sesek54e387d2016-12-02 17:27:50 -0500149 && path.find("/../") == std::string::npos) {
150 return true;
151 }
152
153 // All regular files that are placed under this path are whitelisted automatically.
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000154 static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
155 if (android::base::StartsWith(path, kZygoteWhitelistPath)
156 && path.find("/../") == std::string::npos) {
Robert Sesek54e387d2016-12-02 17:27:50 -0500157 return true;
158 }
159
160 return false;
161}
162
163FileDescriptorWhitelist::FileDescriptorWhitelist()
164 : whitelist_() {
165}
166
Robert Sesek54e387d2016-12-02 17:27:50 -0500167FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
168
Andreas Gampe183a5d32018-03-12 14:53:34 -0700169// Keeps track of all relevant information (flags, offset etc.) of an
170// open zygote file descriptor.
171class FileDescriptorInfo {
172 public:
Chris Wailesaa1c9622019-01-10 16:55:32 -0800173 // Create a FileDescriptorInfo for a given file descriptor.
174 static FileDescriptorInfo* CreateFromFd(int fd, fail_fn_t fail_fn);
Andreas Gampe183a5d32018-03-12 14:53:34 -0700175
176 // Checks whether the file descriptor associated with this object
177 // refers to the same description.
Chris Wailesaa1c9622019-01-10 16:55:32 -0800178 bool RefersToSameFile() const;
Andreas Gampe183a5d32018-03-12 14:53:34 -0700179
Chris Wailesaa1c9622019-01-10 16:55:32 -0800180 void ReopenOrDetach(fail_fn_t fail_fn) const;
Andreas Gampe183a5d32018-03-12 14:53:34 -0700181
182 const int fd;
183 const struct stat stat;
184 const std::string file_path;
185 const int open_flags;
186 const int fd_flags;
187 const int fs_flags;
188 const off_t offset;
189 const bool is_sock;
190
191 private:
Chih-Hung Hsieh0727be12018-12-20 13:43:46 -0800192 explicit FileDescriptorInfo(int fd);
Andreas Gampe183a5d32018-03-12 14:53:34 -0700193
194 FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
195 int fd_flags, int fs_flags, off_t offset);
196
197 // Returns the locally-bound name of the socket |fd|. Returns true
198 // iff. all of the following hold :
199 //
200 // - the socket's sa_family is AF_UNIX.
201 // - the length of the path is greater than zero (i.e, not an unnamed socket).
202 // - the first byte of the path isn't zero (i.e, not a socket with an abstract
203 // address).
204 static bool GetSocketName(const int fd, std::string* result);
205
Chris Wailesaa1c9622019-01-10 16:55:32 -0800206 void DetachSocket(fail_fn_t fail_fn) const;
Andreas Gampe183a5d32018-03-12 14:53:34 -0700207
208 DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
209};
210
Robert Sesek54e387d2016-12-02 17:27:50 -0500211// static
Chris Wailesaa1c9622019-01-10 16:55:32 -0800212FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500213 struct stat f_stat;
214 // This should never happen; the zygote should always have the right set
215 // of permissions required to stat all its open files.
216 if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800217 fail_fn(android::base::StringPrintf("Unable to stat %d", fd));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500218 }
219
Robert Sesek54e387d2016-12-02 17:27:50 -0500220 const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get();
221
Robert Sesek8225b7c2016-12-16 14:02:31 -0500222 if (S_ISSOCK(f_stat.st_mode)) {
223 std::string socket_name;
224 if (!GetSocketName(fd, &socket_name)) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800225 fail_fn("Unable to get socket name");
Robert Sesek8225b7c2016-12-16 14:02:31 -0500226 }
227
Robert Sesek54e387d2016-12-02 17:27:50 -0500228 if (!whitelist->IsAllowed(socket_name)) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800229 fail_fn(android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)",
230 socket_name.c_str(),
231 fd));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500232 }
233
234 return new FileDescriptorInfo(fd);
235 }
236
237 // We only handle whitelisted regular files and character devices. Whitelisted
238 // character devices must provide a guarantee of sensible behaviour when
239 // reopened.
240 //
241 // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
242 // S_ISLINK : Not supported.
243 // S_ISBLK : Not supported.
Chris Wailes7e797b62019-02-22 18:29:22 -0800244 // S_ISFIFO : Not supported. Note that the Zygote and USAPs use pipes to
Chris Wailesaa1c9622019-01-10 16:55:32 -0800245 // communicate with the child processes across forks but those should have been
246 // added to the redirection exemption list.
Robert Sesek8225b7c2016-12-16 14:02:31 -0500247 if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800248 std::string mode = "Unknown";
249
250 if (S_ISDIR(f_stat.st_mode)) {
251 mode = "DIR";
252 } else if (S_ISLNK(f_stat.st_mode)) {
253 mode = "LINK";
254 } else if (S_ISBLK(f_stat.st_mode)) {
255 mode = "BLOCK";
256 } else if (S_ISFIFO(f_stat.st_mode)) {
257 mode = "FIFO";
258 }
259
260 fail_fn(android::base::StringPrintf("Unsupported st_mode for FD %d: %s", fd, mode.c_str()));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500261 }
262
263 std::string file_path;
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000264 const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
265 if (!android::base::Readlink(fd_path, &file_path)) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800266 fail_fn(android::base::StringPrintf("Could not read fd link %s: %s",
267 fd_path.c_str(),
268 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500269 }
270
Robert Sesek54e387d2016-12-02 17:27:50 -0500271 if (!whitelist->IsAllowed(file_path)) {
Nicolas Geoffray983f8a52019-06-11 17:47:16 +0100272 fail_fn(android::base::StringPrintf("Not whitelisted (%d): %s", fd, file_path.c_str()));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500273 }
274
275 // File descriptor flags : currently on FD_CLOEXEC. We can set these
276 // using F_SETFD - we're single threaded at this point of execution so
277 // there won't be any races.
278 const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
279 if (fd_flags == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800280 fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s",
281 fd,
282 file_path.c_str(),
283 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500284 }
285
286 // File status flags :
287 // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
288 // to the open() call.
289 //
290 // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
291 // do about these, since the file has already been created. We shall ignore
292 // them here.
293 //
294 // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
295 // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
296 // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
297 // their presence and pass them in to open().
298 int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
299 if (fs_flags == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800300 fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s",
301 fd,
302 file_path.c_str(),
303 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500304 }
305
306 // File offset : Ignore the offset for non seekable files.
307 const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
308
309 // We pass the flags that open accepts to open, and use F_SETFL for
310 // the rest of them.
311 static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
312 int open_flags = fs_flags & (kOpenFlags);
313 fs_flags = fs_flags & (~(kOpenFlags));
314
315 return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
316}
317
Chris Wailesaa1c9622019-01-10 16:55:32 -0800318bool FileDescriptorInfo::RefersToSameFile() const {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500319 struct stat f_stat;
320 if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
Narayan Kamatha352d242017-03-02 14:44:45 +0000321 PLOG(ERROR) << "Unable to restat fd " << fd;
Robert Sesek8225b7c2016-12-16 14:02:31 -0500322 return false;
323 }
324
325 return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
326}
327
Chris Wailesaa1c9622019-01-10 16:55:32 -0800328void FileDescriptorInfo::ReopenOrDetach(fail_fn_t fail_fn) const {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500329 if (is_sock) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800330 return DetachSocket(fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500331 }
332
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +0000333 // Children can directly use the in-memory file created by ART through memfd_create.
334 if (IsArtMemfd(file_path)) {
Nicolas Geoffray813b9e82019-10-24 15:33:01 +0100335 return;
336 }
337
Robert Sesek8225b7c2016-12-16 14:02:31 -0500338 // NOTE: This might happen if the file was unlinked after being opened.
339 // It's a common pattern in the case of temporary files and the like but
340 // we should not allow such usage from the zygote.
341 const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
342
343 if (new_fd == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800344 fail_fn(android::base::StringPrintf("Failed open(%s, %i): %s",
345 file_path.c_str(),
346 open_flags,
347 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500348 }
349
350 if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
351 close(new_fd);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800352 fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s",
353 new_fd,
354 fd_flags,
355 file_path.c_str(),
356 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500357 }
358
359 if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
360 close(new_fd);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800361 fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s",
362 new_fd,
363 fs_flags,
364 file_path.c_str(),
365 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500366 }
367
368 if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
369 close(new_fd);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800370 fail_fn(android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s",
371 new_fd,
372 file_path.c_str(),
373 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500374 }
375
Chris Wailesaa1c9622019-01-10 16:55:32 -0800376 int dup_flags = (fd_flags & FD_CLOEXEC) ? O_CLOEXEC : 0;
377 if (TEMP_FAILURE_RETRY(dup3(new_fd, fd, dup_flags)) == -1) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500378 close(new_fd);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800379 fail_fn(android::base::StringPrintf("Failed dup3(%d, %d, %d) (%s): %s",
380 fd,
381 new_fd,
382 dup_flags,
383 file_path.c_str(),
384 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500385 }
386
387 close(new_fd);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500388}
389
390FileDescriptorInfo::FileDescriptorInfo(int fd) :
391 fd(fd),
392 stat(),
393 open_flags(0),
394 fd_flags(0),
395 fs_flags(0),
396 offset(0),
397 is_sock(true) {
398}
399
400FileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file_path,
401 int fd, int open_flags, int fd_flags, int fs_flags,
402 off_t offset) :
403 fd(fd),
404 stat(stat),
405 file_path(file_path),
406 open_flags(open_flags),
407 fd_flags(fd_flags),
408 fs_flags(fs_flags),
409 offset(offset),
410 is_sock(false) {
411}
412
Robert Sesek8225b7c2016-12-16 14:02:31 -0500413bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
414 sockaddr_storage ss;
415 sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
416 socklen_t addr_len = sizeof(ss);
417
418 if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
Narayan Kamath84b55112017-03-02 17:04:08 +0000419 PLOG(ERROR) << "Failed getsockname(" << fd << ")";
Robert Sesek8225b7c2016-12-16 14:02:31 -0500420 return false;
421 }
422
423 if (addr->sa_family != AF_UNIX) {
Narayan Kamath84b55112017-03-02 17:04:08 +0000424 LOG(ERROR) << "Unsupported socket (fd=" << fd << ") with family " << addr->sa_family;
Robert Sesek8225b7c2016-12-16 14:02:31 -0500425 return false;
426 }
427
428 const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
429
430 size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
431 // This is an unnamed local socket, we do not accept it.
432 if (path_len == 0) {
Narayan Kamath84b55112017-03-02 17:04:08 +0000433 LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with empty path.";
Robert Sesek8225b7c2016-12-16 14:02:31 -0500434 return false;
435 }
436
Robert Sesekd0a190df2018-02-12 18:46:01 -0500437 // This is a local socket with an abstract address. Remove the leading NUL byte and
438 // add a human-readable "ABSTRACT/" prefix.
Robert Sesek8225b7c2016-12-16 14:02:31 -0500439 if (unix_addr->sun_path[0] == '\0') {
Robert Sesekd0a190df2018-02-12 18:46:01 -0500440 *result = "ABSTRACT/";
441 result->append(&unix_addr->sun_path[1], path_len - 1);
442 return true;
Robert Sesek8225b7c2016-12-16 14:02:31 -0500443 }
444
445 // If we're here, sun_path must refer to a null terminated filesystem
446 // pathname (man 7 unix). Remove the terminator before assigning it to an
447 // std::string.
448 if (unix_addr->sun_path[path_len - 1] == '\0') {
449 --path_len;
450 }
451
452 result->assign(unix_addr->sun_path, path_len);
453 return true;
454}
455
Chris Wailesaa1c9622019-01-10 16:55:32 -0800456void FileDescriptorInfo::DetachSocket(fail_fn_t fail_fn) const {
Nick Kralevich0361ce12019-01-25 10:08:58 -0800457 const int dev_null_fd = open("/dev/null", O_RDWR | O_CLOEXEC);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500458 if (dev_null_fd < 0) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800459 fail_fn(std::string("Failed to open /dev/null: ").append(strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500460 }
461
Nick Kralevich0361ce12019-01-25 10:08:58 -0800462 if (dup3(dev_null_fd, fd, O_CLOEXEC) == -1) {
463 fail_fn(android::base::StringPrintf("Failed dup3 on socket descriptor %d: %s",
Chris Wailesaa1c9622019-01-10 16:55:32 -0800464 fd,
465 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500466 }
467
468 if (close(dev_null_fd) == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800469 fail_fn(android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500470 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500471}
472
473// static
Andreas Gampe183a5d32018-03-12 14:53:34 -0700474FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore,
Chris Wailesaa1c9622019-01-10 16:55:32 -0800475 fail_fn_t fail_fn) {
476 DIR* proc_fd_dir = opendir(kFdPath);
477 if (proc_fd_dir == nullptr) {
478 fail_fn(std::string("Unable to open directory ").append(kFdPath));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500479 }
Chris Wailesaa1c9622019-01-10 16:55:32 -0800480
481 int dir_fd = dirfd(proc_fd_dir);
482 dirent* dir_entry;
Robert Sesek8225b7c2016-12-16 14:02:31 -0500483
484 std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
Chris Wailesaa1c9622019-01-10 16:55:32 -0800485 while ((dir_entry = readdir(proc_fd_dir)) != nullptr) {
486 const int fd = ParseFd(dir_entry, dir_fd);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500487 if (fd == -1) {
488 continue;
489 }
Chris Wailesaa1c9622019-01-10 16:55:32 -0800490
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800491 if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800492 continue;
493 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500494
Chris Wailesaa1c9622019-01-10 16:55:32 -0800495 open_fd_map[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500496 }
497
Chris Wailesaa1c9622019-01-10 16:55:32 -0800498 if (closedir(proc_fd_dir) == -1) {
499 fail_fn("Unable to close directory");
Robert Sesek8225b7c2016-12-16 14:02:31 -0500500 }
Chris Wailesaa1c9622019-01-10 16:55:32 -0800501
Robert Sesek8225b7c2016-12-16 14:02:31 -0500502 return new FileDescriptorTable(open_fd_map);
503}
504
Chris Wailesaa1c9622019-01-10 16:55:32 -0800505void FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, fail_fn_t fail_fn) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500506 std::set<int> open_fds;
507
508 // First get the list of open descriptors.
Chris Wailesaa1c9622019-01-10 16:55:32 -0800509 DIR* proc_fd_dir = opendir(kFdPath);
510 if (proc_fd_dir == nullptr) {
511 fail_fn(android::base::StringPrintf("Unable to open directory %s: %s",
512 kFdPath,
513 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500514 }
515
Chris Wailesaa1c9622019-01-10 16:55:32 -0800516 int dir_fd = dirfd(proc_fd_dir);
517 dirent* dir_entry;
518 while ((dir_entry = readdir(proc_fd_dir)) != nullptr) {
519 const int fd = ParseFd(dir_entry, dir_fd);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500520 if (fd == -1) {
521 continue;
522 }
Chris Wailesaa1c9622019-01-10 16:55:32 -0800523
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800524 if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800525 continue;
526 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500527
528 open_fds.insert(fd);
529 }
530
Chris Wailesaa1c9622019-01-10 16:55:32 -0800531 if (closedir(proc_fd_dir) == -1) {
532 fail_fn(android::base::StringPrintf("Unable to close directory: %s", strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500533 }
534
Chris Wailesaa1c9622019-01-10 16:55:32 -0800535 RestatInternal(open_fds, fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500536}
537
Chris Wailesaa1c9622019-01-10 16:55:32 -0800538// Reopens all file descriptors that are contained in the table.
539void FileDescriptorTable::ReopenOrDetach(fail_fn_t fail_fn) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500540 std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
541 for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
542 const FileDescriptorInfo* info = it->second;
Chris Wailesaa1c9622019-01-10 16:55:32 -0800543 if (info == nullptr) {
544 return;
545 } else {
546 info->ReopenOrDetach(fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500547 }
548 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500549}
550
551FileDescriptorTable::FileDescriptorTable(
552 const std::unordered_map<int, FileDescriptorInfo*>& map)
553 : open_fd_map_(map) {
554}
555
Chris Wailesaa1c9622019-01-10 16:55:32 -0800556void FileDescriptorTable::RestatInternal(std::set<int>& open_fds, fail_fn_t fail_fn) {
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +0000557 // ART creates a file through memfd for optimization purposes. We make sure
558 // there is at most one being created.
559 bool art_memfd_seen = false;
560
Robert Sesek8225b7c2016-12-16 14:02:31 -0500561 // Iterate through the list of file descriptors we've already recorded
562 // and check whether :
563 //
564 // (a) they continue to be open.
565 // (b) they refer to the same file.
Andreas Gampe183a5d32018-03-12 14:53:34 -0700566 //
567 // We'll only store the last error message.
Robert Sesek8225b7c2016-12-16 14:02:31 -0500568 std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
569 while (it != open_fd_map_.end()) {
570 std::set<int>::const_iterator element = open_fds.find(it->first);
571 if (element == open_fds.end()) {
572 // The entry from the file descriptor table is no longer in the list
573 // of open files. We warn about this condition and remove it from
574 // the list of FDs under consideration.
575 //
576 // TODO(narayan): This will be an error in a future android release.
577 // error = true;
578 // ALOGW("Zygote closed file descriptor %d.", it->first);
579 it = open_fd_map_.erase(it);
580 } else {
581 // The entry from the file descriptor table is still open. Restat
582 // it and check whether it refers to the same file.
Chris Wailesaa1c9622019-01-10 16:55:32 -0800583 if (!it->second->RefersToSameFile()) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500584 // The file descriptor refers to a different description. We must
585 // update our entry in the table.
586 delete it->second;
Chris Wailesaa1c9622019-01-10 16:55:32 -0800587 it->second = FileDescriptorInfo::CreateFromFd(*element, fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500588 } else {
589 // It's the same file. Nothing to do here. Move on to the next open
590 // FD.
Robert Sesek8225b7c2016-12-16 14:02:31 -0500591 }
592
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +0000593 if (IsArtMemfd(it->second->file_path)) {
594 if (art_memfd_seen) {
595 fail_fn("ART fd already seen: " + it->second->file_path);
596 } else {
597 art_memfd_seen = true;
598 }
599 }
600
Chris Wailesaa1c9622019-01-10 16:55:32 -0800601 ++it;
602
Robert Sesek8225b7c2016-12-16 14:02:31 -0500603 // Finally, remove the FD from the set of open_fds. We do this last because
604 // |element| will not remain valid after a call to erase.
605 open_fds.erase(element);
606 }
607 }
608
609 if (open_fds.size() > 0) {
610 // The zygote has opened new file descriptors since our last inspection.
611 // We warn about this condition and add them to our table.
612 //
613 // TODO(narayan): This will be an error in a future android release.
614 // error = true;
615 // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
616
617 // TODO(narayan): This code will be removed in a future android release.
618 std::set<int>::const_iterator it;
619 for (it = open_fds.begin(); it != open_fds.end(); ++it) {
620 const int fd = (*it);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800621 open_fd_map_[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500622 }
623 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500624}
625
626// static
Chris Wailesaa1c9622019-01-10 16:55:32 -0800627int FileDescriptorTable::ParseFd(dirent* dir_entry, int dir_fd) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500628 char* end;
Chris Wailesaa1c9622019-01-10 16:55:32 -0800629 const int fd = strtol(dir_entry->d_name, &end, 10);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500630 if ((*end) != '\0') {
631 return -1;
632 }
633
634 // Don't bother with the standard input/output/error, they're handled
635 // specially post-fork anyway.
636 if (fd <= STDERR_FILENO || fd == dir_fd) {
637 return -1;
638 }
639
640 return fd;
641}