NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/60488: nd6: two-byte buffer overread in source/target linkaddr options
>Number: 60488
>Category: kern
>Synopsis: nd6: two-byte buffer overread in source/target linkaddr options
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jul 23 19:35:00 +0000 2026
>Originator: Taylor R Campbell
>Release: current, 11, 10, 9, ...
>Organization:
The NeighBSD Discoverflow, Inc.
>Environment:
>Description:
In both nd6_ns_input and nd6_na_input, the option length in
struct nd_opt_hdr::nd_opt_len is taken to be the length of the
payload _excluding_ the headder, but what the protocol
specifies, and what is verified in nd6.c, is that nd_opt_len is
the length of the whole option _including_ the header:
185 if (ndopts.nd_opts_src_lladdr) {
186 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
187 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
188 }
https://nxr.netbsd.org/xref/src/sys/netinet6/nd6_nbr.c?r=1.186#185
678 if (ndopts.nd_opts_tgt_lladdr != NULL) {
679 struct ifnet *ifp_ll;
680 struct psref psref_ll;
681
682 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
683 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
https://nxr.netbsd.org/xref/src/sys/netinet6/nd6_nbr.c?r=1.186#678
This lladdrlen is later used as a source buffer size for
sockaddr_dl_init:
322 if (lladdr != NULL)
323 sdlp = sockaddr_dl_init(&sdl, sizeof(sdl),
324 ifp->if_index, ifp->if_type,
325 NULL, 0, lladdr, lladdrlen);
https://nxr.netbsd.org/xref/src/sys/netinet6/nd6_nbr.c?r=1.186#322
716 if (lladdr != NULL)
717 sdlp = sockaddr_dl_init(&sdl, sizeof(sdl),
718 ifp->if_index, ifp->if_type,
719 NULL, 0, lladdr, lladdrlen);
https://nxr.netbsd.org/xref/src/sys/netinet6/nd6_nbr.c?r=1.186#716
That can lead sockaddr_dl_init to read past the verified end of
the option buffer by two bytes.
Note: The ND_OPT_TARGET_LINKADDR case appears to check the
lladdrlen against ((ifp->if_addrlen + 2 + 7) & ~7) exactly, so
there is probably no overread in that case.
>How-To-Repeat:
convince NetBSD to process an nd6 packet with
ND_OPT_TARGET_LINKADDR
>Fix:
subtract two from lladdrlen
Home |
Main Index |
Thread Index |
Old Index