@@ -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;
}
@@ -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;
@@ -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;
@@ -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;
};
@@ -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
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@gmail.com> --- 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(-)