tun: reject packets larger MTU

Reported-by: syzbot+d82dbadde2cbe70eb6dd@syzkaller.appspotmail.com
PiperOrigin-RevId: 429508995
This commit is contained in:
Andrei Vagin
2022-02-18 01:48:29 -08:00
committed by gVisor bot
parent b413d78c27
commit f51097051a
3 changed files with 50 additions and 0 deletions
+7
View File
@@ -143,6 +143,13 @@ func (fd *tunFD) Write(ctx context.Context, src usermem.IOSequence, opts vfs.Wri
if src.NumBytes() == 0 {
return 0, unix.EINVAL
}
mtu, err := fd.device.MTU()
if err != nil {
return 0, err
}
if int64(mtu) < src.NumBytes() {
return 0, unix.EMSGSIZE
}
data := make([]byte, src.NumBytes())
if _, err := src.CopyIn(ctx, data); err != nil {
return 0, err
+14
View File
@@ -166,6 +166,20 @@ func attachOrCreateNIC(s *stack.Stack, name, prefix string, linkCaps stack.LinkE
}
}
// MTU returns the tun enpoint MTU (maximum transmission unit).
func (d *Device) MTU() (uint32, error) {
d.mu.RLock()
endpoint := d.endpoint
d.mu.RUnlock()
if endpoint == nil {
return 0, linuxerr.EBADFD
}
if !endpoint.IsAttached() {
return 0, linuxerr.EIO
}
return endpoint.MTU(), nil
}
// Write inject one inbound packet to the network interface.
func (d *Device) Write(data []byte) (int64, error) {
d.mu.RLock()
+29
View File
@@ -13,6 +13,7 @@
// limitations under the License.
#include <arpa/inet.h>
#include <asm-generic/errno.h>
#include <linux/capability.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
@@ -414,6 +415,34 @@ TEST_F(TuntapTest, PingKernel) {
}
}
TEST_F(TuntapTest, LargeWritesFailWithEMSGSIZE) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));
const auto& [fd, link] = ASSERT_NO_ERRNO_AND_VALUE(OpenAndAttachTunTap(
kTapName, kTapIPAddr, true /* tap */, false /* no_pi */));
ping_pkt ping_req =
CreatePingPacket(kMacB, kTapPeerIPAddr, kMacA, kTapIPAddr);
std::string arp_rep =
CreateArpPacket(kMacB, kTapPeerIPAddr, kMacA, kTapIPAddr);
constexpr int kBufSize = 4096;
std::vector<char> buf(kBufSize);
struct iovec iov[2] = {
{
.iov_base = &ping_req,
.iov_len = sizeof(ping_req),
},
{
.iov_base = buf.data(),
.iov_len = kBufSize,
},
};
// A packet is large than MTU which is 1500 by default..
EXPECT_THAT(writev(fd.get(), iov, 2), SyscallFailsWithErrno(EMSGSIZE));
}
TEST_F(TuntapTest, SendUdpTriggersArpResolution) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));