~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to net/sunrpc/auth_unix.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * linux/net/sunrpc/auth_unix.c
 
3
 *
 
4
 * UNIX-style authentication; no AUTH_SHORT support
 
5
 *
 
6
 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
 
7
 */
 
8
 
 
9
#include <linux/slab.h>
 
10
#include <linux/types.h>
 
11
#include <linux/sched.h>
 
12
#include <linux/module.h>
 
13
#include <linux/sunrpc/clnt.h>
 
14
#include <linux/sunrpc/auth.h>
 
15
 
 
16
#define NFS_NGROUPS     16
 
17
 
 
18
struct unx_cred {
 
19
        struct rpc_cred         uc_base;
 
20
        gid_t                   uc_gid;
 
21
        gid_t                   uc_gids[NFS_NGROUPS];
 
22
};
 
23
#define uc_uid                  uc_base.cr_uid
 
24
 
 
25
#define UNX_WRITESLACK          (21 + (UNX_MAXNODENAME >> 2))
 
26
 
 
27
#ifdef RPC_DEBUG
 
28
# define RPCDBG_FACILITY        RPCDBG_AUTH
 
29
#endif
 
30
 
 
31
static struct rpc_auth          unix_auth;
 
32
static const struct rpc_credops unix_credops;
 
33
 
 
34
static struct rpc_auth *
 
35
unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 
36
{
 
37
        dprintk("RPC:       creating UNIX authenticator for client %p\n",
 
38
                        clnt);
 
39
        atomic_inc(&unix_auth.au_count);
 
40
        return &unix_auth;
 
41
}
 
42
 
 
43
static void
 
44
unx_destroy(struct rpc_auth *auth)
 
45
{
 
46
        dprintk("RPC:       destroying UNIX authenticator %p\n", auth);
 
47
        rpcauth_clear_credcache(auth->au_credcache);
 
48
}
 
49
 
 
50
/*
 
51
 * Lookup AUTH_UNIX creds for current process
 
52
 */
 
53
static struct rpc_cred *
 
54
unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 
55
{
 
56
        return rpcauth_lookup_credcache(auth, acred, flags);
 
57
}
 
58
 
 
59
static struct rpc_cred *
 
60
unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 
61
{
 
62
        struct unx_cred *cred;
 
63
        unsigned int groups = 0;
 
64
        unsigned int i;
 
65
 
 
66
        dprintk("RPC:       allocating UNIX cred for uid %d gid %d\n",
 
67
                        acred->uid, acred->gid);
 
68
 
 
69
        if (!(cred = kmalloc(sizeof(*cred), GFP_NOFS)))
 
70
                return ERR_PTR(-ENOMEM);
 
71
 
 
72
        rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
 
73
        cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
 
74
 
 
75
        if (acred->group_info != NULL)
 
76
                groups = acred->group_info->ngroups;
 
77
        if (groups > NFS_NGROUPS)
 
78
                groups = NFS_NGROUPS;
 
79
 
 
80
        cred->uc_gid = acred->gid;
 
81
        for (i = 0; i < groups; i++)
 
82
                cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
 
83
        if (i < NFS_NGROUPS)
 
84
                cred->uc_gids[i] = NOGROUP;
 
85
 
 
86
        return &cred->uc_base;
 
87
}
 
88
 
 
89
static void
 
90
unx_free_cred(struct unx_cred *unx_cred)
 
91
{
 
92
        dprintk("RPC:       unx_free_cred %p\n", unx_cred);
 
93
        kfree(unx_cred);
 
94
}
 
95
 
 
96
static void
 
97
unx_free_cred_callback(struct rcu_head *head)
 
98
{
 
99
        struct unx_cred *unx_cred = container_of(head, struct unx_cred, uc_base.cr_rcu);
 
100
        unx_free_cred(unx_cred);
 
101
}
 
102
 
 
103
static void
 
104
unx_destroy_cred(struct rpc_cred *cred)
 
105
{
 
106
        call_rcu(&cred->cr_rcu, unx_free_cred_callback);
 
107
}
 
108
 
 
109
/*
 
110
 * Match credentials against current process creds.
 
111
 * The root_override argument takes care of cases where the caller may
 
112
 * request root creds (e.g. for NFS swapping).
 
113
 */
 
114
static int
 
115
unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
 
116
{
 
117
        struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base);
 
118
        unsigned int groups = 0;
 
119
        unsigned int i;
 
120
 
 
121
 
 
122
        if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid)
 
123
                return 0;
 
124
 
 
125
        if (acred->group_info != NULL)
 
126
                groups = acred->group_info->ngroups;
 
127
        if (groups > NFS_NGROUPS)
 
128
                groups = NFS_NGROUPS;
 
