PERFORCE change 111036 for review
Todd Miller
millert at FreeBSD.org
Mon Dec 4 10:05:51 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=111036
Change 111036 by millert at 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 @@
<key>OSBundleCompatibleVersion</key>
<string>${POLICY_COMPVER}</string>
+__EOF__
+
+if [ -f Default.plist ] ; then
+ cat Default.plist
+fi
+
+cat << __EOF__
<key>OSBundleLibraries</key>
<dict>
__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 <IOKit/assert.h>
+/*
+ * 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 <osfmk/kern/kalloc.h>
#include <libsa/libsa/kext.h>
+/*
+ * 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.
<key>OSModuleData</key>
+ <dict>
+ <key>foo</key>
+ <string>bar</string>
+ <key>Beers</key>
+ <array>
<dict>
- <key>foo</key>
- <string>bar</string>
+ <key>type</key>
+ <string>lager</string>
+ <key>Name</key>
+ <string>Anchor Steam</string>
+ </dict>
+ <dict>
+ <key>type</key>
+ <string>ale</string>
+ <key>Name</key>
+ <string>Sierra Nevada Pale Ale</string>
</dict>
+ </array>
+ </dict>
*/
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 <kern/kalloc.h>
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 <dict>, 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);
More information about the trustedbsd-cvs
mailing list