mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix SIOCGIFCONF in hostinet
Add a syscall test with a bad nested pointer. The implementation properly copies out a sentry buffer. PiperOrigin-RevId: 421847766
This commit is contained in:
@@ -97,10 +97,24 @@ func ioctl(ctx context.Context, fd int, io usermem.IO, args arch.SyscallArgument
|
||||
if _, err := ifc.CopyIn(cc, args[2].Pointer()); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// TODO(b/209503078): Check ifc.Ptr range is in untrusted range.
|
||||
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(&ifc))); errno != 0 {
|
||||
|
||||
// The user's ifconf can have a nullable pointer to a buffer. Use a Sentry array if non-null.
|
||||
ifcNested := linux.IFConf{Len: ifc.Len}
|
||||
var ifcBuf []byte
|
||||
if ifc.Ptr != 0 {
|
||||
ifcBuf = make([]byte, ifc.Len)
|
||||
ifcNested.Ptr = uint64(uintptr(unsafe.Pointer(&ifcBuf[0])))
|
||||
}
|
||||
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(&ifcNested))); errno != 0 {
|
||||
return 0, translateIOSyscallError(errno)
|
||||
}
|
||||
// Copy out the buffer if it was non-null.
|
||||
if ifc.Ptr != 0 {
|
||||
if _, err := cc.CopyOutBytes(hostarch.Addr(ifc.Ptr), ifcBuf); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
ifc.Len = ifcNested.Len
|
||||
_, err := ifc.CopyOut(cc, args[2].Pointer())
|
||||
return 0, err
|
||||
case linux.SIOCETHTOOL:
|
||||
|
||||
@@ -241,6 +241,7 @@ syscall_test(
|
||||
|
||||
syscall_test(
|
||||
size = "medium",
|
||||
add_hostinet = True,
|
||||
add_overlay = True,
|
||||
test = "//test/syscalls/linux:ioctl_test",
|
||||
)
|
||||
|
||||
@@ -350,6 +350,22 @@ TEST_P(IoctlTestSIOCGIFCONF, ValidateNoPartialIfrsReturned) {
|
||||
ASSERT_NE(ifr.ifr_name[0], '\0'); // An interface can now be returned.
|
||||
}
|
||||
|
||||
// This test validates that nested pointers aren't allowed to escape the
|
||||
// address space.
|
||||
TEST_P(IoctlTestSIOCGIFCONF, ValidateNestedPointerCheck) {
|
||||
auto fd = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
|
||||
|
||||
struct ifconf ifconf = {};
|
||||
ifconf.ifc_len = sizeof(ifreq);
|
||||
// Address chosen with ASLR disabled, pausing here, and inspecting the
|
||||
// process with /proc/<pid>/maps to find a writable mapping in the low range
|
||||
// of gr0 memory.
|
||||
ifconf.ifc_ifcu.ifcu_req = reinterpret_cast<ifreq*>(0x3f9000d51000);
|
||||
|
||||
ASSERT_THAT(ioctl(fd->get(), SIOCGIFCONF, &ifconf),
|
||||
SyscallFailsWithErrno(EFAULT));
|
||||
}
|
||||
|
||||
TEST_P(IoctlTestSIOCGIFCONF, ValidateLoopbackIsPresent) {
|
||||
auto fd = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user