The function __cil_verify_rule() is currently not used as all call sites
are commented out. Keep the function for future references.
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
checkpolicy(8) since 01b88ac3 ("checkpolicy: warn on bogus IP address or
netmask in nodecon statement") warns about host bits set in IPv6
addresses.
Adjust IPv6 netmasks in the libsepol tests so that the used address ::1
does not set any host bits and running the tests does not print several
of the following warnings:
net_contexts:15:WARNING 'host bits in ipv6 address set' at token '' on line 594:
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Since test-linker-cond-map.h and test-linker-types.h references
policydb_t, include the policydb header file.
Signed-off-by: James Carter <jwcart2@gmail.com>
`hashtab_search()` takes a const_hashtab_key_t, alias `const char*` as
second key parameter type. Do not unnecessarily cast variables of type
`const char*` to hashtab_key_t, alias `char*`.
policydb.c: In function ‘policydb_string_to_security_class’:
policydb.c:4164:39: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual]
4164 | (hashtab_key_t) class_name);
| ^
policydb.c: In function ‘policydb_string_to_av_perm’:
policydb.c:4184:25: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual]
4184 | (hashtab_key_t)perm_name);
| ^
policydb.c:4193:25: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual]
4193 | (hashtab_key_t)perm_name);
| ^
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Check the actual pointer which memory was assigned to, not its parent
array pointer.
services.c:810:14: warning: Assigned value is garbage or undefined [core.uninitialized.Assign]
**r_buf = **new_buf;
^ ~~~~~~~~~
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Since calloc() will return an error if nmemb * size would overflow,
just use it instead of mallocarray(). This also allows code that
initializes the array to zero to be removed.
Signed-off-by: James Carter <jwcart2@gmail.com>
Export functions needed for converting security identifiers from and to
strings and functions computing security server decisions. These can
be used to debug or run tests on binary policies without running on a
SELinux enabled kernel.
TODO:
These functions have currently a non consistent return behavior: some
are returning -1 on failure and set errno most but not all of the time,
some return a negative errno like value.
Maybe this should be addressed before exporting them?
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The typedef `sepol_security_context_t` is used for contexts. For the
read-only input parameter in `sepol_context_to_sid()`
`const sepol_security_context_t` is used as type, which does not expand
to the expected `const char*` but `char *const`.
Introduce a corresponding typedef for `const char*`.
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Add a wrapper around the utility function sepol_av_to_string() on the
service internal policy. This allows callers to convert a permission
bit set into a string representation without access to the internal
policy structure.
Acked-by: James Carter <jwcart2@gmail.com>
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
It seems to be unused since its initial addition in 76ba6eaa
("Squashed 'libsepol/cil/' changes from 08520e9..28ad56e").
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.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>
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>
Acked-by: James Carter <jwcart2@gmail.com>
Check return values of memory allocation functions and propagate their
failure.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
GCC 12 produces an array-bounds warning:
In file included from ../include/sepol/policydb/context.h:23,
from ../include/sepol/policydb/policydb.h:62,
from ../cil/src/cil_binary.c:41:
In function ‘mls_level_init’,
inlined from ‘mls_level_destroy’ at ../include/sepol/policydb/mls_types.h:99:2,
inlined from ‘mls_level_destroy’ at ../include/sepol/policydb/mls_types.h:92:20,
inlined from ‘mls_range_destroy’ at ../include/sepol/policydb/mls_types.h:149:2,
inlined from ‘cil_rangetransition_to_policydb’ at ../cil/src/cil_binary.c:3231:6:
../include/sepol/policydb/mls_types.h:89:9: error: ‘memset’ offset [0, 23] is out of the bounds [0, 0] [-Werror=array-bounds]
89 | memset(level, 0, sizeof(mls_level_t));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../include/sepol/policydb/mls_types.h:89:9: error: ‘memset’ offset [0, 23] is out of the bounds [0, 0] [-Werror=array-bounds]
cc1: all warnings being treated as errors
This is a false positive, by inspecting the code and compiling with -O3
and -flto.
Closes: https://github.com/SELinuxProject/selinux/issues/339
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
When validating a policydb, validate the conditional expressions
including the values of the booleans within them.
Found by oss-fuzz (#45523)
Signed-off-by: James Carter <jwcart2@gmail.com>
Use calloc() instead of mallocarray() so that everything is
initialized to zero to prevent the use of unitialized memory when
validating malformed binary policies.
Found by oss-fuzz (#45493)
Signed-off-by: James Carter <jwcart2@gmail.com>
The MAX_LOG_SIZE is 512. It is possible that a log message could
exceed the max size (such as for neverallowx rules). If so, then
write out "<LOG MESSAGE TRUNCATED>", so that it is obvious that
the log message has been truncated.
Reported-by: Jonathan Hettwer <j2468h@googlemail.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
When writing a conf file or CIL policy out from a kernel binary,
do not write out a constraint rule if it has no permissions.
Signed-off-by: James Carter <jwcart2@gmail.com>
Since CIL allows permission expressions, it is possible for the
expression to evaluate to no permissions. If this is the case,
then don't add the constraint.
Signed-off-by: James Carter <jwcart2@gmail.com>
Shorten "CAPABILITY" to "CAP" following the kernel naming convention.
The SELinux policy capability enum names should now follow the
"POLICYDB_CAP_XXX" format.
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
Acked-by: James Carter <jwcart2@gmail.com>
Extended permission and neverallow rules are not permitted in
conditional statements.
This causes issues on policy optimization where avtab_search() might
return a non extended permission rule when searching for one.
Found by oss-fuzz (#45327)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
When validating a policydb, do a more thorough validation of the
constraints.
- No permissions if it is a (mls)validatetrans.
- Only mlsvalidatetrans can use u3, r3, and t3.
- Expressions not involving types should have an empty type set.
- Only "==" and "!=" are allowed when there are names.
- If names are not used in an expression then both the names bitmap
and the type set should be empty.
- Only roles and mls expressions can used "dom", "domby", and "incomp".
- An mls expression cannot use names.
- If the expression is "not", "and", or "or", then the names bitmap
and the type set should be empty.
Signed-off-by: James Carter <jwcart2@gmail.com>
In f0a5f6e, calls to reallocarray were introduced. Ensure that the
correct header (private.h) is included when necessary.
Fixes: f0a5f6e ("libsepol: use reallocarray wrapper to avoid overflows")
Signed-off-by: Thiébaud Weksteen <tweek@google.com>
Acked-by: James Carter <jwcart2@gmail.com>
Test: Built using Android CI (glibc 2.17)
On the first loop iteration the variables `r_buf` and `reason_buf_used`
are NULL respective 0. Please UBSAN by not adding them but instead
directly assign NULL.
services.c:800:16: runtime error: applying zero offset to null pointer
#0 0x4d4fce in constraint_expr_eval_reason ./libsepol/src/services.c:800:16
#1 0x4cf31a in sepol_validate_transition_reason_buffer ./libsepol/src/services.c:1079:8
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
When an assertion fails, the error message refers to a generic
"policy.conf" file. When parsing a policy in checkpolicy, populate its
name using the original filename (source_filename is still build using
the #line directives within the policy).
Signed-off-by: Thiébaud Weksteen <tweek@google.com>
[Merge conflicts fixed by: James Carter <jwcart2@gmail.com>]
Signed-off-by: James Carter <jwcart2@gmail.com>
When there are conflicting context rules, the location of the
conflicting rules are written out. If there are many duplicates of
the same context rule, there will be many pairs of conflicts written
out. This hides the fact that all of the rules are the same and can
make it hard to see the different conflicts.
First, since these are warnings and not reported at the default log
verbosity level (which only reports errors), only search for the
locations of the conflicting rules when the verbosity level means
that the warnings will actually be reported.
Second, Report all the duplicate conflicting rules together.
Third, Report the first four conflicts of the same rule if when
the verbosity level is at CIL_WARN ("-v") and report all of them
when the verbosity level is at CIL_INFO or higher ("-v -v").
Fixes problem found by oss-fuzz (#39735)
Signed-off-by: James Carter <jwcart2@gmail.com>
When there is a neverallow violation, a search is made for all of
the rules that violate the neverallow. The violating rules as well
as their parents are written out to make it easier to find these
rules.
If there is a lot of rules that violate a neverallow, then this
amount of reporting is too much. Instead, only print out the first
four rules (with their parents) that match the violated neverallow
rule along with the total number of rules that violate the
neverallow at the default log level. Report all the violations when
at a higher verbosity level.
Signed-off-by: James Carter <jwcart2@gmail.com>
Commit 4b2e2a248e (libsepol/cil: Limit
the amount of reporting for bounds failures) limited the number of
bounds failures that were reported to the first two matching rules
for the first two bad rules.
Instead, report the first two matching rules for the first four bad
rules at the default log level and report all matching rules for all
bad rules for higher verbosity levels.
Signed-off-by: James Carter <jwcart2@gmail.com>
Not all violations of neverallowxperm rules were being reported.
In check_assertion_extended_permissions_avtab(), a break was
performed after finding a match rather than just returning right
away. This means that if other src and tgt pairs were checked
afterward that did not match, then no match would be reported.
Example:
allow attr attr:CLASS ioctl;
allowxperm attr attr:CLASS ioctl 0x9401;
allowxperm t1 self:CLASS ioctl 0x9421;
neverallowxperm attr self:CLASS ioctl 0x9421;
Would result in no assertion violations being found.
Another problem was that the reporting function did not properly
recognize when there was a valid allowxperm rule and falsely
reported additional violations that did not exist. (There had
to be at least one legitimate violation.)
Using the same example as above (and assuming t1 and t2 both have
attribute attr), the following would be reported as:
neverallowxperm on line 4 of policy.conf (or line 4 of policy.conf)
violated by
allowxperm t1 t1:CLASS ioctl { 0x9421 };
neverallowxperm on line 4 of policy.conf (or line 4 of policy.conf)
violated by
allow t2 t2:CLASS4 { ioctl };
There is no violation for t2 because there is a valid allowxperm
rule for it.
With this patch, only the first error message (which is the correct
one) is printed.
Signed-off-by: James Carter <jwcart2@gmail.com>
The changes are the same as in a patch sent by Christian Göttsche
<cgzones@googlemail.com> to support adding not-self to neverallowxperm
checking, but it is needed for normal neverallowxperm checking as well
and the following explanation reflects that.
When reporting neverallowxperm violations, the avtab is searched to
find the rule that violates the assertion. If the avtab pointer of
the args is not set, then it will report the error as if no extended
permissions existed for the source and target (so allowing the ioctl
permission at all violates the neverallowxperm).
Example (where t1 has attribute attr):
allow attr attr:CLASS ioctl;
allowxperm attr attr:CLASS ioctl 0x9411;
neverallowxperm t1 self:CLASS ioctl 0x9411;
Would be reported as:
neverallowxperm on line 3 of policy.conf (or line 3 of policy.conf)
violated by
allow t1 t1:CLASS { ioctl };
Instead of:
neverallowxperm on line 3 of policy.conf (or line 3 of policy.conf)
violated by
allowxperm attr attr:CLASS ioctl { 0x9411 };
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: James Carter <jwcart2@gmail.com>
When checking for violations of neverallow rules, if the neverallow
uses self, then the src and tgt must be the same when checking
extended permissions and when reporting violations.
Example:
allow attr attr : CLASS PERM;
neverallow attr self : CLASS PERM;
If the types t1 and t2 have attribute attr, then the violations
that would be reported would be:
allow t1 t1 : CLASS PERM;
allow t1 t2 : CLASS PERM;
allow t2 t1 : CLASS PERM;
allow t2 t2 : CLASS PERM;
instead of:
allow t1 t1 : CLASS PERM;
allow t2 t2 : CLASS PERM;
Signed-off-by: James Carter <jwcart2@gmail.com>
The value returned from report_assertion_extended_permissions() is
the nubmer of errors, so call it that instead of ret.
Signed-off-by: James Carter <jwcart2@gmail.com>
In both check_assertion_extended_permissions() and
report_assertion_avtab_matches(), when checking for a match involving
a rule using self, the matches between the source and target of the
rule being checked are found using ebitmap_and() and then the matches
between that result and the source of the neverallow are found using
another ebitmap_and() call.
Since the matches between the sources of the rule being checked and
the neverallow have already been found, just find the matches between
that result and the target of the rule being checked. This only
requires one call to ebitmap_and() instead of two.
Signed-off-by: James Carter <jwcart2@gmail.com>
When check_assertion_extended_permissions() is called, it has already
been determined that there is a match, and, since neither the class
nor the permissions are used, there is no need for the check.
Signed-off-by: James Carter <jwcart2@gmail.com>
Inorder to differentiate errors from matches, use "(rc < 0)" when
calling ebitmap_* functions while checking neverallow rules.
Also, just use rc instead of having a separate variable (ret) in
check_assertion_extended_permissions().
Signed-off-by: James Carter <jwcart2@gmail.com>
If a neverallow has target types as well as using self and a match
is found with the target types, then self does not even need to
be checked, since the rule is already in violation of the assertion.
So move the check for a match of the target types before dealing with
self.
Signed-off-by: James Carter <jwcart2@gmail.com>
In check_assertion_avtab_match(), for the functions that do not return
an error, but only returns 0 or 1 depending on if a match is found,
call the function in an if statement.
Signed-off-by: James Carter <jwcart2@gmail.com>
Return an error if check_assertion_extended_permissions() returns
an error instead of treating it as an assertion violation.
Signed-off-by: James Carter <jwcart2@gmail.com>
An out of memory condition is unlikely and the general message
that an error occured while checking neverallows is sufficient.
Signed-off-by: James Carter <jwcart2@gmail.com>
Instead of calling report_assertion_failures() and treating an
error like it was a neverallow violation, just return an error.
Signed-off-by: James Carter <jwcart2@gmail.com>
Check the type for type and role sets is valid.
Check the scope of a scope datum is valid.
Check the flavor and flags of a type datum are valid.
Check xperms are set if and only if it is an extended permission avrule.
Check xperms has a valid specified field.
Check the flag of avrule blocks is valid.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Check the permission bitset in normal constraints is not empty and has
no invalid bits set.
Check the names and type_names members are empty in case they are not
used.
Check the operator and attribute type are not set for simple expression
types.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The callback function apply in hashtap_map has a return type of int and
can return -1 on error. Use int as type to save the return value to
avoid implicit conversions:
hashtab.c:236:10: runtime error: implicit conversion from type 'int' of value -1 (32-bit, signed) to type 'unsigned int' changed the value to 4294967295 (32-bit, unsigned)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Map classes use the same struct as kernel classes, but only the kernel
class uses the pointer to a common class. When resolving a classcommon,
make sure that the class that is found is a kernel class and not a
map class. If not, then return an error.
Found by oss-fuzz (#43209)
Signed-off-by: James Carter <jwcart2@gmail.com>
Since abstract blocks will not appear in the final policy, do not
resolve names to a declaration inside one.
When resolving blockabstract rules, they must be collected in a list
and processed at the end of the pass because if a parent block is
marked as abstract, then a blockabstract rule for a sub-block will
fail to resolve.
Found by oss-fuzz (#42981)
Signed-off-by: James Carter <jwcart2@gmail.com>
If a block is marked as abstract, then it will be skipped during
every pass after blockabstracts are resolved (only tunables,
in-befores, and blockinherits are before blockabstracts), so mark
all of its sub-blocks as abstract to reflect their actual status.
Signed-off-by: James Carter <jwcart2@gmail.com>
Do not copy any blockabstract statements when copying a block to
resolve a blockinherit statement. Inheriting a block from what was
just inherited does not work, so there is no reason to create an
abstract block.
Signed-off-by: James Carter <jwcart2@gmail.com>
When converting an ebitmap into a string list, skip potential gaps in
ebitmap_to_strs(). All converting functions like strs_to_str(),
strs_write_each() and strs_write_each_indented() do already skip NULL
elements, but sorting such a list will lead to a NULL dereference.
#0 0x432ce5 in strcmp /src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc:462:25
#1 0x4f4893 in strs_cmp selinux/libsepol/src/kernel_to_common.c:258:9
#2 0x47b74b in qsort_r /src/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc:9994:7
#3 0x4f481d in strs_sort selinux/libsepol/src/kernel_to_common.c:266:2
#4 0x4fe781 in attrmap_to_str selinux/libsepol/src/kernel_to_conf.c:1560:2
#5 0x4fe781 in write_type_attribute_sets_to_conf selinux/libsepol/src/kernel_to_conf.c:1599:11
#6 0x4f8098 in sepol_kernel_policydb_to_conf selinux/libsepol/src/kernel_to_conf.c:3182:7
#7 0x4e0277 in LLVMFuzzerTestOneInput selinux/libsepol/fuzz/binpolicy-fuzzer.c:50:9
#8 0x4d613b in main
#9 0x7fa2d50260b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/libc-start.c:308:16
#10 0x41d4ed in _start
Found by oss-fuzz (#44170)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The length of an ebitmap is the current highest allocated (not set) bit
and always a multiple of MAPTYPE (= 64). The role ebitmap should only
have valid role bits set, even after inverting. The length might be
smaller than the maximum number of defined roles leading to non defined
role bits set afterwards.
Only invert up to the number of roles defined instead the full ebitmap
length, similar to type_set_expand().
This also avoids timeouts on an invalid huge highbit set, since the
ebitmap has not been validated yet, on which inverting will take
excessive amount of memory and time, found by oss-fuzz (#43709).
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
For policy versions between 20 and 23 the type_val_to_struct array might
contain gaps. Skip those gaps to avoid NULL pointer dereferences:
==1250==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x00000058560b bp 0x7ffdca60c110 sp 0x7ffdca60bfc0 T0)
==1250==The signal is caused by a READ memory access.
==1250==Hint: address points to the zero page.
#0 0x58560b in build_type_map selinux/libsepol/src/optimize.c:107:33
#1 0x58560b in policydb_optimize selinux/libsepol/src/optimize.c:441:13
#2 0x55e63e in LLVMFuzzerTestOneInput selinux/libsepol/fuzz/binpolicy-fuzzer.c:42:10
#3 0x455283 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) cxa_noexception.cpp:0
#4 0x440ec2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
#5 0x44671c in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) cxa_noexception.cpp:0
#6 0x46f522 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#7 0x7f9c160d00b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/libc-start.c:308:16
#8 0x41f67d in _start
Found by oss-fuzz (#42697)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The default log handler sepol_msg_default_handler() appends a newline
and the majority of log messages do not contain a trailing newline in
the format string.
Fixes: 5c178f9f55 ("libsepol: use logging framework in conditional.c")
Fixes: 852f14d43d ("libsepol: use logging framework in ebitmap.c")
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Do not return success if the class name length is saturated (or too big
in the fuzzer build).
Fixes: c3d52a6a ("libsepol: check for saturated class name length")
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Check the from the polciy read length value to guard allocations.
In the fuzzer build the value will also be bounded to avoid oom reports.
==143646==ERROR: AddressSanitizer: allocator is out of memory trying to allocate 0xd60000000 bytes
#0 0x4dac18 in __interceptor_calloc (./out/binpolicy-fuzzer+0x4dac18)
#1 0x55d388 in scope_index_read ./libsepol/src/policydb.c:3945:7
#2 0x550097 in avrule_decl_read ./libsepol/src/policydb.c:3984:6
#3 0x550097 in avrule_block_read ./libsepol/src/policydb.c:4044:8
#4 0x54b3ac in policydb_read ./libsepol/src/policydb.c:4456:7
#5 0x518fd9 in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:35:6
#6 0x43f623 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (./out/binpolicy-fuzzer+0x43f623)
#7 0x42910f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (./out/binpolicy-fuzzer+0x42910f)
#8 0x42ee76 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (./out/binpolicy-fuzzer+0x42ee76)
#9 0x458ff2 in main (./out/binpolicy-fuzzer+0x458ff2)
#10 0x7fd37b7931c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
Found by oss-fuzz (#42909)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Check the sensitivity is valid and thus the lookup in the name array
`p_sens_val_to_name` is valid.
Found by oss-fuzz (#42729, #42730, #42735, #42741)
==54784==The signal is caused by a READ memory access.
#0 0x5a10f3 in mls_semantic_level_expand ./selinux/libsepol/src/expand.c:934:11
#1 0x53839e in policydb_user_cache ./selinux/libsepol/src/policydb.c:972:7
#2 0x5c6325 in hashtab_map ./selinux/libsepol/src/hashtab.c:236:10
#3 0x5392e9 in policydb_index_others ./selinux/libsepol/src/policydb.c:1274:6
#4 0x53f90a in policydb_read ./selinux/libsepol/src/policydb.c:4496:6
#5 0x50c679 in LLVMFuzzerTestOneInput ./selinux/libsepol/fuzz/binpolicy-fuzzer.c:35:6
#6 0x4409e3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (./selinux/out/binpolicy-fuzzer+0x4409e3)
#7 0x4295bf in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (./selinux/out/binpolicy-fuzzer+0x4295bf)
#8 0x42f850 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (./selinux/out/binpolicy-fuzzer+0x42f850)
#9 0x45b6d2 in main (./selinux/out/binpolicy-fuzzer+0x45b6d2)
#10 0x7f059fcd71c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#11 0x7f059fcd7277 in __libc_start_main csu/../csu/libc-start.c:409:3
#12 0x423900 in _start (./out/binpolicy-fuzzer+0x423900)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Do not continue with a negative return value once a string append
operation fails to avoid increasing the buffer length variable
`str_len`, potentially leading to an out-of-bounds write.
Found by GitHub CodeQL.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Followed the following steps:
# aosp mirror does not have the upstream tags. Manually mark the
# 3.3 release. See
# https://github.com/SELinuxProject/selinux/releases/tag/3.3
git tag 3.3 7f600c40bc
repo start update_3_3 .
git merge 3.3 --no-ff # No merge conflicts were found.
lunch && m
repo upload .
Bug: 37755687
Test: Build aosp_bramble-userdebug and manually compare the generated
/{system,vendor,product}/etc/selinux* files with their previous
versions. All are identical.
Change-Id: I6a514d7db9a752c44cc61d343f7c1a60f750f317
Check the class default targets are valid values, e.g. source or target
for user, role and type.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Check all categories have valid values, especially important for
aliases.
==7888==ERROR: AddressSanitizer: SEGV on unknown address 0x602000400710 (pc 0x00000055debc bp 0x7ffe0ff2a9d0 sp 0x7ffe0ff2a8e0 T0)
==7888==The signal is caused by a READ memory access.
#0 0x55debc in write_category_rules_to_conf ./libsepol/src/kernel_to_conf.c:946:9
#1 0x55debc in write_mls_rules_to_conf ./libsepol/src/kernel_to_conf.c:1137:7
#2 0x55adb1 in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3106:7
#3 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:37:9
#4 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#5 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#6 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#7 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#8 0x7fe80ccaf7ec in __libc_start_main csu/../csu/libc-start.c:332:16
#9 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Check the literal contexts in ocontext statements are defined.
==91274==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f60b0afe8c6 bp 0x7ffd42edc990 sp 0x7ffd42edc148 T0)
==91274==The signal is caused by a READ memory access.
==91274==Hint: address points to the zero page.
#0 0x7f60b0afe8c6 string/../sysdeps/x86_64/multiarch/../strlen.S:120
#1 0x4bd128 in __interceptor_strlen (./out/binpolicy-fuzzer+0x4bd128)
#2 0x5eb387 in create_str_helper ./libsepol/src/kernel_to_common.c:69:10
#3 0x5eb11e in create_str ./libsepol/src/kernel_to_common.c:99:8
#4 0x56ad7b in context_to_str ./libsepol/src/kernel_to_conf.c:2408:9
#5 0x56a717 in write_sid_context_rules_to_conf ./libsepol/src/kernel_to_conf.c:2441:9
#6 0x55b26c in write_selinux_isid_rules_to_conf ./libsepol/src/kernel_to_conf.c:2476:9
#7 0x55b26c in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3206:8
#8 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9
#9 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#10 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#11 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#12 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#13 0x7f60b0a887ec in __libc_start_main csu/../csu/libc-start.c:332:16
#14 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
==80903==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000005c0 at pc 0x0000005696c8 bp 0x7ffdb11ea560 sp 0x7ffdb11ea558
READ of size 8 at 0x6020000005c0 thread T0
#0 0x5696c7 in avtab_node_to_str ./libsepol/src/kernel_to_conf.c:1736:9
#1 0x569013 in map_avtab_write_helper ./libsepol/src/kernel_to_conf.c:1767:10
#2 0x5ab837 in avtab_map ./libsepol/src/avtab.c:347:10
#3 0x561f9a in write_avtab_flavor_to_conf ./libsepol/src/kernel_to_conf.c:1798:7
#4 0x561f9a in write_avtab_to_conf ./libsepol/src/kernel_to_conf.c:1819:8
#5 0x55afba in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3159:7
#6 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9
#7 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#8 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#9 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#10 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#11 0x7f97a83fd7ec in __libc_start_main csu/../csu/libc-start.c:332:16
#12 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Check a common class or a class together with its common class parent
does not have more than the supported 32 permissions.
==28413==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f74ec3341a3 bp 0x7ffd0b7e5030 sp 0x7ffd0b7e47e8 T0)
==28413==The signal is caused by a READ memory access.
==28413==Hint: address points to the zero page.
#0 0x7f74ec3341a3 string/../sysdeps/x86_64/multiarch/../strchr.S:32
#1 0x4bfc78 in strchr (./out/binpolicy-fuzzer+0x4bfc78)
#2 0x55b7f2 in class_constraint_rules_to_strs ./libsepol/src/kernel_to_conf.c:288:7
#3 0x55b7f2 in constraint_rules_to_strs ./libsepol/src/kernel_to_conf.c:364:9
#4 0x55ac80 in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3071:7
#5 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9
#6 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#7 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#8 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#9 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#10 0x7f74ec2be7ec in __libc_start_main csu/../csu/libc-start.c:332:16
#11 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Check those contains valid values.
==57532==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000001178 at pc 0x000000564c04 bp 0x7ffed7a5ad90 sp 0x7ffed7a5ad88
READ of size 8 at 0x603000001178 thread T0
#0 0x564c03 in level_to_str ./libsepol/src/kernel_to_conf.c:1901:19
#1 0x564c03 in range_to_str ./libsepol/src/kernel_to_conf.c:1926:9
#2 0x564c03 in write_user_decl_rules_to_conf ./libsepol/src/kernel_to_conf.c:2367:12
#3 0x55b137 in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3184:7
#4 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9
#5 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#6 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#7 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#8 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#9 0x7f2c2e1a77ec in __libc_start_main csu/../csu/libc-start.c:332:16
#10 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Validate the level map of the policy to ensure no level refers to a non
existent category.
READ of size 8 at 0x602000000c58 thread T0
#0 0x568d2c in cats_ebitmap_len ./libsepol/src/kernel_to_conf.c:1003:14
#1 0x568d2c in cats_ebitmap_to_str ./libsepol/src/kernel_to_conf.c:1038:19
#2 0x55e371 in write_level_rules_to_conf ./libsepol/src/kernel_to_conf.c:1106:11
#3 0x55e371 in write_mls_rules_to_conf ./libsepol/src/kernel_to_conf.c:1140:7
#4 0x55adb1 in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3103:7
#5 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9
#6 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#7 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#8 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#9 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#10 0x7f741d0d67ec in __libc_start_main csu/../csu/libc-start.c:332:16
#11 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Split the validation of array datums regarding their gaps and entries to
simplify further checking of common classes, booleans, levels and
categories.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Currently is it implementation defined, due to the size being passed to
calloc(3), whether the operations fails nor not.
Also strs_add() does not handle a size of zero, cause it just multiplies
the size by two.
Use a default size of 1 if 0 is passed and swap the calloc arguments for
consistency.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Use the number of categories not levels, which might be zero, for the
string list initial size of categories.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Handle gaps in the user table while printing a policy configuration.
==24424==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x0000004bdc55 bp 0x7ffc8790b810 sp 0x7ffc8790afb0 T0)
==24424==The signal is caused by a READ memory access.
==24424==Hint: address points to the zero page.
#0 0x4bdc55 in __interceptor_strcmp (./out/binpolicy-fuzzer+0x4bdc55)
#1 0x5ebdf6 in strs_cmp ./libsepol/src/kernel_to_common.c:253:9
#2 0x505669 in __interceptor_qsort (./out/binpolicy-fuzzer+0x505669)
#3 0x5ebd84 in strs_sort ./libsepol/src/kernel_to_common.c:261:2
#4 0x564550 in write_user_decl_rules_to_conf ./libsepol/src/kernel_to_conf.c:2333:2
#5 0x55b137 in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3190:7
#6 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9
#7 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#8 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#9 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#10 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#11 0x7f530128d7ec in __libc_start_main csu/../csu/libc-start.c:332:16
#12 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Handle gaps in the class table while printing a policy configuration.
==21763==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000028 (pc 0x00000055b696 bp 0x7ffe69e8ab50 sp 0x7ffe69e8aa60 T0)
==21763==The signal is caused by a READ memory access.
==21763==Hint: address points to the zero page.
#0 0x55b696 in constraint_rules_to_strs ./libsepol/src/kernel_to_conf.c:361:14
#1 0x55ac80 in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3063:7
#2 0x55a34f in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:38:9
#3 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#4 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#5 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#6 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#7 0x7fc60d39e7ec in __libc_start_main csu/../csu/libc-start.c:332:16
#8 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Handle format arguments that do not have a size of at least 2.
kernel_to_common.c:69:20: runtime error: unsigned integer overflow: 1 - 2 cannot be represented in type 'unsigned long'
#0 0x557b0b in create_str_helper ./libsepol/src/kernel_to_common.c:69:20
#1 0x5577b8 in create_str ./libsepol/src/kernel_to_common.c:99:8
#2 0x56448c in cond_expr_to_str ./libsepol/src/kernel_to_conf.c:82:15
#3 0x56448c in write_cond_nodes_to_conf ./libsepol/src/kernel_to_conf.c:2103:10
#4 0x55bd9b in sepol_kernel_policydb_to_conf ./libsepol/src/kernel_to_conf.c:3171:7
#5 0x4f9d79 in main ./checkpolicy/checkpolicy.c:684:11
#6 0x7fe2a342b7ec in __libc_start_main csu/../csu/libc-start.c:332:16
#7 0x41f3a9 in _start (./checkpolicy/checkpolicy+0x41f3a9)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The `next` member might be checked against NULL and dereferenced before
it gets assigned, due to jumps from failure gotos to the cleanup
section.
==31017==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x000000579654 bp 0x7ffd3a07d110 sp 0x7ffd3a07d000 T0)
==31017==The signal is caused by a READ memory access.
==31017==Hint: this fault was caused by a dereference of a high value address (see register values below). Disassemble the provided pc to learn which register was used.
#0 0x579654 in filename_trans_read_one ./libsepol/src/policydb.c:2874:55
#1 0x579654 in filename_trans_read ./libsepol/src/policydb.c:2902:9
#2 0x5771b7 in policydb_read ./libsepol/src/policydb.c:4509:7
#3 0x55a1f5 in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:24:6
#4 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#5 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#6 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#7 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#8 0x7f2a4e7f97ec in __libc_start_main csu/../csu/libc-start.c:332:16
#9 0x423689 in _start (./out/binpolicy-fuzzer+0x423689)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Free the local access vector list on failure as it does not get moved
into the policy structure.
Drop the now redundant, but non-exhaustive, resource cleanup in
cond_insertf().
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x52596d in malloc (./out/binpolicy-fuzzer+0x52596d)
#1 0x5b30d2 in cond_insertf ./libsepol/src/conditional.c:682:9
#2 0x5ac218 in avtab_read_item ./libsepol/src/avtab.c:583:10
#3 0x5b21f4 in cond_read_av_list ./libsepol/src/conditional.c:725:8
#4 0x5b21f4 in cond_read_node ./libsepol/src/conditional.c:798:7
#5 0x5b21f4 in cond_read_list ./libsepol/src/conditional.c:847:7
#6 0x576b6e in policydb_read ./libsepol/src/policydb.c:4436:8
#7 0x55a1fe in LLVMFuzzerTestOneInput ./libsepol/fuzz/binpolicy-fuzzer.c:24:6
#8 0x45aed3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) fuzzer.o
#9 0x446a12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) fuzzer.o
#10 0x44c93b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) fuzzer.o
#11 0x475dd2 in main (./out/binpolicy-fuzzer+0x475dd2)
#12 0x7f47abeb87ec in __libc_start_main csu/../csu/libc-start.c:332:16
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>