Subject: Re: Fw: Local Denial-of-Service attack against Linux To: davem@redhat.com (David S. Miller) Date: Sun, 26 Mar 2000 23:41:58 +0800 (SGT) From: kuznet@ms2.inr.ac.ru (Alexey Kuznetosv) Hello! The patch for 2.3 is appended. I apologize, I compiled it, but did not test, I will not have a machine to boot for several days. The idea is clear: sock_wmalloc() is wrong function, it cannot be used in the places, where we have choice: to sleep or not to sleep. Luckily, there are only two such places: sock_alloc_send_skb() and its analogue in tcp_sendmsg(). Alexey Index: net/core/sock.c =================================================================== RCS file: /vger/u4/cvs/linux/net/core/sock.c,v retrieving revision 1.91 diff -u -r1.91 sock.c --- net/core/sock.c 2000/03/25 01:55:03 1.91 +++ net/core/sock.c 2000/03/26 15:04:31 @@ -786,18 +786,22 @@ if (sk->shutdown&SEND_SHUTDOWN) goto failure; - if (fallback) { - /* The buffer get won't block, or use the atomic queue. - * It does produce annoying no free page messages still. - */ - skb = sock_wmalloc(sk, size, 0, GFP_BUFFER); + if (atomic_read(&sk->wmem_alloc) < sk->sndbuf) { + if (fallback) { + /* The buffer get won't block, or use the atomic queue. + * It does produce annoying no free page messages still. + */ + skb = alloc_skb(size, GFP_BUFFER); + if (skb) + break; + try_size = fallback; + } + skb = alloc_skb(try_size, sk->allocation); if (skb) break; - try_size = fallback; + err = -ENOBUFS; + goto failure; } - skb = sock_wmalloc(sk, try_size, 0, sk->allocation); - if (skb) - break; /* * This means we have too many buffers for this socket already. @@ -813,6 +817,7 @@ timeo = sock_wait_for_wmem(sk, timeo); } + skb_set_owner_w(skb, sk); return skb; interrupted: Index: net/ipv4/tcp.c =================================================================== RCS file: /vger/u4/cvs/linux/net/ipv4/tcp.c,v retrieving revision 1.166 diff -u -r1.166 tcp.c --- net/ipv4/tcp.c 2000/03/25 01:55:11 1.166 +++ net/ipv4/tcp.c 2000/03/26 15:04:31 @@ -951,10 +951,14 @@ tmp += copy; queue_it = 0; } - skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL); - /* If we didn't get any memory, we need to sleep. */ - if (skb == NULL) { + if (tcp_memory_free(sk)) { + skb = alloc_skb(tmp, GFP_KERNEL); + if (skb == NULL) + goto do_oom; + skb_set_owner_w(skb, sk); + } else { + /* If we didn't get any memory, we need to sleep. */ set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags); set_bit(SOCK_NOSPACE, &sk->socket->flags); @@ -1028,6 +1032,9 @@ send_sig(SIGPIPE, current, 0); err = -EPIPE; } + goto out; +do_oom: + err = copied ? : -ENOBUFS; goto out; do_interrupted: if(copied) Index: net/unix/af_unix.c =================================================================== RCS file: /vger/u4/cvs/linux/net/unix/af_unix.c,v retrieving revision 1.91 diff -u -r1.91 af_unix.c --- net/unix/af_unix.c 2000/03/25 01:55:34 1.91 +++ net/unix/af_unix.c 2000/03/26 15:04:32 @@ -1087,6 +1087,10 @@ goto out; } + err = -EMSGSIZE; + if (len > sk->sndbuf) + goto out; + if (sock->passcred && !sk->protinfo.af_unix.addr && (err = unix_autobind(sock)) != 0) goto out; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/