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