diff mbox

[RFC] cfg80211: NL80211_ATTR_SOCKET_OWNER support for CMD_CONNECT

Message ID 20161202205611.14141-1-andrew.zaborowski@intel.com (mailing list archive)
State RFC
Delegated to: Johannes Berg
Headers show

Commit Message

Andrew Zaborowski Dec. 2, 2016, 8:56 p.m. UTC
Disconnect or deauthenticate when the owning socket is closed if this
flag has been supplied to CMD_CONNECT, CMD_AUTHENTICATE or CMD_ASSOCIATE.

Signed-off-by: Andrew Zaborowski <andrew.zaborowski@intel.com>
---
 include/net/cfg80211.h       |  5 +++++
 include/uapi/linux/nl80211.h |  3 +++
 net/wireless/core.c          | 23 +++++++++++++++++++++++
 net/wireless/mlme.c          |  4 ++++
 net/wireless/nl80211.c       | 29 ++++++++++++++++++++++++++++-
 net/wireless/sme.c           |  4 ++++
 6 files changed, 67 insertions(+), 1 deletion(-)

Comments

Johannes Berg Dec. 5, 2016, 1:51 p.m. UTC | #1
On Fri, 2016-12-02 at 21:56 +0100, Andrew Zaborowski wrote:
> Disconnect or deauthenticate when the owning socket is closed if this
> flag has been supplied to CMD_CONNECT, CMD_AUTHENTICATE or
> CMD_ASSOCIATE.

Huh. That I think needs a lot more commit log to justify this code -
why do you think this would be useful? Connection managers dying don't
really mean you need to disconnect immediately, after all, and if they
restart it's pretty simple to detect the existing connection and
perhaps even use it...

johannes
Denis Kenzior Dec. 5, 2016, 2:55 p.m. UTC | #2
Hi Johannes,

On 12/05/2016 07:51 AM, Johannes Berg wrote:
> On Fri, 2016-12-02 at 21:56 +0100, Andrew Zaborowski wrote:
>> Disconnect or deauthenticate when the owning socket is closed if this
>> flag has been supplied to CMD_CONNECT, CMD_AUTHENTICATE or
>> CMD_ASSOCIATE.
>
> Huh. That I think needs a lot more commit log to justify this code -
> why do you think this would be useful? Connection managers dying don't
> really mean you need to disconnect immediately, after all, and if they
> restart it's pretty simple to detect the existing connection and
> perhaps even use it...
>

Detecting it is easy, sure.  But I'm a bit lost on how you propose to 
'use' it.  The connection is active up until the next rekey event.  If 
rekey offloading is supported, then this might never involve user space. 
  But if it isn't (and I can't get rekey offload to work on any recent 
kernel I tried) then how do you propose userspace obtains the rekey 
counter, or the various keys used in the connection?

What about all the other state information?  FT, Pre-Authentication, etc?

Can you point me to a connection manager that actually performs this 
'reuse' and not just simply wipes the state clean when starting?

Regards,
-Denis
Johannes Berg Dec. 5, 2016, 2:58 p.m. UTC | #3
> Detecting it is easy, sure.  But I'm a bit lost on how you propose
> to 
> 'use' it.  The connection is active up until the next rekey
> event.  If 
> rekey offloading is supported, then this might never involve user
> space. 
>   But if it isn't (and I can't get rekey offload to work on any
> recent 
> kernel I tried) then how do you propose userspace obtains the rekey 
> counter, or the various keys used in the connection?
> 
> What about all the other state information?  FT, Pre-Authentication,
> etc?

Well, no, that'd only work with an open connection :)

johannes
Denis Kenzior Dec. 5, 2016, 3:05 p.m. UTC | #4
Hi Johannes,

