Netdev List
 help / color / mirror / Atom feed
* Re: xfrm command fails
From: Naveen BN @ 2009-11-11  7:10 UTC (permalink / raw)
  To: netdev; +Cc: David Miller
In-Reply-To: <4AFA56B1.1010109@globaledgesoft.com>

Hi All,
This proper command to create SA using ip xfrm is
ip xfrm state add src 192.168.1.20 dst 192.168.1.5 proto esp spi 
0x354cb04b mode tunnel reqid 16385 replay-window 32 auth sha1 
0xecf02a5cf6568556e1bdcd961c7ec3f92afd01cc enc aes 
0x5c0cfa9672ce67ba545b593076dfb278 sel src 0.0.0.0/0 dst 0.0.0.0/0

But how can create a session based SA with ports also used in sa 
selection for the same host .
Please help me on this . In selection of OUTBOUND SA does ports also 
involve.

Regards
Naveen

Naveen BN wrote:
> adding David in loop
> Naveen BN wrote:
>> I am using fedora with version => 2.6.23.1-42.fc8.
>> Please guide me to solve the error message "RTNETLINK answers: 
>> Function not implemented"
>>
>> Regards
>> Naveen
>> Naveen BN wrote:
>>> Hi All
>>> I am trying to create a security association using ip xfrm command, 
>>> but i get an message saying
>>> "*RTNETLINK answers: Function not implemented*" and ip xfrm state 
>>> succeeds in displaying  sa  written using setkey .
>>>
>>> ip xfrm state add src 192.168.1.20 dst 192.168.1.5 proto esp spi 
>>> 0x354cb04b mode tunnel reqid 16385 replay-window 32 auth hmac 
>>> 0xecf02a5cf6568556e1bdcd961c7ec3f92afd01cc enc cbc 
>>> 0x5c0cfa9672ce67ba545b593076dfb278 sel src 0.0.0.0/0 dst 0.0.0.0/0
>>>
>>> ERROR message => "RTNETLINK answers: Function not implemented"
>>>
>>> Regards
>>> Naveen
>>> -- 
>>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>
>> -- 
>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
> -- 
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


^ permalink raw reply

* Re: [Bugme-new] [Bug 14546] New: Off-by-two stack buffer overflow in function rpc_uaddr2sockaddr() of net/sunrpc/addr.c
From: Patroklos Argyroudis @ 2009-11-11  7:51 UTC (permalink / raw)
  To: Chuck Lever
  Cc: bugzilla-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r,
	bugme-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r,
	Linux Network Developers, J. Bruce Fields, Trond Myklebust,
	Neil Brown, Andrew Morton, Linux NFS Mailing list
In-Reply-To: <967DC2CE-588D-4207-BF2D-59727454DC2E-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>

On Nov 10, 2009, at 6:29 PM, Andrew Morton wrote:
> >
> >Please don't submit patches via bugzilla.
> >
> >Please prepare this patch as per Documentation/SubmittingPatches and
> >email it to all the recipients of this email, thanks.

Ok, I will do so.

On Tue, Nov 10, 2009 at 06:38:05PM -0500, Chuck Lever wrote:
> Why wouldn't you bump the size of the buffer by two as well?
> Otherwise valid universal addresses that are RPCBIND_MAXUADDRLEN
> bytes long will fail here.
> 
> >	memcpy(buf, uaddr, uaddr_len);

There is no need to increase the size of the buffer since the new check
(if (uaddr_len > sizeof(buf) - 2)) will terminate the function in case
the valid universal address is RPCBIND_MAXUADDRLEN bytes.

Cheers,
Patroklos
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] act_mirred: don't go back.
From: jamal @ 2009-11-11  8:11 UTC (permalink / raw)
  To: Changli Gao; +Cc: Stephen Hemminger, David S. Miller, netdev
In-Reply-To: <412e6f7f0911100050k39920adfl1ab70e345269833a@mail.gmail.com>

Hi,

On Tue, 2009-11-10 at 16:50 +0800, Changli Gao wrote:
 
> Where? After skb2 is allocated, there won't be any failure any more.


Sorry, yes, your change does look like an improvement.
If you can test a little more - please add my sign-off and submit.

> 
> It's just OK. When using tc, I also found act_mirred doesn't support
> ingress, then I realized that there isn't any difference between
> ingress and egress, as it depends on its parent. However I do think it
> is confused, when it prints:
> filter parent ffff: protocol ip pref 49152 basic handle 0x1
>         action order 1: mirred (Egress Redirect to device ifb0) stolen
>         index 5 ref 1 bind 1.
> And the TODO note still is in the source code of act_mirred, it do
> make me wonder for a while!

Well, you know if you have the energy - doing socket redirect would
be very interesting indeed. Ingress is another beast, it requires some
thinking and a lot more testing depending on the devices because of
possible loops.

cheers,
jamal


^ permalink raw reply

* Re: [PATCH 1/2] rps: core implementation
From: Eric Dumazet @ 2009-11-11  8:20 UTC (permalink / raw)
  To: Tom Herbert; +Cc: David Miller, netdev
In-Reply-To: <65634d660911102253o2b4f7a19kfed5849e5c88bfe1@mail.gmail.com>

Tom Herbert a écrit :
> Third version of RPS.
> 
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
>  include/linux/interrupt.h |    1 +
>  include/linux/netdevice.h |   18 ++++
>  include/linux/skbuff.h    |    2 +
>  net/core/dev.c            |  227 ++++++++++++++++++++++++++++++++++++++-------
>  net/core/net-sysfs.c      |  135 +++++++++++++++++++++++++++
>  5 files changed, 348 insertions(+), 35 deletions(-)
> 

I must say this is really exciting :)

> diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
> index b78cf81..fa91194 100644
> --- a/include/linux/interrupt.h
> +++ b/include/linux/interrupt.h
> @@ -345,6 +345,7 @@ enum
>  	TIMER_SOFTIRQ,
>  	NET_TX_SOFTIRQ,
>  	NET_RX_SOFTIRQ,
> +	NET_RPS_SOFTIRQ,
>  	BLOCK_SOFTIRQ,
>  	BLOCK_IOPOLL_SOFTIRQ,
>  	TASKLET_SOFTIRQ,
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 8380009..c1b1bbb 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -639,6 +639,18 @@ struct net_device_ops {
>  };
> 
>  /*
> + * Structure for Receive Packet Steering.  Length of map and array of CPU ID's.
> + */
> +struct rps_map {
> +	int len;
> +	u16 map[0];
> +};
> +
> +/* Maximum size of RPS map (for allocation) */
> +#define RPS_MAP_SIZE (sizeof(struct rps_map) + \
> +    (num_possible_cpus() * sizeof(u16)))
> +

Problem of possible cpus is the number can be very large on some arches,
but yet few cpus online....

In this kind of situation, get_rps_cpu() will return -1 most of the time,
defeating goal of RPS ?