129
        for (i = 0; i < groups ; i++)
 
130
                if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
 
131
                        return 0;
 
132
        if (groups < NFS_NGROUPS &&
 
133
            cred->uc_gids[groups] != NOGROUP)
 
134
                return 0;
 
135
        return 1;
 
136
}
 
137
 
 
138
/*
 
139
 * Marshal credentials.
 
140
 * Maybe we should keep a cached credential for performance reasons.
 
141
 */
 
142
static __be32 *
 
143
unx_marshal(struct rpc_task *task, __be32 *p)
 
144
{
 
145
        struct rpc_clnt *clnt = task->tk_client;
 
146
        struct unx_cred *cred = container_of(task->tk_rqstp->rq_cred, struct unx_cred, uc_base);
 
147
        __be32          *base, *hold;
 
148
        int             i;
 
149
 
 
150
        *p++ = htonl(RPC_AUTH_UNIX);
 
151
        base = p++;
 
152
        *p++ = htonl(jiffies/HZ);
 
153
 
 
154
        /*
 
155
         * Copy the UTS nodename captured when the client was created.
 
156
         */
 
157
        p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
 
158
 
 
159
        *p++ = htonl((u32) cred->uc_uid);
 
160
        *p++ = htonl((u32) cred->uc_gid);
 
161
        hold = p++;
 
162
        for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
 
163
                *p++ = htonl((u32) cred->uc_gids[i]);
 
164
        *hold = htonl(p - hold - 1);            /* gid array length */
 
165
        *base = htonl((p - base - 1) << 2);     /* cred length */
 
166
 
 
167
        *p++ = htonl(RPC_AUTH_NULL);
 
168
        *p++ = htonl(0);
 
169
 
 
170
        return p;
 
171
}
 
172
 
 
173
/*
 
174
 * Refresh credentials. This is a no-op for AUTH_UNIX
 
175
 */
 
176
static int
 
177
unx_refresh(struct rpc_task *task)
 
178
{
 
179
        set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_rqstp->rq_cred->cr_flags);
 
180
        return 0;
 
181
}
 
182
 
 
183
static __be32 *
 
184
unx_validate(struct rpc_task *task, __be32 *p)
 
185
{
 
186
        rpc_authflavor_t        flavor;
 
187
        u32                     size;
 
188
 
 
189
        flavor = ntohl(*p++);
 
190
        if (flavor != RPC_AUTH_NULL &&
 
191
            flavor != RPC_AUTH_UNIX &&
 
192
            flavor != RPC_AUTH_SHORT) {
 
193
                printk("RPC: bad verf flavor: %u\n", flavor);
 
194
                return NULL;
 
195
        }
 
196
 
 
197
        size = ntohl(*p++);
 
198
        if (size > RPC_MAX_AUTH_SIZE) {
 
199
                printk("RPC: giant verf size: %u\n", size);
 
200
                return NULL;
 
201
        }
 
202
        task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2;
 
203
        p += (size >> 2);
 
204
 
 
205
        return p;
 
206
}
 
207
 
 
208
int __init rpc_init_authunix(void)
 
209
{
 
210
        return rpcauth_init_credcache(&unix_auth);
 
211
}
 
212
 
 
213
void rpc_destroy_authunix(void)
 
214
{
 
215
        rpcauth_destroy_credcache(&unix_auth);
 
216
}
 
217
 
 
218
const struct rpc_authops authunix_ops = {
 
219
        .owner          = THIS_MODULE,
 
220
        .au_flavor      = RPC_AUTH_UNIX,
 
221
        .au_name        = "UNIX",
 
222
        .create         = unx_create,
 
223
        .destroy        = unx_destroy,
 
224
        .lookup_cred    = unx_lookup_cred,
 
225
        .crcreate       = unx_create_cred,
 
226
};
 
227
 
 
228
static
 
229
struct rpc_auth         unix_auth = {
 
230
        .au_cslack      = UNX_WRITESLACK,
 
231
        .au_rslack      = 2,                    /* assume AUTH_NULL verf */
 
232
        .au_ops         = &authunix_ops,
 
233
        .au_flavor      = RPC_AUTH_UNIX,
 
234
        .au_count       = ATOMIC_INIT(0),
 
235
};
 
236
 
 
237
static
 
238
const struct rpc_credops unix_credops = {
 
239
        .cr_name        = "AUTH_UNIX",
 
240
        .crdestroy      = unx_destroy_cred,
 
241
        .crbind         = rpcauth_generic_bind_cred,
 
242
        .crmatch        = unx_match,
 
243
        .crmarshal      = unx_marshal,
 
244
        .crrefresh      = unx_refresh,
 
245
        .crvalidate     = unx_validate,
 
246
};