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