2 * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/types.h>
28 #include <sys/param.h>
30 #include <sys/vnode.h>
31 #include <sys/mntent.h>
32 #include <sys/mount.h>
35 #include <sys/policy.h>
36 #include <sys/zfs_vfsops.h>
37 #include <sys/zfs_znode.h>
41 secpolicy_nfs(cred_t
*cr
)
44 return (priv_check_cred(cr
, PRIV_NFS_DAEMON
));
48 secpolicy_zfs(cred_t
*cr
)
51 return (priv_check_cred(cr
, PRIV_VFS_MOUNT
));
55 secpolicy_zfs_proc(cred_t
*cr
, proc_t
*proc
)
58 return (priv_check_cred(cr
, PRIV_VFS_MOUNT
));
62 secpolicy_sys_config(cred_t
*cr
, int checkonly __unused
)
65 return (priv_check_cred(cr
, PRIV_ZFS_POOL_CONFIG
));
69 secpolicy_zinject(cred_t
*cr
)
72 return (priv_check_cred(cr
, PRIV_ZFS_INJECT
));
76 secpolicy_fs_unmount(cred_t
*cr
, struct mount
*vfsp __unused
)
79 return (priv_check_cred(cr
, PRIV_VFS_UNMOUNT
));
83 secpolicy_fs_owner(struct mount
*mp
, cred_t
*cr
)
86 if (zfs_super_owner
) {
87 if (cr
->cr_uid
== mp
->mnt_cred
->cr_uid
&&
88 cr
->cr_prison
== mp
->mnt_cred
->cr_prison
) {
96 * This check is done in kern_link(), so we could just return 0 here.
98 extern int hardlink_check_uid
;
100 secpolicy_basic_link(vnode_t
*vp
, cred_t
*cr
)
103 if (!hardlink_check_uid
)
105 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
107 return (priv_check_cred(cr
, PRIV_VFS_LINK
));
111 secpolicy_vnode_stky_modify(cred_t
*cr
)
118 secpolicy_vnode_remove(vnode_t
*vp
, cred_t
*cr
)
121 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
123 return (priv_check_cred(cr
, PRIV_VFS_ADMIN
));
127 secpolicy_vnode_access(cred_t
*cr
, vnode_t
*vp
, uid_t owner
, accmode_t accmode
)
130 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
133 if ((accmode
& VREAD
) && priv_check_cred(cr
, PRIV_VFS_READ
) != 0)
135 if ((accmode
& VWRITE
) &&
136 priv_check_cred(cr
, PRIV_VFS_WRITE
) != 0) {
139 if (accmode
& VEXEC
) {
140 if (vp
->v_type
== VDIR
) {
141 if (priv_check_cred(cr
, PRIV_VFS_LOOKUP
) != 0)
144 if (priv_check_cred(cr
, PRIV_VFS_EXEC
) != 0)
152 * Like secpolicy_vnode_access() but we get the actual wanted mode and the
153 * current mode of the file, not the missing bits.
156 secpolicy_vnode_access2(cred_t
*cr
, vnode_t
*vp
, uid_t owner
,
157 accmode_t curmode
, accmode_t wantmode
)
161 mode
= ~curmode
& wantmode
;
166 return (secpolicy_vnode_access(cr
, vp
, owner
, mode
));
170 secpolicy_vnode_any_access(cred_t
*cr
, vnode_t
*vp
, uid_t owner
)
172 static int privs
[] = {
181 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
184 /* Same as secpolicy_vnode_setdac */
185 if (owner
== cr
->cr_uid
)
188 for (i
= 0; i
< sizeof (privs
)/sizeof (int); i
++) {
191 switch (priv
= privs
[i
]) {
193 if (vp
->v_type
== VDIR
)
196 case PRIV_VFS_LOOKUP
:
197 if (vp
->v_type
!= VDIR
)
201 if (priv_check_cred(cr
, priv
) == 0)
208 secpolicy_vnode_setdac(vnode_t
*vp
, cred_t
*cr
, uid_t owner
)
211 if (owner
== cr
->cr_uid
)
213 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
215 return (priv_check_cred(cr
, PRIV_VFS_ADMIN
));
219 secpolicy_vnode_setattr(cred_t
*cr
, vnode_t
*vp
, struct vattr
*vap
,
220 const struct vattr
*ovap
, int flags
,
221 int unlocked_access(void *, int, cred_t
*), void *node
)
223 int mask
= vap
->va_mask
;
226 if (mask
& AT_SIZE
) {
227 if (vp
->v_type
== VDIR
)
229 error
= unlocked_access(node
, VWRITE
, cr
);
233 if (mask
& AT_MODE
) {
235 * If not the owner of the file then check privilege
236 * for two things: the privilege to set the mode at all
237 * and, if we're setting setuid, we also need permissions
238 * to add the set-uid bit, if we're not the owner.
239 * In the specific case of creating a set-uid root
240 * file, we need even more permissions.
242 error
= secpolicy_vnode_setdac(vp
, cr
, ovap
->va_uid
);
245 error
= secpolicy_setid_setsticky_clear(vp
, vap
, ovap
, cr
);
249 vap
->va_mode
= ovap
->va_mode
;
251 if (mask
& (AT_UID
| AT_GID
)) {
252 error
= secpolicy_vnode_setdac(vp
, cr
, ovap
->va_uid
);
257 * To change the owner of a file, or change the group of
258 * a file to a group of which we are not a member, the
259 * caller must have privilege.
261 if (((mask
& AT_UID
) && vap
->va_uid
!= ovap
->va_uid
) ||
262 ((mask
& AT_GID
) && vap
->va_gid
!= ovap
->va_gid
&&
263 !groupmember(vap
->va_gid
, cr
))) {
264 if (secpolicy_fs_owner(vp
->v_mount
, cr
) != 0) {
265 error
= priv_check_cred(cr
, PRIV_VFS_CHOWN
);
271 if (((mask
& AT_UID
) && vap
->va_uid
!= ovap
->va_uid
) ||
272 ((mask
& AT_GID
) && vap
->va_gid
!= ovap
->va_gid
)) {
273 secpolicy_setid_clear(vap
, vp
, cr
);
276 if (mask
& (AT_ATIME
| AT_MTIME
)) {
279 * If times is NULL, ... The caller must be the owner of
280 * the file, have permission to write the file, or be the
282 * If times is non-NULL, ... The caller must be the owner of
283 * the file or be the super-user.
285 error
= secpolicy_vnode_setdac(vp
, cr
, ovap
->va_uid
);
286 if (error
&& (vap
->va_vaflags
& VA_UTIMES_NULL
))
287 error
= unlocked_access(node
, VWRITE
, cr
);
295 secpolicy_vnode_create_gid(cred_t
*cr
)
302 secpolicy_vnode_setids_setgids(vnode_t
*vp
, cred_t
*cr
, gid_t gid
)
305 if (groupmember(gid
, cr
))
307 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
309 return (priv_check_cred(cr
, PRIV_VFS_SETGID
));
313 secpolicy_vnode_setid_retain(znode_t
*zp
, cred_t
*cr
,
314 boolean_t issuidroot __unused
)
317 if (secpolicy_fs_owner(ZTOV(zp
)->v_mount
, cr
) == 0)
319 return (priv_check_cred(cr
, PRIV_VFS_RETAINSUGID
));
323 secpolicy_setid_clear(struct vattr
*vap
, vnode_t
*vp
, cred_t
*cr
)
326 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
329 if ((vap
->va_mode
& (S_ISUID
| S_ISGID
)) != 0) {
330 if (priv_check_cred(cr
, PRIV_VFS_RETAINSUGID
)) {
331 vap
->va_mask
|= AT_MODE
;
332 vap
->va_mode
&= ~(S_ISUID
|S_ISGID
);
338 secpolicy_setid_setsticky_clear(vnode_t
*vp
, struct vattr
*vap
,
339 const struct vattr
*ovap
, cred_t
*cr
)
343 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
347 * Privileged processes may set the sticky bit on non-directories,
348 * as well as set the setgid bit on a file with a group that the process
349 * is not a member of. Both of these are allowed in jail(8).
351 if (vp
->v_type
!= VDIR
&& (vap
->va_mode
& S_ISTXT
)) {
352 if (priv_check_cred(cr
, PRIV_VFS_STICKYFILE
))
356 * Check for privilege if attempting to set the
359 if ((vap
->va_mode
& S_ISGID
) != 0) {
360 error
= secpolicy_vnode_setids_setgids(vp
, cr
, ovap
->va_gid
);
365 * Deny setting setuid if we are not the file owner.
367 if ((vap
->va_mode
& S_ISUID
) && ovap
->va_uid
!= cr
->cr_uid
) {
368 error
= priv_check_cred(cr
, PRIV_VFS_ADMIN
);
376 secpolicy_fs_mount(cred_t
*cr
, vnode_t
*mvp
, struct mount
*vfsp
)
379 return (priv_check_cred(cr
, PRIV_VFS_MOUNT
));
383 secpolicy_vnode_owner(vnode_t
*vp
, cred_t
*cr
, uid_t owner
)
386 if (owner
== cr
->cr_uid
)
388 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
391 /* XXX: vfs_suser()? */
392 return (priv_check_cred(cr
, PRIV_VFS_MOUNT_OWNER
));
396 secpolicy_vnode_chown(vnode_t
*vp
, cred_t
*cr
, uid_t owner
)
399 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
401 return (priv_check_cred(cr
, PRIV_VFS_CHOWN
));
405 secpolicy_fs_mount_clearopts(cred_t
*cr
, struct mount
*vfsp
)
408 if (priv_check_cred(cr
, PRIV_VFS_MOUNT_NONUSER
) != 0) {
410 vfsp
->vfs_flag
|= VFS_NOSETUID
| MNT_USER
;
411 vfs_clearmntopt(vfsp
, MNTOPT_SETUID
);
412 vfs_setmntopt(vfsp
, MNTOPT_NOSETUID
, NULL
, 0);
418 * Check privileges for setting xvattr attributes
421 secpolicy_xvattr(vnode_t
*vp
, xvattr_t
*xvap
, uid_t owner
, cred_t
*cr
,
425 if (secpolicy_fs_owner(vp
->v_mount
, cr
) == 0)
427 return (priv_check_cred(cr
, PRIV_VFS_SYSFLAGS
));
431 secpolicy_smb(cred_t
*cr
)
434 return (priv_check_cred(cr
, PRIV_NETSMB
));