From owner-p4-projects@FreeBSD.ORG Mon Dec 4 18:05:40 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 1B3FF16A47C; Mon, 4 Dec 2006 18:05:40 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id B3EF016A407 for ; Mon, 4 Dec 2006 18:05:39 +0000 (UTC) (envelope-from millert@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.FreeBSD.org (Postfix) with ESMTP id 6920D43CA3 for ; Mon, 4 Dec 2006 18:05:05 +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 kB4I5dsD084457 for ; Mon, 4 Dec 2006 18:05:39 GMT (envelope-from millert@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id kB4I5dTd084454 for perforce@freebsd.org; Mon, 4 Dec 2006 18:05:39 GMT (envelope-from millert@freebsd.org) Date: Mon, 4 Dec 2006 18:05:39 GMT Message-Id: <200612041805.kB4I5dTd084454@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 111036 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Dec 2006 18:05:40 -0000 http://perforce.freebsd.org/chv.cgi?CH=111036 Change 111036 by millert@millert_macbook on 2006/12/04 18:04:51 Integrate Device Access Control changes. Support Array/Dictionary in OSModuleData. Move 'device_access' policy configuration to Info.plist. Affected files ... .. //depot/projects/trustedbsd/sedarwin8/darwin/build/mkPolicyInfoPlist.sh#3 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControlFireWire.h#3 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControlUSB.h#3 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/iokit/Kernel/IOCatalogue.cpp#4 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac.h#10 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_base.c#23 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_data.h#4 edit .. //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_iokit.c#2 edit .. //depot/projects/trustedbsd/sedarwin8/policies/device_access/mac_device_access.c#5 edit Differences ... ==== //depot/projects/trustedbsd/sedarwin8/darwin/build/mkPolicyInfoPlist.sh#3 (xtext) ==== @@ -28,6 +28,13 @@ OSBundleCompatibleVersion ${POLICY_COMPVER} +__EOF__ + +if [ -f Default.plist ] ; then + cat Default.plist +fi + +cat << __EOF__ OSBundleLibraries __EOF__ ==== //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControlFireWire.h#3 (text+ko) ==== @@ -52,7 +52,7 @@ extern "C" vm_map_t kernel_map; extern "C" void kmem_free(vm_map_t map, vm_offset_t addr, vm_size_t size); -extern "C" int mac_iokit_check_device(int, struct mac_module_data *); +extern "C" int mac_iokit_check_device(char *, struct mac_module_data *); // Uncomment to enable debug output #define DEVICEACCESSCONTROL_DEBUG 1 ==== //depot/projects/trustedbsd/sedarwin8/darwin/drivers/DeviceAccessControl/DeviceAccessControlUSB.h#3 (text+ko) ==== @@ -51,7 +51,7 @@ extern "C" vm_map_t kernel_map; extern "C" void kmem_free(vm_map_t map, vm_offset_t addr, vm_size_t size); -extern "C" int mac_iokit_check_device(int, struct mac_module_data *); +extern "C" int mac_iokit_check_device(char *, struct mac_module_data *); // Uncomment to enable debug output #define DEVICEACCESSCONTROL_DEBUG 1 ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/iokit/Kernel/IOCatalogue.cpp#4 (text+ko) ==== @@ -57,6 +57,17 @@ #include +/* + * define IOC_DEBUG to display run-time debugging information + * #define IOC_DEBUG 1 + */ + +#ifdef IOC_DEBUG +#define DPRINTF(x) printf x +#else +#define IOC_DEBUG +#define DPRINTF(x) +#endif extern "C" { int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize ); @@ -130,6 +141,86 @@ extern "C" kern_return_t kmod_retain(kmod_t id); extern "C" kern_return_t kmod_release(kmod_t id); +static bool +primitive_type(OSObject *obj) +{ + const OSMetaClass *typeID; + + typeID = OSTypeIDInst(obj); + if (typeID == OSTypeID(OSString) || typeID == OSTypeID(OSNumber) || + typeID == OSTypeID(OSBoolean) || typeID == OSTypeID(OSData)) + return(true); + else + return(false); +} + +static int +primitive_type_length(OSObject *obj) +{ + const OSMetaClass *typeID; + int len; + + typeID = OSTypeIDInst(obj); + if (typeID == OSTypeID(OSString)) { + OSString * stringObj = OSDynamicCast(OSString, obj); + len = stringObj->getLength() + 1; + } + else if (typeID == OSTypeID(OSNumber)) { + len = sizeof("4294967295"); /* UINT32_MAX */ + } + else if (typeID == OSTypeID(OSBoolean)) { + OSBoolean * boolObj = OSDynamicCast(OSBoolean, obj); + len = boolObj->isTrue() ? sizeof("true") : sizeof("false"); + } + else if (typeID == OSTypeID(OSData)) { + OSData * dataObj = OSDynamicCast(OSData, obj); + len = dataObj->getLength(); + } + else { + len = 0; + } + return(len); +} + +static void +primitive_type_collect(struct mac_module_data_element *element, OSObject *value) +{ + const OSMetaClass *typeID; + + typeID = OSTypeIDInst(value); + if (typeID == OSTypeID(OSString)) { + OSString *stringObj = OSDynamicCast(OSString, value); + element->value_type = MAC_DATA_TYPE_PRIMITIVE; + element->value_size = stringObj->getLength() + 1; + DPRINTF(("osdict: string %s size %d\n", + stringObj->getCStringNoCopy(), element->value_size)); + memcpy(element->value, stringObj->getCStringNoCopy(), + element->value_size); + } else if (typeID == OSTypeID(OSNumber)) { + OSNumber *numberObj = OSDynamicCast(OSNumber, value); + element->value_type = MAC_DATA_TYPE_PRIMITIVE; + element->value_size = sprintf(element->value, "%u", + numberObj->unsigned32BitValue()) + 1; + } else if (typeID == OSTypeID(OSBoolean)) { + OSBoolean *boolObj = OSDynamicCast(OSBoolean, value); + element->value_type = MAC_DATA_TYPE_PRIMITIVE; + if (boolObj->isTrue()) { + strcpy(element->value, "true"); + element->value_size = 5; + } else { + strcpy(element->value, "false"); + element->value_size = 6; + } + } else if (typeID == OSTypeID(OSData)) { + OSData *dataObj = OSDynamicCast(OSData, value); + element->value_type = MAC_DATA_TYPE_PRIMITIVE; + element->value_size = dataObj->getLength(); + DPRINTF(("osdict: data size %d\n", dataObj->getLength())); + memcpy(element->value, dataObj->getBytesNoCopy(), + element->value_size); + } +} + /********************************************************************* * This function takes an OSDictionary and returns a struct mac_module_data * list. @@ -143,9 +234,13 @@ struct mac_module_data * module_data = 0; struct mac_module_data_element * element; unsigned int strtabsize = 0; + unsigned int listtabsize = 0; + unsigned int dicttabsize = 0; unsigned int nkeys = 0; unsigned int datalen; - char * strtab = 0; + char *strtab = NULL; + char *listtab = NULL; + char *dicttab = NULL; vm_offset_t data_addr; keyIterator = OSCollectionIterator::withCollection(dict); @@ -161,18 +256,69 @@ continue; typeID = OSTypeIDInst(value); - if (typeID == OSTypeID(OSString)) { - OSString * stringObj = OSDynamicCast(OSString, value); - strtabsize += stringObj->getLength() + 1; - } else if (typeID == OSTypeID(OSNumber)) { - strtabsize += sizeof("4294967295"); /* UINT32_MAX */ - } else if (typeID == OSTypeID(OSBoolean)) { - OSBoolean * boolObj = OSDynamicCast(OSBoolean, value); - strtabsize += boolObj->isTrue() ? sizeof("true") : sizeof("false"); - } else if (typeID == OSTypeID(OSData)) { - OSData * dataObj = OSDynamicCast(OSData, value); - strtabsize += dataObj->getLength(); - } else { + if (primitive_type(value)) { + strtabsize += primitive_type_length(value); + } + else if (typeID == OSTypeID(OSArray)) { + unsigned int k, cnt, nents; + OSArray *arrayObj = OSDynamicCast(OSArray, value); + + nents = 0; + cnt = arrayObj->getCount(); + for (k = 0; k < cnt; k++) { + value = arrayObj->getObject(k); + typeID = OSTypeIDInst(value); + if (primitive_type(value)) { + listtabsize += primitive_type_length(value); + nents++; + } + else if (typeID == OSTypeID(OSDictionary)) { + unsigned int dents; + OSDictionary *dictObj; + OSString *dictkey; + OSCollectionIterator *dictIterator; + + dents = 0; + dictObj = OSDynamicCast(OSDictionary, value); + dictIterator = OSCollectionIterator::withCollection(dictObj); + if (!dictIterator) + goto finish; + while ((dictkey = OSDynamicCast(OSString, + dictIterator->getNextObject()))) { + OSObject *dictvalue; + + dictvalue = dictObj->getObject(dictkey); + if (!dictvalue) + continue; + if (primitive_type(dictvalue)) { + strtabsize += primitive_type_length(dictvalue); + } + else { + continue; /* Only handle primitive types here. */ + } + /* + * Allow for the "arraynnn/" prefix in the key length. + */ + strtabsize += dictkey->getLength() + 1; + dents++; + } + dictIterator->release(); + if (dents-- > 0) { + dicttabsize += sizeof(struct mac_module_data_list) + + dents * sizeof(struct mac_module_data_element); + nents++; + } + } + else { + continue; /* Skip everything else. */ + } + } + if (nents == 0) + continue; + listtabsize += sizeof(struct mac_module_data_list) + + (nents - 1) * sizeof(struct mac_module_data_element); + } + else { continue; /* skip anything else */ } strtabsize += key->getLength() + 1; @@ -185,16 +331,26 @@ * Allocate and fill in the module data structures. */ datalen = sizeof(struct mac_module_data) + - sizeof(mac_module_data_element) * (nkeys - 1) + strtabsize; + sizeof(mac_module_data_element) * (nkeys - 1) + + strtabsize + listtabsize + dicttabsize; + DPRINTF(("osdict: datalen %d strtabsize %d listtabsize %d dicttabsize %d\n", + datalen, strtabsize, listtabsize, dicttabsize)); if (kmem_alloc(kernel_map, &data_addr, datalen) != KERN_SUCCESS) goto finish; module_data = (mac_module_data *)data_addr; + module_data->base_addr = data_addr; module_data->size = datalen; module_data->count = nkeys; strtab = (char *)&module_data->data[nkeys]; + listtab = strtab + strtabsize; + dicttab = listtab + listtabsize; + DPRINTF(("osdict: data_addr %p strtab %p listtab %p dicttab %p end %p\n", + data_addr, strtab, listtab, dicttab, data_addr + datalen)); keyIterator->reset(); + nkeys = 0; element = &module_data->data[0]; + DPRINTF(("osdict: element %p\n", element)); while ( (key = OSDynamicCast(OSString, keyIterator->getNextObject())) ) { // Get the key's value and determine its type @@ -203,43 +359,138 @@ continue; /* Store key */ + DPRINTF(("osdict: element @%p\n", element)); element->key = strtab; element->key_size = key->getLength() + 1; + DPRINTF(("osdict: key %s size %d @%p\n", key->getCStringNoCopy(), element->key_size, strtab)); memcpy(element->key, key->getCStringNoCopy(), element->key_size); - /* Store value */ - element->value = element->key + element->key_size; typeID = OSTypeIDInst(value); - if (typeID == OSTypeID(OSString)) { - OSString * stringObj = OSDynamicCast(OSString, value); - element->value_size = stringObj->getLength() + 1; - memcpy(element->value, stringObj->getCStringNoCopy(), - element->value_size); - } else if (typeID == OSTypeID(OSNumber)) { - OSNumber * numberObj = OSDynamicCast(OSNumber, value); - element->value_size = sprintf(element->value, "%u", - numberObj->unsigned32BitValue()) + 1; - } else if (typeID == OSTypeID(OSBoolean)) { - OSBoolean * boolObj = OSDynamicCast(OSBoolean, value); - if (boolObj->isTrue()) { - strcpy(element->value, "true"); - element->value_size = 5; - } else { - strcpy(element->value, "false"); - element->value_size = 6; + if (primitive_type(value)) { + /* Store value */ + element->value = element->key + element->key_size; + DPRINTF(("osdict: primitive element value %p\n", element->value)); + primitive_type_collect(element, value); + strtab += element->key_size + element->value_size; + DPRINTF(("osdict: new strtab %p\n", strtab)); + } + else if (typeID == OSTypeID(OSArray)) { + unsigned int k, cnt, nents; + char *astrtab; + struct mac_module_data_list *arrayhd; + struct mac_module_data_element *ele; + OSArray *arrayObj = OSDynamicCast(OSArray, value); + + element->value = listtab; + DPRINTF(("osdict: array element value %p\n", element->value)); + element->value_type = MAC_DATA_TYPE_ARRAY; + arrayhd = (struct mac_module_data_list *)element->value; + arrayhd->type = 0; + DPRINTF(("osdict: arrayhd %p\n", arrayhd)); + nents = 0; + astrtab = strtab + element->key_size; + ele = &(arrayhd->list[0]); + cnt = arrayObj->getCount(); + for (k = 0; k < cnt; k++) { + value = arrayObj->getObject(k); + DPRINTF(("osdict: array ele %d @%p\n", nents, ele)); + ele->key = NULL; + ele->key_size = 0; + typeID = OSTypeIDInst(value); + if (primitive_type(value)) { + if (arrayhd->type != 0 && + arrayhd->type != MAC_DATA_TYPE_PRIMITIVE) + continue; + arrayhd->type = MAC_DATA_TYPE_PRIMITIVE; + ele->value = astrtab; + primitive_type_collect(ele, value); + astrtab += ele->value_size; + DPRINTF(("osdict: array new astrtab %p\n", astrtab)); + } + else if (typeID == OSTypeID(OSDictionary)) { + unsigned int dents; + char *dstrtab; + OSDictionary *dictObj; + OSString *dictkey; + OSCollectionIterator *dictIterator; + struct mac_module_data_list *dicthd; + struct mac_module_data_element *dele; + + if (arrayhd->type != 0 && + arrayhd->type != MAC_DATA_TYPE_DICT) + continue; + dictObj = OSDynamicCast(OSDictionary, value); + dictIterator = OSCollectionIterator::withCollection(dictObj); + if (!dictIterator) + goto finish; + DPRINTF(("osdict: dict\n")); + ele->value = dicttab; + ele->value_type = MAC_DATA_TYPE_DICT; + dicthd = (struct mac_module_data_list *)ele->value; + DPRINTF(("osdict: dicthd %p\n", dicthd)); + dstrtab = astrtab; + dents = 0; + while ((dictkey = OSDynamicCast(OSString, + dictIterator->getNextObject()))) { + OSObject *dictvalue; + + dictvalue = dictObj->getObject(dictkey); + if (!dictvalue) + continue; + dele = &(dicthd->list[dents]); + DPRINTF(("osdict: dict ele %d @%p\n", dents, dele)); + if (primitive_type(dictvalue)) { + dele->key = dstrtab; + dele->key_size = dictkey->getLength() + 1; + DPRINTF(("osdict: dictkey %s size %d @%p\n", + dictkey->getCStringNoCopy(), dictkey->getLength(), dstrtab)); + memcpy(dele->key, dictkey->getCStringNoCopy(), + dele->key_size); + dele->value = dele->key + dele->key_size; + primitive_type_collect(dele, dictvalue); + dstrtab += dele->key_size + dele->value_size; + DPRINTF(("osdict: dict new dstrtab %p\n", dstrtab)); + } + else { + continue; /* Only handle primitive types here. */ + } + dents++; + } + dictIterator->release(); + if (dents == 0) + continue; + arrayhd->type = MAC_DATA_TYPE_DICT; + ele->value_size = sizeof(struct mac_module_data_list) + + (dents - 1) * sizeof(struct mac_module_data_element); + DPRINTF(("osdict: dict ele size %d ents %d\n", ele->value_size, dents)); + dicttab += ele->value_size; + DPRINTF(("osdict: new dicttab %p\n", dicttab)); + dicthd->count = dents; + astrtab = dstrtab; + } + else { + continue; /* Skip everything else. */ + } + nents++; + ele++; } - } else if (typeID == OSTypeID(OSData)) { - OSData * dataObj = OSDynamicCast(OSData, value); - element->value_size = dataObj->getLength(); - memcpy(element->value, dataObj->getBytesNoCopy(), - element->value_size); - } else { + if (nents == 0) + continue; + element->value_size = sizeof(struct mac_module_data_list) + + (nents - 1) * sizeof(struct mac_module_data_element); + listtab += element->value_size; + DPRINTF(("osdict: new listtab %p\n", listtab)); + arrayhd->count = nents; + strtab = astrtab; + DPRINTF(("osdict: new strtab %p\n", strtab)); + } + else { continue; /* skip anything else */ } - - strtab += element->key_size + element->value_size; element++; } + DPRINTF(("module_data list @%p, key %p value %p\n", + module_data, module_data->data[0].key, module_data->data[0].value)); finish: if (keyIterator) keyIterator->release(); @@ -273,7 +524,7 @@ */ vm_map_copyin(kernel_map, (vm_offset_t)module_data, *datalen, FALSE, ©); kmem_free(kernel_map, (vm_offset_t)module_data, *datalen); - + DPRINTF(("get_module_data: copy @ %p\n", copy)); finish: return (kmod_args_t)copy; } ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac.h#10 (text+ko) ==== @@ -70,8 +70,9 @@ /* * Device types for mac_iokit_check_device() */ -#define MAC_DEVICE_USB 0 -#define MAC_DEVICE_FIREWIRE 1 +#define MAC_DEVICE_USB "USB" +#define MAC_DEVICE_FIREWIRE "FireWire" +#define MAC_DEVICE_TYPE_KEY "DeviceType" #ifndef KERNEL /* @@ -117,7 +118,7 @@ * I/O Kit device access control. * Note that this routine is called from a C++ I/O Kit driver. */ -int mac_iokit_check_device(int devtype, struct module_data *mdata); +int mac_iokit_check_device(char *devtype, struct module_data *mdata); __END_DECLS #endif ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_base.c#23 (text+ko) ==== @@ -69,6 +69,18 @@ #include #include +/* + * define MB_DEBUG to display run-time debugging information + * #define MB_DEBUG 1 + */ + +#ifdef MB_DEBUG +#define DPRINTF(x) printf x +#else +#define MB_DEBUG +#define DPRINTF(x) +#endif + SYSCTL_NODE(, OID_AUTO, security, CTLFLAG_RW, 0, "Security Controls"); SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, @@ -671,6 +683,44 @@ } } +static __inline void +mac_policy_fixup_mmd_list(struct mac_module_data *new) +{ + struct mac_module_data *old; + struct mac_module_data_element *ele, *aele, *dele; + struct mac_module_data_list *arr, *dict; + unsigned int i, j, k; + + old = new->base_addr; + DPRINTF(("fixup_mmd: old %p new %p\n", old, new)); + for (i = 0; i < new->count; i++) { + ele = &(new->data[i]); + DPRINTF(("fixup_mmd: ele %p\n", ele)); + DPRINTF((" key %p value %p\n", ele->key, ele->value)); + mmd_fixup_ele(old, new, ele); /* Fix up key/value ptrs. */ + DPRINTF((" key %p value %p\n", ele->key, ele->value)); + if (ele->value_type == MAC_DATA_TYPE_ARRAY) { + arr = (struct mac_module_data_list *)ele->value; + DPRINTF(("fixup_mmd: array @%p\n", arr)); + for (j = 0; j < arr->count; j++) { + aele = &(arr->list[j]); + DPRINTF(("fixup_mmd: aele %p\n", aele)); + DPRINTF((" key %p value %p\n", aele->key, aele->value)); + mmd_fixup_ele(old, new, aele); + DPRINTF((" key %p value %p\n", aele->key, aele->value)); + if (arr->type == MAC_DATA_TYPE_DICT) { + dict = (struct mac_module_data_list *)aele->value; + DPRINTF(("fixup_mmd: dict @%p\n", dict)); + for (k = 0; k < dict->count; k++) + mmd_fixup_ele(old, new, + &(dict->list[k])); + } + } + } + } + new->base_addr = new; +} + int mac_policy_register(struct mac_policy_conf *mpc, mac_policy_handle_t *handlep, void *xd) @@ -766,22 +816,14 @@ if (xd) { struct mac_module_data *mmd = xd; /* module data from plist */ - char *strtab; /* Make a copy of the data. */ mpc->mpc_data = (void *)kalloc(mmd->size); if (mpc->mpc_data != NULL) { memcpy(mpc->mpc_data, mmd, mmd->size); - mmd = mpc->mpc_data; - /* Fix up pointers into string table after copy. */ - strtab = (char *)&mmd->data[mmd->count]; - for (i = 0; i < mmd->count; i++) { - mmd->data[i].key = strtab; - strtab += mmd->data[i].key_size; - mmd->data[i].value = strtab; - strtab += mmd->data[i].value_size; - } + /* Fix up pointers after copy. */ + mac_policy_fixup_mmd_list(mpc->mpc_data); } } ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_data.h#4 (text+ko) ==== @@ -33,7 +33,11 @@ This structure specifies module data that is passed in to the TrustedBSD MAC policy module by the kernel module loader. The data is made of up key/value pairs where the key is always a - string and the value is either a string or binary data. + string and the value is a string, binary data or array. An array + may be a list of values (actually a similar set of key/value pairs, + but in this case the keys are always null), and may also consist of + a set of dictionaries, which in turn are made up of a list of key/value + pairs. Module data may be specified in the MAC policy module's Info.plist file as part of the OSModuleData dictionary. @@ -41,30 +45,74 @@ E.g. OSModuleData + + foo + bar + Beers + - foo - bar + type + lager + Name + Anchor Steam + + + type + ale + Name + Sierra Nevada Pale Ale + + */ struct mac_module_data_element { unsigned int key_size; unsigned int value_size; + unsigned int value_type; char *key; char *value; }; +struct mac_module_data_list { + unsigned int count; + unsigned int type; + struct mac_module_data_element list[1]; +}; struct mac_module_data { + void *base_addr; /* Orig base address, for ptr fixup. */ unsigned int size; unsigned int count; struct mac_module_data_element data[1]; /* actually bigger */ }; +#define MAC_DATA_TYPE_PRIMITIVE 0 /* Primitive type (int, string, etc.) */ +#define MAC_DATA_TYPE_ARRAY 1 /* Array type. */ +#define MAC_DATA_TYPE_DICT 2 /* Dictionary type. */ + #ifdef _SECURITY_MAC_POLICY_H_ /* XXX mac_policy_handle_t is defined in mac_policy.h, move prototype there? */ int mac_find_policy_data(const mac_policy_handle_t, const char *key, void **valp, size_t *sizep); int mac_find_module_data(struct mac_module_data *mmd, const char *key, void **valp, size_t *sizep); + +/* + * This is a routine to fix up pointers in a mac_module_data_element when the + * mac_module_data has been copied to a new area. It depends on the pointers + * all being offset from base_addr. + */ +static __inline void +mmd_fixup_ele(struct mac_module_data *oldbase, + struct mac_module_data *newbase, struct mac_module_data_element *ele) +{ + if (ele->key != NULL) { /* Array elements have no keys. */ + ele->key -= (unsigned int)oldbase; + ele->key += (unsigned int)newbase; + } + ele->value -= (unsigned int)oldbase; + ele->value += (unsigned int)newbase; +} + #endif #endif /* !_SECURITY_MAC_DATA_H_ */ ==== //depot/projects/trustedbsd/sedarwin8/darwin/xnu/security/mac_iokit.c#2 (text+ko) ==== @@ -37,7 +37,7 @@ #include int -mac_iokit_check_device(int devtype, struct module_data *mdata) +mac_iokit_check_device(char *devtype, struct module_data *mdata) { int error; ==== //depot/projects/trustedbsd/sedarwin8/policies/device_access/mac_device_access.c#5 (text+ko) ==== @@ -36,7 +36,6 @@ * define DA_DEBUG to display run-time debugging information * #define DA_DEBUG 1 */ -#define DA_DEBUG 1 #ifdef DA_DEBUG #define DA_TRACE printf("In %s\n", __FUNCTION__) @@ -48,85 +47,7 @@ #define MAC_DEVACCESS_POLICY_NAME "device_access" -struct keyvals { - unsigned int ksize; - const char *k; - unsigned int vsize; - const char *v; -}; -struct allowed_devs { - int type; /* Device type. */ - unsigned int nprops; /* Number of properties. */ - struct keyvals props[2]; -}; -static struct allowed_devs devlist[] = { - { MAC_DEVICE_USB, 2, { /* Apple Extended USB Keyboard */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 4, "516" } /* 0x0204 */ - } - }, - { MAC_DEVICE_USB, 2, { /* Apple Extended USB Keyboard */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 4, "517" } /* 0x0205 */ - } - }, - { MAC_DEVICE_USB, 2, { /* Apple Extended USB Keyboard */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 4, "523" } /* 0x020b */ - } - }, - { MAC_DEVICE_USB, 2, { /* Apple Extended USB Keyboard */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 4, "524" } /* 0x020c */ - } - }, - { MAC_DEVICE_USB, 2, { /* Apple Optical USB Mouse */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 4, "770" } /* 0x0302 */ - } - }, - { MAC_DEVICE_USB, 2, { /* Apple Optical USB Mouse */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 4, "772" } /* 0x0304 */ - } - }, - { MAC_DEVICE_USB, 2, { /* Apple Optical USB Mouse */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 4, "774" } /* 0x0306 */ - } - }, - { MAC_DEVICE_USB, 2, { /* OHCI Root Hub Simulation */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 6, "32773" } /* 0x8005 */ - } - }, - { MAC_DEVICE_USB, 2, { /* Hub in Apple Extended USB Keyboard */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 5, "4098" } /* 0x1002 */ - } - }, - { MAC_DEVICE_USB, 2, { /* Hub in Apple Extended USB Keyboard */ - { 9, "VendorID", 5, "1452" }, /* 0x05ac */ - { 12, "ModelNumber", 5, "4099" } /* 0x1003 */ - } - }, - { MAC_DEVICE_USB, 2, { /* Texas Instruments Hub */ - { 9, "VendorID", 5, "1105" }, /* 0x0451 */ - { 12, "ModelNumber", 5, "8262" } /* 0x2046 */ - } - }, - { MAC_DEVICE_USB, 2, { /* MachKey Intl USB KVM Switch */ - { 9, "VendorID", 5, "1778" }, /* 0x06f2 */ - { 12, "ModelNumber", 4, "123" } /* 0x007b */ - } - }, - { MAC_DEVICE_FIREWIRE, 2, { /* Apple laptop. */ - { 9, "VendorID", 5, "2599" }, - { 12, "ModelNumber", 3, "10" } - } - } -}; -static unsigned int devlist_ents = sizeof(devlist) / sizeof(struct allowed_devs); +static struct mac_module_data *device_access_list = NULL; /* * SYSCTL entry points @@ -145,8 +66,15 @@ device_access_policy_init(struct mac_policy_conf *mpc) { DA_TRACE; + if (device_access_list == NULL && mpc->mpc_data != NULL) { + device_access_list = mpc->mpc_data; + DPRINTF(("device_access list @%p, key %p value %p\n", + device_access_list, device_access_list->data[0].key, + device_access_list->data[0].value)); + } printf("MAC Device Access policy is initialized\n"); - DPRINTF((" %sabled\n", mac_device_access_enabled ? "En" : "Dis")); + DPRINTF((" %sabled, device_access_list @%p\n", + mac_device_access_enabled ? "En" : "Dis", device_access_list)); } static void @@ -160,49 +88,102 @@ device_access_policy_initbsd(struct mac_policy_conf *mpc) { DA_TRACE; + if (device_access_list == NULL && mpc->mpc_data != NULL) + device_access_list = mpc->mpc_data; sysctl_register_oid(&sysctl__security_mac_device_access); sysctl_register_oid(&sysctl__security_mac_device_access_enabled); } +/* + * Compare a device access dictionary entry against the device properties. + * Return true if a matching key exists in the properties with a matching + * value. + */ static int -dev_match(struct mac_module_data *mdata, struct keyvals *props) +dev_match(struct mac_module_data *props, struct mac_module_data_element *ele) { unsigned int k; int kmatch = 0; - for (k = 0; k < mdata->count; k++) { - if (mdata->data[k].key_size != props->ksize) + for (k = 0; k < props->count; k++) { + if (props->data[k].key_size != ele->key_size) continue; - if (!strncmp(mdata->data[k].key, props->k, props->ksize) && - !bcmp(mdata->data[k].value, props->v, props->vsize)) + if (!strncmp(props->data[k].key, ele->key, ele->key_size) && + props->data[k].value_size == ele->value_size && + !bcmp(props->data[k].value, ele->value, ele->value_size)) kmatch++; } return(kmatch); } static int -device_access_iokit_check_device(int devtype, struct mac_module_data *mdata) +device_access_iokit_check_device(char *devtype, struct mac_module_data *mdata) { + struct mac_module_data_list *dict, *list; unsigned int matches; unsigned int i, j; DA_TRACE; - if (!mac_device_access_enabled) + if (!mac_device_access_enabled || device_access_list == NULL) + return(0); + /* + * The module data should have one entry, an array of dicts. Each + * dict is itself an array of key/value pairs that describe an + * allowed device. + */ + if (device_access_list->data[0].value_type != MAC_DATA_TYPE_ARRAY) + return(0); + list = (struct mac_module_data_list *)device_access_list->data[0].value; + /* + * If it's not an array of , somebody messed up and it's + * unusable. + */ + if (list->type != MAC_DATA_TYPE_DICT) return(0); /* - * Go through our list of allowed devices. If all the properties of - * one of our listed devices match corresponding properties in the - * passed device properties, the device is allowed. + * Go through the list of dictionaries and compare each one to the + * passed device property list. If all the entries of a dictionary + * match corresponding properties in the passed property list, the + * device is allowed. */ - for (i = 0; i < devlist_ents; i++) { - if (devlist[i].type != devtype) /* Skip if the wrong type. */ - continue; - matches = 0; - for (j = 0; j < devlist[i].nprops; j++) { - if (dev_match(mdata, &(devlist[i].props[j])) > 0) - matches++; /* Key matched. */ + for (i = 0; i < list->count; i++) { + dict = (struct mac_module_data_list *)list->list[i].value; + /* + * If this dictionary doesn't match the device type, skip it. + */ + for (j = 0; j < dict->count; j++) { + unsigned int keylen, vallen; + + keylen = strlen(MAC_DEVICE_TYPE_KEY) + 1; + vallen = strlen(devtype) + 1; + if (dict->list[j].key_size != keylen || + strncmp(dict->list[j].key, MAC_DEVICE_TYPE_KEY, keylen)) + continue; /* Key mismatch, next key. */ + if (vallen == dict->list[j].value_size && + !bcmp(devtype, dict->list[j].value, vallen)) + break; /* Match. */ + } + if (j == dict->count) /* Key found and matched? */ + continue; /* No, go to next dictionary. */ + /* + * Compare all the dictionary entries against the device + * property list. If they all match, the device is allowed. + */ + matches = 1; /* We've already matched devtype. */ + for (j = 0; j < dict->count; j++) { + /* + * If there's a "Name" entry in the dict, it always + * matches. + */ + if (dict->list[j].key_size == strlen("Name")+1 && + !strncmp(dict->list[j].key, "Name", strlen("Name"))) { + matches++; + continue; + } + if (dev_match(mdata, &(dict->list[j])) > 0) + matches++; /* Entry matched. */ } - if (matches == devlist[i].nprops) + if (matches == dict->count) return(0); } return(EPERM);