Commit 5615968a authored by David S. Miller's avatar David S. Miller

appletalk: Add proper locking around IPDDP routing table.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 385a154c
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n"; static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n";
static struct ipddp_route *ipddp_route_list; static struct ipddp_route *ipddp_route_list;
static DEFINE_SPINLOCK(ipddp_route_lock);
#ifdef CONFIG_IPDDP_ENCAP #ifdef CONFIG_IPDDP_ENCAP
static int ipddp_mode = IPDDP_ENCAP; static int ipddp_mode = IPDDP_ENCAP;
...@@ -50,7 +51,7 @@ static int ipddp_mode = IPDDP_DECAP; ...@@ -50,7 +51,7 @@ static int ipddp_mode = IPDDP_DECAP;
static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev); static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev);
static int ipddp_create(struct ipddp_route *new_rt); static int ipddp_create(struct ipddp_route *new_rt);
static int ipddp_delete(struct ipddp_route *rt); static int ipddp_delete(struct ipddp_route *rt);
static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt); static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt);
static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static const struct net_device_ops ipddp_netdev_ops = { static const struct net_device_ops ipddp_netdev_ops = {
...@@ -119,6 +120,8 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -119,6 +120,8 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
struct ipddp_route *rt; struct ipddp_route *rt;
struct atalk_addr *our_addr; struct atalk_addr *our_addr;
spin_lock(&ipddp_route_lock);
/* /*
* Find appropriate route to use, based only on IP number. * Find appropriate route to use, based only on IP number.
*/ */
...@@ -127,8 +130,10 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -127,8 +130,10 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
if(rt->ip == paddr) if(rt->ip == paddr)
break; break;
} }
if(rt == NULL) if(rt == NULL) {
spin_unlock(&ipddp_route_lock);
return 0; return 0;
}
our_addr = atalk_find_dev_addr(rt->dev); our_addr = atalk_find_dev_addr(rt->dev);
...@@ -174,6 +179,8 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -174,6 +179,8 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0) if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0)
dev_kfree_skb(skb); dev_kfree_skb(skb);
spin_unlock(&ipddp_route_lock);
return 0; return 0;
} }
...@@ -196,7 +203,9 @@ static int ipddp_create(struct ipddp_route *new_rt) ...@@ -196,7 +203,9 @@ static int ipddp_create(struct ipddp_route *new_rt)
return -ENETUNREACH; return -ENETUNREACH;
} }
if (ipddp_find_route(rt)) { spin_lock_bh(&ipddp_route_lock);
if (__ipddp_find_route(rt)) {
spin_unlock_bh(&ipddp_route_lock);
kfree(rt); kfree(rt);
return -EEXIST; return -EEXIST;
} }
...@@ -204,6 +213,8 @@ static int ipddp_create(struct ipddp_route *new_rt) ...@@ -204,6 +213,8 @@ static int ipddp_create(struct ipddp_route *new_rt)
rt->next = ipddp_route_list; rt->next = ipddp_route_list;
ipddp_route_list = rt; ipddp_route_list = rt;
spin_unlock_bh(&ipddp_route_lock);
return 0; return 0;
} }
...@@ -216,6 +227,7 @@ static int ipddp_delete(struct ipddp_route *rt) ...@@ -216,6 +227,7 @@ static int ipddp_delete(struct ipddp_route *rt)
struct ipddp_route **r = &ipddp_route_list; struct ipddp_route **r = &ipddp_route_list;
struct ipddp_route *tmp; struct ipddp_route *tmp;
spin_lock_bh(&ipddp_route_lock);
while((tmp = *r) != NULL) while((tmp = *r) != NULL)
{ {
if(tmp->ip == rt->ip if(tmp->ip == rt->ip
...@@ -223,19 +235,21 @@ static int ipddp_delete(struct ipddp_route *rt) ...@@ -223,19 +235,21 @@ static int ipddp_delete(struct ipddp_route *rt)
&& tmp->at.s_node == rt->at.s_node) && tmp->at.s_node == rt->at.s_node)
{ {
*r = tmp->next; *r = tmp->next;
spin_unlock_bh(&ipddp_route_lock);
kfree(tmp); kfree(tmp);
return 0; return 0;
} }
r = &tmp->next; r = &tmp->next;
} }
spin_unlock_bh(&ipddp_route_lock);
return (-ENOENT); return (-ENOENT);
} }
/* /*
* Find a routing entry, we only return a FULL match * Find a routing entry, we only return a FULL match
*/ */
static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt) static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt)
{ {
struct ipddp_route *f; struct ipddp_route *f;
...@@ -253,7 +267,7 @@ static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt) ...@@ -253,7 +267,7 @@ static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt)
static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
struct ipddp_route __user *rt = ifr->ifr_data; struct ipddp_route __user *rt = ifr->ifr_data;
struct ipddp_route rcp; struct ipddp_route rcp, rcp2, *rp;
if(!capable(CAP_NET_ADMIN)) if(!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
...@@ -267,9 +281,19 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -267,9 +281,19 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return (ipddp_create(&rcp)); return (ipddp_create(&rcp));
case SIOCFINDIPDDPRT: case SIOCFINDIPDDPRT:
if(copy_to_user(rt, ipddp_find_route(&rcp), sizeof(struct ipddp_route))) spin_lock_bh(&ipddp_route_lock);
rp = __ipddp_find_route(&rcp);
if (rp)
memcpy(&rcp2, rp, sizeof(rcp2));
spin_unlock_bh(&ipddp_route_lock);
if (rp) {
if (copy_to_user(rt, &rcp2,
sizeof(struct ipddp_route)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} else
return -ENOENT;
case SIOCDELIPDDPRT: case SIOCDELIPDDPRT:
return (ipddp_delete(&rcp)); return (ipddp_delete(&rcp));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment