// SPDX-License-Identifier: BSD-3-Clause /* * Simple tool to set SECBIT_EXEC_RESTRICT_FILE, SECBIT_EXEC_DENY_INTERACTIVE, * before executing a command. * * Copyright © 2024 Microsoft Corporation */ #define _GNU_SOURCE #define __SANE_USERSPACE_TYPES__ #include #include #include #include #include #include #include #include #include static void print_usage(const char *argv0) { fprintf(stderr, "usage: %s -f|-i -- [args]...\n\n", argv0); fprintf(stderr, "Execute a command with\n"); fprintf(stderr, "- SECBIT_EXEC_RESTRICT_FILE set: -f\n"); fprintf(stderr, "- SECBIT_EXEC_DENY_INTERACTIVE set: -i\n"); } int main(const int argc, char *const argv[], char *const *const envp) { const char *cmd_path; char *const *cmd_argv; int opt, secbits_cur, secbits_new; bool has_policy = false; secbits_cur = prctl(PR_GET_SECUREBITS); if (secbits_cur == -1) { /* * This should never happen, except with a buggy seccomp * filter. */ perror("ERROR: Failed to get securebits"); return 1; } secbits_new = secbits_cur; while ((opt = getopt(argc, argv, "fi")) != -1) { switch (opt) { case 'f': secbits_new |= SECBIT_EXEC_RESTRICT_FILE | SECBIT_EXEC_RESTRICT_FILE_LOCKED; has_policy = true; break; case 'i': secbits_new |= SECBIT_EXEC_DENY_INTERACTIVE | SECBIT_EXEC_DENY_INTERACTIVE_LOCKED; has_policy = true; break; default: print_usage(argv[0]); return 1; } } if (!argv[optind] || !has_policy) { print_usage(argv[0]); return 1; } if (secbits_cur != secbits_new && prctl(PR_SET_SECUREBITS, secbits_new)) { perror("Failed to set secure bit(s)."); fprintf(stderr, "Hint: The running kernel may not support this feature.\n"); return 1; } cmd_path = argv[optind]; cmd_argv = argv + optind; fprintf(stderr, "Executing command...\n"); execvpe(cmd_path, cmd_argv, envp); fprintf(stderr, "Failed to execute \"%s\": %s\n", cmd_path, strerror(errno)); return 1; }