linux_dsm_epyc7002/net/sunrpc/auth_gss
NeilBrown 1cded9d297 SUNRPC: fix refcounting problems with auth_gss messages.
There are two problems with refcounting of auth_gss messages.

First, the reference on the pipe->pipe list (taken by a call
to rpc_queue_upcall()) is not counted.  It seems to be
assumed that a message in pipe->pipe will always also be in
pipe->in_downcall, where it is correctly reference counted.

However there is no guaranty of this.  I have a report of a
NULL dereferences in rpc_pipe_read() which suggests a msg
that has been freed is still on the pipe->pipe list.

One way I imagine this might happen is:
- message is queued for uid=U and auth->service=S1
- rpc.gssd reads this message and starts processing.
  This removes the message from pipe->pipe
- message is queued for uid=U and auth->service=S2
- rpc.gssd replies to the first message. gss_pipe_downcall()
  calls __gss_find_upcall(pipe, U, NULL) and it finds the
  *second* message, as new messages are placed at the head
  of ->in_downcall, and the service type is not checked.
- This second message is removed from ->in_downcall and freed
  by gss_release_msg() (even though it is still on pipe->pipe)
- rpc.gssd tries to read another message, and dereferences a pointer
  to this message that has just been freed.

I fix this by incrementing the reference count before calling
rpc_queue_upcall(), and decrementing it if that fails, or normally in
gss_pipe_destroy_msg().

It seems strange that the reply doesn't target the message more
precisely, but I don't know all the details.  In any case, I think the
reference counting irregularity became a measureable bug when the
extra arg was added to __gss_find_upcall(), hence the Fixes: line
below.

The second problem is that if rpc_queue_upcall() fails, the new
message is not freed. gss_alloc_msg() set the ->count to 1,
gss_add_msg() increments this to 2, gss_unhash_msg() decrements to 1,
then the pointer is discarded so the memory never gets freed.

Fixes: 9130b8dbc6 ("SUNRPC: allow for upcalls for same uid but different gss service")
Cc: stable@vger.kernel.org
Link: https://bugzilla.opensuse.org/show_bug.cgi?id=1011250
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
2016-12-10 10:29:29 -05:00
..
auth_gss.c SUNRPC: fix refcounting problems with auth_gss messages. 2016-12-10 10:29:29 -05:00
gss_generic_token.c
gss_krb5_crypto.c sunrpc: don't pass on-stack memory to sg_set_buf 2016-10-26 15:49:48 -04:00
gss_krb5_keys.c sunrpc: Use skcipher and ahash/shash 2016-01-27 20:36:01 +08:00
gss_krb5_mech.c xprtrdma: No direct data placement with krb5i and krb5p 2016-07-11 15:50:43 -04:00
gss_krb5_seal.c
gss_krb5_seqnum.c sunrpc: Use skcipher and ahash/shash 2016-01-27 20:36:01 +08:00
gss_krb5_unseal.c
gss_krb5_wrap.c mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros 2016-04-04 10:41:08 -07:00
gss_mech_switch.c xprtrdma: No direct data placement with krb5i and krb5p 2016-07-11 15:50:43 -04:00
gss_rpc_upcall.c nfsd4: fix gss-proxy 4.1 mounts for some AD principals 2015-11-24 11:36:31 -07:00
gss_rpc_upcall.h
gss_rpc_xdr.c cred: simpler, 1D supplementary groups 2016-10-07 18:46:30 -07:00
gss_rpc_xdr.h
Makefile
svcauth_gss.c sunrpc: don't pass on-stack memory to sg_set_buf 2016-10-26 15:49:48 -04:00