Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / sunrpc / auth_unix.c
index 33741fc..4f2ad4f 100644 (file)
@@ -9,8 +9,6 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/vserver/xid.h>
@@ -20,8 +18,7 @@
 struct unx_cred {
        struct rpc_cred         uc_base;
        gid_t                   uc_gid;
-       uid_t                   uc_puid;                /* process uid */
-       gid_t                   uc_pgid;                /* process gid */
+       xid_t                   uc_xid;
        gid_t                   uc_gids[NFS_NGROUPS];
 };
 #define uc_uid                 uc_base.cr_uid
@@ -37,24 +34,17 @@ struct unx_cred {
 # define RPCDBG_FACILITY       RPCDBG_AUTH
 #endif
 
+static struct rpc_auth         unix_auth;
+static struct rpc_cred_cache   unix_cred_cache;
 static struct rpc_credops      unix_credops;
 
 static struct rpc_auth *
 unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 {
-       struct rpc_auth *auth;
-
        dprintk("RPC: creating UNIX authenticator for client %p\n", clnt);
-       if (!(auth = (struct rpc_auth *) kmalloc(sizeof(*auth), GFP_KERNEL)))
-               return NULL;
-       auth->au_cslack = UNX_WRITESLACK;
-       auth->au_rslack = 2;    /* assume AUTH_NULL verf */
-       auth->au_expire = UNX_CRED_EXPIRE;
-       auth->au_ops = &authunix_ops;
-
-       rpcauth_init_credcache(auth);
-
-       return auth;
+       if (atomic_inc_return(&unix_auth.au_count) == 0)
+               unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
+       return &unix_auth;
 }
 
 static void
@@ -64,6 +54,15 @@ unx_destroy(struct rpc_auth *auth)
        rpcauth_free_credcache(auth);
 }
 
+/*
+ * Lookup AUTH_UNIX creds for current process
+ */
+static struct rpc_cred *
+unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+{
+       return rpcauth_lookup_credcache(auth, acred, flags);
+}
+
 static struct rpc_cred *
 unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 {
@@ -73,14 +72,15 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
        dprintk("RPC:      allocating UNIX cred for uid %d gid %d\n",
                                acred->uid, acred->gid);
 
-       if (!(cred = (struct unx_cred *) kmalloc(sizeof(*cred), GFP_KERNEL)))
-               return NULL;
+       if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
+               return ERR_PTR(-ENOMEM);
 
-       atomic_set(&cred->uc_count, 0);
+       atomic_set(&cred->uc_count, 1);
        cred->uc_flags = RPCAUTH_CRED_UPTODATE;
-       if (flags & RPC_TASK_ROOTCREDS) {
-               cred->uc_uid = cred->uc_puid = 0;
-               cred->uc_gid = cred->uc_pgid = 0;
+       if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
+               cred->uc_uid = 0;
+               cred->uc_gid = 0;
+               cred->uc_xid = vx_current_xid();
                cred->uc_gids[0] = NOGROUP;
        } else {
                int groups = acred->group_info->ngroups;
@@ -89,10 +89,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 
                cred->uc_uid = acred->uid;
                cred->uc_gid = acred->gid;
-//             cred->uc_puid = XIDINO_UID(current->uid, current->xid);
-//             cred->uc_pgid = XIDINO_GID(current->gid, current->xid);
-               cred->uc_puid = current->uid;
-               cred->uc_pgid = current->gid;
+               cred->uc_xid = acred->xid;
                for (i = 0; i < groups; i++)
                        cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
                if (i < NFS_NGROUPS)
@@ -115,18 +112,17 @@ unx_destroy_cred(struct rpc_cred *cred)
  * request root creds (e.g. for NFS swapping).
  */
 static int
-unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
+unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
 {
        struct unx_cred *cred = (struct unx_cred *) rcred;
        int             i;
 
-       if (!(taskflags & RPC_TASK_ROOTCREDS)) {
+       if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
                int groups;
 
                if (cred->uc_uid != acred->uid
                 || cred->uc_gid != acred->gid
-                || cred->uc_puid != XIDINO_UID(current->uid, current->xid)
-                || cred->uc_pgid != XIDINO_GID(current->gid, current->xid))
+                || cred->uc_xid != acred->xid)
                        return 0;
 
                groups = acred->group_info->ngroups;
@@ -137,8 +133,8 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
                                return 0;
                return 1;
        }
-       return (cred->uc_uid == 0 && cred->uc_puid == 0
-            && cred->uc_gid == 0 && cred->uc_pgid == 0
+       return (cred->uc_uid == 0
+            && cred->uc_gid == 0
             && cred->uc_gids[0] == (gid_t) NOGROUP);
 }
 
@@ -147,12 +143,12 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
  * Maybe we should keep a cached credential for performance reasons.
  */
 static u32 *
-unx_marshal(struct rpc_task *task, u32 *p, int ruid)
+unx_marshal(struct rpc_task *task, u32 *p)
 {
        struct rpc_clnt *clnt = task->tk_client;
        struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
        u32             *base, *hold;
-       int             i;
+       int             i, tagxid;
 
        *p++ = htonl(RPC_AUTH_UNIX);
        base = p++;
@@ -162,15 +158,12 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid)
         * Copy the UTS nodename captured when the client was created.
         */
        p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
+       tagxid = task->tk_client->cl_tagxid;
 
-       /* Note: we don't use real uid if it involves raising privilege */
-       if (ruid && cred->uc_puid != 0 && cred->uc_pgid != 0) {
-               *p++ = htonl((u32) cred->uc_puid);
-               *p++ = htonl((u32) cred->uc_pgid);
-       } else {
-               *p++ = htonl((u32) cred->uc_uid);
-               *p++ = htonl((u32) cred->uc_gid);
-       }
+       *p++ = htonl((u32) XIDINO_UID(tagxid,
+               cred->uc_uid, cred->uc_xid));
+       *p++ = htonl((u32) XIDINO_GID(tagxid,
+               cred->uc_gid, cred->uc_xid));
        hold = p++;
        for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
                *p++ = htonl((u32) cred->uc_gids[i]);
@@ -190,7 +183,7 @@ static int
 unx_refresh(struct rpc_task *task)
 {
        task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
-       return task->tk_status = -EACCES;
+       return 0;
 }
 
 static u32 *
@@ -226,11 +219,27 @@ struct rpc_authops        authunix_ops = {
 #endif
        .create         = unx_create,
        .destroy        = unx_destroy,
+       .lookup_cred    = unx_lookup_cred,
        .crcreate       = unx_create_cred,
 };
 
+static
+struct rpc_cred_cache  unix_cred_cache = {
+       .expire         = UNX_CRED_EXPIRE,
+};
+
+static
+struct rpc_auth                unix_auth = {
+       .au_cslack      = UNX_WRITESLACK,
+       .au_rslack      = 2,                    /* assume AUTH_NULL verf */
+       .au_ops         = &authunix_ops,
+       .au_count       = ATOMIC_INIT(0),
+       .au_credcache   = &unix_cred_cache,
+};
+
 static
 struct rpc_credops     unix_credops = {
+       .cr_name        = "AUTH_UNIX",
        .crdestroy      = unx_destroy_cred,
        .crmatch        = unx_match,
        .crmarshal      = unx_marshal,