open-unlink.c (2252B)
1// SPDX-License-Identifier: GPL-2.0 2#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 else 35 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_ACCESS 84 */ 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}