Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'net-rose-fix-module-unload-issues'

Eric Dumazet says:

====================
net: rose: fix module unload issues

Bernard Pidoux reported that unloading rose module could lead
to infamous "unregistered_netdevice:" issues.

First patch is the fix, stable candidate.
Second patch is adding netdev ref tracker to af_rose.

I chose net-next to not inflict merge conflicts, because
Jakub changed dev_put_track() to netdev_put_track() in net-next.
====================

Link: https://lore.kernel.org/r/20220729091233.1030680-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+19 -3
+2 -1
include/net/rose.h
··· 132 132 ax25_address source_digis[ROSE_MAX_DIGIS]; 133 133 ax25_address dest_digis[ROSE_MAX_DIGIS]; 134 134 struct rose_neigh *neighbour; 135 - struct net_device *device; 135 + struct net_device *device; 136 + netdevice_tracker dev_tracker; 136 137 unsigned int lci, rand; 137 138 unsigned char state, condition, qbitincl, defer; 138 139 unsigned char cause, diagnostic;
+15 -2
net/rose/af_rose.c
··· 192 192 rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); 193 193 if (rose->neighbour) 194 194 rose->neighbour->use--; 195 + netdev_put(rose->device, &rose->dev_tracker); 195 196 rose->device = NULL; 196 197 } 197 198 } ··· 593 592 rose->idle = orose->idle; 594 593 rose->defer = orose->defer; 595 594 rose->device = orose->device; 595 + if (rose->device) 596 + netdev_hold(rose->device, &rose->dev_tracker, GFP_ATOMIC); 596 597 rose->qbitincl = orose->qbitincl; 597 598 598 599 return sk; ··· 648 645 break; 649 646 } 650 647 648 + netdev_put(rose->device, &rose->dev_tracker); 651 649 sock->sk = NULL; 652 650 release_sock(sk); 653 651 sock_put(sk); ··· 700 696 701 697 rose->source_addr = addr->srose_addr; 702 698 rose->device = dev; 699 + netdev_tracker_alloc(rose->device, &rose->dev_tracker, GFP_KERNEL); 703 700 rose->source_ndigis = addr->srose_ndigis; 704 701 705 702 if (addr_len == sizeof(struct full_sockaddr_rose)) { ··· 726 721 struct rose_sock *rose = rose_sk(sk); 727 722 struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; 728 723 unsigned char cause, diagnostic; 729 - struct net_device *dev; 730 724 ax25_uid_assoc *user; 731 725 int n, err = 0; 732 726 ··· 782 778 } 783 779 784 780 if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */ 781 + struct net_device *dev; 782 + 785 783 sock_reset_flag(sk, SOCK_ZAPPED); 786 784 787 - if ((dev = rose_dev_first()) == NULL) { 785 + dev = rose_dev_first(); 786 + if (!dev) { 788 787 err = -ENETUNREACH; 789 788 goto out_release; 790 789 } ··· 795 788 user = ax25_findbyuid(current_euid()); 796 789 if (!user) { 797 790 err = -EINVAL; 791 + dev_put(dev); 798 792 goto out_release; 799 793 } 800 794 801 795 memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); 802 796 rose->source_call = user->call; 803 797 rose->device = dev; 798 + netdev_tracker_alloc(rose->device, &rose->dev_tracker, 799 + GFP_KERNEL); 804 800 ax25_uid_put(user); 805 801 806 802 rose_insert_socket(sk); /* Finish the bind */ ··· 1027 1017 make_rose->source_digis[n] = facilities.source_digis[n]; 1028 1018 make_rose->neighbour = neigh; 1029 1019 make_rose->device = dev; 1020 + /* Caller got a reference for us. */ 1021 + netdev_tracker_alloc(make_rose->device, &make_rose->dev_tracker, 1022 + GFP_ATOMIC); 1030 1023 make_rose->facilities = facilities; 1031 1024 1032 1025 make_rose->neighbour->use++;
+2
net/rose/rose_route.c
··· 615 615 if (first == NULL || strncmp(dev->name, first->name, 3) < 0) 616 616 first = dev; 617 617 } 618 + if (first) 619 + dev_hold(first); 618 620 rcu_read_unlock(); 619 621 620 622 return first;