1 /* 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 <string> 18 #include <unordered_map> 19 #include <set> 20 #include <vector> 21 #include <algorithm> 22 23 #include <dirent.h> 24 #include <fcntl.h> 25 #include <grp.h> 26 #include <inttypes.h> 27 #include <stdlib.h> 28 #include <sys/socket.h> 29 #include <sys/stat.h> 30 #include <sys/types.h> 31 #include <sys/un.h> 32 #include <unistd.h> 33 34 #include <cutils/log.h> 35 #include "JNIHelp.h" 36 #include "ScopedPrimitiveArray.h" 37 38 // Whitelist of open paths that the zygote is allowed to keep open. 39 // 40 // In addition to the paths listed here, all files ending with 41 // ".jar" under /system/framework" are whitelisted. See 42 // FileDescriptorInfo::IsWhitelisted for the canonical definition. 43 // 44 // If the whitelisted path is associated with a regular file or a 45 // character device, the file is reopened after a fork with the same 46 // offset and mode. If the whilelisted path is associated with a 47 // AF_UNIX socket, the socket will refer to /dev/null after each 48 // fork, and all operations on it will fail. 49 static const char* kPathWhitelist[] = { 50 "/dev/null", 51 "/dev/socket/zygote", 52 "/dev/socket/zygote_secondary", 53 "/sys/kernel/debug/tracing/trace_marker", 54 "/system/framework/framework-res.apk", 55 "/dev/urandom", 56 "/dev/ion", 57 "/dev/dri/renderD129", // Fixes b/31172436 58 }; 59 60 static const char* kFdPath = "/proc/self/fd"; 61 62 // Keeps track of all relevant information (flags, offset etc.) of an 63 // open zygote file descriptor. 64 class FileDescriptorInfo { 65 public: 66 // Create a FileDescriptorInfo for a given file descriptor. Returns 67 // |NULL| if an error occurred. 68 static FileDescriptorInfo* createFromFd(int fd) { 69 struct stat f_stat; 70 // This should never happen; the zygote should always have the right set 71 // of permissions required to stat all its open files. 72 if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { 73 ALOGE("Unable to stat fd %d : %s", fd, strerror(errno)); 74 return NULL; 75 } 76 77 if (S_ISSOCK(f_stat.st_mode)) { 78 std::string socket_name; 79 if (!GetSocketName(fd, &socket_name)) { 80 return NULL; 81 } 82 83 if (!IsWhitelisted(socket_name)) { 84 ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd); 85 return NULL; 86 } 87 88 return new FileDescriptorInfo(fd); 89 } 90 91 // We only handle whitelisted regular files and character devices. Whitelisted 92 // character devices must provide a guarantee of sensible behaviour when 93 // reopened. 94 // 95 // S_ISDIR : Not supported. (We could if we wanted to, but it's unused). 96 // S_ISLINK : Not supported. 97 // S_ISBLK : Not supported. 98 // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate 99 // with the child process across forks but those should have been closed 100 // before we got to this point. 101 if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) { 102 ALOGE("Unsupported st_mode %d", f_stat.st_mode); 103 return NULL; 104 } 105 106 std::string file_path; 107 if (!Readlink(fd, &file_path)) { 108 return NULL; 109 } 110 111 if (!IsWhitelisted(file_path)) { 112 ALOGE("Not whitelisted : %s", file_path.c_str()); 113 return NULL; 114 } 115 116 // File descriptor flags : currently on FD_CLOEXEC. We can set these 117 // using F_SETFD - we're single threaded at this point of execution so 118 // there won't be any races. 119 const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)); 120 if (fd_flags == -1) { 121 ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno)); 122 return NULL; 123 } 124 125 // File status flags : 126 // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through 127 // to the open() call. 128 // 129 // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can 130 // do about these, since the file has already been created. We shall ignore 131 // them here. 132 // 133 // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL 134 // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK. 135 // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for 136 // their presence and pass them in to open(). 137 int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); 138 if (fs_flags == -1) { 139 ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno)); 140 return NULL; 141 } 142 143 // File offset : Ignore the offset for non seekable files. 144 const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR)); 145 146 // We pass the flags that open accepts to open, and use F_SETFL for 147 // the rest of them. 148 static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC); 149 int open_flags = fs_flags & (kOpenFlags); 150 fs_flags = fs_flags & (~(kOpenFlags)); 151 152 return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset); 153 } 154 155 // Checks whether the file descriptor associated with this object 156 // refers to the same description. 157 bool Restat() const { 158 struct stat f_stat; 159 if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { 160 return false; 161 } 162 163 return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev; 164 } 165 166 bool ReopenOrDetach() const { 167 if (is_sock) { 168 return DetachSocket(); 169 } 170 171 // NOTE: This might happen if the file was unlinked after being opened. 172 // It's a common pattern in the case of temporary files and the like but 173 // we should not allow such usage from the zygote. 174 const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags)); 175 176 if (new_fd == -1) { 177 ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno)); 178 return false; 179 } 180 181 if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) { 182 close(new_fd); 183 ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno)); 184 return false; 185 } 186 187 if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) { 188 close(new_fd); 189 ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno)); 190 return false; 191 } 192 193 if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) { 194 close(new_fd); 195 ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno)); 196 return false; 197 } 198 199 if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) { 200 close(new_fd); 201 ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno)); 202 return false; 203 } 204 205 close(new_fd); 206 207 return true; 208 } 209 210 const int fd; 211 const struct stat stat; 212 const std::string file_path; 213 const int open_flags; 214 const int fd_flags; 215 const int fs_flags; 216 const off_t offset; 217 const bool is_sock; 218 219 private: 220 FileDescriptorInfo(int fd) : 221 fd(fd), 222 stat(), 223 open_flags(0), 224 fd_flags(0), 225 fs_flags(0), 226 offset(0), 227 is_sock(true) { 228 } 229 230 FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, 231 int fd_flags, int fs_flags, off_t offset) : 232 fd(fd), 233 stat(stat), 234 file_path(file_path), 235 open_flags(open_flags), 236 fd_flags(fd_flags), 237 fs_flags(fs_flags), 238 offset(offset), 239 is_sock(false) { 240 } 241 242 // Returns true iff. a given path is whitelisted. A path is whitelisted 243 // if it belongs to the whitelist (see kPathWhitelist) or if it's a path 244 // under /system/framework that ends with ".jar". 245 static bool IsWhitelisted(const std::string& path) { 246 for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) { 247 if (kPathWhitelist[i] == path) { 248 return true; 249 } 250 } 251 252 static const std::string kFrameworksPrefix = "/system/framework/"; 253 static const std::string kJarSuffix = ".jar"; 254 if (path.compare(0, kFrameworksPrefix.size(), kFrameworksPrefix) == 0 && 255 path.compare(path.size() - kJarSuffix.size(), kJarSuffix.size(), kJarSuffix) == 0) { 256 return true; 257 } 258 return false; 259 } 260 261 // TODO: Call android::base::Readlink instead of copying the code here. 262 static bool Readlink(const int fd, std::string* result) { 263 char path[64]; 264 snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); 265 266 // Code copied from android::base::Readlink starts here : 267 268 // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer, 269 // and truncates to whatever size you do supply, so it can't be used to query. 270 // We could call lstat first, but that would introduce a race condition that 271 // we couldn't detect. 272 // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here. 273 char buf[4096]; 274 ssize_t len = readlink(path, buf, sizeof(buf)); 275 if (len == -1) return false; 276 277 result->assign(buf, len); 278 return true; 279 } 280 281 // Returns the locally-bound name of the socket |fd|. Returns true 282 // iff. all of the following hold : 283 // 284 // - the socket's sa_family is AF_UNIX. 285 // - the length of the path is greater than zero (i.e, not an unnamed socket). 286 // - the first byte of the path isn't zero (i.e, not a socket with an abstract 287 // address). 288 static bool GetSocketName(const int fd, std::string* result) { 289 sockaddr_storage ss; 290 sockaddr* addr = reinterpret_cast<sockaddr*>(&ss); 291 socklen_t addr_len = sizeof(ss); 292 293 if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) { 294 ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno)); 295 return false; 296 } 297 298 if (addr->sa_family != AF_UNIX) { 299 ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family); 300 return false; 301 } 302 303 const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss); 304 305 size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path); 306 // This is an unnamed local socket, we do not accept it. 307 if (path_len == 0) { 308 ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd); 309 return false; 310 } 311 312 // This is a local socket with an abstract address, we do not accept it. 313 if (unix_addr->sun_path[0] == '\0') { 314 ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd); 315 return false; 316 } 317 318 // If we're here, sun_path must refer to a null terminated filesystem 319 // pathname (man 7 unix). Remove the terminator before assigning it to an 320 // std::string. 321 if (unix_addr->sun_path[path_len - 1] == '\0') { 322 --path_len; 323 } 324 325 result->assign(unix_addr->sun_path, path_len); 326 return true; 327 } 328 329 bool DetachSocket() const { 330 const int dev_null_fd = open("/dev/null", O_RDWR); 331 if (dev_null_fd < 0) { 332 ALOGE("Failed to open /dev/null : %s", strerror(errno)); 333 return false; 334 } 335 336 if (dup2(dev_null_fd, fd) == -1) { 337 ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno)); 338 return false; 339 } 340 341 if (close(dev_null_fd) == -1) { 342 ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno)); 343 return false; 344 } 345 346 return true; 347 } 348 349 DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo); 350 }; 351 352 // A FileDescriptorTable is a collection of FileDescriptorInfo objects 353 // keyed by their FDs. 354 class FileDescriptorTable { 355 public: 356 // Creates a new FileDescriptorTable. This function scans 357 // /proc/self/fd for the list of open file descriptors and collects 358 // information about them. Returns NULL if an error occurs. 359 static FileDescriptorTable* Create() { 360 DIR* d = opendir(kFdPath); 361 if (d == NULL) { 362 ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); 363 return NULL; 364 } 365 int dir_fd = dirfd(d); 366 dirent* e; 367 368 std::unordered_map<int, FileDescriptorInfo*> open_fd_map; 369 while ((e = readdir(d)) != NULL) { 370 const int fd = ParseFd(e, dir_fd); 371 if (fd == -1) { 372 continue; 373 } 374 375 FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd); 376 if (info == NULL) { 377 if (closedir(d) == -1) { 378 ALOGE("Unable to close directory : %s", strerror(errno)); 379 } 380 return NULL; 381 } 382 open_fd_map[fd] = info; 383 } 384 385 if (closedir(d) == -1) { 386 ALOGE("Unable to close directory : %s", strerror(errno)); 387 return NULL; 388 } 389 return new FileDescriptorTable(open_fd_map); 390 } 391 392 bool Restat() { 393 std::set<int> open_fds; 394 395 // First get the list of open descriptors. 396 DIR* d = opendir(kFdPath); 397 if (d == NULL) { 398 ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); 399 return false; 400 } 401 402 int dir_fd = dirfd(d); 403 dirent* e; 404 while ((e = readdir(d)) != NULL) { 405 const int fd = ParseFd(e, dir_fd); 406 if (fd == -1) { 407 continue; 408 } 409 410 open_fds.insert(fd); 411 } 412 413 if (closedir(d) == -1) { 414 ALOGE("Unable to close directory : %s", strerror(errno)); 415 return false; 416 } 417 418 return RestatInternal(open_fds); 419 } 420 421 // Reopens all file descriptors that are contained in the table. Returns true 422 // if all descriptors were successfully re-opened or detached, and false if an 423 // error occurred. 424 bool ReopenOrDetach() { 425 std::unordered_map<int, FileDescriptorInfo*>::const_iterator it; 426 for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { 427 const FileDescriptorInfo* info = it->second; 428 if (info == NULL || !info->ReopenOrDetach()) { 429 return false; 430 } 431 } 432 433 return true; 434 } 435 436 private: 437 FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map) 438 : open_fd_map_(map) { 439 } 440 441 bool RestatInternal(std::set<int>& open_fds) { 442 bool error = false; 443 444 // Iterate through the list of file descriptors we've already recorded 445 // and check whether : 446 // 447 // (a) they continue to be open. 448 // (b) they refer to the same file. 449 std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin(); 450 while (it != open_fd_map_.end()) { 451 std::set<int>::const_iterator element = open_fds.find(it->first); 452 if (element == open_fds.end()) { 453 // The entry from the file descriptor table is no longer in the list 454 // of open files. We warn about this condition and remove it from 455 // the list of FDs under consideration. 456 // 457 // TODO(narayan): This will be an error in a future android release. 458 // error = true; 459 // ALOGW("Zygote closed file descriptor %d.", it->first); 460 it = open_fd_map_.erase(it); 461 } else { 462 // The entry from the file descriptor table is still open. Restat 463 // it and check whether it refers to the same file. 464 const bool same_file = it->second->Restat(); 465 if (!same_file) { 466 // The file descriptor refers to a different description. We must 467 // update our entry in the table. 468 delete it->second; 469 it->second = FileDescriptorInfo::createFromFd(*element); 470 if (it->second == NULL) { 471 // The descriptor no longer no longer refers to a whitelisted file. 472 // We flag an error and remove it from the list of files we're 473 // tracking. 474 error = true; 475 it = open_fd_map_.erase(it); 476 } else { 477 // Successfully restatted the file, move on to the next open FD. 478 ++it; 479 } 480 } else { 481 // It's the same file. Nothing to do here. Move on to the next open 482 // FD. 483 ++it; 484 } 485 486 // Finally, remove the FD from the set of open_fds. We do this last because 487 // |element| will not remain valid after a call to erase. 488 open_fds.erase(element); 489 } 490 } 491 492 if (open_fds.size() > 0) { 493 // The zygote has opened new file descriptors since our last inspection. 494 // We warn about this condition and add them to our table. 495 // 496 // TODO(narayan): This will be an error in a future android release. 497 // error = true; 498 // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size()); 499 500 // TODO(narayan): This code will be removed in a future android release. 501 std::set<int>::const_iterator it; 502 for (it = open_fds.begin(); it != open_fds.end(); ++it) { 503 const int fd = (*it); 504 FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd); 505 if (info == NULL) { 506 // A newly opened file is not on the whitelist. Flag an error and 507 // continue. 508 error = true; 509 } else { 510 // Track the newly opened file. 511 open_fd_map_[fd] = info; 512 } 513 } 514 } 515 516 return !error; 517 } 518 519 static int ParseFd(dirent* e, int dir_fd) { 520 char* end; 521 const int fd = strtol(e->d_name, &end, 10); 522 if ((*end) != '\0') { 523 return -1; 524 } 525 526 // Don't bother with the standard input/output/error, they're handled 527 // specially post-fork anyway. 528 if (fd <= STDERR_FILENO || fd == dir_fd) { 529 return -1; 530 } 531 532 return fd; 533 } 534 535 // Invariant: All values in this unordered_map are non-NULL. 536 std::unordered_map<int, FileDescriptorInfo*> open_fd_map_; 537 538 DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable); 539 }; 540