* [PATCH] libsepol/checkpolicy: Add support for multiple target OSes
@ 2009-09-14 13:22 pjnuzzi
2009-09-14 19:07 ` Joshua Brindle
0 siblings, 1 reply; 6+ messages in thread
From: pjnuzzi @ 2009-09-14 13:22 UTC (permalink / raw)
To: selinux
Add support for multiple target OSes to libsepol and checkpolicy, where
the particular target OS is selected using a new -t target option to
checkpolicy. The default target remains SELinux. A new target and
support is introduced for Xen. The target OS is identified in the
policy image by using different policy string identifiers in the header.
At present, policy string identifiers are required to have the same
length for ease of parsing the header and to preserve file(1) parsing of
subsequent fields after the string identifier. For SELinux, the string
identifier remains "SE Linux". For Xen, the string identifier is
"XenFlask". The latent support for just "Flask" in the policy reading
code that was introduced for FMAC is dropped; a separate identifier for
Solaris (e.g. "SolFlask") will be introduced later using this new target
mechanism if needed. The same support can easily be extended for other
OSes.
Based on the selected target, the source and binary policies may be
parsed differently. For SELinux vs. Xen, the current difference is the
interpretation of object context records. New object context records
for object contexts for pirqs, iomem ranges, ioport ranges, and pci
devices are enabled if building for the Xen target. The SELinux object
context records other than initial SIDs are disabled if building for the
Xen target. checkpolicy will generate an error if an attempt is made to
build a policy that has invalid object context records for the selected
target, and libsepol will likewise reject a binary policy if its object
context records are invalid for the target identified by its string
identifier.
No changes are required to the SELinux kernel code to support this
change; the SELinux kernel will continue to accept only policies with
the "SE Linux" identifier. A patch for the Xen Flask module will be
submitted after this patch to enable it to accept policies built with
either string identifier (for compatibility with existing policies),
where the new object context record support will only be enabled if the
policy was built for the Xen target.
Support for selecting the target platform for libsemanage will be added
later.
Signed-off-by: Paul Nuzzi <pjnuzzi@tycho.ncsc.mil>
---
checkpolicy/checkpolicy.c | 20 +-
checkpolicy/policy_define.c | 262 +++++++++++++++++++++++++++++
checkpolicy/policy_define.h | 4
checkpolicy/policy_parse.y | 29 +++
checkpolicy/policy_scan.l | 10 -
libsepol/include/sepol/policydb/policydb.h | 28 ++-
libsepol/src/expand.c | 85 ++++++++-
libsepol/src/policydb.c | 178 ++++++++++++++++---
libsepol/src/policydb_internal.h | 1
libsepol/src/write.c | 90 +++++++++
sepolgen/src/sepolgen/refparser.py | 54 +++++
sepolgen/src/sepolgen/refpolicy.py | 35 +++
12 files changed, 755 insertions(+), 41 deletions(-)
diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index d7772d5..76d8ed3 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -100,7 +100,9 @@ unsigned int policyvers = POLICYDB_VERSION_MAX;
void usage(char *progname)
{
printf
- ("usage: %s [-b] [-d] [-U handle_unknown (allow,deny,reject) [-M] [-c policyvers (%d-%d)] [-o output_file] [input_file]\n",
+ ("usage: %s [-b] [-d] [-U handle_unknown (allow,deny,reject) [-M]"
+ "[-c policyvers (%d-%d)] [-o output_file] [-t platform]"
+ "[input_file]\n",
progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
exit(1);
}
@@ -381,7 +383,7 @@ int main(int argc, char **argv)
unsigned int protocol, port;
unsigned int binary = 0, debug = 0;
struct val_to_name v;
- int ret, ch, fd;
+ int ret, ch, fd, target = SEPOL_TARGET_SELINUX;
unsigned int nel, uret;
struct stat sb;
void *map;
@@ -391,11 +393,22 @@ int main(int argc, char **argv)
int show_version = 0;
struct policy_file pf;
- while ((ch = getopt(argc, argv, "o:dbU:MVc:")) != EOF) {
+ while ((ch = getopt(argc, argv, "o:t:dbU:MVc:")) != EOF) {
switch (ch) {
case 'o':
outfile = optarg;
break;
+ case 't':
+ if (!strcasecmp(optarg, "Xen"))
+ target = SEPOL_TARGET_XEN;
+ else if (!strcasecmp(optarg, "SELinux"))
+ target = SEPOL_TARGET_SELINUX;
+ else{
+ fprintf(stderr, "%s: Unknown target platform:"
+ "%s\n", argv[0], optarg);
+ exit(1);
+ }
+ break;
case 'b':
binary = 1;
file = binfile;
@@ -528,6 +541,7 @@ int main(int argc, char **argv)
exit(1);
/* We build this as a base policy first since that is all the parser understands */
parse_policy.policy_type = POLICY_BASE;
+ policydb_set_target_platform(&parse_policy, target);
/* Let sepol know if we are dealing with MLS support */
parse_policy.mls = mlspol;
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 17b84ce..1e19bda 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -3372,12 +3372,254 @@ int define_fs_context(unsigned int major, unsigned int minor)
return 0;
}
+int define_pirq_context(unsigned int pirq)
+{
+ ocontext_t *newc, *c, *l, *head;
+ char *id;
+
+ if (policydbp->target_type != SEPOL_TARGET_XEN) {
+ yyerror("pirqcon only supported for target Xen");
+ return -1;
+ }
+
+ if (pass == 1) {
+ id = (char *) queue_remove(id_queue);
+ free(id);
+ parse_security_context(NULL);
+ return 0;
+ }
+
+ newc = malloc(sizeof(ocontext_t));
+ if (!newc) {
+ yyerror("out of memory");
+ return -1;
+ }
+ memset(newc, 0, sizeof(ocontext_t));
+
+ newc->u.pirq = pirq;
+
+ if (parse_security_context(&newc->context[0])) {
+ free(newc);
+ return -1;
+ }
+
+ head = policydbp->ocontexts[OCON_PIRQ];
+ for (l = NULL, c = head; c; l = c, c = c->next) {
+ unsigned int pirq2;
+
+ pirq2 = c->u.pirq;
+ if (pirq == pirq2) {
+ yyerror2("duplicate pirqcon entry for %d ", pirq);
+ goto bad;
+ }
+ }
+
+ if (l)
+ l->next = newc;
+ else
+ policydbp->ocontexts[OCON_PIRQ] = newc;
+
+ return 0;
+
+bad:
+ free(newc);
+ return -1;
+}
+
+int define_iomem_context(unsigned long low, unsigned long high)
+{
+ ocontext_t *newc, *c, *l, *head;
+ char *id;
+
+ if (policydbp->target_type != SEPOL_TARGET_XEN) {
+ yyerror("iomemcon only supported for target Xen");
+ return -1;
+ }
+
+ if (pass == 1) {
+ id = (char *)queue_remove(id_queue);
+ free(id);
+ parse_security_context(NULL);
+ return 0;
+ }
+
+ newc = malloc(sizeof(ocontext_t));
+ if (!newc) {
+ yyerror("out of memory");
+ return -1;
+ }
+ memset(newc, 0, sizeof(ocontext_t));
+
+ newc->u.iomem.low_iomem = low;
+ newc->u.iomem.high_iomem = high;
+
+ if (low > high) {
+ yyerror2("low memory 0x%x exceeds high memory 0x%x", low, high);
+ free(newc);
+ return -1;
+ }
+
+ if (parse_security_context(&newc->context[0])) {
+ free(newc);
+ return -1;
+ }
+
+ head = policydbp->ocontexts[OCON_IOMEM];
+ for (l = NULL, c = head; c; l = c, c = c->next) {
+ unsigned int low2, high2;
+
+ low2 = c->u.iomem.low_iomem;
+ high2 = c->u.iomem.high_iomem;
+ if (low <= high2 && low2 <= high) {
+ yyerror2("iomemcon entry for 0x%x-0x%x overlaps with "
+ "earlier entry 0x%x-0x%x", low, high,
+ low2, high2);
+ goto bad;
+ }
+ }
+
+ if (l)
+ l->next = newc;
+ else
+ policydbp->ocontexts[OCON_IOMEM] = newc;
+
+ return 0;
+
+bad:
+ free(newc);
+ return -1;
+}
+
+int define_ioport_context(unsigned long low, unsigned long high)
+{
+ ocontext_t *newc, *c, *l, *head;
+ char *id;
+
+ if (policydbp->target_type != SEPOL_TARGET_XEN) {
+ yyerror("ioportcon only supported for target Xen");
+ return -1;
+ }
+
+ if (pass == 1) {
+ id = (char *)queue_remove(id_queue);
+ free(id);
+ parse_security_context(NULL);
+ return 0;
+ }
+
+ newc = malloc(sizeof(ocontext_t));
+ if (!newc) {
+ yyerror("out of memory");
+ return -1;
+ }
+ memset(newc, 0, sizeof(ocontext_t));
+
+ newc->u.ioport.low_ioport = low;
+ newc->u.ioport.high_ioport = high;
+
+ if (low > high) {
+ yyerror2("low ioport 0x%x exceeds high ioport 0x%x", low, high);
+ free(newc);
+ return -1;
+ }
+
+ if (parse_security_context(&newc->context[0])) {
+ free(newc);
+ return -1;
+ }
+
+ head = policydbp->ocontexts[OCON_IOPORT];
+ for (l = NULL, c = head; c; l = c, c = c->next) {
+ unsigned int low2, high2;
+
+ low2 = c->u.ioport.low_ioport;
+ high2 = c->u.ioport.high_ioport;
+ if (low <= high2 && low2 <= high) {
+ yyerror2("ioportcon entry for 0x%x-0x%x overlaps with"
+ "earlier entry 0x%x-0x%x", low, high,
+ low2, high2);
+ goto bad;
+ }
+ }
+
+ if (l)
+ l->next = newc;
+ else
+ policydbp->ocontexts[OCON_IOPORT] = newc;
+
+ return 0;
+
+bad:
+ free(newc);
+ return -1;
+}
+
+int define_pcidevice_context(unsigned long device)
+{
+ ocontext_t *newc, *c, *l, *head;
+ char *id;
+
+ if (policydbp->target_type != SEPOL_TARGET_XEN) {
+ yyerror("pcidevicecon only supported for target Xen");
+ return -1;
+ }
+
+ if (pass == 1) {
+ id = (char *) queue_remove(id_queue);
+ free(id);
+ parse_security_context(NULL);
+ return 0;
+ }
+
+ newc = malloc(sizeof(ocontext_t));
+ if (!newc) {
+ yyerror("out of memory");
+ return -1;
+ }
+ memset(newc, 0, sizeof(ocontext_t));
+
+ newc->u.device = device;
+
+ if (parse_security_context(&newc->context[0])) {
+ free(newc);
+ return -1;
+ }
+
+ head = policydbp->ocontexts[OCON_DEVICE];
+ for (l = NULL, c = head; c; l = c, c = c->next) {
+ unsigned int device2;
+
+ device2 = c->u.device;
+ if (device == device2) {
+ yyerror2("duplicate pcidevicecon entry for 0x%x ",
+ device);
+ goto bad;
+ }
+ }
+
+ if (l)
+ l->next = newc;
+ else
+ policydbp->ocontexts[OCON_DEVICE] = newc;
+
+ return 0;
+
+bad:
+ free(newc);
+ return -1;
+}
+
int define_port_context(unsigned int low, unsigned int high)
{
ocontext_t *newc, *c, *l, *head;
unsigned int protocol;
char *id;
+ if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
+ yyerror("portcon only supported for target SELinux");
+ return -1;
+ }
+
if (pass == 1) {
id = (char *)queue_remove(id_queue);
free(id);
@@ -3460,6 +3702,11 @@ int define_netif_context(void)
{
ocontext_t *newc, *c, *head;
+ if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
+ yyerror("netifcon only supported for target SELinux");
+ return -1;
+ }
+
if (pass == 1) {
free(queue_remove(id_queue));
parse_security_context(NULL);
@@ -3516,6 +3763,11 @@ int define_ipv4_node_context()
struct in_addr addr, mask;
ocontext_t *newc, *c, *l, *head;
+ if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
+ yyerror("nodecon only supported for target SELinux");
+ return -1;
+ }
+
if (pass == 1) {
free(queue_remove(id_queue));
free(queue_remove(id_queue));
@@ -3597,6 +3849,11 @@ int define_ipv6_node_context(void)
struct in6_addr addr, mask;
ocontext_t *newc, *c, *l, *head;
+ if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
+ yyerror("nodecon only supported by target SELinux");
+ return -1;
+ }
+
if (pass == 1) {
free(queue_remove(id_queue));
free(queue_remove(id_queue));
@@ -3677,6 +3934,11 @@ int define_fs_use(int behavior)
{
ocontext_t *newc, *c, *head;
+ if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
+ yyerror("unsupported target");
+ return -1;
+ }
+
if (pass == 1) {
free(queue_remove(id_queue));
parse_security_context(NULL);
diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
index b5a972e..5ac6667 100644
--- a/checkpolicy/policy_define.h
+++ b/checkpolicy/policy_define.h
@@ -39,6 +39,10 @@ int define_netif_context(void);
int define_permissive(void);
int define_polcap(void);
int define_port_context(unsigned int low, unsigned int high);
+int define_pirq_context(unsigned int pirq);
+int define_iomem_context(unsigned long low, unsigned long high);
+int define_ioport_context(unsigned long low, unsigned long high);
+int define_pcidevice_context(unsigned long device);
int define_range_trans(int class_specified);
int define_role_allow(void);
int define_role_trans(void);
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index 5ca7101..8d1bc37 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -123,6 +123,7 @@ typedef int (* require_func_t)();
%token TARGET
%token SAMEUSER
%token FSCON PORTCON NETIFCON NODECON
+%token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON
%token FSUSEXATTR FSUSETASK FSUSETRANS
%token GENFSCON
%token U1 U2 U3 R1 R2 R3 T1 T2 T3 L1 L2 H1 H2
@@ -154,7 +155,7 @@ base_policy : { if (define_policy(pass, 0) == -1) return -1; }
opt_mls te_rbac users opt_constraints
{ if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;}
else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1;}}
- initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts
+ initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts
;
classes : class_def
| classes class_def
@@ -562,6 +563,32 @@ initial_sid_contexts : initial_sid_context_def
initial_sid_context_def : SID identifier security_context_def
{if (define_initial_sid_context()) return -1;}
;
+opt_dev_contexts : dev_contexts |
+ ;
+dev_contexts : dev_context_def
+ | dev_contexts dev_context_def
+ ;
+dev_context_def : pirq_context_def |
+ iomem_context_def |
+ ioport_context_def |
+ pci_context_def
+ ;
+pirq_context_def : PIRQCON number security_context_def
+ {if (define_pirq_context($2)) return -1;}
+ ;
+iomem_context_def : IOMEMCON number security_context_def
+ {if (define_iomem_context($2,$2)) return -1;}
+ | IOMEMCON number '-' number security_context_def
+ {if (define_iomem_context($2,$4)) return -1;}
+ ;
+ioport_context_def : IOPORTCON number security_context_def
+ {if (define_ioport_context($2,$2)) return -1;}
+ | IOPORTCON number '-' number security_context_def
+ {if (define_ioport_context($2,$4)) return -1;}
+ ;
+pci_context_def : PCIDEVICECON number security_context_def
+ {if (define_pcidevice_context($2)) return -1;}
+ ;
opt_fs_contexts : fs_contexts
|
;
diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
index b55c659..48128a8 100644
--- a/checkpolicy/policy_scan.l
+++ b/checkpolicy/policy_scan.l
@@ -169,6 +169,14 @@ netifcon |
NETIFCON { return(NETIFCON);}
nodecon |
NODECON { return(NODECON);}
+pirqcon |
+PIRQCON { return(PIRQCON);}
+iomemcon |
+IOMEMCON { return(IOMEMCON);}
+ioportcon |
+IOPORTCON { return(IOPORTCON);}
+pcidevicecon |
+PCIDEVICECON { return(PCIDEVICECON);}
fs_use_xattr |
FS_USE_XATTR { return(FSUSEXATTR);}
fs_use_task |
@@ -209,7 +217,7 @@ permissive |
PERMISSIVE { return(PERMISSIVE); }
"/"({alnum}|[_\.\-/])* { return(PATH); }
{letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))* { return(IDENTIFIER); }
-{digit}+ { return(NUMBER); }
+{digit}+|0x{hexval}+ { return(NUMBER); }
{digit}{1,3}(\.{digit}{1,3}){3} { return(IPV4_ADDR); }
{hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])* { return(IPV6_ADDR); }
{digit}+(\.({alnum}|[_.])*)? { return(VERSION_IDENTIFIER); }
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 0105cf4..2013238 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -276,6 +276,16 @@ typedef struct ocontext {
uint32_t addr[4]; /* network order */
uint32_t mask[4]; /* network order */
} node6; /* IPv6 node information */
+ uint32_t device;
+ uint16_t pirq;
+ struct {
+ uint32_t low_iomem;
+ uint32_t high_iomem;
+ } iomem;
+ struct {
+ uint32_t low_ioport;
+ uint32_t high_ioport;
+ } ioport;
} u;
union {
uint32_t sclass; /* security class for genfs */
@@ -313,6 +323,17 @@ typedef struct genfs {
#define OCON_NODE6 6 /* IPv6 nodes */
#define OCON_NUM 7
+/* object context array indices for Xen */
+#define OCON_ISID 0 /* initial SIDs */
+#define OCON_PIRQ 1 /* physical irqs */
+#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
+
+
/* section: module information */
/* scope_index_t holds all of the symbols that are in scope in a
@@ -400,6 +421,7 @@ typedef struct policydb {
uint32_t policy_type;
char *name;
char *version;
+ uint32_t target_type;
/* Set when the policydb is modified such that writing is unsupported */
int unsupported_format;
@@ -593,6 +615,7 @@ extern int avrule_read_list(policydb_t * p, avrule_t ** avrules,
struct policy_file *fp);
extern int policydb_write(struct policydb *p, struct policy_file *pf);
+extern int policydb_set_target_platform(policydb_t *p, int platform);
#define PERM_SYMTAB_SIZE 32
@@ -651,9 +674,12 @@ extern int policydb_write(struct policydb *p, struct policy_file *pf);
#define POLICYDB_MAGIC SELINUX_MAGIC
#define POLICYDB_STRING "SE Linux"
-#define POLICYDB_ALT_STRING "Flask"
+#define POLICYDB_XEN_STRING "XenFlask"
#define POLICYDB_MOD_MAGIC SELINUX_MOD_MAGIC
#define POLICYDB_MOD_STRING "SE Linux Module"
+#define SEPOL_TARGET_SELINUX 0
+#define SEPOL_TARGET_XEN 1
+
#endif /* _POLICYDB_H_ */
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index e9cd986..38e2481 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -1819,9 +1819,9 @@ static int context_copy(context_struct_t * dst, context_struct_t * src,
return mls_context_cpy(dst, src);
}
-static int ocontext_copy(expand_state_t * state)
+static int ocontext_copy_xen(expand_state_t *state)
{
- unsigned int i, j;
+ unsigned int i;
ocontext_t *c, *n, *l;
for (i = 0; i < OCON_NUM; i++) {
@@ -1833,11 +1833,63 @@ static int ocontext_copy(expand_state_t * state)
return -1;
}
memset(n, 0, sizeof(ocontext_t));
- if (l) {
+ if (l)
l->next = n;
- } else {
+ else
state->out->ocontexts[i] = n;
+ l = n;
+ if (context_copy(&n->context[0], &c->context[0],
+ state)) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
+ }
+ switch (i) {
+ case OCON_ISID:
+ n->sid[0] = c->sid[0];
+ break;
+ case OCON_PIRQ:
+ n->u.pirq = c->u.pirq;
+ break;
+ case OCON_IOPORT:
+ n->u.ioport.low_ioport = c->u.ioport.low_ioport;
+ n->u.ioport.high_ioport =
+ c->u.ioport.high_ioport;
+ break;
+ case OCON_IOMEM:
+ n->u.iomem.low_iomem = c->u.iomem.low_iomem;
+ n->u.iomem.high_iomem = c->u.iomem.high_iomem;
+ break;
+ case OCON_DEVICE:
+ n->u.device = c->u.device;
+ break;
+ default:
+ /* shouldn't get here */
+ ERR(state->handle, "Unknown ocontext");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int ocontext_copy_selinux(expand_state_t *state)
+{
+ unsigned int i, j;
+ ocontext_t *c, *n, *l;
+
+ for (i = 0; i < OCON_NUM; i++) {
+ l = NULL;
+ for (c = state->base->ocontexts[i]; c; c = c->next) {
+ n = malloc(sizeof(ocontext_t));
+ if (!n) {
+ ERR(state->handle, "Out of memory!");
+ return -1;
}
+ memset(n, 0, sizeof(ocontext_t));
+ if (l)
+ l->next = n;
+ else
+ state->out->ocontexts[i] = n;
l = n;
if (context_copy(&n->context[0], &c->context[0], state)) {
ERR(state->handle, "Out of memory!");
@@ -1885,13 +1937,31 @@ static int ocontext_copy(expand_state_t * state)
break;
default:
/* shouldn't get here */
- assert(0);
+ ERR(state->handle, "Unknown ocontext");
+ return -1;
}
}
}
return 0;
}
+static int ocontext_copy(expand_state_t *state, uint32_t target)
+{
+ int rc = -1;
+ switch (target) {
+ case SEPOL_TARGET_SELINUX:
+ rc = ocontext_copy_selinux(state);
+ break;
+ case SEPOL_TARGET_XEN:
+ rc = ocontext_copy_xen(state);
+ break;
+ default:
+ ERR(state->handle, "Unknown target");
+ return -1;
+ }
+ return rc;
+}
+
static int genfs_copy(expand_state_t * state)
{
ocontext_t *c, *newc, *l;
@@ -2418,6 +2488,9 @@ int expand_module(sepol_handle_t * handle,
out->mls = base->mls;
out->handle_unknown = base->handle_unknown;
+ /* Copy target from base to out */
+ out->target_type = base->target_type;
+
/* Copy policy capabilities */
if (ebitmap_cpy(&out->policycaps, &base->policycaps)) {
ERR(handle, "Out of memory!");
@@ -2576,7 +2649,7 @@ int expand_module(sepol_handle_t * handle,
evaluate_conds(state.out);
/* copy ocontexts */
- if (ocontext_copy(&state))
+ if (ocontext_copy(&state, out->target_type))
goto cleanup;
/* copy genfs */
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 85ddefc..a66a007 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -54,6 +54,9 @@
#include "debug.h"
#include "mls.h"
+#define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings)
+char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
+
/* These need to be updated if SYM_NUM or OCON_NUM changes */
static struct policydb_compat_info policydb_compat[] = {
{
@@ -1079,9 +1082,13 @@ void policydb_destroy(policydb_t * p)
c = c->next;
context_destroy(&ctmp->context[0]);
context_destroy(&ctmp->context[1]);
- if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF
- || i == OCON_FSUSE)
+ if (i == OCON_ISID)
+ free(ctmp->u.name);
+ if (p->target_type == SEPOL_TARGET_SELINUX &&
+ (i == OCON_FS || i == OCON_NETIF ||
+ i == OCON_FSUSE))
free(ctmp->u.name);
+
free(ctmp);
}
}
@@ -2102,7 +2109,88 @@ int role_allow_read(role_allow_t ** r, struct policy_file *fp)
return 0;
}
-static int ocontext_read(struct policydb_compat_info *info,
+static int ocontext_read_xen(struct policydb_compat_info *info,
+ policydb_t *p, struct policy_file *fp)
+{
+ unsigned int i, j;
+ size_t nel;
+ ocontext_t *l, *c;
+ uint32_t buf[8];
+ int rc;
+
+ for (i = 0; i < info->ocon_num; i++) {
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ nel = le32_to_cpu(buf[0]);
+ l = NULL;
+ for (j = 0; j < nel; j++) {
+ c = calloc(1, sizeof(ocontext_t));
+ if (!c)
+ return -1;
+ if (l)
+ l->next = c;
+ else
+ p->ocontexts[i] = c;
+ l = c;
+ switch (i) {
+ case OCON_ISID:
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ c->sid[0] = le32_to_cpu(buf[0]);
+ if (context_read_and_validate
+ (&c->context[0], p, fp))
+ return -1;
+ break;
+ case OCON_PIRQ:
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ c->u.pirq = le32_to_cpu(buf[0]);
+ if (context_read_and_validate
+ (&c->context[0], p, fp))
+ return -1;
+ break;
+ case OCON_IOPORT:
+ rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
+ if (rc < 0)
+ return -1;
+ c->u.ioport.low_ioport = le32_to_cpu(buf[0]);
+ c->u.ioport.high_ioport = le32_to_cpu(buf[1]);
+ if (context_read_and_validate
+ (&c->context[0], p, fp))
+ return -1;
+ break;
+ case OCON_IOMEM:
+ rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
+ if (rc < 0)
+ return -1;
+ c->u.iomem.low_iomem = le32_to_cpu(buf[0]);
+ c->u.iomem.high_iomem = le32_to_cpu(buf[1]);
+ if (context_read_and_validate
+ (&c->context[0], p, fp))
+ return -1;
+ break;
+ case OCON_DEVICE:
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ c->u.device = le32_to_cpu(buf[0]);
+ if (context_read_and_validate
+ (&c->context[0], p, fp))
+ return -1;
+ break;
+ default:
+ /* should never get here */
+ ERR(fp->handle, "Unknown Xen ocontext");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+static int ocontext_read_selinux(struct policydb_compat_info *info,
policydb_t * p, struct policy_file *fp)
{
unsigned int i, j;
@@ -2197,23 +2285,25 @@ static int ocontext_read(struct policydb_compat_info *info,
return -1;
break;
case OCON_NODE6:{
- int k;
-
- rc = next_entry(buf, fp,
- sizeof(uint32_t) * 8);
- if (rc < 0)
- return -1;
- for (k = 0; k < 4; k++)
- c->u.node6.addr[k] = buf[k]; /* network order */
- for (k = 0; k < 4; k++)
- c->u.node6.mask[k] = buf[k + 4]; /* network order */
- if (context_read_and_validate
- (&c->context[0], p, fp))
- return -1;
- break;
+ int k;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t) * 8);
+ if (rc < 0)
+ return -1;
+ for (k = 0; k < 4; k++)
+ /* network order */
+ c->u.node6.addr[k] = buf[k];
+ for (k = 0; k < 4; k++)
+ /* network order */
+ c->u.node6.mask[k] = buf[k + 4];
+ if (context_read_and_validate
+ (&c->context[0], p, fp))
+ return -1;
+ break;
}
default:{
- assert(0); /* should never get here */
+ ERR(fp->handle, "Unknown SELinux ocontext");
+ return -1;
}
}
}
@@ -2221,6 +2311,23 @@ static int ocontext_read(struct policydb_compat_info *info,
return 0;
}
+static int ocontext_read(struct policydb_compat_info *info,
+ policydb_t *p, struct policy_file *fp)
+{
+ int rc = -1;
+ switch (p->target_type) {
+ case SEPOL_TARGET_SELINUX:
+ rc = ocontext_read_selinux(info, p, fp);
+ break;
+ case SEPOL_TARGET_XEN:
+ rc = ocontext_read_xen(info, p, fp);
+ break;
+ default:
+ ERR(fp->handle, "Unknown target");
+ }
+ return rc;
+}
+
static int genfs_read(policydb_t * p, struct policy_file *fp)
{
uint32_t buf[1];
@@ -3070,7 +3177,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
unsigned int i, j, r_policyvers;
uint32_t buf[5], config;
size_t len, nprim, nel;
- char *policydb_str, *target_str = NULL, *alt_target_str = NULL;
+ char *policydb_str, *target_str = NULL;
struct policydb_compat_info *info;
unsigned int policy_type, bufindex;
ebitmap_node_t *tnode;
@@ -3088,7 +3195,6 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
if (buf[0] == POLICYDB_MAGIC) {
policy_type = POLICY_KERN;
target_str = POLICYDB_STRING;
- alt_target_str = POLICYDB_ALT_STRING;
} else if (buf[0] == POLICYDB_MOD_MAGIC) {
policy_type = POLICY_MOD;
target_str = POLICYDB_MOD_STRING;
@@ -3100,8 +3206,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
}
len = buf[1];
- if (len != strlen(target_str) &&
- (!alt_target_str || len != strlen(alt_target_str))) {
+ if (len != strlen(target_str)) {
ERR(fp->handle, "policydb string length %zu does not match "
"expected length %zu", len, strlen(target_str));
return POLICYDB_ERROR;
@@ -3120,13 +3225,21 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
return POLICYDB_ERROR;
}
policydb_str[len] = 0;
- if (strcmp(policydb_str, target_str) &&
- (!alt_target_str || strcmp(policydb_str, alt_target_str))) {
- ERR(fp->handle, "policydb string %s does not match "
- "my string %s", policydb_str, target_str);
+
+ for (i = 0; i < POLICYDB_TARGET_SZ; i++) {
+ if ((strcmp(policydb_str, policydb_target_strings[i]) == 0)) {
+ policydb_set_target_platform(p, i);
+ break;
+ }
+ }
+
+ if (i == POLICYDB_TARGET_SZ) {
+ ERR(fp->handle, "cannot find a valid target for policy "
+ "my string %s", policydb_str);
free(policydb_str);
return POLICYDB_ERROR;
}
+
/* Done with policydb_str. */
free(policydb_str);
policydb_str = NULL;
@@ -3391,3 +3504,16 @@ void policy_file_init(policy_file_t *pf)
{
memset(pf, 0, sizeof(policy_file_t));
}
+
+int policydb_set_target_platform(policydb_t *p, int platform)
+{
+ if (platform == SEPOL_TARGET_SELINUX)
+ p->target_type = SEPOL_TARGET_SELINUX;
+ else if (platform == SEPOL_TARGET_XEN)
+ p->target_type = SEPOL_TARGET_XEN;
+ else
+ return -1;
+
+ return 0;
+}
+
diff --git a/libsepol/src/policydb_internal.h b/libsepol/src/policydb_internal.h
index 1eb99e5..8a31506 100644
--- a/libsepol/src/policydb_internal.h
+++ b/libsepol/src/policydb_internal.h
@@ -6,4 +6,5 @@
hidden_proto(sepol_policydb_create)
hidden_proto(sepol_policydb_free)
+extern char *policydb_target_strings[];
#endif
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 66b35ec..a557c2e 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -1084,10 +1084,79 @@ static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
common_write, class_write, role_write, type_write, user_write,
cond_write_bool, sens_write, cat_write,};
-static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
+static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
struct policy_file *fp)
{
unsigned int i, j;
+ size_t nel, items;
+ uint32_t buf[32];
+ ocontext_t *c;
+ for (i = 0; i < info->ocon_num; i++) {
+ nel = 0;
+ for (c = p->ocontexts[i]; c; c = c->next)
+ nel++;
+ buf[0] = cpu_to_le32(nel);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ for (c = p->ocontexts[i]; c; c = c->next) {
+ switch (i) {
+ case OCON_ISID:
+ buf[0] = cpu_to_le32(c->sid[0]);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ if (context_write(p, &c->context[0], fp))
+ return POLICYDB_ERROR;
+ break;
+ case OCON_PIRQ:
+ buf[0] = cpu_to_le32(c->u.pirq);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ if (context_write(p, &c->context[0], fp))
+ return POLICYDB_ERROR;
+ break;
+ case OCON_IOPORT:
+ buf[0] = c->u.ioport.low_ioport;
+ buf[1] = c->u.ioport.high_ioport;
+ for (j = 0; j < 2; j++)
+ buf[j] = cpu_to_le32(buf[j]);
+ items = put_entry(buf, sizeof(uint32_t), 2, fp);
+ if (items != 2)
+ return POLICYDB_ERROR;
+ if (context_write(p, &c->context[0], fp))
+ return POLICYDB_ERROR;
+ break;
+ case OCON_IOMEM:
+ buf[0] = c->u.iomem.low_iomem;
+ buf[1] = c->u.iomem.high_iomem;
+ for (j = 0; j < 2; j++)
+ buf[j] = cpu_to_le32(buf[j]);
+ items = put_entry(buf, sizeof(uint32_t), 2, fp);
+ if (items != 2)
+ return POLICYDB_ERROR;
+ if (context_write(p, &c->context[0], fp))
+ return POLICYDB_ERROR;
+ break;
+ case OCON_DEVICE:
+ buf[0] = cpu_to_le32(c->u.device);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+ if (context_write(p, &c->context[0], fp))
+ return POLICYDB_ERROR;
+ break;
+ }
+ }
+ }
+ return POLICYDB_SUCCESS;
+}
+
+static int ocontext_write_selinux(struct policydb_compat_info *info,
+ policydb_t *p, struct policy_file *fp)
+{
+ unsigned int i, j;
size_t nel, items, len;
uint32_t buf[32];
ocontext_t *c;
@@ -1176,6 +1245,21 @@ static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
return POLICYDB_SUCCESS;
}
+static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
+ struct policy_file *fp)
+{
+ int rc = POLICYDB_ERROR;
+ switch (p->target_type) {
+ case SEPOL_TARGET_SELINUX:
+ rc = ocontext_write_selinux(info, p, fp);
+ break;
+ case SEPOL_TARGET_XEN:
+ rc = ocontext_write_xen(info, p, fp);
+ break;
+ }
+ return rc;
+}
+
static int genfs_write(policydb_t * p, struct policy_file *fp)
{
genfs_t *genfs;
@@ -1610,8 +1694,8 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
items = 0;
if (p->policy_type == POLICY_KERN) {
buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
- len = strlen(POLICYDB_STRING);
- policydb_str = POLICYDB_STRING;
+ len = strlen(policydb_target_strings[p->target_type]);
+ policydb_str = policydb_target_strings[p->target_type];
} else {
buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
len = strlen(POLICYDB_MOD_STRING);
diff --git a/sepolgen/src/sepolgen/refparser.py b/sepolgen/src/sepolgen/refparser.py
index 65d1d90..23beb39 100644
--- a/sepolgen/src/sepolgen/refparser.py
+++ b/sepolgen/src/sepolgen/refparser.py
@@ -83,6 +83,10 @@ tokens = (
'PORTCON',
'NODECON',
'NETIFCON',
+ 'PIRQCON',
+ 'IOMEMCON',
+ 'IOPORTCON',
+ 'PCIDEVICECON',
# object classes
'CLASS',
# types and attributes
@@ -140,6 +144,10 @@ reserved = {
'portcon' : 'PORTCON',
'nodecon' : 'NODECON',
'netifcon' : 'NETIFCON',
+ 'pirqcon' : 'PIRQCON',
+ 'iomemcon' : 'IOMEMCON',
+ 'ioportcon' : 'IOPORTCON',
+ 'pcidevicecon' : 'PCIDEVICECON',
# object classes
'class' : 'CLASS',
# types and attributes
@@ -495,6 +503,10 @@ def p_policy_stmt(p):
| portcon
| nodecon
| netifcon
+ | pirqcon
+ | iomemcon
+ | ioportcon
+ | pcidevicecon
'''
if p[1]:
p[0] = [p[1]]
@@ -631,6 +643,48 @@ def p_netifcon(p):
p[0] = n
+def p_pirqcon(p):
+ 'pirqcon : PIRQCON NUMBER context'
+ c = refpolicy.PirqCon()
+ c.pirq_number = p[2]
+ c.context = p[3]
+
+ p[0] = c
+
+def p_iomemcon(p):
+ '''iomemcon : IOMEMCON NUMBER context
+ | IOMEMCON NUMBER MINUS NUMBER context'''
+ c = refpolicy.IomemCon()
+ if len(p) == 4:
+ c.device_mem = p[2]
+ c.context = p[3]
+ else:
+ c.device_mem = p[2] + "-" + p[3]
+ c.context = p[4]
+
+ p[0] = c
+
+def p_ioportcon(p):
+ '''ioportcon : IOPORTCON NUMBER context
+ | IOPORTCON NUMBER MINUS NUMBER context'''
+ c = refpolicy.IoportCon()
+ if len(p) == 4:
+ c.ioport = p[2]
+ c.context = p[3]
+ else:
+ c.ioport = p[2] + "-" + p[3]
+ c.context = p[4]
+
+ p[0] = c
+
+def p_pcidevicecon(p):
+ 'pcidevicecon : PCIDEVICECON NUMBER context'
+ c = refpolicy.PciDeviceCon()
+ c.device = p[2]
+ c.context = p[3]
+
+ p[0] = c
+
def p_mls_range_def(p):
'''mls_range_def : mls_level_def MINUS mls_level_def
| mls_level_def
diff --git a/sepolgen/src/sepolgen/refpolicy.py b/sepolgen/src/sepolgen/refpolicy.py
index 724b870..b138e3d 100644
--- a/sepolgen/src/sepolgen/refpolicy.py
+++ b/sepolgen/src/sepolgen/refpolicy.py
@@ -618,6 +618,41 @@ class NetifCon(Leaf):
def to_string(self):
return "netifcon %s %s %s" % (self.interface, str(self.interface_context),
str(self.packet_context))
+class PirqCon(Leaf):
+ def __init__(self, parent=None):
+ Leaf.__init__(self, parent)
+ self.pirq_number = ""
+ self.context = None
+
+ def to_string(self):
+ return "pirqcon %s %s" % (self.pirq_number, str(self.context))
+
+class IomemCon(Leaf):
+ def __init__(self, parent=None):
+ Leaf.__init__(self, parent)
+ self.device_mem = ""
+ self.context = None
+
+ def to_string(self):
+ return "iomemcon %s %s" % (self.device_mem, str(self.context))
+
+class IoportCon(Leaf):
+ def __init__(self, parent=None):
+ Leaf.__init__(self, parent)
+ self.ioport = ""
+ self.context = None
+
+ def to_string(self):
+ return "ioportcon %s %s" % (self.ioport, str(self.context))
+
+class PciDeviceCon(Leaf):
+ def __init__(self, parent=None):
+ Leaf.__init__(self, parent)
+ self.device = ""
+ self.context = None
+
+ def to_string(self):
+ return "pcidevicecon %s %s" % (self.device, str(self.context))
# Reference policy specific types
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] libsepol/checkpolicy: Add support for multiple target OSes
2009-09-14 13:22 [PATCH] libsepol/checkpolicy: Add support for multiple target OSes pjnuzzi
@ 2009-09-14 19:07 ` Joshua Brindle
2009-09-14 19:33 ` Stephen Smalley
0 siblings, 1 reply; 6+ messages in thread
From: Joshua Brindle @ 2009-09-14 19:07 UTC (permalink / raw)
To: pjnuzzi; +Cc: selinux
On 09/14/2009 09:22 AM, pjnuzzi wrote:
> Add support for multiple target OSes to libsepol and checkpolicy, where
>
what about checkmodule?
> the particular target OS is selected using a new -t target option to
> checkpolicy. The default target remains SELinux. A new target and
> support is introduced for Xen. The target OS is identified in the
> policy image by using different policy string identifiers in the header.
> At present, policy string identifiers are required to have the same
> length for ease of parsing the header and to preserve file(1) parsing of
>
That is not the case today. Does file really not have the ability to
read a length and then a string of that length?
> subsequent fields after the string identifier. For SELinux, the string
> identifier remains "SE Linux". For Xen, the string identifier is
> "XenFlask". The latent support for just "Flask" in the policy reading
> code that was introduced for FMAC is dropped; a separate identifier for
>
Was it already in use? I don't think arbitrarily dropping identifiers is
a good idea.
> Solaris (e.g. "SolFlask") will be introduced later using this new target
> mechanism if needed. The same support can easily be extended for other
> OSes.
>
> Based on the selected target, the source and binary policies may be
> parsed differently. For SELinux vs. Xen, the current difference is the
> interpretation of object context records. New object context records
> for object contexts for pirqs, iomem ranges, ioport ranges, and pci
> devices are enabled if building for the Xen target. The SELinux object
> context records other than initial SIDs are disabled if building for the
> Xen target. checkpolicy will generate an error if an attempt is made to
> build a policy that has invalid object context records for the selected
> target, and libsepol will likewise reject a binary policy if its object
> context records are invalid for the target identified by its string
> identifier.
>
> No changes are required to the SELinux kernel code to support this
> change; the SELinux kernel will continue to accept only policies with
> the "SE Linux" identifier. A patch for the Xen Flask module will be
> submitted after this patch to enable it to accept policies built with
> either string identifier (for compatibility with existing policies),
> where the new object context record support will only be enabled if the
> policy was built for the Xen target.
>
> Support for selecting the target platform for libsemanage will be added
> later.
>
> Signed-off-by: Paul Nuzzi<pjnuzzi@tycho.ncsc.mil>
>
> ---
> checkpolicy/checkpolicy.c | 20 +-
> checkpolicy/policy_define.c | 262 +++++++++++++++++++++++++++++
> checkpolicy/policy_define.h | 4
> checkpolicy/policy_parse.y | 29 +++
> checkpolicy/policy_scan.l | 10 -
> libsepol/include/sepol/policydb/policydb.h | 28 ++-
> libsepol/src/expand.c | 85 ++++++++-
> libsepol/src/policydb.c | 178 ++++++++++++++++---
> libsepol/src/policydb_internal.h | 1
> libsepol/src/write.c | 90 +++++++++
> sepolgen/src/sepolgen/refparser.py | 54 +++++
> sepolgen/src/sepolgen/refpolicy.py | 35 +++
> 12 files changed, 755 insertions(+), 41 deletions(-)
>
>
This is a fairly large patch, it might take a while to get through it.
Splitting it up would have been helpful.
> diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
> index d7772d5..76d8ed3 100644
> --- a/checkpolicy/checkpolicy.c
> +++ b/checkpolicy/checkpolicy.c
> @@ -100,7 +100,9 @@ unsigned int policyvers = POLICYDB_VERSION_MAX;
> void usage(char *progname)
> {
> printf
> - ("usage: %s [-b] [-d] [-U handle_unknown (allow,deny,reject) [-M] [-c policyvers (%d-%d)] [-o output_file] [input_file]\n",
> + ("usage: %s [-b] [-d] [-U handle_unknown (allow,deny,reject) [-M]"
> + "[-c policyvers (%d-%d)] [-o output_file] [-t platform]"
> + "[input_file]\n",
> progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
> exit(1);
> }
> @@ -381,7 +383,7 @@ int main(int argc, char **argv)
> unsigned int protocol, port;
> unsigned int binary = 0, debug = 0;
> struct val_to_name v;
> - int ret, ch, fd;
> + int ret, ch, fd, target = SEPOL_TARGET_SELINUX;
> unsigned int nel, uret;
> struct stat sb;
> void *map;
> @@ -391,11 +393,22 @@ int main(int argc, char **argv)
> int show_version = 0;
> struct policy_file pf;
>
> - while ((ch = getopt(argc, argv, "o:dbU:MVc:")) != EOF) {
> + while ((ch = getopt(argc, argv, "o:t:dbU:MVc:")) != EOF) {
> switch (ch) {
> case 'o':
> outfile = optarg;
> break;
> + case 't':
> + if (!strcasecmp(optarg, "Xen"))
> + target = SEPOL_TARGET_XEN;
> + else if (!strcasecmp(optarg, "SELinux"))
> + target = SEPOL_TARGET_SELINUX;
> + else{
> + fprintf(stderr, "%s: Unknown target platform:"
> + "%s\n", argv[0], optarg);
> + exit(1);
> + }
> + break;
> case 'b':
> binary = 1;
> file = binfile;
> @@ -528,6 +541,7 @@ int main(int argc, char **argv)
> exit(1);
> /* We build this as a base policy first since that is all the parser understands */
> parse_policy.policy_type = POLICY_BASE;
> + policydb_set_target_platform(&parse_policy, target);
>
> /* Let sepol know if we are dealing with MLS support */
> parse_policy.mls = mlspol;
> diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
> index 17b84ce..1e19bda 100644
> --- a/checkpolicy/policy_define.c
> +++ b/checkpolicy/policy_define.c
> @@ -3372,12 +3372,254 @@ int define_fs_context(unsigned int major, unsigned int minor)
> return 0;
> }
>
> +int define_pirq_context(unsigned int pirq)
> +{
> + ocontext_t *newc, *c, *l, *head;
> + char *id;
> +
> + if (policydbp->target_type != SEPOL_TARGET_XEN) {
> + yyerror("pirqcon only supported for target Xen");
> + return -1;
> + }
> +
> + if (pass == 1) {
> + id = (char *) queue_remove(id_queue);
> + free(id);
> + parse_security_context(NULL);
> + return 0;
> + }
> +
> + newc = malloc(sizeof(ocontext_t));
> + if (!newc) {
> + yyerror("out of memory");
> + return -1;
> + }
> + memset(newc, 0, sizeof(ocontext_t));
> +
> + newc->u.pirq = pirq;
> +
> + if (parse_security_context(&newc->context[0])) {
> + free(newc);
> + return -1;
> + }
> +
> + head = policydbp->ocontexts[OCON_PIRQ];
> + for (l = NULL, c = head; c; l = c, c = c->next) {
> + unsigned int pirq2;
> +
> + pirq2 = c->u.pirq;
> + if (pirq == pirq2) {
> + yyerror2("duplicate pirqcon entry for %d ", pirq);
> + goto bad;
> + }
> + }
> +
> + if (l)
> + l->next = newc;
> + else
> + policydbp->ocontexts[OCON_PIRQ] = newc;
> +
> + return 0;
> +
> +bad:
> + free(newc);
> + return -1;
> +}
> +
> +int define_iomem_context(unsigned long low, unsigned long high)
> +{
> + ocontext_t *newc, *c, *l, *head;
> + char *id;
> +
> + if (policydbp->target_type != SEPOL_TARGET_XEN) {
> + yyerror("iomemcon only supported for target Xen");
> + return -1;
> + }
> +
> + if (pass == 1) {
> + id = (char *)queue_remove(id_queue);
> + free(id);
> + parse_security_context(NULL);
> + return 0;
> + }
> +
> + newc = malloc(sizeof(ocontext_t));
> + if (!newc) {
> + yyerror("out of memory");
> + return -1;
> + }
> + memset(newc, 0, sizeof(ocontext_t));
> +
> + newc->u.iomem.low_iomem = low;
> + newc->u.iomem.high_iomem = high;
> +
> + if (low> high) {
> + yyerror2("low memory 0x%x exceeds high memory 0x%x", low, high);
> + free(newc);
> + return -1;
> + }
> +
> + if (parse_security_context(&newc->context[0])) {
> + free(newc);
> + return -1;
> + }
> +
> + head = policydbp->ocontexts[OCON_IOMEM];
> + for (l = NULL, c = head; c; l = c, c = c->next) {
> + unsigned int low2, high2;
> +
> + low2 = c->u.iomem.low_iomem;
> + high2 = c->u.iomem.high_iomem;
> + if (low<= high2&& low2<= high) {
> + yyerror2("iomemcon entry for 0x%x-0x%x overlaps with "
> + "earlier entry 0x%x-0x%x", low, high,
> + low2, high2);
> + goto bad;
> + }
> + }
> +
> + if (l)
> + l->next = newc;
> + else
> + policydbp->ocontexts[OCON_IOMEM] = newc;
> +
> + return 0;
> +
> +bad:
> + free(newc);
> + return -1;
> +}
> +
> +int define_ioport_context(unsigned long low, unsigned long high)
> +{
> + ocontext_t *newc, *c, *l, *head;
> + char *id;
> +
> + if (policydbp->target_type != SEPOL_TARGET_XEN) {
> + yyerror("ioportcon only supported for target Xen");
> + return -1;
> + }
> +
> + if (pass == 1) {
> + id = (char *)queue_remove(id_queue);
> + free(id);
> + parse_security_context(NULL);
> + return 0;
> + }
> +
> + newc = malloc(sizeof(ocontext_t));
> + if (!newc) {
> + yyerror("out of memory");
> + return -1;
> + }
> + memset(newc, 0, sizeof(ocontext_t));
> +
> + newc->u.ioport.low_ioport = low;
> + newc->u.ioport.high_ioport = high;
> +
> + if (low> high) {
> + yyerror2("low ioport 0x%x exceeds high ioport 0x%x", low, high);
> + free(newc);
> + return -1;
> + }
> +
> + if (parse_security_context(&newc->context[0])) {
> + free(newc);
> + return -1;
> + }
> +
> + head = policydbp->ocontexts[OCON_IOPORT];
> + for (l = NULL, c = head; c; l = c, c = c->next) {
> + unsigned int low2, high2;
> +
> + low2 = c->u.ioport.low_ioport;
> + high2 = c->u.ioport.high_ioport;
> + if (low<= high2&& low2<= high) {
> + yyerror2("ioportcon entry for 0x%x-0x%x overlaps with"
> + "earlier entry 0x%x-0x%x", low, high,
> + low2, high2);
> + goto bad;
> + }
> + }
> +
> + if (l)
> + l->next = newc;
> + else
> + policydbp->ocontexts[OCON_IOPORT] = newc;
> +
> + return 0;
> +
> +bad:
> + free(newc);
> + return -1;
> +}
> +
> +int define_pcidevice_context(unsigned long device)
> +{
> + ocontext_t *newc, *c, *l, *head;
> + char *id;
> +
> + if (policydbp->target_type != SEPOL_TARGET_XEN) {
> + yyerror("pcidevicecon only supported for target Xen");
> + return -1;
> + }
> +
> + if (pass == 1) {
> + id = (char *) queue_remove(id_queue);
> + free(id);
> + parse_security_context(NULL);
> + return 0;
> + }
> +
> + newc = malloc(sizeof(ocontext_t));
> + if (!newc) {
> + yyerror("out of memory");
> + return -1;
> + }
> + memset(newc, 0, sizeof(ocontext_t));
> +
> + newc->u.device = device;
> +
> + if (parse_security_context(&newc->context[0])) {
> + free(newc);
> + return -1;
> + }
> +
> + head = policydbp->ocontexts[OCON_DEVICE];
> + for (l = NULL, c = head; c; l = c, c = c->next) {
> + unsigned int device2;
> +
> + device2 = c->u.device;
> + if (device == device2) {
> + yyerror2("duplicate pcidevicecon entry for 0x%x ",
> + device);
> + goto bad;
> + }
> + }
> +
> + if (l)
> + l->next = newc;
> + else
> + policydbp->ocontexts[OCON_DEVICE] = newc;
> +
> + return 0;
> +
> +bad:
> + free(newc);
> + return -1;
> +}
> +
> int define_port_context(unsigned int low, unsigned int high)
> {
> ocontext_t *newc, *c, *l, *head;
> unsigned int protocol;
> char *id;
>
> + if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
> + yyerror("portcon only supported for target SELinux");
> + return -1;
> + }
> +
> if (pass == 1) {
> id = (char *)queue_remove(id_queue);
> free(id);
> @@ -3460,6 +3702,11 @@ int define_netif_context(void)
> {
> ocontext_t *newc, *c, *head;
>
> + if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
> + yyerror("netifcon only supported for target SELinux");
> + return -1;
> + }
> +
> if (pass == 1) {
> free(queue_remove(id_queue));
> parse_security_context(NULL);
> @@ -3516,6 +3763,11 @@ int define_ipv4_node_context()
> struct in_addr addr, mask;
> ocontext_t *newc, *c, *l, *head;
>
> + if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
> + yyerror("nodecon only supported for target SELinux");
> + return -1;
> + }
> +
> if (pass == 1) {
> free(queue_remove(id_queue));
> free(queue_remove(id_queue));
> @@ -3597,6 +3849,11 @@ int define_ipv6_node_context(void)
> struct in6_addr addr, mask;
> ocontext_t *newc, *c, *l, *head;
>
> + if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
> + yyerror("nodecon only supported by target SELinux");
> + return -1;
> + }
> +
> if (pass == 1) {
> free(queue_remove(id_queue));
> free(queue_remove(id_queue));
> @@ -3677,6 +3934,11 @@ int define_fs_use(int behavior)
> {
> ocontext_t *newc, *c, *head;
>
> + if (policydbp->target_type != SEPOL_TARGET_SELINUX) {
> + yyerror("unsupported target");
> + return -1;
> + }
> +
> if (pass == 1) {
> free(queue_remove(id_queue));
> parse_security_context(NULL);
> diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h
> index b5a972e..5ac6667 100644
> --- a/checkpolicy/policy_define.h
> +++ b/checkpolicy/policy_define.h
> @@ -39,6 +39,10 @@ int define_netif_context(void);
> int define_permissive(void);
> int define_polcap(void);
> int define_port_context(unsigned int low, unsigned int high);
> +int define_pirq_context(unsigned int pirq);
> +int define_iomem_context(unsigned long low, unsigned long high);
> +int define_ioport_context(unsigned long low, unsigned long high);
> +int define_pcidevice_context(unsigned long device);
> int define_range_trans(int class_specified);
> int define_role_allow(void);
> int define_role_trans(void);
> diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
> index 5ca7101..8d1bc37 100644
> --- a/checkpolicy/policy_parse.y
> +++ b/checkpolicy/policy_parse.y
> @@ -123,6 +123,7 @@ typedef int (* require_func_t)();
> %token TARGET
> %token SAMEUSER
> %token FSCON PORTCON NETIFCON NODECON
> +%token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON
> %token FSUSEXATTR FSUSETASK FSUSETRANS
> %token GENFSCON
> %token U1 U2 U3 R1 R2 R3 T1 T2 T3 L1 L2 H1 H2
> @@ -154,7 +155,7 @@ base_policy : { if (define_policy(pass, 0) == -1) return -1; }
> opt_mls te_rbac users opt_constraints
> { if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;}
> else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1;}}
> - initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts
> + initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts
> ;
> classes : class_def
> | classes class_def
> @@ -562,6 +563,32 @@ initial_sid_contexts : initial_sid_context_def
> initial_sid_context_def : SID identifier security_context_def
> {if (define_initial_sid_context()) return -1;}
> ;
> +opt_dev_contexts : dev_contexts |
> + ;
> +dev_contexts : dev_context_def
> + | dev_contexts dev_context_def
> + ;
> +dev_context_def : pirq_context_def |
> + iomem_context_def |
> + ioport_context_def |
> + pci_context_def
> + ;
> +pirq_context_def : PIRQCON number security_context_def
> + {if (define_pirq_context($2)) return -1;}
> + ;
> +iomem_context_def : IOMEMCON number security_context_def
> + {if (define_iomem_context($2,$2)) return -1;}
> + | IOMEMCON number '-' number security_context_def
> + {if (define_iomem_context($2,$4)) return -1;}
> + ;
> +ioport_context_def : IOPORTCON number security_context_def
> + {if (define_ioport_context($2,$2)) return -1;}
> + | IOPORTCON number '-' number security_context_def
> + {if (define_ioport_context($2,$4)) return -1;}
> + ;
> +pci_context_def : PCIDEVICECON number security_context_def
> + {if (define_pcidevice_context($2)) return -1;}
> + ;
> opt_fs_contexts : fs_contexts
> |
> ;
> diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
> index b55c659..48128a8 100644
> --- a/checkpolicy/policy_scan.l
> +++ b/checkpolicy/policy_scan.l
> @@ -169,6 +169,14 @@ netifcon |
> NETIFCON { return(NETIFCON);}
> nodecon |
> NODECON { return(NODECON);}
> +pirqcon |
> +PIRQCON { return(PIRQCON);}
> +iomemcon |
> +IOMEMCON { return(IOMEMCON);}
> +ioportcon |
> +IOPORTCON { return(IOPORTCON);}
> +pcidevicecon |
> +PCIDEVICECON { return(PCIDEVICECON);}
> fs_use_xattr |
> FS_USE_XATTR { return(FSUSEXATTR);}
> fs_use_task |
> @@ -209,7 +217,7 @@ permissive |
> PERMISSIVE { return(PERMISSIVE); }
> "/"({alnum}|[_\.\-/])* { return(PATH); }
> {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))* { return(IDENTIFIER); }
> -{digit}+ { return(NUMBER); }
> +{digit}+|0x{hexval}+ { return(NUMBER); }
> {digit}{1,3}(\.{digit}{1,3}){3} { return(IPV4_ADDR); }
> {hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])* { return(IPV6_ADDR); }
> {digit}+(\.({alnum}|[_.])*)? { return(VERSION_IDENTIFIER); }
> diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
> index 0105cf4..2013238 100644
> --- a/libsepol/include/sepol/policydb/policydb.h
> +++ b/libsepol/include/sepol/policydb/policydb.h
> @@ -276,6 +276,16 @@ typedef struct ocontext {
> uint32_t addr[4]; /* network order */
> uint32_t mask[4]; /* network order */
> } node6; /* IPv6 node information */
> + uint32_t device;
> + uint16_t pirq;
> + struct {
> + uint32_t low_iomem;
> + uint32_t high_iomem;
> + } iomem;
> + struct {
> + uint32_t low_ioport;
> + uint32_t high_ioport;
> + } ioport;
> } u;
> union {
> uint32_t sclass; /* security class for genfs */
> @@ -313,6 +323,17 @@ typedef struct genfs {
> #define OCON_NODE6 6 /* IPv6 nodes */
> #define OCON_NUM 7
>
> +/* object context array indices for Xen */
> +#define OCON_ISID 0 /* initial SIDs */
> +#define OCON_PIRQ 1 /* physical irqs */
> +#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
> +
> +
> /* section: module information */
>
> /* scope_index_t holds all of the symbols that are in scope in a
> @@ -400,6 +421,7 @@ typedef struct policydb {
> uint32_t policy_type;
> char *name;
> char *version;
> + uint32_t target_type;
>
> /* Set when the policydb is modified such that writing is unsupported */
> int unsupported_format;
> @@ -593,6 +615,7 @@ extern int avrule_read_list(policydb_t * p, avrule_t ** avrules,
> struct policy_file *fp);
>
> extern int policydb_write(struct policydb *p, struct policy_file *pf);
> +extern int policydb_set_target_platform(policydb_t *p, int platform);
>
> #define PERM_SYMTAB_SIZE 32
>
> @@ -651,9 +674,12 @@ extern int policydb_write(struct policydb *p, struct policy_file *pf);
>
> #define POLICYDB_MAGIC SELINUX_MAGIC
> #define POLICYDB_STRING "SE Linux"
> -#define POLICYDB_ALT_STRING "Flask"
> +#define POLICYDB_XEN_STRING "XenFlask"
> #define POLICYDB_MOD_MAGIC SELINUX_MOD_MAGIC
> #define POLICYDB_MOD_STRING "SE Linux Module"
> +#define SEPOL_TARGET_SELINUX 0
> +#define SEPOL_TARGET_XEN 1
> +
>
> #endif /* _POLICYDB_H_ */
>
> diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
> index e9cd986..38e2481 100644
> --- a/libsepol/src/expand.c
> +++ b/libsepol/src/expand.c
> @@ -1819,9 +1819,9 @@ static int context_copy(context_struct_t * dst, context_struct_t * src,
> return mls_context_cpy(dst, src);
> }
>
> -static int ocontext_copy(expand_state_t * state)
> +static int ocontext_copy_xen(expand_state_t *state)
> {
> - unsigned int i, j;
> + unsigned int i;
> ocontext_t *c, *n, *l;
>
> for (i = 0; i< OCON_NUM; i++) {
> @@ -1833,11 +1833,63 @@ static int ocontext_copy(expand_state_t * state)
> return -1;
> }
> memset(n, 0, sizeof(ocontext_t));
> - if (l) {
> + if (l)
> l->next = n;
> - } else {
> + else
> state->out->ocontexts[i] = n;
> + l = n;
> + if (context_copy(&n->context[0],&c->context[0],
> + state)) {
> + ERR(state->handle, "Out of memory!");
> + return -1;
> + }
> + switch (i) {
> + case OCON_ISID:
> + n->sid[0] = c->sid[0];
> + break;
> + case OCON_PIRQ:
> + n->u.pirq = c->u.pirq;
> + break;
> + case OCON_IOPORT:
> + n->u.ioport.low_ioport = c->u.ioport.low_ioport;
> + n->u.ioport.high_ioport =
> + c->u.ioport.high_ioport;
> + break;
> + case OCON_IOMEM:
> + n->u.iomem.low_iomem = c->u.iomem.low_iomem;
> + n->u.iomem.high_iomem = c->u.iomem.high_iomem;
> + break;
> + case OCON_DEVICE:
> + n->u.device = c->u.device;
> + break;
> + default:
> + /* shouldn't get here */
> + ERR(state->handle, "Unknown ocontext");
> + return -1;
> + }
> + }
> + }
> + return 0;
> +}
> +
> +static int ocontext_copy_selinux(expand_state_t *state)
> +{
> + unsigned int i, j;
> + ocontext_t *c, *n, *l;
> +
> + for (i = 0; i< OCON_NUM; i++) {
> + l = NULL;
> + for (c = state->base->ocontexts[i]; c; c = c->next) {
> + n = malloc(sizeof(ocontext_t));
> + if (!n) {
> + ERR(state->handle, "Out of memory!");
> + return -1;
> }
> + memset(n, 0, sizeof(ocontext_t));
> + if (l)
> + l->next = n;
> + else
> + state->out->ocontexts[i] = n;
> l = n;
> if (context_copy(&n->context[0],&c->context[0], state)) {
> ERR(state->handle, "Out of memory!");
> @@ -1885,13 +1937,31 @@ static int ocontext_copy(expand_state_t * state)
> break;
> default:
> /* shouldn't get here */
> - assert(0);
> + ERR(state->handle, "Unknown ocontext");
> + return -1;
> }
> }
> }
> return 0;
> }
>
> +static int ocontext_copy(expand_state_t *state, uint32_t target)
> +{
> + int rc = -1;
> + switch (target) {
> + case SEPOL_TARGET_SELINUX:
> + rc = ocontext_copy_selinux(state);
> + break;
> + case SEPOL_TARGET_XEN:
> + rc = ocontext_copy_xen(state);
> + break;
> + default:
> + ERR(state->handle, "Unknown target");
> + return -1;
> + }
> + return rc;
> +}
> +
> static int genfs_copy(expand_state_t * state)
> {
> ocontext_t *c, *newc, *l;
> @@ -2418,6 +2488,9 @@ int expand_module(sepol_handle_t * handle,
> out->mls = base->mls;
> out->handle_unknown = base->handle_unknown;
>
> + /* Copy target from base to out */
> + out->target_type = base->target_type;
> +
> /* Copy policy capabilities */
> if (ebitmap_cpy(&out->policycaps,&base->policycaps)) {
> ERR(handle, "Out of memory!");
> @@ -2576,7 +2649,7 @@ int expand_module(sepol_handle_t * handle,
> evaluate_conds(state.out);
>
> /* copy ocontexts */
> - if (ocontext_copy(&state))
> + if (ocontext_copy(&state, out->target_type))
> goto cleanup;
>
> /* copy genfs */
> diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
> index 85ddefc..a66a007 100644
> --- a/libsepol/src/policydb.c
> +++ b/libsepol/src/policydb.c
> @@ -54,6 +54,9 @@
> #include "debug.h"
> #include "mls.h"
>
> +#define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings)
> +char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
> +
> /* These need to be updated if SYM_NUM or OCON_NUM changes */
> static struct policydb_compat_info policydb_compat[] = {
> {
> @@ -1079,9 +1082,13 @@ void policydb_destroy(policydb_t * p)
> c = c->next;
> context_destroy(&ctmp->context[0]);
> context_destroy(&ctmp->context[1]);
> - if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF
> - || i == OCON_FSUSE)
> + if (i == OCON_ISID)
> + free(ctmp->u.name);
> + if (p->target_type == SEPOL_TARGET_SELINUX&&
> + (i == OCON_FS || i == OCON_NETIF ||
> + i == OCON_FSUSE))
> free(ctmp->u.name);
> +
> free(ctmp);
> }
> }
> @@ -2102,7 +2109,88 @@ int role_allow_read(role_allow_t ** r, struct policy_file *fp)
> return 0;
> }
>
> -static int ocontext_read(struct policydb_compat_info *info,
> +static int ocontext_read_xen(struct policydb_compat_info *info,
> + policydb_t *p, struct policy_file *fp)
> +{
> + unsigned int i, j;
> + size_t nel;
> + ocontext_t *l, *c;
> + uint32_t buf[8];
> + int rc;
> +
> + for (i = 0; i< info->ocon_num; i++) {
> + rc = next_entry(buf, fp, sizeof(uint32_t));
> + if (rc< 0)
> + return -1;
> + nel = le32_to_cpu(buf[0]);
> + l = NULL;
> + for (j = 0; j< nel; j++) {
> + c = calloc(1, sizeof(ocontext_t));
> + if (!c)
> + return -1;
> + if (l)
> + l->next = c;
> + else
> + p->ocontexts[i] = c;
> + l = c;
> + switch (i) {
> + case OCON_ISID:
> + rc = next_entry(buf, fp, sizeof(uint32_t));
> + if (rc< 0)
> + return -1;
> + c->sid[0] = le32_to_cpu(buf[0]);
> + if (context_read_and_validate
> + (&c->context[0], p, fp))
> + return -1;
> + break;
> + case OCON_PIRQ:
> + rc = next_entry(buf, fp, sizeof(uint32_t));
> + if (rc< 0)
> + return -1;
> + c->u.pirq = le32_to_cpu(buf[0]);
> + if (context_read_and_validate
> + (&c->context[0], p, fp))
> + return -1;
> + break;
> + case OCON_IOPORT:
> + rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
> + if (rc< 0)
> + return -1;
> + c->u.ioport.low_ioport = le32_to_cpu(buf[0]);
> + c->u.ioport.high_ioport = le32_to_cpu(buf[1]);
> + if (context_read_and_validate
> + (&c->context[0], p, fp))
> + return -1;
> + break;
> + case OCON_IOMEM:
> + rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
> + if (rc< 0)
> + return -1;
> + c->u.iomem.low_iomem = le32_to_cpu(buf[0]);
> + c->u.iomem.high_iomem = le32_to_cpu(buf[1]);
> + if (context_read_and_validate
> + (&c->context[0], p, fp))
> + return -1;
> + break;
> + case OCON_DEVICE:
> + rc = next_entry(buf, fp, sizeof(uint32_t));
> + if (rc< 0)
> + return -1;
> + c->u.device = le32_to_cpu(buf[0]);
> + if (context_read_and_validate
> + (&c->context[0], p, fp))
> + return -1;
> + break;
> + default:
> + /* should never get here */
> + ERR(fp->handle, "Unknown Xen ocontext");
> + return -1;
> + }
> + }
> + }
> + return 0;
> +}
> +static int ocontext_read_selinux(struct policydb_compat_info *info,
> policydb_t * p, struct policy_file *fp)
> {
> unsigned int i, j;
> @@ -2197,23 +2285,25 @@ static int ocontext_read(struct policydb_compat_info *info,
> return -1;
> break;
> case OCON_NODE6:{
> - int k;
> -
> - rc = next_entry(buf, fp,
> - sizeof(uint32_t) * 8);
> - if (rc< 0)
> - return -1;
> - for (k = 0; k< 4; k++)
> - c->u.node6.addr[k] = buf[k]; /* network order */
> - for (k = 0; k< 4; k++)
> - c->u.node6.mask[k] = buf[k + 4]; /* network order */
> - if (context_read_and_validate
> - (&c->context[0], p, fp))
> - return -1;
> - break;
> + int k;
> +
> + rc = next_entry(buf, fp, sizeof(uint32_t) * 8);
> + if (rc< 0)
> + return -1;
> + for (k = 0; k< 4; k++)
> + /* network order */
> + c->u.node6.addr[k] = buf[k];
> + for (k = 0; k< 4; k++)
> + /* network order */
> + c->u.node6.mask[k] = buf[k + 4];
> + if (context_read_and_validate
> + (&c->context[0], p, fp))
> + return -1;
> + break;
> }
> default:{
> - assert(0); /* should never get here */
> + ERR(fp->handle, "Unknown SELinux ocontext");
> + return -1;
> }
> }
> }
> @@ -2221,6 +2311,23 @@ static int ocontext_read(struct policydb_compat_info *info,
> return 0;
> }
>
> +static int ocontext_read(struct policydb_compat_info *info,
> + policydb_t *p, struct policy_file *fp)
> +{
> + int rc = -1;
> + switch (p->target_type) {
> + case SEPOL_TARGET_SELINUX:
> + rc = ocontext_read_selinux(info, p, fp);
> + break;
> + case SEPOL_TARGET_XEN:
> + rc = ocontext_read_xen(info, p, fp);
> + break;
> + default:
> + ERR(fp->handle, "Unknown target");
> + }
> + return rc;
> +}
> +
> static int genfs_read(policydb_t * p, struct policy_file *fp)
> {
> uint32_t buf[1];
> @@ -3070,7 +3177,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
> unsigned int i, j, r_policyvers;
> uint32_t buf[5], config;
> size_t len, nprim, nel;
> - char *policydb_str, *target_str = NULL, *alt_target_str = NULL;
> + char *policydb_str, *target_str = NULL;
> struct policydb_compat_info *info;
> unsigned int policy_type, bufindex;
> ebitmap_node_t *tnode;
> @@ -3088,7 +3195,6 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
> if (buf[0] == POLICYDB_MAGIC) {
> policy_type = POLICY_KERN;
> target_str = POLICYDB_STRING;
> - alt_target_str = POLICYDB_ALT_STRING;
> } else if (buf[0] == POLICYDB_MOD_MAGIC) {
> policy_type = POLICY_MOD;
> target_str = POLICYDB_MOD_STRING;
> @@ -3100,8 +3206,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
> }
>
> len = buf[1];
> - if (len != strlen(target_str)&&
> - (!alt_target_str || len != strlen(alt_target_str))) {
> + if (len != strlen(target_str)) {
> ERR(fp->handle, "policydb string length %zu does not match "
> "expected length %zu", len, strlen(target_str));
> return POLICYDB_ERROR;
> @@ -3120,13 +3225,21 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
> return POLICYDB_ERROR;
> }
> policydb_str[len] = 0;
> - if (strcmp(policydb_str, target_str)&&
> - (!alt_target_str || strcmp(policydb_str, alt_target_str))) {
> - ERR(fp->handle, "policydb string %s does not match "
> - "my string %s", policydb_str, target_str);
> +
> + for (i = 0; i< POLICYDB_TARGET_SZ; i++) {
> + if ((strcmp(policydb_str, policydb_target_strings[i]) == 0)) {
> + policydb_set_target_platform(p, i);
> + break;
> + }
> + }
> +
> + if (i == POLICYDB_TARGET_SZ) {
> + ERR(fp->handle, "cannot find a valid target for policy "
> + "my string %s", policydb_str);
> free(policydb_str);
> return POLICYDB_ERROR;
> }
> +
> /* Done with policydb_str. */
> free(policydb_str);
> policydb_str = NULL;
> @@ -3391,3 +3504,16 @@ void policy_file_init(policy_file_t *pf)
> {
> memset(pf, 0, sizeof(policy_file_t));
> }
> +
> +int policydb_set_target_platform(policydb_t *p, int platform)
> +{
> + if (platform == SEPOL_TARGET_SELINUX)
> + p->target_type = SEPOL_TARGET_SELINUX;
> + else if (platform == SEPOL_TARGET_XEN)
> + p->target_type = SEPOL_TARGET_XEN;
> + else
> + return -1;
> +
> + return 0;
> +}
> +
> diff --git a/libsepol/src/policydb_internal.h b/libsepol/src/policydb_internal.h
> index 1eb99e5..8a31506 100644
> --- a/libsepol/src/policydb_internal.h
> +++ b/libsepol/src/policydb_internal.h
> @@ -6,4 +6,5 @@
>
> hidden_proto(sepol_policydb_create)
> hidden_proto(sepol_policydb_free)
> +extern char *policydb_target_strings[];
> #endif
> diff --git a/libsepol/src/write.c b/libsepol/src/write.c
> index 66b35ec..a557c2e 100644
> --- a/libsepol/src/write.c
> +++ b/libsepol/src/write.c
> @@ -1084,10 +1084,79 @@ static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
> common_write, class_write, role_write, type_write, user_write,
> cond_write_bool, sens_write, cat_write,};
>
> -static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
> +static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
> struct policy_file *fp)
> {
> unsigned int i, j;
> + size_t nel, items;
> + uint32_t buf[32];
> + ocontext_t *c;
> + for (i = 0; i< info->ocon_num; i++) {
> + nel = 0;
> + for (c = p->ocontexts[i]; c; c = c->next)
> + nel++;
> + buf[0] = cpu_to_le32(nel);
> + items = put_entry(buf, sizeof(uint32_t), 1, fp);
> + if (items != 1)
> + return POLICYDB_ERROR;
> + for (c = p->ocontexts[i]; c; c = c->next) {
> + switch (i) {
> + case OCON_ISID:
> + buf[0] = cpu_to_le32(c->sid[0]);
> + items = put_entry(buf, sizeof(uint32_t), 1, fp);
> + if (items != 1)
> + return POLICYDB_ERROR;
> + if (context_write(p,&c->context[0], fp))
> + return POLICYDB_ERROR;
> + break;
> + case OCON_PIRQ:
> + buf[0] = cpu_to_le32(c->u.pirq);
> + items = put_entry(buf, sizeof(uint32_t), 1, fp);
> + if (items != 1)
> + return POLICYDB_ERROR;
> + if (context_write(p,&c->context[0], fp))
> + return POLICYDB_ERROR;
> + break;
> + case OCON_IOPORT:
> + buf[0] = c->u.ioport.low_ioport;
> + buf[1] = c->u.ioport.high_ioport;
> + for (j = 0; j< 2; j++)
> + buf[j] = cpu_to_le32(buf[j]);
> + items = put_entry(buf, sizeof(uint32_t), 2, fp);
> + if (items != 2)
> + return POLICYDB_ERROR;
> + if (context_write(p,&c->context[0], fp))
> + return POLICYDB_ERROR;
> + break;
> + case OCON_IOMEM:
> + buf[0] = c->u.iomem.low_iomem;
> + buf[1] = c->u.iomem.high_iomem;
> + for (j = 0; j< 2; j++)
> + buf[j] = cpu_to_le32(buf[j]);
> + items = put_entry(buf, sizeof(uint32_t), 2, fp);
> + if (items != 2)
> + return POLICYDB_ERROR;
> + if (context_write(p,&c->context[0], fp))
> + return POLICYDB_ERROR;
> + break;
> + case OCON_DEVICE:
> + buf[0] = cpu_to_le32(c->u.device);
> + items = put_entry(buf, sizeof(uint32_t), 1, fp);
> + if (items != 1)
> + return POLICYDB_ERROR;
> + if (context_write(p,&c->context[0], fp))
> + return POLICYDB_ERROR;
> + break;
> + }
> + }
> + }
> + return POLICYDB_SUCCESS;
> +}
> +
> +static int ocontext_write_selinux(struct policydb_compat_info *info,
> + policydb_t *p, struct policy_file *fp)
> +{
> + unsigned int i, j;
> size_t nel, items, len;
> uint32_t buf[32];
> ocontext_t *c;
> @@ -1176,6 +1245,21 @@ static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
> return POLICYDB_SUCCESS;
> }
>
> +static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
> + struct policy_file *fp)
> +{
> + int rc = POLICYDB_ERROR;
> + switch (p->target_type) {
> + case SEPOL_TARGET_SELINUX:
> + rc = ocontext_write_selinux(info, p, fp);
> + break;
> + case SEPOL_TARGET_XEN:
> + rc = ocontext_write_xen(info, p, fp);
> + break;
> + }
> + return rc;
> +}
> +
> static int genfs_write(policydb_t * p, struct policy_file *fp)
> {
> genfs_t *genfs;
> @@ -1610,8 +1694,8 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
> items = 0;
> if (p->policy_type == POLICY_KERN) {
> buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
> - len = strlen(POLICYDB_STRING);
> - policydb_str = POLICYDB_STRING;
> + len = strlen(policydb_target_strings[p->target_type]);
> + policydb_str = policydb_target_strings[p->target_type];
> } else {
> buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
> len = strlen(POLICYDB_MOD_STRING);
> diff --git a/sepolgen/src/sepolgen/refparser.py b/sepolgen/src/sepolgen/refparser.py
> index 65d1d90..23beb39 100644
> --- a/sepolgen/src/sepolgen/refparser.py
> +++ b/sepolgen/src/sepolgen/refparser.py
> @@ -83,6 +83,10 @@ tokens = (
> 'PORTCON',
> 'NODECON',
> 'NETIFCON',
> + 'PIRQCON',
> + 'IOMEMCON',
> + 'IOPORTCON',
> + 'PCIDEVICECON',
> # object classes
> 'CLASS',
> # types and attributes
> @@ -140,6 +144,10 @@ reserved = {
> 'portcon' : 'PORTCON',
> 'nodecon' : 'NODECON',
> 'netifcon' : 'NETIFCON',
> + 'pirqcon' : 'PIRQCON',
> + 'iomemcon' : 'IOMEMCON',
> + 'ioportcon' : 'IOPORTCON',
> + 'pcidevicecon' : 'PCIDEVICECON',
> # object classes
> 'class' : 'CLASS',
> # types and attributes
> @@ -495,6 +503,10 @@ def p_policy_stmt(p):
> | portcon
> | nodecon
> | netifcon
> + | pirqcon
> + | iomemcon
> + | ioportcon
> + | pcidevicecon
> '''
> if p[1]:
> p[0] = [p[1]]
> @@ -631,6 +643,48 @@ def p_netifcon(p):
>
> p[0] = n
>
> +def p_pirqcon(p):
> + 'pirqcon : PIRQCON NUMBER context'
> + c = refpolicy.PirqCon()
> + c.pirq_number = p[2]
> + c.context = p[3]
> +
> + p[0] = c
> +
> +def p_iomemcon(p):
> + '''iomemcon : IOMEMCON NUMBER context
> + | IOMEMCON NUMBER MINUS NUMBER context'''
> + c = refpolicy.IomemCon()
> + if len(p) == 4:
> + c.device_mem = p[2]
> + c.context = p[3]
> + else:
> + c.device_mem = p[2] + "-" + p[3]
> + c.context = p[4]
> +
> + p[0] = c
> +
> +def p_ioportcon(p):
> + '''ioportcon : IOPORTCON NUMBER context
> + | IOPORTCON NUMBER MINUS NUMBER context'''
> + c = refpolicy.IoportCon()
> + if len(p) == 4:
> + c.ioport = p[2]
> + c.context = p[3]
> + else:
> + c.ioport = p[2] + "-" + p[3]
> + c.context = p[4]
> +
> + p[0] = c
> +
> +def p_pcidevicecon(p):
> + 'pcidevicecon : PCIDEVICECON NUMBER context'
> + c = refpolicy.PciDeviceCon()
> + c.device = p[2]
> + c.context = p[3]
> +
> + p[0] = c
> +
> def p_mls_range_def(p):
> '''mls_range_def : mls_level_def MINUS mls_level_def
> | mls_level_def
> diff --git a/sepolgen/src/sepolgen/refpolicy.py b/sepolgen/src/sepolgen/refpolicy.py
> index 724b870..b138e3d 100644
> --- a/sepolgen/src/sepolgen/refpolicy.py
> +++ b/sepolgen/src/sepolgen/refpolicy.py
> @@ -618,6 +618,41 @@ class NetifCon(Leaf):
> def to_string(self):
> return "netifcon %s %s %s" % (self.interface, str(self.interface_context),
> str(self.packet_context))
> +class PirqCon(Leaf):
> + def __init__(self, parent=None):
> + Leaf.__init__(self, parent)
> + self.pirq_number = ""
> + self.context = None
> +
> + def to_string(self):
> + return "pirqcon %s %s" % (self.pirq_number, str(self.context))
> +
> +class IomemCon(Leaf):
> + def __init__(self, parent=None):
> + Leaf.__init__(self, parent)
> + self.device_mem = ""
> + self.context = None
> +
> + def to_string(self):
> + return "iomemcon %s %s" % (self.device_mem, str(self.context))
> +
> +class IoportCon(Leaf):
> + def __init__(self, parent=None):
> + Leaf.__init__(self, parent)
> + self.ioport = ""
> + self.context = None
> +
> + def to_string(self):
> + return "ioportcon %s %s" % (self.ioport, str(self.context))
> +
> +class PciDeviceCon(Leaf):
> + def __init__(self, parent=None):
> + Leaf.__init__(self, parent)
> + self.device = ""
> + self.context = None
> +
> + def to_string(self):
> + return "pcidevicecon %s %s" % (self.device, str(self.context))
>
> # Reference policy specific types
>
>
>
> --
> This message was distributed to subscribers of the selinux mailing list.
> If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
> the words "unsubscribe selinux" without quotes as the message.
>
>
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] libsepol/checkpolicy: Add support for multiple target OSes
2009-09-14 19:07 ` Joshua Brindle
@ 2009-09-14 19:33 ` Stephen Smalley
2009-09-15 13:07 ` Stephen Smalley
2009-09-15 17:09 ` Chad Sellers
0 siblings, 2 replies; 6+ messages in thread
From: Stephen Smalley @ 2009-09-14 19:33 UTC (permalink / raw)
To: Joshua Brindle; +Cc: pjnuzzi, selinux
On Mon, 2009-09-14 at 15:07 -0400, Joshua Brindle wrote:
> On 09/14/2009 09:22 AM, pjnuzzi wrote:
> > Add support for multiple target OSes to libsepol and checkpolicy, where
> >
>
> what about checkmodule?
At present, the patch only deals with monolithic policy. To update for
modular policy, we'd need to introduce multiple string identifiers in
the modular format as well. Which could be done, but I'm not sure it is
worthwhile given plans for replacing the module format. The other
option is to select the output target platform in libsemanage via
semanage.conf configuration rather than embedding the target in the
modules.
> > the particular target OS is selected using a new -t target option to
> > checkpolicy. The default target remains SELinux. A new target and
> > support is introduced for Xen. The target OS is identified in the
> > policy image by using different policy string identifiers in the header.
> > At present, policy string identifiers are required to have the same
> > length for ease of parsing the header and to preserve file(1) parsing of
> >
>
> That is not the case today. Does file really not have the ability to
> read a length and then a string of that length?
I'm not sure what you mean by "not the case today". The current
libsepol code does require a specific length and won't even try to read
the string if the length does not match the expected value, and the
existing /usr/share/magic definition for file(1) parsing expects fixed
offsets for the fields after the string identifier. We could certainly
relax that requirement, but then we'd have to update /usr/share/magic
everywhere. That seemed unnecessary - a string of 8 characters is
sufficient to identify the full range of possible target OSes.
> > subsequent fields after the string identifier. For SELinux, the string
> > identifier remains "SE Linux". For Xen, the string identifier is
> > "XenFlask". The latent support for just "Flask" in the policy reading
> > code that was introduced for FMAC is dropped; a separate identifier for
> >
>
> Was it already in use? I don't think arbitrarily dropping identifiers is
> a good idea.
Only in the FMAC checkpolicy program. Not precisely production code,
and if we want to customize the policy format for OpenSolaris, we'll
want a distinctive string identifier anyway, not just a generic "Flask".
Easy to fix on the OpenSolaris FMAC side if it resumes development.
> > Solaris (e.g. "SolFlask") will be introduced later using this new target
> > mechanism if needed. The same support can easily be extended for other
> > OSes.
> This is a fairly large patch, it might take a while to get through it.
> Splitting it up would have been helpful.
Sorry - based on Chad's earlier comment in response to another patch
that a complete single patch against the selinux tree was fine, and
given that this does form a single logical change against a single
repository, I recommended keeping it as a single patch.
FWIW, I have reviewed this patch.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libsepol/checkpolicy: Add support for multiple target OSes
2009-09-14 19:33 ` Stephen Smalley
@ 2009-09-15 13:07 ` Stephen Smalley
2009-09-15 17:09 ` Chad Sellers
1 sibling, 0 replies; 6+ messages in thread
From: Stephen Smalley @ 2009-09-15 13:07 UTC (permalink / raw)
To: Joshua Brindle; +Cc: pjnuzzi, selinux
On Mon, 2009-09-14 at 15:33 -0400, Stephen Smalley wrote:
> On Mon, 2009-09-14 at 15:07 -0400, Joshua Brindle wrote:
> > On 09/14/2009 09:22 AM, pjnuzzi wrote:
> > > Add support for multiple target OSes to libsepol and checkpolicy, where
> > >
> >
> > what about checkmodule?
>
> At present, the patch only deals with monolithic policy. To update for
> modular policy, we'd need to introduce multiple string identifiers in
> the modular format as well. Which could be done, but I'm not sure it is
> worthwhile given plans for replacing the module format. The other
> option is to select the output target platform in libsemanage via
> semanage.conf configuration rather than embedding the target in the
> modules.
>
> > > the particular target OS is selected using a new -t target option to
> > > checkpolicy. The default target remains SELinux. A new target and
> > > support is introduced for Xen. The target OS is identified in the
> > > policy image by using different policy string identifiers in the header.
> > > At present, policy string identifiers are required to have the same
> > > length for ease of parsing the header and to preserve file(1) parsing of
> > >
> >
> > That is not the case today. Does file really not have the ability to
> > read a length and then a string of that length?
>
> I'm not sure what you mean by "not the case today". The current
> libsepol code does require a specific length and won't even try to read
> the string if the length does not match the expected value, and the
> existing /usr/share/magic definition for file(1) parsing expects fixed
> offsets for the fields after the string identifier. We could certainly
> relax that requirement, but then we'd have to update /usr/share/magic
> everywhere. That seemed unnecessary - a string of 8 characters is
> sufficient to identify the full range of possible target OSes.
Ah, actually, I see that the patch doesn't handle the modular policy
case correctly there. So we'll re-spin the patch and loosen the fixed
length restriction in our code, even though I expect we'll keep it in
practice due to existing /usr/share/magic definitions.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libsepol/checkpolicy: Add support for multiple target OSes
2009-09-14 19:33 ` Stephen Smalley
2009-09-15 13:07 ` Stephen Smalley
@ 2009-09-15 17:09 ` Chad Sellers
2009-09-15 17:18 ` Stephen Smalley
1 sibling, 1 reply; 6+ messages in thread
From: Chad Sellers @ 2009-09-15 17:09 UTC (permalink / raw)
To: Stephen Smalley, Joshua Brindle; +Cc: pjnuzzi, selinux
On 9/14/09 3:33 PM, "Stephen Smalley" <sds@tycho.nsa.gov> wrote:
> On Mon, 2009-09-14 at 15:07 -0400, Joshua Brindle wrote:
>> On 09/14/2009 09:22 AM, pjnuzzi wrote:
>>> Add support for multiple target OSes to libsepol and checkpolicy, where
>>>
<snip>
>>> Solaris (e.g. "SolFlask") will be introduced later using this new target
>>> mechanism if needed. The same support can easily be extended for other
>>> OSes.
>
>> This is a fairly large patch, it might take a while to get through it.
>> Splitting it up would have been helpful.
>
> Sorry - based on Chad's earlier comment in response to another patch
> that a complete single patch against the selinux tree was fine, and
> given that this does form a single logical change against a single
> repository, I recommended keeping it as a single patch.
>
Sorry if I created confusion. I was just meaning splitting on component
(libsepol, checkpolicy, etc.) was unnecessary. Splitting into logical pieces
is still preferred, and I have a hard time believing that a patch this large
could not be split into logical pieces.
Thanks,
Chad
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] libsepol/checkpolicy: Add support for multiple target OSes
2009-09-15 17:09 ` Chad Sellers
@ 2009-09-15 17:18 ` Stephen Smalley
0 siblings, 0 replies; 6+ messages in thread
From: Stephen Smalley @ 2009-09-15 17:18 UTC (permalink / raw)
To: Chad Sellers; +Cc: Joshua Brindle, pjnuzzi, selinux
On Tue, 2009-09-15 at 13:09 -0400, Chad Sellers wrote:
> On 9/14/09 3:33 PM, "Stephen Smalley" <sds@tycho.nsa.gov> wrote:
>
> > On Mon, 2009-09-14 at 15:07 -0400, Joshua Brindle wrote:
> >> On 09/14/2009 09:22 AM, pjnuzzi wrote:
> >>> Add support for multiple target OSes to libsepol and checkpolicy, where
> >>>
> <snip>
> >>> Solaris (e.g. "SolFlask") will be introduced later using this new target
> >>> mechanism if needed. The same support can easily be extended for other
> >>> OSes.
> >
> >> This is a fairly large patch, it might take a while to get through it.
> >> Splitting it up would have been helpful.
> >
> > Sorry - based on Chad's earlier comment in response to another patch
> > that a complete single patch against the selinux tree was fine, and
> > given that this does form a single logical change against a single
> > repository, I recommended keeping it as a single patch.
> >
> Sorry if I created confusion. I was just meaning splitting on component
> (libsepol, checkpolicy, etc.) was unnecessary. Splitting into logical pieces
> is still preferred, and I have a hard time believing that a patch this large
> could not be split into logical pieces.
It was one logical change - adding support for multiple target OSes,
where the Xen support represented the first new target. In any event,
the patch was just re-posted split along component boundaries. But note
that one of the reasons for such splitting in the Linux kernel case is
because different subsystems have different maintainers there. In the
case of the selinux userland tree, there is one repo and one set of
maintainers for the entire tree, so it isn't clear that this is needed.
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-09-15 17:18 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-09-14 13:22 [PATCH] libsepol/checkpolicy: Add support for multiple target OSes pjnuzzi
2009-09-14 19:07 ` Joshua Brindle
2009-09-14 19:33 ` Stephen Smalley
2009-09-15 13:07 ` Stephen Smalley
2009-09-15 17:09 ` Chad Sellers
2009-09-15 17:18 ` Stephen Smalley
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.