On 12/05/2016 08:58 AM, Johannes Berg wrote:
>
>> Detecting it is easy, sure.  But I'm a bit lost on how you propose
>> to
>> 'use' it.  The connection is active up until the next rekey
>> event.  If
>> rekey offloading is supported, then this might never involve user
>> space.
>>    But if it isn't (and I can't get rekey offload to work on any
>> recent
>> kernel I tried) then how do you propose userspace obtains the rekey
>> counter, or the various keys used in the connection?
>>
>> What about all the other state information?  FT, Pre-Authentication,
>> etc?
>
> Well, no, that'd only work with an open connection :)
>

And even that is questionable in my mind for some of the more advanced 
cases.

But I'm not sure what your point is, do you still have objections to 
this approach?

Regards,
-Denis
Johannes Berg Dec. 5, 2016, 3:14 p.m. UTC | #5
> > Well, no, that'd only work with an open connection :)

Actually, it also works fairly easily for when firmware has 4-way-
handshake offload, which will be coming to a kernel near you soon.

> And even that is questionable in my mind for some of the more
> advanced cases.

Well, at least in that case you can have things running (for a while)
if the manager crashes?

> But I'm not sure what your point is, do you still have objections to 
> this approach?

Well, first of all, you can keep things running, at least until you've
figured out how to restart wpa_supplicant/whatever.

There also aren't really any important resources to clear when
userspace dies, at least nothing that userspace can't trivially clear
later by disconnecting (even unconditionally and ignoring the
result)...

So basically I just don't see the advantage. It feels like trading a
single line of userspace code to disconnect with some (not super
complex, but still somewhat involved) kernel-side tracking. That
doesn't really seem like a worthwhile tradeoff to me.

johannes
Denis Kenzior Dec. 5, 2016, 3:32 p.m. UTC | #6
Hi Johannes,

On 12/05/2016 09:14 AM, Johannes Berg wrote:
>>> Well, no, that'd only work with an open connection :)
>
> Actually, it also works fairly easily for when firmware has 4-way-
> handshake offload, which will be coming to a kernel near you soon.
>

Great, but still not applicable for all devices, and still questionable 
how useful an unmanaged connection actually is.  But okay.

>> And even that is questionable in my mind for some of the more
>> advanced cases.
>
> Well, at least in that case you can have things running (for a while)
> if the manager crashes?
>

To what purpose?  That's like saying that maybe a socket should be kept 
open in case an application crashes.

>> But I'm not sure what your point is, do you still have objections to
>> this approach?
>
> Well, first of all, you can keep things running, at least until you've
> figured out how to restart wpa_supplicant/whatever.
>
> There also aren't really any important resources to clear when
> userspace dies, at least nothing that userspace can't trivially clear
> later by disconnecting (even unconditionally and ignoring the
> result)...

Sure, but in the meantime you have a completely unmanaged connection, 
with no connection manager to tell you what the state of it is.  Maybe 
okay for a command line system with a brain in front of it, but not much 
use anywhere else.

But for that use case the SOCKET_OWNER attribute can be omitted...

>
> So basically I just don't see the advantage. It feels like trading a
> single line of userspace code to disconnect with some (not super
> complex, but still somewhat involved) kernel-side tracking. That
> doesn't really seem like a worthwhile tradeoff to me.
>

Well, we'd be trading quite a bit of race-prone user space code that 
performs the clean up on start up for one line of attributes.  I call 
that a good trade.

Also, I thought it was good form / the UNIX way to clean up after 
processes exit ungracefully.  You seem to be arguing against that?  I 
would argue the kernel should be doing the opposite.  It should always 
clean up the connection unless user space has indicated it can be 'reused'.

Regards,
-Denis
Marcel Holtmann Dec. 5, 2016, 3:40 p.m. UTC | #7
Hi Johannes,

