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