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