set-exec.c 2.0 KB

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