diff -r 8ca4e32583b6 docs/misc/xsm-flask.txt --- a/docs/misc/xsm-flask.txt Fri Oct 23 10:15:17 2009 +0100 +++ b/docs/misc/xsm-flask.txt Fri Oct 23 11:41:41 2009 -0400 @@ -168,6 +168,70 @@ often lead to adding parameterized rules to the interfaces in xen.if to address the general case. +Device Policy +------------- + +Flask is capable of labeling devices and enforcing policies associated with +them. To enable this functionality the latest version of checkpolicy +(>= 2.0.20) and libsepol (>=2.0.39) will be needed in order to compile it. To +enable the building of the new policies the following changes will need to be +done to tools/flask/policy/Makefile. + +######################################## +# +# Build a binary policy locally +# +$(POLVER): policy.conf + @echo "Compiling $(NAME) $(POLVER)" + $(QUIET) $(CHECKPOLICY) $^ -o $@ (Comment out this line) +# Uncomment line below to enable policies for devices +# $(QUIET) $(CHECKPOLICY) -t Xen $^ -o $@ (Uncomment this line) + +######################################## +# +# Install a binary policy +# +$(LOADPATH): policy.conf + @echo "Compiling and installing $(NAME) $(LOADPATH)" + $(QUIET) $(CHECKPOLICY) $^ -o $@ (Comment out this line) +# Uncomment line below to enable policies for devices +# $(QUIET) $(CHECKPOLICY) -t Xen $^ -o $@ (Uncomment this line) + + +Pirqs, PCI devices, I/O memory and ports can all be labeled. There are +commented out lines in xen.te policy for examples on how to label devices. + +Device Labeling +--------------- + +The "lspci -vvn" command can be used to output all the devices and identifiers +associated with them. For example, to label an Intel e1000e ethernet card the +lspci output is.. + +00:19.0 0200: 8086:10de (rev 02) + Subsystem: 1028:0276 + Interrupt: pin A routed to IRQ 33 + Region 0: Memory at febe0000 (32-bit, non-prefetchable) [size=128K] + Region 1: Memory at febd9000 (32-bit, non-prefetchable) [size=4K] + Region 2: I/O ports at ecc0 [size=32] + Kernel modules: e1000e + +The labeling can be done with these commands + +pirqcon 33 system_u:object_r:nicP_t +iomemcon 0xfebe0-0xfebff system_u:object_r:nicP_t +iomemcon 0xfebd9 system_u:object_r:nicP_t +ioportcon 0xecc0-0xecdf system_u:object_r:nicP_t +pcidevicecon 0xc800 system_u:object_r:nicP_t + +Labeling of the PCI device is tricky since there is no output in lspci that +makes the information easily available. The easiest way to obtain the +information is to look at the avc denial line for the correct hex value. + +(XEN) avc: denied { add_device } for domid=0 device=0xc800 <--- +scontext=system_u:system_r:dom0_t tcontext=system_u:object_r:device_t +tclass=resource + Additional notes on XSM:FLASK ----------------------------- diff -r 8ca4e32583b6 tools/flask/policy/Makefile --- a/tools/flask/policy/Makefile Fri Oct 23 10:15:17 2009 +0100 +++ b/tools/flask/policy/Makefile Fri Oct 23 11:41:41 2009 -0400 @@ -148,7 +148,9 @@ # $(POLVER): policy.conf @echo "Compiling $(NAME) $(POLVER)" - $(QUIET) $(CHECKPOLICY) $^ -o $@ + $(QUIET) $(CHECKPOLICY) $^ -o $@ +# Uncomment line below to enable policies for devices +# $(QUIET) $(CHECKPOLICY) -t Xen $^ -o $@ ######################################## # @@ -156,7 +158,9 @@ # $(LOADPATH): policy.conf @echo "Compiling and installing $(NAME) $(LOADPATH)" - $(QUIET) $(CHECKPOLICY) $^ -o $@ + $(QUIET) $(CHECKPOLICY) $^ -o $@ +# Uncomment line below to enable policies for devices +# $(QUIET) $(CHECKPOLICY) -t Xen $^ -o $@ ######################################## # @@ -206,8 +210,18 @@ $(QUIET) grep '^type ' tmp/all_te_files.conf >> tmp/all_attrs_types.conf $(QUIET) cat tmp/post_te_files.conf > tmp/all_post.conf $(QUIET) grep '^sid ' tmp/all_te_files.conf >> tmp/all_post.conf || true + $(QUIET) grep ^pirqcon tmp/all_te_files.conf >> \ + tmp/all_post.conf || true + $(QUIET) grep ^ioportcon tmp/all_te_files.conf >> \ + tmp/all_post.conf || true + $(QUIET) grep ^iomemcon tmp/all_te_files.conf >> \ + tmp/all_post.conf || true + $(QUIET) grep ^pcidevicecon tmp/all_te_files.conf >> \ + tmp/all_post.conf || true $(QUIET) sed -r -e /^attribute/d -e '/^type /d' -e '/^sid /d' \ - < tmp/all_te_files.conf > tmp/only_te_rules.conf + -e "/^pirqcon/d" -e "/^pcidevicecon/d" -e "/^ioportcon/d" \ + -e "/^iomemcon/d" < tmp/all_te_files.conf \ + > tmp/only_te_rules.conf ######################################## # diff -r 8ca4e32583b6 tools/flask/policy/policy/modules/xen/xen.if --- a/tools/flask/policy/policy/modules/xen/xen.if Fri Oct 23 10:15:17 2009 +0100 +++ b/tools/flask/policy/policy/modules/xen/xen.if Fri Oct 23 11:41:41 2009 -0400 @@ -60,3 +60,34 @@ allow $1 $3:event {create}; allow $3 $2:event {bind}; ') +############################################################################### +# +# create_passthrough_resource(priv_dom, domain, resource) +# +############################################################################### +define(`create_passthrough_resource', ` + type $3, resource_type; + allow $1 $3:event vector; + allow $1 $2:resource {add remove}; + allow $1 ioport_t:resource {add_ioport use}; + allow $1 iomem_t:resource {add_iomem use}; + allow $1 pirq_t:resource {add_irq use}; + allow $1 domio_t:mmu {map_read map_write}; + allow $2 domio_t:mmu {map_write}; + allow $2 pirq_t:resource {use}; + allow $1 $3:resource {add_irq add_iomem add_ioport remove_irq remove_iomem remove_ioport use add_device remove_device}; + allow $2 $3:resource {use add_ioport add_iomem remove_ioport remove_iomem}; + allow $2 $3:mmu {map_read map_write}; +') +############################################################################### +# +# create_hvm_resource(priv_dom, domain, resource) +# +############################################################################### +define(`create_hvm_resource', ` + type $3, resource_type; + allow $1 $2:resource {add remove}; + allow $1 $3:hvm {bind_irq}; + allow $1 $3:resource {stat_device add_device remove_device add_irq remove_irq add_iomem remove_iomem add_ioport remove_ioport}; + allow $2 $3:resource {use}; +') diff -r 8ca4e32583b6 tools/flask/policy/policy/modules/xen/xen.te --- a/tools/flask/policy/policy/modules/xen/xen.te Fri Oct 23 10:15:17 2009 +0100 +++ b/tools/flask/policy/policy/modules/xen/xen.te Fri Oct 23 11:41:41 2009 -0400 @@ -76,6 +76,41 @@ allow dom0_t domU_t:grant {copy}; allow domU_t domU_t:grant {copy}; +############################################################################### +# +# Create device labels +# +############################################################################### + +# create device resources +#create_passthrough_resource(dom0_t, domU_t, nicP_t) +#create_hvm_resource(dom0_t, domHU_t, nicP_t) + +# label e1000e nic +#pirqcon 33 system_u:object_r:nicP_t +#pirqcon 55 system_u:object_r:nicP_t +#iomemcon 0xfebe0-0xfebff system_u:object_r:nicP_t +#iomemcon 0xfebd9 system_u:object_r:nicP_t +#ioportcon 0xecc0-0xecdf system_u:object_r:nicP_t +#pcidevicecon 0xc800 system_u:object_r:nicP_t + +# label e100 nic +#pirqcon 16 system_u:object_r:nicP_t +#iomemcon 0xfe5df system_u:object_r:nicP_t +#iomemcon 0xfe5e0-0xfe5ff system_u:object_r:nicP_t +#iomemcon 0xc2000-0xc200f system_u:object_r:nicP_t +#ioportcon 0xccc0-0xcd00 system_u:object_r:nicP_t + +# label usb 1d.0-2 1d.7 +#pirqcon 23 system_u:object_r:nicP_t +#pirqcon 17 system_u:object_r:nicP_t +#pirqcon 18 system_u:object_r:nicP_t +#ioportcon 0xff80-0xFF9F system_u:object_r:nicP_t +#ioportcon 0xff60-0xff7f system_u:object_r:nicP_t +#ioportcon 0xff40-0xff5f system_u:object_r:nicP_t +#iomemcon 0xff980 system_u:object_r:nicP_t +#ioportcon 0xff00-0xff1f system_u:object_r:nicP_t + manage_domain(dom0_t, domU_t) ################################################################################ diff -r 8ca4e32583b6 xen/xsm/flask/avc.c --- a/xen/xsm/flask/avc.c Fri Oct 23 10:15:17 2009 +0100 +++ b/xen/xsm/flask/avc.c Fri Oct 23 11:41:41 2009 -0400 @@ -566,6 +566,8 @@ d = a->d; if ( d ) printk("domid=%d ", d->domain_id); + if ( a && a->device ) + printk("device=0x%lx ", a->device); avc_dump_query(ssid, tsid, tclass); printk("\n"); diff -r 8ca4e32583b6 xen/xsm/flask/hooks.c --- a/xen/xsm/flask/hooks.c Fri Oct 23 10:15:17 2009 +0100 +++ b/xen/xsm/flask/hooks.c Fri Oct 23 11:41:41 2009 -0400 @@ -649,6 +649,7 @@ int rc = -EPERM; struct domain_security_struct *ssec, *tsec; + struct avc_audit_data ad; rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, resource_to_perm(access)); @@ -668,13 +669,16 @@ if ( rc ) return rc; - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, NULL); + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = (unsigned long) pirq; + + rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); if ( rc ) return rc; if ( access ) return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, - RESOURCE__USE, NULL); + RESOURCE__USE, &ad); else return rc; } @@ -686,6 +690,7 @@ int rc = -EPERM; struct domain_security_struct *ssec, *tsec; + struct avc_audit_data ad; rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, resource_to_perm(access)); @@ -704,13 +709,16 @@ if ( rc ) return rc; - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, NULL); + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = mfn; + + rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); if ( rc ) return rc; return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, - RESOURCE__USE, NULL); + RESOURCE__USE, &ad); } static int flask_perfcontrol(void) @@ -753,6 +761,7 @@ u32 rsid; int rc = -EPERM; + struct avc_audit_data ad; struct domain_security_struct *ssec, *tsec; rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, @@ -773,13 +782,16 @@ if ( rc ) return rc; - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, NULL); + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = ioport; + + rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); if ( rc ) return rc; if ( access ) return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, - RESOURCE__USE, NULL); + RESOURCE__USE, &ad); else return rc; } @@ -1081,6 +1093,7 @@ u32 rsid; int rc = -EPERM; struct domain_security_struct *ssec, *tsec; + struct avc_audit_data ad; rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD); if ( rc ) @@ -1090,13 +1103,15 @@ if ( rc ) return rc; + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = (unsigned long) machine_bdf; ssec = current->domain->ssid; - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, NULL); + rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, &ad); if ( rc ) return rc; tsec = d->ssid; - return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, NULL); + return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } static int flask_deassign_device(struct domain *d, uint32_t machine_bdf) diff -r 8ca4e32583b6 xen/xsm/flask/include/avc.h --- a/xen/xsm/flask/include/avc.h Fri Oct 23 10:15:17 2009 +0100 +++ b/xen/xsm/flask/include/avc.h Fri Oct 23 11:41:41 2009 -0400 @@ -38,11 +38,9 @@ /* Auxiliary data to use in generating the audit record. */ struct avc_audit_data { char type; -#define AVC_AUDIT_DATA_FS 1 -#define AVC_AUDIT_DATA_NET 2 -#define AVC_AUDIT_DATA_CAP 3 -#define AVC_AUDIT_DATA_IPC 4 +#define AVC_AUDIT_DATA_DEV 1 struct domain *d; + unsigned long device; }; #define v4info fam.v4 diff -r 8ca4e32583b6 xen/xsm/flask/ss/policydb.c --- a/xen/xsm/flask/ss/policydb.c Fri Oct 23 10:15:17 2009 +0100 +++ b/xen/xsm/flask/ss/policydb.c Fri Oct 23 11:41:41 2009 -0400 @@ -1773,10 +1773,13 @@ goto bad; } policydb_str[len] = 0; - if ( strcmp(policydb_str, POLICYDB_STRING) ) + if ( strcmp(policydb_str, POLICYDB_STRING) == 0 ) + p->target_type = TARGET_XEN; + else if ( strcmp(policydb_str, POLICYDB_STRING_OLD) == 0 ) + p->target_type = TARGET_XEN_OLD; + else { - printk(KERN_ERR "Flask: policydb string %s does not match " - "my string %s\n", policydb_str, POLICYDB_STRING); + printk(KERN_ERR "Flask: %s not a valid policydb string", policydb_str); xfree(policydb_str); goto bad; } @@ -1988,6 +1991,68 @@ if ( rc ) goto bad; break; + case OCON_PIRQ: + if ( p->target_type != TARGET_XEN ) + { + printk(KERN_ERR + "Old xen policy does not support pirqcon"); + goto bad; + } + rc = next_entry(buf, fp, sizeof(u32)); + if ( rc < 0 ) + goto bad; + c->u.pirq = le32_to_cpu(buf[0]); + rc = context_read_and_validate(&c->context[0], p, fp); + if ( rc ) + goto bad; + break; + case OCON_IOPORT: + if ( p->target_type != TARGET_XEN ) + { + printk(KERN_ERR + "Old xen policy does not support ioportcon"); + goto bad; + } + rc = next_entry(buf, fp, sizeof(u32) *2); + if ( rc < 0 ) + goto bad; + c->u.ioport.low_ioport = le32_to_cpu(buf[0]); + c->u.ioport.high_ioport = le32_to_cpu(buf[1]); + rc = context_read_and_validate(&c->context[0], p, fp); + if ( rc ) + goto bad; + break; + case OCON_IOMEM: + if ( p->target_type != TARGET_XEN ) + { + printk(KERN_ERR + "Old xen policy does not support iomemcon"); + goto bad; + } + rc = next_entry(buf, fp, sizeof(u32) *2); + if ( rc < 0 ) + goto bad; + c->u.iomem.low_iomem = le32_to_cpu(buf[0]); + c->u.iomem.high_iomem = le32_to_cpu(buf[1]); + rc = context_read_and_validate(&c->context[0], p, fp); + if ( rc ) + goto bad; + break; + case OCON_DEVICE: + if ( p->target_type != TARGET_XEN ) + { + printk(KERN_ERR + "Old xen policy does not support pcidevicecon"); + goto bad; + } + rc = next_entry(buf, fp, sizeof(u32)); + if ( rc < 0 ) + goto bad; + c->u.device = le32_to_cpu(buf[0]); + rc = context_read_and_validate(&c->context[0], p, fp); + if ( rc ) + goto bad; + break; default: printk(KERN_ERR "Flask: unsupported object context config data\n"); diff -r 8ca4e32583b6 xen/xsm/flask/ss/policydb.h --- a/xen/xsm/flask/ss/policydb.h Fri Oct 23 10:15:17 2009 +0100 +++ b/xen/xsm/flask/ss/policydb.h Fri Oct 23 11:41:41 2009 -0400 @@ -147,10 +147,16 @@ struct ocontext { union { char *name; /* name of initial SID, fs, netif, fstype, path */ - int pirq; - u32 ioport; - unsigned long iomem; + u16 pirq; u32 device; + struct { + u32 low_ioport; + u32 high_ioport; + } ioport; + struct { + u32 low_iomem; + u32 high_iomem; + } iomem; } u; struct context context[2]; /* security context(s) */ u32 sid[2]; /* SID(s) */ @@ -174,9 +180,7 @@ #define OCON_IOPORT 2 /* io ports */ #define OCON_IOMEM 3 /* io memory */ #define OCON_DEVICE 4 /* pci devices */ -#define OCON_DUMMY1 5 /* reserved */ -#define OCON_DUMMY2 6 /* reserved */ -#define OCON_NUM 7 +#define OCON_NUM 5 /* The policy database */ struct policydb { @@ -239,6 +243,8 @@ struct ebitmap permissive_map; unsigned int policyvers; + + u16 target_type; }; extern void policydb_destroy(struct policydb *p); @@ -257,7 +263,10 @@ #define OBJECT_R_VAL 1 #define POLICYDB_MAGIC FLASK_MAGIC -#define POLICYDB_STRING "SE Linux" +#define POLICYDB_STRING "XenFlask" +#define POLICYDB_STRING_OLD "SE Linux" +#define TARGET_XEN 1 +#define TARGET_XEN_OLD 0 struct policy_file { char *data; diff -r 8ca4e32583b6 xen/xsm/flask/ss/services.c --- a/xen/xsm/flask/ss/services.c Fri Oct 23 10:15:17 2009 +0100 +++ b/xen/xsm/flask/ss/services.c Fri Oct 23 11:41:41 2009 -0400 @@ -1569,7 +1569,7 @@ c = policydb.ocontexts[OCON_IOMEM]; while ( c ) { - if ( c->u.iomem == mfn ) + if ( c->u.iomem.low_iomem <= mfn && c->u.iomem.high_iomem >= mfn ) break; c = c->next; } @@ -1609,7 +1609,8 @@ c = policydb.ocontexts[OCON_IOPORT]; while ( c ) { - if ( c->u.ioport == ioport ) + if ( c->u.ioport.low_ioport <= ioport && + c->u.ioport.high_ioport >= ioport ) break; c = c->next; } @@ -1635,8 +1636,8 @@ } /** - * security_ioport_sid - Obtain the SID for an ioport. - * @ioport: ioport + * security_device_sid - Obtain the SID for a PCI device. + * @ioport: device * @out_sid: security identifier */ int security_device_sid(u32 device, u32 *out_sid)