>>> Well, no, that'd only work with an open connection :)
> 
> Actually, it also works fairly easily for when firmware has 4-way-
> handshake offload, which will be coming to a kernel near you soon.
> 
>> And even that is questionable in my mind for some of the more
>> advanced cases.
> 
> Well, at least in that case you can have things running (for a while)
> if the manager crashes?
> 
>> But I'm not sure what your point is, do you still have objections to 
>> this approach?
> 
> Well, first of all, you can keep things running, at least until you've
> figured out how to restart wpa_supplicant/whatever.
> 
> There also aren't really any important resources to clear when
> userspace dies, at least nothing that userspace can't trivially clear
> later by disconnecting (even unconditionally and ignoring the
> result)...
> 
> So basically I just don't see the advantage. It feels like trading a
> single line of userspace code to disconnect with some (not super
> complex, but still somewhat involved) kernel-side tracking. That
> doesn't really seem like a worthwhile tradeoff to me.

I do not get this argument. That is what WEXT forced you to do since the APIs were awful and clueless. I thought we have moved passed this messy userspace and racy guess work.

If I am a wireless management daemon, I want to decide what happens when I unexpectedly die or get killed for some reason where it is no longer in my control to do this. And there is no guarantee that the daemon even gets restarted. Now you leave dangling connections around. If userspace asks the kernel to clean up after it, then the kernel should be able to do so. That is the only sane option since everything else is racy. The daemon is not in control and has no idea how much time has passed or what happened while it was away. So the only clean thing to do, ask the kernel to disconnect in case something unexpected happens.

And frankly if the wireless daemon can not ask the kernel to clean up, how would a connection manager then even begin to handle this properly. It causes more races and more issues. It becomes a state tracking nightmare. And this is not some theoretical issue, we have seen all the issues with ConnMan. Remember that ConnMan runs in production consumer devices. So these things are real. These systems have to kill daemons for resource limits and other reasons that are out of the control of the daemon itself. And there is no recovery, and if there is, there is no knowing when that happens.

So userspace can clear later argument is not valid for me. If your userspace wants to do that, then fine. Our userspace does not want unsupervised or unmanaged connections. If it goes away, then it wants that these are cleared. And that option is clearly what this patch provides. I find this a clean and useful addition to nl80211. Why are you saying this is not worthwhile?

Regards

Marcel
Johannes Berg Dec. 6, 2016, 7:16 a.m. UTC | #8
On Mon, 2016-12-05 at 09:32 -0600, Denis Kenzior wrote:

> To what purpose?  That's like saying that maybe a socket should be
> kept open in case an application crashes.

That socket would be useless, so no, that's not comparable at all. It's
more like saying the disk should be unmounted once 'mount' exits ;-)

Anyway ... I'm not even super against this patch, but you need to fix
things:
 * this is actually wrong for authenticate - I'll let you figure out
   why by yourself
 * you need to teach people to write useful commit messages

johannes
Denis Kenzior Dec. 6, 2016, 9:42 p.m. UTC | #9
Hi Johannes,

On 12/06/2016 01:16 AM, Johannes Berg wrote:
> On Mon, 2016-12-05 at 09:32 -0600, Denis Kenzior wrote:
>
>> To what purpose?  That's like saying that maybe a socket should be
>> kept open in case an application crashes.
>
> That socket would be useless, so no, that's not comparable at all. It's
> more like saying the disk should be unmounted once 'mount' exits ;-)
>

Except the kernel doesn't want to reconfigure mount parameters every 
15-30 minutes.  So no, its not like 'mount' at all ;)  But I digress, I 
can see that we won't agree here.  But we still would like the kernel to 
clean up nicely if stuff hits the fan.

> Anyway ... I'm not even super against this patch, but you need to fix

I'm afraid to consider what you're like when you _are_ 'super' against 
something :)

> things:
>   * this is actually wrong for authenticate - I'll let you figure out
>     why by yourself

So here's a quick test, with the client triggering authenticate, then 
crashing:

