Home | History | Annotate | Download | only in efivarfs
      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 
     13 static 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 
     44 static 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 
     68 int 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 }
    135