The optional specification of a file type for a genfscon rule to make it apply only to a specific security class is allowed by checkpolicy and checkmodule and should be allowed for CIL policies as well. Allow an optional file type to be specified for a genfscon rule. The new syntax: (genfscon FSNAME PATH [FILE_TYPE] CONTEXT) FSNAME - The name of the supported filesystem PATH - If FSNAME is proc then this is the partial path, othewise this must be "/". FILE_TYPE - A single keyword representing the file type. file type security class any Same as not specifying a file type file file dir dir char chr_file block blk_file socket sock_file pipe fifo_file symlink lnk_file CONTEXT - Either a previously declared security context identifier or an anonymous security context. Signed-off-by: James Carter <jwcart2@xxxxxxxxx> --- v2: Initialize file_type field Reordered if else block to start with "any" Write out file type when writing AST libsepol/cil/src/cil.c | 1 + libsepol/cil/src/cil_binary.c | 37 +++++++++++++++++++++++++++ libsepol/cil/src/cil_build_ast.c | 43 +++++++++++++++++++++++++++++--- libsepol/cil/src/cil_internal.h | 1 + libsepol/cil/src/cil_write_ast.c | 27 ++++++++++++++++++++ 5 files changed, 105 insertions(+), 4 deletions(-) diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c index a152d689..9916cbee 100644 --- a/libsepol/cil/src/cil.c +++ b/libsepol/cil/src/cil.c @@ -2577,6 +2577,7 @@ void cil_genfscon_init(struct cil_genfscon **genfscon) (*genfscon)->fs_str = NULL; (*genfscon)->path_str = NULL; + (*genfscon)->file_type = CIL_FILECON_ANY; (*genfscon)->context_str = NULL; (*genfscon)->context = NULL; } diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c index d8aa495a..4ac8ce8d 100644 --- a/libsepol/cil/src/cil_binary.c +++ b/libsepol/cil/src/cil_binary.c @@ -3462,6 +3462,43 @@ int cil_genfscon_to_policydb(policydb_t *pdb, struct cil_sort *genfscons) new_ocon->u.name = cil_strdup(cil_genfscon->path_str); + if (cil_genfscon->file_type != CIL_FILECON_ANY) { + class_datum_t *class_datum; + const char *class_name; + switch (cil_genfscon->file_type) { + case CIL_FILECON_FILE: + class_name = "file"; + break; + case CIL_FILECON_DIR: + class_name = "dir"; + break; + case CIL_FILECON_CHAR: + class_name = "chr_file"; + break; + case CIL_FILECON_BLOCK: + class_name = "blk_file"; + break; + case CIL_FILECON_SOCKET: + class_name = "sock_file"; + break; + case CIL_FILECON_PIPE: + class_name = "fifo_file"; + break; + case CIL_FILECON_SYMLINK: + class_name = "lnk_file"; + break; + default: + rc = SEPOL_ERR; + goto exit; + } + class_datum = hashtab_search(pdb->p_classes.table, class_name); + if (!class_datum) { + rc = SEPOL_ERR; + goto exit; + } + new_ocon->v.sclass = class_datum->s.value; + } + rc = __cil_context_to_sepol_context(pdb, cil_genfscon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c index 6a6f4f33..4a501b8f 100644 --- a/libsepol/cil/src/cil_build_ast.c +++ b/libsepol/cil/src/cil_build_ast.c @@ -4572,9 +4572,11 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, + CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); + struct cil_tree_node *context_node; int rc = SEPOL_ERR; struct cil_genfscon *genfscon = NULL; @@ -4592,15 +4594,48 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str genfscon->fs_str = parse_current->next->data; genfscon->path_str = parse_current->next->next->data; - if (parse_current->next->next->next->cl_head == NULL ) { - genfscon->context_str = parse_current->next->next->next->data; + if (parse_current->next->next->next->next) { + /* (genfscon <FS_STR> <PATH_STR> <FILE_TYPE> ... */ + char *file_type = parse_current->next->next->next->data; + if (file_type == CIL_KEY_ANY) { + genfscon->file_type = CIL_FILECON_ANY; + } else if (file_type == CIL_KEY_FILE) { + genfscon->file_type = CIL_FILECON_FILE; + } else if (file_type == CIL_KEY_DIR) { + genfscon->file_type = CIL_FILECON_DIR; + } else if (file_type == CIL_KEY_CHAR) { + genfscon->file_type = CIL_FILECON_CHAR; + } else if (file_type == CIL_KEY_BLOCK) { + genfscon->file_type = CIL_FILECON_BLOCK; + } else if (file_type == CIL_KEY_SOCKET) { + genfscon->file_type = CIL_FILECON_SOCKET; + } else if (file_type == CIL_KEY_PIPE) { + genfscon->file_type = CIL_FILECON_PIPE; + } else if (file_type == CIL_KEY_SYMLINK) { + genfscon->file_type = CIL_FILECON_SYMLINK; + } else { + if (parse_current->next->next->next->cl_head) { + cil_log(CIL_ERR, "Expecting file type, but found a list\n"); + } else { + cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type); + } + rc = SEPOL_ERR; + goto exit; + } + context_node = parse_current->next->next->next->next; } else { - cil_context_init(&genfscon->context); + /* (genfscon <FS_STR> <PATH_STR> ... */ + context_node = parse_current->next->next->next; + } - rc = cil_fill_context(parse_current->next->next->next->cl_head, genfscon->context); + if (context_node->cl_head) { + cil_context_init(&genfscon->context); + rc = cil_fill_context(context_node->cl_head, genfscon->context); if (rc != SEPOL_OK) { goto exit; } + } else { + genfscon->context_str = context_node->data; } ast_node->data = genfscon; diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h index fb2856d6..a7604762 100644 --- a/libsepol/cil/src/cil_internal.h +++ b/libsepol/cil/src/cil_internal.h @@ -791,6 +791,7 @@ struct cil_ipaddr { struct cil_genfscon { char *fs_str; char *path_str; + enum cil_filecon_types file_type; char *context_str; struct cil_context *context; }; diff --git a/libsepol/cil/src/cil_write_ast.c b/libsepol/cil/src/cil_write_ast.c index 40effcdc..bebb2670 100644 --- a/libsepol/cil/src/cil_write_ast.c +++ b/libsepol/cil/src/cil_write_ast.c @@ -1328,6 +1328,33 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) struct cil_genfscon *genfscon = node->data; fprintf(out, "(genfscon "); fprintf(out, "%s \"%s\" ", genfscon->fs_str, genfscon->path_str); + if (genfscon->file_type != CIL_FILECON_ANY) { + switch (genfscon->file_type) { + case CIL_FILECON_FILE: + fprintf(out, "%s ", CIL_KEY_FILE); + break; + case CIL_FILECON_DIR: + fprintf(out, "%s ", CIL_KEY_DIR); + break; + case CIL_FILECON_CHAR: + fprintf(out, "%s ", CIL_KEY_CHAR); + break; + case CIL_FILECON_BLOCK: + fprintf(out, "%s ", CIL_KEY_BLOCK); + break; + case CIL_FILECON_SOCKET: + fprintf(out, "%s ", CIL_KEY_SOCKET); + break; + case CIL_FILECON_PIPE: + fprintf(out, "%s ", CIL_KEY_PIPE); + break; + case CIL_FILECON_SYMLINK: + fprintf(out, "%s ", CIL_KEY_SYMLINK); + break; + default: + fprintf(out, "<?FILETYPE> "); + } + } if (genfscon->context) write_context(out, genfscon->context, CIL_TRUE); else -- 2.31.1