< Request: Authenticate (0x25) len 52 [ack]                  362.339712
     Interface Index: 3 (0x00000003)
     Wiphy Frequency: 2417 (0x00000971)
     MAC Address <snip>
     SSID: len 9
         <snip>
     Auth Type: 0 (0x00000000)
 > Event: New Station (0x13) len 32                           362.341337
     Interface Index: 3 (0x00000003)
 > Response: Authenticate (0x25) len 4                        362.341860
     Status: Success (0)
 > Event: Authenticate (0x25) len 64                          362.343640
     Wiphy: 0 (0x00000000)
     Interface Index: 3 (0x00000003)
 > Event: Del Station (0x14) len 1144                         367.442024
     Interface Index: 3 (0x00000003)
     MAC Address <snip>

Pay attention to the time stamps.  The del station event comes in 5 
seconds or so after our client has aborted.  So for 5 seconds we have an 
unmanaged link to some AP.  It would be nice if the authentication was 
aborted as soon as we crash.

So again, why do you say that SOCKET_OWNER is 'wrong' for authenticate? 
  Or do you mean something else?

>   * you need to teach people to write useful commit messages

The commit description in this patch was lacking.  We both agree here.

Regards,
-Denis
Andrew Zaborowski Dec. 7, 2016, 1:40 a.m. UTC | #10
Hi,

On 6 December 2016 at 22:42, Denis Kenzior <denkenz@gmail.com> wrote:
> On 12/06/2016 01:16 AM, Johannes Berg wrote:
>> Anyway ... I'm not even super against this patch, but you need to fix
>> things:
>>   * this is actually wrong for authenticate - I'll let you figure out
>>     why by yourself
>
>
> So here's a quick test, with the client triggering authenticate, then
> crashing:
>
> < Request: Authenticate (0x25) len 52 [ack]                  362.339712
>     Interface Index: 3 (0x00000003)
>     Wiphy Frequency: 2417 (0x00000971)
>     MAC Address <snip>
>     SSID: len 9
>         <snip>
>     Auth Type: 0 (0x00000000)
>> Event: New Station (0x13) len 32                           362.341337
>     Interface Index: 3 (0x00000003)
>> Response: Authenticate (0x25) len 4                        362.341860
>     Status: Success (0)
>> Event: Authenticate (0x25) len 64                          362.343640
>     Wiphy: 0 (0x00000000)
>     Interface Index: 3 (0x00000003)
>> Event: Del Station (0x14) len 1144                         367.442024
>     Interface Index: 3 (0x00000003)
>     MAC Address <snip>
>
> Pay attention to the time stamps.  The del station event comes in 5 seconds
> or so after our client has aborted.  So for 5 seconds we have an unmanaged
> link to some AP.  It would be nice if the authentication was aborted as soon
> as we crash.
>
> So again, why do you say that SOCKET_OWNER is 'wrong' for authenticate?  Or
> do you mean something else?

Possibly Johanness refers to the fact that if you use
CMD_AUTHENTICATE, or if you use CMD_CONNECT but the driver implements
the SME -- doesn't use the cfg80211 software SME -- then
cfg80211_disconnect won't do anything if we're not associated, only
authenticated.  Currently cfg80211 doesn't have knowledge of whether
it is authenticated and where to.

With the software SME current_bss would be set from the moment the
authentication attempt starts, so there seems to be an inconsistency
which would affect for example the NL80211_BSS_STATUS_ASSOCIATED flags
in the result of CMD_GET_SCAN.  Perhaps this can be fixed by always
setting current_bss on auth attempt start, with flags to indicate
whether authentication has happened and whether association happened.

At the very least with this patch if you set the socket owner during
CMD_AUTHENTICATE and then separately associate, you'd get the expected
deauthentication.

Best regards
Johannes Berg Dec. 7, 2016, 6:15 a.m. UTC | #11
> I'm afraid to consider what you're like when you _are_ 'super'
> against something :)

Why, that's easy, there wouldn't be a long discussion like that ;-)

> So here's a quick test, with the client triggering authenticate, then
> crashing:

> < Request: Authenticate (0x25) len 52
> [ack]                  362.339712

> [...]

>  > Event: Del Station (0x14) len
> 1144                         367.442024

> Pay attention to the time stamps.  The del station event comes in 5 
> seconds or so after our client has aborted.  So for 5 seconds we have
> an unmanaged link to some AP.

No, this is the part you didn't understand. Simply authenticating
doesn't actually create anything like a "link" to the AP. The only
reason we keep the station entry around for a few seconds is that it
*probably* will be used next to associate. But if you don't do that, or
authenticate to some other AP, or do whatever else - nothing stops you
from doing that. There's no connection, nothing really stays active
except for this 5 second grace period to associate.

So even if you crash here like in the example, there's nothing to clean
up, a subsequent authentication attempt to the same or another AP will
go through anyway.

Therefore, there's nothing to "own" with an authentication attempt,
since it doesn't actually keep any (permanent) state in the kernel, and
keeping the station entry around is just an optimisation.

I don't think it's worth trying to clean that up.

Also, consider that authentication doesn't block anything, so another
socket might immediately do another authentication/association, and you
don't want to kill that even when the first one dies. Corner case,
sure, but at least with association the second one would get "-EBUSY"
or so, whereas authentication keeps no state in the kernel.

johannes
Johannes Berg Dec. 7, 2016, 6:19 a.m. UTC | #12
> Possibly Johanness refers to the fact that if you use
> CMD_AUTHENTICATE, or if you use CMD_CONNECT but the driver implements
> the SME -- doesn't use the cfg80211 software SME -- then
> cfg80211_disconnect won't do anything if we're not associated, only
> authenticated.  Currently cfg80211 doesn't have knowledge of whether
> it is authenticated and where to.

We used to track it, but it was a nightmare and just always buggy :)

> With the software SME current_bss would be set from the moment the
> authentication attempt starts, 

I'm almost certain this isn't true, what makes you think so?

> so there seems to be an inconsistency
> which would affect for example the NL80211_BSS_STATUS_ASSOCIATED
> flags in the result of CMD_GET_SCAN.

Thus this can't be the case.

> Perhaps this can be fixed by always
> setting current_bss on auth attempt start, with flags to indicate
> whether authentication has happened and whether association happened.

No! That would be wrong!

> At the very least with this patch if you set the socket owner during
> CMD_AUTHENTICATE and then separately associate, you'd get the
> expected deauthentication.

That would *NOT* be expected. There's no need to even authenticate
through CMD_AUTHENTICATE at all to connect to (another) AP!

You need to think beyond the 1996 version of 802.11 ;-)

johannes
Denis Kenzior Dec. 7, 2016, 6:40 a.m. UTC | #13
Hi Johannes,

On 12/07/2016 12:15 AM, Johannes Berg wrote:
>
>> I'm afraid to consider what you're like when you _are_ 'super'
>> against something :)
>
> Why, that's easy, there wouldn't be a long discussion like that ;-)

lol

>
> No, this is the part you didn't understand. Simply authenticating
> doesn't actually create anything like a "link" to the AP. The only

Okay, but it is then a bit misleading that iw link reports us being 
'connected' during this time for example.

> reason we keep the station entry around for a few seconds is that it
> *probably* will be used next to associate. But if you don't do that, or
> authenticate to some other AP, or do whatever else - nothing stops you
> from doing that. There's no connection, nothing really stays active
> except for this 5 second grace period to associate.
>
> So even if you crash here like in the example, there's nothing to clean
> up, a subsequent authentication attempt to the same or another AP will
> go through anyway.
>
> Therefore, there's nothing to "own" with an authentication attempt,
> since it doesn't actually keep any (permanent) state in the kernel, and
> keeping the station entry around is just an optimisation.
>
> I don't think it's worth trying to clean that up.

Fair enough.  I think we can live with that since we're not using 
CMD_AUTHENTICATE unless we need to roam using FT.

Regards,
-Denis
Johannes Berg Dec. 7, 2016, 6:48 a.m. UTC | #14
On Wed, 2016-12-07 at 00:40 -0600, Denis Kenzior wrote:

> > No, this is the part you didn't understand. Simply authenticating
> > doesn't actually create anything like a "link" to the AP. The only
> 
> Okay, but it is then a bit misleading that iw link reports us being 
> 'connected' during this time for example.

It doesn't!

# iw wlan0 auth <ssid> <bssid> open 2462

-> iw event reporting
wlan0 (phy #0): auth <localMAC> -> <bssid> status: 0: Successful

# iw wlan0 link
Not connected.


> Fair enough.  I think we can live with that since we're not using 
> CMD_AUTHENTICATE unless we need to roam using FT.

That seems like a very strange decision, but it's obviously up to you
:)

johannes
Denis Kenzior Dec. 7, 2016, 7:07 a.m. UTC | #15
Hi Johannes,

On 12/07/2016 12:48 AM, Johannes Berg wrote:
> On Wed, 2016-12-07 at 00:40 -0600, Denis Kenzior wrote:
>>
>>> No, this is the part you didn't understand. Simply authenticating
>>> doesn't actually create anything like a "link" to the AP. The only
>>
>> Okay, but it is then a bit misleading that iw link reports us being
>> 'connected' during this time for example.
>
> It doesn't!
>
> # iw wlan0 auth <ssid> <bssid> open 2462
>
> -> iw event reporting
> wlan0 (phy #0): auth <localMAC> -> <bssid> status: 0: Successful
>
> # iw wlan0 link
> Not connected.
>

Yes, you're right.  It is iw info that shows us 'connected'

< Request: Get Interface (0x05) len 8 [ack]                 35235.316448
     Interface Index: 3 (0x00000003)
 > Result: New Interface (0x07) len 108                      35235.316455
     Interface Index: 3 (0x00000003)
     Interface Name: wlp2s0
     Wiphy: 0 (0x00000000)
     Interface Type: 2 (0x00000002)
     Wireless Device: 1 (0x0000000000000001)
     Generation: 5 (0x00000005)
     Wiphy Frequency: 2417 (0x00000971)
     Wiphy Channel Type: 1 (0x00000001)
     Channel Width: 1 (0x00000001)
     Center Frequency 1: 2417 (0x00000971)
     Wiphy TX Power Level: 2200 (0x00000898)
 > Response: Get Interface (0x05) len 4                      35235.316457
     Status: Success (0)

>
>> Fair enough.  I think we can live with that since we're not using
>> CMD_AUTHENTICATE unless we need to roam using FT.
>
> That seems like a very strange decision, but it's obviously up to you
> :)
>

Care to elaborate ?

Regards,
-Denis
Johannes Berg Dec. 7, 2016, 7:38 a.m. UTC | #16
> > > Fair enough.  I think we can live with that since we're not using
> > > CMD_AUTHENTICATE unless we need to roam using FT.
> > 
> > That seems like a very strange decision, but it's obviously up to
> > you
> > :)
> > 
> 
> Care to elaborate ?

Well, for example, you won't be able to do SAE, the upcoming FILS or
generally have any control over what's going on in the auth/assoc
handshake, since the kernel's version thereof is really really simple.

johannes
Andrew Zaborowski Dec. 7, 2016, 9:49 a.m. UTC | #17
On 7 December 2016 at 07:19, Johannes Berg <johannes@sipsolutions.net> wrote:
>> Possibly Johanness refers to the fact that if you use
>> CMD_AUTHENTICATE, or if you use CMD_CONNECT but the driver implements
>> the SME -- doesn't use the cfg80211 software SME -- then
>> cfg80211_disconnect won't do anything if we're not associated, only
>> authenticated.  Currently cfg80211 doesn't have knowledge of whether
>> it is authenticated and where to.
>
> We used to track it, but it was a nightmare and just always buggy :)
>
>> With the software SME current_bss would be set from the moment the
>> authentication attempt starts,
>
> I'm almost certain this isn't true, what makes you think so?

Ok, I think I misread the code, indeed it looks consistent between the
driver SME and cfg80211 SME.

I'm fine only adding the socket owner flag to CMD_ASSOCIATE and
CMD_CONNECT.  I'll need to store the bssid of the association in
progress so we can send the Deauthenticate if the socket is closed
before association finishes.

>
>> so there seems to be an inconsistency
>> which would affect for example the NL80211_BSS_STATUS_ASSOCIATED
>> flags in the result of CMD_GET_SCAN.
>
> Thus this can't be the case.
>
>> Perhaps this can be fixed by always
>> setting current_bss on auth attempt start, with flags to indicate
>> whether authentication has happened and whether association happened.
>
> No! That would be wrong!
>
>> At the very least with this patch if you set the socket owner during
>> CMD_AUTHENTICATE and then separately associate, you'd get the
>> expected deauthentication.
>
> That would *NOT* be expected. There's no need to even authenticate
> through CMD_AUTHENTICATE at all to connect to (another) AP!
>
> You need to think beyond the 1996 version of 802.11 ;-)

Best regards
diff mbox

Patch

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bd19faa..413f5b5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3764,6 +3764,8 @@  struct cfg80211_cached_keys;
  * @conn: (private) cfg80211 software SME connection state machine data
  * @connect_keys: (private) keys to set after connection is established
  * @conn_bss_type: connecting/connected BSS type
+ * @conn_owner_nlportid: (private) connection owner socket port ID
+ * @disconnect_wk: (private) auto-disconnect work
  * @ibss_fixed: (private) IBSS is using fixed BSSID
  * @ibss_dfs_possible: (private) IBSS may change to a DFS channel
  * @event_list: (private) list for internal event processing
@@ -3795,6 +3797,9 @@  struct wireless_dev {
 	struct cfg80211_conn *conn;
 	struct cfg80211_cached_keys *connect_keys;
 	enum ieee80211_bss_type conn_bss_type;
+	u32 conn_owner_nlportid;
+
+	struct work_struct disconnect_wk;
 
 	struct list_head event_list;
 	spinlock_t event_lock;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 56368e9..12f41b0 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1788,6 +1788,9 @@  enum nl80211_commands {
  *	and remove functions. NAN notifications will be sent in unicast to that
  *	socket. Without this attribute, any socket can add functions and the
  *	notifications will be sent to the %NL80211_MCGRP_NAN multicast group.
+ *	If set during one of: %NL80211_CMD_AUTHENTICATE, %NL80211_CMD_ASSOCIATE
+ *	or %NL80211_CMD_CONNECT the station will deauthenticate when the
+ *	socket is closed.
  *
  * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
  *	the TDLS link initiator.
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8201e6d..98db6b2 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -357,6 +357,26 @@  static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
 	rtnl_unlock();
 }
 
+static void cfg80211_disconnect_wk(struct work_struct *work)
+{
+	struct cfg80211_registered_device *rdev;
+	struct wireless_dev *wdev;
+
+	wdev = container_of(work, struct wireless_dev, disconnect_wk);
+	rdev = wiphy_to_rdev(wdev->wiphy);
+
+	if (!wdev->netdev)
+		return;
+
+	wdev_lock(wdev);
+
+	if (wdev->conn_owner_nlportid)
+		cfg80211_disconnect(rdev, wdev->netdev,
+					WLAN_REASON_DEAUTH_LEAVING, true);
+
+	wdev_unlock(wdev);
+}
+
 /* exported functions */
 
 struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
@@ -1117,6 +1137,8 @@  static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 		     wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
 			dev->priv_flags |= IFF_DONT_BRIDGE;
 
+		INIT_WORK(&wdev->disconnect_wk, cfg80211_disconnect_wk);
+
 		nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
 		break;
 	case NETDEV_GOING_DOWN:
@@ -1205,6 +1227,7 @@  static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 #ifdef CONFIG_CFG80211_WEXT
 			kzfree(wdev->wext.keys);
 #endif
+			flush_work(&wdev->disconnect_wk);
 		}
 		/*
 		 * synchronise (so that we won't find this netdev
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index cbb48e2..eaf2d1d 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -130,6 +130,8 @@  void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr)
 
 	nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
 	cfg80211_sme_auth_timeout(wdev);
+
+	wdev->conn_owner_nlportid = 0;
 }
 EXPORT_SYMBOL(cfg80211_auth_timeout);
 
@@ -146,6 +148,8 @@  void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss)
 
 	cfg80211_unhold_bss(bss_from_pub(bss));
 	cfg80211_put_bss(wiphy, bss);
+
+	wdev->conn_owner_nlportid = 0;
 }
 EXPORT_SYMBOL(cfg80211_assoc_timeout);
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c510810..ccd74c7 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7818,6 +7818,10 @@  static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
 				 key.p.key, key.p.key_len, key.idx,
 				 sae_data, sae_data_len);
 	wdev_unlock(dev->ieee80211_ptr);
+
+	if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
+		dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
+
 	return err;
 }
 
@@ -8003,6 +8007,9 @@  static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 		wdev_unlock(dev->ieee80211_ptr);
 	}
 
+	if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
+		dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
+
 	return err;
 }
 
@@ -8050,6 +8057,10 @@  static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
 	err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
 				   local_state_change);
 	wdev_unlock(dev->ieee80211_ptr);
+
+	if (!err)
+		dev->ieee80211_ptr->conn_owner_nlportid = 0;
+
 	return err;
 }
 
@@ -8097,6 +8108,10 @@  static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
 	err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
 				     local_state_change);
 	wdev_unlock(dev->ieee80211_ptr);
+
+	if (!err)
+		dev->ieee80211_ptr->conn_owner_nlportid = 0;
+
 	return err;
 }
 
@@ -8723,6 +8738,10 @@  static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 	wdev_unlock(dev->ieee80211_ptr);
 	if (err)
 		kzfree(connkeys);
+
+	if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER])
+		dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
+
 	return err;
 }
 
@@ -14425,13 +14444,21 @@  static int nl80211_netlink_notify(struct notifier_block * nb,
 				spin_unlock(&rdev->destroy_list_lock);
 				schedule_work(&rdev->destroy_work);
 			}
-		} else if (schedule_scan_stop) {
+
+			continue;
+		}
+
+		if (schedule_scan_stop) {
 			sched_scan_req->owner_nlportid = 0;
 
 			if (rdev->ops->sched_scan_stop &&
 			    rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
 				schedule_work(&rdev->sched_scan_stop_wk);
 		}
+
+		list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list)
+			if (wdev->conn_owner_nlportid == notify->portid)
+				schedule_work(&wdev->disconnect_wk);
 	}
 
 	rcu_read_unlock();
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a77db33..e77f5fa 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -718,6 +718,7 @@  void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
 			cfg80211_put_bss(wdev->wiphy, bss);
 		}
 		cfg80211_sme_free(wdev);
+		wdev->conn_owner_nlportid = 0;
 		return;
 	}
 
@@ -941,6 +942,7 @@  void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
 
 	wdev->current_bss = NULL;
 	wdev->ssid_len = 0;
+	wdev->conn_owner_nlportid = 0;
 
 	nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
 
@@ -1084,6 +1086,8 @@  int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
 	kzfree(wdev->connect_keys);
 	wdev->connect_keys = NULL;
 
+	wdev->conn_owner_nlportid = 0;
+
 	if (wdev->conn)
 		err = cfg80211_sme_disconnect(wdev, reason);
 	else if (!rdev->ops->disconnect)