diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2009-11-05 23:56:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-05 23:56:07 -0500 |
commit | b4ec824021493ba6cb7eeb61572f4d2f8a80a52e (patch) | |
tree | 17a2848c3deac1ad7efd24bfae43fb019f35cd19 | |
parent | 1056bd51674e529813213186471bb4ac6689a755 (diff) |
rose: device refcount leak
While hunting dev_put() for net-next-2.6, I found a device refcount
leak in ROSE, ioctl(SIOCADDRT) error path.
Fix is to not touch device refcount, as we hold RTNL
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/rose/rose_route.c | 16 |
1 files changed, 6 insertions, 10 deletions
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 9478d9b3d977..f3e21989b88c 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -578,18 +578,18 @@ static int rose_clear_routes(void) | |||
578 | 578 | ||
579 | /* | 579 | /* |
580 | * Check that the device given is a valid AX.25 interface that is "up". | 580 | * Check that the device given is a valid AX.25 interface that is "up". |
581 | * called whith RTNL | ||
581 | */ | 582 | */ |
582 | static struct net_device *rose_ax25_dev_get(char *devname) | 583 | static struct net_device *rose_ax25_dev_find(char *devname) |
583 | { | 584 | { |
584 | struct net_device *dev; | 585 | struct net_device *dev; |
585 | 586 | ||
586 | if ((dev = dev_get_by_name(&init_net, devname)) == NULL) | 587 | if ((dev = __dev_get_by_name(&init_net, devname)) == NULL) |
587 | return NULL; | 588 | return NULL; |
588 | 589 | ||
589 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25) | 590 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25) |
590 | return dev; | 591 | return dev; |
591 | 592 | ||
592 | dev_put(dev); | ||
593 | return NULL; | 593 | return NULL; |
594 | } | 594 | } |
595 | 595 | ||
@@ -720,27 +720,23 @@ int rose_rt_ioctl(unsigned int cmd, void __user *arg) | |||
720 | case SIOCADDRT: | 720 | case SIOCADDRT: |
721 | if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) | 721 | if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) |
722 | return -EFAULT; | 722 | return -EFAULT; |
723 | if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL) | 723 | if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL) |
724 | return -EINVAL; | 724 | return -EINVAL; |
725 | if (rose_dev_exists(&rose_route.address)) { /* Can't add routes to ourself */ | 725 | if (rose_dev_exists(&rose_route.address)) /* Can't add routes to ourself */ |
726 | dev_put(dev); | ||
727 | return -EINVAL; | 726 | return -EINVAL; |
728 | } | ||
729 | if (rose_route.mask > 10) /* Mask can't be more than 10 digits */ | 727 | if (rose_route.mask > 10) /* Mask can't be more than 10 digits */ |
730 | return -EINVAL; | 728 | return -EINVAL; |
731 | if (rose_route.ndigis > AX25_MAX_DIGIS) | 729 | if (rose_route.ndigis > AX25_MAX_DIGIS) |
732 | return -EINVAL; | 730 | return -EINVAL; |
733 | err = rose_add_node(&rose_route, dev); | 731 | err = rose_add_node(&rose_route, dev); |
734 | dev_put(dev); | ||
735 | return err; | 732 | return err; |
736 | 733 | ||
737 | case SIOCDELRT: | 734 | case SIOCDELRT: |
738 | if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) | 735 | if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) |
739 | return -EFAULT; | 736 | return -EFAULT; |
740 | if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL) | 737 | if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL) |
741 | return -EINVAL; | 738 | return -EINVAL; |
742 | err = rose_del_node(&rose_route, dev); | 739 | err = rose_del_node(&rose_route, dev); |
743 | dev_put(dev); | ||
744 | return err; | 740 | return err; |
745 | 741 | ||
746 | case SIOCRSCLRRT: | 742 | case SIOCRSCLRRT: |