Date: Tue, 14 Nov 2006 18:38:57 GMT From: Todd Miller <millert@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 109953 for review Message-ID: <200611141838.kAEIcveY008673@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=109953 Change 109953 by millert@millert_g5tower on 2006/11/14 18:38:53 Move mmap checks from vnode to file. Add file_has_perm to sebsd.c that checks both the fd label and the underlying vnode label, similar to what SELinux does. Affected files ... .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/bsd/kern/kern_mman.c#4 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_file.c#5 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_framework.h#12 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_policy.h#20 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_vfs.c#15 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/sorted-policynames.vim#2 edit .. //depot/projects/trustedbsd/sedarwin8/policies/color/mac_color.c#10 edit .. //depot/projects/trustedbsd/sedarwin8/policies/mls/mac_mls.c#18 edit .. //depot/projects/trustedbsd/sedarwin8/policies/readonly/mac_readonly.c#7 edit .. //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/sebsd.c#34 edit .. //depot/projects/trustedbsd/sedarwin8/policies/vanity/vanity.c#7 edit Differences ... ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/bsd/kern/kern_mman.c#4 (text+ko) ==== @@ -373,8 +373,8 @@ handle = (void *)vp; #ifdef MAC - error = mac_vnode_check_mmap(vfs_context_ucred(&context), - vp, prot, flags, &maxprot); + error = mac_file_check_mmap(vfs_context_ucred(&context), + fp->f_fglob, prot, flags, &maxprot); if (error) { (void)vnode_put(vp); goto bad; ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_file.c#5 (text+ko) ==== @@ -221,3 +221,39 @@ MAC_CHECK(file_check_set, cred, fg, buf, buflen); return (error); } + +/* + * On some platforms, VM_PROT_READ implies VM_PROT_EXECUTE. If that is true, + * both prot and maxprot will have VM_PROT_EXECUTE set after file_check_mmap + * if VM_PROT_READ is set. + * + * The type of maxprot in file_check_mmap must be equivalent to vm_prot_t * + * (defined in <mach/vm_prot.h>). mac_policy.h does not include any header + * files, so cannot use the typedef itself. + */ +int +mac_file_check_mmap(struct ucred *cred, struct fileglob *fg, int prot, + int flags, int *maxprot) +{ + int error; + int maxp; + + maxp = *maxprot; + MAC_CHECK(file_check_mmap, cred, fg, fg->fg_label, prot, flags, &maxp); + if ((maxp | *maxprot) != *maxprot) + panic("file_check_mmap increased max protections"); + *maxprot = maxp; + return (error); +} + +void +mac_file_check_mmap_downgrade(struct ucred *cred, struct fileglob *fg, + int *prot) +{ + int result = *prot; + + MAC_PERFORM(file_check_mmap_downgrade, cred, fg, fg->fg_label, + &result); + + *prot = result; +} ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_framework.h#12 (text+ko) ==== @@ -310,6 +310,10 @@ struct fileglob *fg, char oldflags, char newflags); int mac_file_check_get_offset(struct ucred *cred, struct fileglob *fg); int mac_file_check_change_offset(struct ucred *cred, struct fileglob *fg); +int mac_file_check_mmap(struct ucred *cred, struct fileglob *fg, + int prot, int flags, int *maxprot); +void mac_file_check_mmap_downgrade(struct ucred *cred, struct fileglob *fg, + int *prot); int mac_file_check_set(struct ucred *cred, struct fileglob *fg, char *buf, int buflen); int mac_sysvsem_check_semget(struct ucred *cred, @@ -407,10 +411,6 @@ int mac_vnode_check_listextattr(struct ucred *cred, struct vnode *vp); int mac_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, struct componentname *cnp); -int mac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, - int prot, int flags, int *maxprot); -void mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, - int *prot); int mac_vnode_check_mprotect(struct ucred *cred, struct vnode *vp, int prot); int mac_vnode_check_open(struct ucred *cred, struct vnode *vp, ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_policy.h#20 (text+ko) ==== @@ -3901,6 +3901,51 @@ ); /** + @brief Access control check for mapping a file + @param cred Subject credential + @param fg fileglob representing file to map + @param label Policy label associated with vp + @param prot mmap protections; see mmap(2) + @param flags Type of mapped object; see mmap(2) + @param maxprot Maximum rights + + Determine whether the subject identified by the credential should be + allowed to map the file represented by fg with the protections specified + in prot. The maxprot field holds the maximum permissions on the new + mapping, a combination of VM_PROT_READ, VM_PROT_WRITE, and VM_PROT_EXECUTE. + To avoid overriding prior access control checks, a policy should only + remove flags from maxprot. + + @return Return 0 if access is granted, otherwise an appropriate value for + errno should be returned. Suggested failure: EACCES for label mismatch or + EPERM for lack of privilege. +*/ +typedef int mpo_file_check_mmap_t( + struct ucred *cred, + struct fileglob *fg, + struct label *label, + int prot, + int flags, + int *maxprot +); + +/** + @brief Downgrade the mmap protections + @param cred Subject credential + @param fg file to map + @param label Policy label associated with vp + @param prot mmap protections to be downgraded + + Downgrade the mmap protections based on the subject and object labels. +*/ +typedef void mpo_file_check_mmap_downgrade_t( + struct ucred *cred, + struct fileglob *fg, + struct label *label, + int *prot +); + +/** @brief Access control for changing the offset of a file descriptor @param cred Subject credential @param fg Fileglob structure @@ -4634,51 +4679,6 @@ ); /** - @brief Access control check for mapping the vnode - @param cred Subject credential - @param vp vnode to map - @param label Policy label associated with vp - @param prot mmap protections; see mmap(2) - @param flags Type of mapped object; see mmap(2) - @param maxprot Maximum rights - - Determine whether the subject identified by the credential should be - allowed to map the vnode vp with the protections specified in prot. - The maxprot field holds the maximum permissions on the new mapping, - a combination of VM_PROT_READ, VM_PROT_WRITE, and VM_PROT_EXECUTE. - To avoid overriding prior access control checks, a policy should only - remove flags from maxprot. - - @return Return 0 if access is granted, otherwise an appropriate value for - errno should be returned. Suggested failure: EACCES for label mismatch or - EPERM for lack of privilege. -*/ -typedef int mpo_vnode_check_mmap_t( - struct ucred *cred, - struct vnode *vp, - struct label *label, - int prot, - int flags, - int *maxprot -); - -/** - @brief Downgrade the mmap protections - @param cred Subject credential - @param vp vnode to map - @param label Policy label associated with vp - @param prot mmap protections to be downgraded - - Downgrade the mmap protections based on the subject and object labels. -*/ -typedef void mpo_vnode_check_mmap_downgrade_t( - struct ucred *cred, - struct vnode *vp, - struct label *label, - int *prot -); - -/** @brief Access control check for setting memory protections @param cred Subject credential @param vp Mapped vnode @@ -5529,10 +5529,12 @@ mpo_file_check_get_flags_t *mpo_file_check_get_flags; mpo_file_check_get_offset_t *mpo_file_check_get_offset; mpo_file_check_get_ofileflags_t *mpo_file_check_get_ofileflags; + mpo_file_check_get_t *mpo_file_check_get; mpo_file_check_inherit_t *mpo_file_check_inherit; mpo_file_check_ioctl_t *mpo_file_check_ioctl; + mpo_file_check_mmap_downgrade_t *mpo_file_check_mmap_downgrade; + mpo_file_check_mmap_t *mpo_file_check_mmap; mpo_file_check_receive_t *mpo_file_check_receive; - mpo_file_check_get_t *mpo_file_check_get; mpo_file_check_set_t *mpo_file_check_set; mpo_port_check_method_t *mpo_port_check_method; mpo_posixsem_check_create_t *mpo_posixsem_check_create; @@ -5613,8 +5615,6 @@ mpo_vnode_check_link_t *mpo_vnode_check_link; mpo_vnode_check_listextattr_t *mpo_vnode_check_listextattr; mpo_vnode_check_lookup_t *mpo_vnode_check_lookup; - mpo_vnode_check_mmap_t *mpo_vnode_check_mmap; - mpo_vnode_check_mmap_downgrade_t *mpo_vnode_check_mmap_downgrade; mpo_vnode_check_mprotect_t *mpo_vnode_check_mprotect; mpo_vnode_check_open_t *mpo_vnode_check_open; mpo_vnode_check_read_t *mpo_vnode_check_read; ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_vfs.c#15 (text+ko) ==== @@ -513,42 +513,6 @@ return (error); } -/* - * On some platforms, VM_PROT_READ implies VM_PROT_EXECUTE. If that is true, - * both prot and maxprot will have VM_PROT_EXECUTE set after vnode_check_mmap - * if VM_PROT_READ is set. - * - * The type of maxprot in vnode_check_mmap must be equivalent to vm_prot_t * - * (defined in <mach/vm_prot.h>). mac_policy.h does not include any header files, - * so cannot use the typedef itself. - */ - -int -mac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, int prot, int flags, - int *maxprot) -{ - int error; - int maxp; - - maxp = *maxprot; - MAC_CHECK(vnode_check_mmap, cred, vp, vp->v_label, prot, flags, &maxp); - if ((maxp | *maxprot) != *maxprot) - panic("vnode_check_mmap increased max protections"); - *maxprot = maxp; - return (error); -} - -void -mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot) -{ - int result = *prot; - - MAC_PERFORM(vnode_check_mmap_downgrade, cred, vp, vp->v_label, - &result); - - *prot = result; -} - int mac_vnode_check_mprotect(struct ucred *cred, struct vnode *vp, int prot) { ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/sorted-policynames.vim#2 (text+ko) ==== @@ -25,6 +25,8 @@ typedef mpo_devfs_label_update_t( typedef mpo_file_check_fcntl_t( typedef mpo_file_check_get_t( +typedef mpo_file_check_mmap_downgrade_t( +typedef mpo_file_check_mmap_t( typedef mpo_file_check_set_t( typedef mpo_iokit_check_device_t( typedef mpo_lctx_check_label_update_t( @@ -210,8 +212,6 @@ typedef mpo_vnode_check_link_t( typedef mpo_vnode_check_listextattr_t( typedef mpo_vnode_check_lookup_t( -typedef mpo_vnode_check_mmap_downgrade_t( -typedef mpo_vnode_check_mmap_t( typedef mpo_vnode_check_mprotect_t( typedef mpo_vnode_check_open_t( typedef mpo_vnode_check_read_t( ==== //depot/projects/trustedbsd/sedarwin8/policies/color/mac_color.c#10 (text+ko) ==== @@ -502,7 +502,7 @@ } static int -color_vnode_check_mmap(struct ucred *cred, struct vnode *vp, +color_file_check_mmap(struct ucred *cred, struct fileglob *fg, struct label *label, int prot, int flags, int *maxprot) { @@ -510,7 +510,7 @@ } static void -color_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, +color_file_check_mmap_downgrade(struct ucred *cred, struct fileglob *fg, struct label *label, int *prot) { @@ -701,6 +701,9 @@ .mpo_cred_check_label_update = color_cred_check_label_update, + .mpo_file_check_mmap = color_file_check_mmap, + .mpo_file_check_mmap_downgrade = color_file_check_mmap_downgrade, + .mpo_lctx_notify_create = color_lctx_notify_create, .mpo_lctx_notify_join = color_lctx_notify_join, .mpo_lctx_notify_leave = color_lctx_notify_leave, @@ -721,8 +724,6 @@ .mpo_vnode_check_link = color_vnode_check_link, .mpo_vnode_check_listextattr = color_vnode_check_listextattr, .mpo_vnode_check_lookup = color_vnode_check_lookup, - .mpo_vnode_check_mmap = color_vnode_check_mmap, - .mpo_vnode_check_mmap_downgrade = color_vnode_check_mmap_downgrade, .mpo_vnode_check_mprotect = color_vnode_check_mprotect, .mpo_vnode_check_open = color_vnode_check_open, .mpo_vnode_check_read = color_vnode_check_read, ==== //depot/projects/trustedbsd/sedarwin8/policies/mls/mac_mls.c#18 (text+ko) ==== @@ -3444,7 +3444,7 @@ } static int -mac_mls_vnode_check_mmap(struct ucred *cred, struct vnode *vp, +mac_mls_file_check_mmap(struct ucred *cred, struct fileglob *fg, struct label *label, int prot, int flags, int *maxprot) { struct mac_mls *subj, *obj; @@ -3487,13 +3487,13 @@ * combination of what each policy thinks it should be. */ static void -mac_mls_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, +mac_mls_file_check_mmap_downgrade(struct ucred *cred, struct fileglob *fg, struct label *vlabel, int *prot) { if (!mac_mls_enabled) return; -#warning Implement mac_mls_vnode_check_mmap_downgrade() +#warning Implement mac_mls_file_check_mmap_downgrade() return; } @@ -4088,8 +4088,8 @@ .mpo_vnode_check_link = mac_mls_vnode_check_link, .mpo_vnode_check_listextattr = mac_mls_vnode_check_listextattr, .mpo_vnode_check_lookup = mac_mls_vnode_check_lookup, - .mpo_vnode_check_mmap = mac_mls_vnode_check_mmap, - .mpo_vnode_check_mmap_downgrade = mac_mls_vnode_check_mmap_downgrade, + .mpo_file_check_mmap = mac_mls_file_check_mmap, + .mpo_file_check_mmap_downgrade = mac_mls_file_check_mmap_downgrade, .mpo_vnode_check_mprotect = mac_mls_vnode_check_mprotect, .mpo_vnode_check_open = mac_mls_vnode_check_open, .mpo_vnode_check_read = mac_mls_vnode_check_read, ==== //depot/projects/trustedbsd/sedarwin8/policies/readonly/mac_readonly.c#7 (text+ko) ==== @@ -1,6 +1,8 @@ #include <sys/types.h> #include <sys/conf.h> #include <sys/kernel.h> +#include <sys/file.h> +#include <sys/file_internal.h> #include <sys/malloc.h> #include <sys/mman.h> #include <sys/mount.h> @@ -420,11 +422,14 @@ } static int -readonly_vnode_check_mmap(struct ucred *cred, struct vnode *vp, +readonly_file_check_mmap(struct ucred *cred, struct fileglob *fg, struct label *label, int prot, int flags, int *maxprot) { - return (ro_checkdiraccess(vp, label, (prot & PROT_WRITE) ? FWRITE : FREAD)); + if (fg->fg_type != DTYPE_VNODE) + return (0); + return (ro_checkdiraccess((struct vnode *)fg->fg_data, label, + (prot & PROT_WRITE) ? FWRITE : FREAD)); } static int @@ -502,6 +507,7 @@ .mpo_policy_destroy = readonly_policy_destroy, .mpo_policy_init = readonly_policy_init, .mpo_policy_initbsd = readonly_policy_initbsd, + .mpo_file_check_mmap = readonly_file_check_mmap, .mpo_vnode_label_init = readonly_label_init, .mpo_vnode_label_destroy = readonly_label_destroy, .mpo_vnode_label_recycle = readonly_label_recycle, @@ -520,7 +526,6 @@ .mpo_vnode_check_deleteextattr = readonly_vnode_check_deleteextattr, .mpo_vnode_check_exchangedata = readonly_vnode_check_exchangedata, .mpo_vnode_check_link = readonly_vnode_check_link, - .mpo_vnode_check_mmap = readonly_vnode_check_mmap, .mpo_vnode_check_open = readonly_vnode_check_open, .mpo_vnode_check_label_update = readonly_vnode_check_label_update, .mpo_vnode_check_rename_from = readonly_vnode_check_rename_from, ==== //depot/projects/trustedbsd/sedarwin8/policies/sedarwin/sedarwin/sebsd.c#34 (text+ko) ==== @@ -467,6 +467,34 @@ } static int +file_has_perm(struct ucred *cred, struct fileglob *fg, struct label *fglabel, + u_int32_t perm) +{ + struct task_security_struct *tsec; + struct file_security_struct *fsec; + int rc = 0; + + tsec = SLOT(cred->cr_label); + fsec = SLOT(fglabel); + + /* Simple use check if file opened by other sid. */ + if (tsec->sid != fsec->sid) { + rc = avc_has_perm(tsec->sid, fsec->sid, SECCLASS_FD, FD__USE, + NULL); + if (rc != 0) + return (rc); + } + + /* Check underlying vnode if there is one. */ + if (fg->fg_type == DTYPE_VNODE && fg->fg_data != NULL) { + rc = vnode_has_perm(cred, (struct vnode *)fg->fg_data, + NULL, perm); + } + + return (rc); +} + +static int pipe_has_perm(struct ucred *cred, struct pipe *pipe, u_int32_t perm) { struct task_security_struct *task; @@ -2891,8 +2919,8 @@ } static int -sebsd_vnode_check_mmap(struct ucred *cred, struct vnode *vp, - struct label *label, int prot, int flags, int *maxprot) +sebsd_file_check_mmap(struct ucred *cred, struct fileglob *fg, + struct label *fglabel, int prot, int flags, int *maxprot) { u_int32_t av; @@ -2900,18 +2928,15 @@ * TBD: Incomplete? * Write access only matters if the mapping is shared. */ - if (vp) { - av = FILE__READ; + av = FILE__READ; - if ((prot & PROT_WRITE) && (flags & MAP_SHARED)) - av |= FILE__WRITE; + if ((prot & PROT_WRITE) && (flags & MAP_SHARED)) + av |= FILE__WRITE; - if (prot & PROT_EXEC) - av |= FILE__EXECUTE; + if (prot & PROT_EXEC) + av |= FILE__EXECUTE; - return (vnode_has_perm(cred, vp, NULL, av)); - } - return (0); + return (file_has_perm(cred, fg, fglabel, av)); } static int @@ -3653,7 +3678,6 @@ // .mpo_vnode_check_kqfilter = sebsd_vnode_check_kqfilter, .mpo_vnode_check_link = sebsd_vnode_check_link, .mpo_vnode_check_lookup = sebsd_vnode_check_lookup, - .mpo_vnode_check_mmap = sebsd_vnode_check_mmap, .mpo_vnode_check_mprotect = sebsd_vnode_check_mprotect, .mpo_vnode_check_open = sebsd_vnode_check_open, .mpo_vnode_check_read = sebsd_vnode_check_read, @@ -3701,6 +3725,7 @@ .mpo_file_check_inherit = sebsd_file_check_receive, .mpo_file_check_receive = sebsd_file_check_receive, .mpo_file_check_dup = sebsd_file_check_dup, + .mpo_file_check_mmap = sebsd_file_check_mmap, /* Mount Points */ .mpo_mount_label_init = sebsd_mount_label_init, ==== //depot/projects/trustedbsd/sedarwin8/policies/vanity/vanity.c#7 (text+ko) ==== @@ -4,6 +4,7 @@ #include <sys/sysctl.h> #include <sys/proc.h> +#include <sys/file_internal.h> #include <sys/mount_internal.h> #include <sys/vnode_internal.h> @@ -315,16 +316,20 @@ } static int -vanity_vnode_check_mmap(struct ucred *cred, struct vnode *vp, struct label *label, int prot, int flags, int *maxprot) +vanity_file_check_mmap(struct ucred *cred, struct fileglob *fg, + struct label *label, int prot, int flags, int *maxprot) { - VANITY(vp); + if (fg->fg_type == DTYPE_VNODE) + VANITY((struct vnode *)fg->fg_data); return (0); } static void -vanity_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, struct label *label, int *prot) +vanity_file_check_mmap_downgrade(struct ucred *cred, struct fileglob *fg, + struct label *label, int *prot) { - VANITY(vp); + if (fg->fg_type == DTYPE_VNODE) + VANITY((struct vnode *)fg->fg_data); } static int @@ -473,6 +478,8 @@ static struct mac_policy_ops mac_vanity_ops = { .mpo_policy_initbsd = vanity_policy_initbsd, + .mpo_file_check_mmap = vanity_file_check_mmap, + .mpo_file_check_mmap_downgrade = vanity_file_check_mmap_downgrade, .mpo_vnode_label_update_extattr = vanity_vnode_label_update_extattr, .mpo_vnode_label_associate_devfs= vanity_vnode_label_associate_devfs, .mpo_vnode_label_associate_extattr= vanity_vnode_label_associate_extattr, @@ -501,8 +508,6 @@ .mpo_vnode_check_link = vanity_vnode_check_link, .mpo_vnode_check_listextattr = vanity_vnode_check_listextattr, .mpo_vnode_check_lookup = vanity_vnode_check_lookup, - .mpo_vnode_check_mmap = vanity_vnode_check_mmap, - .mpo_vnode_check_mmap_downgrade = vanity_vnode_check_mmap_downgrade, .mpo_vnode_check_mprotect = vanity_vnode_check_mprotect, .mpo_vnode_check_open = vanity_vnode_check_open, .mpo_vnode_check_read = vanity_vnode_check_read,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611141838.kAEIcveY008673>