135 lines · c
1// SPDX-License-Identifier: GPL-2.02#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 13static 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 else35 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 44static 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 68int 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_ACCESS84 */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