Skip to content

Commit

Permalink
Introduce name_list
Browse files Browse the repository at this point in the history
For checks checking for missing or redundant required types
`get_names_in_node()` and `get_names_required()` return a list of names.
Currently those are just a list of strings without any type information.
Add a new datatype to store known type information to improve checks
iterating these names.
  • Loading branch information
cgzones committed Dec 29, 2023
1 parent fa70204 commit b13978d
Show file tree
Hide file tree
Showing 12 changed files with 736 additions and 144 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ tests/check_startup
tests/check_te_checks
tests/check_ordering
tests/check_perm_macro
tests/check_name_list
tests/functional/policies/parse_errors/test3_tmp.if
tests/functional/policies/parse_errors/test5_tmp.te
tests/functional/policies/parse_errors/test6_tmp.if
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

bin_PROGRAMS = selint
selint_SOURCES = main.c lex.l parse.y tree.c tree.h selint_error.h parse_functions.c parse_functions.h maps.c maps.h runner.c runner.h parse_fc.c parse_fc.h template.c template.h file_list.c file_list.h check_hooks.c check_hooks.h fc_checks.c fc_checks.h util.c util.h if_checks.c if_checks.h selint_config.c selint_config.h string_list.c string_list.h startup.c startup.h te_checks.c te_checks.h ordering.c ordering.h color.c color.h perm_macro.c perm_macro.h xalloc.h
selint_SOURCES = main.c lex.l parse.y tree.c tree.h selint_error.h parse_functions.c parse_functions.h maps.c maps.h runner.c runner.h parse_fc.c parse_fc.h template.c template.h file_list.c file_list.h check_hooks.c check_hooks.h fc_checks.c fc_checks.h util.c util.h if_checks.c if_checks.h selint_config.c selint_config.h string_list.c string_list.h startup.c startup.h te_checks.c te_checks.h ordering.c ordering.h color.c color.h perm_macro.c perm_macro.h xalloc.h name_list.c name_list.h
BUILT_SOURCES = parse.h
AM_YFLAGS = -d -Wno-yacc -Werror=conflicts-rr -Werror=conflicts-sr

Expand Down
67 changes: 31 additions & 36 deletions src/if_checks.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ struct check_result *check_name_used_but_not_required_in_if(const struct

const struct policy_node *cur = node;

struct string_list *names_in_current_node = get_names_in_node(node);
struct name_list *names_in_current_node = get_names_in_node(node);

if (!names_in_current_node) {
return NULL;
Expand All @@ -276,15 +276,15 @@ struct check_result *check_name_used_but_not_required_in_if(const struct
}

if (!cur) {
free_string_list(names_in_current_node);
free_name_list(names_in_current_node);
return NULL;
}
// In a template or interface, and cur is a pointer to the definition node

cur = cur->first_child;

struct string_list *names_required = NULL;
struct string_list *names_required_tail = NULL;
struct name_list *names_required = NULL;
struct name_list *names_required_tail = NULL;

while (cur && cur != node) {
if (cur->flavor == NODE_GEN_REQ
Expand All @@ -305,35 +305,30 @@ struct check_result *check_name_used_but_not_required_in_if(const struct
// for example in an ifdef
}

const struct string_list *name_node = names_in_current_node;
const struct name_list *name_node = names_in_current_node;
/* In declarations skip the first name, which is the new declared type */
if (node->flavor == NODE_DECL) {
name_node = name_node->next;
}
const char *flavor = NULL;

while (name_node) {
if (!str_in_sl(name_node->string, names_required)) {
if (0 == strcmp(name_node->string, "system_r")) {
const struct name_data *ndata = name_node->data;
if (!name_list_contains_name(names_required, ndata)) {
if (name_is_role(ndata) && 0 == strcmp(ndata->name, "system_r")) {
// system_r is required by default in all modules
// so that is an exception that shouldn't be warned
// about.
name_node = name_node->next;
continue;
}
if (look_up_in_decl_map(name_node->string, DECL_TYPE)) {
if (name_is_type(ndata) && look_up_in_decl_map(ndata->name, DECL_TYPE)) {
flavor = "Type";
} else
if (look_up_in_decl_map
(name_node->string, DECL_ATTRIBUTE)) {
} else if (name_is_typeattr(ndata) && look_up_in_decl_map(ndata->name, DECL_ATTRIBUTE)) {
flavor = "Attribute";
} else
if (look_up_in_decl_map
(name_node->string, DECL_ATTRIBUTE_ROLE)) {
} else if (name_is_roleattr(ndata) && look_up_in_decl_map(ndata->name, DECL_ATTRIBUTE_ROLE)) {
flavor = "Role Attribute";
} else
if (look_up_in_decl_map
(name_node->string, DECL_ROLE)) {
} else if (name_is_role(ndata) && look_up_in_decl_map(ndata->name, DECL_ROLE)) {
flavor = "Role";
} else {
// This is a string we don't recognize. Other checks and/or
Expand All @@ -344,16 +339,16 @@ struct check_result *check_name_used_but_not_required_in_if(const struct

struct check_result *res =
make_check_result('W', W_ID_NO_REQ, NOT_REQ_MESSAGE,
flavor, name_node->string);
free_string_list(names_in_current_node);
free_string_list(names_required);
flavor, ndata->name);
free_name_list(names_in_current_node);
free_name_list(names_required);
return res;
}
name_node = name_node->next;
}

free_string_list(names_in_current_node);
free_string_list(names_required);
free_name_list(names_in_current_node);
free_name_list(names_required);

return NULL;
}
Expand Down Expand Up @@ -405,7 +400,7 @@ struct check_result *check_name_required_but_not_used_in_if(const struct
return NULL;
}

struct string_list *names_to_check = get_names_in_node(node);
struct name_list *names_to_check = get_names_in_node(node);
if (!names_to_check) {
// This should never happen
return alloc_internal_error(
Expand All @@ -416,22 +411,22 @@ struct check_result *check_name_required_but_not_used_in_if(const struct

cur = cur->next;

struct string_list *sl_end = NULL;
struct string_list *sl_head = NULL;
struct name_list *nl_end = NULL;
struct name_list *nl_head = NULL;

int depth = 0;

while (cur) {
struct string_list *names_used = get_names_in_node(cur);
struct name_list *names_used = get_names_in_node(cur);
if (names_used) {
if (!sl_head) {
sl_head = sl_end = names_used;
if (!nl_head) {
nl_head = nl_end = names_used;
} else {
sl_end->next = names_used;
nl_end->next = names_used;
}

while (sl_end->next) {
sl_end = sl_end->next;
while (nl_end->next) {
nl_end = nl_end->next;
}
}

Expand All @@ -452,24 +447,24 @@ struct check_result *check_name_required_but_not_used_in_if(const struct
}
}

const struct string_list *name_node = names_to_check;
const struct name_list *name_node = names_to_check;

struct check_result *res = NULL;

while (name_node) {
if (!str_in_sl(name_node->string, sl_head)) {
if (!name_list_contains_name(nl_head, name_node->data)) {
res = make_check_result('W',
W_ID_UNUSED_REQ,
"%s %s is listed in require block but not used in interface",
flavor,
name_node->string);
name_node->data->name);
break;
}
name_node = name_node->next;
}

free_string_list(sl_head);
free_string_list(names_to_check);
free_name_list(nl_head);
free_name_list(names_to_check);
return res;
}

Expand Down
Loading

0 comments on commit b13978d

Please sign in to comment.