]>
git.proxmox.com Git - mirror_ubuntu-kernels.git/blob - net/sunrpc/auth_unix.c
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 dprintk("RPC: creating UNIX authenticator for client %p\n",
33 refcount_inc(&unix_auth
.au_count
);
38 unx_destroy(struct rpc_auth
*auth
)
40 dprintk("RPC: destroying UNIX authenticator %p\n", auth
);
44 * Lookup AUTH_UNIX creds for current process
46 static struct rpc_cred
*
47 unx_lookup_cred(struct rpc_auth
*auth
, struct auth_cred
*acred
, int flags
)
49 struct rpc_cred
*ret
= mempool_alloc(unix_pool
, GFP_NOFS
);
51 dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
52 from_kuid(&init_user_ns
, acred
->cred
->fsuid
),
53 from_kgid(&init_user_ns
, acred
->cred
->fsgid
));
55 rpcauth_init_cred(ret
, acred
, auth
, &unix_credops
);
56 ret
->cr_flags
= 1UL << RPCAUTH_CRED_UPTODATE
;
61 unx_free_cred_callback(struct rcu_head
*head
)
63 struct rpc_cred
*rpc_cred
= container_of(head
, struct rpc_cred
, cr_rcu
);
64 dprintk("RPC: unx_free_cred %p\n", rpc_cred
);
65 put_cred(rpc_cred
->cr_cred
);
66 mempool_free(rpc_cred
, unix_pool
);
70 unx_destroy_cred(struct rpc_cred
*cred
)
72 call_rcu(&cred
->cr_rcu
, unx_free_cred_callback
);
76 * Match credentials against current the auth_cred.
79 unx_match(struct auth_cred
*acred
, struct rpc_cred
*cred
, int flags
)
81 unsigned int groups
= 0;
84 if (cred
->cr_cred
== acred
->cred
)
87 if (!uid_eq(cred
->cr_cred
->fsuid
, acred
->cred
->fsuid
) || !gid_eq(cred
->cr_cred
->fsgid
, acred
->cred
->fsgid
))
90 if (acred
->cred
&& acred
->cred
->group_info
!= NULL
)
91 groups
= acred
->cred
->group_info
->ngroups
;
92 if (groups
> UNX_NGROUPS
)
94 if (cred
->cr_cred
->group_info
== NULL
)
96 if (groups
!= cred
->cr_cred
->group_info
->ngroups
)
99 for (i
= 0; i
< groups
; i
++)
100 if (!gid_eq(cred
->cr_cred
->group_info
->gid
[i
], acred
->cred
->group_info
->gid
[i
]))
106 * Marshal credentials.
107 * Maybe we should keep a cached credential for performance reasons.
110 unx_marshal(struct rpc_task
*task
, __be32
*p
)
112 struct rpc_clnt
*clnt
= task
->tk_client
;
113 struct rpc_cred
*cred
= task
->tk_rqstp
->rq_cred
;
116 struct group_info
*gi
= cred
->cr_cred
->group_info
;
118 *p
++ = htonl(RPC_AUTH_UNIX
);
120 *p
++ = htonl(jiffies
/HZ
);
123 * Copy the UTS nodename captured when the client was created.
125 p
= xdr_encode_array(p
, clnt
->cl_nodename
, clnt
->cl_nodelen
);
127 *p
++ = htonl((u32
) from_kuid(&init_user_ns
, cred
->cr_cred
->fsuid
));
128 *p
++ = htonl((u32
) from_kgid(&init_user_ns
, cred
->cr_cred
->fsgid
));
131 for (i
= 0; i
< UNX_NGROUPS
&& i
< gi
->ngroups
; i
++)
132 *p
++ = htonl((u32
) from_kgid(&init_user_ns
, gi
->gid
[i
]));
133 *hold
= htonl(p
- hold
- 1); /* gid array length */
134 *base
= htonl((p
- base
- 1) << 2); /* cred length */
136 *p
++ = htonl(RPC_AUTH_NULL
);
143 * Refresh credentials. This is a no-op for AUTH_UNIX
146 unx_refresh(struct rpc_task
*task
)
148 set_bit(RPCAUTH_CRED_UPTODATE
, &task
->tk_rqstp
->rq_cred
->cr_flags
);
153 unx_validate(struct rpc_task
*task
, __be32
*p
)
155 rpc_authflavor_t flavor
;
158 flavor
= ntohl(*p
++);
159 if (flavor
!= RPC_AUTH_NULL
&&
160 flavor
!= RPC_AUTH_UNIX
&&
161 flavor
!= RPC_AUTH_SHORT
) {
162 printk("RPC: bad verf flavor: %u\n", flavor
);
163 return ERR_PTR(-EIO
);
167 if (size
> RPC_MAX_AUTH_SIZE
) {
168 printk("RPC: giant verf size: %u\n", size
);
169 return ERR_PTR(-EIO
);
171 task
->tk_rqstp
->rq_cred
->cr_auth
->au_rslack
= (size
>> 2) + 2;
177 int __init
rpc_init_authunix(void)
179 unix_pool
= mempool_create_kmalloc_pool(16, sizeof(struct rpc_cred
));
180 return unix_pool
? 0 : -ENOMEM
;
183 void rpc_destroy_authunix(void)
185 mempool_destroy(unix_pool
);
188 const struct rpc_authops authunix_ops
= {
189 .owner
= THIS_MODULE
,
190 .au_flavor
= RPC_AUTH_UNIX
,
192 .create
= unx_create
,
193 .destroy
= unx_destroy
,
194 .lookup_cred
= unx_lookup_cred
,
198 struct rpc_auth unix_auth
= {
199 .au_cslack
= UNX_CALLSLACK
,
200 .au_rslack
= NUL_REPLYSLACK
,
201 .au_ops
= &authunix_ops
,
202 .au_flavor
= RPC_AUTH_UNIX
,
203 .au_count
= REFCOUNT_INIT(1),
207 const struct rpc_credops unix_credops
= {
208 .cr_name
= "AUTH_UNIX",
209 .crdestroy
= unx_destroy_cred
,
210 .crmatch
= unx_match
,
211 .crmarshal
= unx_marshal
,
212 .crrefresh
= unx_refresh
,
213 .crvalidate
= unx_validate
,