Blame view

net/sunrpc/auth_unix.c 5.29 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
  /*
   * linux/net/sunrpc/auth_unix.c
   *
   * UNIX-style authentication; no AUTH_SHORT support
   *
   * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
   */
5a0e3ad6a   Tejun Heo   include cleanup: ...
9
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
  #include <linux/types.h>
  #include <linux/sched.h>
  #include <linux/module.h>
2edd8d746   NeilBrown   SUNRPC: simplify ...
13
  #include <linux/mempool.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  #include <linux/sunrpc/clnt.h>
  #include <linux/sunrpc/auth.h>
ae2975bc3   Eric W. Biederman   userns: Convert g...
16
  #include <linux/user_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18

f895b252d   Jeff Layton   sunrpc: eliminate...
19
  #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
  # define RPCDBG_FACILITY	RPCDBG_AUTH
  #endif
  
  static struct rpc_auth		unix_auth;
f1c0a8615   Trond Myklebust   SUNRPC: Mark auth...
24
  static const struct rpc_credops	unix_credops;
2edd8d746   NeilBrown   SUNRPC: simplify ...
25
  static mempool_t		*unix_pool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  
  static struct rpc_auth *
82b98ca56   Sargun Dhillon   net/sunrpc: Make ...
28
  unx_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  {
331bc71cb   Trond Myklebust   SUNRPC: Convert t...
30
  	refcount_inc(&unix_auth.au_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
36
  	return &unix_auth;
  }
  
  static void
  unx_destroy(struct rpc_auth *auth)
  {
1e035d065   Frank Sorenson   sunrpc: add auth_...
37
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
42
43
  /*
   * Lookup AUTH_UNIX creds for current process
   */
  static struct rpc_cred *
  unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
  {
2edd8d746   NeilBrown   SUNRPC: simplify ...
44
  	struct rpc_cred *ret = mempool_alloc(unix_pool, GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

2edd8d746   NeilBrown   SUNRPC: simplify ...
46
47
48
  	rpcauth_init_cred(ret, acred, auth, &unix_credops);
  	ret->cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
  	return ret;
31be5bf15   Trond Myklebust   SUNRPC: Convert t...
49
  }
696e38df9   Trond Myklebust   SUNRPC: replace c...
50

31be5bf15   Trond Myklebust   SUNRPC: Convert t...
51
52
53
  static void
  unx_free_cred_callback(struct rcu_head *head)
  {
2edd8d746   NeilBrown   SUNRPC: simplify ...
54
  	struct rpc_cred *rpc_cred = container_of(head, struct rpc_cred, cr_rcu);
80125d4ae   Chuck Lever   SUNRPC: Remove so...
55

2edd8d746   NeilBrown   SUNRPC: simplify ...
56
57
  	put_cred(rpc_cred->cr_cred);
  	mempool_free(rpc_cred, unix_pool);
31be5bf15   Trond Myklebust   SUNRPC: Convert t...
58
59
60
61
62
63
  }
  
  static void
  unx_destroy_cred(struct rpc_cred *cred)
  {
  	call_rcu(&cred->cr_rcu, unx_free_cred_callback);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
  }
  
  /*
2edd8d746   NeilBrown   SUNRPC: simplify ...
67
   * Match credentials against current the auth_cred.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
   */
  static int
2edd8d746   NeilBrown   SUNRPC: simplify ...
70
  unx_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  {
af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
72
73
  	unsigned int groups = 0;
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74

2edd8d746   NeilBrown   SUNRPC: simplify ...
75
76
  	if (cred->cr_cred == acred->cred)
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77

2edd8d746   NeilBrown   SUNRPC: simplify ...
78
  	if (!uid_eq(cred->cr_cred->fsuid, acred->cred->fsuid) || !gid_eq(cred->cr_cred->fsgid, acred->cred->fsgid))
af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
79
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80

e3735c899   NeilBrown   SUNRPC: remove po...
81
  	if (acred->cred->group_info != NULL)
fc0664fd9   NeilBrown   SUNRPC: remove gr...
82
  		groups = acred->cred->group_info->ngroups;
5786461bd   Kinglong Mee   sunrpc: rename NF...
83
84
  	if (groups > UNX_NGROUPS)
  		groups = UNX_NGROUPS;
2edd8d746   NeilBrown   SUNRPC: simplify ...
85
86
87
88
  	if (cred->cr_cred->group_info == NULL)
  		return groups == 0;
  	if (groups != cred->cr_cred->group_info->ngroups)
  		return 0;
9132adb02   Eric W. Biederman   sunrpc: Simplify ...
89
  	for (i = 0; i < groups ; i++)
2edd8d746   NeilBrown   SUNRPC: simplify ...
90
  		if (!gid_eq(cred->cr_cred->group_info->gid[i], acred->cred->group_info->gid[i]))
af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
91
92
  			return 0;
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
97
98
  }
  
  /*
   * Marshal credentials.
   * Maybe we should keep a cached credential for performance reasons.
   */
e8680a24a   Chuck Lever   SUNRPC: Use struc...
99
100
  static int
  unx_marshal(struct rpc_task *task, struct xdr_stream *xdr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
  {
  	struct rpc_clnt	*clnt = task->tk_client;
2edd8d746   NeilBrown   SUNRPC: simplify ...
103
  	struct rpc_cred	*cred = task->tk_rqstp->rq_cred;
e8680a24a   Chuck Lever   SUNRPC: Use struc...
104
  	__be32		*p, *cred_len, *gidarr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  	int		i;
2edd8d746   NeilBrown   SUNRPC: simplify ...
106
  	struct group_info *gi = cred->cr_cred->group_info;
283ebe3ec   Trond Myklebust   SUNRPC: Use the c...
107
108
  	struct user_namespace *userns = clnt->cl_cred ?
  		clnt->cl_cred->user_ns : &init_user_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109

e8680a24a   Chuck Lever   SUNRPC: Use struc...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  	/* Credential */
  
  	p = xdr_reserve_space(xdr, 3 * sizeof(*p));
  	if (!p)
  		goto marshal_failed;
  	*p++ = rpc_auth_unix;
  	cred_len = p++;
  	*p++ = xdr_zero;	/* stamp */
  	if (xdr_stream_encode_opaque(xdr, clnt->cl_nodename,
  				     clnt->cl_nodelen) < 0)
  		goto marshal_failed;
  	p = xdr_reserve_space(xdr, 3 * sizeof(*p));
  	if (!p)
  		goto marshal_failed;
283ebe3ec   Trond Myklebust   SUNRPC: Use the c...
124
125
  	*p++ = cpu_to_be32(from_kuid_munged(userns, cred->cr_cred->fsuid));
  	*p++ = cpu_to_be32(from_kgid_munged(userns, cred->cr_cred->fsgid));
e8680a24a   Chuck Lever   SUNRPC: Use struc...
126
127
  
  	gidarr_len = p++;
2edd8d746   NeilBrown   SUNRPC: simplify ...
128
129
  	if (gi)
  		for (i = 0; i < UNX_NGROUPS && i < gi->ngroups; i++)
283ebe3ec   Trond Myklebust   SUNRPC: Use the c...
130
  			*p++ = cpu_to_be32(from_kgid_munged(userns, gi->gid[i]));
e8680a24a   Chuck Lever   SUNRPC: Use struc...
131
132
133
134
135
136
137
138
139
140
141
142
143
  	*gidarr_len = cpu_to_be32(p - gidarr_len - 1);
  	*cred_len = cpu_to_be32((p - cred_len - 1) << 2);
  	p = xdr_reserve_space(xdr, (p - gidarr_len - 1) << 2);
  	if (!p)
  		goto marshal_failed;
  
  	/* Verifier */
  
  	p = xdr_reserve_space(xdr, 2 * sizeof(*p));
  	if (!p)
  		goto marshal_failed;
  	*p++ = rpc_auth_null;
  	*p   = xdr_zero;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144

e8680a24a   Chuck Lever   SUNRPC: Use struc...
145
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146

e8680a24a   Chuck Lever   SUNRPC: Use struc...
147
148
  marshal_failed:
  	return -EMSGSIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
151
152
153
154
155
156
  }
  
  /*
   * Refresh credentials. This is a no-op for AUTH_UNIX
   */
  static int
  unx_refresh(struct rpc_task *task)
  {
a17c2153d   Trond Myklebust   SUNRPC: Move the ...
157
  	set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_rqstp->rq_cred->cr_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  	return 0;
  }
a0584ee9a   Chuck Lever   SUNRPC: Use struc...
160
161
  static int
  unx_validate(struct rpc_task *task, struct xdr_stream *xdr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  {
a00275baa   Chuck Lever   SUNRPC: Make AUTH...
163
  	struct rpc_auth *auth = task->tk_rqstp->rq_cred->cr_auth;
a0584ee9a   Chuck Lever   SUNRPC: Use struc...
164
165
  	__be32 *p;
  	u32 size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166

a0584ee9a   Chuck Lever   SUNRPC: Use struc...
167
168
169
170
171
172
173
174
175
176
  	p = xdr_inline_decode(xdr, 2 * sizeof(*p));
  	if (!p)
  		return -EIO;
  	switch (*p++) {
  	case rpc_auth_null:
  	case rpc_auth_unix:
  	case rpc_auth_short:
  		break;
  	default:
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  	}
a0584ee9a   Chuck Lever   SUNRPC: Use struc...
178
179
180
181
182
183
  	size = be32_to_cpup(p);
  	if (size > RPC_MAX_AUTH_SIZE)
  		return -EIO;
  	p = xdr_inline_decode(xdr, size);
  	if (!p)
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184

a00275baa   Chuck Lever   SUNRPC: Make AUTH...
185
186
  	auth->au_verfsize = XDR_QUADLEN(size) + 2;
  	auth->au_rslack = XDR_QUADLEN(size) + 2;
35e77d21b   Chuck Lever   SUNRPC: Add rpc_a...
187
  	auth->au_ralign = XDR_QUADLEN(size) + 2;
a0584ee9a   Chuck Lever   SUNRPC: Use struc...
188
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  }
5d8d9a4d9   Trond Myklebust   NFS: Ensure the A...
190
  int __init rpc_init_authunix(void)
9499b4341   Trond Myklebust   SUNRPC: Give cred...
191
  {
2edd8d746   NeilBrown   SUNRPC: simplify ...
192
193
  	unix_pool = mempool_create_kmalloc_pool(16, sizeof(struct rpc_cred));
  	return unix_pool ? 0 : -ENOMEM;
5d8d9a4d9   Trond Myklebust   NFS: Ensure the A...
194
195
196
197
  }
  
  void rpc_destroy_authunix(void)
  {
2edd8d746   NeilBrown   SUNRPC: simplify ...
198
  	mempool_destroy(unix_pool);
9499b4341   Trond Myklebust   SUNRPC: Give cred...
199
  }
f1c0a8615   Trond Myklebust   SUNRPC: Mark auth...
200
  const struct rpc_authops authunix_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
  	.owner		= THIS_MODULE,
  	.au_flavor	= RPC_AUTH_UNIX,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  	.au_name	= "UNIX",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
  	.create		= unx_create,
  	.destroy	= unx_destroy,
  	.lookup_cred	= unx_lookup_cred,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
209
  };
  
  static
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  struct rpc_auth		unix_auth = {
4500632f6   Chuck Lever   nfsd: Lower NFSv4...
211
212
  	.au_cslack	= UNX_CALLSLACK,
  	.au_rslack	= NUL_REPLYSLACK,
a00275baa   Chuck Lever   SUNRPC: Make AUTH...
213
  	.au_verfsize	= NUL_REPLYSLACK,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	.au_ops		= &authunix_ops,
81039f1f2   Trond Myklebust   NFS: Display the ...
215
  	.au_flavor	= RPC_AUTH_UNIX,
331bc71cb   Trond Myklebust   SUNRPC: Convert t...
216
  	.au_count	= REFCOUNT_INIT(1),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
  };
  
  static
f1c0a8615   Trond Myklebust   SUNRPC: Mark auth...
220
  const struct rpc_credops unix_credops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
  	.cr_name	= "AUTH_UNIX",
  	.crdestroy	= unx_destroy_cred,
  	.crmatch	= unx_match,
  	.crmarshal	= unx_marshal,
e8680a24a   Chuck Lever   SUNRPC: Use struc...
225
  	.crwrap_req	= rpcauth_wrap_req_encode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
  	.crrefresh	= unx_refresh,
  	.crvalidate	= unx_validate,
a0584ee9a   Chuck Lever   SUNRPC: Use struc...
228
  	.crunwrap_resp	= rpcauth_unwrap_resp_decode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  };