1ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes/*
2ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * Copyright (C) 2012 The Android Open Source Project
3ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes *
4ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * you may not use this file except in compliance with the License.
6ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * You may obtain a copy of the License at
7ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes *
8ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes *
10ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * See the License for the specific language governing permissions and
14ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * limitations under the License.
15ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes */
16ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
17ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes/*
18ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes * Contributed by: Intel Corporation
19ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes */
20ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
21ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes#include <gtest/gtest.h>
229df70403d95f5cfe6824e38a9a6c35f9b9bbc76aYabin Cui#include "BionicDeathTest.h"
23ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
24ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes#include <pthread.h>
25ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes#include <stdint.h>
26ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes#include <stdio.h>
27ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes#include <unistd.h>
28ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes#include <set>
29ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
3012393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes#include "private/bionic_tls.h"
3112393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes
3212393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughesextern "C" pid_t gettid(); // glibc defines this but doesn't declare it anywhere.
3312393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes
3412393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes#if defined(__BIONIC__)
3512393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughesextern uintptr_t __stack_chk_guard;
3612393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes#endif
37ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
38ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughesstruct stack_protector_checker {
39ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes  std::set<pid_t> tids;
4012393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  std::set<void*> guards;
41ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
42ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes  void Check() {
43ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    pid_t tid = gettid();
4412393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    void* guard = __get_tls()[TLS_SLOT_STACK_GUARD];
45ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
4612393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    printf("[thread %d] TLS stack guard = %p\n", tid, guard);
47ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
48ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    // Duplicate tid. gettid(2) bug? Seeing this would be very upsetting.
49ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    ASSERT_TRUE(tids.find(tid) == tids.end());
50d3920b3a996b358e48232f417aa0a1e44a60f155Elliott Hughes
5112393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    // Uninitialized guard. Our bug. Note this is potentially flaky; we _could_
5212393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    // get four random zero bytes, but it should be vanishingly unlikely.
5312393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    ASSERT_NE(guard, nullptr);
5412393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes
5512393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes#if defined(__BIONIC__)
5612393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    // bionic always has the global too.
5712393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    ASSERT_EQ(__stack_chk_guard, reinterpret_cast<uintptr_t>(guard));
5812393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes#endif
59ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
60ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    tids.insert(tid);
61ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    guards.insert(guard);
62ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes  }
63ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes};
64ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
65d3920b3a996b358e48232f417aa0a1e44a60f155Elliott HughesTEST(stack_protector, same_guard_per_thread) {
6612393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  // Everyone has the TLS slot set, even if their stack protector
6712393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  // implementation doesn't yet use it.
68ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes  stack_protector_checker checker;
6912393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes
7012393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  // Check the main thread.
7112393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  ASSERT_EQ(getpid(), gettid()); // We are the main thread, right?
7212393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  checker.Check();
7312393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes
7412393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  size_t thread_count = 9;
7512393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  for (size_t i = 1; i < thread_count; ++i) {
76ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    pthread_t t;
7712393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    ASSERT_EQ(0, pthread_create(&t, NULL, [](void* arg) -> void* {
7812393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes      stack_protector_checker* checker = reinterpret_cast<stack_protector_checker*>(arg);
7912393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes      checker->Check();
8012393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes      return nullptr;
8112393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes    }, &checker));
82ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    void* result;
83ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    ASSERT_EQ(0, pthread_join(t, &result));
84ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes    ASSERT_EQ(NULL, result);
85ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes  }
86ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes  ASSERT_EQ(thread_count, checker.tids.size());
87ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
8812393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  // Both bionic and glibc use the same guard for every thread.
89ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes  ASSERT_EQ(1U, checker.guards.size());
90ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes}
91ad88a0863110798cef5169dcf917e18b967a7cf6Elliott Hughes
92f04935c85e0b466f0d30d2cd4c0fa2fff62e7d6dChristopher FerrisTEST(stack_protector, global_guard) {
9312393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes#if defined(__BIONIC__)
9412393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  // Bionic always has a global, even if it's using TLS.
95f04935c85e0b466f0d30d2cd4c0fa2fff62e7d6dChristopher Ferris  ASSERT_NE(0, gettid());
96f04935c85e0b466f0d30d2cd4c0fa2fff62e7d6dChristopher Ferris  ASSERT_NE(0U, __stack_chk_guard);
9712393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes#else
9812393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  GTEST_LOG_(INFO) << "glibc doesn't have a global __stack_chk_guard.\n";
9912393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes#endif
100f04935c85e0b466f0d30d2cd4c0fa2fff62e7d6dChristopher Ferris}
101dcab1b2c76a498c56bc00024613386de8b4b2aaeNick Kralevich
1029df70403d95f5cfe6824e38a9a6c35f9b9bbc76aYabin Cuiclass stack_protector_DeathTest : public BionicDeathTest {};
1039df70403d95f5cfe6824e38a9a6c35f9b9bbc76aYabin Cui
1049df70403d95f5cfe6824e38a9a6c35f9b9bbc76aYabin CuiTEST_F(stack_protector_DeathTest, modify_stack_protector) {
10512393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  // In another file to prevent inlining, which removes stack protection.
10612393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  extern void modify_stack_protector_test();
10712393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes  ASSERT_EXIT(modify_stack_protector_test(),
10812393862e55b9ab28dd29ae16fbdf498371726a7Elliott Hughes              testing::KilledBySignal(SIGABRT), "stack corruption detected");
109dcab1b2c76a498c56bc00024613386de8b4b2aaeNick Kralevich}
110