Browse Source

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [EBTABLES]: Clean up vmalloc usage in net/bridge/netfilter/ebtables.c
  [NET]: Add skb->truesize assertion checking.
  [TCP]: Account skb overhead in tcp_fragment
  [SUNGEM]: Marvell PHY suspend.
  [LLC]: Use pskb_trim_rcsum() in llc_fixup_skb().
  [NET]: sockfd_lookup_light() returns random error for -EBADFD
Linus Torvalds 19 years ago
parent
commit
d3d3cf05ed

+ 6 - 5
drivers/net/sungem_phy.c

@@ -275,7 +275,7 @@ static int bcm5411_init(struct mii_phy* phy)
 	return 0;
 	return 0;
 }
 }
 
 
-static int bcm5411_suspend(struct mii_phy* phy)
+static int generic_suspend(struct mii_phy* phy)
 {
 {
 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
 
 
@@ -738,7 +738,7 @@ static struct mii_phy_def bcm5401_phy_def = {
 /* Broadcom BCM 5411 */
 /* Broadcom BCM 5411 */
 static struct mii_phy_ops bcm5411_phy_ops = {
 static struct mii_phy_ops bcm5411_phy_ops = {
 	.init		= bcm5411_init,
 	.init		= bcm5411_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
 	.poll_link	= genmii_poll_link,
@@ -757,7 +757,7 @@ static struct mii_phy_def bcm5411_phy_def = {
 /* Broadcom BCM 5421 */
 /* Broadcom BCM 5421 */
 static struct mii_phy_ops bcm5421_phy_ops = {
 static struct mii_phy_ops bcm5421_phy_ops = {
 	.init		= bcm5421_init,
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
 	.poll_link	= genmii_poll_link,
@@ -776,7 +776,7 @@ static struct mii_phy_def bcm5421_phy_def = {
 /* Broadcom BCM 5421 built-in K2 */
 /* Broadcom BCM 5421 built-in K2 */
 static struct mii_phy_ops bcm5421k2_phy_ops = {
 static struct mii_phy_ops bcm5421k2_phy_ops = {
 	.init		= bcm5421_init,
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
 	.poll_link	= genmii_poll_link,
@@ -795,7 +795,7 @@ static struct mii_phy_def bcm5421k2_phy_def = {
 /* Broadcom BCM 5462 built-in Vesta */
 /* Broadcom BCM 5462 built-in Vesta */
 static struct mii_phy_ops bcm5462V_phy_ops = {
 static struct mii_phy_ops bcm5462V_phy_ops = {
 	.init		= bcm5421_init,
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
 	.poll_link	= genmii_poll_link,
@@ -816,6 +816,7 @@ static struct mii_phy_def bcm5462V_phy_def = {
  * would be useful here) --BenH.
  * would be useful here) --BenH.
  */
  */
 static struct mii_phy_ops marvell_phy_ops = {
 static struct mii_phy_ops marvell_phy_ops = {
+	.suspend	= generic_suspend,
 	.setup_aneg	= marvell_setup_aneg,
 	.setup_aneg	= marvell_setup_aneg,
 	.setup_forced	= marvell_setup_forced,
 	.setup_forced	= marvell_setup_forced,
 	.poll_link	= genmii_poll_link,
 	.poll_link	= genmii_poll_link,

+ 7 - 0
include/linux/skbuff.h

@@ -344,6 +344,13 @@ extern void	      skb_over_panic(struct sk_buff *skb, int len,
 				     void *here);
 				     void *here);
 extern void	      skb_under_panic(struct sk_buff *skb, int len,
 extern void	      skb_under_panic(struct sk_buff *skb, int len,
 				      void *here);
 				      void *here);
+extern void	      skb_truesize_bug(struct sk_buff *skb);
+
+static inline void skb_truesize_check(struct sk_buff *skb)
+{
+	if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len))
+		skb_truesize_bug(skb);
+}
 
 
 extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 			int getfrag(void *from, char *to, int offset,
 			int getfrag(void *from, char *to, int offset,

+ 1 - 0
include/net/sock.h

@@ -454,6 +454,7 @@ static inline void sk_stream_set_owner_r(struct sk_buff *skb, struct sock *sk)
 
 
 static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
 static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
 {
 {
+	skb_truesize_check(skb);
 	sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
 	sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
 	sk->sk_wmem_queued   -= skb->truesize;
 	sk->sk_wmem_queued   -= skb->truesize;
 	sk->sk_forward_alloc += skb->truesize;
 	sk->sk_forward_alloc += skb->truesize;

+ 7 - 13
net/bridge/netfilter/ebtables.c

@@ -831,7 +831,7 @@ static int translate_table(struct ebt_replace *repl,
 			return -ENOMEM;
 			return -ENOMEM;
 		for_each_possible_cpu(i) {
 		for_each_possible_cpu(i) {
 			newinfo->chainstack[i] =
 			newinfo->chainstack[i] =
-			   vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
+			  vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
 			if (!newinfo->chainstack[i]) {
 			if (!newinfo->chainstack[i]) {
 				while (i)
 				while (i)
 					vfree(newinfo->chainstack[--i]);
 					vfree(newinfo->chainstack[--i]);
@@ -841,8 +841,7 @@ static int translate_table(struct ebt_replace *repl,
 			}
 			}
 		}
 		}
 
 
-		cl_s = (struct ebt_cl_stack *)
-		   vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
+		cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
 		if (!cl_s)
 		if (!cl_s)
 			return -ENOMEM;
 			return -ENOMEM;
 		i = 0; /* the i'th udc */
 		i = 0; /* the i'th udc */
@@ -944,8 +943,7 @@ static int do_replace(void __user *user, unsigned int len)
 
 
 	countersize = COUNTER_OFFSET(tmp.nentries) * 
 	countersize = COUNTER_OFFSET(tmp.nentries) * 
 					(highest_possible_processor_id()+1);
 					(highest_possible_processor_id()+1);
-	newinfo = (struct ebt_table_info *)
-	   vmalloc(sizeof(struct ebt_table_info) + countersize);
+	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	if (!newinfo)
 	if (!newinfo)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
@@ -967,8 +965,7 @@ static int do_replace(void __user *user, unsigned int len)
 	/* the user wants counters back
 	/* the user wants counters back
 	   the check on the size is done later, when we have the lock */
 	   the check on the size is done later, when we have the lock */
 	if (tmp.num_counters) {
 	if (tmp.num_counters) {
-		counterstmp = (struct ebt_counter *)
-		   vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
+		counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
 		if (!counterstmp) {
 		if (!counterstmp) {
 			ret = -ENOMEM;
 			ret = -ENOMEM;
 			goto free_entries;
 			goto free_entries;
@@ -1148,8 +1145,7 @@ int ebt_register_table(struct ebt_table *table)
 
 
 	countersize = COUNTER_OFFSET(table->table->nentries) *
 	countersize = COUNTER_OFFSET(table->table->nentries) *
 					(highest_possible_processor_id()+1);
 					(highest_possible_processor_id()+1);
-	newinfo = (struct ebt_table_info *)
-	   vmalloc(sizeof(struct ebt_table_info) + countersize);
+	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	ret = -ENOMEM;
 	ret = -ENOMEM;
 	if (!newinfo)
 	if (!newinfo)
 		return -ENOMEM;
 		return -ENOMEM;
@@ -1247,8 +1243,7 @@ static int update_counters(void __user *user, unsigned int len)
 	if (hlp.num_counters == 0)
 	if (hlp.num_counters == 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if ( !(tmp = (struct ebt_counter *)
-	   vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){
+	if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
 		MEMPRINT("Update_counters && nomemory\n");
 		MEMPRINT("Update_counters && nomemory\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
@@ -1377,8 +1372,7 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user,
 			BUGPRINT("Num_counters wrong\n");
 			BUGPRINT("Num_counters wrong\n");
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
-		counterstmp = (struct ebt_counter *)
-		   vmalloc(nentries * sizeof(struct ebt_counter));
+		counterstmp = vmalloc(nentries * sizeof(*counterstmp));
 		if (!counterstmp) {
 		if (!counterstmp) {
 			MEMPRINT("Couldn't copy counters, out of memory\n");
 			MEMPRINT("Couldn't copy counters, out of memory\n");
 			return -ENOMEM;
 			return -ENOMEM;

+ 8 - 0
net/core/skbuff.c

@@ -112,6 +112,14 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
 	BUG();
 	BUG();
 }
 }
 
 
+void skb_truesize_bug(struct sk_buff *skb)
+{
+	printk(KERN_ERR "SKB BUG: Invalid truesize (%u) "
+	       "len=%u, sizeof(sk_buff)=%Zd\n",
+	       skb->truesize, skb->len, sizeof(struct sk_buff));
+}
+EXPORT_SYMBOL(skb_truesize_bug);
+
 /* 	Allocate a new skbuff. We do this ourselves so we can fill in a few
 /* 	Allocate a new skbuff. We do this ourselves so we can fill in a few
  *	'private' fields and also do memory statistics to find all the
  *	'private' fields and also do memory statistics to find all the
  *	[BEEP] leaks.
  *	[BEEP] leaks.

+ 1 - 0
net/core/stream.c

@@ -176,6 +176,7 @@ void sk_stream_rfree(struct sk_buff *skb)
 {
 {
 	struct sock *sk = skb->sk;
 	struct sock *sk = skb->sk;
 
 
+	skb_truesize_check(skb);
 	atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
 	atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
 	sk->sk_forward_alloc += skb->truesize;
 	sk->sk_forward_alloc += skb->truesize;
 }
 }

+ 7 - 3
net/ipv4/tcp_output.c

@@ -533,6 +533,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *buff;
 	struct sk_buff *buff;
 	int nsize, old_factor;
 	int nsize, old_factor;
+	int nlen;
 	u16 flags;
 	u16 flags;
 
 
 	BUG_ON(len > skb->len);
 	BUG_ON(len > skb->len);
@@ -552,8 +553,10 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
 	if (buff == NULL)
 	if (buff == NULL)
 		return -ENOMEM; /* We'll just try again later. */
 		return -ENOMEM; /* We'll just try again later. */
 
 
-	buff->truesize = skb->len - len;
-	skb->truesize -= buff->truesize;
+	sk_charge_skb(sk, buff);
+	nlen = skb->len - len - nsize;
+	buff->truesize += nlen;
+	skb->truesize -= nlen;
 
 
 	/* Correct the sequence numbers. */
 	/* Correct the sequence numbers. */
 	TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
 	TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
@@ -1039,7 +1042,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
 	if (unlikely(buff == NULL))
 	if (unlikely(buff == NULL))
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	buff->truesize = nlen;
+	sk_charge_skb(sk, buff);
+	buff->truesize += nlen;
 	skb->truesize -= nlen;
 	skb->truesize -= nlen;
 
 
 	/* Correct the sequence numbers. */
 	/* Correct the sequence numbers. */

+ 2 - 1
net/llc/llc_input.c

@@ -118,7 +118,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
 		u16 pdulen = eth_hdr(skb)->h_proto,
 		u16 pdulen = eth_hdr(skb)->h_proto,
 		    data_size = ntohs(pdulen) - llc_len;
 		    data_size = ntohs(pdulen) - llc_len;
 
 
-		skb_trim(skb, data_size);
+		if (unlikely(pskb_trim_rcsum(skb, data_size)))
+			return 0;
 	}
 	}
 	return 1;
 	return 1;
 }
 }

+ 1 - 0
net/socket.c

@@ -490,6 +490,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
 	struct file *file;
 	struct file *file;
 	struct socket *sock;
 	struct socket *sock;
 
 
+	*err = -EBADF;
 	file = fget_light(fd, fput_needed);
 	file = fget_light(fd, fput_needed);
 	if (file) {
 	if (file) {
 		sock = sock_from_file(file, err);
 		sock = sock_from_file(file, err);