> +/*
>   *	The DEVICE structure.
>   *	Actually, this whole structure is a big mistake.  It mixes I/O
>   *	data with strictly "high-level" data, and it has to know about
> @@ -807,6 +819,9 @@ struct net_device
>  	void			*ax25_ptr;	/* AX.25 specific data */
>  	struct wireless_dev	*ieee80211_ptr;	/* IEEE 802.11 specific data,
>  						   assign before registering */
> +	void			*rps_maps;	/* Array of per-NAPI maps for
> +						   receive packet steeing */
> +	int			rps_num_maps;	/* Number of RPS maps */
> 
>  /*
>   * Cache line mostly used on receive path (including eth_type_trans())
> @@ -1217,6 +1232,9 @@ struct softnet_data
>  	struct Qdisc		*output_queue;
>  	struct sk_buff_head	input_pkt_queue;
>  	struct list_head	poll_list;
> +
> +	struct call_single_data	csd;
> +
>  	struct sk_buff		*completion_queue;
> 
>  	struct napi_struct	backlog;
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 0c68fbd..95feac7 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -396,6 +396,8 @@ struct sk_buff {
> 
>  	__u16			vlan_tci;
> 
> +	__u32			rxhash;
> +
>  	sk_buff_data_t		transport_header;
>  	sk_buff_data_t		network_header;
>  	sk_buff_data_t		mac_header;
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 28b0b9e..735e7e3 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -1976,6 +1976,162 @@ int weight_p __read_mostly = 64;            /*
> old backlog weight */
> 
>  DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
> 
> +static u32 simple_hashrnd;
> +
> +/**
> + * get_rps_cpu is called from netif_receive_skb and returns the target
> + * CPU from the RPS map of the receiving NAPI instance for a given skb.
> + */
> +static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb)
> +{
> +	u32 addr1, addr2, ports;
> +	struct ipv6hdr *ip6;
> +	struct iphdr *ip;
> +	u32 hash, ihl;
> +	u8 ip_proto;
> +	int cpu;
> +	struct rps_map *map = NULL;
> +
> +	if (dev->rps_num_maps) {
> +		/*
> +		 * Locate the map corresponding to the NAPI queue that
> +		 * the packet was received on.
> +		 */
> +		int index = skb_get_rx_queue(skb);
> +		if (index < 0 || index >= dev->rps_num_maps)
> +			index = 0;
> +
> +		map = (struct rps_map *)
> +		    (dev->rps_maps + (RPS_MAP_SIZE * index));
> +		if (!map->len)
> +			map = NULL;
> +	}
> +
> +	if (!map)
> +		return -1;
> +
> +	hash = skb->rxhash;
> +	if (hash)
> +		goto got_hash; /* Skip hash computation on packet header */
> +
> +	switch (skb->protocol) {
> +	case __constant_htons(ETH_P_IP):
> +		if (!pskb_may_pull(skb, sizeof(*ip)))
> +			return -1;
> +
> +		ip = (struct iphdr *) skb->data;
> +		ip_proto = ip->protocol;
> +		addr1 = ip->saddr;
> +		addr2 = ip->daddr;
> +		ihl = ip->ihl;
> +		break;
> +	case __constant_htons(ETH_P_IPV6):
> +		if (!pskb_may_pull(skb, sizeof(*ip6)))
> +			return -1;
> +
> +		ip6 = (struct ipv6hdr *) skb->data;
> +		ip_proto = ip6->nexthdr;
> +		addr1 = ip6->saddr.s6_addr32[3];
> +		addr2 = ip6->daddr.s6_addr32[3];
> +		ihl = (40 >> 2);
> +		break;
> +	default:
> +		return -1;
> +	}
> +	ports = 0;
> +	switch (ip_proto) {
> +	case IPPROTO_TCP:
> +	case IPPROTO_UDP:
> +	case IPPROTO_DCCP:
> +	case IPPROTO_ESP:
> +	case IPPROTO_AH:
> +	case IPPROTO_SCTP:
> +	case IPPROTO_UDPLITE:
> +		if (pskb_may_pull(skb, (ihl * 4) + 4))
> +			ports = *((u32 *) (skb->data + (ihl * 4)));
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	hash = jhash_3words(addr1, addr2, ports, simple_hashrnd);

I wonder if you tried to exchange addr1/addr2  port1/port2 so that conntracking/routing
is also speedup ...

ie make sure hash will be the same regardless of the direction of packet.

union {
	u32 port;
	u16 ports[2];
} p;

if (addr1 < addr2)
	swap(addr1, addr2);

if (p.ports[0] < p.ports[1]);
	swap(p.ports[0], p.ports[1]);

hash = jhash_3words(addr1, addr2, ports, simple_hashrnd);


I think I'll try to extend your patches with TX completion recycling too.

Ie record in skb the cpu number of original sender, and queue skb to
remote queue for destruction (sock_wfree() call and expensive scheduler calls...)

(This probably needs driver cooperation, instead of calling consume_skb(),
use a different function)

Thanks

^ permalink raw reply

* Re: [PATCH] act_mirred: don't go back.
From: Changli Gao @ 2009-11-11  8:44 UTC (permalink / raw)
  To: hadi; +Cc: Stephen Hemminger, David S. Miller, netdev
In-Reply-To: <1257927097.4685.4.camel@bigi>

On Wed, Nov 11, 2009 at 4:11 PM, jamal <hadi@cyberus.ca> wrote:
> Hi,
>
> On Tue, 2009-11-10 at 16:50 +0800, Changli Gao wrote:
>
>> Where? After skb2 is allocated, there won't be any failure any more.
>
>
> Sorry, yes, your change does look like an improvement.
> If you can test a little more - please add my sign-off and submit.

OK. I'll do some test first, then send it out for review.

>
>>
>> It's just OK. When using tc, I also found act_mirred doesn't support
>> ingress, then I realized that there isn't any difference between
>> ingress and egress, as it depends on its parent. However I do think it
>> is confused, when it prints:
>> filter parent ffff: protocol ip pref 49152 basic handle 0x1
>>         action order 1: mirred (Egress Redirect to device ifb0) stolen
>>         index 5 ref 1 bind 1.
>> And the TODO note still is in the source code of act_mirred, it do
>> make me wonder for a while!
>
> Well, you know if you have the energy - doing socket redirect would
> be very interesting indeed. Ingress is another beast, it requires some
> thinking and a lot more testing depending on the devices because of
> possible loops.
>

The current kernel and iproute2 support ingress in another way, that
is attaching the filter to the corresponding ingress qdisc. refter to
http://www.linuxfoundation.org/en/Net:IFB . The loops is avoided in
netif_receive_skb() and with TTL mechanism. Do you have more
documentation or examples about socket redirect? Sorry, I don't know
what it is used to do. Is it sth. like ipt_REDIRECT?


-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: [PATCH] act_mirred: don't go back.
From: jamal @ 2009-11-11  9:03 UTC (permalink / raw)
  To: Changli Gao; +Cc: Stephen Hemminger, David S. Miller, netdev
In-Reply-To: <412e6f7f0911110044i22c28ab6pa3a3691c014e76a8@mail.gmail.com>

On Wed, 2009-11-11 at 16:44 +0800, Changli Gao wrote:

> The current kernel and iproute2 support ingress in another way, that
> is attaching the filter to the corresponding ingress qdisc. refter to
> http://www.linuxfoundation.org/en/Net:IFB . 

that looks like something i wrote ;->

> The loops is avoided in
> netif_receive_skb() and with TTL mechanism. 
> Do you have more
> documentation or examples about socket redirect? Sorry, I don't know
> what it is used to do. Is it sth. like ipt_REDIRECT?

I open a socket and I install a filter to mirror or redirect to this
socket. It is possible to do it today if you use tun device; thats
why i have never been motivated to do it.

cheers,
jamal


^ permalink raw reply

* Re: [PATCH] act_mirred: don't go back.
From: Changli Gao @ 2009-11-11  9:23 UTC (permalink / raw)
  To: hadi; +Cc: Stephen Hemminger, David S. Miller, netdev
In-Reply-To: <1257930232.4685.20.camel@bigi>

On Wed, Nov 11, 2009 at 5:03 PM, jamal <hadi@cyberus.ca> wrote:
> On Wed, 2009-11-11 at 16:44 +0800, Changli Gao wrote:
>
> I open a socket and I install a filter to mirror or redirect to this
> socket. It is possible to do it today if you use tun device; thats
> why i have never been motivated to do it.
>

PF_PACKET can mirror to socket. And with the help of ingress polices,
it can emulate redirection too. Am I right?


-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* [PATCH] ifb: add multi-queue support
From: Changli Gao @ 2009-11-11  9:51 UTC (permalink / raw)
  To: David S. Miller
  Cc: Stephen Hemminger, Patrick McHardy, Eric Dumazet, Tom Herbert,
	netdev

ifb: add multi-queue support

Add multi-queue support, and one kernel thread is created for per queue.
It can used to emulate multi-queue NIC in software, and distribute work
among CPUs.
gentux linux # modprobe ifb numtxqs=2
gentux linux # ifconfig ifb0 up
gentux linux # pgrep ifb0
18508
18509
gentux linux # taskset -p 1 18508
pid 18508's current affinity mask: 3
pid 18508's new affinity mask: 1
gentux linux # taskset -p 2 18509
pid 18509's current affinity mask: 3
pid 18509's new affinity mask: 2
gentux linux # tc qdisc add dev br0 ingress
gentux linux # tc filter add dev br0 parent ffff: protocol ip basic
action mirred egress redirect dev ifb0

This patch also introduces a ip link option "numtxqs" for specifying the
number of the TX queues. so you can add a new ifb with the command:

ip link add numtxqs 4 type ifb

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
drivers/net/ifb.c | 414 ++++++++++++++++++++++++++++++++----------------
include/linux/if_link.h | 1
net/core/rtnetlink.c | 3
3 files changed, 283 insertions(+), 135 deletions(-)

diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 69c2566..ac04e85 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -33,161 +33,157 @@
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/moduleparam.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ip.h>
 #include <net/pkt_sched.h>
 #include <net/net_namespace.h>
 
-#define TX_TIMEOUT  (2*HZ)
-
 #define TX_Q_LIMIT    32
+
+struct ifb_private_q {
+	struct net_device	*dev;
+	struct sk_buff_head	rq;
+	struct sk_buff_head	tq;
+	wait_queue_head_t	wq;
+	struct task_struct	*task;
+	unsigned long		rx_packets;
+	unsigned long		rx_bytes;
+	unsigned long		rx_dropped;
+} ____cacheline_aligned_in_smp;
+
 struct ifb_private {
-	struct tasklet_struct   ifb_tasklet;
-	int     tasklet_pending;
-	/* mostly debug stats leave in for now */
-	unsigned long   st_task_enter; /* tasklet entered */
-	unsigned long   st_txq_refl_try; /* transmit queue refill attempt */
-	unsigned long   st_rxq_enter; /* receive queue entered */
-	unsigned long   st_rx2tx_tran; /* receive to trasmit transfers */
-	unsigned long   st_rxq_notenter; /*receiveQ not entered, resched */
-	unsigned long   st_rx_frm_egr; /* received from egress path */
-	unsigned long   st_rx_frm_ing; /* received from ingress path */
-	unsigned long   st_rxq_check;
-	unsigned long   st_rxq_rsch;
-	struct sk_buff_head     rq;
-	struct sk_buff_head     tq;
+	struct ifb_private_q	*pq;
 };
 
+/* Number of ifb devices to be set up by this module. */
 static int numifbs = 2;
+module_param(numifbs, int, 0444);
+MODULE_PARM_DESC(numifbs, "Number of ifb devices");
 
-static void ri_tasklet(unsigned long dev);
-static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev);
-static int ifb_open(struct net_device *dev);
-static int ifb_close(struct net_device *dev);
+/* Number of TX queues per ifb */
+static int numtxqs = 1;
+module_param(numtxqs, int, 0444);
+MODULE_PARM_DESC(numtxqs, "Number of TX queues per ifb");
 
-static void ri_tasklet(unsigned long dev)
+static int ifb_thread(void *priv)
 {
-
-	struct net_device *_dev = (struct net_device *)dev;
-	struct ifb_private *dp = netdev_priv(_dev);
-	struct net_device_stats *stats = &_dev->stats;
-	struct netdev_queue *txq;
+	struct ifb_private_q *pq = priv;
+	struct net_device *dev = pq->dev;
+	int num = pq - ((struct ifb_private *)netdev_priv(dev))->pq;
+	struct netdev_queue *txq = netdev_get_tx_queue(dev, num);
 	struct sk_buff *skb;
-
-	txq = netdev_get_tx_queue(_dev, 0);
-	dp->st_task_enter++;
-	if ((skb = skb_peek(&dp->tq)) == NULL) {
-		dp->st_txq_refl_try++;
-		if (__netif_tx_trylock(txq)) {
-			dp->st_rxq_enter++;
-			while ((skb = skb_dequeue(&dp->rq)) != NULL) {
-				skb_queue_tail(&dp->tq, skb);
-				dp->st_rx2tx_tran++;
-			}
-			__netif_tx_unlock(txq);
-		} else {
-			/* reschedule */
-			dp->st_rxq_notenter++;
-			goto resched;
+	DEFINE_WAIT(wait);
+
+	while (1) {
+		/* move skb from rq to tq */
+		while (1) {
+			prepare_to_wait(&pq->wq, &wait, TASK_UNINTERRUPTIBLE);
+			__netif_tx_lock_bh(txq);
+			while ((skb = skb_dequeue(&pq->rq)) != NULL)
+				skb_queue_tail(&pq->tq, skb);
+			if (netif_queue_stopped(dev))
+				netif_wake_queue(dev);
+			__netif_tx_unlock_bh(txq);
+			if (kthread_should_stop() || !skb_queue_empty(&pq->tq))
+				break;
+			schedule();
 		}
-	}
-
-	while ((skb = skb_dequeue(&dp->tq)) != NULL) {
-		u32 from = G_TC_FROM(skb->tc_verd);
-
-		skb->tc_verd = 0;
-		skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
-		stats->tx_packets++;
-		stats->tx_bytes +=skb->len;
-
-		rcu_read_lock();
-		skb->dev = dev_get_by_index_rcu(&init_net, skb->iif);
-		if (!skb->dev) {
-			rcu_read_unlock();
-			dev_kfree_skb(skb);
-			stats->tx_dropped++;
+		finish_wait(&pq->wq, &wait);
+		if (kthread_should_stop())
 			break;
+		if (need_resched())
+			schedule();
+
+		/* transfer packets */
+		while ((skb = skb_dequeue(&pq->tq)) != NULL) {
+			u32 from = G_TC_FROM(skb->tc_verd);
+	
+			skb->tc_verd = 0;
+			skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
+			txq->tx_packets++;
+			txq->tx_bytes +=skb->len;
+
+			rcu_read_lock();
+			skb->dev = dev_get_by_index_rcu(&init_net, skb->iif);
+			if (!skb->dev) {
+				rcu_read_unlock();
+				dev_kfree_skb(skb);
+				txq->tx_dropped++;
+				break;
+			}
+			rcu_read_unlock();
+			skb->iif = dev->ifindex;
+	
+			if (from & AT_EGRESS) {
+				dev_queue_xmit(skb);
+			} else if (from & AT_INGRESS) {
+				skb_pull(skb, skb->dev->hard_header_len);
+				netif_rx_ni(skb);
+			} else
+				BUG();
 		}
-		rcu_read_unlock();
-		skb->iif = _dev->ifindex;
-
-		if (from & AT_EGRESS) {
-			dp->st_rx_frm_egr++;
-			dev_queue_xmit(skb);
-		} else if (from & AT_INGRESS) {
-			dp->st_rx_frm_ing++;
-			skb_pull(skb, skb->dev->hard_header_len);
-			netif_rx(skb);
-		} else
-			BUG();
-	}
-
-	if (__netif_tx_trylock(txq)) {
-		dp->st_rxq_check++;
-		if ((skb = skb_peek(&dp->rq)) == NULL) {
-			dp->tasklet_pending = 0;
-			if (netif_queue_stopped(_dev))
-				netif_wake_queue(_dev);
-		} else {
-			dp->st_rxq_rsch++;
-			__netif_tx_unlock(txq);
-			goto resched;
-		}
-		__netif_tx_unlock(txq);
-	} else {
-resched:
-		dp->tasklet_pending = 1;
-		tasklet_schedule(&dp->ifb_tasklet);
 	}
 
+	return 0;
 }
 
-static const struct net_device_ops ifb_netdev_ops = {
-	.ndo_open	= ifb_open,
-	.ndo_stop	= ifb_close,
-	.ndo_start_xmit	= ifb_xmit,
-	.ndo_validate_addr = eth_validate_addr,
-};
-
-static void ifb_setup(struct net_device *dev)
+struct net_device_stats* ifb_get_stats(struct net_device *dev)
 {
-	/* Initialize the device structure. */
-	dev->destructor = free_netdev;
-	dev->netdev_ops = &ifb_netdev_ops;
+	struct net_device_stats *stats = &dev->stats;
+	struct ifb_private *dp = netdev_priv(dev);
+	struct ifb_private_q *pq = dp->pq;
+	struct netdev_queue *txq;
+	int i;
+	unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0;
+	unsigned long tx_packets = 0, tx_bytes = 0, tx_dropped = 0;
+
+	for (i = 0; i < dev->real_num_tx_queues; i++) {
+		rx_packets += pq[i].rx_packets;
+		rx_bytes += pq[i].rx_bytes;
+		rx_dropped += pq[i].rx_dropped;
+		txq = netdev_get_tx_queue(dev, i);
+		tx_packets += txq->tx_packets;
+		tx_bytes += txq->tx_bytes;
+		tx_dropped += txq->tx_dropped;
+	}
 
-	/* Fill in device structure with ethernet-generic values. */
-	ether_setup(dev);
-	dev->tx_queue_len = TX_Q_LIMIT;
+	stats->rx_packets = rx_packets;
+	stats->rx_bytes = rx_bytes;
+	stats->rx_dropped = rx_dropped;
+	stats->tx_packets = tx_packets;
+	stats->tx_bytes = tx_bytes;
+	stats->tx_dropped = tx_dropped;
 
-	dev->flags |= IFF_NOARP;
-	dev->flags &= ~IFF_MULTICAST;
-	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
-	random_ether_addr(dev->dev_addr);
+	return stats;
 }
 
 static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct ifb_private *dp = netdev_priv(dev);
-	struct net_device_stats *stats = &dev->stats;
 	u32 from = G_TC_FROM(skb->tc_verd);
+	int num = skb_get_queue_mapping(skb);
+	struct ifb_private *dp = netdev_priv(dev);
+	struct ifb_private_q *pq = dp->pq + num;
+	struct netdev_queue *txq = netdev_get_tx_queue(dev, num);
 
-	stats->rx_packets++;
-	stats->rx_bytes+=skb->len;
+	pq->rx_packets++;
+	pq->rx_bytes += skb->len;
 
 	if (!(from & (AT_INGRESS|AT_EGRESS)) || !skb->iif) {
 		dev_kfree_skb(skb);
-		stats->rx_dropped++;
+		pq->rx_dropped++;
 		return NETDEV_TX_OK;
 	}
 
-	if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) {
+	txq->trans_start = jiffies;
+	skb_queue_tail(&pq->rq, skb);
+	if (skb_queue_len(&pq->rq) >= dev->tx_queue_len)
 		netif_stop_queue(dev);
-	}
-
-	dev->trans_start = jiffies;
-	skb_queue_tail(&dp->rq, skb);
-	if (!dp->tasklet_pending) {
-		dp->tasklet_pending = 1;
-		tasklet_schedule(&dp->ifb_tasklet);
-	}
+	if (skb_queue_len(&pq->rq) == 1)
+		wake_up(&pq->wq);
 
 	return NETDEV_TX_OK;
 }
@@ -195,26 +191,162 @@ static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
 static int ifb_close(struct net_device *dev)
 {
 	struct ifb_private *dp = netdev_priv(dev);
+	struct ifb_private_q *pq = dp->pq;
+	int i;
 
-	tasklet_kill(&dp->ifb_tasklet);
 	netif_stop_queue(dev);
-	skb_queue_purge(&dp->rq);
-	skb_queue_purge(&dp->tq);
+	for (i = 0; i < dev->real_num_tx_queues; i++) {
+		kthread_stop(pq[i].task);
+		skb_queue_purge(&pq[i].tq);
+		skb_queue_purge(&pq[i].rq);
+	}
+
 	return 0;
 }
 
 static int ifb_open(struct net_device *dev)
 {
 	struct ifb_private *dp = netdev_priv(dev);
-
-	tasklet_init(&dp->ifb_tasklet, ri_tasklet, (unsigned long)dev);
-	skb_queue_head_init(&dp->rq);
-	skb_queue_head_init(&dp->tq);
+	struct ifb_private_q *pq = dp->pq;
+	int i;
+	
+	for (i = 0; i < dev->real_num_tx_queues; i++) {
+		pq[i].task = kthread_run(ifb_thread, &pq[i], "%s/%d", dev->name,
+					 i);
+		if (IS_ERR(pq[i].task)) {
+			int err = PTR_ERR(pq[i].task);
+			while (--i >= 0)
+				kthread_stop(pq[i].task);
+			return err;
+		}
+	}
 	netif_start_queue(dev);
 
 	return 0;
 }
 
+static u32 simple_tx_hashrnd;
+
+static u16 ifb_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+	u32 addr1, addr2;
+	u32 hash, ihl;
+	union {
+		u16 in16[2];
+		u32 in32;
+	} ports;
+	u8 ip_proto;
+
+	if ((hash = skb_rx_queue_recorded(skb))) {
+		while (hash >= dev->real_num_tx_queues)
+			hash -= dev->real_num_tx_queues;
+		return hash;
+	}
+
+	switch (skb->protocol) {
+	case __constant_htons(ETH_P_IP):
+		if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)))
+			ip_proto = ip_hdr(skb)->protocol;
+		else
+			ip_proto = 0;
+		addr1 = ip_hdr(skb)->saddr;
+		addr2 = ip_hdr(skb)->daddr;
+		ihl = ip_hdr(skb)->ihl << 2;
+		break;
+	case __constant_htons(ETH_P_IPV6):
+		ip_proto = ipv6_hdr(skb)->nexthdr;
+		addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
+		addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
+		ihl = 10;
+		break;
+	default:
+		return 0;
+	}
+	if (addr1 > addr2)
+		swap(addr1, addr2);
+
+	switch (ip_proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_DCCP:
+	case IPPROTO_ESP:
+	case IPPROTO_AH:
+	case IPPROTO_SCTP:
+	case IPPROTO_UDPLITE:
+		ports.in32 = *((u32 *) (skb_network_header(skb) + ihl));
+		if (ports.in16[0] > ports.in16[1])
+			swap(ports.in16[0], ports.in16[1]);
+		break;
+
+	default:
+		ports.in32 = 0;
+		break;
+	}
+
+	hash = jhash_3words(addr1, addr2, ports.in32,
+			    simple_tx_hashrnd ^ ip_proto);
+
+	return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
+}
+
+static int ifb_init(struct net_device *dev)
+{
+	struct ifb_private *dp = netdev_priv(dev);
+	struct ifb_private_q *pq = dp->pq;
+	int i;
+
+	pq = kmalloc(sizeof(*pq) * dev->real_num_tx_queues, GFP_KERNEL);
+	if (pq == NULL)
+		return -ENOMEM;
+	dp->pq = pq;
+
+	for (i = 0; i < dev->real_num_tx_queues; i++) {
+		pq[i].dev = dev;
+		skb_queue_head_init(&pq[i].rq);
+		skb_queue_head_init(&pq[i].tq);
+		init_waitqueue_head(&pq[i].wq);
+		pq[i].rx_packets = 0;
+		pq[i].rx_bytes = 0;
+		pq[i].rx_dropped = 0;
+	}
+
+	return 0;
+}
+
+static void ifb_uninit(struct net_device *dev)
+{
+	struct ifb_private *dp = netdev_priv(dev);
+
+	kfree(dp->pq);
+}
+
+static const struct net_device_ops ifb_netdev_ops = {
+	.ndo_init		= ifb_init,
+	.ndo_uninit		= ifb_uninit,
+	.ndo_open		= ifb_open,
+	.ndo_stop		= ifb_close,
+	.ndo_start_xmit		= ifb_xmit,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_select_queue	= ifb_select_queue,
+	.ndo_get_stats		= ifb_get_stats,
+};
+
+static void ifb_setup(struct net_device *dev)
+{
+	/* Initialize the device structure. */
+	dev->destructor = free_netdev;
+	dev->netdev_ops = &ifb_netdev_ops;
+
+	/* Fill in device structure with ethernet-generic values. */
+	ether_setup(dev);
+	dev->tx_queue_len = TX_Q_LIMIT;
+
+	dev->flags |= IFF_NOARP;
+	dev->flags &= ~IFF_MULTICAST;
+	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+	random_ether_addr(dev->dev_addr);
+}
+
 static int ifb_validate(struct nlattr *tb[], struct nlattr *data[])
 {
 	if (tb[IFLA_ADDRESS]) {
@@ -226,24 +358,36 @@ static int ifb_validate(struct nlattr *tb[], struct nlattr *data[])
 	return 0;
 }
 
+static int ifb_get_tx_queues(struct net *net, struct nlattr *tb[],
+			     unsigned int *num_tx_queues,
+			     unsigned int *real_num_tx_queues)
+{
+	if (tb[IFLA_NTXQ]) {
+		*num_tx_queues = nla_get_u16(tb[IFLA_NTXQ]);
+		*real_num_tx_queues = *num_tx_queues;
+	} else {
+		*num_tx_queues = numtxqs;
+		*real_num_tx_queues = numtxqs;
+	}
+
+	return 0;
+}
+
 static struct rtnl_link_ops ifb_link_ops __read_mostly = {
 	.kind		= "ifb",
-	.priv_size	= sizeof(struct ifb_private),
 	.setup		= ifb_setup,
 	.validate	= ifb_validate,
+	.get_tx_queues	= ifb_get_tx_queues,
+	.priv_size	= sizeof(struct ifb_private),
 };
 
-/* Number of ifb devices to be set up by this module. */
-module_param(numifbs, int, 0);
-MODULE_PARM_DESC(numifbs, "Number of ifb devices");
-
 static int __init ifb_init_one(int index)
 {
 	struct net_device *dev_ifb;
 	int err;
 
-	dev_ifb = alloc_netdev(sizeof(struct ifb_private),
-				 "ifb%d", ifb_setup);
+	dev_ifb = alloc_netdev_mq(sizeof(struct ifb_private), "ifb%d",
+				  ifb_setup, numtxqs);
 
 	if (!dev_ifb)
 		return -ENOMEM;
@@ -268,9 +412,9 @@ static int __init ifb_init_module(void)
 {
 	int i, err;
 
+	get_random_bytes(&simple_tx_hashrnd, 4);
 	rtnl_lock();
 	err = __rtnl_link_register(&ifb_link_ops);
-
 	for (i = 0; i < numifbs && !err; i++)
 		err = ifb_init_one(i);
 	if (err)
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 1d3b242..99da411 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -78,6 +78,7 @@ enum {
 #define IFLA_LINKINFO IFLA_LINKINFO
 	IFLA_NET_NS_PID,
 	IFLA_IFALIAS,
+	IFLA_NTXQ,
 	__IFLA_MAX
 };
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 33148a5..7b94fd7 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -597,6 +597,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev)
 	       + nla_total_size(4) /* IFLA_MASTER */
 	       + nla_total_size(1) /* IFLA_OPERSTATE */
 	       + nla_total_size(1) /* IFLA_LINKMODE */
+	       + nla_total_size(2) /* IFLA_NTXQ */
 	       + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
 }
 
@@ -627,6 +628,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 		   netif_running(dev) ? dev->operstate : IF_OPER_DOWN);
 	NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode);
 	NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
