From: Lennart Poettering Date: Wed, 4 Oct 2017 11:48:51 +0000 (+0200) Subject: btrfs-util: when opening subvolume fds, always set O_NOFOLLOW X-Git-Tag: v236~280^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f7c9f4a2a9bdb476b6b0e0e88291fa8d5e9fc0de;p=thirdparty%2Fsystemd.git btrfs-util: when opening subvolume fds, always set O_NOFOLLOW Some of the btrfs utility functions already used O_NOFOLLOW others didn't. Let's streamline this, and refuse operation when we are called for symlinks on "remove" and "snapshot" too. In particular in the "remove" case following symlinks is a bad idea, and is quite different from how unlink() and friends work, which always remove the symlink, and not the destination, a logic we should follow here too. --- diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index c2061addd17..783ff13a361 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -1212,7 +1212,7 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol if (!S_ISDIR(st.st_mode)) return -EINVAL; - subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); if (subvol_fd < 0) return -errno; @@ -1292,7 +1292,7 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol * hence we need to open the * containing directory first */ - child_fd = openat(subvol_fd, ino_args.name, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + child_fd = openat(subvol_fd, ino_args.name, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); if (child_fd < 0) return -errno; @@ -1641,7 +1641,7 @@ static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolum if (!c) return -ENOMEM; - old_child_fd = openat(old_fd, c, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + old_child_fd = openat(old_fd, c, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); if (old_child_fd < 0) return -errno; @@ -1649,7 +1649,7 @@ static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolum if (!np) return -ENOMEM; - new_child_fd = openat(new_fd, np, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + new_child_fd = openat(new_fd, np, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); if (new_child_fd < 0) return -errno; @@ -1660,7 +1660,7 @@ static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolum * into place. */ if (subvolume_fd < 0) { - subvolume_fd = openat(new_fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + subvolume_fd = openat(new_fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); if (subvolume_fd < 0) return -errno; }