/* * Copyright (C) 2023 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. */ // Shell code that sets the current SELinux context to a given string. // // The desired SELinux context is appended to the payload as a null-terminated // string. // // After the SELinux context has been updated the current process will raise // SIGSTOP. #include "./shell-code/constants.S" #include "./shell-code/constants-x86.S" .globl __setcon_shell_code_start .globl __setcon_shell_code_end __setcon_shell_code_start: // x86 does not have RIP relative addressing. To work around this, relative // calls are used to obtain the runtime address of a label. Once the location // of one label is known, other labels can be addressed relative to the known // label. call constant_relative_address constant_relative_address: pop %esi // Ensure that the context and SELinux /proc file are readable. This assumes // that the max length of these two strings is shorter than 0x1000. // // mprotect(context & ~0xFFF, 0x2000, PROT_READ | PROT_EXEC) mov $SYS_MPROTECT, %eax mov $~0xFFF, %ebx and %esi, %ebx mov $0x2000, %ecx mov $(PROT_READ | PROT_EXEC), %edx int $0x80 // ebx = open("/proc/self/attr/current", O_WRONLY, O_WRONLY) mov $SYS_OPEN, %eax lea (selinux_proc_file - constant_relative_address)(%esi), %ebx mov $O_WRONLY, %ecx mov $O_WRONLY, %edx int $0x80 mov %eax, %ebx // write(ebx, context, strlen(context)) xor %edx, %edx leal (context - constant_relative_address)(%esi), %ecx strlen_start: movb (%ecx, %edx), %al test %al, %al jz strlen_done inc %edx jmp strlen_start strlen_done: mov $SYS_WRITE, %eax int $0x80 // close(ebx) mov $SYS_CLOSE, %eax int $0x80 // ebx = getpid() mov $SYS_GETPID, %eax int $0x80 mov %eax, %ebx // kill(ebx, SIGSTOP) mov $SYS_KILL, %eax mov $SIGSTOP, %ecx int $0x80 selinux_proc_file: .asciz "/proc/self/attr/current" context: __setcon_shell_code_end: