# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1256647977 0
# Node ID c4958b2edaa5f113da8e1dc4c7dac751bf43a7ac
# Parent 2489f766fa68e21cb693f375765bd8b907651209
xsm: Add support for Xen device policies
Add support for Xen ocontext records to enable device polices. The
default policy will not be changed and instructions have been added to
enable the new functionality. Examples on how to use the new policy
language have been added but commented out. The newest version of
checkpolicy (>= 2.0.20) and libsepol (>= 2.0.39) is needed in order to
compile it. Devices can be labeled and enforced using the following
new commands; pirqcon, iomemcon, ioportcon and pcidevicecon.
Signed-off-by : George Coker <gscoker@xxxxxxxxxxxxxx>
Signed-off-by : Paul Nuzzi <pjnuzzi@xxxxxxxxxxxxxx>
---
docs/misc/xsm-flask.txt | 64 +++++++++++++++++++++++
tools/flask/policy/Makefile | 16 +++++
tools/flask/policy/policy/modules/xen/xen.if | 31 +++++++++++
tools/flask/policy/policy/modules/xen/xen.te | 35 ++++++++++++
xen/xsm/flask/avc.c | 2
xen/xsm/flask/hooks.c | 31 ++++++++---
xen/xsm/flask/include/avc.h | 6 --
xen/xsm/flask/ss/policydb.c | 73 +++++++++++++++++++++++++--
xen/xsm/flask/ss/policydb.h | 23 +++++---
xen/xsm/flask/ss/services.c | 9 +--
10 files changed, 262 insertions(+), 28 deletions(-)
diff -r 2489f766fa68 -r c4958b2edaa5 docs/misc/xsm-flask.txt
--- a/docs/misc/xsm-flask.txt Tue Oct 27 12:52:14 2009 +0000
+++ b/docs/misc/xsm-flask.txt Tue Oct 27 12:52:57 2009 +0000
@@ -168,6 +168,70 @@ often lead to adding parameterized rules
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 2489f766fa68 -r c4958b2edaa5 tools/flask/policy/Makefile
--- a/tools/flask/policy/Makefile Tue Oct 27 12:52:14 2009 +0000
+++ b/tools/flask/policy/Makefile Tue Oct 27 12:52:57 2009 +0000
@@ -149,6 +149,8 @@ load: tmp/load
$(POLVER): policy.conf
@echo "Compiling $(NAME) $(POLVER)"
$(QUIET) $(CHECKPOLICY) $^ -o $@
+# Uncomment line below to enable policies for devices
+# $(QUIET) $(CHECKPOLICY) -t Xen $^ -o $@
########################################
#
@@ -157,6 +159,8 @@ load: tmp/load
$(LOADPATH): policy.conf
@echo "Compiling and installing $(NAME) $(LOADPATH)"
$(QUIET) $(CHECKPOLICY) $^ -o $@
+# Uncomment line below to enable policies for devices
+# $(QUIET) $(CHECKPOLICY) -t Xen $^ -o $@
########################################
#
@@ -206,8 +210,18 @@ tmp/all_attrs_types.conf tmp/only_te_rul
$(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 2489f766fa68 -r c4958b2edaa5
tools/flask/policy/policy/modules/xen/xen.if
--- a/tools/flask/policy/policy/modules/xen/xen.if Tue Oct 27 12:52:14
2009 +0000
+++ b/tools/flask/policy/policy/modules/xen/xen.if Tue Oct 27 12:52:57
2009 +0000
@@ -60,3 +60,34 @@ define(`create_channel', `
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 2489f766fa68 -r c4958b2edaa5
tools/flask/policy/policy/modules/xen/xen.te
--- a/tools/flask/policy/policy/modules/xen/xen.te Tue Oct 27 12:52:14
2009 +0000
+++ b/tools/flask/policy/policy/modules/xen/xen.te Tue Oct 27 12:52:57
2009 +0000
@@ -76,6 +76,41 @@ allow dom0_t domU_t:grant {copy};
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 2489f766fa68 -r c4958b2edaa5 xen/xsm/flask/avc.c
--- a/xen/xsm/flask/avc.c Tue Oct 27 12:52:14 2009 +0000
+++ b/xen/xsm/flask/avc.c Tue Oct 27 12:52:57 2009 +0000
@@ -566,6 +566,8 @@ void avc_audit(u32 ssid, u32 tsid, u16 t
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 2489f766fa68 -r c4958b2edaa5 xen/xsm/flask/hooks.c
--- a/xen/xsm/flask/hooks.c Tue Oct 27 12:52:14 2009 +0000
+++ b/xen/xsm/flask/hooks.c Tue Oct 27 12:52:57 2009 +0000
@@ -649,6 +649,7 @@ static int irq_has_perm(struct domain *d
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 @@ static int irq_has_perm(struct domain *d
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 @@ static int iomem_has_perm(struct domain
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 @@ static int iomem_has_perm(struct domain
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 @@ static int ioport_has_perm(struct domain
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 @@ static int ioport_has_perm(struct domain
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 @@ static int flask_assign_device(struct do
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 @@ static int flask_assign_device(struct do
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 2489f766fa68 -r c4958b2edaa5 xen/xsm/flask/include/avc.h
--- a/xen/xsm/flask/include/avc.h Tue Oct 27 12:52:14 2009 +0000
+++ b/xen/xsm/flask/include/avc.h Tue Oct 27 12:52:57 2009 +0000
@@ -38,11 +38,9 @@ struct sk_buff;
/* 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 2489f766fa68 -r c4958b2edaa5 xen/xsm/flask/ss/policydb.c
--- a/xen/xsm/flask/ss/policydb.c Tue Oct 27 12:52:14 2009 +0000
+++ b/xen/xsm/flask/ss/policydb.c Tue Oct 27 12:52:57 2009 +0000
@@ -1773,10 +1773,13 @@ int policydb_read(struct policydb *p, vo
goto bad;
}
policydb_str[len] = 0;
- if ( strcmp(policydb_str, POLICYDB_STRING) )
- {
- printk(KERN_ERR "Flask: policydb string %s does not match "
- "my string %s\n", 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: %s not a valid policydb string", policydb_str);
xfree(policydb_str);
goto bad;
}
@@ -1984,6 +1987,68 @@ int policydb_read(struct policydb *p, vo
if ( rc < 0 )
goto bad;
c->sid[0] = le32_to_cpu(buf[0]);
+ rc = context_read_and_validate(&c->context[0], p, fp);
+ 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;
diff -r 2489f766fa68 -r c4958b2edaa5 xen/xsm/flask/ss/policydb.h
--- a/xen/xsm/flask/ss/policydb.h Tue Oct 27 12:52:14 2009 +0000
+++ b/xen/xsm/flask/ss/policydb.h Tue Oct 27 12:52:57 2009 +0000
@@ -147,10 +147,16 @@ struct ocontext {
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 @@ struct ocontext {
#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 policydb {
struct ebitmap permissive_map;
unsigned int policyvers;
+
+ u16 target_type;
};
extern void policydb_destroy(struct policydb *p);
@@ -257,7 +263,10 @@ extern int policydb_read(struct policydb
#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 2489f766fa68 -r c4958b2edaa5 xen/xsm/flask/ss/services.c
--- a/xen/xsm/flask/ss/services.c Tue Oct 27 12:52:14 2009 +0000
+++ b/xen/xsm/flask/ss/services.c Tue Oct 27 12:52:57 2009 +0000
@@ -1569,7 +1569,7 @@ int security_iomem_sid(unsigned long mfn
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 @@ int security_ioport_sid(u32 ioport, u32
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 @@ out:
}
/**
- * 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)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|