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>
