Message ID | 20220325150420.029041400@linuxfoundation.org |
---|---|
State | Superseded |
Headers | show |
Series | None | expand |
Hi! > From: Eric Dumazet <edumazet@google.com> > > commit 764f4eb6846f5475f1244767d24d25dd86528a4a upstream. > > Whenever llc_ui_bind() and/or llc_ui_autobind() > took a reference on a netdevice but subsequently fail, > they must properly release their reference > or risk the infamous message from unregister_netdevice() > at device dismantle. > > unregister_netdevice: waiting for eth0 to become free. Usage count = > 3 Can someone check this? AFAICT this is buggy. static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) { struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap; int rc = -EINVAL; if (!sock_flag(sk, SOCK_ZAPPED)) goto out; There are 'goto out's from both before dev_get() and after it, dev_put() will be called with NULL pointer. dev_put() can't handle NULL at least in the old kernels... this is simply confused. Mainline has dev_put_track() there, but I see same confusion. Best regards, Pavel > --- a/net/llc/af_llc.c > +++ b/net/llc/af_llc.c > @@ -311,6 +311,10 @@ static int llc_ui_autobind(struct socket > sock_reset_flag(sk, SOCK_ZAPPED); > rc = 0; > out: > + if (rc) { > + dev_put(llc->dev); > + llc->dev = NULL; > + } > return rc; > } > > @@ -409,6 +413,10 @@ static int llc_ui_bind(struct socket *so > out_put: > llc_sap_put(sap); > out: > + if (rc) { > + dev_put(llc->dev); > + llc->dev = NULL; > + } > release_sock(sk); > return rc; > } >
On Sat, 26 Mar 2022 21:09:22 +0100 Pavel Machek wrote: > Can someone check this? AFAICT this is buggy. > > static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) > { > struct sock *sk = sock->sk; > struct llc_sock *llc = llc_sk(sk); > struct llc_sap *sap; > int rc = -EINVAL; > > if (!sock_flag(sk, SOCK_ZAPPED)) > goto out; > > There are 'goto out's from both before dev_get() and after it, > dev_put() will be called with NULL pointer. dev_put() can't handle > NULL at least in the old kernels... this is simply confused. > > Mainline has dev_put_track() there, but I see same confusion. > > Best regards, commit 2d327a79ee17 ("llc: only change llc->dev when bind() succeeds"), https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=2d327a79ee176930dc72c131a970c891d367c1dc Should be in mainline on Thursday, LMK if we need to accelerate. IDK if anyone enables LLC2.
Hi! > > Can someone check this? AFAICT this is buggy. > > > > static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) > > { > > struct sock *sk = sock->sk; > > struct llc_sock *llc = llc_sk(sk); > > struct llc_sap *sap; > > int rc = -EINVAL; > > > > if (!sock_flag(sk, SOCK_ZAPPED)) > > goto out; > > > > There are 'goto out's from both before dev_get() and after it, > > dev_put() will be called with NULL pointer. dev_put() can't handle > > NULL at least in the old kernels... this is simply confused. > > > > Mainline has dev_put_track() there, but I see same confusion. > > > > Best regards, > > commit 2d327a79ee17 ("llc: only change llc->dev when bind() succeeds"), > https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=2d327a79ee176930dc72c131a970c891d367c1dc > > Should be in mainline on Thursday, LMK if we need to accelerate. > IDK if anyone enables LLC2. Thank you, yes, that looks good at the fast glance. But this patch does more harm than good on its own, so I believe it should be dropped for now, and only queued when the fixes are available. Best regards, Pavel
On Sat, Mar 26, 2022 at 01:13:25PM -0700, Jakub Kicinski wrote: > On Sat, 26 Mar 2022 21:09:22 +0100 Pavel Machek wrote: > > Can someone check this? AFAICT this is buggy. > > > > static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) > > { > > struct sock *sk = sock->sk; > > struct llc_sock *llc = llc_sk(sk); > > struct llc_sap *sap; > > int rc = -EINVAL; > > > > if (!sock_flag(sk, SOCK_ZAPPED)) > > goto out; > > > > There are 'goto out's from both before dev_get() and after it, > > dev_put() will be called with NULL pointer. dev_put() can't handle > > NULL at least in the old kernels... this is simply confused. > > > > Mainline has dev_put_track() there, but I see same confusion. > > > > Best regards, > > commit 2d327a79ee17 ("llc: only change llc->dev when bind() succeeds"), > https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=2d327a79ee176930dc72c131a970c891d367c1dc > > Should be in mainline on Thursday, LMK if we need to accelerate. > IDK if anyone enables LLC2. I'll queue this up now, thanks. greg k-h
Hi! > > > Can someone check this? AFAICT this is buggy. > > > > > > static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) > > > { > > > struct sock *sk = sock->sk; > > > struct llc_sock *llc = llc_sk(sk); > > > struct llc_sap *sap; > > > int rc = -EINVAL; > > > > > > if (!sock_flag(sk, SOCK_ZAPPED)) > > > goto out; > > > > > > There are 'goto out's from both before dev_get() and after it, > > > dev_put() will be called with NULL pointer. dev_put() can't handle > > > NULL at least in the old kernels... this is simply confused. > > > > > > Mainline has dev_put_track() there, but I see same confusion. > > > > > > Best regards, > > > > commit 2d327a79ee17 ("llc: only change llc->dev when bind() succeeds"), > > https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=2d327a79ee176930dc72c131a970c891d367c1dc > > > > Should be in mainline on Thursday, LMK if we need to accelerate. > > IDK if anyone enables LLC2. > > I'll queue this up now, thanks. As the changelog says, this needs b37a46683739, otherwise there will be oops-es in even more cases. Best regards, Pavel
Hi! > > > > commit 2d327a79ee17 ("llc: only change llc->dev when bind() succeeds"), > > > > https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=2d327a79ee176930dc72c131a970c891d367c1dc > > > > > > > > Should be in mainline on Thursday, LMK if we need to accelerate. > > > > IDK if anyone enables LLC2. > > > > > > I'll queue this up now, thanks. > > > > As the changelog says, this needs b37a46683739, otherwise there will > > be oops-es in even more cases. > > If you look at the change, I think I already handled that issue. If > not, please let me know. Actually, AFAICT it will now oops even in the common (non-error) path in llc_ui_autobind(). Best regards, Pavel
On Mon, Mar 28, 2022 at 11:31:16AM +0200, Pavel Machek wrote: > Hi! > > > > > > Should be in mainline on Thursday, LMK if we need to accelerate. > > > > > IDK if anyone enables LLC2. > > > > > > > > I'll queue this up now, thanks. > > > > > > As the changelog says, this needs b37a46683739, otherwise there will > > > be oops-es in even more cases. > > > > If you look at the change, I think I already handled that issue. If > > not, please let me know. > > I did not notice you making changes there, but no, it is not correct > AFAICT. > > # commit 163960a7de1333514c9352deb7c80c6b9fd9abf2 > # Author: Eric Dumazet <edumazet@google.com> > # Date: Thu Mar 24 20:58:27 2022 -0700 > > # llc: only change llc->dev when bind() succeeds > ... > # Make sure commit b37a46683739 ("netdevice: add the case if dev is NULL") > # is already present in your trees. > > Before b37a46683739, dev_put can't handle NULL. > > +++ b/net/llc/af_llc.c > @@ -287,14 +288,14 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) > ... > > - llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); > - if (!llc->dev) > + dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); > + if (!dev) > goto out; > rc = -EUSERS; > llc->laddr.lsap = llc_ui_autoport(); > > One of several paths where we goto out with dev==NULL. > > @@ -311,10 +317,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) > sock_reset_flag(sk, SOCK_ZAPPED); > rc = 0; > out: > - if (rc) { > - dev_put(llc->dev); > - llc->dev = NULL; > - } > + dev_put(dev); > return rc; > } > > > But dev_put can't handle NULL. Ah, missed that one. I'll go queue up b37a46683739 now. thanks, greg k-h
--- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -311,6 +311,10 @@ static int llc_ui_autobind(struct socket sock_reset_flag(sk, SOCK_ZAPPED); rc = 0; out: + if (rc) { + dev_put(llc->dev); + llc->dev = NULL; + } return rc; } @@ -409,6 +413,10 @@ static int llc_ui_bind(struct socket *so out_put: llc_sap_put(sap); out: + if (rc) { + dev_put(llc->dev); + llc->dev = NULL; + } release_sock(sk); return rc; }