]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic: Make sure we're extra paranoid in chattr_full
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 3 Dec 2021 10:07:02 +0000 (11:07 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 6 Dec 2021 21:17:40 +0000 (22:17 +0100)
On btrfs, trying to disable FS_NOCOW_FL on a file that has data
already written will fail silently without reporting an error. To
catch such cases, let's query the flags again if the IOC_SETFLAGS
ioctl() succeeds to make sure the flags we tried to configure we're
actually accepted by the kernel.

src/basic/chattr-util.c

index 59707a79c07905062cf03ce196f474a667688985..807288a6498f741d2ab7baae15a3d4617d104b25 100644 (file)
@@ -59,11 +59,25 @@ int chattr_full(const char *path,
         }
 
         if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) >= 0) {
-                if (ret_previous)
-                        *ret_previous = old_attr;
-                if (ret_final)
-                        *ret_final = new_attr;
-                return 1;
+                unsigned attr;
+
+                /* Some filesystems (BTRFS) silently fail when a flag cannot be set. Let's make sure our
+                 * changes actually went through by querying the flags again and verifying they're equal to
+                 * the flags we tried to configure. */
+
+                if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
+                        return -errno;
+
+                if (new_attr == attr) {
+                        if (ret_previous)
+                                *ret_previous = old_attr;
+                        if (ret_final)
+                                *ret_final = new_attr;
+                        return 1;
+                }
+
+                /* Trigger the fallback logic. */
+                errno = EINVAL;
         }
 
         if ((errno != EINVAL && !ERRNO_IS_NOT_SUPPORTED(errno)) ||