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>
This commit is contained in:
parent
4e95d7d028
commit
e3e10fc8c6
|
@ -561,3 +561,21 @@ class TestSubvolume(BtrfsTestCase):
|
|||
self._test_subvolume_iterator_race()
|
||||
finally:
|
||||
os.chdir(pwd)
|
||||
|
||||
def test_subvolume_iterator_fd_unprivileged(self):
|
||||
pwd = os.getcwd()
|
||||
try:
|
||||
os.chdir(self.mountpoint)
|
||||
btrfsutil.create_subvolume('subvol')
|
||||
with drop_privs():
|
||||
fd = os.open('.', os.O_RDONLY | os.O_DIRECTORY)
|
||||
try:
|
||||
with btrfsutil.SubvolumeIterator(fd) as it:
|
||||
for _ in it:
|
||||
break
|
||||
finally:
|
||||
# A bug in SubvolumeIterator previously made it close the
|
||||
# passed in fd, so this would fail with EBADF.
|
||||
os.close(fd)
|
||||
finally:
|
||||
os.chdir(pwd)
|
||||
|
|
|
@ -930,7 +930,8 @@ static enum btrfs_util_error append_to_search_stack(struct btrfs_util_subvolume_
|
|||
return err;
|
||||
}
|
||||
|
||||
close(iter->cur_fd);
|
||||
if (iter->cur_fd != iter->fd)
|
||||
close(iter->cur_fd);
|
||||
iter->cur_fd = fd;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue