From: Vlad Yasevich <vyasevich@gmail.com>
To: Daniel Borkmann <dborkman@redhat.com>, davem@davemloft.net
Cc: netdev@vger.kernel.org, linux-sctp@vger.kernel.org
Subject: Re: [PATCH net] net: sctp: fix slab corruption from use after free on INIT collisions
Date: Thu, 22 Jan 2015 17:52:34 +0000 [thread overview]
Message-ID: <54C138E2.30807@gmail.com> (raw)
In-Reply-To: <1421947614-31407-1-git-send-email-dborkman@redhat.com>
On 01/22/2015 12:26 PM, Daniel Borkmann wrote:
> When hitting an INIT collision case during the 4WHS with AUTH enabled, as
> already described in detail in commit 1be9a950c646 ("net: sctp: inherit
> auth_capable on INIT collisions"), it can happen that we occasionally
> still remotely trigger the following panic on server side which seems to
> have been uncovered after the fix from commit 1be9a950c646 ...
>
> [ 533.876389] BUG: unable to handle kernel paging request at 00000000ffffffff
> [ 533.913657] IP: [<ffffffff811ac385>] __kmalloc+0x95/0x230
> [ 533.940559] PGD 5030f2067 PUD 0
> [ 533.957104] Oops: 0000 [#1] SMP
> [ 533.974283] Modules linked in: sctp mlx4_en [...]
> [ 534.939704] Call Trace:
> [ 534.951833] [<ffffffff81294e30>] ? crypto_init_shash_ops+0x60/0xf0
> [ 534.984213] [<ffffffff81294e30>] crypto_init_shash_ops+0x60/0xf0
> [ 535.015025] [<ffffffff8128c8ed>] __crypto_alloc_tfm+0x6d/0x170
> [ 535.045661] [<ffffffff8128d12c>] crypto_alloc_base+0x4c/0xb0
> [ 535.074593] [<ffffffff8160bd42>] ? _raw_spin_lock_bh+0x12/0x50
> [ 535.105239] [<ffffffffa0418c11>] sctp_inet_listen+0x161/0x1e0 [sctp]
> [ 535.138606] [<ffffffff814e43bd>] SyS_listen+0x9d/0xb0
> [ 535.166848] [<ffffffff816149a9>] system_call_fastpath+0x16/0x1b
>
> ... or depending on the the application, for example this one:
>
> [ 1370.026490] BUG: unable to handle kernel paging request at 00000000ffffffff
> [ 1370.026506] IP: [<ffffffff811ab455>] kmem_cache_alloc+0x75/0x1d0
> [ 1370.054568] PGD 633c94067 PUD 0
> [ 1370.070446] Oops: 0000 [#1] SMP
> [ 1370.085010] Modules linked in: sctp kvm_amd kvm [...]
> [ 1370.963431] Call Trace:
> [ 1370.974632] [<ffffffff8120f7cf>] ? SyS_epoll_ctl+0x53f/0x960
> [ 1371.000863] [<ffffffff8120f7cf>] SyS_epoll_ctl+0x53f/0x960
> [ 1371.027154] [<ffffffff812100d3>] ? anon_inode_getfile+0xd3/0x170
> [ 1371.054679] [<ffffffff811e3d67>] ? __alloc_fd+0xa7/0x130
> [ 1371.080183] [<ffffffff816149a9>] system_call_fastpath+0x16/0x1b
>
> With slab debugging enabled, we can see that the poison has been overwritten:
>
> [ 669.826368] BUG kmalloc-128 (Tainted: G W ): Poison overwritten
> [ 669.826385] INFO: 0xffff880228b32e50-0xffff880228b32e50. First byte 0x6a instead of 0x6b
> [ 669.826414] INFO: Allocated in sctp_auth_create_key+0x23/0x50 [sctp] age=3 cpu=0 pid\x18494
> [ 669.826424] __slab_alloc+0x4bf/0x566
> [ 669.826433] __kmalloc+0x280/0x310
> [ 669.826453] sctp_auth_create_key+0x23/0x50 [sctp]
> [ 669.826471] sctp_auth_asoc_create_secret+0xcb/0x1e0 [sctp]
> [ 669.826488] sctp_auth_asoc_init_active_key+0x68/0xa0 [sctp]
> [ 669.826505] sctp_do_sm+0x29d/0x17c0 [sctp] [...]
> [ 669.826629] INFO: Freed in kzfree+0x31/0x40 age=1 cpu=0 pid\x18494
> [ 669.826635] __slab_free+0x39/0x2a8
> [ 669.826643] kfree+0x1d6/0x230
> [ 669.826650] kzfree+0x31/0x40
> [ 669.826666] sctp_auth_key_put+0x19/0x20 [sctp]
> [ 669.826681] sctp_assoc_update+0x1ee/0x2d0 [sctp]
> [ 669.826695] sctp_do_sm+0x674/0x17c0 [sctp]
>
> Since this only triggers in some collision-cases with AUTH, the problem at
> heart is that sctp_auth_key_put() on asoc->asoc_shared_key is called twice
> when having refcnt 1, once directly in sctp_assoc_update() and yet again
> from within sctp_auth_asoc_init_active_key() via sctp_assoc_update() on
> the already kzfree'd memory, which is also consistent with the observation
> of the poison decrease from 0x6b to 0x6a (note: the overwrite is detected
> at a later point in time when poison is checked on new allocation).
>
> Reference counting of auth keys revisited:
>
> Shared keys for AUTH chunks are being stored in endpoints and associations
> in endpoint_shared_keys list. On endpoint creation, a null key is being
> added; on association creation, all endpoint shared keys are being cached
> and thus cloned over to the association. struct sctp_shared_key only holds
> a pointer to the actual key bytes, that is, struct sctp_auth_bytes which
> keeps track of users internally through refcounting. Naturally, on assoc
> or enpoint destruction, sctp_shared_key are being destroyed directly and
> the reference on sctp_auth_bytes dropped.
>
> User space can add keys to either list via setsockopt(2) through struct
> sctp_authkey and by passing that to sctp_auth_set_key() which replaces or
> adds a new auth key. There, sctp_auth_create_key() creates a new sctp_auth_bytes
> with refcount 1 and in case of replacement drops the reference on the old
> sctp_auth_bytes. A key can be set active from user space through setsockopt()
> on the id via sctp_auth_set_active_key(), which iterates through either
> endpoint_shared_keys and in case of an assoc, invokes (one of various places)
> sctp_auth_asoc_init_active_key().
>
> sctp_auth_asoc_init_active_key() computes the actual secret from local's
> and peer's random, hmac and shared key parameters and returns a new key
> directly as sctp_auth_bytes, that is asoc->asoc_shared_key, plus drops
> the reference if there was a previous one. The secret, which where we
> eventually double drop the ref comes from sctp_auth_asoc_set_secret() with
> intitial refcount of 1, which also stays unchanged eventually in
> sctp_assoc_update(). This key is later being used for crypto layer to
> set the key for the hash in crypto_hash_setkey() from sctp_auth_calculate_hmac().
>
> To close the loop: asoc->asoc_shared_key is freshly allocated secret
> material and independant of the sctp_shared_key management keeping track
> of only shared keys in endpoints and assocs. Hence, also commit 4184b2a79a76
> ("net: sctp: fix memory leak in auth key management") is independant of
> this bug here since it concerns a different layer (though same structures
> being used eventually). asoc->asoc_shared_key is reference dropped correctly
> on assoc destruction in sctp_association_free() and when active keys are
> being replaced in sctp_auth_asoc_init_active_key(), it always has a refcount
> of 1. Hence, it's freed prematurely in sctp_assoc_update(). Simple fix is
> to remove that sctp_auth_key_put() from there which fixes these panics.
>
> Fixes: 730fc3d05cd4 ("[SCTP]: Implete SCTP-AUTH parameter processing")
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
-vlad
> ---
> net/sctp/associola.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index f791edd..26d06db 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1182,7 +1182,6 @@ void sctp_assoc_update(struct sctp_association *asoc,
> asoc->peer.peer_hmacs = new->peer.peer_hmacs;
> new->peer.peer_hmacs = NULL;
>
> - sctp_auth_key_put(asoc->asoc_shared_key);
> sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC);
> }
>
>
WARNING: multiple messages have this Message-ID (diff)
From: Vlad Yasevich <vyasevich@gmail.com>
To: Daniel Borkmann <dborkman@redhat.com>, davem@davemloft.net
Cc: netdev@vger.kernel.org, linux-sctp@vger.kernel.org
Subject: Re: [PATCH net] net: sctp: fix slab corruption from use after free on INIT collisions
Date: Thu, 22 Jan 2015 12:52:34 -0500 [thread overview]
Message-ID: <54C138E2.30807@gmail.com> (raw)
In-Reply-To: <1421947614-31407-1-git-send-email-dborkman@redhat.com>
On 01/22/2015 12:26 PM, Daniel Borkmann wrote:
> When hitting an INIT collision case during the 4WHS with AUTH enabled, as
> already described in detail in commit 1be9a950c646 ("net: sctp: inherit
> auth_capable on INIT collisions"), it can happen that we occasionally
> still remotely trigger the following panic on server side which seems to
> have been uncovered after the fix from commit 1be9a950c646 ...
>
> [ 533.876389] BUG: unable to handle kernel paging request at 00000000ffffffff
> [ 533.913657] IP: [<ffffffff811ac385>] __kmalloc+0x95/0x230
> [ 533.940559] PGD 5030f2067 PUD 0
> [ 533.957104] Oops: 0000 [#1] SMP
> [ 533.974283] Modules linked in: sctp mlx4_en [...]
> [ 534.939704] Call Trace:
> [ 534.951833] [<ffffffff81294e30>] ? crypto_init_shash_ops+0x60/0xf0
> [ 534.984213] [<ffffffff81294e30>] crypto_init_shash_ops+0x60/0xf0
> [ 535.015025] [<ffffffff8128c8ed>] __crypto_alloc_tfm+0x6d/0x170
> [ 535.045661] [<ffffffff8128d12c>] crypto_alloc_base+0x4c/0xb0
> [ 535.074593] [<ffffffff8160bd42>] ? _raw_spin_lock_bh+0x12/0x50
> [ 535.105239] [<ffffffffa0418c11>] sctp_inet_listen+0x161/0x1e0 [sctp]
> [ 535.138606] [<ffffffff814e43bd>] SyS_listen+0x9d/0xb0
> [ 535.166848] [<ffffffff816149a9>] system_call_fastpath+0x16/0x1b
>
> ... or depending on the the application, for example this one:
>
> [ 1370.026490] BUG: unable to handle kernel paging request at 00000000ffffffff
> [ 1370.026506] IP: [<ffffffff811ab455>] kmem_cache_alloc+0x75/0x1d0
> [ 1370.054568] PGD 633c94067 PUD 0
> [ 1370.070446] Oops: 0000 [#1] SMP
> [ 1370.085010] Modules linked in: sctp kvm_amd kvm [...]
> [ 1370.963431] Call Trace:
> [ 1370.974632] [<ffffffff8120f7cf>] ? SyS_epoll_ctl+0x53f/0x960
> [ 1371.000863] [<ffffffff8120f7cf>] SyS_epoll_ctl+0x53f/0x960
> [ 1371.027154] [<ffffffff812100d3>] ? anon_inode_getfile+0xd3/0x170
> [ 1371.054679] [<ffffffff811e3d67>] ? __alloc_fd+0xa7/0x130
> [ 1371.080183] [<ffffffff816149a9>] system_call_fastpath+0x16/0x1b
>
> With slab debugging enabled, we can see that the poison has been overwritten:
>
> [ 669.826368] BUG kmalloc-128 (Tainted: G W ): Poison overwritten
> [ 669.826385] INFO: 0xffff880228b32e50-0xffff880228b32e50. First byte 0x6a instead of 0x6b
> [ 669.826414] INFO: Allocated in sctp_auth_create_key+0x23/0x50 [sctp] age=3 cpu=0 pid=18494
> [ 669.826424] __slab_alloc+0x4bf/0x566
> [ 669.826433] __kmalloc+0x280/0x310
> [ 669.826453] sctp_auth_create_key+0x23/0x50 [sctp]
> [ 669.826471] sctp_auth_asoc_create_secret+0xcb/0x1e0 [sctp]
> [ 669.826488] sctp_auth_asoc_init_active_key+0x68/0xa0 [sctp]
> [ 669.826505] sctp_do_sm+0x29d/0x17c0 [sctp] [...]
> [ 669.826629] INFO: Freed in kzfree+0x31/0x40 age=1 cpu=0 pid=18494
> [ 669.826635] __slab_free+0x39/0x2a8
> [ 669.826643] kfree+0x1d6/0x230
> [ 669.826650] kzfree+0x31/0x40
> [ 669.826666] sctp_auth_key_put+0x19/0x20 [sctp]
> [ 669.826681] sctp_assoc_update+0x1ee/0x2d0 [sctp]
> [ 669.826695] sctp_do_sm+0x674/0x17c0 [sctp]
>
> Since this only triggers in some collision-cases with AUTH, the problem at
> heart is that sctp_auth_key_put() on asoc->asoc_shared_key is called twice
> when having refcnt 1, once directly in sctp_assoc_update() and yet again
> from within sctp_auth_asoc_init_active_key() via sctp_assoc_update() on
> the already kzfree'd memory, which is also consistent with the observation
> of the poison decrease from 0x6b to 0x6a (note: the overwrite is detected
> at a later point in time when poison is checked on new allocation).
>
> Reference counting of auth keys revisited:
>
> Shared keys for AUTH chunks are being stored in endpoints and associations
> in endpoint_shared_keys list. On endpoint creation, a null key is being
> added; on association creation, all endpoint shared keys are being cached
> and thus cloned over to the association. struct sctp_shared_key only holds
> a pointer to the actual key bytes, that is, struct sctp_auth_bytes which
> keeps track of users internally through refcounting. Naturally, on assoc
> or enpoint destruction, sctp_shared_key are being destroyed directly and
> the reference on sctp_auth_bytes dropped.
>
> User space can add keys to either list via setsockopt(2) through struct
> sctp_authkey and by passing that to sctp_auth_set_key() which replaces or
> adds a new auth key. There, sctp_auth_create_key() creates a new sctp_auth_bytes
> with refcount 1 and in case of replacement drops the reference on the old
> sctp_auth_bytes. A key can be set active from user space through setsockopt()
> on the id via sctp_auth_set_active_key(), which iterates through either
> endpoint_shared_keys and in case of an assoc, invokes (one of various places)
> sctp_auth_asoc_init_active_key().
>
> sctp_auth_asoc_init_active_key() computes the actual secret from local's
> and peer's random, hmac and shared key parameters and returns a new key
> directly as sctp_auth_bytes, that is asoc->asoc_shared_key, plus drops
> the reference if there was a previous one. The secret, which where we
> eventually double drop the ref comes from sctp_auth_asoc_set_secret() with
> intitial refcount of 1, which also stays unchanged eventually in
> sctp_assoc_update(). This key is later being used for crypto layer to
> set the key for the hash in crypto_hash_setkey() from sctp_auth_calculate_hmac().
>
> To close the loop: asoc->asoc_shared_key is freshly allocated secret
> material and independant of the sctp_shared_key management keeping track
> of only shared keys in endpoints and assocs. Hence, also commit 4184b2a79a76
> ("net: sctp: fix memory leak in auth key management") is independant of
> this bug here since it concerns a different layer (though same structures
> being used eventually). asoc->asoc_shared_key is reference dropped correctly
> on assoc destruction in sctp_association_free() and when active keys are
> being replaced in sctp_auth_asoc_init_active_key(), it always has a refcount
> of 1. Hence, it's freed prematurely in sctp_assoc_update(). Simple fix is
> to remove that sctp_auth_key_put() from there which fixes these panics.
>
> Fixes: 730fc3d05cd4 ("[SCTP]: Implete SCTP-AUTH parameter processing")
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
-vlad
> ---
> net/sctp/associola.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index f791edd..26d06db 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -1182,7 +1182,6 @@ void sctp_assoc_update(struct sctp_association *asoc,
> asoc->peer.peer_hmacs = new->peer.peer_hmacs;
> new->peer.peer_hmacs = NULL;
>
> - sctp_auth_key_put(asoc->asoc_shared_key);
> sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC);
> }
>
>
next prev parent reply other threads:[~2015-01-22 17:52 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-22 17:26 [PATCH net] net: sctp: fix slab corruption from use after free on INIT collisions Daniel Borkmann
2015-01-22 17:26 ` Daniel Borkmann
2015-01-22 17:52 ` Vlad Yasevich [this message]
2015-01-22 17:52 ` Vlad Yasevich
2015-01-26 12:33 ` Neil Horman
2015-01-26 12:33 ` Neil Horman
2015-01-27 1:05 ` David Miller
2015-01-27 1:05 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54C138E2.30807@gmail.com \
--to=vyasevich@gmail.com \
--cc=davem@davemloft.net \
--cc=dborkman@redhat.com \
--cc=linux-sctp@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.