From f6e5b582604715729b09db3e36a7aeb8c24b36a4 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Fri, 1 Jun 2018 15:30:54 -0700 Subject: Introduce api to track fd ownership in libc. Add two functions to allow objects that own a file descriptor to enforce that only they can close their file descriptor. Use them in FILE* and DIR*. Bug: http://b/110100358 Test: bionic_unit_tests Test: aosp/master boots without errors Test: treehugger Change-Id: Iecd6e8b26c62217271e0822dc3d2d7888b091a45 --- libc/stdio/stdio.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'libc/stdio/stdio.cpp') diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp index 1f08ea13d..050157bda 100644 --- a/libc/stdio/stdio.cpp +++ b/libc/stdio/stdio.cpp @@ -46,6 +46,8 @@ #include #include +#include + #include #include "local.h" @@ -54,6 +56,8 @@ #include "private/ErrnoRestorer.h" #include "private/thread_private.h" +extern "C" int ___close(int fd); + #define ALIGNBYTES (sizeof(uintptr_t) - 1) #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES) @@ -102,6 +106,19 @@ FILE* stdout = &__sF[1]; FILE* stderr = &__sF[2]; static pthread_mutex_t __stdio_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +static uint64_t __get_file_tag(FILE* fp) { + // Don't use a tag for the standard streams. + // They don't really own their file descriptors, because the values are well-known, and you're + // allowed to do things like `close(STDIN_FILENO); open("foo", O_RDONLY)` when single-threaded. + if (fp == stdin || fp == stderr || fp == stdout) { + return 0; + } + + return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_FILE, + reinterpret_cast(fp)); +} + struct glue __sglue = { nullptr, 3, __sF }; static struct glue* lastglue = &__sglue; @@ -219,6 +236,7 @@ static FILE* __fopen(int fd, int flags) { FILE* fp = __sfp(); if (fp != nullptr) { fp->_file = fd; + android_fdsan_exchange_owner_tag(fd, 0, __get_file_tag(fp)); fp->_flags = flags; fp->_cookie = fp; fp->_read = __sread; @@ -373,6 +391,7 @@ FILE* freopen(const char* file, const char* mode, FILE* fp) { fp->_flags = flags; fp->_file = fd; + android_fdsan_exchange_owner_tag(fd, 0, __get_file_tag(fp)); fp->_cookie = fp; fp->_read = __sread; fp->_write = __swrite; @@ -518,7 +537,7 @@ off64_t __sseek64(void* cookie, off64_t offset, int whence) { int __sclose(void* cookie) { FILE* fp = reinterpret_cast(cookie); - return close(fp->_file); + return android_fdsan_close_with_tag(fp->_file, __get_file_tag(fp)); } static off64_t __seek_unlocked(FILE* fp, off64_t offset, int whence) { -- cgit v1.2.3