+	NLA_PUT_U16(skb, IFLA_NTXQ, dev->real_num_tx_queues);
 
 	if (dev->ifindex != dev->iflink)
 		NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
@@ -725,6 +727,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_LINKINFO]		= { .type = NLA_NESTED },
 	[IFLA_NET_NS_PID]	= { .type = NLA_U32 },
 	[IFLA_IFALIAS]	        = { .type = NLA_STRING, .len = IFALIASZ-1 },
+	[IFLA_NTXQ]		= { .type = NLA_U16 },
 };
 EXPORT_SYMBOL(ifla_policy);
 



^ permalink raw reply related

* Re: [PATCH] ifb: add multi-queue support
From: Changli Gao @ 2009-11-11  9:56 UTC (permalink / raw)
  To: David S. Miller, Stephen Hemminger
  Cc: Patrick McHardy, Eric Dumazet, Tom Herbert, netdev
In-Reply-To: <4AFA8911.7050204@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1106 bytes --]

2009/11/11 Changli Gao <xiaosuo@gmail.com>:
> ifb: add multi-queue support
>
> Add multi-queue support, and one kernel thread is created for per queue.
> It can used to emulate multi-queue NIC in software, and distribute work
> among CPUs.
> gentux linux # modprobe ifb numtxqs=2
> gentux linux # ifconfig ifb0 up
> gentux linux # pgrep ifb0
> 18508
> 18509
> gentux linux # taskset -p 1 18508
> pid 18508's current affinity mask: 3
> pid 18508's new affinity mask: 1
> gentux linux # taskset -p 2 18509
> pid 18509's current affinity mask: 3
> pid 18509's new affinity mask: 2
> gentux linux # tc qdisc add dev br0 ingress
> gentux linux # tc filter add dev br0 parent ffff: protocol ip basic
> action mirred egress redirect dev ifb0
>
> This patch also introduces a ip link option "numtxqs" for specifying the
> number of the TX queues. so you can add a new ifb with the command:
>
> ip link add numtxqs 4 type ifb
>

The corresponding patch for iproute2 is attached too. And you need to
update the linux header files too.


-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

