diff options
Diffstat (limited to 'net/ax25/ax25_dev.c')
| -rw-r--r-- | net/ax25/ax25_dev.c | 28 | 
1 files changed, 23 insertions, 5 deletions
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c index 256fadb94df3..d2a244e1c260 100644 --- a/net/ax25/ax25_dev.c +++ b/net/ax25/ax25_dev.c @@ -37,6 +37,7 @@ ax25_dev *ax25_addr_ax25dev(ax25_address *addr)  	for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)  		if (ax25cmp(addr, (const ax25_address *)ax25_dev->dev->dev_addr) == 0) {  			res = ax25_dev; +			ax25_dev_hold(ax25_dev);  		}  	spin_unlock_bh(&ax25_dev_lock); @@ -56,6 +57,7 @@ void ax25_dev_device_up(struct net_device *dev)  		return;  	} +	refcount_set(&ax25_dev->refcount, 1);  	dev->ax25_ptr     = ax25_dev;  	ax25_dev->dev     = dev;  	dev_hold_track(dev, &ax25_dev->dev_tracker, GFP_ATOMIC); @@ -84,6 +86,7 @@ void ax25_dev_device_up(struct net_device *dev)  	ax25_dev->next = ax25_dev_list;  	ax25_dev_list  = ax25_dev;  	spin_unlock_bh(&ax25_dev_lock); +	ax25_dev_hold(ax25_dev);  	ax25_register_dev_sysctl(ax25_dev);  } @@ -113,9 +116,10 @@ void ax25_dev_device_down(struct net_device *dev)  	if ((s = ax25_dev_list) == ax25_dev) {  		ax25_dev_list = s->next;  		spin_unlock_bh(&ax25_dev_lock); +		ax25_dev_put(ax25_dev);  		dev->ax25_ptr = NULL;  		dev_put_track(dev, &ax25_dev->dev_tracker); -		kfree(ax25_dev); +		ax25_dev_put(ax25_dev);  		return;  	} @@ -123,9 +127,10 @@ void ax25_dev_device_down(struct net_device *dev)  		if (s->next == ax25_dev) {  			s->next = ax25_dev->next;  			spin_unlock_bh(&ax25_dev_lock); +			ax25_dev_put(ax25_dev);  			dev->ax25_ptr = NULL;  			dev_put_track(dev, &ax25_dev->dev_tracker); -			kfree(ax25_dev); +			ax25_dev_put(ax25_dev);  			return;  		} @@ -133,6 +138,7 @@ void ax25_dev_device_down(struct net_device *dev)  	}  	spin_unlock_bh(&ax25_dev_lock);  	dev->ax25_ptr = NULL; +	ax25_dev_put(ax25_dev);  }  int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd) @@ -144,20 +150,32 @@ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)  	switch (cmd) {  	case SIOCAX25ADDFWD: -		if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL) +		fwd_dev = ax25_addr_ax25dev(&fwd->port_to); +		if (!fwd_dev) { +			ax25_dev_put(ax25_dev);  			return -EINVAL; -		if (ax25_dev->forward != NULL) +		} +		if (ax25_dev->forward) { +			ax25_dev_put(fwd_dev); +			ax25_dev_put(ax25_dev);  			return -EINVAL; +		}  		ax25_dev->forward = fwd_dev->dev; +		ax25_dev_put(fwd_dev); +		ax25_dev_put(ax25_dev);  		break;  	case SIOCAX25DELFWD: -		if (ax25_dev->forward == NULL) +		if (!ax25_dev->forward) { +			ax25_dev_put(ax25_dev);  			return -EINVAL; +		}  		ax25_dev->forward = NULL; +		ax25_dev_put(ax25_dev);  		break;  	default: +		ax25_dev_put(ax25_dev);  		return -EINVAL;  	}  | 
