Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=30f3deeee81cf22546da1b0b89a937bb991dea23
Commit:     30f3deeee81cf22546da1b0b89a937bb991dea23
Parent:     94256dd680f837dc14dd7d1377c5326fb3362721
Author:     NeilBrown <[EMAIL PROTECTED]>
AuthorDate: Mon Apr 16 22:53:25 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Apr 17 16:36:27 2007 -0700

    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 <[EMAIL PROTECTED]>
    Cc: Gabriel Barazer <[EMAIL PROTECTED]>
    Signed-off-by: Neil Brown <[EMAIL PROTECTED]>
    Cc: <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 net/sunrpc/svcauth_unix.c |   21 ++++++++++++++++-----
 1 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 9bae409..2bd23ea 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -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);
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to