mirror of
https://github.com/joel16/android_kernel_sony_msm8994.git
synced 2024-11-29 07:01:10 +00:00
knfsd: use a spinlock to protect sk_info_authunix
sk_info_authunix is not being protected properly so the object that it points to can be cache_put twice, leading to corruption. We borrow svsk->sk_defer_lock to provide the protection. We should probably rename that lock to have a more generic name - later. Thanks to Gabriel for reporting this. Cc: Greg Banks <gnb@melbourne.sgi.com> Cc: Gabriel Barazer <gabriel@oxeva.fr> Signed-off-by: Neil Brown <neilb@suse.de> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
94256dd680
commit
30f3deeee8
@ -383,7 +383,10 @@ void svcauth_unix_purge(void)
|
||||
static inline struct ip_map *
|
||||
ip_map_cached_get(struct svc_rqst *rqstp)
|
||||
{
|
||||
struct ip_map *ipm = rqstp->rq_sock->sk_info_authunix;
|
||||
struct ip_map *ipm;
|
||||
struct svc_sock *svsk = rqstp->rq_sock;
|
||||
spin_lock_bh(&svsk->sk_defer_lock);
|
||||
ipm = svsk->sk_info_authunix;
|
||||
if (ipm != NULL) {
|
||||
if (!cache_valid(&ipm->h)) {
|
||||
/*
|
||||
@ -391,12 +394,14 @@ ip_map_cached_get(struct svc_rqst *rqstp)
|
||||
* remembered, e.g. by a second mount from the
|
||||
* same IP address.
|
||||
*/
|
||||
rqstp->rq_sock->sk_info_authunix = NULL;
|
||||
svsk->sk_info_authunix = NULL;
|
||||
spin_unlock_bh(&svsk->sk_defer_lock);
|
||||
cache_put(&ipm->h, &ip_map_cache);
|
||||
return NULL;
|
||||
}
|
||||
cache_get(&ipm->h);
|
||||
}
|
||||
spin_unlock_bh(&svsk->sk_defer_lock);
|
||||
return ipm;
|
||||
}
|
||||
|
||||
@ -405,9 +410,15 @@ ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm)
|
||||
{
|
||||
struct svc_sock *svsk = rqstp->rq_sock;
|
||||
|
||||
if (svsk->sk_sock->type == SOCK_STREAM && svsk->sk_info_authunix == NULL)
|
||||
svsk->sk_info_authunix = ipm; /* newly cached, keep the reference */
|
||||
else
|
||||
spin_lock_bh(&svsk->sk_defer_lock);
|
||||
if (svsk->sk_sock->type == SOCK_STREAM &&
|
||||
svsk->sk_info_authunix == NULL) {
|
||||
/* newly cached, keep the reference */
|
||||
svsk->sk_info_authunix = ipm;
|
||||
ipm = NULL;
|
||||
}
|
||||
spin_unlock_bh(&svsk->sk_defer_lock);
|
||||
if (ipm)
|
||||
cache_put(&ipm->h, &ip_map_cache);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user