0001
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
0082
0083
0084
0085 *(uint32_t *)buf = 0x7;
0086 buf[4] = 0;
0087
0088
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 }