open-unlink.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <errno.h>
  3. #include <stdio.h>
  4. #include <stdint.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #include <linux/fs.h>
  12. static int set_immutable(const char *path, int immutable)
  13. {
  14. unsigned int flags;
  15. int fd;
  16. int rc;
  17. int error;
  18. fd = open(path, O_RDONLY);
  19. if (fd < 0)
  20. return fd;
  21. rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
  22. if (rc < 0) {
  23. error = errno;
  24. close(fd);
  25. errno = error;
  26. return rc;
  27. }
  28. if (immutable)
  29. flags |= FS_IMMUTABLE_FL;
  30. else
  31. flags &= ~FS_IMMUTABLE_FL;
  32. rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
  33. error = errno;
  34. close(fd);
  35. errno = error;
  36. return rc;
  37. }
  38. static int get_immutable(const char *path)
  39. {
  40. unsigned int flags;
  41. int fd;
  42. int rc;
  43. int error;
  44. fd = open(path, O_RDONLY);
  45. if (fd < 0)
  46. return fd;
  47. rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
  48. if (rc < 0) {
  49. error = errno;
  50. close(fd);
  51. errno = error;
  52. return rc;
  53. }
  54. close(fd);
  55. if (flags & FS_IMMUTABLE_FL)
  56. return 1;
  57. return 0;
  58. }
  59. int main(int argc, char **argv)
  60. {
  61. const char *path;
  62. char buf[5];
  63. int fd, rc;
  64. if (argc < 2) {
  65. fprintf(stderr, "usage: %s <path>\n", argv[0]);
  66. return EXIT_FAILURE;
  67. }
  68. path = argv[1];
  69. /* attributes: EFI_VARIABLE_NON_VOLATILE |
  70. * EFI_VARIABLE_BOOTSERVICE_ACCESS |
  71. * EFI_VARIABLE_RUNTIME_ACCESS
  72. */
  73. *(uint32_t *)buf = 0x7;
  74. buf[4] = 0;
  75. /* create a test variable */
  76. fd = open(path, O_WRONLY | O_CREAT, 0600);
  77. if (fd < 0) {
  78. perror("open(O_WRONLY)");
  79. return EXIT_FAILURE;
  80. }
  81. rc = write(fd, buf, sizeof(buf));
  82. if (rc != sizeof(buf)) {
  83. perror("write");
  84. return EXIT_FAILURE;
  85. }
  86. close(fd);
  87. rc = get_immutable(path);
  88. if (rc < 0) {
  89. perror("ioctl(FS_IOC_GETFLAGS)");
  90. return EXIT_FAILURE;
  91. } else if (rc) {
  92. rc = set_immutable(path, 0);
  93. if (rc < 0) {
  94. perror("ioctl(FS_IOC_SETFLAGS)");
  95. return EXIT_FAILURE;
  96. }
  97. }
  98. fd = open(path, O_RDONLY);
  99. if (fd < 0) {
  100. perror("open");
  101. return EXIT_FAILURE;
  102. }
  103. if (unlink(path) < 0) {
  104. perror("unlink");
  105. return EXIT_FAILURE;
  106. }
  107. rc = read(fd, buf, sizeof(buf));
  108. if (rc > 0) {
  109. fprintf(stderr, "reading from an unlinked variable "
  110. "shouldn't be possible\n");
  111. return EXIT_FAILURE;
  112. }
  113. return EXIT_SUCCESS;
  114. }