1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Simple tool to set SECBIT_EXEC_RESTRICT_FILE, SECBIT_EXEC_DENY_INTERACTIVE, 4 * before executing a command. 5 * 6 * Copyright © 2024 Microsoft Corporation 7 */ 8 9 #define _GNU_SOURCE 10 #define __SANE_USERSPACE_TYPES__ 11 #include <errno.h> 12 #include <linux/prctl.h> 13 #include <linux/securebits.h> 14 #include <stdbool.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <sys/prctl.h> 19 #include <unistd.h> 20 21 static void print_usage(const char *argv0) 22 { 23 fprintf(stderr, "usage: %s -f|-i -- <cmd> [args]...\n\n", argv0); 24 fprintf(stderr, "Execute a command with\n"); 25 fprintf(stderr, "- SECBIT_EXEC_RESTRICT_FILE set: -f\n"); 26 fprintf(stderr, "- SECBIT_EXEC_DENY_INTERACTIVE set: -i\n"); 27 } 28 29 int main(const int argc, char *const argv[], char *const *const envp) 30 { 31 const char *cmd_path; 32 char *const *cmd_argv; 33 int opt, secbits_cur, secbits_new; 34 bool has_policy = false; 35 36 secbits_cur = prctl(PR_GET_SECUREBITS); 37 if (secbits_cur == -1) { 38 /* 39 * This should never happen, except with a buggy seccomp 40 * filter. 41 */ 42 perror("ERROR: Failed to get securebits"); 43 return 1; 44 } 45 46 secbits_new = secbits_cur; 47 while ((opt = getopt(argc, argv, "fi")) != -1) { 48 switch (opt) { 49 case 'f': 50 secbits_new |= SECBIT_EXEC_RESTRICT_FILE | 51 SECBIT_EXEC_RESTRICT_FILE_LOCKED; 52 has_policy = true; 53 break; 54 case 'i': 55 secbits_new |= SECBIT_EXEC_DENY_INTERACTIVE | 56 SECBIT_EXEC_DENY_INTERACTIVE_LOCKED; 57 has_policy = true; 58 break; 59 default: 60 print_usage(argv[0]); 61 return 1; 62 } 63 } 64 65 if (!argv[optind] || !has_policy) { 66 print_usage(argv[0]); 67 return 1; 68 } 69 70 if (secbits_cur != secbits_new && 71 prctl(PR_SET_SECUREBITS, secbits_new)) { 72 perror("Failed to set secure bit(s)."); 73 fprintf(stderr, 74 "Hint: The running kernel may not support this feature.\n"); 75 return 1; 76 } 77 78 cmd_path = argv[optind]; 79 cmd_argv = argv + optind; 80 fprintf(stderr, "Executing command...\n"); 81 execvpe(cmd_path, cmd_argv, envp); 82 fprintf(stderr, "Failed to execute \"%s\": %s\n", cmd_path, 83 strerror(errno)); 84 return 1; 85 } 86