[Bug 271820] libalias's AliasHandleQuestion() can run off the end of a ppp packet

From: <bugzilla-noreply_at_freebsd.org>
Date: Sun, 04 Jun 2023 15:08:13 UTC

            Bug ID: 271820
           Summary: libalias's AliasHandleQuestion() can run off the end
                    of a ppp packet
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: bin
          Assignee: bugs@FreeBSD.org
          Reporter: rtm@lcs.mit.edu
 Attachment #242592 text/plain
         mime type:

Created attachment 242592
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=242592&action=edit
send ppp -nat a packet that causes AliasHandleQuestion() to run off the end of
a buffer

I've attached a program which sends a short packet into ppp -nat, UDP, sport
137 (NetBios NS). The IP and UDP headers that libalias sees:

(gdb) print/x *pip
$26 = {ip_hl = 0x0, ip_v = 0x0, ip_tos = 0x89, ip_len = 0x4600, ip_id = 0xffff,
ip_off = 0xe0, ip_ttl = 0xff, ip_p = 0x11, ip_sum = 0xff7f, ip_src = {
    s_addr = 0xffffff7f}, ip_dst = {s_addr = 0x7fff7fff}}
(gdb) print/x *uh
$27 = {uh_sport = 0x8900, uh_dport = 0x4600, uh_ulen = 0xffff, uh_sum = 0xe0}

What ultimately happens is that libalias/alias_nbt.c's
AliasHandleQuestion() thinks the UDP packet is 65536 bytes long, due
to uh_ulen, but the actual packet buffer is only 70 bytes long, so
AliasHandleQuestion() reads off the end of the packet. That can cause
ppp to crash, though it doesn't always.

ValidateUdpLength() doesn't reject the crazy uh_ulen because the IP_MF
flag is set in ip_off.

LibAliasInLocked() doesn't reject the crazy ip_hl of zero; it only
checks for ip_hl too large.

To see this with the attached program:

# cc -g ppp2b.c
# gdb a.out
(gdb) set follow-fork-mode child
(gdb) catch exec
(gdb) run
(gdb) break AliasHandleQuestion
(gdb) c
(gdb) print (char*)pmax - (char*)q
$1 = 65515
(gdb) up
(gdb) print/x pip->ip_len
$2 = 0x4600
*** 65515 is much bigger than the packet ***
(gdb) where
#0  AliasHandleQuestion (count=32767, q=0x801c7114c, pmax=0x801c81137 "",
nbtarg=<optimized out>) at /usr/src/sys/netinet/libalias/alias_nbt.c:426
#1  AliasHandleUdpNbtNS (la=<optimized out>, pip=0x801c71138, lnk=<optimized
out>, alias_address=<optimized out>, alias_port=<optimized out>,
original_address=<optimized out>, 
    original_port=0x801c7113a) at /usr/src/sys/netinet/libalias/alias_nbt.c:807
#2  0x00000008010d0ccf in protohandler2in (la=<optimized out>, pip=0x801c71138,
ah=<optimized out>) at /usr/src/sys/netinet/libalias/alias_nbt.c:114
#3  0x00000008011306b5 in UdpAliasIn (la=la@entry=0x801c1a000,
pip=pip@entry=0x801c71138) at /usr/src/sys/netinet/libalias/alias.c:786
#4  0x000000080112f93c in LibAliasInLocked (la=0x801c1a000,
pip=pip@entry=0x801c71138, maxpacketsize=<optimized out>) at
#5  0x000000080112f787 in LibAliasIn (la=0x801c71138, ptr=0x7fff,
ptr@entry=0x801c71138, maxpacketsize=0) at
#6  0x0000000001088452 in nat_LayerPull (bundle=0x10974b0
<bundle_Create.bundle>, l=<optimized out>, bp=0x801c71100, proto=<optimized
out>) at /usr/src/usr.sbin/ppp/nat_cmd.c:532
#7  0x0000000001070ff4 in link_PullPacket (l=0x801c4d600, buf=<optimized out>,
len=<optimized out>, b=0x10974b0 <bundle_Create.bundle>) at
#8  0x000000000104ae25 in bundle_DescriptorRead (d=<optimized out>,
bundle=0x10974b0 <bundle_Create.bundle>, fdset=0x801c78140) at
#9  0x0000000001074704 in DoLoop (bundle=0x10974b0 <bundle_Create.bundle>) at
#10 main (argc=3, argv=<optimized out>) at /usr/src/usr.sbin/ppp/main.c:535

You are receiving this mail because:
You are the assignee for the bug.