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