fd_utils.cpp revision 54e387ddbe6a0462bc8e9e15c7c7b3463adfcb24
18225b7c95185dfbfe67da105df4402430784393cRobert Sesek/* 28225b7c95185dfbfe67da105df4402430784393cRobert Sesek * Copyright (C) 2016 The Android Open Source Project 38225b7c95185dfbfe67da105df4402430784393cRobert Sesek * 48225b7c95185dfbfe67da105df4402430784393cRobert Sesek * Licensed under the Apache License, Version 2.0 (the "License"); 58225b7c95185dfbfe67da105df4402430784393cRobert Sesek * you may not use this file except in compliance with the License. 68225b7c95185dfbfe67da105df4402430784393cRobert Sesek * You may obtain a copy of the License at 78225b7c95185dfbfe67da105df4402430784393cRobert Sesek * 88225b7c95185dfbfe67da105df4402430784393cRobert Sesek * http://www.apache.org/licenses/LICENSE-2.0 98225b7c95185dfbfe67da105df4402430784393cRobert Sesek * 108225b7c95185dfbfe67da105df4402430784393cRobert Sesek * Unless required by applicable law or agreed to in writing, software 118225b7c95185dfbfe67da105df4402430784393cRobert Sesek * distributed under the License is distributed on an "AS IS" BASIS, 128225b7c95185dfbfe67da105df4402430784393cRobert Sesek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138225b7c95185dfbfe67da105df4402430784393cRobert Sesek * See the License for the specific language governing permissions and 148225b7c95185dfbfe67da105df4402430784393cRobert Sesek * limitations under the License. 158225b7c95185dfbfe67da105df4402430784393cRobert Sesek */ 168225b7c95185dfbfe67da105df4402430784393cRobert Sesek 178225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include "fd_utils.h" 188225b7c95185dfbfe67da105df4402430784393cRobert Sesek 198225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <algorithm> 208225b7c95185dfbfe67da105df4402430784393cRobert Sesek 218225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <fcntl.h> 228225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <grp.h> 238225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <stdlib.h> 248225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <sys/socket.h> 258225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <sys/types.h> 268225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <sys/un.h> 278225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <unistd.h> 288225b7c95185dfbfe67da105df4402430784393cRobert Sesek 298225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <android-base/strings.h> 308225b7c95185dfbfe67da105df4402430784393cRobert Sesek#include <cutils/log.h> 318225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek// Static whitelist of open paths that the zygote is allowed to keep open. 338225b7c95185dfbfe67da105df4402430784393cRobert Sesekstatic const char* kPathWhitelist[] = { 348225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/dev/null", 358225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/dev/socket/zygote", 368225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/dev/socket/zygote_secondary", 378225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/dev/socket/webview_zygote", 388225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/sys/kernel/debug/tracing/trace_marker", 398225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/system/framework/framework-res.apk", 408225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/dev/urandom", 418225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/dev/ion", 428225b7c95185dfbfe67da105df4402430784393cRobert Sesek "/dev/dri/renderD129", // Fixes b/31172436 438225b7c95185dfbfe67da105df4402430784393cRobert Sesek}; 448225b7c95185dfbfe67da105df4402430784393cRobert Sesek 458225b7c95185dfbfe67da105df4402430784393cRobert Sesekstatic const char kFdPath[] = "/proc/self/fd"; 468225b7c95185dfbfe67da105df4402430784393cRobert Sesek 478225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static 4854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert SesekFileDescriptorWhitelist* FileDescriptorWhitelist::Get() { 4954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (instance_ == nullptr) { 5054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek instance_ = new FileDescriptorWhitelist(); 5154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek } 5254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return instance_; 5354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek} 5454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 5554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesekbool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { 5654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // Check the static whitelist path. 5754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek for (const auto& whitelist_path : kPathWhitelist) { 5854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (path == whitelist_path) 5954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return true; 6054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek } 6154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 6254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // Check any paths added to the dynamic whitelist. 6354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek for (const auto& whitelist_path : whitelist_) { 6454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (path == whitelist_path) 6554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return true; 6654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek } 6754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 6854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kFrameworksPrefix = "/system/framework/"; 6954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kJarSuffix = ".jar"; 7054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) { 7154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return true; 7254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek } 7354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 7454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // Whitelist files needed for Runtime Resource Overlay, like these: 7554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // /system/vendor/overlay/framework-res.apk 7654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // /system/vendor/overlay-subdir/pg/framework-res.apk 7754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // /vendor/overlay/framework-res.apk 7854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk 7954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap 8054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap 8154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // See AssetManager.cpp for more details on overlay-subdir. 8254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kOverlayDir = "/system/vendor/overlay/"; 8354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kVendorOverlayDir = "/vendor/overlay"; 8454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/"; 8554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kApkSuffix = ".apk"; 8654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 8754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir) 8854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek || StartsWith(path, kVendorOverlayDir)) 8954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek && EndsWith(path, kApkSuffix) 9054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek && path.find("/../") == std::string::npos) { 9154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return true; 9254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek } 9354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 9454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kOverlayIdmapPrefix = "/data/resource-cache/"; 9554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kOverlayIdmapSuffix = ".apk@idmap"; 9654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix) 9754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek && path.find("/../") == std::string::npos) { 9854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return true; 9954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek } 10054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 10154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek // All regular files that are placed under this path are whitelisted automatically. 10254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/"; 10354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) { 10454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return true; 10554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek } 10654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 10754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return false; 10854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek} 10954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 11054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert SesekFileDescriptorWhitelist::FileDescriptorWhitelist() 11154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek : whitelist_() { 11254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek} 11354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 11454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek// TODO: Call android::base::StartsWith instead of copying the code here. 11554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek// static 11654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesekbool FileDescriptorWhitelist::StartsWith(const std::string& str, 11754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek const std::string& prefix) { 11854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return str.compare(0, prefix.size(), prefix) == 0; 11954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek} 12054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 12154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek// TODO: Call android::base::EndsWith instead of copying the code here. 12254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek// static 12354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesekbool FileDescriptorWhitelist::EndsWith(const std::string& str, 12454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek const std::string& suffix) { 12554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (suffix.size() > str.size()) { 12654e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return false; 12754e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek } 12854e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 12954e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; 13054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek} 13154e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 13254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert SesekFileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr; 13354e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 13454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek// static 1358225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { 1368225b7c95185dfbfe67da105df4402430784393cRobert Sesek struct stat f_stat; 1378225b7c95185dfbfe67da105df4402430784393cRobert Sesek // This should never happen; the zygote should always have the right set 1388225b7c95185dfbfe67da105df4402430784393cRobert Sesek // of permissions required to stat all its open files. 1398225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { 1408225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unable to stat fd %d : %s", fd, strerror(errno)); 1418225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 1428225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 1438225b7c95185dfbfe67da105df4402430784393cRobert Sesek 14454e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get(); 14554e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek 1468225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (S_ISSOCK(f_stat.st_mode)) { 1478225b7c95185dfbfe67da105df4402430784393cRobert Sesek std::string socket_name; 1488225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (!GetSocketName(fd, &socket_name)) { 1498225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 1508225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 1518225b7c95185dfbfe67da105df4402430784393cRobert Sesek 15254e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (!whitelist->IsAllowed(socket_name)) { 1538225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd); 1548225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 1558225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 1568225b7c95185dfbfe67da105df4402430784393cRobert Sesek 1578225b7c95185dfbfe67da105df4402430784393cRobert Sesek return new FileDescriptorInfo(fd); 1588225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 1598225b7c95185dfbfe67da105df4402430784393cRobert Sesek 1608225b7c95185dfbfe67da105df4402430784393cRobert Sesek // We only handle whitelisted regular files and character devices. Whitelisted 1618225b7c95185dfbfe67da105df4402430784393cRobert Sesek // character devices must provide a guarantee of sensible behaviour when 1628225b7c95185dfbfe67da105df4402430784393cRobert Sesek // reopened. 1638225b7c95185dfbfe67da105df4402430784393cRobert Sesek // 1648225b7c95185dfbfe67da105df4402430784393cRobert Sesek // S_ISDIR : Not supported. (We could if we wanted to, but it's unused). 1658225b7c95185dfbfe67da105df4402430784393cRobert Sesek // S_ISLINK : Not supported. 1668225b7c95185dfbfe67da105df4402430784393cRobert Sesek // S_ISBLK : Not supported. 1678225b7c95185dfbfe67da105df4402430784393cRobert Sesek // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate 1688225b7c95185dfbfe67da105df4402430784393cRobert Sesek // with the child process across forks but those should have been closed 1698225b7c95185dfbfe67da105df4402430784393cRobert Sesek // before we got to this point. 1708225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) { 1718225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unsupported st_mode %d", f_stat.st_mode); 1728225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 1738225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 1748225b7c95185dfbfe67da105df4402430784393cRobert Sesek 1758225b7c95185dfbfe67da105df4402430784393cRobert Sesek std::string file_path; 1768225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (!Readlink(fd, &file_path)) { 1778225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 1788225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 1798225b7c95185dfbfe67da105df4402430784393cRobert Sesek 18054e387ddbe6a0462bc8e9e15c7c7b3463adfcb24Robert Sesek if (!whitelist->IsAllowed(file_path)) { 1818225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Not whitelisted : %s", file_path.c_str()); 1828225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 1838225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 1848225b7c95185dfbfe67da105df4402430784393cRobert Sesek 1858225b7c95185dfbfe67da105df4402430784393cRobert Sesek // File descriptor flags : currently on FD_CLOEXEC. We can set these 1868225b7c95185dfbfe67da105df4402430784393cRobert Sesek // using F_SETFD - we're single threaded at this point of execution so 1878225b7c95185dfbfe67da105df4402430784393cRobert Sesek // there won't be any races. 1888225b7c95185dfbfe67da105df4402430784393cRobert Sesek const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)); 1898225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (fd_flags == -1) { 1908225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno)); 1918225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 1928225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 1938225b7c95185dfbfe67da105df4402430784393cRobert Sesek 1948225b7c95185dfbfe67da105df4402430784393cRobert Sesek // File status flags : 1958225b7c95185dfbfe67da105df4402430784393cRobert Sesek // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through 1968225b7c95185dfbfe67da105df4402430784393cRobert Sesek // to the open() call. 1978225b7c95185dfbfe67da105df4402430784393cRobert Sesek // 1988225b7c95185dfbfe67da105df4402430784393cRobert Sesek // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can 1998225b7c95185dfbfe67da105df4402430784393cRobert Sesek // do about these, since the file has already been created. We shall ignore 2008225b7c95185dfbfe67da105df4402430784393cRobert Sesek // them here. 2018225b7c95185dfbfe67da105df4402430784393cRobert Sesek // 2028225b7c95185dfbfe67da105df4402430784393cRobert Sesek // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL 2038225b7c95185dfbfe67da105df4402430784393cRobert Sesek // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK. 2048225b7c95185dfbfe67da105df4402430784393cRobert Sesek // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for 2058225b7c95185dfbfe67da105df4402430784393cRobert Sesek // their presence and pass them in to open(). 2068225b7c95185dfbfe67da105df4402430784393cRobert Sesek int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); 2078225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (fs_flags == -1) { 2088225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno)); 2098225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 2108225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 2118225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2128225b7c95185dfbfe67da105df4402430784393cRobert Sesek // File offset : Ignore the offset for non seekable files. 2138225b7c95185dfbfe67da105df4402430784393cRobert Sesek const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR)); 2148225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2158225b7c95185dfbfe67da105df4402430784393cRobert Sesek // We pass the flags that open accepts to open, and use F_SETFL for 2168225b7c95185dfbfe67da105df4402430784393cRobert Sesek // the rest of them. 2178225b7c95185dfbfe67da105df4402430784393cRobert Sesek static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC); 2188225b7c95185dfbfe67da105df4402430784393cRobert Sesek int open_flags = fs_flags & (kOpenFlags); 2198225b7c95185dfbfe67da105df4402430784393cRobert Sesek fs_flags = fs_flags & (~(kOpenFlags)); 2208225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2218225b7c95185dfbfe67da105df4402430784393cRobert Sesek return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset); 2228225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 2238225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2248225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::Restat() const { 2258225b7c95185dfbfe67da105df4402430784393cRobert Sesek struct stat f_stat; 2268225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { 2278225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 2288225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 2298225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2308225b7c95185dfbfe67da105df4402430784393cRobert Sesek return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev; 2318225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 2328225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2338225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::ReopenOrDetach() const { 2348225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (is_sock) { 2358225b7c95185dfbfe67da105df4402430784393cRobert Sesek return DetachSocket(); 2368225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 2378225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2388225b7c95185dfbfe67da105df4402430784393cRobert Sesek // NOTE: This might happen if the file was unlinked after being opened. 2398225b7c95185dfbfe67da105df4402430784393cRobert Sesek // It's a common pattern in the case of temporary files and the like but 2408225b7c95185dfbfe67da105df4402430784393cRobert Sesek // we should not allow such usage from the zygote. 2418225b7c95185dfbfe67da105df4402430784393cRobert Sesek const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags)); 2428225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2438225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (new_fd == -1) { 2448225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno)); 2458225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 2468225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 2478225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2488225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) { 2498225b7c95185dfbfe67da105df4402430784393cRobert Sesek close(new_fd); 2508225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno)); 2518225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 2528225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 2538225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2548225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) { 2558225b7c95185dfbfe67da105df4402430784393cRobert Sesek close(new_fd); 2568225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno)); 2578225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 2588225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 2598225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2608225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) { 2618225b7c95185dfbfe67da105df4402430784393cRobert Sesek close(new_fd); 2628225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno)); 2638225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 2648225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 2658225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2668225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) { 2678225b7c95185dfbfe67da105df4402430784393cRobert Sesek close(new_fd); 2688225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno)); 2698225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 2708225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 2718225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2728225b7c95185dfbfe67da105df4402430784393cRobert Sesek close(new_fd); 2738225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2748225b7c95185dfbfe67da105df4402430784393cRobert Sesek return true; 2758225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 2768225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2778225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorInfo::FileDescriptorInfo(int fd) : 2788225b7c95185dfbfe67da105df4402430784393cRobert Sesek fd(fd), 2798225b7c95185dfbfe67da105df4402430784393cRobert Sesek stat(), 2808225b7c95185dfbfe67da105df4402430784393cRobert Sesek open_flags(0), 2818225b7c95185dfbfe67da105df4402430784393cRobert Sesek fd_flags(0), 2828225b7c95185dfbfe67da105df4402430784393cRobert Sesek fs_flags(0), 2838225b7c95185dfbfe67da105df4402430784393cRobert Sesek offset(0), 2848225b7c95185dfbfe67da105df4402430784393cRobert Sesek is_sock(true) { 2858225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 2868225b7c95185dfbfe67da105df4402430784393cRobert Sesek 2878225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file_path, 2888225b7c95185dfbfe67da105df4402430784393cRobert Sesek int fd, int open_flags, int fd_flags, int fs_flags, 2898225b7c95185dfbfe67da105df4402430784393cRobert Sesek off_t offset) : 2908225b7c95185dfbfe67da105df4402430784393cRobert Sesek fd(fd), 2918225b7c95185dfbfe67da105df4402430784393cRobert Sesek stat(stat), 2928225b7c95185dfbfe67da105df4402430784393cRobert Sesek file_path(file_path), 2938225b7c95185dfbfe67da105df4402430784393cRobert Sesek open_flags(open_flags), 2948225b7c95185dfbfe67da105df4402430784393cRobert Sesek fd_flags(fd_flags), 2958225b7c95185dfbfe67da105df4402430784393cRobert Sesek fs_flags(fs_flags), 2968225b7c95185dfbfe67da105df4402430784393cRobert Sesek offset(offset), 2978225b7c95185dfbfe67da105df4402430784393cRobert Sesek is_sock(false) { 2988225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 2998225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3008225b7c95185dfbfe67da105df4402430784393cRobert Sesek// TODO: Call android::base::Readlink instead of copying the code here. 3018225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static 3028225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::Readlink(const int fd, std::string* result) { 3038225b7c95185dfbfe67da105df4402430784393cRobert Sesek char path[64]; 3048225b7c95185dfbfe67da105df4402430784393cRobert Sesek snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); 3058225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3068225b7c95185dfbfe67da105df4402430784393cRobert Sesek // Code copied from android::base::Readlink starts here : 3078225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3088225b7c95185dfbfe67da105df4402430784393cRobert Sesek // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer, 3098225b7c95185dfbfe67da105df4402430784393cRobert Sesek // and truncates to whatever size you do supply, so it can't be used to query. 3108225b7c95185dfbfe67da105df4402430784393cRobert Sesek // We could call lstat first, but that would introduce a race condition that 3118225b7c95185dfbfe67da105df4402430784393cRobert Sesek // we couldn't detect. 3128225b7c95185dfbfe67da105df4402430784393cRobert Sesek // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here. 3138225b7c95185dfbfe67da105df4402430784393cRobert Sesek char buf[4096]; 3148225b7c95185dfbfe67da105df4402430784393cRobert Sesek ssize_t len = readlink(path, buf, sizeof(buf)); 3158225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (len == -1) return false; 3168225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3178225b7c95185dfbfe67da105df4402430784393cRobert Sesek result->assign(buf, len); 3188225b7c95185dfbfe67da105df4402430784393cRobert Sesek return true; 3198225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 3208225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3218225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static 3228225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) { 3238225b7c95185dfbfe67da105df4402430784393cRobert Sesek sockaddr_storage ss; 3248225b7c95185dfbfe67da105df4402430784393cRobert Sesek sockaddr* addr = reinterpret_cast<sockaddr*>(&ss); 3258225b7c95185dfbfe67da105df4402430784393cRobert Sesek socklen_t addr_len = sizeof(ss); 3268225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3278225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) { 3288225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno)); 3298225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 3308225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3318225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3328225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (addr->sa_family != AF_UNIX) { 3338225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family); 3348225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 3358225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3368225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3378225b7c95185dfbfe67da105df4402430784393cRobert Sesek const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss); 3388225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3398225b7c95185dfbfe67da105df4402430784393cRobert Sesek size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path); 3408225b7c95185dfbfe67da105df4402430784393cRobert Sesek // This is an unnamed local socket, we do not accept it. 3418225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (path_len == 0) { 3428225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd); 3438225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 3448225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3458225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3468225b7c95185dfbfe67da105df4402430784393cRobert Sesek // This is a local socket with an abstract address, we do not accept it. 3478225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (unix_addr->sun_path[0] == '\0') { 3488225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd); 3498225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 3508225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3518225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3528225b7c95185dfbfe67da105df4402430784393cRobert Sesek // If we're here, sun_path must refer to a null terminated filesystem 3538225b7c95185dfbfe67da105df4402430784393cRobert Sesek // pathname (man 7 unix). Remove the terminator before assigning it to an 3548225b7c95185dfbfe67da105df4402430784393cRobert Sesek // std::string. 3558225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (unix_addr->sun_path[path_len - 1] == '\0') { 3568225b7c95185dfbfe67da105df4402430784393cRobert Sesek --path_len; 3578225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3588225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3598225b7c95185dfbfe67da105df4402430784393cRobert Sesek result->assign(unix_addr->sun_path, path_len); 3608225b7c95185dfbfe67da105df4402430784393cRobert Sesek return true; 3618225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 3628225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3638225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorInfo::DetachSocket() const { 3648225b7c95185dfbfe67da105df4402430784393cRobert Sesek const int dev_null_fd = open("/dev/null", O_RDWR); 3658225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (dev_null_fd < 0) { 3668225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed to open /dev/null : %s", strerror(errno)); 3678225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 3688225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3698225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3708225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (dup2(dev_null_fd, fd) == -1) { 3718225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno)); 3728225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 3738225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3748225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3758225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (close(dev_null_fd) == -1) { 3768225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno)); 3778225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 3788225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3798225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3808225b7c95185dfbfe67da105df4402430784393cRobert Sesek return true; 3818225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 3828225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3838225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static 3848225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorTable* FileDescriptorTable::Create() { 3858225b7c95185dfbfe67da105df4402430784393cRobert Sesek DIR* d = opendir(kFdPath); 3868225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (d == NULL) { 3878225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); 3888225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 3898225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3908225b7c95185dfbfe67da105df4402430784393cRobert Sesek int dir_fd = dirfd(d); 3918225b7c95185dfbfe67da105df4402430784393cRobert Sesek dirent* e; 3928225b7c95185dfbfe67da105df4402430784393cRobert Sesek 3938225b7c95185dfbfe67da105df4402430784393cRobert Sesek std::unordered_map<int, FileDescriptorInfo*> open_fd_map; 3948225b7c95185dfbfe67da105df4402430784393cRobert Sesek while ((e = readdir(d)) != NULL) { 3958225b7c95185dfbfe67da105df4402430784393cRobert Sesek const int fd = ParseFd(e, dir_fd); 3968225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (fd == -1) { 3978225b7c95185dfbfe67da105df4402430784393cRobert Sesek continue; 3988225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 3998225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4008225b7c95185dfbfe67da105df4402430784393cRobert Sesek FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd); 4018225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (info == NULL) { 4028225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (closedir(d) == -1) { 4038225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unable to close directory : %s", strerror(errno)); 4048225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4058225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 4068225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4078225b7c95185dfbfe67da105df4402430784393cRobert Sesek open_fd_map[fd] = info; 4088225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4098225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4108225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (closedir(d) == -1) { 4118225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unable to close directory : %s", strerror(errno)); 4128225b7c95185dfbfe67da105df4402430784393cRobert Sesek return NULL; 4138225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4148225b7c95185dfbfe67da105df4402430784393cRobert Sesek return new FileDescriptorTable(open_fd_map); 4158225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 4168225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4178225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorTable::Restat() { 4188225b7c95185dfbfe67da105df4402430784393cRobert Sesek std::set<int> open_fds; 4198225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4208225b7c95185dfbfe67da105df4402430784393cRobert Sesek // First get the list of open descriptors. 4218225b7c95185dfbfe67da105df4402430784393cRobert Sesek DIR* d = opendir(kFdPath); 4228225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (d == NULL) { 4238225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); 4248225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 4258225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4268225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4278225b7c95185dfbfe67da105df4402430784393cRobert Sesek int dir_fd = dirfd(d); 4288225b7c95185dfbfe67da105df4402430784393cRobert Sesek dirent* e; 4298225b7c95185dfbfe67da105df4402430784393cRobert Sesek while ((e = readdir(d)) != NULL) { 4308225b7c95185dfbfe67da105df4402430784393cRobert Sesek const int fd = ParseFd(e, dir_fd); 4318225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (fd == -1) { 4328225b7c95185dfbfe67da105df4402430784393cRobert Sesek continue; 4338225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4348225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4358225b7c95185dfbfe67da105df4402430784393cRobert Sesek open_fds.insert(fd); 4368225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4378225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4388225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (closedir(d) == -1) { 4398225b7c95185dfbfe67da105df4402430784393cRobert Sesek ALOGE("Unable to close directory : %s", strerror(errno)); 4408225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 4418225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4428225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4438225b7c95185dfbfe67da105df4402430784393cRobert Sesek return RestatInternal(open_fds); 4448225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 4458225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4468225b7c95185dfbfe67da105df4402430784393cRobert Sesek// Reopens all file descriptors that are contained in the table. Returns true 4478225b7c95185dfbfe67da105df4402430784393cRobert Sesek// if all descriptors were successfully re-opened or detached, and false if an 4488225b7c95185dfbfe67da105df4402430784393cRobert Sesek// error occurred. 4498225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorTable::ReopenOrDetach() { 4508225b7c95185dfbfe67da105df4402430784393cRobert Sesek std::unordered_map<int, FileDescriptorInfo*>::const_iterator it; 4518225b7c95185dfbfe67da105df4402430784393cRobert Sesek for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { 4528225b7c95185dfbfe67da105df4402430784393cRobert Sesek const FileDescriptorInfo* info = it->second; 4538225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (info == NULL || !info->ReopenOrDetach()) { 4548225b7c95185dfbfe67da105df4402430784393cRobert Sesek return false; 4558225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4568225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 4578225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4588225b7c95185dfbfe67da105df4402430784393cRobert Sesek return true; 4598225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 4608225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4618225b7c95185dfbfe67da105df4402430784393cRobert SesekFileDescriptorTable::FileDescriptorTable( 4628225b7c95185dfbfe67da105df4402430784393cRobert Sesek const std::unordered_map<int, FileDescriptorInfo*>& map) 4638225b7c95185dfbfe67da105df4402430784393cRobert Sesek : open_fd_map_(map) { 4648225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 4658225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4668225b7c95185dfbfe67da105df4402430784393cRobert Sesekbool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) { 4678225b7c95185dfbfe67da105df4402430784393cRobert Sesek bool error = false; 4688225b7c95185dfbfe67da105df4402430784393cRobert Sesek 4698225b7c95185dfbfe67da105df4402430784393cRobert Sesek // Iterate through the list of file descriptors we've already recorded 4708225b7c95185dfbfe67da105df4402430784393cRobert Sesek // and check whether : 4718225b7c95185dfbfe67da105df4402430784393cRobert Sesek // 4728225b7c95185dfbfe67da105df4402430784393cRobert Sesek // (a) they continue to be open. 4738225b7c95185dfbfe67da105df4402430784393cRobert Sesek // (b) they refer to the same file. 4748225b7c95185dfbfe67da105df4402430784393cRobert Sesek std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin(); 4758225b7c95185dfbfe67da105df4402430784393cRobert Sesek while (it != open_fd_map_.end()) { 4768225b7c95185dfbfe67da105df4402430784393cRobert Sesek std::set<int>::const_iterator element = open_fds.find(it->first); 4778225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (element == open_fds.end()) { 4788225b7c95185dfbfe67da105df4402430784393cRobert Sesek // The entry from the file descriptor table is no longer in the list 4798225b7c95185dfbfe67da105df4402430784393cRobert Sesek // of open files. We warn about this condition and remove it from 4808225b7c95185dfbfe67da105df4402430784393cRobert Sesek // the list of FDs under consideration. 4818225b7c95185dfbfe67da105df4402430784393cRobert Sesek // 4828225b7c95185dfbfe67da105df4402430784393cRobert Sesek // TODO(narayan): This will be an error in a future android release. 4838225b7c95185dfbfe67da105df4402430784393cRobert Sesek // error = true; 4848225b7c95185dfbfe67da105df4402430784393cRobert Sesek // ALOGW("Zygote closed file descriptor %d.", it->first); 4858225b7c95185dfbfe67da105df4402430784393cRobert Sesek it = open_fd_map_.erase(it); 4868225b7c95185dfbfe67da105df4402430784393cRobert Sesek } else { 4878225b7c95185dfbfe67da105df4402430784393cRobert Sesek // The entry from the file descriptor table is still open. Restat 4888225b7c95185dfbfe67da105df4402430784393cRobert Sesek // it and check whether it refers to the same file. 4898225b7c95185dfbfe67da105df4402430784393cRobert Sesek const bool same_file = it->second->Restat(); 4908225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (!same_file) { 4918225b7c95185dfbfe67da105df4402430784393cRobert Sesek // The file descriptor refers to a different description. We must 4928225b7c95185dfbfe67da105df4402430784393cRobert Sesek // update our entry in the table. 4938225b7c95185dfbfe67da105df4402430784393cRobert Sesek delete it->second; 4948225b7c95185dfbfe67da105df4402430784393cRobert Sesek it->second = FileDescriptorInfo::CreateFromFd(*element); 4958225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (it->second == NULL) { 4968225b7c95185dfbfe67da105df4402430784393cRobert Sesek // The descriptor no longer no longer refers to a whitelisted file. 4978225b7c95185dfbfe67da105df4402430784393cRobert Sesek // We flag an error and remove it from the list of files we're 4988225b7c95185dfbfe67da105df4402430784393cRobert Sesek // tracking. 4998225b7c95185dfbfe67da105df4402430784393cRobert Sesek error = true; 5008225b7c95185dfbfe67da105df4402430784393cRobert Sesek it = open_fd_map_.erase(it); 5018225b7c95185dfbfe67da105df4402430784393cRobert Sesek } else { 5028225b7c95185dfbfe67da105df4402430784393cRobert Sesek // Successfully restatted the file, move on to the next open FD. 5038225b7c95185dfbfe67da105df4402430784393cRobert Sesek ++it; 5048225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5058225b7c95185dfbfe67da105df4402430784393cRobert Sesek } else { 5068225b7c95185dfbfe67da105df4402430784393cRobert Sesek // It's the same file. Nothing to do here. Move on to the next open 5078225b7c95185dfbfe67da105df4402430784393cRobert Sesek // FD. 5088225b7c95185dfbfe67da105df4402430784393cRobert Sesek ++it; 5098225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5108225b7c95185dfbfe67da105df4402430784393cRobert Sesek 5118225b7c95185dfbfe67da105df4402430784393cRobert Sesek // Finally, remove the FD from the set of open_fds. We do this last because 5128225b7c95185dfbfe67da105df4402430784393cRobert Sesek // |element| will not remain valid after a call to erase. 5138225b7c95185dfbfe67da105df4402430784393cRobert Sesek open_fds.erase(element); 5148225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5158225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5168225b7c95185dfbfe67da105df4402430784393cRobert Sesek 5178225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (open_fds.size() > 0) { 5188225b7c95185dfbfe67da105df4402430784393cRobert Sesek // The zygote has opened new file descriptors since our last inspection. 5198225b7c95185dfbfe67da105df4402430784393cRobert Sesek // We warn about this condition and add them to our table. 5208225b7c95185dfbfe67da105df4402430784393cRobert Sesek // 5218225b7c95185dfbfe67da105df4402430784393cRobert Sesek // TODO(narayan): This will be an error in a future android release. 5228225b7c95185dfbfe67da105df4402430784393cRobert Sesek // error = true; 5238225b7c95185dfbfe67da105df4402430784393cRobert Sesek // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size()); 5248225b7c95185dfbfe67da105df4402430784393cRobert Sesek 5258225b7c95185dfbfe67da105df4402430784393cRobert Sesek // TODO(narayan): This code will be removed in a future android release. 5268225b7c95185dfbfe67da105df4402430784393cRobert Sesek std::set<int>::const_iterator it; 5278225b7c95185dfbfe67da105df4402430784393cRobert Sesek for (it = open_fds.begin(); it != open_fds.end(); ++it) { 5288225b7c95185dfbfe67da105df4402430784393cRobert Sesek const int fd = (*it); 5298225b7c95185dfbfe67da105df4402430784393cRobert Sesek FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd); 5308225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (info == NULL) { 5318225b7c95185dfbfe67da105df4402430784393cRobert Sesek // A newly opened file is not on the whitelist. Flag an error and 5328225b7c95185dfbfe67da105df4402430784393cRobert Sesek // continue. 5338225b7c95185dfbfe67da105df4402430784393cRobert Sesek error = true; 5348225b7c95185dfbfe67da105df4402430784393cRobert Sesek } else { 5358225b7c95185dfbfe67da105df4402430784393cRobert Sesek // Track the newly opened file. 5368225b7c95185dfbfe67da105df4402430784393cRobert Sesek open_fd_map_[fd] = info; 5378225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5388225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5398225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5408225b7c95185dfbfe67da105df4402430784393cRobert Sesek 5418225b7c95185dfbfe67da105df4402430784393cRobert Sesek return !error; 5428225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 5438225b7c95185dfbfe67da105df4402430784393cRobert Sesek 5448225b7c95185dfbfe67da105df4402430784393cRobert Sesek// static 5458225b7c95185dfbfe67da105df4402430784393cRobert Sesekint FileDescriptorTable::ParseFd(dirent* e, int dir_fd) { 5468225b7c95185dfbfe67da105df4402430784393cRobert Sesek char* end; 5478225b7c95185dfbfe67da105df4402430784393cRobert Sesek const int fd = strtol(e->d_name, &end, 10); 5488225b7c95185dfbfe67da105df4402430784393cRobert Sesek if ((*end) != '\0') { 5498225b7c95185dfbfe67da105df4402430784393cRobert Sesek return -1; 5508225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5518225b7c95185dfbfe67da105df4402430784393cRobert Sesek 5528225b7c95185dfbfe67da105df4402430784393cRobert Sesek // Don't bother with the standard input/output/error, they're handled 5538225b7c95185dfbfe67da105df4402430784393cRobert Sesek // specially post-fork anyway. 5548225b7c95185dfbfe67da105df4402430784393cRobert Sesek if (fd <= STDERR_FILENO || fd == dir_fd) { 5558225b7c95185dfbfe67da105df4402430784393cRobert Sesek return -1; 5568225b7c95185dfbfe67da105df4402430784393cRobert Sesek } 5578225b7c95185dfbfe67da105df4402430784393cRobert Sesek 5588225b7c95185dfbfe67da105df4402430784393cRobert Sesek return fd; 5598225b7c95185dfbfe67da105df4402430784393cRobert Sesek} 560