blob: fd6984b830d7bffa86ff554513225d696deb7f8f [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[] = {
Adam Vartanian25095752019-01-08 11:00:40 +000036 "/apex/com.android.conscrypt/javalib/conscrypt.jar",
Benedict Wong1b70ca22019-11-19 18:45:17 -080037 "/apex/com.android.ipsec/javalib/ike.jar",
Dongwon Kang0d035532019-01-17 13:35:03 -080038 "/apex/com.android.media/javalib/updatable-media.jar",
Anton Hansson9a96a582019-12-02 13:21:18 +000039 "/apex/com.android.sdkext/javalib/framework-sdkext.jar",
Robert Sesek8225b7c2016-12-16 14:02:31 -050040 "/dev/null",
41 "/dev/socket/zygote",
42 "/dev/socket/zygote_secondary",
Chris Wailes7e797b62019-02-22 18:29:22 -080043 "/dev/socket/usap_pool_primary",
44 "/dev/socket/usap_pool_secondary",
Robert Sesek8225b7c2016-12-16 14:02:31 -050045 "/dev/socket/webview_zygote",
Florian Mayer6ce2d992018-10-16 14:30:02 +010046 "/dev/socket/heapprofd",
Robert Sesek8225b7c2016-12-16 14:02:31 -050047 "/sys/kernel/debug/tracing/trace_marker",
48 "/system/framework/framework-res.apk",
49 "/dev/urandom",
50 "/dev/ion",
51 "/dev/dri/renderD129", // Fixes b/31172436
52};
53
54static const char kFdPath[] = "/proc/self/fd";
55
56// static
Robert Sesek54e387d2016-12-02 17:27:50 -050057FileDescriptorWhitelist* FileDescriptorWhitelist::Get() {
58 if (instance_ == nullptr) {
59 instance_ = new FileDescriptorWhitelist();
60 }
61 return instance_;
62}
63
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +000064static bool IsArtMemfd(const std::string& path) {
65 return android::base::StartsWith(path, "/memfd:/boot-image-methods.art");
Nicolas Geoffray813b9e82019-10-24 15:33:01 +010066}
67
Robert Sesek54e387d2016-12-02 17:27:50 -050068bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
69 // Check the static whitelist path.
70 for (const auto& whitelist_path : kPathWhitelist) {
71 if (path == whitelist_path)
72 return true;
73 }
74
75 // Check any paths added to the dynamic whitelist.
76 for (const auto& whitelist_path : whitelist_) {
77 if (path == whitelist_path)
78 return true;
79 }
80
Nicolas Geoffrayfca69e92019-01-22 20:56:44 +000081 // Framework jars are allowed.
Narayan Kamath3879ecc2017-03-02 17:30:03 +000082 static const char* kFrameworksPrefix = "/system/framework/";
83 static const char* kJarSuffix = ".jar";
84 if (android::base::StartsWith(path, kFrameworksPrefix)
85 && android::base::EndsWith(path, kJarSuffix)) {
Robert Sesek54e387d2016-12-02 17:27:50 -050086 return true;
87 }
88
Martin Stjernholm28f0a762019-07-17 22:10:40 +010089 // Jars from the ART APEX are allowed.
90 static const char* kArtApexPrefix = "/apex/com.android.art/javalib/";
91 if (android::base::StartsWith(path, kArtApexPrefix)
Nicolas Geoffrayfca69e92019-01-22 20:56:44 +000092 && android::base::EndsWith(path, kJarSuffix)) {
93 return true;
94 }
95
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +000096 // the in-memory file created by ART through memfd_create is allowed.
97 if (IsArtMemfd(path)) {
Nicolas Geoffray813b9e82019-10-24 15:33:01 +010098 return true;
99 }
100
Robert Sesek54e387d2016-12-02 17:27:50 -0500101 // Whitelist files needed for Runtime Resource Overlay, like these:
102 // /system/vendor/overlay/framework-res.apk
103 // /system/vendor/overlay-subdir/pg/framework-res.apk
104 // /vendor/overlay/framework-res.apk
105 // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
106 // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
107 // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
108 // See AssetManager.cpp for more details on overlay-subdir.
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000109 static const char* kOverlayDir = "/system/vendor/overlay/";
110 static const char* kVendorOverlayDir = "/vendor/overlay";
Mårten Kongstad06a1ac82018-09-20 13:09:47 +0200111 static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/";
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900112 static const char* kSystemProductOverlayDir = "/system/product/overlay/";
113 static const char* kProductOverlayDir = "/product/overlay";
Jeongik Cha3e725f22019-07-09 23:58:01 +0900114 static const char* kSystemSystemExtOverlayDir = "/system/system_ext/overlay/";
115 static const char* kSystemExtOverlayDir = "/system_ext/overlay";
Mårten Kongstad48c24cf2019-02-25 10:54:09 +0100116 static const char* kSystemOdmOverlayDir = "/system/odm/overlay";
117 static const char* kOdmOverlayDir = "/odm/overlay";
Mårten Kongstadeb8a5c02019-02-25 14:18:17 +0100118 static const char* kSystemOemOverlayDir = "/system/oem/overlay";
119 static const char* kOemOverlayDir = "/oem/overlay";
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000120 static const char* kApkSuffix = ".apk";
Robert Sesek54e387d2016-12-02 17:27:50 -0500121
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000122 if ((android::base::StartsWith(path, kOverlayDir)
Mårten Kongstad06a1ac82018-09-20 13:09:47 +0200123 || android::base::StartsWith(path, kVendorOverlaySubdir)
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900124 || android::base::StartsWith(path, kVendorOverlayDir)
125 || android::base::StartsWith(path, kSystemProductOverlayDir)
Dario Freni4ce46792018-06-01 14:02:08 +0100126 || android::base::StartsWith(path, kProductOverlayDir)
Jeongik Cha3e725f22019-07-09 23:58:01 +0900127 || android::base::StartsWith(path, kSystemSystemExtOverlayDir)
128 || android::base::StartsWith(path, kSystemExtOverlayDir)
Mårten Kongstad48c24cf2019-02-25 10:54:09 +0100129 || android::base::StartsWith(path, kSystemOdmOverlayDir)
Mårten Kongstadeb8a5c02019-02-25 14:18:17 +0100130 || android::base::StartsWith(path, kOdmOverlayDir)
131 || android::base::StartsWith(path, kSystemOemOverlayDir)
132 || android::base::StartsWith(path, kOemOverlayDir))
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000133 && android::base::EndsWith(path, kApkSuffix)
Robert Sesek54e387d2016-12-02 17:27:50 -0500134 && path.find("/../") == std::string::npos) {
135 return true;
136 }
137
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000138 static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
139 static const char* kOverlayIdmapSuffix = ".apk@idmap";
140 if (android::base::StartsWith(path, kOverlayIdmapPrefix)
141 && android::base::EndsWith(path, kOverlayIdmapSuffix)
Robert Sesek54e387d2016-12-02 17:27:50 -0500142 && path.find("/../") == std::string::npos) {
143 return true;
144 }
145
146 // All regular files that are placed under this path are whitelisted automatically.
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000147 static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
148 if (android::base::StartsWith(path, kZygoteWhitelistPath)
149 && path.find("/../") == std::string::npos) {
Robert Sesek54e387d2016-12-02 17:27:50 -0500150 return true;
151 }
152
153 return false;
154}
155
156FileDescriptorWhitelist::FileDescriptorWhitelist()
157 : whitelist_() {
158}
159
Robert Sesek54e387d2016-12-02 17:27:50 -0500160FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
161
Andreas Gampe183a5d32018-03-12 14:53:34 -0700162// Keeps track of all relevant information (flags, offset etc.) of an
163// open zygote file descriptor.
164class FileDescriptorInfo {
165 public:
Chris Wailesaa1c9622019-01-10 16:55:32 -0800166 // Create a FileDescriptorInfo for a given file descriptor.
167 static FileDescriptorInfo* CreateFromFd(int fd, fail_fn_t fail_fn);
Andreas Gampe183a5d32018-03-12 14:53:34 -0700168
169 // Checks whether the file descriptor associated with this object
170 // refers to the same description.
Chris Wailesaa1c9622019-01-10 16:55:32 -0800171 bool RefersToSameFile() const;
Andreas Gampe183a5d32018-03-12 14:53:34 -0700172
Chris Wailesaa1c9622019-01-10 16:55:32 -0800173 void ReopenOrDetach(fail_fn_t fail_fn) const;
Andreas Gampe183a5d32018-03-12 14:53:34 -0700174
175 const int fd;
176 const struct stat stat;
177 const std::string file_path;
178 const int open_flags;
179 const int fd_flags;
180 const int fs_flags;
181 const off_t offset;
182 const bool is_sock;
183
184 private:
Chih-Hung Hsieh0727be12018-12-20 13:43:46 -0800185 explicit FileDescriptorInfo(int fd);
Andreas Gampe183a5d32018-03-12 14:53:34 -0700186
187 FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
188 int fd_flags, int fs_flags, off_t offset);
189
190 // Returns the locally-bound name of the socket |fd|. Returns true
191 // iff. all of the following hold :
192 //
193 // - the socket's sa_family is AF_UNIX.
194 // - the length of the path is greater than zero (i.e, not an unnamed socket).
195 // - the first byte of the path isn't zero (i.e, not a socket with an abstract
196 // address).
197 static bool GetSocketName(const int fd, std::string* result);
198
Chris Wailesaa1c9622019-01-10 16:55:32 -0800199 void DetachSocket(fail_fn_t fail_fn) const;
Andreas Gampe183a5d32018-03-12 14:53:34 -0700200
201 DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
202};
203
Robert Sesek54e387d2016-12-02 17:27:50 -0500204// static
Chris Wailesaa1c9622019-01-10 16:55:32 -0800205FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, fail_fn_t fail_fn) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500206 struct stat f_stat;
207 // This should never happen; the zygote should always have the right set
208 // of permissions required to stat all its open files.
209 if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800210 fail_fn(android::base::StringPrintf("Unable to stat %d", fd));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500211 }
212
Robert Sesek54e387d2016-12-02 17:27:50 -0500213 const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get();
214
Robert Sesek8225b7c2016-12-16 14:02:31 -0500215 if (S_ISSOCK(f_stat.st_mode)) {
216 std::string socket_name;
217 if (!GetSocketName(fd, &socket_name)) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800218 fail_fn("Unable to get socket name");
Robert Sesek8225b7c2016-12-16 14:02:31 -0500219 }
220
Robert Sesek54e387d2016-12-02 17:27:50 -0500221 if (!whitelist->IsAllowed(socket_name)) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800222 fail_fn(android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)",
223 socket_name.c_str(),
224 fd));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500225 }
226
227 return new FileDescriptorInfo(fd);
228 }
229
230 // We only handle whitelisted regular files and character devices. Whitelisted
231 // character devices must provide a guarantee of sensible behaviour when
232 // reopened.
233 //
234 // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
235 // S_ISLINK : Not supported.
236 // S_ISBLK : Not supported.
Chris Wailes7e797b62019-02-22 18:29:22 -0800237 // S_ISFIFO : Not supported. Note that the Zygote and USAPs use pipes to
Chris Wailesaa1c9622019-01-10 16:55:32 -0800238 // communicate with the child processes across forks but those should have been
239 // added to the redirection exemption list.
Robert Sesek8225b7c2016-12-16 14:02:31 -0500240 if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800241 std::string mode = "Unknown";
242
243 if (S_ISDIR(f_stat.st_mode)) {
244 mode = "DIR";
245 } else if (S_ISLNK(f_stat.st_mode)) {
246 mode = "LINK";
247 } else if (S_ISBLK(f_stat.st_mode)) {
248 mode = "BLOCK";
249 } else if (S_ISFIFO(f_stat.st_mode)) {
250 mode = "FIFO";
251 }
252
253 fail_fn(android::base::StringPrintf("Unsupported st_mode for FD %d: %s", fd, mode.c_str()));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500254 }
255
256 std::string file_path;
Narayan Kamath3879ecc2017-03-02 17:30:03 +0000257 const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
258 if (!android::base::Readlink(fd_path, &file_path)) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800259 fail_fn(android::base::StringPrintf("Could not read fd link %s: %s",
260 fd_path.c_str(),
261 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500262 }
263
Robert Sesek54e387d2016-12-02 17:27:50 -0500264 if (!whitelist->IsAllowed(file_path)) {
Nicolas Geoffray983f8a52019-06-11 17:47:16 +0100265 fail_fn(android::base::StringPrintf("Not whitelisted (%d): %s", fd, file_path.c_str()));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500266 }
267
268 // File descriptor flags : currently on FD_CLOEXEC. We can set these
269 // using F_SETFD - we're single threaded at this point of execution so
270 // there won't be any races.
271 const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
272 if (fd_flags == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800273 fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s",
274 fd,
275 file_path.c_str(),
276 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500277 }
278
279 // File status flags :
280 // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
281 // to the open() call.
282 //
283 // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
284 // do about these, since the file has already been created. We shall ignore
285 // them here.
286 //
287 // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
288 // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
289 // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
290 // their presence and pass them in to open().
291 int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
292 if (fs_flags == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800293 fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s",
294 fd,
295 file_path.c_str(),
296 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500297 }
298
299 // File offset : Ignore the offset for non seekable files.
300 const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
301
302 // We pass the flags that open accepts to open, and use F_SETFL for
303 // the rest of them.
304 static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
305 int open_flags = fs_flags & (kOpenFlags);
306 fs_flags = fs_flags & (~(kOpenFlags));
307
308 return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
309}
310
Chris Wailesaa1c9622019-01-10 16:55:32 -0800311bool FileDescriptorInfo::RefersToSameFile() const {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500312 struct stat f_stat;
313 if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
Narayan Kamatha352d242017-03-02 14:44:45 +0000314 PLOG(ERROR) << "Unable to restat fd " << fd;
Robert Sesek8225b7c2016-12-16 14:02:31 -0500315 return false;
316 }
317
318 return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
319}
320
Chris Wailesaa1c9622019-01-10 16:55:32 -0800321void FileDescriptorInfo::ReopenOrDetach(fail_fn_t fail_fn) const {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500322 if (is_sock) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800323 return DetachSocket(fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500324 }
325
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +0000326 // Children can directly use the in-memory file created by ART through memfd_create.
327 if (IsArtMemfd(file_path)) {
Nicolas Geoffray813b9e82019-10-24 15:33:01 +0100328 return;
329 }
330
Robert Sesek8225b7c2016-12-16 14:02:31 -0500331 // NOTE: This might happen if the file was unlinked after being opened.
332 // It's a common pattern in the case of temporary files and the like but
333 // we should not allow such usage from the zygote.
334 const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
335
336 if (new_fd == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800337 fail_fn(android::base::StringPrintf("Failed open(%s, %i): %s",
338 file_path.c_str(),
339 open_flags,
340 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500341 }
342
343 if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
344 close(new_fd);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800345 fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s",
346 new_fd,
347 fd_flags,
348 file_path.c_str(),
349 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500350 }
351
352 if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
353 close(new_fd);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800354 fail_fn(android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s",
355 new_fd,
356 fs_flags,
357 file_path.c_str(),
358 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500359 }
360
361 if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
362 close(new_fd);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800363 fail_fn(android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s",
364 new_fd,
365 file_path.c_str(),
366 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500367 }
368
Chris Wailesaa1c9622019-01-10 16:55:32 -0800369 int dup_flags = (fd_flags & FD_CLOEXEC) ? O_CLOEXEC : 0;
370 if (TEMP_FAILURE_RETRY(dup3(new_fd, fd, dup_flags)) == -1) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500371 close(new_fd);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800372 fail_fn(android::base::StringPrintf("Failed dup3(%d, %d, %d) (%s): %s",
373 fd,
374 new_fd,
375 dup_flags,
376 file_path.c_str(),
377 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500378 }
379
380 close(new_fd);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500381}
382
383FileDescriptorInfo::FileDescriptorInfo(int fd) :
384 fd(fd),
385 stat(),
386 open_flags(0),
387 fd_flags(0),
388 fs_flags(0),
389 offset(0),
390 is_sock(true) {
391}
392
393FileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file_path,
394 int fd, int open_flags, int fd_flags, int fs_flags,
395 off_t offset) :
396 fd(fd),
397 stat(stat),
398 file_path(file_path),
399 open_flags(open_flags),
400 fd_flags(fd_flags),
401 fs_flags(fs_flags),
402 offset(offset),
403 is_sock(false) {
404}
405
Robert Sesek8225b7c2016-12-16 14:02:31 -0500406bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
407 sockaddr_storage ss;
408 sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
409 socklen_t addr_len = sizeof(ss);
410
411 if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
Narayan Kamath84b55112017-03-02 17:04:08 +0000412 PLOG(ERROR) << "Failed getsockname(" << fd << ")";
Robert Sesek8225b7c2016-12-16 14:02:31 -0500413 return false;
414 }
415
416 if (addr->sa_family != AF_UNIX) {
Narayan Kamath84b55112017-03-02 17:04:08 +0000417 LOG(ERROR) << "Unsupported socket (fd=" << fd << ") with family " << addr->sa_family;
Robert Sesek8225b7c2016-12-16 14:02:31 -0500418 return false;
419 }
420
421 const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
422
423 size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
424 // This is an unnamed local socket, we do not accept it.
425 if (path_len == 0) {
Narayan Kamath84b55112017-03-02 17:04:08 +0000426 LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with empty path.";
Robert Sesek8225b7c2016-12-16 14:02:31 -0500427 return false;
428 }
429
Robert Sesekd0a190df2018-02-12 18:46:01 -0500430 // This is a local socket with an abstract address. Remove the leading NUL byte and
431 // add a human-readable "ABSTRACT/" prefix.
Robert Sesek8225b7c2016-12-16 14:02:31 -0500432 if (unix_addr->sun_path[0] == '\0') {
Robert Sesekd0a190df2018-02-12 18:46:01 -0500433 *result = "ABSTRACT/";
434 result->append(&unix_addr->sun_path[1], path_len - 1);
435 return true;
Robert Sesek8225b7c2016-12-16 14:02:31 -0500436 }
437
438 // If we're here, sun_path must refer to a null terminated filesystem
439 // pathname (man 7 unix). Remove the terminator before assigning it to an
440 // std::string.
441 if (unix_addr->sun_path[path_len - 1] == '\0') {
442 --path_len;
443 }
444
445 result->assign(unix_addr->sun_path, path_len);
446 return true;
447}
448
Chris Wailesaa1c9622019-01-10 16:55:32 -0800449void FileDescriptorInfo::DetachSocket(fail_fn_t fail_fn) const {
Nick Kralevich0361ce12019-01-25 10:08:58 -0800450 const int dev_null_fd = open("/dev/null", O_RDWR | O_CLOEXEC);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500451 if (dev_null_fd < 0) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800452 fail_fn(std::string("Failed to open /dev/null: ").append(strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500453 }
454
Nick Kralevich0361ce12019-01-25 10:08:58 -0800455 if (dup3(dev_null_fd, fd, O_CLOEXEC) == -1) {
456 fail_fn(android::base::StringPrintf("Failed dup3 on socket descriptor %d: %s",
Chris Wailesaa1c9622019-01-10 16:55:32 -0800457 fd,
458 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500459 }
460
461 if (close(dev_null_fd) == -1) {
Chris Wailesaa1c9622019-01-10 16:55:32 -0800462 fail_fn(android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500463 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500464}
465
466// static
Andreas Gampe183a5d32018-03-12 14:53:34 -0700467FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore,
Chris Wailesaa1c9622019-01-10 16:55:32 -0800468 fail_fn_t fail_fn) {
469 DIR* proc_fd_dir = opendir(kFdPath);
470 if (proc_fd_dir == nullptr) {
471 fail_fn(std::string("Unable to open directory ").append(kFdPath));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500472 }
Chris Wailesaa1c9622019-01-10 16:55:32 -0800473
474 int dir_fd = dirfd(proc_fd_dir);
475 dirent* dir_entry;
Robert Sesek8225b7c2016-12-16 14:02:31 -0500476
477 std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
Chris Wailesaa1c9622019-01-10 16:55:32 -0800478 while ((dir_entry = readdir(proc_fd_dir)) != nullptr) {
479 const int fd = ParseFd(dir_entry, dir_fd);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500480 if (fd == -1) {
481 continue;
482 }
Chris Wailesaa1c9622019-01-10 16:55:32 -0800483
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800484 if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800485 continue;
486 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500487
Chris Wailesaa1c9622019-01-10 16:55:32 -0800488 open_fd_map[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500489 }
490
Chris Wailesaa1c9622019-01-10 16:55:32 -0800491 if (closedir(proc_fd_dir) == -1) {
492 fail_fn("Unable to close directory");
Robert Sesek8225b7c2016-12-16 14:02:31 -0500493 }
Chris Wailesaa1c9622019-01-10 16:55:32 -0800494
Robert Sesek8225b7c2016-12-16 14:02:31 -0500495 return new FileDescriptorTable(open_fd_map);
496}
497
Chris Wailesaa1c9622019-01-10 16:55:32 -0800498void FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, fail_fn_t fail_fn) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500499 std::set<int> open_fds;
500
501 // First get the list of open descriptors.
Chris Wailesaa1c9622019-01-10 16:55:32 -0800502 DIR* proc_fd_dir = opendir(kFdPath);
503 if (proc_fd_dir == nullptr) {
504 fail_fn(android::base::StringPrintf("Unable to open directory %s: %s",
505 kFdPath,
506 strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500507 }
508
Chris Wailesaa1c9622019-01-10 16:55:32 -0800509 int dir_fd = dirfd(proc_fd_dir);
510 dirent* dir_entry;
511 while ((dir_entry = readdir(proc_fd_dir)) != nullptr) {
512 const int fd = ParseFd(dir_entry, dir_fd);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500513 if (fd == -1) {
514 continue;
515 }
Chris Wailesaa1c9622019-01-10 16:55:32 -0800516
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800517 if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
Andreas Gampe8dfa1782017-01-05 12:45:58 -0800518 continue;
519 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500520
521 open_fds.insert(fd);
522 }
523
Chris Wailesaa1c9622019-01-10 16:55:32 -0800524 if (closedir(proc_fd_dir) == -1) {
525 fail_fn(android::base::StringPrintf("Unable to close directory: %s", strerror(errno)));
Robert Sesek8225b7c2016-12-16 14:02:31 -0500526 }
527
Chris Wailesaa1c9622019-01-10 16:55:32 -0800528 RestatInternal(open_fds, fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500529}
530
Chris Wailesaa1c9622019-01-10 16:55:32 -0800531// Reopens all file descriptors that are contained in the table.
532void FileDescriptorTable::ReopenOrDetach(fail_fn_t fail_fn) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500533 std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
534 for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
535 const FileDescriptorInfo* info = it->second;
Chris Wailesaa1c9622019-01-10 16:55:32 -0800536 if (info == nullptr) {
537 return;
538 } else {
539 info->ReopenOrDetach(fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500540 }
541 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500542}
543
544FileDescriptorTable::FileDescriptorTable(
545 const std::unordered_map<int, FileDescriptorInfo*>& map)
546 : open_fd_map_(map) {
547}
548
Chris Wailesaa1c9622019-01-10 16:55:32 -0800549void FileDescriptorTable::RestatInternal(std::set<int>& open_fds, fail_fn_t fail_fn) {
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +0000550 // ART creates a file through memfd for optimization purposes. We make sure
551 // there is at most one being created.
552 bool art_memfd_seen = false;
553
Robert Sesek8225b7c2016-12-16 14:02:31 -0500554 // Iterate through the list of file descriptors we've already recorded
555 // and check whether :
556 //
557 // (a) they continue to be open.
558 // (b) they refer to the same file.
Andreas Gampe183a5d32018-03-12 14:53:34 -0700559 //
560 // We'll only store the last error message.
Robert Sesek8225b7c2016-12-16 14:02:31 -0500561 std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
562 while (it != open_fd_map_.end()) {
563 std::set<int>::const_iterator element = open_fds.find(it->first);
564 if (element == open_fds.end()) {
565 // The entry from the file descriptor table is no longer in the list
566 // of open files. We warn about this condition and remove it from
567 // the list of FDs under consideration.
568 //
569 // TODO(narayan): This will be an error in a future android release.
570 // error = true;
571 // ALOGW("Zygote closed file descriptor %d.", it->first);
572 it = open_fd_map_.erase(it);
573 } else {
574 // The entry from the file descriptor table is still open. Restat
575 // it and check whether it refers to the same file.
Chris Wailesaa1c9622019-01-10 16:55:32 -0800576 if (!it->second->RefersToSameFile()) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500577 // The file descriptor refers to a different description. We must
578 // update our entry in the table.
579 delete it->second;
Chris Wailesaa1c9622019-01-10 16:55:32 -0800580 it->second = FileDescriptorInfo::CreateFromFd(*element, fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500581 } else {
582 // It's the same file. Nothing to do here. Move on to the next open
583 // FD.
Robert Sesek8225b7c2016-12-16 14:02:31 -0500584 }
585
Nicolas Geoffrayabbd4a72019-10-29 15:45:46 +0000586 if (IsArtMemfd(it->second->file_path)) {
587 if (art_memfd_seen) {
588 fail_fn("ART fd already seen: " + it->second->file_path);
589 } else {
590 art_memfd_seen = true;
591 }
592 }
593
Chris Wailesaa1c9622019-01-10 16:55:32 -0800594 ++it;
595
Robert Sesek8225b7c2016-12-16 14:02:31 -0500596 // Finally, remove the FD from the set of open_fds. We do this last because
597 // |element| will not remain valid after a call to erase.
598 open_fds.erase(element);
599 }
600 }
601
602 if (open_fds.size() > 0) {
603 // The zygote has opened new file descriptors since our last inspection.
604 // We warn about this condition and add them to our table.
605 //
606 // TODO(narayan): This will be an error in a future android release.
607 // error = true;
608 // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
609
610 // TODO(narayan): This code will be removed in a future android release.
611 std::set<int>::const_iterator it;
612 for (it = open_fds.begin(); it != open_fds.end(); ++it) {
613 const int fd = (*it);
Chris Wailesaa1c9622019-01-10 16:55:32 -0800614 open_fd_map_[fd] = FileDescriptorInfo::CreateFromFd(fd, fail_fn);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500615 }
616 }
Robert Sesek8225b7c2016-12-16 14:02:31 -0500617}
618
619// static
Chris Wailesaa1c9622019-01-10 16:55:32 -0800620int FileDescriptorTable::ParseFd(dirent* dir_entry, int dir_fd) {
Robert Sesek8225b7c2016-12-16 14:02:31 -0500621 char* end;
Chris Wailesaa1c9622019-01-10 16:55:32 -0800622 const int fd = strtol(dir_entry->d_name, &end, 10);
Robert Sesek8225b7c2016-12-16 14:02:31 -0500623 if ((*end) != '\0') {
624 return -1;
625 }
626
627 // Don't bother with the standard input/output/error, they're handled
628 // specially post-fork anyway.
629 if (fd <= STDERR_FILENO || fd == dir_fd) {
630 return -1;
631 }
632
633 return fd;
634}