selinux: convert cond_expr to array

Since it is fixed-size after allocation and we know the size beforehand,
using a plain old array is simpler and more efficient.

Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Reviewed-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
Ondrej Mosnacek 2020-02-03 12:27:22 +01:00 committed by Paul Moore
parent 2b3a003e15
commit 8794d78390
2 changed files with 33 additions and 43 deletions

View file

@ -23,18 +23,19 @@
*/ */
static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr) static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
{ {
u32 i;
struct cond_expr *cur;
int s[COND_EXPR_MAXDEPTH]; int s[COND_EXPR_MAXDEPTH];
int sp = -1; int sp = -1;
for (cur = expr; cur; cur = cur->next) { for (i = 0; i < expr->len; i++) {
switch (cur->expr_type) { struct cond_expr_node *node = &expr->nodes[i];
switch (node->expr_type) {
case COND_BOOL: case COND_BOOL:
if (sp == (COND_EXPR_MAXDEPTH - 1)) if (sp == (COND_EXPR_MAXDEPTH - 1))
return -1; return -1;
sp++; sp++;
s[sp] = p->bool_val_to_struct[cur->bool - 1]->state; s[sp] = p->bool_val_to_struct[node->bool - 1]->state;
break; break;
case COND_NOT: case COND_NOT:
if (sp < 0) if (sp < 0)
@ -91,7 +92,7 @@ void evaluate_cond_node(struct policydb *p, struct cond_node *node)
int new_state; int new_state;
u32 i; u32 i;
new_state = cond_evaluate_expr(p, node->expr); new_state = cond_evaluate_expr(p, &node->expr);
if (new_state != node->cur_state) { if (new_state != node->cur_state) {
node->cur_state = new_state; node->cur_state = new_state;
if (new_state == -1) if (new_state == -1)
@ -133,12 +134,7 @@ int cond_policydb_init(struct policydb *p)
static void cond_node_destroy(struct cond_node *node) static void cond_node_destroy(struct cond_node *node)
{ {
struct cond_expr *cur_expr, *next_expr; kfree(node->expr.nodes);
for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) {
next_expr = cur_expr->next;
kfree(cur_expr);
}
/* the avtab_ptr_t nodes are destroyed by the avtab */ /* the avtab_ptr_t nodes are destroyed by the avtab */
kfree(node->true_list.nodes); kfree(node->true_list.nodes);
kfree(node->false_list.nodes); kfree(node->false_list.nodes);
@ -355,7 +351,7 @@ static int cond_read_av_list(struct policydb *p, void *fp,
return 0; return 0;
} }
static int expr_isvalid(struct policydb *p, struct cond_expr *expr) static int expr_node_isvalid(struct policydb *p, struct cond_expr_node *expr)
{ {
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
pr_err("SELinux: conditional expressions uses unknown operator.\n"); pr_err("SELinux: conditional expressions uses unknown operator.\n");
@ -372,43 +368,37 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
{ {
__le32 buf[2]; __le32 buf[2];
u32 len, i; u32 i, len;
int rc; int rc;
struct cond_expr *expr = NULL, *last = NULL;
rc = next_entry(buf, fp, sizeof(u32) * 2); rc = next_entry(buf, fp, sizeof(u32) * 2);
if (rc) if (rc)
goto err; return rc;
node->cur_state = le32_to_cpu(buf[0]); node->cur_state = le32_to_cpu(buf[0]);
/* expr */ /* expr */
len = le32_to_cpu(buf[1]); len = le32_to_cpu(buf[1]);
node->expr.nodes = kcalloc(len, sizeof(*node->expr.nodes), GFP_KERNEL);
if (!node->expr.nodes)
return -ENOMEM;
node->expr.len = len;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
struct cond_expr_node *expr = &node->expr.nodes[i];
rc = next_entry(buf, fp, sizeof(u32) * 2); rc = next_entry(buf, fp, sizeof(u32) * 2);
if (rc) if (rc)
goto err; goto err;
rc = -ENOMEM;
expr = kzalloc(sizeof(*expr), GFP_KERNEL);
if (!expr)
goto err;
expr->expr_type = le32_to_cpu(buf[0]); expr->expr_type = le32_to_cpu(buf[0]);
expr->bool = le32_to_cpu(buf[1]); expr->bool = le32_to_cpu(buf[1]);
if (!expr_isvalid(p, expr)) { if (!expr_node_isvalid(p, expr)) {
rc = -EINVAL; rc = -EINVAL;
kfree(expr);
goto err; goto err;
} }
if (i == 0)
node->expr = expr;
else
last->next = expr;
last = expr;
} }
rc = cond_read_av_list(p, fp, &node->true_list, NULL); rc = cond_read_av_list(p, fp, &node->true_list, NULL);
@ -513,27 +503,23 @@ static int cond_write_av_list(struct policydb *p,
static int cond_write_node(struct policydb *p, struct cond_node *node, static int cond_write_node(struct policydb *p, struct cond_node *node,
struct policy_file *fp) struct policy_file *fp)
{ {
struct cond_expr *cur_expr;
__le32 buf[2]; __le32 buf[2];
int rc; int rc;
u32 len = 0; u32 i;
buf[0] = cpu_to_le32(node->cur_state); buf[0] = cpu_to_le32(node->cur_state);
rc = put_entry(buf, sizeof(u32), 1, fp); rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc) if (rc)
return rc; return rc;
for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) buf[0] = cpu_to_le32(node->expr.len);
len++;
buf[0] = cpu_to_le32(len);
rc = put_entry(buf, sizeof(u32), 1, fp); rc = put_entry(buf, sizeof(u32), 1, fp);
if (rc) if (rc)
return rc; return rc;
for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { for (i = 0; i < node->expr.len; i++) {
buf[0] = cpu_to_le32(cur_expr->expr_type); buf[0] = cpu_to_le32(node->expr.nodes[i].expr_type);
buf[1] = cpu_to_le32(cur_expr->bool); buf[1] = cpu_to_le32(node->expr.nodes[i].bool);
rc = put_entry(buf, sizeof(u32), 2, fp); rc = put_entry(buf, sizeof(u32), 2, fp);
if (rc) if (rc)
return rc; return rc;

View file

@ -19,7 +19,7 @@
* A conditional expression is a list of operators and operands * A conditional expression is a list of operators and operands
* in reverse polish notation. * in reverse polish notation.
*/ */
struct cond_expr { struct cond_expr_node {
#define COND_BOOL 1 /* plain bool */ #define COND_BOOL 1 /* plain bool */
#define COND_NOT 2 /* !bool */ #define COND_NOT 2 /* !bool */
#define COND_OR 3 /* bool || bool */ #define COND_OR 3 /* bool || bool */
@ -28,9 +28,13 @@ struct cond_expr {
#define COND_EQ 6 /* bool == bool */ #define COND_EQ 6 /* bool == bool */
#define COND_NEQ 7 /* bool != bool */ #define COND_NEQ 7 /* bool != bool */
#define COND_LAST COND_NEQ #define COND_LAST COND_NEQ
__u32 expr_type; u32 expr_type;
__u32 bool; u32 bool;
struct cond_expr *next; };
struct cond_expr {
struct cond_expr_node *nodes;
u32 len;
}; };
/* /*
@ -52,7 +56,7 @@ struct cond_av_list {
*/ */
struct cond_node { struct cond_node {
int cur_state; int cur_state;
struct cond_expr *expr; struct cond_expr expr;
struct cond_av_list true_list; struct cond_av_list true_list;
struct cond_av_list false_list; struct cond_av_list false_list;
}; };