xref: /aosp_15_r20/platform_testing/utils/shell-as/shell-code.cpp (revision dd0948b35e70be4c0246aabd6c72554a5eb8b22a)
1*dd0948b3SAndroid Build Coastguard Worker /*
2*dd0948b3SAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
3*dd0948b3SAndroid Build Coastguard Worker  *
4*dd0948b3SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*dd0948b3SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*dd0948b3SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*dd0948b3SAndroid Build Coastguard Worker  *
8*dd0948b3SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*dd0948b3SAndroid Build Coastguard Worker  *
10*dd0948b3SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*dd0948b3SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*dd0948b3SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*dd0948b3SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*dd0948b3SAndroid Build Coastguard Worker  * limitations under the License.
15*dd0948b3SAndroid Build Coastguard Worker  */
16*dd0948b3SAndroid Build Coastguard Worker 
17*dd0948b3SAndroid Build Coastguard Worker #include "./shell-code.h"
18*dd0948b3SAndroid Build Coastguard Worker 
19*dd0948b3SAndroid Build Coastguard Worker #include <sys/mman.h>
20*dd0948b3SAndroid Build Coastguard Worker #include <sys/types.h>
21*dd0948b3SAndroid Build Coastguard Worker #include <unistd.h>
22*dd0948b3SAndroid Build Coastguard Worker 
23*dd0948b3SAndroid Build Coastguard Worker // Shell code that sets the SELinux context of the current process.
24*dd0948b3SAndroid Build Coastguard Worker //
25*dd0948b3SAndroid Build Coastguard Worker // The shell code expects a null-terminated SELinux context string to be placed
26*dd0948b3SAndroid Build Coastguard Worker // immediately after it in memory. After the SELinux context has been changed
27*dd0948b3SAndroid Build Coastguard Worker // the shell code will stop the current process with SIGSTOP.
28*dd0948b3SAndroid Build Coastguard Worker //
29*dd0948b3SAndroid Build Coastguard Worker // This shell code must be self-contained and position-independent.
30*dd0948b3SAndroid Build Coastguard Worker extern "C" void __setcon_shell_code_start();
31*dd0948b3SAndroid Build Coastguard Worker extern "C" void __setcon_shell_code_end();
32*dd0948b3SAndroid Build Coastguard Worker 
33*dd0948b3SAndroid Build Coastguard Worker // Shell code that stops execution of the current process by raising a signal.
34*dd0948b3SAndroid Build Coastguard Worker // The specific signal that is raised is given in __trap_shell_code_signal.
35*dd0948b3SAndroid Build Coastguard Worker //
36*dd0948b3SAndroid Build Coastguard Worker // This shell code can be used to inject break points into a traced process.
37*dd0948b3SAndroid Build Coastguard Worker //
38*dd0948b3SAndroid Build Coastguard Worker // The shell code must not modify any registers other than the program counter.
39*dd0948b3SAndroid Build Coastguard Worker extern "C" void __trap_shell_code_start();
40*dd0948b3SAndroid Build Coastguard Worker extern "C" void __trap_shell_code_end();
41*dd0948b3SAndroid Build Coastguard Worker extern "C" int __trap_shell_code_signal;
42*dd0948b3SAndroid Build Coastguard Worker 
43*dd0948b3SAndroid Build Coastguard Worker namespace shell_as {
44*dd0948b3SAndroid Build Coastguard Worker 
45*dd0948b3SAndroid Build Coastguard Worker namespace {
PageStart(void (* addr)())46*dd0948b3SAndroid Build Coastguard Worker uintptr_t PageStart(void (*addr)()) {
47*dd0948b3SAndroid Build Coastguard Worker   return ((uintptr_t)addr & ~(getpagesize() - 1));
48*dd0948b3SAndroid Build Coastguard Worker }
49*dd0948b3SAndroid Build Coastguard Worker 
EnsureShellcodeReadable(void (* start)(),void (* end)())50*dd0948b3SAndroid Build Coastguard Worker void EnsureShellcodeReadable(void (*start)(), void (*end)()) {
51*dd0948b3SAndroid Build Coastguard Worker   mprotect((void*)PageStart(start),
52*dd0948b3SAndroid Build Coastguard Worker            PageStart(end) - PageStart(start) + getpagesize(),
53*dd0948b3SAndroid Build Coastguard Worker            PROT_READ | PROT_EXEC);
54*dd0948b3SAndroid Build Coastguard Worker }
55*dd0948b3SAndroid Build Coastguard Worker }  // namespace
56*dd0948b3SAndroid Build Coastguard Worker 
GetSELinuxShellCode(char * selinux_context,size_t * total_size)57*dd0948b3SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> GetSELinuxShellCode(
58*dd0948b3SAndroid Build Coastguard Worker     char* selinux_context, size_t* total_size) {
59*dd0948b3SAndroid Build Coastguard Worker   EnsureShellcodeReadable(&__setcon_shell_code_start, &__setcon_shell_code_end);
60*dd0948b3SAndroid Build Coastguard Worker 
61*dd0948b3SAndroid Build Coastguard Worker   size_t shell_code_size = (uintptr_t)&__setcon_shell_code_end -
62*dd0948b3SAndroid Build Coastguard Worker                            (uintptr_t)&__setcon_shell_code_start;
63*dd0948b3SAndroid Build Coastguard Worker   size_t selinux_context_size = strlen(selinux_context) + 1 /* null byte */;
64*dd0948b3SAndroid Build Coastguard Worker   *total_size = shell_code_size + selinux_context_size;
65*dd0948b3SAndroid Build Coastguard Worker 
66*dd0948b3SAndroid Build Coastguard Worker   std::unique_ptr<uint8_t[]> shell_code(new uint8_t[*total_size]);
67*dd0948b3SAndroid Build Coastguard Worker   memcpy(shell_code.get(), (void*)&__setcon_shell_code_start, shell_code_size);
68*dd0948b3SAndroid Build Coastguard Worker   memcpy(shell_code.get() + shell_code_size, selinux_context,
69*dd0948b3SAndroid Build Coastguard Worker          selinux_context_size);
70*dd0948b3SAndroid Build Coastguard Worker   return shell_code;
71*dd0948b3SAndroid Build Coastguard Worker }
72*dd0948b3SAndroid Build Coastguard Worker 
GetTrapShellCode(int * expected_signal,size_t * total_size)73*dd0948b3SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> GetTrapShellCode(int* expected_signal,
74*dd0948b3SAndroid Build Coastguard Worker                                             size_t* total_size) {
75*dd0948b3SAndroid Build Coastguard Worker   EnsureShellcodeReadable(&__trap_shell_code_start, &__trap_shell_code_end);
76*dd0948b3SAndroid Build Coastguard Worker 
77*dd0948b3SAndroid Build Coastguard Worker   *expected_signal = __trap_shell_code_signal;
78*dd0948b3SAndroid Build Coastguard Worker 
79*dd0948b3SAndroid Build Coastguard Worker   *total_size =
80*dd0948b3SAndroid Build Coastguard Worker       (uintptr_t)&__trap_shell_code_end - (uintptr_t)&__trap_shell_code_start;
81*dd0948b3SAndroid Build Coastguard Worker   std::unique_ptr<uint8_t[]> shell_code(new uint8_t[*total_size]);
82*dd0948b3SAndroid Build Coastguard Worker   memcpy(shell_code.get(), (void*)&__trap_shell_code_start, *total_size);
83*dd0948b3SAndroid Build Coastguard Worker   return shell_code;
84*dd0948b3SAndroid Build Coastguard Worker }
85*dd0948b3SAndroid Build Coastguard Worker }  // namespace shell_as
86