[-- Attachment #2: iproute2-support-numtxqs.diff --]
[-- Type: application/octet-stream, Size: 1214 bytes --]

--- ip/iplink.c.orig	2009-11-11 16:56:41.000000000 +0800
+++ ip/iplink.c	2009-11-11 17:32:52.000000000 +0800
@@ -48,6 +48,7 @@
 		fprintf(stderr, "                   [ address LLADDR ]\n");
 		fprintf(stderr, "                   [ broadcast LLADDR ]\n");
 		fprintf(stderr, "                   [ mtu MTU ]\n");
+		fprintf(stderr, "                   [ numtxqs NUMTXQS ]\n");
 		fprintf(stderr, "                   type TYPE [ ARGS ]\n");
 		fprintf(stderr, "       ip link delete DEV type TYPE [ ARGS ]\n");
 		fprintf(stderr, "\n");
@@ -180,6 +181,7 @@
 	int qlen = -1;
 	int mtu = -1;
 	int netns = -1;
+	int numtxqs = -1;
 
 	ret = argc;
 
@@ -221,6 +223,13 @@
 			if (get_integer(&mtu, *argv, 0))
 				invarg("Invalid \"mtu\" value\n", *argv);
 			addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
+		} else if (strcmp(*argv, "numtxqs") == 0) {
+			NEXT_ARG();
+			if (numtxqs != -1)
+				duparg("numtxqs", *argv);
+			if (get_integer(&numtxqs, *argv, 0))
+				invarg("Invalid \"numtxqs\" value\n", *argv);
+			addattr_l(&req->n, sizeof(*req), IFLA_NTXQ, &numtxqs, 2);
                 } else if (strcmp(*argv, "netns") == 0) {
                         NEXT_ARG();
                         if (netns != -1)

^ permalink raw reply

* Re: [PATCH] ifb: add multi-queue support
From: Eric Dumazet @ 2009-11-11 10:30 UTC (permalink / raw)
  To: xiaosuo
  Cc: David S. Miller, Stephen Hemminger, Patrick McHardy, Tom Herbert,
	netdev
In-Reply-To: <4AFA8911.7050204@gmail.com>

Changli Gao a écrit :
> ifb: add multi-queue support
> 
> Add multi-queue support, and one kernel thread is created for per queue.
> It can used to emulate multi-queue NIC in software, and distribute work
> among CPUs.
> gentux linux # modprobe ifb numtxqs=2
> gentux linux # ifconfig ifb0 up
> gentux linux # pgrep ifb0
> 18508
> 18509
> gentux linux # taskset -p 1 18508
> pid 18508's current affinity mask: 3
> pid 18508's new affinity mask: 1
> gentux linux # taskset -p 2 18509
> pid 18509's current affinity mask: 3
> pid 18509's new affinity mask: 2
> gentux linux # tc qdisc add dev br0 ingress
> gentux linux # tc filter add dev br0 parent ffff: protocol ip basic
> action mirred egress redirect dev ifb0
> 
> This patch also introduces a ip link option "numtxqs" for specifying the
> number of the TX queues. so you can add a new ifb with the command:
> 
> ip link add numtxqs 4 type ifb
> 
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
> ----
> drivers/net/ifb.c | 414 ++++++++++++++++++++++++++++++++----------------
> include/linux/if_link.h | 1
> net/core/rtnetlink.c | 3
> 3 files changed, 283 insertions(+), 135 deletions(-)
> 
> diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
> index 69c2566..ac04e85 100644
> --- a/drivers/net/ifb.c
> +++ b/drivers/net/ifb.c
> @@ -33,161 +33,157 @@
>  #include <linux/etherdevice.h>
>  #include <linux/init.h>
>  #include <linux/moduleparam.h>
> +#include <linux/wait.h>
> +#include <linux/sched.h>
> +#include <linux/kthread.h>
> +#include <linux/ip.h>
> +#include <linux/ipv6.h>
> +#include <net/ip.h>
>  #include <net/pkt_sched.h>
>  #include <net/net_namespace.h>
>  
> -#define TX_TIMEOUT  (2*HZ)
> -
>  #define TX_Q_LIMIT    32
> +
> +struct ifb_private_q {
> +	struct net_device	*dev;
> +	struct sk_buff_head	rq;
> +	struct sk_buff_head	tq;
> +	wait_queue_head_t	wq;
> +	struct task_struct	*task;
> +	unsigned long		rx_packets;
> +	unsigned long		rx_bytes;
> +	unsigned long		rx_dropped;
> +} ____cacheline_aligned_in_smp;
> +

Could you split this struct in two parts, one used by ifb_xmit(),
one used by the ifb_thread() ?
This would reduce number of cache line ping pongs...


struct ifb_private_q {

	struct net_device	*dev;
	struct task_struct	*task;

/* used by ifb_xmit() */

	struct sk_buff_head	rq;
	unsigned long		rx_packets;
	unsigned long		rx_bytes;
	unsigned long		rx_dropped;
	wait_queue_head_t	wq;

/* used by ifb_thread() */

	struct sk_buff_head	tq ____cacheline_aligned_in_smp;
} ____cacheline_aligned_in_smp;


Or even better, tq could be local to ifb_xmit()

ifb_xmit() would purge it itself, and could use __skb_dequeue() and
other lockless primitives.

The whole :

while ((skb = skb_dequeue(&pq->rq)) != NULL)
	skb_queue_tail(&pq->tq, skb);

could be optimized a lot IMHO, its almost a skb_queue_splice() thing...


^ permalink raw reply

* Re: [PATCH] ifb: add multi-queue support
From: Changli Gao @ 2009-11-11 10:57 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David S. Miller, Stephen Hemminger, Patrick McHardy, Tom Herbert,
	netdev
In-Reply-To: <4AFA9235.1030004@gmail.com>

2009/11/11 Eric Dumazet <eric.dumazet@gmail.com>:
>
> Or even better, tq could be local to ifb_xmit()
>
> ifb_xmit() would purge it itself, and could use __skb_dequeue() and
> other lockless primitives.
>
> The whole :
>
> while ((skb = skb_dequeue(&pq->rq)) != NULL)
>        skb_queue_tail(&pq->tq, skb);
>
> could be optimized a lot IMHO, its almost a skb_queue_splice() thing...
>

Thanks, it is a good idea. Any others?


-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* [PATCH] sunrpc: off-by-two stack buffer overflow in function rpc_uaddr2sockaddr()
From: Patroklos Argyroudis @ 2009-11-11 11:02 UTC (permalink / raw)
  To: Andrew Morton
  Cc: netdev, J. Bruce Fields, Trond Myklebust, Neil Brown, linux-nfs
In-Reply-To: <20091110152908.7558a471.akpm@linux-foundation.org>

There is an off-by-two stack buffer overflow in function rpc_uaddr2sockaddr()
of file net/sunrpc/addr.c in the Linux kernel SUNRPC implementation.
 
The function rpc_uaddr2sockaddr() that is used to convert a universal address
to a socket address takes as an argument the size_t variable uaddr_len (the
length of the universal address string). The stack buffer buf is declared in
line 315 to be of size RPCBIND_MAXUADDRLEN. If the passed argument uaddr_len is
equal to RPCBIND_MAXUADDRLEN then the check at line 319 passes and then at
lines 324 and 325 there are two out-of-bounds assignments:
 
    319         if (uaddr_len > sizeof(buf))
    320                 return 0;
 ...
    324         buf[uaddr_len] = '\n';
    325         buf[uaddr_len + 1] = '\0';

Signed-off-by: Patroklos Argyroudis <argp@census-labs.com>
---

--- linux-2.6/net/sunrpc/addr.c.orig    2009-11-11 12:33:04.000000000 +0200
+++ linux-2.6/net/sunrpc/addr.c 2009-11-11 12:33:32.000000000 +0200
@@ -316,7 +316,7 @@ size_t rpc_uaddr2sockaddr(const char *ua
    unsigned long portlo, porthi;
    unsigned short port;
 
-   if (uaddr_len > sizeof(buf))
+   if (uaddr_len > sizeof(buf) - 2)
        return 0;
 
    memcpy(buf, uaddr, uaddr_len);


^ permalink raw reply

* Oops from tcp_collapse() when using splice()
From: Karl Hiramoto @ 2009-11-11 11:22 UTC (permalink / raw)
  To: netdev

Hi, the following oops occurs with both 2.6.28.9 and 2.6.30.9

userspace program is using  splice() on two tcp sockets.


Internal error: Oops: 817 [#1]                                                                         
Modules linked in: pppoe pppox br2684 crc_ccitt nf_nat_pptp nf_nat_proto_gre nf_conntrack_pptp nf_conntrack_proto_gre af_key ixp4xx_crypto ipt_MASQUERADE
CPU: 0    Not tainted  (2.6.30.9 #1)                                                                                                                      
PC is at tcp_collapse+0x268/0x338                                                                                                                         
LR is at 0xc2c49640                                                                                                                                       
pc : [<c020be4c>]    lr : [<c2c49640>]    psr: 80000013                                                                                                   
sp : c0323c80  ip : c3a09920  fp : c0323cb8                                                                                                               
r10: 20ec0490  r9 : 00000e2c  r8 : c2d117a0                                                                                                               
r7 : c2c49620  r6 : c2d11780  r5 : c2c49600  r4 : 00000074                                                                                                
r3 : 00000000  r2 : 20ec4594  r1 : 00004104  r0 : c2c49600                                                                                                
Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel                                                                                       
Control: 000039ff  Table: 02efc000  DAC: 00000017                                                                                                         
Process swapper (pid: 0, stack limit = 0xc0322260)                                                                                                        
Stack: (0xc0323c80 to 0xc0324000)                                                                                                                         
3c80: c3a09920 c3a09920 c3a098c0 ffffc476 c3a098c0 c3a098c0 0000059a c2cded80                                                                             
3ca0: c2eef054 c3a09c20 c2eef054 c0323cfc c0323cbc c020c114 c020bbf0 20ec0490                                                                             
3cc0: 20ed15b0 18295345 00000000 c3a09c20 00000000 000008ec c3a098c0 0000059a                                                                             
3ce0: c2cded80 c2eef054 c2cdeda0 c2eef054 c0323d30 c0323d00 c020c394 c020bf28                                                                             
3d00: c2e5ec00 ffffffff c3a098c0 c2cded80 0000059a c2eef054 00000020 c2cdeda0                                                                             
3d20: c2eef054 c0323d5c c0323d34 c02102f8 c020c1b4 00000000 c2cded80 c3a098c0                                                                             
3d40: c2eef054 c03576fc c2eef040 0000cd2b c0323d8c c0323d60 c0215770 c020fddc                                                                             
3d60: bf11dcfc 00000000 c0323d8c c0323d78 00000000 c2cded80 c3a098c0 c2eef054                                                                             
3d80: c0323dc8 c0323d90 c021750c c021574c 0a430f2d 0000cd2b 00000005 c0357e58                                                                             
3da0: c033dd04 c2cded80 00000000 c03576fc c0358518 c033b870 00000000 c0323dec                                                                             
3dc0: c0323dcc c01fb6ac c0216e6c c2cded80 c2cded80 c2eef040 c2e5ec00 c0357a40                                                                             
3de0: c0323e0c c0323df0 c01fbb68 c01fb55c 00000000 c01fb550 80000000 c0357a20                                                                             
3e00: c0323e38 c0323e10 c01fb52c c01fbaf8 c2e5ec00 c2cded80 c0357a20 c2cded80                                                                             
3e20: c03576fc c2e5ec00 c0357a40 c0323e64 c0323e3c c01fbab8 c01fb22c 00000000                                                                             
3e40: c01fb220 80000000 c0357a20 c2cded80 c2e5ec00 00000800 c0323e94 c0323e68                                                                             
3e60: c01ddf24 c01fb86c c2e5c600 c0323ecc 00000002 c033b888 ffffbe5e 00000040                                                                             
3e80: 00000000 c033b86c c0323ec0 c0323e98 c01ddff4 c01ddb9c c033b888 00000040                                                                             
3ea0: 00000100 0000012c c033b86c c033b87c ffffbe60 c0323eec c0323ec4 c01e095c                                                                             
3ec0: c01ddf74 c0322000 0000000c 00000100 00000001 00000009 c034b72c 00000000                                                                             
3ee0: c0323f20 c0323ef0 c00359dc c01e0900 c0323efc c0029608 00000003 00000000                                                                             
3f00: 00000008 c03426a8 0001c608 690541f1 0001c49c c0323f30 c0323f24 c0035c98                                                                             
3f20: c003597c c0323f48 c0323f34 c0020058 c0035c60 ffffffff 0000001f c0323fa0                                                                             
3f40: c0323f4c c00209c4 c002000c c03273c8 c383e300 c0322000 00000000 c0021de8                                                                             
3f60: c0322000 c0021de8 c03426a8 0001c608 690541f1 0001c49c c0323fa0 c0323fa4                                                                             
3f80: c0323f94 c0021cb0 c0021dfc 60000013 ffffffff c0323fc0 c0323fa4 c0021cb0                                                                             
3fa0: c0021df4 c034dfc4 c0342450 c001dd60 c0326344 c0323fd0 c0323fc4 c0263be4                                                                             
3fc0: c0021c80 c0323ff4 c0323fd4 c00089c0 c0263b98 c00083ac c001dd60 000039fd                                                                             
3fe0: c03426d8 c001e164 00000000 c0323ff8 00008034 c00087bc 00000000 00000000                                                                             
Backtrace:                                                                                                                                                
[<c020bbe4>] (tcp_collapse+0x0/0x338) from [<c020c114>] (tcp_prune_queue+0x1f8/0x28c)                                                                     
[<c020bf1c>] (tcp_prune_queue+0x0/0x28c) from [<c020c394>] (tcp_data_queue+0x1ec/0xc3c)                                                                   
[<c020c1a8>] (tcp_data_queue+0x0/0xc3c) from [<c02102f8>] (tcp_rcv_established+0x528/0x5e0)                                                               
[<c020fdd0>] (tcp_rcv_established+0x0/0x5e0) from [<c0215770>] (tcp_v4_do_rcv+0x30/0x1c4)                                                                 
[<c0215740>] (tcp_v4_do_rcv+0x0/0x1c4) from [<c021750c>] (tcp_v4_rcv+0x6ac/0x754)                                                                         
 r7:c2eef054 r6:c3a098c0 r5:c2cded80 r4:00000000                                                                                                          
[<c0216e60>] (tcp_v4_rcv+0x0/0x754) from [<c01fb6ac>] (ip_local_deliver_finish+0x15c/0x21c)                                                               
[<c01fb550>] (ip_local_deliver_finish+0x0/0x21c) from [<c01fbb68>] (ip_local_deliver+0x7c/0x88)                                                           
 r8:c0357a40 r7:c2e5ec00 r6:c2eef040 r5:c2cded80 r4:c2cded80                                                                                              
[<c01fbaec>] (ip_local_deliver+0x0/0x88) from [<c01fb52c>] (ip_rcv_finish+0x30c/0x330)                                                                    
 r4:c0357a20                                                                                                                                              
[<c01fb220>] (ip_rcv_finish+0x0/0x330) from [<c01fbab8>] (ip_rcv+0x258/0x28c)                                                                             
 r8:c0357a40 r7:c2e5ec00 r6:c03576fc r5:c2cded80 r4:c0357a20                                                                                              
[<c01fb860>] (ip_rcv+0x0/0x28c) from [<c01ddf24>] (netif_receive_skb+0x394/0x3d8)                                                                         
 r7:00000800 r6:c2e5ec00 r5:c2cded80 r4:c0357a20                                                                                                          
[<c01ddb90>] (netif_receive_skb+0x0/0x3d8) from [<c01ddff4>] (process_backlog+0x8c/0xd8)                                                                  
[<c01ddf68>] (process_backlog+0x0/0xd8) from [<c01e095c>] (net_rx_action+0x68/0x188)                                                                      
[<c01e08f4>] (net_rx_action+0x0/0x188) from [<c00359dc>] (__do_softirq+0x6c/0xf8)                                                                         
[<c0035970>] (__do_softirq+0x0/0xf8) from [<c0035c98>] (irq_exit+0x44/0x4c)                                                                               
[<c0035c54>] (irq_exit+0x0/0x4c) from [<c0020058>] (asm_do_IRQ+0x58/0x6c)                                                                                 
[<c0020000>] (asm_do_IRQ+0x0/0x6c) from [<c00209c4>] (__irq_svc+0x24/0x80)                                                                                
Exception stack(0xc0323f4c to 0xc0323f94)                                                                                                                 
3f40:                            c03273c8 c383e300 c0322000 00000000 c0021de8                                                                             
3f60: c0322000 c0021de8 c03426a8 0001c608 690541f1 0001c49c c0323fa0 c0323fa4                                                                             
3f80: c0323f94 c0021cb0 c0021dfc 60000013 ffffffff                                                                                                        
 r5:0000001f r4:ffffffff                                                                                                                                  
[<c0021de8>] (default_idle+0x0/0x4c) from [<c0021cb0>] (cpu_idle+0x3c/0x58)                                                                               
[<c0021c74>] (cpu_idle+0x0/0x58) from [<c0263be4>] (rest_init+0x58/0x6c)                                                                                  
 r7:c0326344 r6:c001dd60 r5:c0342450 r4:c034dfc4                                                                                                          
[<c0263b8c>] (rest_init+0x0/0x6c) from [<c00089c0>] (start_kernel+0x210/0x264)                                                                            
[<c00087b0>] (start_kernel+0x0/0x264) from [<00008034>] (0x8034)                                                                                          
 r6:c001e164 r5:c03426d8 r4:000039fd                                                                                                                      
Code: e50b302c e06a1002 5a000002 e3a03000 (e5833000) 


^ permalink raw reply

* Re: Oops from tcp_collapse() when using splice()
From: Karl Hiramoto @ 2009-11-11 11:38 UTC (permalink / raw)
  To: netdev
In-Reply-To: <4AFA9E81.3050508@hiramoto.org>

Karl Hiramoto wrote:
> Hi, the following oops occurs with both 2.6.28.9 and 2.6.30.9
>
> userspace program is using  splice() on two tcp sockets.
>
 Unable to handle kernel NULL pointer dereference at virtual address 
00000000
pgd = 
c0004000                                                               
[00000000] 
*pgd=00000000                                                     
Internal error: Oops: 817 
[#1]                                               
Modules linked in: pppoe pppox br2684 crc_ccitt nf_nat_pptp 
nf_nat_proto_gre nf_conntrack_pptp nf_conntrack_proto_gre af_key 
ixp4xx_crypto ipt_MASQUERADEc
CPU: 0    Not tainted  (2.6.30.9 
#1)                                                                                                                      

PC is at 
tcp_collapse+0x268/0x338                                                                                                                         

LR is at 
0xc2f047c0                                                                                                                                       

pc : [<c020be4c>]    lr : [<c2f047c0>]    psr: 
80000013                                                                                                   

sp : c0323c90  ip : c3881d40  fp : 
c0323cc8                                                                                                               

r10: c6762c80  r9 : 00000e2c  r8 : 
c3b85920                                                                                                               

r7 : c2f047a0  r6 : c3b85900  r5 : c2f04780  r4 : 
00000074                                                                                                

r3 : 00000000  r2 : c6766d84  r1 : 00004104  r0 : 
c2f04780                                                                                                

Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment 
kernel                                                                                       

Control: 000039ff  Table: 02cd0000  DAC: 
00000017                                                                                                         

Process swapper (pid: 0, stack limit = 
0xc0322260)                                                                                                        

Stack: (0xc0323c90 to 
0xc0324000)                                                                                                                         

3c80:                                     c3881d40 c3881d40 c3881ce0 
ffffc476                                                                             

3ca0: c3881ce0 c3881ce0 0000059a c2dd2d80 c2ea1054 c3882040 c2ea1054 
c0323d0c                                                                             

3cc0: c0323ccc c020c114 c020bbf0 c6762c80 c6773da0 b87d516b 00000000 
c3882040                                                                             

3ce0: 00000000 000008ec c3881ce0 0000059a c2dd2d80 c2ea1054 c2dd2da0 
c2ea1054                                                                             

3d00: c0323d40 c0323d10 c020c394 c020bf28 c2e46000 ffffffff c3881ce0 
c2dd2d80                                                                             

3d20: 0000059a c2ea1054 00000020 c2dd2da0 c2ea1054 c0323d6c c0323d44 
c02102f8                                                                             

3d40: c020c1b4 00000000 c2dd2d80 c3881ce0 c2ea1054 c03576fc c2ea1040 
0000e76d                                                                             

3d60: c0323d9c c0323d70 c0215770 c020fddc bf11dcfc 00000000 c0323d9c 
c0323d88                                                                             

3d80: 00000000 c2dd2d80 c3881ce0 c2ea1054 c0323dd8 c0323da0 c021750c 
c021574c                                                                             

3da0: 0a430f30 0000e76d 00000005 c0357e58 c033dd04 c2dd2d80 00000000 
c03576fc                                                                             

3dc0: c0358518 c033b870 00000000 c0323dfc c0323ddc c01fb6ac c0216e6c 
c2dd2d80                                                                             

3de0: c2dd2d80 c2ea1040 c2e46000 c0357a40 c0323e1c c0323e00 c01fbb68 
c01fb55c                                                                             

3e00: 00000000 c01fb550 80000000 c0357a20 c0323e48 c0323e20 c01fb52c 
c01fbaf8                                                                             

3e20: c2e46000 c2dd2d80 c0357a20 c2dd2d80 c03576fc c2e46000 c0357a40 
c0323e74                                                                             

3e40: c0323e4c c01fbab8 c01fb22c 00000000 c01fb220 80000000 c0357a20 
c2dd2d80                                                                             

3e60: c2e46000 00000800 c0323ea4 c0323e78 c01ddf24 c01fb86c c2e57a00 
c0323edc                                                                             

3e80: 00000002 c033b888 ffffabd7 00000040 00000000 c033b86c c0323ed0 
c0323ea8                                                                             

3ea0: c01ddff4 c01ddb9c c033b888 00000040 00000100 0000012c c033b86c 
c033b87c                                                                             

3ec0: ffffabd9 c0323efc c0323ed4 c01e095c c01ddf74 c0322000 0000000c 
00000100                                                                             

3ee0: 00000001 00000009 c034b72c 00000000 c0323f30 c0323f00 c00359dc 
c01e0900                                                                             

3f00: c0323f0c c0029608 00000003 00000000 00000008 c03426a8 0001c608 
690541f1                                                                             

3f20: 0001c49c c0323f40 c0323f34 c0035c98 c003597c c0323f58 c0323f44 
c0020058                                                                             

3f40: c0035c60 ffffffff 0000001f c0323fc0 c0323f5c c00209c4 c002000c 
c03273c8                                                                             

3f60: c381a900 a0000013 00000000 c0021de8 c0322000 c0021de8 c03426a8 
0001c608                                                                             

3f80: 690541f1 0001c49c c0323fc0 c0323fa4 c0323fa4 c0021cb0 c0021de8 
60000013                                                                             

3fa0: ffffffff c034dfc4 c0342450 c001dd60 c0326344 c0323fd0 c0323fc4 
c0263be4                                                                             

3fc0: c0021c80 c0323ff4 c0323fd4 c00089c0 c0263b98 c00083ac c001dd60 
000039fd                                                                             

3fe0: c03426d8 c001e164 00000000 c0323ff8 00008034 c00087bc 00000000 
00000000                                                                             

Backtrace:                                                                                                                                                

[<c020bbe4>] (tcp_collapse+0x0/0x338) from [<c020c114>] 
(tcp_prune_queue+0x1f8/0x28c)                                                                     

[<c020bf1c>] (tcp_prune_queue+0x0/0x28c) from [<c020c394>] 
(tcp_data_queue+0x1ec/0xc3c)
[<c020c1a8>] (tcp_data_queue+0x0/0xc3c) from [<c02102f8>] 
(tcp_rcv_established+0x528/0x5e0)
[<c020fdd0>] (tcp_rcv_established+0x0/0x5e0) from [<c0215770>] 
(tcp_v4_do_rcv+0x30/0x1c4)
[<c0215740>] (tcp_v4_do_rcv+0x0/0x1c4) from [<c021750c>] 
(tcp_v4_rcv+0x6ac/0x754)
 r7:c2ea1054 r6:c3881ce0 r5:c2dd2d80 r4:00000000
[<c0216e60>] (tcp_v4_rcv+0x0/0x754) from [<c01fb6ac>] 
(ip_local_deliver_finish+0x15c/0x21c)
[<c01fb550>] (ip_local_deliver_finish+0x0/0x21c) from [<c01fbb68>] 
(ip_local_deliver+0x7c/0x88)
 r8:c0357a40 r7:c2e46000 r6:c2ea1040 r5:c2dd2d80 r4:c2dd2d80
[<c01fbaec>] (ip_local_deliver+0x0/0x88) from [<c01fb52c>] 
(ip_rcv_finish+0x30c/0x330)
 r4:c0357a20
[<c01fb220>] (ip_rcv_finish+0x0/0x330) from [<c01fbab8>] 
(ip_rcv+0x258/0x28c)
 r8:c0357a40 r7:c2e46000 r6:c03576fc r5:c2dd2d80 r4:c0357a20
[<c01fb860>] (ip_rcv+0x0/0x28c) from [<c01ddf24>] 
(netif_receive_skb+0x394/0x3d8)
 r7:00000800 r6:c2e46000 r5:c2dd2d80 r4:c0357a20
[<c01ddb90>] (netif_receive_skb+0x0/0x3d8) from [<c01ddff4>] 
(process_backlog+0x8c/0xd8)
[<c01ddf68>] (process_backlog+0x0/0xd8) from [<c01e095c>] 
(net_rx_action+0x68/0x188)
[<c01e08f4>] (net_rx_action+0x0/0x188) from [<c00359dc>] 
(__do_softirq+0x6c/0xf8)
[<c0035970>] (__do_softirq+0x0/0xf8) from [<c0035c98>] (irq_exit+0x44/0x4c)
[<c0035c54>] (irq_exit+0x0/0x4c) from [<c0020058>] (asm_do_IRQ+0x58/0x6c)
[<c0020000>] (asm_do_IRQ+0x0/0x6c) from [<c00209c4>] (__irq_svc+0x24/0x80)
Exception stack(0xc0323f5c to 0xc0323fa4)
3f40:                                                                
c03273c8
3f60: c381a900 a0000013 00000000 c0021de8 c0322000 c0021de8 c03426a8 
0001c608
3f80: 690541f1 0001c49c c0323fc0 c0323fa4 c0323fa4 c0021cb0 c0021de8 
60000013
3fa0: ffffffff
 r5:0000001f r4:ffffffff
[<c0021c74>] (cpu_idle+0x0/0x58) from [<c0263be4>] (rest_init+0x58/0x6c)
 r7:c0326344 r6:c001dd60 r5:c0342450 r4:c034dfc4
[<c0263b8c>] (rest_init+0x0/0x6c) from [<c00089c0>] 
(start_kernel+0x210/0x264)
[<c00087b0>] (start_kernel+0x0/0x264) from [<00008034>] (0x8034)
 r6:c001e164 r5:c03426d8 r4:000039fd
Code: e50b302c e06a1002 5a000002 e3a03000 (e5833000)

^ permalink raw reply

* Re: [PATCH 2/2] au1000-eth: convert to platform_driver model
From: Florian Fainelli @ 2009-11-11 11:54 UTC (permalink / raw)
  To: Manuel Lauss; +Cc: Ralf Baechle, linux-mips, netdev, David Miller
In-Reply-To: <f861ec6f0911100120j12d86b0cs3ef9c2816019eaf9@mail.gmail.com>

Hi Manuel,

On Tuesday 10 November 2009 10:20:25 Manuel Lauss wrote:
> Hi Florian,
> 
> On Tue, Nov 10, 2009 at 1:13 AM, Florian Fainelli <florian@openwrt.org> 
wrote:
> > This patch converts the au1000-eth driver to become a full
> > platform-driver as it ought to be. We now pass PHY-speficic
> > configurations through platform_data but for compatibility
> > the driver still assumes the default settings (search for PHY1 on
> > MAC0) when no platform_data is passed. Tested on my MTX-1 board.
[snip]
> >
> > -                       phydev = tmp_phydev;
> > -                       break; /* found it */
> > +               if (aup->phy1_search_mac0) {
> > +                       /* try harder to find a PHY */
> > +                       if (!phydev && (aup->mac_id == 1)) {
> > +                               /* no PHY found, maybe we have a dual
> > PHY? */ +                               printk (KERN_INFO DRV_NAME ": no
> > PHY found on MAC1, " +                                       "let's see
> > if it's attached to MAC0...\n"); +
> > +                               /* find the first (lowest address)
> > non-attached PHY on +                                * the MAC0 MII bus
> > */
> > +                               for (phy_addr = 0; phy_addr <
> > PHY_MAX_ADDR; phy_addr++) { +                                       if
> > (aup->mac_id == 1)
> > +                                               break;
> 
> aup->mac_id needs to be 1 for this loop to be executed in the first
> place, and here
> you immediately bail out if it is.

>From the reading of the comment, it seems to me like we should not do anything 
in this for loop if we were using MAC1, but I may have misunderstood that, as 
such I have added this break to "comply" with the comment.

> Also, how do you access the phy map of the other controller without use of
>  the au_macs[] structure? (which is unused after this patch and could be
>  removed, along
> with the NUM_ETH_INTERFACES constant)

We access the phy map of the other controller by using the correct mii bus 
identifier, since we have registered a per-interface mdio bus or have I 
overlooked something ?

> 
> > +                                       struct phy_device *const
> > tmp_phydev = +                                                      
> > aup->mii_bus->phy_map[phy_addr];
> 
> My compiler complains about mixed code/declarations.

That declaration was already there and as this patch has no intent to clean 
anything right now, I have left it as-is.
--
Florian

^ permalink raw reply

* Re: [PATCH 2/2] au1000-eth: convert to platform_driver model
From: Manuel Lauss @ 2009-11-11 12:00 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: Ralf Baechle, linux-mips, netdev, David Miller
In-Reply-To: <200911111254.16500.florian@openwrt.org>

On Wed, Nov 11, 2009 at 12:54 PM, Florian Fainelli <florian@openwrt.org> wrote:
> Hi Manuel,
>
> On Tuesday 10 November 2009 10:20:25 Manuel Lauss wrote:
>> Hi Florian,
>>
>> On Tue, Nov 10, 2009 at 1:13 AM, Florian Fainelli <florian@openwrt.org>
> wrote:
>> > This patch converts the au1000-eth driver to become a full
>> > platform-driver as it ought to be. We now pass PHY-speficic
>> > configurations through platform_data but for compatibility
>> > the driver still assumes the default settings (search for PHY1 on
>> > MAC0) when no platform_data is passed. Tested on my MTX-1 board.
> [snip]
>> >
>> > -                       phydev = tmp_phydev;
>> > -                       break; /* found it */
>> > +               if (aup->phy1_search_mac0) {
>> > +                       /* try harder to find a PHY */
>> > +                       if (!phydev && (aup->mac_id == 1)) {
>> > +                               /* no PHY found, maybe we have a dual
>> > PHY? */ +                               printk (KERN_INFO DRV_NAME ": no
>> > PHY found on MAC1, " +                                       "let's see
>> > if it's attached to MAC0...\n"); +
>> > +                               /* find the first (lowest address)
>> > non-attached PHY on +                                * the MAC0 MII bus
>> > */
>> > +                               for (phy_addr = 0; phy_addr <
>> > PHY_MAX_ADDR; phy_addr++) { +                                       if
>> > (aup->mac_id == 1)
>> > +                                               break;
>>
>> aup->mac_id needs to be 1 for this loop to be executed in the first
>> place, and here
>> you immediately bail out if it is.
>
> From the reading of the comment, it seems to me like we should not do anything
> in this for loop if we were using MAC1, but I may have misunderstood that, as
> such I have added this break to "comply" with the comment.
>
>> Also, how do you access the phy map of the other controller without use of
>>  the au_macs[] structure? (which is unused after this patch and could be
>>  removed, along
>> with the NUM_ETH_INTERFACES constant)
>
> We access the phy map of the other controller by using the correct mii bus
> identifier, since we have registered a per-interface mdio bus or have I
> overlooked something ?

Don't know, that's why I asked.


>>
>> > +                                       struct phy_device *const
>> > tmp_phydev = +
>> > aup->mii_bus->phy_map[phy_addr];
>>
>> My compiler complains about mixed code/declarations.
>
> That declaration was already there and as this patch has no intent to clean
> anything right now, I have left it as-is.

The "if (aup->mac_id == 1)" you inserted before it causes it.

You're right though in that there's some cleanup potential after this
patch has gone in...

      Manuel Lauss

^ permalink raw reply

* [patch] missing dev_put() on error path in vif_add()
From: Dan Carpenter @ 2009-11-11 12:03 UTC (permalink / raw)
  To: netdev; +Cc: davem

The other error paths in front of this one have a dev_put() but this one 
got missed.

Found by smatch static checker.

regards,
dan carpenter

Signed-off-by: Dan Carpenter <error27@gmail.com>

--- orig/net/ipv4/ipmr.c	2009-11-11 13:34:20.000000000 +0200
+++ devel/net/ipv4/ipmr.c	2009-11-11 13:34:59.000000000 +0200
@@ -483,8 +483,10 @@
 		return -EINVAL;
 	}
 
-	if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
+	if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) {
+		dev_put(dev);
 		return -EADDRNOTAVAIL;
+	}
 	IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
 	ip_rt_multicast_event(in_dev);
 

^ permalink raw reply

* Re: [Bugme-new] [Bug 14546] New: Off-by-two stack buffer overflow in function rpc_uaddr2sockaddr() of net/sunrpc/addr.c
From: Fabio Olive Leite @ 2009-11-11 12:11 UTC (permalink / raw)
  To: Patroklos Argyroudis
  Cc: Chuck Lever, bugzilla-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r,
	bugme-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r,
	Linux Network Developers, J. Bruce Fields, Trond Myklebust,
	Neil Brown, Andrew Morton, Linux NFS Mailing list
In-Reply-To: <20091111075128.GA28323@evola>

On 2009-11-11 Patroklos Argyroudis wrote:
> On Tue, Nov 10, 2009 at 06:38:05PM -0500, Chuck Lever wrote:
> > Why wouldn't you bump the size of the buffer by two as well?
> > Otherwise valid universal addresses that are RPCBIND_MAXUADDRLEN
> > bytes long will fail here.
> > 
> > >	memcpy(buf, uaddr, uaddr_len);
> 
> There is no need to increase the size of the buffer since the new
> check (if (uaddr_len > sizeof(buf) - 2)) will terminate the function
> in case the valid universal address is RPCBIND_MAXUADDRLEN bytes.

Failing to convert a valid address is incorrect and unexpected. What
Chuck meant is that since it is valid to have an address up to
RPCBIND_MAXUADDRLEN bytes long, the function should be able to work on
that, by having an internal buffer that allows for the extra "\n\0".

Cheers,
Fábio Olivé
-- 
ex sed lex awk yacc, e pluribus unix, amem
na matemática das idéias, permuta é igual a adição
e um debate inteligente implementa a multiplicação
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [Bugme-new] [Bug 14546] New: Off-by-two stack buffer overflow in function rpc_uaddr2sockaddr() of net/sunrpc/addr.c
From: Fabio Olive Leite @ 2009-11-11 12:34 UTC (permalink / raw)
  To: Patroklos Argyroudis
  Cc: Chuck Lever, bugzilla-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r,
	bugme-daemon-590EEB7GvNiWaY/ihj7yzEB+6BGkLq7r,
	Linux Network Developers, J. Bruce Fields, Trond Myklebust,
	Neil Brown, Andrew Morton, Linux NFS Mailing list
In-Reply-To: <20091111075128.GA28323@evola>

On 2009-11-11 Patroklos Argyroudis wrote:
> There is no need to increase the size of the buffer since the new
> check (if (uaddr_len > sizeof(buf) - 2)) will terminate the function
> in case the valid universal address is RPCBIND_MAXUADDRLEN bytes.

On a second note, why is '\n' needed there? You should only need '\0',
as a '\n' at the end is not required by any of the string functions used
to convert the address.

I believe you could go with buf[RPCBIND_MAXUADDRLEN+1] for the extra
NUL only.

Cheers,
Fábio Olivé
-- 
ex sed lex awk yacc, e pluribus unix, amem
na matemática das idéias, permuta é igual a adição
e um debate inteligente implementa a multiplicação
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH] net/atm: move all compat_ioctl handling to atm/ioctl.c
From: Arnd Bergmann @ 2009-11-11 13:30 UTC (permalink / raw)
  To: David Miller; +Cc: dwmw2, linux-kernel, netdev, eric.dumazet
In-Reply-To: <20091110.204118.12070030.davem@davemloft.net>

We have two implementations of the compat_ioctl handling for ATM, the
one that we have had for ages in fs/compat_ioctl.c and the one added to
net/atm/ioctl.c by David Woodhouse. Unfortunately, both versions are
incomplete, and in practice we use a very confusing combination of the
two.

For ioctl numbers that have the same identifier on 32 and 64 bit systems,
we go directly through the compat_ioctl socket operation, for those that
differ, we do a conversion in fs/compat_ioctl.c.

This patch moves both variants into the vcc_compat_ioctl() function,
while preserving the current behaviour. It also kills off the COMPATIBLE_IOCTL
definitions that we never use here.
Doing it this way is clearly not a good solution, but I hope it is a
step into the right direction, so that someone is able to clean up this
mess for real.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>

---
 net/atm/ioctl.c |  188 +++++++++++++++++++++++++++++++++++++++++++++++-
 net/socket.c    |  218 -------------------------------------------------------
 2 files changed, 186 insertions(+), 220 deletions(-)

diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index 4da8892..4539c5c 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -191,8 +191,192 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 }
 
 #ifdef CONFIG_COMPAT
-int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+/*
+ * FIXME:
+ * The compat_ioctl handling is duplicated, using both these conversion
+ * routines and the compat argument to the actual handlers. Both
+ * versions are somewhat incomplete and should be merged, e.g. by
+ * moving the ioctl number translation into the actual handlers and
+ * killing the conversion code.
+ *
+ * -arnd, November 2009
+ */
+struct atmif_sioc32 {
+	compat_int_t	number;
+	compat_int_t	length;
+	compat_caddr_t	arg;
+};
+
+struct atm_iobuf32 {
+	compat_int_t	length;
+	compat_caddr_t	buffer;
+};
+
+#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
+#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
+#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
+#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
+#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
+#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
+#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
+#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
+#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
+#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
+#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
+#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
+#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
+#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
+#define ATM_GETLOOP32	  _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
+#define ATM_SETLOOP32	  _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
+#define ATM_QUERYLOOP32	  _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
+
+static struct {
+	unsigned int cmd32;
+	unsigned int cmd;
+} atm_ioctl_map[] = {
+	{ ATM_GETLINKRATE32, ATM_GETLINKRATE },
+	{ ATM_GETNAMES32,    ATM_GETNAMES },
+	{ ATM_GETTYPE32,     ATM_GETTYPE },
+	{ ATM_GETESI32,	     ATM_GETESI },
+	{ ATM_GETADDR32,     ATM_GETADDR },
+	{ ATM_RSTADDR32,     ATM_RSTADDR },
+	{ ATM_ADDADDR32,     ATM_ADDADDR },
+	{ ATM_DELADDR32,     ATM_DELADDR },
+	{ ATM_GETCIRANGE32,  ATM_GETCIRANGE },
+	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
+	{ ATM_SETESI32,	     ATM_SETESI },
+	{ ATM_SETESIF32,     ATM_SETESIF },
+	{ ATM_GETSTAT32,     ATM_GETSTAT },
+	{ ATM_GETSTATZ32     ATM_GETSTATZ },
+	{ ATM_GETLOOP32,     ATM_GETLOOP },
+	{ ATM_SETLOOP32,     ATM_SETLOOP },
+	{ ATM_QUERYLOOP32,   ATM_QUERYLOOP },
+};
+
+#define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map)
+
+static int do_atm_iobuf(struct socket *sock, unsigned int cmd,
+			unsigned long arg)
+{
+	struct atm_iobuf __user *iobuf;
+	struct atm_iobuf32 __user *iobuf32;
+	u32 data;
+	void __user *datap;
+	int len, err;
+
+	iobuf = compat_alloc_user_space(sizeof(*iobuf));
+	iobuf32 = compat_ptr(arg);
+
+	if (get_user(len, &iobuf32->length) ||
+	    get_user(data, &iobuf32->buffer))
+		return -EFAULT;
+	datap = compat_ptr(data);
+	if (put_user(len, &iobuf->length) ||
+	    put_user(datap, &iobuf->buffer))
+		return -EFAULT;
+
+	err = do_vcc_ioctl(sock, cmd, (unsigned long) iobuf, 0);
+
+	if (!err) {
+		if (copy_in_user(&iobuf32->length, &iobuf->length,
+				 sizeof(int)))
+			err = -EFAULT;
+	}
+
+	return err;
+}
+
+static int do_atmif_sioc(struct socket *sock, unsigned int cmd,
+			 unsigned long arg)
+{
+	struct atmif_sioc __user *sioc;
+	struct atmif_sioc32 __user *sioc32;
+	u32 data;
+	void __user *datap;
+	int err;
+
+	sioc = compat_alloc_user_space(sizeof(*sioc));
+	sioc32 = compat_ptr(arg);
+
+	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int))
+	    || get_user(data, &sioc32->arg))
+		return -EFAULT;
+	datap = compat_ptr(data);
+	if (put_user(datap, &sioc->arg))
+		return -EFAULT;
+
+	err = do_vcc_ioctl(sock, cmd, (unsigned long) sioc, 0);
+
+	if (!err) {
+		if (copy_in_user(&sioc32->length, &sioc->length,
+				 sizeof(int)))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
+			unsigned long arg)
 {
-	return do_vcc_ioctl(sock, cmd, arg, 1);
+	int i;
+	unsigned int cmd = 0;
+
+	switch (cmd32) {
+	case SONET_GETSTAT:
+	case SONET_GETSTATZ:
+	case SONET_GETDIAG:
+	case SONET_SETDIAG:
+	case SONET_CLRDIAG:
+	case SONET_SETFRAMING:
+	case SONET_GETFRAMING:
+	case SONET_GETFRSENSE:
+		return do_atmif_sioc(sock, cmd32, arg);
+	}
+
+	for (i = 0; i < NR_ATM_IOCTL; i++) {
+		if (cmd32 == atm_ioctl_map[i].cmd32) {
+			cmd = atm_ioctl_map[i].cmd;
+			break;
+		}
+	}
+	if (i == NR_ATM_IOCTL)
+		return -EINVAL;
+
+	switch (cmd) {
+	case ATM_GETNAMES:
+		return do_atm_iobuf(sock, cmd, arg);
+
+	case ATM_GETLINKRATE:
+	case ATM_GETTYPE:
+	case ATM_GETESI:
+	case ATM_GETADDR:
+	case ATM_RSTADDR:
+	case ATM_ADDADDR:
+	case ATM_DELADDR:
+	case ATM_GETCIRANGE:
+	case ATM_SETCIRANGE:
+	case ATM_SETESI:
+	case ATM_SETESIF:
+	case ATM_GETSTAT:
+	case ATM_GETSTATZ:
+	case ATM_GETLOOP:
+	case ATM_SETLOOP:
+	case ATM_QUERYLOOP:
+		return do_atmif_sioc(sock, cmd, arg);
+	}
+
+	return -EINVAL;
+}
+
+int vcc_compat_ioctl(struct socket *sock, unsigned int cmd,
+		     unsigned long arg)
+{
+	int ret;
+
+	ret = do_vcc_ioctl(sock, cmd, arg, 1);
+	if (ret != -ENOIOCTLCMD)
+		return ret;
+
+	return do_atm_ioctl(sock, cmd, arg);
 }
 #endif
diff --git a/net/socket.c b/net/socket.c
index 05c4828..402abb3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -100,14 +100,6 @@
 #include <linux/if_tun.h>
 #include <linux/ipv6_route.h>
 #include <linux/route.h>
-#include <linux/atmdev.h>
-#include <linux/atmarp.h>
-#include <linux/atmsvc.h>
-#include <linux/atmlec.h>
-#include <linux/atmclip.h>
-#include <linux/atmmpc.h>
-#include <linux/atm_tcp.h>
-#include <linux/sonet.h>
 #include <linux/sockios.h>
 #include <linux/atalk.h>
 
@@ -2917,173 +2909,6 @@ static int old_bridge_ioctl(compat_ulong_t __user *argp)
 	return -EINVAL;
 }
 
-struct atmif_sioc32 {
-	compat_int_t	number;
-	compat_int_t	length;
-	compat_caddr_t	arg;
-};
-
-struct atm_iobuf32 {
-	compat_int_t	length;
-	compat_caddr_t	buffer;
-};
-
-#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
-#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
-#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
-#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
-#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
-#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
-#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
-#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
-#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
-#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
-#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
-#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
-#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
-#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
-#define ATM_GETLOOP32	  _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
-#define ATM_SETLOOP32	  _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
-#define ATM_QUERYLOOP32	  _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
-
-static struct {
-	unsigned int cmd32;
-	unsigned int cmd;
-} atm_ioctl_map[] = {
-	{ ATM_GETLINKRATE32, ATM_GETLINKRATE },
-	{ ATM_GETNAMES32,    ATM_GETNAMES },
-	{ ATM_GETTYPE32,     ATM_GETTYPE },
-	{ ATM_GETESI32,      ATM_GETESI },
-	{ ATM_GETADDR32,     ATM_GETADDR },
-	{ ATM_RSTADDR32,     ATM_RSTADDR },
-	{ ATM_ADDADDR32,     ATM_ADDADDR },
-	{ ATM_DELADDR32,     ATM_DELADDR },
-	{ ATM_GETCIRANGE32,  ATM_GETCIRANGE },
-	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
-	{ ATM_SETESI32,      ATM_SETESI },
-	{ ATM_SETESIF32,     ATM_SETESIF },
-	{ ATM_GETSTAT32,     ATM_GETSTAT },
-	{ ATM_GETSTATZ32,    ATM_GETSTATZ },
-	{ ATM_GETLOOP32,     ATM_GETLOOP },
-	{ ATM_SETLOOP32,     ATM_SETLOOP },
-	{ ATM_QUERYLOOP32,   ATM_QUERYLOOP }
-};
-
-#define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map)
-
-static int do_atm_iobuf(struct net *net, struct socket *sock,
-			 unsigned int cmd, unsigned long arg)
-{
-	struct atm_iobuf   __user *iobuf;
-	struct atm_iobuf32 __user *iobuf32;
-	u32 data;
-	void __user *datap;
-	int len, err;
-
-	iobuf = compat_alloc_user_space(sizeof(*iobuf));
-	iobuf32 = compat_ptr(arg);
-
-	if (get_user(len, &iobuf32->length) ||
-	    get_user(data, &iobuf32->buffer))
-		return -EFAULT;
-	datap = compat_ptr(data);
-	if (put_user(len, &iobuf->length) ||
-	    put_user(datap, &iobuf->buffer))
-		return -EFAULT;
-
-	err = sock_do_ioctl(net, sock, cmd, (unsigned long)iobuf);
-
-	if (!err) {
-		if (copy_in_user(&iobuf32->length, &iobuf->length,
-				 sizeof(int)))
-			err = -EFAULT;
-	}
-
-	return err;
-}
-
-static int do_atmif_sioc(struct net *net, struct socket *sock,
-			 unsigned int cmd, unsigned long arg)
-{
-	struct atmif_sioc   __user *sioc;
-	struct atmif_sioc32 __user *sioc32;
-	u32 data;
-	void __user *datap;
-	int err;
-
-	sioc = compat_alloc_user_space(sizeof(*sioc));
-	sioc32 = compat_ptr(arg);
-
-	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
-	    get_user(data, &sioc32->arg))
-		return -EFAULT;
-	datap = compat_ptr(data);
-	if (put_user(datap, &sioc->arg))
-		return -EFAULT;
-
-	err = sock_do_ioctl(net, sock, cmd, (unsigned long) sioc);
-
-	if (!err) {
-		if (copy_in_user(&sioc32->length, &sioc->length,
-				 sizeof(int)))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-static int do_atm_ioctl(struct net *net, struct socket *sock,
-			 unsigned int cmd32, unsigned long arg)
-{
-	int i;
-	unsigned int cmd = 0;
-
-	switch (cmd32) {
-	case SONET_GETSTAT:
-	case SONET_GETSTATZ:
-	case SONET_GETDIAG:
-	case SONET_SETDIAG:
-	case SONET_CLRDIAG:
-	case SONET_SETFRAMING:
-	case SONET_GETFRAMING:
-	case SONET_GETFRSENSE:
-		return do_atmif_sioc(net, sock, cmd32, arg);
-	}
-
-	for (i = 0; i < NR_ATM_IOCTL; i++) {
-		if (cmd32 == atm_ioctl_map[i].cmd32) {
-			cmd = atm_ioctl_map[i].cmd;
-			break;
-		}
-	}
-	if (i == NR_ATM_IOCTL)
-	        return -EINVAL;
-
-        switch (cmd) {
-	case ATM_GETNAMES:
-		return do_atm_iobuf(net, sock, cmd, arg);
-
-	case ATM_GETLINKRATE:
-	case ATM_GETTYPE:
-	case ATM_GETESI:
-	case ATM_GETADDR:
-	case ATM_RSTADDR:
-	case ATM_ADDADDR:
-	case ATM_DELADDR:
-	case ATM_GETCIRANGE:
-	case ATM_SETCIRANGE:
-	case ATM_SETESI:
-	case ATM_SETESIF:
-	case ATM_GETSTAT:
-	case ATM_GETSTATZ:
-	case ATM_GETLOOP:
-	case ATM_SETLOOP:
-	case ATM_QUERYLOOP:
-		return do_atmif_sioc(net, sock, cmd, arg);
-	}
-
-	return -EINVAL;
-}
-
 static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
 			 unsigned int cmd, unsigned long arg)
 {
@@ -3173,49 +2998,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
 	case SIOCSMIIREG:
 		return dev_ifsioc(net, sock, cmd, argp);
 
-	case ATM_GETLINKRATE32:
-	case ATM_GETNAMES32:
-	case ATM_GETTYPE32:
-	case ATM_GETESI32:
-	case ATM_GETADDR32:
-	case ATM_RSTADDR32:
-	case ATM_ADDADDR32:
-	case ATM_DELADDR32:
-	case ATM_GETCIRANGE32:
-	case ATM_SETCIRANGE32:
-	case ATM_SETESI32:
-	case ATM_SETESIF32:
-	case ATM_GETSTAT32:
-	case ATM_GETSTATZ32:
-	case ATM_GETLOOP32:
-	case ATM_SETLOOP32:
-	case ATM_QUERYLOOP32:
-	case SONET_GETSTAT:
-	case SONET_GETSTATZ:
-	case SONET_GETDIAG:
-	case SONET_SETDIAG:
-	case SONET_CLRDIAG:
-	case SONET_SETFRAMING:
-	case SONET_GETFRAMING:
-	case SONET_GETFRSENSE:
-		return do_atm_ioctl(net, sock, cmd, arg);
-
-	case ATMSIGD_CTRL:
-	case ATMARPD_CTRL:
-	case ATMLEC_CTRL:
-	case ATMLEC_MCAST:
-	case ATMLEC_DATA:
-	case ATM_SETSC:
-	case SIOCSIFATMTCP:
-	case SIOCMKCLIP:
-	case ATMARP_MKIP:
-	case ATMARP_SETENTRY:
-	case ATMARP_ENCAP:
-	case ATMTCP_CREATE:
-	case ATMTCP_REMOVE:
-	case ATMMPC_CTRL:
-	case ATMMPC_DATA:
-
 	case SIOCSARP:
 	case SIOCGARP:
 	case SIOCDARP:
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH] net/atm: move all compat_ioctl handling to atm/ioctl.c
From: David Woodhouse @ 2009-11-11 13:34 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: David Miller, linux-kernel, netdev, eric.dumazet
In-Reply-To: <200911111430.44361.arnd@arndb.de>

On Wed, 2009-11-11 at 14:30 +0100, Arnd Bergmann wrote:
> 
> +struct atmif_sioc32 {
> +       compat_int_t    number;
> +       compat_int_t    length;
> +       compat_caddr_t  arg;
> +};
> +
> +struct atm_iobuf32 {
> +       compat_int_t    length;
> +       compat_caddr_t  buffer;
> +}; 

We already have compat_atmif_sioc and compat_atm_iobuf structures
defined -- do those need to be duplicated?

Other than that, it looks sane. I wish I'd noticed that we already had
half a COMPAT implementation when I added the new bits. Thanks.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

^ permalink raw reply

* [PATCH] net/compat: fix dev_ifsioc emulation corner cases
From: Arnd Bergmann @ 2009-11-11 13:39 UTC (permalink / raw)
  To: David Miller, linux-kernel, Patrick Ohly; +Cc: netdev
In-Reply-To: <20091110.204118.12070030.davem@davemloft.net>

Handling for SIOCSHWTSTAMP is broken on architectures
with a split user/kernel address space like s390,
because it passes a real user pointer while using
set_fs(KERNEL_DS).
A similar problem might arise the next time somebody
adds code to dev_ifsioc.

Split up dev_ifsioc into three separate functions for
SIOCSHWTSTAMP, SIOC*IFMAP and all other numbers so
we can get rid of set_fs in all potentially affected
cases.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Patrick Ohly <patrick.ohly@intel.com>
Cc: David S. Miller <davem@davemloft.net>
---
 net/socket.c |  117 +++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 72 insertions(+), 45 deletions(-)

Resending this one as well, rebased to current net-next.
Please tell me if you want a backport to 2.6.32 or -stable
for this one.

diff --git a/net/socket.c b/net/socket.c
index befd9f5..05c4828 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2723,38 +2723,15 @@ static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
 static int dev_ifsioc(struct net *net, struct socket *sock,
 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
 {
-	struct ifreq ifr;
-	struct compat_ifmap __user *uifmap32;
-	mm_segment_t old_fs;
+	struct ifreq __user *uifr;
 	int err;
 
-	uifmap32 = &uifr32->ifr_ifru.ifru_map;
-	switch (cmd) {
-	case SIOCSIFMAP:
-		err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
-		err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
-		err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
-		err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
-		err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
-		err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
-		err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
-		if (err)
-			return -EFAULT;
-		break;
-	case SIOCSHWTSTAMP:
-		if (copy_from_user(&ifr, uifr32, sizeof(*uifr32)))
-			return -EFAULT;
-		ifr.ifr_data = compat_ptr(uifr32->ifr_ifru.ifru_data);
-		break;
-	default:
-		if (copy_from_user(&ifr, uifr32, sizeof(*uifr32)))
-			return -EFAULT;
-		break;
-	}
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ifr);
-	set_fs (old_fs);
+	uifr = compat_alloc_user_space(sizeof(*uifr));
+	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
+		return -EFAULT;
+
+	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
+
 	if (!err) {
 		switch (cmd) {
 		case SIOCGIFFLAGS:
@@ -2771,18 +2748,7 @@ static int dev_ifsioc(struct net *net, struct socket *sock,
 		case SIOCGIFTXQLEN:
 		case SIOCGMIIPHY:
 		case SIOCGMIIREG:
-			if (copy_to_user(uifr32, &ifr, sizeof(*uifr32)))
-				return -EFAULT;
-			break;
-		case SIOCGIFMAP:
-			err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
-			err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
-			err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
-			err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
-			err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
-			err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
-			err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
-			if (err)
+			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
 				err = -EFAULT;
 			break;
 		}
@@ -2790,6 +2756,65 @@ static int dev_ifsioc(struct net *net, struct socket *sock,
 	return err;
 }
 
+static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
+			struct compat_ifreq __user *uifr32)
+{
+	struct ifreq ifr;
+	struct compat_ifmap __user *uifmap32;
+	mm_segment_t old_fs;
+	int err;
+
+	uifmap32 = &uifr32->ifr_ifru.ifru_map;
+	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
+	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
+	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
+	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
+	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
+	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
+	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
+	if (err)
+		return -EFAULT;
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = dev_ioctl(net, cmd, (void __user *)&ifr);
+	set_fs (old_fs);
+
+	if (cmd == SIOCGIFMAP && !err) {
+		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
+		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
+		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
+		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
+		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
+		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
+		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
+		if (err)
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
+{
+	void __user *uptr;
+	compat_uptr_t uptr32;
+	struct ifreq __user *uifr;
+
+	uifr = compat_alloc_user_space(sizeof (*uifr));
+	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
+		return -EFAULT;
+
+	if (get_user(uptr32, &uifr32->ifr_data))
+		return -EFAULT;
+
+	uptr = compat_ptr(uptr32);
+
+	if (put_user(uptr, &uifr->ifr_data))
+		return -EFAULT;
+
+	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
+}
+
 struct rtentry32 {
 	u32   		rt_pad1;
 	struct sockaddr rt_dst;         /* target address               */
@@ -3081,6 +3106,9 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
 		return ethtool_ioctl(net, argp);
 	case SIOCWANDEV:
 		return compat_siocwandev(net, argp);
+	case SIOCGIFMAP:
+	case SIOCSIFMAP:
+		return compat_sioc_ifmap(net, cmd, argp);
 	case SIOCBONDENSLAVE:
 	case SIOCBONDRELEASE:
 	case SIOCBONDSETHWADDR:
@@ -3095,6 +3123,8 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
 		return do_siocgstamp(net, sock, cmd, argp);
 	case SIOCGSTAMPNS:
 		return do_siocgstampns(net, sock, cmd, argp);
+	case SIOCSHWTSTAMP:
+		return compat_siocshwtstamp(net, argp);
 
 	case FIOSETOWN:
 	case SIOCSPGRP:
@@ -3121,12 +3151,9 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
 	case SIOCGIFINDEX:
-	case SIOCGIFMAP:
-	case SIOCSIFMAP:
 	case SIOCGIFADDR:
 	case SIOCSIFADDR:
 	case SIOCSIFHWBROADCAST:
-	case SIOCSHWTSTAMP:
 	case SIOCDIFADDR:
 	case SIOCGIFBRDADDR:
 	case SIOCSIFBRDADDR:
-- 
1.6.3.3


^ permalink raw reply related

* [PATCH v3] net/atm: move all compat_ioctl handling to atm/ioctl.c
From: Arnd Bergmann @ 2009-11-11 13:45 UTC (permalink / raw)
  To: David Woodhouse; +Cc: David Miller, linux-kernel, netdev, eric.dumazet
In-Reply-To: <1257946490.25961.1396.camel@macbook.infradead.org>

We have two implementations of the compat_ioctl handling for ATM, the
one that we have had for ages in fs/compat_ioctl.c and the one added to
net/atm/ioctl.c by David Woodhouse. Unfortunately, both versions are
incomplete, and in practice we use a very confusing combination of the
two.

For ioctl numbers that have the same identifier on 32 and 64 bit systems,
we go directly through the compat_ioctl socket operation, for those that
differ, we do a conversion in fs/compat_ioctl.c.

This patch moves both variants into the vcc_compat_ioctl() function,
while preserving the current behaviour. It also kills off the COMPATIBLE_IOCTL
definitions that we never use here.
Doing it this way is clearly not a good solution, but I hope it is a
step into the right direction, so that someone is able to clean up this
mess for real.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
---

history:
v3: now with the duplicate data structures removed.

v2: ported to net-next, which has the code in net/socket.c

 net/atm/ioctl.c |  177 ++++++++++++++++++++++++++++++++++++++++++++-
 net/socket.c    |  218 -------------------------------------------------------
 2 files changed, 175 insertions(+), 220 deletions(-)

diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index 4da8892..2ea4099 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -191,8 +191,181 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 }
 
 #ifdef CONFIG_COMPAT
-int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+/*
+ * FIXME:
+ * The compat_ioctl handling is duplicated, using both these conversion
+ * routines and the compat argument to the actual handlers. Both
+ * versions are somewhat incomplete and should be merged, e.g. by
+ * moving the ioctl number translation into the actual handlers and
+ * killing the conversion code.
+ *
+ * -arnd, November 2009
+ */
+#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct compat_atmif_sioc)
+#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct compat_atm_iobuf)
+#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct compat_atmif_sioc)
+#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct compat_atmif_sioc)
+#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct compat_atmif_sioc)
+#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct compat_atmif_sioc)
+#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct compat_atmif_sioc)
+#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct compat_atmif_sioc)
+#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct compat_atmif_sioc)
+#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct compat_atmif_sioc)
+#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct compat_atmif_sioc)
+#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct compat_atmif_sioc)
+#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct compat_atmif_sioc)
+#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct compat_atmif_sioc)
+#define ATM_GETLOOP32	  _IOW('a', ATMIOC_SARCOM+2, struct compat_atmif_sioc)
+#define ATM_SETLOOP32	  _IOW('a', ATMIOC_SARCOM+3, struct compat_atmif_sioc)
+#define ATM_QUERYLOOP32	  _IOW('a', ATMIOC_SARCOM+4, struct compat_atmif_sioc)
+
+static struct {
+	unsigned int cmd32;
+	unsigned int cmd;
+} atm_ioctl_map[] = {
+	{ ATM_GETLINKRATE32, ATM_GETLINKRATE },
+	{ ATM_GETNAMES32,    ATM_GETNAMES },
+	{ ATM_GETTYPE32,     ATM_GETTYPE },
+	{ ATM_GETESI32,	     ATM_GETESI },
+	{ ATM_GETADDR32,     ATM_GETADDR },
+	{ ATM_RSTADDR32,     ATM_RSTADDR },
+	{ ATM_ADDADDR32,     ATM_ADDADDR },
+	{ ATM_DELADDR32,     ATM_DELADDR },
+	{ ATM_GETCIRANGE32,  ATM_GETCIRANGE },
+	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
+	{ ATM_SETESI32,	     ATM_SETESI },
+	{ ATM_SETESIF32,     ATM_SETESIF },
+	{ ATM_GETSTAT32,     ATM_GETSTAT },
+	{ ATM_GETSTATZ32,    ATM_GETSTATZ },
+	{ ATM_GETLOOP32,     ATM_GETLOOP },
+	{ ATM_SETLOOP32,     ATM_SETLOOP },
+	{ ATM_QUERYLOOP32,   ATM_QUERYLOOP },
+};
+
+#define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map)
+
+static int do_atm_iobuf(struct socket *sock, unsigned int cmd,
+			unsigned long arg)
+{
+	struct atm_iobuf __user *iobuf;
+	struct compat_atm_iobuf __user *iobuf32;
+	u32 data;
+	void __user *datap;
+	int len, err;
+
+	iobuf = compat_alloc_user_space(sizeof(*iobuf));
+	iobuf32 = compat_ptr(arg);
+
+	if (get_user(len, &iobuf32->length) ||
+	    get_user(data, &iobuf32->buffer))
+		return -EFAULT;
+	datap = compat_ptr(data);
+	if (put_user(len, &iobuf->length) ||
+	    put_user(datap, &iobuf->buffer))
+		return -EFAULT;
+
+	err = do_vcc_ioctl(sock, cmd, (unsigned long) iobuf, 0);
+
+	if (!err) {
+		if (copy_in_user(&iobuf32->length, &iobuf->length,
+				 sizeof(int)))
+			err = -EFAULT;
+	}
+
+	return err;
+}
+
+static int do_atmif_sioc(struct socket *sock, unsigned int cmd,
+			 unsigned long arg)
+{
+	struct atmif_sioc __user *sioc;
+	struct compat_atmif_sioc __user *sioc32;
+	u32 data;
+	void __user *datap;
+	int err;
+
+	sioc = compat_alloc_user_space(sizeof(*sioc));
+	sioc32 = compat_ptr(arg);
+
+	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int))
+	    || get_user(data, &sioc32->arg))
+		return -EFAULT;
+	datap = compat_ptr(data);
+	if (put_user(datap, &sioc->arg))
+		return -EFAULT;
+
+	err = do_vcc_ioctl(sock, cmd, (unsigned long) sioc, 0);
+
+	if (!err) {
+		if (copy_in_user(&sioc32->length, &sioc->length,
+				 sizeof(int)))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
+			unsigned long arg)
+{
+	int i;
+	unsigned int cmd = 0;
+
+	switch (cmd32) {
+	case SONET_GETSTAT:
+	case SONET_GETSTATZ:
+	case SONET_GETDIAG:
+	case SONET_SETDIAG:
+	case SONET_CLRDIAG:
+	case SONET_SETFRAMING:
+	case SONET_GETFRAMING:
+	case SONET_GETFRSENSE:
+		return do_atmif_sioc(sock, cmd32, arg);
+	}
+
+	for (i = 0; i < NR_ATM_IOCTL; i++) {
+		if (cmd32 == atm_ioctl_map[i].cmd32) {
+			cmd = atm_ioctl_map[i].cmd;
+			break;
+		}
+	}
+	if (i == NR_ATM_IOCTL)
+		return -EINVAL;
+
+	switch (cmd) {
+	case ATM_GETNAMES:
+		return do_atm_iobuf(sock, cmd, arg);
+
+	case ATM_GETLINKRATE:
+	case ATM_GETTYPE:
+	case ATM_GETESI:
+	case ATM_GETADDR:
+	case ATM_RSTADDR:
+	case ATM_ADDADDR:
+	case ATM_DELADDR:
+	case ATM_GETCIRANGE:
+	case ATM_SETCIRANGE:
+	case ATM_SETESI:
+	case ATM_SETESIF:
+	case ATM_GETSTAT:
+	case ATM_GETSTATZ:
+	case ATM_GETLOOP:
+	case ATM_SETLOOP:
+	case ATM_QUERYLOOP:
+		return do_atmif_sioc(sock, cmd, arg);
+	}
+
+	return -EINVAL;
+}
+
+int vcc_compat_ioctl(struct socket *sock, unsigned int cmd,
+		     unsigned long arg)
 {
-	return do_vcc_ioctl(sock, cmd, arg, 1);
+	int ret;
+
+	ret = do_vcc_ioctl(sock, cmd, arg, 1);
+	if (ret != -ENOIOCTLCMD)
+		return ret;
+
+	return do_atm_ioctl(sock, cmd, arg);
 }
 #endif
diff --git a/net/socket.c b/net/socket.c
index 05c4828..402abb3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -100,14 +100,6 @@
 #include <linux/if_tun.h>
 #include <linux/ipv6_route.h>
 #include <linux/route.h>
-#include <linux/atmdev.h>
-#include <linux/atmarp.h>
-#include <linux/atmsvc.h>
-#include <linux/atmlec.h>
-#include <linux/atmclip.h>
-#include <linux/atmmpc.h>
-#include <linux/atm_tcp.h>
-#include <linux/sonet.h>
 #include <linux/sockios.h>
 #include <linux/atalk.h>
 
@@ -2917,173 +2909,6 @@ static int old_bridge_ioctl(compat_ulong_t __user *argp)
 	return -EINVAL;
 }
 
-struct atmif_sioc32 {
-	compat_int_t	number;
-	compat_int_t	length;
-	compat_caddr_t	arg;
-};
-
-struct atm_iobuf32 {
-	compat_int_t	length;
-	compat_caddr_t	buffer;
-};
-
-#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
-#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
-#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
-#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
-#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
-#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
-#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
-#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
-#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
-#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
-#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
-#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
-#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
-#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
-#define ATM_GETLOOP32	  _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
-#define ATM_SETLOOP32	  _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
-#define ATM_QUERYLOOP32	  _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
-
-static struct {
-	unsigned int cmd32;
-	unsigned int cmd;
-} atm_ioctl_map[] = {
-	{ ATM_GETLINKRATE32, ATM_GETLINKRATE },
-	{ ATM_GETNAMES32,    ATM_GETNAMES },
-	{ ATM_GETTYPE32,     ATM_GETTYPE },
-	{ ATM_GETESI32,      ATM_GETESI },
-	{ ATM_GETADDR32,     ATM_GETADDR },
-	{ ATM_RSTADDR32,     ATM_RSTADDR },
-	{ ATM_ADDADDR32,     ATM_ADDADDR },
-	{ ATM_DELADDR32,     ATM_DELADDR },
-	{ ATM_GETCIRANGE32,  ATM_GETCIRANGE },
-	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
-	{ ATM_SETESI32,      ATM_SETESI },
-	{ ATM_SETESIF32,     ATM_SETESIF },
-	{ ATM_GETSTAT32,     ATM_GETSTAT },
-	{ ATM_GETSTATZ32,    ATM_GETSTATZ },
-	{ ATM_GETLOOP32,     ATM_GETLOOP },
-	{ ATM_SETLOOP32,     ATM_SETLOOP },
-	{ ATM_QUERYLOOP32,   ATM_QUERYLOOP }
-};
-
-#define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map)
-
-static int do_atm_iobuf(struct net *net, struct socket *sock,
-			 unsigned int cmd, unsigned long arg)
-{
-	struct atm_iobuf   __user *iobuf;
-	struct atm_iobuf32 __user *iobuf32;
-	u32 data;
-	void __user *datap;
-	int len, err;
-
-	iobuf = compat_alloc_user_space(sizeof(*iobuf));
-	iobuf32 = compat_ptr(arg);
-
-	if (get_user(len, &iobuf32->length) ||
-	    get_user(data, &iobuf32->buffer))
-		return -EFAULT;
-	datap = compat_ptr(data);
-	if (put_user(len, &iobuf->length) ||
-	    put_user(datap, &iobuf->buffer))
-		return -EFAULT;
-
-	err = sock_do_ioctl(net, sock, cmd, (unsigned long)iobuf);
-
-	if (!err) {
-		if (copy_in_user(&iobuf32->length, &iobuf->length,
-				 sizeof(int)))
-			err = -EFAULT;
-	}
-
-	return err;
-}
-
-static int do_atmif_sioc(struct net *net, struct socket *sock,
-			 unsigned int cmd, unsigned long arg)
-{
-	struct atmif_sioc   __user *sioc;
-	struct atmif_sioc32 __user *sioc32;
-	u32 data;
-	void __user *datap;
-	int err;
-
-	sioc = compat_alloc_user_space(sizeof(*sioc));
-	sioc32 = compat_ptr(arg);
-
-	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
-	    get_user(data, &sioc32->arg))
-		return -EFAULT;
-	datap = compat_ptr(data);
-	if (put_user(datap, &sioc->arg))
-		return -EFAULT;
-
-	err = sock_do_ioctl(net, sock, cmd, (unsigned long) sioc);
-
-	if (!err) {
-		if (copy_in_user(&sioc32->length, &sioc->length,
-				 sizeof(int)))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-static int do_atm_ioctl(struct net *net, struct socket *sock,
-			 unsigned int cmd32, unsigned long arg)
-{
-	int i;
-	unsigned int cmd = 0;
-
-	switch (cmd32) {
-	case SONET_GETSTAT:
-	case SONET_GETSTATZ:
-	case SONET_GETDIAG:
-	case SONET_SETDIAG:
-	case SONET_CLRDIAG:
-	case SONET_SETFRAMING:
-	case SONET_GETFRAMING:
-	case SONET_GETFRSENSE:
-		return do_atmif_sioc(net, sock, cmd32, arg);
-	}
-
-	for (i = 0; i < NR_ATM_IOCTL; i++) {
-		if (cmd32 == atm_ioctl_map[i].cmd32) {
-			cmd = atm_ioctl_map[i].cmd;
-			break;
-		}
-	}
-	if (i == NR_ATM_IOCTL)
-	        return -EINVAL;
-
-        switch (cmd) {
-	case ATM_GETNAMES:
-		return do_atm_iobuf(net, sock, cmd, arg);
-
-	case ATM_GETLINKRATE:
-	case ATM_GETTYPE:
-	case ATM_GETESI:
-	case ATM_GETADDR:
-	case ATM_RSTADDR:
-	case ATM_ADDADDR:
-	case ATM_DELADDR:
-	case ATM_GETCIRANGE:
-	case ATM_SETCIRANGE:
-	case ATM_SETESI:
-	case ATM_SETESIF:
-	case ATM_GETSTAT:
-	case ATM_GETSTATZ:
-	case ATM_GETLOOP:
-	case ATM_SETLOOP:
-	case ATM_QUERYLOOP:
-		return do_atmif_sioc(net, sock, cmd, arg);
-	}
-
-	return -EINVAL;
-}
-
 static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
 			 unsigned int cmd, unsigned long arg)
 {
@@ -3173,49 +2998,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
 	case SIOCSMIIREG:
 		return dev_ifsioc(net, sock, cmd, argp);
 
-	case ATM_GETLINKRATE32:
-	case ATM_GETNAMES32:
-	case ATM_GETTYPE32:
-	case ATM_GETESI32:
-	case ATM_GETADDR32:
-	case ATM_RSTADDR32:
-	case ATM_ADDADDR32:
-	case ATM_DELADDR32:
-	case ATM_GETCIRANGE32:
-	case ATM_SETCIRANGE32:
-	case ATM_SETESI32:
-	case ATM_SETESIF32:
-	case ATM_GETSTAT32:
-	case ATM_GETSTATZ32:
-	case ATM_GETLOOP32:
-	case ATM_SETLOOP32:
-	case ATM_QUERYLOOP32:
-	case SONET_GETSTAT:
-	case SONET_GETSTATZ:
-	case SONET_GETDIAG:
-	case SONET_SETDIAG:
-	case SONET_CLRDIAG:
-	case SONET_SETFRAMING:
-	case SONET_GETFRAMING:
-	case SONET_GETFRSENSE:
-		return do_atm_ioctl(net, sock, cmd, arg);
-
-	case ATMSIGD_CTRL:
-	case ATMARPD_CTRL:
-	case ATMLEC_CTRL:
-	case ATMLEC_MCAST:
-	case ATMLEC_DATA:
-	case ATM_SETSC:
-	case SIOCSIFATMTCP:
-	case SIOCMKCLIP:
-	case ATMARP_MKIP:
-	case ATMARP_SETENTRY:
-	case ATMARP_ENCAP:
-	case ATMTCP_CREATE:
-	case ATMTCP_REMOVE:
-	case ATMMPC_CTRL:
-	case ATMMPC_DATA:
-
 	case SIOCSARP:
 	case SIOCGARP:
 	case SIOCDARP:
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH 04/10] AOE: use rcu to find network device
From: Ed Cashin @ 2009-11-11 14:22 UTC (permalink / raw)
  To: shemminger, ecashin, davem, harvey.harrison, bzolnier, netdev
In-Reply-To: <20091110150617.0e6920f0@nehalam>

On Tue Nov 10 18:06:41 EST 2009, shemminger@vyatta.com wrote:
...
> Hmm, looks like AOE actually is not ref counting the network device.
> So my patch is incorrect. 
> 
> As it stands (before my patch), it is UNSAFE. It can decide to queue
> packets to a device that is removed out from underneath it causing
> reference to freed memory.

Yes, that's right.  I will look at the patch you sent in the follow
up.  Thanks.

-- 
  Ed

^ permalink raw reply

* [PATCH] ARM: fix bug of checking on signed return value using unsigned statement in w90p910 platform
From: Wan ZongShun @ 2009-11-11 14:35 UTC (permalink / raw)
  To: David S. Miller, roel.kluin; +Cc: linux-arm-kernel, linux-netdev

Dear sir,

To fix the bug of checking on signed return value using unsigned statement.
Thanks Roel Kluin for digging out it. 

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>

---
 drivers/net/arm/w90p910_ether.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
index 25e2627..b7f3866 100644
--- a/drivers/net/arm/w90p910_ether.c
+++ b/drivers/net/arm/w90p910_ether.c
@@ -160,8 +160,8 @@ struct  w90p910_ether {
 	struct mii_if_info mii;
 	struct timer_list check_timer;
 	void __iomem *reg;
-	unsigned int rxirq;
-	unsigned int txirq;
+	int rxirq;
+	int txirq;
 	unsigned int cur_tx;
 	unsigned int cur_rx;
 	unsigned int finish_tx;
-- 
1.5.6.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox