diff --git a/BUILD.gn b/BUILD.gn
index af9b60ca7dcf40a5aad21406cf27313409e4cbd2..bb53bb4751eb8527ccea7844d9e84da9aa61ac1e 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -48,6 +48,7 @@ ohos_shared_library("libsepol") {
"$LIBSEPOL_ROOT_DIR/cil/src/cil_symtab.c",
"$LIBSEPOL_ROOT_DIR/cil/src/cil_tree.c",
"$LIBSEPOL_ROOT_DIR/cil/src/cil_verify.c",
+ "$LIBSEPOL_ROOT_DIR/cil/src/cil_write_ast.c",
"$LIBSEPOL_ROOT_DIR/src/assertion.c",
"$LIBSEPOL_ROOT_DIR/src/avrule_block.c",
"$LIBSEPOL_ROOT_DIR/src/avtab.c",
diff --git a/OAT.xml b/OAT.xml
index 88d2342844241dd6567f40c5216aea7321d3b189..49b18d1a59fe527be23f80db1c273c61a374d6bd 100644
--- a/OAT.xml
+++ b/OAT.xml
@@ -35,6 +35,7 @@
+
@@ -51,6 +52,9 @@
+
+
+
diff --git a/checkpolicy/.gitignore b/checkpolicy/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a7bd076d9df43328f543816433b02be35f31d7a9
--- /dev/null
+++ b/checkpolicy/.gitignore
@@ -0,0 +1,5 @@
+checkmodule
+checkpolicy
+lex.yy.c
+y.tab.c
+y.tab.h
diff --git a/checkpolicy/Makefile b/checkpolicy/Makefile
index 0d282ef93d14f5e15e385367e84c5742f1be7030..f9e1fc7cecd4e862e773a29097fce04dfbc99dab 100644
--- a/checkpolicy/Makefile
+++ b/checkpolicy/Makefile
@@ -10,7 +10,7 @@ TARGETS = checkpolicy checkmodule
LEX = flex
YACC = bison -y
-CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -pipe -fno-strict-aliasing
+CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -fno-strict-aliasing
# If no specific libsepol.a is specified, fall back on LDFLAGS search path
# Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there
@@ -30,10 +30,10 @@ all: $(TARGETS)
$(MAKE) -C test
checkpolicy: $(CHECKPOLOBJS) $(LIBSEPOLA)
- $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA)
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA)
checkmodule: $(CHECKMODOBJS) $(LIBSEPOLA)
- $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA)
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA)
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
diff --git a/checkpolicy/VERSION b/checkpolicy/VERSION
index a3ec5a4bd3d7209b4a687a77cad49b945339994b..eb39e5382f4f035e4d71c7f67712cdbfa6c0c335 100644
--- a/checkpolicy/VERSION
+++ b/checkpolicy/VERSION
@@ -1 +1 @@
-3.2
+3.3
diff --git a/checkpolicy/checkmodule.8 b/checkpolicy/checkmodule.8
index c4b1592b1d12b86736d99bebf08144f5b28acbcd..1061a6f2ce15d5389590136a5e18f1aef8b58845 100644
--- a/checkpolicy/checkmodule.8
+++ b/checkpolicy/checkmodule.8
@@ -3,7 +3,7 @@
checkmodule \- SELinux policy module compiler
.SH SYNOPSIS
.B checkmodule
-.I "[\-h] [\-b] [\-C] [\-m] [\-M] [\-U handle_unknown ] [\-V] [\-o output_file] [input_file]"
+.I "[\-h] [\-b] [\-c policy_version] [\-C] [\-E] [\-m] [\-M] [\-U handle_unknown] [\-V] [\-o output_file] [input_file]"
.SH "DESCRIPTION"
This manual page describes the
.BR checkmodule
@@ -15,9 +15,12 @@ into a binary representation. It can generate either a base policy
module (default) or a non-base policy module (\-m option); typically,
you would build a non-base policy module to add to an existing module
store that already has a base module provided by the base policy. Use
-semodule_package to combine this module with its optional file
-contexts to create a policy package, and then use semodule to install
-the module package into the module store and load the resulting policy.
+.B semodule_package(8)
+to combine this module with its optional file
+contexts to create a policy package, and then use
+.B semodule(8)
+to install the module package into the module store and load the resulting
+policy.
.SH OPTIONS
.TP
diff --git a/checkpolicy/checkmodule.c b/checkpolicy/checkmodule.c
index 40d0ec9924e9e540880807da98956fddc21eea70..3432608bef2ef2e96224238d37fb1654df6afbaa 100644
--- a/checkpolicy/checkmodule.c
+++ b/checkpolicy/checkmodule.c
@@ -34,9 +34,6 @@
#include "checkpolicy.h"
#include "parse_util.h"
-extern char *optarg;
-extern int optind;
-
static sidtab_t sidtab;
extern int mlspol;
@@ -126,7 +123,7 @@ static int write_binary_policy(policydb_t * p, FILE *outfp)
static __attribute__((__noreturn__)) void usage(const char *progname)
{
- printf("usage: %s [-h] [-V] [-b] [-C] [-E] [-U handle_unknown] [-m] [-M] [-o FILE] [INPUT]\n", progname);
+ printf("usage: %s [-h] [-V] [-b] [-C] [-E] [-U handle_unknown] [-m] [-M] [-o FILE] [-c VERSION] [INPUT]\n", progname);
printf("Build base and policy modules.\n");
printf("Options:\n");
printf(" INPUT build module from INPUT (else read from \"%s\")\n",
@@ -155,7 +152,7 @@ int main(int argc, char **argv)
int ch;
int show_version = 0;
policydb_t modpolicydb;
- struct option long_options[] = {
+ const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"output", required_argument, NULL, 'o'},
{"binary", no_argument, NULL, 'b'},
@@ -271,7 +268,7 @@ int main(int argc, char **argv)
} else {
if (policydb_init(&modpolicydb)) {
fprintf(stderr, "%s: out of memory!\n", argv[0]);
- return -1;
+ exit(1);
}
modpolicydb.policy_type = policy_type;
@@ -283,19 +280,21 @@ int main(int argc, char **argv)
}
if (hierarchy_check_constraints(NULL, &modpolicydb)) {
- return -1;
+ exit(1);
}
}
if (policy_type != POLICY_BASE && outfile) {
+ char *out_name;
+ char *separator;
char *mod_name = modpolicydb.name;
char *out_path = strdup(outfile);
if (out_path == NULL) {
fprintf(stderr, "%s: out of memory\n", argv[0]);
exit(1);
}
- char *out_name = basename(out_path);
- char *separator = strrchr(out_name, '.');
+ out_name = basename(out_path);
+ separator = strrchr(out_name, '.');
if (separator) {
*separator = '\0';
}
@@ -334,7 +333,7 @@ int main(int argc, char **argv)
FILE *outfp = fopen(outfile, "w");
if (!outfp) {
- perror(outfile);
+ fprintf(stderr, "%s: error opening %s: %s\n", argv[0], outfile, strerror(errno));
exit(1);
}
@@ -350,7 +349,10 @@ int main(int argc, char **argv)
}
}
- fclose(outfp);
+ if (fclose(outfp)) {
+ fprintf(stderr, "%s: error closing %s: %s\n", argv[0], outfile, strerror(errno));
+ exit(1);
+ }
} else if (cil) {
fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]);
exit(1);
diff --git a/checkpolicy/checkpolicy.8 b/checkpolicy/checkpolicy.8
index f4e6fb24cd57e2c76c12b69e88d58f8fbace27c2..2984c238f4d80c7139b516d1930c9f43cfe880ab 100644
--- a/checkpolicy/checkpolicy.8
+++ b/checkpolicy/checkpolicy.8
@@ -3,7 +3,7 @@
checkpolicy \- SELinux policy compiler
.SH SYNOPSIS
.B checkpolicy
-.I "[\-b[F]] [\-C] [\-d] [\-U handle_unknown (allow,deny,reject)] [\-M] [\-c policyvers] [\-o output_file|\-] [\-S] [\-t target_platform (selinux,xen)] [\-V] [input_file]"
+.I "[\-b[F]] [\-C] [\-d] [\-U handle_unknown (allow,deny,reject)] [\-M] [\-c policyvers] [\-o output_file|\-] [\-S] [\-t target_platform (selinux,xen)] [\-O] [\-E] [\-V] [input_file]"
.br
.SH "DESCRIPTION"
This manual page describes the
@@ -13,8 +13,10 @@ command.
.B checkpolicy
is a program that checks and compiles a SELinux security policy configuration
into a binary representation that can be loaded into the kernel. If no
-input file name is specified, checkpolicy will attempt to read from
-policy.conf or policy, depending on whether the \-b flag is specified.
+input file name is specified,
+.B checkpolicy
+will attempt to read from policy.conf or policy, depending on whether the \-b
+flag is specified.
.SH OPTIONS
.TP
diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 5841c5c4c1965f3cb93056edd2c7ea34577af25f..926ce72c1cfdd56bea93ca2f8e51e98e4155aa75 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -92,9 +92,6 @@
#include "checkpolicy.h"
#include "parse_util.h"
-extern char *optarg;
-extern int optind;
-
static policydb_t policydb;
static sidtab_t sidtab;
@@ -106,24 +103,27 @@ static int handle_unknown = SEPOL_DENY_UNKNOWN;
static const char *txtfile = "policy.conf";
static const char *binfile = "policy";
-unsigned int policyvers = POLICYDB_VERSION_MAX;
+unsigned int policyvers = 0;
static __attribute__((__noreturn__)) void usage(const char *progname)
{
printf
("usage: %s [-b[F]] [-C] [-d] [-U handle_unknown (allow,deny,reject)] [-M] "
- "[-c policyvers (%d-%d)] [-o output_file|-] [-S] "
+ "[-c policyvers (%d-%d)] [-o output_file|-] [-S] [-O] "
"[-t target_platform (selinux,xen)] [-E] [-V] [input_file]\n",
progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
exit(1);
}
#define FGETS(out, size, in) \
-if (fgets(out,size,in)==NULL) { \
- fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,\
- strerror(errno)); \
- exit(1);\
-}
+do { \
+ if (fgets(out,size,in)==NULL) { \
+ fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, \
+ strerror(errno)); \
+ exit(1);\
+ } \
+} while (0)
+
static int print_sid(sepol_security_id_t sid,
context_struct_t * context
__attribute__ ((unused)), void *data
@@ -294,9 +294,7 @@ static int identify_equiv_types(void)
}
#endif
-extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av);
-
-int display_bools(void)
+static int display_bools(void)
{
uint32_t i;
@@ -307,10 +305,10 @@ int display_bools(void)
return 0;
}
-void display_expr(cond_expr_t * exp)
+static void display_expr(const cond_expr_t * exp)
{
- cond_expr_t *cur;
+ const cond_expr_t *cur;
for (cur = exp; cur != NULL; cur = cur->next) {
switch (cur->expr_type) {
case COND_BOOL:
@@ -342,9 +340,9 @@ void display_expr(cond_expr_t * exp)
}
}
-int display_cond_expressions(void)
+static int display_cond_expressions(void)
{
- cond_node_t *cur;
+ const cond_node_t *cur;
for (cur = policydbp->cond_list; cur != NULL; cur = cur->next) {
printf("expression: ");
@@ -354,7 +352,7 @@ int display_cond_expressions(void)
return 0;
}
-int change_bool(char *name, int state)
+static int change_bool(const char *name, int state)
{
cond_bool_datum_t *bool;
@@ -409,7 +407,7 @@ int main(int argc, char **argv)
unsigned int reason;
int flags;
struct policy_file pf;
- struct option long_options[] = {
+ const struct option long_options[] = {
{"output", required_argument, NULL, 'o'},
{"target", required_argument, NULL, 't'},
{"binary", no_argument, NULL, 'b'},
@@ -501,8 +499,7 @@ int main(int argc, char **argv)
usage(argv[0]);
exit(1);
}
- if (policyvers != n)
- policyvers = n;
+ policyvers = n;
break;
}
case 'E':
@@ -515,7 +512,8 @@ int main(int argc, char **argv)
}
if (show_version) {
- printf("%d (compatibility range %d-%d)\n", policyvers,
+ printf("%d (compatibility range %d-%d)\n",
+ policyvers ? policyvers : POLICYDB_VERSION_MAX ,
POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN);
exit(0);
}
@@ -588,6 +586,16 @@ int main(int argc, char **argv)
exit(1);
}
}
+
+ if (policydbp->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ if (policyvers > policydbp->policyvers) {
+ fprintf(stderr, "Binary policies with version <= %u cannot be upgraded\n", POLICYDB_VERSION_PERMISSIVE);
+ } else if (policyvers) {
+ policydbp->policyvers = policyvers;
+ }
+ } else {
+ policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX;
+ }
} else {
if (conf) {
fprintf(stderr, "Can only generate policy.conf from binary policy\n");
@@ -629,6 +637,8 @@ int main(int argc, char **argv)
policydb_destroy(policydbp);
policydbp = &policydb;
}
+
+ policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX;
}
if (policydb_load_isids(&policydb, &sidtab))
@@ -654,8 +664,6 @@ int main(int argc, char **argv)
}
}
- policydb.policyvers = policyvers;
-
if (!cil) {
if (!conf) {
policydb.policy_type = POLICY_KERN;
@@ -693,7 +701,10 @@ int main(int argc, char **argv)
}
if (outfp != stdout) {
- fclose(outfp);
+ if(fclose(outfp)) {
+ fprintf(stderr, "%s: error closing %s: %s\n", argv[0], outfile, strerror(errno));
+ exit(1);
+ }
}
} else if (cil) {
fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]);
@@ -783,7 +794,7 @@ int main(int argc, char **argv)
case 0:
printf("\nallowed {");
for (i = 1; i <= sizeof(avd.allowed) * 8; i++) {
- if (avd.allowed & (1 << (i - 1))) {
+ if (avd.allowed & (UINT32_C(1) << (i - 1))) {
v.val = i;
ret =
hashtab_map(cladatum->
@@ -957,8 +968,12 @@ int main(int argc, char **argv)
printf("fs kdevname? ");
FGETS(ans, sizeof(ans), stdin);
ans[strlen(ans) - 1] = 0;
- sepol_fs_sid(ans, &ssid, &tsid);
- printf("fs_sid %d default_file_sid %d\n", ssid, tsid);
+ ret = sepol_fs_sid(ans, &ssid, &tsid);
+ if (ret) {
+ printf("unknown fs kdevname\n");
+ } else {
+ printf("fs_sid %d default_file_sid %d\n", ssid, tsid);
+ }
break;
case '9':
printf("protocol? ");
@@ -986,8 +1001,12 @@ int main(int argc, char **argv)
printf("netif name? ");
FGETS(ans, sizeof(ans), stdin);
ans[strlen(ans) - 1] = 0;
- sepol_netif_sid(ans, &ssid, &tsid);
- printf("if_sid %d default_msg_sid %d\n", ssid, tsid);
+ ret = sepol_netif_sid(ans, &ssid, &tsid);
+ if (ret) {
+ printf("unknown name\n");
+ } else {
+ printf("if_sid %d default_msg_sid %d\n", ssid, tsid);
+ }
break;
case 'b':{
char *p;
@@ -1166,8 +1185,6 @@ int main(int argc, char **argv)
printf("\nNo such class.\n");
break;
}
- cladatum =
- policydb.class_val_to_struct[tclass - 1];
} else {
ans[strlen(ans) - 1] = 0;
cladatum =
@@ -1219,8 +1236,6 @@ int main(int argc, char **argv)
printf("\nNo such class.\n");
break;
}
- cladatum =
- policydb.class_val_to_struct[tclass - 1];
} else {
ans[strlen(ans) - 1] = 0;
cladatum =
diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c
index ada7cb2ae9c726827ceecc5a2b5e91699746c760..5f5b0b19b511d81f040eb228c99f6e011fb2346a 100644
--- a/checkpolicy/module_compiler.c
+++ b/checkpolicy/module_compiler.c
@@ -165,7 +165,7 @@ static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_
decl->decl_id, dest_value);
if (ret == 1 && dest_value) {
- symtab_datum_t *s =
+ hashtab_datum_t s =
hashtab_search(policydbp->symtab[symbol_type].table,
key);
assert(s != NULL);
@@ -173,7 +173,7 @@ static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_
if (symbol_type == SYM_LEVELS) {
*dest_value = ((level_datum_t *)s)->level->sens;
} else {
- *dest_value = s->value;
+ *dest_value = ((symtab_datum_t *)s)->value;
}
} else if (ret == -2) {
return -2;
@@ -999,7 +999,7 @@ static int require_bool_tunable(int pass, int is_tunable)
if (is_tunable)
booldatum->flags |= COND_BOOL_FLAGS_TUNABLE;
retval =
- require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum,
+ require_symbol(SYM_BOOLS, id, booldatum,
&booldatum->s.value, &booldatum->s.value);
if (retval != 0) {
cond_destroy_bool(id, booldatum, NULL);
@@ -1051,7 +1051,7 @@ int require_sens(int pass)
return -1;
}
mls_level_init(level->level);
- retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level,
+ retval = require_symbol(SYM_LEVELS, id, level,
&level->level->sens, &level->level->sens);
if (retval != 0) {
free(id);
@@ -1089,7 +1089,7 @@ int require_cat(int pass)
}
cat_datum_init(cat);
- retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat,
+ retval = require_symbol(SYM_CATS, id, cat,
&cat->s.value, &cat->s.value);
if (retval != 0) {
free(id);
@@ -1104,14 +1104,14 @@ int require_cat(int pass)
return 0;
}
-static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
+static int is_scope_in_stack(const scope_datum_t * scope, const scope_stack_t * stack)
{
uint32_t i;
if (stack == NULL) {
return 0; /* no matching scope found */
}
if (stack->type == 1) {
- avrule_decl_t *decl = stack->decl;
+ const avrule_decl_t *decl = stack->decl;
for (i = 0; i < scope->decl_ids_len; i++) {
if (scope->decl_ids[i] == decl->decl_id) {
return 1;
@@ -1126,9 +1126,9 @@ static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
return is_scope_in_stack(scope, stack->parent);
}
-int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
+int is_id_in_scope(uint32_t symbol_type, const_hashtab_key_t id)
{
- scope_datum_t *scope =
+ const scope_datum_t *scope =
(scope_datum_t *) hashtab_search(policydbp->scope[symbol_type].
table, id);
if (scope == NULL) {
@@ -1138,7 +1138,7 @@ int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
}
static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
- scope_index_t * scope)
+ const scope_index_t * scope)
{
if (class_value > scope->class_perms_len) {
return 1;
@@ -1151,7 +1151,7 @@ static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
}
static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
- scope_stack_t * stack)
+ const scope_stack_t * stack)
{
if (stack == NULL) {
return 0; /* no matching scope found */
@@ -1173,12 +1173,12 @@ static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
return is_perm_in_stack(perm_value, class_value, stack->parent);
}
-int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id)
+int is_perm_in_scope(const_hashtab_key_t perm_id, const_hashtab_key_t class_id)
{
- class_datum_t *cladatum =
+ const class_datum_t *cladatum =
(class_datum_t *) hashtab_search(policydbp->p_classes.table,
class_id);
- perm_datum_t *perdatum;
+ const perm_datum_t *perdatum;
if (cladatum == NULL) {
return 1;
}
@@ -1361,17 +1361,17 @@ int begin_optional_else(int pass)
return 0;
}
-static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
+static int copy_requirements(avrule_decl_t * dest, const scope_stack_t * stack)
{
uint32_t i;
if (stack == NULL) {
return 0;
}
if (stack->type == 1) {
- scope_index_t *src_scope = &stack->decl->required;
+ const scope_index_t *src_scope = &stack->decl->required;
scope_index_t *dest_scope = &dest->required;
for (i = 0; i < SYM_NUM; i++) {
- ebitmap_t *src_bitmap = &src_scope->scope[i];
+ const ebitmap_t *src_bitmap = &src_scope->scope[i];
ebitmap_t *dest_bitmap = &dest_scope->scope[i];
if (ebitmap_union(dest_bitmap, src_bitmap)) {
yyerror("Out of memory!");
@@ -1397,7 +1397,7 @@ static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
src_scope->class_perms_len;
}
for (i = 0; i < src_scope->class_perms_len; i++) {
- ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
+ const ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
ebitmap_t *dest_bitmap =
&dest_scope->class_perms_map[i];
if (ebitmap_union(dest_bitmap, src_bitmap)) {
diff --git a/checkpolicy/module_compiler.h b/checkpolicy/module_compiler.h
index 72c2d9bb9931f3d16e000219a4b42831cedcf1dd..29b824b425d563813cc3f69841a4fd29363bfa06 100644
--- a/checkpolicy/module_compiler.h
+++ b/checkpolicy/module_compiler.h
@@ -65,12 +65,12 @@ int require_cat(int pass);
/* Check if an identifier is within the scope of the current
* declaration or any of its parents. Return 1 if it is, 0 if not.
* If the identifier is not known at all then return 1 (truth). */
-int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id);
+int is_id_in_scope(uint32_t symbol_type, const_hashtab_key_t id);
/* Check if a particular permission is within the scope of the current
* declaration or any of its parents. Return 1 if it is, 0 if not.
* If the identifier is not known at all then return 1 (truth). */
-int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id);
+int is_perm_in_scope(const_hashtab_key_t perm_id, const_hashtab_key_t class_id);
/* Search the current avrules block for a conditional with the same
* expression as 'cond'. If the conditional does not exist then
diff --git a/checkpolicy/parse_util.c b/checkpolicy/parse_util.c
index f2809b483be38df655e0d41b830277c43f0c0a3c..8c1f393cec7e65cc90387669955f265fc1e61e65 100644
--- a/checkpolicy/parse_util.c
+++ b/checkpolicy/parse_util.c
@@ -28,7 +28,6 @@ extern int yyparse(void);
extern void yyrestart(FILE *);
extern queue_t id_queue;
extern unsigned int policydb_errors;
-extern unsigned long policydb_lineno;
extern policydb_t *policydbp;
extern int mlspol;
extern void set_source_file(const char *name);
@@ -37,7 +36,7 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname)
{
yyin = fopen(file, "r");
if (!yyin) {
- fprintf(stderr, "%s: unable to open %s\n", progname, file);
+ fprintf(stderr, "%s: unable to open %s: %s\n", progname, file, strerror(errno));
return -1;
}
set_source_file(file);
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index c9286f7733c5193b4313d928ebd27e22f417a4a9..d3eb6111ead4b2be817816a9f11e00bb606eb669 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -60,10 +60,13 @@
#include "module_compiler.h"
#include "policy_define.h"
+extern void init_parser(int pass_number);
+__attribute__ ((format(printf, 1, 2)))
+extern void yyerror2(const char *fmt, ...);
+
policydb_t *policydbp;
queue_t id_queue = 0;
unsigned int pass;
-char *curfile = 0;
int mlspol = 0;
extern unsigned long policydb_lineno;
@@ -74,12 +77,6 @@ extern char source_file[PATH_MAX];
extern int yywarn(const char *msg);
extern int yyerror(const char *msg);
-#define ERRORMSG_LEN 255
-static char errormsg[ERRORMSG_LEN + 1] = {0};
-
-static int id_has_dot(char *id);
-static int parse_security_context(context_struct_t *c);
-
/* initialize all of the state variables for the scanner/parser */
void init_parser(int pass_number)
{
@@ -89,12 +86,12 @@ void init_parser(int pass_number)
pass = pass_number;
}
-__attribute__ ((format(printf, 1, 2)))
void yyerror2(const char *fmt, ...)
{
+ char errormsg[256];
va_list ap;
va_start(ap, fmt);
- vsnprintf(errormsg, ERRORMSG_LEN, fmt, ap);
+ vsnprintf(errormsg, sizeof(errormsg), fmt, ap);
yyerror(errormsg);
va_end(ap);
}
@@ -141,7 +138,7 @@ int insert_id(const char *id, int push)
/* If the identifier has a dot within it and that its first character
is not a dot then return 1, else return 0. */
-static int id_has_dot(char *id)
+static int id_has_dot(const char *id)
{
if (strchr(id, '.') >= id + 1) {
return 1;
@@ -1168,11 +1165,6 @@ int expand_attrib(void)
ebitmap_init(&attrs);
while ((id = queue_remove(id_queue))) {
- if (!id) {
- yyerror("No attribute name for expandattribute statement?");
- goto exit;
- }
-
if (!is_id_in_scope(SYM_TYPES, id)) {
yyerror2("attribute %s is not within scope", id);
goto exit;
@@ -1610,7 +1602,7 @@ static int set_types(type_set_t * set, char *id, int *add, char starallowed)
return -1;
}
-int define_compute_type_helper(int which, avrule_t ** rule)
+static int define_compute_type_helper(int which, avrule_t ** rule)
{
char *id;
type_datum_t *datum;
@@ -1801,7 +1793,7 @@ int define_bool_tunable(int is_tunable)
return -1;
}
- datum->state = (int)(bool_value[0] == 'T') ? 1 : 0;
+ datum->state = (bool_value[0] == 'T') ? 1 : 0;
free(bool_value);
return 0;
cleanup:
@@ -1837,7 +1829,7 @@ struct av_ioctl_range_list {
struct av_ioctl_range_list *next;
};
-int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead)
+static int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_ioctl_range_list *r, *r2, *sorted, *sortedhead = NULL;
@@ -1885,7 +1877,7 @@ error:
return -1;
}
-int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
+static int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_ioctl_range_list *r, *tmp;
r = *rangehead;
@@ -1905,13 +1897,14 @@ int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
return 0;
}
-int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
+static int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
{
char *id;
struct av_ioctl_range_list *rnew, *r = NULL;
- *rangehead = NULL;
uint8_t omit = 0;
+ *rangehead = NULL;
+
/* read in all the ioctl commands */
while ((id = queue_remove(id_queue))) {
if (strcmp(id,"~") == 0) {
@@ -1947,7 +1940,9 @@ int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
}
}
r = *rangehead;
- r->omit = omit;
+ if (r) {
+ r->omit = omit;
+ }
return 0;
error:
yyerror("out of memory");
@@ -1955,7 +1950,7 @@ error:
}
/* flip to included ranges */
-int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead)
+static int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_ioctl_range_list *rnew, *r, *newhead, *r2;
@@ -2003,7 +1998,7 @@ error:
return -1;
}
-int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
+static int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
{
struct av_ioctl_range_list *rangehead;
uint8_t omit;
@@ -2031,7 +2026,7 @@ int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
return 0;
}
-int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
+static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
{
char *id;
class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
@@ -2131,7 +2126,7 @@ int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
policydbp->p_class_val_to_name[i]);
continue;
} else {
- cur_perms->data |= 1U << (perdatum->s.value - 1);
+ cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1);
}
}
@@ -2145,14 +2140,14 @@ out:
}
/* index of the u32 containing the permission */
-#define XPERM_IDX(x) (x >> 5)
+#define XPERM_IDX(x) ((x) >> 5)
/* set bits 0 through x-1 within the u32 */
-#define XPERM_SETBITS(x) ((1U << (x & 0x1f)) - 1)
+#define XPERM_SETBITS(x) ((UINT32_C(1) << ((x) & 0x1f)) - 1)
/* low value for this u32 */
-#define XPERM_LOW(x) (x << 5)
+#define XPERM_LOW(x) ((x) << 5)
/* high value for this u32 */
-#define XPERM_HIGH(x) (((x + 1) << 5) - 1)
-void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
+#define XPERM_HIGH(x) ((((x) + 1) << 5) - 1)
+static void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
av_extended_perms_t *xperms)
{
unsigned int i;
@@ -2174,7 +2169,7 @@ void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
}
}
-int avrule_xperms_used(av_extended_perms_t *xperms)
+static int avrule_xperms_used(const av_extended_perms_t *xperms)
{
unsigned int i;
@@ -2191,10 +2186,10 @@ int avrule_xperms_used(av_extended_perms_t *xperms)
* dir, size, driver, and function. Only the driver and function fields
* are considered here
*/
-#define IOC_DRIV(x) (x >> 8)
-#define IOC_FUNC(x) (x & 0xff)
-#define IOC_CMD(driver, func) ((driver << 8) + func)
-int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
+#define IOC_DRIV(x) ((x) >> 8)
+#define IOC_FUNC(x) ((x) & 0xff)
+#define IOC_CMD(driver, func) (((driver) << 8) + (func))
+static int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
av_extended_perms_t *complete_driver,
av_extended_perms_t **extended_perms)
{
@@ -2233,7 +2228,7 @@ int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
}
-int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
+static int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
av_extended_perms_t **extended_perms)
{
struct av_ioctl_range_list *r;
@@ -2275,7 +2270,7 @@ int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
return 0;
}
-int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
+static int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
av_extended_perms_t **extended_perms, unsigned int driver)
{
struct av_ioctl_range_list *r;
@@ -2325,18 +2320,7 @@ int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
return 0;
}
-void avrule_ioctl_freeranges(struct av_ioctl_range_list *rangelist)
-{
- struct av_ioctl_range_list *r, *tmp;
- r = rangelist;
- while (r) {
- tmp = r;
- r = r->next;
- free(tmp);
- }
-}
-
-unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
+static unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
{
unsigned int i;
for (i = *bit; i < sizeof(xperms->perms)*8; i++) {
@@ -2349,7 +2333,7 @@ unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
return 0;
}
-int avrule_cpy(avrule_t *dest, avrule_t *src)
+static int avrule_cpy(avrule_t *dest, const avrule_t *src)
{
class_perm_node_t *src_perms;
class_perm_node_t *dest_perms, *dest_tail;
@@ -2397,10 +2381,10 @@ int avrule_cpy(avrule_t *dest, avrule_t *src)
return 0;
}
-int define_te_avtab_ioctl(avrule_t *avrule_template)
+static int define_te_avtab_ioctl(const avrule_t *avrule_template)
{
avrule_t *avrule;
- struct av_ioctl_range_list *rangelist;
+ struct av_ioctl_range_list *rangelist, *r;
av_extended_perms_t *complete_driver, *partial_driver, *xperms;
unsigned int i;
@@ -2458,6 +2442,12 @@ done:
if (partial_driver)
free(partial_driver);
+ while (rangelist != NULL) {
+ r = rangelist;
+ rangelist = rangelist->next;
+ free(r);
+ }
+
return 0;
}
@@ -2466,6 +2456,7 @@ int define_te_avtab_extended_perms(int which)
char *id;
unsigned int i;
avrule_t *avrule_template;
+ int rc = 0;
if (pass == 1) {
for (i = 0; i < 4; i++) {
@@ -2481,18 +2472,20 @@ int define_te_avtab_extended_perms(int which)
id = queue_remove(id_queue);
if (strcmp(id,"ioctl") == 0) {
- free(id);
- if (define_te_avtab_ioctl(avrule_template))
- return -1;
+ rc = define_te_avtab_ioctl(avrule_template);
} else {
yyerror("only ioctl extended permissions are supported");
- free(id);
- return -1;
+ rc = -1;
}
- return 0;
+
+ free(id);
+ avrule_destroy(avrule_template);
+ free(avrule_template);
+
+ return rc;
}
-int define_te_avtab_helper(int which, avrule_t ** rule)
+static int define_te_avtab_helper(int which, avrule_t ** rule)
{
char *id;
class_datum_t *cladatum;
@@ -2619,7 +2612,7 @@ int define_te_avtab_helper(int which, avrule_t ** rule)
}
continue;
} else {
- cur_perms->data |= 1U << (perdatum->s.value - 1);
+ cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1);
}
next:
cur_perms = cur_perms->next;
@@ -3446,9 +3439,10 @@ bad:
return -1;
}
-static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr)
+static constraint_expr_t *constraint_expr_clone(const constraint_expr_t * expr)
{
- constraint_expr_t *h = NULL, *l = NULL, *e, *newe;
+ constraint_expr_t *h = NULL, *l = NULL, *newe;
+ const constraint_expr_t *e;
for (e = expr; e; e = e->next) {
newe = malloc(sizeof(*newe));
if (!newe)
@@ -3621,7 +3615,7 @@ int define_constraint(constraint_expr_t * expr)
return -1;
}
}
- node->permissions |= (1 << (perdatum->s.value - 1));
+ node->permissions |= (UINT32_C(1) << (perdatum->s.value - 1));
}
free(id);
}
@@ -4088,8 +4082,6 @@ cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void *arg2)
static int set_user_roles(role_set_t * set, char *id)
{
role_datum_t *r;
- unsigned int i;
- ebitmap_node_t *node;
if (strcmp(id, "*") == 0) {
free(id);
@@ -4115,12 +4107,9 @@ static int set_user_roles(role_set_t * set, char *id)
return -1;
}
- /* set the role and every role it dominates */
- ebitmap_for_each_positive_bit(&r->dominates, node, i) {
- if (ebitmap_set_bit(&set->roles, i, TRUE))
- goto oom;
- }
free(id);
+ if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE))
+ goto oom;
return 0;
oom:
yyerror("out of memory");
@@ -5476,7 +5465,7 @@ int define_fs_use(int behavior)
return 0;
}
-int define_genfs_context_helper(char *fstype, int has_type)
+static int define_genfs_context_helper(char *fstype, int has_type)
{
struct genfs *genfs_p, *genfs, *newgenfs;
ocontext_t *newc, *c, *head, *p;
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index 6098eb504d0c9c4f2d8efa0baf06f60b64216b71..45f973ffaeb030a408033b8ac629ed89112a9864 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -890,10 +890,26 @@ filename : FILENAME
{ yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; }
;
number : NUMBER
- { $$ = strtoul(yytext,NULL,0); }
+ { unsigned long x;
+ errno = 0;
+ x = strtoul(yytext, NULL, 0);
+ if (errno)
+ return -1;
+#if ULONG_MAX > UINT_MAX
+ if (x > UINT_MAX)
+ return -1;
+#endif
+ $$ = (unsigned int) x;
+ }
;
number64 : NUMBER
- { $$ = strtoull(yytext,NULL,0); }
+ { unsigned long long x;
+ errno = 0;
+ x = strtoull(yytext, NULL, 0);
+ if (errno)
+ return -1;
+ $$ = (uint64_t) x;
+ }
;
ipv6_addr : IPV6_ADDR
{ if (insert_id(yytext,0)) return -1; }
diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
index 4067268bdd81ab933f675f8ce145ebe5ebf95dc0..129a8a2a09263928b5c68f5bb0969e1a3cea05eb 100644
--- a/checkpolicy/policy_scan.l
+++ b/checkpolicy/policy_scan.l
@@ -59,12 +59,17 @@ alnum [a-zA-Z0-9]
hexval [0-9A-Fa-f]
%%
-\n.* { strncpy(linebuf[lno], yytext+1, 255);
- linebuf[lno][254] = 0;
- lno = 1 - lno;
- policydb_lineno++;
- source_lineno++;
- yyless(1); }
+\n.* {
+ strncpy(linebuf[lno], yytext+1, 255);
+ linebuf[lno][254] = 0;
+ lno = 1 - lno;
+ policydb_lineno++;
+ if (source_lineno == ULONG_MAX)
+ yywarn("source line number overflow");
+ else
+ source_lineno++;
+ yyless(1);
+ }
CLONE |
clone { return(CLONE); }
COMMON |
@@ -270,7 +275,13 @@ GLBLUB { return(GLBLUB); }
{hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])* { return(IPV6_ADDR); }
{digit}+(\.({alnum}|[_.])*)? { return(VERSION_IDENTIFIER); }
#line[ ]1[ ]\"[^\n]*\" { set_source_file(yytext+9); }
-#line[ ]{digit}+ { source_lineno = atoi(yytext+6)-1; }
+#line[ ]{digit}+ {
+ errno = 0;
+ source_lineno = strtoul(yytext+6, NULL, 10) - 1;
+ if (errno) {
+ yywarn("source line number too big");
+ }
+ }
#[^\n]* { /* delete comments */ }
[ \t\f]+ { /* delete whitespace */ }
"==" { return(EQUALS); }
diff --git a/checkpolicy/test/.gitignore b/checkpolicy/test/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..dbb03b958e50d907caa0c6c37f49982b75f21283
--- /dev/null
+++ b/checkpolicy/test/.gitignore
@@ -0,0 +1,2 @@
+dismod
+dispol
diff --git a/checkpolicy/test/Makefile b/checkpolicy/test/Makefile
index 89e7557c7aa623709c9a644f9f845069b0928ea0..8e5d16b3c5f0a4557a53f27172cfe6b7943d1242 100644
--- a/checkpolicy/test/Makefile
+++ b/checkpolicy/test/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for building the dispol program
#
-CFLAGS ?= -g -Wall -W -Werror -O2 -pipe
+CFLAGS ?= -g -Wall -W -Werror -O2
# If no specific libsepol.a is specified, fall back on LDFLAGS search path
# Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there
@@ -13,10 +13,10 @@ endif
all: dispol dismod
dispol: dispol.o $(LIBSEPOLA)
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
dismod: dismod.o $(LIBSEPOLA)
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
clean:
-rm -f dispol dismod *.o
diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
index 3408e9b6b7677567f6a7925590eba860308fd1c0..ec2a3e9aeae51da86835dae4393dcaea786e0e29 100644
--- a/checkpolicy/test/dismod.c
+++ b/checkpolicy/test/dismod.c
@@ -89,7 +89,7 @@ static void render_access_bitmap(ebitmap_t * map, uint32_t class,
fprintf(fp, "{");
for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) {
if (ebitmap_get_bit(map, i)) {
- perm = sepol_av_to_string(p, class, 1 << i);
+ perm = sepol_av_to_string(p, class, UINT32_C(1) << i);
if (perm)
fprintf(fp, " %s", perm);
}
@@ -111,7 +111,7 @@ static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type,
}
}
-int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
+static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
FILE * fp)
{
unsigned int i, num_types;
@@ -175,7 +175,7 @@ int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
return 0;
}
-int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
+static int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
{
unsigned int i, num = 0;
@@ -210,7 +210,7 @@ int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
}
-int display_avrule(avrule_t * avrule, policydb_t * policy,
+static int display_avrule(avrule_t * avrule, policydb_t * policy,
FILE * fp)
{
class_perm_node_t *cur;
@@ -313,7 +313,7 @@ int display_avrule(avrule_t * avrule, policydb_t * policy,
return 0;
}
-int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
+static int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
type_datum_t *type;
FILE *fp;
@@ -355,14 +355,14 @@ int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
return 0;
}
-int display_types(policydb_t * p, FILE * fp)
+static int display_types(policydb_t * p, FILE * fp)
{
if (hashtab_map(p->p_types.table, display_type_callback, fp))
return -1;
return 0;
}
-int display_users(policydb_t * p, FILE * fp)
+static int display_users(policydb_t * p, FILE * fp)
{
unsigned int i, j;
ebitmap_t *bitmap;
@@ -381,7 +381,7 @@ int display_users(policydb_t * p, FILE * fp)
return 0;
}
-int display_bools(policydb_t * p, FILE * fp)
+static int display_bools(policydb_t * p, FILE * fp)
{
unsigned int i;
@@ -392,7 +392,7 @@ int display_bools(policydb_t * p, FILE * fp)
return 0;
}
-void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
+static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
{
cond_expr_t *cur;
@@ -427,14 +427,14 @@ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
}
}
-void display_policycon(FILE * fp)
+static void display_policycon(FILE * fp)
{
/* There was an attempt to implement this at one time. Look through
* git history to find it. */
fprintf(fp, "Sorry, not implemented\n");
}
-void display_initial_sids(policydb_t * p, FILE * fp)
+static void display_initial_sids(policydb_t * p, FILE * fp)
{
ocontext_t *cur;
char *user, *role, *type;
@@ -459,7 +459,7 @@ void display_initial_sids(policydb_t * p, FILE * fp)
#endif
}
-void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
+static void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
{
unsigned int i, num = 0;
@@ -482,7 +482,7 @@ void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
fprintf(fp, " }");
}
-void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
+static void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
{
for (; tr; tr = tr->next) {
fprintf(fp, "role transition ");
@@ -495,7 +495,7 @@ void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
}
}
-void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
+static void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
{
for (; ra; ra = ra->next) {
fprintf(fp, "role allow ");
@@ -517,7 +517,7 @@ static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, F
}
}
-int role_display_callback(hashtab_key_t key __attribute__((unused)),
+static int role_display_callback(hashtab_key_t key __attribute__((unused)),
hashtab_datum_t datum, void *data)
{
role_datum_t *role;
@@ -611,7 +611,7 @@ int change_bool(char *name, int state, policydb_t * p, FILE * fp)
}
#endif
-int display_avdecl(avrule_decl_t * decl, int field,
+static int display_avdecl(avrule_decl_t * decl, int field,
policydb_t * policy, FILE * out_fp)
{
fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
@@ -692,13 +692,13 @@ int display_avdecl(avrule_decl_t * decl, int field,
return 0; /* should never get here */
}
-int display_avblock(int field, policydb_t * policy,
+static int display_avblock(int field, policydb_t * policy,
FILE * out_fp)
{
avrule_block_t *block = policydb.global;
while (block != NULL) {
- fprintf(out_fp, "--- begin avrule block ---\n");
avrule_decl_t *decl = block->branch_list;
+ fprintf(out_fp, "--- begin avrule block ---\n");
while (decl != NULL) {
if (display_avdecl(decl, field, policy, out_fp)) {
return -1;
@@ -710,7 +710,7 @@ int display_avblock(int field, policydb_t * policy,
return 0;
}
-int display_handle_unknown(policydb_t * p, FILE * out_fp)
+static int display_handle_unknown(policydb_t * p, FILE * out_fp)
{
if (p->handle_unknown == ALLOW_UNKNOWN)
fprintf(out_fp, "Allow unknown classes and perms\n");
@@ -751,12 +751,14 @@ static int read_policy(char *filename, policydb_t * policy)
fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
exit(1);
}
+ sepol_policydb_free(package->policy);
package->policy = (sepol_policydb_t *) policy;
package->file_contexts = NULL;
retval =
sepol_module_package_read(package,
(sepol_policy_file_t *) & f, 1);
- free(package->file_contexts);
+ package->policy = NULL;
+ sepol_module_package_free(package);
} else {
if (policydb_init(policy)) {
fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
@@ -827,14 +829,14 @@ static void display_policycaps(policydb_t * p, FILE * fp)
ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
capname = sepol_polcap_getname(i);
if (capname == NULL) {
- snprintf(buf, sizeof(buf), "unknown (%d)", i);
+ snprintf(buf, sizeof(buf), "unknown (%u)", i);
capname = buf;
}
fprintf(fp, "\t%s\n", capname);
}
}
-int menu(void)
+static int menu(void)
{
printf("\nSelect a command:\n");
printf("1) display unconditional AVTAB\n");
diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c
index 8785b7252824a50029fca7ae60242ecbfd767da5..8ddefb04ac89480c94317b05c57d9993f62f7eb4 100644
--- a/checkpolicy/test/dispol.c
+++ b/checkpolicy/test/dispol.c
@@ -42,7 +42,7 @@ static __attribute__((__noreturn__)) void usage(const char *progname)
exit(1);
}
-int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
+static int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
FILE * fp)
{
char *perm;
@@ -54,13 +54,13 @@ int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
return 0;
}
-int render_type(uint32_t type, policydb_t * p, FILE * fp)
+static int render_type(uint32_t type, policydb_t * p, FILE * fp)
{
fprintf(fp, "%s", p->p_type_val_to_name[type - 1]);
return 0;
}
-int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
+static int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
{
char *stype, *ttype, *tclass;
stype = p->p_type_val_to_name[key->source_type - 1];
@@ -84,7 +84,7 @@ int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
#define RENDER_DISABLED 0x0004
#define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED)
-int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
+static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
policydb_t * p, FILE * fp)
{
if (!(what & RENDER_UNCONDITIONAL)) {
@@ -163,7 +163,7 @@ int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
return 0;
}
-int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
+static int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
{
unsigned int i;
avtab_ptr_t cur;
@@ -178,7 +178,7 @@ int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
return 0;
}
-int display_bools(policydb_t * p, FILE * fp)
+static int display_bools(policydb_t * p, FILE * fp)
{
unsigned int i;
@@ -189,7 +189,7 @@ int display_bools(policydb_t * p, FILE * fp)
return 0;
}
-void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
+static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
{
cond_expr_t *cur;
@@ -224,7 +224,7 @@ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
}
}
-int display_cond_expressions(policydb_t * p, FILE * fp)
+static int display_cond_expressions(policydb_t * p, FILE * fp)
{
cond_node_t *cur;
cond_av_list_t *av_cur;
@@ -249,7 +249,7 @@ int display_cond_expressions(policydb_t * p, FILE * fp)
return 0;
}
-int display_handle_unknown(policydb_t * p, FILE * out_fp)
+static int display_handle_unknown(policydb_t * p, FILE * out_fp)
{
if (p->handle_unknown == ALLOW_UNKNOWN)
fprintf(out_fp, "Allow unknown classes and permissions\n");
@@ -260,7 +260,7 @@ int display_handle_unknown(policydb_t * p, FILE * out_fp)
return 0;
}
-int change_bool(char *name, int state, policydb_t * p, FILE * fp)
+static int change_bool(char *name, int state, policydb_t * p, FILE * fp)
{
cond_bool_datum_t *bool;
@@ -285,7 +285,7 @@ static void display_policycaps(policydb_t * p, FILE * fp)
ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
capname = sepol_polcap_getname(i);
if (capname == NULL) {
- snprintf(buf, sizeof(buf), "unknown (%d)", i);
+ snprintf(buf, sizeof(buf), "unknown (%u)", i);
capname = buf;
}
fprintf(fp, "\t%s\n", capname);
@@ -368,7 +368,7 @@ static void display_filename_trans(policydb_t *p, FILE *fp)
hashtab_map(p->filename_trans, filenametr_display, &args);
}
-int menu(void)
+static int menu(void)
{
printf("\nSelect a command:\n");
printf("1) display unconditional AVTAB\n");
diff --git a/libselinux/Makefile b/libselinux/Makefile
index ac16c15e8d0aca3966697bc1c562f0e9692f8498..439bc6a9b7fd35fdceb42daaa7ffac4b363ae690 100644
--- a/libselinux/Makefile
+++ b/libselinux/Makefile
@@ -50,24 +50,24 @@ all install relabel clean distclean indent:
done
swigify: all
- $(MAKE) -C src swigify $@
+ $(MAKE) -C src $@
pywrap:
- $(MAKE) -C src pywrap $@
+ $(MAKE) -C src $@
rubywrap:
- $(MAKE) -C src rubywrap $@
+ $(MAKE) -C src $@
install-pywrap:
- $(MAKE) -C src install-pywrap $@
+ $(MAKE) -C src $@
install-rubywrap:
- $(MAKE) -C src install-rubywrap $@
+ $(MAKE) -C src $@
clean-pywrap:
- $(MAKE) -C src clean-pywrap $@
+ $(MAKE) -C src $@
clean-rubywrap:
- $(MAKE) -C src clean-rubywrap $@
+ $(MAKE) -C src $@
test:
diff --git a/libselinux/VERSION b/libselinux/VERSION
index a3ec5a4bd3d7209b4a687a77cad49b945339994b..eb39e5382f4f035e4d71c7f67712cdbfa6c0c335 100644
--- a/libselinux/VERSION
+++ b/libselinux/VERSION
@@ -1 +1 @@
-3.2
+3.3
diff --git a/libselinux/man/man3/avc_open.3 b/libselinux/man/man3/avc_open.3
index 3090dd5077c73c1adf96308de0c224d53677af2c..55683bb6594bea7502edaf44bfaea2898e62a43e 100644
--- a/libselinux/man/man3/avc_open.3
+++ b/libselinux/man/man3/avc_open.3
@@ -26,6 +26,9 @@ initializes the userspace AVC and must be called before any other AVC operation
destroys the userspace AVC, freeing all internal memory structures. After this call has been made,
.BR avc_open ()
must be called again before any AVC operations can be performed.
+.BR avc_destroy ()
+also closes the SELinux status page, which might have been opened manually by
+.BR selinux_status_open (3).
.BR avc_reset ()
flushes the userspace AVC, causing it to forget any cached access decisions. The userspace AVC normally calls this function automatically when needed, see
diff --git a/libselinux/man/man3/getcon.3 b/libselinux/man/man3/getcon.3
index 67872a4dede6b2dd45cf763a6ef4862ee87906f1..e7e394f305b7116a380bfd20f0e53cbc05fc24f9 100644
--- a/libselinux/man/man3/getcon.3
+++ b/libselinux/man/man3/getcon.3
@@ -7,7 +7,7 @@ freecon, freeconary \- free memory associated with SELinux security contexts
getpeercon \- get security context of a peer socket
setcon \- set current security context of a process
-.
+
.SH "SYNOPSIS"
.B #include
.sp
@@ -31,30 +31,39 @@ setcon \- set current security context of a process
.sp
.BI "void freeconary(char **" con );
.sp
-.BI "int setcon(char *" context );
+.BI "int setcon(const char *" context );
.sp
-.BI "int setcon_raw(char *" context );
-.
+.BI "int setcon_raw(const char *" context );
+
.SH "DESCRIPTION"
+.TP
.BR getcon ()
retrieves the context of the current process, which must be free'd with
-freecon.
+.BR freecon ().
+.TP
.BR getprevcon ()
same as getcon but gets the context before the last exec.
+.TP
.BR getpidcon ()
-returns the process context for the specified PID.
+returns the process context for the specified PID, which must be free'd with
+.BR freecon ().
+.TP
.BR getpeercon ()
-retrieves context of peer socket, and set
-.BI * context
-to refer to it, which must be free'd with
+retrieves the context of the peer socket, which must be free'd with
.BR freecon ().
+.TP
.BR freecon ()
frees the memory allocated for a security context.
+If
+.I con
+is NULL, no operation is performed.
+
+.TP
.BR freeconary ()
frees the memory allocated for a context array.
@@ -62,6 +71,7 @@ If
.I con
is NULL, no operation is performed.
+.TP
.BR setcon ()
sets the current security context of the process to a new value. Note
that use of this function requires that the entire application be
@@ -110,6 +120,8 @@ context and the
.BR setcon ()
will fail if it is not allowed by policy.
+.TP
+.BR *_raw()
.BR getcon_raw (),
.BR getprevcon_raw (),
.BR getpidcon_raw (),
@@ -118,9 +130,14 @@ and
.BR setcon_raw ()
behave identically to their non-raw counterparts but do not perform context
translation.
-.
+
.SH "RETURN VALUE"
-On error \-1 is returned. On success 0 is returned.
-.
+On error \-1 is returned with errno set. On success 0 is returned.
+
+.SH "NOTES"
+The retrieval functions might return success and set
+.I *context
+to NULL if and only if SELinux is not enabled.
+
.SH "SEE ALSO"
.BR selinux "(8), " setexeccon "(3)"
diff --git a/libselinux/man/man8/selinux.8 b/libselinux/man/man8/selinux.8
index 0ef014609a36c849cac4f2bc3cee0d256801b0a6..5842150bfc721715a97b94c23d79b48d208068af 100644
--- a/libselinux/man/man8/selinux.8
+++ b/libselinux/man/man8/selinux.8
@@ -94,6 +94,13 @@ and reboot.
also has this capability. The
.BR restorecon / fixfiles
commands are also available for relabeling files.
+
+Please note that using mount flag
+.I nosuid
+also disables SELinux domain transitions, unless permission
+.I nosuid_transition
+is used in the policy to allow this, which in turn needs also policy capability
+.IR nnp_nosuid_transition .
.
.SH AUTHOR
This manual page was written by Dan Walsh .
diff --git a/libselinux/src/.gitignore b/libselinux/src/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..001f20b01e3936e33d86c3cc86c5a990b4486ca9
--- /dev/null
+++ b/libselinux/src/.gitignore
@@ -0,0 +1,3 @@
+selinux.py
+selinuxswig_python_wrap.c
+selinuxswig_ruby_wrap.c
diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c
index d56b56eb2a1a9e7cd703a3c59ce6a667b0884f2c..ca38e13c0eeb4ebf521f863126170fce71fb581f 100644
--- a/libselinux/src/audit2why.c
+++ b/libselinux/src/audit2why.c
@@ -204,8 +204,8 @@ static int __policy_init(const char *init_path)
fp = fopen(path, "re");
if (!fp) {
snprintf(errormsg, sizeof(errormsg),
- "unable to open %s: %s\n",
- path, strerror(errno));
+ "unable to open %s: %m\n",
+ path);
PyErr_SetString( PyExc_ValueError, errormsg);
return 1;
}
@@ -221,9 +221,8 @@ static int __policy_init(const char *init_path)
fp = fopen(curpolicy, "re");
if (!fp) {
snprintf(errormsg, sizeof(errormsg),
- "unable to open %s: %s\n",
- curpolicy,
- strerror(errno));
+ "unable to open %s: %m\n",
+ curpolicy);
PyErr_SetString( PyExc_ValueError, errormsg);
return 1;
}
@@ -242,7 +241,7 @@ static int __policy_init(const char *init_path)
if (sepol_policy_file_create(&pf) ||
sepol_policydb_create(&avc->policydb)) {
snprintf(errormsg, sizeof(errormsg),
- "policydb_init failed: %s\n", strerror(errno));
+ "policydb_init failed: %m\n");
PyErr_SetString( PyExc_RuntimeError, errormsg);
fclose(fp);
return 1;
@@ -275,7 +274,7 @@ static int __policy_init(const char *init_path)
}
sepol_bool_iterate(avc->handle, avc->policydb,
- load_booleans, (void *)NULL);
+ load_booleans, NULL);
/* Initialize the sidtab for subsequent use by sepol_context_to_sid
and sepol_compute_av_reason. */
diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c
index 8314d7ba3de6e45fb682e95985d1150212a85837..7493e4b24df2d144b96f022cdf1c46db29c07b47 100644
--- a/libselinux/src/avc.c
+++ b/libselinux/src/avc.c
@@ -206,19 +206,18 @@ static int avc_init_internal(const char *prefix,
rc = security_getenforce();
if (rc < 0) {
avc_log(SELINUX_ERROR,
- "%s: could not determine enforcing mode: %s\n",
- avc_prefix,
- strerror(errno));
+ "%s: could not determine enforcing mode: %m\n",
+ avc_prefix);
goto out;
}
avc_enforcing = rc;
}
- rc = selinux_status_open(1);
+ rc = selinux_status_open(0);
if (rc < 0) {
avc_log(SELINUX_ERROR,
- "%s: could not open selinux status page: %d (%s)\n",
- avc_prefix, errno, strerror(errno));
+ "%s: could not open selinux status page: %d (%m)\n",
+ avc_prefix, errno);
goto out;
}
avc_running = 1;
diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c
index 53a99a1fe9575825839ba428b6af89d9802deb22..71a1357bc564cb33a8da221490f2ec49eadb42c2 100644
--- a/libselinux/src/avc_internal.c
+++ b/libselinux/src/avc_internal.c
@@ -308,8 +308,8 @@ int avc_netlink_acquire_fd(void)
rc = avc_netlink_open(0);
if (rc < 0) {
avc_log(SELINUX_ERROR,
- "%s: could not open netlink socket: %d (%s)\n",
- avc_prefix, errno, strerror(errno));
+ "%s: could not open netlink socket: %d (%m)\n",
+ avc_prefix, errno);
return rc;
}
}
diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h
index da67affc9307aa981a436cbb5c62c37ce3b55fc4..a9a4aa0b3c42c3b63428f28a5670de41ec26f810 100644
--- a/libselinux/src/avc_internal.h
+++ b/libselinux/src/avc_internal.h
@@ -85,10 +85,12 @@ static inline void avc_free(void *ptr)
/* this is a macro in order to use the variadic capability. */
#define avc_log(type, format...) \
- if (avc_func_log) \
- avc_func_log(format); \
- else \
- selinux_log(type, format);
+ do { \
+ if (avc_func_log) \
+ avc_func_log(format); \
+ else \
+ selinux_log(type, format); \
+ } while (0)
static inline void avc_suppl_audit(void *ptr, security_class_t class,
char *buf, size_t len)
@@ -137,14 +139,18 @@ static inline void avc_free_lock(void *lock)
#ifdef AVC_CACHE_STATS
#define avc_cache_stats_incr(field) \
- cache_stats.field ++;
+ do { \
+ cache_stats.field ++; \
+ } while (0)
#define avc_cache_stats_add(field, num) \
- cache_stats.field += num;
+ do { \
+ cache_stats.field += num; \
+ } while (0)
#else
-#define avc_cache_stats_incr(field)
-#define avc_cache_stats_add(field, num)
+#define avc_cache_stats_incr(field) do {} while (0)
+#define avc_cache_stats_add(field, num) do {} while (0)
#endif
diff --git a/libselinux/src/avc_sidtab.c b/libselinux/src/avc_sidtab.c
index 9669264d651a485768a90dbf64851af68d135c29..f179d8558a45206d88c66a5d277189c21d037da3 100644
--- a/libselinux/src/avc_sidtab.c
+++ b/libselinux/src/avc_sidtab.c
@@ -15,14 +15,13 @@
static inline unsigned sidtab_hash(const char * key)
{
- char *p, *keyp;
+ const char *p;
unsigned int size;
unsigned int val;
val = 0;
- keyp = (char *)key;
- size = strlen(keyp);
- for (p = keyp; (unsigned int)(p - keyp) < size; p++)
+ size = strlen(key);
+ for (p = key; (unsigned int)(p - key) < size; p++)
val =
(val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val & (SIDTAB_SIZE - 1);
@@ -57,7 +56,7 @@ int sidtab_insert(struct sidtab *s, const char * ctx)
rc = -1;
goto out;
}
- newctx = (char *) strdup(ctx);
+ newctx = strdup(ctx);
if (!newctx) {
rc = -1;
avc_free(newnode);
@@ -101,7 +100,7 @@ sidtab_context_to_sid(struct sidtab *s,
return rc;
}
-void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
+void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen)
{
int i, chain_len, slots_used, max_chain_len;
struct sidtab_node *cur;
@@ -109,7 +108,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
slots_used = 0;
max_chain_len = 0;
for (i = 0; i < SIDTAB_SIZE; i++) {
- cur = h->htable[i];
+ cur = s->htable[i];
if (cur) {
slots_used++;
chain_len = 0;
@@ -125,7 +124,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
snprintf(buf, buflen,
"%s: %u SID entries and %d/%d buckets used, longest "
- "chain length %d\n", avc_prefix, h->nel, slots_used,
+ "chain length %d\n", avc_prefix, s->nel, slots_used,
SIDTAB_SIZE, max_chain_len);
}
diff --git a/libselinux/src/checkAccess.c b/libselinux/src/checkAccess.c
index b337ea64f977dc211ae236476ab6215779715724..022cd6b5ecabfbe2b83d6c023a22e3126df8fea3 100644
--- a/libselinux/src/checkAccess.c
+++ b/libselinux/src/checkAccess.c
@@ -78,7 +78,9 @@ static int selinux_check_passwd_access_internal(access_vector_t requested)
passwd_class = string_to_security_class("passwd");
if (passwd_class == 0) {
freecon(user_context);
- return 0;
+ if (security_deny_unknown() == 0)
+ return 0;
+ return -1;
}
retval = security_compute_av_raw(user_context,
diff --git a/libselinux/src/context.c b/libselinux/src/context.c
index ce4258806c53fda5172c365c23a7ffc055648d73..b2144c7cf76c77393c81cb13aac7b6d2b4bb0b75 100644
--- a/libselinux/src/context.c
+++ b/libselinux/src/context.c
@@ -37,7 +37,7 @@ context_t context_new(const char *str)
}
n->current_str = n->component[0] = n->component[1] = n->component[2] =
n->component[3] = 0;
- for (i = count = 0, p = str; *p; p++) {
+ for (count = 0, p = str; *p; p++) {
switch (*p) {
case ':':
count++;
diff --git a/libselinux/src/is_customizable_type.c b/libselinux/src/is_customizable_type.c
index 92876f4d9371214260b72ec68c55f44e5a926b15..1b17860c362253e1fd4b6951701e556e8ca32faf 100644
--- a/libselinux/src/is_customizable_type.c
+++ b/libselinux/src/is_customizable_type.c
@@ -38,7 +38,7 @@ static int get_customizable_type_list(char *** retlist)
while (fgets_unlocked(buf, selinux_page_size, fp)
&& i < ctr) {
buf[strlen(buf) - 1] = 0;
- list[i] = (char *) strdup(buf);
+ list[i] = strdup(buf);
if (!list[i]) {
unsigned int j;
for (j = 0; j < i; j++)
diff --git a/libselinux/src/label_backends_android.c b/libselinux/src/label_backends_android.c
index cb8aae261d5c1864ef6e36e0e926830f1c315855..66d4df2d2895a10cd6f1045d084cc387abaf3037 100644
--- a/libselinux/src/label_backends_android.c
+++ b/libselinux/src/label_backends_android.c
@@ -94,9 +94,15 @@ static int process_line(struct selabel_handle *rec,
items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context);
if (items < 0) {
items = errno;
- selinux_log(SELINUX_ERROR,
- "%s: line %u error due to: %s\n", path,
- lineno, errbuf ?: strerror(errno));
+ if (errbuf) {
+ selinux_log(SELINUX_ERROR,
+ "%s: line %u error due to: %s\n", path,
+ lineno, errbuf);
+ } else {
+ selinux_log(SELINUX_ERROR,
+ "%s: line %u error due to: %m\n", path,
+ lineno);
+ }
errno = items;
return -1;
}
diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c
index fba96c92299f514973f48fe7533b3ef2d46cd410..94c05c6d439709dad7fab3565e9b509264c3fecc 100644
--- a/libselinux/src/label_db.c
+++ b/libselinux/src/label_db.c
@@ -277,7 +277,7 @@ db_init(const struct selinux_opt *opts, unsigned nopts,
if (!path)
path = selinux_sepgsql_context_path();
- if ((filp = fopen(path, "rb")) == NULL) {
+ if ((filp = fopen(path, "re")) == NULL) {
free(catalog);
return NULL;
}
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 726394ca43321c886bbc999f77fec6b4c55a63e9..2e28d0474d731ddf4c6c219d4610cf05596a050b 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -188,6 +188,9 @@ static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec,
str_buf[entry_len] = '\0';
if ((strcmp(str_buf, reg_version) != 0)) {
+ COMPAT_LOG(SELINUX_ERROR,
+ "Regex version mismatch, expected: %s actual: %s\n",
+ reg_version, str_buf);
free(str_buf);
return -1;
}
@@ -371,7 +374,7 @@ end_arch_check:
if (stem_id < 0 || stem_id >= (int32_t)stem_map_len)
spec->stem_id = -1;
- else
+ else
spec->stem_id = stem_map[stem_id];
/* retrieve the hasMetaChars bit */
@@ -756,6 +759,10 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
}
#endif
+
+ if (!path)
+ goto finish;
+
rec->spec_file = strdup(path);
/*
@@ -845,7 +852,7 @@ static void closef(struct selabel_handle *rec)
// Finds all the matches of |key| in the given context. Returns the result in
// the allocated array and updates the match count. If match_count is NULL,
// stops early once the 1st match is found.
-static const struct spec **lookup_all(struct selabel_handle *rec,
+static struct spec **lookup_all(struct selabel_handle *rec,
const char *key,
int type,
bool partial,
@@ -861,7 +868,7 @@ static const struct spec **lookup_all(struct selabel_handle *rec,
unsigned int sofar = 0;
char *sub = NULL;
- const struct spec **result = NULL;
+ struct spec **result = NULL;
if (match_count) {
*match_count = 0;
result = calloc(data->nspec, sizeof(struct spec*));
@@ -909,7 +916,7 @@ static const struct spec **lookup_all(struct selabel_handle *rec,
if (!clean_key)
goto finish;
- strncpy(clean_key, key, len - 1);
+ memcpy(clean_key, key, len - 1);
}
clean_key[len - 1] = '\0';
@@ -987,11 +994,11 @@ static struct spec *lookup_common(struct selabel_handle *rec,
const char *key,
int type,
bool partial) {
- const struct spec **matches = lookup_all(rec, key, type, partial, NULL);
+ struct spec **matches = lookup_all(rec, key, type, partial, NULL);
if (!matches) {
return NULL;
}
- struct spec *result = (struct spec*)matches[0];
+ struct spec *result = matches[0];
free(matches);
return result;
}
@@ -1054,7 +1061,7 @@ static bool hash_all_partial_matches(struct selabel_handle *rec, const char *key
assert(digest);
size_t total_matches;
- const struct spec **matches = lookup_all(rec, key, 0, true, &total_matches);
+ struct spec **matches = lookup_all(rec, key, 0, true, &total_matches);
if (!matches) {
return false;
}
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index baed3341b6b3dc0ad704011c1dbafa6e4999423d..343ffc705e433ac2f92043e632202807814cbf4f 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -286,7 +286,6 @@ static inline int store_stem(struct saved_data *data, char *buf, int stem_len)
tmp_arr = realloc(data->stem_arr,
sizeof(*tmp_arr) * alloc_stems);
if (!tmp_arr) {
- free(buf);
return -1;
}
data->alloc_stems = alloc_stems;
@@ -308,6 +307,7 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
int stem_len = get_stem_from_spec(buf);
int stemid;
char *stem;
+ int r;
if (!stem_len)
return -1;
@@ -321,7 +321,11 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
if (!stem)
return -1;
- return store_stem(data, stem, stem_len);
+ r = store_stem(data, stem, stem_len);
+ if (r < 0)
+ free(stem);
+
+ return r;
}
/* This will always check for buffer over-runs and either read the next entry
@@ -441,9 +445,15 @@ static inline int process_line(struct selabel_handle *rec,
items = read_spec_entries(line_buf, &errbuf, 3, ®ex, &type, &context);
if (items < 0) {
rc = errno;
- selinux_log(SELINUX_ERROR,
- "%s: line %u error due to: %s\n", path,
- lineno, errbuf ?: strerror(errno));
+ if (errbuf) {
+ selinux_log(SELINUX_ERROR,
+ "%s: line %u error due to: %s\n", path,
+ lineno, errbuf);
+ } else {
+ selinux_log(SELINUX_ERROR,
+ "%s: line %u error due to: %m\n", path,
+ lineno);
+ }
errno = rc;
return -1;
}
diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h
index 361b443cb9c4333b43ead03730c63657d8e4f683..782c6aa8cc0ce7bf7abee23bc30dee6e38ac68ef 100644
--- a/libselinux/src/label_internal.h
+++ b/libselinux/src/label_internal.h
@@ -128,10 +128,12 @@ extern int myprintf_compat;
extern void __attribute__ ((format(printf, 1, 2)))
(*myprintf) (const char *fmt, ...) ;
-#define COMPAT_LOG(type, fmt...) if (myprintf_compat) \
- myprintf(fmt); \
- else \
- selinux_log(type, fmt);
+#define COMPAT_LOG(type, fmt...) do { \
+ if (myprintf_compat) \
+ myprintf(fmt); \
+ else \
+ selinux_log(type, fmt); \
+ } while (0)
extern int
compat_validate(struct selabel_handle *rec,
diff --git a/libselinux/src/label_media.c b/libselinux/src/label_media.c
index d202e5d5ab838e93f8218a58e36caf351703c839..eb27deaf510ead4ea43582acb27cf5fe8b659254 100644
--- a/libselinux/src/label_media.c
+++ b/libselinux/src/label_media.c
@@ -119,7 +119,6 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
if (process_line(path, line_buf, pass, ++lineno, rec))
goto finish;
}
- lineno = 0;
if (pass == 0) {
if (data->nspec == 0) {
diff --git a/libselinux/src/label_x.c b/libselinux/src/label_x.c
index 9674529931a73ff00209adf3e0a1f700aebacf79..e9fa063fafffb42e3b329508f338bd5087bc4363 100644
--- a/libselinux/src/label_x.c
+++ b/libselinux/src/label_x.c
@@ -146,7 +146,6 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
if (process_line(path, line_buf, pass, ++lineno, rec))
goto finish;
}
- lineno = 0;
if (pass == 0) {
if (data->nspec == 0) {
diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c
index 0034fa53d6e609f5cec0def7963c883ec52bef49..d8c715edb0b67119e8da3491719f4d447ca52b97 100644
--- a/libselinux/src/load_policy.c
+++ b/libselinux/src/load_policy.c
@@ -80,7 +80,7 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
if (libsepolh) {
usesepol = 1;
dlerror();
-#define DLERR() if ((errormsg = dlerror())) goto dlclose;
+#define DLERR() do { if ((errormsg = dlerror())) goto dlclose; } while (0)
vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max");
DLERR();
vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min");
@@ -137,15 +137,15 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
}
if (fd < 0) {
fprintf(stderr,
- "SELinux: Could not open policy file <= %s.%d: %s\n",
- selinux_binary_policy_path(), maxvers, strerror(errno));
+ "SELinux: Could not open policy file <= %s.%d: %m\n",
+ selinux_binary_policy_path(), maxvers);
goto dlclose;
}
if (fstat(fd, &sb) < 0) {
fprintf(stderr,
- "SELinux: Could not stat policy file %s: %s\n",
- path, strerror(errno));
+ "SELinux: Could not stat policy file %s: %m\n",
+ path);
goto close;
}
@@ -153,8 +153,8 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
data = map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
fprintf(stderr,
- "SELinux: Could not map policy file %s: %s\n",
- path, strerror(errno));
+ "SELinux: Could not map policy file %s: %m\n",
+ path);
goto close;
}
@@ -193,8 +193,8 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
if (rc)
fprintf(stderr,
- "SELinux: Could not load policy file %s: %s\n",
- path, strerror(errno));
+ "SELinux: Could not load policy file %s: %m\n",
+ path);
unmap:
if (data != map)
@@ -306,7 +306,7 @@ int selinux_init_load_policy(int *enforce)
*enforce = 0;
} else {
/* Only emit this error if selinux was not disabled */
- fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno));
+ fprintf(stderr, "Mount failed for selinuxfs on %s: %m\n", SELINUXMNT);
}
if (rc == 0)
@@ -352,7 +352,7 @@ int selinux_init_load_policy(int *enforce)
if (orig_enforce != *enforce) {
rc = security_setenforce(*enforce);
if (rc < 0) {
- fprintf(stderr, "SELinux: Unable to switch to %s mode: %s\n", (*enforce ? "enforcing" : "permissive"), strerror(errno));
+ fprintf(stderr, "SELinux: Unable to switch to %s mode: %m\n", (*enforce ? "enforcing" : "permissive"));
if (*enforce)
goto noload;
}
diff --git a/libselinux/src/mapping.c b/libselinux/src/mapping.c
index 96395fd40f145db8b87f7fc9651db96f9f658871..dd2f10390ad1969bd519e22f30719172189f0837 100644
--- a/libselinux/src/mapping.c
+++ b/libselinux/src/mapping.c
@@ -144,9 +144,9 @@ unmap_perm(security_class_t tclass, access_vector_t tperm)
access_vector_t kperm = 0;
for (i = 0; i < current_mapping[tclass].num_perms; i++)
- if (tperm & (1<allowed & mapping->perms[i])
- result |= 1<perms[i])
- result |= 1<allowed = result;
for (i = 0, result = 0; i < n; i++) {
if (avd->decided & mapping->perms[i])
- result |= 1<perms[i])
- result |= 1<decided = result;
for (i = 0, result = 0; i < n; i++)
if (avd->auditallow & mapping->perms[i])
- result |= 1<auditallow = result;
for (i = 0, result = 0; i < n; i++) {
if (avd->auditdeny & mapping->perms[i])
- result |= 1<perms[i])
- result |= 1<auditdeny = result;
}
}
diff --git a/libselinux/src/matchmediacon.c b/libselinux/src/matchmediacon.c
index 23d01af476d292603dbac5bd0c40fb7c92d973ad..d3d9504348e1133723e4cf7e382c0ef19a1d181e 100644
--- a/libselinux/src/matchmediacon.c
+++ b/libselinux/src/matchmediacon.c
@@ -22,6 +22,7 @@ int matchmediacon(const char *media, char ** con)
return -1;
while (!feof_unlocked(infile)) {
if (!fgets_unlocked(current_line, sizeof(current_line), infile)) {
+ fclose(infile);
return -1;
}
if (current_line[strlen(current_line) - 1])
diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
index 2ec66650cae0cf4921ee47ab6370a878c1c274ff..1e7f8890c22e36d5301d08435bd911501208235b 100644
--- a/libselinux/src/matchpathcon.c
+++ b/libselinux/src/matchpathcon.c
@@ -78,17 +78,30 @@ static pthread_once_t once = PTHREAD_ONCE_INIT;
static pthread_key_t destructor_key;
static int destructor_key_initialized = 0;
+static void free_array_elts(void)
+{
+ int i;
+ for (i = 0; i < con_array_used; i++)
+ free(con_array[i]);
+ free(con_array);
+
+ con_array_size = con_array_used = 0;
+ con_array = NULL;
+}
+
static int add_array_elt(char *con)
{
+ char **tmp;
if (con_array_size) {
while (con_array_used >= con_array_size) {
con_array_size *= 2;
- con_array = (char **)realloc(con_array, sizeof(char*) *
+ tmp = (char **)realloc(con_array, sizeof(char*) *
con_array_size);
- if (!con_array) {
- con_array_size = con_array_used = 0;
+ if (!tmp) {
+ free_array_elts();
return -1;
}
+ con_array = tmp;
}
} else {
con_array_size = 1000;
@@ -105,13 +118,6 @@ static int add_array_elt(char *con)
return con_array_used++;
}
-static void free_array_elts(void)
-{
- con_array_size = con_array_used = 0;
- free(con_array);
- con_array = NULL;
-}
-
void set_matchpathcon_invalidcon(int (*f) (const char *p, unsigned l, char *c))
{
myinvalidcon = f;
@@ -387,8 +393,8 @@ int realpath_not_final(const char *name, char *resolved_path)
tmp_path = strdup(name);
if (!tmp_path) {
- myprintf("symlink_realpath(%s) strdup() failed: %s\n",
- name, strerror(errno));
+ myprintf("symlink_realpath(%s) strdup() failed: %m\n",
+ name);
rc = -1;
goto out;
}
@@ -408,8 +414,8 @@ int realpath_not_final(const char *name, char *resolved_path)
}
if (!p) {
- myprintf("symlink_realpath(%s) realpath() failed: %s\n",
- name, strerror(errno));
+ myprintf("symlink_realpath(%s) realpath() failed: %m\n",
+ name);
rc = -1;
goto out;
}
@@ -477,15 +483,15 @@ void matchpathcon_checkmatches(char *str __attribute__((unused)))
int selinux_file_context_cmp(const char * a,
const char * b)
{
- char *rest_a, *rest_b; /* Rest of the context after the user */
+ const char *rest_a, *rest_b; /* Rest of the context after the user */
if (!a && !b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
- rest_a = strchr((char *)a, ':');
- rest_b = strchr((char *)b, ':');
+ rest_a = strchr(a, ':');
+ rest_b = strchr(b, ':');
if (!rest_a && !rest_b)
return 0;
if (!rest_a)
diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c
index ca7f97864473a7073555d096168feb7f90908818..72eb5efe922eea86ac3d4c7e92de01aae123326c 100644
--- a/libselinux/src/procattr.c
+++ b/libselinux/src/procattr.c
@@ -146,7 +146,7 @@ static int getprocattrcon_raw(char ** context,
default:
errno = ENOENT;
return -1;
- };
+ }
if (prev_context && prev_context != UNSET) {
*context = strdup(prev_context);
@@ -240,7 +240,7 @@ static int setprocattrcon_raw(const char * context,
default:
errno = ENOENT;
return -1;
- };
+ }
if (!context && !*prev_context)
return 0;
diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c
index 770bc3ea1310896c8f72b3e8a02815baaf50d9ae..73987d9f106389ec5b8e9108a31a95bbf4e839dc 100644
--- a/libselinux/src/regex.c
+++ b/libselinux/src/regex.c
@@ -319,7 +319,7 @@ char const *regex_version(void)
}
int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex,
- int unused __attribute__((unused)), bool *regex_compiled)
+ int do_load_precompregex __attribute__((unused)), bool *regex_compiled)
{
int rc;
uint32_t entry_len;
@@ -387,7 +387,7 @@ static inline pcre_extra *get_pcre_extra(struct regex_data *regex)
}
int regex_writef(struct regex_data *regex, FILE *fp,
- int unused __attribute__((unused)))
+ int do_write_precompregex __attribute__((unused)))
{
int rc;
size_t len;
diff --git a/libselinux/src/regex.h b/libselinux/src/regex.h
index 10c3df7856e1eaf1dc8e760b89c8a63c371c3dc9..2dfa2534203470be6a5af89014a2da7755afca2d 100644
--- a/libselinux/src/regex.h
+++ b/libselinux/src/regex.h
@@ -44,7 +44,7 @@ struct mmap_area;
char const *regex_arch_string(void) ;
/**
- * regex_verison returns the version string of the underlying regular
+ * regex_version returns the version string of the underlying regular
* regular expressions library. In the case of PCRE it just returns the
* result of pcre_version(). In the case of PCRE2, the very first time this
* function is called it allocates a buffer large enough to hold the version
diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c
index 6c5238953cb1750c06de46641b16a82bcefe4433..97f81a8b61ce18ec06c234889d7f2fb017413bbb 100644
--- a/libselinux/src/selinux_config.c
+++ b/libselinux/src/selinux_config.c
@@ -177,8 +177,11 @@ static void init_selinux_config(void)
if (!strncasecmp(buf_p, SELINUXTYPETAG,
sizeof(SELINUXTYPETAG) - 1)) {
type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1);
- if (!type)
+ if (!type) {
+ free(line_buf);
+ fclose(fp);
return;
+ }
end = type + strlen(type) - 1;
while ((end > type) &&
(isspace(*end) || iscntrl(*end))) {
@@ -187,6 +190,8 @@ static void init_selinux_config(void)
}
if (setpolicytype(type) != 0) {
free(type);
+ free(line_buf);
+ fclose(fp);
return;
}
free(type);
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 898dd9105e442c7af079f38999aad1a77cce91e2..e2553cdabeb54837190122680b390d7ebf41360d 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -62,7 +62,7 @@ static uint64_t fc_count = 0; /* Number of files processed so far */
static uint64_t efile_count; /* Estimated total number of files */
/* Store information on directories with xattr's. */
-struct dir_xattr *dir_xattr_list;
+static struct dir_xattr *dir_xattr_list;
static struct dir_xattr *dir_xattr_last;
/* restorecon_flags for passing to restorecon_sb() */
@@ -230,7 +230,6 @@ static int exclude_non_seclabel_mounts(void)
struct utsname uts;
FILE *fp;
size_t len;
- ssize_t num;
int index = 0, found = 0, nfile = 0;
char *mount_info[4];
char *buf = NULL, *item;
@@ -245,7 +244,7 @@ static int exclude_non_seclabel_mounts(void)
if (!fp)
return 0;
- while ((num = getline(&buf, &len, fp)) != -1) {
+ while (getline(&buf, &len, fp) != -1) {
found = 0;
index = 0;
item = strtok(buf, " ");
@@ -334,8 +333,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
rc = removexattr(directory, RESTORECON_PARTIAL_MATCH_DIGEST);
if (rc) {
selinux_log(SELINUX_ERROR,
- "Error: %s removing xattr \"%s\" from: %s\n",
- strerror(errno),
+ "Error: %m removing xattr \"%s\" from: %s\n",
RESTORECON_PARTIAL_MATCH_DIGEST, directory);
digest_result = ERROR;
}
@@ -748,8 +746,8 @@ out1:
return rc;
err:
selinux_log(SELINUX_ERROR,
- "Could not set context for %s: %s\n",
- pathname, strerror(errno));
+ "Could not set context for %s: %m\n",
+ pathname);
rc = -1;
goto out1;
}
@@ -871,6 +869,7 @@ int selinux_restorecon(const char *pathname_orig,
dev_t dev_num = 0;
struct dir_hash_node *current = NULL;
struct dir_hash_node *head = NULL;
+ int errno_tmp;
if (flags.verbose && flags.progress)
flags.verbose = false;
@@ -943,8 +942,8 @@ int selinux_restorecon(const char *pathname_orig,
return 0;
} else {
selinux_log(SELINUX_ERROR,
- "lstat(%s) failed: %s\n",
- pathname, strerror(errno));
+ "lstat(%s) failed: %m\n",
+ pathname);
error = -1;
goto cleanup;
}
@@ -968,8 +967,8 @@ int selinux_restorecon(const char *pathname_orig,
memset(&sfsb, 0, sizeof sfsb);
if (!S_ISLNK(sb.st_mode) && statfs(pathname, &sfsb) < 0) {
selinux_log(SELINUX_ERROR,
- "statfs(%s) failed: %s\n",
- pathname, strerror(errno));
+ "statfs(%s) failed: %m\n",
+ pathname);
error = -1;
goto cleanup;
}
@@ -1020,24 +1019,30 @@ int selinux_restorecon(const char *pathname_orig,
case FTS_DP:
continue;
case FTS_DNR:
+ errno_tmp = errno;
+ errno = ftsent->fts_errno;
selinux_log(SELINUX_ERROR,
- "Could not read %s: %s.\n",
- ftsent->fts_path,
- strerror(ftsent->fts_errno));
+ "Could not read %s: %m.\n",
+ ftsent->fts_path);
+ errno = errno_tmp;
fts_set(fts, ftsent, FTS_SKIP);
continue;
case FTS_NS:
+ errno_tmp = errno;
+ errno = ftsent->fts_errno;
selinux_log(SELINUX_ERROR,
- "Could not stat %s: %s.\n",
- ftsent->fts_path,
- strerror(ftsent->fts_errno));
+ "Could not stat %s: %m.\n",
+ ftsent->fts_path);
+ errno = errno_tmp;
fts_set(fts, ftsent, FTS_SKIP);
continue;
case FTS_ERR:
+ errno_tmp = errno;
+ errno = ftsent->fts_errno;
selinux_log(SELINUX_ERROR,
- "Error on %s: %s.\n",
- ftsent->fts_path,
- strerror(ftsent->fts_errno));
+ "Error on %s: %m.\n",
+ ftsent->fts_path);
+ errno = errno_tmp;
fts_set(fts, ftsent, FTS_SKIP);
continue;
case FTS_D:
@@ -1101,9 +1106,8 @@ int selinux_restorecon(const char *pathname_orig,
current->digest,
SHA1_HASH_SIZE, 0) < 0) {
selinux_log(SELINUX_ERROR,
- "setxattr failed: %s: %s\n",
- current->path,
- strerror(errno));
+ "setxattr failed: %s: %m\n",
+ current->path);
}
current = current->next;
}
@@ -1145,16 +1149,16 @@ oom:
realpatherr:
sverrno = errno;
selinux_log(SELINUX_ERROR,
- "SELinux: Could not get canonical path for %s restorecon: %s.\n",
- pathname_orig, strerror(errno));
+ "SELinux: Could not get canonical path for %s restorecon: %m.\n",
+ pathname_orig);
errno = sverrno;
error = -1;
goto cleanup;
fts_err:
selinux_log(SELINUX_ERROR,
- "fts error while labeling %s: %s\n",
- paths[0], strerror(errno));
+ "fts error while labeling %s: %m\n",
+ paths[0]);
error = -1;
goto cleanup;
}
@@ -1166,7 +1170,7 @@ void selinux_restorecon_set_sehandle(struct selabel_handle *hndl)
unsigned char *fc_digest;
size_t num_specfiles, fc_digest_len;
- fc_sehandle = (struct selabel_handle *) hndl;
+ fc_sehandle = hndl;
if (!fc_sehandle)
return;
@@ -1195,8 +1199,7 @@ struct selabel_handle *selinux_restorecon_default_handle(void)
if (!sehandle) {
selinux_log(SELINUX_ERROR,
- "Error obtaining file context handle: %s\n",
- strerror(errno));
+ "Error obtaining file context handle: %m\n");
return NULL;
}
@@ -1216,8 +1219,8 @@ void selinux_restorecon_set_exclude_list(const char **exclude_list)
for (i = 0; exclude_list[i]; i++) {
if (lstat(exclude_list[i], &sb) < 0 && errno != EACCES) {
selinux_log(SELINUX_ERROR,
- "lstat error on exclude path \"%s\", %s - ignoring.\n",
- exclude_list[i], strerror(errno));
+ "lstat error on exclude path \"%s\", %m - ignoring.\n",
+ exclude_list[i]);
break;
}
if (add_exclude(exclude_list[i], CALLER_EXCLUDED) &&
@@ -1283,8 +1286,8 @@ int selinux_restorecon_xattr(const char *pathname, unsigned int xattr_flags,
return 0;
selinux_log(SELINUX_ERROR,
- "lstat(%s) failed: %s\n",
- pathname, strerror(errno));
+ "lstat(%s) failed: %m\n",
+ pathname);
return -1;
}
@@ -1314,8 +1317,8 @@ int selinux_restorecon_xattr(const char *pathname, unsigned int xattr_flags,
fts = fts_open(paths, fts_flags, NULL);
if (!fts) {
selinux_log(SELINUX_ERROR,
- "fts error on %s: %s\n",
- paths[0], strerror(errno));
+ "fts error on %s: %m\n",
+ paths[0]);
return -1;
}
diff --git a/libselinux/src/sestatus.c b/libselinux/src/sestatus.c
index 12b015e088ea3666bab58a8bfd8aa3d68913e26e..89c1f6216702d1b3775ac89509e2a38ca4752420 100644
--- a/libselinux/src/sestatus.c
+++ b/libselinux/src/sestatus.c
@@ -282,6 +282,10 @@ int selinux_status_open(int fallback)
long pagesize;
uint32_t seqno;
+ if (selinux_status != NULL) {
+ return (selinux_status == MAP_FAILED) ? 1 : 0;
+ }
+
if (!selinux_mnt) {
errno = ENOENT;
return -1;
diff --git a/libselinux/src/setexecfilecon.c b/libselinux/src/setexecfilecon.c
index e72ba0d9888015aeab6acf988eedb8247b9e5701..2c6505a96a4825f24bee565387edab78b5ff1fe6 100644
--- a/libselinux/src/setexecfilecon.c
+++ b/libselinux/src/setexecfilecon.c
@@ -37,7 +37,6 @@ int setexecfilecon(const char *filename, const char *fallback_type)
newcon = strdup(context_str(con));
if (!newcon)
goto out;
- rc = 0;
}
rc = setexeccon(newcon);
diff --git a/libselinux/src/setup.py b/libselinux/src/setup.py
index 48fefdeb28636da31702ab683f745bfddd73a153..b79b2750748083387a37197207c60a6fed427de6 100644
--- a/libselinux/src/setup.py
+++ b/libselinux/src/setup.py
@@ -4,7 +4,7 @@ from distutils.core import Extension, setup
setup(
name="selinux",
- version="3.2",
+ version="3.3",
description="SELinux python 3 bindings",
author="SELinux Project",
author_email="selinux@vger.kernel.org",
diff --git a/libselinux/src/sha1.c b/libselinux/src/sha1.c
index 9a8ce01dcedadb2fbb2ecfdf4de437b8ba9efb5b..a848467785f3a13aa448ac60251c9e1c29f0837d 100644
--- a/libselinux/src/sha1.c
+++ b/libselinux/src/sha1.c
@@ -16,6 +16,7 @@
// sha1.c:73:33: error: cast from 'uint8_t *' (aka 'unsigned char *') to 'CHAR64LONG16 *' increases required alignment from 1 to 4 [-Werror,-Wcast-align]
// CHAR64LONG16* block = (CHAR64LONG16*) workspace;
// William Roberts
+// - Silence clang's -Wextra-semi-stmt warning - July 2021, Nicolas Iooss
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -49,11 +50,11 @@ typedef union
^block->l[(i+2)&15]^block->l[i&15],1))
// (R0+R1), R2, R3, R4 are the different operations used in SHA1
-#define R0(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30);
-#define R1(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30);
-#define R2(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30);
-#define R3(v,w,x,y,z,i) z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30);
-#define R4(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30);
+#define R0(v,w,x,y,z,i) do { z += ((w&(x^y))^y) + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30); } while (0)
+#define R1(v,w,x,y,z,i) do { z += ((w&(x^y))^y) + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30); } while (0)
+#define R2(v,w,x,y,z,i) do { z += (w^x^y) + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30); } while (0)
+#define R3(v,w,x,y,z,i) do { z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30); } while (0)
+#define R4(v,w,x,y,z,i) do { z += (w^x^y) + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30); } while (0)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -151,7 +152,7 @@ void
Sha1Update
(
Sha1Context* Context,
- void* Buffer,
+ const void* Buffer,
uint32_t BufferSize
)
{
@@ -172,7 +173,7 @@ void
TransformFunction(Context->State, Context->Buffer);
for (; i + 63 < BufferSize; i += 64)
{
- TransformFunction(Context->State, (uint8_t*)Buffer + i);
+ TransformFunction(Context->State, (const uint8_t*)Buffer + i);
}
j = 0;
}
@@ -181,7 +182,7 @@ void
i = 0;
}
- memcpy(&Context->Buffer[j], &((uint8_t*)Buffer)[i], BufferSize - i);
+ memcpy(&Context->Buffer[j], &((const uint8_t*)Buffer)[i], BufferSize - i);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -205,10 +206,10 @@ void
finalcount[i] = (unsigned char)((Context->Count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); // Endian independent
}
- Sha1Update(Context, (uint8_t*)"\x80", 1);
+ Sha1Update(Context, (const uint8_t*)"\x80", 1);
while ((Context->Count[0] & 504) != 448)
{
- Sha1Update(Context, (uint8_t*)"\0", 1);
+ Sha1Update(Context, (const uint8_t*)"\0", 1);
}
Sha1Update(Context, finalcount, 8); // Should cause a Sha1TransformFunction()
diff --git a/libselinux/src/sha1.h b/libselinux/src/sha1.h
index eac3c195351ac754a14bf26ec7cb5a1151a20eb8..f83a6e7ed7baf6510b4bc598493d7068771ebacc 100644
--- a/libselinux/src/sha1.h
+++ b/libselinux/src/sha1.h
@@ -64,7 +64,7 @@ void
Sha1Update
(
Sha1Context* Context,
- void* Buffer,
+ const void* Buffer,
uint32_t BufferSize
);
diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c
index 012a740a622e6548dde60e811a06a4acb4d7ad42..2fe69f4391aeee0502cf85921b990a08c0ccaed5 100644
--- a/libselinux/src/stringrep.c
+++ b/libselinux/src/stringrep.c
@@ -229,7 +229,7 @@ access_vector_t string_to_av_perm(security_class_t tclass, const char *s)
size_t i;
for (i = 0; i < MAXVECTORS && node->perms[i] != NULL; i++)
if (strcmp(node->perms[i],s) == 0)
- return map_perm(tclass, 1<perms[i];
return NULL;
@@ -279,7 +279,7 @@ int security_av_string(security_class_t tclass, access_vector_t av, char **res)
/* first pass computes the required length */
for (i = 0; tmp; tmp >>= 1, i++) {
if (tmp & 1) {
- str = security_av_perm_to_string(tclass, av & (1<>= 1, i++) {
if (tmp & 1) {
- str = security_av_perm_to_string(tclass, av & (1< 0) {
switch (opt) {
case 'l':
+ free(level);
level = strdup(optarg);
if (!level) {
fprintf(stderr, "memory allocation failure: %d(%s)\n",
diff --git a/libselinux/utils/getdefaultcon.c b/libselinux/utils/getdefaultcon.c
index 96a5a8c23656c2ded3274ad57edafe7b761d702c..957c1cb2e307fc0ea2b4b210ebd33b8ce95e7262 100644
--- a/libselinux/utils/getdefaultcon.c
+++ b/libselinux/utils/getdefaultcon.c
@@ -28,12 +28,15 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "l:r:s:v")) > 0) {
switch (opt) {
case 'l':
+ free(level);
level = strdup(optarg);
break;
case 'r':
+ free(role);
role = strdup(optarg);
break;
case 's':
+ free(service);
service = strdup(optarg);
break;
case 'v':
diff --git a/libselinux/utils/getseuser.c b/libselinux/utils/getseuser.c
index ce1b7b27dbd9e48ab77f9a7dd3f2008ad85de9ed..34f2e887ffa0d5045a907d0dec3f10b718ec45e8 100644
--- a/libselinux/utils/getseuser.c
+++ b/libselinux/utils/getseuser.c
@@ -9,7 +9,7 @@ int main(int argc, char **argv)
{
char *seuser = NULL, *level = NULL;
char **contextlist;
- int rc, n;
+ int rc, n, i;
if (argc != 3) {
fprintf(stderr, "usage: %s linuxuser fromcon\n", argv[0]);
@@ -50,7 +50,7 @@ int main(int argc, char **argv)
if (n == 0)
printf("no valid context found\n");
- for (int i = 0; i < n; i++)
+ for (i = 0; i < n; i++)
printf("Context %d\t%s\n", i, contextlist[i]);
freeconary(contextlist);
diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c
index a07e160dee714471b2063e75e11bb410dc460103..1d713c01f81cc9c86cd57e16bee0f2121b791b33 100644
--- a/libselinux/utils/matchpathcon.c
+++ b/libselinux/utils/matchpathcon.c
@@ -65,7 +65,7 @@ static mode_t string_to_mode(char *s)
return S_IFREG;
default:
return -1;
- };
+ }
return -1;
}
diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c
index dcb0085ad67ee51564840dd41fbdd1665a2df567..6c32172d994443fcefe9a71e12fc8c41d55afb0c 100644
--- a/libselinux/utils/sefcontext_compile.c
+++ b/libselinux/utils/sefcontext_compile.c
@@ -14,7 +14,7 @@
#include "../src/label_file.h"
#include "../src/regex.h"
-const char *policy_file;
+static const char *policy_file;
static int ctx_err;
static int validate_context(char **ctxp)
diff --git a/libselinux/utils/selabel_get_digests_all_partial_matches.c b/libselinux/utils/selabel_get_digests_all_partial_matches.c
index 0c2edc67771de6ea22425b7339fcde6e026f2467..e28833d2ce970d3304ce9ed1716b20f4e0c8f391 100644
--- a/libselinux/utils/selabel_get_digests_all_partial_matches.c
+++ b/libselinux/utils/selabel_get_digests_all_partial_matches.c
@@ -128,7 +128,7 @@ int main(int argc, char **argv)
printf("No SHA1 digest available for: %s\n",
ftsent->fts_path);
printf("as file_context entry is \"<>\"\n");
- break;
+ goto cleanup;
}
printf("The file_context entries for: %s\n",
@@ -149,11 +149,11 @@ int main(int argc, char **argv)
xattr_digest[i]);
printf("%s\n", sha1_buf);
}
-
- free(xattr_digest);
- free(calculated_digest);
- free(sha1_buf);
}
+ cleanup:
+ free(xattr_digest);
+ free(calculated_digest);
+ free(sha1_buf);
break;
}
default:
diff --git a/libselinux/utils/selabel_lookup_best_match.c b/libselinux/utils/selabel_lookup_best_match.c
index 6a7174233667c327d2d1678bd381db279e58c038..2cddc6cde0510ec8fdcf061dfad3805a9e3738ad 100644
--- a/libselinux/utils/selabel_lookup_best_match.c
+++ b/libselinux/utils/selabel_lookup_best_match.c
@@ -47,7 +47,7 @@ static mode_t string_to_mode(char *s)
return S_IFSOCK;
case 'f':
return S_IFREG;
- };
+ }
return 0;
}
diff --git a/libsepol/.gitignore b/libsepol/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..77bb5911c3f24371d977f5d0578d840430b61e50
--- /dev/null
+++ b/libsepol/.gitignore
@@ -0,0 +1,2 @@
+utils/chkcon
+libsepol.map
diff --git a/libsepol/VERSION b/libsepol/VERSION
index a3ec5a4bd3d7209b4a687a77cad49b945339994b..eb39e5382f4f035e4d71c7f67712cdbfa6c0c335 100644
--- a/libsepol/VERSION
+++ b/libsepol/VERSION
@@ -1 +1 @@
-3.2
+3.3
diff --git a/libsepol/cil/.gitignore b/libsepol/cil/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..7218d83c298dfbf0296288bc58c1a979221938d5
--- /dev/null
+++ b/libsepol/cil/.gitignore
@@ -0,0 +1,14 @@
+*.swp
+*.gcda
+*.gcno
+*.o
+*.a
+src/cil_lexer.c
+unit_tests
+cov
+secilc
+docs/pdf/
+docs/html/
+docs/man8/
+policy.*
+file_contexts
diff --git a/libsepol/cil/include/cil/cil.h b/libsepol/cil/include/cil/cil.h
index e6f4503eb33a45ed32d7f1178dedb7b99e00c3db..482ca522277b79f6ef6ce96bcbd5d47f9eefe1b1 100644
--- a/libsepol/cil/include/cil/cil.h
+++ b/libsepol/cil/include/cil/cil.h
@@ -51,6 +51,7 @@ extern int cil_selinuxusers_to_string(cil_db_t *db, char **out, size_t *size);
extern int cil_filecons_to_string(cil_db_t *db, char **out, size_t *size);
extern void cil_set_disable_dontaudit(cil_db_t *db, int disable_dontaudit);
extern void cil_set_multiple_decls(cil_db_t *db, int multiple_decls);
+extern void cil_set_qualified_names(struct cil_db *db, int qualified_names);
extern void cil_set_disable_neverallow(cil_db_t *db, int disable_neverallow);
extern void cil_set_preserve_tunables(cil_db_t *db, int preserve_tunables);
extern int cil_set_handle_unknown(cil_db_t *db, int handle_unknown);
@@ -60,6 +61,9 @@ extern void cil_set_attrs_expand_size(struct cil_db *db, unsigned attrs_expand_s
extern void cil_set_target_platform(cil_db_t *db, int target_platform);
extern void cil_set_policy_version(cil_db_t *db, int policy_version);
extern void cil_write_policy_conf(FILE *out, struct cil_db *db);
+extern int cil_write_parse_ast(FILE *out, cil_db_t *db);
+extern int cil_write_build_ast(FILE *out, cil_db_t *db);
+extern int cil_write_resolve_ast(FILE *out, cil_db_t *db);
enum cil_log_level {
CIL_ERR = 1,
diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 99c8e288912c3af1bc286f0bb09735cf9ab431b5..4cc7f87fa9474802435cb10387b64475760df485 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -50,10 +50,11 @@
#include "cil_binary.h"
#include "cil_policy.h"
#include "cil_strpool.h"
+#include "cil_write_ast.h"
-int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
+const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
{64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
- {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
+ {8, 8, 8, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
@@ -141,6 +142,8 @@ char *CIL_KEY_HANDLEUNKNOWN_DENY;
char *CIL_KEY_HANDLEUNKNOWN_REJECT;
char *CIL_KEY_MACRO;
char *CIL_KEY_IN;
+char *CIL_KEY_IN_BEFORE;
+char *CIL_KEY_IN_AFTER;
char *CIL_KEY_MLS;
char *CIL_KEY_DEFAULTRANGE;
char *CIL_KEY_BLOCKINHERIT;
@@ -219,7 +222,9 @@ char *CIL_KEY_IOCTL;
char *CIL_KEY_UNORDERED;
char *CIL_KEY_SRC_INFO;
char *CIL_KEY_SRC_CIL;
-char *CIL_KEY_SRC_HLL;
+char *CIL_KEY_SRC_HLL_LMS;
+char *CIL_KEY_SRC_HLL_LMX;
+char *CIL_KEY_SRC_HLL_LME;
static void cil_init_keys(void)
{
@@ -352,6 +357,8 @@ static void cil_init_keys(void)
CIL_KEY_DEFAULTTYPE = cil_strpool_add("defaulttype");
CIL_KEY_MACRO = cil_strpool_add("macro");
CIL_KEY_IN = cil_strpool_add("in");
+ CIL_KEY_IN_BEFORE = cil_strpool_add("before");
+ CIL_KEY_IN_AFTER = cil_strpool_add("after");
CIL_KEY_MLS = cil_strpool_add("mls");
CIL_KEY_DEFAULTRANGE = cil_strpool_add("defaultrange");
CIL_KEY_GLOB = cil_strpool_add("*");
@@ -383,8 +390,10 @@ static void cil_init_keys(void)
CIL_KEY_IOCTL = cil_strpool_add("ioctl");
CIL_KEY_UNORDERED = cil_strpool_add("unordered");
CIL_KEY_SRC_INFO = cil_strpool_add("");
- CIL_KEY_SRC_CIL = cil_strpool_add("");
- CIL_KEY_SRC_HLL = cil_strpool_add("");
+ CIL_KEY_SRC_CIL = cil_strpool_add("cil");
+ CIL_KEY_SRC_HLL_LMS = cil_strpool_add("lms");
+ CIL_KEY_SRC_HLL_LMX = cil_strpool_add("lmx");
+ CIL_KEY_SRC_HLL_LME = cil_strpool_add("lme");
}
void cil_db_init(struct cil_db **db)
@@ -439,6 +448,7 @@ void cil_db_init(struct cil_db **db)
(*db)->handle_unknown = -1;
(*db)->mls = -1;
(*db)->multiple_decls = CIL_FALSE;
+ (*db)->qualified_names = CIL_FALSE;
(*db)->target_platform = SEPOL_TARGET_SELINUX;
(*db)->policy_version = POLICYDB_VERSION_MAX;
}
@@ -539,7 +549,7 @@ int cil_compile(struct cil_db *db)
cil_log(CIL_INFO, "Building AST from Parse Tree\n");
rc = cil_build_ast(db, db->parse->root, db->ast->root);
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "Failed to build ast\n");
+ cil_log(CIL_ERR, "Failed to build AST\n");
goto exit;
}
@@ -549,21 +559,21 @@ int cil_compile(struct cil_db *db)
cil_log(CIL_INFO, "Resolving AST\n");
rc = cil_resolve_ast(db, db->ast->root);
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "Failed to resolve ast\n");
+ cil_log(CIL_ERR, "Failed to resolve AST\n");
goto exit;
}
cil_log(CIL_INFO, "Qualifying Names\n");
rc = cil_fqn_qualify(db->ast->root);
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "Failed to qualify names\n");
+ cil_log(CIL_ERR, "Failed to qualify names\n");
goto exit;
}
cil_log(CIL_INFO, "Compile post process\n");
rc = cil_post_process(db);
if (rc != SEPOL_OK ) {
- cil_log(CIL_INFO, "Post process failed\n");
+ cil_log(CIL_ERR, "Post process failed\n");
goto exit;
}
@@ -572,6 +582,97 @@ exit:
return rc;
}
+int cil_write_parse_ast(FILE *out, cil_db_t *db)
+{
+ int rc = SEPOL_ERR;
+
+ if (db == NULL) {
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Writing Parse AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_PARSE, db->parse->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write parse ast\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
+int cil_write_build_ast(FILE *out, cil_db_t *db)
+{
+ int rc = SEPOL_ERR;
+
+ if (db == NULL) {
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Building AST from Parse Tree\n");
+ rc = cil_build_ast(db, db->parse->root, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to build ast\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Destroying Parse Tree\n");
+ cil_tree_destroy(&db->parse);
+
+ cil_log(CIL_INFO, "Writing Build AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_BUILD, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write build ast\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
+int cil_write_resolve_ast(FILE *out, cil_db_t *db)
+{
+ int rc = SEPOL_ERR;
+
+ if (db == NULL) {
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Building AST from Parse Tree\n");
+ rc = cil_build_ast(db, db->parse->root, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to build ast\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Destroying Parse Tree\n");
+ cil_tree_destroy(&db->parse);
+
+ cil_log(CIL_INFO, "Resolving AST\n");
+ rc = cil_resolve_ast(db, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to resolve ast\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Qualifying Names\n");
+ rc = cil_fqn_qualify(db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to qualify names\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Writing Resolve AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_RESOLVE, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write resolve ast\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db)
{
int rc;
@@ -1780,6 +1881,11 @@ void cil_set_multiple_decls(struct cil_db *db, int multiple_decls)
db->multiple_decls = multiple_decls;
}
+void cil_set_qualified_names(struct cil_db *db, int qualified_names)
+{
+ db->qualified_names = qualified_names;
+}
+
void cil_set_target_platform(struct cil_db *db, int target_platform)
{
db->target_platform = target_platform;
@@ -1790,7 +1896,7 @@ void cil_set_policy_version(struct cil_db *db, int policy_version)
db->policy_version = policy_version;
}
-void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM])
+void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM])
{
uint32_t i = 0;
for (i = 0; i < CIL_SYM_NUM; i++) {
@@ -1899,6 +2005,63 @@ exit:
return SEPOL_ERR;
}
+int cil_string_to_uint32(const char *string, uint32_t *value, int base)
+{
+ unsigned long val;
+ char *end = NULL;
+ int rc = SEPOL_ERR;
+
+ if (string == NULL || value == NULL) {
+ goto exit;
+ }
+
+ errno = 0;
+ val = strtoul(string, &end, base);
+ if (errno != 0 || end == string || *end != '\0') {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ /* Ensure that the value fits a 32-bit integer without triggering -Wtype-limits */
+#if ULONG_MAX > UINT32_MAX
+ if (val > UINT32_MAX) {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+#endif
+
+ *value = val;
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Failed to create uint32_t from string\n");
+ return rc;
+}
+
+int cil_string_to_uint64(const char *string, uint64_t *value, int base)
+{
+ char *end = NULL;
+ int rc = SEPOL_ERR;
+
+ if (string == NULL || value == NULL) {
+ goto exit;
+ }
+
+ errno = 0;
+ *value = strtoull(string, &end, base);
+ if (errno != 0 || end == string || *end != '\0') {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Failed to create uint64_t from string\n");
+ return rc;
+}
+
void cil_sort_init(struct cil_sort **sort)
{
*sort = cil_malloc(sizeof(**sort));
@@ -2023,6 +2186,7 @@ void cil_in_init(struct cil_in **in)
*in = cil_malloc(sizeof(**in));
cil_symtab_array_init((*in)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_IN]);
+ (*in)->is_after = CIL_FALSE;
(*in)->block_str = NULL;
}
@@ -2660,7 +2824,6 @@ void cil_call_init(struct cil_call **call)
void cil_optional_init(struct cil_optional **optional)
{
*optional = cil_malloc(sizeof(**optional));
- (*optional)->enabled = CIL_TRUE;
cil_symtab_datum_init(&(*optional)->datum);
}
@@ -2727,6 +2890,7 @@ void cil_mls_init(struct cil_mls **mls)
void cil_src_info_init(struct cil_src_info **info)
{
*info = cil_malloc(sizeof(**info));
- (*info)->is_cil = 0;
+ (*info)->kind = NULL;
+ (*info)->hll_line = 0;
(*info)->path = NULL;
}
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index f80d84679f853ae8be91d6a32a74212dee36a359..d8aa495a487eb4c1c17c1c47152753789f019eaa 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -55,9 +55,6 @@
#include "cil_find.h"
#include "cil_build_ast.h"
-/* There are 44000 filename_trans in current fedora policy. 1.33 times this is the recommended
- * size of a hashtable. The next power of 2 of this is 2 ** 16.
- */
#define ROLE_TRANS_TABLE_SIZE (1 << 10)
#define AVRULEX_TABLE_SIZE (1 << 10)
#define PERMS_PER_CLASS 32
@@ -593,11 +590,11 @@ exit:
int __cil_typeattr_bitmap_init(policydb_t *pdb)
{
int rc = SEPOL_ERR;
+ uint32_t i;
pdb->type_attr_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t));
pdb->attr_type_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t));
- uint32_t i = 0;
for (i = 0; i < pdb->p_types.nprim; i++) {
ebitmap_init(&pdb->type_attr_map[i]);
ebitmap_init(&pdb->attr_type_map[i]);
@@ -1073,7 +1070,7 @@ int __cil_type_rule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct ci
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
type_datum_t *sepol_result = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
ebitmap_node_t *node1, *node2;
@@ -1129,7 +1126,7 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
type_datum_t *sepol_result = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
ebitmap_node_t *node1, *node2;
@@ -1228,7 +1225,7 @@ int __perm_str_to_datum(char *perm_str, class_datum_t *sepol_class, uint32_t *da
goto exit;
}
}
- *datum |= 1 << (sepol_perm->s.value - 1);
+ *datum |= UINT32_C(1) << (sepol_perm->s.value - 1);
return SEPOL_OK;
@@ -1526,7 +1523,7 @@ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_
/* index of the u32 containing the permission */
#define XPERM_IDX(x) (x >> 5)
/* set bits 0 through x-1 within the u32 */
-#define XPERM_SETBITS(x) ((1U << (x & 0x1f)) - 1)
+#define XPERM_SETBITS(x) ((UINT32_C(1) << (x & 0x1f)) - 1)
/* low value for this u32 */
#define XPERM_LOW(x) (x << 5)
/* high value for this u32 */
@@ -1668,14 +1665,6 @@ exit:
}
cil_list_destroy(&xperms_list, CIL_FALSE);
}
-
- // hashtab_t does not have a way to free keys or datum since it doesn't
- // know what they are. We won't need the keys/datum after this function, so
- // clean them up here.
- free(avtab_key);
- ebitmap_destroy(datum);
- free(datum);
-
return rc;
}
@@ -1885,6 +1874,15 @@ exit:
return rc;
}
+static int __cil_avrulex_ioctl_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args)
+{
+ free(k);
+ ebitmap_destroy(datum);
+ free(datum);
+
+ return SEPOL_OK;
+}
+
int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
{
int rc;
@@ -2226,7 +2224,7 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
int rc = SEPOL_ERR;
struct cil_args_booleanif bool_args;
struct cil_booleanif *cil_boolif = (struct cil_booleanif*)node->data;
- struct cil_tree_node *cb_node = node->cl_head;
+ struct cil_tree_node *cb_node;
struct cil_tree_node *true_node = NULL;
struct cil_tree_node *false_node = NULL;
struct cil_tree_node *tmp_node = NULL;
@@ -2337,7 +2335,7 @@ int cil_roletrans_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
role_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
role_datum_t *sepol_result = NULL;
role_trans_t *new = NULL;
uint32_t *new_role = NULL;
@@ -2656,6 +2654,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_
int rc = SEPOL_ERR;
struct cil_list_item *item;
enum cil_flavor flavor;
+ enum cil_flavor cil_op;
constraint_expr_t *op, *h1, *h2, *t1, *t2;
int is_leaf = CIL_FALSE;
@@ -2672,7 +2671,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_
goto exit;
}
- enum cil_flavor cil_op = (enum cil_flavor)(uintptr_t)item->data;
+ cil_op = (enum cil_flavor)(uintptr_t)item->data;
switch (cil_op) {
case CIL_NOT:
op->expr_type = CEXPR_NOT;
@@ -3164,7 +3163,7 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_class = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
range_trans_t *newkey = NULL;
struct mls_range *newdatum = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
@@ -3601,7 +3600,7 @@ int cil_default_to_policydb(policydb_t *pdb, struct cil_default *def)
{
struct cil_list_item *curr;
class_datum_t *sepol_class;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
cil_list_for_each(curr, def->class_datums) {
struct cil_list_item *c;
@@ -3656,7 +3655,7 @@ int cil_defaultrange_to_policydb(policydb_t *pdb, struct cil_defaultrange *def)
{
struct cil_list_item *curr;
class_datum_t *sepol_class;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
cil_list_for_each(curr, def->class_datums) {
struct cil_list_item *c;
@@ -4275,7 +4274,7 @@ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hash
uint32_t hash = 0;
-#define mix(input) { \
+#define mix(input) do { \
uint32_t v = input; \
v *= c1; \
v = (v << r1) | (v >> (32 - r1)); \
@@ -4283,7 +4282,7 @@ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hash
hash ^= v; \
hash = (hash << r2) | (hash >> (32 - r2)); \
hash = hash * m + n; \
-}
+} while (0)
mix(k->target_class);
mix(k->target_type);
@@ -4481,7 +4480,8 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no
avrule_t *avrule;
struct cil_tree_node *source_node;
char *source_path;
- int is_cil;
+ char *lm_kind;
+ uint32_t hll_line;
avrule = cil_malloc(sizeof(avrule_t));
avrule->specified = kind;
@@ -4493,11 +4493,11 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no
avrule->source_filename = NULL;
avrule->source_line = node->line;
- source_node = cil_tree_get_next_path(node, &source_path, &is_cil);
+ source_node = cil_tree_get_next_path(node, &lm_kind, &hll_line, &source_path);
if (source_node) {
avrule->source_filename = source_path;
- if (!is_cil) {
- avrule->source_line = node->hll_line;
+ if (lm_kind != CIL_KEY_SRC_CIL) {
+ avrule->source_line = hll_line + node->hll_offset - source_node->hll_offset - 1;
}
}
@@ -4760,7 +4760,7 @@ static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t clas
cil_list_init(&cp->perms, CIL_PERM);
for (i = 0; i < sepol_class->permissions.nprim; i++) {
struct cil_perm *perm;
- if ((data & (1 << i)) == 0) continue;
+ if ((data & (UINT32_C(1) << i)) == 0) continue;
perm = perm_value_to_cil[class][i+1];
if (!perm) goto exit;
cil_list_append(cp->perms, CIL_PERM, perm);
@@ -4825,6 +4825,7 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void
avtab_ptr_t cur;
struct cil_avrule target;
struct cil_tree_node *n1 = NULL;
+ int count_bad = 0;
*violation = CIL_TRUE;
@@ -4838,10 +4839,13 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void
for (cur = bad; cur; cur = cur->next) {
struct cil_list_item *i2;
struct cil_list *matching;
+ int num_matching = 0;
+ int count_matching = 0;
rc = cil_avrule_from_sepol(pdb, cur, &target, type_value_to_cil, class_value_to_cil, perm_value_to_cil);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to convert sepol avrule to CIL\n");
+ bounds_destroy_bad(bad);
goto exit;
}
__cil_print_rule(" ", "allow", &target);
@@ -4854,6 +4858,9 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void
bounds_destroy_bad(bad);
goto exit;
}
+ cil_list_for_each(i2, matching) {
+ num_matching++;
+ }
cil_list_for_each(i2, matching) {
struct cil_tree_node *n2 = i2->data;
struct cil_avrule *r2 = n2->data;
@@ -4864,9 +4871,19 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void
__cil_print_parents(" ", n2);
__cil_print_rule(" ", "allow", r2);
}
+ count_matching++;
+ if (count_matching >= 2) {
+ cil_log(CIL_ERR, " Only first 2 of %d matching rules shown\n", num_matching);
+ break;
+ }
}
cil_list_destroy(&matching, CIL_FALSE);
cil_list_destroy(&target.perms.classperms, CIL_TRUE);
+ count_bad++;
+ if (count_bad >= 2) {
+ cil_log(CIL_ERR, " Only first 2 of %d bad rules shown\n", numbad);
+ break;
+ }
}
bounds_destroy_bad(bad);
}
@@ -5037,6 +5054,7 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
exit:
hashtab_destroy(role_trans_table);
+ hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
hashtab_destroy(avrulex_ioctl_table);
free(type_value_to_cil);
free(class_value_to_cil);
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 1fef25d46f6a223f9acf4334103e224f830fed26..9c34be2339984b763d7c376eaad7b33ae0172509 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -64,7 +64,7 @@ int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct
CIL_SYN_N_STRINGS,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(current, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -83,39 +83,69 @@ exit:
return rc;
}
-/*
- * Determine whether or not multiple declarations of the same key can share a
- * datum, given the new datum and the one already present in a given symtab.
- */
-int cil_is_datum_multiple_decl(__attribute__((unused)) struct cil_symtab_datum *cur,
- struct cil_symtab_datum *old,
- enum cil_flavor f)
+static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old)
{
- int rc = CIL_FALSE;
+ if (f_new != f_old) {
+ return CIL_FALSE;
+ }
- switch (f) {
+ switch (f_new) {
case CIL_TYPE:
case CIL_TYPEATTRIBUTE:
- if (!old || f != FLAVOR(old)) {
- rc = CIL_FALSE;
- } else {
- /* type and typeattribute statements insert empty datums */
- rc = CIL_TRUE;
+ if (db->multiple_decls) {
+ return CIL_TRUE;
}
break;
+ case CIL_OPTIONAL:
+ return CIL_TRUE;
+ break;
default:
break;
}
- return rc;
+
+ return CIL_FALSE;
+}
+
+int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node)
+{
+ int rc;
+
+ if (symtab == NULL || datum == NULL || node == NULL) {
+ return SEPOL_ERR;
+ }
+
+ rc = cil_symtab_insert(symtab, key, datum, node);
+ if (rc == SEPOL_EEXIST) {
+ struct cil_symtab_datum *prev;
+ rc = cil_symtab_get_datum(symtab, key, &prev);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(node), key);
+ return SEPOL_ERR;
+ }
+ if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) {
+ /* multiple_decls not ok, ret error */
+ struct cil_tree_node *n = NODE(prev);
+ cil_log(CIL_ERR, "Re-declaration of %s %s\n",
+ cil_node_to_string(node), key);
+ cil_tree_log(node, CIL_ERR, "Previous declaration of %s",
+ cil_node_to_string(n));
+ return SEPOL_ERR;
+ }
+ /* multiple_decls is enabled and works for this datum type, add node */
+ cil_list_append(prev->nodes, CIL_NODE, node);
+ node->data = prev;
+ return SEPOL_EEXIST;
+ }
+
+ return SEPOL_OK;
}
int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor)
{
int rc = SEPOL_ERR;
symtab_t *symtab = NULL;
- struct cil_symtab_datum *prev;
- rc = __cil_verify_name((const char*)key);
+ rc = cil_verify_name(db, (const char*)key, nflavor);
if (rc != SEPOL_OK) {
goto exit;
}
@@ -128,47 +158,15 @@ int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_s
ast_node->data = datum;
ast_node->flavor = nflavor;
- if (symtab != NULL) {
- rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node);
- if (rc == SEPOL_EEXIST) {
- rc = cil_symtab_get_datum(symtab, (hashtab_key_t)key, &prev);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(ast_node), key);
- goto exit;
- }
- if (!db->multiple_decls ||
- !cil_is_datum_multiple_decl(datum, prev, nflavor)) {
- /* multiple_decls not ok, ret error */
- struct cil_tree_node *node = NODE(prev);
- cil_log(CIL_ERR, "Re-declaration of %s %s\n",
- cil_node_to_string(ast_node), key);
- cil_tree_log(node, CIL_ERR, "Previous declaration of %s",
- cil_node_to_string(node));
- rc = SEPOL_ERR;
- goto exit;
- }
- /* multiple_decls is enabled and works for this datum type, add node */
- cil_list_append(prev->nodes, CIL_NODE, ast_node);
- ast_node->data = prev;
- cil_symtab_datum_destroy(datum);
- free(datum);
- }
+ rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
if (ast_node->parent->flavor == CIL_MACRO) {
- struct cil_list_item *item;
- struct cil_list *param_list = ((struct cil_macro*)ast_node->parent->data)->params;
- if (param_list != NULL) {
- cil_list_for_each(item, param_list) {
- struct cil_param *param = item->data;
- if (param->flavor == ast_node->flavor) {
- if (param->str == key) {
- cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(ast_node), key);
- rc = SEPOL_ERR;
- goto exit;
- }
- }
- }
+ rc = cil_verify_decl_does_not_shadow_macro_parameter(ast_node->parent->data, ast_node, key);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
}
@@ -196,7 +194,7 @@ int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_N_LISTS | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_block *block = NULL;
int rc = SEPOL_ERR;
@@ -205,6 +203,11 @@ int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Blocks are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -267,7 +270,7 @@ int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_blockinherit *inherit = NULL;
int rc = SEPOL_ERR;
@@ -275,6 +278,11 @@ int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current,
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Block inherit rules are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -324,7 +332,7 @@ int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_blockabstract *abstract = NULL;
int rc = SEPOL_ERR;
@@ -332,6 +340,11 @@ int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Block abstract rules are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -366,10 +379,11 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
- CIL_SYN_N_LISTS,
+ CIL_SYN_STRING | CIL_SYN_N_LISTS,
+ CIL_SYN_N_LISTS | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_in *in = NULL;
@@ -377,6 +391,11 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "In-statements are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -384,14 +403,29 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci
cil_in_init(&in);
- in->block_str = parse_current->next->data;
+ if (parse_current->next->next->data) {
+ char *is_after_str = parse_current->next->data;
+ if (is_after_str == CIL_KEY_IN_BEFORE) {
+ in->is_after = CIL_FALSE;
+ } else if (is_after_str == CIL_KEY_IN_AFTER) {
+ in->is_after = CIL_TRUE;
+ } else {
+ cil_log(CIL_ERR, "Value must be either \'before\' or \'after\'\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ in->block_str = parse_current->next->next->data;
+ } else {
+ in->is_after = CIL_FALSE;
+ in->block_str = parse_current->next->data;
+ }
ast_node->data = in;
ast_node->flavor = CIL_IN;
return SEPOL_OK;
exit:
- cil_tree_log(parse_current, CIL_ERR, "Bad in statement");
+ cil_tree_log(parse_current, CIL_ERR, "Bad in-statement");
cil_destroy_in(in);
return rc;
}
@@ -415,7 +449,7 @@ int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_class *class = NULL;
struct cil_tree_node *perms = NULL;
@@ -448,6 +482,8 @@ int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct
}
if (class->num_perms > CIL_PERMS_PER_CLASS) {
cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name);
+ cil_tree_children_destroy(ast_node);
+ rc = SEPOL_ERR;
goto exit;
}
@@ -481,7 +517,7 @@ int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, s
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_classorder *classorder = NULL;
struct cil_list_item *curr = NULL;
struct cil_list_item *head = NULL;
@@ -598,7 +634,7 @@ int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, st
cil_tree_node_init(&new_ast);
new_ast->parent = ast_node;
new_ast->line = current_perm->line;
- new_ast->hll_line = current_perm->hll_line;
+ new_ast->hll_offset = current_perm->hll_offset;
rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms);
if (rc != SEPOL_OK) {
@@ -632,7 +668,7 @@ int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms)
CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -659,7 +695,7 @@ int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classper
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -715,20 +751,11 @@ int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_lis
{
int rc = SEPOL_ERR;
struct cil_tree_node *curr;
- enum cil_syntax syntax[] = {
- CIL_SYN_STRING | CIL_SYN_LIST,
- };
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
if (parse_current == NULL || cp_list == NULL) {
goto exit;
}
- rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
cil_list_init(cp_list, CIL_CLASSPERMS);
curr = parse_current->cl_head;
@@ -789,7 +816,7 @@ int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_curre
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
@@ -847,7 +874,7 @@ int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_cu
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
@@ -897,7 +924,7 @@ int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_class *map = NULL;
int rc = SEPOL_ERR;
@@ -941,7 +968,7 @@ int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
@@ -993,7 +1020,7 @@ int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_class *common = NULL;
int rc = SEPOL_ERR;
@@ -1022,6 +1049,8 @@ int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struc
}
if (common->num_perms > CIL_PERMS_PER_CLASS) {
cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name);
+ cil_tree_children_destroy(ast_node);
+ rc = SEPOL_ERR;
goto exit;
}
@@ -1043,7 +1072,7 @@ int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_classcommon *clscom = NULL;
int rc = SEPOL_ERR;
@@ -1089,7 +1118,7 @@ int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct c
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_sid *sid = NULL;
int rc = SEPOL_ERR;
@@ -1139,7 +1168,7 @@ int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, s
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_sidcontext *sidcon = NULL;
int rc = SEPOL_ERR;
@@ -1198,7 +1227,7 @@ int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_sidorder *sidorder = NULL;
struct cil_list_item *curr = NULL;
int rc = SEPOL_ERR;
@@ -1258,7 +1287,7 @@ int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_user *user = NULL;
int rc = SEPOL_ERR;
@@ -1309,7 +1338,7 @@ int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_userattribute *attr = NULL;
int rc = SEPOL_ERR;
@@ -1376,7 +1405,7 @@ int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_curr
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userattributeset *attrset = NULL;
int rc = SEPOL_ERR;
@@ -1429,7 +1458,7 @@ int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userlevel *usrlvl = NULL;
int rc = SEPOL_ERR;
@@ -1489,7 +1518,7 @@ int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userrange *userrange = NULL;
int rc = SEPOL_ERR;
@@ -1549,7 +1578,7 @@ int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, s
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userprefix *userprefix = NULL;
int rc = SEPOL_ERR;
@@ -1595,7 +1624,7 @@ int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_selinuxuser *selinuxuser = NULL;
int rc = SEPOL_ERR;
@@ -1642,7 +1671,7 @@ int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_cu
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_selinuxuser *selinuxuser = NULL;
int rc = SEPOL_ERR;
@@ -1701,7 +1730,7 @@ int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_role *role = NULL;
int rc = SEPOL_ERR;
@@ -1753,7 +1782,7 @@ int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_roletype *roletype = NULL;
int rc = SEPOL_ERR;
@@ -1799,7 +1828,7 @@ int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userrole *userrole = NULL;
int rc = SEPOL_ERR;
@@ -1847,7 +1876,7 @@ int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_roletransition *roletrans = NULL;
int rc = SEPOL_ERR;
@@ -1895,7 +1924,7 @@ int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_roleallow *roleallow = NULL;
int rc = SEPOL_ERR;
@@ -1940,7 +1969,7 @@ int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_roleattribute *attr = NULL;
int rc = SEPOL_ERR;
@@ -1954,12 +1983,6 @@ int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_roleattribute_init(&attr);
key = parse_current->next->data;
@@ -2010,7 +2033,7 @@ int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_curr
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_roleattributeset *attrset = NULL;
int rc = SEPOL_ERR;
@@ -2064,7 +2087,7 @@ int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *as
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_avrule *rule = NULL;
int rc = SEPOL_ERR;
@@ -2126,7 +2149,7 @@ int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permiss
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
@@ -2164,7 +2187,7 @@ int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_permissionx *permx = NULL;
int rc = SEPOL_ERR;
@@ -2224,7 +2247,7 @@ int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *a
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_avrule *rule = NULL;
int rc = SEPOL_ERR;
@@ -2276,7 +2299,7 @@ int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_type_rule *rule = NULL;
int rc = SEPOL_ERR;
@@ -2324,7 +2347,7 @@ int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_type *type = NULL;
int rc = SEPOL_ERR;
@@ -2338,18 +2361,17 @@ int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_type_init(&type);
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE);
if (rc != SEPOL_OK) {
- goto exit;
+ if (rc == SEPOL_EEXIST) {
+ cil_destroy_type(type);
+ type = NULL;
+ } else {
+ goto exit;
+ }
}
return SEPOL_OK;
@@ -2378,7 +2400,7 @@ int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_typeattribute *attr = NULL;
int rc = SEPOL_ERR;
@@ -2392,18 +2414,17 @@ int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_typeattribute_init(&attr);
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
if (rc != SEPOL_OK) {
- goto exit;
+ if (rc == SEPOL_EEXIST) {
+ cil_destroy_typeattribute(attr);
+ attr = NULL;
+ } else {
+ goto exit;
+ }
}
return SEPOL_OK;
@@ -2449,7 +2470,7 @@ int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_bool *boolean = NULL;
int rc = SEPOL_ERR;
@@ -2513,7 +2534,7 @@ int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_tunable *tunable = NULL;
int rc = SEPOL_ERR;
@@ -2853,7 +2874,7 @@ int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_booleanif *bif = NULL;
struct cil_tree_node *next = NULL;
int rc = SEPOL_ERR;
@@ -2921,7 +2942,7 @@ int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_tunableif *tif = NULL;
struct cil_tree_node *next = NULL;
int rc = SEPOL_ERR;
@@ -2982,7 +3003,7 @@ int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_N_LISTS,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_condblock *cb = NULL;
@@ -3034,7 +3055,7 @@ int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_alias *alias = NULL;
enum cil_sym_index sym_index;
@@ -3049,12 +3070,6 @@ int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
- if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_alias_init(&alias);
key = parse_current->next->data;
@@ -3099,7 +3114,7 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_aliasactual *aliasactual = NULL;
if (db == NULL || parse_current == NULL || ast_node == NULL) {
@@ -3151,7 +3166,7 @@ int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_curr
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_typeattributeset *attrset = NULL;
int rc = SEPOL_ERR;
@@ -3204,7 +3219,7 @@ int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_c
CIL_SYN_END
};
char *expand_str;
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_expandtypeattribute *expandattr = NULL;
int rc = SEPOL_ERR;
@@ -3237,6 +3252,7 @@ int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_c
expandattr->expand = CIL_FALSE;
} else {
cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
+ rc = SEPOL_ERR;
goto exit;
}
@@ -3271,7 +3287,7 @@ int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_curren
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_typepermissive *typeperm = NULL;
int rc = SEPOL_ERR;
@@ -3320,7 +3336,7 @@ int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_curren
CIL_SYN_STRING | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *s1, *s2, *s3, *s4, *s5;
if (db == NULL || parse_current == NULL || ast_node == NULL ) {
@@ -3410,7 +3426,7 @@ int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_curre
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_rangetransition *rangetrans = NULL;
int rc = SEPOL_ERR;
@@ -3473,7 +3489,7 @@ int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_sens *sens = NULL;
int rc = SEPOL_ERR;
@@ -3525,7 +3541,7 @@ int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_cat *cat = NULL;
int rc = SEPOL_ERR;
@@ -3575,7 +3591,7 @@ int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_catset *catset = NULL;
int rc = SEPOL_ERR;
@@ -3632,7 +3648,7 @@ int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_catorder *catorder = NULL;
struct cil_list_item *curr = NULL;
int rc = SEPOL_ERR;
@@ -3692,7 +3708,7 @@ int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_curr
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_sensorder *sensorder = NULL;
struct cil_list_item *curr = NULL;
int rc = SEPOL_ERR;
@@ -3715,7 +3731,7 @@ int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_curr
cil_list_for_each(curr, sensorder->sens_list_str) {
if (curr->data == CIL_KEY_UNORDERED) {
- cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
+ cil_log(CIL_ERR, "Sensitivity order cannot be unordered.\n");
rc = SEPOL_ERR;
goto exit;
}
@@ -3753,7 +3769,7 @@ int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_senscat *senscat = NULL;
int rc = SEPOL_ERR;
@@ -3805,7 +3821,7 @@ int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_level *level = NULL;
int rc = SEPOL_ERR;
@@ -3863,7 +3879,7 @@ int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlran
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
if (low == NULL || lvlrange == NULL) {
@@ -3911,7 +3927,7 @@ int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, s
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_levelrange *lvlrange = NULL;
int rc = SEPOL_ERR;
@@ -3975,7 +3991,7 @@ int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_constrain *cons = NULL;
int rc = SEPOL_ERR;
@@ -4032,7 +4048,7 @@ int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_validatetrans *validtrans = NULL;
int rc = SEPOL_ERR;
@@ -4089,7 +4105,7 @@ int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *contex
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
if (user_node == NULL || context == NULL) {
@@ -4133,7 +4149,7 @@ int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_context *context = NULL;
int rc = SEPOL_ERR;
@@ -4176,7 +4192,7 @@ void cil_destroy_context(struct cil_context *context)
return;
}
- cil_symtab_datum_destroy(&context->datum);;
+ cil_symtab_datum_destroy(&context->datum);
if (context->range_str == NULL && context->range != NULL) {
cil_destroy_levelrange(context->range);
@@ -4194,7 +4210,7 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_filecon *filecon = NULL;
char *type = NULL;
@@ -4284,7 +4300,7 @@ int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax) / sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_ibpkeycon *ibpkeycon = NULL;
@@ -4367,7 +4383,7 @@ int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_portcon *portcon = NULL;
char *proto;
@@ -4469,7 +4485,7 @@ int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_nodecon *nodecon = NULL;
@@ -4558,7 +4574,7 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_genfscon *genfscon = NULL;
@@ -4621,7 +4637,7 @@ int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_netifcon *netifcon = NULL;
@@ -4697,7 +4713,7 @@ int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_t
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax) / sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_ibendportcon *ibendportcon = NULL;
@@ -4758,7 +4774,7 @@ int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_pirqcon *pirqcon = NULL;
@@ -4821,7 +4837,7 @@ int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_iomemcon *iomemcon = NULL;
@@ -4906,7 +4922,7 @@ int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_ioportcon *ioportcon = NULL;
@@ -4991,7 +5007,7 @@ int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_pcidevicecon *pcidevicecon = NULL;
@@ -5054,7 +5070,7 @@ int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_devicetreecon *devicetreecon = NULL;
@@ -5115,7 +5131,7 @@ int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *type = NULL;
struct cil_fsuse *fsuse = NULL;
int rc = SEPOL_ERR;
@@ -5196,6 +5212,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
char *key = NULL;
struct cil_macro *macro = NULL;
struct cil_tree_node *macro_content = NULL;
+ struct cil_tree_node *current_item;
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
@@ -5203,7 +5220,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_N_LISTS | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/ sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/ sizeof(*syntax);
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
@@ -5218,7 +5235,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
key = parse_current->next->data;
- struct cil_tree_node *current_item = parse_current->next->next->cl_head;
+ current_item = parse_current->next->next->cl_head;
while (current_item != NULL) {
enum cil_syntax param_syntax[] = {
CIL_SYN_STRING,
@@ -5228,6 +5245,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
char *kind = NULL;
struct cil_param *param = NULL;
+ struct cil_list_item *curr_param;
rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
if (rc != SEPOL_OK) {
@@ -5279,14 +5297,13 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
param->str = current_item->cl_head->next->data;
- rc = __cil_verify_name(param->str);
+ rc = cil_verify_name(db, param->str, param->flavor);
if (rc != SEPOL_OK) {
cil_destroy_param(param);
goto exit;
}
//walk current list and check for duplicate parameters
- struct cil_list_item *curr_param;
cil_list_for_each(curr_param, macro->params) {
if (param->str == ((struct cil_param*)curr_param->data)->str) {
cil_log(CIL_ERR, "Duplicate parameter\n");
@@ -5348,7 +5365,7 @@ int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_call *call = NULL;
int rc = SEPOL_ERR;
@@ -5453,7 +5470,7 @@ int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_N_LISTS | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_optional *optional = NULL;
int rc = SEPOL_ERR;
@@ -5472,8 +5489,14 @@ int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, str
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
- if (rc != SEPOL_OK)
- goto exit;
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ cil_destroy_optional(optional);
+ optional = NULL;
+ } else {
+ goto exit;
+ }
+ }
return SEPOL_OK;
@@ -5501,7 +5524,7 @@ int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_policycap *polcap = NULL;
int rc = SEPOL_ERR;
@@ -5550,7 +5573,7 @@ int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_ipaddr *ipaddr = NULL;
int rc = SEPOL_ERR;
@@ -5600,60 +5623,40 @@ void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
{
int rc = SEPOL_ERR;
- char *endptr = NULL;
- unsigned long val;
if (int_node == NULL || int_node->data == NULL || integer == NULL) {
goto exit;
}
- errno = 0;
- val = strtoul(int_node->data, &endptr, base);
- if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
- rc = SEPOL_ERR;
- goto exit;
- }
-
- /* Ensure that the value fits a 32-bit integer without triggering -Wtype-limits */
-#if ULONG_MAX > UINT32_MAX
- if (val > UINT32_MAX) {
- rc = SEPOL_ERR;
+ rc = cil_string_to_uint32(int_node->data, integer, base);
+ if (rc != SEPOL_OK) {
goto exit;
}
-#endif
-
- *integer = val;
return SEPOL_OK;
exit:
- cil_log(CIL_ERR, "Failed to create integer from string\n");
+ cil_log(CIL_ERR, "Failed to fill 32-bit integer\n");
return rc;
}
int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
{
int rc = SEPOL_ERR;
- char *endptr = NULL;
- uint64_t val;
if (int_node == NULL || int_node->data == NULL || integer == NULL) {
goto exit;
}
- errno = 0;
- val = strtoull(int_node->data, &endptr, base);
- if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
- rc = SEPOL_ERR;
+ rc = cil_string_to_uint64(int_node->data, integer, base);
+ if (rc != SEPOL_OK) {
goto exit;
}
- *integer = val;
-
return SEPOL_OK;
exit:
- cil_log(CIL_ERR, "Failed to create integer from string\n");
+ cil_log(CIL_ERR, "Failed to fill 64-bit integer\n");
return rc;
}
@@ -5665,10 +5668,6 @@ int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
goto exit;
}
- if (addr_node->cl_head != NULL || addr_node->next != NULL) {
- goto exit;
- }
-
if (strchr(addr_node->data, '.') != NULL) {
addr->family = AF_INET;
} else {
@@ -5696,7 +5695,7 @@ int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
if (curr == NULL) {
goto exit;
@@ -5757,7 +5756,7 @@ int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_bounds *bounds = NULL;
int rc = SEPOL_ERR;
@@ -5819,7 +5818,7 @@ int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *a
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -5888,7 +5887,7 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no
CIL_SYN_STRING | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -5909,6 +5908,11 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no
object = parse_current->next->next->data;
if (object == CIL_KEY_SOURCE) {
+ if (!parse_current->next->next->next) {
+ cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
range = parse_current->next->next->next->data;
if (range == CIL_KEY_LOW) {
def->object_range = CIL_DEFAULT_SOURCE_LOW;
@@ -5922,6 +5926,11 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no
goto exit;
}
} else if (object == CIL_KEY_TARGET) {
+ if (!parse_current->next->next->next) {
+ cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
range = parse_current->next->next->next->data;
if (range == CIL_KEY_LOW) {
def->object_range = CIL_DEFAULT_TARGET_LOW;
@@ -5974,7 +5983,7 @@ int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_n
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_handleunknown *unknown = NULL;
char *unknown_key;
@@ -6026,7 +6035,7 @@ int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_n
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_mls *mls = NULL;
if (parse_current == NULL || ast_node == NULL) {
@@ -6068,23 +6077,52 @@ void cil_destroy_mls(struct cil_mls *mls)
int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
- /* No need to check syntax, because this is auto generated */
+ int rc = SEPOL_ERR;
+ enum cil_syntax syntax[] = {
+ CIL_SYN_STRING,
+ CIL_SYN_STRING,
+ CIL_SYN_STRING,
+ CIL_SYN_STRING,
+ CIL_SYN_N_LISTS | CIL_SYN_END,
+ CIL_SYN_END
+ };
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_src_info *info = NULL;
- if (parse_current->next == NULL || parse_current->next->next == NULL) {
- cil_tree_log(parse_current, CIL_ERR, "Bad ");
- return SEPOL_ERR;
+ if (parse_current == NULL || ast_node == NULL) {
+ goto exit;
+ }
+
+ rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
cil_src_info_init(&info);
- info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE;
- info->path = parse_current->next->next->data;
+ info->kind = parse_current->next->data;
+ if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) {
+ cil_log(CIL_ERR, "Invalid src info kind\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ info->path = parse_current->next->next->next->data;
ast_node->data = info;
ast_node->flavor = CIL_SRC_INFO;
return SEPOL_OK;
+
+exit:
+ cil_tree_log(parse_current, CIL_ERR, "Bad src info");
+ cil_destroy_src_info(info);
+ return rc;
}
void cil_destroy_src_info(struct cil_src_info *info)
@@ -6092,78 +6130,55 @@ void cil_destroy_src_info(struct cil_src_info *info)
free(info);
}
-int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
+static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
{
- struct cil_args_build *args = extra_args;
- struct cil_db *db = args->db;
- struct cil_tree_node *ast_current = args->ast;
- struct cil_tree_node *tunif = args->tunif;
- struct cil_tree_node *in = args->in;
- struct cil_tree_node *macro = args->macro;
- struct cil_tree_node *optional = args->optional;
- struct cil_tree_node *boolif = args->boolif;
- struct cil_tree_node *ast_node = NULL;
- int rc = SEPOL_ERR;
-
- if (parse_current->parent->cl_head != parse_current) {
- /* ignore anything that isn't following a parenthesis */
- rc = SEPOL_OK;
- goto exit;
- } else if (parse_current->data == NULL) {
- /* the only time parenthesis can immediately following parenthesis is if
- * the parent is the root node */
- if (parse_current->parent->parent == NULL) {
- rc = SEPOL_OK;
- } else {
- cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
- }
- goto exit;
- }
-
- if (tunif != NULL) {
+ if (args->tunif != NULL) {
if (parse_current->data == CIL_KEY_TUNABLE) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found tunable");
- cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
- goto exit;
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data);
+ return SEPOL_ERR;
}
}
- if (in != NULL) {
- if (parse_current->data == CIL_KEY_IN) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
- cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
- goto exit;
+ if (args->in != NULL) {
+ struct cil_in *in_block = args->in->data;
+ if (parse_current->data == CIL_KEY_TUNABLE ||
+ parse_current->data == CIL_KEY_IN) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data);
+ return SEPOL_ERR;
+ }
+ if (in_block->is_after == CIL_TRUE) {
+ if (parse_current->data == CIL_KEY_BLOCKINHERIT ||
+ parse_current->data == CIL_KEY_BLOCKABSTRACT) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data);
+ return SEPOL_ERR;
+ }
}
}
- if (macro != NULL) {
+ if (args->macro != NULL) {
if (parse_current->data == CIL_KEY_TUNABLE ||
parse_current->data == CIL_KEY_IN ||
parse_current->data == CIL_KEY_BLOCK ||
parse_current->data == CIL_KEY_BLOCKINHERIT ||
parse_current->data == CIL_KEY_BLOCKABSTRACT ||
parse_current->data == CIL_KEY_MACRO) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data);
- goto exit;
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data);
+ return SEPOL_ERR;
}
}
- if (optional != NULL) {
+ if (args->optional != NULL) {
if (parse_current->data == CIL_KEY_TUNABLE ||
parse_current->data == CIL_KEY_IN ||
parse_current->data == CIL_KEY_BLOCK ||
parse_current->data == CIL_KEY_BLOCKABSTRACT ||
parse_current->data == CIL_KEY_MACRO) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optionals", (char *)parse_current->data);
- goto exit;
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data);
+ return SEPOL_ERR;
}
}
- if (boolif != NULL) {
+ if (args->boolif != NULL) {
if (parse_current->data != CIL_KEY_TUNABLEIF &&
parse_current->data != CIL_KEY_CALL &&
parse_current->data != CIL_KEY_CONDTRUE &&
@@ -6174,341 +6189,320 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
parse_current->data != CIL_KEY_TYPETRANSITION &&
parse_current->data != CIL_KEY_TYPECHANGE &&
parse_current->data != CIL_KEY_TYPEMEMBER) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
- if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
- cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n",
- (char*)parse_current->data);
+ if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
} else {
- cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n",
- (char*)parse_current->data);
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
}
- goto exit;
+ return SEPOL_ERR;
}
}
- cil_tree_node_init(&ast_node);
+ return SEPOL_OK;
+}
+
+static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent)
+{
+ struct cil_tree_node *new_ast_node = NULL;
+ int rc = SEPOL_ERR;
- ast_node->parent = ast_current;
- ast_node->line = parse_current->line;
- ast_node->hll_line = parse_current->hll_line;
+ cil_tree_node_init(&new_ast_node);
+ new_ast_node->parent = ast_parent;
+ new_ast_node->line = parse_current->line;
+ new_ast_node->hll_offset = parse_current->hll_offset;
if (parse_current->data == CIL_KEY_BLOCK) {
- rc = cil_gen_block(db, parse_current, ast_node, 0);
+ rc = cil_gen_block(db, parse_current, new_ast_node, 0);
} else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
- rc = cil_gen_blockinherit(db, parse_current, ast_node);
+ rc = cil_gen_blockinherit(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
- rc = cil_gen_blockabstract(db, parse_current, ast_node);
+ rc = cil_gen_blockabstract(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IN) {
- rc = cil_gen_in(db, parse_current, ast_node);
+ rc = cil_gen_in(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASS) {
- rc = cil_gen_class(db, parse_current, ast_node);
- // To avoid parsing list of perms again
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_class(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSORDER) {
- rc = cil_gen_classorder(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_classorder(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_MAP_CLASS) {
- rc = cil_gen_map_class(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_map_class(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
- rc = cil_gen_classmapping(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_classmapping(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
- rc = cil_gen_classpermission(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_classpermission(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
- rc = cil_gen_classpermissionset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_classpermissionset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_COMMON) {
- rc = cil_gen_common(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_common(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
- rc = cil_gen_classcommon(db, parse_current, ast_node);
+ rc = cil_gen_classcommon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SID) {
- rc = cil_gen_sid(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_sid(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
- rc = cil_gen_sidcontext(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_sidcontext(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SIDORDER) {
- rc = cil_gen_sidorder(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_sidorder(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USER) {
- rc = cil_gen_user(db, parse_current, ast_node);
+ rc = cil_gen_user(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
- rc = cil_gen_userattribute(db, parse_current, ast_node);
+ rc = cil_gen_userattribute(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
- rc = cil_gen_userattributeset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_userattributeset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERLEVEL) {
- rc = cil_gen_userlevel(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_userlevel(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERRANGE) {
- rc = cil_gen_userrange(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_userrange(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERBOUNDS) {
- rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER);
+ rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER);
} else if (parse_current->data == CIL_KEY_USERPREFIX) {
- rc = cil_gen_userprefix(db, parse_current, ast_node);
+ rc = cil_gen_userprefix(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SELINUXUSER) {
- rc = cil_gen_selinuxuser(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_selinuxuser(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
- rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPE) {
- rc = cil_gen_type(db, parse_current, ast_node);
+ rc = cil_gen_type(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
- rc = cil_gen_typeattribute(db, parse_current, ast_node);
+ rc = cil_gen_typeattribute(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
- rc = cil_gen_typeattributeset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_typeattributeset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
- rc = cil_gen_expandtypeattribute(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPEALIAS) {
- rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS);
+ rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS);
} else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
- rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL);
+ rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL);
} else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
- rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE);
+ rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE);
} else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
- rc = cil_gen_typepermissive(db, parse_current, ast_node);
+ rc = cil_gen_typepermissive(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
- rc = cil_gen_rangetransition(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_rangetransition(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLE) {
- rc = cil_gen_role(db, parse_current, ast_node);
+ rc = cil_gen_role(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERROLE) {
- rc = cil_gen_userrole(db, parse_current, ast_node);
+ rc = cil_gen_userrole(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLETYPE) {
- rc = cil_gen_roletype(db, parse_current, ast_node);
+ rc = cil_gen_roletype(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
- rc = cil_gen_roletransition(parse_current, ast_node);
+ rc = cil_gen_roletransition(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLEALLOW) {
- rc = cil_gen_roleallow(db, parse_current, ast_node);
+ rc = cil_gen_roleallow(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
- rc = cil_gen_roleattribute(db, parse_current, ast_node);
+ rc = cil_gen_roleattribute(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
- rc = cil_gen_roleattributeset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_roleattributeset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
- rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE);
+ rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE);
} else if (parse_current->data == CIL_KEY_BOOL) {
- rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE);
+ rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE);
} else if (parse_current->data == CIL_KEY_BOOLEANIF) {
- rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE);
+ rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE);
} else if(parse_current->data == CIL_KEY_TUNABLE) {
if (db->preserve_tunables) {
- rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE);
+ rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE);
} else {
- rc = cil_gen_tunable(db, parse_current, ast_node);
+ rc = cil_gen_tunable(db, parse_current, new_ast_node);
}
} else if (parse_current->data == CIL_KEY_TUNABLEIF) {
if (db->preserve_tunables) {
- rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE);
+ rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE);
} else {
- rc = cil_gen_tunif(db, parse_current, ast_node);
+ rc = cil_gen_tunif(db, parse_current, new_ast_node);
}
} else if (parse_current->data == CIL_KEY_CONDTRUE) {
- rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE);
+ rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE);
} else if (parse_current->data == CIL_KEY_CONDFALSE) {
- rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE);
+ rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE);
} else if (parse_current->data == CIL_KEY_ALLOW) {
- rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED);
- // So that the object and perms lists do not get parsed again
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
} else if (parse_current->data == CIL_KEY_AUDITALLOW) {
- rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
} else if (parse_current->data == CIL_KEY_DONTAUDIT) {
- rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
- rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
} else if (parse_current->data == CIL_KEY_ALLOWX) {
- rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
- rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
- rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
} else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
- rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
- rc = cil_gen_permissionx(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_permissionx(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
- rc = cil_gen_typetransition(db, parse_current, ast_node);
+ rc = cil_gen_typetransition(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPECHANGE) {
- rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE);
+ rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE);
} else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
- rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER);
+ rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER);
} else if (parse_current->data == CIL_KEY_SENSITIVITY) {
- rc = cil_gen_sensitivity(db, parse_current, ast_node);
+ rc = cil_gen_sensitivity(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SENSALIAS) {
- rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS);
+ rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS);
} else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
- rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL);
+ rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL);
} else if (parse_current->data == CIL_KEY_CATEGORY) {
- rc = cil_gen_category(db, parse_current, ast_node);
+ rc = cil_gen_category(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CATALIAS) {
- rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS);
+ rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS);
} else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
- rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL);
+ rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL);
} else if (parse_current->data == CIL_KEY_CATSET) {
- rc = cil_gen_catset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_catset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CATORDER) {
- rc = cil_gen_catorder(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_catorder(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
- rc = cil_gen_sensitivityorder(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_sensitivityorder(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SENSCAT) {
- rc = cil_gen_senscat(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_senscat(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_LEVEL) {
- rc = cil_gen_level(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_level(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_LEVELRANGE) {
- rc = cil_gen_levelrange(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_levelrange(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CONSTRAIN) {
- rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN);
} else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
- rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN);
} else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
- rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS);
} else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
- rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS);
} else if (parse_current->data == CIL_KEY_CONTEXT) {
- rc = cil_gen_context(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_context(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_FILECON) {
- rc = cil_gen_filecon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_filecon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IBPKEYCON) {
- rc = cil_gen_ibpkeycon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
- rc = cil_gen_ibendportcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_ibendportcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_PORTCON) {
- rc = cil_gen_portcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_portcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_NODECON) {
- rc = cil_gen_nodecon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_nodecon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_GENFSCON) {
- rc = cil_gen_genfscon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_genfscon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_NETIFCON) {
- rc = cil_gen_netifcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_netifcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_PIRQCON) {
- rc = cil_gen_pirqcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_pirqcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IOMEMCON) {
- rc = cil_gen_iomemcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_iomemcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IOPORTCON) {
- rc = cil_gen_ioportcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_ioportcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
- rc = cil_gen_pcidevicecon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_DEVICETREECON) {
- rc = cil_gen_devicetreecon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_devicetreecon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_FSUSE) {
- rc = cil_gen_fsuse(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_fsuse(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_MACRO) {
- rc = cil_gen_macro(db, parse_current, ast_node);
+ rc = cil_gen_macro(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CALL) {
- rc = cil_gen_call(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_call(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_POLICYCAP) {
- rc = cil_gen_policycap(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_policycap(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_OPTIONAL) {
- rc = cil_gen_optional(db, parse_current, ast_node);
+ rc = cil_gen_optional(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IPADDR) {
- rc = cil_gen_ipaddr(db, parse_current, ast_node);
+ rc = cil_gen_ipaddr(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
- rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER);
} else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
- rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE);
} else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
- rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE);
} else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
- rc = cil_gen_defaultrange(parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_defaultrange(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
- rc = cil_gen_handleunknown(parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_handleunknown(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_MLS) {
- rc = cil_gen_mls(parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_mls(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SRC_INFO) {
- rc = cil_gen_src_info(parse_current, ast_node);
+ rc = cil_gen_src_info(parse_current, new_ast_node);
} else {
cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
rc = SEPOL_ERR;
}
if (rc == SEPOL_OK) {
- if (ast_current->cl_head == NULL) {
- ast_current->cl_head = ast_node;
+ if (ast_parent->cl_head == NULL) {
+ ast_parent->cl_head = new_ast_node;
} else {
- ast_current->cl_tail->next = ast_node;
+ ast_parent->cl_tail->next = new_ast_node;
}
- ast_current->cl_tail = ast_node;
- ast_current = ast_node;
- args->ast = ast_current;
+ ast_parent->cl_tail = new_ast_node;
} else {
- cil_tree_node_destroy(&ast_node);
+ cil_tree_node_destroy(&new_ast_node);
+ new_ast_node = NULL;
}
-exit:
- return rc;
+ return new_ast_node;
}
-int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
+int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
{
struct cil_args_build *args = extra_args;
- struct cil_tree_node *ast = args->ast;
+ struct cil_tree_node *new_ast_node = NULL;
+ int rc = SEPOL_ERR;
- if (ast->flavor == CIL_TUNABLEIF) {
- args->tunif = ast;
+ if (parse_current->parent->cl_head != parse_current) {
+ /* ignore anything that isn't following a parenthesis */
+ return SEPOL_OK;
+ } else if (parse_current->data == NULL) {
+ /* the only time parenthesis can immediately following parenthesis is if
+ * the parent is the root node */
+ if (parse_current->parent->parent == NULL) {
+ return SEPOL_OK;
+ } else {
+ cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
+ return SEPOL_ERR;
+ }
}
- if (ast->flavor == CIL_IN) {
- args->in = ast;
+ rc = check_for_illegal_statement(parse_current, args);
+ if (rc != SEPOL_OK) {
+ return SEPOL_ERR;
}
- if (ast->flavor == CIL_MACRO) {
- args->macro = ast;
+ new_ast_node = parse_statement(args->db, parse_current, args->ast);
+ if (!new_ast_node) {
+ return SEPOL_ERR;
}
- if (ast->flavor == CIL_OPTIONAL) {
- args->optional = ast;
+ args->ast = new_ast_node;
+
+ if (parse_current->data != CIL_KEY_BLOCK &&
+ parse_current->data != CIL_KEY_IN &&
+ parse_current->data != CIL_KEY_TUNABLEIF &&
+ parse_current->data != CIL_KEY_BOOLEANIF &&
+ parse_current->data != CIL_KEY_CONDTRUE &&
+ parse_current->data != CIL_KEY_CONDFALSE &&
+ parse_current->data != CIL_KEY_MACRO &&
+ parse_current->data != CIL_KEY_OPTIONAL &&
+ parse_current->data != CIL_KEY_SRC_INFO) {
+ /* Skip anything that does not contain a list of policy statements */
+ *finished = CIL_TREE_SKIP_NEXT;
}
- if (ast->flavor == CIL_BOOLEANIF) {
+ return SEPOL_OK;
+}
+
+int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
+{
+ struct cil_args_build *args = extra_args;
+ struct cil_tree_node *ast = args->ast;
+
+ if (ast->flavor == CIL_TUNABLEIF) {
+ args->tunif = ast;
+ } else if (ast->flavor == CIL_IN) {
+ args->in = ast;
+ } else if (ast->flavor == CIL_MACRO) {
+ args->macro = ast;
+ } else if (ast->flavor == CIL_OPTIONAL) {
+ args->optional = ast;
+ } else if (ast->flavor == CIL_BOOLEANIF) {
args->boolif = ast;
}
diff --git a/libsepol/cil/src/cil_build_ast.h b/libsepol/cil/src/cil_build_ast.h
index 8153e51e3a971824dc5824281c1a3beff9aa0192..fd9053ce55cac66a0ee4aae243bed4023816e7ae 100644
--- a/libsepol/cil/src/cil_build_ast.h
+++ b/libsepol/cil/src/cil_build_ast.h
@@ -37,6 +37,8 @@
#include "cil_tree.h"
#include "cil_list.h"
+int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node);
+
int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor);
int cil_parse_to_list(struct cil_tree_node *parse_cl_head, struct cil_list *ast_cl, enum cil_flavor flavor);
diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c
index c9aada9db3489ea9d48d00b36470d5122aa2a202..2fad972c617bcfdbeb94b81eaf2316c0d0d7e477 100644
--- a/libsepol/cil/src/cil_copy_ast.c
+++ b/libsepol/cil/src/cil_copy_ast.c
@@ -40,8 +40,10 @@
#include "cil_copy_ast.h"
#include "cil_build_ast.h"
#include "cil_strpool.h"
+#include "cil_verify.h"
struct cil_args_copy {
+ struct cil_tree_node *orig_dest;
struct cil_tree_node *dest;
struct cil_db *db;
};
@@ -102,12 +104,19 @@ int cil_copy_block(__attribute__((unused)) struct cil_db *db, void *data, void *
struct cil_symtab_datum *datum = NULL;
cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
+ if (datum != NULL) {
+ if (FLAVOR(datum) != CIL_BLOCK) {
+ cil_tree_log(NODE(orig), CIL_ERR, "Block %s being copied", key);
+ cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum)));
+ return SEPOL_ERR;
+ }
+ cil_tree_log(NODE(orig), CIL_WARN, "Block %s being copied", key);
+ cil_tree_log(NODE(datum), CIL_WARN, " Previously declared");
+ *copy = datum;
+ } else {
struct cil_block *new;
cil_block_init(&new);
*copy = new;
- } else {
- *copy = datum;;
}
return SEPOL_OK;
@@ -581,20 +590,12 @@ int cil_copy_roleallow(__attribute__((unused)) struct cil_db *db, void *data, vo
return SEPOL_OK;
}
-int cil_copy_type(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
+int cil_copy_type(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
- struct cil_type *orig = data;
- char *key = orig->datum.name;
- struct cil_symtab_datum *datum = NULL;
+ struct cil_type *new;
- cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
- struct cil_type *new;
- cil_type_init(&new);
- *copy = new;
- } else {
- *copy = datum;
- }
+ cil_type_init(&new);
+ *copy = new;
return SEPOL_OK;
}
@@ -613,20 +614,12 @@ int cil_copy_typepermissive(__attribute__((unused)) struct cil_db *db, void *dat
return SEPOL_OK;
}
-int cil_copy_typeattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
+int cil_copy_typeattribute(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
- struct cil_typeattribute *orig = data;
- char *key = orig->datum.name;
- struct cil_symtab_datum *datum = NULL;
+ struct cil_typeattribute *new;
- cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
- struct cil_typeattribute *new;
- cil_typeattribute_init(&new);
- *copy = new;
- } else {
- *copy = datum;
- }
+ cil_typeattribute_init(&new);
+ *copy = new;
return SEPOL_OK;
}
@@ -1511,78 +1504,33 @@ int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void *
struct cil_symtab_datum *datum = NULL;
cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
+ if (datum != NULL) {
+ if (FLAVOR(datum) != CIL_MACRO) {
+ cil_tree_log(NODE(orig), CIL_ERR, "Macro %s being copied", key);
+ cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum)));
+ return SEPOL_ERR;
+ }
+ cil_tree_log(NODE(orig), CIL_WARN, "Skipping macro %s", key);
+ cil_tree_log(NODE(datum), CIL_WARN, " Previously declared");
+ *copy = NULL;
+ } else {
struct cil_macro *new;
cil_macro_init(&new);
if (orig->params != NULL) {
cil_copy_list(orig->params, &new->params);
}
-
*copy = new;
-
- } else {
- struct cil_list_item *curr_orig = NULL;
- struct cil_list_item *curr_new = NULL;
- struct cil_param *param_orig = NULL;
- struct cil_param *param_new = NULL;
-
- if (((struct cil_macro*)datum)->params != NULL) {
- curr_new = ((struct cil_macro*)datum)->params->head;
- }
-
- if (orig->params != NULL) {
- curr_orig = orig->params->head;
- }
-
- if (curr_orig != NULL && curr_new != NULL) {
- while (curr_orig != NULL) {
- if (curr_new == NULL) {
- goto exit;
- }
-
- param_orig = (struct cil_param*)curr_orig->data;
- param_new = (struct cil_param*)curr_new->data;
- if (param_orig->str != param_new->str) {
- goto exit;
- } else if (param_orig->flavor != param_new->flavor) {
- goto exit;
- }
-
- curr_orig = curr_orig->next;
- curr_new = curr_new->next;
- }
-
- if (curr_new != NULL) {
- goto exit;
- }
- } else if (!(curr_orig == NULL && curr_new == NULL)) {
- goto exit;
- }
-
- *copy = datum;
}
return SEPOL_OK;
-
-exit:
- cil_log(CIL_INFO, "cil_copy_macro: macro cannot be redefined\n");
- return SEPOL_ERR;
}
-int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
+int cil_copy_optional(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
- struct cil_optional *orig = data;
- char *key = orig->datum.name;
- struct cil_symtab_datum *datum = NULL;
+ struct cil_optional *new;
- cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
- struct cil_optional *new;
- cil_optional_init(&new);
- *copy = new;
- } else {
- *copy = datum;
- }
+ cil_optional_init(&new);
+ *copy = new;
return SEPOL_OK;
}
@@ -1740,7 +1688,8 @@ int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, voi
cil_src_info_init(&new);
- new->is_cil = orig->is_cil;
+ new->kind = orig->kind;
+ new->hll_line = orig->hll_line;
new->path = orig->path;
*copy = new;
@@ -1748,7 +1697,7 @@ int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, voi
return SEPOL_OK;
}
-int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) uint32_t *finished, void *extra_args)
+int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished, void *extra_args)
{
int rc = SEPOL_ERR;
struct cil_tree_node *parent = NULL;
@@ -1756,7 +1705,6 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
struct cil_db *db = NULL;
struct cil_args_copy *args = NULL;
struct cil_tree_node *namespace = NULL;
- struct cil_param *param = NULL;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
symtab_t *symtab = NULL;
void *data = NULL;
@@ -2054,15 +2002,33 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
rc = (*copy_func)(db, orig->data, &data, symtab);
if (rc == SEPOL_OK) {
+ if (orig->flavor == CIL_MACRO && data == NULL) {
+ /* Skipping macro re-declaration */
+ if (args->orig_dest->flavor != CIL_BLOCKINHERIT) {
+ cil_log(CIL_ERR, " Re-declaration of macro is only allowed when inheriting a block\n");
+ return SEPOL_ERR;
+ }
+ *finished = CIL_TREE_SKIP_HEAD;
+ return SEPOL_OK;
+ }
+
cil_tree_node_init(&new);
new->parent = parent;
new->line = orig->line;
- new->hll_line = orig->hll_line;
+ new->hll_offset = orig->hll_offset;
new->flavor = orig->flavor;
new->data = data;
- if (orig->flavor >= CIL_MIN_DECLARATIVE) {
+ if (orig->flavor == CIL_BLOCK && DATUM(data)->nodes->head != NULL) {
+ /* Duplicate block */
+ if (args->orig_dest->flavor != CIL_BLOCKINHERIT) {
+ cil_log(CIL_ERR, " Re-declaration of block is only allowed when inheriting a block\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ cil_list_append(DATUM(new->data)->nodes, CIL_NODE, new);
+ } else if (orig->flavor >= CIL_MIN_DECLARATIVE) {
/* Check the flavor of data if was found in the destination symtab */
if (DATUM(data)->nodes->head && FLAVOR(data) != orig->flavor) {
cil_tree_log(orig, CIL_ERR, "Incompatible flavor when trying to copy %s", DATUM(data)->name);
@@ -2071,7 +2037,18 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
rc = SEPOL_ERR;
goto exit;
}
- rc = cil_symtab_insert(symtab, ((struct cil_symtab_datum*)orig->data)->name, ((struct cil_symtab_datum*)data), new);
+
+ rc = cil_add_decl_to_symtab(db, symtab, DATUM(orig->data)->name, DATUM(data), new);
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ cil_symtab_datum_destroy(data);
+ free(data);
+ data = NULL;
+ rc = SEPOL_OK;
+ } else {
+ goto exit;
+ }
+ }
namespace = new;
while (namespace->flavor != CIL_MACRO && namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_ROOT) {
@@ -2079,21 +2056,9 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
}
if (namespace->flavor == CIL_MACRO) {
- struct cil_macro *macro = namespace->data;
- struct cil_list *param_list = macro->params;
- if (param_list != NULL) {
- struct cil_list_item *item;
- cil_list_for_each(item, param_list) {
- param = item->data;
- if (param->flavor == new->flavor) {
- if (param->str == ((struct cil_symtab_datum*)new->data)->name) {
- cil_tree_log(orig, CIL_ERR, "%s %s shadows a macro parameter", cil_node_to_string(new), ((struct cil_symtab_datum*)orig->data)->name);
- cil_tree_log(namespace, CIL_ERR, "Note: macro declaration");
- rc = SEPOL_ERR;
- goto exit;
- }
- }
- }
+ rc = cil_verify_decl_does_not_shadow_macro_parameter(namespace->data, orig, DATUM(orig->data)->name);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
}
}
@@ -2122,6 +2087,7 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
args->dest = new;
}
} else {
+ cil_tree_log(orig, CIL_ERR, "Problem copying %s node", cil_node_to_string(orig));
goto exit;
}
@@ -2154,12 +2120,13 @@ int cil_copy_ast(struct cil_db *db, struct cil_tree_node *orig, struct cil_tree_
int rc = SEPOL_ERR;
struct cil_args_copy extra_args;
+ extra_args.orig_dest = dest;
extra_args.dest = dest;
extra_args.db = db;
rc = cil_tree_walk(orig, __cil_copy_node_helper, NULL, __cil_copy_last_child_helper, &extra_args);
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc);
+ cil_tree_log(dest, CIL_ERR, "Failed to copy %s to %s", cil_node_to_string(orig), cil_node_to_string(dest));
goto exit;
}
diff --git a/libsepol/cil/src/cil_fqn.c b/libsepol/cil/src/cil_fqn.c
index 097222a83da9aa23740bca8ca896de7e4802ebe0..46db069b254a35b65e6039971557fed1b166c25b 100644
--- a/libsepol/cil/src/cil_fqn.c
+++ b/libsepol/cil/src/cil_fqn.c
@@ -78,12 +78,13 @@ static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, has
struct cil_tree_node *node = NODE(datum);
int i;
int rc = SEPOL_OK;
+ int newlen;
if (node->flavor != CIL_BLOCK) {
goto exit;
}
- int newlen = fqn_args->len + strlen(datum->name) + 1;
+ newlen = fqn_args->len + strlen(datum->name) + 1;
if (newlen >= CIL_MAX_NAME_LENGTH) {
cil_log(CIL_INFO, "Fully qualified name for block %s is too long\n", datum->name);
rc = SEPOL_ERR;
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index 9bdcbdd013c0e0af86b38d8ce0ddd5f09dcae4a3..6f1d3cb51fae7161637e282fa38c08da3222700f 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -48,16 +48,19 @@
#define CIL_MAX_NAME_LENGTH 2048
+#define CIL_DEGENERATE_INHERITANCE_DEPTH 10UL
+#define CIL_DEGENERATE_INHERITANCE_MINIMUM (0x01 << CIL_DEGENERATE_INHERITANCE_DEPTH)
+#define CIL_DEGENERATE_INHERITANCE_GROWTH 10UL
enum cil_pass {
CIL_PASS_INIT = 0,
CIL_PASS_TIF,
- CIL_PASS_IN,
+ CIL_PASS_IN_BEFORE,
CIL_PASS_BLKIN_LINK,
CIL_PASS_BLKIN_COPY,
CIL_PASS_BLKABS,
- CIL_PASS_MACRO,
+ CIL_PASS_IN_AFTER,
CIL_PASS_CALL1,
CIL_PASS_CALL2,
CIL_PASS_ALIAS1,
@@ -156,6 +159,8 @@ extern char *CIL_KEY_HANDLEUNKNOWN_DENY;
extern char *CIL_KEY_HANDLEUNKNOWN_REJECT;
extern char *CIL_KEY_MACRO;
extern char *CIL_KEY_IN;
+extern char *CIL_KEY_IN_BEFORE;
+extern char *CIL_KEY_IN_AFTER;
extern char *CIL_KEY_MLS;
extern char *CIL_KEY_DEFAULTRANGE;
extern char *CIL_KEY_BLOCKINHERIT;
@@ -234,7 +239,9 @@ extern char *CIL_KEY_IOCTL;
extern char *CIL_KEY_UNORDERED;
extern char *CIL_KEY_SRC_INFO;
extern char *CIL_KEY_SRC_CIL;
-extern char *CIL_KEY_SRC_HLL;
+extern char *CIL_KEY_SRC_HLL_LMS;
+extern char *CIL_KEY_SRC_HLL_LMX;
+extern char *CIL_KEY_SRC_HLL_LME;
/*
Symbol Table Array Indices
@@ -273,7 +280,7 @@ enum cil_sym_array {
CIL_SYM_ARRAY_NUM
};
-extern int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM];
+extern const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM];
#define CIL_CLASS_SYM_SIZE 256
#define CIL_PERMS_PER_CLASS (sizeof(sepol_access_vector_t) * 8)
@@ -319,6 +326,7 @@ struct cil_db {
int handle_unknown;
int mls;
int multiple_decls;
+ int qualified_names;
int target_platform;
int policy_version;
};
@@ -352,12 +360,12 @@ struct cil_blockabstract {
struct cil_in {
symtab_t symtab[CIL_SYM_NUM];
+ int is_after;
char *block_str;
};
struct cil_optional {
struct cil_symtab_datum datum;
- int enabled;
};
struct cil_perm {
@@ -961,7 +969,8 @@ struct cil_mls {
};
struct cil_src_info {
- int is_cil;
+ char *kind;
+ uint32_t hll_line;
char *path;
};
@@ -980,10 +989,12 @@ int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size);
int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size);
int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size);
-void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM]);
+void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM]);
void cil_symtab_array_destroy(symtab_t symtab[]);
void cil_destroy_ast_symtabs(struct cil_tree_node *root);
int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_sym_index sym_index);
+int cil_string_to_uint32(const char *string, uint32_t *value, int base);
+int cil_string_to_uint64(const char *string, uint64_t *value, int base);
void cil_sort_init(struct cil_sort **sort);
void cil_sort_destroy(struct cil_sort **sort);
diff --git a/libsepol/cil/src/cil_lexer.l b/libsepol/cil/src/cil_lexer.l
index e28c33ecb9f136e3b72ed802e9c25c2ddf1d3243..8bf2b6e7765a389e90954eca3e859730af032612 100644
--- a/libsepol/cil/src/cil_lexer.l
+++ b/libsepol/cil/src/cil_lexer.l
@@ -49,7 +49,7 @@ spec_char [\[\]\.\@\=\/\*\-\_\$\%\+\-\!\|\&\^\:\~\`\#\{\}\'\<\>\?\,]
symbol ({digit}|{alpha}|{spec_char})+
white [ \t]
newline [\n\r]
-qstring \"[^"\n]*\"
+qstring \"[^"\n\0]*\"
hll_lm ^;;\*
comment ;
diff --git a/libsepol/cil/src/cil_list.c b/libsepol/cil/src/cil_list.c
index 4e7843cb01ef79b01979cc5b3bc07f7314ad0bc6..8a426f1f5950e9aea54e1d8e8f306e3e0d030ff0 100644
--- a/libsepol/cil/src/cil_list.c
+++ b/libsepol/cil/src/cil_list.c
@@ -55,15 +55,16 @@ void cil_list_init(struct cil_list **list, enum cil_flavor flavor)
void cil_list_destroy(struct cil_list **list, unsigned destroy_data)
{
+ struct cil_list_item *item;
+
if (*list == NULL) {
return;
}
- struct cil_list_item *item = (*list)->head;
- struct cil_list_item *next = NULL;
+ item = (*list)->head;
while (item != NULL)
{
- next = item->next;
+ struct cil_list_item *next = item->next;
if (item->flavor == CIL_LIST) {
cil_list_destroy((struct cil_list**)&(item->data), destroy_data);
free(item);
diff --git a/libsepol/cil/src/cil_parser.c b/libsepol/cil/src/cil_parser.c
index a93062180ff88363cc7c85b2e9ba26077dbe585e..5375d49a104b3e70d99794a91a666a5bc1fa3cac 100644
--- a/libsepol/cil/src/cil_parser.c
+++ b/libsepol/cil/src/cil_parser.c
@@ -42,50 +42,44 @@
#include "cil_strpool.h"
#include "cil_stack.h"
-char *CIL_KEY_HLL_LMS;
-char *CIL_KEY_HLL_LMX;
-char *CIL_KEY_HLL_LME;
+#define CIL_PARSER_MAX_EXPR_DEPTH (0x1 << 12)
struct hll_info {
- uint32_t hll_lineno;
+ uint32_t hll_offset;
uint32_t hll_expand;
};
-static void push_hll_info(struct cil_stack *stack, uint32_t hll_lineno, uint32_t hll_expand)
+static void push_hll_info(struct cil_stack *stack, uint32_t hll_offset, uint32_t hll_expand)
{
struct hll_info *new = cil_malloc(sizeof(*new));
- new->hll_lineno = hll_lineno;
+ new->hll_offset = hll_offset;
new->hll_expand = hll_expand;
cil_stack_push(stack, CIL_NONE, new);
}
-static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_lineno, uint32_t *hll_expand)
+static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_offset, uint32_t *hll_expand)
{
struct cil_stack_item *curr = cil_stack_pop(stack);
- struct cil_stack_item *prev = cil_stack_peek(stack);
- struct hll_info *old;
+ struct hll_info *info;
- free(curr->data);
-
- if (!prev) {
- *hll_lineno = 0;
- *hll_expand = 0;
- } else {
- old = prev->data;
- *hll_lineno = old->hll_lineno;
- *hll_expand = old->hll_expand;
+ if (!curr) {
+ return;
}
+ info = curr->data;
+ *hll_expand = info->hll_expand;
+ *hll_offset = info->hll_offset;
+ free(curr->data);
}
-static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_line, void *value)
+static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_offset, void *value)
{
cil_tree_node_init(node);
(*node)->parent = current;
(*node)->flavor = CIL_NODE;
(*node)->line = line;
- (*node)->hll_line = hll_line;
+ (*node)->hll_offset = hll_offset;
(*node)->data = value;
}
@@ -99,64 +93,67 @@ static void insert_node(struct cil_tree_node *node, struct cil_tree_node *curren
current->cl_tail = node;
}
-static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno, uint32_t *hll_expand, struct cil_stack *stack, char *path)
+static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_offset, uint32_t *hll_expand, struct cil_stack *stack, char *path)
{
char *hll_type;
struct cil_tree_node *node;
struct token tok;
- char *hll_file;
- char *end = NULL;
- unsigned long val;
+ uint32_t prev_hll_expand, prev_hll_offset;
cil_lexer_next(&tok);
+ if (tok.type != SYMBOL) {
+ cil_log(CIL_ERR, "Invalid line mark syntax\n");
+ goto exit;
+ }
hll_type = cil_strpool_add(tok.value);
- if (hll_type == CIL_KEY_HLL_LME) {
+ if (hll_type != CIL_KEY_SRC_HLL_LME && hll_type != CIL_KEY_SRC_HLL_LMS && hll_type != CIL_KEY_SRC_HLL_LMX) {
+ cil_log(CIL_ERR, "Invalid line mark syntax\n");
+ goto exit;
+ }
+ if (hll_type == CIL_KEY_SRC_HLL_LME) {
if (cil_stack_is_empty(stack)) {
cil_log(CIL_ERR, "Line mark end without start\n");
goto exit;
}
- pop_hll_info(stack, hll_lineno, hll_expand);
+ prev_hll_expand = *hll_expand;
+ prev_hll_offset = *hll_offset;
+ pop_hll_info(stack, hll_offset, hll_expand);
+ if (!*hll_expand) {
+ /* This is needed if not going back to an lmx section. */
+ *hll_offset = prev_hll_offset;
+ }
+ if (prev_hll_expand && !*hll_expand) {
+ /* This is needed to count the lme at the end of an lmx section
+ * within an lms section (or within no hll section).
+ */
+ (*hll_offset)++;
+ }
*current = (*current)->parent;
} else {
- create_node(&node, *current, tok.line, *hll_lineno, NULL);
+ push_hll_info(stack, *hll_offset, *hll_expand);
+ if (cil_stack_number_of_items(stack) > CIL_PARSER_MAX_EXPR_DEPTH) {
+ cil_log(CIL_ERR, "Number of active line marks exceeds limit of %d\n", CIL_PARSER_MAX_EXPR_DEPTH);
+ goto exit;
+ }
+
+ create_node(&node, *current, tok.line, *hll_offset, NULL);
insert_node(node, *current);
*current = node;
- create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_INFO);
+ create_node(&node, *current, tok.line, *hll_offset, CIL_KEY_SRC_INFO);
insert_node(node, *current);
- create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_HLL);
+ create_node(&node, *current, tok.line, *hll_offset, hll_type);
insert_node(node, *current);
- if (hll_type == CIL_KEY_HLL_LMS) {
- *hll_expand = 0;
- } else if (hll_type == CIL_KEY_HLL_LMX) {
- *hll_expand = 1;
- } else {
- cil_log(CIL_ERR, "Invalid line mark syntax\n");
- goto exit;
- }
-
cil_lexer_next(&tok);
if (tok.type != SYMBOL) {
cil_log(CIL_ERR, "Invalid line mark syntax\n");
goto exit;
}
- val = strtoul(tok.value, &end, 10);
- if (errno == ERANGE || *end != '\0') {
- cil_log(CIL_ERR, "Problem parsing line number for line mark\n");
- goto exit;
- }
-#if ULONG_MAX > UINT32_MAX
- if (val > UINT32_MAX) {
- cil_log(CIL_ERR, "Line mark line number > UINT32_MAX\n");
- goto exit;
- }
-#endif
- *hll_lineno = val;
-
- push_hll_info(stack, *hll_lineno, *hll_expand);
+ create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value));
+ insert_node(node, *current);
cil_lexer_next(&tok);
if (tok.type != SYMBOL && tok.type != QSTRING) {
@@ -169,10 +166,10 @@ static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno
tok.value = tok.value+1;
}
- hll_file = cil_strpool_add(tok.value);
-
- create_node(&node, *current, tok.line, *hll_lineno, hll_file);
+ create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value));
insert_node(node, *current);
+
+ *hll_expand = (hll_type == CIL_KEY_SRC_HLL_LMX) ? 1 : 0;
}
cil_lexer_next(&tok);
@@ -181,6 +178,11 @@ static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno
goto exit;
}
+ if (!*hll_expand) {
+ /* Need to increment because of the NEWLINE */
+ (*hll_offset)++;
+ }
+
return SEPOL_OK;
exit:
@@ -202,6 +204,9 @@ static void add_cil_path(struct cil_tree_node **current, char *path)
create_node(&node, *current, 0, 0, CIL_KEY_SRC_CIL);
insert_node(node, *current);
+ create_node(&node, *current, 0, 0, cil_strpool_add("1"));
+ insert_node(node, *current);
+
create_node(&node, *current, 0, 0, path);
insert_node(node, *current);
}
@@ -216,15 +221,11 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
struct cil_tree_node *current = NULL;
char *path = cil_strpool_add(_path);
struct cil_stack *stack;
- uint32_t hll_lineno = 0;
+ uint32_t hll_offset = 1;
uint32_t hll_expand = 0;
struct token tok;
int rc = SEPOL_OK;
- CIL_KEY_HLL_LMS = cil_strpool_add("lms");
- CIL_KEY_HLL_LMX = cil_strpool_add("lmx");
- CIL_KEY_HLL_LME = cil_strpool_add("lme");
-
cil_stack_init(&stack);
cil_lexer_setup(buffer, size);
@@ -238,15 +239,18 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
cil_lexer_next(&tok);
switch (tok.type) {
case HLL_LINEMARK:
- rc = add_hll_linemark(¤t, &hll_lineno, &hll_expand, stack, path);
+ rc = add_hll_linemark(¤t, &hll_offset, &hll_expand, stack, path);
if (rc != SEPOL_OK) {
goto exit;
}
break;
case OPAREN:
paren_count++;
-
- create_node(&node, current, tok.line, hll_lineno, NULL);
+ if (paren_count > CIL_PARSER_MAX_EXPR_DEPTH) {
+ cil_log(CIL_ERR, "Number of open parenthesis exceeds limit of %d at line %d of %s\n", CIL_PARSER_MAX_EXPR_DEPTH, tok.line, path);
+ goto exit;
+ }
+ create_node(&node, current, tok.line, hll_offset, NULL);
insert_node(node, current);
current = node;
break;
@@ -268,12 +272,12 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
goto exit;
}
- create_node(&node, current, tok.line, hll_lineno, cil_strpool_add(tok.value));
+ create_node(&node, current, tok.line, hll_offset, cil_strpool_add(tok.value));
insert_node(node, current);
break;
case NEWLINE :
if (!hll_expand) {
- hll_lineno++;
+ hll_offset++;
}
break;
case COMMENT:
@@ -281,7 +285,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
cil_lexer_next(&tok);
}
if (!hll_expand) {
- hll_lineno++;
+ hll_offset++;
}
if (tok.type != END_OF_FILE) {
break;
@@ -318,7 +322,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree *
exit:
while (!cil_stack_is_empty(stack)) {
- pop_hll_info(stack, &hll_lineno, &hll_expand);
+ pop_hll_info(stack, &hll_offset, &hll_expand);
}
cil_lexer_destroy();
cil_stack_destroy(&stack);
diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
index a55df1ea5bb01b7f90f2ba70e62a643b9906e0db..7e2c2b9a85c3545630b4c5554a2795e11c085605 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -27,6 +27,7 @@
* either expressed or implied, of Tresys Technology, LLC.
*/
+#include
#include
#include
#include
@@ -50,6 +51,12 @@
#define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/src/module_to_cil.c */
#define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/src/module_to_cil.c */
+struct fc_data {
+ unsigned int meta;
+ size_t stem_len;
+ size_t str_len;
+};
+
static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
@@ -156,9 +163,9 @@ static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
return CIL_TRUE;
}
-void cil_post_fc_fill_data(struct fc_data *fc, char *path)
+static void cil_post_fc_fill_data(struct fc_data *fc, const char *path)
{
- int c = 0;
+ size_t c = 0;
fc->meta = 0;
fc->stem_len = 0;
fc->str_len = 0;
@@ -179,6 +186,13 @@ void cil_post_fc_fill_data(struct fc_data *fc, char *path)
break;
case '\\':
c++;
+ if (path[c] == '\0') {
+ if (!fc->meta) {
+ fc->stem_len++;
+ }
+ fc->str_len++;
+ return;
+ }
/* FALLTHRU */
default:
if (!fc->meta) {
@@ -199,8 +213,8 @@ int cil_post_filecon_compare(const void *a, const void *b)
struct fc_data *a_data = cil_malloc(sizeof(*a_data));
struct fc_data *b_data = cil_malloc(sizeof(*b_data));
char *a_path = cil_malloc(strlen(a_filecon->path_str) + 1);
- a_path[0] = '\0';
char *b_path = cil_malloc(strlen(b_filecon->path_str) + 1);
+ a_path[0] = '\0';
b_path[0] = '\0';
strcat(a_path, a_filecon->path_str);
strcat(b_path, b_filecon->path_str);
@@ -1480,6 +1494,10 @@ static void __mark_neverallow_attrs(struct cil_list *expr_list)
{
struct cil_list_item *curr;
+ if (!expr_list) {
+ return;
+ }
+
cil_list_for_each(curr, expr_list) {
if (curr->flavor == CIL_DATUM) {
if (FLAVOR(curr->data) == CIL_TYPEATTRIBUTE) {
@@ -2123,6 +2141,10 @@ static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db
}
} else { /* MAP */
struct cil_list_item *i = NULL;
+ rc = __evaluate_classperms(cp, db);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
cil_list_for_each(i, cp->perms) {
struct cil_perm *cmp = i->data;
rc = __evaluate_classperms_list(cmp->classperms, db);
diff --git a/libsepol/cil/src/cil_post.h b/libsepol/cil/src/cil_post.h
index 3d5415486b7719f155dd39d82bf40b4d532a0f6e..b1d2206f9ef6eb2fca19632d67119ba84302f25c 100644
--- a/libsepol/cil/src/cil_post.h
+++ b/libsepol/cil/src/cil_post.h
@@ -30,13 +30,6 @@
#ifndef CIL_POST_H_
#define CIL_POST_H_
-struct fc_data {
- int meta;
- int stem_len;
- int str_len;
-};
-
-void cil_post_fc_fill_data(struct fc_data *fc, char *path);
int cil_post_filecon_compare(const void *a, const void *b);
int cil_post_ibpkeycon_compare(const void *a, const void *b);
int cil_post_portcon_compare(const void *a, const void *b);
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 89f91e568d0ee846efb4e188a56650745ad54f30..0ba075c840eee60c5f3facdc7bf52cc5881a42fc 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -45,6 +45,7 @@ static inline void cil_reset_classperms(struct cil_classperms *cp)
return;
}
+ cp->class = NULL;
cil_list_destroy(&cp->perms, CIL_FALSE);
}
@@ -59,7 +60,15 @@ static void cil_reset_classpermission(struct cil_classpermission *cp)
static void cil_reset_classperms_set(struct cil_classperms_set *cp_set)
{
- cil_reset_classpermission(cp_set->set);
+ if (cp_set == NULL || cp_set->set == NULL) {
+ return;
+ }
+
+ if (cp_set->set->datum.name == NULL) {
+ cil_reset_classperms_list(cp_set->set->classperms);
+ }
+
+ cp_set->set = NULL;
}
static inline void cil_reset_classperms_list(struct cil_list *cp_list)
@@ -131,8 +140,11 @@ static void cil_reset_userattributeset(struct cil_userattributeset *uas)
static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser)
{
+ selinuxuser->user = NULL;
if (selinuxuser->range_str == NULL) {
cil_reset_levelrange(selinuxuser->range);
+ } else {
+ selinuxuser->range = NULL;
}
}
@@ -196,6 +208,11 @@ static void cil_reset_typeattributeset(struct cil_typeattributeset *tas)
cil_list_destroy(&tas->datum_expr, CIL_FALSE);
}
+static void cil_reset_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
+{
+ cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
+}
+
static void cil_reset_avrule(struct cil_avrule *rule)
{
cil_reset_classperms_list(rule->perms.classperms);
@@ -205,6 +222,8 @@ static void cil_reset_rangetransition(struct cil_rangetransition *rangetrans)
{
if (rangetrans->range_str == NULL) {
cil_reset_levelrange(rangetrans->range);
+ } else {
+ rangetrans->range = NULL;
}
}
@@ -242,6 +261,7 @@ static void cil_reset_catset(struct cil_catset *catset)
static inline void cil_reset_level(struct cil_level *level)
{
+ level->sens = NULL;
cil_reset_cats(level->cats);
}
@@ -249,10 +269,14 @@ static inline void cil_reset_levelrange(struct cil_levelrange *levelrange)
{
if (levelrange->low_str == NULL) {
cil_reset_level(levelrange->low);
+ } else {
+ levelrange->low = NULL;
}
if (levelrange->high_str == NULL) {
cil_reset_level(levelrange->high);
+ } else {
+ levelrange->high = NULL;
}
}
@@ -260,6 +284,8 @@ static inline void cil_reset_userlevel(struct cil_userlevel *userlevel)
{
if (userlevel->level_str == NULL) {
cil_reset_level(userlevel->level);
+ } else {
+ userlevel->level = NULL;
}
}
@@ -267,13 +293,20 @@ static inline void cil_reset_userrange(struct cil_userrange *userrange)
{
if (userrange->range_str == NULL) {
cil_reset_levelrange(userrange->range);
+ } else {
+ userrange->range = NULL;
}
}
static inline void cil_reset_context(struct cil_context *context)
{
+ if (!context) {
+ return;
+ }
if (context->range_str == NULL) {
cil_reset_levelrange(context->range);
+ } else {
+ context->range = NULL;
}
}
@@ -281,26 +314,35 @@ static void cil_reset_sidcontext(struct cil_sidcontext *sidcontext)
{
if (sidcontext->context_str == NULL) {
cil_reset_context(sidcontext->context);
+ } else {
+ sidcontext->context = NULL;
}
}
static void cil_reset_filecon(struct cil_filecon *filecon)
{
- if (filecon->context_str == NULL && filecon->context != NULL) {
+ if (filecon->context_str == NULL) {
cil_reset_context(filecon->context);
+ } else {
+ filecon->context = NULL;
}
}
static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
{
- if (!ibpkeycon->context_str)
+ if (ibpkeycon->context_str == NULL) {
cil_reset_context(ibpkeycon->context);
+ } else {
+ ibpkeycon->context = NULL;
+ }
}
static void cil_reset_portcon(struct cil_portcon *portcon)
{
if (portcon->context_str == NULL) {
cil_reset_context(portcon->context);
+ } else {
+ portcon->context = NULL;
}
}
@@ -308,6 +350,8 @@ static void cil_reset_nodecon(struct cil_nodecon *nodecon)
{
if (nodecon->context_str == NULL) {
cil_reset_context(nodecon->context);
+ } else {
+ nodecon->context = NULL;
}
}
@@ -315,6 +359,8 @@ static void cil_reset_genfscon(struct cil_genfscon *genfscon)
{
if (genfscon->context_str == NULL) {
cil_reset_context(genfscon->context);
+ } else {
+ genfscon->context = NULL;
}
}
@@ -322,17 +368,23 @@ static void cil_reset_netifcon(struct cil_netifcon *netifcon)
{
if (netifcon->if_context_str == NULL) {
cil_reset_context(netifcon->if_context);
+ } else {
+ netifcon->if_context = NULL;
}
if (netifcon->packet_context_str == NULL) {
cil_reset_context(netifcon->packet_context);
+ } else {
+ netifcon->packet_context = NULL;
}
}
static void cil_reset_ibendportcon(struct cil_ibendportcon *ibendportcon)
{
- if (!ibendportcon->context_str) {
+ if (ibendportcon->context_str == NULL) {
cil_reset_context(ibendportcon->context);
+ } else {
+ ibendportcon->context = NULL;
}
}
@@ -340,6 +392,8 @@ static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon)
{
if (pirqcon->context_str == NULL) {
cil_reset_context(pirqcon->context);
+ } else {
+ pirqcon->context = NULL;
}
}
@@ -347,6 +401,8 @@ static void cil_reset_iomemcon(struct cil_iomemcon *iomemcon)
{
if (iomemcon->context_str == NULL) {
cil_reset_context(iomemcon->context);
+ } else {
+ iomemcon->context = NULL;
}
}
@@ -354,6 +410,8 @@ static void cil_reset_ioportcon(struct cil_ioportcon *ioportcon)
{
if (ioportcon->context_str == NULL) {
cil_reset_context(ioportcon->context);
+ } else {
+ ioportcon->context = NULL;
}
}
@@ -361,6 +419,8 @@ static void cil_reset_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
{
if (pcidevicecon->context_str == NULL) {
cil_reset_context(pcidevicecon->context);
+ } else {
+ pcidevicecon->context = NULL;
}
}
@@ -368,6 +428,8 @@ static void cil_reset_devicetreecon(struct cil_devicetreecon *devicetreecon)
{
if (devicetreecon->context_str == NULL) {
cil_reset_context(devicetreecon->context);
+ } else {
+ devicetreecon->context = NULL;
}
}
@@ -375,6 +437,8 @@ static void cil_reset_fsuse(struct cil_fsuse *fsuse)
{
if (fsuse->context_str == NULL) {
cil_reset_context(fsuse->context);
+ } else {
+ fsuse->context = NULL;
}
}
@@ -472,6 +536,9 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32
case CIL_TYPEATTRIBUTESET:
cil_reset_typeattributeset(node->data);
break;
+ case CIL_EXPANDTYPEATTRIBUTE:
+ cil_reset_expandtypeattribute(node->data);
+ break;
case CIL_RANGETRANSITION:
cil_reset_rangetransition(node->data);
break;
@@ -571,7 +638,6 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32
case CIL_CLASSORDER:
case CIL_CATORDER:
case CIL_SENSITIVITYORDER:
- case CIL_EXPANDTYPEATTRIBUTE:
break; /* Nothing to reset */
default:
break;
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index b5edfc04fd45d41fe17b1e14c96349e1ad9f9c43..e97a9f46908d188626e532fa7f670efa6e2c7a9a 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -46,22 +46,25 @@
#include "cil_verify.h"
#include "cil_strpool.h"
#include "cil_symtab.h"
+#include "cil_stack.h"
struct cil_args_resolve {
struct cil_db *db;
enum cil_pass pass;
uint32_t *changed;
- struct cil_list *disabled_optionals;
+ struct cil_list *to_destroy;
struct cil_tree_node *block;
struct cil_tree_node *macro;
struct cil_tree_node *optional;
+ struct cil_tree_node *disabled_optional;
struct cil_tree_node *boolif;
struct cil_list *sidorder_lists;
struct cil_list *classorder_lists;
struct cil_list *unordered_classorder_lists;
struct cil_list *catorder_lists;
struct cil_list *sensitivityorder_lists;
- struct cil_list *in_list;
+ struct cil_list *in_list_before;
+ struct cil_list *in_list_after;
};
static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node)
@@ -82,10 +85,11 @@ static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key,
} else if (parent->flavor == CIL_MACRO) {
macro = parent->data;
}
- if (macro != NULL) {
+ if (macro != NULL && macro->params != NULL) {
struct cil_list_item *item;
cil_list_for_each(item, macro->params) {
- if (((struct cil_param*)item->data)->str == key) {
+ struct cil_param *param = item->data;
+ if (param->flavor == CIL_NAME && param->str == key) {
return NULL;
}
}
@@ -158,6 +162,10 @@ int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms
symtab_t *common_symtab = NULL;
struct cil_class *class;
+ if (cp->class) {
+ return SEPOL_OK;
+ }
+
rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, extra_args, &datum);
if (rc != SEPOL_OK) {
goto exit;
@@ -438,11 +446,6 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrtypes->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_TYPEATTRIBUTE);
}
@@ -772,6 +775,7 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args)
class->num_perms += common->num_perms;
if (class->num_perms > CIL_PERMS_PER_CLASS) {
cil_tree_log(current, CIL_ERR, "Too many permissions in class '%s' when including common permissions", class->datum.name);
+ rc = SEPOL_ERR;
goto exit;
}
@@ -1088,7 +1092,6 @@ int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args)
node = NODE(result_datum);
if (node->flavor != CIL_ROLE) {
rc = SEPOL_ERR;
- printf("%i\n", node->flavor);
cil_log(CIL_ERR, "roletransition must result in a role, but %s is a %s\n", roletrans->result_str, cil_node_to_string(node));
goto exit;
}
@@ -1151,11 +1154,6 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrroles->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_ROLEATTRIBUTE);
}
@@ -1485,6 +1483,12 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ if (FLAVOR(datum) != CIL_CLASS) {
+ cil_log(CIL_ERR, "%s is not a class. Only classes are allowed in classorder statements\n", datum->name);
+ rc = SEPOL_ERR;
goto exit;
}
cil_list_append(new, CIL_CLASS, datum);
@@ -1525,6 +1529,12 @@ int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args)
cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data);
goto exit;
}
+ if (FLAVOR(datum) != CIL_SID) {
+ cil_log(CIL_ERR, "%s is not a sid. Only sids are allowed in sidorder statements\n", datum->name);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
cil_list_append(new, CIL_SID, datum);
}
@@ -1613,7 +1623,12 @@ int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args
cil_list_for_each(curr, sensorder->sens_list_str) {
rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, extra_args, &datum);
if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to resolve sensitivty %s in sensitivityorder\n", (char *)curr->data);
+ cil_log(CIL_ERR, "Failed to resolve sensitivity %s in sensitivityorder\n", (char *)curr->data);
+ goto exit;
+ }
+ if (FLAVOR(datum) != CIL_SENS) {
+ cil_log(CIL_ERR, "%s is not a sensitivity. Only sensitivities are allowed in sensitivityorder statements\n", datum->name);
+ rc = SEPOL_ERR;
goto exit;
}
cil_list_append(new, CIL_SENS, datum);
@@ -1649,21 +1664,7 @@ exit:
int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args)
{
- int rc = SEPOL_ERR;
-
- rc = cil_resolve_cats(current, catset->cats, extra_args);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
- rc = cil_verify_no_self_reference((struct cil_symtab_datum *)catset, catset->cats->datum_expr);
- if (rc != SEPOL_OK) {
- cil_list_destroy(&catset->cats->datum_expr, CIL_FALSE);
- goto exit;
- }
-
-exit:
- return rc;
+ return cil_resolve_cats(current, catset->cats, extra_args);
}
int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args)
@@ -1703,6 +1704,10 @@ int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, vo
struct cil_symtab_datum *sens_datum = NULL;
int rc = SEPOL_ERR;
+ if (level->sens) {
+ return SEPOL_OK;
+ }
+
rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, extra_args, &sens_datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to find sensitivity\n");
@@ -2338,77 +2343,6 @@ exit:
return rc;
}
-void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node)
-{
- struct cil_list *trace = NULL;
- struct cil_list_item *item = NULL;
- struct cil_tree_node *curr = NULL;
-
- cil_list_init(&trace, CIL_NODE);
-
- for (curr = bi_node; curr != terminating_node; curr = curr->parent) {
- if (curr->flavor == CIL_BLOCK) {
- cil_list_prepend(trace, CIL_NODE, curr);
- } else if (curr->flavor == CIL_BLOCKINHERIT) {
- if (curr != bi_node) {
- cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_blockinherit *)curr->data)->block));
- }
- cil_list_prepend(trace, CIL_NODE, curr);
- } else {
- cil_list_prepend(trace, CIL_NODE, curr);
- }
- }
- cil_list_prepend(trace, CIL_NODE, terminating_node);
-
- cil_list_for_each(item, trace) {
- curr = item->data;
- if (curr->flavor == CIL_BLOCK) {
- cil_tree_log(curr, CIL_ERR, "block %s", DATUM(curr->data)->name);
- } else if (curr->flavor == CIL_BLOCKINHERIT) {
- cil_tree_log(curr, CIL_ERR, "blockinherit %s", ((struct cil_blockinherit *)curr->data)->block_str);
- } else if (curr->flavor == CIL_OPTIONAL) {
- cil_tree_log(curr, CIL_ERR, "optional %s", DATUM(curr->data)->name);
- } else {
- cil_tree_log(curr, CIL_ERR, "%s", cil_node_to_string(curr));
- }
- }
-
- cil_list_destroy(&trace, CIL_FALSE);
-}
-
-int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node)
-{
- struct cil_tree_node *curr = NULL;
- struct cil_blockinherit *bi = NULL;
- struct cil_block *block = NULL;
- int rc = SEPOL_ERR;
-
- bi = bi_node->data;
-
- for (curr = bi_node->parent; curr != NULL; curr = curr->parent) {
- if (curr->flavor != CIL_BLOCK) {
- continue;
- }
-
- block = curr->data;
-
- if (block != bi->block) {
- continue;
- }
-
- cil_log(CIL_ERR, "Recursive blockinherit found:\n");
- cil_print_recursive_blockinherit(bi_node, curr);
-
- rc = SEPOL_ERR;
- goto exit;
- }
-
- rc = SEPOL_OK;
-
-exit:
- return rc;
-}
-
int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args)
{
struct cil_block *block = current->data;
@@ -2432,11 +2366,6 @@ int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_arg
}
cil_list_for_each(item, block->bi_nodes) {
- rc = cil_check_recursive_blockinherit(item->data);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
rc = cil_copy_ast(db, current, item->data);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n");
@@ -2465,6 +2394,7 @@ int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args)
block_node = NODE(block_datum);
if (block_node->flavor != CIL_BLOCK) {
cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc);
+ rc = SEPOL_ERR;
goto exit;
}
@@ -2496,15 +2426,22 @@ int cil_resolve_in(struct cil_tree_node *current, void *extra_args)
block_node = NODE(block_datum);
+ if (block_node->flavor == CIL_OPTIONAL) {
+ if (block_datum->nodes && block_datum->nodes->head != block_datum->nodes->tail) {
+ cil_tree_log(current, CIL_ERR, "Multiple optional blocks referred to by in-statement");
+ cil_tree_log(block_node, CIL_ERR, "First optional block");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
+
rc = cil_copy_ast(db, current, block_node);
if (rc != SEPOL_OK) {
- printf("Failed to copy in, rc: %d\n", rc);
+ cil_tree_log(current, CIL_ERR, "Failed to copy in-statement");
goto exit;
}
cil_tree_children_destroy(current);
- current->cl_head = NULL;
- current->cl_tail = NULL;
return SEPOL_OK;
@@ -2512,10 +2449,8 @@ exit:
return rc;
}
-int cil_resolve_in_list(void *extra_args)
+int cil_resolve_in_list(struct cil_list *in_list, void *extra_args)
{
- struct cil_args_resolve *args = extra_args;
- struct cil_list *ins = args->in_list;
struct cil_list_item *curr = NULL;
struct cil_tree_node *node = NULL;
struct cil_tree_node *last_failed_node = NULL;
@@ -2529,7 +2464,7 @@ int cil_resolve_in_list(void *extra_args)
resolved = 0;
unresolved = 0;
- cil_list_for_each(curr, ins) {
+ cil_list_for_each(curr, in_list) {
if (curr->flavor != CIL_NODE) {
continue;
}
@@ -2768,359 +2703,368 @@ exit:
return rc;
}
-int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
+static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call *call, struct cil_macro *macro, void *extra_args)
{
- struct cil_call *new_call = current->data;
struct cil_args_resolve *args = extra_args;
- struct cil_db *db = NULL;
- struct cil_tree_node *macro_node = NULL;
- struct cil_symtab_datum *macro_datum = NULL;
+ struct cil_list_item *item;
+ struct cil_args *arg = NULL;
+ struct cil_tree_node *arg_node = NULL;
int rc = SEPOL_ERR;
- if (args != NULL) {
- db = args->db;
+ if (macro->params == NULL) {
+ if (call->args_tree == NULL) {
+ return SEPOL_OK;
+ } else {
+ cil_tree_log(call_node, CIL_ERR, "Unexpected arguments");
+ return SEPOL_ERR;
+ }
}
-
- rc = cil_resolve_name(current, new_call->macro_str, CIL_SYM_BLOCKS, extra_args, ¯o_datum);
- if (rc != SEPOL_OK) {
- goto exit;
+ if (call->args_tree == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Missing arguments");
+ return SEPOL_ERR;
}
- macro_node = NODE(macro_datum);
-
- if (macro_node->flavor != CIL_MACRO) {
- printf("Failed to resolve %s to a macro\n", new_call->macro_str);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_call->macro = (struct cil_macro*)macro_datum;
+ arg_node = call->args_tree->root->cl_head;
- if (new_call->macro->params != NULL ) {
+ cil_list_init(&call->args, CIL_LIST_ITEM);
- struct cil_list_item *item;
- struct cil_args *new_arg = NULL;
- struct cil_tree_node *pc = NULL;
+ cil_list_for_each(item, macro->params) {
+ enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor;
- if (new_call->args_tree == NULL) {
- cil_tree_log(current, CIL_ERR, "Missing arguments");
+ if (arg_node == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Missing arguments");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ if (item->flavor != CIL_PARAM) {
rc = SEPOL_ERR;
goto exit;
}
- pc = new_call->args_tree->root->cl_head;
-
- cil_list_init(&new_call->args, CIL_LIST_ITEM);
-
- cil_list_for_each(item, new_call->macro->params) {
- enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor;
+ cil_args_init(&arg);
- if (pc == NULL) {
- cil_tree_log(current, CIL_ERR, "Missing arguments");
+ switch (flavor) {
+ case CIL_NAME: {
+ struct cil_name *name;
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
- if (item->flavor != CIL_PARAM) {
+ name = __cil_insert_name(args->db, arg_node->data, call_node);
+ if (name != NULL) {
+ arg->arg = (struct cil_symtab_datum *)name;
+ } else {
+ arg->arg_str = arg_node->data;
+ }
+ }
+ break;
+ case CIL_TYPE:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
-
- cil_args_init(&new_arg);
-
- switch (flavor) {
- case CIL_NAME: {
- struct cil_name *name;
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- name = __cil_insert_name(args->db, pc->data, current);
- if (name != NULL) {
- new_arg->arg = (struct cil_symtab_datum *)name;
- } else {
- new_arg->arg_str = pc->data;
- }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_ROLE:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
}
- break;
- case CIL_TYPE:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_ROLE:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_USER:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_SENS:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_CAT:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_BOOL:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_CATSET: {
- if (pc->cl_head != NULL) {
- struct cil_catset *catset = NULL;
- struct cil_tree_node *cat_node = NULL;
- cil_catset_init(&catset);
- rc = cil_fill_cats(pc, &catset->cats);
- if (rc != SEPOL_OK) {
- cil_destroy_catset(catset);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&cat_node);
- cat_node->flavor = CIL_CATSET;
- cat_node->data = catset;
- cil_list_append(((struct cil_symtab_datum*)catset)->nodes,
- CIL_LIST_ITEM, cat_node);
- new_arg->arg = (struct cil_symtab_datum*)catset;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_USER:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_SENS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CAT:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_BOOL:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CATSET: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_catset *catset = NULL;
+ struct cil_tree_node *cat_node = NULL;
+ cil_catset_init(&catset);
+ rc = cil_fill_cats(arg_node, &catset->cats);
+ if (rc != SEPOL_OK) {
+ cil_destroy_catset(catset);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
-
- break;
+ cil_tree_node_init(&cat_node);
+ cat_node->flavor = CIL_CATSET;
+ cat_node->data = catset;
+ cil_list_append(((struct cil_symtab_datum*)catset)->nodes,
+ CIL_LIST_ITEM, cat_node);
+ arg->arg = (struct cil_symtab_datum*)catset;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_LEVEL: {
- if (pc->cl_head != NULL) {
- struct cil_level *level = NULL;
- struct cil_tree_node *lvl_node = NULL;
- cil_level_init(&level);
- rc = cil_fill_level(pc->cl_head, level);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc);
- cil_destroy_level(level);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&lvl_node);
- lvl_node->flavor = CIL_LEVEL;
- lvl_node->data = level;
- cil_list_append(((struct cil_symtab_datum*)level)->nodes,
- CIL_LIST_ITEM, lvl_node);
- new_arg->arg = (struct cil_symtab_datum*)level;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+ break;
+ }
+ case CIL_LEVEL: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_level *level = NULL;
+ struct cil_tree_node *lvl_node = NULL;
+ cil_level_init(&level);
+
+ rc = cil_fill_level(arg_node->cl_head, level);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc);
+ cil_destroy_level(level);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
-
- break;
+ cil_tree_node_init(&lvl_node);
+ lvl_node->flavor = CIL_LEVEL;
+ lvl_node->data = level;
+ cil_list_append(((struct cil_symtab_datum*)level)->nodes,
+ CIL_LIST_ITEM, lvl_node);
+ arg->arg = (struct cil_symtab_datum*)level;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_LEVELRANGE: {
- if (pc->cl_head != NULL) {
- struct cil_levelrange *range = NULL;
- struct cil_tree_node *range_node = NULL;
- cil_levelrange_init(&range);
- rc = cil_fill_levelrange(pc->cl_head, range);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc);
- cil_destroy_levelrange(range);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&range_node);
- range_node->flavor = CIL_LEVELRANGE;
- range_node->data = range;
- cil_list_append(((struct cil_symtab_datum*)range)->nodes,
- CIL_LIST_ITEM, range_node);
- new_arg->arg = (struct cil_symtab_datum*)range;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+ break;
+ }
+ case CIL_LEVELRANGE: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_levelrange *range = NULL;
+ struct cil_tree_node *range_node = NULL;
+ cil_levelrange_init(&range);
+
+ rc = cil_fill_levelrange(arg_node->cl_head, range);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc);
+ cil_destroy_levelrange(range);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
-
- break;
+ cil_tree_node_init(&range_node);
+ range_node->flavor = CIL_LEVELRANGE;
+ range_node->data = range;
+ cil_list_append(((struct cil_symtab_datum*)range)->nodes,
+ CIL_LIST_ITEM, range_node);
+ arg->arg = (struct cil_symtab_datum*)range;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_IPADDR: {
- if (pc->cl_head != NULL) {
- struct cil_ipaddr *ipaddr = NULL;
- struct cil_tree_node *addr_node = NULL;
- cil_ipaddr_init(&ipaddr);
- rc = cil_fill_ipaddr(pc->cl_head, ipaddr);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous ip address, rc: %d\n", rc);
- cil_destroy_ipaddr(ipaddr);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&addr_node);
- addr_node->flavor = CIL_IPADDR;
- addr_node->data = ipaddr;
- cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes,
- CIL_LIST_ITEM, addr_node);
- new_arg->arg = (struct cil_symtab_datum*)ipaddr;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+ break;
+ }
+ case CIL_IPADDR: {
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else if (strchr(arg_node->data, '.') || strchr(arg_node->data, ':')) {
+ struct cil_ipaddr *ipaddr = NULL;
+ struct cil_tree_node *addr_node = NULL;
+ cil_ipaddr_init(&ipaddr);
+ rc = cil_fill_ipaddr(arg_node, ipaddr);
+ if (rc != SEPOL_OK) {
+ cil_tree_log(call_node, CIL_ERR, "Failed to create anonymous ip address");
+ cil_destroy_ipaddr(ipaddr);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
-
- break;
+ cil_tree_node_init(&addr_node);
+ addr_node->flavor = CIL_IPADDR;
+ addr_node->data = ipaddr;
+ cil_list_append(DATUM(ipaddr)->nodes, CIL_LIST_ITEM, addr_node);
+ arg->arg = DATUM(ipaddr);
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_CLASS:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_MAP_CLASS:
- if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_arg->arg_str = pc->data;
- break;
- case CIL_CLASSPERMISSION: {
- if (pc->cl_head != NULL) {
- struct cil_classpermission *cp = NULL;
- struct cil_tree_node *cp_node = NULL;
+ break;
+ }
+ case CIL_CLASS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_MAP_CLASS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CLASSPERMISSION: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_classpermission *cp = NULL;
+ struct cil_tree_node *cp_node = NULL;
- cil_classpermission_init(&cp);
- rc = cil_fill_classperms_list(pc, &cp->classperms);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous classpermission\n");
- cil_destroy_classpermission(cp);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&cp_node);
- cp_node->flavor = CIL_CLASSPERMISSION;
- cp_node->data = cp;
- cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node);
- new_arg->arg = (struct cil_symtab_datum*)cp;
- } else if (pc->data == NULL) {
- cil_tree_log(current, CIL_ERR, "Invalid macro parameter");
- cil_destroy_args(new_arg);
- rc = SEPOL_ERR;
+ cil_classpermission_init(&cp);
+ rc = cil_fill_classperms_list(arg_node, &cp->classperms);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous classpermission\n");
+ cil_destroy_classpermission(cp);
+ cil_destroy_args(arg);
goto exit;
- } else {
- new_arg->arg_str = pc->data;
}
- break;
- }
- default:
- cil_log(CIL_ERR, "Unexpected flavor: %d\n",
- (((struct cil_param*)item->data)->flavor));
- cil_destroy_args(new_arg);
+ cil_tree_node_init(&cp_node);
+ cp_node->flavor = CIL_CLASSPERMISSION;
+ cp_node->data = cp;
+ cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node);
+ arg->arg = (struct cil_symtab_datum*)cp;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- new_arg->param_str = ((struct cil_param*)item->data)->str;
- new_arg->flavor = flavor;
-
- cil_list_append(new_call->args, CIL_ARGS, new_arg);
-
- pc = pc->next;
+ break;
}
-
- if (pc != NULL) {
- cil_tree_log(current, CIL_ERR, "Unexpected arguments");
+ default:
+ cil_log(CIL_ERR, "Unexpected flavor: %d\n",
+ (((struct cil_param*)item->data)->flavor));
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
- } else if (new_call->args_tree != NULL) {
- cil_tree_log(current, CIL_ERR, "Unexpected arguments");
+ arg->param_str = ((struct cil_param*)item->data)->str;
+ arg->flavor = flavor;
+
+ cil_list_append(call->args, CIL_ARGS, arg);
+
+ arg_node = arg_node->next;
+ }
+
+ if (arg_node != NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Unexpected arguments");
rc = SEPOL_ERR;
goto exit;
}
- if (new_call->copied == 0) {
- new_call->copied = 1;
+ return SEPOL_OK;
- rc = cil_check_recursive_call(current, macro_node);
- if (rc != SEPOL_OK) {
- goto exit;
- }
+exit:
+ return rc;
+}
- rc = cil_copy_ast(db, macro_node, current);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to copy macro, rc: %d\n", rc);
- goto exit;
- }
+int cil_resolve_call(struct cil_tree_node *current, void *extra_args)
+{
+ struct cil_call *call = current->data;
+ struct cil_args_resolve *args = extra_args;
+ struct cil_tree_node *macro_node = NULL;
+ struct cil_symtab_datum *macro_datum = NULL;
+ int rc = SEPOL_ERR;
+
+ if (call->copied) {
+ return SEPOL_OK;
}
+ rc = cil_resolve_name(current, call->macro_str, CIL_SYM_BLOCKS, extra_args, ¯o_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ macro_node = NODE(macro_datum);
+
+ if (macro_node->flavor != CIL_MACRO) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s to a macro", call->macro_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ call->macro = (struct cil_macro*)macro_datum;
+
+ rc = cil_build_call_args(current, call, call->macro, extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = cil_check_recursive_call(current, macro_node);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = cil_copy_ast(args->db, macro_node, current);
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to copy macro %s to call", macro_datum->name);
+ goto exit;
+ }
+
+ call->copied = 1;
+
return SEPOL_OK;
exit:
return rc;
}
-int cil_resolve_call2(struct cil_tree_node *current, void *extra_args)
+int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args)
{
- struct cil_call *new_call = current->data;
+ struct cil_call *call = current->data;
int rc = SEPOL_ERR;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
struct cil_list_item *item;
- if (new_call->args == NULL) {
+ if (call->args == NULL) {
rc = SEPOL_OK;
goto exit;
}
- cil_list_for_each(item, new_call->args) {
+ cil_list_for_each(item, call->args) {
struct cil_args *arg = item->data;
if (arg->arg == NULL && arg->arg_str == NULL) {
cil_log(CIL_ERR, "Arguments not created correctly\n");
@@ -3203,10 +3147,37 @@ int cil_resolve_call2(struct cil_tree_node *current, void *extra_args)
}
if (sym_index != CIL_SYM_UNKNOWN) {
- rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
+ struct cil_symtab_datum *datum;
+ struct cil_tree_node *n;
+ rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &datum);
if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str);
goto exit;
}
+ arg->arg = datum;
+ n = NODE(datum);
+ while (n && n->flavor != CIL_ROOT) {
+ if (n == current) {
+ symtab_t *s = datum->symtab;
+ /* Call arg should not resolve to declaration in the call
+ * Need to remove datum temporarily to resolve to a datum outside
+ * the call.
+ */
+ cil_symtab_remove_datum(datum);
+ rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str);
+ goto exit;
+ }
+ rc = cil_symtab_insert(s, datum->name, datum, NULL);
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to re-insert datum while resolving %s in call argument list", arg->arg_str);
+ goto exit;
+ }
+ break;
+ }
+ n = n->parent;
+ }
}
}
@@ -3236,7 +3207,7 @@ int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_i
if (param_index == sym_index) {
if (name == arg->param_str) {
*datum = arg->arg;
- rc = SEPOL_OK;
+ rc = *datum ? SEPOL_OK : SEPOL_ERR;
goto exit;
}
}
@@ -3254,6 +3225,8 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc
struct cil_list_item *curr;
struct cil_symtab_datum *res_datum = NULL;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
+ struct cil_list *datum_sub_expr;
+ enum cil_flavor op = CIL_NONE;
switch (str_expr->flavor) {
case CIL_BOOL:
@@ -3287,31 +3260,53 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc
if (rc != SEPOL_OK) {
goto exit;
}
-
- if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) {
- cil_type_used(res_datum, CIL_ATTR_CONSTRAINT);
+ if (sym_index == CIL_SYM_CATS && NODE(res_datum)->flavor == CIL_CATSET) {
+ struct cil_catset *catset = (struct cil_catset *)res_datum;
+ if (op == CIL_RANGE) {
+ cil_tree_log(parent, CIL_ERR, "Category set not allowed in category range");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ if (!res_datum->name) {
+ /* Anonymous category sets need to be resolved when encountered */
+ if (!catset->cats->datum_expr) {
+ rc = cil_resolve_expr(expr_type, catset->cats->str_expr, &catset->cats->datum_expr, parent, extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ }
+ cil_copy_list(catset->cats->datum_expr, &datum_sub_expr);
+ cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr);
+ } else {
+ cil_list_append(*datum_expr, CIL_DATUM, res_datum);
+ }
+ } else {
+ if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) {
+ cil_type_used(res_datum, CIL_ATTR_CONSTRAINT);
+ }
+ cil_list_append(*datum_expr, CIL_DATUM, res_datum);
}
-
- cil_list_append(*datum_expr, CIL_DATUM, res_datum);
break;
case CIL_LIST: {
- struct cil_list *datum_sub_expr;
rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, extra_args);
if (rc != SEPOL_OK) {
- cil_list_destroy(&datum_sub_expr, CIL_TRUE);
goto exit;
}
cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr);
break;
}
default:
+ if (curr->flavor == CIL_OP) {
+ op = (enum cil_flavor)(uintptr_t)curr->data;
+ }
cil_list_append(*datum_expr, curr->flavor, curr->data);
break;
- }
+ }
}
return SEPOL_OK;
exit:
+ cil_list_destroy(datum_expr, CIL_FALSE);
return rc;
}
@@ -3472,11 +3467,6 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE);
}
@@ -3489,17 +3479,119 @@ exit:
return rc;
}
+/*
+ * Degenerate inheritance leads to exponential growth of the policy
+ * It can take many forms, but here is one example.
+ * ...
+ * (blockinherit ba)
+ * (block b0
+ * (block b1
+ * (block b2
+ * (block b3
+ * ...
+ * )
+ * (blockinherit b3)
+ * )
+ * (blockinherit b2)
+ * )
+ * (blockinherit b1)
+ * )
+ * (blockinherit b0)
+ * ...
+ * This leads to 2^4 copies of the content of block b3, 2^3 copies of the
+ * contents of block b2, etc.
+ */
+static unsigned cil_count_actual(struct cil_tree_node *node)
+{
+ unsigned count = 0;
+
+ if (node->flavor == CIL_BLOCKINHERIT) {
+ count += 1;
+ }
+
+ for (node = node->cl_head; node; node = node->next) {
+ count += cil_count_actual(node);
+ }
+
+ return count;
+}
+
+static int cil_check_inheritances(struct cil_tree_node *node, unsigned max, unsigned *count, struct cil_stack *stack, unsigned *loop)
+{
+ int rc;
+
+ if (node->flavor == CIL_BLOCKINHERIT) {
+ struct cil_blockinherit *bi = node->data;
+ *count += 1;
+ if (*count > max) {
+ cil_tree_log(node, CIL_ERR, "Degenerate inheritance detected");
+ return SEPOL_ERR;
+ }
+ if (bi->block) {
+ struct cil_tree_node *block_node = NODE(bi->block);
+ struct cil_stack_item *item;
+ int i = 0;
+ cil_stack_for_each(stack, i, item) {
+ if (block_node == (struct cil_tree_node *)item->data) {
+ *loop = CIL_TRUE;
+ cil_tree_log(block_node, CIL_ERR, "Block inheritance loop found");
+ cil_tree_log(node, CIL_ERR, " blockinherit");
+ return SEPOL_ERR;
+ }
+ }
+ cil_stack_push(stack, CIL_BLOCK, block_node);
+ rc = cil_check_inheritances(block_node, max, count, stack, loop);
+ cil_stack_pop(stack);
+ if (rc != SEPOL_OK) {
+ if (*loop == CIL_TRUE) {
+ cil_tree_log(node, CIL_ERR, " blockinherit");
+ }
+ return SEPOL_ERR;
+ }
+ }
+ }
+
+ for (node = node->cl_head; node; node = node->next) {
+ rc = cil_check_inheritances(node, max, count, stack, loop);
+ if (rc != SEPOL_OK) {
+ return SEPOL_ERR;
+ }
+ }
+
+ return SEPOL_OK;
+}
+
+static int cil_check_for_bad_inheritance(struct cil_tree_node *node)
+{
+ unsigned num_actual, max;
+ unsigned num_potential = 0;
+ unsigned loop = CIL_FALSE;
+ struct cil_stack *stack;
+ int rc;
+
+ num_actual = cil_count_actual(node);
+
+ max = num_actual * CIL_DEGENERATE_INHERITANCE_GROWTH;
+ if (max < CIL_DEGENERATE_INHERITANCE_MINIMUM) {
+ max = CIL_DEGENERATE_INHERITANCE_MINIMUM;
+ }
+
+ cil_stack_init(&stack);
+ rc = cil_check_inheritances(node, max, &num_potential, stack, &loop);
+ cil_stack_destroy(&stack);
+
+ return rc;
+}
+
int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
{
int rc = SEPOL_OK;
struct cil_args_resolve *args = extra_args;
enum cil_pass pass = 0;
- struct cil_list *ins;
if (node == NULL || args == NULL) {
goto exit;
}
- ins = args->in_list;
pass = args->pass;
switch (pass) {
@@ -3508,11 +3600,14 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
rc = cil_resolve_tunif(node, args);
}
break;
- case CIL_PASS_IN:
+ case CIL_PASS_IN_BEFORE:
if (node->flavor == CIL_IN) {
// due to ordering issues, in statements are just gathered here and
// resolved together in cil_resolve_in_list once all are found
- cil_list_prepend(ins, CIL_NODE, node);
+ struct cil_in *in = node->data;
+ if (in->is_after == CIL_FALSE) {
+ cil_list_prepend(args->in_list_before, CIL_NODE, node);
+ }
}
break;
case CIL_PASS_BLKIN_LINK:
@@ -3530,19 +3625,24 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
rc = cil_resolve_blockabstract(node, args);
}
break;
- case CIL_PASS_MACRO:
- if (node->flavor == CIL_CALL && args->macro != NULL) {
- rc = cil_resolve_call1(node, args);
+ case CIL_PASS_IN_AFTER:
+ if (node->flavor == CIL_IN) {
+ // due to ordering issues, in statements are just gathered here and
+ // resolved together in cil_resolve_in_list once all are found
+ struct cil_in *in = node->data;
+ if (in->is_after == CIL_TRUE) {
+ cil_list_prepend(args->in_list_after, CIL_NODE, node);
+ }
}
break;
case CIL_PASS_CALL1:
- if (node->flavor == CIL_CALL) {
- rc = cil_resolve_call1(node, args);
+ if (node->flavor == CIL_CALL && args->macro == NULL) {
+ rc = cil_resolve_call(node, args);
}
break;
case CIL_PASS_CALL2:
- if (node->flavor == CIL_CALL) {
- rc = cil_resolve_call2(node, args);
+ if (node->flavor == CIL_CALL && args->macro == NULL) {
+ rc = cil_resolve_call_args(node, args);
}
break;
case CIL_PASS_ALIAS1:
@@ -3790,18 +3890,20 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
if (block != NULL) {
if (node->flavor == CIL_CAT ||
node->flavor == CIL_SENS) {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in blocks", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in block", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
}
if (macro != NULL) {
- if (node->flavor == CIL_BLOCK ||
+ if (node->flavor == CIL_TUNABLE ||
+ node->flavor == CIL_IN ||
+ node->flavor == CIL_BLOCK ||
node->flavor == CIL_BLOCKINHERIT ||
node->flavor == CIL_BLOCKABSTRACT ||
node->flavor == CIL_MACRO) {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in macros", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in macro", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
@@ -3813,7 +3915,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
node->flavor == CIL_BLOCK ||
node->flavor == CIL_BLOCKABSTRACT ||
node->flavor == CIL_MACRO) {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in optional", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
@@ -3835,16 +3937,16 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
}
if (rc == SEPOL_ERR) {
if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif)", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", cil_node_to_string(node));
} else {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in booleanif", cil_node_to_string(node));
}
goto exit;
}
}
if (node->flavor == CIL_MACRO) {
- if (pass != CIL_PASS_TIF && pass != CIL_PASS_MACRO) {
+ if (pass > CIL_PASS_IN_AFTER) {
*finished = CIL_TREE_SKIP_HEAD;
rc = SEPOL_OK;
goto exit;
@@ -3859,22 +3961,16 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
rc = __cil_resolve_ast_node(node, extra_args);
if (rc == SEPOL_ENOENT) {
- enum cil_log_level lvl = CIL_ERR;
-
- if (optional != NULL) {
- lvl = CIL_INFO;
-
- struct cil_optional *opt = (struct cil_optional *)optional->data;
- struct cil_tree_node *opt_node = NODE(opt);;
- /* disable an optional if something failed to resolve */
- opt->enabled = CIL_FALSE;
- cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node));
- cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name);
+ if (optional == NULL) {
+ cil_tree_log(node, CIL_ERR, "Failed to resolve %s statement", cil_node_to_string(node));
+ } else {
+ if (!args->disabled_optional) {
+ args->disabled_optional = optional;
+ }
+ cil_tree_log(node, CIL_INFO, "Failed to resolve %s statement", cil_node_to_string(node));
+ cil_tree_log(optional, CIL_INFO, "Disabling optional '%s'", DATUM(optional->data)->name);
rc = SEPOL_OK;
- goto exit;
}
-
- cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node));
goto exit;
}
@@ -3939,9 +4035,10 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext
args->macro = NULL;
} else if (parent->flavor == CIL_OPTIONAL) {
struct cil_tree_node *n = parent->parent;
- if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) {
+ if (args->disabled_optional == parent) {
*(args->changed) = CIL_TRUE;
- cil_list_append(args->disabled_optionals, CIL_NODE, parent);
+ cil_list_append(args->to_destroy, CIL_NODE, parent);
+ args->disabled_optional = NULL;
}
args->optional = NULL;
while (n && n->flavor != CIL_ROOT) {
@@ -3978,21 +4075,25 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
extra_args.block = NULL;
extra_args.macro = NULL;
extra_args.optional = NULL;
+ extra_args.disabled_optional = NULL;
extra_args.boolif= NULL;
extra_args.sidorder_lists = NULL;
extra_args.classorder_lists = NULL;
extra_args.unordered_classorder_lists = NULL;
extra_args.catorder_lists = NULL;
extra_args.sensitivityorder_lists = NULL;
- extra_args.in_list = NULL;
+ extra_args.in_list_before = NULL;
+ extra_args.in_list_after = NULL;
- cil_list_init(&extra_args.disabled_optionals, CIL_NODE);
+ cil_list_init(&extra_args.to_destroy, CIL_NODE);
cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
- cil_list_init(&extra_args.in_list, CIL_IN);
+ cil_list_init(&extra_args.in_list_before, CIL_IN);
+ cil_list_init(&extra_args.in_list_after, CIL_IN);
+
for (pass = CIL_PASS_TIF; pass < CIL_PASS_NUM; pass++) {
extra_args.pass = pass;
rc = cil_tree_walk(current, __cil_resolve_ast_node_helper, __cil_resolve_ast_first_child_helper, __cil_resolve_ast_last_child_helper, &extra_args);
@@ -4001,12 +4102,26 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
goto exit;
}
- if (pass == CIL_PASS_IN) {
- rc = cil_resolve_in_list(&extra_args);
+ if (pass == CIL_PASS_IN_BEFORE) {
+ rc = cil_resolve_in_list(extra_args.in_list_before, &extra_args);
if (rc != SEPOL_OK) {
goto exit;
}
- cil_list_destroy(&extra_args.in_list, CIL_FALSE);
+ cil_list_destroy(&extra_args.in_list_before, CIL_FALSE);
+ } else if (pass == CIL_PASS_IN_AFTER) {
+ rc = cil_resolve_in_list(extra_args.in_list_after, &extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ cil_list_destroy(&extra_args.in_list_after, CIL_FALSE);
+ }
+
+ if (pass == CIL_PASS_BLKIN_LINK) {
+ rc = cil_check_for_bad_inheritance(current);
+ if (rc != SEPOL_OK) {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
}
if (pass == CIL_PASS_MISC1) {
@@ -4053,41 +4168,53 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
}
}
- if (changed && (pass > CIL_PASS_CALL1)) {
+ if (changed) {
struct cil_list_item *item;
- /* Need to re-resolve because an optional was disabled that contained
- * one or more declarations. We only need to reset to the call1 pass
- * because things done in the preceding passes aren't allowed in
- * optionals, and thus can't be disabled.
- * Note: set pass to CIL_PASS_CALL1 because the pass++ will increment
- * it to CIL_PASS_CALL2
- */
- cil_log(CIL_INFO, "Resetting declarations\n");
-
- if (pass >= CIL_PASS_MISC1) {
- __cil_ordered_lists_reset(&extra_args.sidorder_lists);
- __cil_ordered_lists_reset(&extra_args.classorder_lists);
- __cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
- __cil_ordered_lists_reset(&extra_args.catorder_lists);
- __cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
- cil_list_destroy(&db->sidorder, CIL_FALSE);
- cil_list_destroy(&db->classorder, CIL_FALSE);
- cil_list_destroy(&db->catorder, CIL_FALSE);
- cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
- }
+ if (pass > CIL_PASS_CALL1) {
+ int has_decls = CIL_FALSE;
- pass = CIL_PASS_CALL1;
+ cil_list_for_each(item, extra_args.to_destroy) {
+ has_decls = cil_tree_subtree_has_decl(item->data);
+ if (has_decls) {
+ break;
+ }
+ }
- rc = cil_reset_ast(current);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to reset declarations\n");
- goto exit;
+ if (has_decls) {
+ /* Need to re-resolve because an optional was disabled that
+ * contained one or more declarations.
+ * Everything that needs to be reset comes after the
+ * CIL_PASS_CALL2 pass. We set pass to CIL_PASS_CALL1 because
+ * the pass++ will increment it to CIL_PASS_CALL2
+ */
+ cil_log(CIL_INFO, "Resetting declarations\n");
+
+ if (pass >= CIL_PASS_MISC1) {
+ __cil_ordered_lists_reset(&extra_args.sidorder_lists);
+ __cil_ordered_lists_reset(&extra_args.classorder_lists);
+ __cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
+ __cil_ordered_lists_reset(&extra_args.catorder_lists);
+ __cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
+ cil_list_destroy(&db->sidorder, CIL_FALSE);
+ cil_list_destroy(&db->classorder, CIL_FALSE);
+ cil_list_destroy(&db->catorder, CIL_FALSE);
+ cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
+ }
+
+ pass = CIL_PASS_CALL1;
+
+ rc = cil_reset_ast(current);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to reset declarations\n");
+ goto exit;
+ }
+ }
}
- cil_list_for_each(item, extra_args.disabled_optionals) {
+ cil_list_for_each(item, extra_args.to_destroy) {
cil_tree_children_destroy(item->data);
}
- cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE);
- cil_list_init(&extra_args.disabled_optionals, CIL_NODE);
+ cil_list_destroy(&extra_args.to_destroy, CIL_FALSE);
+ cil_list_init(&extra_args.to_destroy, CIL_NODE);
changed = 0;
}
}
@@ -4104,8 +4231,9 @@ exit:
__cil_ordered_lists_destroy(&extra_args.catorder_lists);
__cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists);
__cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists);
- cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE);
- cil_list_destroy(&extra_args.in_list, CIL_FALSE);
+ cil_list_destroy(&extra_args.to_destroy, CIL_FALSE);
+ cil_list_destroy(&extra_args.in_list_before, CIL_FALSE);
+ cil_list_destroy(&extra_args.in_list_after, CIL_FALSE);
return rc;
}
@@ -4136,7 +4264,7 @@ static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *nam
rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum);
if (rc != SEPOL_OK) {
/* Continue search in original block's parent */
- rc = __cil_resolve_name_with_parents(NODE(inherit->block), name, sym_index, datum);
+ rc = __cil_resolve_name_with_parents(NODE(inherit->block)->parent, name, sym_index, datum);
goto exit;
}
}
@@ -4149,10 +4277,18 @@ static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *nam
break;
case CIL_CALL: {
struct cil_call *call = node->data;
- rc = cil_resolve_name_call_args(call, name, sym_index, datum);
- if (rc != SEPOL_OK) {
- /* Continue search in macro's parent */
- rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum);
+ struct cil_macro *macro = call->macro;
+ symtab = ¯o->symtab[sym_index];
+ rc = cil_symtab_get_datum(symtab, name, datum);
+ if (rc == SEPOL_OK) {
+ /* If the name was declared in the macro, just look on the call side */
+ rc = SEPOL_ERR;
+ } else {
+ rc = cil_resolve_name_call_args(call, name, sym_index, datum);
+ if (rc != SEPOL_OK) {
+ /* Continue search in macro's parent */
+ rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum);
+ }
}
}
break;
@@ -4224,8 +4360,8 @@ int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, en
*datum = NULL;
- if (strchr(name,'.') == NULL) {
- /* No '.' in name */
+ if (db->qualified_names || strchr(name,'.') == NULL) {
+ /* Using qualified names or No '.' in name */
rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum);
if (rc != SEPOL_OK) {
goto exit;
diff --git a/libsepol/cil/src/cil_stack.c b/libsepol/cil/src/cil_stack.c
index bbfb961a1f5b1ee045aa333fb7a0e9c89a1d5756..70a77bc1ada52c80750d6e517b773d1257fef7e1 100644
--- a/libsepol/cil/src/cil_stack.c
+++ b/libsepol/cil/src/cil_stack.c
@@ -67,6 +67,11 @@ int cil_stack_is_empty(struct cil_stack *stack)
return (stack->pos == -1);
}
+int cil_stack_number_of_items(struct cil_stack *stack)
+{
+ return stack->pos + 1;
+}
+
void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data)
{
stack->pos++;
diff --git a/libsepol/cil/src/cil_stack.h b/libsepol/cil/src/cil_stack.h
index b78535ac8f8295b0077cd046fc65b5916f9dbbb7..0e3eff6642b81141d01f6a50c169d50756637900 100644
--- a/libsepol/cil/src/cil_stack.h
+++ b/libsepol/cil/src/cil_stack.h
@@ -52,6 +52,7 @@ void cil_stack_destroy(struct cil_stack **stack);
void cil_stack_empty(struct cil_stack *stack);
int cil_stack_is_empty(struct cil_stack *stack);
+int cil_stack_number_of_items(struct cil_stack *stack);
void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data);
struct cil_stack_item *cil_stack_pop(struct cil_stack *stack);
diff --git a/libsepol/cil/src/cil_strpool.c b/libsepol/cil/src/cil_strpool.c
index 2598bbf3d80ec64e055be7c97694688f0641e38f..e32ee4e90f34699e83f3d8b1a53bcb36663d151b 100644
--- a/libsepol/cil/src/cil_strpool.c
+++ b/libsepol/cil/src/cil_strpool.c
@@ -47,14 +47,13 @@ static hashtab_t cil_strpool_tab = NULL;
static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key)
{
- const char *p, *keyp;
+ const char *p;
size_t size;
unsigned int val;
val = 0;
- keyp = (const char*)key;
- size = strlen(keyp);
- for (p = keyp; ((size_t) (p - keyp)) < size; p++)
+ size = strlen(key);
+ for (p = key; ((size_t) (p - key)) < size; p++)
val =
(val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val & (h->size - 1);
@@ -62,9 +61,7 @@ static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key)
static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2)
{
- const char *keyp1 = (const char*)key1;
- const char *keyp2 = (const char*)key2;
- return strcmp(keyp1, keyp2);
+ return strcmp(key1, key2);
}
char *cil_strpool_add(const char *str)
@@ -73,11 +70,12 @@ char *cil_strpool_add(const char *str)
pthread_mutex_lock(&cil_strpool_mutex);
- strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str);
+ strpool_ref = hashtab_search(cil_strpool_tab, str);
if (strpool_ref == NULL) {
+ int rc;
strpool_ref = cil_malloc(sizeof(*strpool_ref));
strpool_ref->str = cil_strdup(str);
- int rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref);
+ rc = hashtab_insert(cil_strpool_tab, strpool_ref->str, strpool_ref);
if (rc != SEPOL_OK) {
pthread_mutex_unlock(&cil_strpool_mutex);
cil_log(CIL_ERR, "Failed to allocate memory\n");
diff --git a/libsepol/cil/src/cil_symtab.c b/libsepol/cil/src/cil_symtab.c
index 579a888e5785f29daad9512e3ff120450a70bcc5..c195156071e1f0a6f5e9e58436fdf343abd2eaea 100644
--- a/libsepol/cil/src/cil_symtab.c
+++ b/libsepol/cil/src/cil_symtab.c
@@ -93,10 +93,10 @@ int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_dat
datum->fqn = key;
datum->symtab = symtab;
symtab->nprim++;
- cil_list_append(datum->nodes, CIL_NODE, node);
- } else if (rc == SEPOL_EEXIST) {
- cil_list_append(datum->nodes, CIL_NODE, node);
- } else {
+ if (node) {
+ cil_list_append(datum->nodes, CIL_NODE, node);
+ }
+ } else if (rc != SEPOL_EEXIST) {
cil_symtab_error("Failed to insert datum into hashtab\n");
}
diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
index 3da972e9cf4e2532215cacb98e2c6f3b5cadee5e..aafc9dee39edf33e36ffd100e67eab07236b1d48 100644
--- a/libsepol/cil/src/cil_tree.c
+++ b/libsepol/cil/src/cil_tree.c
@@ -41,15 +41,6 @@
#include "cil_parser.h"
#include "cil_strpool.h"
-void cil_tree_print_perms_list(struct cil_tree_node *current_perm);
-void cil_tree_print_classperms(struct cil_classperms *cp);
-void cil_tree_print_level(struct cil_level *level);
-void cil_tree_print_levelrange(struct cil_levelrange *lvlrange);
-void cil_tree_print_context(struct cil_context *context);
-void cil_tree_print_expr_tree(struct cil_tree_node *expr_root);
-void cil_tree_print_constrain(struct cil_constrain *cons);
-void cil_tree_print_node(struct cil_tree_node *node);
-
__attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_error(const char* msg, ...)
{
va_list ap;
@@ -59,28 +50,38 @@ __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_e
exit(1);
}
-struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil)
+struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path)
{
+ int rc;
+
if (!node) {
- return NULL;
+ goto exit;
}
node = node->parent;
while (node) {
if (node->flavor == CIL_NODE && node->data == NULL) {
- if (node->cl_head->data == CIL_KEY_SRC_INFO && node->cl_head->next != NULL && node->cl_head->next->next != NULL) {
+ if (node->cl_head && node->cl_head->data == CIL_KEY_SRC_INFO) {
+ if (!node->cl_head->next || !node->cl_head->next->next || !node->cl_head->next->next->next) {
+ goto exit;
+ }
/* Parse Tree */
- *path = node->cl_head->next->next->data;
- *is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL);
+ *info_kind = node->cl_head->next->data;
+ rc = cil_string_to_uint32(node->cl_head->next->next->data, hll_line, 10);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ *path = node->cl_head->next->next->next->data;
return node;
}
node = node->parent;
} else if (node->flavor == CIL_SRC_INFO) {
/* AST */
struct cil_src_info *info = node->data;
+ *info_kind = info->kind;
+ *hll_line = info->hll_line;
*path = info->path;
- *is_cil = info->is_cil;
return node;
} else {
if (node->flavor == CIL_CALL) {
@@ -95,17 +96,22 @@ struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **
}
}
+exit:
+ *info_kind = NULL;
+ *hll_line = 0;
+ *path = NULL;
return NULL;
}
char *cil_tree_get_cil_path(struct cil_tree_node *node)
{
- char *path = NULL;
- int is_cil;
+ char *info_kind;
+ uint32_t hll_line;
+ char *path;
while (node) {
- node = cil_tree_get_next_path(node, &path, &is_cil);
- if (node && is_cil) {
+ node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path);
+ if (node && info_kind == CIL_KEY_SRC_CIL) {
return path;
}
}
@@ -123,28 +129,51 @@ __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *n
if (node) {
char *path = NULL;
- int is_cil;
- unsigned hll_line = node->hll_line;
+ uint32_t hll_offset = node->hll_offset;
path = cil_tree_get_cil_path(node);
if (path != NULL) {
- cil_log(lvl, " at %s:%d", path, node->line);
+ cil_log(lvl, " at %s:%u", path, node->line);
}
while (node) {
- node = cil_tree_get_next_path(node, &path, &is_cil);
- if (node && !is_cil) {
- cil_log(lvl," from %s:%d", path, hll_line);
- path = NULL;
- hll_line = node->hll_line;
- }
+ do {
+ char *info_kind;
+ uint32_t hll_line;
+
+ node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path);
+ if (!node || info_kind == CIL_KEY_SRC_CIL) {
+ break;
+ }
+ if (info_kind == CIL_KEY_SRC_HLL_LMS) {
+ hll_line += hll_offset - node->hll_offset - 1;
+ }
+
+ cil_log(lvl," from %s:%u", path, hll_line);
+ } while (1);
}
}
cil_log(lvl,"\n");
}
+int cil_tree_subtree_has_decl(struct cil_tree_node *node)
+{
+ while (node) {
+ if (node->flavor >= CIL_MIN_DECLARATIVE) {
+ return CIL_TRUE;
+ }
+ if (node->cl_head != NULL) {
+ if (cil_tree_subtree_has_decl(node->cl_head))
+ return CIL_TRUE;
+ }
+ node = node->next;
+ }
+
+ return CIL_FALSE;
+}
+
int cil_tree_init(struct cil_tree **tree)
{
struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree));
@@ -175,34 +204,21 @@ void cil_tree_subtree_destroy(struct cil_tree_node *node)
void cil_tree_children_destroy(struct cil_tree_node *node)
{
- struct cil_tree_node *start_node = node;
- struct cil_tree_node *next = NULL;
+ struct cil_tree_node *curr, *next;
- if (node == NULL) {
+ if (!node) {
return;
}
- if (node->cl_head != NULL) {
- node = node->cl_head;
- }
-
- while (node != start_node) {
- if (node->cl_head != NULL){
- next = node->cl_head;
- } else {
- if (node->next == NULL) {
- next = node->parent;
- if (node->parent != NULL) {
- node->parent->cl_head = NULL;
- }
- cil_tree_node_destroy(&node);
- } else {
- next = node->next;
- cil_tree_node_destroy(&node);
- }
- }
- node = next;
+ curr = node->cl_head;
+ while (curr) {
+ next = curr->next;
+ cil_tree_children_destroy(curr);
+ cil_tree_node_destroy(&curr);
+ curr = next;
}
+ node->cl_head = NULL;
+ node->cl_tail = NULL;
}
void cil_tree_node_init(struct cil_tree_node **node)
@@ -215,7 +231,7 @@ void cil_tree_node_init(struct cil_tree_node **node)
new_node->next = NULL;
new_node->flavor = CIL_ROOT;
new_node->line = 0;
- new_node->hll_line = 0;
+ new_node->hll_offset = 0;
*node = new_node;
}
@@ -328,1465 +344,3 @@ int cil_tree_walk(struct cil_tree_node *node,
return SEPOL_OK;
}
-
-
-/* Copied from cil_policy.c, but changed to prefix -- Need to refactor */
-static int cil_expr_to_string(struct cil_list *expr, char **out)
-{
- int rc = SEPOL_ERR;
- struct cil_list_item *curr;
- char *stack[COND_EXPR_MAXDEPTH] = {};
- int pos = 0;
-
- cil_list_for_each(curr, expr) {
- if (pos >= COND_EXPR_MAXDEPTH) {
- rc = SEPOL_ERR;
- goto exit;
- }
- switch (curr->flavor) {
- case CIL_LIST:
- rc = cil_expr_to_string(curr->data, &stack[pos]);
- if (rc != SEPOL_OK) {
- goto exit;
- }
- pos++;
- break;
- case CIL_STRING:
- stack[pos] = curr->data;
- pos++;
- break;
- case CIL_DATUM:
- stack[pos] = ((struct cil_symtab_datum *)curr->data)->name;
- pos++;
- break;
- case CIL_OP: {
- int len;
- char *expr_str;
- enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data);
- char *op_str = NULL;
-
- if (pos == 0) {
- rc = SEPOL_ERR;
- goto exit;
- }
- switch (op_flavor) {
- case CIL_AND:
- op_str = CIL_KEY_AND;
- break;
- case CIL_OR:
- op_str = CIL_KEY_OR;
- break;
- case CIL_NOT:
- op_str = CIL_KEY_NOT;
- break;
- case CIL_ALL:
- op_str = CIL_KEY_ALL;
- break;
- case CIL_EQ:
- op_str = CIL_KEY_EQ;
- break;
- case CIL_NEQ:
- op_str = CIL_KEY_NEQ;
- break;
- case CIL_XOR:
- op_str = CIL_KEY_XOR;
- break;
- case CIL_RANGE:
- op_str = CIL_KEY_RANGE;
- break;
- case CIL_CONS_DOM:
- op_str = CIL_KEY_CONS_DOM;
- break;
- case CIL_CONS_DOMBY:
- op_str = CIL_KEY_CONS_DOMBY;
- break;
- case CIL_CONS_INCOMP:
- op_str = CIL_KEY_CONS_INCOMP;
- break;
- default:
- cil_log(CIL_ERR, "Unknown operator in expression\n");
- goto exit;
- break;
- }
- if (op_flavor == CIL_NOT) {
- len = strlen(stack[pos-1]) + strlen(op_str) + 4;
- expr_str = cil_malloc(len);
- snprintf(expr_str, len, "(%s %s)", op_str, stack[pos-1]);
- free(stack[pos-1]);
- stack[pos-1] = NULL;
- pos--;
- } else {
- if (pos < 2) {
- rc = SEPOL_ERR;
- goto exit;
- }
- len = strlen(stack[pos-1]) + strlen(stack[pos-2]) + strlen(op_str) + 5;
- expr_str = cil_malloc(len);
- snprintf(expr_str, len, "(%s %s %s)", op_str, stack[pos-1], stack[pos-2]);
- free(stack[pos-2]);
- free(stack[pos-1]);
- stack[pos-2] = NULL;
- stack[pos-1] = NULL;
- pos -= 2;
- }
- stack[pos] = expr_str;
- pos++;
- break;
- }
- case CIL_CONS_OPERAND: {
- enum cil_flavor operand_flavor = *((enum cil_flavor *)curr->data);
- char *operand_str = NULL;
- switch (operand_flavor) {
- case CIL_CONS_U1:
- operand_str = CIL_KEY_CONS_U1;
- break;
- case CIL_CONS_U2:
- operand_str = CIL_KEY_CONS_U2;
- break;
- case CIL_CONS_U3:
- operand_str = CIL_KEY_CONS_U3;
- break;
- case CIL_CONS_T1:
- operand_str = CIL_KEY_CONS_T1;
- break;
- case CIL_CONS_T2:
- operand_str = CIL_KEY_CONS_T2;
- break;
- case CIL_CONS_T3:
- operand_str = CIL_KEY_CONS_T3;
- break;
- case CIL_CONS_R1:
- operand_str = CIL_KEY_CONS_R1;
- break;
- case CIL_CONS_R2:
- operand_str = CIL_KEY_CONS_R2;
- break;
- case CIL_CONS_R3:
- operand_str = CIL_KEY_CONS_R3;
- break;
- case CIL_CONS_L1:
- operand_str = CIL_KEY_CONS_L1;
- break;
- case CIL_CONS_L2:
- operand_str = CIL_KEY_CONS_L2;
- break;
- case CIL_CONS_H1:
- operand_str = CIL_KEY_CONS_H1;
- break;
- case CIL_CONS_H2:
- operand_str = CIL_KEY_CONS_H2;
- break;
- default:
- cil_log(CIL_ERR, "Unknown operand in expression\n");
- goto exit;
- break;
- }
- stack[pos] = operand_str;
- pos++;
- break;
- }
- default:
- cil_log(CIL_ERR, "Unknown flavor in expression\n");
- goto exit;
- break;
- }
- }
-
- *out = stack[0];
-
- return SEPOL_OK;
-
-exit:
- return rc;
-}
-
-void cil_tree_print_expr(struct cil_list *datum_expr, struct cil_list *str_expr)
-{
- char *expr_str;
- int rc;
-
- cil_log(CIL_INFO, "(");
-
- if (datum_expr != NULL) {
- rc = cil_expr_to_string(datum_expr, &expr_str);
- } else {
- rc = cil_expr_to_string(str_expr, &expr_str);
- }
- if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "ERROR)");
- return;
- }
- cil_log(CIL_INFO, "%s)", expr_str);
- free(expr_str);
-}
-
-void cil_tree_print_perms_list(struct cil_tree_node *current_perm)
-{
- while (current_perm != NULL) {
- if (current_perm->flavor == CIL_PERM) {
- cil_log(CIL_INFO, " %s", ((struct cil_perm *)current_perm->data)->datum.name);
- } else if (current_perm->flavor == CIL_MAP_PERM) {
- cil_log(CIL_INFO, " %s", ((struct cil_perm*)current_perm->data)->datum.name);
- } else {
- cil_log(CIL_INFO, "\n\n perms list contained unexpected data type: %d\n", current_perm->flavor);
- break;
- }
- current_perm = current_perm->next;
- }
-}
-
-void cil_tree_print_cats(struct cil_cats *cats)
-{
- cil_tree_print_expr(cats->datum_expr, cats->str_expr);
-}
-
-void cil_tree_print_perm_strs(struct cil_list *perm_strs)
-{
- struct cil_list_item *curr;
-
- if (perm_strs == NULL) {
- return;
- }
-
- cil_log(CIL_INFO, " (");
-
- cil_list_for_each(curr, perm_strs) {
- cil_log(CIL_INFO, " %s", (char*)curr->data);
- }
-
- cil_log(CIL_INFO, " )");
-}
-
-
-void cil_tree_print_classperms(struct cil_classperms *cp)
-{
- if (cp == NULL) {
- return;
- }
-
- cil_log(CIL_INFO, " class: %s", cp->class_str);
- cil_log(CIL_INFO, ", perm_strs:");
- cil_tree_print_perm_strs(cp->perm_strs);
-}
-
-void cil_tree_print_classperms_set(struct cil_classperms_set *cp_set)
-{
- if (cp_set == NULL) {
- return;
- }
-
- cil_log(CIL_INFO, " %s", cp_set->set_str);
-}
-
-void cil_tree_print_classperms_list(struct cil_list *cp_list)
-{
- struct cil_list_item *i;
-
- if (cp_list == NULL) {
- return;
- }
-
- cil_list_for_each(i, cp_list) {
- if (i->flavor == CIL_CLASSPERMS) {
- cil_tree_print_classperms(i->data);
- } else {
- cil_tree_print_classperms_set(i->data);
- }
- }
-}
-
-void cil_tree_print_level(struct cil_level *level)
-{
- if (level->sens != NULL) {
- cil_log(CIL_INFO, " %s", level->sens->datum.name);
- } else if (level->sens_str != NULL) {
- cil_log(CIL_INFO, " %s", level->sens_str);
- }
-
- cil_tree_print_cats(level->cats);
-
- return;
-}
-
-void cil_tree_print_levelrange(struct cil_levelrange *lvlrange)
-{
- cil_log(CIL_INFO, " (");
- if (lvlrange->low != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_level(lvlrange->low);
- cil_log(CIL_INFO, " )");
- } else if (lvlrange->low_str != NULL) {
- cil_log(CIL_INFO, " %s", lvlrange->low_str);
- }
-
- if (lvlrange->high != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_level(lvlrange->high);
- cil_log(CIL_INFO, " )");
- } else if (lvlrange->high_str != NULL) {
- cil_log(CIL_INFO, " %s", lvlrange->high_str);
- }
- cil_log(CIL_INFO, " )");
-}
-
-void cil_tree_print_context(struct cil_context *context)
-{
- cil_log(CIL_INFO, " (");
- if (context->user != NULL) {
- cil_log(CIL_INFO, " %s", context->user->datum.name);
- } else if (context->user_str != NULL) {
- cil_log(CIL_INFO, " %s", context->user_str);
- }
-
- if (context->role != NULL) {
- cil_log(CIL_INFO, " %s", context->role->datum.name);
- } else if (context->role_str != NULL) {
- cil_log(CIL_INFO, " %s", context->role_str);
- }
-
- if (context->type != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)context->type)->name);
- } else if (context->type_str != NULL) {
- cil_log(CIL_INFO, " %s", context->type_str);
- }
-
- if (context->range != NULL) {
- cil_tree_print_levelrange(context->range);
- } else if (context->range_str != NULL) {
- cil_log(CIL_INFO, " %s", context->range_str);
- }
-
- cil_log(CIL_INFO, " )");
-
- return;
-}
-
-void cil_tree_print_constrain(struct cil_constrain *cons)
-{
- cil_tree_print_classperms_list(cons->classperms);
-
- cil_tree_print_expr(cons->datum_expr, cons->str_expr);
-
- cil_log(CIL_INFO, "\n");
-}
-
-void cil_tree_print_node(struct cil_tree_node *node)
-{
- if (node->data == NULL) {
- cil_log(CIL_INFO, "FLAVOR: %d", node->flavor);
- return;
- } else {
- switch( node->flavor ) {
- case CIL_BLOCK: {
- struct cil_block *block = node->data;
- cil_log(CIL_INFO, "BLOCK: %s\n", block->datum.name);
- return;
- }
- case CIL_BLOCKINHERIT: {
- struct cil_blockinherit *inherit = node->data;
- cil_log(CIL_INFO, "BLOCKINHERIT: %s\n", inherit->block_str);
- return;
- }
- case CIL_BLOCKABSTRACT: {
- struct cil_blockabstract *abstract = node->data;
- cil_log(CIL_INFO, "BLOCKABSTRACT: %s\n", abstract->block_str);
- return;
- }
- case CIL_IN: {
- struct cil_in *in = node->data;
- cil_log(CIL_INFO, "IN: %s\n", in->block_str);
- return;
- }
- case CIL_USER: {
- struct cil_user *user = node->data;
- cil_log(CIL_INFO, "USER: %s\n", user->datum.name);
- return;
- }
- case CIL_TYPE: {
- struct cil_type *type = node->data;
- cil_log(CIL_INFO, "TYPE: %s\n", type->datum.name);
- return;
- }
- case CIL_EXPANDTYPEATTRIBUTE: {
- struct cil_expandtypeattribute *attr = node->data;
-
- cil_log(CIL_INFO, "(EXPANDTYPEATTRIBUTE ");
- cil_tree_print_expr(attr->attr_datums, attr->attr_strs);
- cil_log(CIL_INFO, "%s)\n",attr->expand ?
- CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE);
-
- return;
- }
- case CIL_TYPEATTRIBUTESET: {
- struct cil_typeattributeset *attr = node->data;
-
- cil_log(CIL_INFO, "(TYPEATTRIBUTESET %s ", attr->attr_str);
-
- cil_tree_print_expr(attr->datum_expr, attr->str_expr);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_TYPEATTRIBUTE: {
- struct cil_typeattribute *attr = node->data;
- cil_log(CIL_INFO, "TYPEATTRIBUTE: %s\n", attr->datum.name);
- return;
- }
- case CIL_ROLE: {
- struct cil_role *role = node->data;
- cil_log(CIL_INFO, "ROLE: %s\n", role->datum.name);
- return;
- }
- case CIL_USERROLE: {
- struct cil_userrole *userrole = node->data;
- cil_log(CIL_INFO, "USERROLE:");
- struct cil_symtab_datum *datum = NULL;
-
- if (userrole->user != NULL) {
- datum = userrole->user;
- cil_log(CIL_INFO, " %s", datum->name);
- } else if (userrole->user_str != NULL) {
- cil_log(CIL_INFO, " %s", userrole->user_str);
- }
-
- if (userrole->role != NULL) {
- datum = userrole->role;
- cil_log(CIL_INFO, " %s", datum->name);
- } else if (userrole->role_str != NULL) {
- cil_log(CIL_INFO, " %s", userrole->role_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_USERLEVEL: {
- struct cil_userlevel *usrlvl = node->data;
- cil_log(CIL_INFO, "USERLEVEL:");
-
- if (usrlvl->user_str != NULL) {
- cil_log(CIL_INFO, " %s", usrlvl->user_str);
- }
-
- if (usrlvl->level != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_level(usrlvl->level);
- cil_log(CIL_INFO, " )");
- } else if (usrlvl->level_str != NULL) {
- cil_log(CIL_INFO, " %s", usrlvl->level_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_USERRANGE: {
- struct cil_userrange *userrange = node->data;
- cil_log(CIL_INFO, "USERRANGE:");
-
- if (userrange->user_str != NULL) {
- cil_log(CIL_INFO, " %s", userrange->user_str);
- }
-
- if (userrange->range != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_levelrange(userrange->range);
- cil_log(CIL_INFO, " )");
- } else if (userrange->range_str != NULL) {
- cil_log(CIL_INFO, " %s", userrange->range_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_USERBOUNDS: {
- struct cil_bounds *bnds = node->data;
- cil_log(CIL_INFO, "USERBOUNDS: user: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
- return;
- }
- case CIL_ROLETYPE: {
- struct cil_roletype *roletype = node->data;
- struct cil_symtab_datum *datum = NULL;
- cil_log(CIL_INFO, "ROLETYPE:");
-
- if (roletype->role != NULL) {
- datum = roletype->role;
- cil_log(CIL_INFO, " %s", datum->name);
- } else if (roletype->role_str != NULL) {
- cil_log(CIL_INFO, " %s", roletype->role_str);
- }
-
- if (roletype->type != NULL) {
- datum = roletype->type;
- cil_log(CIL_INFO, " %s", datum->name);
- } else if (roletype->type_str != NULL) {
- cil_log(CIL_INFO, " %s", roletype->type_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_ROLETRANSITION: {
- struct cil_roletransition *roletrans = node->data;
- cil_log(CIL_INFO, "ROLETRANSITION:");
-
- if (roletrans->src != NULL) {
- cil_log(CIL_INFO, " %s", roletrans->src->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", roletrans->src_str);
- }
-
- if (roletrans->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)roletrans->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", roletrans->tgt_str);
- }
-
- if (roletrans->obj != NULL) {
- cil_log(CIL_INFO, " %s", roletrans->obj->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", roletrans->obj_str);
- }
-
- if (roletrans->result != NULL) {
- cil_log(CIL_INFO, " %s\n", roletrans->result->datum.name);
- } else {
- cil_log(CIL_INFO, " %s\n", roletrans->result_str);
- }
-
- return;
- }
- case CIL_ROLEALLOW: {
- struct cil_roleallow *roleallow = node->data;
- cil_log(CIL_INFO, "ROLEALLOW:");
-
- if (roleallow->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", roleallow->src_str);
- }
-
- if (roleallow->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", roleallow->tgt_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_ROLEATTRIBUTESET: {
- struct cil_roleattributeset *attr = node->data;
-
- cil_log(CIL_INFO, "(ROLEATTRIBUTESET %s ", attr->attr_str);
-
- cil_tree_print_expr(attr->datum_expr, attr->str_expr);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_ROLEATTRIBUTE: {
- struct cil_roleattribute *attr = node->data;
- cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name);
- return;
- }
- case CIL_USERATTRIBUTESET: {
- struct cil_userattributeset *attr = node->data;
-
- cil_log(CIL_INFO, "(USERATTRIBUTESET %s ", attr->attr_str);
-
- cil_tree_print_expr(attr->datum_expr, attr->str_expr);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_USERATTRIBUTE: {
- struct cil_userattribute *attr = node->data;
- cil_log(CIL_INFO, "USERATTRIBUTE: %s\n", attr->datum.name);
- return;
- }
- case CIL_ROLEBOUNDS: {
- struct cil_bounds *bnds = node->data;
- cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
- return;
- }
- case CIL_CLASS: {
- struct cil_class *cls = node->data;
- cil_log(CIL_INFO, "CLASS: %s ", cls->datum.name);
-
- if (cls->common != NULL) {
- cil_log(CIL_INFO, "inherits: %s ", cls->common->datum.name);
- }
- cil_log(CIL_INFO, "(");
-
- cil_tree_print_perms_list(node->cl_head);
-
- cil_log(CIL_INFO, " )");
- return;
- }
- case CIL_CLASSORDER: {
- struct cil_classorder *classorder = node->data;
- struct cil_list_item *class;
-
- if (classorder->class_list_str == NULL) {
- cil_log(CIL_INFO, "CLASSORDER: ()\n");
- return;
- }
-
- cil_log(CIL_INFO, "CLASSORDER: (");
- cil_list_for_each(class, classorder->class_list_str) {
- cil_log(CIL_INFO, " %s", (char*)class->data);
- }
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_COMMON: {
- struct cil_class *common = node->data;
- cil_log(CIL_INFO, "COMMON: %s (", common->datum.name);
-
- cil_tree_print_perms_list(node->cl_head);
-
- cil_log(CIL_INFO, " )");
- return;
- }
- case CIL_CLASSCOMMON: {
- struct cil_classcommon *clscom = node->data;
-
- cil_log(CIL_INFO, "CLASSCOMMON: class: %s, common: %s\n", clscom->class_str, clscom->common_str);
-
- return;
- }
- case CIL_CLASSPERMISSION: {
- struct cil_classpermission *cp = node->data;
-
- cil_log(CIL_INFO, "CLASSPERMISSION: %s", cp->datum.name);
-
- cil_log(CIL_INFO, "\n");
-
- return;
- }
- case CIL_CLASSPERMISSIONSET: {
- struct cil_classpermissionset *cps = node->data;
-
- cil_log(CIL_INFO, "CLASSPERMISSIONSET: %s", cps->set_str);
-
- cil_tree_print_classperms_list(cps->classperms);
-
- cil_log(CIL_INFO, "\n");
-
- return;
- }
- case CIL_MAP_CLASS: {
- struct cil_class *cm = node->data;
- cil_log(CIL_INFO, "MAP_CLASS: %s", cm->datum.name);
-
- cil_log(CIL_INFO, " (");
- cil_tree_print_perms_list(node->cl_head);
- cil_log(CIL_INFO, " )\n");
-
- return;
- }
- case CIL_MAP_PERM: {
- struct cil_perm *cmp = node->data;
-
- cil_log(CIL_INFO, "MAP_PERM: %s", cmp->datum.name);
-
- if (cmp->classperms == NULL) {
- cil_log(CIL_INFO, " perms: ()");
- return;
- }
-
- cil_log(CIL_INFO, " kernel class perms: (");
-
- cil_tree_print_classperms_list(cmp->classperms);
-
- cil_log(CIL_INFO, " )\n");
-
- return;
- }
- case CIL_CLASSMAPPING: {
- struct cil_classmapping *mapping = node->data;
-
- cil_log(CIL_INFO, "CLASSMAPPING: map class: %s, map perm: %s,", mapping->map_class_str, mapping->map_perm_str);
-
- cil_log(CIL_INFO, " (");
-
- cil_tree_print_classperms_list(mapping->classperms);
-
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_BOOL: {
- struct cil_bool *boolean = node->data;
- cil_log(CIL_INFO, "BOOL: %s, value: %d\n", boolean->datum.name, boolean->value);
- return;
- }
- case CIL_TUNABLE: {
- struct cil_tunable *tunable = node->data;
- cil_log(CIL_INFO, "TUNABLE: %s, value: %d\n", tunable->datum.name, tunable->value);
- return;
- }
- case CIL_BOOLEANIF: {
- struct cil_booleanif *bif = node->data;
-
- cil_log(CIL_INFO, "(BOOLEANIF ");
-
- cil_tree_print_expr(bif->datum_expr, bif->str_expr);
-
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_TUNABLEIF: {
- struct cil_tunableif *tif = node->data;
-
- cil_log(CIL_INFO, "(TUNABLEIF ");
-
- cil_tree_print_expr(tif->datum_expr, tif->str_expr);
-
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_CONDBLOCK: {
- struct cil_condblock *cb = node->data;
- if (cb->flavor == CIL_CONDTRUE) {
- cil_log(CIL_INFO, "true\n");
- } else if (cb->flavor == CIL_CONDFALSE) {
- cil_log(CIL_INFO, "false\n");
- }
- return;
- }
- case CIL_ALL:
- cil_log(CIL_INFO, "all");
- return;
- case CIL_AND:
- cil_log(CIL_INFO, "&&");
- return;
- case CIL_OR:
- cil_log(CIL_INFO, "|| ");
- return;
- case CIL_NOT:
- cil_log(CIL_INFO, "!");
- return;
- case CIL_EQ:
- cil_log(CIL_INFO, "==");
- return;
- case CIL_NEQ:
- cil_log(CIL_INFO, "!=");
- return;
- case CIL_TYPEALIAS: {
- struct cil_alias *alias = node->data;
- cil_log(CIL_INFO, "TYPEALIAS: %s\n", alias->datum.name);
- return;
- }
- case CIL_TYPEALIASACTUAL: {
- struct cil_aliasactual *aliasactual = node->data;
- cil_log(CIL_INFO, "TYPEALIASACTUAL: type: %s, alias: %s\n", aliasactual->alias_str, aliasactual->actual_str);
- return;
- }
- case CIL_TYPEBOUNDS: {
- struct cil_bounds *bnds = node->data;
- cil_log(CIL_INFO, "TYPEBOUNDS: type: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
- return;
- }
- case CIL_TYPEPERMISSIVE: {
- struct cil_typepermissive *typeperm = node->data;
-
- if (typeperm->type != NULL) {
- cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", ((struct cil_symtab_datum *)typeperm->type)->name);
- } else {
- cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", typeperm->type_str);
- }
-
- return;
- }
- case CIL_NAMETYPETRANSITION: {
- struct cil_nametypetransition *nametypetrans = node->data;
- cil_log(CIL_INFO, "TYPETRANSITION:");
-
- if (nametypetrans->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", nametypetrans->src_str);
- }
-
- if (nametypetrans->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", nametypetrans->tgt_str);
- }
-
- if (nametypetrans->obj != NULL) {
- cil_log(CIL_INFO, " %s", nametypetrans->obj->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", nametypetrans->obj_str);
- }
-
- cil_log(CIL_INFO, " %s\n", nametypetrans->name_str);
-
- if (nametypetrans->result != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->result)->name);
- } else {
- cil_log(CIL_INFO, " %s", nametypetrans->result_str);
- }
-
- return;
- }
- case CIL_RANGETRANSITION: {
- struct cil_rangetransition *rangetrans = node->data;
- cil_log(CIL_INFO, "RANGETRANSITION:");
-
- if (rangetrans->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", rangetrans->src_str);
- }
-
- if (rangetrans->exec != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->exec)->name);
- } else {
- cil_log(CIL_INFO, " %s", rangetrans->exec_str);
- }
-
- if (rangetrans->obj != NULL) {
- cil_log(CIL_INFO, " %s", rangetrans->obj->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", rangetrans->obj_str);
- }
-
- if (rangetrans->range != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_levelrange(rangetrans->range);
- cil_log(CIL_INFO, " )");
- } else {
- cil_log(CIL_INFO, " %s", rangetrans->range_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_AVRULE: {
- struct cil_avrule *rule = node->data;
- switch (rule->rule_kind) {
- case CIL_AVRULE_ALLOWED:
- cil_log(CIL_INFO, "ALLOW:");
- break;
- case CIL_AVRULE_AUDITALLOW:
- cil_log(CIL_INFO, "AUDITALLOW:");
- break;
- case CIL_AVRULE_DONTAUDIT:
- cil_log(CIL_INFO, "DONTAUDIT:");
- break;
- case CIL_AVRULE_NEVERALLOW:
- cil_log(CIL_INFO, "NEVERALLOW:");
- break;
- }
-
- if (rule->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", rule->src_str);
- }
-
- if (rule->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", rule->tgt_str);
- }
-
- cil_tree_print_classperms_list(rule->perms.classperms);
-
- cil_log(CIL_INFO, "\n");
-
- return;
- }
- case CIL_TYPE_RULE: {
- struct cil_type_rule *rule = node->data;
- switch (rule->rule_kind) {
- case CIL_TYPE_TRANSITION:
- cil_log(CIL_INFO, "TYPETRANSITION:");
- break;
- case CIL_TYPE_MEMBER:
- cil_log(CIL_INFO, "TYPEMEMBER:");
- break;
- case CIL_TYPE_CHANGE:
- cil_log(CIL_INFO, "TYPECHANGE:");
- break;
- }
-
- if (rule->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", rule->src_str);
- }
-
- if (rule->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", rule->tgt_str);
- }
-
- if (rule->obj != NULL) {
- cil_log(CIL_INFO, " %s", rule->obj->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", rule->obj_str);
- }
-
- if (rule->result != NULL) {
- cil_log(CIL_INFO, " %s\n", ((struct cil_symtab_datum *)rule->result)->name);
- } else {
- cil_log(CIL_INFO, " %s\n", rule->result_str);
- }
-
- return;
- }
- case CIL_SENS: {
- struct cil_sens *sens = node->data;
- cil_log(CIL_INFO, "SENSITIVITY: %s\n", sens->datum.name);
- return;
- }
- case CIL_SENSALIAS: {
- struct cil_alias *alias = node->data;
- cil_log(CIL_INFO, "SENSITIVITYALIAS: %s\n", alias->datum.name);
- return;
- }
- case CIL_SENSALIASACTUAL: {
- struct cil_aliasactual *aliasactual = node->data;
- cil_log(CIL_INFO, "SENSITIVITYALIAS: alias: %s, sensitivity: %s\n", aliasactual->alias_str, aliasactual->actual_str);
-
- return;
- }
- case CIL_CAT: {
- struct cil_cat *cat = node->data;
- cil_log(CIL_INFO, "CATEGORY: %s\n", cat->datum.name);
- return;
- }
- case CIL_CATALIAS: {
- struct cil_alias *alias = node->data;
- cil_log(CIL_INFO, "CATEGORYALIAS: %s\n", alias->datum.name);
- return;
- }
- case CIL_CATALIASACTUAL: {
- struct cil_aliasactual *aliasactual = node->data;
- cil_log(CIL_INFO, "CATEGORYALIAS: alias %s, category: %s\n", aliasactual->alias_str, aliasactual->actual_str);
- return;
- }
- case CIL_CATSET: {
- struct cil_catset *catset = node->data;
-
- cil_log(CIL_INFO, "CATSET: %s ",catset->datum.name);
-
- cil_tree_print_cats(catset->cats);
-
- return;
- }
- case CIL_CATORDER: {
- struct cil_catorder *catorder = node->data;
- struct cil_list_item *cat;
-
- if (catorder->cat_list_str == NULL) {
- cil_log(CIL_INFO, "CATORDER: ()\n");
- return;
- }
-
- cil_log(CIL_INFO, "CATORDER: (");
- cil_list_for_each(cat, catorder->cat_list_str) {
- cil_log(CIL_INFO, " %s", (char*)cat->data);
- }
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_SENSCAT: {
- struct cil_senscat *senscat = node->data;
-
- cil_log(CIL_INFO, "SENSCAT: sens:");
-
- if (senscat->sens_str != NULL) {
- cil_log(CIL_INFO, " %s ", senscat->sens_str);
- } else {
- cil_log(CIL_INFO, " [processed]");
- }
-
- cil_tree_print_cats(senscat->cats);
-
- return;
- }
- case CIL_SENSITIVITYORDER: {
- struct cil_sensorder *sensorder = node->data;
- struct cil_list_item *sens;
-
- cil_log(CIL_INFO, "SENSITIVITYORDER: (");
-
- if (sensorder->sens_list_str != NULL) {
- cil_list_for_each(sens, sensorder->sens_list_str) {
- if (sens->flavor == CIL_LIST) {
- struct cil_list_item *sub;
- cil_log(CIL_INFO, " (");
- cil_list_for_each(sub, (struct cil_list*)sens->data) {
- cil_log(CIL_INFO, " %s", (char*)sub->data);
- }
- cil_log(CIL_INFO, " )");
- } else {
- cil_log(CIL_INFO, " %s", (char*)sens->data);
- }
- }
- }
-
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_LEVEL: {
- struct cil_level *level = node->data;
- cil_log(CIL_INFO, "LEVEL %s:", level->datum.name);
- cil_tree_print_level(level);
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_LEVELRANGE: {
- struct cil_levelrange *lvlrange = node->data;
- cil_log(CIL_INFO, "LEVELRANGE %s:", lvlrange->datum.name);
- cil_tree_print_levelrange(lvlrange);
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_CONSTRAIN: {
- struct cil_constrain *cons = node->data;
- cil_log(CIL_INFO, "CONSTRAIN: (");
- cil_tree_print_constrain(cons);
- return;
- }
- case CIL_MLSCONSTRAIN: {
- struct cil_constrain *cons = node->data;
- cil_log(CIL_INFO, "MLSCONSTRAIN: (");
- cil_tree_print_constrain(cons);
- return;
- }
- case CIL_VALIDATETRANS: {
- struct cil_validatetrans *vt = node->data;
-
- cil_log(CIL_INFO, "(VALIDATETRANS ");
-
- if (vt->class != NULL) {
- cil_log(CIL_INFO, "%s ", vt->class->datum.name);
- } else if (vt->class_str != NULL) {
- cil_log(CIL_INFO, "%s ", vt->class_str);
- }
-
- cil_tree_print_expr(vt->datum_expr, vt->str_expr);
-
- cil_log(CIL_INFO, ")\n");
- return;
- }
- case CIL_MLSVALIDATETRANS: {
- struct cil_validatetrans *vt = node->data;
-
- cil_log(CIL_INFO, "(MLSVALIDATETRANS ");
-
- if (vt->class != NULL) {
- cil_log(CIL_INFO, "%s ", vt->class->datum.name);
- } else if (vt->class_str != NULL) {
- cil_log(CIL_INFO, "%s ", vt->class_str);
- }
-
- cil_tree_print_expr(vt->datum_expr, vt->str_expr);
-
- cil_log(CIL_INFO, ")\n");
- return;
- }
- case CIL_CONTEXT: {
- struct cil_context *context = node->data;
- cil_log(CIL_INFO, "CONTEXT %s:", context->datum.name);
- cil_tree_print_context(context);
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_FILECON: {
- struct cil_filecon *filecon = node->data;
- cil_log(CIL_INFO, "FILECON:");
- cil_log(CIL_INFO, " %s %d", filecon->path_str, filecon->type);
-
- if (filecon->context != NULL) {
- cil_tree_print_context(filecon->context);
- } else if (filecon->context_str != NULL) {
- cil_log(CIL_INFO, " %s", filecon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
-
- }
- case CIL_IBPKEYCON: {
- struct cil_ibpkeycon *ibpkeycon = node->data;
-
- cil_log(CIL_INFO, "IBPKEYCON: %s", ibpkeycon->subnet_prefix_str);
- cil_log(CIL_INFO, " (%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high);
-
- if (ibpkeycon->context)
- cil_tree_print_context(ibpkeycon->context);
- else if (ibpkeycon->context_str)
- cil_log(CIL_INFO, " %s", ibpkeycon->context_str);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_PORTCON: {
- struct cil_portcon *portcon = node->data;
- cil_log(CIL_INFO, "PORTCON:");
- if (portcon->proto == CIL_PROTOCOL_UDP) {
- cil_log(CIL_INFO, " udp");
- } else if (portcon->proto == CIL_PROTOCOL_TCP) {
- cil_log(CIL_INFO, " tcp");
- } else if (portcon->proto == CIL_PROTOCOL_DCCP) {
- cil_log(CIL_INFO, " dccp");
- } else if (portcon->proto == CIL_PROTOCOL_SCTP) {
- cil_log(CIL_INFO, " sctp");
- }
- cil_log(CIL_INFO, " (%d %d)", portcon->port_low, portcon->port_high);
-
- if (portcon->context != NULL) {
- cil_tree_print_context(portcon->context);
- } else if (portcon->context_str != NULL) {
- cil_log(CIL_INFO, " %s", portcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_NODECON: {
- struct cil_nodecon *nodecon = node->data;
- char buf[256];
-
- cil_log(CIL_INFO, "NODECON:");
-
- if (nodecon->addr) {
- inet_ntop(nodecon->addr->family, &nodecon->addr->ip, buf, 256);
- cil_log(CIL_INFO, " %s", buf);
- } else {
- cil_log(CIL_INFO, " %s", nodecon->addr_str);
- }
-
- if (nodecon->mask) {
- inet_ntop(nodecon->mask->family, &nodecon->mask->ip, buf, 256);
- cil_log(CIL_INFO, " %s", buf);
- } else {
- cil_log(CIL_INFO, " %s", nodecon->mask_str);
- }
-
- if (nodecon->context != NULL) {
- cil_tree_print_context(nodecon->context);
- } else if (nodecon->context_str != NULL) {
- cil_log(CIL_INFO, " %s", nodecon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_GENFSCON: {
- struct cil_genfscon *genfscon = node->data;
- cil_log(CIL_INFO, "GENFSCON:");
- cil_log(CIL_INFO, " %s %s", genfscon->fs_str, genfscon->path_str);
-
- if (genfscon->context != NULL) {
- cil_tree_print_context(genfscon->context);
- } else if (genfscon->context_str != NULL) {
- cil_log(CIL_INFO, " %s", genfscon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_NETIFCON: {
- struct cil_netifcon *netifcon = node->data;
- cil_log(CIL_INFO, "NETIFCON %s", netifcon->interface_str);
-
- if (netifcon->if_context != NULL) {
- cil_tree_print_context(netifcon->if_context);
- } else if (netifcon->if_context_str != NULL) {
- cil_log(CIL_INFO, " %s", netifcon->if_context_str);
- }
-
- if (netifcon->packet_context != NULL) {
- cil_tree_print_context(netifcon->packet_context);
- } else if (netifcon->packet_context_str != NULL) {
- cil_log(CIL_INFO, " %s", netifcon->packet_context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_IBENDPORTCON: {
- struct cil_ibendportcon *ibendportcon = node->data;
-
- cil_log(CIL_INFO, "IBENDPORTCON: %s %u ", ibendportcon->dev_name_str, ibendportcon->port);
-
- if (ibendportcon->context)
- cil_tree_print_context(ibendportcon->context);
- else if (ibendportcon->context_str)
- cil_log(CIL_INFO, " %s", ibendportcon->context_str);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_PIRQCON: {
- struct cil_pirqcon *pirqcon = node->data;
-
- cil_log(CIL_INFO, "PIRQCON %d", pirqcon->pirq);
- if (pirqcon->context != NULL) {
- cil_tree_print_context(pirqcon->context);
- } else {
- cil_log(CIL_INFO, " %s", pirqcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_IOMEMCON: {
- struct cil_iomemcon *iomemcon = node->data;
-
- cil_log(CIL_INFO, "IOMEMCON ( %"PRId64" %"PRId64" )", iomemcon->iomem_low, iomemcon->iomem_high);
- if (iomemcon->context != NULL) {
- cil_tree_print_context(iomemcon->context);
- } else {
- cil_log(CIL_INFO, " %s", iomemcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_IOPORTCON: {
- struct cil_ioportcon *ioportcon = node->data;
-
- cil_log(CIL_INFO, "IOPORTCON ( %d %d )", ioportcon->ioport_low, ioportcon->ioport_high);
- if (ioportcon->context != NULL) {
- cil_tree_print_context(ioportcon->context);
- } else {
- cil_log(CIL_INFO, " %s", ioportcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_PCIDEVICECON: {
- struct cil_pcidevicecon *pcidevicecon = node->data;
-
- cil_log(CIL_INFO, "PCIDEVICECON %d", pcidevicecon->dev);
- if (pcidevicecon->context != NULL) {
- cil_tree_print_context(pcidevicecon->context);
- } else {
- cil_log(CIL_INFO, " %s", pcidevicecon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_DEVICETREECON: {
- struct cil_devicetreecon *devicetreecon = node->data;
-
- cil_log(CIL_INFO, "DEVICETREECON %s", devicetreecon->path);
- if (devicetreecon->context != NULL) {
- cil_tree_print_context(devicetreecon->context);
- } else {
- cil_log(CIL_INFO, " %s", devicetreecon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_FSUSE: {
- struct cil_fsuse *fsuse = node->data;
- cil_log(CIL_INFO, "FSUSE: ");
-
- if (fsuse->type == CIL_FSUSE_XATTR) {
- cil_log(CIL_INFO, "xattr ");
- } else if (fsuse->type == CIL_FSUSE_TASK) {
- cil_log(CIL_INFO, "task ");
- } else if (fsuse->type == CIL_FSUSE_TRANS) {
- cil_log(CIL_INFO, "trans ");
- } else {
- cil_log(CIL_INFO, "unknown ");
- }
-
- cil_log(CIL_INFO, "%s ", fsuse->fs_str);
-
- if (fsuse->context != NULL) {
- cil_tree_print_context(fsuse->context);
- } else {
- cil_log(CIL_INFO, " %s", fsuse->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_SID: {
- struct cil_sid *sid = node->data;
- cil_log(CIL_INFO, "SID: %s\n", sid->datum.name);
- return;
- }
- case CIL_SIDCONTEXT: {
- struct cil_sidcontext *sidcon = node->data;
- cil_log(CIL_INFO, "SIDCONTEXT: %s", sidcon->sid_str);
-
- if (sidcon->context != NULL) {
- cil_tree_print_context(sidcon->context);
- } else {
- cil_log(CIL_INFO, " %s", sidcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_SIDORDER: {
- struct cil_sidorder *sidorder = node->data;
- struct cil_list_item *sid;
-
- if (sidorder->sid_list_str == NULL) {
- cil_log(CIL_INFO, "SIDORDER: ()\n");
- return;
- }
-
- cil_log(CIL_INFO, "SIDORDER: (");
- cil_list_for_each(sid, sidorder->sid_list_str) {
- cil_log(CIL_INFO, " %s", (char*)sid->data);
- }
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_POLICYCAP: {
- struct cil_policycap *polcap = node->data;
- cil_log(CIL_INFO, "POLICYCAP: %s\n", polcap->datum.name);
- return;
- }
- case CIL_MACRO: {
- struct cil_macro *macro = node->data;
- cil_log(CIL_INFO, "MACRO %s:", macro->datum.name);
-
- if (macro->params != NULL && macro->params->head != NULL) {
- struct cil_list_item *curr_param;
- cil_log(CIL_INFO, " parameters: (");
- cil_list_for_each(curr_param, macro->params) {
- cil_log(CIL_INFO, " flavor: %d, string: %s;", ((struct cil_param*)curr_param->data)->flavor, ((struct cil_param*)curr_param->data)->str);
-
- }
- cil_log(CIL_INFO, " )");
- }
- cil_log(CIL_INFO, "\n");
-
- return;
- }
- case CIL_CALL: {
- struct cil_call *call = node->data;
- cil_log(CIL_INFO, "CALL: macro name:");
-
- if (call->macro != NULL) {
- cil_log(CIL_INFO, " %s", call->macro->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", call->macro_str);
- }
-
- if (call->args != NULL) {
- cil_log(CIL_INFO, ", args: ( ");
- struct cil_list_item *item;
- cil_list_for_each(item, call->args) {
- struct cil_symtab_datum *datum = ((struct cil_args*)item->data)->arg;
- if (datum != NULL) {
- if (datum->nodes != NULL && datum->nodes->head != NULL) {
- cil_tree_print_node(NODE(datum));
- }
- } else if (((struct cil_args*)item->data)->arg_str != NULL) {
- switch (item->flavor) {
- case CIL_TYPE: cil_log(CIL_INFO, "type:"); break;
- case CIL_USER: cil_log(CIL_INFO, "user:"); break;
- case CIL_ROLE: cil_log(CIL_INFO, "role:"); break;
- case CIL_SENS: cil_log(CIL_INFO, "sensitivity:"); break;
- case CIL_CAT: cil_log(CIL_INFO, "category:"); break;
- case CIL_CATSET: cil_log(CIL_INFO, "categoryset:"); break;
- case CIL_LEVEL: cil_log(CIL_INFO, "level:"); break;
- case CIL_CLASS: cil_log(CIL_INFO, "class:"); break;
- default: break;
- }
- cil_log(CIL_INFO, "%s ", ((struct cil_args*)item->data)->arg_str);
- }
- }
- cil_log(CIL_INFO, ")");
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_OPTIONAL: {
- struct cil_optional *optional = node->data;
- cil_log(CIL_INFO, "OPTIONAL: %s\n", optional->datum.name);
- return;
- }
- case CIL_IPADDR: {
- struct cil_ipaddr *ipaddr = node->data;
- char buf[256];
-
- inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256);
- cil_log(CIL_INFO, "IPADDR %s: %s\n", ipaddr->datum.name, buf);
-
- break;
- }
- default : {
- cil_log(CIL_INFO, "CIL FLAVOR: %d\n", node->flavor);
- return;
- }
- }
- }
-}
-
-void cil_tree_print(struct cil_tree_node *tree, uint32_t depth)
-{
- struct cil_tree_node *current = NULL;
- current = tree;
- uint32_t x = 0;
-
- if (current != NULL) {
- if (current->cl_head == NULL) {
- if (current->flavor == CIL_NODE) {
- if (current->parent->cl_head == current) {
- cil_log(CIL_INFO, "%s", (char*)current->data);
- } else {
- cil_log(CIL_INFO, " %s", (char*)current->data);
- }
- } else if (current->flavor != CIL_PERM) {
- for (x = 0; xparent != NULL) {
- cil_log(CIL_INFO, "\n");
- for (x = 0; xflavor != CIL_NODE) {
- cil_tree_print_node(current);
- }
- }
- cil_tree_print(current->cl_head, depth + 1);
- }
-
- if (current->next == NULL) {
- if ((current->parent != NULL) && (current->parent->cl_tail == current) && (current->parent->parent != NULL)) {
- if (current->flavor == CIL_PERM) {
- cil_log(CIL_INFO, ")\n");
- } else if (current->flavor != CIL_NODE) {
- for (x = 0; xparent != NULL) && (current->parent->parent == NULL))
- cil_log(CIL_INFO, "\n\n");
- } else {
- cil_tree_print(current->next, depth);
- }
- } else {
- cil_log(CIL_INFO, "Tree is NULL\n");
- }
-}
diff --git a/libsepol/cil/src/cil_tree.h b/libsepol/cil/src/cil_tree.h
index aeded5608239c81b8a6a77ae3aca12fa64258119..5a98da558cc0e082b346bec93d9ef7c4cc10b3d3 100644
--- a/libsepol/cil/src/cil_tree.h
+++ b/libsepol/cil/src/cil_tree.h
@@ -46,14 +46,16 @@ struct cil_tree_node {
struct cil_tree_node *next; //Each element in the list points to the next element
enum cil_flavor flavor;
uint32_t line;
- uint32_t hll_line;
+ uint32_t hll_offset;
void *data;
};
-struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil);
+struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path);
char *cil_tree_get_cil_path(struct cil_tree_node *node);
__attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...);
+int cil_tree_subtree_has_decl(struct cil_tree_node *node);
+
int cil_tree_init(struct cil_tree **tree);
void cil_tree_destroy(struct cil_tree **tree);
void cil_tree_subtree_destroy(struct cil_tree_node *node);
@@ -62,8 +64,6 @@ void cil_tree_children_destroy(struct cil_tree_node *node);
void cil_tree_node_init(struct cil_tree_node **node);
void cil_tree_node_destroy(struct cil_tree_node **node);
-void cil_tree_print(struct cil_tree_node *tree, uint32_t depth);
-
//finished values
#define CIL_TREE_SKIP_NOTHING 0
#define CIL_TREE_SKIP_NEXT 1
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 6706e21921fee896833026fbd622bded37fb9c4b..d994d717d52963fab38290ba125c91c21756d9d4 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -44,10 +44,55 @@
#include "cil_tree.h"
#include "cil_list.h"
#include "cil_find.h"
+#include "cil_stack.h"
#include "cil_verify.h"
-int __cil_verify_name(const char *name)
+static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
+{
+ switch (flavor) {
+ case CIL_BOOL:
+ case CIL_TUNABLE:
+ if ((name == CIL_KEY_EQ) || (name == CIL_KEY_NEQ))
+ return CIL_TRUE;
+ break;
+ case CIL_PERM:
+ case CIL_MAP_PERM:
+ case CIL_USER:
+ case CIL_USERATTRIBUTE:
+ case CIL_ROLE:
+ case CIL_ROLEATTRIBUTE:
+ if (name == CIL_KEY_ALL)
+ return CIL_TRUE;
+ break;
+ case CIL_TYPE:
+ case CIL_TYPEATTRIBUTE:
+ case CIL_TYPEALIAS:
+ if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF))
+ return CIL_TRUE;
+ break;
+ case CIL_CAT:
+ case CIL_CATSET:
+ case CIL_CATALIAS:
+ case CIL_PERMISSIONX:
+ if ((name == CIL_KEY_ALL) || (name == CIL_KEY_RANGE))
+ return CIL_TRUE;
+ break;
+ default:
+ /* All of these are not used in expressions */
+ return CIL_FALSE;
+ break;
+ }
+
+ /* Everything not under the default case is also checked for these */
+ if ((name == CIL_KEY_AND) || (name == CIL_KEY_OR) || (name == CIL_KEY_NOT) || (name == CIL_KEY_XOR)) {
+ return CIL_TRUE;
+ }
+
+ return CIL_FALSE;
+}
+
+int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor)
{
int rc = SEPOL_ERR;
int len;
@@ -71,12 +116,27 @@ int __cil_verify_name(const char *name)
goto exit;
}
- for (i = 1; i < len; i++) {
- if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
- cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
- goto exit;
+ if (db->qualified_names == CIL_FALSE) {
+ for (i = 1; i < len; i++) {
+ if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
+ cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
+ goto exit;
+ }
+ }
+ } else {
+ for (i = 1; i < len; i++) {
+ if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-' && name[i] != '.') {
+ cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
+ goto exit;
+ }
}
}
+
+ if (__cil_is_reserved_name(name, flavor)) {
+ cil_log(CIL_ERR, "Name %s is a reserved word\n", name);
+ goto exit;
+ }
+
return SEPOL_OK;
exit:
@@ -84,70 +144,45 @@ exit:
return rc;
}
-int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len)
+int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t len)
{
- int rc = SEPOL_ERR;
- int num_extras = 0;
struct cil_tree_node *c = parse_current;
- int i = 0;
- while (i < len) {
- if ((s[i] & CIL_SYN_END) && c == NULL) {
- break;
- }
-
- if (s[i] & CIL_SYN_N_LISTS || s[i] & CIL_SYN_N_STRINGS) {
- if (c == NULL) {
- if (num_extras > 0) {
- i++;
- continue;
+ size_t i = 0;
+
+ while (i < len && c != NULL) {
+ if ((s[i] & CIL_SYN_STRING) && c->data != NULL && c->cl_head == NULL) {
+ c = c->next;
+ i++;
+ } else if ((s[i] & CIL_SYN_LIST) && c->data == NULL && c->cl_head != NULL) {
+ c = c->next;
+ i++;
+ } else if ((s[i] & CIL_SYN_EMPTY_LIST) && c->data == NULL && c->cl_head == NULL) {
+ c = c->next;
+ i++;
+ } else if ((s[i] & CIL_SYN_N_LISTS) || (s[i] & CIL_SYN_N_STRINGS)) {
+ while (c != NULL) {
+ if ((s[i] & CIL_SYN_N_LISTS) && c->data == NULL && c->cl_head != NULL) {
+ c = c->next;
+ } else if ((s[i] & CIL_SYN_N_STRINGS) && c->data != NULL && c->cl_head == NULL) {
+ c = c->next;
} else {
goto exit;
}
- } else if ((s[i] & CIL_SYN_N_LISTS) && (c->data == NULL && c->cl_head != NULL)) {
- c = c->next;
- num_extras++;
- continue;
- } else if ((s[i] & CIL_SYN_N_STRINGS) && (c->data != NULL && c->cl_head == NULL)) {
- c = c->next;
- num_extras++;
- continue;
}
- }
-
- if (c == NULL) {
+ i++;
+ break; /* Only CIL_SYN_END allowed after these */
+ } else {
goto exit;
}
+ }
- if (s[i] & CIL_SYN_STRING) {
- if (c->data != NULL && c->cl_head == NULL) {
- c = c->next;
- i++;
- continue;
- }
- }
-
- if (s[i] & CIL_SYN_LIST) {
- if (c->data == NULL && c->cl_head != NULL) {
- c = c->next;
- i++;
- continue;
- }
- }
-
- if (s[i] & CIL_SYN_EMPTY_LIST) {
- if (c->data == NULL && c->cl_head == NULL) {
- c = c->next;
- i++;
- continue;
- }
- }
- goto exit;
+ if (i < len && (s[i] & CIL_SYN_END) && c == NULL) {
+ return SEPOL_OK;
}
- return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Invalid syntax\n");
- return rc;
+ return SEPOL_ERR;
}
int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor)
@@ -225,12 +260,15 @@ int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_fl
cil_log(CIL_ERR, "u3, r3, and t3 can only be used with (mls)validatetrans rules\n");
goto exit;
}
- } else if (r_flavor == CIL_LIST) {
- cil_log(CIL_ERR, "t1, t2, r1, r2, u1, u2 cannot be used on the left side with a list on the right side\n");
- goto exit;
}
} else {
- if (r_flavor == CIL_CONS_U2) {
+ if (r_flavor == CIL_CONS_U1 || r_flavor == CIL_CONS_R1 || r_flavor == CIL_CONS_T1) {
+ cil_log(CIL_ERR, "u1, r1, and t1 are not allowed on the right side\n");
+ goto exit;
+ } else if (r_flavor == CIL_CONS_U3 || r_flavor == CIL_CONS_R3 || r_flavor == CIL_CONS_T3) {
+ cil_log(CIL_ERR, "u3, r3, and t3 are not allowed on the right side\n");
+ goto exit;
+ } else if (r_flavor == CIL_CONS_U2) {
if (op != CIL_EQ && op != CIL_NEQ) {
cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n");
goto exit;
@@ -359,28 +397,100 @@ int cil_verify_conditional_blocks(struct cil_tree_node *current)
return SEPOL_OK;
}
-int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list)
+int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name)
{
- struct cil_list_item *i;
-
- cil_list_for_each(i, datum_list) {
- if (i->flavor == CIL_DATUM) {
- struct cil_symtab_datum *d = i->data;
- if (d == datum) {
- cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name);
- return SEPOL_ERR;
- }
- } else if (i->flavor == CIL_LIST) {
- int rc = cil_verify_no_self_reference(datum, i->data);
- if (rc != SEPOL_OK) {
- return SEPOL_ERR;
+ struct cil_list_item *item;
+ struct cil_list *param_list = macro->params;
+ if (param_list != NULL) {
+ cil_list_for_each(item, param_list) {
+ struct cil_param *param = item->data;
+ if (param->flavor == node->flavor) {
+ if (param->str == name) {
+ cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(node), name);
+ return SEPOL_ERR;
+ }
}
}
}
+ return SEPOL_OK;
+}
+
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack);
+
+static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_stack *stack)
+{
+ struct cil_list_item *item;
+ int rc = SEPOL_OK;
+
+ if (!expr) {
+ return SEPOL_OK;
+ }
+
+ cil_list_for_each(item, expr) {
+ if (item->flavor == CIL_DATUM) {
+ struct cil_symtab_datum* datum = item->data;
+ rc = cil_verify_no_self_reference(FLAVOR(datum), datum, stack);
+ } else if (item->flavor == CIL_LIST) {
+ rc = __verify_no_self_reference_in_expr(item->data, stack);
+ }
+ if (rc != SEPOL_OK) {
+ return SEPOL_ERR;
+ }
+ }
return SEPOL_OK;
}
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack)
+{
+ struct cil_stack_item *item;
+ int i = 0;
+ int rc = SEPOL_OK;
+
+ cil_stack_for_each(stack, i, item) {
+ struct cil_symtab_datum *prev = item->data;
+ if (datum == prev) {
+ cil_tree_log(NODE(datum), CIL_ERR, "Self-reference found for %s", datum->name);
+ return SEPOL_ERR;
+ }
+ }
+
+ switch (flavor) {
+ case CIL_USERATTRIBUTE: {
+ struct cil_userattribute *attr = (struct cil_userattribute *)datum;
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
+ break;
+ }
+ case CIL_ROLEATTRIBUTE: {
+ struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
+ break;
+ }
+ case CIL_TYPEATTRIBUTE: {
+ struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
+ break;
+ }
+ case CIL_CATSET: {
+ struct cil_catset *set = (struct cil_catset *)datum;
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, stack);
+ cil_stack_pop(stack);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return rc;
+}
+
int __cil_verify_ranges(struct cil_list *list)
{
int rc = SEPOL_ERR;
@@ -1579,6 +1689,15 @@ exit:
return rc;
}
+static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ struct cil_list *perm_list = (struct cil_list *)args;
+
+ cil_list_append(perm_list, CIL_DATUM, d);
+
+ return SEPOL_OK;
+}
+
static int __cil_verify_classperms(struct cil_list *classperms,
struct cil_symtab_datum *orig,
struct cil_symtab_datum *parent,
@@ -1620,13 +1739,34 @@ static int __cil_verify_classperms(struct cil_list *classperms,
if (FLAVOR(cp->class) != CIL_CLASS) { /* MAP */
struct cil_list_item *i = NULL;
cil_list_for_each(i, cp->perms) {
- struct cil_perm *cmp = i->data;
- rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
- if (rc != SEPOL_OK) {
- goto exit;
+ if (i->flavor != CIL_OP) {
+ struct cil_perm *cmp = i->data;
+ rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ } else {
+ enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data;
+ if (op == CIL_ALL) {
+ struct cil_class *mc = cp->class;
+ struct cil_list *perm_list;
+ struct cil_list_item *j = NULL;
+
+ cil_list_init(&perm_list, CIL_MAP_PERM);
+ cil_symtab_map(&mc->perms, __add_perm_to_list, perm_list);
+ cil_list_for_each(j, perm_list) {
+ struct cil_perm *cmp = j->data;
+ rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
+ if (rc != SEPOL_OK) {
+ cil_list_destroy(&perm_list, CIL_FALSE);
+ goto exit;
+ }
+ }
+ cil_list_destroy(&perm_list, CIL_FALSE);
+ }
}
}
- }
+ }
} else { /* SET */
struct cil_classperms_set *cp_set = curr->data;
struct cil_classpermission *cp = cp_set->set;
@@ -1660,8 +1800,12 @@ static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k,
{
struct cil_verify_map_args *map_args = args;
struct cil_perm *cmp = (struct cil_perm *)d;
+ int rc;
- map_args->rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2);
+ rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2);
+ if (rc != SEPOL_OK) {
+ map_args->rc = rc;
+ }
return SEPOL_OK;
}
@@ -1686,27 +1830,22 @@ static int __cil_verify_map_class(struct cil_tree_node *node)
int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
{
- int rc = SEPOL_ERR;
+ int rc = SEPOL_OK;
- if (node->flavor == CIL_MACRO) {
+ switch (node->flavor) {
+ case CIL_MACRO: {
*finished = CIL_TREE_SKIP_HEAD;
- rc = SEPOL_OK;
- goto exit;
- } else if (node->flavor == CIL_BLOCK) {
+ break;
+ }
+ case CIL_BLOCK: {
struct cil_block *blk = node->data;
if (blk->is_abstract == CIL_TRUE) {
*finished = CIL_TREE_SKIP_HEAD;
}
- rc = SEPOL_OK;
- goto exit;
+ break;
}
-
- switch (node->flavor) {
case CIL_USER:
rc = __cil_verify_user_pre_eval(node);
- if (rc != SEPOL_OK) {
- goto exit;
- }
break;
case CIL_MAP_CLASS:
rc = __cil_verify_map_class(node);
@@ -1714,11 +1853,20 @@ int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __at
case CIL_CLASSPERMISSION:
rc = __cil_verify_classpermission(node);
break;
+ case CIL_USERATTRIBUTE:
+ case CIL_ROLEATTRIBUTE:
+ case CIL_TYPEATTRIBUTE:
+ case CIL_CATSET: {
+ struct cil_stack *stack;
+ cil_stack_init(&stack);
+ rc = cil_verify_no_self_reference(node->flavor, node->data, stack);
+ cil_stack_destroy(&stack);
+ break;
+ }
default:
rc = SEPOL_OK;
break;
}
-exit:
return rc;
}
diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h
index 905761b0a19ce4700573fa44a56e6d65d3fc233f..bb1a072c7fffeb935e29879373cd4f3c7bfdba0c 100644
--- a/libsepol/cil/src/cil_verify.h
+++ b/libsepol/cil/src/cil_verify.h
@@ -56,13 +56,13 @@ struct cil_args_verify {
int *pass;
};
-int __cil_verify_name(const char *name);
-int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len);
+int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor);
+int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t len);
int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor);
int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor);
int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op);
int cil_verify_conditional_blocks(struct cil_tree_node *current);
-int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list);
+int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name);
int __cil_verify_ranges(struct cil_list *list);
int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args);
int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor);
diff --git a/libsepol/cil/src/cil_write_ast.c b/libsepol/cil/src/cil_write_ast.c
new file mode 100644
index 0000000000000000000000000000000000000000..d7f00bcc35d82ea00caf875acfde9ec43e77299c
--- /dev/null
+++ b/libsepol/cil/src/cil_write_ast.c
@@ -0,0 +1,1590 @@
+/*
+ * Copyright 2011 Tresys Technology, LLC. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those
+ * of the authors and should not be interpreted as representing official policies,
+ * either expressed or implied, of Tresys Technology, LLC.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "cil_internal.h"
+#include "cil_flavor.h"
+#include "cil_list.h"
+#include "cil_log.h"
+#include "cil_symtab.h"
+#include "cil_tree.h"
+#include "cil_write_ast.h"
+
+
+static inline const char *datum_or_str(struct cil_symtab_datum *datum, const char *str)
+{
+ return datum ? datum->fqn : str;
+}
+
+static inline const char *datum_to_str(struct cil_symtab_datum *datum)
+{
+ return datum ? datum->fqn : "";
+}
+
+static void write_expr(FILE *out, struct cil_list *expr)
+{
+ struct cil_list_item *curr;
+ int notfirst = 0;
+
+ fprintf(out, "(");
+ cil_list_for_each(curr, expr) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ switch (curr->flavor) {
+ case CIL_LIST:
+ write_expr(out, curr->data);
+ break;
+ case CIL_STRING:
+ fprintf(out, "%s", (char *)curr->data);
+ break;
+ case CIL_DATUM:
+ case CIL_TYPE:
+ case CIL_ROLE:
+ case CIL_USER:
+ case CIL_SENS:
+ case CIL_CAT:
+ case CIL_BOOL:
+ case CIL_CLASS:
+ case CIL_MAP_CLASS:
+ case CIL_NAME:
+ fprintf(out, "%s", datum_to_str(curr->data));
+ break;
+ case CIL_OP: {
+ const char *op_str;
+ enum cil_flavor op_flavor = (enum cil_flavor)(uintptr_t)curr->data;
+ switch (op_flavor) {
+ case CIL_AND:
+ op_str = CIL_KEY_AND;
+ break;
+ case CIL_OR:
+ op_str = CIL_KEY_OR;
+ break;
+ case CIL_NOT:
+ op_str = CIL_KEY_NOT;
+ break;
+ case CIL_ALL:
+ op_str = CIL_KEY_ALL;
+ break;
+ case CIL_EQ:
+ op_str = CIL_KEY_EQ;
+ break;
+ case CIL_NEQ:
+ op_str = CIL_KEY_NEQ;
+ break;
+ case CIL_XOR:
+ op_str = CIL_KEY_XOR;
+ break;
+ case CIL_RANGE:
+ op_str = CIL_KEY_RANGE;
+ break;
+ case CIL_CONS_DOM:
+ op_str = CIL_KEY_CONS_DOM;
+ break;
+ case CIL_CONS_DOMBY:
+ op_str = CIL_KEY_CONS_DOMBY;
+ break;
+ case CIL_CONS_INCOMP:
+ op_str = CIL_KEY_CONS_INCOMP;
+ break;
+ default:
+ op_str = "";
+ break;
+ }
+ fprintf(out, "%s", op_str);
+ break;
+ }
+ case CIL_CONS_OPERAND: {
+ const char *operand_str;
+ enum cil_flavor operand_flavor = (enum cil_flavor)(uintptr_t)curr->data;
+ switch (operand_flavor) {
+ case CIL_CONS_U1:
+ operand_str = CIL_KEY_CONS_U1;
+ break;
+ case CIL_CONS_U2:
+ operand_str = CIL_KEY_CONS_U2;
+ break;
+ case CIL_CONS_U3:
+ operand_str = CIL_KEY_CONS_U3;
+ break;
+ case CIL_CONS_T1:
+ operand_str = CIL_KEY_CONS_T1;
+ break;
+ case CIL_CONS_T2:
+ operand_str = CIL_KEY_CONS_T2;
+ break;
+ case CIL_CONS_T3:
+ operand_str = CIL_KEY_CONS_T3;
+ break;
+ case CIL_CONS_R1:
+ operand_str = CIL_KEY_CONS_R1;
+ break;
+ case CIL_CONS_R2:
+ operand_str = CIL_KEY_CONS_R2;
+ break;
+ case CIL_CONS_R3:
+ operand_str = CIL_KEY_CONS_R3;
+ break;
+ case CIL_CONS_L1:
+ operand_str = CIL_KEY_CONS_L1;
+ break;
+ case CIL_CONS_L2:
+ operand_str = CIL_KEY_CONS_L2;
+ break;
+ case CIL_CONS_H1:
+ operand_str = CIL_KEY_CONS_H1;
+ break;
+ case CIL_CONS_H2:
+ operand_str = CIL_KEY_CONS_H2;
+ break;
+ default:
+ operand_str = "";
+ break;
+ }
+ fprintf(out, "%s", operand_str);
+ break;
+ }
+ default:
+ fprintf(out, "");
+ break;
+ }
+ }
+ fprintf(out, ")");
+}
+
+static void write_node_list(FILE *out, struct cil_tree_node *current)
+{
+ int notfirst = 0;
+
+ fprintf(out, "(");
+ while (current) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+
+ fprintf(out, "%s", datum_to_str(current->data));
+ current = current->next;
+ }
+ fprintf(out, ")");
+}
+
+static void write_string_list(FILE *out, struct cil_list *list)
+{
+ struct cil_list_item *curr;
+ int notfirst = 0;
+
+ if (!list) {
+ fprintf(out, "()");
+ return;
+ }
+
+ fprintf(out, "(");
+ cil_list_for_each(curr, list) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ fprintf(out, "%s", (char*)curr->data);
+ }
+ fprintf(out, ")");
+}
+
+static void write_datum_list(FILE *out, struct cil_list *list)
+{
+ struct cil_list_item *curr;
+ int notfirst = 0;
+
+ if (!list) {
+ fprintf(out, "()");
+ return;
+ }
+
+ fprintf(out, "(");
+ cil_list_for_each(curr, list) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ fprintf(out, "%s", datum_to_str(curr->data));
+ }
+ fprintf(out, ")");
+}
+
+static void write_classperms(FILE *out, struct cil_classperms *cp)
+{
+ if (!cp) {
+ fprintf(out, "()");
+ return;
+ }
+
+ fprintf(out, "(%s ", datum_or_str(DATUM(cp->class), cp->class_str));
+ if (cp->perms)
+ write_expr(out, cp->perms);
+ else
+ write_expr(out, cp->perm_strs);
+ fprintf(out, ")");
+}
+
+static void write_classperms_list(FILE *out, struct cil_list *cp_list)
+{
+ struct cil_list_item *curr;
+ int notfirst = 0;
+ int num = 0;
+
+ if (!cp_list) {
+ fprintf(out, "()");
+ return;
+ }
+
+ cil_list_for_each(curr, cp_list) {
+ num++;
+ }
+ if (num > 1)
+ fprintf(out, "(");
+ cil_list_for_each(curr, cp_list) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ if (curr->flavor == CIL_CLASSPERMS) {
+ write_classperms(out, curr->data);
+ } else {
+ struct cil_classperms_set *cp_set = curr->data;
+ struct cil_classpermission *cp = cp_set->set;
+ if (cp) {
+ if (cp->datum.name)
+ fprintf(out, "%s", datum_to_str(DATUM(cp)));
+ else
+ write_classperms_list(out,cp->classperms);
+ } else {
+ fprintf(out, "%s", cp_set->set_str);
+ }
+ }
+ }
+ if (num > 1)
+ fprintf(out, ")");
+}
+
+static void write_permx(FILE *out, struct cil_permissionx *permx)
+{
+ if (permx->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(permx)));
+ } else {
+ fprintf(out, "(");
+ fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "");
+ fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
+ write_expr(out, permx->expr_str);
+ fprintf(out, ")");
+ }
+}
+
+static void write_cats(FILE *out, struct cil_cats *cats)
+{
+ if (cats->datum_expr) {
+ write_expr(out, cats->datum_expr);
+ } else {
+ write_expr(out, cats->str_expr);
+ }
+}
+
+static void write_level(FILE *out, struct cil_level *level, int print_name)
+{
+ if (print_name && level->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(level)));
+ } else {
+ fprintf(out, "(");
+ fprintf(out, "%s", datum_or_str(DATUM(level->sens), level->sens_str));
+ if (level->cats) {
+ fprintf(out, " ");
+ write_cats(out, level->cats);
+ }
+ fprintf(out, ")");
+ }
+}
+
+static void write_range(FILE *out, struct cil_levelrange *range, int print_name)
+{
+ if (print_name && range->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(range)));
+ } else {
+ fprintf(out, "(");
+ if (range->low)
+ write_level(out, range->low, CIL_TRUE);
+ else
+ fprintf(out, "%s", range->low_str);
+ fprintf(out, " ");
+ if (range->high)
+ write_level(out, range->high, CIL_TRUE);
+ else
+ fprintf(out, "%s", range->high_str);
+ fprintf(out, ")");
+ }
+}
+
+static void write_context(FILE *out, struct cil_context *context, int print_name)
+{
+ if (print_name && context->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(context)));
+ } else {
+ fprintf(out, "(");
+ fprintf(out, "%s ", datum_or_str(DATUM(context->user), context->user_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(context->role), context->role_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(context->type), context->type_str));
+ if (context->range)
+ write_range(out, context->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", context->range_str);
+ fprintf(out, ")");
+ }
+}
+
+static void write_ipaddr(FILE *out, struct cil_ipaddr *ipaddr)
+{
+ if (ipaddr->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(ipaddr)));
+ } else {
+ char buf[256];
+ if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL)
+ strcpy(buf, "");
+ fprintf(out, "(%s)", buf);
+ }
+}
+
+static void write_constrain(FILE *out, struct cil_constrain *cons)
+{
+ write_classperms_list(out, cons->classperms);
+ fprintf(out, " ");
+ if (cons->datum_expr)
+ write_expr(out, cons->datum_expr);
+ else
+ write_expr(out, cons->str_expr);
+}
+
+static void write_call_args(FILE *out, struct cil_list *args)
+{
+ struct cil_list_item *item;
+ int notfirst = 0;
+
+ fprintf(out, "(");
+ cil_list_for_each(item, args) {
+ struct cil_args* arg = item->data;
+ enum cil_flavor arg_flavor = arg->flavor;
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ switch (arg_flavor) {
+ case CIL_TYPE:
+ case CIL_ROLE:
+ case CIL_USER:
+ case CIL_SENS:
+ case CIL_CAT:
+ case CIL_BOOL:
+ case CIL_CLASS:
+ case CIL_MAP_CLASS:
+ case CIL_NAME: {
+ fprintf(out, "%s", datum_or_str(arg->arg, arg->arg_str));
+ break;
+ }
+ case CIL_CATSET: {
+ if (arg->arg) {
+ struct cil_catset *catset = (struct cil_catset *)arg->arg;
+ write_cats(out, catset->cats);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
+ break;
+ }
+ case CIL_LEVEL: {
+ if (arg->arg) {
+ struct cil_level *level = (struct cil_level *)arg->arg;
+ write_level(out, level, CIL_TRUE);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
+ break;
+ }
+ case CIL_LEVELRANGE: {
+ if (arg->arg) {
+ struct cil_levelrange *range = (struct cil_levelrange *)arg->arg;
+ write_range(out, range, CIL_TRUE);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
+ break;
+ }
+ case CIL_IPADDR: {
+ if (arg->arg) {
+ struct cil_ipaddr *addr = (struct cil_ipaddr *)arg->arg;
+ write_ipaddr(out, addr);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
+ break;
+ }
+ case CIL_CLASSPERMISSION: {
+ if (arg->arg) {
+ struct cil_classpermission *cp = (struct cil_classpermission *)arg->arg;
+ if (cp->datum.name)
+ fprintf(out, "%s", datum_to_str(DATUM(cp)));
+ else
+ write_classperms_list(out, cp->classperms);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
+ break;
+ }
+ default:
+ fprintf(out, "", datum_or_str(arg->arg, arg->arg_str));
+ break;
+ }
+ }
+ fprintf(out, ")");
+}
+
+static void write_call_args_tree(FILE *out, struct cil_tree_node *arg_node)
+{
+ while (arg_node) {
+ if (arg_node->data) {
+ fprintf(out, "%s", (char *)arg_node->data);
+ } else if (arg_node->cl_head) {
+ fprintf(out, "(");
+ write_call_args_tree(out, arg_node->cl_head);
+ fprintf(out, ")");
+ }
+ if (arg_node->next)
+ fprintf(out, " ");
+ arg_node = arg_node->next;
+ }
+}
+
+static const char *macro_param_flavor_to_string(enum cil_flavor flavor)
+{
+ const char *str;
+ switch(flavor) {
+ case CIL_TYPE:
+ str = CIL_KEY_TYPE;
+ break;
+ case CIL_ROLE:
+ str = CIL_KEY_ROLE;
+ break;
+ case CIL_USER:
+ str = CIL_KEY_USER;
+ break;
+ case CIL_SENS:
+ str = CIL_KEY_SENSITIVITY;
+ break;
+ case CIL_CAT:
+ str = CIL_KEY_CATEGORY;
+ break;
+ case CIL_CATSET:
+ str = CIL_KEY_CATSET;
+ break;
+ case CIL_LEVEL:
+ str = CIL_KEY_LEVEL;
+ break;
+ case CIL_LEVELRANGE:
+ str = CIL_KEY_LEVELRANGE;
+ break;
+ case CIL_CLASS:
+ str = CIL_KEY_CLASS;
+ break;
+ case CIL_IPADDR:
+ str = CIL_KEY_IPADDR;
+ break;
+ case CIL_MAP_CLASS:
+ str = CIL_KEY_MAP_CLASS;
+ break;
+ case CIL_CLASSPERMISSION:
+ str = CIL_KEY_CLASSPERMISSION;
+ break;
+ case CIL_BOOL:
+ str = CIL_KEY_BOOL;
+ break;
+ case CIL_STRING:
+ str = CIL_KEY_STRING;
+ break;
+ case CIL_NAME:
+ str = CIL_KEY_NAME;
+ break;
+ default:
+ str = "";
+ break;
+ }
+ return str;
+}
+
+void cil_write_src_info_node(FILE *out, struct cil_tree_node *node)
+{
+ struct cil_src_info *info = node->data;
+ if (info->kind == CIL_KEY_SRC_CIL || info->kind == CIL_KEY_SRC_HLL_LMS) {
+ fprintf(out, ";;* lms %u %s\n", info->hll_line, info->path);
+ } else if (info->kind == CIL_KEY_SRC_HLL_LMX) {
+ fprintf(out, ";;* lmx %u %s\n", info->hll_line, info->path);
+ } else {
+ fprintf(out, ";;* %u %s\n", info->hll_line, info->path);
+ }
+}
+
+void cil_write_ast_node(FILE *out, struct cil_tree_node *node)
+{
+ if (!node->data) {
+ return;
+ }
+
+ switch(node->flavor) {
+ case CIL_NODE: {
+ fprintf(out, "%s\n", (char *)node->data);
+ break;
+ }
+ case CIL_BLOCK: {
+ struct cil_block *block = node->data;
+ fprintf(out, "(block %s", datum_to_str(DATUM(block)));
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
+ break;
+ }
+ case CIL_BLOCKINHERIT: {
+ struct cil_blockinherit *inherit = node->data;
+ fprintf(out, "(blockinherit %s)\n", datum_or_str(DATUM(inherit->block), inherit->block_str));
+ break;
+ }
+ case CIL_IN: {
+ struct cil_in *in = node->data;
+ fprintf(out, "(in %s", in->block_str);
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
+ break;
+ }
+ case CIL_OPTIONAL: {
+ struct cil_optional *optional = node->data;
+ fprintf(out, "(optional %s", datum_to_str(DATUM(optional)));
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
+ break;
+ }
+ case CIL_BOOLEANIF: {
+ struct cil_booleanif *bif = node->data;
+ fprintf(out, "(booleanif ");
+ if (bif->datum_expr)
+ write_expr(out, bif->datum_expr);
+ else
+ write_expr(out, bif->str_expr);
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
+ break;
+ }
+ case CIL_TUNABLEIF: {
+ struct cil_tunableif *tif = node->data;
+ fprintf(out, "(tunableif ");
+ if (tif->datum_expr)
+ write_expr(out, tif->datum_expr);
+ else
+ write_expr(out, tif->str_expr);
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
+ break;
+ }
+ case CIL_CONDBLOCK: {
+ struct cil_condblock *cb = node->data;
+ fprintf(out, "(%s", cb->flavor == CIL_CONDTRUE ? "true" : "false");
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
+ break;
+ }
+ case CIL_MACRO: {
+ struct cil_macro *macro = node->data;
+ struct cil_list_item *curr;
+ fprintf(out, "(macro %s (", datum_to_str(DATUM(macro)));
+ if (macro->params) {
+ cil_list_for_each(curr, macro->params) {
+ struct cil_param *param = curr->data;
+ fprintf(out, "(%s %s)", macro_param_flavor_to_string(param->flavor), param->str);
+ }
+ }
+ fprintf(out, ")");
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
+ break;
+ }
+ case CIL_CALL: {
+ struct cil_call *call = node->data;
+ fprintf(out, "(call %s", datum_or_str(DATUM(call->macro), call->macro_str));
+ if (call->args) {
+ fprintf(out, " ");
+ write_call_args(out, call->args);
+ } else if (call->args_tree) {
+ fprintf(out, " ");
+ write_call_args_tree(out, call->args_tree->root);
+ }
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
+ break;
+ }
+ case CIL_BLOCKABSTRACT: {
+ struct cil_blockabstract *abstract = node->data;
+ fprintf(out, "(blockabstract %s)\n", abstract->block_str);
+ break;
+ }
+ case CIL_MLS: {
+ struct cil_mls *mls = node->data;
+ fprintf(out, "(mls %s)\n", mls->value ? "true" : "false");
+ break;
+ }
+ case CIL_HANDLEUNKNOWN: {
+ struct cil_handleunknown *unknown = node->data;
+ fprintf(out, "(handleunknown ");
+ if (unknown->handle_unknown == SEPOL_ALLOW_UNKNOWN)
+ fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_ALLOW);
+ else if (unknown->handle_unknown == SEPOL_DENY_UNKNOWN)
+ fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_DENY);
+ else if (unknown->handle_unknown == SEPOL_REJECT_UNKNOWN)
+ fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_REJECT);
+ else
+ fprintf(out, "");
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_DEFAULTUSER: {
+ struct cil_default *def = node->data;
+ fprintf(out, "(defaultuser ");
+ if (def->class_datums)
+ write_datum_list(out, def->class_datums);
+ else
+ write_string_list(out, def->class_strs);
+ if (def->object == CIL_DEFAULT_SOURCE)
+ fprintf(out, " source");
+ else if (def->object == CIL_DEFAULT_TARGET)
+ fprintf(out, " target");
+ else
+ fprintf(out, " ");
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_DEFAULTROLE: {
+ struct cil_default *def = node->data;
+ fprintf(out, "(defaultrole ");
+ if (def->class_datums)
+ write_datum_list(out, def->class_datums);
+ else
+ write_string_list(out, def->class_strs);
+ if (def->object == CIL_DEFAULT_SOURCE)
+ fprintf(out, " source");
+ else if (def->object == CIL_DEFAULT_TARGET)
+ fprintf(out, " target");
+ else
+ fprintf(out, " ");
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_DEFAULTTYPE: {
+ struct cil_default *def = node->data;
+ fprintf(out, "(defaulttype ");
+ if (def->class_datums)
+ write_datum_list(out, def->class_datums);
+ else
+ write_string_list(out, def->class_strs);
+ if (def->object == CIL_DEFAULT_SOURCE)
+ fprintf(out, " source");
+ else if (def->object == CIL_DEFAULT_TARGET)
+ fprintf(out, " target");
+ else
+ fprintf(out, " ");
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_DEFAULTRANGE: {
+ struct cil_defaultrange *def = node->data;
+ fprintf(out, "(defaultrange ");
+ if (def->class_datums)
+ write_datum_list(out, def->class_datums);
+ else
+ write_string_list(out, def->class_strs);
+ if (def->object_range == CIL_DEFAULT_SOURCE_LOW)
+ fprintf(out, " source low");
+ else if (def->object_range == CIL_DEFAULT_SOURCE_HIGH)
+ fprintf(out, " source high");
+ else if (def->object_range == CIL_DEFAULT_SOURCE_LOW_HIGH)
+ fprintf(out, " source low-high");
+ else if (def->object_range == CIL_DEFAULT_TARGET_LOW)
+ fprintf(out, " target low");
+ else if (def->object_range == CIL_DEFAULT_TARGET_HIGH)
+ fprintf(out, " target high");
+ else if (def->object_range == CIL_DEFAULT_TARGET_LOW_HIGH)
+ fprintf(out, " target low-high");
+ else
+ fprintf(out, " ");
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_CLASS: {
+ struct cil_class *class = node->data;
+ fprintf(out, "(class %s ", datum_to_str(DATUM(class)));
+ write_node_list(out, node->cl_head);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_CLASSORDER: {
+ struct cil_classorder *classorder = node->data;
+ fprintf(out, "(classorder ");
+ write_string_list(out, classorder->class_list_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_COMMON: {
+ struct cil_class *common = node->data;
+ fprintf(out, "(common %s ", datum_to_str(DATUM(common)));
+ write_node_list(out, node->cl_head);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_CLASSCOMMON: {
+ struct cil_classcommon *cc = node->data;
+ fprintf(out, "(classcommon %s %s)\n", cc->class_str, cc->common_str);
+ break;
+ }
+ case CIL_CLASSPERMISSION: {
+ struct cil_classpermission *cp = node->data;
+ fprintf(out, "(classpermission %s)\n", datum_to_str(DATUM(cp)));
+ break;
+ }
+ case CIL_CLASSPERMISSIONSET: {
+ struct cil_classpermissionset *cps = node->data;
+ fprintf(out, "(classpermissionset %s ", cps->set_str);
+ write_classperms_list(out, cps->classperms);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_MAP_CLASS: {
+ struct cil_class *map = node->data;
+ fprintf(out, "(classmap %s ", datum_to_str(DATUM(map)));
+ write_node_list(out, node->cl_head);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_CLASSMAPPING: {
+ struct cil_classmapping *mapping = node->data;
+ fprintf(out, "(classmapping %s %s ", mapping->map_class_str, mapping->map_perm_str);
+ write_classperms_list(out, mapping->classperms);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_PERMISSIONX: {
+ struct cil_permissionx *permx = node->data;
+ fprintf(out, "(permissionx %s (", datum_to_str(DATUM(permx)));
+ fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "");
+ fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
+ write_expr(out, permx->expr_str);
+ fprintf(out, "))\n");
+ break;
+ }
+ case CIL_SID: {
+ struct cil_sid *sid = node->data;
+ fprintf(out, "(sid %s)\n", datum_to_str(DATUM(sid)));
+ break;
+ }
+ case CIL_SIDCONTEXT: {
+ struct cil_sidcontext *sidcon = node->data;
+ fprintf(out, "(sidcontext %s ", sidcon->sid_str);
+ if (sidcon->context)
+ write_context(out, sidcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", sidcon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_SIDORDER: {
+ struct cil_sidorder *sidorder = node->data;
+ fprintf(out, "(sidorder ");
+ write_string_list(out, sidorder->sid_list_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_BOOL: {
+ struct cil_bool *boolean = node->data;
+ fprintf(out, "(boolean %s %s)\n", datum_to_str(DATUM(boolean)), boolean->value ? "true" : "false");
+ break;
+ }
+ case CIL_TUNABLE: {
+ struct cil_tunable *tunable = node->data;
+ fprintf(out, "(tunable %s %s)\n", datum_to_str(DATUM(tunable)), tunable->value ? "true" : "false");
+ break;
+ }
+ case CIL_SENS: {
+ struct cil_sens *sens = node->data;
+ fprintf(out, "(sensitivity %s)\n", datum_to_str(DATUM(sens)));
+ break;
+ }
+ case CIL_SENSALIAS: {
+ struct cil_alias *alias = node->data;
+ fprintf(out, "(sensitivityalias %s)\n", datum_to_str(DATUM(alias)));
+ break;
+ }
+ case CIL_SENSALIASACTUAL: {
+ struct cil_aliasactual *aliasactual = node->data;
+ fprintf(out, "(sensitivityaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
+ break;
+ }
+ case CIL_CAT: {
+ struct cil_cat *cat = node->data;
+ fprintf(out, "(category %s)\n", datum_to_str(DATUM(cat)));
+ break;
+ }
+ case CIL_CATALIAS: {
+ struct cil_alias *alias = node->data;
+ fprintf(out, "(categoryalias %s)\n", datum_to_str(DATUM(alias)));
+ break;
+ }
+ case CIL_CATALIASACTUAL: {
+ struct cil_aliasactual *aliasactual = node->data;
+ fprintf(out, "(categoryaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
+ break;
+ }
+ case CIL_CATSET: {
+ struct cil_catset *catset = node->data;
+ fprintf(out, "(categoryset %s ", datum_to_str(DATUM(catset)));
+ write_cats(out, catset->cats);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_CATORDER: {
+ struct cil_catorder *catorder = node->data;
+ fprintf(out, "(categoryorder ");
+ write_string_list(out, catorder->cat_list_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_SENSCAT: {
+ struct cil_senscat *senscat = node->data;
+ fprintf(out, "(sensitivitycategory ");
+ fprintf(out, "%s ", senscat->sens_str);
+ write_cats(out, senscat->cats);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_SENSITIVITYORDER: {
+ struct cil_sensorder *sensorder = node->data;
+ fprintf(out, "(sensitivityorder ");
+ write_string_list(out, sensorder->sens_list_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_LEVEL: {
+ struct cil_level *level = node->data;
+ fprintf(out, "(level %s ", datum_to_str(&level->datum));
+ write_level(out, level, CIL_FALSE);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_LEVELRANGE: {
+ struct cil_levelrange *lvlrange = node->data;
+ fprintf(out, "(levelrange %s ", datum_to_str(DATUM(lvlrange)));
+ write_range(out, lvlrange, CIL_FALSE);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_USER: {
+ struct cil_user *user = node->data;
+ fprintf(out, "(user %s)\n", datum_to_str(DATUM(user)));
+ break;
+ }
+ case CIL_USERATTRIBUTE: {
+ struct cil_userattribute *attr = node->data;
+ fprintf(out, "(userattribute %s)\n", datum_to_str(DATUM(attr)));
+ break;
+ }
+ case CIL_USERATTRIBUTESET: {
+ struct cil_userattributeset *attr = node->data;
+ fprintf(out, "(userattributeset %s ", attr->attr_str);
+ if (attr->datum_expr)
+ write_expr(out, attr->datum_expr);
+ else
+ write_expr(out, attr->str_expr);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_USERROLE: {
+ struct cil_userrole *userrole = node->data;
+ fprintf(out, "(userrole ");
+ fprintf(out, "%s ", datum_or_str(userrole->user, userrole->user_str));
+ fprintf(out, "%s", datum_or_str(userrole->role, userrole->role_str));
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_USERLEVEL: {
+ struct cil_userlevel *userlevel = node->data;
+ fprintf(out, "(userlevel %s ", userlevel->user_str);
+ if (userlevel->level)
+ write_level(out, userlevel->level, CIL_TRUE);
+ else
+ fprintf(out, "%s", userlevel->level_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_USERRANGE: {
+ struct cil_userrange *userrange = node->data;
+ fprintf(out, "(userrange %s ", userrange->user_str);
+ if (userrange->range)
+ write_range(out, userrange->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", userrange->range_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_USERBOUNDS: {
+ struct cil_bounds *bounds = node->data;
+ fprintf(out, "(userbounds %s %s)\n", bounds->parent_str, bounds->child_str);
+ break;
+ }
+ case CIL_USERPREFIX: {
+ struct cil_userprefix *prefix = node->data;
+ fprintf(out, "(userprefix ");
+ fprintf(out, "%s ", datum_or_str(DATUM(prefix->user), prefix->user_str));
+ fprintf(out, "%s)\n", prefix->prefix_str);
+ break;
+ }
+ case CIL_SELINUXUSER: {
+ struct cil_selinuxuser *selinuxuser = node->data;
+ fprintf(out, "(selinuxuser %s ", selinuxuser->name_str);
+ fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str));
+ if (selinuxuser->range)
+ write_range(out, selinuxuser->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", selinuxuser->range_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_SELINUXUSERDEFAULT: {
+ struct cil_selinuxuser *selinuxuser = node->data;
+ fprintf(out, "(selinuxuserdefault ");
+ fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str));
+ if (selinuxuser->range)
+ write_range(out, selinuxuser->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", selinuxuser->range_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_ROLE: {
+ fprintf(out, "(role %s)\n", datum_to_str(node->data));
+ break;
+ }
+ case CIL_ROLEATTRIBUTE: {
+ fprintf(out, "(roleattribute %s)\n", datum_to_str(node->data));
+ break;
+ }
+ case CIL_ROLEATTRIBUTESET: {
+ struct cil_roleattributeset *attr = node->data;
+ fprintf(out, "(roleattributeset %s ", attr->attr_str);
+ if (attr->datum_expr)
+ write_expr(out, attr->datum_expr);
+ else
+ write_expr(out, attr->str_expr);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_ROLETYPE: {
+ struct cil_roletype *roletype = node->data;
+ fprintf(out, "(roletype ");
+ fprintf(out, "%s ", datum_or_str(DATUM(roletype->role), roletype->role_str));
+ fprintf(out, "%s", datum_or_str(DATUM(roletype->type), roletype->type_str));
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_ROLEBOUNDS: {
+ struct cil_bounds *bnds = node->data;
+ fprintf(out, "(rolebounds %s %s)\n", bnds->parent_str, bnds->child_str);
+ break;
+ }
+ case CIL_TYPE: {
+ fprintf(out, "(type %s)\n", datum_to_str(node->data));
+ break;
+ }
+ case CIL_TYPEALIAS: {
+ fprintf(out, "(typealias %s)\n", datum_to_str(node->data));
+ break;
+ }
+ case CIL_TYPEALIASACTUAL: {
+ struct cil_aliasactual *aliasactual = node->data;
+ fprintf(out, "(typealiasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
+ break;
+ }
+ case CIL_TYPEATTRIBUTE: {
+ fprintf(out, "(typeattribute %s)\n", datum_to_str(node->data));
+ break;
+ }
+ case CIL_TYPEATTRIBUTESET: {
+ struct cil_typeattributeset *attr = node->data;
+ fprintf(out, "(typeattributeset %s ", attr->attr_str);
+ if (attr->datum_expr)
+ write_expr(out, attr->datum_expr);
+ else
+ write_expr(out, attr->str_expr);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_EXPANDTYPEATTRIBUTE: {
+ struct cil_expandtypeattribute *attr = node->data;
+ fprintf(out, "(expandtypeattribute ");
+ if (attr->attr_datums)
+ write_expr(out, attr->attr_datums);
+ else
+ write_expr(out, attr->attr_strs);
+ fprintf(out, " %s)\n", attr->expand ? "true" : "false");
+ break;
+ }
+ case CIL_TYPEPERMISSIVE: {
+ struct cil_typepermissive *tp = node->data;
+ fprintf(out, "(typepermissive ");
+ fprintf(out, "%s", datum_or_str(DATUM(tp->type), tp->type_str));
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_TYPEBOUNDS: {
+ struct cil_bounds *bounds = node->data;
+ fprintf(out, "(typebounds %s %s)\n", bounds->parent_str, bounds->child_str);
+ break;
+ }
+ case CIL_ROLEALLOW: {
+ struct cil_roleallow *roleallow = node->data;
+ fprintf(out, "(roleallow ");
+ fprintf(out, "%s ", datum_or_str(DATUM(roleallow->src), roleallow->src_str));
+ fprintf(out, "%s", datum_or_str(DATUM(roleallow->tgt), roleallow->tgt_str));
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_ROLETRANSITION: {
+ struct cil_roletransition *roletrans = node->data;
+ fprintf(out, "(roletransition ");
+ fprintf(out, "%s ", datum_or_str(DATUM(roletrans->src), roletrans->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(roletrans->tgt), roletrans->tgt_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(roletrans->obj), roletrans->obj_str));
+ fprintf(out, "%s", datum_or_str(DATUM(roletrans->result), roletrans->result_str));
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_AVRULE: {
+ struct cil_avrule *rule = node->data;
+ if (rule->rule_kind == AVRULE_ALLOWED)
+ fprintf(out, "(allow ");
+ else if (rule->rule_kind == AVRULE_AUDITALLOW)
+ fprintf(out, "(auditallow ");
+ else if (rule->rule_kind == AVRULE_DONTAUDIT)
+ fprintf(out, "(dontaudit ");
+ else if (rule->rule_kind == AVRULE_NEVERALLOW)
+ fprintf(out, "(neverallow ");
+ else
+ fprintf(out, "( ");
+
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
+ write_classperms_list(out, rule->perms.classperms);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_AVRULEX: {
+ struct cil_avrule *rule = node->data;
+ if (rule->rule_kind == AVRULE_ALLOWED)
+ fprintf(out, "(allowx ");
+ else if (rule->rule_kind == AVRULE_AUDITALLOW)
+ fprintf(out, "(auditallowx ");
+ else if (rule->rule_kind == AVRULE_DONTAUDIT)
+ fprintf(out, "(dontauditx ");
+ else if (rule->rule_kind == AVRULE_NEVERALLOW)
+ fprintf(out, "(neverallowx ");
+ else
+ fprintf(out, "( ");
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
+ if (rule->perms.x.permx_str) {
+ fprintf(out, "%s",rule->perms.x.permx_str);
+ } else {
+ write_permx(out, rule->perms.x.permx);
+ }
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_TYPE_RULE: {
+ struct cil_type_rule *rule = node->data;
+ if (rule->rule_kind == AVRULE_TRANSITION)
+ fprintf(out, "(typetransition ");
+ else if (rule->rule_kind == AVRULE_MEMBER)
+ fprintf(out, "(typemember ");
+ else if (rule->rule_kind == AVRULE_CHANGE)
+ fprintf(out, "(typechange ");
+ else
+ fprintf(out, "( ");
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
+ fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str));
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_NAMETYPETRANSITION: {
+ struct cil_nametypetransition *rule = node->data;
+ fprintf(out, "(typetransition ");
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
+ fprintf(out, "\"%s\" ", datum_or_str(DATUM(rule->name), rule->name_str));
+ fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str));
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_RANGETRANSITION: {
+ struct cil_rangetransition *rule = node->data;
+ fprintf(out, "(rangetransition ");
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->exec), rule->exec_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
+ if (rule->range)
+ write_range(out, rule->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", rule->range_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_CONSTRAIN: {
+ struct cil_constrain *cons = node->data;
+ fprintf(out, "(constrain ");
+ write_constrain(out, cons);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_MLSCONSTRAIN: {
+ struct cil_constrain *cons = node->data;
+ fprintf(out, "(mlsconstrain ");
+ write_constrain(out, cons);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_VALIDATETRANS: {
+ struct cil_validatetrans *vt = node->data;
+ fprintf(out, "(validatetrans ");
+ fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str));
+ if (vt->datum_expr)
+ write_expr(out, vt->datum_expr);
+ else
+ write_expr(out, vt->str_expr);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_MLSVALIDATETRANS: {
+ struct cil_validatetrans *vt = node->data;
+ fprintf(out, "(mlsvalidatetrans ");
+ fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str));
+ if (vt->datum_expr)
+ write_expr(out, vt->datum_expr);
+ else
+ write_expr(out, vt->str_expr);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_CONTEXT: {
+ struct cil_context *context = node->data;
+ fprintf(out, "(context %s ", datum_to_str(DATUM(context)));
+ write_context(out, context, CIL_FALSE);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_FILECON: {
+ struct cil_filecon *filecon = node->data;
+ fprintf(out, "(filecon ");
+ fprintf(out, "\"%s\" ", filecon->path_str);
+ if (filecon->type == CIL_FILECON_FILE)
+ fprintf(out, "%s ", CIL_KEY_FILE);
+ else if (filecon->type == CIL_FILECON_DIR)
+ fprintf(out, "%s ", CIL_KEY_DIR);
+ else if (filecon->type == CIL_FILECON_CHAR)
+ fprintf(out, "%s ", CIL_KEY_CHAR);
+ else if (filecon->type == CIL_FILECON_BLOCK)
+ fprintf(out, "%s ", CIL_KEY_BLOCK);
+ else if (filecon->type == CIL_FILECON_SOCKET)
+ fprintf(out, "%s ", CIL_KEY_SOCKET);
+ else if (filecon->type == CIL_FILECON_PIPE)
+ fprintf(out, "%s ", CIL_KEY_PIPE);
+ else if (filecon->type == CIL_FILECON_SYMLINK)
+ fprintf(out, "%s ", CIL_KEY_SYMLINK);
+ else if (filecon->type == CIL_FILECON_ANY)
+ fprintf(out, "%s ", CIL_KEY_ANY);
+ else
+ fprintf(out, " ");
+ if (filecon->context)
+ write_context(out, filecon->context, CIL_TRUE);
+ else if (filecon->context_str)
+ fprintf(out, "%s", filecon->context_str);
+ else
+ fprintf(out, "()");
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_IBPKEYCON: {
+ struct cil_ibpkeycon *ibpkeycon = node->data;
+ fprintf(out, "(ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
+ fprintf(out, "(%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high);
+ if (ibpkeycon->context)
+ write_context(out, ibpkeycon->context, CIL_TRUE);
+ else if (ibpkeycon->context_str)
+ fprintf(out, "%s", ibpkeycon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_PORTCON: {
+ struct cil_portcon *portcon = node->data;
+ fprintf(out, "(portcon ");
+ if (portcon->proto == CIL_PROTOCOL_UDP)
+ fprintf(out, " udp ");
+ else if (portcon->proto == CIL_PROTOCOL_TCP)
+ fprintf(out, " tcp ");
+ else if (portcon->proto == CIL_PROTOCOL_DCCP)
+ fprintf(out, "dccp ");
+ else if (portcon->proto == CIL_PROTOCOL_SCTP)
+ fprintf(out, "sctp ");
+ else
+ fprintf(out, " ");
+ if (portcon->port_low == portcon->port_high)
+ fprintf(out, "%d ", portcon->port_low);
+ else
+ fprintf(out, "(%d %d) ", portcon->port_low, portcon->port_high);
+ if (portcon->context)
+ write_context(out, portcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", portcon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_NODECON: {
+ struct cil_nodecon *nodecon = node->data;
+ fprintf(out, "(nodecon ");
+ if (nodecon->addr)
+ write_ipaddr(out, nodecon->addr);
+ else
+ fprintf(out, "%s ", nodecon->addr_str);
+ fprintf(out, " ");
+ if (nodecon->mask)
+ write_ipaddr(out, nodecon->mask);
+ else
+ fprintf(out, "%s ", nodecon->mask_str);
+ fprintf(out, " ");
+ if (nodecon->context)
+ write_context(out, nodecon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", nodecon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_GENFSCON: {
+ struct cil_genfscon *genfscon = node->data;
+ fprintf(out, "(genfscon ");
+ fprintf(out, "%s \"%s\" ", genfscon->fs_str, genfscon->path_str);
+ if (genfscon->context)
+ write_context(out, genfscon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", genfscon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_NETIFCON: {
+ struct cil_netifcon *netifcon = node->data;
+ fprintf(out, "(netifcon %s ", netifcon->interface_str);
+ if (netifcon->if_context)
+ write_context(out, netifcon->if_context, CIL_TRUE);
+ else
+ fprintf(out, "%s", netifcon->if_context_str);
+ fprintf(out, " ");
+ if (netifcon->packet_context)
+ write_context(out, netifcon->packet_context, CIL_TRUE);
+ else
+ fprintf(out, "%s", netifcon->packet_context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_IBENDPORTCON: {
+ struct cil_ibendportcon *ibendportcon = node->data;
+ fprintf(out, "(ibendportcon %s %u ", ibendportcon->dev_name_str, ibendportcon->port);
+ if (ibendportcon->context)
+ write_context(out, ibendportcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", ibendportcon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_PIRQCON: {
+ struct cil_pirqcon *pirqcon = node->data;
+ fprintf(out, "(pirqcon %d ", pirqcon->pirq);
+ if (pirqcon->context)
+ write_context(out, pirqcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", pirqcon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_IOMEMCON: {
+ struct cil_iomemcon *iomemcon = node->data;
+ fprintf(out, "(iomemcon (%"PRId64" %"PRId64") ", iomemcon->iomem_low, iomemcon->iomem_high);
+ if (iomemcon->context)
+ write_context(out, iomemcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", iomemcon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_IOPORTCON: {
+ struct cil_ioportcon *ioportcon = node->data;
+ fprintf(out, "(ioportcon ");
+ if (ioportcon->ioport_low == ioportcon->ioport_high)
+ fprintf(out, "%d ", ioportcon->ioport_low);
+ else
+ fprintf(out, "(%d %d) ", ioportcon->ioport_low, ioportcon->ioport_high);
+
+ if (ioportcon->context)
+ write_context(out, ioportcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", ioportcon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_PCIDEVICECON: {
+ struct cil_pcidevicecon *pcidevicecon = node->data;
+ fprintf(out, "(pcidevicecon %d ", pcidevicecon->dev);
+ if (pcidevicecon->context)
+ write_context(out, pcidevicecon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", pcidevicecon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_DEVICETREECON: {
+ struct cil_devicetreecon *devicetreecon = node->data;
+ fprintf(out, "(devicetreecon \"%s\" ", devicetreecon->path);
+ if (devicetreecon->context)
+ write_context(out, devicetreecon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", devicetreecon->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_FSUSE: {
+ struct cil_fsuse *fsuse = node->data;
+ fprintf(out, "(fsuse ");
+ if (fsuse->type == CIL_FSUSE_XATTR)
+ fprintf(out, "xattr ");
+ else if (fsuse->type == CIL_FSUSE_TASK)
+ fprintf(out, "task ");
+ else if (fsuse->type == CIL_FSUSE_TRANS)
+ fprintf(out, "trans ");
+ else
+ fprintf(out, " ");
+ fprintf(out, "%s ", fsuse->fs_str);
+ if (fsuse->context)
+ write_context(out, fsuse->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", fsuse->context_str);
+ fprintf(out, ")\n");
+ break;
+ }
+ case CIL_POLICYCAP: {
+ struct cil_policycap *polcap = node->data;
+ fprintf(out, "(policycap %s)\n", polcap->datum.name);
+ break;
+ }
+ case CIL_IPADDR: {
+ struct cil_ipaddr *ipaddr = node->data;
+ char buf[256];
+ if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL)
+ strcpy(buf, "");
+ fprintf(out, "(ipaddr %s %s)\n", datum_to_str(&ipaddr->datum), buf);
+ break;
+ }
+ default :
+ fprintf(out, "()\n", cil_node_to_string(node));
+ break;
+ }
+}
+
+/*
+ * Tree walk data and helper functions for writing the AST of the various phases
+ */
+
+struct cil_write_ast_args {
+ FILE *out;
+ int depth;
+};
+
+/*
+ * Helper functions for writing the parse AST
+ */
+
+static int __write_parse_ast_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+
+ fprintf(args->out, "%*s", args->depth*4, "");
+ if (!node->data) {
+ if (node->cl_head)
+ fprintf(args->out, "(\n");
+ else
+ fprintf(args->out, "()\n");
+ } else {
+ char *str = (char *)node->data;
+ size_t len = strlen(str);
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (isspace(str[i])) {
+ fprintf(args->out, "\"%s\"\n", str);
+ return SEPOL_OK;
+ }
+ }
+
+ fprintf(args->out, "%s\n", (char *)node->data);
+ }
+
+ return SEPOL_OK;
+}
+
+static int __write_parse_ast_first_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+ struct cil_tree_node *parent = node->parent;
+
+ if (parent->flavor != CIL_ROOT) {
+ args->depth++;
+ }
+
+ return SEPOL_OK;
+}
+
+static int __write_parse_ast_last_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+ struct cil_tree_node *parent = node->parent;
+
+ if (parent->flavor == CIL_ROOT) {
+ return SEPOL_OK;
+ }
+
+ args->depth--;
+ fprintf(args->out, "%*s", args->depth*4, "");
+ fprintf(args->out, ")\n");
+
+ return SEPOL_OK;
+}
+
+/*
+ * Helper functions for writing the CIL AST for the build and resolve phases
+ */
+
+static int __write_cil_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+
+ if (node->flavor == CIL_SRC_INFO) {
+ cil_write_src_info_node(args->out, node);
+ return SEPOL_OK;
+ }
+
+ fprintf(args->out, "%*s", args->depth*4, "");
+
+ cil_write_ast_node(args->out, node);
+
+ if (node->flavor == CIL_CLASS || node->flavor == CIL_COMMON || node->flavor == CIL_MAP_CLASS) {
+ *finished = CIL_TREE_SKIP_HEAD;
+ }
+
+ return SEPOL_OK;
+}
+
+static int __write_cil_ast_first_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+ struct cil_tree_node *parent = node->parent;
+
+ if (parent->flavor != CIL_SRC_INFO && parent->flavor != CIL_ROOT) {
+ args->depth++;
+ }
+
+ return SEPOL_OK;
+}
+
+static int __write_cil_ast_last_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+ struct cil_tree_node *parent = node->parent;
+
+ if (parent->flavor == CIL_ROOT) {
+ return SEPOL_OK;
+ } else if (parent->flavor == CIL_SRC_INFO) {
+ fprintf(args->out, ";;* lme\n");
+ return SEPOL_OK;
+ }
+
+ args->depth--;
+ fprintf(args->out, "%*s", args->depth*4, "");
+ fprintf(args->out, ")\n");
+
+ return SEPOL_OK;
+}
+
+int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node)
+{
+ struct cil_write_ast_args extra_args;
+ int rc;
+
+ extra_args.out = out;
+ extra_args.depth = 0;
+
+ if (phase == CIL_WRITE_AST_PHASE_PARSE) {
+ rc = cil_tree_walk(node, __write_parse_ast_node_helper, __write_parse_ast_first_child_helper, __write_parse_ast_last_child_helper, &extra_args);
+ } else {
+ rc = cil_tree_walk(node, __write_cil_ast_node_helper, __write_cil_ast_first_child_helper, __write_cil_ast_last_child_helper, &extra_args);
+ }
+
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write AST\n");
+ return SEPOL_ERR;
+ }
+
+ return SEPOL_OK;
+}
diff --git a/libsepol/cil/src/cil_write_ast.h b/libsepol/cil/src/cil_write_ast.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f4b9d95ca1a19bddacd0d667beec6b6fc19f8ad
--- /dev/null
+++ b/libsepol/cil/src/cil_write_ast.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011 Tresys Technology, LLC. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those
+ * of the authors and should not be interpreted as representing official policies,
+ * either expressed or implied, of Tresys Technology, LLC.
+ */
+
+#ifndef CIL_WRITE_AST_H_
+#define CIL_WRITE_AST_H_
+
+#include
+
+#include "cil_tree.h"
+
+enum cil_write_ast_phase {
+ CIL_WRITE_AST_PHASE_PARSE = 0,
+ CIL_WRITE_AST_PHASE_BUILD,
+ CIL_WRITE_AST_PHASE_RESOLVE,
+};
+
+void cil_write_ast_node(FILE *out, struct cil_tree_node *node);
+int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node);
+
+#endif /* CIL_WRITE_AST_H_ */
diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c
new file mode 100644
index 0000000000000000000000000000000000000000..255b324187c8157974d8063e9619a76b4a58c903
--- /dev/null
+++ b/libsepol/fuzz/secilc-fuzzer.c
@@ -0,0 +1,69 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ enum cil_log_level log_level = CIL_ERR;
+ struct sepol_policy_file *pf = NULL;
+ FILE *dev_null = NULL;
+ int target = SEPOL_TARGET_SELINUX;
+ int disable_dontaudit = 0;
+ int multiple_decls = 0;
+ int disable_neverallow = 0;
+ int preserve_tunables = 0;
+ int policyvers = POLICYDB_VERSION_MAX;
+ int mls = -1;
+ int attrs_expand_generated = 0;
+ struct cil_db *db = NULL;
+ sepol_policydb_t *pdb = NULL;
+
+ cil_set_log_level(log_level);
+
+ cil_db_init(&db);
+ cil_set_disable_dontaudit(db, disable_dontaudit);
+ cil_set_multiple_decls(db, multiple_decls);
+ cil_set_disable_neverallow(db, disable_neverallow);
+ cil_set_preserve_tunables(db, preserve_tunables);
+ cil_set_mls(db, mls);
+ cil_set_target_platform(db, target);
+ cil_set_policy_version(db, policyvers);
+ cil_set_attrs_expand_generated(db, attrs_expand_generated);
+
+ if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK)
+ goto exit;
+
+ if (cil_compile(db) != SEPOL_OK)
+ goto exit;
+
+ if (cil_build_policydb(db, &pdb) != SEPOL_OK)
+ goto exit;
+
+ if (sepol_policydb_optimize(pdb) != SEPOL_OK)
+ goto exit;
+
+ dev_null = fopen("/dev/null", "w");
+ if (dev_null == NULL)
+ goto exit;
+
+ if (sepol_policy_file_create(&pf) != 0)
+ goto exit;
+
+ sepol_policy_file_set_fp(pf, dev_null);
+
+ if (sepol_policydb_write(pdb, pf) != 0)
+ goto exit;
+exit:
+ if (dev_null != NULL)
+ fclose(dev_null);
+
+ cil_db_destroy(&db);
+ sepol_policydb_free(pdb);
+ sepol_policy_file_free(pf);
+ return 0;
+}
diff --git a/libsepol/include/sepol/policydb/conditional.h b/libsepol/include/sepol/policydb/conditional.h
index 9c3df3ef488e5e24baa0d56b8e2fdc66b12bc725..49c0d76631c46e61aa7533548b1fa96e6bda9f3d 100644
--- a/libsepol/include/sepol/policydb/conditional.h
+++ b/libsepol/include/sepol/policydb/conditional.h
@@ -90,7 +90,7 @@ typedef struct cond_node {
uint32_t expr_pre_comp;
struct cond_node *next;
/* a tunable conditional, calculated and used at expansion */
-#define COND_NODE_FLAGS_TUNABLE 0x01
+#define COND_NODE_FLAGS_TUNABLE UINT32_C(0x01)
uint32_t flags;
} cond_node_t;
diff --git a/libsepol/include/sepol/policydb/ebitmap.h b/libsepol/include/sepol/policydb/ebitmap.h
index 634436f6c30be893c022f51a1c4f27ce1b98c91c..81d0c7a67347809112328e36d8c777f94aeaf22a 100644
--- a/libsepol/include/sepol/policydb/ebitmap.h
+++ b/libsepol/include/sepol/policydb/ebitmap.h
@@ -67,7 +67,7 @@ static inline unsigned int ebitmap_next(ebitmap_node_t ** n, unsigned int bit)
return (bit + 1);
}
-static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit)
+static inline int ebitmap_node_get_bit(const ebitmap_node_t * n, unsigned int bit)
{
if (n->map & (MAPBIT << (bit - n->startbit)))
return 1;
@@ -83,18 +83,18 @@ static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit)
extern int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1);
-extern int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
-extern int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
-extern int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit);
-extern int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit);
-extern unsigned int ebitmap_cardinality(ebitmap_t *e1);
-extern int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2);
+extern int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2);
+extern int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2);
+extern int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit);
+extern int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit);
+extern unsigned int ebitmap_cardinality(const ebitmap_t *e1);
+extern int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src);
extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2);
extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit);
extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value);
-extern unsigned int ebitmap_highest_set_bit(ebitmap_t * e);
+extern unsigned int ebitmap_highest_set_bit(const ebitmap_t * e);
extern void ebitmap_destroy(ebitmap_t * e);
extern int ebitmap_read(ebitmap_t * e, void *fp);
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 9ef43abc2f127daf29a81423e2af3a4ab80e734d..4bf9f05ddd0a3442f033292ff0da0318f4a1a6b0 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -251,9 +251,9 @@ typedef struct class_perm_node {
struct class_perm_node *next;
} class_perm_node_t;
-#define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f)))
-#define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f)))
-#define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f)))
+#define xperm_test(x, p) (UINT32_C(1) & (p[x >> 5] >> (x & 0x1f)))
+#define xperm_set(x, p) (p[x >> 5] |= (UINT32_C(1) << (x & 0x1f)))
+#define xperm_clear(x, p) (p[x >> 5] &= ~(UINT32_C(1) << (x & 0x1f)))
#define EXTENDED_PERMS_LEN 8
typedef struct av_extended_perms {
@@ -667,8 +667,8 @@ extern int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p);
extern void class_perm_node_init(class_perm_node_t * x);
extern void type_set_init(type_set_t * x);
extern void type_set_destroy(type_set_t * x);
-extern int type_set_cpy(type_set_t * dst, type_set_t * src);
-extern int type_set_or_eq(type_set_t * dst, type_set_t * other);
+extern int type_set_cpy(type_set_t * dst, const type_set_t * src);
+extern int type_set_or_eq(type_set_t * dst, const type_set_t * other);
extern void role_set_init(role_set_t * x);
extern void role_set_destroy(role_set_t * x);
extern void avrule_init(avrule_t * x);
diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c
index 266f67d74c563b6584adce7db12f445afc3d5c33..dd2749a09dc08dbddc3f130c961c8a10a514d296 100644
--- a/libsepol/src/assertion.c
+++ b/libsepol/src/assertion.c
@@ -291,7 +291,7 @@ exit:
return rc;
}
-int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
+static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
{
int rc;
struct avtab_match_args args;
diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c
index a9832d0d118fe80e37e9bf8a4c2c3d18b7d5dfeb..dcfce8b8492c3dcc29250956b2df13726f0d521f 100644
--- a/libsepol/src/avrule_block.c
+++ b/libsepol/src/avrule_block.c
@@ -30,7 +30,7 @@
/* It is anticipated that there be less declarations within an avrule
* block than the global policy. Thus the symbol table sizes are
* smaller than those listed in policydb.c */
-static unsigned int symtab_sizes[SYM_NUM] = {
+static const unsigned int symtab_sizes[SYM_NUM] = {
2,
4,
8,
diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c
index 257f051a86ece79749fa15b81040a920fccf2c0a..46e1e75d7751fa014f0870ac404870f668890fc4 100644
--- a/libsepol/src/avtab.c
+++ b/libsepol/src/avtab.c
@@ -52,6 +52,7 @@
/* Based on MurmurHash3, written by Austin Appleby and placed in the
* public domain.
*/
+ignore_unsigned_overflow_
static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
{
static const uint32_t c1 = 0xcc9e2d51;
@@ -63,7 +64,7 @@ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
uint32_t hash = 0;
-#define mix(input) { \
+#define mix(input) do { \
uint32_t v = input; \
v *= c1; \
v = (v << r1) | (v >> (32 - r1)); \
@@ -71,7 +72,7 @@ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
hash ^= v; \
hash = (hash << r2) | (hash >> (32 - r2)); \
hash = hash * m + n; \
-}
+} while (0)
mix(keyp->target_class);
mix(keyp->target_type);
@@ -375,7 +376,7 @@ int avtab_alloc(avtab_t *h, uint32_t nrules)
}
if (shift > 2)
shift = shift - 2;
- nslot = 1 << shift;
+ nslot = UINT32_C(1) << shift;
if (nslot > MAX_AVTAB_HASH_BUCKETS)
nslot = MAX_AVTAB_HASH_BUCKETS;
mask = nslot - 1;
@@ -418,7 +419,7 @@ void avtab_hash_eval(avtab_t * h, char *tag)
}
/* Ordering of datums in the original avtab format in the policy file. */
-static uint16_t spec_order[] = {
+static const uint16_t spec_order[] = {
AVTAB_ALLOWED,
AVTAB_AUDITDENY,
AVTAB_AUDITALLOW,
diff --git a/libsepol/src/booleans.c b/libsepol/src/booleans.c
index 30fcf29d892b9ab8daed23b84e4ce051de9645b5..716da6b487a95e1a066c561993255d19e5f008a7 100644
--- a/libsepol/src/booleans.c
+++ b/libsepol/src/booleans.c
@@ -19,6 +19,7 @@ static int bool_update(sepol_handle_t * handle,
const char *cname;
char *name;
int value;
+ cond_bool_datum_t *datum;
sepol_bool_key_unpack(key, &cname);
name = strdup(cname);
@@ -27,8 +28,7 @@ static int bool_update(sepol_handle_t * handle,
if (!name)
goto omem;
- cond_bool_datum_t *datum =
- hashtab_search(policydb->p_bools.table, name);
+ datum = hashtab_search(policydb->p_bools.table, name);
if (!datum) {
ERR(handle, "boolean %s no longer in policy", name);
goto err;
@@ -84,10 +84,10 @@ int sepol_bool_set(sepol_handle_t * handle,
const sepol_bool_key_t * key, const sepol_bool_t * data)
{
+ policydb_t *policydb = &p->p;
const char *name;
sepol_bool_key_unpack(key, &name);
- policydb_t *policydb = &p->p;
if (bool_update(handle, policydb, key, data) < 0)
goto err;
diff --git a/libsepol/src/conditional.c b/libsepol/src/conditional.c
index 823b649a9163e5de7bb331010e5ad3742d590fd2..037dc7e2fcee6eb6be3c0a78e23481f2b4db9cfa 100644
--- a/libsepol/src/conditional.c
+++ b/libsepol/src/conditional.c
@@ -388,7 +388,6 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
for (e = cn->expr; e != NULL; e = e->next) {
switch (e->expr_type) {
case COND_BOOL:
- i = 0;
/* see if we've already seen this bool */
if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) {
/* count em all but only record up to COND_MAX_BOOLS */
@@ -412,13 +411,13 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
}
/* loop through all possible combinations of values for bools in expression */
- for (test = 0x0; test < (0x1U << cn->nbools); test++) {
+ for (test = 0x0; test < (UINT32_C(1) << cn->nbools); test++) {
/* temporarily set the value for all the bools in the
* expression using the corr. bit in test */
for (j = 0; j < cn->nbools; j++) {
p->bool_val_to_struct[cn->bool_ids[j] -
1]->state =
- (test & (0x1 << j)) ? 1 : 0;
+ (test & (UINT32_C(1) << j)) ? 1 : 0;
}
k = cond_evaluate_expr(p, cn->expr);
if (k == -1) {
@@ -429,7 +428,7 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
}
/* set the bit if expression evaluates true */
if (k)
- cn->expr_pre_comp |= 0x1 << test;
+ cn->expr_pre_comp |= UINT32_C(1) << test;
}
/* restore bool default values */
@@ -715,7 +714,6 @@ static int cond_read_av_list(policydb_t * p, void *fp,
*ret_list = NULL;
- len = 0;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
return -1;
@@ -769,7 +767,6 @@ static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp)
node->cur_state = le32_to_cpu(buf[0]);
- len = 0;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
goto err;
diff --git a/libsepol/src/context_internal.h b/libsepol/src/context_internal.h
index 3cae28cc1c671ecd90e86ea3995521b756443e8a..3dc9cd156a9ce921e4df4705872c579abf2ea919 100644
--- a/libsepol/src/context_internal.h
+++ b/libsepol/src/context_internal.h
@@ -1,6 +1,7 @@
#ifndef _SEPOL_CONTEXT_INTERNAL_H_
#define _SEPOL_CONTEXT_INTERNAL_H_
+#include
#include
#endif
diff --git a/libsepol/src/context_record.c b/libsepol/src/context_record.c
index 317a42133884a4a4e432b00e231d54792e739807..435f788058c47ace0200a0492452a1c6f8467f61 100644
--- a/libsepol/src/context_record.c
+++ b/libsepol/src/context_record.c
@@ -267,31 +267,13 @@ int sepol_context_from_string(sepol_handle_t * handle,
return STATUS_ERR;
}
-
-static inline int safe_sum(size_t *sum, const size_t augends[], const size_t cnt) {
-
- size_t a, i;
-
- *sum = 0;
- for(i=0; i < cnt; i++) {
- /* sum should not be smaller than the addend */
- a = augends[i];
- *sum += a;
- if (*sum < a) {
- return i;
- }
- }
-
- return 0;
-}
-
int sepol_context_to_string(sepol_handle_t * handle,
const sepol_context_t * con, char **str_ptr)
{
int rc;
char *str = NULL;
- size_t total_sz, err;
+ size_t total_sz = 0, i;
const size_t sizes[] = {
strlen(con->user), /* user length */
strlen(con->role), /* role length */
@@ -300,10 +282,11 @@ int sepol_context_to_string(sepol_handle_t * handle,
((con->mls) ? 3 : 2) + 1 /* mls has extra ":" also null byte */
};
- err = safe_sum(&total_sz, sizes, ARRAY_SIZE(sizes));
- if (err) {
- ERR(handle, "invalid size, overflow at position: %zu", err);
- goto err;
+ for (i = 0; i < ARRAY_SIZE(sizes); i++) {
+ if (__builtin_add_overflow(total_sz, sizes[i], &total_sz)) {
+ ERR(handle, "invalid size, overflow at position: %zu", i);
+ goto err;
+ }
}
str = (char *)malloc(total_sz);
diff --git a/libsepol/src/debug.c b/libsepol/src/debug.c
index 0458e3538884d90c749d1e5ff57ebf1ad645ff10..f6a59ae701ede5669a082db1235c71108c12a3c4 100644
--- a/libsepol/src/debug.c
+++ b/libsepol/src/debug.c
@@ -44,6 +44,7 @@ void sepol_msg_default_handler(void *varg __attribute__ ((unused)),
{
FILE *stream = NULL;
+ va_list ap;
switch (sepol_msg_get_level(handle)) {
@@ -60,7 +61,6 @@ void sepol_msg_default_handler(void *varg __attribute__ ((unused)),
fprintf(stream, "%s.%s: ",
sepol_msg_get_channel(handle), sepol_msg_get_fname(handle));
- va_list ap;
va_start(ap, fmt);
vfprintf(stream, fmt, ap);
va_end(ap);
diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c
index 7f425349c229b8cecac888afa0520096923131f9..1de3816aec18fa7095641599ea87e369ac9a4f76 100644
--- a/libsepol/src/ebitmap.c
+++ b/libsepol/src/ebitmap.c
@@ -17,7 +17,8 @@
int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2)
{
- ebitmap_node_t *n1, *n2, *new, *prev;
+ const ebitmap_node_t *n1, *n2;
+ ebitmap_node_t *new, *prev;
ebitmap_init(dst);
@@ -71,7 +72,7 @@ int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1)
return 0;
}
-int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2)
{
unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2));
ebitmap_init(dst);
@@ -85,7 +86,7 @@ int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
return 0;
}
-int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2)
{
unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2));
ebitmap_init(dst);
@@ -98,7 +99,7 @@ int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
return 0;
}
-int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
+int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit)
{
unsigned int i;
ebitmap_init(dst);
@@ -111,11 +112,12 @@ int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
return 0;
}
-int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit)
+int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit)
{
+ int rc;
ebitmap_t e3;
ebitmap_init(dst);
- int rc = ebitmap_not(&e3, e2, maxbit);
+ rc = ebitmap_not(&e3, e2, maxbit);
if (rc < 0)
return rc;
rc = ebitmap_and(dst, e1, &e3);
@@ -125,10 +127,10 @@ int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int ma
return 0;
}
-unsigned int ebitmap_cardinality(ebitmap_t *e1)
+unsigned int ebitmap_cardinality(const ebitmap_t *e1)
{
unsigned int count = 0;
- ebitmap_node_t *n;
+ const ebitmap_node_t *n;
for (n = e1->node; n; n = n->next) {
count += __builtin_popcountll(n->map);
@@ -136,22 +138,24 @@ unsigned int ebitmap_cardinality(ebitmap_t *e1)
return count;
}
-int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2)
+int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2)
{
+ int rc;
+ ebitmap_t tmp;
+ int distance;
if (ebitmap_cmp(e1, e2))
return 0;
- ebitmap_t tmp;
- int rc = ebitmap_xor(&tmp, e1, e2);
+ rc = ebitmap_xor(&tmp, e1, e2);
if (rc < 0)
return -1;
- int distance = ebitmap_cardinality(&tmp);
+ distance = ebitmap_cardinality(&tmp);
ebitmap_destroy(&tmp);
return distance;
}
int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2)
{
- ebitmap_node_t *n1, *n2;
+ const ebitmap_node_t *n1, *n2;
if (e1->highbit != e2->highbit)
return 0;
@@ -172,7 +176,8 @@ int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2)
int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src)
{
- ebitmap_node_t *n, *new, *prev;
+ const ebitmap_node_t *n;
+ ebitmap_node_t *new, *prev;
ebitmap_init(dst);
n = src->node;
@@ -201,7 +206,7 @@ int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src)
int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2)
{
- ebitmap_node_t *n1, *n2;
+ const ebitmap_node_t *n1, *n2;
if (e1->highbit < e2->highbit)
return 0;
@@ -228,8 +233,8 @@ int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2)
int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2)
{
- ebitmap_node_t *n1 = e1->node;
- ebitmap_node_t *n2 = e2->node;
+ const ebitmap_node_t *n1 = e1->node;
+ const ebitmap_node_t *n2 = e2->node;
while (n1 && n2) {
if (n1->startbit < n2->startbit) {
@@ -250,7 +255,7 @@ int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2)
int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit)
{
- ebitmap_node_t *n;
+ const ebitmap_node_t *n;
if (e->highbit < bit)
return 0;
@@ -344,9 +349,9 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value)
return 0;
}
-unsigned int ebitmap_highest_set_bit(ebitmap_t * e)
+unsigned int ebitmap_highest_set_bit(const ebitmap_t * e)
{
- ebitmap_node_t *n;
+ const ebitmap_node_t *n;
MAPTYPE map;
unsigned int pos = 0;
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index eac7e4507d02ae9e22e03168644d27b568854d2c..a6a466f78ee410aaf43b16fe5fa4e6240770f082 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -71,6 +71,38 @@ static int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map)
return 0;
}
+static int ebitmap_expand_roles(policydb_t *p, ebitmap_t *roles)
+{
+ ebitmap_node_t *node;
+ unsigned int bit;
+ role_datum_t *role;
+ ebitmap_t tmp;
+
+ ebitmap_init(&tmp);
+ ebitmap_for_each_positive_bit(roles, node, bit) {
+ role = p->role_val_to_struct[bit];
+ assert(role);
+ if (role->flavor != ROLE_ATTRIB) {
+ if (ebitmap_set_bit(&tmp, bit, 1)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ } else {
+ if (ebitmap_union(&tmp, &role->roles)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ }
+ }
+ ebitmap_destroy(roles);
+ if (ebitmap_cpy(roles, &tmp)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ ebitmap_destroy(&tmp);
+ return 0;
+}
+
static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
void *data)
{
@@ -211,7 +243,7 @@ static int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
new_perm->s.value = perm->s.value;
s->nprim++;
- ret = hashtab_insert(s->table, new_id, (hashtab_datum_t *) new_perm);
+ ret = hashtab_insert(s->table, new_id, (hashtab_datum_t) new_perm);
if (ret) {
free(new_id);
free(new_perm);
@@ -262,7 +294,7 @@ static int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
ret =
hashtab_insert(state->out->p_commons.table, new_id,
- (hashtab_datum_t *) new_common);
+ (hashtab_datum_t) new_common);
if (ret) {
ERR(state->handle, "hashtab overflow");
free(new_common);
@@ -333,6 +365,9 @@ static int constraint_node_clone(constraint_node_t ** dst,
if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) {
goto out_of_mem;
}
+ if (ebitmap_expand_roles(state->out, &new_expr->names)) {
+ goto out_of_mem;
+ }
} else if (new_expr->attr & CEXPR_USER) {
if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) {
goto out_of_mem;
@@ -457,7 +492,7 @@ static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
ret =
hashtab_insert(state->out->p_classes.table, new_id,
- (hashtab_datum_t *) new_class);
+ (hashtab_datum_t) new_class);
if (ret) {
ERR(state->handle, "hashtab overflow");
free(new_class);
@@ -1606,7 +1641,7 @@ static avtab_ptr_t find_avtab_node(sepol_handle_t * handle,
* AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for
* others. Initialize the data accordingly.
*/
- avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0 : 0;
+ avdatum.data = key->specified == AVTAB_AUDITDENY ? ~UINT32_C(0) : UINT32_C(0);
/* this is used to get the node - insertion is actually unique */
node = avtab_insert_nonunique(avtab, key, &avdatum);
if (!node) {
@@ -3017,10 +3052,6 @@ int expand_module(sepol_handle_t * handle,
if (hashtab_map(state.base->p_roles.table,
role_bounds_copy_callback, &state))
goto cleanup;
- /* escalate the type_set_t in a role attribute to all regular roles
- * that belongs to it. */
- if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
- goto cleanup;
/* copy MLS's sensitivity level and categories - this needs to be done
* before expanding users (they need to be indexed too) */
@@ -3086,6 +3117,11 @@ int expand_module(sepol_handle_t * handle,
goto cleanup;
}
+ /* escalate the type_set_t in a role attribute to all regular roles
+ * that belongs to it. */
+ if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
+ goto cleanup;
+
if (copy_and_expand_avrule_block(&state) < 0) {
ERR(handle, "Error during expand");
goto cleanup;
@@ -3338,9 +3374,9 @@ static int expand_cond_insert(cond_av_list_t ** l,
return 0;
}
-int expand_cond_av_node(policydb_t * p,
- avtab_ptr_t node,
- cond_av_list_t ** newl, avtab_t * expa)
+static int expand_cond_av_node(policydb_t * p,
+ avtab_ptr_t node,
+ cond_av_list_t ** newl, avtab_t * expa)
{
avtab_key_t *k = &node->key;
avtab_datum_t *d = &node->datum;
diff --git a/libsepol/src/ibendport_record.c b/libsepol/src/ibendport_record.c
index adf671615e5cdd076e9d8007f051efb98529cbfe..1eb50914b8c05e54511bfb6d5e212f4a4285ebfb 100644
--- a/libsepol/src/ibendport_record.c
+++ b/libsepol/src/ibendport_record.c
@@ -62,7 +62,7 @@ int sepol_ibendport_key_create(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_key->ibdev_name) < 0)
goto err;
- strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1);
tmp_key->port = port;
*key_ptr = tmp_key;
@@ -166,7 +166,7 @@ int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0)
goto err;
- strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1);
*ibdev_name = tmp_ibdev_name;
return STATUS_SUCCESS;
@@ -186,7 +186,7 @@ int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0)
goto err;
- strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX - 1);
free(ibendport->ibdev_name);
ibendport->ibdev_name = tmp;
return STATUS_SUCCESS;
@@ -230,7 +230,7 @@ int sepol_ibendport_clone(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &new_ibendport->ibdev_name) < 0)
goto omem;
- strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1);
new_ibendport->port = ibendport->port;
if (ibendport->con &&
diff --git a/libsepol/src/ibendports.c b/libsepol/src/ibendports.c
index 6d56c9a1793f7ce4420ba740e4a1c66b2ad0ab2b..ee5cb1930f313514868fed1b53345cfbed1c6db5 100644
--- a/libsepol/src/ibendports.c
+++ b/libsepol/src/ibendports.c
@@ -34,7 +34,7 @@ static int ibendport_from_record(sepol_handle_t *handle,
&ibdev_name) < 0)
goto err;
- strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1);
free(ibdev_name);
ibdev_name = NULL;
diff --git a/libsepol/src/ibpkey_record.c b/libsepol/src/ibpkey_record.c
index 6f7aa65602d1679abcea6327942684166bbfde4e..d95e95fe8a0d24102add0152755dbdbaf6f733aa 100644
--- a/libsepol/src/ibpkey_record.c
+++ b/libsepol/src/ibpkey_record.c
@@ -38,8 +38,8 @@ static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle,
struct in6_addr in_addr;
if (inet_pton(AF_INET6, subnet_prefix_str, &in_addr) <= 0) {
- ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %s",
- subnet_prefix_str, strerror(errno));
+ ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %m",
+ subnet_prefix_str);
return STATUS_ERR;
}
@@ -64,8 +64,7 @@ static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle,
if (inet_ntop(AF_INET6, &addr, subnet_prefix_str,
INET6_ADDRSTRLEN) == NULL) {
ERR(handle,
- "could not expand IPv6 address to string: %s",
- strerror(errno));
+ "could not expand IPv6 address to string: %m");
return STATUS_ERR;
}
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index a146ac514018eebea90dd046eba85a22ca8d774f..305567a5ef1e2b1c3438274571242f9c667ae39d 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -189,9 +189,13 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr
names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
}
if (!names) {
- goto exit;
+ names = strdup("NO_IDENTIFIER");
+ }
+ if (strchr(names, ' ')) {
+ new_val = create_str("(%s %s (%s))", 3, op, attr1, names);
+ } else {
+ new_val = create_str("(%s %s %s)", 3, op, attr1, names);
}
- new_val = create_str("(%s %s %s)", 3, op, attr1, names);
free(names);
}
} else {
@@ -1030,11 +1034,14 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
{
struct ebitmap_node *node;
uint32_t i, start, range;
- char *catsbuf, *p;
+ char *catsbuf = NULL, *p;
const char *fmt;
int len, remaining;
remaining = (int)cats_ebitmap_len(cats, val_to_name);
+ if (remaining == 0) {
+ goto exit;
+ }
catsbuf = malloc(remaining);
if (!catsbuf) {
goto exit;
@@ -1043,7 +1050,7 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
p = catsbuf;
*p++ = '(';
- remaining--;;
+ remaining--;
range = 0;
ebitmap_for_each_positive_bit(cats, node, i) {
@@ -2490,9 +2497,10 @@ static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
sepol_printf(out, ")\n");
}
- strs_destroy(&strs);
-
exit:
+ if (strs)
+ strs_destroy(&strs);
+
if (rc != 0) {
sepol_log_err("Error writing user declarations to CIL\n");
}
@@ -2650,7 +2658,7 @@ static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
- rc = strs_create_and_add(strs, "(genfscon %s %s %s)", 3,
+ rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", 3,
fstype, name, ctx);
free(ctx);
if (rc != 0) {
@@ -2772,13 +2780,13 @@ static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb)
for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon address is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon mask is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2812,13 +2820,13 @@ static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb)
for (node = pdb->ocontexts[6]; node != NULL; node = node->next) {
if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon address is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon mask is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2860,8 +2868,7 @@ static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)
if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("ibpkeycon subnet_prefix is invalid: %s",
- strerror(errno));
+ sepol_log_err("ibpkeycon subnet_prefix is invalid: %m");
rc = -1;
goto exit;
}
@@ -3111,7 +3118,7 @@ static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
- sepol_printf(out, "(devicetreecon %s %s)\n", name, ctx);
+ sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx);
free(ctx);
}
@@ -3164,6 +3171,18 @@ int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
+ if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but only in the type_attr_map. This means that there are gaps in both
+ * the type_val_to_struct and p_type_val_to_name arrays and policy rules
+ * can refer to those gaps.
+ */
+ sepol_log_err("Writing policy versions between 20 and 23 as CIL is not supported");
+ rc = -1;
+ goto exit;
+ }
+
rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
if (rc != 0) {
goto exit;
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index a22f196df9e958ddf24d25ccb9b1e09460e2f6fd..eb72e4ac983e09d6a31cb073d74fce3a563a3176 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -186,9 +186,13 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr
names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
}
if (!names) {
- goto exit;
+ names = strdup("NO_IDENTIFIER");
+ }
+ if (strchr(names, ' ')) {
+ new_val = create_str("%s %s { %s }", 3, attr1, op, names);
+ } else {
+ new_val = create_str("%s %s %s", 3, attr1, op, names);
}
- new_val = create_str("%s %s %s", 3, attr1, op, names);
free(names);
}
} else {
@@ -1021,12 +1025,15 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
{
struct ebitmap_node *node;
uint32_t i, start, range, first;
- char *catsbuf, *p;
+ char *catsbuf = NULL, *p;
const char *fmt;
char sep;
int len, remaining;
remaining = (int)cats_ebitmap_len(cats, val_to_name);
+ if (remaining == 0) {
+ goto exit;
+ }
catsbuf = malloc(remaining);
if (!catsbuf) {
goto exit;
@@ -2368,9 +2375,10 @@ static int write_user_decl_rules_to_conf(FILE *out, struct policydb *pdb)
sepol_printf(out, ";\n");
}
- strs_destroy(&strs);
-
exit:
+ if (strs)
+ strs_destroy(&strs);
+
if (rc != 0) {
sepol_log_err("Error writing user declarations to policy.conf\n");
}
@@ -2523,7 +2531,7 @@ static int write_genfscon_rules_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
- rc = strs_create_and_add(strs, "genfscon %s %s %s", 3,
+ rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s", 3,
fstype, name, ctx);
free(ctx);
if (rc != 0) {
@@ -2645,13 +2653,13 @@ static int write_selinux_node_rules_to_conf(FILE *out, struct policydb *pdb)
for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon address is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon mask is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2686,13 +2694,13 @@ static int write_selinux_node6_rules_to_conf(FILE *out, struct policydb *pdb)
for (node6 = pdb->ocontexts[6]; node6 != NULL; node6 = node6->next) {
if (inet_ntop(AF_INET6, &node6->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon address is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET6, &node6->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon mask is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2734,8 +2742,7 @@ static int write_selinux_ibpkey_rules_to_conf(FILE *out, struct policydb *pdb)
if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("ibpkeycon address is invalid: %s",
- strerror(errno));
+ sepol_log_err("ibpkeycon address is invalid: %m");
rc = -1;
goto exit;
}
@@ -2988,7 +2995,7 @@ static int write_xen_devicetree_rules_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
- sepol_printf(out, "devicetreecon %s %s\n", name, ctx);
+ sepol_printf(out, "devicetreecon \"%s\" %s\n", name, ctx);
free(ctx);
}
@@ -3041,6 +3048,18 @@ int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
+ if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but only in the type_attr_map. This means that there are gaps in both
+ * the type_val_to_struct and p_type_val_to_name arrays and policy rules
+ * can refer to those gaps.
+ */
+ sepol_log_err("Writing policy versions between 20 and 23 as a policy.conf is not supported");
+ rc = -1;
+ goto exit;
+ }
+
rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
if (rc != 0) {
goto exit;
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index eb5721257638faacd1c9d18f424d499a87e6eee2..0e05d606478945e93e6bf0ad8248349cc4e06435 100644
--- a/libsepol/src/libsepol.map.in
+++ b/libsepol/src/libsepol.map.in
@@ -269,4 +269,8 @@ LIBSEPOL_1.1 {
LIBSEPOL_3.0 {
global:
sepol_policydb_optimize;
+ cil_write_parse_ast;
+ cil_write_build_ast;
+ cil_write_resolve_ast;
+ cil_set_qualified_names;
} LIBSEPOL_1.1;
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index 83bbc8a5c7d14e8b241af0383aa3d14f9602ad6b..7512a4d927f9afec26444f18b3f4389c9a3102a2 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -78,7 +78,7 @@ typedef struct missing_requirement {
uint32_t perm_value;
} missing_requirement_t;
-static const char *symtab_names[SYM_NUM] = {
+static const char * const symtab_names[SYM_NUM] = {
"common", "class", "role", "type/attribute", "user",
"bool", "level", "category"
};
@@ -1291,10 +1291,10 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst,
i <
module->perm_map_len[cur_perm->tclass - 1];
i++) {
- if (!(cur_perm->data & (1U << i)))
+ if (!(cur_perm->data & (UINT32_C(1) << i)))
continue;
new_perm->data |=
- (1U <<
+ (UINT32_C(1) <<
(module->
perm_map[cur_perm->tclass - 1][i] -
1));
@@ -2573,36 +2573,6 @@ int link_modules(sepol_handle_t * handle,
goto cleanup;
}
- /* copy all types, declared and required */
- for (i = 0; i < len; i++) {
- state.cur = modules[i];
- state.cur_mod_name = modules[i]->policy->name;
- ret =
- hashtab_map(modules[i]->policy->p_types.table,
- type_copy_callback, &state);
- if (ret) {
- retval = ret;
- goto cleanup;
- }
- }
-
- /* then copy everything else, including aliases, and fixup attributes */
- for (i = 0; i < len; i++) {
- state.cur = modules[i];
- state.cur_mod_name = modules[i]->policy->name;
- ret =
- copy_identifiers(&state, modules[i]->policy->symtab, NULL);
- if (ret) {
- retval = ret;
- goto cleanup;
- }
- }
-
- if (policydb_index_others(state.handle, state.base, 0)) {
- ERR(state.handle, "Error while indexing others");
- goto cleanup;
- }
-
/* copy and remap the module's data over to base */
for (i = 0; i < len; i++) {
state.cur = modules[i];
diff --git a/libsepol/src/module.c b/libsepol/src/module.c
index 836da308f8d3bdd516e6384549426dc7093ce038..02a5de2ca5dd04606e3eb504b004a49be76c3bee 100644
--- a/libsepol/src/module.c
+++ b/libsepol/src/module.c
@@ -82,7 +82,7 @@ static int policy_file_length(struct policy_file *fp, size_t *out)
break;
case PF_USE_MEMORY:
*out = fp->size;
- break;;
+ break;
default:
*out = 0;
break;
@@ -796,7 +796,9 @@ int sepol_module_package_info(struct sepol_policy_file *spf, int *type,
len = le32_to_cpu(buf[0]);
if (str_read(name, file, len)) {
- ERR(file->handle, "%s", strerror(errno));
+ ERR(file->handle,
+ "cannot read module name (at section %u): %m",
+ i);
goto cleanup;
}
@@ -809,7 +811,9 @@ int sepol_module_package_info(struct sepol_policy_file *spf, int *type,
}
len = le32_to_cpu(buf[0]);
if (str_read(version, file, len)) {
- ERR(file->handle, "%s", strerror(errno));
+ ERR(file->handle,
+ "cannot read module version (at section %u): %m",
+ i);
goto cleanup;
}
seen |= SEEN_MOD;
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index a87bc15e761031bfd13109f80bf678f5e155ddaf..16e4004e3ae8670179c82a88e02173b355ad6693 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -62,7 +62,7 @@
# define UNUSED(x) UNUSED_ ## x
#endif
-FILE *out_file;
+static FILE *out_file;
#define STACK_SIZE 16
#define DEFAULT_LEVEL "systemlow"
@@ -107,8 +107,8 @@ static void cil_printf(const char *fmt, ...) {
__attribute__ ((format(printf, 2, 3)))
static void cil_println(int indent, const char *fmt, ...)
{
- cil_indent(indent);
va_list argptr;
+ cil_indent(indent);
va_start(argptr, fmt);
if (vfprintf(out_file, fmt, argptr) < 0) {
log_err("Failed to write to output");
@@ -235,12 +235,14 @@ static void role_list_destroy(void)
static void attr_list_destroy(struct list **attr_list)
{
+ struct list_node *curr;
+ struct attr_list_node *attr;
+
if (attr_list == NULL || *attr_list == NULL) {
return;
}
- struct list_node *curr = (*attr_list)->head;
- struct attr_list_node *attr;
+ curr = (*attr_list)->head;
while (curr != NULL) {
attr = curr->data;
@@ -571,7 +573,7 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const
rule = "auditallow";
break;
case AVRULE_AUDITDENY:
- rule = "auditdenty";
+ rule = "auditdeny";
break;
case AVRULE_DONTAUDIT:
rule = "dontaudit";
@@ -717,9 +719,9 @@ exit:
return rc;
}
-static int num_digits(int n)
+static unsigned int num_digits(unsigned int n)
{
- int num = 1;
+ unsigned int num = 1;
while (n >= 10) {
n /= 10;
num++;
@@ -945,7 +947,7 @@ static char *search_attr_list(struct list *attr_list, int is_type, void *set)
return NULL;
}
-static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, int *num_names)
+static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, unsigned int *num_names)
{
char *attr_name = NULL;
int rc = 0;
@@ -982,12 +984,12 @@ exit:
return rc;
}
-static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, int *num_names)
+static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, unsigned int *num_names)
{
int rc = 0;
struct ebitmap_node *node;
uint32_t i;
- uint32_t num;
+ unsigned int num;
char **name_arr;
num = 0;
@@ -1026,7 +1028,7 @@ exit:
return rc;
}
-static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, int *num_names)
+static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, unsigned int *num_names)
{
int rc = 0;
@@ -1049,7 +1051,7 @@ exit:
return rc;
}
-static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, int *num_names)
+static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, unsigned int *num_names)
{
int rc = 0;
@@ -1072,7 +1074,7 @@ exit:
return rc;
}
-static void names_destroy(char ***names, int *num_names)
+static void names_destroy(char ***names, unsigned int *num_names)
{
free(*names);
*names = NULL;
@@ -1083,7 +1085,7 @@ static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack *
{
struct list_node *curr;
char **tnames = NULL;
- int num_tnames, i;
+ unsigned int num_tnames, i;
struct role_list_node *role_node = NULL;
int rc;
struct type_set *ts;
@@ -1124,26 +1126,24 @@ exit:
}
-static int name_list_to_string(char **names, int num_names, char **string)
+static int name_list_to_string(char **names, unsigned int num_names, char **string)
{
// create a space separated string of the names
int rc = -1;
size_t len = 0;
- int i;
+ unsigned int i;
char *str;
char *strpos;
for (i = 0; i < num_names; i++) {
- len += strlen(names[i]);
- if (len < strlen(names[i])) {
+ if (__builtin_add_overflow(len, strlen(names[i]), &len)) {
log_err("Overflow");
return -1;
}
}
// add spaces + null terminator
- len += num_names;
- if (len < (size_t)num_names) {
+ if (__builtin_add_overflow(len, (size_t)num_names, &len)) {
log_err("Overflow");
return -1;
}
@@ -1184,7 +1184,7 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
struct avrule *avrule;
char **snames = NULL;
char **tnames = NULL;
- int s, t, num_snames, num_tnames;
+ unsigned int s, t, num_snames, num_tnames;
struct type_set *ts;
for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) {
@@ -1257,7 +1257,7 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *
char *new_val = NULL;
char *val1 = NULL;
char *val2 = NULL;
- int num_params;
+ unsigned int num_params;
const char *op;
const char *fmt_str;
const char *type;
@@ -1432,11 +1432,11 @@ static int role_trans_to_cil(int indent, struct policydb *pdb, struct role_trans
int rc = 0;
struct role_trans_rule *rule;
char **role_names = NULL;
- int num_role_names = 0;
- int role;
+ unsigned int num_role_names = 0;
+ unsigned int role;
char **type_names = NULL;
- int num_type_names = 0;
- int type;
+ unsigned int num_type_names = 0;
+ unsigned int type;
uint32_t i;
struct ebitmap_node *node;
struct type_set *ts;
@@ -1482,10 +1482,10 @@ static int role_allows_to_cil(int indent, struct policydb *pdb, struct role_allo
int rc = -1;
struct role_allow_rule *rule;
char **roles = NULL;
- int num_roles = 0;
+ unsigned int num_roles = 0;
char **new_roles = NULL;
- int num_new_roles = 0;
- int i,j;
+ unsigned int num_new_roles = 0;
+ unsigned int i, j;
struct role_set *rs;
for (rule = rules; rule != NULL; rule = rule->next) {
@@ -1525,11 +1525,11 @@ static int range_trans_to_cil(int indent, struct policydb *pdb, struct range_tra
int rc = -1;
struct range_trans_rule *rule;
char **stypes = NULL;
- int num_stypes = 0;
- int stype;
+ unsigned int num_stypes = 0;
+ unsigned int stype;
char **ttypes = NULL;
- int num_ttypes = 0;
- int ttype;
+ unsigned int num_ttypes = 0;
+ unsigned int ttype;
struct ebitmap_node *node;
uint32_t i;
struct type_set *ts;
@@ -1594,11 +1594,11 @@ static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filena
{
int rc = -1;
char **stypes = NULL;
- int num_stypes = 0;
- int stype;
+ unsigned int num_stypes = 0;
+ unsigned int stype;
char **ttypes = NULL;
- int num_ttypes = 0;
- int ttype;
+ unsigned int num_ttypes = 0;
+ unsigned int ttype;
struct type_set *ts;
struct filename_trans_rule *rule;
@@ -1716,7 +1716,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
const char *attr2;
char *names = NULL;
char **name_list = NULL;
- int num_names = 0;
+ unsigned int num_names = 0;
struct type_set *ts;
rc = stack_init(&stack);
@@ -1793,20 +1793,31 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
goto exit;
}
}
- rc = name_list_to_string(name_list, num_names, &names);
- if (rc != 0) {
- goto exit;
+ if (num_names == 0) {
+ names = strdup("NO_IDENTIFIER");
+ } else {
+ rc = name_list_to_string(name_list, num_names, &names);
+ if (rc != 0) {
+ goto exit;
+ }
}
// length of values/oper + 2 spaces + 2 parens + null terminator
len = strlen(op) + strlen(attr1) + strlen(names) + 2 + 2 + 1;
+ if (num_names > 1) {
+ len += 2; // 2 more parens
+ }
new_val = malloc(len);
if (new_val == NULL) {
log_err("Out of memory");
rc = -1;
goto exit;
}
- rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names);
+ if (num_names > 1) {
+ rlen = snprintf(new_val, len, "(%s %s (%s))", op, attr1, names);
+ } else {
+ rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names);
+ }
if (rlen < 0 || rlen >= len) {
log_err("Failed to generate constraint expression");
rc = -1;
@@ -2090,9 +2101,9 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
int rc = -1;
struct ebitmap_node *node;
uint32_t i;
- int j;
+ unsigned int j;
char **types = NULL;
- int num_types = 0;
+ unsigned int num_types = 0;
struct role_datum *role = datum;
struct type_set *ts;
struct list *attr_list = NULL;
@@ -2657,8 +2668,7 @@ static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb,
if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
- log_err("ibpkeycon subnet_prefix is invalid: %s",
- strerror(errno));
+ log_err("ibpkeycon subnet_prefix is invalid: %m");
rc = -1;
goto exit;
}
@@ -2703,13 +2713,13 @@ static int ocontext_selinux_node_to_cil(struct policydb *pdb, struct ocontext *n
for (node = nodes; node != NULL; node = node->next) {
if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
- log_err("Nodecon address is invalid: %s", strerror(errno));
+ log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
- log_err("Nodecon mask is invalid: %s", strerror(errno));
+ log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2735,13 +2745,13 @@ static int ocontext_selinux_node6_to_cil(struct policydb *pdb, struct ocontext *
for (node = nodes; node != NULL; node = node->next) {
if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
- log_err("Nodecon address is invalid: %s", strerror(errno));
+ log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
- log_err("Nodecon mask is invalid: %s", strerror(errno));
+ log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2954,7 +2964,7 @@ static int genfscon_to_cil(struct policydb *pdb)
for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
- cil_printf("(genfscon %s %s ", genfs->fstype, ocon->u.name);
+ cil_printf("(genfscon %s \"%s\" ", genfs->fstype, ocon->u.name);
context_to_cil(pdb, &ocon->context[0]);
cil_printf(")\n");
}
@@ -3344,9 +3354,14 @@ static int typealiases_to_cil(int indent, struct policydb *pdb, struct avrule_bl
char *type_name;
struct list_node *curr;
struct avrule_decl *decl = stack_peek(decl_stack);
- struct list *alias_list = typealias_lists[decl->decl_id];
+ struct list *alias_list;
int rc = -1;
+ if (decl == NULL) {
+ return -1;
+ }
+
+ alias_list = typealias_lists[decl->decl_id];
if (alias_list == NULL) {
return 0;
}
@@ -3516,12 +3531,12 @@ exit:
static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
{
int rc = -1;
+ struct avrule_decl *decl = stack_peek(decl_stack);
struct map_args args;
args.pdb = pdb;
args.block = block;
args.decl_stack = decl_stack;
args.indent = indent;
- struct avrule_decl *decl = stack_peek(decl_stack);
for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) {
if (func_to_cil[args.sym_index] == NULL) {
@@ -3963,7 +3978,7 @@ int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked)
if (pdb->policy_type != SEPOL_POLICY_BASE &&
pdb->policy_type != SEPOL_POLICY_MOD) {
- log_err("Policy pakcage is not a base or module");
+ log_err("Policy package is not a base or module");
rc = -1;
goto exit;
}
diff --git a/libsepol/src/node_record.c b/libsepol/src/node_record.c
index 9ef429da876871980fe4660e7f4165829194f612..2e575bf12abd8091667703b2b6085e3098112287 100644
--- a/libsepol/src/node_record.c
+++ b/libsepol/src/node_record.c
@@ -53,7 +53,7 @@ static int node_parse_addr(sepol_handle_t * handle,
if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) {
ERR(handle, "could not parse IPv4 address "
- "%s: %s", addr_str, strerror(errno));
+ "%s: %m", addr_str);
return STATUS_ERR;
}
@@ -66,7 +66,7 @@ static int node_parse_addr(sepol_handle_t * handle,
if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) {
ERR(handle, "could not parse IPv6 address "
- "%s: %s", addr_str, strerror(errno));
+ "%s: %m", addr_str);
return STATUS_ERR;
}
@@ -147,8 +147,7 @@ static int node_expand_addr(sepol_handle_t * handle,
INET_ADDRSTRLEN) == NULL) {
ERR(handle,
- "could not expand IPv4 address to string: %s",
- strerror(errno));
+ "could not expand IPv4 address to string: %m");
return STATUS_ERR;
}
break;
@@ -163,8 +162,7 @@ static int node_expand_addr(sepol_handle_t * handle,
INET6_ADDRSTRLEN) == NULL) {
ERR(handle,
- "could not expand IPv6 address to string: %s",
- strerror(errno));
+ "could not expand IPv6 address to string: %m");
return STATUS_ERR;
}
break;
diff --git a/libsepol/src/nodes.c b/libsepol/src/nodes.c
index 820346d0f5df96ea6d9d58b7d091099b581e1821..97a0f959c7caff480307bf6850e9c1b2a94e63c6 100644
--- a/libsepol/src/nodes.c
+++ b/libsepol/src/nodes.c
@@ -19,20 +19,20 @@ static int node_from_record(sepol_handle_t * handle,
ocontext_t *tmp_node = NULL;
context_struct_t *tmp_con = NULL;
char *addr_buf = NULL, *mask_buf = NULL;
+ size_t addr_bsize, mask_bsize;
+ int proto;
tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
if (!tmp_node)
goto omem;
- size_t addr_bsize, mask_bsize;
-
/* Address and netmask */
if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
goto err;
if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
goto err;
- int proto = sepol_node_get_proto(data);
+ proto = sepol_node_get_proto(data);
switch (proto) {
case SEPOL_PROTO_IP4:
diff --git a/libsepol/src/polcaps.c b/libsepol/src/polcaps.c
index 67ed5786db1603f56749077f6b9f605c9505a956..6a74ec7d3c3af8ad073158d305b1328fe8bc4cad 100644
--- a/libsepol/src/polcaps.c
+++ b/libsepol/src/polcaps.c
@@ -5,7 +5,7 @@
#include
#include
-static const char *polcap_names[] = {
+static const char * const polcap_names[] = {
"network_peer_controls", /* POLICYDB_CAPABILITY_NETPEER */
"open_perms", /* POLICYDB_CAPABILITY_OPENPERM */
"extended_socket_class", /* POLICYDB_CAPABILITY_EXTSOCKCLASS */
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index ffa2797156865a69127e32b2d22a4e220489d2f7..587ba64a5dbe7726a1b51801dff2e8e12e67691d 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -57,10 +57,10 @@
#include "policydb_validate.h"
#define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings)
-const char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
+const char * const 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[] = {
+static const struct policydb_compat_info policydb_compat[] = {
{
.type = POLICY_KERN,
.version = POLICYDB_VERSION_BOUNDARY,
@@ -460,7 +460,7 @@ static char *symtab_name[SYM_NUM] = {
};
#endif
-static unsigned int symtab_sizes[SYM_NUM] = {
+static const unsigned int symtab_sizes[SYM_NUM] = {
2,
32,
16,
@@ -471,12 +471,12 @@ static unsigned int symtab_sizes[SYM_NUM] = {
16,
};
-struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
- unsigned int type,
- unsigned int target_platform)
+const struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
+ unsigned int type,
+ unsigned int target_platform)
{
unsigned int i;
- struct policydb_compat_info *info = NULL;
+ const struct policydb_compat_info *info = NULL;
for (i = 0; i < sizeof(policydb_compat) / sizeof(*info); i++) {
if (policydb_compat[i].version == version &&
@@ -635,7 +635,7 @@ void role_trans_rule_init(role_trans_rule_t * x)
ebitmap_init(&x->classes);
}
-void role_trans_rule_destroy(role_trans_rule_t * x)
+static void role_trans_rule_destroy(role_trans_rule_t * x)
{
if (x != NULL) {
role_set_destroy(&x->roles);
@@ -789,6 +789,7 @@ static int roles_init(policydb_t * p)
goto out;
}
+ignore_unsigned_overflow_
static inline unsigned long
partial_name_hash(unsigned long c, unsigned long prevhash)
{
@@ -817,11 +818,11 @@ static int filenametr_cmp(hashtab_t h __attribute__ ((unused)),
const filename_trans_key_t *ft2 = (const filename_trans_key_t *)k2;
int v;
- v = ft1->ttype - ft2->ttype;
+ v = spaceship_cmp(ft1->ttype, ft2->ttype);
if (v)
return v;
- v = ft1->tclass - ft2->tclass;
+ v = spaceship_cmp(ft1->tclass, ft2->tclass);
if (v)
return v;
@@ -843,15 +844,15 @@ static int rangetr_cmp(hashtab_t h __attribute__ ((unused)),
const struct range_trans *key2 = (const struct range_trans *)k2;
int v;
- v = key1->source_type - key2->source_type;
+ v = spaceship_cmp(key1->source_type, key2->source_type);
if (v)
return v;
- v = key1->target_type - key2->target_type;
+ v = spaceship_cmp(key1->target_type, key2->target_type);
if (v)
return v;
- v = key1->target_class - key2->target_class;
+ v = spaceship_cmp(key1->target_class, key2->target_class);
return v;
}
@@ -1166,7 +1167,7 @@ int policydb_index_bools(policydb_t * p)
return 0;
}
-int policydb_index_decls(sepol_handle_t * handle, policydb_t * p)
+static int policydb_index_decls(sepol_handle_t * handle, policydb_t * p)
{
avrule_block_t *curblock;
avrule_decl_t *decl;
@@ -1426,7 +1427,7 @@ static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum,
return 0;
}
-void ocontext_selinux_free(ocontext_t **ocontexts)
+static void ocontext_selinux_free(ocontext_t **ocontexts)
{
ocontext_t *c, *ctmp;
int i;
@@ -1448,7 +1449,7 @@ void ocontext_selinux_free(ocontext_t **ocontexts)
}
}
-void ocontext_xen_free(ocontext_t **ocontexts)
+static void ocontext_xen_free(ocontext_t **ocontexts)
{
ocontext_t *c, *ctmp;
int i;
@@ -1747,7 +1748,7 @@ int symtab_insert(policydb_t * pol, uint32_t sym,
return retval;
}
-int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
+static int type_set_or(type_set_t * dst, const type_set_t * a, const type_set_t * b)
{
type_set_init(dst);
@@ -1764,7 +1765,7 @@ int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
return 0;
}
-int type_set_cpy(type_set_t * dst, type_set_t * src)
+int type_set_cpy(type_set_t * dst, const type_set_t * src)
{
type_set_init(dst);
@@ -1777,7 +1778,7 @@ int type_set_cpy(type_set_t * dst, type_set_t * src)
return 0;
}
-int type_set_or_eq(type_set_t * dst, type_set_t * other)
+int type_set_or_eq(type_set_t * dst, const type_set_t * other)
{
int ret;
type_set_t tmp;
@@ -1791,24 +1792,6 @@ int type_set_or_eq(type_set_t * dst, type_set_t * other)
return ret;
}
-int role_set_get_role(role_set_t * x, uint32_t role)
-{
- if (x->flags & ROLE_STAR)
- return 1;
-
- if (ebitmap_get_bit(&x->roles, role - 1)) {
- if (x->flags & ROLE_COMP)
- return 0;
- else
- return 1;
- } else {
- if (x->flags & ROLE_COMP)
- return 1;
- else
- return 0;
- }
-}
-
/***********************************************************************/
/* everything below is for policy reads */
@@ -2521,7 +2504,7 @@ static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
return -1;
}
-int role_trans_read(policydb_t *p, struct policy_file *fp)
+static int role_trans_read(policydb_t *p, struct policy_file *fp)
{
role_trans_t **t = &p->role_tr;
unsigned int i;
@@ -2564,7 +2547,7 @@ int role_trans_read(policydb_t *p, struct policy_file *fp)
return 0;
}
-int role_allow_read(role_allow_t ** r, struct policy_file *fp)
+static int role_allow_read(role_allow_t ** r, struct policy_file *fp)
{
unsigned int i;
uint32_t buf[2], nel;
@@ -2839,7 +2822,7 @@ err:
return -1;
}
-int filename_trans_read(policydb_t *p, struct policy_file *fp)
+static int filename_trans_read(policydb_t *p, struct policy_file *fp)
{
unsigned int i;
uint32_t buf[1], nel;
@@ -2866,7 +2849,7 @@ int filename_trans_read(policydb_t *p, struct policy_file *fp)
return 0;
}
-static int ocontext_read_xen(struct policydb_compat_info *info,
+static int ocontext_read_xen(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
unsigned int i, j;
@@ -2975,7 +2958,7 @@ static int ocontext_read_xen(struct policydb_compat_info *info,
}
return 0;
}
-static int ocontext_read_selinux(struct policydb_compat_info *info,
+static int ocontext_read_selinux(const struct policydb_compat_info *info,
policydb_t * p, struct policy_file *fp)
{
unsigned int i, j;
@@ -3153,7 +3136,7 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
return 0;
}
-static int ocontext_read(struct policydb_compat_info *info,
+static int ocontext_read(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
int rc = -1;
@@ -4183,7 +4166,7 @@ static sepol_access_vector_t policydb_string_to_av_perm(
hashtab_search(tclass_datum->permissions.table,
(hashtab_key_t)perm_name);
if (perm_datum != NULL)
- return 0x1U << (perm_datum->s.value - 1);
+ return UINT32_C(1) << (perm_datum->s.value - 1);
if (tclass_datum->comdatum == NULL)
return 0;
@@ -4193,7 +4176,7 @@ static sepol_access_vector_t policydb_string_to_av_perm(
(hashtab_key_t)perm_name);
if (perm_datum != NULL)
- return 0x1U << (perm_datum->s.value - 1);
+ return UINT32_C(1) << (perm_datum->s.value - 1);
return 0;
}
@@ -4210,7 +4193,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
uint32_t buf[5];
size_t len, nprim, nel;
char *policydb_str;
- struct policydb_compat_info *info;
+ const struct policydb_compat_info *info;
unsigned int policy_type, bufindex;
ebitmap_node_t *tnode;
int rc;
diff --git a/libsepol/src/policydb_internal.h b/libsepol/src/policydb_internal.h
index 06ba5c8be1446de938ab9967ff942dd6d4e9be94..dd8f25d0fc743a6934338639b172490f2b7f68b9 100644
--- a/libsepol/src/policydb_internal.h
+++ b/libsepol/src/policydb_internal.h
@@ -3,5 +3,5 @@
#include
-extern const char *policydb_target_strings[];
+extern const char * const policydb_target_strings[];
#endif
diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c
index b2891ddd64f3e55a73854501ef49be672e8dd531..5804d24742995577abca56c4f592d7beb31d2fc0 100644
--- a/libsepol/src/policydb_validate.c
+++ b/libsepol/src/policydb_validate.c
@@ -641,7 +641,7 @@ static int validate_scope_index(sepol_handle_t *handle, scope_index_t *scope_ind
return 0;
bad:
- ERR(handle, "Invalide scope");
+ ERR(handle, "Invalid scope");
return -1;
}
@@ -722,12 +722,21 @@ bad:
return -1;
}
+static void validate_array_destroy(validate_t flavors[])
+{
+ unsigned int i;
+
+ for (i = 0; i < SYM_NUM; i++) {
+ ebitmap_destroy(&flavors[i].gaps);
+ }
+}
+
/*
* Validate policydb
*/
int validate_policydb(sepol_handle_t *handle, policydb_t *p)
{
- validate_t flavors[SYM_NUM];
+ validate_t flavors[SYM_NUM] = {};
if (validate_array_init(p, flavors))
goto bad;
@@ -756,9 +765,12 @@ int validate_policydb(sepol_handle_t *handle, policydb_t *p)
if (validate_datum_arrays(handle, p, flavors))
goto bad;
+ validate_array_destroy(flavors);
+
return 0;
bad:
ERR(handle, "Invalid policydb");
+ validate_array_destroy(flavors);
return -1;
}
diff --git a/libsepol/src/private.h b/libsepol/src/private.h
index f5b5277f183a5ace1f8880326885aa3b61100048..71287282fbc0670aecd2b570a16eb9a49520ec9e 100644
--- a/libsepol/src/private.h
+++ b/libsepol/src/private.h
@@ -47,6 +47,19 @@
#define is_saturated(x) (x == (typeof(x))-1)
#define zero_or_saturated(x) ((x == 0) || is_saturated(x))
+#define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b)))
+
+/* Use to ignore intentional unsigned under- and overflows while running under UBSAN. */
+#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 4)
+#if (__clang_major__ >= 12)
+#define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow", "unsigned-shift-base")))
+#else
+#define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#else
+#define ignore_unsigned_overflow_
+#endif
+
/* Policy compatibility information. */
struct policydb_compat_info {
unsigned int type;
@@ -56,9 +69,9 @@ struct policydb_compat_info {
unsigned int target_platform;
};
-extern struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
- unsigned int type,
- unsigned int target_platform);
+extern const struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
+ unsigned int type,
+ unsigned int target_platform);
/* Reading from a policy "file". */
extern int next_entry(void *buf, struct policy_file *fp, size_t bytes);
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 6596431c38e24dc36ef187f7016cb0d5d7d48e5d..3407058fd446915e1cb311eb92bd8a202040ad47 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -86,7 +86,7 @@ static int next_stack_entry;
static void push(char *expr_ptr)
{
if (next_stack_entry >= stack_len) {
- char **new_stack = stack;
+ char **new_stack;
int new_stack_len;
if (stack_len == 0)
@@ -145,7 +145,7 @@ int sepol_set_policydb_from_file(FILE * fp)
}
if (policydb_read(&mypolicydb, &pf, 0)) {
policydb_destroy(&mypolicydb);
- ERR(NULL, "can't read binary policy: %s", strerror(errno));
+ ERR(NULL, "can't read binary policy: %m");
return -1;
}
policydb = &mypolicydb;
@@ -175,7 +175,7 @@ static int expr_buf_len;
static void cat_expr_buf(char *e_buf, const char *string)
{
int len, new_buf_len;
- char *p, *new_buf = e_buf;
+ char *p, *new_buf;
while (1) {
p = e_buf + expr_buf_used;
@@ -290,6 +290,19 @@ static char *get_class_info(sepol_security_class_t tclass,
{
constraint_expr_t *e;
int mls, state_num;
+ /* Determine statement type */
+ const char *statements[] = {
+ "constrain ", /* 0 */
+ "mlsconstrain ", /* 1 */
+ "validatetrans ", /* 2 */
+ "mlsvalidatetrans ", /* 3 */
+ 0 };
+ size_t class_buf_len = 0;
+ size_t new_class_buf_len;
+ size_t buf_used;
+ int len;
+ char *class_buf = NULL, *p;
+ char *new_class_buf = NULL;
/* Find if MLS statement or not */
mls = 0;
@@ -300,26 +313,11 @@ static char *get_class_info(sepol_security_class_t tclass,
}
}
- /* Determine statement type */
- const char *statements[] = {
- "constrain ", /* 0 */
- "mlsconstrain ", /* 1 */
- "validatetrans ", /* 2 */
- "mlsvalidatetrans ", /* 3 */
- 0 };
-
if (xcontext == NULL)
state_num = mls + 0;
else
state_num = mls + 2;
- size_t class_buf_len = 0;
- size_t new_class_buf_len;
- size_t buf_used;
- int len;
- char *class_buf = NULL, *p;
- char *new_class_buf = NULL;
-
while (1) {
new_class_buf_len = class_buf_len + EXPR_BUF_SIZE;
new_class_buf = realloc(class_buf, new_class_buf_len);
@@ -408,7 +406,7 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
#define TARGET 2
#define XTARGET 3
- int s_t_x_num = SOURCE;
+ int s_t_x_num;
/* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */
int u_r_t = 0;
@@ -417,6 +415,8 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
char *tgt = NULL;
int rc = 0, x;
char *class_buf = NULL;
+ int expr_list_len = 0;
+ int expr_count;
/*
* The array of expression answer buffer pointers and counter.
@@ -424,6 +424,11 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
char **answer_list = NULL;
int answer_counter = 0;
+ /* The pop operands */
+ char *a;
+ char *b;
+ int a_len, b_len;
+
class_buf = get_class_info(tclass, constraint, xcontext);
if (!class_buf) {
ERR(NULL, "failed to allocate class buffer");
@@ -431,13 +436,12 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
}
/* Original function but with buffer support */
- int expr_list_len = 0;
expr_counter = 0;
expr_list = NULL;
for (e = constraint->expr; e; e = e->next) {
/* Allocate a stack to hold expression buffer entries */
if (expr_counter >= expr_list_len) {
- char **new_expr_list = expr_list;
+ char **new_expr_list;
int new_expr_list_len;
if (expr_list_len == 0)
@@ -701,7 +705,7 @@ mls_ops:
* expr_list malloc's. Normally they are released by the RPN to
* infix code.
*/
- int expr_count = expr_counter;
+ expr_count = expr_counter;
expr_counter = 0;
/*
@@ -715,11 +719,6 @@ mls_ops:
goto out;
}
- /* The pop operands */
- char *a;
- char *b;
- int a_len, b_len;
-
/* Convert constraint from RPN to infix notation. */
for (x = 0; x != expr_count; x++) {
if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x],
@@ -778,14 +777,6 @@ mls_ops:
xcontext ? "Validatetrans" : "Constraint",
s[0] ? "GRANTED" : "DENIED");
- int len, new_buf_len;
- char *p, **new_buf = r_buf;
- /*
- * These contain the constraint components that are added to the
- * callers reason buffer.
- */
- const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
-
/*
* This will add the constraints to the callers reason buffer (who is
* responsible for freeing the memory). It will handle any realloc's
@@ -796,6 +787,14 @@ mls_ops:
if (r_buf && ((s[0] == 0) || ((s[0] == 1 &&
(flags & SHOW_GRANTED) == SHOW_GRANTED)))) {
+ int len, new_buf_len;
+ char *p, **new_buf = r_buf;
+ /*
+ * These contain the constraint components that are added to the
+ * callers reason buffer.
+ */
+ const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
+
for (x = 0; buffers[x] != NULL; x++) {
while (1) {
p = *r_buf + reason_buf_used;
@@ -1024,53 +1023,6 @@ static int context_struct_compute_av(context_struct_t * scontext,
return 0;
}
-int sepol_validate_transition(sepol_security_id_t oldsid,
- sepol_security_id_t newsid,
- sepol_security_id_t tasksid,
- sepol_security_class_t tclass)
-{
- context_struct_t *ocontext;
- context_struct_t *ncontext;
- context_struct_t *tcontext;
- class_datum_t *tclass_datum;
- constraint_node_t *constraint;
-
- if (!tclass || tclass > policydb->p_classes.nprim) {
- ERR(NULL, "unrecognized class %d", tclass);
- return -EINVAL;
- }
- tclass_datum = policydb->class_val_to_struct[tclass - 1];
-
- ocontext = sepol_sidtab_search(sidtab, oldsid);
- if (!ocontext) {
- ERR(NULL, "unrecognized SID %d", oldsid);
- return -EINVAL;
- }
-
- ncontext = sepol_sidtab_search(sidtab, newsid);
- if (!ncontext) {
- ERR(NULL, "unrecognized SID %d", newsid);
- return -EINVAL;
- }
-
- tcontext = sepol_sidtab_search(sidtab, tasksid);
- if (!tcontext) {
- ERR(NULL, "unrecognized SID %d", tasksid);
- return -EINVAL;
- }
-
- constraint = tclass_datum->validatetrans;
- while (constraint) {
- if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext,
- 0, constraint, NULL, 0)) {
- return -EPERM;
- }
- constraint = constraint->next;
- }
-
- return 0;
-}
-
/*
* sepol_validate_transition_reason_buffer - the reason buffer is realloc'd
* in the constraint_expr_eval_reason() function.
@@ -1230,7 +1182,7 @@ int sepol_string_to_security_class(const char *class_name,
class_datum_t *tclass_datum;
tclass_datum = hashtab_search(policydb->p_classes.table,
- (hashtab_key_t) class_name);
+ class_name);
if (!tclass_datum) {
ERR(NULL, "unrecognized class %s", class_name);
return STATUS_ERR;
@@ -1259,9 +1211,9 @@ int sepol_string_to_av_perm(sepol_security_class_t tclass,
/* Check for unique perms then the common ones (if any) */
perm_datum = (perm_datum_t *)
hashtab_search(tclass_datum->permissions.table,
- (hashtab_key_t)perm_name);
+ perm_name);
if (perm_datum != NULL) {
- *av = 0x1 << (perm_datum->s.value - 1);
+ *av = UINT32_C(1) << (perm_datum->s.value - 1);
return STATUS_SUCCESS;
}
@@ -1270,10 +1222,10 @@ int sepol_string_to_av_perm(sepol_security_class_t tclass,
perm_datum = (perm_datum_t *)
hashtab_search(tclass_datum->comdatum->permissions.table,
- (hashtab_key_t)perm_name);
+ perm_name);
if (perm_datum != NULL) {
- *av = 0x1 << (perm_datum->s.value - 1);
+ *av = UINT32_C(1) << (perm_datum->s.value - 1);
return STATUS_SUCCESS;
}
out:
diff --git a/libsepol/src/sidtab.c b/libsepol/src/sidtab.c
index e6bf57161e5207959a627441c945e36b684dd117..255e072524124304d1dbb303d7128d1c3a0f4f6c 100644
--- a/libsepol/src/sidtab.c
+++ b/libsepol/src/sidtab.c
@@ -84,37 +84,6 @@ int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid,
return 0;
}
-int sepol_sidtab_remove(sidtab_t * s, sepol_security_id_t sid)
-{
- int hvalue;
- sidtab_node_t *cur, *last;
-
- if (!s || !s->htable)
- return -ENOENT;
-
- hvalue = SIDTAB_HASH(sid);
- last = NULL;
- cur = s->htable[hvalue];
- while (cur != NULL && sid > cur->sid) {
- last = cur;
- cur = cur->next;
- }
-
- if (cur == NULL || sid != cur->sid)
- return -ENOENT;
-
- if (last == NULL)
- s->htable[hvalue] = cur->next;
- else
- last->next = cur->next;
-
- context_destroy(&cur->context);
-
- free(cur);
- s->nel--;
- return 0;
-}
-
context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid)
{
int hvalue;
diff --git a/libsepol/src/symtab.c b/libsepol/src/symtab.c
index 9a417ca24b53fdf694256abe84fdef3ed2704a5b..a60618510bd3372560a1b33ee24678b9451456d2 100644
--- a/libsepol/src/symtab.c
+++ b/libsepol/src/symtab.c
@@ -8,9 +8,13 @@
*/
#include
+
+#include "private.h"
+
#include
#include
+ignore_unsigned_overflow_
static unsigned int symhash(hashtab_t h, const_hashtab_key_t key)
{
const char *p, *keyp;
diff --git a/libsepol/src/util.c b/libsepol/src/util.c
index d51750af3fa1e4d74b7838694f584cd02125e612..902c63c5b18267fabd3b28b2b40b8043f2ad023c 100644
--- a/libsepol/src/util.c
+++ b/libsepol/src/util.c
@@ -92,7 +92,7 @@ char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass,
cladatum = policydbp->class_val_to_struct[tclass - 1];
p = avbuf;
for (i = 0; i < cladatum->permissions.nprim; i++) {
- if (av & (1 << i)) {
+ if (av & (UINT32_C(1) << i)) {
v.val = i + 1;
rc = hashtab_map(cladatum->permissions.table,
perm_name, &v);
@@ -129,9 +129,9 @@ char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms)
unsigned int bit;
unsigned int in_range = 0;
static char xpermsbuf[2048];
- xpermsbuf[0] = '\0';
char *p;
int len, xpermslen = 0;
+ xpermsbuf[0] = '\0';
p = xpermsbuf;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 84bcaf3f57ca83d5c2d15f0d13bd90a665eab076..3bd034d65cb1b8fb9339691d1e69f1ce46295824 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -1345,7 +1345,7 @@ 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_xen(struct policydb_compat_info *info, policydb_t *p,
+static int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p,
struct policy_file *fp)
{
unsigned int i, j;
@@ -1453,7 +1453,7 @@ static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
return POLICYDB_SUCCESS;
}
-static int ocontext_write_selinux(struct policydb_compat_info *info,
+static int ocontext_write_selinux(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
unsigned int i, j;
@@ -1583,7 +1583,7 @@ static int ocontext_write_selinux(struct policydb_compat_info *info,
return POLICYDB_SUCCESS;
}
-static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
+static int ocontext_write(const struct policydb_compat_info *info, policydb_t * p,
struct policy_file *fp)
{
int rc = POLICYDB_ERROR;
@@ -2179,7 +2179,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
unsigned int i, num_syms;
uint32_t buf[32], config;
size_t items, items2, len;
- struct policydb_compat_info *info;
+ const struct policydb_compat_info *info;
struct policy_data pd;
const char *policydb_str;
diff --git a/libsepol/tests/.gitignore b/libsepol/tests/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c3f60fd2b945067673e46613c21914b073be81d3
--- /dev/null
+++ b/libsepol/tests/.gitignore
@@ -0,0 +1 @@
+libsepol-tests
diff --git a/libsepol/tests/libsepol-tests.c b/libsepol/tests/libsepol-tests.c
index 544c792d2ab5cea40d48866d8c44c42e6f215ea3..dc8fd5ce5f6cec2f1bece086edb134ba04ac6bf2 100644
--- a/libsepol/tests/libsepol-tests.c
+++ b/libsepol/tests/libsepol-tests.c
@@ -36,13 +36,17 @@
int mls;
#define DECLARE_SUITE(name) \
- suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \
- if (NULL == suite) { \
- CU_cleanup_registry(); \
- return CU_get_error(); } \
- if (name##_add_tests(suite)) { \
- CU_cleanup_registry(); \
- return CU_get_error(); }
+ do { \
+ suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \
+ if (NULL == suite) { \
+ CU_cleanup_registry(); \
+ return CU_get_error(); \
+ } \
+ if (name##_add_tests(suite)) { \
+ CU_cleanup_registry(); \
+ return CU_get_error(); \
+ } \
+ } while (0)
static void usage(char *progname)
{
diff --git a/libsepol/tests/policies/.gitignore b/libsepol/tests/policies/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5a547a8aa9dffd671f9967e075819aed96dc5587
--- /dev/null
+++ b/libsepol/tests/policies/.gitignore
@@ -0,0 +1,3 @@
+test-downgrade/
+test-*/*.mls
+test-*/*.std
diff --git a/secilc/.gitignore b/secilc/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2a3daf1665cd22c0d047f56b7773b543a6e7b06
--- /dev/null
+++ b/secilc/.gitignore
@@ -0,0 +1,13 @@
+secilc
+secilc.8
+secil2conf
+secil2conf.8
+secil2tree
+secil2tree.8
+policy.*
+file_contexts
+docs/html
+docs/pdf
+docs/tmp
+opt-actual.bin
+opt-actual.cil
diff --git a/secilc/Makefile b/secilc/Makefile
index d4a1c35a2878b400171bdcecc6f357b2144d0867..94be048194471cc40c5ec13c2fa605dcae861ae8 100644
--- a/secilc/Makefile
+++ b/secilc/Makefile
@@ -10,8 +10,13 @@ SECIL2CONF = secil2conf
SECIL2CONF_SRCS := secil2conf.c
SECIL2CONF_OBJS := $(patsubst %.c,%.o,$(SECIL2CONF_SRCS))
+SECIL2TREE = secil2tree
+SECIL2TREE_SRCS := secil2tree.c
+SECIL2TREE_OBJS := $(patsubst %.c,%.o,$(SECIL2TREE_SRCS))
+
SECILC_MANPAGE = secilc.8
SECIL2CONF_MANPAGE = secil2conf.8
+SECIL2TREE_MANPAGE = secil2tree.8
XMLTO = xmlto
DIFF = diff
@@ -23,7 +28,7 @@ CFLAGS ?= -Wall -Wshadow -Wextra -Wundef -Wmissing-format-attribute -Wcast-align
override CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
override LDLIBS += -lsepol
-all: $(SECILC) $(SECIL2CONF) man
+all: $(SECILC) $(SECIL2CONF) $(SECIL2TREE) man
$(SECILC): $(SECILC_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
@@ -37,7 +42,10 @@ test: $(SECILC)
$(SECIL2CONF): $(SECIL2CONF_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE)
+$(SECIL2TREE): $(SECIL2TREE_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE) $(SECIL2TREE_MANPAGE)
$(SECILC_MANPAGE): $(SECILC_MANPAGE).xml
$(XMLTO) man $(SECILC_MANPAGE).xml
@@ -45,13 +53,18 @@ $(SECILC_MANPAGE): $(SECILC_MANPAGE).xml
$(SECIL2CONF_MANPAGE): $(SECIL2CONF_MANPAGE).xml
$(XMLTO) man $(SECIL2CONF_MANPAGE).xml
+$(SECIL2TREE_MANPAGE): $(SECIL2TREE_MANPAGE).xml
+ $(XMLTO) man $(SECIL2TREE_MANPAGE).xml
+
install: all man
-mkdir -p $(DESTDIR)$(BINDIR)
-mkdir -p $(DESTDIR)$(MANDIR)/man8
install -m 755 $(SECILC) $(DESTDIR)$(BINDIR)
install -m 755 $(SECIL2CONF) $(DESTDIR)$(BINDIR)
+ install -m 755 $(SECIL2TREE) $(DESTDIR)$(BINDIR)
install -m 644 $(SECILC_MANPAGE) $(DESTDIR)$(MANDIR)/man8
install -m 644 $(SECIL2CONF_MANPAGE) $(DESTDIR)$(MANDIR)/man8
+ install -m 644 $(SECIL2TREE_MANPAGE) $(DESTDIR)$(MANDIR)/man8
doc:
$(MAKE) -C docs
@@ -61,10 +74,13 @@ clean:
rm -f $(SECILC_OBJS)
rm -f $(SECIL2CONF)
rm -f $(SECIL2CONF_OBJS)
+ rm -f $(SECIL2TREE)
+ rm -f $(SECIL2TREE_OBJS)
rm -f policy.*
rm -f file_contexts
rm -f $(SECILC_MANPAGE)
rm -f $(SECIL2CONF_MANPAGE)
+ rm -f $(SECIL2TREE_MANPAGE)
rm -f opt-actual.cil
rm -f opt-actual.bin
$(MAKE) -C docs clean
diff --git a/secilc/VERSION b/secilc/VERSION
index a3ec5a4bd3d7209b4a687a77cad49b945339994b..eb39e5382f4f035e4d71c7f67712cdbfa6c0c335 100644
--- a/secilc/VERSION
+++ b/secilc/VERSION
@@ -1 +1 @@
-3.2
+3.3
diff --git a/secilc/docs/cil_access_vector_rules.md b/secilc/docs/cil_access_vector_rules.md
index fa68609ea0b3864472c5030330b7de7d5efcaf99..f0ba4a903a317d3ee2966d61e54db4d5c4e30983 100644
--- a/secilc/docs/cil_access_vector_rules.md
+++ b/secilc/docs/cil_access_vector_rules.md
@@ -360,7 +360,7 @@ dontauditx
Do not audit the access rights defined when access denied. This stops excessive log entries for known events.
-Note that for this to work there must *also* be atleast one [`allowx`](cil_access_vector_rules.md#allowx) rule associated with the target type.
+Note that for this to work there must *also* be at least one [`allowx`](cil_access_vector_rules.md#allowx) rule associated with the target type.
Note that these rules can be omitted by the CIL compiler command line parameter `-D` or `--disable-dontaudit` flags.
diff --git a/secilc/docs/cil_call_macro_statements.md b/secilc/docs/cil_call_macro_statements.md
index 352a9fb06efef38bd4ff377ef1ea25b9ac3f109e..dcc6139ff7b3b691e4a8ac1ab85bf70c89efc314 100644
--- a/secilc/docs/cil_call_macro_statements.md
+++ b/secilc/docs/cil_call_macro_statements.md
@@ -8,6 +8,18 @@ Instantiate a [macro](#macro) within the current namespace. There may be zero or
Each parameter passed contains an argument to be resolved by the [macro](#macro), these can be named or anonymous but must conform to the parameter types defined in the [`macro`](cil_call_macro_statements.md#macro) statement.
+Macro rules are resolved by searching in the following order:
+
+- The macro namespace (If found this means that the name was declared in the macro and is now declared in the namespace of one of the parents of the call.)
+
+- The call arguments
+
+- The parent namespaces of the macro being called (if any) with the exception of the global namespace.
+
+- The parent namespaces of the call (if any) with the exception of the global namespace.
+
+- The global namespace
+
**Statement definition:**
```secil
@@ -46,20 +58,10 @@ macro
Declare a macro in the current namespace with its associated parameters. The macro identifier is used by the [`call`](cil_call_macro_statements.md#call) statement to instantiate the macro and resolve any parameters. The call statement may be within the body of a macro.
-When resolving macros the following places are checked in this order:
-
-- Items defined inside the macro
-
-- Items passed into the macro as arguments
-
-- Items defined in the same namespace of the macro
-
-- Items defined in the callers namespace
-
-- Items defined in the global namespace
-
[`tunable`](cil_conditional_statements.md#tunable), [`in`](cil_container_statements.md#in), [`block`](cil_container_statements.md#block), [`blockinherit`](cil_container_statements.md#blockinherit), [`blockabstract`](cil_container_statements.md#blockabstract), and other [`macro`](cil_call_macro_statements.md#macro) statements are not allowed in [`macro`](cil_call_macro_statements.md#macro) blocks.
+Duplicate [`macro`](cil_call_macro_statements.md#macro) declarations in the same namespace will normally cause an error, but inheriting a macro into a namespace (with [`blockinherit`](cil_container_statements.md#blockinherit)) that already has a macro with the same name will only result in a warning message and not cause an error. This behavior allows inherited macros to be overridden with local ones.
+
**Statement definition:**
```secil
diff --git a/secilc/docs/cil_conditional_statements.md b/secilc/docs/cil_conditional_statements.md
index d0c8e2ce483290c281d3a154625288b67349118d..9afd4153a24a035f84cb7fff89b2c71d98f062e7 100644
--- a/secilc/docs/cil_conditional_statements.md
+++ b/secilc/docs/cil_conditional_statements.md
@@ -80,12 +80,12 @@ Contains the run time conditional statements that are instantiated in the binary
expr
Zero or more expr's, the valid operators and syntax are:
-
(and (boolean_id boolean_id))
-
(or (boolean_id boolean_id))
-
(xor (boolean_id boolean_id))
-
(eq (boolean_id boolean_id))
-
(neq (boolean_id boolean_id))
-
(not (boolean_id))
+
(and boolean_id boolean_id)
+
(or boolean_id boolean_id)
+
(xor boolean_id boolean_id)
+
(eq boolean_id boolean_id)
+
(neq boolean_id boolean_id)
+
(not boolean_id)
true
@@ -202,12 +202,12 @@ If tunables are being treated as booleans (by using the CIL compiler command lin
expr
Zero or more expr's, the valid operators and syntax are:
-
(and (tunable_id tunable_id))
-
(or (tunable_id tunable_id))
-
(xor (tunable_id tunable_id))
-
(eq (tunable_id tunable_id))
-
(neq (tunable_id tunable_id))
-
(not (tunable_id))
+
(and tunable_id tunable_id)
+
(or tunable_id tunable_id)
+
(xor tunable_id tunable_id)
+
(eq tunable_id tunable_id)
+
(neq tunable_id tunable_id)
+
(not tunable_id)
true
diff --git a/secilc/docs/cil_constraint_statements.md b/secilc/docs/cil_constraint_statements.md
index 2dd6e6f022db3d1b20779aadbc5ac361f2ed4cb7..358927d6398162d1d85ee1a76788f9276fa79d8e 100644
--- a/secilc/docs/cil_constraint_statements.md
+++ b/secilc/docs/cil_constraint_statements.md
@@ -34,12 +34,12 @@ Enable constraints to be placed on the specified permissions of the object class
(op u1 u2)
(role_op r1 r2)
(op t1 t2)
-
(op u1 user_id)
-
(op u2 user_id)
-
(op r1 role_id)
-
(op r2 role_id)
-
(op t1 type_id)
-
(op t2 type_id)
+
(op u1 user_id | (user_id ...))
+
(op u2 user_id | (user_id ...))
+
(op r1 role_id | (role_id ...))
+
(op r2 role_id | (role_id ...))
+
(op t1 type_id | (type_id ...))
+
(op t2 type_id | (type_id ...))
where:
u1, r1, t1 = Source context: user, role or type
u2, r2, t2 = Target context: user, role or type
diff --git a/secilc/docs/cil_container_statements.md b/secilc/docs/cil_container_statements.md
index 7a7f67cc27c4bbdabf821919e096386bf480e8db..f70160cb60c27985716178f358dfcf6fb1c7dd57 100644
--- a/secilc/docs/cil_container_statements.md
+++ b/secilc/docs/cil_container_statements.md
@@ -10,6 +10,8 @@ Not allowed in [`macro`](cil_call_macro_statements.md#macro) and [`optional`](ci
[`sensitivity`](cil_mls_labeling_statements.md#sensitivity) and [`category`](cil_mls_labeling_statements.md#category) statements are not allowed in [`block`](cil_container_statements.md#block) blocks.
+Duplicate declarations of a [`block`](cil_container_statements.md#block) in the same namespace will normally cause an error, but inheriting a block into a namespace (with [`blockinherit`](cil_container_statements.md#blockinherit)) that already has a block with the same name will only result in a warning message and not cause an error. The policy from both blocks will end up in the binary policy. This behavior was used in the past to allow a block to be declared so that an [`in-statement`](cil_container_statements.md#in) could be used on it, but now an [`in-statement`](cil_container_statements.md#in) can be specified to occur after inheritance, so this behavior is not necessary (but is still allowed).
+
**Statement definition:**
```secil
@@ -103,6 +105,14 @@ blockinherit
Used to add common policy rules to the current namespace via a template that has been defined with the [`blockabstract`](cil_container_statements.md#blockabstract) statement. All [`blockinherit`](cil_container_statements.md#blockinherit) statements are resolved first and then the contents of the block are copied. This is so that inherited blocks will not be inherited. For a concrete example, please see the examples section.
+Inherited rules are resolved by searching namespaces in the following order:
+
+- The parent namespaces (if any) where the [`blockinherit`](cil_container_statements.md#blockinherit) rule is located with the exception of the global namespace.
+
+- The parent namespaces of the block being inherited (but not that block's namespace) with the exception of the global namespace.
+
+- The global namespace.
+
Not allowed in [`macro`](cil_call_macro_statements.md#macro) blocks.
**Statement definition:**
@@ -270,7 +280,7 @@ This example will instantiate the optional block `ext_gateway.move_file` into po
in
--
-Allows the insertion of CIL statements into a named container ([`block`](cil_container_statements.md#block), [`optional`](cil_container_statements.md#optional) or [`macro`](cil_call_macro_statements.md#macro)).
+Allows the insertion of CIL statements into a named container ([`block`](cil_container_statements.md#block), [`optional`](cil_container_statements.md#optional) or [`macro`](cil_call_macro_statements.md#macro)). This insertion can be specified to occur either before or after block inheritance has been resolved.
Not allowed in [`macro`](cil_call_macro_statements.md#macro), [`booleanif`](cil_conditional_statements.md#booleanif), and other [`in`](cil_container_statements.md#in) blocks.
@@ -279,7 +289,7 @@ Not allowed in [`macro`](cil_call_macro_statements.md#macro), [`booleanif`](cil_
**Statement definition:**
```secil
- (in container_id
+ (in [before|after] container_id
cil_statement
...
)
@@ -298,10 +308,14 @@ Not allowed in [`macro`](cil_call_macro_statements.md#macro), [`booleanif`](cil_
The in keyword.
+
before|after
+
An optional value that specifies whether to process the [`in`](cil_container_statements.md#in) before or after block inheritance. If no value is specified, then the [`in`](cil_container_statements.md#in) will be processed before block inheritance.
+
+
container_id
A valid block, optional or macro namespace identifier.
-
+
cil_statement
Zero or more valid CIL statements.
diff --git a/secilc/docs/secil.xml b/secilc/docs/secil.xml
index daa80ded9b8aedbde976b96a9a51bb32c208e957..b015490d3201b9ccc38eed4ef12174f0f78725ef 100644
--- a/secilc/docs/secil.xml
+++ b/secilc/docs/secil.xml
@@ -208,7 +208,7 @@
-
+
diff --git a/secilc/secil2conf.8.xml b/secilc/secil2conf.8.xml
index 59d87a5496cd6a43aff1b4bf250b51ee2620e951..33646f97739b179b9bf2cc9cf665efac5b36a232 100644
--- a/secilc/secil2conf.8.xml
+++ b/secilc/secil2conf.8.xml
@@ -50,6 +50,11 @@
Treat tunables as booleans.
+
+
+ Allow names containing dots (qualified names). Blocks, blockinherits, blockabstracts, and in-statements will not be allowed.
+
+
Increment verbosity level.
diff --git a/secilc/secil2conf.c b/secilc/secil2conf.c
index 4e97dd66a436624cffd9a62bcde58127bea599eb..c49522e5684c5be19c6b065891119d22eb2c6901 100644
--- a/secilc/secil2conf.c
+++ b/secilc/secil2conf.c
@@ -52,6 +52,9 @@ static __attribute__((__noreturn__)) void usage(const char *prog)
printf(" This will override the (mls boolean) statement\n");
printf(" if present in the policy\n");
printf(" -P, --preserve-tunables treat tunables as booleans\n");
+ printf(" -Q, --qualified-names Allow names containing dots (qualified names).\n");
+ printf(" Blocks, blockinherits, blockabstracts, and\n");
+ printf(" in-statements will not be allowed.\n");
printf(" -v, --verbose increment verbosity level\n");
printf(" -h, --help display usage information\n");
exit(1);
@@ -68,6 +71,7 @@ int main(int argc, char *argv[])
struct cil_db *db = NULL;
int mls = -1;
int preserve_tunables = 0;
+ int qualified_names = 0;
int opt_char;
int opt_index = 0;
enum cil_log_level log_level = CIL_ERR;
@@ -76,13 +80,14 @@ int main(int argc, char *argv[])
{"verbose", no_argument, 0, 'v'},
{"mls", required_argument, 0, 'M'},
{"preserve-tunables", no_argument, 0, 'P'},
+ {"qualified-names", no_argument, 0, 'Q'},
{"output", required_argument, 0, 'o'},
{0, 0, 0, 0}
};
int i;
while (1) {
- opt_char = getopt_long(argc, argv, "o:hvM:P", long_opts, &opt_index);
+ opt_char = getopt_long(argc, argv, "o:hvM:PQ", long_opts, &opt_index);
if (opt_char == -1) {
break;
}
@@ -102,7 +107,11 @@ int main(int argc, char *argv[])
case 'P':
preserve_tunables = 1;
break;
+ case 'Q':
+ qualified_names = 1;
+ break;
case 'o':
+ free(output);
output = strdup(optarg);
break;
case 'h':
@@ -123,6 +132,7 @@ int main(int argc, char *argv[])
cil_db_init(&db);
cil_set_preserve_tunables(db, preserve_tunables);
+ cil_set_qualified_names(db, qualified_names);
cil_set_mls(db, mls);
cil_set_attrs_expand_generated(db, 0);
cil_set_attrs_expand_size(db, 0);
diff --git a/secilc/secil2tree.8.xml b/secilc/secil2tree.8.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e95a8947775ca28c533fbaa672017579bbfc5004
--- /dev/null
+++ b/secilc/secil2tree.8.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ JamesCarter
+
+
+
+
+ SECIL2TREE
+ 8
+ 05 April 2021
+ secil2tree
+ SELinux CIL AST Writer
+
+
+ secil2tree
+ invoke the SELinux Common Intermediate Language (CIL) AST Writer
+
+
+
+
+ secil2tree
+ OPTION
+ file
+
+
+
+ DESCRIPTION
+ secil2tree invokes the CIL AST Writer with the specified arguments.
+
+
+ OPTIONS
+
+
+
+ Write AST to file (default: stdout)
+
+
+
+
+ Treat tunables as booleans.
+
+
+
+
+ Allow names containing dots (qualified names). Blocks, blockinherits, blockabstracts, and in-statements will not be allowed.
+
+
+
+
+ Write AST of phase phase. Must be parse, build, or resolve. (default: resolve)
+
+
+
+
+ Increment verbosity level.
+
+
+
+
+ Display usage information.
+
+
+
+
+ SEE ALSO
+
+
+
+ secilc
+ 8
+
+
+ secil2conf
+ 8
+
+
+
+ HTML documentation describing the CIL language statements is available starting with docs/html/index.html.
+ PDF documentation describing the CIL language statements is available at: docs/pdf/CIL_Reference_Guide.pdf.
+
+
diff --git a/secilc/secil2tree.c b/secilc/secil2tree.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5cdf6bd299cdefd3fa39ee6d7aea094d49470bb
--- /dev/null
+++ b/secilc/secil2tree.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2011 Tresys Technology, LLC. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those
+ * of the authors and should not be interpreted as representing official policies,
+ * either expressed or implied, of Tresys Technology, LLC.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef ANDROID
+#include
+#else
+#include
+#endif
+#include
+
+enum write_ast_phase {
+ WRITE_AST_PHASE_PARSE = 0,
+ WRITE_AST_PHASE_BUILD,
+ WRITE_AST_PHASE_RESOLVE,
+};
+
+static __attribute__((__noreturn__)) void usage(const char *prog)
+{
+ printf("Usage: %s [OPTION]... FILE...\n", prog);
+ printf("\n");
+ printf("Options:\n");
+ printf(" -o, --output= write AST to . (default: stdout)\n");
+ printf(" -P, --preserve-tunables treat tunables as booleans\n");
+ printf(" -Q, --qualified-names Allow names containing dots (qualified names).\n");
+ printf(" Blocks, blockinherits, blockabstracts, and\n");
+ printf(" in-statements will not be allowed.\n");
+ printf(" -A, --ast-phase= write AST of phase . Phase must be parse, \n");
+ printf(" build, or resolve. (default: resolve)\n");
+ printf(" -v, --verbose increment verbosity level\n");
+ printf(" -h, --help display usage information\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ int rc = SEPOL_ERR;
+ FILE *file = NULL;
+ char *buffer = NULL;
+ struct stat filedata;
+ uint32_t file_size;
+ char *output = NULL;
+ struct cil_db *db = NULL;
+ int preserve_tunables = 0;
+ int qualified_names = 0;
+ enum write_ast_phase write_ast = WRITE_AST_PHASE_RESOLVE;
+ int opt_char;
+ int opt_index = 0;
+ enum cil_log_level log_level = CIL_ERR;
+ static struct option long_opts[] = {
+ {"help", no_argument, 0, 'h'},
+ {"verbose", no_argument, 0, 'v'},
+ {"preserve-tunables", no_argument, 0, 'P'},
+ {"qualified-names", no_argument, 0, 'Q'},
+ {"output", required_argument, 0, 'o'},
+ {"ast-phase", required_argument, 0, 'A'},
+ {0, 0, 0, 0}
+ };
+ int i;
+
+ while (1) {
+ opt_char = getopt_long(argc, argv, "o:hvPQA:", long_opts, &opt_index);
+ if (opt_char == -1) {
+ break;
+ }
+ switch (opt_char) {
+ case 'v':
+ log_level++;
+ break;
+ case 'P':
+ preserve_tunables = 1;
+ break;
+ case 'Q':
+ qualified_names = 1;
+ break;
+ case 'o':
+ output = strdup(optarg);
+ break;
+ case 'A':
+ if (!strcasecmp(optarg, "parse")) {
+ write_ast = WRITE_AST_PHASE_PARSE;
+ } else if (!strcasecmp(optarg, "build")) {
+ write_ast = WRITE_AST_PHASE_BUILD;
+ } else if (!strcasecmp(optarg, "resolve")) {
+ write_ast = WRITE_AST_PHASE_RESOLVE;
+ } else {
+ fprintf(stderr, "Invalid AST phase: %s\n", optarg);
+ usage(argv[0]);
+ }
+ break;
+ case 'h':
+ usage(argv[0]);
+ case '?':
+ break;
+ default:
+ fprintf(stderr, "Unsupported option: %s\n", optarg);
+ usage(argv[0]);
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "No cil files specified\n");
+ usage(argv[0]);
+ }
+
+ cil_set_log_level(log_level);
+
+ cil_db_init(&db);
+ cil_set_preserve_tunables(db, preserve_tunables);
+ cil_set_qualified_names(db, qualified_names);
+ cil_set_attrs_expand_generated(db, 0);
+ cil_set_attrs_expand_size(db, 0);
+
+ for (i = optind; i < argc; i++) {
+ file = fopen(argv[i], "r");
+ if (!file) {
+ fprintf(stderr, "Could not open file: %s\n", argv[i]);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ rc = stat(argv[i], &filedata);
+ if (rc == -1) {
+ fprintf(stderr, "Could not stat file: %s\n", argv[i]);
+ goto exit;
+ }
+ file_size = filedata.st_size;
+
+ buffer = malloc(file_size);
+ rc = fread(buffer, file_size, 1, file);
+ if (rc != 1) {
+ fprintf(stderr, "Failure reading file: %s\n", argv[i]);
+ goto exit;
+ }
+ fclose(file);
+ file = NULL;
+
+ rc = cil_add_file(db, argv[i], buffer, file_size);
+ if (rc != SEPOL_OK) {
+ fprintf(stderr, "Failure adding %s\n", argv[i]);
+ goto exit;
+ }
+
+ free(buffer);
+ buffer = NULL;
+ }
+
+ if (output == NULL) {
+ file = stdout;
+ } else {
+ file = fopen(output, "w");
+ if (file == NULL) {
+ fprintf(stderr, "Failure opening file %s for writing\n", output);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
+
+ switch (write_ast) {
+ case WRITE_AST_PHASE_PARSE:
+ rc = cil_write_parse_ast(file, db);
+ break;
+ case WRITE_AST_PHASE_BUILD:
+ rc = cil_write_build_ast(file, db);
+ break;
+ case WRITE_AST_PHASE_RESOLVE:
+ rc = cil_write_resolve_ast(file, db);
+ break;
+ }
+
+ if (rc != SEPOL_OK) {
+ fprintf(stderr, "Failed to write AST\n");
+ goto exit;
+ }
+
+exit:
+ if (file != NULL && file != stdin) {
+ fclose(file);
+ }
+ free(buffer);
+ free(output);
+ cil_db_destroy(&db);
+ return rc;
+}
diff --git a/secilc/secilc.8.xml b/secilc/secilc.8.xml
index 2b734f09cf1327c78f546928d65fce0fd41f7f5d..e9a121e26aeec5a1c85009232fab4b05be6df7da 100644
--- a/secilc/secilc.8.xml
+++ b/secilc/secilc.8.xml
@@ -75,6 +75,11 @@
Treat tunables as booleans.
+
+
+ Allow names containing dots (qualified names). Blocks, blockinherits, blockabstracts, and in-statements will not be allowed.
+
+
Allow some statements to be re-declared.
diff --git a/secilc/secilc.c b/secilc/secilc.c
index e41f5cfc8a0a87621e9531a4460d69413a6e239a..1e1b83e432c4ba9468bd5048a19f67ab2ff11345 100644
--- a/secilc/secilc.c
+++ b/secilc/secilc.c
@@ -63,6 +63,9 @@ static __attribute__((__noreturn__)) void usage(const char *prog)
printf(" statement if present in the policy\n");
printf(" -D, --disable-dontaudit do not add dontaudit rules to the binary policy\n");
printf(" -P, --preserve-tunables treat tunables as booleans\n");
+ printf(" -Q, --qualified-names Allow names containing dots (qualified names).\n");
+ printf(" Blocks, blockinherits, blockabstracts, and\n");
+ printf(" in-statements will not be allowed.\n");
printf(" -m, --multiple-decls allow some statements to be re-declared\n");
printf(" -N, --disable-neverallow do not check neverallow rules\n");
printf(" -G, --expand-generated Expand and remove auto-generated attributes\n");
@@ -94,6 +97,7 @@ int main(int argc, char *argv[])
int multiple_decls = 0;
int disable_neverallow = 0;
int preserve_tunables = 0;
+ int qualified_names = 0;
int handle_unknown = -1;
int policyvers = POLICYDB_VERSION_MAX;
int attrs_expand_generated = 0;
@@ -115,6 +119,7 @@ int main(int argc, char *argv[])
{"multiple-decls", no_argument, 0, 'm'},
{"disable-neverallow", no_argument, 0, 'N'},
{"preserve-tunables", no_argument, 0, 'P'},
+ {"qualified-names", no_argument, 0, 'Q'},
{"output", required_argument, 0, 'o'},
{"filecontexts", required_argument, 0, 'f'},
{"expand-generated", no_argument, 0, 'G'},
@@ -125,7 +130,7 @@ int main(int argc, char *argv[])
int i;
while (1) {
- opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDmNOc:GX:n", long_opts, &opt_index);
+ opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PQDmNOc:GX:n", long_opts, &opt_index);
if (opt_char == -1) {
break;
}
@@ -190,10 +195,15 @@ int main(int argc, char *argv[])
case 'P':
preserve_tunables = 1;
break;
+ case 'Q':
+ qualified_names = 1;
+ break;
case 'o':
+ free(output);
output = strdup(optarg);
break;
case 'f':
+ free(filecontexts);
filecontexts = strdup(optarg);
break;
case 'G':
@@ -238,6 +248,7 @@ int main(int argc, char *argv[])
cil_set_multiple_decls(db, multiple_decls);
cil_set_disable_neverallow(db, disable_neverallow);
cil_set_preserve_tunables(db, preserve_tunables);
+ cil_set_qualified_names(db, qualified_names);
if (handle_unknown != -1) {
rc = cil_set_handle_unknown(db, handle_unknown);
if (rc != SEPOL_OK) {
@@ -268,6 +279,12 @@ int main(int argc, char *argv[])
}
file_size = filedata.st_size;
+ if (!file_size) {
+ fclose(file);
+ file = NULL;
+ continue;
+ }
+
buffer = malloc(file_size);
rc = fread(buffer, file_size, 1, file);
if (rc != 1) {
diff --git a/secilc/test/anonymous_arg_test.cil b/secilc/test/anonymous_arg_test.cil
new file mode 100644
index 0000000000000000000000000000000000000000..46f8ce7342f678cc32491996a216a435e3205c0d
--- /dev/null
+++ b/secilc/test/anonymous_arg_test.cil
@@ -0,0 +1,106 @@
+;; Test anonymous args
+
+(mls true)
+(class CLASS (PERM))
+(classorder (CLASS))
+(sid SID)
+(sidorder (SID))
+(user USER)
+(role ROLE)
+(type TYPE)
+(category CAT)
+(categoryorder (CAT))
+(sensitivity SENS)
+(sensitivityorder (SENS))
+(sensitivitycategory SENS (CAT))
+(allow TYPE self (CLASS (PERM)))
+(roletype ROLE TYPE)
+(userrole USER ROLE)
+(userlevel USER (SENS))
+(userrange USER ((SENS)(SENS (CAT))))
+(sidcontext SID (USER ROLE TYPE ((SENS)(SENS))))
+
+(category c0)
+(category c1)
+(category c2)
+(category c3)
+(categoryorder (CAT c0 c1 c2 c3))
+(categoryset cs01 (c0 c1))
+(categoryset cs03 (range c0 c3))
+
+(sensitivity s0)
+(sensitivity s1)
+(sensitivity s2)
+(sensitivity s3)
+(sensitivityorder (SENS s0 s1 s2 s3))
+
+(sensitivitycategory s0 (cs01 c2 c3))
+(sensitivitycategory s1 (c0 c1 c2 c3))
+(sensitivitycategory s2 (c0 c1 c2 c3))
+(sensitivitycategory s3 (range c0 c3))
+
+(level lvl (s0 (c0)))
+(level lvl0 (s0))
+(level lvl3 (s3 (range c0 c3)))
+
+(levelrange rng ((s0) (s3 (c0 c1 c2 c3))))
+
+(user u1)
+(user u2)
+(user u3)
+(user u4)
+
+(userrole u1 ROLE)
+(userrole u2 ROLE)
+(userrole u3 ROLE)
+(userrole u4 ROLE)
+
+; Test categoryset
+(macro m1 ((user u)(sensitivity s)(categoryset cs))
+ (userlevel u (s (cs)))
+)
+(call m1 (u1 s1 (c0 c1)))
+(call m1 (u2 s2 cs01))
+
+; Test level
+(macro m2 ((user u)(level l))
+ (userlevel u l)
+)
+(call m2 (u3 (s3 (c2))))
+(call m2 (u4 lvl))
+
+; Test levelrange
+(macro m3 ((user u)(levelrange lr))
+ (userrange u lr)
+)
+(call m3 (u1 ((s0) (s3 (range c0 c3)))))
+(call m3 (u2 (lvl0 (s3 (cs03)))))
+(call m3 (u3 (lvl0 lvl3)))
+(call m3 (u4 rng))
+
+; Test ipaddr
+(macro m4 ((user u)(ipaddr nm)(ipaddr ip))
+ (nodecon ip nm (u ROLE TYPE ((s0) (s0))))
+)
+(ipaddr nm1 255.255.255.0)
+(ipaddr ip4 1.2.3.4)
+(call m4 (u1 nm1 192.25.35.200))
+(call m4 (u2 255.255.255.0 ip4))
+
+; Test classpermission
+(type t1)
+(type t2)
+(type t3)
+
+(classpermission cp1)
+(classpermissionset cp1 (CLASS (PERM)))
+
+(classmap cm1 (cm1p))
+(classmapping cm1 cm1p (CLASS (PERM)))
+
+(macro m5 ((type t)(classpermission cp))
+ (allow t self cp)
+)
+(call m5 (t1 (CLASS (PERM))))
+(call m5 (t2 cp1))
+(call m5 (t3 (cm1 (cm1p))))
diff --git a/secilc/test/block_test.cil b/secilc/test/block_test.cil
index 2dfcb89914157bc383694818babcab04a67393e9..2dd30c236c46aa87c43df8869e43a28353cfc34a 100644
--- a/secilc/test/block_test.cil
+++ b/secilc/test/block_test.cil
@@ -84,7 +84,7 @@
)
-;; Inherting the abstract block causes the allow rule to be in the policy
+;; Inheriting the abstract block causes the allow rule to be in the policy
(type t5)
(block b5
(blockabstract b5)