NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/60486: tcp syncache leaks 4-byte kernel stack content



>Number:         60486
>Category:       kern
>Synopsis:       tcp syncache leaks 4-byte kernel stack content
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jul 23 17:40:00 +0000 2026
>Originator:     Taylor R Campbell
>Release:        current, 11, 10, 9, ...
>Organization:
The NetTCP Leakstacktion, Inc.
>Environment:
>Description:

	The tcp syncache logic can leak a four-byte section of kernel
	stack memory to the network.

    877 syn_cache_add(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
    878     unsigned int toff, struct socket *so, struct mbuf *m, u_char *optp,
    879     int optlen, struct tcp_opt_info *oi)
    880 {
    881 	struct tcpcb tb, *tp;
...
    897 #ifdef TCP_SIGNATURE
    898 	if (optp || (tp->t_flags & TF_SIGNATURE))
    899 #else
    900 	if (optp)
    901 #endif
    902 	{
    903 		tb.t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
    904 #ifdef TCP_SIGNATURE
    905 		tb.t_flags |= (tp->t_flags & TF_SIGNATURE);
    906 #endif
    907 		tb.t_state = TCPS_LISTEN;
    908 		if (tcp_dooptions(&tb, optp, optlen, th, m, toff, oi) < 0)
    909 			return 0;
    910 	} else
    911 		tb.t_flags = 0;
...
    938 		sc->sc_timestamp = tb.ts_recent;
...
    940 		if (syn_cache_respond(sc) == 0) {

https://nxr.netbsd.org/xref/src/sys/netinet/tcp_syncache.c#863

	Not all paths to

    938 		sc->sc_timestamp = tb.ts_recent;

	initialize tb.ts_recent, so it may be uninitialized data from
	the kernel stack.  This may be then sent out on the wire in
	syn_cache_respond:

   1075 syn_cache_respond(struct syn_cache *sc)
   1076 {
...
   1115 	/*
   1116 	 * Create the IP+TCP header from scratch.
   1117 	 */
   1118 	MGETHDR(m, M_DONTWAIT, MT_DATA);
...
   1172 	optp = (u_int8_t *)(th + 1);
...
   1138 	case AF_INET:
   1139 		ip = mtod(m, struct ip *);
...
   1144 		th = (struct tcphdr *)(ip + 1);
...
   1149 	case AF_INET6:
   1150 		ip6 = mtod(m, struct ip6_hdr *);
...
   1156 		th = (struct tcphdr *)(ip6 + 1);
...
   1172 	optp = (u_int8_t *)(th + 1);
...
   1195 	if (sc->sc_flags & SCF_TIMESTAMP) {
...
   1202 		u_int32_t *lp = (u_int32_t *)(optp);
...
=> 1205 		*lp   = htonl(sc->sc_timestamp);
...
   1208 	}
...
   1337 	case AF_INET:
   1338 		error = ip_output(m, sc->sc_ipopts, ro,
...
   1348 		error = ip6_output(m, NULL /*XXX*/, ro, 0, NULL,

https://nxr.netbsd.org/xref/src/sys/netinet/tcp_syncache.c#1068

	Forwarded to us by Chris Jarrett-Davies <chrisjd%openai.com@localhost>.

>How-To-Repeat:

	do a retransmitted SYN/ACK dance with syncache

>Fix:

	memset(&tb, 0, sizeof(tb)) will rule it out, at some cost to
	performance under load, since this is a ~800-byte structure.

	Could try to be more selective about initialization, or about
	when we set sc->sc_timestamp = tb.ts_recent.n




Home | Main Index | Thread Index | Old Index