| Nick Kralevich | bd4d45d | 2015-12-23 17:42:29 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2015 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 <gtest/gtest.h> | 
|  | 18 | #include <pthread.h> | 
|  | 19 | #include <fcntl.h> | 
|  | 20 | #include <unistd.h> | 
|  | 21 | #include <sys/types.h> | 
|  | 22 | #include <sys/stat.h> | 
|  | 23 | #include <sys/prctl.h> | 
|  | 24 |  | 
|  | 25 | #include "private/ScopeGuard.h" | 
|  | 26 |  | 
|  | 27 | extern "C" pid_t gettid(); | 
|  | 28 |  | 
|  | 29 | static void ProcSelfReadlinkBody() { | 
|  | 30 | char buf[100]; | 
|  | 31 | char buf2[1024]; | 
|  | 32 | int fd = open("/dev/null", O_RDWR | O_CLOEXEC); | 
|  | 33 | ASSERT_NE(-1, fd); | 
|  | 34 | snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); | 
|  | 35 | const char* ERRORMSG = "Please apply the following two kernel patches:\n" | 
|  | 36 | "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=73af963f9f3036dffed55c3a2898598186db1045\n" | 
|  | 37 | "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=96d0df79f2644fc823f26c06491e182d87a90c2a\n"; | 
|  | 38 | ASSERT_NE(-1, readlink(buf, buf2, sizeof(buf2))) << ERRORMSG; | 
|  | 39 | ASSERT_STREQ("/dev/null", buf2); | 
|  | 40 | close(fd); | 
|  | 41 | } | 
|  | 42 |  | 
|  | 43 | static void* ProcSelfReadlink(void*) { | 
|  | 44 | ProcSelfReadlinkBody(); | 
|  | 45 | return NULL; | 
|  | 46 | } | 
|  | 47 |  | 
|  | 48 | TEST(bug_26110743, ProcSelfReadlink) { | 
|  | 49 | pthread_t t; | 
|  | 50 | ASSERT_EQ(0, pthread_create(&t, NULL, ProcSelfReadlink, NULL)); | 
|  | 51 | void* result; | 
|  | 52 | ASSERT_EQ(0, pthread_join(t, &result)); | 
|  | 53 | ASSERT_EQ(NULL, result); | 
|  | 54 | } | 
|  | 55 |  | 
|  | 56 | TEST(bug_26110743, ProcSelfReadlink_NotDumpable) { | 
|  | 57 | int dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0); | 
|  | 58 | prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); | 
|  | 59 | auto guard = make_scope_guard([&]() { | 
|  | 60 | // restore dumpable | 
|  | 61 | prctl(PR_SET_DUMPABLE, dumpable, 0, 0, 0); | 
|  | 62 | }); | 
|  | 63 |  | 
|  | 64 | pthread_t t; | 
|  | 65 | ASSERT_EQ(0, pthread_create(&t, NULL, ProcSelfReadlink, NULL)); | 
|  | 66 | void* result; | 
|  | 67 | ASSERT_EQ(0, pthread_join(t, &result)); | 
|  | 68 | ASSERT_EQ(NULL, result); | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | static void ProcTaskFdReadlinkBody() { | 
|  | 72 | char buf[200]; | 
|  | 73 | char buf2[1024]; | 
|  | 74 | int fd = open("/dev/null", O_RDWR | O_CLOEXEC); | 
|  | 75 | ASSERT_NE(-1, fd); | 
|  | 76 | pid_t mypid = getpid(); | 
|  | 77 | pid_t mytid = gettid(); | 
|  | 78 | ASSERT_NE(mypid, mytid); | 
|  | 79 | snprintf(buf, sizeof(buf), "/proc/%d/task/%d/fd/%d", mypid, mytid, fd); | 
|  | 80 | const char* ERRORMSG = "Please apply the following kernel patch:\n" | 
|  | 81 | "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=54708d2858e79a2bdda10bf8a20c80eb96c20613\n"; | 
|  | 82 | ASSERT_NE(-1, readlink(buf, buf2, sizeof(buf2))) << ERRORMSG; | 
|  | 83 | ASSERT_STREQ("/dev/null", buf2); | 
|  | 84 | close(fd); | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | static void* ProcTaskFdReadlink(void*) { | 
|  | 88 | ProcTaskFdReadlinkBody(); | 
|  | 89 | return NULL; | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | TEST(bug_26110743, ProcTaskFdReadlink) { | 
|  | 93 | pthread_t t; | 
|  | 94 | ASSERT_EQ(0, pthread_create(&t, NULL, ProcTaskFdReadlink, NULL)); | 
|  | 95 | void* result; | 
|  | 96 | ASSERT_EQ(0, pthread_join(t, &result)); | 
|  | 97 | ASSERT_EQ(NULL, result); | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | TEST(bug_26110743, ProcTaskFdReadlink_NotDumpable) { | 
|  | 101 | int dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0); | 
|  | 102 | prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); | 
|  | 103 | auto guard = make_scope_guard([&]() { | 
|  | 104 | // restore dumpable | 
|  | 105 | prctl(PR_SET_DUMPABLE, dumpable, 0, 0, 0); | 
|  | 106 | }); | 
|  | 107 |  | 
|  | 108 | pthread_t t; | 
|  | 109 | ASSERT_EQ(0, pthread_create(&t, NULL, ProcTaskFdReadlink, NULL)); | 
|  | 110 | void* result; | 
|  | 111 | ASSERT_EQ(0, pthread_join(t, &result)); | 
|  | 112 | ASSERT_EQ(NULL, result); | 
|  | 113 | } |