xref: /llvm-project/libc/test/integration/src/unistd/stack_smashing_test.cpp (revision 46944b0cbc9a9d8daad0182c40fcd3560bc9ca35)
1*28245b4eStnv01 //===--- Stack smashing test to check stack canary set up  ----------------===//
2*28245b4eStnv01 //
3*28245b4eStnv01 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*28245b4eStnv01 // See https://llvm.org/LICENSE.txt for license information.
5*28245b4eStnv01 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*28245b4eStnv01 //
7*28245b4eStnv01 //===----------------------------------------------------------------------===//
8*28245b4eStnv01 
9*28245b4eStnv01 #include "src/__support/CPP/string.h"
10*28245b4eStnv01 #include "src/__support/OSUtil/io.h"
11*28245b4eStnv01 #include "src/pthread/pthread_atfork.h"
12*28245b4eStnv01 #include "src/signal/raise.h"
13*28245b4eStnv01 #include "src/sys/wait/wait.h"
14*28245b4eStnv01 #include "src/sys/wait/wait4.h"
15*28245b4eStnv01 #include "src/sys/wait/waitpid.h"
16*28245b4eStnv01 #include "src/unistd/fork.h"
17*28245b4eStnv01 
18*28245b4eStnv01 #include "test/IntegrationTest/test.h"
19*28245b4eStnv01 
20*28245b4eStnv01 #include <signal.h>
21*28245b4eStnv01 #include <sys/wait.h>
22*28245b4eStnv01 #include <unistd.h>
23*28245b4eStnv01 
24*28245b4eStnv01 void no_stack_smashing_normal_exit() {
25*28245b4eStnv01   pid_t pid = LIBC_NAMESPACE::fork();
26*28245b4eStnv01   if (pid == 0) {
27*28245b4eStnv01     // Child process
28*28245b4eStnv01     char foo[30];
29*28245b4eStnv01     for (int i = 0; i < 30; i++)
30*28245b4eStnv01       foo[i] = (foo[i] != 42) ? 42 : 24;
31*28245b4eStnv01     return;
32*28245b4eStnv01   }
33*28245b4eStnv01   ASSERT_TRUE(pid > 0);
34*28245b4eStnv01   int status;
35*28245b4eStnv01   pid_t cpid = LIBC_NAMESPACE::wait(&status);
36*28245b4eStnv01   ASSERT_TRUE(cpid > 0);
37*28245b4eStnv01   ASSERT_EQ(cpid, pid);
38*28245b4eStnv01   ASSERT_TRUE(WIFEXITED(status));
39*28245b4eStnv01 }
40*28245b4eStnv01 
41*28245b4eStnv01 void stack_smashing_abort() {
42*28245b4eStnv01   pid_t pid = LIBC_NAMESPACE::fork();
43*28245b4eStnv01   if (pid == 0) {
44*28245b4eStnv01     // Child process
45*28245b4eStnv01     char foo[30];
46*28245b4eStnv01     char *frame_ptr = static_cast<char *>(__builtin_frame_address(0));
47*28245b4eStnv01     char *cur_ptr = &foo[0];
48*28245b4eStnv01     // Corrupt the stack
49*28245b4eStnv01     while (cur_ptr != frame_ptr) {
50*28245b4eStnv01       *cur_ptr = (*cur_ptr != 42) ? 42 : 24;
51*28245b4eStnv01       cur_ptr++;
52*28245b4eStnv01     }
53*28245b4eStnv01     return;
54*28245b4eStnv01   }
55*28245b4eStnv01   ASSERT_TRUE(pid > 0);
56*28245b4eStnv01   int status;
57*28245b4eStnv01   pid_t cpid = LIBC_NAMESPACE::wait(&status);
58*28245b4eStnv01   ASSERT_TRUE(cpid > 0);
59*28245b4eStnv01   ASSERT_EQ(cpid, pid);
60*28245b4eStnv01   ASSERT_TRUE(WTERMSIG(status) == SIGABRT);
61*28245b4eStnv01 }
62*28245b4eStnv01 
63*28245b4eStnv01 TEST_MAIN(int argc, char **argv, char **envp) {
64*28245b4eStnv01   no_stack_smashing_normal_exit();
65*28245b4eStnv01   stack_smashing_abort();
66*28245b4eStnv01   return 0;
67*28245b4eStnv01 }
68