Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <errno.h>
0003 #include <stdio.h>
0004 #include <stdint.h>
0005 #include <stdlib.h>
0006 #include <unistd.h>
0007 #include <sys/ioctl.h>
0008 #include <sys/types.h>
0009 #include <sys/stat.h>
0010 #include <fcntl.h>
0011 #include <linux/fs.h>
0012 
0013 static int set_immutable(const char *path, int immutable)
0014 {
0015     unsigned int flags;
0016     int fd;
0017     int rc;
0018     int error;
0019 
0020     fd = open(path, O_RDONLY);
0021     if (fd < 0)
0022         return fd;
0023 
0024     rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
0025     if (rc < 0) {
0026         error = errno;
0027         close(fd);
0028         errno = error;
0029         return rc;
0030     }
0031 
0032     if (immutable)
0033         flags |= FS_IMMUTABLE_FL;
0034     else
0035         flags &= ~FS_IMMUTABLE_FL;
0036 
0037     rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
0038     error = errno;
0039     close(fd);
0040     errno = error;
0041     return rc;
0042 }
0043 
0044 static int get_immutable(const char *path)
0045 {
0046     unsigned int flags;
0047     int fd;
0048     int rc;
0049     int error;
0050 
0051     fd = open(path, O_RDONLY);
0052     if (fd < 0)
0053         return fd;
0054 
0055     rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
0056     if (rc < 0) {
0057         error = errno;
0058         close(fd);
0059         errno = error;
0060         return rc;
0061     }
0062     close(fd);
0063     if (flags & FS_IMMUTABLE_FL)
0064         return 1;
0065     return 0;
0066 }
0067 
0068 int main(int argc, char **argv)
0069 {
0070     const char *path;
0071     char buf[5];
0072     int fd, rc;
0073 
0074     if (argc < 2) {
0075         fprintf(stderr, "usage: %s <path>\n", argv[0]);
0076         return EXIT_FAILURE;
0077     }
0078 
0079     path = argv[1];
0080 
0081     /* attributes: EFI_VARIABLE_NON_VOLATILE |
0082      *      EFI_VARIABLE_BOOTSERVICE_ACCESS |
0083      *      EFI_VARIABLE_RUNTIME_ACCESS
0084      */
0085     *(uint32_t *)buf = 0x7;
0086     buf[4] = 0;
0087 
0088     /* create a test variable */
0089     fd = open(path, O_WRONLY | O_CREAT, 0600);
0090     if (fd < 0) {
0091         perror("open(O_WRONLY)");
0092         return EXIT_FAILURE;
0093     }
0094 
0095     rc = write(fd, buf, sizeof(buf));
0096     if (rc != sizeof(buf)) {
0097         perror("write");
0098         return EXIT_FAILURE;
0099     }
0100 
0101     close(fd);
0102 
0103     rc = get_immutable(path);
0104     if (rc < 0) {
0105         perror("ioctl(FS_IOC_GETFLAGS)");
0106         return EXIT_FAILURE;
0107     } else if (rc) {
0108         rc = set_immutable(path, 0);
0109         if (rc < 0) {
0110             perror("ioctl(FS_IOC_SETFLAGS)");
0111             return EXIT_FAILURE;
0112         }
0113     }
0114 
0115     fd = open(path, O_RDONLY);
0116     if (fd < 0) {
0117         perror("open");
0118         return EXIT_FAILURE;
0119     }
0120 
0121     if (unlink(path) < 0) {
0122         perror("unlink");
0123         return EXIT_FAILURE;
0124     }
0125 
0126     rc = read(fd, buf, sizeof(buf));
0127     if (rc > 0) {
0128         fprintf(stderr, "reading from an unlinked variable "
0129                 "shouldn't be possible\n");
0130         return EXIT_FAILURE;
0131     }
0132 
0133     return EXIT_SUCCESS;
0134 }