1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2ed8b0de5SPeter Jones #include <errno.h>
3455ce1c7SJeremy Kerr #include <stdio.h>
4455ce1c7SJeremy Kerr #include <stdint.h>
5455ce1c7SJeremy Kerr #include <stdlib.h>
6455ce1c7SJeremy Kerr #include <unistd.h>
7ed8b0de5SPeter Jones #include <sys/ioctl.h>
8455ce1c7SJeremy Kerr #include <sys/types.h>
9455ce1c7SJeremy Kerr #include <sys/stat.h>
10455ce1c7SJeremy Kerr #include <fcntl.h>
11ed8b0de5SPeter Jones #include <linux/fs.h>
12ed8b0de5SPeter Jones
set_immutable(const char * path,int immutable)13ed8b0de5SPeter Jones static int set_immutable(const char *path, int immutable)
14ed8b0de5SPeter Jones {
15ed8b0de5SPeter Jones unsigned int flags;
16ed8b0de5SPeter Jones int fd;
17ed8b0de5SPeter Jones int rc;
18ed8b0de5SPeter Jones int error;
19ed8b0de5SPeter Jones
20ed8b0de5SPeter Jones fd = open(path, O_RDONLY);
21ed8b0de5SPeter Jones if (fd < 0)
22ed8b0de5SPeter Jones return fd;
23ed8b0de5SPeter Jones
24ed8b0de5SPeter Jones rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
25ed8b0de5SPeter Jones if (rc < 0) {
26ed8b0de5SPeter Jones error = errno;
27ed8b0de5SPeter Jones close(fd);
28ed8b0de5SPeter Jones errno = error;
29ed8b0de5SPeter Jones return rc;
30ed8b0de5SPeter Jones }
31ed8b0de5SPeter Jones
32ed8b0de5SPeter Jones if (immutable)
33ed8b0de5SPeter Jones flags |= FS_IMMUTABLE_FL;
34ed8b0de5SPeter Jones else
35ed8b0de5SPeter Jones flags &= ~FS_IMMUTABLE_FL;
36ed8b0de5SPeter Jones
37ed8b0de5SPeter Jones rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
38ed8b0de5SPeter Jones error = errno;
39ed8b0de5SPeter Jones close(fd);
40ed8b0de5SPeter Jones errno = error;
41ed8b0de5SPeter Jones return rc;
42ed8b0de5SPeter Jones }
43ed8b0de5SPeter Jones
get_immutable(const char * path)44ed8b0de5SPeter Jones static int get_immutable(const char *path)
45ed8b0de5SPeter Jones {
46ed8b0de5SPeter Jones unsigned int flags;
47ed8b0de5SPeter Jones int fd;
48ed8b0de5SPeter Jones int rc;
49ed8b0de5SPeter Jones int error;
50ed8b0de5SPeter Jones
51ed8b0de5SPeter Jones fd = open(path, O_RDONLY);
52ed8b0de5SPeter Jones if (fd < 0)
53ed8b0de5SPeter Jones return fd;
54ed8b0de5SPeter Jones
55ed8b0de5SPeter Jones rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
56ed8b0de5SPeter Jones if (rc < 0) {
57ed8b0de5SPeter Jones error = errno;
58ed8b0de5SPeter Jones close(fd);
59ed8b0de5SPeter Jones errno = error;
60ed8b0de5SPeter Jones return rc;
61ed8b0de5SPeter Jones }
62ed8b0de5SPeter Jones close(fd);
63ed8b0de5SPeter Jones if (flags & FS_IMMUTABLE_FL)
64ed8b0de5SPeter Jones return 1;
65ed8b0de5SPeter Jones return 0;
66ed8b0de5SPeter Jones }
67455ce1c7SJeremy Kerr
main(int argc,char ** argv)68455ce1c7SJeremy Kerr int main(int argc, char **argv)
69455ce1c7SJeremy Kerr {
70455ce1c7SJeremy Kerr const char *path;
71455ce1c7SJeremy Kerr char buf[5];
72455ce1c7SJeremy Kerr int fd, rc;
73455ce1c7SJeremy Kerr
74455ce1c7SJeremy Kerr if (argc < 2) {
75455ce1c7SJeremy Kerr fprintf(stderr, "usage: %s <path>\n", argv[0]);
76455ce1c7SJeremy Kerr return EXIT_FAILURE;
77455ce1c7SJeremy Kerr }
78455ce1c7SJeremy Kerr
79455ce1c7SJeremy Kerr path = argv[1];
80455ce1c7SJeremy Kerr
81455ce1c7SJeremy Kerr /* attributes: EFI_VARIABLE_NON_VOLATILE |
82455ce1c7SJeremy Kerr * EFI_VARIABLE_BOOTSERVICE_ACCESS |
83455ce1c7SJeremy Kerr * EFI_VARIABLE_RUNTIME_ACCESS
84455ce1c7SJeremy Kerr */
85455ce1c7SJeremy Kerr *(uint32_t *)buf = 0x7;
86455ce1c7SJeremy Kerr buf[4] = 0;
87455ce1c7SJeremy Kerr
88455ce1c7SJeremy Kerr /* create a test variable */
89ed8b0de5SPeter Jones fd = open(path, O_WRONLY | O_CREAT, 0600);
90455ce1c7SJeremy Kerr if (fd < 0) {
91455ce1c7SJeremy Kerr perror("open(O_WRONLY)");
92455ce1c7SJeremy Kerr return EXIT_FAILURE;
93455ce1c7SJeremy Kerr }
94455ce1c7SJeremy Kerr
95455ce1c7SJeremy Kerr rc = write(fd, buf, sizeof(buf));
96455ce1c7SJeremy Kerr if (rc != sizeof(buf)) {
97455ce1c7SJeremy Kerr perror("write");
98455ce1c7SJeremy Kerr return EXIT_FAILURE;
99455ce1c7SJeremy Kerr }
100455ce1c7SJeremy Kerr
101455ce1c7SJeremy Kerr close(fd);
102455ce1c7SJeremy Kerr
103ed8b0de5SPeter Jones rc = get_immutable(path);
104ed8b0de5SPeter Jones if (rc < 0) {
105ed8b0de5SPeter Jones perror("ioctl(FS_IOC_GETFLAGS)");
106ed8b0de5SPeter Jones return EXIT_FAILURE;
107ed8b0de5SPeter Jones } else if (rc) {
108ed8b0de5SPeter Jones rc = set_immutable(path, 0);
109ed8b0de5SPeter Jones if (rc < 0) {
110ed8b0de5SPeter Jones perror("ioctl(FS_IOC_SETFLAGS)");
111ed8b0de5SPeter Jones return EXIT_FAILURE;
112ed8b0de5SPeter Jones }
113ed8b0de5SPeter Jones }
114ed8b0de5SPeter Jones
115455ce1c7SJeremy Kerr fd = open(path, O_RDONLY);
116455ce1c7SJeremy Kerr if (fd < 0) {
117455ce1c7SJeremy Kerr perror("open");
118455ce1c7SJeremy Kerr return EXIT_FAILURE;
119455ce1c7SJeremy Kerr }
120455ce1c7SJeremy Kerr
121455ce1c7SJeremy Kerr if (unlink(path) < 0) {
122455ce1c7SJeremy Kerr perror("unlink");
123455ce1c7SJeremy Kerr return EXIT_FAILURE;
124455ce1c7SJeremy Kerr }
125455ce1c7SJeremy Kerr
126455ce1c7SJeremy Kerr rc = read(fd, buf, sizeof(buf));
127455ce1c7SJeremy Kerr if (rc > 0) {
128455ce1c7SJeremy Kerr fprintf(stderr, "reading from an unlinked variable "
129455ce1c7SJeremy Kerr "shouldn't be possible\n");
130455ce1c7SJeremy Kerr return EXIT_FAILURE;
131455ce1c7SJeremy Kerr }
132455ce1c7SJeremy Kerr
133455ce1c7SJeremy Kerr return EXIT_SUCCESS;
134455ce1c7SJeremy Kerr }
135