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/sunrpc/clnt.h>
15 #include <linux/sunrpc/auth.h>
16 #include <linux/user_namespace.h>
19 struct rpc_cred uc_base
;
21 kgid_t uc_gids
[UNX_NGROUPS
];
23 #define uc_uid uc_base.cr_uid
25 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
26 # define RPCDBG_FACILITY RPCDBG_AUTH
29 static struct rpc_auth unix_auth
;
30 static const struct rpc_credops unix_credops
;
32 static struct rpc_auth
*
33 unx_create(const struct rpc_auth_create_args
*args
, struct rpc_clnt
*clnt
)
35 dprintk("RPC: creating UNIX authenticator for client %p\n",
37 refcount_inc(&unix_auth
.au_count
);
42 unx_destroy(struct rpc_auth
*auth
)
44 dprintk("RPC: destroying UNIX authenticator %p\n", auth
);
45 rpcauth_clear_credcache(auth
->au_credcache
);
49 unx_hash_cred(struct auth_cred
*acred
, unsigned int hashbits
)
51 return hash_64(from_kgid(&init_user_ns
, acred
->gid
) |
52 ((u64
)from_kuid(&init_user_ns
, acred
->uid
) <<
53 (sizeof(gid_t
) * 8)), hashbits
);
57 * Lookup AUTH_UNIX creds for current process
59 static struct rpc_cred
*
60 unx_lookup_cred(struct rpc_auth
*auth
, struct auth_cred
*acred
, int flags
)
62 return rpcauth_lookup_credcache(auth
, acred
, flags
, GFP_NOFS
);
65 static struct rpc_cred
*
66 unx_create_cred(struct rpc_auth
*auth
, struct auth_cred
*acred
, int flags
, gfp_t gfp
)
68 struct unx_cred
*cred
;
69 unsigned int groups
= 0;
72 dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
73 from_kuid(&init_user_ns
, acred
->uid
),
74 from_kgid(&init_user_ns
, acred
->gid
));
76 if (!(cred
= kmalloc(sizeof(*cred
), gfp
)))
77 return ERR_PTR(-ENOMEM
);
79 rpcauth_init_cred(&cred
->uc_base
, acred
, auth
, &unix_credops
);
80 cred
->uc_base
.cr_flags
= 1UL << RPCAUTH_CRED_UPTODATE
;
82 if (acred
->group_info
!= NULL
)
83 groups
= acred
->group_info
->ngroups
;
84 if (groups
> UNX_NGROUPS
)
87 cred
->uc_gid
= acred
->gid
;
88 for (i
= 0; i
< groups
; i
++)
89 cred
->uc_gids
[i
] = acred
->group_info
->gid
[i
];
91 cred
->uc_gids
[i
] = INVALID_GID
;
93 return &cred
->uc_base
;
97 unx_free_cred(struct unx_cred
*unx_cred
)
99 dprintk("RPC: unx_free_cred %p\n", unx_cred
);
104 unx_free_cred_callback(struct rcu_head
*head
)
106 struct unx_cred
*unx_cred
= container_of(head
, struct unx_cred
, uc_base
.cr_rcu
);
107 unx_free_cred(unx_cred
);
111 unx_destroy_cred(struct rpc_cred
*cred
)
113 call_rcu(&cred
->cr_rcu
, unx_free_cred_callback
);
117 * Match credentials against current process creds.
118 * The root_override argument takes care of cases where the caller may
119 * request root creds (e.g. for NFS swapping).
122 unx_match(struct auth_cred
*acred
, struct rpc_cred
*rcred
, int flags
)
124 struct unx_cred
*cred
= container_of(rcred
, struct unx_cred
, uc_base
);
125 unsigned int groups
= 0;
129 if (!uid_eq(cred
->uc_uid
, acred
->uid
) || !gid_eq(cred
->uc_gid
, acred
->gid
))
132 if (acred
->group_info
!= NULL
)
133 groups
= acred
->group_info
->ngroups
;
134 if (groups
> UNX_NGROUPS
)
135 groups
= UNX_NGROUPS
;
136 for (i
= 0; i
< groups
; i
++)
137 if (!gid_eq(cred
->uc_gids
[i
], acred
->group_info
->gid
[i
]))
139 if (groups
< UNX_NGROUPS
&& gid_valid(cred
->uc_gids
[groups
]))
145 * Marshal credentials.
146 * Maybe we should keep a cached credential for performance reasons.
149 unx_marshal(struct rpc_task
*task
, __be32
*p
)
151 struct rpc_clnt
*clnt
= task
->tk_client
;
152 struct unx_cred
*cred
= container_of(task
->tk_rqstp
->rq_cred
, struct unx_cred
, uc_base
);
156 *p
++ = htonl(RPC_AUTH_UNIX
);
158 *p
++ = htonl(jiffies
/HZ
);
161 * Copy the UTS nodename captured when the client was created.
163 p
= xdr_encode_array(p
, clnt
->cl_nodename
, clnt
->cl_nodelen
);
165 *p
++ = htonl((u32
) from_kuid(&init_user_ns
, cred
->uc_uid
));
166 *p
++ = htonl((u32
) from_kgid(&init_user_ns
, cred
->uc_gid
));
168 for (i
= 0; i
< UNX_NGROUPS
&& gid_valid(cred
->uc_gids
[i
]); i
++)
169 *p
++ = htonl((u32
) from_kgid(&init_user_ns
, cred
->uc_gids
[i
]));
170 *hold
= htonl(p
- hold
- 1); /* gid array length */
171 *base
= htonl((p
- base
- 1) << 2); /* cred length */
173 *p
++ = htonl(RPC_AUTH_NULL
);
180 * Refresh credentials. This is a no-op for AUTH_UNIX
183 unx_refresh(struct rpc_task
*task
)
185 set_bit(RPCAUTH_CRED_UPTODATE
, &task
->tk_rqstp
->rq_cred
->cr_flags
);
190 unx_validate(struct rpc_task
*task
, __be32
*p
)
192 rpc_authflavor_t flavor
;
195 flavor
= ntohl(*p
++);
196 if (flavor
!= RPC_AUTH_NULL
&&
197 flavor
!= RPC_AUTH_UNIX
&&
198 flavor
!= RPC_AUTH_SHORT
) {
199 printk("RPC: bad verf flavor: %u\n", flavor
);
200 return ERR_PTR(-EIO
);
204 if (size
> RPC_MAX_AUTH_SIZE
) {
205 printk("RPC: giant verf size: %u\n", size
);
206 return ERR_PTR(-EIO
);
208 task
->tk_rqstp
->rq_cred
->cr_auth
->au_rslack
= (size
>> 2) + 2;
214 int __init
rpc_init_authunix(void)
216 return rpcauth_init_credcache(&unix_auth
);
219 void rpc_destroy_authunix(void)
221 rpcauth_destroy_credcache(&unix_auth
);
224 const struct rpc_authops authunix_ops
= {
225 .owner
= THIS_MODULE
,
226 .au_flavor
= RPC_AUTH_UNIX
,
228 .create
= unx_create
,
229 .destroy
= unx_destroy
,
230 .hash_cred
= unx_hash_cred
,
231 .lookup_cred
= unx_lookup_cred
,
232 .crcreate
= unx_create_cred
,
236 struct rpc_auth unix_auth
= {
237 .au_cslack
= UNX_CALLSLACK
,
238 .au_rslack
= NUL_REPLYSLACK
,
239 .au_flags
= RPCAUTH_AUTH_NO_CRKEY_TIMEOUT
,
240 .au_ops
= &authunix_ops
,
241 .au_flavor
= RPC_AUTH_UNIX
,
242 .au_count
= REFCOUNT_INIT(1),
246 const struct rpc_credops unix_credops
= {
247 .cr_name
= "AUTH_UNIX",
248 .crdestroy
= unx_destroy_cred
,
249 .crbind
= rpcauth_generic_bind_cred
,
250 .crmatch
= unx_match
,
251 .crmarshal
= unx_marshal
,
252 .crrefresh
= unx_refresh
,
253 .crvalidate
= unx_validate
,