Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/bionic/bionic/tests/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 4 kB image not shown  

Quelle  stack_protector_test.cpp

  Sprache: C
 

/*
 * Copyright (C) 2012 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.
 */


/*
 * Contributed by: Intel Corporation
 */


#include <gtest/gtest.h>

#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <set>

#include <android-base/silent_death_test.h>

#include "platform/bionic/mte.h"
#include "private/bionic_tls.h"

extern "C" pid_t gettid(); // glibc defines this but doesn't declare it anywhere.

#if defined(__BIONIC__)
extern uintptr_t __stack_chk_guard;
#endif

struct stack_protector_checker {
  std::set<pid_t> tids;
  std::set<void*> guards;

  void Check() {
    pid_t tid = gettid();
    void* guard = __get_tls()[TLS_SLOT_STACK_GUARD];

    printf("[thread %d] TLS stack guard = %p\n", tid, guard);

    // Duplicate tid. gettid(2) bug? Seeing this would be very upsetting.
    ASSERT_FALSE(tids.contains(tid));

    // Uninitialized guard. Our bug. Note this is potentially flaky; we _could_
    // get four random zero bytes, but it should be vanishingly unlikely.
    ASSERT_NE(guard, nullptr);

#if defined(__BIONIC__)
    // bionic always has the global too.
    ASSERT_EQ(__stack_chk_guard, reinterpret_cast<uintptr_t>(guard));
#endif

    tids.insert(tid);
    guards.insert(guard);
  }
};

TEST(stack_protector, same_guard_per_thread) {
  // Everyone has the TLS slot set, even if their stack protector
  // implementation doesn't yet use it.
  stack_protector_checker checker;

  // Check the main thread.
  ASSERT_EQ(getpid(), gettid()); // We are the main thread, right?
  checker.Check();

  size_t thread_count = 9;
  for (size_t i = 1; i < thread_count; ++i) {
    pthread_t t;
    ASSERT_EQ(0, pthread_create(&t, nullptr, [](void* arg) -> void* {
      stack_protector_checker* checker = reinterpret_cast<stack_protector_checker*>(arg);
      checker->Check();
      return nullptr;
    }, &checker));
    void* result;
    ASSERT_EQ(0, pthread_join(t, &result));
    ASSERT_EQ(nullptr, result);
  }
  ASSERT_EQ(thread_count, checker.tids.size());

  // Both bionic and glibc use the same guard for every thread.
  ASSERT_EQ(1U, checker.guards.size());
}

TEST(stack_protector, global_guard) {
#if defined(__BIONIC__)
  // Bionic always has a global, even if it's using TLS.
  ASSERT_NE(0, gettid());
  ASSERT_NE(0U, __stack_chk_guard);
#else
  GTEST_SKIP() << "glibc doesn't have a global __stack_chk_guard";
#endif
}

// Make sure that a stack variable (`*p`) is tagged under MTE, by forcing the
// stack safety analysis to fail.
int z;
__attribute__((noinline)) void escape_stack_safety_analysis(int* p) {
  *p = z;
}

bool stack_mte_enabled() {
  if (!mte_supported()) return false;
  int stack_variable;
  escape_stack_safety_analysis(&stack_variable);
#if defined(__aarch64__)
  return reinterpret_cast<uintptr_t>(&stack_variable) & (0xfull << 56);
#else   // !defined(__aarch64__)
  return false;
#endif  // defined(__aarch64__)
}

bool hwasan_enabled() {
#if __has_feature(hwaddress_sanitizer)
  return true;
#else
  return false;
#endif  // __has_feature(hwaddress_sanitizer)
}

using stack_protector_DeathTest = SilentDeathTest;

TEST_F(stack_protector_DeathTest, modify_stack_protector) {
  // In another file to prevent inlining, which removes stack protection.
  extern void modify_stack_protector_test();

  if (stack_mte_enabled()) {
    GTEST_SKIP() << "Stack MTE is enabled, stack protector is not available";
  } else if (hwasan_enabled()) {
    GTEST_SKIP() << "HWASan is enabled, stack protector is not testable";
  } else {
    ASSERT_EXIT(modify_stack_protector_test(), testing::KilledBySignal(SIGABRT),
                "stack corruption detected");
  }
}

Messung V0.5 in Prozent
C=97 H=96 G=96

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.