forked from Mirrors/btrfs-progs
Btrfs-progs: fix mount point detection due to partial prefix match
When attempting to find the mount point of a path we can end up returning an incorrect mount point. This happens because we consider a mount point valid for the given path even if it only partially matches the path. Consider the following example, which makes btrfs receive fail: $ truncate -s 1G disk1 $ truncate -s 1G disk2 $ losetup /dev/loop1 disk1 $ losetup /dev/loop2 disk2 $ mkfs.btrfs -f /dev/loop1 $ mkfs.btrfs -f /dev/loop2 $ mount /dev/loop1 /mnt $ mkdir /mnt/ddis $ mkdir /mnt/ddis-not-a-mount $ mount /dev/loop2 /mnt/ddis $ echo "some data" > /mnt/ddis/file $ btrfs subvolume snapshot -r /mnt/ddis /mnt/ddis/snap $ btrfs send -f /tmp/send.data /mnt/ddis/snap $ btrfs receive -f /tmp/send.data /mnt/ddis-not-a-mount At subvol snap ERROR: chown failed: No such file or directory In that example btrfs receive passes the path "/mnt/ddis-not-a-mount" to find_mount_root() which picks "/mnt/ddis" as the mount point instead of "/mnt". The wrong decision happens because "/mnt/ddis" is the longest string found that is a prefix of "/mnt/ddis-not-a-mount", however it shouldn't be considered valid because what follows the substring "ddis" in the given path is not a path separator ("/") nor the null character ('\0'). So fix find_mount_root() to check for the presence of a path separator or a null byte character after if finds a mount point string that matches the given path. A test case will follow soon in a separate patch. Reported-by: David Disseldorp <ddiss@suse.com> Reviewed-by: David Disseldorp <ddiss@suse.de> Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>master
parent
5c880c82c2
commit
cb8abddb20
3
utils.c
3
utils.c
|
@ -2078,7 +2078,8 @@ int find_mount_root(const char *path, char **mount_root)
|
|||
|
||||
while ((ent = getmntent(mnttab))) {
|
||||
len = strlen(ent->mnt_dir);
|
||||
if (strncmp(ent->mnt_dir, path, len) == 0) {
|
||||
if (strncmp(ent->mnt_dir, path, len) == 0 &&
|
||||
(path[len] == '/' || path[len] == '\0')) {
|
||||
/* match found and use the latest match */
|
||||
if (longest_matchlen <= len) {
|
||||
free(longest_match);
|
||||
|
|
Loading…
Reference in New Issue