Unverified Commit d636f566 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!1629 can: raw: fix receiver memory leak

Merge Pull Request from: @ci-robot 
 
PR sync from: Ziyang Xuan <william.xuanziyang@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/PN6CJX7CQ6YCEZFFWSQPDTGBGIIF7PGE/ 
Backport can/raw receiver memory leak fix commits.

Eric Dumazet (1):
  can: raw: fix lockdep issue in raw_release()

Ziyang Xuan (1):
  can: raw: fix receiver memory leak


-- 
2.25.1
 
https://gitee.com/openeuler/kernel/issues/I7PM10 
 
Link:https://gitee.com/openeuler/kernel/pulls/1629

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Signed-off-by: default avatarLiu YongQiang <liuyongqiang13@huawei.com>
parents c28ee72a ad3aec46
Loading
Loading
Loading
Loading
+29 −39
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ struct raw_sock {
	struct sock sk;
	int bound;
	int ifindex;
	struct net_device *dev;
	struct list_head notifier;
	int loopback;
	int recv_own_msgs;
@@ -278,7 +279,7 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,
	if (!net_eq(dev_net(dev), sock_net(sk)))
		return;

	if (ro->ifindex != dev->ifindex)
	if (ro->dev != dev)
		return;

	switch (msg) {
@@ -294,6 +295,7 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,

		ro->ifindex = 0;
		ro->bound = 0;
		ro->dev = NULL;
		ro->count = 0;
		release_sock(sk);

@@ -339,6 +341,7 @@ static int raw_init(struct sock *sk)

	ro->bound            = 0;
	ro->ifindex          = 0;
	ro->dev              = NULL;

	/* set default filter to single entry dfilter */
	ro->dfilter.can_id   = 0;
@@ -384,19 +387,14 @@ static int raw_release(struct socket *sock)
	list_del(&ro->notifier);
	spin_unlock(&raw_notifier_lock);

	rtnl_lock();
	lock_sock(sk);

	/* remove current filters & unregister */
	if (ro->bound) {
		if (ro->ifindex) {
			struct net_device *dev;

			dev = dev_get_by_index(sock_net(sk), ro->ifindex);
			if (dev) {
				raw_disable_allfilters(dev_net(dev), dev, sk);
				dev_put(dev);
			}
		} else
		if (ro->dev)
			raw_disable_allfilters(dev_net(ro->dev), ro->dev, sk);
		else
			raw_disable_allfilters(sock_net(sk), NULL, sk);
	}

@@ -405,6 +403,7 @@ static int raw_release(struct socket *sock)

	ro->ifindex = 0;
	ro->bound = 0;
	ro->dev = NULL;
	ro->count = 0;
	free_percpu(ro->uniq);

@@ -412,6 +411,8 @@ static int raw_release(struct socket *sock)
	sock->sk = NULL;

	release_sock(sk);
	rtnl_unlock();

	sock_put(sk);

	return 0;
@@ -422,6 +423,7 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
	struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
	struct sock *sk = sock->sk;
	struct raw_sock *ro = raw_sk(sk);
	struct net_device *dev = NULL;
	int ifindex;
	int err = 0;
	int notify_enetdown = 0;
@@ -431,14 +433,13 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
	if (addr->can_family != AF_CAN)
		return -EINVAL;

	rtnl_lock();
	lock_sock(sk);

	if (ro->bound && addr->can_ifindex == ro->ifindex)
		goto out;

	if (addr->can_ifindex) {
		struct net_device *dev;

		dev = dev_get_by_index(sock_net(sk), addr->can_ifindex);
		if (!dev) {
			err = -ENODEV;
@@ -467,25 +468,20 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
	if (!err) {
		if (ro->bound) {
			/* unregister old filters */
			if (ro->ifindex) {
				struct net_device *dev;

				dev = dev_get_by_index(sock_net(sk),
						       ro->ifindex);
				if (dev) {
					raw_disable_allfilters(dev_net(dev),
							       dev, sk);
					dev_put(dev);
				}
			} else
			if (ro->dev)
				raw_disable_allfilters(dev_net(ro->dev),
						       ro->dev, sk);
			else
				raw_disable_allfilters(sock_net(sk), NULL, sk);
		}
		ro->ifindex = ifindex;
		ro->bound = 1;
		ro->dev = dev;
	}

 out:
	release_sock(sk);
	rtnl_unlock();

	if (notify_enetdown) {
		sk->sk_err = ENETDOWN;
@@ -552,9 +548,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
		rtnl_lock();
		lock_sock(sk);

		if (ro->bound && ro->ifindex) {
			dev = dev_get_by_index(sock_net(sk), ro->ifindex);
			if (!dev) {
		dev = ro->dev;
		if (ro->bound && dev) {
			if (dev->reg_state != NETREG_REGISTERED) {
				if (count > 1)
					kfree(filter);
				err = -ENODEV;
@@ -595,9 +591,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
		ro->count  = count;

 out_fil:
		if (dev)
			dev_put(dev);

		release_sock(sk);
		rtnl_unlock();

@@ -615,9 +608,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
		rtnl_lock();
		lock_sock(sk);

		if (ro->bound && ro->ifindex) {
			dev = dev_get_by_index(sock_net(sk), ro->ifindex);
			if (!dev) {
		dev = ro->dev;
		if (ro->bound && dev) {
			if (dev->reg_state != NETREG_REGISTERED) {
				err = -ENODEV;
				goto out_err;
			}
@@ -641,9 +634,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
		ro->err_mask = err_mask;

 out_err:
		if (dev)
			dev_put(dev);

		release_sock(sk);
		rtnl_unlock();