linux/tools/testing/selftests/efivarfs/open-unlink.c
<<
>>
Prefs
   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}
 135