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
set_immutable(const char * path,int immutable)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
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
get_immutable(const char * path)43 static 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
main(int argc,char ** argv)67 int 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