patch-2.2.2 linux/net/core/sock.c

Next file: linux/net/ipv4/af_inet.c
Previous file: linux/net/core/skbuff.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.1/linux/net/core/sock.c linux/net/core/sock.c
@@ -155,10 +155,6 @@
 	int err;
 	struct linger ling;
 	int ret = 0;
-
-#ifdef CONFIG_FILTER
-	struct sock_fprog fprog;
-#endif
 	
 	/*
 	 *	Options without arguments
@@ -256,12 +252,13 @@
 
 		case SO_PRIORITY:
 			if (val >= 0 && val <= 7) 
+			{
+				if(val==7 && !capable(CAP_NET_ADMIN))
+					return -EPERM;
 				sk->priority = val;
-			else
-				return(-EINVAL);
+			}			
 			break;
 
-
 		case SO_LINGER:
 			if(optlen<sizeof(ling))
 				return -EINVAL;	/* 1003.1g */
@@ -310,10 +307,12 @@
 				if (optlen > IFNAMSIZ) 
 					optlen = IFNAMSIZ; 
 				if (copy_from_user(devname, optval, optlen))
-				    return -EFAULT;
-				    
+					return -EFAULT;
+
 				/* Remove any cached route for this socket. */
+				lock_sock(sk);
 				dst_release(xchg(&sk->dst_cache, NULL));
+				release_sock(sk);
 
 				if (devname[0] == '\0') {
 					sk->bound_dev_if = 0;
@@ -331,30 +330,32 @@
 
 #ifdef CONFIG_FILTER
 		case SO_ATTACH_FILTER:
-			if(optlen < sizeof(struct sock_fprog))
-				return -EINVAL;
+			ret = -EINVAL;
+			if (optlen == sizeof(struct sock_fprog)) {
+				struct sock_fprog fprog;
 
-			if(copy_from_user(&fprog, optval, sizeof(fprog)))
-			{
 				ret = -EFAULT;
-				break;
-			}
+				if (copy_from_user(&fprog, optval, sizeof(fprog)))
+					break;
 
-			ret = sk_attach_filter(&fprog, sk);
+				ret = sk_attach_filter(&fprog, sk);
+			}
 			break;
 
 		case SO_DETACH_FILTER:
-                        if(sk->filter)
-			{
-				fprog.filter = sk->filter_data;
-				kfree_s(fprog.filter, (sizeof(fprog.filter) * sk->filter));
-				sk->filter_data = NULL;
-				sk->filter = 0;
+                        if(sk->filter) {
+				struct sk_filter *filter;
+
+				filter = sk->filter;
+
+				sk->filter = NULL;
+				wmb();
+				
+				if (filter)
+					sk_filter_release(sk, filter);
 				return 0;
 			}
-			else
-				return -EINVAL;
-			break;
+			return -ENOENT;
 #endif
 		/* We implement the SO_SNDLOWAT etc to
 		   not be settable (1003.1g 5.3) */
@@ -503,6 +504,16 @@
 {
 	if (sk->destruct)
 		sk->destruct(sk);
+
+#ifdef CONFIG_FILTER
+	if (sk->filter) {
+		sk_filter_release(sk, sk->filter);
+		sk->filter = NULL;
+	}
+#endif
+
+	if (atomic_read(&sk->omem_alloc))
+		printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
 
 	kmem_cache_free(sk_cachep, sk);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)