Error out instead of silently converting too big integer values in
policy sources.
policy_parse.y:893:41: runtime error: implicit conversion from type 'unsigned long' of value 18446744073709551615 (64-bit, unsigned) to type 'unsigned int' changed the value to 4294967295 (32-bit, unsigned)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Avoid implicit conversions from signed to unsigned values, found by
UB sanitizers, by using unsigned values in the first place.
dismod.c:92:42: runtime error: left shift of 1 by 31 places cannot be represented in type 'int'
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Example leak:
Indirect leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x49bacd in __interceptor_malloc (./checkpolicy/test/dismod+0x49bacd)
#1 0x58ae54 in add_i_to_a ./libsepol/src/util.c:55:21
#2 0x53ea8e in symtab_insert ./libsepol/src/policydb.c:1729:6
#3 0x536252 in roles_init ./libsepol/src/policydb.c:772:7
#4 0x536252 in policydb_init ./libsepol/src/policydb.c:892:7
#5 0x562ff1 in sepol_policydb_create ./libsepol/src/policydb_public.c:69:6
#6 0x521a7c in module_package_init ./libsepol/src/module.c:96:6
#7 0x521a7c in sepol_module_package_create ./libsepol/src/module.c:126:7
#8 0x4cfb80 in read_policy ./checkpolicy/test/dismod.c:750:7
#9 0x4cda10 in main ./checkpolicy/test/dismod.c:878:6
#10 0x7f8538d01e49 in __libc_start_main csu/../csu/libc-start.c:314:16
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Ideally they should be declared in the corresponding header file, but
the overall include style in the checkpolicy code is quite messy.
Declare them for now in the source file before defining them to silence
related compiler warnings:
policy_define.c:84:6: error: no previous prototype for function 'init_parser' [-Werror,-Wmissing-prototypes]
void init_parser(int pass_number)
^
policy_define.c:93:6: error: no previous prototype for function 'yyerror2' [-Werror,-Wmissing-prototypes]
void yyerror2(const char *fmt, ...)
^
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Make it more obvious which parameters are read-only and not being
modified and allow callers to pass const pointers.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Add missing argument in usage message.
Drop redundant includes `optarg` and `optind`, which are declared in
<getopt.h>.
Mark file local functions static.
Drop unused function declaration.
Check closing file streams after writing, which can signal a failed
write or sync to disk and should be checked.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Add missing argument in usage message.
Drop redundant includes `optarg` and `optind`, which are declared in
<getopt.h>.
Use consistent quit style by using `exit(1)`.
Mark read-only options struct const.
Check closing file streams after writing, which can signal a failed
write or sync to disk and should be checked.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Make it more obvious which parameters are read-only and not being
modified and allow callers to pass const pointers.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
checkpolicy.c: In function ‘main’:
checkpolicy.c:1000:25: error: ‘tsid’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
1000 | printf("if_sid %d default_msg_sid %d\n", ssid, tsid);
| ^
checkpolicy.c: In function ‘main’:
checkpolicy.c:971:25: error: ‘tsid’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
971 | printf("fs_sid %d default_file_sid %d\n", ssid, tsid);
| ^
Found by GCC 11 with LTO enabled.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
policy_define.c: In function ‘define_te_avtab_extended_perms’:
policy_define.c:1946:17: error: potential null pointer dereference [-Werror=null-dereference]
1946 | r->omit = omit;
| ^
In the case of `r` being NULL, avrule_read_ioctls() would return
with its parameter `rangehead` being a pointer to NULL, which is
considered a failure in its caller `avrule_ioctl_ranges`.
So it is not necessary to alter the return value.
Found by GCC 11 with LTO enabled.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The variable `cladatum` is otherwise always assigned before used, so
these two assignments without a follow up usages are not needed.
Found by clang-analyzer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Follow the project style of no declaration after statement.
Found by the GCC warning -Wdeclaration-after-statement.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
test/dispol.c:288:4: warning: %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]
snprintf(buf, sizeof(buf), "unknown (%d)", i);
^
test/dismod.c:830:4: warning: %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]
snprintf(buf, sizeof(buf), "unknown (%d)", i);
^
Found by Cppcheck.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The variable `id` is guaranteed to be non-NULL due to the preceding
while condition.
policy_define.c:1171:7: style: Condition '!id' is always false [knownConditionTrueFalse]
if (!id) {
^
policy_define.c:1170:13: note: Assuming that condition 'id=queue_remove(id_queue)' is not redundant
while ((id = queue_remove(id_queue))) {
^
policy_define.c:1171:7: note: Condition '!id' is always false
if (!id) {
^
Found by Cppcheck.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
checkpolicy.c:504:20: style: The statement 'if (policyvers!=n) policyvers=n' is logically equivalent to 'policyvers=n'. [duplicateConditionalAssign]
if (policyvers != n)
^
checkpolicy.c:505:17: note: Assignment 'policyvers=n'
policyvers = n;
^
checkpolicy.c:504:20: note: Condition 'policyvers!=n' is redundant
if (policyvers != n)
^
Found by Cppcheck
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The compiler option -pipe does not affect the generated code; it affects
whether the compiler uses temporary files or pipes. As the benefit might
vary from system to system usually its up to the packager or build
framework to set it.
Also these are the only places where the flag is used.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Pass CFLAGS when invoking CC at link time, it might contain optimization
or sanitizer flags required for linking.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
checkpolicy.c:740:33: error: empty expression statement has no
effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
FGETS(ans, sizeof(ans), stdin);
^
Introduce "do { } while (0)" blocks to silence such warnings.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
When reading a binary policy, do not automatically change the version
to the max policy version supported by libsepol or, if specified, the
value given using the "-c" flag.
If the binary policy version is less than or equal to version 23
(POLICYDB_VERSION_PERMISSIVE) than do not automatically upgrade the
policy and if a policy version is specified by the "-c" flag, only set
the binary policy to the specified version if it is lower than the
current version.
If the binary policy version is greater than version 23 than it should
be set to the maximum version supported by libsepol or, if specified,
the value given by the "-c" flag.
The reason for this change is that policy versions 20
(POLICYDB_VERSION_AVTAB) to 23 have a more primitive support for type
attributes where the datums are not written out, but they exist in the
type_attr_map. This means that when the binary policy is read by
libsepol, there will be gaps in the type_val_to_struct and
p_type_val_to_name arrays and policy rules can refer to those gaps.
Certain libsepol functions like sepol_kernel_policydb_to_conf() and
sepol_kernel_policydb_to_cil() do not support this behavior and need
to be able to identify these policies. Policies before version 20 do not
support attributes at all and can be handled by all libsepol functions.
Signed-off-by: James Carter <jwcart2@gmail.com>
Roles in an optional block have two datums, one in the global block
and one in the avrule_decl where it is declared. The datum in the
global block does not have its dominace set. This is a problem because
the function set_user_role() sets the user's roles based on the global
datum's dominance ebitmap. If a user is declared with an associated role
that was declared in an optional block, then it will not have any roles
set for it because the dominance ebitmap is empty.
Example/
# handle_unknown deny
class CLASS1
sid kernel
class CLASS1 { PERM1 }
type TYPE1;
allow TYPE1 self:CLASS1 PERM1;
role ROLE1;
role ROLE1 types { TYPE1 };
optional {
require {
class CLASS1 { PERM1 };
}
role ROLE1A;
user USER1A roles ROLE1A;
}
user USER1 roles ROLE1;
sid kernel USER1:ROLE1:TYPE1
In this example, USER1A would not have ROLE1A associated with it.
Instead of using dominance, which has been deprecated anyway, just
set the bit corresponding to the role's value in the user's roles
ebitmap in set_user_role().
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
[N.I: added spaces around "-" operator]
When __cil_validate_constrain_expr() fails,
cil_constrain_to_policydb_helper() does not destroy the constraint
expression. This leads to a memory leak reported by OSS-Fuzz with the
following CIL policy:
(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))))
(constrain
(CLASS (PERM))
(or
(eq t1 TYPE)
(or
(eq t1 TYPE)
(or
(eq t1 TYPE)
(or
(eq t1 TYPE)
(or
(eq t1 TYPE)
(eq t1 TYPE)
)
)
)
)
)
)
Add constraint_expr_destroy(sepol_expr) to destroy the expression.
Moreover constraint_expr_destroy() was not freeing all items of an
expression. Code in libsepol/src and checkpolicy contained while loop to
free all the items of a constraint expression, but not the one in
libsepol/cil. As freeing only the first item of an expression is
misleading, change the semantic of constraint_expr_destroy() to iterate
the list of constraint_expr_t and to free all items.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28938
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Acked-by: James Carter <jwcart2@gmail.com>
When compiling SELinux userspace tools with -ftrapv (this option
generates traps for signed overflow on addition, subtraction,
multiplication operations, instead of silently wrapping around),
semodule crashes when running the tests from
scripts/ci/fedora-test-runner.sh in a Fedora 32 virtual machine:
[root@localhost selinux-testsuite]# make test
make -C policy load
make[1]: Entering directory '/root/selinux-testsuite/policy'
# Test for "expand-check = 0" in /etc/selinux/semanage.conf
# General policy build
make[2]: Entering directory '/root/selinux-testsuite/policy/test_policy'
Compiling targeted test_policy module
Creating targeted test_policy.pp policy package
rm tmp/test_policy.mod.fc
make[2]: Leaving directory '/root/selinux-testsuite/policy/test_policy'
# General policy load
domain_fd_use --> off
/usr/sbin/semodule -i test_policy/test_policy.pp test_mlsconstrain.cil test_overlay_defaultrange.cil test_add_levels.cil test_glblub.cil
make[1]: *** [Makefile:174: load] Aborted (core dumped)
Using "coredumpctl gdb" leads to the following strack trace:
(gdb) bt
#0 0x00007f608fe4fa25 in raise () from /lib64/libc.so.6
#1 0x00007f608fe38895 in abort () from /lib64/libc.so.6
#2 0x00007f6090028aca in __addvsi3.cold () from /lib64/libsepol.so.1
#3 0x00007f6090096f59 in __avrule_xperm_setrangebits (low=30, high=30, xperms=0x8b9eea0)
at ../cil/src/cil_binary.c:1551
#4 0x00007f60900970dd in __cil_permx_bitmap_to_sepol_xperms_list (xperms=0xb650a30, xperms_list=0x7ffce2653b18)
at ../cil/src/cil_binary.c:1596
#5 0x00007f6090097286 in __cil_avrulex_ioctl_to_policydb (k=0xb8ec200 "@\023\214\022\006", datum=0xb650a30,
args=0x239a640) at ../cil/src/cil_binary.c:1649
#6 0x00007f609003f1e5 in hashtab_map (h=0x41f8710, apply=0x7f60900971da <__cil_avrulex_ioctl_to_policydb>,
args=0x239a640) at hashtab.c:234
#7 0x00007f609009ea19 in cil_binary_create_allocated_pdb (db=0x2394f10, policydb=0x239a640)
at ../cil/src/cil_binary.c:4969
#8 0x00007f609009d19d in cil_binary_create (db=0x2394f10, policydb=0x7ffce2653d30) at ../cil/src/cil_binary.c:4329
#9 0x00007f609008ec23 in cil_build_policydb_create_pdb (db=0x2394f10, sepol_db=0x7ffce2653d30)
at ../cil/src/cil.c:631
#10 0x00007f608fff4bf3 in semanage_direct_commit () from /lib64/libsemanage.so.1
#11 0x00007f608fff9fae in semanage_commit () from /lib64/libsemanage.so.1
#12 0x0000000000403e2b in main (argc=7, argv=0x7ffce2655058) at semodule.c:753
(gdb) f 3
#3 0x00007f6090096f59 in __avrule_xperm_setrangebits (low=30, high=30, xperms=0x8b9eea0)
at ../cil/src/cil_binary.c:1551
1551 xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low);
A signed integer overflow therefore occurs in XPERM_SETBITS(h):
#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1)
This macro is expanded with h=31, so "(1 << 31) - 1" is computed:
* (1 << 31) = -0x80000000 is the lowest signed 32-bit integer value
* (1 << 31) - 1 overflows the capacity of a signed 32-bit integer and
results in 0x7fffffff (which is unsigned)
Using unsigned integers (with "1U") fixes the crash, as
(1U << 31) = 0x80000000U has no overflowing issues.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
In preparation to support a new policy format with a more optimal
representation of filename transition rules, this patch applies an
equivalent change from kernel commit c3a276111ea2 ("selinux: optimize
storage of filename transitions").
See the kernel commit's description [1] for the rationale behind this
representation. This change doesn't bring any measurable difference of
policy build performance (semodule -B) on Fedora.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git/commit/?id=c3a276111ea2572399281988b3129683e2a6b60b
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Spell Árpád’s name with the correct diacritics, put Olesya’s first name
in front of her last name.
Signed-off-by: Andrej Shadura <andrew.shadura@collabora.co.uk>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
policy_scan.l:294:3: warning: implicit declaration of function 'yyerror' is
invalid in C99 [-Wimplicit-function-declaration]
{ yyerror("unrecognized character");}
^
policy_scan.l:294:3: warning: this function declaration is not a prototype
[-Wstrict-prototypes]
Acked-by: William Roberts <william.c.roberts@intel.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
libsepol carried its own (outdated) copy of flask.h with the generated
security class and initial SID values for use by the policy
compiler and the forked copy of the security server code
leveraged by tools such as audit2why. Convert libsepol and
checkpolicy entirely to looking up class values from the policy,
remove the SECCLASS_* definitions from its flask.h header, and move
the header with its remaining initial SID definitions private to
libsepol. While we are here, fix the sepol_compute_sid() logic to
properly support features long since added to the policy and kernel,
although there are no users of it other than checkpolicy -d (debug)
and it is not exported to users of the shared library. There
are still some residual differences between the kernel logic and
libsepol.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: Petr Lautrbach <plautrba@redhat.com>
When the lexer encounters an unexpected character in a policy source file, it prints a warning, discards the character and moves on. In some build environments, these characters could be a symptom of an earlier problem, such as unintended results of expansion of preprocessor macros, and the ability to have the compiler halt on such issues would be helpful for diagnosis.
Signed-off-by: Daniel Burgener <Daniel.Burgener@microsoft.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Previously the behavior was to warn, discard the character and proceed.
Now the build will halt upon encountering an unexpected character.
Signed-off-by: Daniel Burgener <dburgener@linux.microsoft.com>
Acked-by: James Carter <jwcart2@gmail.com>
Remove restrictions in libsepol and checkpolicy that required all
declared initial SIDs to be assigned a context. With this patch,
it is possible to build and load a policy that drops the sid <sidname>
<context> declarations for the unused initial SIDs. It is still
required to retain the sid <sidname> declarations (in the flask
definitions) in order to preserve the initial SID ordering/values.
The unused initial SIDs can be renamed, e.g. to add an unused_
prefix or similar, if desired, since the names used in the policy
are not stored in the kernel binary policy.
In CIL policies, the (sid ...) and (sidorder (...)) statements
must be left intact for compatibility but the (sidcontext ...)
statements for the unused initial SIDs can be omitted after this change.
With current kernels, if one removes an unused initial SID context
from policy, builds policy with this change applied and loads the
policy into the kernel, cat /sys/fs/selinux/initial_contexts/<sidname>
will show the unlabeled context. With the kernel patch to remove unused
initial SIDs, the /sys/fs/selinux/initial_contexts/<sidname>
file will not be created for unused initial SIDs in the first place.
NB If an unused initial SID was assigned a context different from
the unlabeled context in existing policy, then it is not safe to
remove that initial SID context from policy and reload policy on
the running kernel that was booted with the original policy. This
is because that kernel may have assigned that SID to various kernel
objects already and those objects will then be treated as having
the unlabeled context after the removal. In refpolicy, examples
of such initial SIDs are the "fs" SID and the "sysctl" SID. Even
though these initial SIDs are not directly used (in code) by the current
kernel, their contexts are being applied to filesystems and sysctl files by
policy and therefore the SIDs are being assigned to objects.
NB The "sysctl" SID was in use by the kernel up until
commit 8e6c96935fcc1ed3dbebc96fddfef3f2f2395afc ("security/selinux:
fix /proc/sys/ labeling) circa v2.6.39. Removing its context from
policy will cause sysctl(2) or /proc/sys accesses to end up
performing permission checks against the unlabeled context and
likely encounter denials for kernels < 2.6.39.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
This variable is declared in a header file, but never defined or used.
The te_assert structure definition is only used in this declaration, so
remove both.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
If - is given as filename for -o option, checkpolicy
writes the policy to standard output. This helps users
to read policy.conf and/or CIL policy file with pager
like less command:
$ checkpolicy -M -F -b /sys/fs/selinux/policy -o - | less
The users don't have to make a temporary file.
/dev/stdout can be used instead. However, - reduces the number of
typing for the purpose. Using - for standard output (and/or standard
input) is popular convention.
Change(s) in v2:
* Check the availability of output stream only when opening
a regualar file. Suggested by Stephen Smalley <sds@tycho.nsa.gov>.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Inner if-condition in following code is redundant:
if (outfile) {
/* ... just referring outfile ... */
if (outfile) {
do_something();
}
}
We can simplify this to:
if (outfile) {
/* ... just referring outfile ... */
do_something();
}
Signed-off-by: Masatake YAMATO <yamato@redhat.com>