Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4335704 authored by Cong Wang's avatar Cong Wang Committed by David S. Miller
Browse files

ax25: fix a use-after-free in ax25_fillin_cb()



There are multiple issues here:

1. After freeing dev->ax25_ptr, we need to set it to NULL otherwise
   we may use a dangling pointer.

2. There is a race between ax25_setsockopt() and device notifier as
   reported by syzbot. Close it by holding RTNL lock.

3. We need to test if dev->ax25_ptr is NULL before using it.

Reported-and-tested-by: default avatar <syzbot+ae6bb869cbed29b29040@syzkaller.appspotmail.com>
Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7f334a7e
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -653,15 +653,22 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
			break;
		}

		dev = dev_get_by_name(&init_net, devname);
		rtnl_lock();
		dev = __dev_get_by_name(&init_net, devname);
		if (!dev) {
			rtnl_unlock();
			res = -ENODEV;
			break;
		}

		ax25->ax25_dev = ax25_dev_ax25dev(dev);
		if (!ax25->ax25_dev) {
			rtnl_unlock();
			res = -ENODEV;
			break;
		}
		ax25_fillin_cb(ax25, ax25->ax25_dev);
		dev_put(dev);
		rtnl_unlock();
		break;

	default:
+2 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ 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);
		dev->ax25_ptr = NULL;
		dev_put(dev);
		kfree(ax25_dev);
		return;
@@ -125,6 +126,7 @@ 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);
			dev->ax25_ptr = NULL;
			dev_put(dev);
			kfree(ax25_dev);
			return;