diff options
author | Pirama Arumuga Nainar <pirama@google.com> | 2020-12-10 10:19:48 -0800 |
---|---|---|
committer | Pirama Arumuga Nainar <pirama@google.com> | 2020-12-10 13:33:21 -0800 |
commit | 04195c55f3f12109f41d4130afe157046a0aa7a6 (patch) | |
tree | 768ab581af4c943718fa4bbdc8c085f9468068d3 | |
parent | 4c43577db1f6c4557d2b4a6fd9b1738cad667a41 (diff) | |
download | extras-04195c55f3f12109f41d4130afe157046a0aa7a6.tar.gz |
[coverage] Wrap calls to open
Bug: http://b/173448692
The coverage runtime creates files with uga+rw permissions but an
earlier umask call can restrict these and cause problems with profile
merging ('%Nm' in LLVM_PROFILE_FILE). This change adds a wrapper to
`open` which will set the permissions again using `fchmod` for files
opened under the /data/misc/trace directory.
Test: Manually validate permissions of files under /data/misc/trace.
Test: libprofile-clang-extras-test
Change-Id: Iee7fe07b4bfb362fe5146c962b54affaa55ef380
-rw-r--r-- | toolchain-extras/Android.bp | 16 | ||||
-rw-r--r-- | toolchain-extras/profile-clang-extras-test.cpp | 21 | ||||
-rw-r--r-- | toolchain-extras/profile-clang-openat.cpp | 55 |
3 files changed, 91 insertions, 1 deletions
diff --git a/toolchain-extras/Android.bp b/toolchain-extras/Android.bp index dec5d404..ff537a52 100644 --- a/toolchain-extras/Android.bp +++ b/toolchain-extras/Android.bp @@ -41,6 +41,7 @@ cc_defaults { name: "libprofile-clang-defaults", srcs: [ "profile-clang-extras.cpp", + "profile-clang-openat.cpp", ], native_coverage: false, } @@ -86,3 +87,18 @@ cc_test { ldflags: ["-uinit_profile_extras"], native_coverage: false, } + +cc_test { + name: "libprofile-clang-extras-test", + srcs: [ + "profile-clang-extras-test.cpp", + ], + static_libs: [ + "libprofile-clang-extras", + ], + ldflags: [ + "-uinit_profile_extras", + "-Wl,--wrap,open", + ], + native_coverage: false, +} diff --git a/toolchain-extras/profile-clang-extras-test.cpp b/toolchain-extras/profile-clang-extras-test.cpp index 2bb7bdbb..0c746478 100644 --- a/toolchain-extras/profile-clang-extras-test.cpp +++ b/toolchain-extras/profile-clang-extras-test.cpp @@ -14,7 +14,10 @@ * limitations under the License. */ +#include <fcntl.h> #include <gtest/gtest.h> +#include <sys/stat.h> + #include "profile-extras.h" static int flush_count = 0; @@ -30,7 +33,23 @@ TEST(profile_extras, smoke) { flush_count = 0; ASSERT_EQ(0, flush_count); - kill(getpid(), GCOV_FLUSH_SIGNAL); + kill(getpid(), COVERAGE_FLUSH_SIGNAL); sleep(2); ASSERT_EQ(1, flush_count); } + +static const char* OPEN_AT_TEST_FNAME = "/data/misc/trace/test.profraw"; +TEST(profile_extras, openat) { + mode_t old_umask = umask(0077); + unlink(OPEN_AT_TEST_FNAME); + + int fd = open(OPEN_AT_TEST_FNAME, O_RDWR | O_CREAT, 0666); + ASSERT_NE(fd, -1); + close(fd); + umask(old_umask); + + struct stat stat_buf; + ASSERT_EQ(stat(OPEN_AT_TEST_FNAME, &stat_buf), 0); + ASSERT_EQ(stat_buf.st_mode & 0777, 0666); + unlink(OPEN_AT_TEST_FNAME); +} diff --git a/toolchain-extras/profile-clang-openat.cpp b/toolchain-extras/profile-clang-openat.cpp new file mode 100644 index 00000000..f2f43d14 --- /dev/null +++ b/toolchain-extras/profile-clang-openat.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fcntl.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +// This file provides a wrapper for open. + +extern "C" { + +int __real_open(const char* pathname, int flags, ...); + +static bool needs_mode(int flags) { + return ((flags & O_CREAT) == O_CREAT) || ((flags & O_TMPFILE) == O_TMPFILE); +} + +static const char* PROFRAW_START = "/data/misc/trace/"; +static bool is_coverage_trace(const char* pathname) { + if (strncmp(pathname, PROFRAW_START, strlen(PROFRAW_START)) == 0) return true; + return false; +} + +__attribute__((weak)) int __wrap_open(const char* pathname, int flags, ...) { + if (!needs_mode(flags)) { + return __real_open(pathname, flags); + } + + va_list args; + va_start(args, flags); + mode_t mode = static_cast<mode_t>(va_arg(args, int)); + va_end(args); + + int ret = __real_open(pathname, flags, mode); + if (is_coverage_trace(pathname)) fchmod(ret, mode); + return ret; +} +} |