1 // SPDX-License-Identifier: GPL-2.0
3 * linux/net/sunrpc/auth_unix.c
5 * UNIX-style authentication; no AUTH_SHORT support
7 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
10 #include <linux/slab.h>
11 #include <linux/types.h>
12 #include <linux/sched.h>
13 #include <linux/module.h>
14 #include <linux/mempool.h>
15 #include <linux/sunrpc/clnt.h>
16 #include <linux/sunrpc/auth.h>
17 #include <linux/user_namespace.h>
20 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
21 # define RPCDBG_FACILITY RPCDBG_AUTH
24 static struct rpc_auth unix_auth
;
25 static const struct rpc_credops unix_credops
;
26 static mempool_t
*unix_pool
;
28 static struct rpc_auth
*
29 unx_create(const struct rpc_auth_create_args
*args
, struct rpc_clnt
*clnt
)
31 refcount_inc(&unix_auth
.au_count
);
36 unx_destroy(struct rpc_auth
*auth
)
41 * Lookup AUTH_UNIX creds for current process
43 static struct rpc_cred
*unx_lookup_cred(struct rpc_auth
*auth
,
44 struct auth_cred
*acred
, int flags
)
48 ret
= kmalloc(sizeof(*ret
), rpc_task_gfp_mask());
50 if (!(flags
& RPCAUTH_LOOKUP_ASYNC
))
51 return ERR_PTR(-ENOMEM
);
52 ret
= mempool_alloc(unix_pool
, GFP_NOWAIT
);
54 return ERR_PTR(-ENOMEM
);
56 rpcauth_init_cred(ret
, acred
, auth
, &unix_credops
);
57 ret
->cr_flags
= 1UL << RPCAUTH_CRED_UPTODATE
;
62 unx_free_cred_callback(struct rcu_head
*head
)
64 struct rpc_cred
*rpc_cred
= container_of(head
, struct rpc_cred
, cr_rcu
);
66 put_cred(rpc_cred
->cr_cred
);
67 mempool_free(rpc_cred
, unix_pool
);
71 unx_destroy_cred(struct rpc_cred
*cred
)
73 call_rcu(&cred
->cr_rcu
, unx_free_cred_callback
);
77 * Match credentials against current the auth_cred.
80 unx_match(struct auth_cred
*acred
, struct rpc_cred
*cred
, int flags
)
82 unsigned int groups
= 0;
85 if (cred
->cr_cred
== acred
->cred
)
88 if (!uid_eq(cred
->cr_cred
->fsuid
, acred
->cred
->fsuid
) || !gid_eq(cred
->cr_cred
->fsgid
, acred
->cred
->fsgid
))
91 if (acred
->cred
->group_info
!= NULL
)
92 groups
= acred
->cred
->group_info
->ngroups
;
93 if (groups
> UNX_NGROUPS
)
95 if (cred
->cr_cred
->group_info
== NULL
)
97 if (groups
!= cred
->cr_cred
->group_info
->ngroups
)
100 for (i
= 0; i
< groups
; i
++)
101 if (!gid_eq(cred
->cr_cred
->group_info
->gid
[i
], acred
->cred
->group_info
->gid
[i
]))
107 * Marshal credentials.
108 * Maybe we should keep a cached credential for performance reasons.
111 unx_marshal(struct rpc_task
*task
, struct xdr_stream
*xdr
)
113 struct rpc_clnt
*clnt
= task
->tk_client
;
114 struct rpc_cred
*cred
= task
->tk_rqstp
->rq_cred
;
115 __be32
*p
, *cred_len
, *gidarr_len
;
117 struct group_info
*gi
= cred
->cr_cred
->group_info
;
118 struct user_namespace
*userns
= clnt
->cl_cred
?
119 clnt
->cl_cred
->user_ns
: &init_user_ns
;
123 p
= xdr_reserve_space(xdr
, 3 * sizeof(*p
));
126 *p
++ = rpc_auth_unix
;
128 *p
++ = xdr_zero
; /* stamp */
129 if (xdr_stream_encode_opaque(xdr
, clnt
->cl_nodename
,
130 clnt
->cl_nodelen
) < 0)
132 p
= xdr_reserve_space(xdr
, 3 * sizeof(*p
));
135 *p
++ = cpu_to_be32(from_kuid_munged(userns
, cred
->cr_cred
->fsuid
));
136 *p
++ = cpu_to_be32(from_kgid_munged(userns
, cred
->cr_cred
->fsgid
));
140 for (i
= 0; i
< UNX_NGROUPS
&& i
< gi
->ngroups
; i
++)
141 *p
++ = cpu_to_be32(from_kgid_munged(userns
, gi
->gid
[i
]));
142 *gidarr_len
= cpu_to_be32(p
- gidarr_len
- 1);
143 *cred_len
= cpu_to_be32((p
- cred_len
- 1) << 2);
144 p
= xdr_reserve_space(xdr
, (p
- gidarr_len
- 1) << 2);
150 p
= xdr_reserve_space(xdr
, 2 * sizeof(*p
));
153 *p
++ = rpc_auth_null
;
163 * Refresh credentials. This is a no-op for AUTH_UNIX
166 unx_refresh(struct rpc_task
*task
)
168 set_bit(RPCAUTH_CRED_UPTODATE
, &task
->tk_rqstp
->rq_cred
->cr_flags
);
173 unx_validate(struct rpc_task
*task
, struct xdr_stream
*xdr
)
175 struct rpc_auth
*auth
= task
->tk_rqstp
->rq_cred
->cr_auth
;
179 p
= xdr_inline_decode(xdr
, 2 * sizeof(*p
));
190 size
= be32_to_cpup(p
);
191 if (size
> RPC_MAX_AUTH_SIZE
)
193 p
= xdr_inline_decode(xdr
, size
);
197 auth
->au_verfsize
= XDR_QUADLEN(size
) + 2;
198 auth
->au_rslack
= XDR_QUADLEN(size
) + 2;
199 auth
->au_ralign
= XDR_QUADLEN(size
) + 2;
203 int __init
rpc_init_authunix(void)
205 unix_pool
= mempool_create_kmalloc_pool(16, sizeof(struct rpc_cred
));
206 return unix_pool
? 0 : -ENOMEM
;
209 void rpc_destroy_authunix(void)
211 mempool_destroy(unix_pool
);
214 const struct rpc_authops authunix_ops
= {
215 .owner
= THIS_MODULE
,
216 .au_flavor
= RPC_AUTH_UNIX
,
218 .create
= unx_create
,
219 .destroy
= unx_destroy
,
220 .lookup_cred
= unx_lookup_cred
,
224 struct rpc_auth unix_auth
= {
225 .au_cslack
= UNX_CALLSLACK
,
226 .au_rslack
= NUL_REPLYSLACK
,
227 .au_verfsize
= NUL_REPLYSLACK
,
228 .au_ops
= &authunix_ops
,
229 .au_flavor
= RPC_AUTH_UNIX
,
230 .au_count
= REFCOUNT_INIT(1),
234 const struct rpc_credops unix_credops
= {
235 .cr_name
= "AUTH_UNIX",
236 .crdestroy
= unx_destroy_cred
,
237 .crmatch
= unx_match
,
238 .crmarshal
= unx_marshal
,
239 .crwrap_req
= rpcauth_wrap_req_encode
,
240 .crrefresh
= unx_refresh
,
241 .crvalidate
= unx_validate
,
242 .crunwrap_resp
= rpcauth_unwrap_resp_decode
,