Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package cil for openSUSE:Factory checked in at 2026-07-13 14:25:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cil (Old) and /work/SRC/openSUSE:Factory/.cil.new.1991 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cil" Mon Jul 13 14:25:19 2026 rev:8 rq:1364574 version:3.11 Changes: -------- --- /work/SRC/openSUSE:Factory/cil/cil.changes 2026-02-09 11:43:25.009890471 +0100 +++ /work/SRC/openSUSE:Factory/.cil.new.1991/cil.changes 2026-07-13 14:25:23.681935096 +0200 @@ -1,0 +2,24 @@ +Tue Jul 7 15:30:46 UTC 2026 - Cathy Hu <[email protected]> + +- Fix secilcheck double-free (bsc#1270622) + - Add patch: 1270622-Fix-double-free-in-secilcheck.patch + - was merged upstream, can be dropped once the new release is out + +------------------------------------------------------------------- +Mon Jul 6 12:34:23 UTC 2026 - Cathy Hu <[email protected]> + +- Update to version 3.11 + https://github.com/SELinuxProject/selinux/releases/tag/3.11 + - User-visible changes: + - Added `secilcheck` program to check CIL neverallows against binary policies + - Multiple documentation improvements. + - Development-relevant changes: + - Reformatted entire tree based on .clang-format and added new + check-format/format make targets to check and/or reformat code to match. + This is now a requirement for new patches. + - Notable Bugfixes: + - secilc: Use fstat instead of stat to avoid TOCTOU issues +- Packaging changes: + - Add secilcheck + +------------------------------------------------------------------- Old: ---- secilc-3.10.tar.gz secilc-3.10.tar.gz.asc New: ---- 1270622-Fix-double-free-in-secilcheck.patch secilc-3.11.tar.gz secilc-3.11.tar.gz.asc ----------(New B)---------- New:- Fix secilcheck double-free (bsc#1270622) - Add patch: 1270622-Fix-double-free-in-secilcheck.patch - was merged upstream, can be dropped once the new release is out ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cil.spec ++++++ --- /var/tmp/diff_new_pack.P4iwE5/_old 2026-07-13 14:25:24.621967236 +0200 +++ /var/tmp/diff_new_pack.P4iwE5/_new 2026-07-13 14:25:24.621967236 +0200 @@ -17,7 +17,7 @@ Name: cil -Version: 3.10 +Version: 3.11 Release: 0 Summary: SELinux Common Intermediate Language compiler License: BSD-2-Clause @@ -26,6 +26,8 @@ Source0: https://github.com/SELinuxProject/selinux/releases/download/%{version}/se%{name}c-%{version}.tar.gz Source1: https://github.com/SELinuxProject/selinux/releases/download/%{version}/se%{name}c-%{version}.tar.gz.asc Source2: cil.keyring +# PATCH-FIX-UPSTREAM 1270622-Fix-double-free-in-secilcheck.patch bsc#1270622 [email protected] +Patch0: 1270622-Fix-double-free-in-secilcheck.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: flex BuildRequires: libsepol-devel @@ -40,7 +42,7 @@ This is a compiler for CIL. %prep -%setup -q -n secilc-%{version}/ +%autosetup -n secilc-%{version}/ %build make @@ -54,4 +56,5 @@ %doc %{_mandir}/man8/* /usr/bin/secil2conf /usr/bin/secil2tree +/usr/bin/secilcheck ++++++ 1270622-Fix-double-free-in-secilcheck.patch ++++++ >From 835e8920ed1582c754f603d8f77769be4176bc9f Mon Sep 17 00:00:00 2001 From: Cathy Hu <[email protected]> Date: Tue, 7 Jul 2026 14:15:33 +0200 Subject: [PATCH] Fix double-free in secilcheck If the file size of the cil file is zero, fclose was called twice. Fixes: ``` localhost:~ # touch ~/.empty.cil localhost:~ # secilcheck /etc/selinux/targeted/policy/policy.35 ./empty.cil free(): double free detected in tcache 2 Aborted (core dumped) secilcheck /etc/selinux/targeted/policy/policy.35 ./empty.cil ``` Signed-off-by: Cathy Hu <[email protected]> --- secilc/secilcheck.c | 1 - 1 file changed, 1 deletion(-) diff --git a/secilc/secilcheck.c b/secilc/secilcheck.c index ee141bc0..b7c32bc6 100644 --- a/secilc/secilcheck.c +++ b/secilc/secilcheck.c @@ -155,7 +155,6 @@ static int add_cil_file(const char *filename, struct cil_db *cdb) file_size = filedata.st_size; if (!file_size) { - fclose(file); rc = 0; goto exit; } -- 2.54.0 ++++++ secilc-3.10.tar.gz -> secilc-3.11.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/.gitignore new/secilc-3.11/.gitignore --- old/secilc-3.10/.gitignore 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/.gitignore 2026-07-01 18:51:05.000000000 +0200 @@ -4,6 +4,8 @@ secil2conf.8 secil2tree secil2tree.8 +secilcheck +secilcheck.8 policy.* file_contexts docs/html diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/Makefile new/secilc-3.11/Makefile --- old/secilc-3.10/Makefile 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/Makefile 2026-07-01 18:51:05.000000000 +0200 @@ -14,9 +14,14 @@ SECIL2TREE_SRCS := secil2tree.c SECIL2TREE_OBJS := $(patsubst %.c,%.o,$(SECIL2TREE_SRCS)) +SECILCHECK = secilcheck +SECILCHECK_SRCS := secilcheck.c +SECILCHECK_OBJS := $(patsubst %.c,%.o,$(SECILCHECK_SRCS)) + SECILC_MANPAGE = secilc.8 SECIL2CONF_MANPAGE = secil2conf.8 SECIL2TREE_MANPAGE = secil2tree.8 +SECILCHECK_MANPAGE = secilcheck.8 XMLTO = xmlto DIFF = diff @@ -28,7 +33,7 @@ override CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 override LDLIBS += -lsepol -all: $(SECILC) $(SECIL2CONF) $(SECIL2TREE) man +all: $(SECILC) $(SECIL2CONF) $(SECIL2TREE) $(SECILCHECK) man $(SECILC): $(SECILC_OBJS) $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) @@ -45,7 +50,10 @@ $(SECIL2TREE): $(SECIL2TREE_OBJS) $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) -man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE) $(SECIL2TREE_MANPAGE) +$(SECILCHECK): $(SECILCHECK_OBJS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE) $(SECIL2TREE_MANPAGE) $(SECILCHECK_MANPAGE) $(SECILC_MANPAGE): $(SECILC_MANPAGE).xml $(XMLTO) man $(SECILC_MANPAGE).xml @@ -56,15 +64,20 @@ $(SECIL2TREE_MANPAGE): $(SECIL2TREE_MANPAGE).xml $(XMLTO) man $(SECIL2TREE_MANPAGE).xml +$(SECILCHECK_MANPAGE): $(SECILCHECK_MANPAGE).xml + $(XMLTO) man $(SECILCHECK_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 755 $(SECILCHECK) $(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 + install -m 644 $(SECILCHECK_MANPAGE) $(DESTDIR)$(MANDIR)/man8 doc: $(MAKE) -C docs @@ -76,11 +89,14 @@ rm -f $(SECIL2CONF_OBJS) rm -f $(SECIL2TREE) rm -f $(SECIL2TREE_OBJS) + rm -f $(SECILCHECK) + rm -f $(SECILCHECK_OBJS) rm -f policy.* rm -f file_contexts rm -f $(SECILC_MANPAGE) rm -f $(SECIL2CONF_MANPAGE) rm -f $(SECIL2TREE_MANPAGE) + rm -f $(SECILCHECK_MANPAGE) rm -f opt-actual.cil rm -f opt-actual.bin $(MAKE) -C docs clean diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/VERSION new/secilc-3.11/VERSION --- old/secilc-3.10/VERSION 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/VERSION 2026-07-01 18:51:05.000000000 +0200 @@ -1 +1 @@ -3.10 +3.11 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/docs/cil_access_vector_rules.md new/secilc-3.11/docs/cil_access_vector_rules.md --- old/secilc-3.10/docs/cil_access_vector_rules.md 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/docs/cil_access_vector_rules.md 2026-07-01 18:51:05.000000000 +0200 @@ -168,7 +168,7 @@ (type type_2) (type type_3) (typeattribute all_types) - (typeattributeset all_types ((all))) + (typeattributeset all_types (all)) (neverallow type_3 all_types (property_service (set))) ; This rule will fail compilation: @@ -313,7 +313,7 @@ (type type_2) (type type_3) (typeattribute all_types) - (typeattributeset all_types ((all))) + (typeattributeset all_types (all)) (neverallowx type_3 all_types (ioctl property_service (range 0x2000 0x20FF))) ; This rule will fail compilation: (allowx type_3 self (ioctl property_service (0x20A0))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/docs/cil_class_and_permission_statements.md new/secilc-3.11/docs/cil_class_and_permission_statements.md --- old/secilc-3.10/docs/cil_class_and_permission_statements.md 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/docs/cil_class_and_permission_statements.md 2026-07-01 18:51:05.000000000 +0200 @@ -529,7 +529,11 @@ <tbody> <tr class="odd"> <td align="left"><p>ioctl</p></td> -<td align="left"><p>Permissions define a whitelist of ioctl values. Permission values must range from <code>0x0000</code> to <code>0xFFFF</code>, inclusive.</p></td> +<td align="left"><p>Permissions define a whitelist of ioctl command values. Permission values must range from <code>0x0000</code> to <code>0xFFFF</code>, inclusive.</p></td> +</tr> +<tr class="even"> +<td align="left"><p>nlmsg</p></td> +<td align="left"><p>Permissions define a whitelist of netlink message type values. Permission values must range from <code>0x0000</code> to <code>0xFFFF</code>, inclusive.</p></td> </tr> </tbody> </table></td> @@ -561,4 +565,5 @@ (permissionx ioctl_1 (ioctl tcp_socket (0x2000 0x3000 0x4000))) (permissionx ioctl_2 (ioctl tcp_socket (range 0x6000 0x60FF))) (permissionx ioctl_3 (ioctl tcp_socket (and (range 0x8000 0x90FF) (not (range 0x8100 0x82FF))))) + (permissionx nlmsg_1 (nlmsg netlink_route_socket (range 0x0010 0x0018))) ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/docs/cil_default_object_statements.md new/secilc-3.11/docs/cil_default_object_statements.md --- old/secilc-3.10/docs/cil_default_object_statements.md 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/docs/cil_default_object_statements.md 2026-07-01 18:51:05.000000000 +0200 @@ -195,7 +195,7 @@ When creating a new `file` object, the appropriate `range` component of the new security context will be taken from the `target` context: ```secil - (defaultrange file target low_high) + (defaultrange file target low-high) ``` MLS userspace object managers may need to compute the common parts of a range such that the object is created with the range common to the subject and containing object: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/docs/cil_mls_labeling_statements.md new/secilc-3.11/docs/cil_mls_labeling_statements.md --- old/secilc-3.10/docs/cil_mls_labeling_statements.md 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/docs/cil_mls_labeling_statements.md 2026-07-01 18:51:05.000000000 +0200 @@ -319,7 +319,7 @@ This example orders one category alias and nine categories: ```secil - (categoryorder (documents c1 c2 c3 c4 c5 c6 c7 c8 c9) + (categoryorder (documents c1 c2 c3 c4 c5 c6 c7 c8 c9)) ``` categoryset @@ -675,7 +675,7 @@ ```secil (sensitivity s0) (sensitivity s1) - (sensitivityorder s0 s1) + (sensitivityorder (s0 s1)) (category c0) ... (level systemlow (s0)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/docs/cil_reference_guide.md new/secilc-3.11/docs/cil_reference_guide.md --- old/secilc-3.10/docs/cil_reference_guide.md 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/docs/cil_reference_guide.md 2026-07-01 18:51:05.000000000 +0200 @@ -93,7 +93,7 @@ Symbol Character Set -------------------- -Symbols (any string not enclosed in double quotes) must only contain alphanumeric `[a-z A-Z] [0-9]` characters plus the following special characters: `\.=/-_$%@+!|&^:` +Symbols (any string not enclosed in double quotes) must only contain alphanumeric `[a-z A-Z] [0-9]` characters plus the following special characters: `` [].@=/*-_$%+-!|&^:~`#{}'<>?, `` However symbols are checked for any specific character set limitations, for example: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/docs/cil_role_statements.md new/secilc-3.11/docs/cil_role_statements.md --- old/secilc-3.10/docs/cil_role_statements.md 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/docs/cil_role_statements.md 2026-07-01 18:51:05.000000000 +0200 @@ -51,7 +51,7 @@ **Statement definition:** ```secil - (role role_id type_id) + (roletype role_id type_id) ``` **Where:** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/secil2conf.c new/secilc-3.11/secil2conf.c --- old/secilc-3.10/secil2conf.c 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/secil2conf.c 2026-07-01 18:51:05.000000000 +0200 @@ -76,51 +76,54 @@ 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'}, - {"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} + { "help", no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { "mls", required_argument, NULL, 'M' }, + { "preserve-tunables", no_argument, NULL, 'P' }, + { "qualified-names", no_argument, NULL, 'Q' }, + { "output", required_argument, NULL, 'o' }, + { NULL, 0, NULL, 0 } }; int i; while (1) { - opt_char = getopt_long(argc, argv, "o:hvM:PQ", long_opts, &opt_index); + opt_char = getopt_long(argc, argv, "o:hvM:PQ", long_opts, + &opt_index); if (opt_char == -1) { break; } switch (opt_char) { - case 'v': - log_level++; - break; - case 'M': - if (!strcasecmp(optarg, "true") || !strcasecmp(optarg, "1")) { - mls = 1; - } else if (!strcasecmp(optarg, "false") || !strcasecmp(optarg, "0")) { - mls = 0; - } else { - usage(argv[0]); - } - break; - case 'P': - preserve_tunables = 1; - break; - case 'Q': - qualified_names = 1; - break; - case 'o': - free(output); - output = strdup(optarg); - break; - case 'h': - usage(argv[0]); - case '?': - break; - default: - fprintf(stderr, "Unsupported option: %s\n", optarg); + case 'v': + log_level++; + break; + case 'M': + if (!strcasecmp(optarg, "true") || + !strcasecmp(optarg, "1")) { + mls = 1; + } else if (!strcasecmp(optarg, "false") || + !strcasecmp(optarg, "0")) { + mls = 0; + } else { usage(argv[0]); + } + break; + case 'P': + preserve_tunables = 1; + break; + case 'Q': + qualified_names = 1; + break; + case 'o': + free(output); + output = strdup(optarg); + break; + case 'h': + usage(argv[0]); + case '?': + break; + default: + fprintf(stderr, "Unsupported option: %s\n", optarg); + usage(argv[0]); } } if (optind >= argc) { @@ -144,7 +147,7 @@ rc = SEPOL_ERR; goto exit; } - rc = stat(argv[i], &filedata); + rc = fstat(fileno(file), &filedata); if (rc == -1) { fprintf(stderr, "Could not stat file: %s\n", argv[i]); goto exit; @@ -188,7 +191,8 @@ file = fopen(output, "w"); } if (file == NULL) { - fprintf(stderr, "Failure opening policy.conf file for writing\n"); + fprintf(stderr, + "Failure opening policy.conf file for writing\n"); rc = SEPOL_ERR; goto exit; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/secil2tree.c new/secilc-3.11/secil2tree.c --- old/secilc-3.10/secil2tree.c 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/secil2tree.c 2026-07-01 18:51:05.000000000 +0200 @@ -81,55 +81,57 @@ 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} + { "help", no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { "preserve-tunables", no_argument, NULL, 'P' }, + { "qualified-names", no_argument, NULL, 'Q' }, + { "output", required_argument, NULL, 'o' }, + { "ast-phase", required_argument, NULL, 'A' }, + { NULL, 0, NULL, 0 } }; int i; while (1) { - opt_char = getopt_long(argc, argv, "o:hvPQA:", long_opts, &opt_index); + 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 if (!strcasecmp(optarg, "post")) { - write_ast = WRITE_AST_PHASE_POST; - } 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); + 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 if (!strcasecmp(optarg, "post")) { + write_ast = WRITE_AST_PHASE_POST; + } 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]); } } @@ -153,7 +155,7 @@ rc = SEPOL_ERR; goto exit; } - rc = stat(argv[i], &filedata); + rc = fstat(fileno(file), &filedata); if (rc == -1) { fprintf(stderr, "Could not stat file: %s\n", argv[i]); goto exit; @@ -190,7 +192,8 @@ } else { file = fopen(output, "w"); if (file == NULL) { - fprintf(stderr, "Failure opening file %s for writing\n", output); + fprintf(stderr, "Failure opening file %s for writing\n", + output); rc = SEPOL_ERR; goto exit; } @@ -217,7 +220,7 @@ } exit: - if (file != NULL && file != stdin) { + if (file != NULL && file != stdout) { fclose(file); } free(buffer); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/secilc.c new/secilc-3.11/secilc.c --- old/secilc-3.10/secilc.c 2026-02-02 03:01:16.000000000 +0100 +++ new/secilc-3.11/secilc.c 2026-07-01 18:51:05.000000000 +0200 @@ -56,7 +56,8 @@ printf(" This will override the (mls boolean) statement\n"); printf(" if present in the policy\n"); printf(" -c, --policyvers=<version> build a binary policy with a given <version>\n"); - printf(" (default: %i)\n", POLICYDB_VERSION_MAX); + printf(" (default: %i)\n", + POLICYDB_VERSION_MAX); printf(" -U, --handle-unknown=<action> how to handle unknown classes or permissions.\n"); printf(" may be deny, allow, or reject. (default: deny)\n"); printf(" This will override the (handleunknown action)\n"); @@ -109,131 +110,141 @@ size_t fc_size; enum cil_log_level log_level = CIL_ERR; static struct option long_opts[] = { - {"help", no_argument, 0, 'h'}, - {"verbose", no_argument, 0, 'v'}, - {"target", required_argument, 0, 't'}, - {"mls", required_argument, 0, 'M'}, - {"policyversion", required_argument, 0, 'c'}, - {"handle-unknown", required_argument, 0, 'U'}, - {"disable-dontaudit", no_argument, 0, 'D'}, - {"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'}, - {"expand-size", required_argument, 0, 'X'}, - {"optimize", no_argument, 0, 'O'}, - {0, 0, 0, 0} + { "help", no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { "target", required_argument, NULL, 't' }, + { "mls", required_argument, NULL, 'M' }, + { "policyversion", required_argument, NULL, 'c' }, + { "handle-unknown", required_argument, NULL, 'U' }, + { "disable-dontaudit", no_argument, NULL, 'D' }, + { "multiple-decls", no_argument, NULL, 'm' }, + { "disable-neverallow", no_argument, NULL, 'N' }, + { "preserve-tunables", no_argument, NULL, 'P' }, + { "qualified-names", no_argument, NULL, 'Q' }, + { "output", required_argument, NULL, 'o' }, + { "filecontexts", required_argument, NULL, 'f' }, + { "expand-generated", no_argument, NULL, 'G' }, + { "expand-size", required_argument, NULL, 'X' }, + { "optimize", no_argument, NULL, 'O' }, + { NULL, 0, NULL, 0 } }; int i; while (1) { - opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PQDmNOc: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; } switch (opt_char) { - case 'v': - log_level++; - break; - case 't': - if (!strcmp(optarg, "selinux")) { - target = SEPOL_TARGET_SELINUX; - } else if (!strcmp(optarg, "xen")) { - target = SEPOL_TARGET_XEN; - } else { - fprintf(stderr, "Unknown target: %s\n", optarg); - usage(argv[0]); - } - break; - case 'M': - if (!strcasecmp(optarg, "true") || !strcasecmp(optarg, "1")) { - mls = 1; - } else if (!strcasecmp(optarg, "false") || !strcasecmp(optarg, "0")) { - mls = 0; - } else { - usage(argv[0]); - } - break; - case 'c': { - char *endptr = NULL; - errno = 0; - policyvers = strtol(optarg, &endptr, 10); - if (errno != 0 || endptr == optarg || *endptr != '\0') { - fprintf(stderr, "Bad policy version: %s\n", optarg); - usage(argv[0]); - } - if (policyvers > POLICYDB_VERSION_MAX || policyvers < POLICYDB_VERSION_MIN) { - fprintf(stderr, "Policy version must be between %d and %d\n", - POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); - usage(argv[0]); - } - break; + case 'v': + log_level++; + break; + case 't': + if (!strcmp(optarg, "selinux")) { + target = SEPOL_TARGET_SELINUX; + } else if (!strcmp(optarg, "xen")) { + target = SEPOL_TARGET_XEN; + } else { + fprintf(stderr, "Unknown target: %s\n", optarg); + usage(argv[0]); } - case 'U': - if (!strcasecmp(optarg, "deny")) { - handle_unknown = SEPOL_DENY_UNKNOWN; - } else if (!strcasecmp(optarg, "allow")) { - handle_unknown = SEPOL_ALLOW_UNKNOWN; - } else if (!strcasecmp(optarg, "reject")) { - handle_unknown = SEPOL_REJECT_UNKNOWN; - } else { - usage(argv[0]); - } - break; - case 'D': - disable_dontaudit = 1; - break; - case 'm': - multiple_decls = 1; - break; - case 'N': - disable_neverallow = 1; - break; - 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': - attrs_expand_generated = 1; - break; - case 'X': { - char *endptr = NULL; - errno = 0; - attrs_expand_size = strtol(optarg, &endptr, 10); - if (errno != 0 || endptr == optarg || *endptr != '\0') { - fprintf(stderr, "Bad attribute expand size: %s\n", optarg); - usage(argv[0]); - } - - if (attrs_expand_size < 0) { - fprintf(stderr, "Attribute expand size must be > 0\n"); - usage(argv[0]); - } - break; + break; + case 'M': + if (!strcasecmp(optarg, "true") || + !strcasecmp(optarg, "1")) { + mls = 1; + } else if (!strcasecmp(optarg, "false") || + !strcasecmp(optarg, "0")) { + mls = 0; + } else { + usage(argv[0]); } - case 'O': - optimize = 1; - break; - case 'h': + break; + case 'c': { + char *endptr = NULL; + errno = 0; + policyvers = strtol(optarg, &endptr, 10); + if (errno != 0 || endptr == optarg || *endptr != '\0') { + fprintf(stderr, "Bad policy version: %s\n", + optarg); usage(argv[0]); - case '?': - break; - default: - fprintf(stderr, "Unsupported option: %s\n", optarg); + } + if (policyvers > POLICYDB_VERSION_MAX || + policyvers < POLICYDB_VERSION_MIN) { + fprintf(stderr, + "Policy version must be between %d and %d\n", + POLICYDB_VERSION_MIN, + POLICYDB_VERSION_MAX); usage(argv[0]); + } + break; + } + case 'U': + if (!strcasecmp(optarg, "deny")) { + handle_unknown = SEPOL_DENY_UNKNOWN; + } else if (!strcasecmp(optarg, "allow")) { + handle_unknown = SEPOL_ALLOW_UNKNOWN; + } else if (!strcasecmp(optarg, "reject")) { + handle_unknown = SEPOL_REJECT_UNKNOWN; + } else { + usage(argv[0]); + } + break; + case 'D': + disable_dontaudit = 1; + break; + case 'm': + multiple_decls = 1; + break; + case 'N': + disable_neverallow = 1; + break; + 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': + attrs_expand_generated = 1; + break; + case 'X': { + char *endptr = NULL; + errno = 0; + attrs_expand_size = strtol(optarg, &endptr, 10); + if (errno != 0 || endptr == optarg || *endptr != '\0') { + fprintf(stderr, + "Bad attribute expand size: %s\n", + optarg); + usage(argv[0]); + } + + if (attrs_expand_size < 0) { + fprintf(stderr, + "Attribute expand size must be > 0\n"); + usage(argv[0]); + } + break; + } + case 'O': + optimize = 1; + break; + case 'h': + usage(argv[0]); + case '?': + break; + default: + fprintf(stderr, "Unsupported option: %s\n", optarg); + usage(argv[0]); } } if (optind >= argc) { @@ -271,7 +282,7 @@ rc = SEPOL_ERR; goto exit; } - rc = stat(argv[i], &filedata); + rc = fstat(fileno(file), &filedata); if (rc == -1) { fprintf(stderr, "Could not stat file: %s\n", argv[i]); rc = SEPOL_ERR; @@ -339,7 +350,8 @@ rc = SEPOL_ERR; goto exit; } - if (snprintf(output, size + 1, "policy.%d", policyvers) != size) { + if (snprintf(output, size + 1, "policy.%d", policyvers) != + size) { fprintf(stderr, "Failed to create output filename\n"); rc = SEPOL_ERR; goto exit; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/secilcheck.8.xml new/secilc-3.11/secilcheck.8.xml --- old/secilc-3.10/secilcheck.8.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/secilc-3.11/secilcheck.8.xml 2026-07-01 18:51:05.000000000 +0200 @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> + +<refentry> + <refentryinfo> + <author> + <firstname>James</firstname><surname>Carter</surname><contrib></contrib> + </author> + </refentryinfo> + + <refmeta> + <refentrytitle>SECILCHECK</refentrytitle> + <manvolnum>8</manvolnum> + <refmiscinfo class="date">29 May 2026</refmiscinfo> + <refmiscinfo class="source">secilcheck</refmiscinfo> + <refmiscinfo class="manual">Check binary policy file against CIL neverallow files</refmiscinfo> + </refmeta> + <refnamediv id="name"> + <refname>secilcheck</refname> + <refpurpose>invoke the CIL neverallow checker</refpurpose> + </refnamediv> + + <refsynopsisdiv id="synopsis"> + <cmdsynopsis> + <command>secilcheck</command> + <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg> + <arg choice="plain"><replaceable>binary</replaceable></arg> + <arg choice="plain" rep="repeat"><replaceable>file</replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1 id="description"><title>DESCRIPTION</title> + <para><emphasis role="italic">secilcheck</emphasis> invokes the CIL neverallow checker with specified <emphasis role="italic">argument</emphasis>s.</para> + </refsect1> + + <refsect1 id="options"><title>OPTIONS</title> + <variablelist> + <varlistentry> + <term><option>-Q, --qualified-names</option></term> + <listitem><para>Allow names containing dots (qualified names). Blocks, blockinherits, blockabstracts, and in-statements will not be allowed.</para></listitem> + </varlistentry> + + <varlistentry> + <term><option>-m, --multiple-decls</option></term> + <listitem><para>Allow some statements to be re-declared.</para></listitem> + </varlistentry> + + <varlistentry> + <term><option>-v, --verbose</option></term> + <listitem><para>Increment verbosity level.</para></listitem> + </varlistentry> + + <varlistentry> + <term><option>-h, --help</option></term> + <listitem><para>Display usage information.</para></listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1 id="see_also"><title>SEE ALSO</title> + <para> + <simplelist type="inline"> + <member><citerefentry> + <refentrytitle>secilc</refentrytitle> + <manvolnum>8</manvolnum> + </citerefentry></member> + <member><citerefentry> + <refentrytitle>secil2tree</refentrytitle> + <manvolnum>8</manvolnum> + </citerefentry></member> + <member><citerefentry> + <refentrytitle>secil2conf</refentrytitle> + <manvolnum>8</manvolnum> + </citerefentry></member> + </simplelist> + </para> + <para>HTML documentation describing the CIL language statements is available starting with <emphasis role="italic">docs/html/index.html</emphasis>.</para> + <para>PDF documentation describing the CIL language statements is available at: <emphasis role="italic">docs/pdf/CIL_Reference_Guide.pdf</emphasis>.</para> + </refsect1> +</refentry> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/secilc-3.10/secilcheck.c new/secilc-3.11/secilcheck.c --- old/secilc-3.10/secilcheck.c 1970-01-01 01:00:00.000000000 +0100 +++ new/secilc-3.11/secilcheck.c 2026-07-01 18:51:05.000000000 +0200 @@ -0,0 +1,309 @@ +/* + * 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 <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <stdint.h> +#include <string.h> +#include <getopt.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#ifdef ANDROID +#include <cil/cil.h> +#else +#include <sepol/cil/cil.h> +#endif +#include <sepol/policydb.h> +#include <sepol/kernel_to_cil.h> + +static int get_binary_policy_db(const char *filename, sepol_policydb_t *pdb) +{ + int fd; + struct stat sb; + void *map = NULL; + sepol_policy_file_t *pf = NULL; + int rc = SEPOL_ERR; + + /* Read binary policy */ + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Could not open file: %s\n", filename); + goto exit; + } + if (fstat(fd, &sb) < 0) { + fprintf(stderr, "Could not stat file: %s\n", filename); + goto exit; + } + map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, + 0); + if (map == MAP_FAILED) { + fprintf(stderr, "Could not map file: %s\n", filename); + goto exit; + } + + if (sepol_policy_file_create(&pf) < 0) { + fprintf(stderr, "Out of memory"); + goto exit; + } + sepol_policy_file_set_mem(pf, map, sb.st_size); + + if (sepol_policydb_read(pdb, pf) < 0) { + fprintf(stderr, "Error reading binary policy: %s\n", filename); + rc = SEPOL_ERR; + goto exit; + } + + rc = SEPOL_OK; + +exit: + if (fd >= 0) + close(fd); + if (map) + munmap(map, sb.st_size); + sepol_policy_file_free(pf); + return rc; +} + +static int add_decls_to_cil(const char *filename, sepol_policydb_t *pdb, + struct cil_db *db) +{ + FILE *cfp = NULL; + char *cptr = NULL; + size_t csize; + int rc = SEPOL_ERR; + + cfp = open_memstream(&cptr, &csize); + if (!cfp) { + fprintf(stderr, + "Failed to open dynamic memory buffer stream\n"); + goto exit; + } + + if (sepol_kernel_policydb_decls_to_cil(cfp, &pdb->p) < 0) { + fprintf(stderr, "Failed to convert binary policy to CIL\n"); + goto exit; + } + + if (fflush(cfp) < 0) { + fprintf(stderr, "Failed to flush CIL memory buffer stream\n"); + goto exit; + } + + /* Add to CIL db */ + if (cil_add_file(db, filename, cptr, csize) < 0) { + fprintf(stderr, "Failed to add binary policy file: %s\n", + filename); + goto exit; + } + + rc = 0; + +exit: + if (cfp) + fclose(cfp); + if (cptr) + free(cptr); + return rc; +} + +static int add_cil_file(const char *filename, struct cil_db *cdb) +{ + FILE *file; + struct stat filedata; + char *buffer = NULL; + size_t file_size; + int rc = -1; + + file = fopen(filename, "r"); + if (!file) { + fprintf(stderr, "Could not open file: %s\n", filename); + goto exit; + } + if (fstat(fileno(file), &filedata) < 0) { + fprintf(stderr, "Could not stat file: %s\n", filename); + goto exit; + } + file_size = filedata.st_size; + + if (!file_size) { + fclose(file); + rc = 0; + goto exit; + } + + buffer = malloc(file_size); + if (!buffer) { + fprintf(stderr, "Out of memory\n"); + goto exit; + } + + if (fread(buffer, file_size, 1, file) != 1) { + fprintf(stderr, "Failure reading file: %s\n", filename); + goto exit; + } + + if (cil_add_file(cdb, filename, buffer, file_size) < 0) { + fprintf(stderr, "Failure adding %s\n", filename); + goto exit; + } + + rc = 0; + +exit: + if (file) + fclose(file); + if (buffer) + free(buffer); + return rc; +} + +static __attribute__((__noreturn__)) void usage(const char *prog) +{ + printf("Usage: %s [OPTION]... BIN_POLICY CIL_NEVERALLOW_FILE1...\n", + prog); + printf("\n"); + printf("Options:\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(" -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; + sepol_policydb_t *pdb = NULL; + int violation = 0; + struct cil_db *db = NULL; + int multiple_decls = 0; + int qualified_names = 0; + int opt_char; + int opt_index = 0; + enum cil_log_level log_level = CIL_ERR; + static struct option long_opts[] = { + { "help", no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { "multiple-decls", no_argument, NULL, 'm' }, + { "qualified-names", no_argument, NULL, 'Q' }, + { NULL, 0, NULL, 0 } + }; + + while (1) { + opt_char = + getopt_long(argc, argv, "hvQm", long_opts, &opt_index); + if (opt_char == -1) { + break; + } + switch (opt_char) { + case 'v': + log_level++; + break; + case 'm': + multiple_decls = 1; + break; + case 'Q': + qualified_names = 1; + break; + case 'h': + usage(argv[0]); + case '?': + break; + default: + fprintf(stderr, "Unsupported option: %s\n", optarg); + usage(argv[0]); + } + } + + if (argc < optind + 2) { + fprintf(stderr, "Not enough files specified\n"); + usage(argv[0]); + } + + cil_set_log_level(log_level); + + cil_db_init(&db); + cil_set_multiple_decls(db, multiple_decls); + cil_set_qualified_names(db, qualified_names); + + if (sepol_policydb_create(&pdb) < 0) { + fprintf(stderr, "Out of memory\n"); + goto exit; + } + if (get_binary_policy_db(argv[optind], pdb) < 0) { + fprintf(stderr, "Failed to get binary policy db\n"); + rc = SEPOL_ERR; + goto exit; + } + if (add_decls_to_cil(argv[optind], pdb, db) < 0) { + fprintf(stderr, "Failed to convert decls to CIL\n"); + rc = SEPOL_ERR; + goto exit; + } + optind++; + + do { + if (add_cil_file(argv[optind], db) < 0) { + fprintf(stderr, + "Failed to add cil file to CIL files\n"); + rc = SEPOL_ERR; + goto exit; + } + optind++; + } while (optind < argc); + + rc = cil_compile(db); + if (rc != SEPOL_OK) { + fprintf(stderr, "Failed to compile cildb: %d\n", rc); + goto exit; + } + + rc = cil_check_neverallows_against_pdb(db, &pdb->p, &violation); + if (rc != SEPOL_OK) { + fprintf(stderr, "Failed to complete neverallow checking\n"); + goto exit; + } + if (violation == 1) { + fprintf(stderr, "There was a neverallow violation\n"); + rc = SEPOL_ERR; + goto exit; + } + + rc = SEPOL_OK; + +exit: + cil_db_destroy(&db); + sepol_policydb_free(pdb); + return rc; +}
