xref: /freebsd-src/sys/contrib/openzfs/module/os/linux/zfs/policy.c (revision da5137abdf463bb5fee85061958a14dd12bc043e)
1eda14cbcSMatt Macy /*
2eda14cbcSMatt Macy  * CDDL HEADER START
3eda14cbcSMatt Macy  *
4eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9eda14cbcSMatt Macy  * or http://www.opensolaris.org/os/licensing.
10eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11eda14cbcSMatt Macy  * and limitations under the License.
12eda14cbcSMatt Macy  *
13eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18eda14cbcSMatt Macy  *
19eda14cbcSMatt Macy  * CDDL HEADER END
20eda14cbcSMatt Macy  */
21eda14cbcSMatt Macy 
22eda14cbcSMatt Macy /*
23eda14cbcSMatt Macy  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24eda14cbcSMatt Macy  * Copyright 2013, Joyent, Inc. All rights reserved.
25eda14cbcSMatt Macy  * Copyright (C) 2016 Lawrence Livermore National Security, LLC.
26eda14cbcSMatt Macy  *
27eda14cbcSMatt Macy  * For Linux the vast majority of this enforcement is already handled via
28eda14cbcSMatt Macy  * the standard Linux VFS permission checks.  However certain administrative
29eda14cbcSMatt Macy  * commands which bypass the standard mechanisms may need to make use of
30eda14cbcSMatt Macy  * this functionality.
31eda14cbcSMatt Macy  */
32eda14cbcSMatt Macy 
33eda14cbcSMatt Macy #include <sys/policy.h>
34eda14cbcSMatt Macy #include <linux/security.h>
35eda14cbcSMatt Macy #include <linux/vfs_compat.h>
36eda14cbcSMatt Macy 
37eda14cbcSMatt Macy /*
38eda14cbcSMatt Macy  * The passed credentials cannot be directly verified because Linux only
39eda14cbcSMatt Macy  * provides and interface to check the *current* process credentials.  In
40eda14cbcSMatt Macy  * order to handle this the capable() test is only run when the passed
41eda14cbcSMatt Macy  * credentials match the current process credentials or the kcred.  In
42eda14cbcSMatt Macy  * all other cases this function must fail and return the passed err.
43eda14cbcSMatt Macy  */
44eda14cbcSMatt Macy static int
45eda14cbcSMatt Macy priv_policy_ns(const cred_t *cr, int capability, int err,
46eda14cbcSMatt Macy     struct user_namespace *ns)
47eda14cbcSMatt Macy {
48eda14cbcSMatt Macy 	if (cr != CRED() && (cr != kcred))
49eda14cbcSMatt Macy 		return (err);
50eda14cbcSMatt Macy 
51eda14cbcSMatt Macy #if defined(CONFIG_USER_NS)
52eda14cbcSMatt Macy 	if (!(ns ? ns_capable(ns, capability) : capable(capability)))
53eda14cbcSMatt Macy #else
54eda14cbcSMatt Macy 	if (!capable(capability))
55eda14cbcSMatt Macy #endif
56eda14cbcSMatt Macy 		return (err);
57eda14cbcSMatt Macy 
58eda14cbcSMatt Macy 	return (0);
59eda14cbcSMatt Macy }
60eda14cbcSMatt Macy 
61eda14cbcSMatt Macy static int
62eda14cbcSMatt Macy priv_policy(const cred_t *cr, int capability, int err)
63eda14cbcSMatt Macy {
64eda14cbcSMatt Macy 	return (priv_policy_ns(cr, capability, err, NULL));
65eda14cbcSMatt Macy }
66eda14cbcSMatt Macy 
67eda14cbcSMatt Macy static int
68eda14cbcSMatt Macy priv_policy_user(const cred_t *cr, int capability, int err)
69eda14cbcSMatt Macy {
70eda14cbcSMatt Macy 	/*
71eda14cbcSMatt Macy 	 * All priv_policy_user checks are preceded by kuid/kgid_has_mapping()
72eda14cbcSMatt Macy 	 * checks. If we cannot do them, we shouldn't be using ns_capable()
73eda14cbcSMatt Macy 	 * since we don't know whether the affected files are valid in our
74eda14cbcSMatt Macy 	 * namespace.
75eda14cbcSMatt Macy 	 */
76eda14cbcSMatt Macy #if defined(CONFIG_USER_NS)
77eda14cbcSMatt Macy 	return (priv_policy_ns(cr, capability, err, cr->user_ns));
78eda14cbcSMatt Macy #else
79eda14cbcSMatt Macy 	return (priv_policy_ns(cr, capability, err, NULL));
80eda14cbcSMatt Macy #endif
81eda14cbcSMatt Macy }
82eda14cbcSMatt Macy 
83eda14cbcSMatt Macy /*
84eda14cbcSMatt Macy  * Checks for operations that are either client-only or are used by
85eda14cbcSMatt Macy  * both clients and servers.
86eda14cbcSMatt Macy  */
87eda14cbcSMatt Macy int
88eda14cbcSMatt Macy secpolicy_nfs(const cred_t *cr)
89eda14cbcSMatt Macy {
90eda14cbcSMatt Macy 	return (priv_policy(cr, CAP_SYS_ADMIN, EPERM));
91eda14cbcSMatt Macy }
92eda14cbcSMatt Macy 
93eda14cbcSMatt Macy /*
94eda14cbcSMatt Macy  * Catch all system configuration.
95eda14cbcSMatt Macy  */
96eda14cbcSMatt Macy int
97eda14cbcSMatt Macy secpolicy_sys_config(const cred_t *cr, boolean_t checkonly)
98eda14cbcSMatt Macy {
99eda14cbcSMatt Macy 	return (priv_policy(cr, CAP_SYS_ADMIN, EPERM));
100eda14cbcSMatt Macy }
101eda14cbcSMatt Macy 
102eda14cbcSMatt Macy /*
103eda14cbcSMatt Macy  * Like secpolicy_vnode_access() but we get the actual wanted mode and the
104eda14cbcSMatt Macy  * current mode of the file, not the missing bits.
105eda14cbcSMatt Macy  *
106eda14cbcSMatt Macy  * Enforced in the Linux VFS.
107eda14cbcSMatt Macy  */
108eda14cbcSMatt Macy int
109eda14cbcSMatt Macy secpolicy_vnode_access2(const cred_t *cr, struct inode *ip, uid_t owner,
110eda14cbcSMatt Macy     mode_t curmode, mode_t wantmode)
111eda14cbcSMatt Macy {
112eda14cbcSMatt Macy 	return (0);
113eda14cbcSMatt Macy }
114eda14cbcSMatt Macy 
115eda14cbcSMatt Macy /*
116eda14cbcSMatt Macy  * This is a special routine for ZFS; it is used to determine whether
117eda14cbcSMatt Macy  * any of the privileges in effect allow any form of access to the
118eda14cbcSMatt Macy  * file.  There's no reason to audit this or any reason to record
119eda14cbcSMatt Macy  * this.  More work is needed to do the "KPLD" stuff.
120eda14cbcSMatt Macy  */
121eda14cbcSMatt Macy int
122eda14cbcSMatt Macy secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner)
123eda14cbcSMatt Macy {
124*da5137abSMartin Matuska 	if (crgetuid(cr) == owner)
125eda14cbcSMatt Macy 		return (0);
126eda14cbcSMatt Macy 
127f9693befSMartin Matuska 	if (zpl_inode_owner_or_capable(kcred->user_ns, ip))
128eda14cbcSMatt Macy 		return (0);
129eda14cbcSMatt Macy 
130eda14cbcSMatt Macy #if defined(CONFIG_USER_NS)
131eda14cbcSMatt Macy 	if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner)))
132eda14cbcSMatt Macy 		return (EPERM);
133eda14cbcSMatt Macy #endif
134eda14cbcSMatt Macy 
135eda14cbcSMatt Macy 	if (priv_policy_user(cr, CAP_DAC_OVERRIDE, EPERM) == 0)
136eda14cbcSMatt Macy 		return (0);
137eda14cbcSMatt Macy 
138eda14cbcSMatt Macy 	if (priv_policy_user(cr, CAP_DAC_READ_SEARCH, EPERM) == 0)
139eda14cbcSMatt Macy 		return (0);
140eda14cbcSMatt Macy 
141eda14cbcSMatt Macy 	return (EPERM);
142eda14cbcSMatt Macy }
143eda14cbcSMatt Macy 
144eda14cbcSMatt Macy /*
145eda14cbcSMatt Macy  * Determine if subject can chown owner of a file.
146eda14cbcSMatt Macy  */
147eda14cbcSMatt Macy int
148eda14cbcSMatt Macy secpolicy_vnode_chown(const cred_t *cr, uid_t owner)
149eda14cbcSMatt Macy {
150*da5137abSMartin Matuska 	if (crgetuid(cr) == owner)
151eda14cbcSMatt Macy 		return (0);
152eda14cbcSMatt Macy 
153eda14cbcSMatt Macy #if defined(CONFIG_USER_NS)
154eda14cbcSMatt Macy 	if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner)))
155eda14cbcSMatt Macy 		return (EPERM);
156eda14cbcSMatt Macy #endif
157eda14cbcSMatt Macy 
158eda14cbcSMatt Macy 	return (priv_policy_user(cr, CAP_FOWNER, EPERM));
159eda14cbcSMatt Macy }
160eda14cbcSMatt Macy 
161eda14cbcSMatt Macy /*
162eda14cbcSMatt Macy  * Determine if subject can change group ownership of a file.
163eda14cbcSMatt Macy  */
164eda14cbcSMatt Macy int
165eda14cbcSMatt Macy secpolicy_vnode_create_gid(const cred_t *cr)
166eda14cbcSMatt Macy {
167eda14cbcSMatt Macy 	return (priv_policy(cr, CAP_SETGID, EPERM));
168eda14cbcSMatt Macy }
169eda14cbcSMatt Macy 
170eda14cbcSMatt Macy /*
171eda14cbcSMatt Macy  * Policy determines whether we can remove an entry from a directory,
172eda14cbcSMatt Macy  * regardless of permission bits.
173eda14cbcSMatt Macy  */
174eda14cbcSMatt Macy int
175eda14cbcSMatt Macy secpolicy_vnode_remove(const cred_t *cr)
176eda14cbcSMatt Macy {
177eda14cbcSMatt Macy 	return (priv_policy(cr, CAP_FOWNER, EPERM));
178eda14cbcSMatt Macy }
179eda14cbcSMatt Macy 
180eda14cbcSMatt Macy /*
181eda14cbcSMatt Macy  * Determine that subject can modify the mode of a file.  allzone privilege
182eda14cbcSMatt Macy  * needed when modifying root owned object.
183eda14cbcSMatt Macy  */
184eda14cbcSMatt Macy int
185eda14cbcSMatt Macy secpolicy_vnode_setdac(const cred_t *cr, uid_t owner)
186eda14cbcSMatt Macy {
187*da5137abSMartin Matuska 	if (crgetuid(cr) == owner)
188eda14cbcSMatt Macy 		return (0);
189eda14cbcSMatt Macy 
190eda14cbcSMatt Macy #if defined(CONFIG_USER_NS)
191eda14cbcSMatt Macy 	if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner)))
192eda14cbcSMatt Macy 		return (EPERM);
193eda14cbcSMatt Macy #endif
194eda14cbcSMatt Macy 
195eda14cbcSMatt Macy 	return (priv_policy_user(cr, CAP_FOWNER, EPERM));
196eda14cbcSMatt Macy }
197eda14cbcSMatt Macy 
198eda14cbcSMatt Macy /*
199eda14cbcSMatt Macy  * Are we allowed to retain the set-uid/set-gid bits when
200eda14cbcSMatt Macy  * changing ownership or when writing to a file?
201eda14cbcSMatt Macy  * "issuid" should be true when set-uid; only in that case
202eda14cbcSMatt Macy  * root ownership is checked (setgid is assumed).
203eda14cbcSMatt Macy  *
204eda14cbcSMatt Macy  * Enforced in the Linux VFS.
205eda14cbcSMatt Macy  */
206eda14cbcSMatt Macy int
2077877fdebSMatt Macy secpolicy_vnode_setid_retain(struct znode *zp __maybe_unused, const cred_t *cr,
2087877fdebSMatt Macy     boolean_t issuidroot)
209eda14cbcSMatt Macy {
210eda14cbcSMatt Macy 	return (priv_policy_user(cr, CAP_FSETID, EPERM));
211eda14cbcSMatt Macy }
212eda14cbcSMatt Macy 
213eda14cbcSMatt Macy /*
214eda14cbcSMatt Macy  * Determine that subject can set the file setgid flag.
215eda14cbcSMatt Macy  */
216eda14cbcSMatt Macy int
217eda14cbcSMatt Macy secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid)
218eda14cbcSMatt Macy {
219eda14cbcSMatt Macy #if defined(CONFIG_USER_NS)
220eda14cbcSMatt Macy 	if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid)))
221eda14cbcSMatt Macy 		return (EPERM);
222eda14cbcSMatt Macy #endif
223*da5137abSMartin Matuska 	if (crgetgid(cr) != gid && !groupmember(gid, cr))
224eda14cbcSMatt Macy 		return (priv_policy_user(cr, CAP_FSETID, EPERM));
225eda14cbcSMatt Macy 
226eda14cbcSMatt Macy 	return (0);
227eda14cbcSMatt Macy }
228eda14cbcSMatt Macy 
229eda14cbcSMatt Macy /*
230eda14cbcSMatt Macy  * Determine if the subject can inject faults in the ZFS fault injection
231eda14cbcSMatt Macy  * framework.  Requires all privileges.
232eda14cbcSMatt Macy  */
233eda14cbcSMatt Macy int
234eda14cbcSMatt Macy secpolicy_zinject(const cred_t *cr)
235eda14cbcSMatt Macy {
236eda14cbcSMatt Macy 	return (priv_policy(cr, CAP_SYS_ADMIN, EACCES));
237eda14cbcSMatt Macy }
238eda14cbcSMatt Macy 
239eda14cbcSMatt Macy /*
240eda14cbcSMatt Macy  * Determine if the subject has permission to manipulate ZFS datasets
241eda14cbcSMatt Macy  * (not pools).  Equivalent to the SYS_MOUNT privilege.
242eda14cbcSMatt Macy  */
243eda14cbcSMatt Macy int
244eda14cbcSMatt Macy secpolicy_zfs(const cred_t *cr)
245eda14cbcSMatt Macy {
246eda14cbcSMatt Macy 	return (priv_policy(cr, CAP_SYS_ADMIN, EACCES));
247eda14cbcSMatt Macy }
248eda14cbcSMatt Macy 
249eda14cbcSMatt Macy /*
250eda14cbcSMatt Macy  * Equivalent to secpolicy_zfs(), but works even if the cred_t is not that of
251eda14cbcSMatt Macy  * the current process.  Takes both cred_t and proc_t so that this can work
252eda14cbcSMatt Macy  * easily on all platforms.
253eda14cbcSMatt Macy  *
254eda14cbcSMatt Macy  * The has_capability() function was first exported in the 4.10 Linux kernel
255eda14cbcSMatt Macy  * then backported to some LTS kernels.  Prior to this change there was no
256eda14cbcSMatt Macy  * mechanism to perform this check therefore EACCES is returned when the
257eda14cbcSMatt Macy  * functionality is not present in the kernel.
258eda14cbcSMatt Macy  */
259eda14cbcSMatt Macy int
260eda14cbcSMatt Macy secpolicy_zfs_proc(const cred_t *cr, proc_t *proc)
261eda14cbcSMatt Macy {
262eda14cbcSMatt Macy #if defined(HAVE_HAS_CAPABILITY)
263eda14cbcSMatt Macy 	if (!has_capability(proc, CAP_SYS_ADMIN))
264eda14cbcSMatt Macy 		return (EACCES);
265eda14cbcSMatt Macy 	return (0);
266eda14cbcSMatt Macy #else
267eda14cbcSMatt Macy 	return (EACCES);
268eda14cbcSMatt Macy #endif
269eda14cbcSMatt Macy }
270eda14cbcSMatt Macy 
271eda14cbcSMatt Macy void
272eda14cbcSMatt Macy secpolicy_setid_clear(vattr_t *vap, cred_t *cr)
273eda14cbcSMatt Macy {
274eda14cbcSMatt Macy 	if ((vap->va_mode & (S_ISUID | S_ISGID)) != 0 &&
2757877fdebSMatt Macy 	    secpolicy_vnode_setid_retain(NULL, cr,
276eda14cbcSMatt Macy 	    (vap->va_mode & S_ISUID) != 0 &&
277eda14cbcSMatt Macy 	    (vap->va_mask & AT_UID) != 0 && vap->va_uid == 0) != 0) {
278eda14cbcSMatt Macy 		vap->va_mask |= AT_MODE;
279eda14cbcSMatt Macy 		vap->va_mode &= ~(S_ISUID|S_ISGID);
280eda14cbcSMatt Macy 	}
281eda14cbcSMatt Macy }
282eda14cbcSMatt Macy 
283eda14cbcSMatt Macy /*
284eda14cbcSMatt Macy  * Determine that subject can set the file setid flags.
285eda14cbcSMatt Macy  */
286eda14cbcSMatt Macy static int
287eda14cbcSMatt Macy secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner)
288eda14cbcSMatt Macy {
289*da5137abSMartin Matuska 	if (crgetuid(cr) == owner)
290eda14cbcSMatt Macy 		return (0);
291eda14cbcSMatt Macy 
292eda14cbcSMatt Macy #if defined(CONFIG_USER_NS)
293eda14cbcSMatt Macy 	if (!kuid_has_mapping(cr->user_ns, SUID_TO_KUID(owner)))
294eda14cbcSMatt Macy 		return (EPERM);
295eda14cbcSMatt Macy #endif
296eda14cbcSMatt Macy 
297eda14cbcSMatt Macy 	return (priv_policy_user(cr, CAP_FSETID, EPERM));
298eda14cbcSMatt Macy }
299eda14cbcSMatt Macy 
300eda14cbcSMatt Macy /*
301eda14cbcSMatt Macy  * Determine that subject can make a file a "sticky".
302eda14cbcSMatt Macy  *
303eda14cbcSMatt Macy  * Enforced in the Linux VFS.
304eda14cbcSMatt Macy  */
305eda14cbcSMatt Macy static int
306eda14cbcSMatt Macy secpolicy_vnode_stky_modify(const cred_t *cr)
307eda14cbcSMatt Macy {
308eda14cbcSMatt Macy 	return (0);
309eda14cbcSMatt Macy }
310eda14cbcSMatt Macy 
311eda14cbcSMatt Macy int
312eda14cbcSMatt Macy secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap,
313eda14cbcSMatt Macy     const vattr_t *ovap, cred_t *cr)
314eda14cbcSMatt Macy {
315eda14cbcSMatt Macy 	int error;
316eda14cbcSMatt Macy 
317eda14cbcSMatt Macy 	if ((vap->va_mode & S_ISUID) != 0 &&
318eda14cbcSMatt Macy 	    (error = secpolicy_vnode_setid_modify(cr,
319eda14cbcSMatt Macy 	    ovap->va_uid)) != 0) {
320eda14cbcSMatt Macy 		return (error);
321eda14cbcSMatt Macy 	}
322eda14cbcSMatt Macy 
323eda14cbcSMatt Macy 	/*
324eda14cbcSMatt Macy 	 * Check privilege if attempting to set the
325eda14cbcSMatt Macy 	 * sticky bit on a non-directory.
326eda14cbcSMatt Macy 	 */
327eda14cbcSMatt Macy 	if (!S_ISDIR(ip->i_mode) && (vap->va_mode & S_ISVTX) != 0 &&
328eda14cbcSMatt Macy 	    secpolicy_vnode_stky_modify(cr) != 0) {
329eda14cbcSMatt Macy 		vap->va_mode &= ~S_ISVTX;
330eda14cbcSMatt Macy 	}
331eda14cbcSMatt Macy 
332eda14cbcSMatt Macy 	/*
333eda14cbcSMatt Macy 	 * Check for privilege if attempting to set the
334eda14cbcSMatt Macy 	 * group-id bit.
335eda14cbcSMatt Macy 	 */
336eda14cbcSMatt Macy 	if ((vap->va_mode & S_ISGID) != 0 &&
337eda14cbcSMatt Macy 	    secpolicy_vnode_setids_setgids(cr, ovap->va_gid) != 0) {
338eda14cbcSMatt Macy 		vap->va_mode &= ~S_ISGID;
339eda14cbcSMatt Macy 	}
340eda14cbcSMatt Macy 
341eda14cbcSMatt Macy 	return (0);
342eda14cbcSMatt Macy }
343eda14cbcSMatt Macy 
344eda14cbcSMatt Macy /*
345eda14cbcSMatt Macy  * Check privileges for setting xvattr attributes
346eda14cbcSMatt Macy  */
347eda14cbcSMatt Macy int
348eda14cbcSMatt Macy secpolicy_xvattr(xvattr_t *xvap, uid_t owner, cred_t *cr, mode_t type)
349eda14cbcSMatt Macy {
350eda14cbcSMatt Macy 	return (secpolicy_vnode_chown(cr, owner));
351eda14cbcSMatt Macy }
352eda14cbcSMatt Macy 
353eda14cbcSMatt Macy /*
354eda14cbcSMatt Macy  * Check privileges for setattr attributes.
355eda14cbcSMatt Macy  *
356eda14cbcSMatt Macy  * Enforced in the Linux VFS.
357eda14cbcSMatt Macy  */
358eda14cbcSMatt Macy int
359eda14cbcSMatt Macy secpolicy_vnode_setattr(cred_t *cr, struct inode *ip, struct vattr *vap,
360eda14cbcSMatt Macy     const struct vattr *ovap, int flags,
361eda14cbcSMatt Macy     int unlocked_access(void *, int, cred_t *), void *node)
362eda14cbcSMatt Macy {
363eda14cbcSMatt Macy 	return (0);
364eda14cbcSMatt Macy }
365eda14cbcSMatt Macy 
366eda14cbcSMatt Macy /*
367eda14cbcSMatt Macy  * Check privileges for links.
368eda14cbcSMatt Macy  *
369eda14cbcSMatt Macy  * Enforced in the Linux VFS.
370eda14cbcSMatt Macy  */
371eda14cbcSMatt Macy int
372eda14cbcSMatt Macy secpolicy_basic_link(const cred_t *cr)
373eda14cbcSMatt Macy {
374eda14cbcSMatt Macy 	return (0);
375eda14cbcSMatt Macy }
376