Skip to content

Commit 16add32

Browse files
osandovkdave
authored andcommitted
libbtrfsutil: fix accidentally closing fd passed to subvolume iterator
For an unprivileged subvolume iterator, append_to_search_stack() closes cur_fd. On the first call to btrfs_util_subvolume_iterator_next(), cur_fd is equal to the fd that was passed to btrfs_util_create_subvolume_iterator_fd(). We're not supposed to close that. We didn't notice it because it's more common to use it through btrfs_util_create_subvolume_iterator(), which opens its own fd that should be closed, and because the fd number is often reused internally by the subvolume iterator. pop_search_stack() already has a check to avoid closing the passed fd; add the same check to append_to_search_stack(). Also add a regression test. Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent d1f27c6 commit 16add32

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

libbtrfsutil/python/tests/test_subvolume.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,3 +561,21 @@ def test_subvolume_iterator_race_unprivileged(self):
561561
self._test_subvolume_iterator_race()
562562
finally:
563563
os.chdir(pwd)
564+
565+
def test_subvolume_iterator_fd_unprivileged(self):
566+
pwd = os.getcwd()
567+
try:
568+
os.chdir(self.mountpoint)
569+
btrfsutil.create_subvolume('subvol')
570+
with drop_privs():
571+
fd = os.open('.', os.O_RDONLY | os.O_DIRECTORY)
572+
try:
573+
with btrfsutil.SubvolumeIterator(fd) as it:
574+
for _ in it:
575+
break
576+
finally:
577+
# A bug in SubvolumeIterator previously made it close the
578+
# passed in fd, so this would fail with EBADF.
579+
os.close(fd)
580+
finally:
581+
os.chdir(pwd)

libbtrfsutil/subvolume.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,8 @@ static enum btrfs_util_error append_to_search_stack(struct btrfs_util_subvolume_
930930
return err;
931931
}
932932

933-
close(iter->cur_fd);
933+
if (iter->cur_fd != iter->fd)
934+
close(iter->cur_fd);
934935
iter->cur_fd = fd;
935936
}
936937
}

0 commit comments

Comments
 (0)