Skip to content

Commit

Permalink
knfsd: use a spinlock to protect sk_info_authunix
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
NeilBrown authored and Linus Torvalds committed Apr 17, 2007
1 parent 94256dd commit 30f3dee
Showing 1 changed file with 16 additions and 5 deletions.
21 changes: 16 additions & 5 deletions net/sunrpc/svcauth_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,20 +383,25 @@ 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)) {
/*
* The entry has been invalidated since it was
* 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;
}

Expand All @@ -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);
}

Expand Down

0 comments on commit 30f3dee

Please sign in to comment.