From owner-trustedbsd-cvs@FreeBSD.ORG Tue Oct 3 15:17:28 2006 Return-Path: X-Original-To: trustedbsd-cvs@freebsd.org Delivered-To: trustedbsd-cvs@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2D5B416A403 for ; Tue, 3 Oct 2006 15:17:28 +0000 (UTC) (envelope-from owner-perforce@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [209.31.154.42]) by mx1.FreeBSD.org (Postfix) with ESMTP id C720743D58 for ; Tue, 3 Oct 2006 15:17:25 +0000 (GMT) (envelope-from owner-perforce@freebsd.org) Received: from mx2.freebsd.org (mx2.freebsd.org [216.136.204.119]) by cyrus.watson.org (Postfix) with ESMTP id B29A446C6E for ; Tue, 3 Oct 2006 11:17:21 -0400 (EDT) Received: from hub.freebsd.org (hub.freebsd.org [216.136.204.18]) by mx2.freebsd.org (Postfix) with ESMTP id 8443958ED8; Tue, 3 Oct 2006 15:17:18 +0000 (GMT) (envelope-from owner-perforce@freebsd.org) Received: by hub.freebsd.org (Postfix, from userid 32767) id 7BCC416A415; Tue, 3 Oct 2006 15:17:18 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 0CFFC16A403 for ; Tue, 3 Oct 2006 15:17:18 +0000 (UTC) (envelope-from millert@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 350E543D58 for ; Tue, 3 Oct 2006 15:17:17 +0000 (GMT) (envelope-from millert@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k93FHHSb029518 for ; Tue, 3 Oct 2006 15:17:17 GMT (envelope-from millert@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k93FHHEu029515 for perforce@freebsd.org; Tue, 3 Oct 2006 15:17:17 GMT (envelope-from millert@freebsd.org) Date: Tue, 3 Oct 2006 15:17:17 GMT Message-Id: <200610031517.k93FHHEu029515@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to millert@freebsd.org using -f From: Todd Miller To: Perforce Change Reviews Cc: Subject: PERFORCE change 107187 for review X-BeenThere: trustedbsd-cvs@FreeBSD.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: TrustedBSD CVS and Perforce commit message list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 03 Oct 2006 15:17:28 -0000 http://perforce.freebsd.org/chv.cgi?CH=107187 Change 107187 by millert@millert_macbook on 2006/10/03 15:16:58 Add iokit access control driver and corresponding MAC entrypoint Panic if audit cannot be initialized Export mac_vnop_removexattr to kexts Better color policy Affected files ... .. //depot/projects/trustedbsd/sedarwin8/darwin/Makefile#3 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControl.xcode/project.pbxproj#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControlFireWire.cpp#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControlFireWire.h#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControlUSB.cpp#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControlUSB.h#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/English.lproj/InfoPlist.strings#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/Info.plist#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/Makefile#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/README#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/Makefile#1 add .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/bsd/kern/kern_audit.c#5 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/bsd/sys/vnode.h#3 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/bsd/vfs/vfs_xattr.c#5 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/config/MACFramework.exports#5 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/iokit/Kernel/IOCatalogue.cpp#2 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/iokit/Kernel/IOService.cpp#2 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/libsa/kext.cpp#2 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/conf/files#2 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac.h#8 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_base.c#13 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_policy.h#10 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_vfs_subr.c#3 edit .. //depot/projects/trustedbsd/sedarwin8/policies/Makefile#3 edit .. //depot/projects/trustedbsd/sedarwin8/policies/color/color_util.c#2 edit .. //depot/projects/trustedbsd/sedarwin8/policies/color/mac_color.c#5 edit .. //depot/projects/trustedbsd/sedarwin8/policies/color/mac_color.h#2 edit .. //depot/projects/trustedbsd/sedarwin8/policies/device_access/Makefile#1 add .. //depot/projects/trustedbsd/sedarwin8/policies/device_access/mac_device_access.c#1 add Differences ... ==== //depot/projects/trustedbsd/sedarwin8/darwin/Makefile#3 (text+ko) ==== @@ -8,6 +8,7 @@ $(MAKE) -C cctools $(MAKE) -C kext_tools $(MAKE) -C $(XNU) + $(MAKE) -C drivers $(MAKE) -C bootstrap_cmds $(MAKE) -C libmac $(MAKE) -C mac_cmds @@ -28,6 +29,7 @@ $(DESTDIR)/$(SYSTEM_PLUGINS)/ install -m 644 $(XNU)/BUILD/dst/mach_kernel $(DESTDIR)/ tar -C $(XNU)/BUILD/dst -cf - usr/include | tar -C $(DESTDIR) -xf - + $(MAKE) -C drivers DSTROOT=$(DESTDIR) install $(MAKE) -C libmac install $(MAKE) -C mac_cmds install $(MAKE) -C osx_cmds install @@ -47,6 +49,7 @@ $(MAKE) -C bootstrap_cmds clean $(MAKE) -C cctools clean $(MAKE) -C kext_tools clean + $(MAKE) -C drivers clean $(MAKE) -C libmac clean $(MAKE) -C mac_cmds clean $(MAKE) -C osx_cmds clean ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/bsd/kern/kern_audit.c#5 (text+ko) ==== @@ -671,9 +671,8 @@ * size as the system call table. */ if (nsys_au_event != nsysent) { - printf("Security auditing service initialization failed, "); - printf("audit event table doesn't match syscall table.\n"); - return; + panic("Security auditing service initialization failed, " + "audit event table doesn't match syscall table."); } printf("Security auditing service present\n"); ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/bsd/sys/vnode.h#3 (text+ko) ==== @@ -645,6 +645,8 @@ int default_setxattr(vnode_t vp, const char *name, uio_t uio, int options, vfs_context_t context); +int default_removexattr(vnode_t vp, const char *name, int options, + vfs_context_t context); __END_DECLS #endif /* KERNEL */ ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/bsd/vfs/vfs_xattr.c#5 (text+ko) ==== @@ -53,7 +53,6 @@ /* * Default xattr support routines. */ -static int default_removexattr(vnode_t vp, const char *name, int options, vfs_context_t context); static int default_listxattr(vnode_t vp, uio_t uio, size_t *size, int options, vfs_context_t context); @@ -989,7 +988,7 @@ /* * Remove an extended attribute. */ -static int +int default_removexattr(vnode_t vp, const char *name, __unused int options, vfs_context_t context) { vnode_t xvp = NULL; ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/config/MACFramework.exports#5 (text+ko) ==== @@ -5,6 +5,7 @@ _mac_vnop_getxattr _mac_vnop_setxattr +_mac_vnop_removexattr _kau_will_audit _mac_audit_text @@ -35,3 +36,8 @@ _mac_zfree _mac_find_module_data + +_mac_iokit_check_device_allowed + +# This should really go in IOKit.exports. +__Z13osdict_encodeP12OSDictionary ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/iokit/Kernel/IOCatalogue.cpp#2 (text+ko) ==== @@ -123,14 +123,12 @@ extern "C" kern_return_t kmod_release(kmod_t id); /********************************************************************* -* This function takes a plist and looks for an OSModuleData dictionary. -* If it is found, an encoded copy is returned. +* This function takes an OSDictionary and returns a struct mac_module_data +* list. *********************************************************************/ -kmod_args_t -get_module_data(OSDictionary * kextPlist, mach_msg_type_number_t * datalen) +struct mac_module_data * +osdict_encode(OSDictionary *dict) { - - OSDictionary * kextModuleData = 0; // don't release const OSMetaClass * typeID; // don't release OSString * key = NULL; // don't release OSCollectionIterator * keyIterator = 0; // must release @@ -138,16 +136,11 @@ struct mac_module_data_element * element; unsigned int strtabsize = 0; unsigned int nkeys = 0; + unsigned int datalen; char * strtab = 0; vm_offset_t data_addr; - vm_map_copy_t copy = 0; - kextModuleData = OSDynamicCast(OSDictionary, - kextPlist->getObject("OSModuleData")); - if (!kextModuleData) - goto finish; - - keyIterator = OSCollectionIterator::withCollection(kextModuleData); + keyIterator = OSCollectionIterator::withCollection(dict); if (!keyIterator) goto finish; @@ -155,7 +148,7 @@ while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) { // Get the key's value and determine its type - OSObject * value = kextModuleData->getObject(key); + OSObject * value = dict->getObject(key); if (!value) continue; @@ -183,12 +176,12 @@ /* * Allocate and fill in the module data structures. */ - *datalen = sizeof(struct mac_module_data) + + datalen = sizeof(struct mac_module_data) + sizeof(mac_module_data_element) * (nkeys - 1) + strtabsize; - if (kmem_alloc(kernel_map, &data_addr, *datalen) != KERN_SUCCESS) + if (kmem_alloc(kernel_map, &data_addr, datalen) != KERN_SUCCESS) goto finish; module_data = (mac_module_data *)data_addr; - module_data->size = *datalen; + module_data->size = datalen; module_data->count = nkeys; strtab = (char *)&module_data->data[nkeys]; @@ -197,7 +190,7 @@ while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) { // Get the key's value and determine its type - OSObject * value = kextModuleData->getObject(key); + OSObject * value = dict->getObject(key); if (!value) continue; @@ -239,18 +232,41 @@ strtab += element->key_size + element->value_size; element++; } +finish: + if (keyIterator) + keyIterator->release(); + return(module_data); +} + +/********************************************************************* +* This function takes a plist and looks for an OSModuleData dictionary. +* If it is found, an encoded copy is returned. +*********************************************************************/ +kmod_args_t +get_module_data(OSDictionary * kextPlist, mach_msg_type_number_t * datalen) +{ + + OSDictionary * kextModuleData = 0; // don't release + struct mac_module_data * module_data = 0; + vm_map_copy_t copy = 0; + kextModuleData = OSDynamicCast(OSDictionary, + kextPlist->getObject("OSModuleData")); + if (!kextModuleData) + goto finish; + + module_data = osdict_encode(kextModuleData); + if (!module_data) + goto finish; + *datalen = module_data->size; /* * Make a CoW copy of data and free the original. The copy is * consumed by a call to vm_map_copyout() in kmod_start_or_stop(). */ - vm_map_copyin(kernel_map, (vm_offset_t)data_addr, *datalen, FALSE, ©); - kmem_free(kernel_map, data_addr, *datalen); + vm_map_copyin(kernel_map, (vm_offset_t)module_data, *datalen, FALSE, ©); + kmem_free(kernel_map, (vm_offset_t)module_data, *datalen); finish: - if (keyIterator) - keyIterator->release(); - return (kmod_args_t)copy; } @@ -1427,4 +1443,3 @@ IOLockUnlock(gIOKLDLock); } - ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/iokit/Kernel/IOService.cpp#2 (text+ko) ==== @@ -2320,6 +2320,8 @@ OSObject * nextMatch = 0; bool started; bool needReloc = false; + OSBoolean * isSandbox = 0; + bool useSandbox = false; #if IOMATCHDEBUG SInt64 debugFlags; #endif @@ -2428,6 +2430,8 @@ if( !symbol) continue; + IOLog("%s alloc (symbol %p props %p)\n", symbol->getCStringNoCopy(), symbol, props); + // alloc the driver instance inst = (IOService *) OSMetaClass::allocClassWithName( symbol); @@ -2454,7 +2458,10 @@ if( 0 == category) category = gIODefaultMatchCategoryKey; inst->setProperty( gIOMatchCategoryKey, (OSObject *) category ); - + + isSandbox = OSDynamicCast(OSBoolean, + props->getObject("IOKitForceMatch")); + // attach driver instance if( !(inst->attach( this ))) continue; @@ -2471,6 +2478,19 @@ newInst = inst->probe( this, &score ); inst->detach( this ); + /* + * If this is the Sandbox driver and it matched, this is a + * disallowed device; toss any drivers that were already + * matched. + */ + if (isSandbox && isSandbox->isTrue() && newInst != 0) { + if (startDict != 0) { + startDict->flushCollection(); + startDict->release(); + startDict = 0; + } + useSandbox = true; + } if( 0 == newInst) { #if IOMATCHDEBUG if( debugFlags & kIOLogProbe) @@ -2509,6 +2529,11 @@ props->release(); if( inst) inst->release(); + /* + * If we're forcing the sandbox, drop out of the loop. + */ + if (isSandbox && isSandbox->isTrue() && useSandbox) + break; } familyMatches->release(); familyMatches = 0; ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/libsa/kext.cpp#2 (text+ko) ==== @@ -77,6 +77,8 @@ extern kmod_args_t get_module_data(OSDictionary * kextPlist, mach_msg_type_number_t * datalen); +extern struct mac_module_data *osdict_encode(OSDictionary *dict); + #define DEBUG #ifdef DEBUG #define LOG_DELAY(x) IODelay((x) * 1000000) ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/conf/files#2 (text+ko) ==== @@ -23,3 +23,4 @@ security/mac_socket.c optional mac security/mac_net.c optional mac security/mac_pipe.c optional mac +security/mac_iokit.c optional mac ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac.h#8 (text+ko) ==== @@ -67,6 +67,12 @@ typedef struct mac *mac_t; +/* + * Device types for mac_iokit_check_device_allowed() + */ +#define MAC_DEVICE_USB 0 +#define MAC_DEVICE_FIREWIRE 1 + #ifndef KERNEL /* * Location of the userland MAC framework configuration file. mac.conf @@ -107,6 +113,11 @@ int mac_set_proc(const mac_t _label); int mac_syscall(const char *_policyname, int _call, void *_arg); int mac_to_text(mac_t mac, char **_text); +/* + * I/O Kit device access control. + * Note that this routine is called from a C++ I/O Kit driver. + */ +int mac_iokit_check_device_allowed(int devtype, struct module_data *mdata); __END_DECLS #endif ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_base.c#13 (text+ko) ==== @@ -1947,15 +1947,22 @@ } int -mac_vnop_setxattr (struct vnode *vp, const char *name, char *buf, size_t len) +mac_vnop_setxattr(struct vnode *vp, const char *name, char *buf, size_t len) +{ + + return (ENOENT); +} + +int +mac_vnop_getxattr(struct vnode *vp, const char *name, char *buf, size_t len, + size_t *attrlen) { return (ENOENT); } int -mac_vnop_getxattr (struct vnode *vp, const char *name, char *buf, size_t len, - size_t *attrlen) +mac_vnop_removexattr(struct vnode *vp, const char *name) { return (ENOENT); ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_policy.h#10 (text+ko) ==== @@ -4924,8 +4924,33 @@ int error, int retval ); + +/** + @brief Device hardware access control + @param devtype Type of device connected + @param properties XML-formatted property list + @param proplen Length of the property list + + This is the MAC Framework device access control, which is called by the I/O + Kit when a new device is connected to the system to determine whether that + device should be trusted. A list of properties associated with the device + is passed as an XML-formatted string. The routine should examine these + properties to determine the trustworthiness of the device. A return value + of EPERM forces the device to be claimed by a special device driver that + will prevent its operation. + + @warning This is an experimental interface and may change in the future. + + @return Return EPERM to indicate that the device is untrusted and should + not be allowed to operate. Return zero to indicate that the device is + trusted and should be allowed to operate normally. + +*/ +typedef int mpo_iokit_check_device_allowed_t( + int devtype, + struct mac_module_data *mdata +); /*@}*/ - /*! \struct mac_policy_ops */ @@ -5232,6 +5257,7 @@ mpo_pipe_check_select_t *mpo_pipe_check_select; mpo_pipe_check_stat_t *mpo_pipe_check_stat; mpo_pipe_check_write_t *mpo_pipe_check_write; + mpo_iokit_check_device_allowed_t *mpo_iokit_check_device_allowed; }; /** @@ -5309,6 +5335,7 @@ int mac_vnop_setxattr(struct vnode *, const char *, char *, size_t); int mac_vnop_getxattr(struct vnode *, const char *, char *, size_t, size_t *); +int mac_vnop_removexattr(struct vnode *, const char *); /* * Arbitrary limit on how much data will be logged by the audit ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_vfs_subr.c#3 (text+ko) ==== @@ -124,3 +124,19 @@ return (error); } + +int +mac_vnop_removexattr (struct vnode *vp, const char *name) +{ + struct vfs_context context; + int error; + + context.vc_proc = current_proc(); + context.vc_ucred = kauth_cred_get(); + + error = VNOP_REMOVEXATTR(vp, name, 0, &context); + if (error == ENOTSUP || error == EPERM) + error = default_removexattr(vp, name, 0, &context); + + return (error); +} ==== //depot/projects/trustedbsd/sedarwin8/policies/Makefile#3 (text+ko) ==== @@ -1,5 +1,6 @@ -SUBDIR= basetest color console count fwinteg ipctrace mls none \ - readonly stacktrace stub test vanity xattr extattr_test +SUBDIR= basetest color console count device_access extattr_test \ + fwinteg ipctrace mls multilabel none readonly stacktrace \ + stub test vanity xattr SUBDIR+= sedarwin include mk/subdir.mk ==== //depot/projects/trustedbsd/sedarwin8/policies/color/color_util.c#2 (text+ko) ==== @@ -96,14 +96,13 @@ LIST_REMOVE(mc, list); free_count--; mc->refs = 0; - mc->valid = 0; } - mc->refs++; + mc->refs = 1; used_count++; mc->color = &colors[0]; LIST_INSERT_HEAD(&mc_list_used, mc, list); -// printf("mc_alloc, mc=%p, refs=%d\n", mc, mc->refs); + MCPRINTF("%s:: mc=%p, refs=%d\n", __func__, mc, mc->refs); return (mc); } @@ -114,7 +113,7 @@ if (mc == NULL) return; -// printf("mc_free, mc=%p, refs=%d\n", mc, mc->refs); + MCPRINTF("%s:: mc=%p, refs=%d\n", __func__, mc, mc->refs); LIST_REMOVE(mc, list); used_count--; @@ -146,7 +145,10 @@ if (mc == NULL) return; - if (--mc->refs <= 0) + mc->refs--; + MCPRINTF("%s:: mc=%p, refs=%d\n", __func__, mc, mc->refs); + + if (mc->refs <= 0) mc_free(mc); co_setreflabel(label, NULL); @@ -205,15 +207,17 @@ if (SLOTREF(dst) != NULL) { /* Already has a reference. */ if (SLOTREF(dst) == mc) { -// printf("co_reference_label: already has matching reference\n"); + MCPRINTF("%s:: already has matching reference\n", + __func__); return; } else { -// printf("co_reference_label: already has a reference\n"); + MCPRINTF("%s:: already has a reference\n", __func__); } co_destroy_reflabel(dst); } - printf("co_reference_label: copying reference, mc=%p, refs=%d\n", mc, mc->refs); mc->refs++; + MCPRINTF("%s:: copying reference, mc=%p, refs=%d\n", __func__, mc, + mc->refs); co_setreflabel(dst, mc); return; @@ -234,6 +238,33 @@ } +int +co_maybe_promote_process(struct ucred *subject, struct label *object) +{ + struct color *filecolor, *credcolor; + + filecolor = co_getlabel(object); + credcolor = co_getreflabel(subject->cr_label)->color; + + /* + * If the file doesn't have a label or they are the same + */ + if ((filecolor == NULL) || (filecolor == credcolor)) + return (0); + + MCPRINTF("%s:: checking file label %s(%d) with cred %s(%d)\n", + __func__, filecolor->name, filecolor->level, + credcolor->name, credcolor->level); + + if (filecolor->level > credcolor->level) { + printf("%s:: promoting label from %s to %s\n", + __func__, credcolor->name, filecolor->name); + co_getreflabel(subject->cr_label)->color = filecolor; + } + + return (0); +} + void color_policy_init(struct mac_policy_conf *conf) { ==== //depot/projects/trustedbsd/sedarwin8/policies/color/mac_color.c#5 (text+ko) ==== @@ -24,6 +24,28 @@ * SUCH DAMAGE. */ +/* + * The MAC Color policy. + * + * This policy demonstrates the potential of using login context + * labels to share privilege amongst a group of processes. It also + * demonstrates the use of floating labels. + * + * The policy has a small number of "rules": + * 1) All processes have a color. Files may optionally have a color. + * 2) Colors are ranked low to high by their position in the + * spectrum (red to violet). + * 3) A subject takes on the color of the highest object it is accessing. + * 4) Objects created by a subject will have the higher of the color + * of the subject at the time of creation or the enclosing directory. + * 5) Objects created will only have a label if the parent directory + * has a label. + * + * Note that this is an example policy, not all entry points are + * imlemented and not all subject access considered. + */ + + #include #include #include @@ -33,6 +55,7 @@ #include #include #include +#include /* struct vfs_context */ #include #include #include @@ -46,7 +69,7 @@ static const char *labelnamespaces[MAC_COLOR_LABEL_COUNT] = { MAC_COLOR_POLICY_NAME }; -static int color_slot; /* Per-policy label storage */ +int color_slot; /* Per-policy label storage */ static mac_policy_handle_t mac_color_handle; @@ -77,7 +100,13 @@ { struct color *color; + if (strncmp(string, "unlabeled", 9) == 0) { + co_setreflabel(label, NULL); + return (0); + } + co_setlabelstring(label, string); + color = co_getlabel(label); if (color == NULL) { printf("%s: No matching color for %s\n", __func__, string); @@ -126,7 +155,6 @@ color_cred_create(struct ucred *parent_cred, struct ucred *child_cred) { -// co_copylabel(parent_cred->cr_label, child_cred->cr_label); co_reference_label(parent_cred->cr_label, child_cred->cr_label); } @@ -134,38 +162,52 @@ color_create_kernel_proc(struct ucred *cred) { - //co_setlabel(cred->cr_label, &colors[0]); + /* Nothing to do here */ } -/* ================================================================= * - * login context entry points - * ================================================================= */ +static int +color_cred_check_setlabel(struct ucred *cred, struct label *newlabel) +{ -#if 0 -static void -color_lctx_init_label(struct label *label) -{ + return (EPERM); } -static void -color_lctx_destroy_label(struct label *label) +static int +color_proc_check_signal(struct ucred *cred, struct proc *proc, int signum) { + + struct color *subjectcolor, *objectcolor; + + subjectcolor = co_getreflabel(cred->cr_label)->color; + objectcolor = co_getreflabel(proc_ucred(proc)->cr_label)->color; + + if (objectcolor->level > subjectcolor->level) { + printf("%s:: promoting label from %s to %s\n", + __func__, subjectcolor->name, objectcolor->name); + co_getreflabel(cred->cr_label)->color = objectcolor; + } + + return (0); } -#endif + +/* ================================================================= * + * login context entry points + * ================================================================= */ static void color_proc_create_lctx(struct proc *p, struct lctx *l) { -// co_copylabel(proc_ucred(p)->cr_label, l->lc_label); -// co_reference_label(proc_ucred(p)->cr_label, l->lc_label); - printf("create_lctx:: process(%s) color %s(%d) creating lctx (which was color %s(%d))\n", - p->p_comm, - co_getreflabel(proc_ucred(p)->cr_label)->color->name, - co_getreflabel(proc_ucred(p)->cr_label)->refs, - co_getreflabel(l->lc_label)->color->name, - co_getreflabel(l->lc_label)->refs); - co_getreflabel(l->lc_label)->color = co_getreflabel(proc_ucred(p)->cr_label)->color; + printf("%s: process(%s) color %s(%d) create lctx (was color %s(%d))\n", + __func__, p->p_comm, + co_getreflabel(proc_ucred(p)->cr_label)->color->name, + co_getreflabel(proc_ucred(p)->cr_label)->refs, + co_getreflabel(l->lc_label)->color->name, + co_getreflabel(l->lc_label)->refs); + + /* copy process label to lctx */ + co_getreflabel(l->lc_label)->color = + co_getreflabel(proc_ucred(p)->cr_label)->color; } static void @@ -173,37 +215,56 @@ { co_reference_label(l->lc_label, proc_ucred(p)->cr_label); - printf("join_lctx:: process(%s) color %s to join lctx color %s\n", - p->p_comm, - co_getreflabel(p->p_ucred->cr_label)->color->name, - co_getreflabel(l->lc_label)->color->name); + MCPRINTF("%s:: process(%s) pid(%d) '%s' to join lctx '%s'\n", + __func__, p->p_comm, p->p_pid, + co_getreflabel(p->p_ucred->cr_label)->color->name, + co_getreflabel(l->lc_label)->color->name); } static void color_proc_leave_lctx(struct proc *p, struct lctx *l) { - printf("leave_lctx:: process(%s) color %s to join lctx color %s\n", - p->p_comm, - co_getreflabel(p->p_ucred->cr_label)->color->name, - co_getreflabel(l->lc_label)->color->name); + MCPRINTF("%s:: process(%s) pid(%d) '%s' to leave lctx '%s'\n", + __func__, p->p_comm, p->p_pid, + co_getreflabel(p->p_ucred->cr_label)->color->name, + co_getreflabel(l->lc_label)->color->name); } static void color_lctx_setlabel(struct lctx *l, struct label *newlabel) { - printf("lctx_setlabel:: newlabel color %s for lctx color %s\n", - co_getreflabel(newlabel)->color->name, - co_getreflabel(l->lc_label)->color->name); + printf("%s:: newlabel color %s for lctx color %s\n", + __func__, co_getreflabel(newlabel)->color->name, + co_getreflabel(l->lc_label)->color->name); } /* ================================================================= * * vnode entry points * ================================================================= */ +static void +color_mount_create(struct ucred *cred, struct mount *mp, + struct label *mntlabel) +{ + struct color *credcolor; + + credcolor = co_getreflabel(cred->cr_label)->color; + co_setlabel(mntlabel, credcolor); +} + static int -color_vnode_associate_extattr(struct mount *mp, struct label *fslabel, +color_mount_check_setlabel(struct ucred *cred, struct mount *mp, + struct label *mntlabel) +{ + + return (EPERM); +} + + +static int +color_vnode_associate_extattr(struct mount *mp, struct label *mntlabel, struct vnode *vp, struct label *vlabel) { int error; @@ -214,6 +275,7 @@ error = mac_vnop_getxattr(vp, MAC_COLOR_XATTR_NAME, buf, sizeof(buf), &buflen); + /* If there's no attribute, the label is NULL */ if (error == ENOATTR || error == EOPNOTSUPP) return (0); @@ -227,11 +289,20 @@ } static void -color_vnode_associate_singlelabel(struct mount *mp, struct label *fslabel, +color_devfs_vnode_associate(struct mount *mp, struct label *mntlabel, + struct devnode *de, struct label *delabel, struct vnode *vp, + struct label *vlabel) +{ + + co_copylabel(mntlabel, vlabel); +} + +static void +color_vnode_associate_singlelabel(struct mount *mp, struct label *mntlabel, struct vnode *vp, struct label *vlabel) { - co_setlabel(vlabel, NULL); + co_copylabel(mntlabel, vlabel); } static void @@ -251,30 +322,39 @@ static int color_vnode_create_extattr(struct ucred *cred, struct mount *mp, - struct label *fslabel, struct vnode *dvp, struct label *dlabel, + struct label *mntlabel, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *vlabel, struct componentname *cnp) { - int error; - struct color *color; + int error = 0; + struct color *dircolor, *credcolor, *newcolor; - /* For now, just inherit the parent directory label */ - color = co_getlabel(dlabel); - if (color == NULL) - return (0); + dircolor = co_getlabel(dlabel); + credcolor = co_getreflabel(cred->cr_label)->color; - error = mac_vnop_setxattr(vp, MAC_COLOR_XATTR_NAME, - color->name, sizeof(color->name)); + /* + * Process credentials always have labels, but files may not. + * If the parent directory has no label, the new file will have + * no label. Otherwise, the new file gets the higher of the + * parent label or the process label. + */ + if ((dircolor == NULL) || (dircolor->level > credcolor->level)) + newcolor = dircolor; + else + newcolor = credcolor; - if (error) - co_setlabel(vlabel, NULL); - else - co_copylabel(dlabel, vlabel); + co_setlabel(vlabel, newcolor); + if (newcolor != NULL) { + error = mac_vnop_setxattr(vp, MAC_COLOR_XATTR_NAME, + newcolor->name, sizeof(newcolor->name)); + if (error) + printf("%s:: Couldn't set file label \n", __func__); + } return (error); } static void -color_vnode_update_extattr(struct mount *mp, struct label *fslabel, +color_vnode_update_extattr(struct mount *mp, struct label *mntlabel, struct vnode *vp, struct label *vlabel, char *name) { int error; @@ -285,6 +365,7 @@ error = mac_vnop_getxattr(vp, MAC_COLOR_XATTR_NAME, buf, sizeof(buf), &buflen); + /* It's ok to have a NULL file label */ if (error) return; @@ -300,10 +381,11 @@ { int error; struct color *color; + struct vfs_context context; color = co_getlabel(intlabel); if (color == NULL) - return (0); + return (mac_vnop_removexattr(vp, MAC_COLOR_XATTR_NAME)); error = mac_vnop_setxattr(vp, MAC_COLOR_XATTR_NAME, color->name, sizeof(color->name)); @@ -312,90 +394,357 @@ } static int +color_vnode_check_access(struct ucred *cred, struct vnode *vp, + struct label *label, int acc_mode) +{ + + return (co_maybe_promote_process(cred, label)); +} + +static int +color_vnode_check_chdir(struct ucred *cred, struct vnode *dvp, + struct label *label) +{ + + return (co_maybe_promote_process(cred, label)); +} + +static int +color_vnode_check_chroot(struct ucred *cred, struct vnode *dvp, + struct label *label) +{ + + return (co_maybe_promote_process(cred, label)); +} + +static int +color_vnode_check_create(struct ucred *cred, struct vnode *dvp, + struct label *label, struct componentname *cnp, struct vnode_attr *vap) +{ + + return (co_maybe_promote_process(cred, label)); +} + +static int +color_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, + struct label *dlabel, struct vnode *vp, struct label *label, + struct componentname *cnp) +{ + + (void)co_maybe_promote_process(cred, dlabel); + return (co_maybe_promote_process(cred, label)); +} + +static int +color_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp, + struct label *label, const char *name) +{ + + return (co_maybe_promote_process(cred, label)); +} + +static int + +color_vnode_check_exchangedata(struct ucred *cred, struct vnode *v1, + struct label *vl1, struct vnode *v2, struct label *vl2) +{ + + (void)co_maybe_promote_process(cred, vl1); + return (co_maybe_promote_process(cred, vl2)); +} + +static int +color_vnode_check_exec(struct ucred *cred, struct vnode *vp, + struct label *label, struct label *execlabel) +{ + + if (execlabel != NULL) + (void)co_maybe_promote_process(cred, execlabel); + return (co_maybe_promote_process(cred, label)); +} + +static int +color_vnode_check_getattrlist(struct ucred *cred, struct vnode *vp, + struct label *label, struct attrlist *alist) +{ + + return (co_maybe_promote_process(cred, label)); +} + +static int +color_vnode_check_getextattr(struct ucred *cred, struct vnode *vp, + struct label *label, const char *name, struct uio *uio) +{ + + return (co_maybe_promote_process(cred, label)); +} + +static int +color_vnode_check_kqfilter(struct ucred *cred, struct ucred *file_cred, + struct knote *kn, struct vnode *vp, struct label *label) +{ >>> TRUNCATED FOR MAIL (1000 lines) <<<