Date: Sun, 18 Feb 2001 21:49:00 +0100 (CET) From: Jesper Skriver <jesper@skriver.dk> To: FreeBSD-gnats-submit@freebsd.org Subject: kern/25195: security update to sys/netinet/in_pcb.c:in_pcbnotify Message-ID: <200102182049.f1IKn0B00683@tam.skriver.dk>
next in thread | raw e-mail | index | archive | help
>Number: 25195 >Category: kern >Synopsis: a attacker can make ICMP messages apply to all sessions. >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sun Feb 18 12:50:01 PST 2001 >Closed-Date: >Last-Modified: >Originator: Jesper Skriver >Release: FreeBSD 5.0-CURRENT i386 >Organization: >Environment: System: FreeBSD tam 5.0-CURRENT FreeBSD 5.0-CURRENT #2: Sun Feb 18 21:15:41 CET 2001 root@tam:/usr/obj/usr/src/sys/TAM2 i386 >Description: In the current code we take the port numbers and address from the ICMP packet we get in, and we use 0 as a wildcard indicator - this means if a attacker sends us a ICMP packet where the attached IP header (+ 8 bytes) has the address and port numbers == 0, then we'll treat it as a wildcard, and apply the notification to all sessions. >How-To-Repeat: >Fix: Apply this fix. diff -ru sys/netinet.old/in_pcb.c sys/netinet/in_pcb.c --- sys/netinet.old/in_pcb.c Sun Feb 18 19:28:38 2001 +++ sys/netinet/in_pcb.c Sun Feb 18 21:03:13 2001 @@ -671,7 +671,8 @@ * a valid TCP sequence number for the session. */ void -in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify, tcp_sequence, tcp_seq_check) +in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify, tcp_sequence, + tcp_seq_check, wild_match) struct inpcbhead *head; struct sockaddr *dst; u_int fport_arg, lport_arg; @@ -680,6 +681,7 @@ void (*notify) __P((struct inpcb *, int)); u_int32_t tcp_sequence; int tcp_seq_check; + int wild_match; { register struct inpcb *inp, *oinp; struct in_addr faddr; @@ -700,9 +702,7 @@ * deliver only to that socket. */ if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { - fport = 0; - lport = 0; - laddr.s_addr = 0; + wild_match = IN_PCBNOTIFY_WILDCARD; if (cmd != PRC_HOSTDEAD) notify = in_rtchange; } @@ -715,11 +715,10 @@ continue; } #endif - if (inp->inp_faddr.s_addr != faddr.s_addr || - inp->inp_socket == 0 || - (lport && inp->inp_lport != lport) || - (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) || - (fport && inp->inp_fport != fport)) { + if (inp->inp_faddr.s_addr != faddr.s_addr || inp->inp_socket == 0 || + (wild_match == IN_PCBNOTIFY_NOT_WILDCARD && + (inp->inp_lport != lport || inp->inp_laddr.s_addr != laddr.s_addr || + inp->inp_fport != fport))) { inp = LIST_NEXT(inp, inp_list); continue; } @@ -733,7 +732,6 @@ * and TCP port numbers. */ if ((tcp_seq_check == 1) && (tcp_seq_vs_sess(inp, tcp_sequence) == 0)) { - inp = LIST_NEXT(inp, inp_list); break; } oinp = inp; diff -ru sys/netinet.old/in_pcb.h sys/netinet/in_pcb.h --- sys/netinet.old/in_pcb.h Sun Feb 18 19:28:38 2001 +++ sys/netinet/in_pcb.h Sun Feb 18 20:42:57 2001 @@ -291,7 +291,9 @@ int, struct ifnet *)); void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *, u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int), - u_int32_t, int)); + u_int32_t, int, int)); +#define IN_PCBNOTIFY_NOT_WILDCARD 0 +#define IN_PCBNOTIFY_WILDCARD 1 void in_pcbrehash __P((struct inpcb *)); int in_setpeeraddr __P((struct socket *so, struct sockaddr **nam)); int in_setsockaddr __P((struct socket *so, struct sockaddr **nam)); diff -ru sys/netinet.old/tcp_subr.c sys/netinet/tcp_subr.c --- sys/netinet.old/tcp_subr.c Sun Feb 18 19:28:38 2001 +++ sys/netinet/tcp_subr.c Sun Feb 18 20:46:58 2001 @@ -1033,9 +1033,11 @@ if (tcp_seq_check == 1) tcp_sequence = ntohl(th->th_seq); in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport, - cmd, notify, tcp_sequence, tcp_seq_check); + cmd, notify, tcp_sequence, tcp_seq_check, + IN_PCBNOTIFY_NOT_WILDCARD); } else - in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify, 0, 0); + in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify, 0, + 0, IN_PCBNOTIFY_WILDCARD); } #ifdef INET6 diff -ru sys/netinet.old/udp_usrreq.c sys/netinet/udp_usrreq.c --- sys/netinet.old/udp_usrreq.c Sun Feb 18 19:28:38 2001 +++ sys/netinet/udp_usrreq.c Sun Feb 18 20:46:05 2001 @@ -512,9 +512,10 @@ if (ip) { uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport, - cmd, udp_notify, 0, 0); + cmd, udp_notify, 0, 0, IN_PCBNOTIFY_NOT_WILDCARD); } else - in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify, 0, 0); + in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify, 0, + 0, IN_PCBNOTIFY_WILDCARD); } static int >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200102182049.f1IKn0B00683>