[LWN Logo]

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/