Commit 076a2e8f authored by Chas Williams's avatar Chas Williams Committed by Stephen Hemminger

[ATM]: In atm_getaddr() do not copy_to_user() with locks held.

parent 70150e54
...@@ -118,23 +118,24 @@ int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size) ...@@ -118,23 +118,24 @@ int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size)
{ {
unsigned long flags; unsigned long flags;
struct atm_dev_addr *walk; struct atm_dev_addr *walk;
int total; int total = 0, error;
struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
total = 0; for (walk = dev->local; walk; walk = walk->next)
for (walk = dev->local; walk; walk = walk->next) {
total += sizeof(struct sockaddr_atmsvc); total += sizeof(struct sockaddr_atmsvc);
if (total > size) { tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
spin_unlock_irqrestore(&dev->lock, flags); if (!tmp_buf) {
return -E2BIG; spin_unlock_irqrestore(&dev->lock, flags);
} return -ENOMEM;
if (copy_to_user(u_buf,&walk->addr,
sizeof(struct sockaddr_atmsvc))) {
spin_unlock_irqrestore(&dev->lock, flags);
return -EFAULT;
}
u_buf++;
} }
for (walk = dev->local; walk; walk = walk->next)
memcpy(tmp_bufp++, &walk->addr, sizeof(struct sockaddr_atmsvc));
spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags);
return total; error = total > size ? -E2BIG : total;
if (copy_to_user(u_buf, tmp_buf, total < size ? total : size))
error = -EFAULT;
kfree(tmp_buf);
return error;
} }
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