mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix validation of close_range last fd argument.
The `last` fd argument can be up to max uint32, and some applications call it with this maximum: https://github.com/GNOME/glib/blob/26bc1d08ec574b387ff4bcd919a020a586727bbf/glib/glib-unix.c#L890 PiperOrigin-RevId: 718526878
This commit is contained in:
committed by
gVisor bot
parent
ddfbe0457b
commit
c238e15234
@@ -15,8 +15,6 @@
|
||||
package linux
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fspath"
|
||||
@@ -455,7 +453,7 @@ func CloseRange(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uint
|
||||
last := args[1].Uint()
|
||||
flags := args[2].Uint()
|
||||
|
||||
if (first > last) || (last > math.MaxInt32) {
|
||||
if first > last {
|
||||
return 0, nil, linuxerr.EINVAL
|
||||
}
|
||||
|
||||
@@ -463,6 +461,12 @@ func CloseRange(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uint
|
||||
return 0, nil, linuxerr.EINVAL
|
||||
}
|
||||
|
||||
// close_range allows fd arguments to be up to MaxUint32, but only fds
|
||||
// up to kernel.MaxFdLimit are valid, so cap it here.
|
||||
if last > uint32(kernel.MaxFdLimit) {
|
||||
last = uint32(kernel.MaxFdLimit)
|
||||
}
|
||||
|
||||
cloexec := flags & linux.CLOSE_RANGE_CLOEXEC
|
||||
unshare := flags & linux.CLOSE_RANGE_UNSHARE
|
||||
|
||||
@@ -474,7 +478,7 @@ func CloseRange(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uint
|
||||
if cloexec == 0 && int32(last) >= t.FDTable().GetLastFd() {
|
||||
t.UnshareFdTable(int32(first))
|
||||
} else {
|
||||
t.UnshareFdTable(math.MaxInt32)
|
||||
t.UnshareFdTable(kernel.MaxFdLimit)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -353,6 +353,23 @@ TEST_F(CloseRangeTest, RangeFirstGreaterThanLast) {
|
||||
SyscallFailsWithErrno(EINVAL));
|
||||
}
|
||||
|
||||
// Test that calling with maximum last argument succeeds and closes all fds in
|
||||
// the range.
|
||||
TEST_F(CloseRangeTest, RangeMaxLast) {
|
||||
SKIP_IF(!IsRunningOnGvisor() && close_range(1, 0, 0) < 0 && errno == ENOSYS);
|
||||
int num_files_in_range = 10;
|
||||
unsigned int flags = 0;
|
||||
|
||||
CreateFiles(num_files_in_range);
|
||||
OpenFilesRdwr();
|
||||
|
||||
EXPECT_THAT(close_range(fds_[0], -1, flags), SyscallSucceeds());
|
||||
for (int fd : fds_) {
|
||||
auto ret = ReadAllFd(fd);
|
||||
EXPECT_THAT(ret, PosixErrorIs(EBADF));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that calling with invalid flags does not succeed.
|
||||
TEST_F(CloseRangeTest, InvalidFlags) {
|
||||
SKIP_IF(!IsRunningOnGvisor() && close_range(1, 0, 0) < 0 && errno == ENOSYS);
|
||||
|
||||
Reference in New Issue
Block a user