libsepol, checkpolicy: widen Xen IOMEM ocontext entries

This expands IOMEMCON device context entries to 64 bits.  This change is
required to support static I/O memory range labeling for systems with
over 16TB of physical address space.  The policy version number change
is shared with the next patch.

While this makes no changes to SELinux policy, a new SELinux policy
compatibility entry was added in order to avoid breaking compilation of
an SELinux policy without explicitly specifying the policy version.

Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
This commit is contained in:
Daniel De Graaf 2015-03-17 16:43:23 -04:00 committed by Stephen Smalley
parent aab2d9f904
commit 82030de5dc
12 changed files with 109 additions and 32 deletions

View File

@ -39,6 +39,7 @@
#include <arpa/inet.h>
#include <stdlib.h>
#include <limits.h>
#include <inttypes.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/policydb.h>
@ -3932,7 +3933,7 @@ bad:
return -1;
}
int define_iomem_context(unsigned long low, unsigned long high)
int define_iomem_context(uint64_t low, uint64_t high)
{
ocontext_t *newc, *c, *l, *head;
char *id;
@ -3960,7 +3961,7 @@ int define_iomem_context(unsigned long low, unsigned long high)
newc->u.iomem.high_iomem = high;
if (low > high) {
yyerror2("low memory 0x%lx exceeds high memory 0x%lx", low, high);
yyerror2("low memory 0x%"PRIx64" exceeds high memory 0x%"PRIx64"", low, high);
free(newc);
return -1;
}
@ -3972,13 +3973,13 @@ int define_iomem_context(unsigned long low, unsigned long high)
head = policydbp->ocontexts[OCON_XEN_IOMEM];
for (l = NULL, c = head; c; l = c, c = c->next) {
uint32_t low2, high2;
uint64_t low2, high2;
low2 = c->u.iomem.low_iomem;
high2 = c->u.iomem.high_iomem;
if (low <= high2 && low2 <= high) {
yyerror2("iomemcon entry for 0x%lx-0x%lx overlaps with "
"earlier entry 0x%x-0x%x", low, high,
yyerror2("iomemcon entry for 0x%"PRIx64"-0x%"PRIx64" overlaps with "
"earlier entry 0x%"PRIx64"-0x%"PRIx64"", low, high,
low2, high2);
goto bad;
}

View File

@ -46,7 +46,7 @@ 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_iomem_context(uint64_t low, uint64_t 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);

View File

@ -67,6 +67,7 @@ typedef int (* require_func_t)(int pass);
%union {
unsigned int val;
uint64_t val64;
uintptr_t valptr;
void *ptr;
require_func_t require_func;
@ -78,6 +79,7 @@ typedef int (* require_func_t)(int pass);
%type <ptr> role_def roles
%type <valptr> cexpr cexpr_prim op role_mls_op
%type <val> ipv4_addr_def number
%type <val64> number64
%type <require_func> require_decl_def
%token PATH
@ -647,9 +649,9 @@ dev_context_def : pirq_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
iomem_context_def : IOMEMCON number64 security_context_def
{if (define_iomem_context($2,$2)) return -1;}
| IOMEMCON number '-' number security_context_def
| IOMEMCON number64 '-' number64 security_context_def
{if (define_iomem_context($2,$4)) return -1;}
;
ioport_context_def : IOPORTCON number security_context_def
@ -815,6 +817,9 @@ filename : FILENAME
number : NUMBER
{ $$ = strtoul(yytext,NULL,0); }
;
number64 : NUMBER
{ $$ = strtoull(yytext,NULL,0); }
;
ipv6_addr : IPV6_ADDR
{ if (insert_id(yytext,0)) return -1; }
;

View File

@ -4319,12 +4319,12 @@ int cil_gen_iomemcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_
if (parse_current->next->cl_head != NULL) {
if (parse_current->next->cl_head->next != NULL &&
parse_current->next->cl_head->next->next == NULL) {
rc = cil_fill_integer(parse_current->next->cl_head, &iomemcon->iomem_low);
rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Improper iomem specified\n");
goto exit;
}
rc = cil_fill_integer(parse_current->next->cl_head->next, &iomemcon->iomem_high);
rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Improper iomem specified\n");
goto exit;
@ -4335,7 +4335,7 @@ int cil_gen_iomemcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_
goto exit;
}
} else {
rc = cil_fill_integer(parse_current->next, &iomemcon->iomem_low);;
rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low);;
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Improper iomem specified\n");
goto exit;
@ -5054,6 +5054,32 @@ exit:
return rc;
}
int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer)
{
int rc = SEPOL_ERR;
char *endptr = NULL;
uint64_t val;
if (int_node == NULL || integer == NULL) {
goto exit;
}
errno = 0;
val = strtoull(int_node->data, &endptr, 10);
if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
rc = SEPOL_ERR;
goto exit;
}
*integer = val;
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Failed to create integer from string\n");
return rc;
}
int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
{
int rc = SEPOL_ERR;

View File

@ -211,6 +211,7 @@ int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats);
void cil_destroy_cats(struct cil_cats *cats);
int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context);
int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer);
int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer);
int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr);
int cil_fill_level(struct cil_tree_node *sens, struct cil_level *level);

View File

@ -719,8 +719,8 @@ struct cil_pirqcon {
};
struct cil_iomemcon {
uint32_t iomem_low;
uint32_t iomem_high;
uint64_t iomem_low;
uint64_t iomem_high;
char *context_str;
struct cil_context *context;
};

View File

@ -32,6 +32,7 @@
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <inttypes.h>
#include <sepol/policydb/conditional.h>
#include <sepol/errcodes.h>
@ -236,7 +237,7 @@ int cil_iomemcon_to_policy(FILE **file_arr, struct cil_sort *sort)
for (i = 0; i < sort->count; i++) {
struct cil_iomemcon *iomemcon = (struct cil_iomemcon*)sort->array[i];
fprintf(file_arr[NETIFCONS], "iomemcon %d-%d ", iomemcon->iomem_low, iomemcon->iomem_high);
fprintf(file_arr[NETIFCONS], "iomemcon %"PRId64"-%"PRId64" ", iomemcon->iomem_low, iomemcon->iomem_high);
cil_context_to_policy(file_arr, NETIFCONS, iomemcon->context);
fprintf(file_arr[NETIFCONS], ";\n");
}

View File

@ -29,6 +29,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>
#include <sepol/policydb/conditional.h>
@ -1392,7 +1393,7 @@ void cil_tree_print_node(struct cil_tree_node *node)
case CIL_IOMEMCON: {
struct cil_iomemcon *iomemcon = node->data;
cil_log(CIL_INFO, "IOMEMCON ( %d %d )", iomemcon->iomem_low, iomemcon->iomem_high);
cil_log(CIL_INFO, "IOMEMCON ( %"PRId64" %"PRId64" )", iomemcon->iomem_low, iomemcon->iomem_high);
if (iomemcon->context != NULL) {
cil_tree_print_context(iomemcon->context);
} else {

View File

@ -325,8 +325,8 @@ typedef struct ocontext {
uint32_t device;
uint16_t pirq;
struct {
uint32_t low_iomem;
uint32_t high_iomem;
uint64_t low_iomem;
uint64_t high_iomem;
} iomem;
struct {
uint32_t low_ioport;
@ -689,10 +689,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
#define POLICYDB_VERSION_DEFAULT_TYPE 28
#define POLICYDB_VERSION_CONSTRAINT_NAMES 29
#define POLICYDB_VERSION_XEN_DEVICETREE 30
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_CONSTRAINT_NAMES
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_XEN_DEVICETREE
/* Module versions and specific changes*/
#define MOD_POLICYDB_VERSION_BASE 4

View File

@ -66,6 +66,13 @@ static struct policydb_compat_info policydb_compat[] = {
.ocon_num = OCON_XEN_PCIDEVICE + 1,
.target_platform = SEPOL_TARGET_XEN,
},
{
.type = POLICY_KERN,
.version = POLICYDB_VERSION_XEN_DEVICETREE,
.sym_num = SYM_NUM,
.ocon_num = OCON_XEN_PCIDEVICE + 1,
.target_platform = SEPOL_TARGET_XEN,
},
{
.type = POLICY_KERN,
.version = POLICYDB_VERSION_BASE,
@ -171,6 +178,13 @@ static struct policydb_compat_info policydb_compat[] = {
.ocon_num = OCON_NODE6 + 1,
.target_platform = SEPOL_TARGET_SELINUX,
},
{
.type = POLICY_KERN,
.version = POLICYDB_VERSION_XEN_DEVICETREE,
.sym_num = SYM_NUM,
.ocon_num = OCON_NODE6 + 1,
.target_platform = SEPOL_TARGET_SELINUX,
},
{
.type = POLICY_BASE,
.version = MOD_POLICYDB_VERSION_BASE,
@ -2514,11 +2528,20 @@ static int ocontext_read_xen(struct policydb_compat_info *info,
return -1;
break;
case OCON_XEN_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 (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) {
uint64_t b64[2];
rc = next_entry(b64, fp, sizeof(uint64_t) * 2);
if (rc < 0)
return -1;
c->u.iomem.low_iomem = le64_to_cpu(b64[0]);
c->u.iomem.high_iomem = le64_to_cpu(b64[1]);
} else {
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;

View File

@ -1252,13 +1252,31 @@ static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
return POLICYDB_ERROR;
break;
case OCON_XEN_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 (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) {
uint64_t b64[2];
b64[0] = c->u.iomem.low_iomem;
b64[1] = c->u.iomem.high_iomem;
for (j = 0; j < 2; j++)
b64[j] = cpu_to_le64(b64[j]);
items = put_entry(b64, sizeof(uint64_t), 2, fp);
if (items != 2)
return POLICYDB_ERROR;
} else {
if (c->u.iomem.high_iomem > 0xFFFFFFFFULL) {
ERR(fp->handle, "policy version %d"
" cannot represent IOMEM addresses over 16TB",
p->policyvers);
return POLICYDB_ERROR;
}
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;

View File

@ -2695,8 +2695,8 @@ static int ocontext_xen_ioport_to_cil(struct policydb *pdb, struct ocontext *iop
static int ocontext_xen_iomem_to_cil(struct policydb *pdb, struct ocontext *iomems)
{
struct ocontext *iomem;
uint32_t low;
uint32_t high;
uint64_t low;
uint64_t high;
for (iomem = iomems; iomem != NULL; iomem = iomem->next) {
low = iomem->u.iomem.low_iomem;