aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-09 20:36:48 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-09 20:36:48 +0000
commit878624af253f6f226308435911426d62c8b805d6 (patch)
tree0ac5f8b919be8431992c69321948d13fdee3ccc6
parent39cdd123e53e5756a6b8be6b43fef5f101d76135 (diff)
parentef81cc4b54ee7ab1834e7b47d68abaedd11d28aa (diff)
downloadselinux-android13-mainline-media-release.tar.gz
Change-Id: Ibe1f0e072c3ca9e846825a818ea6f0c9146100e7
-rw-r--r--.circleci/config.yml2
-rw-r--r--.github/workflows/cifuzz.yml40
-rw-r--r--.github/workflows/run_tests.yml199
-rw-r--r--.github/workflows/vm_testsuite.yml23
-rw-r--r--.travis.yml158
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--Makefile4
-rw-r--r--OWNERS2
-rw-r--r--README25
-rw-r--r--README.md146
-rw-r--r--VERSION1
-rw-r--r--checkpolicy/Makefile6
-rw-r--r--checkpolicy/VERSION2
-rw-r--r--checkpolicy/checkmodule.816
-rw-r--r--checkpolicy/checkmodule.c33
-rw-r--r--checkpolicy/checkpolicy.813
-rw-r--r--checkpolicy/checkpolicy.c93
-rw-r--r--checkpolicy/module_compiler.c37
-rw-r--r--checkpolicy/module_compiler.h4
-rw-r--r--checkpolicy/parse_util.c4
-rw-r--r--checkpolicy/policy_define.c283
-rw-r--r--checkpolicy/policy_parse.y21
-rw-r--r--checkpolicy/policy_scan.l47
-rw-r--r--checkpolicy/ru/checkmodule.84
-rw-r--r--checkpolicy/ru/checkpolicy.84
-rw-r--r--checkpolicy/test/Makefile6
-rw-r--r--checkpolicy/test/dismod.c47
-rw-r--r--checkpolicy/test/dispol.c44
-rw-r--r--dbus/VERSION2
-rw-r--r--dbus/selinux_server.py79
-rw-r--r--gui/VERSION2
-rw-r--r--gui/fcontextPage.py7
-rw-r--r--gui/system-config-selinux.ui26
-rw-r--r--libselinux/Android.bp58
-rw-r--r--libselinux/Makefile24
-rw-r--r--libselinux/VERSION2
-rw-r--r--libselinux/fuzzers/selabel_lookup_fuzzer.cpp2
-rw-r--r--libselinux/include/selinux/avc.h18
-rw-r--r--libselinux/include/selinux/get_context_list.h12
-rw-r--r--libselinux/include/selinux/restorecon.h51
-rw-r--r--libselinux/include/selinux/selinux.h75
-rw-r--r--libselinux/man/man3/avc_init.351
-rw-r--r--libselinux/man/man3/avc_netlink_loop.38
-rw-r--r--libselinux/man/man3/avc_open.339
-rw-r--r--libselinux/man/man3/get_ordered_context_list.336
-rw-r--r--libselinux/man/man3/getcon.341
-rw-r--r--libselinux/man/man3/is_selinux_enabled.31
-rw-r--r--libselinux/man/man3/security_check_context.34
-rw-r--r--libselinux/man/man3/security_compute_av.35
-rw-r--r--libselinux/man/man3/selinux_restorecon.333
-rw-r--r--libselinux/man/man3/selinux_restorecon_parallel.31
-rw-r--r--libselinux/man/man3/selinux_set_callback.314
-rw-r--r--libselinux/man/man3/selinux_status_open.313
-rw-r--r--libselinux/man/man5/selabel_file.59
-rw-r--r--libselinux/man/man8/selinux.849
-rw-r--r--libselinux/man/ru/man5/failsafe_context.54
-rw-r--r--libselinux/src/Makefile22
-rw-r--r--libselinux/src/android/android.c19
-rw-r--r--libselinux/src/android/android_common.h1
-rw-r--r--libselinux/src/android/android_host.c8
-rw-r--r--libselinux/src/android/android_platform.c224
-rw-r--r--libselinux/src/audit2why.c13
-rw-r--r--libselinux/src/avc.c68
-rw-r--r--libselinux/src/avc_internal.c82
-rw-r--r--libselinux/src/avc_internal.h78
-rw-r--r--libselinux/src/avc_sidtab.c15
-rw-r--r--libselinux/src/avc_sidtab.h11
-rw-r--r--libselinux/src/booleans.c5
-rw-r--r--libselinux/src/callbacks.c8
-rw-r--r--libselinux/src/callbacks.h22
-rw-r--r--libselinux/src/canonicalize_context.c2
-rw-r--r--libselinux/src/checkAccess.c14
-rw-r--r--libselinux/src/check_context.c2
-rw-r--r--libselinux/src/checkreqprot.c1
-rw-r--r--libselinux/src/compute_av.c4
-rw-r--r--libselinux/src/compute_create.c4
-rw-r--r--libselinux/src/compute_member.c1
-rw-r--r--libselinux/src/compute_relabel.c1
-rw-r--r--libselinux/src/compute_user.c5
-rw-r--r--libselinux/src/context.c15
-rw-r--r--libselinux/src/context_internal.h12
-rw-r--r--libselinux/src/deny_unknown.c1
-rw-r--r--libselinux/src/disable.c1
-rw-r--r--libselinux/src/dso.h23
-rw-r--r--libselinux/src/enabled.c2
-rwxr-xr-xlibselinux/src/exception.sh21
-rw-r--r--libselinux/src/fgetfilecon.c1
-rw-r--r--libselinux/src/freecon.c1
-rw-r--r--libselinux/src/freeconary.c1
-rw-r--r--libselinux/src/fsetfilecon.c1
-rw-r--r--libselinux/src/get_context_list.c262
-rw-r--r--libselinux/src/get_context_list_internal.h4
-rw-r--r--libselinux/src/get_default_type_internal.h2
-rw-r--r--libselinux/src/get_initial_context.c2
-rw-r--r--libselinux/src/getenforce.c1
-rw-r--r--libselinux/src/getfilecon.c2
-rw-r--r--libselinux/src/getpeercon.c1
-rw-r--r--libselinux/src/init.c4
-rw-r--r--libselinux/src/is_customizable_type.c25
-rw-r--r--libselinux/src/label_backends_android.c12
-rw-r--r--libselinux/src/label_db.c2
-rw-r--r--libselinux/src/label_file.c54
-rw-r--r--libselinux/src/label_file.h22
-rw-r--r--libselinux/src/label_internal.h29
-rw-r--r--libselinux/src/label_media.c1
-rw-r--r--libselinux/src/label_support.c6
-rw-r--r--libselinux/src/label_x.c1
-rw-r--r--libselinux/src/lgetfilecon.c1
-rw-r--r--libselinux/src/libselinux.map247
-rw-r--r--libselinux/src/load_policy.c29
-rw-r--r--libselinux/src/lsetfilecon.c1
-rw-r--r--libselinux/src/mapping.c22
-rw-r--r--libselinux/src/matchmediacon.c1
-rw-r--r--libselinux/src/matchpathcon.c72
-rw-r--r--libselinux/src/policyvers.c2
-rw-r--r--libselinux/src/procattr.c45
-rw-r--r--libselinux/src/regex.c4
-rw-r--r--libselinux/src/regex.h23
-rw-r--r--libselinux/src/reject_unknown.c1
-rw-r--r--libselinux/src/selinux_check_securetty_context.c1
-rw-r--r--libselinux/src/selinux_config.c60
-rw-r--r--libselinux/src/selinux_internal.h133
-rw-r--r--libselinux/src/selinux_restorecon.c529
-rw-r--r--libselinux/src/selinuxswig_python.i6
-rw-r--r--libselinux/src/selinuxswig_python_exception.i464
-rw-r--r--libselinux/src/sestatus.c76
-rw-r--r--libselinux/src/setenforce.c1
-rw-r--r--libselinux/src/setexecfilecon.c1
-rw-r--r--libselinux/src/setfilecon.c1
-rw-r--r--libselinux/src/setrans_client.c10
-rw-r--r--libselinux/src/setup.py2
-rw-r--r--libselinux/src/seusers.c2
-rw-r--r--libselinux/src/sha1.c28
-rw-r--r--libselinux/src/sha1.h2
-rw-r--r--libselinux/src/stringrep.c9
-rw-r--r--libselinux/src/validatetrans.c2
-rw-r--r--libselinux/utils/Makefile9
-rw-r--r--libselinux/utils/avcstat.c4
-rw-r--r--libselinux/utils/compute_user.c38
-rw-r--r--libselinux/utils/getconlist.c14
-rw-r--r--libselinux/utils/getdefaultcon.c3
-rw-r--r--libselinux/utils/getseuser.c43
-rw-r--r--libselinux/utils/matchpathcon.c86
-rw-r--r--libselinux/utils/sefcontext_compile.c2
-rw-r--r--libselinux/utils/selabel_get_digests_all_partial_matches.c10
-rw-r--r--libselinux/utils/selabel_lookup_best_match.c2
-rw-r--r--libsemanage/VERSION2
-rw-r--r--libsemanage/include/semanage/handle.h5
-rw-r--r--libsemanage/include/semanage/modules.h28
-rw-r--r--libsemanage/man/man5/semanage.conf.56
-rw-r--r--libsemanage/man/ru/man5/semanage.conf.52
-rw-r--r--libsemanage/src/Makefile7
-rw-r--r--libsemanage/src/boolean_internal.h13
-rw-r--r--libsemanage/src/boolean_record.c16
-rw-r--r--libsemanage/src/booleans_file.c2
-rw-r--r--libsemanage/src/compressed_file.c224
-rw-r--r--libsemanage/src/compressed_file.h78
-rw-r--r--libsemanage/src/conf-parse.y4
-rw-r--r--libsemanage/src/context_internal.h11
-rw-r--r--libsemanage/src/context_record.c7
-rw-r--r--libsemanage/src/database_join.c12
-rw-r--r--libsemanage/src/database_llist.c2
-rw-r--r--libsemanage/src/debug.c7
-rw-r--r--libsemanage/src/debug.h8
-rw-r--r--libsemanage/src/direct_api.c553
-rw-r--r--libsemanage/src/direct_api.h4
-rw-r--r--libsemanage/src/dso.h23
-rw-r--r--libsemanage/src/exception.sh3
-rw-r--r--libsemanage/src/fcontext_internal.h20
-rw-r--r--libsemanage/src/fcontext_record.c16
-rw-r--r--libsemanage/src/fcontexts_file.c7
-rw-r--r--libsemanage/src/fcontexts_local.c4
-rw-r--r--libsemanage/src/genhomedircon.c2
-rw-r--r--libsemanage/src/handle.c16
-rw-r--r--libsemanage/src/handle.h2
-rw-r--r--libsemanage/src/handle_internal.h13
-rw-r--r--libsemanage/src/ibendport_internal.h20
-rw-r--r--libsemanage/src/ibendport_record.c15
-rw-r--r--libsemanage/src/ibendports_file.c5
-rw-r--r--libsemanage/src/ibendports_local.c3
-rw-r--r--libsemanage/src/ibpkey_internal.h24
-rw-r--r--libsemanage/src/ibpkey_record.c19
-rw-r--r--libsemanage/src/ibpkeys_file.c5
-rw-r--r--libsemanage/src/ibpkeys_local.c3
-rw-r--r--libsemanage/src/iface_internal.h15
-rw-r--r--libsemanage/src/iface_record.c13
-rw-r--r--libsemanage/src/interfaces_file.c7
-rw-r--r--libsemanage/src/libsemanage.map403
-rw-r--r--libsemanage/src/module_internal.h27
-rw-r--r--libsemanage/src/modules.c237
-rw-r--r--libsemanage/src/modules.h16
-rw-r--r--libsemanage/src/node_internal.h27
-rw-r--r--libsemanage/src/node_record.c22
-rw-r--r--libsemanage/src/nodes_file.c9
-rw-r--r--libsemanage/src/nodes_local.c1
-rw-r--r--libsemanage/src/parse_utils.c6
-rw-r--r--libsemanage/src/parse_utils.h11
-rw-r--r--libsemanage/src/port_internal.h23
-rw-r--r--libsemanage/src/port_record.c18
-rw-r--r--libsemanage/src/ports_file.c5
-rw-r--r--libsemanage/src/ports_local.c3
-rw-r--r--libsemanage/src/semanage.conf5
-rw-r--r--libsemanage/src/semanage_store.c87
-rw-r--r--libsemanage/src/semanage_store.h5
-rw-r--r--libsemanage/src/semanageswig_python.i2
-rw-r--r--libsemanage/src/semanageswig_python_exception.i271
-rw-r--r--libsemanage/src/seuser_internal.h20
-rw-r--r--libsemanage/src/seuser_record.c14
-rw-r--r--libsemanage/src/seusers_file.c6
-rw-r--r--libsemanage/src/seusers_local.c3
-rw-r--r--libsemanage/src/seusers_policy.c1
-rw-r--r--libsemanage/src/sha256.c294
-rw-r--r--libsemanage/src/sha256.h89
-rw-r--r--libsemanage/src/user_base_record.c32
-rw-r--r--libsemanage/src/user_extra_record.c14
-rw-r--r--libsemanage/src/user_internal.h72
-rw-r--r--libsemanage/src/user_record.c22
-rw-r--r--libsemanage/src/users_base_file.c7
-rw-r--r--libsemanage/src/users_extra_file.c4
-rw-r--r--libsemanage/src/users_policy.c2
-rw-r--r--libsemanage/src/utilities.c2
-rw-r--r--libsemanage/tests/libsemanage-tests.c18
-rw-r--r--libsemanage/tests/test_bool.c34
-rw-r--r--libsemanage/tests/test_fcontext.c32
-rw-r--r--libsemanage/tests/test_ibendport.c13
-rw-r--r--libsemanage/tests/test_iface.c24
-rw-r--r--libsemanage/tests/test_node.c29
-rw-r--r--libsemanage/tests/test_other.c6
-rw-r--r--libsemanage/tests/test_port.c24
-rw-r--r--libsemanage/tests/test_user.c17
-rw-r--r--libsemanage/tests/utilities.c5
-rw-r--r--libsemanage/tests/utilities.h2
-rw-r--r--libsepol/Android.bp37
-rw-r--r--libsepol/VERSION2
-rw-r--r--libsepol/cil/include/cil/cil.h8
-rw-r--r--libsepol/cil/include/cil/cil_write_ast.h7
-rw-r--r--libsepol/cil/src/android.c1
-rw-r--r--libsepol/cil/src/cil.c260
-rw-r--r--libsepol/cil/src/cil_binary.c293
-rw-r--r--libsepol/cil/src/cil_build_ast.c1229
-rw-r--r--libsepol/cil/src/cil_build_ast.h2
-rw-r--r--libsepol/cil/src/cil_copy_ast.c190
-rw-r--r--libsepol/cil/src/cil_find.c11
-rw-r--r--libsepol/cil/src/cil_fqn.c4
-rw-r--r--libsepol/cil/src/cil_internal.h30
-rw-r--r--libsepol/cil/src/cil_lexer.l2
-rw-r--r--libsepol/cil/src/cil_list.c7
-rw-r--r--libsepol/cil/src/cil_log.c11
-rw-r--r--libsepol/cil/src/cil_log.h2
-rw-r--r--libsepol/cil/src/cil_mem.c1
-rw-r--r--libsepol/cil/src/cil_parser.c139
-rw-r--r--libsepol/cil/src/cil_parser.h2
-rw-r--r--libsepol/cil/src/cil_policy.c21
-rw-r--r--libsepol/cil/src/cil_post.c89
-rw-r--r--libsepol/cil/src/cil_post.h7
-rw-r--r--libsepol/cil/src/cil_reset_ast.c88
-rw-r--r--libsepol/cil/src/cil_resolve_ast.c1310
-rw-r--r--libsepol/cil/src/cil_stack.c5
-rw-r--r--libsepol/cil/src/cil_stack.h1
-rw-r--r--libsepol/cil/src/cil_strpool.c16
-rw-r--r--libsepol/cil/src/cil_symtab.c10
-rw-r--r--libsepol/cil/src/cil_tree.c1583
-rw-r--r--libsepol/cil/src/cil_tree.h8
-rw-r--r--libsepol/cil/src/cil_verify.c361
-rw-r--r--libsepol/cil/src/cil_verify.h7
-rw-r--r--libsepol/cil/src/cil_write_ast.c2736
-rw-r--r--libsepol/cil/src/cil_write_ast.h46
-rw-r--r--libsepol/cil/src/dso.h27
-rw-r--r--libsepol/fuzz/binpolicy-fuzzer.c63
-rw-r--r--libsepol/fuzz/policy.binbin0 -> 1552 bytes
-rw-r--r--libsepol/fuzz/secilc-fuzzer.c74
-rw-r--r--libsepol/include/sepol/booleans.h5
-rw-r--r--libsepol/include/sepol/policydb/conditional.h2
-rw-r--r--libsepol/include/sepol/policydb/ebitmap.h16
-rw-r--r--libsepol/include/sepol/policydb/flask.h94
-rw-r--r--libsepol/include/sepol/policydb/flask_types.h8
-rw-r--r--libsepol/include/sepol/policydb/hashtab.h28
-rw-r--r--libsepol/include/sepol/policydb/polcaps.h19
-rw-r--r--libsepol/include/sepol/policydb/policydb.h36
-rw-r--r--libsepol/include/sepol/roles.h18
-rw-r--r--libsepol/include/sepol/users.h6
-rw-r--r--libsepol/src/Makefile10
-rw-r--r--libsepol/src/assertion.c223
-rw-r--r--libsepol/src/av_permissions.h3
-rw-r--r--libsepol/src/avrule_block.c2
-rw-r--r--libsepol/src/avtab.c16
-rw-r--r--libsepol/src/boolean_internal.h9
-rw-r--r--libsepol/src/boolean_record.c8
-rw-r--r--libsepol/src/booleans.c6
-rw-r--r--libsepol/src/conditional.c64
-rw-r--r--libsepol/src/constraint.c6
-rw-r--r--libsepol/src/context_internal.h14
-rw-r--r--libsepol/src/context_record.c43
-rw-r--r--libsepol/src/debug.c7
-rw-r--r--libsepol/src/debug.h6
-rw-r--r--libsepol/src/deprecated_funcs.c50
-rw-r--r--libsepol/src/dso.h27
-rw-r--r--libsepol/src/ebitmap.c96
-rw-r--r--libsepol/src/expand.c160
-rw-r--r--libsepol/src/flask.h38
-rw-r--r--libsepol/src/hashtab.c133
-rw-r--r--libsepol/src/hierarchy.c2
-rw-r--r--libsepol/src/ibendport_internal.h11
-rw-r--r--libsepol/src/ibendport_record.c18
-rw-r--r--libsepol/src/ibendports.c2
-rw-r--r--libsepol/src/ibpkey_internal.h14
-rw-r--r--libsepol/src/ibpkey_record.c20
-rw-r--r--libsepol/src/iface_internal.h11
-rw-r--r--libsepol/src/iface_record.c10
-rw-r--r--libsepol/src/kernel_to_cil.c336
-rw-r--r--libsepol/src/kernel_to_common.c33
-rw-r--r--libsepol/src/kernel_to_common.h4
-rw-r--r--libsepol/src/kernel_to_conf.c206
-rw-r--r--libsepol/src/libsepol.map.in270
-rw-r--r--libsepol/src/link.c60
-rw-r--r--libsepol/src/mls.c8
-rw-r--r--libsepol/src/module.c29
-rw-r--r--libsepol/src/module_internal.h3
-rw-r--r--libsepol/src/module_to_cil.c207
-rw-r--r--libsepol/src/node_internal.h19
-rw-r--r--libsepol/src/node_record.c28
-rw-r--r--libsepol/src/nodes.c6
-rw-r--r--libsepol/src/optimize.c141
-rw-r--r--libsepol/src/polcaps.c21
-rw-r--r--libsepol/src/policydb.c551
-rw-r--r--libsepol/src/policydb_internal.h5
-rw-r--r--libsepol/src/policydb_public.c3
-rw-r--r--libsepol/src/policydb_validate.c1340
-rw-r--r--libsepol/src/policydb_validate.h7
-rw-r--r--libsepol/src/port_internal.h13
-rw-r--r--libsepol/src/port_record.c12
-rw-r--r--libsepol/src/private.h53
-rw-r--r--libsepol/src/roles.c53
-rw-r--r--libsepol/src/services.c314
-rw-r--r--libsepol/src/sidtab.c36
-rw-r--r--libsepol/src/symtab.c4
-rw-r--r--libsepol/src/user_internal.h13
-rw-r--r--libsepol/src/user_record.c20
-rw-r--r--libsepol/src/users.c12
-rw-r--r--libsepol/src/util.c20
-rw-r--r--libsepol/src/write.c140
-rw-r--r--libsepol/tests/Makefile12
-rw-r--r--libsepol/tests/libsepol-tests.c18
-rw-r--r--mcstrans/Makefile6
-rw-r--r--mcstrans/VERSION2
-rw-r--r--mcstrans/share/util/mlstrans-test4
-rw-r--r--mcstrans/src/Makefile4
-rw-r--r--mcstrans/src/mcscolor.c10
-rw-r--r--mcstrans/src/mcscolor.h8
-rw-r--r--mcstrans/src/mcstrans.c203
-rw-r--r--mcstrans/src/mcstrans.h5
-rw-r--r--mcstrans/src/mcstrans.service3
-rw-r--r--mcstrans/src/mcstransd.c15
-rw-r--r--mcstrans/utils/Makefile6
-rw-r--r--mcstrans/utils/transcon.c2
-rw-r--r--mcstrans/utils/untranscon.c2
-rw-r--r--policycoreutils/VERSION2
-rw-r--r--policycoreutils/man/man5/selinux_config.54
-rw-r--r--policycoreutils/man/ru/man5/selinux_config.52
-rw-r--r--policycoreutils/newrole/Makefile20
-rw-r--r--policycoreutils/newrole/hashtab.c94
-rw-r--r--policycoreutils/newrole/hashtab.h28
-rw-r--r--policycoreutils/newrole/newrole.c83
-rw-r--r--policycoreutils/run_init/open_init_pty.c2
-rw-r--r--policycoreutils/run_init/run_init.c19
-rwxr-xr-xpolicycoreutils/scripts/fixfiles56
-rw-r--r--policycoreutils/scripts/fixfiles.830
-rw-r--r--policycoreutils/secon/secon.c24
-rw-r--r--policycoreutils/semodule/genhomedircon.83
-rw-r--r--policycoreutils/semodule/semodule.813
-rw-r--r--policycoreutils/semodule/semodule.c112
-rw-r--r--policycoreutils/sestatus/Makefile8
-rw-r--r--policycoreutils/sestatus/sestatus.c13
-rw-r--r--policycoreutils/setfiles/.gitignore1
-rw-r--r--policycoreutils/setfiles/Makefile14
-rw-r--r--policycoreutils/setfiles/restore.c11
-rw-r--r--policycoreutils/setfiles/restore.h3
-rw-r--r--policycoreutils/setfiles/restorecon.822
-rw-r--r--policycoreutils/setfiles/restorecon_xattr.c14
-rw-r--r--policycoreutils/setfiles/ru/setfiles.82
-rw-r--r--policycoreutils/setfiles/setfiles.820
-rw-r--r--policycoreutils/setfiles/setfiles.c81
-rw-r--r--policycoreutils/setsebool/setsebool.c4
-rwxr-xr-xprebuilts/bin/audit2allow23
-rwxr-xr-xprebuilts/bin/audit2why23
-rwxr-xr-xprebuilts/bin/sediff15
-rwxr-xr-xprebuilts/bin/sediff.py1366
-rwxr-xr-xprebuilts/bin/seinfo16
-rwxr-xr-xprebuilts/bin/seinfo.py366
-rwxr-xr-xprebuilts/bin/sesearch9
-rwxr-xr-xprebuilts/bin/sesearch.py248
-rw-r--r--python/VERSION2
-rw-r--r--python/audit2allow/Makefile2
-rw-r--r--python/audit2allow/sepolgen-ifgen28
-rw-r--r--python/audit2allow/sepolgen-ifgen-attr-helper.c45
-rw-r--r--python/semanage/semanage22
-rw-r--r--python/semanage/semanage-bash-completion.sh10
-rw-r--r--python/semanage/semanage-fcontext.820
-rw-r--r--python/semanage/semanage-node.82
-rw-r--r--python/semanage/seobject.py53
-rw-r--r--python/semanage/test-semanage.py12
-rw-r--r--python/sepolgen/VERSION2
-rw-r--r--python/sepolgen/src/sepolgen/output.py5
-rw-r--r--python/sepolgen/src/sepolgen/refparser.py24
-rw-r--r--python/sepolgen/src/sepolgen/refpolicy.py7
-rw-r--r--python/sepolgen/src/sepolgen/yacc.py2
-rw-r--r--python/sepolgen/tests/test_access.py10
-rw-r--r--python/sepolgen/tests/test_refpolicy.py12
-rw-r--r--python/sepolicy/Makefile2
-rw-r--r--python/sepolicy/sepolicy/__init__.py109
-rw-r--r--python/sepolicy/sepolicy/generate.py4
-rw-r--r--python/sepolicy/sepolicy/interface.py6
-rwxr-xr-xpython/sepolicy/sepolicy/manpage.py12
-rwxr-xr-xpython/sepolicy/sepolicy/network.py6
-rw-r--r--python/sepolicy/sepolicy/sedbus.py9
-rw-r--r--python/sepolicy/sepolicy/sepolicy.glade12
-rw-r--r--python/sepolicy/setup.py2
-rw-r--r--restorecond/Makefile17
-rw-r--r--restorecond/VERSION2
-rw-r--r--restorecond/org.selinux.Restorecond.service1
-rw-r--r--restorecond/restorecond.desktop1
-rw-r--r--restorecond/restorecond_user.service10
-rw-r--r--restorecond/user.c197
-rw-r--r--sandbox/VERSION2
-rw-r--r--sandbox/seunshare.c12
-rw-r--r--scripts/ci/.gitignore1
-rw-r--r--scripts/ci/LICENSE5
-rw-r--r--scripts/ci/README.md8
-rw-r--r--scripts/ci/Vagrantfile48
-rwxr-xr-xscripts/ci/fedora-test-runner.sh98
-rwxr-xr-xscripts/ci/travis-kvm-setup.sh130
-rwxr-xr-xscripts/env_use_destdir29
-rwxr-xr-xscripts/oss-fuzz.sh72
-rwxr-xr-xscripts/release97
-rwxr-xr-xscripts/run-flake82
-rwxr-xr-xscripts/run-scan-build22
-rw-r--r--secilc/.gitignore4
-rw-r--r--secilc/Makefile29
-rw-r--r--secilc/VERSION2
-rw-r--r--secilc/docs/Makefile22
-rw-r--r--secilc/docs/README.md1
-rw-r--r--secilc/docs/cil_access_vector_rules.md48
-rw-r--r--secilc/docs/cil_call_macro_statements.md36
-rw-r--r--secilc/docs/cil_class_and_permission_statements.md42
-rw-r--r--secilc/docs/cil_conditional_statements.md46
-rw-r--r--secilc/docs/cil_constraint_statements.md28
-rw-r--r--secilc/docs/cil_container_statements.md62
-rw-r--r--secilc/docs/cil_context_statement.md10
-rw-r--r--secilc/docs/cil_default_object_statements.md18
-rw-r--r--secilc/docs/cil_file_labeling_statements.md24
-rw-r--r--secilc/docs/cil_infiniband_statements.md9
-rw-r--r--secilc/docs/cil_mls_labeling_statements.md52
-rw-r--r--secilc/docs/cil_network_labeling_statements.md37
-rw-r--r--secilc/docs/cil_policy_config_statements.md12
-rw-r--r--secilc/docs/cil_reference_guide.md31
-rw-r--r--secilc/docs/cil_role_statements.md28
-rw-r--r--secilc/docs/cil_sid_statements.md12
-rw-r--r--secilc/docs/cil_type_statements.md101
-rw-r--r--secilc/docs/cil_user_statements.md44
-rw-r--r--secilc/docs/cil_xen_statements.md20
-rw-r--r--secilc/docs/secil.xml236
-rw-r--r--secilc/docs/theme.theme59
-rw-r--r--secilc/secil2conf.8.xml5
-rw-r--r--secilc/secil2conf.c12
-rw-r--r--secilc/secil2tree.8.xml86
-rw-r--r--secilc/secil2tree.c215
-rw-r--r--secilc/secilc.8.xml5
-rw-r--r--secilc/secilc.c13
-rw-r--r--secilc/test/anonymous_arg_test.cil106
-rw-r--r--secilc/test/block_test.cil2
-rw-r--r--secilc/test/opt-expected.cil60
-rw-r--r--secilc/test/opt-input.cil65
-rw-r--r--semodule-utils/VERSION2
473 files changed, 15482 insertions, 12452 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 5d3177da..af20484b 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -13,7 +13,7 @@ jobs:
# Install dependencies
- run: sudo apt-get update -qq
- - run: sudo apt-get install -qq bison clang clang-tools flex gawk gettext libaudit-dev libcap-dev libcap-ng-dev libcunit1-dev libdbus-glib-1-dev libpcre3-dev python3-dev python-dev ruby-dev swig xmlto
+ - run: sudo apt-get install -qq bison clang clang-tools flex gawk gettext libaudit-dev libcap-dev libcap-ng-dev libcunit1-dev libdbus-glib-1-dev libpcre2-dev python3-dev python-dev ruby-dev swig xmlto
- run:
name: Setup environment variables
diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml
new file mode 100644
index 00000000..92523db4
--- /dev/null
+++ b/.github/workflows/cifuzz.yml
@@ -0,0 +1,40 @@
+---
+name: CIFuzz
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+jobs:
+ Fuzzing:
+ runs-on: ubuntu-latest
+ if: github.repository == 'SELinuxProject/selinux'
+ strategy:
+ fail-fast: false
+ matrix:
+ sanitizer: [address, undefined, memory]
+ steps:
+ - name: Build Fuzzers (${{ matrix.sanitizer }})
+ id: build
+ uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
+ with:
+ oss-fuzz-project-name: 'selinux'
+ dry-run: false
+ allowed-broken-targets-percentage: 0
+ sanitizer: ${{ matrix.sanitizer }}
+ - name: Run Fuzzers (${{ matrix.sanitizer }})
+ uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
+ with:
+ oss-fuzz-project-name: 'selinux'
+ fuzz-seconds: 600
+ dry-run: false
+ report-unreproducible-crashes: true
+ sanitizer: ${{ matrix.sanitizer }}
+ - name: Upload Crash
+ uses: actions/upload-artifact@v1
+ if: failure() && steps.build.outcome == 'success'
+ with:
+ name: ${{ matrix.sanitizer }}-artifacts
+ path: ./out/artifacts
diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
new file mode 100644
index 00000000..8b7cb720
--- /dev/null
+++ b/.github/workflows/run_tests.yml
@@ -0,0 +1,199 @@
+name: Run tests
+
+on: [push, pull_request]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ compiler: [gcc, clang]
+ python-ruby-version:
+ - {python: 3.9, ruby: 2.7}
+ - {python: 3.9, ruby: 2.7, other: test-flags-override}
+ - {python: 3.9, ruby: 2.7, other: test-debug}
+ - {python: 3.9, ruby: 2.7, other: linker-bfd}
+ - {python: 3.9, ruby: 2.7, other: linker-gold}
+ # Test several Python versions with the latest Ruby version
+ - {python: 3.8, ruby: 2.7}
+ - {python: 3.7, ruby: 2.7}
+ - {python: 3.6, ruby: 2.7}
+ - {python: 3.5, ruby: 2.7}
+ - {python: pypy3, ruby: 2.7}
+ # Test several Ruby versions with the latest Python version
+ - {python: 3.9, ruby: 2.6}
+ - {python: 3.9, ruby: 2.5}
+ exclude:
+ - compiler: clang
+ python-ruby-version: {python: 3.9, ruby: 2.7, other: linker-bfd}
+ - compiler: clang
+ python-ruby-version: {python: 3.9, ruby: 2.7, other: linker-gold}
+ include:
+ - compiler: gcc
+ python-ruby-version: {python: 3.9, ruby: 2.7, other: sanitizers}
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Python ${{ matrix.python-ruby-version.python }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-ruby-version.python }}
+
+ - name: Set up Ruby ${{ matrix.python-ruby-version.ruby }}
+ uses: actions/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.python-ruby-version.ruby }}
+
+ - name: Install dependencies
+ run: |
+ sudo apt-get update -qq
+ sudo apt-get install -qqy \
+ bison \
+ clang \
+ flex \
+ gawk \
+ gettext \
+ libaudit-dev \
+ libcap-dev \
+ libcap-ng-dev \
+ libcunit1-dev \
+ libdbus-glib-1-dev \
+ libpcre2-dev \
+ python3-dev \
+ python-dev \
+ ruby-dev \
+ swig \
+ xmlto
+
+ pip install flake8
+
+ - name: Configure the environment
+ run: |
+ DESTDIR=/tmp/destdir
+ echo "PYTHON=python" >> $GITHUB_ENV
+ echo "RUBY=ruby" >> $GITHUB_ENV
+ echo "DESTDIR=$DESTDIR" >> $GITHUB_ENV
+
+ CC=${{ matrix.compiler }}
+ if [ "${{ matrix.python-ruby-version.other }}" = "linker-bfd" ] ; then
+ CC="$CC -fuse-ld=bfd"
+ elif [ "${{ matrix.python-ruby-version.other }}" = "linker-gold" ] ; then
+ CC="$CC -fuse-ld=gold"
+ fi
+ echo "CC=$CC" >> $GITHUB_ENV
+
+ EXPLICIT_MAKE_VARS=
+ if [ "${{ matrix.python-ruby-version.other }}" = "test-flags-override" ] ; then
+ # Test that overriding CFLAGS, LDFLAGS and other variables works fine
+ EXPLICIT_MAKE_VARS="CFLAGS=-I$DESTDIR/usr/include LDFLAGS=-L$DESTDIR/usr/lib LDLIBS= CPPFLAGS="
+ elif [ "${{ matrix.python-ruby-version.other }}" = "test-debug" ] ; then
+ # Test hat debug build works fine
+ EXPLICIT_MAKE_VARS="DEBUG=1"
+ elif [ "${{ matrix.python-ruby-version.other }}" = "sanitizers" ] ; then
+ sanitizers='-fsanitize=address,undefined'
+ EXPLICIT_MAKE_VARS="CFLAGS='-g -I$DESTDIR/usr/include $sanitizers' LDFLAGS='-L$DESTDIR/usr/lib $sanitizers' LDLIBS= CPPFLAGS= OPT_SUBDIRS="
+ echo "ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1" >> $GITHUB_ENV
+ echo "UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1" >> $GITHUB_ENV
+ else
+ EXPLICIT_MAKE_VARS=
+ fi
+ echo "EXPLICIT_MAKE_VARS=${EXPLICIT_MAKE_VARS}" >> $GITHUB_ENV
+
+ # Find files in order of pkgconf to be able to find Python.h
+ # For example with Python 3.5:
+ # * python is located at /opt/hostedtoolcache/Python/3.5.10/x64/bin/python
+ # * sys.prefix is /opt/hostedtoolcache/Python/3.5.10/x64
+ # * Python.h is located at /opt/hostedtoolcache/Python/3.5.10/x64/include/python3.5m/Python.h
+ # * python-3.5.pc is located at /opt/hostedtoolcache/Python/3.5.10/x64/lib/pkgconfig/python-3.5.pc
+ PYTHON_SYS_PREFIX="$(python -c 'import sys;print(sys.prefix)')"
+ echo "PKG_CONFIG_PATH=${PYTHON_SYS_PREFIX}/lib/pkgconfig" >> $GITHUB_ENV
+
+ if [ "${{ matrix.python-ruby-version.python }}" = "pypy3" ] ; then
+ # PyPy does not provide a config file for pkg-config
+ # libpypy-c.so is provided in bin/libpypy-c.so for PyPy and bin/libpypy3-c.so for PyPy3
+ echo "PYINC=-I${PYTHON_SYS_PREFIX}/include" >> $GITHUB_ENV
+ echo "PYLIBS=-L${PYTHON_SYS_PREFIX}/bin -lpypy3-c" >> $GITHUB_ENV
+ fi
+
+ # Display the final environment file, for debugging purpose
+ cat $GITHUB_ENV
+
+ - name: Download and install refpolicy headers for sepolgen tests
+ run: |
+ curl --location --retry 10 -o refpolicy.tar.bz2 https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_2_20180701/refpolicy-2.20180701.tar.bz2
+ tar -xvjf refpolicy.tar.bz2
+ sed -e "s,^PREFIX :=.*,PREFIX := $DESTDIR/usr," -i refpolicy/support/Makefile.devel
+ sudo make -C refpolicy install-headers clean
+ sudo mkdir -p /etc/selinux
+ echo 'SELINUXTYPE=refpolicy' | sudo tee /etc/selinux/config
+ echo 'SELINUX_DEVEL_PATH = /usr/share/selinux/refpolicy' | sudo tee /etc/selinux/sepolgen.conf
+ sed -e "s,\"\(/usr/bin/[cs]\),\"$DESTDIR\1," -i python/sepolgen/src/sepolgen/module.py
+ rm -r refpolicy refpolicy.tar.bz2
+
+ - name: Display versions
+ run: |
+ echo "::group::Compiler ($CC):"
+ $CC --version
+ echo "::endgroup::"
+ echo "::group::Python ($(which "$PYTHON")):"
+ $PYTHON --version
+ echo "::endgroup::"
+ echo "::group::Ruby ($(which "$RUBY")):"
+ $RUBY --version
+ echo "::endgroup::"
+
+ - name: Run tests
+ run: |
+ echo "::group::make install"
+ eval make -j$(nproc) install $EXPLICIT_MAKE_VARS -k
+ echo "::endgroup::"
+ echo "::group::make install-pywrap"
+ eval make -j$(nproc) install-pywrap $EXPLICIT_MAKE_VARS -k
+ echo "::endgroup::"
+ echo "::group::make install-rubywrap"
+ eval make -j$(nproc) install-rubywrap $EXPLICIT_MAKE_VARS -k
+ echo "::endgroup::"
+
+ # Now that everything is installed, run "make all" to build everything which may have not been built
+ echo "::group::make all"
+ eval make -j$(nproc) all $EXPLICIT_MAKE_VARS -k
+ echo "::endgroup::"
+
+ # Set up environment variables for the tests and show variables (to help debugging issues)
+ echo "::group::Environment variables"
+ . ./scripts/env_use_destdir
+ echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
+ echo "PATH=$PATH"
+ echo "PYTHONPATH=$PYTHONPATH"
+ echo "RUBYLIB=$RUBYLIB"
+ echo "::endgroup::"
+
+ # Run tests
+ echo "::group::make test"
+ eval make test $EXPLICIT_MAKE_VARS
+ echo "::endgroup::"
+
+ if [ "${{ matrix.python-ruby-version.other }}" != "sanitizers" ] ; then
+ # Test Python and Ruby wrappers
+ echo "::group::Test Python and Ruby wrappers"
+ $PYTHON -c 'import selinux;import selinux.audit2why;import semanage;print(selinux.is_selinux_enabled())'
+ $RUBY -e 'require "selinux";require "semanage";puts Selinux::is_selinux_enabled()'
+ echo "::endgroup::"
+
+ # Run Python linter, but not on the downloaded refpolicy
+ echo "::group::scripts/run-flake8"
+ ./scripts/run-flake8
+ echo "::endgroup::"
+ fi
+
+ echo "::group::Test .gitignore and make clean distclean"
+ # Remove every installed files
+ rm -rf "$DESTDIR"
+ # Test that "git status" looks clean, or print a clear error message
+ git status --short | sed -n 's/^??/error: missing .gitignore entry for/p' | (! grep '^')
+ # Clean up everything and show which file needs to be added to "make clean"
+ eval make clean distclean $EXPLICIT_MAKE_VARS
+ git ls-files --ignored --others --exclude-standard | sed 's/^/error: "make clean distclean" did not remove /' | (! grep '^')
+ echo "::endgroup::"
diff --git a/.github/workflows/vm_testsuite.yml b/.github/workflows/vm_testsuite.yml
new file mode 100644
index 00000000..601276dd
--- /dev/null
+++ b/.github/workflows/vm_testsuite.yml
@@ -0,0 +1,23 @@
+name: Run SELinux testsuite in a virtual machine
+
+on: [push, pull_request]
+
+jobs:
+ vm_testsuite:
+
+ # Use VirtualBox+vagrant on macOS, as described in https://github.com/actions/virtual-environments/issues/433
+ # Use an old version of macOS until https://github.com/actions/virtual-environments/pull/4010 is merged.
+ runs-on: macos-10.15
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Create Vagrant VM
+ run: |
+ cd scripts/ci
+ vagrant up
+
+ - name: Run SELinux testsuite in the VM
+ run: |
+ cd scripts/ci
+ vagrant ssh -- ./run-selinux-test.sh
diff --git a/.travis.yml b/.travis.yml
index 918958ac..1c2c7f33 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,164 +1,12 @@
# Define the building environment
language: c
-matrix:
- fast_finish: true
-
-compiler:
- - clang
- - gcc
-
-env:
- matrix:
- # Test the last version of Python and Ruby together, with some linkers
- - PYVER=python3.7 RUBYLIBVER=2.6
- - PYVER=python3.7 RUBYLIBVER=2.6 TEST_FLAGS_OVERRIDE=1
- - PYVER=python3.7 RUBYLIBVER=2.6 TEST_DEBUG=1
- - PYVER=python3.7 RUBYLIBVER=2.6 LINKER=gold
- - PYVER=python3.7 RUBYLIBVER=2.6 LINKER=bfd
-
- # Test several Python versions
- - PYVER=python3.5 RUBYLIBVER=2.6
- - PYVER=python3.6 RUBYLIBVER=2.6
- - PYVER=pypy3.5-6.0 RUBYLIBVER=2.6
-
- # Test several Ruby versions (http://rubies.travis-ci.org/)
- - PYVER=python3.7 RUBYLIBVER=2.5.1
- - PYVER=python3.7 RUBYLIBVER=2.4
- - PYVER=python3.7 RUBYLIBVER=2.3
- - PYVER=python3.7 RUBYLIBVER=2.2
-
-matrix:
- exclude:
- - compiler: clang
- env: PYVER=python3.7 RUBYLIBVER=2.6 LINKER=gold
- - compiler: clang
- env: PYVER=python3.7 RUBYLIBVER=2.6 LINKER=bfd
-
-# Use Travis-CI Ubuntu 16.04 Xenial Xerus infrastructure, "full image" variant
+# Use Travis-CI Ubuntu 18.04 Bionic Beaver, "full image" variant
sudo: required
-dist: xenial
-
-# Install SELinux userspace utilities dependencies
-addons:
- apt:
- packages:
- - bison
- - flex
- - gawk
- - gettext
- - libaudit-dev
- - libbz2-dev
- - libcap-dev
- - libcap-ng-dev # This package is not whitelisted for the container infrastructure (https://github.com/travis-ci/apt-package-whitelist/issues/1096)
- - libcunit1-dev
- - libdbus-glib-1-dev
- - libncurses5-dev
- - libpcre3-dev
- - patch
- - python3-dev
- - python-dev
- - swig
- - xmlto
-
-install:
- # Download and install refpolicy headers for sepolgen tests
- - curl --location --retry 10 -o "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2" https://github.com/SELinuxProject/refpolicy/releases/download/RELEASE_2_20180701/refpolicy-2.20180701.tar.bz2
- - tar -C "$TRAVIS_BUILD_DIR" -xvjf "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2"
- # Make refpolicy Makefile use the new toolchain when building modules
- - sed -e "s,^PREFIX :=.*,PREFIX := \$(DESTDIR)/usr," -i "$TRAVIS_BUILD_DIR/refpolicy/support/Makefile.devel"
- - sudo make -C "$TRAVIS_BUILD_DIR/refpolicy" install-headers
- - sudo rm -rf "$TRAVIS_BUILD_DIR/refpolicy.tar.bz2" "$TRAVIS_BUILD_DIR/refpolicy"
- - sudo mkdir -p /etc/selinux
- - echo 'SELINUXTYPE=refpolicy' | sudo tee /etc/selinux/config
- - echo 'SELINUX_DEVEL_PATH = /usr/share/selinux/refpolicy' | sudo tee /etc/selinux/sepolgen.conf
-
- # Make sepolgen tests work without really installing anything in the real root (doing this would conflict with Ubuntu packages)
- - sed -e "s,\"\(/usr/bin/[cs]\),\"$TRAVIS_BUILD_DIR/installdir\1," -i python/sepolgen/src/sepolgen/module.py
-
- # Download the required python version if it is not installed
- - VIRTUAL_ENV="$HOME/virtualenv/$PYVER"
- - if ! [ -d "$VIRTUAL_ENV" ] ; then
- curl --retry 10 -o python.tar.bz2 "https://s3.amazonaws.com/travis-python-archives/binaries/ubuntu/16.04/x86_64/${PYVER/python/python-}.tar.bz2" &&
- sudo tar xjf python.tar.bz2 --directory / &&
- rm python.tar.bz2 ;
- fi
-
- # Install flake8 for the given python version
- - $VIRTUAL_ENV/bin/pip install flake8
-
-before_script:
- # Build and install in a temporary directory to run tests
- - export DESTDIR="$TRAVIS_BUILD_DIR/installdir"
-
- # Configure the variables for Python parts
- - export VIRTUAL_ENV="$HOME/virtualenv/$PYVER"
- - export PYTHON="$VIRTUAL_ENV/bin/python"
- # Use the header files in /opt/python/... for Python because the virtualenvs do not provide Python.h
- - export PKG_CONFIG_PATH="/opt/python/$($PYTHON -c 'import sys;print("%d.%d.%d" % sys.version_info[:3])')/lib/pkgconfig"
- # PyPy does not provide a config file for pkg-config
- # libpypy-c.so is provided in bin/libpypy-c.so for PyPy and bin/libpypy3-c.so for PyPy3
- - if echo "$PYVER" | grep -q pypy ; then
- export PYINC=-I$($PYTHON -c 'import sys;print(sys.prefix)')/include ;
- export PYLIBS="$($PYTHON -c 'import sys;print("-L%s/bin -l%s" % (sys.prefix, "pypy-c" if sys.version_info < (3,) else "pypy3-c"))')" ;
- fi
-
- # Find the Ruby executable with version $RUBYLIBVER
- - rvm reinstall ruby-$RUBYLIBVER --binary
- - export RUBY="$(ls -d -1 "$HOME/.rvm/rubies/ruby-$RUBYLIBVER"*/bin/ruby | head -n 1)"
-
- # Set the linker in $CC so that it gets used everywhere
- - if [ -n "$LINKER" ]; then CC="$CC -fuse-ld=$LINKER" ; fi
-
- # Show variables and versions (to help debugging)
- - echo "$CC" ; $CC --version
- - echo "$PYTHON" ; $PYTHON --version
- - echo "$RUBY" ; $RUBY --version
-
- # If TEST_FLAGS_OVERRIDE is defined, test that overriding CFLAGS, LDFLAGS and other variables works fine
- - if [ -n "$TEST_FLAGS_OVERRIDE" ]; then EXPLICIT_MAKE_VARS="CFLAGS=-I$DESTDIR/usr/include LDFLAGS=-L$DESTDIR/usr/lib LDLIBS= CPPFLAGS=" ; fi
- # If TEST_DEBUG is defined, test that debug build works fine
- - if [ -n "$TEST_DEBUG" ]; then EXPLICIT_MAKE_VARS="$EXPLICIT_MAKE_VARS DEBUG=1" ; fi
+dist: bionic
script:
- # Start by installing everything into $DESTDIR
- - make install $EXPLICIT_MAKE_VARS -k
- - make install-pywrap $EXPLICIT_MAKE_VARS -k
- - make install-rubywrap $EXPLICIT_MAKE_VARS -k
-
- # Now that everything is installed, run "make all" to build everything which may have not been built
- - make all $EXPLICIT_MAKE_VARS -k
-
- # Set up environment variables for the tests
- - . ./scripts/env_use_destdir
-
- # Show variables (to help debugging issues)
- - echo "$LD_LIBRARY_PATH"
- - echo "$PATH"
- - echo "$PYTHONPATH"
- - echo "$RUBYLIB"
-
- # Run tests
- - make test $EXPLICIT_MAKE_VARS
-
- # Test Python and Ruby wrappers
- - $PYTHON -c 'import selinux;import selinux.audit2why;import semanage;print(selinux.is_selinux_enabled())'
- - $RUBY -e 'require "selinux";require "semanage";puts Selinux::is_selinux_enabled()'
-
- # Run Python linter
- - PATH="$VIRTUAL_ENV/bin:$PATH" ./scripts/run-flake8
-
- # Remove every installed files
- - rm -rf "$DESTDIR"
-
- # Test that "git status" looks clean, or print a clear error message
- - |-
- git status --short | sed -n 's/^??/error: missing .gitignore entry for/p' | (! grep '^')
-
- # Clean up everything and show which file would be added to "make clean"
- - make clean distclean $EXPLICIT_MAKE_VARS
- - |-
- git ls-files --ignored --others --exclude-standard | sed 's/^/error: "make clean distclean" did not remove /' | (! grep '^')
+ - FEDORA_MAJOR=33 FEDORA_MINOR=1.2 scripts/ci/travis-kvm-setup.sh
# Do not spam by email so long as the build succeeds
notifications:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a3517cb8..7c548e58 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,7 +26,7 @@ using a custom policy please include it as well.
There are a number of dependencies required to build the userspace
tools/libraries. On a Fedora system you can install them with yum:
- # yum install audit-libs-devel bison bzip2-devel dbus-devel dbus-glib-devel flex flex-devel flex-static glib2-devel libcap-devel libcap-ng-devel pam-devel pcre-devel python-devel setools-devel swig ustr-devel
+ # yum install audit-libs-devel bison bzip2-devel dbus-devel dbus-glib-devel flex flex-devel flex-static glib2-devel libcap-devel libcap-ng-devel pam-devel pcre2-devel python-devel setools-devel swig ustr-devel
The tools and libraries can be built and installed under a private directory from the top level with make, e.g.
diff --git a/Makefile b/Makefile
index 298cd2b7..215e313e 100644
--- a/Makefile
+++ b/Makefile
@@ -9,8 +9,12 @@ ifeq ($(DEBUG),1)
export LDFLAGS = -g
else
export CFLAGS ?= -O2 -Werror -Wall -Wextra \
+ -Wfloat-equal \
+ -Wformat=2 \
+ -Winit-self \
-Wmissing-format-attribute \
-Wmissing-noreturn \
+ -Wnull-dereference \
-Wpointer-arith \
-Wshadow \
-Wstrict-prototypes \
diff --git a/OWNERS b/OWNERS
index cfada96f..df6b25ef 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,3 @@
alanstokes@google.com
jeffv@google.com
-jgalenson@google.com
+tweek@google.com
diff --git a/README b/README
deleted file mode 100644
index e4423ca2..00000000
--- a/README
+++ /dev/null
@@ -1,25 +0,0 @@
-Please submit all bug reports and patches to selinux@vger.kernel.org.
-Subscribe by sending "subscribe selinux" in the body of an email
-to majordomo@vger.kernel.org.
-
-Build dependencies on Fedora:
-yum install audit-libs-devel bison bzip2-devel dbus-devel dbus-glib-devel flex flex-devel flex-static glib2-devel libcap-devel libcap-ng-devel pam-devel pcre-devel python3-devel python3-setools swig xmlto redhat-rpm-config
-
-To build and install everything under a private directory, run:
-make DESTDIR=~/obj install install-pywrap
-
-To install as the default system libraries and binaries
-(overwriting any previously installed ones - dangerous!),
-on x86_64, run:
-make LIBDIR=/usr/lib64 SHLIBDIR=/lib64 install install-pywrap relabel
-or on x86 (32-bit), run:
-make install install-pywrap relabel
-
-This may render your system unusable if the upstream SELinux userspace
-lacks library functions or other dependencies relied upon by your
-distribution. If it breaks, you get to keep both pieces.
-
-To install libsepol on macOS (mainly for policy analysis):
-cd libsepol; make PREFIX=/usr/local install
-
-This requires GNU coreutils (brew install coreutils).
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..74b0a0c3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,146 @@
+SELinux Userspace
+=================
+
+![SELinux logo](https://github.com/SELinuxProject.png)
+[![Run Tests](https://github.com/SELinuxProject/selinux/actions/workflows/run_tests.yml/badge.svg)](https://github.com/SELinuxProject/selinux/actions/workflows/run_tests.yml)
+[![Run SELinux testsuite in a virtual machine](https://github.com/SELinuxProject/selinux/actions/workflows/vm_testsuite.yml/badge.svg)](https://github.com/SELinuxProject/selinux/actions/workflows/vm_testsuite.yml)
+[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/selinux.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#selinux)
+[![CIFuzz Status](https://github.com/SELinuxProject/selinux/actions/workflows/cifuzz.yml/badge.svg)](https://github.com/SELinuxProject/selinux/actions/workflows/cifuzz.yml)
+
+Please submit all bug reports and patches to <selinux@vger.kernel.org>.
+
+Subscribe by sending "subscribe selinux" in the body of an email
+to <majordomo@vger.kernel.org>.
+
+Archive of this mailing list is available on https://lore.kernel.org/selinux/.
+
+
+Installation
+------------
+
+SELinux libraries and tools are packaged in several Linux distributions:
+
+* Alpine Linux (https://pkgs.alpinelinux.org/package/edge/testing/x86/policycoreutils)
+* Arch Linux User Repository (https://aur.archlinux.org/packages/policycoreutils/)
+* Buildroot (https://git.buildroot.net/buildroot/tree/package/policycoreutils)
+* Debian and Ubuntu (https://packages.debian.org/sid/policycoreutils)
+* Gentoo (https://packages.gentoo.org/packages/sys-apps/policycoreutils)
+* RHEL and Fedora (https://src.fedoraproject.org/rpms/policycoreutils)
+* Yocto Project (http://git.yoctoproject.org/cgit/cgit.cgi/meta-selinux/tree/recipes-security/selinux)
+* and many more (https://repology.org/project/policycoreutils/versions)
+
+
+Building and testing
+--------------------
+
+Build dependencies on Fedora:
+
+```sh
+# For C libraries and programs
+dnf install \
+ audit-libs-devel \
+ bison \
+ bzip2-devel \
+ CUnit-devel \
+ diffutils \
+ flex \
+ gcc \
+ gettext \
+ glib2-devel \
+ make \
+ libcap-devel \
+ libcap-ng-devel \
+ pam-devel \
+ pcre2-devel \
+ xmlto
+
+# For Python and Ruby bindings
+dnf install \
+ python3-devel \
+ ruby-devel \
+ swig
+```
+
+Build dependencies on Debian:
+
+```sh
+# For C libraries and programs
+apt-get install --no-install-recommends --no-install-suggests \
+ bison \
+ flex \
+ gawk \
+ gcc \
+ gettext \
+ make \
+ libaudit-dev \
+ libbz2-dev \
+ libcap-dev \
+ libcap-ng-dev \
+ libcunit1-dev \
+ libglib2.0-dev \
+ libpcre2-dev \
+ pkgconf \
+ python3 \
+ python3-distutils \
+ systemd \
+ xmlto
+
+# For Python and Ruby bindings
+apt-get install --no-install-recommends --no-install-suggests \
+ python3-dev \
+ ruby-dev \
+ swig
+```
+
+To build and install everything under a private directory, run:
+
+ make clean distclean
+
+ make DESTDIR=~/obj install install-rubywrap install-pywrap
+
+On Debian `PYTHON_SETUP_ARGS=--install-layout=deb` needs to be set when installing the python wrappers in order to create the correct python directory structure.
+
+To run tests with the built libraries and programs, several paths (relative to `$DESTDIR`) need to be added to variables `$LD_LIBRARY_PATH`, `$PATH` and `$PYTHONPATH`.
+This can be done using [./scripts/env_use_destdir](./scripts/env_use_destdir):
+
+ DESTDIR=~/obj ./scripts/env_use_destdir make test
+
+Some tests require the reference policy to be installed (for example in `python/sepolgen`).
+In order to run these ones, instructions similar to the ones in section `install` of [./.travis.yml](./.travis.yml) can be executed.
+
+To install as the default system libraries and binaries
+(overwriting any previously installed ones - dangerous!),
+on x86_64, run:
+
+ make LIBDIR=/usr/lib64 SHLIBDIR=/lib64 install install-pywrap relabel
+
+or on x86 (32-bit), run:
+
+ make install install-pywrap relabel
+
+This may render your system unusable if the upstream SELinux userspace
+lacks library functions or other dependencies relied upon by your
+distribution. If it breaks, you get to keep both pieces.
+
+
+## Setting CFLAGS
+
+Setting CFLAGS during the make process will cause the omission of many defaults. While the project strives
+to provide a reasonable set of default flags, custom CFLAGS could break the build, or have other undesired
+changes on the build output. Thus, be very careful when setting CFLAGS. CFLAGS that are encouraged to be
+set when overriding are:
+
+- -fno-semantic-interposition for gcc or compilers that do not do this. clang does this by default. clang-10 and up
+ will support passing this flag, but ignore it. Previous clang versions fail.
+
+
+macOS
+-----
+
+To install libsepol on macOS (mainly for policy analysis):
+
+ cd libsepol; make PREFIX=/usr/local install
+
+This requires GNU coreutils:
+
+ brew install coreutils
diff --git a/VERSION b/VERSION
new file mode 100644
index 00000000..eb39e538
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+3.3
diff --git a/checkpolicy/Makefile b/checkpolicy/Makefile
index 0d282ef9..f9e1fc7c 100644
--- a/checkpolicy/Makefile
+++ b/checkpolicy/Makefile
@@ -10,7 +10,7 @@ TARGETS = checkpolicy checkmodule
LEX = flex
YACC = bison -y
-CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -pipe -fno-strict-aliasing
+CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -fno-strict-aliasing
# If no specific libsepol.a is specified, fall back on LDFLAGS search path
# Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there
@@ -30,10 +30,10 @@ all: $(TARGETS)
$(MAKE) -C test
checkpolicy: $(CHECKPOLOBJS) $(LIBSEPOLA)
- $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA)
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA)
checkmodule: $(CHECKMODOBJS) $(LIBSEPOLA)
- $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA)
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA)
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
diff --git a/checkpolicy/VERSION b/checkpolicy/VERSION
index 9f55b2cc..eb39e538 100644
--- a/checkpolicy/VERSION
+++ b/checkpolicy/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/checkpolicy/checkmodule.8 b/checkpolicy/checkmodule.8
index e597d9d4..1061a6f2 100644
--- a/checkpolicy/checkmodule.8
+++ b/checkpolicy/checkmodule.8
@@ -3,7 +3,7 @@
checkmodule \- SELinux policy module compiler
.SH SYNOPSIS
.B checkmodule
-.I "[\-h] [\-b] [\-C] [\-m] [\-M] [\-U handle_unknown ] [\-V] [\-o output_file] [input_file]"
+.I "[\-h] [\-b] [\-c policy_version] [\-C] [\-E] [\-m] [\-M] [\-U handle_unknown] [\-V] [\-o output_file] [input_file]"
.SH "DESCRIPTION"
This manual page describes the
.BR checkmodule
@@ -15,9 +15,12 @@ into a binary representation. It can generate either a base policy
module (default) or a non-base policy module (\-m option); typically,
you would build a non-base policy module to add to an existing module
store that already has a base module provided by the base policy. Use
-semodule_package to combine this module with its optional file
-contexts to create a policy package, and then use semodule to install
-the module package into the module store and load the resulting policy.
+.B semodule_package(8)
+to combine this module with its optional file
+contexts to create a policy package, and then use
+.B semodule(8)
+to install the module package into the module store and load the resulting
+policy.
.SH OPTIONS
.TP
@@ -28,6 +31,9 @@ module file. This option is a development/debugging aid.
.B \-C,\-\-cil
Write CIL policy file rather than binary policy file.
.TP
+.B \-E,\-\-werror
+Treat warnings as errors
+.TP
.B \-h,\-\-help
Print usage.
.TP
@@ -64,6 +70,6 @@ SELinux Reference Policy documentation at https://github.com/SELinuxProject/refp
.SH AUTHOR
This manual page was copied from the checkpolicy man page
-written by Arpad Magosanyi <mag@bunuel.tii.matav.hu>,
+written by Ãrpád Magosányi <mag@bunuel.tii.matav.hu>,
and edited by Dan Walsh <dwalsh@redhat.com>.
The program was written by Stephen Smalley <sds@tycho.nsa.gov>.
diff --git a/checkpolicy/checkmodule.c b/checkpolicy/checkmodule.c
index c9efaf8b..3432608b 100644
--- a/checkpolicy/checkmodule.c
+++ b/checkpolicy/checkmodule.c
@@ -25,7 +25,6 @@
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/hierarchy.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/link.h>
@@ -35,12 +34,10 @@
#include "checkpolicy.h"
#include "parse_util.h"
-extern char *optarg;
-extern int optind;
-
static sidtab_t sidtab;
extern int mlspol;
+extern int werror;
static int handle_unknown = SEPOL_DENY_UNKNOWN;
static const char *txtfile = "policy.conf";
@@ -126,7 +123,7 @@ static int write_binary_policy(policydb_t * p, FILE *outfp)
static __attribute__((__noreturn__)) void usage(const char *progname)
{
- printf("usage: %s [-h] [-V] [-b] [-C] [-U handle_unknown] [-m] [-M] [-o FILE] [INPUT]\n", progname);
+ printf("usage: %s [-h] [-V] [-b] [-C] [-E] [-U handle_unknown] [-m] [-M] [-o FILE] [-c VERSION] [INPUT]\n", progname);
printf("Build base and policy modules.\n");
printf("Options:\n");
printf(" INPUT build module from INPUT (else read from \"%s\")\n",
@@ -134,6 +131,7 @@ static __attribute__((__noreturn__)) void usage(const char *progname)
printf(" -V show policy versions created by this program\n");
printf(" -b treat input as a binary policy file\n");
printf(" -C output CIL policy instead of binary policy\n");
+ printf(" -E treat warnings as errors\n");
printf(" -h print usage\n");
printf(" -U OPTION How to handle unknown classes and permissions\n");
printf(" deny: Deny unknown kernel checks\n");
@@ -154,7 +152,7 @@ int main(int argc, char **argv)
int ch;
int show_version = 0;
policydb_t modpolicydb;
- struct option long_options[] = {
+ const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"output", required_argument, NULL, 'o'},
{"binary", no_argument, NULL, 'b'},
@@ -162,10 +160,11 @@ int main(int argc, char **argv)
{"handle-unknown", required_argument, NULL, 'U'},
{"mls", no_argument, NULL, 'M'},
{"cil", no_argument, NULL, 'C'},
+ {"werror", no_argument, NULL, 'E'},
{NULL, 0, NULL, 0}
};
- while ((ch = getopt_long(argc, argv, "ho:bVU:mMCc:", long_options, NULL)) != -1) {
+ while ((ch = getopt_long(argc, argv, "ho:bVEU:mMCc:", long_options, NULL)) != -1) {
switch (ch) {
case 'h':
usage(argv[0]);
@@ -180,6 +179,9 @@ int main(int argc, char **argv)
case 'V':
show_version = 1;
break;
+ case 'E':
+ werror = 1;
+ break;
case 'U':
if (!strcasecmp(optarg, "deny")) {
handle_unknown = DENY_UNKNOWN;
@@ -266,7 +268,7 @@ int main(int argc, char **argv)
} else {
if (policydb_init(&modpolicydb)) {
fprintf(stderr, "%s: out of memory!\n", argv[0]);
- return -1;
+ exit(1);
}
modpolicydb.policy_type = policy_type;
@@ -278,19 +280,21 @@ int main(int argc, char **argv)
}
if (hierarchy_check_constraints(NULL, &modpolicydb)) {
- return -1;
+ exit(1);
}
}
if (policy_type != POLICY_BASE && outfile) {
+ char *out_name;
+ char *separator;
char *mod_name = modpolicydb.name;
char *out_path = strdup(outfile);
if (out_path == NULL) {
fprintf(stderr, "%s: out of memory\n", argv[0]);
exit(1);
}
- char *out_name = basename(out_path);
- char *separator = strrchr(out_name, '.');
+ out_name = basename(out_path);
+ separator = strrchr(out_name, '.');
if (separator) {
*separator = '\0';
}
@@ -329,7 +333,7 @@ int main(int argc, char **argv)
FILE *outfp = fopen(outfile, "w");
if (!outfp) {
- perror(outfile);
+ fprintf(stderr, "%s: error opening %s: %s\n", argv[0], outfile, strerror(errno));
exit(1);
}
@@ -345,7 +349,10 @@ int main(int argc, char **argv)
}
}
- fclose(outfp);
+ if (fclose(outfp)) {
+ fprintf(stderr, "%s: error closing %s: %s\n", argv[0], outfile, strerror(errno));
+ exit(1);
+ }
} else if (cil) {
fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]);
exit(1);
diff --git a/checkpolicy/checkpolicy.8 b/checkpolicy/checkpolicy.8
index 97e10ca7..2984c238 100644
--- a/checkpolicy/checkpolicy.8
+++ b/checkpolicy/checkpolicy.8
@@ -3,7 +3,7 @@
checkpolicy \- SELinux policy compiler
.SH SYNOPSIS
.B checkpolicy
-.I "[\-b[F]] [\-C] [\-d] [\-U handle_unknown (allow,deny,reject)] [\-M] [\-c policyvers] [\-o output_file|\-] [\-S] [\-t target_platform (selinux,xen)] [\-V] [input_file]"
+.I "[\-b[F]] [\-C] [\-d] [\-U handle_unknown (allow,deny,reject)] [\-M] [\-c policyvers] [\-o output_file|\-] [\-S] [\-t target_platform (selinux,xen)] [\-O] [\-E] [\-V] [input_file]"
.br
.SH "DESCRIPTION"
This manual page describes the
@@ -13,8 +13,10 @@ command.
.B checkpolicy
is a program that checks and compiles a SELinux security policy configuration
into a binary representation that can be loaded into the kernel. If no
-input file name is specified, checkpolicy will attempt to read from
-policy.conf or policy, depending on whether the \-b flag is specified.
+input file name is specified,
+.B checkpolicy
+will attempt to read from policy.conf or policy, depending on whether the \-b
+flag is specified.
.SH OPTIONS
.TP
@@ -53,6 +55,9 @@ Specify the target platform (selinux or xen).
.B \-O,\-\-optimize
Optimize the final kernel policy (remove redundant rules).
.TP
+.B \-E,\-\-werror
+Treat warnings as errors
+.TP
.B \-V,\-\-version
Show version information.
.TP
@@ -64,6 +69,6 @@ SELinux Reference Policy documentation at https://github.com/SELinuxProject/refp
.SH AUTHOR
-This manual page was written by Arpad Magosanyi <mag@bunuel.tii.matav.hu>,
+This manual page was written by Ãrpád Magosányi <mag@bunuel.tii.matav.hu>,
and edited by Stephen Smalley <sds@tycho.nsa.gov>.
The program was written by Stephen Smalley <sds@tycho.nsa.gov>.
diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c
index 7c5b63f8..926ce72c 100644
--- a/checkpolicy/checkpolicy.c
+++ b/checkpolicy/checkpolicy.c
@@ -85,7 +85,6 @@
#include <sepol/policydb/services.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/hierarchy.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/link.h>
@@ -93,37 +92,38 @@
#include "checkpolicy.h"
#include "parse_util.h"
-extern char *optarg;
-extern int optind;
-
static policydb_t policydb;
static sidtab_t sidtab;
extern policydb_t *policydbp;
extern int mlspol;
+extern int werror;
static int handle_unknown = SEPOL_DENY_UNKNOWN;
static const char *txtfile = "policy.conf";
static const char *binfile = "policy";
-unsigned int policyvers = POLICYDB_VERSION_MAX;
+unsigned int policyvers = 0;
static __attribute__((__noreturn__)) void usage(const char *progname)
{
printf
("usage: %s [-b[F]] [-C] [-d] [-U handle_unknown (allow,deny,reject)] [-M] "
- "[-c policyvers (%d-%d)] [-o output_file|-] [-S] "
- "[-t target_platform (selinux,xen)] [-V] [input_file]\n",
+ "[-c policyvers (%d-%d)] [-o output_file|-] [-S] [-O] "
+ "[-t target_platform (selinux,xen)] [-E] [-V] [input_file]\n",
progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
exit(1);
}
#define FGETS(out, size, in) \
-if (fgets(out,size,in)==NULL) { \
- fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,\
- strerror(errno)); \
- exit(1);\
-}
+do { \
+ if (fgets(out,size,in)==NULL) { \
+ fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, \
+ strerror(errno)); \
+ exit(1);\
+ } \
+} while (0)
+
static int print_sid(sepol_security_id_t sid,
context_struct_t * context
__attribute__ ((unused)), void *data
@@ -294,9 +294,7 @@ static int identify_equiv_types(void)
}
#endif
-extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av);
-
-int display_bools(void)
+static int display_bools(void)
{
uint32_t i;
@@ -307,10 +305,10 @@ int display_bools(void)
return 0;
}
-void display_expr(cond_expr_t * exp)
+static void display_expr(const cond_expr_t * exp)
{
- cond_expr_t *cur;
+ const cond_expr_t *cur;
for (cur = exp; cur != NULL; cur = cur->next) {
switch (cur->expr_type) {
case COND_BOOL:
@@ -342,9 +340,9 @@ void display_expr(cond_expr_t * exp)
}
}
-int display_cond_expressions(void)
+static int display_cond_expressions(void)
{
- cond_node_t *cur;
+ const cond_node_t *cur;
for (cur = policydbp->cond_list; cur != NULL; cur = cur->next) {
printf("expression: ");
@@ -354,7 +352,7 @@ int display_cond_expressions(void)
return 0;
}
-int change_bool(char *name, int state)
+static int change_bool(const char *name, int state)
{
cond_bool_datum_t *bool;
@@ -409,7 +407,7 @@ int main(int argc, char **argv)
unsigned int reason;
int flags;
struct policy_file pf;
- struct option long_options[] = {
+ const struct option long_options[] = {
{"output", required_argument, NULL, 'o'},
{"target", required_argument, NULL, 't'},
{"binary", no_argument, NULL, 'b'},
@@ -421,11 +419,12 @@ int main(int argc, char **argv)
{"conf",no_argument, NULL, 'F'},
{"sort", no_argument, NULL, 'S'},
{"optimize", no_argument, NULL, 'O'},
+ {"werror", no_argument, NULL, 'E'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
- while ((ch = getopt_long(argc, argv, "o:t:dbU:MCFSVc:Oh", long_options, NULL)) != -1) {
+ while ((ch = getopt_long(argc, argv, "o:t:dbU:MCFSVc:OEh", long_options, NULL)) != -1) {
switch (ch) {
case 'o':
outfile = optarg;
@@ -500,10 +499,12 @@ int main(int argc, char **argv)
usage(argv[0]);
exit(1);
}
- if (policyvers != n)
- policyvers = n;
+ policyvers = n;
break;
}
+ case 'E':
+ werror = 1;
+ break;
case 'h':
default:
usage(argv[0]);
@@ -511,7 +512,8 @@ int main(int argc, char **argv)
}
if (show_version) {
- printf("%d (compatibility range %d-%d)\n", policyvers,
+ printf("%d (compatibility range %d-%d)\n",
+ policyvers ? policyvers : POLICYDB_VERSION_MAX ,
POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN);
exit(0);
}
@@ -584,6 +586,16 @@ int main(int argc, char **argv)
exit(1);
}
}
+
+ if (policydbp->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ if (policyvers > policydbp->policyvers) {
+ fprintf(stderr, "Binary policies with version <= %u cannot be upgraded\n", POLICYDB_VERSION_PERMISSIVE);
+ } else if (policyvers) {
+ policydbp->policyvers = policyvers;
+ }
+ } else {
+ policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX;
+ }
} else {
if (conf) {
fprintf(stderr, "Can only generate policy.conf from binary policy\n");
@@ -625,6 +637,8 @@ int main(int argc, char **argv)
policydb_destroy(policydbp);
policydbp = &policydb;
}
+
+ policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX;
}
if (policydb_load_isids(&policydb, &sidtab))
@@ -650,8 +664,6 @@ int main(int argc, char **argv)
}
}
- policydb.policyvers = policyvers;
-
if (!cil) {
if (!conf) {
policydb.policy_type = POLICY_KERN;
@@ -689,7 +701,10 @@ int main(int argc, char **argv)
}
if (outfp != stdout) {
- fclose(outfp);
+ if(fclose(outfp)) {
+ fprintf(stderr, "%s: error closing %s: %s\n", argv[0], outfile, strerror(errno));
+ exit(1);
+ }
}
} else if (cil) {
fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]);
@@ -779,7 +794,7 @@ int main(int argc, char **argv)
case 0:
printf("\nallowed {");
for (i = 1; i <= sizeof(avd.allowed) * 8; i++) {
- if (avd.allowed & (1 << (i - 1))) {
+ if (avd.allowed & (UINT32_C(1) << (i - 1))) {
v.val = i;
ret =
hashtab_map(cladatum->
@@ -953,8 +968,12 @@ int main(int argc, char **argv)
printf("fs kdevname? ");
FGETS(ans, sizeof(ans), stdin);
ans[strlen(ans) - 1] = 0;
- sepol_fs_sid(ans, &ssid, &tsid);
- printf("fs_sid %d default_file_sid %d\n", ssid, tsid);
+ ret = sepol_fs_sid(ans, &ssid, &tsid);
+ if (ret) {
+ printf("unknown fs kdevname\n");
+ } else {
+ printf("fs_sid %d default_file_sid %d\n", ssid, tsid);
+ }
break;
case '9':
printf("protocol? ");
@@ -982,8 +1001,12 @@ int main(int argc, char **argv)
printf("netif name? ");
FGETS(ans, sizeof(ans), stdin);
ans[strlen(ans) - 1] = 0;
- sepol_netif_sid(ans, &ssid, &tsid);
- printf("if_sid %d default_msg_sid %d\n", ssid, tsid);
+ ret = sepol_netif_sid(ans, &ssid, &tsid);
+ if (ret) {
+ printf("unknown name\n");
+ } else {
+ printf("if_sid %d default_msg_sid %d\n", ssid, tsid);
+ }
break;
case 'b':{
char *p;
@@ -1162,8 +1185,6 @@ int main(int argc, char **argv)
printf("\nNo such class.\n");
break;
}
- cladatum =
- policydb.class_val_to_struct[tclass - 1];
} else {
ans[strlen(ans) - 1] = 0;
cladatum =
@@ -1215,8 +1236,6 @@ int main(int argc, char **argv)
printf("\nNo such class.\n");
break;
}
- cladatum =
- policydb.class_val_to_struct[tclass - 1];
} else {
ans[strlen(ans) - 1] = 0;
cladatum =
diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c
index ada7cb2a..129650fa 100644
--- a/checkpolicy/module_compiler.c
+++ b/checkpolicy/module_compiler.c
@@ -99,6 +99,7 @@ int define_policy(int pass, int module_header_given)
yyerror("no module name");
return -1;
}
+ free(policydbp->name);
policydbp->name = id;
if ((policydbp->version =
queue_remove(id_queue)) == NULL) {
@@ -165,7 +166,7 @@ static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_
decl->decl_id, dest_value);
if (ret == 1 && dest_value) {
- symtab_datum_t *s =
+ hashtab_datum_t s =
hashtab_search(policydbp->symtab[symbol_type].table,
key);
assert(s != NULL);
@@ -173,7 +174,7 @@ static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_
if (symbol_type == SYM_LEVELS) {
*dest_value = ((level_datum_t *)s)->level->sens;
} else {
- *dest_value = s->value;
+ *dest_value = ((symtab_datum_t *)s)->value;
}
} else if (ret == -2) {
return -2;
@@ -999,7 +1000,7 @@ static int require_bool_tunable(int pass, int is_tunable)
if (is_tunable)
booldatum->flags |= COND_BOOL_FLAGS_TUNABLE;
retval =
- require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum,
+ require_symbol(SYM_BOOLS, id, booldatum,
&booldatum->s.value, &booldatum->s.value);
if (retval != 0) {
cond_destroy_bool(id, booldatum, NULL);
@@ -1051,7 +1052,7 @@ int require_sens(int pass)
return -1;
}
mls_level_init(level->level);
- retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level,
+ retval = require_symbol(SYM_LEVELS, id, level,
&level->level->sens, &level->level->sens);
if (retval != 0) {
free(id);
@@ -1089,7 +1090,7 @@ int require_cat(int pass)
}
cat_datum_init(cat);
- retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat,
+ retval = require_symbol(SYM_CATS, id, cat,
&cat->s.value, &cat->s.value);
if (retval != 0) {
free(id);
@@ -1104,14 +1105,14 @@ int require_cat(int pass)
return 0;
}
-static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
+static int is_scope_in_stack(const scope_datum_t * scope, const scope_stack_t * stack)
{
uint32_t i;
if (stack == NULL) {
return 0; /* no matching scope found */
}
if (stack->type == 1) {
- avrule_decl_t *decl = stack->decl;
+ const avrule_decl_t *decl = stack->decl;
for (i = 0; i < scope->decl_ids_len; i++) {
if (scope->decl_ids[i] == decl->decl_id) {
return 1;
@@ -1126,9 +1127,9 @@ static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
return is_scope_in_stack(scope, stack->parent);
}
-int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
+int is_id_in_scope(uint32_t symbol_type, const_hashtab_key_t id)
{
- scope_datum_t *scope =
+ const scope_datum_t *scope =
(scope_datum_t *) hashtab_search(policydbp->scope[symbol_type].
table, id);
if (scope == NULL) {
@@ -1138,7 +1139,7 @@ int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
}
static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
- scope_index_t * scope)
+ const scope_index_t * scope)
{
if (class_value > scope->class_perms_len) {
return 1;
@@ -1151,7 +1152,7 @@ static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
}
static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
- scope_stack_t * stack)
+ const scope_stack_t * stack)
{
if (stack == NULL) {
return 0; /* no matching scope found */
@@ -1173,12 +1174,12 @@ static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
return is_perm_in_stack(perm_value, class_value, stack->parent);
}
-int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id)
+int is_perm_in_scope(const_hashtab_key_t perm_id, const_hashtab_key_t class_id)
{
- class_datum_t *cladatum =
+ const class_datum_t *cladatum =
(class_datum_t *) hashtab_search(policydbp->p_classes.table,
class_id);
- perm_datum_t *perdatum;
+ const perm_datum_t *perdatum;
if (cladatum == NULL) {
return 1;
}
@@ -1361,17 +1362,17 @@ int begin_optional_else(int pass)
return 0;
}
-static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
+static int copy_requirements(avrule_decl_t * dest, const scope_stack_t * stack)
{
uint32_t i;
if (stack == NULL) {
return 0;
}
if (stack->type == 1) {
- scope_index_t *src_scope = &stack->decl->required;
+ const scope_index_t *src_scope = &stack->decl->required;
scope_index_t *dest_scope = &dest->required;
for (i = 0; i < SYM_NUM; i++) {
- ebitmap_t *src_bitmap = &src_scope->scope[i];
+ const ebitmap_t *src_bitmap = &src_scope->scope[i];
ebitmap_t *dest_bitmap = &dest_scope->scope[i];
if (ebitmap_union(dest_bitmap, src_bitmap)) {
yyerror("Out of memory!");
@@ -1397,7 +1398,7 @@ static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack)
src_scope->class_perms_len;
}
for (i = 0; i < src_scope->class_perms_len; i++) {
- ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
+ const ebitmap_t *src_bitmap = &src_scope->class_perms_map[i];
ebitmap_t *dest_bitmap =
&dest_scope->class_perms_map[i];
if (ebitmap_union(dest_bitmap, src_bitmap)) {
diff --git a/checkpolicy/module_compiler.h b/checkpolicy/module_compiler.h
index 72c2d9bb..29b824b4 100644
--- a/checkpolicy/module_compiler.h
+++ b/checkpolicy/module_compiler.h
@@ -65,12 +65,12 @@ int require_cat(int pass);
/* Check if an identifier is within the scope of the current
* declaration or any of its parents. Return 1 if it is, 0 if not.
* If the identifier is not known at all then return 1 (truth). */
-int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id);
+int is_id_in_scope(uint32_t symbol_type, const_hashtab_key_t id);
/* Check if a particular permission is within the scope of the current
* declaration or any of its parents. Return 1 if it is, 0 if not.
* If the identifier is not known at all then return 1 (truth). */
-int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id);
+int is_perm_in_scope(const_hashtab_key_t perm_id, const_hashtab_key_t class_id);
/* Search the current avrules block for a conditional with the same
* expression as 'cond'. If the conditional does not exist then
diff --git a/checkpolicy/parse_util.c b/checkpolicy/parse_util.c
index f2809b48..f2d1e04d 100644
--- a/checkpolicy/parse_util.c
+++ b/checkpolicy/parse_util.c
@@ -28,7 +28,6 @@ extern int yyparse(void);
extern void yyrestart(FILE *);
extern queue_t id_queue;
extern unsigned int policydb_errors;
-extern unsigned long policydb_lineno;
extern policydb_t *policydbp;
extern int mlspol;
extern void set_source_file(const char *name);
@@ -37,7 +36,7 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname)
{
yyin = fopen(file, "r");
if (!yyin) {
- fprintf(stderr, "%s: unable to open %s\n", progname, file);
+ fprintf(stderr, "%s: unable to open %s: %s\n", progname, file, strerror(errno));
return -1;
}
set_source_file(file);
@@ -48,6 +47,7 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname)
}
policydbp = p;
+ policydbp->name = strdup(file);
mlspol = p->mls;
init_parser(1);
diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index e295bc52..16b78346 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -53,7 +53,6 @@
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/hierarchy.h>
#include <sepol/policydb/polcaps.h>
#include "queue.h"
@@ -61,10 +60,13 @@
#include "module_compiler.h"
#include "policy_define.h"
+extern void init_parser(int pass_number);
+__attribute__ ((format(printf, 1, 2)))
+extern void yyerror2(const char *fmt, ...);
+
policydb_t *policydbp;
queue_t id_queue = 0;
unsigned int pass;
-char *curfile = 0;
int mlspol = 0;
extern unsigned long policydb_lineno;
@@ -75,12 +77,6 @@ extern char source_file[PATH_MAX];
extern int yywarn(const char *msg);
extern int yyerror(const char *msg);
-#define ERRORMSG_LEN 255
-static char errormsg[ERRORMSG_LEN + 1] = {0};
-
-static int id_has_dot(char *id);
-static int parse_security_context(context_struct_t *c);
-
/* initialize all of the state variables for the scanner/parser */
void init_parser(int pass_number)
{
@@ -90,12 +86,12 @@ void init_parser(int pass_number)
pass = pass_number;
}
-__attribute__ ((format(printf, 1, 2)))
void yyerror2(const char *fmt, ...)
{
+ char errormsg[256];
va_list ap;
va_start(ap, fmt);
- vsnprintf(errormsg, ERRORMSG_LEN, fmt, ap);
+ vsnprintf(errormsg, sizeof(errormsg), fmt, ap);
yyerror(errormsg);
va_end(ap);
}
@@ -142,7 +138,7 @@ int insert_id(const char *id, int push)
/* If the identifier has a dot within it and that its first character
is not a dot then return 1, else return 0. */
-static int id_has_dot(char *id)
+static int id_has_dot(const char *id)
{
if (strchr(id, '.') >= id + 1) {
return 1;
@@ -1169,11 +1165,6 @@ int expand_attrib(void)
ebitmap_init(&attrs);
while ((id = queue_remove(id_queue))) {
- if (!id) {
- yyerror("No attribute name for expandattribute statement?");
- goto exit;
- }
-
if (!is_id_in_scope(SYM_TYPES, id)) {
yyerror2("attribute %s is not within scope", id);
goto exit;
@@ -1611,7 +1602,7 @@ static int set_types(type_set_t * set, char *id, int *add, char starallowed)
return -1;
}
-int define_compute_type_helper(int which, avrule_t ** rule)
+static int define_compute_type_helper(int which, avrule_t ** rule)
{
char *id;
type_datum_t *datum;
@@ -1802,7 +1793,7 @@ int define_bool_tunable(int is_tunable)
return -1;
}
- datum->state = (int)(bool_value[0] == 'T') ? 1 : 0;
+ datum->state = (bool_value[0] == 'T') ? 1 : 0;
free(bool_value);
return 0;
cleanup:
@@ -1838,7 +1829,7 @@ struct av_ioctl_range_list {
struct av_ioctl_range_list *next;
};
-int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead)
+static int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_ioctl_range_list *r, *r2, *sorted, *sortedhead = NULL;
@@ -1886,7 +1877,7 @@ error:
return -1;
}
-int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
+static int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_ioctl_range_list *r, *tmp;
r = *rangehead;
@@ -1906,13 +1897,14 @@ int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
return 0;
}
-int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
+static int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
{
char *id;
struct av_ioctl_range_list *rnew, *r = NULL;
- *rangehead = NULL;
uint8_t omit = 0;
+ *rangehead = NULL;
+
/* read in all the ioctl commands */
while ((id = queue_remove(id_queue))) {
if (strcmp(id,"~") == 0) {
@@ -1948,7 +1940,9 @@ int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
}
}
r = *rangehead;
- r->omit = omit;
+ if (r) {
+ r->omit = omit;
+ }
return 0;
error:
yyerror("out of memory");
@@ -1956,7 +1950,7 @@ error:
}
/* flip to included ranges */
-int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead)
+static int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_ioctl_range_list *rnew, *r, *newhead, *r2;
@@ -2004,7 +1998,7 @@ error:
return -1;
}
-int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
+static int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
{
struct av_ioctl_range_list *rangehead;
uint8_t omit;
@@ -2032,7 +2026,7 @@ int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
return 0;
}
-int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
+static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
{
char *id;
class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
@@ -2132,7 +2126,7 @@ int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
policydbp->p_class_val_to_name[i]);
continue;
} else {
- cur_perms->data |= 1U << (perdatum->s.value - 1);
+ cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1);
}
}
@@ -2146,14 +2140,14 @@ out:
}
/* index of the u32 containing the permission */
-#define XPERM_IDX(x) (x >> 5)
+#define XPERM_IDX(x) ((x) >> 5)
/* set bits 0 through x-1 within the u32 */
-#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1)
+#define XPERM_SETBITS(x) ((UINT32_C(1) << ((x) & 0x1f)) - 1)
/* low value for this u32 */
-#define XPERM_LOW(x) (x << 5)
+#define XPERM_LOW(x) ((x) << 5)
/* high value for this u32 */
-#define XPERM_HIGH(x) (((x + 1) << 5) - 1)
-void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
+#define XPERM_HIGH(x) ((((x) + 1) << 5) - 1)
+static void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
av_extended_perms_t *xperms)
{
unsigned int i;
@@ -2175,7 +2169,7 @@ void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
}
}
-int avrule_xperms_used(av_extended_perms_t *xperms)
+static int avrule_xperms_used(const av_extended_perms_t *xperms)
{
unsigned int i;
@@ -2192,10 +2186,10 @@ int avrule_xperms_used(av_extended_perms_t *xperms)
* dir, size, driver, and function. Only the driver and function fields
* are considered here
*/
-#define IOC_DRIV(x) (x >> 8)
-#define IOC_FUNC(x) (x & 0xff)
-#define IOC_CMD(driver, func) ((driver << 8) + func)
-int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
+#define IOC_DRIV(x) ((x) >> 8)
+#define IOC_FUNC(x) ((x) & 0xff)
+#define IOC_CMD(driver, func) (((driver) << 8) + (func))
+static int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
av_extended_perms_t *complete_driver,
av_extended_perms_t **extended_perms)
{
@@ -2234,7 +2228,7 @@ int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
}
-int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
+static int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
av_extended_perms_t **extended_perms)
{
struct av_ioctl_range_list *r;
@@ -2276,7 +2270,7 @@ int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
return 0;
}
-int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
+static int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
av_extended_perms_t **extended_perms, unsigned int driver)
{
struct av_ioctl_range_list *r;
@@ -2326,18 +2320,7 @@ int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
return 0;
}
-void avrule_ioctl_freeranges(struct av_ioctl_range_list *rangelist)
-{
- struct av_ioctl_range_list *r, *tmp;
- r = rangelist;
- while (r) {
- tmp = r;
- r = r->next;
- free(tmp);
- }
-}
-
-unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
+static unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
{
unsigned int i;
for (i = *bit; i < sizeof(xperms->perms)*8; i++) {
@@ -2350,7 +2333,7 @@ unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
return 0;
}
-int avrule_cpy(avrule_t *dest, avrule_t *src)
+static int avrule_cpy(avrule_t *dest, const avrule_t *src)
{
class_perm_node_t *src_perms;
class_perm_node_t *dest_perms, *dest_tail;
@@ -2398,10 +2381,10 @@ int avrule_cpy(avrule_t *dest, avrule_t *src)
return 0;
}
-int define_te_avtab_ioctl(avrule_t *avrule_template)
+static int define_te_avtab_ioctl(const avrule_t *avrule_template)
{
avrule_t *avrule;
- struct av_ioctl_range_list *rangelist;
+ struct av_ioctl_range_list *rangelist, *r;
av_extended_perms_t *complete_driver, *partial_driver, *xperms;
unsigned int i;
@@ -2459,6 +2442,12 @@ done:
if (partial_driver)
free(partial_driver);
+ while (rangelist != NULL) {
+ r = rangelist;
+ rangelist = rangelist->next;
+ free(r);
+ }
+
return 0;
}
@@ -2467,6 +2456,7 @@ int define_te_avtab_extended_perms(int which)
char *id;
unsigned int i;
avrule_t *avrule_template;
+ int rc = 0;
if (pass == 1) {
for (i = 0; i < 4; i++) {
@@ -2482,18 +2472,20 @@ int define_te_avtab_extended_perms(int which)
id = queue_remove(id_queue);
if (strcmp(id,"ioctl") == 0) {
- free(id);
- if (define_te_avtab_ioctl(avrule_template))
- return -1;
+ rc = define_te_avtab_ioctl(avrule_template);
} else {
yyerror("only ioctl extended permissions are supported");
- free(id);
- return -1;
+ rc = -1;
}
- return 0;
+
+ free(id);
+ avrule_destroy(avrule_template);
+ free(avrule_template);
+
+ return rc;
}
-int define_te_avtab_helper(int which, avrule_t ** rule)
+static int define_te_avtab_helper(int which, avrule_t ** rule)
{
char *id;
class_datum_t *cladatum;
@@ -2620,7 +2612,7 @@ int define_te_avtab_helper(int which, avrule_t ** rule)
}
continue;
} else {
- cur_perms->data |= 1U << (perdatum->s.value - 1);
+ cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1);
}
next:
cur_perms = cur_perms->next;
@@ -3304,8 +3296,6 @@ int define_filename_trans(void)
ebitmap_t e_stypes, e_ttypes;
ebitmap_t e_tclasses;
ebitmap_node_t *snode, *tnode, *cnode;
- filename_trans_t *ft;
- filename_trans_datum_t *ftdatum;
filename_trans_rule_t *ftr;
type_datum_t *typdatum;
uint32_t otype;
@@ -3389,40 +3379,19 @@ int define_filename_trans(void)
ebitmap_for_each_positive_bit(&e_tclasses, cnode, c) {
ebitmap_for_each_positive_bit(&e_stypes, snode, s) {
ebitmap_for_each_positive_bit(&e_ttypes, tnode, t) {
- ft = calloc(1, sizeof(*ft));
- if (!ft) {
- yyerror("out of memory");
- goto bad;
- }
- ft->stype = s+1;
- ft->ttype = t+1;
- ft->tclass = c+1;
- ft->name = strdup(name);
- if (!ft->name) {
- yyerror("out of memory");
- goto bad;
- }
-
- ftdatum = hashtab_search(policydbp->filename_trans,
- (hashtab_key_t)ft);
- if (ftdatum) {
- yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
- name,
- policydbp->p_type_val_to_name[s],
- policydbp->p_type_val_to_name[t],
- policydbp->p_class_val_to_name[c]);
- goto bad;
- }
-
- ftdatum = calloc(1, sizeof(*ftdatum));
- if (!ftdatum) {
- yyerror("out of memory");
- goto bad;
- }
- rc = hashtab_insert(policydbp->filename_trans,
- (hashtab_key_t)ft,
- ftdatum);
- if (rc) {
+ rc = policydb_filetrans_insert(
+ policydbp, s+1, t+1, c+1, name,
+ NULL, otype, NULL
+ );
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
+ name,
+ policydbp->p_type_val_to_name[s],
+ policydbp->p_type_val_to_name[t],
+ policydbp->p_class_val_to_name[c]);
+ goto bad;
+ }
yyerror("out of memory");
goto bad;
}
@@ -3470,9 +3439,10 @@ bad:
return -1;
}
-static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr)
+static constraint_expr_t *constraint_expr_clone(const constraint_expr_t * expr)
{
- constraint_expr_t *h = NULL, *l = NULL, *e, *newe;
+ constraint_expr_t *h = NULL, *l = NULL, *newe;
+ const constraint_expr_t *e;
for (e = expr; e; e = e->next) {
newe = malloc(sizeof(*newe));
if (!newe)
@@ -3503,15 +3473,12 @@ static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr)
return h;
oom:
- e = h;
- while (e) {
- l = e;
- e = e->next;
- constraint_expr_destroy(l);
- }
+ constraint_expr_destroy(h);
return NULL;
}
+#define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1))
+
int define_constraint(constraint_expr_t * expr)
{
struct constraint_node *node;
@@ -3625,6 +3592,22 @@ int define_constraint(constraint_expr_t * expr)
cladatum = policydbp->class_val_to_struct[i];
node = cladatum->constraints;
+ if (strcmp(id, "*") == 0) {
+ node->permissions = PERMISSION_MASK(cladatum->permissions.nprim);
+ continue;
+ }
+
+ if (strcmp(id, "~") == 0) {
+ node->permissions = ~node->permissions & PERMISSION_MASK(cladatum->permissions.nprim);
+ if (node->permissions == 0) {
+ yywarn("omitting constraint with no permission set");
+ cladatum->constraints = node->next;
+ constraint_expr_destroy(node->expr);
+ free(node);
+ }
+ continue;
+ }
+
perdatum =
(perm_datum_t *) hashtab_search(cladatum->
permissions.
@@ -3650,7 +3633,7 @@ int define_constraint(constraint_expr_t * expr)
return -1;
}
}
- node->permissions |= (1 << (perdatum->s.value - 1));
+ node->permissions |= (UINT32_C(1) << (perdatum->s.value - 1));
}
free(id);
}
@@ -4117,8 +4100,6 @@ cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void *arg2)
static int set_user_roles(role_set_t * set, char *id)
{
role_datum_t *r;
- unsigned int i;
- ebitmap_node_t *node;
if (strcmp(id, "*") == 0) {
free(id);
@@ -4144,12 +4125,9 @@ static int set_user_roles(role_set_t * set, char *id)
return -1;
}
- /* set the role and every role it dominates */
- ebitmap_for_each_positive_bit(&r->dominates, node, i) {
- if (ebitmap_set_bit(&set->roles, i, TRUE))
- goto oom;
- }
free(id);
+ if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE))
+ goto oom;
return 0;
oom:
yyerror("out of memory");
@@ -5330,6 +5308,14 @@ int define_ipv4_node_context()
goto out;
}
+ if (mask.s_addr != 0 && ((~mask.s_addr + 1) & ~mask.s_addr) != 0) {
+ yywarn("ipv4 mask is not contiguous");
+ }
+
+ if ((~mask.s_addr & addr.s_addr) != 0) {
+ yywarn("host bits in ipv4 address set");
+ }
+
newc = malloc(sizeof(ocontext_t));
if (!newc) {
yyerror("out of memory");
@@ -5365,6 +5351,40 @@ out:
return rc;
}
+static int ipv6_is_mask_contiguous(const struct in6_addr *mask)
+{
+ int filled = 1;
+ unsigned i;
+
+ for (i = 0; i < 16; i++) {
+ if ((((~mask->s6_addr[i] & 0xFF) + 1) & (~mask->s6_addr[i] & 0xFF)) != 0) {
+ return 0;
+ }
+ if (!filled && mask->s6_addr[i] != 0) {
+ return 0;
+ }
+
+ if (filled && mask->s6_addr[i] != 0xFF) {
+ filled = 0;
+ }
+ }
+
+ return 1;
+}
+
+static int ipv6_has_host_bits_set(const struct in6_addr *addr, const struct in6_addr *mask)
+{
+ unsigned i;
+
+ for (i = 0; i < 16; i++) {
+ if ((addr->s6_addr[i] & ~mask->s6_addr[i]) != 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
int define_ipv6_node_context(void)
{
char *id;
@@ -5416,6 +5436,14 @@ int define_ipv6_node_context(void)
goto out;
}
+ if (!ipv6_is_mask_contiguous(&mask)) {
+ yywarn("ipv6 mask is not contiguous");
+ }
+
+ if (ipv6_has_host_bits_set(&addr, &mask)) {
+ yywarn("host bits in ipv6 address set");
+ }
+
newc = malloc(sizeof(ocontext_t));
if (!newc) {
yyerror("out of memory");
@@ -5505,11 +5533,13 @@ int define_fs_use(int behavior)
return 0;
}
-int define_genfs_context_helper(char *fstype, int has_type)
+static int define_genfs_context_helper(char *fstype, int has_type)
{
struct genfs *genfs_p, *genfs, *newgenfs;
ocontext_t *newc, *c, *head, *p;
+ class_datum_t *cladatum;
char *type = NULL;
+ const char *sclass;
int len, len2;
if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
@@ -5571,30 +5601,39 @@ int define_genfs_context_helper(char *fstype, int has_type)
}
switch (type[0]) {
case 'b':
- newc->v.sclass = SECCLASS_BLK_FILE;
+ sclass = "blk_file";
break;
case 'c':
- newc->v.sclass = SECCLASS_CHR_FILE;
+ sclass = "chr_file";
break;
case 'd':
- newc->v.sclass = SECCLASS_DIR;
+ sclass = "dir";
break;
case 'p':
- newc->v.sclass = SECCLASS_FIFO_FILE;
+ sclass = "fifo_file";
break;
case 'l':
- newc->v.sclass = SECCLASS_LNK_FILE;
+ sclass = "lnk_file";
break;
case 's':
- newc->v.sclass = SECCLASS_SOCK_FILE;
+ sclass = "sock_file";
break;
case '-':
- newc->v.sclass = SECCLASS_FILE;
+ sclass = "file";
break;
default:
yyerror2("invalid type %s", type);
goto fail;
}
+
+ cladatum = hashtab_search(policydbp->p_classes.table,
+ sclass);
+ if (!cladatum) {
+ yyerror2("could not find class %s for "
+ "genfscon statement", sclass);
+ goto fail;
+ }
+ newc->v.sclass = cladatum->s.value;
}
if (parse_security_context(&newc->context[0]))
goto fail;
diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y
index abb7d885..45f973ff 100644
--- a/checkpolicy/policy_parse.y
+++ b/checkpolicy/policy_parse.y
@@ -46,7 +46,6 @@
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/hierarchy.h>
#include <sepol/policydb/polcaps.h>
#include "queue.h"
@@ -891,10 +890,26 @@ filename : FILENAME
{ yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; }
;
number : NUMBER
- { $$ = strtoul(yytext,NULL,0); }
+ { unsigned long x;
+ errno = 0;
+ x = strtoul(yytext, NULL, 0);
+ if (errno)
+ return -1;
+#if ULONG_MAX > UINT_MAX
+ if (x > UINT_MAX)
+ return -1;
+#endif
+ $$ = (unsigned int) x;
+ }
;
number64 : NUMBER
- { $$ = strtoull(yytext,NULL,0); }
+ { unsigned long long x;
+ errno = 0;
+ x = strtoull(yytext, NULL, 0);
+ if (errno)
+ return -1;
+ $$ = (uint64_t) x;
+ }
;
ipv6_addr : IPV6_ADDR
{ if (insert_id(yytext,0)) return -1; }
diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l
index e2f676e4..9fefea7b 100644
--- a/checkpolicy/policy_scan.l
+++ b/checkpolicy/policy_scan.l
@@ -36,6 +36,8 @@ typedef int (* require_func_t)(void);
static char linebuf[2][255];
static unsigned int lno = 0;
+int werror = 0;
+int yyerror(const char *msg);
int yywarn(const char *msg);
void set_source_file(const char *name);
@@ -57,12 +59,24 @@ alnum [a-zA-Z0-9]
hexval [0-9A-Fa-f]
%%
-\n.* { strncpy(linebuf[lno], yytext+1, 255);
- linebuf[lno][254] = 0;
- lno = 1 - lno;
- policydb_lineno++;
- source_lineno++;
- yyless(1); }
+\n.* {
+#if defined(__GNUC__) && __GNUC__ >= 8
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-truncation"
+#endif
+ strncpy(linebuf[lno], yytext+1, 255);
+#if defined(__GNUC__) && __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+ linebuf[lno][254] = 0;
+ lno = 1 - lno;
+ policydb_lineno++;
+ if (source_lineno == ULONG_MAX)
+ yywarn("source line number overflow");
+ else
+ source_lineno++;
+ yyless(1);
+ }
CLONE |
clone { return(CLONE); }
COMMON |
@@ -268,7 +282,13 @@ GLBLUB { return(GLBLUB); }
{hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])* { return(IPV6_ADDR); }
{digit}+(\.({alnum}|[_.])*)? { return(VERSION_IDENTIFIER); }
#line[ ]1[ ]\"[^\n]*\" { set_source_file(yytext+9); }
-#line[ ]{digit}+ { source_lineno = atoi(yytext+6)-1; }
+#line[ ]{digit}+ {
+ errno = 0;
+ source_lineno = strtoul(yytext+6, NULL, 10) - 1;
+ if (errno) {
+ yywarn("source line number too big");
+ }
+ }
#[^\n]* { /* delete comments */ }
[ \t\f]+ { /* delete whitespace */ }
"==" { return(EQUALS); }
@@ -290,16 +310,16 @@ GLBLUB { return(GLBLUB); }
"]" |
"~" |
"*" { return(yytext[0]); }
-. { yywarn("unrecognized character");}
+. { yyerror("unrecognized character");}
%%
int yyerror(const char *msg)
{
if (source_file[0])
- fprintf(stderr, "%s:%ld:",
+ fprintf(stderr, "%s:%lu:",
source_file, source_lineno);
else
fprintf(stderr, "(unknown source)::");
- fprintf(stderr, "ERROR '%s' at token '%s' on line %ld:\n%s\n%s\n",
+ fprintf(stderr, "ERROR '%s' at token '%s' on line %lu:\n%s\n%s\n",
msg,
yytext,
policydb_lineno,
@@ -310,12 +330,15 @@ int yyerror(const char *msg)
int yywarn(const char *msg)
{
+ if (werror)
+ return yyerror(msg);
+
if (source_file[0])
- fprintf(stderr, "%s:%ld:",
+ fprintf(stderr, "%s:%lu:",
source_file, source_lineno);
else
fprintf(stderr, "(unknown source)::");
- fprintf(stderr, "WARNING '%s' at token '%s' on line %ld:\n%s\n%s\n",
+ fprintf(stderr, "WARNING '%s' at token '%s' on line %lu:\n%s\n%s\n",
msg,
yytext,
policydb_lineno,
diff --git a/checkpolicy/ru/checkmodule.8 b/checkpolicy/ru/checkmodule.8
index a1d687e3..d7d3f65c 100644
--- a/checkpolicy/ru/checkmodule.8
+++ b/checkpolicy/ru/checkmodule.8
@@ -50,7 +50,7 @@ $ checkmodule \-M \-m httpd.te \-o httpd.mod
.SH ÐВТОРЫ
-Эта Ñтраница руководÑтва была Ñкопирована Ñо Ñтраницы руководÑтва checkpolicy, напиÑанной Arpad Magosanyi <mag@bunuel.tii.matav.hu>,
+Эта Ñтраница руководÑтва была Ñкопирована Ñо Ñтраницы руководÑтва checkpolicy, напиÑанной Ãrpád Magosányi <mag@bunuel.tii.matav.hu>,
и отредактирована Dan Walsh <dwalsh@redhat.com>.
Программа была напиÑана Stephen Smalley <sds@tycho.nsa.gov>.
-Перевод на руÑÑкий Ñзык выполнила ГераÑименко ОлеÑÑ <gammaray@basealt.ru>.
+Перевод на руÑÑкий Ñзык выполнила ОлеÑÑ Ð“ÐµÑ€Ð°Ñименко <gammaray@basealt.ru>.
diff --git a/checkpolicy/ru/checkpolicy.8 b/checkpolicy/ru/checkpolicy.8
index 25b0e555..f08d1dc9 100644
--- a/checkpolicy/ru/checkpolicy.8
+++ b/checkpolicy/ru/checkpolicy.8
@@ -54,7 +54,7 @@ checkpolicy \- компилÑтор политики SELinux
Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ SELinux Reference Policy по адреÑу https://github.com/SELinuxProject/refpolicy/wiki
.SH ÐВТОРЫ
-Эта Ñтраница руководÑтва была напиÑана Arpad Magosanyi <mag@bunuel.tii.matav.hu>,
+Эта Ñтраница руководÑтва была напиÑана Ãrpád Magosányi <mag@bunuel.tii.matav.hu>,
и отредактирована Stephen Smalley <sds@tycho.nsa.gov>.
Программа была напиÑана Stephen Smalley <sds@tycho.nsa.gov>.
-Перевод на руÑÑкий Ñзык выполнила ГераÑименко ОлеÑÑ <gammaray@basealt.ru>.
+Перевод на руÑÑкий Ñзык выполнила ОлеÑÑ Ð“ÐµÑ€Ð°Ñименко <gammaray@basealt.ru>.
diff --git a/checkpolicy/test/Makefile b/checkpolicy/test/Makefile
index 89e7557c..8e5d16b3 100644
--- a/checkpolicy/test/Makefile
+++ b/checkpolicy/test/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for building the dispol program
#
-CFLAGS ?= -g -Wall -W -Werror -O2 -pipe
+CFLAGS ?= -g -Wall -W -Werror -O2
# If no specific libsepol.a is specified, fall back on LDFLAGS search path
# Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there
@@ -13,10 +13,10 @@ endif
all: dispol dismod
dispol: dispol.o $(LIBSEPOLA)
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
dismod: dismod.o $(LIBSEPOLA)
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
clean:
-rm -f dispol dismod *.o
diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
index 41bde48f..ec2a3e9a 100644
--- a/checkpolicy/test/dismod.c
+++ b/checkpolicy/test/dismod.c
@@ -30,7 +30,6 @@
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/link.h>
#include <sepol/policydb/module.h>
#include <sepol/policydb/util.h>
@@ -90,7 +89,7 @@ static void render_access_bitmap(ebitmap_t * map, uint32_t class,
fprintf(fp, "{");
for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) {
if (ebitmap_get_bit(map, i)) {
- perm = sepol_av_to_string(p, class, 1 << i);
+ perm = sepol_av_to_string(p, class, UINT32_C(1) << i);
if (perm)
fprintf(fp, " %s", perm);
}
@@ -112,7 +111,7 @@ static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type,
}
}
-int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
+static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
FILE * fp)
{
unsigned int i, num_types;
@@ -176,7 +175,7 @@ int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
return 0;
}
-int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
+static int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
{
unsigned int i, num = 0;
@@ -211,7 +210,7 @@ int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
}
-int display_avrule(avrule_t * avrule, policydb_t * policy,
+static int display_avrule(avrule_t * avrule, policydb_t * policy,
FILE * fp)
{
class_perm_node_t *cur;
@@ -314,7 +313,7 @@ int display_avrule(avrule_t * avrule, policydb_t * policy,
return 0;
}
-int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
+static int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
{
type_datum_t *type;
FILE *fp;
@@ -356,14 +355,14 @@ int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
return 0;
}
-int display_types(policydb_t * p, FILE * fp)
+static int display_types(policydb_t * p, FILE * fp)
{
if (hashtab_map(p->p_types.table, display_type_callback, fp))
return -1;
return 0;
}
-int display_users(policydb_t * p, FILE * fp)
+static int display_users(policydb_t * p, FILE * fp)
{
unsigned int i, j;
ebitmap_t *bitmap;
@@ -382,7 +381,7 @@ int display_users(policydb_t * p, FILE * fp)
return 0;
}
-int display_bools(policydb_t * p, FILE * fp)
+static int display_bools(policydb_t * p, FILE * fp)
{
unsigned int i;
@@ -393,7 +392,7 @@ int display_bools(policydb_t * p, FILE * fp)
return 0;
}
-void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
+static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
{
cond_expr_t *cur;
@@ -428,14 +427,14 @@ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
}
}
-void display_policycon(FILE * fp)
+static void display_policycon(FILE * fp)
{
/* There was an attempt to implement this at one time. Look through
* git history to find it. */
fprintf(fp, "Sorry, not implemented\n");
}
-void display_initial_sids(policydb_t * p, FILE * fp)
+static void display_initial_sids(policydb_t * p, FILE * fp)
{
ocontext_t *cur;
char *user, *role, *type;
@@ -460,7 +459,7 @@ void display_initial_sids(policydb_t * p, FILE * fp)
#endif
}
-void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
+static void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
{
unsigned int i, num = 0;
@@ -483,7 +482,7 @@ void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
fprintf(fp, " }");
}
-void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
+static void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
{
for (; tr; tr = tr->next) {
fprintf(fp, "role transition ");
@@ -496,7 +495,7 @@ void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
}
}
-void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
+static void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
{
for (; ra; ra = ra->next) {
fprintf(fp, "role allow ");
@@ -518,7 +517,7 @@ static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, F
}
}
-int role_display_callback(hashtab_key_t key __attribute__((unused)),
+static int role_display_callback(hashtab_key_t key __attribute__((unused)),
hashtab_datum_t datum, void *data)
{
role_datum_t *role;
@@ -612,7 +611,7 @@ int change_bool(char *name, int state, policydb_t * p, FILE * fp)
}
#endif
-int display_avdecl(avrule_decl_t * decl, int field,
+static int display_avdecl(avrule_decl_t * decl, int field,
policydb_t * policy, FILE * out_fp)
{
fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
@@ -693,13 +692,13 @@ int display_avdecl(avrule_decl_t * decl, int field,
return 0; /* should never get here */
}
-int display_avblock(int field, policydb_t * policy,
+static int display_avblock(int field, policydb_t * policy,
FILE * out_fp)
{
avrule_block_t *block = policydb.global;
while (block != NULL) {
- fprintf(out_fp, "--- begin avrule block ---\n");
avrule_decl_t *decl = block->branch_list;
+ fprintf(out_fp, "--- begin avrule block ---\n");
while (decl != NULL) {
if (display_avdecl(decl, field, policy, out_fp)) {
return -1;
@@ -711,7 +710,7 @@ int display_avblock(int field, policydb_t * policy,
return 0;
}
-int display_handle_unknown(policydb_t * p, FILE * out_fp)
+static int display_handle_unknown(policydb_t * p, FILE * out_fp)
{
if (p->handle_unknown == ALLOW_UNKNOWN)
fprintf(out_fp, "Allow unknown classes and perms\n");
@@ -752,12 +751,14 @@ static int read_policy(char *filename, policydb_t * policy)
fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
exit(1);
}
+ sepol_policydb_free(package->policy);
package->policy = (sepol_policydb_t *) policy;
package->file_contexts = NULL;
retval =
sepol_module_package_read(package,
(sepol_policy_file_t *) & f, 1);
- free(package->file_contexts);
+ package->policy = NULL;
+ sepol_module_package_free(package);
} else {
if (policydb_init(policy)) {
fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
@@ -828,14 +829,14 @@ static void display_policycaps(policydb_t * p, FILE * fp)
ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
capname = sepol_polcap_getname(i);
if (capname == NULL) {
- snprintf(buf, sizeof(buf), "unknown (%d)", i);
+ snprintf(buf, sizeof(buf), "unknown (%u)", i);
capname = buf;
}
fprintf(fp, "\t%s\n", capname);
}
}
-int menu(void)
+static int menu(void)
{
printf("\nSelect a command:\n");
printf("1) display unconditional AVTAB\n");
diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c
index d72d9fb3..8ddefb04 100644
--- a/checkpolicy/test/dispol.c
+++ b/checkpolicy/test/dispol.c
@@ -42,7 +42,7 @@ static __attribute__((__noreturn__)) void usage(const char *progname)
exit(1);
}
-int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
+static int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
FILE * fp)
{
char *perm;
@@ -54,13 +54,13 @@ int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
return 0;
}
-int render_type(uint32_t type, policydb_t * p, FILE * fp)
+static int render_type(uint32_t type, policydb_t * p, FILE * fp)
{
fprintf(fp, "%s", p->p_type_val_to_name[type - 1]);
return 0;
}
-int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
+static int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
{
char *stype, *ttype, *tclass;
stype = p->p_type_val_to_name[key->source_type - 1];
@@ -84,7 +84,7 @@ int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
#define RENDER_DISABLED 0x0004
#define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED)
-int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
+static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
policydb_t * p, FILE * fp)
{
if (!(what & RENDER_UNCONDITIONAL)) {
@@ -163,7 +163,7 @@ int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
return 0;
}
-int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
+static int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
{
unsigned int i;
avtab_ptr_t cur;
@@ -178,7 +178,7 @@ int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
return 0;
}
-int display_bools(policydb_t * p, FILE * fp)
+static int display_bools(policydb_t * p, FILE * fp)
{
unsigned int i;
@@ -189,7 +189,7 @@ int display_bools(policydb_t * p, FILE * fp)
return 0;
}
-void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
+static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
{
cond_expr_t *cur;
@@ -224,7 +224,7 @@ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
}
}
-int display_cond_expressions(policydb_t * p, FILE * fp)
+static int display_cond_expressions(policydb_t * p, FILE * fp)
{
cond_node_t *cur;
cond_av_list_t *av_cur;
@@ -249,7 +249,7 @@ int display_cond_expressions(policydb_t * p, FILE * fp)
return 0;
}
-int display_handle_unknown(policydb_t * p, FILE * out_fp)
+static int display_handle_unknown(policydb_t * p, FILE * out_fp)
{
if (p->handle_unknown == ALLOW_UNKNOWN)
fprintf(out_fp, "Allow unknown classes and permissions\n");
@@ -260,7 +260,7 @@ int display_handle_unknown(policydb_t * p, FILE * out_fp)
return 0;
}
-int change_bool(char *name, int state, policydb_t * p, FILE * fp)
+static int change_bool(char *name, int state, policydb_t * p, FILE * fp)
{
cond_bool_datum_t *bool;
@@ -285,7 +285,7 @@ static void display_policycaps(policydb_t * p, FILE * fp)
ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
capname = sepol_polcap_getname(i);
if (capname == NULL) {
- snprintf(buf, sizeof(buf), "unknown (%d)", i);
+ snprintf(buf, sizeof(buf), "unknown (%u)", i);
capname = buf;
}
fprintf(fp, "\t%s\n", capname);
@@ -335,17 +335,25 @@ static int filenametr_display(hashtab_key_t key,
hashtab_datum_t datum,
void *ptr)
{
- struct filename_trans *ft = (struct filename_trans *)key;
+ struct filename_trans_key *ft = (struct filename_trans_key *)key;
struct filename_trans_datum *ftdatum = datum;
struct filenametr_display_args *args = ptr;
policydb_t *p = args->p;
FILE *fp = args->fp;
+ ebitmap_node_t *node;
+ uint32_t bit;
+
+ do {
+ ebitmap_for_each_positive_bit(&ftdatum->stypes, node, bit) {
+ display_id(p, fp, SYM_TYPES, bit, "");
+ display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
+ display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
+ display_id(p, fp, SYM_TYPES, ftdatum->otype - 1, "");
+ fprintf(fp, " %s\n", ft->name);
+ }
+ ftdatum = ftdatum->next;
+ } while (ftdatum);
- display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
- display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
- display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
- display_id(p, fp, SYM_TYPES, ftdatum->otype - 1, "");
- fprintf(fp, " %s\n", ft->name);
return 0;
}
@@ -360,7 +368,7 @@ static void display_filename_trans(policydb_t *p, FILE *fp)
hashtab_map(p->filename_trans, filenametr_display, &args);
}
-int menu(void)
+static int menu(void)
{
printf("\nSelect a command:\n");
printf("1) display unconditional AVTAB\n");
diff --git a/dbus/VERSION b/dbus/VERSION
index 9f55b2cc..eb39e538 100644
--- a/dbus/VERSION
+++ b/dbus/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/dbus/selinux_server.py b/dbus/selinux_server.py
index be4f4557..a969f226 100644
--- a/dbus/selinux_server.py
+++ b/dbus/selinux_server.py
@@ -2,28 +2,36 @@
import dbus
import dbus.service
-import dbus.mainloop.glib
+from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GObject
-import slip.dbus.service
-from slip.dbus import polkit
+from gi.repository import GLib
import os
import selinux
from subprocess import Popen, PIPE, STDOUT
-class selinux_server(slip.dbus.service.Object):
+class selinux_server(dbus.service.Object):
default_polkit_auth_required = "org.selinux.semanage"
def __init__(self, *p, **k):
super(selinux_server, self).__init__(*p, **k)
+ def is_authorized(self, sender, action_id):
+ bus = dbus.SystemBus()
+ proxy = bus.get_object('org.freedesktop.PolicyKit1', '/org/freedesktop/PolicyKit1/Authority')
+ authority = dbus.Interface(proxy, dbus_interface='org.freedesktop.PolicyKit1.Authority')
+ subject = ('system-bus-name', {'name': sender})
+ result = authority.CheckAuthorization(subject, action_id, {}, 1, '')
+ return result[0]
+
#
# The semanage method runs a transaction on a series of semanage commands,
# these commands can take the output of customized
#
- @slip.dbus.polkit.require_auth("org.selinux.semanage")
- @dbus.service.method("org.selinux", in_signature='s')
- def semanage(self, buf):
+ @dbus.service.method("org.selinux", in_signature='s', sender_keyword="sender")
+ def semanage(self, buf, sender):
+ if not self.is_authorized(sender, "org.selinux.semanage"):
+ raise dbus.exceptions.DBusException("Not authorized")
p = Popen(["/usr/sbin/semanage", "import"], stdout=PIPE, stderr=PIPE, stdin=PIPE, universal_newlines=True)
p.stdin.write(buf)
output = p.communicate()
@@ -35,9 +43,10 @@ class selinux_server(slip.dbus.service.Object):
# on the server. This output can be used with the semanage method on
# another server to make the two systems have duplicate policy.
#
- @slip.dbus.polkit.require_auth("org.selinux.customized")
- @dbus.service.method("org.selinux", in_signature='', out_signature='s')
- def customized(self):
+ @dbus.service.method("org.selinux", in_signature='', out_signature='s', sender_keyword="sender")
+ def customized(self, sender):
+ if not self.is_authorized(sender, "org.selinux.customized"):
+ raise dbus.exceptions.DBusException("Not authorized")
p = Popen(["/usr/sbin/semanage", "export"], stdout=PIPE, stderr=PIPE, universal_newlines=True)
buf = p.stdout.read()
output = p.communicate()
@@ -49,9 +58,10 @@ class selinux_server(slip.dbus.service.Object):
# The semodule_list method will return the output of semodule --list=full, using the customized polkit,
# since this is a readonly behaviour
#
- @slip.dbus.polkit.require_auth("org.selinux.semodule_list")
- @dbus.service.method("org.selinux", in_signature='', out_signature='s')
- def semodule_list(self):
+ @dbus.service.method("org.selinux", in_signature='', out_signature='s', sender_keyword="sender")
+ def semodule_list(self, sender):
+ if not self.is_authorized(sender, "org.selinux.semodule_list"):
+ raise dbus.exceptions.DBusException("Not authorized")
p = Popen(["/usr/sbin/semodule", "--list=full"], stdout=PIPE, stderr=PIPE, universal_newlines=True)
buf = p.stdout.read()
output = p.communicate()
@@ -62,25 +72,28 @@ class selinux_server(slip.dbus.service.Object):
#
# The restorecon method modifies any file path to the default system label
#
- @slip.dbus.polkit.require_auth("org.selinux.restorecon")
- @dbus.service.method("org.selinux", in_signature='s')
- def restorecon(self, path):
+ @dbus.service.method("org.selinux", in_signature='s', sender_keyword="sender")
+ def restorecon(self, path, sender):
+ if not self.is_authorized(sender, "org.selinux.restorecon"):
+ raise dbus.exceptions.DBusException("Not authorized")
selinux.restorecon(str(path), recursive=1)
#
# The setenforce method turns off the current enforcement of SELinux
#
- @slip.dbus.polkit.require_auth("org.selinux.setenforce")
- @dbus.service.method("org.selinux", in_signature='i')
- def setenforce(self, value):
+ @dbus.service.method("org.selinux", in_signature='i', sender_keyword="sender")
+ def setenforce(self, value, sender):
+ if not self.is_authorized(sender, "org.selinux.setenforce"):
+ raise dbus.exceptions.DBusException("Not authorized")
selinux.security_setenforce(value)
#
# The setenforce method turns off the current enforcement of SELinux
#
- @slip.dbus.polkit.require_auth("org.selinux.relabel_on_boot")
- @dbus.service.method("org.selinux", in_signature='i')
- def relabel_on_boot(self, value):
+ @dbus.service.method("org.selinux", in_signature='i', sender_keyword="sender")
+ def relabel_on_boot(self, value, sender):
+ if not self.is_authorized(sender, "org.selinux.relabel_on_boot"):
+ raise dbus.exceptions.DBusException("Not authorized")
if value == 1:
fd = open("/.autorelabel", "w")
fd.close()
@@ -111,9 +124,10 @@ class selinux_server(slip.dbus.service.Object):
#
# The change_default_enforcement modifies the current enforcement mode
#
- @slip.dbus.polkit.require_auth("org.selinux.change_default_mode")
- @dbus.service.method("org.selinux", in_signature='s')
- def change_default_mode(self, value):
+ @dbus.service.method("org.selinux", in_signature='s', sender_keyword="sender")
+ def change_default_mode(self, value, sender):
+ if not self.is_authorized(sender, "org.selinux.change_default_mode"):
+ raise dbus.exceptions.DBusException("Not authorized")
values = ["enforcing", "permissive", "disabled"]
if value not in values:
raise ValueError("Enforcement mode must be %s" % ", ".join(values))
@@ -122,19 +136,20 @@ class selinux_server(slip.dbus.service.Object):
#
# The change_default_policy method modifies the policy type
#
- @slip.dbus.polkit.require_auth("org.selinux.change_default_policy")
- @dbus.service.method("org.selinux", in_signature='s')
- def change_default_policy(self, value):
+ @dbus.service.method("org.selinux", in_signature='s', sender_keyword="sender")
+ def change_default_policy(self, value, sender):
+ if not self.is_authorized(sender, "org.selinux.change_default_policy"):
+ raise dbus.exceptions.DBusException("Not authorized")
path = selinux.selinux_path() + value
if os.path.isdir(path):
return self.write_selinux_config(policy=value)
raise ValueError("%s does not exist" % path)
if __name__ == "__main__":
- mainloop = GObject.MainLoop()
- dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+ DBusGMainLoop(set_as_default=True)
+ mainloop = GLib.MainLoop()
+
system_bus = dbus.SystemBus()
name = dbus.service.BusName("org.selinux", system_bus)
- object = selinux_server(system_bus, "/org/selinux/object")
- slip.dbus.service.set_mainloop(mainloop)
+ server = selinux_server(system_bus, "/org/selinux/object")
mainloop.run()
diff --git a/gui/VERSION b/gui/VERSION
index 9f55b2cc..eb39e538 100644
--- a/gui/VERSION
+++ b/gui/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/gui/fcontextPage.py b/gui/fcontextPage.py
index 370bbee4..d26aa1b4 100644
--- a/gui/fcontextPage.py
+++ b/gui/fcontextPage.py
@@ -102,6 +102,13 @@ class fcontextPage(semanagePage):
self.load()
self.fcontextEntry = xml.get_object("fcontextEntry")
self.fcontextFileTypeCombo = xml.get_object("fcontextFileTypeCombo")
+ # Populate file type combo_box
+ liststore = self.fcontextFileTypeCombo.get_model()
+ for ftype in seobject.file_type_str_to_option.keys():
+ iter = liststore.append()
+ liststore.set_value(iter, 0, ftype)
+ iter = liststore.get_iter_first()
+ self.fcontextFileTypeCombo.set_active_iter(iter)
self.fcontextTypeEntry = xml.get_object("fcontextTypeEntry")
self.fcontextMLSEntry = xml.get_object("fcontextMLSEntry")
diff --git a/gui/system-config-selinux.ui b/gui/system-config-selinux.ui
index 7cc1cc53..e7b84a64 100644
--- a/gui/system-config-selinux.ui
+++ b/gui/system-config-selinux.ui
@@ -401,32 +401,6 @@ Level</property>
<!-- column-name gchararray -->
<column type="gchararray"/>
</columns>
- <data>
- <row>
- <col id="0" translatable="yes">all files</col>
- </row>
- <row>
- <col id="0" translatable="yes">regular file</col>
- </row>
- <row>
- <col id="0" translatable="yes">directory</col>
- </row>
- <row>
- <col id="0" translatable="yes">character device</col>
- </row>
- <row>
- <col id="0" translatable="yes">block device</col>
- </row>
- <row>
- <col id="0" translatable="yes">socket file</col>
- </row>
- <row>
- <col id="0" translatable="yes">symbolic link</col>
- </row>
- <row>
- <col id="0" translatable="yes">named pipe</col>
- </row>
- </data>
</object>
<object class="GtkDialog" id="fcontextDialog">
<property name="can_focus">False</property>
diff --git a/libselinux/Android.bp b/libselinux/Android.bp
index 272a3a61..fab05ba0 100644
--- a/libselinux/Android.bp
+++ b/libselinux/Android.bp
@@ -110,6 +110,7 @@ cc_defaults {
shared_libs: [
"liblog",
],
+ system_shared_libs: ["libc"],
header_libs: ["libcutils_headers"],
@@ -126,7 +127,6 @@ cc_defaults {
export_include_dirs: ["include"],
stl: "none",
- system_shared_libs: ["libc"],
}
cc_library {
@@ -150,9 +150,8 @@ cc_library {
],
target: {
- linux_glibc: {
+ host_linux: {
srcs: [
- "src/android/android_host.c",
"src/avc.c",
"src/avc_internal.c",
"src/avc_sidtab.c",
@@ -162,48 +161,30 @@ cc_library {
"src/context.c",
"src/deny_unknown.c",
"src/enabled.c",
- "src/fgetfilecon.c",
"src/getenforce.c",
"src/getfilecon.c",
"src/get_initial_context.c",
"src/init.c",
- "src/lgetfilecon.c",
"src/load_policy.c",
- "src/lsetfilecon.c",
"src/mapping.c",
"src/procattr.c",
"src/reject_unknown.c",
- "src/setenforce.c",
+ "src/sestatus.c",
"src/setexecfilecon.c",
- "src/setfilecon.c",
"src/stringrep.c",
],
},
- linux_bionic: {
- enabled: true,
+ linux_glibc: {
srcs: [
- "src/android/android_host.c",
- "src/avc.c",
- "src/avc_internal.c",
- "src/avc_sidtab.c",
- "src/compute_av.c",
- "src/compute_create.c",
- "src/compute_member.c",
- "src/context.c",
- "src/deny_unknown.c",
- "src/enabled.c",
- "src/getenforce.c",
- "src/getfilecon.c",
- "src/get_initial_context.c",
- "src/init.c",
- "src/load_policy.c",
- "src/mapping.c",
- "src/procattr.c",
- "src/reject_unknown.c",
- "src/setexecfilecon.c",
- "src/stringrep.c",
+ "src/fgetfilecon.c",
+ "src/lgetfilecon.c",
+ "src/lsetfilecon.c",
+ "src/setfilecon.c",
],
},
+ linux_bionic: {
+ enabled: true,
+ },
android: {
srcs: [
@@ -329,4 +310,21 @@ rust_bindgen {
// This is mainly to run layout tests for generated bindings on the host.
host_supported: true,
+
+ apex_available: [
+ "com.android.virt",
+ "//apex_available:platform",
+ ],
+}
+
+rust_test {
+ name: "libselinux_bindgen_test",
+ srcs: [
+ ":libselinux_bindgen",
+ ],
+ crate_name: "selinux_bindgen_test",
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ clippy_lints: "none",
+ lints: "none",
}
diff --git a/libselinux/Makefile b/libselinux/Makefile
index 16531fe9..6d9e2736 100644
--- a/libselinux/Makefile
+++ b/libselinux/Makefile
@@ -1,9 +1,10 @@
-SUBDIRS = src include utils man
+SUBDIRS = include src utils man
PKG_CONFIG ?= pkg-config
DISABLE_SETRANS ?= n
DISABLE_RPM ?= n
ANDROID_HOST ?= n
+LABEL_BACKEND_ANDROID ?= n
ifeq ($(ANDROID_HOST),y)
override DISABLE_SETRANS=y
override DISABLE_BOOL=y
@@ -17,9 +18,12 @@ endif
ifeq ($(DISABLE_BOOL),y)
DISABLE_FLAGS+= -DDISABLE_BOOL
endif
-export DISABLE_SETRANS DISABLE_RPM DISABLE_FLAGS ANDROID_HOST
+ifeq ($(DISABLE_X11),y)
+ DISABLE_FLAGS+= -DNO_X_BACKEND
+endif
+export DISABLE_SETRANS DISABLE_RPM DISABLE_FLAGS ANDROID_HOST DISABLE_X11 LABEL_BACKEND_ANDROID
-USE_PCRE2 ?= n
+USE_PCRE2 ?= y
ifeq ($(USE_PCRE2),y)
PCRE_MODULE := libpcre2-8
PCRE_CFLAGS := -DUSE_PCRE2 -DPCRE2_CODE_UNIT_WIDTH=8
@@ -46,24 +50,24 @@ all install relabel clean distclean indent:
done
swigify: all
- $(MAKE) -C src swigify $@
+ $(MAKE) -C src $@
pywrap:
- $(MAKE) -C src pywrap $@
+ $(MAKE) -C src $@
rubywrap:
- $(MAKE) -C src rubywrap $@
+ $(MAKE) -C src $@
install-pywrap:
- $(MAKE) -C src install-pywrap $@
+ $(MAKE) -C src $@
install-rubywrap:
- $(MAKE) -C src install-rubywrap $@
+ $(MAKE) -C src $@
clean-pywrap:
- $(MAKE) -C src clean-pywrap $@
+ $(MAKE) -C src $@
clean-rubywrap:
- $(MAKE) -C src clean-rubywrap $@
+ $(MAKE) -C src $@
test:
diff --git a/libselinux/VERSION b/libselinux/VERSION
index 9f55b2cc..eb39e538 100644
--- a/libselinux/VERSION
+++ b/libselinux/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/libselinux/fuzzers/selabel_lookup_fuzzer.cpp b/libselinux/fuzzers/selabel_lookup_fuzzer.cpp
index 38e44f5a..69e92aea 100644
--- a/libselinux/fuzzers/selabel_lookup_fuzzer.cpp
+++ b/libselinux/fuzzers/selabel_lookup_fuzzer.cpp
@@ -43,5 +43,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
selabel_lookup(handle, &conn, str.data(), type);
+ free(conn);
+
return 0;
}
diff --git a/libselinux/include/selinux/avc.h b/libselinux/include/selinux/avc.h
index 46c51419..9b23357a 100644
--- a/libselinux/include/selinux/avc.h
+++ b/libselinux/include/selinux/avc.h
@@ -64,7 +64,11 @@ extern int avc_context_to_sid_raw(const char * ctx, security_id_t * sid);
* reference count). Note that avc_context_to_sid() also
* increments reference counts.
*/
-extern int sidget(security_id_t sid);
+extern int sidget(security_id_t sid)
+#ifdef __GNUC__
+__attribute__ ((deprecated))
+#endif
+;
/**
* sidput - decrement SID reference counter.
@@ -76,7 +80,11 @@ extern int sidget(security_id_t sid);
* zero, the SID is invalid, and avc_context_to_sid() must
* be called to obtain a new SID for the security context.
*/
-extern int sidput(security_id_t sid);
+extern int sidput(security_id_t sid)
+#ifdef __GNUC__
+__attribute__ ((deprecated))
+#endif
+;
/**
* avc_get_initial_sid - get SID for an initial kernel security identifier
@@ -192,7 +200,11 @@ extern int avc_init(const char *msgprefix,
const struct avc_memory_callback *mem_callbacks,
const struct avc_log_callback *log_callbacks,
const struct avc_thread_callback *thread_callbacks,
- const struct avc_lock_callback *lock_callbacks);
+ const struct avc_lock_callback *lock_callbacks)
+#ifdef __GNUC__
+ __attribute__ ((deprecated("Use avc_open and selinux_set_callback")))
+#endif
+;
/**
* avc_open - Initialize the AVC.
diff --git a/libselinux/include/selinux/get_context_list.h b/libselinux/include/selinux/get_context_list.h
index db8641a4..6b2f14f3 100644
--- a/libselinux/include/selinux/get_context_list.h
+++ b/libselinux/include/selinux/get_context_list.h
@@ -17,14 +17,14 @@ extern "C" {
If 'fromcon' is NULL, defaults to current context.
Caller must free via freeconary. */
extern int get_ordered_context_list(const char *user,
- char * fromcon,
+ const char *fromcon,
char *** list);
/* As above, but use the provided MLS level rather than the
default level for the user. */
extern int get_ordered_context_list_with_level(const char *user,
const char *level,
- char * fromcon,
+ const char *fromcon,
char *** list);
/* Get the default security context for a user session for 'user'
@@ -35,14 +35,14 @@ extern "C" {
Returns 0 on success or -1 otherwise.
Caller must free via freecon. */
extern int get_default_context(const char *user,
- char * fromcon,
+ const char *fromcon,
char ** newcon);
/* As above, but use the provided MLS level rather than the
default level for the user. */
extern int get_default_context_with_level(const char *user,
const char *level,
- char * fromcon,
+ const char *fromcon,
char ** newcon);
/* Same as get_default_context, but only return a context
@@ -50,7 +50,7 @@ extern "C" {
for the user with that role, then return -1. */
extern int get_default_context_with_role(const char *user,
const char *role,
- char * fromcon,
+ const char *fromcon,
char ** newcon);
/* Same as get_default_context, but only return a context
@@ -59,7 +59,7 @@ extern "C" {
extern int get_default_context_with_rolelevel(const char *user,
const char *role,
const char *level,
- char * fromcon,
+ const char *fromcon,
char ** newcon);
/* Given a list of authorized security contexts for the user,
diff --git a/libselinux/include/selinux/restorecon.h b/libselinux/include/selinux/restorecon.h
index 754b8645..1821a3dc 100644
--- a/libselinux/include/selinux/restorecon.h
+++ b/libselinux/include/selinux/restorecon.h
@@ -2,6 +2,7 @@
#define _RESTORECON_H_
#include <sys/types.h>
+#include <stddef.h>
#include <stdarg.h>
#ifdef __cplusplus
@@ -23,6 +24,19 @@ extern "C" {
*/
extern int selinux_restorecon(const char *pathname,
unsigned int restorecon_flags);
+/**
+ * selinux_restorecon_parallel - Relabel files, optionally use more threads.
+ * @pathname: specifies file/directory to relabel.
+ * @restorecon_flags: specifies the actions to be performed when relabeling.
+ * @nthreads: specifies the number of threads to use (0 = use number of CPUs
+ * currently online)
+ *
+ * Same as selinux_restorecon(3), but allows to use multiple threads to do
+ * the work.
+ */
+extern int selinux_restorecon_parallel(const char *pathname,
+ unsigned int restorecon_flags,
+ size_t nthreads);
/*
* restorecon_flags options
*/
@@ -30,77 +44,82 @@ extern int selinux_restorecon(const char *pathname,
* Force the checking of labels even if the stored SHA1 digest
* matches the specfiles SHA1 digest (requires CAP_SYS_ADMIN).
*/
-#define SELINUX_RESTORECON_IGNORE_DIGEST 0x0001
+#define SELINUX_RESTORECON_IGNORE_DIGEST 0x00001
/*
* Do not change file labels.
*/
-#define SELINUX_RESTORECON_NOCHANGE 0x0002
+#define SELINUX_RESTORECON_NOCHANGE 0x00002
/*
* If set, change file label to that in spec file.
* If not, only change type component to that in spec file.
*/
-#define SELINUX_RESTORECON_SET_SPECFILE_CTX 0x0004
+#define SELINUX_RESTORECON_SET_SPECFILE_CTX 0x00004
/*
* Recursively descend directories.
*/
-#define SELINUX_RESTORECON_RECURSE 0x0008
+#define SELINUX_RESTORECON_RECURSE 0x00008
/*
* Log changes to selinux log. Note that if VERBOSE and
* PROGRESS are set, then PROGRESS will take precedence.
*/
-#define SELINUX_RESTORECON_VERBOSE 0x0010
+#define SELINUX_RESTORECON_VERBOSE 0x00010
/*
* If SELINUX_RESTORECON_PROGRESS is true and
* SELINUX_RESTORECON_MASS_RELABEL is true, then output approx % complete,
* else output the number of files in 1k blocks processed to stdout.
*/
-#define SELINUX_RESTORECON_PROGRESS 0x0020
+#define SELINUX_RESTORECON_PROGRESS 0x00020
/*
* Convert passed-in pathname to canonical pathname.
*/
-#define SELINUX_RESTORECON_REALPATH 0x0040
+#define SELINUX_RESTORECON_REALPATH 0x00040
/*
* Prevent descending into directories that have a different
* device number than the pathname from which the descent began.
*/
-#define SELINUX_RESTORECON_XDEV 0x0080
+#define SELINUX_RESTORECON_XDEV 0x00080
/*
* Attempt to add an association between an inode and a specification.
* If there is already an association for the inode and it conflicts
* with the specification, then use the last matching specification.
*/
-#define SELINUX_RESTORECON_ADD_ASSOC 0x0100
+#define SELINUX_RESTORECON_ADD_ASSOC 0x00100
/*
* Abort on errors during the file tree walk.
*/
-#define SELINUX_RESTORECON_ABORT_ON_ERROR 0x0200
+#define SELINUX_RESTORECON_ABORT_ON_ERROR 0x00200
/*
* Log any label changes to syslog.
*/
-#define SELINUX_RESTORECON_SYSLOG_CHANGES 0x0400
+#define SELINUX_RESTORECON_SYSLOG_CHANGES 0x00400
/*
* Log what spec matched each file.
*/
-#define SELINUX_RESTORECON_LOG_MATCHES 0x0800
+#define SELINUX_RESTORECON_LOG_MATCHES 0x00800
/*
* Ignore files that do not exist.
*/
-#define SELINUX_RESTORECON_IGNORE_NOENTRY 0x1000
+#define SELINUX_RESTORECON_IGNORE_NOENTRY 0x01000
/*
* Do not read /proc/mounts to obtain a list of non-seclabel
* mounts to be excluded from relabeling checks.
*/
-#define SELINUX_RESTORECON_IGNORE_MOUNTS 0x2000
+#define SELINUX_RESTORECON_IGNORE_MOUNTS 0x02000
/*
* Set if there is a mass relabel required.
* See SELINUX_RESTORECON_PROGRESS flag for details.
*/
-#define SELINUX_RESTORECON_MASS_RELABEL 0x4000
+#define SELINUX_RESTORECON_MASS_RELABEL 0x04000
/*
* Set if no digest is to be read or written (as only processes
* running with CAP_SYS_ADMIN can read/write digests).
*/
-#define SELINUX_RESTORECON_SKIP_DIGEST 0x8000
+#define SELINUX_RESTORECON_SKIP_DIGEST 0x08000
+
+/*
+ * Set to treat conflicting specifications as errors.
+ */
+#define SELINUX_RESTORECON_CONFLICT_ERROR 0x10000
/**
* selinux_restorecon_set_sehandle - Set the global fc handle.
diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
index 7922d96b..ae98a92e 100644
--- a/libselinux/include/selinux/selinux.h
+++ b/libselinux/include/selinux/selinux.h
@@ -8,13 +8,17 @@
extern "C" {
#endif
-/* Return 1 if we are running on a SELinux kernel, or 0 if not or -1 if we get an error. */
+/* Return 1 if we are running on a SELinux kernel, or 0 otherwise. */
extern int is_selinux_enabled(void);
/* Return 1 if we are running on a SELinux MLS kernel, or 0 otherwise. */
extern int is_selinux_mls_enabled(void);
/* No longer used; here for compatibility with legacy callers. */
-typedef char *security_context_t;
+typedef char *security_context_t
+#ifdef __GNUC__
+__attribute__ ((deprecated))
+#endif
+;
/* Free the memory allocated for a context by any of the below get* calls. */
extern void freecon(char * con);
@@ -178,6 +182,8 @@ extern void selinux_set_callback(int type, union selinux_callback cb);
#define SELINUX_WARNING 1
#define SELINUX_INFO 2
#define SELINUX_AVC 3
+#define SELINUX_POLICYLOAD 4
+#define SELINUX_SETENFORCE 5
#define SELINUX_TRANS_DIR "/var/run/setrans"
/* Compute an access decision. */
@@ -246,8 +252,12 @@ extern int security_compute_member_raw(const char * scon,
security_class_t tclass,
char ** newcon);
-/* Compute the set of reachable user contexts and set *con to refer to
- the NULL-terminated array of contexts. Caller must free via freeconary. */
+/*
+ * Compute the set of reachable user contexts and set *con to refer to
+ * the NULL-terminated array of contexts. Caller must free via freeconary.
+ * These interfaces are deprecated. Use get_ordered_context_list() or
+ * one of its variant interfaces instead.
+ */
extern int security_compute_user(const char * scon,
const char *username,
char *** con);
@@ -319,9 +329,13 @@ extern int security_set_boolean_list(size_t boolcnt,
SELboolean * boollist, int permanent);
/* Load policy boolean settings. Deprecated as local policy booleans no
- * longer supported. Will always return 0.
+ * longer supported. Will always return -1.
*/
-extern int security_load_booleans(char *path);
+extern int security_load_booleans(char *path)
+#ifdef __GNUC__
+__attribute__ ((deprecated))
+#endif
+;
/* Check the validity of a security context. */
extern int security_check_context(const char * con);
@@ -457,14 +471,22 @@ extern void set_matchpathcon_flags(unsigned int flags);
function also checks for a 'path'.homedirs file and
a 'path'.local file and loads additional specifications
from them if present. */
-extern int matchpathcon_init(const char *path);
+extern int matchpathcon_init(const char *path)
+#ifdef __GNUC__
+ __attribute__ ((deprecated("Use selabel_open with backend SELABEL_CTX_FILE")))
+#endif
+;
/* Same as matchpathcon_init, but only load entries with
regexes that have stems that are prefixes of 'prefix'. */
extern int matchpathcon_init_prefix(const char *path, const char *prefix);
/* Free the memory allocated by matchpathcon_init. */
-extern void matchpathcon_fini(void);
+extern void matchpathcon_fini(void)
+#ifdef __GNUC__
+ __attribute__ ((deprecated("Use selabel_close")))
+#endif
+;
/* Resolve all of the symlinks and relative portions of a pathname, but NOT
* the final component (same a realpath() unless the final component is a
@@ -478,7 +500,11 @@ extern int realpath_not_final(const char *name, char *resolved_path);
If matchpathcon_init has not already been called, then this function
will call it upon its first invocation with a NULL path. */
extern int matchpathcon(const char *path,
- mode_t mode, char ** con);
+ mode_t mode, char ** con)
+#ifdef __GNUC__
+ __attribute__ ((deprecated("Use selabel_lookup instead")))
+#endif
+;
/* Same as above, but return a specification index for
later use in a matchpathcon_filespec_add() call - see below. */
@@ -571,10 +597,18 @@ extern const char *selinux_contexts_path(void);
extern const char *selinux_securetty_types_path(void);
extern const char *selinux_booleans_subs_path(void);
/* Deprecated as local policy booleans no longer supported. */
-extern const char *selinux_booleans_path(void);
+extern const char *selinux_booleans_path(void)
+#ifdef __GNUC__
+__attribute__ ((deprecated))
+#endif
+;
extern const char *selinux_customizable_types_path(void);
/* Deprecated as policy ./users no longer supported. */
-extern const char *selinux_users_path(void);
+extern const char *selinux_users_path(void)
+#ifdef __GNUC__
+__attribute__ ((deprecated))
+#endif
+;
extern const char *selinux_usersconf_path(void);
extern const char *selinux_translations_path(void);
extern const char *selinux_colors_path(void);
@@ -602,8 +636,17 @@ extern int selinux_check_access(const char * scon, const char * tcon, const char
/* Check a permission in the passwd class.
Return 0 if granted or -1 otherwise. */
-extern int selinux_check_passwd_access(access_vector_t requested);
-extern int checkPasswdAccess(access_vector_t requested);
+extern int selinux_check_passwd_access(access_vector_t requested)
+#ifdef __GNUC__
+ __attribute__ ((deprecated("Use selinux_check_access")))
+#endif
+;
+
+extern int checkPasswdAccess(access_vector_t requested)
+#ifdef __GNUC__
+ __attribute__ ((deprecated("Use selinux_check_access")))
+#endif
+;
/* Check if the tty_context is defined as a securetty
Return 0 if secure, < 0 otherwise. */
@@ -629,7 +672,11 @@ extern int setexecfilecon(const char *filename, const char *fallback_type);
/* Execute a helper for rpm in an appropriate security context. */
extern int rpm_execcon(unsigned int verified,
const char *filename,
- char *const argv[], char *const envp[]);
+ char *const argv[], char *const envp[])
+#ifdef __GNUC__
+ __attribute__((deprecated("Use setexecfilecon and execve")))
+#endif
+;
#endif
/* Returns whether a file context is customizable, and should not
diff --git a/libselinux/man/man3/avc_init.3 b/libselinux/man/man3/avc_init.3
index e26c3be6..a5dc7c93 100644
--- a/libselinux/man/man3/avc_init.3
+++ b/libselinux/man/man3/avc_init.3
@@ -117,6 +117,8 @@ argument, which does not return under normal conditions. The
callback should cancel the running thread referenced by
.IR thread .
By default, threading is not used; see
+.B KERNEL STATUS PAGE
+and
.B NETLINK NOTIFICATION
below.
@@ -153,14 +155,49 @@ callback should destroy
.IR lock ,
freeing any resources associated with it. The default behavior is not to perform any locking. Note that undefined behavior may result if threading is used without appropriate locking.
.
-.SH "NETLINK NOTIFICATION"
-Beginning with version 2.6.4, the Linux kernel supports SELinux status change notification via netlink. Two message types are currently implemented, indicating changes to the enforcing mode and to the loaded policy in the kernel, respectively. The userspace AVC listens for these messages and takes the appropriate action, modifying the behavior of
-.BR avc_has_perm (3)
-to reflect the current enforcing mode and flushing the cache on receipt of a policy load notification. Audit messages are produced when netlink notifications are processed.
+.SH "KERNEL STATUS PAGE"
+Linux kernel version 2.6.37 supports the SELinux kernel status page, enabling userspace applications to
+.BR mmap (2)
+SELinux status state in read-only mode to avoid system calls during the cache hit code path.
-In the default single-threaded mode, the userspace AVC checks for new netlink messages at the start of each permission query. If threading and locking callbacks are passed to
.BR avc_init ()
-however, a dedicated thread will be started to listen on the netlink socket. This may increase performance and will ensure that log messages are generated immediately rather than at the time of the next permission query.
+calls
+.BR selinux_status_open (3)
+to initialize the selinux status state. If successfully initialized, the userspace AVC will default to single-threaded mode and ignore the
+.B func_create_thread
+and
+.B func_stop_thread
+callbacks. All callbacks set via
+.BR selinux_set_callback (3)
+will still be honored.
+
+.BR avc_has_perm (3)
+and
+.BR selinux_check_access (3)
+both check for status updates through calls to
+.BR selinux_status_updated (3)
+at the start of each permission query and take the appropriate action.
+
+Two status types are currently implemented.
+.B setenforce
+events will change the effective enforcing state used within the AVC, and
+.B policyload
+events will result in a cache flush.
+.
+.SH "NETLINK NOTIFICATION"
+In the event that the kernel status page is not successfully
+.BR mmap (2)'ed
+the AVC will default to the netlink fallback mechanism, which opens a netlink socket for receiving status updates.
+.B setenforce
+and
+.B policyload
+events will have the same results as for the status page implementation, but all status update checks will now require a system call.
+
+By default,
+.BR avc_open (3)
+does not set threading or locking callbacks. In the fallback case, the userspace AVC checks for new netlink messages at the start of each permission query. If threading and locking callbacks are passed to
+.BR avc_init (),
+a dedicated thread will be started to listen on the netlink socket. This may increase performance in the absence of the status page and will ensure that log messages are generated immediately rather than at the time of the next permission query.
.
.SH "RETURN VALUE"
Functions with a return value return zero on success. On error, \-1 is returned and
@@ -192,5 +229,7 @@ Eamon Walsh <ewalsh@tycho.nsa.gov>
.
.SH "SEE ALSO"
.BR avc_open (3),
+.BR selinux_status_open (3),
+.BR selinux_status_updated (3),
.BR selinux_set_callback (3),
.BR selinux (8)
diff --git a/libselinux/man/man3/avc_netlink_loop.3 b/libselinux/man/man3/avc_netlink_loop.3
index c8268a12..f03d7813 100644
--- a/libselinux/man/man3/avc_netlink_loop.3
+++ b/libselinux/man/man3/avc_netlink_loop.3
@@ -54,6 +54,11 @@ closes the netlink socket. This function is called automatically by
returns the netlink socket descriptor number and informs the userspace AVC
not to check the socket descriptor automatically on calls to
.BR avc_has_perm (3).
+If no such socket descriptor exists,
+.BR avc_netlink_acquire_fd (3)
+will first call
+.BR avc_netlink_open (3)
+and then return the resulting fd.
.BR avc_netlink_release_fd ()
returns control of the netlink socket to the userspace AVC, re-enabling
@@ -78,6 +83,9 @@ with a return value return zero on success. On error, \-1 is returned and
.I errno
is set appropriately.
.
+.SH "AUTHOR"
+Originally KaiGai Kohei. Updated by Mike Palmiotto <mike.palmiotto@crunchydata.com>
+.
.SH "SEE ALSO"
.BR avc_open (3),
.BR selinux_set_callback (3),
diff --git a/libselinux/man/man3/avc_open.3 b/libselinux/man/man3/avc_open.3
index 5b275a8e..55683bb6 100644
--- a/libselinux/man/man3/avc_open.3
+++ b/libselinux/man/man3/avc_open.3
@@ -26,6 +26,9 @@ initializes the userspace AVC and must be called before any other AVC operation
destroys the userspace AVC, freeing all internal memory structures. After this call has been made,
.BR avc_open ()
must be called again before any AVC operations can be performed.
+.BR avc_destroy ()
+also closes the SELinux status page, which might have been opened manually by
+.BR selinux_status_open (3).
.BR avc_reset ()
flushes the userspace AVC, causing it to forget any cached access decisions. The userspace AVC normally calls this function automatically when needed, see
@@ -46,10 +49,37 @@ include the following:
.B AVC_OPT_SETENFORCE
This option forces the userspace AVC into enforcing mode if the option value is non-NULL; permissive mode otherwise. The system enforcing mode will be ignored.
.
-.SH "NETLINK NOTIFICATION"
-Beginning with version 2.6.4, the Linux kernel supports SELinux status change notification via netlink. Two message types are currently implemented, indicating changes to the enforcing mode and to the loaded policy in the kernel, respectively. The userspace AVC listens for these messages and takes the appropriate action, modifying the behavior of
+.SH "KERNEL STATUS PAGE"
+Linux kernel version 2.6.37 supports the SELinux kernel status page, enabling userspace applications to
+.BR mmap (2)
+SELinux status state in read-only mode to avoid system calls during the cache hit code path.
+
+.BR avc_open ()
+calls
+.BR selinux_status_open (3)
+to initialize the selinux status state.
+
.BR avc_has_perm (3)
-to reflect the current enforcing mode and flushing the cache on receipt of a policy load notification. Audit messages are produced when netlink notifications are processed.
+and
+.BR selinux_check_access (3)
+both check for status updates through calls to
+.BR selinux_status_updated (3)
+at the start of each permission query and take the appropriate action.
+
+Two status types are currently implemented.
+.B setenforce
+events will change the effective enforcing state used within the AVC, and
+.B policyload
+events will result in a cache flush.
+.
+.SH "NETLINK NOTIFICATION"
+In the event that the kernel status page is not successfully
+.BR mmap (2)'ed
+the AVC will default to the netlink fallback mechanism, which opens a netlink socket for receiving status updates.
+.B setenforce
+and
+.B policyload
+events will have the same results as for the status page implementation, but all status update checks will now require a system call.
.
.SH "RETURN VALUE"
Functions with a return value return zero on success. On error, \-1 is returned and
@@ -61,9 +91,12 @@ Eamon Walsh <ewalsh@tycho.nsa.gov>
.
.SH "SEE ALSO"
.BR selinux (8),
+.BR selinux_check_access (3),
.BR avc_has_perm (3),
.BR avc_context_to_sid (3),
.BR avc_cache_stats (3),
.BR avc_add_callback (3),
+.BR selinux_status_open (3),
+.BR selinux_status_updated (3),
.BR selinux_set_callback (3),
.BR security_compute_av (3)
diff --git a/libselinux/man/man3/get_ordered_context_list.3 b/libselinux/man/man3/get_ordered_context_list.3
index e084da40..2a1e08f0 100644
--- a/libselinux/man/man3/get_ordered_context_list.3
+++ b/libselinux/man/man3/get_ordered_context_list.3
@@ -7,17 +7,17 @@ get_ordered_context_list, get_ordered_context_list_with_level, get_default_conte
.br
.B #include <selinux/get_context_list.h>
.sp
-.BI "int get_ordered_context_list(const char *" user ", char *" fromcon ", char ***" list );
+.BI "int get_ordered_context_list(const char *" user ", const char *" fromcon ", char ***" list );
.sp
-.BI "int get_ordered_context_list_with_level(const char *" user ", const char *" level ", char *" fromcon ", char ***" list );
+.BI "int get_ordered_context_list_with_level(const char *" user ", const char *" level ", const char *" fromcon ", char ***" list );
.sp
-.BI "int get_default_context(const char *" user ", char *" fromcon ", char **" newcon );
+.BI "int get_default_context(const char *" user ", const char *" fromcon ", char **" newcon );
.sp
-.BI "int get_default_context_with_level(const char *" user ", const char *" level ", char *" fromcon ", char **" newcon );
+.BI "int get_default_context_with_level(const char *" user ", const char *" level ", const char *" fromcon ", char **" newcon );
.sp
-.BI "int get_default_context_with_role(const char *" user ", const char *" role ", char *" fromcon ", char **" newcon ");
+.BI "int get_default_context_with_role(const char *" user ", const char *" role ", const char *" fromcon ", char **" newcon ");
.sp
-.BI "int get_default_context_with_rolelevel(const char *" user ", const char *" role ", const char *" level ", char *" fromcon ", char **" newcon ");
+.BI "int get_default_context_with_rolelevel(const char *" user ", const char *" role ", const char *" level ", const char *" fromcon ", char **" newcon ");
.sp
.BI "int query_user_context(char **" list ", char **" newcon );
.sp
@@ -26,14 +26,28 @@ get_ordered_context_list, get_ordered_context_list_with_level, get_default_conte
.BI "int get_default_type(const char *" role ", char **" type );
.
.SH "DESCRIPTION"
+
+This family of functions can be used to obtain either a prioritized list of
+all reachable security contexts for a given SELinux user or a single default
+(highest priority) context for a given SELinux user for use by login-like
+programs. These functions takes a SELinux user identity that must
+be defined in the SELinux policy as their input, not a Linux username.
+Most callers should typically first call
+.BR getseuserbyname(3)
+to look up the SELinux user identity and level for a given
+Linux username and then invoke one of
+.BR get_ordered_context_list_with_level ()
+or
+.BR get_default_context_with_level ()
+with the returned SELinux user and level as inputs.
+
.BR get_ordered_context_list ()
-invokes the
-.BR security_compute_user (3)
-function to obtain the list of contexts for the specified
+obtains the list of contexts for the specified
+SELinux
.I user
-that are reachable from the specified
+identity that are reachable from the specified
.I fromcon
-context. The function then orders the resulting list based on the global
+context based on the global
.I \%/etc/selinux/{SELINUXTYPE}/contexts/default_contexts
file and the per-user
.I \%/etc/selinux/{SELINUXTYPE}/contexts/users/<username>
diff --git a/libselinux/man/man3/getcon.3 b/libselinux/man/man3/getcon.3
index 67872a4d..e7e394f3 100644
--- a/libselinux/man/man3/getcon.3
+++ b/libselinux/man/man3/getcon.3
@@ -7,7 +7,7 @@ freecon, freeconary \- free memory associated with SELinux security contexts
getpeercon \- get security context of a peer socket
setcon \- set current security context of a process
-.
+
.SH "SYNOPSIS"
.B #include <selinux/selinux.h>
.sp
@@ -31,30 +31,39 @@ setcon \- set current security context of a process
.sp
.BI "void freeconary(char **" con );
.sp
-.BI "int setcon(char *" context );
+.BI "int setcon(const char *" context );
.sp
-.BI "int setcon_raw(char *" context );
-.
+.BI "int setcon_raw(const char *" context );
+
.SH "DESCRIPTION"
+.TP
.BR getcon ()
retrieves the context of the current process, which must be free'd with
-freecon.
+.BR freecon ().
+.TP
.BR getprevcon ()
same as getcon but gets the context before the last exec.
+.TP
.BR getpidcon ()
-returns the process context for the specified PID.
+returns the process context for the specified PID, which must be free'd with
+.BR freecon ().
+.TP
.BR getpeercon ()
-retrieves context of peer socket, and set
-.BI * context
-to refer to it, which must be free'd with
+retrieves the context of the peer socket, which must be free'd with
.BR freecon ().
+.TP
.BR freecon ()
frees the memory allocated for a security context.
+If
+.I con
+is NULL, no operation is performed.
+
+.TP
.BR freeconary ()
frees the memory allocated for a context array.
@@ -62,6 +71,7 @@ If
.I con
is NULL, no operation is performed.
+.TP
.BR setcon ()
sets the current security context of the process to a new value. Note
that use of this function requires that the entire application be
@@ -110,6 +120,8 @@ context and the
.BR setcon ()
will fail if it is not allowed by policy.
+.TP
+.BR *_raw()
.BR getcon_raw (),
.BR getprevcon_raw (),
.BR getpidcon_raw (),
@@ -118,9 +130,14 @@ and
.BR setcon_raw ()
behave identically to their non-raw counterparts but do not perform context
translation.
-.
+
.SH "RETURN VALUE"
-On error \-1 is returned. On success 0 is returned.
-.
+On error \-1 is returned with errno set. On success 0 is returned.
+
+.SH "NOTES"
+The retrieval functions might return success and set
+.I *context
+to NULL if and only if SELinux is not enabled.
+
.SH "SEE ALSO"
.BR selinux "(8), " setexeccon "(3)"
diff --git a/libselinux/man/man3/is_selinux_enabled.3 b/libselinux/man/man3/is_selinux_enabled.3
index df62c225..a887b48c 100644
--- a/libselinux/man/man3/is_selinux_enabled.3
+++ b/libselinux/man/man3/is_selinux_enabled.3
@@ -15,7 +15,6 @@ is_selinux_mls_enabled \- check whether SELinux is enabled for (Multi Level Secu
.SH "DESCRIPTION"
.BR is_selinux_enabled ()
returns 1 if SELinux is running or 0 if it is not.
-On error, \-1 is returned.
.BR is_selinux_mls_enabled ()
returns 1 if SELinux is capable of running in MLS mode or 0 if it is not. To
diff --git a/libselinux/man/man3/security_check_context.3 b/libselinux/man/man3/security_check_context.3
index 2b9a2d4c..213ac282 100644
--- a/libselinux/man/man3/security_check_context.3
+++ b/libselinux/man/man3/security_check_context.3
@@ -5,9 +5,9 @@ security_check_context \- check the validity of a SELinux context
.SH "SYNOPSIS"
.B #include <selinux/selinux.h>
.sp
-.BI "int security_check_context(char *" con );
+.BI "int security_check_context(const char *" con );
.sp
-.BI "int security_check_context_raw(char *" con );
+.BI "int security_check_context_raw(const char *" con );
.
.SH "DESCRIPTION"
.BR security_check_context ()
diff --git a/libselinux/man/man3/security_compute_av.3 b/libselinux/man/man3/security_compute_av.3
index 3de1b0fe..efa4baf3 100644
--- a/libselinux/man/man3/security_compute_av.3
+++ b/libselinux/man/man3/security_compute_av.3
@@ -134,8 +134,9 @@ instance.
.BR security_compute_user ()
is used to determine the set of user contexts that can be reached from a
-source context. It is mainly used by
-.BR get_ordered_context_list (3).
+source context. This function is deprecated; use
+.BR get_ordered_context_list (3)
+instead.
.BR security_validatetrans ()
is used to determine if a transition from scon to newcon using tcon as the object
diff --git a/libselinux/man/man3/selinux_restorecon.3 b/libselinux/man/man3/selinux_restorecon.3
index f6e5f2d7..334d2930 100644
--- a/libselinux/man/man3/selinux_restorecon.3
+++ b/libselinux/man/man3/selinux_restorecon.3
@@ -11,6 +11,14 @@ selinux_restorecon \- restore file(s) default SELinux security contexts
.br
.BI "unsigned int " restorecon_flags ");"
.in
+.sp
+.BI "int selinux_restorecon_parallel(const char *" pathname ,
+.in +\w'int selinux_restorecon_parallel('u
+.br
+.BI "unsigned int " restorecon_flags ","
+.br
+.BI "size_t " nthreads ");"
+.in
.
.SH "DESCRIPTION"
.BR selinux_restorecon ()
@@ -152,6 +160,10 @@ Setting
.B SELINUX_RESTORECON_IGNORE_MOUNTS
is useful where there is a non-seclabel fs mounted with a seclabel fs mounted
on a directory below this.
+.sp
+.B SELINUX_RESTORECON_CONFLICT_ERROR
+to treat conflicting specifications, such as where two hardlinks for the
+same inode have different contexts, as errors.
.RE
.sp
The behavior regarding the checking and updating of the SHA1 digest described
@@ -183,6 +195,27 @@ unless the
.B SELINUX_RESTORECON_IGNORE_MOUNTS
flag has been set.
.RE
+.sp
+.BR selinux_restorecon_parallel()
+is similar to
+.BR selinux_restorecon (3),
+but accepts another parameter that allows to run relabeling over multiple
+threads:
+.sp
+.RS
+.IR nthreads
+specifies the number of threads to use during relabeling. When set to 1,
+the behavior is the same as calling
+.BR selinux_restorecon (3).
+When set to 0, the function will try to use as many threads as there are
+online CPU cores. When set to any other number, the function will try to use
+the given number of threads.
+.sp
+Note that to use the parallel relabeling capability, the calling process
+must be linked with the
+.B libpthread
+library (either at compile time or dynamically at run time). Otherwise the
+function will print a warning and fall back to the single threaded mode.
.
.SH "RETURN VALUE"
On success, zero is returned. On error, \-1 is returned and
diff --git a/libselinux/man/man3/selinux_restorecon_parallel.3 b/libselinux/man/man3/selinux_restorecon_parallel.3
new file mode 100644
index 00000000..092d8412
--- /dev/null
+++ b/libselinux/man/man3/selinux_restorecon_parallel.3
@@ -0,0 +1 @@
+.so man3/selinux_restorecon.3
diff --git a/libselinux/man/man3/selinux_set_callback.3 b/libselinux/man/man3/selinux_set_callback.3
index a4c613ad..75f49b06 100644
--- a/libselinux/man/man3/selinux_set_callback.3
+++ b/libselinux/man/man3/selinux_set_callback.3
@@ -46,6 +46,20 @@ argument indicates the type of message and will be set to one of the following:
.B SELINUX_INFO
.B SELINUX_AVC
+
+.B SELINUX_POLICYLOAD
+
+.B SELINUX_SETENFORCE
+
+SELINUX_ERROR, SELINUX_WARNING, and SELINUX_INFO indicate standard log severity
+levels and are not auditable messages.
+
+The SELINUX_AVC, SELINUX_POLICYLOAD, and SELINUX_SETENFORCE message types can be
+audited with AUDIT_USER_AVC, AUDIT_USER_MAC_POLICY_LOAD, and AUDIT_USER_MAC_STATUS
+values from libaudit, respectively. If they are not audited, SELINUX_AVC should be
+considered equivalent to SELINUX_ERROR; similarly, SELINUX_POLICYLOAD and
+SELINUX_SETENFORCE should be considered equivalent to SELINUX_INFO.
+
.
.TP
.B SELINUX_CB_AUDIT
diff --git a/libselinux/man/man3/selinux_status_open.3 b/libselinux/man/man3/selinux_status_open.3
index 2d44be57..5c9da2f6 100644
--- a/libselinux/man/man3/selinux_status_open.3
+++ b/libselinux/man/man3/selinux_status_open.3
@@ -48,7 +48,7 @@ Set 1 on the
argument to handle a case of older kernels without kernel status page support.
In this case, this function tries to open a netlink socket using
.BR avc_netlink_open (3)
-and overwrite corresponding callbacks ( setenforce and policyload).
+and overwrite corresponding callbacks (setenforce and policyload).
Thus, we need to pay attention to the interaction with these interfaces,
when fallback mode is enabled.
.sp
@@ -57,9 +57,14 @@ unmap the kernel status page and close its file descriptor, or close the
netlink socket if fallbacked.
.sp
.BR selinux_status_updated ()
-informs us whether something has been updated since the last call.
-It returns 0 if nothing was happened, however, 1 if something has been
-updated in this duration, or \-1 on error.
+processes status update events. There are two kinds of status updates.
+.B setenforce
+events will change the effective enforcing state used within the AVC, and
+.B policyload
+events will result in a cache flush.
+
+This function returns 0 if there have been no updates since the last call,
+1 if there have been updates since the last call, or \-1 on error.
.sp
.BR selinux_status_getenforce ()
returns 0 if SELinux is running in permissive mode, 1 if enforcing mode,
diff --git a/libselinux/man/man5/selabel_file.5 b/libselinux/man/man5/selabel_file.5
index e97bd826..baba7776 100644
--- a/libselinux/man/man5/selabel_file.5
+++ b/libselinux/man/man5/selabel_file.5
@@ -125,7 +125,14 @@ Where:
.RS
.I pathname
.RS
-An entry that defines the pathname that may be in the form of a regular expression.
+An entry that defines the path to be labeled.
+May contain either a fully qualified path,
+or a Perl compatible regular expression (PCRE),
+describing fully qualified path(s).
+The only PCRE flag in use is PCRE2_DOTALL,
+which causes a wildcard '.' to match anything, including a new line.
+Strings representing paths are processed as bytes (as opposed to Unicode),
+meaning that non-ASCII characters are not matched by a single wildcard.
.RE
.I file_type
.RS
diff --git a/libselinux/man/man8/selinux.8 b/libselinux/man/man8/selinux.8
index 31364271..5842150b 100644
--- a/libselinux/man/man8/selinux.8
+++ b/libselinux/man/man8/selinux.8
@@ -19,18 +19,36 @@ enabled or disabled, and if enabled, whether SELinux operates in
permissive mode or enforcing mode. The
.B SELINUX
variable may be set to
-any one of disabled, permissive, or enforcing to select one of these
-options. The disabled option completely disables the SELinux kernel
-and application code, leaving the system running without any SELinux
-protection. The permissive option enables the SELinux code, but
-causes it to operate in a mode where accesses that would be denied by
-policy are permitted but audited. The enforcing option enables the
-SELinux code and causes it to enforce access denials as well as
-auditing them. Permissive mode may yield a different set of denials
-than enforcing mode, both because enforcing mode will prevent an
-operation from proceeding past the first denial and because some
-application code will fall back to a less privileged mode of operation
-if denied access.
+any one of \fIdisabled\fR, \fIpermissive\fR, or \fIenforcing\fR to
+select one of these options. The \fIdisabled\fR disables most of the
+SELinux kernel and application code, leaving the system
+running without any SELinux protection. The \fIpermissive\fR option
+enables the SELinux code, but causes it to operate in a mode where
+accesses that would be denied by policy are permitted but audited. The
+\fIenforcing\fR option enables the SELinux code and causes it to enforce
+access denials as well as auditing them. \fIpermissive\fR mode may
+yield a different set of denials than enforcing mode, both because
+enforcing mode will prevent an operation from proceeding past the first
+denial and because some application code will fall back to a less
+privileged mode of operation if denied access.
+
+.B NOTE:
+Disabling SELinux by setting
+.B SELINUX=disabled
+in
+.I /etc/selinux/config
+is deprecated and depending on kernel version and configuration it might
+not lead to SELinux being completely disabled. Specifically, the
+SELinux hooks will still be executed internally, but the SELinux policy
+will not be loaded and no operation will be denied. In such state, the
+system will act as if SELinux was disabled, although some operations
+might behave slightly differently. To properly disable SELinux, it is
+recommended to use the
+.B selinux=0
+kernel boot option instead. In that case SELinux will be disabled
+regardless of what is set in the
+.I /etc/selinux/config
+file.
The
.I /etc/selinux/config
@@ -76,6 +94,13 @@ and reboot.
also has this capability. The
.BR restorecon / fixfiles
commands are also available for relabeling files.
+
+Please note that using mount flag
+.I nosuid
+also disables SELinux domain transitions, unless permission
+.I nosuid_transition
+is used in the policy to allow this, which in turn needs also policy capability
+.IR nnp_nosuid_transition .
.
.SH AUTHOR
This manual page was written by Dan Walsh <dwalsh@redhat.com>.
diff --git a/libselinux/man/ru/man5/failsafe_context.5 b/libselinux/man/ru/man5/failsafe_context.5
index 01d6b0ea..54cecf39 100644
--- a/libselinux/man/ru/man5/failsafe_context.5
+++ b/libselinux/man/ru/man5/failsafe_context.5
@@ -1,6 +1,6 @@
.TH "failsafe_context" "5" "28 ноÑÐ±Ñ€Ñ 2011" "Security Enhanced Linux" "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ SELinux"
.SH "ИМЯ"
-failsafe_context \- файл конфигурации надёжного контекÑта SELinux
+failsafe_context \- файл конфигурации резервного контекÑта SELinux
.
.SH "ОПИСÐÐИЕ"
Файл
@@ -10,7 +10,7 @@ failsafe_context \- файл конфигурации надёжного конÑ
получать извеÑтный дейÑтвительный контекÑÑ‚ входа Ð´Ð»Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратора, еÑли в других раÑположениÑÑ… отÑутÑтвуют дейÑтвительные запиÑи по умолчанию.
.sp
.BR selinux_failsafe_context_path "(3) "
-возвращает путь активной политики к Ñтому файлу. Файл надёжного контекÑта по умолчанию:
+возвращает путь активной политики к Ñтому файлу. Файл резервного контекÑта по умолчанию:
.RS
.I /etc/selinux/{SELINUXTYPE}/contexts/failsafe_context
.RE
diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index 7f5a5d74..04bf4f24 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -15,7 +15,7 @@ INCLUDEDIR ?= $(PREFIX)/include
PYINC ?= $(shell $(PKG_CONFIG) --cflags $(PYPREFIX))
PYLIBS ?= $(shell $(PKG_CONFIG) --libs $(PYPREFIX))
PYTHONLIBDIR ?= $(shell $(PYTHON) -c "from distutils.sysconfig import *; print(get_python_lib(plat_specific=1, prefix='$(PREFIX)'))")
-PYCEXT ?= $(shell $(PYTHON) -c 'import imp;print([s for s,m,t in imp.get_suffixes() if t == imp.C_EXTENSION][0])')
+PYCEXT ?= $(shell $(PYTHON) -c 'import importlib.machinery;print(importlib.machinery.EXTENSION_SUFFIXES[0])')
RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]')
RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]')
RUBYINSTALL ?= $(shell $(RUBY) -e 'puts RbConfig::CONFIG["vendorarchdir"]')
@@ -65,7 +65,7 @@ EXTRA_CFLAGS = -fipa-pure-const -Wlogical-op -Wpacked-bitfield-compat -Wsync-nan
-Wcoverage-mismatch -Wcpp -Wformat-contains-nul -Wnormalized=nfc -Wsuggest-attribute=const \
-Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wtrampolines -Wjump-misses-init \
-Wno-suggest-attribute=pure -Wno-suggest-attribute=const -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 \
- -Wstrict-overflow=5
+ -Wstrict-overflow=5 -fno-semantic-interposition
else
EXTRA_CFLAGS = -Wunused-command-line-argument
endif
@@ -90,7 +90,7 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi
-Werror -Wno-aggregate-return -Wno-redundant-decls \
$(EXTRA_CFLAGS)
-LD_SONAME_FLAGS=-soname,$(LIBSO),-z,defs,-z,relro
+LD_SONAME_FLAGS=-soname,$(LIBSO),--version-script=libselinux.map,-z,defs,-z,relro
ifeq ($(OS), Darwin)
override CFLAGS += -I/opt/local/include
@@ -98,14 +98,14 @@ override LDFLAGS += -L/opt/local/lib -undefined dynamic_lookup
LD_SONAME_FLAGS=-install_name,$(LIBSO)
endif
-PCRE_LDLIBS ?= -lpcre
# override with -lfts when building on Musl libc to use fts-standalone
FTS_LDLIBS ?=
override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS)
SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \
- -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations
+ -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations \
+ -Wno-deprecated-declarations
RANLIB ?= ranlib
@@ -121,8 +121,16 @@ SRCS= callbacks.c freecon.c label.c label_file.c \
label_backends_android.c regex.c label_support.c \
matchpathcon.c setrans_client.c sha1.c booleans.c
else
-DISABLE_FLAGS+= -DNO_ANDROID_BACKEND
+LABEL_BACKEND_ANDROID=y
+endif
+
+ifneq ($(LABEL_BACKEND_ANDROIDT),y)
SRCS:= $(filter-out label_backends_android.c, $(SRCS))
+DISABLE_FLAGS+= -DNO_ANDROID_BACKEND
+endif
+
+ifeq ($(DISABLE_X11),y)
+SRCS:= $(filter-out label_x.c, $(SRCS))
endif
SWIGRUBY = swig -Wall -ruby -o $(SWIGRUBYCOUT) -outdir ./ $(DISABLE_FLAGS)
@@ -173,7 +181,7 @@ install: all
ln -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET)
install-pywrap: pywrap
- $(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)`
+ $(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` $(PYTHON_SETUP_ARGS)
install -m 644 $(SWIGPYOUT) $(DESTDIR)$(PYTHONLIBDIR)/selinux/__init__.py
ln -sf --relative $(DESTDIR)$(PYTHONLIBDIR)/selinux/_selinux$(PYCEXT) $(DESTDIR)$(PYTHONLIBDIR)/_selinux$(PYCEXT)
diff --git a/libselinux/src/android/android.c b/libselinux/src/android/android.c
index 87877082..7ee9e774 100644
--- a/libselinux/src/android/android.c
+++ b/libselinux/src/android/android.c
@@ -14,6 +14,9 @@ static const struct selinux_opt seopts_service_plat[] = {
{ SELABEL_OPT_PATH, "/system/etc/selinux/plat_service_contexts" },
{ SELABEL_OPT_PATH, "/plat_service_contexts" }
};
+static const struct selinux_opt seopts_service_apex[] = {
+ { SELABEL_OPT_PATH, "/dev/selinux/apex_service_contexts" }
+};
static const struct selinux_opt seopts_service_system_ext[] = {
{ SELABEL_OPT_PATH, "/system_ext/etc/selinux/system_ext_service_contexts" },
{ SELABEL_OPT_PATH, "/system_ext_service_contexts" }
@@ -24,10 +27,7 @@ static const struct selinux_opt seopts_service_product[] = {
};
static const struct selinux_opt seopts_service_vendor[] = {
{ SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_service_contexts" },
- { SELABEL_OPT_PATH, "/vendor_service_contexts" },
- // TODO: remove nonplat* when no need to retain backward compatibility.
- { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_service_contexts" },
- { SELABEL_OPT_PATH, "/nonplat_service_contexts" }
+ { SELABEL_OPT_PATH, "/vendor_service_contexts" }
};
static const struct selinux_opt seopts_hwservice_plat[] = {
@@ -44,10 +44,7 @@ static const struct selinux_opt seopts_hwservice_product[] = {
};
static const struct selinux_opt seopts_hwservice_vendor[] = {
{ SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_hwservice_contexts" },
- { SELABEL_OPT_PATH, "/vendor_hwservice_contexts" },
- // TODO: remove nonplat* when no need to retain backward compatibility.
- { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_hwservice_contexts" },
- { SELABEL_OPT_PATH, "/nonplat_hwservice_contexts" }
+ { SELABEL_OPT_PATH, "/vendor_hwservice_contexts" }
};
static const struct selinux_opt seopts_hwservice_odm[] = {
{ SELABEL_OPT_PATH, "/odm/etc/selinux/odm_hwservice_contexts" },
@@ -128,6 +125,12 @@ struct selabel_handle* selinux_android_service_context_handle(void)
break;
}
}
+ for (i = 0; i < ARRAY_SIZE(seopts_service_apex); i++) {
+ if (access(seopts_service_apex[i].value, R_OK) != -1) {
+ seopts_service[size++] = seopts_service_apex[i];
+ break;
+ }
+ }
for (i = 0; i < ARRAY_SIZE(seopts_service_system_ext); i++) {
if (access(seopts_service_system_ext[i].value, R_OK) != -1) {
seopts_service[size++] = seopts_service_system_ext[i];
diff --git a/libselinux/src/android/android_common.h b/libselinux/src/android/android_common.h
index 5853c2bc..78b2e712 100644
--- a/libselinux/src/android/android_common.h
+++ b/libselinux/src/android/android_common.h
@@ -20,7 +20,6 @@
#include <selinux/context.h>
#include <selinux/android.h>
#include <selinux/label.h>
-#include <selinux/avc.h>
#ifndef __ANDROID_VNDK__
#include <private/android_filesystem_config.h>
#endif
diff --git a/libselinux/src/android/android_host.c b/libselinux/src/android/android_host.c
deleted file mode 100644
index 8b55aa78..00000000
--- a/libselinux/src/android/android_host.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <stdlib.h>
-
-// HACK: placeholder for a library the python bindings expect.
-// Delete after b/33170640 is fixed.
-const char *selinux_openssh_contexts_path(void)
-{
- abort();
-}
diff --git a/libselinux/src/android/android_platform.c b/libselinux/src/android/android_platform.c
index 2e52c153..05c923bc 100644
--- a/libselinux/src/android/android_platform.c
+++ b/libselinux/src/android/android_platform.c
@@ -1,9 +1,9 @@
#include "android_common.h"
#include <packagelistparser/packagelistparser.h>
-// For 'system', 'system_ext' (optional), 'product' (optional), 'vendor' (mandatory)
-// and/or 'odm' (optional).
-#define MAX_FILE_CONTEXT_SIZE 5
+// For 'system', 'system_ext' (optional), 'apex' (optional), 'product' (optional),
+// 'vendor' (mandatory) and/or 'odm' (optional) .
+#define MAX_FILE_CONTEXT_SIZE 6
static const char *const sepolicy_file = "/sepolicy";
@@ -11,6 +11,9 @@ static const struct selinux_opt seopts_file_plat[] = {
{ SELABEL_OPT_PATH, "/system/etc/selinux/plat_file_contexts" },
{ SELABEL_OPT_PATH, "/plat_file_contexts" }
};
+static const struct selinux_opt seopts_file_apex[] = {
+ { SELABEL_OPT_PATH, "/dev/selinux/apex_file_contexts" }
+};
static const struct selinux_opt seopts_file_system_ext[] = {
{ SELABEL_OPT_PATH, "/system_ext/etc/selinux/system_ext_file_contexts" },
{ SELABEL_OPT_PATH, "/system_ext_file_contexts" }
@@ -21,10 +24,7 @@ static const struct selinux_opt seopts_file_product[] = {
};
static const struct selinux_opt seopts_file_vendor[] = {
{ SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_file_contexts" },
- { SELABEL_OPT_PATH, "/vendor_file_contexts" },
- // TODO: remove nonplat* when no need to retain backward compatibility.
- { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_file_contexts" },
- { SELABEL_OPT_PATH, "/nonplat_file_contexts" }
+ { SELABEL_OPT_PATH, "/vendor_file_contexts" }
};
static const struct selinux_opt seopts_file_odm[] = {
{ SELABEL_OPT_PATH, "/odm/etc/selinux/odm_file_contexts" },
@@ -41,6 +41,9 @@ static char const * const seapp_contexts_plat[] = {
"/system/etc/selinux/plat_seapp_contexts",
"/plat_seapp_contexts"
};
+static char const * const seapp_contexts_apex[] = {
+ "/dev/selinux/apex_seapp_contexts"
+};
static char const * const seapp_contexts_system_ext[] = {
"/system_ext/etc/selinux/system_ext_seapp_contexts",
"/system_ext_seapp_contexts"
@@ -51,10 +54,7 @@ static char const * const seapp_contexts_product[] = {
};
static char const * const seapp_contexts_vendor[] = {
"/vendor/etc/selinux/vendor_seapp_contexts",
- "/vendor_seapp_contexts",
- // TODO: remove nonplat* when no need to retain backward compatibility.
- "/vendor/etc/selinux/nonplat_seapp_contexts",
- "/nonplat_seapp_contexts"
+ "/vendor_seapp_contexts"
};
static char const * const seapp_contexts_odm[] = {
"/odm/etc/selinux/odm_seapp_contexts",
@@ -94,6 +94,12 @@ struct selabel_handle* selinux_android_file_context_handle(void)
break;
}
}
+ for (i = 0; i < ARRAY_SIZE(seopts_file_apex); i++) {
+ if (access(seopts_file_apex[i].value, R_OK) != -1) {
+ seopts_file[size++] = seopts_file_apex[i];
+ break;
+ }
+ }
for (i = 0; i < ARRAY_SIZE(seopts_file_system_ext); i++) {
if (access(seopts_file_system_ext[i].value, R_OK) != -1) {
seopts_file[size++] = seopts_file_system_ext[i];
@@ -155,12 +161,9 @@ struct seapp_context {
bool isSystemServer;
bool isEphemeralAppSet;
bool isEphemeralApp;
- bool isOwnerSet;
- bool isOwner;
struct prefix_str user;
char *seinfo;
struct prefix_str name;
- struct prefix_str path;
bool isPrivAppSet;
bool isPrivApp;
int32_t minTargetSdkVersion;
@@ -180,7 +183,6 @@ static void free_seapp_context(struct seapp_context *s)
free_prefix_str(&s->user);
free(s->seinfo);
free_prefix_str(&s->name);
- free_prefix_str(&s->path);
free(s->domain);
free(s->type);
free(s->level);
@@ -204,10 +206,6 @@ static int seapp_context_cmp(const void *A, const void *B)
if (s1->isEphemeralAppSet != s2->isEphemeralAppSet)
return (s1->isEphemeralAppSet ? -1 : 1);
- /* Give precedence to a specified isOwner= over an unspecified isOwner=. */
- if (s1->isOwnerSet != s2->isOwnerSet)
- return (s1->isOwnerSet ? -1 : 1);
-
/* Give precedence to a specified user= over an unspecified user=. */
if (s1->user.str && !s2->user.str)
return -1;
@@ -246,22 +244,6 @@ static int seapp_context_cmp(const void *A, const void *B)
return (s1->name.len > s2->name.len) ? -1 : 1;
}
- /* Give precedence to a specified path= over an unspecified path=. */
- if (s1->path.str && !s2->path.str)
- return -1;
- if (!s1->path.str && s2->path.str)
- return 1;
-
- if (s1->path.str) {
- /* Give precedence to a fixed path= string over a prefix. */
- if (s1->path.is_prefix != s2->path.is_prefix)
- return (s2->path.is_prefix ? -1 : 1);
-
- /* Give precedence to a longer prefix over a shorter prefix. */
- if (s1->path.is_prefix && s1->path.len != s2->path.len)
- return (s1->path.len > s2->path.len) ? -1 : 1;
- }
-
/* Give precedence to a specified isPrivApp= over an unspecified isPrivApp=. */
if (s1->isPrivAppSet != s2->isPrivAppSet)
return (s1->isPrivAppSet ? -1 : 1);
@@ -280,16 +262,14 @@ static int seapp_context_cmp(const void *A, const void *B)
/*
* Check for a duplicated entry on the input selectors.
- * We already compared isSystemServer, isOwnerSet, and isOwner above.
+ * We already compared isSystemServer above.
* We also have already checked that both entries specify the same
* string fields, so if s1 has a non-NULL string, then so does s2.
*/
dup = (!s1->user.str || !strcmp(s1->user.str, s2->user.str)) &&
(!s1->seinfo || !strcmp(s1->seinfo, s2->seinfo)) &&
(!s1->name.str || !strcmp(s1->name.str, s2->name.str)) &&
- (!s1->path.str || !strcmp(s1->path.str, s2->path.str)) &&
(s1->isPrivAppSet && s1->isPrivApp == s2->isPrivApp) &&
- (s1->isOwnerSet && s1->isOwner == s2->isOwner) &&
(s1->isSystemServer && s1->isSystemServer == s2->isSystemServer) &&
(s1->isEphemeralAppSet && s1->isEphemeralApp == s2->isEphemeralApp);
@@ -302,8 +282,6 @@ static int seapp_context_cmp(const void *A, const void *B)
selinux_log(SELINUX_ERROR, " seinfo=%s\n", s1->seinfo);
if (s1->name.str)
selinux_log(SELINUX_ERROR, " name=%s\n", s1->name.str);
- if (s1->path.str)
- selinux_log(SELINUX_ERROR, " path=%s\n", s1->path.str);
}
/* Anything else has equal precedence. */
@@ -357,6 +335,12 @@ int selinux_android_seapp_context_reload(void)
break;
}
}
+ for (i = 0; i < ARRAY_SIZE(seapp_contexts_apex); i++) {
+ if (access(seapp_contexts_apex[i], R_OK) != -1) {
+ seapp_contexts_files[files_len++] = seapp_contexts_apex[i];
+ break;
+ }
+ }
for (i = 0; i < ARRAY_SIZE(seapp_contexts_system_ext); i++) {
if (access(seapp_contexts_system_ext[i], R_OK) != -1) {
seapp_contexts_files[files_len++] = seapp_contexts_system_ext[i];
@@ -469,16 +453,6 @@ int selinux_android_seapp_context_reload(void)
free_seapp_context(cur);
goto err;
}
- } else if (!strcasecmp(name, "isOwner")) {
- cur->isOwnerSet = true;
- if (!strcasecmp(value, "true"))
- cur->isOwner = true;
- else if (!strcasecmp(value, "false"))
- cur->isOwner = false;
- else {
- free_seapp_context(cur);
- goto err;
- }
} else if (!strcasecmp(name, "user")) {
if (cur->user.str) {
free_seapp_context(cur);
@@ -579,19 +553,6 @@ int selinux_android_seapp_context_reload(void)
free_seapp_context(cur);
goto oom;
}
- } else if (!strcasecmp(name, "path")) {
- if (cur->path.str) {
- free_seapp_context(cur);
- goto err;
- }
- cur->path.str = strdup(value);
- if (!cur->path.str) {
- free_seapp_context(cur);
- goto oom;
- }
- cur->path.len = strlen(cur->path.str);
- if (cur->path.str[cur->path.len-1] == '*')
- cur->path.is_prefix = 1;
} else if (!strcasecmp(name, "isPrivApp")) {
cur->isPrivAppSet = true;
if (!strcasecmp(value, "true"))
@@ -654,14 +615,13 @@ int selinux_android_seapp_context_reload(void)
int i;
for (i = 0; i < nspec; i++) {
cur = seapp_contexts[i];
- selinux_log(SELINUX_INFO, "%s: isSystemServer=%s isEphemeralApp=%s isOwner=%s user=%s seinfo=%s "
- "name=%s path=%s isPrivApp=%s minTargetSdkVersion=%d fromRunAs=%s -> domain=%s type=%s level=%s levelFrom=%s",
+ selinux_log(SELINUX_INFO, "%s: isSystemServer=%s isEphemeralApp=%s user=%s seinfo=%s "
+ "name=%s isPrivApp=%s minTargetSdkVersion=%d fromRunAs=%s -> domain=%s type=%s level=%s levelFrom=%s",
__FUNCTION__,
cur->isSystemServer ? "true" : "false",
cur->isEphemeralAppSet ? (cur->isEphemeralApp ? "true" : "false") : "null",
- cur->isOwnerSet ? (cur->isOwner ? "true" : "false") : "null",
cur->user.str,
- cur->seinfo, cur->name.str, cur->path.str,
+ cur->seinfo, cur->name.str,
cur->isPrivAppSet ? (cur->isPrivApp ? "true" : "false") : "null",
cur->minTargetSdkVersion,
cur->fromRunAs ? "true" : "false",
@@ -798,11 +758,9 @@ static int seapp_context_lookup(enum seapp_kind kind,
bool isSystemServer,
const char *seinfo,
const char *pkgname,
- const char *path,
context_t ctx)
{
struct passwd *pwd;
- bool isOwner;
const char *username = NULL;
struct seapp_context *cur = NULL;
int i;
@@ -833,7 +791,6 @@ static int seapp_context_lookup(enum seapp_kind kind,
}
userid = uid / AID_USER;
- isOwner = (userid == 0);
appid = uid % AID_USER;
if (appid < AID_APP) {
/*
@@ -849,9 +806,12 @@ static int seapp_context_lookup(enum seapp_kind kind,
username = pwd->pw_name;
- } else if (appid < AID_ISOLATED_START) {
+ } else if (appid < AID_SDK_SANDBOX_PROCESS_START) {
username = "_app";
appid -= AID_APP;
+ } else if (appid < AID_ISOLATED_START) {
+ username = "_sdksandbox";
+ appid -= AID_SDK_SANDBOX_PROCESS_START;
} else {
username = "_isolated";
appid -= AID_ISOLATED_START;
@@ -869,9 +829,6 @@ static int seapp_context_lookup(enum seapp_kind kind,
if (cur->isEphemeralAppSet && cur->isEphemeralApp != isEphemeralApp)
continue;
- if (cur->isOwnerSet && cur->isOwner != isOwner)
- continue;
-
if (cur->user.str) {
if (cur->user.is_prefix) {
if (strncasecmp(username, cur->user.str, cur->user.len-1))
@@ -909,19 +866,6 @@ static int seapp_context_lookup(enum seapp_kind kind,
if (cur->fromRunAs != fromRunAs)
continue;
- if (cur->path.str) {
- if (!path)
- continue;
-
- if (cur->path.is_prefix) {
- if (strncmp(path, cur->path.str, cur->path.len-1))
- continue;
- } else {
- if (strcmp(path, cur->path.str))
- continue;
- }
- }
-
if (kind == SEAPP_TYPE && !cur->type)
continue;
else if (kind == SEAPP_DOMAIN && !cur->domain)
@@ -1045,7 +989,7 @@ int selinux_android_setcontext(uid_t uid,
if (!ctx)
goto oom;
- rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx);
+ rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
if (rc == -1)
goto err;
else if (rc == -2)
@@ -1069,7 +1013,6 @@ int selinux_android_setcontext(uid_t uid,
out:
freecon(orig_ctx_str);
context_free(ctx);
- avc_netlink_close();
return rc;
err:
if (isSystemServer)
@@ -1179,20 +1122,49 @@ struct pkg_info *package_info_lookup(const char *name)
* credentials are presented (filenames inside are mangled), so we need
* to delay restorecon of those until vold explicitly requests it. */
// NOTE: these paths need to be kept in sync with vold
-#define DATA_SYSTEM_CE_PREFIX "/data/system_ce"
-#define DATA_VENDOR_CE_PREFIX "/data/vendor_ce"
-#define DATA_MISC_CE_PREFIX "/data/misc_ce"
+#define DATA_SYSTEM_CE_PATH "/data/system_ce"
+#define DATA_VENDOR_CE_PATH "/data/vendor_ce"
+#define DATA_MISC_CE_PATH "/data/misc_ce"
+#define DATA_MISC_DE_PATH "/data/misc_de"
/* The path prefixes of package data directories. */
#define DATA_DATA_PATH "/data/data"
#define DATA_USER_PATH "/data/user"
#define DATA_USER_DE_PATH "/data/user_de"
-#define EXPAND_USER_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user"
-#define EXPAND_USER_DE_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user_de"
#define USER_PROFILE_PATH "/data/misc/profiles/cur/*"
+#define SDK_SANDBOX_DATA_CE_PATH "/data/misc_ce/*/sdksandbox"
+#define SDK_SANDBOX_DATA_DE_PATH "/data/misc_de/*/sdksandbox"
+
+#define EXPAND_MNT_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?"
+#define EXPAND_USER_PATH EXPAND_MNT_PATH "/user"
+#define EXPAND_USER_DE_PATH EXPAND_MNT_PATH "/user_de"
+#define EXPAND_SDK_CE_PATH EXPAND_MNT_PATH "/misc_ce/*/sdksandbox"
+#define EXPAND_SDK_DE_PATH EXPAND_MNT_PATH "/misc_de/*/sdksandbox"
+
#define DATA_DATA_PREFIX DATA_DATA_PATH "/"
#define DATA_USER_PREFIX DATA_USER_PATH "/"
#define DATA_USER_DE_PREFIX DATA_USER_DE_PATH "/"
+#define DATA_MISC_CE_PREFIX DATA_MISC_CE_PATH "/"
+#define DATA_MISC_DE_PREFIX DATA_MISC_DE_PATH "/"
+#define EXPAND_MNT_PATH_PREFIX EXPAND_MNT_PATH "/"
+
+/*
+ * This method helps in identifying paths that refer to users' app data. Labeling for app data is
+ * based on seapp_contexts and seinfo assignments rather than file_contexts and is managed by
+ * installd rather than by init.
+ */
+static bool is_app_data_path(const char *pathname) {
+ int flags = FNM_LEADING_DIR|FNM_PATHNAME;
+ return (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
+ !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
+ !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
+ !fnmatch(EXPAND_USER_PATH, pathname, flags) ||
+ !fnmatch(EXPAND_USER_DE_PATH, pathname, flags) ||
+ !fnmatch(SDK_SANDBOX_DATA_CE_PATH, pathname, flags) ||
+ !fnmatch(SDK_SANDBOX_DATA_DE_PATH, pathname, flags) ||
+ !fnmatch(EXPAND_SDK_CE_PATH, pathname, flags) ||
+ !fnmatch(EXPAND_SDK_DE_PATH, pathname, flags));
+}
static int pkgdir_selabel_lookup(const char *pathname,
const char *seinfo,
@@ -1240,6 +1212,40 @@ static int pkgdir_selabel_lookup(const char *pathname,
pathname++;
else
return 0;
+ } else if (!strncmp(pathname, DATA_MISC_CE_PREFIX, sizeof(DATA_MISC_CE_PREFIX)-1)) {
+ pathname += sizeof(DATA_MISC_CE_PREFIX) - 1;
+ while (isdigit(*pathname))
+ pathname++;
+ if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1)) {
+ pathname += sizeof("/sdksandbox/") - 1;
+ } else
+ return 0;
+ } else if (!strncmp(pathname, DATA_MISC_DE_PREFIX, sizeof(DATA_MISC_DE_PREFIX)-1)) {
+ pathname += sizeof(DATA_MISC_DE_PREFIX) - 1;
+ while (isdigit(*pathname))
+ pathname++;
+ if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1)) {
+ pathname += sizeof("/sdksandbox/") - 1;
+ } else
+ return 0;
+ } else if (!fnmatch(EXPAND_SDK_CE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
+ pathname += sizeof(EXPAND_MNT_PATH_PREFIX) - 1;
+ pathname += sizeof("misc_ce/") - 1;
+ while (isdigit(*pathname))
+ pathname++;
+ if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1)) {
+ pathname += sizeof("/sdksandbox/") - 1;
+ } else
+ return 0;
+ } else if (!fnmatch(EXPAND_SDK_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
+ pathname += sizeof(EXPAND_MNT_PATH_PREFIX) - 1;
+ pathname += sizeof("misc_de/") - 1;
+ while (isdigit(*pathname))
+ pathname++;
+ if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1)) {
+ pathname += sizeof("/sdksandbox/") - 1;
+ } else
+ return 0;
} else
return 0;
@@ -1272,7 +1278,7 @@ static int pkgdir_selabel_lookup(const char *pathname,
goto err;
rc = seapp_context_lookup(SEAPP_TYPE, info ? info->uid : uid, 0,
- info ? info->seinfo : seinfo, info ? info->name : pkgname, pathname, ctx);
+ info ? info->seinfo : seinfo, info ? info->name : pkgname, ctx);
if (rc < 0)
goto err;
@@ -1300,7 +1306,8 @@ out:
return rc;
err:
selinux_log(SELINUX_ERROR, "%s: Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n",
- __FUNCTION__, pathname, pkgname, info->seinfo, info->uid, strerror(errno));
+ __FUNCTION__, pathname, pkgname, info ? info->seinfo : seinfo,
+ info ? info->uid : uid, strerror(errno));
rc = -1;
goto out;
}
@@ -1327,11 +1334,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,
* have different labeling rules, based off of /seapp_contexts, and
* installd is responsible for managing these labels instead of init.
*/
- if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
- !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
- !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
- !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) ||
- !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
+ if (is_app_data_path(pathname)) {
if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0)
goto err;
}
@@ -1494,11 +1497,7 @@ static int selinux_android_restorecon_common(const char* pathname_orig,
* assignments rather than file_contexts and is managed by
* installd rather than init.
*/
- if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
- !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
- !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
- !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) ||
- !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME))
+ if (is_app_data_path(pathname))
setrestoreconlast = false;
/* Also ignore on /sys since it is regenerated on each boot regardless. */
@@ -1575,20 +1574,15 @@ static int selinux_android_restorecon_common(const char* pathname_orig,
}
if (skipce &&
- (!strncmp(ftsent->fts_path, DATA_SYSTEM_CE_PREFIX, sizeof(DATA_SYSTEM_CE_PREFIX)-1) ||
- !strncmp(ftsent->fts_path, DATA_MISC_CE_PREFIX, sizeof(DATA_MISC_CE_PREFIX)-1) ||
- !strncmp(ftsent->fts_path, DATA_VENDOR_CE_PREFIX, sizeof(DATA_VENDOR_CE_PREFIX)-1))) {
+ (!strncmp(ftsent->fts_path, DATA_SYSTEM_CE_PATH, sizeof(DATA_SYSTEM_CE_PATH)-1) ||
+ !strncmp(ftsent->fts_path, DATA_MISC_CE_PATH, sizeof(DATA_MISC_CE_PATH)-1) ||
+ !strncmp(ftsent->fts_path, DATA_VENDOR_CE_PATH, sizeof(DATA_VENDOR_CE_PATH)-1))) {
// Don't label anything below this directory.
fts_set(fts, ftsent, FTS_SKIP);
// but fall through and make sure we label the directory itself
}
- if (!datadata &&
- (!strcmp(ftsent->fts_path, DATA_DATA_PATH) ||
- !strncmp(ftsent->fts_path, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
- !strncmp(ftsent->fts_path, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
- !fnmatch(EXPAND_USER_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME) ||
- !fnmatch(EXPAND_USER_DE_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME))) {
+ if (!datadata && is_app_data_path(ftsent->fts_path)) {
// Don't label anything below this directory.
fts_set(fts, ftsent, FTS_SKIP);
// but fall through and make sure we label the directory itself
diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c
index d56b56eb..ca38e13c 100644
--- a/libselinux/src/audit2why.c
+++ b/libselinux/src/audit2why.c
@@ -204,8 +204,8 @@ static int __policy_init(const char *init_path)
fp = fopen(path, "re");
if (!fp) {
snprintf(errormsg, sizeof(errormsg),
- "unable to open %s: %s\n",
- path, strerror(errno));
+ "unable to open %s: %m\n",
+ path);
PyErr_SetString( PyExc_ValueError, errormsg);
return 1;
}
@@ -221,9 +221,8 @@ static int __policy_init(const char *init_path)
fp = fopen(curpolicy, "re");
if (!fp) {
snprintf(errormsg, sizeof(errormsg),
- "unable to open %s: %s\n",
- curpolicy,
- strerror(errno));
+ "unable to open %s: %m\n",
+ curpolicy);
PyErr_SetString( PyExc_ValueError, errormsg);
return 1;
}
@@ -242,7 +241,7 @@ static int __policy_init(const char *init_path)
if (sepol_policy_file_create(&pf) ||
sepol_policydb_create(&avc->policydb)) {
snprintf(errormsg, sizeof(errormsg),
- "policydb_init failed: %s\n", strerror(errno));
+ "policydb_init failed: %m\n");
PyErr_SetString( PyExc_RuntimeError, errormsg);
fclose(fp);
return 1;
@@ -275,7 +274,7 @@ static int __policy_init(const char *init_path)
}
sepol_bool_iterate(avc->handle, avc->policydb,
- load_booleans, (void *)NULL);
+ load_booleans, NULL);
/* Initialize the sidtab for subsequent use by sepol_context_to_sid
and sepol_compute_av_reason. */
diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c
index 5230efd2..7493e4b2 100644
--- a/libselinux/src/avc.c
+++ b/libselinux/src/avc.c
@@ -50,7 +50,6 @@ struct avc_callback_node {
struct avc_callback_node *next;
};
-static void *avc_netlink_thread = NULL;
static void *avc_lock = NULL;
static void *avc_log_lock = NULL;
static struct avc_node *avc_node_freelist = NULL;
@@ -145,22 +144,7 @@ int avc_get_initial_sid(const char * name, security_id_t * sid)
return rc;
}
-int avc_open(struct selinux_opt *opts, unsigned nopts)
-{
- avc_setenforce = 0;
-
- while (nopts--)
- switch(opts[nopts].type) {
- case AVC_OPT_SETENFORCE:
- avc_setenforce = 1;
- avc_enforcing = !!opts[nopts].value;
- break;
- }
-
- return avc_init("avc", NULL, NULL, NULL, NULL);
-}
-
-int avc_init(const char *prefix,
+static int avc_init_internal(const char *prefix,
const struct avc_memory_callback *mem_cb,
const struct avc_log_callback *log_cb,
const struct avc_thread_callback *thread_cb,
@@ -222,30 +206,49 @@ int avc_init(const char *prefix,
rc = security_getenforce();
if (rc < 0) {
avc_log(SELINUX_ERROR,
- "%s: could not determine enforcing mode: %s\n",
- avc_prefix,
- strerror(errno));
+ "%s: could not determine enforcing mode: %m\n",
+ avc_prefix);
goto out;
}
avc_enforcing = rc;
}
- rc = avc_netlink_open(0);
+ rc = selinux_status_open(0);
if (rc < 0) {
avc_log(SELINUX_ERROR,
- "%s: can't open netlink socket: %d (%s)\n",
- avc_prefix, errno, strerror(errno));
+ "%s: could not open selinux status page: %d (%m)\n",
+ avc_prefix, errno);
goto out;
}
- if (avc_using_threads) {
- avc_netlink_thread = avc_create_thread(&avc_netlink_loop);
- avc_netlink_trouble = 0;
- }
avc_running = 1;
out:
return rc;
}
+int avc_open(struct selinux_opt *opts, unsigned nopts)
+{
+ avc_setenforce = 0;
+
+ while (nopts--)
+ switch(opts[nopts].type) {
+ case AVC_OPT_SETENFORCE:
+ avc_setenforce = 1;
+ avc_enforcing = !!opts[nopts].value;
+ break;
+ }
+
+ return avc_init_internal("avc", NULL, NULL, NULL, NULL);
+}
+
+int avc_init(const char *prefix,
+ const struct avc_memory_callback *mem_cb,
+ const struct avc_log_callback *log_cb,
+ const struct avc_thread_callback *thread_cb,
+ const struct avc_lock_callback *lock_cb)
+{
+ return avc_init_internal(prefix, mem_cb, log_cb, thread_cb, lock_cb);
+}
+
void avc_cache_stats(struct avc_cache_stats *p)
{
memcpy(p, &cache_stats, sizeof(cache_stats));
@@ -294,7 +297,6 @@ void avc_av_stats(void)
slots_used, AVC_CACHE_SLOTS, max_chain_len);
}
-hidden_def(avc_av_stats)
static inline struct avc_node *avc_reclaim_node(void)
{
@@ -494,7 +496,6 @@ void avc_cleanup(void)
{
}
-hidden_def(avc_cleanup)
int avc_reset(void)
{
@@ -539,7 +540,6 @@ int avc_reset(void)
return rc;
}
-hidden_def(avc_reset)
void avc_destroy(void)
{
@@ -551,9 +551,7 @@ void avc_destroy(void)
avc_get_lock(avc_lock);
- if (avc_using_threads)
- avc_stop_thread(avc_netlink_thread);
- avc_netlink_close();
+ selinux_status_close();
for (i = 0; i < AVC_CACHE_SLOTS; i++) {
node = avc_cache.slots[i];
@@ -733,7 +731,6 @@ void avc_audit(security_id_t ssid, security_id_t tsid,
avc_release_lock(avc_log_lock);
}
-hidden_def(avc_audit)
static void avd_init(struct av_decision *avd)
@@ -761,7 +758,7 @@ int avc_has_perm_noaudit(security_id_t ssid,
avd_init(avd);
if (!avc_using_threads && !avc_app_main_loop) {
- (void)avc_netlink_check_nb();
+ (void) selinux_status_updated();
}
if (!aeref) {
@@ -825,7 +822,6 @@ int avc_has_perm_noaudit(security_id_t ssid,
return rc;
}
-hidden_def(avc_has_perm_noaudit)
int avc_has_perm(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t requested,
diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c
index 568a3d92..71a1357b 100644
--- a/libselinux/src/avc_internal.c
+++ b/libselinux/src/avc_internal.c
@@ -53,6 +53,49 @@ int avc_enforcing = 1;
int avc_setenforce = 0;
int avc_netlink_trouble = 0;
+/* process setenforce events for netlink and sestatus */
+int avc_process_setenforce(int enforcing)
+{
+ int rc = 0;
+
+ avc_log(SELINUX_SETENFORCE,
+ "%s: op=setenforce lsm=selinux enforcing=%d res=1",
+ avc_prefix, enforcing);
+ if (avc_setenforce)
+ goto out;
+ avc_enforcing = enforcing;
+ if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
+ avc_log(SELINUX_ERROR,
+ "%s: cache reset returned %d (errno %d)\n",
+ avc_prefix, rc, errno);
+ return rc;
+ }
+
+out:
+ return selinux_netlink_setenforce(enforcing);
+}
+
+/* process policyload events for netlink and sestatus */
+int avc_process_policyload(uint32_t seqno)
+{
+ int rc = 0;
+
+ avc_log(SELINUX_POLICYLOAD,
+ "%s: op=load_policy lsm=selinux seqno=%u res=1",
+ avc_prefix, seqno);
+ rc = avc_ss_reset(seqno);
+ if (rc < 0) {
+ avc_log(SELINUX_ERROR,
+ "%s: cache reset returned %d (errno %d)\n",
+ avc_prefix, rc, errno);
+ return rc;
+ }
+
+ selinux_flush_class_cache();
+
+ return selinux_netlink_policyload(seqno);
+}
+
/* netlink socket code */
static int fd = -1;
@@ -177,20 +220,7 @@ static int avc_netlink_process(void *buf)
case SELNL_MSG_SETENFORCE:{
struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
- msg->val = !!msg->val;
- avc_log(SELINUX_INFO,
- "%s: received setenforce notice (enforcing=%d)\n",
- avc_prefix, msg->val);
- if (avc_setenforce)
- break;
- avc_enforcing = msg->val;
- if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
- avc_log(SELINUX_ERROR,
- "%s: cache reset returned %d (errno %d)\n",
- avc_prefix, rc, errno);
- return rc;
- }
- rc = selinux_netlink_setenforce(msg->val);
+ rc = avc_process_setenforce(!!msg->val);
if (rc < 0)
return rc;
break;
@@ -198,18 +228,7 @@ static int avc_netlink_process(void *buf)
case SELNL_MSG_POLICYLOAD:{
struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
- avc_log(SELINUX_INFO,
- "%s: received policyload notice (seqno=%u)\n",
- avc_prefix, msg->seqno);
- rc = avc_ss_reset(msg->seqno);
- if (rc < 0) {
- avc_log(SELINUX_ERROR,
- "%s: cache reset returned %d (errno %d)\n",
- avc_prefix, rc, errno);
- return rc;
- }
- selinux_flush_class_cache();
- rc = selinux_netlink_policyload(msg->seqno);
+ rc = avc_process_policyload(msg->seqno);
if (rc < 0)
return rc;
break;
@@ -284,6 +303,17 @@ void avc_netlink_loop(void)
int avc_netlink_acquire_fd(void)
{
+ if (fd < 0) {
+ int rc = 0;
+ rc = avc_netlink_open(0);
+ if (rc < 0) {
+ avc_log(SELINUX_ERROR,
+ "%s: could not open netlink socket: %d (%m)\n",
+ avc_prefix, errno);
+ return rc;
+ }
+ }
+
avc_app_main_loop = 1;
return fd;
diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h
index f8516590..a9a4aa0b 100644
--- a/libselinux/src/avc_internal.h
+++ b/libselinux/src/avc_internal.h
@@ -14,24 +14,27 @@
#include <string.h>
#include <selinux/avc.h>
#include "callbacks.h"
-#include "dso.h"
/* callback pointers */
-extern void *(*avc_func_malloc) (size_t) hidden;
-extern void (*avc_func_free) (void *)hidden;
+extern void *(*avc_func_malloc) (size_t) ;
+extern void (*avc_func_free) (void *);
-extern void (*avc_func_log) (const char *, ...) __attribute__((__format__(printf,1,2))) hidden;
-extern void (*avc_func_audit) (void *, security_class_t, char *, size_t)hidden;
+extern void (*avc_func_log) (const char *, ...) __attribute__((__format__(printf,1,2))) ;
+extern void (*avc_func_audit) (void *, security_class_t, char *, size_t);
-extern int avc_using_threads hidden;
-extern int avc_app_main_loop hidden;
-extern void *(*avc_func_create_thread) (void (*)(void))hidden;
-extern void (*avc_func_stop_thread) (void *)hidden;
+extern int avc_using_threads ;
+extern int avc_app_main_loop ;
+extern void *(*avc_func_create_thread) (void (*)(void));
+extern void (*avc_func_stop_thread) (void *);
-extern void *(*avc_func_alloc_lock) (void)hidden;
-extern void (*avc_func_get_lock) (void *)hidden;
-extern void (*avc_func_release_lock) (void *)hidden;
-extern void (*avc_func_free_lock) (void *)hidden;
+extern void *(*avc_func_alloc_lock) (void);
+extern void (*avc_func_get_lock) (void *);
+extern void (*avc_func_release_lock) (void *);
+extern void (*avc_func_free_lock) (void *);
+
+/* selinux status processing for netlink and sestatus */
+extern int avc_process_setenforce(int enforcing);
+extern int avc_process_policyload(uint32_t seqno);
static inline void set_callbacks(const struct avc_memory_callback *mem_cb,
const struct avc_log_callback *log_cb,
@@ -61,10 +64,10 @@ static inline void set_callbacks(const struct avc_memory_callback *mem_cb,
/* message prefix and enforcing mode*/
#define AVC_PREFIX_SIZE 16
-extern char avc_prefix[AVC_PREFIX_SIZE] hidden;
-extern int avc_running hidden;
-extern int avc_enforcing hidden;
-extern int avc_setenforce hidden;
+extern char avc_prefix[AVC_PREFIX_SIZE] ;
+extern int avc_running ;
+extern int avc_enforcing ;
+extern int avc_setenforce ;
/* user-supplied callback interface for avc */
static inline void *avc_malloc(size_t size)
@@ -82,10 +85,12 @@ static inline void avc_free(void *ptr)
/* this is a macro in order to use the variadic capability. */
#define avc_log(type, format...) \
- if (avc_func_log) \
- avc_func_log(format); \
- else \
- selinux_log(type, format);
+ do { \
+ if (avc_func_log) \
+ avc_func_log(format); \
+ else \
+ selinux_log(type, format); \
+ } while (0)
static inline void avc_suppl_audit(void *ptr, security_class_t class,
char *buf, size_t len)
@@ -134,14 +139,18 @@ static inline void avc_free_lock(void *lock)
#ifdef AVC_CACHE_STATS
#define avc_cache_stats_incr(field) \
- cache_stats.field ++;
+ do { \
+ cache_stats.field ++; \
+ } while (0)
#define avc_cache_stats_add(field, num) \
- cache_stats.field += num;
+ do { \
+ cache_stats.field += num; \
+ } while (0)
#else
-#define avc_cache_stats_incr(field)
-#define avc_cache_stats_add(field, num)
+#define avc_cache_stats_incr(field) do {} while (0)
+#define avc_cache_stats_add(field, num) do {} while (0)
#endif
@@ -155,28 +164,23 @@ static inline void avc_free_lock(void *lock)
/* internal callbacks */
int avc_ss_grant(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t perms,
- uint32_t seqno) hidden;
+ uint32_t seqno) ;
int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid,
security_class_t tclass,
access_vector_t perms, uint32_t seqno,
- access_vector_t * out_retained) hidden;
+ access_vector_t * out_retained) ;
int avc_ss_revoke(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t perms,
- uint32_t seqno) hidden;
-int avc_ss_reset(uint32_t seqno) hidden;
+ uint32_t seqno) ;
+int avc_ss_reset(uint32_t seqno) ;
int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t perms,
- uint32_t seqno, uint32_t enable) hidden;
+ uint32_t seqno, uint32_t enable) ;
int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t perms,
- uint32_t seqno, uint32_t enable) hidden;
+ uint32_t seqno, uint32_t enable) ;
/* netlink kernel message code */
-extern int avc_netlink_trouble hidden;
+extern int avc_netlink_trouble ;
-hidden_proto(avc_av_stats)
- hidden_proto(avc_cleanup)
- hidden_proto(avc_reset)
- hidden_proto(avc_audit)
- hidden_proto(avc_has_perm_noaudit)
#endif /* _SELINUX_AVC_INTERNAL_H_ */
diff --git a/libselinux/src/avc_sidtab.c b/libselinux/src/avc_sidtab.c
index 9669264d..f179d855 100644
--- a/libselinux/src/avc_sidtab.c
+++ b/libselinux/src/avc_sidtab.c
@@ -15,14 +15,13 @@
static inline unsigned sidtab_hash(const char * key)
{
- char *p, *keyp;
+ const char *p;
unsigned int size;
unsigned int val;
val = 0;
- keyp = (char *)key;
- size = strlen(keyp);
- for (p = keyp; (unsigned int)(p - keyp) < size; p++)
+ size = strlen(key);
+ for (p = key; (unsigned int)(p - key) < size; p++)
val =
(val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val & (SIDTAB_SIZE - 1);
@@ -57,7 +56,7 @@ int sidtab_insert(struct sidtab *s, const char * ctx)
rc = -1;
goto out;
}
- newctx = (char *) strdup(ctx);
+ newctx = strdup(ctx);
if (!newctx) {
rc = -1;
avc_free(newnode);
@@ -101,7 +100,7 @@ sidtab_context_to_sid(struct sidtab *s,
return rc;
}
-void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
+void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen)
{
int i, chain_len, slots_used, max_chain_len;
struct sidtab_node *cur;
@@ -109,7 +108,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
slots_used = 0;
max_chain_len = 0;
for (i = 0; i < SIDTAB_SIZE; i++) {
- cur = h->htable[i];
+ cur = s->htable[i];
if (cur) {
slots_used++;
chain_len = 0;
@@ -125,7 +124,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
snprintf(buf, buflen,
"%s: %u SID entries and %d/%d buckets used, longest "
- "chain length %d\n", avc_prefix, h->nel, slots_used,
+ "chain length %d\n", avc_prefix, s->nel, slots_used,
SIDTAB_SIZE, max_chain_len);
}
diff --git a/libselinux/src/avc_sidtab.h b/libselinux/src/avc_sidtab.h
index bce9b877..cc5abe35 100644
--- a/libselinux/src/avc_sidtab.h
+++ b/libselinux/src/avc_sidtab.h
@@ -7,7 +7,6 @@
#include <selinux/selinux.h>
#include <selinux/avc.h>
-#include "dso.h"
struct sidtab_node {
struct security_id sid_s;
@@ -24,13 +23,13 @@ struct sidtab {
unsigned nel;
};
-int sidtab_init(struct sidtab *s) hidden;
-int sidtab_insert(struct sidtab *s, const char * ctx) hidden;
+int sidtab_init(struct sidtab *s) ;
+int sidtab_insert(struct sidtab *s, const char * ctx) ;
int sidtab_context_to_sid(struct sidtab *s,
- const char * ctx, security_id_t * sid) hidden;
+ const char * ctx, security_id_t * sid) ;
-void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) hidden;
-void sidtab_destroy(struct sidtab *s) hidden;
+void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) ;
+void sidtab_destroy(struct sidtab *s) ;
#endif /* _SELINUX_AVC_SIDTAB_H_ */
diff --git a/libselinux/src/booleans.c b/libselinux/src/booleans.c
index ffa8d26b..ef1f64a0 100644
--- a/libselinux/src/booleans.c
+++ b/libselinux/src/booleans.c
@@ -414,8 +414,3 @@ char *selinux_boolean_sub(const char *name __attribute__((unused)))
}
#endif
-hidden_def(security_get_boolean_names)
-hidden_def(selinux_boolean_sub)
-hidden_def(security_get_boolean_active)
-hidden_def(security_set_boolean)
-hidden_def(security_commit_booleans)
diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c
index c18ccc54..469c4055 100644
--- a/libselinux/src/callbacks.c
+++ b/libselinux/src/callbacks.c
@@ -10,6 +10,8 @@
#include <selinux/selinux.h>
#include "callbacks.h"
+pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
+
/* default implementations */
static int __attribute__ ((format(printf, 2, 3)))
default_selinux_log(int type __attribute__((unused)), const char *fmt, ...)
@@ -56,7 +58,7 @@ default_selinux_policyload(int seqno __attribute__((unused)))
/* callback pointers */
int __attribute__ ((format(printf, 2, 3)))
-(*selinux_log)(int, const char *, ...) =
+(*selinux_log_direct)(int, const char *, ...) =
default_selinux_log;
int
@@ -81,7 +83,7 @@ selinux_set_callback(int type, union selinux_callback cb)
{
switch (type) {
case SELINUX_CB_LOG:
- selinux_log = cb.func_log;
+ selinux_log_direct = cb.func_log;
break;
case SELINUX_CB_AUDIT:
selinux_audit = cb.func_audit;
@@ -106,7 +108,7 @@ selinux_get_callback(int type)
switch (type) {
case SELINUX_CB_LOG:
- cb.func_log = selinux_log;
+ cb.func_log = selinux_log_direct;
break;
case SELINUX_CB_AUDIT:
cb.func_audit = selinux_audit;
diff --git a/libselinux/src/callbacks.h b/libselinux/src/callbacks.h
index 2a572e08..f4dab157 100644
--- a/libselinux/src/callbacks.h
+++ b/libselinux/src/callbacks.h
@@ -9,22 +9,32 @@
#include <stdlib.h>
#include <string.h>
#include <selinux/selinux.h>
-#include "dso.h"
+
+#include "selinux_internal.h"
/* callback pointers */
extern int __attribute__ ((format(printf, 2, 3)))
-(*selinux_log) (int type, const char *, ...) hidden;
+(*selinux_log_direct) (int type, const char *, ...) ;
extern int
-(*selinux_audit) (void *, security_class_t, char *, size_t) hidden;
+(*selinux_audit) (void *, security_class_t, char *, size_t) ;
extern int
-(*selinux_validate)(char **ctx) hidden;
+(*selinux_validate)(char **ctx) ;
extern int
-(*selinux_netlink_setenforce) (int enforcing) hidden;
+(*selinux_netlink_setenforce) (int enforcing) ;
extern int
-(*selinux_netlink_policyload) (int seqno) hidden;
+(*selinux_netlink_policyload) (int seqno) ;
+
+/* Thread-safe selinux_log() function */
+extern pthread_mutex_t log_mutex;
+
+#define selinux_log(type, ...) do { \
+ __pthread_mutex_lock(&log_mutex); \
+ selinux_log_direct(type, __VA_ARGS__); \
+ __pthread_mutex_unlock(&log_mutex); \
+} while(0)
#endif /* _SELINUX_CALLBACKS_H_ */
diff --git a/libselinux/src/canonicalize_context.c b/libselinux/src/canonicalize_context.c
index ba4c9a2c..faab7305 100644
--- a/libselinux/src/canonicalize_context.c
+++ b/libselinux/src/canonicalize_context.c
@@ -60,7 +60,6 @@ int security_canonicalize_context_raw(const char * con,
return ret;
}
-hidden_def(security_canonicalize_context_raw)
int security_canonicalize_context(const char * con,
char ** canoncon)
@@ -83,4 +82,3 @@ int security_canonicalize_context(const char * con,
return ret;
}
-hidden_def(security_canonicalize_context)
diff --git a/libselinux/src/checkAccess.c b/libselinux/src/checkAccess.c
index 7227ffe5..022cd6b5 100644
--- a/libselinux/src/checkAccess.c
+++ b/libselinux/src/checkAccess.c
@@ -39,7 +39,7 @@ int selinux_check_access(const char *scon, const char *tcon, const char *class,
if (rc < 0)
return rc;
- (void) avc_netlink_check_nb();
+ (void) selinux_status_updated();
sclass = string_to_security_class(class);
if (sclass == 0) {
@@ -64,7 +64,7 @@ int selinux_check_access(const char *scon, const char *tcon, const char *class,
return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux);
}
-int selinux_check_passwd_access(access_vector_t requested)
+static int selinux_check_passwd_access_internal(access_vector_t requested)
{
int status = -1;
char *user_context;
@@ -78,7 +78,9 @@ int selinux_check_passwd_access(access_vector_t requested)
passwd_class = string_to_security_class("passwd");
if (passwd_class == 0) {
freecon(user_context);
- return 0;
+ if (security_deny_unknown() == 0)
+ return 0;
+ return -1;
}
retval = security_compute_av_raw(user_context,
@@ -99,9 +101,11 @@ int selinux_check_passwd_access(access_vector_t requested)
return status;
}
-hidden_def(selinux_check_passwd_access)
+int selinux_check_passwd_access(access_vector_t requested) {
+ return selinux_check_passwd_access_internal(requested);
+}
int checkPasswdAccess(access_vector_t requested)
{
- return selinux_check_passwd_access(requested);
+ return selinux_check_passwd_access_internal(requested);
}
diff --git a/libselinux/src/check_context.c b/libselinux/src/check_context.c
index 8a7997f0..5096a2c4 100644
--- a/libselinux/src/check_context.c
+++ b/libselinux/src/check_context.c
@@ -31,7 +31,6 @@ int security_check_context_raw(const char * con)
return 0;
}
-hidden_def(security_check_context_raw)
int security_check_context(const char * con)
{
@@ -48,4 +47,3 @@ int security_check_context(const char * con)
return ret;
}
-hidden_def(security_check_context)
diff --git a/libselinux/src/checkreqprot.c b/libselinux/src/checkreqprot.c
index 9b4b12d7..3dc79d97 100644
--- a/libselinux/src/checkreqprot.c
+++ b/libselinux/src/checkreqprot.c
@@ -37,4 +37,3 @@ int security_get_checkreqprot(void)
return checkreqprot;
}
-hidden_def(security_get_checkreqprot);
diff --git a/libselinux/src/compute_av.c b/libselinux/src/compute_av.c
index a47cffe9..9d17339d 100644
--- a/libselinux/src/compute_av.c
+++ b/libselinux/src/compute_av.c
@@ -80,7 +80,6 @@ int security_compute_av_flags_raw(const char * scon,
return ret;
}
-hidden_def(security_compute_av_flags_raw)
int security_compute_av_raw(const char * scon,
const char * tcon,
@@ -107,7 +106,6 @@ int security_compute_av_raw(const char * scon,
return ret;
}
-hidden_def(security_compute_av_raw)
int security_compute_av_flags(const char * scon,
const char * tcon,
@@ -134,7 +132,6 @@ int security_compute_av_flags(const char * scon,
return ret;
}
-hidden_def(security_compute_av_flags)
int security_compute_av(const char * scon,
const char * tcon,
@@ -162,4 +159,3 @@ int security_compute_av(const char * scon,
return ret;
}
-hidden_def(security_compute_av)
diff --git a/libselinux/src/compute_create.c b/libselinux/src/compute_create.c
index 0975aeac..1d75714d 100644
--- a/libselinux/src/compute_create.c
+++ b/libselinux/src/compute_create.c
@@ -105,7 +105,6 @@ int security_compute_create_name_raw(const char * scon,
close(fd);
return ret;
}
-hidden_def(security_compute_create_name_raw)
int security_compute_create_raw(const char * scon,
const char * tcon,
@@ -115,7 +114,6 @@ int security_compute_create_raw(const char * scon,
return security_compute_create_name_raw(scon, tcon, tclass,
NULL, newcon);
}
-hidden_def(security_compute_create_raw)
int security_compute_create_name(const char * scon,
const char * tcon,
@@ -146,7 +144,6 @@ int security_compute_create_name(const char * scon,
return ret;
}
-hidden_def(security_compute_create_name)
int security_compute_create(const char * scon,
const char * tcon,
@@ -155,4 +152,3 @@ int security_compute_create(const char * scon,
{
return security_compute_create_name(scon, tcon, tclass, NULL, newcon);
}
-hidden_def(security_compute_create)
diff --git a/libselinux/src/compute_member.c b/libselinux/src/compute_member.c
index 4e2d221e..16234b79 100644
--- a/libselinux/src/compute_member.c
+++ b/libselinux/src/compute_member.c
@@ -60,7 +60,6 @@ int security_compute_member_raw(const char * scon,
return ret;
}
-hidden_def(security_compute_member_raw)
int security_compute_member(const char * scon,
const char * tcon,
diff --git a/libselinux/src/compute_relabel.c b/libselinux/src/compute_relabel.c
index 49f77ef3..dd20d652 100644
--- a/libselinux/src/compute_relabel.c
+++ b/libselinux/src/compute_relabel.c
@@ -60,7 +60,6 @@ int security_compute_relabel_raw(const char * scon,
return ret;
}
-hidden_def(security_compute_relabel_raw)
int security_compute_relabel(const char * scon,
const char * tcon,
diff --git a/libselinux/src/compute_user.c b/libselinux/src/compute_user.c
index 7b881215..ae5e7b4a 100644
--- a/libselinux/src/compute_user.c
+++ b/libselinux/src/compute_user.c
@@ -8,6 +8,7 @@
#include "selinux_internal.h"
#include "policy.h"
#include <limits.h>
+#include "callbacks.h"
int security_compute_user_raw(const char * scon,
const char *user, char *** con)
@@ -24,6 +25,8 @@ int security_compute_user_raw(const char * scon,
return -1;
}
+ selinux_log(SELINUX_WARNING, "Direct use of security_compute_user() is deprecated, switch to get_ordered_context_list()\n");
+
snprintf(path, sizeof path, "%s/user", selinux_mnt);
fd = open(path, O_RDWR | O_CLOEXEC);
if (fd < 0)
@@ -77,7 +80,6 @@ int security_compute_user_raw(const char * scon,
return ret;
}
-hidden_def(security_compute_user_raw)
int security_compute_user(const char * scon,
const char *user, char *** con)
@@ -107,4 +109,3 @@ int security_compute_user(const char * scon,
return ret;
}
-hidden_def(security_compute_user)
diff --git a/libselinux/src/context.c b/libselinux/src/context.c
index b673733e..b2144c7c 100644
--- a/libselinux/src/context.c
+++ b/libselinux/src/context.c
@@ -37,7 +37,7 @@ context_t context_new(const char *str)
}
n->current_str = n->component[0] = n->component[1] = n->component[2] =
n->component[3] = 0;
- for (i = count = 0, p = str; *p; p++) {
+ for (count = 0, p = str; *p; p++) {
switch (*p) {
case ':':
count++;
@@ -82,7 +82,6 @@ context_t context_new(const char *str)
return 0;
}
-hidden_def(context_new)
static void conditional_free(char **v)
{
@@ -113,7 +112,6 @@ void context_free(context_t context)
}
}
-hidden_def(context_free)
/*
* Return a pointer to the string value of the context.
@@ -144,7 +142,6 @@ char *context_str(context_t context)
return n->current_str;
}
-hidden_def(context_str)
/* Returns nonzero iff failed */
static int set_comp(context_private_t * n, int idx, const char *str)
@@ -154,14 +151,14 @@ static int set_comp(context_private_t * n, int idx, const char *str)
if (str) {
t = (char *)malloc(strlen(str) + 1);
if (!t) {
- return 1;
+ return -1;
}
for (p = str; *p; p++) {
if (*p == '\t' || *p == '\n' || *p == '\r' ||
((*p == ':' || *p == ' ') && idx != COMP_RANGE)) {
free(t);
errno = EINVAL;
- return 1;
+ return -1;
}
}
strcpy(t, str);
@@ -176,8 +173,7 @@ const char * context_ ## name ## _get(context_t context) \
{ \
context_private_t *n = context->ptr; \
return n->component[tag]; \
-} \
-hidden_def(context_ ## name ## _get)
+}
def_get(type, COMP_TYPE)
def_get(user, COMP_USER)
@@ -187,8 +183,7 @@ def_get(type, COMP_TYPE)
int context_ ## name ## _set(context_t context, const char* str) \
{ \
return set_comp(context->ptr,tag,str);\
-} \
-hidden_def(context_ ## name ## _set)
+}
def_set(type, COMP_TYPE)
def_set(role, COMP_ROLE)
def_set(user, COMP_USER)
diff --git a/libselinux/src/context_internal.h b/libselinux/src/context_internal.h
index 3c71e802..a7698106 100644
--- a/libselinux/src/context_internal.h
+++ b/libselinux/src/context_internal.h
@@ -1,14 +1,2 @@
#include <selinux/context.h>
-#include "dso.h"
-hidden_proto(context_new)
- hidden_proto(context_free)
- hidden_proto(context_str)
- hidden_proto(context_type_set)
- hidden_proto(context_type_get)
- hidden_proto(context_role_set)
- hidden_proto(context_role_get)
- hidden_proto(context_user_set)
- hidden_proto(context_user_get)
- hidden_proto(context_range_set)
- hidden_proto(context_range_get)
diff --git a/libselinux/src/deny_unknown.c b/libselinux/src/deny_unknown.c
index 77d04e37..fdd32b50 100644
--- a/libselinux/src/deny_unknown.c
+++ b/libselinux/src/deny_unknown.c
@@ -37,4 +37,3 @@ int security_deny_unknown(void)
return deny_unknown;
}
-hidden_def(security_deny_unknown);
diff --git a/libselinux/src/disable.c b/libselinux/src/disable.c
index 8d66262a..1a5ae417 100644
--- a/libselinux/src/disable.c
+++ b/libselinux/src/disable.c
@@ -35,4 +35,3 @@ int security_disable(void)
return 0;
}
-hidden_def(security_disable)
diff --git a/libselinux/src/dso.h b/libselinux/src/dso.h
deleted file mode 100644
index 12c3d116..00000000
--- a/libselinux/src/dso.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _SELINUX_DSO_H
-#define _SELINUX_DSO_H 1
-
-#ifdef SHARED
-# define hidden __attribute__ ((visibility ("hidden")))
-# define hidden_proto(fct) __hidden_proto (fct, fct##_internal)
-# define __hidden_proto(fct, internal) \
- extern __typeof (fct) internal; \
- extern __typeof (fct) fct __asm (#internal) hidden;
-# if defined(__alpha__) || defined(__mips__)
-# define hidden_def(fct) \
- asm (".globl " #fct "\n" #fct " = " #fct "_internal");
-# else
-# define hidden_def(fct) \
- asm (".globl " #fct "\n.set " #fct ", " #fct "_internal");
-#endif
-#else
-# define hidden
-# define hidden_proto(fct)
-# define hidden_def(fct)
-#endif
-
-#endif
diff --git a/libselinux/src/enabled.c b/libselinux/src/enabled.c
index dd628fba..fefb0bd9 100644
--- a/libselinux/src/enabled.c
+++ b/libselinux/src/enabled.c
@@ -20,7 +20,6 @@ int is_selinux_enabled(void)
#endif
}
-hidden_def(is_selinux_enabled)
/*
* Function: is_selinux_mls_enabled()
@@ -55,4 +54,3 @@ int is_selinux_mls_enabled(void)
return enabled;
}
-hidden_def(is_selinux_mls_enabled)
diff --git a/libselinux/src/exception.sh b/libselinux/src/exception.sh
index 33ceef80..3b7f2450 100755
--- a/libselinux/src/exception.sh
+++ b/libselinux/src/exception.sh
@@ -1,3 +1,5 @@
+#!/bin/bash
+
function except() {
case $1 in
selinux_file_context_cmp) # ignore
@@ -10,15 +12,26 @@ echo "
PyErr_SetFromErrno(PyExc_OSError);
SWIG_fail;
}
-}
-"
+}"
;;
esac
}
-if ! ${CC:-gcc} -x c -c -I../include -o temp.o - -aux-info temp.aux < ../include/selinux/selinux.h
+
+# Make sure that selinux.h is included first in order not to depend on the order
+# in which "#include <selinux/selinux.h>" appears in other files.
+FILE_LIST=(
+ ../include/selinux/selinux.h
+ ../include/selinux/avc.h
+ ../include/selinux/context.h
+ ../include/selinux/get_context_list.h
+ ../include/selinux/get_default_type.h
+ ../include/selinux/label.h
+ ../include/selinux/restorecon.h
+)
+if ! cat "${FILE_LIST[@]}" | ${CC:-gcc} -x c -c -I../include -o temp.o - -aux-info temp.aux
then
# clang does not support -aux-info so fall back to gcc
- gcc -x c -c -I../include -o temp.o - -aux-info temp.aux < ../include/selinux/selinux.h
+ cat "${FILE_LIST[@]}" | gcc -x c -c -I../include -o temp.o - -aux-info temp.aux
fi
for i in `awk '/<stdin>.*extern int/ { print $6 }' temp.aux`; do except $i ; done
rm -f -- temp.aux temp.o
diff --git a/libselinux/src/fgetfilecon.c b/libselinux/src/fgetfilecon.c
index 5522ac16..8c748f8a 100644
--- a/libselinux/src/fgetfilecon.c
+++ b/libselinux/src/fgetfilecon.c
@@ -49,7 +49,6 @@ int fgetfilecon_raw(int fd, char ** context)
return ret;
}
-hidden_def(fgetfilecon_raw)
int fgetfilecon(int fd, char ** context)
{
diff --git a/libselinux/src/freecon.c b/libselinux/src/freecon.c
index 5290dfa1..df2d7e28 100644
--- a/libselinux/src/freecon.c
+++ b/libselinux/src/freecon.c
@@ -8,4 +8,3 @@ void freecon(char * con)
free(con);
}
-hidden_def(freecon)
diff --git a/libselinux/src/freeconary.c b/libselinux/src/freeconary.c
index 8d07718e..fd2dbaab 100644
--- a/libselinux/src/freeconary.c
+++ b/libselinux/src/freeconary.c
@@ -16,4 +16,3 @@ void freeconary(char ** con)
free(con);
}
-hidden_def(freeconary)
diff --git a/libselinux/src/fsetfilecon.c b/libselinux/src/fsetfilecon.c
index 52707d05..5cf34e3f 100644
--- a/libselinux/src/fsetfilecon.c
+++ b/libselinux/src/fsetfilecon.c
@@ -25,7 +25,6 @@ int fsetfilecon_raw(int fd, const char * context)
return rc;
}
-hidden_def(fsetfilecon_raw)
int fsetfilecon(int fd, const char *context)
{
diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c
index 689e4658..cfe38e59 100644
--- a/libselinux/src/get_context_list.c
+++ b/libselinux/src/get_context_list.c
@@ -2,6 +2,7 @@
#include <errno.h>
#include <stdio.h>
#include <stdio_ext.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -12,7 +13,7 @@
int get_default_context_with_role(const char *user,
const char *role,
- char * fromcon,
+ const char *fromcon,
char ** newcon)
{
char **conary;
@@ -51,28 +52,28 @@ int get_default_context_with_role(const char *user,
return rc;
}
-hidden_def(get_default_context_with_role)
int get_default_context_with_rolelevel(const char *user,
const char *role,
const char *level,
- char * fromcon,
+ const char *fromcon,
char ** newcon)
{
- int rc = 0;
- int freefrom = 0;
+ int rc;
+ char *backup_fromcon = NULL;
context_t con;
- char *newfromcon;
+ const char *newfromcon;
+
if (!level)
return get_default_context_with_role(user, role, fromcon,
newcon);
if (!fromcon) {
- rc = getcon(&fromcon);
+ rc = getcon(&backup_fromcon);
if (rc < 0)
return rc;
- freefrom = 1;
+ fromcon = backup_fromcon;
}
rc = -1;
@@ -91,14 +92,13 @@ int get_default_context_with_rolelevel(const char *user,
out:
context_free(con);
- if (freefrom)
- freecon(fromcon);
+ freecon(backup_fromcon);
return rc;
}
int get_default_context(const char *user,
- char * fromcon, char ** newcon)
+ const char *fromcon, char ** newcon)
{
char **conary;
int rc;
@@ -114,64 +114,41 @@ int get_default_context(const char *user,
return 0;
}
-static int find_partialcon(char ** list,
- unsigned int nreach, char *part)
+static int is_in_reachable(char **reachable, const char *usercon_str)
{
- const char *conrole, *contype;
- char *partrole, *parttype, *ptr;
- context_t con;
- unsigned int i;
+ if (!reachable)
+ return 0;
- partrole = part;
- ptr = part;
- while (*ptr && !isspace(*ptr) && *ptr != ':')
- ptr++;
- if (*ptr != ':')
- return -1;
- *ptr++ = 0;
- parttype = ptr;
- while (*ptr && !isspace(*ptr) && *ptr != ':')
- ptr++;
- *ptr = 0;
-
- for (i = 0; i < nreach; i++) {
- con = context_new(list[i]);
- if (!con)
- return -1;
- conrole = context_role_get(con);
- contype = context_type_get(con);
- if (!conrole || !contype) {
- context_free(con);
- return -1;
- }
- if (!strcmp(conrole, partrole) && !strcmp(contype, parttype)) {
- context_free(con);
- return i;
+ for (; *reachable != NULL; reachable++) {
+ if (strcmp(*reachable, usercon_str) == 0) {
+ return 1;
}
- context_free(con);
}
-
- return -1;
+ return 0;
}
-static int get_context_order(FILE * fp,
- char * fromcon,
- char ** reachable,
- unsigned int nreach,
- unsigned int *ordering, unsigned int *nordered)
+static int get_context_user(FILE * fp,
+ const char * fromcon,
+ const char * user,
+ char ***reachable,
+ unsigned int *nreachable)
{
char *start, *end = NULL;
char *line = NULL;
- size_t line_len = 0;
+ size_t line_len = 0, usercon_len;
+ size_t user_len = strlen(user);
ssize_t len;
int found = 0;
- const char *fromrole, *fromtype;
+ const char *fromrole, *fromtype, *fromlevel;
char *linerole, *linetype;
- unsigned int i;
+ char **new_reachable = NULL;
+ char *usercon_str;
context_t con;
+ context_t usercon;
+
int rc;
- errno = -EINVAL;
+ errno = EINVAL;
/* Extract the role and type of the fromcon for matching.
User identity and MLS range can be variable. */
@@ -180,6 +157,7 @@ static int get_context_order(FILE * fp,
return -1;
fromrole = context_role_get(con);
fromtype = context_type_get(con);
+ fromlevel = context_range_get(con);
if (!fromrole || !fromtype) {
context_free(con);
return -1;
@@ -243,23 +221,75 @@ static int get_context_order(FILE * fp,
if (*end)
*end++ = 0;
- /* Check for a match in the reachable list. */
- rc = find_partialcon(reachable, nreach, start);
- if (rc < 0) {
- /* No match, skip it. */
+ /* Check whether a new context is valid */
+ if (SIZE_MAX - user_len < strlen(start) + 2) {
+ fprintf(stderr, "%s: one of partial contexts is too big\n", __FUNCTION__);
+ errno = EINVAL;
+ rc = -1;
+ goto out;
+ }
+ usercon_len = user_len + strlen(start) + 2;
+ usercon_str = malloc(usercon_len);
+ if (!usercon_str) {
+ rc = -1;
+ goto out;
+ }
+
+ /* set range from fromcon in the new usercon */
+ snprintf(usercon_str, usercon_len, "%s:%s", user, start);
+ usercon = context_new(usercon_str);
+ if (!usercon) {
+ if (errno != EINVAL) {
+ free(usercon_str);
+ rc = -1;
+ goto out;
+ }
+ fprintf(stderr,
+ "%s: can't create a context from %s, skipping\n",
+ __FUNCTION__, usercon_str);
+ free(usercon_str);
start = end;
continue;
}
+ free(usercon_str);
+ if (context_range_set(usercon, fromlevel) != 0) {
+ context_free(usercon);
+ rc = -1;
+ goto out;
+ }
+ usercon_str = context_str(usercon);
+ if (!usercon_str) {
+ context_free(usercon);
+ rc = -1;
+ goto out;
+ }
- /* If a match is found and the entry is not already ordered
- (e.g. due to prior match in prior config file), then set
- the ordering for it. */
- i = rc;
- if (ordering[i] == nreach)
- ordering[i] = (*nordered)++;
+ /* check whether usercon is already in reachable */
+ if (is_in_reachable(*reachable, usercon_str)) {
+ context_free(usercon);
+ start = end;
+ continue;
+ }
+ if (security_check_context(usercon_str) == 0) {
+ new_reachable = realloc(*reachable, (*nreachable + 2) * sizeof(char *));
+ if (!new_reachable) {
+ context_free(usercon);
+ rc = -1;
+ goto out;
+ }
+ *reachable = new_reachable;
+ new_reachable[*nreachable] = strdup(usercon_str);
+ if (new_reachable[*nreachable] == NULL) {
+ context_free(usercon);
+ rc = -1;
+ goto out;
+ }
+ new_reachable[*nreachable + 1] = 0;
+ *nreachable += 1;
+ }
+ context_free(usercon);
start = end;
}
-
rc = 0;
out:
@@ -313,39 +343,24 @@ static int get_failsafe_context(const char *user, char ** newcon)
return 0;
}
-struct context_order {
- char * con;
- unsigned int order;
-};
-
-static int order_compare(const void *A, const void *B)
-{
- const struct context_order *c1 = A, *c2 = B;
- if (c1->order < c2->order)
- return -1;
- else if (c1->order > c2->order)
- return 1;
- return strcmp(c1->con, c2->con);
-}
-
int get_ordered_context_list_with_level(const char *user,
const char *level,
- char * fromcon,
+ const char *fromcon,
char *** list)
{
int rc;
- int freefrom = 0;
+ char *backup_fromcon = NULL;
context_t con;
- char *newfromcon;
+ const char *newfromcon;
if (!level)
return get_ordered_context_list(user, fromcon, list);
if (!fromcon) {
- rc = getcon(&fromcon);
+ rc = getcon(&backup_fromcon);
if (rc < 0)
return rc;
- freefrom = 1;
+ fromcon = backup_fromcon;
}
rc = -1;
@@ -364,16 +379,14 @@ int get_ordered_context_list_with_level(const char *user,
out:
context_free(con);
- if (freefrom)
- freecon(fromcon);
+ freecon(backup_fromcon);
return rc;
}
-hidden_def(get_ordered_context_list_with_level)
int get_default_context_with_level(const char *user,
const char *level,
- char * fromcon,
+ const char *fromcon,
char ** newcon)
{
char **conary;
@@ -391,15 +404,13 @@ int get_default_context_with_level(const char *user,
}
int get_ordered_context_list(const char *user,
- char * fromcon,
+ const char *fromcon,
char *** list)
{
char **reachable = NULL;
- unsigned int *ordering = NULL;
- struct context_order *co = NULL;
- char **ptr;
int rc = 0;
- unsigned int nreach = 0, nordered = 0, freefrom = 0, i;
+ unsigned nreachable = 0;
+ char *backup_fromcon = NULL;
FILE *fp;
char *fname = NULL;
size_t fname_len;
@@ -407,29 +418,12 @@ int get_ordered_context_list(const char *user,
if (!fromcon) {
/* Get the current context and use it for the starting context */
- rc = getcon(&fromcon);
+ rc = getcon(&backup_fromcon);
if (rc < 0)
return rc;
- freefrom = 1;
+ fromcon = backup_fromcon;
}
- /* Determine the set of reachable contexts for the user. */
- rc = security_compute_user(fromcon, user, &reachable);
- if (rc < 0)
- goto failsafe;
- nreach = 0;
- for (ptr = reachable; *ptr; ptr++)
- nreach++;
- if (!nreach)
- goto failsafe;
-
- /* Initialize ordering array. */
- ordering = malloc(nreach * sizeof(unsigned int));
- if (!ordering)
- goto failsafe;
- for (i = 0; i < nreach; i++)
- ordering[i] = nreach;
-
/* Determine the ordering to apply from the optional per-user config
and from the global config. */
fname_len = strlen(user_contexts_path) + strlen(user) + 2;
@@ -440,8 +434,8 @@ int get_ordered_context_list(const char *user,
fp = fopen(fname, "re");
if (fp) {
__fsetlocking(fp, FSETLOCKING_BYCALLER);
- rc = get_context_order(fp, fromcon, reachable, nreach, ordering,
- &nordered);
+ rc = get_context_user(fp, fromcon, user, &reachable, &nreachable);
+
fclose(fp);
if (rc < 0 && errno != ENOENT) {
fprintf(stderr,
@@ -454,8 +448,7 @@ int get_ordered_context_list(const char *user,
fp = fopen(selinux_default_context_path(), "re");
if (fp) {
__fsetlocking(fp, FSETLOCKING_BYCALLER);
- rc = get_context_order(fp, fromcon, reachable, nreach, ordering,
- &nordered);
+ rc = get_context_user(fp, fromcon, user, &reachable, &nreachable);
fclose(fp);
if (rc < 0 && errno != ENOENT) {
fprintf(stderr,
@@ -463,42 +456,20 @@ int get_ordered_context_list(const char *user,
__FUNCTION__, selinux_default_context_path());
/* Fall through */
}
- rc = 0;
}
- if (!nordered)
+ if (!nreachable)
goto failsafe;
- /* Apply the ordering. */
- co = malloc(nreach * sizeof(struct context_order));
- if (!co)
- goto failsafe;
- for (i = 0; i < nreach; i++) {
- co[i].con = reachable[i];
- co[i].order = ordering[i];
- }
- qsort(co, nreach, sizeof(struct context_order), order_compare);
- for (i = 0; i < nreach; i++)
- reachable[i] = co[i].con;
- free(co);
-
- /* Only report the ordered entries to the caller. */
- if (nordered <= nreach) {
- for (i = nordered; i < nreach; i++)
- free(reachable[i]);
- reachable[nordered] = NULL;
- rc = nordered;
- }
-
out:
- if (rc > 0)
+ if (nreachable > 0) {
*list = reachable;
+ rc = nreachable;
+ }
else
freeconary(reachable);
- free(ordering);
- if (freefrom)
- freecon(fromcon);
+ freecon(backup_fromcon);
return rc;
@@ -519,8 +490,7 @@ int get_ordered_context_list(const char *user,
reachable = NULL;
goto out;
}
- rc = 1; /* one context in the list */
+ nreachable = 1; /* one context in the list */
goto out;
}
-hidden_def(get_ordered_context_list)
diff --git a/libselinux/src/get_context_list_internal.h b/libselinux/src/get_context_list_internal.h
index c224834e..a7c1d41b 100644
--- a/libselinux/src/get_context_list_internal.h
+++ b/libselinux/src/get_context_list_internal.h
@@ -1,6 +1,2 @@
#include <selinux/get_context_list.h>
-#include "dso.h"
-hidden_proto(get_ordered_context_list)
- hidden_proto(get_ordered_context_list_with_level)
- hidden_proto(get_default_context_with_role)
diff --git a/libselinux/src/get_default_type_internal.h b/libselinux/src/get_default_type_internal.h
index 0da3c512..deb5d296 100644
--- a/libselinux/src/get_default_type_internal.h
+++ b/libselinux/src/get_default_type_internal.h
@@ -1,4 +1,2 @@
#include <selinux/get_default_type.h>
-#include "dso.h"
-hidden_proto(selinux_default_type_path)
diff --git a/libselinux/src/get_initial_context.c b/libselinux/src/get_initial_context.c
index 5e919f47..97ae3dcf 100644
--- a/libselinux/src/get_initial_context.c
+++ b/libselinux/src/get_initial_context.c
@@ -53,7 +53,6 @@ int security_get_initial_context_raw(const char * name, char ** con)
return ret;
}
-hidden_def(security_get_initial_context_raw)
int security_get_initial_context(const char * name, char ** con)
{
@@ -69,4 +68,3 @@ int security_get_initial_context(const char * name, char ** con)
return ret;
}
-hidden_def(security_get_initial_context)
diff --git a/libselinux/src/getenforce.c b/libselinux/src/getenforce.c
index d909dced..3f1e2002 100644
--- a/libselinux/src/getenforce.c
+++ b/libselinux/src/getenforce.c
@@ -37,4 +37,3 @@ int security_getenforce(void)
return !!enforce;
}
-hidden_def(security_getenforce)
diff --git a/libselinux/src/getfilecon.c b/libselinux/src/getfilecon.c
index 20bee8ab..4bee3137 100644
--- a/libselinux/src/getfilecon.c
+++ b/libselinux/src/getfilecon.c
@@ -49,7 +49,6 @@ int getfilecon_raw(const char *path, char ** context)
return ret;
}
-hidden_def(getfilecon_raw)
int getfilecon(const char *path, char ** context)
{
@@ -70,4 +69,3 @@ int getfilecon(const char *path, char ** context)
return ret;
}
-hidden_def(getfilecon)
diff --git a/libselinux/src/getpeercon.c b/libselinux/src/getpeercon.c
index 3a77a2de..a9dca73e 100644
--- a/libselinux/src/getpeercon.c
+++ b/libselinux/src/getpeercon.c
@@ -43,7 +43,6 @@ int getpeercon_raw(int fd, char ** context)
return ret;
}
-hidden_def(getpeercon_raw)
int getpeercon(int fd, char ** context)
{
diff --git a/libselinux/src/init.c b/libselinux/src/init.c
index 083638c4..542c979b 100644
--- a/libselinux/src/init.c
+++ b/libselinux/src/init.c
@@ -12,7 +12,6 @@
#include <stdint.h>
#include <limits.h>
-#include "dso.h"
#include "policy.h"
#include "selinux_internal.h"
#include "setrans_internal.h"
@@ -79,7 +78,6 @@ int selinuxfs_exists(void)
fclose(fp);
return exists;
}
-hidden_def(selinuxfs_exists)
static void init_selinuxmnt(void)
{
@@ -138,14 +136,12 @@ void fini_selinuxmnt(void)
selinux_mnt = NULL;
}
-hidden_def(fini_selinuxmnt)
void set_selinuxmnt(const char *mnt)
{
selinux_mnt = strdup(mnt);
}
-hidden_def(set_selinuxmnt)
static void init_lib(void) __attribute__ ((constructor));
static void init_lib(void)
diff --git a/libselinux/src/is_customizable_type.c b/libselinux/src/is_customizable_type.c
index 92876f4d..f83e1e83 100644
--- a/libselinux/src/is_customizable_type.c
+++ b/libselinux/src/is_customizable_type.c
@@ -9,7 +9,10 @@
#include "selinux_internal.h"
#include "context_internal.h"
-static int get_customizable_type_list(char *** retlist)
+static char **customizable_list = NULL;
+static pthread_once_t customizable_once = PTHREAD_ONCE_INIT;
+
+static void customizable_init(void)
{
FILE *fp;
char *buf;
@@ -18,12 +21,12 @@ static int get_customizable_type_list(char *** retlist)
fp = fopen(selinux_customizable_types_path(), "re");
if (!fp)
- return -1;
+ return;
buf = malloc(selinux_page_size);
if (!buf) {
fclose(fp);
- return -1;
+ return;
}
while (fgets_unlocked(buf, selinux_page_size, fp) && ctr < UINT_MAX) {
ctr++;
@@ -38,7 +41,7 @@ static int get_customizable_type_list(char *** retlist)
while (fgets_unlocked(buf, selinux_page_size, fp)
&& i < ctr) {
buf[strlen(buf) - 1] = 0;
- list[i] = (char *) strdup(buf);
+ list[i] = strdup(buf);
if (!list[i]) {
unsigned int j;
for (j = 0; j < i; j++)
@@ -54,23 +57,19 @@ static int get_customizable_type_list(char *** retlist)
fclose(fp);
free(buf);
if (!list)
- return -1;
- *retlist = list;
- return 0;
+ return;
+ customizable_list = list;
}
-static char **customizable_list = NULL;
-
int is_context_customizable(const char * scontext)
{
int i;
const char *type;
context_t c;
- if (!customizable_list) {
- if (get_customizable_type_list(&customizable_list) != 0)
- return -1;
- }
+ __selinux_once(customizable_once, customizable_init);
+ if (!customizable_list)
+ return -1;
c = context_new(scontext);
if (!c)
diff --git a/libselinux/src/label_backends_android.c b/libselinux/src/label_backends_android.c
index 121b52f5..e52b44d4 100644
--- a/libselinux/src/label_backends_android.c
+++ b/libselinux/src/label_backends_android.c
@@ -96,9 +96,15 @@ static int process_line(struct selabel_handle *rec,
items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context);
if (items < 0) {
items = errno;
- selinux_log(SELINUX_ERROR,
- "%s: line %u error due to: %s\n", path,
- lineno, errbuf ?: strerror(errno));
+ if (errbuf) {
+ selinux_log(SELINUX_ERROR,
+ "%s: line %u error due to: %s\n", path,
+ lineno, errbuf);
+ } else {
+ selinux_log(SELINUX_ERROR,
+ "%s: line %u error due to: %m\n", path,
+ lineno);
+ }
errno = items;
return -1;
}
diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c
index fba96c92..94c05c6d 100644
--- a/libselinux/src/label_db.c
+++ b/libselinux/src/label_db.c
@@ -277,7 +277,7 @@ db_init(const struct selinux_opt *opts, unsigned nopts,
if (!path)
path = selinux_sepgsql_context_path();
- if ((filp = fopen(path, "rb")) == NULL) {
+ if ((filp = fopen(path, "re")) == NULL) {
free(catalog);
return NULL;
}
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 280430b5..695d6a9e 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -188,6 +188,9 @@ static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec,
str_buf[entry_len] = '\0';
if ((strcmp(str_buf, reg_version) != 0)) {
+ COMPAT_LOG(SELINUX_ERROR,
+ "Regex version mismatch, expected: %s actual: %s\n",
+ reg_version, str_buf);
free(str_buf);
return -1;
}
@@ -371,7 +374,7 @@ end_arch_check:
if (stem_id < 0 || stem_id >= (int32_t)stem_map_len)
spec->stem_id = -1;
- else
+ else
spec->stem_id = stem_map[stem_id];
/* retrieve the hasMetaChars bit */
@@ -895,7 +898,7 @@ static void closef(struct selabel_handle *rec)
// Finds all the matches of |key| in the given context. Returns the result in
// the allocated array and updates the match count. If match_count is NULL,
// stops early once the 1st match is found.
-static const struct spec **lookup_all(struct selabel_handle *rec,
+static struct spec **lookup_all(struct selabel_handle *rec,
const char *key,
int type,
bool partial,
@@ -904,13 +907,14 @@ static const struct spec **lookup_all(struct selabel_handle *rec,
struct saved_data *data = (struct saved_data *)rec->data;
struct spec *spec_arr = data->spec_arr;
int i, rc, file_stem;
+ size_t len;
mode_t mode = (mode_t)type;
char *clean_key = NULL;
const char *prev_slash, *next_slash;
unsigned int sofar = 0;
char *sub = NULL;
- const struct spec **result = NULL;
+ struct spec **result = NULL;
if (match_count) {
*match_count = 0;
result = calloc(data->nspec, sizeof(struct spec*));
@@ -944,6 +948,27 @@ static const struct spec **lookup_all(struct selabel_handle *rec,
key = clean_key;
}
+ /* remove trailing slash */
+ len = strlen(key);
+ if (len == 0) {
+ errno = EINVAL;
+ goto finish;
+ }
+
+ if (len > 1 && key[len - 1] == '/') {
+ /* reuse clean_key from above if available */
+ if (!clean_key) {
+ clean_key = (char *) malloc(len);
+ if (!clean_key)
+ goto finish;
+
+ memcpy(clean_key, key, len - 1);
+ }
+
+ clean_key[len - 1] = '\0';
+ key = clean_key;
+ }
+
sub = selabel_sub_key(data, key);
if (sub)
key = sub;
@@ -972,7 +997,12 @@ static const struct spec **lookup_all(struct selabel_handle *rec,
rc = regex_match(spec->regex, key, partial);
if (rc == REGEX_MATCH || (partial && rc == REGEX_MATCH_PARTIAL)) {
if (rc == REGEX_MATCH) {
- spec->matches++;
+#ifdef __ATOMIC_RELAXED
+ __atomic_store_n(&spec->any_matches,
+ true, __ATOMIC_RELAXED);
+#else
+#error "Please use a compiler that supports __atomic builtins"
+#endif
}
if (strcmp(spec_arr[i].lr.ctx_raw, "<<none>>") == 0) {
@@ -998,6 +1028,8 @@ static const struct spec **lookup_all(struct selabel_handle *rec,
goto finish;
}
}
+ if (!result[0])
+ errno = ENOENT;
finish:
free(clean_key);
@@ -1013,11 +1045,11 @@ static struct spec *lookup_common(struct selabel_handle *rec,
const char *key,
int type,
bool partial) {
- const struct spec **matches = lookup_all(rec, key, type, partial, NULL);
+ struct spec **matches = lookup_all(rec, key, type, partial, NULL);
if (!matches) {
return NULL;
}
- struct spec *result = (struct spec*)matches[0];
+ struct spec *result = matches[0];
free(matches);
return result;
}
@@ -1080,7 +1112,7 @@ static bool hash_all_partial_matches(struct selabel_handle *rec, const char *key
assert(digest);
size_t total_matches;
- const struct spec **matches = lookup_all(rec, key, 0, true, &total_matches);
+ struct spec **matches = lookup_all(rec, key, 0, true, &total_matches);
if (!matches) {
return false;
}
@@ -1268,9 +1300,15 @@ static void stats(struct selabel_handle *rec)
struct saved_data *data = (struct saved_data *)rec->data;
unsigned int i, nspec = data->nspec;
struct spec *spec_arr = data->spec_arr;
+ bool any_matches;
for (i = 0; i < nspec; i++) {
- if (spec_arr[i].matches == 0) {
+#ifdef __ATOMIC_RELAXED
+ any_matches = __atomic_load_n(&spec_arr[i].any_matches, __ATOMIC_RELAXED);
+#else
+#error "Please use a compiler that supports __atomic builtins"
+#endif
+ if (!any_matches) {
if (spec_arr[i].type_str) {
COMPAT_LOG(SELINUX_WARNING,
"Warning! No matches for (%s, %s, %s)\n",
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index baed3341..b453e13f 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -51,7 +51,7 @@ struct spec {
bool regex_compiled; /* bool to indicate if the regex is compiled */
pthread_mutex_t regex_lock; /* lock for lazy compilation of regex */
mode_t mode; /* mode format value */
- int matches; /* number of matching pathnames */
+ bool any_matches; /* did any pathname match? */
int stem_id; /* indicates which stem-compression item */
char hasMetaChars; /* regular expression has meta-chars */
char from_mmap; /* this spec is from an mmap of the data */
@@ -286,7 +286,6 @@ static inline int store_stem(struct saved_data *data, char *buf, int stem_len)
tmp_arr = realloc(data->stem_arr,
sizeof(*tmp_arr) * alloc_stems);
if (!tmp_arr) {
- free(buf);
return -1;
}
data->alloc_stems = alloc_stems;
@@ -308,6 +307,7 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
int stem_len = get_stem_from_spec(buf);
int stemid;
char *stem;
+ int r;
if (!stem_len)
return -1;
@@ -321,7 +321,11 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
if (!stem)
return -1;
- return store_stem(data, stem, stem_len);
+ r = store_stem(data, stem, stem_len);
+ if (r < 0)
+ free(stem);
+
+ return r;
}
/* This will always check for buffer over-runs and either read the next entry
@@ -441,9 +445,15 @@ static inline int process_line(struct selabel_handle *rec,
items = read_spec_entries(line_buf, &errbuf, 3, &regex, &type, &context);
if (items < 0) {
rc = errno;
- selinux_log(SELINUX_ERROR,
- "%s: line %u error due to: %s\n", path,
- lineno, errbuf ?: strerror(errno));
+ if (errbuf) {
+ selinux_log(SELINUX_ERROR,
+ "%s: line %u error due to: %s\n", path,
+ lineno, errbuf);
+ } else {
+ selinux_log(SELINUX_ERROR,
+ "%s: line %u error due to: %m\n", path,
+ lineno);
+ }
errno = rc;
return -1;
}
diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h
index 95f9a14c..d09847c8 100644
--- a/libselinux/src/label_internal.h
+++ b/libselinux/src/label_internal.h
@@ -13,7 +13,6 @@
#include <stdio.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
-#include "dso.h"
#include "sha1.h"
#if defined(ANDROID) || defined(__APPLE__)
@@ -26,22 +25,22 @@
*/
int selabel_file_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
- unsigned nopts) hidden;
+ unsigned nopts) ;
int selabel_media_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
- unsigned nopts) hidden;
+ unsigned nopts) ;
int selabel_x_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
- unsigned nopts) hidden;
+ unsigned nopts) ;
int selabel_db_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
- unsigned nopts) hidden;
+ unsigned nopts) ;
int selabel_property_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
- unsigned nopts) hidden;
+ unsigned nopts) ;
int selabel_exact_match_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
- unsigned nopts) hidden;
+ unsigned nopts) ;
/*
* Labeling internal structures
@@ -122,24 +121,26 @@ struct selabel_handle {
*/
extern int
selabel_validate(struct selabel_handle *rec,
- struct selabel_lookup_rec *contexts) hidden;
+ struct selabel_lookup_rec *contexts) ;
/*
* Compatibility support
*/
extern int myprintf_compat;
extern void __attribute__ ((format(printf, 1, 2)))
-(*myprintf) (const char *fmt, ...) hidden;
+(*myprintf) (const char *fmt, ...) ;
-#define COMPAT_LOG(type, fmt...) if (myprintf_compat) \
- myprintf(fmt); \
- else \
- selinux_log(type, fmt);
+#define COMPAT_LOG(type, fmt...) do { \
+ if (myprintf_compat) \
+ myprintf(fmt); \
+ else \
+ selinux_log(type, fmt); \
+ } while (0)
extern int
compat_validate(struct selabel_handle *rec,
struct selabel_lookup_rec *contexts,
- const char *path, unsigned lineno) hidden;
+ const char *path, unsigned lineno) ;
/*
* The read_spec_entries function may be used to
diff --git a/libselinux/src/label_media.c b/libselinux/src/label_media.c
index d202e5d5..eb27deaf 100644
--- a/libselinux/src/label_media.c
+++ b/libselinux/src/label_media.c
@@ -119,7 +119,6 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
if (process_line(path, line_buf, pass, ++lineno, rec))
goto finish;
}
- lineno = 0;
if (pass == 0) {
if (data->nspec == 0) {
diff --git a/libselinux/src/label_support.c b/libselinux/src/label_support.c
index 26f9ef15..94ed6e42 100644
--- a/libselinux/src/label_support.c
+++ b/libselinux/src/label_support.c
@@ -63,7 +63,7 @@ static inline int read_spec_entry(char **entry, char **ptr, int *len, const char
* This function calls read_spec_entry() to do the actual string processing.
* As such, can return anything from that function as well.
*/
-int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
+int read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
{
char **spec_entry, *buf_p;
int len, rc, items, entry_len = 0;
@@ -113,7 +113,7 @@ int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args,
}
/* Once all the specfiles are in the hash_buf, generate the hash. */
-void hidden digest_gen_hash(struct selabel_digest *digest)
+void digest_gen_hash(struct selabel_digest *digest)
{
Sha1Context context;
@@ -141,7 +141,7 @@ void hidden digest_gen_hash(struct selabel_digest *digest)
*
* Return %0 on success, -%1 with @errno set on failure.
*/
-int hidden digest_add_specfile(struct selabel_digest *digest, FILE *fp,
+int digest_add_specfile(struct selabel_digest *digest, FILE *fp,
char *from_addr, size_t buf_len,
const char *path)
{
diff --git a/libselinux/src/label_x.c b/libselinux/src/label_x.c
index 96745299..e9fa063f 100644
--- a/libselinux/src/label_x.c
+++ b/libselinux/src/label_x.c
@@ -146,7 +146,6 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
if (process_line(path, line_buf, pass, ++lineno, rec))
goto finish;
}
- lineno = 0;
if (pass == 0) {
if (data->nspec == 0) {
diff --git a/libselinux/src/lgetfilecon.c b/libselinux/src/lgetfilecon.c
index db67bc60..d1fb821b 100644
--- a/libselinux/src/lgetfilecon.c
+++ b/libselinux/src/lgetfilecon.c
@@ -49,7 +49,6 @@ int lgetfilecon_raw(const char *path, char ** context)
return ret;
}
-hidden_def(lgetfilecon_raw)
int lgetfilecon(const char *path, char ** context)
{
diff --git a/libselinux/src/libselinux.map b/libselinux/src/libselinux.map
new file mode 100644
index 00000000..4acf1caa
--- /dev/null
+++ b/libselinux/src/libselinux.map
@@ -0,0 +1,247 @@
+LIBSELINUX_1.0 {
+ global:
+ avc_add_callback;
+ avc_audit;
+ avc_av_stats;
+ avc_cache_stats;
+ avc_cleanup;
+ avc_compute_create;
+ avc_compute_member;
+ avc_context_to_sid;
+ avc_context_to_sid_raw;
+ avc_destroy;
+ avc_get_initial_sid;
+ avc_has_perm;
+ avc_has_perm_noaudit;
+ avc_init;
+ avc_netlink_acquire_fd;
+ avc_netlink_check_nb;
+ avc_netlink_close;
+ avc_netlink_loop;
+ avc_netlink_open;
+ avc_netlink_release_fd;
+ avc_open;
+ avc_reset;
+ avc_sid_stats;
+ avc_sid_to_context;
+ avc_sid_to_context_raw;
+ checkPasswdAccess;
+ context_free;
+ context_new;
+ context_range_get;
+ context_range_set;
+ context_role_get;
+ context_role_set;
+ context_str;
+ context_type_get;
+ context_type_set;
+ context_user_get;
+ context_user_set;
+ fgetfilecon;
+ fgetfilecon_raw;
+ fini_selinuxmnt;
+ freecon;
+ freeconary;
+ fsetfilecon;
+ fsetfilecon_raw;
+ getcon;
+ getcon_raw;
+ get_default_context;
+ get_default_context_with_level;
+ get_default_context_with_role;
+ get_default_context_with_rolelevel;
+ get_default_type;
+ getexeccon;
+ getexeccon_raw;
+ getfilecon;
+ getfilecon_raw;
+ getfscreatecon;
+ getfscreatecon_raw;
+ getkeycreatecon;
+ getkeycreatecon_raw;
+ get_ordered_context_list;
+ get_ordered_context_list_with_level;
+ getpeercon;
+ getpeercon_raw;
+ getpidcon;
+ getpidcon_raw;
+ getprevcon;
+ getprevcon_raw;
+ getseuser;
+ getseuserbyname;
+ getsockcreatecon;
+ getsockcreatecon_raw;
+ is_context_customizable;
+ is_selinux_enabled;
+ is_selinux_mls_enabled;
+ lgetfilecon;
+ lgetfilecon_raw;
+ lsetfilecon;
+ lsetfilecon_raw;
+ manual_user_enter_context;
+ matchmediacon;
+ matchpathcon;
+ matchpathcon_checkmatches;
+ matchpathcon_filespec_add;
+ matchpathcon_filespec_destroy;
+ matchpathcon_filespec_eval;
+ matchpathcon_fini;
+ matchpathcon_index;
+ matchpathcon_init;
+ matchpathcon_init_prefix;
+ mode_to_security_class;
+ print_access_vector;
+ query_user_context;
+ realpath_not_final;
+ rpm_execcon;
+ security_av_perm_to_string;
+ security_av_string;
+ security_canonicalize_context;
+ security_canonicalize_context_raw;
+ security_check_context;
+ security_check_context_raw;
+ security_class_to_string;
+ security_commit_booleans;
+ security_compute_av;
+ security_compute_av_flags;
+ security_compute_av_flags_raw;
+ security_compute_av_raw;
+ security_compute_create;
+ security_compute_create_name;
+ security_compute_create_name_raw;
+ security_compute_create_raw;
+ security_compute_member;
+ security_compute_member_raw;
+ security_compute_relabel;
+ security_compute_relabel_raw;
+ security_compute_user;
+ security_compute_user_raw;
+ security_deny_unknown;
+ security_disable;
+ security_get_boolean_active;
+ security_get_boolean_names;
+ security_get_boolean_pending;
+ security_get_checkreqprot;
+ security_getenforce;
+ security_get_initial_context;
+ security_get_initial_context_raw;
+ security_load_booleans;
+ security_load_policy;
+ security_policyvers;
+ security_reject_unknown;
+ security_set_boolean;
+ security_set_boolean_list;
+ security_setenforce;
+ security_validatetrans;
+ security_validatetrans_raw;
+ selabel_close;
+ selabel_cmp;
+ selabel_digest;
+ selabel_get_digests_all_partial_matches;
+ selabel_hash_all_partial_matches;
+ selabel_lookup;
+ selabel_lookup_best_match;
+ selabel_lookup_best_match_raw;
+ selabel_lookup_raw;
+ selabel_open;
+ selabel_partial_match;
+ selabel_stats;
+ selinux_binary_policy_path;
+ selinux_booleans_path;
+ selinux_booleans_subs_path;
+ selinux_boolean_sub;
+ selinux_check_access;
+ selinux_check_passwd_access;
+ selinux_check_securetty_context;
+ selinux_colors_path;
+ selinux_contexts_path;
+ selinux_current_policy_path;
+ selinux_customizable_types_path;
+ selinux_default_context_path;
+ selinux_default_type_path;
+ selinux_failsafe_context_path;
+ selinux_file_context_cmp;
+ selinux_file_context_homedir_path;
+ selinux_file_context_local_path;
+ selinux_file_context_path;
+ selinux_file_context_subs_dist_path;
+ selinux_file_context_subs_path;
+ selinux_file_context_verify;
+ selinux_flush_class_cache;
+ selinuxfs_exists;
+ selinux_get_callback;
+ selinux_getenforcemode;
+ selinux_getpolicytype;
+ selinux_homedir_context_path;
+ selinux_init_load_policy;
+ selinux_lsetfilecon_default;
+ selinux_lxc_contexts_path;
+ selinux_media_context_path;
+ selinux_mkload_policy;
+ selinux_mnt;
+ selinux_netfilter_context_path;
+ selinux_openrc_contexts_path;
+ selinux_openssh_contexts_path;
+ selinux_path;
+ selinux_policy_root;
+ selinux_raw_context_to_color;
+ selinux_raw_to_trans_context;
+ selinux_removable_context_path;
+ selinux_reset_config;
+ selinux_restorecon;
+ selinux_restorecon_default_handle;
+ selinux_restorecon_set_alt_rootpath;
+ selinux_restorecon_set_exclude_list;
+ selinux_restorecon_set_sehandle;
+ selinux_restorecon_xattr;
+ selinux_securetty_types_path;
+ selinux_sepgsql_context_path;
+ selinux_set_callback;
+ selinux_set_mapping;
+ selinux_set_policy_root;
+ selinux_snapperd_contexts_path;
+ selinux_status_close;
+ selinux_status_deny_unknown;
+ selinux_status_getenforce;
+ selinux_status_open;
+ selinux_status_policyload;
+ selinux_status_updated;
+ selinux_systemd_contexts_path;
+ selinux_translations_path;
+ selinux_trans_to_raw_context;
+ selinux_user_contexts_path;
+ selinux_usersconf_path;
+ selinux_users_path;
+ selinux_virtual_domain_context_path;
+ selinux_virtual_image_context_path;
+ selinux_x_context_path;
+ setcon;
+ setcon_raw;
+ setexeccon;
+ setexeccon_raw;
+ setexecfilecon;
+ setfilecon;
+ setfilecon_raw;
+ setfscreatecon;
+ setfscreatecon_raw;
+ setkeycreatecon;
+ setkeycreatecon_raw;
+ set_matchpathcon_canoncon;
+ set_matchpathcon_flags;
+ set_matchpathcon_invalidcon;
+ set_matchpathcon_printf;
+ set_selinuxmnt;
+ setsockcreatecon;
+ setsockcreatecon_raw;
+ sidget;
+ sidput;
+ string_to_av_perm;
+ string_to_security_class;
+ local:
+ *;
+};
+
+LIBSELINUX_3.4 {
+ global:
+ selinux_restorecon_parallel;
+} LIBSELINUX_1.0;
diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c
index 9e75292d..d8c715ed 100644
--- a/libselinux/src/load_policy.c
+++ b/libselinux/src/load_policy.c
@@ -45,7 +45,6 @@ int security_load_policy(void *data, size_t len)
return 0;
}
-hidden_def(security_load_policy)
#ifndef ANDROID
#undef max
@@ -77,11 +76,11 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
#ifdef SHARED
char *errormsg = NULL;
void *libsepolh = NULL;
- libsepolh = dlopen("libsepol.so.1", RTLD_NOW);
+ libsepolh = dlopen("libsepol.so.2", RTLD_NOW);
if (libsepolh) {
usesepol = 1;
dlerror();
-#define DLERR() if ((errormsg = dlerror())) goto dlclose;
+#define DLERR() do { if ((errormsg = dlerror())) goto dlclose; } while (0)
vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max");
DLERR();
vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min");
@@ -138,15 +137,15 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
}
if (fd < 0) {
fprintf(stderr,
- "SELinux: Could not open policy file <= %s.%d: %s\n",
- selinux_binary_policy_path(), maxvers, strerror(errno));
+ "SELinux: Could not open policy file <= %s.%d: %m\n",
+ selinux_binary_policy_path(), maxvers);
goto dlclose;
}
if (fstat(fd, &sb) < 0) {
fprintf(stderr,
- "SELinux: Could not stat policy file %s: %s\n",
- path, strerror(errno));
+ "SELinux: Could not stat policy file %s: %m\n",
+ path);
goto close;
}
@@ -154,8 +153,8 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
data = map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
fprintf(stderr,
- "SELinux: Could not map policy file %s: %s\n",
- path, strerror(errno));
+ "SELinux: Could not map policy file %s: %m\n",
+ path);
goto close;
}
@@ -194,8 +193,8 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
if (rc)
fprintf(stderr,
- "SELinux: Could not load policy file %s: %s\n",
- path, strerror(errno));
+ "SELinux: Could not load policy file %s: %m\n",
+ path);
unmap:
if (data != map)
@@ -213,7 +212,6 @@ int selinux_mkload_policy(int preservebools __attribute__((unused)))
return rc;
}
-hidden_def(selinux_mkload_policy)
/*
* Mount point for selinuxfs.
@@ -281,7 +279,8 @@ int selinux_init_load_policy(int *enforce)
const char *mntpoint = NULL;
/* First make sure /sys is mounted */
if (mount("sysfs", "/sys", "sysfs", 0, 0) == 0 || errno == EBUSY) {
- if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
+ /* MS_NODEV can't be set because of /sys/fs/selinux/null device, used by Android */
+ if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, MS_NOEXEC | MS_NOSUID, 0) == 0 || errno == EBUSY) {
mntpoint = SELINUXMNT;
} else {
/* check old mountpoint */
@@ -307,7 +306,7 @@ int selinux_init_load_policy(int *enforce)
*enforce = 0;
} else {
/* Only emit this error if selinux was not disabled */
- fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno));
+ fprintf(stderr, "Mount failed for selinuxfs on %s: %m\n", SELINUXMNT);
}
if (rc == 0)
@@ -353,7 +352,7 @@ int selinux_init_load_policy(int *enforce)
if (orig_enforce != *enforce) {
rc = security_setenforce(*enforce);
if (rc < 0) {
- fprintf(stderr, "SELinux: Unable to switch to %s mode: %s\n", (*enforce ? "enforcing" : "permissive"), strerror(errno));
+ fprintf(stderr, "SELinux: Unable to switch to %s mode: %m\n", (*enforce ? "enforcing" : "permissive"));
if (*enforce)
goto noload;
}
diff --git a/libselinux/src/lsetfilecon.c b/libselinux/src/lsetfilecon.c
index 1d3b28a1..213fb684 100644
--- a/libselinux/src/lsetfilecon.c
+++ b/libselinux/src/lsetfilecon.c
@@ -25,7 +25,6 @@ int lsetfilecon_raw(const char *path, const char * context)
return rc;
}
-hidden_def(lsetfilecon_raw)
int lsetfilecon(const char *path, const char *context)
{
diff --git a/libselinux/src/mapping.c b/libselinux/src/mapping.c
index 96395fd4..dd2f1039 100644
--- a/libselinux/src/mapping.c
+++ b/libselinux/src/mapping.c
@@ -144,9 +144,9 @@ unmap_perm(security_class_t tclass, access_vector_t tperm)
access_vector_t kperm = 0;
for (i = 0; i < current_mapping[tclass].num_perms; i++)
- if (tperm & (1<<i)) {
+ if (tperm & (UINT32_C(1)<<i)) {
kperm |= current_mapping[tclass].perms[i];
- tperm &= ~(1<<i);
+ tperm &= ~(UINT32_C(1)<<i);
}
return kperm;
}
@@ -191,7 +191,7 @@ map_perm(security_class_t tclass, access_vector_t kperm)
for (i = 0; i < current_mapping[tclass].num_perms; i++)
if (kperm & current_mapping[tclass].perms[i]) {
- tperm |= 1<<i;
+ tperm |= UINT32_C(1)<<i;
kperm &= ~current_mapping[tclass].perms[i];
}
@@ -216,30 +216,30 @@ map_decision(security_class_t tclass, struct av_decision *avd)
for (i = 0, result = 0; i < n; i++) {
if (avd->allowed & mapping->perms[i])
- result |= 1<<i;
+ result |= UINT32_C(1)<<i;
else if (allow_unknown && !mapping->perms[i])
- result |= 1<<i;
+ result |= UINT32_C(1)<<i;
}
avd->allowed = result;
for (i = 0, result = 0; i < n; i++) {
if (avd->decided & mapping->perms[i])
- result |= 1<<i;
+ result |= UINT32_C(1)<<i;
else if (allow_unknown && !mapping->perms[i])
- result |= 1<<i;
+ result |= UINT32_C(1)<<i;
}
avd->decided = result;
for (i = 0, result = 0; i < n; i++)
if (avd->auditallow & mapping->perms[i])
- result |= 1<<i;
+ result |= UINT32_C(1)<<i;
avd->auditallow = result;
for (i = 0, result = 0; i < n; i++) {
if (avd->auditdeny & mapping->perms[i])
- result |= 1<<i;
+ result |= UINT32_C(1)<<i;
else if (!allow_unknown && !mapping->perms[i])
- result |= 1<<i;
+ result |= UINT32_C(1)<<i;
}
/*
@@ -248,7 +248,7 @@ map_decision(security_class_t tclass, struct av_decision *avd)
* a bug in the object manager.
*/
for (; i < (sizeof(result)*8); i++)
- result |= 1<<i;
+ result |= UINT32_C(1)<<i;
avd->auditdeny = result;
}
}
diff --git a/libselinux/src/matchmediacon.c b/libselinux/src/matchmediacon.c
index 23d01af4..d3d95043 100644
--- a/libselinux/src/matchmediacon.c
+++ b/libselinux/src/matchmediacon.c
@@ -22,6 +22,7 @@ int matchmediacon(const char *media, char ** con)
return -1;
while (!feof_unlocked(infile)) {
if (!fgets_unlocked(current_line, sizeof(current_line), infile)) {
+ fclose(infile);
return -1;
}
if (current_line[strlen(current_line) - 1])
diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
index 05a5cfa4..ea78a23e 100644
--- a/libselinux/src/matchpathcon.c
+++ b/libselinux/src/matchpathcon.c
@@ -78,17 +78,30 @@ static pthread_once_t once = PTHREAD_ONCE_INIT;
static pthread_key_t destructor_key;
static int destructor_key_initialized = 0;
+static void free_array_elts(void)
+{
+ int i;
+ for (i = 0; i < con_array_used; i++)
+ free(con_array[i]);
+ free(con_array);
+
+ con_array_size = con_array_used = 0;
+ con_array = NULL;
+}
+
static int add_array_elt(char *con)
{
+ char **tmp;
if (con_array_size) {
while (con_array_used >= con_array_size) {
con_array_size *= 2;
- con_array = (char **)realloc(con_array, sizeof(char*) *
+ tmp = (char **)realloc(con_array, sizeof(char*) *
con_array_size);
- if (!con_array) {
- con_array_size = con_array_used = 0;
+ if (!tmp) {
+ free_array_elts();
return -1;
}
+ con_array = tmp;
}
} else {
con_array_size = 1000;
@@ -105,13 +118,6 @@ static int add_array_elt(char *con)
return con_array_used++;
}
-static void free_array_elts(void)
-{
- con_array_size = con_array_used = 0;
- free(con_array);
- con_array = NULL;
-}
-
void set_matchpathcon_invalidcon(int (*f) (const char *p, unsigned l, char *c))
{
myinvalidcon = f;
@@ -315,14 +321,24 @@ void matchpathcon_filespec_destroy(void)
fl_head = NULL;
}
+static void matchpathcon_fini_internal(void)
+{
+ free_array_elts();
+
+ if (hnd) {
+ selabel_close(hnd);
+ hnd = NULL;
+ }
+}
+
static void matchpathcon_thread_destructor(void __attribute__((unused)) *ptr)
{
- matchpathcon_fini();
+ matchpathcon_fini_internal();
}
void __attribute__((destructor)) matchpathcon_lib_destructor(void);
-void hidden __attribute__((destructor)) matchpathcon_lib_destructor(void)
+void __attribute__((destructor)) matchpathcon_lib_destructor(void)
{
if (destructor_key_initialized)
__selinux_key_delete(destructor_key);
@@ -340,7 +356,7 @@ int matchpathcon_init_prefix(const char *path, const char *subset)
mycanoncon = default_canoncon;
__selinux_once(once, matchpathcon_init_once);
- __selinux_setspecific(destructor_key, (void *)1);
+ __selinux_setspecific(destructor_key, /* some valid address to please GCC */ &selinux_page_size);
options[SELABEL_OPT_SUBSET].type = SELABEL_OPT_SUBSET;
options[SELABEL_OPT_SUBSET].value = subset;
@@ -351,7 +367,6 @@ int matchpathcon_init_prefix(const char *path, const char *subset)
return hnd ? 0 : -1;
}
-hidden_def(matchpathcon_init_prefix)
int matchpathcon_init(const char *path)
{
@@ -360,12 +375,7 @@ int matchpathcon_init(const char *path)
void matchpathcon_fini(void)
{
- free_array_elts();
-
- if (hnd) {
- selabel_close(hnd);
- hnd = NULL;
- }
+ matchpathcon_fini_internal();
}
/*
@@ -383,8 +393,8 @@ int realpath_not_final(const char *name, char *resolved_path)
tmp_path = strdup(name);
if (!tmp_path) {
- myprintf("symlink_realpath(%s) strdup() failed: %s\n",
- name, strerror(errno));
+ myprintf("symlink_realpath(%s) strdup() failed: %m\n",
+ name);
rc = -1;
goto out;
}
@@ -404,8 +414,8 @@ int realpath_not_final(const char *name, char *resolved_path)
}
if (!p) {
- myprintf("symlink_realpath(%s) realpath() failed: %s\n",
- name, strerror(errno));
+ myprintf("symlink_realpath(%s) realpath() failed: %m\n",
+ name);
rc = -1;
goto out;
}
@@ -428,7 +438,7 @@ out:
return rc;
}
-int matchpathcon(const char *path, mode_t mode, char ** con)
+static int matchpathcon_internal(const char *path, mode_t mode, char ** con)
{
char stackpath[PATH_MAX + 1];
char *p = NULL;
@@ -449,9 +459,13 @@ int matchpathcon(const char *path, mode_t mode, char ** con)
selabel_lookup(hnd, con, path, mode);
}
+int matchpathcon(const char *path, mode_t mode, char ** con) {
+ return matchpathcon_internal(path, mode, con);
+}
+
int matchpathcon_index(const char *name, mode_t mode, char ** con)
{
- int i = matchpathcon(name, mode, con);
+ int i = matchpathcon_internal(name, mode, con);
if (i < 0)
return -1;
@@ -469,15 +483,15 @@ void matchpathcon_checkmatches(char *str __attribute__((unused)))
int selinux_file_context_cmp(const char * a,
const char * b)
{
- char *rest_a, *rest_b; /* Rest of the context after the user */
+ const char *rest_a, *rest_b; /* Rest of the context after the user */
if (!a && !b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
- rest_a = strchr((char *)a, ':');
- rest_b = strchr((char *)b, ':');
+ rest_a = strchr(a, ':');
+ rest_b = strchr(b, ':');
if (!rest_a && !rest_b)
return 0;
if (!rest_a)
diff --git a/libselinux/src/policyvers.c b/libselinux/src/policyvers.c
index c97dd9df..e5aa2f3f 100644
--- a/libselinux/src/policyvers.c
+++ b/libselinux/src/policyvers.c
@@ -7,7 +7,6 @@
#include "selinux_internal.h"
#include <stdio.h>
#include "policy.h"
-#include "dso.h"
#include <limits.h>
int security_policyvers(void)
@@ -42,4 +41,3 @@ int security_policyvers(void)
return vers;
}
-hidden_def(security_policyvers)
diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c
index c6799ef2..142fbf3a 100644
--- a/libselinux/src/procattr.c
+++ b/libselinux/src/procattr.c
@@ -25,21 +25,23 @@ static __thread char destructor_initialized;
/* Bionic and glibc >= 2.30 declare gettid() system call wrapper in unistd.h and
* has a definition for it */
#ifdef __BIONIC__
- #define OVERRIDE_GETTID 0
+ #define HAVE_GETTID 1
#elif !defined(__GLIBC_PREREQ)
- #define OVERRIDE_GETTID 1
+ #define HAVE_GETTID 0
#elif !__GLIBC_PREREQ(2,30)
- #define OVERRIDE_GETTID 1
+ #define HAVE_GETTID 0
#else
- #define OVERRIDE_GETTID 0
+ #define HAVE_GETTID 1
#endif
-#if OVERRIDE_GETTID
-static pid_t gettid(void)
+static pid_t selinux_gettid(void)
{
+#if HAVE_GETTID
+ return gettid();
+#else
return syscall(__NR_gettid);
-}
#endif
+}
static void procattr_thread_destructor(void __attribute__((unused)) *unused)
{
@@ -57,7 +59,7 @@ static void procattr_thread_destructor(void __attribute__((unused)) *unused)
void __attribute__((destructor)) procattr_destructor(void);
-void hidden __attribute__((destructor)) procattr_destructor(void)
+void __attribute__((destructor)) procattr_destructor(void)
{
if (destructor_key_initialized)
__selinux_key_delete(destructor_key);
@@ -66,7 +68,7 @@ void hidden __attribute__((destructor)) procattr_destructor(void)
static inline void init_thread_destructor(void)
{
if (destructor_initialized == 0) {
- __selinux_setspecific(destructor_key, (void *)1);
+ __selinux_setspecific(destructor_key, /* some valid address to please GCC */ &selinux_page_size);
destructor_initialized = 1;
}
}
@@ -94,7 +96,7 @@ static int openattr(pid_t pid, const char *attr, int flags)
if (fd >= 0 || errno != ENOENT)
goto out;
free(path);
- tid = gettid();
+ tid = selinux_gettid();
rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr);
} else {
errno = EINVAL;
@@ -144,7 +146,7 @@ static int getprocattrcon_raw(char ** context,
default:
errno = ENOENT;
return -1;
- };
+ }
if (prev_context && prev_context != UNSET) {
*context = strdup(prev_context);
@@ -238,7 +240,7 @@ static int setprocattrcon_raw(const char * context,
default:
errno = ENOENT;
return -1;
- };
+ }
if (!context && !*prev_context)
return 0;
@@ -345,22 +347,3 @@ all_selfattr_def(con, current)
all_selfattr_def(sockcreatecon, sockcreate)
all_selfattr_def(keycreatecon, keycreate)
- hidden_def(getcon_raw)
- hidden_def(getcon)
- hidden_def(getexeccon_raw)
- hidden_def(getfilecon_raw)
- hidden_def(getfilecon)
- hidden_def(getfscreatecon_raw)
- hidden_def(getkeycreatecon_raw)
- hidden_def(getpeercon_raw)
- hidden_def(getpidcon_raw)
- hidden_def(getprevcon_raw)
- hidden_def(getprevcon)
- hidden_def(getsockcreatecon_raw)
- hidden_def(setcon_raw)
- hidden_def(setexeccon_raw)
- hidden_def(setexeccon)
- hidden_def(setfilecon_raw)
- hidden_def(setfscreatecon_raw)
- hidden_def(setkeycreatecon_raw)
- hidden_def(setsockcreatecon_raw)
diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c
index 770bc3ea..73987d9f 100644
--- a/libselinux/src/regex.c
+++ b/libselinux/src/regex.c
@@ -319,7 +319,7 @@ char const *regex_version(void)
}
int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex,
- int unused __attribute__((unused)), bool *regex_compiled)
+ int do_load_precompregex __attribute__((unused)), bool *regex_compiled)
{
int rc;
uint32_t entry_len;
@@ -387,7 +387,7 @@ static inline pcre_extra *get_pcre_extra(struct regex_data *regex)
}
int regex_writef(struct regex_data *regex, FILE *fp,
- int unused __attribute__((unused)))
+ int do_write_precompregex __attribute__((unused)))
{
int rc;
size_t len;
diff --git a/libselinux/src/regex.h b/libselinux/src/regex.h
index 6732b349..2dfa2534 100644
--- a/libselinux/src/regex.h
+++ b/libselinux/src/regex.h
@@ -10,7 +10,6 @@
#include <pcre.h>
#endif
-#include "dso.h"
enum { REGEX_MATCH,
REGEX_MATCH_PARTIAL,
@@ -42,10 +41,10 @@ struct mmap_area;
* expressions are not portable across architectures that do not have a
* matching arch-string.
*/
-char const *regex_arch_string(void) hidden;
+char const *regex_arch_string(void) ;
/**
- * regex_verison returns the version string of the underlying regular
+ * regex_version returns the version string of the underlying regular
* regular expressions library. In the case of PCRE it just returns the
* result of pcre_version(). In the case of PCRE2, the very first time this
* function is called it allocates a buffer large enough to hold the version
@@ -55,12 +54,12 @@ char const *regex_arch_string(void) hidden;
*
* It may return NULL on error.
*/
-char const *regex_version(void) hidden;
+char const *regex_version(void) ;
/**
* This constructor function allocates a buffer for a regex_data structure.
* The buffer is being initialized with zeroes.
*/
-struct regex_data *regex_data_create(void) hidden;
+struct regex_data *regex_data_create(void) ;
/**
* This complementary destructor function frees the a given regex_data buffer.
* It also frees any non NULL member pointers with the appropriate pcreX_X_free
@@ -68,7 +67,7 @@ struct regex_data *regex_data_create(void) hidden;
* the pcre_extra data conditionally. Calling this function on a NULL pointer is
* save.
*/
-void regex_data_free(struct regex_data *regex) hidden;
+void regex_data_free(struct regex_data *regex) ;
/**
* This function compiles the regular expression. Additionally, it prepares
* data structures required by the different underlying engines. For PCRE
@@ -88,7 +87,7 @@ void regex_data_free(struct regex_data *regex) hidden;
* @retval -1 on error
*/
int regex_prepare_data(struct regex_data **regex, char const *pattern_string,
- struct regex_error_data *errordata) hidden;
+ struct regex_error_data *errordata) ;
/**
* This function loads a serialized precompiled pattern from a contiguous
* data region given by map_area.
@@ -109,7 +108,7 @@ int regex_prepare_data(struct regex_data **regex, char const *pattern_string,
int regex_load_mmap(struct mmap_area *map_area,
struct regex_data **regex,
int do_load_precompregex,
- bool *regex_compiled) hidden;
+ bool *regex_compiled) ;
/**
* This function stores a precompiled regular expression to a file.
* In the case of PCRE, it just dumps the binary representation of the
@@ -122,7 +121,7 @@ int regex_load_mmap(struct mmap_area *map_area,
* the output file (ignored by PCRE1 back-end).
*/
int regex_writef(struct regex_data *regex, FILE *fp,
- int do_write_precompregex) hidden;
+ int do_write_precompregex) ;
/**
* This function applies a precompiled pattern to a subject string and
* returns whether or not a match was found.
@@ -139,7 +138,7 @@ int regex_writef(struct regex_data *regex, FILE *fp,
* regular expression
*/
int regex_match(struct regex_data *regex, char const *subject,
- int partial) hidden;
+ int partial) ;
/**
* This function compares two compiled regular expressions (regex1 and regex2).
* It compares the binary representations of the compiled patterns. It is a very
@@ -150,7 +149,7 @@ int regex_match(struct regex_data *regex, char const *subject,
* the same
* @retval SELABEL_INCOMPARABLE otherwise
*/
-int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) hidden;
+int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) ;
/**
* This function takes the error data returned by regex_prepare_data and turns
* it in to a human readable error message.
@@ -163,5 +162,5 @@ int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) hidden;
* @arg buf_size Total size of the given buffer in bytes.
*/
void regex_format_error(struct regex_error_data const *error_data, char *buffer,
- size_t buf_size) hidden;
+ size_t buf_size) ;
#endif /* SRC_REGEX_H_ */
diff --git a/libselinux/src/reject_unknown.c b/libselinux/src/reject_unknown.c
index 5c1d3605..96e60be3 100644
--- a/libselinux/src/reject_unknown.c
+++ b/libselinux/src/reject_unknown.c
@@ -37,4 +37,3 @@ int security_reject_unknown(void)
return reject_unknown;
}
-hidden_def(security_reject_unknown);
diff --git a/libselinux/src/selinux_check_securetty_context.c b/libselinux/src/selinux_check_securetty_context.c
index 55d4e039..c5c557fd 100644
--- a/libselinux/src/selinux_check_securetty_context.c
+++ b/libselinux/src/selinux_check_securetty_context.c
@@ -50,4 +50,3 @@ int selinux_check_securetty_context(const char * tty_context)
return found;
}
-hidden_def(selinux_check_securetty_context)
diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c
index b16a3851..d2e49ee1 100644
--- a/libselinux/src/selinux_config.c
+++ b/libselinux/src/selinux_config.c
@@ -92,6 +92,7 @@ int selinux_getenforcemode(int *enforce)
FILE *cfg = fopen(SELINUXCONFIG, "re");
if (cfg) {
char *buf;
+ char *tag;
int len = sizeof(SELINUXTAG) - 1;
buf = malloc(selinux_page_size);
if (!buf) {
@@ -101,21 +102,24 @@ int selinux_getenforcemode(int *enforce)
while (fgets_unlocked(buf, selinux_page_size, cfg)) {
if (strncmp(buf, SELINUXTAG, len))
continue;
+ tag = buf+len;
+ while (isspace(*tag))
+ tag++;
if (!strncasecmp
- (buf + len, "enforcing", sizeof("enforcing") - 1)) {
+ (tag, "enforcing", sizeof("enforcing") - 1)) {
*enforce = 1;
ret = 0;
break;
} else
if (!strncasecmp
- (buf + len, "permissive",
+ (tag, "permissive",
sizeof("permissive") - 1)) {
*enforce = 0;
ret = 0;
break;
} else
if (!strncasecmp
- (buf + len, "disabled",
+ (tag, "disabled",
sizeof("disabled") - 1)) {
*enforce = -1;
ret = 0;
@@ -128,7 +132,6 @@ int selinux_getenforcemode(int *enforce)
return ret;
}
-hidden_def(selinux_getenforcemode)
static char *selinux_policytype;
@@ -141,7 +144,6 @@ int selinux_getpolicytype(char **type)
return *type ? 0 : -1;
}
-hidden_def(selinux_getpolicytype)
static int setpolicytype(const char *type)
{
@@ -178,9 +180,15 @@ static void init_selinux_config(void)
if (!strncasecmp(buf_p, SELINUXTYPETAG,
sizeof(SELINUXTYPETAG) - 1)) {
- type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1);
- if (!type)
+ buf_p += sizeof(SELINUXTYPETAG) - 1;
+ while (isspace(*buf_p))
+ buf_p++;
+ type = strdup(buf_p);
+ if (!type) {
+ free(line_buf);
+ fclose(fp);
return;
+ }
end = type + strlen(type) - 1;
while ((end > type) &&
(isspace(*end) || iscntrl(*end))) {
@@ -189,6 +197,8 @@ static void init_selinux_config(void)
}
if (setpolicytype(type) != 0) {
free(type);
+ free(line_buf);
+ fclose(fp);
return;
}
free(type);
@@ -196,6 +206,8 @@ static void init_selinux_config(void)
} else if (!strncmp(buf_p, REQUIRESEUSERS,
sizeof(REQUIRESEUSERS) - 1)) {
value = buf_p + sizeof(REQUIRESEUSERS) - 1;
+ while (isspace(*value))
+ value++;
intptr = &require_seusers;
} else {
continue;
@@ -249,7 +261,6 @@ void selinux_reset_config(void)
init_selinux_config();
}
-hidden_def(selinux_reset_config)
static const char *get_path(int idx)
{
@@ -262,7 +273,6 @@ const char *selinux_default_type_path(void)
return get_path(DEFAULT_TYPE);
}
-hidden_def(selinux_default_type_path)
const char *selinux_policy_root(void)
{
@@ -305,42 +315,36 @@ const char *selinux_path(void)
return selinux_rootpath;
}
-hidden_def(selinux_path)
const char *selinux_default_context_path(void)
{
return get_path(DEFAULT_CONTEXTS);
}
-hidden_def(selinux_default_context_path)
const char *selinux_securetty_types_path(void)
{
return get_path(SECURETTY_TYPES);
}
-hidden_def(selinux_securetty_types_path)
const char *selinux_failsafe_context_path(void)
{
return get_path(FAILSAFE_CONTEXT);
}
-hidden_def(selinux_failsafe_context_path)
const char *selinux_removable_context_path(void)
{
return get_path(REMOVABLE_CONTEXT);
}
-hidden_def(selinux_removable_context_path)
const char *selinux_binary_policy_path(void)
{
return get_path(BINPOLICY);
}
-hidden_def(selinux_binary_policy_path)
const char *selinux_current_policy_path(void)
{
@@ -365,35 +369,30 @@ const char *selinux_current_policy_path(void)
return policy_path;
}
-hidden_def(selinux_current_policy_path)
const char *selinux_file_context_path(void)
{
return get_path(FILE_CONTEXTS);
}
-hidden_def(selinux_file_context_path)
const char *selinux_homedir_context_path(void)
{
return get_path(HOMEDIR_CONTEXTS);
}
-hidden_def(selinux_homedir_context_path)
const char *selinux_media_context_path(void)
{
return get_path(MEDIA_CONTEXTS);
}
-hidden_def(selinux_media_context_path)
const char *selinux_customizable_types_path(void)
{
return get_path(CUSTOMIZABLE_TYPES);
}
-hidden_def(selinux_customizable_types_path)
const char *selinux_contexts_path(void)
{
@@ -405,7 +404,6 @@ const char *selinux_user_contexts_path(void)
return get_path(USER_CONTEXTS);
}
-hidden_def(selinux_user_contexts_path)
/* Deprecated as local policy booleans no longer supported. */
const char *selinux_booleans_path(void)
@@ -413,7 +411,6 @@ const char *selinux_booleans_path(void)
return get_path(BOOLEANS);
}
-hidden_def(selinux_booleans_path)
/* Deprecated as no longer supported. */
const char *selinux_users_path(void)
@@ -421,127 +418,108 @@ const char *selinux_users_path(void)
return get_path(USERS_DIR);
}
-hidden_def(selinux_users_path)
const char *selinux_usersconf_path(void)
{
return get_path(SEUSERS);
}
-hidden_def(selinux_usersconf_path)
const char *selinux_translations_path(void)
{
return get_path(TRANSLATIONS);
}
-hidden_def(selinux_translations_path)
const char *selinux_colors_path(void)
{
return get_path(COLORS);
}
-hidden_def(selinux_colors_path)
const char *selinux_netfilter_context_path(void)
{
return get_path(NETFILTER_CONTEXTS);
}
-hidden_def(selinux_netfilter_context_path)
const char *selinux_file_context_homedir_path(void)
{
return get_path(FILE_CONTEXTS_HOMEDIR);
}
-hidden_def(selinux_file_context_homedir_path)
const char *selinux_file_context_local_path(void)
{
return get_path(FILE_CONTEXTS_LOCAL);
}
-hidden_def(selinux_file_context_local_path)
const char *selinux_x_context_path(void)
{
return get_path(X_CONTEXTS);
}
-hidden_def(selinux_x_context_path)
const char *selinux_virtual_domain_context_path(void)
{
return get_path(VIRTUAL_DOMAIN);
}
-hidden_def(selinux_virtual_domain_context_path)
const char *selinux_virtual_image_context_path(void)
{
return get_path(VIRTUAL_IMAGE);
}
-hidden_def(selinux_virtual_image_context_path)
const char *selinux_lxc_contexts_path(void)
{
return get_path(LXC_CONTEXTS);
}
-hidden_def(selinux_lxc_contexts_path)
const char *selinux_openrc_contexts_path(void)
{
return get_path(OPENRC_CONTEXTS);
}
-hidden_def(selinux_openrc_contexts_path)
const char *selinux_openssh_contexts_path(void)
{
return get_path(OPENSSH_CONTEXTS);
}
-hidden_def(selinux_openssh_contexts_path)
const char *selinux_snapperd_contexts_path(void)
{
return get_path(SNAPPERD_CONTEXTS);
}
-hidden_def(selinux_snapperd_contexts_path)
const char *selinux_systemd_contexts_path(void)
{
return get_path(SYSTEMD_CONTEXTS);
}
-hidden_def(selinux_systemd_contexts_path)
const char * selinux_booleans_subs_path(void) {
return get_path(BOOLEAN_SUBS);
}
-hidden_def(selinux_booleans_subs_path)
const char * selinux_file_context_subs_path(void) {
return get_path(FILE_CONTEXT_SUBS);
}
-hidden_def(selinux_file_context_subs_path)
const char * selinux_file_context_subs_dist_path(void) {
return get_path(FILE_CONTEXT_SUBS_DIST);
}
-hidden_def(selinux_file_context_subs_dist_path)
const char *selinux_sepgsql_context_path(void)
{
return get_path(SEPGSQL_CONTEXTS);
}
-hidden_def(selinux_sepgsql_context_path)
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
index 61b78aaa..297dcf26 100644
--- a/libselinux/src/selinux_internal.h
+++ b/libselinux/src/selinux_internal.h
@@ -1,116 +1,9 @@
#include <selinux/selinux.h>
#include <pthread.h>
-#include "dso.h"
-
-hidden_proto(selinux_mkload_policy)
- hidden_proto(fini_selinuxmnt)
- hidden_proto(set_selinuxmnt)
- hidden_proto(selinuxfs_exists)
- hidden_proto(security_disable)
- hidden_proto(security_policyvers)
- hidden_proto(security_load_policy)
- hidden_proto(security_get_boolean_active)
- hidden_proto(security_get_boolean_names)
- hidden_proto(security_set_boolean)
- hidden_proto(security_commit_booleans)
- hidden_proto(security_check_context)
- hidden_proto(security_check_context_raw)
- hidden_proto(security_canonicalize_context)
- hidden_proto(security_canonicalize_context_raw)
- hidden_proto(security_compute_av)
- hidden_proto(security_compute_av_raw)
- hidden_proto(security_compute_av_flags)
- hidden_proto(security_compute_av_flags_raw)
- hidden_proto(security_compute_user)
- hidden_proto(security_compute_user_raw)
- hidden_proto(security_compute_create)
- hidden_proto(security_compute_create_raw)
- hidden_proto(security_compute_create_name)
- hidden_proto(security_compute_create_name_raw)
- hidden_proto(security_compute_member_raw)
- hidden_proto(security_compute_relabel_raw)
- hidden_proto(security_validatetrans)
- hidden_proto(security_validatetrans_raw)
- hidden_proto(is_selinux_enabled)
- hidden_proto(is_selinux_mls_enabled)
- hidden_proto(freecon)
- hidden_proto(freeconary)
- hidden_proto(getprevcon)
- hidden_proto(getprevcon_raw)
- hidden_proto(getcon)
- hidden_proto(getcon_raw)
- hidden_proto(setcon_raw)
- hidden_proto(getpeercon_raw)
- hidden_proto(getpidcon_raw)
- hidden_proto(getexeccon_raw)
- hidden_proto(getfilecon)
- hidden_proto(getfilecon_raw)
- hidden_proto(lgetfilecon_raw)
- hidden_proto(fgetfilecon_raw)
- hidden_proto(setfilecon_raw)
- hidden_proto(lsetfilecon_raw)
- hidden_proto(fsetfilecon_raw)
- hidden_proto(setexeccon)
- hidden_proto(setexeccon_raw)
- hidden_proto(getfscreatecon_raw)
- hidden_proto(getkeycreatecon_raw)
- hidden_proto(getsockcreatecon_raw)
- hidden_proto(setfscreatecon_raw)
- hidden_proto(setkeycreatecon_raw)
- hidden_proto(setsockcreatecon_raw)
- hidden_proto(security_getenforce)
- hidden_proto(security_setenforce)
- hidden_proto(security_deny_unknown)
- hidden_proto(security_reject_unknown)
- hidden_proto(security_get_checkreqprot)
- hidden_proto(selinux_boolean_sub)
- hidden_proto(selinux_current_policy_path)
- hidden_proto(selinux_binary_policy_path)
- hidden_proto(selinux_booleans_subs_path)
- hidden_proto(selinux_default_context_path)
- hidden_proto(selinux_securetty_types_path)
- hidden_proto(selinux_failsafe_context_path)
- hidden_proto(selinux_removable_context_path)
- hidden_proto(selinux_virtual_domain_context_path)
- hidden_proto(selinux_virtual_image_context_path)
- hidden_proto(selinux_lxc_contexts_path)
- hidden_proto(selinux_file_context_path)
- hidden_proto(selinux_file_context_homedir_path)
- hidden_proto(selinux_file_context_local_path)
- hidden_proto(selinux_file_context_subs_dist_path)
- hidden_proto(selinux_file_context_subs_path)
- hidden_proto(selinux_netfilter_context_path)
- hidden_proto(selinux_homedir_context_path)
- hidden_proto(selinux_user_contexts_path)
- hidden_proto(selinux_booleans_path)
- hidden_proto(selinux_customizable_types_path)
- hidden_proto(selinux_media_context_path)
- hidden_proto(selinux_x_context_path)
- hidden_proto(selinux_sepgsql_context_path)
- hidden_proto(selinux_openrc_contexts_path)
- hidden_proto(selinux_openssh_contexts_path)
- hidden_proto(selinux_snapperd_contexts_path)
- hidden_proto(selinux_systemd_contexts_path)
- hidden_proto(selinux_path)
- hidden_proto(selinux_check_passwd_access)
- hidden_proto(selinux_check_securetty_context)
- hidden_proto(matchpathcon_init_prefix)
- hidden_proto(selinux_users_path)
- hidden_proto(selinux_usersconf_path);
-hidden_proto(selinux_translations_path);
-hidden_proto(selinux_colors_path);
-hidden_proto(selinux_getenforcemode);
-hidden_proto(selinux_getpolicytype);
-hidden_proto(selinux_raw_to_trans_context);
-hidden_proto(selinux_trans_to_raw_context);
- hidden_proto(selinux_raw_context_to_color);
-hidden_proto(security_get_initial_context);
-hidden_proto(security_get_initial_context_raw);
-hidden_proto(selinux_reset_config);
-hidden_proto(selinux_flush_class_cache);
-
-extern int require_seusers hidden;
-extern int selinux_page_size hidden;
+
+
+extern int require_seusers ;
+extern int selinux_page_size ;
/* Make pthread_once optional */
#pragma weak pthread_once
@@ -176,8 +69,24 @@ extern int selinux_page_size hidden;
pthread_mutex_unlock(LOCK); \
} while (0)
+#pragma weak pthread_create
+#pragma weak pthread_join
+#pragma weak pthread_cond_init
+#pragma weak pthread_cond_signal
+#pragma weak pthread_cond_destroy
+#pragma weak pthread_cond_wait
+
+/* check if all functions needed to do parallel operations are available */
+#define __pthread_supported ( \
+ pthread_create && \
+ pthread_join && \
+ pthread_cond_init && \
+ pthread_cond_destroy && \
+ pthread_cond_signal && \
+ pthread_cond_wait \
+)
#define SELINUXDIR "/etc/selinux/"
#define SELINUXCONFIG SELINUXDIR "config"
-extern int has_selinux_config hidden;
+extern int has_selinux_config ;
diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
index 028d8924..72f4fb46 100644
--- a/libselinux/src/selinux_restorecon.c
+++ b/libselinux/src/selinux_restorecon.c
@@ -60,9 +60,10 @@ static int exclude_count = 0;
static struct edir *exclude_lst = NULL;
static uint64_t fc_count = 0; /* Number of files processed so far */
static uint64_t efile_count; /* Estimated total number of files */
+static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Store information on directories with xattr's. */
-struct dir_xattr *dir_xattr_list;
+static struct dir_xattr *dir_xattr_list;
static struct dir_xattr *dir_xattr_last;
/* restorecon_flags for passing to restorecon_sb() */
@@ -81,6 +82,7 @@ struct rest_flags {
bool log_matches;
bool ignore_noent;
bool warnonnomatch;
+ bool conflicterror;
};
static void restorecon_init(void)
@@ -229,7 +231,6 @@ static int exclude_non_seclabel_mounts(void)
struct utsname uts;
FILE *fp;
size_t len;
- ssize_t num;
int index = 0, found = 0, nfile = 0;
char *mount_info[4];
char *buf = NULL, *item;
@@ -244,7 +245,7 @@ static int exclude_non_seclabel_mounts(void)
if (!fp)
return 0;
- while ((num = getline(&buf, &len, fp)) != -1) {
+ while (getline(&buf, &len, fp) != -1) {
found = 0;
index = 0;
item = strtok(buf, " ");
@@ -296,6 +297,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
char *sha1_buf = NULL;
size_t i, digest_len = 0;
int rc, digest_result;
+ bool match;
struct dir_xattr *new_entry;
uint8_t *xattr_digest = NULL;
uint8_t *calculated_digest = NULL;
@@ -305,9 +307,9 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
return -1;
}
- selabel_get_digests_all_partial_matches(fc_sehandle, directory,
- &calculated_digest,
- &xattr_digest, &digest_len);
+ match = selabel_get_digests_all_partial_matches(fc_sehandle, directory,
+ &calculated_digest, &xattr_digest,
+ &digest_len);
if (!xattr_digest || !digest_len) {
free(calculated_digest);
@@ -325,16 +327,14 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch,
for (i = 0; i < digest_len; i++)
sprintf((&sha1_buf[i * 2]), "%02x", xattr_digest[i]);
- rc = memcmp(calculated_digest, xattr_digest, digest_len);
- digest_result = rc ? NOMATCH : MATCH;
+ digest_result = match ? MATCH : NOMATCH;
- if ((delete_nonmatch && rc != 0) || delete_all) {
- digest_result = rc ? DELETED_NOMATCH : DELETED_MATCH;
+ if ((delete_nonmatch && !match) || delete_all) {
+ digest_result = match ? DELETED_MATCH : DELETED_NOMATCH;
rc = removexattr(directory, RESTORECON_PARTIAL_MATCH_DIGEST);
if (rc) {
selinux_log(SELINUX_ERROR,
- "Error: %s removing xattr \"%s\" from: %s\n",
- strerror(errno),
+ "Error: %m removing xattr \"%s\" from: %s\n",
RESTORECON_PARTIAL_MATCH_DIGEST, directory);
digest_result = ERROR;
}
@@ -412,23 +412,26 @@ typedef struct file_spec {
} file_spec_t;
static file_spec_t *fl_head;
+static pthread_mutex_t fl_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* Try to add an association between an inode and a context. If there is a
* different context that matched the inode, then use the first context
* that matched.
*/
-static int filespec_add(ino_t ino, const char *con, const char *file)
+static int filespec_add(ino_t ino, const char *con, const char *file,
+ struct rest_flags *flags)
{
file_spec_t *prevfl, *fl;
int h, ret;
struct stat64 sb;
+ __pthread_mutex_lock(&fl_mutex);
+
if (!fl_head) {
- fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS);
+ fl_head = calloc(HASH_BUCKETS, sizeof(file_spec_t));
if (!fl_head)
goto oom;
- memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS);
}
h = (ino + (ino >> HASH_BITS)) & HASH_MASK;
@@ -445,11 +448,11 @@ static int filespec_add(ino_t ino, const char *con, const char *file)
fl->con = strdup(con);
if (!fl->con)
goto oom;
- return 1;
+ goto unlock_1;
}
if (strcmp(fl->con, con) == 0)
- return 1;
+ goto unlock_1;
selinux_log(SELINUX_ERROR,
"conflicting specifications for %s and %s, using %s.\n",
@@ -458,6 +461,14 @@ static int filespec_add(ino_t ino, const char *con, const char *file)
fl->file = strdup(file);
if (!fl->file)
goto oom;
+
+ __pthread_mutex_unlock(&fl_mutex);
+
+ if (flags->conflicterror) {
+ selinux_log(SELINUX_ERROR,
+ "treating conflicting specifications as an error.\n");
+ return -1;
+ }
return 1;
}
@@ -477,13 +488,19 @@ static int filespec_add(ino_t ino, const char *con, const char *file)
goto oom_freefl;
fl->next = prevfl->next;
prevfl->next = fl;
+
+ __pthread_mutex_unlock(&fl_mutex);
return 0;
oom_freefl:
free(fl);
oom:
+ __pthread_mutex_unlock(&fl_mutex);
selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__);
return -1;
+unlock_1:
+ __pthread_mutex_unlock(&fl_mutex);
+ return 1;
}
/*
@@ -593,7 +610,7 @@ out:
}
static int restorecon_sb(const char *pathname, const struct stat *sb,
- struct rest_flags *flags)
+ struct rest_flags *flags, bool first)
{
char *newcon = NULL;
char *curcon = NULL;
@@ -622,7 +639,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,
sb->st_mode);
if (rc < 0) {
- if (errno == ENOENT && flags->warnonnomatch)
+ if (errno == ENOENT && flags->warnonnomatch && first)
selinux_log(SELINUX_INFO,
"Warning no default label for %s\n",
lookup_path);
@@ -631,6 +648,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,
}
if (flags->progress) {
+ __pthread_mutex_lock(&progress_mutex);
fc_count++;
if (fc_count % STAR_COUNT == 0) {
if (flags->mass_relabel && efile_count > 0) {
@@ -642,10 +660,11 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,
}
fflush(stdout);
}
+ __pthread_mutex_unlock(&progress_mutex);
}
if (flags->add_assoc) {
- rc = filespec_add(sb->st_ino, newcon, pathname);
+ rc = filespec_add(sb->st_ino, newcon, pathname, flags);
if (rc < 0) {
selinux_log(SELINUX_ERROR,
@@ -728,8 +747,8 @@ out1:
return rc;
err:
selinux_log(SELINUX_ERROR,
- "Could not set context for %s: %s\n",
- pathname, strerror(errno));
+ "Could not set context for %s: %m\n",
+ pathname);
rc = -1;
goto out1;
}
@@ -795,63 +814,215 @@ oom:
goto free;
}
+struct rest_state {
+ struct rest_flags flags;
+ dev_t dev_num;
+ struct statfs sfsb;
+ bool ignore_digest;
+ bool setrestorecondigest;
+ bool parallel;
-/*
- * Public API
- */
+ FTS *fts;
+ FTSENT *ftsent_first;
+ struct dir_hash_node *head, *current;
+ bool abort;
+ int error;
+ int saved_errno;
+ pthread_mutex_t mutex;
+};
-/* selinux_restorecon(3) - Main function that is responsible for labeling */
-int selinux_restorecon(const char *pathname_orig,
- unsigned int restorecon_flags)
+static void *selinux_restorecon_thread(void *arg)
{
- struct rest_flags flags;
+ struct rest_state *state = arg;
+ FTS *fts = state->fts;
+ FTSENT *ftsent;
+ int error;
+ char ent_path[PATH_MAX];
+ struct stat ent_st;
+ bool first = false;
+
+ if (state->parallel)
+ pthread_mutex_lock(&state->mutex);
+
+ if (state->ftsent_first) {
+ ftsent = state->ftsent_first;
+ state->ftsent_first = NULL;
+ first = true;
+ goto loop_body;
+ }
+
+ while (((void)(errno = 0), ftsent = fts_read(fts)) != NULL) {
+loop_body:
+ /* If the FTS_XDEV flag is set and the device is different */
+ if (state->flags.set_xdev &&
+ ftsent->fts_statp->st_dev != state->dev_num)
+ continue;
+
+ switch (ftsent->fts_info) {
+ case FTS_DC:
+ selinux_log(SELINUX_ERROR,
+ "Directory cycle on %s.\n",
+ ftsent->fts_path);
+ errno = ELOOP;
+ state->error = -1;
+ state->abort = true;
+ goto finish;
+ case FTS_DP:
+ continue;
+ case FTS_DNR:
+ error = errno;
+ errno = ftsent->fts_errno;
+ selinux_log(SELINUX_ERROR,
+ "Could not read %s: %m.\n",
+ ftsent->fts_path);
+ errno = error;
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ case FTS_NS:
+ error = errno;
+ errno = ftsent->fts_errno;
+ selinux_log(SELINUX_ERROR,
+ "Could not stat %s: %m.\n",
+ ftsent->fts_path);
+ errno = error;
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ case FTS_ERR:
+ error = errno;
+ errno = ftsent->fts_errno;
+ selinux_log(SELINUX_ERROR,
+ "Error on %s: %m.\n",
+ ftsent->fts_path);
+ errno = error;
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ case FTS_D:
+ if (state->sfsb.f_type == SYSFS_MAGIC &&
+ !selabel_partial_match(fc_sehandle,
+ ftsent->fts_path)) {
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ }
+
+ if (check_excluded(ftsent->fts_path)) {
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ }
+
+ if (state->setrestorecondigest) {
+ struct dir_hash_node *new_node = NULL;
+
+ if (check_context_match_for_dir(ftsent->fts_path,
+ &new_node,
+ state->error) &&
+ !state->ignore_digest) {
+ selinux_log(SELINUX_INFO,
+ "Skipping restorecon on directory(%s)\n",
+ ftsent->fts_path);
+ fts_set(fts, ftsent, FTS_SKIP);
+ continue;
+ }
+
+ if (new_node && !state->error) {
+ if (!state->current) {
+ state->current = new_node;
+ state->head = state->current;
+ } else {
+ state->current->next = new_node;
+ state->current = new_node;
+ }
+ }
+ }
+ /* fall through */
+ default:
+ strcpy(ent_path, ftsent->fts_path);
+ ent_st = *ftsent->fts_statp;
+ if (state->parallel)
+ pthread_mutex_unlock(&state->mutex);
+
+ error = restorecon_sb(ent_path, &ent_st, &state->flags,
+ first);
+
+ if (state->parallel) {
+ pthread_mutex_lock(&state->mutex);
+ if (state->abort)
+ goto unlock;
+ }
- flags.nochange = (restorecon_flags &
+ state->error |= error;
+ first = false;
+ if (error && state->flags.abort_on_error) {
+ state->abort = true;
+ goto finish;
+ }
+ break;
+ }
+ }
+
+finish:
+ if (!state->saved_errno)
+ state->saved_errno = errno;
+unlock:
+ if (state->parallel)
+ pthread_mutex_unlock(&state->mutex);
+ return NULL;
+}
+
+static int selinux_restorecon_common(const char *pathname_orig,
+ unsigned int restorecon_flags,
+ size_t nthreads)
+{
+ struct rest_state state;
+
+ state.flags.nochange = (restorecon_flags &
SELINUX_RESTORECON_NOCHANGE) ? true : false;
- flags.verbose = (restorecon_flags &
+ state.flags.verbose = (restorecon_flags &
SELINUX_RESTORECON_VERBOSE) ? true : false;
- flags.progress = (restorecon_flags &
+ state.flags.progress = (restorecon_flags &
SELINUX_RESTORECON_PROGRESS) ? true : false;
- flags.mass_relabel = (restorecon_flags &
+ state.flags.mass_relabel = (restorecon_flags &
SELINUX_RESTORECON_MASS_RELABEL) ? true : false;
- flags.recurse = (restorecon_flags &
+ state.flags.recurse = (restorecon_flags &
SELINUX_RESTORECON_RECURSE) ? true : false;
- flags.set_specctx = (restorecon_flags &
+ state.flags.set_specctx = (restorecon_flags &
SELINUX_RESTORECON_SET_SPECFILE_CTX) ? true : false;
- flags.userealpath = (restorecon_flags &
+ state.flags.userealpath = (restorecon_flags &
SELINUX_RESTORECON_REALPATH) ? true : false;
- flags.set_xdev = (restorecon_flags &
+ state.flags.set_xdev = (restorecon_flags &
SELINUX_RESTORECON_XDEV) ? true : false;
- flags.add_assoc = (restorecon_flags &
+ state.flags.add_assoc = (restorecon_flags &
SELINUX_RESTORECON_ADD_ASSOC) ? true : false;
- flags.abort_on_error = (restorecon_flags &
+ state.flags.abort_on_error = (restorecon_flags &
SELINUX_RESTORECON_ABORT_ON_ERROR) ? true : false;
- flags.syslog_changes = (restorecon_flags &
+ state.flags.syslog_changes = (restorecon_flags &
SELINUX_RESTORECON_SYSLOG_CHANGES) ? true : false;
- flags.log_matches = (restorecon_flags &
+ state.flags.log_matches = (restorecon_flags &
SELINUX_RESTORECON_LOG_MATCHES) ? true : false;
- flags.ignore_noent = (restorecon_flags &
+ state.flags.ignore_noent = (restorecon_flags &
SELINUX_RESTORECON_IGNORE_NOENTRY) ? true : false;
- flags.warnonnomatch = true;
+ state.flags.warnonnomatch = true;
+ state.flags.conflicterror = (restorecon_flags &
+ SELINUX_RESTORECON_CONFLICT_ERROR) ? true : false;
ignore_mounts = (restorecon_flags &
SELINUX_RESTORECON_IGNORE_MOUNTS) ? true : false;
- bool ignore_digest = (restorecon_flags &
+ state.ignore_digest = (restorecon_flags &
SELINUX_RESTORECON_IGNORE_DIGEST) ? true : false;
- bool setrestorecondigest = true;
+ state.setrestorecondigest = true;
+
+ state.head = NULL;
+ state.current = NULL;
+ state.abort = false;
+ state.error = 0;
+ state.saved_errno = 0;
struct stat sb;
- struct statfs sfsb;
- FTS *fts;
- FTSENT *ftsent;
char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname;
char *paths[2] = { NULL, NULL };
int fts_flags, error, sverrno;
- dev_t dev_num = 0;
struct dir_hash_node *current = NULL;
- struct dir_hash_node *head = NULL;
- if (flags.verbose && flags.progress)
- flags.verbose = false;
+ if (state.flags.verbose && state.flags.progress)
+ state.flags.verbose = false;
__selinux_once(fc_once, restorecon_init);
@@ -864,13 +1035,31 @@ int selinux_restorecon(const char *pathname_orig,
*/
if (selabel_no_digest ||
(restorecon_flags & SELINUX_RESTORECON_SKIP_DIGEST))
- setrestorecondigest = false;
+ state.setrestorecondigest = false;
+
+ if (!__pthread_supported) {
+ if (nthreads != 1) {
+ nthreads = 1;
+ selinux_log(SELINUX_WARNING,
+ "Threading functionality not available, falling back to 1 thread.");
+ }
+ } else if (nthreads == 0) {
+ long nproc = sysconf(_SC_NPROCESSORS_ONLN);
+
+ if (nproc > 0) {
+ nthreads = nproc;
+ } else {
+ nthreads = 1;
+ selinux_log(SELINUX_WARNING,
+ "Unable to detect CPU count, falling back to 1 thread.");
+ }
+ }
/*
* Convert passed-in pathname to canonical pathname by resolving
* realpath of containing dir, then appending last component name.
*/
- if (flags.userealpath) {
+ if (state.flags.userealpath) {
char *basename_cpy = strdup(pathname_orig);
if (!basename_cpy)
goto realpatherr;
@@ -915,58 +1104,59 @@ int selinux_restorecon(const char *pathname_orig,
paths[0] = pathname;
if (lstat(pathname, &sb) < 0) {
- if (flags.ignore_noent && errno == ENOENT) {
+ if (state.flags.ignore_noent && errno == ENOENT) {
free(pathdnamer);
free(pathname);
return 0;
} else {
selinux_log(SELINUX_ERROR,
- "lstat(%s) failed: %s\n",
- pathname, strerror(errno));
+ "lstat(%s) failed: %m\n",
+ pathname);
error = -1;
goto cleanup;
}
}
/* Skip digest if not a directory */
- if ((sb.st_mode & S_IFDIR) != S_IFDIR)
- setrestorecondigest = false;
+ if (!S_ISDIR(sb.st_mode))
+ state.setrestorecondigest = false;
- if (!flags.recurse) {
+ if (!state.flags.recurse) {
if (check_excluded(pathname)) {
error = 0;
goto cleanup;
}
- error = restorecon_sb(pathname, &sb, &flags);
+ error = restorecon_sb(pathname, &sb, &state.flags, true);
goto cleanup;
}
/* Obtain fs type */
- if (statfs(pathname, &sfsb) < 0) {
+ memset(&state.sfsb, 0, sizeof(state.sfsb));
+ if (!S_ISLNK(sb.st_mode) && statfs(pathname, &state.sfsb) < 0) {
selinux_log(SELINUX_ERROR,
- "statfs(%s) failed: %s\n",
- pathname, strerror(errno));
+ "statfs(%s) failed: %m\n",
+ pathname);
error = -1;
goto cleanup;
}
/* Skip digest on in-memory filesystems and /sys */
- if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC ||
- sfsb.f_type == SYSFS_MAGIC)
- setrestorecondigest = false;
+ if (state.sfsb.f_type == RAMFS_MAGIC || state.sfsb.f_type == TMPFS_MAGIC ||
+ state.sfsb.f_type == SYSFS_MAGIC)
+ state.setrestorecondigest = false;
- if (flags.set_xdev)
+ if (state.flags.set_xdev)
fts_flags = FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV;
else
fts_flags = FTS_PHYSICAL | FTS_NOCHDIR;
- fts = fts_open(paths, fts_flags, NULL);
- if (!fts)
+ state.fts = fts_open(paths, fts_flags, NULL);
+ if (!state.fts)
goto fts_err;
- ftsent = fts_read(fts);
- if (!ftsent)
+ state.ftsent_first = fts_read(state.fts);
+ if (!state.ftsent_first)
goto fts_err;
/*
@@ -978,131 +1168,95 @@ int selinux_restorecon(const char *pathname_orig,
* directories with a different device number when the FTS_XDEV flag
* is set (from http://marc.info/?l=selinux&m=124688830500777&w=2).
*/
- dev_num = ftsent->fts_statp->st_dev;
+ state.dev_num = state.ftsent_first->fts_statp->st_dev;
- error = 0;
- do {
- /* If the FTS_XDEV flag is set and the device is different */
- if (flags.set_xdev && ftsent->fts_statp->st_dev != dev_num)
- continue;
+ if (nthreads == 1) {
+ state.parallel = false;
+ selinux_restorecon_thread(&state);
+ } else {
+ size_t i;
+ pthread_t self = pthread_self();
+ pthread_t *threads = NULL;
- switch (ftsent->fts_info) {
- case FTS_DC:
- selinux_log(SELINUX_ERROR,
- "Directory cycle on %s.\n",
- ftsent->fts_path);
- errno = ELOOP;
- error = -1;
- goto out;
- case FTS_DP:
- continue;
- case FTS_DNR:
- selinux_log(SELINUX_ERROR,
- "Could not read %s: %s.\n",
- ftsent->fts_path,
- strerror(ftsent->fts_errno));
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_NS:
- selinux_log(SELINUX_ERROR,
- "Could not stat %s: %s.\n",
- ftsent->fts_path,
- strerror(ftsent->fts_errno));
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_ERR:
- selinux_log(SELINUX_ERROR,
- "Error on %s: %s.\n",
- ftsent->fts_path,
- strerror(ftsent->fts_errno));
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_D:
- if (sfsb.f_type == SYSFS_MAGIC &&
- !selabel_partial_match(fc_sehandle,
- ftsent->fts_path)) {
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- }
+ pthread_mutex_init(&state.mutex, NULL);
- if (check_excluded(ftsent->fts_path)) {
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- }
+ threads = calloc(nthreads - 1, sizeof(*threads));
+ if (!threads)
+ goto oom;
- if (setrestorecondigest) {
- struct dir_hash_node *new_node = NULL;
+ state.parallel = true;
+ /*
+ * Start (nthreads - 1) threads - the main thread is going to
+ * take part, too.
+ */
+ for (i = 0; i < nthreads - 1; i++) {
+ if (pthread_create(&threads[i], NULL,
+ selinux_restorecon_thread, &state)) {
+ /*
+ * If any thread fails to be created, just mark
+ * it as such and let the successfully created
+ * threads do the job. In the worst case the
+ * main thread will do everything, but that's
+ * still better than to give up.
+ */
+ threads[i] = self;
+ }
+ }
- if (check_context_match_for_dir(ftsent->fts_path,
- &new_node,
- error) &&
- !ignore_digest) {
- selinux_log(SELINUX_INFO,
- "Skipping restorecon on directory(%s)\n",
- ftsent->fts_path);
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- }
+ /* Let's join in on the fun! */
+ selinux_restorecon_thread(&state);
- if (new_node && !error) {
- if (!current) {
- current = new_node;
- head = current;
- } else {
- current->next = new_node;
- current = current->next;
- }
- }
- }
- /* fall through */
- default:
- error |= restorecon_sb(ftsent->fts_path,
- ftsent->fts_statp, &flags);
- if (flags.warnonnomatch)
- flags.warnonnomatch = false;
- if (error && flags.abort_on_error)
- goto out;
- break;
+ /* Now wait for all threads to finish. */
+ for (i = 0; i < nthreads - 1; i++) {
+ /* Skip threads that failed to be created. */
+ if (pthread_equal(threads[i], self))
+ continue;
+ pthread_join(threads[i], NULL);
}
- } while ((ftsent = fts_read(fts)) != NULL);
+ free(threads);
+
+ pthread_mutex_destroy(&state.mutex);
+ }
+
+ error = state.error;
+ if (state.saved_errno)
+ goto out;
/*
* Labeling successful. Write partial match digests for subdirectories.
* TODO: Write digest upon FTS_DP if no error occurs in its descents.
*/
- if (setrestorecondigest && !flags.nochange && !error) {
- current = head;
+ if (state.setrestorecondigest && !state.flags.nochange && !error) {
+ current = state.head;
while (current != NULL) {
if (setxattr(current->path,
RESTORECON_PARTIAL_MATCH_DIGEST,
current->digest,
SHA1_HASH_SIZE, 0) < 0) {
selinux_log(SELINUX_ERROR,
- "setxattr failed: %s: %s\n",
- current->path,
- strerror(errno));
+ "setxattr failed: %s: %m\n",
+ current->path);
}
current = current->next;
}
}
out:
- if (flags.progress && flags.mass_relabel)
+ if (state.flags.progress && state.flags.mass_relabel)
fprintf(stdout, "\r%s 100.0%%\n", pathname);
- sverrno = errno;
- (void) fts_close(fts);
- errno = sverrno;
+ (void) fts_close(state.fts);
+ errno = state.saved_errno;
cleanup:
- if (flags.add_assoc) {
- if (flags.verbose)
+ if (state.flags.add_assoc) {
+ if (state.flags.verbose)
filespec_eval();
filespec_destroy();
}
free(pathdnamer);
free(pathname);
- current = head;
+ current = state.head;
while (current != NULL) {
struct dir_hash_node *next = current->next;
@@ -1122,20 +1276,40 @@ oom:
realpatherr:
sverrno = errno;
selinux_log(SELINUX_ERROR,
- "SELinux: Could not get canonical path for %s restorecon: %s.\n",
- pathname_orig, strerror(errno));
+ "SELinux: Could not get canonical path for %s restorecon: %m.\n",
+ pathname_orig);
errno = sverrno;
error = -1;
goto cleanup;
fts_err:
selinux_log(SELINUX_ERROR,
- "fts error while labeling %s: %s\n",
- paths[0], strerror(errno));
+ "fts error while labeling %s: %m\n",
+ paths[0]);
error = -1;
goto cleanup;
}
+
+/*
+ * Public API
+ */
+
+/* selinux_restorecon(3) - Main function that is responsible for labeling */
+int selinux_restorecon(const char *pathname_orig,
+ unsigned int restorecon_flags)
+{
+ return selinux_restorecon_common(pathname_orig, restorecon_flags, 1);
+}
+
+/* selinux_restorecon_parallel(3) - Parallel version of selinux_restorecon(3) */
+int selinux_restorecon_parallel(const char *pathname_orig,
+ unsigned int restorecon_flags,
+ size_t nthreads)
+{
+ return selinux_restorecon_common(pathname_orig, restorecon_flags, nthreads);
+}
+
/* selinux_restorecon_set_sehandle(3) is called to set the global fc handle */
void selinux_restorecon_set_sehandle(struct selabel_handle *hndl)
{
@@ -1143,7 +1317,9 @@ void selinux_restorecon_set_sehandle(struct selabel_handle *hndl)
unsigned char *fc_digest;
size_t num_specfiles, fc_digest_len;
- fc_sehandle = (struct selabel_handle *) hndl;
+ fc_sehandle = hndl;
+ if (!fc_sehandle)
+ return;
/* Check if digest requested in selabel_open(3), if so use it. */
if (selabel_digest(fc_sehandle, &fc_digest, &fc_digest_len,
@@ -1170,8 +1346,7 @@ struct selabel_handle *selinux_restorecon_default_handle(void)
if (!sehandle) {
selinux_log(SELINUX_ERROR,
- "Error obtaining file context handle: %s\n",
- strerror(errno));
+ "Error obtaining file context handle: %m\n");
return NULL;
}
@@ -1191,8 +1366,8 @@ void selinux_restorecon_set_exclude_list(const char **exclude_list)
for (i = 0; exclude_list[i]; i++) {
if (lstat(exclude_list[i], &sb) < 0 && errno != EACCES) {
selinux_log(SELINUX_ERROR,
- "lstat error on exclude path \"%s\", %s - ignoring.\n",
- exclude_list[i], strerror(errno));
+ "lstat error on exclude path \"%s\", %m - ignoring.\n",
+ exclude_list[i]);
break;
}
if (add_exclude(exclude_list[i], CALLER_EXCLUDED) &&
@@ -1258,8 +1433,8 @@ int selinux_restorecon_xattr(const char *pathname, unsigned int xattr_flags,
return 0;
selinux_log(SELINUX_ERROR,
- "lstat(%s) failed: %s\n",
- pathname, strerror(errno));
+ "lstat(%s) failed: %m\n",
+ pathname);
return -1;
}
@@ -1289,8 +1464,8 @@ int selinux_restorecon_xattr(const char *pathname, unsigned int xattr_flags,
fts = fts_open(paths, fts_flags, NULL);
if (!fts) {
selinux_log(SELINUX_ERROR,
- "fts error on %s: %s\n",
- paths[0], strerror(errno));
+ "fts error on %s: %m\n",
+ paths[0]);
return -1;
}
diff --git a/libselinux/src/selinuxswig_python.i b/libselinux/src/selinuxswig_python.i
index 4c73bf92..17e03b9e 100644
--- a/libselinux/src/selinuxswig_python.i
+++ b/libselinux/src/selinuxswig_python.i
@@ -20,7 +20,7 @@ DISABLED = -1
PERMISSIVE = 0
ENFORCING = 1
-def restorecon(path, recursive=False, verbose=False, force=False):
+def restorecon(path, recursive=False, verbose=False, force=False, nthreads=1):
""" Restore SELinux context on a given path
Arguments:
@@ -32,6 +32,8 @@ def restorecon(path, recursive=False, verbose=False, force=False):
force -- Force reset of context to match file_context for customizable files,
and the default file context, changing the user, role, range portion as well
as the type (default False)
+ nthreads -- The number of threads to use during relabeling, or 0 to use as many
+ threads as there are online CPU cores (default 1)
"""
restorecon_flags = SELINUX_RESTORECON_IGNORE_DIGEST | SELINUX_RESTORECON_REALPATH
@@ -41,7 +43,7 @@ def restorecon(path, recursive=False, verbose=False, force=False):
restorecon_flags |= SELINUX_RESTORECON_VERBOSE
if force:
restorecon_flags |= SELINUX_RESTORECON_SET_SPECFILE_CTX
- selinux_restorecon(os.path.expanduser(path), restorecon_flags)
+ selinux_restorecon_parallel(os.path.expanduser(path), restorecon_flags, nthreads)
def chcon(path, context, recursive=False):
""" Set the SELinux context on a given path """
diff --git a/libselinux/src/selinuxswig_python_exception.i b/libselinux/src/selinuxswig_python_exception.i
index cf658259..a02f4923 100644
--- a/libselinux/src/selinuxswig_python_exception.i
+++ b/libselinux/src/selinuxswig_python_exception.i
@@ -7,7 +7,6 @@
}
}
-
%exception is_selinux_mls_enabled {
$action
if (result < 0) {
@@ -16,7 +15,6 @@
}
}
-
%exception getcon {
$action
if (result < 0) {
@@ -25,7 +23,6 @@
}
}
-
%exception getcon_raw {
$action
if (result < 0) {
@@ -34,7 +31,6 @@
}
}
-
%exception setcon {
$action
if (result < 0) {
@@ -43,7 +39,6 @@
}
}
-
%exception setcon_raw {
$action
if (result < 0) {
@@ -52,7 +47,6 @@
}
}
-
%exception getpidcon {
$action
if (result < 0) {
@@ -61,7 +55,6 @@
}
}
-
%exception getpidcon_raw {
$action
if (result < 0) {
@@ -70,7 +63,6 @@
}
}
-
%exception getprevcon {
$action
if (result < 0) {
@@ -79,7 +71,6 @@
}
}
-
%exception getprevcon_raw {
$action
if (result < 0) {
@@ -88,7 +79,6 @@
}
}
-
%exception getexeccon {
$action
if (result < 0) {
@@ -97,7 +87,6 @@
}
}
-
%exception getexeccon_raw {
$action
if (result < 0) {
@@ -106,7 +95,6 @@
}
}
-
%exception setexeccon {
$action
if (result < 0) {
@@ -115,7 +103,6 @@
}
}
-
%exception setexeccon_raw {
$action
if (result < 0) {
@@ -124,7 +111,6 @@
}
}
-
%exception getfscreatecon {
$action
if (result < 0) {
@@ -133,7 +119,6 @@
}
}
-
%exception getfscreatecon_raw {
$action
if (result < 0) {
@@ -142,7 +127,6 @@
}
}
-
%exception setfscreatecon {
$action
if (result < 0) {
@@ -151,7 +135,6 @@
}
}
-
%exception setfscreatecon_raw {
$action
if (result < 0) {
@@ -160,7 +143,6 @@
}
}
-
%exception getkeycreatecon {
$action
if (result < 0) {
@@ -169,7 +151,6 @@
}
}
-
%exception getkeycreatecon_raw {
$action
if (result < 0) {
@@ -178,7 +159,6 @@
}
}
-
%exception setkeycreatecon {
$action
if (result < 0) {
@@ -187,7 +167,6 @@
}
}
-
%exception setkeycreatecon_raw {
$action
if (result < 0) {
@@ -196,7 +175,6 @@
}
}
-
%exception getsockcreatecon {
$action
if (result < 0) {
@@ -205,7 +183,6 @@
}
}
-
%exception getsockcreatecon_raw {
$action
if (result < 0) {
@@ -214,7 +191,6 @@
}
}
-
%exception setsockcreatecon {
$action
if (result < 0) {
@@ -223,7 +199,6 @@
}
}
-
%exception setsockcreatecon_raw {
$action
if (result < 0) {
@@ -232,7 +207,6 @@
}
}
-
%exception getfilecon {
$action
if (result < 0) {
@@ -241,7 +215,6 @@
}
}
-
%exception getfilecon_raw {
$action
if (result < 0) {
@@ -250,7 +223,6 @@
}
}
-
%exception lgetfilecon {
$action
if (result < 0) {
@@ -259,7 +231,6 @@
}
}
-
%exception lgetfilecon_raw {
$action
if (result < 0) {
@@ -268,7 +239,6 @@
}
}
-
%exception fgetfilecon {
$action
if (result < 0) {
@@ -277,7 +247,6 @@
}
}
-
%exception fgetfilecon_raw {
$action
if (result < 0) {
@@ -286,7 +255,6 @@
}
}
-
%exception setfilecon {
$action
if (result < 0) {
@@ -295,7 +263,6 @@
}
}
-
%exception setfilecon_raw {
$action
if (result < 0) {
@@ -304,7 +271,6 @@
}
}
-
%exception lsetfilecon {
$action
if (result < 0) {
@@ -313,7 +279,6 @@
}
}
-
%exception lsetfilecon_raw {
$action
if (result < 0) {
@@ -322,7 +287,6 @@
}
}
-
%exception fsetfilecon {
$action
if (result < 0) {
@@ -331,7 +295,6 @@
}
}
-
%exception fsetfilecon_raw {
$action
if (result < 0) {
@@ -340,7 +303,6 @@
}
}
-
%exception getpeercon {
$action
if (result < 0) {
@@ -349,7 +311,6 @@
}
}
-
%exception getpeercon_raw {
$action
if (result < 0) {
@@ -358,7 +319,6 @@
}
}
-
%exception security_compute_av {
$action
if (result < 0) {
@@ -367,7 +327,6 @@
}
}
-
%exception security_compute_av_raw {
$action
if (result < 0) {
@@ -376,7 +335,6 @@
}
}
-
%exception security_compute_av_flags {
$action
if (result < 0) {
@@ -385,7 +343,6 @@
}
}
-
%exception security_compute_av_flags_raw {
$action
if (result < 0) {
@@ -394,7 +351,6 @@
}
}
-
%exception security_compute_create {
$action
if (result < 0) {
@@ -403,7 +359,6 @@
}
}
-
%exception security_compute_create_raw {
$action
if (result < 0) {
@@ -412,7 +367,6 @@
}
}
-
%exception security_compute_create_name {
$action
if (result < 0) {
@@ -421,7 +375,6 @@
}
}
-
%exception security_compute_create_name_raw {
$action
if (result < 0) {
@@ -430,7 +383,6 @@
}
}
-
%exception security_compute_relabel {
$action
if (result < 0) {
@@ -439,7 +391,6 @@
}
}
-
%exception security_compute_relabel_raw {
$action
if (result < 0) {
@@ -448,7 +399,6 @@
}
}
-
%exception security_compute_member {
$action
if (result < 0) {
@@ -457,7 +407,6 @@
}
}
-
%exception security_compute_member_raw {
$action
if (result < 0) {
@@ -466,7 +415,6 @@
}
}
-
%exception security_compute_user {
$action
if (result < 0) {
@@ -475,7 +423,6 @@
}
}
-
%exception security_compute_user_raw {
$action
if (result < 0) {
@@ -484,7 +431,6 @@
}
}
-
%exception security_validatetrans {
$action
if (result < 0) {
@@ -493,7 +439,6 @@
}
}
-
%exception security_validatetrans_raw {
$action
if (result < 0) {
@@ -502,7 +447,6 @@
}
}
-
%exception security_load_policy {
$action
if (result < 0) {
@@ -511,7 +455,6 @@
}
}
-
%exception security_get_initial_context {
$action
if (result < 0) {
@@ -520,7 +463,6 @@
}
}
-
%exception security_get_initial_context_raw {
$action
if (result < 0) {
@@ -529,7 +471,6 @@
}
}
-
%exception selinux_mkload_policy {
$action
if (result < 0) {
@@ -538,7 +479,6 @@
}
}
-
%exception selinux_init_load_policy {
$action
if (result < 0) {
@@ -547,7 +487,6 @@
}
}
-
%exception security_set_boolean_list {
$action
if (result < 0) {
@@ -556,7 +495,6 @@
}
}
-
%exception security_load_booleans {
$action
if (result < 0) {
@@ -565,7 +503,6 @@
}
}
-
%exception security_check_context {
$action
if (result < 0) {
@@ -574,7 +511,6 @@
}
}
-
%exception security_check_context_raw {
$action
if (result < 0) {
@@ -583,7 +519,6 @@
}
}
-
%exception security_canonicalize_context {
$action
if (result < 0) {
@@ -592,7 +527,6 @@
}
}
-
%exception security_canonicalize_context_raw {
$action
if (result < 0) {
@@ -601,7 +535,6 @@
}
}
-
%exception security_getenforce {
$action
if (result < 0) {
@@ -610,7 +543,6 @@
}
}
-
%exception security_setenforce {
$action
if (result < 0) {
@@ -619,7 +551,6 @@
}
}
-
%exception security_reject_unknown {
$action
if (result < 0) {
@@ -628,7 +559,6 @@
}
}
-
%exception security_deny_unknown {
$action
if (result < 0) {
@@ -637,7 +567,6 @@
}
}
-
%exception security_get_checkreqprot {
$action
if (result < 0) {
@@ -646,7 +575,6 @@
}
}
-
%exception security_disable {
$action
if (result < 0) {
@@ -655,7 +583,6 @@
}
}
-
%exception security_policyvers {
$action
if (result < 0) {
@@ -664,7 +591,6 @@
}
}
-
%exception security_get_boolean_names {
$action
if (result < 0) {
@@ -673,7 +599,6 @@
}
}
-
%exception security_get_boolean_pending {
$action
if (result < 0) {
@@ -682,7 +607,6 @@
}
}
-
%exception security_get_boolean_active {
$action
if (result < 0) {
@@ -691,7 +615,6 @@
}
}
-
%exception security_set_boolean {
$action
if (result < 0) {
@@ -700,7 +623,6 @@
}
}
-
%exception security_commit_booleans {
$action
if (result < 0) {
@@ -709,7 +631,6 @@
}
}
-
%exception selinux_set_mapping {
$action
if (result < 0) {
@@ -718,7 +639,6 @@
}
}
-
%exception security_av_string {
$action
if (result < 0) {
@@ -727,7 +647,6 @@
}
}
-
%exception matchpathcon_init {
$action
if (result < 0) {
@@ -736,7 +655,6 @@
}
}
-
%exception matchpathcon_init_prefix {
$action
if (result < 0) {
@@ -745,7 +663,6 @@
}
}
-
%exception realpath_not_final {
$action
if (result < 0) {
@@ -754,7 +671,6 @@
}
}
-
%exception matchpathcon {
$action
if (result < 0) {
@@ -763,7 +679,6 @@
}
}
-
%exception matchpathcon_index {
$action
if (result < 0) {
@@ -772,7 +687,6 @@
}
}
-
%exception matchpathcon_filespec_add {
$action
if (result < 0) {
@@ -781,7 +695,6 @@
}
}
-
%exception matchmediacon {
$action
if (result < 0) {
@@ -790,7 +703,6 @@
}
}
-
%exception selinux_getenforcemode {
$action
if (result < 0) {
@@ -799,7 +711,6 @@
}
}
-
%exception selinux_getpolicytype {
$action
if (result < 0) {
@@ -808,7 +719,6 @@
}
}
-
%exception selinux_set_policy_root {
$action
if (result < 0) {
@@ -817,7 +727,6 @@
}
}
-
%exception selinux_check_access {
$action
if (result < 0) {
@@ -826,7 +735,6 @@
}
}
-
%exception selinux_check_passwd_access {
$action
if (result < 0) {
@@ -835,7 +743,6 @@
}
}
-
%exception checkPasswdAccess {
$action
if (result < 0) {
@@ -844,7 +751,6 @@
}
}
-
%exception selinux_check_securetty_context {
$action
if (result < 0) {
@@ -853,7 +759,6 @@
}
}
-
%exception selinuxfs_exists {
$action
if (result < 0) {
@@ -862,7 +767,6 @@
}
}
-
%exception setexecfilecon {
$action
if (result < 0) {
@@ -871,7 +775,6 @@
}
}
-
%exception rpm_execcon {
$action
if (result < 0) {
@@ -880,7 +783,6 @@
}
}
-
%exception is_context_customizable {
$action
if (result < 0) {
@@ -889,7 +791,6 @@
}
}
-
%exception selinux_trans_to_raw_context {
$action
if (result < 0) {
@@ -898,7 +799,6 @@
}
}
-
%exception selinux_raw_to_trans_context {
$action
if (result < 0) {
@@ -907,7 +807,6 @@
}
}
-
%exception selinux_raw_context_to_color {
$action
if (result < 0) {
@@ -916,7 +815,6 @@
}
}
-
%exception getseuserbyname {
$action
if (result < 0) {
@@ -925,7 +823,6 @@
}
}
-
%exception getseuser {
$action
if (result < 0) {
@@ -934,7 +831,6 @@
}
}
-
%exception selinux_file_context_verify {
$action
if (result < 0) {
@@ -943,7 +839,6 @@
}
}
-
%exception selinux_lsetfilecon_default {
$action
if (result < 0) {
@@ -952,3 +847,362 @@
}
}
+%exception avc_sid_to_context {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_sid_to_context_raw {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_context_to_sid {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_context_to_sid_raw {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception sidget {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception sidput {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_get_initial_sid {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_init {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_open {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_reset {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_has_perm_noaudit {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_has_perm {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_compute_create {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_compute_member {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_add_callback {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_netlink_open {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_netlink_acquire_fd {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception avc_netlink_check_nb {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_status_open {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_status_updated {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_status_getenforce {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_status_policyload {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_status_deny_unknown {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception context_type_set {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception context_range_set {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception context_role_set {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception context_user_set {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception get_ordered_context_list {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception get_ordered_context_list_with_level {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception get_default_context {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception get_default_context_with_level {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception get_default_context_with_role {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception get_default_context_with_rolelevel {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception query_user_context {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception manual_user_enter_context {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception get_default_type {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selabel_lookup {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selabel_lookup_raw {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selabel_lookup_best_match {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selabel_lookup_best_match_raw {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selabel_digest {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_restorecon {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_restorecon_parallel {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_restorecon_set_alt_rootpath {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
+
+%exception selinux_restorecon_xattr {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
diff --git a/libselinux/src/sestatus.c b/libselinux/src/sestatus.c
index ede5a289..89c1f621 100644
--- a/libselinux/src/sestatus.c
+++ b/libselinux/src/sestatus.c
@@ -37,13 +37,15 @@ struct selinux_status_t
* Valid Pointer : opened and mapped correctly
*/
static struct selinux_status_t *selinux_status = NULL;
-static int selinux_status_fd;
static uint32_t last_seqno;
+static uint32_t last_policyload;
static uint32_t fallback_sequence;
static int fallback_enforcing;
static int fallback_policyload;
+static void *fallback_netlink_thread = NULL;
+
/*
* read_sequence
*
@@ -88,7 +90,9 @@ static inline uint32_t read_sequence(struct selinux_status_t *status)
int selinux_status_updated(void)
{
uint32_t curr_seqno;
- int result = 0;
+ uint32_t tmp_seqno;
+ uint32_t enforcing;
+ uint32_t policyload;
if (selinux_status == NULL) {
errno = EINVAL;
@@ -114,12 +118,29 @@ int selinux_status_updated(void)
if (last_seqno & 0x0001)
last_seqno = curr_seqno;
- if (last_seqno != curr_seqno)
- {
- last_seqno = curr_seqno;
- result = 1;
+ if (last_seqno == curr_seqno)
+ return 0;
+
+ /* sequence must not be changed during references */
+ do {
+ enforcing = selinux_status->enforcing;
+ policyload = selinux_status->policyload;
+ tmp_seqno = curr_seqno;
+ curr_seqno = read_sequence(selinux_status);
+ } while (tmp_seqno != curr_seqno);
+
+ if (avc_enforcing != (int) enforcing) {
+ if (avc_process_setenforce(enforcing) < 0)
+ return -1;
+ }
+ if (last_policyload != policyload) {
+ if (avc_process_policyload(policyload) < 0)
+ return -1;
+ last_policyload = policyload;
}
- return result;
+ last_seqno = curr_seqno;
+
+ return 1;
}
/*
@@ -250,13 +271,20 @@ static int fallback_cb_policyload(int policyload)
* Since Linux 2.6.37 or later supports this feature, we may run
* fallback routine using a netlink socket on older kernels, if
* the supplied `fallback' is not zero.
- * It returns 0 on success, or -1 on error.
+ * It returns 0 on success, -1 on error or 1 when we are ready to
+ * use these interfaces, but netlink socket was opened as fallback
+ * instead of the kernel status page.
*/
int selinux_status_open(int fallback)
{
- int fd;
- char path[PATH_MAX];
- long pagesize;
+ int fd;
+ char path[PATH_MAX];
+ long pagesize;
+ uint32_t seqno;
+
+ if (selinux_status != NULL) {
+ return (selinux_status == MAP_FAILED) ? 1 : 0;
+ }
if (!selinux_mnt) {
errno = ENOENT;
@@ -273,13 +301,23 @@ int selinux_status_open(int fallback)
goto error;
selinux_status = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
+ close(fd);
if (selinux_status == MAP_FAILED) {
- close(fd);
goto error;
}
- selinux_status_fd = fd;
last_seqno = (uint32_t)(-1);
+ /* sequence must not be changed during references */
+ do {
+ seqno = read_sequence(selinux_status);
+
+ last_policyload = selinux_status->policyload;
+
+ } while (seqno != read_sequence(selinux_status));
+
+ /* No need to use avc threads if the kernel status page is available */
+ avc_using_threads = 0;
+
return 0;
error:
@@ -300,9 +338,14 @@ error:
/* mark as fallback mode */
selinux_status = MAP_FAILED;
- selinux_status_fd = avc_netlink_acquire_fd();
last_seqno = (uint32_t)(-1);
+ if (avc_using_threads)
+ {
+ fallback_netlink_thread = avc_create_thread(&avc_netlink_loop);
+ avc_netlink_trouble = 0;
+ }
+
fallback_sequence = 0;
fallback_enforcing = security_getenforce();
fallback_policyload = 0;
@@ -331,6 +374,9 @@ void selinux_status_close(void)
/* fallback-mode */
if (selinux_status == MAP_FAILED)
{
+ if (avc_using_threads)
+ avc_stop_thread(fallback_netlink_thread);
+
avc_netlink_release_fd();
avc_netlink_close();
selinux_status = NULL;
@@ -343,7 +389,5 @@ void selinux_status_close(void)
munmap(selinux_status, pagesize);
selinux_status = NULL;
- close(selinux_status_fd);
- selinux_status_fd = -1;
last_seqno = (uint32_t)(-1);
}
diff --git a/libselinux/src/setenforce.c b/libselinux/src/setenforce.c
index 09cad3ce..a87ff2d0 100644
--- a/libselinux/src/setenforce.c
+++ b/libselinux/src/setenforce.c
@@ -34,4 +34,3 @@ int security_setenforce(int value)
return 0;
}
-hidden_def(security_setenforce)
diff --git a/libselinux/src/setexecfilecon.c b/libselinux/src/setexecfilecon.c
index e72ba0d9..2c6505a9 100644
--- a/libselinux/src/setexecfilecon.c
+++ b/libselinux/src/setexecfilecon.c
@@ -37,7 +37,6 @@ int setexecfilecon(const char *filename, const char *fallback_type)
newcon = strdup(context_str(con));
if (!newcon)
goto out;
- rc = 0;
}
rc = setexeccon(newcon);
diff --git a/libselinux/src/setfilecon.c b/libselinux/src/setfilecon.c
index d05969c6..bd45f12c 100644
--- a/libselinux/src/setfilecon.c
+++ b/libselinux/src/setfilecon.c
@@ -25,7 +25,6 @@ int setfilecon_raw(const char *path, const char * context)
return rc;
}
-hidden_def(setfilecon_raw)
int setfilecon(const char *path, const char *context)
{
diff --git a/libselinux/src/setrans_client.c b/libselinux/src/setrans_client.c
index fa188a82..faa12681 100644
--- a/libselinux/src/setrans_client.c
+++ b/libselinux/src/setrans_client.c
@@ -19,7 +19,6 @@
#include <ctype.h>
#include <unistd.h>
#include <sys/uio.h>
-#include "dso.h"
#include "selinux_internal.h"
#include "setrans_internal.h"
@@ -260,7 +259,7 @@ static void setrans_thread_destructor(void __attribute__((unused)) *unused)
void __attribute__((destructor)) setrans_lib_destructor(void);
-void hidden __attribute__((destructor)) setrans_lib_destructor(void)
+void __attribute__((destructor)) setrans_lib_destructor(void)
{
if (!has_setrans)
return;
@@ -273,7 +272,7 @@ static inline void init_thread_destructor(void)
if (!has_setrans)
return;
if (destructor_initialized == 0) {
- __selinux_setspecific(destructor_key, (void *)1);
+ __selinux_setspecific(destructor_key, /* some valid address to please GCC */ &selinux_page_size);
destructor_initialized = 1;
}
}
@@ -327,7 +326,6 @@ int selinux_trans_to_raw_context(const char * trans,
return *rawp ? 0 : -1;
}
-hidden_def(selinux_trans_to_raw_context)
int selinux_raw_to_trans_context(const char * raw,
char ** transp)
@@ -369,7 +367,6 @@ int selinux_raw_to_trans_context(const char * raw,
return *transp ? 0 : -1;
}
-hidden_def(selinux_raw_to_trans_context)
int selinux_raw_context_to_color(const char * raw, char **transp)
{
@@ -410,7 +407,6 @@ int selinux_raw_context_to_color(const char * raw, char **transp)
return *transp ? 0 : -1;
}
-hidden_def(selinux_raw_context_to_color)
#else /*DISABLE_SETRANS*/
int selinux_trans_to_raw_context(const char * trans,
@@ -426,7 +422,6 @@ int selinux_trans_to_raw_context(const char * trans,
return *rawp ? 0 : -1;
}
-hidden_def(selinux_trans_to_raw_context)
int selinux_raw_to_trans_context(const char * raw,
char ** transp)
@@ -440,5 +435,4 @@ int selinux_raw_to_trans_context(const char * raw,
return *transp ? 0 : -1;
}
-hidden_def(selinux_raw_to_trans_context)
#endif /*DISABLE_SETRANS*/
diff --git a/libselinux/src/setup.py b/libselinux/src/setup.py
index c8270bdc..b79b2750 100644
--- a/libselinux/src/setup.py
+++ b/libselinux/src/setup.py
@@ -4,7 +4,7 @@ from distutils.core import Extension, setup
setup(
name="selinux",
- version="3.0",
+ version="3.3",
description="SELinux python 3 bindings",
author="SELinux Project",
author_email="selinux@vger.kernel.org",
diff --git a/libselinux/src/seusers.c b/libselinux/src/seusers.c
index 7ec7d12c..fff80c1a 100644
--- a/libselinux/src/seusers.c
+++ b/libselinux/src/seusers.c
@@ -88,7 +88,7 @@ static int process_seusers(const char *buffer,
return -2; /* error */
}
-int require_seusers hidden = 0;
+int require_seusers = 0;
#include <pwd.h>
#include <grp.h>
diff --git a/libselinux/src/sha1.c b/libselinux/src/sha1.c
index 004fcd3b..a8484677 100644
--- a/libselinux/src/sha1.c
+++ b/libselinux/src/sha1.c
@@ -16,6 +16,7 @@
// sha1.c:73:33: error: cast from 'uint8_t *' (aka 'unsigned char *') to 'CHAR64LONG16 *' increases required alignment from 1 to 4 [-Werror,-Wcast-align]
// CHAR64LONG16* block = (CHAR64LONG16*) workspace;
// William Roberts <william.c.roberts@intel.com>
+// - Silence clang's -Wextra-semi-stmt warning - July 2021, Nicolas Iooss <nicolas.iooss@m4x.org>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -23,7 +24,6 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "sha1.h"
-#include "dso.h"
#include <memory.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -50,11 +50,11 @@ typedef union
^block->l[(i+2)&15]^block->l[i&15],1))
// (R0+R1), R2, R3, R4 are the different operations used in SHA1
-#define R0(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30);
-#define R1(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30);
-#define R2(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30);
-#define R3(v,w,x,y,z,i) z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30);
-#define R4(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30);
+#define R0(v,w,x,y,z,i) do { z += ((w&(x^y))^y) + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30); } while (0)
+#define R1(v,w,x,y,z,i) do { z += ((w&(x^y))^y) + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30); } while (0)
+#define R2(v,w,x,y,z,i) do { z += (w^x^y) + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30); } while (0)
+#define R3(v,w,x,y,z,i) do { z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30); } while (0)
+#define R4(v,w,x,y,z,i) do { z += (w^x^y) + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30); } while (0)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -126,7 +126,7 @@ void
//
// Initialises an SHA1 Context. Use this to initialise/reset a context.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void hidden
+void
Sha1Initialise
(
Sha1Context* Context
@@ -148,11 +148,11 @@ void hidden
// Adds data to the SHA1 context. This will process the data and update the internal state of the context. Keep on
// calling this function until all the data has been added. Then call Sha1Finalise to calculate the hash.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void hidden
+void
Sha1Update
(
Sha1Context* Context,
- void* Buffer,
+ const void* Buffer,
uint32_t BufferSize
)
{
@@ -173,7 +173,7 @@ void hidden
TransformFunction(Context->State, Context->Buffer);
for (; i + 63 < BufferSize; i += 64)
{
- TransformFunction(Context->State, (uint8_t*)Buffer + i);
+ TransformFunction(Context->State, (const uint8_t*)Buffer + i);
}
j = 0;
}
@@ -182,7 +182,7 @@ void hidden
i = 0;
}
- memcpy(&Context->Buffer[j], &((uint8_t*)Buffer)[i], BufferSize - i);
+ memcpy(&Context->Buffer[j], &((const uint8_t*)Buffer)[i], BufferSize - i);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -191,7 +191,7 @@ void hidden
// Performs the final calculation of the hash and returns the digest (20 byte buffer containing 160bit hash). After
// calling this, Sha1Initialised must be used to reuse the context.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void hidden
+void
Sha1Finalise
(
Sha1Context* Context,
@@ -206,10 +206,10 @@ void hidden
finalcount[i] = (unsigned char)((Context->Count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); // Endian independent
}
- Sha1Update(Context, (uint8_t*)"\x80", 1);
+ Sha1Update(Context, (const uint8_t*)"\x80", 1);
while ((Context->Count[0] & 504) != 448)
{
- Sha1Update(Context, (uint8_t*)"\0", 1);
+ Sha1Update(Context, (const uint8_t*)"\0", 1);
}
Sha1Update(Context, finalcount, 8); // Should cause a Sha1TransformFunction()
diff --git a/libselinux/src/sha1.h b/libselinux/src/sha1.h
index eac3c195..f83a6e7e 100644
--- a/libselinux/src/sha1.h
+++ b/libselinux/src/sha1.h
@@ -64,7 +64,7 @@ void
Sha1Update
(
Sha1Context* Context,
- void* Buffer,
+ const void* Buffer,
uint32_t BufferSize
);
diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c
index 29757b75..2fe69f43 100644
--- a/libselinux/src/stringrep.c
+++ b/libselinux/src/stringrep.c
@@ -180,7 +180,6 @@ void selinux_flush_class_cache(void)
discover_class_cache = NULL;
}
-hidden_def(selinux_flush_class_cache)
security_class_t string_to_security_class(const char *s)
{
@@ -230,7 +229,7 @@ access_vector_t string_to_av_perm(security_class_t tclass, const char *s)
size_t i;
for (i = 0; i < MAXVECTORS && node->perms[i] != NULL; i++)
if (strcmp(node->perms[i],s) == 0)
- return map_perm(tclass, 1<<i);
+ return map_perm(tclass, UINT32_C(1)<<i);
}
errno = EINVAL;
@@ -262,7 +261,7 @@ const char *security_av_perm_to_string(security_class_t tclass,
node = get_class_cache_entry_value(tclass);
if (av && node)
for (i = 0; i<MAXVECTORS; i++)
- if ((1<<i) & av)
+ if ((UINT32_C(1)<<i) & av)
return node->perms[i];
return NULL;
@@ -280,7 +279,7 @@ int security_av_string(security_class_t tclass, access_vector_t av, char **res)
/* first pass computes the required length */
for (i = 0; tmp; tmp >>= 1, i++) {
if (tmp & 1) {
- str = security_av_perm_to_string(tclass, av & (1<<i));
+ str = security_av_perm_to_string(tclass, av & (UINT32_C(1)<<i));
if (str)
len += strlen(str) + 1;
}
@@ -304,7 +303,7 @@ int security_av_string(security_class_t tclass, access_vector_t av, char **res)
ptr += sprintf(ptr, "{ ");
for (i = 0; tmp; tmp >>= 1, i++) {
if (tmp & 1) {
- str = security_av_perm_to_string(tclass, av & (1<<i));
+ str = security_av_perm_to_string(tclass, av & (UINT32_C(1)<<i));
if (str)
ptr += sprintf(ptr, "%s ", str);
}
diff --git a/libselinux/src/validatetrans.c b/libselinux/src/validatetrans.c
index 2aa300cf..66ac7405 100644
--- a/libselinux/src/validatetrans.c
+++ b/libselinux/src/validatetrans.c
@@ -57,7 +57,6 @@ out:
return ret;
}
-hidden_def(security_validatetrans_raw)
int security_validatetrans(const char *scon,
const char *tcon,
@@ -91,4 +90,3 @@ out:
return ret;
}
-hidden_def(security_validatetrans)
diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile
index 36150638..801066cb 100644
--- a/libselinux/utils/Makefile
+++ b/libselinux/utils/Makefile
@@ -36,8 +36,6 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi
-Werror -Wno-aggregate-return -Wno-redundant-decls -Wstrict-overflow=5 \
$(EXTRA_CFLAGS)
-LD_SONAME_FLAGS=-soname,$(LIBSO),-z,defs,-z,relro
-
ifeq ($(OS), Darwin)
override CFLAGS += -I/opt/local/include -I../../libsepol/include
override LDFLAGS += -L../../libsepol/src -undefined dynamic_lookup
@@ -45,8 +43,7 @@ endif
override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS)
override LDFLAGS += -L../src
-override LDLIBS += -lselinux
-PCRE_LDLIBS ?= -lpcre
+override LDLIBS += -lselinux $(FTS_LDLIBS)
ifeq ($(ANDROID_HOST),y)
TARGETS=sefcontext_compile
@@ -54,9 +51,7 @@ else
TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c)))
endif
-sefcontext_compile: LDLIBS += $(PCRE_LDLIBS) ../src/libselinux.a -lsepol
-
-sefcontext_compile: sefcontext_compile.o ../src/regex.o
+sefcontext_compile: LDLIBS += ../src/libselinux.a $(PCRE_LDLIBS) -lsepol
all: $(TARGETS)
diff --git a/libselinux/utils/avcstat.c b/libselinux/utils/avcstat.c
index da239287..cc9a48dd 100644
--- a/libselinux/utils/avcstat.c
+++ b/libselinux/utils/avcstat.c
@@ -205,7 +205,7 @@ int main(int argc, char **argv)
die("unable to parse \'%s\': no data", avcstatfile);
if (cumulative || !i)
- printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n",
+ printf("%10llu %10llu %10llu %10llu %10llu %10llu\n",
tot.lookups, tot.hits, tot.misses,
tot.allocations, tot.reclaims, tot.frees);
else {
@@ -215,7 +215,7 @@ int main(int argc, char **argv)
rel.allocations = tot.allocations - last.allocations;
rel.reclaims = tot.reclaims - last.reclaims;
rel.frees = tot.frees - last.frees;
- printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n",
+ printf("%10llu %10llu %10llu %10llu %10llu %10llu\n",
rel.lookups, rel.hits, rel.misses,
rel.allocations, rel.reclaims, rel.frees);
}
diff --git a/libselinux/utils/compute_user.c b/libselinux/utils/compute_user.c
deleted file mode 100644
index 86d00a6e..00000000
--- a/libselinux/utils/compute_user.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <ctype.h>
-#include <selinux/selinux.h>
-
-int main(int argc, char **argv)
-{
- char **buf, **ptr;
- int ret;
-
- if (argc != 3) {
- fprintf(stderr, "usage: %s context user\n", argv[0]);
- exit(1);
- }
-
- ret = security_compute_user(argv[1], argv[2], &buf);
- if (ret < 0) {
- fprintf(stderr, "%s: security_compute_user(%s,%s) failed\n",
- argv[0], argv[1], argv[2]);
- exit(2);
- }
-
- if (!buf[0]) {
- printf("none\n");
- exit(EXIT_SUCCESS);
- }
-
- for (ptr = buf; *ptr; ptr++) {
- printf("%s\n", *ptr);
- }
- freeconary(buf);
- exit(EXIT_SUCCESS);
-}
diff --git a/libselinux/utils/getconlist.c b/libselinux/utils/getconlist.c
index 29c16640..0bb28469 100644
--- a/libselinux/utils/getconlist.c
+++ b/libselinux/utils/getconlist.c
@@ -26,6 +26,7 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "l:")) > 0) {
switch (opt) {
case 'l':
+ free(level);
level = strdup(optarg);
if (!level) {
fprintf(stderr, "memory allocation failure: %d(%s)\n",
@@ -58,8 +59,14 @@ int main(int argc, char **argv)
free(level);
return 2;
}
- } else
+ } else {
cur_context = argv[optind + 1];
+ if (security_check_context(cur_context) != 0) {
+ fprintf(stderr, "Given context '%s' is invalid.\n", cur_context);
+ free(level);
+ return 3;
+ }
+ }
/* Get the list and print it */
if (level)
@@ -72,6 +79,11 @@ int main(int argc, char **argv)
for (i = 0; list[i]; i++)
puts(list[i]);
freeconary(list);
+ } else {
+ fprintf(stderr, "get_ordered_context_list%s failure: %d(%s)\n",
+ level ? "_with_level" : "", errno, strerror(errno));
+ free(level);
+ return 4;
}
free(level);
diff --git a/libselinux/utils/getdefaultcon.c b/libselinux/utils/getdefaultcon.c
index 96a5a8c2..957c1cb2 100644
--- a/libselinux/utils/getdefaultcon.c
+++ b/libselinux/utils/getdefaultcon.c
@@ -28,12 +28,15 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "l:r:s:v")) > 0) {
switch (opt) {
case 'l':
+ free(level);
level = strdup(optarg);
break;
case 'r':
+ free(role);
role = strdup(optarg);
break;
case 's':
+ free(service);
service = strdup(optarg);
break;
case 'v':
diff --git a/libselinux/utils/getseuser.c b/libselinux/utils/getseuser.c
index 9193fe0a..34f2e887 100644
--- a/libselinux/utils/getseuser.c
+++ b/libselinux/utils/getseuser.c
@@ -13,28 +13,47 @@ int main(int argc, char **argv)
if (argc != 3) {
fprintf(stderr, "usage: %s linuxuser fromcon\n", argv[0]);
- exit(1);
+ return 1;
+ }
+
+ if (!is_selinux_enabled()) {
+ fprintf(stderr, "%s may be used only on a SELinux enabled kernel.\n", argv[0]);
+ return 4;
}
rc = getseuserbyname(argv[1], &seuser, &level);
if (rc) {
- fprintf(stderr, "getseuserbyname failed: %s\n",
- strerror(errno));
- exit(2);
+ fprintf(stderr, "getseuserbyname failed: %s\n", strerror(errno));
+ return 2;
}
printf("seuser: %s, level %s\n", seuser, level);
- n = get_ordered_context_list_with_level(seuser, level, argv[2],
- &contextlist);
- if (n <= 0) {
- fprintf(stderr,
- "get_ordered_context_list_with_level failed: %s\n",
- strerror(errno));
- exit(3);
+
+ rc = security_check_context(argv[2]);
+ if (rc) {
+ fprintf(stderr, "context '%s' is invalid\n", argv[2]);
+ free(seuser);
+ free(level);
+ return 5;
+ }
+
+ n = get_ordered_context_list_with_level(seuser, level, argv[2], &contextlist);
+ if (n < 0) {
+ fprintf(stderr, "get_ordered_context_list_with_level failed: %s\n", strerror(errno));
+ free(seuser);
+ free(level);
+ return 3;
}
+
free(seuser);
free(level);
+
+ if (n == 0)
+ printf("no valid context found\n");
+
for (i = 0; i < n; i++)
printf("Context %d\t%s\n", i, contextlist[i]);
+
freeconary(contextlist);
- exit(EXIT_SUCCESS);
+
+ return EXIT_SUCCESS;
}
diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c
index eb39a188..1d713c01 100644
--- a/libselinux/utils/matchpathcon.c
+++ b/libselinux/utils/matchpathcon.c
@@ -1,15 +1,14 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
#include <errno.h>
-#include <string.h>
+#include <getopt.h>
#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <selinux/label.h>
#include <selinux/selinux.h>
-#include <limits.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
static __attribute__ ((__noreturn__)) void usage(const char *progname)
{
@@ -19,15 +18,21 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname)
exit(1);
}
-static int printmatchpathcon(const char *path, int header, int mode)
+static int printmatchpathcon(struct selabel_handle *hnd, const char *path, int header, int mode, int notrans)
{
- char *buf;
- int rc = matchpathcon(path, mode, &buf);
+ char *buf = NULL;
+ int rc;
+
+ if (notrans) {
+ rc = selabel_lookup_raw(hnd, &buf, path, mode);
+ } else {
+ rc = selabel_lookup(hnd, &buf, path, mode);
+ }
if (rc < 0) {
if (errno == ENOENT) {
buf = strdup("<<none>>");
} else {
- fprintf(stderr, "matchpathcon(%s) failed: %s\n", path,
+ fprintf(stderr, "selabel_lookup(%s) failed: %s\n", path,
strerror(errno));
return 1;
}
@@ -60,18 +65,20 @@ static mode_t string_to_mode(char *s)
return S_IFREG;
default:
return -1;
- };
+ }
return -1;
}
int main(int argc, char **argv)
{
- int i, init = 0, force_mode = 0;
+ int i, force_mode = 0;
int header = 1, opt;
int verify = 0;
int notrans = 0;
int error = 0;
int quiet = 0;
+ struct selabel_handle *hnd;
+ struct selinux_opt options[SELABEL_NOPT] = {};
if (argc < 2)
usage(argv[0]);
@@ -93,23 +100,10 @@ int main(int argc, char **argv)
break;
case 'N':
notrans = 1;
- set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
break;
case 'f':
- if (init) {
- fprintf(stderr,
- "%s: -f and -p are exclusive\n",
- argv[0]);
- exit(1);
- }
- init = 1;
- if (matchpathcon_init(optarg)) {
- fprintf(stderr,
- "Error while processing %s: %s\n",
- optarg,
- errno ? strerror(errno) : "invalid");
- exit(1);
- }
+ options[SELABEL_OPT_PATH].type = SELABEL_OPT_PATH;
+ options[SELABEL_OPT_PATH].value = optarg;
break;
case 'P':
if (selinux_set_policy_root(optarg) < 0 ) {
@@ -121,20 +115,11 @@ int main(int argc, char **argv)
}
break;
case 'p':
- if (init) {
- fprintf(stderr,
- "%s: -f and -p are exclusive\n",
- argv[0]);
- exit(1);
- }
- init = 1;
- if (matchpathcon_init_prefix(NULL, optarg)) {
- fprintf(stderr,
- "Error while processing %s: %s\n",
- optarg,
- errno ? strerror(errno) : "invalid");
- exit(1);
- }
+ // This option has been deprecated since libselinux 2.5 (2016):
+ // https://github.com/SELinuxProject/selinux/commit/26e05da0fc2d0a4bd274320968a88f8acbb3b6a6
+ fprintf(stderr, "Warning: using %s -p is deprecated\n", argv[0]);
+ options[SELABEL_OPT_SUBSET].type = SELABEL_OPT_SUBSET;
+ options[SELABEL_OPT_SUBSET].value = optarg;
break;
case 'q':
quiet = 1;
@@ -143,6 +128,13 @@ int main(int argc, char **argv)
usage(argv[0]);
}
}
+ hnd = selabel_open(SELABEL_CTX_FILE, options, SELABEL_NOPT);
+ if (!hnd) {
+ fprintf(stderr,
+ "Error while opening file contexts database: %s\n",
+ strerror(errno));
+ return -1;
+ }
for (i = optind; i < argc; i++) {
int rc, mode = 0;
struct stat buf;
@@ -182,19 +174,19 @@ int main(int argc, char **argv)
if (rc >= 0) {
printf("%s has context %s, should be ",
path, con);
- printmatchpathcon(path, 0, mode);
+ printmatchpathcon(hnd, path, 0, mode, notrans);
freecon(con);
} else {
printf
("actual context unknown: %s, should be ",
strerror(errno));
- printmatchpathcon(path, 0, mode);
+ printmatchpathcon(hnd, path, 0, mode, notrans);
}
}
} else {
- error |= printmatchpathcon(path, header, mode);
+ error |= printmatchpathcon(hnd, path, header, mode, notrans);
}
}
- matchpathcon_fini();
+ selabel_close(hnd);
return error;
}
diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c
index dcb0085a..6c32172d 100644
--- a/libselinux/utils/sefcontext_compile.c
+++ b/libselinux/utils/sefcontext_compile.c
@@ -14,7 +14,7 @@
#include "../src/label_file.h"
#include "../src/regex.h"
-const char *policy_file;
+static const char *policy_file;
static int ctx_err;
static int validate_context(char **ctxp)
diff --git a/libselinux/utils/selabel_get_digests_all_partial_matches.c b/libselinux/utils/selabel_get_digests_all_partial_matches.c
index 0c2edc67..e28833d2 100644
--- a/libselinux/utils/selabel_get_digests_all_partial_matches.c
+++ b/libselinux/utils/selabel_get_digests_all_partial_matches.c
@@ -128,7 +128,7 @@ int main(int argc, char **argv)
printf("No SHA1 digest available for: %s\n",
ftsent->fts_path);
printf("as file_context entry is \"<<none>>\"\n");
- break;
+ goto cleanup;
}
printf("The file_context entries for: %s\n",
@@ -149,11 +149,11 @@ int main(int argc, char **argv)
xattr_digest[i]);
printf("%s\n", sha1_buf);
}
-
- free(xattr_digest);
- free(calculated_digest);
- free(sha1_buf);
}
+ cleanup:
+ free(xattr_digest);
+ free(calculated_digest);
+ free(sha1_buf);
break;
}
default:
diff --git a/libselinux/utils/selabel_lookup_best_match.c b/libselinux/utils/selabel_lookup_best_match.c
index 6a717423..2cddc6cd 100644
--- a/libselinux/utils/selabel_lookup_best_match.c
+++ b/libselinux/utils/selabel_lookup_best_match.c
@@ -47,7 +47,7 @@ static mode_t string_to_mode(char *s)
return S_IFSOCK;
case 'f':
return S_IFREG;
- };
+ }
return 0;
}
diff --git a/libsemanage/VERSION b/libsemanage/VERSION
index 9f55b2cc..eb39e538 100644
--- a/libsemanage/VERSION
+++ b/libsemanage/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/libsemanage/include/semanage/handle.h b/libsemanage/include/semanage/handle.h
index 946d69bc..0157be4f 100644
--- a/libsemanage/include/semanage/handle.h
+++ b/libsemanage/include/semanage/handle.h
@@ -66,6 +66,11 @@ extern void semanage_set_reload(semanage_handle_t * handle, int do_reload);
* 1 for yes, 0 for no (default) */
extern void semanage_set_rebuild(semanage_handle_t * handle, int do_rebuild);
+/* set whether to rebuild the policy on commit when potential changes
+ * to module files since last rebuild are detected,
+ * 1 for yes (default), 0 for no */
+extern void semanage_set_check_ext_changes(semanage_handle_t * handle, int do_check);
+
/* Fills *compiler_path with the location of the hll compiler sh->conf->compiler_directory_path
* corresponding to lang_ext.
* Upon success returns 0, -1 on error. */
diff --git a/libsemanage/include/semanage/modules.h b/libsemanage/include/semanage/modules.h
index ac403931..14666f6d 100644
--- a/libsemanage/include/semanage/modules.h
+++ b/libsemanage/include/semanage/modules.h
@@ -33,7 +33,7 @@ typedef struct semanage_module_key semanage_module_key_t;
*/
extern int semanage_module_install(semanage_handle_t *,
- char *module_data, size_t data_len, char *name, char *ext_lang);
+ char *module_data, size_t data_len, const char *name, const char *ext_lang);
extern int semanage_module_install_file(semanage_handle_t *,
const char *module_name);
extern int semanage_module_remove(semanage_handle_t *, char *module_name);
@@ -282,4 +282,30 @@ extern int semanage_module_get_enabled(semanage_handle_t *sh,
const semanage_module_key_t *modkey,
int *enabled);
+/* Compute checksum for @modkey module contents.
+ *
+ * If @checksum is NULL, the function will just return the length of the
+ * checksum string in @checksum_len (checksum strings are guaranteed to
+ * have a fixed length for a given libsemanage binary). @modkey and @cil
+ * are ignored in this case and should be set to NULL and 0 (respectively).
+ *
+ * If @checksum is non-NULL, on success, @checksum will point to a buffer
+ * containing the checksum string and @checksum_len will point to the
+ * length of the string (without the null terminator). The semantics of
+ * @cil are the same as for @extract_cil in semanage_module_extract().
+ *
+ * The caller is responsible to free the buffer returned in @checksum (using
+ * free(3)).
+ *
+ * Callers may assume that if the checksum strings for two modules match,
+ * the module content is the same (collisions are theoretically possible,
+ * yet extremely unlikely).
+ *
+ * Returns 0 on success and -1 on error.
+ */
+extern int semanage_module_compute_checksum(semanage_handle_t *sh,
+ semanage_module_key_t *modkey,
+ int cil, char **checksum,
+ size_t *checksum_len);
+
#endif
diff --git a/libsemanage/man/man5/semanage.conf.5 b/libsemanage/man/man5/semanage.conf.5
index 8efc7dd5..380b58be 100644
--- a/libsemanage/man/man5/semanage.conf.5
+++ b/libsemanage/man/man5/semanage.conf.5
@@ -23,7 +23,7 @@ Management library writes to the SELinux policy module store directly (this is t
Otherwise a socket path or a server name can be used for the argument.
If the argument begins with "/" (as in "/foo/bar"), it represents the path to a named socket that should be used to connect the policy management
server.
-If the argument does not begin with a "/" (as in "foo.com:4242"), it should be interpreted as the name of a remote policy management server
+If the argument does not begin with a "/" (as in "example.com:4242"), it should be interpreted as the name of a remote policy management server
to be used through a TCP connection (default port is 4242 unless a different one is specified after the server name using the colon to separate
the two fields).
@@ -95,8 +95,8 @@ to this option set to "false").
.TP
.B handle-unknown
-This option controls the kernel behavior for handling permissions defined in the kernel but missing from the actual policy.
-It can be set to "deny", "reject" or "allow".
+This option overrides the kernel behavior for handling permissions defined in the kernel but missing from the actual policy.
+It can be set to "deny", "reject" or "allow". By default the setting from the policy is taken.
.TP
.B bzip-blocksize
diff --git a/libsemanage/man/ru/man5/semanage.conf.5 b/libsemanage/man/ru/man5/semanage.conf.5
index cf65b3e6..548aa58d 100644
--- a/libsemanage/man/ru/man5/semanage.conf.5
+++ b/libsemanage/man/ru/man5/semanage.conf.5
@@ -19,7 +19,7 @@ semanage.conf \- глобальный файл конфигурации Ð´Ð»Ñ Ð
Указать, как библиотека ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ SELinux должна взаимодейÑтвовать Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰ÐµÐ¼ политики SELinux. ЕÑли уÑтановлено "direct", библиотека ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ SELinux выполнÑет запиÑÑŒ напрÑмую в хранилище модулей политики SELinux (Ñто значение по умолчанию).
Ð’ ином Ñлучае в качеÑтве аргумента может иÑпользоватьÑÑ Ð¿ÑƒÑ‚ÑŒ к Ñокету или Ð¸Ð¼Ñ Ñервера.
ЕÑли аргумент начинаетÑÑ Ñ "/" (как в "/foo/bar"), он предÑтавлÑет Ñобой путь к именованному Ñокету, который Ñледует иÑпользовать Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñервера ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñ‚Ð¸ÐºÐ¾Ð¹.
-ЕÑли аргумент не начинаетÑÑ Ñ "/" (как в "foo.com:4242"), он должен интерпретироватьÑÑ ÐºÐ°Ðº Ð¸Ð¼Ñ ÑƒÐ´Ð°Ð»Ñ‘Ð½Ð½Ð¾Ð³Ð¾ Ñервера ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñ‚Ð¸ÐºÐ¾Ð¹, который Ñледует иÑпользовать через TCP-подключение (порт по умолчанию 4242, еÑли только поÑле имени Ñервера через двоеточие, разделÑющее два полÑ, не указан другой порт).
+ЕÑли аргумент не начинаетÑÑ Ñ "/" (как в "example.com:4242"), он должен интерпретироватьÑÑ ÐºÐ°Ðº Ð¸Ð¼Ñ ÑƒÐ´Ð°Ð»Ñ‘Ð½Ð½Ð¾Ð³Ð¾ Ñервера ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ñ‚Ð¸ÐºÐ¾Ð¹, который Ñледует иÑпользовать через TCP-подключение (порт по умолчанию 4242, еÑли только поÑле имени Ñервера через двоеточие, разделÑющее два полÑ, не указан другой порт).
.TP
.B root
diff --git a/libsemanage/src/Makefile b/libsemanage/src/Makefile
index f6780dc6..ab6cae51 100644
--- a/libsemanage/src/Makefile
+++ b/libsemanage/src/Makefile
@@ -14,7 +14,7 @@ INCLUDEDIR ?= $(PREFIX)/include
PYINC ?= $(shell $(PKG_CONFIG) --cflags $(PYPREFIX))
PYLIBS ?= $(shell $(PKG_CONFIG) --libs $(PYPREFIX))
PYTHONLIBDIR ?= $(shell $(PYTHON) -c "from distutils.sysconfig import *; print(get_python_lib(plat_specific=1, prefix='$(PREFIX)'))")
-PYCEXT ?= $(shell $(PYTHON) -c 'import imp;print([s for s,m,t in imp.get_suffixes() if t == imp.C_EXTENSION][0])')
+PYCEXT ?= $(shell $(PYTHON) -c 'import importlib.machinery;print(importlib.machinery.EXTENSION_SUFFIXES[0])')
RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]')
RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]')
RUBYINSTALL ?= $(shell $(RUBY) -e 'puts RbConfig::CONFIG["vendorarchdir"]')
@@ -32,7 +32,7 @@ YACC = bison
YFLAGS = -d
VERSION = $(shell cat ../VERSION)
-LIBVERSION = 1
+LIBVERSION = 2
LIBA=libsemanage.a
TARGET=libsemanage.so
@@ -53,7 +53,8 @@ SRCS= $(filter-out $(GENERATED),$(sort $(wildcard *.c)))
OBJS= $(patsubst %.c,%.o,$(SRCS)) conf-scan.o conf-parse.o
LOBJS= $(patsubst %.c,%.lo,$(SRCS)) conf-scan.lo conf-parse.lo
-CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-noreturn -Wmissing-format-attribute
+CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-noreturn -Wmissing-format-attribute \
+ -fno-semantic-interposition
SWIG_CFLAGS += -Wno-error -Wno-unused-but-set-variable -Wno-unused-variable -Wno-shadow \
-Wno-unused-parameter
diff --git a/libsemanage/src/boolean_internal.h b/libsemanage/src/boolean_internal.h
index dc23c273..8d1c20dc 100644
--- a/libsemanage/src/boolean_internal.h
+++ b/libsemanage/src/boolean_internal.h
@@ -7,19 +7,6 @@
#include <semanage/booleans_active.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_bool_clone)
- hidden_proto(semanage_bool_compare)
- hidden_proto(semanage_bool_compare2)
- hidden_proto(semanage_bool_create)
- hidden_proto(semanage_bool_free)
- hidden_proto(semanage_bool_get_name)
- hidden_proto(semanage_bool_get_value)
- hidden_proto(semanage_bool_key_extract)
- hidden_proto(semanage_bool_key_free)
- hidden_proto(semanage_bool_set_name)
- hidden_proto(semanage_bool_set_value)
/* BOOL RECORD: method table */
extern record_table_t SEMANAGE_BOOL_RTABLE;
diff --git a/libsemanage/src/boolean_record.c b/libsemanage/src/boolean_record.c
index c234094e..40dc6545 100644
--- a/libsemanage/src/boolean_record.c
+++ b/libsemanage/src/boolean_record.c
@@ -7,8 +7,10 @@
*/
#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
#include <sepol/boolean_record.h>
-#include "handle_internal.h"
typedef sepol_bool_t semanage_bool_t;
typedef sepol_bool_key_t semanage_bool_key_t;
@@ -21,7 +23,6 @@ typedef semanage_bool_key_t record_key_t;
#include "boolean_internal.h"
#include "handle.h"
#include "database.h"
-#include <stdlib.h>
#include <selinux/selinux.h>
/* Key */
@@ -40,14 +41,12 @@ int semanage_bool_key_extract(semanage_handle_t * handle,
return sepol_bool_key_extract(handle->sepolh, boolean, key);
}
-hidden_def(semanage_bool_key_extract)
void semanage_bool_key_free(semanage_bool_key_t * key)
{
sepol_bool_key_free(key);
}
-hidden_def(semanage_bool_key_free)
int semanage_bool_compare(const semanage_bool_t * boolean,
const semanage_bool_key_t * key)
@@ -56,7 +55,6 @@ int semanage_bool_compare(const semanage_bool_t * boolean,
return sepol_bool_compare(boolean, key);
}
-hidden_def(semanage_bool_compare)
int semanage_bool_compare2(const semanage_bool_t * boolean,
const semanage_bool_t * boolean2)
@@ -65,7 +63,6 @@ int semanage_bool_compare2(const semanage_bool_t * boolean,
return sepol_bool_compare2(boolean, boolean2);
}
-hidden_def(semanage_bool_compare2)
static int semanage_bool_compare2_qsort(const semanage_bool_t ** boolean,
const semanage_bool_t ** boolean2)
@@ -81,7 +78,6 @@ const char *semanage_bool_get_name(const semanage_bool_t * boolean)
return sepol_bool_get_name(boolean);
}
-hidden_def(semanage_bool_get_name)
int semanage_bool_set_name(semanage_handle_t * handle,
semanage_bool_t * boolean, const char *name)
@@ -141,7 +137,6 @@ out:
return rc;
}
-hidden_def(semanage_bool_set_name)
/* Value */
int semanage_bool_get_value(const semanage_bool_t * boolean)
@@ -150,7 +145,6 @@ int semanage_bool_get_value(const semanage_bool_t * boolean)
return sepol_bool_get_value(boolean);
}
-hidden_def(semanage_bool_get_value)
void semanage_bool_set_value(semanage_bool_t * boolean, int value)
{
@@ -158,7 +152,6 @@ void semanage_bool_set_value(semanage_bool_t * boolean, int value)
sepol_bool_set_value(boolean, value);
}
-hidden_def(semanage_bool_set_value)
/* Create/Clone/Destroy */
int semanage_bool_create(semanage_handle_t * handle,
@@ -168,7 +161,6 @@ int semanage_bool_create(semanage_handle_t * handle,
return sepol_bool_create(handle->sepolh, bool_ptr);
}
-hidden_def(semanage_bool_create)
int semanage_bool_clone(semanage_handle_t * handle,
const semanage_bool_t * boolean,
@@ -178,7 +170,6 @@ int semanage_bool_clone(semanage_handle_t * handle,
return sepol_bool_clone(handle->sepolh, boolean, bool_ptr);
}
-hidden_def(semanage_bool_clone)
void semanage_bool_free(semanage_bool_t * boolean)
{
@@ -186,7 +177,6 @@ void semanage_bool_free(semanage_bool_t * boolean)
sepol_bool_free(boolean);
}
-hidden_def(semanage_bool_free)
/* Record base functions */
record_table_t SEMANAGE_BOOL_RTABLE = {
diff --git a/libsemanage/src/booleans_file.c b/libsemanage/src/booleans_file.c
index f79d0b44..6d600bbc 100644
--- a/libsemanage/src/booleans_file.c
+++ b/libsemanage/src/booleans_file.c
@@ -48,7 +48,7 @@ static int bool_parse(semanage_handle_t * handle,
goto last;
/* Extract name */
- if (parse_fetch_string(handle, info, &str, '=') < 0)
+ if (parse_fetch_string(handle, info, &str, '=', 0) < 0)
goto err;
if (semanage_bool_set_name(handle, boolean, str) < 0)
diff --git a/libsemanage/src/compressed_file.c b/libsemanage/src/compressed_file.c
new file mode 100644
index 00000000..5546b830
--- /dev/null
+++ b/libsemanage/src/compressed_file.c
@@ -0,0 +1,224 @@
+/* Author: Jason Tang <jtang@tresys.com>
+ * Christopher Ashworth <cashworth@tresys.com>
+ * Ondrej Mosnacek <omosnacek@gmail.com>
+ *
+ * Copyright (C) 2004-2006 Tresys Technology, LLC
+ * Copyright (C) 2005-2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <bzlib.h>
+
+#include "compressed_file.h"
+
+#include "debug.h"
+
+#define BZ2_MAGICSTR "BZh"
+#define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1)
+
+/* bzip() a data to a file, returning the total number of compressed bytes
+ * in the file. Returns -1 if file could not be compressed. */
+static int bzip(semanage_handle_t *sh, const char *filename, void *data,
+ size_t num_bytes)
+{
+ BZFILE* b;
+ size_t size = 1<<16;
+ int bzerror;
+ size_t total = 0;
+ size_t len = 0;
+ FILE *f;
+
+ if ((f = fopen(filename, "wb")) == NULL) {
+ return -1;
+ }
+
+ if (!sh->conf->bzip_blocksize) {
+ if (fwrite(data, 1, num_bytes, f) < num_bytes) {
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+ return 0;
+ }
+
+ b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0);
+ if (bzerror != BZ_OK) {
+ BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
+ fclose(f);
+ return -1;
+ }
+
+ while ( num_bytes > total ) {
+ if (num_bytes - total > size) {
+ len = size;
+ } else {
+ len = num_bytes - total;
+ }
+ BZ2_bzWrite ( &bzerror, b, (uint8_t *)data + total, len );
+ if (bzerror == BZ_IO_ERROR) {
+ BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
+ fclose(f);
+ return -1;
+ }
+ total += len;
+ }
+
+ BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 );
+ fclose(f);
+ if (bzerror == BZ_IO_ERROR) {
+ return -1;
+ }
+ return 0;
+}
+
+/* bunzip() a file to '*data', returning the total number of uncompressed bytes
+ * in the file. Returns -1 if file could not be decompressed. */
+static ssize_t bunzip(semanage_handle_t *sh, FILE *f, void **data)
+{
+ BZFILE* b = NULL;
+ size_t nBuf;
+ uint8_t* buf = NULL;
+ size_t size = 1<<18;
+ size_t bufsize = size;
+ int bzerror;
+ size_t total = 0;
+ uint8_t* uncompress = NULL;
+ uint8_t* tmpalloc = NULL;
+ int ret = -1;
+
+ buf = malloc(bufsize);
+ if (buf == NULL) {
+ ERR(sh, "Failure allocating memory.");
+ goto exit;
+ }
+
+ /* Check if the file is bzipped */
+ bzerror = fread(buf, 1, BZ2_MAGICLEN, f);
+ rewind(f);
+ if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) {
+ goto exit;
+ }
+
+ b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 );
+ if ( bzerror != BZ_OK ) {
+ ERR(sh, "Failure opening bz2 archive.");
+ goto exit;
+ }
+
+ uncompress = malloc(size);
+ if (uncompress == NULL) {
+ ERR(sh, "Failure allocating memory.");
+ goto exit;
+ }
+
+ while ( bzerror == BZ_OK) {
+ nBuf = BZ2_bzRead ( &bzerror, b, buf, bufsize);
+ if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) {
+ if (total + nBuf > size) {
+ size *= 2;
+ tmpalloc = realloc(uncompress, size);
+ if (tmpalloc == NULL) {
+ ERR(sh, "Failure allocating memory.");
+ goto exit;
+ }
+ uncompress = tmpalloc;
+ }
+ memcpy(&uncompress[total], buf, nBuf);
+ total += nBuf;
+ }
+ }
+ if ( bzerror != BZ_STREAM_END ) {
+ ERR(sh, "Failure reading bz2 archive.");
+ goto exit;
+ }
+
+ ret = total;
+ *data = uncompress;
+
+exit:
+ BZ2_bzReadClose ( &bzerror, b );
+ free(buf);
+ if ( ret < 0 ) {
+ free(uncompress);
+ }
+ return ret;
+}
+
+int map_compressed_file(semanage_handle_t *sh, const char *path,
+ struct file_contents *contents)
+{
+ ssize_t size = -1;
+ void *uncompress;
+ int ret = 0, fd = -1;
+ FILE *file = NULL;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ ERR(sh, "Unable to open %s\n", path);
+ return -1;
+ }
+
+ file = fdopen(fd, "r");
+ if (file == NULL) {
+ ERR(sh, "Unable to open %s\n", path);
+ close(fd);
+ return -1;
+ }
+
+ if ((size = bunzip(sh, file, &uncompress)) >= 0) {
+ contents->data = uncompress;
+ contents->len = size;
+ contents->compressed = 1;
+ } else {
+ struct stat sb;
+ if (fstat(fd, &sb) == -1 ||
+ (uncompress = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) ==
+ MAP_FAILED) {
+ ret = -1;
+ } else {
+ contents->data = uncompress;
+ contents->len = sb.st_size;
+ contents->compressed = 0;
+ }
+ }
+ fclose(file);
+ return ret;
+}
+
+void unmap_compressed_file(struct file_contents *contents)
+{
+ if (!contents->data)
+ return;
+
+ if (contents->compressed) {
+ free(contents->data);
+ } else {
+ munmap(contents->data, contents->len);
+ }
+}
+
+int write_compressed_file(semanage_handle_t *sh, const char *path,
+ void *data, size_t len)
+{
+ return bzip(sh, path, data, len);
+}
diff --git a/libsemanage/src/compressed_file.h b/libsemanage/src/compressed_file.h
new file mode 100644
index 00000000..96cfb4b6
--- /dev/null
+++ b/libsemanage/src/compressed_file.h
@@ -0,0 +1,78 @@
+/* Author: Jason Tang <jtang@tresys.com>
+ * Christopher Ashworth <cashworth@tresys.com>
+ * Ondrej Mosnacek <omosnacek@gmail.com>
+ *
+ * Copyright (C) 2004-2006 Tresys Technology, LLC
+ * Copyright (C) 2005-2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SEMANAGE_CIL_FILE_H_
+#define _SEMANAGE_CIL_FILE_H_
+
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include "handle.h"
+
+struct file_contents {
+ void *data; /** file contents (uncompressed) */
+ size_t len; /** length of contents */
+ int compressed; /** whether file was compressed */
+};
+
+/**
+ * Map/read a possibly-compressed file into memory.
+ *
+ * If the file is bzip compressed map_file will uncompress the file into
+ * @p contents. The caller is responsible for calling
+ * @ref unmap_compressed_file on @p contents on success.
+ *
+ * @param sh semanage handle
+ * @param path path to the file
+ * @param contents pointer to struct file_contents, which will be
+ * populated with data pointer, size, and an indication whether
+ * the file was compressed or not
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+int map_compressed_file(semanage_handle_t *sh, const char *path,
+ struct file_contents *contents);
+
+/**
+ * Destroy a previously mapped possibly-compressed file.
+ *
+ * If all fields of @p contents are zero/NULL, the function is
+ * guaranteed to do nothing.
+ *
+ * @param contents pointer to struct file_contents to destroy
+ */
+void unmap_compressed_file(struct file_contents *contents);
+
+/**
+ * Write bytes into a file, using compression if configured.
+ *
+ * @param sh semanage handle
+ * @param path path to the file
+ * @param data pointer to the data
+ * @param len length of the data
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+int write_compressed_file(semanage_handle_t *sh, const char *path,
+ void *data, size_t len);
+
+#endif
diff --git a/libsemanage/src/conf-parse.y b/libsemanage/src/conf-parse.y
index 9bf9364a..eac91344 100644
--- a/libsemanage/src/conf-parse.y
+++ b/libsemanage/src/conf-parse.y
@@ -516,12 +516,12 @@ static int parse_module_store(char *arg)
char *s;
current_conf->store_type = SEMANAGE_CON_POLSERV_REMOTE;
if ((s = strchr(arg, ':')) == NULL) {
- current_conf->store_path = arg;
+ current_conf->store_path = strdup(arg);
current_conf->server_port = 4242;
} else {
char *endptr;
*s = '\0';
- current_conf->store_path = arg;
+ current_conf->store_path = strdup(arg);
current_conf->server_port = strtol(s + 1, &endptr, 10);
if (*(s + 1) == '\0' || *endptr != '\0') {
return -2;
diff --git a/libsemanage/src/context_internal.h b/libsemanage/src/context_internal.h
deleted file mode 100644
index 729bfc84..00000000
--- a/libsemanage/src/context_internal.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _SEMANAGE_CONTEXT_INTERNAL_H_
-#define _SEMANAGE_CONTEXT_INTERNAL_H_
-
-#include <semanage/context_record.h>
-#include "dso.h"
-
-hidden_proto(semanage_context_clone)
- hidden_proto(semanage_context_free)
- hidden_proto(semanage_context_from_string)
- hidden_proto(semanage_context_to_string)
-#endif
diff --git a/libsemanage/src/context_record.c b/libsemanage/src/context_record.c
index a228565e..dafb90fc 100644
--- a/libsemanage/src/context_record.c
+++ b/libsemanage/src/context_record.c
@@ -6,7 +6,8 @@
typedef sepol_context_t semanage_context_t;
#define _SEMANAGE_CONTEXT_DEFINED_
-#include "context_internal.h"
+
+#include <semanage/context_record.h>
/* User */
const char *semanage_context_get_user(const semanage_context_t * con)
@@ -80,7 +81,6 @@ int semanage_context_clone(semanage_handle_t * handle,
return sepol_context_clone(handle->sepolh, con, con_ptr);
}
-hidden_def(semanage_context_clone)
void semanage_context_free(semanage_context_t * con)
{
@@ -88,7 +88,6 @@ void semanage_context_free(semanage_context_t * con)
sepol_context_free(con);
}
-hidden_def(semanage_context_free)
/* Parse to/from string */
int semanage_context_from_string(semanage_handle_t * handle,
@@ -98,7 +97,6 @@ int semanage_context_from_string(semanage_handle_t * handle,
return sepol_context_from_string(handle->sepolh, str, con);
}
-hidden_def(semanage_context_from_string)
int semanage_context_to_string(semanage_handle_t * handle,
const semanage_context_t * con, char **str_ptr)
@@ -107,4 +105,3 @@ int semanage_context_to_string(semanage_handle_t * handle,
return sepol_context_to_string(handle->sepolh, con, str_ptr);
}
-hidden_def(semanage_context_to_string)
diff --git a/libsemanage/src/database_join.c b/libsemanage/src/database_join.c
index b9b35a61..a49a6226 100644
--- a/libsemanage/src/database_join.c
+++ b/libsemanage/src/database_join.c
@@ -77,10 +77,14 @@ static int dbase_join_cache(semanage_handle_t * handle, dbase_join_t * dbase)
goto err;
/* Sort for quicker merge later */
- qsort(records1, rcount1, sizeof(record1_t *),
- (int (*)(const void *, const void *))rtable1->compare2_qsort);
- qsort(records2, rcount2, sizeof(record2_t *),
- (int (*)(const void *, const void *))rtable2->compare2_qsort);
+ if (rcount1 > 0) {
+ qsort(records1, rcount1, sizeof(record1_t *),
+ (int (*)(const void *, const void *))rtable1->compare2_qsort);
+ }
+ if (rcount2 > 0) {
+ qsort(records2, rcount2, sizeof(record2_t *),
+ (int (*)(const void *, const void *))rtable2->compare2_qsort);
+ }
/* Now merge into this dbase */
while (i < rcount1 || j < rcount2) {
diff --git a/libsemanage/src/database_llist.c b/libsemanage/src/database_llist.c
index c8f4ff0b..240b2557 100644
--- a/libsemanage/src/database_llist.c
+++ b/libsemanage/src/database_llist.c
@@ -218,7 +218,7 @@ int dbase_llist_modify(semanage_handle_t * handle,
return STATUS_ERR;
}
-hidden int dbase_llist_count(semanage_handle_t * handle __attribute__ ((unused)),
+ int dbase_llist_count(semanage_handle_t * handle __attribute__ ((unused)),
dbase_llist_t * dbase, unsigned int *response)
{
diff --git a/libsemanage/src/debug.c b/libsemanage/src/debug.c
index 08a9e026..3c345462 100644
--- a/libsemanage/src/debug.c
+++ b/libsemanage/src/debug.c
@@ -33,25 +33,22 @@ int semanage_msg_get_level(semanage_handle_t * handle)
return handle->msg_level;
}
-hidden_def(semanage_msg_get_level)
const char *semanage_msg_get_channel(semanage_handle_t * handle)
{
return handle->msg_channel;
}
-hidden_def(semanage_msg_get_channel)
const char *semanage_msg_get_fname(semanage_handle_t * handle)
{
return handle->msg_fname;
}
-hidden_def(semanage_msg_get_fname)
#ifdef __GNUC__
__attribute__ ((format(printf, 3, 4)))
#endif
-void hidden semanage_msg_default_handler(void *varg __attribute__ ((unused)),
+void semanage_msg_default_handler(void *varg __attribute__ ((unused)),
semanage_handle_t * handle,
const char *fmt, ...)
{
@@ -91,7 +88,7 @@ void hidden semanage_msg_default_handler(void *varg __attribute__ ((unused)),
#ifdef __GNUC__
__attribute__ ((format(printf, 3, 4)))
#endif
-void hidden semanage_msg_relay_handler(void *varg,
+void semanage_msg_relay_handler(void *varg,
sepol_handle_t * sepolh,
const char *fmt, ...)
{
diff --git a/libsemanage/src/debug.h b/libsemanage/src/debug.h
index 92bfcf5f..a18a95be 100644
--- a/libsemanage/src/debug.h
+++ b/libsemanage/src/debug.h
@@ -27,7 +27,6 @@
#include <semanage/debug.h>
#include <sepol/debug.h>
#include "handle.h"
-#include "dso.h"
#define STATUS_SUCCESS 0
#define STATUS_ERR -1
@@ -62,18 +61,15 @@
#ifdef __GNUC__
__attribute__ ((format(printf, 3, 4)))
#endif
-extern void hidden semanage_msg_default_handler(void *varg,
+extern void semanage_msg_default_handler(void *varg,
semanage_handle_t * handle,
const char *fmt, ...);
#ifdef __GNUC__
__attribute__ ((format(printf, 3, 4)))
#endif
-extern void hidden semanage_msg_relay_handler(void *varg,
+extern void semanage_msg_relay_handler(void *varg,
sepol_handle_t * handle,
const char *fmt, ...);
-hidden_proto(semanage_msg_get_channel)
- hidden_proto(semanage_msg_get_fname)
- hidden_proto(semanage_msg_get_level)
#endif
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index 1088a0ac..d83941b0 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -33,6 +33,8 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
#include <limits.h>
#include <errno.h>
#include <dirent.h>
@@ -50,13 +52,13 @@
#include "debug.h"
#include "handle.h"
+#include "compressed_file.h"
#include "modules.h"
#include "direct_api.h"
#include "semanage_store.h"
#include "database_policydb.h"
#include "policy.h"
-#include <sys/mman.h>
-#include <sys/wait.h>
+#include "sha256.h"
#define PIPE_READ 0
#define PIPE_WRITE 1
@@ -446,198 +448,10 @@ static int parse_module_headers(semanage_handle_t * sh, char *module_data,
return 0;
}
-#include <stdlib.h>
-#include <bzlib.h>
-#include <string.h>
-#include <sys/sendfile.h>
-
-/* bzip() a data to a file, returning the total number of compressed bytes
- * in the file. Returns -1 if file could not be compressed. */
-static ssize_t bzip(semanage_handle_t *sh, const char *filename, char *data,
- size_t num_bytes)
-{
- BZFILE* b;
- size_t size = 1<<16;
- int bzerror;
- size_t total = 0;
- size_t len = 0;
- FILE *f;
-
- if ((f = fopen(filename, "wb")) == NULL) {
- return -1;
- }
-
- if (!sh->conf->bzip_blocksize) {
- if (fwrite(data, 1, num_bytes, f) < num_bytes) {
- fclose(f);
- return -1;
- }
- fclose(f);
- return num_bytes;
- }
-
- b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0);
- if (bzerror != BZ_OK) {
- BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
- return -1;
- }
-
- while ( num_bytes > total ) {
- if (num_bytes - total > size) {
- len = size;
- } else {
- len = num_bytes - total;
- }
- BZ2_bzWrite ( &bzerror, b, &data[total], len );
- if (bzerror == BZ_IO_ERROR) {
- BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 );
- return -1;
- }
- total += len;
- }
-
- BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 );
- fclose(f);
- if (bzerror == BZ_IO_ERROR) {
- return -1;
- }
- return total;
-}
-
-#define BZ2_MAGICSTR "BZh"
-#define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1)
-
-/* bunzip() a file to '*data', returning the total number of uncompressed bytes
- * in the file. Returns -1 if file could not be decompressed. */
-ssize_t bunzip(semanage_handle_t *sh, FILE *f, char **data)
-{
- BZFILE* b = NULL;
- size_t nBuf;
- char* buf = NULL;
- size_t size = 1<<18;
- size_t bufsize = size;
- int bzerror;
- size_t total = 0;
- char* uncompress = NULL;
- char* tmpalloc = NULL;
- int ret = -1;
-
- buf = malloc(bufsize);
- if (buf == NULL) {
- ERR(sh, "Failure allocating memory.");
- goto exit;
- }
-
- /* Check if the file is bzipped */
- bzerror = fread(buf, 1, BZ2_MAGICLEN, f);
- rewind(f);
- if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) {
- goto exit;
- }
-
- b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 );
- if ( bzerror != BZ_OK ) {
- ERR(sh, "Failure opening bz2 archive.");
- goto exit;
- }
-
- uncompress = malloc(size);
- if (uncompress == NULL) {
- ERR(sh, "Failure allocating memory.");
- goto exit;
- }
-
- while ( bzerror == BZ_OK) {
- nBuf = BZ2_bzRead ( &bzerror, b, buf, bufsize);
- if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) {
- if (total + nBuf > size) {
- size *= 2;
- tmpalloc = realloc(uncompress, size);
- if (tmpalloc == NULL) {
- ERR(sh, "Failure allocating memory.");
- goto exit;
- }
- uncompress = tmpalloc;
- }
- memcpy(&uncompress[total], buf, nBuf);
- total += nBuf;
- }
- }
- if ( bzerror != BZ_STREAM_END ) {
- ERR(sh, "Failure reading bz2 archive.");
- goto exit;
- }
-
- ret = total;
- *data = uncompress;
-
-exit:
- BZ2_bzReadClose ( &bzerror, b );
- free(buf);
- if ( ret < 0 ) {
- free(uncompress);
- }
- return ret;
-}
-
-/* mmap() a file to '*data',
- * If the file is bzip compressed map_file will uncompress
- * the file into '*data'.
- * Returns the total number of bytes in memory .
- * Returns -1 if file could not be opened or mapped. */
-static ssize_t map_file(semanage_handle_t *sh, const char *path, char **data,
- int *compressed)
-{
- ssize_t size = -1;
- char *uncompress;
- int fd = -1;
- FILE *file = NULL;
-
- fd = open(path, O_RDONLY);
- if (fd == -1) {
- ERR(sh, "Unable to open %s\n", path);
- return -1;
- }
-
- file = fdopen(fd, "r");
- if (file == NULL) {
- ERR(sh, "Unable to open %s\n", path);
- close(fd);
- return -1;
- }
-
- if ((size = bunzip(sh, file, &uncompress)) > 0) {
- *data = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
- if (*data == MAP_FAILED) {
- free(uncompress);
- fclose(file);
- return -1;
- } else {
- memcpy(*data, uncompress, size);
- }
- free(uncompress);
- *compressed = 1;
- } else {
- struct stat sb;
- if (fstat(fd, &sb) == -1 ||
- (*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) ==
- MAP_FAILED) {
- size = -1;
- } else {
- size = sb.st_size;
- }
- *compressed = 0;
- }
-
- fclose(file);
-
- return size;
-}
-
/* Writes a block of data to a file. Returns 0 on success, -1 on
* error. */
static int write_file(semanage_handle_t * sh,
- const char *filename, char *data, size_t num_bytes)
+ const char *filename, const char *data, size_t num_bytes)
{
int out;
@@ -1022,6 +836,7 @@ static int semanage_direct_write_langext(semanage_handle_t *sh,
if (fclose(fp) != 0) {
ERR(sh, "Unable to close %s module ext file.", modinfo->name);
+ fp = NULL;
ret = -1;
goto cleanup;
}
@@ -1036,23 +851,33 @@ cleanup:
return ret;
}
+static void update_checksum_with_len(Sha256Context *context, size_t s)
+{
+ int i;
+ uint8_t buffer[8];
+
+ for (i = 0; i < 8; i++) {
+ buffer[i] = s & 0xff;
+ s >>= 8;
+ }
+ Sha256Update(context, buffer, 8);
+}
+
static int semanage_compile_module(semanage_handle_t *sh,
- semanage_module_info_t *modinfo)
+ semanage_module_info_t *modinfo,
+ Sha256Context *context)
{
char cil_path[PATH_MAX];
char hll_path[PATH_MAX];
char *compiler_path = NULL;
char *cil_data = NULL;
char *err_data = NULL;
- char *hll_data = NULL;
char *start = NULL;
char *end = NULL;
- ssize_t hll_data_len = 0;
- ssize_t bzip_status;
int status = 0;
- int compressed;
size_t cil_data_len = 0;
size_t err_data_len = 0;
+ struct file_contents hll_contents = {};
if (!strcasecmp(modinfo->lang_ext, "cil")) {
goto cleanup;
@@ -1083,13 +908,15 @@ static int semanage_compile_module(semanage_handle_t *sh,
goto cleanup;
}
- if ((hll_data_len = map_file(sh, hll_path, &hll_data, &compressed)) <= 0) {
+ status = map_compressed_file(sh, hll_path, &hll_contents);
+ if (status < 0) {
ERR(sh, "Unable to read file %s\n", hll_path);
- status = -1;
goto cleanup;
}
- status = semanage_pipe_data(sh, compiler_path, hll_data, (size_t)hll_data_len, &cil_data, &cil_data_len, &err_data, &err_data_len);
+ status = semanage_pipe_data(sh, compiler_path, hll_contents.data,
+ hll_contents.len, &cil_data, &cil_data_len,
+ &err_data, &err_data_len);
if (err_data_len > 0) {
for (start = end = err_data; end < err_data + err_data_len; end++) {
if (*end == '\n') {
@@ -1109,10 +936,14 @@ static int semanage_compile_module(semanage_handle_t *sh,
goto cleanup;
}
- bzip_status = bzip(sh, cil_path, cil_data, cil_data_len);
- if (bzip_status == -1) {
- ERR(sh, "Failed to bzip %s\n", cil_path);
- status = -1;
+ if (context) {
+ update_checksum_with_len(context, cil_data_len);
+ Sha256Update(context, cil_data, cil_data_len);
+ }
+
+ status = write_compressed_file(sh, cil_path, cil_data, cil_data_len);
+ if (status == -1) {
+ ERR(sh, "Failed to write %s\n", cil_path);
goto cleanup;
}
@@ -1130,9 +961,7 @@ static int semanage_compile_module(semanage_handle_t *sh,
}
cleanup:
- if (hll_data_len > 0) {
- munmap(hll_data, hll_data_len);
- }
+ unmap_compressed_file(&hll_contents);
free(cil_data);
free(err_data);
free(compiler_path);
@@ -1140,18 +969,40 @@ cleanup:
return status;
}
+static int modinfo_cmp(const void *a, const void *b)
+{
+ const semanage_module_info_t *ma = a;
+ const semanage_module_info_t *mb = b;
+
+ return strcmp(ma->name, mb->name);
+}
+
static int semanage_compile_hll_modules(semanage_handle_t *sh,
- semanage_module_info_t *modinfos,
- int num_modinfos)
+ semanage_module_info_t *modinfos,
+ int num_modinfos,
+ char *cil_checksum)
{
- int status = 0;
- int i;
+ /* to be incremented when checksum input data format changes */
+ static const size_t CHECKSUM_EPOCH = 1;
+
+ int i, status = 0;
char cil_path[PATH_MAX];
struct stat sb;
+ Sha256Context context;
+ SHA256_HASH hash;
+ struct file_contents contents = {};
assert(sh);
assert(modinfos);
+ /* Sort modules by name to get consistent ordering. */
+ qsort(modinfos, num_modinfos, sizeof(*modinfos), &modinfo_cmp);
+
+ Sha256Initialise(&context);
+ update_checksum_with_len(&context, CHECKSUM_EPOCH);
+
+ /* prefix with module count to avoid collisions */
+ update_checksum_with_len(&context, num_modinfos);
for (i = 0; i < num_modinfos; i++) {
status = semanage_module_get_path(
sh,
@@ -1159,36 +1010,108 @@ static int semanage_compile_hll_modules(semanage_handle_t *sh,
SEMANAGE_MODULE_PATH_CIL,
cil_path,
sizeof(cil_path));
- if (status != 0) {
- goto cleanup;
- }
+ if (status != 0)
+ return -1;
- if (semanage_get_ignore_module_cache(sh) == 0 &&
- (status = stat(cil_path, &sb)) == 0) {
- continue;
- }
- if (status != 0 && errno != ENOENT) {
- ERR(sh, "Unable to access %s: %s\n", cil_path, strerror(errno));
- goto cleanup; //an error in the "stat" call
+ if (!semanage_get_ignore_module_cache(sh)) {
+ status = stat(cil_path, &sb);
+ if (status == 0) {
+ status = map_compressed_file(sh, cil_path, &contents);
+ if (status < 0) {
+ ERR(sh, "Error mapping file: %s", cil_path);
+ return -1;
+ }
+
+ /* prefix with length to avoid collisions */
+ update_checksum_with_len(&context, contents.len);
+ Sha256Update(&context, contents.data, contents.len);
+
+ unmap_compressed_file(&contents);
+ continue;
+ } else if (errno != ENOENT) {
+ ERR(sh, "Unable to access %s: %s\n", cil_path,
+ strerror(errno));
+ return -1; //an error in the "stat" call
+ }
}
- status = semanage_compile_module(sh, &modinfos[i]);
- if (status < 0) {
- goto cleanup;
+ status = semanage_compile_module(sh, &modinfos[i], &context);
+ if (status < 0)
+ return -1;
+ }
+ Sha256Finalise(&context, &hash);
+
+ semanage_hash_to_checksum_string(hash.bytes, cil_checksum);
+ return 0;
+}
+
+static int semanage_compare_checksum(semanage_handle_t *sh, const char *reference)
+{
+ const char *path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_CHECKSUM);
+ struct stat sb;
+ int fd, retval;
+ char *data;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ if (errno != ENOENT) {
+ ERR(sh, "Unable to open %s: %s\n", path, strerror(errno));
+ return -1;
}
+ /* Checksum file not present - force a rebuild. */
+ return 1;
+ }
+
+ if (fstat(fd, &sb) == -1) {
+ ERR(sh, "Unable to stat %s\n", path);
+ retval = -1;
+ goto out_close;
}
- status = 0;
+ if (sb.st_size != (off_t)CHECKSUM_CONTENT_SIZE) {
+ /* Incompatible/invalid hash type - just force a rebuild. */
+ WARN(sh, "Module checksum invalid - forcing a rebuild\n");
+ retval = 1;
+ goto out_close;
+ }
-cleanup:
- return status;
+ data = mmap(NULL, CHECKSUM_CONTENT_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == MAP_FAILED) {
+ ERR(sh, "Unable to mmap %s\n", path);
+ retval = -1;
+ goto out_close;
+ }
+
+ retval = memcmp(data, reference, CHECKSUM_CONTENT_SIZE) != 0;
+ munmap(data, sb.st_size);
+out_close:
+ close(fd);
+ return retval;
}
+static int semanage_write_modules_checksum(semanage_handle_t *sh,
+ const char *checksum)
+{
+ const char *path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_CHECKSUM);
+
+ return write_file(sh, path, checksum, CHECKSUM_CONTENT_SIZE);
+}
+
+/* Files that must exist in order to skip policy rebuild. */
+static const int semanage_computed_files[] = {
+ SEMANAGE_STORE_KERNEL,
+ SEMANAGE_STORE_FC,
+ SEMANAGE_STORE_SEUSERS,
+ SEMANAGE_LINKED,
+ SEMANAGE_SEUSERS_LINKED,
+ SEMANAGE_USERS_EXTRA_LINKED
+};
+
/* Copies a file from src to dst. If dst already exists then
* overwrite it. If source doesn't exist then return success.
* Returns 0 on success, -1 on error. */
static int copy_file_if_exists(const char *src, const char *dst, mode_t mode){
- int rc = semanage_copy_file(src, dst, mode);
+ int rc = semanage_copy_file(src, dst, mode, false);
return (rc < 0 && errno != ENOENT) ? rc : 0;
}
@@ -1210,6 +1133,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)
semanage_module_info_t *modinfos = NULL;
mode_t mask = umask(0077);
struct stat sb;
+ char modules_checksum[CHECKSUM_CONTENT_SIZE + 1 /* '\0' */];
int do_rebuild, do_write_kernel, do_install;
int fcontexts_modified, ports_modified, seusers_modified,
@@ -1243,6 +1167,14 @@ static int semanage_direct_commit(semanage_handle_t * sh)
seusers_modified = seusers->dtable->is_modified(seusers->dbase);
fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase);
+ /* Before we do anything else, flush the join to its component parts.
+ * This *does not* flush to disk automatically */
+ if (users->dtable->is_modified(users->dbase)) {
+ retval = users->dtable->flush(sh, users->dbase);
+ if (retval < 0)
+ goto cleanup;
+ }
+
/* Rebuild if explicitly requested or any module changes occurred. */
do_rebuild = sh->do_rebuild | sh->modules_modified;
@@ -1309,14 +1241,6 @@ static int semanage_direct_commit(semanage_handle_t * sh)
}
}
- /* Before we do anything else, flush the join to its component parts.
- * This *does not* flush to disk automatically */
- if (users->dtable->is_modified(users->dbase)) {
- retval = users->dtable->flush(sh, users->dbase);
- if (retval < 0)
- goto cleanup;
- }
-
/*
* This is for systems that have already migrated with an older version
* of semanage_migrate_store. The older version did not copy
@@ -1325,70 +1249,59 @@ static int semanage_direct_commit(semanage_handle_t * sh)
* in order to skip re-linking are present; otherwise, we force
* a rebuild.
*/
- if (!do_rebuild) {
- int files[] = {SEMANAGE_STORE_KERNEL,
- SEMANAGE_STORE_FC,
- SEMANAGE_STORE_SEUSERS,
- SEMANAGE_LINKED,
- SEMANAGE_SEUSERS_LINKED,
- SEMANAGE_USERS_EXTRA_LINKED};
-
- for (i = 0; i < (int) ARRAY_SIZE(files); i++) {
- path = semanage_path(SEMANAGE_TMP, files[i]);
- if (stat(path, &sb) != 0) {
- if (errno != ENOENT) {
- ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
- retval = -1;
- goto cleanup;
- }
-
- do_rebuild = 1;
- goto rebuild;
+ for (i = 0; !do_rebuild && i < (int)ARRAY_SIZE(semanage_computed_files); i++) {
+ path = semanage_path(SEMANAGE_TMP, semanage_computed_files[i]);
+ if (stat(path, &sb) != 0) {
+ if (errno != ENOENT) {
+ ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
+ retval = -1;
+ goto cleanup;
}
+
+ do_rebuild = 1;
+ break;
}
}
-rebuild:
- /*
- * Now that we know whether or not a rebuild is required,
- * we can determine what else needs to be done.
- * We need to write the kernel policy if we are rebuilding
- * or if any other policy component that lives in the kernel
- * policy has been modified.
- * We need to install the policy files if any of the managed files
- * that live under /etc/selinux (kernel policy, seusers, file contexts)
- * will be modified.
- */
- do_write_kernel = do_rebuild | ports_modified | ibpkeys_modified |
- ibendports_modified |
- bools->dtable->is_modified(bools->dbase) |
- ifaces->dtable->is_modified(ifaces->dbase) |
- nodes->dtable->is_modified(nodes->dbase) |
- users->dtable->is_modified(users_base->dbase);
- do_install = do_write_kernel | seusers_modified | fcontexts_modified;
-
- /*
- * If there were policy changes, or explicitly requested, or
- * any required files are missing, rebuild the policy.
- */
- if (do_rebuild) {
- /* =================== Module expansion =============== */
-
+ if (do_rebuild || sh->check_ext_changes) {
retval = semanage_get_active_modules(sh, &modinfos, &num_modinfos);
if (retval < 0) {
goto cleanup;
}
+ /* No modules - nothing to rebuild. */
if (num_modinfos == 0) {
goto cleanup;
}
- retval = semanage_compile_hll_modules(sh, modinfos, num_modinfos);
+ retval = semanage_compile_hll_modules(sh, modinfos, num_modinfos,
+ modules_checksum);
if (retval < 0) {
ERR(sh, "Failed to compile hll files into cil files.\n");
goto cleanup;
}
+ if (!do_rebuild && sh->check_ext_changes) {
+ retval = semanage_compare_checksum(sh, modules_checksum);
+ if (retval < 0)
+ goto cleanup;
+ do_rebuild = retval;
+ }
+
+ retval = semanage_write_modules_checksum(sh, modules_checksum);
+ if (retval < 0) {
+ ERR(sh, "Failed to write module checksum file.\n");
+ goto cleanup;
+ }
+ }
+
+ /*
+ * If there were policy changes, or explicitly requested, or
+ * any required files are missing, rebuild the policy.
+ */
+ if (do_rebuild) {
+ /* =================== Module expansion =============== */
+
retval = semanage_get_cil_paths(sh, modinfos, num_modinfos, &mod_filenames);
if (retval < 0)
goto cleanup;
@@ -1488,7 +1401,7 @@ rebuild:
retval = semanage_copy_file(path,
semanage_path(SEMANAGE_TMP,
SEMANAGE_STORE_SEUSERS),
- 0);
+ 0, false);
if (retval < 0)
goto cleanup;
pseusers->dtable->drop_cache(pseusers->dbase);
@@ -1506,7 +1419,7 @@ rebuild:
retval = semanage_copy_file(path,
semanage_path(SEMANAGE_TMP,
SEMANAGE_USERS_EXTRA),
- 0);
+ 0, false);
if (retval < 0)
goto cleanup;
pusers_extra->dtable->drop_cache(pusers_extra->dbase);
@@ -1520,6 +1433,23 @@ rebuild:
}
}
+ /*
+ * Determine what else needs to be done.
+ * We need to write the kernel policy if we are rebuilding
+ * or if any other policy component that lives in the kernel
+ * policy has been modified.
+ * We need to install the policy files if any of the managed files
+ * that live under /etc/selinux (kernel policy, seusers, file contexts)
+ * will be modified.
+ */
+ do_write_kernel = do_rebuild | ports_modified | ibpkeys_modified |
+ ibendports_modified |
+ bools->dtable->is_modified(bools->dbase) |
+ ifaces->dtable->is_modified(ifaces->dbase) |
+ nodes->dtable->is_modified(nodes->dbase) |
+ users->dtable->is_modified(users_base->dbase);
+ do_install = do_write_kernel | seusers_modified | fcontexts_modified;
+
/* Attach our databases to the policydb we just created or loaded. */
dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase, out);
dbase_policydb_attach((dbase_policydb_t *) pports->dbase, out);
@@ -1595,7 +1525,7 @@ rebuild:
retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL),
- sh->conf->file_mode);
+ sh->conf->file_mode, false);
if (retval < 0) {
goto cleanup;
}
@@ -1634,7 +1564,7 @@ rebuild:
retval = semanage_copy_file(
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS),
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_HOMEDIRS),
- sh->conf->file_mode);
+ sh->conf->file_mode, false);
if (retval < 0) {
goto cleanup;
}
@@ -1755,19 +1685,17 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
{
int retval = -1;
- char *data = NULL;
- ssize_t data_len = 0;
- int compressed = 0;
char *path = NULL;
char *filename;
char *lang_ext = NULL;
char *module_name = NULL;
char *separator;
char *version = NULL;
+ struct file_contents contents = {};
- if ((data_len = map_file(sh, install_filename, &data, &compressed)) <= 0) {
+ retval = map_compressed_file(sh, install_filename, &contents);
+ if (retval < 0) {
ERR(sh, "Unable to read file %s\n", install_filename);
- retval = -1;
goto cleanup;
}
@@ -1780,7 +1708,7 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
filename = basename(path);
- if (compressed) {
+ if (contents.compressed) {
separator = strrchr(filename, '.');
if (separator == NULL) {
ERR(sh, "Compressed module does not have a valid extension.");
@@ -1804,7 +1732,8 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
}
if (strcmp(lang_ext, "pp") == 0) {
- retval = parse_module_headers(sh, data, data_len, &module_name, &version);
+ retval = parse_module_headers(sh, contents.data, contents.len,
+ &module_name, &version);
free(version);
if (retval != 0)
goto cleanup;
@@ -1821,10 +1750,11 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
fprintf(stderr, "Warning: SELinux userspace will refer to the module from %s as %s rather than %s\n", install_filename, module_name, filename);
}
- retval = semanage_direct_install(sh, data, data_len, module_name, lang_ext);
+ retval = semanage_direct_install(sh, contents.data, contents.len,
+ module_name, lang_ext);
cleanup:
- if (data_len > 0) munmap(data, data_len);
+ unmap_compressed_file(&contents);
free(module_name);
free(path);
@@ -1843,10 +1773,8 @@ static int semanage_direct_extract(semanage_handle_t * sh,
enum semanage_module_path_type file_type;
int rc = -1;
semanage_module_info_t *_modinfo = NULL;
- ssize_t _data_len;
- char *_data;
- int compressed;
struct stat sb;
+ struct file_contents contents = {};
/* get path of module */
rc = semanage_module_get_path(
@@ -1896,25 +1824,39 @@ static int semanage_direct_extract(semanage_handle_t * sh,
goto cleanup;
}
- rc = semanage_compile_module(sh, _modinfo);
+ rc = semanage_compile_module(sh, _modinfo, NULL);
if (rc < 0) {
goto cleanup;
}
}
- _data_len = map_file(sh, input_file, &_data, &compressed);
- if (_data_len <= 0) {
+ rc = map_compressed_file(sh, input_file, &contents);
+ if (rc < 0) {
ERR(sh, "Error mapping file: %s", input_file);
- rc = -1;
goto cleanup;
}
+ /* The API promises an mmap'ed pointer */
+ if (contents.compressed) {
+ *mapped_data = mmap(NULL, contents.len, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+ if (*mapped_data == MAP_FAILED) {
+ ERR(sh, "Unable to map memory");
+ rc = -1;
+ goto cleanup;
+ }
+ memcpy(*mapped_data, contents.data, contents.len);
+ free(contents.data);
+ } else {
+ *mapped_data = contents.data;
+ }
+
*modinfo = _modinfo;
- *data_len = (size_t)_data_len;
- *mapped_data = _data;
+ *data_len = contents.len;
cleanup:
if (rc != 0) {
+ unmap_compressed_file(&contents);
semanage_module_info_destroy(sh, _modinfo);
free(_modinfo);
}
@@ -1951,6 +1893,7 @@ static int semanage_direct_remove(semanage_handle_t * sh, char *module_name)
status = semanage_direct_remove_key(sh, &modkey);
cleanup:
+ semanage_module_key_destroy(sh, &modkey);
return status;
}
@@ -2867,8 +2810,8 @@ static int semanage_direct_install_info(semanage_handle_t *sh,
goto cleanup;
}
- ret = bzip(sh, path, data, data_len);
- if (ret <= 0) {
+ ret = write_compressed_file(sh, path, data, data_len);
+ if (ret < 0) {
ERR(sh, "Error while writing to %s.", path);
status = -3;
goto cleanup;
diff --git a/libsemanage/src/direct_api.h b/libsemanage/src/direct_api.h
index e56107b2..ffd428eb 100644
--- a/libsemanage/src/direct_api.h
+++ b/libsemanage/src/direct_api.h
@@ -39,8 +39,4 @@ int semanage_direct_access_check(struct semanage_handle *sh);
int semanage_direct_mls_enabled(struct semanage_handle *sh);
-#include <stdio.h>
-#include <unistd.h>
-ssize_t bunzip(struct semanage_handle *sh, FILE *f, char **data);
-
#endif
diff --git a/libsemanage/src/dso.h b/libsemanage/src/dso.h
deleted file mode 100644
index 8c9a0140..00000000
--- a/libsemanage/src/dso.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _SEMANAGE_DSO_H
-#define _SEMANAGE_DSO_H 1
-
-#ifdef SHARED
-# define hidden __attribute__ ((visibility ("hidden")))
-# define hidden_proto(fct) __hidden_proto (fct, fct##_internal)
-# define __hidden_proto(fct, internal) \
- extern __typeof (fct) internal; \
- extern __typeof (fct) fct __asm (#internal) hidden;
-# if defined(__alpha__) || defined(__mips__)
-# define hidden_def(fct) \
- asm (".globl " #fct "\n" #fct " = " #fct "_internal");
-# else
-# define hidden_def(fct) \
- asm (".globl " #fct "\n.set " #fct ", " #fct "_internal");
-#endif
-#else
-# define hidden
-# define hidden_proto(fct)
-# define hidden_def(fct)
-#endif
-
-#endif
diff --git a/libsemanage/src/exception.sh b/libsemanage/src/exception.sh
index fc1d4035..e1d01b59 100644
--- a/libsemanage/src/exception.sh
+++ b/libsemanage/src/exception.sh
@@ -6,8 +6,7 @@ echo "
PyErr_SetFromErrno(PyExc_OSError);
SWIG_fail;
}
-}
-"
+}"
}
if ! ${CC:-gcc} -x c -c -I../include -o temp.o - -aux-info temp.aux < ../include/semanage/semanage.h
then
diff --git a/libsemanage/src/fcontext_internal.h b/libsemanage/src/fcontext_internal.h
index c7767d07..7ae20f12 100644
--- a/libsemanage/src/fcontext_internal.h
+++ b/libsemanage/src/fcontext_internal.h
@@ -7,24 +7,6 @@
#include <sepol/policydb.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_fcontext_key_create)
- hidden_proto(semanage_fcontext_key_extract)
- hidden_proto(semanage_fcontext_key_free)
- hidden_proto(semanage_fcontext_compare)
- hidden_proto(semanage_fcontext_compare2)
- hidden_proto(semanage_fcontext_create)
- hidden_proto(semanage_fcontext_get_expr)
- hidden_proto(semanage_fcontext_set_expr)
- hidden_proto(semanage_fcontext_get_type)
- hidden_proto(semanage_fcontext_get_type_str)
- hidden_proto(semanage_fcontext_set_type)
- hidden_proto(semanage_fcontext_get_con)
- hidden_proto(semanage_fcontext_set_con)
- hidden_proto(semanage_fcontext_clone)
- hidden_proto(semanage_fcontext_free)
- hidden_proto(semanage_fcontext_iterate_local)
/* FCONTEXT RECORD: method table */
extern record_table_t SEMANAGE_FCONTEXT_RTABLE;
@@ -36,7 +18,7 @@ extern int fcontext_file_dbase_init(semanage_handle_t * handle,
extern void fcontext_file_dbase_release(dbase_config_t * dconfig);
-extern int hidden semanage_fcontext_validate_local(semanage_handle_t * handle,
+extern int semanage_fcontext_validate_local(semanage_handle_t * handle,
const sepol_policydb_t *
policydb);
diff --git a/libsemanage/src/fcontext_record.c b/libsemanage/src/fcontext_record.c
index f39efa19..ae1b0324 100644
--- a/libsemanage/src/fcontext_record.c
+++ b/libsemanage/src/fcontext_record.c
@@ -7,7 +7,6 @@ typedef struct semanage_fcontext_key record_key_t;
#include <stdlib.h>
#include <string.h>
#include "fcontext_internal.h"
-#include "context_internal.h"
#include "debug.h"
struct semanage_fcontext {
@@ -57,7 +56,6 @@ int semanage_fcontext_key_create(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_fcontext_key_create)
int semanage_fcontext_key_extract(semanage_handle_t * handle,
const semanage_fcontext_t * fcontext,
@@ -75,7 +73,6 @@ int semanage_fcontext_key_extract(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_fcontext_key_extract)
void semanage_fcontext_key_free(semanage_fcontext_key_t * key)
{
@@ -83,7 +80,6 @@ void semanage_fcontext_key_free(semanage_fcontext_key_t * key)
free(key);
}
-hidden_def(semanage_fcontext_key_free)
int semanage_fcontext_compare(const semanage_fcontext_t * fcontext,
const semanage_fcontext_key_t * key)
@@ -104,7 +100,6 @@ int semanage_fcontext_compare(const semanage_fcontext_t * fcontext,
}
}
-hidden_def(semanage_fcontext_compare)
int semanage_fcontext_compare2(const semanage_fcontext_t * fcontext,
const semanage_fcontext_t * fcontext2)
@@ -125,7 +120,6 @@ int semanage_fcontext_compare2(const semanage_fcontext_t * fcontext,
}
}
-hidden_def(semanage_fcontext_compare2)
static int semanage_fcontext_compare2_qsort(const semanage_fcontext_t **
fcontext,
@@ -158,7 +152,6 @@ int semanage_fcontext_create(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_fcontext_create)
/* Regexp */
const char *semanage_fcontext_get_expr(const semanage_fcontext_t * fcontext)
@@ -167,7 +160,6 @@ const char *semanage_fcontext_get_expr(const semanage_fcontext_t * fcontext)
return fcontext->expr;
}
-hidden_def(semanage_fcontext_get_expr)
int semanage_fcontext_set_expr(semanage_handle_t * handle,
semanage_fcontext_t * fcontext, const char *expr)
@@ -183,7 +175,6 @@ int semanage_fcontext_set_expr(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_fcontext_set_expr)
/* Type */
int semanage_fcontext_get_type(const semanage_fcontext_t * fcontext)
@@ -192,7 +183,6 @@ int semanage_fcontext_get_type(const semanage_fcontext_t * fcontext)
return fcontext->type;
}
-hidden_def(semanage_fcontext_get_type)
const char *semanage_fcontext_get_type_str(int type)
{
@@ -219,7 +209,6 @@ const char *semanage_fcontext_get_type_str(int type)
}
}
-hidden_def(semanage_fcontext_get_type_str)
void semanage_fcontext_set_type(semanage_fcontext_t * fcontext, int type)
{
@@ -227,7 +216,6 @@ void semanage_fcontext_set_type(semanage_fcontext_t * fcontext, int type)
fcontext->type = type;
}
-hidden_def(semanage_fcontext_set_type)
/* Context */
semanage_context_t *semanage_fcontext_get_con(const semanage_fcontext_t *
@@ -237,7 +225,6 @@ semanage_context_t *semanage_fcontext_get_con(const semanage_fcontext_t *
return fcontext->con;
}
-hidden_def(semanage_fcontext_get_con)
int semanage_fcontext_set_con(semanage_handle_t * handle,
semanage_fcontext_t * fcontext,
@@ -256,7 +243,6 @@ int semanage_fcontext_set_con(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_fcontext_set_con)
/* Deep copy clone */
int semanage_fcontext_clone(semanage_handle_t * handle,
@@ -288,7 +274,6 @@ int semanage_fcontext_clone(semanage_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(semanage_fcontext_clone)
/* Destroy */
void semanage_fcontext_free(semanage_fcontext_t * fcontext)
@@ -302,7 +287,6 @@ void semanage_fcontext_free(semanage_fcontext_t * fcontext)
free(fcontext);
}
-hidden_def(semanage_fcontext_free)
/* Record base functions */
record_table_t SEMANAGE_FCONTEXT_RTABLE = {
diff --git a/libsemanage/src/fcontexts_file.c b/libsemanage/src/fcontexts_file.c
index 1e596519..f3579410 100644
--- a/libsemanage/src/fcontexts_file.c
+++ b/libsemanage/src/fcontexts_file.c
@@ -15,7 +15,6 @@ typedef struct dbase_file dbase_t;
#include <strings.h>
#include <semanage/handle.h>
#include "fcontext_internal.h"
-#include "context_internal.h"
#include "database_file.h"
#include "parse_utils.h"
#include "debug.h"
@@ -91,7 +90,7 @@ static int fcontext_parse(semanage_handle_t * handle,
goto last;
/* Regexp */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_fcontext_set_expr(handle, fcontext, str) < 0)
goto err;
@@ -101,7 +100,7 @@ static int fcontext_parse(semanage_handle_t * handle,
/* Type */
if (parse_assert_space(handle, info) < 0)
goto err;
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (!strcasecmp(str, "-s"))
semanage_fcontext_set_type(fcontext, SEMANAGE_FCONTEXT_SOCK);
@@ -125,7 +124,7 @@ static int fcontext_parse(semanage_handle_t * handle,
/* Context */
if (parse_assert_space(handle, info) < 0)
goto err;
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
process_context:
diff --git a/libsemanage/src/fcontexts_local.c b/libsemanage/src/fcontexts_local.c
index b0da236b..ea994d8c 100644
--- a/libsemanage/src/fcontexts_local.c
+++ b/libsemanage/src/fcontexts_local.c
@@ -10,7 +10,6 @@ typedef struct semanage_fcontext record_t;
#include <sepol/policydb.h>
#include <sepol/context.h>
#include "fcontext_internal.h"
-#include "context_internal.h"
#include "debug.h"
#include "handle.h"
#include "database.h"
@@ -68,7 +67,6 @@ int semanage_fcontext_iterate_local(semanage_handle_t * handle,
return dbase_iterate(handle, dconfig, handler, handler_arg);
}
-hidden_def(semanage_fcontext_iterate_local)
int semanage_fcontext_list_local(semanage_handle_t * handle,
semanage_fcontext_t *** records,
@@ -118,7 +116,7 @@ static int validate_handler(const semanage_fcontext_t * fcon, void *varg)
return -1;
}
-int hidden semanage_fcontext_validate_local(semanage_handle_t * handle,
+int semanage_fcontext_validate_local(semanage_handle_t * handle,
const sepol_policydb_t * policydb)
{
diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
index d08c88de..7ca9afc3 100644
--- a/libsemanage/src/genhomedircon.c
+++ b/libsemanage/src/genhomedircon.c
@@ -740,7 +740,7 @@ static int write_user_context(genhomedircon_settings_t * s, FILE * out,
static int seuser_sort_func(const void *arg1, const void *arg2)
{
const semanage_seuser_t **u1 = (const semanage_seuser_t **) arg1;
- const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;;
+ const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;
const char *name1 = semanage_seuser_get_name(*u1);
const char *name2 = semanage_seuser_get_name(*u2);
diff --git a/libsemanage/src/handle.c b/libsemanage/src/handle.c
index 5e59aef7..b2201ee3 100644
--- a/libsemanage/src/handle.c
+++ b/libsemanage/src/handle.c
@@ -48,7 +48,6 @@ int semanage_set_root(const char *root)
return 0;
}
-hidden_def(semanage_set_root);
const char * semanage_root(void)
{
@@ -58,7 +57,6 @@ const char * semanage_root(void)
return private_semanage_root;
}
-hidden_def(semanage_root);
semanage_handle_t *semanage_handle_create(void)
{
@@ -118,20 +116,23 @@ semanage_handle_t *semanage_handle_create(void)
void semanage_set_rebuild(semanage_handle_t * sh, int do_rebuild)
{
-
assert(sh != NULL);
sh->do_rebuild = do_rebuild;
- return;
}
void semanage_set_reload(semanage_handle_t * sh, int do_reload)
{
-
assert(sh != NULL);
sh->do_reload = do_reload;
- return;
+}
+
+void semanage_set_check_ext_changes(semanage_handle_t * sh, int do_check)
+{
+ assert(sh != NULL);
+
+ sh->check_ext_changes = do_check;
}
int semanage_get_hll_compiler_path(semanage_handle_t *sh,
@@ -364,7 +365,6 @@ int semanage_access_check(semanage_handle_t * sh)
return -1; /* unreachable */
}
-hidden_def(semanage_access_check)
int semanage_disconnect(semanage_handle_t * sh)
{
@@ -394,7 +394,6 @@ void semanage_handle_destroy(semanage_handle_t * sh)
free(sh);
}
-hidden_def(semanage_handle_destroy)
/********************* public transaction functions *********************/
int semanage_begin_transaction(semanage_handle_t * sh)
@@ -416,7 +415,6 @@ int semanage_begin_transaction(semanage_handle_t * sh)
return 0;
}
-hidden_def(semanage_begin_transaction)
int semanage_commit(semanage_handle_t * sh)
{
diff --git a/libsemanage/src/handle.h b/libsemanage/src/handle.h
index a91907b0..4d2aae8f 100644
--- a/libsemanage/src/handle.h
+++ b/libsemanage/src/handle.h
@@ -25,7 +25,6 @@
#include <stdint.h>
#include <stddef.h>
-#include "handle_internal.h"
#include <sepol/handle.h>
#include "modules.h"
#include "semanage_conf.h"
@@ -62,6 +61,7 @@ struct semanage_handle {
int is_in_transaction;
int do_reload; /* whether to reload policy after commit */
int do_rebuild; /* whether to rebuild policy if there were no changes */
+ int check_ext_changes; /* whether to rebuild if external changes are detected via checksum */
int commit_err; /* set by semanage_direct_commit() if there are
* any errors when building or committing the
* sandbox to kernel policy at /etc/selinux
diff --git a/libsemanage/src/handle_internal.h b/libsemanage/src/handle_internal.h
deleted file mode 100644
index d4b4d9c7..00000000
--- a/libsemanage/src/handle_internal.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _SEMANAGE_HANDLE_INTERNAL_H_
-#define _SEMANAGE_HANDLE_INTERNAL_H_
-
-#include <semanage/handle.h>
-#include "dso.h"
-
-hidden_proto(semanage_begin_transaction)
-hidden_proto(semanage_handle_destroy)
-hidden_proto(semanage_reload_policy)
-hidden_proto(semanage_access_check)
-hidden_proto(semanage_set_root)
-hidden_proto(semanage_root)
-#endif
diff --git a/libsemanage/src/ibendport_internal.h b/libsemanage/src/ibendport_internal.h
index 970fbdb2..eada2d4b 100644
--- a/libsemanage/src/ibendport_internal.h
+++ b/libsemanage/src/ibendport_internal.h
@@ -6,22 +6,6 @@
#include <semanage/ibendports_policy.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_ibendport_create)
-hidden_proto(semanage_ibendport_compare)
-hidden_proto(semanage_ibendport_compare2)
-hidden_proto(semanage_ibendport_clone)
-hidden_proto(semanage_ibendport_free)
-hidden_proto(semanage_ibendport_key_extract)
-hidden_proto(semanage_ibendport_key_free)
-hidden_proto(semanage_ibendport_get_port)
-hidden_proto(semanage_ibendport_set_port)
-hidden_proto(semanage_ibendport_get_con)
-hidden_proto(semanage_ibendport_set_con)
-hidden_proto(semanage_ibendport_list_local)
-hidden_proto(semanage_ibendport_get_ibdev_name)
-hidden_proto(semanage_ibendport_set_ibdev_name)
/* IBENDPORT RECORD: method table */
extern record_table_t SEMANAGE_IBENDPORT_RTABLE;
@@ -38,11 +22,11 @@ extern int ibendport_policydb_dbase_init(semanage_handle_t *handle,
extern void ibendport_policydb_dbase_release(dbase_config_t *dconfig);
-extern int hidden semanage_ibendport_validate_local(semanage_handle_t *handle);
+extern int semanage_ibendport_validate_local(semanage_handle_t *handle);
/* ==== Internal (to ibendports) API === */
-hidden int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport,
+ int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport,
const semanage_ibendport_t **ibendport2);
#endif
diff --git a/libsemanage/src/ibendport_record.c b/libsemanage/src/ibendport_record.c
index 955067ea..a8cb125d 100644
--- a/libsemanage/src/ibendport_record.c
+++ b/libsemanage/src/ibendport_record.c
@@ -29,7 +29,6 @@ int semanage_ibendport_compare(const semanage_ibendport_t *ibendport,
return sepol_ibendport_compare(ibendport, key);
}
-hidden_def(semanage_ibendport_compare)
int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport,
const semanage_ibendport_t *ibendport2)
@@ -37,9 +36,8 @@ int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport,
return sepol_ibendport_compare2(ibendport, ibendport2);
}
-hidden_def(semanage_ibendport_compare2)
-hidden int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport,
+ int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport,
const semanage_ibendport_t **ibendport2)
{
return sepol_ibendport_compare2(*ibendport, *ibendport2);
@@ -60,14 +58,12 @@ int semanage_ibendport_key_extract(semanage_handle_t *handle,
return sepol_ibendport_key_extract(handle->sepolh, ibendport, key_ptr);
}
-hidden_def(semanage_ibendport_key_extract)
void semanage_ibendport_key_free(semanage_ibendport_key_t *key)
{
sepol_ibendport_key_free(key);
}
-hidden_def(semanage_ibendport_key_free)
int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle,
const semanage_ibendport_t *ibendport,
@@ -76,7 +72,6 @@ int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle,
return sepol_ibendport_get_ibdev_name(handle->sepolh, ibendport, ibdev_name_ptr);
}
-hidden_def(semanage_ibendport_get_ibdev_name)
int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle,
semanage_ibendport_t *ibendport,
@@ -85,28 +80,24 @@ int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle,
return sepol_ibendport_set_ibdev_name(handle->sepolh, ibendport, ibdev_name);
}
-hidden_def(semanage_ibendport_set_ibdev_name)
int semanage_ibendport_get_port(const semanage_ibendport_t *ibendport)
{
return sepol_ibendport_get_port(ibendport);
}
-hidden_def(semanage_ibendport_get_port)
void semanage_ibendport_set_port(semanage_ibendport_t *ibendport, int port)
{
sepol_ibendport_set_port(ibendport, port);
}
-hidden_def(semanage_ibendport_set_port)
semanage_context_t *semanage_ibendport_get_con(const semanage_ibendport_t *ibendport)
{
return sepol_ibendport_get_con(ibendport);
}
-hidden_def(semanage_ibendport_get_con)
int semanage_ibendport_set_con(semanage_handle_t *handle,
semanage_ibendport_t *ibendport,
@@ -115,7 +106,6 @@ int semanage_ibendport_set_con(semanage_handle_t *handle,
return sepol_ibendport_set_con(handle->sepolh, ibendport, con);
}
-hidden_def(semanage_ibendport_set_con)
int semanage_ibendport_create(semanage_handle_t *handle,
semanage_ibendport_t **ibendport_ptr)
@@ -123,7 +113,6 @@ int semanage_ibendport_create(semanage_handle_t *handle,
return sepol_ibendport_create(handle->sepolh, ibendport_ptr);
}
-hidden_def(semanage_ibendport_create)
int semanage_ibendport_clone(semanage_handle_t *handle,
const semanage_ibendport_t *ibendport,
@@ -132,14 +121,12 @@ int semanage_ibendport_clone(semanage_handle_t *handle,
return sepol_ibendport_clone(handle->sepolh, ibendport, ibendport_ptr);
}
-hidden_def(semanage_ibendport_clone)
void semanage_ibendport_free(semanage_ibendport_t *ibendport)
{
sepol_ibendport_free(ibendport);
}
-hidden_def(semanage_ibendport_free)
/*key base functions */
record_table_t SEMANAGE_IBENDPORT_RTABLE = {
diff --git a/libsemanage/src/ibendports_file.c b/libsemanage/src/ibendports_file.c
index 402c7a5e..2fa2a67c 100644
--- a/libsemanage/src/ibendports_file.c
+++ b/libsemanage/src/ibendports_file.c
@@ -15,7 +15,6 @@ typedef struct dbase_file dbase_t;
#include <strings.h>
#include <semanage/handle.h>
#include "ibendport_internal.h"
-#include "context_internal.h"
#include "database_file.h"
#include "parse_utils.h"
#include "debug.h"
@@ -76,7 +75,7 @@ static int ibendport_parse(semanage_handle_t *handle,
goto err;
/* IB Device Name */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_ibendport_set_ibdev_name(handle, ibendport, str) < 0)
goto err;
@@ -93,7 +92,7 @@ static int ibendport_parse(semanage_handle_t *handle,
/* context */
if (parse_assert_space(handle, info) < 0)
goto err;
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_context_from_string(handle, str, &con) < 0) {
ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
diff --git a/libsemanage/src/ibendports_local.c b/libsemanage/src/ibendports_local.c
index 8b5567d8..e696fdca 100644
--- a/libsemanage/src/ibendports_local.c
+++ b/libsemanage/src/ibendports_local.c
@@ -74,9 +74,8 @@ int semanage_ibendport_list_local(semanage_handle_t *handle,
return dbase_list(handle, dconfig, records, count);
}
-hidden_def(semanage_ibendport_list_local)
-int hidden semanage_ibendport_validate_local(semanage_handle_t *handle)
+int semanage_ibendport_validate_local(semanage_handle_t *handle)
{
semanage_ibendport_t **ibendports = NULL;
unsigned int nibendports = 0;
diff --git a/libsemanage/src/ibpkey_internal.h b/libsemanage/src/ibpkey_internal.h
index 9465bb8d..1e206b62 100644
--- a/libsemanage/src/ibpkey_internal.h
+++ b/libsemanage/src/ibpkey_internal.h
@@ -6,26 +6,6 @@
#include <semanage/ibpkeys_policy.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_ibpkey_create)
-hidden_proto(semanage_ibpkey_compare)
-hidden_proto(semanage_ibpkey_compare2)
-hidden_proto(semanage_ibpkey_clone)
-hidden_proto(semanage_ibpkey_free)
-hidden_proto(semanage_ibpkey_key_extract)
-hidden_proto(semanage_ibpkey_key_free)
-hidden_proto(semanage_ibpkey_get_high)
-hidden_proto(semanage_ibpkey_get_low)
-hidden_proto(semanage_ibpkey_set_pkey)
-hidden_proto(semanage_ibpkey_set_range)
-hidden_proto(semanage_ibpkey_get_con)
-hidden_proto(semanage_ibpkey_set_con)
-hidden_proto(semanage_ibpkey_list_local)
-hidden_proto(semanage_ibpkey_get_subnet_prefix)
-hidden_proto(semanage_ibpkey_get_subnet_prefix_bytes)
-hidden_proto(semanage_ibpkey_set_subnet_prefix)
-hidden_proto(semanage_ibpkey_set_subnet_prefix_bytes)
/* PKEY RECORD: method table */
extern record_table_t SEMANAGE_IBPKEY_RTABLE;
@@ -42,11 +22,11 @@ extern int ibpkey_policydb_dbase_init(semanage_handle_t *handle,
extern void ibpkey_policydb_dbase_release(dbase_config_t *dconfig);
-extern int hidden semanage_ibpkey_validate_local(semanage_handle_t *handle);
+extern int semanage_ibpkey_validate_local(semanage_handle_t *handle);
/* ==== Internal (to ibpkeys) API === */
-hidden int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t **ibpkey,
+ int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t **ibpkey,
const semanage_ibpkey_t **ibpkey2);
#endif
diff --git a/libsemanage/src/ibpkey_record.c b/libsemanage/src/ibpkey_record.c
index ca5bc76d..bb7fa6ea 100644
--- a/libsemanage/src/ibpkey_record.c
+++ b/libsemanage/src/ibpkey_record.c
@@ -29,7 +29,6 @@ int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
return sepol_ibpkey_compare(ibpkey, key);
}
-hidden_def(semanage_ibpkey_compare)
int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
const semanage_ibpkey_t *ibpkey2)
@@ -37,9 +36,8 @@ int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
return sepol_ibpkey_compare2(ibpkey, ibpkey2);
}
-hidden_def(semanage_ibpkey_compare2)
-hidden int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t **ibpkey,
+ int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t **ibpkey,
const semanage_ibpkey_t **ibpkey2)
{
return sepol_ibpkey_compare2(*ibpkey, *ibpkey2);
@@ -60,14 +58,12 @@ int semanage_ibpkey_key_extract(semanage_handle_t *handle,
return sepol_ibpkey_key_extract(handle->sepolh, ibpkey, key_ptr);
}
-hidden_def(semanage_ibpkey_key_extract)
void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key)
{
sepol_ibpkey_key_free(key);
}
-hidden_def(semanage_ibpkey_key_free)
int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle,
const semanage_ibpkey_t *ibpkey,
@@ -76,14 +72,12 @@ int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle,
return sepol_ibpkey_get_subnet_prefix(handle->sepolh, ibpkey, subnet_prefix_ptr);
}
-hidden_def(semanage_ibpkey_get_subnet_prefix)
uint64_t semanage_ibpkey_get_subnet_prefix_bytes(const semanage_ibpkey_t *ibpkey)
{
return sepol_ibpkey_get_subnet_prefix_bytes(ibpkey);
}
-hidden_def(semanage_ibpkey_get_subnet_prefix_bytes)
int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle,
semanage_ibpkey_t *ibpkey,
@@ -92,7 +86,6 @@ int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle,
return sepol_ibpkey_set_subnet_prefix(handle->sepolh, ibpkey, subnet_prefix);
}
-hidden_def(semanage_ibpkey_set_subnet_prefix)
void semanage_ibpkey_set_subnet_prefix_bytes(semanage_ibpkey_t *ibpkey,
uint64_t subnet_prefix)
@@ -100,42 +93,36 @@ void semanage_ibpkey_set_subnet_prefix_bytes(semanage_ibpkey_t *ibpkey,
return sepol_ibpkey_set_subnet_prefix_bytes(ibpkey, subnet_prefix);
}
-hidden_def(semanage_ibpkey_set_subnet_prefix_bytes)
int semanage_ibpkey_get_low(const semanage_ibpkey_t *ibpkey)
{
return sepol_ibpkey_get_low(ibpkey);
}
-hidden_def(semanage_ibpkey_get_low)
int semanage_ibpkey_get_high(const semanage_ibpkey_t *ibpkey)
{
return sepol_ibpkey_get_high(ibpkey);
}
-hidden_def(semanage_ibpkey_get_high)
void semanage_ibpkey_set_pkey(semanage_ibpkey_t *ibpkey, int ibpkey_num)
{
sepol_ibpkey_set_pkey(ibpkey, ibpkey_num);
}
-hidden_def(semanage_ibpkey_set_pkey)
void semanage_ibpkey_set_range(semanage_ibpkey_t *ibpkey, int low, int high)
{
sepol_ibpkey_set_range(ibpkey, low, high);
}
-hidden_def(semanage_ibpkey_set_range)
semanage_context_t *semanage_ibpkey_get_con(const semanage_ibpkey_t *ibpkey)
{
return sepol_ibpkey_get_con(ibpkey);
}
-hidden_def(semanage_ibpkey_get_con)
int semanage_ibpkey_set_con(semanage_handle_t *handle,
semanage_ibpkey_t *ibpkey, semanage_context_t *con)
@@ -143,7 +130,6 @@ int semanage_ibpkey_set_con(semanage_handle_t *handle,
return sepol_ibpkey_set_con(handle->sepolh, ibpkey, con);
}
-hidden_def(semanage_ibpkey_set_con)
int semanage_ibpkey_create(semanage_handle_t *handle,
semanage_ibpkey_t **ibpkey_ptr)
@@ -151,7 +137,6 @@ int semanage_ibpkey_create(semanage_handle_t *handle,
return sepol_ibpkey_create(handle->sepolh, ibpkey_ptr);
}
-hidden_def(semanage_ibpkey_create)
int semanage_ibpkey_clone(semanage_handle_t *handle,
const semanage_ibpkey_t *ibpkey,
@@ -160,14 +145,12 @@ int semanage_ibpkey_clone(semanage_handle_t *handle,
return sepol_ibpkey_clone(handle->sepolh, ibpkey, ibpkey_ptr);
}
-hidden_def(semanage_ibpkey_clone)
void semanage_ibpkey_free(semanage_ibpkey_t *ibpkey)
{
sepol_ibpkey_free(ibpkey);
}
-hidden_def(semanage_ibpkey_free)
/* key base functions */
record_table_t SEMANAGE_IBPKEY_RTABLE = {
diff --git a/libsemanage/src/ibpkeys_file.c b/libsemanage/src/ibpkeys_file.c
index ceaea7ad..edde69f0 100644
--- a/libsemanage/src/ibpkeys_file.c
+++ b/libsemanage/src/ibpkeys_file.c
@@ -15,7 +15,6 @@ typedef struct dbase_file dbase_t;
#include <strings.h>
#include <semanage/handle.h>
#include "ibpkey_internal.h"
-#include "context_internal.h"
#include "database_file.h"
#include "parse_utils.h"
#include "debug.h"
@@ -81,7 +80,7 @@ static int ibpkey_parse(semanage_handle_t *handle,
goto err;
/* Subnet Prefix */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_ibpkey_set_subnet_prefix(handle, ibpkey, str) < 0)
goto err;
@@ -116,7 +115,7 @@ static int ibpkey_parse(semanage_handle_t *handle,
semanage_ibpkey_set_pkey(ibpkey, low);
}
/* Pkey context */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_context_from_string(handle, str, &con) < 0) {
ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
diff --git a/libsemanage/src/ibpkeys_local.c b/libsemanage/src/ibpkeys_local.c
index e194ee01..6d05d125 100644
--- a/libsemanage/src/ibpkeys_local.c
+++ b/libsemanage/src/ibpkeys_local.c
@@ -74,9 +74,8 @@ int semanage_ibpkey_list_local(semanage_handle_t *handle,
return dbase_list(handle, dconfig, records, count);
}
-hidden_def(semanage_ibpkey_list_local)
-int hidden semanage_ibpkey_validate_local(semanage_handle_t *handle)
+int semanage_ibpkey_validate_local(semanage_handle_t *handle)
{
semanage_ibpkey_t **ibpkeys = NULL;
unsigned int nibpkeys = 0;
diff --git a/libsemanage/src/iface_internal.h b/libsemanage/src/iface_internal.h
index 5cb77789..df38fb0f 100644
--- a/libsemanage/src/iface_internal.h
+++ b/libsemanage/src/iface_internal.h
@@ -6,21 +6,6 @@
#include <semanage/interfaces_policy.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_iface_create)
- hidden_proto(semanage_iface_compare)
- hidden_proto(semanage_iface_compare2)
- hidden_proto(semanage_iface_clone)
- hidden_proto(semanage_iface_free)
- hidden_proto(semanage_iface_get_ifcon)
- hidden_proto(semanage_iface_get_msgcon)
- hidden_proto(semanage_iface_get_name)
- hidden_proto(semanage_iface_key_extract)
- hidden_proto(semanage_iface_key_free)
- hidden_proto(semanage_iface_set_ifcon)
- hidden_proto(semanage_iface_set_msgcon)
- hidden_proto(semanage_iface_set_name)
/* IFACE RECORD: method table */
extern record_table_t SEMANAGE_IFACE_RTABLE;
diff --git a/libsemanage/src/iface_record.c b/libsemanage/src/iface_record.c
index e7d72d75..e54cdd2d 100644
--- a/libsemanage/src/iface_record.c
+++ b/libsemanage/src/iface_record.c
@@ -31,7 +31,6 @@ int semanage_iface_compare(const semanage_iface_t * iface,
return sepol_iface_compare(iface, key);
}
-hidden_def(semanage_iface_compare)
int semanage_iface_compare2(const semanage_iface_t * iface,
const semanage_iface_t * iface2)
@@ -40,7 +39,6 @@ int semanage_iface_compare2(const semanage_iface_t * iface,
return sepol_iface_compare2(iface, iface2);
}
-hidden_def(semanage_iface_compare2)
static int semanage_iface_compare2_qsort(const semanage_iface_t ** iface,
const semanage_iface_t ** iface2)
@@ -64,7 +62,6 @@ int semanage_iface_key_extract(semanage_handle_t * handle,
return sepol_iface_key_extract(handle->sepolh, iface, key_ptr);
}
-hidden_def(semanage_iface_key_extract)
void semanage_iface_key_free(semanage_iface_key_t * key)
{
@@ -72,7 +69,6 @@ void semanage_iface_key_free(semanage_iface_key_t * key)
sepol_iface_key_free(key);
}
-hidden_def(semanage_iface_key_free)
/* Name */
const char *semanage_iface_get_name(const semanage_iface_t * iface)
@@ -81,7 +77,6 @@ const char *semanage_iface_get_name(const semanage_iface_t * iface)
return sepol_iface_get_name(iface);
}
-hidden_def(semanage_iface_get_name)
int semanage_iface_set_name(semanage_handle_t * handle,
semanage_iface_t * iface, const char *name)
@@ -90,7 +85,6 @@ int semanage_iface_set_name(semanage_handle_t * handle,
return sepol_iface_set_name(handle->sepolh, iface, name);
}
-hidden_def(semanage_iface_set_name)
/* Context */
semanage_context_t *semanage_iface_get_ifcon(const semanage_iface_t * iface)
@@ -99,7 +93,6 @@ semanage_context_t *semanage_iface_get_ifcon(const semanage_iface_t * iface)
return sepol_iface_get_ifcon(iface);
}
-hidden_def(semanage_iface_get_ifcon)
int semanage_iface_set_ifcon(semanage_handle_t * handle,
semanage_iface_t * iface, semanage_context_t * con)
@@ -108,7 +101,6 @@ int semanage_iface_set_ifcon(semanage_handle_t * handle,
return sepol_iface_set_ifcon(handle->sepolh, iface, con);
}
-hidden_def(semanage_iface_set_ifcon)
semanage_context_t *semanage_iface_get_msgcon(const semanage_iface_t * iface)
{
@@ -116,7 +108,6 @@ semanage_context_t *semanage_iface_get_msgcon(const semanage_iface_t * iface)
return sepol_iface_get_msgcon(iface);
}
-hidden_def(semanage_iface_get_msgcon)
int semanage_iface_set_msgcon(semanage_handle_t * handle,
semanage_iface_t * iface,
@@ -126,7 +117,6 @@ int semanage_iface_set_msgcon(semanage_handle_t * handle,
return sepol_iface_set_msgcon(handle->sepolh, iface, con);
}
-hidden_def(semanage_iface_set_msgcon)
/* Create/Clone/Destroy */
int semanage_iface_create(semanage_handle_t * handle,
@@ -136,7 +126,6 @@ int semanage_iface_create(semanage_handle_t * handle,
return sepol_iface_create(handle->sepolh, iface_ptr);
}
-hidden_def(semanage_iface_create)
int semanage_iface_clone(semanage_handle_t * handle,
const semanage_iface_t * iface,
@@ -146,7 +135,6 @@ int semanage_iface_clone(semanage_handle_t * handle,
return sepol_iface_clone(handle->sepolh, iface, iface_ptr);
}
-hidden_def(semanage_iface_clone)
void semanage_iface_free(semanage_iface_t * iface)
{
@@ -154,7 +142,6 @@ void semanage_iface_free(semanage_iface_t * iface)
sepol_iface_free(iface);
}
-hidden_def(semanage_iface_free)
/* Record base functions */
record_table_t SEMANAGE_IFACE_RTABLE = {
diff --git a/libsemanage/src/interfaces_file.c b/libsemanage/src/interfaces_file.c
index 1478af97..244f0ae5 100644
--- a/libsemanage/src/interfaces_file.c
+++ b/libsemanage/src/interfaces_file.c
@@ -14,7 +14,6 @@ typedef struct dbase_file dbase_t;
#include <stdio.h>
#include <semanage/handle.h>
#include "iface_internal.h"
-#include "context_internal.h"
#include "database_file.h"
#include "parse_utils.h"
#include "debug.h"
@@ -73,7 +72,7 @@ static int iface_parse(semanage_handle_t * handle,
goto err;
/* Name */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_iface_set_name(handle, iface, str) < 0)
goto err;
@@ -83,7 +82,7 @@ static int iface_parse(semanage_handle_t * handle,
/* Interface context */
if (parse_assert_space(handle, info) < 0)
goto err;
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_context_from_string(handle, str, &con) < 0) {
ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
@@ -107,7 +106,7 @@ static int iface_parse(semanage_handle_t * handle,
/* Message context */
if (parse_assert_space(handle, info) < 0)
goto err;
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_context_from_string(handle, str, &con) < 0) {
ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
index 02036696..c8214b26 100644
--- a/libsemanage/src/libsemanage.map
+++ b/libsemanage/src/libsemanage.map
@@ -1,65 +1,352 @@
LIBSEMANAGE_1.0 {
- global: semanage_handle_create; semanage_handle_destroy;
- semanage_is_managed; semanage_connect; semanage_disconnect;
- semanage_msg_*;
- semanage_begin_transaction; semanage_commit;
- semanage_module_install; semanage_module_install_file;
- semanage_module_upgrade; semanage_module_upgrade_file;
- semanage_module_install_base; semanage_module_install_base_file;
- semanage_module_enable;
- semanage_module_disable;
- semanage_module_remove;
- semanage_module_list; semanage_module_info_datum_destroy;
- semanage_module_list_nth; semanage_module_get_name;
- semanage_module_get_version; semanage_select_store;
- semanage_module_get_enabled;
- semanage_reload_policy; semanage_set_reload; semanage_set_rebuild;
- semanage_set_root;
- semanage_root;
- semanage_user_*; semanage_bool_*; semanage_seuser_*;
- semanage_iface_*; semanage_port_*; semanage_context_*;
- semanage_ibpkey_*;
- semanage_ibendport_*;
- semanage_node_*;
- semanage_fcontext_*; semanage_access_check; semanage_set_create_store;
- semanage_is_connected; semanage_get_disable_dontaudit; semanage_set_disable_dontaudit;
- semanage_mls_enabled;
- semanage_set_check_contexts;
- semanage_get_preserve_tunables; semanage_set_preserve_tunables;
+ global:
+ semanage_access_check;
+ semanage_begin_transaction;
+ semanage_bool_clone;
+ semanage_bool_compare;
+ semanage_bool_compare2;
+ semanage_bool_count;
+ semanage_bool_count_active;
+ semanage_bool_count_local;
+ semanage_bool_create;
+ semanage_bool_del_local;
+ semanage_bool_exists;
+ semanage_bool_exists_active;
+ semanage_bool_exists_local;
+ semanage_bool_free;
+ semanage_bool_get_name;
+ semanage_bool_get_value;
+ semanage_bool_iterate;
+ semanage_bool_iterate_active;
+ semanage_bool_iterate_local;
+ semanage_bool_key_create;
+ semanage_bool_key_extract;
+ semanage_bool_key_free;
+ semanage_bool_list;
+ semanage_bool_list_active;
+ semanage_bool_list_local;
+ semanage_bool_modify_local;
+ semanage_bool_query;
+ semanage_bool_query_active;
+ semanage_bool_query_local;
+ semanage_bool_set_active;
+ semanage_bool_set_name;
+ semanage_bool_set_value;
+ semanage_commit;
+ semanage_connect;
+ semanage_context_clone;
+ semanage_context_create;
+ semanage_context_free;
+ semanage_context_from_string;
+ semanage_context_get_mls;
+ semanage_context_get_role;
+ semanage_context_get_type;
+ semanage_context_get_user;
+ semanage_context_set_mls;
+ semanage_context_set_role;
+ semanage_context_set_type;
+ semanage_context_set_user;
+ semanage_context_to_string;
+ semanage_disconnect;
+ semanage_fcontext_clone;
+ semanage_fcontext_compare;
+ semanage_fcontext_compare2;
+ semanage_fcontext_count;
+ semanage_fcontext_count_local;
+ semanage_fcontext_create;
+ semanage_fcontext_del_local;
+ semanage_fcontext_exists;
+ semanage_fcontext_exists_local;
+ semanage_fcontext_free;
+ semanage_fcontext_get_con;
+ semanage_fcontext_get_expr;
+ semanage_fcontext_get_type;
+ semanage_fcontext_get_type_str;
+ semanage_fcontext_iterate;
+ semanage_fcontext_iterate_local;
+ semanage_fcontext_key_create;
+ semanage_fcontext_key_extract;
+ semanage_fcontext_key_free;
+ semanage_fcontext_list;
+ semanage_fcontext_list_homedirs;
+ semanage_fcontext_list_local;
+ semanage_fcontext_modify_local;
+ semanage_fcontext_query;
+ semanage_fcontext_query_local;
+ semanage_fcontext_set_con;
+ semanage_fcontext_set_expr;
+ semanage_fcontext_set_type;
+ semanage_get_disable_dontaudit;
+ semanage_get_preserve_tunables;
+ semanage_handle_create;
+ semanage_handle_destroy;
+ semanage_ibendport_clone;
+ semanage_ibendport_compare;
+ semanage_ibendport_compare2;
+ semanage_ibendport_count;
+ semanage_ibendport_count_local;
+ semanage_ibendport_create;
+ semanage_ibendport_del_local;
+ semanage_ibendport_exists;
+ semanage_ibendport_exists_local;
+ semanage_ibendport_free;
+ semanage_ibendport_get_con;
+ semanage_ibendport_get_ibdev_name;
+ semanage_ibendport_get_port;
+ semanage_ibendport_iterate;
+ semanage_ibendport_iterate_local;
+ semanage_ibendport_key_create;
+ semanage_ibendport_key_extract;
+ semanage_ibendport_key_free;
+ semanage_ibendport_list;
+ semanage_ibendport_list_local;
+ semanage_ibendport_modify_local;
+ semanage_ibendport_query;
+ semanage_ibendport_query_local;
+ semanage_ibendport_set_con;
+ semanage_ibendport_set_ibdev_name;
+ semanage_ibendport_set_port;
+ semanage_ibpkey_clone;
+ semanage_ibpkey_compare;
+ semanage_ibpkey_compare2;
+ semanage_ibpkey_count;
+ semanage_ibpkey_count_local;
+ semanage_ibpkey_create;
+ semanage_ibpkey_del_local;
+ semanage_ibpkey_exists;
+ semanage_ibpkey_exists_local;
+ semanage_ibpkey_free;
+ semanage_ibpkey_get_con;
+ semanage_ibpkey_get_high;
+ semanage_ibpkey_get_low;
+ semanage_ibpkey_get_subnet_prefix;
+ semanage_ibpkey_get_subnet_prefix_bytes;
+ semanage_ibpkey_iterate;
+ semanage_ibpkey_iterate_local;
+ semanage_ibpkey_key_create;
+ semanage_ibpkey_key_extract;
+ semanage_ibpkey_key_free;
+ semanage_ibpkey_list;
+ semanage_ibpkey_list_local;
+ semanage_ibpkey_modify_local;
+ semanage_ibpkey_query;
+ semanage_ibpkey_query_local;
+ semanage_ibpkey_set_con;
+ semanage_ibpkey_set_pkey;
+ semanage_ibpkey_set_range;
+ semanage_ibpkey_set_subnet_prefix;
+ semanage_ibpkey_set_subnet_prefix_bytes;
+ semanage_iface_clone;
+ semanage_iface_compare;
+ semanage_iface_compare2;
+ semanage_iface_count;
+ semanage_iface_count_local;
+ semanage_iface_create;
+ semanage_iface_del_local;
+ semanage_iface_exists;
+ semanage_iface_exists_local;
+ semanage_iface_free;
+ semanage_iface_get_ifcon;
+ semanage_iface_get_msgcon;
+ semanage_iface_get_name;
+ semanage_iface_iterate;
+ semanage_iface_iterate_local;
+ semanage_iface_key_create;
+ semanage_iface_key_extract;
+ semanage_iface_key_free;
+ semanage_iface_list;
+ semanage_iface_list_local;
+ semanage_iface_modify_local;
+ semanage_iface_query;
+ semanage_iface_query_local;
+ semanage_iface_set_ifcon;
+ semanage_iface_set_msgcon;
+ semanage_iface_set_name;
+ semanage_is_connected;
+ semanage_is_managed;
+ semanage_mls_enabled;
+ semanage_module_get_name;
+ semanage_module_get_version;
+ semanage_module_info_datum_destroy;
+ semanage_module_install_file;
+ semanage_module_list;
+ semanage_module_list_nth;
+ semanage_module_remove;
+ semanage_module_upgrade_file;
+ semanage_msg_get_channel;
+ semanage_msg_get_fname;
+ semanage_msg_get_level;
+ semanage_msg_set_callback;
+ semanage_node_clone;
+ semanage_node_compare;
+ semanage_node_compare2;
+ semanage_node_count;
+ semanage_node_count_local;
+ semanage_node_create;
+ semanage_node_del_local;
+ semanage_node_exists;
+ semanage_node_exists_local;
+ semanage_node_free;
+ semanage_node_get_addr;
+ semanage_node_get_addr_bytes;
+ semanage_node_get_con;
+ semanage_node_get_mask;
+ semanage_node_get_mask_bytes;
+ semanage_node_get_proto;
+ semanage_node_get_proto_str;
+ semanage_node_iterate;
+ semanage_node_iterate_local;
+ semanage_node_key_create;
+ semanage_node_key_extract;
+ semanage_node_key_free;
+ semanage_node_list;
+ semanage_node_list_local;
+ semanage_node_modify_local;
+ semanage_node_query;
+ semanage_node_query_local;
+ semanage_node_set_addr;
+ semanage_node_set_addr_bytes;
+ semanage_node_set_con;
+ semanage_node_set_mask;
+ semanage_node_set_mask_bytes;
+ semanage_node_set_proto;
+ semanage_port_clone;
+ semanage_port_compare;
+ semanage_port_compare2;
+ semanage_port_count;
+ semanage_port_count_local;
+ semanage_port_create;
+ semanage_port_del_local;
+ semanage_port_exists;
+ semanage_port_exists_local;
+ semanage_port_free;
+ semanage_port_get_con;
+ semanage_port_get_high;
+ semanage_port_get_low;
+ semanage_port_get_proto;
+ semanage_port_get_proto_str;
+ semanage_port_iterate;
+ semanage_port_iterate_local;
+ semanage_port_key_create;
+ semanage_port_key_extract;
+ semanage_port_key_free;
+ semanage_port_list;
+ semanage_port_list_local;
+ semanage_port_modify_local;
+ semanage_port_query;
+ semanage_port_query_local;
+ semanage_port_set_con;
+ semanage_port_set_port;
+ semanage_port_set_proto;
+ semanage_port_set_range;
+ semanage_reload_policy;
+ semanage_root;
+ semanage_select_store;
+ semanage_set_check_contexts;
+ semanage_set_create_store;
+ semanage_set_disable_dontaudit;
+ semanage_set_preserve_tunables;
+ semanage_set_rebuild;
+ semanage_set_reload;
+ semanage_set_root;
+ semanage_seuser_clone;
+ semanage_seuser_compare;
+ semanage_seuser_compare2;
+ semanage_seuser_count;
+ semanage_seuser_count_local;
+ semanage_seuser_create;
+ semanage_seuser_del_local;
+ semanage_seuser_exists;
+ semanage_seuser_exists_local;
+ semanage_seuser_free;
+ semanage_seuser_get_mlsrange;
+ semanage_seuser_get_name;
+ semanage_seuser_get_sename;
+ semanage_seuser_iterate;
+ semanage_seuser_iterate_local;
+ semanage_seuser_key_create;
+ semanage_seuser_key_extract;
+ semanage_seuser_key_free;
+ semanage_seuser_list;
+ semanage_seuser_list_local;
+ semanage_seuser_modify_local;
+ semanage_seuser_query;
+ semanage_seuser_query_local;
+ semanage_seuser_set_mlsrange;
+ semanage_seuser_set_name;
+ semanage_seuser_set_sename;
+ semanage_user_add_role;
+ semanage_user_clone;
+ semanage_user_compare;
+ semanage_user_compare2;
+ semanage_user_count;
+ semanage_user_count_local;
+ semanage_user_create;
+ semanage_user_del_local;
+ semanage_user_del_role;
+ semanage_user_exists;
+ semanage_user_exists_local;
+ semanage_user_free;
+ semanage_user_get_mlslevel;
+ semanage_user_get_mlsrange;
+ semanage_user_get_name;
+ semanage_user_get_num_roles;
+ semanage_user_get_prefix;
+ semanage_user_get_roles;
+ semanage_user_has_role;
+ semanage_user_iterate;
+ semanage_user_iterate_local;
+ semanage_user_key_create;
+ semanage_user_key_extract;
+ semanage_user_key_free;
+ semanage_user_list;
+ semanage_user_list_local;
+ semanage_user_modify_local;
+ semanage_user_query;
+ semanage_user_query_local;
+ semanage_user_set_mlslevel;
+ semanage_user_set_mlsrange;
+ semanage_user_set_name;
+ semanage_user_set_prefix;
+ semanage_user_set_roles;
local: *;
};
LIBSEMANAGE_1.1 {
global:
- semanage_module_install;
- semanage_module_extract;
- semanage_get_hll_compiler_path;
- semanage_get_ignore_module_cache;
- semanage_set_ignore_module_cache;
- semanage_get_default_priority;
- semanage_set_default_priority;
- semanage_module_info_create;
- semanage_module_info_destroy;
- semanage_module_info_get_priority;
- semanage_module_info_get_name;
- semanage_module_info_get_lang_ext;
- semanage_module_info_get_enabled;
- semanage_module_info_set_priority;
- semanage_module_info_set_name;
- semanage_module_info_set_lang_ext;
- semanage_module_info_set_enabled;
- semanage_module_key_create;
- semanage_module_key_destroy;
- semanage_module_key_get_priority;
- semanage_module_key_get_name;
- semanage_module_key_set_priority;
- semanage_module_key_set_name;
- semanage_module_get_module_info;
- semanage_module_list_all;
- semanage_module_get_enabled;
- semanage_module_set_enabled;
- semanage_module_install_info;
- semanage_module_upgrade_info;
- semanage_module_remove_key;
- semanage_set_store_root;
+ semanage_module_install;
+ semanage_module_extract;
+ semanage_get_hll_compiler_path;
+ semanage_get_ignore_module_cache;
+ semanage_set_ignore_module_cache;
+ semanage_get_default_priority;
+ semanage_set_default_priority;
+ semanage_module_info_create;
+ semanage_module_info_destroy;
+ semanage_module_info_get_priority;
+ semanage_module_info_get_name;
+ semanage_module_info_get_lang_ext;
+ semanage_module_info_get_enabled;
+ semanage_module_info_set_priority;
+ semanage_module_info_set_name;
+ semanage_module_info_set_lang_ext;
+ semanage_module_info_set_enabled;
+ semanage_module_key_create;
+ semanage_module_key_destroy;
+ semanage_module_key_get_priority;
+ semanage_module_key_get_name;
+ semanage_module_key_set_priority;
+ semanage_module_key_set_name;
+ semanage_module_get_module_info;
+ semanage_module_list_all;
+ semanage_module_get_enabled;
+ semanage_module_set_enabled;
+ semanage_module_install_info;
+ semanage_module_remove_key;
+ semanage_set_store_root;
} LIBSEMANAGE_1.0;
+
+LIBSEMANAGE_3.4 {
+ semanage_module_compute_checksum;
+ semanage_set_check_ext_changes;
+} LIBSEMANAGE_1.1;
diff --git a/libsemanage/src/module_internal.h b/libsemanage/src/module_internal.h
deleted file mode 100644
index c99f6c28..00000000
--- a/libsemanage/src/module_internal.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _SEMANAGE_MODULE_INTERNAL_H_
-#define _SEMANAGE_MODULE_INTERNAL_H_
-
-#include <semanage/modules.h>
-#include "dso.h"
-
-hidden_proto(semanage_module_get_name)
- hidden_proto(semanage_module_info_datum_destroy)
- hidden_proto(semanage_module_list_nth)
- hidden_proto(semanage_module_info_create)
- hidden_proto(semanage_module_info_destroy)
- hidden_proto(semanage_module_info_get_priority)
- hidden_proto(semanage_module_info_get_name)
- hidden_proto(semanage_module_info_get_lang_ext)
- hidden_proto(semanage_module_info_get_enabled)
- hidden_proto(semanage_module_info_set_priority)
- hidden_proto(semanage_module_info_set_name)
- hidden_proto(semanage_module_info_set_lang_ext)
- hidden_proto(semanage_module_info_set_enabled)
- hidden_proto(semanage_module_key_create)
- hidden_proto(semanage_module_key_destroy)
- hidden_proto(semanage_module_key_get_priority)
- hidden_proto(semanage_module_key_get_name)
- hidden_proto(semanage_module_key_set_priority)
- hidden_proto(semanage_module_key_set_name)
- hidden_proto(semanage_module_set_enabled)
-#endif
diff --git a/libsemanage/src/modules.c b/libsemanage/src/modules.c
index 19043505..c3bd90ac 100644
--- a/libsemanage/src/modules.c
+++ b/libsemanage/src/modules.c
@@ -22,6 +22,7 @@
/* This file implements only the publicly-visible module functions to libsemanage. */
#include "direct_api.h"
+#include "modules.h"
#include "semanage_conf.h"
#include "semanage_store.h"
@@ -34,77 +35,16 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include <errno.h>
#include <ctype.h>
#include "handle.h"
#include "modules.h"
+#include "sha256.h"
#include "debug.h"
-asm(".symver semanage_module_get_enabled_1_1,semanage_module_get_enabled@@LIBSEMANAGE_1.1");
-asm(".symver semanage_module_get_enabled_1_0,semanage_module_get_enabled@LIBSEMANAGE_1.0");
-asm(".symver semanage_module_install_pp,semanage_module_install@LIBSEMANAGE_1.0");
-asm(".symver semanage_module_install_hll,semanage_module_install@@LIBSEMANAGE_1.1");
-
-/* Takes a module stored in 'module_data' and parses its headers.
- * Sets reference variables 'module_name' to module's name and
- * 'version' to module's version. The caller is responsible for
- * free()ing 'module_name' and 'version'; they will be
- * set to NULL upon entering this function. Returns 0 on success, -1
- * if out of memory, or -2 if data did not represent a module.
- */
-static int parse_module_headers(semanage_handle_t * sh, char *module_data,
- size_t data_len, char **module_name, char **version)
-{
- struct sepol_policy_file *pf;
- int file_type;
- *version = NULL;
-
- if (sepol_policy_file_create(&pf)) {
- ERR(sh, "Out of memory!");
- return -1;
- }
- sepol_policy_file_set_mem(pf, module_data, data_len);
- sepol_policy_file_set_handle(pf, sh->sepolh);
- if (module_data == NULL ||
- data_len == 0 ||
- sepol_module_package_info(pf, &file_type, module_name, version) == -1) {
- sepol_policy_file_free(pf);
- ERR(sh, "Could not parse module data.");
- return -2;
- }
- sepol_policy_file_free(pf);
- if (file_type != SEPOL_POLICY_MOD) {
- ERR(sh, "Data did not represent a pp module. Please upgrade to the latest version of libsemanage to support hll modules.");
- return -2;
- }
-
- return 0;
-}
-
-/* This function is used to preserve ABI compatibility with
- * versions of semodule using LIBSEMANAGE_1.0
- */
-int semanage_module_install_pp(semanage_handle_t * sh,
- char *module_data, size_t data_len)
-{
- char *name = NULL;
- char *version = NULL;
- int status;
-
- if ((status = parse_module_headers(sh, module_data, data_len, &name, &version)) != 0) {
- goto cleanup;
- }
-
- status = semanage_module_install_hll(sh, module_data, data_len, name, "pp");
-
-cleanup:
- free(name);
- free(version);
- return status;
-}
-
-int semanage_module_install_hll(semanage_handle_t * sh,
+int semanage_module_install(semanage_handle_t * sh,
char *module_data, size_t data_len, const char *name, const char *ext_lang)
{
if (sh->funcs->install == NULL) {
@@ -160,16 +100,6 @@ int semanage_module_extract(semanage_handle_t * sh,
}
/* Legacy function that remains to preserve ABI
- * compatibility. Please use semanage_module_install instead.
- */
-int semanage_module_upgrade(semanage_handle_t * sh,
- char *module_data, size_t data_len)
-{
- return semanage_module_install_pp(sh, module_data, data_len);
-
-}
-
-/* Legacy function that remains to preserve ABI
* compatibility. Please use semanage_module_install_file instead.
*/
int semanage_module_upgrade_file(semanage_handle_t * sh,
@@ -178,24 +108,6 @@ int semanage_module_upgrade_file(semanage_handle_t * sh,
return semanage_module_install_file(sh, module_name);
}
-/* Legacy function that remains to preserve ABI
- * compatibility. Please use semanage_module_install instead.
- */
-int semanage_module_install_base(semanage_handle_t * sh,
- char *module_data, size_t data_len)
-{
- return semanage_module_install_pp(sh, module_data, data_len);
-}
-
-/* Legacy function that remains to preserve ABI
- * compatibility. Please use semanage_module_install_file instead.
- */
-int semanage_module_install_base_file(semanage_handle_t * sh,
- const char *module_name)
-{
- return semanage_module_install_file(sh, module_name);
-}
-
int semanage_module_remove(semanage_handle_t * sh, char *module_name)
{
if (sh->funcs->remove == NULL) {
@@ -241,7 +153,6 @@ void semanage_module_info_datum_destroy(semanage_module_info_t * modinfo)
}
}
-hidden_def(semanage_module_info_datum_destroy)
semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list,
int n)
@@ -249,18 +160,17 @@ semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list,
return list + n;
}
-hidden_def(semanage_module_list_nth)
const char *semanage_module_get_name(semanage_module_info_t * modinfo)
{
return modinfo->name;
}
-hidden_def(semanage_module_get_name)
/* Legacy function that remains to preserve ABI
* compatibility.
*/
+extern const char *semanage_module_get_version(semanage_module_info_t *);
const char *semanage_module_get_version(semanage_module_info_t * modinfo
__attribute__ ((unused)))
{
@@ -279,7 +189,6 @@ int semanage_module_info_create(semanage_handle_t *sh,
return semanage_module_info_init(sh, *modinfo);
}
-hidden_def(semanage_module_info_create)
int semanage_module_info_destroy(semanage_handle_t *sh,
semanage_module_info_t *modinfo)
@@ -296,7 +205,6 @@ int semanage_module_info_destroy(semanage_handle_t *sh,
return semanage_module_info_init(sh, modinfo);
}
-hidden_def(semanage_module_info_destroy)
int semanage_module_info_init(semanage_handle_t *sh,
semanage_module_info_t *modinfo)
@@ -371,7 +279,6 @@ int semanage_module_info_get_priority(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_info_get_priority)
int semanage_module_info_get_name(semanage_handle_t *sh,
semanage_module_info_t *modinfo,
@@ -386,7 +293,6 @@ int semanage_module_info_get_name(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_info_get_name)
int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
semanage_module_info_t *modinfo,
@@ -401,7 +307,6 @@ int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_info_get_lang_ext)
int semanage_module_info_get_enabled(semanage_handle_t *sh,
semanage_module_info_t *modinfo,
@@ -416,7 +321,6 @@ int semanage_module_info_get_enabled(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_info_get_enabled)
int semanage_module_info_set_priority(semanage_handle_t *sh,
semanage_module_info_t *modinfo,
@@ -437,7 +341,6 @@ int semanage_module_info_set_priority(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_info_set_priority)
int semanage_module_info_set_name(semanage_handle_t *sh,
semanage_module_info_t *modinfo,
@@ -468,7 +371,6 @@ int semanage_module_info_set_name(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_info_set_name)
int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
semanage_module_info_t *modinfo,
@@ -499,7 +401,6 @@ int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_info_set_lang_ext)
int semanage_module_info_set_enabled(semanage_handle_t *sh,
semanage_module_info_t *modinfo,
@@ -520,7 +421,6 @@ int semanage_module_info_set_enabled(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_info_set_enabled)
int semanage_module_get_path(semanage_handle_t *sh,
const semanage_module_info_t *modinfo,
@@ -685,7 +585,6 @@ int semanage_module_key_create(semanage_handle_t *sh,
return semanage_module_key_init(sh, *modkey);
}
-hidden_def(semanage_module_key_create)
int semanage_module_key_destroy(semanage_handle_t *sh,
semanage_module_key_t *modkey)
@@ -701,7 +600,6 @@ int semanage_module_key_destroy(semanage_handle_t *sh,
return semanage_module_key_init(sh, modkey);
}
-hidden_def(semanage_module_key_destroy)
int semanage_module_key_init(semanage_handle_t *sh,
semanage_module_key_t *modkey)
@@ -728,7 +626,6 @@ int semanage_module_key_get_name(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_key_get_name)
int semanage_module_key_get_priority(semanage_handle_t *sh,
semanage_module_key_t *modkey,
@@ -743,7 +640,6 @@ int semanage_module_key_get_priority(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_key_get_priority)
int semanage_module_key_set_name(semanage_handle_t *sh,
semanage_module_key_t *modkey,
@@ -776,7 +672,6 @@ cleanup:
return status;
}
-hidden_def(semanage_module_key_set_name)
int semanage_module_key_set_priority(semanage_handle_t *sh,
semanage_module_key_t *modkey,
@@ -796,9 +691,8 @@ int semanage_module_key_set_priority(semanage_handle_t *sh,
return 0;
}
-hidden_def(semanage_module_key_set_priority)
-int semanage_module_get_enabled_1_1(semanage_handle_t *sh,
+int semanage_module_get_enabled(semanage_handle_t *sh,
const semanage_module_key_t *modkey,
int *enabled)
{
@@ -818,11 +712,6 @@ int semanage_module_get_enabled_1_1(semanage_handle_t *sh,
return sh->funcs->get_enabled(sh, modkey, enabled);
}
-int semanage_module_get_enabled_1_0(semanage_module_info_t *modinfo)
-{
- return modinfo->enabled;
-}
-
int semanage_module_set_enabled(semanage_handle_t *sh,
const semanage_module_key_t *modkey,
int enabled)
@@ -847,63 +736,6 @@ int semanage_module_set_enabled(semanage_handle_t *sh,
return sh->funcs->set_enabled(sh, modkey, enabled);
}
-hidden_def(semanage_module_set_enabled)
-
-/* This function exists only for ABI compatibility. It has been deprecated and
- * should not be used. Instead, use semanage_module_set_enabled() */
-int semanage_module_enable(semanage_handle_t *sh, char *module_name)
-{
- int rc = -1;
- semanage_module_key_t *modkey = NULL;
-
- rc = semanage_module_key_create(sh, &modkey);
- if (rc != 0)
- goto exit;
-
- rc = semanage_module_key_set_name(sh, modkey, module_name);
- if (rc != 0)
- goto exit;
-
- rc = semanage_module_set_enabled(sh, modkey, 1);
- if (rc != 0)
- goto exit;
-
- rc = 0;
-
-exit:
- semanage_module_key_destroy(sh, modkey);
- free(modkey);
-
- return rc;
-}
-
-/* This function exists only for ABI compatibility. It has been deprecated and
- * should not be used. Instead, use semanage_module_set_enabled() */
-int semanage_module_disable(semanage_handle_t *sh, char *module_name)
-{
- int rc = -1;
- semanage_module_key_t *modkey = NULL;
-
- rc = semanage_module_key_create(sh, &modkey);
- if (rc != 0)
- goto exit;
-
- rc = semanage_module_key_set_name(sh, modkey, module_name);
- if (rc != 0)
- goto exit;
-
- rc = semanage_module_set_enabled(sh, modkey, 0);
- if (rc != 0)
- goto exit;
-
- rc = 0;
-
-exit:
- semanage_module_key_destroy(sh, modkey);
- free(modkey);
-
- return rc;
-}
/* Converts a string to a priority
*
@@ -1146,3 +978,60 @@ int semanage_module_remove_key(semanage_handle_t *sh,
return sh->funcs->remove_key(sh, modkey);
}
+static const char CHECKSUM_TYPE[] = "sha256";
+const size_t CHECKSUM_CONTENT_SIZE = sizeof(CHECKSUM_TYPE) + 1 + 2 * SHA256_HASH_SIZE;
+
+void semanage_hash_to_checksum_string(const uint8_t *hash, char *checksum)
+{
+ size_t i;
+
+ checksum += sprintf(checksum, "%s:", CHECKSUM_TYPE);
+ for (i = 0; i < SHA256_HASH_SIZE; i++) {
+ checksum += sprintf(checksum, "%02x", (unsigned)hash[i]);
+ }
+}
+
+int semanage_module_compute_checksum(semanage_handle_t *sh,
+ semanage_module_key_t *modkey,
+ int cil, char **checksum,
+ size_t *checksum_len)
+{
+ semanage_module_info_t *extract_info = NULL;
+ Sha256Context context;
+ SHA256_HASH sha256_hash;
+ char *checksum_str;
+ void *data;
+ size_t data_len = 0;
+ int result;
+
+ if (!checksum_len)
+ return -1;
+
+ if (!checksum) {
+ *checksum_len = CHECKSUM_CONTENT_SIZE;
+ return 0;
+ }
+
+ result = semanage_module_extract(sh, modkey, cil, &data, &data_len, &extract_info);
+ if (result != 0)
+ return -1;
+
+ semanage_module_info_destroy(sh, extract_info);
+ free(extract_info);
+
+ Sha256Initialise(&context);
+ Sha256Update(&context, data, data_len);
+ Sha256Finalise(&context, &sha256_hash);
+
+ munmap(data, data_len);
+
+ checksum_str = malloc(CHECKSUM_CONTENT_SIZE + 1 /* '\0' */);
+ if (!checksum_str)
+ return -1;
+
+ semanage_hash_to_checksum_string(sha256_hash.bytes, checksum_str);
+
+ *checksum = checksum_str;
+ *checksum_len = CHECKSUM_CONTENT_SIZE;
+ return 0;
+}
diff --git a/libsemanage/src/modules.h b/libsemanage/src/modules.h
index 8a5c01f4..cf2432c5 100644
--- a/libsemanage/src/modules.h
+++ b/libsemanage/src/modules.h
@@ -24,18 +24,11 @@
#include <stdint.h>
-#include "module_internal.h"
-
-int semanage_module_install_pp(semanage_handle_t * sh,
- char *module_data, size_t data_len);
-int semanage_module_install_hll(semanage_handle_t * sh,
- char *module_data, size_t data_len, const char *name, const char *ext_lang);
-int semanage_module_upgrade(semanage_handle_t * sh,
- char *module_data, size_t data_len);
+#include "semanage/modules.h"
+
+
int semanage_module_upgrade_file(semanage_handle_t * sh,
const char *module_name);
-int semanage_module_install_base(semanage_handle_t * sh,
- char *module_data, size_t data_len);
int semanage_module_install_base_file(semanage_handle_t * sh,
const char *module_name);
@@ -109,4 +102,7 @@ int semanage_module_get_path(semanage_handle_t *sh,
char *path,
size_t len);
+extern const size_t CHECKSUM_CONTENT_SIZE;
+void semanage_hash_to_checksum_string(const uint8_t *hash, char *checksum);
+
#endif
diff --git a/libsemanage/src/node_internal.h b/libsemanage/src/node_internal.h
index 58175603..234143b4 100644
--- a/libsemanage/src/node_internal.h
+++ b/libsemanage/src/node_internal.h
@@ -6,29 +6,6 @@
#include <semanage/nodes_policy.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_node_create)
- hidden_proto(semanage_node_compare)
- hidden_proto(semanage_node_compare2)
- hidden_proto(semanage_node_clone)
- hidden_proto(semanage_node_free)
- hidden_proto(semanage_node_key_extract)
- hidden_proto(semanage_node_key_free)
- hidden_proto(semanage_node_get_addr)
- hidden_proto(semanage_node_get_addr_bytes)
- hidden_proto(semanage_node_get_mask)
- hidden_proto(semanage_node_get_mask_bytes)
- hidden_proto(semanage_node_get_proto)
- hidden_proto(semanage_node_set_addr)
- hidden_proto(semanage_node_set_addr_bytes)
- hidden_proto(semanage_node_set_mask)
- hidden_proto(semanage_node_set_mask_bytes)
- hidden_proto(semanage_node_set_proto)
- hidden_proto(semanage_node_get_proto_str)
- hidden_proto(semanage_node_get_con)
- hidden_proto(semanage_node_set_con)
- hidden_proto(semanage_node_list_local)
/* NODE RECORD: method table */
extern record_table_t SEMANAGE_NODE_RTABLE;
@@ -45,11 +22,11 @@ extern int node_policydb_dbase_init(semanage_handle_t * handle,
extern void node_policydb_dbase_release(dbase_config_t * dconfig);
-extern int hidden semanage_node_validate_local(semanage_handle_t * handle);
+extern int semanage_node_validate_local(semanage_handle_t * handle);
/* ==== Internal (to nodes) API === */
-hidden int semanage_node_compare2_qsort(const semanage_node_t ** node,
+ int semanage_node_compare2_qsort(const semanage_node_t ** node,
const semanage_node_t ** node2);
#endif
diff --git a/libsemanage/src/node_record.c b/libsemanage/src/node_record.c
index 5368ceee..e1c6e03a 100644
--- a/libsemanage/src/node_record.c
+++ b/libsemanage/src/node_record.c
@@ -32,7 +32,6 @@ int semanage_node_compare(const semanage_node_t * node,
return sepol_node_compare(node, key);
}
-hidden_def(semanage_node_compare)
int semanage_node_compare2(const semanage_node_t * node,
const semanage_node_t * node2)
@@ -41,9 +40,8 @@ int semanage_node_compare2(const semanage_node_t * node,
return sepol_node_compare2(node, node2);
}
-hidden_def(semanage_node_compare2)
-hidden int semanage_node_compare2_qsort(const semanage_node_t ** node,
+ int semanage_node_compare2_qsort(const semanage_node_t ** node,
const semanage_node_t ** node2)
{
@@ -68,7 +66,6 @@ int semanage_node_key_extract(semanage_handle_t * handle,
return sepol_node_key_extract(handle->sepolh, node, key_ptr);
}
-hidden_def(semanage_node_key_extract)
void semanage_node_key_free(semanage_node_key_t * key)
{
@@ -76,7 +73,6 @@ void semanage_node_key_free(semanage_node_key_t * key)
sepol_node_key_free(key);
}
-hidden_def(semanage_node_key_free)
/* Address */
int semanage_node_get_addr(semanage_handle_t * handle,
@@ -86,7 +82,6 @@ int semanage_node_get_addr(semanage_handle_t * handle,
return sepol_node_get_addr(handle->sepolh, node, addr_ptr);
}
-hidden_def(semanage_node_get_addr)
int semanage_node_get_addr_bytes(semanage_handle_t * handle,
const semanage_node_t * node,
@@ -96,7 +91,6 @@ int semanage_node_get_addr_bytes(semanage_handle_t * handle,
return sepol_node_get_addr_bytes(handle->sepolh, node, addr, addr_sz);
}
-hidden_def(semanage_node_get_addr_bytes)
int semanage_node_set_addr(semanage_handle_t * handle,
semanage_node_t * node, int proto, const char *addr)
@@ -105,7 +99,6 @@ int semanage_node_set_addr(semanage_handle_t * handle,
return sepol_node_set_addr(handle->sepolh, node, proto, addr);
}
-hidden_def(semanage_node_set_addr)
int semanage_node_set_addr_bytes(semanage_handle_t * handle,
semanage_node_t * node,
@@ -115,7 +108,6 @@ int semanage_node_set_addr_bytes(semanage_handle_t * handle,
return sepol_node_set_addr_bytes(handle->sepolh, node, addr, addr_sz);
}
-hidden_def(semanage_node_set_addr_bytes)
/* Netmask */
int semanage_node_get_mask(semanage_handle_t * handle,
@@ -125,7 +117,6 @@ int semanage_node_get_mask(semanage_handle_t * handle,
return sepol_node_get_mask(handle->sepolh, node, mask_ptr);
}
-hidden_def(semanage_node_get_mask)
int semanage_node_get_mask_bytes(semanage_handle_t * handle,
const semanage_node_t * node,
@@ -135,7 +126,6 @@ int semanage_node_get_mask_bytes(semanage_handle_t * handle,
return sepol_node_get_mask_bytes(handle->sepolh, node, mask, mask_sz);
}
-hidden_def(semanage_node_get_mask_bytes)
int semanage_node_set_mask(semanage_handle_t * handle,
semanage_node_t * node, int proto, const char *mask)
@@ -144,7 +134,6 @@ int semanage_node_set_mask(semanage_handle_t * handle,
return sepol_node_set_mask(handle->sepolh, node, proto, mask);
}
-hidden_def(semanage_node_set_mask)
int semanage_node_set_mask_bytes(semanage_handle_t * handle,
semanage_node_t * node,
@@ -154,7 +143,6 @@ int semanage_node_set_mask_bytes(semanage_handle_t * handle,
return sepol_node_set_mask_bytes(handle->sepolh, node, mask, mask_sz);
}
-hidden_def(semanage_node_set_mask_bytes)
/* Protocol */
int semanage_node_get_proto(const semanage_node_t * node)
@@ -163,7 +151,6 @@ int semanage_node_get_proto(const semanage_node_t * node)
return sepol_node_get_proto(node);
}
-hidden_def(semanage_node_get_proto)
void semanage_node_set_proto(semanage_node_t * node, int proto)
{
@@ -171,7 +158,6 @@ void semanage_node_set_proto(semanage_node_t * node, int proto)
sepol_node_set_proto(node, proto);
}
-hidden_def(semanage_node_set_proto)
const char *semanage_node_get_proto_str(int proto)
{
@@ -179,7 +165,6 @@ const char *semanage_node_get_proto_str(int proto)
return sepol_node_get_proto_str(proto);
}
-hidden_def(semanage_node_get_proto_str)
/* Context */
semanage_context_t *semanage_node_get_con(const semanage_node_t * node)
@@ -188,7 +173,6 @@ semanage_context_t *semanage_node_get_con(const semanage_node_t * node)
return sepol_node_get_con(node);
}
-hidden_def(semanage_node_get_con)
int semanage_node_set_con(semanage_handle_t * handle,
semanage_node_t * node, semanage_context_t * con)
@@ -197,7 +181,6 @@ int semanage_node_set_con(semanage_handle_t * handle,
return sepol_node_set_con(handle->sepolh, node, con);
}
-hidden_def(semanage_node_set_con)
/* Create/Clone/Destroy */
int semanage_node_create(semanage_handle_t * handle,
@@ -207,7 +190,6 @@ int semanage_node_create(semanage_handle_t * handle,
return sepol_node_create(handle->sepolh, node_ptr);
}
-hidden_def(semanage_node_create)
int semanage_node_clone(semanage_handle_t * handle,
const semanage_node_t * node,
@@ -217,7 +199,6 @@ int semanage_node_clone(semanage_handle_t * handle,
return sepol_node_clone(handle->sepolh, node, node_ptr);
}
-hidden_def(semanage_node_clone)
void semanage_node_free(semanage_node_t * node)
{
@@ -225,7 +206,6 @@ void semanage_node_free(semanage_node_t * node)
sepol_node_free(node);
}
-hidden_def(semanage_node_free)
/* Port base functions */
record_table_t SEMANAGE_NODE_RTABLE = {
diff --git a/libsemanage/src/nodes_file.c b/libsemanage/src/nodes_file.c
index f6c8895d..2d2b7fe0 100644
--- a/libsemanage/src/nodes_file.c
+++ b/libsemanage/src/nodes_file.c
@@ -15,7 +15,6 @@ typedef struct dbase_file dbase_t;
#include <strings.h>
#include <semanage/handle.h>
#include "node_internal.h"
-#include "context_internal.h"
#include "database_file.h"
#include "parse_utils.h"
#include "debug.h"
@@ -78,7 +77,7 @@ static int node_parse(semanage_handle_t * handle,
goto err;
/* Protocol */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (!strcasecmp(str, "ipv4"))
proto = SEMANAGE_PROTO_IP4;
@@ -97,7 +96,7 @@ static int node_parse(semanage_handle_t * handle,
/* Address */
if (parse_assert_space(handle, info) < 0)
goto err;
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_node_set_addr(handle, node, proto, str) < 0)
goto err;
@@ -107,7 +106,7 @@ static int node_parse(semanage_handle_t * handle,
str = NULL;
/* Netmask */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_node_set_mask(handle, node, proto, str) < 0)
goto err;
@@ -117,7 +116,7 @@ static int node_parse(semanage_handle_t * handle,
str = NULL;
/* Port context */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_context_from_string(handle, str, &con) < 0) {
ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
diff --git a/libsemanage/src/nodes_local.c b/libsemanage/src/nodes_local.c
index 93af4501..c85fe4e7 100644
--- a/libsemanage/src/nodes_local.c
+++ b/libsemanage/src/nodes_local.c
@@ -69,4 +69,3 @@ int semanage_node_list_local(semanage_handle_t * handle,
return dbase_list(handle, dconfig, records, count);
}
-hidden_def(semanage_node_list_local)
diff --git a/libsemanage/src/parse_utils.c b/libsemanage/src/parse_utils.c
index 4fb54fc3..918dee43 100644
--- a/libsemanage/src/parse_utils.c
+++ b/libsemanage/src/parse_utils.c
@@ -239,7 +239,7 @@ int parse_fetch_int(semanage_handle_t * handle,
char *test = NULL;
int value = 0;
- if (parse_fetch_string(handle, info, &str, delim) < 0)
+ if (parse_fetch_string(handle, info, &str, delim, 0) < 0)
goto err;
if (!isdigit((int)*str)) {
@@ -267,7 +267,7 @@ int parse_fetch_int(semanage_handle_t * handle,
}
int parse_fetch_string(semanage_handle_t * handle,
- parse_info_t * info, char **str, char delim)
+ parse_info_t * info, char **str, char delim, int allow_spaces)
{
char *start = info->ptr;
@@ -277,7 +277,7 @@ int parse_fetch_string(semanage_handle_t * handle,
if (parse_assert_noeof(handle, info) < 0)
goto err;
- while (*(info->ptr) && !isspace(*(info->ptr)) &&
+ while (*(info->ptr) && (allow_spaces || !isspace(*(info->ptr))) &&
(*(info->ptr) != delim)) {
info->ptr++;
len++;
diff --git a/libsemanage/src/parse_utils.h b/libsemanage/src/parse_utils.h
index 0f334860..3e44aca1 100644
--- a/libsemanage/src/parse_utils.h
+++ b/libsemanage/src/parse_utils.h
@@ -71,12 +71,11 @@ extern int parse_optional_str(parse_info_t * info, const char *str);
int parse_fetch_int(semanage_handle_t * hgandle,
parse_info_t * info, int *num, char delim);
-/* Extract the next string (delimited by
- * whitespace), and move the read pointer past it.
- * Stop of the optional character delim is encountered,
- * or if whitespace/eof is encountered. Fail if the
- * string is of length 0. */
+/* Extract the next string and move the read pointer past it.
+ * Stop if the optional character delim (or eof) is encountered,
+ * or if whitespace is encountered and allow_spaces is 0.
+ * Fail if the string is of length 0. */
extern int parse_fetch_string(semanage_handle_t * handle,
- parse_info_t * info, char **str_ptr, char delim);
+ parse_info_t * info, char **str_ptr, char delim, int allow_spaces);
#endif
diff --git a/libsemanage/src/port_internal.h b/libsemanage/src/port_internal.h
index ebd2bc84..67017472 100644
--- a/libsemanage/src/port_internal.h
+++ b/libsemanage/src/port_internal.h
@@ -6,25 +6,6 @@
#include <semanage/ports_policy.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_port_create)
- hidden_proto(semanage_port_compare)
- hidden_proto(semanage_port_compare2)
- hidden_proto(semanage_port_clone)
- hidden_proto(semanage_port_free)
- hidden_proto(semanage_port_key_extract)
- hidden_proto(semanage_port_key_free)
- hidden_proto(semanage_port_get_high)
- hidden_proto(semanage_port_get_low)
- hidden_proto(semanage_port_set_port)
- hidden_proto(semanage_port_set_range)
- hidden_proto(semanage_port_get_proto)
- hidden_proto(semanage_port_set_proto)
- hidden_proto(semanage_port_get_proto_str)
- hidden_proto(semanage_port_get_con)
- hidden_proto(semanage_port_set_con)
- hidden_proto(semanage_port_list_local)
/* PORT RECORD: method table */
extern record_table_t SEMANAGE_PORT_RTABLE;
@@ -41,11 +22,11 @@ extern int port_policydb_dbase_init(semanage_handle_t * handle,
extern void port_policydb_dbase_release(dbase_config_t * dconfig);
-extern int hidden semanage_port_validate_local(semanage_handle_t * handle);
+extern int semanage_port_validate_local(semanage_handle_t * handle);
/* ==== Internal (to ports) API === */
-hidden int semanage_port_compare2_qsort(const semanage_port_t ** port,
+ int semanage_port_compare2_qsort(const semanage_port_t ** port,
const semanage_port_t ** port2);
#endif
diff --git a/libsemanage/src/port_record.c b/libsemanage/src/port_record.c
index b878ca78..f8a1633e 100644
--- a/libsemanage/src/port_record.c
+++ b/libsemanage/src/port_record.c
@@ -31,7 +31,6 @@ int semanage_port_compare(const semanage_port_t * port,
return sepol_port_compare(port, key);
}
-hidden_def(semanage_port_compare)
int semanage_port_compare2(const semanage_port_t * port,
const semanage_port_t * port2)
@@ -40,9 +39,8 @@ int semanage_port_compare2(const semanage_port_t * port,
return sepol_port_compare2(port, port2);
}
-hidden_def(semanage_port_compare2)
-hidden int semanage_port_compare2_qsort(const semanage_port_t ** port,
+ int semanage_port_compare2_qsort(const semanage_port_t ** port,
const semanage_port_t ** port2)
{
@@ -65,7 +63,6 @@ int semanage_port_key_extract(semanage_handle_t * handle,
return sepol_port_key_extract(handle->sepolh, port, key_ptr);
}
-hidden_def(semanage_port_key_extract)
void semanage_port_key_free(semanage_port_key_t * key)
{
@@ -73,7 +70,6 @@ void semanage_port_key_free(semanage_port_key_t * key)
sepol_port_key_free(key);
}
-hidden_def(semanage_port_key_free)
/* Protocol */
int semanage_port_get_proto(const semanage_port_t * port)
@@ -82,7 +78,6 @@ int semanage_port_get_proto(const semanage_port_t * port)
return sepol_port_get_proto(port);
}
-hidden_def(semanage_port_get_proto)
void semanage_port_set_proto(semanage_port_t * port, int proto)
{
@@ -90,7 +85,6 @@ void semanage_port_set_proto(semanage_port_t * port, int proto)
sepol_port_set_proto(port, proto);
}
-hidden_def(semanage_port_set_proto)
const char *semanage_port_get_proto_str(int proto)
{
@@ -98,7 +92,6 @@ const char *semanage_port_get_proto_str(int proto)
return sepol_port_get_proto_str(proto);
}
-hidden_def(semanage_port_get_proto_str)
/* Port */
int semanage_port_get_low(const semanage_port_t * port)
@@ -107,7 +100,6 @@ int semanage_port_get_low(const semanage_port_t * port)
return sepol_port_get_low(port);
}
-hidden_def(semanage_port_get_low)
int semanage_port_get_high(const semanage_port_t * port)
{
@@ -115,7 +107,6 @@ int semanage_port_get_high(const semanage_port_t * port)
return sepol_port_get_high(port);
}
-hidden_def(semanage_port_get_high)
void semanage_port_set_port(semanage_port_t * port, int port_num)
{
@@ -123,7 +114,6 @@ void semanage_port_set_port(semanage_port_t * port, int port_num)
sepol_port_set_port(port, port_num);
}
-hidden_def(semanage_port_set_port)
void semanage_port_set_range(semanage_port_t * port, int low, int high)
{
@@ -131,7 +121,6 @@ void semanage_port_set_range(semanage_port_t * port, int low, int high)
sepol_port_set_range(port, low, high);
}
-hidden_def(semanage_port_set_range)
/* Context */
semanage_context_t *semanage_port_get_con(const semanage_port_t * port)
@@ -140,7 +129,6 @@ semanage_context_t *semanage_port_get_con(const semanage_port_t * port)
return sepol_port_get_con(port);
}
-hidden_def(semanage_port_get_con)
int semanage_port_set_con(semanage_handle_t * handle,
semanage_port_t * port, semanage_context_t * con)
@@ -149,7 +137,6 @@ int semanage_port_set_con(semanage_handle_t * handle,
return sepol_port_set_con(handle->sepolh, port, con);
}
-hidden_def(semanage_port_set_con)
/* Create/Clone/Destroy */
int semanage_port_create(semanage_handle_t * handle,
@@ -159,7 +146,6 @@ int semanage_port_create(semanage_handle_t * handle,
return sepol_port_create(handle->sepolh, port_ptr);
}
-hidden_def(semanage_port_create)
int semanage_port_clone(semanage_handle_t * handle,
const semanage_port_t * port,
@@ -169,7 +155,6 @@ int semanage_port_clone(semanage_handle_t * handle,
return sepol_port_clone(handle->sepolh, port, port_ptr);
}
-hidden_def(semanage_port_clone)
void semanage_port_free(semanage_port_t * port)
{
@@ -177,7 +162,6 @@ void semanage_port_free(semanage_port_t * port)
sepol_port_free(port);
}
-hidden_def(semanage_port_free)
/* Port base functions */
record_table_t SEMANAGE_PORT_RTABLE = {
diff --git a/libsemanage/src/ports_file.c b/libsemanage/src/ports_file.c
index 4738d467..1356021a 100644
--- a/libsemanage/src/ports_file.c
+++ b/libsemanage/src/ports_file.c
@@ -15,7 +15,6 @@ typedef struct dbase_file dbase_t;
#include <strings.h>
#include <semanage/handle.h>
#include "port_internal.h"
-#include "context_internal.h"
#include "database_file.h"
#include "parse_utils.h"
#include "debug.h"
@@ -78,7 +77,7 @@ static int port_parse(semanage_handle_t * handle,
goto err;
/* Protocol */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (!strcasecmp(str, "tcp"))
semanage_port_set_proto(port, SEMANAGE_PROTO_TCP);
@@ -124,7 +123,7 @@ static int port_parse(semanage_handle_t * handle,
semanage_port_set_port(port, low);
/* Port context */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_context_from_string(handle, str, &con) < 0) {
ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
diff --git a/libsemanage/src/ports_local.c b/libsemanage/src/ports_local.c
index ffd5a838..e7e9bdbf 100644
--- a/libsemanage/src/ports_local.c
+++ b/libsemanage/src/ports_local.c
@@ -71,9 +71,8 @@ int semanage_port_list_local(semanage_handle_t * handle,
return dbase_list(handle, dconfig, records, count);
}
-hidden_def(semanage_port_list_local)
-int hidden semanage_port_validate_local(semanage_handle_t * handle)
+int semanage_port_validate_local(semanage_handle_t * handle)
{
semanage_port_t **ports = NULL;
diff --git a/libsemanage/src/semanage.conf b/libsemanage/src/semanage.conf
index dc8d46b8..98d769b5 100644
--- a/libsemanage/src/semanage.conf
+++ b/libsemanage/src/semanage.conf
@@ -24,8 +24,9 @@
# /foo/bar - Write by way of a policy management server, whose
# named socket is at /foo/bar. The path must begin
# with a '/'.
-# foo.com:4242 - Establish a TCP connection to a remote policy
-# management server at foo.com. If there is a colon
+# example.com:4242
+# - Establish a TCP connection to a remote policy
+# management server at example.com. If there is a colon
# then the remainder is interpreted as a port number;
# otherwise default to port 4242.
module-store = direct
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index 58dded6e..767f05cb 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -59,6 +59,7 @@ typedef struct dbase_policydb dbase_t;
#include "debug.h"
#include "utilities.h"
+#include "compressed_file.h"
#define SEMANAGE_CONF_FILE "semanage.conf"
/* relative path names to enum semanage_paths to special files and
@@ -114,6 +115,7 @@ static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
"/disable_dontaudit",
"/preserve_tunables",
"/modules/disabled",
+ "/modules_checksum",
"/policy.kern",
"/file_contexts.local",
"/file_contexts.homedirs",
@@ -707,7 +709,8 @@ static int semanage_filename_select(const struct dirent *d)
/* Copies a file from src to dst. If dst already exists then
* overwrite it. Returns 0 on success, -1 on error. */
-int semanage_copy_file(const char *src, const char *dst, mode_t mode)
+int semanage_copy_file(const char *src, const char *dst, mode_t mode,
+ bool syncrequired)
{
int in, out, retval = 0, amount_read, n, errsv = errno;
char tmp[PATH_MAX];
@@ -735,8 +738,11 @@ int semanage_copy_file(const char *src, const char *dst, mode_t mode)
}
umask(mask);
while (retval == 0 && (amount_read = read(in, buf, sizeof(buf))) > 0) {
- if (write(out, buf, amount_read) < 0) {
- errsv = errno;
+ if (write(out, buf, amount_read) != amount_read) {
+ if (errno)
+ errsv = errno;
+ else
+ errsv = EIO;
retval = -1;
}
}
@@ -745,6 +751,10 @@ int semanage_copy_file(const char *src, const char *dst, mode_t mode)
retval = -1;
}
close(in);
+ if (syncrequired && fsync(out) < 0) {
+ errsv = errno;
+ retval = -1;
+ }
if (close(out) < 0) {
errsv = errno;
retval = -1;
@@ -811,7 +821,8 @@ static int semanage_copy_dir_flags(const char *src, const char *dst, int flag)
umask(mask);
} else if (S_ISREG(sb.st_mode) && flag == 1) {
mask = umask(0077);
- if (semanage_copy_file(path, path2, sb.st_mode) < 0) {
+ if (semanage_copy_file(path, path2, sb.st_mode,
+ false) < 0) {
umask(mask);
goto cleanup;
}
@@ -1476,7 +1487,6 @@ int semanage_reload_policy(semanage_handle_t * sh)
return r;
}
-hidden_def(semanage_reload_policy)
/* This expands the file_context.tmpl file to file_context and homedirs.template */
int semanage_split_fc(semanage_handle_t * sh)
@@ -1640,7 +1650,8 @@ static int semanage_install_final_tmp(semanage_handle_t * sh)
goto cleanup;
}
- ret = semanage_copy_file(src, dst, sh->conf->file_mode);
+ ret = semanage_copy_file(src, dst, sh->conf->file_mode,
+ true);
if (ret < 0) {
ERR(sh, "Could not copy %s to %s.", src, dst);
goto cleanup;
@@ -1727,6 +1738,19 @@ static int semanage_commit_sandbox(semanage_handle_t * sh)
}
close(fd);
+ /* sync changes in sandbox to filesystem */
+ fd = open(sandbox, O_DIRECTORY);
+ if (fd == -1) {
+ ERR(sh, "Error while opening %s for syncfs(): %d", sandbox, errno);
+ return -1;
+ }
+ if (syncfs(fd) == -1) {
+ ERR(sh, "Error while syncing %s to filesystem: %d", sandbox, errno);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
retval = commit_number;
if (semanage_get_active_lock(sh) < 0) {
@@ -2032,60 +2056,27 @@ int semanage_direct_get_serial(semanage_handle_t * sh)
int semanage_load_files(semanage_handle_t * sh, cil_db_t *cildb, char **filenames, int numfiles)
{
- int retval = 0;
- FILE *fp;
- ssize_t size;
- char *data = NULL;
+ int i, retval = 0;
char *filename;
- int i;
+ struct file_contents contents = {};
for (i = 0; i < numfiles; i++) {
filename = filenames[i];
- if ((fp = fopen(filename, "rb")) == NULL) {
- ERR(sh, "Could not open module file %s for reading.", filename);
- goto cleanup;
- }
-
- if ((size = bunzip(sh, fp, &data)) <= 0) {
- rewind(fp);
- __fsetlocking(fp, FSETLOCKING_BYCALLER);
-
- if (fseek(fp, 0, SEEK_END) != 0) {
- ERR(sh, "Failed to determine size of file %s.", filename);
- goto cleanup;
- }
- size = ftell(fp);
- rewind(fp);
-
- data = malloc(size);
- if (fread(data, size, 1, fp) != 1) {
- ERR(sh, "Failed to read file %s.", filename);
- goto cleanup;
- }
- }
+ retval = map_compressed_file(sh, filename, &contents);
+ if (retval < 0)
+ return -1;
- fclose(fp);
- fp = NULL;
+ retval = cil_add_file(cildb, filename, contents.data, contents.len);
+ unmap_compressed_file(&contents);
- retval = cil_add_file(cildb, filename, data, size);
if (retval != SEPOL_OK) {
ERR(sh, "Error while reading from file %s.", filename);
- goto cleanup;
+ return -1;
}
-
- free(data);
- data = NULL;
}
- return retval;
-
- cleanup:
- if (fp != NULL) {
- fclose(fp);
- }
- free(data);
- return -1;
+ return 0;
}
/*
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index 34bf8523..1fc77da8 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -24,6 +24,7 @@
#ifndef SEMANAGE_MODULE_STORE_H
#define SEMANAGE_MODULE_STORE_H
+#include <stdbool.h>
#include <sys/time.h>
#include <sepol/module.h>
#include <sepol/cil/cil.h>
@@ -59,6 +60,7 @@ enum semanage_sandbox_defs {
SEMANAGE_DISABLE_DONTAUDIT,
SEMANAGE_PRESERVE_TUNABLES,
SEMANAGE_MODULES_DISABLED,
+ SEMANAGE_MODULES_CHECKSUM,
SEMANAGE_STORE_KERNEL,
SEMANAGE_STORE_FC_LOCAL,
SEMANAGE_STORE_FC_HOMEDIRS,
@@ -162,6 +164,7 @@ int semanage_nc_sort(semanage_handle_t * sh,
size_t buf_len,
char **sorted_buf, size_t * sorted_buf_len);
-int semanage_copy_file(const char *src, const char *dst, mode_t mode);
+int semanage_copy_file(const char *src, const char *dst, mode_t mode,
+ bool syncrequired);
#endif
diff --git a/libsemanage/src/semanageswig_python.i b/libsemanage/src/semanageswig_python.i
index 8dd79fc2..5f011396 100644
--- a/libsemanage/src/semanageswig_python.i
+++ b/libsemanage/src/semanageswig_python.i
@@ -30,8 +30,6 @@
%}
%include "stdint.i"
-%ignore semanage_module_install_pp;
-%ignore semanage_module_install_hll;
%wrapper %{
diff --git a/libsemanage/src/semanageswig_python_exception.i b/libsemanage/src/semanageswig_python_exception.i
index 06c60267..0df8bbc3 100644
--- a/libsemanage/src/semanageswig_python_exception.i
+++ b/libsemanage/src/semanageswig_python_exception.i
@@ -7,7 +7,6 @@
}
}
-
%exception semanage_get_hll_compiler_path {
$action
if (result < 0) {
@@ -16,7 +15,6 @@
}
}
-
%exception semanage_get_disable_dontaudit {
$action
if (result < 0) {
@@ -25,7 +23,6 @@
}
}
-
%exception semanage_set_default_priority {
$action
if (result < 0) {
@@ -34,7 +31,6 @@
}
}
-
%exception semanage_is_managed {
$action
if (result < 0) {
@@ -43,7 +39,6 @@
}
}
-
%exception semanage_connect {
$action
if (result < 0) {
@@ -52,7 +47,6 @@
}
}
-
%exception semanage_disconnect {
$action
if (result < 0) {
@@ -61,7 +55,6 @@
}
}
-
%exception semanage_begin_transaction {
$action
if (result < 0) {
@@ -70,7 +63,6 @@
}
}
-
%exception semanage_commit {
$action
if (result < 0) {
@@ -79,7 +71,6 @@
}
}
-
%exception semanage_access_check {
$action
if (result < 0) {
@@ -88,7 +79,6 @@
}
}
-
%exception semanage_is_connected {
$action
if (result < 0) {
@@ -97,7 +87,6 @@
}
}
-
%exception semanage_mls_enabled {
$action
if (result < 0) {
@@ -106,7 +95,6 @@
}
}
-
%exception semanage_set_root {
$action
if (result < 0) {
@@ -115,7 +103,6 @@
}
}
-
%exception semanage_get_preserve_tunables {
$action
if (result < 0) {
@@ -124,7 +111,6 @@
}
}
-
%exception semanage_get_ignore_module_cache {
$action
if (result < 0) {
@@ -133,7 +119,6 @@
}
}
-
%exception select {
$action
if (result < 0) {
@@ -142,7 +127,6 @@
}
}
-
%exception pselect {
$action
if (result < 0) {
@@ -151,7 +135,6 @@
}
}
-
%exception semanage_module_install {
$action
if (result < 0) {
@@ -160,7 +143,6 @@
}
}
-
%exception semanage_module_install_file {
$action
if (result < 0) {
@@ -169,7 +151,6 @@
}
}
-
%exception semanage_module_remove {
$action
if (result < 0) {
@@ -178,7 +159,6 @@
}
}
-
%exception semanage_module_extract {
$action
if (result < 0) {
@@ -187,7 +167,6 @@
}
}
-
%exception semanage_module_list {
$action
if (result < 0) {
@@ -196,7 +175,6 @@
}
}
-
%exception semanage_module_info_create {
$action
if (result < 0) {
@@ -205,7 +183,6 @@
}
}
-
%exception semanage_module_info_destroy {
$action
if (result < 0) {
@@ -214,7 +191,6 @@
}
}
-
%exception semanage_module_info_get_priority {
$action
if (result < 0) {
@@ -223,7 +199,6 @@
}
}
-
%exception semanage_module_info_get_name {
$action
if (result < 0) {
@@ -232,7 +207,6 @@
}
}
-
%exception semanage_module_info_get_lang_ext {
$action
if (result < 0) {
@@ -241,7 +215,6 @@
}
}
-
%exception semanage_module_info_get_enabled {
$action
if (result < 0) {
@@ -250,7 +223,6 @@
}
}
-
%exception semanage_module_info_set_priority {
$action
if (result < 0) {
@@ -259,7 +231,6 @@
}
}
-
%exception semanage_module_info_set_name {
$action
if (result < 0) {
@@ -268,7 +239,6 @@
}
}
-
%exception semanage_module_info_set_lang_ext {
$action
if (result < 0) {
@@ -277,7 +247,6 @@
}
}
-
%exception semanage_module_info_set_enabled {
$action
if (result < 0) {
@@ -286,7 +255,6 @@
}
}
-
%exception semanage_module_key_create {
$action
if (result < 0) {
@@ -295,7 +263,6 @@
}
}
-
%exception semanage_module_key_destroy {
$action
if (result < 0) {
@@ -304,7 +271,6 @@
}
}
-
%exception semanage_module_key_get_name {
$action
if (result < 0) {
@@ -313,7 +279,6 @@
}
}
-
%exception semanage_module_key_get_priority {
$action
if (result < 0) {
@@ -322,7 +287,6 @@
}
}
-
%exception semanage_module_key_set_name {
$action
if (result < 0) {
@@ -331,7 +295,6 @@
}
}
-
%exception semanage_module_key_set_priority {
$action
if (result < 0) {
@@ -340,7 +303,6 @@
}
}
-
%exception semanage_module_set_enabled {
$action
if (result < 0) {
@@ -349,7 +311,6 @@
}
}
-
%exception semanage_module_get_module_info {
$action
if (result < 0) {
@@ -358,7 +319,6 @@
}
}
-
%exception semanage_module_list_all {
$action
if (result < 0) {
@@ -367,7 +327,6 @@
}
}
-
%exception semanage_module_install_info {
$action
if (result < 0) {
@@ -376,7 +335,6 @@
}
}
-
%exception semanage_module_remove_key {
$action
if (result < 0) {
@@ -385,7 +343,6 @@
}
}
-
%exception semanage_module_get_enabled {
$action
if (result < 0) {
@@ -394,6 +351,13 @@
}
}
+%exception semanage_module_compute_checksum {
+ $action
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ SWIG_fail;
+ }
+}
%exception semanage_msg_get_level {
$action
@@ -403,7 +367,6 @@
}
}
-
%exception semanage_bool_key_create {
$action
if (result < 0) {
@@ -412,7 +375,6 @@
}
}
-
%exception semanage_bool_key_extract {
$action
if (result < 0) {
@@ -421,7 +383,6 @@
}
}
-
%exception semanage_bool_compare {
$action
if (result < 0) {
@@ -430,7 +391,6 @@
}
}
-
%exception semanage_bool_compare2 {
$action
if (result < 0) {
@@ -439,7 +399,6 @@
}
}
-
%exception semanage_bool_set_name {
$action
if (result < 0) {
@@ -448,7 +407,6 @@
}
}
-
%exception semanage_bool_get_value {
$action
if (result < 0) {
@@ -457,7 +415,6 @@
}
}
-
%exception semanage_bool_create {
$action
if (result < 0) {
@@ -466,7 +423,6 @@
}
}
-
%exception semanage_bool_clone {
$action
if (result < 0) {
@@ -475,7 +431,6 @@
}
}
-
%exception semanage_user_key_create {
$action
if (result < 0) {
@@ -484,7 +439,6 @@
}
}
-
%exception semanage_user_key_extract {
$action
if (result < 0) {
@@ -493,7 +447,6 @@
}
}
-
%exception semanage_user_compare {
$action
if (result < 0) {
@@ -502,7 +455,6 @@
}
}
-
%exception semanage_user_compare2 {
$action
if (result < 0) {
@@ -511,7 +463,6 @@
}
}
-
%exception semanage_user_set_name {
$action
if (result < 0) {
@@ -520,7 +471,6 @@
}
}
-
%exception semanage_user_set_prefix {
$action
if (result < 0) {
@@ -529,7 +479,6 @@
}
}
-
%exception semanage_user_set_mlslevel {
$action
if (result < 0) {
@@ -538,7 +487,6 @@
}
}
-
%exception semanage_user_set_mlsrange {
$action
if (result < 0) {
@@ -547,7 +495,6 @@
}
}
-
%exception semanage_user_get_num_roles {
$action
if (result < 0) {
@@ -556,7 +503,6 @@
}
}
-
%exception semanage_user_add_role {
$action
if (result < 0) {
@@ -565,7 +511,6 @@
}
}
-
%exception semanage_user_has_role {
$action
if (result < 0) {
@@ -574,7 +519,6 @@
}
}
-
%exception semanage_user_get_roles {
$action
if (result < 0) {
@@ -583,7 +527,6 @@
}
}
-
%exception semanage_user_set_roles {
$action
if (result < 0) {
@@ -592,7 +535,6 @@
}
}
-
%exception semanage_user_create {
$action
if (result < 0) {
@@ -601,7 +543,6 @@
}
}
-
%exception semanage_user_clone {
$action
if (result < 0) {
@@ -610,7 +551,6 @@
}
}
-
%exception semanage_seuser_key_create {
$action
if (result < 0) {
@@ -619,7 +559,6 @@
}
}
-
%exception semanage_seuser_key_extract {
$action
if (result < 0) {
@@ -628,7 +567,6 @@
}
}
-
%exception semanage_seuser_compare {
$action
if (result < 0) {
@@ -637,7 +575,6 @@
}
}
-
%exception semanage_seuser_compare2 {
$action
if (result < 0) {
@@ -646,7 +583,6 @@
}
}
-
%exception semanage_seuser_set_name {
$action
if (result < 0) {
@@ -655,7 +591,6 @@
}
}
-
%exception semanage_seuser_set_sename {
$action
if (result < 0) {
@@ -664,7 +599,6 @@
}
}
-
%exception semanage_seuser_set_mlsrange {
$action
if (result < 0) {
@@ -673,7 +607,6 @@
}
}
-
%exception semanage_seuser_create {
$action
if (result < 0) {
@@ -682,7 +615,6 @@
}
}
-
%exception semanage_seuser_clone {
$action
if (result < 0) {
@@ -691,7 +623,6 @@
}
}
-
%exception semanage_context_set_user {
$action
if (result < 0) {
@@ -700,7 +631,6 @@
}
}
-
%exception semanage_context_set_role {
$action
if (result < 0) {
@@ -709,7 +639,6 @@
}
}
-
%exception semanage_context_set_type {
$action
if (result < 0) {
@@ -718,7 +647,6 @@
}
}
-
%exception semanage_context_set_mls {
$action
if (result < 0) {
@@ -727,7 +655,6 @@
}
}
-
%exception semanage_context_create {
$action
if (result < 0) {
@@ -736,7 +663,6 @@
}
}
-
%exception semanage_context_clone {
$action
if (result < 0) {
@@ -745,7 +671,6 @@
}
}
-
%exception semanage_context_from_string {
$action
if (result < 0) {
@@ -754,7 +679,6 @@
}
}
-
%exception semanage_context_to_string {
$action
if (result < 0) {
@@ -763,7 +687,6 @@
}
}
-
%exception semanage_iface_compare {
$action
if (result < 0) {
@@ -772,7 +695,6 @@
}
}
-
%exception semanage_iface_compare2 {
$action
if (result < 0) {
@@ -781,7 +703,6 @@
}
}
-
%exception semanage_iface_key_create {
$action
if (result < 0) {
@@ -790,7 +711,6 @@
}
}
-
%exception semanage_iface_key_extract {
$action
if (result < 0) {
@@ -799,7 +719,6 @@
}
}
-
%exception semanage_iface_set_name {
$action
if (result < 0) {
@@ -808,7 +727,6 @@
}
}
-
%exception semanage_iface_set_ifcon {
$action
if (result < 0) {
@@ -817,7 +735,6 @@
}
}
-
%exception semanage_iface_set_msgcon {
$action
if (result < 0) {
@@ -826,7 +743,6 @@
}
}
-
%exception semanage_iface_create {
$action
if (result < 0) {
@@ -835,7 +751,6 @@
}
}
-
%exception semanage_iface_clone {
$action
if (result < 0) {
@@ -844,7 +759,6 @@
}
}
-
%exception semanage_port_compare {
$action
if (result < 0) {
@@ -853,7 +767,6 @@
}
}
-
%exception semanage_port_compare2 {
$action
if (result < 0) {
@@ -862,7 +775,6 @@
}
}
-
%exception semanage_port_key_create {
$action
if (result < 0) {
@@ -871,7 +783,6 @@
}
}
-
%exception semanage_port_key_extract {
$action
if (result < 0) {
@@ -880,7 +791,6 @@
}
}
-
%exception semanage_port_get_proto {
$action
if (result < 0) {
@@ -889,7 +799,6 @@
}
}
-
%exception semanage_port_get_low {
$action
if (result < 0) {
@@ -898,7 +807,6 @@
}
}
-
%exception semanage_port_get_high {
$action
if (result < 0) {
@@ -907,7 +815,6 @@
}
}
-
%exception semanage_port_set_con {
$action
if (result < 0) {
@@ -916,7 +823,6 @@
}
}
-
%exception semanage_port_create {
$action
if (result < 0) {
@@ -925,7 +831,6 @@
}
}
-
%exception semanage_port_clone {
$action
if (result < 0) {
@@ -934,7 +839,6 @@
}
}
-
%exception semanage_ibpkey_compare {
$action
if (result < 0) {
@@ -943,7 +847,6 @@
}
}
-
%exception semanage_ibpkey_compare2 {
$action
if (result < 0) {
@@ -952,7 +855,6 @@
}
}
-
%exception semanage_ibpkey_key_create {
$action
if (result < 0) {
@@ -961,7 +863,6 @@
}
}
-
%exception semanage_ibpkey_key_extract {
$action
if (result < 0) {
@@ -970,7 +871,6 @@
}
}
-
%exception semanage_ibpkey_get_subnet_prefix {
$action
if (result < 0) {
@@ -979,7 +879,6 @@
}
}
-
%exception semanage_ibpkey_set_subnet_prefix {
$action
if (result < 0) {
@@ -988,7 +887,6 @@
}
}
-
%exception semanage_ibpkey_get_low {
$action
if (result < 0) {
@@ -997,7 +895,6 @@
}
}
-
%exception semanage_ibpkey_get_high {
$action
if (result < 0) {
@@ -1006,7 +903,6 @@
}
}
-
%exception semanage_ibpkey_set_con {
$action
if (result < 0) {
@@ -1015,7 +911,6 @@
}
}
-
%exception semanage_ibpkey_create {
$action
if (result < 0) {
@@ -1024,7 +919,6 @@
}
}
-
%exception semanage_ibpkey_clone {
$action
if (result < 0) {
@@ -1033,7 +927,6 @@
}
}
-
%exception semanage_ibendport_compare {
$action
if (result < 0) {
@@ -1042,7 +935,6 @@
}
}
-
%exception semanage_ibendport_compare2 {
$action
if (result < 0) {
@@ -1051,7 +943,6 @@
}
}
-
%exception semanage_ibendport_key_create {
$action
if (result < 0) {
@@ -1060,7 +951,6 @@
}
}
-
%exception semanage_ibendport_key_extract {
$action
if (result < 0) {
@@ -1069,7 +959,6 @@
}
}
-
%exception semanage_ibendport_get_ibdev_name {
$action
if (result < 0) {
@@ -1078,7 +967,6 @@
}
}
-
%exception semanage_ibendport_set_ibdev_name {
$action
if (result < 0) {
@@ -1087,7 +975,6 @@
}
}
-
%exception semanage_ibendport_get_port {
$action
if (result < 0) {
@@ -1096,7 +983,6 @@
}
}
-
%exception semanage_ibendport_set_con {
$action
if (result < 0) {
@@ -1105,7 +991,6 @@
}
}
-
%exception semanage_ibendport_create {
$action
if (result < 0) {
@@ -1114,7 +999,6 @@
}
}
-
%exception semanage_ibendport_clone {
$action
if (result < 0) {
@@ -1123,7 +1007,6 @@
}
}
-
%exception semanage_node_compare {
$action
if (result < 0) {
@@ -1132,7 +1015,6 @@
}
}
-
%exception semanage_node_compare2 {
$action
if (result < 0) {
@@ -1141,7 +1023,6 @@
}
}
-
%exception semanage_node_key_create {
$action
if (result < 0) {
@@ -1150,7 +1031,6 @@
}
}
-
%exception semanage_node_key_extract {
$action
if (result < 0) {
@@ -1159,7 +1039,6 @@
}
}
-
%exception semanage_node_get_addr {
$action
if (result < 0) {
@@ -1168,7 +1047,6 @@
}
}
-
%exception semanage_node_get_addr_bytes {
$action
if (result < 0) {
@@ -1177,7 +1055,6 @@
}
}
-
%exception semanage_node_set_addr {
$action
if (result < 0) {
@@ -1186,7 +1063,6 @@
}
}
-
%exception semanage_node_set_addr_bytes {
$action
if (result < 0) {
@@ -1195,7 +1071,6 @@
}
}
-
%exception semanage_node_get_mask {
$action
if (result < 0) {
@@ -1204,7 +1079,6 @@
}
}
-
%exception semanage_node_get_mask_bytes {
$action
if (result < 0) {
@@ -1213,7 +1087,6 @@
}
}
-
%exception semanage_node_set_mask {
$action
if (result < 0) {
@@ -1222,7 +1095,6 @@
}
}
-
%exception semanage_node_set_mask_bytes {
$action
if (result < 0) {
@@ -1231,7 +1103,6 @@
}
}
-
%exception semanage_node_get_proto {
$action
if (result < 0) {
@@ -1240,7 +1111,6 @@
}
}
-
%exception semanage_node_set_con {
$action
if (result < 0) {
@@ -1249,7 +1119,6 @@
}
}
-
%exception semanage_node_create {
$action
if (result < 0) {
@@ -1258,7 +1127,6 @@
}
}
-
%exception semanage_node_clone {
$action
if (result < 0) {
@@ -1267,7 +1135,6 @@
}
}
-
%exception semanage_bool_modify_local {
$action
if (result < 0) {
@@ -1276,7 +1143,6 @@
}
}
-
%exception semanage_bool_del_local {
$action
if (result < 0) {
@@ -1285,7 +1151,6 @@
}
}
-
%exception semanage_bool_query_local {
$action
if (result < 0) {
@@ -1294,7 +1159,6 @@
}
}
-
%exception semanage_bool_exists_local {
$action
if (result < 0) {
@@ -1303,7 +1167,6 @@
}
}
-
%exception semanage_bool_count_local {
$action
if (result < 0) {
@@ -1312,7 +1175,6 @@
}
}
-
%exception semanage_bool_iterate_local {
$action
if (result < 0) {
@@ -1321,7 +1183,6 @@
}
}
-
%exception semanage_bool_list_local {
$action
if (result < 0) {
@@ -1330,7 +1191,6 @@
}
}
-
%exception semanage_bool_query {
$action
if (result < 0) {
@@ -1339,7 +1199,6 @@
}
}
-
%exception semanage_bool_exists {
$action
if (result < 0) {
@@ -1348,7 +1207,6 @@
}
}
-
%exception semanage_bool_count {
$action
if (result < 0) {
@@ -1357,7 +1215,6 @@
}
}
-
%exception semanage_bool_iterate {
$action
if (result < 0) {
@@ -1366,7 +1223,6 @@
}
}
-
%exception semanage_bool_list {
$action
if (result < 0) {
@@ -1375,7 +1231,6 @@
}
}
-
%exception semanage_bool_set_active {
$action
if (result < 0) {
@@ -1384,7 +1239,6 @@
}
}
-
%exception semanage_bool_query_active {
$action
if (result < 0) {
@@ -1393,7 +1247,6 @@
}
}
-
%exception semanage_bool_exists_active {
$action
if (result < 0) {
@@ -1402,7 +1255,6 @@
}
}
-
%exception semanage_bool_count_active {
$action
if (result < 0) {
@@ -1411,7 +1263,6 @@
}
}
-
%exception semanage_bool_iterate_active {
$action
if (result < 0) {
@@ -1420,7 +1271,6 @@
}
}
-
%exception semanage_bool_list_active {
$action
if (result < 0) {
@@ -1429,7 +1279,6 @@
}
}
-
%exception semanage_user_modify_local {
$action
if (result < 0) {
@@ -1438,7 +1287,6 @@
}
}
-
%exception semanage_user_del_local {
$action
if (result < 0) {
@@ -1447,7 +1295,6 @@
}
}
-
%exception semanage_user_query_local {
$action
if (result < 0) {
@@ -1456,7 +1303,6 @@
}
}
-
%exception semanage_user_exists_local {
$action
if (result < 0) {
@@ -1465,7 +1311,6 @@
}
}
-
%exception semanage_user_count_local {
$action
if (result < 0) {
@@ -1474,7 +1319,6 @@
}
}
-
%exception semanage_user_iterate_local {
$action
if (result < 0) {
@@ -1483,7 +1327,6 @@
}
}
-
%exception semanage_user_list_local {
$action
if (result < 0) {
@@ -1492,7 +1335,6 @@
}
}
-
%exception semanage_user_query {
$action
if (result < 0) {
@@ -1501,7 +1343,6 @@
}
}
-
%exception semanage_user_exists {
$action
if (result < 0) {
@@ -1510,7 +1351,6 @@
}
}
-
%exception semanage_user_count {
$action
if (result < 0) {
@@ -1519,7 +1359,6 @@
}
}
-
%exception semanage_user_iterate {
$action
if (result < 0) {
@@ -1528,7 +1367,6 @@
}
}
-
%exception semanage_user_list {
$action
if (result < 0) {
@@ -1537,7 +1375,6 @@
}
}
-
%exception semanage_fcontext_compare {
$action
if (result < 0) {
@@ -1546,7 +1383,6 @@
}
}
-
%exception semanage_fcontext_compare2 {
$action
if (result < 0) {
@@ -1555,7 +1391,6 @@
}
}
-
%exception semanage_fcontext_key_create {
$action
if (result < 0) {
@@ -1564,7 +1399,6 @@
}
}
-
%exception semanage_fcontext_key_extract {
$action
if (result < 0) {
@@ -1573,7 +1407,6 @@
}
}
-
%exception semanage_fcontext_set_expr {
$action
if (result < 0) {
@@ -1582,7 +1415,6 @@
}
}
-
%exception semanage_fcontext_get_type {
$action
if (result < 0) {
@@ -1591,7 +1423,6 @@
}
}
-
%exception semanage_fcontext_set_con {
$action
if (result < 0) {
@@ -1600,7 +1431,6 @@
}
}
-
%exception semanage_fcontext_create {
$action
if (result < 0) {
@@ -1609,7 +1439,6 @@
}
}
-
%exception semanage_fcontext_clone {
$action
if (result < 0) {
@@ -1618,7 +1447,6 @@
}
}
-
%exception semanage_fcontext_modify_local {
$action
if (result < 0) {
@@ -1627,7 +1455,6 @@
}
}
-
%exception semanage_fcontext_del_local {
$action
if (result < 0) {
@@ -1636,7 +1463,6 @@
}
}
-
%exception semanage_fcontext_query_local {
$action
if (result < 0) {
@@ -1645,7 +1471,6 @@
}
}
-
%exception semanage_fcontext_exists_local {
$action
if (result < 0) {
@@ -1654,7 +1479,6 @@
}
}
-
%exception semanage_fcontext_count_local {
$action
if (result < 0) {
@@ -1663,7 +1487,6 @@
}
}
-
%exception semanage_fcontext_iterate_local {
$action
if (result < 0) {
@@ -1672,7 +1495,6 @@
}
}
-
%exception semanage_fcontext_list_local {
$action
if (result < 0) {
@@ -1681,7 +1503,6 @@
}
}
-
%exception semanage_fcontext_query {
$action
if (result < 0) {
@@ -1690,7 +1511,6 @@
}
}
-
%exception semanage_fcontext_exists {
$action
if (result < 0) {
@@ -1699,7 +1519,6 @@
}
}
-
%exception semanage_fcontext_count {
$action
if (result < 0) {
@@ -1708,7 +1527,6 @@
}
}
-
%exception semanage_fcontext_iterate {
$action
if (result < 0) {
@@ -1717,7 +1535,6 @@
}
}
-
%exception semanage_fcontext_list {
$action
if (result < 0) {
@@ -1726,7 +1543,6 @@
}
}
-
%exception semanage_fcontext_list_homedirs {
$action
if (result < 0) {
@@ -1735,7 +1551,6 @@
}
}
-
%exception semanage_seuser_modify_local {
$action
if (result < 0) {
@@ -1744,7 +1559,6 @@
}
}
-
%exception semanage_seuser_del_local {
$action
if (result < 0) {
@@ -1753,7 +1567,6 @@
}
}
-
%exception semanage_seuser_query_local {
$action
if (result < 0) {
@@ -1762,7 +1575,6 @@
}
}
-
%exception semanage_seuser_exists_local {
$action
if (result < 0) {
@@ -1771,7 +1583,6 @@
}
}
-
%exception semanage_seuser_count_local {
$action
if (result < 0) {
@@ -1780,7 +1591,6 @@
}
}
-
%exception semanage_seuser_iterate_local {
$action
if (result < 0) {
@@ -1789,7 +1599,6 @@
}
}
-
%exception semanage_seuser_list_local {
$action
if (result < 0) {
@@ -1798,7 +1607,6 @@
}
}
-
%exception semanage_seuser_query {
$action
if (result < 0) {
@@ -1807,7 +1615,6 @@
}
}
-
%exception semanage_seuser_exists {
$action
if (result < 0) {
@@ -1816,7 +1623,6 @@
}
}
-
%exception semanage_seuser_count {
$action
if (result < 0) {
@@ -1825,7 +1631,6 @@
}
}
-
%exception semanage_seuser_iterate {
$action
if (result < 0) {
@@ -1834,7 +1639,6 @@
}
}
-
%exception semanage_seuser_list {
$action
if (result < 0) {
@@ -1843,7 +1647,6 @@
}
}
-
%exception semanage_port_modify_local {
$action
if (result < 0) {
@@ -1852,7 +1655,6 @@
}
}
-
%exception semanage_port_del_local {
$action
if (result < 0) {
@@ -1861,7 +1663,6 @@
}
}
-
%exception semanage_port_query_local {
$action
if (result < 0) {
@@ -1870,7 +1671,6 @@
}
}
-
%exception semanage_port_exists_local {
$action
if (result < 0) {
@@ -1879,7 +1679,6 @@
}
}
-
%exception semanage_port_count_local {
$action
if (result < 0) {
@@ -1888,7 +1687,6 @@
}
}
-
%exception semanage_port_iterate_local {
$action
if (result < 0) {
@@ -1897,7 +1695,6 @@
}
}
-
%exception semanage_port_list_local {
$action
if (result < 0) {
@@ -1906,7 +1703,6 @@
}
}
-
%exception semanage_port_query {
$action
if (result < 0) {
@@ -1915,7 +1711,6 @@
}
}
-
%exception semanage_port_exists {
$action
if (result < 0) {
@@ -1924,7 +1719,6 @@
}
}
-
%exception semanage_port_count {
$action
if (result < 0) {
@@ -1933,7 +1727,6 @@
}
}
-
%exception semanage_port_iterate {
$action
if (result < 0) {
@@ -1942,7 +1735,6 @@
}
}
-
%exception semanage_port_list {
$action
if (result < 0) {
@@ -1951,7 +1743,6 @@
}
}
-
%exception semanage_ibpkey_modify_local {
$action
if (result < 0) {
@@ -1960,7 +1751,6 @@
}
}
-
%exception semanage_ibpkey_del_local {
$action
if (result < 0) {
@@ -1969,7 +1759,6 @@
}
}
-
%exception semanage_ibpkey_query_local {
$action
if (result < 0) {
@@ -1978,7 +1767,6 @@
}
}
-
%exception semanage_ibpkey_exists_local {
$action
if (result < 0) {
@@ -1987,7 +1775,6 @@
}
}
-
%exception semanage_ibpkey_count_local {
$action
if (result < 0) {
@@ -1996,7 +1783,6 @@
}
}
-
%exception semanage_ibpkey_iterate_local {
$action
if (result < 0) {
@@ -2005,7 +1791,6 @@
}
}
-
%exception semanage_ibpkey_list_local {
$action
if (result < 0) {
@@ -2014,7 +1799,6 @@
}
}
-
%exception semanage_ibendport_modify_local {
$action
if (result < 0) {
@@ -2023,7 +1807,6 @@
}
}
-
%exception semanage_ibendport_del_local {
$action
if (result < 0) {
@@ -2032,7 +1815,6 @@
}
}
-
%exception semanage_ibendport_query_local {
$action
if (result < 0) {
@@ -2041,7 +1823,6 @@
}
}
-
%exception semanage_ibendport_exists_local {
$action
if (result < 0) {
@@ -2050,7 +1831,6 @@
}
}
-
%exception semanage_ibendport_count_local {
$action
if (result < 0) {
@@ -2059,7 +1839,6 @@
}
}
-
%exception semanage_ibendport_iterate_local {
$action
if (result < 0) {
@@ -2068,7 +1847,6 @@
}
}
-
%exception semanage_ibendport_list_local {
$action
if (result < 0) {
@@ -2077,7 +1855,6 @@
}
}
-
%exception semanage_ibendport_query {
$action
if (result < 0) {
@@ -2086,7 +1863,6 @@
}
}
-
%exception semanage_ibendport_exists {
$action
if (result < 0) {
@@ -2095,7 +1871,6 @@
}
}
-
%exception semanage_ibendport_count {
$action
if (result < 0) {
@@ -2104,7 +1879,6 @@
}
}
-
%exception semanage_ibendport_iterate {
$action
if (result < 0) {
@@ -2113,7 +1887,6 @@
}
}
-
%exception semanage_ibendport_list {
$action
if (result < 0) {
@@ -2122,7 +1895,6 @@
}
}
-
%exception semanage_ibpkey_query {
$action
if (result < 0) {
@@ -2131,7 +1903,6 @@
}
}
-
%exception semanage_ibpkey_exists {
$action
if (result < 0) {
@@ -2140,7 +1911,6 @@
}
}
-
%exception semanage_ibpkey_count {
$action
if (result < 0) {
@@ -2149,7 +1919,6 @@
}
}
-
%exception semanage_ibpkey_iterate {
$action
if (result < 0) {
@@ -2158,7 +1927,6 @@
}
}
-
%exception semanage_ibpkey_list {
$action
if (result < 0) {
@@ -2167,7 +1935,6 @@
}
}
-
%exception semanage_iface_modify_local {
$action
if (result < 0) {
@@ -2176,7 +1943,6 @@
}
}
-
%exception semanage_iface_del_local {
$action
if (result < 0) {
@@ -2185,7 +1951,6 @@
}
}
-
%exception semanage_iface_query_local {
$action
if (result < 0) {
@@ -2194,7 +1959,6 @@
}
}
-
%exception semanage_iface_exists_local {
$action
if (result < 0) {
@@ -2203,7 +1967,6 @@
}
}
-
%exception semanage_iface_count_local {
$action
if (result < 0) {
@@ -2212,7 +1975,6 @@
}
}
-
%exception semanage_iface_iterate_local {
$action
if (result < 0) {
@@ -2221,7 +1983,6 @@
}
}
-
%exception semanage_iface_list_local {
$action
if (result < 0) {
@@ -2230,7 +1991,6 @@
}
}
-
%exception semanage_iface_query {
$action
if (result < 0) {
@@ -2239,7 +1999,6 @@
}
}
-
%exception semanage_iface_exists {
$action
if (result < 0) {
@@ -2248,7 +2007,6 @@
}
}
-
%exception semanage_iface_count {
$action
if (result < 0) {
@@ -2257,7 +2015,6 @@
}
}
-
%exception semanage_iface_iterate {
$action
if (result < 0) {
@@ -2266,7 +2023,6 @@
}
}
-
%exception semanage_iface_list {
$action
if (result < 0) {
@@ -2275,7 +2031,6 @@
}
}
-
%exception semanage_node_modify_local {
$action
if (result < 0) {
@@ -2284,7 +2039,6 @@
}
}
-
%exception semanage_node_del_local {
$action
if (result < 0) {
@@ -2293,7 +2047,6 @@
}
}
-
%exception semanage_node_query_local {
$action
if (result < 0) {
@@ -2302,7 +2055,6 @@
}
}
-
%exception semanage_node_exists_local {
$action
if (result < 0) {
@@ -2311,7 +2063,6 @@
}
}
-
%exception semanage_node_count_local {
$action
if (result < 0) {
@@ -2320,7 +2071,6 @@
}
}
-
%exception semanage_node_iterate_local {
$action
if (result < 0) {
@@ -2329,7 +2079,6 @@
}
}
-
%exception semanage_node_list_local {
$action
if (result < 0) {
@@ -2338,7 +2087,6 @@
}
}
-
%exception semanage_node_query {
$action
if (result < 0) {
@@ -2347,7 +2095,6 @@
}
}
-
%exception semanage_node_exists {
$action
if (result < 0) {
@@ -2356,7 +2103,6 @@
}
}
-
%exception semanage_node_count {
$action
if (result < 0) {
@@ -2365,7 +2111,6 @@
}
}
-
%exception semanage_node_iterate {
$action
if (result < 0) {
@@ -2374,7 +2119,6 @@
}
}
-
%exception semanage_node_list {
$action
if (result < 0) {
@@ -2382,4 +2126,3 @@
SWIG_fail;
}
}
-
diff --git a/libsemanage/src/seuser_internal.h b/libsemanage/src/seuser_internal.h
index bf9cab0c..fdb52ef9 100644
--- a/libsemanage/src/seuser_internal.h
+++ b/libsemanage/src/seuser_internal.h
@@ -7,24 +7,6 @@
#include <sepol/policydb.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_seuser_clone)
- hidden_proto(semanage_seuser_compare)
- hidden_proto(semanage_seuser_compare2)
- hidden_proto(semanage_seuser_create)
- hidden_proto(semanage_seuser_free)
- hidden_proto(semanage_seuser_get_mlsrange)
- hidden_proto(semanage_seuser_get_name)
- hidden_proto(semanage_seuser_get_sename)
- hidden_proto(semanage_seuser_key_create)
- hidden_proto(semanage_seuser_key_extract)
- hidden_proto(semanage_seuser_key_free)
- hidden_proto(semanage_seuser_set_mlsrange)
- hidden_proto(semanage_seuser_set_name)
- hidden_proto(semanage_seuser_set_sename)
- hidden_proto(semanage_seuser_iterate)
- hidden_proto(semanage_seuser_iterate_local)
/* SEUSER RECORD: method table */
extern record_table_t SEMANAGE_SEUSER_RTABLE;
@@ -36,7 +18,7 @@ extern int seuser_file_dbase_init(semanage_handle_t * handle,
extern void seuser_file_dbase_release(dbase_config_t * dconfig);
-extern int hidden semanage_seuser_validate_local(semanage_handle_t * handle,
+extern int semanage_seuser_validate_local(semanage_handle_t * handle,
const sepol_policydb_t *
policydb);
diff --git a/libsemanage/src/seuser_record.c b/libsemanage/src/seuser_record.c
index 1ed45948..44a54758 100644
--- a/libsemanage/src/seuser_record.c
+++ b/libsemanage/src/seuser_record.c
@@ -59,7 +59,6 @@ int semanage_seuser_key_create(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_seuser_key_create)
int semanage_seuser_key_extract(semanage_handle_t * handle,
const semanage_seuser_t * seuser,
@@ -76,7 +75,6 @@ int semanage_seuser_key_extract(semanage_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(semanage_seuser_key_extract)
void semanage_seuser_key_free(semanage_seuser_key_t * key)
{
@@ -84,7 +82,6 @@ void semanage_seuser_key_free(semanage_seuser_key_t * key)
free(key);
}
-hidden_def(semanage_seuser_key_free)
int semanage_seuser_compare(const semanage_seuser_t * seuser,
const semanage_seuser_key_t * key)
@@ -93,7 +90,6 @@ int semanage_seuser_compare(const semanage_seuser_t * seuser,
return strcmp(seuser->name, key->name);
}
-hidden_def(semanage_seuser_compare)
int semanage_seuser_compare2(const semanage_seuser_t * seuser,
const semanage_seuser_t * seuser2)
@@ -102,7 +98,6 @@ int semanage_seuser_compare2(const semanage_seuser_t * seuser,
return strcmp(seuser->name, seuser2->name);
}
-hidden_def(semanage_seuser_compare2)
static int semanage_seuser_compare2_qsort(const semanage_seuser_t ** seuser,
const semanage_seuser_t ** seuser2)
@@ -118,7 +113,6 @@ const char *semanage_seuser_get_name(const semanage_seuser_t * seuser)
return seuser->name;
}
-hidden_def(semanage_seuser_get_name)
int semanage_seuser_set_name(semanage_handle_t * handle,
semanage_seuser_t * seuser, const char *name)
@@ -134,7 +128,6 @@ int semanage_seuser_set_name(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_seuser_set_name)
/* Selinux Name */
const char *semanage_seuser_get_sename(const semanage_seuser_t * seuser)
@@ -143,7 +136,6 @@ const char *semanage_seuser_get_sename(const semanage_seuser_t * seuser)
return seuser->sename;
}
-hidden_def(semanage_seuser_get_sename)
int semanage_seuser_set_sename(semanage_handle_t * handle,
semanage_seuser_t * seuser, const char *sename)
@@ -160,7 +152,6 @@ int semanage_seuser_set_sename(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_seuser_set_sename)
/* MLS Range */
const char *semanage_seuser_get_mlsrange(const semanage_seuser_t * seuser)
@@ -169,7 +160,6 @@ const char *semanage_seuser_get_mlsrange(const semanage_seuser_t * seuser)
return seuser->mls_range;
}
-hidden_def(semanage_seuser_get_mlsrange)
int semanage_seuser_set_mlsrange(semanage_handle_t * handle,
semanage_seuser_t * seuser,
@@ -186,7 +176,6 @@ int semanage_seuser_set_mlsrange(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_seuser_set_mlsrange)
/* Create */
int semanage_seuser_create(semanage_handle_t * handle,
@@ -209,7 +198,6 @@ int semanage_seuser_create(semanage_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(semanage_seuser_create)
/* Deep copy clone */
int semanage_seuser_clone(semanage_handle_t * handle,
@@ -242,7 +230,6 @@ int semanage_seuser_clone(semanage_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(semanage_seuser_clone)
/* Destroy */
void semanage_seuser_free(semanage_seuser_t * seuser)
@@ -257,7 +244,6 @@ void semanage_seuser_free(semanage_seuser_t * seuser)
free(seuser);
}
-hidden_def(semanage_seuser_free)
/* Record base functions */
record_table_t SEMANAGE_SEUSER_RTABLE = {
diff --git a/libsemanage/src/seusers_file.c b/libsemanage/src/seusers_file.c
index 910bedf4..21b970ac 100644
--- a/libsemanage/src/seusers_file.c
+++ b/libsemanage/src/seusers_file.c
@@ -53,7 +53,7 @@ static int seuser_parse(semanage_handle_t * handle,
goto last;
/* Extract name */
- if (parse_fetch_string(handle, info, &str, ':') < 0)
+ if (parse_fetch_string(handle, info, &str, ':', 1) < 0)
goto err;
if (semanage_seuser_set_name(handle, seuser, str) < 0)
goto err;
@@ -68,7 +68,7 @@ static int seuser_parse(semanage_handle_t * handle,
goto err;
/* Extract sename */
- if (parse_fetch_string(handle, info, &str, ':') < 0)
+ if (parse_fetch_string(handle, info, &str, ':', 1) < 0)
goto err;
if (semanage_seuser_set_sename(handle, seuser, str) < 0)
goto err;
@@ -83,7 +83,7 @@ static int seuser_parse(semanage_handle_t * handle,
goto err;
/* NOTE: does not allow spaces/multiline */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_seuser_set_mlsrange(handle, seuser, str) < 0)
diff --git a/libsemanage/src/seusers_local.c b/libsemanage/src/seusers_local.c
index 3e2761c4..6508ec05 100644
--- a/libsemanage/src/seusers_local.c
+++ b/libsemanage/src/seusers_local.c
@@ -223,7 +223,6 @@ int semanage_seuser_iterate_local(semanage_handle_t * handle,
return dbase_iterate(handle, dconfig, handler, handler_arg);
}
-hidden_def(semanage_seuser_iterate_local)
int semanage_seuser_list_local(semanage_handle_t * handle,
semanage_seuser_t *** records,
@@ -320,7 +319,7 @@ static int validate_handler(const semanage_seuser_t * seuser, void *varg)
* it will (1) deadlock, because iterate is not reentrant outside
* a transaction, and (2) be racy, because it makes multiple dbase calls */
-int hidden semanage_seuser_validate_local(semanage_handle_t * handle,
+int semanage_seuser_validate_local(semanage_handle_t * handle,
const sepol_policydb_t * policydb)
{
diff --git a/libsemanage/src/seusers_policy.c b/libsemanage/src/seusers_policy.c
index 89fb4d8f..77af0dd2 100644
--- a/libsemanage/src/seusers_policy.c
+++ b/libsemanage/src/seusers_policy.c
@@ -47,7 +47,6 @@ int semanage_seuser_iterate(semanage_handle_t * handle,
return dbase_iterate(handle, dconfig, handler, handler_arg);
}
-hidden_def(semanage_seuser_iterate)
int semanage_seuser_list(semanage_handle_t * handle,
semanage_seuser_t *** records, unsigned int *count)
diff --git a/libsemanage/src/sha256.c b/libsemanage/src/sha256.c
new file mode 100644
index 00000000..fe2aeef0
--- /dev/null
+++ b/libsemanage/src/sha256.c
@@ -0,0 +1,294 @@
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// WjCryptLib_Sha256
+//
+// Implementation of SHA256 hash function.
+// Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+// Modified by WaterJuice retaining Public Domain license.
+//
+// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// IMPORTS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "sha256.h"
+#include <memory.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// MACROS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
+
+#define MIN(x, y) ( ((x)<(y))?(x):(y) )
+
+#define STORE32H(x, y) \
+ { (y)[0] = (uint8_t)(((x)>>24)&255); (y)[1] = (uint8_t)(((x)>>16)&255); \
+ (y)[2] = (uint8_t)(((x)>>8)&255); (y)[3] = (uint8_t)((x)&255); }
+
+#define LOAD32H(x, y) \
+ { x = ((uint32_t)((y)[0] & 255)<<24) | \
+ ((uint32_t)((y)[1] & 255)<<16) | \
+ ((uint32_t)((y)[2] & 255)<<8) | \
+ ((uint32_t)((y)[3] & 255)); }
+
+#define STORE64H(x, y) \
+ { (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255); \
+ (y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255); \
+ (y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255); \
+ (y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// CONSTANTS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// The K array
+static const uint32_t K[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+ 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+ 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+ 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+ 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+ 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+ 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+ 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+ 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+ 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+#define BLOCK_SIZE 64
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// INTERNAL FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Various logical functions
+#define Ch( x, y, z ) (z ^ (x & (y ^ z)))
+#define Maj( x, y, z ) (((x | y) & z) | (x & y))
+#define S( x, n ) ror((x),(n))
+#define R( x, n ) (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0( x ) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1( x ) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0( x ) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1( x ) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+#define Sha256Round( a, b, c, d, e, f, g, h, i ) \
+ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// TransformFunction
+//
+// Compress 512-bits
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+static
+void
+ TransformFunction
+ (
+ Sha256Context* Context,
+ uint8_t const* Buffer
+ )
+{
+ uint32_t S[8];
+ uint32_t W[64];
+ uint32_t t0;
+ uint32_t t1;
+ uint32_t t;
+ int i;
+
+ // Copy state into S
+ for( i=0; i<8; i++ )
+ {
+ S[i] = Context->state[i];
+ }
+
+ // Copy the state into 512-bits into W[0..15]
+ for( i=0; i<16; i++ )
+ {
+ LOAD32H( W[i], Buffer + (4*i) );
+ }
+
+ // Fill W[16..63]
+ for( i=16; i<64; i++ )
+ {
+ W[i] = Gamma1( W[i-2]) + W[i-7] + Gamma0( W[i-15] ) + W[i-16];
+ }
+
+ // Compress
+ for( i=0; i<64; i++ )
+ {
+ Sha256Round( S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i );
+ t = S[7];
+ S[7] = S[6];
+ S[6] = S[5];
+ S[5] = S[4];
+ S[4] = S[3];
+ S[3] = S[2];
+ S[2] = S[1];
+ S[1] = S[0];
+ S[0] = t;
+ }
+
+ // Feedback
+ for( i=0; i<8; i++ )
+ {
+ Context->state[i] = Context->state[i] + S[i];
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sha256Initialise
+//
+// Initialises a SHA256 Context. Use this to initialise/reset a context.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Sha256Initialise
+ (
+ Sha256Context* Context // [out]
+ )
+{
+ Context->curlen = 0;
+ Context->length = 0;
+ Context->state[0] = 0x6A09E667UL;
+ Context->state[1] = 0xBB67AE85UL;
+ Context->state[2] = 0x3C6EF372UL;
+ Context->state[3] = 0xA54FF53AUL;
+ Context->state[4] = 0x510E527FUL;
+ Context->state[5] = 0x9B05688CUL;
+ Context->state[6] = 0x1F83D9ABUL;
+ Context->state[7] = 0x5BE0CD19UL;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sha256Update
+//
+// Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
+// calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Sha256Update
+ (
+ Sha256Context* Context, // [in out]
+ void const* Buffer, // [in]
+ uint32_t BufferSize // [in]
+ )
+{
+ uint32_t n;
+
+ if( Context->curlen > sizeof(Context->buf) )
+ {
+ return;
+ }
+
+ while( BufferSize > 0 )
+ {
+ if( Context->curlen == 0 && BufferSize >= BLOCK_SIZE )
+ {
+ TransformFunction( Context, (uint8_t*)Buffer );
+ Context->length += BLOCK_SIZE * 8;
+ Buffer = (uint8_t*)Buffer + BLOCK_SIZE;
+ BufferSize -= BLOCK_SIZE;
+ }
+ else
+ {
+ n = MIN( BufferSize, (BLOCK_SIZE - Context->curlen) );
+ memcpy( Context->buf + Context->curlen, Buffer, (size_t)n );
+ Context->curlen += n;
+ Buffer = (uint8_t*)Buffer + n;
+ BufferSize -= n;
+ if( Context->curlen == BLOCK_SIZE )
+ {
+ TransformFunction( Context, Context->buf );
+ Context->length += 8*BLOCK_SIZE;
+ Context->curlen = 0;
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sha256Finalise
+//
+// Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
+// calling this, Sha256Initialised must be used to reuse the context.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Sha256Finalise
+ (
+ Sha256Context* Context, // [in out]
+ SHA256_HASH* Digest // [out]
+ )
+{
+ int i;
+
+ if( Context->curlen >= sizeof(Context->buf) )
+ {
+ return;
+ }
+
+ // Increase the length of the message
+ Context->length += Context->curlen * 8;
+
+ // Append the '1' bit
+ Context->buf[Context->curlen++] = (uint8_t)0x80;
+
+ // if the length is currently above 56 bytes we append zeros
+ // then compress. Then we can fall back to padding zeros and length
+ // encoding like normal.
+ if( Context->curlen > 56 )
+ {
+ while( Context->curlen < 64 )
+ {
+ Context->buf[Context->curlen++] = (uint8_t)0;
+ }
+ TransformFunction(Context, Context->buf);
+ Context->curlen = 0;
+ }
+
+ // Pad up to 56 bytes of zeroes
+ while( Context->curlen < 56 )
+ {
+ Context->buf[Context->curlen++] = (uint8_t)0;
+ }
+
+ // Store length
+ STORE64H( Context->length, Context->buf+56 );
+ TransformFunction( Context, Context->buf );
+
+ // Copy output
+ for( i=0; i<8; i++ )
+ {
+ STORE32H( Context->state[i], Digest->bytes+(4*i) );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sha256Calculate
+//
+// Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
+// buffer.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Sha256Calculate
+ (
+ void const* Buffer, // [in]
+ uint32_t BufferSize, // [in]
+ SHA256_HASH* Digest // [in]
+ )
+{
+ Sha256Context context;
+
+ Sha256Initialise( &context );
+ Sha256Update( &context, Buffer, BufferSize );
+ Sha256Finalise( &context, Digest );
+}
diff --git a/libsemanage/src/sha256.h b/libsemanage/src/sha256.h
new file mode 100644
index 00000000..406ed869
--- /dev/null
+++ b/libsemanage/src/sha256.h
@@ -0,0 +1,89 @@
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// WjCryptLib_Sha256
+//
+// Implementation of SHA256 hash function.
+// Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+// Modified by WaterJuice retaining Public Domain license.
+//
+// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// IMPORTS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include <stdint.h>
+#include <stdio.h>
+
+typedef struct
+{
+ uint64_t length;
+ uint32_t state[8];
+ uint32_t curlen;
+ uint8_t buf[64];
+} Sha256Context;
+
+#define SHA256_HASH_SIZE ( 256 / 8 )
+
+typedef struct
+{
+ uint8_t bytes [SHA256_HASH_SIZE];
+} SHA256_HASH;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC FUNCTIONS
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sha256Initialise
+//
+// Initialises a SHA256 Context. Use this to initialise/reset a context.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Sha256Initialise
+ (
+ Sha256Context* Context // [out]
+ );
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sha256Update
+//
+// Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
+// calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Sha256Update
+ (
+ Sha256Context* Context, // [in out]
+ void const* Buffer, // [in]
+ uint32_t BufferSize // [in]
+ );
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sha256Finalise
+//
+// Performs the final calculation of the hash and returns the digest (32 byte buffer containing 256bit hash). After
+// calling this, Sha256Initialised must be used to reuse the context.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Sha256Finalise
+ (
+ Sha256Context* Context, // [in out]
+ SHA256_HASH* Digest // [out]
+ );
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Sha256Calculate
+//
+// Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
+// buffer.
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void
+ Sha256Calculate
+ (
+ void const* Buffer, // [in]
+ uint32_t BufferSize, // [in]
+ SHA256_HASH* Digest // [in]
+ );
diff --git a/libsemanage/src/user_base_record.c b/libsemanage/src/user_base_record.c
index 7dfa8c6b..47037665 100644
--- a/libsemanage/src/user_base_record.c
+++ b/libsemanage/src/user_base_record.c
@@ -25,7 +25,7 @@ typedef semanage_user_key_t record_key_t;
#include "debug.h"
/* Key */
-hidden int semanage_user_base_key_extract(semanage_handle_t * handle,
+ int semanage_user_base_key_extract(semanage_handle_t * handle,
const semanage_user_base_t * user,
semanage_user_key_t ** key)
{
@@ -56,14 +56,14 @@ static int semanage_user_base_compare2_qsort(const semanage_user_base_t ** user,
}
/* Name */
-hidden const char *semanage_user_base_get_name(const semanage_user_base_t *
+ const char *semanage_user_base_get_name(const semanage_user_base_t *
user)
{
return sepol_user_get_name(user);
}
-hidden int semanage_user_base_set_name(semanage_handle_t * handle,
+ int semanage_user_base_set_name(semanage_handle_t * handle,
semanage_user_base_t * user,
const char *name)
{
@@ -72,14 +72,14 @@ hidden int semanage_user_base_set_name(semanage_handle_t * handle,
}
/* MLS */
-hidden const char *semanage_user_base_get_mlslevel(const semanage_user_base_t *
+ const char *semanage_user_base_get_mlslevel(const semanage_user_base_t *
user)
{
return sepol_user_get_mlslevel(user);
}
-hidden int semanage_user_base_set_mlslevel(semanage_handle_t * handle,
+ int semanage_user_base_set_mlslevel(semanage_handle_t * handle,
semanage_user_base_t * user,
const char *mls_level)
{
@@ -87,14 +87,14 @@ hidden int semanage_user_base_set_mlslevel(semanage_handle_t * handle,
return sepol_user_set_mlslevel(handle->sepolh, user, mls_level);
}
-hidden const char *semanage_user_base_get_mlsrange(const semanage_user_base_t *
+ const char *semanage_user_base_get_mlsrange(const semanage_user_base_t *
user)
{
return sepol_user_get_mlsrange(user);
}
-hidden int semanage_user_base_set_mlsrange(semanage_handle_t * handle,
+ int semanage_user_base_set_mlsrange(semanage_handle_t * handle,
semanage_user_base_t * user,
const char *mls_range)
{
@@ -103,13 +103,13 @@ hidden int semanage_user_base_set_mlsrange(semanage_handle_t * handle,
}
/* Role management */
-hidden int semanage_user_base_get_num_roles(const semanage_user_base_t * user)
+ int semanage_user_base_get_num_roles(const semanage_user_base_t * user)
{
return sepol_user_get_num_roles(user);
}
-hidden int semanage_user_base_add_role(semanage_handle_t * handle,
+ int semanage_user_base_add_role(semanage_handle_t * handle,
semanage_user_base_t * user,
const char *role)
{
@@ -117,21 +117,21 @@ hidden int semanage_user_base_add_role(semanage_handle_t * handle,
return sepol_user_add_role(handle->sepolh, user, role);
}
-hidden void semanage_user_base_del_role(semanage_user_base_t * user,
+ void semanage_user_base_del_role(semanage_user_base_t * user,
const char *role)
{
sepol_user_del_role(user, role);
}
-hidden int semanage_user_base_has_role(const semanage_user_base_t * user,
+ int semanage_user_base_has_role(const semanage_user_base_t * user,
const char *role)
{
return sepol_user_has_role(user, role);
}
-hidden int semanage_user_base_get_roles(semanage_handle_t * handle,
+ int semanage_user_base_get_roles(semanage_handle_t * handle,
const semanage_user_base_t * user,
const char ***roles_arr,
unsigned int *num_roles)
@@ -140,7 +140,7 @@ hidden int semanage_user_base_get_roles(semanage_handle_t * handle,
return sepol_user_get_roles(handle->sepolh, user, roles_arr, num_roles);
}
-hidden int semanage_user_base_set_roles(semanage_handle_t * handle,
+ int semanage_user_base_set_roles(semanage_handle_t * handle,
semanage_user_base_t * user,
const char **roles_arr,
unsigned int num_roles)
@@ -150,14 +150,14 @@ hidden int semanage_user_base_set_roles(semanage_handle_t * handle,
}
/* Create/Clone/Destroy */
-hidden int semanage_user_base_create(semanage_handle_t * handle,
+ int semanage_user_base_create(semanage_handle_t * handle,
semanage_user_base_t ** user_ptr)
{
return sepol_user_create(handle->sepolh, user_ptr);
}
-hidden int semanage_user_base_clone(semanage_handle_t * handle,
+ int semanage_user_base_clone(semanage_handle_t * handle,
const semanage_user_base_t * user,
semanage_user_base_t ** user_ptr)
{
@@ -165,7 +165,7 @@ hidden int semanage_user_base_clone(semanage_handle_t * handle,
return sepol_user_clone(handle->sepolh, user, user_ptr);
}
-hidden void semanage_user_base_free(semanage_user_base_t * user)
+ void semanage_user_base_free(semanage_user_base_t * user)
{
sepol_user_free(user);
diff --git a/libsemanage/src/user_extra_record.c b/libsemanage/src/user_extra_record.c
index efb9c5bf..d2707224 100644
--- a/libsemanage/src/user_extra_record.c
+++ b/libsemanage/src/user_extra_record.c
@@ -76,14 +76,14 @@ static int semanage_user_extra_compare2_qsort(const semanage_user_extra_t **
}
/* Name */
-hidden const char *semanage_user_extra_get_name(const semanage_user_extra_t *
+ const char *semanage_user_extra_get_name(const semanage_user_extra_t *
user_extra)
{
return user_extra->name;
}
-hidden int semanage_user_extra_set_name(semanage_handle_t * handle,
+ int semanage_user_extra_set_name(semanage_handle_t * handle,
semanage_user_extra_t * user_extra,
const char *name)
{
@@ -100,14 +100,14 @@ hidden int semanage_user_extra_set_name(semanage_handle_t * handle,
}
/* Labeling prefix */
-hidden const char *semanage_user_extra_get_prefix(const semanage_user_extra_t *
+ const char *semanage_user_extra_get_prefix(const semanage_user_extra_t *
user_extra)
{
return user_extra->prefix;
}
-hidden int semanage_user_extra_set_prefix(semanage_handle_t * handle,
+ int semanage_user_extra_set_prefix(semanage_handle_t * handle,
semanage_user_extra_t * user_extra,
const char *prefix)
{
@@ -124,7 +124,7 @@ hidden int semanage_user_extra_set_prefix(semanage_handle_t * handle,
}
/* Create */
-hidden int semanage_user_extra_create(semanage_handle_t * handle,
+ int semanage_user_extra_create(semanage_handle_t * handle,
semanage_user_extra_t ** user_extra_ptr)
{
@@ -145,7 +145,7 @@ hidden int semanage_user_extra_create(semanage_handle_t * handle,
}
/* Destroy */
-hidden void semanage_user_extra_free(semanage_user_extra_t * user_extra)
+ void semanage_user_extra_free(semanage_user_extra_t * user_extra)
{
if (!user_extra)
@@ -157,7 +157,7 @@ hidden void semanage_user_extra_free(semanage_user_extra_t * user_extra)
}
/* Deep copy clone */
-hidden int semanage_user_extra_clone(semanage_handle_t * handle,
+ int semanage_user_extra_clone(semanage_handle_t * handle,
const semanage_user_extra_t * user_extra,
semanage_user_extra_t ** user_extra_ptr)
{
diff --git a/libsemanage/src/user_internal.h b/libsemanage/src/user_internal.h
index 2fede947..678a73a5 100644
--- a/libsemanage/src/user_internal.h
+++ b/libsemanage/src/user_internal.h
@@ -7,26 +7,6 @@
#include <semanage/users_policy.h>
#include "database.h"
#include "handle.h"
-#include "dso.h"
-
-hidden_proto(semanage_user_add_role)
- hidden_proto(semanage_user_clone)
- hidden_proto(semanage_user_compare)
- hidden_proto(semanage_user_compare2)
- hidden_proto(semanage_user_create)
- hidden_proto(semanage_user_free)
- hidden_proto(semanage_user_get_mlslevel)
- hidden_proto(semanage_user_get_mlsrange)
- hidden_proto(semanage_user_get_name)
- hidden_proto(semanage_user_get_roles)
- hidden_proto(semanage_user_key_create)
- hidden_proto(semanage_user_key_extract)
- hidden_proto(semanage_user_key_free)
- hidden_proto(semanage_user_set_mlslevel)
- hidden_proto(semanage_user_set_mlsrange)
- hidden_proto(semanage_user_set_name)
- hidden_proto(semanage_user_exists)
- hidden_proto(semanage_user_query)
/* USER record: method table */
extern record_table_t SEMANAGE_USER_RTABLE;
@@ -77,99 +57,99 @@ typedef struct semanage_user_base semanage_user_base_t;
#define _SEMANAGE_USER_BASE_DEFINED_
#endif
-hidden int semanage_user_base_create(semanage_handle_t * handle,
+ int semanage_user_base_create(semanage_handle_t * handle,
semanage_user_base_t ** user_ptr);
-hidden int semanage_user_base_clone(semanage_handle_t * handle,
+ int semanage_user_base_clone(semanage_handle_t * handle,
const semanage_user_base_t * user,
semanage_user_base_t ** user_ptr);
-hidden int semanage_user_base_key_extract(semanage_handle_t * handle,
+ int semanage_user_base_key_extract(semanage_handle_t * handle,
const semanage_user_base_t * user,
semanage_user_key_t ** key);
-hidden const char *semanage_user_base_get_name(const semanage_user_base_t *
+ const char *semanage_user_base_get_name(const semanage_user_base_t *
user);
-hidden int semanage_user_base_set_name(semanage_handle_t * handle,
+ int semanage_user_base_set_name(semanage_handle_t * handle,
semanage_user_base_t * user,
const char *name);
-hidden const char *semanage_user_base_get_mlslevel(const semanage_user_base_t *
+ const char *semanage_user_base_get_mlslevel(const semanage_user_base_t *
user);
-hidden int semanage_user_base_set_mlslevel(semanage_handle_t * handle,
+ int semanage_user_base_set_mlslevel(semanage_handle_t * handle,
semanage_user_base_t * user,
const char *mls_level);
-hidden const char *semanage_user_base_get_mlsrange(const semanage_user_base_t *
+ const char *semanage_user_base_get_mlsrange(const semanage_user_base_t *
user);
-hidden int semanage_user_base_set_mlsrange(semanage_handle_t * handle,
+ int semanage_user_base_set_mlsrange(semanage_handle_t * handle,
semanage_user_base_t * user,
const char *mls_range);
-hidden int semanage_user_base_get_num_roles(const semanage_user_base_t * user);
+ int semanage_user_base_get_num_roles(const semanage_user_base_t * user);
-hidden int semanage_user_base_add_role(semanage_handle_t * handle,
+ int semanage_user_base_add_role(semanage_handle_t * handle,
semanage_user_base_t * user,
const char *role);
-hidden void semanage_user_base_del_role(semanage_user_base_t * user,
+ void semanage_user_base_del_role(semanage_user_base_t * user,
const char *role);
-hidden int semanage_user_base_has_role(const semanage_user_base_t * user,
+ int semanage_user_base_has_role(const semanage_user_base_t * user,
const char *role);
-hidden int semanage_user_base_get_roles(semanage_handle_t * handle,
+ int semanage_user_base_get_roles(semanage_handle_t * handle,
const semanage_user_base_t * user,
const char ***roles_arr,
unsigned int *num_roles);
-hidden int semanage_user_base_set_roles(semanage_handle_t * handle,
+ int semanage_user_base_set_roles(semanage_handle_t * handle,
semanage_user_base_t * user,
const char **roles_arr,
unsigned int num_roles);
-hidden void semanage_user_base_free(semanage_user_base_t * user);
+ void semanage_user_base_free(semanage_user_base_t * user);
/*=========== Internal API: Extra User record ==========*/
struct semanage_user_extra;
typedef struct semanage_user_extra semanage_user_extra_t;
-hidden int semanage_user_extra_create(semanage_handle_t * handle,
+ int semanage_user_extra_create(semanage_handle_t * handle,
semanage_user_extra_t ** user_extra_ptr);
-hidden int semanage_user_extra_clone(semanage_handle_t * handle,
+ int semanage_user_extra_clone(semanage_handle_t * handle,
const semanage_user_extra_t * user_extra,
semanage_user_extra_t ** user_extra_ptr);
-hidden const char *semanage_user_extra_get_name(const semanage_user_extra_t *
+ const char *semanage_user_extra_get_name(const semanage_user_extra_t *
user_extra);
-hidden int semanage_user_extra_set_name(semanage_handle_t * handle,
+ int semanage_user_extra_set_name(semanage_handle_t * handle,
semanage_user_extra_t * user_extra,
const char *name);
-hidden const char *semanage_user_extra_get_prefix(const semanage_user_extra_t *
+ const char *semanage_user_extra_get_prefix(const semanage_user_extra_t *
user_extra);
-hidden int semanage_user_extra_set_prefix(semanage_handle_t * handle,
+ int semanage_user_extra_set_prefix(semanage_handle_t * handle,
semanage_user_extra_t * user_extra,
const char *prefix);
-hidden void semanage_user_extra_free(semanage_user_extra_t * user_extra);
+ void semanage_user_extra_free(semanage_user_extra_t * user_extra);
/*======== Internal API: Join record ========== */
-hidden void semanage_user_key_unpack(const semanage_user_key_t * key,
+ void semanage_user_key_unpack(const semanage_user_key_t * key,
const char **name);
-hidden int semanage_user_join(semanage_handle_t * handle,
+ int semanage_user_join(semanage_handle_t * handle,
const semanage_user_base_t * record1,
const semanage_user_extra_t * record2,
semanage_user_t ** result);
-hidden int semanage_user_split(semanage_handle_t * handle,
+ int semanage_user_split(semanage_handle_t * handle,
const semanage_user_t * record,
semanage_user_base_t ** split1,
semanage_user_extra_t ** split2);
diff --git a/libsemanage/src/user_record.c b/libsemanage/src/user_record.c
index 45239250..bb8f4de1 100644
--- a/libsemanage/src/user_record.c
+++ b/libsemanage/src/user_record.c
@@ -37,7 +37,6 @@ int semanage_user_key_create(semanage_handle_t * handle,
return sepol_user_key_create(handle->sepolh, name, key);
}
-hidden_def(semanage_user_key_create)
int semanage_user_key_extract(semanage_handle_t * handle,
const semanage_user_t * user,
@@ -47,7 +46,6 @@ int semanage_user_key_extract(semanage_handle_t * handle,
return semanage_user_base_key_extract(handle, user->base, key);
}
-hidden_def(semanage_user_key_extract)
void semanage_user_key_free(semanage_user_key_t * key)
{
@@ -55,9 +53,8 @@ void semanage_user_key_free(semanage_user_key_t * key)
sepol_user_key_free(key);
}
-hidden_def(semanage_user_key_free)
-hidden void semanage_user_key_unpack(const semanage_user_key_t * key,
+ void semanage_user_key_unpack(const semanage_user_key_t * key,
const char **name)
{
@@ -73,7 +70,6 @@ int semanage_user_compare(const semanage_user_t * user,
return strcmp(user->name, name);
}
-hidden_def(semanage_user_compare)
int semanage_user_compare2(const semanage_user_t * user,
const semanage_user_t * user2)
@@ -82,7 +78,6 @@ int semanage_user_compare2(const semanage_user_t * user,
return strcmp(user->name, user2->name);
}
-hidden_def(semanage_user_compare2)
static int semanage_user_compare2_qsort(const semanage_user_t ** user,
const semanage_user_t ** user2)
@@ -97,7 +92,6 @@ const char *semanage_user_get_name(const semanage_user_t * user)
return user->name;
}
-hidden_def(semanage_user_get_name)
int semanage_user_set_name(semanage_handle_t * handle,
semanage_user_t * user, const char *name)
@@ -126,7 +120,6 @@ int semanage_user_set_name(semanage_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(semanage_user_set_name)
/* Labeling prefix */
const char *semanage_user_get_prefix(const semanage_user_t * user)
@@ -149,7 +142,6 @@ const char *semanage_user_get_mlslevel(const semanage_user_t * user)
return semanage_user_base_get_mlslevel(user->base);
}
-hidden_def(semanage_user_get_mlslevel)
int semanage_user_set_mlslevel(semanage_handle_t * handle,
semanage_user_t * user, const char *mls_level)
@@ -158,7 +150,6 @@ int semanage_user_set_mlslevel(semanage_handle_t * handle,
return semanage_user_base_set_mlslevel(handle, user->base, mls_level);
}
-hidden_def(semanage_user_set_mlslevel)
const char *semanage_user_get_mlsrange(const semanage_user_t * user)
{
@@ -166,7 +157,6 @@ const char *semanage_user_get_mlsrange(const semanage_user_t * user)
return semanage_user_base_get_mlsrange(user->base);
}
-hidden_def(semanage_user_get_mlsrange)
int semanage_user_set_mlsrange(semanage_handle_t * handle,
semanage_user_t * user, const char *mls_range)
@@ -175,7 +165,6 @@ int semanage_user_set_mlsrange(semanage_handle_t * handle,
return semanage_user_base_set_mlsrange(handle, user->base, mls_range);
}
-hidden_def(semanage_user_set_mlsrange)
/* Role management */
int semanage_user_get_num_roles(const semanage_user_t * user)
@@ -191,7 +180,6 @@ int semanage_user_add_role(semanage_handle_t * handle,
return semanage_user_base_add_role(handle, user->base, role);
}
-hidden_def(semanage_user_add_role)
void semanage_user_del_role(semanage_user_t * user, const char *role)
{
@@ -214,7 +202,6 @@ int semanage_user_get_roles(semanage_handle_t * handle,
num_roles);
}
-hidden_def(semanage_user_get_roles)
int semanage_user_set_roles(semanage_handle_t * handle,
semanage_user_t * user,
@@ -255,7 +242,6 @@ int semanage_user_create(semanage_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(semanage_user_create)
int semanage_user_clone(semanage_handle_t * handle,
const semanage_user_t * user,
@@ -289,7 +275,6 @@ int semanage_user_clone(semanage_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(semanage_user_clone)
void semanage_user_free(semanage_user_t * user)
{
@@ -303,10 +288,9 @@ void semanage_user_free(semanage_user_t * user)
free(user);
}
-hidden_def(semanage_user_free)
/* Join properties */
-hidden int semanage_user_join(semanage_handle_t * handle,
+ int semanage_user_join(semanage_handle_t * handle,
const semanage_user_base_t * record1,
const semanage_user_extra_t * record2,
semanage_user_t ** result)
@@ -369,7 +353,7 @@ hidden int semanage_user_join(semanage_handle_t * handle,
return STATUS_ERR;
}
-hidden int semanage_user_split(semanage_handle_t * handle,
+ int semanage_user_split(semanage_handle_t * handle,
const semanage_user_t * record,
semanage_user_base_t ** split1,
semanage_user_extra_t ** split2)
diff --git a/libsemanage/src/users_base_file.c b/libsemanage/src/users_base_file.c
index 0f0a8fdb..a0f8cd7e 100644
--- a/libsemanage/src/users_base_file.c
+++ b/libsemanage/src/users_base_file.c
@@ -83,7 +83,7 @@ static int user_base_parse(semanage_handle_t * handle,
goto err;
/* Parse user name */
- if (parse_fetch_string(handle, info, &name_str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &name_str, ' ', 0) < 0)
goto err;
if (semanage_user_base_set_name(handle, user, name_str) < 0) {
@@ -150,7 +150,7 @@ static int user_base_parse(semanage_handle_t * handle,
goto err;
/* NOTE: does not allow spaces/multiline */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_user_base_set_mlslevel(handle, user, str) < 0)
goto err;
@@ -165,8 +165,7 @@ static int user_base_parse(semanage_handle_t * handle,
if (parse_assert_space(handle, info) < 0)
goto err;
- /* NOTE: does not allow spaces/multiline */
- if (parse_fetch_string(handle, info, &str, ';') < 0)
+ if (parse_fetch_string(handle, info, &str, ';', 1) < 0)
goto err;
if (semanage_user_base_set_mlsrange(handle, user, str) < 0)
goto err;
diff --git a/libsemanage/src/users_extra_file.c b/libsemanage/src/users_extra_file.c
index 8f2bebd6..7aa9df3c 100644
--- a/libsemanage/src/users_extra_file.c
+++ b/libsemanage/src/users_extra_file.c
@@ -57,7 +57,7 @@ static int user_extra_parse(semanage_handle_t * handle,
goto err;
/* Extract name */
- if (parse_fetch_string(handle, info, &str, ' ') < 0)
+ if (parse_fetch_string(handle, info, &str, ' ', 0) < 0)
goto err;
if (semanage_user_extra_set_name(handle, user_extra, str) < 0)
goto err;
@@ -73,7 +73,7 @@ static int user_extra_parse(semanage_handle_t * handle,
goto err;
/* Extract prefix */
- if (parse_fetch_string(handle, info, &str, ';') < 0)
+ if (parse_fetch_string(handle, info, &str, ';', 1) < 0)
goto err;
if (semanage_user_extra_set_prefix(handle, user_extra, str) < 0)
goto err;
diff --git a/libsemanage/src/users_policy.c b/libsemanage/src/users_policy.c
index 74f59dc1..a7551324 100644
--- a/libsemanage/src/users_policy.c
+++ b/libsemanage/src/users_policy.c
@@ -19,7 +19,6 @@ int semanage_user_query(semanage_handle_t * handle,
return dbase_query(handle, dconfig, key, response);
}
-hidden_def(semanage_user_query)
int semanage_user_exists(semanage_handle_t * handle,
const semanage_user_key_t * key, int *response)
@@ -29,7 +28,6 @@ int semanage_user_exists(semanage_handle_t * handle,
return dbase_exists(handle, dconfig, key, response);
}
-hidden_def(semanage_user_exists)
int semanage_user_count(semanage_handle_t * handle, unsigned int *response)
{
diff --git a/libsemanage/src/utilities.c b/libsemanage/src/utilities.c
index fc5a6a51..fdbb8ad6 100644
--- a/libsemanage/src/utilities.c
+++ b/libsemanage/src/utilities.c
@@ -292,7 +292,7 @@ char *semanage_str_replace(const char *search, const char *replace,
*
* returns the newly created node or NULL on error
*/
-semanage_list_t *list_addafter_controlmem(semanage_list_t * item, char *data)
+static semanage_list_t *list_addafter_controlmem(semanage_list_t * item, char *data)
{
semanage_list_t *temp = malloc(sizeof(semanage_list_t));
diff --git a/libsemanage/tests/libsemanage-tests.c b/libsemanage/tests/libsemanage-tests.c
index 2ae4a21b..ee176703 100644
--- a/libsemanage/tests/libsemanage-tests.c
+++ b/libsemanage/tests/libsemanage-tests.c
@@ -41,13 +41,17 @@
#include <stdlib.h>
#define DECLARE_SUITE(name) \
- suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \
- if (NULL == suite) { \
- CU_cleanup_registry(); \
- return CU_get_error(); } \
- if (name##_add_tests(suite)) { \
- CU_cleanup_registry(); \
- return CU_get_error(); }
+ do { \
+ suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \
+ if (NULL == suite) { \
+ CU_cleanup_registry(); \
+ return CU_get_error(); \
+ } \
+ if (name##_add_tests(suite)) { \
+ CU_cleanup_registry(); \
+ return CU_get_error(); \
+ } \
+ } while (0)
static void usage(char *progname)
{
diff --git a/libsemanage/tests/test_bool.c b/libsemanage/tests/test_bool.c
index ae80d448..7bf5225b 100644
--- a/libsemanage/tests/test_bool.c
+++ b/libsemanage/tests/test_bool.c
@@ -132,6 +132,8 @@ semanage_bool_t *get_bool_nth(int idx)
if (i != (unsigned int) idx)
semanage_bool_free(records[i]);
+ free(records);
+
return boolean;
}
@@ -163,6 +165,8 @@ semanage_bool_key_t *get_bool_key_nth(int idx)
CU_ASSERT_FATAL(res >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+ semanage_bool_free(boolean);
+
return key;
}
@@ -196,6 +200,9 @@ void add_local_bool(const char *name)
CU_ASSERT_PTR_NOT_NULL_FATAL(boolean);
CU_ASSERT_FATAL(semanage_bool_modify_local(sh, key, boolean) >= 0);
+
+ semanage_bool_key_free(key);
+ semanage_bool_free(boolean);
}
void delete_local_bool(const char *name)
@@ -208,6 +215,8 @@ void delete_local_bool(const char *name)
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
CU_ASSERT_FATAL(semanage_bool_del_local(sh, key) >= 0);
+
+ semanage_bool_key_free(key);
}
/* Function bool_key_create */
@@ -447,6 +456,8 @@ void helper_bool_create(level_t level)
CU_ASSERT_PTR_NULL(semanage_bool_get_name(boolean));
CU_ASSERT(semanage_bool_get_value(boolean) == 0);
+ semanage_bool_free(boolean);
+
cleanup_handle(level);
}
@@ -483,6 +494,9 @@ void helper_bool_clone(level_t level, int bool_idx)
CU_ASSERT_EQUAL(val, val_clone);
+ semanage_bool_free(boolean_clone);
+ semanage_bool_free(boolean);
+
cleanup_handle(level);
}
@@ -514,6 +528,9 @@ void helper_bool_query(level_t level, const char *bool_str, int exp_res)
CU_ASSERT_PTR_NULL(resp);
}
+ semanage_bool_free(resp);
+ semanage_bool_key_free(key);
+
cleanup_handle(level);
}
@@ -647,6 +664,8 @@ void helper_bool_list(level_t level)
for (unsigned int i = 0; i < count; i++)
semanage_bool_free(records[i]);
+ free(records);
+
cleanup_handle(level);
}
@@ -662,7 +681,7 @@ void helper_bool_modify_del_local(level_t level, const char *name,
int old_val, int exp_res)
{
semanage_bool_t *boolean;
- semanage_bool_t *boolean_local;
+ semanage_bool_t *boolean_local = NULL;
semanage_bool_key_t *key = NULL;
int res;
int new_val;
@@ -696,6 +715,8 @@ void helper_bool_modify_del_local(level_t level, const char *name,
CU_ASSERT(semanage_bool_query_local(sh, key,
&boolean_local) >= 0);
CU_ASSERT(semanage_bool_compare2(boolean_local, boolean) == 0);
+ semanage_bool_free(boolean_local);
+
CU_ASSERT(semanage_bool_del_local(sh, key) >= 0);
CU_ASSERT(semanage_bool_query_local(sh, key,
&boolean_local) < 0);
@@ -734,15 +755,18 @@ void test_bool_query_local(void)
/* transaction */
setup_handle(SH_TRANS);
+ semanage_bool_key_free(key);
CU_ASSERT(semanage_bool_key_create(sh, BOOL1_NAME, &key) >= 0);
CU_ASSERT_PTR_NOT_NULL(key);
CU_ASSERT(semanage_bool_query_local(sh, key, &resp) < 0);
CU_ASSERT_PTR_NULL(resp);
+ semanage_bool_free(resp);
add_local_bool(BOOL1_NAME);
CU_ASSERT(semanage_bool_query_local(sh, key, &resp) >= 0);
CU_ASSERT_PTR_NOT_NULL(resp);
+ semanage_bool_free(resp);
semanage_bool_key_free(key);
CU_ASSERT(semanage_bool_key_create(sh, BOOL2_NAME, &key) >= 0);
@@ -751,8 +775,10 @@ void test_bool_query_local(void)
add_local_bool(BOOL2_NAME);
CU_ASSERT(semanage_bool_query_local(sh, key, &resp) >= 0);
CU_ASSERT_PTR_NOT_NULL(resp);
+ semanage_bool_free(resp);
/* cleanup */
+ semanage_bool_key_free(key);
delete_local_bool(BOOL1_NAME);
delete_local_bool(BOOL2_NAME);
cleanup_handle(SH_TRANS);
@@ -784,6 +810,7 @@ void test_bool_exists_local(void)
CU_ASSERT(resp == 0);
/* cleanup */
+ semanage_bool_key_free(key);
cleanup_handle(SH_TRANS);
}
@@ -918,12 +945,17 @@ void test_bool_list_local(void)
CU_ASSERT(semanage_bool_list_local(sh, &records, &count) >= 0);
CU_ASSERT(count == init_count + 1);
CU_ASSERT_PTR_NOT_NULL(records[0]);
+ semanage_bool_free(records[0]);
+ free(records);
add_local_bool(BOOL2_NAME);
CU_ASSERT(semanage_bool_list_local(sh, &records, &count) >= 0);
CU_ASSERT(count == init_count + 2);
CU_ASSERT_PTR_NOT_NULL(records[0]);
CU_ASSERT_PTR_NOT_NULL(records[1]);
+ semanage_bool_free(records[0]);
+ semanage_bool_free(records[1]);
+ free(records);
/* cleanup */
delete_local_bool(BOOL1_NAME);
diff --git a/libsemanage/tests/test_fcontext.c b/libsemanage/tests/test_fcontext.c
index 62af711f..a5fcf849 100644
--- a/libsemanage/tests/test_fcontext.c
+++ b/libsemanage/tests/test_fcontext.c
@@ -214,6 +214,8 @@ semanage_fcontext_t *get_fcontext_nth(int idx)
if (i != (unsigned int) idx)
semanage_fcontext_free(records[i]);
+ free(records);
+
return fcontext;
}
@@ -230,6 +232,8 @@ semanage_fcontext_key_t *get_fcontext_key_nth(int idx)
CU_ASSERT_FATAL(semanage_fcontext_key_extract(sh, fcontext, &key) >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+ semanage_fcontext_free(fcontext);
+
return key;
}
@@ -246,6 +250,10 @@ void add_local_fcontext(int fcontext_idx)
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
CU_ASSERT_FATAL(semanage_fcontext_modify_local(sh, key, fcontext) >= 0);
+
+ /* cleanup */
+ semanage_fcontext_key_free(key);
+ semanage_fcontext_free(fcontext);
}
void delete_local_fcontext(int fcontext_idx)
@@ -257,6 +265,8 @@ void delete_local_fcontext(int fcontext_idx)
key = get_fcontext_key_nth(fcontext_idx);
CU_ASSERT_FATAL(semanage_fcontext_del_local(sh, key) >= 0);
+
+ semanage_fcontext_key_free(key);
}
semanage_fcontext_key_t *get_fcontext_key_from_str(const char *str, int type)
@@ -477,6 +487,7 @@ void helper_fcontext_get_set_con(level_t level, int fcontext_idx,
}
/* cleanup */
+ semanage_context_free(con);
semanage_fcontext_free(fcontext);
cleanup_handle(level);
}
@@ -587,12 +598,14 @@ void helper_fcontext_query(level_t level, const char *fcontext_expr,
CU_ASSERT(res >= 0);
const char *expr = semanage_fcontext_get_expr(resp);
CU_ASSERT_STRING_EQUAL(expr, fcontext_expr);
+ semanage_fcontext_free(resp);
} else {
CU_ASSERT(res < 0);
CU_ASSERT(resp == (void *) 42);
}
/* cleanup */
+ semanage_fcontext_key_free(key);
cleanup_handle(level);
}
@@ -752,6 +765,8 @@ void helper_fcontext_list(level_t level)
for (unsigned int i = 0; i < count; i++)
semanage_fcontext_free(records[i]);
+ free(records);
+
/* cleanup */
cleanup_handle(level);
}
@@ -768,7 +783,7 @@ void helper_fcontext_modify_del_local(level_t level, int fcontext_idx,
const char *con_str, int exp_res)
{
semanage_fcontext_t *fcontext;
- semanage_fcontext_t *fcontext_local;
+ semanage_fcontext_t *fcontext_local = NULL;
semanage_fcontext_key_t *key = NULL;
semanage_context_t *con = NULL;
int res;
@@ -803,6 +818,8 @@ void helper_fcontext_modify_del_local(level_t level, int fcontext_idx,
&fcontext_local) >= 0);
CU_ASSERT(semanage_fcontext_compare2(fcontext_local,
fcontext) == 0);
+ semanage_fcontext_free(fcontext_local);
+
CU_ASSERT(semanage_fcontext_del_local(sh, key) >= 0);
CU_ASSERT(semanage_fcontext_query_local(sh, key,
&fcontext_local) < 0);
@@ -811,6 +828,7 @@ void helper_fcontext_modify_del_local(level_t level, int fcontext_idx,
}
/* cleanup */
+ semanage_context_free(con);
semanage_fcontext_key_free(key);
semanage_fcontext_free(fcontext);
cleanup_handle(level);
@@ -846,6 +864,7 @@ void test_fcontext_query_local(void)
/* transaction */
setup_handle(SH_TRANS);
+ semanage_fcontext_key_free(key);
key = get_fcontext_key_nth(I_FIRST);
CU_ASSERT(semanage_fcontext_query_local(sh, key, &resp) < 0);
CU_ASSERT_PTR_NULL(resp);
@@ -853,14 +872,19 @@ void test_fcontext_query_local(void)
add_local_fcontext(I_FIRST);
CU_ASSERT(semanage_fcontext_query_local(sh, key, &resp) >= 0);
CU_ASSERT_PTR_NOT_NULL(resp);
+ semanage_fcontext_free(resp);
+ resp = NULL;
semanage_fcontext_key_free(key);
key = get_fcontext_key_nth(I_SECOND);
add_local_fcontext(I_SECOND);
CU_ASSERT(semanage_fcontext_query_local(sh, key, &resp) >= 0);
CU_ASSERT_PTR_NOT_NULL(resp);
+ semanage_fcontext_free(resp);
+ resp = NULL;
/* cleanup */
+ semanage_fcontext_key_free(key);
delete_local_fcontext(I_FIRST);
delete_local_fcontext(I_SECOND);
cleanup_handle(SH_TRANS);
@@ -898,6 +922,7 @@ void test_fcontext_exists_local(void)
CU_ASSERT(resp == 0);
/* cleanup */
+ semanage_fcontext_key_free(key);
cleanup_handle(SH_TRANS);
}
@@ -1031,12 +1056,17 @@ void test_fcontext_list_local(void)
CU_ASSERT(semanage_fcontext_list_local(sh, &records, &count) >= 0);
CU_ASSERT(count == 1);
CU_ASSERT_PTR_NOT_NULL(records[0]);
+ semanage_fcontext_free(records[0]);
+ free(records);
add_local_fcontext(I_SECOND);
CU_ASSERT(semanage_fcontext_list_local(sh, &records, &count) >= 0);
CU_ASSERT(count == 2);
CU_ASSERT_PTR_NOT_NULL(records[0]);
CU_ASSERT_PTR_NOT_NULL(records[1]);
+ semanage_fcontext_free(records[0]);
+ semanage_fcontext_free(records[1]);
+ free(records);
/* cleanup */
delete_local_fcontext(I_FIRST);
diff --git a/libsemanage/tests/test_ibendport.c b/libsemanage/tests/test_ibendport.c
index 79a8e2c8..8addc908 100644
--- a/libsemanage/tests/test_ibendport.c
+++ b/libsemanage/tests/test_ibendport.c
@@ -113,6 +113,8 @@ semanage_ibendport_t *get_ibendport_nth(int idx)
if (i != (unsigned int) idx)
semanage_ibendport_free(records[i]);
+ free(records);
+
return ibendport;
}
@@ -132,6 +134,8 @@ semanage_ibendport_key_t *get_ibendport_key_nth(int idx)
CU_ASSERT_FATAL(res >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+ semanage_ibendport_free(ibendport);
+
return key;
}
@@ -148,6 +152,9 @@ void add_local_ibendport(int idx)
CU_ASSERT_FATAL(semanage_ibendport_modify_local(sh, key,
ibendport) >= 0);
+
+ semanage_ibendport_key_free(key);
+ semanage_ibendport_free(ibendport);
}
void delete_local_ibendport(int idx)
@@ -155,6 +162,8 @@ void delete_local_ibendport(int idx)
semanage_ibendport_key_t *key = NULL;
key = get_ibendport_key_nth(idx);
CU_ASSERT_FATAL(semanage_ibendport_del_local(sh, key) >= 0);
+
+ semanage_ibendport_key_free(key);
}
/* Function semanage_ibendport_query */
@@ -195,7 +204,9 @@ void test_ibendport_query(void)
CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
/* cleanup */
+ free(name_exp);
free(name);
+ semanage_ibendport_key_free(key);
semanage_ibendport_free(ibendport);
semanage_ibendport_free(ibendport_exp);
cleanup_handle(SH_CONNECT);
@@ -356,12 +367,14 @@ void test_ibendport_modify_del_query_local(void)
CU_ASSERT(semanage_ibendport_query_local(sh, key,
&ibendport_local) >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(ibendport_local);
+ semanage_ibendport_free(ibendport_local);
CU_ASSERT(semanage_ibendport_del_local(sh, key) >= 0);
CU_ASSERT(semanage_ibendport_query_local(sh, key,
&ibendport_local) < 0);
/* cleanup */
+ semanage_ibendport_key_free(key);
semanage_ibendport_free(ibendport);
cleanup_handle(SH_TRANS);
}
diff --git a/libsemanage/tests/test_iface.c b/libsemanage/tests/test_iface.c
index d5d530a8..434372f8 100644
--- a/libsemanage/tests/test_iface.c
+++ b/libsemanage/tests/test_iface.c
@@ -139,6 +139,8 @@ semanage_iface_t *get_iface_nth(int idx)
if (i != (unsigned int) idx)
semanage_iface_free(records[i]);
+ free(records);
+
return iface;
}
@@ -157,6 +159,9 @@ semanage_iface_key_t *get_iface_key_nth(int idx)
CU_ASSERT_FATAL(res >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+ /* cleanup */
+ semanage_iface_free(iface);
+
return key;
}
@@ -171,6 +176,10 @@ void add_local_iface(int idx)
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
CU_ASSERT_FATAL(semanage_iface_modify_local(sh, key, iface) >= 0);
+
+ /* cleanup */
+ semanage_iface_key_free(key);
+ semanage_iface_free(iface);
}
void delete_local_iface(int idx)
@@ -178,6 +187,9 @@ void delete_local_iface(int idx)
semanage_iface_key_t *key = NULL;
key = get_iface_key_nth(idx);
CU_ASSERT_FATAL(semanage_iface_del_local(sh, key) >= 0);
+
+ /* cleanup */
+ semanage_iface_key_free(key);
}
/* Function semanage_iface_compare */
@@ -309,6 +321,7 @@ void test_iface_get_set_ifcon(void)
CU_ASSERT_CONTEXT_EQUAL(con1, con2);
/* cleanup */
+ semanage_context_free(con1);
semanage_iface_free(iface);
cleanup_handle(SH_CONNECT);
}
@@ -332,6 +345,7 @@ void test_iface_get_set_msgcon(void)
CU_ASSERT_CONTEXT_EQUAL(con1, con2);
/* cleanup */
+ semanage_context_free(con1);
semanage_iface_free(iface);
cleanup_handle(SH_CONNECT);
}
@@ -357,6 +371,8 @@ void test_iface_create(void)
CU_ASSERT(semanage_iface_set_msgcon(sh, iface, msgcon) >= 0);
/* cleanup */
+ semanage_context_free(msgcon);
+ semanage_context_free(ifcon);
semanage_iface_free(iface);
cleanup_handle(SH_CONNECT);
}
@@ -393,6 +409,8 @@ void test_iface_clone(void)
CU_ASSERT_CONTEXT_EQUAL(msgcon, msgcon2);
/* cleanup */
+ semanage_context_free(msgcon);
+ semanage_context_free(ifcon);
semanage_iface_free(iface);
semanage_iface_free(iface_clone);
cleanup_handle(SH_CONNECT);
@@ -426,6 +444,7 @@ void test_iface_query(void)
CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
/* cleanup */
+ semanage_iface_key_free(key);
semanage_iface_free(iface);
semanage_iface_free(iface_exp);
cleanup_handle(SH_CONNECT);
@@ -513,6 +532,8 @@ void test_iface_list(void)
for (unsigned int i = 0; i < count; i++)
semanage_iface_free(records[i]);
+ free(records);
+
/* cleanup */
cleanup_handle(SH_CONNECT);
}
@@ -541,11 +562,13 @@ void test_iface_modify_del_query_local(void)
CU_ASSERT(semanage_iface_query_local(sh, key, &iface_local) >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(iface_local);
+ semanage_iface_free(iface_local);
CU_ASSERT(semanage_iface_del_local(sh, key) >= 0);
CU_ASSERT(semanage_iface_query_local(sh, key, &iface_local) < 0);
/* cleanup */
+ semanage_iface_key_free(key);
semanage_iface_free(iface);
cleanup_handle(SH_TRANS);
}
@@ -658,6 +681,7 @@ void test_iface_list_local(void)
/* cleanup */
for (unsigned int i = 0; i < count; i++)
semanage_iface_free(records[i]);
+ free(records);
delete_local_iface(I_FIRST);
delete_local_iface(I_SECOND);
diff --git a/libsemanage/tests/test_node.c b/libsemanage/tests/test_node.c
index 53c2eb69..e49e8c3b 100644
--- a/libsemanage/tests/test_node.c
+++ b/libsemanage/tests/test_node.c
@@ -148,6 +148,8 @@ semanage_node_t *get_node_nth(int idx)
if (i != (unsigned int) idx)
semanage_node_free(records[i]);
+ free(records);
+
return node;
}
@@ -167,6 +169,8 @@ semanage_node_key_t *get_node_key_nth(int idx)
CU_ASSERT_FATAL(res >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+ semanage_node_free(node);
+
return key;
}
@@ -181,6 +185,10 @@ void add_local_node(int idx)
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
CU_ASSERT_FATAL(semanage_node_modify_local(sh, key, node) >= 0);
+
+ /* cleanup */
+ semanage_node_key_free(key);
+ semanage_node_free(node);
}
void delete_local_node(int idx)
@@ -190,6 +198,9 @@ void delete_local_node(int idx)
key = get_node_key_nth(idx);
CU_ASSERT_FATAL(semanage_node_del_local(sh, key) >= 0);
+
+ /* cleanup */
+ semanage_node_key_free(key);
}
/* Function semanage_node_compare */
@@ -305,6 +316,7 @@ void test_node_get_set_addr(void)
CU_ASSERT_STRING_EQUAL(addr, "192.168.0.1");
/* cleanup */
+ free(addr);
semanage_node_free(node);
cleanup_handle(SH_CONNECT);
}
@@ -334,6 +346,7 @@ void test_node_get_set_addr_bytes(void)
CU_ASSERT(addr1[i] == addr2[i]);
/* cleanup */
+ free(addr2);
semanage_node_free(node);
cleanup_handle(SH_CONNECT);
}
@@ -357,6 +370,7 @@ void test_node_get_set_mask(void)
CU_ASSERT_STRING_EQUAL(mask, "255.255.255.0");
/* cleanup */
+ free(mask);
semanage_node_free(node);
cleanup_handle(SH_CONNECT);
}
@@ -386,6 +400,7 @@ void test_node_get_set_mask_bytes(void)
CU_ASSERT(mask1[i] == mask2[i]);
/* cleanup */
+ free(mask2);
semanage_node_free(node);
cleanup_handle(SH_CONNECT);
}
@@ -436,6 +451,7 @@ void test_node_get_set_con(void)
CU_ASSERT_CONTEXT_EQUAL(con1, con2);
/* cleanup */
+ semanage_context_free(con1);
semanage_node_free(node);
cleanup_handle(SH_CONNECT);
}
@@ -461,6 +477,7 @@ void test_node_create(void)
CU_ASSERT(semanage_node_set_con(sh, node, con) >= 0);
/* cleanup */
+ semanage_context_free(con);
semanage_node_free(node);
cleanup_handle(SH_CONNECT);
}
@@ -508,6 +525,9 @@ void test_node_clone(void)
CU_ASSERT_CONTEXT_EQUAL(con, con2);
/* cleanup */
+ free(mask2);
+ free(addr2);
+ semanage_context_free(con);
semanage_node_free(node);
semanage_node_free(node_clone);
cleanup_handle(SH_CONNECT);
@@ -552,6 +572,8 @@ void test_node_query(void)
CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
/* cleanup */
+ semanage_node_key_free(key);
+ semanage_node_free(node_exp);
semanage_node_free(node);
cleanup_handle(SH_CONNECT);
}
@@ -638,6 +660,8 @@ void test_node_list(void)
for (unsigned int i = 0; i < count; i++)
semanage_node_free(records[i]);
+ free(records);
+
/* cleanup */
cleanup_handle(SH_CONNECT);
}
@@ -679,6 +703,7 @@ void test_node_modify_del_query_local(void)
CU_ASSERT(semanage_node_query_local(sh, key, &node_local) >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(node_local);
+ semanage_node_free(node_local);
CU_ASSERT(semanage_node_del_local(sh, key) >= 0);
CU_ASSERT(semanage_node_del_local(sh, key_tmp) >= 0);
@@ -686,6 +711,8 @@ void test_node_modify_del_query_local(void)
CU_ASSERT(semanage_node_query_local(sh, key, &node_local) < 0);
/* cleanup */
+ semanage_node_key_free(key_tmp);
+ semanage_node_key_free(key);
semanage_node_free(node);
semanage_node_free(node_tmp);
cleanup_handle(SH_TRANS);
@@ -800,6 +827,8 @@ void test_node_list_local(void)
for (unsigned int i = 0; i < count; i++)
semanage_node_free(records[i]);
+ free(records);
+
delete_local_node(I_FIRST);
delete_local_node(I_SECOND);
delete_local_node(I_THIRD);
diff --git a/libsemanage/tests/test_other.c b/libsemanage/tests/test_other.c
index c4ee0ed8..0a57e247 100644
--- a/libsemanage/tests/test_other.c
+++ b/libsemanage/tests/test_other.c
@@ -81,6 +81,9 @@ void test_semanage_context(void)
assert(str);
CU_ASSERT_STRING_EQUAL(str, "user_u:role_r:type_t:s0");
+ semanage_context_free(con);
+ con = NULL;
+
CU_ASSERT(semanage_context_from_string(sh, "my_u:my_r:my_t:s0",
&con) >= 0);
CU_ASSERT_STRING_EQUAL(semanage_context_get_user(con), "my_u");
@@ -95,6 +98,7 @@ void test_semanage_context(void)
CU_ASSERT_STRING_EQUAL(semanage_context_get_mls(con_clone), "s0");
/* cleanup */
+ free(str);
semanage_context_free(con);
semanage_context_free(con_clone);
cleanup_handle(SH_CONNECT);
@@ -115,6 +119,8 @@ void test_debug(void)
CU_ASSERT(semanage_module_info_set_priority(sh, modinfo, -42) < 0);
/* cleanup */
+ semanage_module_info_destroy(sh, modinfo);
+ free(modinfo);
CU_ASSERT(semanage_disconnect(sh) >= 0);
semanage_handle_destroy(sh);
}
diff --git a/libsemanage/tests/test_port.c b/libsemanage/tests/test_port.c
index 0408be4d..f4c6ec21 100644
--- a/libsemanage/tests/test_port.c
+++ b/libsemanage/tests/test_port.c
@@ -146,6 +146,8 @@ semanage_port_t *get_port_nth(int idx)
if (i != (unsigned int) idx)
semanage_port_free(records[i]);
+ free(records);
+
return port;
}
@@ -165,6 +167,9 @@ semanage_port_key_t *get_port_key_nth(int idx)
CU_ASSERT_FATAL(res >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+ /* cleanup */
+ semanage_port_free(port);
+
return key;
}
@@ -181,6 +186,10 @@ void add_local_port(int port_idx)
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
CU_ASSERT_FATAL(semanage_port_modify_local(sh, key, port) >= 0);
+
+ /* cleanup */
+ semanage_port_key_free(key);
+ semanage_port_free(port);
}
void delete_local_port(int port_idx)
@@ -192,6 +201,8 @@ void delete_local_port(int port_idx)
key = get_port_key_nth(port_idx);
CU_ASSERT_FATAL(semanage_port_del_local(sh, key) >= 0);
+
+ semanage_port_key_free(key);
}
/* Function semanage_port_compare */
@@ -447,6 +458,7 @@ void test_port_clone(void)
CU_ASSERT_CONTEXT_EQUAL(con, con2);
/* cleanup */
+ semanage_context_free(con);
semanage_port_free(port);
semanage_port_free(port_clone);
cleanup_handle(SH_CONNECT);
@@ -480,6 +492,7 @@ void test_port_query(void)
CU_ASSERT_CONTEXT_EQUAL(con, con_exp);
/* cleanup */
+ semanage_port_key_free(key);
semanage_port_free(port);
semanage_port_free(port_exp);
cleanup_handle(SH_CONNECT);
@@ -567,6 +580,8 @@ void test_port_list(void)
for (unsigned int i = 0; i < count; i++)
semanage_port_free(records[i]);
+ free(records);
+
cleanup_handle(SH_CONNECT);
}
@@ -594,11 +609,14 @@ void test_port_modify_del_local(void)
con_local = semanage_port_get_con(port_local);
CU_ASSERT_CONTEXT_EQUAL(con, con_local);
+ semanage_port_free(port_local);
CU_ASSERT(semanage_port_del_local(sh, key) >= 0);
CU_ASSERT(semanage_port_query_local(sh, key, &port_local) < 0);
/* cleanup */
+ semanage_context_free(con);
+ semanage_port_key_free(key);
semanage_port_free(port);
cleanup_handle(SH_TRANS);
}
@@ -633,6 +651,7 @@ void test_port_query_local(void)
/* cleanup */
delete_local_port(I_FIRST);
+ semanage_port_key_free(key);
semanage_port_free(port);
semanage_port_free(port_exp);
cleanup_handle(SH_TRANS);
@@ -747,6 +766,8 @@ void test_port_list_local(void)
for (unsigned int i = 0; i < count; i++)
semanage_port_free(records[i]);
+ free(records);
+
delete_local_port(I_FIRST);
delete_local_port(I_SECOND);
delete_local_port(I_THIRD);
@@ -773,6 +794,7 @@ void helper_port_validate_local_noport(void)
helper_commit();
/* cleanup */
+ semanage_port_key_free(key);
helper_begin_transaction();
delete_local_port(I_FIRST);
cleanup_handle(SH_TRANS);
@@ -832,6 +854,8 @@ void helper_port_validate_local_twoports(void)
helper_begin_transaction();
CU_ASSERT(semanage_port_del_local(sh, key1) >= 0);
CU_ASSERT(semanage_port_del_local(sh, key2) >= 0);
+ semanage_context_free(con2);
+ semanage_context_free(con1);
semanage_port_key_free(key1);
semanage_port_key_free(key2);
semanage_port_free(port1);
diff --git a/libsemanage/tests/test_user.c b/libsemanage/tests/test_user.c
index cd082030..c3835c8d 100644
--- a/libsemanage/tests/test_user.c
+++ b/libsemanage/tests/test_user.c
@@ -130,6 +130,8 @@ semanage_user_t *get_user_nth(int idx)
if (i != (unsigned int) idx)
semanage_user_free(records[i]);
+ free(records);
+
return user;
}
@@ -149,6 +151,8 @@ semanage_user_key_t *get_user_key_nth(int idx)
CU_ASSERT_FATAL(res >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
+ semanage_user_free(user);
+
return key;
}
@@ -165,6 +169,9 @@ void add_local_user(int user_idx)
CU_ASSERT_PTR_NOT_NULL_FATAL(key);
CU_ASSERT_FATAL(semanage_user_modify_local(sh, key, user) >= 0);
+
+ semanage_user_key_free(key);
+ semanage_user_free(user);
}
void delete_local_user(int user_idx)
@@ -176,6 +183,8 @@ void delete_local_user(int user_idx)
key = get_user_key_nth(user_idx);
CU_ASSERT_FATAL(semanage_user_del_local(sh, key) >= 0);
+
+ semanage_user_key_free(key);
}
/* Function semanage_user_compare */
@@ -391,6 +400,7 @@ void test_user_roles(void)
CU_ASSERT(semanage_user_get_num_roles(user) == 0);
/* cleanup */
+ free(roles_arr);
semanage_user_free(user);
cleanup_handle(SH_CONNECT);
}
@@ -459,6 +469,7 @@ void test_user_query(void)
CU_ASSERT_PTR_NOT_NULL(user);
/* cleanup */
+ semanage_user_key_free(key);
semanage_user_free(user);
cleanup_handle(SH_CONNECT);
}
@@ -546,6 +557,8 @@ void test_user_list(void)
for (unsigned int i = 0; i < count; i++)
semanage_user_free(records[i]);
+ free(records);
+
cleanup_handle(SH_CONNECT);
}
@@ -573,10 +586,12 @@ void test_user_modify_del_query_local(void)
CU_ASSERT(semanage_user_query_local(sh, key, &user_local) >= 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(user_local);
+ semanage_user_free(user_local);
CU_ASSERT(semanage_user_del_local(sh, key) >= 0);
CU_ASSERT(semanage_user_query_local(sh, key, &user_local) < 0);
/* cleanup */
+ semanage_user_key_free(key);
semanage_user_free(user);
cleanup_handle(SH_TRANS);
}
@@ -683,6 +698,8 @@ void test_user_list_local(void)
for (unsigned int i = 0; i < count; i++)
semanage_user_free(records[i]);
+ free(records);
+
delete_local_user(I_FIRST);
delete_local_user(I_SECOND);
delete_local_user(I_THIRD);
diff --git a/libsemanage/tests/utilities.c b/libsemanage/tests/utilities.c
index 18393215..b28ae155 100644
--- a/libsemanage/tests/utilities.c
+++ b/libsemanage/tests/utilities.c
@@ -99,6 +99,7 @@ int write_test_policy_from_file(const char *filename) {
char *buf = NULL;
size_t len = 0;
FILE *fptr = fopen(filename, "rb");
+ int rc;
if (!fptr) {
perror("fopen");
@@ -120,7 +121,9 @@ int write_test_policy_from_file(const char *filename) {
fread(buf, len, 1, fptr);
fclose(fptr);
- return write_test_policy(buf, len);
+ rc = write_test_policy(buf, len);
+ free(buf);
+ return rc;
}
int write_test_policy_src(unsigned char *data, unsigned int data_len) {
diff --git a/libsemanage/tests/utilities.h b/libsemanage/tests/utilities.h
index db4dabf9..298b3280 100644
--- a/libsemanage/tests/utilities.h
+++ b/libsemanage/tests/utilities.h
@@ -39,6 +39,8 @@
CU_ASSERT(semanage_context_to_string(sh, CON1, &__str) >= 0); \
CU_ASSERT(semanage_context_to_string(sh, CON2, &__str2) >= 0); \
CU_ASSERT_STRING_EQUAL(__str, __str2); \
+ free(__str2); \
+ free(__str); \
} while (0)
diff --git a/libsepol/Android.bp b/libsepol/Android.bp
index 9c56fc4b..6135745c 100644
--- a/libsepol/Android.bp
+++ b/libsepol/Android.bp
@@ -33,21 +33,32 @@ license {
],
}
-common_CFLAGS = [
- "-D_GNU_SOURCE",
- "-Wall",
- "-Werror",
- "-W",
- "-Wundef",
- "-Wshadow",
- "-Wno-error=missing-noreturn",
- "-Wmissing-format-attribute",
-]
+cc_defaults {
+ name: "libsepol_defaults",
+ cflags: [
+ "-D_GNU_SOURCE",
+ "-Wall",
+ "-Werror",
+ "-W",
+ "-Wundef",
+ "-Wshadow",
+ "-Wno-error=missing-noreturn",
+ "-Wmissing-format-attribute",
+ ],
+ target: {
+ bionic: {
+ cflags: ["-DHAVE_REALLOCARRAY"]
+ },
+ musl: {
+ cflags: ["-DHAVE_REALLOCARRAY"]
+ }
+ }
+}
cc_library {
name: "libsepol",
+ defaults: ["libsepol_defaults"],
host_supported: true,
- cflags: common_CFLAGS,
srcs: [
"src/assertion.c",
"src/avrule_block.c",
@@ -80,9 +91,9 @@ cc_library {
"src/policydb.c",
"src/policydb_convert.c",
"src/policydb_public.c",
+ "src/policydb_validate.c",
"src/port_record.c",
"src/ports.c",
- "src/roles.c",
"src/services.c",
"src/sidtab.c",
"src/symtab.c",
@@ -135,7 +146,7 @@ cc_library {
cc_binary_host {
name: "chkcon",
+ defaults: ["libsepol_defaults"],
srcs: ["utils/chkcon.c"],
shared_libs: ["libsepol"],
- cflags: common_CFLAGS,
}
diff --git a/libsepol/VERSION b/libsepol/VERSION
index 9f55b2cc..eb39e538 100644
--- a/libsepol/VERSION
+++ b/libsepol/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/libsepol/cil/include/cil/cil.h b/libsepol/cil/include/cil/cil.h
index f8cfc3be..482ca522 100644
--- a/libsepol/cil/include/cil/cil.h
+++ b/libsepol/cil/include/cil/cil.h
@@ -42,7 +42,7 @@ typedef struct cil_db cil_db_t;
extern void cil_db_init(cil_db_t **db);
extern void cil_db_destroy(cil_db_t **db);
-extern int cil_add_file(cil_db_t *db, char *name, char *data, size_t size);
+extern int cil_add_file(cil_db_t *db, const char *name, const char *data, size_t size);
extern int cil_compile(cil_db_t *db);
extern int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db);
@@ -51,6 +51,7 @@ extern int cil_selinuxusers_to_string(cil_db_t *db, char **out, size_t *size);
extern int cil_filecons_to_string(cil_db_t *db, char **out, size_t *size);
extern void cil_set_disable_dontaudit(cil_db_t *db, int disable_dontaudit);
extern void cil_set_multiple_decls(cil_db_t *db, int multiple_decls);
+extern void cil_set_qualified_names(struct cil_db *db, int qualified_names);
extern void cil_set_disable_neverallow(cil_db_t *db, int disable_neverallow);
extern void cil_set_preserve_tunables(cil_db_t *db, int preserve_tunables);
extern int cil_set_handle_unknown(cil_db_t *db, int handle_unknown);
@@ -60,6 +61,9 @@ extern void cil_set_attrs_expand_size(struct cil_db *db, unsigned attrs_expand_s
extern void cil_set_target_platform(cil_db_t *db, int target_platform);
extern void cil_set_policy_version(cil_db_t *db, int policy_version);
extern void cil_write_policy_conf(FILE *out, struct cil_db *db);
+extern int cil_write_parse_ast(FILE *out, cil_db_t *db);
+extern int cil_write_build_ast(FILE *out, cil_db_t *db);
+extern int cil_write_resolve_ast(FILE *out, cil_db_t *db);
enum cil_log_level {
CIL_ERR = 1,
@@ -67,7 +71,7 @@ enum cil_log_level {
CIL_INFO
};
extern void cil_set_log_level(enum cil_log_level lvl);
-extern void cil_set_log_handler(void (*handler)(int lvl, char *msg));
+extern void cil_set_log_handler(void (*handler)(int lvl, const char *msg));
#ifdef __GNUC__
__attribute__ ((format(printf, 2, 3)))
diff --git a/libsepol/cil/include/cil/cil_write_ast.h b/libsepol/cil/include/cil/cil_write_ast.h
deleted file mode 100644
index 77c3087e..00000000
--- a/libsepol/cil/include/cil/cil_write_ast.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef CIL_WRITE_H_
-#define CIL_WRITE_H_
-
-#include <cil/cil.h>
-
-int cil_write_ast(struct cil_db *db, const char* path);
-#endif /* CIL_WRITE_H_ */
diff --git a/libsepol/cil/src/android.c b/libsepol/cil/src/android.c
index 2fa5e965..ecbd86a4 100644
--- a/libsepol/cil/src/android.c
+++ b/libsepol/cil/src/android.c
@@ -829,6 +829,7 @@ static int cil_build_mappings_tree(hashtab_key_t k, hashtab_datum_t d, void *arg
/* re)declare typeattribute. */
cil_typeattribute_init(&typeattr);
typeattr->datum.name = new_key;
+ typeattr->datum.fqn = new_key;
cil_tree_node_init(&ast_node);
ast_node->data = typeattr;
ast_node->flavor = CIL_TYPEATTRIBUTE;
diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index d222ad3a..38edcf8e 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -50,28 +50,11 @@
#include "cil_binary.h"
#include "cil_policy.h"
#include "cil_strpool.h"
-#include "dso.h"
+#include "cil_write_ast.h"
-#ifndef DISABLE_SYMVER
-asm(".symver cil_build_policydb_pdb, cil_build_policydb@LIBSEPOL_1.0");
-asm(".symver cil_build_policydb_create_pdb, cil_build_policydb@@LIBSEPOL_1.1");
-
-asm(".symver cil_compile_pdb, cil_compile@LIBSEPOL_1.0");
-asm(".symver cil_compile_nopdb, cil_compile@@LIBSEPOL_1.1");
-
-asm(".symver cil_userprefixes_to_string_pdb, cil_userprefixes_to_string@LIBSEPOL_1.0");
-asm(".symver cil_userprefixes_to_string_nopdb, cil_userprefixes_to_string@@LIBSEPOL_1.1");
-
-asm(".symver cil_selinuxusers_to_string_pdb, cil_selinuxusers_to_string@LIBSEPOL_1.0");
-asm(".symver cil_selinuxusers_to_string_nopdb, cil_selinuxusers_to_string@@LIBSEPOL_1.1");
-
-asm(".symver cil_filecons_to_string_pdb, cil_filecons_to_string@LIBSEPOL_1.0");
-asm(".symver cil_filecons_to_string_nopdb, cil_filecons_to_string@@LIBSEPOL_1.1");
-#endif
-
-int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
+const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
{64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
- {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
+ {8, 8, 8, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
@@ -159,6 +142,8 @@ char *CIL_KEY_HANDLEUNKNOWN_DENY;
char *CIL_KEY_HANDLEUNKNOWN_REJECT;
char *CIL_KEY_MACRO;
char *CIL_KEY_IN;
+char *CIL_KEY_IN_BEFORE;
+char *CIL_KEY_IN_AFTER;
char *CIL_KEY_MLS;
char *CIL_KEY_DEFAULTRANGE;
char *CIL_KEY_BLOCKINHERIT;
@@ -237,7 +222,9 @@ char *CIL_KEY_IOCTL;
char *CIL_KEY_UNORDERED;
char *CIL_KEY_SRC_INFO;
char *CIL_KEY_SRC_CIL;
-char *CIL_KEY_SRC_HLL;
+char *CIL_KEY_SRC_HLL_LMS;
+char *CIL_KEY_SRC_HLL_LMX;
+char *CIL_KEY_SRC_HLL_LME;
static void cil_init_keys(void)
{
@@ -370,6 +357,8 @@ static void cil_init_keys(void)
CIL_KEY_DEFAULTTYPE = cil_strpool_add("defaulttype");
CIL_KEY_MACRO = cil_strpool_add("macro");
CIL_KEY_IN = cil_strpool_add("in");
+ CIL_KEY_IN_BEFORE = cil_strpool_add("before");
+ CIL_KEY_IN_AFTER = cil_strpool_add("after");
CIL_KEY_MLS = cil_strpool_add("mls");
CIL_KEY_DEFAULTRANGE = cil_strpool_add("defaultrange");
CIL_KEY_GLOB = cil_strpool_add("*");
@@ -401,8 +390,10 @@ static void cil_init_keys(void)
CIL_KEY_IOCTL = cil_strpool_add("ioctl");
CIL_KEY_UNORDERED = cil_strpool_add("unordered");
CIL_KEY_SRC_INFO = cil_strpool_add("<src_info>");
- CIL_KEY_SRC_CIL = cil_strpool_add("<src_cil>");
- CIL_KEY_SRC_HLL = cil_strpool_add("<src_hll>");
+ CIL_KEY_SRC_CIL = cil_strpool_add("cil");
+ CIL_KEY_SRC_HLL_LMS = cil_strpool_add("lms");
+ CIL_KEY_SRC_HLL_LMX = cil_strpool_add("lmx");
+ CIL_KEY_SRC_HLL_LME = cil_strpool_add("lme");
}
void cil_db_init(struct cil_db **db)
@@ -456,6 +447,8 @@ void cil_db_init(struct cil_db **db)
(*db)->preserve_tunables = CIL_FALSE;
(*db)->handle_unknown = -1;
(*db)->mls = -1;
+ (*db)->multiple_decls = CIL_FALSE;
+ (*db)->qualified_names = CIL_FALSE;
(*db)->target_platform = SEPOL_TARGET_SELINUX;
(*db)->policy_version = POLICYDB_VERSION_MAX;
}
@@ -517,7 +510,7 @@ void cil_root_destroy(struct cil_root *root)
free(root);
}
-int cil_add_file(cil_db_t *db, char *name, char *data, size_t size)
+int cil_add_file(cil_db_t *db, const char *name, const char *data, size_t size)
{
char *buffer = NULL;
int rc;
@@ -545,11 +538,7 @@ exit:
return rc;
}
-#ifdef DISABLE_SYMVER
int cil_compile(struct cil_db *db)
-#else
-int cil_compile_nopdb(struct cil_db *db)
-#endif
{
int rc = SEPOL_ERR;
@@ -560,7 +549,7 @@ int cil_compile_nopdb(struct cil_db *db)
cil_log(CIL_INFO, "Building AST from Parse Tree\n");
rc = cil_build_ast(db, db->parse->root, db->ast->root);
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "Failed to build ast\n");
+ cil_log(CIL_ERR, "Failed to build AST\n");
goto exit;
}
@@ -570,21 +559,21 @@ int cil_compile_nopdb(struct cil_db *db)
cil_log(CIL_INFO, "Resolving AST\n");
rc = cil_resolve_ast(db, db->ast->root);
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "Failed to resolve ast\n");
+ cil_log(CIL_ERR, "Failed to resolve AST\n");
goto exit;
}
cil_log(CIL_INFO, "Qualifying Names\n");
rc = cil_fqn_qualify(db->ast->root);
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "Failed to qualify names\n");
+ cil_log(CIL_ERR, "Failed to qualify names\n");
goto exit;
}
cil_log(CIL_INFO, "Compile post process\n");
rc = cil_post_process(db);
if (rc != SEPOL_OK ) {
- cil_log(CIL_INFO, "Post process failed\n");
+ cil_log(CIL_ERR, "Post process failed\n");
goto exit;
}
@@ -593,33 +582,98 @@ exit:
return rc;
}
-#ifndef DISABLE_SYMVER
-int cil_compile_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db)
+int cil_write_parse_ast(FILE *out, cil_db_t *db)
{
- return cil_compile_nopdb(db);
+ int rc = SEPOL_ERR;
+
+ if (db == NULL) {
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Writing Parse AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_PARSE, db->parse->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write parse ast\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
}
-int cil_build_policydb_pdb(cil_db_t *db, sepol_policydb_t *sepol_db)
+int cil_write_build_ast(FILE *out, cil_db_t *db)
{
- int rc;
+ int rc = SEPOL_ERR;
- cil_log(CIL_INFO, "Building policy binary\n");
- rc = cil_binary_create_allocated_pdb(db, sepol_db);
+ if (db == NULL) {
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Building AST from Parse Tree\n");
+ rc = cil_build_ast(db, db->parse->root, db->ast->root);
if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to generate binary\n");
+ cil_log(CIL_ERR, "Failed to build ast\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Destroying Parse Tree\n");
+ cil_tree_destroy(&db->parse);
+
+ cil_log(CIL_INFO, "Writing Build AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_BUILD, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write build ast\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
+int cil_write_resolve_ast(FILE *out, cil_db_t *db)
+{
+ int rc = SEPOL_ERR;
+
+ if (db == NULL) {
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Building AST from Parse Tree\n");
+ rc = cil_build_ast(db, db->parse->root, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to build ast\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Destroying Parse Tree\n");
+ cil_tree_destroy(&db->parse);
+
+ cil_log(CIL_INFO, "Resolving AST\n");
+ rc = cil_resolve_ast(db, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to resolve ast\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Qualifying Names\n");
+ rc = cil_fqn_qualify(db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to qualify names\n");
+ goto exit;
+ }
+
+ cil_log(CIL_INFO, "Writing Resolve AST\n");
+ rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_RESOLVE, db->ast->root);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write resolve ast\n");
goto exit;
}
exit:
return rc;
}
-#endif
-#ifdef DISABLE_SYMVER
int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db)
-#else
-int cil_build_policydb_create_pdb(cil_db_t *db, sepol_policydb_t **sepol_db)
-#endif
{
int rc;
@@ -1367,11 +1421,7 @@ const char * cil_node_to_string(struct cil_tree_node *node)
return "<unknown>";
}
-#ifdef DISABLE_SYMVER
int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size)
-#else
-int cil_userprefixes_to_string_nopdb(struct cil_db *db, char **out, size_t *size)
-#endif
{
int rc = SEPOL_ERR;
size_t str_len = 0;
@@ -1406,6 +1456,12 @@ int cil_userprefixes_to_string_nopdb(struct cil_db *db, char **out, size_t *size
buf_pos = snprintf(str_tmp, str_len, "user %s prefix %s;\n", user->datum.fqn,
userprefix->prefix_str);
+ if (buf_pos < 0) {
+ free(str_tmp);
+ *size = 0;
+ *out = NULL;
+ goto exit;
+ }
str_len -= buf_pos;
str_tmp += buf_pos;
}
@@ -1416,13 +1472,6 @@ exit:
}
-#ifndef DISABLE_SYMVER
-int cil_userprefixes_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size)
-{
- return cil_userprefixes_to_string_nopdb(db, out, size);
-}
-#endif
-
static int cil_cats_to_ebitmap(struct cil_cats *cats, struct ebitmap* cats_ebitmap)
{
int rc = SEPOL_ERR;
@@ -1438,7 +1487,7 @@ static int cil_cats_to_ebitmap(struct cil_cats *cats, struct ebitmap* cats_ebitm
}
cil_list_for_each(i, cats->datum_expr) {
- node = DATUM(i->data)->nodes->head->data;
+ node = NODE(i->data);
if (node->flavor == CIL_CATSET) {
cs = (struct cil_catset*)i->data;
cil_list_for_each(j, cs->cats->datum_expr) {
@@ -1610,11 +1659,7 @@ static int __cil_level_to_string(struct cil_level *lvl, char *out)
return str_tmp - out;
}
-#ifdef DISABLE_SYMVER
int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size)
-#else
-int cil_selinuxusers_to_string_nopdb(struct cil_db *db, char **out, size_t *size)
-#endif
{
size_t str_len = 0;
int buf_pos = 0;
@@ -1671,18 +1716,7 @@ int cil_selinuxusers_to_string_nopdb(struct cil_db *db, char **out, size_t *size
return SEPOL_OK;
}
-#ifndef DISABLE_SYMVER
-int cil_selinuxusers_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size)
-{
- return cil_selinuxusers_to_string_nopdb(db, out, size);
-}
-#endif
-
-#ifdef DISABLE_SYMVER
int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size)
-#else
-int cil_filecons_to_string_nopdb(struct cil_db *db, char **out, size_t *size)
-#endif
{
uint32_t i = 0;
int buf_pos = 0;
@@ -1737,6 +1771,9 @@ int cil_filecons_to_string_nopdb(struct cil_db *db, char **out, size_t *size)
str_tmp += buf_pos;
switch(filecon->type) {
+ case CIL_FILECON_ANY:
+ str_type = "";
+ break;
case CIL_FILECON_FILE:
str_type = "\t--";
break;
@@ -1800,13 +1837,6 @@ int cil_filecons_to_string_nopdb(struct cil_db *db, char **out, size_t *size)
return SEPOL_OK;
}
-#ifndef DISABLE_SYMVER
-int cil_filecons_to_string_pdb(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size)
-{
- return cil_filecons_to_string_nopdb(db, out, size);
-}
-#endif
-
void cil_set_disable_dontaudit(struct cil_db *db, int disable_dontaudit)
{
db->disable_dontaudit = disable_dontaudit;
@@ -1860,6 +1890,11 @@ void cil_set_multiple_decls(struct cil_db *db, int multiple_decls)
db->multiple_decls = multiple_decls;
}
+void cil_set_qualified_names(struct cil_db *db, int qualified_names)
+{
+ db->qualified_names = qualified_names;
+}
+
void cil_set_target_platform(struct cil_db *db, int target_platform)
{
db->target_platform = target_platform;
@@ -1870,7 +1905,7 @@ void cil_set_policy_version(struct cil_db *db, int policy_version)
db->policy_version = policy_version;
}
-void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM])
+void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM])
{
uint32_t i = 0;
for (i = 0; i < CIL_SYM_NUM; i++) {
@@ -1979,6 +2014,63 @@ exit:
return SEPOL_ERR;
}
+int cil_string_to_uint32(const char *string, uint32_t *value, int base)
+{
+ unsigned long val;
+ char *end = NULL;
+ int rc = SEPOL_ERR;
+
+ if (string == NULL || value == NULL) {
+ goto exit;
+ }
+
+ errno = 0;
+ val = strtoul(string, &end, base);
+ if (errno != 0 || end == string || *end != '\0') {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ /* Ensure that the value fits a 32-bit integer without triggering -Wtype-limits */
+#if ULONG_MAX > UINT32_MAX
+ if (val > UINT32_MAX) {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+#endif
+
+ *value = val;
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Failed to create uint32_t from string\n");
+ return rc;
+}
+
+int cil_string_to_uint64(const char *string, uint64_t *value, int base)
+{
+ char *end = NULL;
+ int rc = SEPOL_ERR;
+
+ if (string == NULL || value == NULL) {
+ goto exit;
+ }
+
+ errno = 0;
+ *value = strtoull(string, &end, base);
+ if (errno != 0 || end == string || *end != '\0') {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Failed to create uint64_t from string\n");
+ return rc;
+}
+
void cil_sort_init(struct cil_sort **sort)
{
*sort = cil_malloc(sizeof(**sort));
@@ -2103,6 +2195,7 @@ void cil_in_init(struct cil_in **in)
*in = cil_malloc(sizeof(**in));
cil_symtab_array_init((*in)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_IN]);
+ (*in)->is_after = CIL_FALSE;
(*in)->block_str = NULL;
}
@@ -2446,7 +2539,7 @@ void cil_filecon_init(struct cil_filecon **filecon)
*filecon = cil_malloc(sizeof(**filecon));
(*filecon)->path_str = NULL;
- (*filecon)->type = 0;
+ (*filecon)->type = CIL_FILECON_ANY;
(*filecon)->context_str = NULL;
(*filecon)->context = NULL;
}
@@ -2490,6 +2583,7 @@ void cil_genfscon_init(struct cil_genfscon **genfscon)
(*genfscon)->fs_str = NULL;
(*genfscon)->path_str = NULL;
+ (*genfscon)->file_type = CIL_FILECON_ANY;
(*genfscon)->context_str = NULL;
(*genfscon)->context = NULL;
}
@@ -2740,7 +2834,6 @@ void cil_call_init(struct cil_call **call)
void cil_optional_init(struct cil_optional **optional)
{
*optional = cil_malloc(sizeof(**optional));
- (*optional)->enabled = CIL_TRUE;
cil_symtab_datum_init(&(*optional)->datum);
}
@@ -2807,6 +2900,7 @@ void cil_mls_init(struct cil_mls **mls)
void cil_src_info_init(struct cil_src_info **info)
{
*info = cil_malloc(sizeof(**info));
- (*info)->is_cil = 0;
+ (*info)->kind = NULL;
+ (*info)->hll_line = 0;
(*info)->path = NULL;
}
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 03d53e1f..53017e2d 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -42,7 +42,6 @@
#include <sepol/policydb/polcaps.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/constraint.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/hierarchy.h>
@@ -56,9 +55,6 @@
#include "cil_find.h"
#include "cil_build_ast.h"
-/* There are 44000 filename_trans in current fedora policy. 1.33 times this is the recommended
- * size of a hashtable. The next power of 2 of this is 2 ** 16.
- */
#define ROLE_TRANS_TABLE_SIZE (1 << 10)
#define AVRULEX_TABLE_SIZE (1 << 10)
#define PERMS_PER_CLASS 32
@@ -148,7 +144,7 @@ static int __cil_get_sepol_level_datum(policydb_t *pdb, struct cil_symtab_datum
static int __cil_expand_user(struct cil_symtab_datum *datum, ebitmap_t *new)
{
- struct cil_tree_node *node = datum->nodes->head->data;
+ struct cil_tree_node *node = NODE(datum);
struct cil_user *user = NULL;
struct cil_userattribute *attr = NULL;
@@ -176,7 +172,7 @@ exit:
static int __cil_expand_role(struct cil_symtab_datum *datum, ebitmap_t *new)
{
- struct cil_tree_node *node = datum->nodes->head->data;
+ struct cil_tree_node *node = NODE(datum);
if (node->flavor == CIL_ROLEATTRIBUTE) {
struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
@@ -202,7 +198,7 @@ exit:
static int __cil_expand_type(struct cil_symtab_datum *datum, ebitmap_t *new)
{
- struct cil_tree_node *node = datum->nodes->head->data;
+ struct cil_tree_node *node = NODE(datum);
if (node->flavor == CIL_TYPEATTRIBUTE) {
struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
@@ -594,11 +590,11 @@ exit:
int __cil_typeattr_bitmap_init(policydb_t *pdb)
{
int rc = SEPOL_ERR;
+ uint32_t i;
pdb->type_attr_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t));
pdb->attr_type_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t));
- uint32_t i = 0;
for (i = 0; i < pdb->p_types.nprim; i++) {
ebitmap_init(&pdb->type_attr_map[i]);
ebitmap_init(&pdb->attr_type_map[i]);
@@ -1074,7 +1070,7 @@ int __cil_type_rule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct ci
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
type_datum_t *sepol_result = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
ebitmap_node_t *node1, *node2;
@@ -1130,13 +1126,12 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
type_datum_t *sepol_result = NULL;
- filename_trans_t *newkey = NULL;
- filename_trans_datum_t *newdatum = NULL, *otype = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
ebitmap_node_t *node1, *node2;
unsigned int i, j;
+ uint32_t otype;
struct cil_list_item *c;
char *name = DATUM(typetrans->name)->name;
@@ -1177,22 +1172,14 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru
rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj);
if (rc != SEPOL_OK) goto exit;
- newkey = cil_calloc(1, sizeof(*newkey));
- newdatum = cil_calloc(1, sizeof(*newdatum));
- newkey->stype = sepol_src->s.value;
- newkey->ttype = sepol_tgt->s.value;
- newkey->tclass = sepol_obj->s.value;
- newkey->name = cil_strdup(name);
- newdatum->otype = sepol_result->s.value;
-
- rc = hashtab_insert(pdb->filename_trans,
- (hashtab_key_t)newkey,
- newdatum);
+ rc = policydb_filetrans_insert(
+ pdb, sepol_src->s.value, sepol_tgt->s.value,
+ sepol_obj->s.value, name, NULL,
+ sepol_result->s.value, &otype
+ );
if (rc != SEPOL_OK) {
if (rc == SEPOL_EEXIST) {
- otype = hashtab_search(pdb->filename_trans,
- (hashtab_key_t)newkey);
- if (newdatum->otype != otype->otype) {
+ if (sepol_result->s.value!= otype) {
cil_log(CIL_ERR, "Conflicting name type transition rules\n");
} else {
rc = SEPOL_OK;
@@ -1200,9 +1187,6 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru
} else {
cil_log(CIL_ERR, "Out of memory\n");
}
- free(newkey->name);
- free(newkey);
- free(newdatum);
if (rc != SEPOL_OK) {
goto exit;
}
@@ -1241,7 +1225,7 @@ int __perm_str_to_datum(char *perm_str, class_datum_t *sepol_class, uint32_t *da
goto exit;
}
}
- *datum |= 1 << (sepol_perm->s.value - 1);
+ *datum |= UINT32_C(1) << (sepol_perm->s.value - 1);
return SEPOL_OK;
@@ -1539,7 +1523,7 @@ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_
/* index of the u32 containing the permission */
#define XPERM_IDX(x) (x >> 5)
/* set bits 0 through x-1 within the u32 */
-#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1)
+#define XPERM_SETBITS(x) ((UINT32_C(1) << (x & 0x1f)) - 1)
/* low value for this u32 */
#define XPERM_LOW(x) (x << 5)
/* high value for this u32 */
@@ -1681,14 +1665,6 @@ exit:
}
cil_list_destroy(&xperms_list, CIL_FALSE);
}
-
- // hashtab_t does not have a way to free keys or datum since it doesn't
- // know what they are. We won't need the keys/datum after this function, so
- // clean them up here.
- free(avtab_key);
- ebitmap_destroy(datum);
- free(datum);
-
return rc;
}
@@ -1898,6 +1874,15 @@ exit:
return rc;
}
+static int __cil_avrulex_ioctl_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args)
+{
+ free(k);
+ ebitmap_destroy(datum);
+ free(datum);
+
+ return SEPOL_OK;
+}
+
int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
{
int rc;
@@ -1990,7 +1975,7 @@ static void __cil_expr_to_string(struct cil_list *expr, enum cil_flavor flavor,
curr = expr->head;
if (curr->flavor == CIL_OP) {
- op = (enum cil_flavor)curr->data;
+ op = (enum cil_flavor)(uintptr_t)curr->data;
if (op == CIL_ALL) {
*out = cil_strdup(CIL_KEY_ALL);
@@ -2089,7 +2074,7 @@ static int __cil_cond_expr_to_sepol_expr_helper(policydb_t *pdb, struct cil_list
if (item == NULL) {
goto exit;
} else if (item->flavor == CIL_OP) {
- enum cil_flavor cil_op = (enum cil_flavor)item->data;
+ enum cil_flavor cil_op = (enum cil_flavor)(uintptr_t)item->data;
op = cil_malloc(sizeof(*op));
op->bool = 0;
@@ -2189,12 +2174,57 @@ static int __cil_cond_expr_to_sepol_expr(policydb_t *pdb, struct cil_list *cil_e
return SEPOL_OK;
}
+int __cil_validate_cond_expr(cond_expr_t *cond_expr)
+{
+ cond_expr_t *e;
+ int depth = -1;
+
+ for (e = cond_expr; e != NULL; e = e->next) {
+ switch (e->expr_type) {
+ case COND_BOOL:
+ if (depth == (COND_EXPR_MAXDEPTH - 1)) {
+ cil_log(CIL_ERR,"Conditional expression exceeded max allowable depth\n");
+ return SEPOL_ERR;
+ }
+ depth++;
+ break;
+ case COND_NOT:
+ if (depth < 0) {
+ cil_log(CIL_ERR,"Invalid conditional expression\n");
+ return SEPOL_ERR;
+ }
+ break;
+ case COND_OR:
+ case COND_AND:
+ case COND_XOR:
+ case COND_EQ:
+ case COND_NEQ:
+ if (depth < 1) {
+ cil_log(CIL_ERR,"Invalid conditional expression\n");
+ return SEPOL_ERR;
+ }
+ depth--;
+ break;
+ default:
+ cil_log(CIL_ERR,"Invalid conditional expression\n");
+ return SEPOL_ERR;
+ }
+ }
+
+ if (depth != 0) {
+ cil_log(CIL_ERR,"Invalid conditional expression\n");
+ return SEPOL_ERR;
+ }
+
+ return SEPOL_OK;
+}
+
int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node)
{
int rc = SEPOL_ERR;
struct cil_args_booleanif bool_args;
struct cil_booleanif *cil_boolif = (struct cil_booleanif*)node->data;
- struct cil_tree_node *cb_node = node->cl_head;
+ struct cil_tree_node *cb_node;
struct cil_tree_node *true_node = NULL;
struct cil_tree_node *false_node = NULL;
struct cil_tree_node *tmp_node = NULL;
@@ -2217,6 +2247,11 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
goto exit;
}
+ rc = __cil_validate_cond_expr(tmp_cond->expr);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
tmp_cond->true_list = &tmp_cl;
rc = cond_normalize_expr(pdb, tmp_cond);
@@ -2300,7 +2335,7 @@ int cil_roletrans_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
role_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_obj = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
role_datum_t *sepol_result = NULL;
role_trans_t *new = NULL;
uint32_t *new_role = NULL;
@@ -2525,7 +2560,7 @@ int __cil_constrain_expr_leaf_to_sepol_expr(policydb_t *pdb, const struct cil_db
struct cil_list_item *l_item = op_item->next;
struct cil_list_item *r_item = op_item->next->next;
- enum cil_flavor l_operand = (enum cil_flavor)l_item->data;
+ enum cil_flavor l_operand = (enum cil_flavor)(uintptr_t)l_item->data;
switch (l_operand) {
case CIL_CONS_U1:
@@ -2556,7 +2591,7 @@ int __cil_constrain_expr_leaf_to_sepol_expr(policydb_t *pdb, const struct cil_db
expr->attr = CEXPR_TYPE | CEXPR_XTARGET;
break;
case CIL_CONS_L1: {
- enum cil_flavor r_operand = (enum cil_flavor)r_item->data;
+ enum cil_flavor r_operand = (enum cil_flavor)(uintptr_t)r_item->data;
if (r_operand == CIL_CONS_L2) {
expr->attr = CEXPR_L1L2;
@@ -2571,7 +2606,7 @@ int __cil_constrain_expr_leaf_to_sepol_expr(policydb_t *pdb, const struct cil_db
expr->attr = CEXPR_L2H2;
break;
case CIL_CONS_H1: {
- enum cil_flavor r_operand = (enum cil_flavor)r_item->data;
+ enum cil_flavor r_operand = (enum cil_flavor)(uintptr_t)r_item->data;
if (r_operand == CIL_CONS_L2) {
expr->attr = CEXPR_H1L2;
} else {
@@ -2619,6 +2654,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_
int rc = SEPOL_ERR;
struct cil_list_item *item;
enum cil_flavor flavor;
+ enum cil_flavor cil_op;
constraint_expr_t *op, *h1, *h2, *t1, *t2;
int is_leaf = CIL_FALSE;
@@ -2635,7 +2671,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_
goto exit;
}
- enum cil_flavor cil_op = (enum cil_flavor)item->data;
+ cil_op = (enum cil_flavor)(uintptr_t)item->data;
switch (cil_op) {
case CIL_NOT:
op->expr_type = CEXPR_NOT;
@@ -2726,6 +2762,49 @@ int __cil_constrain_expr_to_sepol_expr(policydb_t *pdb, const struct cil_db *db,
return SEPOL_OK;
}
+int __cil_validate_constrain_expr(constraint_expr_t *sepol_expr)
+{
+ constraint_expr_t *e;
+ int depth = -1;
+
+ for (e = sepol_expr; e != NULL; e = e->next) {
+ switch (e->expr_type) {
+ case CEXPR_NOT:
+ if (depth < 0) {
+ cil_log(CIL_ERR,"Invalid constraint expression\n");
+ return SEPOL_ERR;
+ }
+ break;
+ case CEXPR_AND:
+ case CEXPR_OR:
+ if (depth < 1) {
+ cil_log(CIL_ERR,"Invalid constraint expression\n");
+ return SEPOL_ERR;
+ }
+ depth--;
+ break;
+ case CEXPR_ATTR:
+ case CEXPR_NAMES:
+ if (depth == (CEXPR_MAXDEPTH - 1)) {
+ cil_log(CIL_ERR,"Constraint expression exceeded max allowable depth\n");
+ return SEPOL_ERR;
+ }
+ depth++;
+ break;
+ default:
+ cil_log(CIL_ERR,"Invalid constraint expression\n");
+ return SEPOL_ERR;
+ }
+ }
+
+ if (depth != 0) {
+ cil_log(CIL_ERR,"Invalid constraint expression\n");
+ return SEPOL_ERR;
+ }
+
+ return SEPOL_OK;
+}
+
int cil_constrain_to_policydb_helper(policydb_t *pdb, const struct cil_db *db, struct cil_symtab_datum *class, struct cil_list *perms, struct cil_list *expr)
{
int rc = SEPOL_ERR;
@@ -2744,11 +2823,22 @@ int cil_constrain_to_policydb_helper(policydb_t *pdb, const struct cil_db *db, s
goto exit;
}
+ if (sepol_constrain->permissions == 0) {
+ /* No permissions, so don't insert rule. */
+ free(sepol_constrain);
+ return SEPOL_OK;
+ }
+
rc = __cil_constrain_expr_to_sepol_expr(pdb, db, expr, &sepol_expr);
if (rc != SEPOL_OK) {
goto exit;
}
+ rc = __cil_validate_constrain_expr(sepol_expr);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
sepol_constrain->expr = sepol_expr;
sepol_constrain->next = sepol_class->constraints;
sepol_class->constraints = sepol_constrain;
@@ -2756,6 +2846,7 @@ int cil_constrain_to_policydb_helper(policydb_t *pdb, const struct cil_db *db, s
return SEPOL_OK;
exit:
+ constraint_expr_destroy(sepol_expr);
free(sepol_constrain);
return rc;
}
@@ -2858,7 +2949,7 @@ int __cil_cats_to_mls_level(policydb_t *pdb, struct cil_cats *cats, mls_level_t
cat_datum_t *sepol_cat = NULL;
cil_list_for_each(i, cats->datum_expr) {
- struct cil_tree_node *node = DATUM(i->data)->nodes->head->data;
+ struct cil_tree_node *node = NODE(i->data);
if (node->flavor == CIL_CATSET) {
struct cil_list_item *j;
struct cil_catset *cs = i->data;
@@ -3078,7 +3169,7 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st
type_datum_t *sepol_src = NULL;
type_datum_t *sepol_tgt = NULL;
class_datum_t *sepol_class = NULL;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
range_trans_t *newkey = NULL;
struct mls_range *newdatum = NULL;
ebitmap_t src_bitmap, tgt_bitmap;
@@ -3377,6 +3468,43 @@ int cil_genfscon_to_policydb(policydb_t *pdb, struct cil_sort *genfscons)
new_ocon->u.name = cil_strdup(cil_genfscon->path_str);
+ if (cil_genfscon->file_type != CIL_FILECON_ANY) {
+ class_datum_t *class_datum;
+ const char *class_name;
+ switch (cil_genfscon->file_type) {
+ case CIL_FILECON_FILE:
+ class_name = "file";
+ break;
+ case CIL_FILECON_DIR:
+ class_name = "dir";
+ break;
+ case CIL_FILECON_CHAR:
+ class_name = "chr_file";
+ break;
+ case CIL_FILECON_BLOCK:
+ class_name = "blk_file";
+ break;
+ case CIL_FILECON_SOCKET:
+ class_name = "sock_file";
+ break;
+ case CIL_FILECON_PIPE:
+ class_name = "fifo_file";
+ break;
+ case CIL_FILECON_SYMLINK:
+ class_name = "lnk_file";
+ break;
+ default:
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ class_datum = hashtab_search(pdb->p_classes.table, class_name);
+ if (!class_datum) {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ new_ocon->v.sclass = class_datum->s.value;
+ }
+
rc = __cil_context_to_sepol_context(pdb, cil_genfscon->context, &new_ocon->context[0]);
if (rc != SEPOL_OK) {
goto exit;
@@ -3515,7 +3643,7 @@ int cil_default_to_policydb(policydb_t *pdb, struct cil_default *def)
{
struct cil_list_item *curr;
class_datum_t *sepol_class;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
cil_list_for_each(curr, def->class_datums) {
struct cil_list_item *c;
@@ -3570,7 +3698,7 @@ int cil_defaultrange_to_policydb(policydb_t *pdb, struct cil_defaultrange *def)
{
struct cil_list_item *curr;
class_datum_t *sepol_class;
- struct cil_list *class_list;
+ struct cil_list *class_list = NULL;
cil_list_for_each(curr, def->class_datums) {
struct cil_list_item *c;
@@ -3616,7 +3744,7 @@ int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args)
type_value_to_cil = args->type_value_to_cil;
if (node->flavor >= CIL_MIN_DECLARATIVE) {
- if (node != DATUM(node->data)->nodes->head->data) {
+ if (node != NODE(node->data)) {
goto exit;
}
}
@@ -4189,7 +4317,7 @@ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hash
uint32_t hash = 0;
-#define mix(input) { \
+#define mix(input) do { \
uint32_t v = input; \
v *= c1; \
v = (v << r1) | (v >> (32 - r1)); \
@@ -4197,7 +4325,7 @@ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hash
hash ^= v; \
hash = (hash << r2) | (hash >> (32 - r2)); \
hash = hash * m + n; \
-}
+} while (0)
mix(k->target_class);
mix(k->target_type);
@@ -4278,15 +4406,13 @@ static int __cil_rule_to_sepol_class_perms(policydb_t *pdb, struct cil_list *cla
rc = __cil_perms_to_datum(cp->perms, sepol_class, &data);
if (rc != SEPOL_OK) goto exit;
- if (data == 0) {
- /* No permissions */
- return SEPOL_OK;
+ if (data != 0) { /* Only add if there are permissions */
+ cpn = cil_malloc(sizeof(class_perm_node_t));
+ cpn->tclass = sepol_class->s.value;
+ cpn->data = data;
+ cpn->next = *sepol_class_perms;
+ *sepol_class_perms = cpn;
}
- cpn = cil_malloc(sizeof(class_perm_node_t));
- cpn->tclass = sepol_class->s.value;
- cpn->data = data;
- cpn->next = *sepol_class_perms;
- *sepol_class_perms = cpn;
} else { /* MAP */
struct cil_list_item *j = NULL;
cil_list_for_each(j, cp->perms) {
@@ -4367,7 +4493,7 @@ static void __cil_init_sepol_type_set(type_set_t *t)
static int __cil_add_sepol_type(policydb_t *pdb, const struct cil_db *db, struct cil_symtab_datum *datum, ebitmap_t *map)
{
int rc = SEPOL_ERR;
- struct cil_tree_node *n = datum->nodes->head->data;
+ struct cil_tree_node *n = NODE(datum);
type_datum_t *sepol_datum = NULL;
if (n->flavor == CIL_TYPEATTRIBUTE) {
@@ -4397,7 +4523,8 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no
avrule_t *avrule;
struct cil_tree_node *source_node;
char *source_path;
- int is_cil;
+ char *lm_kind;
+ uint32_t hll_line;
avrule = cil_malloc(sizeof(avrule_t));
avrule->specified = kind;
@@ -4409,11 +4536,11 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no
avrule->source_filename = NULL;
avrule->source_line = node->line;
- source_node = cil_tree_get_next_path(node, &source_path, &is_cil);
+ source_node = cil_tree_get_next_path(node, &lm_kind, &hll_line, &source_path);
if (source_node) {
avrule->source_filename = source_path;
- if (!is_cil) {
- avrule->source_line = node->hll_line;
+ if (lm_kind != CIL_KEY_SRC_CIL) {
+ avrule->source_line = hll_line + node->hll_offset - source_node->hll_offset - 1;
}
}
@@ -4519,6 +4646,9 @@ static int __cil_print_neverallow_failure(const struct cil_db *db, struct cil_tr
char *neverallow_str;
char *allow_str;
enum cil_flavor avrule_flavor;
+ int num_matching = 0;
+ int count_matching = 0;
+ enum cil_log_level log_level = cil_get_log_level();
target.rule_kind = CIL_AVRULE_ALLOWED;
target.is_extended = cil_rule->is_extended;
@@ -4546,10 +4676,18 @@ static int __cil_print_neverallow_failure(const struct cil_db *db, struct cil_tr
}
cil_list_for_each(i2, matching) {
+ num_matching++;
+ }
+ cil_list_for_each(i2, matching) {
n2 = i2->data;
r2 = n2->data;
__cil_print_parents(" ", n2);
__cil_print_rule(" ", allow_str, r2);
+ count_matching++;
+ if (count_matching >= 4 && num_matching > 4 && log_level == CIL_ERR) {
+ cil_log(CIL_ERR, " Only first 4 of %d matching rules shown (use \"-v\" to show all)\n", num_matching);
+ break;
+ }
}
cil_log(CIL_ERR,"\n");
cil_list_destroy(&matching, CIL_FALSE);
@@ -4676,7 +4814,7 @@ static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t clas
cil_list_init(&cp->perms, CIL_PERM);
for (i = 0; i < sepol_class->permissions.nprim; i++) {
struct cil_perm *perm;
- if ((data & (1 << i)) == 0) continue;
+ if ((data & (UINT32_C(1) << i)) == 0) continue;
perm = perm_value_to_cil[class][i+1];
if (!perm) goto exit;
cil_list_append(cp->perms, CIL_PERM, perm);
@@ -4741,6 +4879,8 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void
avtab_ptr_t cur;
struct cil_avrule target;
struct cil_tree_node *n1 = NULL;
+ int count_bad = 0;
+ enum cil_log_level log_level = cil_get_log_level();
*violation = CIL_TRUE;
@@ -4754,10 +4894,13 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void
for (cur = bad; cur; cur = cur->next) {
struct cil_list_item *i2;
struct cil_list *matching;
+ int num_matching = 0;
+ int count_matching = 0;
rc = cil_avrule_from_sepol(pdb, cur, &target, type_value_to_cil, class_value_to_cil, perm_value_to_cil);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to convert sepol avrule to CIL\n");
+ bounds_destroy_bad(bad);
goto exit;
}
__cil_print_rule(" ", "allow", &target);
@@ -4771,6 +4914,9 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void
goto exit;
}
cil_list_for_each(i2, matching) {
+ num_matching++;
+ }
+ cil_list_for_each(i2, matching) {
struct cil_tree_node *n2 = i2->data;
struct cil_avrule *r2 = n2->data;
if (n1 == n2) {
@@ -4780,9 +4926,19 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void
__cil_print_parents(" ", n2);
__cil_print_rule(" ", "allow", r2);
}
+ count_matching++;
+ if (count_matching >= 2 && num_matching > 2 && log_level == CIL_ERR) {
+ cil_log(CIL_ERR, " Only first 2 of %d matching rules shown (use \"-v\" to show all)\n", num_matching);
+ break;
+ }
}
cil_list_destroy(&matching, CIL_FALSE);
cil_list_destroy(&target.perms.classperms, CIL_TRUE);
+ count_bad++;
+ if (count_bad >= 4 && numbad > 4 && log_level == CIL_ERR) {
+ cil_log(CIL_ERR, " Only first 4 of %d bad rules shown (use \"-v\" to show all)\n", numbad);
+ break;
+ }
}
bounds_destroy_bad(bad);
}
@@ -4953,6 +5109,7 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
exit:
hashtab_destroy(role_trans_table);
+ hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
hashtab_destroy(avrulex_ioctl_table);
free(type_value_to_cil);
free(class_value_to_cil);
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 307b1ee3..5f9392d1 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -49,10 +49,11 @@
struct cil_args_build {
struct cil_tree_node *ast;
struct cil_db *db;
- struct cil_tree_node *macro;
- struct cil_tree_node *boolif;
struct cil_tree_node *tunif;
struct cil_tree_node *in;
+ struct cil_tree_node *macro;
+ struct cil_tree_node *optional;
+ struct cil_tree_node *boolif;
};
int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list)
@@ -63,7 +64,7 @@ int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct
CIL_SYN_N_STRINGS,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(current, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -82,35 +83,69 @@ exit:
return rc;
}
-/*
- * Determine whether or not multiple declarations of the same key can share a
- * datum, given the new datum and the one already present in a given symtab.
- */
-int cil_is_datum_multiple_decl(__attribute__((unused)) struct cil_symtab_datum *cur,
- __attribute__((unused)) struct cil_symtab_datum *old,
- enum cil_flavor f)
+static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old)
{
- int rc = CIL_FALSE;
+ if (f_new != f_old) {
+ return CIL_FALSE;
+ }
- switch (f) {
+ switch (f_new) {
case CIL_TYPE:
case CIL_TYPEATTRIBUTE:
- /* type and typeattribute statements insert empty datums, ret true */
- rc = CIL_TRUE;
+ if (db->multiple_decls) {
+ return CIL_TRUE;
+ }
+ break;
+ case CIL_OPTIONAL:
+ return CIL_TRUE;
break;
default:
break;
}
- return rc;
+
+ return CIL_FALSE;
+}
+
+int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node)
+{
+ int rc;
+
+ if (symtab == NULL || datum == NULL || node == NULL) {
+ return SEPOL_ERR;
+ }
+
+ rc = cil_symtab_insert(symtab, key, datum, node);
+ if (rc == SEPOL_EEXIST) {
+ struct cil_symtab_datum *prev;
+ rc = cil_symtab_get_datum(symtab, key, &prev);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(node), key);
+ return SEPOL_ERR;
+ }
+ if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) {
+ /* multiple_decls not ok, ret error */
+ struct cil_tree_node *n = NODE(prev);
+ cil_log(CIL_ERR, "Re-declaration of %s %s\n",
+ cil_node_to_string(node), key);
+ cil_tree_log(node, CIL_ERR, "Previous declaration of %s",
+ cil_node_to_string(n));
+ return SEPOL_ERR;
+ }
+ /* multiple_decls is enabled and works for this datum type, add node */
+ cil_list_append(prev->nodes, CIL_NODE, node);
+ node->data = prev;
+ return SEPOL_EEXIST;
+ }
+
+ return SEPOL_OK;
}
int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor)
{
int rc = SEPOL_ERR;
symtab_t *symtab = NULL;
- struct cil_symtab_datum *prev;
- rc = __cil_verify_name((const char*)key);
+ rc = cil_verify_name(db, (const char*)key, nflavor);
if (rc != SEPOL_OK) {
goto exit;
}
@@ -123,53 +158,21 @@ int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_s
ast_node->data = datum;
ast_node->flavor = nflavor;
- if (symtab != NULL) {
- rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node);
- if (rc == SEPOL_EEXIST) {
- if (!db->multiple_decls ||
- cil_symtab_get_datum(symtab, (hashtab_key_t)key, &prev) != SEPOL_OK ||
- !cil_is_datum_multiple_decl(datum, prev, nflavor)) {
-
- /* multiple_decls not ok, ret error */
- cil_log(CIL_ERR, "Re-declaration of %s %s\n",
- cil_node_to_string(ast_node), key);
- if (cil_symtab_get_datum(symtab, key, &datum) == SEPOL_OK) {
- if (sflavor == CIL_SYM_BLOCKS) {
- struct cil_tree_node *node = datum->nodes->head->data;
- cil_tree_log(node, CIL_ERR, "Previous declaration");
- }
- }
- goto exit;
- }
- /* multiple_decls is enabled and works for this datum type, add node */
- cil_list_append(prev->nodes, CIL_NODE, ast_node);
- ast_node->data = prev;
- cil_symtab_datum_destroy(datum);
- free(datum);
- }
+ rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
- if (ast_node->flavor >= CIL_MIN_DECLARATIVE && ast_node->parent->flavor == CIL_MACRO) {
- struct cil_list_item *item;
- struct cil_list *param_list = ((struct cil_macro*)ast_node->parent->data)->params;
- if (param_list != NULL) {
- cil_list_for_each(item, param_list) {
- struct cil_param *param = item->data;
- if (param->flavor == ast_node->flavor) {
- if (param->str == key) {
- cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(ast_node), key);
- rc = SEPOL_ERR;
- goto exit;
- }
- }
- }
+ if (ast_node->parent->flavor == CIL_MACRO) {
+ rc = cil_verify_decl_does_not_shadow_macro_parameter(ast_node->parent->data, ast_node, key);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
}
return SEPOL_OK;
exit:
- cil_log(CIL_ERR, "Failed to create node\n");
return rc;
}
@@ -191,7 +194,7 @@ int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_N_LISTS | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_block *block = NULL;
int rc = SEPOL_ERR;
@@ -200,6 +203,11 @@ int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Blocks are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -227,13 +235,30 @@ exit:
void cil_destroy_block(struct cil_block *block)
{
+ struct cil_list_item *item;
+ struct cil_tree_node *bi_node;
+ struct cil_blockinherit *inherit;
+
if (block == NULL) {
return;
}
cil_symtab_datum_destroy(&block->datum);
cil_symtab_array_destroy(block->symtab);
- cil_list_destroy(&block->bi_nodes, CIL_FALSE);
+ if (block->bi_nodes != NULL) {
+ /* unlink blockinherit->block */
+ cil_list_for_each(item, block->bi_nodes) {
+ bi_node = item->data;
+ /* the conditions should always be true, but better be sure */
+ if (bi_node->flavor == CIL_BLOCKINHERIT) {
+ inherit = bi_node->data;
+ if (inherit->block == block) {
+ inherit->block = NULL;
+ }
+ }
+ }
+ cil_list_destroy(&block->bi_nodes, CIL_FALSE);
+ }
free(block);
}
@@ -245,7 +270,7 @@ int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_blockinherit *inherit = NULL;
int rc = SEPOL_ERR;
@@ -253,6 +278,11 @@ int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current,
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Block inherit rules are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -279,6 +309,19 @@ void cil_destroy_blockinherit(struct cil_blockinherit *inherit)
return;
}
+ if (inherit->block != NULL && inherit->block->bi_nodes != NULL) {
+ struct cil_tree_node *node;
+ struct cil_list_item *item;
+
+ cil_list_for_each(item, inherit->block->bi_nodes) {
+ node = item->data;
+ if (node->data == inherit) {
+ cil_list_remove(inherit->block->bi_nodes, CIL_NODE, node, CIL_FALSE);
+ break;
+ }
+ }
+ }
+
free(inherit);
}
@@ -289,7 +332,7 @@ int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_blockabstract *abstract = NULL;
int rc = SEPOL_ERR;
@@ -297,6 +340,11 @@ int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "Block abstract rules are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -331,10 +379,11 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
- CIL_SYN_N_LISTS,
+ CIL_SYN_STRING | CIL_SYN_N_LISTS,
+ CIL_SYN_N_LISTS | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_in *in = NULL;
@@ -342,6 +391,11 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci
goto exit;
}
+ if (db->qualified_names) {
+ cil_log(CIL_ERR, "In-statements are not allowed when the option for qualified names is used\n");
+ goto exit;
+ }
+
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
@@ -349,14 +403,29 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci
cil_in_init(&in);
- in->block_str = parse_current->next->data;
+ if (parse_current->next->next->data) {
+ char *is_after_str = parse_current->next->data;
+ if (is_after_str == CIL_KEY_IN_BEFORE) {
+ in->is_after = CIL_FALSE;
+ } else if (is_after_str == CIL_KEY_IN_AFTER) {
+ in->is_after = CIL_TRUE;
+ } else {
+ cil_log(CIL_ERR, "Value must be either \'before\' or \'after\'\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ in->block_str = parse_current->next->next->data;
+ } else {
+ in->is_after = CIL_FALSE;
+ in->block_str = parse_current->next->data;
+ }
ast_node->data = in;
ast_node->flavor = CIL_IN;
return SEPOL_OK;
exit:
- cil_tree_log(parse_current, CIL_ERR, "Bad in statement");
+ cil_tree_log(parse_current, CIL_ERR, "Bad in-statement");
cil_destroy_in(in);
return rc;
}
@@ -380,7 +449,7 @@ int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_class *class = NULL;
struct cil_tree_node *perms = NULL;
@@ -413,6 +482,8 @@ int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct
}
if (class->num_perms > CIL_PERMS_PER_CLASS) {
cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name);
+ cil_tree_children_destroy(ast_node);
+ rc = SEPOL_ERR;
goto exit;
}
@@ -446,7 +517,7 @@ int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, s
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_classorder *classorder = NULL;
struct cil_list_item *curr = NULL;
struct cil_list_item *head = NULL;
@@ -563,7 +634,7 @@ int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, st
cil_tree_node_init(&new_ast);
new_ast->parent = ast_node;
new_ast->line = current_perm->line;
- new_ast->hll_line = current_perm->hll_line;
+ new_ast->hll_offset = current_perm->hll_offset;
rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms);
if (rc != SEPOL_OK) {
@@ -597,7 +668,7 @@ int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms)
CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -624,7 +695,7 @@ int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classper
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -680,20 +751,11 @@ int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_lis
{
int rc = SEPOL_ERR;
struct cil_tree_node *curr;
- enum cil_syntax syntax[] = {
- CIL_SYN_STRING | CIL_SYN_LIST,
- };
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
if (parse_current == NULL || cp_list == NULL) {
goto exit;
}
- rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
cil_list_init(cp_list, CIL_CLASSPERMS);
curr = parse_current->cl_head;
@@ -754,7 +816,7 @@ int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_curre
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
@@ -812,7 +874,7 @@ int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_cu
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
@@ -862,7 +924,7 @@ int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_class *map = NULL;
int rc = SEPOL_ERR;
@@ -906,7 +968,7 @@ int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
@@ -958,7 +1020,7 @@ int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_class *common = NULL;
int rc = SEPOL_ERR;
@@ -987,6 +1049,8 @@ int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struc
}
if (common->num_perms > CIL_PERMS_PER_CLASS) {
cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name);
+ cil_tree_children_destroy(ast_node);
+ rc = SEPOL_ERR;
goto exit;
}
@@ -1008,7 +1072,7 @@ int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_classcommon *clscom = NULL;
int rc = SEPOL_ERR;
@@ -1054,7 +1118,7 @@ int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct c
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_sid *sid = NULL;
int rc = SEPOL_ERR;
@@ -1104,7 +1168,7 @@ int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, s
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_sidcontext *sidcon = NULL;
int rc = SEPOL_ERR;
@@ -1163,7 +1227,7 @@ int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_sidorder *sidorder = NULL;
struct cil_list_item *curr = NULL;
int rc = SEPOL_ERR;
@@ -1223,7 +1287,7 @@ int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_user *user = NULL;
int rc = SEPOL_ERR;
@@ -1274,7 +1338,7 @@ int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_userattribute *attr = NULL;
int rc = SEPOL_ERR;
@@ -1341,7 +1405,7 @@ int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_curr
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userattributeset *attrset = NULL;
int rc = SEPOL_ERR;
@@ -1394,7 +1458,7 @@ int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userlevel *usrlvl = NULL;
int rc = SEPOL_ERR;
@@ -1454,7 +1518,7 @@ int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userrange *userrange = NULL;
int rc = SEPOL_ERR;
@@ -1514,7 +1578,7 @@ int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, s
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userprefix *userprefix = NULL;
int rc = SEPOL_ERR;
@@ -1560,7 +1624,7 @@ int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_selinuxuser *selinuxuser = NULL;
int rc = SEPOL_ERR;
@@ -1607,7 +1671,7 @@ int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_cu
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_selinuxuser *selinuxuser = NULL;
int rc = SEPOL_ERR;
@@ -1666,7 +1730,7 @@ int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_role *role = NULL;
int rc = SEPOL_ERR;
@@ -1718,7 +1782,7 @@ int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_roletype *roletype = NULL;
int rc = SEPOL_ERR;
@@ -1764,7 +1828,7 @@ int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userrole *userrole = NULL;
int rc = SEPOL_ERR;
@@ -1812,7 +1876,7 @@ int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_roletransition *roletrans = NULL;
int rc = SEPOL_ERR;
@@ -1860,7 +1924,7 @@ int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_roleallow *roleallow = NULL;
int rc = SEPOL_ERR;
@@ -1905,7 +1969,7 @@ int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_roleattribute *attr = NULL;
int rc = SEPOL_ERR;
@@ -1919,12 +1983,6 @@ int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_roleattribute_init(&attr);
key = parse_current->next->data;
@@ -1975,7 +2033,7 @@ int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_curr
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_roleattributeset *attrset = NULL;
int rc = SEPOL_ERR;
@@ -2029,7 +2087,7 @@ int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *as
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_avrule *rule = NULL;
int rc = SEPOL_ERR;
@@ -2091,7 +2149,7 @@ int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permiss
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
@@ -2129,7 +2187,7 @@ int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_permissionx *permx = NULL;
int rc = SEPOL_ERR;
@@ -2189,7 +2247,7 @@ int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *a
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_avrule *rule = NULL;
int rc = SEPOL_ERR;
@@ -2241,7 +2299,7 @@ int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_type_rule *rule = NULL;
int rc = SEPOL_ERR;
@@ -2289,7 +2347,7 @@ int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_type *type = NULL;
int rc = SEPOL_ERR;
@@ -2303,18 +2361,17 @@ int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_type_init(&type);
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE);
if (rc != SEPOL_OK) {
- goto exit;
+ if (rc == SEPOL_EEXIST) {
+ cil_destroy_type(type);
+ type = NULL;
+ } else {
+ goto exit;
+ }
}
return SEPOL_OK;
@@ -2343,7 +2400,7 @@ int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_typeattribute *attr = NULL;
int rc = SEPOL_ERR;
@@ -2357,18 +2414,17 @@ int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current
goto exit;
}
- if (parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_typeattribute_init(&attr);
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
if (rc != SEPOL_OK) {
- goto exit;
+ if (rc == SEPOL_EEXIST) {
+ cil_destroy_typeattribute(attr);
+ attr = NULL;
+ } else {
+ goto exit;
+ }
}
return SEPOL_OK;
@@ -2414,7 +2470,7 @@ int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_bool *boolean = NULL;
int rc = SEPOL_ERR;
@@ -2478,7 +2534,7 @@ int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_tunable *tunable = NULL;
int rc = SEPOL_ERR;
@@ -2544,18 +2600,13 @@ static enum cil_flavor __cil_get_expr_operator_flavor(const char *op)
else return CIL_NONE;
}
-static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth);
+static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr);
-static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth)
+static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
{
int rc = SEPOL_ERR;
enum cil_flavor op;
- if (flavor == CIL_BOOL && *depth > COND_EXPR_MAXDEPTH) {
- cil_log(CIL_ERR, "Max depth of %d exceeded for boolean expression\n", COND_EXPR_MAXDEPTH);
- goto exit;
- }
-
op = __cil_get_expr_operator_flavor(current->data);
rc = cil_verify_expr_syntax(current, op, flavor);
@@ -2568,26 +2619,20 @@ static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor
current = current->next;
}
- if (op == CIL_NONE || op == CIL_ALL) {
- (*depth)++;
- }
-
for (;current != NULL; current = current->next) {
- rc = __cil_fill_expr(current, flavor, expr, depth);
+ rc = __cil_fill_expr(current, flavor, expr);
if (rc != SEPOL_OK) {
goto exit;
}
}
- (*depth)--;
-
return SEPOL_OK;
exit:
return rc;
}
-static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth)
+static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
{
int rc = SEPOL_ERR;
@@ -2601,7 +2646,7 @@ static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor
} else {
struct cil_list *sub_expr;
cil_list_init(&sub_expr, flavor);
- rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr, depth);
+ rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr);
if (rc != SEPOL_OK) {
cil_list_destroy(&sub_expr, CIL_TRUE);
goto exit;
@@ -2619,14 +2664,13 @@ exit:
int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
{
int rc = SEPOL_ERR;
- int depth = 0;
cil_list_init(expr, flavor);
if (current->cl_head == NULL) {
- rc = __cil_fill_expr(current, flavor, *expr, &depth);
+ rc = __cil_fill_expr(current, flavor, *expr);
} else {
- rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr, &depth);
+ rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr);
}
if (rc != SEPOL_OK) {
@@ -2721,8 +2765,12 @@ static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current, enum c
cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data);
} else if (r_flavor == CIL_LIST) {
struct cil_list *sub_list;
- cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
- cil_list_append(*leaf_expr, CIL_LIST, &sub_list);
+ rc = cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
+ if (rc != SEPOL_OK) {
+ cil_list_destroy(leaf_expr, CIL_TRUE);
+ goto exit;
+ }
+ cil_list_append(*leaf_expr, CIL_LIST, sub_list);
} else {
cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor);
}
@@ -2734,7 +2782,7 @@ exit:
return SEPOL_ERR;
}
-static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr, int *depth)
+static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
{
int rc = SEPOL_ERR;
enum cil_flavor op;
@@ -2746,12 +2794,6 @@ static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_fl
goto exit;
}
- if (*depth > CEXPR_MAXDEPTH) {
- cil_log(CIL_ERR, "Max depth of %d exceeded for constraint expression\n", CEXPR_MAXDEPTH);
- rc = SEPOL_ERR;
- goto exit;
- }
-
op = __cil_get_constraint_operator_flavor(current->data);
rc = cil_verify_constraint_expr_syntax(current, op);
@@ -2765,14 +2807,13 @@ static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_fl
case CIL_CONS_DOM:
case CIL_CONS_DOMBY:
case CIL_CONS_INCOMP:
- (*depth)++;
rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr);
if (rc != SEPOL_OK) {
goto exit;
}
break;
case CIL_NOT:
- rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth);
+ rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr);
if (rc != SEPOL_OK) {
goto exit;
}
@@ -2781,11 +2822,11 @@ static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_fl
cil_list_append(*expr, CIL_LIST, lexpr);
break;
default:
- rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr, depth);
+ rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr);
if (rc != SEPOL_OK) {
goto exit;
}
- rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr, depth);
+ rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr);
if (rc != SEPOL_OK) {
cil_list_destroy(&lexpr, CIL_TRUE);
goto exit;
@@ -2797,8 +2838,6 @@ static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_fl
break;
}
- (*depth)--;
-
return SEPOL_OK;
exit:
@@ -2808,13 +2847,12 @@ exit:
int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
{
int rc = SEPOL_ERR;
- int depth = 0;
if (current->cl_head == NULL) {
goto exit;
}
- rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr, &depth);
+ rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr);
if (rc != SEPOL_OK) {
goto exit;
}
@@ -2836,10 +2874,9 @@ int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_booleanif *bif = NULL;
struct cil_tree_node *next = NULL;
- struct cil_tree_node *cond = NULL;
int rc = SEPOL_ERR;
if (db == NULL || parse_current == NULL || ast_node == NULL) {
@@ -2859,27 +2896,12 @@ int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struc
goto exit;
}
- cond = parse_current->next->next;
-
- /* Destroying expr tree after stack is created*/
- if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
- cond->cl_head->data != CIL_KEY_CONDFALSE) {
- rc = SEPOL_ERR;
- cil_log(CIL_ERR, "Conditional neither true nor false\n");
+ rc = cil_verify_conditional_blocks(parse_current->next->next);
+ if (rc != SEPOL_OK) {
goto exit;
}
- if (cond->next != NULL) {
- cond = cond->next;
- if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
- cond->cl_head->data != CIL_KEY_CONDFALSE) {
- rc = SEPOL_ERR;
- cil_log(CIL_ERR, "Conditional neither true nor false\n");
- goto exit;
- }
- }
-
-
+ /* Destroying expr tree */
next = parse_current->next->next;
cil_tree_subtree_destroy(parse_current->next);
parse_current->next = next;
@@ -2920,10 +2942,9 @@ int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_tunableif *tif = NULL;
struct cil_tree_node *next = NULL;
- struct cil_tree_node *cond = NULL;
int rc = SEPOL_ERR;
if (db == NULL || parse_current == NULL || ast_node == NULL) {
@@ -2942,27 +2963,12 @@ int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
- cond = parse_current->next->next;
-
- if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
- cond->cl_head->data != CIL_KEY_CONDFALSE) {
- rc = SEPOL_ERR;
- cil_log(CIL_ERR, "Conditional neither true nor false\n");
+ rc = cil_verify_conditional_blocks(parse_current->next->next);
+ if (rc != SEPOL_OK) {
goto exit;
}
- if (cond->next != NULL) {
- cond = cond->next;
-
- if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
- cond->cl_head->data != CIL_KEY_CONDFALSE) {
- rc = SEPOL_ERR;
- cil_log(CIL_ERR, "Conditional neither true nor false\n");
- goto exit;
- }
- }
-
- /* Destroying expr tree after stack is created*/
+ /* Destroying expr tree */
next = parse_current->next->next;
cil_tree_subtree_destroy(parse_current->next);
parse_current->next = next;
@@ -2997,7 +3003,7 @@ int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_N_LISTS,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_condblock *cb = NULL;
@@ -3049,7 +3055,7 @@ int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_alias *alias = NULL;
enum cil_sym_index sym_index;
@@ -3064,12 +3070,6 @@ int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct
goto exit;
}
- if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) {
- cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
- rc = SEPOL_ERR;
- goto exit;
- }
-
cil_alias_init(&alias);
key = parse_current->next->data;
@@ -3114,7 +3114,7 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_aliasactual *aliasactual = NULL;
if (db == NULL || parse_current == NULL || ast_node == NULL) {
@@ -3166,7 +3166,7 @@ int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_curr
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_typeattributeset *attrset = NULL;
int rc = SEPOL_ERR;
@@ -3219,7 +3219,7 @@ int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_c
CIL_SYN_END
};
char *expand_str;
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_expandtypeattribute *expandattr = NULL;
int rc = SEPOL_ERR;
@@ -3252,6 +3252,7 @@ int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_c
expandattr->expand = CIL_FALSE;
} else {
cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
+ rc = SEPOL_ERR;
goto exit;
}
@@ -3286,7 +3287,7 @@ int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_curren
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_typepermissive *typeperm = NULL;
int rc = SEPOL_ERR;
@@ -3335,7 +3336,7 @@ int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_curren
CIL_SYN_STRING | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *s1, *s2, *s3, *s4, *s5;
if (db == NULL || parse_current == NULL || ast_node == NULL ) {
@@ -3425,7 +3426,7 @@ int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_curre
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_rangetransition *rangetrans = NULL;
int rc = SEPOL_ERR;
@@ -3488,7 +3489,7 @@ int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_sens *sens = NULL;
int rc = SEPOL_ERR;
@@ -3540,7 +3541,7 @@ int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_cat *cat = NULL;
int rc = SEPOL_ERR;
@@ -3590,7 +3591,7 @@ int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_catset *catset = NULL;
int rc = SEPOL_ERR;
@@ -3647,7 +3648,7 @@ int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_catorder *catorder = NULL;
struct cil_list_item *curr = NULL;
int rc = SEPOL_ERR;
@@ -3707,7 +3708,7 @@ int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_curr
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_sensorder *sensorder = NULL;
struct cil_list_item *curr = NULL;
int rc = SEPOL_ERR;
@@ -3730,7 +3731,7 @@ int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_curr
cil_list_for_each(curr, sensorder->sens_list_str) {
if (curr->data == CIL_KEY_UNORDERED) {
- cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
+ cil_log(CIL_ERR, "Sensitivity order cannot be unordered.\n");
rc = SEPOL_ERR;
goto exit;
}
@@ -3768,7 +3769,7 @@ int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_senscat *senscat = NULL;
int rc = SEPOL_ERR;
@@ -3820,7 +3821,7 @@ int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_level *level = NULL;
int rc = SEPOL_ERR;
@@ -3878,7 +3879,7 @@ int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlran
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
if (low == NULL || lvlrange == NULL) {
@@ -3926,7 +3927,7 @@ int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, s
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_levelrange *lvlrange = NULL;
int rc = SEPOL_ERR;
@@ -3990,7 +3991,7 @@ int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_constrain *cons = NULL;
int rc = SEPOL_ERR;
@@ -4047,7 +4048,7 @@ int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_validatetrans *validtrans = NULL;
int rc = SEPOL_ERR;
@@ -4104,7 +4105,7 @@ int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *contex
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
if (user_node == NULL || context == NULL) {
@@ -4148,7 +4149,7 @@ int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_context *context = NULL;
int rc = SEPOL_ERR;
@@ -4191,7 +4192,7 @@ void cil_destroy_context(struct cil_context *context)
return;
}
- cil_symtab_datum_destroy(&context->datum);;
+ cil_symtab_datum_destroy(&context->datum);
if (context->range_str == NULL && context->range != NULL) {
cil_destroy_levelrange(context->range);
@@ -4209,7 +4210,7 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_filecon *filecon = NULL;
char *type = NULL;
@@ -4228,7 +4229,9 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru
filecon->path_str = parse_current->next->data;
- if (type == CIL_KEY_FILE) {
+ if (type == CIL_KEY_ANY) {
+ filecon->type = CIL_FILECON_ANY;
+ } else if (type == CIL_KEY_FILE) {
filecon->type = CIL_FILECON_FILE;
} else if (type == CIL_KEY_DIR) {
filecon->type = CIL_FILECON_DIR;
@@ -4242,8 +4245,6 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru
filecon->type = CIL_FILECON_PIPE;
} else if (type == CIL_KEY_SYMLINK) {
filecon->type = CIL_FILECON_SYMLINK;
- } else if (type == CIL_KEY_ANY) {
- filecon->type = CIL_FILECON_ANY;
} else {
cil_log(CIL_ERR, "Invalid file type\n");
rc = SEPOL_ERR;
@@ -4299,7 +4300,7 @@ int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax) / sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_ibpkeycon *ibpkeycon = NULL;
@@ -4382,7 +4383,7 @@ int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_portcon *portcon = NULL;
char *proto;
@@ -4484,7 +4485,7 @@ int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_nodecon *nodecon = NULL;
@@ -4571,9 +4572,11 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING,
CIL_SYN_STRING,
CIL_SYN_STRING | CIL_SYN_LIST,
+ CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
+ struct cil_tree_node *context_node;
int rc = SEPOL_ERR;
struct cil_genfscon *genfscon = NULL;
@@ -4591,15 +4594,48 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str
genfscon->fs_str = parse_current->next->data;
genfscon->path_str = parse_current->next->next->data;
- if (parse_current->next->next->next->cl_head == NULL ) {
- genfscon->context_str = parse_current->next->next->next->data;
+ if (parse_current->next->next->next->next) {
+ /* (genfscon <FS_STR> <PATH_STR> <FILE_TYPE> ... */
+ char *file_type = parse_current->next->next->next->data;
+ if (file_type == CIL_KEY_ANY) {
+ genfscon->file_type = CIL_FILECON_ANY;
+ } else if (file_type == CIL_KEY_FILE) {
+ genfscon->file_type = CIL_FILECON_FILE;
+ } else if (file_type == CIL_KEY_DIR) {
+ genfscon->file_type = CIL_FILECON_DIR;
+ } else if (file_type == CIL_KEY_CHAR) {
+ genfscon->file_type = CIL_FILECON_CHAR;
+ } else if (file_type == CIL_KEY_BLOCK) {
+ genfscon->file_type = CIL_FILECON_BLOCK;
+ } else if (file_type == CIL_KEY_SOCKET) {
+ genfscon->file_type = CIL_FILECON_SOCKET;
+ } else if (file_type == CIL_KEY_PIPE) {
+ genfscon->file_type = CIL_FILECON_PIPE;
+ } else if (file_type == CIL_KEY_SYMLINK) {
+ genfscon->file_type = CIL_FILECON_SYMLINK;
+ } else {
+ if (parse_current->next->next->next->cl_head) {
+ cil_log(CIL_ERR, "Expecting file type, but found a list\n");
+ } else {
+ cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type);
+ }
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ context_node = parse_current->next->next->next->next;
} else {
- cil_context_init(&genfscon->context);
+ /* (genfscon <FS_STR> <PATH_STR> ... */
+ context_node = parse_current->next->next->next;
+ }
- rc = cil_fill_context(parse_current->next->next->next->cl_head, genfscon->context);
+ if (context_node->cl_head) {
+ cil_context_init(&genfscon->context);
+ rc = cil_fill_context(context_node->cl_head, genfscon->context);
if (rc != SEPOL_OK) {
goto exit;
}
+ } else {
+ genfscon->context_str = context_node->data;
}
ast_node->data = genfscon;
@@ -4636,7 +4672,7 @@ int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_netifcon *netifcon = NULL;
@@ -4712,7 +4748,7 @@ int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_t
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax) / sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_ibendportcon *ibendportcon = NULL;
@@ -4773,7 +4809,7 @@ int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, stru
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_pirqcon *pirqcon = NULL;
@@ -4836,7 +4872,7 @@ int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_iomemcon *iomemcon = NULL;
@@ -4921,7 +4957,7 @@ int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_ioportcon *ioportcon = NULL;
@@ -5006,7 +5042,7 @@ int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_pcidevicecon *pcidevicecon = NULL;
@@ -5069,7 +5105,7 @@ int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
struct cil_devicetreecon *devicetreecon = NULL;
@@ -5130,7 +5166,7 @@ int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *type = NULL;
struct cil_fsuse *fsuse = NULL;
int rc = SEPOL_ERR;
@@ -5211,6 +5247,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
char *key = NULL;
struct cil_macro *macro = NULL;
struct cil_tree_node *macro_content = NULL;
+ struct cil_tree_node *current_item;
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
@@ -5218,7 +5255,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_N_LISTS | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/ sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/ sizeof(*syntax);
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
@@ -5233,7 +5270,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
key = parse_current->next->data;
- struct cil_tree_node *current_item = parse_current->next->next->cl_head;
+ current_item = parse_current->next->next->cl_head;
while (current_item != NULL) {
enum cil_syntax param_syntax[] = {
CIL_SYN_STRING,
@@ -5243,6 +5280,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
char *kind = NULL;
struct cil_param *param = NULL;
+ struct cil_list_item *curr_param;
rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
if (rc != SEPOL_OK) {
@@ -5294,21 +5332,18 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct
param->str = current_item->cl_head->next->data;
- rc = __cil_verify_name(param->str);
+ rc = cil_verify_name(db, param->str, param->flavor);
if (rc != SEPOL_OK) {
cil_destroy_param(param);
goto exit;
}
//walk current list and check for duplicate parameters
- struct cil_list_item *curr_param;
cil_list_for_each(curr_param, macro->params) {
if (param->str == ((struct cil_param*)curr_param->data)->str) {
- if (param->flavor == ((struct cil_param*)curr_param->data)->flavor) {
- cil_log(CIL_ERR, "Duplicate parameter\n");
- cil_destroy_param(param);
- goto exit;
- }
+ cil_log(CIL_ERR, "Duplicate parameter\n");
+ cil_destroy_param(param);
+ goto exit;
}
}
@@ -5365,7 +5400,7 @@ int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct
CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_call *call = NULL;
int rc = SEPOL_ERR;
@@ -5470,7 +5505,7 @@ int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, str
CIL_SYN_N_LISTS | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_optional *optional = NULL;
int rc = SEPOL_ERR;
@@ -5489,8 +5524,14 @@ int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, str
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
- if (rc != SEPOL_OK)
- goto exit;
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ cil_destroy_optional(optional);
+ optional = NULL;
+ } else {
+ goto exit;
+ }
+ }
return SEPOL_OK;
@@ -5518,7 +5559,7 @@ int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, st
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_policycap *polcap = NULL;
int rc = SEPOL_ERR;
@@ -5567,7 +5608,7 @@ int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_ipaddr *ipaddr = NULL;
int rc = SEPOL_ERR;
@@ -5617,52 +5658,40 @@ void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
{
int rc = SEPOL_ERR;
- char *endptr = NULL;
- int val;
- if (int_node == NULL || integer == NULL) {
+ if (int_node == NULL || int_node->data == NULL || integer == NULL) {
goto exit;
}
- errno = 0;
- val = strtol(int_node->data, &endptr, base);
- if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
- rc = SEPOL_ERR;
+ rc = cil_string_to_uint32(int_node->data, integer, base);
+ if (rc != SEPOL_OK) {
goto exit;
}
- *integer = val;
-
return SEPOL_OK;
exit:
- cil_log(CIL_ERR, "Failed to create integer from string\n");
+ cil_log(CIL_ERR, "Failed to fill 32-bit integer\n");
return rc;
}
int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
{
int rc = SEPOL_ERR;
- char *endptr = NULL;
- uint64_t val;
- if (int_node == NULL || integer == NULL) {
+ if (int_node == NULL || int_node->data == NULL || integer == NULL) {
goto exit;
}
- errno = 0;
- val = strtoull(int_node->data, &endptr, base);
- if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
- rc = SEPOL_ERR;
+ rc = cil_string_to_uint64(int_node->data, integer, base);
+ if (rc != SEPOL_OK) {
goto exit;
}
- *integer = val;
-
return SEPOL_OK;
exit:
- cil_log(CIL_ERR, "Failed to create integer from string\n");
+ cil_log(CIL_ERR, "Failed to fill 64-bit integer\n");
return rc;
}
@@ -5670,18 +5699,14 @@ int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
{
int rc = SEPOL_ERR;
- if (addr_node == NULL || addr == NULL) {
- goto exit;
- }
-
- if (addr_node->cl_head != NULL || addr_node->next != NULL) {
+ if (addr_node == NULL || addr_node->data == NULL || addr == NULL) {
goto exit;
}
- if (strchr(addr_node->data, '.') != NULL) {
- addr->family = AF_INET;
- } else {
+ if (strchr(addr_node->data, ':') != NULL) {
addr->family = AF_INET6;
+ } else {
+ addr->family = AF_INET;
}
rc = inet_pton(addr->family, addr_node->data, &addr->ip);
@@ -5693,7 +5718,7 @@ int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
return SEPOL_OK;
exit:
- cil_log(CIL_ERR, "Bad ip address or netmask\n");
+ cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "n/a");
return rc;
}
@@ -5705,7 +5730,7 @@ int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
if (curr == NULL) {
goto exit;
@@ -5766,7 +5791,7 @@ int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struc
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_bounds *bounds = NULL;
int rc = SEPOL_ERR;
@@ -5828,7 +5853,7 @@ int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *a
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -5897,7 +5922,7 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no
CIL_SYN_STRING | CIL_SYN_END,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
@@ -5918,6 +5943,11 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no
object = parse_current->next->next->data;
if (object == CIL_KEY_SOURCE) {
+ if (!parse_current->next->next->next) {
+ cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
range = parse_current->next->next->next->data;
if (range == CIL_KEY_LOW) {
def->object_range = CIL_DEFAULT_SOURCE_LOW;
@@ -5931,6 +5961,11 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no
goto exit;
}
} else if (object == CIL_KEY_TARGET) {
+ if (!parse_current->next->next->next) {
+ cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
range = parse_current->next->next->next->data;
if (range == CIL_KEY_LOW) {
def->object_range = CIL_DEFAULT_TARGET_LOW;
@@ -5983,7 +6018,7 @@ int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_n
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_handleunknown *unknown = NULL;
char *unknown_key;
@@ -6035,7 +6070,7 @@ int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_n
CIL_SYN_STRING,
CIL_SYN_END
};
- int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_mls *mls = NULL;
if (parse_current == NULL || ast_node == NULL) {
@@ -6077,18 +6112,52 @@ void cil_destroy_mls(struct cil_mls *mls)
int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
- /* No need to check syntax, because this is auto generated */
+ int rc = SEPOL_ERR;
+ enum cil_syntax syntax[] = {
+ CIL_SYN_STRING,
+ CIL_SYN_STRING,
+ CIL_SYN_STRING,
+ CIL_SYN_STRING,
+ CIL_SYN_N_LISTS | CIL_SYN_END,
+ CIL_SYN_END
+ };
+ size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_src_info *info = NULL;
+ if (parse_current == NULL || ast_node == NULL) {
+ goto exit;
+ }
+
+ rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
cil_src_info_init(&info);
- info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE;
- info->path = parse_current->next->next->data;
+ info->kind = parse_current->next->data;
+ if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) {
+ cil_log(CIL_ERR, "Invalid src info kind\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ info->path = parse_current->next->next->next->data;
ast_node->data = info;
ast_node->flavor = CIL_SRC_INFO;
return SEPOL_OK;
+
+exit:
+ cil_tree_log(parse_current, CIL_ERR, "Bad src info");
+ cil_destroy_src_info(info);
+ return rc;
}
void cil_destroy_src_info(struct cil_src_info *info)
@@ -6096,443 +6165,396 @@ void cil_destroy_src_info(struct cil_src_info *info)
free(info);
}
-int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
+static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
{
- struct cil_args_build *args = NULL;
- struct cil_tree_node *ast_current = NULL;
- struct cil_db *db = NULL;
- struct cil_tree_node *ast_node = NULL;
- struct cil_tree_node *macro = NULL;
- struct cil_tree_node *boolif = NULL;
- struct cil_tree_node *tunif = NULL;
- struct cil_tree_node *in = NULL;
- int rc = SEPOL_ERR;
-
- if (parse_current == NULL || finished == NULL || extra_args == NULL) {
- goto exit;
+ if (args->tunif != NULL) {
+ if (parse_current->data == CIL_KEY_TUNABLE) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data);
+ return SEPOL_ERR;
+ }
}
- args = extra_args;
- ast_current = args->ast;
- db = args->db;
- macro = args->macro;
- boolif = args->boolif;
- tunif = args->tunif;
- in = args->in;
-
- if (parse_current->parent->cl_head != parse_current) {
- /* ignore anything that isn't following a parenthesis */
- rc = SEPOL_OK;
- goto exit;
- } else if (parse_current->data == NULL) {
- /* the only time parenthesis can immediately following parenthesis is if
- * the parent is the root node */
- if (parse_current->parent->parent == NULL) {
- rc = SEPOL_OK;
- } else {
- cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
+ if (args->in != NULL) {
+ struct cil_in *in_block = args->in->data;
+ if (parse_current->data == CIL_KEY_TUNABLE ||
+ parse_current->data == CIL_KEY_IN) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data);
+ return SEPOL_ERR;
+ }
+ if (in_block->is_after == CIL_TRUE) {
+ if (parse_current->data == CIL_KEY_BLOCKINHERIT ||
+ parse_current->data == CIL_KEY_BLOCKABSTRACT) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data);
+ return SEPOL_ERR;
+ }
}
- goto exit;
}
- if (macro != NULL) {
- if (parse_current->data == CIL_KEY_MACRO ||
- parse_current->data == CIL_KEY_TUNABLE ||
+ if (args->macro != NULL) {
+ if (parse_current->data == CIL_KEY_TUNABLE ||
parse_current->data == CIL_KEY_IN ||
parse_current->data == CIL_KEY_BLOCK ||
parse_current->data == CIL_KEY_BLOCKINHERIT ||
- parse_current->data == CIL_KEY_BLOCKABSTRACT) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data);
- goto exit;
+ parse_current->data == CIL_KEY_BLOCKABSTRACT ||
+ parse_current->data == CIL_KEY_MACRO) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data);
+ return SEPOL_ERR;
}
}
- if (boolif != NULL) {
- if (parse_current->data != CIL_KEY_CONDTRUE &&
+ if (args->optional != NULL) {
+ if (parse_current->data == CIL_KEY_TUNABLE ||
+ parse_current->data == CIL_KEY_IN ||
+ parse_current->data == CIL_KEY_BLOCK ||
+ parse_current->data == CIL_KEY_BLOCKABSTRACT ||
+ parse_current->data == CIL_KEY_MACRO) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data);
+ return SEPOL_ERR;
+ }
+ }
+
+ if (args->boolif != NULL) {
+ if (parse_current->data != CIL_KEY_TUNABLEIF &&
+ parse_current->data != CIL_KEY_CALL &&
+ parse_current->data != CIL_KEY_CONDTRUE &&
parse_current->data != CIL_KEY_CONDFALSE &&
- parse_current->data != CIL_KEY_AUDITALLOW &&
- parse_current->data != CIL_KEY_TUNABLEIF &&
parse_current->data != CIL_KEY_ALLOW &&
parse_current->data != CIL_KEY_DONTAUDIT &&
+ parse_current->data != CIL_KEY_AUDITALLOW &&
parse_current->data != CIL_KEY_TYPETRANSITION &&
parse_current->data != CIL_KEY_TYPECHANGE &&
- parse_current->data != CIL_KEY_CALL) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
- if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
- cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n",
- (char*)parse_current->data);
+ parse_current->data != CIL_KEY_TYPEMEMBER) {
+ if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) {
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
} else {
- cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n",
- (char*)parse_current->data);
+ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
}
- goto exit;
- }
- }
-
- if (tunif != NULL) {
- if (parse_current->data == CIL_KEY_TUNABLE) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found tunable");
- cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
- goto exit;
+ return SEPOL_ERR;
}
}
- if (in != NULL) {
- if (parse_current->data == CIL_KEY_IN) {
- rc = SEPOL_ERR;
- cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
- cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
- goto exit;
- }
- }
+ return SEPOL_OK;
+}
- cil_tree_node_init(&ast_node);
+static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent)
+{
+ struct cil_tree_node *new_ast_node = NULL;
+ int rc = SEPOL_ERR;
- ast_node->parent = ast_current;
- ast_node->line = parse_current->line;
- ast_node->hll_line = parse_current->hll_line;
+ cil_tree_node_init(&new_ast_node);
+ new_ast_node->parent = ast_parent;
+ new_ast_node->line = parse_current->line;
+ new_ast_node->hll_offset = parse_current->hll_offset;
if (parse_current->data == CIL_KEY_BLOCK) {
- rc = cil_gen_block(db, parse_current, ast_node, 0);
+ rc = cil_gen_block(db, parse_current, new_ast_node, 0);
} else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
- rc = cil_gen_blockinherit(db, parse_current, ast_node);
+ rc = cil_gen_blockinherit(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
- rc = cil_gen_blockabstract(db, parse_current, ast_node);
+ rc = cil_gen_blockabstract(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IN) {
- rc = cil_gen_in(db, parse_current, ast_node);
+ rc = cil_gen_in(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASS) {
- rc = cil_gen_class(db, parse_current, ast_node);
- // To avoid parsing list of perms again
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_class(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSORDER) {
- rc = cil_gen_classorder(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_classorder(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_MAP_CLASS) {
- rc = cil_gen_map_class(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_map_class(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
- rc = cil_gen_classmapping(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_classmapping(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
- rc = cil_gen_classpermission(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_classpermission(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
- rc = cil_gen_classpermissionset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_classpermissionset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_COMMON) {
- rc = cil_gen_common(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_common(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
- rc = cil_gen_classcommon(db, parse_current, ast_node);
+ rc = cil_gen_classcommon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SID) {
- rc = cil_gen_sid(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_sid(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
- rc = cil_gen_sidcontext(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_sidcontext(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SIDORDER) {
- rc = cil_gen_sidorder(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_sidorder(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USER) {
- rc = cil_gen_user(db, parse_current, ast_node);
+ rc = cil_gen_user(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
- rc = cil_gen_userattribute(db, parse_current, ast_node);
+ rc = cil_gen_userattribute(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
- rc = cil_gen_userattributeset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_userattributeset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERLEVEL) {
- rc = cil_gen_userlevel(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_userlevel(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERRANGE) {
- rc = cil_gen_userrange(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_userrange(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERBOUNDS) {
- rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER);
+ rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER);
} else if (parse_current->data == CIL_KEY_USERPREFIX) {
- rc = cil_gen_userprefix(db, parse_current, ast_node);
+ rc = cil_gen_userprefix(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SELINUXUSER) {
- rc = cil_gen_selinuxuser(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_selinuxuser(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
- rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPE) {
- rc = cil_gen_type(db, parse_current, ast_node);
+ rc = cil_gen_type(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
- rc = cil_gen_typeattribute(db, parse_current, ast_node);
+ rc = cil_gen_typeattribute(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
- rc = cil_gen_typeattributeset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_typeattributeset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
- rc = cil_gen_expandtypeattribute(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPEALIAS) {
- rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS);
+ rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS);
} else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
- rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL);
+ rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL);
} else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
- rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE);
+ rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE);
} else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
- rc = cil_gen_typepermissive(db, parse_current, ast_node);
+ rc = cil_gen_typepermissive(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
- rc = cil_gen_rangetransition(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_rangetransition(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLE) {
- rc = cil_gen_role(db, parse_current, ast_node);
+ rc = cil_gen_role(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_USERROLE) {
- rc = cil_gen_userrole(db, parse_current, ast_node);
+ rc = cil_gen_userrole(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLETYPE) {
- rc = cil_gen_roletype(db, parse_current, ast_node);
+ rc = cil_gen_roletype(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
- rc = cil_gen_roletransition(parse_current, ast_node);
+ rc = cil_gen_roletransition(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLEALLOW) {
- rc = cil_gen_roleallow(db, parse_current, ast_node);
+ rc = cil_gen_roleallow(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
- rc = cil_gen_roleattribute(db, parse_current, ast_node);
+ rc = cil_gen_roleattribute(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
- rc = cil_gen_roleattributeset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_roleattributeset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
- rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE);
+ rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE);
} else if (parse_current->data == CIL_KEY_BOOL) {
- rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE);
+ rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE);
} else if (parse_current->data == CIL_KEY_BOOLEANIF) {
- rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE);
+ rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE);
} else if(parse_current->data == CIL_KEY_TUNABLE) {
if (db->preserve_tunables) {
- rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE);
+ rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE);
} else {
- rc = cil_gen_tunable(db, parse_current, ast_node);
+ rc = cil_gen_tunable(db, parse_current, new_ast_node);
}
} else if (parse_current->data == CIL_KEY_TUNABLEIF) {
if (db->preserve_tunables) {
- rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE);
+ rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE);
} else {
- rc = cil_gen_tunif(db, parse_current, ast_node);
+ rc = cil_gen_tunif(db, parse_current, new_ast_node);
}
} else if (parse_current->data == CIL_KEY_CONDTRUE) {
- rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE);
+ rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE);
} else if (parse_current->data == CIL_KEY_CONDFALSE) {
- rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE);
+ rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE);
} else if (parse_current->data == CIL_KEY_ALLOW) {
- rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED);
- // So that the object and perms lists do not get parsed again
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
} else if (parse_current->data == CIL_KEY_AUDITALLOW) {
- rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
} else if (parse_current->data == CIL_KEY_DONTAUDIT) {
- rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
- rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
} else if (parse_current->data == CIL_KEY_ALLOWX) {
- rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
- rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
- rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
} else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
- rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
- rc = cil_gen_permissionx(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_permissionx(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
- rc = cil_gen_typetransition(db, parse_current, ast_node);
+ rc = cil_gen_typetransition(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_TYPECHANGE) {
- rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE);
+ rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE);
} else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
- rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER);
+ rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER);
} else if (parse_current->data == CIL_KEY_SENSITIVITY) {
- rc = cil_gen_sensitivity(db, parse_current, ast_node);
+ rc = cil_gen_sensitivity(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SENSALIAS) {
- rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS);
+ rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS);
} else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
- rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL);
+ rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL);
} else if (parse_current->data == CIL_KEY_CATEGORY) {
- rc = cil_gen_category(db, parse_current, ast_node);
+ rc = cil_gen_category(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CATALIAS) {
- rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS);
+ rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS);
} else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
- rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL);
+ rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL);
} else if (parse_current->data == CIL_KEY_CATSET) {
- rc = cil_gen_catset(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_catset(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CATORDER) {
- rc = cil_gen_catorder(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_catorder(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
- rc = cil_gen_sensitivityorder(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_sensitivityorder(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SENSCAT) {
- rc = cil_gen_senscat(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_senscat(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_LEVEL) {
- rc = cil_gen_level(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_level(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_LEVELRANGE) {
- rc = cil_gen_levelrange(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_levelrange(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CONSTRAIN) {
- rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN);
} else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
- rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN);
} else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
- rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS);
} else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
- rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS);
} else if (parse_current->data == CIL_KEY_CONTEXT) {
- rc = cil_gen_context(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_context(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_FILECON) {
- rc = cil_gen_filecon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_filecon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IBPKEYCON) {
- rc = cil_gen_ibpkeycon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
- rc = cil_gen_ibendportcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_ibendportcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_PORTCON) {
- rc = cil_gen_portcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_portcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_NODECON) {
- rc = cil_gen_nodecon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_nodecon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_GENFSCON) {
- rc = cil_gen_genfscon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_genfscon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_NETIFCON) {
- rc = cil_gen_netifcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_netifcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_PIRQCON) {
- rc = cil_gen_pirqcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_pirqcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IOMEMCON) {
- rc = cil_gen_iomemcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_iomemcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IOPORTCON) {
- rc = cil_gen_ioportcon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_ioportcon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
- rc = cil_gen_pcidevicecon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_DEVICETREECON) {
- rc = cil_gen_devicetreecon(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_devicetreecon(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_FSUSE) {
- rc = cil_gen_fsuse(db, parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_fsuse(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_MACRO) {
- rc = cil_gen_macro(db, parse_current, ast_node);
+ rc = cil_gen_macro(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_CALL) {
- rc = cil_gen_call(db, parse_current, ast_node);
- *finished = 1;
+ rc = cil_gen_call(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_POLICYCAP) {
- rc = cil_gen_policycap(db, parse_current, ast_node);
- *finished = 1;
+ rc = cil_gen_policycap(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_OPTIONAL) {
- rc = cil_gen_optional(db, parse_current, ast_node);
+ rc = cil_gen_optional(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_IPADDR) {
- rc = cil_gen_ipaddr(db, parse_current, ast_node);
+ rc = cil_gen_ipaddr(db, parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
- rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER);
} else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
- rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE);
} else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
- rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE);
} else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
- rc = cil_gen_defaultrange(parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_defaultrange(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
- rc = cil_gen_handleunknown(parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_handleunknown(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_MLS) {
- rc = cil_gen_mls(parse_current, ast_node);
- *finished = CIL_TREE_SKIP_NEXT;
+ rc = cil_gen_mls(parse_current, new_ast_node);
} else if (parse_current->data == CIL_KEY_SRC_INFO) {
- rc = cil_gen_src_info(parse_current, ast_node);
+ rc = cil_gen_src_info(parse_current, new_ast_node);
} else {
cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
rc = SEPOL_ERR;
}
if (rc == SEPOL_OK) {
- if (ast_current->cl_head == NULL) {
- if (ast_current->flavor == CIL_MACRO) {
- args->macro = ast_current;
- }
-
- if (ast_current->flavor == CIL_BOOLEANIF) {
- args->boolif = ast_current;
- }
-
- if (ast_current->flavor == CIL_TUNABLEIF) {
- args->tunif = ast_current;
- }
-
- if (ast_current->flavor == CIL_IN) {
- args->in = ast_current;
- }
-
- ast_current->cl_head = ast_node;
+ if (ast_parent->cl_head == NULL) {
+ ast_parent->cl_head = new_ast_node;
} else {
- ast_current->cl_tail->next = ast_node;
+ ast_parent->cl_tail->next = new_ast_node;
}
- ast_current->cl_tail = ast_node;
- ast_current = ast_node;
- args->ast = ast_current;
+ ast_parent->cl_tail = new_ast_node;
} else {
- cil_tree_node_destroy(&ast_node);
+ cil_tree_node_destroy(&new_ast_node);
+ new_ast_node = NULL;
}
-exit:
- return rc;
+ return new_ast_node;
}
-int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
+int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
{
+ struct cil_args_build *args = extra_args;
+ struct cil_tree_node *new_ast_node = NULL;
int rc = SEPOL_ERR;
- struct cil_tree_node *ast = NULL;
- struct cil_args_build *args = NULL;
- if (extra_args == NULL) {
- goto exit;
+ if (parse_current->parent->cl_head != parse_current) {
+ /* ignore anything that isn't following a parenthesis */
+ return SEPOL_OK;
+ } else if (parse_current->data == NULL) {
+ /* the only time parenthesis can immediately following parenthesis is if
+ * the parent is the root node */
+ if (parse_current->parent->parent == NULL) {
+ return SEPOL_OK;
+ } else {
+ cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
+ return SEPOL_ERR;
+ }
}
- args = extra_args;
- ast = args->ast;
+ rc = check_for_illegal_statement(parse_current, args);
+ if (rc != SEPOL_OK) {
+ return SEPOL_ERR;
+ }
- if (ast->flavor == CIL_ROOT) {
- rc = SEPOL_OK;
- goto exit;
+ new_ast_node = parse_statement(args->db, parse_current, args->ast);
+ if (!new_ast_node) {
+ return SEPOL_ERR;
}
- args->ast = ast->parent;
+ args->ast = new_ast_node;
- if (ast->flavor == CIL_MACRO) {
- args->macro = NULL;
+ if (parse_current->data != CIL_KEY_BLOCK &&
+ parse_current->data != CIL_KEY_IN &&
+ parse_current->data != CIL_KEY_TUNABLEIF &&
+ parse_current->data != CIL_KEY_BOOLEANIF &&
+ parse_current->data != CIL_KEY_CONDTRUE &&
+ parse_current->data != CIL_KEY_CONDFALSE &&
+ parse_current->data != CIL_KEY_MACRO &&
+ parse_current->data != CIL_KEY_OPTIONAL &&
+ parse_current->data != CIL_KEY_SRC_INFO) {
+ /* Skip anything that does not contain a list of policy statements */
+ *finished = CIL_TREE_SKIP_NEXT;
}
- if (ast->flavor == CIL_BOOLEANIF) {
- args->boolif = NULL;
+ return SEPOL_OK;
+}
+
+int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
+{
+ struct cil_args_build *args = extra_args;
+ struct cil_tree_node *ast = args->ast;
+
+ if (ast->flavor == CIL_TUNABLEIF) {
+ args->tunif = ast;
+ } else if (ast->flavor == CIL_IN) {
+ args->in = ast;
+ } else if (ast->flavor == CIL_MACRO) {
+ args->macro = ast;
+ } else if (ast->flavor == CIL_OPTIONAL) {
+ args->optional = ast;
+ } else if (ast->flavor == CIL_BOOLEANIF) {
+ args->boolif = ast;
}
+ return SEPOL_OK;
+}
+
+int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
+{
+ struct cil_args_build *args = extra_args;
+ struct cil_tree_node *ast = args->ast;
+
+ if (ast->flavor == CIL_ROOT) {
+ return SEPOL_OK;
+ }
+
+ args->ast = ast->parent;
+
if (ast->flavor == CIL_TUNABLEIF) {
args->tunif = NULL;
}
@@ -6541,6 +6563,27 @@ int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void
args->in = NULL;
}
+ if (ast->flavor == CIL_MACRO) {
+ args->macro = NULL;
+ }
+
+ if (ast->flavor == CIL_OPTIONAL) {
+ struct cil_tree_node *n = ast->parent;
+ args->optional = NULL;
+ /* Optionals can be nested */
+ while (n && n->flavor != CIL_ROOT) {
+ if (n->flavor == CIL_OPTIONAL) {
+ args->optional = n;
+ break;
+ }
+ n = n->parent;
+ }
+ }
+
+ if (ast->flavor == CIL_BOOLEANIF) {
+ args->boolif = NULL;
+ }
+
// At this point we no longer have any need for parse_current or any of its
// siblings; they have all been converted to the appropriate AST node. The
// full parse tree will get deleted elsewhere, but in an attempt to
@@ -6549,9 +6592,6 @@ int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void
cil_tree_children_destroy(parse_current->parent);
return SEPOL_OK;
-
-exit:
- return rc;
}
int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
@@ -6565,12 +6605,13 @@ int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct ci
extra_args.ast = ast;
extra_args.db = db;
- extra_args.macro = NULL;
- extra_args.boolif = NULL;
extra_args.tunif = NULL;
extra_args.in = NULL;
+ extra_args.macro = NULL;
+ extra_args.optional = NULL;
+ extra_args.boolif = NULL;
- rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args);
+ rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, __cil_build_ast_first_child_helper, __cil_build_ast_last_child_helper, &extra_args);
if (rc != SEPOL_OK) {
goto exit;
}
diff --git a/libsepol/cil/src/cil_build_ast.h b/libsepol/cil/src/cil_build_ast.h
index 8153e51e..fd9053ce 100644
--- a/libsepol/cil/src/cil_build_ast.h
+++ b/libsepol/cil/src/cil_build_ast.h
@@ -37,6 +37,8 @@
#include "cil_tree.h"
#include "cil_list.h"
+int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node);
+
int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor);
int cil_parse_to_list(struct cil_tree_node *parse_cl_head, struct cil_list *ast_cl, enum cil_flavor flavor);
diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c
index 67dd8528..a4ead9db 100644
--- a/libsepol/cil/src/cil_copy_ast.c
+++ b/libsepol/cil/src/cil_copy_ast.c
@@ -40,8 +40,10 @@
#include "cil_copy_ast.h"
#include "cil_build_ast.h"
#include "cil_strpool.h"
+#include "cil_verify.h"
struct cil_args_copy {
+ struct cil_tree_node *orig_dest;
struct cil_tree_node *dest;
struct cil_db *db;
};
@@ -102,12 +104,19 @@ int cil_copy_block(__attribute__((unused)) struct cil_db *db, void *data, void *
struct cil_symtab_datum *datum = NULL;
cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
+ if (datum != NULL) {
+ if (FLAVOR(datum) != CIL_BLOCK) {
+ cil_tree_log(NODE(orig), CIL_ERR, "Block %s being copied", key);
+ cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum)));
+ return SEPOL_ERR;
+ }
+ cil_tree_log(NODE(orig), CIL_WARN, "Block %s being copied", key);
+ cil_tree_log(NODE(datum), CIL_WARN, " Previously declared");
+ *copy = datum;
+ } else {
struct cil_block *new;
cil_block_init(&new);
*copy = new;
- } else {
- *copy = datum;;
}
return SEPOL_OK;
@@ -581,20 +590,12 @@ int cil_copy_roleallow(__attribute__((unused)) struct cil_db *db, void *data, vo
return SEPOL_OK;
}
-int cil_copy_type(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
+int cil_copy_type(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
- struct cil_type *orig = data;
- char *key = orig->datum.name;
- struct cil_symtab_datum *datum = NULL;
+ struct cil_type *new;
- cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
- struct cil_type *new;
- cil_type_init(&new);
- *copy = new;
- } else {
- *copy = datum;
- }
+ cil_type_init(&new);
+ *copy = new;
return SEPOL_OK;
}
@@ -613,20 +614,12 @@ int cil_copy_typepermissive(__attribute__((unused)) struct cil_db *db, void *dat
return SEPOL_OK;
}
-int cil_copy_typeattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
+int cil_copy_typeattribute(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
- struct cil_typeattribute *orig = data;
- char *key = orig->datum.name;
- struct cil_symtab_datum *datum = NULL;
+ struct cil_typeattribute *new;
- cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
- struct cil_typeattribute *new;
- cil_typeattribute_init(&new);
- *copy = new;
- } else {
- *copy = datum;
- }
+ cil_typeattribute_init(&new);
+ *copy = new;
return SEPOL_OK;
}
@@ -653,7 +646,6 @@ int cil_copy_expandtypeattribute(__attribute__((unused)) struct cil_db *db, void
struct cil_expandtypeattribute *orig = data;
struct cil_expandtypeattribute *new = NULL;
- fprintf(stderr, "%s %u\n", __func__, __LINE__);
cil_expandtypeattribute_init(&new);
if (orig->attr_strs != NULL) {
@@ -1512,78 +1504,33 @@ int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void *
struct cil_symtab_datum *datum = NULL;
cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
+ if (datum != NULL) {
+ if (FLAVOR(datum) != CIL_MACRO) {
+ cil_tree_log(NODE(orig), CIL_ERR, "Macro %s being copied", key);
+ cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum)));
+ return SEPOL_ERR;
+ }
+ cil_tree_log(NODE(orig), CIL_WARN, "Skipping macro %s", key);
+ cil_tree_log(NODE(datum), CIL_WARN, " Previously declared");
+ *copy = NULL;
+ } else {
struct cil_macro *new;
cil_macro_init(&new);
if (orig->params != NULL) {
cil_copy_list(orig->params, &new->params);
}
-
*copy = new;
-
- } else {
- struct cil_list_item *curr_orig = NULL;
- struct cil_list_item *curr_new = NULL;
- struct cil_param *param_orig = NULL;
- struct cil_param *param_new = NULL;
-
- if (((struct cil_macro*)datum)->params != NULL) {
- curr_new = ((struct cil_macro*)datum)->params->head;
- }
-
- if (orig->params != NULL) {
- curr_orig = orig->params->head;
- }
-
- if (curr_orig != NULL && curr_new != NULL) {
- while (curr_orig != NULL) {
- if (curr_new == NULL) {
- goto exit;
- }
-
- param_orig = (struct cil_param*)curr_orig->data;
- param_new = (struct cil_param*)curr_new->data;
- if (param_orig->str != param_new->str) {
- goto exit;
- } else if (param_orig->flavor != param_new->flavor) {
- goto exit;
- }
-
- curr_orig = curr_orig->next;
- curr_new = curr_new->next;
- }
-
- if (curr_new != NULL) {
- goto exit;
- }
- } else if (!(curr_orig == NULL && curr_new == NULL)) {
- goto exit;
- }
-
- *copy = datum;
}
return SEPOL_OK;
-
-exit:
- cil_log(CIL_INFO, "cil_copy_macro: macro cannot be redefined\n");
- return SEPOL_ERR;
}
-int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
+int cil_copy_optional(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
- struct cil_optional *orig = data;
- char *key = orig->datum.name;
- struct cil_symtab_datum *datum = NULL;
+ struct cil_optional *new;
- cil_symtab_get_datum(symtab, key, &datum);
- if (datum == NULL) {
- struct cil_optional *new;
- cil_optional_init(&new);
- *copy = new;
- } else {
- *copy = datum;
- }
+ cil_optional_init(&new);
+ *copy = new;
return SEPOL_OK;
}
@@ -1741,7 +1688,8 @@ int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, voi
cil_src_info_init(&new);
- new->is_cil = orig->is_cil;
+ new->kind = orig->kind;
+ new->hll_line = orig->hll_line;
new->path = orig->path;
*copy = new;
@@ -1749,7 +1697,7 @@ int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, voi
return SEPOL_OK;
}
-int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) uint32_t *finished, void *extra_args)
+int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished, void *extra_args)
{
int rc = SEPOL_ERR;
struct cil_tree_node *parent = NULL;
@@ -1757,7 +1705,6 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
struct cil_db *db = NULL;
struct cil_args_copy *args = NULL;
struct cil_tree_node *namespace = NULL;
- struct cil_param *param = NULL;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
symtab_t *symtab = NULL;
void *data = NULL;
@@ -1778,6 +1725,12 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
copy_func = &cil_copy_block;
break;
case CIL_BLOCKABSTRACT:
+ if (args->orig_dest->flavor == CIL_BLOCKINHERIT) {
+ /* When inheriting a block, don't copy any blockabstract
+ * statements. Inheriting a block from a block that was
+ * just inherited never worked. */
+ return SEPOL_OK;
+ }
copy_func = &cil_copy_blockabstract;
break;
case CIL_BLOCKINHERIT:
@@ -2055,15 +2008,33 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
rc = (*copy_func)(db, orig->data, &data, symtab);
if (rc == SEPOL_OK) {
+ if (orig->flavor == CIL_MACRO && data == NULL) {
+ /* Skipping macro re-declaration */
+ if (args->orig_dest->flavor != CIL_BLOCKINHERIT) {
+ cil_log(CIL_ERR, " Re-declaration of macro is only allowed when inheriting a block\n");
+ return SEPOL_ERR;
+ }
+ *finished = CIL_TREE_SKIP_HEAD;
+ return SEPOL_OK;
+ }
+
cil_tree_node_init(&new);
new->parent = parent;
new->line = orig->line;
- new->hll_line = orig->hll_line;
+ new->hll_offset = orig->hll_offset;
new->flavor = orig->flavor;
new->data = data;
- if (orig->flavor >= CIL_MIN_DECLARATIVE) {
+ if (orig->flavor == CIL_BLOCK && DATUM(data)->nodes->head != NULL) {
+ /* Duplicate block */
+ if (args->orig_dest->flavor != CIL_BLOCKINHERIT) {
+ cil_log(CIL_ERR, " Re-declaration of block is only allowed when inheriting a block\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ cil_list_append(DATUM(new->data)->nodes, CIL_NODE, new);
+ } else if (orig->flavor >= CIL_MIN_DECLARATIVE) {
/* Check the flavor of data if was found in the destination symtab */
if (DATUM(data)->nodes->head && FLAVOR(data) != orig->flavor) {
cil_tree_log(orig, CIL_ERR, "Incompatible flavor when trying to copy %s", DATUM(data)->name);
@@ -2072,7 +2043,18 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
rc = SEPOL_ERR;
goto exit;
}
- rc = cil_symtab_insert(symtab, ((struct cil_symtab_datum*)orig->data)->name, ((struct cil_symtab_datum*)data), new);
+
+ rc = cil_add_decl_to_symtab(db, symtab, DATUM(orig->data)->name, DATUM(data), new);
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ cil_symtab_datum_destroy(data);
+ free(data);
+ data = NULL;
+ rc = SEPOL_OK;
+ } else {
+ goto exit;
+ }
+ }
namespace = new;
while (namespace->flavor != CIL_MACRO && namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_ROOT) {
@@ -2080,21 +2062,9 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
}
if (namespace->flavor == CIL_MACRO) {
- struct cil_macro *macro = namespace->data;
- struct cil_list *param_list = macro->params;
- if (param_list != NULL) {
- struct cil_list_item *item;
- cil_list_for_each(item, param_list) {
- param = item->data;
- if (param->flavor == new->flavor) {
- if (param->str == ((struct cil_symtab_datum*)new->data)->name) {
- cil_tree_log(orig, CIL_ERR, "%s %s shadows a macro parameter", cil_node_to_string(new), ((struct cil_symtab_datum*)orig->data)->name);
- cil_tree_log(namespace, CIL_ERR, "Note: macro declaration");
- rc = SEPOL_ERR;
- goto exit;
- }
- }
- }
+ rc = cil_verify_decl_does_not_shadow_macro_parameter(namespace->data, orig, DATUM(orig->data)->name);
+ if (rc != SEPOL_OK) {
+ goto exit;
}
}
}
@@ -2123,6 +2093,7 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
args->dest = new;
}
} else {
+ cil_tree_log(orig, CIL_ERR, "Problem copying %s node", cil_node_to_string(orig));
goto exit;
}
@@ -2155,12 +2126,13 @@ int cil_copy_ast(struct cil_db *db, struct cil_tree_node *orig, struct cil_tree_
int rc = SEPOL_ERR;
struct cil_args_copy extra_args;
+ extra_args.orig_dest = dest;
extra_args.dest = dest;
extra_args.db = db;
rc = cil_tree_walk(orig, __cil_copy_node_helper, NULL, __cil_copy_last_child_helper, &extra_args);
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc);
+ cil_tree_log(dest, CIL_ERR, "Failed to copy %s to %s", cil_node_to_string(orig), cil_node_to_string(dest));
goto exit;
}
diff --git a/libsepol/cil/src/cil_find.c b/libsepol/cil/src/cil_find.c
index 41342424..3898725f 100644
--- a/libsepol/cil/src/cil_find.c
+++ b/libsepol/cil/src/cil_find.c
@@ -30,6 +30,7 @@
#include <sepol/policydb/ebitmap.h>
#include "cil_internal.h"
+#include "cil_find.h"
#include "cil_flavor.h"
#include "cil_list.h"
#include "cil_log.h"
@@ -44,8 +45,8 @@ struct cil_args_find {
static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_datum *d2)
{
- enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor;
- enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor;
+ enum cil_flavor f1 = FLAVOR(d1);
+ enum cil_flavor f2 = FLAVOR(d2);
if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
struct cil_type *t1 = (struct cil_type *)d1;
@@ -81,8 +82,8 @@ static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_dat
static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2)
{
int rc = SEPOL_OK;
- enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor;
- enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor;
+ enum cil_flavor f1 = FLAVOR(d1);
+ enum cil_flavor f2 = FLAVOR(d2);
if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
struct cil_type *t1 = (struct cil_type *)d1;
@@ -118,7 +119,7 @@ static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, str
static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
{
int rc;
- struct cil_tree_node *n1 = s1->nodes->head->data;
+ struct cil_tree_node *n1 = NODE(s1);
if (n1->flavor != CIL_TYPEATTRIBUTE) {
rc = cil_type_match_any(s1, t2);
} else {
diff --git a/libsepol/cil/src/cil_fqn.c b/libsepol/cil/src/cil_fqn.c
index 2e76f873..46db069b 100644
--- a/libsepol/cil/src/cil_fqn.c
+++ b/libsepol/cil/src/cil_fqn.c
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <string.h>
+#include "cil_fqn.h"
#include "cil_internal.h"
#include "cil_log.h"
#include "cil_strpool.h"
@@ -77,12 +78,13 @@ static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, has
struct cil_tree_node *node = NODE(datum);
int i;
int rc = SEPOL_OK;
+ int newlen;
if (node->flavor != CIL_BLOCK) {
goto exit;
}
- int newlen = fqn_args->len + strlen(datum->name) + 1;
+ newlen = fqn_args->len + strlen(datum->name) + 1;
if (newlen >= CIL_MAX_NAME_LENGTH) {
cil_log(CIL_INFO, "Fully qualified name for block %s is too long\n", datum->name);
rc = SEPOL_ERR;
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index 9bdcbdd0..a7604762 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -48,16 +48,19 @@
#define CIL_MAX_NAME_LENGTH 2048
+#define CIL_DEGENERATE_INHERITANCE_DEPTH 10UL
+#define CIL_DEGENERATE_INHERITANCE_MINIMUM (0x01 << CIL_DEGENERATE_INHERITANCE_DEPTH)
+#define CIL_DEGENERATE_INHERITANCE_GROWTH 10UL
enum cil_pass {
CIL_PASS_INIT = 0,
CIL_PASS_TIF,
- CIL_PASS_IN,
+ CIL_PASS_IN_BEFORE,
CIL_PASS_BLKIN_LINK,
CIL_PASS_BLKIN_COPY,
CIL_PASS_BLKABS,
- CIL_PASS_MACRO,
+ CIL_PASS_IN_AFTER,
CIL_PASS_CALL1,
CIL_PASS_CALL2,
CIL_PASS_ALIAS1,
@@ -156,6 +159,8 @@ extern char *CIL_KEY_HANDLEUNKNOWN_DENY;
extern char *CIL_KEY_HANDLEUNKNOWN_REJECT;
extern char *CIL_KEY_MACRO;
extern char *CIL_KEY_IN;
+extern char *CIL_KEY_IN_BEFORE;
+extern char *CIL_KEY_IN_AFTER;
extern char *CIL_KEY_MLS;
extern char *CIL_KEY_DEFAULTRANGE;
extern char *CIL_KEY_BLOCKINHERIT;
@@ -234,7 +239,9 @@ extern char *CIL_KEY_IOCTL;
extern char *CIL_KEY_UNORDERED;
extern char *CIL_KEY_SRC_INFO;
extern char *CIL_KEY_SRC_CIL;
-extern char *CIL_KEY_SRC_HLL;
+extern char *CIL_KEY_SRC_HLL_LMS;
+extern char *CIL_KEY_SRC_HLL_LMX;
+extern char *CIL_KEY_SRC_HLL_LME;
/*
Symbol Table Array Indices
@@ -273,7 +280,7 @@ enum cil_sym_array {
CIL_SYM_ARRAY_NUM
};
-extern int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM];
+extern const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM];
#define CIL_CLASS_SYM_SIZE 256
#define CIL_PERMS_PER_CLASS (sizeof(sepol_access_vector_t) * 8)
@@ -319,6 +326,7 @@ struct cil_db {
int handle_unknown;
int mls;
int multiple_decls;
+ int qualified_names;
int target_platform;
int policy_version;
};
@@ -352,12 +360,12 @@ struct cil_blockabstract {
struct cil_in {
symtab_t symtab[CIL_SYM_NUM];
+ int is_after;
char *block_str;
};
struct cil_optional {
struct cil_symtab_datum datum;
- int enabled;
};
struct cil_perm {
@@ -722,14 +730,14 @@ struct cil_context {
};
enum cil_filecon_types {
- CIL_FILECON_FILE = 1,
+ CIL_FILECON_ANY = 0,
+ CIL_FILECON_FILE,
CIL_FILECON_DIR,
CIL_FILECON_CHAR,
CIL_FILECON_BLOCK,
CIL_FILECON_SOCKET,
CIL_FILECON_PIPE,
CIL_FILECON_SYMLINK,
- CIL_FILECON_ANY
};
struct cil_filecon {
@@ -783,6 +791,7 @@ struct cil_ipaddr {
struct cil_genfscon {
char *fs_str;
char *path_str;
+ enum cil_filecon_types file_type;
char *context_str;
struct cil_context *context;
};
@@ -961,7 +970,8 @@ struct cil_mls {
};
struct cil_src_info {
- int is_cil;
+ char *kind;
+ uint32_t hll_line;
char *path;
};
@@ -980,10 +990,12 @@ int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size);
int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size);
int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size);
-void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM]);
+void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM]);
void cil_symtab_array_destroy(symtab_t symtab[]);
void cil_destroy_ast_symtabs(struct cil_tree_node *root);
int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_sym_index sym_index);
+int cil_string_to_uint32(const char *string, uint32_t *value, int base);
+int cil_string_to_uint64(const char *string, uint64_t *value, int base);
void cil_sort_init(struct cil_sort **sort);
void cil_sort_destroy(struct cil_sort **sort);
diff --git a/libsepol/cil/src/cil_lexer.l b/libsepol/cil/src/cil_lexer.l
index e28c33ec..8bf2b6e7 100644
--- a/libsepol/cil/src/cil_lexer.l
+++ b/libsepol/cil/src/cil_lexer.l
@@ -49,7 +49,7 @@ spec_char [\[\]\.\@\=\/\*\-\_\$\%\+\-\!\|\&\^\:\~\`\#\{\}\'\<\>\?\,]
symbol ({digit}|{alpha}|{spec_char})+
white [ \t]
newline [\n\r]
-qstring \"[^"\n]*\"
+qstring \"[^"\n\0]*\"
hll_lm ^;;\*
comment ;
diff --git a/libsepol/cil/src/cil_list.c b/libsepol/cil/src/cil_list.c
index 4e7843cb..8a426f1f 100644
--- a/libsepol/cil/src/cil_list.c
+++ b/libsepol/cil/src/cil_list.c
@@ -55,15 +55,16 @@ void cil_list_init(struct cil_list **list, enum cil_flavor flavor)
void cil_list_destroy(struct cil_list **list, unsigned destroy_data)
{
+ struct cil_list_item *item;
+
if (*list == NULL) {
return;
}
- struct cil_list_item *item = (*list)->head;
- struct cil_list_item *next = NULL;
+ item = (*list)->head;
while (item != NULL)
{
- next = item->next;
+ struct cil_list_item *next = item->next;
if (item->flavor == CIL_LIST) {
cil_list_destroy((struct cil_list**)&(item->data), destroy_data);
free(item);
diff --git a/libsepol/cil/src/cil_log.c b/libsepol/cil/src/cil_log.c
index b222b155..a296929b 100644
--- a/libsepol/cil/src/cil_log.c
+++ b/libsepol/cil/src/cil_log.c
@@ -37,14 +37,14 @@
static enum cil_log_level cil_log_level = CIL_ERR;
-void cil_default_log_handler(__attribute__((unused)) int lvl, char *msg)
+void cil_default_log_handler(__attribute__((unused)) int lvl, const char *msg)
{
fprintf(stderr, "%s", msg);
}
-void (*cil_log_handler)(int lvl, char *msg) = &cil_default_log_handler;
+void (*cil_log_handler)(int lvl, const char *msg) = &cil_default_log_handler;
-void cil_set_log_handler(void (*handler)(int lvl, char *msg))
+void cil_set_log_handler(void (*handler)(int lvl, const char *msg))
{
cil_log_handler = handler;
}
@@ -70,3 +70,8 @@ void cil_set_log_level(enum cil_log_level lvl)
{
cil_log_level = lvl;
}
+
+enum cil_log_level cil_get_log_level(void)
+{
+ return cil_log_level;
+}
diff --git a/libsepol/cil/src/cil_log.h b/libsepol/cil/src/cil_log.h
index 541569be..442781fb 100644
--- a/libsepol/cil/src/cil_log.h
+++ b/libsepol/cil/src/cil_log.h
@@ -38,4 +38,6 @@
__attribute__ ((format(printf, 2, 0))) void cil_vlog(enum cil_log_level lvl, const char *msg, va_list args);
__attribute__ ((format(printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...);
+enum cil_log_level cil_get_log_level(void);
+
#endif // CIL_LOG_H_
diff --git a/libsepol/cil/src/cil_mem.c b/libsepol/cil/src/cil_mem.c
index f73021b5..8e4a1d24 100644
--- a/libsepol/cil/src/cil_mem.c
+++ b/libsepol/cil/src/cil_mem.c
@@ -33,6 +33,7 @@
#include <string.h>
#include "cil_log.h"
+#include "cil_mem.h"
void *cil_malloc(size_t size)
{
diff --git a/libsepol/cil/src/cil_parser.c b/libsepol/cil/src/cil_parser.c
index 585ea770..5375d49a 100644
--- a/libsepol/cil/src/cil_parser.c
+++ b/libsepol/cil/src/cil_parser.c
@@ -38,53 +38,48 @@
#include "cil_mem.h"
#include "cil_tree.h"
#include "cil_lexer.h"
+#include "cil_parser.h"
#include "cil_strpool.h"
#include "cil_stack.h"
-char *CIL_KEY_HLL_LMS;
-char *CIL_KEY_HLL_LMX;
-char *CIL_KEY_HLL_LME;
+#define CIL_PARSER_MAX_EXPR_DEPTH (0x1 << 12)
struct hll_info {
- int hll_lineno;
- int hll_expand;
+ uint32_t hll_offset;
+ uint32_t hll_expand;
};
-static void push_hll_info(struct cil_stack *stack, int hll_lineno, int hll_expand)
+static void push_hll_info(struct cil_stack *stack, uint32_t hll_offset, uint32_t hll_expand)
{
struct hll_info *new = cil_malloc(sizeof(*new));
- new->hll_lineno = hll_lineno;
+ new->hll_offset = hll_offset;
new->hll_expand = hll_expand;
cil_stack_push(stack, CIL_NONE, new);
}
-static void pop_hll_info(struct cil_stack *stack, int *hll_lineno, int *hll_expand)
+static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_offset, uint32_t *hll_expand)
{
struct cil_stack_item *curr = cil_stack_pop(stack);
- struct cil_stack_item *prev = cil_stack_peek(stack);
- struct hll_info *old;
+ struct hll_info *info;
- free(curr->data);
-
- if (!prev) {
- *hll_lineno = -1;
- *hll_expand = -1;
- } else {
- old = prev->data;
- *hll_lineno = old->hll_lineno;
- *hll_expand = old->hll_expand;
+ if (!curr) {
+ return;
}
+ info = curr->data;
+ *hll_expand = info->hll_expand;
+ *hll_offset = info->hll_offset;
+ free(curr->data);
}
-static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, int line, int hll_line, void *value)
+static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_offset, void *value)
{
cil_tree_node_init(node);
(*node)->parent = current;
(*node)->flavor = CIL_NODE;
(*node)->line = line;
- (*node)->hll_line = hll_line;
+ (*node)->hll_offset = hll_offset;
(*node)->data = value;
}
@@ -98,55 +93,67 @@ static void insert_node(struct cil_tree_node *node, struct cil_tree_node *curren
current->cl_tail = node;
}
-static int add_hll_linemark(struct cil_tree_node **current, int *hll_lineno, int *hll_expand, struct cil_stack *stack, char *path)
+static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_offset, uint32_t *hll_expand, struct cil_stack *stack, char *path)
{
char *hll_type;
struct cil_tree_node *node;
struct token tok;
- char *hll_file;
- char *end = NULL;
+ uint32_t prev_hll_expand, prev_hll_offset;
cil_lexer_next(&tok);
+ if (tok.type != SYMBOL) {
+ cil_log(CIL_ERR, "Invalid line mark syntax\n");
+ goto exit;
+ }
hll_type = cil_strpool_add(tok.value);
- if (hll_type == CIL_KEY_HLL_LME) {
+ if (hll_type != CIL_KEY_SRC_HLL_LME && hll_type != CIL_KEY_SRC_HLL_LMS && hll_type != CIL_KEY_SRC_HLL_LMX) {
+ cil_log(CIL_ERR, "Invalid line mark syntax\n");
+ goto exit;
+ }
+ if (hll_type == CIL_KEY_SRC_HLL_LME) {
if (cil_stack_is_empty(stack)) {
cil_log(CIL_ERR, "Line mark end without start\n");
goto exit;
}
- pop_hll_info(stack, hll_lineno, hll_expand);
+ prev_hll_expand = *hll_expand;
+ prev_hll_offset = *hll_offset;
+ pop_hll_info(stack, hll_offset, hll_expand);
+ if (!*hll_expand) {
+ /* This is needed if not going back to an lmx section. */
+ *hll_offset = prev_hll_offset;
+ }
+ if (prev_hll_expand && !*hll_expand) {
+ /* This is needed to count the lme at the end of an lmx section
+ * within an lms section (or within no hll section).
+ */
+ (*hll_offset)++;
+ }
*current = (*current)->parent;
} else {
- create_node(&node, *current, tok.line, *hll_lineno, NULL);
+ push_hll_info(stack, *hll_offset, *hll_expand);
+ if (cil_stack_number_of_items(stack) > CIL_PARSER_MAX_EXPR_DEPTH) {
+ cil_log(CIL_ERR, "Number of active line marks exceeds limit of %d\n", CIL_PARSER_MAX_EXPR_DEPTH);
+ goto exit;
+ }
+
+ create_node(&node, *current, tok.line, *hll_offset, NULL);
insert_node(node, *current);
*current = node;
- create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_INFO);
+ create_node(&node, *current, tok.line, *hll_offset, CIL_KEY_SRC_INFO);
insert_node(node, *current);
- create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_HLL);
+ create_node(&node, *current, tok.line, *hll_offset, hll_type);
insert_node(node, *current);
- if (hll_type == CIL_KEY_HLL_LMS) {
- *hll_expand = 0;
- } else if (hll_type == CIL_KEY_HLL_LMX) {
- *hll_expand = 1;
- } else {
- cil_log(CIL_ERR, "Invalid line mark syntax\n");
- goto exit;
- }
-
cil_lexer_next(&tok);
if (tok.type != SYMBOL) {
cil_log(CIL_ERR, "Invalid line mark syntax\n");
goto exit;
}
- *hll_lineno = strtol(tok.value, &end, 10);
- if (errno == ERANGE || *end != '\0') {
- cil_log(CIL_ERR, "Problem parsing line number for line mark\n");
- goto exit;
- }
- push_hll_info(stack, *hll_lineno, *hll_expand);
+ create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value));
+ insert_node(node, *current);
cil_lexer_next(&tok);
if (tok.type != SYMBOL && tok.type != QSTRING) {
@@ -159,10 +166,10 @@ static int add_hll_linemark(struct cil_tree_node **current, int *hll_lineno, int
tok.value = tok.value+1;
}
- hll_file = cil_strpool_add(tok.value);
-
- create_node(&node, *current, tok.line, *hll_lineno, hll_file);
+ create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value));
insert_node(node, *current);
+
+ *hll_expand = (hll_type == CIL_KEY_SRC_HLL_LMX) ? 1 : 0;
}
cil_lexer_next(&tok);
@@ -171,10 +178,15 @@ static int add_hll_linemark(struct cil_tree_node **current, int *hll_lineno, int
goto exit;
}
+ if (!*hll_expand) {
+ /* Need to increment because of the NEWLINE */
+ (*hll_offset)++;
+ }
+
return SEPOL_OK;
exit:
- cil_log(CIL_ERR, "Problem with high-level line mark at line %d of %s\n", tok.line, path);
+ cil_log(CIL_ERR, "Problem with high-level line mark at line %u of %s\n", tok.line, path);
return SEPOL_ERR;
}
@@ -192,11 +204,14 @@ static void add_cil_path(struct cil_tree_node **current, char *path)
create_node(&node, *current, 0, 0, CIL_KEY_SRC_CIL);
insert_node(node, *current);
+ create_node(&node, *current, 0, 0, cil_strpool_add("1"));
+ insert_node(node, *current);
+
create_node(&node, *current, 0, 0, path);
insert_node(node, *current);
}
-int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse_tree)
+int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree **parse_tree)
{
int paren_count = 0;
@@ -206,15 +221,11 @@ int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse
struct cil_tree_node *current = NULL;
char *path = cil_strpool_add(_path);
struct cil_stack *stack;
- int hll_lineno = -1;
- int hll_expand = -1;
+ uint32_t hll_offset = 1;
+ uint32_t hll_expand = 0;
struct token tok;
int rc = SEPOL_OK;
- CIL_KEY_HLL_LMS = cil_strpool_add("lms");
- CIL_KEY_HLL_LMX = cil_strpool_add("lmx");
- CIL_KEY_HLL_LME = cil_strpool_add("lme");
-
cil_stack_init(&stack);
cil_lexer_setup(buffer, size);
@@ -228,15 +239,18 @@ int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse
cil_lexer_next(&tok);
switch (tok.type) {
case HLL_LINEMARK:
- rc = add_hll_linemark(&current, &hll_lineno, &hll_expand, stack, path);
+ rc = add_hll_linemark(&current, &hll_offset, &hll_expand, stack, path);
if (rc != SEPOL_OK) {
goto exit;
}
break;
case OPAREN:
paren_count++;
-
- create_node(&node, current, tok.line, hll_lineno, NULL);
+ if (paren_count > CIL_PARSER_MAX_EXPR_DEPTH) {
+ cil_log(CIL_ERR, "Number of open parenthesis exceeds limit of %d at line %d of %s\n", CIL_PARSER_MAX_EXPR_DEPTH, tok.line, path);
+ goto exit;
+ }
+ create_node(&node, current, tok.line, hll_offset, NULL);
insert_node(node, current);
current = node;
break;
@@ -258,12 +272,12 @@ int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse
goto exit;
}
- create_node(&node, current, tok.line, hll_lineno, cil_strpool_add(tok.value));
+ create_node(&node, current, tok.line, hll_offset, cil_strpool_add(tok.value));
insert_node(node, current);
break;
case NEWLINE :
if (!hll_expand) {
- hll_lineno++;
+ hll_offset++;
}
break;
case COMMENT:
@@ -271,7 +285,7 @@ int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse
cil_lexer_next(&tok);
}
if (!hll_expand) {
- hll_lineno++;
+ hll_offset++;
}
if (tok.type != END_OF_FILE) {
break;
@@ -308,8 +322,9 @@ int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse
exit:
while (!cil_stack_is_empty(stack)) {
- pop_hll_info(stack, &hll_lineno, &hll_expand);
+ pop_hll_info(stack, &hll_offset, &hll_expand);
}
+ cil_lexer_destroy();
cil_stack_destroy(&stack);
return SEPOL_ERR;
diff --git a/libsepol/cil/src/cil_parser.h b/libsepol/cil/src/cil_parser.h
index 02ecb784..1cec6394 100644
--- a/libsepol/cil/src/cil_parser.h
+++ b/libsepol/cil/src/cil_parser.h
@@ -32,6 +32,6 @@
#include "cil_tree.h"
-int cil_parser(char *path, char *buffer, uint32_t size, struct cil_tree **parse_tree);
+int cil_parser(const char *path, char *buffer, uint32_t size, struct cil_tree **parse_tree);
#endif /* CIL_PARSER_H_ */
diff --git a/libsepol/cil/src/cil_policy.c b/libsepol/cil/src/cil_policy.c
index 06d7d74e..7c543c47 100644
--- a/libsepol/cil/src/cil_policy.c
+++ b/libsepol/cil/src/cil_policy.c
@@ -41,6 +41,7 @@
#include "cil_flavor.h"
#include "cil_find.h"
#include "cil_mem.h"
+#include "cil_policy.h"
#include "cil_tree.h"
#include "cil_list.h"
#include "cil_symtab.h"
@@ -284,7 +285,7 @@ static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first)
struct cil_list_item *i1 = expr->head;
if (i1->flavor == CIL_OP) {
- enum cil_flavor op = (enum cil_flavor)i1->data;
+ enum cil_flavor op = (enum cil_flavor)(uintptr_t)i1->data;
fprintf(out, "(");
switch (op) {
case CIL_NOT:
@@ -384,7 +385,7 @@ static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_ite
static size_t __cil_cons_leaf_op_len(struct cil_list_item *op)
{
- enum cil_flavor flavor = (enum cil_flavor)op->data;
+ enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data;
size_t len;
switch (flavor) {
@@ -419,7 +420,7 @@ static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr)
i1 = cons_expr->head;
- op = (enum cil_flavor)i1->data;
+ op = (enum cil_flavor)(uintptr_t)i1->data;
switch (op) {
case CIL_NOT:
len = 6; /* "(not )" */
@@ -471,7 +472,7 @@ static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_lis
size_t o_len;
if (flavor == CIL_CONS_OPERAND) {
- enum cil_flavor o_flavor = (enum cil_flavor)operand->data;
+ enum cil_flavor o_flavor = (enum cil_flavor)(uintptr_t)operand->data;
switch (o_flavor) {
case CIL_CONS_U1:
o_str = "u1";
@@ -554,7 +555,7 @@ static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_lis
static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new)
{
- enum cil_flavor flavor = (enum cil_flavor)op->data;
+ enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data;
const char *op_str;
size_t len;
@@ -598,7 +599,7 @@ static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_
i1 = cons_expr->head;
- op = (enum cil_flavor)i1->data;
+ op = (enum cil_flavor)(uintptr_t)i1->data;
switch (op) {
case CIL_NOT:
*new++ = '(';
@@ -1659,9 +1660,11 @@ static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls
cil_list_for_each(i1, sids) {
sid = i1->data;
- fprintf(out, "sid %s ", sid->datum.fqn);
- cil_context_to_policy(out, sid->context, mls);
- fprintf(out,"\n");
+ if (sid->context) {
+ fprintf(out, "sid %s ", sid->datum.fqn);
+ cil_context_to_policy(out, sid->context, mls);
+ fprintf(out,"\n");
+ }
}
}
diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
index a0cadfde..09c02af9 100644
--- a/libsepol/cil/src/cil_post.c
+++ b/libsepol/cil/src/cil_post.c
@@ -27,6 +27,7 @@
* either expressed or implied, of Tresys Technology, LLC.
*/
+#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -50,6 +51,12 @@
#define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/src/module_to_cil.c */
#define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/src/module_to_cil.c */
+struct fc_data {
+ unsigned int meta;
+ size_t stem_len;
+ size_t str_len;
+};
+
static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
@@ -156,9 +163,9 @@ static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
return CIL_TRUE;
}
-void cil_post_fc_fill_data(struct fc_data *fc, char *path)
+static void cil_post_fc_fill_data(struct fc_data *fc, const char *path)
{
- int c = 0;
+ size_t c = 0;
fc->meta = 0;
fc->stem_len = 0;
fc->str_len = 0;
@@ -179,6 +186,13 @@ void cil_post_fc_fill_data(struct fc_data *fc, char *path)
break;
case '\\':
c++;
+ if (path[c] == '\0') {
+ if (!fc->meta) {
+ fc->stem_len++;
+ }
+ fc->str_len++;
+ return;
+ }
/* FALLTHRU */
default:
if (!fc->meta) {
@@ -199,8 +213,8 @@ int cil_post_filecon_compare(const void *a, const void *b)
struct fc_data *a_data = cil_malloc(sizeof(*a_data));
struct fc_data *b_data = cil_malloc(sizeof(*b_data));
char *a_path = cil_malloc(strlen(a_filecon->path_str) + 1);
- a_path[0] = '\0';
char *b_path = cil_malloc(strlen(b_filecon->path_str) + 1);
+ a_path[0] = '\0';
b_path[0] = '\0';
strcat(a_path, a_filecon->path_str);
strcat(b_path, b_filecon->path_str);
@@ -1301,7 +1315,7 @@ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max,
flavor = expr->flavor;
if (curr->flavor == CIL_OP) {
- enum cil_flavor op = (enum cil_flavor)curr->data;
+ enum cil_flavor op = (enum cil_flavor)(uintptr_t)curr->data;
if (op == CIL_ALL) {
ebitmap_init(&b1); /* all zeros */
@@ -1480,9 +1494,13 @@ static void __mark_neverallow_attrs(struct cil_list *expr_list)
{
struct cil_list_item *curr;
+ if (!expr_list) {
+ return;
+ }
+
cil_list_for_each(curr, expr_list) {
if (curr->flavor == CIL_DATUM) {
- if (NODE(curr->data)->flavor == CIL_TYPEATTRIBUTE) {
+ if (FLAVOR(curr->data) == CIL_TYPEATTRIBUTE) {
struct cil_typeattribute *attr = curr->data;
if (strstr(DATUM(attr)->name, TYPEATTR_INFIX)) {
__mark_neverallow_attrs(attr->expr_list);
@@ -2123,6 +2141,10 @@ static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db
}
} else { /* MAP */
struct cil_list_item *i = NULL;
+ rc = __evaluate_classperms(cp, db);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
cil_list_for_each(i, cp->perms) {
struct cil_perm *cmp = i->data;
rc = __evaluate_classperms_list(cmp->classperms, db);
@@ -2258,8 +2280,10 @@ static int __cil_post_report_conflict(struct cil_tree_node *node, uint32_t *fini
static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar)(const void *, const void *), int (*concompar)(const void *, const void *), struct cil_db *db, enum cil_flavor flavor, const char *flavor_str)
{
uint32_t count = sort->count;
- uint32_t i, j = 0, removed = 0;
+ uint32_t i = 0, j, removed = 0;
+ int conflicting = 0;
int rc = SEPOL_OK;
+ enum cil_log_level log_level = cil_get_log_level();
if (count < 2) {
return SEPOL_OK;
@@ -2267,36 +2291,43 @@ static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar)
qsort(sort->array, sort->count, sizeof(sort->array), compar);
- for (i=1; i<count; i++) {
+ for (j=1; j<count; j++) {
if (compar(&sort->array[i], &sort->array[j]) != 0) {
- j++;
+ i++;
+ if (conflicting >= 4) {
+ /* 2 rules were written when conflicting == 1 */
+ cil_log(CIL_WARN, " Only first 4 of %d conflicting rules shown\n", conflicting);
+ }
+ conflicting = 0;
} else {
removed++;
- if (!db->multiple_decls ||
- concompar(&sort->array[i], &sort->array[j]) != 0) {
- struct cil_list_item li;
- int rc2;
- cil_log(CIL_WARN, "Found conflicting %s rules\n",
- flavor_str);
- rc = SEPOL_ERR;
- li.flavor = flavor;
- li.data = sort->array[i];
- rc2 = cil_tree_walk(db->ast->root,
- __cil_post_report_conflict,
- NULL, NULL, &li);
- if (rc2 != SEPOL_OK) goto exit;
- li.data = sort->array[j];
- rc2 = cil_tree_walk(db->ast->root,
- __cil_post_report_conflict,
- NULL, NULL, &li);
- if (rc2 != SEPOL_OK) goto exit;
+ if (!db->multiple_decls || concompar(&sort->array[i], &sort->array[j]) != 0) {
+ conflicting++;
+ if (log_level >= CIL_WARN) {
+ struct cil_list_item li;
+ int rc2;
+ li.flavor = flavor;
+ if (conflicting == 1) {
+ cil_log(CIL_WARN, "Found conflicting %s rules\n", flavor_str);
+ rc = SEPOL_ERR;
+ li.data = sort->array[i];
+ rc2 = cil_tree_walk(db->ast->root, __cil_post_report_conflict,
+ NULL, NULL, &li);
+ if (rc2 != SEPOL_OK) goto exit;
+ }
+ if (conflicting < 4 || log_level > CIL_WARN) {
+ li.data = sort->array[j];
+ rc2 = cil_tree_walk(db->ast->root, __cil_post_report_conflict,
+ NULL, NULL, &li);
+ if (rc2 != SEPOL_OK) goto exit;
+ }
+ }
}
}
- if (i != j) {
- sort->array[j] = sort->array[i];
+ if (i != j && !conflicting) {
+ sort->array[i] = sort->array[j];
}
}
-
sort->count = count - removed;
exit:
diff --git a/libsepol/cil/src/cil_post.h b/libsepol/cil/src/cil_post.h
index 3d541548..b1d2206f 100644
--- a/libsepol/cil/src/cil_post.h
+++ b/libsepol/cil/src/cil_post.h
@@ -30,13 +30,6 @@
#ifndef CIL_POST_H_
#define CIL_POST_H_
-struct fc_data {
- int meta;
- int stem_len;
- int str_len;
-};
-
-void cil_post_fc_fill_data(struct fc_data *fc, char *path);
int cil_post_filecon_compare(const void *a, const void *b);
int cil_post_ibpkeycon_compare(const void *a, const void *b);
int cil_post_portcon_compare(const void *a, const void *b);
diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c
index 43e6b88e..0ba075c8 100644
--- a/libsepol/cil/src/cil_reset_ast.c
+++ b/libsepol/cil/src/cil_reset_ast.c
@@ -2,6 +2,7 @@
#include "cil_internal.h"
#include "cil_log.h"
#include "cil_list.h"
+#include "cil_reset_ast.h"
#include "cil_symtab.h"
static inline void cil_reset_classperms_list(struct cil_list *cp_list);
@@ -22,11 +23,12 @@ static int __class_reset_perm_values(__attribute__((unused)) hashtab_key_t k, ha
static void cil_reset_class(struct cil_class *class)
{
if (class->common != NULL) {
- struct cil_class *common = class->common;
- cil_symtab_map(&class->perms, __class_reset_perm_values, &common->num_perms);
+ /* Must assume that the common has been destroyed */
+ int num_common_perms = class->num_perms - class->perms.nprim;
+ cil_symtab_map(&class->perms, __class_reset_perm_values, &num_common_perms);
/* during a re-resolve, we need to reset the common, so a classcommon
* statement isn't seen as a duplicate */
- class->num_perms -= common->num_perms;
+ class->num_perms = class->perms.nprim;
class->common = NULL; /* Must make this NULL or there will be an error when re-resolving */
}
class->ordered = CIL_FALSE;
@@ -34,7 +36,7 @@ static void cil_reset_class(struct cil_class *class)
static void cil_reset_perm(struct cil_perm *perm)
{
- cil_reset_classperms_list(perm->classperms);
+ cil_list_destroy(&perm->classperms, CIL_FALSE);
}
static inline void cil_reset_classperms(struct cil_classperms *cp)
@@ -43,6 +45,7 @@ static inline void cil_reset_classperms(struct cil_classperms *cp)
return;
}
+ cp->class = NULL;
cil_list_destroy(&cp->perms, CIL_FALSE);
}
@@ -52,12 +55,20 @@ static void cil_reset_classpermission(struct cil_classpermission *cp)
return;
}
- cil_reset_classperms_list(cp->classperms);
+ cil_list_destroy(&cp->classperms, CIL_FALSE);
}
static void cil_reset_classperms_set(struct cil_classperms_set *cp_set)
{
- cil_reset_classpermission(cp_set->set);
+ if (cp_set == NULL || cp_set->set == NULL) {
+ return;
+ }
+
+ if (cp_set->set->datum.name == NULL) {
+ cil_reset_classperms_list(cp_set->set->classperms);
+ }
+
+ cp_set->set = NULL;
}
static inline void cil_reset_classperms_list(struct cil_list *cp_list)
@@ -129,8 +140,11 @@ static void cil_reset_userattributeset(struct cil_userattributeset *uas)
static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser)
{
+ selinuxuser->user = NULL;
if (selinuxuser->range_str == NULL) {
cil_reset_levelrange(selinuxuser->range);
+ } else {
+ selinuxuser->range = NULL;
}
}
@@ -194,6 +208,11 @@ static void cil_reset_typeattributeset(struct cil_typeattributeset *tas)
cil_list_destroy(&tas->datum_expr, CIL_FALSE);
}
+static void cil_reset_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
+{
+ cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
+}
+
static void cil_reset_avrule(struct cil_avrule *rule)
{
cil_reset_classperms_list(rule->perms.classperms);
@@ -203,6 +222,8 @@ static void cil_reset_rangetransition(struct cil_rangetransition *rangetrans)
{
if (rangetrans->range_str == NULL) {
cil_reset_levelrange(rangetrans->range);
+ } else {
+ rangetrans->range = NULL;
}
}
@@ -240,6 +261,7 @@ static void cil_reset_catset(struct cil_catset *catset)
static inline void cil_reset_level(struct cil_level *level)
{
+ level->sens = NULL;
cil_reset_cats(level->cats);
}
@@ -247,10 +269,14 @@ static inline void cil_reset_levelrange(struct cil_levelrange *levelrange)
{
if (levelrange->low_str == NULL) {
cil_reset_level(levelrange->low);
+ } else {
+ levelrange->low = NULL;
}
if (levelrange->high_str == NULL) {
cil_reset_level(levelrange->high);
+ } else {
+ levelrange->high = NULL;
}
}
@@ -258,6 +284,8 @@ static inline void cil_reset_userlevel(struct cil_userlevel *userlevel)
{
if (userlevel->level_str == NULL) {
cil_reset_level(userlevel->level);
+ } else {
+ userlevel->level = NULL;
}
}
@@ -265,13 +293,20 @@ static inline void cil_reset_userrange(struct cil_userrange *userrange)
{
if (userrange->range_str == NULL) {
cil_reset_levelrange(userrange->range);
+ } else {
+ userrange->range = NULL;
}
}
static inline void cil_reset_context(struct cil_context *context)
{
+ if (!context) {
+ return;
+ }
if (context->range_str == NULL) {
cil_reset_levelrange(context->range);
+ } else {
+ context->range = NULL;
}
}
@@ -279,26 +314,35 @@ static void cil_reset_sidcontext(struct cil_sidcontext *sidcontext)
{
if (sidcontext->context_str == NULL) {
cil_reset_context(sidcontext->context);
+ } else {
+ sidcontext->context = NULL;
}
}
static void cil_reset_filecon(struct cil_filecon *filecon)
{
- if (filecon->context_str == NULL && filecon->context != NULL) {
+ if (filecon->context_str == NULL) {
cil_reset_context(filecon->context);
+ } else {
+ filecon->context = NULL;
}
}
static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
{
- if (!ibpkeycon->context_str)
+ if (ibpkeycon->context_str == NULL) {
cil_reset_context(ibpkeycon->context);
+ } else {
+ ibpkeycon->context = NULL;
+ }
}
static void cil_reset_portcon(struct cil_portcon *portcon)
{
if (portcon->context_str == NULL) {
cil_reset_context(portcon->context);
+ } else {
+ portcon->context = NULL;
}
}
@@ -306,6 +350,8 @@ static void cil_reset_nodecon(struct cil_nodecon *nodecon)
{
if (nodecon->context_str == NULL) {
cil_reset_context(nodecon->context);
+ } else {
+ nodecon->context = NULL;
}
}
@@ -313,6 +359,8 @@ static void cil_reset_genfscon(struct cil_genfscon *genfscon)
{
if (genfscon->context_str == NULL) {
cil_reset_context(genfscon->context);
+ } else {
+ genfscon->context = NULL;
}
}
@@ -320,17 +368,23 @@ static void cil_reset_netifcon(struct cil_netifcon *netifcon)
{
if (netifcon->if_context_str == NULL) {
cil_reset_context(netifcon->if_context);
+ } else {
+ netifcon->if_context = NULL;
}
if (netifcon->packet_context_str == NULL) {
cil_reset_context(netifcon->packet_context);
+ } else {
+ netifcon->packet_context = NULL;
}
}
static void cil_reset_ibendportcon(struct cil_ibendportcon *ibendportcon)
{
- if (!ibendportcon->context_str) {
+ if (ibendportcon->context_str == NULL) {
cil_reset_context(ibendportcon->context);
+ } else {
+ ibendportcon->context = NULL;
}
}
@@ -338,6 +392,8 @@ static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon)
{
if (pirqcon->context_str == NULL) {
cil_reset_context(pirqcon->context);
+ } else {
+ pirqcon->context = NULL;
}
}
@@ -345,6 +401,8 @@ static void cil_reset_iomemcon(struct cil_iomemcon *iomemcon)
{
if (iomemcon->context_str == NULL) {
cil_reset_context(iomemcon->context);
+ } else {
+ iomemcon->context = NULL;
}
}
@@ -352,6 +410,8 @@ static void cil_reset_ioportcon(struct cil_ioportcon *ioportcon)
{
if (ioportcon->context_str == NULL) {
cil_reset_context(ioportcon->context);
+ } else {
+ ioportcon->context = NULL;
}
}
@@ -359,6 +419,8 @@ static void cil_reset_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
{
if (pcidevicecon->context_str == NULL) {
cil_reset_context(pcidevicecon->context);
+ } else {
+ pcidevicecon->context = NULL;
}
}
@@ -366,6 +428,8 @@ static void cil_reset_devicetreecon(struct cil_devicetreecon *devicetreecon)
{
if (devicetreecon->context_str == NULL) {
cil_reset_context(devicetreecon->context);
+ } else {
+ devicetreecon->context = NULL;
}
}
@@ -373,6 +437,8 @@ static void cil_reset_fsuse(struct cil_fsuse *fsuse)
{
if (fsuse->context_str == NULL) {
cil_reset_context(fsuse->context);
+ } else {
+ fsuse->context = NULL;
}
}
@@ -470,6 +536,9 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32
case CIL_TYPEATTRIBUTESET:
cil_reset_typeattributeset(node->data);
break;
+ case CIL_EXPANDTYPEATTRIBUTE:
+ cil_reset_expandtypeattribute(node->data);
+ break;
case CIL_RANGETRANSITION:
cil_reset_rangetransition(node->data);
break;
@@ -569,7 +638,6 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32
case CIL_CLASSORDER:
case CIL_CATORDER:
case CIL_SENSITIVITYORDER:
- case CIL_EXPANDTYPEATTRIBUTE:
break; /* Nothing to reset */
default:
break;
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 87575860..69a8a2ed 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -46,22 +46,26 @@
#include "cil_verify.h"
#include "cil_strpool.h"
#include "cil_symtab.h"
+#include "cil_stack.h"
struct cil_args_resolve {
struct cil_db *db;
enum cil_pass pass;
uint32_t *changed;
- char *last_resolved_name;
- struct cil_tree_node *optstack;
- struct cil_tree_node *boolif;
+ struct cil_list *to_destroy;
+ struct cil_tree_node *block;
struct cil_tree_node *macro;
- struct cil_tree_node *blockstack;
+ struct cil_tree_node *optional;
+ struct cil_tree_node *disabled_optional;
+ struct cil_tree_node *boolif;
struct cil_list *sidorder_lists;
struct cil_list *classorder_lists;
struct cil_list *unordered_classorder_lists;
struct cil_list *catorder_lists;
struct cil_list *sensitivityorder_lists;
- struct cil_list *in_list;
+ struct cil_list *in_list_before;
+ struct cil_list *in_list_after;
+ struct cil_list *abstract_blocks;
};
static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node)
@@ -76,29 +80,30 @@ static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key,
enum cil_sym_index sym_index;
struct cil_symtab_datum *datum = NULL;
- cil_flavor_to_symtab_index(CIL_NAME, &sym_index);
- symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
-
- cil_symtab_get_datum(symtab, key, &datum);
- if (datum != NULL) {
- return (struct cil_name *)datum;
- }
-
if (parent->flavor == CIL_CALL) {
struct cil_call *call = parent->data;
macro = call->macro;
} else if (parent->flavor == CIL_MACRO) {
macro = parent->data;
}
- if (macro != NULL) {
+ if (macro != NULL && macro->params != NULL) {
struct cil_list_item *item;
cil_list_for_each(item, macro->params) {
- if (((struct cil_param*)item->data)->str == key) {
+ struct cil_param *param = item->data;
+ if (param->flavor == CIL_NAME && param->str == key) {
return NULL;
}
}
}
+ cil_flavor_to_symtab_index(CIL_NAME, &sym_index);
+ symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
+
+ cil_symtab_get_datum(symtab, key, &datum);
+ if (datum != NULL) {
+ return (struct cil_name *)datum;
+ }
+
cil_name_init(&name);
cil_symtab_insert(symtab, key, (struct cil_symtab_datum *)name, ast_node);
cil_list_append(db->names, CIL_NAME, name);
@@ -147,6 +152,7 @@ static int __cil_resolve_perms(symtab_t *class_symtab, symtab_t *common_symtab,
return SEPOL_OK;
exit:
+ cil_list_destroy(perm_datums, CIL_FALSE);
return rc;
}
@@ -157,6 +163,10 @@ int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms
symtab_t *common_symtab = NULL;
struct cil_class *class;
+ if (cp->class) {
+ return SEPOL_OK;
+ }
+
rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, extra_args, &datum);
if (rc != SEPOL_OK) {
goto exit;
@@ -394,7 +404,7 @@ int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args)
goto exit;
}
- result_node = result_datum->nodes->head->data;
+ result_node = NODE(result_datum);
if (result_node->flavor != CIL_TYPE) {
cil_log(CIL_ERR, "Type rule result must be a type [%d]\n",result_node->flavor);
@@ -422,7 +432,7 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- attr_node = attr_datum->nodes->head->data;
+ attr_node = NODE(attr_datum);
if (attr_node->flavor != CIL_TYPEATTRIBUTE) {
rc = SEPOL_ERR;
@@ -437,11 +447,6 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrtypes->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_TYPEATTRIBUTE);
}
@@ -471,7 +476,7 @@ int cil_resolve_expandtypeattribute(struct cil_tree_node *current, void *extra_a
goto exit;
}
- attr_node = attr_datum->nodes->head->data;
+ attr_node = NODE(attr_datum);
if (attr_node->flavor != CIL_TYPEATTRIBUTE) {
rc = SEPOL_ERR;
@@ -506,7 +511,7 @@ int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_args, enu
if (rc != SEPOL_OK) {
goto exit;
}
- if (NODE(alias_datum)->flavor != alias_flavor) {
+ if (FLAVOR(alias_datum) != alias_flavor) {
cil_log(CIL_ERR, "%s is not an alias\n",alias_datum->name);
rc = SEPOL_ERR;
goto exit;
@@ -517,7 +522,7 @@ int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_args, enu
goto exit;
}
- if (NODE(actual_datum)->flavor != flavor && NODE(actual_datum)->flavor != alias_flavor) {
+ if (FLAVOR(actual_datum) != flavor && FLAVOR(actual_datum) != alias_flavor) {
cil_log(CIL_ERR, "%s is a %s, but aliases a %s\n", alias_datum->name, cil_node_to_string(NODE(alias_datum)), cil_node_to_string(NODE(actual_datum)));
rc = SEPOL_ERR;
goto exit;
@@ -556,6 +561,10 @@ int cil_resolve_alias_to_actual(struct cil_tree_node *current, enum cil_flavor f
a1_node = a1->datum.nodes->head->data;
while (flavor != a1_node->flavor) {
+ if (a1->actual == NULL) {
+ cil_tree_log(current, CIL_ERR, "Alias %s references an unused alias %s", alias->datum.name, a1->datum.name);
+ return SEPOL_ERR;
+ }
a1 = a1->actual;
a1_node = a1->datum.nodes->head->data;
steps += 1;
@@ -595,7 +604,7 @@ int cil_resolve_typepermissive(struct cil_tree_node *current, void *extra_args)
goto exit;
}
- type_node = type_datum->nodes->head->data;
+ type_node = NODE(type_datum);
if (type_node->flavor != CIL_TYPE && type_node->flavor != CIL_TYPEALIAS) {
cil_log(CIL_ERR, "Typepermissive must be a type or type alias\n");
@@ -655,7 +664,7 @@ int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_ar
goto exit;
}
- result_node = result_datum->nodes->head->data;
+ result_node = NODE(result_datum);
if (result_node->flavor != CIL_TYPE && result_node->flavor != CIL_TYPEALIAS) {
cil_log(CIL_ERR, "typetransition result is not a type or type alias\n");
@@ -746,6 +755,11 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args)
if (rc != SEPOL_OK) {
goto exit;
}
+ if (NODE(class_datum)->flavor != CIL_CLASS) {
+ cil_log(CIL_ERR, "Class %s is not a kernel class and cannot be associated with common %s\n", clscom->class_str, clscom->common_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
rc = cil_resolve_name(current, clscom->common_str, CIL_SYM_COMMONS, extra_args, &common_datum);
if (rc != SEPOL_OK) {
@@ -767,6 +781,7 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args)
class->num_perms += common->num_perms;
if (class->num_perms > CIL_PERMS_PER_CLASS) {
cil_tree_log(current, CIL_ERR, "Too many permissions in class '%s' when including common permissions", class->datum.name);
+ rc = SEPOL_ERR;
goto exit;
}
@@ -856,7 +871,7 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args)
goto exit;
}
- user_node = user_datum->nodes->head->data;
+ user_node = NODE(user_datum);
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userlevel must be a user\n");
@@ -909,7 +924,7 @@ int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args)
goto exit;
}
- user_node = user_datum->nodes->head->data;
+ user_node = NODE(user_datum);
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userrange must be a user: %s\n", user_datum->fqn);
@@ -960,7 +975,7 @@ int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args)
goto exit;
}
- user_node = user_datum->nodes->head->data;
+ user_node = NODE(user_datum);
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userprefix must be a user: %s\n", user_datum->fqn);
@@ -987,7 +1002,7 @@ int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args)
goto exit;
}
- user_node = user_datum->nodes->head->data;
+ user_node = NODE(user_datum);
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Selinuxuser must be a user: %s\n", user_datum->fqn);
@@ -1080,10 +1095,9 @@ int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args)
if (rc != SEPOL_OK) {
goto exit;
}
- node = result_datum->nodes->head->data;
+ node = NODE(result_datum);
if (node->flavor != CIL_ROLE) {
rc = SEPOL_ERR;
- printf("%i\n", node->flavor);
cil_log(CIL_ERR, "roletransition must result in a role, but %s is a %s\n", roletrans->result_str, cil_node_to_string(node));
goto exit;
}
@@ -1132,7 +1146,7 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args
if (rc != SEPOL_OK) {
goto exit;
}
- attr_node = attr_datum->nodes->head->data;
+ attr_node = NODE(attr_datum);
if (attr_node->flavor != CIL_ROLEATTRIBUTE) {
rc = SEPOL_ERR;
@@ -1146,11 +1160,6 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrroles->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_ROLEATTRIBUTE);
}
@@ -1480,6 +1489,12 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ if (FLAVOR(datum) != CIL_CLASS) {
+ cil_log(CIL_ERR, "%s is not a class. Only classes are allowed in classorder statements\n", datum->name);
+ rc = SEPOL_ERR;
goto exit;
}
cil_list_append(new, CIL_CLASS, datum);
@@ -1520,6 +1535,12 @@ int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args)
cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data);
goto exit;
}
+ if (FLAVOR(datum) != CIL_SID) {
+ cil_log(CIL_ERR, "%s is not a sid. Only sids are allowed in sidorder statements\n", datum->name);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
cil_list_append(new, CIL_SID, datum);
}
@@ -1570,7 +1591,7 @@ int cil_resolve_catorder(struct cil_tree_node *current, void *extra_args)
cil_log(CIL_ERR, "Failed to resolve category %s in categoryorder\n", (char *)curr->data);
goto exit;
}
- node = cat_datum->nodes->head->data;
+ node = NODE(cat_datum);
if (node->flavor != CIL_CAT) {
cil_log(CIL_ERR, "%s is not a category. Only categories are allowed in categoryorder statements\n", cat_datum->name);
rc = SEPOL_ERR;
@@ -1608,7 +1629,12 @@ int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args
cil_list_for_each(curr, sensorder->sens_list_str) {
rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, extra_args, &datum);
if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to resolve sensitivty %s in sensitivityorder\n", (char *)curr->data);
+ cil_log(CIL_ERR, "Failed to resolve sensitivity %s in sensitivityorder\n", (char *)curr->data);
+ goto exit;
+ }
+ if (FLAVOR(datum) != CIL_SENS) {
+ cil_log(CIL_ERR, "%s is not a sensitivity. Only sensitivities are allowed in sensitivityorder statements\n", datum->name);
+ rc = SEPOL_ERR;
goto exit;
}
cil_list_append(new, CIL_SENS, datum);
@@ -1644,21 +1670,7 @@ exit:
int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args)
{
- int rc = SEPOL_ERR;
-
- rc = cil_resolve_cats(current, catset->cats, extra_args);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
- rc = cil_verify_no_self_reference((struct cil_symtab_datum *)catset, catset->cats->datum_expr);
- if (rc != SEPOL_OK) {
- cil_list_destroy(&catset->cats->datum_expr, CIL_FALSE);
- goto exit;
- }
-
-exit:
- return rc;
+ return cil_resolve_cats(current, catset->cats, extra_args);
}
int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args)
@@ -1698,6 +1710,10 @@ int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, vo
struct cil_symtab_datum *sens_datum = NULL;
int rc = SEPOL_ERR;
+ if (level->sens) {
+ return SEPOL_OK;
+ }
+
rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, extra_args, &sens_datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to find sensitivity\n");
@@ -1833,7 +1849,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte
goto exit;
}
- node = user_datum->nodes->head->data;
+ node = NODE(user_datum);
if (node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn);
@@ -1848,7 +1864,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte
goto exit;
}
- node = role_datum->nodes->head->data;
+ node = NODE(role_datum);
if (node->flavor != CIL_ROLE) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn);
@@ -1862,7 +1878,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte
goto exit;
}
- node = type_datum->nodes->head->data;
+ node = NODE(type_datum);
if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) {
rc = SEPOL_ERR;
@@ -2312,7 +2328,7 @@ int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_arg
goto exit;
}
- node = block_datum->nodes->head->data;
+ node = NODE(block_datum);
if (node->flavor != CIL_BLOCK) {
cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node));
@@ -2333,71 +2349,6 @@ exit:
return rc;
}
-void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node)
-{
- struct cil_list *trace = NULL;
- struct cil_list_item *item = NULL;
- struct cil_tree_node *curr = NULL;
-
- cil_list_init(&trace, CIL_NODE);
-
- for (curr = bi_node; curr != terminating_node; curr = curr->parent) {
- if (curr->flavor == CIL_BLOCK) {
- cil_list_prepend(trace, CIL_NODE, curr);
- } else {
- if (curr != bi_node) {
- cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_blockinherit *)curr->data)->block));
- }
- cil_list_prepend(trace, CIL_NODE, curr);
- }
- }
- cil_list_prepend(trace, CIL_NODE, terminating_node);
-
- cil_list_for_each(item, trace) {
- curr = item->data;
- if (curr->flavor == CIL_BLOCK) {
- cil_tree_log(curr, CIL_ERR, "block %s", DATUM(curr->data)->name);
- } else {
- cil_tree_log(curr, CIL_ERR, "blockinherit %s", ((struct cil_blockinherit *)curr->data)->block_str);
- }
- }
-
- cil_list_destroy(&trace, CIL_FALSE);
-}
-
-int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node)
-{
- struct cil_tree_node *curr = NULL;
- struct cil_blockinherit *bi = NULL;
- struct cil_block *block = NULL;
- int rc = SEPOL_ERR;
-
- bi = bi_node->data;
-
- for (curr = bi_node->parent; curr != NULL; curr = curr->parent) {
- if (curr->flavor != CIL_BLOCK) {
- continue;
- }
-
- block = curr->data;
-
- if (block != bi->block) {
- continue;
- }
-
- cil_log(CIL_ERR, "Recursive blockinherit found:\n");
- cil_print_recursive_blockinherit(bi_node, curr);
-
- rc = SEPOL_ERR;
- goto exit;
- }
-
- rc = SEPOL_OK;
-
-exit:
- return rc;
-}
-
int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args)
{
struct cil_block *block = current->data;
@@ -2421,11 +2372,6 @@ int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_arg
}
cil_list_for_each(item, block->bi_nodes) {
- rc = cil_check_recursive_blockinherit(item->data);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
rc = cil_copy_ast(db, current, item->data);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n");
@@ -2439,11 +2385,25 @@ exit:
return rc;
}
+static void cil_mark_subtree_abstract(struct cil_tree_node *node)
+{
+ struct cil_block *block = node->data;
+
+ block->is_abstract = CIL_TRUE;
+
+ for (node = node->cl_head; node; node = node->next) {
+ if (node->flavor == CIL_BLOCK) {
+ cil_mark_subtree_abstract(node);
+ }
+ }
+}
+
int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args)
{
struct cil_blockabstract *abstract = current->data;
struct cil_symtab_datum *block_datum = NULL;
struct cil_tree_node *block_node = NULL;
+ struct cil_args_resolve *args = extra_args;
int rc = SEPOL_ERR;
rc = cil_resolve_name(current, abstract->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum);
@@ -2451,13 +2411,14 @@ int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args)
goto exit;
}
- block_node = block_datum->nodes->head->data;
+ block_node = NODE(block_datum);
if (block_node->flavor != CIL_BLOCK) {
cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc);
+ rc = SEPOL_ERR;
goto exit;
}
- ((struct cil_block*)block_datum)->is_abstract = CIL_TRUE;
+ cil_list_append(args->abstract_blocks, CIL_NODE, block_node);
return SEPOL_OK;
@@ -2483,17 +2444,24 @@ int cil_resolve_in(struct cil_tree_node *current, void *extra_args)
goto exit;
}
- block_node = block_datum->nodes->head->data;
+ block_node = NODE(block_datum);
+
+ if (block_node->flavor == CIL_OPTIONAL) {
+ if (block_datum->nodes && block_datum->nodes->head != block_datum->nodes->tail) {
+ cil_tree_log(current, CIL_ERR, "Multiple optional blocks referred to by in-statement");
+ cil_tree_log(block_node, CIL_ERR, "First optional block");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
rc = cil_copy_ast(db, current, block_node);
if (rc != SEPOL_OK) {
- printf("Failed to copy in, rc: %d\n", rc);
+ cil_tree_log(current, CIL_ERR, "Failed to copy in-statement");
goto exit;
}
cil_tree_children_destroy(current);
- current->cl_head = NULL;
- current->cl_tail = NULL;
return SEPOL_OK;
@@ -2501,10 +2469,8 @@ exit:
return rc;
}
-int cil_resolve_in_list(void *extra_args)
+int cil_resolve_in_list(struct cil_list *in_list, void *extra_args)
{
- struct cil_args_resolve *args = extra_args;
- struct cil_list *ins = args->in_list;
struct cil_list_item *curr = NULL;
struct cil_tree_node *node = NULL;
struct cil_tree_node *last_failed_node = NULL;
@@ -2518,7 +2484,7 @@ int cil_resolve_in_list(void *extra_args)
resolved = 0;
unresolved = 0;
- cil_list_for_each(curr, ins) {
+ cil_list_for_each(curr, in_list) {
if (curr->flavor != CIL_NODE) {
continue;
}
@@ -2574,7 +2540,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
if (rc != SEPOL_OK) {
goto exit;
}
- if (NODE(parent_datum)->flavor == attr_flavor) {
+ if (FLAVOR(parent_datum) == attr_flavor) {
cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
rc = SEPOL_ERR;
goto exit;
@@ -2585,7 +2551,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
if (rc != SEPOL_OK) {
goto exit;
}
- if (NODE(child_datum)->flavor == attr_flavor) {
+ if (FLAVOR(child_datum) == attr_flavor) {
cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
rc = SEPOL_ERR;
goto exit;
@@ -2757,280 +2723,368 @@ exit:
return rc;
}
-int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
+static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call *call, struct cil_macro *macro, void *extra_args)
{
- struct cil_call *new_call = current->data;
struct cil_args_resolve *args = extra_args;
- struct cil_db *db = NULL;
- struct cil_tree_node *macro_node = NULL;
- struct cil_symtab_datum *macro_datum = NULL;
+ struct cil_list_item *item;
+ struct cil_args *arg = NULL;
+ struct cil_tree_node *arg_node = NULL;
int rc = SEPOL_ERR;
- if (args != NULL) {
- db = args->db;
+ if (macro->params == NULL) {
+ if (call->args_tree == NULL) {
+ return SEPOL_OK;
+ } else {
+ cil_tree_log(call_node, CIL_ERR, "Unexpected arguments");
+ return SEPOL_ERR;
+ }
}
-
- rc = cil_resolve_name(current, new_call->macro_str, CIL_SYM_BLOCKS, extra_args, &macro_datum);
- if (rc != SEPOL_OK) {
- goto exit;
+ if (call->args_tree == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Missing arguments");
+ return SEPOL_ERR;
}
- macro_node = macro_datum->nodes->head->data;
+ arg_node = call->args_tree->root->cl_head;
- if (macro_node->flavor != CIL_MACRO) {
- printf("Failed to resolve %s to a macro\n", new_call->macro_str);
- rc = SEPOL_ERR;
- goto exit;
- }
- new_call->macro = (struct cil_macro*)macro_datum;
-
- if (new_call->macro->params != NULL ) {
+ cil_list_init(&call->args, CIL_LIST_ITEM);
- struct cil_list_item *item;
- struct cil_args *new_arg = NULL;
- struct cil_tree_node *pc = NULL;
+ cil_list_for_each(item, macro->params) {
+ enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor;
- if (new_call->args_tree == NULL) {
- cil_tree_log(current, CIL_ERR, "Missing arguments");
+ if (arg_node == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Missing arguments");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ if (item->flavor != CIL_PARAM) {
rc = SEPOL_ERR;
goto exit;
}
- pc = new_call->args_tree->root->cl_head;
-
- cil_list_init(&new_call->args, CIL_LIST_ITEM);
-
- cil_list_for_each(item, new_call->macro->params) {
- enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor;
+ cil_args_init(&arg);
- if (pc == NULL) {
- cil_tree_log(current, CIL_ERR, "Missing arguments");
+ switch (flavor) {
+ case CIL_NAME: {
+ struct cil_name *name;
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
- if (item->flavor != CIL_PARAM) {
+ name = __cil_insert_name(args->db, arg_node->data, call_node);
+ if (name != NULL) {
+ arg->arg = (struct cil_symtab_datum *)name;
+ } else {
+ arg->arg_str = arg_node->data;
+ }
+ }
+ break;
+ case CIL_TYPE:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
-
- cil_args_init(&new_arg);
-
- switch (flavor) {
- case CIL_NAME: {
- struct cil_name *name;
- name = __cil_insert_name(args->db, pc->data, current);
- if (name != NULL) {
- new_arg->arg = (struct cil_symtab_datum *)name;
- } else {
- new_arg->arg_str = pc->data;
- }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_ROLE:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
}
- break;
- case CIL_TYPE:
- new_arg->arg_str = pc->data;
- break;
- case CIL_ROLE:
- new_arg->arg_str = pc->data;
- break;
- case CIL_USER:
- new_arg->arg_str = pc->data;
- break;
- case CIL_SENS:
- new_arg->arg_str = pc->data;
- break;
- case CIL_CAT:
- new_arg->arg_str = pc->data;
- break;
- case CIL_BOOL:
- new_arg->arg_str = pc->data;
- break;
- case CIL_CATSET: {
- if (pc->cl_head != NULL) {
- struct cil_catset *catset = NULL;
- struct cil_tree_node *cat_node = NULL;
- cil_catset_init(&catset);
- rc = cil_fill_cats(pc, &catset->cats);
- if (rc != SEPOL_OK) {
- cil_destroy_catset(catset);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&cat_node);
- cat_node->flavor = CIL_CATSET;
- cat_node->data = catset;
- cil_list_append(((struct cil_symtab_datum*)catset)->nodes,
- CIL_LIST_ITEM, cat_node);
- new_arg->arg = (struct cil_symtab_datum*)catset;
- } else {
- new_arg->arg_str = pc->data;
- }
-
- break;
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_USER:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
}
- case CIL_LEVEL: {
- if (pc->cl_head != NULL) {
- struct cil_level *level = NULL;
- struct cil_tree_node *lvl_node = NULL;
- cil_level_init(&level);
-
- rc = cil_fill_level(pc->cl_head, level);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc);
- cil_destroy_level(level);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&lvl_node);
- lvl_node->flavor = CIL_LEVEL;
- lvl_node->data = level;
- cil_list_append(((struct cil_symtab_datum*)level)->nodes,
- CIL_LIST_ITEM, lvl_node);
- new_arg->arg = (struct cil_symtab_datum*)level;
- } else {
- new_arg->arg_str = pc->data;
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_SENS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CAT:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_BOOL:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CATSET: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_catset *catset = NULL;
+ struct cil_tree_node *cat_node = NULL;
+ cil_catset_init(&catset);
+ rc = cil_fill_cats(arg_node, &catset->cats);
+ if (rc != SEPOL_OK) {
+ cil_destroy_catset(catset);
+ cil_destroy_args(arg);
+ goto exit;
}
-
- break;
+ cil_tree_node_init(&cat_node);
+ cat_node->flavor = CIL_CATSET;
+ cat_node->data = catset;
+ cil_list_append(((struct cil_symtab_datum*)catset)->nodes,
+ CIL_LIST_ITEM, cat_node);
+ arg->arg = (struct cil_symtab_datum*)catset;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_LEVELRANGE: {
- if (pc->cl_head != NULL) {
- struct cil_levelrange *range = NULL;
- struct cil_tree_node *range_node = NULL;
- cil_levelrange_init(&range);
- rc = cil_fill_levelrange(pc->cl_head, range);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc);
- cil_destroy_levelrange(range);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&range_node);
- range_node->flavor = CIL_LEVELRANGE;
- range_node->data = range;
- cil_list_append(((struct cil_symtab_datum*)range)->nodes,
- CIL_LIST_ITEM, range_node);
- new_arg->arg = (struct cil_symtab_datum*)range;
- } else {
- new_arg->arg_str = pc->data;
- }
+ break;
+ }
+ case CIL_LEVEL: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_level *level = NULL;
+ struct cil_tree_node *lvl_node = NULL;
+ cil_level_init(&level);
- break;
+ rc = cil_fill_level(arg_node->cl_head, level);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc);
+ cil_destroy_level(level);
+ cil_destroy_args(arg);
+ goto exit;
+ }
+ cil_tree_node_init(&lvl_node);
+ lvl_node->flavor = CIL_LEVEL;
+ lvl_node->data = level;
+ cil_list_append(((struct cil_symtab_datum*)level)->nodes,
+ CIL_LIST_ITEM, lvl_node);
+ arg->arg = (struct cil_symtab_datum*)level;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_IPADDR: {
- if (pc->cl_head != NULL) {
- struct cil_ipaddr *ipaddr = NULL;
- struct cil_tree_node *addr_node = NULL;
- cil_ipaddr_init(&ipaddr);
- rc = cil_fill_ipaddr(pc->cl_head, ipaddr);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous ip address, rc: %d\n", rc);
- cil_destroy_ipaddr(ipaddr);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&addr_node);
- addr_node->flavor = CIL_IPADDR;
- addr_node->data = ipaddr;
- cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes,
- CIL_LIST_ITEM, addr_node);
- new_arg->arg = (struct cil_symtab_datum*)ipaddr;
- } else {
- new_arg->arg_str = pc->data;
- }
+ break;
+ }
+ case CIL_LEVELRANGE: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_levelrange *range = NULL;
+ struct cil_tree_node *range_node = NULL;
+ cil_levelrange_init(&range);
- break;
+ rc = cil_fill_levelrange(arg_node->cl_head, range);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc);
+ cil_destroy_levelrange(range);
+ cil_destroy_args(arg);
+ goto exit;
+ }
+ cil_tree_node_init(&range_node);
+ range_node->flavor = CIL_LEVELRANGE;
+ range_node->data = range;
+ cil_list_append(((struct cil_symtab_datum*)range)->nodes,
+ CIL_LIST_ITEM, range_node);
+ arg->arg = (struct cil_symtab_datum*)range;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
}
- case CIL_CLASS:
- new_arg->arg_str = pc->data;
- break;
- case CIL_MAP_CLASS:
- new_arg->arg_str = pc->data;
- break;
- case CIL_CLASSPERMISSION: {
- if (pc->cl_head != NULL) {
- struct cil_classpermission *cp = NULL;
- struct cil_tree_node *cp_node = NULL;
- cil_classpermission_init(&cp);
- rc = cil_fill_classperms_list(pc, &cp->classperms);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to create anonymous classpermission\n");
- cil_destroy_classpermission(cp);
- cil_destroy_args(new_arg);
- goto exit;
- }
- cil_tree_node_init(&cp_node);
- cp_node->flavor = CIL_CLASSPERMISSION;
- cp_node->data = cp;
- cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node);
- new_arg->arg = (struct cil_symtab_datum*)cp;
- } else {
- new_arg->arg_str = pc->data;
+ break;
+ }
+ case CIL_IPADDR: {
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else if (strchr(arg_node->data, '.') || strchr(arg_node->data, ':')) {
+ struct cil_ipaddr *ipaddr = NULL;
+ struct cil_tree_node *addr_node = NULL;
+ cil_ipaddr_init(&ipaddr);
+ rc = cil_fill_ipaddr(arg_node, ipaddr);
+ if (rc != SEPOL_OK) {
+ cil_tree_log(call_node, CIL_ERR, "Failed to create anonymous ip address");
+ cil_destroy_ipaddr(ipaddr);
+ cil_destroy_args(arg);
+ goto exit;
}
- break;
+ cil_tree_node_init(&addr_node);
+ addr_node->flavor = CIL_IPADDR;
+ addr_node->data = ipaddr;
+ cil_list_append(DATUM(ipaddr)->nodes, CIL_LIST_ITEM, addr_node);
+ arg->arg = DATUM(ipaddr);
+ } else {
+ arg->arg_str = arg_node->data;
}
- default:
- cil_log(CIL_ERR, "Unexpected flavor: %d\n",
- (((struct cil_param*)item->data)->flavor));
- cil_destroy_args(new_arg);
+ break;
+ }
+ case CIL_CLASS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
- new_arg->param_str = ((struct cil_param*)item->data)->str;
- new_arg->flavor = flavor;
-
- cil_list_append(new_call->args, CIL_ARGS, new_arg);
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_MAP_CLASS:
+ if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ arg->arg_str = arg_node->data;
+ break;
+ case CIL_CLASSPERMISSION: {
+ if (arg_node->cl_head != NULL) {
+ struct cil_classpermission *cp = NULL;
+ struct cil_tree_node *cp_node = NULL;
- pc = pc->next;
+ cil_classpermission_init(&cp);
+ rc = cil_fill_classperms_list(arg_node, &cp->classperms);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to create anonymous classpermission\n");
+ cil_destroy_classpermission(cp);
+ cil_destroy_args(arg);
+ goto exit;
+ }
+ cil_tree_node_init(&cp_node);
+ cp_node->flavor = CIL_CLASSPERMISSION;
+ cp_node->data = cp;
+ cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node);
+ arg->arg = (struct cil_symtab_datum*)cp;
+ } else if (arg_node->data == NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter");
+ cil_destroy_args(arg);
+ rc = SEPOL_ERR;
+ goto exit;
+ } else {
+ arg->arg_str = arg_node->data;
+ }
+ break;
}
-
- if (pc != NULL) {
- cil_tree_log(current, CIL_ERR, "Unexpected arguments");
+ default:
+ cil_log(CIL_ERR, "Unexpected flavor: %d\n",
+ (((struct cil_param*)item->data)->flavor));
+ cil_destroy_args(arg);
rc = SEPOL_ERR;
goto exit;
}
- } else if (new_call->args_tree != NULL) {
- cil_tree_log(current, CIL_ERR, "Unexpected arguments");
+ arg->param_str = ((struct cil_param*)item->data)->str;
+ arg->flavor = flavor;
+
+ cil_list_append(call->args, CIL_ARGS, arg);
+
+ arg_node = arg_node->next;
+ }
+
+ if (arg_node != NULL) {
+ cil_tree_log(call_node, CIL_ERR, "Unexpected arguments");
rc = SEPOL_ERR;
goto exit;
}
- if (new_call->copied == 0) {
- new_call->copied = 1;
+ return SEPOL_OK;
- rc = cil_check_recursive_call(current, macro_node);
- if (rc != SEPOL_OK) {
- goto exit;
- }
+exit:
+ return rc;
+}
- rc = cil_copy_ast(db, macro_node, current);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to copy macro, rc: %d\n", rc);
- goto exit;
- }
+int cil_resolve_call(struct cil_tree_node *current, void *extra_args)
+{
+ struct cil_call *call = current->data;
+ struct cil_args_resolve *args = extra_args;
+ struct cil_tree_node *macro_node = NULL;
+ struct cil_symtab_datum *macro_datum = NULL;
+ int rc = SEPOL_ERR;
+
+ if (call->copied) {
+ return SEPOL_OK;
}
+ rc = cil_resolve_name(current, call->macro_str, CIL_SYM_BLOCKS, extra_args, &macro_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ macro_node = NODE(macro_datum);
+
+ if (macro_node->flavor != CIL_MACRO) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s to a macro", call->macro_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ call->macro = (struct cil_macro*)macro_datum;
+
+ rc = cil_build_call_args(current, call, call->macro, extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = cil_check_recursive_call(current, macro_node);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = cil_copy_ast(args->db, macro_node, current);
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to copy macro %s to call", macro_datum->name);
+ goto exit;
+ }
+
+ call->copied = 1;
+
return SEPOL_OK;
exit:
return rc;
}
-int cil_resolve_call2(struct cil_tree_node *current, void *extra_args)
+int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args)
{
- struct cil_call *new_call = current->data;
+ struct cil_call *call = current->data;
int rc = SEPOL_ERR;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
struct cil_list_item *item;
- if (new_call->args == NULL) {
+ if (call->args == NULL) {
rc = SEPOL_OK;
goto exit;
}
- cil_list_for_each(item, new_call->args) {
+ cil_list_for_each(item, call->args) {
struct cil_args *arg = item->data;
if (arg->arg == NULL && arg->arg_str == NULL) {
cil_log(CIL_ERR, "Arguments not created correctly\n");
@@ -3113,10 +3167,37 @@ int cil_resolve_call2(struct cil_tree_node *current, void *extra_args)
}
if (sym_index != CIL_SYM_UNKNOWN) {
- rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
+ struct cil_symtab_datum *datum;
+ struct cil_tree_node *n;
+ rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &datum);
if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str);
goto exit;
}
+ arg->arg = datum;
+ n = NODE(datum);
+ while (n && n->flavor != CIL_ROOT) {
+ if (n == current) {
+ symtab_t *s = datum->symtab;
+ /* Call arg should not resolve to declaration in the call
+ * Need to remove datum temporarily to resolve to a datum outside
+ * the call.
+ */
+ cil_symtab_remove_datum(datum);
+ rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg));
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str);
+ goto exit;
+ }
+ rc = cil_symtab_insert(s, datum->name, datum, NULL);
+ if (rc != SEPOL_OK) {
+ cil_tree_log(current, CIL_ERR, "Failed to re-insert datum while resolving %s in call argument list", arg->arg_str);
+ goto exit;
+ }
+ break;
+ }
+ n = n->parent;
+ }
}
}
@@ -3146,7 +3227,7 @@ int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_i
if (param_index == sym_index) {
if (name == arg->param_str) {
*datum = arg->arg;
- rc = SEPOL_OK;
+ rc = *datum ? SEPOL_OK : SEPOL_ERR;
goto exit;
}
}
@@ -3164,6 +3245,8 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc
struct cil_list_item *curr;
struct cil_symtab_datum *res_datum = NULL;
enum cil_sym_index sym_index = CIL_SYM_UNKNOWN;
+ struct cil_list *datum_sub_expr;
+ enum cil_flavor op = CIL_NONE;
switch (str_expr->flavor) {
case CIL_BOOL:
@@ -3197,31 +3280,53 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc
if (rc != SEPOL_OK) {
goto exit;
}
-
- if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) {
- cil_type_used(res_datum, CIL_ATTR_CONSTRAINT);
+ if (sym_index == CIL_SYM_CATS && NODE(res_datum)->flavor == CIL_CATSET) {
+ struct cil_catset *catset = (struct cil_catset *)res_datum;
+ if (op == CIL_RANGE) {
+ cil_tree_log(parent, CIL_ERR, "Category set not allowed in category range");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ if (!res_datum->name) {
+ /* Anonymous category sets need to be resolved when encountered */
+ if (!catset->cats->datum_expr) {
+ rc = cil_resolve_expr(expr_type, catset->cats->str_expr, &catset->cats->datum_expr, parent, extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ }
+ cil_copy_list(catset->cats->datum_expr, &datum_sub_expr);
+ cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr);
+ } else {
+ cil_list_append(*datum_expr, CIL_DATUM, res_datum);
+ }
+ } else {
+ if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) {
+ cil_type_used(res_datum, CIL_ATTR_CONSTRAINT);
+ }
+ cil_list_append(*datum_expr, CIL_DATUM, res_datum);
}
-
- cil_list_append(*datum_expr, CIL_DATUM, res_datum);
break;
case CIL_LIST: {
- struct cil_list *datum_sub_expr;
rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, extra_args);
if (rc != SEPOL_OK) {
- cil_list_destroy(&datum_sub_expr, CIL_TRUE);
goto exit;
}
cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr);
break;
}
default:
+ if (curr->flavor == CIL_OP) {
+ op = (enum cil_flavor)(uintptr_t)curr->data;
+ }
cil_list_append(*datum_expr, curr->flavor, curr->data);
break;
- }
+ }
}
return SEPOL_OK;
exit:
+ cil_list_destroy(datum_expr, CIL_FALSE);
return rc;
}
@@ -3266,7 +3371,7 @@ static int __cil_evaluate_tunable_expr(struct cil_list_item *curr)
return CIL_FALSE;
} else if (curr->flavor == CIL_OP) {
uint16_t v1, v2;
- enum cil_flavor op_flavor = (enum cil_flavor)curr->data;
+ enum cil_flavor op_flavor = (enum cil_flavor)(uintptr_t)curr->data;
v1 = __cil_evaluate_tunable_expr_helper(curr->next);
@@ -3368,7 +3473,7 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args
if (rc != SEPOL_OK) {
goto exit;
}
- attr_node = attr_datum->nodes->head->data;
+ attr_node = NODE(attr_datum);
if (attr_node->flavor != CIL_USERATTRIBUTE) {
rc = SEPOL_ERR;
@@ -3382,11 +3487,6 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args
goto exit;
}
- rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr);
- if (rc != SEPOL_OK) {
- goto exit;
- }
-
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE);
}
@@ -3399,17 +3499,119 @@ exit:
return rc;
}
+/*
+ * Degenerate inheritance leads to exponential growth of the policy
+ * It can take many forms, but here is one example.
+ * ...
+ * (blockinherit ba)
+ * (block b0
+ * (block b1
+ * (block b2
+ * (block b3
+ * ...
+ * )
+ * (blockinherit b3)
+ * )
+ * (blockinherit b2)
+ * )
+ * (blockinherit b1)
+ * )
+ * (blockinherit b0)
+ * ...
+ * This leads to 2^4 copies of the content of block b3, 2^3 copies of the
+ * contents of block b2, etc.
+ */
+static unsigned cil_count_actual(struct cil_tree_node *node)
+{
+ unsigned count = 0;
+
+ if (node->flavor == CIL_BLOCKINHERIT) {
+ count += 1;
+ }
+
+ for (node = node->cl_head; node; node = node->next) {
+ count += cil_count_actual(node);
+ }
+
+ return count;
+}
+
+static int cil_check_inheritances(struct cil_tree_node *node, unsigned max, unsigned *count, struct cil_stack *stack, unsigned *loop)
+{
+ int rc;
+
+ if (node->flavor == CIL_BLOCKINHERIT) {
+ struct cil_blockinherit *bi = node->data;
+ *count += 1;
+ if (*count > max) {
+ cil_tree_log(node, CIL_ERR, "Degenerate inheritance detected");
+ return SEPOL_ERR;
+ }
+ if (bi->block) {
+ struct cil_tree_node *block_node = NODE(bi->block);
+ struct cil_stack_item *item;
+ int i = 0;
+ cil_stack_for_each(stack, i, item) {
+ if (block_node == (struct cil_tree_node *)item->data) {
+ *loop = CIL_TRUE;
+ cil_tree_log(block_node, CIL_ERR, "Block inheritance loop found");
+ cil_tree_log(node, CIL_ERR, " blockinherit");
+ return SEPOL_ERR;
+ }
+ }
+ cil_stack_push(stack, CIL_BLOCK, block_node);
+ rc = cil_check_inheritances(block_node, max, count, stack, loop);
+ cil_stack_pop(stack);
+ if (rc != SEPOL_OK) {
+ if (*loop == CIL_TRUE) {
+ cil_tree_log(node, CIL_ERR, " blockinherit");
+ }
+ return SEPOL_ERR;
+ }
+ }
+ }
+
+ for (node = node->cl_head; node; node = node->next) {
+ rc = cil_check_inheritances(node, max, count, stack, loop);
+ if (rc != SEPOL_OK) {
+ return SEPOL_ERR;
+ }
+ }
+
+ return SEPOL_OK;
+}
+
+static int cil_check_for_bad_inheritance(struct cil_tree_node *node)
+{
+ unsigned num_actual, max;
+ unsigned num_potential = 0;
+ unsigned loop = CIL_FALSE;
+ struct cil_stack *stack;
+ int rc;
+
+ num_actual = cil_count_actual(node);
+
+ max = num_actual * CIL_DEGENERATE_INHERITANCE_GROWTH;
+ if (max < CIL_DEGENERATE_INHERITANCE_MINIMUM) {
+ max = CIL_DEGENERATE_INHERITANCE_MINIMUM;
+ }
+
+ cil_stack_init(&stack);
+ rc = cil_check_inheritances(node, max, &num_potential, stack, &loop);
+ cil_stack_destroy(&stack);
+
+ return rc;
+}
+
int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
{
int rc = SEPOL_OK;
struct cil_args_resolve *args = extra_args;
enum cil_pass pass = 0;
- struct cil_list *ins;
if (node == NULL || args == NULL) {
goto exit;
}
- ins = args->in_list;
pass = args->pass;
switch (pass) {
@@ -3418,11 +3620,14 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
rc = cil_resolve_tunif(node, args);
}
break;
- case CIL_PASS_IN:
+ case CIL_PASS_IN_BEFORE:
if (node->flavor == CIL_IN) {
// due to ordering issues, in statements are just gathered here and
// resolved together in cil_resolve_in_list once all are found
- cil_list_prepend(ins, CIL_NODE, node);
+ struct cil_in *in = node->data;
+ if (in->is_after == CIL_FALSE) {
+ cil_list_prepend(args->in_list_before, CIL_NODE, node);
+ }
}
break;
case CIL_PASS_BLKIN_LINK:
@@ -3440,19 +3645,24 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
rc = cil_resolve_blockabstract(node, args);
}
break;
- case CIL_PASS_MACRO:
- if (node->flavor == CIL_CALL && args->macro != NULL) {
- rc = cil_resolve_call1(node, args);
+ case CIL_PASS_IN_AFTER:
+ if (node->flavor == CIL_IN) {
+ // due to ordering issues, in statements are just gathered here and
+ // resolved together in cil_resolve_in_list once all are found
+ struct cil_in *in = node->data;
+ if (in->is_after == CIL_TRUE) {
+ cil_list_prepend(args->in_list_after, CIL_NODE, node);
+ }
}
break;
case CIL_PASS_CALL1:
- if (node->flavor == CIL_CALL) {
- rc = cil_resolve_call1(node, args);
+ if (node->flavor == CIL_CALL && args->macro == NULL) {
+ rc = cil_resolve_call(node, args);
}
break;
case CIL_PASS_CALL2:
- if (node->flavor == CIL_CALL) {
- rc = cil_resolve_call2(node, args);
+ if (node->flavor == CIL_CALL && args->macro == NULL) {
+ rc = cil_resolve_call_args(node, args);
}
break;
case CIL_PASS_ALIAS1:
@@ -3685,65 +3895,78 @@ exit:
int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
{
- int rc = SEPOL_ERR;
+ int rc = SEPOL_OK;
struct cil_args_resolve *args = extra_args;
enum cil_pass pass = args->pass;
- struct cil_tree_node *optstack = args->optstack;
- struct cil_tree_node *boolif = args->boolif;
- struct cil_tree_node *blockstack = args->blockstack;
+ struct cil_tree_node *block = args->block;
struct cil_tree_node *macro = args->macro;
+ struct cil_tree_node *optional = args->optional;
+ struct cil_tree_node *boolif = args->boolif;
if (node == NULL) {
goto exit;
}
- if (optstack != NULL) {
- if (node->flavor == CIL_TUNABLE || node->flavor == CIL_MACRO) {
- /* tuanbles and macros are not allowed in optionals*/
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node));
+ if (block != NULL) {
+ if (node->flavor == CIL_CAT ||
+ node->flavor == CIL_SENS) {
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in block", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
}
- if (blockstack != NULL) {
- if (node->flavor == CIL_CAT || node->flavor == CIL_SENS) {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in blocks", cil_node_to_string(node));
+ if (macro != NULL) {
+ if (node->flavor == CIL_TUNABLE ||
+ node->flavor == CIL_IN ||
+ node->flavor == CIL_BLOCK ||
+ node->flavor == CIL_BLOCKINHERIT ||
+ node->flavor == CIL_BLOCKABSTRACT ||
+ node->flavor == CIL_MACRO) {
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in macro", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
}
- if (macro != NULL) {
- if (node->flavor == CIL_BLOCKINHERIT ||
+ if (optional != NULL) {
+ if (node->flavor == CIL_TUNABLE ||
+ node->flavor == CIL_IN ||
node->flavor == CIL_BLOCK ||
node->flavor == CIL_BLOCKABSTRACT ||
- node->flavor == CIL_MACRO) {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in macros", cil_node_to_string(node));
+ node->flavor == CIL_MACRO) {
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in optional", cil_node_to_string(node));
rc = SEPOL_ERR;
goto exit;
}
}
if (boolif != NULL) {
- if (!(node->flavor == CIL_CONDBLOCK ||
- node->flavor == CIL_AVRULE ||
- node->flavor == CIL_TYPE_RULE ||
- node->flavor == CIL_CALL ||
- node->flavor == CIL_TUNABLEIF ||
- node->flavor == CIL_NAMETYPETRANSITION)) {
+ if (node->flavor != CIL_TUNABLEIF &&
+ node->flavor != CIL_CALL &&
+ node->flavor != CIL_CONDBLOCK &&
+ node->flavor != CIL_AVRULE &&
+ node->flavor != CIL_TYPE_RULE &&
+ node->flavor != CIL_NAMETYPETRANSITION) {
+ rc = SEPOL_ERR;
+ } else if (node->flavor == CIL_AVRULE) {
+ struct cil_avrule *rule = node->data;
+ if (rule->rule_kind == CIL_AVRULE_NEVERALLOW) {
+ rc = SEPOL_ERR;
+ }
+ }
+ if (rc == SEPOL_ERR) {
if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif)", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", cil_node_to_string(node));
} else {
- cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs", cil_node_to_string(node));
+ cil_tree_log(node, CIL_ERR, "%s is not allowed in booleanif", cil_node_to_string(node));
}
- rc = SEPOL_ERR;
goto exit;
}
}
if (node->flavor == CIL_MACRO) {
- if (pass != CIL_PASS_TIF && pass != CIL_PASS_MACRO) {
+ if (pass > CIL_PASS_IN_AFTER) {
*finished = CIL_TREE_SKIP_HEAD;
rc = SEPOL_OK;
goto exit;
@@ -3758,22 +3981,16 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished
rc = __cil_resolve_ast_node(node, extra_args);
if (rc == SEPOL_ENOENT) {
- enum cil_log_level lvl = CIL_ERR;
-
- if (optstack != NULL) {
- lvl = CIL_INFO;
-
- struct cil_optional *opt = (struct cil_optional *)optstack->data;
- struct cil_tree_node *opt_node = opt->datum.nodes->head->data;
- /* disable an optional if something failed to resolve */
- opt->enabled = CIL_FALSE;
- cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node));
- cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name);
+ if (optional == NULL) {
+ cil_tree_log(node, CIL_ERR, "Failed to resolve %s statement", cil_node_to_string(node));
+ } else {
+ if (!args->disabled_optional) {
+ args->disabled_optional = optional;
+ }
+ cil_tree_log(node, CIL_INFO, "Failed to resolve %s statement", cil_node_to_string(node));
+ cil_tree_log(optional, CIL_INFO, "Disabling optional '%s'", DATUM(optional->data)->name);
rc = SEPOL_OK;
- goto exit;
}
-
- cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node));
goto exit;
}
@@ -3787,43 +4004,22 @@ int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *ex
{
int rc = SEPOL_ERR;
struct cil_args_resolve *args = extra_args;
- struct cil_tree_node *optstack = NULL;
struct cil_tree_node *parent = NULL;
- struct cil_tree_node *blockstack = NULL;
- struct cil_tree_node *new = NULL;
if (current == NULL || extra_args == NULL) {
goto exit;
}
- optstack = args->optstack;
parent = current->parent;
- blockstack = args->blockstack;
- if (parent->flavor == CIL_OPTIONAL || parent->flavor == CIL_BLOCK) {
- /* push this node onto a stack */
- cil_tree_node_init(&new);
-
- new->data = parent->data;
- new->flavor = parent->flavor;
-
- if (parent->flavor == CIL_OPTIONAL) {
- if (optstack != NULL) {
- optstack->parent = new;
- new->cl_head = optstack;
- }
- args->optstack = new;
- } else if (parent->flavor == CIL_BLOCK) {
- if (blockstack != NULL) {
- blockstack->parent = new;
- new->cl_head = blockstack;
- }
- args->blockstack = new;
- }
- } else if (parent->flavor == CIL_BOOLEANIF) {
- args->boolif = parent;
+ if (parent->flavor == CIL_BLOCK) {
+ args->block = parent;
} else if (parent->flavor == CIL_MACRO) {
args->macro = parent;
+ } else if (parent->flavor == CIL_OPTIONAL) {
+ args->optional = parent;
+ } else if (parent->flavor == CIL_BOOLEANIF) {
+ args->boolif = parent;
}
return SEPOL_OK;
@@ -3838,7 +4034,6 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext
int rc = SEPOL_ERR;
struct cil_args_resolve *args = extra_args;
struct cil_tree_node *parent = NULL;
- struct cil_tree_node *blockstack = NULL;
if (current == NULL || extra_args == NULL) {
goto exit;
@@ -3846,33 +4041,35 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext
parent = current->parent;
- if (parent->flavor == CIL_MACRO) {
+ if (parent->flavor == CIL_BLOCK) {
+ struct cil_tree_node *n = parent->parent;
+ args->block = NULL;
+ while (n && n->flavor != CIL_ROOT) {
+ if (n->flavor == CIL_BLOCK) {
+ args->block = n;
+ break;
+ }
+ n = n->parent;
+ }
+ } else if (parent->flavor == CIL_MACRO) {
args->macro = NULL;
} else if (parent->flavor == CIL_OPTIONAL) {
- struct cil_tree_node *optstack;
-
- if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) {
+ struct cil_tree_node *n = parent->parent;
+ if (args->disabled_optional == parent) {
*(args->changed) = CIL_TRUE;
- cil_tree_children_destroy(parent);
+ cil_list_append(args->to_destroy, CIL_NODE, parent);
+ args->disabled_optional = NULL;
}
-
- /* pop off the stack */
- optstack = args->optstack;
- args->optstack = optstack->cl_head;
- if (optstack->cl_head) {
- optstack->cl_head->parent = NULL;
+ args->optional = NULL;
+ while (n && n->flavor != CIL_ROOT) {
+ if (n->flavor == CIL_OPTIONAL) {
+ args->optional = n;
+ break;
+ }
+ n = n->parent;
}
- free(optstack);
} else if (parent->flavor == CIL_BOOLEANIF) {
args->boolif = NULL;
- } else if (parent->flavor == CIL_BLOCK) {
- /* pop off the stack */
- blockstack = args->blockstack;
- args->blockstack = blockstack->cl_head;
- if (blockstack->cl_head) {
- blockstack->cl_head->parent = NULL;
- }
- free(blockstack);
}
return SEPOL_OK;
@@ -3881,16 +4078,6 @@ exit:
return rc;
}
-static void cil_destroy_tree_node_stack(struct cil_tree_node *curr)
-{
- struct cil_tree_node *next;
- while (curr != NULL) {
- next = curr->cl_head;
- free(curr);
- curr = next;
- }
-}
-
int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
{
int rc = SEPOL_ERR;
@@ -3905,24 +4092,30 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
extra_args.db = db;
extra_args.pass = pass;
extra_args.changed = &changed;
- extra_args.last_resolved_name = NULL;
- extra_args.optstack = NULL;
- extra_args.boolif= NULL;
+ extra_args.block = NULL;
extra_args.macro = NULL;
+ extra_args.optional = NULL;
+ extra_args.disabled_optional = NULL;
+ extra_args.boolif= NULL;
extra_args.sidorder_lists = NULL;
extra_args.classorder_lists = NULL;
extra_args.unordered_classorder_lists = NULL;
extra_args.catorder_lists = NULL;
extra_args.sensitivityorder_lists = NULL;
- extra_args.in_list = NULL;
- extra_args.blockstack = NULL;
+ extra_args.in_list_before = NULL;
+ extra_args.in_list_after = NULL;
+ extra_args.abstract_blocks = NULL;
+ cil_list_init(&extra_args.to_destroy, CIL_NODE);
cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
- cil_list_init(&extra_args.in_list, CIL_IN);
+ cil_list_init(&extra_args.in_list_before, CIL_IN);
+ cil_list_init(&extra_args.in_list_after, CIL_IN);
+ cil_list_init(&extra_args.abstract_blocks, CIL_NODE);
+
for (pass = CIL_PASS_TIF; pass < CIL_PASS_NUM; pass++) {
extra_args.pass = pass;
rc = cil_tree_walk(current, __cil_resolve_ast_node_helper, __cil_resolve_ast_first_child_helper, __cil_resolve_ast_last_child_helper, &extra_args);
@@ -3931,12 +4124,33 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
goto exit;
}
- if (pass == CIL_PASS_IN) {
- rc = cil_resolve_in_list(&extra_args);
+ if (pass == CIL_PASS_IN_BEFORE) {
+ rc = cil_resolve_in_list(extra_args.in_list_before, &extra_args);
if (rc != SEPOL_OK) {
goto exit;
}
- cil_list_destroy(&extra_args.in_list, CIL_FALSE);
+ cil_list_destroy(&extra_args.in_list_before, CIL_FALSE);
+ } else if (pass == CIL_PASS_IN_AFTER) {
+ rc = cil_resolve_in_list(extra_args.in_list_after, &extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ cil_list_destroy(&extra_args.in_list_after, CIL_FALSE);
+ }
+
+ if (pass == CIL_PASS_BLKABS) {
+ struct cil_list_item *item;
+ cil_list_for_each(item, extra_args.abstract_blocks) {
+ cil_mark_subtree_abstract(item->data);
+ }
+ }
+
+ if (pass == CIL_PASS_BLKIN_LINK) {
+ rc = cil_check_for_bad_inheritance(current);
+ if (rc != SEPOL_OK) {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
}
if (pass == CIL_PASS_MISC1) {
@@ -3983,46 +4197,54 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
}
}
- if (changed && (pass > CIL_PASS_CALL1)) {
- /* Need to re-resolve because an optional was disabled that contained
- * one or more declarations. We only need to reset to the call1 pass
- * because things done in the preceding passes aren't allowed in
- * optionals, and thus can't be disabled.
- * Note: set pass to CIL_PASS_CALL1 because the pass++ will increment
- * it to CIL_PASS_CALL2
- */
- cil_log(CIL_INFO, "Resetting declarations\n");
-
- if (pass >= CIL_PASS_MISC1) {
- __cil_ordered_lists_reset(&extra_args.sidorder_lists);
- __cil_ordered_lists_reset(&extra_args.classorder_lists);
- __cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
- __cil_ordered_lists_reset(&extra_args.catorder_lists);
- __cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
- cil_list_destroy(&db->sidorder, CIL_FALSE);
- cil_list_destroy(&db->classorder, CIL_FALSE);
- cil_list_destroy(&db->catorder, CIL_FALSE);
- cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
- }
+ if (changed) {
+ struct cil_list_item *item;
+ if (pass > CIL_PASS_CALL1) {
+ int has_decls = CIL_FALSE;
- pass = CIL_PASS_CALL1;
+ cil_list_for_each(item, extra_args.to_destroy) {
+ has_decls = cil_tree_subtree_has_decl(item->data);
+ if (has_decls) {
+ break;
+ }
+ }
- rc = cil_reset_ast(current);
- if (rc != SEPOL_OK) {
- cil_log(CIL_ERR, "Failed to reset declarations\n");
- goto exit;
- }
- }
+ if (has_decls) {
+ /* Need to re-resolve because an optional was disabled that
+ * contained one or more declarations.
+ * Everything that needs to be reset comes after the
+ * CIL_PASS_CALL2 pass. We set pass to CIL_PASS_CALL1 because
+ * the pass++ will increment it to CIL_PASS_CALL2
+ */
+ cil_log(CIL_INFO, "Resetting declarations\n");
+
+ if (pass >= CIL_PASS_MISC1) {
+ __cil_ordered_lists_reset(&extra_args.sidorder_lists);
+ __cil_ordered_lists_reset(&extra_args.classorder_lists);
+ __cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
+ __cil_ordered_lists_reset(&extra_args.catorder_lists);
+ __cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
+ cil_list_destroy(&db->sidorder, CIL_FALSE);
+ cil_list_destroy(&db->classorder, CIL_FALSE);
+ cil_list_destroy(&db->catorder, CIL_FALSE);
+ cil_list_destroy(&db->sensitivityorder, CIL_FALSE);
+ }
- /* reset the arguments */
- changed = 0;
- while (extra_args.optstack != NULL) {
- cil_destroy_tree_node_stack(extra_args.optstack);
- extra_args.optstack = NULL;
- }
- while (extra_args.blockstack!= NULL) {
- cil_destroy_tree_node_stack(extra_args.blockstack);
- extra_args.blockstack = NULL;
+ pass = CIL_PASS_CALL1;
+
+ rc = cil_reset_ast(current);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to reset declarations\n");
+ goto exit;
+ }
+ }
+ }
+ cil_list_for_each(item, extra_args.to_destroy) {
+ cil_tree_children_destroy(item->data);
+ }
+ cil_list_destroy(&extra_args.to_destroy, CIL_FALSE);
+ cil_list_init(&extra_args.to_destroy, CIL_NODE);
+ changed = 0;
}
}
@@ -4033,14 +4255,15 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
rc = SEPOL_OK;
exit:
- cil_destroy_tree_node_stack(extra_args.optstack);
- cil_destroy_tree_node_stack(extra_args.blockstack);
__cil_ordered_lists_destroy(&extra_args.sidorder_lists);
__cil_ordered_lists_destroy(&extra_args.classorder_lists);
__cil_ordered_lists_destroy(&extra_args.catorder_lists);
__cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists);
__cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists);
- cil_list_destroy(&extra_args.in_list, CIL_FALSE);
+ cil_list_destroy(&extra_args.to_destroy, CIL_FALSE);
+ cil_list_destroy(&extra_args.in_list_before, CIL_FALSE);
+ cil_list_destroy(&extra_args.in_list_after, CIL_FALSE);
+ cil_list_destroy(&extra_args.abstract_blocks, CIL_FALSE);
return rc;
}
@@ -4062,16 +4285,20 @@ static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *nam
case CIL_ROOT:
goto exit;
break;
- case CIL_BLOCK:
- symtab = &((struct cil_block*)node->data)->symtab[sym_index];
- rc = cil_symtab_get_datum(symtab, name, datum);
+ case CIL_BLOCK: {
+ struct cil_block *block = node->data;
+ if (!block->is_abstract) {
+ symtab = &block->symtab[sym_index];
+ rc = cil_symtab_get_datum(symtab, name, datum);
+ }
+ }
break;
case CIL_BLOCKINHERIT: {
struct cil_blockinherit *inherit = node->data;
rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum);
if (rc != SEPOL_OK) {
/* Continue search in original block's parent */
- rc = __cil_resolve_name_with_parents(NODE(inherit->block), name, sym_index, datum);
+ rc = __cil_resolve_name_with_parents(NODE(inherit->block)->parent, name, sym_index, datum);
goto exit;
}
}
@@ -4084,10 +4311,18 @@ static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *nam
break;
case CIL_CALL: {
struct cil_call *call = node->data;
- rc = cil_resolve_name_call_args(call, name, sym_index, datum);
- if (rc != SEPOL_OK) {
- /* Continue search in macro's parent */
- rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum);
+ struct cil_macro *macro = call->macro;
+ symtab = &macro->symtab[sym_index];
+ rc = cil_symtab_get_datum(symtab, name, datum);
+ if (rc == SEPOL_OK) {
+ /* If the name was declared in the macro, just look on the call side */
+ rc = SEPOL_ERR;
+ } else {
+ rc = cil_resolve_name_call_args(call, name, sym_index, datum);
+ if (rc != SEPOL_OK) {
+ /* Continue search in macro's parent */
+ rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum);
+ }
}
}
break;
@@ -4159,8 +4394,8 @@ int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, en
*datum = NULL;
- if (strchr(name,'.') == NULL) {
- /* No '.' in name */
+ if (db->qualified_names || strchr(name,'.') == NULL) {
+ /* Using qualified names or No '.' in name */
rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum);
if (rc != SEPOL_OK) {
goto exit;
@@ -4211,9 +4446,6 @@ int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, en
if (node->flavor == CIL_MACRO) {
struct cil_macro *macro = node->data;
symtab = &macro->symtab[sym_index];
- } else {
- /* optional */
- symtab = (*datum)->symtab;
}
}
current = next;
@@ -4234,7 +4466,5 @@ exit:
*datum = NULL;
}
- args->last_resolved_name = name;
-
return rc;
}
diff --git a/libsepol/cil/src/cil_stack.c b/libsepol/cil/src/cil_stack.c
index bbfb961a..70a77bc1 100644
--- a/libsepol/cil/src/cil_stack.c
+++ b/libsepol/cil/src/cil_stack.c
@@ -67,6 +67,11 @@ int cil_stack_is_empty(struct cil_stack *stack)
return (stack->pos == -1);
}
+int cil_stack_number_of_items(struct cil_stack *stack)
+{
+ return stack->pos + 1;
+}
+
void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data)
{
stack->pos++;
diff --git a/libsepol/cil/src/cil_stack.h b/libsepol/cil/src/cil_stack.h
index b78535ac..0e3eff66 100644
--- a/libsepol/cil/src/cil_stack.h
+++ b/libsepol/cil/src/cil_stack.h
@@ -52,6 +52,7 @@ void cil_stack_destroy(struct cil_stack **stack);
void cil_stack_empty(struct cil_stack *stack);
int cil_stack_is_empty(struct cil_stack *stack);
+int cil_stack_number_of_items(struct cil_stack *stack);
void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data);
struct cil_stack_item *cil_stack_pop(struct cil_stack *stack);
diff --git a/libsepol/cil/src/cil_strpool.c b/libsepol/cil/src/cil_strpool.c
index 2598bbf3..e32ee4e9 100644
--- a/libsepol/cil/src/cil_strpool.c
+++ b/libsepol/cil/src/cil_strpool.c
@@ -47,14 +47,13 @@ static hashtab_t cil_strpool_tab = NULL;
static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key)
{
- const char *p, *keyp;
+ const char *p;
size_t size;
unsigned int val;
val = 0;
- keyp = (const char*)key;
- size = strlen(keyp);
- for (p = keyp; ((size_t) (p - keyp)) < size; p++)
+ size = strlen(key);
+ for (p = key; ((size_t) (p - key)) < size; p++)
val =
(val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val & (h->size - 1);
@@ -62,9 +61,7 @@ static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key)
static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2)
{
- const char *keyp1 = (const char*)key1;
- const char *keyp2 = (const char*)key2;
- return strcmp(keyp1, keyp2);
+ return strcmp(key1, key2);
}
char *cil_strpool_add(const char *str)
@@ -73,11 +70,12 @@ char *cil_strpool_add(const char *str)
pthread_mutex_lock(&cil_strpool_mutex);
- strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str);
+ strpool_ref = hashtab_search(cil_strpool_tab, str);
if (strpool_ref == NULL) {
+ int rc;
strpool_ref = cil_malloc(sizeof(*strpool_ref));
strpool_ref->str = cil_strdup(str);
- int rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref);
+ rc = hashtab_insert(cil_strpool_tab, strpool_ref->str, strpool_ref);
if (rc != SEPOL_OK) {
pthread_mutex_unlock(&cil_strpool_mutex);
cil_log(CIL_ERR, "Failed to allocate memory\n");
diff --git a/libsepol/cil/src/cil_symtab.c b/libsepol/cil/src/cil_symtab.c
index 2970b863..c1951560 100644
--- a/libsepol/cil/src/cil_symtab.c
+++ b/libsepol/cil/src/cil_symtab.c
@@ -92,10 +92,11 @@ int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_dat
datum->name = key;
datum->fqn = key;
datum->symtab = symtab;
- cil_list_append(datum->nodes, CIL_NODE, node);
- } else if (rc == SEPOL_EEXIST) {
- cil_list_append(datum->nodes, CIL_NODE, node);
- } else {
+ symtab->nprim++;
+ if (node) {
+ cil_list_append(datum->nodes, CIL_NODE, node);
+ }
+ } else if (rc != SEPOL_EEXIST) {
cil_symtab_error("Failed to insert datum into hashtab\n");
}
@@ -111,6 +112,7 @@ void cil_symtab_remove_datum(struct cil_symtab_datum *datum)
}
hashtab_remove(symtab->table, datum->name, NULL, NULL);
+ symtab->nprim--;
datum->symtab = NULL;
}
diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c
index b1cbda91..aafc9dee 100644
--- a/libsepol/cil/src/cil_tree.c
+++ b/libsepol/cil/src/cil_tree.c
@@ -41,15 +41,6 @@
#include "cil_parser.h"
#include "cil_strpool.h"
-void cil_tree_print_perms_list(struct cil_tree_node *current_perm);
-void cil_tree_print_classperms(struct cil_classperms *cp);
-void cil_tree_print_level(struct cil_level *level);
-void cil_tree_print_levelrange(struct cil_levelrange *lvlrange);
-void cil_tree_print_context(struct cil_context *context);
-void cil_tree_print_expr_tree(struct cil_tree_node *expr_root);
-void cil_tree_print_constrain(struct cil_constrain *cons);
-void cil_tree_print_node(struct cil_tree_node *node);
-
__attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_error(const char* msg, ...)
{
va_list ap;
@@ -59,28 +50,38 @@ __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_e
exit(1);
}
-struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil)
+struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path)
{
+ int rc;
+
if (!node) {
- return NULL;
+ goto exit;
}
node = node->parent;
while (node) {
if (node->flavor == CIL_NODE && node->data == NULL) {
- if (node->cl_head->data == CIL_KEY_SRC_INFO) {
+ if (node->cl_head && node->cl_head->data == CIL_KEY_SRC_INFO) {
+ if (!node->cl_head->next || !node->cl_head->next->next || !node->cl_head->next->next->next) {
+ goto exit;
+ }
/* Parse Tree */
- *path = node->cl_head->next->next->data;
- *is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL);
+ *info_kind = node->cl_head->next->data;
+ rc = cil_string_to_uint32(node->cl_head->next->next->data, hll_line, 10);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ *path = node->cl_head->next->next->next->data;
return node;
}
node = node->parent;
} else if (node->flavor == CIL_SRC_INFO) {
/* AST */
struct cil_src_info *info = node->data;
+ *info_kind = info->kind;
+ *hll_line = info->hll_line;
*path = info->path;
- *is_cil = info->is_cil;
return node;
} else {
if (node->flavor == CIL_CALL) {
@@ -95,17 +96,22 @@ struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **
}
}
+exit:
+ *info_kind = NULL;
+ *hll_line = 0;
+ *path = NULL;
return NULL;
}
char *cil_tree_get_cil_path(struct cil_tree_node *node)
{
- char *path = NULL;
- int is_cil;
+ char *info_kind;
+ uint32_t hll_line;
+ char *path;
while (node) {
- node = cil_tree_get_next_path(node, &path, &is_cil);
- if (node && is_cil) {
+ node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path);
+ if (node && info_kind == CIL_KEY_SRC_CIL) {
return path;
}
}
@@ -123,28 +129,51 @@ __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *n
if (node) {
char *path = NULL;
- int is_cil;
- unsigned hll_line = node->hll_line;
+ uint32_t hll_offset = node->hll_offset;
path = cil_tree_get_cil_path(node);
if (path != NULL) {
- cil_log(lvl, " at %s:%d", path, node->line);
+ cil_log(lvl, " at %s:%u", path, node->line);
}
while (node) {
- node = cil_tree_get_next_path(node, &path, &is_cil);
- if (node && !is_cil) {
- cil_log(lvl," from %s:%d", path, hll_line);
- path = NULL;
- hll_line = node->hll_line;
- }
+ do {
+ char *info_kind;
+ uint32_t hll_line;
+
+ node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path);
+ if (!node || info_kind == CIL_KEY_SRC_CIL) {
+ break;
+ }
+ if (info_kind == CIL_KEY_SRC_HLL_LMS) {
+ hll_line += hll_offset - node->hll_offset - 1;
+ }
+
+ cil_log(lvl," from %s:%u", path, hll_line);
+ } while (1);
}
}
cil_log(lvl,"\n");
}
+int cil_tree_subtree_has_decl(struct cil_tree_node *node)
+{
+ while (node) {
+ if (node->flavor >= CIL_MIN_DECLARATIVE) {
+ return CIL_TRUE;
+ }
+ if (node->cl_head != NULL) {
+ if (cil_tree_subtree_has_decl(node->cl_head))
+ return CIL_TRUE;
+ }
+ node = node->next;
+ }
+
+ return CIL_FALSE;
+}
+
int cil_tree_init(struct cil_tree **tree)
{
struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree));
@@ -175,34 +204,21 @@ void cil_tree_subtree_destroy(struct cil_tree_node *node)
void cil_tree_children_destroy(struct cil_tree_node *node)
{
- struct cil_tree_node *start_node = node;
- struct cil_tree_node *next = NULL;
+ struct cil_tree_node *curr, *next;
- if (node == NULL) {
+ if (!node) {
return;
}
- if (node->cl_head != NULL) {
- node = node->cl_head;
- }
-
- while (node != start_node) {
- if (node->cl_head != NULL){
- next = node->cl_head;
- } else {
- if (node->next == NULL) {
- next = node->parent;
- if (node->parent != NULL) {
- node->parent->cl_head = NULL;
- }
- cil_tree_node_destroy(&node);
- } else {
- next = node->next;
- cil_tree_node_destroy(&node);
- }
- }
- node = next;
+ curr = node->cl_head;
+ while (curr) {
+ next = curr->next;
+ cil_tree_children_destroy(curr);
+ cil_tree_node_destroy(&curr);
+ curr = next;
}
+ node->cl_head = NULL;
+ node->cl_tail = NULL;
}
void cil_tree_node_init(struct cil_tree_node **node)
@@ -215,7 +231,7 @@ void cil_tree_node_init(struct cil_tree_node **node)
new_node->next = NULL;
new_node->flavor = CIL_ROOT;
new_node->line = 0;
- new_node->hll_line = 0;
+ new_node->hll_offset = 0;
*node = new_node;
}
@@ -328,1466 +344,3 @@ int cil_tree_walk(struct cil_tree_node *node,
return SEPOL_OK;
}
-
-
-/* Copied from cil_policy.c, but changed to prefix -- Need to refactor */
-static int cil_expr_to_string(struct cil_list *expr, char **out)
-{
- int rc = SEPOL_ERR;
- struct cil_list_item *curr;
- char *stack[COND_EXPR_MAXDEPTH] = {};
- int pos = 0;
-
- cil_list_for_each(curr, expr) {
- if (pos >= COND_EXPR_MAXDEPTH) {
- rc = SEPOL_ERR;
- goto exit;
- }
- switch (curr->flavor) {
- case CIL_LIST:
- rc = cil_expr_to_string(curr->data, &stack[pos]);
- if (rc != SEPOL_OK) {
- goto exit;
- }
- pos++;
- break;
- case CIL_STRING:
- stack[pos] = curr->data;
- pos++;
- break;
- case CIL_DATUM:
- stack[pos] = ((struct cil_symtab_datum *)curr->data)->name;
- pos++;
- break;
- case CIL_OP: {
- int len;
- char *expr_str;
- enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data);
- char *op_str = NULL;
-
- if (pos == 0) {
- rc = SEPOL_ERR;
- goto exit;
- }
- switch (op_flavor) {
- case CIL_AND:
- op_str = CIL_KEY_AND;
- break;
- case CIL_OR:
- op_str = CIL_KEY_OR;
- break;
- case CIL_NOT:
- op_str = CIL_KEY_NOT;
- break;
- case CIL_ALL:
- op_str = CIL_KEY_ALL;
- break;
- case CIL_EQ:
- op_str = CIL_KEY_EQ;
- break;
- case CIL_NEQ:
- op_str = CIL_KEY_NEQ;
- break;
- case CIL_XOR:
- op_str = CIL_KEY_XOR;
- break;
- case CIL_RANGE:
- op_str = CIL_KEY_RANGE;
- break;
- case CIL_CONS_DOM:
- op_str = CIL_KEY_CONS_DOM;
- break;
- case CIL_CONS_DOMBY:
- op_str = CIL_KEY_CONS_DOMBY;
- break;
- case CIL_CONS_INCOMP:
- op_str = CIL_KEY_CONS_INCOMP;
- break;
- default:
- cil_log(CIL_ERR, "Unknown operator in expression\n");
- goto exit;
- break;
- }
- if (op_flavor == CIL_NOT) {
- len = strlen(stack[pos-1]) + strlen(op_str) + 4;
- expr_str = cil_malloc(len);
- snprintf(expr_str, len, "(%s %s)", op_str, stack[pos-1]);
- free(stack[pos-1]);
- stack[pos-1] = NULL;
- pos--;
- } else {
- if (pos < 2) {
- rc = SEPOL_ERR;
- goto exit;
- }
- len = strlen(stack[pos-1]) + strlen(stack[pos-2]) + strlen(op_str) + 5;
- expr_str = cil_malloc(len);
- snprintf(expr_str, len, "(%s %s %s)", op_str, stack[pos-1], stack[pos-2]);
- free(stack[pos-2]);
- free(stack[pos-1]);
- stack[pos-2] = NULL;
- stack[pos-1] = NULL;
- pos -= 2;
- }
- stack[pos] = expr_str;
- pos++;
- break;
- }
- case CIL_CONS_OPERAND: {
- enum cil_flavor operand_flavor = *((enum cil_flavor *)curr->data);
- char *operand_str = NULL;
- switch (operand_flavor) {
- case CIL_CONS_U1:
- operand_str = CIL_KEY_CONS_U1;
- break;
- case CIL_CONS_U2:
- operand_str = CIL_KEY_CONS_U2;
- break;
- case CIL_CONS_U3:
- operand_str = CIL_KEY_CONS_U3;
- break;
- case CIL_CONS_T1:
- operand_str = CIL_KEY_CONS_T1;
- break;
- case CIL_CONS_T2:
- operand_str = CIL_KEY_CONS_T2;
- break;
- case CIL_CONS_T3:
- operand_str = CIL_KEY_CONS_T3;
- break;
- case CIL_CONS_R1:
- operand_str = CIL_KEY_CONS_R1;
- break;
- case CIL_CONS_R2:
- operand_str = CIL_KEY_CONS_R2;
- break;
- case CIL_CONS_R3:
- operand_str = CIL_KEY_CONS_R3;
- break;
- case CIL_CONS_L1:
- operand_str = CIL_KEY_CONS_L1;
- break;
- case CIL_CONS_L2:
- operand_str = CIL_KEY_CONS_L2;
- break;
- case CIL_CONS_H1:
- operand_str = CIL_KEY_CONS_H1;
- break;
- case CIL_CONS_H2:
- operand_str = CIL_KEY_CONS_H2;
- break;
- default:
- cil_log(CIL_ERR, "Unknown operand in expression\n");
- goto exit;
- break;
- }
- stack[pos] = operand_str;
- pos++;
- break;
- }
- default:
- cil_log(CIL_ERR, "Unknown flavor in expression\n");
- goto exit;
- break;
- }
- }
-
- *out = stack[0];
-
- return SEPOL_OK;
-
-exit:
- return rc;
-}
-
-void cil_tree_print_expr(struct cil_list *datum_expr, struct cil_list *str_expr)
-{
- char *expr_str;
- int rc;
-
- cil_log(CIL_INFO, "(");
-
- if (datum_expr != NULL) {
- rc = cil_expr_to_string(datum_expr, &expr_str);
- } else {
- rc = cil_expr_to_string(str_expr, &expr_str);
- }
- if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "ERROR)");
- return;
- }
- cil_log(CIL_INFO, "%s)", expr_str);
- free(expr_str);
-}
-
-void cil_tree_print_perms_list(struct cil_tree_node *current_perm)
-{
- while (current_perm != NULL) {
- if (current_perm->flavor == CIL_PERM) {
- cil_log(CIL_INFO, " %s", ((struct cil_perm *)current_perm->data)->datum.name);
- } else if (current_perm->flavor == CIL_MAP_PERM) {
- cil_log(CIL_INFO, " %s", ((struct cil_perm*)current_perm->data)->datum.name);
- } else {
- cil_log(CIL_INFO, "\n\n perms list contained unexpected data type: %d\n", current_perm->flavor);
- break;
- }
- current_perm = current_perm->next;
- }
-}
-
-void cil_tree_print_cats(struct cil_cats *cats)
-{
- cil_tree_print_expr(cats->datum_expr, cats->str_expr);
-}
-
-void cil_tree_print_perm_strs(struct cil_list *perm_strs)
-{
- struct cil_list_item *curr;
-
- if (perm_strs == NULL) {
- return;
- }
-
- cil_log(CIL_INFO, " (");
-
- cil_list_for_each(curr, perm_strs) {
- cil_log(CIL_INFO, " %s", (char*)curr->data);
- }
-
- cil_log(CIL_INFO, " )");
-}
-
-
-void cil_tree_print_classperms(struct cil_classperms *cp)
-{
- if (cp == NULL) {
- return;
- }
-
- cil_log(CIL_INFO, " class: %s", cp->class_str);
- cil_log(CIL_INFO, ", perm_strs:");
- cil_tree_print_perm_strs(cp->perm_strs);
-}
-
-void cil_tree_print_classperms_set(struct cil_classperms_set *cp_set)
-{
- if (cp_set == NULL) {
- return;
- }
-
- cil_log(CIL_INFO, " %s", cp_set->set_str);
-}
-
-void cil_tree_print_classperms_list(struct cil_list *cp_list)
-{
- struct cil_list_item *i;
-
- if (cp_list == NULL) {
- return;
- }
-
- cil_list_for_each(i, cp_list) {
- if (i->flavor == CIL_CLASSPERMS) {
- cil_tree_print_classperms(i->data);
- } else {
- cil_tree_print_classperms_set(i->data);
- }
- }
-}
-
-void cil_tree_print_level(struct cil_level *level)
-{
- if (level->sens != NULL) {
- cil_log(CIL_INFO, " %s", level->sens->datum.name);
- } else if (level->sens_str != NULL) {
- cil_log(CIL_INFO, " %s", level->sens_str);
- }
-
- cil_tree_print_cats(level->cats);
-
- return;
-}
-
-void cil_tree_print_levelrange(struct cil_levelrange *lvlrange)
-{
- cil_log(CIL_INFO, " (");
- if (lvlrange->low != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_level(lvlrange->low);
- cil_log(CIL_INFO, " )");
- } else if (lvlrange->low_str != NULL) {
- cil_log(CIL_INFO, " %s", lvlrange->low_str);
- }
-
- if (lvlrange->high != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_level(lvlrange->high);
- cil_log(CIL_INFO, " )");
- } else if (lvlrange->high_str != NULL) {
- cil_log(CIL_INFO, " %s", lvlrange->high_str);
- }
- cil_log(CIL_INFO, " )");
-}
-
-void cil_tree_print_context(struct cil_context *context)
-{
- cil_log(CIL_INFO, " (");
- if (context->user != NULL) {
- cil_log(CIL_INFO, " %s", context->user->datum.name);
- } else if (context->user_str != NULL) {
- cil_log(CIL_INFO, " %s", context->user_str);
- }
-
- if (context->role != NULL) {
- cil_log(CIL_INFO, " %s", context->role->datum.name);
- } else if (context->role_str != NULL) {
- cil_log(CIL_INFO, " %s", context->role_str);
- }
-
- if (context->type != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)context->type)->name);
- } else if (context->type_str != NULL) {
- cil_log(CIL_INFO, " %s", context->type_str);
- }
-
- if (context->range != NULL) {
- cil_tree_print_levelrange(context->range);
- } else if (context->range_str != NULL) {
- cil_log(CIL_INFO, " %s", context->range_str);
- }
-
- cil_log(CIL_INFO, " )");
-
- return;
-}
-
-void cil_tree_print_constrain(struct cil_constrain *cons)
-{
- cil_tree_print_classperms_list(cons->classperms);
-
- cil_tree_print_expr(cons->datum_expr, cons->str_expr);
-
- cil_log(CIL_INFO, "\n");
-}
-
-void cil_tree_print_node(struct cil_tree_node *node)
-{
- if (node->data == NULL) {
- cil_log(CIL_INFO, "FLAVOR: %d", node->flavor);
- return;
- } else {
- switch( node->flavor ) {
- case CIL_BLOCK: {
- struct cil_block *block = node->data;
- cil_log(CIL_INFO, "BLOCK: %s\n", block->datum.name);
- return;
- }
- case CIL_BLOCKINHERIT: {
- struct cil_blockinherit *inherit = node->data;
- cil_log(CIL_INFO, "BLOCKINHERIT: %s\n", inherit->block_str);
- return;
- }
- case CIL_BLOCKABSTRACT: {
- struct cil_blockabstract *abstract = node->data;
- cil_log(CIL_INFO, "BLOCKABSTRACT: %s\n", abstract->block_str);
- return;
- }
- case CIL_IN: {
- struct cil_in *in = node->data;
- cil_log(CIL_INFO, "IN: %s\n", in->block_str);
- return;
- }
- case CIL_USER: {
- struct cil_user *user = node->data;
- cil_log(CIL_INFO, "USER: %s\n", user->datum.name);
- return;
- }
- case CIL_TYPE: {
- struct cil_type *type = node->data;
- cil_log(CIL_INFO, "TYPE: %s\n", type->datum.name);
- return;
- }
- case CIL_EXPANDTYPEATTRIBUTE: {
- struct cil_expandtypeattribute *attr = node->data;
-
- fprintf(stderr, "%s %u\n", __func__, __LINE__);
- cil_log(CIL_INFO, "(EXPANDTYPEATTRIBUTE ");
- cil_tree_print_expr(attr->attr_datums, attr->attr_strs);
- cil_log(CIL_INFO, "%s)\n",attr->expand ?
- CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE);
-
- return;
- }
- case CIL_TYPEATTRIBUTESET: {
- struct cil_typeattributeset *attr = node->data;
-
- cil_log(CIL_INFO, "(TYPEATTRIBUTESET %s ", attr->attr_str);
-
- cil_tree_print_expr(attr->datum_expr, attr->str_expr);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_TYPEATTRIBUTE: {
- struct cil_typeattribute *attr = node->data;
- cil_log(CIL_INFO, "TYPEATTRIBUTE: %s\n", attr->datum.name);
- return;
- }
- case CIL_ROLE: {
- struct cil_role *role = node->data;
- cil_log(CIL_INFO, "ROLE: %s\n", role->datum.name);
- return;
- }
- case CIL_USERROLE: {
- struct cil_userrole *userrole = node->data;
- cil_log(CIL_INFO, "USERROLE:");
- struct cil_symtab_datum *datum = NULL;
-
- if (userrole->user != NULL) {
- datum = userrole->user;
- cil_log(CIL_INFO, " %s", datum->name);
- } else if (userrole->user_str != NULL) {
- cil_log(CIL_INFO, " %s", userrole->user_str);
- }
-
- if (userrole->role != NULL) {
- datum = userrole->role;
- cil_log(CIL_INFO, " %s", datum->name);
- } else if (userrole->role_str != NULL) {
- cil_log(CIL_INFO, " %s", userrole->role_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_USERLEVEL: {
- struct cil_userlevel *usrlvl = node->data;
- cil_log(CIL_INFO, "USERLEVEL:");
-
- if (usrlvl->user_str != NULL) {
- cil_log(CIL_INFO, " %s", usrlvl->user_str);
- }
-
- if (usrlvl->level != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_level(usrlvl->level);
- cil_log(CIL_INFO, " )");
- } else if (usrlvl->level_str != NULL) {
- cil_log(CIL_INFO, " %s", usrlvl->level_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_USERRANGE: {
- struct cil_userrange *userrange = node->data;
- cil_log(CIL_INFO, "USERRANGE:");
-
- if (userrange->user_str != NULL) {
- cil_log(CIL_INFO, " %s", userrange->user_str);
- }
-
- if (userrange->range != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_levelrange(userrange->range);
- cil_log(CIL_INFO, " )");
- } else if (userrange->range_str != NULL) {
- cil_log(CIL_INFO, " %s", userrange->range_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_USERBOUNDS: {
- struct cil_bounds *bnds = node->data;
- cil_log(CIL_INFO, "USERBOUNDS: user: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
- return;
- }
- case CIL_ROLETYPE: {
- struct cil_roletype *roletype = node->data;
- struct cil_symtab_datum *datum = NULL;
- cil_log(CIL_INFO, "ROLETYPE:");
-
- if (roletype->role != NULL) {
- datum = roletype->role;
- cil_log(CIL_INFO, " %s", datum->name);
- } else if (roletype->role_str != NULL) {
- cil_log(CIL_INFO, " %s", roletype->role_str);
- }
-
- if (roletype->type != NULL) {
- datum = roletype->type;
- cil_log(CIL_INFO, " %s", datum->name);
- } else if (roletype->type_str != NULL) {
- cil_log(CIL_INFO, " %s", roletype->type_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_ROLETRANSITION: {
- struct cil_roletransition *roletrans = node->data;
- cil_log(CIL_INFO, "ROLETRANSITION:");
-
- if (roletrans->src != NULL) {
- cil_log(CIL_INFO, " %s", roletrans->src->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", roletrans->src_str);
- }
-
- if (roletrans->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)roletrans->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", roletrans->tgt_str);
- }
-
- if (roletrans->obj != NULL) {
- cil_log(CIL_INFO, " %s", roletrans->obj->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", roletrans->obj_str);
- }
-
- if (roletrans->result != NULL) {
- cil_log(CIL_INFO, " %s\n", roletrans->result->datum.name);
- } else {
- cil_log(CIL_INFO, " %s\n", roletrans->result_str);
- }
-
- return;
- }
- case CIL_ROLEALLOW: {
- struct cil_roleallow *roleallow = node->data;
- cil_log(CIL_INFO, "ROLEALLOW:");
-
- if (roleallow->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", roleallow->src_str);
- }
-
- if (roleallow->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", roleallow->tgt_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_ROLEATTRIBUTESET: {
- struct cil_roleattributeset *attr = node->data;
-
- cil_log(CIL_INFO, "(ROLEATTRIBUTESET %s ", attr->attr_str);
-
- cil_tree_print_expr(attr->datum_expr, attr->str_expr);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_ROLEATTRIBUTE: {
- struct cil_roleattribute *attr = node->data;
- cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name);
- return;
- }
- case CIL_USERATTRIBUTESET: {
- struct cil_userattributeset *attr = node->data;
-
- cil_log(CIL_INFO, "(USERATTRIBUTESET %s ", attr->attr_str);
-
- cil_tree_print_expr(attr->datum_expr, attr->str_expr);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_USERATTRIBUTE: {
- struct cil_userattribute *attr = node->data;
- cil_log(CIL_INFO, "USERATTRIBUTE: %s\n", attr->datum.name);
- return;
- }
- case CIL_ROLEBOUNDS: {
- struct cil_bounds *bnds = node->data;
- cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
- return;
- }
- case CIL_CLASS: {
- struct cil_class *cls = node->data;
- cil_log(CIL_INFO, "CLASS: %s ", cls->datum.name);
-
- if (cls->common != NULL) {
- cil_log(CIL_INFO, "inherits: %s ", cls->common->datum.name);
- }
- cil_log(CIL_INFO, "(");
-
- cil_tree_print_perms_list(node->cl_head);
-
- cil_log(CIL_INFO, " )");
- return;
- }
- case CIL_CLASSORDER: {
- struct cil_classorder *classorder = node->data;
- struct cil_list_item *class;
-
- if (classorder->class_list_str == NULL) {
- cil_log(CIL_INFO, "CLASSORDER: ()\n");
- return;
- }
-
- cil_log(CIL_INFO, "CLASSORDER: (");
- cil_list_for_each(class, classorder->class_list_str) {
- cil_log(CIL_INFO, " %s", (char*)class->data);
- }
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_COMMON: {
- struct cil_class *common = node->data;
- cil_log(CIL_INFO, "COMMON: %s (", common->datum.name);
-
- cil_tree_print_perms_list(node->cl_head);
-
- cil_log(CIL_INFO, " )");
- return;
- }
- case CIL_CLASSCOMMON: {
- struct cil_classcommon *clscom = node->data;
-
- cil_log(CIL_INFO, "CLASSCOMMON: class: %s, common: %s\n", clscom->class_str, clscom->common_str);
-
- return;
- }
- case CIL_CLASSPERMISSION: {
- struct cil_classpermission *cp = node->data;
-
- cil_log(CIL_INFO, "CLASSPERMISSION: %s", cp->datum.name);
-
- cil_log(CIL_INFO, "\n");
-
- return;
- }
- case CIL_CLASSPERMISSIONSET: {
- struct cil_classpermissionset *cps = node->data;
-
- cil_log(CIL_INFO, "CLASSPERMISSIONSET: %s", cps->set_str);
-
- cil_tree_print_classperms_list(cps->classperms);
-
- cil_log(CIL_INFO, "\n");
-
- return;
- }
- case CIL_MAP_CLASS: {
- struct cil_class *cm = node->data;
- cil_log(CIL_INFO, "MAP_CLASS: %s", cm->datum.name);
-
- cil_log(CIL_INFO, " (");
- cil_tree_print_perms_list(node->cl_head);
- cil_log(CIL_INFO, " )\n");
-
- return;
- }
- case CIL_MAP_PERM: {
- struct cil_perm *cmp = node->data;
-
- cil_log(CIL_INFO, "MAP_PERM: %s", cmp->datum.name);
-
- if (cmp->classperms == NULL) {
- cil_log(CIL_INFO, " perms: ()");
- return;
- }
-
- cil_log(CIL_INFO, " kernel class perms: (");
-
- cil_tree_print_classperms_list(cmp->classperms);
-
- cil_log(CIL_INFO, " )\n");
-
- return;
- }
- case CIL_CLASSMAPPING: {
- struct cil_classmapping *mapping = node->data;
-
- cil_log(CIL_INFO, "CLASSMAPPING: map class: %s, map perm: %s,", mapping->map_class_str, mapping->map_perm_str);
-
- cil_log(CIL_INFO, " (");
-
- cil_tree_print_classperms_list(mapping->classperms);
-
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_BOOL: {
- struct cil_bool *boolean = node->data;
- cil_log(CIL_INFO, "BOOL: %s, value: %d\n", boolean->datum.name, boolean->value);
- return;
- }
- case CIL_TUNABLE: {
- struct cil_tunable *tunable = node->data;
- cil_log(CIL_INFO, "TUNABLE: %s, value: %d\n", tunable->datum.name, tunable->value);
- return;
- }
- case CIL_BOOLEANIF: {
- struct cil_booleanif *bif = node->data;
-
- cil_log(CIL_INFO, "(BOOLEANIF ");
-
- cil_tree_print_expr(bif->datum_expr, bif->str_expr);
-
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_TUNABLEIF: {
- struct cil_tunableif *tif = node->data;
-
- cil_log(CIL_INFO, "(TUNABLEIF ");
-
- cil_tree_print_expr(tif->datum_expr, tif->str_expr);
-
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_CONDBLOCK: {
- struct cil_condblock *cb = node->data;
- if (cb->flavor == CIL_CONDTRUE) {
- cil_log(CIL_INFO, "true\n");
- } else if (cb->flavor == CIL_CONDFALSE) {
- cil_log(CIL_INFO, "false\n");
- }
- return;
- }
- case CIL_ALL:
- cil_log(CIL_INFO, "all");
- return;
- case CIL_AND:
- cil_log(CIL_INFO, "&&");
- return;
- case CIL_OR:
- cil_log(CIL_INFO, "|| ");
- return;
- case CIL_NOT:
- cil_log(CIL_INFO, "!");
- return;
- case CIL_EQ:
- cil_log(CIL_INFO, "==");
- return;
- case CIL_NEQ:
- cil_log(CIL_INFO, "!=");
- return;
- case CIL_TYPEALIAS: {
- struct cil_alias *alias = node->data;
- cil_log(CIL_INFO, "TYPEALIAS: %s\n", alias->datum.name);
- return;
- }
- case CIL_TYPEALIASACTUAL: {
- struct cil_aliasactual *aliasactual = node->data;
- cil_log(CIL_INFO, "TYPEALIASACTUAL: type: %s, alias: %s\n", aliasactual->alias_str, aliasactual->actual_str);
- return;
- }
- case CIL_TYPEBOUNDS: {
- struct cil_bounds *bnds = node->data;
- cil_log(CIL_INFO, "TYPEBOUNDS: type: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);
- return;
- }
- case CIL_TYPEPERMISSIVE: {
- struct cil_typepermissive *typeperm = node->data;
-
- if (typeperm->type != NULL) {
- cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", ((struct cil_symtab_datum *)typeperm->type)->name);
- } else {
- cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", typeperm->type_str);
- }
-
- return;
- }
- case CIL_NAMETYPETRANSITION: {
- struct cil_nametypetransition *nametypetrans = node->data;
- cil_log(CIL_INFO, "TYPETRANSITION:");
-
- if (nametypetrans->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", nametypetrans->src_str);
- }
-
- if (nametypetrans->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", nametypetrans->tgt_str);
- }
-
- if (nametypetrans->obj != NULL) {
- cil_log(CIL_INFO, " %s", nametypetrans->obj->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", nametypetrans->obj_str);
- }
-
- cil_log(CIL_INFO, " %s\n", nametypetrans->name_str);
-
- if (nametypetrans->result != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->result)->name);
- } else {
- cil_log(CIL_INFO, " %s", nametypetrans->result_str);
- }
-
- return;
- }
- case CIL_RANGETRANSITION: {
- struct cil_rangetransition *rangetrans = node->data;
- cil_log(CIL_INFO, "RANGETRANSITION:");
-
- if (rangetrans->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", rangetrans->src_str);
- }
-
- if (rangetrans->exec != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->exec)->name);
- } else {
- cil_log(CIL_INFO, " %s", rangetrans->exec_str);
- }
-
- if (rangetrans->obj != NULL) {
- cil_log(CIL_INFO, " %s", rangetrans->obj->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", rangetrans->obj_str);
- }
-
- if (rangetrans->range != NULL) {
- cil_log(CIL_INFO, " (");
- cil_tree_print_levelrange(rangetrans->range);
- cil_log(CIL_INFO, " )");
- } else {
- cil_log(CIL_INFO, " %s", rangetrans->range_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_AVRULE: {
- struct cil_avrule *rule = node->data;
- switch (rule->rule_kind) {
- case CIL_AVRULE_ALLOWED:
- cil_log(CIL_INFO, "ALLOW:");
- break;
- case CIL_AVRULE_AUDITALLOW:
- cil_log(CIL_INFO, "AUDITALLOW:");
- break;
- case CIL_AVRULE_DONTAUDIT:
- cil_log(CIL_INFO, "DONTAUDIT:");
- break;
- case CIL_AVRULE_NEVERALLOW:
- cil_log(CIL_INFO, "NEVERALLOW:");
- break;
- }
-
- if (rule->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", rule->src_str);
- }
-
- if (rule->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", rule->tgt_str);
- }
-
- cil_tree_print_classperms_list(rule->perms.classperms);
-
- cil_log(CIL_INFO, "\n");
-
- return;
- }
- case CIL_TYPE_RULE: {
- struct cil_type_rule *rule = node->data;
- switch (rule->rule_kind) {
- case CIL_TYPE_TRANSITION:
- cil_log(CIL_INFO, "TYPETRANSITION:");
- break;
- case CIL_TYPE_MEMBER:
- cil_log(CIL_INFO, "TYPEMEMBER:");
- break;
- case CIL_TYPE_CHANGE:
- cil_log(CIL_INFO, "TYPECHANGE:");
- break;
- }
-
- if (rule->src != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->src)->name);
- } else {
- cil_log(CIL_INFO, " %s", rule->src_str);
- }
-
- if (rule->tgt != NULL) {
- cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->tgt)->name);
- } else {
- cil_log(CIL_INFO, " %s", rule->tgt_str);
- }
-
- if (rule->obj != NULL) {
- cil_log(CIL_INFO, " %s", rule->obj->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", rule->obj_str);
- }
-
- if (rule->result != NULL) {
- cil_log(CIL_INFO, " %s\n", ((struct cil_symtab_datum *)rule->result)->name);
- } else {
- cil_log(CIL_INFO, " %s\n", rule->result_str);
- }
-
- return;
- }
- case CIL_SENS: {
- struct cil_sens *sens = node->data;
- cil_log(CIL_INFO, "SENSITIVITY: %s\n", sens->datum.name);
- return;
- }
- case CIL_SENSALIAS: {
- struct cil_alias *alias = node->data;
- cil_log(CIL_INFO, "SENSITIVITYALIAS: %s\n", alias->datum.name);
- return;
- }
- case CIL_SENSALIASACTUAL: {
- struct cil_aliasactual *aliasactual = node->data;
- cil_log(CIL_INFO, "SENSITIVITYALIAS: alias: %s, sensitivity: %s\n", aliasactual->alias_str, aliasactual->actual_str);
-
- return;
- }
- case CIL_CAT: {
- struct cil_cat *cat = node->data;
- cil_log(CIL_INFO, "CATEGORY: %s\n", cat->datum.name);
- return;
- }
- case CIL_CATALIAS: {
- struct cil_alias *alias = node->data;
- cil_log(CIL_INFO, "CATEGORYALIAS: %s\n", alias->datum.name);
- return;
- }
- case CIL_CATALIASACTUAL: {
- struct cil_aliasactual *aliasactual = node->data;
- cil_log(CIL_INFO, "CATEGORYALIAS: alias %s, category: %s\n", aliasactual->alias_str, aliasactual->actual_str);
- return;
- }
- case CIL_CATSET: {
- struct cil_catset *catset = node->data;
-
- cil_log(CIL_INFO, "CATSET: %s ",catset->datum.name);
-
- cil_tree_print_cats(catset->cats);
-
- return;
- }
- case CIL_CATORDER: {
- struct cil_catorder *catorder = node->data;
- struct cil_list_item *cat;
-
- if (catorder->cat_list_str == NULL) {
- cil_log(CIL_INFO, "CATORDER: ()\n");
- return;
- }
-
- cil_log(CIL_INFO, "CATORDER: (");
- cil_list_for_each(cat, catorder->cat_list_str) {
- cil_log(CIL_INFO, " %s", (char*)cat->data);
- }
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_SENSCAT: {
- struct cil_senscat *senscat = node->data;
-
- cil_log(CIL_INFO, "SENSCAT: sens:");
-
- if (senscat->sens_str != NULL) {
- cil_log(CIL_INFO, " %s ", senscat->sens_str);
- } else {
- cil_log(CIL_INFO, " [processed]");
- }
-
- cil_tree_print_cats(senscat->cats);
-
- return;
- }
- case CIL_SENSITIVITYORDER: {
- struct cil_sensorder *sensorder = node->data;
- struct cil_list_item *sens;
-
- cil_log(CIL_INFO, "SENSITIVITYORDER: (");
-
- if (sensorder->sens_list_str != NULL) {
- cil_list_for_each(sens, sensorder->sens_list_str) {
- if (sens->flavor == CIL_LIST) {
- struct cil_list_item *sub;
- cil_log(CIL_INFO, " (");
- cil_list_for_each(sub, (struct cil_list*)sens->data) {
- cil_log(CIL_INFO, " %s", (char*)sub->data);
- }
- cil_log(CIL_INFO, " )");
- } else {
- cil_log(CIL_INFO, " %s", (char*)sens->data);
- }
- }
- }
-
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_LEVEL: {
- struct cil_level *level = node->data;
- cil_log(CIL_INFO, "LEVEL %s:", level->datum.name);
- cil_tree_print_level(level);
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_LEVELRANGE: {
- struct cil_levelrange *lvlrange = node->data;
- cil_log(CIL_INFO, "LEVELRANGE %s:", lvlrange->datum.name);
- cil_tree_print_levelrange(lvlrange);
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_CONSTRAIN: {
- struct cil_constrain *cons = node->data;
- cil_log(CIL_INFO, "CONSTRAIN: (");
- cil_tree_print_constrain(cons);
- return;
- }
- case CIL_MLSCONSTRAIN: {
- struct cil_constrain *cons = node->data;
- cil_log(CIL_INFO, "MLSCONSTRAIN: (");
- cil_tree_print_constrain(cons);
- return;
- }
- case CIL_VALIDATETRANS: {
- struct cil_validatetrans *vt = node->data;
-
- cil_log(CIL_INFO, "(VALIDATETRANS ");
-
- if (vt->class != NULL) {
- cil_log(CIL_INFO, "%s ", vt->class->datum.name);
- } else if (vt->class_str != NULL) {
- cil_log(CIL_INFO, "%s ", vt->class_str);
- }
-
- cil_tree_print_expr(vt->datum_expr, vt->str_expr);
-
- cil_log(CIL_INFO, ")\n");
- return;
- }
- case CIL_MLSVALIDATETRANS: {
- struct cil_validatetrans *vt = node->data;
-
- cil_log(CIL_INFO, "(MLSVALIDATETRANS ");
-
- if (vt->class != NULL) {
- cil_log(CIL_INFO, "%s ", vt->class->datum.name);
- } else if (vt->class_str != NULL) {
- cil_log(CIL_INFO, "%s ", vt->class_str);
- }
-
- cil_tree_print_expr(vt->datum_expr, vt->str_expr);
-
- cil_log(CIL_INFO, ")\n");
- return;
- }
- case CIL_CONTEXT: {
- struct cil_context *context = node->data;
- cil_log(CIL_INFO, "CONTEXT %s:", context->datum.name);
- cil_tree_print_context(context);
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_FILECON: {
- struct cil_filecon *filecon = node->data;
- cil_log(CIL_INFO, "FILECON:");
- cil_log(CIL_INFO, " %s %d", filecon->path_str, filecon->type);
-
- if (filecon->context != NULL) {
- cil_tree_print_context(filecon->context);
- } else if (filecon->context_str != NULL) {
- cil_log(CIL_INFO, " %s", filecon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
-
- }
- case CIL_IBPKEYCON: {
- struct cil_ibpkeycon *ibpkeycon = node->data;
-
- cil_log(CIL_INFO, "IBPKEYCON: %s", ibpkeycon->subnet_prefix_str);
- cil_log(CIL_INFO, " (%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high);
-
- if (ibpkeycon->context)
- cil_tree_print_context(ibpkeycon->context);
- else if (ibpkeycon->context_str)
- cil_log(CIL_INFO, " %s", ibpkeycon->context_str);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_PORTCON: {
- struct cil_portcon *portcon = node->data;
- cil_log(CIL_INFO, "PORTCON:");
- if (portcon->proto == CIL_PROTOCOL_UDP) {
- cil_log(CIL_INFO, " udp");
- } else if (portcon->proto == CIL_PROTOCOL_TCP) {
- cil_log(CIL_INFO, " tcp");
- } else if (portcon->proto == CIL_PROTOCOL_DCCP) {
- cil_log(CIL_INFO, " dccp");
- } else if (portcon->proto == CIL_PROTOCOL_SCTP) {
- cil_log(CIL_INFO, " sctp");
- }
- cil_log(CIL_INFO, " (%d %d)", portcon->port_low, portcon->port_high);
-
- if (portcon->context != NULL) {
- cil_tree_print_context(portcon->context);
- } else if (portcon->context_str != NULL) {
- cil_log(CIL_INFO, " %s", portcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_NODECON: {
- struct cil_nodecon *nodecon = node->data;
- char buf[256];
-
- cil_log(CIL_INFO, "NODECON:");
-
- if (nodecon->addr) {
- inet_ntop(nodecon->addr->family, &nodecon->addr->ip, buf, 256);
- cil_log(CIL_INFO, " %s", buf);
- } else {
- cil_log(CIL_INFO, " %s", nodecon->addr_str);
- }
-
- if (nodecon->mask) {
- inet_ntop(nodecon->mask->family, &nodecon->mask->ip, buf, 256);
- cil_log(CIL_INFO, " %s", buf);
- } else {
- cil_log(CIL_INFO, " %s", nodecon->mask_str);
- }
-
- if (nodecon->context != NULL) {
- cil_tree_print_context(nodecon->context);
- } else if (nodecon->context_str != NULL) {
- cil_log(CIL_INFO, " %s", nodecon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_GENFSCON: {
- struct cil_genfscon *genfscon = node->data;
- cil_log(CIL_INFO, "GENFSCON:");
- cil_log(CIL_INFO, " %s %s", genfscon->fs_str, genfscon->path_str);
-
- if (genfscon->context != NULL) {
- cil_tree_print_context(genfscon->context);
- } else if (genfscon->context_str != NULL) {
- cil_log(CIL_INFO, " %s", genfscon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_NETIFCON: {
- struct cil_netifcon *netifcon = node->data;
- cil_log(CIL_INFO, "NETIFCON %s", netifcon->interface_str);
-
- if (netifcon->if_context != NULL) {
- cil_tree_print_context(netifcon->if_context);
- } else if (netifcon->if_context_str != NULL) {
- cil_log(CIL_INFO, " %s", netifcon->if_context_str);
- }
-
- if (netifcon->packet_context != NULL) {
- cil_tree_print_context(netifcon->packet_context);
- } else if (netifcon->packet_context_str != NULL) {
- cil_log(CIL_INFO, " %s", netifcon->packet_context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_IBENDPORTCON: {
- struct cil_ibendportcon *ibendportcon = node->data;
-
- cil_log(CIL_INFO, "IBENDPORTCON: %s %u ", ibendportcon->dev_name_str, ibendportcon->port);
-
- if (ibendportcon->context)
- cil_tree_print_context(ibendportcon->context);
- else if (ibendportcon->context_str)
- cil_log(CIL_INFO, " %s", ibendportcon->context_str);
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_PIRQCON: {
- struct cil_pirqcon *pirqcon = node->data;
-
- cil_log(CIL_INFO, "PIRQCON %d", pirqcon->pirq);
- if (pirqcon->context != NULL) {
- cil_tree_print_context(pirqcon->context);
- } else {
- cil_log(CIL_INFO, " %s", pirqcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_IOMEMCON: {
- struct cil_iomemcon *iomemcon = node->data;
-
- cil_log(CIL_INFO, "IOMEMCON ( %"PRId64" %"PRId64" )", iomemcon->iomem_low, iomemcon->iomem_high);
- if (iomemcon->context != NULL) {
- cil_tree_print_context(iomemcon->context);
- } else {
- cil_log(CIL_INFO, " %s", iomemcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_IOPORTCON: {
- struct cil_ioportcon *ioportcon = node->data;
-
- cil_log(CIL_INFO, "IOPORTCON ( %d %d )", ioportcon->ioport_low, ioportcon->ioport_high);
- if (ioportcon->context != NULL) {
- cil_tree_print_context(ioportcon->context);
- } else {
- cil_log(CIL_INFO, " %s", ioportcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_PCIDEVICECON: {
- struct cil_pcidevicecon *pcidevicecon = node->data;
-
- cil_log(CIL_INFO, "PCIDEVICECON %d", pcidevicecon->dev);
- if (pcidevicecon->context != NULL) {
- cil_tree_print_context(pcidevicecon->context);
- } else {
- cil_log(CIL_INFO, " %s", pcidevicecon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_DEVICETREECON: {
- struct cil_devicetreecon *devicetreecon = node->data;
-
- cil_log(CIL_INFO, "DEVICETREECON %s", devicetreecon->path);
- if (devicetreecon->context != NULL) {
- cil_tree_print_context(devicetreecon->context);
- } else {
- cil_log(CIL_INFO, " %s", devicetreecon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_FSUSE: {
- struct cil_fsuse *fsuse = node->data;
- cil_log(CIL_INFO, "FSUSE: ");
-
- if (fsuse->type == CIL_FSUSE_XATTR) {
- cil_log(CIL_INFO, "xattr ");
- } else if (fsuse->type == CIL_FSUSE_TASK) {
- cil_log(CIL_INFO, "task ");
- } else if (fsuse->type == CIL_FSUSE_TRANS) {
- cil_log(CIL_INFO, "trans ");
- } else {
- cil_log(CIL_INFO, "unknown ");
- }
-
- cil_log(CIL_INFO, "%s ", fsuse->fs_str);
-
- if (fsuse->context != NULL) {
- cil_tree_print_context(fsuse->context);
- } else {
- cil_log(CIL_INFO, " %s", fsuse->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_SID: {
- struct cil_sid *sid = node->data;
- cil_log(CIL_INFO, "SID: %s\n", sid->datum.name);
- return;
- }
- case CIL_SIDCONTEXT: {
- struct cil_sidcontext *sidcon = node->data;
- cil_log(CIL_INFO, "SIDCONTEXT: %s", sidcon->sid_str);
-
- if (sidcon->context != NULL) {
- cil_tree_print_context(sidcon->context);
- } else {
- cil_log(CIL_INFO, " %s", sidcon->context_str);
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_SIDORDER: {
- struct cil_sidorder *sidorder = node->data;
- struct cil_list_item *sid;
-
- if (sidorder->sid_list_str == NULL) {
- cil_log(CIL_INFO, "SIDORDER: ()\n");
- return;
- }
-
- cil_log(CIL_INFO, "SIDORDER: (");
- cil_list_for_each(sid, sidorder->sid_list_str) {
- cil_log(CIL_INFO, " %s", (char*)sid->data);
- }
- cil_log(CIL_INFO, " )\n");
- return;
- }
- case CIL_POLICYCAP: {
- struct cil_policycap *polcap = node->data;
- cil_log(CIL_INFO, "POLICYCAP: %s\n", polcap->datum.name);
- return;
- }
- case CIL_MACRO: {
- struct cil_macro *macro = node->data;
- cil_log(CIL_INFO, "MACRO %s:", macro->datum.name);
-
- if (macro->params != NULL && macro->params->head != NULL) {
- struct cil_list_item *curr_param;
- cil_log(CIL_INFO, " parameters: (");
- cil_list_for_each(curr_param, macro->params) {
- cil_log(CIL_INFO, " flavor: %d, string: %s;", ((struct cil_param*)curr_param->data)->flavor, ((struct cil_param*)curr_param->data)->str);
-
- }
- cil_log(CIL_INFO, " )");
- }
- cil_log(CIL_INFO, "\n");
-
- return;
- }
- case CIL_CALL: {
- struct cil_call *call = node->data;
- cil_log(CIL_INFO, "CALL: macro name:");
-
- if (call->macro != NULL) {
- cil_log(CIL_INFO, " %s", call->macro->datum.name);
- } else {
- cil_log(CIL_INFO, " %s", call->macro_str);
- }
-
- if (call->args != NULL) {
- cil_log(CIL_INFO, ", args: ( ");
- struct cil_list_item *item;
- cil_list_for_each(item, call->args) {
- struct cil_symtab_datum *datum = ((struct cil_args*)item->data)->arg;
- if (datum != NULL) {
- if (datum->nodes != NULL && datum->nodes->head != NULL) {
- cil_tree_print_node((struct cil_tree_node*)datum->nodes->head->data);
- }
- } else if (((struct cil_args*)item->data)->arg_str != NULL) {
- switch (item->flavor) {
- case CIL_TYPE: cil_log(CIL_INFO, "type:"); break;
- case CIL_USER: cil_log(CIL_INFO, "user:"); break;
- case CIL_ROLE: cil_log(CIL_INFO, "role:"); break;
- case CIL_SENS: cil_log(CIL_INFO, "sensitivity:"); break;
- case CIL_CAT: cil_log(CIL_INFO, "category:"); break;
- case CIL_CATSET: cil_log(CIL_INFO, "categoryset:"); break;
- case CIL_LEVEL: cil_log(CIL_INFO, "level:"); break;
- case CIL_CLASS: cil_log(CIL_INFO, "class:"); break;
- default: break;
- }
- cil_log(CIL_INFO, "%s ", ((struct cil_args*)item->data)->arg_str);
- }
- }
- cil_log(CIL_INFO, ")");
- }
-
- cil_log(CIL_INFO, "\n");
- return;
- }
- case CIL_OPTIONAL: {
- struct cil_optional *optional = node->data;
- cil_log(CIL_INFO, "OPTIONAL: %s\n", optional->datum.name);
- return;
- }
- case CIL_IPADDR: {
- struct cil_ipaddr *ipaddr = node->data;
- char buf[256];
-
- inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256);
- cil_log(CIL_INFO, "IPADDR %s: %s\n", ipaddr->datum.name, buf);
-
- break;
- }
- default : {
- cil_log(CIL_INFO, "CIL FLAVOR: %d\n", node->flavor);
- return;
- }
- }
- }
-}
-
-void cil_tree_print(struct cil_tree_node *tree, uint32_t depth)
-{
- struct cil_tree_node *current = NULL;
- current = tree;
- uint32_t x = 0;
-
- if (current != NULL) {
- if (current->cl_head == NULL) {
- if (current->flavor == CIL_NODE) {
- if (current->parent->cl_head == current) {
- cil_log(CIL_INFO, "%s", (char*)current->data);
- } else {
- cil_log(CIL_INFO, " %s", (char*)current->data);
- }
- } else if (current->flavor != CIL_PERM) {
- for (x = 0; x<depth; x++) {
- cil_log(CIL_INFO, "\t");
- }
- cil_tree_print_node(current);
- }
- } else {
- if (current->parent != NULL) {
- cil_log(CIL_INFO, "\n");
- for (x = 0; x<depth; x++) {
- cil_log(CIL_INFO, "\t");
- }
- cil_log(CIL_INFO, "(");
-
- if (current->flavor != CIL_NODE) {
- cil_tree_print_node(current);
- }
- }
- cil_tree_print(current->cl_head, depth + 1);
- }
-
- if (current->next == NULL) {
- if ((current->parent != NULL) && (current->parent->cl_tail == current) && (current->parent->parent != NULL)) {
- if (current->flavor == CIL_PERM) {
- cil_log(CIL_INFO, ")\n");
- } else if (current->flavor != CIL_NODE) {
- for (x = 0; x<depth-1; x++) {
- cil_log(CIL_INFO, "\t");
- }
- cil_log(CIL_INFO, ")\n");
- } else {
- cil_log(CIL_INFO, ")");
- }
- }
-
- if ((current->parent != NULL) && (current->parent->parent == NULL))
- cil_log(CIL_INFO, "\n\n");
- } else {
- cil_tree_print(current->next, depth);
- }
- } else {
- cil_log(CIL_INFO, "Tree is NULL\n");
- }
-}
diff --git a/libsepol/cil/src/cil_tree.h b/libsepol/cil/src/cil_tree.h
index aeded560..5a98da55 100644
--- a/libsepol/cil/src/cil_tree.h
+++ b/libsepol/cil/src/cil_tree.h
@@ -46,14 +46,16 @@ struct cil_tree_node {
struct cil_tree_node *next; //Each element in the list points to the next element
enum cil_flavor flavor;
uint32_t line;
- uint32_t hll_line;
+ uint32_t hll_offset;
void *data;
};
-struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil);
+struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path);
char *cil_tree_get_cil_path(struct cil_tree_node *node);
__attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...);
+int cil_tree_subtree_has_decl(struct cil_tree_node *node);
+
int cil_tree_init(struct cil_tree **tree);
void cil_tree_destroy(struct cil_tree **tree);
void cil_tree_subtree_destroy(struct cil_tree_node *node);
@@ -62,8 +64,6 @@ void cil_tree_children_destroy(struct cil_tree_node *node);
void cil_tree_node_init(struct cil_tree_node **node);
void cil_tree_node_destroy(struct cil_tree_node **node);
-void cil_tree_print(struct cil_tree_node *tree, uint32_t depth);
-
//finished values
#define CIL_TREE_SKIP_NOTHING 0
#define CIL_TREE_SKIP_NEXT 1
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index c73bbeee..d994d717 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -44,10 +44,55 @@
#include "cil_tree.h"
#include "cil_list.h"
#include "cil_find.h"
+#include "cil_stack.h"
#include "cil_verify.h"
-int __cil_verify_name(const char *name)
+static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
+{
+ switch (flavor) {
+ case CIL_BOOL:
+ case CIL_TUNABLE:
+ if ((name == CIL_KEY_EQ) || (name == CIL_KEY_NEQ))
+ return CIL_TRUE;
+ break;
+ case CIL_PERM:
+ case CIL_MAP_PERM:
+ case CIL_USER:
+ case CIL_USERATTRIBUTE:
+ case CIL_ROLE:
+ case CIL_ROLEATTRIBUTE:
+ if (name == CIL_KEY_ALL)
+ return CIL_TRUE;
+ break;
+ case CIL_TYPE:
+ case CIL_TYPEATTRIBUTE:
+ case CIL_TYPEALIAS:
+ if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF))
+ return CIL_TRUE;
+ break;
+ case CIL_CAT:
+ case CIL_CATSET:
+ case CIL_CATALIAS:
+ case CIL_PERMISSIONX:
+ if ((name == CIL_KEY_ALL) || (name == CIL_KEY_RANGE))
+ return CIL_TRUE;
+ break;
+ default:
+ /* All of these are not used in expressions */
+ return CIL_FALSE;
+ break;
+ }
+
+ /* Everything not under the default case is also checked for these */
+ if ((name == CIL_KEY_AND) || (name == CIL_KEY_OR) || (name == CIL_KEY_NOT) || (name == CIL_KEY_XOR)) {
+ return CIL_TRUE;
+ }
+
+ return CIL_FALSE;
+}
+
+int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor)
{
int rc = SEPOL_ERR;
int len;
@@ -71,12 +116,27 @@ int __cil_verify_name(const char *name)
goto exit;
}
- for (i = 1; i < len; i++) {
- if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
- cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
- goto exit;
+ if (db->qualified_names == CIL_FALSE) {
+ for (i = 1; i < len; i++) {
+ if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
+ cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
+ goto exit;
+ }
+ }
+ } else {
+ for (i = 1; i < len; i++) {
+ if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-' && name[i] != '.') {
+ cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
+ goto exit;
+ }
}
}
+
+ if (__cil_is_reserved_name(name, flavor)) {
+ cil_log(CIL_ERR, "Name %s is a reserved word\n", name);
+ goto exit;
+ }
+
return SEPOL_OK;
exit:
@@ -84,70 +144,45 @@ exit:
return rc;
}
-int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len)
+int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t len)
{
- int rc = SEPOL_ERR;
- int num_extras = 0;
struct cil_tree_node *c = parse_current;
- int i = 0;
- while (i < len) {
- if ((s[i] & CIL_SYN_END) && c == NULL) {
- break;
- }
-
- if (s[i] & CIL_SYN_N_LISTS || s[i] & CIL_SYN_N_STRINGS) {
- if (c == NULL) {
- if (num_extras > 0) {
- i++;
- continue;
+ size_t i = 0;
+
+ while (i < len && c != NULL) {
+ if ((s[i] & CIL_SYN_STRING) && c->data != NULL && c->cl_head == NULL) {
+ c = c->next;
+ i++;
+ } else if ((s[i] & CIL_SYN_LIST) && c->data == NULL && c->cl_head != NULL) {
+ c = c->next;
+ i++;
+ } else if ((s[i] & CIL_SYN_EMPTY_LIST) && c->data == NULL && c->cl_head == NULL) {
+ c = c->next;
+ i++;
+ } else if ((s[i] & CIL_SYN_N_LISTS) || (s[i] & CIL_SYN_N_STRINGS)) {
+ while (c != NULL) {
+ if ((s[i] & CIL_SYN_N_LISTS) && c->data == NULL && c->cl_head != NULL) {
+ c = c->next;
+ } else if ((s[i] & CIL_SYN_N_STRINGS) && c->data != NULL && c->cl_head == NULL) {
+ c = c->next;
} else {
goto exit;
}
- } else if ((s[i] & CIL_SYN_N_LISTS) && (c->data == NULL && c->cl_head != NULL)) {
- c = c->next;
- num_extras++;
- continue;
- } else if ((s[i] & CIL_SYN_N_STRINGS) && (c->data != NULL && c->cl_head == NULL)) {
- c = c->next;
- num_extras++;
- continue;
}
- }
-
- if (c == NULL) {
+ i++;
+ break; /* Only CIL_SYN_END allowed after these */
+ } else {
goto exit;
}
+ }
- if (s[i] & CIL_SYN_STRING) {
- if (c->data != NULL && c->cl_head == NULL) {
- c = c->next;
- i++;
- continue;
- }
- }
-
- if (s[i] & CIL_SYN_LIST) {
- if (c->data == NULL && c->cl_head != NULL) {
- c = c->next;
- i++;
- continue;
- }
- }
-
- if (s[i] & CIL_SYN_EMPTY_LIST) {
- if (c->data == NULL && c->cl_head == NULL) {
- c = c->next;
- i++;
- continue;
- }
- }
- goto exit;
+ if (i < len && (s[i] & CIL_SYN_END) && c == NULL) {
+ return SEPOL_OK;
}
- return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Invalid syntax\n");
- return rc;
+ return SEPOL_ERR;
}
int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor)
@@ -225,12 +260,15 @@ int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_fl
cil_log(CIL_ERR, "u3, r3, and t3 can only be used with (mls)validatetrans rules\n");
goto exit;
}
- } else if (r_flavor == CIL_LIST) {
- cil_log(CIL_ERR, "t1, t2, r1, r2, u1, u2 cannot be used on the left side with a list on the right side\n");
- goto exit;
}
} else {
- if (r_flavor == CIL_CONS_U2) {
+ if (r_flavor == CIL_CONS_U1 || r_flavor == CIL_CONS_R1 || r_flavor == CIL_CONS_T1) {
+ cil_log(CIL_ERR, "u1, r1, and t1 are not allowed on the right side\n");
+ goto exit;
+ } else if (r_flavor == CIL_CONS_U3 || r_flavor == CIL_CONS_R3 || r_flavor == CIL_CONS_T3) {
+ cil_log(CIL_ERR, "u3, r3, and t3 are not allowed on the right side\n");
+ goto exit;
+ } else if (r_flavor == CIL_CONS_U2) {
if (op != CIL_EQ && op != CIL_NEQ) {
cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n");
goto exit;
@@ -324,28 +362,135 @@ exit:
return SEPOL_ERR;
}
-int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list)
+int cil_verify_conditional_blocks(struct cil_tree_node *current)
{
- struct cil_list_item *i;
+ int found_true = CIL_FALSE;
+ int found_false = CIL_FALSE;
- cil_list_for_each(i, datum_list) {
- if (i->flavor == CIL_DATUM) {
- struct cil_symtab_datum *d = i->data;
- if (d == datum) {
- cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name);
+ if (current->cl_head->data == CIL_KEY_CONDTRUE) {
+ found_true = CIL_TRUE;
+ } else if (current->cl_head->data == CIL_KEY_CONDFALSE) {
+ found_false = CIL_TRUE;
+ } else {
+ cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional");
+ return SEPOL_ERR;
+ }
+
+ current = current->next;
+ if (current != NULL) {
+ if (current->cl_head->data == CIL_KEY_CONDTRUE) {
+ if (found_true) {
+ cil_tree_log(current, CIL_ERR, "More than one true block in conditional");
return SEPOL_ERR;
}
- } else if (i->flavor == CIL_LIST) {
- int rc = cil_verify_no_self_reference(datum, i->data);
- if (rc != SEPOL_OK) {
+ } else if (current->cl_head->data == CIL_KEY_CONDFALSE) {
+ if (found_false) {
+ cil_tree_log(current, CIL_ERR, "More than one false block in conditional");
return SEPOL_ERR;
}
+ } else {
+ cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional");
+ return SEPOL_ERR;
}
}
return SEPOL_OK;
}
+int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name)
+{
+ struct cil_list_item *item;
+ struct cil_list *param_list = macro->params;
+ if (param_list != NULL) {
+ cil_list_for_each(item, param_list) {
+ struct cil_param *param = item->data;
+ if (param->flavor == node->flavor) {
+ if (param->str == name) {
+ cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(node), name);
+ return SEPOL_ERR;
+ }
+ }
+ }
+ }
+ return SEPOL_OK;
+}
+
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack);
+
+static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_stack *stack)
+{
+ struct cil_list_item *item;
+ int rc = SEPOL_OK;
+
+ if (!expr) {
+ return SEPOL_OK;
+ }
+
+ cil_list_for_each(item, expr) {
+ if (item->flavor == CIL_DATUM) {
+ struct cil_symtab_datum* datum = item->data;
+ rc = cil_verify_no_self_reference(FLAVOR(datum), datum, stack);
+ } else if (item->flavor == CIL_LIST) {
+ rc = __verify_no_self_reference_in_expr(item->data, stack);
+ }
+ if (rc != SEPOL_OK) {
+ return SEPOL_ERR;
+ }
+ }
+
+ return SEPOL_OK;
+}
+
+static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack)
+{
+ struct cil_stack_item *item;
+ int i = 0;
+ int rc = SEPOL_OK;
+
+ cil_stack_for_each(stack, i, item) {
+ struct cil_symtab_datum *prev = item->data;
+ if (datum == prev) {
+ cil_tree_log(NODE(datum), CIL_ERR, "Self-reference found for %s", datum->name);
+ return SEPOL_ERR;
+ }
+ }
+
+ switch (flavor) {
+ case CIL_USERATTRIBUTE: {
+ struct cil_userattribute *attr = (struct cil_userattribute *)datum;
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
+ break;
+ }
+ case CIL_ROLEATTRIBUTE: {
+ struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
+ break;
+ }
+ case CIL_TYPEATTRIBUTE: {
+ struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
+ cil_stack_pop(stack);
+ break;
+ }
+ case CIL_CATSET: {
+ struct cil_catset *set = (struct cil_catset *)datum;
+ cil_stack_push(stack, CIL_DATUM, datum);
+ rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, stack);
+ cil_stack_pop(stack);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return rc;
+}
+
int __cil_verify_ranges(struct cil_list *list)
{
int rc = SEPOL_ERR;
@@ -1544,6 +1689,15 @@ exit:
return rc;
}
+static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ struct cil_list *perm_list = (struct cil_list *)args;
+
+ cil_list_append(perm_list, CIL_DATUM, d);
+
+ return SEPOL_OK;
+}
+
static int __cil_verify_classperms(struct cil_list *classperms,
struct cil_symtab_datum *orig,
struct cil_symtab_datum *parent,
@@ -1585,13 +1739,34 @@ static int __cil_verify_classperms(struct cil_list *classperms,
if (FLAVOR(cp->class) != CIL_CLASS) { /* MAP */
struct cil_list_item *i = NULL;
cil_list_for_each(i, cp->perms) {
- struct cil_perm *cmp = i->data;
- rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
- if (rc != SEPOL_OK) {
- goto exit;
+ if (i->flavor != CIL_OP) {
+ struct cil_perm *cmp = i->data;
+ rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ } else {
+ enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data;
+ if (op == CIL_ALL) {
+ struct cil_class *mc = cp->class;
+ struct cil_list *perm_list;
+ struct cil_list_item *j = NULL;
+
+ cil_list_init(&perm_list, CIL_MAP_PERM);
+ cil_symtab_map(&mc->perms, __add_perm_to_list, perm_list);
+ cil_list_for_each(j, perm_list) {
+ struct cil_perm *cmp = j->data;
+ rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit);
+ if (rc != SEPOL_OK) {
+ cil_list_destroy(&perm_list, CIL_FALSE);
+ goto exit;
+ }
+ }
+ cil_list_destroy(&perm_list, CIL_FALSE);
+ }
}
}
- }
+ }
} else { /* SET */
struct cil_classperms_set *cp_set = curr->data;
struct cil_classpermission *cp = cp_set->set;
@@ -1625,8 +1800,12 @@ static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k,
{
struct cil_verify_map_args *map_args = args;
struct cil_perm *cmp = (struct cil_perm *)d;
+ int rc;
- map_args->rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2);
+ rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2);
+ if (rc != SEPOL_OK) {
+ map_args->rc = rc;
+ }
return SEPOL_OK;
}
@@ -1651,27 +1830,22 @@ static int __cil_verify_map_class(struct cil_tree_node *node)
int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
{
- int rc = SEPOL_ERR;
+ int rc = SEPOL_OK;
- if (node->flavor == CIL_MACRO) {
+ switch (node->flavor) {
+ case CIL_MACRO: {
*finished = CIL_TREE_SKIP_HEAD;
- rc = SEPOL_OK;
- goto exit;
- } else if (node->flavor == CIL_BLOCK) {
+ break;
+ }
+ case CIL_BLOCK: {
struct cil_block *blk = node->data;
if (blk->is_abstract == CIL_TRUE) {
*finished = CIL_TREE_SKIP_HEAD;
}
- rc = SEPOL_OK;
- goto exit;
+ break;
}
-
- switch (node->flavor) {
case CIL_USER:
rc = __cil_verify_user_pre_eval(node);
- if (rc != SEPOL_OK) {
- goto exit;
- }
break;
case CIL_MAP_CLASS:
rc = __cil_verify_map_class(node);
@@ -1679,11 +1853,20 @@ int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __at
case CIL_CLASSPERMISSION:
rc = __cil_verify_classpermission(node);
break;
+ case CIL_USERATTRIBUTE:
+ case CIL_ROLEATTRIBUTE:
+ case CIL_TYPEATTRIBUTE:
+ case CIL_CATSET: {
+ struct cil_stack *stack;
+ cil_stack_init(&stack);
+ rc = cil_verify_no_self_reference(node->flavor, node->data, stack);
+ cil_stack_destroy(&stack);
+ break;
+ }
default:
rc = SEPOL_OK;
break;
}
-exit:
return rc;
}
diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h
index bda1565f..bb1a072c 100644
--- a/libsepol/cil/src/cil_verify.h
+++ b/libsepol/cil/src/cil_verify.h
@@ -56,12 +56,13 @@ struct cil_args_verify {
int *pass;
};
-int __cil_verify_name(const char *name);
-int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len);
+int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor);
+int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t len);
int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor);
int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor);
int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op);
-int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list);
+int cil_verify_conditional_blocks(struct cil_tree_node *current);
+int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name);
int __cil_verify_ranges(struct cil_list *list);
int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args);
int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor);
diff --git a/libsepol/cil/src/cil_write_ast.c b/libsepol/cil/src/cil_write_ast.c
index bcf5f416..c0ee7473 100644
--- a/libsepol/cil/src/cil_write_ast.c
+++ b/libsepol/cil/src/cil_write_ast.c
@@ -1,1509 +1,1633 @@
-#include <stdlib.h>
+/*
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <ctype.h>
-#include "cil_flavor.h"
#include "cil_internal.h"
+#include "cil_flavor.h"
+#include "cil_list.h"
#include "cil_log.h"
+#include "cil_symtab.h"
#include "cil_tree.h"
+#include "cil_write_ast.h"
-struct cil_args_write {
- FILE *cil_out;
- struct cil_db *db;
-};
-
-static int cil_unfill_expr(struct cil_list *expr_str, char **out_str, int paren);
-static int cil_unfill_classperms_list(struct cil_list *classperms, char **out_str, int paren);
-static int __cil_write_first_child_helper(struct cil_tree_node *node, void *extra_args);
-static int __cil_write_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args);
-static int __cil_write_last_child_helper(struct cil_tree_node *node, void *extra_args);
-static int __cil_strlist_concat(struct cil_list *str_list, char **out_str, int paren) {
- size_t len = paren ? 3 : 1;
- size_t num_elems = 0;
- char *p = NULL;
- struct cil_list_item *curr;
+static inline const char *datum_or_str(struct cil_symtab_datum *datum, const char *str)
+{
+ return datum ? datum->fqn : str;
+}
- /* get buffer size */
- cil_list_for_each(curr, str_list) {
- len += strlen((char *)curr->data);
- num_elems++;
- }
- if (num_elems != 0) {
- /* add spaces between elements */
- len += num_elems - 1;
- }
- *out_str = cil_malloc(len);
- p = *out_str;
- if (paren)
- *p++ = '(';
- cil_list_for_each(curr, str_list) {
- size_t src_len = strlen((char *)curr->data);
- memcpy(p, curr->data, src_len);
- p += src_len;
- if (curr->next != NULL)
- *p++ = ' ';
- }
- if (paren)
- *p++ = ')';
- *p++ = '\0';
- return SEPOL_OK;
+static inline const char *datum_to_str(struct cil_symtab_datum *datum)
+{
+ return datum ? datum->fqn : "<?DATUM>";
}
-static int __cil_unfill_expr_helper(struct cil_list_item *curr,
- struct cil_list_item **next, char **out_str, int paren) {
- int rc = SEPOL_ERR;
- char *str = NULL;
- char *operand1 = NULL;
- char *operand2 = NULL;
-
- switch(curr->flavor) {
- case CIL_LIST:
- rc = cil_unfill_expr((struct cil_list *)curr->data, &str, paren);
- if (rc != SEPOL_OK)
- goto exit;
- *out_str = str;
- *next = curr->next;
- break;
- case CIL_STRING:
- str = strdup((char *)curr->data);
- if (!str) {
- cil_log(CIL_ERR, "OOM. Unable to copy string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- *out_str = str;
- *next = curr->next;
- break;
- case CIL_DATUM:
- str = strdup(((struct cil_symtab_datum *)curr->data)->name);
- if (!str) {
- cil_log(CIL_ERR, "OOM. Unable to copy string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- *out_str = str;
- *next = curr->next;
- break;
- case CIL_OP: {
- char *op_str = NULL;
- size_t len = 0;
- enum cil_flavor op_flavor = (enum cil_flavor)curr->data;
- switch (op_flavor) {
- case CIL_AND:
- op_str = CIL_KEY_AND;
- break;
- case CIL_OR:
- op_str = CIL_KEY_OR;
- break;
- case CIL_NOT:
- op_str = CIL_KEY_NOT;
- break;
- case CIL_ALL:
- op_str = CIL_KEY_ALL;
- break;
- case CIL_EQ:
- op_str = CIL_KEY_EQ;
- break;
- case CIL_NEQ:
- op_str = CIL_KEY_NEQ;
- break;
- case CIL_RANGE:
- op_str = CIL_KEY_RANGE;
- break;
- case CIL_XOR:
- op_str = CIL_KEY_XOR;
- break;
- case CIL_CONS_DOM:
- op_str = CIL_KEY_CONS_DOM;
+static void write_expr(FILE *out, struct cil_list *expr)
+{
+ struct cil_list_item *curr;
+ int notfirst = 0;
+
+ fprintf(out, "(");
+ cil_list_for_each(curr, expr) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ switch (curr->flavor) {
+ case CIL_LIST:
+ write_expr(out, curr->data);
break;
- case CIL_CONS_DOMBY:
- op_str = CIL_KEY_CONS_DOMBY;
+ case CIL_STRING:
+ fprintf(out, "%s", (char *)curr->data);
break;
- case CIL_CONS_INCOMP:
- op_str = CIL_KEY_CONS_INCOMP;
+ case CIL_DATUM:
+ case CIL_TYPE:
+ case CIL_ROLE:
+ case CIL_USER:
+ case CIL_SENS:
+ case CIL_CAT:
+ case CIL_BOOL:
+ case CIL_CLASS:
+ case CIL_MAP_CLASS:
+ case CIL_NAME:
+ fprintf(out, "%s", datum_to_str(curr->data));
break;
- default:
- cil_log(CIL_ERR, "Unknown operator in expression: %d\n", op_flavor);
- goto exit;
+ case CIL_OP: {
+ const char *op_str;
+ enum cil_flavor op_flavor = (enum cil_flavor)(uintptr_t)curr->data;
+ switch (op_flavor) {
+ case CIL_AND:
+ op_str = CIL_KEY_AND;
+ break;
+ case CIL_OR:
+ op_str = CIL_KEY_OR;
+ break;
+ case CIL_NOT:
+ op_str = CIL_KEY_NOT;
+ break;
+ case CIL_ALL:
+ op_str = CIL_KEY_ALL;
+ break;
+ case CIL_EQ:
+ op_str = CIL_KEY_EQ;
+ break;
+ case CIL_NEQ:
+ op_str = CIL_KEY_NEQ;
+ break;
+ case CIL_XOR:
+ op_str = CIL_KEY_XOR;
+ break;
+ case CIL_RANGE:
+ op_str = CIL_KEY_RANGE;
+ break;
+ case CIL_CONS_DOM:
+ op_str = CIL_KEY_CONS_DOM;
+ break;
+ case CIL_CONS_DOMBY:
+ op_str = CIL_KEY_CONS_DOMBY;
+ break;
+ case CIL_CONS_INCOMP:
+ op_str = CIL_KEY_CONS_INCOMP;
+ break;
+ default:
+ op_str = "<?OP>";
+ break;
+ }
+ fprintf(out, "%s", op_str);
break;
}
- /* all operands take two args except for 'all' and 'not', which take
- * one and two, respectively */
- len = strlen(op_str) + 3;
- if (op_flavor == CIL_ALL) {
- *out_str = cil_malloc(len);
- sprintf(*out_str, "(%s)", op_str);
- *next = curr->next;
- } else if (op_flavor == CIL_NOT) {
- rc = __cil_unfill_expr_helper(curr->next, next, &operand1, paren);
- if (rc != SEPOL_OK)
- goto exit;
- len += strlen(operand1) + 1;
- *out_str = cil_malloc(len);
- sprintf(*out_str, "(%s %s)", op_str, operand1);
- // *next already set by recursive call
- } else {
- rc = __cil_unfill_expr_helper(curr->next, next, &operand1, paren);
- if (rc != SEPOL_OK)
- goto exit;
- len += strlen(operand1) + 1;
- // *next contains operand2, but keep track of next after that
- rc = __cil_unfill_expr_helper(*next, next, &operand2, paren);
- if (rc != SEPOL_OK)
- goto exit;
- len += strlen(operand2) + 1;
- *out_str = cil_malloc(len);
- sprintf(*out_str, "(%s %s %s)", op_str, operand1, operand2);
- // *next already set by recursive call
- }
- }
- break;
- case CIL_CONS_OPERAND: {
- enum cil_flavor operand_flavor = (enum cil_flavor)curr->data;
- char *operand_str = NULL;
- switch (operand_flavor) {
- case CIL_CONS_U1:
- operand_str = CIL_KEY_CONS_U1;
- break;
- case CIL_CONS_U2:
- operand_str = CIL_KEY_CONS_U2;
- break;
- case CIL_CONS_U3:
- operand_str = CIL_KEY_CONS_U3;
- break;
- case CIL_CONS_T1:
- operand_str = CIL_KEY_CONS_T1;
- break;
- case CIL_CONS_T2:
- operand_str = CIL_KEY_CONS_T2;
- break;
- case CIL_CONS_T3:
- operand_str = CIL_KEY_CONS_T3;
- break;
- case CIL_CONS_R1:
- operand_str = CIL_KEY_CONS_R1;
- break;
- case CIL_CONS_R2:
- operand_str = CIL_KEY_CONS_R2;
- break;
- case CIL_CONS_R3:
- operand_str = CIL_KEY_CONS_R3;
- break;
- case CIL_CONS_L1:
- operand_str = CIL_KEY_CONS_L1;
- break;
- case CIL_CONS_L2:
- operand_str = CIL_KEY_CONS_L2;
- break;
- case CIL_CONS_H1:
- operand_str = CIL_KEY_CONS_H1;
- break;
- case CIL_CONS_H2:
- operand_str = CIL_KEY_CONS_H2;
+ case CIL_CONS_OPERAND: {
+ const char *operand_str;
+ enum cil_flavor operand_flavor = (enum cil_flavor)(uintptr_t)curr->data;
+ switch (operand_flavor) {
+ case CIL_CONS_U1:
+ operand_str = CIL_KEY_CONS_U1;
+ break;
+ case CIL_CONS_U2:
+ operand_str = CIL_KEY_CONS_U2;
+ break;
+ case CIL_CONS_U3:
+ operand_str = CIL_KEY_CONS_U3;
+ break;
+ case CIL_CONS_T1:
+ operand_str = CIL_KEY_CONS_T1;
+ break;
+ case CIL_CONS_T2:
+ operand_str = CIL_KEY_CONS_T2;
+ break;
+ case CIL_CONS_T3:
+ operand_str = CIL_KEY_CONS_T3;
+ break;
+ case CIL_CONS_R1:
+ operand_str = CIL_KEY_CONS_R1;
+ break;
+ case CIL_CONS_R2:
+ operand_str = CIL_KEY_CONS_R2;
+ break;
+ case CIL_CONS_R3:
+ operand_str = CIL_KEY_CONS_R3;
+ break;
+ case CIL_CONS_L1:
+ operand_str = CIL_KEY_CONS_L1;
+ break;
+ case CIL_CONS_L2:
+ operand_str = CIL_KEY_CONS_L2;
+ break;
+ case CIL_CONS_H1:
+ operand_str = CIL_KEY_CONS_H1;
+ break;
+ case CIL_CONS_H2:
+ operand_str = CIL_KEY_CONS_H2;
+ break;
+ default:
+ operand_str = "<?OPERAND>";
+ break;
+ }
+ fprintf(out, "%s", operand_str);
break;
+ }
default:
- cil_log(CIL_ERR, "Unknown operand in expression\n");
- goto exit;
+ fprintf(out, "<?FLAVOR>");
break;
}
- str = strdup(operand_str);
- if (!str) {
- cil_log(CIL_ERR, "OOM. Unable to copy string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- *out_str = str;
- *next = curr->next;
- }
- break;
- default:
- cil_log(CIL_ERR, "Unknown flavor in expression\n");
- goto exit;
- break;
}
- rc = SEPOL_OK;
-exit:
- free(operand1);
- free(operand2);
- return rc;
+ fprintf(out, ")");
}
-static int cil_unfill_expr(struct cil_list *expr_str, char **out_str, int paren) {
- int rc = SEPOL_ERR;
-
- /* reuse cil_list to keep track of strings */
- struct cil_list *str_list = NULL;
- struct cil_list_item *curr = NULL;
-
- cil_list_init(&str_list, CIL_NONE);
-
- /* iterate through cil_list, grabbing elements as needed */
- curr = expr_str->head;
- while(curr != NULL) {
- char *str = NULL;
- struct cil_list_item *next = NULL;
-
- rc = __cil_unfill_expr_helper(curr, &next, &str, paren);
- if (rc != SEPOL_OK)
- goto exit;
- cil_list_append(str_list, CIL_STRING, (void *) str);
- str = NULL;
- curr = next;
- }
- rc = __cil_strlist_concat(str_list, out_str, paren);
- if (rc != SEPOL_OK)
- goto exit;
- rc = SEPOL_OK;
-exit:
- cil_list_for_each(curr, str_list) {
- free(curr->data);
- }
- cil_list_destroy(&str_list, 0);
- return rc;
-}
+static void write_node_list(FILE *out, struct cil_tree_node *current)
+{
+ int notfirst = 0;
-static int cil_unfill_cats(struct cil_cats *cats, char **out_str) {
- return cil_unfill_expr(cats->str_expr, out_str, 0);
-}
+ fprintf(out, "(");
+ while (current) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
-static int cil_unfill_level(struct cil_level *lvl, char **out_str) {
- int rc = SEPOL_ERR;
- size_t len = 0;
- char *sens, *cats = NULL;
- sens = lvl->sens_str;
- len = strlen(sens) + 3; // '()\0'
- if (lvl->cats != NULL) {
- rc = cil_unfill_cats(lvl->cats, &cats);
- if (rc != SEPOL_OK)
- goto exit;
- len += strlen(cats) + 1;
- }
- *out_str = cil_malloc(len);
- if (cats == NULL) {
- if (sprintf(*out_str, "(%s)", sens) < 0) {
- cil_log(CIL_ERR, "Error unpacking and writing level\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- } else {
- if (sprintf(*out_str, "(%s %s)", sens, cats) < 0) {
- cil_log(CIL_ERR, "Error unpacking and writing level\n");
- rc = SEPOL_ERR;
- goto exit;
- }
+ fprintf(out, "%s", datum_to_str(current->data));
+ current = current->next;
}
- rc = SEPOL_OK;
-exit:
- free(cats);
- return rc;
-}
-
-static int cil_unfill_levelrange(struct cil_levelrange *lvlrnge, char **out_str) {
- int rc = SEPOL_ERR;
- size_t len = 0;
- char *low = NULL, *high = NULL;
- if (lvlrnge->low_str != NULL) {
- low = strdup(lvlrnge->low_str);
- if (low == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy level string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- } else {
- rc = cil_unfill_level(lvlrnge->low, &low);
- if (rc != SEPOL_OK)
- goto exit;
- }
- if (lvlrnge->high_str != NULL) {
- high = strdup(lvlrnge->high_str);
- if (high == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy level string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- } else {
- rc = cil_unfill_level(lvlrnge->high, &high);
- if (rc != SEPOL_OK)
- goto exit;
- }
- len = strlen(low) + strlen(high) + 4;
- *out_str = cil_malloc(len);
- if (sprintf(*out_str, "(%s %s)", low, high) < 0) {
- cil_log(CIL_ERR, "Error unpacking and writing levelrange\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- rc = SEPOL_OK;
-exit:
- free(low);
- free(high);
- return rc;
+ fprintf(out, ")");
}
-static int cil_unfill_context(struct cil_context *context, char **out_str) {
- int rc = SEPOL_ERR;
- size_t len = 0;
- char *user_str, *role_str, *type_str;
- char *range_str = NULL;
-
- user_str = context->user_str;
- role_str = context->role_str;
- type_str = context->type_str;
- if (context->range_str != NULL) {
- range_str = strdup(context->range_str);
- if (range_str == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy range string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- } else {
- rc = cil_unfill_levelrange(context->range, &range_str);
- if (rc != SEPOL_OK)
- goto exit;
- }
- len = strlen(user_str) + strlen(role_str) + strlen(type_str)
- + strlen(range_str) + 6;
- *out_str = cil_malloc(len);
- if (sprintf(*out_str, "(%s %s %s %s)", user_str, role_str, type_str, range_str) < 0) {
- cil_log(CIL_ERR, "Error unpacking and writing context\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- rc = SEPOL_OK;
-exit:
- free(range_str);
- return rc;
-}
+static void write_string_list(FILE *out, struct cil_list *list)
+{
+ struct cil_list_item *curr;
+ int notfirst = 0;
-static int cil_unfill_permx(struct cil_permissionx *permx, char **out_str) {
- size_t len = 3;
- int rc = SEPOL_ERR;
- char *kind, *obj;
- char *expr = NULL;
+ if (!list) {
+ fprintf(out, "()");
+ return;
+ }
- switch (permx->kind) {
- case CIL_PERMX_KIND_IOCTL:
- kind = CIL_KEY_IOCTL;
- break;
- default:
- cil_log(CIL_ERR, "Unknown permissionx kind: %d\n", permx->kind);
- rc = SEPOL_ERR;
- goto exit;
- break;
- }
- obj = permx->obj_str;
- rc = cil_unfill_expr(permx->expr_str, &expr, 1);
- if (rc != SEPOL_OK)
- goto exit;
- len += strlen(kind) + strlen(obj) + strlen(expr) + 2;
- *out_str = cil_malloc(len);
- if (sprintf(*out_str, "(%s %s %s)", kind, obj, expr) < 0) {
- cil_log(CIL_ERR, "Error writing xperm\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- rc = SEPOL_OK;
-exit:
- free(expr);
- return rc;
+ fprintf(out, "(");
+ cil_list_for_each(curr, list) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ fprintf(out, "%s", (char*)curr->data);
+ }
+ fprintf(out, ")");
}
-#define cil_write_unsupported(flavor) _cil_write_unsupported(flavor, __LINE__)
-static int _cil_write_unsupported(const char *flavor, int line) {
- cil_log(CIL_ERR,
- "flavor \"%s\" is not supported, look in file \"%s\""
- " on line %d to add support.\n", flavor, __FILE__, line);
- return SEPOL_ENOTSUP;
-}
+static void write_datum_list(FILE *out, struct cil_list *list)
+{
+ struct cil_list_item *curr;
+ int notfirst = 0;
-static int cil_write_policycap(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_policycap *polcap = (struct cil_policycap *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_POLICYCAP, polcap->datum.name);
- return SEPOL_OK;
-}
+ if (!list) {
+ fprintf(out, "()");
+ return;
+ }
-static int cil_write_perm(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_perm *perm = (struct cil_perm *)node->data;
- fprintf(cil_out, "%s", perm->datum.name);
- if (node->next != NULL)
- fprintf(cil_out, " ");
- return SEPOL_OK;
+ fprintf(out, "(");
+ cil_list_for_each(curr, list) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ fprintf(out, "%s", datum_to_str(curr->data));
+ }
+ fprintf(out, ")");
}
+static void write_classperms(FILE *out, struct cil_classperms *cp)
+{
+ if (!cp) {
+ fprintf(out, "()");
+ return;
+ }
-static int cil_write_class(struct cil_tree_node *node, uint32_t *finished,
- struct cil_args_write *extra_args) {
- int rc = SEPOL_ERR;
- FILE *cil_out = extra_args->cil_out;
- struct cil_symtab_datum *datum = (struct cil_symtab_datum *)node->data;
- char *class_type = (node->flavor == CIL_CLASS) ? CIL_KEY_CLASS : CIL_KEY_COMMON;
-
- /* print preamble */
- fprintf(cil_out, "(%s %s ", class_type, datum->name);
-
- if (node->cl_head == NULL) {
- /* no associated perms in this part of tree */
- fprintf(cil_out, "()");
- } else {
-
- /* visit subtree (perms) */
- rc = cil_tree_walk(node, __cil_write_node_helper,
- __cil_write_first_child_helper,
- __cil_write_last_child_helper,
- extra_args);
- if (rc != SEPOL_OK)
- goto exit;
- }
-
- /* postamble (trailing paren) */
- fprintf(cil_out, ")\n");
- *finished = CIL_TREE_SKIP_HEAD;
- rc = SEPOL_OK;
-exit:
- return rc;
-}
-
-static int cil_write_classorder(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *ord_str = NULL;
- struct cil_classorder *classord = (struct cil_classorder *)node->data;
-
- /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */
- rc = cil_unfill_expr(classord->class_list_str, &ord_str, 1);
- if (rc != SEPOL_OK)
- goto exit;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_CLASSORDER, ord_str);
- rc = SEPOL_OK;
-exit:
- free(ord_str);
- return rc;
+ fprintf(out, "(%s ", datum_or_str(DATUM(cp->class), cp->class_str));
+ if (cp->perms)
+ write_expr(out, cp->perms);
+ else
+ write_expr(out, cp->perm_strs);
+ fprintf(out, ")");
}
-static int cil_write_classcommon(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_classcommon *classcommon = (struct cil_classcommon *)node->data;
- fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_CLASSCOMMON, classcommon->class_str,
- classcommon->common_str);
- return SEPOL_OK;
-}
+static void write_classperms_list(FILE *out, struct cil_list *cp_list)
+{
+ struct cil_list_item *curr;
+ int notfirst = 0;
+ int num = 0;
-static int cil_write_sid(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_sid *sid = (struct cil_sid *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_SID, sid->datum.name);
- return SEPOL_OK;
-}
+ if (!cp_list) {
+ fprintf(out, "()");
+ return;
+ }
-static int cil_write_sidcontext(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *sid;
- char *ctx_str = NULL;
- struct cil_sidcontext *sidcon = (struct cil_sidcontext *)node->data;
-
- sid = sidcon->sid_str;
- if (sidcon->context_str != NULL) {
- ctx_str = strdup(sidcon->context_str);
- if (ctx_str == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy context string.\n");
- rc = SEPOL_ERR;
- goto exit;
+ cil_list_for_each(curr, cp_list) {
+ num++;
+ }
+ if (num > 1)
+ fprintf(out, "(");
+ cil_list_for_each(curr, cp_list) {
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ if (curr->flavor == CIL_CLASSPERMS) {
+ write_classperms(out, curr->data);
+ } else {
+ struct cil_classperms_set *cp_set = curr->data;
+ struct cil_classpermission *cp = cp_set->set;
+ if (cp) {
+ if (cp->datum.name)
+ fprintf(out, "%s", datum_to_str(DATUM(cp)));
+ else
+ write_classperms_list(out,cp->classperms);
+ } else {
+ fprintf(out, "%s", cp_set->set_str);
+ }
}
- } else {
- rc = cil_unfill_context(sidcon->context, &ctx_str);
- if (rc != SEPOL_OK)
- goto exit;
- }
- fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_SIDCONTEXT, sid, ctx_str);
- rc = SEPOL_OK;
-exit:
- free(ctx_str);
- return rc;
-}
-
-static int cil_write_sidorder(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *ord_str = NULL;
- struct cil_sidorder *sidord = (struct cil_sidorder *)node->data;
-
- /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */
- rc = cil_unfill_expr(sidord->sid_list_str, &ord_str, 1);
- if (rc != SEPOL_OK)
- goto exit;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_SIDORDER, ord_str);
- rc = SEPOL_OK;
-exit:
- free(ord_str);
- return rc;
-}
-
-static int cil_write_user(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_user *user = (struct cil_user *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_USER, user->datum.name);
- return SEPOL_OK;
-}
-
-static int cil_write_userrole(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_userrole *userrole = (struct cil_userrole *)node->data;
- fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERROLE, userrole->user_str,
- userrole->role_str);
- return SEPOL_OK;
+ }
+ if (num > 1)
+ fprintf(out, ")");
}
-static int cil_write_userlevel(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_userlevel *usrlvl = (struct cil_userlevel *)node->data;
- int rc = SEPOL_ERR;
- char *usr;
- char *lvl = NULL;
-
- usr = usrlvl->user_str;
- if (usrlvl->level_str != NULL) {
- lvl = strdup(usrlvl->level_str);
- if (lvl == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy level string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
+static void write_permx(FILE *out, struct cil_permissionx *permx)
+{
+ if (permx->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(permx)));
} else {
- rc = cil_unfill_level(usrlvl->level, &lvl);
- if (rc != SEPOL_OK)
- goto exit;
- }
- fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERLEVEL, usr, lvl);
- rc = SEPOL_OK;
-exit:
- free(lvl);
- return rc;
+ fprintf(out, "(");
+ fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "<?KIND>");
+ fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
+ write_expr(out, permx->expr_str);
+ fprintf(out, ")");
+ }
}
-static int cil_write_userrange(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_userrange *usrrng = (struct cil_userrange *)node->data;
- int rc = SEPOL_ERR;
- char *usr;
- char *range = NULL;
-
- usr = usrrng->user_str;
- if (usrrng->range_str != NULL) {
- range = strdup(usrrng->range_str);
- if (range == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy levelrange string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
+static void write_cats(FILE *out, struct cil_cats *cats)
+{
+ if (cats->datum_expr) {
+ write_expr(out, cats->datum_expr);
} else {
- rc = cil_unfill_levelrange(usrrng->range, &range);
- if (rc != SEPOL_OK)
- goto exit;
- }
- fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERRANGE, usr, range);
- rc = SEPOL_OK;
-exit:
- free(range);
- return rc;
-}
-
-static int cil_write_role(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_role *role = (struct cil_role *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_ROLE, role->datum.name);
- return SEPOL_OK;
-}
-
-static int cil_write_roletype(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_roletype *roletype = (struct cil_roletype *)node->data;
- fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_ROLETYPE, roletype->role_str, roletype->type_str);
- return SEPOL_OK;
-}
-
-static int cil_write_roleattribute(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_roleattribute *roleattr = (struct cil_roleattribute *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_ROLEATTRIBUTE, roleattr->datum.name);
- return SEPOL_OK;
-}
-
-static int cil_write_type(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_type *type = (struct cil_type *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPE, type->datum.name);
- return SEPOL_OK;
-}
-
-static int cil_write_typepermissive(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_typepermissive *type = (struct cil_typepermissive *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPEPERMISSIVE, type->type_str);
- return SEPOL_OK;
-}
-
-static int cil_write_typeattribute(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_typeattribute *typeattr = (struct cil_typeattribute *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPEATTRIBUTE, typeattr->datum.name);
- return SEPOL_OK;
-}
-
-static int cil_write_typeattributeset(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *typeattr;
- char *set_str = NULL;
- struct cil_typeattributeset *typeattrset = (struct cil_typeattributeset *)node->data;
-
- typeattr = typeattrset->attr_str;
- rc = cil_unfill_expr(typeattrset->str_expr, &set_str, 1);
- if (rc != SEPOL_OK)
- goto exit;
-
- fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_TYPEATTRIBUTESET, typeattr, set_str);
- rc = SEPOL_OK;
-exit:
- free(set_str);
- return rc;
+ write_expr(out, cats->str_expr);
+ }
}
-static int cil_write_expandtypeattribute(struct cil_tree_node *node, FILE *cil_out)
+static void write_level(FILE *out, struct cil_level *level, int print_name)
{
- int rc = SEPOL_ERR;
- char *attr_strs = NULL;
- struct cil_expandtypeattribute *expandattr = (struct cil_expandtypeattribute *)node->data;
-
- rc = cil_unfill_expr(expandattr->attr_strs, &attr_strs, 1);
- if (rc != SEPOL_OK)
- goto exit;
-
- fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_EXPANDTYPEATTRIBUTE, attr_strs,
- expandattr->expand ? CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE);
- rc = SEPOL_OK;
-exit:
- free(attr_strs);
- return rc;
-}
-
-static int cil_write_alias(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *type;
- struct cil_alias *alias = (struct cil_alias *)node->data;
-
- switch (node->flavor) {
- case CIL_TYPEALIAS:
- type = CIL_KEY_TYPEALIAS;
- break;
- case CIL_SENSALIAS:
- type = CIL_KEY_SENSALIAS;
- break;
- case CIL_CATALIAS:
- type = CIL_KEY_CATALIAS;
- break;
- default:
- cil_log(CIL_ERR, "Unknown alias type: %d\n", node->flavor);
- rc = SEPOL_ERR;
- goto exit;
- break;
+ if (print_name && level->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(level)));
+ } else {
+ fprintf(out, "(");
+ fprintf(out, "%s", datum_or_str(DATUM(level->sens), level->sens_str));
+ if (level->cats) {
+ fprintf(out, " ");
+ write_cats(out, level->cats);
+ }
+ fprintf(out, ")");
}
- fprintf(cil_out, "(%s %s)\n", type, alias->datum.name);
- rc = SEPOL_OK;
-exit:
- return rc;
}
-static int cil_write_aliasactual(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *type, *alias, *actual;
- struct cil_aliasactual *aliasact = (struct cil_aliasactual *)node->data;
-
- switch (node->flavor) {
- case CIL_TYPEALIASACTUAL:
- type = CIL_KEY_TYPEALIASACTUAL;
- break;
- case CIL_SENSALIASACTUAL:
- type = CIL_KEY_SENSALIASACTUAL;
- break;
- case CIL_CATALIASACTUAL:
- type = CIL_KEY_CATALIASACTUAL;
- break;
- default:
- cil_log(CIL_ERR, "Unknown alias type: %d\n", node->flavor);
- rc = SEPOL_ERR;
- goto exit;
- break;
+static void write_range(FILE *out, struct cil_levelrange *range, int print_name)
+{
+ if (print_name && range->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(range)));
+ } else {
+ fprintf(out, "(");
+ if (range->low)
+ write_level(out, range->low, CIL_TRUE);
+ else
+ fprintf(out, "%s", range->low_str);
+ fprintf(out, " ");
+ if (range->high)
+ write_level(out, range->high, CIL_TRUE);
+ else
+ fprintf(out, "%s", range->high_str);
+ fprintf(out, ")");
}
- alias = aliasact->alias_str;
- actual = aliasact->actual_str;
- fprintf(cil_out, "(%s %s %s)\n", type, alias, actual);
- rc = SEPOL_OK;
-exit:
- return rc;
-}
-
-static int cil_write_nametypetransition(struct cil_tree_node *node, FILE *cil_out) {
- char *src, *tgt, *obj, *res, *name;
- struct cil_nametypetransition *ntrans = (struct cil_nametypetransition *)node->data;
-
- src = ntrans->src_str;
- tgt = ntrans->tgt_str;
- obj = ntrans->obj_str;
- res = ntrans->result_str;
- name = ntrans->name_str;
- fprintf(cil_out, "(%s %s %s %s \"%s\" %s)\n", CIL_KEY_TYPETRANSITION,
- src, tgt, obj, name, res);
- return SEPOL_OK;
}
-static int cil_write_avrule_x(struct cil_avrule *avrule, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *rulekind, *src, *tgt;
- char *xperms = NULL;
-
- switch (avrule->rule_kind) {
- case CIL_AVRULE_ALLOWED:
- rulekind = CIL_KEY_ALLOWX;
- break;
- case CIL_AVRULE_AUDITALLOW:
- rulekind = CIL_KEY_AUDITALLOWX;
- break;
- case CIL_AVRULE_DONTAUDIT:
- rulekind = CIL_KEY_DONTAUDITX;
- break;
- case CIL_AVRULE_NEVERALLOW:
- rulekind = CIL_KEY_NEVERALLOWX;
- break;
- default:
- cil_log(CIL_ERR, "Unknown AVRULE type: %d\n", avrule->rule_kind);
- rc = SEPOL_ERR;
- goto exit;
- break;
- }
- src = avrule->src_str;
- tgt = avrule->tgt_str;
-
- if (avrule->perms.x.permx_str != NULL) {
- xperms = strdup(avrule->perms.x.permx_str);
- if (xperms == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy xperms string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
+static void write_context(FILE *out, struct cil_context *context, int print_name)
+{
+ if (print_name && context->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(context)));
} else {
- rc = cil_unfill_permx(avrule->perms.x.permx, &xperms);
- if (rc != SEPOL_OK)
- goto exit;
- }
- fprintf(cil_out, "(%s %s %s %s)\n", rulekind, src, tgt, xperms);
- rc = SEPOL_OK;
-exit:
- free(xperms);
- return rc;
+ fprintf(out, "(");
+ fprintf(out, "%s ", datum_or_str(DATUM(context->user), context->user_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(context->role), context->role_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(context->type), context->type_str));
+ if (context->range)
+ write_range(out, context->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", context->range_str);
+ fprintf(out, ")");
+ }
}
-static int cil_write_avrule_orig(struct cil_avrule *avrule, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *rulekind, *src, *tgt;
- char *classperms = NULL;
-
- switch (avrule->rule_kind) {
- case CIL_AVRULE_ALLOWED:
- rulekind = CIL_KEY_ALLOW;
- break;
- case CIL_AVRULE_AUDITALLOW:
- rulekind = CIL_KEY_AUDITALLOW;
- break;
- case CIL_AVRULE_DONTAUDIT:
- rulekind = CIL_KEY_DONTAUDIT;
- break;
- case CIL_AVRULE_NEVERALLOW:
- rulekind = CIL_KEY_NEVERALLOW;
- break;
- default:
- cil_log(CIL_ERR, "Unknown AVRULE type: %d\n", avrule->rule_kind);
- rc = SEPOL_ERR;
- goto exit;
- break;
- }
- src = avrule->src_str;
- tgt = avrule->tgt_str;
-
- rc = cil_unfill_classperms_list(avrule->perms.classperms, &classperms, 0);
- if (rc != SEPOL_OK)
- goto exit;
- fprintf(cil_out, "(%s %s %s %s)\n", rulekind, src, tgt, classperms);
- rc = SEPOL_OK;
-exit:
- free(classperms);
- return rc;
+static void write_ipaddr(FILE *out, struct cil_ipaddr *ipaddr)
+{
+ if (ipaddr->datum.name) {
+ fprintf(out, "%s", datum_to_str(DATUM(ipaddr)));
+ } else {
+ char buf[256];
+ if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL)
+ strcpy(buf, "<?IPADDR>");
+ fprintf(out, "(%s)", buf);
+ }
}
-static int cil_write_avrule(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- struct cil_avrule *avrule = (struct cil_avrule *)node->data;
-
- if (avrule->is_extended)
- rc = cil_write_avrule_x(avrule, cil_out);
+static void write_constrain(FILE *out, struct cil_constrain *cons)
+{
+ write_classperms_list(out, cons->classperms);
+ fprintf(out, " ");
+ if (cons->datum_expr)
+ write_expr(out, cons->datum_expr);
else
- rc = cil_write_avrule_orig(avrule, cil_out);
- return rc;
-}
-
-static int cil_write_type_rule(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *type, *src, *tgt, *obj, *res;
- struct cil_type_rule *typerule = (struct cil_type_rule *)node->data;
-
- switch (typerule->rule_kind) {
- case CIL_TYPE_TRANSITION:
- type = CIL_KEY_TYPETRANSITION;
- break;
- case CIL_TYPE_MEMBER:
- type = CIL_KEY_TYPEMEMBER;
- break;
- case CIL_TYPE_CHANGE:
- type = CIL_KEY_TYPECHANGE;
- break;
- default:
- cil_log(CIL_ERR, "Unknown TYPERULE type: %d\n", typerule->rule_kind);
- rc = SEPOL_ERR;
- goto exit;
- break;
- }
- src = typerule->src_str;
- tgt = typerule->tgt_str;
- obj = typerule->obj_str;
- res = typerule->result_str;
- fprintf(cil_out, "(%s %s %s %s %s)\n", type, src, tgt, obj, res);
- rc = SEPOL_OK;
-exit:
- return rc;
-}
-
-static int cil_write_sens(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_sens *sens = (struct cil_sens *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_SENSITIVITY, sens->datum.name);
- return SEPOL_OK;
-}
-
-static int cil_write_cat(struct cil_tree_node *node, FILE *cil_out) {
- struct cil_cat *cat = (struct cil_cat *)node->data;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_CATEGORY, cat->datum.name);
- return SEPOL_OK;
-}
-
-static int cil_write_senscat(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *sens;
- char *cats = NULL;
- struct cil_senscat *senscat = (struct cil_senscat *)node->data;
-
- sens = senscat->sens_str;
- rc = cil_unfill_cats(senscat->cats, &cats);
- if (rc != SEPOL_OK)
- goto exit;
- /* TODO: deal with extra/missing parens */
- fprintf(cil_out, "(%s %s (%s))\n", CIL_KEY_SENSCAT, sens, cats);
- rc = SEPOL_OK;
-exit:
- free(cats);
- return rc;
-}
-
-static int cil_write_catorder(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *ord_str = NULL;
- struct cil_catorder *catord = (struct cil_catorder *)node->data;
-
- /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */
- rc = cil_unfill_expr(catord->cat_list_str, &ord_str, 1);
- if (rc != SEPOL_OK)
- goto exit;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_CATORDER, ord_str);
- rc = SEPOL_OK;
-exit:
- free(ord_str);
- return rc;
-}
-
-static int cil_write_sensorder(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *ord_str = NULL;
- struct cil_sensorder *sensord = (struct cil_sensorder *)node->data;
-
- /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */
- rc = cil_unfill_expr(sensord->sens_list_str, &ord_str, 1);
- if (rc != SEPOL_OK)
- goto exit;
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_SENSITIVITYORDER, ord_str);
- rc = SEPOL_OK;
-exit:
- free(ord_str);
- return rc;
+ write_expr(out, cons->str_expr);
}
-static int cil_write_genfscon(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- char *ctx_str = NULL;
-
- struct cil_genfscon *genfscon = (struct cil_genfscon *)node->data;
- if (genfscon->context_str != NULL) {
- ctx_str = strdup(genfscon->context_str);
- if (ctx_str == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy context string.\n");
- rc = SEPOL_ERR;
- goto exit;
+static void write_call_args(FILE *out, struct cil_list *args)
+{
+ struct cil_list_item *item;
+ int notfirst = 0;
+
+ fprintf(out, "(");
+ cil_list_for_each(item, args) {
+ struct cil_args* arg = item->data;
+ enum cil_flavor arg_flavor = arg->flavor;
+ if (notfirst)
+ fprintf(out, " ");
+ else
+ notfirst = 1;
+ switch (arg_flavor) {
+ case CIL_TYPE:
+ case CIL_ROLE:
+ case CIL_USER:
+ case CIL_SENS:
+ case CIL_CAT:
+ case CIL_BOOL:
+ case CIL_CLASS:
+ case CIL_MAP_CLASS:
+ case CIL_NAME: {
+ fprintf(out, "%s", datum_or_str(arg->arg, arg->arg_str));
+ break;
}
- } else {
- rc = cil_unfill_context(genfscon->context, &ctx_str);
- if (rc != SEPOL_OK)
- goto exit;
- }
- fprintf(cil_out, "(%s %s %s %s)\n", CIL_KEY_GENFSCON, genfscon->fs_str,
- genfscon->path_str, ctx_str);
- rc = SEPOL_OK;
-exit:
- free(ctx_str);
- return rc;
-}
-
-static int cil_unfill_classperms(struct cil_list_item *curr, char **out_str) {
- int rc = SEPOL_ERR;
- size_t len = 3;
- char *class_str;
- char *perms_str = NULL;
- struct cil_classperms *cp = (struct cil_classperms *)curr->data;
-
- class_str = cp->class_str;
- len += strlen(class_str) + 1;
-
- /* fill_perms just calls gen_expr */
- rc = cil_unfill_expr(cp->perm_strs, &perms_str, 1);
- if (rc != SEPOL_OK)
- goto exit;
- len += strlen(perms_str);
- *out_str = cil_malloc(len);
- sprintf(*out_str, "(%s %s)", class_str, perms_str);
- rc = SEPOL_OK;
-exit:
- free(perms_str);
- return rc;
-}
-
-static int cil_unfill_classperms_list(struct cil_list *classperms, char **out_str, int paren) {
- int rc = SEPOL_ERR;
- struct cil_list_item *curr;
- char *str = NULL;
-
- /* reuse cil_list to keep track of strings */
- struct cil_list *str_list = NULL;
- cil_list_init(&str_list, CIL_NONE);
- cil_list_for_each(curr, classperms) {
- switch (curr->flavor) {
- case CIL_CLASSPERMS_SET:
- str = strdup(((struct cil_classperms_set *)curr->data)->set_str);
- if (str == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy classpermset.\n");
- rc = SEPOL_ERR;
- goto exit;
+ case CIL_CATSET: {
+ if (arg->arg) {
+ struct cil_catset *catset = (struct cil_catset *)arg->arg;
+ write_cats(out, catset->cats);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
}
break;
- case CIL_CLASSPERMS:
- rc = cil_unfill_classperms(curr, &str);
- if (rc != SEPOL_OK)
- goto exit;
+ }
+ case CIL_LEVEL: {
+ if (arg->arg) {
+ struct cil_level *level = (struct cil_level *)arg->arg;
+ write_level(out, level, CIL_TRUE);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
break;
+ }
+ case CIL_LEVELRANGE: {
+ if (arg->arg) {
+ struct cil_levelrange *range = (struct cil_levelrange *)arg->arg;
+ write_range(out, range, CIL_TRUE);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
+ break;
+ }
+ case CIL_IPADDR: {
+ if (arg->arg) {
+ struct cil_ipaddr *addr = (struct cil_ipaddr *)arg->arg;
+ write_ipaddr(out, addr);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
+ break;
+ }
+ case CIL_CLASSPERMISSION: {
+ if (arg->arg) {
+ struct cil_classpermission *cp = (struct cil_classpermission *)arg->arg;
+ if (cp->datum.name)
+ fprintf(out, "%s", datum_to_str(DATUM(cp)));
+ else
+ write_classperms_list(out, cp->classperms);
+ } else {
+ fprintf(out, "%s", arg->arg_str);
+ }
+ break;
+ }
default:
- cil_log(CIL_ERR, "Unrecognized classperms flavor\n.");
- goto exit;
+ fprintf(out, "<?ARG:%s>", datum_or_str(arg->arg, arg->arg_str));
+ break;
}
- cil_list_append(str_list, CIL_STRING, (void *) str);
- str = NULL;
- }
- rc = __cil_strlist_concat(str_list, out_str, paren);
- if (rc != SEPOL_OK)
- goto exit;
- rc = SEPOL_OK;
-exit:
- cil_list_for_each(curr, str_list) {
- free(curr->data);
- }
- cil_list_destroy(&str_list, 0);
- return rc;
+ }
+ fprintf(out, ")");
}
-static int cil_write_fsuse(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- struct cil_fsuse *fsuse = (struct cil_fsuse *)node->data;
- char *type, *fsname;
- char *ctx_str = NULL;
+static void write_call_args_tree(FILE *out, struct cil_tree_node *arg_node)
+{
+ while (arg_node) {
+ if (arg_node->data) {
+ fprintf(out, "%s", (char *)arg_node->data);
+ } else if (arg_node->cl_head) {
+ fprintf(out, "(");
+ write_call_args_tree(out, arg_node->cl_head);
+ fprintf(out, ")");
+ }
+ if (arg_node->next)
+ fprintf(out, " ");
+ arg_node = arg_node->next;
+ }
+}
- switch(fsuse->type) {
- case CIL_FSUSE_XATTR:
- type = CIL_KEY_XATTR;
+static const char *macro_param_flavor_to_string(enum cil_flavor flavor)
+{
+ const char *str;
+ switch(flavor) {
+ case CIL_TYPE:
+ str = CIL_KEY_TYPE;
break;
- case CIL_FSUSE_TASK:
- type = CIL_KEY_TASK;
+ case CIL_ROLE:
+ str = CIL_KEY_ROLE;
break;
- case CIL_FSUSE_TRANS:
- type = CIL_KEY_TRANS;
+ case CIL_USER:
+ str = CIL_KEY_USER;
break;
- default:
- cil_log(CIL_ERR, "Unrecognized fsuse type\n");
- rc = SEPOL_ERR;
- goto exit;
+ case CIL_SENS:
+ str = CIL_KEY_SENSITIVITY;
break;
- }
-
- fsname = fsuse->fs_str;
- if (fsuse->context_str != NULL) {
- ctx_str = strdup(fsuse->context_str);
- if (ctx_str == NULL) {
- cil_log(CIL_ERR, "OOM. Unable to copy context string.\n");
- rc = SEPOL_ERR;
- goto exit;
- }
- } else {
- rc = cil_unfill_context(fsuse->context, &ctx_str);
- if (rc != SEPOL_OK)
- goto exit;
- }
- fprintf(cil_out, "(%s %s %s %s)\n", CIL_KEY_FSUSE, type, fsname, ctx_str);
-exit:
- free(ctx_str);
- return rc;
-}
-
-static int cil_write_constrain(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_ERR;
- struct cil_constrain *cons = (struct cil_constrain *)node->data;
- char *flav;
- char *classperms = NULL;
- char *expr = NULL;
-
- flav = (node->flavor == CIL_CONSTRAIN) ? CIL_KEY_CONSTRAIN : CIL_KEY_MLSCONSTRAIN;
-
- rc = cil_unfill_classperms_list(cons->classperms, &classperms, 0);
- if (rc != SEPOL_OK)
- goto exit;
-
- rc = cil_unfill_expr(cons->str_expr, &expr, 0);
- if (rc != SEPOL_OK)
- goto exit;
-
- fprintf(cil_out, "(%s %s %s)\n", flav, classperms, expr);
-exit:
- free(classperms);
- free(expr);
- return rc;
-}
-
-static int cil_write_handleunknown(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_OK;
- struct cil_handleunknown *handunknown = (struct cil_handleunknown *)node->data;
- char *val = NULL;
- switch (handunknown->handle_unknown) {
- case SEPOL_ALLOW_UNKNOWN:
- val = CIL_KEY_HANDLEUNKNOWN_ALLOW;
+ case CIL_CAT:
+ str = CIL_KEY_CATEGORY;
break;
- case SEPOL_DENY_UNKNOWN:
- val = CIL_KEY_HANDLEUNKNOWN_DENY;
+ case CIL_CATSET:
+ str = CIL_KEY_CATSET;
break;
- case SEPOL_REJECT_UNKNOWN:
- val = CIL_KEY_HANDLEUNKNOWN_REJECT;
+ case CIL_LEVEL:
+ str = CIL_KEY_LEVEL;
break;
- default:
- cil_log(CIL_ERR, "Unknown handleunknown value: %d.\n",
- handunknown->handle_unknown);
- rc = SEPOL_ERR;
- goto exit;
+ case CIL_LEVELRANGE:
+ str = CIL_KEY_LEVELRANGE;
break;
- }
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_HANDLEUNKNOWN, val);
-exit:
- return rc;
-}
-
-static int cil_write_mls(struct cil_tree_node *node, FILE *cil_out) {
- int rc = SEPOL_OK;
- struct cil_mls *mls = (struct cil_mls *)node->data;
- char *val = NULL;
- switch (mls->value) {
- case CIL_TRUE:
- val = CIL_KEY_CONDTRUE;
+ case CIL_CLASS:
+ str = CIL_KEY_CLASS;
break;
- case CIL_FALSE:
- val = CIL_KEY_CONDFALSE;
+ case CIL_IPADDR:
+ str = CIL_KEY_IPADDR;
+ break;
+ case CIL_MAP_CLASS:
+ str = CIL_KEY_MAP_CLASS;
+ break;
+ case CIL_CLASSPERMISSION:
+ str = CIL_KEY_CLASSPERMISSION;
+ break;
+ case CIL_BOOL:
+ str = CIL_KEY_BOOL;
+ break;
+ case CIL_STRING:
+ str = CIL_KEY_STRING;
+ break;
+ case CIL_NAME:
+ str = CIL_KEY_NAME;
break;
default:
- cil_log(CIL_ERR, "Unknown mls value: %d.\n", mls->value);
- rc = SEPOL_ERR;
- goto exit;
+ str = "<?FLAVOR>";
break;
}
- fprintf(cil_out, "(%s %s)\n", CIL_KEY_MLS, val);
-exit:
- return rc;
+ return str;
}
-static int __cil_write_first_child_helper(struct cil_tree_node *node, void *extra_args)
+void cil_write_src_info_node(FILE *out, struct cil_tree_node *node)
{
- int rc = SEPOL_ERR;
- struct cil_args_write *args = (struct cil_args_write *) extra_args;
- FILE *cil_out = NULL;
-
- if (node == NULL || extra_args == NULL) {
- goto exit;
+ struct cil_src_info *info = node->data;
+ if (info->kind == CIL_KEY_SRC_CIL || info->kind == CIL_KEY_SRC_HLL_LMS) {
+ fprintf(out, ";;* lms %u %s\n", info->hll_line, info->path);
+ } else if (info->kind == CIL_KEY_SRC_HLL_LMX) {
+ fprintf(out, ";;* lmx %u %s\n", info->hll_line, info->path);
+ } else {
+ fprintf(out, ";;* <?SRC_INFO_KIND> %u %s\n", info->hll_line, info->path);
}
-
- cil_out = args->cil_out;
-
- if (node->parent && node->parent->flavor != CIL_ROOT && node->parent->flavor != CIL_SRC_INFO)
- fprintf(cil_out,"(");
- rc = SEPOL_OK;
-exit:
- return rc;
}
-static int __cil_write_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
+void cil_write_ast_node(FILE *out, struct cil_tree_node *node)
{
- int rc = SEPOL_OK;
- struct cil_args_write *args = NULL;
- FILE *cil_out = NULL;
-
- if (node == NULL || extra_args == NULL) {
- goto exit;
+ if (!node->data) {
+ return;
}
- args = extra_args;
- cil_out = args->cil_out;
-
- switch (node->flavor) {
- case CIL_BLOCK:
- rc = cil_write_unsupported("CIL_BLOCK");
+ switch(node->flavor) {
+ case CIL_NODE: {
+ fprintf(out, "%s\n", (char *)node->data);
break;
- case CIL_BLOCKABSTRACT:
- rc = cil_write_unsupported("CIL_BLOCKABSTRACT");
+ }
+ case CIL_BLOCK: {
+ struct cil_block *block = node->data;
+ fprintf(out, "(block %s", datum_to_str(DATUM(block)));
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
break;
- case CIL_BLOCKINHERIT:
- rc = cil_write_unsupported("CIL_BLOCKINHERIT");
+ }
+ case CIL_BLOCKINHERIT: {
+ struct cil_blockinherit *inherit = node->data;
+ fprintf(out, "(blockinherit %s)\n", datum_or_str(DATUM(inherit->block), inherit->block_str));
break;
- case CIL_IN:
- rc = cil_write_unsupported("CIL_IN");
+ }
+ case CIL_IN: {
+ struct cil_in *in = node->data;
+ fprintf(out, "(in %s", in->block_str);
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
break;
- case CIL_POLICYCAP:
- cil_write_policycap(node, cil_out);
+ }
+ case CIL_OPTIONAL: {
+ struct cil_optional *optional = node->data;
+ fprintf(out, "(optional %s", datum_to_str(DATUM(optional)));
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
break;
- case CIL_PERM:
- rc = cil_write_perm(node, cil_out);
+ }
+ case CIL_BOOLEANIF: {
+ struct cil_booleanif *bif = node->data;
+ fprintf(out, "(booleanif ");
+ if (bif->datum_expr)
+ write_expr(out, bif->datum_expr);
+ else
+ write_expr(out, bif->str_expr);
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
break;
- case CIL_MAP_PERM:
- rc = cil_write_unsupported("CIL_MAP_PERM");
+ }
+ case CIL_TUNABLEIF: {
+ struct cil_tunableif *tif = node->data;
+ fprintf(out, "(tunableif ");
+ if (tif->datum_expr)
+ write_expr(out, tif->datum_expr);
+ else
+ write_expr(out, tif->str_expr);
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
break;
- case CIL_CLASSMAPPING:
- rc = cil_write_unsupported("CIL_CLASSMAPPING");
+ }
+ case CIL_CONDBLOCK: {
+ struct cil_condblock *cb = node->data;
+ fprintf(out, "(%s", cb->flavor == CIL_CONDTRUE ? "true" : "false");
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
break;
- case CIL_CLASS:
- rc = cil_write_class(node, finished, extra_args);
+ }
+ case CIL_MACRO: {
+ struct cil_macro *macro = node->data;
+ struct cil_list_item *curr;
+ fprintf(out, "(macro %s (", datum_to_str(DATUM(macro)));
+ if (macro->params) {
+ cil_list_for_each(curr, macro->params) {
+ struct cil_param *param = curr->data;
+ fprintf(out, "(%s %s)", macro_param_flavor_to_string(param->flavor), param->str);
+ }
+ }
+ fprintf(out, ")");
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
break;
- case CIL_COMMON:
- rc = cil_write_class(node, finished, extra_args);
+ }
+ case CIL_CALL: {
+ struct cil_call *call = node->data;
+ fprintf(out, "(call %s", datum_or_str(DATUM(call->macro), call->macro_str));
+ if (call->args) {
+ fprintf(out, " ");
+ write_call_args(out, call->args);
+ } else if (call->args_tree) {
+ fprintf(out, " ");
+ write_call_args_tree(out, call->args_tree->root);
+ }
+ if (!node->cl_head)
+ fprintf(out, ")");
+ fprintf(out, "\n");
break;
- case CIL_MAP_CLASS:
- rc = cil_write_unsupported("CIL_MAP_CLASS");
+ }
+ case CIL_BLOCKABSTRACT: {
+ struct cil_blockabstract *abstract = node->data;
+ fprintf(out, "(blockabstract %s)\n", abstract->block_str);
break;
- case CIL_CLASSORDER:
- rc = cil_write_classorder(node, cil_out);
+ }
+ case CIL_MLS: {
+ struct cil_mls *mls = node->data;
+ fprintf(out, "(mls %s)\n", mls->value ? "true" : "false");
break;
- case CIL_CLASSPERMISSION:
- rc = cil_write_unsupported("CIL_CLASSPERMISSION");
+ }
+ case CIL_HANDLEUNKNOWN: {
+ struct cil_handleunknown *unknown = node->data;
+ fprintf(out, "(handleunknown ");
+ if (unknown->handle_unknown == SEPOL_ALLOW_UNKNOWN)
+ fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_ALLOW);
+ else if (unknown->handle_unknown == SEPOL_DENY_UNKNOWN)
+ fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_DENY);
+ else if (unknown->handle_unknown == SEPOL_REJECT_UNKNOWN)
+ fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_REJECT);
+ else
+ fprintf(out, "<?UNKNOWN>");
+ fprintf(out, ")\n");
break;
- case CIL_CLASSPERMISSIONSET:
- rc = cil_write_unsupported("CIL_CLASSPERMISSIONSET");
+ }
+ case CIL_DEFAULTUSER: {
+ struct cil_default *def = node->data;
+ fprintf(out, "(defaultuser ");
+ if (def->class_datums)
+ write_datum_list(out, def->class_datums);
+ else
+ write_string_list(out, def->class_strs);
+ if (def->object == CIL_DEFAULT_SOURCE)
+ fprintf(out, " source");
+ else if (def->object == CIL_DEFAULT_TARGET)
+ fprintf(out, " target");
+ else
+ fprintf(out, " <?DEFAULT>");
+ fprintf(out, ")\n");
break;
- case CIL_CLASSCOMMON:
- rc = cil_write_classcommon(node, cil_out);
+ }
+ case CIL_DEFAULTROLE: {
+ struct cil_default *def = node->data;
+ fprintf(out, "(defaultrole ");
+ if (def->class_datums)
+ write_datum_list(out, def->class_datums);
+ else
+ write_string_list(out, def->class_strs);
+ if (def->object == CIL_DEFAULT_SOURCE)
+ fprintf(out, " source");
+ else if (def->object == CIL_DEFAULT_TARGET)
+ fprintf(out, " target");
+ else
+ fprintf(out, " <?DEFAULT>");
+ fprintf(out, ")\n");
break;
- case CIL_SID:
- rc = cil_write_sid(node, cil_out);
+ }
+ case CIL_DEFAULTTYPE: {
+ struct cil_default *def = node->data;
+ fprintf(out, "(defaulttype ");
+ if (def->class_datums)
+ write_datum_list(out, def->class_datums);
+ else
+ write_string_list(out, def->class_strs);
+ if (def->object == CIL_DEFAULT_SOURCE)
+ fprintf(out, " source");
+ else if (def->object == CIL_DEFAULT_TARGET)
+ fprintf(out, " target");
+ else
+ fprintf(out, " <?DEFAULT>");
+ fprintf(out, ")\n");
break;
- case CIL_SIDCONTEXT:
- rc = cil_write_sidcontext(node, cil_out);
+ }
+ case CIL_DEFAULTRANGE: {
+ struct cil_defaultrange *def = node->data;
+ fprintf(out, "(defaultrange ");
+ if (def->class_datums)
+ write_datum_list(out, def->class_datums);
+ else
+ write_string_list(out, def->class_strs);
+ if (def->object_range == CIL_DEFAULT_SOURCE_LOW)
+ fprintf(out, " source low");
+ else if (def->object_range == CIL_DEFAULT_SOURCE_HIGH)
+ fprintf(out, " source high");
+ else if (def->object_range == CIL_DEFAULT_SOURCE_LOW_HIGH)
+ fprintf(out, " source low-high");
+ else if (def->object_range == CIL_DEFAULT_TARGET_LOW)
+ fprintf(out, " target low");
+ else if (def->object_range == CIL_DEFAULT_TARGET_HIGH)
+ fprintf(out, " target high");
+ else if (def->object_range == CIL_DEFAULT_TARGET_LOW_HIGH)
+ fprintf(out, " target low-high");
+ else
+ fprintf(out, " <?DEFAULT>");
+ fprintf(out, ")\n");
break;
- case CIL_SIDORDER:
- rc = cil_write_sidorder(node, cil_out);
+ }
+ case CIL_CLASS: {
+ struct cil_class *class = node->data;
+ fprintf(out, "(class %s ", datum_to_str(DATUM(class)));
+ write_node_list(out, node->cl_head);
+ fprintf(out, ")\n");
break;
- case CIL_USER:
- rc = cil_write_user(node, cil_out);
+ }
+ case CIL_CLASSORDER: {
+ struct cil_classorder *classorder = node->data;
+ fprintf(out, "(classorder ");
+ write_string_list(out, classorder->class_list_str);
+ fprintf(out, ")\n");
break;
- case CIL_USERATTRIBUTE:
- rc = cil_write_unsupported("CIL_USERATTRIBUTE");
+ }
+ case CIL_COMMON: {
+ struct cil_class *common = node->data;
+ fprintf(out, "(common %s ", datum_to_str(DATUM(common)));
+ write_node_list(out, node->cl_head);
+ fprintf(out, ")\n");
break;
- case CIL_USERATTRIBUTESET:
- rc = cil_write_unsupported("CIL_USERATTRIBUTESET");
+ }
+ case CIL_CLASSCOMMON: {
+ struct cil_classcommon *cc = node->data;
+ fprintf(out, "(classcommon %s %s)\n", cc->class_str, cc->common_str);
break;
- case CIL_USERROLE:
- rc = cil_write_userrole(node, cil_out);
+ }
+ case CIL_CLASSPERMISSION: {
+ struct cil_classpermission *cp = node->data;
+ fprintf(out, "(classpermission %s)\n", datum_to_str(DATUM(cp)));
break;
- case CIL_USERLEVEL:
- rc = cil_write_userlevel(node, cil_out);
+ }
+ case CIL_CLASSPERMISSIONSET: {
+ struct cil_classpermissionset *cps = node->data;
+ fprintf(out, "(classpermissionset %s ", cps->set_str);
+ write_classperms_list(out, cps->classperms);
+ fprintf(out, ")\n");
break;
- case CIL_USERRANGE:
- rc = cil_write_userrange(node, cil_out);
+ }
+ case CIL_MAP_CLASS: {
+ struct cil_class *map = node->data;
+ fprintf(out, "(classmap %s ", datum_to_str(DATUM(map)));
+ write_node_list(out, node->cl_head);
+ fprintf(out, ")\n");
break;
- case CIL_USERBOUNDS:
- rc = cil_write_unsupported("CIL_USERBOUNDS");
+ }
+ case CIL_CLASSMAPPING: {
+ struct cil_classmapping *mapping = node->data;
+ fprintf(out, "(classmapping %s %s ", mapping->map_class_str, mapping->map_perm_str);
+ write_classperms_list(out, mapping->classperms);
+ fprintf(out, ")\n");
break;
- case CIL_USERPREFIX:
- rc = cil_write_unsupported("CIL_USERPREFIX");
+ }
+ case CIL_PERMISSIONX: {
+ struct cil_permissionx *permx = node->data;
+ fprintf(out, "(permissionx %s (", datum_to_str(DATUM(permx)));
+ fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "<?KIND>");
+ fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
+ write_expr(out, permx->expr_str);
+ fprintf(out, "))\n");
break;
- case CIL_ROLE:
- rc = cil_write_role(node, cil_out);
+ }
+ case CIL_SID: {
+ struct cil_sid *sid = node->data;
+ fprintf(out, "(sid %s)\n", datum_to_str(DATUM(sid)));
break;
- case CIL_ROLETYPE:
- rc = cil_write_roletype(node, cil_out);
+ }
+ case CIL_SIDCONTEXT: {
+ struct cil_sidcontext *sidcon = node->data;
+ fprintf(out, "(sidcontext %s ", sidcon->sid_str);
+ if (sidcon->context)
+ write_context(out, sidcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", sidcon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_ROLEBOUNDS:
- rc = cil_write_unsupported("CIL_ROLEBOUNDS");
+ }
+ case CIL_SIDORDER: {
+ struct cil_sidorder *sidorder = node->data;
+ fprintf(out, "(sidorder ");
+ write_string_list(out, sidorder->sid_list_str);
+ fprintf(out, ")\n");
break;
- case CIL_ROLEATTRIBUTE:
- cil_write_roleattribute(node, cil_out);
+ }
+ case CIL_BOOL: {
+ struct cil_bool *boolean = node->data;
+ fprintf(out, "(boolean %s %s)\n", datum_to_str(DATUM(boolean)), boolean->value ? "true" : "false");
break;
- case CIL_ROLEATTRIBUTESET:
- rc = cil_write_unsupported("CIL_ROLEATTRIBUTESET");
+ }
+ case CIL_TUNABLE: {
+ struct cil_tunable *tunable = node->data;
+ fprintf(out, "(tunable %s %s)\n", datum_to_str(DATUM(tunable)), tunable->value ? "true" : "false");
break;
- case CIL_ROLEALLOW:
- rc = cil_write_unsupported("CIL_ROLEALLOW");
+ }
+ case CIL_SENS: {
+ struct cil_sens *sens = node->data;
+ fprintf(out, "(sensitivity %s)\n", datum_to_str(DATUM(sens)));
break;
- case CIL_TYPE:
- rc = cil_write_type(node, cil_out);
+ }
+ case CIL_SENSALIAS: {
+ struct cil_alias *alias = node->data;
+ fprintf(out, "(sensitivityalias %s)\n", datum_to_str(DATUM(alias)));
break;
- case CIL_TYPEBOUNDS:
- rc = cil_write_unsupported("CIL_TYPEBOUNDS");
+ }
+ case CIL_SENSALIASACTUAL: {
+ struct cil_aliasactual *aliasactual = node->data;
+ fprintf(out, "(sensitivityaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
break;
- case CIL_TYPEPERMISSIVE:
- rc = cil_write_typepermissive(node, cil_out);
+ }
+ case CIL_CAT: {
+ struct cil_cat *cat = node->data;
+ fprintf(out, "(category %s)\n", datum_to_str(DATUM(cat)));
break;
- case CIL_TYPEATTRIBUTE:
- rc = cil_write_typeattribute(node, cil_out);
+ }
+ case CIL_CATALIAS: {
+ struct cil_alias *alias = node->data;
+ fprintf(out, "(categoryalias %s)\n", datum_to_str(DATUM(alias)));
break;
- case CIL_TYPEATTRIBUTESET:
- rc = cil_write_typeattributeset(node, cil_out);
+ }
+ case CIL_CATALIASACTUAL: {
+ struct cil_aliasactual *aliasactual = node->data;
+ fprintf(out, "(categoryaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
break;
- case CIL_EXPANDTYPEATTRIBUTE:
- rc = cil_write_expandtypeattribute(node, cil_out);
- break;
- case CIL_TYPEALIAS:
- rc = cil_write_alias(node, cil_out);
+ }
+ case CIL_CATSET: {
+ struct cil_catset *catset = node->data;
+ fprintf(out, "(categoryset %s ", datum_to_str(DATUM(catset)));
+ write_cats(out, catset->cats);
+ fprintf(out, ")\n");
break;
- case CIL_TYPEALIASACTUAL:
- rc = cil_write_aliasactual(node, cil_out);
+ }
+ case CIL_CATORDER: {
+ struct cil_catorder *catorder = node->data;
+ fprintf(out, "(categoryorder ");
+ write_string_list(out, catorder->cat_list_str);
+ fprintf(out, ")\n");
break;
- case CIL_ROLETRANSITION:
- rc = cil_write_unsupported("CIL_ROLETRANSITION");
+ }
+ case CIL_SENSCAT: {
+ struct cil_senscat *senscat = node->data;
+ fprintf(out, "(sensitivitycategory ");
+ fprintf(out, "%s ", senscat->sens_str);
+ write_cats(out, senscat->cats);
+ fprintf(out, ")\n");
break;
- case CIL_NAMETYPETRANSITION:
- rc = cil_write_nametypetransition(node, cil_out);
+ }
+ case CIL_SENSITIVITYORDER: {
+ struct cil_sensorder *sensorder = node->data;
+ fprintf(out, "(sensitivityorder ");
+ write_string_list(out, sensorder->sens_list_str);
+ fprintf(out, ")\n");
break;
- case CIL_RANGETRANSITION:
- rc = cil_write_unsupported("CIL_RANGETRANSITION");
+ }
+ case CIL_LEVEL: {
+ struct cil_level *level = node->data;
+ fprintf(out, "(level %s ", datum_to_str(&level->datum));
+ write_level(out, level, CIL_FALSE);
+ fprintf(out, ")\n");
break;
- case CIL_TUNABLE:
- rc = cil_write_unsupported("CIL_TUNABLE");
+ }
+ case CIL_LEVELRANGE: {
+ struct cil_levelrange *lvlrange = node->data;
+ fprintf(out, "(levelrange %s ", datum_to_str(DATUM(lvlrange)));
+ write_range(out, lvlrange, CIL_FALSE);
+ fprintf(out, ")\n");
break;
- case CIL_BOOL:
- rc = cil_write_unsupported("CIL_BOOL");
+ }
+ case CIL_USER: {
+ struct cil_user *user = node->data;
+ fprintf(out, "(user %s)\n", datum_to_str(DATUM(user)));
break;
- case CIL_AVRULE:
- case CIL_AVRULEX:
- rc = cil_write_avrule(node, cil_out);
+ }
+ case CIL_USERATTRIBUTE: {
+ struct cil_userattribute *attr = node->data;
+ fprintf(out, "(userattribute %s)\n", datum_to_str(DATUM(attr)));
break;
- case CIL_PERMISSIONX:
- rc = cil_write_unsupported("CIL_PERMISSIONX");
+ }
+ case CIL_USERATTRIBUTESET: {
+ struct cil_userattributeset *attr = node->data;
+ fprintf(out, "(userattributeset %s ", attr->attr_str);
+ if (attr->datum_expr)
+ write_expr(out, attr->datum_expr);
+ else
+ write_expr(out, attr->str_expr);
+ fprintf(out, ")\n");
break;
- case CIL_TYPE_RULE:
- cil_write_type_rule(node, cil_out);
+ }
+ case CIL_USERROLE: {
+ struct cil_userrole *userrole = node->data;
+ fprintf(out, "(userrole ");
+ fprintf(out, "%s ", datum_or_str(userrole->user, userrole->user_str));
+ fprintf(out, "%s", datum_or_str(userrole->role, userrole->role_str));
+ fprintf(out, ")\n");
break;
- case CIL_SENS:
- rc = cil_write_sens(node, cil_out);
+ }
+ case CIL_USERLEVEL: {
+ struct cil_userlevel *userlevel = node->data;
+ fprintf(out, "(userlevel %s ", userlevel->user_str);
+ if (userlevel->level)
+ write_level(out, userlevel->level, CIL_TRUE);
+ else
+ fprintf(out, "%s", userlevel->level_str);
+ fprintf(out, ")\n");
break;
- case CIL_SENSALIAS:
- rc = cil_write_alias(node, cil_out);
+ }
+ case CIL_USERRANGE: {
+ struct cil_userrange *userrange = node->data;
+ fprintf(out, "(userrange %s ", userrange->user_str);
+ if (userrange->range)
+ write_range(out, userrange->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", userrange->range_str);
+ fprintf(out, ")\n");
break;
- case CIL_SENSALIASACTUAL:
- rc = cil_write_aliasactual(node, cil_out);
+ }
+ case CIL_USERBOUNDS: {
+ struct cil_bounds *bounds = node->data;
+ fprintf(out, "(userbounds %s %s)\n", bounds->parent_str, bounds->child_str);
break;
- case CIL_CAT:
- rc = cil_write_cat(node, cil_out);
+ }
+ case CIL_USERPREFIX: {
+ struct cil_userprefix *prefix = node->data;
+ fprintf(out, "(userprefix ");
+ fprintf(out, "%s ", datum_or_str(DATUM(prefix->user), prefix->user_str));
+ fprintf(out, "%s)\n", prefix->prefix_str);
break;
- case CIL_CATALIAS:
- rc = cil_write_alias(node, cil_out);
+ }
+ case CIL_SELINUXUSER: {
+ struct cil_selinuxuser *selinuxuser = node->data;
+ fprintf(out, "(selinuxuser %s ", selinuxuser->name_str);
+ fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str));
+ if (selinuxuser->range)
+ write_range(out, selinuxuser->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", selinuxuser->range_str);
+ fprintf(out, ")\n");
break;
- case CIL_CATALIASACTUAL:
- rc = cil_write_aliasactual(node, cil_out);
+ }
+ case CIL_SELINUXUSERDEFAULT: {
+ struct cil_selinuxuser *selinuxuser = node->data;
+ fprintf(out, "(selinuxuserdefault ");
+ fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str));
+ if (selinuxuser->range)
+ write_range(out, selinuxuser->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", selinuxuser->range_str);
+ fprintf(out, ")\n");
break;
- case CIL_CATSET:
- rc = cil_write_unsupported("CIL_CATSET");
+ }
+ case CIL_ROLE: {
+ fprintf(out, "(role %s)\n", datum_to_str(node->data));
break;
- case CIL_SENSCAT:
- rc = cil_write_senscat(node, cil_out);
+ }
+ case CIL_ROLEATTRIBUTE: {
+ fprintf(out, "(roleattribute %s)\n", datum_to_str(node->data));
break;
- case CIL_CATORDER:
- rc = cil_write_catorder(node, cil_out);
+ }
+ case CIL_ROLEATTRIBUTESET: {
+ struct cil_roleattributeset *attr = node->data;
+ fprintf(out, "(roleattributeset %s ", attr->attr_str);
+ if (attr->datum_expr)
+ write_expr(out, attr->datum_expr);
+ else
+ write_expr(out, attr->str_expr);
+ fprintf(out, ")\n");
break;
- case CIL_SENSITIVITYORDER:
- rc = cil_write_sensorder(node, cil_out);
+ }
+ case CIL_ROLETYPE: {
+ struct cil_roletype *roletype = node->data;
+ fprintf(out, "(roletype ");
+ fprintf(out, "%s ", datum_or_str(DATUM(roletype->role), roletype->role_str));
+ fprintf(out, "%s", datum_or_str(DATUM(roletype->type), roletype->type_str));
+ fprintf(out, ")\n");
break;
- case CIL_LEVEL:
- rc = cil_write_unsupported("CIL_LEVEL");
+ }
+ case CIL_ROLEBOUNDS: {
+ struct cil_bounds *bnds = node->data;
+ fprintf(out, "(rolebounds %s %s)\n", bnds->parent_str, bnds->child_str);
break;
- case CIL_LEVELRANGE:
- rc = cil_write_unsupported("CIL_LEVELRANGE");
+ }
+ case CIL_TYPE: {
+ fprintf(out, "(type %s)\n", datum_to_str(node->data));
break;
- case CIL_CONTEXT:
- rc = cil_write_unsupported("CIL_CONTEXT");
+ }
+ case CIL_TYPEALIAS: {
+ fprintf(out, "(typealias %s)\n", datum_to_str(node->data));
break;
- case CIL_NETIFCON:
- rc = cil_write_unsupported("CIL_NETIFCON");
+ }
+ case CIL_TYPEALIASACTUAL: {
+ struct cil_aliasactual *aliasactual = node->data;
+ fprintf(out, "(typealiasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
break;
- case CIL_GENFSCON:
- rc = cil_write_genfscon(node, cil_out);
+ }
+ case CIL_TYPEATTRIBUTE: {
+ fprintf(out, "(typeattribute %s)\n", datum_to_str(node->data));
break;
- case CIL_FILECON:
- rc = cil_write_unsupported("CIL_FILECON");
+ }
+ case CIL_TYPEATTRIBUTESET: {
+ struct cil_typeattributeset *attr = node->data;
+ fprintf(out, "(typeattributeset %s ", attr->attr_str);
+ if (attr->datum_expr)
+ write_expr(out, attr->datum_expr);
+ else
+ write_expr(out, attr->str_expr);
+ fprintf(out, ")\n");
break;
- case CIL_NODECON:
- rc = cil_write_unsupported("CIL_NODECON");
+ }
+ case CIL_EXPANDTYPEATTRIBUTE: {
+ struct cil_expandtypeattribute *attr = node->data;
+ fprintf(out, "(expandtypeattribute ");
+ if (attr->attr_datums)
+ write_expr(out, attr->attr_datums);
+ else
+ write_expr(out, attr->attr_strs);
+ fprintf(out, " %s)\n", attr->expand ? "true" : "false");
break;
- case CIL_PORTCON:
- rc = cil_write_unsupported("CIL_PORTCON");
+ }
+ case CIL_TYPEPERMISSIVE: {
+ struct cil_typepermissive *tp = node->data;
+ fprintf(out, "(typepermissive ");
+ fprintf(out, "%s", datum_or_str(DATUM(tp->type), tp->type_str));
+ fprintf(out, ")\n");
break;
- case CIL_PIRQCON:
- rc = cil_write_unsupported("CIL_PIRQCON");
+ }
+ case CIL_TYPEBOUNDS: {
+ struct cil_bounds *bounds = node->data;
+ fprintf(out, "(typebounds %s %s)\n", bounds->parent_str, bounds->child_str);
break;
- case CIL_IOMEMCON:
- rc = cil_write_unsupported("CIL_IOMEMCON");
+ }
+ case CIL_ROLEALLOW: {
+ struct cil_roleallow *roleallow = node->data;
+ fprintf(out, "(roleallow ");
+ fprintf(out, "%s ", datum_or_str(DATUM(roleallow->src), roleallow->src_str));
+ fprintf(out, "%s", datum_or_str(DATUM(roleallow->tgt), roleallow->tgt_str));
+ fprintf(out, ")\n");
break;
- case CIL_IOPORTCON:
- rc = cil_write_unsupported("CIL_IOPORTCON");
+ }
+ case CIL_ROLETRANSITION: {
+ struct cil_roletransition *roletrans = node->data;
+ fprintf(out, "(roletransition ");
+ fprintf(out, "%s ", datum_or_str(DATUM(roletrans->src), roletrans->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(roletrans->tgt), roletrans->tgt_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(roletrans->obj), roletrans->obj_str));
+ fprintf(out, "%s", datum_or_str(DATUM(roletrans->result), roletrans->result_str));
+ fprintf(out, ")\n");
break;
- case CIL_PCIDEVICECON:
- rc = cil_write_unsupported("CIL_PCIDEVICECON");
+ }
+ case CIL_AVRULE: {
+ struct cil_avrule *rule = node->data;
+ if (rule->rule_kind == AVRULE_ALLOWED)
+ fprintf(out, "(allow ");
+ else if (rule->rule_kind == AVRULE_AUDITALLOW)
+ fprintf(out, "(auditallow ");
+ else if (rule->rule_kind == AVRULE_DONTAUDIT)
+ fprintf(out, "(dontaudit ");
+ else if (rule->rule_kind == AVRULE_NEVERALLOW)
+ fprintf(out, "(neverallow ");
+ else
+ fprintf(out, "(<?AVRULE> ");
+
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
+ write_classperms_list(out, rule->perms.classperms);
+ fprintf(out, ")\n");
break;
- case CIL_DEVICETREECON:
- rc = cil_write_unsupported("CIL_DEVICETREECON");
+ }
+ case CIL_AVRULEX: {
+ struct cil_avrule *rule = node->data;
+ if (rule->rule_kind == AVRULE_ALLOWED)
+ fprintf(out, "(allowx ");
+ else if (rule->rule_kind == AVRULE_AUDITALLOW)
+ fprintf(out, "(auditallowx ");
+ else if (rule->rule_kind == AVRULE_DONTAUDIT)
+ fprintf(out, "(dontauditx ");
+ else if (rule->rule_kind == AVRULE_NEVERALLOW)
+ fprintf(out, "(neverallowx ");
+ else
+ fprintf(out, "(<?AVRULEX> ");
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
+ if (rule->perms.x.permx_str) {
+ fprintf(out, "%s",rule->perms.x.permx_str);
+ } else {
+ write_permx(out, rule->perms.x.permx);
+ }
+ fprintf(out, ")\n");
break;
- case CIL_FSUSE:
- rc = cil_write_fsuse(node, cil_out);
+ }
+ case CIL_TYPE_RULE: {
+ struct cil_type_rule *rule = node->data;
+ if (rule->rule_kind == AVRULE_TRANSITION)
+ fprintf(out, "(typetransition ");
+ else if (rule->rule_kind == AVRULE_MEMBER)
+ fprintf(out, "(typemember ");
+ else if (rule->rule_kind == AVRULE_CHANGE)
+ fprintf(out, "(typechange ");
+ else
+ fprintf(out, "(<?TYPERULE> ");
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
+ fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str));
+ fprintf(out, ")\n");
break;
- case CIL_CONSTRAIN:
- rc = cil_write_unsupported("CIL_CONSTRAIN");
+ }
+ case CIL_NAMETYPETRANSITION: {
+ struct cil_nametypetransition *rule = node->data;
+ fprintf(out, "(typetransition ");
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
+ fprintf(out, "\"%s\" ", datum_or_str(DATUM(rule->name), rule->name_str));
+ fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str));
+ fprintf(out, ")\n");
break;
- case CIL_MLSCONSTRAIN:
- rc = cil_write_constrain(node, cil_out);
+ }
+ case CIL_RANGETRANSITION: {
+ struct cil_rangetransition *rule = node->data;
+ fprintf(out, "(rangetransition ");
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->exec), rule->exec_str));
+ fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
+ if (rule->range)
+ write_range(out, rule->range, CIL_TRUE);
+ else
+ fprintf(out, "%s", rule->range_str);
+ fprintf(out, ")\n");
break;
- case CIL_VALIDATETRANS:
- rc = cil_write_unsupported("CIL_VALIDATETRANS");
+ }
+ case CIL_CONSTRAIN: {
+ struct cil_constrain *cons = node->data;
+ fprintf(out, "(constrain ");
+ write_constrain(out, cons);
+ fprintf(out, ")\n");
break;
- case CIL_MLSVALIDATETRANS:
- rc = cil_write_unsupported("CIL_MLSVALIDATETRANS");
+ }
+ case CIL_MLSCONSTRAIN: {
+ struct cil_constrain *cons = node->data;
+ fprintf(out, "(mlsconstrain ");
+ write_constrain(out, cons);
+ fprintf(out, ")\n");
break;
- case CIL_CALL:
- rc = cil_write_unsupported("CIL_CALL");
+ }
+ case CIL_VALIDATETRANS: {
+ struct cil_validatetrans *vt = node->data;
+ fprintf(out, "(validatetrans ");
+ fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str));
+ if (vt->datum_expr)
+ write_expr(out, vt->datum_expr);
+ else
+ write_expr(out, vt->str_expr);
+ fprintf(out, ")\n");
break;
- case CIL_MACRO:
- rc = cil_write_unsupported("CIL_MACRO");
+ }
+ case CIL_MLSVALIDATETRANS: {
+ struct cil_validatetrans *vt = node->data;
+ fprintf(out, "(mlsvalidatetrans ");
+ fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str));
+ if (vt->datum_expr)
+ write_expr(out, vt->datum_expr);
+ else
+ write_expr(out, vt->str_expr);
+ fprintf(out, ")\n");
break;
- case CIL_NODE:
- rc = cil_write_unsupported("CIL_NODE");
+ }
+ case CIL_CONTEXT: {
+ struct cil_context *context = node->data;
+ fprintf(out, "(context %s ", datum_to_str(DATUM(context)));
+ write_context(out, context, CIL_FALSE);
+ fprintf(out, ")\n");
break;
- case CIL_OPTIONAL:
- rc = cil_write_unsupported("CIL_OPTIONAL");
+ }
+ case CIL_FILECON: {
+ struct cil_filecon *filecon = node->data;
+ fprintf(out, "(filecon ");
+ fprintf(out, "\"%s\" ", filecon->path_str);
+ switch (filecon->type) {
+ case CIL_FILECON_ANY:
+ fprintf(out, "%s ", CIL_KEY_ANY);
+ break;
+ case CIL_FILECON_FILE:
+ fprintf(out, "%s ", CIL_KEY_FILE);
+ break;
+ case CIL_FILECON_DIR:
+ fprintf(out, "%s ", CIL_KEY_DIR);
+ break;
+ case CIL_FILECON_CHAR:
+ fprintf(out, "%s ", CIL_KEY_CHAR);
+ break;
+ case CIL_FILECON_BLOCK:
+ fprintf(out, "%s ", CIL_KEY_BLOCK);
+ break;
+ case CIL_FILECON_SOCKET:
+ fprintf(out, "%s ", CIL_KEY_SOCKET);
+ break;
+ case CIL_FILECON_PIPE:
+ fprintf(out, "%s ", CIL_KEY_PIPE);
+ break;
+ case CIL_FILECON_SYMLINK:
+ fprintf(out, "%s ", CIL_KEY_SYMLINK);
+ break;
+ default:
+ fprintf(out, "<?FILETYPE> ");
+ }
+ if (filecon->context)
+ write_context(out, filecon->context, CIL_TRUE);
+ else if (filecon->context_str)
+ fprintf(out, "%s", filecon->context_str);
+ else
+ fprintf(out, "()");
+ fprintf(out, ")\n");
break;
- case CIL_IPADDR:
- rc = cil_write_unsupported("CIL_IPADDR");
+ }
+ case CIL_IBPKEYCON: {
+ struct cil_ibpkeycon *ibpkeycon = node->data;
+ fprintf(out, "(ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
+ fprintf(out, "(%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high);
+ if (ibpkeycon->context)
+ write_context(out, ibpkeycon->context, CIL_TRUE);
+ else if (ibpkeycon->context_str)
+ fprintf(out, "%s", ibpkeycon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_CONDBLOCK:
- rc = cil_write_unsupported("CIL_CONDBLOCK");
+ }
+ case CIL_PORTCON: {
+ struct cil_portcon *portcon = node->data;
+ fprintf(out, "(portcon ");
+ if (portcon->proto == CIL_PROTOCOL_UDP)
+ fprintf(out, " udp ");
+ else if (portcon->proto == CIL_PROTOCOL_TCP)
+ fprintf(out, " tcp ");
+ else if (portcon->proto == CIL_PROTOCOL_DCCP)
+ fprintf(out, "dccp ");
+ else if (portcon->proto == CIL_PROTOCOL_SCTP)
+ fprintf(out, "sctp ");
+ else
+ fprintf(out, "<?PROTOCOL> ");
+ if (portcon->port_low == portcon->port_high)
+ fprintf(out, "%d ", portcon->port_low);
+ else
+ fprintf(out, "(%d %d) ", portcon->port_low, portcon->port_high);
+ if (portcon->context)
+ write_context(out, portcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", portcon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_BOOLEANIF:
- rc = cil_write_unsupported("CIL_BOOLEANIF");
+ }
+ case CIL_NODECON: {
+ struct cil_nodecon *nodecon = node->data;
+ fprintf(out, "(nodecon ");
+ if (nodecon->addr)
+ write_ipaddr(out, nodecon->addr);
+ else
+ fprintf(out, "%s ", nodecon->addr_str);
+ fprintf(out, " ");
+ if (nodecon->mask)
+ write_ipaddr(out, nodecon->mask);
+ else
+ fprintf(out, "%s ", nodecon->mask_str);
+ fprintf(out, " ");
+ if (nodecon->context)
+ write_context(out, nodecon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", nodecon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_TUNABLEIF:
- rc = cil_write_unsupported("CIL_TUNABLEIF");
+ }
+ case CIL_GENFSCON: {
+ struct cil_genfscon *genfscon = node->data;
+ fprintf(out, "(genfscon ");
+ fprintf(out, "%s \"%s\" ", genfscon->fs_str, genfscon->path_str);
+ if (genfscon->file_type != CIL_FILECON_ANY) {
+ switch (genfscon->file_type) {
+ case CIL_FILECON_FILE:
+ fprintf(out, "%s ", CIL_KEY_FILE);
+ break;
+ case CIL_FILECON_DIR:
+ fprintf(out, "%s ", CIL_KEY_DIR);
+ break;
+ case CIL_FILECON_CHAR:
+ fprintf(out, "%s ", CIL_KEY_CHAR);
+ break;
+ case CIL_FILECON_BLOCK:
+ fprintf(out, "%s ", CIL_KEY_BLOCK);
+ break;
+ case CIL_FILECON_SOCKET:
+ fprintf(out, "%s ", CIL_KEY_SOCKET);
+ break;
+ case CIL_FILECON_PIPE:
+ fprintf(out, "%s ", CIL_KEY_PIPE);
+ break;
+ case CIL_FILECON_SYMLINK:
+ fprintf(out, "%s ", CIL_KEY_SYMLINK);
+ break;
+ default:
+ fprintf(out, "<?FILETYPE> ");
+ }
+ }
+ if (genfscon->context)
+ write_context(out, genfscon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", genfscon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_DEFAULTUSER:
- rc = cil_write_unsupported("CIL_DEFAULTUSER");
+ }
+ case CIL_NETIFCON: {
+ struct cil_netifcon *netifcon = node->data;
+ fprintf(out, "(netifcon %s ", netifcon->interface_str);
+ if (netifcon->if_context)
+ write_context(out, netifcon->if_context, CIL_TRUE);
+ else
+ fprintf(out, "%s", netifcon->if_context_str);
+ fprintf(out, " ");
+ if (netifcon->packet_context)
+ write_context(out, netifcon->packet_context, CIL_TRUE);
+ else
+ fprintf(out, "%s", netifcon->packet_context_str);
+ fprintf(out, ")\n");
break;
- case CIL_DEFAULTROLE:
- rc = cil_write_unsupported("CIL_DEFAULTROLE");
+ }
+ case CIL_IBENDPORTCON: {
+ struct cil_ibendportcon *ibendportcon = node->data;
+ fprintf(out, "(ibendportcon %s %u ", ibendportcon->dev_name_str, ibendportcon->port);
+ if (ibendportcon->context)
+ write_context(out, ibendportcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", ibendportcon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_DEFAULTTYPE:
- rc = cil_write_unsupported("CIL_DEFAULTTYPE");
+ }
+ case CIL_PIRQCON: {
+ struct cil_pirqcon *pirqcon = node->data;
+ fprintf(out, "(pirqcon %d ", pirqcon->pirq);
+ if (pirqcon->context)
+ write_context(out, pirqcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", pirqcon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_DEFAULTRANGE:
- rc = cil_write_unsupported("CIL_DEFAULTRANGE");
+ }
+ case CIL_IOMEMCON: {
+ struct cil_iomemcon *iomemcon = node->data;
+ fprintf(out, "(iomemcon (%"PRId64" %"PRId64") ", iomemcon->iomem_low, iomemcon->iomem_high);
+ if (iomemcon->context)
+ write_context(out, iomemcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", iomemcon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_SELINUXUSER:
- rc = cil_write_unsupported("CIL_SELINUXUSER");
+ }
+ case CIL_IOPORTCON: {
+ struct cil_ioportcon *ioportcon = node->data;
+ fprintf(out, "(ioportcon ");
+ if (ioportcon->ioport_low == ioportcon->ioport_high)
+ fprintf(out, "%d ", ioportcon->ioport_low);
+ else
+ fprintf(out, "(%d %d) ", ioportcon->ioport_low, ioportcon->ioport_high);
+
+ if (ioportcon->context)
+ write_context(out, ioportcon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", ioportcon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_SELINUXUSERDEFAULT:
- rc = cil_write_unsupported("CIL_SELINUXUSERDEFAULT");
+ }
+ case CIL_PCIDEVICECON: {
+ struct cil_pcidevicecon *pcidevicecon = node->data;
+ fprintf(out, "(pcidevicecon %d ", pcidevicecon->dev);
+ if (pcidevicecon->context)
+ write_context(out, pcidevicecon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", pcidevicecon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_HANDLEUNKNOWN:
- rc = cil_write_handleunknown(node, cil_out);
+ }
+ case CIL_DEVICETREECON: {
+ struct cil_devicetreecon *devicetreecon = node->data;
+ fprintf(out, "(devicetreecon \"%s\" ", devicetreecon->path);
+ if (devicetreecon->context)
+ write_context(out, devicetreecon->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", devicetreecon->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_MLS:
- rc = cil_write_mls(node, cil_out);
+ }
+ case CIL_FSUSE: {
+ struct cil_fsuse *fsuse = node->data;
+ fprintf(out, "(fsuse ");
+ if (fsuse->type == CIL_FSUSE_XATTR)
+ fprintf(out, "xattr ");
+ else if (fsuse->type == CIL_FSUSE_TASK)
+ fprintf(out, "task ");
+ else if (fsuse->type == CIL_FSUSE_TRANS)
+ fprintf(out, "trans ");
+ else
+ fprintf(out, "<?TYPE> ");
+ fprintf(out, "%s ", fsuse->fs_str);
+ if (fsuse->context)
+ write_context(out, fsuse->context, CIL_TRUE);
+ else
+ fprintf(out, "%s", fsuse->context_str);
+ fprintf(out, ")\n");
break;
- case CIL_SRC_INFO:
+ }
+ case CIL_POLICYCAP: {
+ struct cil_policycap *polcap = node->data;
+ fprintf(out, "(policycap %s)\n", polcap->datum.name);
break;
- case CIL_NONE:
- // TODO: add proper removal support
- *finished = CIL_TREE_SKIP_HEAD;
+ }
+ case CIL_IPADDR: {
+ struct cil_ipaddr *ipaddr = node->data;
+ char buf[256];
+ if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL)
+ strcpy(buf, "<?IPADDR>");
+ fprintf(out, "(ipaddr %s %s)\n", datum_to_str(&ipaddr->datum), buf);
break;
- default:
- cil_log(CIL_ERR, "Unknown AST flavor: %d.\n", node->flavor);
- rc = SEPOL_ERR;
- goto exit;
+ }
+ default :
+ fprintf(out, "(<?RULE:%s>)\n", cil_node_to_string(node));
break;
}
-exit:
- return rc;
}
-static int __cil_write_last_child_helper(struct cil_tree_node *node, void *extra_args)
+/*
+ * Tree walk data and helper functions for writing the AST of the various phases
+ */
+
+struct cil_write_ast_args {
+ FILE *out;
+ int depth;
+};
+
+/*
+ * Helper functions for writing the parse AST
+ */
+
+static int __write_parse_ast_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+
+ fprintf(args->out, "%*s", args->depth*4, "");
+ if (!node->data) {
+ if (node->cl_head)
+ fprintf(args->out, "(\n");
+ else
+ fprintf(args->out, "()\n");
+ } else {
+ char *str = (char *)node->data;
+ size_t len = strlen(str);
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (isspace(str[i])) {
+ fprintf(args->out, "\"%s\"\n", str);
+ return SEPOL_OK;
+ }
+ }
+
+ fprintf(args->out, "%s\n", (char *)node->data);
+ }
+
+ return SEPOL_OK;
+}
+
+static int __write_parse_ast_first_child_helper(struct cil_tree_node *node, void *extra_args)
{
- int rc = SEPOL_ERR;
- struct cil_args_write *args = NULL;
- FILE *cil_out = NULL;
+ struct cil_write_ast_args *args = extra_args;
+ struct cil_tree_node *parent = node->parent;
- if (node == NULL || extra_args == NULL) {
- goto exit;
+ if (parent->flavor != CIL_ROOT) {
+ args->depth++;
}
- args = extra_args;
- cil_out = args->cil_out;
+ return SEPOL_OK;
+}
- if (node->parent && node->parent->flavor != CIL_ROOT && node->parent->flavor != CIL_SRC_INFO) {
- fprintf(cil_out,")");
+static int __write_parse_ast_last_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+ struct cil_tree_node *parent = node->parent;
+
+ if (parent->flavor == CIL_ROOT) {
+ return SEPOL_OK;
}
- rc = SEPOL_OK;
-exit:
- return rc;
+
+ args->depth--;
+ fprintf(args->out, "%*s", args->depth*4, "");
+ fprintf(args->out, ")\n");
+
+ return SEPOL_OK;
}
-/* main exported function */
-int cil_write_ast(struct cil_db *db, const char* path) {
- int rc = SEPOL_ERR;
- struct cil_args_write extra_args;
- FILE *cil_out = NULL;
-
- cil_out = fopen(path, "we");
- if (cil_out == NULL) {
- cil_log(CIL_ERR, "Failure opening output file for writing AST\n");
- rc = SEPOL_ERR;
- goto exit;
- }
-
- extra_args.cil_out = cil_out;
- extra_args.db = db;
- rc = cil_tree_walk(db->ast->root, __cil_write_node_helper,
- __cil_write_first_child_helper,
- __cil_write_last_child_helper,
- &extra_args);
+/*
+ * Helper functions for writing the CIL AST for the build and resolve phases
+ */
+
+static int __write_cil_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+
+ if (node->flavor == CIL_SRC_INFO) {
+ // ANDROID: The generated cil may be split/merged later on. Do not output
+ // source information to avoid issues when loading the resulting policy with
+ // libsepol.
+ // cil_write_src_info_node(args->out, node);
+ return SEPOL_OK;
+ }
+
+ fprintf(args->out, "%*s", args->depth*4, "");
+
+ cil_write_ast_node(args->out, node);
+
+ if (node->flavor == CIL_CLASS || node->flavor == CIL_COMMON || node->flavor == CIL_MAP_CLASS) {
+ *finished = CIL_TREE_SKIP_HEAD;
+ }
+
+ return SEPOL_OK;
+}
+
+static int __write_cil_ast_first_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+ struct cil_tree_node *parent = node->parent;
+
+ if (parent->flavor != CIL_SRC_INFO && parent->flavor != CIL_ROOT) {
+ args->depth++;
+ }
+
+ return SEPOL_OK;
+}
+
+static int __write_cil_ast_last_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_write_ast_args *args = extra_args;
+ struct cil_tree_node *parent = node->parent;
+
+ if (parent->flavor == CIL_ROOT) {
+ return SEPOL_OK;
+ } else if (parent->flavor == CIL_SRC_INFO) {
+ // ANDROID: The generated cil may be split/merged later on. Do not output
+ // source information to avoid issues when loading the resulting policy with
+ // libsepol.
+ // fprintf(args->out, ";;* lme\n");
+ return SEPOL_OK;
+ }
+
+ args->depth--;
+ fprintf(args->out, "%*s", args->depth*4, "");
+ fprintf(args->out, ")\n");
+
+ return SEPOL_OK;
+}
+
+int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node)
+{
+ struct cil_write_ast_args extra_args;
+ int rc;
+
+ extra_args.out = out;
+ extra_args.depth = 0;
+
+ if (phase == CIL_WRITE_AST_PHASE_PARSE) {
+ rc = cil_tree_walk(node, __write_parse_ast_node_helper, __write_parse_ast_first_child_helper, __write_parse_ast_last_child_helper, &extra_args);
+ } else {
+ rc = cil_tree_walk(node, __write_cil_ast_node_helper, __write_cil_ast_first_child_helper, __write_cil_ast_last_child_helper, &extra_args);
+ }
+
if (rc != SEPOL_OK) {
- cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc);
- goto exit;
+ cil_log(CIL_ERR, "Failed to write AST\n");
+ return SEPOL_ERR;
}
-exit:
- fclose(cil_out);
- cil_out = NULL;
- return rc;
+ return SEPOL_OK;
}
diff --git a/libsepol/cil/src/cil_write_ast.h b/libsepol/cil/src/cil_write_ast.h
new file mode 100644
index 00000000..3f4b9d95
--- /dev/null
+++ b/libsepol/cil/src/cil_write_ast.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef CIL_WRITE_AST_H_
+#define CIL_WRITE_AST_H_
+
+#include <stdio.h>
+
+#include "cil_tree.h"
+
+enum cil_write_ast_phase {
+ CIL_WRITE_AST_PHASE_PARSE = 0,
+ CIL_WRITE_AST_PHASE_BUILD,
+ CIL_WRITE_AST_PHASE_RESOLVE,
+};
+
+void cil_write_ast_node(FILE *out, struct cil_tree_node *node);
+int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node);
+
+#endif /* CIL_WRITE_AST_H_ */
diff --git a/libsepol/cil/src/dso.h b/libsepol/cil/src/dso.h
deleted file mode 100644
index 64a162ce..00000000
--- a/libsepol/cil/src/dso.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _SEPOL_DSO_H
-#define _SEPOL_DSO_H 1
-
-#if !defined(SHARED) || defined(ANDROID) || defined(__APPLE__)
- #define DISABLE_SYMVER 1
-#endif
-
-#ifdef SHARED
-# define hidden __attribute__ ((visibility ("hidden")))
-# define hidden_proto(fct) __hidden_proto (fct, fct##_internal)
-# define __hidden_proto(fct, internal) \
- extern __typeof (fct) internal; \
- extern __typeof (fct) fct __asm (#internal) hidden;
-# if defined(__alpha__) || defined(__mips__)
-# define hidden_def(fct) \
- asm (".globl " #fct "\n" #fct " = " #fct "_internal");
-# else
-# define hidden_def(fct) \
- asm (".globl " #fct "\n.set " #fct ", " #fct "_internal");
-#endif
-#else
-# define hidden
-# define hidden_proto(fct)
-# define hidden_def(fct)
-#endif
-
-#endif
diff --git a/libsepol/fuzz/binpolicy-fuzzer.c b/libsepol/fuzz/binpolicy-fuzzer.c
new file mode 100644
index 00000000..85c59645
--- /dev/null
+++ b/libsepol/fuzz/binpolicy-fuzzer.c
@@ -0,0 +1,63 @@
+#include <sepol/debug.h>
+#include <sepol/kernel_to_cil.h>
+#include <sepol/kernel_to_conf.h>
+#include <sepol/policydb/policydb.h>
+
+extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static int write_binary_policy(policydb_t *p, FILE *outfp)
+{
+ struct policy_file pf;
+
+ policy_file_init(&pf);
+ pf.type = PF_USE_STDIO;
+ pf.fp = outfp;
+ return policydb_write(p, &pf);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ policydb_t policydb = {};
+ sidtab_t sidtab = {};
+ struct policy_file pf;
+ FILE *devnull = NULL;
+
+ sepol_debug(0);
+
+ policy_file_init(&pf);
+ pf.type = PF_USE_MEMORY;
+ pf.data = (char *) data;
+ pf.len = size;
+
+ if (policydb_init(&policydb))
+ goto exit;
+
+ if (policydb_read(&policydb, &pf, /*verbose=*/0))
+ goto exit;
+
+ if (policydb_load_isids(&policydb, &sidtab))
+ goto exit;
+
+ if (policydb.policy_type == POLICY_KERN)
+ (void) policydb_optimize(&policydb);
+
+ devnull = fopen("/dev/null", "w");
+ if (!devnull)
+ goto exit;
+
+ (void) write_binary_policy(&policydb, devnull);
+
+ (void) sepol_kernel_policydb_to_conf(devnull, &policydb);
+
+ (void) sepol_kernel_policydb_to_cil(devnull, &policydb);
+
+exit:
+ if (devnull != NULL)
+ fclose(devnull);
+
+ policydb_destroy(&policydb);
+ sepol_sidtab_destroy(&sidtab);
+
+ /* Non-zero return values are reserved for future use. */
+ return 0;
+}
diff --git a/libsepol/fuzz/policy.bin b/libsepol/fuzz/policy.bin
new file mode 100644
index 00000000..6f977ef3
--- /dev/null
+++ b/libsepol/fuzz/policy.bin
Binary files differ
diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c
new file mode 100644
index 00000000..9a1a16de
--- /dev/null
+++ b/libsepol/fuzz/secilc-fuzzer.c
@@ -0,0 +1,74 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/stat.h>
+
+#include <sepol/cil/cil.h>
+#include <sepol/policydb.h>
+
+static void log_handler(__attribute__((unused)) int lvl, __attribute__((unused)) const char *msg) {
+ /* be quiet */
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ enum cil_log_level log_level = CIL_ERR;
+ struct sepol_policy_file *pf = NULL;
+ FILE *dev_null = NULL;
+ int target = SEPOL_TARGET_SELINUX;
+ int disable_dontaudit = 0;
+ int multiple_decls = 0;
+ int disable_neverallow = 0;
+ int preserve_tunables = 0;
+ int policyvers = POLICYDB_VERSION_MAX;
+ int mls = -1;
+ int attrs_expand_generated = 0;
+ struct cil_db *db = NULL;
+ sepol_policydb_t *pdb = NULL;
+
+ cil_set_log_level(log_level);
+ cil_set_log_handler(log_handler);
+
+ cil_db_init(&db);
+ cil_set_disable_dontaudit(db, disable_dontaudit);
+ cil_set_multiple_decls(db, multiple_decls);
+ cil_set_disable_neverallow(db, disable_neverallow);
+ cil_set_preserve_tunables(db, preserve_tunables);
+ cil_set_mls(db, mls);
+ cil_set_target_platform(db, target);
+ cil_set_policy_version(db, policyvers);
+ cil_set_attrs_expand_generated(db, attrs_expand_generated);
+
+ if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK)
+ goto exit;
+
+ if (cil_compile(db) != SEPOL_OK)
+ goto exit;
+
+ if (cil_build_policydb(db, &pdb) != SEPOL_OK)
+ goto exit;
+
+ if (sepol_policydb_optimize(pdb) != SEPOL_OK)
+ goto exit;
+
+ dev_null = fopen("/dev/null", "w");
+ if (dev_null == NULL)
+ goto exit;
+
+ if (sepol_policy_file_create(&pf) != 0)
+ goto exit;
+
+ sepol_policy_file_set_fp(pf, dev_null);
+
+ if (sepol_policydb_write(pdb, pf) != 0)
+ goto exit;
+exit:
+ if (dev_null != NULL)
+ fclose(dev_null);
+
+ cil_db_destroy(&db);
+ sepol_policydb_free(pdb);
+ sepol_policy_file_free(pf);
+ return 0;
+}
diff --git a/libsepol/include/sepol/booleans.h b/libsepol/include/sepol/booleans.h
index 06d2230c..25229057 100644
--- a/libsepol/include/sepol/booleans.h
+++ b/libsepol/include/sepol/booleans.h
@@ -10,11 +10,6 @@
extern "C" {
#endif
-/* These two functions are deprecated. See src/deprecated_funcs.c */
-extern int sepol_genbools(void *data, size_t len, const char *boolpath);
-extern int sepol_genbools_array(void *data, size_t len,
- char **names, int *values, int nel);
-
/* Set the specified boolean */
extern int sepol_bool_set(sepol_handle_t * handle,
sepol_policydb_t * policydb,
diff --git a/libsepol/include/sepol/policydb/conditional.h b/libsepol/include/sepol/policydb/conditional.h
index 9c3df3ef..49c0d766 100644
--- a/libsepol/include/sepol/policydb/conditional.h
+++ b/libsepol/include/sepol/policydb/conditional.h
@@ -90,7 +90,7 @@ typedef struct cond_node {
uint32_t expr_pre_comp;
struct cond_node *next;
/* a tunable conditional, calculated and used at expansion */
-#define COND_NODE_FLAGS_TUNABLE 0x01
+#define COND_NODE_FLAGS_TUNABLE UINT32_C(0x01)
uint32_t flags;
} cond_node_t;
diff --git a/libsepol/include/sepol/policydb/ebitmap.h b/libsepol/include/sepol/policydb/ebitmap.h
index e62df01c..81d0c7a6 100644
--- a/libsepol/include/sepol/policydb/ebitmap.h
+++ b/libsepol/include/sepol/policydb/ebitmap.h
@@ -39,6 +39,7 @@ typedef struct ebitmap {
uint32_t highbit; /* highest position in the total bitmap */
} ebitmap_t;
+#define ebitmap_is_empty(e) (((e)->highbit) == 0)
#define ebitmap_length(e) ((e)->highbit)
#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
#define ebitmap_startnode(e) ((e)->node)
@@ -66,7 +67,7 @@ static inline unsigned int ebitmap_next(ebitmap_node_t ** n, unsigned int bit)
return (bit + 1);
}
-static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit)
+static inline int ebitmap_node_get_bit(const ebitmap_node_t * n, unsigned int bit)
{
if (n->map & (MAPBIT << (bit - n->startbit)))
return 1;
@@ -82,17 +83,18 @@ static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit)
extern int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1);
-extern int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
-extern int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2);
-extern int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit);
-extern int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit);
-extern unsigned int ebitmap_cardinality(ebitmap_t *e1);
-extern int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2);
+extern int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2);
+extern int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2);
+extern int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit);
+extern int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit);
+extern unsigned int ebitmap_cardinality(const ebitmap_t *e1);
+extern int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src);
extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2);
extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit);
extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value);
+extern unsigned int ebitmap_highest_set_bit(const ebitmap_t * e);
extern void ebitmap_destroy(ebitmap_t * e);
extern int ebitmap_read(ebitmap_t * e, void *fp);
diff --git a/libsepol/include/sepol/policydb/flask.h b/libsepol/include/sepol/policydb/flask.h
deleted file mode 100644
index 3134284b..00000000
--- a/libsepol/include/sepol/policydb/flask.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* This file is automatically generated. Do not edit. */
-#ifndef _SEPOL_POLICYDB_FLASK_H_
-#define _SEPOL_POLICYDB_FLASK_H_
-
-/*
- * Security object class definitions
- */
-#define SECCLASS_SECURITY 1
-#define SECCLASS_PROCESS 2
-#define SECCLASS_SYSTEM 3
-#define SECCLASS_CAPABILITY 4
-#define SECCLASS_FILESYSTEM 5
-#define SECCLASS_FILE 6
-#define SECCLASS_DIR 7
-#define SECCLASS_FD 8
-#define SECCLASS_LNK_FILE 9
-#define SECCLASS_CHR_FILE 10
-#define SECCLASS_BLK_FILE 11
-#define SECCLASS_SOCK_FILE 12
-#define SECCLASS_FIFO_FILE 13
-#define SECCLASS_SOCKET 14
-#define SECCLASS_TCP_SOCKET 15
-#define SECCLASS_UDP_SOCKET 16
-#define SECCLASS_RAWIP_SOCKET 17
-#define SECCLASS_NODE 18
-#define SECCLASS_NETIF 19
-#define SECCLASS_NETLINK_SOCKET 20
-#define SECCLASS_PACKET_SOCKET 21
-#define SECCLASS_KEY_SOCKET 22
-#define SECCLASS_UNIX_STREAM_SOCKET 23
-#define SECCLASS_UNIX_DGRAM_SOCKET 24
-#define SECCLASS_SEM 25
-#define SECCLASS_MSG 26
-#define SECCLASS_MSGQ 27
-#define SECCLASS_SHM 28
-#define SECCLASS_IPC 29
-#define SECCLASS_PASSWD 30
-#define SECCLASS_DRAWABLE 31
-#define SECCLASS_WINDOW 32
-#define SECCLASS_GC 33
-#define SECCLASS_FONT 34
-#define SECCLASS_COLORMAP 35
-#define SECCLASS_PROPERTY 36
-#define SECCLASS_CURSOR 37
-#define SECCLASS_XCLIENT 38
-#define SECCLASS_XINPUT 39
-#define SECCLASS_XSERVER 40
-#define SECCLASS_XEXTENSION 41
-#define SECCLASS_PAX 42
-#define SECCLASS_NETLINK_ROUTE_SOCKET 43
-#define SECCLASS_NETLINK_FIREWALL_SOCKET 44
-#define SECCLASS_NETLINK_TCPDIAG_SOCKET 45
-#define SECCLASS_NETLINK_NFLOG_SOCKET 46
-#define SECCLASS_NETLINK_XFRM_SOCKET 47
-#define SECCLASS_NETLINK_SELINUX_SOCKET 48
-#define SECCLASS_NETLINK_AUDIT_SOCKET 49
-#define SECCLASS_NETLINK_IP6FW_SOCKET 50
-#define SECCLASS_NETLINK_DNRT_SOCKET 51
-#define SECCLASS_DBUS 52
-
-/*
- * Security identifier indices for initial entities
- */
-#define SECINITSID_KERNEL 1
-#define SECINITSID_SECURITY 2
-#define SECINITSID_UNLABELED 3
-#define SECINITSID_FS 4
-#define SECINITSID_FILE 5
-#define SECINITSID_FILE_LABELS 6
-#define SECINITSID_INIT 7
-#define SECINITSID_ANY_SOCKET 8
-#define SECINITSID_PORT 9
-#define SECINITSID_NETIF 10
-#define SECINITSID_NETMSG 11
-#define SECINITSID_NODE 12
-#define SECINITSID_IGMP_PACKET 13
-#define SECINITSID_ICMP_SOCKET 14
-#define SECINITSID_TCP_SOCKET 15
-#define SECINITSID_SYSCTL_MODPROBE 16
-#define SECINITSID_SYSCTL 17
-#define SECINITSID_SYSCTL_FS 18
-#define SECINITSID_SYSCTL_KERNEL 19
-#define SECINITSID_SYSCTL_NET 20
-#define SECINITSID_SYSCTL_NET_UNIX 21
-#define SECINITSID_SYSCTL_VM 22
-#define SECINITSID_SYSCTL_DEV 23
-#define SECINITSID_KMOD 24
-#define SECINITSID_POLICY 25
-#define SECINITSID_SCMP_PACKET 26
-#define SECINITSID_DEVNULL 27
-
-#define SECINITSID_NUM 27
-
-#endif
diff --git a/libsepol/include/sepol/policydb/flask_types.h b/libsepol/include/sepol/policydb/flask_types.h
index 714176fd..7bec5129 100644
--- a/libsepol/include/sepol/policydb/flask_types.h
+++ b/libsepol/include/sepol/policydb/flask_types.h
@@ -33,17 +33,13 @@ typedef char *sepol_security_context_t;
* for a pair of SIDs. The bits within an access vector
* are interpreted differently depending on the class of
* the object. The access vector interpretations are specified
- * in flask/access_vectors, and the corresponding constants
- * for permissions are defined in the automatically generated
- * header file av_permissions.h.
+ * in policy.
*/
typedef uint32_t sepol_access_vector_t;
/*
* Each object class is identified by a fixed-size value.
- * The set of security classes is specified in flask/security_classes,
- * with the corresponding constants defined in the automatically
- * generated header file flask.h.
+ * The set of security classes is specified in policy.
*/
typedef uint16_t sepol_security_class_t;
#define SEPOL_SECCLASS_NULL 0x0000 /* no class */
diff --git a/libsepol/include/sepol/policydb/hashtab.h b/libsepol/include/sepol/policydb/hashtab.h
index ca5ba862..dca8c983 100644
--- a/libsepol/include/sepol/policydb/hashtab.h
+++ b/libsepol/include/sepol/policydb/hashtab.h
@@ -80,20 +80,6 @@ extern int hashtab_remove(hashtab_t h, hashtab_key_t k,
void *args), void *args);
/*
- Insert or replace the specified (key, datum) pair in the specified
- hash table. If an entry for the specified key already exists,
- then the specified destroy function is applied to (key,datum,args)
- for the entry prior to replacing the entry's contents.
-
- Returns SEPOL_ENOMEM if insufficient space is available or
- SEPOL_OK otherwise.
- */
-extern int hashtab_replace(hashtab_t h, hashtab_key_t k, hashtab_datum_t d,
- void (*destroy) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args), void *args);
-
-/*
Searches for the entry with the specified key in the hash table.
Returns NULL if no entry has the specified key or
@@ -122,20 +108,6 @@ extern int hashtab_map(hashtab_t h,
hashtab_datum_t d,
void *args), void *args);
-/*
- Same as hashtab_map, except that if apply returns a non-zero status,
- then the (key,datum) pair will be removed from the hashtab and the
- destroy function will be applied to (key,datum,args).
- */
-extern void hashtab_map_remove_on_error(hashtab_t h,
- int (*apply) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args),
- void (*destroy) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args),
- void *args);
-
extern void hashtab_hash_eval(hashtab_t h, char *tag);
#ifdef __cplusplus
diff --git a/libsepol/include/sepol/policydb/polcaps.h b/libsepol/include/sepol/policydb/polcaps.h
index 40669fb5..f5e32e60 100644
--- a/libsepol/include/sepol/policydb/polcaps.h
+++ b/libsepol/include/sepol/policydb/polcaps.h
@@ -7,16 +7,17 @@ extern "C" {
/* Policy capabilities */
enum {
- POLICYDB_CAPABILITY_NETPEER,
- POLICYDB_CAPABILITY_OPENPERM,
- POLICYDB_CAPABILITY_EXTSOCKCLASS,
- POLICYDB_CAPABILITY_ALWAYSNETWORK,
- POLICYDB_CAPABILITY_CGROUPSECLABEL,
- POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION,
- POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS,
- __POLICYDB_CAPABILITY_MAX
+ POLICYDB_CAP_NETPEER,
+ POLICYDB_CAP_OPENPERM,
+ POLICYDB_CAP_EXTSOCKCLASS,
+ POLICYDB_CAP_ALWAYSNETWORK,
+ POLICYDB_CAP_CGROUPSECLABEL,
+ POLICYDB_CAP_NNP_NOSUID_TRANSITION,
+ POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS,
+ POLICYDB_CAP_IOCTL_SKIP_CLOEXEC,
+ __POLICYDB_CAP_MAX
};
-#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
+#define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1)
/* Convert a capability name to number. */
extern int sepol_polcap_getnum(const char *name);
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 36e51375..f0f3476c 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -162,15 +162,16 @@ typedef struct role_allow {
} role_allow_t;
/* filename_trans rules */
-typedef struct filename_trans {
- uint32_t stype;
+typedef struct filename_trans_key {
uint32_t ttype;
uint32_t tclass;
char *name;
-} filename_trans_t;
+} filename_trans_key_t;
typedef struct filename_trans_datum {
- uint32_t otype; /* expected of new object */
+ ebitmap_t stypes;
+ uint32_t otype;
+ struct filename_trans_datum *next;
} filename_trans_datum_t;
/* Type attributes */
@@ -250,9 +251,9 @@ typedef struct class_perm_node {
struct class_perm_node *next;
} class_perm_node_t;
-#define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f)))
-#define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f)))
-#define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f)))
+#define xperm_test(x, p) (UINT32_C(1) & (p[x >> 5] >> (x & 0x1f)))
+#define xperm_set(x, p) (p[x >> 5] |= (UINT32_C(1) << (x & 0x1f)))
+#define xperm_clear(x, p) (p[x >> 5] &= ~(UINT32_C(1) << (x & 0x1f)))
#define EXTENDED_PERMS_LEN 8
typedef struct av_extended_perms {
@@ -591,6 +592,7 @@ typedef struct policydb {
/* file transitions with the last path component */
hashtab_t filename_trans;
+ uint32_t filename_trans_count;
ebitmap_t *type_attr_map;
@@ -605,6 +607,11 @@ typedef struct policydb {
unsigned policyvers;
unsigned handle_unknown;
+
+ sepol_security_class_t process_class;
+ sepol_security_class_t dir_class;
+ sepol_access_vector_t process_trans;
+ sepol_access_vector_t process_trans_dyntrans;
} policydb_t;
struct sepol_policydb {
@@ -645,6 +652,11 @@ extern int policydb_load_isids(policydb_t * p, sidtab_t * s);
extern int policydb_sort_ocontexts(policydb_t *p);
+extern int policydb_filetrans_insert(policydb_t *p, uint32_t stype,
+ uint32_t ttype, uint32_t tclass,
+ const char *name, char **name_alloc,
+ uint32_t otype, uint32_t *present_otype);
+
/* Deprecated */
extern int policydb_context_isvalid(const policydb_t * p,
const context_struct_t * c);
@@ -655,8 +667,8 @@ extern int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p);
extern void class_perm_node_init(class_perm_node_t * x);
extern void type_set_init(type_set_t * x);
extern void type_set_destroy(type_set_t * x);
-extern int type_set_cpy(type_set_t * dst, type_set_t * src);
-extern int type_set_or_eq(type_set_t * dst, type_set_t * other);
+extern int type_set_cpy(type_set_t * dst, const type_set_t * src);
+extern int type_set_or_eq(type_set_t * dst, const type_set_t * other);
extern void role_set_init(role_set_t * x);
extern void role_set_destroy(role_set_t * x);
extern void avrule_init(avrule_t * x);
@@ -743,10 +755,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define POLICYDB_VERSION_XPERMS_IOCTL 30 /* Linux-specific */
#define POLICYDB_VERSION_INFINIBAND 31 /* Linux-specific */
#define POLICYDB_VERSION_GLBLUB 32
+#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_GLBLUB
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS
/* Module versions and specific changes*/
#define MOD_POLICYDB_VERSION_BASE 4
@@ -791,7 +804,8 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define POLICYDB_CONFIG_UNKNOWN_MASK (DENY_UNKNOWN | REJECT_UNKNOWN | ALLOW_UNKNOWN)
-#define POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE 1 << 31;
+#define POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE (1 << 31)
+#define POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH (1 << 30)
#define OBJECT_R "object_r"
#define OBJECT_R_VAL 1
diff --git a/libsepol/include/sepol/roles.h b/libsepol/include/sepol/roles.h
deleted file mode 100644
index e750078c..00000000
--- a/libsepol/include/sepol/roles.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _SEPOL_ROLES_H_
-#define _SEPOL_ROLES_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int sepol_role_exists(const sepol_policydb_t * policydb,
- const char *role, int *response);
-
-extern int sepol_role_list(const sepol_policydb_t * policydb,
- char ***roles, unsigned int *nroles);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/libsepol/include/sepol/users.h b/libsepol/include/sepol/users.h
index 70158ac4..156d1adb 100644
--- a/libsepol/include/sepol/users.h
+++ b/libsepol/include/sepol/users.h
@@ -10,12 +10,6 @@
extern "C" {
#endif
-/* These two functions are deprecated. See src/deprecated_funcs.c */
-extern int sepol_genusers(void *data, size_t len,
- const char *usersdir,
- void **newdata, size_t * newlen);
-extern void sepol_set_delusers(int on);
-
/* Modify the user, or add it, if the key is not found */
extern int sepol_user_modify(sepol_handle_t * handle,
sepol_policydb_t * policydb,
diff --git a/libsepol/src/Makefile b/libsepol/src/Makefile
index ccb70233..13410c67 100644
--- a/libsepol/src/Makefile
+++ b/libsepol/src/Makefile
@@ -7,7 +7,7 @@ RANLIB ?= ranlib
CILDIR ?= ../cil
VERSION = $(shell cat ../VERSION)
-LIBVERSION = 1
+LIBVERSION = 2
LEX = flex
CIL_GENERATED = $(CILDIR)/src/cil_lexer.c
@@ -19,7 +19,7 @@ LIBMAP=libsepol.map
LIBSO=$(TARGET).$(LIBVERSION)
OBJS= $(patsubst %.c,%.o,$(sort $(wildcard *.c)))
LOBJS= $(patsubst %.c,%.lo,$(sort $(wildcard *.c)))
-CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-format-attribute -O2
+CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-format-attribute -O2 -fno-semantic-interposition
override CFLAGS += -I. -I../include -D_GNU_SOURCE
@@ -29,6 +29,12 @@ LOBJS += $(sort $(patsubst %.c,%.lo,$(sort $(wildcard $(CILDIR)/src/*.c)) $(CIL_
override CFLAGS += -I$(CILDIR)/include
endif
+# check for reallocarray(3) availability
+H := \#
+ifeq (yes,$(shell printf '${H}define _GNU_SOURCE\n${H}include <stdlib.h>\nint main(void){void*p=reallocarray(NULL, 1, sizeof(char));return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes))
+override CFLAGS += -DHAVE_REALLOCARRAY
+endif
+
LD_SONAME_FLAGS=-soname,$(LIBSO),--version-script=$(LIBMAP),-z,defs
LN=ln
diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c
index 1181edc2..161874c3 100644
--- a/libsepol/src/assertion.c
+++ b/libsepol/src/assertion.c
@@ -36,13 +36,21 @@ struct avtab_match_args {
unsigned long errors;
};
+static const char* policy_name(policydb_t *p) {
+ const char *policy_file = "policy.conf";
+ if (p->name) {
+ policy_file = p->name;
+ }
+ return policy_file;
+}
+
static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule,
unsigned int stype, unsigned int ttype,
const class_perm_node_t *curperm, uint32_t perms)
{
if (avrule->source_filename) {
- ERR(handle, "neverallow on line %lu of %s (or line %lu of policy.conf) violated by allow %s %s:%s {%s };",
- avrule->source_line, avrule->source_filename, avrule->line,
+ ERR(handle, "neverallow on line %lu of %s (or line %lu of %s) violated by allow %s %s:%s {%s };",
+ avrule->source_line, avrule->source_filename, avrule->line, policy_name(p),
p->p_type_val_to_name[stype],
p->p_type_val_to_name[ttype],
p->p_class_val_to_name[curperm->tclass - 1],
@@ -65,14 +73,11 @@ static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t
static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data)
{
for (; cp; cp = cp->next) {
- if ((cp->tclass == class) && (cp->data & data)) {
- break;
- }
+ if ((cp->tclass == class) && (cp->data & data))
+ return 1;
}
- if (!cp)
- return 0;
- return 1;
+ return 0;
}
static int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) {
@@ -151,15 +156,16 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle,
ebitmap_t *tattr = &p->type_attr_map[ttype];
ebitmap_node_t *snode, *tnode;
unsigned int i, j;
- int rc = 1;
- int ret = 0;
+ int rc;
+ int found_xperm = 0;
+ int errors = 0;
memcpy(&tmp_key, k, sizeof(avtab_key_t));
tmp_key.specified = AVTAB_XPERMS_ALLOWED;
ebitmap_for_each_positive_bit(sattr, snode, i) {
+ tmp_key.source_type = i + 1;
ebitmap_for_each_positive_bit(tattr, tnode, j) {
- tmp_key.source_type = i + 1;
tmp_key.target_type = j + 1;
for (node = avtab_search_node(avtab, &tmp_key);
node;
@@ -168,40 +174,39 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle,
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
continue;
-
+ found_xperm = 1;
rc = check_extended_permissions(avrule->xperms, xperms);
/* failure on the extended permission check_extended_permissions */
if (rc) {
extended_permissions_violated(&error, avrule->xperms, xperms);
- ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
+ ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
"allowxperm %s %s:%s %s;",
- avrule->source_line, avrule->source_filename, avrule->line,
+ avrule->source_line, avrule->source_filename, avrule->line, policy_name(p),
p->p_type_val_to_name[i],
p->p_type_val_to_name[j],
p->p_class_val_to_name[curperm->tclass - 1],
sepol_extended_perms_to_string(&error));
- rc = 0;
- ret++;
+ errors++;
}
}
}
}
/* failure on the regular permissions */
- if (rc) {
- ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
+ if (!found_xperm) {
+ ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
"allow %s %s:%s {%s };",
- avrule->source_line, avrule->source_filename, avrule->line,
+ avrule->source_line, avrule->source_filename, avrule->line, policy_name(p),
p->p_type_val_to_name[stype],
p->p_type_val_to_name[ttype],
p->p_class_val_to_name[curperm->tclass - 1],
sepol_av_to_string(p, curperm->tclass, perms));
- ret++;
+ errors++;
}
- return ret;
+ return errors;
}
static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args)
@@ -214,9 +219,10 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void
avrule_t *avrule = a->avrule;
class_perm_node_t *cp;
uint32_t perms;
- ebitmap_t src_matches, tgt_matches, self_matches, matches;
+ ebitmap_t src_matches, tgt_matches, self_matches;
ebitmap_node_t *snode, *tnode;
unsigned int i, j;
+ const int is_avrule_self = (avrule->flags & RULE_SELF) != 0;
if ((k->specified & AVTAB_ALLOWED) == 0)
return 0;
@@ -227,36 +233,32 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void
ebitmap_init(&src_matches);
ebitmap_init(&tgt_matches);
ebitmap_init(&self_matches);
- ebitmap_init(&matches);
rc = ebitmap_and(&src_matches, &avrule->stypes.types,
&p->attr_type_map[k->source_type - 1]);
- if (rc)
+ if (rc < 0)
goto oom;
- if (ebitmap_length(&src_matches) == 0)
+ if (ebitmap_is_empty(&src_matches))
goto exit;
rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
- if (rc)
+ if (rc < 0)
goto oom;
- if (avrule->flags == RULE_SELF) {
- rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1]);
- if (rc)
- goto oom;
- rc = ebitmap_and(&self_matches, &avrule->stypes.types, &matches);
- if (rc)
+ if (is_avrule_self) {
+ rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]);
+ if (rc < 0)
goto oom;
- if (ebitmap_length(&self_matches) > 0) {
+ if (!ebitmap_is_empty(&self_matches)) {
rc = ebitmap_union(&tgt_matches, &self_matches);
- if (rc)
+ if (rc < 0)
goto oom;
}
}
- if (ebitmap_length(&tgt_matches) == 0)
+ if (ebitmap_is_empty(&tgt_matches))
goto exit;
for (cp = avrule->perms; cp; cp = cp->next) {
@@ -268,6 +270,8 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void
ebitmap_for_each_positive_bit(&src_matches, snode, i) {
ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
+ if (is_avrule_self && i != j)
+ continue;
if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
a->errors += report_assertion_extended_permissions(handle,p, avrule,
i, j, cp, perms, k, avtab);
@@ -278,20 +282,16 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void
}
}
}
- goto exit;
oom:
- ERR(NULL, "Out of memory - unable to check neverallows");
-
exit:
ebitmap_destroy(&src_matches);
ebitmap_destroy(&tgt_matches);
ebitmap_destroy(&self_matches);
- ebitmap_destroy(&matches);
return rc;
}
-int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
+static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
{
int rc;
struct avtab_match_args args;
@@ -301,12 +301,14 @@ int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *a
args.avrule = avrule;
args.errors = 0;
+ args.avtab = &p->te_avtab;
rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args);
- if (rc)
+ if (rc < 0)
goto oom;
+ args.avtab = &p->te_cond_avtab;
rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args);
- if (rc)
+ if (rc < 0)
goto oom;
return args.errors;
@@ -337,8 +339,8 @@ static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t
tmp_key.specified = AVTAB_XPERMS_ALLOWED;
ebitmap_for_each_positive_bit(sattr, snode, i) {
+ tmp_key.source_type = i + 1;
ebitmap_for_each_positive_bit(tattr, tnode, j) {
- tmp_key.source_type = i + 1;
tmp_key.target_type = j + 1;
for (node = avtab_search_node(avtab, &tmp_key);
node;
@@ -350,7 +352,7 @@ static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t
continue;
rc = check_extended_permissions(neverallow_xperms, xperms);
if (rc)
- break;
+ return rc;
}
}
}
@@ -377,125 +379,138 @@ static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t
static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab,
avtab_key_t *k, policydb_t *p)
{
- ebitmap_t src_matches, tgt_matches, self_matches, matches;
+ ebitmap_t src_matches, tgt_matches, self_matches;
unsigned int i, j;
ebitmap_node_t *snode, *tnode;
- class_perm_node_t *cp;
+ const int is_avrule_self = (avrule->flags & RULE_SELF) != 0;
int rc;
- int ret = 1;
ebitmap_init(&src_matches);
ebitmap_init(&tgt_matches);
ebitmap_init(&self_matches);
- ebitmap_init(&matches);
rc = ebitmap_and(&src_matches, &avrule->stypes.types,
&p->attr_type_map[k->source_type - 1]);
- if (rc)
+ if (rc < 0)
goto oom;
- if (ebitmap_length(&src_matches) == 0)
+ if (ebitmap_is_empty(&src_matches)) {
+ rc = 0;
goto exit;
+ }
rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types,
&p->attr_type_map[k->target_type -1]);
- if (rc)
+ if (rc < 0)
goto oom;
- if (avrule->flags == RULE_SELF) {
- rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1],
- &p->attr_type_map[k->target_type - 1]);
- if (rc)
- goto oom;
- rc = ebitmap_and(&self_matches, &avrule->stypes.types, &matches);
- if (rc)
+ if (is_avrule_self) {
+ rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]);
+ if (rc < 0)
goto oom;
- if (ebitmap_length(&self_matches) > 0) {
+ if (!ebitmap_is_empty(&self_matches)) {
rc = ebitmap_union(&tgt_matches, &self_matches);
- if (rc)
+ if (rc < 0)
goto oom;
}
}
- if (ebitmap_length(&tgt_matches) == 0)
+ if (ebitmap_is_empty(&tgt_matches)) {
+ rc = 0;
goto exit;
+ }
- for (cp = avrule->perms; cp; cp = cp->next) {
- if (cp->tclass != k->target_class)
- continue;
- ebitmap_for_each_positive_bit(&src_matches, snode, i) {
- ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
- ret = check_assertion_extended_permissions_avtab(
- avrule, avtab, i, j, k, p);
- if (ret)
- goto exit;
+ ebitmap_for_each_positive_bit(&src_matches, snode, i) {
+ ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
+ if (is_avrule_self && i != j)
+ continue;
+ if (check_assertion_extended_permissions_avtab(avrule, avtab, i, j, k, p)) {
+ rc = 1;
+ goto exit;
}
}
}
- goto exit;
-oom:
- ERR(NULL, "Out of memory - unable to check neverallows");
+ rc = 0;
+oom:
exit:
ebitmap_destroy(&src_matches);
ebitmap_destroy(&tgt_matches);
- ebitmap_destroy(&matches);
- return ret;
+ ebitmap_destroy(&self_matches);
+ return rc;
+}
+
+static int check_assertion_self_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p)
+{
+ ebitmap_t src_matches;
+ int rc;
+
+ /* The key's target must match something in the matches of the avrule's source
+ * and the key's source.
+ */
+
+ rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]);
+ if (rc < 0)
+ goto oom;
+
+ if (!ebitmap_match_any(&src_matches, &p->attr_type_map[k->target_type - 1])) {
+ rc = 0;
+ goto nomatch;
+ }
+
+ rc = 1;
+
+oom:
+nomatch:
+ ebitmap_destroy(&src_matches);
+ return rc;
}
static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args)
{
- int rc, rc2 = 0;
+ int rc;
struct avtab_match_args *a = (struct avtab_match_args *)args;
policydb_t *p = a->p;
avrule_t *avrule = a->avrule;
avtab_t *avtab = a->avtab;
if ((k->specified & AVTAB_ALLOWED) == 0)
- goto exit;
+ goto nomatch;
if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
- goto exit;
+ goto nomatch;
- rc = ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1]);
- if (rc == 0)
- goto exit;
+ if (!ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1]))
+ goto nomatch;
- if (avrule->flags == RULE_SELF) {
- /* If the neverallow uses SELF, then it is not enough that the
- * neverallow's source matches the src and tgt of the rule being checked.
- * It must match the same thing in the src and tgt, so AND the source
- * and target together and check for a match on the result.
- */
- ebitmap_t match;
- rc = ebitmap_and(&match, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1] );
- if (rc) {
- ebitmap_destroy(&match);
- goto oom;
+ /* neverallow may have tgts even if it uses SELF */
+ if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) {
+ if (avrule->flags == RULE_SELF) {
+ rc = check_assertion_self_match(k, avrule, p);
+ if (rc < 0)
+ goto oom;
+ if (rc == 0)
+ goto nomatch;
+ } else {
+ goto nomatch;
}
- rc2 = ebitmap_match_any(&avrule->stypes.types, &match);
- ebitmap_destroy(&match);
}
- /* neverallow may have tgts even if it uses SELF */
- rc = ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
- if (rc == 0 && rc2 == 0)
- goto exit;
-
if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
rc = check_assertion_extended_permissions(avrule, avtab, k, p);
+ if (rc < 0)
+ goto oom;
if (rc == 0)
- goto exit;
+ goto nomatch;
}
return 1;
-exit:
+nomatch:
return 0;
oom:
- ERR(NULL, "Out of memory - unable to check neverallows");
return rc;
}
@@ -538,6 +553,10 @@ int check_assertions(sepol_handle_t * handle, policydb_t * p,
if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)))
continue;
rc = check_assertion(p, a);
+ if (rc < 0) {
+ ERR(handle, "Error occurred while checking neverallows");
+ return -1;
+ }
if (rc) {
rc = report_assertion_failures(handle, p, a);
if (rc < 0) {
diff --git a/libsepol/src/av_permissions.h b/libsepol/src/av_permissions.h
deleted file mode 100644
index 97278ed9..00000000
--- a/libsepol/src/av_permissions.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/* Used by security_compute_av. */
-#define PROCESS__TRANSITION 0x00000002UL
-#define PROCESS__DYNTRANSITION 0x00800000UL
diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c
index a9832d0d..dcfce8b8 100644
--- a/libsepol/src/avrule_block.c
+++ b/libsepol/src/avrule_block.c
@@ -30,7 +30,7 @@
/* It is anticipated that there be less declarations within an avrule
* block than the global policy. Thus the symbol table sizes are
* smaller than those listed in policydb.c */
-static unsigned int symtab_sizes[SYM_NUM] = {
+static const unsigned int symtab_sizes[SYM_NUM] = {
2,
4,
8,
diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c
index 257f051a..7920b60a 100644
--- a/libsepol/src/avtab.c
+++ b/libsepol/src/avtab.c
@@ -52,6 +52,7 @@
/* Based on MurmurHash3, written by Austin Appleby and placed in the
* public domain.
*/
+ignore_unsigned_overflow_
static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
{
static const uint32_t c1 = 0xcc9e2d51;
@@ -63,7 +64,7 @@ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
uint32_t hash = 0;
-#define mix(input) { \
+#define mix(input) do { \
uint32_t v = input; \
v *= c1; \
v = (v << r1) | (v >> (32 - r1)); \
@@ -71,7 +72,7 @@ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
hash ^= v; \
hash = (hash << r2) | (hash >> (32 - r2)); \
hash = hash * m + n; \
-}
+} while (0)
mix(keyp->target_class);
mix(keyp->target_type);
@@ -375,7 +376,7 @@ int avtab_alloc(avtab_t *h, uint32_t nrules)
}
if (shift > 2)
shift = shift - 2;
- nslot = 1 << shift;
+ nslot = UINT32_C(1) << shift;
if (nslot > MAX_AVTAB_HASH_BUCKETS)
nslot = MAX_AVTAB_HASH_BUCKETS;
mask = nslot - 1;
@@ -418,7 +419,7 @@ void avtab_hash_eval(avtab_t * h, char *tag)
}
/* Ordering of datums in the original avtab format in the policy file. */
-static uint16_t spec_order[] = {
+static const uint16_t spec_order[] = {
AVTAB_ALLOWED,
AVTAB_AUDITDENY,
AVTAB_AUDITALLOW,
@@ -502,6 +503,11 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
if (val & spec_order[i]) {
+ if (items >= items2) { /* items is index, items2 is total number */
+ ERR(fp->handle, "entry has too many items (%d/%d)",
+ items + 1, items2);
+ return -1;
+ }
key.specified = spec_order[i] | enabled;
datum.data = le32_to_cpu(buf32[items++]);
rc = insertf(a, &key, &datum, p);
@@ -542,7 +548,7 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) &&
(key.specified & AVTAB_XPERMS)) {
ERR(fp->handle, "policy version %u does not support extended "
- "permissions rules and one was specified\n", vers);
+ "permissions rules and one was specified", vers);
return -1;
} else if (key.specified & AVTAB_XPERMS) {
rc = next_entry(&buf8, fp, sizeof(uint8_t));
diff --git a/libsepol/src/boolean_internal.h b/libsepol/src/boolean_internal.h
index aad7adec..1c1e6a39 100644
--- a/libsepol/src/boolean_internal.h
+++ b/libsepol/src/boolean_internal.h
@@ -3,14 +3,5 @@
#include <sepol/boolean_record.h>
#include <sepol/booleans.h>
-#include "dso.h"
-hidden_proto(sepol_bool_key_create)
- hidden_proto(sepol_bool_key_unpack)
- hidden_proto(sepol_bool_get_name)
- hidden_proto(sepol_bool_set_name)
- hidden_proto(sepol_bool_get_value)
- hidden_proto(sepol_bool_set_value)
- hidden_proto(sepol_bool_create)
- hidden_proto(sepol_bool_free)
#endif
diff --git a/libsepol/src/boolean_record.c b/libsepol/src/boolean_record.c
index a194704e..6cbf627a 100644
--- a/libsepol/src/boolean_record.c
+++ b/libsepol/src/boolean_record.c
@@ -41,7 +41,6 @@ int sepol_bool_key_create(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_bool_key_create)
void sepol_bool_key_unpack(const sepol_bool_key_t * key, const char **name)
{
@@ -49,7 +48,6 @@ void sepol_bool_key_unpack(const sepol_bool_key_t * key, const char **name)
*name = key->name;
}
-hidden_def(sepol_bool_key_unpack)
int sepol_bool_key_extract(sepol_handle_t * handle,
const sepol_bool_t * boolean,
@@ -94,7 +92,6 @@ const char *sepol_bool_get_name(const sepol_bool_t * boolean)
return boolean->name;
}
-hidden_def(sepol_bool_get_name)
int sepol_bool_set_name(sepol_handle_t * handle,
sepol_bool_t * boolean, const char *name)
@@ -110,7 +107,6 @@ int sepol_bool_set_name(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_bool_set_name)
/* Value */
int sepol_bool_get_value(const sepol_bool_t * boolean)
@@ -119,7 +115,6 @@ int sepol_bool_get_value(const sepol_bool_t * boolean)
return boolean->value;
}
-hidden_def(sepol_bool_get_value)
void sepol_bool_set_value(sepol_bool_t * boolean, int value)
{
@@ -127,7 +122,6 @@ void sepol_bool_set_value(sepol_bool_t * boolean, int value)
boolean->value = value;
}
-hidden_def(sepol_bool_set_value)
/* Create */
int sepol_bool_create(sepol_handle_t * handle, sepol_bool_t ** bool_ptr)
@@ -148,7 +142,6 @@ int sepol_bool_create(sepol_handle_t * handle, sepol_bool_t ** bool_ptr)
return STATUS_SUCCESS;
}
-hidden_def(sepol_bool_create)
/* Deep copy clone */
int sepol_bool_clone(sepol_handle_t * handle,
@@ -185,4 +178,3 @@ void sepol_bool_free(sepol_bool_t * boolean)
free(boolean);
}
-hidden_def(sepol_bool_free)
diff --git a/libsepol/src/booleans.c b/libsepol/src/booleans.c
index 30fcf29d..716da6b4 100644
--- a/libsepol/src/booleans.c
+++ b/libsepol/src/booleans.c
@@ -19,6 +19,7 @@ static int bool_update(sepol_handle_t * handle,
const char *cname;
char *name;
int value;
+ cond_bool_datum_t *datum;
sepol_bool_key_unpack(key, &cname);
name = strdup(cname);
@@ -27,8 +28,7 @@ static int bool_update(sepol_handle_t * handle,
if (!name)
goto omem;
- cond_bool_datum_t *datum =
- hashtab_search(policydb->p_bools.table, name);
+ datum = hashtab_search(policydb->p_bools.table, name);
if (!datum) {
ERR(handle, "boolean %s no longer in policy", name);
goto err;
@@ -84,10 +84,10 @@ int sepol_bool_set(sepol_handle_t * handle,
const sepol_bool_key_t * key, const sepol_bool_t * data)
{
+ policydb_t *policydb = &p->p;
const char *name;
sepol_bool_key_unpack(key, &name);
- policydb_t *policydb = &p->p;
if (bool_update(handle, policydb, key, data) < 0)
goto err;
diff --git a/libsepol/src/conditional.c b/libsepol/src/conditional.c
index 823b649a..f78b38a2 100644
--- a/libsepol/src/conditional.c
+++ b/libsepol/src/conditional.c
@@ -25,6 +25,7 @@
#include <sepol/policydb/conditional.h>
#include "private.h"
+#include "debug.h"
/* move all type rules to top of t/f lists to help kernel on evaluation */
static void cond_optimize(cond_av_list_t ** l)
@@ -314,8 +315,7 @@ static int evaluate_cond_node(policydb_t * p, cond_node_t * node)
if (new_state != node->cur_state) {
node->cur_state = new_state;
if (new_state == -1)
- printf
- ("expression result was undefined - disabling all rules.\n");
+ WARN(NULL, "expression result was undefined - disabling all rules.");
/* turn the rules on or off */
for (cur = node->true_list; cur != NULL; cur = cur->next) {
if (new_state <= 0) {
@@ -368,8 +368,7 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
if (ne) {
ne->next = NULL;
} else { /* ne should never be NULL */
- printf
- ("Found expr with no bools and only a ! - this should never happen.\n");
+ ERR(NULL, "Found expr with no bools and only a ! - this should never happen.");
return -1;
}
/* swap the true and false lists */
@@ -388,7 +387,6 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
for (e = cn->expr; e != NULL; e = e->next) {
switch (e->expr_type) {
case COND_BOOL:
- i = 0;
/* see if we've already seen this bool */
if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) {
/* count em all but only record up to COND_MAX_BOOLS */
@@ -412,24 +410,23 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
}
/* loop through all possible combinations of values for bools in expression */
- for (test = 0x0; test < (0x1U << cn->nbools); test++) {
+ for (test = 0x0; test < (UINT32_C(1) << cn->nbools); test++) {
/* temporarily set the value for all the bools in the
* expression using the corr. bit in test */
for (j = 0; j < cn->nbools; j++) {
p->bool_val_to_struct[cn->bool_ids[j] -
1]->state =
- (test & (0x1 << j)) ? 1 : 0;
+ (test & (UINT32_C(1) << j)) ? 1 : 0;
}
k = cond_evaluate_expr(p, cn->expr);
if (k == -1) {
- printf
- ("While testing expression, expression result "
- "was undefined - this should never happen.\n");
+ ERR(NULL, "While testing expression, expression result "
+ "was undefined - this should never happen.");
return -1;
}
/* set the bit if expression evaluates true */
if (k)
- cn->expr_pre_comp |= 0x1 << test;
+ cn->expr_pre_comp |= UINT32_C(1) << test;
}
/* restore bool default values */
@@ -525,7 +522,7 @@ int cond_init_bool_indexes(policydb_t * p)
if (p->bool_val_to_struct)
free(p->bool_val_to_struct);
p->bool_val_to_struct = (cond_bool_datum_t **)
- malloc(p->p_bools.nprim * sizeof(cond_bool_datum_t *));
+ mallocarray(p->p_bools.nprim, sizeof(cond_bool_datum_t *));
if (!p->bool_val_to_struct)
return -1;
return 0;
@@ -636,9 +633,8 @@ static int cond_insertf(avtab_t * a
*/
if (k->specified & AVTAB_TYPE) {
if (avtab_search(&p->te_avtab, k)) {
- printf
- ("security: type rule already exists outside of a conditional.");
- goto err;
+ WARN(NULL, "security: type rule already exists outside of a conditional.");
+ return -1;
}
/*
* If we are reading the false list other will be a pointer to
@@ -653,9 +649,8 @@ static int cond_insertf(avtab_t * a
if (node_ptr) {
if (avtab_search_node_next
(node_ptr, k->specified)) {
- printf
- ("security: too many conflicting type rules.");
- goto err;
+ ERR(NULL, "security: too many conflicting type rules.");
+ return -1;
}
found = 0;
for (cur = other; cur != NULL; cur = cur->next) {
@@ -665,30 +660,28 @@ static int cond_insertf(avtab_t * a
}
}
if (!found) {
- printf
- ("security: conflicting type rules.\n");
- goto err;
+ ERR(NULL, "security: conflicting type rules.");
+ return -1;
}
}
} else {
if (avtab_search(&p->te_cond_avtab, k)) {
- printf
- ("security: conflicting type rules when adding type rule for true.\n");
- goto err;
+ ERR(NULL, "security: conflicting type rules when adding type rule for true.");
+ return -1;
}
}
}
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
if (!node_ptr) {
- printf("security: could not insert rule.");
- goto err;
+ ERR(NULL, "security: could not insert rule.");
+ return -1;
}
node_ptr->parse_context = (void *)1;
list = malloc(sizeof(cond_av_list_t));
if (!list)
- goto err;
+ return -1;
memset(list, 0, sizeof(cond_av_list_t));
list->node = node_ptr;
@@ -698,11 +691,6 @@ static int cond_insertf(avtab_t * a
data->tail->next = list;
data->tail = list;
return 0;
-
- err:
- cond_av_list_destroy(data->head);
- data->head = NULL;
- return -1;
}
static int cond_read_av_list(policydb_t * p, void *fp,
@@ -715,7 +703,6 @@ static int cond_read_av_list(policydb_t * p, void *fp,
*ret_list = NULL;
- len = 0;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
return -1;
@@ -732,8 +719,10 @@ static int cond_read_av_list(policydb_t * p, void *fp,
for (i = 0; i < len; i++) {
rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab,
cond_insertf, &data);
- if (rc)
+ if (rc) {
+ cond_av_list_destroy(data.head);
return rc;
+ }
}
@@ -744,14 +733,12 @@ static int cond_read_av_list(policydb_t * p, void *fp,
static int expr_isvalid(policydb_t * p, cond_expr_t * expr)
{
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
- printf
- ("security: conditional expressions uses unknown operator.\n");
+ WARN(NULL, "security: conditional expressions uses unknown operator.");
return 0;
}
if (expr->bool > p->p_bools.nprim) {
- printf
- ("security: conditional expressions uses unknown bool.\n");
+ WARN(NULL, "security: conditional expressions uses unknown bool.");
return 0;
}
return 1;
@@ -769,7 +756,6 @@ static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp)
node->cur_state = le32_to_cpu(buf[0]);
- len = 0;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
goto err;
diff --git a/libsepol/src/constraint.c b/libsepol/src/constraint.c
index 71540195..58eb6da7 100644
--- a/libsepol/src/constraint.c
+++ b/libsepol/src/constraint.c
@@ -38,10 +38,14 @@ int constraint_expr_init(constraint_expr_t * expr)
void constraint_expr_destroy(constraint_expr_t * expr)
{
- if (expr != NULL) {
+ constraint_expr_t *next;
+
+ while (expr != NULL) {
+ next = expr->next;
ebitmap_destroy(&expr->names);
type_set_destroy(expr->type_names);
free(expr->type_names);
free(expr);
+ expr = next;
}
}
diff --git a/libsepol/src/context_internal.h b/libsepol/src/context_internal.h
index 7987c1ce..3dc9cd15 100644
--- a/libsepol/src/context_internal.h
+++ b/libsepol/src/context_internal.h
@@ -1,19 +1,7 @@
#ifndef _SEPOL_CONTEXT_INTERNAL_H_
#define _SEPOL_CONTEXT_INTERNAL_H_
+#include <sepol/context.h>
#include <sepol/context_record.h>
-#include "dso.h"
-hidden_proto(sepol_context_clone)
- hidden_proto(sepol_context_create)
- hidden_proto(sepol_context_free)
- hidden_proto(sepol_context_from_string)
- hidden_proto(sepol_context_get_mls)
- hidden_proto(sepol_context_get_role)
- hidden_proto(sepol_context_get_type)
- hidden_proto(sepol_context_get_user)
- hidden_proto(sepol_context_set_mls)
- hidden_proto(sepol_context_set_role)
- hidden_proto(sepol_context_set_type)
- hidden_proto(sepol_context_set_user)
#endif
diff --git a/libsepol/src/context_record.c b/libsepol/src/context_record.c
index 0a8bbf6d..2bda121b 100644
--- a/libsepol/src/context_record.c
+++ b/libsepol/src/context_record.c
@@ -29,7 +29,6 @@ const char *sepol_context_get_user(const sepol_context_t * con)
return con->user;
}
-hidden_def(sepol_context_get_user)
int sepol_context_set_user(sepol_handle_t * handle,
sepol_context_t * con, const char *user)
@@ -47,7 +46,6 @@ int sepol_context_set_user(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_context_set_user)
/* Role */
const char *sepol_context_get_role(const sepol_context_t * con)
@@ -56,7 +54,6 @@ const char *sepol_context_get_role(const sepol_context_t * con)
return con->role;
}
-hidden_def(sepol_context_get_role)
int sepol_context_set_role(sepol_handle_t * handle,
sepol_context_t * con, const char *role)
@@ -73,7 +70,6 @@ int sepol_context_set_role(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_context_set_role)
/* Type */
const char *sepol_context_get_type(const sepol_context_t * con)
@@ -82,7 +78,6 @@ const char *sepol_context_get_type(const sepol_context_t * con)
return con->type;
}
-hidden_def(sepol_context_get_type)
int sepol_context_set_type(sepol_handle_t * handle,
sepol_context_t * con, const char *type)
@@ -99,7 +94,6 @@ int sepol_context_set_type(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_context_set_type)
/* MLS */
const char *sepol_context_get_mls(const sepol_context_t * con)
@@ -108,7 +102,6 @@ const char *sepol_context_get_mls(const sepol_context_t * con)
return con->mls;
}
-hidden_def(sepol_context_get_mls)
int sepol_context_set_mls(sepol_handle_t * handle,
sepol_context_t * con, const char *mls)
@@ -125,7 +118,6 @@ int sepol_context_set_mls(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_context_set_mls)
/* Create */
int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr)
@@ -135,7 +127,7 @@ int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr)
(sepol_context_t *) malloc(sizeof(sepol_context_t));
if (!con) {
- ERR(handle, "out of memory, could not " "create context\n");
+ ERR(handle, "out of memory, could not create context");
return STATUS_ERR;
}
@@ -147,7 +139,6 @@ int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr)
return STATUS_SUCCESS;
}
-hidden_def(sepol_context_create)
/* Deep copy clone */
int sepol_context_clone(sepol_handle_t * handle,
@@ -188,7 +179,6 @@ int sepol_context_clone(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_context_clone)
/* Destroy */
void sepol_context_free(sepol_context_t * con)
@@ -204,7 +194,6 @@ void sepol_context_free(sepol_context_t * con)
free(con);
}
-hidden_def(sepol_context_free)
int sepol_context_from_string(sepol_handle_t * handle,
const char *str, sepol_context_t ** con)
@@ -278,32 +267,13 @@ int sepol_context_from_string(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_context_from_string)
-
-static inline int safe_sum(size_t *sum, const size_t augends[], const size_t cnt) {
-
- size_t a, i;
-
- *sum = 0;
- for(i=0; i < cnt; i++) {
- /* sum should not be smaller than the addend */
- a = augends[i];
- *sum += a;
- if (*sum < a) {
- return i;
- }
- }
-
- return 0;
-}
-
int sepol_context_to_string(sepol_handle_t * handle,
const sepol_context_t * con, char **str_ptr)
{
int rc;
char *str = NULL;
- size_t total_sz, err;
+ size_t total_sz = 0, i;
const size_t sizes[] = {
strlen(con->user), /* user length */
strlen(con->role), /* role length */
@@ -312,10 +282,11 @@ int sepol_context_to_string(sepol_handle_t * handle,
((con->mls) ? 3 : 2) + 1 /* mls has extra ":" also null byte */
};
- err = safe_sum(&total_sz, sizes, ARRAY_SIZE(sizes));
- if (err) {
- ERR(handle, "invalid size, overflow at position: %zu", err);
- goto err;
+ for (i = 0; i < ARRAY_SIZE(sizes); i++) {
+ if (__builtin_add_overflow(total_sz, sizes[i], &total_sz)) {
+ ERR(handle, "invalid size, overflow at position: %zu", i);
+ goto err;
+ }
}
str = (char *)malloc(total_sz);
diff --git a/libsepol/src/debug.c b/libsepol/src/debug.c
index db57090f..f6a59ae7 100644
--- a/libsepol/src/debug.c
+++ b/libsepol/src/debug.c
@@ -23,30 +23,28 @@ int sepol_msg_get_level(sepol_handle_t * handle)
return handle->msg_level;
}
-hidden_def(sepol_msg_get_level)
const char *sepol_msg_get_channel(sepol_handle_t * handle)
{
return handle->msg_channel;
}
-hidden_def(sepol_msg_get_channel)
const char *sepol_msg_get_fname(sepol_handle_t * handle)
{
return handle->msg_fname;
}
-hidden_def(sepol_msg_get_fname)
#ifdef __GNUC__
__attribute__ ((format(printf, 3, 4)))
#endif
-void hidden sepol_msg_default_handler(void *varg __attribute__ ((unused)),
+void sepol_msg_default_handler(void *varg __attribute__ ((unused)),
sepol_handle_t * handle,
const char *fmt, ...)
{
FILE *stream = NULL;
+ va_list ap;
switch (sepol_msg_get_level(handle)) {
@@ -63,7 +61,6 @@ void hidden sepol_msg_default_handler(void *varg __attribute__ ((unused)),
fprintf(stream, "%s.%s: ",
sepol_msg_get_channel(handle), sepol_msg_get_fname(handle));
- va_list ap;
va_start(ap, fmt);
vfprintf(stream, fmt, ap);
va_end(ap);
diff --git a/libsepol/src/debug.h b/libsepol/src/debug.h
index 56b397b5..0b3965d8 100644
--- a/libsepol/src/debug.h
+++ b/libsepol/src/debug.h
@@ -21,7 +21,6 @@
#include <stdio.h>
#include <sepol/debug.h>
-#include "dso.h"
#include "handle.h"
#define STATUS_SUCCESS 0
@@ -62,13 +61,10 @@
#ifdef __GNUC__
__attribute__ ((format(printf, 3, 4)))
#endif
-extern void hidden sepol_msg_default_handler(void *varg,
+extern void sepol_msg_default_handler(void *varg,
sepol_handle_t * msg,
const char *fmt, ...);
extern struct sepol_handle sepol_compat_handle;
-hidden_proto(sepol_msg_get_channel)
- hidden_proto(sepol_msg_get_fname)
- hidden_proto(sepol_msg_get_level)
#endif
diff --git a/libsepol/src/deprecated_funcs.c b/libsepol/src/deprecated_funcs.c
deleted file mode 100644
index d0dab7df..00000000
--- a/libsepol/src/deprecated_funcs.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <stdio.h>
-#include "debug.h"
-
-/*
- * Need to keep these stubs for the libsepol interfaces exported in
- * libsepol.map.in, as they are part of the shared library ABI.
- */
-
-static const char *msg = "Deprecated interface";
-
-/*
- * These two functions are deprecated and referenced in:
- * include/libsepol/users.h
- */
-int sepol_genusers(void *data __attribute((unused)),
- size_t len __attribute((unused)),
- const char *usersdir __attribute((unused)),
- void **newdata __attribute((unused)),
- size_t *newlen __attribute((unused)))
-{
- WARN(NULL, "%s", msg);
- return -1;
-}
-
-void sepol_set_delusers(int on __attribute((unused)))
-{
- WARN(NULL, "%s", msg);
-}
-
-/*
- * These two functions are deprecated and referenced in:
- * include/libsepol/booleans.h
- */
-int sepol_genbools(void *data __attribute((unused)),
- size_t len __attribute((unused)),
- const char *booleans __attribute((unused)))
-{
- WARN(NULL, "%s", msg);
- return -1;
-}
-
-int sepol_genbools_array(void *data __attribute((unused)),
- size_t len __attribute((unused)),
- char **names __attribute((unused)),
- int *values __attribute((unused)),
- int nel __attribute((unused)))
-{
- WARN(NULL, "%s", msg);
- return -1;
-}
diff --git a/libsepol/src/dso.h b/libsepol/src/dso.h
deleted file mode 100644
index a06e3496..00000000
--- a/libsepol/src/dso.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _SEPOL_DSO_H
-#define _SEPOL_DSO_H 1
-
-#if !defined(SHARED) || defined(ANDROID)
- #define DISABLE_SYMVER 1
-#endif
-
-#ifdef SHARED
-# define hidden __attribute__ ((visibility ("hidden")))
-# define hidden_proto(fct) __hidden_proto (fct, fct##_internal)
-# define __hidden_proto(fct, internal) \
- extern __typeof (fct) internal; \
- extern __typeof (fct) fct __asm (#internal) hidden;
-# if defined(__alpha__) || defined(__mips__)
-# define hidden_def(fct) \
- asm (".globl " #fct "\n" #fct " = " #fct "_internal");
-# else
-# define hidden_def(fct) \
- asm (".globl " #fct "\n.set " #fct ", " #fct "_internal");
-#endif
-#else
-# define hidden
-# define hidden_proto(fct)
-# define hidden_def(fct)
-#endif
-
-#endif
diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c
index 6c9951b7..bd98c0f8 100644
--- a/libsepol/src/ebitmap.c
+++ b/libsepol/src/ebitmap.c
@@ -17,7 +17,8 @@
int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2)
{
- ebitmap_node_t *n1, *n2, *new, *prev;
+ const ebitmap_node_t *n1, *n2;
+ ebitmap_node_t *new, *prev;
ebitmap_init(dst);
@@ -71,7 +72,7 @@ int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1)
return 0;
}
-int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2)
{
unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2));
ebitmap_init(dst);
@@ -85,7 +86,7 @@ int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
return 0;
}
-int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
+int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2)
{
unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2));
ebitmap_init(dst);
@@ -98,7 +99,7 @@ int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
return 0;
}
-int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
+int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit)
{
unsigned int i;
ebitmap_init(dst);
@@ -111,11 +112,12 @@ int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
return 0;
}
-int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit)
+int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit)
{
+ int rc;
ebitmap_t e3;
ebitmap_init(dst);
- int rc = ebitmap_not(&e3, e2, maxbit);
+ rc = ebitmap_not(&e3, e2, maxbit);
if (rc < 0)
return rc;
rc = ebitmap_and(dst, e1, &e3);
@@ -125,31 +127,35 @@ int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int ma
return 0;
}
-unsigned int ebitmap_cardinality(ebitmap_t *e1)
+unsigned int ebitmap_cardinality(const ebitmap_t *e1)
{
- unsigned int i, count = 0;
- for (i=ebitmap_startbit(e1); i < ebitmap_length(e1); i++)
- if (ebitmap_get_bit(e1, i))
- count++;
+ unsigned int count = 0;
+ const ebitmap_node_t *n;
+
+ for (n = e1->node; n; n = n->next) {
+ count += __builtin_popcountll(n->map);
+ }
return count;
}
-int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2)
+int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2)
{
+ int rc;
+ ebitmap_t tmp;
+ int distance;
if (ebitmap_cmp(e1, e2))
return 0;
- ebitmap_t tmp;
- int rc = ebitmap_xor(&tmp, e1, e2);
+ rc = ebitmap_xor(&tmp, e1, e2);
if (rc < 0)
return -1;
- int distance = ebitmap_cardinality(&tmp);
+ distance = ebitmap_cardinality(&tmp);
ebitmap_destroy(&tmp);
return distance;
}
int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2)
{
- ebitmap_node_t *n1, *n2;
+ const ebitmap_node_t *n1, *n2;
if (e1->highbit != e2->highbit)
return 0;
@@ -170,7 +176,8 @@ int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2)
int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src)
{
- ebitmap_node_t *n, *new, *prev;
+ const ebitmap_node_t *n;
+ ebitmap_node_t *new, *prev;
ebitmap_init(dst);
n = src->node;
@@ -199,7 +206,7 @@ int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src)
int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2)
{
- ebitmap_node_t *n1, *n2;
+ const ebitmap_node_t *n1, *n2;
if (e1->highbit < e2->highbit)
return 0;
@@ -226,8 +233,8 @@ int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2)
int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2)
{
- ebitmap_node_t *n1 = e1->node;
- ebitmap_node_t *n2 = e2->node;
+ const ebitmap_node_t *n1 = e1->node;
+ const ebitmap_node_t *n2 = e2->node;
while (n1 && n2) {
if (n1->startbit < n2->startbit) {
@@ -248,7 +255,7 @@ int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2)
int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit)
{
- ebitmap_node_t *n;
+ const ebitmap_node_t *n;
if (e->highbit < bit)
return 0;
@@ -342,6 +349,26 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value)
return 0;
}
+unsigned int ebitmap_highest_set_bit(const ebitmap_t * e)
+{
+ const ebitmap_node_t *n;
+ MAPTYPE map;
+ unsigned int pos = 0;
+
+ n = e->node;
+ if (!n)
+ return 0;
+
+ while (n->next)
+ n = n->next;
+
+ map = n->map;
+ while (map >>= 1)
+ pos++;
+
+ return n->startbit + pos;
+}
+
void ebitmap_destroy(ebitmap_t * e)
{
ebitmap_node_t *n, *temp;
@@ -379,8 +406,7 @@ int ebitmap_read(ebitmap_t * e, void *fp)
count = le32_to_cpu(buf[2]);
if (mapsize != MAPSIZE) {
- printf
- ("security: ebitmap: map size %d does not match my size %zu (high bit was %d)\n",
+ ERR(NULL, "security: ebitmap: map size %d does not match my size %zu (high bit was %d)",
mapsize, MAPSIZE, e->highbit);
goto bad;
}
@@ -389,8 +415,7 @@ int ebitmap_read(ebitmap_t * e, void *fp)
goto ok;
}
if (e->highbit & (MAPSIZE - 1)) {
- printf
- ("security: ebitmap: high bit (%d) is not a multiple of the map size (%zu)\n",
+ ERR(NULL, "security: ebitmap: high bit (%d) is not a multiple of the map size (%zu)",
e->highbit, MAPSIZE);
goto bad;
}
@@ -402,12 +427,12 @@ int ebitmap_read(ebitmap_t * e, void *fp)
for (i = 0; i < count; i++) {
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0) {
- printf("security: ebitmap: truncated map\n");
+ ERR(NULL, "security: ebitmap: truncated map");
goto bad;
}
n = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
if (!n) {
- printf("security: ebitmap: out of memory\n");
+ ERR(NULL, "security: ebitmap: out of memory");
rc = -ENOMEM;
goto bad;
}
@@ -416,34 +441,30 @@ int ebitmap_read(ebitmap_t * e, void *fp)
n->startbit = le32_to_cpu(buf[0]);
if (n->startbit & (MAPSIZE - 1)) {
- printf
- ("security: ebitmap start bit (%d) is not a multiple of the map size (%zu)\n",
+ ERR(NULL, "security: ebitmap start bit (%d) is not a multiple of the map size (%zu)",
n->startbit, MAPSIZE);
goto bad_free;
}
if (n->startbit > (e->highbit - MAPSIZE)) {
- printf
- ("security: ebitmap start bit (%d) is beyond the end of the bitmap (%zu)\n",
+ ERR(NULL, "security: ebitmap start bit (%d) is beyond the end of the bitmap (%zu)",
n->startbit, (e->highbit - MAPSIZE));
goto bad_free;
}
rc = next_entry(&map, fp, sizeof(uint64_t));
if (rc < 0) {
- printf("security: ebitmap: truncated map\n");
+ ERR(NULL, "security: ebitmap: truncated map");
goto bad_free;
}
n->map = le64_to_cpu(map);
if (!n->map) {
- printf
- ("security: ebitmap: null map in ebitmap (startbit %d)\n",
+ ERR(NULL, "security: ebitmap: null map in ebitmap (startbit %d)",
n->startbit);
goto bad_free;
}
if (l) {
if (n->startbit <= l->startbit) {
- printf
- ("security: ebitmap: start bit %d comes after start bit %d\n",
+ ERR(NULL, "security: ebitmap: start bit %d comes after start bit %d",
n->startbit, l->startbit);
goto bad_free;
}
@@ -454,8 +475,7 @@ int ebitmap_read(ebitmap_t * e, void *fp)
l = n;
}
if (count && l->startbit + MAPSIZE != e->highbit) {
- printf
- ("security: ebitmap: high bit %u has not the expected value %zu\n",
+ ERR(NULL, "security: ebitmap: high bit %u has not the expected value %zu",
e->highbit, l->startbit + MAPSIZE);
goto bad;
}
diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c
index 5738b598..7da51a40 100644
--- a/libsepol/src/expand.c
+++ b/libsepol/src/expand.c
@@ -71,6 +71,38 @@ static int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map)
return 0;
}
+static int ebitmap_expand_roles(policydb_t *p, ebitmap_t *roles)
+{
+ ebitmap_node_t *node;
+ unsigned int bit;
+ role_datum_t *role;
+ ebitmap_t tmp;
+
+ ebitmap_init(&tmp);
+ ebitmap_for_each_positive_bit(roles, node, bit) {
+ role = p->role_val_to_struct[bit];
+ assert(role);
+ if (role->flavor != ROLE_ATTRIB) {
+ if (ebitmap_set_bit(&tmp, bit, 1)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ } else {
+ if (ebitmap_union(&tmp, &role->roles)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ }
+ }
+ ebitmap_destroy(roles);
+ if (ebitmap_cpy(roles, &tmp)) {
+ ebitmap_destroy(&tmp);
+ return -1;
+ }
+ ebitmap_destroy(&tmp);
+ return 0;
+}
+
static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
void *data)
{
@@ -134,7 +166,7 @@ static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
if (new_type->flags & TYPE_FLAGS_PERMISSIVE)
if (ebitmap_set_bit(&state->out->permissive_map, new_type->s.value, 1)) {
- ERR(state->handle, "Out of memory!\n");
+ ERR(state->handle, "Out of memory!");
return -1;
}
@@ -211,7 +243,7 @@ static int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
new_perm->s.value = perm->s.value;
s->nprim++;
- ret = hashtab_insert(s->table, new_id, (hashtab_datum_t *) new_perm);
+ ret = hashtab_insert(s->table, new_id, (hashtab_datum_t) new_perm);
if (ret) {
free(new_id);
free(new_perm);
@@ -262,7 +294,7 @@ static int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
ret =
hashtab_insert(state->out->p_commons.table, new_id,
- (hashtab_datum_t *) new_common);
+ (hashtab_datum_t) new_common);
if (ret) {
ERR(state->handle, "hashtab overflow");
free(new_common);
@@ -333,6 +365,9 @@ static int constraint_node_clone(constraint_node_t ** dst,
if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) {
goto out_of_mem;
}
+ if (ebitmap_expand_roles(state->out, &new_expr->names)) {
+ goto out_of_mem;
+ }
} else if (new_expr->attr & CEXPR_USER) {
if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) {
goto out_of_mem;
@@ -457,7 +492,7 @@ static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
ret =
hashtab_insert(state->out->p_classes.table, new_id,
- (hashtab_datum_t *) new_class);
+ (hashtab_datum_t) new_class);
if (ret) {
ERR(state->handle, "hashtab overflow");
free(new_class);
@@ -894,11 +929,15 @@ int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l,
if (!sl->sens)
return 0;
+ /* Invalid sensitivity */
+ if (sl->sens > p->p_levels.nprim || !p->p_sens_val_to_name[sl->sens - 1])
+ return -1;
+
l->sens = sl->sens;
levdatum = (level_datum_t *) hashtab_search(p->p_levels.table,
p->p_sens_val_to_name[l->sens - 1]);
if (!levdatum) {
- ERR(h, "%s: Impossible situation found, nothing in p_levels.table.\n",
+ ERR(h, "%s: Impossible situation found, nothing in p_levels.table.",
__func__);
errno = ENOENT;
return -1;
@@ -1371,8 +1410,6 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
{
unsigned int i, j;
- filename_trans_t key, *new_trans;
- filename_trans_datum_t *otype;
filename_trans_rule_t *cur_rule;
ebitmap_t stypes, ttypes;
ebitmap_node_t *snode, *tnode;
@@ -1380,7 +1417,7 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
cur_rule = rules;
while (cur_rule) {
- uint32_t mapped_otype;
+ uint32_t mapped_otype, present_otype;
ebitmap_init(&stypes);
ebitmap_init(&ttypes);
@@ -1401,15 +1438,14 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
ebitmap_for_each_positive_bit(&stypes, snode, i) {
ebitmap_for_each_positive_bit(&ttypes, tnode, j) {
- key.stype = i + 1;
- key.ttype = j + 1;
- key.tclass = cur_rule->tclass;
- key.name = cur_rule->name;
- otype = hashtab_search(state->out->filename_trans,
- (hashtab_key_t) &key);
- if (otype) {
+ rc = policydb_filetrans_insert(
+ state->out, i + 1, j + 1,
+ cur_rule->tclass, cur_rule->name,
+ NULL, mapped_otype, &present_otype
+ );
+ if (rc == SEPOL_EEXIST) {
/* duplicate rule, ignore */
- if (otype->otype == mapped_otype)
+ if (present_otype == mapped_otype)
continue;
ERR(state->handle, "Conflicting name-based type_transition %s %s:%s \"%s\": %s vs %s",
@@ -1417,44 +1453,11 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
state->out->p_type_val_to_name[j],
state->out->p_class_val_to_name[cur_rule->tclass - 1],
cur_rule->name,
- state->out->p_type_val_to_name[otype->otype - 1],
+ state->out->p_type_val_to_name[present_otype - 1],
state->out->p_type_val_to_name[mapped_otype - 1]);
return -1;
- }
-
- new_trans = calloc(1, sizeof(*new_trans));
- if (!new_trans) {
- ERR(state->handle, "Out of memory!");
- return -1;
- }
-
- new_trans->name = strdup(cur_rule->name);
- if (!new_trans->name) {
- ERR(state->handle, "Out of memory!");
- free(new_trans);
- return -1;
- }
- new_trans->stype = i + 1;
- new_trans->ttype = j + 1;
- new_trans->tclass = cur_rule->tclass;
-
- otype = calloc(1, sizeof(*otype));
- if (!otype) {
+ } else if (rc < 0) {
ERR(state->handle, "Out of memory!");
- free(new_trans->name);
- free(new_trans);
- return -1;
- }
- otype->otype = mapped_otype;
-
- rc = hashtab_insert(state->out->filename_trans,
- (hashtab_key_t)new_trans,
- otype);
- if (rc) {
- ERR(state->handle, "Out of memory!");
- free(otype);
- free(new_trans->name);
- free(new_trans);
return -1;
}
}
@@ -1606,17 +1609,22 @@ static avtab_ptr_t find_avtab_node(sepol_handle_t * handle,
/* AVTAB_XPERMS entries are not necessarily unique */
if (key->specified & AVTAB_XPERMS) {
- node = avtab_search_node(avtab, key);
- while (node) {
- if ((node->datum.xperms->specified == xperms->specified) &&
- (node->datum.xperms->driver == xperms->driver)) {
- match = 1;
- break;
+ if (xperms == NULL) {
+ ERR(handle, "searching xperms NULL");
+ node = NULL;
+ } else {
+ node = avtab_search_node(avtab, key);
+ while (node) {
+ if ((node->datum.xperms->specified == xperms->specified) &&
+ (node->datum.xperms->driver == xperms->driver)) {
+ match = 1;
+ break;
+ }
+ node = avtab_search_node_next(node, key->specified);
}
- node = avtab_search_node_next(node, key->specified);
+ if (!match)
+ node = NULL;
}
- if (!match)
- node = NULL;
} else {
node = avtab_search_node(avtab, key);
}
@@ -1637,7 +1645,7 @@ static avtab_ptr_t find_avtab_node(sepol_handle_t * handle,
* AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for
* others. Initialize the data accordingly.
*/
- avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0 : 0;
+ avdatum.data = key->specified == AVTAB_AUDITDENY ? ~UINT32_C(0) : UINT32_C(0);
/* this is used to get the node - insertion is actually unique */
node = avtab_insert_nonunique(avtab, key, &avdatum);
if (!node) {
@@ -1686,7 +1694,7 @@ static int expand_terule_helper(sepol_handle_t * handle,
uint32_t oldtype = 0;
if (!(specified & (AVRULE_TRANSITION|AVRULE_MEMBER|AVRULE_CHANGE))) {
- ERR(handle, "Invalid specification: %"PRIu32"\n", specified);
+ ERR(handle, "Invalid specification: %"PRIu32, specified);
return EXPAND_RULE_ERROR;
}
@@ -1865,7 +1873,7 @@ static int expand_avrule_helper(sepol_handle_t * handle,
return EXPAND_RULE_ERROR;
break;
default:
- ERR(handle, "Unknown specification: %"PRIu32"\n", specified);
+ ERR(handle, "Unknown specification: %"PRIu32, specified);
return EXPAND_RULE_ERROR;
}
@@ -2473,7 +2481,7 @@ int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t
/* if role is to be complimented, invert the entire bitmap here */
if (x->flags & ROLE_COMP) {
- for (i = 0; i < ebitmap_length(r); i++) {
+ for (i = 0; i < p->p_roles.nprim; i++) {
if (ebitmap_get_bit(r, i)) {
if (ebitmap_set_bit(r, i, 0))
return -1;
@@ -2504,7 +2512,7 @@ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p,
unsigned int i;
ebitmap_t types, neg_types;
ebitmap_node_t *tnode;
- unsigned char expand = alwaysexpand || ebitmap_length(&set->negset) || set->flags;
+ unsigned char expand = alwaysexpand || !ebitmap_is_empty(&set->negset) || set->flags;
type_datum_t *type;
int rc =-1;
@@ -2962,6 +2970,9 @@ int expand_module(sepol_handle_t * handle,
state.out->policy_type = POLICY_KERN;
state.out->policyvers = POLICYDB_VERSION_MAX;
+ if (state.base->name) {
+ state.out->name = strdup(state.base->name);
+ }
/* Copy mls state from base to out */
out->mls = base->mls;
@@ -3048,10 +3059,6 @@ int expand_module(sepol_handle_t * handle,
if (hashtab_map(state.base->p_roles.table,
role_bounds_copy_callback, &state))
goto cleanup;
- /* escalate the type_set_t in a role attribute to all regular roles
- * that belongs to it. */
- if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
- goto cleanup;
/* copy MLS's sensitivity level and categories - this needs to be done
* before expanding users (they need to be indexed too) */
@@ -3117,6 +3124,11 @@ int expand_module(sepol_handle_t * handle,
goto cleanup;
}
+ /* escalate the type_set_t in a role attribute to all regular roles
+ * that belongs to it. */
+ if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state))
+ goto cleanup;
+
if (copy_and_expand_avrule_block(&state) < 0) {
ERR(handle, "Error during expand");
goto cleanup;
@@ -3141,9 +3153,9 @@ int expand_module(sepol_handle_t * handle,
goto cleanup;
/* Build the type<->attribute maps and remove attributes. */
- state.out->attr_type_map = malloc(state.out->p_types.nprim *
+ state.out->attr_type_map = mallocarray(state.out->p_types.nprim,
sizeof(ebitmap_t));
- state.out->type_attr_map = malloc(state.out->p_types.nprim *
+ state.out->type_attr_map = mallocarray(state.out->p_types.nprim,
sizeof(ebitmap_t));
if (!state.out->attr_type_map || !state.out->type_attr_map) {
ERR(handle, "Out of memory!");
@@ -3369,9 +3381,9 @@ static int expand_cond_insert(cond_av_list_t ** l,
return 0;
}
-int expand_cond_av_node(policydb_t * p,
- avtab_ptr_t node,
- cond_av_list_t ** newl, avtab_t * expa)
+static int expand_cond_av_node(policydb_t * p,
+ avtab_ptr_t node,
+ cond_av_list_t ** newl, avtab_t * expa)
{
avtab_key_t *k = &node->key;
avtab_datum_t *d = &node->datum;
diff --git a/libsepol/src/flask.h b/libsepol/src/flask.h
new file mode 100644
index 00000000..b4130bbc
--- /dev/null
+++ b/libsepol/src/flask.h
@@ -0,0 +1,38 @@
+/* This file is automatically generated. Do not edit. */
+#ifndef _SEPOL_POLICYDB_FLASK_H_
+#define _SEPOL_POLICYDB_FLASK_H_
+
+/*
+ * Security identifier indices for initial entities
+ */
+#define SECINITSID_KERNEL 1
+#define SECINITSID_SECURITY 2
+#define SECINITSID_UNLABELED 3
+#define SECINITSID_FS 4
+#define SECINITSID_FILE 5
+#define SECINITSID_FILE_LABELS 6
+#define SECINITSID_INIT 7
+#define SECINITSID_ANY_SOCKET 8
+#define SECINITSID_PORT 9
+#define SECINITSID_NETIF 10
+#define SECINITSID_NETMSG 11
+#define SECINITSID_NODE 12
+#define SECINITSID_IGMP_PACKET 13
+#define SECINITSID_ICMP_SOCKET 14
+#define SECINITSID_TCP_SOCKET 15
+#define SECINITSID_SYSCTL_MODPROBE 16
+#define SECINITSID_SYSCTL 17
+#define SECINITSID_SYSCTL_FS 18
+#define SECINITSID_SYSCTL_KERNEL 19
+#define SECINITSID_SYSCTL_NET 20
+#define SECINITSID_SYSCTL_NET_UNIX 21
+#define SECINITSID_SYSCTL_VM 22
+#define SECINITSID_SYSCTL_DEV 23
+#define SECINITSID_KMOD 24
+#define SECINITSID_POLICY 25
+#define SECINITSID_SCMP_PACKET 26
+#define SECINITSID_DEVNULL 27
+
+#define SECINITSID_NUM 27
+
+#endif
diff --git a/libsepol/src/hashtab.c b/libsepol/src/hashtab.c
index f5407ab6..3ecaf165 100644
--- a/libsepol/src/hashtab.c
+++ b/libsepol/src/hashtab.c
@@ -32,6 +32,8 @@
#include <string.h>
#include <sepol/policydb/hashtab.h>
+#include "private.h"
+
hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
const_hashtab_key_t key),
int (*keycmp) (hashtab_t h,
@@ -52,7 +54,7 @@ hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
p->nel = 0;
p->hash_value = hash_value;
p->keycmp = keycmp;
- p->htable = (hashtab_ptr_t *) malloc(sizeof(hashtab_ptr_t) * size);
+ p->htable = (hashtab_ptr_t *) mallocarray(size, sizeof(hashtab_ptr_t));
if (p->htable == NULL) {
free(p);
return NULL;
@@ -63,6 +65,45 @@ hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
return p;
}
+static void hashtab_check_resize(hashtab_t h)
+{
+ unsigned int hvalue, i, old_size, new_size = h->size;
+ hashtab_ptr_t *new_htable, *dst, cur, next;
+
+ while (new_size <= h->nel && new_size * 2 != 0)
+ new_size *= 2;
+
+ if (h->size == new_size)
+ return;
+
+ new_htable = calloc(new_size, sizeof(*new_htable));
+ if (!new_htable)
+ return;
+
+ old_size = h->size;
+ h->size = new_size;
+
+ /* Move all elements to the new htable */
+ for (i = 0; i < old_size; i++) {
+ cur = h->htable[i];
+ while (cur != NULL) {
+ hvalue = h->hash_value(h, cur->key);
+ dst = &new_htable[hvalue];
+ while (*dst && h->keycmp(h, cur->key, (*dst)->key) > 0)
+ dst = &(*dst)->next;
+
+ next = cur->next;
+
+ cur->next = *dst;
+ *dst = cur;
+
+ cur = next;
+ }
+ }
+ free(h->htable);
+ h->htable = new_htable;
+}
+
int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
{
int hvalue;
@@ -71,6 +112,8 @@ int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
if (!h)
return SEPOL_ENOMEM;
+ hashtab_check_resize(h);
+
hvalue = h->hash_value(h, key);
prev = NULL;
cur = h->htable[hvalue];
@@ -133,48 +176,6 @@ int hashtab_remove(hashtab_t h, hashtab_key_t key,
return SEPOL_OK;
}
-int hashtab_replace(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum,
- void (*destroy) (hashtab_key_t k,
- hashtab_datum_t d, void *args), void *args)
-{
- int hvalue;
- hashtab_ptr_t prev, cur, newnode;
-
- if (!h)
- return SEPOL_ENOMEM;
-
- hvalue = h->hash_value(h, key);
- prev = NULL;
- cur = h->htable[hvalue];
- while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
- prev = cur;
- cur = cur->next;
- }
-
- if (cur && (h->keycmp(h, key, cur->key) == 0)) {
- if (destroy)
- destroy(cur->key, cur->datum, args);
- cur->key = key;
- cur->datum = datum;
- } else {
- newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
- if (newnode == NULL)
- return SEPOL_ENOMEM;
- memset(newnode, 0, sizeof(struct hashtab_node));
- newnode->key = key;
- newnode->datum = datum;
- if (prev) {
- newnode->next = prev->next;
- prev->next = newnode;
- } else {
- newnode->next = h->htable[hvalue];
- h->htable[hvalue] = newnode;
- }
- }
-
- return SEPOL_OK;
-}
-
hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key)
{
@@ -223,8 +224,9 @@ int hashtab_map(hashtab_t h,
int (*apply) (hashtab_key_t k,
hashtab_datum_t d, void *args), void *args)
{
- unsigned int i, ret;
+ unsigned int i;
hashtab_ptr_t cur;
+ int ret;
if (!h)
return SEPOL_OK;
@@ -241,49 +243,6 @@ int hashtab_map(hashtab_t h,
return SEPOL_OK;
}
-void hashtab_map_remove_on_error(hashtab_t h,
- int (*apply) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args),
- void (*destroy) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args), void *args)
-{
- unsigned int i;
- int ret;
- hashtab_ptr_t last, cur, temp;
-
- if (!h)
- return;
-
- for (i = 0; i < h->size; i++) {
- last = NULL;
- cur = h->htable[i];
- while (cur != NULL) {
- ret = apply(cur->key, cur->datum, args);
- if (ret) {
- if (last) {
- last->next = cur->next;
- } else {
- h->htable[i] = cur->next;
- }
-
- temp = cur;
- cur = cur->next;
- if (destroy)
- destroy(temp->key, temp->datum, args);
- free(temp);
- h->nel--;
- } else {
- last = cur;
- cur = cur->next;
- }
- }
- }
-
- return;
-}
-
void hashtab_hash_eval(hashtab_t h, char *tag)
{
unsigned int i;
diff --git a/libsepol/src/hierarchy.c b/libsepol/src/hierarchy.c
index 8919daa7..350443a8 100644
--- a/libsepol/src/hierarchy.c
+++ b/libsepol/src/hierarchy.c
@@ -237,7 +237,7 @@ oom:
ERR(handle, "Insufficient memory");
exit:
- ERR(handle,"Failed to expand parent rules\n");
+ ERR(handle,"Failed to expand parent rules");
avtab_destroy(global_avtab);
bounds_destroy_cond_info(*cond_info);
*cond_info = NULL;
diff --git a/libsepol/src/ibendport_internal.h b/libsepol/src/ibendport_internal.h
index ed8f9b4d..8bfb499e 100644
--- a/libsepol/src/ibendport_internal.h
+++ b/libsepol/src/ibendport_internal.h
@@ -3,16 +3,5 @@
#include <sepol/ibendport_record.h>
#include <sepol/ibendports.h>
-#include "dso.h"
-hidden_proto(sepol_ibendport_create)
-hidden_proto(sepol_ibendport_free)
-hidden_proto(sepol_ibendport_get_con)
-hidden_proto(sepol_ibendport_get_port)
-hidden_proto(sepol_ibendport_key_create)
-hidden_proto(sepol_ibendport_key_unpack)
-hidden_proto(sepol_ibendport_set_con)
-hidden_proto(sepol_ibendport_set_port)
-hidden_proto(sepol_ibendport_get_ibdev_name)
-hidden_proto(sepol_ibendport_set_ibdev_name)
#endif
diff --git a/libsepol/src/ibendport_record.c b/libsepol/src/ibendport_record.c
index bc56f090..1eb50914 100644
--- a/libsepol/src/ibendport_record.c
+++ b/libsepol/src/ibendport_record.c
@@ -62,7 +62,7 @@ int sepol_ibendport_key_create(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_key->ibdev_name) < 0)
goto err;
- strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1);
tmp_key->port = port;
*key_ptr = tmp_key;
@@ -78,7 +78,6 @@ err:
return STATUS_ERR;
}
-hidden_def(sepol_ibendport_key_create)
void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key,
const char **ibdev_name, int *port)
@@ -87,7 +86,6 @@ void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key,
*port = key->port;
}
-hidden_def(sepol_ibendport_key_unpack)
int sepol_ibendport_key_extract(sepol_handle_t *handle,
const sepol_ibendport_t *ibendport,
@@ -152,14 +150,12 @@ int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport)
return ibendport->port;
}
-hidden_def(sepol_ibendport_get_port)
void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port)
{
ibendport->port = port;
}
-hidden_def(sepol_ibendport_set_port)
int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle,
const sepol_ibendport_t *ibendport,
@@ -170,7 +166,7 @@ int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0)
goto err;
- strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1);
*ibdev_name = tmp_ibdev_name;
return STATUS_SUCCESS;
@@ -180,7 +176,6 @@ err:
return STATUS_ERR;
}
-hidden_def(sepol_ibendport_get_ibdev_name)
int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle,
sepol_ibendport_t *ibendport,
@@ -191,7 +186,7 @@ int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0)
goto err;
- strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX - 1);
free(ibendport->ibdev_name);
ibendport->ibdev_name = tmp;
return STATUS_SUCCESS;
@@ -202,7 +197,6 @@ err:
return STATUS_ERR;
}
-hidden_def(sepol_ibendport_set_ibdev_name)
/* Create */
int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport)
@@ -222,7 +216,6 @@ int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport
return STATUS_SUCCESS;
}
-hidden_def(sepol_ibendport_create)
/* Deep copy clone */
int sepol_ibendport_clone(sepol_handle_t *handle,
@@ -237,7 +230,7 @@ int sepol_ibendport_clone(sepol_handle_t *handle,
if (sepol_ibendport_alloc_ibdev_name(handle, &new_ibendport->ibdev_name) < 0)
goto omem;
- strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1);
new_ibendport->port = ibendport->port;
if (ibendport->con &&
@@ -267,7 +260,6 @@ void sepol_ibendport_free(sepol_ibendport_t *ibendport)
free(ibendport);
}
-hidden_def(sepol_ibendport_free)
/* Context */
sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport)
@@ -275,7 +267,6 @@ sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport)
return ibendport->con;
}
-hidden_def(sepol_ibendport_get_con)
int sepol_ibendport_set_con(sepol_handle_t *handle,
sepol_ibendport_t *ibendport, sepol_context_t *con)
@@ -292,4 +283,3 @@ int sepol_ibendport_set_con(sepol_handle_t *handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_ibendport_set_con)
diff --git a/libsepol/src/ibendports.c b/libsepol/src/ibendports.c
index 6d56c9a1..ee5cb193 100644
--- a/libsepol/src/ibendports.c
+++ b/libsepol/src/ibendports.c
@@ -34,7 +34,7 @@ static int ibendport_from_record(sepol_handle_t *handle,
&ibdev_name) < 0)
goto err;
- strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX);
+ strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1);
free(ibdev_name);
ibdev_name = NULL;
diff --git a/libsepol/src/ibpkey_internal.h b/libsepol/src/ibpkey_internal.h
index addf80a8..b875f942 100644
--- a/libsepol/src/ibpkey_internal.h
+++ b/libsepol/src/ibpkey_internal.h
@@ -3,19 +3,5 @@
#include <sepol/ibpkey_record.h>
#include <sepol/ibpkeys.h>
-#include "dso.h"
-hidden_proto(sepol_ibpkey_create)
-hidden_proto(sepol_ibpkey_free)
-hidden_proto(sepol_ibpkey_get_con)
-hidden_proto(sepol_ibpkey_get_high)
-hidden_proto(sepol_ibpkey_get_low)
-hidden_proto(sepol_ibpkey_key_create)
-hidden_proto(sepol_ibpkey_key_unpack)
-hidden_proto(sepol_ibpkey_set_con)
-hidden_proto(sepol_ibpkey_set_range)
-hidden_proto(sepol_ibpkey_get_subnet_prefix)
-hidden_proto(sepol_ibpkey_get_subnet_prefix_bytes)
-hidden_proto(sepol_ibpkey_set_subnet_prefix)
-hidden_proto(sepol_ibpkey_set_subnet_prefix_bytes)
#endif
diff --git a/libsepol/src/ibpkey_record.c b/libsepol/src/ibpkey_record.c
index badf2b3b..d95e95fe 100644
--- a/libsepol/src/ibpkey_record.c
+++ b/libsepol/src/ibpkey_record.c
@@ -38,8 +38,8 @@ static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle,
struct in6_addr in_addr;
if (inet_pton(AF_INET6, subnet_prefix_str, &in_addr) <= 0) {
- ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %s",
- subnet_prefix_str, strerror(errno));
+ ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %m",
+ subnet_prefix_str);
return STATUS_ERR;
}
@@ -64,8 +64,7 @@ static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle,
if (inet_ntop(AF_INET6, &addr, subnet_prefix_str,
INET6_ADDRSTRLEN) == NULL) {
ERR(handle,
- "could not expand IPv6 address to string: %s",
- strerror(errno));
+ "could not expand IPv6 address to string: %m");
return STATUS_ERR;
}
@@ -128,7 +127,6 @@ err:
return STATUS_ERR;
}
-hidden_def(sepol_ibpkey_key_create)
void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key,
uint64_t *subnet_prefix, int *low, int *high)
@@ -138,7 +136,6 @@ void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key,
*high = key->high;
}
-hidden_def(sepol_ibpkey_key_unpack)
int sepol_ibpkey_key_extract(sepol_handle_t *handle,
const sepol_ibpkey_t *ibpkey,
@@ -213,14 +210,12 @@ int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey)
return ibpkey->low;
}
-hidden_def(sepol_ibpkey_get_low)
int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey)
{
return ibpkey->high;
}
-hidden_def(sepol_ibpkey_get_high)
void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num)
{
@@ -234,7 +229,6 @@ void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high)
ibpkey->high = high;
}
-hidden_def(sepol_ibpkey_set_range)
int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle,
const sepol_ibpkey_t *ibpkey,
@@ -257,7 +251,6 @@ err:
return STATUS_ERR;
}
-hidden_def(sepol_ibpkey_get_subnet_prefix)
/* Subnet prefix */
uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey)
@@ -265,7 +258,6 @@ uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey)
return ibpkey->subnet_prefix;
}
-hidden_def(sepol_ibpkey_get_subnet_prefix_bytes)
int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
sepol_ibpkey_t *ibpkey,
@@ -284,7 +276,6 @@ err:
return STATUS_ERR;
}
-hidden_def(sepol_ibpkey_set_subnet_prefix)
void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey,
uint64_t subnet_prefix)
@@ -292,7 +283,6 @@ void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey,
ibpkey->subnet_prefix = subnet_prefix;
}
-hidden_def(sepol_ibpkey_set_subnet_prefix_bytes)
/* Create */
int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey)
@@ -313,7 +303,6 @@ int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey)
return STATUS_SUCCESS;
}
-hidden_def(sepol_ibpkey_create)
/* Deep copy clone */
int sepol_ibpkey_clone(sepol_handle_t *handle,
@@ -351,7 +340,6 @@ void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey)
free(ibpkey);
}
-hidden_def(sepol_ibpkey_free)
/* Context */
sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey)
@@ -359,7 +347,6 @@ sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey)
return ibpkey->con;
}
-hidden_def(sepol_ibpkey_get_con)
int sepol_ibpkey_set_con(sepol_handle_t *handle,
sepol_ibpkey_t *ibpkey, sepol_context_t *con)
@@ -376,4 +363,3 @@ int sepol_ibpkey_set_con(sepol_handle_t *handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_ibpkey_set_con)
diff --git a/libsepol/src/iface_internal.h b/libsepol/src/iface_internal.h
index 5b78d9bd..82fb60cb 100644
--- a/libsepol/src/iface_internal.h
+++ b/libsepol/src/iface_internal.h
@@ -3,16 +3,5 @@
#include <sepol/iface_record.h>
#include <sepol/interfaces.h>
-#include "dso.h"
-hidden_proto(sepol_iface_create)
- hidden_proto(sepol_iface_free)
- hidden_proto(sepol_iface_get_ifcon)
- hidden_proto(sepol_iface_get_msgcon)
- hidden_proto(sepol_iface_get_name)
- hidden_proto(sepol_iface_key_create)
- hidden_proto(sepol_iface_key_unpack)
- hidden_proto(sepol_iface_set_ifcon)
- hidden_proto(sepol_iface_set_msgcon)
- hidden_proto(sepol_iface_set_name)
#endif
diff --git a/libsepol/src/iface_record.c b/libsepol/src/iface_record.c
index 6d568355..e7756989 100644
--- a/libsepol/src/iface_record.c
+++ b/libsepol/src/iface_record.c
@@ -47,7 +47,6 @@ int sepol_iface_key_create(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_iface_key_create)
void sepol_iface_key_unpack(const sepol_iface_key_t * key, const char **name)
{
@@ -55,7 +54,6 @@ void sepol_iface_key_unpack(const sepol_iface_key_t * key, const char **name)
*name = key->name;
}
-hidden_def(sepol_iface_key_unpack)
int sepol_iface_key_extract(sepol_handle_t * handle,
const sepol_iface_t * iface,
@@ -114,7 +112,6 @@ int sepol_iface_create(sepol_handle_t * handle, sepol_iface_t ** iface)
return STATUS_SUCCESS;
}
-hidden_def(sepol_iface_create)
/* Name */
const char *sepol_iface_get_name(const sepol_iface_t * iface)
@@ -123,7 +120,6 @@ const char *sepol_iface_get_name(const sepol_iface_t * iface)
return iface->name;
}
-hidden_def(sepol_iface_get_name)
int sepol_iface_set_name(sepol_handle_t * handle,
sepol_iface_t * iface, const char *name)
@@ -139,7 +135,6 @@ int sepol_iface_set_name(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_iface_set_name)
/* Interface Context */
sepol_context_t *sepol_iface_get_ifcon(const sepol_iface_t * iface)
@@ -148,7 +143,6 @@ sepol_context_t *sepol_iface_get_ifcon(const sepol_iface_t * iface)
return iface->netif_con;
}
-hidden_def(sepol_iface_get_ifcon)
int sepol_iface_set_ifcon(sepol_handle_t * handle,
sepol_iface_t * iface, sepol_context_t * con)
@@ -166,7 +160,6 @@ int sepol_iface_set_ifcon(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_iface_set_ifcon)
/* Message Context */
sepol_context_t *sepol_iface_get_msgcon(const sepol_iface_t * iface)
@@ -175,7 +168,6 @@ sepol_context_t *sepol_iface_get_msgcon(const sepol_iface_t * iface)
return iface->netmsg_con;
}
-hidden_def(sepol_iface_get_msgcon)
int sepol_iface_set_msgcon(sepol_handle_t * handle,
sepol_iface_t * iface, sepol_context_t * con)
@@ -192,7 +184,6 @@ int sepol_iface_set_msgcon(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_iface_set_msgcon)
/* Deep copy clone */
int sepol_iface_clone(sepol_handle_t * handle,
@@ -238,4 +229,3 @@ void sepol_iface_free(sepol_iface_t * iface)
free(iface);
}
-hidden_def(sepol_iface_free)
diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
index ca2e4a9b..869f6940 100644
--- a/libsepol/src/kernel_to_cil.c
+++ b/libsepol/src/kernel_to_cil.c
@@ -16,9 +16,9 @@
#define IPPROTO_SCTP 132
#endif
+#include <sepol/kernel_to_cil.h>
#include <sepol/policydb/avtab.h>
#include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/hashtab.h>
#include <sepol/policydb/polcaps.h>
#include <sepol/policydb/policydb.h>
@@ -189,9 +189,13 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr
names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
}
if (!names) {
- goto exit;
+ names = strdup("NO_IDENTIFIER");
+ }
+ if (strchr(names, ' ')) {
+ new_val = create_str("(%s %s (%s))", 3, op, attr1, names);
+ } else {
+ new_val = create_str("(%s %s %s)", 3, op, attr1, names);
}
- new_val = create_str("(%s %s %s)", 3, op, attr1, names);
free(names);
}
} else {
@@ -274,10 +278,13 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey,
char *expr = NULL;
int is_mls;
char *perms;
- const char *format_str;
+ const char *key_word;
struct strs *strs;
for (curr = constraint_rules; curr != NULL; curr = curr->next) {
+ if (curr->permissions == 0) {
+ continue;
+ }
expr = constraint_expr_to_str(pdb, curr->expr, &is_mls);
if (!expr) {
rc = -1;
@@ -287,14 +294,14 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey,
perms = sepol_av_to_string(pdb, class->s.value, curr->permissions);
if (is_mls) {
- format_str = "(mlsconstrain (%s (%s)) %s)";
+ key_word = "mlsconstrain";
strs = mls_list;
} else {
- format_str = "(constrain (%s (%s)) %s)";
+ key_word = "constrain";
strs = non_mls_list;
}
- rc = strs_create_and_add(strs, format_str, 3, classkey, perms+1, expr);
+ rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", 4, key_word, classkey, perms+1, expr);
free(expr);
if (rc != 0) {
goto exit;
@@ -315,7 +322,7 @@ static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classke
struct constraint_node *curr;
char *expr = NULL;
int is_mls;
- const char *format_str;
+ const char *key_word;
struct strs *strs;
int rc = 0;
@@ -327,14 +334,14 @@ static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classke
}
if (is_mls) {
- format_str = "(mlsvalidatetrans %s %s)";
+ key_word = "mlsvalidatetrans";
strs = mls_list;
} else {
- format_str = "(validatetrans %s %s)";
+ key_word = "validatetrans";
strs = non_mls_list;
}
- rc = strs_create_and_add(strs, format_str, 2, classkey, expr);
+ rc = strs_create_and_add(strs, "(%s %s %s)", 3, key_word, classkey, expr);
free(expr);
if (rc != 0) {
goto exit;
@@ -354,6 +361,7 @@ static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs,
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->constraints) {
name = pdb->p_class_val_to_name[i];
rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs);
@@ -379,6 +387,7 @@ static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_st
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->validatetrans) {
name = pdb->p_class_val_to_name[i];
rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs);
@@ -457,6 +466,7 @@ static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb)
/* class */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
name = pdb->p_class_val_to_name[i];
perms = class_or_common_perms_to_str(&class->permissions);
if (perms) {
@@ -484,6 +494,7 @@ static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb)
/* classcommon */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
name = pdb->p_class_val_to_name[i];
if (class->comkey != NULL) {
sepol_printf(out, "(classcommon %s %s)\n", name, class->comkey);
@@ -499,6 +510,7 @@ static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb)
}
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
name = class->comkey;
if (name != NULL) {
common = hashtab_search(pdb->p_commons.table, name);
@@ -723,6 +735,7 @@ static int write_default_rules_to_cil(FILE *out, struct policydb *pdb)
/* default_user */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->default_user != 0) {
rc = write_default_user_to_cil(out, pdb->p_class_val_to_name[i], class);
if (rc != 0) {
@@ -734,6 +747,7 @@ static int write_default_rules_to_cil(FILE *out, struct policydb *pdb)
/* default_role */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->default_role != 0) {
rc = write_default_role_to_cil(out, pdb->p_class_val_to_name[i], class);
if (rc != 0) {
@@ -745,6 +759,7 @@ static int write_default_rules_to_cil(FILE *out, struct policydb *pdb)
/* default_type */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->default_type != 0) {
rc = write_default_type_to_cil(out, pdb->p_class_val_to_name[i], class);
if (rc != 0) {
@@ -760,6 +775,7 @@ static int write_default_rules_to_cil(FILE *out, struct policydb *pdb)
/* default_range */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->default_range) {
rc = write_default_range_to_cil(out, pdb->p_class_val_to_name[i], class);
if (rc != 0) {
@@ -778,9 +794,20 @@ exit:
static void write_default_mls_level(FILE *out)
{
- sepol_printf(out, "(sensitivity s0)");
- sepol_printf(out, "(sensitivityorder (s0))");
- sepol_printf(out, "(level %s (s0))", DEFAULT_LEVEL);
+ sepol_printf(out, "(sensitivity s0)\n");
+ sepol_printf(out, "(sensitivityorder (s0))\n");
+ sepol_printf(out, "(level %s (s0))\n", DEFAULT_LEVEL);
+}
+
+static int map_count_sensitivity_aliases(__attribute__((unused)) char *key, void *data, void *args)
+{
+ level_datum_t *sens = data;
+ unsigned *count = args;
+
+ if (sens->isalias)
+ (*count)++;
+
+ return SEPOL_OK;
}
static int map_sensitivity_aliases_to_strs(char *key, void *data, void *args)
@@ -800,26 +827,13 @@ static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb)
{
level_datum_t *level;
char *prev, *name, *actual;
- struct strs *strs;
- unsigned i, num;
+ struct strs *strs = NULL;
+ unsigned i, num = 0;
int rc = 0;
- rc = strs_init(&strs, pdb->p_levels.nprim);
- if (rc != 0) {
- goto exit;
- }
-
/* sensitivities */
for (i=0; i < pdb->p_levels.nprim; i++) {
name = pdb->p_sens_val_to_name[i];
- if (!name) continue;
- level = hashtab_search(pdb->p_levels.table, name);
- if (!level) {
- rc = -1;
- goto exit;
- }
- if (level->isalias) continue;
-
sepol_printf(out, "(sensitivity %s)\n", name);
}
@@ -828,14 +842,6 @@ static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb)
prev = NULL;
for (i=0; i < pdb->p_levels.nprim; i++) {
name = pdb->p_sens_val_to_name[i];
- if (!name) continue;
- level = hashtab_search(pdb->p_levels.table, name);
- if (!level) {
- rc = -1;
- goto exit;
- }
- if (level->isalias) continue;
-
if (prev) {
sepol_printf(out, "%s ", prev);
}
@@ -846,6 +852,22 @@ static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb)
}
sepol_printf(out, "))\n");
+ rc = hashtab_map(pdb->p_levels.table, map_count_sensitivity_aliases, &num);
+ if (rc != 0) {
+ goto exit;
+ }
+
+ if (num == 0) {
+ /* No aliases, so skip sensitivity alias rules */
+ rc = 0;
+ goto exit;
+ }
+
+ rc = strs_init(&strs, num);
+ if (rc != 0) {
+ goto exit;
+ }
+
rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs);
if (rc != 0) {
goto exit;
@@ -853,16 +875,9 @@ static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb)
strs_sort(strs);
- num = strs_num_items(strs);
-
/* sensitivity aliases */
for (i=0; i < num; i++) {
name = strs_read_at_index(strs, i);
- level = hashtab_search(pdb->p_levels.table, name);
- if (!level) {
- rc = -1;
- goto exit;
- }
sepol_printf(out, "(sensitivityalias %s)\n", name);
}
@@ -888,6 +903,17 @@ exit:
return rc;
}
+static int map_count_category_aliases(__attribute__((unused)) char *key, void *data, void *args)
+{
+ cat_datum_t *cat = data;
+ unsigned *count = args;
+
+ if (cat->isalias)
+ (*count)++;
+
+ return SEPOL_OK;
+}
+
static int map_category_aliases_to_strs(char *key, void *data, void *args)
{
cat_datum_t *cat = data;
@@ -905,26 +931,13 @@ static int write_category_rules_to_cil(FILE *out, struct policydb *pdb)
{
cat_datum_t *cat;
char *prev, *name, *actual;
- struct strs *strs;
- unsigned i, num;
+ struct strs *strs = NULL;
+ unsigned i, num = 0;
int rc = 0;
- rc = strs_init(&strs, pdb->p_levels.nprim);
- if (rc != 0) {
- goto exit;
- }
-
/* categories */
for (i=0; i < pdb->p_cats.nprim; i++) {
name = pdb->p_cat_val_to_name[i];
- if (!name) continue;
- cat = hashtab_search(pdb->p_cats.table, name);
- if (!cat) {
- rc = -1;
- goto exit;
- }
- if (cat->isalias) continue;
-
sepol_printf(out, "(category %s)\n", name);
}
@@ -933,14 +946,6 @@ static int write_category_rules_to_cil(FILE *out, struct policydb *pdb)
prev = NULL;
for (i=0; i < pdb->p_cats.nprim; i++) {
name = pdb->p_cat_val_to_name[i];
- if (!name) continue;
- cat = hashtab_search(pdb->p_cats.table, name);
- if (!cat) {
- rc = -1;
- goto exit;
- }
- if (cat->isalias) continue;
-
if (prev) {
sepol_printf(out, "%s ", prev);
}
@@ -951,6 +956,22 @@ static int write_category_rules_to_cil(FILE *out, struct policydb *pdb)
}
sepol_printf(out, "))\n");
+ rc = hashtab_map(pdb->p_cats.table, map_count_category_aliases, &num);
+ if (rc != 0) {
+ goto exit;
+ }
+
+ if (num == 0) {
+ /* No aliases, so skip category alias rules */
+ rc = 0;
+ goto exit;
+ }
+
+ rc = strs_init(&strs, num);
+ if (rc != 0) {
+ goto exit;
+ }
+
rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs);
if (rc != 0) {
goto exit;
@@ -958,16 +979,9 @@ static int write_category_rules_to_cil(FILE *out, struct policydb *pdb)
strs_sort(strs);
- num = strs_num_items(strs);
-
/* category aliases */
for (i=0; i < num; i++) {
name = strs_read_at_index(strs, i);
- cat = hashtab_search(pdb->p_cats.table, name);
- if (!cat) {
- rc = -1;
- goto exit;
- }
sepol_printf(out, "(categoryalias %s)\n", name);
}
@@ -1032,11 +1046,13 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
{
struct ebitmap_node *node;
uint32_t i, start, range;
- char *catsbuf, *p;
- const char *fmt;
+ char *catsbuf = NULL, *p;
int len, remaining;
remaining = (int)cats_ebitmap_len(cats, val_to_name);
+ if (remaining == 0) {
+ goto exit;
+ }
catsbuf = malloc(remaining);
if (!catsbuf) {
goto exit;
@@ -1045,7 +1061,7 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
p = catsbuf;
*p++ = '(';
- remaining--;;
+ remaining--;
range = 0;
ebitmap_for_each_positive_bit(cats, node, i) {
@@ -1058,9 +1074,15 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
continue;
if (range > 1) {
- fmt = (range == 2) ? "%s %s " : "(range %s %s) ";
- len = snprintf(p, remaining, fmt,
- val_to_name[start], val_to_name[i]);
+ if (range == 2) {
+ len = snprintf(p, remaining, "%s %s ",
+ val_to_name[start],
+ val_to_name[i]);
+ } else {
+ len = snprintf(p, remaining, "(range %s %s) ",
+ val_to_name[start],
+ val_to_name[i]);
+ }
} else {
len = snprintf(p, remaining, "%s ", val_to_name[start]);
}
@@ -1101,7 +1123,7 @@ static int write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pd
}
if (level->isalias) continue;
- if (ebitmap_cardinality(&level->level->cat) > 0) {
+ if (!ebitmap_is_empty(&level->level->cat)) {
cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name);
sepol_printf(out, "(sensitivitycategory %s %s)\n", name, cats);
free(cats);
@@ -1208,7 +1230,7 @@ static int write_type_attributes_to_cil(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
type = pdb->type_val_to_struct[i];
- if (type->flavor == TYPE_ATTRIB) {
+ if (type && type->flavor == TYPE_ATTRIB) {
rc = strs_add(strs, pdb->p_type_val_to_name[i]);
if (rc != 0) {
goto exit;
@@ -1338,7 +1360,7 @@ static int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
type = pdb->type_val_to_struct[i];
- if (type->flavor == TYPE_TYPE && type->primary) {
+ if (type && type->flavor == TYPE_TYPE && type->primary) {
rc = strs_add(strs, pdb->p_type_val_to_name[i]);
if (rc != 0) {
goto exit;
@@ -1368,33 +1390,55 @@ exit:
return rc;
}
+static int map_count_type_aliases(__attribute__((unused)) char *key, void *data, void *args)
+{
+ type_datum_t *datum = data;
+ unsigned *count = args;
+
+ if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
+ (*count)++;
+
+ return SEPOL_OK;
+}
+
+static int map_type_aliases_to_strs(char *key, void *data, void *args)
+{
+ type_datum_t *datum = data;
+ struct strs *strs = args;
+ int rc = 0;
+
+ if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
+ rc = strs_add(strs, key);
+
+ return rc;
+}
+
static int write_type_alias_rules_to_cil(FILE *out, struct policydb *pdb)
{
type_datum_t *alias;
struct strs *strs;
char *name;
char *type;
- unsigned i, num;
+ unsigned i, num = 0;
int rc = 0;
- rc = strs_init(&strs, pdb->p_types.nprim);
+ rc = hashtab_map(pdb->p_types.table, map_count_type_aliases, &num);
if (rc != 0) {
goto exit;
}
- for (i=0; i < pdb->p_types.nprim; i++) {
- alias = pdb->type_val_to_struct[i];
- if (!alias->primary) {
- rc = strs_add(strs, pdb->p_type_val_to_name[i]);
- if (rc != 0) {
- goto exit;
- }
- }
+ rc = strs_init(&strs, num);
+ if (rc != 0) {
+ goto exit;
+ }
+
+ rc = hashtab_map(pdb->p_types.table, map_type_aliases_to_strs, strs);
+ if (rc != 0) {
+ goto exit;
}
strs_sort(strs);
- num = strs_num_items(strs);
for (i=0; i<num; i++) {
name = strs_read_at_index(strs, i);
if (!name) {
@@ -1445,7 +1489,7 @@ static int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
type = pdb->type_val_to_struct[i];
- if (type->flavor == TYPE_TYPE) {
+ if (type && type->flavor == TYPE_TYPE) {
if (type->bounds > 0) {
rc = strs_add(strs, pdb->p_type_val_to_name[i]);
if (rc != 0) {
@@ -1499,10 +1543,10 @@ static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
attr = pdb->type_val_to_struct[i];
- if (attr->flavor != TYPE_ATTRIB) continue;
+ if (!attr || attr->flavor != TYPE_ATTRIB) continue;
name = pdb->p_type_val_to_name[i];
typemap = &pdb->attr_type_map[i];
- if (ebitmap_cardinality(typemap) == 0) continue;
+ if (ebitmap_is_empty(typemap)) continue;
types = ebitmap_to_str(typemap, pdb->p_type_val_to_name, 1);
if (!types) {
rc = -1;
@@ -1822,21 +1866,35 @@ struct map_filename_trans_args {
static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg)
{
- filename_trans_t *ft = (filename_trans_t *)key;
+ filename_trans_key_t *ft = (filename_trans_key_t *)key;
filename_trans_datum_t *datum = data;
struct map_filename_trans_args *map_args = arg;
struct policydb *pdb = map_args->pdb;
struct strs *strs = map_args->strs;
char *src, *tgt, *class, *filename, *new;
+ struct ebitmap_node *node;
+ uint32_t bit;
+ int rc;
- src = pdb->p_type_val_to_name[ft->stype - 1];
tgt = pdb->p_type_val_to_name[ft->ttype - 1];
class = pdb->p_class_val_to_name[ft->tclass - 1];
filename = ft->name;
- new = pdb->p_type_val_to_name[datum->otype - 1];
+ do {
+ new = pdb->p_type_val_to_name[datum->otype - 1];
- return strs_create_and_add(strs, "(typetransition %s %s %s %s %s)", 5,
- src, tgt, class, filename, new);
+ ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
+ src = pdb->p_type_val_to_name[bit];
+ rc = strs_create_and_add(strs,
+ "(typetransition %s %s %s %s %s)",
+ 5, src, tgt, class, filename, new);
+ if (rc)
+ return rc;
+ }
+
+ datum = datum->next;
+ } while (datum);
+
+ return 0;
}
static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb)
@@ -1879,7 +1937,7 @@ static char *level_to_str(struct policydb *pdb, struct mls_level *level)
char *sens_str = pdb->p_sens_val_to_name[level->sens - 1];
char *cats_str;
- if (ebitmap_cardinality(cats) > 0) {
+ if (!ebitmap_is_empty(cats)) {
cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name);
level_str = create_str("(%s %s)", 2, sens_str, cats_str);
free(cats_str);
@@ -2188,7 +2246,7 @@ static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
types = &role->types.types;
- if (types && (ebitmap_cardinality(types) > 0)) {
+ if (types && !ebitmap_is_empty(types)) {
rc = strs_init(&type_strs, pdb->p_types.nprim);
if (rc != 0) {
goto exit;
@@ -2218,7 +2276,7 @@ static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
type_datum = pdb->type_val_to_struct[i];
- if (type_datum->flavor == TYPE_TYPE && type_datum->primary) {
+ if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) {
rc = strs_add(strs, pdb->p_type_val_to_name[i]);
if (rc != 0) {
goto exit;
@@ -2342,6 +2400,7 @@ static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
}
for (i=0; i < pdb->p_users.nprim; i++) {
+ if (!pdb->p_user_val_to_name[i]) continue;
rc = strs_add(strs, pdb->p_user_val_to_name[i]);
if (rc != 0) {
goto exit;
@@ -2373,7 +2432,7 @@ static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
}
roles = &user->roles.roles;
- if (roles && (ebitmap_cardinality(roles) > 0)) {
+ if (roles && !ebitmap_is_empty(roles)) {
rc = strs_init(&role_strs, pdb->p_roles.nprim);
if (rc != 0) {
goto exit;
@@ -2456,9 +2515,10 @@ static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
sepol_printf(out, ")\n");
}
- strs_destroy(&strs);
-
exit:
+ if (strs)
+ strs_destroy(&strs);
+
if (rc != 0) {
sepol_log_err("Error writing user declarations to CIL\n");
}
@@ -2598,6 +2658,8 @@ static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
struct ocontext *ocon;
struct strs *strs;
char *fstype, *name, *ctx;
+ uint32_t sclass;
+ const char *file_type;
int rc;
rc = strs_init(&strs, 32);
@@ -2610,14 +2672,43 @@ static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
fstype = genfs->fstype;
name = ocon->u.name;
+ sclass = ocon->v.sclass;
+ file_type = NULL;
+ if (sclass) {
+ const char *class_name = pdb->p_class_val_to_name[sclass-1];
+ if (strcmp(class_name, "file") == 0) {
+ file_type = "file";
+ } else if (strcmp(class_name, "dir") == 0) {
+ file_type = "dir";
+ } else if (strcmp(class_name, "chr_file") == 0) {
+ file_type = "char";
+ } else if (strcmp(class_name, "blk_file") == 0) {
+ file_type = "block";
+ } else if (strcmp(class_name, "sock_file") == 0) {
+ file_type = "socket";
+ } else if (strcmp(class_name, "fifo_file") == 0) {
+ file_type = "pipe";
+ } else if (strcmp(class_name, "lnk_file") == 0) {
+ file_type = "symlink";
+ } else {
+ rc = -1;
+ goto exit;
+ }
+ }
+
ctx = context_to_str(pdb, &ocon->context[0]);
if (!ctx) {
rc = -1;
goto exit;
}
- rc = strs_create_and_add(strs, "(genfscon %s %s %s)", 3,
- fstype, name, ctx);
+ if (file_type) {
+ rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)", 4,
+ fstype, name, file_type, ctx);
+ } else {
+ rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", 3,
+ fstype, name, ctx);
+ }
free(ctx);
if (rc != 0) {
goto exit;
@@ -2738,13 +2829,13 @@ static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb)
for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon address is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon mask is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2778,13 +2869,13 @@ static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb)
for (node = pdb->ocontexts[6]; node != NULL; node = node->next) {
if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon address is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon mask is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2826,8 +2917,7 @@ static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)
if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("ibpkeycon subnet_prefix is invalid: %s",
- strerror(errno));
+ sepol_log_err("ibpkeycon subnet_prefix is invalid: %m");
rc = -1;
goto exit;
}
@@ -3077,7 +3167,7 @@ static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
- sepol_printf(out, "(devicetreecon %s %s)\n", name, ctx);
+ sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx);
free(ctx);
}
@@ -3130,6 +3220,18 @@ int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
goto exit;
}
+ if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but only in the type_attr_map. This means that there are gaps in both
+ * the type_val_to_struct and p_type_val_to_name arrays and policy rules
+ * can refer to those gaps.
+ */
+ sepol_log_err("Writing policy versions between 20 and 23 as CIL is not supported");
+ rc = -1;
+ goto exit;
+ }
+
rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
if (rc != 0) {
goto exit;
diff --git a/libsepol/src/kernel_to_common.c b/libsepol/src/kernel_to_common.c
index 7b53c92f..972499ab 100644
--- a/libsepol/src/kernel_to_common.c
+++ b/libsepol/src/kernel_to_common.c
@@ -18,6 +18,7 @@
#include <sepol/policydb/hashtab.h>
#include <sepol/policydb/symtab.h>
+#include "private.h"
#include "kernel_to_common.h"
@@ -57,7 +58,7 @@ static char *create_str_helper(const char *fmt, int num, va_list vargs)
va_list vargs2;
char *str = NULL;
char *s;
- size_t len;
+ size_t len, s_len;
int i, rc;
va_copy(vargs2, vargs);
@@ -66,7 +67,8 @@ static char *create_str_helper(const char *fmt, int num, va_list vargs)
for (i=0; i<num; i++) {
s = va_arg(vargs, char *);
- len += strlen(s) - 2; /* -2 for each %s in fmt */
+ s_len = strlen(s);
+ len += s_len > 1 ? s_len - 2 : 0; /* -2 for each %s in fmt */
}
str = malloc(len);
@@ -106,6 +108,10 @@ int strs_init(struct strs **strs, size_t size)
{
struct strs *new;
+ if (size == 0) {
+ size = 1;
+ }
+
*strs = NULL;
new = malloc(sizeof(struct strs));
@@ -114,7 +120,7 @@ int strs_init(struct strs **strs, size_t size)
return -1;
}
- new->list = calloc(sizeof(char *), size);
+ new->list = calloc(size, sizeof(char *));
if (!new->list) {
sepol_log_err("Out of memory");
free(new);
@@ -159,9 +165,9 @@ int strs_add(struct strs *strs, char *s)
{
if (strs->num + 1 > strs->size) {
char **new;
- unsigned i = strs->size;
+ size_t i = strs->size;
strs->size *= 2;
- new = realloc(strs->list, sizeof(char *)*strs->size);
+ new = reallocarray(strs->list, strs->size, sizeof(char *));
if (!new) {
sepol_log_err("Out of memory");
return -1;
@@ -212,15 +218,15 @@ char *strs_remove_last(struct strs *strs)
return strs->list[strs->num];
}
-int strs_add_at_index(struct strs *strs, char *s, unsigned index)
+int strs_add_at_index(struct strs *strs, char *s, size_t index)
{
if (index >= strs->size) {
char **new;
- unsigned i = strs->size;
+ size_t i = strs->size;
while (index >= strs->size) {
strs->size *= 2;
}
- new = realloc(strs->list, sizeof(char *)*strs->size);
+ new = reallocarray(strs->list, strs->size, sizeof(char *));
if (!new) {
sepol_log_err("Out of memory");
return -1;
@@ -237,7 +243,7 @@ int strs_add_at_index(struct strs *strs, char *s, unsigned index)
return 0;
}
-char *strs_read_at_index(struct strs *strs, unsigned index)
+char *strs_read_at_index(struct strs *strs, size_t index)
{
if (index >= strs->num) {
return NULL;
@@ -361,6 +367,9 @@ int ebitmap_to_strs(struct ebitmap *map, struct strs *strs, char **val_to_name)
int rc;
ebitmap_for_each_positive_bit(map, node, i) {
+ if (!val_to_name[i])
+ continue;
+
rc = strs_add(strs, val_to_name[i]);
if (rc != 0) {
return -1;
@@ -470,11 +479,9 @@ static int portcon_data_cmp(const void *a, const void *b)
rc = compare_ranges((*aa)->u.port.low_port, (*aa)->u.port.high_port,
(*bb)->u.port.low_port, (*bb)->u.port.high_port);
if (rc == 0) {
- if ((*aa)->u.port.protocol == (*bb)->u.port.protocol) {
- rc = 0;
- } else if ((*aa)->u.port.protocol == IPPROTO_TCP) {
+ if ((*aa)->u.port.protocol < (*bb)->u.port.protocol) {
rc = -1;
- } else {
+ } else if ((*aa)->u.port.protocol > (*bb)->u.port.protocol) {
rc = 1;
}
}
diff --git a/libsepol/src/kernel_to_common.h b/libsepol/src/kernel_to_common.h
index 8aa483fa..e9932d30 100644
--- a/libsepol/src/kernel_to_common.h
+++ b/libsepol/src/kernel_to_common.h
@@ -99,8 +99,8 @@ int strs_add(struct strs *strs, char *s);
__attribute__ ((format(printf, 2, 4)))
int strs_create_and_add(struct strs *strs, const char *fmt, int num, ...);
char *strs_remove_last(struct strs *strs);
-int strs_add_at_index(struct strs *strs, char *s, unsigned index);
-char *strs_read_at_index(struct strs *strs, unsigned index);
+int strs_add_at_index(struct strs *strs, char *s, size_t index);
+char *strs_read_at_index(struct strs *strs, size_t index);
void strs_sort(struct strs *strs);
unsigned strs_num_items(struct strs *strs);
size_t strs_len_items(struct strs *strs);
diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
index b4966162..3544f73d 100644
--- a/libsepol/src/kernel_to_conf.c
+++ b/libsepol/src/kernel_to_conf.c
@@ -15,9 +15,9 @@
#define IPPROTO_SCTP 132
#endif
+#include <sepol/kernel_to_conf.h>
#include <sepol/policydb/avtab.h>
#include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/hashtab.h>
#include <sepol/policydb/polcaps.h>
#include <sepol/policydb/policydb.h>
@@ -186,9 +186,13 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr
names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
}
if (!names) {
- goto exit;
+ names = strdup("NO_IDENTIFIER");
+ }
+ if (strchr(names, ' ')) {
+ new_val = create_str("%s %s { %s }", 3, attr1, op, names);
+ } else {
+ new_val = create_str("%s %s %s", 3, attr1, op, names);
}
- new_val = create_str("%s %s %s", 3, attr1, op, names);
free(names);
}
} else {
@@ -267,12 +271,15 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey,
{
struct constraint_node *curr;
struct strs *strs;
- const char *format_str, *flavor;
+ const char *flavor, *perm_prefix, *perm_suffix;
char *perms, *expr;
int is_mls;
int rc = 0;
for (curr = constraint_rules; curr != NULL; curr = curr->next) {
+ if (curr->permissions == 0) {
+ continue;
+ }
expr = constraint_expr_to_str(pdb, curr->expr, &is_mls);
if (!expr) {
rc = -1;
@@ -281,9 +288,11 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey,
perms = sepol_av_to_string(pdb, class->s.value, curr->permissions);
if (strchr(perms, ' ')) {
- format_str = "%s %s { %s } %s;";
+ perm_prefix = "{ ";
+ perm_suffix = " }";
} else {
- format_str = "%s %s %s %s";
+ perm_prefix = "";
+ perm_suffix = "";
}
if (is_mls) {
flavor = "mlsconstrain";
@@ -293,8 +302,10 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey,
strs = non_mls_list;
}
- rc = strs_create_and_add(strs, format_str, 4,
- flavor, classkey, perms+1, expr);
+ rc = strs_create_and_add(strs, "%s %s %s%s%s %s;", 6,
+ flavor, classkey,
+ perm_prefix, perms+1, perm_suffix,
+ expr);
free(expr);
if (rc != 0) {
goto exit;
@@ -354,7 +365,7 @@ static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs,
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
- if (class->constraints) {
+ if (class && class->constraints) {
name = pdb->p_class_val_to_name[i];
rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs);
if (rc != 0) {
@@ -379,7 +390,7 @@ static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_st
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
- if (class->validatetrans) {
+ if (class && class->validatetrans) {
name = pdb->p_class_val_to_name[i];
rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs);
if (rc != 0) {
@@ -547,6 +558,7 @@ static int write_class_and_common_rules_to_conf(FILE *out, struct policydb *pdb)
}
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
name = class->comkey;
if (!name) continue;
common = hashtab_search(pdb->p_commons.table, name);
@@ -573,6 +585,7 @@ static int write_class_and_common_rules_to_conf(FILE *out, struct policydb *pdb)
/* class */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
name = pdb->p_class_val_to_name[i];
sepol_printf(out, "class %s", name);
if (class->comkey) {
@@ -698,6 +711,7 @@ static int write_default_rules_to_conf(FILE *out, struct policydb *pdb)
/* default_user */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->default_user != 0) {
rc = write_default_user_to_conf(out, pdb->p_class_val_to_name[i], class);
if (rc != 0) {
@@ -709,6 +723,7 @@ static int write_default_rules_to_conf(FILE *out, struct policydb *pdb)
/* default_role */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->default_role != 0) {
rc = write_default_role_to_conf(out, pdb->p_class_val_to_name[i], class);
if (rc != 0) {
@@ -720,6 +735,7 @@ static int write_default_rules_to_conf(FILE *out, struct policydb *pdb)
/* default_type */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->default_type != 0) {
rc = write_default_type_to_conf(out, pdb->p_class_val_to_name[i], class);
if (rc != 0) {
@@ -735,6 +751,7 @@ static int write_default_rules_to_conf(FILE *out, struct policydb *pdb)
/* default_range */
for (i=0; i < pdb->p_classes.nprim; i++) {
class = pdb->class_val_to_struct[i];
+ if (!class) continue;
if (class->default_range != 0) {
rc = write_default_range_to_conf(out, pdb->p_class_val_to_name[i], class);
if (rc != 0) {
@@ -904,7 +921,7 @@ static int write_category_rules_to_conf(FILE *out, struct policydb *pdb)
unsigned i, j, num;
int rc = 0;
- rc = strs_init(&strs, pdb->p_levels.nprim);
+ rc = strs_init(&strs, pdb->p_cats.nprim);
if (rc != 0) {
goto exit;
}
@@ -1021,12 +1038,14 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
{
struct ebitmap_node *node;
uint32_t i, start, range, first;
- char *catsbuf, *p;
- const char *fmt;
+ char *catsbuf = NULL, *p;
char sep;
int len, remaining;
remaining = (int)cats_ebitmap_len(cats, val_to_name);
+ if (remaining == 0) {
+ goto exit;
+ }
catsbuf = malloc(remaining);
if (!catsbuf) {
goto exit;
@@ -1047,12 +1066,12 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
if (range > 1) {
sep = (range == 2) ? ',' : '.';
- fmt = first ? "%s%c%s" : ",%s%c%s";
- len = snprintf(p, remaining, fmt,
+ len = snprintf(p, remaining, "%s%s%c%s",
+ first ? "" : ",",
val_to_name[start], sep, val_to_name[i]);
} else {
- fmt = first ? "%s" : ",%s";
- len = snprintf(p, remaining, fmt, val_to_name[start]);
+ len = snprintf(p, remaining, "%s%s", first ? "" : ",",
+ val_to_name[start]);
}
if (len < 0 || len >= remaining) {
@@ -1090,7 +1109,7 @@ static int write_level_rules_to_conf(FILE *out, struct policydb *pdb)
}
if (level->isalias) continue;
- if (ebitmap_cardinality(&level->level->cat) > 0) {
+ if (!ebitmap_is_empty(&level->level->cat)) {
cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name);
sepol_printf(out, "level %s:%s;\n", name, cats);
free(cats);
@@ -1194,7 +1213,7 @@ static int write_type_attributes_to_conf(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
type = pdb->type_val_to_struct[i];
- if (type->flavor == TYPE_ATTRIB) {
+ if (type && type->flavor == TYPE_ATTRIB) {
rc = strs_add(strs, pdb->p_type_val_to_name[i]);
if (rc != 0) {
goto exit;
@@ -1324,7 +1343,7 @@ static int write_type_decl_rules_to_conf(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
type = pdb->type_val_to_struct[i];
- if (type->flavor == TYPE_TYPE && type->primary) {
+ if (type && type->flavor == TYPE_TYPE && type->primary) {
rc = strs_add(strs, pdb->p_type_val_to_name[i]);
if (rc != 0) {
goto exit;
@@ -1354,33 +1373,54 @@ exit:
return rc;
}
+static int map_count_type_aliases(__attribute__((unused)) char *key, void *data, void *args)
+{
+ type_datum_t *datum = data;
+ unsigned *count = args;
+
+ if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
+ (*count)++;
+
+ return SEPOL_OK;
+}
+
+static int map_type_aliases_to_strs(char *key, void *data, void *args)
+{
+ type_datum_t *datum = data;
+ struct strs *strs = args;
+ int rc = 0;
+
+ if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
+ rc = strs_add(strs, key);
+
+ return rc;
+}
+
static int write_type_alias_rules_to_conf(FILE *out, struct policydb *pdb)
{
type_datum_t *alias;
struct strs *strs;
char *name;
char *type;
- unsigned i, num;
+ unsigned i, num = 0;
int rc = 0;
- rc = strs_init(&strs, pdb->p_types.nprim);
+ rc = hashtab_map(pdb->p_types.table, map_count_type_aliases, &num);
if (rc != 0) {
goto exit;
}
- for (i=0; i < pdb->p_types.nprim; i++) {
- alias = pdb->type_val_to_struct[i];
- if (!alias->primary) {
- rc = strs_add(strs, pdb->p_type_val_to_name[i]);
- if (rc != 0) {
- goto exit;
- }
- }
+ rc = strs_init(&strs, num);
+ if (rc != 0) {
+ goto exit;
}
- strs_sort(strs);
+ rc = hashtab_map(pdb->p_types.table, map_type_aliases_to_strs, strs);
+ if (rc != 0) {
+ goto exit;
+ }
- num = strs_num_items(strs);
+ strs_sort(strs);
for (i=0; i<num; i++) {
name = strs_read_at_index(strs, i);
@@ -1394,7 +1434,7 @@ static int write_type_alias_rules_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
type = pdb->p_type_val_to_name[alias->s.value - 1];
- sepol_printf(out, "typealias %s %s;\n", type, name);
+ sepol_printf(out, "typealias %s alias %s;\n", type, name);
}
exit:
@@ -1423,7 +1463,7 @@ static int write_type_bounds_rules_to_conf(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
type = pdb->type_val_to_struct[i];
- if (type->flavor == TYPE_TYPE) {
+ if (type && type->flavor == TYPE_TYPE) {
if (type->bounds > 0) {
rc = strs_add(strs, pdb->p_type_val_to_name[i]);
if (rc != 0) {
@@ -1546,7 +1586,7 @@ static int write_type_attribute_sets_to_conf(FILE *out, struct policydb *pdb)
for (i=0; i < pdb->p_types.nprim; i++) {
type = pdb->type_val_to_struct[i];
- if (type->flavor != TYPE_TYPE || !type->primary) continue;
+ if (!type || type->flavor != TYPE_TYPE || !type->primary) continue;
if (ebitmap_cardinality(&pdb->type_attr_map[i]) == 1) continue;
rc = ebitmap_cpy(&attrmap, &pdb->type_attr_map[i]);
@@ -1802,21 +1842,35 @@ struct map_filename_trans_args {
static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg)
{
- filename_trans_t *ft = (filename_trans_t *)key;
+ filename_trans_key_t *ft = (filename_trans_key_t *)key;
filename_trans_datum_t *datum = data;
struct map_filename_trans_args *map_args = arg;
struct policydb *pdb = map_args->pdb;
struct strs *strs = map_args->strs;
char *src, *tgt, *class, *filename, *new;
+ struct ebitmap_node *node;
+ uint32_t bit;
+ int rc;
- src = pdb->p_type_val_to_name[ft->stype - 1];
tgt = pdb->p_type_val_to_name[ft->ttype - 1];
class = pdb->p_class_val_to_name[ft->tclass - 1];
filename = ft->name;
- new = pdb->p_type_val_to_name[datum->otype - 1];
+ do {
+ new = pdb->p_type_val_to_name[datum->otype - 1];
+
+ ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
+ src = pdb->p_type_val_to_name[bit];
+ rc = strs_create_and_add(strs,
+ "type_transition %s %s:%s %s \"%s\";",
+ 5, src, tgt, class, new, filename);
+ if (rc)
+ return rc;
+ }
- return strs_create_and_add(strs, "type_transition %s %s:%s %s \"%s\";", 5,
- src, tgt, class, new, filename);
+ datum = datum->next;
+ } while (datum);
+
+ return 0;
}
static int write_filename_trans_rules_to_conf(FILE *out, struct policydb *pdb)
@@ -1859,7 +1913,7 @@ static char *level_to_str(struct policydb *pdb, struct mls_level *level)
char *sens_str = pdb->p_sens_val_to_name[level->sens - 1];
char *cats_str;
- if (ebitmap_cardinality(cats) > 0) {
+ if (!ebitmap_is_empty(cats)) {
cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name);
level_str = create_str("%s:%s", 2, sens_str, cats_str);
free(cats_str);
@@ -2145,7 +2199,7 @@ static int write_role_decl_rules_to_conf(FILE *out, struct policydb *pdb)
rc = -1;
goto exit;
}
- if (ebitmap_cardinality(&role->types.types) == 0) continue;
+ if (ebitmap_is_empty(&role->types.types)) continue;
types = ebitmap_to_str(&role->types.types, pdb->p_type_val_to_name, 1);
if (!types) {
rc = -1;
@@ -2276,6 +2330,7 @@ static int write_user_decl_rules_to_conf(FILE *out, struct policydb *pdb)
}
for (i=0; i < pdb->p_users.nprim; i++) {
+ if (!pdb->p_user_val_to_name[i]) continue;
rc = strs_add(strs, pdb->p_user_val_to_name[i]);
if (rc != 0) {
goto exit;
@@ -2298,7 +2353,7 @@ static int write_user_decl_rules_to_conf(FILE *out, struct policydb *pdb)
}
sepol_printf(out, "user %s", name);
- if (ebitmap_cardinality(&user->roles.roles) > 0) {
+ if (!ebitmap_is_empty(&user->roles.roles)) {
roles = ebitmap_to_str(&user->roles.roles,
pdb->p_role_val_to_name, 1);
if (!roles) {
@@ -2333,9 +2388,10 @@ static int write_user_decl_rules_to_conf(FILE *out, struct policydb *pdb)
sepol_printf(out, ";\n");
}
- strs_destroy(&strs);
-
exit:
+ if (strs)
+ strs_destroy(&strs);
+
if (rc != 0) {
sepol_log_err("Error writing user declarations to policy.conf\n");
}
@@ -2470,6 +2526,8 @@ static int write_genfscon_rules_to_conf(FILE *out, struct policydb *pdb)
struct ocontext *ocon;
struct strs *strs;
char *fstype, *name, *ctx;
+ uint32_t sclass;
+ const char *file_type;
int rc;
rc = strs_init(&strs, 32);
@@ -2482,14 +2540,43 @@ static int write_genfscon_rules_to_conf(FILE *out, struct policydb *pdb)
fstype = genfs->fstype;
name = ocon->u.name;
+ sclass = ocon->v.sclass;
+ file_type = NULL;
+ if (sclass) {
+ const char *class_name = pdb->p_class_val_to_name[sclass-1];
+ if (strcmp(class_name, "file") == 0) {
+ file_type = "--";
+ } else if (strcmp(class_name, "dir") == 0) {
+ file_type = "-d";
+ } else if (strcmp(class_name, "chr_file") == 0) {
+ file_type = "-c";
+ } else if (strcmp(class_name, "blk_file") == 0) {
+ file_type = "-b";
+ } else if (strcmp(class_name, "sock_file") == 0) {
+ file_type = "-s";
+ } else if (strcmp(class_name, "fifo_file") == 0) {
+ file_type = "-p";
+ } else if (strcmp(class_name, "lnk_file") == 0) {
+ file_type = "-l";
+ } else {
+ rc = -1;
+ goto exit;
+ }
+ }
+
ctx = context_to_str(pdb, &ocon->context[0]);
if (!ctx) {
rc = -1;
goto exit;
}
- rc = strs_create_and_add(strs, "genfscon %s %s %s", 3,
- fstype, name, ctx);
+ if (file_type) {
+ rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s %s", 4,
+ fstype, name, file_type, ctx);
+ } else {
+ rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s", 3,
+ fstype, name, ctx);
+ }
free(ctx);
if (rc != 0) {
goto exit;
@@ -2610,13 +2697,13 @@ static int write_selinux_node_rules_to_conf(FILE *out, struct policydb *pdb)
for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon address is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon mask is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2651,13 +2738,13 @@ static int write_selinux_node6_rules_to_conf(FILE *out, struct policydb *pdb)
for (node6 = pdb->ocontexts[6]; node6 != NULL; node6 = node6->next) {
if (inet_ntop(AF_INET6, &node6->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon address is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET6, &node6->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("Nodecon mask is invalid: %s", strerror(errno));
+ sepol_log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2699,8 +2786,7 @@ static int write_selinux_ibpkey_rules_to_conf(FILE *out, struct policydb *pdb)
if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
- sepol_log_err("ibpkeycon address is invalid: %s",
- strerror(errno));
+ sepol_log_err("ibpkeycon address is invalid: %m");
rc = -1;
goto exit;
}
@@ -2953,7 +3039,7 @@ static int write_xen_devicetree_rules_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
- sepol_printf(out, "devicetreecon %s %s\n", name, ctx);
+ sepol_printf(out, "devicetreecon \"%s\" %s\n", name, ctx);
free(ctx);
}
@@ -3006,6 +3092,18 @@ int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb)
goto exit;
}
+ if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but only in the type_attr_map. This means that there are gaps in both
+ * the type_val_to_struct and p_type_val_to_name arrays and policy rules
+ * can refer to those gaps.
+ */
+ sepol_log_err("Writing policy versions between 20 and 23 as a policy.conf is not supported");
+ rc = -1;
+ goto exit;
+ }
+
rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
if (rc != 0) {
goto exit;
diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in
index f4946a79..0e05d606 100644
--- a/libsepol/src/libsepol.map.in
+++ b/libsepol/src/libsepol.map.in
@@ -1,39 +1,245 @@
LIBSEPOL_1.0 {
- global:
- expand_module_avrules;
- sepol_module_package_*; sepol_link_modules; sepol_expand_module; sepol_link_packages;
- sepol_bool_*; sepol_genbools*;
- sepol_context_*; sepol_mls_*; sepol_check_context;
- sepol_iface_*;
- sepol_port_*;
- sepol_ibpkey_*;
- sepol_ibendport_*;
- sepol_node_*;
- sepol_user_*; sepol_genusers; sepol_set_delusers;
- sepol_msg_*; sepol_debug;
- sepol_handle_*;
- sepol_policydb_*; sepol_set_policydb_from_file;
- sepol_policy_kern_*;
- sepol_policy_file_*;
- sepol_get_disable_dontaudit;
- sepol_set_disable_dontaudit;
- sepol_set_expand_consume_base;
- sepol_get_preserve_tunables; sepol_set_preserve_tunables;
+ global:
+ cil_add_file;
+ cil_db_destroy;
cil_db_init;
cil_set_disable_dontaudit;
cil_set_disable_neverallow;
- cil_set_preserve_tunables;
cil_set_handle_unknown;
- cil_db_destroy;
- cil_add_file;
- cil_compile;
- cil_build_policydb;
- cil_userprefixes_to_string;
- cil_selinuxusers_to_string;
- cil_filecons_to_string;
- cil_set_log_level;
cil_set_log_handler;
- cil_set_malloc_error_handler;
+ cil_set_log_level;
+ cil_set_preserve_tunables;
+ expand_module_avrules;
+ sepol_bool_clone;
+ sepol_bool_compare;
+ sepol_bool_compare2;
+ sepol_bool_count;
+ sepol_bool_create;
+ sepol_bool_exists;
+ sepol_bool_free;
+ sepol_bool_get_name;
+ sepol_bool_get_value;
+ sepol_bool_iterate;
+ sepol_bool_key_create;
+ sepol_bool_key_extract;
+ sepol_bool_key_free;
+ sepol_bool_key_unpack;
+ sepol_bool_query;
+ sepol_bool_set;
+ sepol_bool_set_name;
+ sepol_bool_set_value;
+ sepol_check_context;
+ sepol_context_check;
+ sepol_context_clone;
+ sepol_context_create;
+ sepol_context_free;
+ sepol_context_from_string;
+ sepol_context_get_mls;
+ sepol_context_get_role;
+ sepol_context_get_type;
+ sepol_context_get_user;
+ sepol_context_set_mls;
+ sepol_context_set_role;
+ sepol_context_set_type;
+ sepol_context_set_user;
+ sepol_context_to_string;
+ sepol_debug;
+ sepol_expand_module;
+ sepol_get_disable_dontaudit;
+ sepol_get_preserve_tunables;
+ sepol_handle_create;
+ sepol_handle_destroy;
+ sepol_ibendport_alloc_ibdev_name;
+ sepol_ibendport_clone;
+ sepol_ibendport_compare;
+ sepol_ibendport_compare2;
+ sepol_ibendport_count;
+ sepol_ibendport_create;
+ sepol_ibendport_exists;
+ sepol_ibendport_free;
+ sepol_ibendport_get_con;
+ sepol_ibendport_get_ibdev_name;
+ sepol_ibendport_get_port;
+ sepol_ibendport_iterate;
+ sepol_ibendport_key_create;
+ sepol_ibendport_key_extract;
+ sepol_ibendport_key_free;
+ sepol_ibendport_key_unpack;
+ sepol_ibendport_modify;
+ sepol_ibendport_query;
+ sepol_ibendport_set_con;
+ sepol_ibendport_set_ibdev_name;
+ sepol_ibendport_set_port;
+ sepol_ibpkey_clone;
+ sepol_ibpkey_compare;
+ sepol_ibpkey_compare2;
+ sepol_ibpkey_count;
+ sepol_ibpkey_create;
+ sepol_ibpkey_exists;
+ sepol_ibpkey_free;
+ sepol_ibpkey_get_con;
+ sepol_ibpkey_get_high;
+ sepol_ibpkey_get_low;
+ sepol_ibpkey_get_subnet_prefix;
+ sepol_ibpkey_get_subnet_prefix_bytes;
+ sepol_ibpkey_iterate;
+ sepol_ibpkey_key_create;
+ sepol_ibpkey_key_extract;
+ sepol_ibpkey_key_free;
+ sepol_ibpkey_key_unpack;
+ sepol_ibpkey_modify;
+ sepol_ibpkey_query;
+ sepol_ibpkey_set_con;
+ sepol_ibpkey_set_pkey;
+ sepol_ibpkey_set_range;
+ sepol_ibpkey_set_subnet_prefix;
+ sepol_ibpkey_set_subnet_prefix_bytes;
+ sepol_iface_clone;
+ sepol_iface_compare;
+ sepol_iface_compare2;
+ sepol_iface_count;
+ sepol_iface_create;
+ sepol_iface_exists;
+ sepol_iface_free;
+ sepol_iface_get_ifcon;
+ sepol_iface_get_msgcon;
+ sepol_iface_get_name;
+ sepol_iface_iterate;
+ sepol_iface_key_create;
+ sepol_iface_key_extract;
+ sepol_iface_key_free;
+ sepol_iface_key_unpack;
+ sepol_iface_modify;
+ sepol_iface_query;
+ sepol_iface_set_ifcon;
+ sepol_iface_set_msgcon;
+ sepol_iface_set_name;
+ sepol_link_modules;
+ sepol_link_packages;
+ sepol_mls_check;
+ sepol_mls_contains;
+ sepol_module_package_create;
+ sepol_module_package_free;
+ sepol_module_package_get_file_contexts;
+ sepol_module_package_get_file_contexts_len;
+ sepol_module_package_get_netfilter_contexts;
+ sepol_module_package_get_netfilter_contexts_len;
+ sepol_module_package_get_policy;
+ sepol_module_package_get_seusers;
+ sepol_module_package_get_seusers_len;
+ sepol_module_package_get_user_extra;
+ sepol_module_package_get_user_extra_len;
+ sepol_module_package_info;
+ sepol_module_package_read;
+ sepol_module_package_set_file_contexts;
+ sepol_module_package_set_netfilter_contexts;
+ sepol_module_package_set_seusers;
+ sepol_module_package_set_user_extra;
+ sepol_module_package_write;
+ sepol_msg_get_channel;
+ sepol_msg_get_fname;
+ sepol_msg_get_level;
+ sepol_msg_set_callback;
+ sepol_node_clone;
+ sepol_node_compare;
+ sepol_node_compare2;
+ sepol_node_count;
+ sepol_node_create;
+ sepol_node_exists;
+ sepol_node_free;
+ sepol_node_get_addr;
+ sepol_node_get_addr_bytes;
+ sepol_node_get_con;
+ sepol_node_get_mask;
+ sepol_node_get_mask_bytes;
+ sepol_node_get_proto;
+ sepol_node_get_proto_str;
+ sepol_node_iterate;
+ sepol_node_key_create;
+ sepol_node_key_extract;
+ sepol_node_key_free;
+ sepol_node_key_unpack;
+ sepol_node_modify;
+ sepol_node_query;
+ sepol_node_set_addr;
+ sepol_node_set_addr_bytes;
+ sepol_node_set_con;
+ sepol_node_set_mask;
+ sepol_node_set_mask_bytes;
+ sepol_node_set_proto;
+ sepol_policydb_compat_net;
+ sepol_policydb_create;
+ sepol_policydb_free;
+ sepol_policydb_from_image;
+ sepol_policydb_mls_enabled;
+ sepol_policydb_read;
+ sepol_policydb_set_handle_unknown;
+ sepol_policydb_set_target_platform;
+ sepol_policydb_set_typevers;
+ sepol_policydb_set_vers;
+ sepol_policydb_to_image;
+ sepol_policydb_write;
+ sepol_policy_file_create;
+ sepol_policy_file_free;
+ sepol_policy_file_get_len;
+ sepol_policy_file_set_fp;
+ sepol_policy_file_set_handle;
+ sepol_policy_file_set_mem;
+ sepol_policy_kern_vers_max;
+ sepol_policy_kern_vers_min;
+ sepol_port_clone;
+ sepol_port_compare;
+ sepol_port_compare2;
+ sepol_port_count;
+ sepol_port_create;
+ sepol_port_exists;
+ sepol_port_free;
+ sepol_port_get_con;
+ sepol_port_get_high;
+ sepol_port_get_low;
+ sepol_port_get_proto;
+ sepol_port_get_proto_str;
+ sepol_port_iterate;
+ sepol_port_key_create;
+ sepol_port_key_extract;
+ sepol_port_key_free;
+ sepol_port_key_unpack;
+ sepol_port_modify;
+ sepol_port_query;
+ sepol_port_set_con;
+ sepol_port_set_port;
+ sepol_port_set_proto;
+ sepol_port_set_range;
+ sepol_set_disable_dontaudit;
+ sepol_set_expand_consume_base;
+ sepol_set_policydb_from_file;
+ sepol_set_preserve_tunables;
+ sepol_user_add_role;
+ sepol_user_clone;
+ sepol_user_compare;
+ sepol_user_compare2;
+ sepol_user_count;
+ sepol_user_create;
+ sepol_user_del_role;
+ sepol_user_exists;
+ sepol_user_free;
+ sepol_user_get_mlslevel;
+ sepol_user_get_mlsrange;
+ sepol_user_get_name;
+ sepol_user_get_num_roles;
+ sepol_user_get_roles;
+ sepol_user_has_role;
+ sepol_user_iterate;
+ sepol_user_key_create;
+ sepol_user_key_extract;
+ sepol_user_key_free;
+ sepol_user_key_unpack;
+ sepol_user_modify;
+ sepol_user_query;
+ sepol_user_set_mlslevel;
+ sepol_user_set_mlsrange;
+ sepol_user_set_name;
+ sepol_user_set_roles;
local: *;
};
@@ -63,4 +269,8 @@ LIBSEPOL_1.1 {
LIBSEPOL_3.0 {
global:
sepol_policydb_optimize;
+ cil_write_parse_ast;
+ cil_write_build_ast;
+ cil_write_resolve_ast;
+ cil_set_qualified_names;
} LIBSEPOL_1.1;
diff --git a/libsepol/src/link.c b/libsepol/src/link.c
index 83bbc8a5..21a5a935 100644
--- a/libsepol/src/link.c
+++ b/libsepol/src/link.c
@@ -34,6 +34,7 @@
#include <assert.h>
#include "debug.h"
+#include "private.h"
#undef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
@@ -78,7 +79,7 @@ typedef struct missing_requirement {
uint32_t perm_value;
} missing_requirement_t;
-static const char *symtab_names[SYM_NUM] = {
+static const char * const symtab_names[SYM_NUM] = {
"common", "class", "role", "type/attribute", "user",
"bool", "level", "category"
};
@@ -164,7 +165,7 @@ static int permission_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
(hashtab_datum_t) new_perm);
if (ret) {
ERR(state->handle,
- "could not insert permission into class\n");
+ "could not insert permission into class");
goto err;
}
new_perm->s.value = dest_class->permissions.nprim + 1;
@@ -190,8 +191,9 @@ static int permission_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
ERR(state->handle, "Out of memory!");
return -1;
}
- memcpy(newmap, mod->perm_map[sclassi],
- mod->perm_map_len[sclassi] * sizeof(*newmap));
+ if (mod->perm_map_len[sclassi] > 0) {
+ memcpy(newmap, mod->perm_map[sclassi], mod->perm_map_len[sclassi] * sizeof(*newmap));
+ }
free(mod->perm_map[sclassi]);
mod->perm_map[sclassi] = newmap;
mod->perm_map_len[sclassi] = perm->s.value;
@@ -287,7 +289,7 @@ static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
new_class =
(class_datum_t *) calloc(1, sizeof(class_datum_t));
if (new_class == NULL) {
- ERR(state->handle, "Memory error\n");
+ ERR(state->handle, "Memory error");
ret = SEPOL_ERR;
goto err;
}
@@ -298,7 +300,7 @@ static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
}
new_id = strdup(id);
if (new_id == NULL) {
- ERR(state->handle, "Memory error\n");
+ ERR(state->handle, "Memory error");
symtab_destroy(&new_class->permissions);
ret = SEPOL_ERR;
goto err;
@@ -694,7 +696,7 @@ static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
return SEPOL_ENOTSUP;
} else {
ERR(state->handle,
- "%s: has an unknown scope: %d\n",
+ "%s: has an unknown scope: %d",
state->cur_mod_name, scope->scope);
return SEPOL_ENOTSUP;
}
@@ -736,7 +738,7 @@ static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
} else {
/* unknown scope? malformed policy? */
ERR(state->handle,
- "%s: has an unknown scope: %d\n",
+ "%s: has an unknown scope: %d",
state->cur_mod_name, scope->scope);
return SEPOL_ENOTSUP;
}
@@ -1291,10 +1293,10 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst,
i <
module->perm_map_len[cur_perm->tclass - 1];
i++) {
- if (!(cur_perm->data & (1U << i)))
+ if (!(cur_perm->data & (UINT32_C(1) << i)))
continue;
new_perm->data |=
- (1U <<
+ (UINT32_C(1) <<
(module->
perm_map[cur_perm->tclass - 1][i] -
1));
@@ -1679,7 +1681,7 @@ static int copy_scope_index(scope_index_t * src, scope_index_t * dest,
}
/* next copy the enabled permissions data */
- if ((dest->class_perms_map = malloc(largest_mapped_class_value *
+ if ((dest->class_perms_map = mallocarray(largest_mapped_class_value,
sizeof(*dest->class_perms_map))) ==
NULL) {
goto cleanup;
@@ -1779,7 +1781,7 @@ static int copy_avrule_block(link_state_t * state, policy_module_t * module,
if (module->policy->name != NULL) {
new_decl->module_name = strdup(module->policy->name);
if (new_decl->module_name == NULL) {
- ERR(state->handle, "Out of memory\n");
+ ERR(state->handle, "Out of memory");
avrule_decl_destroy(new_decl);
ret = -1;
goto cleanup;
@@ -2206,7 +2208,7 @@ static int enable_avrules(link_state_t * state, policydb_t * pol)
if (state->verbose) {
const char *mod_name = decl->module_name ?
decl->module_name : "BASE";
- INFO(state->handle, "check module %s decl %d\n",
+ INFO(state->handle, "check module %s decl %d",
mod_name, decl->decl_id);
}
rc = is_decl_requires_met(state, decl, &req);
@@ -2552,7 +2554,7 @@ int link_modules(sepol_handle_t * handle,
if (mods[i]->policyvers > b->policyvers) {
WARN(state.handle,
- "Upgrading policy version from %u to %u\n", b->policyvers, mods[i]->policyvers);
+ "Upgrading policy version from %u to %u", b->policyvers, mods[i]->policyvers);
b->policyvers = mods[i]->policyvers;
}
@@ -2573,36 +2575,6 @@ int link_modules(sepol_handle_t * handle,
goto cleanup;
}
- /* copy all types, declared and required */
- for (i = 0; i < len; i++) {
- state.cur = modules[i];
- state.cur_mod_name = modules[i]->policy->name;
- ret =
- hashtab_map(modules[i]->policy->p_types.table,
- type_copy_callback, &state);
- if (ret) {
- retval = ret;
- goto cleanup;
- }
- }
-
- /* then copy everything else, including aliases, and fixup attributes */
- for (i = 0; i < len; i++) {
- state.cur = modules[i];
- state.cur_mod_name = modules[i]->policy->name;
- ret =
- copy_identifiers(&state, modules[i]->policy->symtab, NULL);
- if (ret) {
- retval = ret;
- goto cleanup;
- }
- }
-
- if (policydb_index_others(state.handle, state.base, 0)) {
- ERR(state.handle, "Error while indexing others");
- goto cleanup;
- }
-
/* copy and remap the module's data over to base */
for (i = 0; i < len; i++) {
state.cur = modules[i];
diff --git a/libsepol/src/mls.c b/libsepol/src/mls.c
index 6ff9a846..366a1114 100644
--- a/libsepol/src/mls.c
+++ b/libsepol/src/mls.c
@@ -27,9 +27,9 @@
* Implementation of the multi-level security (MLS) policy.
*/
+#include <sepol/context.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/services.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/context.h>
#include <stdlib.h>
@@ -649,7 +649,7 @@ int mls_compute_sid(policydb_t * policydb,
/* Fallthrough */
case AVTAB_CHANGE:
- if (tclass == SECCLASS_PROCESS)
+ if (tclass == policydb->process_class)
/* Use the process MLS attributes. */
return mls_copy_context(newcontext, scontext);
else
@@ -665,7 +665,7 @@ int mls_compute_sid(policydb_t * policydb,
}
int sepol_mls_contains(sepol_handle_t * handle,
- sepol_policydb_t * policydb,
+ const sepol_policydb_t * policydb,
const char *mls1, const char *mls2, int *response)
{
@@ -704,7 +704,7 @@ int sepol_mls_contains(sepol_handle_t * handle,
}
int sepol_mls_check(sepol_handle_t * handle,
- sepol_policydb_t * policydb, const char *mls)
+ const sepol_policydb_t * policydb, const char *mls)
{
int ret;
diff --git a/libsepol/src/module.c b/libsepol/src/module.c
index 3b8a0a59..d93d08a2 100644
--- a/libsepol/src/module.c
+++ b/libsepol/src/module.c
@@ -82,7 +82,7 @@ static int policy_file_length(struct policy_file *fp, size_t *out)
break;
case PF_USE_MEMORY:
*out = fp->size;
- break;;
+ break;
default:
*out = 0;
break;
@@ -132,7 +132,6 @@ int sepol_module_package_create(sepol_module_package_t ** p)
return rc;
}
-hidden_def(sepol_module_package_create)
/* Deallocates all memory associated with a module package, including
* the pointer itself. Does nothing if p is NULL.
@@ -150,7 +149,6 @@ void sepol_module_package_free(sepol_module_package_t * p)
free(p);
}
-hidden_def(sepol_module_package_free)
char *sepol_module_package_get_file_contexts(sepol_module_package_t * p)
{
@@ -295,11 +293,14 @@ static int link_netfilter_contexts(sepol_module_package_t * base,
}
base->netfilter_contexts = base_context;
for (i = 0; i < num_modules; i++) {
- memcpy(base->netfilter_contexts + base->netfilter_contexts_len,
- modules[i]->netfilter_contexts,
- modules[i]->netfilter_contexts_len);
- base->netfilter_contexts_len +=
- modules[i]->netfilter_contexts_len;
+ if (modules[i]->netfilter_contexts_len > 0) {
+ memcpy(base->netfilter_contexts + base->netfilter_contexts_len,
+ modules[i]->netfilter_contexts,
+ modules[i]->netfilter_contexts_len);
+ base->netfilter_contexts_len +=
+ modules[i]->netfilter_contexts_len;
+ }
+
}
return 0;
}
@@ -408,14 +409,14 @@ static int module_package_read_offsets(sepol_module_package_t * mod,
goto err;
}
- off = (size_t *) malloc((nsec + 1) * sizeof(size_t));
+ off = (size_t *) mallocarray(nsec + 1, sizeof(size_t));
if (!off) {
ERR(file->handle, "out of memory");
goto err;
}
free(buf);
- buf = malloc(sizeof(uint32_t) * nsec);
+ buf = mallocarray(nsec, sizeof(uint32_t));
if (!buf) {
ERR(file->handle, "out of memory");
goto err;
@@ -798,7 +799,9 @@ int sepol_module_package_info(struct sepol_policy_file *spf, int *type,
len = le32_to_cpu(buf[0]);
if (str_read(name, file, len)) {
- ERR(file->handle, "%s", strerror(errno));
+ ERR(file->handle,
+ "cannot read module name (at section %u): %m",
+ i);
goto cleanup;
}
@@ -811,7 +814,9 @@ int sepol_module_package_info(struct sepol_policy_file *spf, int *type,
}
len = le32_to_cpu(buf[0]);
if (str_read(version, file, len)) {
- ERR(file->handle, "%s", strerror(errno));
+ ERR(file->handle,
+ "cannot read module version (at section %u): %m",
+ i);
goto cleanup;
}
seen |= SEEN_MOD;
diff --git a/libsepol/src/module_internal.h b/libsepol/src/module_internal.h
index cdd5ec65..ac1be36a 100644
--- a/libsepol/src/module_internal.h
+++ b/libsepol/src/module_internal.h
@@ -1,5 +1,2 @@
#include <sepol/module.h>
-#include "dso.h"
-hidden_proto(sepol_module_package_create)
- hidden_proto(sepol_module_package_free)
diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index e20c3d44..c9e88f1e 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -62,7 +62,7 @@
# define UNUSED(x) UNUSED_ ## x
#endif
-FILE *out_file;
+static FILE *out_file;
#define STACK_SIZE 16
#define DEFAULT_LEVEL "systemlow"
@@ -107,8 +107,8 @@ static void cil_printf(const char *fmt, ...) {
__attribute__ ((format(printf, 2, 3)))
static void cil_println(int indent, const char *fmt, ...)
{
- cil_indent(indent);
va_list argptr;
+ cil_indent(indent);
va_start(argptr, fmt);
if (vfprintf(out_file, fmt, argptr) < 0) {
log_err("Failed to write to output");
@@ -235,12 +235,14 @@ static void role_list_destroy(void)
static void attr_list_destroy(struct list **attr_list)
{
+ struct list_node *curr;
+ struct attr_list_node *attr;
+
if (attr_list == NULL || *attr_list == NULL) {
return;
}
- struct list_node *curr = (*attr_list)->head;
- struct attr_list_node *attr;
+ curr = (*attr_list)->head;
while (curr != NULL) {
attr = curr->data;
@@ -428,7 +430,7 @@ static int stack_init(struct stack **stack)
goto exit;
}
- s->stack = malloc(sizeof(*s->stack) * STACK_SIZE);
+ s->stack = mallocarray(STACK_SIZE, sizeof(*s->stack));
if (s->stack == NULL) {
goto exit;
}
@@ -451,7 +453,7 @@ static int stack_push(struct stack *stack, void *ptr)
void *new_stack;
if (stack->pos + 1 == stack->size) {
- new_stack = realloc(stack->stack, sizeof(*stack->stack) * (stack->size * 2));
+ new_stack = reallocarray(stack->stack, stack->size * 2, sizeof(*stack->stack));
if (new_stack == NULL) {
goto exit;
}
@@ -571,7 +573,7 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const
rule = "auditallow";
break;
case AVRULE_AUDITDENY:
- rule = "auditdenty";
+ rule = "auditdeny";
break;
case AVRULE_DONTAUDIT:
rule = "dontaudit";
@@ -717,9 +719,9 @@ exit:
return rc;
}
-static int num_digits(int n)
+static unsigned int num_digits(unsigned int n)
{
- int num = 1;
+ unsigned int num = 1;
while (n >= 10) {
n /= 10;
num++;
@@ -829,8 +831,8 @@ static int cil_print_attr_strs(int indent, struct policydb *pdb, int is_type, vo
pos = &ts->types;
neg = &ts->negset;
flags = ts->flags;
- has_positive = pos && (ebitmap_length(pos) > 0);
- has_negative = neg && (ebitmap_length(neg) > 0);
+ has_positive = pos && !ebitmap_is_empty(pos);
+ has_negative = neg && !ebitmap_is_empty(neg);
} else {
kind = "role";
val_to_name = pdb->p_role_val_to_name;
@@ -838,7 +840,7 @@ static int cil_print_attr_strs(int indent, struct policydb *pdb, int is_type, vo
pos = &rs->roles;
neg = NULL;
flags = rs->flags;
- has_positive = pos && (ebitmap_length(pos) > 0);
+ has_positive = pos && !ebitmap_is_empty(pos);
has_negative = 0;
}
@@ -945,7 +947,7 @@ static char *search_attr_list(struct list *attr_list, int is_type, void *set)
return NULL;
}
-static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, int *num_names)
+static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, unsigned int *num_names)
{
char *attr_name = NULL;
int rc = 0;
@@ -982,12 +984,12 @@ exit:
return rc;
}
-static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, int *num_names)
+static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, unsigned int *num_names)
{
int rc = 0;
struct ebitmap_node *node;
uint32_t i;
- uint32_t num;
+ unsigned int num;
char **name_arr;
num = 0;
@@ -1006,7 +1008,7 @@ static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***n
goto exit;
}
- name_arr = malloc(sizeof(*name_arr) * num);
+ name_arr = mallocarray(num, sizeof(*name_arr));
if (name_arr == NULL) {
log_err("Out of memory");
rc = -1;
@@ -1026,7 +1028,7 @@ exit:
return rc;
}
-static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, int *num_names)
+static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, unsigned int *num_names)
{
int rc = 0;
@@ -1049,14 +1051,14 @@ exit:
return rc;
}
-static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, int *num_names)
+static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, unsigned int *num_names)
{
int rc = 0;
*names = NULL;
*num_names = 0;
- if (ebitmap_length(&ts->negset) > 0 || ts->flags != 0) {
+ if (!ebitmap_is_empty(&ts->negset) || ts->flags != 0) {
rc = set_to_names(pdb, 1, ts, attr_list, names, num_names);
if (rc != 0) {
goto exit;
@@ -1072,7 +1074,7 @@ exit:
return rc;
}
-static void names_destroy(char ***names, int *num_names)
+static void names_destroy(char ***names, unsigned int *num_names)
{
free(*names);
*names = NULL;
@@ -1083,7 +1085,7 @@ static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack *
{
struct list_node *curr;
char **tnames = NULL;
- int num_tnames, i;
+ unsigned int num_tnames, i;
struct role_list_node *role_node = NULL;
int rc;
struct type_set *ts;
@@ -1124,26 +1126,24 @@ exit:
}
-static int name_list_to_string(char **names, int num_names, char **string)
+static int name_list_to_string(char **names, unsigned int num_names, char **string)
{
// create a space separated string of the names
int rc = -1;
size_t len = 0;
- int i;
+ unsigned int i;
char *str;
char *strpos;
for (i = 0; i < num_names; i++) {
- len += strlen(names[i]);
- if (len < strlen(names[i])) {
+ if (__builtin_add_overflow(len, strlen(names[i]), &len)) {
log_err("Overflow");
return -1;
}
}
// add spaces + null terminator
- len += num_names;
- if (len < (size_t)num_names) {
+ if (__builtin_add_overflow(len, (size_t)num_names, &len)) {
log_err("Overflow");
return -1;
}
@@ -1184,7 +1184,7 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
struct avrule *avrule;
char **snames = NULL;
char **tnames = NULL;
- int s, t, num_snames, num_tnames;
+ unsigned int s, t, num_snames, num_tnames;
struct type_set *ts;
for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) {
@@ -1257,9 +1257,9 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *
char *new_val = NULL;
char *val1 = NULL;
char *val2 = NULL;
- int num_params;
+ unsigned int num_params;
const char *op;
- const char *fmt_str;
+ const char *sep;
const char *type;
rc = stack_init(&stack);
@@ -1308,11 +1308,11 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *
rc = -1;
goto exit;
}
- fmt_str = "(%s %s)";
+ sep = "";
} else {
val2 = stack_pop(stack);
val1 = stack_pop(stack);
- fmt_str = "(%s %s %s)";
+ sep = " ";
}
if (val1 == NULL || val2 == NULL) {
@@ -1334,10 +1334,7 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *
goto exit;
}
- // although we always supply val2 and there isn't always a 2nd
- // value, it should only be used when there are actually two values
- // in the format strings
- rlen = snprintf(new_val, len, fmt_str, op, val1, val2);
+ rlen = snprintf(new_val, len, "(%s %s%s%s)", op, val1, sep, val2);
if (rlen < 0 || rlen >= len) {
log_err("Failed to generate conditional expression");
rc = -1;
@@ -1432,11 +1429,11 @@ static int role_trans_to_cil(int indent, struct policydb *pdb, struct role_trans
int rc = 0;
struct role_trans_rule *rule;
char **role_names = NULL;
- int num_role_names = 0;
- int role;
+ unsigned int num_role_names = 0;
+ unsigned int role;
char **type_names = NULL;
- int num_type_names = 0;
- int type;
+ unsigned int num_type_names = 0;
+ unsigned int type;
uint32_t i;
struct ebitmap_node *node;
struct type_set *ts;
@@ -1482,10 +1479,10 @@ static int role_allows_to_cil(int indent, struct policydb *pdb, struct role_allo
int rc = -1;
struct role_allow_rule *rule;
char **roles = NULL;
- int num_roles = 0;
+ unsigned int num_roles = 0;
char **new_roles = NULL;
- int num_new_roles = 0;
- int i,j;
+ unsigned int num_new_roles = 0;
+ unsigned int i, j;
struct role_set *rs;
for (rule = rules; rule != NULL; rule = rule->next) {
@@ -1525,11 +1522,11 @@ static int range_trans_to_cil(int indent, struct policydb *pdb, struct range_tra
int rc = -1;
struct range_trans_rule *rule;
char **stypes = NULL;
- int num_stypes = 0;
- int stype;
+ unsigned int num_stypes = 0;
+ unsigned int stype;
char **ttypes = NULL;
- int num_ttypes = 0;
- int ttype;
+ unsigned int num_ttypes = 0;
+ unsigned int ttype;
struct ebitmap_node *node;
uint32_t i;
struct type_set *ts;
@@ -1594,11 +1591,11 @@ static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filena
{
int rc = -1;
char **stypes = NULL;
- int num_stypes = 0;
- int stype;
+ unsigned int num_stypes = 0;
+ unsigned int stype;
char **ttypes = NULL;
- int num_ttypes = 0;
- int ttype;
+ unsigned int num_ttypes = 0;
+ unsigned int ttype;
struct type_set *ts;
struct filename_trans_rule *rule;
@@ -1711,12 +1708,12 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
char *val2 = NULL;
uint32_t num_params;
const char *op;
- const char *fmt_str;
+ const char *sep;
const char *attr1;
const char *attr2;
char *names = NULL;
char **name_list = NULL;
- int num_names = 0;
+ unsigned int num_names = 0;
struct type_set *ts;
rc = stack_init(&stack);
@@ -1745,7 +1742,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
case CEXPR_ROLE: attr1 = "r1"; attr2 = "r2"; break;
case CEXPR_ROLE | CEXPR_TARGET: attr1 = "r2"; attr2 = ""; break;
case CEXPR_ROLE | CEXPR_XTARGET: attr1 = "r3"; attr2 = ""; break;
- case CEXPR_TYPE: attr1 = "t1"; attr2 = ""; break;
+ case CEXPR_TYPE: attr1 = "t1"; attr2 = "t2"; break;
case CEXPR_TYPE | CEXPR_TARGET: attr1 = "t2"; attr2 = ""; break;
case CEXPR_TYPE | CEXPR_XTARGET: attr1 = "t3"; attr2 = ""; break;
case CEXPR_L1L2: attr1 = "l1"; attr2 = "l2"; break;
@@ -1793,20 +1790,31 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
goto exit;
}
}
- rc = name_list_to_string(name_list, num_names, &names);
- if (rc != 0) {
- goto exit;
+ if (num_names == 0) {
+ names = strdup("NO_IDENTIFIER");
+ } else {
+ rc = name_list_to_string(name_list, num_names, &names);
+ if (rc != 0) {
+ goto exit;
+ }
}
// length of values/oper + 2 spaces + 2 parens + null terminator
len = strlen(op) + strlen(attr1) + strlen(names) + 2 + 2 + 1;
+ if (num_names > 1) {
+ len += 2; // 2 more parens
+ }
new_val = malloc(len);
if (new_val == NULL) {
log_err("Out of memory");
rc = -1;
goto exit;
}
- rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names);
+ if (num_names > 1) {
+ rlen = snprintf(new_val, len, "(%s %s (%s))", op, attr1, names);
+ } else {
+ rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names);
+ }
if (rlen < 0 || rlen >= len) {
log_err("Failed to generate constraint expression");
rc = -1;
@@ -1838,11 +1846,11 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
rc = -1;
goto exit;
}
- fmt_str = "(%s %s)";
+ sep = "";
} else {
val2 = stack_pop(stack);
val1 = stack_pop(stack);
- fmt_str = "(%s %s %s)";
+ sep = " ";
}
if (val1 == NULL || val2 == NULL) {
@@ -1864,10 +1872,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
goto exit;
}
- // although we always supply val2 and there isn't always a 2nd
- // value, it should only be used when there are actually two values
- // in the format strings
- rlen = snprintf(new_val, len, fmt_str, op, val1, val2);
+ rlen = snprintf(new_val, len, "(%s %s%s%s)", op, val1, sep, val2);
if (rlen < 0 || rlen >= len) {
log_err("Failed to generate constraint expression");
rc = -1;
@@ -2069,7 +2074,7 @@ static int class_order_to_cil(int indent, struct policydb *pdb, struct ebitmap o
struct ebitmap_node *node;
uint32_t i;
- if (ebitmap_cardinality(&order) == 0) {
+ if (ebitmap_is_empty(&order)) {
return 0;
}
@@ -2090,9 +2095,9 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
int rc = -1;
struct ebitmap_node *node;
uint32_t i;
- int j;
+ unsigned int j;
char **types = NULL;
- int num_types = 0;
+ unsigned int num_types = 0;
struct role_datum *role = datum;
struct type_set *ts;
struct list *attr_list = NULL;
@@ -2175,7 +2180,7 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
cil_println(indent, "(roleattribute %s)", key);
}
- if (ebitmap_cardinality(&role->roles) > 0) {
+ if (!ebitmap_is_empty(&role->roles)) {
cil_indent(indent);
cil_printf("(roleattributeset %s (", key);
ebitmap_for_each_positive_bit(&role->roles, node, i) {
@@ -2269,7 +2274,7 @@ static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
cil_printf(")\n");
}
- if (ebitmap_cardinality(&type->types) > 0) {
+ if (!ebitmap_is_empty(&type->types)) {
cil_indent(indent);
cil_printf("(typeattributeset %s (", key);
ebitmap_to_cil(pdb, &type->types, SYM_TYPES);
@@ -2372,7 +2377,7 @@ static int sens_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN
}
}
- if (ebitmap_cardinality(&level->level->cat) > 0) {
+ if (!ebitmap_is_empty(&level->level->cat)) {
cil_indent(indent);
cil_printf("(sensitivitycategory %s (", key);
ebitmap_to_cil(pdb, &level->level->cat, SYM_CATS);
@@ -2387,7 +2392,7 @@ static int sens_order_to_cil(int indent, struct policydb *pdb, struct ebitmap or
struct ebitmap_node *node;
uint32_t i;
- if (ebitmap_cardinality(&order) == 0) {
+ if (ebitmap_is_empty(&order)) {
return 0;
}
@@ -2427,7 +2432,7 @@ static int cat_order_to_cil(int indent, struct policydb *pdb, struct ebitmap ord
struct ebitmap_node *node;
uint32_t i;
- if (ebitmap_cardinality(&order) == 0) {
+ if (ebitmap_is_empty(&order)) {
rc = 0;
goto exit;
}
@@ -2478,7 +2483,7 @@ static int level_to_cil(struct policydb *pdb, struct mls_level *level)
cil_printf("(%s", pdb->p_sens_val_to_name[level->sens - 1]);
- if (ebitmap_cardinality(map) > 0) {
+ if (!ebitmap_is_empty(map)) {
cil_printf("(");
ebitmap_to_cil(pdb, map, SYM_CATS);
cil_printf(")");
@@ -2657,8 +2662,7 @@ static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb,
if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
- log_err("ibpkeycon subnet_prefix is invalid: %s",
- strerror(errno));
+ log_err("ibpkeycon subnet_prefix is invalid: %m");
rc = -1;
goto exit;
}
@@ -2703,13 +2707,13 @@ static int ocontext_selinux_node_to_cil(struct policydb *pdb, struct ocontext *n
for (node = nodes; node != NULL; node = node->next) {
if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
- log_err("Nodecon address is invalid: %s", strerror(errno));
+ log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
- log_err("Nodecon mask is invalid: %s", strerror(errno));
+ log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2735,13 +2739,13 @@ static int ocontext_selinux_node6_to_cil(struct policydb *pdb, struct ocontext *
for (node = nodes; node != NULL; node = node->next) {
if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
- log_err("Nodecon address is invalid: %s", strerror(errno));
+ log_err("Nodecon address is invalid: %m");
rc = -1;
goto exit;
}
if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
- log_err("Nodecon mask is invalid: %s", strerror(errno));
+ log_err("Nodecon mask is invalid: %m");
rc = -1;
goto exit;
}
@@ -2951,10 +2955,35 @@ static int genfscon_to_cil(struct policydb *pdb)
{
struct genfs *genfs;
struct ocontext *ocon;
+ uint32_t sclass;
for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
- cil_printf("(genfscon %s %s ", genfs->fstype, ocon->u.name);
+ sclass = ocon->v.sclass;
+ if (sclass) {
+ const char *file_type;
+ const char *class_name = pdb->p_class_val_to_name[sclass-1];
+ if (strcmp(class_name, "file") == 0) {
+ file_type = "file";
+ } else if (strcmp(class_name, "dir") == 0) {
+ file_type = "dir";
+ } else if (strcmp(class_name, "chr_file") == 0) {
+ file_type = "char";
+ } else if (strcmp(class_name, "blk_file") == 0) {
+ file_type = "block";
+ } else if (strcmp(class_name, "sock_file") == 0) {
+ file_type = "socket";
+ } else if (strcmp(class_name, "fifo_file") == 0) {
+ file_type = "pipe";
+ } else if (strcmp(class_name, "lnk_file") == 0) {
+ file_type = "symlink";
+ } else {
+ return -1;
+ }
+ cil_printf("(genfscon %s \"%s\" %s ", genfs->fstype, ocon->u.name, file_type);
+ } else {
+ cil_printf("(genfscon %s \"%s\" ", genfs->fstype, ocon->u.name);
+ }
context_to_cil(pdb, &ocon->context[0]);
cil_printf(")\n");
}
@@ -3344,9 +3373,14 @@ static int typealiases_to_cil(int indent, struct policydb *pdb, struct avrule_bl
char *type_name;
struct list_node *curr;
struct avrule_decl *decl = stack_peek(decl_stack);
- struct list *alias_list = typealias_lists[decl->decl_id];
+ struct list *alias_list;
int rc = -1;
+ if (decl == NULL) {
+ return -1;
+ }
+
+ alias_list = typealias_lists[decl->decl_id];
if (alias_list == NULL) {
return 0;
}
@@ -3516,12 +3550,12 @@ exit:
static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack)
{
int rc = -1;
+ struct avrule_decl *decl = stack_peek(decl_stack);
struct map_args args;
args.pdb = pdb;
args.block = block;
args.decl_stack = decl_stack;
args.indent = indent;
- struct avrule_decl *decl = stack_peek(decl_stack);
for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) {
if (func_to_cil[args.sym_index] == NULL) {
@@ -3963,7 +3997,7 @@ int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked)
if (pdb->policy_type != SEPOL_POLICY_BASE &&
pdb->policy_type != SEPOL_POLICY_MOD) {
- log_err("Policy pakcage is not a base or module");
+ log_err("Policy package is not a base or module");
rc = -1;
goto exit;
}
@@ -4108,7 +4142,7 @@ exit:
static int fp_to_buffer(FILE *fp, char **data, size_t *data_len)
{
int rc = -1;
- char *d = NULL;
+ char *d = NULL, *d_tmp;
size_t d_len = 0;
size_t read_len = 0;
size_t max_len = 1 << 17; // start at 128KB, this is enough to hold about half of all the existing pp files
@@ -4124,12 +4158,13 @@ static int fp_to_buffer(FILE *fp, char **data, size_t *data_len)
d_len += read_len;
if (d_len == max_len) {
max_len *= 2;
- d = realloc(d, max_len);
- if (d == NULL) {
+ d_tmp = realloc(d, max_len);
+ if (d_tmp == NULL) {
log_err("Out of memory");
rc = -1;
goto exit;
}
+ d = d_tmp;
}
}
diff --git a/libsepol/src/node_internal.h b/libsepol/src/node_internal.h
index 802cda97..6d3c2505 100644
--- a/libsepol/src/node_internal.h
+++ b/libsepol/src/node_internal.h
@@ -3,24 +3,5 @@
#include <sepol/node_record.h>
#include <sepol/nodes.h>
-#include "dso.h"
-hidden_proto(sepol_node_create)
- hidden_proto(sepol_node_key_free)
- hidden_proto(sepol_node_free)
- hidden_proto(sepol_node_get_con)
- hidden_proto(sepol_node_get_addr)
- hidden_proto(sepol_node_get_addr_bytes)
- hidden_proto(sepol_node_get_mask)
- hidden_proto(sepol_node_get_mask_bytes)
- hidden_proto(sepol_node_get_proto)
- hidden_proto(sepol_node_get_proto_str)
- hidden_proto(sepol_node_key_create)
- hidden_proto(sepol_node_key_unpack)
- hidden_proto(sepol_node_set_con)
- hidden_proto(sepol_node_set_addr)
- hidden_proto(sepol_node_set_addr_bytes)
- hidden_proto(sepol_node_set_mask)
- hidden_proto(sepol_node_set_mask_bytes)
- hidden_proto(sepol_node_set_proto)
#endif
diff --git a/libsepol/src/node_record.c b/libsepol/src/node_record.c
index f3e78ff3..2e575bf1 100644
--- a/libsepol/src/node_record.c
+++ b/libsepol/src/node_record.c
@@ -53,7 +53,7 @@ static int node_parse_addr(sepol_handle_t * handle,
if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) {
ERR(handle, "could not parse IPv4 address "
- "%s: %s", addr_str, strerror(errno));
+ "%s: %m", addr_str);
return STATUS_ERR;
}
@@ -66,7 +66,7 @@ static int node_parse_addr(sepol_handle_t * handle,
if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) {
ERR(handle, "could not parse IPv6 address "
- "%s: %s", addr_str, strerror(errno));
+ "%s: %m", addr_str);
return STATUS_ERR;
}
@@ -147,8 +147,7 @@ static int node_expand_addr(sepol_handle_t * handle,
INET_ADDRSTRLEN) == NULL) {
ERR(handle,
- "could not expand IPv4 address to string: %s",
- strerror(errno));
+ "could not expand IPv4 address to string: %m");
return STATUS_ERR;
}
break;
@@ -163,8 +162,7 @@ static int node_expand_addr(sepol_handle_t * handle,
INET6_ADDRSTRLEN) == NULL) {
ERR(handle,
- "could not expand IPv6 address to string: %s",
- strerror(errno));
+ "could not expand IPv6 address to string: %m");
return STATUS_ERR;
}
break;
@@ -259,7 +257,6 @@ int sepol_node_key_create(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_node_key_create)
void sepol_node_key_unpack(const sepol_node_key_t * key,
const char **addr, const char **mask, int *proto)
@@ -270,7 +267,6 @@ void sepol_node_key_unpack(const sepol_node_key_t * key,
*proto = key->proto;
}
-hidden_def(sepol_node_key_unpack)
int sepol_node_key_extract(sepol_handle_t * handle,
const sepol_node_t * node,
@@ -314,7 +310,6 @@ void sepol_node_key_free(sepol_node_key_t * key)
free(key);
}
-hidden_def(sepol_node_key_free)
int sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key)
{
@@ -375,7 +370,6 @@ int sepol_node_get_addr(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_node_get_addr)
int sepol_node_get_addr_bytes(sepol_handle_t * handle,
const sepol_node_t * node,
@@ -394,7 +388,6 @@ int sepol_node_get_addr_bytes(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_node_get_addr_bytes)
int sepol_node_set_addr(sepol_handle_t * handle,
sepol_node_t * node, int proto, const char *addr)
@@ -420,7 +413,6 @@ int sepol_node_set_addr(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_node_set_addr)
int sepol_node_set_addr_bytes(sepol_handle_t * handle,
sepol_node_t * node,
@@ -440,7 +432,6 @@ int sepol_node_set_addr_bytes(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_node_set_addr_bytes)
/* Mask */
int sepol_node_get_mask(sepol_handle_t * handle,
@@ -464,7 +455,6 @@ int sepol_node_get_mask(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_node_get_mask)
int sepol_node_get_mask_bytes(sepol_handle_t * handle,
const sepol_node_t * node,
@@ -483,7 +473,6 @@ int sepol_node_get_mask_bytes(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_node_get_mask_bytes)
int sepol_node_set_mask(sepol_handle_t * handle,
sepol_node_t * node, int proto, const char *mask)
@@ -509,7 +498,6 @@ int sepol_node_set_mask(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_node_set_mask)
int sepol_node_set_mask_bytes(sepol_handle_t * handle,
sepol_node_t * node,
@@ -528,7 +516,6 @@ int sepol_node_set_mask_bytes(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_node_set_mask_bytes)
/* Protocol */
int sepol_node_get_proto(const sepol_node_t * node)
@@ -537,7 +524,6 @@ int sepol_node_get_proto(const sepol_node_t * node)
return node->proto;
}
-hidden_def(sepol_node_get_proto)
void sepol_node_set_proto(sepol_node_t * node, int proto)
{
@@ -545,7 +531,6 @@ void sepol_node_set_proto(sepol_node_t * node, int proto)
node->proto = proto;
}
-hidden_def(sepol_node_set_proto)
const char *sepol_node_get_proto_str(int proto)
{
@@ -560,7 +545,6 @@ const char *sepol_node_get_proto_str(int proto)
}
}
-hidden_def(sepol_node_get_proto_str)
/* Create */
int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node)
@@ -584,7 +568,6 @@ int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node)
return STATUS_SUCCESS;
}
-hidden_def(sepol_node_create)
/* Deep copy clone */
int sepol_node_clone(sepol_handle_t * handle,
@@ -637,7 +620,6 @@ void sepol_node_free(sepol_node_t * node)
free(node);
}
-hidden_def(sepol_node_free)
/* Context */
sepol_context_t *sepol_node_get_con(const sepol_node_t * node)
@@ -646,7 +628,6 @@ sepol_context_t *sepol_node_get_con(const sepol_node_t * node)
return node->con;
}
-hidden_def(sepol_node_get_con)
int sepol_node_set_con(sepol_handle_t * handle,
sepol_node_t * node, sepol_context_t * con)
@@ -664,4 +645,3 @@ int sepol_node_set_con(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_node_set_con)
diff --git a/libsepol/src/nodes.c b/libsepol/src/nodes.c
index 820346d0..97a0f959 100644
--- a/libsepol/src/nodes.c
+++ b/libsepol/src/nodes.c
@@ -19,20 +19,20 @@ static int node_from_record(sepol_handle_t * handle,
ocontext_t *tmp_node = NULL;
context_struct_t *tmp_con = NULL;
char *addr_buf = NULL, *mask_buf = NULL;
+ size_t addr_bsize, mask_bsize;
+ int proto;
tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
if (!tmp_node)
goto omem;
- size_t addr_bsize, mask_bsize;
-
/* Address and netmask */
if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
goto err;
if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
goto err;
- int proto = sepol_node_get_proto(data);
+ proto = sepol_node_get_proto(data);
switch (proto) {
case SEPOL_PROTO_IP4:
diff --git a/libsepol/src/optimize.c b/libsepol/src/optimize.c
index 1e5e97e8..93ff2116 100644
--- a/libsepol/src/optimize.c
+++ b/libsepol/src/optimize.c
@@ -31,28 +31,102 @@
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/conditional.h>
+#include "debug.h"
+#include "private.h"
+
+#define TYPE_VEC_INIT_SIZE 16
+
+struct type_vec {
+ uint32_t *types;
+ unsigned int count, capacity;
+};
+
+static int type_vec_init(struct type_vec *v)
+{
+ v->capacity = TYPE_VEC_INIT_SIZE;
+ v->count = 0;
+ v->types = mallocarray(v->capacity, sizeof(*v->types));
+ if (!v->types)
+ return -1;
+ return 0;
+}
+
+static void type_vec_destroy(struct type_vec *v)
+{
+ free(v->types);
+}
+
+static int type_vec_append(struct type_vec *v, uint32_t type)
+{
+ if (v->capacity == v->count) {
+ unsigned int new_capacity = v->capacity * 2;
+ uint32_t *new_types = reallocarray(v->types,
+ new_capacity,
+ sizeof(*v->types));
+ if (!new_types)
+ return -1;
+
+ v->types = new_types;
+ v->capacity = new_capacity;
+ }
+
+ v->types[v->count++] = type;
+ return 0;
+}
+
+static int type_vec_contains(const struct type_vec *v, uint32_t type)
+{
+ unsigned int s = 0, e = v->count;
+
+ while (s != e) {
+ unsigned int mid = (s + e) / 2;
+
+ if (v->types[mid] == type)
+ return 1;
+
+ if (v->types[mid] < type)
+ s = mid + 1;
+ else
+ e = mid;
+ }
+ return 0;
+}
+
/* builds map: type/attribute -> {all attributes that are a superset of it} */
-static ebitmap_t *build_type_map(const policydb_t *p)
+static struct type_vec *build_type_map(const policydb_t *p)
{
unsigned int i, k;
- ebitmap_t *map = malloc(p->p_types.nprim * sizeof(ebitmap_t));
+ ebitmap_node_t *n;
+ struct type_vec *map = mallocarray(p->p_types.nprim, sizeof(*map));
if (!map)
return NULL;
for (i = 0; i < p->p_types.nprim; i++) {
- if (p->type_val_to_struct[i] &&
- p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) {
- if (ebitmap_cpy(&map[i], &p->type_attr_map[i]))
- goto err;
+ if (type_vec_init(&map[i]))
+ goto err;
+
+ if (!p->type_val_to_struct[i])
+ continue;
+
+ if (p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) {
+ ebitmap_for_each_positive_bit(&p->type_attr_map[i],
+ n, k) {
+ if (type_vec_append(&map[i], k))
+ goto err;
+ }
} else {
ebitmap_t *types_i = &p->attr_type_map[i];
- ebitmap_init(&map[i]);
for (k = 0; k < p->p_types.nprim; k++) {
- ebitmap_t *types_k = &p->attr_type_map[k];
+ const ebitmap_t *types_k;
+
+ if (!p->type_val_to_struct[k] || p->type_val_to_struct[k]->flavor != TYPE_ATTRIB)
+ continue;
+
+ types_k = &p->attr_type_map[k];
if (ebitmap_contains(types_k, types_i)) {
- if (ebitmap_set_bit(&map[i], k, 1))
+ if (type_vec_append(&map[i], k))
goto err;
}
}
@@ -61,16 +135,16 @@ static ebitmap_t *build_type_map(const policydb_t *p)
return map;
err:
for (k = 0; k <= i; k++)
- ebitmap_destroy(&map[k]);
+ type_vec_destroy(&map[k]);
free(map);
return NULL;
}
-static void destroy_type_map(const policydb_t *p, ebitmap_t *type_map)
+static void destroy_type_map(const policydb_t *p, struct type_vec *type_map)
{
unsigned int i;
for (i = 0; i < p->p_types.nprim; i++)
- ebitmap_destroy(&type_map[i]);
+ type_vec_destroy(&type_map[i]);
free(type_map);
}
@@ -123,10 +197,11 @@ static int process_avtab_datum(uint16_t specified,
/* checks if avtab contains a rule that covers the given rule */
static int is_avrule_redundant(avtab_ptr_t entry, avtab_t *tab,
- const ebitmap_t *type_map, unsigned char not_cond)
+ const struct type_vec *type_map,
+ unsigned char not_cond)
{
unsigned int i, k, s_idx, t_idx;
- ebitmap_node_t *snode, *tnode;
+ uint32_t st, tt;
avtab_datum_t *d1, *d2;
avtab_key_t key;
@@ -142,14 +217,17 @@ static int is_avrule_redundant(avtab_ptr_t entry, avtab_t *tab,
d1 = &entry->datum;
- ebitmap_for_each_positive_bit(&type_map[s_idx], snode, i) {
- key.source_type = i + 1;
+ for (i = 0; i < type_map[s_idx].count; i++) {
+ st = type_map[s_idx].types[i];
+ key.source_type = st + 1;
- ebitmap_for_each_positive_bit(&type_map[t_idx], tnode, k) {
- if (not_cond && s_idx == i && t_idx == k)
+ for (k = 0; k < type_map[t_idx].count; k++) {
+ tt = type_map[t_idx].types[k];
+
+ if (not_cond && s_idx == st && t_idx == tt)
continue;
- key.target_type = k + 1;
+ key.target_type = tt + 1;
d2 = avtab_search(tab, &key);
if (!d2)
@@ -177,7 +255,7 @@ static int is_avrule_with_attr(avtab_ptr_t entry, policydb_t *p)
/* checks if conditional list contains a rule that covers the given rule */
static int is_cond_rule_redundant(avtab_ptr_t e1, cond_av_list_t *list,
- const ebitmap_t *type_map)
+ const struct type_vec *type_map)
{
unsigned int s1, t1, c1, k1, s2, t2, c2, k2;
@@ -203,9 +281,9 @@ static int is_cond_rule_redundant(avtab_ptr_t e1, cond_av_list_t *list,
if (s1 == s2 && t1 == t2)
continue;
- if (!ebitmap_get_bit(&type_map[s1], s2))
+ if (!type_vec_contains(&type_map[s1], s2))
continue;
- if (!ebitmap_get_bit(&type_map[t1], t2))
+ if (!type_vec_contains(&type_map[t1], t2))
continue;
if (process_avtab_datum(k1, &e1->datum, &e2->datum))
@@ -214,7 +292,7 @@ static int is_cond_rule_redundant(avtab_ptr_t e1, cond_av_list_t *list,
return 0;
}
-static void optimize_avtab(policydb_t *p, const ebitmap_t *type_map)
+static void optimize_avtab(policydb_t *p, const struct type_vec *type_map)
{
avtab_t *tab = &p->te_avtab;
unsigned int i;
@@ -243,7 +321,7 @@ static void optimize_avtab(policydb_t *p, const ebitmap_t *type_map)
/* find redundant rules in (*cond) and put them into (*del) */
static void optimize_cond_av_list(cond_av_list_t **cond, cond_av_list_t **del,
- policydb_t *p, const ebitmap_t *type_map)
+ policydb_t *p, const struct type_vec *type_map)
{
cond_av_list_t **listp = cond;
cond_av_list_t *pcov = NULL;
@@ -292,7 +370,7 @@ static void optimize_cond_av_list(cond_av_list_t **cond, cond_av_list_t **del,
}
}
-static void optimize_cond_avtab(policydb_t *p, const ebitmap_t *type_map)
+static void optimize_cond_avtab(policydb_t *p, const struct type_vec *type_map)
{
avtab_t *tab = &p->te_cond_avtab;
unsigned int i;
@@ -361,11 +439,22 @@ static void optimize_cond_avtab(policydb_t *p, const ebitmap_t *type_map)
int policydb_optimize(policydb_t *p)
{
- ebitmap_t *type_map;
+ struct type_vec *type_map;
if (p->policy_type != POLICY_KERN)
return -1;
+ if (p->policyvers >= POLICYDB_VERSION_AVTAB && p->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but only in the type_attr_map. This means that there are gaps in both
+ * the type_val_to_struct and p_type_val_to_name arrays and policy rules
+ * can refer to those gaps.
+ */
+ ERR(NULL, "Optimizing policy versions between 20 and 23 is not supported");
+ return -1;
+ }
+
type_map = build_type_map(p);
if (!type_map)
return -1;
diff --git a/libsepol/src/polcaps.c b/libsepol/src/polcaps.c
index 67ed5786..687e971c 100644
--- a/libsepol/src/polcaps.c
+++ b/libsepol/src/polcaps.c
@@ -5,14 +5,15 @@
#include <string.h>
#include <sepol/policydb/polcaps.h>
-static const char *polcap_names[] = {
- "network_peer_controls", /* POLICYDB_CAPABILITY_NETPEER */
- "open_perms", /* POLICYDB_CAPABILITY_OPENPERM */
- "extended_socket_class", /* POLICYDB_CAPABILITY_EXTSOCKCLASS */
- "always_check_network", /* POLICYDB_CAPABILITY_ALWAYSNETWORK */
- "cgroup_seclabel", /* POLICYDB_CAPABILITY_SECLABEL */
- "nnp_nosuid_transition", /* POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION */
- "genfs_seclabel_symlinks", /* POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS */
+static const char * const polcap_names[] = {
+ "network_peer_controls", /* POLICYDB_CAP_NETPEER */
+ "open_perms", /* POLICYDB_CAP_OPENPERM */
+ "extended_socket_class", /* POLICYDB_CAP_EXTSOCKCLASS */
+ "always_check_network", /* POLICYDB_CAP_ALWAYSNETWORK */
+ "cgroup_seclabel", /* POLICYDB_CAP_SECLABEL */
+ "nnp_nosuid_transition", /* POLICYDB_CAP_NNP_NOSUID_TRANSITION */
+ "genfs_seclabel_symlinks", /* POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS */
+ "ioctl_skip_cloexec", /* POLICYDB_CAP_IOCTL_SKIP_CLOEXEC */
NULL
};
@@ -20,7 +21,7 @@ int sepol_polcap_getnum(const char *name)
{
int capnum;
- for (capnum = 0; capnum <= POLICYDB_CAPABILITY_MAX; capnum++) {
+ for (capnum = 0; capnum <= POLICYDB_CAP_MAX; capnum++) {
if (polcap_names[capnum] == NULL)
continue;
if (strcasecmp(polcap_names[capnum], name) == 0)
@@ -31,7 +32,7 @@ int sepol_polcap_getnum(const char *name)
const char *sepol_polcap_getname(unsigned int capnum)
{
- if (capnum > POLICYDB_CAPABILITY_MAX)
+ if (capnum > POLICYDB_CAP_MAX)
return NULL;
return polcap_names[capnum];
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 2c69a609..fc71463e 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -49,18 +49,18 @@
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/avrule_block.h>
#include <sepol/policydb/util.h>
-#include <sepol/policydb/flask.h>
#include "kernel_to_common.h"
#include "private.h"
#include "debug.h"
#include "mls.h"
+#include "policydb_validate.h"
#define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings)
-const char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
+const char * const policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
/* These need to be updated if SYM_NUM or OCON_NUM changes */
-static struct policydb_compat_info policydb_compat[] = {
+static const struct policydb_compat_info policydb_compat[] = {
{
.type = POLICY_KERN,
.version = POLICYDB_VERSION_BOUNDARY,
@@ -202,6 +202,13 @@ static struct policydb_compat_info policydb_compat[] = {
.target_platform = SEPOL_TARGET_SELINUX,
},
{
+ .type = POLICY_KERN,
+ .version = POLICYDB_VERSION_COMP_FTRANS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_IBENDPORT + 1,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
+ {
.type = POLICY_BASE,
.version = MOD_POLICYDB_VERSION_BASE,
.sym_num = SYM_NUM,
@@ -453,7 +460,7 @@ static char *symtab_name[SYM_NUM] = {
};
#endif
-static unsigned int symtab_sizes[SYM_NUM] = {
+static const unsigned int symtab_sizes[SYM_NUM] = {
2,
32,
16,
@@ -464,12 +471,12 @@ static unsigned int symtab_sizes[SYM_NUM] = {
16,
};
-struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
- unsigned int type,
- unsigned int target_platform)
+const struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
+ unsigned int type,
+ unsigned int target_platform)
{
unsigned int i;
- struct policydb_compat_info *info = NULL;
+ const struct policydb_compat_info *info = NULL;
for (i = 0; i < sizeof(policydb_compat) / sizeof(*info); i++) {
if (policydb_compat[i].version == version &&
@@ -628,7 +635,7 @@ void role_trans_rule_init(role_trans_rule_t * x)
ebitmap_init(&x->classes);
}
-void role_trans_rule_destroy(role_trans_rule_t * x)
+static void role_trans_rule_destroy(role_trans_rule_t * x)
{
if (x != NULL) {
role_set_destroy(&x->roles);
@@ -782,6 +789,7 @@ static int roles_init(policydb_t * p)
goto out;
}
+ignore_unsigned_overflow_
static inline unsigned long
partial_name_hash(unsigned long c, unsigned long prevhash)
{
@@ -790,12 +798,12 @@ partial_name_hash(unsigned long c, unsigned long prevhash)
static unsigned int filenametr_hash(hashtab_t h, const_hashtab_key_t k)
{
- const struct filename_trans *ft = (const struct filename_trans *)k;
+ const filename_trans_key_t *ft = (const filename_trans_key_t *)k;
unsigned long hash;
unsigned int byte_num;
unsigned char focus;
- hash = ft->stype ^ ft->ttype ^ ft->tclass;
+ hash = ft->ttype ^ ft->tclass;
byte_num = 0;
while ((focus = ft->name[byte_num++]))
@@ -806,19 +814,15 @@ static unsigned int filenametr_hash(hashtab_t h, const_hashtab_key_t k)
static int filenametr_cmp(hashtab_t h __attribute__ ((unused)),
const_hashtab_key_t k1, const_hashtab_key_t k2)
{
- const struct filename_trans *ft1 = (const struct filename_trans *)k1;
- const struct filename_trans *ft2 = (const struct filename_trans *)k2;
+ const filename_trans_key_t *ft1 = (const filename_trans_key_t *)k1;
+ const filename_trans_key_t *ft2 = (const filename_trans_key_t *)k2;
int v;
- v = ft1->stype - ft2->stype;
+ v = spaceship_cmp(ft1->ttype, ft2->ttype);
if (v)
return v;
- v = ft1->ttype - ft2->ttype;
- if (v)
- return v;
-
- v = ft1->tclass - ft2->tclass;
+ v = spaceship_cmp(ft1->tclass, ft2->tclass);
if (v)
return v;
@@ -840,15 +844,15 @@ static int rangetr_cmp(hashtab_t h __attribute__ ((unused)),
const struct range_trans *key2 = (const struct range_trans *)k2;
int v;
- v = key1->source_type - key2->source_type;
+ v = spaceship_cmp(key1->source_type, key2->source_type);
if (v)
return v;
- v = key1->target_type - key2->target_type;
+ v = spaceship_cmp(key1->target_type, key2->target_type);
if (v)
return v;
- v = key1->target_class - key2->target_class;
+ v = spaceship_cmp(key1->target_class, key2->target_class);
return v;
}
@@ -991,7 +995,7 @@ static int common_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
comdatum = (common_datum_t *) datum;
p = (policydb_t *) datap;
- if (!comdatum->s.value || comdatum->s.value > p->p_commons.nprim)
+ if (!value_isvalid(comdatum->s.value, p->p_commons.nprim))
return -EINVAL;
if (p->p_common_val_to_name[comdatum->s.value - 1] != NULL)
return -EINVAL;
@@ -1007,7 +1011,7 @@ static int class_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
cladatum = (class_datum_t *) datum;
p = (policydb_t *) datap;
- if (!cladatum->s.value || cladatum->s.value > p->p_classes.nprim)
+ if (!value_isvalid(cladatum->s.value, p->p_classes.nprim))
return -EINVAL;
if (p->p_class_val_to_name[cladatum->s.value - 1] != NULL)
return -EINVAL;
@@ -1024,7 +1028,7 @@ static int role_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
role = (role_datum_t *) datum;
p = (policydb_t *) datap;
- if (!role->s.value || role->s.value > p->p_roles.nprim)
+ if (!value_isvalid(role->s.value, p->p_roles.nprim))
return -EINVAL;
if (p->p_role_val_to_name[role->s.value - 1] != NULL)
return -EINVAL;
@@ -1043,7 +1047,7 @@ static int type_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
p = (policydb_t *) datap;
if (typdatum->primary) {
- if (!typdatum->s.value || typdatum->s.value > p->p_types.nprim)
+ if (!value_isvalid(typdatum->s.value, p->p_types.nprim))
return -EINVAL;
if (p->p_type_val_to_name[typdatum->s.value - 1] != NULL)
return -EINVAL;
@@ -1062,7 +1066,7 @@ static int user_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
usrdatum = (user_datum_t *) datum;
p = (policydb_t *) datap;
- if (!usrdatum->s.value || usrdatum->s.value > p->p_users.nprim)
+ if (!value_isvalid(usrdatum->s.value, p->p_users.nprim))
return -EINVAL;
if (p->p_user_val_to_name[usrdatum->s.value - 1] != NULL)
return -EINVAL;
@@ -1081,8 +1085,7 @@ static int sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
p = (policydb_t *) datap;
if (!levdatum->isalias) {
- if (!levdatum->level->sens ||
- levdatum->level->sens > p->p_levels.nprim)
+ if (!value_isvalid(levdatum->level->sens, p->p_levels.nprim))
return -EINVAL;
if (p->p_sens_val_to_name[levdatum->level->sens - 1] != NULL)
return -EINVAL;
@@ -1101,7 +1104,7 @@ static int cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap)
p = (policydb_t *) datap;
if (!catdatum->isalias) {
- if (!catdatum->s.value || catdatum->s.value > p->p_cats.nprim)
+ if (!value_isvalid(catdatum->s.value, p->p_cats.nprim))
return -EINVAL;
if (p->p_cat_val_to_name[catdatum->s.value - 1] != NULL)
return -EINVAL;
@@ -1164,7 +1167,7 @@ int policydb_index_bools(policydb_t * p)
return 0;
}
-int policydb_index_decls(sepol_handle_t * handle, policydb_t * p)
+static int policydb_index_decls(sepol_handle_t * handle, policydb_t * p)
{
avrule_block_t *curblock;
avrule_decl_t *decl;
@@ -1188,7 +1191,7 @@ int policydb_index_decls(sepol_handle_t * handle, policydb_t * p)
for (curblock = p->global; curblock != NULL; curblock = curblock->next) {
for (decl = curblock->branch_list; decl != NULL;
decl = decl->next) {
- if (decl->decl_id < 1 || decl->decl_id > num_decls) {
+ if (!value_isvalid(decl->decl_id, num_decls)) {
ERR(handle, "invalid decl ID %u", decl->decl_id);
return -1;
}
@@ -1308,7 +1311,6 @@ static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
{
class_datum_t *cladatum;
constraint_node_t *constraint, *ctemp;
- constraint_expr_t *e, *etmp;
if (key)
free(key);
@@ -1320,12 +1322,7 @@ static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
hashtab_destroy(cladatum->permissions.table);
constraint = cladatum->constraints;
while (constraint) {
- e = constraint->expr;
- while (e) {
- etmp = e;
- e = e->next;
- constraint_expr_destroy(etmp);
- }
+ constraint_expr_destroy(constraint->expr);
ctemp = constraint;
constraint = constraint->next;
free(ctemp);
@@ -1333,12 +1330,7 @@ static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
constraint = cladatum->validatetrans;
while (constraint) {
- e = constraint->expr;
- while (e) {
- etmp = e;
- e = e->next;
- constraint_expr_destroy(etmp);
- }
+ constraint_expr_destroy(constraint->expr);
ctemp = constraint;
constraint = constraint->next;
free(ctemp);
@@ -1410,10 +1402,17 @@ common_destroy, class_destroy, role_destroy, type_destroy, user_destroy,
static int filenametr_destroy(hashtab_key_t key, hashtab_datum_t datum,
void *p __attribute__ ((unused)))
{
- struct filename_trans *ft = (struct filename_trans *)key;
+ filename_trans_key_t *ft = (filename_trans_key_t *)key;
+ filename_trans_datum_t *fd = datum, *next;
+
free(ft->name);
free(key);
- free(datum);
+ do {
+ next = fd->next;
+ ebitmap_destroy(&fd->stypes);
+ free(fd);
+ fd = next;
+ } while (fd);
return 0;
}
@@ -1428,7 +1427,7 @@ static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum,
return 0;
}
-void ocontext_selinux_free(ocontext_t **ocontexts)
+static void ocontext_selinux_free(ocontext_t **ocontexts)
{
ocontext_t *c, *ctmp;
int i;
@@ -1450,7 +1449,7 @@ void ocontext_selinux_free(ocontext_t **ocontexts)
}
}
-void ocontext_xen_free(ocontext_t **ocontexts)
+static void ocontext_xen_free(ocontext_t **ocontexts)
{
ocontext_t *c, *ctmp;
int i;
@@ -1749,7 +1748,7 @@ int symtab_insert(policydb_t * pol, uint32_t sym,
return retval;
}
-int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
+static int type_set_or(type_set_t * dst, const type_set_t * a, const type_set_t * b)
{
type_set_init(dst);
@@ -1766,7 +1765,7 @@ int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b)
return 0;
}
-int type_set_cpy(type_set_t * dst, type_set_t * src)
+int type_set_cpy(type_set_t * dst, const type_set_t * src)
{
type_set_init(dst);
@@ -1779,7 +1778,7 @@ int type_set_cpy(type_set_t * dst, type_set_t * src)
return 0;
}
-int type_set_or_eq(type_set_t * dst, type_set_t * other)
+int type_set_or_eq(type_set_t * dst, const type_set_t * other)
{
int ret;
type_set_t tmp;
@@ -1793,24 +1792,6 @@ int type_set_or_eq(type_set_t * dst, type_set_t * other)
return ret;
}
-int role_set_get_role(role_set_t * x, uint32_t role)
-{
- if (x->flags & ROLE_STAR)
- return 1;
-
- if (ebitmap_get_bit(&x->roles, role - 1)) {
- if (x->flags & ROLE_COMP)
- return 0;
- else
- return 1;
- } else {
- if (x->flags & ROLE_COMP)
- return 1;
- else
- return 0;
- }
-}
-
/***********************************************************************/
/* everything below is for policy reads */
@@ -2062,7 +2043,7 @@ static int context_read_and_validate(context_struct_t * c,
static int perm_read(policydb_t * p
__attribute__ ((unused)), hashtab_t h,
- struct policy_file *fp)
+ struct policy_file *fp, uint32_t nprim)
{
char *key = 0;
perm_datum_t *perdatum;
@@ -2083,6 +2064,8 @@ static int perm_read(policydb_t * p
goto bad;
perdatum->s.value = le32_to_cpu(buf[1]);
+ if (!value_isvalid(perdatum->s.value, nprim))
+ goto bad;
if (hashtab_insert(h, key, perdatum))
goto bad;
@@ -2120,6 +2103,8 @@ static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE))
goto bad;
comdatum->permissions.nprim = le32_to_cpu(buf[2]);
+ if (comdatum->permissions.nprim > PERM_SYMTAB_SIZE)
+ goto bad;
nel = le32_to_cpu(buf[3]);
key = malloc(len + 1);
@@ -2131,7 +2116,7 @@ static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
key[len] = 0;
for (i = 0; i < nel; i++) {
- if (perm_read(p, comdatum->permissions.table, fp))
+ if (perm_read(p, comdatum->permissions.table, fp, comdatum->permissions.nprim))
goto bad;
}
@@ -2268,6 +2253,8 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE))
goto bad;
cladatum->permissions.nprim = le32_to_cpu(buf[3]);
+ if (cladatum->permissions.nprim > PERM_SYMTAB_SIZE)
+ goto bad;
nel = le32_to_cpu(buf[4]);
ncons = le32_to_cpu(buf[5]);
@@ -2297,7 +2284,7 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
}
}
for (i = 0; i < nel; i++) {
- if (perm_read(p, cladatum->permissions.table, fp))
+ if (perm_read(p, cladatum->permissions.table, fp, cladatum->permissions.nprim))
goto bad;
}
@@ -2521,7 +2508,7 @@ static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp)
return -1;
}
-int role_trans_read(policydb_t *p, struct policy_file *fp)
+static int role_trans_read(policydb_t *p, struct policy_file *fp)
{
role_trans_t **t = &p->role_tr;
unsigned int i;
@@ -2558,13 +2545,13 @@ int role_trans_read(policydb_t *p, struct policy_file *fp)
return -1;
tr->tclass = le32_to_cpu(buf[0]);
} else
- tr->tclass = SECCLASS_PROCESS;
+ tr->tclass = p->process_class;
ltr = tr;
}
return 0;
}
-int role_allow_read(role_allow_t ** r, struct policy_file *fp)
+static int role_allow_read(role_allow_t ** r, struct policy_file *fp)
{
unsigned int i;
uint32_t buf[2], nel;
@@ -2596,90 +2583,280 @@ int role_allow_read(role_allow_t ** r, struct policy_file *fp)
return 0;
}
-int filename_trans_read(policydb_t *p, struct policy_file *fp)
+int policydb_filetrans_insert(policydb_t *p, uint32_t stype, uint32_t ttype,
+ uint32_t tclass, const char *name,
+ char **name_alloc, uint32_t otype,
+ uint32_t *present_otype)
{
- unsigned int i;
- uint32_t buf[4], nel, len;
- filename_trans_t *ft;
- filename_trans_datum_t *otype;
+ filename_trans_key_t *ft, key;
+ filename_trans_datum_t *datum, *last;
+
+ key.ttype = ttype;
+ key.tclass = tclass;
+ key.name = (char *)name;
+
+ last = NULL;
+ datum = hashtab_search(p->filename_trans, (hashtab_key_t)&key);
+ while (datum) {
+ if (ebitmap_get_bit(&datum->stypes, stype - 1)) {
+ if (present_otype)
+ *present_otype = datum->otype;
+ return SEPOL_EEXIST;
+ }
+ if (datum->otype == otype)
+ break;
+ last = datum;
+ datum = datum->next;
+ }
+ if (!datum) {
+ datum = malloc(sizeof(*datum));
+ if (!datum)
+ return SEPOL_ENOMEM;
+
+ ebitmap_init(&datum->stypes);
+ datum->otype = otype;
+ datum->next = NULL;
+
+ if (last) {
+ last->next = datum;
+ } else {
+ char *name_dup;
+
+ if (name_alloc) {
+ name_dup = *name_alloc;
+ *name_alloc = NULL;
+ } else {
+ name_dup = strdup(name);
+ if (!name_dup) {
+ free(datum);
+ return SEPOL_ENOMEM;
+ }
+ }
+
+ ft = malloc(sizeof(*ft));
+ if (!ft) {
+ free(name_dup);
+ free(datum);
+ return SEPOL_ENOMEM;
+ }
+
+ ft->ttype = ttype;
+ ft->tclass = tclass;
+ ft->name = name_dup;
+
+ if (hashtab_insert(p->filename_trans, (hashtab_key_t)ft,
+ (hashtab_datum_t)datum)) {
+ free(name_dup);
+ free(datum);
+ free(ft);
+ return SEPOL_ENOMEM;
+ }
+ }
+ }
+
+ p->filename_trans_count++;
+ return ebitmap_set_bit(&datum->stypes, stype - 1, 1);
+}
+
+static int filename_trans_read_one_compat(policydb_t *p, struct policy_file *fp)
+{
+ uint32_t buf[4], len, stype, ttype, tclass, otype;
+ char *name = NULL;
int rc;
- char *name;
rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
return -1;
- nel = le32_to_cpu(buf[0]);
+ len = le32_to_cpu(buf[0]);
+ if (zero_or_saturated(len))
+ return -1;
- for (i = 0; i < nel; i++) {
- ft = NULL;
- otype = NULL;
- name = NULL;
+ name = calloc(len + 1, sizeof(*name));
+ if (!name)
+ return -1;
- ft = calloc(1, sizeof(*ft));
- if (!ft)
- goto err;
- otype = calloc(1, sizeof(*otype));
- if (!otype)
- goto err;
- rc = next_entry(buf, fp, sizeof(uint32_t));
- if (rc < 0)
- goto err;
- len = le32_to_cpu(buf[0]);
- if (zero_or_saturated(len))
+ rc = next_entry(name, fp, len);
+ if (rc < 0)
+ goto err;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t) * 4);
+ if (rc < 0)
+ goto err;
+
+ stype = le32_to_cpu(buf[0]);
+ if (stype == 0)
+ goto err;
+
+ ttype = le32_to_cpu(buf[1]);
+ tclass = le32_to_cpu(buf[2]);
+ otype = le32_to_cpu(buf[3]);
+
+ rc = policydb_filetrans_insert(p, stype, ttype, tclass, name, &name,
+ otype, NULL);
+ if (rc) {
+ if (rc != SEPOL_EEXIST)
goto err;
+ /*
+ * Some old policies were wrongly generated with
+ * duplicate filename transition rules. For backward
+ * compatibility, do not reject such policies, just
+ * ignore the duplicate.
+ */
+ }
+ free(name);
+ return 0;
+err:
+ free(name);
+ return -1;
+}
+
+static int filename_trans_check_datum(filename_trans_datum_t *datum)
+{
+ ebitmap_t stypes, otypes;
+ int rc = -1;
+
+ ebitmap_init(&stypes);
+ ebitmap_init(&otypes);
+
+ while (datum) {
+ if (ebitmap_get_bit(&otypes, datum->otype))
+ goto out;
+
+ if (ebitmap_set_bit(&otypes, datum->otype, 1))
+ goto out;
+
+ if (ebitmap_match_any(&stypes, &datum->stypes))
+ goto out;
+
+ if (ebitmap_union(&stypes, &datum->stypes))
+ goto out;
+
+ datum = datum->next;
+ }
+ rc = 0;
+out:
+ ebitmap_destroy(&stypes);
+ ebitmap_destroy(&otypes);
+ return rc;
+}
+
+static int filename_trans_read_one(policydb_t *p, struct policy_file *fp)
+{
+ filename_trans_key_t *ft = NULL;
+ filename_trans_datum_t **dst, *datum, *first = NULL;
+ unsigned int i;
+ uint32_t buf[3], len, ttype, tclass, ndatum;
+ char *name = NULL;
+ int rc;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ len = le32_to_cpu(buf[0]);
+ if (zero_or_saturated(len))
+ return -1;
+
+ name = calloc(len + 1, sizeof(*name));
+ if (!name)
+ return -1;
+
+ rc = next_entry(name, fp, len);
+ if (rc < 0)
+ goto err;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
+ if (rc < 0)
+ goto err;
- name = calloc(len + 1, sizeof(*name));
- if (!name)
+ ttype = le32_to_cpu(buf[0]);
+ tclass = le32_to_cpu(buf[1]);
+ ndatum = le32_to_cpu(buf[2]);
+ if (ndatum == 0)
+ goto err;
+
+ dst = &first;
+ for (i = 0; i < ndatum; i++) {
+ datum = malloc(sizeof(*datum));
+ if (!datum)
goto err;
- ft->name = name;
+ datum->next = NULL;
+ *dst = datum;
- rc = next_entry(name, fp, len);
+ /* ebitmap_read() will at least init the bitmap */
+ rc = ebitmap_read(&datum->stypes, fp);
if (rc < 0)
goto err;
- rc = next_entry(buf, fp, sizeof(uint32_t) * 4);
+ rc = next_entry(buf, fp, sizeof(uint32_t));
if (rc < 0)
goto err;
- ft->stype = le32_to_cpu(buf[0]);
- ft->ttype = le32_to_cpu(buf[1]);
- ft->tclass = le32_to_cpu(buf[2]);
- otype->otype = le32_to_cpu(buf[3]);
+ datum->otype = le32_to_cpu(buf[0]);
- rc = hashtab_insert(p->filename_trans, (hashtab_key_t) ft,
- otype);
- if (rc) {
- if (rc != SEPOL_EEXIST)
- goto err;
- /*
- * Some old policies were wrongly generated with
- * duplicate filename transition rules. For backward
- * compatibility, do not reject such policies, just
- * issue a warning and ignore the duplicate.
- */
- WARN(fp->handle,
- "Duplicate name-based type_transition %s %s:%s \"%s\": %s, ignoring",
- p->p_type_val_to_name[ft->stype - 1],
- p->p_type_val_to_name[ft->ttype - 1],
- p->p_class_val_to_name[ft->tclass - 1],
- ft->name,
- p->p_type_val_to_name[otype->otype - 1]);
- free(ft);
- free(name);
- free(otype);
- /* continue, ignoring this one */
- }
+ p->filename_trans_count += ebitmap_cardinality(&datum->stypes);
+
+ dst = &datum->next;
}
+
+ if (ndatum > 1 && filename_trans_check_datum(first))
+ goto err;
+
+ ft = malloc(sizeof(*ft));
+ if (!ft)
+ goto err;
+
+ ft->ttype = ttype;
+ ft->tclass = tclass;
+ ft->name = name;
+
+ rc = hashtab_insert(p->filename_trans, (hashtab_key_t)ft,
+ (hashtab_datum_t)first);
+ if (rc)
+ goto err;
+
return 0;
err:
free(ft);
- free(otype);
free(name);
+ while (first) {
+ datum = first;
+ first = first->next;
+
+ ebitmap_destroy(&datum->stypes);
+ free(datum);
+ }
return -1;
}
-static int ocontext_read_xen(struct policydb_compat_info *info,
+static int filename_trans_read(policydb_t *p, struct policy_file *fp)
+{
+ unsigned int i;
+ uint32_t buf[1], nel;
+ int rc;
+
+ rc = next_entry(buf, fp, sizeof(uint32_t));
+ if (rc < 0)
+ return -1;
+ nel = le32_to_cpu(buf[0]);
+
+ if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
+ for (i = 0; i < nel; i++) {
+ rc = filename_trans_read_one_compat(p, fp);
+ if (rc < 0)
+ return -1;
+ }
+ } else {
+ for (i = 0; i < nel; i++) {
+ rc = filename_trans_read_one(p, fp);
+ if (rc < 0)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int ocontext_read_xen(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
unsigned int i, j;
@@ -2709,6 +2886,8 @@ static int ocontext_read_xen(struct policydb_compat_info *info,
if (rc < 0)
return -1;
c->sid[0] = le32_to_cpu(buf[0]);
+ if (is_saturated(c->sid[0]))
+ return -1;
if (context_read_and_validate
(&c->context[0], p, fp))
return -1;
@@ -2788,7 +2967,7 @@ static int ocontext_read_xen(struct policydb_compat_info *info,
}
return 0;
}
-static int ocontext_read_selinux(struct policydb_compat_info *info,
+static int ocontext_read_selinux(const struct policydb_compat_info *info,
policydb_t * p, struct policy_file *fp)
{
unsigned int i, j;
@@ -2820,6 +2999,8 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
if (rc < 0)
return -1;
c->sid[0] = le32_to_cpu(buf[0]);
+ if (is_saturated(c->sid[0]))
+ return -1;
if (context_read_and_validate
(&c->context[0], p, fp))
return -1;
@@ -2966,7 +3147,7 @@ static int ocontext_read_selinux(struct policydb_compat_info *info,
return 0;
}
-static int ocontext_read(struct policydb_compat_info *info,
+static int ocontext_read(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
int rc = -1;
@@ -3446,14 +3627,20 @@ static int range_read(policydb_t * p, struct policy_file *fp)
if (rc < 0)
goto err;
rt->source_type = le32_to_cpu(buf[0]);
+ if (!value_isvalid(rt->source_type, p->p_types.nprim))
+ goto err;
rt->target_type = le32_to_cpu(buf[1]);
+ if (!value_isvalid(rt->target_type, p->p_types.nprim))
+ goto err;
if (new_rangetr) {
rc = next_entry(buf, fp, (sizeof(uint32_t)));
if (rc < 0)
goto err;
rt->target_class = le32_to_cpu(buf[0]);
+ if (!value_isvalid(rt->target_class, p->p_classes.nprim))
+ goto err;
} else
- rt->target_class = SECCLASS_PROCESS;
+ rt->target_class = p->process_class;
r = calloc(1, sizeof(*r));
if (!r)
goto err;
@@ -3582,7 +3769,9 @@ static int role_trans_rule_read(policydb_t *p, role_trans_rule_t ** r,
if (ebitmap_read(&tr->classes, fp))
return -1;
} else {
- if (ebitmap_set_bit(&tr->classes, SECCLASS_PROCESS - 1, 1))
+ if (!p->process_class)
+ return -1;
+ if (ebitmap_set_bit(&tr->classes, p->process_class - 1, 1))
return -1;
}
@@ -3748,6 +3937,8 @@ static int scope_index_read(scope_index_t * scope_index,
if (rc < 0)
return -1;
scope_index->class_perms_len = le32_to_cpu(buf[0]);
+ if (is_saturated(scope_index->class_perms_len))
+ return -1;
if (scope_index->class_perms_len == 0) {
scope_index->class_perms_map = NULL;
return 0;
@@ -3802,6 +3993,8 @@ static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl,
if (rc < 0)
return -1;
nprim = le32_to_cpu(buf[0]);
+ if (is_saturated(nprim))
+ return -1;
nel = le32_to_cpu(buf[1]);
for (j = 0; j < nel; j++) {
if (read_f[i] (p, decl->symtab[i].table, fp)) {
@@ -3928,12 +4121,12 @@ static int scope_read(policydb_t * p, int symnum, struct policy_file *fp)
goto cleanup;
scope->scope = le32_to_cpu(buf[0]);
scope->decl_ids_len = le32_to_cpu(buf[1]);
- if (scope->decl_ids_len == 0) {
+ if (zero_or_saturated(scope->decl_ids_len)) {
ERR(fp->handle, "invalid scope with no declaration");
goto cleanup;
}
if ((scope->decl_ids =
- malloc(scope->decl_ids_len * sizeof(uint32_t))) == NULL) {
+ mallocarray(scope->decl_ids_len, sizeof(uint32_t))) == NULL) {
goto cleanup;
}
rc = next_entry(scope->decl_ids, fp, sizeof(uint32_t) * scope->decl_ids_len);
@@ -3959,6 +4152,51 @@ static int scope_read(policydb_t * p, int symnum, struct policy_file *fp)
return -1;
}
+static sepol_security_class_t policydb_string_to_security_class(
+ struct policydb *policydb,
+ const char *class_name)
+{
+ class_datum_t *tclass_datum;
+
+ tclass_datum = hashtab_search(policydb->p_classes.table,
+ (hashtab_key_t) class_name);
+ if (!tclass_datum)
+ return 0;
+ return tclass_datum->s.value;
+}
+
+static sepol_access_vector_t policydb_string_to_av_perm(
+ struct policydb *policydb,
+ sepol_security_class_t tclass,
+ const char *perm_name)
+{
+ class_datum_t *tclass_datum;
+ perm_datum_t *perm_datum;
+
+ if (!tclass || tclass > policydb->p_classes.nprim)
+ return 0;
+ tclass_datum = policydb->class_val_to_struct[tclass - 1];
+
+ perm_datum = (perm_datum_t *)
+ hashtab_search(tclass_datum->permissions.table,
+ (hashtab_key_t)perm_name);
+ if (perm_datum != NULL)
+ return UINT32_C(1) << (perm_datum->s.value - 1);
+
+ if (tclass_datum->comdatum == NULL)
+ return 0;
+
+ perm_datum = (perm_datum_t *)
+ hashtab_search(tclass_datum->comdatum->permissions.table,
+ (hashtab_key_t)perm_name);
+
+ if (perm_datum != NULL)
+ return UINT32_C(1) << (perm_datum->s.value - 1);
+
+ return 0;
+}
+
+
/*
* Read the configuration data from a policy database binary
* representation file into a policy database structure.
@@ -3970,7 +4208,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
uint32_t buf[5];
size_t len, nprim, nel;
char *policydb_str;
- struct policydb_compat_info *info;
+ const struct policydb_compat_info *info;
unsigned int policy_type, bufindex;
ebitmap_node_t *tnode;
int rc;
@@ -4173,6 +4411,8 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
if (rc < 0)
goto bad;
nprim = le32_to_cpu(buf[0]);
+ if (is_saturated(nprim))
+ goto bad;
nel = le32_to_cpu(buf[1]);
if (nel && !nprim) {
ERR(fp->handle, "unexpected items in symbol table with no symbol");
@@ -4186,6 +4426,18 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
p->symtab[i].nprim = nprim;
}
+ switch (p->target_platform) {
+ case SEPOL_TARGET_SELINUX:
+ p->process_class = policydb_string_to_security_class(p, "process");
+ p->dir_class = policydb_string_to_security_class(p, "dir");
+ break;
+ case SEPOL_TARGET_XEN:
+ p->process_class = policydb_string_to_security_class(p, "domain");
+ break;
+ default:
+ break;
+ }
+
if (policy_type == POLICY_KERN) {
if (avtab_read(&p->te_avtab, fp, r_policyvers))
goto bad;
@@ -4229,6 +4481,20 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
if (policydb_index_classes(p))
goto bad;
+ switch (p->target_platform) {
+ case SEPOL_TARGET_SELINUX:
+ /* fall through */
+ case SEPOL_TARGET_XEN:
+ p->process_trans = policydb_string_to_av_perm(p, p->process_class,
+ "transition");
+ p->process_trans_dyntrans = p->process_trans |
+ policydb_string_to_av_perm(p, p->process_class,
+ "dyntransition");
+ break;
+ default:
+ break;
+ }
+
if (policydb_index_others(fp->handle, p, verbose))
goto bad;
@@ -4251,8 +4517,8 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
}
if (policy_type == POLICY_KERN) {
- p->type_attr_map = malloc(p->p_types.nprim * sizeof(ebitmap_t));
- p->attr_type_map = malloc(p->p_types.nprim * sizeof(ebitmap_t));
+ p->type_attr_map = mallocarray(p->p_types.nprim, sizeof(ebitmap_t));
+ p->attr_type_map = mallocarray(p->p_types.nprim, sizeof(ebitmap_t));
if (!p->type_attr_map || !p->attr_type_map)
goto bad;
for (i = 0; i < p->p_types.nprim; i++) {
@@ -4286,6 +4552,9 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
}
}
+ if (validate_policydb(fp->handle, p))
+ goto bad;
+
return POLICYDB_SUCCESS;
bad:
return POLICYDB_ERROR;
diff --git a/libsepol/src/policydb_internal.h b/libsepol/src/policydb_internal.h
index f7bcdfa3..dd8f25d0 100644
--- a/libsepol/src/policydb_internal.h
+++ b/libsepol/src/policydb_internal.h
@@ -2,9 +2,6 @@
#define _SEPOL_POLICYDB_INTERNAL_H_
#include <sepol/policydb.h>
-#include "dso.h"
-hidden_proto(sepol_policydb_create)
- hidden_proto(sepol_policydb_free)
-extern const char *policydb_target_strings[];
+extern const char * const policydb_target_strings[];
#endif
diff --git a/libsepol/src/policydb_public.c b/libsepol/src/policydb_public.c
index 747a43ff..0218c940 100644
--- a/libsepol/src/policydb_public.c
+++ b/libsepol/src/policydb_public.c
@@ -68,12 +68,12 @@ int sepol_policydb_create(sepol_policydb_t ** sp)
p = &(*sp)->p;
if (policydb_init(p)) {
free(*sp);
+ *sp = NULL;
return -1;
}
return 0;
}
-hidden_def(sepol_policydb_create)
void sepol_policydb_free(sepol_policydb_t * p)
{
@@ -83,7 +83,6 @@ void sepol_policydb_free(sepol_policydb_t * p)
free(p);
}
-hidden_def(sepol_policydb_free)
int sepol_policy_kern_vers_min(void)
{
diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c
new file mode 100644
index 00000000..a2dcebe4
--- /dev/null
+++ b/libsepol/src/policydb_validate.c
@@ -0,0 +1,1340 @@
+
+#include <sepol/policydb/conditional.h>
+#include <sepol/policydb/ebitmap.h>
+#include <sepol/policydb/policydb.h>
+#include <sepol/policydb/services.h>
+
+#include "debug.h"
+#include "policydb_validate.h"
+
+#define bool_xor(a, b) (!(a) != !(b))
+#define bool_xnor(a, b) !bool_xor(a, b)
+
+typedef struct validate {
+ uint32_t nprim;
+ ebitmap_t gaps;
+} validate_t;
+
+typedef struct map_arg {
+ validate_t *flavors;
+ sepol_handle_t *handle;
+ int mls;
+} map_arg_t;
+
+static int create_gap_ebitmap(char **val_to_name, uint32_t nprim, ebitmap_t *gaps)
+{
+ unsigned int i;
+
+ ebitmap_init(gaps);
+
+ for (i = 0; i < nprim; i++) {
+ if (!val_to_name[i]) {
+ if (ebitmap_set_bit(gaps, i, 1))
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int validate_init(validate_t *flavor, char **val_to_name, uint32_t nprim)
+{
+ flavor->nprim = nprim;
+ if (create_gap_ebitmap(val_to_name, nprim, &flavor->gaps))
+ return -1;
+
+ return 0;
+}
+
+static int validate_array_init(policydb_t *p, validate_t flavors[])
+{
+ if (validate_init(&flavors[SYM_CLASSES], p->p_class_val_to_name, p->p_classes.nprim))
+ goto bad;
+ if (validate_init(&flavors[SYM_ROLES], p->p_role_val_to_name, p->p_roles.nprim))
+ goto bad;
+ if (p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) {
+ if (validate_init(&flavors[SYM_TYPES], p->p_type_val_to_name, p->p_types.nprim))
+ goto bad;
+ } else {
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but they only exist in the type_attr_map, so there will be references
+ * to gaps and we just have to treat this case as if there were no gaps.
+ */
+ flavors[SYM_TYPES].nprim = p->p_types.nprim;
+ ebitmap_init(&flavors[SYM_TYPES].gaps);
+ }
+ if (validate_init(&flavors[SYM_USERS], p->p_user_val_to_name, p->p_users.nprim))
+ goto bad;
+ if (validate_init(&flavors[SYM_BOOLS], p->p_bool_val_to_name, p->p_bools.nprim))
+ goto bad;
+ if (validate_init(&flavors[SYM_LEVELS], p->p_sens_val_to_name, p->p_levels.nprim))
+ goto bad;
+ if (validate_init(&flavors[SYM_CATS], p->p_cat_val_to_name, p->p_cats.nprim))
+ goto bad;
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+/*
+ * Functions to validate both kernel and module policydbs
+ */
+
+int value_isvalid(uint32_t value, uint32_t nprim)
+{
+ if (!value || value > nprim)
+ return 0;
+
+ return 1;
+}
+
+static int validate_value(uint32_t value, validate_t *flavor)
+{
+ if (!value || value > flavor->nprim)
+ goto bad;
+ if (ebitmap_get_bit(&flavor->gaps, value-1))
+ goto bad;
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_ebitmap(ebitmap_t *map, validate_t *flavor)
+{
+ if (ebitmap_length(map) > 0 && ebitmap_highest_set_bit(map) >= flavor->nprim)
+ goto bad;
+ if (ebitmap_match_any(map, &flavor->gaps))
+ goto bad;
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_type_set(type_set_t *type_set, validate_t *type)
+{
+ if (validate_ebitmap(&type_set->types, type))
+ goto bad;
+ if (validate_ebitmap(&type_set->negset, type))
+ goto bad;
+
+ switch (type_set->flags) {
+ case 0:
+ case TYPE_STAR:
+ case TYPE_COMP:
+ break;
+ default:
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_empty_type_set(type_set_t *type_set)
+{
+ if (!ebitmap_is_empty(&type_set->types))
+ goto bad;
+ if (!ebitmap_is_empty(&type_set->negset))
+ goto bad;
+ if (type_set->flags != 0)
+ goto bad;
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_role_set(role_set_t *role_set, validate_t *role)
+{
+ if (validate_ebitmap(&role_set->roles, role))
+ goto bad;
+
+ switch (role_set->flags) {
+ case 0:
+ case ROLE_STAR:
+ case ROLE_COMP:
+ break;
+ default:
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_scope(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ scope_datum_t *scope_datum = (scope_datum_t *)d;
+ uint32_t *nprim = (uint32_t *)args;
+ unsigned int i;
+
+ switch (scope_datum->scope) {
+ case SCOPE_REQ:
+ case SCOPE_DECL:
+ break;
+ default:
+ goto bad;
+ }
+
+ for (i = 0; i < scope_datum->decl_ids_len; i++) {
+ if (!value_isvalid(scope_datum->decl_ids[i], *nprim))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_scopes(sepol_handle_t *handle, symtab_t scopes[], avrule_block_t *block)
+{
+ avrule_decl_t *decl;
+ unsigned int i;
+ unsigned int num_decls = 0;
+
+ for (; block != NULL; block = block->next) {
+ for (decl = block->branch_list; decl; decl = decl->next) {
+ num_decls++;
+ }
+ }
+
+ for (i = 0; i < SYM_NUM; i++) {
+ if (hashtab_map(scopes[i].table, validate_scope, &num_decls))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid scope");
+ return -1;
+}
+
+static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms, constraint_node_t *cons, validate_t flavors[])
+{
+ constraint_expr_t *cexp;
+
+ for (; cons; cons = cons->next) {
+ if (nperms == 0 && cons->permissions != 0)
+ goto bad;
+ if (nperms > 0 && cons->permissions == 0)
+ goto bad;
+ if (nperms > 0 && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms))
+ goto bad;
+
+ for (cexp = cons->expr; cexp; cexp = cexp->next) {
+ if (cexp->expr_type == CEXPR_NAMES) {
+ if (cexp->attr & CEXPR_XTARGET && nperms != 0)
+ goto bad;
+ if (!(cexp->attr & CEXPR_TYPE)) {
+ if (validate_empty_type_set(cexp->type_names))
+ goto bad;
+ }
+
+ switch (cexp->op) {
+ case CEXPR_EQ:
+ case CEXPR_NEQ:
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (cexp->attr) {
+ case CEXPR_USER:
+ case CEXPR_USER | CEXPR_TARGET:
+ case CEXPR_USER | CEXPR_XTARGET:
+ if (validate_ebitmap(&cexp->names, &flavors[SYM_USERS]))
+ goto bad;
+ break;
+ case CEXPR_ROLE:
+ case CEXPR_ROLE | CEXPR_TARGET:
+ case CEXPR_ROLE | CEXPR_XTARGET:
+ if (validate_ebitmap(&cexp->names, &flavors[SYM_ROLES]))
+ goto bad;
+ break;
+ case CEXPR_TYPE:
+ case CEXPR_TYPE | CEXPR_TARGET:
+ case CEXPR_TYPE | CEXPR_XTARGET:
+ if (validate_ebitmap(&cexp->names, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_type_set(cexp->type_names, &flavors[SYM_TYPES]))
+ goto bad;
+ break;
+ default:
+ goto bad;
+ }
+ } else if (cexp->expr_type == CEXPR_ATTR) {
+ if (!ebitmap_is_empty(&cexp->names))
+ goto bad;
+ if (validate_empty_type_set(cexp->type_names))
+ goto bad;
+
+ switch (cexp->op) {
+ case CEXPR_EQ:
+ case CEXPR_NEQ:
+ break;
+ case CEXPR_DOM:
+ case CEXPR_DOMBY:
+ case CEXPR_INCOMP:
+ if ((cexp->attr & CEXPR_USER) || (cexp->attr & CEXPR_TYPE))
+ goto bad;
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (cexp->attr) {
+ case CEXPR_USER:
+ case CEXPR_ROLE:
+ case CEXPR_TYPE:
+ case CEXPR_L1L2:
+ case CEXPR_L1H2:
+ case CEXPR_H1L2:
+ case CEXPR_H1H2:
+ case CEXPR_L1H1:
+ case CEXPR_L2H2:
+ break;
+ default:
+ goto bad;
+ }
+ } else {
+ switch (cexp->expr_type) {
+ case CEXPR_NOT:
+ case CEXPR_AND:
+ case CEXPR_OR:
+ break;
+ default:
+ goto bad;
+ }
+
+ if (cexp->op != 0)
+ goto bad;
+ if (cexp->attr != 0)
+ goto bad;
+ if (!ebitmap_is_empty(&cexp->names))
+ goto bad;
+ if (validate_empty_type_set(cexp->type_names))
+ goto bad;
+ }
+ }
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid constraint expr");
+ return -1;
+}
+
+static int validate_class_datum(sepol_handle_t *handle, class_datum_t *class, validate_t flavors[])
+{
+ if (validate_value(class->s.value, &flavors[SYM_CLASSES]))
+ goto bad;
+ if (class->permissions.nprim > PERM_SYMTAB_SIZE)
+ goto bad;
+ if (validate_constraint_nodes(handle, class->permissions.nprim, class->constraints, flavors))
+ goto bad;
+ if (validate_constraint_nodes(handle, 0, class->validatetrans, flavors))
+ goto bad;
+
+ switch (class->default_user) {
+ case 0:
+ case DEFAULT_SOURCE:
+ case DEFAULT_TARGET:
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (class->default_role) {
+ case 0:
+ case DEFAULT_SOURCE:
+ case DEFAULT_TARGET:
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (class->default_type) {
+ case 0:
+ case DEFAULT_SOURCE:
+ case DEFAULT_TARGET:
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (class->default_range) {
+ case 0:
+ case DEFAULT_SOURCE_LOW:
+ case DEFAULT_SOURCE_HIGH:
+ case DEFAULT_SOURCE_LOW_HIGH:
+ case DEFAULT_TARGET_LOW:
+ case DEFAULT_TARGET_HIGH:
+ case DEFAULT_TARGET_LOW_HIGH:
+ case DEFAULT_GLBLUB:
+ break;
+ default:
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid class datum");
+ return -1;
+}
+
+static int validate_class_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ map_arg_t *margs = args;
+
+ return validate_class_datum(margs->handle, d, margs->flavors);
+}
+
+static int validate_common_datum(sepol_handle_t *handle, common_datum_t *common)
+{
+ if (common->permissions.nprim > PERM_SYMTAB_SIZE)
+ goto bad;
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid common class datum");
+ return -1;
+}
+
+static int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ map_arg_t *margs = args;
+
+ return validate_common_datum(margs->handle, d);
+}
+
+static int validate_role_datum(sepol_handle_t *handle, role_datum_t *role, validate_t flavors[])
+{
+ if (validate_value(role->s.value, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_ebitmap(&role->dominates, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_type_set(&role->types, &flavors[SYM_TYPES]))
+ goto bad;
+ if (role->bounds && validate_value(role->bounds, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_ebitmap(&role->roles, &flavors[SYM_ROLES]))
+ goto bad;
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid role datum");
+ return -1;
+}
+
+static int validate_role_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ map_arg_t *margs = args;
+
+ return validate_role_datum(margs->handle, d, margs->flavors);
+}
+
+static int validate_type_datum(sepol_handle_t *handle, type_datum_t *type, validate_t flavors[])
+{
+ if (validate_value(type->s.value, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_ebitmap(&type->types, &flavors[SYM_TYPES]))
+ goto bad;
+ if (type->bounds && validate_value(type->bounds, &flavors[SYM_TYPES]))
+ goto bad;
+
+ switch (type->flavor) {
+ case TYPE_TYPE:
+ case TYPE_ATTRIB:
+ case TYPE_ALIAS:
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (type->flags) {
+ case 0:
+ case TYPE_FLAGS_PERMISSIVE:
+ case TYPE_FLAGS_EXPAND_ATTR_TRUE:
+ case TYPE_FLAGS_EXPAND_ATTR_FALSE:
+ case TYPE_FLAGS_EXPAND_ATTR:
+ break;
+ default:
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid type datum");
+ return -1;
+}
+
+static int validate_type_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ map_arg_t *margs = args;
+
+ return validate_type_datum(margs->handle, d, margs->flavors);
+}
+
+static int validate_mls_semantic_cat(mls_semantic_cat_t *cat, validate_t *cats)
+{
+ for (; cat; cat = cat->next) {
+ if (validate_value(cat->low, cats))
+ goto bad;
+ if (validate_value(cat->high, cats))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_mls_semantic_level(mls_semantic_level_t *level, validate_t *sens, validate_t *cats)
+{
+ if (level->sens == 0)
+ return 0;
+ if (validate_value(level->sens, sens))
+ goto bad;
+ if (validate_mls_semantic_cat(level->cat, cats))
+ goto bad;
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_mls_semantic_range(mls_semantic_range_t *range, validate_t *sens, validate_t *cats)
+{
+ if (validate_mls_semantic_level(&range->level[0], sens, cats))
+ goto bad;
+ if (validate_mls_semantic_level(&range->level[1], sens, cats))
+ goto bad;
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_mls_level(mls_level_t *level, validate_t *sens, validate_t *cats)
+{
+ if (validate_value(level->sens, sens))
+ goto bad;
+ if (validate_ebitmap(&level->cat, cats))
+ goto bad;
+
+ return 0;
+
+ bad:
+ return -1;
+}
+
+static int validate_level_datum(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ level_datum_t *level = d;
+ validate_t *flavors = args;
+
+ return validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS]);
+}
+
+static int validate_mls_range(mls_range_t *range, validate_t *sens, validate_t *cats)
+{
+ if (validate_mls_level(&range->level[0], sens, cats))
+ goto bad;
+ if (validate_mls_level(&range->level[1], sens, cats))
+ goto bad;
+
+ return 0;
+
+ bad:
+ return -1;
+}
+
+static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, validate_t flavors[], int mls)
+{
+ if (validate_value(user->s.value, &flavors[SYM_USERS]))
+ goto bad;
+ if (validate_role_set(&user->roles, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_mls_semantic_range(&user->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+ goto bad;
+ if (validate_mls_semantic_level(&user->dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+ goto bad;
+ if (mls && validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+ goto bad;
+ if (mls && validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+ goto bad;
+ if (user->bounds && validate_value(user->bounds, &flavors[SYM_USERS]))
+ goto bad;
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid user datum");
+ return -1;
+}
+
+static int validate_user_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ map_arg_t *margs = args;
+
+ return validate_user_datum(margs->handle, d, margs->flavors, margs->mls);
+}
+
+static int validate_bool_datum(sepol_handle_t *handle, cond_bool_datum_t *boolean, validate_t flavors[])
+{
+ if (validate_value(boolean->s.value, &flavors[SYM_BOOLS]))
+ goto bad;
+
+ switch (boolean->state) {
+ case 0:
+ case 1:
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (boolean->flags) {
+ case 0:
+ case COND_BOOL_FLAGS_TUNABLE:
+ break;
+ default:
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid bool datum");
+ return -1;
+}
+
+static int validate_bool_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ map_arg_t *margs = args;
+
+ return validate_bool_datum(margs->handle, d, margs->flavors);
+}
+
+static int validate_datum_array_gaps(sepol_handle_t *handle, policydb_t *p, validate_t flavors[])
+{
+ unsigned int i;
+
+ for (i = 0; i < p->p_classes.nprim; i++) {
+ if (bool_xnor(p->class_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_CLASSES].gaps, i)))
+ goto bad;
+ }
+
+ for (i = 0; i < p->p_roles.nprim; i++) {
+ if (bool_xnor(p->role_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_ROLES].gaps, i)))
+ goto bad;
+ }
+
+ /*
+ * For policy versions between 20 and 23, attributes exist in the policy,
+ * but only in the type_attr_map, so all gaps must be assumed to be valid.
+ */
+ if (p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) {
+ for (i = 0; i < p->p_types.nprim; i++) {
+ if (bool_xnor(p->type_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_TYPES].gaps, i)))
+ goto bad;
+ }
+ }
+
+ for (i = 0; i < p->p_users.nprim; i++) {
+ if (bool_xnor(p->user_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_USERS].gaps, i)))
+ goto bad;
+ }
+
+ for (i = 0; i < p->p_bools.nprim; i++) {
+ if (bool_xnor(p->bool_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_BOOLS].gaps, i)))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid datum array gaps");
+ return -1;
+}
+
+static int validate_datum(__attribute__ ((unused))hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ symtab_datum_t *s = d;
+ uint32_t *nprim = (uint32_t *)args;
+
+ return !value_isvalid(s->value, *nprim);
+}
+
+static int validate_datum_array_entries(sepol_handle_t *handle, policydb_t *p, validate_t flavors[])
+{
+ map_arg_t margs = { flavors, handle, p->mls };
+
+ if (hashtab_map(p->p_commons.table, validate_common_datum_wrapper, &margs))
+ goto bad;
+
+ if (hashtab_map(p->p_classes.table, validate_class_datum_wrapper, &margs))
+ goto bad;
+
+ if (hashtab_map(p->p_roles.table, validate_role_datum_wrapper, &margs))
+ goto bad;
+
+ if (hashtab_map(p->p_types.table, validate_type_datum_wrapper, &margs))
+ goto bad;
+
+ if (hashtab_map(p->p_users.table, validate_user_datum_wrapper, &margs))
+ goto bad;
+
+ if (p->mls && hashtab_map(p->p_levels.table, validate_level_datum, flavors))
+ goto bad;
+
+ if (hashtab_map(p->p_cats.table, validate_datum, &flavors[SYM_CATS]))
+ goto bad;
+
+ if (hashtab_map(p->p_bools.table, validate_bool_datum_wrapper, &margs))
+ goto bad;
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid datum array entries");
+ return -1;
+}
+
+/*
+ * Functions to validate a kernel policydb
+ */
+
+static int validate_avtab_key(avtab_key_t *key, int conditional, validate_t flavors[])
+{
+ if (validate_value(key->source_type, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_value(key->target_type, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_value(key->target_class, &flavors[SYM_CLASSES]))
+ goto bad;
+ switch (0xFFF & key->specified) {
+ case AVTAB_ALLOWED:
+ case AVTAB_AUDITALLOW:
+ case AVTAB_AUDITDENY:
+ case AVTAB_TRANSITION:
+ case AVTAB_MEMBER:
+ case AVTAB_CHANGE:
+ break;
+ case AVTAB_XPERMS_ALLOWED:
+ case AVTAB_XPERMS_AUDITALLOW:
+ case AVTAB_XPERMS_DONTAUDIT:
+ if (conditional)
+ goto bad;
+ break;
+ default:
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *args)
+{
+ validate_t *flavors = (validate_t *)args;
+
+ if (validate_avtab_key(k, 0, flavors))
+ return -1;
+
+ if ((k->specified & AVTAB_TYPE) && validate_value(d->data, &flavors[SYM_TYPES]))
+ return -1;
+
+ return 0;
+}
+
+static int validate_avtab(sepol_handle_t *handle, avtab_t *avtab, validate_t flavors[])
+{
+ if (avtab_map(avtab, validate_avtab_key_and_datum, flavors)) {
+ ERR(handle, "Invalid avtab");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int validate_cond_av_list(sepol_handle_t *handle, cond_av_list_t *cond_av, validate_t flavors[])
+{
+ avtab_ptr_t avtab_ptr;
+
+ for (; cond_av; cond_av = cond_av->next) {
+ for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) {
+ if (validate_avtab_key(&avtab_ptr->key, 1, flavors)) {
+ ERR(handle, "Invalid cond av list");
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int validate_avrules(sepol_handle_t *handle, avrule_t *avrule, int conditional, validate_t flavors[])
+{
+ class_perm_node_t *class;
+
+ for (; avrule; avrule = avrule->next) {
+ if (validate_type_set(&avrule->stypes, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_type_set(&avrule->ttypes, &flavors[SYM_TYPES]))
+ goto bad;
+ class = avrule->perms;
+ for (; class; class = class->next) {
+ if (validate_value(class->tclass, &flavors[SYM_CLASSES]))
+ goto bad;
+ }
+
+ switch(avrule->specified) {
+ case AVRULE_ALLOWED:
+ case AVRULE_AUDITALLOW:
+ case AVRULE_AUDITDENY:
+ case AVRULE_DONTAUDIT:
+ case AVRULE_TRANSITION:
+ case AVRULE_MEMBER:
+ case AVRULE_CHANGE:
+ break;
+ case AVRULE_NEVERALLOW:
+ case AVRULE_XPERMS_ALLOWED:
+ case AVRULE_XPERMS_AUDITALLOW:
+ case AVRULE_XPERMS_DONTAUDIT:
+ case AVRULE_XPERMS_NEVERALLOW:
+ if (conditional)
+ goto bad;
+ break;
+ default:
+ goto bad;
+ }
+
+ if (avrule->specified & AVRULE_XPERMS) {
+ if (!avrule->xperms)
+ goto bad;
+ switch (avrule->xperms->specified) {
+ case AVRULE_XPERMS_IOCTLFUNCTION:
+ case AVRULE_XPERMS_IOCTLDRIVER:
+ break;
+ default:
+ goto bad;
+ }
+ } else if (avrule->xperms)
+ goto bad;
+
+ switch(avrule->flags) {
+ case 0:
+ case RULE_SELF:
+ break;
+ default:
+ goto bad;
+ }
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid avrule");
+ return -1;
+}
+
+static int validate_bool_id_array(sepol_handle_t *handle, uint32_t bool_ids[], unsigned int nbools, validate_t *bool)
+{
+ unsigned int i;
+
+ if (nbools >= COND_MAX_BOOLS)
+ goto bad;
+
+ for (i=0; i < nbools; i++) {
+ if (validate_value(bool_ids[i], bool))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid bool id array");
+ return -1;
+}
+
+static int validate_cond_list(sepol_handle_t *handle, cond_list_t *cond, validate_t flavors[])
+{
+ for (; cond; cond = cond->next) {
+ if (validate_cond_av_list(handle, cond->true_list, flavors))
+ goto bad;
+ if (validate_cond_av_list(handle, cond->false_list, flavors))
+ goto bad;
+ if (validate_avrules(handle, cond->avtrue_list, 1, flavors))
+ goto bad;
+ if (validate_avrules(handle, cond->avfalse_list, 1, flavors))
+ goto bad;
+ if (validate_bool_id_array(handle, cond->bool_ids, cond->nbools, &flavors[SYM_BOOLS]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid cond list");
+ return -1;
+}
+
+static int validate_role_transes(sepol_handle_t *handle, role_trans_t *role_trans, validate_t flavors[])
+{
+ for (; role_trans; role_trans = role_trans->next) {
+ if (validate_value(role_trans->role, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_value(role_trans->type, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_value(role_trans->tclass, &flavors[SYM_CLASSES]))
+ goto bad;
+ if (validate_value(role_trans->new_role, &flavors[SYM_ROLES]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid role trans");
+ return -1;
+}
+
+static int validate_role_allows(sepol_handle_t *handle, role_allow_t *role_allow, validate_t flavors[])
+{
+ for (; role_allow; role_allow = role_allow->next) {
+ if (validate_value(role_allow->role, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_value(role_allow->new_role, &flavors[SYM_ROLES]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid role allow");
+ return -1;
+}
+
+static int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *args)
+{
+ filename_trans_key_t *ftk = (filename_trans_key_t *)k;
+ filename_trans_datum_t *ftd = d;
+ validate_t *flavors = (validate_t *)args;
+
+ if (validate_value(ftk->ttype, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_value(ftk->tclass, &flavors[SYM_CLASSES]))
+ goto bad;
+ for (; ftd; ftd = ftd->next) {
+ if (validate_ebitmap(&ftd->stypes, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_value(ftd->otype, &flavors[SYM_TYPES]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ return -1;
+}
+
+static int validate_filename_trans_hashtab(sepol_handle_t *handle, hashtab_t filename_trans, validate_t flavors[])
+{
+ if (hashtab_map(filename_trans, validate_filename_trans, flavors)) {
+ ERR(handle, "Invalid filename trans");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int validate_context(context_struct_t *con, validate_t flavors[], int mls)
+{
+ if (validate_value(con->user, &flavors[SYM_USERS]))
+ return -1;
+ if (validate_value(con->role, &flavors[SYM_ROLES]))
+ return -1;
+ if (validate_value(con->type, &flavors[SYM_TYPES]))
+ return -1;
+ if (mls && validate_mls_range(&con->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+ return -1;
+
+ return 0;
+}
+
+static int validate_ocontexts(sepol_handle_t *handle, policydb_t *p, validate_t flavors[])
+{
+ ocontext_t *octx;
+ unsigned int i;
+
+ for (i = 0; i < OCON_NUM; i++) {
+ for (octx = p->ocontexts[i]; octx; octx = octx->next) {
+ if (validate_context(&octx->context[0], flavors, p->mls))
+ goto bad;
+
+ if (p->target_platform == SEPOL_TARGET_SELINUX) {
+ switch (i) {
+ case OCON_FS:
+ case OCON_NETIF:
+ if (validate_context(&octx->context[1], flavors, p->mls))
+ goto bad;
+ break;
+ case OCON_FSUSE:
+ switch (octx->v.behavior) {
+ case SECURITY_FS_USE_XATTR:
+ case SECURITY_FS_USE_TRANS:
+ case SECURITY_FS_USE_TASK:
+ break;
+ default:
+ goto bad;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid ocontext");
+ return -1;
+}
+
+static int validate_genfs(sepol_handle_t *handle, policydb_t *p, validate_t flavors[])
+{
+ genfs_t *genfs;
+ ocontext_t *octx;
+
+ for (genfs = p->genfs; genfs; genfs = genfs->next) {
+ for (octx = genfs->head; octx; octx = octx->next) {
+ if (validate_context(&octx->context[0], flavors, p->mls))
+ goto bad;
+ }
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid genfs");
+ return -1;
+}
+
+/*
+ * Functions to validate a module policydb
+ */
+
+static int validate_role_trans_rules(sepol_handle_t *handle, role_trans_rule_t *role_trans, validate_t flavors[])
+{
+ for (; role_trans; role_trans = role_trans->next) {
+ if (validate_role_set(&role_trans->roles, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_type_set(&role_trans->types, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_ebitmap(&role_trans->classes, &flavors[SYM_CLASSES]))
+ goto bad;
+ if (validate_value(role_trans->new_role, &flavors[SYM_ROLES]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid role trans rule");
+ return -1;
+}
+
+static int validate_role_allow_rules(sepol_handle_t *handle, role_allow_rule_t *role_allow, validate_t flavors[])
+{
+ for (; role_allow; role_allow = role_allow->next) {
+ if (validate_role_set(&role_allow->roles, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_role_set(&role_allow->new_roles, &flavors[SYM_ROLES]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid role allow rule");
+ return -1;
+}
+
+static int validate_range_trans_rules(sepol_handle_t *handle, range_trans_rule_t *range_trans, validate_t flavors[])
+{
+ for (; range_trans; range_trans = range_trans->next) {
+ if (validate_type_set(&range_trans->stypes, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_type_set(&range_trans->ttypes, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_ebitmap(&range_trans->tclasses, &flavors[SYM_CLASSES]))
+ goto bad;
+ if (validate_mls_semantic_range(&range_trans->trange, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid range trans rule");
+ return -1;
+}
+
+static int validate_scope_index(sepol_handle_t *handle, scope_index_t *scope_index, validate_t flavors[])
+{
+ if (validate_ebitmap(&scope_index->p_classes_scope, &flavors[SYM_CLASSES]))
+ goto bad;
+ if (validate_ebitmap(&scope_index->p_roles_scope, &flavors[SYM_ROLES]))
+ goto bad;
+ if (validate_ebitmap(&scope_index->p_types_scope, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_ebitmap(&scope_index->p_users_scope, &flavors[SYM_USERS]))
+ goto bad;
+ if (validate_ebitmap(&scope_index->p_bools_scope, &flavors[SYM_BOOLS]))
+ goto bad;
+ if (validate_ebitmap(&scope_index->p_sens_scope, &flavors[SYM_LEVELS]))
+ goto bad;
+ if (validate_ebitmap(&scope_index->p_cat_scope, &flavors[SYM_CATS]))
+ goto bad;
+ if (scope_index->class_perms_len > flavors[SYM_CLASSES].nprim)
+ goto bad;
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid scope");
+ return -1;
+}
+
+
+static int validate_filename_trans_rules(sepol_handle_t *handle, filename_trans_rule_t *filename_trans, validate_t flavors[])
+{
+ for (; filename_trans; filename_trans = filename_trans->next) {
+ if (validate_type_set(&filename_trans->stypes, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_type_set(&filename_trans->ttypes, &flavors[SYM_TYPES]))
+ goto bad;
+ if (validate_value(filename_trans->tclass,&flavors[SYM_CLASSES] ))
+ goto bad;
+ if (validate_value(filename_trans->otype, &flavors[SYM_TYPES]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid filename trans rule list");
+ return -1;
+}
+
+static int validate_symtabs(sepol_handle_t *handle, symtab_t symtabs[], validate_t flavors[])
+{
+ unsigned int i;
+
+ for (i = 0; i < SYM_NUM; i++) {
+ if (hashtab_map(symtabs[i].table, validate_datum, &flavors[i].nprim)) {
+ ERR(handle, "Invalid symtab");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int validate_avrule_blocks(sepol_handle_t *handle, avrule_block_t *avrule_block, validate_t flavors[])
+{
+ avrule_decl_t *decl;
+
+ for (; avrule_block; avrule_block = avrule_block->next) {
+ for (decl = avrule_block->branch_list; decl != NULL; decl = decl->next) {
+ if (validate_cond_list(handle, decl->cond_list, flavors))
+ goto bad;
+ if (validate_avrules(handle, decl->avrules, 0, flavors))
+ goto bad;
+ if (validate_role_trans_rules(handle, decl->role_tr_rules, flavors))
+ goto bad;
+ if (validate_role_allow_rules(handle, decl->role_allow_rules, flavors))
+ goto bad;
+ if (validate_range_trans_rules(handle, decl->range_tr_rules, flavors))
+ goto bad;
+ if (validate_scope_index(handle, &decl->required, flavors))
+ goto bad;
+ if (validate_scope_index(handle, &decl->declared, flavors))
+ goto bad;
+ if (validate_filename_trans_rules(handle, decl->filename_trans_rules, flavors))
+ goto bad;
+ if (validate_symtabs(handle, decl->symtab, flavors))
+ goto bad;
+ }
+
+ switch (avrule_block->flags) {
+ case 0:
+ case AVRULE_OPTIONAL:
+ break;
+ default:
+ goto bad;
+ }
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid avrule block");
+ return -1;
+}
+
+static int validate_permissives(sepol_handle_t *handle, policydb_t *p, validate_t flavors[])
+{
+ ebitmap_node_t *node;
+ unsigned i;
+
+ ebitmap_for_each_positive_bit(&p->permissive_map, node, i) {
+ if (validate_value(i, &flavors[SYM_TYPES]))
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid permissive type");
+ return -1;
+}
+
+static int validate_properties(sepol_handle_t *handle, policydb_t *p)
+{
+ switch (p->policy_type) {
+ case POLICY_KERN:
+ if (p->policyvers < POLICYDB_VERSION_MIN || p->policyvers > POLICYDB_VERSION_MAX)
+ goto bad;
+ break;
+ case POLICY_BASE:
+ case POLICY_MOD:
+ if (p->policyvers < MOD_POLICYDB_VERSION_MIN || p->policyvers > MOD_POLICYDB_VERSION_MAX)
+ goto bad;
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (p->target_platform) {
+ case SEPOL_TARGET_SELINUX:
+ case SEPOL_TARGET_XEN:
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (p->mls) {
+ case 0:
+ case 1:
+ break;
+ default:
+ goto bad;
+ }
+
+ switch (p->handle_unknown) {
+ case SEPOL_DENY_UNKNOWN:
+ case SEPOL_REJECT_UNKNOWN:
+ case SEPOL_ALLOW_UNKNOWN:
+ break;
+ default:
+ goto bad;
+ }
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid policy property");
+ return -1;
+}
+
+static void validate_array_destroy(validate_t flavors[])
+{
+ unsigned int i;
+
+ for (i = 0; i < SYM_NUM; i++) {
+ ebitmap_destroy(&flavors[i].gaps);
+ }
+}
+
+/*
+ * Validate policydb
+ */
+int validate_policydb(sepol_handle_t *handle, policydb_t *p)
+{
+ validate_t flavors[SYM_NUM] = {};
+
+ if (validate_array_init(p, flavors))
+ goto bad;
+
+ if (validate_properties(handle, p))
+ goto bad;
+
+ if (p->policy_type == POLICY_KERN) {
+ if (validate_avtab(handle, &p->te_avtab, flavors))
+ goto bad;
+ if (p->policyvers >= POLICYDB_VERSION_BOOL)
+ if (validate_cond_list(handle, p->cond_list, flavors))
+ goto bad;
+ if (validate_role_transes(handle, p->role_tr, flavors))
+ goto bad;
+ if (validate_role_allows(handle, p->role_allow, flavors))
+ goto bad;
+ if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS)
+ if (validate_filename_trans_hashtab(handle, p->filename_trans, flavors))
+ goto bad;
+ } else {
+ if (validate_avrule_blocks(handle, p->global, flavors))
+ goto bad;
+ }
+
+ if (validate_ocontexts(handle, p, flavors))
+ goto bad;
+
+ if (validate_genfs(handle, p, flavors))
+ goto bad;
+
+ if (validate_scopes(handle, p->scope, p->global))
+ goto bad;
+
+ if (validate_datum_array_gaps(handle, p, flavors))
+ goto bad;
+
+ if (validate_datum_array_entries(handle, p, flavors))
+ goto bad;
+
+ if (validate_permissives(handle, p, flavors))
+ goto bad;
+
+ validate_array_destroy(flavors);
+
+ return 0;
+
+bad:
+ ERR(handle, "Invalid policydb");
+ validate_array_destroy(flavors);
+ return -1;
+}
diff --git a/libsepol/src/policydb_validate.h b/libsepol/src/policydb_validate.h
new file mode 100644
index 00000000..d9f7229b
--- /dev/null
+++ b/libsepol/src/policydb_validate.h
@@ -0,0 +1,7 @@
+#include <stdint.h>
+
+#include <sepol/handle.h>
+#include <sepol/policydb/policydb.h>
+
+int value_isvalid(uint32_t value, uint32_t nprim);
+int validate_policydb(sepol_handle_t *handle, policydb_t *p);
diff --git a/libsepol/src/port_internal.h b/libsepol/src/port_internal.h
index ffb5f65a..80cf5c25 100644
--- a/libsepol/src/port_internal.h
+++ b/libsepol/src/port_internal.h
@@ -3,18 +3,5 @@
#include <sepol/port_record.h>
#include <sepol/ports.h>
-#include "dso.h"
-hidden_proto(sepol_port_create)
- hidden_proto(sepol_port_free)
- hidden_proto(sepol_port_get_con)
- hidden_proto(sepol_port_get_high)
- hidden_proto(sepol_port_get_low)
- hidden_proto(sepol_port_get_proto)
- hidden_proto(sepol_port_get_proto_str)
- hidden_proto(sepol_port_key_create)
- hidden_proto(sepol_port_key_unpack)
- hidden_proto(sepol_port_set_con)
- hidden_proto(sepol_port_set_proto)
- hidden_proto(sepol_port_set_range)
#endif
diff --git a/libsepol/src/port_record.c b/libsepol/src/port_record.c
index 15fb198f..7054dbc2 100644
--- a/libsepol/src/port_record.c
+++ b/libsepol/src/port_record.c
@@ -46,7 +46,6 @@ int sepol_port_key_create(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_port_key_create)
void sepol_port_key_unpack(const sepol_port_key_t * key,
int *low, int *high, int *proto)
@@ -57,7 +56,6 @@ void sepol_port_key_unpack(const sepol_port_key_t * key,
*proto = key->proto;
}
-hidden_def(sepol_port_key_unpack)
int sepol_port_key_extract(sepol_handle_t * handle,
const sepol_port_t * port,
@@ -141,7 +139,6 @@ int sepol_port_get_low(const sepol_port_t * port)
return port->low;
}
-hidden_def(sepol_port_get_low)
int sepol_port_get_high(const sepol_port_t * port)
{
@@ -149,7 +146,6 @@ int sepol_port_get_high(const sepol_port_t * port)
return port->high;
}
-hidden_def(sepol_port_get_high)
void sepol_port_set_port(sepol_port_t * port, int port_num)
{
@@ -165,7 +161,6 @@ void sepol_port_set_range(sepol_port_t * port, int low, int high)
port->high = high;
}
-hidden_def(sepol_port_set_range)
/* Protocol */
int sepol_port_get_proto(const sepol_port_t * port)
@@ -174,7 +169,6 @@ int sepol_port_get_proto(const sepol_port_t * port)
return port->proto;
}
-hidden_def(sepol_port_get_proto)
const char *sepol_port_get_proto_str(int proto)
{
@@ -193,7 +187,6 @@ const char *sepol_port_get_proto_str(int proto)
}
}
-hidden_def(sepol_port_get_proto_str)
void sepol_port_set_proto(sepol_port_t * port, int proto)
{
@@ -201,7 +194,6 @@ void sepol_port_set_proto(sepol_port_t * port, int proto)
port->proto = proto;
}
-hidden_def(sepol_port_set_proto)
/* Create */
int sepol_port_create(sepol_handle_t * handle, sepol_port_t ** port)
@@ -223,7 +215,6 @@ int sepol_port_create(sepol_handle_t * handle, sepol_port_t ** port)
return STATUS_SUCCESS;
}
-hidden_def(sepol_port_create)
/* Deep copy clone */
int sepol_port_clone(sepol_handle_t * handle,
@@ -262,7 +253,6 @@ void sepol_port_free(sepol_port_t * port)
free(port);
}
-hidden_def(sepol_port_free)
/* Context */
sepol_context_t *sepol_port_get_con(const sepol_port_t * port)
@@ -271,7 +261,6 @@ sepol_context_t *sepol_port_get_con(const sepol_port_t * port)
return port->con;
}
-hidden_def(sepol_port_get_con)
int sepol_port_set_con(sepol_handle_t * handle,
sepol_port_t * port, sepol_context_t * con)
@@ -289,4 +278,3 @@ int sepol_port_set_con(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_port_set_con)
diff --git a/libsepol/src/private.h b/libsepol/src/private.h
index b884c23b..a8cc1472 100644
--- a/libsepol/src/private.h
+++ b/libsepol/src/private.h
@@ -14,7 +14,6 @@
#endif
#include <errno.h>
-#include <dso.h>
#ifdef __APPLE__
#define __BYTE_ORDER BYTE_ORDER
@@ -45,9 +44,27 @@
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
-#define is_saturated(x) (x == (typeof(x))-1)
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+# define is_saturated(x) (x == (typeof(x))-1 || (x) > (1U << 16))
+#else
+# define is_saturated(x) (x == (typeof(x))-1)
+#endif
+
#define zero_or_saturated(x) ((x == 0) || is_saturated(x))
+#define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b)))
+
+/* Use to ignore intentional unsigned under- and overflows while running under UBSAN. */
+#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 4)
+#if (__clang_major__ >= 12)
+#define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow", "unsigned-shift-base")))
+#else
+#define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#else
+#define ignore_unsigned_overflow_
+#endif
+
/* Policy compatibility information. */
struct policydb_compat_info {
unsigned int type;
@@ -57,12 +74,32 @@ struct policydb_compat_info {
unsigned int target_platform;
};
-extern struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
- unsigned int type,
- unsigned int target_platform);
+extern const struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
+ unsigned int type,
+ unsigned int target_platform);
/* Reading from a policy "file". */
-extern int next_entry(void *buf, struct policy_file *fp, size_t bytes) hidden;
+extern int next_entry(void *buf, struct policy_file *fp, size_t bytes);
extern size_t put_entry(const void *ptr, size_t size, size_t n,
- struct policy_file *fp) hidden;
-extern int str_read(char **strp, struct policy_file *fp, size_t len) hidden;
+ struct policy_file *fp);
+extern int str_read(char **strp, struct policy_file *fp, size_t len);
+
+static inline void* mallocarray(size_t nmemb, size_t size) {
+ if (size && nmemb > (size_t)-1 / size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ return malloc(nmemb * size);
+}
+
+#ifndef HAVE_REALLOCARRAY
+static inline void* reallocarray(void *ptr, size_t nmemb, size_t size) {
+ if (size && nmemb > (size_t)-1 / size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ return realloc(ptr, nmemb * size);
+}
+#endif
diff --git a/libsepol/src/roles.c b/libsepol/src/roles.c
deleted file mode 100644
index 4540cee8..00000000
--- a/libsepol/src/roles.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include <sepol/policydb/hashtab.h>
-#include <sepol/policydb/policydb.h>
-
-#include "debug.h"
-#include "handle.h"
-
-/* Check if a role exists */
-int sepol_role_exists(sepol_handle_t * handle __attribute__ ((unused)),
- sepol_policydb_t * p, const char *role, int *response)
-{
-
- policydb_t *policydb = &p->p;
- *response = (hashtab_search(policydb->p_roles.table, role) != NULL);
-
- return STATUS_SUCCESS;
-}
-
-/* Fill an array with all valid roles */
-int sepol_role_list(sepol_handle_t * handle,
- sepol_policydb_t * p, char ***roles, unsigned int *nroles)
-{
-
- policydb_t *policydb = &p->p;
- unsigned int tmp_nroles = policydb->p_roles.nprim;
- char **tmp_roles = (char **)malloc(tmp_nroles * sizeof(char *));
- char **ptr;
- unsigned int i;
- if (!tmp_roles)
- goto omem;
-
- for (i = 0; i < tmp_nroles; i++) {
- tmp_roles[i] = strdup(policydb->p_role_val_to_name[i]);
- if (!tmp_roles[i])
- goto omem;
- }
-
- *nroles = tmp_nroles;
- *roles = tmp_roles;
-
- return STATUS_SUCCESS;
-
- omem:
- ERR(handle, "out of memory, could not list roles");
-
- ptr = tmp_roles;
- while (ptr && *ptr)
- free(*ptr++);
- free(tmp_roles);
- return STATUS_ERR;
-}
diff --git a/libsepol/src/services.c b/libsepol/src/services.c
index 3758436f..29723729 100644
--- a/libsepol/src/services.c
+++ b/libsepol/src/services.c
@@ -1,4 +1,3 @@
-
/*
* Author : Stephen Smalley, <sds@tycho.nsa.gov>
*/
@@ -59,18 +58,16 @@
#include <sepol/policydb/sidtab.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/conditional.h>
-#include <sepol/policydb/flask.h>
#include <sepol/policydb/util.h>
+#include <sepol/sepol.h>
#include "debug.h"
#include "private.h"
#include "context.h"
-#include "av_permissions.h"
-#include "dso.h"
#include "mls.h"
+#include "flask.h"
#define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
-#define BUG_ON(x) do { if (x) ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0)
static int selinux_enforcing = 1;
@@ -89,7 +86,7 @@ static int next_stack_entry;
static void push(char *expr_ptr)
{
if (next_stack_entry >= stack_len) {
- char **new_stack = stack;
+ char **new_stack;
int new_stack_len;
if (stack_len == 0)
@@ -97,7 +94,7 @@ static void push(char *expr_ptr)
else
new_stack_len = stack_len * 2;
- new_stack = realloc(stack, new_stack_len * sizeof(*stack));
+ new_stack = reallocarray(stack, new_stack_len, sizeof(*stack));
if (!new_stack) {
ERR(NULL, "unable to allocate stack space");
return;
@@ -121,13 +118,13 @@ static char *pop(void)
}
/* End Stack services */
-int hidden sepol_set_sidtab(sidtab_t * s)
+int sepol_set_sidtab(sidtab_t * s)
{
sidtab = s;
return 0;
}
-int hidden sepol_set_policydb(policydb_t * p)
+int sepol_set_policydb(policydb_t * p)
{
policydb = p;
return 0;
@@ -148,7 +145,7 @@ int sepol_set_policydb_from_file(FILE * fp)
}
if (policydb_read(&mypolicydb, &pf, 0)) {
policydb_destroy(&mypolicydb);
- ERR(NULL, "can't read binary policy: %s", strerror(errno));
+ ERR(NULL, "can't read binary policy: %m");
return -1;
}
policydb = &mypolicydb;
@@ -178,7 +175,7 @@ static int expr_buf_len;
static void cat_expr_buf(char *e_buf, const char *string)
{
int len, new_buf_len;
- char *p, *new_buf = e_buf;
+ char *p, *new_buf;
while (1) {
p = e_buf + expr_buf_used;
@@ -293,6 +290,19 @@ static char *get_class_info(sepol_security_class_t tclass,
{
constraint_expr_t *e;
int mls, state_num;
+ /* Determine statement type */
+ const char *statements[] = {
+ "constrain ", /* 0 */
+ "mlsconstrain ", /* 1 */
+ "validatetrans ", /* 2 */
+ "mlsvalidatetrans ", /* 3 */
+ 0 };
+ size_t class_buf_len = 0;
+ size_t new_class_buf_len;
+ size_t buf_used;
+ int len;
+ char *class_buf = NULL, *p;
+ char *new_class_buf = NULL;
/* Find if MLS statement or not */
mls = 0;
@@ -303,30 +313,18 @@ static char *get_class_info(sepol_security_class_t tclass,
}
}
- /* Determine statement type */
- const char *statements[] = {
- "constrain ", /* 0 */
- "mlsconstrain ", /* 1 */
- "validatetrans ", /* 2 */
- "mlsvalidatetrans ", /* 3 */
- 0 };
-
if (xcontext == NULL)
state_num = mls + 0;
else
state_num = mls + 2;
- int class_buf_len = 0;
- int new_class_buf_len;
- int len, buf_used;
- char *class_buf = NULL, *p;
- char *new_class_buf = NULL;
-
while (1) {
new_class_buf_len = class_buf_len + EXPR_BUF_SIZE;
new_class_buf = realloc(class_buf, new_class_buf_len);
- if (!new_class_buf)
- return NULL;
+ if (!new_class_buf) {
+ free(class_buf);
+ return NULL;
+ }
class_buf_len = new_class_buf_len;
class_buf = new_class_buf;
buf_used = 0;
@@ -334,7 +332,7 @@ static char *get_class_info(sepol_security_class_t tclass,
/* Add statement type */
len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]);
- if (len < 0 || len >= class_buf_len - buf_used)
+ if (len < 0 || (size_t)len >= class_buf_len - buf_used)
continue;
/* Add class entry */
@@ -342,7 +340,7 @@ static char *get_class_info(sepol_security_class_t tclass,
buf_used += len;
len = snprintf(p, class_buf_len - buf_used, "%s ",
policydb->p_class_val_to_name[tclass - 1]);
- if (len < 0 || len >= class_buf_len - buf_used)
+ if (len < 0 || (size_t)len >= class_buf_len - buf_used)
continue;
/* Add permission entries (validatetrans does not have perms) */
@@ -355,7 +353,7 @@ static char *get_class_info(sepol_security_class_t tclass,
} else {
len = snprintf(p, class_buf_len - buf_used, "(");
}
- if (len < 0 || len >= class_buf_len - buf_used)
+ if (len < 0 || (size_t)len >= class_buf_len - buf_used)
continue;
break;
}
@@ -408,7 +406,7 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
#define TARGET 2
#define XTARGET 3
- int s_t_x_num = SOURCE;
+ int s_t_x_num;
/* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */
int u_r_t = 0;
@@ -417,6 +415,8 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
char *tgt = NULL;
int rc = 0, x;
char *class_buf = NULL;
+ int expr_list_len = 0;
+ int expr_count;
/*
* The array of expression answer buffer pointers and counter.
@@ -424,6 +424,11 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
char **answer_list = NULL;
int answer_counter = 0;
+ /* The pop operands */
+ char *a;
+ char *b;
+ int a_len, b_len;
+
class_buf = get_class_info(tclass, constraint, xcontext);
if (!class_buf) {
ERR(NULL, "failed to allocate class buffer");
@@ -431,13 +436,12 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
}
/* Original function but with buffer support */
- int expr_list_len = 0;
expr_counter = 0;
expr_list = NULL;
for (e = constraint->expr; e; e = e->next) {
/* Allocate a stack to hold expression buffer entries */
if (expr_counter >= expr_list_len) {
- char **new_expr_list = expr_list;
+ char **new_expr_list;
int new_expr_list_len;
if (expr_list_len == 0)
@@ -445,8 +449,8 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
else
new_expr_list_len = expr_list_len * 2;
- new_expr_list = realloc(expr_list,
- new_expr_list_len * sizeof(*expr_list));
+ new_expr_list = reallocarray(expr_list,
+ new_expr_list_len, sizeof(*expr_list));
if (!new_expr_list) {
ERR(NULL, "failed to allocate expr buffer stack");
rc = -ENOMEM;
@@ -472,18 +476,30 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
/* Now process each expression of the constraint */
switch (e->expr_type) {
case CEXPR_NOT:
- BUG_ON(sp < 0);
+ if (sp < 0) {
+ BUG();
+ rc = -EINVAL;
+ goto out;
+ }
s[sp] = !s[sp];
cat_expr_buf(expr_list[expr_counter], "not");
break;
case CEXPR_AND:
- BUG_ON(sp < 1);
+ if (sp < 1) {
+ BUG();
+ rc = -EINVAL;
+ goto out;
+ }
sp--;
s[sp] &= s[sp + 1];
cat_expr_buf(expr_list[expr_counter], "and");
break;
case CEXPR_OR:
- BUG_ON(sp < 1);
+ if (sp < 1) {
+ BUG();
+ rc = -EINVAL;
+ goto out;
+ }
sp--;
s[sp] |= s[sp + 1];
cat_expr_buf(expr_list[expr_counter], "or");
@@ -689,25 +705,20 @@ mls_ops:
* expr_list malloc's. Normally they are released by the RPN to
* infix code.
*/
- int expr_count = expr_counter;
+ expr_count = expr_counter;
expr_counter = 0;
/*
* Generate the same number of answer buffer entries as expression
* buffers (as there will never be more).
*/
- answer_list = malloc(expr_count * sizeof(*answer_list));
+ answer_list = mallocarray(expr_count, sizeof(*answer_list));
if (!answer_list) {
ERR(NULL, "failed to allocate answer stack");
rc = -ENOMEM;
goto out;
}
- /* The pop operands */
- char *a;
- char *b;
- int a_len, b_len;
-
/* Convert constraint from RPN to infix notation. */
for (x = 0; x != expr_count; x++) {
if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x],
@@ -766,14 +777,6 @@ mls_ops:
xcontext ? "Validatetrans" : "Constraint",
s[0] ? "GRANTED" : "DENIED");
- int len, new_buf_len;
- char *p, **new_buf = r_buf;
- /*
- * These contain the constraint components that are added to the
- * callers reason buffer.
- */
- const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
-
/*
* This will add the constraints to the callers reason buffer (who is
* responsible for freeing the memory). It will handle any realloc's
@@ -784,9 +787,17 @@ mls_ops:
if (r_buf && ((s[0] == 0) || ((s[0] == 1 &&
(flags & SHOW_GRANTED) == SHOW_GRANTED)))) {
+ int len, new_buf_len;
+ char *p, **new_buf = r_buf;
+ /*
+ * These contain the constraint components that are added to the
+ * callers reason buffer.
+ */
+ const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
+
for (x = 0; buffers[x] != NULL; x++) {
while (1) {
- p = *r_buf + reason_buf_used;
+ p = *r_buf ? (*r_buf + reason_buf_used) : NULL;
len = snprintf(p, reason_buf_len - reason_buf_used,
"%s", buffers[x]);
if (len < 0 || len >= reason_buf_len - reason_buf_used) {
@@ -989,8 +1000,8 @@ static int context_struct_compute_av(context_struct_t * scontext,
* role is changing, then check the (current_role, new_role)
* pair.
*/
- if (tclass == SECCLASS_PROCESS &&
- (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) &&
+ if (tclass == policydb->process_class &&
+ (avd->allowed & policydb->process_trans_dyntrans) &&
scontext->role != tcontext->role) {
for (ra = policydb->role_allow; ra; ra = ra->next) {
if (scontext->role == ra->role &&
@@ -998,8 +1009,7 @@ static int context_struct_compute_av(context_struct_t * scontext,
break;
}
if (!ra)
- avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
- PROCESS__DYNTRANSITION);
+ avd->allowed &= ~policydb->process_trans_dyntrans;
}
if (requested & ~avd->allowed) {
@@ -1013,58 +1023,11 @@ static int context_struct_compute_av(context_struct_t * scontext,
return 0;
}
-int hidden sepol_validate_transition(sepol_security_id_t oldsid,
- sepol_security_id_t newsid,
- sepol_security_id_t tasksid,
- sepol_security_class_t tclass)
-{
- context_struct_t *ocontext;
- context_struct_t *ncontext;
- context_struct_t *tcontext;
- class_datum_t *tclass_datum;
- constraint_node_t *constraint;
-
- if (!tclass || tclass > policydb->p_classes.nprim) {
- ERR(NULL, "unrecognized class %d", tclass);
- return -EINVAL;
- }
- tclass_datum = policydb->class_val_to_struct[tclass - 1];
-
- ocontext = sepol_sidtab_search(sidtab, oldsid);
- if (!ocontext) {
- ERR(NULL, "unrecognized SID %d", oldsid);
- return -EINVAL;
- }
-
- ncontext = sepol_sidtab_search(sidtab, newsid);
- if (!ncontext) {
- ERR(NULL, "unrecognized SID %d", newsid);
- return -EINVAL;
- }
-
- tcontext = sepol_sidtab_search(sidtab, tasksid);
- if (!tcontext) {
- ERR(NULL, "unrecognized SID %d", tasksid);
- return -EINVAL;
- }
-
- constraint = tclass_datum->validatetrans;
- while (constraint) {
- if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext,
- 0, constraint, NULL, 0)) {
- return -EPERM;
- }
- constraint = constraint->next;
- }
-
- return 0;
-}
-
/*
* sepol_validate_transition_reason_buffer - the reason buffer is realloc'd
* in the constraint_expr_eval_reason() function.
*/
-int hidden sepol_validate_transition_reason_buffer(sepol_security_id_t oldsid,
+int sepol_validate_transition_reason_buffer(sepol_security_id_t oldsid,
sepol_security_id_t newsid,
sepol_security_id_t tasksid,
sepol_security_class_t tclass,
@@ -1122,7 +1085,7 @@ int hidden sepol_validate_transition_reason_buffer(sepol_security_id_t oldsid,
return 0;
}
-int hidden sepol_compute_av_reason(sepol_security_id_t ssid,
+int sepol_compute_av_reason(sepol_security_id_t ssid,
sepol_security_id_t tsid,
sepol_security_class_t tclass,
sepol_access_vector_t requested,
@@ -1156,7 +1119,7 @@ int hidden sepol_compute_av_reason(sepol_security_id_t ssid,
* REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd
* in the constraint_expr_eval_reason() function.
*/
-int hidden sepol_compute_av_reason_buffer(sepol_security_id_t ssid,
+int sepol_compute_av_reason_buffer(sepol_security_id_t ssid,
sepol_security_id_t tsid,
sepol_security_class_t tclass,
sepol_access_vector_t requested,
@@ -1198,7 +1161,7 @@ out:
return rc;
}
-int hidden sepol_compute_av(sepol_security_id_t ssid,
+int sepol_compute_av(sepol_security_id_t ssid,
sepol_security_id_t tsid,
sepol_security_class_t tclass,
sepol_access_vector_t requested,
@@ -1213,13 +1176,13 @@ int hidden sepol_compute_av(sepol_security_id_t ssid,
* Return a class ID associated with the class string specified by
* class_name.
*/
-int hidden sepol_string_to_security_class(const char *class_name,
+int sepol_string_to_security_class(const char *class_name,
sepol_security_class_t *tclass)
{
class_datum_t *tclass_datum;
tclass_datum = hashtab_search(policydb->p_classes.table,
- (hashtab_key_t) class_name);
+ class_name);
if (!tclass_datum) {
ERR(NULL, "unrecognized class %s", class_name);
return STATUS_ERR;
@@ -1232,7 +1195,7 @@ int hidden sepol_string_to_security_class(const char *class_name,
* Return access vector bit associated with the class ID and permission
* string.
*/
-int hidden sepol_string_to_av_perm(sepol_security_class_t tclass,
+int sepol_string_to_av_perm(sepol_security_class_t tclass,
const char *perm_name,
sepol_access_vector_t *av)
{
@@ -1248,9 +1211,9 @@ int hidden sepol_string_to_av_perm(sepol_security_class_t tclass,
/* Check for unique perms then the common ones (if any) */
perm_datum = (perm_datum_t *)
hashtab_search(tclass_datum->permissions.table,
- (hashtab_key_t)perm_name);
+ perm_name);
if (perm_datum != NULL) {
- *av = 0x1 << (perm_datum->s.value - 1);
+ *av = UINT32_C(1) << (perm_datum->s.value - 1);
return STATUS_SUCCESS;
}
@@ -1259,10 +1222,10 @@ int hidden sepol_string_to_av_perm(sepol_security_class_t tclass,
perm_datum = (perm_datum_t *)
hashtab_search(tclass_datum->comdatum->permissions.table,
- (hashtab_key_t)perm_name);
+ perm_name);
if (perm_datum != NULL) {
- *av = 0x1 << (perm_datum->s.value - 1);
+ *av = UINT32_C(1) << (perm_datum->s.value - 1);
return STATUS_SUCCESS;
}
out:
@@ -1277,7 +1240,7 @@ out:
* to point to this string and set `*scontext_len' to
* the length of the string.
*/
-int hidden sepol_sid_to_context(sepol_security_id_t sid,
+int sepol_sid_to_context(sepol_security_id_t sid,
sepol_security_context_t * scontext,
size_t * scontext_len)
{
@@ -1300,7 +1263,7 @@ int hidden sepol_sid_to_context(sepol_security_id_t sid,
* Return a SID associated with the security context that
* has the string representation specified by `scontext'.
*/
-int hidden sepol_context_to_sid(const sepol_security_context_t scontext,
+int sepol_context_to_sid(const sepol_security_context_t scontext,
size_t scontext_len, sepol_security_id_t * sid)
{
@@ -1361,6 +1324,7 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
sepol_security_class_t tclass,
uint32_t specified, sepol_security_id_t * out_sid)
{
+ struct class_datum *cladatum = NULL;
context_struct_t *scontext = 0, *tcontext = 0, newcontext;
struct role_trans *roletr = 0;
avtab_key_t avkey;
@@ -1381,14 +1345,22 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
goto out;
}
+ if (tclass && tclass <= policydb->p_classes.nprim)
+ cladatum = policydb->class_val_to_struct[tclass - 1];
+
context_init(&newcontext);
/* Set the user identity. */
switch (specified) {
case AVTAB_TRANSITION:
case AVTAB_CHANGE:
- /* Use the process user identity. */
- newcontext.user = scontext->user;
+ if (cladatum && cladatum->default_user == DEFAULT_TARGET) {
+ newcontext.user = tcontext->user;
+ } else {
+ /* notice this gets both DEFAULT_SOURCE and unset */
+ /* Use the process user identity. */
+ newcontext.user = scontext->user;
+ }
break;
case AVTAB_MEMBER:
/* Use the related object owner. */
@@ -1396,18 +1368,31 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
break;
}
- /* Set the role and type to default values. */
- switch (tclass) {
- case SECCLASS_PROCESS:
- /* Use the current role and type of process. */
+ /* Set the role to default values. */
+ if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {
newcontext.role = scontext->role;
+ } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
+ newcontext.role = tcontext->role;
+ } else {
+ if (tclass == policydb->process_class)
+ newcontext.role = scontext->role;
+ else
+ newcontext.role = OBJECT_R_VAL;
+ }
+
+ /* Set the type to default values. */
+ if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
newcontext.type = scontext->type;
- break;
- default:
- /* Use the well-defined object role. */
- newcontext.role = OBJECT_R_VAL;
- /* Use the type of the related object. */
+ } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
newcontext.type = tcontext->type;
+ } else {
+ if (tclass == policydb->process_class) {
+ /* Use the type of process. */
+ newcontext.type = scontext->type;
+ } else {
+ /* Use the type of the related object. */
+ newcontext.type = tcontext->type;
+ }
}
/* Look for a type transition/member/change rule. */
@@ -1435,23 +1420,18 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
}
/* Check for class-specific changes. */
- switch (tclass) {
- case SECCLASS_PROCESS:
- if (specified & AVTAB_TRANSITION) {
- /* Look for a role transition rule. */
- for (roletr = policydb->role_tr; roletr;
- roletr = roletr->next) {
- if (roletr->role == scontext->role &&
- roletr->type == tcontext->type) {
- /* Use the role transition rule. */
- newcontext.role = roletr->new_role;
- break;
- }
+ if (specified & AVTAB_TRANSITION) {
+ /* Look for a role transition rule. */
+ for (roletr = policydb->role_tr; roletr;
+ roletr = roletr->next) {
+ if (roletr->role == scontext->role &&
+ roletr->type == tcontext->type &&
+ roletr->tclass == tclass) {
+ /* Use the role transition rule. */
+ newcontext.role = roletr->new_role;
+ break;
}
}
- break;
- default:
- break;
}
/* Set the MLS attributes.
@@ -1480,7 +1460,7 @@ static int sepol_compute_sid(sepol_security_id_t ssid,
* Compute a SID to use for labeling a new object in the
* class `tclass' based on a SID pair.
*/
-int hidden sepol_transition_sid(sepol_security_id_t ssid,
+int sepol_transition_sid(sepol_security_id_t ssid,
sepol_security_id_t tsid,
sepol_security_class_t tclass,
sepol_security_id_t * out_sid)
@@ -1493,7 +1473,7 @@ int hidden sepol_transition_sid(sepol_security_id_t ssid,
* polyinstantiated object of class `tclass' based on
* a SID pair.
*/
-int hidden sepol_member_sid(sepol_security_id_t ssid,
+int sepol_member_sid(sepol_security_id_t ssid,
sepol_security_id_t tsid,
sepol_security_class_t tclass,
sepol_security_id_t * out_sid)
@@ -1505,7 +1485,7 @@ int hidden sepol_member_sid(sepol_security_id_t ssid,
* Compute a SID to use for relabeling an object in the
* class `tclass' based on a SID pair.
*/
-int hidden sepol_change_sid(sepol_security_id_t ssid,
+int sepol_change_sid(sepol_security_id_t ssid,
sepol_security_id_t tsid,
sepol_security_class_t tclass,
sepol_security_id_t * out_sid)
@@ -1573,7 +1553,7 @@ static int validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p)
cladatum2->comdatum->permissions.table)) {
ERR(NULL,
" in the access vector definition "
- "for class %s\n", key);
+ "for class %s", key);
return -1;
}
}
@@ -1691,7 +1671,7 @@ static int convert_context(sepol_security_id_t key __attribute__ ((unused)),
}
/* Reading from a policy "file". */
-int hidden next_entry(void *buf, struct policy_file *fp, size_t bytes)
+int next_entry(void *buf, struct policy_file *fp, size_t bytes)
{
size_t nread;
@@ -1718,7 +1698,7 @@ int hidden next_entry(void *buf, struct policy_file *fp, size_t bytes)
return 0;
}
-size_t hidden put_entry(const void *ptr, size_t size, size_t n,
+size_t put_entry(const void *ptr, size_t size, size_t n,
struct policy_file *fp)
{
size_t bytes = size * n;
@@ -1753,7 +1733,7 @@ size_t hidden put_entry(const void *ptr, size_t size, size_t n,
* 0 - Success
* -1 - Failure with errno set
*/
-int hidden str_read(char **strp, struct policy_file *fp, size_t len)
+int str_read(char **strp, struct policy_file *fp, size_t len)
{
int rc;
char *str;
@@ -1796,7 +1776,7 @@ int hidden str_read(char **strp, struct policy_file *fp, size_t len)
*
* Reset the access vector cache.
*/
-int hidden sepol_load_policy(void *data, size_t len)
+int sepol_load_policy(void *data, size_t len)
{
policydb_t oldpolicydb, newpolicydb;
sidtab_t oldsidtab, newsidtab;
@@ -1869,7 +1849,7 @@ int hidden sepol_load_policy(void *data, size_t len)
* the file system and the `file_sid' SID is returned
* for all files within that file system.
*/
-int hidden sepol_fs_sid(char *name,
+int sepol_fs_sid(char *name,
sepol_security_id_t * fs_sid,
sepol_security_id_t * file_sid)
{
@@ -1911,7 +1891,7 @@ int hidden sepol_fs_sid(char *name,
* Return the SID of the ibpkey specified by
* `subnet prefix', and `pkey number'.
*/
-int hidden sepol_ibpkey_sid(uint64_t subnet_prefix,
+int sepol_ibpkey_sid(uint64_t subnet_prefix,
uint16_t pkey, sepol_security_id_t *out_sid)
{
ocontext_t *c;
@@ -1947,7 +1927,7 @@ out:
* Return the SID of the subnet management interface specified by
* `device name', and `port'.
*/
-int hidden sepol_ibendport_sid(char *dev_name,
+int sepol_ibendport_sid(char *dev_name,
uint8_t port,
sepol_security_id_t *out_sid)
{
@@ -1984,7 +1964,7 @@ out:
* Return the SID of the port specified by
* `domain', `type', `protocol', and `port'.
*/
-int hidden sepol_port_sid(uint16_t domain __attribute__ ((unused)),
+int sepol_port_sid(uint16_t domain __attribute__ ((unused)),
uint16_t type __attribute__ ((unused)),
uint8_t protocol,
uint16_t port, sepol_security_id_t * out_sid)
@@ -2024,7 +2004,7 @@ int hidden sepol_port_sid(uint16_t domain __attribute__ ((unused)),
* the default SID for messages received on the
* interface.
*/
-int hidden sepol_netif_sid(char *name,
+int sepol_netif_sid(char *name,
sepol_security_id_t * if_sid,
sepol_security_id_t * msg_sid)
{
@@ -2082,7 +2062,7 @@ static int match_ipv6_addrmask(uint32_t * input, uint32_t * addr,
* in bytes and `domain' is the communications domain or
* address family in which the address should be interpreted.
*/
-int hidden sepol_node_sid(uint16_t domain,
+int sepol_node_sid(uint16_t domain,
void *addrp,
size_t addrlen, sepol_security_id_t * out_sid)
{
@@ -2155,7 +2135,7 @@ int hidden sepol_node_sid(uint16_t domain,
*/
#define SIDS_NEL 25
-int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
+int sepol_get_user_sids(sepol_security_id_t fromsid,
char *username,
sepol_security_id_t ** sids, uint32_t * nel)
{
@@ -2183,7 +2163,7 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
}
usercon.user = user->s.value;
- mysids = malloc(maxnel * sizeof(sepol_security_id_t));
+ mysids = mallocarray(maxnel, sizeof(sepol_security_id_t));
if (!mysids) {
rc = -ENOMEM;
goto out;
@@ -2203,10 +2183,10 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
continue;
rc = context_struct_compute_av(fromcon, &usercon,
- SECCLASS_PROCESS,
- PROCESS__TRANSITION,
+ policydb->process_class,
+ policydb->process_trans,
&avd, &reason, NULL, 0);
- if (rc || !(avd.allowed & PROCESS__TRANSITION))
+ if (rc || !(avd.allowed & policydb->process_trans))
continue;
rc = sepol_sidtab_context_to_sid(sidtab, &usercon,
&sid);
@@ -2219,7 +2199,7 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
} else {
maxnel += SIDS_NEL;
mysids2 =
- malloc(maxnel *
+ mallocarray(maxnel,
sizeof(sepol_security_id_t));
if (!mysids2) {
@@ -2250,7 +2230,7 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
* that cannot support a persistent label mapping or use another
* fixed labeling behavior like transition SIDs or task SIDs.
*/
-int hidden sepol_genfs_sid(const char *fstype,
+int sepol_genfs_sid(const char *fstype,
const char *path,
sepol_security_class_t sclass,
sepol_security_id_t * sid)
@@ -2297,7 +2277,7 @@ int hidden sepol_genfs_sid(const char *fstype,
return rc;
}
-int hidden sepol_fs_use(const char *fstype,
+int sepol_fs_use(const char *fstype,
unsigned int *behavior, sepol_security_id_t * sid)
{
int rc = 0;
@@ -2321,7 +2301,7 @@ int hidden sepol_fs_use(const char *fstype,
}
*sid = c->sid[0];
} else {
- rc = sepol_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
+ rc = sepol_genfs_sid(fstype, "/", policydb->dir_class, sid);
if (rc) {
*behavior = SECURITY_FS_USE_NONE;
rc = 0;
diff --git a/libsepol/src/sidtab.c b/libsepol/src/sidtab.c
index 23b2e8f3..adeae6eb 100644
--- a/libsepol/src/sidtab.c
+++ b/libsepol/src/sidtab.c
@@ -14,7 +14,8 @@
#include <sepol/policydb/sidtab.h>
-#include <sepol/policydb/flask.h>
+#include "flask.h"
+#include "private.h"
#define SIDTAB_HASH(sid) \
(sid & SIDTAB_HASH_MASK)
@@ -27,7 +28,7 @@ int sepol_sidtab_init(sidtab_t * s)
{
int i;
- s->htable = malloc(sizeof(sidtab_ptr_t) * SIDTAB_SIZE);
+ s->htable = mallocarray(SIDTAB_SIZE, sizeof(sidtab_ptr_t));
if (!s->htable)
return -ENOMEM;
for (i = 0; i < SIDTAB_SIZE; i++)
@@ -84,37 +85,6 @@ int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid,
return 0;
}
-int sepol_sidtab_remove(sidtab_t * s, sepol_security_id_t sid)
-{
- int hvalue;
- sidtab_node_t *cur, *last;
-
- if (!s || !s->htable)
- return -ENOENT;
-
- hvalue = SIDTAB_HASH(sid);
- last = NULL;
- cur = s->htable[hvalue];
- while (cur != NULL && sid > cur->sid) {
- last = cur;
- cur = cur->next;
- }
-
- if (cur == NULL || sid != cur->sid)
- return -ENOENT;
-
- if (last == NULL)
- s->htable[hvalue] = cur->next;
- else
- last->next = cur->next;
-
- context_destroy(&cur->context);
-
- free(cur);
- s->nel--;
- return 0;
-}
-
context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid)
{
int hvalue;
diff --git a/libsepol/src/symtab.c b/libsepol/src/symtab.c
index 9a417ca2..a6061851 100644
--- a/libsepol/src/symtab.c
+++ b/libsepol/src/symtab.c
@@ -8,9 +8,13 @@
*/
#include <string.h>
+
+#include "private.h"
+
#include <sepol/policydb/hashtab.h>
#include <sepol/policydb/symtab.h>
+ignore_unsigned_overflow_
static unsigned int symhash(hashtab_t h, const_hashtab_key_t key)
{
const char *p, *keyp;
diff --git a/libsepol/src/user_internal.h b/libsepol/src/user_internal.h
index 7523b7d5..f5b22b02 100644
--- a/libsepol/src/user_internal.h
+++ b/libsepol/src/user_internal.h
@@ -3,18 +3,5 @@
#include <sepol/user_record.h>
#include <sepol/users.h>
-#include "dso.h"
-hidden_proto(sepol_user_add_role)
- hidden_proto(sepol_user_create)
- hidden_proto(sepol_user_free)
- hidden_proto(sepol_user_get_mlslevel)
- hidden_proto(sepol_user_get_mlsrange)
- hidden_proto(sepol_user_get_roles)
- hidden_proto(sepol_user_has_role)
- hidden_proto(sepol_user_key_create)
- hidden_proto(sepol_user_key_unpack)
- hidden_proto(sepol_user_set_mlslevel)
- hidden_proto(sepol_user_set_mlsrange)
- hidden_proto(sepol_user_set_name)
#endif
diff --git a/libsepol/src/user_record.c b/libsepol/src/user_record.c
index fa95f2d1..404fa3a8 100644
--- a/libsepol/src/user_record.c
+++ b/libsepol/src/user_record.c
@@ -4,6 +4,7 @@
#include "user_internal.h"
#include "debug.h"
+#include "private.h"
struct sepol_user {
/* This user's name */
@@ -51,7 +52,6 @@ int sepol_user_key_create(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_user_key_create)
void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name)
{
@@ -59,7 +59,6 @@ void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name)
*name = key->name;
}
-hidden_def(sepol_user_key_unpack)
int sepol_user_key_extract(sepol_handle_t * handle,
const sepol_user_t * user,
@@ -115,7 +114,6 @@ int sepol_user_set_name(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_user_set_name)
/* MLS */
const char *sepol_user_get_mlslevel(const sepol_user_t * user)
@@ -124,7 +122,6 @@ const char *sepol_user_get_mlslevel(const sepol_user_t * user)
return user->mls_level;
}
-hidden_def(sepol_user_get_mlslevel)
int sepol_user_set_mlslevel(sepol_handle_t * handle,
sepol_user_t * user, const char *mls_level)
@@ -141,7 +138,6 @@ int sepol_user_set_mlslevel(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_user_set_mlslevel)
const char *sepol_user_get_mlsrange(const sepol_user_t * user)
{
@@ -149,7 +145,6 @@ const char *sepol_user_get_mlsrange(const sepol_user_t * user)
return user->mls_range;
}
-hidden_def(sepol_user_get_mlsrange)
int sepol_user_set_mlsrange(sepol_handle_t * handle,
sepol_user_t * user, const char *mls_range)
@@ -166,7 +161,6 @@ int sepol_user_set_mlsrange(sepol_handle_t * handle,
return STATUS_SUCCESS;
}
-hidden_def(sepol_user_set_mlsrange)
/* Roles */
int sepol_user_get_num_roles(const sepol_user_t * user)
@@ -189,8 +183,9 @@ int sepol_user_add_role(sepol_handle_t * handle,
if (!role_cp)
goto omem;
- roles_realloc = realloc(user->roles,
- sizeof(char *) * (user->num_roles + 1));
+ roles_realloc = reallocarray(user->roles,
+ user->num_roles + 1,
+ sizeof(char *));
if (!roles_realloc)
goto omem;
@@ -207,7 +202,6 @@ int sepol_user_add_role(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_user_add_role)
int sepol_user_has_role(const sepol_user_t * user, const char *role)
{
@@ -220,7 +214,6 @@ int sepol_user_has_role(const sepol_user_t * user, const char *role)
return 0;
}
-hidden_def(sepol_user_has_role)
int sepol_user_set_roles(sepol_handle_t * handle,
sepol_user_t * user,
@@ -274,7 +267,7 @@ int sepol_user_get_roles(sepol_handle_t * handle,
unsigned int i;
const char **tmp_roles =
- (const char **)malloc(sizeof(char *) * user->num_roles);
+ (const char **)mallocarray(user->num_roles, sizeof(char *));
if (!tmp_roles)
goto omem;
@@ -292,7 +285,6 @@ int sepol_user_get_roles(sepol_handle_t * handle,
return STATUS_ERR;
}
-hidden_def(sepol_user_get_roles)
void sepol_user_del_role(sepol_user_t * user, const char *role)
{
@@ -330,7 +322,6 @@ int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr)
return STATUS_SUCCESS;
}
-hidden_def(sepol_user_create)
/* Deep copy clone */
int sepol_user_clone(sepol_handle_t * handle,
@@ -386,4 +377,3 @@ void sepol_user_free(sepol_user_t * user)
free(user);
}
-hidden_def(sepol_user_free)
diff --git a/libsepol/src/users.c b/libsepol/src/users.c
index b895b7f5..a7406214 100644
--- a/libsepol/src/users.c
+++ b/libsepol/src/users.c
@@ -226,17 +226,17 @@ int sepol_user_modify(sepol_handle_t * handle,
void *tmp_ptr;
/* Ensure reverse lookup array has enough space */
- tmp_ptr = realloc(policydb->user_val_to_struct,
- (policydb->p_users.nprim +
- 1) * sizeof(user_datum_t *));
+ tmp_ptr = reallocarray(policydb->user_val_to_struct,
+ policydb->p_users.nprim + 1,
+ sizeof(user_datum_t *));
if (!tmp_ptr)
goto omem;
policydb->user_val_to_struct = tmp_ptr;
policydb->user_val_to_struct[policydb->p_users.nprim] = NULL;
- tmp_ptr = realloc(policydb->sym_val_to_name[SYM_USERS],
- (policydb->p_users.nprim +
- 1) * sizeof(char *));
+ tmp_ptr = reallocarray(policydb->sym_val_to_name[SYM_USERS],
+ policydb->p_users.nprim + 1,
+ sizeof(char *));
if (!tmp_ptr)
goto omem;
policydb->sym_val_to_name[SYM_USERS] = tmp_ptr;
diff --git a/libsepol/src/util.c b/libsepol/src/util.c
index a4008882..1cd1308d 100644
--- a/libsepol/src/util.c
+++ b/libsepol/src/util.c
@@ -27,7 +27,8 @@
#include <sepol/policydb/flask_types.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/util.h>
-#include <dso.h>
+
+#include "private.h"
struct val_to_name {
unsigned int val;
@@ -41,6 +42,8 @@ struct val_to_name {
* 0). Return 0 on success, -1 on out of memory. */
int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a)
{
+ uint32_t *new;
+
if (cnt == NULL || a == NULL)
return -1;
@@ -49,17 +52,18 @@ int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a)
* than be smart about it, for now we realloc() the array each
* time a new uint32_t is added! */
if (*a != NULL)
- *a = (uint32_t *) realloc(*a, (*cnt + 1) * sizeof(uint32_t));
+ new = (uint32_t *) reallocarray(*a, *cnt + 1, sizeof(uint32_t));
else { /* empty list */
*cnt = 0;
- *a = (uint32_t *) malloc(sizeof(uint32_t));
+ new = (uint32_t *) malloc(sizeof(uint32_t));
}
- if (*a == NULL) {
+ if (new == NULL) {
return -1;
}
- (*a)[*cnt] = i;
+ new[*cnt] = i;
(*cnt)++;
+ *a = new;
return 0;
}
@@ -93,7 +97,7 @@ char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass,
cladatum = policydbp->class_val_to_struct[tclass - 1];
p = avbuf;
for (i = 0; i < cladatum->permissions.nprim; i++) {
- if (av & (1 << i)) {
+ if (av & (UINT32_C(1) << i)) {
v.val = i + 1;
rc = hashtab_map(cladatum->permissions.table,
perm_name, &v);
@@ -130,9 +134,9 @@ char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms)
unsigned int bit;
unsigned int in_range = 0;
static char xpermsbuf[2048];
- xpermsbuf[0] = '\0';
char *p;
int len, xpermslen = 0;
+ xpermsbuf[0] = '\0';
p = xpermsbuf;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
@@ -250,7 +254,7 @@ static inline int tokenize_str(char delim, char **str, char **ptr, size_t *len)
* contain the remaining content of line_buf. If the delimiter is any whitespace
* character, then all whitespace will be squashed.
*/
-int hidden tokenize(char *line_buf, char delim, int num_args, ...)
+int tokenize(char *line_buf, char delim, int num_args, ...)
{
char **arg, *buf_p;
int rc, items;
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 65aba32a..db244c08 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -40,7 +40,6 @@
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/expand.h>
-#include <sepol/policydb/flask.h>
#include "debug.h"
#include "private.h"
@@ -514,7 +513,7 @@ static int role_trans_write(policydb_t *p, struct policy_file *fp)
nel = 0;
for (tr = r; tr; tr = tr->next)
- if(new_roletr || tr->tclass == SECCLASS_PROCESS)
+ if(new_roletr || tr->tclass == p->process_class)
nel++;
buf[0] = cpu_to_le32(nel);
@@ -522,7 +521,7 @@ static int role_trans_write(policydb_t *p, struct policy_file *fp)
if (items != 1)
return POLICYDB_ERROR;
for (tr = r; tr; tr = tr->next) {
- if (!new_roletr && tr->tclass != SECCLASS_PROCESS) {
+ if (!new_roletr && tr->tclass != p->process_class) {
if (!warning_issued)
WARN(fp->handle, "Discarding role_transition "
"rules for security classes other than "
@@ -570,12 +569,48 @@ static int role_allow_write(role_allow_t * r, struct policy_file *fp)
return POLICYDB_SUCCESS;
}
-static int filename_write_helper(hashtab_key_t key, void *data, void *ptr)
+static int filename_write_one_compat(hashtab_key_t key, void *data, void *ptr)
{
- uint32_t buf[4];
+ uint32_t bit, buf[4];
size_t items, len;
- struct filename_trans *ft = (struct filename_trans *)key;
- struct filename_trans_datum *otype = data;
+ filename_trans_key_t *ft = (filename_trans_key_t *)key;
+ filename_trans_datum_t *datum = data;
+ ebitmap_node_t *node;
+ void *fp = ptr;
+
+ len = strlen(ft->name);
+ do {
+ ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
+ buf[0] = cpu_to_le32(len);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+
+ items = put_entry(ft->name, sizeof(char), len, fp);
+ if (items != len)
+ return POLICYDB_ERROR;
+
+ buf[0] = cpu_to_le32(bit + 1);
+ buf[1] = cpu_to_le32(ft->ttype);
+ buf[2] = cpu_to_le32(ft->tclass);
+ buf[3] = cpu_to_le32(datum->otype);
+ items = put_entry(buf, sizeof(uint32_t), 4, fp);
+ if (items != 4)
+ return POLICYDB_ERROR;
+ }
+
+ datum = datum->next;
+ } while (datum);
+
+ return 0;
+}
+
+static int filename_write_one(hashtab_key_t key, void *data, void *ptr)
+{
+ uint32_t buf[3];
+ size_t items, len, ndatum;
+ filename_trans_key_t *ft = (filename_trans_key_t *)key;
+ filename_trans_datum_t *datum;
void *fp = ptr;
len = strlen(ft->name);
@@ -588,37 +623,62 @@ static int filename_write_helper(hashtab_key_t key, void *data, void *ptr)
if (items != len)
return POLICYDB_ERROR;
- buf[0] = cpu_to_le32(ft->stype);
- buf[1] = cpu_to_le32(ft->ttype);
- buf[2] = cpu_to_le32(ft->tclass);
- buf[3] = cpu_to_le32(otype->otype);
- items = put_entry(buf, sizeof(uint32_t), 4, fp);
- if (items != 4)
+ ndatum = 0;
+ datum = data;
+ do {
+ ndatum++;
+ datum = datum->next;
+ } while (datum);
+
+ buf[0] = cpu_to_le32(ft->ttype);
+ buf[1] = cpu_to_le32(ft->tclass);
+ buf[2] = cpu_to_le32(ndatum);
+ items = put_entry(buf, sizeof(uint32_t), 3, fp);
+ if (items != 3)
return POLICYDB_ERROR;
+ datum = data;
+ do {
+ if (ebitmap_write(&datum->stypes, fp))
+ return POLICYDB_ERROR;
+
+ buf[0] = cpu_to_le32(datum->otype);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
+
+ datum = datum->next;
+ } while (datum);
+
return 0;
}
static int filename_trans_write(struct policydb *p, void *fp)
{
- size_t nel, items;
+ size_t items;
uint32_t buf[1];
int rc;
if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
return 0;
- nel = p->filename_trans->nel;
- buf[0] = cpu_to_le32(nel);
- items = put_entry(buf, sizeof(uint32_t), 1, fp);
- if (items != 1)
- return POLICYDB_ERROR;
+ if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
+ buf[0] = cpu_to_le32(p->filename_trans_count);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
- rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
- if (rc)
- return rc;
+ rc = hashtab_map(p->filename_trans, filename_write_one_compat,
+ fp);
+ } else {
+ buf[0] = cpu_to_le32(p->filename_trans->nel);
+ items = put_entry(buf, sizeof(uint32_t), 1, fp);
+ if (items != 1)
+ return POLICYDB_ERROR;
- return 0;
+ rc = hashtab_map(p->filename_trans, filename_write_one, fp);
+ }
+ return rc;
}
static int role_set_write(role_set_t * x, struct policy_file *fp)
@@ -1285,7 +1345,7 @@ static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
common_write, class_write, role_write, type_write, user_write,
cond_write_bool, sens_write, cat_write,};
-static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
+static int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p,
struct policy_file *fp)
{
unsigned int i, j;
@@ -1393,7 +1453,7 @@ static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
return POLICYDB_SUCCESS;
}
-static int ocontext_write_selinux(struct policydb_compat_info *info,
+static int ocontext_write_selinux(const struct policydb_compat_info *info,
policydb_t *p, struct policy_file *fp)
{
unsigned int i, j;
@@ -1523,7 +1583,7 @@ static int ocontext_write_selinux(struct policydb_compat_info *info,
return POLICYDB_SUCCESS;
}
-static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
+static int ocontext_write(const struct policydb_compat_info *info, policydb_t * p,
struct policy_file *fp)
{
int rc = POLICYDB_ERROR;
@@ -1592,6 +1652,7 @@ struct rangetrans_write_args {
size_t nel;
int new_rangetr;
struct policy_file *fp;
+ struct policydb *p;
};
static int rangetrans_count(hashtab_key_t key,
@@ -1600,11 +1661,12 @@ static int rangetrans_count(hashtab_key_t key,
{
struct range_trans *rt = (struct range_trans *)key;
struct rangetrans_write_args *args = ptr;
+ struct policydb *p = args->p;
/* all range_transitions are written for the new format, only
process related range_transitions are written for the old
format, so count accordingly */
- if (args->new_rangetr || rt->target_class == SECCLASS_PROCESS)
+ if (args->new_rangetr || rt->target_class == p->process_class)
args->nel++;
return 0;
}
@@ -1616,12 +1678,13 @@ static int range_write_helper(hashtab_key_t key, void *data, void *ptr)
struct mls_range *r = data;
struct rangetrans_write_args *args = ptr;
struct policy_file *fp = args->fp;
+ struct policydb *p = args->p;
int new_rangetr = args->new_rangetr;
size_t items;
static int warning_issued = 0;
int rc;
- if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
+ if (!new_rangetr && rt->target_class != p->process_class) {
if (!warning_issued)
WARN(fp->handle, "Discarding range_transition "
"rules for security classes other than "
@@ -1660,6 +1723,7 @@ static int range_write(policydb_t * p, struct policy_file *fp)
args.nel = 0;
args.new_rangetr = new_rangetr;
args.fp = fp;
+ args.p = p;
rc = hashtab_map(p->range_tr, rangetrans_count, &args);
if (rc)
return rc;
@@ -1784,13 +1848,18 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules,
return POLICYDB_SUCCESS;
}
-static int only_process(ebitmap_t *in)
+static int only_process(ebitmap_t *in, struct policydb *p)
{
- unsigned int i;
+ unsigned int i, value;
ebitmap_node_t *node;
+ if (!p->process_class)
+ return 0;
+
+ value = p->process_class - 1;
+
ebitmap_for_each_positive_bit(in, node, i) {
- if (i != SECCLASS_PROCESS - 1)
+ if (i != value)
return 0;
}
return 1;
@@ -1807,7 +1876,7 @@ static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
for (tr = t; tr; tr = tr->next)
- if (new_role || only_process(&tr->classes))
+ if (new_role || only_process(&tr->classes, p))
nel++;
buf[0] = cpu_to_le32(nel);
@@ -1815,7 +1884,7 @@ static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
if (items != 1)
return POLICYDB_ERROR;
for (tr = t; tr; tr = tr->next) {
- if (!new_role && !only_process(&tr->classes)) {
+ if (!new_role && !only_process(&tr->classes, p)) {
if (!warned)
WARN(fp->handle, "Discarding role_transition "
"rules for security classes other than "
@@ -2048,7 +2117,7 @@ static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
* buffer. this would have been easier with C99's
* dynamic arrays... */
rc = POLICYDB_ERROR;
- dyn_buf = malloc(items * sizeof(*dyn_buf));
+ dyn_buf = mallocarray(items, sizeof(*dyn_buf));
if (!dyn_buf)
goto err;
buf = dyn_buf;
@@ -2110,7 +2179,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
unsigned int i, num_syms;
uint32_t buf[32], config;
size_t items, items2, len;
- struct policydb_compat_info *info;
+ const struct policydb_compat_info *info;
struct policy_data pd;
const char *policydb_str;
@@ -2138,6 +2207,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
config |= POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE;
+ config |= POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH;
/* Write the magic number and string identifiers. */
items = 0;
diff --git a/libsepol/tests/Makefile b/libsepol/tests/Makefile
index e7e305e8..a72c327d 100644
--- a/libsepol/tests/Makefile
+++ b/libsepol/tests/Makefile
@@ -1,3 +1,4 @@
+ENV ?= env
M4 ?= m4
MKDIR ?= mkdir
EXE ?= libsepol-tests
@@ -32,7 +33,7 @@ all: $(EXE) $(policies)
policies: $(policies)
$(EXE): $(objs) $(parserobjs) $(LIBSEPOL)
- $(CC) $(LDFLAGS) $(objs) $(parserobjs) -lcunit -lcurses $(LIBSEPOL) -o $@
+ $(CC) $(LDFLAGS) $(objs) $(parserobjs) -lcunit $(LIBSEPOL) -o $@
%.conf.std: $(m4support) %.conf
$(M4) $(M4PARAMS) $^ > $@
@@ -44,10 +45,15 @@ clean:
rm -f $(objs) $(EXE)
rm -f $(policies)
rm -f policies/test-downgrade/policy.hi policies/test-downgrade/policy.lo
-
+# mkdir is run in a clean environment created by env -i to avoid failing under ASan with:
+#
+# ASan runtime does not come first in initial library list;
+# you should either link runtime to your application or manually preload it with LD_PRELOAD
+#
+# when the source code is built with ASan
test: $(EXE) $(policies)
- $(MKDIR) -p policies/test-downgrade
+ $(ENV) -i $(MKDIR) -p policies/test-downgrade
../../checkpolicy/checkpolicy -M policies/test-cond/refpolicy-base.conf -o policies/test-downgrade/policy.hi
./$(EXE)
diff --git a/libsepol/tests/libsepol-tests.c b/libsepol/tests/libsepol-tests.c
index 544c792d..dc8fd5ce 100644
--- a/libsepol/tests/libsepol-tests.c
+++ b/libsepol/tests/libsepol-tests.c
@@ -36,13 +36,17 @@
int mls;
#define DECLARE_SUITE(name) \
- suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \
- if (NULL == suite) { \
- CU_cleanup_registry(); \
- return CU_get_error(); } \
- if (name##_add_tests(suite)) { \
- CU_cleanup_registry(); \
- return CU_get_error(); }
+ do { \
+ suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \
+ if (NULL == suite) { \
+ CU_cleanup_registry(); \
+ return CU_get_error(); \
+ } \
+ if (name##_add_tests(suite)) { \
+ CU_cleanup_registry(); \
+ return CU_get_error(); \
+ } \
+ } while (0)
static void usage(char *progname)
{
diff --git a/mcstrans/Makefile b/mcstrans/Makefile
index c993a9f5..b20279ab 100644
--- a/mcstrans/Makefile
+++ b/mcstrans/Makefile
@@ -1,3 +1,9 @@
+PKG_CONFIG ?= pkg-config
+PCRE_MODULE := libpcre2-8
+PCRE_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(PCRE_MODULE)) -DPCRE2_CODE_UNIT_WIDTH=8
+PCRE_LDLIBS := $(shell $(PKG_CONFIG) --libs $(PCRE_MODULE))
+export PCRE_MODULE PCRE_CFLAGS PCRE_LDLIBS
+
all:
$(MAKE) -C src
$(MAKE) -C utils
diff --git a/mcstrans/VERSION b/mcstrans/VERSION
index 9f55b2cc..eb39e538 100644
--- a/mcstrans/VERSION
+++ b/mcstrans/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/mcstrans/share/util/mlstrans-test b/mcstrans/share/util/mlstrans-test
index 085fa82d..df34e0e6 100644
--- a/mcstrans/share/util/mlstrans-test
+++ b/mcstrans/share/util/mlstrans-test
@@ -15,7 +15,7 @@ def untrans(trans, val):
errors += 1
else:
if verbose:
- print("untrans: %s -> %s != %s SUCCESS" % (trans, raw, val))
+ print("untrans: '%s' -> '%s' == '%s' SUCCESS" % (trans, raw, val))
def trans(raw, val):
@@ -26,7 +26,7 @@ def trans(raw, val):
errors += 1
else:
if verbose:
- print("trans: %s -> %s != %s SUCCESS" % (raw, trans, val))
+ print("trans: '%s' -> '%s' == '%s' SUCCESS" % (raw, trans, val))
if len(sys.argv) > 1 and sys.argv[1] == "-v":
diff --git a/mcstrans/src/Makefile b/mcstrans/src/Makefile
index 76ef0557..ef518625 100644
--- a/mcstrans/src/Makefile
+++ b/mcstrans/src/Makefile
@@ -20,10 +20,10 @@ CFLAGS ?= -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute
all: $(PROG)
$(PROG): $(PROG_OBJS) $(LIBSEPOLA)
- $(CC) $(LDFLAGS) -pie -o $@ $^ -lselinux -lcap -lpcre $(LDLIBS_LIBSEPOLA)
+ $(CC) $(LDFLAGS) -pie -o $@ $^ -lselinux -lcap $(PCRE_LDLIBS) $(LDLIBS_LIBSEPOLA)
%.o: %.c
- $(CC) $(CFLAGS) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -fPIE -c -o $@ $<
+ $(CC) $(CFLAGS) $(PCRE_CFLAGS) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -fPIE -c -o $@ $<
install: all
test -d $(DESTDIR)$(SBINDIR) || install -m 755 -d $(DESTDIR)$(SBINDIR)
diff --git a/mcstrans/src/mcscolor.c b/mcstrans/src/mcscolor.c
index 4ee0db50..9ff0ce2f 100644
--- a/mcstrans/src/mcscolor.c
+++ b/mcstrans/src/mcscolor.c
@@ -11,6 +11,8 @@
#include <syslog.h>
#include <selinux/selinux.h>
#include <selinux/context.h>
+
+#include "mcscolor.h"
#include "mcstrans.h"
/* Define data structures */
@@ -44,7 +46,7 @@ static setab_t *clist[N_COLOR];
static setab_t *cend[N_COLOR];
static semnemonic_t *mnemonics;
-static security_context_t my_context;
+static char *my_context;
void finish_context_colors(void) {
setab_t *cur, *next;
@@ -76,7 +78,7 @@ void finish_context_colors(void) {
}
static int check_dominance(const char *pattern, const char *raw) {
- security_context_t ctx;
+ char *ctx;
context_t con;
struct av_decision avd;
int rc = -1;
@@ -109,7 +111,7 @@ static int check_dominance(const char *pattern, const char *raw) {
if (!raw)
goto out;
- rc = security_compute_av_raw(ctx, (security_context_t)raw, context_class, context_contains_perm, &avd);
+ rc = security_compute_av_raw(ctx, raw, context_class, context_contains_perm, &avd);
if (rc)
goto out;
@@ -282,7 +284,7 @@ static int parse_components(context_t con, char **components) {
/* Look up colors.
*/
-int raw_color(const security_context_t raw, char **color_str) {
+int raw_color(const char *raw, char **color_str) {
#define CHARS_PER_COLOR 16
context_t con;
uint32_t i, j, mask = 0;
diff --git a/mcstrans/src/mcscolor.h b/mcstrans/src/mcscolor.h
new file mode 100644
index 00000000..c37fe6ed
--- /dev/null
+++ b/mcstrans/src/mcscolor.h
@@ -0,0 +1,8 @@
+#ifndef __mcscolor_h__
+#define __mcscolor_h__
+
+extern void finish_context_colors(void);
+extern int init_colors(void);
+extern int raw_color(const char *raw, char **color_str);
+
+#endif
diff --git a/mcstrans/src/mcstrans.c b/mcstrans/src/mcstrans.c
index 96bdbdff..d42760fd 100644
--- a/mcstrans/src/mcstrans.c
+++ b/mcstrans/src/mcstrans.c
@@ -7,8 +7,8 @@
int init_translations(void);
void finish_context_translations(void);
- int trans_context(const security_context_t, security_context_t *);
- int untrans_context(const security_context_t, security_context_t *);
+ int trans_context(const char *, char **);
+ int untrans_context(const char *, char **);
*/
@@ -26,7 +26,7 @@
#include <selinux/context.h>
#include <syslog.h>
#include <errno.h>
-#include <pcre.h>
+#include <pcre2.h>
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
@@ -36,14 +36,13 @@
#include "mcstrans.h"
#define N_BUCKETS 1453
-#define OVECCOUNT (512*3)
#define log_error(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#ifdef DEBUG
#define log_debug(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else
-#define log_debug(fmt, ...) ;
+#define log_debug(fmt, ...) do {} while (0)
#endif
static unsigned int maxbit=0;
@@ -82,9 +81,9 @@ typedef struct word_group {
affix_t *suffixes;
word_t *words;
- pcre *prefix_regexp;
- pcre *word_regexp;
- pcre *suffix_regexp;
+ pcre2_code *prefix_regexp;
+ pcre2_code *word_regexp;
+ pcre2_code *suffix_regexp;
ebitmap_t def;
@@ -109,7 +108,7 @@ typedef struct domain {
base_classification_t *base_classifications;
word_group_t *groups;
- pcre *base_classification_regexp;
+ pcre2_code *base_classification_regexp;
struct domain *next;
} domain_t;
@@ -136,7 +135,7 @@ typedef struct cat_constraint {
static cat_constraint_t *cat_constraints;
-unsigned int
+static unsigned int
hash(const char *str) {
unsigned int hash = 5381;
int c;
@@ -213,7 +212,7 @@ parse_category(ebitmap_t *e, const char *raw, int allowinverse)
return 0;
}
-int
+static int
parse_ebitmap(ebitmap_t *e, ebitmap_t *def, const char *raw) {
int rc = ebitmap_cpy(e, def);
if (rc < 0)
@@ -224,7 +223,7 @@ parse_ebitmap(ebitmap_t *e, ebitmap_t *def, const char *raw) {
return 0;
}
-mls_level_t *
+static mls_level_t *
parse_raw(const char *raw) {
mls_level_t *mls = calloc(1, sizeof(mls_level_t));
if (!mls)
@@ -248,7 +247,7 @@ err:
return NULL;
}
-void
+static void
destroy_word(word_t **list, word_t *word) {
if (!word) {
return;
@@ -267,7 +266,7 @@ destroy_word(word_t **list, word_t *word) {
free(word);
}
-word_t *
+static word_t *
create_word(word_t **list, const char *text) {
word_t *w = calloc(1, sizeof(word_t));
if (!w) {
@@ -291,7 +290,7 @@ err:
return NULL;
}
-void
+static void
destroy_group(word_group_t **list, word_group_t *group) {
for (; list && *list; list = &(*list)->next) {
if (*list == group) {
@@ -317,14 +316,14 @@ destroy_group(word_group_t **list, word_group_t *group) {
free(group->name);
free(group->sword);
free(group->join);
- pcre_free(group->prefix_regexp);
- pcre_free(group->word_regexp);
- pcre_free(group->suffix_regexp);
+ pcre2_code_free(group->prefix_regexp);
+ pcre2_code_free(group->word_regexp);
+ pcre2_code_free(group->suffix_regexp);
ebitmap_destroy(&group->def);
free(group);
}
-word_group_t *
+static word_group_t *
create_group(word_group_t **list, const char *name) {
word_group_t *group = calloc(1, sizeof(word_group_t));
if (!group)
@@ -357,7 +356,7 @@ err:
return NULL;
}
-void
+static void
destroy_domain(domain_t *domain) {
int i;
unsigned int rt = 0, tr = 0;
@@ -392,7 +391,7 @@ destroy_domain(domain_t *domain) {
free(domain->base_classifications);
domain->base_classifications = next;
}
- pcre_free(domain->base_classification_regexp);
+ pcre2_code_free(domain->base_classification_regexp);
while (domain->groups)
destroy_group(&domain->groups, domain->groups);
free(domain->name);
@@ -401,7 +400,7 @@ destroy_domain(domain_t *domain) {
syslog(LOG_INFO, "cache sizes: tr = %u, rt = %u", tr, rt);
}
-domain_t *
+static domain_t *
create_domain(const char *name) {
domain_t *domain = calloc(1, sizeof(domain_t));
if (!domain) {
@@ -425,7 +424,7 @@ err:
return NULL;
}
-int
+static int
add_word(word_group_t *group, char *raw, char *trans) {
if (strchr(trans,'-')) {
log_error("'%s'is invalid because '-' is illegal in modifiers.\n", trans);
@@ -451,7 +450,7 @@ add_word(word_group_t *group, char *raw, char *trans) {
return 0;
}
-int
+static int
add_constraint(char op, char *raw, char *tok) {
log_debug("%s\n", "add_constraint");
ebitmap_t empty;
@@ -521,7 +520,7 @@ add_constraint(char op, char *raw, char *tok) {
return 0;
}
-int
+static int
violates_constraints(mls_level_t *l) {
int nbits;
sens_constraint_t *s;
@@ -563,7 +562,7 @@ violates_constraints(mls_level_t *l) {
return 0;
}
-void
+static void
destroy_sens_constraint(sens_constraint_t **list, sens_constraint_t *constraint) {
if (!constraint) {
return;
@@ -580,7 +579,7 @@ destroy_sens_constraint(sens_constraint_t **list, sens_constraint_t *constraint)
free(constraint);
}
-void
+static void
destroy_cat_constraint(cat_constraint_t **list, cat_constraint_t *constraint) {
if (!constraint) {
return;
@@ -663,7 +662,7 @@ find_in_table(context_map_node_t **table, const char *key) {
return NULL;
}
-char *
+static char *
trim(char *str, const char *whitespace) {
char *p = str + strlen(str);
@@ -672,7 +671,7 @@ trim(char *str, const char *whitespace) {
return str;
}
-char *
+static char *
triml(char *str, const char *whitespace) {
char *p = str;
@@ -681,7 +680,7 @@ triml(char *str, const char *whitespace) {
return p;
}
-int
+static int
update(char **p, char *const val) {
free (*p);
*p = strdup(val);
@@ -692,7 +691,7 @@ update(char **p, char *const val) {
return 0;
}
-int
+static int
append(affix_t **affixes, const char *val) {
affix_t *affix = calloc(1, sizeof(affix_t));
if (!affix) {
@@ -887,8 +886,8 @@ init_translations(void) {
return(read_translations(selinux_translations_path()));
}
-char *
-extract_range(const security_context_t incon) {
+static char *
+extract_range(const char *incon) {
context_t con = context_new(incon);
if (!con) {
syslog(LOG_ERR, "extract_range context_new(%s) failed: %s", incon, strerror(errno));
@@ -910,8 +909,8 @@ extract_range(const security_context_t incon) {
return r;
}
-char *
-new_context_str(const security_context_t incon, const char *range) {
+static char *
+new_context_str(const char *incon, const char *range) {
char *rcon = NULL;
context_t con = context_new(incon);
if (!con) {
@@ -919,6 +918,7 @@ new_context_str(const security_context_t incon, const char *range) {
}
context_range_set(con, range);
rcon = strdup(context_str(con));
+ context_free(con);
if (!rcon) {
goto exit;
}
@@ -930,7 +930,7 @@ exit:
return NULL;
}
-char *
+static char *
find_in_hashtable(const char *range, domain_t *domain, context_map_node_t **table) {
char *trans = NULL;
context_map_t *map = find_in_table(table, range);
@@ -945,13 +945,6 @@ find_in_hashtable(const char *range, domain_t *domain, context_map_node_t **tabl
return trans;
}
-void
-emit_whitespace(char*buffer, char *whitespace) {
- strcat(buffer, "[");
- strcat(buffer, whitespace);
- strcat(buffer, "]");
-}
-
static int
string_size(const void *p1, const void *p2) {
return strlen(*(char **)p2) - strlen(*(char **)p1);
@@ -968,20 +961,22 @@ word_size(const void *p1, const void *p2) {
return (w2_len - w1_len);
}
-void
-build_regexp(pcre **r, char *buffer) {
- const char *error;
- int error_offset;
+static void
+build_regexp(pcre2_code **r, char *buffer) {
+ int error;
+ PCRE2_SIZE error_offset;
if (*r)
- pcre_free(*r);
- *r = pcre_compile(buffer, PCRE_CASELESS, &error, &error_offset, NULL);
- if (error) {
- log_error("pcre=%s, error=%s\n", buffer, error ? error: "none");
+ pcre2_code_free(*r);
+ *r = pcre2_compile((PCRE2_SPTR8) buffer, PCRE2_ZERO_TERMINATED, PCRE2_CASELESS, &error, &error_offset, NULL);
+ if (!*r) {
+ PCRE2_UCHAR errbuf[256];
+ pcre2_get_error_message(error, errbuf, sizeof(errbuf));
+ log_error("pcre compilation of '%s' failed at offset %zu: %s\n", buffer, error_offset, errbuf);
}
buffer[0] = '\0';
}
-int
+static int
build_regexps(domain_t *domain) {
char buffer[1024 * 128];
buffer[0] = '\0';
@@ -1085,7 +1080,7 @@ build_regexps(domain_t *domain) {
return 0;
}
-char *
+static char *
compute_raw_from_trans(const char *level, domain_t *domain) {
#ifdef DEBUG
@@ -1094,12 +1089,12 @@ compute_raw_from_trans(const char *level, domain_t *domain) {
#endif
int rc = 0;
- int ovector[OVECCOUNT];
+ pcre2_match_data *match_data = NULL;
word_group_t *g = NULL;
char *work = NULL;
char *r = NULL;
- const char * match = NULL;
- int work_len;
+ char *match = NULL;
+ size_t work_len;
mls_level_t *mraw = NULL;
ebitmap_t set, clear, tmp;
@@ -1120,11 +1115,20 @@ compute_raw_from_trans(const char *level, domain_t *domain) {
if (!domain->base_classification_regexp)
goto err;
log_debug(" compute_raw_from_trans work = %s\n", work);
- rc = pcre_exec(domain->base_classification_regexp, 0, work, work_len, 0, PCRE_ANCHORED, ovector, OVECCOUNT);
+ match_data = pcre2_match_data_create_from_pattern(domain->base_classification_regexp, NULL);
+ if (!match_data) {
+ log_error("allocation error %s", strerror(errno));
+ goto err;
+ }
+ rc = pcre2_match(domain->base_classification_regexp, (PCRE2_SPTR8)work, work_len, 0, PCRE2_ANCHORED, match_data, NULL);
if (rc > 0) {
- match = NULL;
- pcre_get_substring(work, ovector, rc, 0, &match);
- log_debug(" compute_raw_from_trans match = %s len = %u\n", match, strlen(match));
+ const PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
+ match = strndup(work + ovector[0], ovector[1] - ovector[0]);
+ if (!match) {
+ log_error("allocation error %s", strerror(errno));
+ goto err;
+ }
+ log_debug(" compute_raw_from_trans match = %s len = %zu\n", match, strlen(match));
base_classification_t *bc;
for (bc = domain->base_classifications; bc; bc = bc->next) {
if (!strcmp(bc->trans, match)) {
@@ -1144,12 +1148,23 @@ compute_raw_from_trans(const char *level, domain_t *domain) {
char *p=work + ovector[0] + ovector[1];
while (*p && (strchr(" ", *p) != NULL))
*p++ = '#';
- pcre_free((char *)match);
+
+ free(match);
match = NULL;
} else {
- log_debug(" compute_raw_from_trans no base classification matched %s\n", level);
+ switch (rc) {
+ case PCRE2_ERROR_NOMATCH:
+ log_debug(" compute_raw_from_trans no base classification matched %s\n", level);
+ break;
+ default:
+ log_error("compute_raw_from_trans: base matching error for input '%s': %d\n", level, rc);
+ break;
+ }
}
+ pcre2_match_data_free(match_data);
+ match_data = NULL;
+
if (mraw == NULL) {
goto err;
}
@@ -1160,23 +1175,43 @@ compute_raw_from_trans(const char *level, domain_t *domain) {
change = 0;
for (g = domain->groups; g && !change && !complete; g = g->next) {
int prefix = 0, suffix = 0;
- int prefix_offset = 0, prefix_len = 0;
- int suffix_offset = 0, suffix_len = 0;
+ PCRE2_SIZE prefix_offset = 0, prefix_len = 0;
+ PCRE2_SIZE suffix_offset = 0, suffix_len = 0;
if (g->prefix_regexp) {
- rc = pcre_exec(g->prefix_regexp, 0, work, work_len, 0, 0, ovector, OVECCOUNT);
+ match_data = pcre2_match_data_create_from_pattern(g->prefix_regexp, NULL);
+ if (!match_data) {
+ log_error("allocation error %s", strerror(errno));
+ goto err;
+ }
+ rc = pcre2_match(g->prefix_regexp, (PCRE2_SPTR8)work, work_len, 0, 0, match_data, NULL);
if (rc > 0) {
+ const PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
prefix = 1;
prefix_offset = ovector[0];
prefix_len = ovector[1] - ovector[0];
+ } else if (rc != PCRE2_ERROR_NOMATCH) {
+ log_error("compute_raw_from_trans: prefix matching error for input '%s': %d\n", level, rc);
}
+ pcre2_match_data_free(match_data);
+ match_data = NULL;
}
if (g->suffix_regexp) {
- rc = pcre_exec(g->suffix_regexp, 0, work, work_len, 0, 0, ovector, OVECCOUNT);
+ match_data = pcre2_match_data_create_from_pattern(g->suffix_regexp, NULL);
+ if (!match_data) {
+ log_error("allocation error %s", strerror(errno));
+ goto err;
+ }
+ rc = pcre2_match(g->suffix_regexp, (PCRE2_SPTR8)work, work_len, 0, 0, match_data, NULL);
if (rc > 0) {
+ const PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
suffix = 1;
suffix_offset = ovector[0];
suffix_len = ovector[1] - ovector[0];
+ } else if (rc != PCRE2_ERROR_NOMATCH) {
+ log_error("compute_raw_from_trans: suffix matching error for input '%s': %d\n", level, rc);
}
+ pcre2_match_data_free(match_data);
+ match_data = NULL;
}
/* anchors prefix ^, suffix $ */
@@ -1185,14 +1220,23 @@ compute_raw_from_trans(const char *level, domain_t *domain) {
(g->suffixes && suffix)) &&
g->word_regexp) {
char *s = work + prefix_offset + prefix_len;
- int l = (suffix_len ? suffix_offset : work_len) - prefix_len - prefix_offset;
- rc = pcre_exec(g->word_regexp, 0, s, l, 0, 0, ovector, OVECCOUNT);
+ PCRE2_SIZE len = (suffix_len ? suffix_offset : work_len) - prefix_len - prefix_offset;
+ match_data = pcre2_match_data_create_from_pattern(g->word_regexp, NULL);
+ if (!match_data) {
+ log_error("allocation error %s", strerror(errno));
+ goto err;
+ }
+ rc = pcre2_match(g->word_regexp, (PCRE2_SPTR8)s, len, 0, 0, match_data, NULL);
if (rc > 0) {
- match = NULL;
- pcre_get_substring(s, ovector, rc, 0, &match);
- trim((char *)match, g->whitespace);
+ const PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
+ match = strndup(s + ovector[0], ovector[1] - ovector[0]);
+ if (!match) {
+ log_error("allocation error %s", strerror(errno));
+ goto err;
+ }
+ trim(match, g->whitespace);
if (*match) {
- char *p = triml((char *)match, g->whitespace);
+ char *p = triml(match, g->whitespace);
while (p && *p) {
int plen = strlen(p);
unsigned int i;
@@ -1229,9 +1273,13 @@ compute_raw_from_trans(const char *level, domain_t *domain) {
memset(work + suffix_offset, '#', suffix_len);
memset(s + ovector[0], '#', ovector[1] - ovector[0]);
}
- pcre_free((void *)match);
+ free(match);
match = NULL;
+ } else if (rc != PCRE2_ERROR_NOMATCH) {
+ log_error("compute_raw_from_trans: word matching error for input '%s' for substring '%s': %d\n", level, s, rc);
}
+ pcre2_match_data_free(match_data);
+ match_data = NULL;
}
/* YYY */
complete=1;
@@ -1270,14 +1318,15 @@ err:
mls_level_destroy(mraw);
free(mraw);
free(work);
- pcre_free((void *)match);
+ free(match);
ebitmap_destroy(&tmp);
ebitmap_destroy(&set);
ebitmap_destroy(&clear);
+ pcre2_match_data_free(match_data);
return NULL;
}
-char *
+static char *
compute_trans_from_raw(const char *level, domain_t *domain) {
#ifdef DEBUG
@@ -1489,7 +1538,7 @@ err:
}
int
-trans_context(const security_context_t incon, security_context_t *rcon) {
+trans_context(const char *incon, char **rcon) {
char *trans = NULL;
*rcon = NULL;
@@ -1612,7 +1661,7 @@ trans_context(const security_context_t incon, security_context_t *rcon) {
}
int
-untrans_context(const security_context_t incon, security_context_t *rcon) {
+untrans_context(const char *incon, char **rcon) {
char *raw = NULL;
*rcon = NULL;
diff --git a/mcstrans/src/mcstrans.h b/mcstrans/src/mcstrans.h
index a2f68c18..0addb325 100644
--- a/mcstrans/src/mcstrans.h
+++ b/mcstrans/src/mcstrans.h
@@ -4,6 +4,5 @@
extern int init_translations(void);
extern void finish_context_translations(void);
-extern int trans_context(const security_context_t, security_context_t *);
-extern int untrans_context(const security_context_t, security_context_t *);
-
+extern int trans_context(const char *, char **);
+extern int untrans_context(const char *, char **);
diff --git a/mcstrans/src/mcstrans.service b/mcstrans/src/mcstrans.service
index 09529432..c13cd09a 100644
--- a/mcstrans/src/mcstrans.service
+++ b/mcstrans/src/mcstrans.service
@@ -2,6 +2,9 @@
Description=Translates SELinux MCS/MLS labels to human readable form
Documentation=man:mcstransd(8)
ConditionSecurity=selinux
+DefaultDependencies=no
+Before=shutdown.target sysinit.target
+Conflicts=shutdown.target
[Service]
ExecStart=/sbin/mcstransd -f
diff --git a/mcstrans/src/mcstransd.c b/mcstrans/src/mcstransd.c
index 85899493..536c0f32 100644
--- a/mcstrans/src/mcstransd.c
+++ b/mcstrans/src/mcstransd.c
@@ -16,6 +16,8 @@
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/un.h>
+
+#include "mcscolor.h"
#include "mcstrans.h"
#ifdef UNUSED
@@ -40,18 +42,9 @@
//#define log_debug(fmt, ...) syslog(LOG_DEBUG, fmt, __VA_ARGS__)
#define log_debug(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else
-#define log_debug(fmt, ...) ;
+#define log_debug(fmt, ...) do {} while (0)
#endif
-extern int init_translations(void);
-extern void finish_context_translations(void);
-extern int trans_context(const security_context_t, security_context_t *);
-extern int untrans_context(const security_context_t, security_context_t *);
-
-extern int init_colors(void);
-extern void finish_context_colors(void);
-extern int raw_color(const security_context_t, char **);
-
#define SETRANSD_PATHNAME "/sbin/mcstransd"
/* name of program (for error messages) */
@@ -514,7 +507,7 @@ initialize(void)
}
-void dropprivs(void)
+static void dropprivs(void)
{
cap_t new_caps;
diff --git a/mcstrans/utils/Makefile b/mcstrans/utils/Makefile
index 9dfe7723..a48f4e72 100644
--- a/mcstrans/utils/Makefile
+++ b/mcstrans/utils/Makefile
@@ -14,13 +14,13 @@ endif
all: $(TARGETS)
transcon: transcon.o ../src/mcstrans.o ../src/mls_level.o $(LIBSEPOLA)
- $(CC) $(LDFLAGS) -o $@ $^ -lpcre -lselinux $(LDLIBS_LIBSEPOLA)
+ $(CC) $(LDFLAGS) -o $@ $^ $(PCRE_LDLIBS) -lselinux $(LDLIBS_LIBSEPOLA)
untranscon: untranscon.o ../src/mcstrans.o ../src/mls_level.o $(LIBSEPOLA)
- $(CC) $(LDFLAGS) -o $@ $^ -lpcre -lselinux $(LDLIBS_LIBSEPOLA)
+ $(CC) $(LDFLAGS) -o $@ $^ $(PCRE_LDLIBS) -lselinux $(LDLIBS_LIBSEPOLA)
%.o: %.c
- $(CC) $(CFLAGS) -D_GNU_SOURCE -I../src -fPIE -c -o $@ $<
+ $(CC) $(CFLAGS) $(PCRE_CFLAGS) -D_GNU_SOURCE -I../src -fPIE -c -o $@ $<
install: all
-mkdir -p $(DESTDIR)$(SBINDIR)
diff --git a/mcstrans/utils/transcon.c b/mcstrans/utils/transcon.c
index f4ded53e..4bf1bd56 100644
--- a/mcstrans/utils/transcon.c
+++ b/mcstrans/utils/transcon.c
@@ -14,7 +14,7 @@ static __attribute__((__noreturn__)) void usage(const char *progname)
}
int main(int argc, char **argv) {
- security_context_t scon;
+ char *scon;
if ( argc != 2 ) usage(argv[0]);
if (init_translations()==0) {
if(trans_context(argv[1],&scon) == 0) {
diff --git a/mcstrans/utils/untranscon.c b/mcstrans/utils/untranscon.c
index 85cea294..81668746 100644
--- a/mcstrans/utils/untranscon.c
+++ b/mcstrans/utils/untranscon.c
@@ -13,7 +13,7 @@ static __attribute__((__noreturn__)) void usage(const char *progname)
exit(1);
}
int main(int argc, char **argv) {
- security_context_t scon;
+ char *scon;
if ( argc != 2 ) usage(argv[0]);
if (init_translations()==0) {
if(untrans_context(argv[1],&scon) == 0) {
diff --git a/policycoreutils/VERSION b/policycoreutils/VERSION
index 9f55b2cc..eb39e538 100644
--- a/policycoreutils/VERSION
+++ b/policycoreutils/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/policycoreutils/man/man5/selinux_config.5 b/policycoreutils/man/man5/selinux_config.5
index 1ffade15..f391befb 100644
--- a/policycoreutils/man/man5/selinux_config.5
+++ b/policycoreutils/man/man5/selinux_config.5
@@ -32,7 +32,7 @@ The \fIconfig\fR file supports the following parameters:
.br
\fBSELINUXTYPE = \fIpolicy_name\fR
.br
-\fBREQUIREUSERS = \fI0\fR | \fI1\fR
+\fBREQUIRESEUSERS = \fI0\fR | \fI1\fR
.br
\fBAUTORELABEL = \fI0\fR | \fI1\fR
.RE
@@ -48,7 +48,7 @@ SELinux security policy is enforced.
.IP \fIpermissive\fR 4
SELinux security policy is not enforced but logs the warnings (i.e. the action is allowed to proceed).
.IP \fIdisabled\fR
-SELinux is disabled and no policy is loaded.
+No SELinux policy is loaded. This option was used to disable SELinux completely, which is now deprecated. Use the \fBselinux=0\fR kernel boot option instead (see \fBselinux\fR(8)).
.RE
.sp
The entry can be determined using the \fBsestatus\fR(8) command or \fBselinux_getenforcemode\fR(3).
diff --git a/policycoreutils/man/ru/man5/selinux_config.5 b/policycoreutils/man/ru/man5/selinux_config.5
index 40039e57..8c0db9ae 100644
--- a/policycoreutils/man/ru/man5/selinux_config.5
+++ b/policycoreutils/man/ru/man5/selinux_config.5
@@ -34,7 +34,7 @@ config \- файл конфигурации подÑиÑтемы SELinux.
.br
\fBSELINUXTYPE = \fIpolicy_name\fR
.br
-\fBREQUIREUSERS = \fI0\fR | \fI1\fR
+\fBREQUIRESEUSERS = \fI0\fR | \fI1\fR
.br
\fBAUTORELABEL = \fI0\fR | \fI1\fR
.RE
diff --git a/policycoreutils/newrole/Makefile b/policycoreutils/newrole/Makefile
index 73ebd413..b3ccf671 100644
--- a/policycoreutils/newrole/Makefile
+++ b/policycoreutils/newrole/Makefile
@@ -5,13 +5,14 @@ BINDIR ?= $(PREFIX)/bin
MANDIR ?= $(PREFIX)/share/man
ETCDIR ?= /etc
LOCALEDIR = $(DESTDIR)$(PREFIX)/share/locale
-PAMH ?= $(shell test -f /usr/include/security/pam_appl.h && echo y)
-AUDITH ?= $(shell test -f /usr/include/libaudit.h && echo y)
+INCLUDEDIR ?= $(PREFIX)/include
+PAMH ?= $(shell test -f $(INCLUDEDIR)/security/pam_appl.h && echo y)
+AUDITH ?= $(shell test -f $(INCLUDEDIR)/libaudit.h && echo y)
# Enable capabilities to permit newrole to generate audit records.
# This will make newrole a setuid root program.
# The capabilities used are: CAP_AUDIT_WRITE.
AUDIT_LOG_PRIV ?= n
-# Enable capabilities to permit newrole to utilitize the pam_namespace module.
+# Enable capabilities to permit newrole to utilize the pam_namespace module.
# This will make newrole a setuid root program.
# The capabilities used are: CAP_SYS_ADMIN, CAP_CHOWN, CAP_FOWNER and
# CAP_DAC_OVERRIDE.
@@ -90,3 +91,16 @@ indent:
relabel: install
/sbin/restorecon $(DESTDIR)$(BINDIR)/newrole
+
+test-build-options:
+ $(MAKE) PAMH=y AUDITH=y AUDIT_LOG_PRIV=y NAMESPACE_PRIV=y clean newrole
+ $(MAKE) PAMH=y AUDITH=y AUDIT_LOG_PRIV=y NAMESPACE_PRIV=n clean newrole
+ $(MAKE) PAMH=y AUDITH=y AUDIT_LOG_PRIV=n NAMESPACE_PRIV=y clean newrole
+ $(MAKE) PAMH=y AUDITH=y AUDIT_LOG_PRIV=n NAMESPACE_PRIV=n clean newrole
+ $(MAKE) PAMH=y AUDITH=y AUDIT_LOG_PRIV=y NAMESPACE_PRIV=y clean newrole
+ $(MAKE) PAMH=y AUDITH=n AUDIT_LOG_PRIV=n NAMESPACE_PRIV=y clean newrole
+ $(MAKE) PAMH=y AUDITH=n AUDIT_LOG_PRIV=n NAMESPACE_PRIV=n clean newrole
+ $(MAKE) PAMH=n AUDITH=y AUDIT_LOG_PRIV=y NAMESPACE_PRIV=n clean newrole
+ $(MAKE) PAMH=n AUDITH=y AUDIT_LOG_PRIV=n NAMESPACE_PRIV=n clean newrole
+ $(MAKE) PAMH=n AUDITH=n AUDIT_LOG_PRIV=n NAMESPACE_PRIV=n clean newrole
+ $(MAKE) clean
diff --git a/policycoreutils/newrole/hashtab.c b/policycoreutils/newrole/hashtab.c
index 24c65c49..26d4f4c7 100644
--- a/policycoreutils/newrole/hashtab.c
+++ b/policycoreutils/newrole/hashtab.c
@@ -44,7 +44,7 @@ hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
{
- int hvalue;
+ unsigned int hvalue;
hashtab_ptr_t prev, cur, newnode;
if (!h)
@@ -83,7 +83,7 @@ int hashtab_remove(hashtab_t h, hashtab_key_t key,
void (*destroy) (hashtab_key_t k,
hashtab_datum_t d, void *args), void *args)
{
- int hvalue;
+ unsigned int hvalue;
hashtab_ptr_t cur, last;
if (!h)
@@ -112,52 +112,10 @@ int hashtab_remove(hashtab_t h, hashtab_key_t key,
return HASHTAB_SUCCESS;
}
-int hashtab_replace(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum,
- void (*destroy) (hashtab_key_t k,
- hashtab_datum_t d, void *args), void *args)
-{
- int hvalue;
- hashtab_ptr_t prev, cur, newnode;
-
- if (!h)
- return HASHTAB_OVERFLOW;
-
- hvalue = h->hash_value(h, key);
- prev = NULL;
- cur = h->htable[hvalue];
- while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
- prev = cur;
- cur = cur->next;
- }
-
- if (cur && (h->keycmp(h, key, cur->key) == 0)) {
- if (destroy)
- destroy(cur->key, cur->datum, args);
- cur->key = key;
- cur->datum = datum;
- } else {
- newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
- if (newnode == NULL)
- return HASHTAB_OVERFLOW;
- memset(newnode, 0, sizeof(struct hashtab_node));
- newnode->key = key;
- newnode->datum = datum;
- if (prev) {
- newnode->next = prev->next;
- prev->next = newnode;
- } else {
- newnode->next = h->htable[hvalue];
- h->htable[hvalue] = newnode;
- }
- }
-
- return HASHTAB_SUCCESS;
-}
-
hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key)
{
- int hvalue;
+ unsigned int hvalue;
hashtab_ptr_t cur;
if (!h)
@@ -202,8 +160,9 @@ int hashtab_map(hashtab_t h,
int (*apply) (hashtab_key_t k,
hashtab_datum_t d, void *args), void *args)
{
- unsigned int i, ret;
+ unsigned int i;
hashtab_ptr_t cur;
+ int ret;
if (!h)
return HASHTAB_SUCCESS;
@@ -220,49 +179,6 @@ int hashtab_map(hashtab_t h,
return HASHTAB_SUCCESS;
}
-void hashtab_map_remove_on_error(hashtab_t h,
- int (*apply) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args),
- void (*destroy) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args), void *args)
-{
- unsigned int i;
- int ret;
- hashtab_ptr_t last, cur, temp;
-
- if (!h)
- return;
-
- for (i = 0; i < h->size; i++) {
- last = NULL;
- cur = h->htable[i];
- while (cur != NULL) {
- ret = apply(cur->key, cur->datum, args);
- if (ret) {
- if (last) {
- last->next = cur->next;
- } else {
- h->htable[i] = cur->next;
- }
-
- temp = cur;
- cur = cur->next;
- if (destroy)
- destroy(temp->key, temp->datum, args);
- free(temp);
- h->nel--;
- } else {
- last = cur;
- cur = cur->next;
- }
- }
- }
-
- return;
-}
-
void hashtab_hash_eval(hashtab_t h, char *tag)
{
unsigned int i;
diff --git a/policycoreutils/newrole/hashtab.h b/policycoreutils/newrole/hashtab.h
index ad5559ba..092b96a9 100644
--- a/policycoreutils/newrole/hashtab.h
+++ b/policycoreutils/newrole/hashtab.h
@@ -82,20 +82,6 @@ extern int hashtab_remove(hashtab_t h, hashtab_key_t k,
void *args), void *args);
/*
- Insert or replace the specified (key, datum) pair in the specified
- hash table. If an entry for the specified key already exists,
- then the specified destroy function is applied to (key,datum,args)
- for the entry prior to replacing the entry's contents.
-
- Returns HASHTAB_OVERFLOW if insufficient space is available or
- HASHTAB_SUCCESS otherwise.
- */
-extern int hashtab_replace(hashtab_t h, hashtab_key_t k, hashtab_datum_t d,
- void (*destroy) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args), void *args);
-
-/*
Searches for the entry with the specified key in the hash table.
Returns NULL if no entry has the specified key or
@@ -124,20 +110,6 @@ extern int hashtab_map(hashtab_t h,
hashtab_datum_t d,
void *args), void *args);
-/*
- Same as hashtab_map, except that if apply returns a non-zero status,
- then the (key,datum) pair will be removed from the hashtab and the
- destroy function will be applied to (key,datum,args).
- */
-extern void hashtab_map_remove_on_error(hashtab_t h,
- int (*apply) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args),
- void (*destroy) (hashtab_key_t k,
- hashtab_datum_t d,
- void *args),
- void *args);
-
extern void hashtab_hash_eval(hashtab_t h, char *tag);
#endif
diff --git a/policycoreutils/newrole/newrole.c b/policycoreutils/newrole/newrole.c
index e70051b1..ae37d725 100644
--- a/policycoreutils/newrole/newrole.c
+++ b/policycoreutils/newrole/newrole.c
@@ -96,11 +96,10 @@
#define USAGE_STRING "USAGE: newrole [ -r role ] [ -t type ] [ -l level ] [ -p ] [ -V ] [ -- args ]"
#ifdef USE_PAM
-#define PAM_SERVICE_CONFIG "/etc/selinux/newrole_pam.conf";
+#define PAM_SERVICE_CONFIG "/etc/selinux/newrole_pam.conf"
#endif
#define DEFAULT_PATH "/usr/bin:/bin"
-#define DEFAULT_CONTEXT_SIZE 255 /* first guess at context size */
extern char **environ;
@@ -115,7 +114,7 @@ extern char **environ;
*
* Returns malloc'd memory
*/
-static char *build_new_range(char *newlevel, const char *range)
+static char *build_new_range(const char *newlevel, const char *range)
{
char *newrangep = NULL;
const char *tmpptr;
@@ -166,7 +165,7 @@ static char *build_new_range(char *newlevel, const char *range)
#include <security/pam_appl.h> /* for PAM functions */
#include <security/pam_misc.h> /* for misc_conv PAM utility function */
-const char *service_name = "newrole";
+static const char *service_name = "newrole";
/* authenticate_via_pam()
*
@@ -182,7 +181,7 @@ const char *service_name = "newrole";
* program. This is the only function in this program that makes PAM
* calls.
*/
-int authenticate_via_pam(const char *ttyn, pam_handle_t * pam_handle)
+static int authenticate_via_pam(const char *ttyn, pam_handle_t * pam_handle)
{
int result = 0; /* set to 0 (not authenticated) by default */
@@ -230,14 +229,13 @@ static int free_hashtab_entry(hashtab_key_t key, hashtab_datum_t d,
static unsigned int reqsymhash(hashtab_t h, const_hashtab_key_t key)
{
- char *p, *keyp;
+ const char *p;
size_t size;
unsigned int val;
val = 0;
- keyp = (char *)key;
- size = strlen(keyp);
- for (p = keyp; ((size_t) (p - keyp)) < size; p++)
+ size = strlen(key);
+ for (p = key; ((size_t) (p - key)) < size; p++)
val =
(val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val & (h->size - 1);
@@ -335,6 +333,14 @@ static int read_pam_config(void)
#define PASSWORD_PROMPT _("Password:") /* prompt for getpass() */
+static void memzero(void *ptr, size_t size)
+{
+ volatile unsigned char * volatile p = ptr;
+ while (size--) {
+ *p++ = '\0';
+ }
+}
+
/* authenticate_via_shadow_passwd()
*
* in: uname - the calling user's user name
@@ -348,11 +354,12 @@ static int read_pam_config(void)
* This function uses the shadow passwd file to thenticate the user running
* this program.
*/
-int authenticate_via_shadow_passwd(const char *uname)
+static int authenticate_via_shadow_passwd(const char *uname)
{
struct spwd *p_shadow_line;
char *unencrypted_password_s;
char *encrypted_password_s;
+ int ret;
setspent();
p_shadow_line = getspnam(uname);
@@ -370,10 +377,18 @@ int authenticate_via_shadow_passwd(const char *uname)
}
/* Use crypt() to encrypt user's input password. */
+ errno = 0;
encrypted_password_s = crypt(unencrypted_password_s,
p_shadow_line->sp_pwdp);
- memset(unencrypted_password_s, 0, strlen(unencrypted_password_s));
- return (!strcmp(encrypted_password_s, p_shadow_line->sp_pwdp));
+ memzero(unencrypted_password_s, strlen(unencrypted_password_s));
+ if (errno || !encrypted_password_s) {
+ fprintf(stderr, _("Cannot encrypt password.\n"));
+ return 0;
+ }
+
+ ret = !strcmp(encrypted_password_s, p_shadow_line->sp_pwdp);
+ memzero(encrypted_password_s, strlen(encrypted_password_s));
+ return ret;
}
#endif /* if/else USE_PAM */
@@ -623,7 +638,7 @@ static inline int drop_capabilities(__attribute__ ((__unused__)) int full)
* This function will set the uid values to be that of caller's uid, and
* will drop any privilege which may have been raised.
*/
-static int transition_to_caller_uid()
+static int transition_to_caller_uid(void)
{
uid_t uid = getuid();
@@ -643,8 +658,8 @@ static int transition_to_caller_uid()
#ifdef AUDIT_LOG_PRIV
/* Send audit message */
static
-int send_audit_message(int success, security_context_t old_context,
- security_context_t new_context, const char *ttyn)
+int send_audit_message(int success, const char *old_context,
+ const char *new_context, const char *ttyn)
{
char *msg = NULL;
int rc;
@@ -677,9 +692,9 @@ int send_audit_message(int success, security_context_t old_context,
#else
static inline
int send_audit_message(int success __attribute__ ((unused)),
- security_context_t old_context
+ const char *old_context
__attribute__ ((unused)),
- security_context_t new_context
+ const char *new_context
__attribute__ ((unused)), const char *ttyn
__attribute__ ((unused)))
{
@@ -695,14 +710,14 @@ static inline
* This function will not fail if it can not relabel the tty when selinux is
* in permissive mode.
*/
-static int relabel_tty(const char *ttyn, security_context_t new_context,
- security_context_t * tty_context,
- security_context_t * new_tty_context)
+static int relabel_tty(const char *ttyn, const char *new_context,
+ char **tty_context,
+ char **new_tty_context)
{
int fd, rc;
int enforcing = security_getenforce();
- security_context_t tty_con = NULL;
- security_context_t new_tty_con = NULL;
+ char *tty_con = NULL;
+ char *new_tty_con = NULL;
if (!ttyn)
return 0;
@@ -775,11 +790,11 @@ static int relabel_tty(const char *ttyn, security_context_t new_context,
* Returns zero on success, non-zero otherwise
*/
static int restore_tty_label(int fd, const char *ttyn,
- security_context_t tty_context,
- security_context_t new_tty_context)
+ const char *tty_context,
+ const char *new_tty_context)
{
int rc = 0;
- security_context_t chk_tty_context = NULL;
+ char *chk_tty_context = NULL;
if (!ttyn)
goto skip_relabel;
@@ -816,8 +831,8 @@ static int restore_tty_label(int fd, const char *ttyn,
* Returns zero on success, non-zero otherwise.
*/
static int parse_command_line_arguments(int argc, char **argv, char *ttyn,
- security_context_t old_context,
- security_context_t * new_context,
+ const char *old_context,
+ char **new_context,
int *preserve_environment)
{
int flag_index; /* flag index in argv[] */
@@ -827,8 +842,8 @@ static int parse_command_line_arguments(int argc, char **argv, char *ttyn,
char *type_ptr = NULL; /* stores malloc'd data from get_default_type */
char *level_s = NULL; /* level spec'd by user in argv[] */
char *range_ptr = NULL;
- security_context_t new_con = NULL;
- security_context_t tty_con = NULL;
+ char *new_con = NULL;
+ char *tty_con = NULL;
context_t context = NULL; /* manipulatable form of new_context */
const struct option long_options[] = {
{"role", 1, 0, 'r'},
@@ -850,7 +865,6 @@ static int parse_command_line_arguments(int argc, char **argv, char *ttyn,
case 'V':
printf("newrole: %s version %s\n", PACKAGE, VERSION);
exit(0);
- break;
case 'p':
*preserve_environment = 1;
break;
@@ -1021,10 +1035,10 @@ static int set_signal_handles(void)
int main(int argc, char *argv[])
{
- security_context_t new_context = NULL; /* target security context */
- security_context_t old_context = NULL; /* original securiy context */
- security_context_t tty_context = NULL; /* current context of tty */
- security_context_t new_tty_context = NULL; /* new context of tty */
+ char *new_context = NULL; /* target security context */
+ char *old_context = NULL; /* original security context */
+ char *tty_context = NULL; /* current context of tty */
+ char *new_tty_context = NULL; /* new context of tty */
struct passwd pw; /* struct derived from passwd file line */
char *ttyn = NULL; /* tty path */
@@ -1239,6 +1253,7 @@ int main(int argc, char *argv[])
free(pw.pw_dir);
free(pw.pw_shell);
free(shell_argv0);
+ free(new_context);
return exit_code;
}
diff --git a/policycoreutils/run_init/open_init_pty.c b/policycoreutils/run_init/open_init_pty.c
index 150cb45e..19101c50 100644
--- a/policycoreutils/run_init/open_init_pty.c
+++ b/policycoreutils/run_init/open_init_pty.c
@@ -244,7 +244,7 @@ int main(int argc, char *argv[])
rb_init(&inbuf, inbuf_mem, sizeof(inbuf_mem));
rb_init(&outbuf, outbuf_mem, sizeof(outbuf_mem));
- if (argc == 1) {
+ if (argc < 2) {
printf("usage: %s PROGRAM [ARGS]...\n", argv[0]);
exit(1);
}
diff --git a/policycoreutils/run_init/run_init.c b/policycoreutils/run_init/run_init.c
index a007ce49..ce499781 100644
--- a/policycoreutils/run_init/run_init.c
+++ b/policycoreutils/run_init/run_init.c
@@ -86,8 +86,6 @@
/* The file containing the context to run
* the scripts under. */
-int authenticate_via_pam(const struct passwd *);
-
/* authenticate_via_pam()
*
* in: p_passwd_line - struct containing data from our user's line in
@@ -104,7 +102,7 @@ int authenticate_via_pam(const struct passwd *);
*
*/
-int authenticate_via_pam(const struct passwd *p_passwd_line)
+static int authenticate_via_pam(const struct passwd *p_passwd_line)
{
int result = 0; /* our result, set to 0 (not authenticated) by default */
@@ -169,8 +167,6 @@ int authenticate_via_pam(const struct passwd *p_passwd_line)
#define PASSWORD_PROMPT _("Password:") /* prompt for getpass() */
-int authenticate_via_shadow_passwd(const struct passwd *);
-
/* authenticate_via_shadow_passwd()
*
* in: p_passwd_line - struct containing data from our user's line in
@@ -187,7 +183,7 @@ int authenticate_via_shadow_passwd(const struct passwd *);
*
*/
-int authenticate_via_shadow_passwd(const struct passwd *p_passwd_line)
+static int authenticate_via_shadow_passwd(const struct passwd *p_passwd_line)
{
struct spwd *p_shadow_line; /* struct derived from shadow passwd file line */
@@ -238,7 +234,7 @@ int authenticate_via_shadow_passwd(const struct passwd *p_passwd_line)
* return: 0 When success
* -1 When failure
*/
-int authenticate_user(void)
+static int authenticate_user(void)
{
#define INITLEN 255
@@ -303,7 +299,7 @@ int authenticate_user(void)
* out: The CONTEXT associated with the context.
* return: 0 on success, -1 on failure.
*/
-int get_init_context(security_context_t * context)
+static int get_init_context(char **context)
{
FILE *fp;
@@ -354,7 +350,7 @@ int main(int argc, char *argv[])
extern char *optarg; /* used by getopt() for arg strings */
extern int opterr; /* controls getopt() error messages */
- security_context_t new_context; /* context for the init script context */
+ char *new_context; /* context for the init script context */
#ifdef USE_NLS
setlocale(LC_ALL, "");
@@ -406,14 +402,19 @@ int main(int argc, char *argv[])
if (chdir("/")) {
perror("chdir");
+ free(new_context);
exit(-1);
}
if (setexeccon(new_context) < 0) {
fprintf(stderr, _("Could not set exec context to %s.\n"),
new_context);
+ free(new_context);
exit(-1);
}
+
+ free(new_context);
+
if (access("/usr/sbin/open_init_pty", X_OK) != 0) {
if (execvp(argv[1], argv + 1)) {
perror("execvp");
diff --git a/policycoreutils/scripts/fixfiles b/policycoreutils/scripts/fixfiles
index 5d777034..7df4303a 100755
--- a/policycoreutils/scripts/fixfiles
+++ b/policycoreutils/scripts/fixfiles
@@ -109,9 +109,11 @@ fullFlag=0
BOOTTIME=""
VERBOSE="-p"
FORCEFLAG=""
+THREADS=""
RPMFILES=""
PREFC=""
RESTORE_MODE=""
+BIND_MOUNT_FILESYSTEMS=""
SETFILES=/sbin/setfiles
RESTORECON=/sbin/restorecon
FILESYSTEMSRW=`get_rw_labeled_mounts`
@@ -151,7 +153,7 @@ newer() {
shift
LogReadOnly
for m in `echo $FILESYSTEMSRW`; do
- find $m -mount -newermt $DATE -print0 2>/dev/null | ${RESTORECON} ${FORCEFLAG} ${VERBOSE} $* -i -0 -f -
+ find $m -mount -newermt $DATE -print0 2>/dev/null | ${RESTORECON} ${FORCEFLAG} ${VERBOSE} ${THREADS} $* -i -0 -f -
done;
}
@@ -161,7 +163,7 @@ newer() {
#
diff_filecontext() {
EXCLUDEDIRS="`exclude_dirs_from_relabelling`"
-for i in /sys /proc /dev /run /mnt /var/tmp /var/lib/BackupPC /home /tmp /dev; do
+for i in /sys /proc /mnt /var/tmp /var/lib/BackupPC /home /root /tmp; do
[ -e $i ] && EXCLUDEDIRS="${EXCLUDEDIRS} -e $i";
done
LogExcluded
@@ -174,7 +176,7 @@ if [ -f ${PREFC} -a -x /usr/bin/diff ]; then
sed -r -e 's,:s0, ,g' $FC | sort -u | \
/usr/bin/diff -b ${PREFCTEMPFILE} - | \
grep '^[<>]'|cut -c3-| grep ^/ | \
- egrep -v '(^/home|^/root|^/tmp|^/dev)' |\
+ egrep -v '(^/home|^/root|^/tmp)' |\
sed -r -e 's,[[:blank:]].*,,g' \
-e 's|\(([/[:alnum:]]+)\)\?|{\1,}|g' \
-e 's|([/[:alnum:]])\?|{\1,}|g' \
@@ -195,7 +197,7 @@ if [ -f ${PREFC} -a -x /usr/bin/diff ]; then
esac; \
fi; \
done | \
- ${RESTORECON} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} $* -i -R -f -; \
+ ${RESTORECON} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -i -R -f -; \
rm -f ${TEMPFILE} ${PREFCTEMPFILE}
fi
}
@@ -233,17 +235,33 @@ LogExcluded
case "$RESTORE_MODE" in
RPMFILES)
for i in `echo "$RPMFILES" | sed 's/,/ /g'`; do
- rpmlist $i | ${RESTORECON} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} $* -i -R -f -
+ rpmlist $i | ${RESTORECON} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -i -R -f -
done
;;
FILEPATH)
- ${RESTORECON} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} $* -R -- "$FILEPATH"
+ ${RESTORECON} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -R -- "$FILEPATH"
;;
*)
if [ -n "${FILESYSTEMSRW}" ]; then
LogReadOnly
echo "${OPTION}ing `echo ${FILESYSTEMSRW}`"
- ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} $* -q ${FC} ${FILESYSTEMSRW}
+
+ if [ -z "$BIND_MOUNT_FILESYSTEMS" ]; then
+ ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} $* -q ${THREADS} ${FC} ${FILESYSTEMSRW}
+ else
+ # we bind mount so we can fix the labels of files that have already been
+ # mounted over
+ for m in `echo $FILESYSTEMSRW`; do
+ TMP_MOUNT="$(mktemp -d)"
+ test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
+
+ mkdir -p "${TMP_MOUNT}${m}" || exit 1
+ mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
+ ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
+ umount "${TMP_MOUNT}${m}" || exit 1
+ rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
+ done;
+ fi
else
echo >&2 "fixfiles: No suitable file systems found"
fi
@@ -312,7 +330,9 @@ case "$1" in
fi
> /.autorelabel || exit $?
[ -z "$FORCEFLAG" ] || echo -n "$FORCEFLAG " >> /.autorelabel
- [ -z "$BOOTTIME" ] || echo -N $BOOTTIME >> /.autorelabel
+ [ -z "$BOOTTIME" ] || echo -n "-N $BOOTTIME " >> /.autorelabel
+ [ -z "$BIND_MOUNT_FILESYSTEMS" ] || echo -n "-M " >> /.autorelabel
+ [ -z "$THREADS" ] || echo -n "$THREADS " >> /.autorelabel
# Force full relabel if SELinux is not enabled
selinuxenabled || echo -F > /.autorelabel
echo "System will relabel on next boot"
@@ -324,17 +344,17 @@ esac
}
usage() {
echo $"""
-Usage: $0 [-v] [-F] [-f] relabel
+Usage: $0 [-v] [-F] [-M] [-f] [-T nthreads] relabel
or
-Usage: $0 [-v] [-F] [-B | -N time ] { check | restore | verify }
+Usage: $0 [-v] [-F] [-B | -N time ] [-T nthreads] { check | restore | verify }
or
-Usage: $0 [-v] [-F] { check | restore | verify } dir/file ...
+Usage: $0 [-v] [-F] [-T nthreads] { check | restore | verify } dir/file ...
or
-Usage: $0 [-v] [-F] -R rpmpackage[,rpmpackage...] { check | restore | verify }
+Usage: $0 [-v] [-F] [-T nthreads] -R rpmpackage[,rpmpackage...] { check | restore | verify }
or
-Usage: $0 [-v] [-F] -C PREVIOUS_FILECONTEXT { check | restore | verify }
+Usage: $0 [-v] [-F] [-T nthreads] -C PREVIOUS_FILECONTEXT { check | restore | verify }
or
-Usage: $0 [-F] [-B] onboot
+Usage: $0 [-F] [-M] [-B] [-T nthreads] onboot
"""
}
@@ -353,7 +373,7 @@ set_restore_mode() {
}
# See how we were called.
-while getopts "N:BC:FfR:l:v" i; do
+while getopts "N:BC:FfR:l:vMT:" i; do
case "$i" in
B)
BOOTTIME=`/bin/who -b | awk '{print $3}'`
@@ -379,12 +399,18 @@ while getopts "N:BC:FfR:l:v" i; do
echo "Redirecting output to $OPTARG"
exec >>"$OPTARG" 2>&1
;;
+ M)
+ BIND_MOUNT_FILESYSTEMS="-M"
+ ;;
F)
FORCEFLAG="-F"
;;
f)
fullFlag=1
;;
+ T)
+ THREADS="-T $OPTARG"
+ ;;
*)
usage
exit 1
diff --git a/policycoreutils/scripts/fixfiles.8 b/policycoreutils/scripts/fixfiles.8
index 9f447f03..9a317d91 100644
--- a/policycoreutils/scripts/fixfiles.8
+++ b/policycoreutils/scripts/fixfiles.8
@@ -6,22 +6,22 @@ fixfiles \- fix file SELinux security contexts.
.na
.B fixfiles
-.I [\-v] [\-F] [\-f] relabel
+.I [\-v] [\-F] [-M] [\-f] [\-T nthreads] relabel
.B fixfiles
-.I [\-v] [\-F] { check | restore | verify } dir/file ...
+.I [\-v] [\-F] [\-T nthreads] { check | restore | verify } dir/file ...
.B fixfiles
-.I [\-v] [\-F] [\-B | \-N time ] { check | restore | verify }
+.I [\-v] [\-F] [\-B | \-N time ] [\-T nthreads] { check | restore | verify }
.B fixfiles
-.I [\-v] [\-F] \-R rpmpackagename[,rpmpackagename...] { check | restore | verify }
+.I [\-v] [\-F] [\-T nthreads] \-R rpmpackagename[,rpmpackagename...] { check | restore | verify }
.B fixfiles
-.I [\-v] [\-F] \-C PREVIOUS_FILECONTEXT { check | restore | verify }
+.I [\-v] [\-F] [\-T nthreads] \-C PREVIOUS_FILECONTEXT { check | restore | verify }
.B fixfiles
-.I [-F] [-B] onboot
+.I [-F] [-M] [-B] [\-T nthreads] onboot
.ad
@@ -35,8 +35,8 @@ database (extended attributes) on filesystems.
.P
It can also be run at any time to relabel when adding support for
new policy, or just check whether the file contexts are all
-as you expect. By default it will relabel all mounted ext2, ext3, xfs and
-jfs file systems as long as they do not have a security context mount
+as you expect. By default it will relabel all mounted ext2, ext3, ext4, gfs2, xfs,
+jfs and btrfs file systems as long as they do not have a security context mount
option. You can use the \-R flag to use rpmpackages as an alternative.
The file /etc/selinux/fixfiles_exclude_dirs can contain a list of directories
excluded from relabeling.
@@ -69,13 +69,22 @@ Only act on files created after the specified date. Date must be specified in
"YYYY\-MM\-DD HH:MM" format. Date field will be passed to find \-\-newermt command.
.TP
+.B \-M
+Bind mount filesystems before relabeling them, this allows fixing the context of files or directories that have been mounted over.
+
+.TP
.B -v
Modify verbosity from progress to verbose. (Run restorecon with \-v instead of \-p)
+.TP
+.B \-T nthreads
+Use parallel relabeling, see
+.B setfiles(8)
+
.SH "ARGUMENTS"
One of:
.TP
-.B check
+.B check | verify
print any incorrect file context labels, showing old and new context, but do not change them.
.TP
.B restore
@@ -84,9 +93,6 @@ change any incorrect file context labels.
.B relabel
Prompt for removal of contents of /tmp directory and then change any incorrect file context labels to match the install file_contexts file.
.TP
-.B verify
-List out files with incorrect file context labels, but do not change them.
-.TP
.B [[dir/file] ... ]
List of files or directories trees that you wish to check file context on.
diff --git a/policycoreutils/secon/secon.c b/policycoreutils/secon/secon.c
index 477057a6..d624fa13 100644
--- a/policycoreutils/secon/secon.c
+++ b/policycoreutils/secon/secon.c
@@ -333,6 +333,9 @@ static void cmd_line(int argc, char *argv[])
opts->from_type = OPTS_FROM_CUR;
if (opts->from_type == OPTS_FROM_ARG) {
+ if (!argv[0])
+ errx(EXIT_FAILURE, "No argument given");
+
opts->f.arg = argv[0];
if (xstreq(argv[0], "-"))
@@ -341,7 +344,7 @@ static void cmd_line(int argc, char *argv[])
errx(EXIT_FAILURE, "SELinux is not enabled");
}
-static int my_getXcon_raw(pid_t pid, security_context_t * con, const char *val)
+static int my_getXcon_raw(pid_t pid, char **con, const char *val)
{
char buf[4096];
FILE *fp = NULL;
@@ -371,23 +374,23 @@ static int my_getXcon_raw(pid_t pid, security_context_t * con, const char *val)
return (0);
}
-static int my_getpidexeccon_raw(pid_t pid, security_context_t * con)
+static int my_getpidexeccon_raw(pid_t pid, char **con)
{
return (my_getXcon_raw(pid, con, "exec"));
}
-static int my_getpidfscreatecon_raw(pid_t pid, security_context_t * con)
+static int my_getpidfscreatecon_raw(pid_t pid, char **con)
{
return (my_getXcon_raw(pid, con, "fscreate"));
}
-static int my_getpidkeycreatecon_raw(pid_t pid, security_context_t * con)
+static int my_getpidkeycreatecon_raw(pid_t pid, char **con)
{
return (my_getXcon_raw(pid, con, "keycreate"));
}
-static security_context_t get_scon(void)
+static char *get_scon(void)
{
static char dummy_NIL[1] = "";
- security_context_t con = NULL, con_tmp;
+ char *con = NULL, *con_tmp;
int ret = -1;
switch (opts->from_type) {
@@ -620,9 +623,10 @@ static void disp__con_val(const char *name, const char *val,
done = TRUE;
}
-static void disp_con(security_context_t scon_raw)
+static void disp_con(const char *scon_raw)
{
- security_context_t scon_trans, scon;
+ char *scon_trans;
+ const char *scon;
context_t con = NULL;
char *color_str = NULL;
struct context_color_t color = { .valid = 0 };
@@ -682,7 +686,7 @@ static void disp_con(security_context_t scon_raw)
color.range_bg = strtok(NULL, " ");
color.valid = 1;
- };
+ }
if (!(con = context_new(scon)))
errx(EXIT_FAILURE, "Couldn't create context from: %s", scon);
@@ -748,7 +752,7 @@ static void disp_con(security_context_t scon_raw)
int main(int argc, char *argv[])
{
- security_context_t scon_raw = NULL;
+ char *scon_raw = NULL;
cmd_line(argc, argv);
diff --git a/policycoreutils/semodule/genhomedircon.8 b/policycoreutils/semodule/genhomedircon.8
index 2a3315b5..ecab7ba3 100644
--- a/policycoreutils/semodule/genhomedircon.8
+++ b/policycoreutils/semodule/genhomedircon.8
@@ -16,6 +16,9 @@ This script is usually executed by
although this default behavior can be optionally modified by setting to "true" the
"disable-genhomedircon" in /etc/selinux/semanage.conf.
+Directories can be excluded from the list of home directories by the setting "ignoredirs"
+in /etc/selinux/semanage.conf.
+
.SH AUTHOR
This manual page was written by
.I Dan Walsh <dwalsh@redhat.com>
diff --git a/policycoreutils/semodule/semodule.8 b/policycoreutils/semodule/semodule.8
index 18d4f708..d1735d21 100644
--- a/policycoreutils/semodule/semodule.8
+++ b/policycoreutils/semodule/semodule.8
@@ -23,6 +23,13 @@ force a reload of policy
.B \-B, \-\-build
force a rebuild of policy (also reloads unless \-n is used)
.TP
+.B \-\-rebuild-if-modules-changed
+Force a rebuild of the policy if any changes to module content are detected
+(by comparing with checksum from the last transaction). One can use this
+instead of \-B to ensure that any changes to the module store done by an
+external tool (e.g. a package manager) are applied, while automatically
+skipping the rebuild if there are no new changes.
+.TP
.B \-D, \-\-disable_dontaudit
Temporarily remove dontaudits from policy. Reverts whenever policy is rebuilt
.TP
@@ -95,6 +102,9 @@ only modules listed in \-\-extract after this option.
.B \-H,\-\-hll
Extract module as an HLL file. This only affects the \-\-extract option and
only modules listed in \-\-extract after this option.
+.TP
+.B \-m,\-\-checksum
+Add SHA256 checksum of modules to the list output.
.SH EXAMPLE
.nf
@@ -130,6 +140,9 @@ $ semodule \-B \-S "/tmp/var/lib/selinux"
# Write the HLL version of puppet and the CIL version of wireshark
# modules at priority 400 to the current working directory
$ semodule \-X 400 \-\-hll \-E puppet \-\-cil \-E wireshark
+# Check whether a module in "localmodule.pp" file is same as installed module "localmodule"
+$ /usr/libexec/selinux/hll/pp localmodule.pp | sha256sum
+$ semodule -l -m | grep localmodule
.fi
.SH SEE ALSO
diff --git a/policycoreutils/semodule/semodule.c b/policycoreutils/semodule/semodule.c
index a1f75e16..1ed8e690 100644
--- a/policycoreutils/semodule/semodule.c
+++ b/policycoreutils/semodule/semodule.c
@@ -47,6 +47,7 @@ static int verbose;
static int reload;
static int no_reload;
static int build;
+static int check_ext_changes;
static int disable_dontaudit;
static int preserve_tunables;
static int ignore_module_cache;
@@ -57,6 +58,7 @@ static semanage_handle_t *sh = NULL;
static char *store;
static char *store_root;
int extract_cil = 0;
+static int checksum = 0;
extern char *optarg;
extern int optind;
@@ -147,6 +149,10 @@ static void usage(char *progname)
printf(" -S,--store-path use an alternate path for the policy store root\n");
printf(" -c, --cil extract module as cil. This only affects module extraction.\n");
printf(" -H, --hll extract module as hll. This only affects module extraction.\n");
+ printf(" -m, --checksum print module checksum (SHA256).\n");
+ printf(" --rebuild-if-modules-changed\n"
+ " force policy rebuild if module content changed since\n"
+ " last rebuild (based on checksum)\n");
}
/* Sets the global mode variable to new_mode, but only if no other
@@ -178,6 +184,7 @@ static void set_mode(enum client_modes new_mode, char *arg)
static void parse_command_line(int argc, char **argv)
{
static struct option opts[] = {
+ {"rebuild-if-modules-changed", 0, NULL, '\0'},
{"store", required_argument, NULL, 's'},
{"base", required_argument, NULL, 'b'},
{"help", 0, NULL, 'h'},
@@ -200,19 +207,31 @@ static void parse_command_line(int argc, char **argv)
{"disable", required_argument, NULL, 'd'},
{"path", required_argument, NULL, 'p'},
{"store-path", required_argument, NULL, 'S'},
+ {"checksum", 0, NULL, 'm'},
{NULL, 0, NULL, 0}
};
int extract_selected = 0;
int cil_hll_set = 0;
- int i;
+ int i, longind;
verbose = 0;
reload = 0;
no_reload = 0;
+ check_ext_changes = 0;
priority = 400;
while ((i =
- getopt_long(argc, argv, "s:b:hi:l::vr:u:RnNBDCPX:e:d:p:S:E:cH", opts,
- NULL)) != -1) {
+ getopt_long(argc, argv, "s:b:hi:l::vr:u:RnNBDCPX:e:d:p:S:E:cHm",
+ opts, &longind)) != -1) {
switch (i) {
+ case '\0':
+ switch(longind) {
+ case 0: /* --rebuild-if-modules-changed */
+ check_ext_changes = 1;
+ break;
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+ break;
case 'b':
fprintf(stderr, "The --base option is deprecated. Use --install instead.\n");
set_mode(INSTALL_M, optarg);
@@ -287,6 +306,9 @@ static void parse_command_line(int argc, char **argv)
case 'd':
set_mode(DISABLE_M, optarg);
break;
+ case 'm':
+ checksum = 1;
+ break;
case '?':
default:{
usage(argv[0]);
@@ -294,13 +316,13 @@ static void parse_command_line(int argc, char **argv)
}
}
}
- if ((build || reload) && num_commands) {
+ if ((build || reload || check_ext_changes) && num_commands) {
fprintf(stderr,
"build or reload should not be used with other commands\n");
usage(argv[0]);
exit(1);
}
- if (num_commands == 0 && reload == 0 && build == 0) {
+ if (num_commands == 0 && reload == 0 && build == 0 && check_ext_changes == 0) {
fprintf(stderr, "At least one mode must be specified.\n");
usage(argv[0]);
exit(1);
@@ -338,6 +360,42 @@ static void parse_command_line(int argc, char **argv)
}
}
+/* Get module checksum */
+static char *hash_module_data(const char *module_name, const int prio) {
+ semanage_module_key_t *modkey = NULL;
+ char *hash_str = NULL;
+ void *hash = NULL;
+ size_t hash_len = 0;
+ int result;
+
+ result = semanage_module_key_create(sh, &modkey);
+ if (result != 0) {
+ goto cleanup;
+ }
+
+ result = semanage_module_key_set_name(sh, modkey, module_name);
+ if (result != 0) {
+ goto cleanup;
+ }
+
+ result = semanage_module_key_set_priority(sh, modkey, prio);
+ if (result != 0) {
+ goto cleanup;
+ }
+
+ result = semanage_module_compute_checksum(sh, modkey, 1, &hash_str,
+ &hash_len);
+ if (result != 0) {
+ goto cleanup;
+ }
+
+cleanup:
+ free(hash);
+ semanage_module_key_destroy(sh, modkey);
+ free(modkey);
+ return hash_str;
+}
+
int main(int argc, char *argv[])
{
int i, commit = 0;
@@ -353,7 +411,7 @@ int main(int argc, char *argv[])
cil_set_log_level(CIL_ERR + verbose);
- if (build)
+ if (build || check_ext_changes)
commit = 1;
sh = semanage_handle_create();
@@ -392,7 +450,7 @@ int main(int argc, char *argv[])
}
}
- if (build) {
+ if (build || check_ext_changes) {
if ((result = semanage_begin_transaction(sh)) < 0) {
fprintf(stderr, "%s: Could not begin transaction: %s\n",
argv[0], errno ? strerror(errno) : "");
@@ -452,8 +510,7 @@ int main(int argc, char *argv[])
}
semanage_module_info_get_priority(sh, extract_info, &curr_priority);
- printf("Module '%s' does not exist at the default priority '%d'. "
- "Extracting at highest existing priority '%d'.\n", mode_arg, priority, curr_priority);
+ printf("Extracting at highest existing priority '%d'.\n", curr_priority);
priority = curr_priority;
}
@@ -547,6 +604,8 @@ cleanup_extract:
int modinfos_len = 0;
semanage_module_info_t *m = NULL;
int j = 0;
+ char *module_checksum = NULL;
+ uint16_t pri = 0;
if (verbose) {
printf
@@ -571,7 +630,18 @@ cleanup_extract:
result = semanage_module_info_get_name(sh, m, &name);
if (result != 0) goto cleanup_list;
- printf("%s\n", name);
+ result = semanage_module_info_get_priority(sh, m, &pri);
+ if (result != 0) goto cleanup_list;
+
+ printf("%s", name);
+ if (checksum) {
+ module_checksum = hash_module_data(name, pri);
+ if (module_checksum) {
+ printf(" %s", module_checksum);
+ free(module_checksum);
+ }
+ }
+ printf("\n");
}
}
else if (strcmp(mode_arg, "full") == 0) {
@@ -586,12 +656,16 @@ cleanup_extract:
}
/* calculate column widths */
- size_t column[4] = { 0, 0, 0, 0 };
+ size_t column[5] = { 0, 0, 0, 0, 0 };
/* fixed width columns */
column[0] = sizeof("000") - 1;
column[3] = sizeof("disabled") - 1;
+ result = semanage_module_compute_checksum(sh, NULL, 0, NULL,
+ &column[4]);
+ if (result != 0) goto cleanup_list;
+
/* variable width columns */
const char *tmp = NULL;
size_t size;
@@ -608,12 +682,11 @@ cleanup_extract:
if (result != 0) goto cleanup_list;
size = strlen(tmp);
- if (size > column[3]) column[3] = size;
+ if (size > column[2]) column[2] = size;
}
/* print out each module */
for (j = 0; j < modinfos_len; j++) {
- uint16_t pri = 0;
const char *name = NULL;
int enabled = 0;
const char *lang_ext = NULL;
@@ -632,11 +705,20 @@ cleanup_extract:
result = semanage_module_info_get_lang_ext(sh, m, &lang_ext);
if (result != 0) goto cleanup_list;
- printf("%0*u %-*s %-*s %-*s\n",
+ printf("%0*u %-*s %-*s %-*s",
(int)column[0], pri,
(int)column[1], name,
(int)column[2], lang_ext,
(int)column[3], enabled ? "" : "disabled");
+ if (checksum) {
+ module_checksum = hash_module_data(name, pri);
+ if (module_checksum) {
+ printf(" %-*s", (int)column[4], module_checksum);
+ free(module_checksum);
+ }
+ }
+ printf("\n");
+
}
}
else {
@@ -741,6 +823,8 @@ cleanup_disable:
semanage_set_reload(sh, 0);
if (build)
semanage_set_rebuild(sh, 1);
+ if (check_ext_changes)
+ semanage_set_check_ext_changes(sh, 1);
if (disable_dontaudit)
semanage_set_disable_dontaudit(sh, 1);
else if (build)
diff --git a/policycoreutils/sestatus/Makefile b/policycoreutils/sestatus/Makefile
index 8c4f45f8..3dbb792b 100644
--- a/policycoreutils/sestatus/Makefile
+++ b/policycoreutils/sestatus/Makefile
@@ -1,6 +1,7 @@
# Installation directories.
LINGUAS ?= ru
PREFIX ?= /usr
+BINDIR ?= $(PREFIX)/bin
SBINDIR ?= $(PREFIX)/sbin
MANDIR = $(PREFIX)/share/man
ETCDIR ?= /etc
@@ -16,8 +17,13 @@ sestatus: sestatus.o
install: all
[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
[ -d $(DESTDIR)$(MANDIR)/man5 ] || mkdir -p $(DESTDIR)$(MANDIR)/man5
+ -mkdir -p $(DESTDIR)$(BINDIR)
-mkdir -p $(DESTDIR)$(SBINDIR)
- install -m 755 sestatus $(DESTDIR)$(SBINDIR)
+ # Some tools hard code /usr/sbin/sestatus ; add a compatibility symlink
+ # install will overwrite a symlink, so create the symlink before calling
+ # install to allow distributions with BINDIR == SBINDIR
+ ln -sf --relative $(DESTDIR)$(BINDIR)/sestatus $(DESTDIR)$(SBINDIR)
+ install -m 755 sestatus $(DESTDIR)$(BINDIR)
install -m 644 sestatus.8 $(DESTDIR)$(MANDIR)/man8
install -m 644 sestatus.conf.5 $(DESTDIR)$(MANDIR)/man5
for lang in $(LINGUAS) ; do \
diff --git a/policycoreutils/sestatus/sestatus.c b/policycoreutils/sestatus/sestatus.c
index b37f0353..7dcc9944 100644
--- a/policycoreutils/sestatus/sestatus.c
+++ b/policycoreutils/sestatus/sestatus.c
@@ -35,7 +35,7 @@ static unsigned int COL = 32;
extern char *selinux_mnt;
-int cmp_cmdline(const char *command, int pid)
+static int cmp_cmdline(const char *command, int pid)
{
char buf[BUFSIZE];
@@ -59,7 +59,7 @@ int cmp_cmdline(const char *command, int pid)
return 0;
}
-int pidof(const char *command)
+static int pidof(const char *command)
{
/* inspired by killall5.c from psmisc */
char stackpath[PATH_MAX + 1], *p;
@@ -92,7 +92,7 @@ int pidof(const char *command)
return ret;
}
-void load_checks(char *pc[], int *npc, char *fc[], int *nfc)
+static void load_checks(char *pc[], int *npc, char *fc[], int *nfc)
{
FILE *fp = fopen(CONF, "r");
@@ -168,11 +168,9 @@ void load_checks(char *pc[], int *npc, char *fc[], int *nfc)
return;
}
-void printf_tab(const char *outp)
+static void printf_tab(const char *outp)
{
- char buf[20];
- snprintf(buf, sizeof(buf), "%%-%us", COL);
- printf(buf, outp);
+ printf("%-*s", COL, outp);
}
@@ -461,6 +459,7 @@ int main(int argc, char **argv)
("%s (could not check link status (%s)!)\n",
context, strerror(errno));
freecon(context);
+ free(fc[i]);
continue;
}
if (S_ISLNK(m.st_mode)) {
diff --git a/policycoreutils/setfiles/.gitignore b/policycoreutils/setfiles/.gitignore
deleted file mode 100644
index 5e899c95..00000000
--- a/policycoreutils/setfiles/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-setfiles.8.man
diff --git a/policycoreutils/setfiles/Makefile b/policycoreutils/setfiles/Makefile
index bc5a8db7..d7670a8f 100644
--- a/policycoreutils/setfiles/Makefile
+++ b/policycoreutils/setfiles/Makefile
@@ -5,17 +5,15 @@ SBINDIR ?= /sbin
MANDIR = $(PREFIX)/share/man
AUDITH ?= $(shell test -f /usr/include/libaudit.h && echo y)
-ABORT_ON_ERRORS=$(shell grep "^\#define ABORT_ON_ERRORS" setfiles.c | awk -S '{ print $$3 }')
-
CFLAGS ?= -g -Werror -Wall -W
-override LDLIBS += -lselinux -lsepol
+override LDLIBS += -lselinux -lsepol -lpthread
ifeq ($(AUDITH), y)
override CFLAGS += -DUSE_AUDIT
override LDLIBS += -laudit
endif
-all: setfiles restorecon restorecon_xattr man
+all: setfiles restorecon restorecon_xattr
setfiles: setfiles.o restore.o
@@ -24,17 +22,13 @@ restorecon: setfiles
restorecon_xattr: restorecon_xattr.o restore.o
-man:
- @cp -af setfiles.8 setfiles.8.man
- @sed -i "s/ABORT_ON_ERRORS/$(ABORT_ON_ERRORS)/g" setfiles.8.man
-
install: all
[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
-mkdir -p $(DESTDIR)$(SBINDIR)
install -m 755 setfiles $(DESTDIR)$(SBINDIR)
(cd $(DESTDIR)$(SBINDIR) && ln -sf setfiles restorecon)
install -m 755 restorecon_xattr $(DESTDIR)$(SBINDIR)
- install -m 644 setfiles.8.man $(DESTDIR)$(MANDIR)/man8/setfiles.8
+ install -m 644 setfiles.8 $(DESTDIR)$(MANDIR)/man8/setfiles.8
install -m 644 restorecon.8 $(DESTDIR)$(MANDIR)/man8/restorecon.8
install -m 644 restorecon_xattr.8 $(DESTDIR)$(MANDIR)/man8/restorecon_xattr.8
for lang in $(LINGUAS) ; do \
@@ -45,7 +39,7 @@ install: all
done
clean:
- rm -f setfiles restorecon restorecon_xattr *.o setfiles.8.man
+ rm -f setfiles restorecon restorecon_xattr *.o
indent:
../../scripts/Lindent $(wildcard *.[ch])
diff --git a/policycoreutils/setfiles/restore.c b/policycoreutils/setfiles/restore.c
index d3335d1a..e9ae33ad 100644
--- a/policycoreutils/setfiles/restore.c
+++ b/policycoreutils/setfiles/restore.c
@@ -29,7 +29,7 @@ void restore_init(struct restore_opts *opts)
opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 3);
if (!opts->hnd) {
- perror(opts->selabel_opt_path);
+ perror(opts->selabel_opt_path ? opts->selabel_opt_path : selinux_file_context_path());
exit(1);
}
@@ -41,7 +41,7 @@ void restore_init(struct restore_opts *opts)
opts->xdev | opts->abort_on_error |
opts->syslog_changes | opts->log_matches |
opts->ignore_noent | opts->ignore_mounts |
- opts->mass_relabel;
+ opts->mass_relabel | opts->conflict_error;
/* Use setfiles, restorecon and restorecond own handles */
selinux_restorecon_set_sehandle(opts->hnd);
@@ -72,7 +72,7 @@ void restore_finish(void)
}
}
-int process_glob(char *name, struct restore_opts *opts)
+int process_glob(char *name, struct restore_opts *opts, size_t nthreads)
{
glob_t globbuf;
size_t i = 0;
@@ -91,8 +91,9 @@ int process_glob(char *name, struct restore_opts *opts)
continue;
if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0)
continue;
- rc = selinux_restorecon(globbuf.gl_pathv[i],
- opts->restorecon_flags);
+ rc = selinux_restorecon_parallel(globbuf.gl_pathv[i],
+ opts->restorecon_flags,
+ nthreads);
if (rc < 0)
errors = rc;
}
diff --git a/policycoreutils/setfiles/restore.h b/policycoreutils/setfiles/restore.h
index b64042a6..bb35a1db 100644
--- a/policycoreutils/setfiles/restore.h
+++ b/policycoreutils/setfiles/restore.h
@@ -34,6 +34,7 @@ struct restore_opts {
unsigned int log_matches;
unsigned int ignore_noent;
unsigned int ignore_mounts;
+ unsigned int conflict_error;
/* restorecon_flags holds | of above for restore_init() */
unsigned int restorecon_flags;
char *rootpath;
@@ -48,7 +49,7 @@ struct restore_opts {
void restore_init(struct restore_opts *opts);
void restore_finish(void);
void add_exclude(const char *directory);
-int process_glob(char *name, struct restore_opts *opts);
+int process_glob(char *name, struct restore_opts *opts, size_t nthreads);
extern char **exclude_list;
#endif
diff --git a/policycoreutils/setfiles/restorecon.8 b/policycoreutils/setfiles/restorecon.8
index bbfc83fe..e07db2c8 100644
--- a/policycoreutils/setfiles/restorecon.8
+++ b/policycoreutils/setfiles/restorecon.8
@@ -13,6 +13,7 @@ restorecon \- restore file(s) default SELinux security contexts.
.RB [ \-F ]
.RB [ \-W ]
.RB [ \-I | \-D ]
+.RB [ \-x ]
.RB [ \-e
.IR directory ]
.IR pathname \ ...
@@ -31,6 +32,9 @@ restorecon \- restore file(s) default SELinux security contexts.
.RB [ \-F ]
.RB [ \-W ]
.RB [ \-I | \-D ]
+.RB [ \-x ]
+.RB [ \-T
+.IR nthreads ]
.SH "DESCRIPTION"
This manual page describes the
@@ -153,14 +157,28 @@ option of GNU
.B find
produces input suitable for this mode.
.TP
+.B \-x
+prevent
+.B restorecon
+from crossing file system boundaries.
+.TP
+.BI \-T \ nthreads
+use up to
+.I nthreads
+threads. Specify 0 to create as many threads as there are available
+CPU cores; 1 to use only a single thread (default); or any positive
+number to use the given number of threads (if possible).
+.TP
.SH "ARGUMENTS"
.IR pathname \ ...
The pathname for the file(s) to be relabeled.
.SH "NOTES"
.IP "1." 4
.B restorecon
-does not follow symbolic links and by default it does not
-operate recursively on directories.
+by default does not operate recursively on directories. Paths leading up the
+final component of the file(s) are canonicalized using
+.BR realpath (3)
+before labeling.
.IP "2." 4
If the
.I pathname
diff --git a/policycoreutils/setfiles/restorecon_xattr.c b/policycoreutils/setfiles/restorecon_xattr.c
index 59b1f748..31fb82fd 100644
--- a/policycoreutils/setfiles/restorecon_xattr.c
+++ b/policycoreutils/setfiles/restorecon_xattr.c
@@ -38,7 +38,7 @@ int main(int argc, char **argv)
unsigned int xattr_flags = 0, delete_digest = 0, recurse = 0;
unsigned int delete_all_digests = 0, ignore_mounts = 0;
bool display_digest = false;
- char *sha1_buf, **specfiles, *fc_file = NULL;
+ char *sha1_buf, **specfiles, *fc_file = NULL, *pathname = NULL;
unsigned char *fc_digest = NULL;
size_t i, fc_digest_len = 0, num_specfiles;
@@ -163,7 +163,16 @@ int main(int argc, char **argv)
xattr_flags = delete_digest | delete_all_digests |
ignore_mounts | recurse;
- if (selinux_restorecon_xattr(argv[optind], xattr_flags, &xattr_list)) {
+ pathname = realpath(argv[optind], NULL);
+ if (!pathname) {
+ fprintf(stderr,
+ "restorecon_xattr: realpath(%s) failed: %s\n",
+ argv[optind], strerror(errno));
+ rc = -1;
+ goto out;
+ }
+
+ if (selinux_restorecon_xattr(pathname, xattr_flags, &xattr_list)) {
fprintf(stderr,
"Error selinux_restorecon_xattr: %s\n",
strerror(errno));
@@ -215,6 +224,7 @@ int main(int argc, char **argv)
rc = 0;
out:
+ free(pathname);
selabel_close(hnd);
restore_finish();
return rc;
diff --git a/policycoreutils/setfiles/ru/setfiles.8 b/policycoreutils/setfiles/ru/setfiles.8
index 27815a3f..91010145 100644
--- a/policycoreutils/setfiles/ru/setfiles.8
+++ b/policycoreutils/setfiles/ru/setfiles.8
@@ -47,7 +47,7 @@ setfiles \- уÑтановить SELinux-контекÑÑ‚Ñ‹ безопаÑноÑ
проверить дейÑтвительноÑÑ‚ÑŒ контекÑтов отноÑительно указанной двоичной политики.
.TP
.B \-d
-показать, ÐºÐ°ÐºÐ°Ñ ÑÐ¿ÐµÑ†Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ ÑоответÑтвует каждому из файлов (не прекращать проверку поÑле Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº ABORT_ON_ERRORS).
+показать, ÐºÐ°ÐºÐ°Ñ ÑÐ¿ÐµÑ†Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ ÑоответÑтвует каждому из файлов.
.TP
.BI \-e \ directory
иÑключить каталог (чтобы иÑключить более одного каталога, Ñтот параметр необходимо иÑпользовать ÑоответÑтвующее количеÑтво раз).
diff --git a/policycoreutils/setfiles/setfiles.8 b/policycoreutils/setfiles/setfiles.8
index c9f8be06..15f939d1 100644
--- a/policycoreutils/setfiles/setfiles.8
+++ b/policycoreutils/setfiles/setfiles.8
@@ -12,12 +12,15 @@ setfiles \- set SELinux file security contexts.
.RB [ \-n ]
.RB [ \-e
.IR directory ]
+.RB [ \-E ]
.RB [ \-p ]
.RB [ \-s ]
.RB [ \-v ]
.RB [ \-W ]
.RB [ \-F ]
.RB [ \-I | \-D ]
+.RB [ \-T
+.IR nthreads ]
.I spec_file
.IR pathname \ ...
@@ -56,12 +59,15 @@ option will force a replacement of the entire context.
check the validity of the contexts against the specified binary policy.
.TP
.B \-d
-show what specification matched each file (do not abort validation
-after ABORT_ON_ERRORS errors).
+show what specification matched each file.
.TP
.BI \-e \ directory
directory to exclude (repeat option for more than one directory).
.TP
+.BI \-E
+treat conflicting specifications as errors, such as where two hardlinks for
+the same inode have different contexts.
+.TP
.BI \-f \ infilename
.I infilename
contains a list of files to be processed. Use
@@ -157,6 +163,13 @@ quote marks or backslashes. The
option of GNU
.B find
produces input suitable for this mode.
+.TP
+.BI \-T \ nthreads
+use up to
+.I nthreads
+threads. Specify 0 to create as many threads as there are available
+CPU cores; 1 to use only a single thread (default); or any positive
+number to use the given number of threads (if possible).
.SH "ARGUMENTS"
.TP
@@ -209,7 +222,8 @@ option is used.
.SH "NOTES"
.IP "1." 4
.B setfiles
-follows symbolic links and operates recursively on directories.
+operates recursively on directories. Paths leading up the final
+component of the file(s) are not canonicalized before labeling.
.IP "2." 4
If the
.I pathname
diff --git a/policycoreutils/setfiles/setfiles.c b/policycoreutils/setfiles/setfiles.c
index bc83c27b..ab7016ac 100644
--- a/policycoreutils/setfiles/setfiles.c
+++ b/policycoreutils/setfiles/setfiles.c
@@ -1,4 +1,5 @@
#include "restore.h"
+#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio_ext.h>
@@ -19,18 +20,9 @@ static int warn_no_match;
static int null_terminated;
static int request_digest;
static struct restore_opts r_opts;
-static int nerr;
#define STAT_BLOCK_SIZE 1
-/* setfiles will abort its operation after reaching the
- * following number of errors (e.g. invalid contexts),
- * unless it is used in "debug" mode (-d option).
- */
-#ifndef ABORT_ON_ERRORS
-#define ABORT_ON_ERRORS 10
-#endif
-
#define SETFILES "setfiles"
#define RESTORECON "restorecon"
static int iamrestorecon;
@@ -43,30 +35,20 @@ static __attribute__((__noreturn__)) void usage(const char *const name)
{
if (iamrestorecon) {
fprintf(stderr,
- "usage: %s [-iIDFmnprRv0] [-e excludedir] pathname...\n"
- "usage: %s [-iIDFmnprRv0] [-e excludedir] -f filename\n",
+ "usage: %s [-iIDFmnprRv0xT] [-e excludedir] pathname...\n"
+ "usage: %s [-iIDFmnprRv0xT] [-e excludedir] -f filename\n",
name, name);
} else {
fprintf(stderr,
- "usage: %s [-diIDlmnpqvFW] [-e excludedir] [-r alt_root_path] spec_file pathname...\n"
- "usage: %s [-diIDlmnpqvFW] [-e excludedir] [-r alt_root_path] spec_file -f filename\n"
- "usage: %s -s [-diIDlmnpqvFW] spec_file\n"
- "usage: %s -c policyfile spec_file\n",
- name, name, name, name);
+ "usage: %s [-diIDlmnpqvEFWT] [-e excludedir] [-r alt_root_path] [-c policyfile] spec_file pathname...\n"
+ "usage: %s [-diIDlmnpqvEFWT] [-e excludedir] [-r alt_root_path] [-c policyfile] spec_file -f filename\n"
+ "usage: %s -s [-diIDlmnpqvFWT] spec_file\n",
+ name, name, name);
}
exit(-1);
}
-void inc_err(void)
-{
- nerr++;
- if (nerr > ABORT_ON_ERRORS - 1 && !r_opts.debug) {
- fprintf(stderr, "Exiting after %d errors.\n", ABORT_ON_ERRORS);
- exit(-1);
- }
-}
-
-void set_rootpath(const char *arg)
+static void set_rootpath(const char *arg)
{
if (strlen(arg) == 1 && strncmp(arg, "/", 1) == 0) {
fprintf(stderr, "%s: invalid alt_rootpath: %s\n",
@@ -83,7 +65,7 @@ void set_rootpath(const char *arg)
}
}
-int canoncon(char **contextp)
+static int canoncon(char **contextp)
{
char *context = *contextp, *tmpcon;
int rc = 0;
@@ -98,7 +80,6 @@ int canoncon(char **contextp)
*contextp = tmpcon;
} else if (errno != ENOENT) {
rc = -1;
- inc_err();
}
return rc;
@@ -164,12 +145,12 @@ int main(int argc, char **argv)
int opt, i = 0;
const char *input_filename = NULL;
int use_input_file = 0;
- char *buf = NULL;
- size_t buf_len;
+ char *buf = NULL, *endptr;
+ size_t buf_len, nthreads = 1;
const char *base;
int errors = 0;
- const char *ropts = "e:f:hiIDlmno:pqrsvFRW0";
- const char *sopts = "c:de:f:hiIDlmno:pqr:svFR:W0";
+ const char *ropts = "e:f:hiIDlmno:pqrsvFRW0xT:";
+ const char *sopts = "c:de:f:hiIDlmno:pqr:svEFR:W0T:";
const char *opts;
union selinux_callback cb;
@@ -180,8 +161,12 @@ int main(int argc, char **argv)
warn_no_match = 0;
request_digest = 0;
policyfile = NULL;
- nerr = 0;
+ r_opts.abort_on_error = 0;
+ if (!argv[0]) {
+ fprintf(stderr, "Called without required program name!\n");
+ exit(-1);
+ }
r_opts.progname = strdup(argv[0]);
if (!r_opts.progname) {
fprintf(stderr, "%s: Out of memory!\n", argv[0]);
@@ -194,7 +179,6 @@ int main(int argc, char **argv)
* setfiles:
* Recursive descent,
* Does not expand paths via realpath,
- * Aborts on errors during the file tree walk,
* Try to track inode associations for conflict detection,
* Does not follow mounts (sets SELINUX_RESTORECON_XDEV),
* Validates all file contexts at init time.
@@ -202,7 +186,6 @@ int main(int argc, char **argv)
iamrestorecon = 0;
r_opts.recurse = SELINUX_RESTORECON_RECURSE;
r_opts.userealpath = 0; /* SELINUX_RESTORECON_REALPATH */
- r_opts.abort_on_error = SELINUX_RESTORECON_ABORT_ON_ERROR;
r_opts.add_assoc = SELINUX_RESTORECON_ADD_ASSOC;
/* FTS_PHYSICAL and FTS_NOCHDIR are always set by selinux_restorecon(3) */
r_opts.xdev = SELINUX_RESTORECON_XDEV;
@@ -226,7 +209,6 @@ int main(int argc, char **argv)
iamrestorecon = 1;
r_opts.recurse = 0;
r_opts.userealpath = SELINUX_RESTORECON_REALPATH;
- r_opts.abort_on_error = 0;
r_opts.add_assoc = 0;
r_opts.xdev = 0;
r_opts.ignore_mounts = 0;
@@ -313,6 +295,10 @@ int main(int argc, char **argv)
r_opts.syslog_changes =
SELINUX_RESTORECON_SYSLOG_CHANGES;
break;
+ case 'E':
+ r_opts.conflict_error =
+ SELINUX_RESTORECON_CONFLICT_ERROR;
+ break;
case 'F':
r_opts.set_specctx =
SELINUX_RESTORECON_SET_SPECFILE_CTX;
@@ -382,6 +368,18 @@ int main(int argc, char **argv)
case '0':
null_terminated = 1;
break;
+ case 'x':
+ if (iamrestorecon) {
+ r_opts.xdev = SELINUX_RESTORECON_XDEV;
+ } else {
+ usage(argv[0]);
+ }
+ break;
+ case 'T':
+ nthreads = strtoull(optarg, &endptr, 10);
+ if (*optarg == '\0' || *endptr != '\0')
+ usage(argv[0]);
+ break;
case 'h':
case '?':
usage(argv[0]);
@@ -398,7 +396,7 @@ int main(int argc, char **argv)
if (!iamrestorecon) {
if (policyfile) {
- if (optind != (argc - 1))
+ if (optind > (argc - 1))
usage(argv[0]);
} else if (use_input_file) {
if (optind != (argc - 1)) {
@@ -429,7 +427,7 @@ int main(int argc, char **argv)
altpath = argv[optind];
optind++;
- } else if (argc == 1)
+ } else if (argc < 2)
usage(argv[0]);
/* Set selabel_open options. */
@@ -437,9 +435,6 @@ int main(int argc, char **argv)
r_opts.selabel_opt_digest = (request_digest ? (char *)1 : NULL);
r_opts.selabel_opt_path = altpath;
- if (nerr)
- exit(-1);
-
restore_init(&r_opts);
if (use_input_file) {
@@ -463,13 +458,13 @@ int main(int argc, char **argv)
buf[len - 1] = 0;
if (!strcmp(buf, "/"))
r_opts.mass_relabel = SELINUX_RESTORECON_MASS_RELABEL;
- errors |= process_glob(buf, &r_opts) < 0;
+ errors |= process_glob(buf, &r_opts, nthreads) < 0;
}
if (strcmp(input_filename, "-") != 0)
fclose(f);
} else {
for (i = optind; i < argc; i++)
- errors |= process_glob(argv[i], &r_opts) < 0;
+ errors |= process_glob(argv[i], &r_opts, nthreads) < 0;
}
maybe_audit_mass_relabel(r_opts.mass_relabel, errors);
diff --git a/policycoreutils/setsebool/setsebool.c b/policycoreutils/setsebool/setsebool.c
index 9d8abfac..60da5df1 100644
--- a/policycoreutils/setsebool/setsebool.c
+++ b/policycoreutils/setsebool/setsebool.c
@@ -200,8 +200,10 @@ static int semanage_set_boolean_list(size_t boolcnt,
if (no_reload)
semanage_set_reload(handle, 0);
- if (semanage_commit(handle) < 0)
+ if (semanage_commit(handle) < 0) {
+ fprintf(stderr, "Failed to commit changes to booleans: %m\n");
goto err;
+ }
semanage_disconnect(handle);
semanage_handle_destroy(handle);
diff --git a/prebuilts/bin/audit2allow b/prebuilts/bin/audit2allow
deleted file mode 100755
index 0d96ca60..00000000
--- a/prebuilts/bin/audit2allow
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-if [ -z "${ANDROID_HOST_OUT}" ]; then
- echo 'ANDROID_HOST_OUT not set. Have you run lunch?'
- exit 1
-elif [ -z "${ANDROID_BUILD_TOP}" ]; then
- echo 'ANDROID_BUILD_TOP not set. Have you run lunch?'
- exit 1
-elif [ ! -f "$ANDROID_HOST_OUT/lib64/libselinux.so" ]; then
- echo "Cannot find $ANDROID_HOST_OUT/lib64/libselinux.so"
- echo "Need to build project"
- exit 1
-fi
-
-unamestr=`uname`
-if [ "$unamestr" = "Linux" -o "$unamestr" = "linux" ]; then
- export LD_PRELOAD=$ANDROID_HOST_OUT/lib64/libselinux.so
- export PYTHONPATH=$ANDROID_BUILD_TOP/prebuilts/python/linux-x86/2.7.5/lib/python2.7/site-packages
- python $ANDROID_BUILD_TOP/external/selinux/python/audit2allow/audit2allow "$@"
-else
- echo "audit2allow is only supported on linux"
- exit 1
-fi
diff --git a/prebuilts/bin/audit2why b/prebuilts/bin/audit2why
deleted file mode 100755
index 38dd602b..00000000
--- a/prebuilts/bin/audit2why
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-if [ -z "${ANDROID_HOST_OUT}" ]; then
- echo 'ANDROID_HOST_OUT not set. Have you run lunch?'
- exit 1
-elif [ -z "${ANDROID_BUILD_TOP}" ]; then
- echo 'ANDROID_BUILD_TOP not set. Have you run lunch?'
- exit 1
-elif [ ! -f "$ANDROID_HOST_OUT/lib64/libselinux.so" ]; then
- echo "Cannot find $ANDROID_HOST_OUT/lib64/libselinux.so"
- echo "Need to build project"
- exit 1
-fi
-
-unamestr=`uname`
-if [ "$unamestr" = "Linux" -o "$unamestr" = "linux" ]; then
- export LD_PRELOAD=$ANDROID_HOST_OUT/lib64/libselinux.so
- export PYTHONPATH=$ANDROID_BUILD_TOP/prebuilts/python/linux-x86/2.7.5/lib/python2.7/site-packages
- exec python $ANDROID_BUILD_TOP/external/selinux/python/audit2allow/audit2why "$@"
-else
- echo "audit2why is only supported on linux"
- exit 1
-fi
diff --git a/prebuilts/bin/sediff b/prebuilts/bin/sediff
deleted file mode 100755
index d9072266..00000000
--- a/prebuilts/bin/sediff
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-if [ -z "${ANDROID_BUILD_TOP}" ]; then
- echo 'ANDROID_BUILD_TOP not set. Have you run lunch?'
- exit 1
-fi
-
-unamestr=`uname`
-if [ "$unamestr" = "Linux" -o "$unamestr" = "linux" ]; then
- export PYTHONPATH=$ANDROID_BUILD_TOP/prebuilts/python/linux-x86/2.7.5/lib/python2.7/site-packages
- python $ANDROID_BUILD_TOP/external/selinux/prebuilts/bin/sediff.py "$@"
-else
- echo "sediff is only supported on linux"
- exit 1
-fi
diff --git a/prebuilts/bin/sediff.py b/prebuilts/bin/sediff.py
deleted file mode 100755
index acb67198..00000000
--- a/prebuilts/bin/sediff.py
+++ /dev/null
@@ -1,1366 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015-2016, Tresys Technology, LLC
-#
-# This file is part of SETools.
-#
-# SETools is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-#
-# SETools is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with SETools. If not, see <http://www.gnu.org/licenses/>.
-#
-
-from __future__ import print_function
-import setools
-import argparse
-import sys
-import logging
-from itertools import chain
-
-parser = argparse.ArgumentParser(
- description="SELinux policy semantic difference tool.",
- epilog="If no differences are selected, all differences will be printed.")
-parser.add_argument("POLICY1", help="Path to the first SELinux policy to diff.", nargs=1)
-parser.add_argument("POLICY2", help="Path to the second SELinux policy to diff.", nargs=1)
-parser.add_argument("--version", action="version", version=setools.__version__)
-parser.add_argument("--stats", action="store_true", help="Display only statistics.")
-parser.add_argument("-v", "--verbose", action="store_true",
- help="Print extra informational messages")
-parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.")
-
-comp = parser.add_argument_group("component differences")
-comp.add_argument("--common", action="store_true", help="Print common differences")
-comp.add_argument("-c", "--class", action="store_true", help="Print class differences",
- dest="class_")
-comp.add_argument("-t", "--type", action="store_true", help="Print type differences",
- dest="type_")
-comp.add_argument("-a", "--attribute", action="store_true", help="Print type attribute differences")
-comp.add_argument("-r", "--role", action="store_true", help="Print role differences")
-comp.add_argument("-u", "--user", action="store_true", help="Print user differences")
-comp.add_argument("-b", "--bool", action="store_true", help="Print Boolean differences",
- dest="bool_")
-comp.add_argument("--sensitivity", action="store_true", help="Print MLS sensitivity differences")
-comp.add_argument("--category", action="store_true", help="Print MLS category differences")
-comp.add_argument("--level", action="store_true", help="Print MLS level definition differences")
-
-terule = parser.add_argument_group("type enforcement rule differences")
-terule.add_argument("-A", action="store_true", help="Print allow and allowxperm rule differences")
-terule.add_argument("--allow", action="store_true", help="Print allow rule differences")
-terule.add_argument("--neverallow", action="store_true", help="Print neverallow rule differences")
-terule.add_argument("--auditallow", action="store_true", help="Print auditallow rule differences")
-terule.add_argument("--dontaudit", action="store_true", help="Print dontaudit rule differences")
-terule.add_argument("--allowxperm", action="store_true", help="Print allowxperm rule differences")
-terule.add_argument("--neverallowxperm", action="store_true",
- help="Print neverallowxperm rule differences")
-terule.add_argument("--auditallowxperm", action="store_true",
- help="Print auditallowxperm rule differences")
-terule.add_argument("--dontauditxperm", action="store_true",
- help="Print dontauditxperm rule differences")
-terule.add_argument("-T", "--type_trans", action="store_true",
- help="Print type_transition rule differences")
-terule.add_argument("--type_change", action="store_true", help="Print type_change rule differences")
-terule.add_argument("--type_member", action="store_true",
- help="Print type_member rule differences")
-
-rbacrule = parser.add_argument_group("RBAC rule differences")
-rbacrule.add_argument("--role_allow", action="store_true", help="Print role allow rule differences")
-rbacrule.add_argument("--role_trans", action="store_true",
- help="Print role_transition rule differences")
-
-mlsrule = parser.add_argument_group("MLS rule differences")
-mlsrule.add_argument("--range_trans", action="store_true",
- help="Print range_transition rule differences")
-
-constrain = parser.add_argument_group("Constraint differences")
-constrain.add_argument("--constrain", action="store_true", help="Print constrain differences")
-constrain.add_argument("--mlsconstrain", action="store_true", help="Print mlsconstrain differences")
-constrain.add_argument("--validatetrans", action="store_true",
- help="Print validatetrans differences")
-constrain.add_argument("--mlsvalidatetrans", action="store_true",
- help="Print mlsvalidatetrans differences")
-
-labeling = parser.add_argument_group("labeling statement differences")
-labeling.add_argument("--initialsid", action="store_true", help="Print initial SID differences")
-labeling.add_argument("--fs_use", action="store_true", help="Print fs_use_* differences")
-labeling.add_argument("--genfscon", action="store_true", help="Print genfscon differences")
-labeling.add_argument("--netifcon", action="store_true", help="Print netifcon differences")
-labeling.add_argument("--nodecon", action="store_true", help="Print nodecon differences")
-labeling.add_argument("--portcon", action="store_true", help="Print portcon differences")
-
-other = parser.add_argument_group("other differences")
-other.add_argument("--default", action="store_true", help="Print default_* differences")
-other.add_argument("--property", action="store_true",
- help="Print policy property differences (handle_unknown, version, MLS)")
-other.add_argument("--polcap", action="store_true", help="Print policy capability differences")
-other.add_argument("--typebounds", action="store_true", help="Print typebounds differences")
-
-args = parser.parse_args()
-
-if args.A:
- args.allow = True
- args.allowxperm = True
-
-all_differences = not any((args.class_, args.common, args.type_, args.attribute, args.role,
- args.user, args.bool_, args.sensitivity, args.category, args.level,
- args.allow, args.neverallow, args.auditallow, args.dontaudit,
- args.type_trans, args.type_change, args.type_member, args.role_allow,
- args.role_trans, args.range_trans, args.initialsid, args.genfscon,
- args.netifcon, args.nodecon, args.portcon, args.fs_use, args.polcap,
- args.property, args.default, args.constrain, args.mlsconstrain,
- args.validatetrans, args.mlsvalidatetrans, args.typebounds,
- args.allowxperm, args.neverallowxperm, args.auditallowxperm,
- args.dontauditxperm))
-
-if args.debug:
- logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)s|%(levelname)s|%(name)s|%(message)s')
-elif args.verbose:
- logging.basicConfig(level=logging.INFO, format='%(message)s')
-else:
- logging.basicConfig(level=logging.WARNING, format='%(message)s')
-
-try:
- p1 = setools.SELinuxPolicy(args.POLICY1[0])
- p2 = setools.SELinuxPolicy(args.POLICY2[0])
- diff = setools.PolicyDifference(p1, p2)
-
- if all_differences or args.property:
- print("Policy Properties ({0} Modified)".format(len(diff.modified_properties)))
-
- if diff.modified_properties and not args.stats:
- for name, added, removed in sorted(diff.modified_properties, key=lambda x: x.property):
- print(" * {0} +{1} -{2}".format(name, added, removed))
-
- print()
-
- if all_differences or args.common:
- if diff.added_commons or diff.removed_commons or diff.modified_commons or args.common:
- print("Commons ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_commons), len(diff.removed_commons), len(diff.modified_commons)))
- if diff.added_commons and not args.stats:
- print(" Added Commons: {0}".format(len(diff.added_commons)))
- for c in sorted(diff.added_commons):
- print(" + {0}".format(c))
- if diff.removed_commons and not args.stats:
- print(" Removed Commons: {0}".format(len(diff.removed_commons)))
- for c in sorted(diff.removed_commons):
- print(" - {0}".format(c))
- if diff.modified_commons and not args.stats:
- print(" Modified Commons: {0}".format(len(diff.modified_commons)))
- for name, mod in sorted(diff.modified_commons.items()):
- change = []
- if mod.added_perms:
- change.append("{0} Added permissions".format(len(mod.added_perms)))
- if mod.removed_perms:
- change.append("{0} Removed permissions".format(len(mod.removed_perms)))
-
- print(" * {0} ({1})".format(name, ", ".join(change)))
- for p in sorted(mod.added_perms):
- print(" + {0}".format(p))
- for p in sorted(mod.removed_perms):
- print(" - {0}".format(p))
- print()
-
- if all_differences or args.class_:
- if diff.added_classes or diff.removed_classes or diff.modified_classes or args.class_:
- print("Classes ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_classes), len(diff.removed_classes), len(diff.modified_classes)))
- if diff.added_classes and not args.stats:
- print(" Added Classes: {0}".format(len(diff.added_classes)))
- for c in sorted(diff.added_classes):
- print(" + {0}".format(c))
- if diff.removed_classes and not args.stats:
- print(" Removed Classes: {0}".format(len(diff.removed_classes)))
- for c in sorted(diff.removed_classes):
- print(" - {0}".format(c))
- if diff.modified_classes and not args.stats:
- print(" Modified Classes: {0}".format(len(diff.modified_classes)))
- for name, mod in sorted(diff.modified_classes.items()):
- change = []
- if mod.added_perms:
- change.append("{0} Added permissions".format(len(mod.added_perms)))
- if mod.removed_perms:
- change.append("{0} Removed permissions".format(len(mod.removed_perms)))
-
- print(" * {0} ({1})".format(name, ", ".join(change)))
- for p in sorted(mod.added_perms):
- print(" + {0}".format(p))
- for p in sorted(mod.removed_perms):
- print(" - {0}".format(p))
- print()
-
- if all_differences or args.bool_:
- if diff.added_booleans or diff.removed_booleans or \
- diff.modified_booleans or args.bool_:
- print("Booleans ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_booleans), len(diff.removed_booleans),
- len(diff.modified_booleans)))
- if diff.added_booleans and not args.stats:
- print(" Added Booleans: {0}".format(len(diff.added_booleans)))
- for a in sorted(diff.added_booleans):
- print(" + {0}".format(a))
- if diff.removed_booleans and not args.stats:
- print(" Removed Booleans: {0}".format(len(diff.removed_booleans)))
- for a in sorted(diff.removed_booleans):
- print(" - {0}".format(a))
- if diff.modified_booleans and not args.stats:
- print(" Modified Booleans: {0}".format(len(diff.modified_booleans)))
- for name, mod in sorted(diff.modified_booleans.items()):
- print(" * {0} (Modified default state)".format(name))
- print(" + {0}".format(mod.added_state))
- print(" - {0}".format(mod.removed_state))
-
- print()
-
- if all_differences or args.role:
- if diff.added_roles or diff.removed_roles or diff.modified_roles or args.role:
- print("Roles ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_roles),
- len(diff.removed_roles),
- len(diff.modified_roles)))
- if diff.added_roles and not args.stats:
- print(" Added Roles: {0}".format(len(diff.added_roles)))
- for r in sorted(diff.added_roles):
- print(" + {0}".format(r))
- if diff.removed_roles and not args.stats:
- print(" Removed Roles: {0}".format(len(diff.removed_roles)))
- for r in sorted(diff.removed_roles):
- print(" - {0}".format(r))
- if diff.modified_roles and not args.stats:
- print(" Modified Roles: {0}".format(len(diff.modified_roles)))
- for name, mod in sorted(diff.modified_roles.items()):
- change = []
- if mod.added_types:
- change.append("{0} Added types".format(len(mod.added_types)))
- if mod.removed_types:
- change.append("{0} Removed types".format(len(mod.removed_types)))
-
- print(" * {0} ({1})".format(name, ", ".join(change)))
- for t in sorted(mod.added_types):
- print(" + {0}".format(t))
- for t in sorted(mod.removed_types):
- print(" - {0}".format(t))
- print()
-
- if all_differences or args.type_:
- if diff.added_types or diff.removed_types or diff.modified_types or args.type_:
- print("Types ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_types),
- len(diff.removed_types),
- len(diff.modified_types)))
- if diff.added_types and not args.stats:
- print(" Added Types: {0}".format(len(diff.added_types)))
- for r in sorted(diff.added_types):
- print(" + {0}".format(r))
- if diff.removed_types and not args.stats:
- print(" Removed Types: {0}".format(len(diff.removed_types)))
- for r in sorted(diff.removed_types):
- print(" - {0}".format(r))
- if diff.modified_types and not args.stats:
- print(" Modified Types: {0}".format(len(diff.modified_types)))
- for name, mod in sorted(diff.modified_types.items()):
- change = []
- if mod.added_attributes:
- change.append("{0} Added attributes".format(len(mod.added_attributes)))
- if mod.removed_attributes:
- change.append("{0} Removed attributes".format(len(mod.removed_attributes)))
- if mod.added_aliases:
- change.append("{0} Added aliases".format(len(mod.added_aliases)))
- if mod.removed_aliases:
- change.append("{0} Removed aliases".format(len(mod.removed_aliases)))
- if mod.modified_permissive:
- if mod.permissive:
- change.append("Removed permissive")
- else:
- change.append("Added permissive")
-
- print(" * {0} ({1})".format(name, ", ".join(change)))
- if mod.added_attributes or mod.removed_attributes:
- print(" Attributes:")
- for t in sorted(mod.added_attributes):
- print(" + {0}".format(t))
- for t in sorted(mod.removed_attributes):
- print(" - {0}".format(t))
-
- if mod.added_aliases or mod.removed_aliases:
- print(" Aliases:")
- for t in sorted(mod.added_aliases):
- print(" + {0}".format(t))
- for t in sorted(mod.removed_aliases):
- print(" - {0}".format(t))
-
- print()
-
- if all_differences or args.attribute:
- if diff.added_type_attributes or diff.removed_type_attributes or \
- diff.modified_type_attributes or args.attribute:
- print("Type Attributes ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_type_attributes), len(diff.removed_type_attributes),
- len(diff.modified_type_attributes)))
- if diff.added_type_attributes and not args.stats:
- print(" Added Type Attributes: {0}".format(len(diff.added_type_attributes)))
- for a in sorted(diff.added_type_attributes):
- print(" + {0}".format(a))
- if diff.removed_type_attributes and not args.stats:
- print(" Removed Type Attributes: {0}".format(len(diff.removed_type_attributes)))
- for a in sorted(diff.removed_type_attributes):
- print(" - {0}".format(a))
- if diff.modified_type_attributes and not args.stats:
- print(" Modified Type Attributes: {0}".format(len(diff.modified_type_attributes)))
- for name, mod in sorted(diff.modified_type_attributes.items()):
- change = []
- if mod.added_types:
- change.append("{0} Added types".format(len(mod.added_types)))
- if mod.removed_types:
- change.append("{0} Removed types".format(len(mod.removed_types)))
-
- print(" * {0} ({1})".format(name, ", ".join(change)))
- for t in sorted(mod.added_types):
- print(" + {0}".format(t))
- for t in sorted(mod.removed_types):
- print(" - {0}".format(t))
- print()
-
- if all_differences or args.user:
- if diff.added_users or diff.removed_users or diff.modified_users or args.user:
- print("Users ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_users),
- len(diff.removed_users),
- len(diff.modified_users)))
- if diff.added_users and not args.stats:
- print(" Added Users: {0}".format(len(diff.added_users)))
- for u in sorted(diff.added_users):
- print(" + {0}".format(u))
- if diff.removed_users and not args.stats:
- print(" Removed Users: {0}".format(len(diff.removed_users)))
- for u in sorted(diff.removed_users):
- print(" - {0}".format(u))
- if diff.modified_users and not args.stats:
- print(" Modified Users: {0}".format(len(diff.modified_users)))
- for name, mod in sorted(diff.modified_users.items()):
- change = []
- if mod.added_roles:
- change.append("{0} Added roles".format(len(mod.added_roles)))
- if mod.removed_roles:
- change.append("{0} Removed roles".format(len(mod.removed_roles)))
- if mod.removed_level:
- change.append("Modified default level")
- if mod.removed_range:
- change.append("Modified range")
-
- print(" * {0} ({1})".format(name, ", ".join(change)))
- if mod.added_roles or mod.removed_roles:
- print(" Roles:")
- for t in sorted(mod.added_roles):
- print(" + {0}".format(t))
- for t in sorted(mod.removed_roles):
- print(" - {0}".format(t))
-
- if mod.removed_level:
- print(" Default level:")
- print(" + {0}".format(mod.added_level))
- print(" - {0}".format(mod.removed_level))
-
- if mod.removed_range:
- print(" Range:")
- print(" + {0}".format(mod.added_range))
- print(" - {0}".format(mod.removed_range))
- print()
-
- if all_differences or args.category:
- if diff.added_categories or diff.removed_categories or diff.modified_categories \
- or args.category:
- print("Categories ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_categories), len(diff.removed_categories),
- len(diff.modified_categories)))
- if diff.added_categories and not args.stats:
- print(" Added Categories: {0}".format(len(diff.added_categories)))
- for c in sorted(diff.added_categories):
- print(" + {0}".format(c))
- if diff.removed_categories and not args.stats:
- print(" Removed Categories: {0}".format(len(diff.removed_categories)))
- for c in sorted(diff.removed_categories):
- print(" - {0}".format(c))
- if diff.modified_categories and not args.stats:
- print(" Modified Categories: {0}".format(len(diff.modified_categories)))
- for name, mod in sorted(diff.modified_categories.items()):
- change = []
- if mod.added_aliases:
- change.append("{0} Added Aliases".format(len(mod.added_aliases)))
- if mod.removed_aliases:
- change.append("{0} Removed Aliases".format(len(mod.removed_aliases)))
-
- print(" * {0} ({1})".format(name, ", ".join(change)))
- print(" Aliases:")
- for a in sorted(mod.added_aliases):
- print(" + {0}".format(a))
- for a in sorted(mod.removed_aliases):
- print(" - {0}".format(a))
-
- print()
-
- if all_differences or args.sensitivity:
- if diff.added_sensitivities or diff.removed_sensitivities or diff.modified_sensitivities \
- or args.sensitivity:
- print("Sensitivities ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_sensitivities), len(diff.removed_sensitivities),
- len(diff.modified_sensitivities)))
- if diff.added_sensitivities and not args.stats:
- print(" Added Sensitivites: {0}".format(len(diff.added_sensitivities)))
- for s in sorted(diff.added_sensitivities):
- print(" + {0}".format(s))
- if diff.removed_sensitivities and not args.stats:
- print(" Removed Sensitivities: {0}".format(len(diff.removed_sensitivities)))
- for s in sorted(diff.removed_sensitivities):
- print(" - {0}".format(s))
- if diff.modified_sensitivities and not args.stats:
- print(" Modified Sensitivities: {0}".format(len(diff.modified_sensitivities)))
- for name, mod in sorted(diff.modified_sensitivities.items()):
- change = []
- if mod.added_aliases:
- change.append("{0} Added Aliases".format(len(mod.added_aliases)))
- if mod.removed_aliases:
- change.append("{0} Removed Aliases".format(len(mod.removed_aliases)))
-
- print(" * {0} ({1})".format(name, ", ".join(change)))
- print(" Aliases:")
- for a in sorted(mod.added_aliases):
- print(" + {0}".format(a))
- for a in sorted(mod.removed_aliases):
- print(" - {0}".format(a))
-
- print()
-
- if all_differences or args.level:
- if diff.added_levels or diff.removed_levels or \
- diff.modified_levels or args.level:
- print("Levels ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_levels), len(diff.removed_levels),
- len(diff.modified_levels)))
- if diff.added_levels and not args.stats:
- print(" Added Levels: {0}".format(len(diff.added_levels)))
- for l in sorted(diff.added_levels):
- print(" + {0}".format(l))
- if diff.removed_levels and not args.stats:
- print(" Removed Levels: {0}".format(len(diff.removed_levels)))
- for l in sorted(diff.removed_levels):
- print(" - {0}".format(l))
- if diff.modified_levels and not args.stats:
- print(" Modified Levels: {0}".format(len(diff.modified_levels)))
- for level, added_categories, removed_categories, _ in sorted(diff.modified_levels,
- key=lambda x: x.level):
- change = []
- if added_categories:
- change.append("{0} Added Categories".format(len(added_categories)))
- if removed_categories:
- change.append("{0} Removed Categories".format(len(removed_categories)))
-
- print(" * {0} ({1})".format(level.sensitivity, ", ".join(change)))
- for c in sorted(added_categories):
- print(" + {0}".format(c))
- for c in sorted(removed_categories):
- print(" - {0}".format(c))
- print()
-
- if all_differences or args.allow:
- if diff.added_allows or diff.removed_allows or diff.modified_allows or args.allow:
- print("Allow Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_allows), len(diff.removed_allows), len(diff.modified_allows)))
-
- if diff.added_allows and not args.stats:
- print(" Added Allow Rules: {0}".format(len(diff.added_allows)))
- for r in sorted(diff.added_allows):
- print(" + {0}".format(r))
-
- if diff.removed_allows and not args.stats:
- print(" Removed Allow Rules: {0}".format(len(diff.removed_allows)))
- for r in sorted(diff.removed_allows):
- print(" - {0}".format(r))
-
- if diff.modified_allows and not args.stats:
- print(" Modified Allow Rules: {0}".format(len(diff.modified_allows)))
-
- for rule, added_perms, removed_perms, matched_perms in sorted(diff.modified_allows,
- key=lambda x: x.rule):
- perms = " ".join(chain((p for p in matched_perms),
- ("+" + p for p in added_perms),
- ("-" + p for p in removed_perms)))
- rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {{ {1} }};".format(
- rule, perms)
-
- try:
- rule_string += " [ {0} ]".format(rule.conditional)
- except AttributeError:
- pass
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.allowxperm:
- if diff.added_allowxperms or diff.removed_allowxperms or diff.modified_allowxperms \
- or args.allowxperm:
-
- print("Allowxperm Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_allowxperms), len(diff.removed_allowxperms),
- len(diff.modified_allowxperms)))
-
- if diff.added_allowxperms and not args.stats:
- print(" Added Allowxperm Rules: {0}".format(len(diff.added_allowxperms)))
- for r in sorted(diff.added_allowxperms):
- print(" + {0}".format(r))
-
- if diff.removed_allowxperms and not args.stats:
- print(" Removed Allowxperm Rules: {0}".format(len(diff.removed_allowxperms)))
- for r in sorted(diff.removed_allowxperms):
- print(" - {0}".format(r))
-
- if diff.modified_allowxperms and not args.stats:
- print(" Modified Allowxperm Rules: {0}".format(len(diff.modified_allowxperms)))
-
- for rule, added_perms, removed_perms, matched_perms in sorted(
- diff.modified_allowxperms, key=lambda x: x.rule):
-
- # Process the string representation of the sets
- # so hex representation and ranges are preserved.
- # Check if the perm sets have contents, otherwise
- # split on empty string will be an empty string.
- # Add brackets to added and removed permissions
- # in case there is a range of permissions.
- perms = []
- if matched_perms:
- for p in str(matched_perms).split(" "):
- perms.append(p)
- if added_perms:
- for p in str(added_perms).split(" "):
- if '-' in p:
- perms.append("+[{0}]".format(p))
- else:
- perms.append("+{0}".format(p))
- if removed_perms:
- for p in str(removed_perms).split(" "):
- if '-' in p:
- perms.append("-[{0}]".format(p))
- else:
- perms.append("-{0}".format(p))
-
- rule_string = \
- "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} {{ {1} }};". \
- format(rule, perms)
-
- print(" * {0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} "
- "{{ {1} }};".format(rule, " ".join(perms)))
-
- print()
-
- if all_differences or args.neverallow:
- if diff.added_neverallows or diff.removed_neverallows or diff.modified_neverallows or \
- args.neverallow:
- print("Neverallow Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_neverallows), len(diff.removed_neverallows),
- len(diff.modified_neverallows)))
-
- if diff.added_neverallows and not args.stats:
- print(" Added Neverallow Rules: {0}".format(len(diff.added_neverallows)))
- for r in sorted(diff.added_neverallows):
- print(" + {0}".format(r))
-
- if diff.removed_neverallows and not args.stats:
- print(" Removed Neverallow Rules: {0}".format(len(diff.removed_neverallows)))
- for r in sorted(diff.removed_neverallows):
- print(" - {0}".format(r))
-
- if diff.modified_neverallows and not args.stats:
- print(" Modified Neverallow Rules: {0}".format(len(diff.modified_neverallows)))
-
- for rule, added_perms, removed_perms, matched_perms in sorted(
- diff.modified_neverallows, key=lambda x: x.rule):
- perms = " ".join(chain((p for p in matched_perms),
- ("+" + p for p in added_perms),
- ("-" + p for p in removed_perms)))
- rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {{ {1} }};".format(
- rule, perms)
-
- try:
- rule_string += " [ {0} ]".format(rule.conditional)
- except AttributeError:
- pass
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.neverallowxperm:
- if diff.added_neverallowxperms or diff.removed_neverallowxperms or \
- diff.modified_neverallowxperms or args.neverallowxperm:
-
- print("Neverallowxperm Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_neverallowxperms), len(diff.removed_neverallowxperms),
- len(diff.modified_neverallowxperms)))
-
- if diff.added_neverallowxperms and not args.stats:
- print(" Added Neverallowxperm Rules: {0}".format(
- len(diff.added_neverallowxperms)))
- for r in sorted(diff.added_neverallowxperms):
- print(" + {0}".format(r))
-
- if diff.removed_neverallowxperms and not args.stats:
- print(" Removed Neverallowxperm Rules: {0}".format(
- len(diff.removed_neverallowxperms)))
- for r in sorted(diff.removed_neverallowxperms):
- print(" - {0}".format(r))
-
- if diff.modified_neverallowxperms and not args.stats:
- print(" Modified Neverallowxperm Rules: {0}".format(
- len(diff.modified_neverallowxperms)))
-
- for rule, added_perms, removed_perms, matched_perms in sorted(
- diff.modified_neverallowxperms, key=lambda x: x.rule):
-
- # Process the string representation of the sets
- # so hex representation and ranges are preserved.
- # Check if the perm sets have contents, otherwise
- # split on empty string will be an empty string.
- # Add brackets to added and removed permissions
- # in case there is a range of permissions.
- perms = []
- if matched_perms:
- for p in str(matched_perms).split(" "):
- perms.append(p)
- if added_perms:
- for p in str(added_perms).split(" "):
- if '-' in p:
- perms.append("+[{0}]".format(p))
- else:
- perms.append("+{0}".format(p))
- if removed_perms:
- for p in str(removed_perms).split(" "):
- if '-' in p:
- perms.append("-[{0}]".format(p))
- else:
- perms.append("-{0}".format(p))
-
- rule_string = \
- "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} {{ {1} }};". \
- format(rule, perms)
-
- print(" * {0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} "
- "{{ {1} }};".format(rule, " ".join(perms)))
-
- print()
-
- if all_differences or args.auditallow:
- if diff.added_auditallows or diff.removed_auditallows or diff.modified_auditallows or \
- args.auditallow:
- print("Auditallow Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_auditallows), len(diff.removed_auditallows),
- len(diff.modified_auditallows)))
-
- if diff.added_auditallows and not args.stats:
- print(" Added Auditallow Rules: {0}".format(len(diff.added_auditallows)))
- for r in sorted(diff.added_auditallows):
- print(" + {0}".format(r))
-
- if diff.removed_auditallows and not args.stats:
- print(" Removed Auditallow Rules: {0}".format(len(diff.removed_auditallows)))
- for r in sorted(diff.removed_auditallows):
- print(" - {0}".format(r))
-
- if diff.modified_auditallows and not args.stats:
- print(" Modified Auditallow Rules: {0}".format(len(diff.modified_auditallows)))
-
- for rule, added_perms, removed_perms, matched_perms in sorted(
- diff.modified_auditallows, key=lambda x: x.rule):
- perms = " ".join(chain((p for p in matched_perms),
- ("+" + p for p in added_perms),
- ("-" + p for p in removed_perms)))
- rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {{ {1} }};".format(
- rule, perms)
-
- try:
- rule_string += " [ {0} ]".format(rule.conditional)
- except AttributeError:
- pass
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.auditallowxperm:
- if diff.added_auditallowxperms or diff.removed_auditallowxperms or \
- diff.modified_auditallowxperms or args.auditallowxperm:
-
- print("Auditallowxperm Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_auditallowxperms), len(diff.removed_auditallowxperms),
- len(diff.modified_auditallowxperms)))
-
- if diff.added_auditallowxperms and not args.stats:
- print(" Added Auditallowxperm Rules: {0}".format(
- len(diff.added_auditallowxperms)))
- for r in sorted(diff.added_auditallowxperms):
- print(" + {0}".format(r))
-
- if diff.removed_auditallowxperms and not args.stats:
- print(" Removed Auditallowxperm Rules: {0}".format(
- len(diff.removed_auditallowxperms)))
- for r in sorted(diff.removed_auditallowxperms):
- print(" - {0}".format(r))
-
- if diff.modified_auditallowxperms and not args.stats:
- print(" Modified Auditallowxperm Rules: {0}".format(
- len(diff.modified_auditallowxperms)))
-
- for rule, added_perms, removed_perms, matched_perms in sorted(
- diff.modified_auditallowxperms, key=lambda x: x.rule):
-
- # Process the string representation of the sets
- # so hex representation and ranges are preserved.
- # Check if the perm sets have contents, otherwise
- # split on empty string will be an empty string.
- # Add brackets to added and removed permissions
- # in case there is a range of permissions.
- perms = []
- if matched_perms:
- for p in str(matched_perms).split(" "):
- perms.append(p)
- if added_perms:
- for p in str(added_perms).split(" "):
- if '-' in p:
- perms.append("+[{0}]".format(p))
- else:
- perms.append("+{0}".format(p))
- if removed_perms:
- for p in str(removed_perms).split(" "):
- if '-' in p:
- perms.append("-[{0}]".format(p))
- else:
- perms.append("-{0}".format(p))
-
- rule_string = \
- "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} {{ {1} }};". \
- format(rule, perms)
-
- print(" * {0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} "
- "{{ {1} }};".format(rule, " ".join(perms)))
-
- print()
-
- if all_differences or args.dontaudit:
- if diff.added_dontaudits or diff.removed_dontaudits or diff.modified_dontaudits or \
- args.dontaudit:
- print("Dontaudit Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_dontaudits), len(diff.removed_dontaudits),
- len(diff.modified_dontaudits)))
-
- if diff.added_dontaudits and not args.stats:
- print(" Added Dontaudit Rules: {0}".format(len(diff.added_dontaudits)))
- for r in sorted(diff.added_dontaudits):
- print(" + {0}".format(r))
-
- if diff.removed_dontaudits and not args.stats:
- print(" Removed Dontaudit Rules: {0}".format(len(diff.removed_dontaudits)))
- for r in sorted(diff.removed_dontaudits):
- print(" - {0}".format(r))
-
- if diff.modified_dontaudits and not args.stats:
- print(" Modified Dontaudit Rules: {0}".format(len(diff.modified_dontaudits)))
-
- for rule, added_perms, removed_perms, matched_perms in sorted(
- diff.modified_dontaudits, key=lambda x: x.rule):
- perms = " ".join(chain((p for p in matched_perms),
- ("+" + p for p in added_perms),
- ("-" + p for p in removed_perms)))
- rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {{ {1} }};".format(
- rule, perms)
-
- try:
- rule_string += " [ {0} ]".format(rule.conditional)
- except AttributeError:
- pass
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.dontauditxperm:
- if diff.added_dontauditxperms or diff.removed_dontauditxperms or \
- diff.modified_dontauditxperms or args.dontauditxperm:
-
- print("Dontauditxperm Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_dontauditxperms), len(diff.removed_dontauditxperms),
- len(diff.modified_dontauditxperms)))
-
- if diff.added_dontauditxperms and not args.stats:
- print(" Added Dontauditxperm Rules: {0}".format(
- len(diff.added_dontauditxperms)))
- for r in sorted(diff.added_dontauditxperms):
- print(" + {0}".format(r))
-
- if diff.removed_dontauditxperms and not args.stats:
- print(" Removed Dontauditxperm Rules: {0}".format(
- len(diff.removed_dontauditxperms)))
- for r in sorted(diff.removed_dontauditxperms):
- print(" - {0}".format(r))
-
- if diff.modified_dontauditxperms and not args.stats:
- print(" Modified Dontauditxperm Rules: {0}".format(
- len(diff.modified_dontauditxperms)))
-
- for rule, added_perms, removed_perms, matched_perms in sorted(
- diff.modified_dontauditxperms, key=lambda x: x.rule):
-
- # Process the string representation of the sets
- # so hex representation and ranges are preserved.
- # Check if the perm sets have contents, otherwise
- # split on empty string will be an empty string.
- # Add brackets to added and removed permissions
- # in case there is a range of permissions.
- perms = []
- if matched_perms:
- for p in str(matched_perms).split(" "):
- perms.append(p)
- if added_perms:
- for p in str(added_perms).split(" "):
- if '-' in p:
- perms.append("+[{0}]".format(p))
- else:
- perms.append("+{0}".format(p))
- if removed_perms:
- for p in str(removed_perms).split(" "):
- if '-' in p:
- perms.append("-[{0}]".format(p))
- else:
- perms.append("-{0}".format(p))
-
- rule_string = \
- "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} {{ {1} }};". \
- format(rule, perms)
-
- print(" * {0.ruletype} {0.source} {0.target}:{0.tclass} {0.xperm_type} "
- "{{ {1} }};".format(rule, " ".join(perms)))
-
- print()
-
- if all_differences or args.type_trans:
- if diff.added_type_transitions or diff.removed_type_transitions or \
- diff.modified_type_transitions or args.type_trans:
- print("Type_transition Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_type_transitions), len(diff.removed_type_transitions),
- len(diff.modified_type_transitions)))
-
- if diff.added_type_transitions and not args.stats:
- print(" Added Type_transition Rules: {0}".format(
- len(diff.added_type_transitions)))
- for r in sorted(diff.added_type_transitions):
- print(" + {0}".format(r))
-
- if diff.removed_type_transitions and not args.stats:
- print(" Removed Type_transition Rules: {0}".format(
- len(diff.removed_type_transitions)))
- for r in sorted(diff.removed_type_transitions):
- print(" - {0}".format(r))
-
- if diff.modified_type_transitions and not args.stats:
- print(" Modified Type_transition Rules: {0}".format(
- len(diff.modified_type_transitions)))
-
- for rule, added_default, removed_default in sorted(diff.modified_type_transitions,
- key=lambda x: x.rule):
- rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} +{1} -{2}".format(
- rule, added_default, removed_default)
-
- try:
- rule_string += " {0}".format(rule.filename)
- except AttributeError:
- pass
-
- rule_string += ";"
-
- try:
- rule_string += " [ {0} ]".format(rule.conditional)
- except AttributeError:
- pass
-
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.type_change:
- if diff.added_type_changes or diff.removed_type_changes or \
- diff.modified_type_changes or args.type_change:
- print("Type_change Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_type_changes), len(diff.removed_type_changes),
- len(diff.modified_type_changes)))
-
- if diff.added_type_changes and not args.stats:
- print(" Added Type_change Rules: {0}".format(len(diff.added_type_changes)))
- for r in sorted(diff.added_type_changes):
- print(" + {0}".format(r))
-
- if diff.removed_type_changes and not args.stats:
- print(" Removed Type_change Rules: {0}".format(len(diff.removed_type_changes)))
- for r in sorted(diff.removed_type_changes):
- print(" - {0}".format(r))
-
- if diff.modified_type_changes and not args.stats:
- print(" Modified Type_change Rules: {0}".format(len(diff.modified_type_changes)))
-
- for rule, added_default, removed_default in sorted(diff.modified_type_changes,
- key=lambda x: x.rule):
- rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} +{1} -{2}".format(
- rule, added_default, removed_default)
-
- try:
- rule_string += " {0}".format(rule.filename)
- except AttributeError:
- pass
-
- rule_string += ";"
-
- try:
- rule_string += " [ {0} ]".format(rule.conditional)
- except AttributeError:
- pass
-
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.type_member:
- if diff.added_type_members or diff.removed_type_members or \
- diff.modified_type_members or args.type_member:
- print("Type_member Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_type_members), len(diff.removed_type_members),
- len(diff.modified_type_members)))
-
- if diff.added_type_members and not args.stats:
- print(" Added Type_member Rules: {0}".format(len(diff.added_type_members)))
- for r in sorted(diff.added_type_members):
- print(" + {0}".format(r))
-
- if diff.removed_type_members and not args.stats:
- print(" Removed Type_member Rules: {0}".format(len(diff.removed_type_members)))
- for r in sorted(diff.removed_type_members):
- print(" - {0}".format(r))
-
- if diff.modified_type_members and not args.stats:
- print(" Modified Type_member Rules: {0}".format(len(diff.modified_type_members)))
-
- for rule, added_default, removed_default in sorted(diff.modified_type_members,
- key=lambda x: x.rule):
- rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} +{1} -{2}".format(
- rule, added_default, removed_default)
-
- try:
- rule_string += " {0}".format(rule.filename)
- except AttributeError:
- pass
-
- rule_string += ";"
-
- try:
- rule_string += " [ {0} ]".format(rule.conditional)
- except AttributeError:
- pass
-
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.role_allow:
- if diff.added_role_allows or diff.removed_role_allows or args.role_allow:
- print("Role allow Rules ({0} Added, {1} Removed)".format(
- len(diff.added_role_allows), len(diff.removed_role_allows)))
-
- if diff.added_role_allows and not args.stats:
- print(" Added Role Allow Rules: {0}".format(
- len(diff.added_role_allows)))
- for r in sorted(diff.added_role_allows):
- print(" + {0}".format(r))
-
- if diff.removed_role_allows and not args.stats:
- print(" Removed Role Allow Rules: {0}".format(
- len(diff.removed_role_allows)))
- for r in sorted(diff.removed_role_allows):
- print(" - {0}".format(r))
-
- print()
-
- if all_differences or args.role_trans:
- if diff.added_role_transitions or diff.removed_role_transitions or \
- diff.modified_role_transitions or args.role_trans:
- print("Role_transition Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_role_transitions), len(diff.removed_role_transitions),
- len(diff.modified_role_transitions)))
-
- if diff.added_role_transitions and not args.stats:
- print(" Added Role_transition Rules: {0}".format(
- len(diff.added_role_transitions)))
- for r in sorted(diff.added_role_transitions):
- print(" + {0}".format(r))
-
- if diff.removed_role_transitions and not args.stats:
- print(" Removed Role_transition Rules: {0}".format(
- len(diff.removed_role_transitions)))
- for r in sorted(diff.removed_role_transitions):
- print(" - {0}".format(r))
-
- if diff.modified_role_transitions and not args.stats:
- print(" Modified Role_transition Rules: {0}".format(
- len(diff.modified_role_transitions)))
-
- for rule, added_default, removed_default in sorted(diff.modified_role_transitions,
- key=lambda x: x.rule):
- rule_string = \
- "{0.ruletype} {0.source} {0.target}:{0.tclass} +{1} -{2}".format(
- rule, added_default, removed_default)
-
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.range_trans:
- if diff.added_range_transitions or diff.removed_range_transitions or \
- diff.modified_range_transitions or args.range_trans:
- print("Range_transition Rules ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_range_transitions), len(diff.removed_range_transitions),
- len(diff.modified_range_transitions)))
-
- if diff.added_range_transitions and not args.stats:
- print(" Added Range_transition Rules: {0}".format(
- len(diff.added_range_transitions)))
- for r in sorted(diff.added_range_transitions):
- print(" + {0}".format(r))
-
- if diff.removed_range_transitions and not args.stats:
- print(" Removed Range_transition Rules: {0}".format(
- len(diff.removed_range_transitions)))
- for r in sorted(diff.removed_range_transitions):
- print(" - {0}".format(r))
-
- if diff.modified_range_transitions and not args.stats:
- print(" Modified Range_transition Rules: {0}".format(
- len(diff.modified_range_transitions)))
-
- for rule, added_default, removed_default in sorted(diff.modified_range_transitions,
- key=lambda x: x.rule):
- # added brackets around range change for clarity since ranges
- # can have '-' and spaces.
- rule_string = \
- "{0.ruletype} {0.source} {0.target}:{0.tclass} +[{1}] -[{2}]".format(
- rule, added_default, removed_default)
-
- print(" * {0}".format(rule_string))
-
- print()
-
- if all_differences or args.constrain:
- if diff.added_constrains or diff.removed_constrains or args.constrain:
- print("Constraints ({0} Added, {1} Removed)".format(
- len(diff.added_constrains), len(diff.removed_constrains)))
-
- if diff.added_constrains and not args.stats:
- print(" Added Constraints: {0}".format(
- len(diff.added_constrains)))
- for r in sorted(diff.added_constrains):
- print(" + {0}".format(r))
-
- if diff.removed_constrains and not args.stats:
- print(" Removed Constraints: {0}".format(
- len(diff.removed_constrains)))
- for r in sorted(diff.removed_constrains):
- print(" - {0}".format(r))
-
- print()
-
- if all_differences or args.mlsconstrain:
- if diff.added_mlsconstrains or diff.removed_mlsconstrains or args.mlsconstrain:
- print("MLS Constraints ({0} Added, {1} Removed)".format(
- len(diff.added_mlsconstrains), len(diff.removed_mlsconstrains)))
-
- if diff.added_mlsconstrains and not args.stats:
- print(" Added MLS Constraints: {0}".format(
- len(diff.added_mlsconstrains)))
- for r in sorted(diff.added_mlsconstrains):
- print(" + {0}".format(r))
-
- if diff.removed_mlsconstrains and not args.stats:
- print(" Removed MLS Constraints: {0}".format(
- len(diff.removed_mlsconstrains)))
- for r in sorted(diff.removed_mlsconstrains):
- print(" - {0}".format(r))
-
- print()
-
- if all_differences or args.validatetrans:
- if diff.added_validatetrans or diff.removed_validatetrans or args.validatetrans:
- print("Validatetrans ({0} Added, {1} Removed)".format(
- len(diff.added_validatetrans), len(diff.removed_validatetrans)))
-
- if diff.added_validatetrans and not args.stats:
- print(" Added Validatetrans: {0}".format(
- len(diff.added_validatetrans)))
- for r in sorted(diff.added_validatetrans):
- print(" + {0}".format(r))
-
- if diff.removed_validatetrans and not args.stats:
- print(" Removed Validatetrans: {0}".format(
- len(diff.removed_validatetrans)))
- for r in sorted(diff.removed_validatetrans):
- print(" - {0}".format(r))
-
- print()
-
- if all_differences or args.mlsvalidatetrans:
- if diff.added_mlsvalidatetrans or diff.removed_mlsvalidatetrans or args.mlsvalidatetrans:
- print("MLS Validatetrans ({0} Added, {1} Removed)".format(
- len(diff.added_mlsvalidatetrans), len(diff.removed_mlsvalidatetrans)))
-
- if diff.added_mlsvalidatetrans and not args.stats:
- print(" Added MLS Validatetrans: {0}".format(
- len(diff.added_mlsvalidatetrans)))
- for r in sorted(diff.added_mlsvalidatetrans):
- print(" + {0}".format(r))
-
- if diff.removed_mlsvalidatetrans and not args.stats:
- print(" Removed MLS Validatetrans: {0}".format(
- len(diff.removed_mlsvalidatetrans)))
- for r in sorted(diff.removed_mlsvalidatetrans):
- print(" - {0}".format(r))
-
- print()
-
- if all_differences or args.initialsid:
- if diff.added_initialsids or diff.removed_initialsids or diff.modified_initialsids \
- or args.initialsid:
- print("Initial SIDs ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_initialsids), len(diff.removed_initialsids),
- len(diff.modified_initialsids)))
- if diff.added_initialsids and not args.stats:
- print(" Added Initial SIDs: {0}".format(len(diff.added_initialsids)))
- for s in sorted(diff.added_initialsids):
- print(" + {0}".format(s.statement()))
- if diff.removed_initialsids and not args.stats:
- print(" Removed Initial SIDs: {0}".format(len(diff.removed_initialsids)))
- for s in sorted(diff.removed_initialsids):
- print(" - {0}".format(s.statement()))
- if diff.modified_initialsids and not args.stats:
- print(" Modified Initial SIDs: {0}".format(len(diff.modified_initialsids)))
- for name, mod in sorted(diff.modified_initialsids.items()):
- print(" * {0} +[{1.added_context}] -[{1.removed_context}];".format(
- name, mod))
-
- print()
-
- if all_differences or args.fs_use:
- if diff.added_fs_uses or diff.removed_fs_uses or diff.modified_fs_uses \
- or args.fs_use:
- print("Fs_use ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_fs_uses), len(diff.removed_fs_uses),
- len(diff.modified_fs_uses)))
- if diff.added_fs_uses and not args.stats:
- print(" Added Fs_use: {0}".format(len(diff.added_fs_uses)))
- for s in sorted(diff.added_fs_uses):
- print(" + {0}".format(s))
- if diff.removed_fs_uses and not args.stats:
- print(" Removed Fs_use: {0}".format(len(diff.removed_fs_uses)))
- for s in sorted(diff.removed_fs_uses):
- print(" - {0}".format(s))
- if diff.modified_fs_uses and not args.stats:
- print(" Modified Fs_use: {0}".format(len(diff.modified_fs_uses)))
- for entry in sorted(diff.modified_fs_uses, key=lambda x: x.rule):
- print(" * {0.ruletype} {0.fs} +[{1}] -[{2}];".format(
- entry.rule, entry.added_context, entry.removed_context))
-
- print()
-
- if all_differences or args.genfscon:
- if diff.added_genfscons or diff.removed_genfscons or diff.modified_genfscons \
- or args.genfscon:
- print("Genfscons ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_genfscons), len(diff.removed_genfscons),
- len(diff.modified_genfscons)))
- if diff.added_genfscons and not args.stats:
- print(" Added Genfscons: {0}".format(len(diff.added_genfscons)))
- for s in sorted(diff.added_genfscons):
- print(" + {0}".format(s))
- if diff.removed_genfscons and not args.stats:
- print(" Removed Genfscons: {0}".format(len(diff.removed_genfscons)))
- for s in sorted(diff.removed_genfscons):
- print(" - {0}".format(s))
- if diff.modified_genfscons and not args.stats:
- print(" Modified Genfscons: {0}".format(len(diff.modified_genfscons)))
- for entry in sorted(diff.modified_genfscons, key=lambda x: x.rule):
- print(" * genfscon {0.fs} {0.path} {0.filetype} +[{1}] -[{2}];".format(
- entry.rule, entry.added_context, entry.removed_context))
-
- print()
-
- if all_differences or args.netifcon:
- if diff.added_netifcons or diff.removed_netifcons or \
- diff.modified_netifcons or args.netifcon:
- print("Netifcons ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_netifcons), len(diff.removed_netifcons),
- len(diff.modified_netifcons)))
- if diff.added_netifcons and not args.stats:
- print(" Added Netifcons: {0}".format(len(diff.added_netifcons)))
- for n in sorted(diff.added_netifcons):
- print(" + {0}".format(n))
- if diff.removed_netifcons and not args.stats:
- print(" Removed Netifcons: {0}".format(len(diff.removed_netifcons)))
- for n in sorted(diff.removed_netifcons):
- print(" - {0}".format(n))
- if diff.modified_netifcons and not args.stats:
- print(" Modified Netifcons: {0}".format(len(diff.modified_netifcons)))
- for entry in sorted(diff.modified_netifcons, key=lambda x: x.rule):
- # This output is different than other statements because
- # it becomes difficult to read if this was condensed
- # into a single line, especially if both contexts
- # are modified.
- change = []
- if entry.removed_context:
- change.append("Modified Context")
- if entry.removed_packet:
- change.append("Modified Packet Context")
-
- print(" * {0.netif} ({1})".format(entry.rule, ", ".join(change)))
-
- if entry.removed_context:
- print(" Context:")
- print(" + {0}".format(entry.added_context))
- print(" - {0}".format(entry.removed_context))
- if entry.removed_packet:
- print(" Packet Context:")
- print(" + {0}".format(entry.added_packet))
- print(" - {0}".format(entry.removed_packet))
-
- print()
-
- if all_differences or args.nodecon:
- if diff.added_nodecons or diff.removed_nodecons or diff.modified_nodecons \
- or args.nodecon:
- print("Nodecons ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_nodecons), len(diff.removed_nodecons),
- len(diff.modified_nodecons)))
- if diff.added_nodecons and not args.stats:
- print(" Added Nodecons: {0}".format(len(diff.added_nodecons)))
- for n in sorted(diff.added_nodecons):
- print(" + {0}".format(n))
- if diff.removed_nodecons and not args.stats:
- print(" Removed Nodecons: {0}".format(len(diff.removed_nodecons)))
- for n in sorted(diff.removed_nodecons):
- print(" - {0}".format(n))
- if diff.modified_nodecons and not args.stats:
- print(" Modified Nodecons: {0}".format(len(diff.modified_nodecons)))
- for con, added_context, removed_context in sorted(diff.modified_nodecons,
- key=lambda x: x.rule):
- print(" * nodecon {0.address} {0.netmask} +[{1}] -[{2}];".format(
- con, added_context, removed_context))
-
- print()
-
- if all_differences or args.portcon:
- if diff.added_portcons or diff.removed_portcons or diff.modified_portcons \
- or args.portcon:
- print("Portcons ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_portcons), len(diff.removed_portcons),
- len(diff.modified_portcons)))
- if diff.added_portcons and not args.stats:
- print(" Added Portcons: {0}".format(len(diff.added_portcons)))
- for n in sorted(diff.added_portcons):
- print(" + {0}".format(n))
- if diff.removed_portcons and not args.stats:
- print(" Removed Portcons: {0}".format(len(diff.removed_portcons)))
- for n in sorted(diff.removed_portcons):
- print(" - {0}".format(n))
- if diff.modified_portcons and not args.stats:
- print(" Modified Portcons: {0}".format(len(diff.modified_portcons)))
- for con, added_context, removed_context in sorted(diff.modified_portcons,
- key=lambda x: x.rule):
- low, high = con.ports
- if low == high:
- print(" * portcon {0.protocol} {1} +[{2}] -[{3}];".format(
- con, low, added_context, removed_context))
- else:
- print(" * portcon {0.protocol} {1}-{2} +[{3}] -[{4}];".format(
- con, low, high, added_context, removed_context))
-
- print()
-
- if all_differences or args.polcap:
- if diff.added_polcaps or diff.removed_polcaps or args.polcap:
- print("Policy Capabilities ({0} Added, {1} Removed)".format(
- len(diff.added_polcaps), len(diff.removed_polcaps)))
- if diff.added_polcaps and not args.stats:
- print(" Added Policy Capabilities: {0}".format(len(diff.added_polcaps)))
- for n in sorted(diff.added_polcaps):
- print(" + {0}".format(n))
- if diff.removed_polcaps and not args.stats:
- print(" Removed Policy Capabilities: {0}".format(len(diff.removed_polcaps)))
- for n in sorted(diff.removed_polcaps):
- print(" - {0}".format(n))
-
- print()
-
- if all_differences or args.default:
- if diff.added_defaults or diff.removed_defaults or args.default:
- print("Defaults ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_defaults), len(diff.removed_defaults), len(diff.modified_defaults)))
- if diff.added_defaults and not args.stats:
- print(" Added Defaults: {0}".format(len(diff.added_defaults)))
- for d in sorted(diff.added_defaults):
- print(" + {0}".format(d))
- if diff.removed_defaults and not args.stats:
- print(" Removed Defaults: {0}".format(len(diff.removed_defaults)))
- for d in sorted(diff.removed_defaults):
- print(" - {0}".format(d))
- if diff.modified_defaults and not args.stats:
- print(" Modified Defaults: {0}".format(len(diff.modified_defaults)))
- for default, added_default, removed_default, added_range, removed_range in sorted(
- diff.modified_defaults, key=lambda x: x.rule):
- line = " * {0.ruletype} {0.tclass} ".format(default)
- if removed_default:
- line += "+{0} -{1}".format(added_default, removed_default)
- else:
- line += default.default
-
- if removed_range:
- line += " +{0} -{1};".format(added_range, removed_range)
- else:
- try:
- line += " {0};".format(default.default_range)
- except AttributeError:
- line += ";"
- print(line)
-
- print()
-
- if all_differences or args.typebounds:
- if diff.added_typebounds or diff.removed_typebounds or args.typebounds:
- print("Typebounds ({0} Added, {1} Removed, {2} Modified)".format(
- len(diff.added_typebounds), len(diff.removed_typebounds),
- len(diff.modified_typebounds)))
- if diff.added_typebounds and not args.stats:
- print(" Added Typebounds: {0}".format(len(diff.added_typebounds)))
- for d in sorted(diff.added_typebounds):
- print(" + {0}".format(d))
- if diff.removed_typebounds and not args.stats:
- print(" Removed Typebounds: {0}".format(len(diff.removed_typebounds)))
- for d in sorted(diff.removed_typebounds):
- print(" - {0}".format(d))
- if diff.modified_typebounds and not args.stats:
- print(" Modified Typebounds: {0}".format(len(diff.modified_typebounds)))
- for bound, added_bound, removed_bound in sorted(
- diff.modified_typebounds, key=lambda x: x.rule):
- print(" * {0.ruletype} +{1} -{2} {0.child};".format(
- bound, added_bound, removed_bound))
-
- print()
-
-except Exception as err:
- if args.debug:
- logging.exception(str(err))
- else:
- print(err)
-
- sys.exit(1)
diff --git a/prebuilts/bin/seinfo b/prebuilts/bin/seinfo
deleted file mode 100755
index a6f6906e..00000000
--- a/prebuilts/bin/seinfo
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-if [ -z "${ANDROID_BUILD_TOP}" ]; then
- echo 'ANDROID_BUILD_TOP not set. Have you run lunch?'
- exit 1
-fi
-
-unamestr=`uname`
-if [ "$unamestr" = "Linux" -o "$unamestr" = "linux" ]; then
- export LD_LIBRARY_PATH=$ANDROID_BUILD_TOP/external/selinux/prebuilts/lib
- export PYTHONPATH=$ANDROID_BUILD_TOP/prebuilts/python/linux-x86/2.7.5/lib/python2.7/site-packages
- exec python $ANDROID_BUILD_TOP/external/selinux/prebuilts/bin/seinfo.py "$@"
-else
- echo "seinfo is only supported on linux"
- exit 1
-fi
diff --git a/prebuilts/bin/seinfo.py b/prebuilts/bin/seinfo.py
deleted file mode 100755
index e794da7f..00000000
--- a/prebuilts/bin/seinfo.py
+++ /dev/null
@@ -1,366 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2014-2015, Tresys Technology, LLC
-#
-# This file is part of SETools.
-#
-# SETools is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-#
-# SETools is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with SETools. If not, see <http://www.gnu.org/licenses/>.
-#
-
-from __future__ import print_function
-import setools
-import argparse
-import sys
-import logging
-
-
-def expand_attr(attr):
- """Render type and role attributes."""
- items = "\n\t".join(sorted(str(i) for i in attr.expand()))
- contents = items if items else "<empty attribute>"
- return "{0}\n\t{1}".format(attr.statement(), contents)
-
-parser = argparse.ArgumentParser(
- description="SELinux policy information tool.")
-parser.add_argument("--version", action="version", version=setools.__version__)
-parser.add_argument("policy", help="Path to the SELinux policy to query.", nargs="?")
-parser.add_argument("-x", "--expand", action="store_true",
- help="Print additional information about the specified components.")
-parser.add_argument("--flat", help="Print without item count nor indentation.",
- dest="flat", default=False, action="store_true")
-parser.add_argument("-v", "--verbose", action="store_true",
- help="Print extra informational messages")
-parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.")
-
-queries = parser.add_argument_group("Component Queries")
-queries.add_argument("-a", "--attribute", help="Print type attributes.", dest="typeattrquery",
- nargs='?', const=True, metavar="ATTR")
-queries.add_argument("-b", "--bool", help="Print Booleans.", dest="boolquery",
- nargs='?', const=True, metavar="BOOL")
-queries.add_argument("-c", "--class", help="Print object classes.", dest="classquery",
- nargs='?', const=True, metavar="CLASS")
-queries.add_argument("-r", "--role", help="Print roles.", dest="rolequery",
- nargs='?', const=True, metavar="ROLE")
-queries.add_argument("-t", "--type", help="Print types.", dest="typequery",
- nargs='?', const=True, metavar="TYPE")
-queries.add_argument("-u", "--user", help="Print users.", dest="userquery",
- nargs='?', const=True, metavar="USER")
-queries.add_argument("--category", help="Print MLS categories.", dest="mlscatsquery",
- nargs='?', const=True, metavar="CAT")
-queries.add_argument("--common", help="Print common permission set.", dest="commonquery",
- nargs='?', const=True, metavar="COMMON")
-queries.add_argument("--constrain", help="Print constraints.", dest="constraintquery",
- nargs='?', const=True, metavar="CLASS")
-queries.add_argument("--default", help="Print default_* rules.", dest="defaultquery",
- nargs='?', const=True, metavar="CLASS")
-queries.add_argument("--fs_use", help="Print fs_use statements.", dest="fsusequery",
- nargs='?', const=True, metavar="FS_TYPE")
-queries.add_argument("--genfscon", help="Print genfscon statements.", dest="genfsconquery",
- nargs='?', const=True, metavar="FS_TYPE")
-queries.add_argument("--initialsid", help="Print initial SIDs (contexts).", dest="initialsidquery",
- nargs='?', const=True, metavar="NAME")
-queries.add_argument("--netifcon", help="Print netifcon statements.", dest="netifconquery",
- nargs='?', const=True, metavar="DEVICE")
-queries.add_argument("--nodecon", help="Print nodecon statements.", dest="nodeconquery",
- nargs='?', const=True, metavar="ADDR")
-queries.add_argument("--permissive", help="Print permissive types.", dest="permissivequery",
- nargs='?', const=True, metavar="TYPE")
-queries.add_argument("--polcap", help="Print policy capabilities.", dest="polcapquery",
- nargs='?', const=True, metavar="NAME")
-queries.add_argument("--portcon", help="Print portcon statements.", dest="portconquery",
- nargs='?', const=True, metavar="PORTNUM[-PORTNUM]")
-queries.add_argument("--sensitivity", help="Print MLS sensitivities.", dest="mlssensquery",
- nargs='?', const=True, metavar="SENS")
-queries.add_argument("--typebounds", help="Print typebounds statements.", dest="typeboundsquery",
- nargs='?', const=True, metavar="BOUND_TYPE")
-queries.add_argument("--validatetrans", help="Print validatetrans.", dest="validatetransquery",
- nargs='?', const=True, metavar="CLASS")
-queries.add_argument("--all", help="Print all of the above. On a Xen policy, the Xen components "
- "will also be printed", dest="all", default=False, action="store_true")
-
-xen = parser.add_argument_group("Xen Component Queries")
-xen.add_argument("--ioportcon", help="Print all ioportcon statements.", dest="ioportconquery",
- default=False, action="store_true")
-xen.add_argument("--iomemcon", help="Print all iomemcon statements.", dest="iomemconquery",
- default=False, action="store_true")
-xen.add_argument("--pcidevicecon", help="Print all pcidevicecon statements.",
- dest="pcideviceconquery", default=False, action="store_true")
-xen.add_argument("--pirqcon", help="Print all pirqcon statements.", dest="pirqconquery",
- default=False, action="store_true")
-xen.add_argument("--devicetreecon", help="Print all devicetreecon statements.",
- dest="devicetreeconquery", default=False, action="store_true")
-
-
-args = parser.parse_args()
-
-if args.debug:
- logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)s|%(levelname)s|%(name)s|%(message)s')
-elif args.verbose:
- logging.basicConfig(level=logging.INFO, format='%(message)s')
-else:
- logging.basicConfig(level=logging.WARNING, format='%(message)s')
-
-try:
- p = setools.SELinuxPolicy(args.policy)
- components = []
-
- if args.boolquery or args.all:
- q = setools.BoolQuery(p)
- if isinstance(args.boolquery, str):
- q.name = args.boolquery
-
- components.append(("Booleans", q, lambda x: x.statement()))
-
- if args.mlscatsquery or args.all:
- q = setools.CategoryQuery(p)
- if isinstance(args.mlscatsquery, str):
- q.name = args.mlscatsquery
-
- components.append(("Categories", q, lambda x: x.statement()))
-
- if args.classquery or args.all:
- q = setools.ObjClassQuery(p)
- if isinstance(args.classquery, str):
- q.name = args.classquery
-
- components.append(("Classes", q, lambda x: x.statement()))
-
- if args.commonquery or args.all:
- q = setools.CommonQuery(p)
- if isinstance(args.commonquery, str):
- q.name = args.commonquery
-
- components.append(("Commons", q, lambda x: x.statement()))
-
- if args.constraintquery or args.all:
- q = setools.ConstraintQuery(p, ruletype=["constrain", "mlsconstrain"])
- if isinstance(args.constraintquery, str):
- q.tclass = [args.constraintquery]
-
- components.append(("Constraints", q, lambda x: x.statement()))
-
- if args.defaultquery or args.all:
- q = setools.DefaultQuery(p)
- if isinstance(args.defaultquery, str):
- q.tclass = [args.defaultquery]
-
- components.append(("Default rules", q, lambda x: x.statement()))
-
- if args.fsusequery or args.all:
- q = setools.FSUseQuery(p)
- if isinstance(args.fsusequery, str):
- q.fs = args.fsusequery
-
- components.append(("Fs_use", q, lambda x: x.statement()))
-
- if args.genfsconquery or args.all:
- q = setools.GenfsconQuery(p)
- if isinstance(args.genfsconquery, str):
- q.fs = args.genfsconquery
-
- components.append(("Genfscon", q, lambda x: x.statement()))
-
- if args.initialsidquery or args.all:
- q = setools.InitialSIDQuery(p)
- if isinstance(args.initialsidquery, str):
- q.name = args.initialsidquery
-
- components.append(("Initial SIDs", q, lambda x: x.statement()))
-
- if args.netifconquery or args.all:
- q = setools.NetifconQuery(p)
- if isinstance(args.netifconquery, str):
- q.name = args.netifconquery
-
- components.append(("Netifcon", q, lambda x: x.statement()))
-
- if args.nodeconquery or args.all:
- q = setools.NodeconQuery(p)
- if isinstance(args.nodeconquery, str):
- q.network = args.nodeconquery
-
- components.append(("Nodecon", q, lambda x: x.statement()))
-
- if args.permissivequery or args.all:
- q = setools.TypeQuery(p, permissive=True, match_permissive=True)
- if isinstance(args.permissivequery, str):
- q.name = args.permissivequery
-
- components.append(("Permissive Types", q, lambda x: x.statement()))
-
- if args.polcapquery or args.all:
- q = setools.PolCapQuery(p)
- if isinstance(args.polcapquery, str):
- q.name = args.polcapquery
-
- components.append(("Polcap", q, lambda x: x.statement()))
-
- if args.portconquery or args.all:
- q = setools.PortconQuery(p)
- if isinstance(args.portconquery, str):
- try:
- ports = [int(i) for i in args.portconquery.split("-")]
- except ValueError:
- parser.error("Enter a port number or range, e.g. 22 or 6000-6020")
-
- if len(ports) == 2:
- q.ports = ports
- elif len(ports) == 1:
- q.ports = (ports[0], ports[0])
- else:
- parser.error("Enter a port number or range, e.g. 22 or 6000-6020")
-
- components.append(("Portcon", q, lambda x: x.statement()))
-
- if args.rolequery or args.all:
- q = setools.RoleQuery(p)
- if isinstance(args.rolequery, str):
- q.name = args.rolequery
-
- components.append(("Roles", q, lambda x: x.statement()))
-
- if args.mlssensquery or args.all:
- q = setools.SensitivityQuery(p)
- if isinstance(args.mlssensquery, str):
- q.name = args.mlssensquery
-
- components.append(("Sensitivities", q, lambda x: x.statement()))
-
- if args.typeboundsquery or args.all:
- q = setools.BoundsQuery(p, ruletype=["typebounds"])
- if isinstance(args.typeboundsquery, str):
- q.child = args.typeboundsquery
-
- components.append(("Typebounds", q, lambda x: x.statement()))
-
- if args.typequery or args.all:
- q = setools.TypeQuery(p)
- if isinstance(args.typequery, str):
- q.name = args.typequery
-
- components.append(("Types", q, lambda x: x.statement()))
-
- if args.typeattrquery or args.all:
- q = setools.TypeAttributeQuery(p)
- if isinstance(args.typeattrquery, str):
- q.name = args.typeattrquery
-
- components.append(("Type Attributes", q, expand_attr))
-
- if args.userquery or args.all:
- q = setools.UserQuery(p)
- if isinstance(args.userquery, str):
- q.name = args.userquery
-
- components.append(("Users", q, lambda x: x.statement()))
-
- if args.validatetransquery or args.all:
- q = setools.ConstraintQuery(p, ruletype=["validatetrans", "mlsvalidatetrans"])
- if isinstance(args.validatetransquery, str):
- q.tclass = [args.validatetransquery]
-
- components.append(("Validatetrans", q, lambda x: x.statement()))
-
- if p.target_platform == "xen":
- if args.ioportconquery or args.all:
- q = setools.IoportconQuery(p)
- components.append(("Ioportcon", q, lambda x: x.statement()))
-
- if args.iomemconquery or args.all:
- q = setools.IomemconQuery(p)
- components.append(("Iomemcon", q, lambda x: x.statement()))
-
- if args.pcideviceconquery or args.all:
- q = setools.PcideviceconQuery(p)
- components.append(("Pcidevicecon", q, lambda x: x.statement()))
-
- if args.pirqconquery or args.all:
- q = setools.PirqconQuery(p)
- components.append(("Pirqcon", q, lambda x: x.statement()))
-
- if args.devicetreeconquery or args.all:
- q = setools.DevicetreeconQuery(p)
- components.append(("Devicetreecon", q, lambda x: x.statement()))
-
- if (not components or args.all) and not args.flat:
- mls = "enabled" if p.mls else "disabled"
-
- print("Statistics for policy file: {0}".format(p))
- print("Policy Version: {0} (MLS {1})".format(p.version, mls))
- print("Target Policy: {0}".format(p.target_platform))
- print("Handle unknown classes: {0}".format(p.handle_unknown))
- print(" Classes: {0:7} Permissions: {1:7}".format(
- p.class_count, p.permission_count))
- print(" Sensitivities: {0:7} Categories: {1:7}".format(
- p.level_count, p.category_count))
- print(" Types: {0:7} Attributes: {1:7}".format(
- p.type_count, p.type_attribute_count))
- print(" Users: {0:7} Roles: {1:7}".format(
- p.user_count, p.role_count))
- print(" Booleans: {0:7} Cond. Expr.: {1:7}".format(
- p.boolean_count, p.conditional_count))
- print(" Allow: {0:7} Neverallow: {1:7}".format(
- p.allow_count, p.neverallow_count))
- print(" Auditallow: {0:7} Dontaudit: {1:7}".format(
- p.auditallow_count, p.dontaudit_count))
- print(" Type_trans: {0:7} Type_change: {1:7}".format(
- p.type_transition_count, p.type_change_count))
- print(" Type_member: {0:7} Range_trans: {1:7}".format(
- p.type_member_count, p.range_transition_count))
- print(" Role allow: {0:7} Role_trans: {1:7}".format(
- p.role_allow_count, p.role_transition_count))
- print(" Constraints: {0:7} Validatetrans: {1:7}".format(
- p.constraint_count, p.validatetrans_count))
- print(" MLS Constrain: {0:7} MLS Val. Tran: {1:7}".format(
- p.mlsconstraint_count, p.mlsvalidatetrans_count))
- print(" Permissives: {0:7} Polcap: {1:7}".format(
- p.permissives_count, p.polcap_count))
- print(" Defaults: {0:7} Typebounds: {1:7}".format(
- p.default_count, p.typebounds_count))
-
- if p.target_platform == "selinux":
- print(" Allowxperm: {0:7} Neverallowxperm: {1:7}".format(
- p.allowxperm_count, p.neverallowxperm_count))
- print(" Auditallowxperm: {0:7} Dontauditxperm: {1:7}".format(
- p.auditallowxperm_count, p.dontauditxperm_count))
- print(" Initial SIDs: {0:7} Fs_use: {1:7}".format(
- p.initialsids_count, p.fs_use_count))
- print(" Genfscon: {0:7} Portcon: {1:7}".format(
- p.genfscon_count, p.portcon_count))
- print(" Netifcon: {0:7} Nodecon: {1:7}".format(
- p.netifcon_count, p.nodecon_count))
- elif p.target_platform == "xen":
- print(" Initial SIDs: {0:7} Devicetreecon {1:7}".format(
- p.initialsids_count, p.devicetreecon_count))
- print(" Iomemcon: {0:7} Ioportcon: {1:7}".format(
- p.iomemcon_count, p.ioportcon_count))
- print(" Pcidevicecon: {0:7} Pirqcon: {1:7}".format(
- p.pcidevicecon_count, p.pirqcon_count))
-
- for desc, component, expander in components:
- results = sorted(component.results())
- if not args.flat:
- print("\n{0}: {1}".format(desc, len(results)))
- for item in results:
- result = expander(item) if args.expand else item
- strfmt = " {0}" if not args.flat else "{0}"
- print(strfmt.format(result))
-
-except Exception as err:
- if args.debug:
- logging.exception(str(err))
- else:
- print(err)
-
- sys.exit(1)
diff --git a/prebuilts/bin/sesearch b/prebuilts/bin/sesearch
deleted file mode 100755
index 4e2a5880..00000000
--- a/prebuilts/bin/sesearch
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-unamestr=`uname`
-if [ "$unamestr" = "Linux" -o "$unamestr" = "linux" ]; then
- export PYTHONPATH=$ANDROID_BUILD_TOP/prebuilts/python/linux-x86/2.7.5/lib/python2.7/site-packages:$PYTHONPATH
- python $ANDROID_BUILD_TOP/external/selinux/prebuilts/bin/sesearch.py "$@"
-else
- echo "sesearch is only supported on linux"
-fi
diff --git a/prebuilts/bin/sesearch.py b/prebuilts/bin/sesearch.py
deleted file mode 100755
index 5879753f..00000000
--- a/prebuilts/bin/sesearch.py
+++ /dev/null
@@ -1,248 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2014-2015, Tresys Technology, LLC
-#
-# This file is part of SETools.
-#
-# SETools is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-#
-# SETools is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with SETools. If not, see <http://www.gnu.org/licenses/>.
-#
-
-from __future__ import print_function
-import setools
-import argparse
-import sys
-import logging
-
-parser = argparse.ArgumentParser(
- description="SELinux policy rule search tool.",
- epilog="TE/MLS rule searches cannot be mixed with RBAC rule searches.")
-parser.add_argument("--version", action="version", version=setools.__version__)
-parser.add_argument("policy", help="Path to the SELinux policy to search.", nargs="?")
-parser.add_argument("-v", "--verbose", action="store_true",
- help="Print extra informational messages")
-parser.add_argument("--debug", action="store_true", dest="debug", help="Enable debugging.")
-
-rtypes = parser.add_argument_group("TE Rule Types")
-rtypes.add_argument("-A", action="store_true", help="Search allow and allowxperm rules.")
-rtypes.add_argument("--allow", action="append_const",
- const="allow", dest="tertypes",
- help="Search allow rules.")
-rtypes.add_argument("--allowxperm", action="append_const",
- const="allowxperm", dest="tertypes",
- help="Search allowxperm rules.")
-rtypes.add_argument("--auditallow", action="append_const",
- const="auditallow", dest="tertypes",
- help="Search auditallow rules.")
-rtypes.add_argument("--auditallowxperm", action="append_const",
- const="auditallowxperm", dest="tertypes",
- help="Search auditallowxperm rules.")
-rtypes.add_argument("--dontaudit", action="append_const",
- const="dontaudit", dest="tertypes",
- help="Search dontaudit rules.")
-rtypes.add_argument("--dontauditxperm", action="append_const",
- const="dontauditxperm", dest="tertypes",
- help="Search dontauditxperm rules.")
-rtypes.add_argument("--neverallow", action="append_const",
- const="neverallow", dest="tertypes",
- help="Search neverallow rules.")
-rtypes.add_argument("--neverallowxperm", action="append_const",
- const="neverallowxperm", dest="tertypes",
- help="Search neverallowxperm rules.")
-rtypes.add_argument("-T", "--type_trans", action="append_const",
- const="type_transition", dest="tertypes",
- help="Search type_transition rules.")
-rtypes.add_argument("--type_change", action="append_const",
- const="type_change", dest="tertypes",
- help="Search type_change rules.")
-rtypes.add_argument("--type_member", action="append_const",
- const="type_member", dest="tertypes",
- help="Search type_member rules.")
-rbacrtypes = parser.add_argument_group("RBAC Rule Types")
-rbacrtypes.add_argument("--role_allow", action="append_const",
- const="allow", dest="rbacrtypes",
- help="Search role allow rules.")
-rbacrtypes.add_argument("--role_trans", action="append_const",
- const="role_transition", dest="rbacrtypes",
- help="Search role_transition rules.")
-
-mlsrtypes = parser.add_argument_group("MLS Rule Types")
-mlsrtypes.add_argument("--range_trans", action="append_const",
- const="range_transition", dest="mlsrtypes",
- help="Search range_transition rules.")
-
-expr = parser.add_argument_group("Expressions")
-expr.add_argument("-s", "--source",
- help="Source type/role of the TE/RBAC rule.")
-expr.add_argument("-t", "--target",
- help="Target type/role of the TE/RBAC rule.")
-expr.add_argument("-c", "--class", dest="tclass",
- help="Comma separated list of object classes")
-expr.add_argument("-p", "--perms", metavar="PERMS",
- help="Comma separated list of permissions.")
-expr.add_argument("-x", "--xperms", metavar="XPERMS",
- help="Comma separated list of extended permissions.")
-expr.add_argument("-D", "--default",
- help="Default of the rule. (type/role/range transition rules)")
-expr.add_argument("-b", "--bool", dest="boolean", metavar="BOOL",
- help="Comma separated list of Booleans in the conditional expression.")
-
-opts = parser.add_argument_group("Search options")
-opts.add_argument("-eb", action="store_true", dest="boolean_equal",
- help="Match Boolean list exactly instead of matching any listed Boolean.")
-opts.add_argument("-ep", action="store_true", dest="perms_equal",
- help="Match permission set exactly instead of matching any listed permission.")
-opts.add_argument("-ex", action="store_true", dest="xperms_equal",
- help="Match extended permission set exactly instead of matching any listed "
- "permission.")
-opts.add_argument("-ds", action="store_false", dest="source_indirect",
- help="Match source attributes directly instead of matching member types/roles.")
-opts.add_argument("-dt", action="store_false", dest="target_indirect",
- help="Match target attributes directly instead of matching member types/roles.")
-opts.add_argument("-rs", action="store_true", dest="source_regex",
- help="Use regular expression matching for the source type/role.")
-opts.add_argument("-rt", action="store_true", dest="target_regex",
- help="Use regular expression matching for the target type/role.")
-opts.add_argument("-rc", action="store_true", dest="tclass_regex",
- help="Use regular expression matching for the object class.")
-opts.add_argument("-rd", action="store_true", dest="default_regex",
- help="Use regular expression matching for the default type/role.")
-opts.add_argument("-rb", action="store_true", dest="boolean_regex",
- help="Use regular expression matching for Booleans.")
-
-args = parser.parse_args()
-
-if args.A:
- try:
- args.tertypes.extend(["allow", "allowxperm"])
- except AttributeError:
- args.tertypes = ["allow", "allowxperm"]
-
-if not args.tertypes and not args.mlsrtypes and not args.rbacrtypes:
- parser.error("At least one rule type must be specified.")
-
-if args.debug:
- logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)s|%(levelname)s|%(name)s|%(message)s')
-elif args.verbose:
- logging.basicConfig(level=logging.INFO, format='%(message)s')
-else:
- logging.basicConfig(level=logging.WARNING, format='%(message)s')
-
-try:
- p = setools.SELinuxPolicy(args.policy)
-
- if args.tertypes:
- q = setools.TERuleQuery(p,
- ruletype=args.tertypes,
- source=args.source,
- source_indirect=args.source_indirect,
- source_regex=args.source_regex,
- target=args.target,
- target_indirect=args.target_indirect,
- target_regex=args.target_regex,
- tclass_regex=args.tclass_regex,
- perms_equal=args.perms_equal,
- xperms_equal=args.xperms_equal,
- default=args.default,
- default_regex=args.default_regex,
- boolean_regex=args.boolean_regex,
- boolean_equal=args.boolean_equal)
-
- # these are broken out from the above statement to prevent making a list
- # with an empty string in it (split on empty string)
- if args.tclass:
- if args.tclass_regex:
- q.tclass = args.tclass
- else:
- q.tclass = args.tclass.split(",")
-
- if args.perms:
- q.perms = args.perms.split(",")
-
- if args.xperms:
- xperms = []
- for item in args.xperms.split(","):
- rng = item.split("-")
- if len(rng) == 2:
- xperms.append((int(rng[0], base=16), int(rng[1], base=16)))
- elif len(rng) == 1:
- xperms.append((int(rng[0], base=16), int(rng[0], base=16)))
- else:
- parser.error("Enter an extended permission or extended permission range, e.g. "
- "0x5411 or 0x8800-0x88ff.")
-
- q.xperms = xperms
-
- if args.boolean:
- if args.boolean_regex:
- q.boolean = args.boolean
- else:
- q.boolean = args.boolean.split(",")
-
- for r in sorted(q.results()):
- print(r)
-
- if args.rbacrtypes:
- q = setools.RBACRuleQuery(p,
- ruletype=args.rbacrtypes,
- source=args.source,
- source_indirect=args.source_indirect,
- source_regex=args.source_regex,
- target=args.target,
- target_indirect=args.target_indirect,
- target_regex=args.target_regex,
- default=args.default,
- default_regex=args.default_regex,
- tclass_regex=args.tclass_regex)
-
- # these are broken out from the above statement to prevent making a list
- # with an empty string in it (split on empty string)
- if args.tclass:
- if args.tclass_regex:
- q.tclass = args.tclass
- else:
- q.tclass = args.tclass.split(",")
-
- for r in sorted(q.results()):
- print(r)
-
- if args.mlsrtypes:
- q = setools.MLSRuleQuery(p,
- ruletype=args.mlsrtypes,
- source=args.source,
- source_indirect=args.source_indirect,
- source_regex=args.source_regex,
- target=args.target,
- target_indirect=args.target_indirect,
- target_regex=args.target_regex,
- tclass_regex=args.tclass_regex,
- default=args.default)
-
- # these are broken out from the above statement to prevent making a list
- # with an empty string in it (split on empty string)
- if args.tclass:
- if args.tclass_regex:
- q.tclass = args.tclass
- else:
- q.tclass = args.tclass.split(",")
-
- for r in sorted(q.results()):
- print(r)
-
-except Exception as err:
- if args.debug:
- logging.exception(str(err))
- else:
- print(err)
-
- sys.exit(1)
diff --git a/python/VERSION b/python/VERSION
index 9f55b2cc..eb39e538 100644
--- a/python/VERSION
+++ b/python/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/python/audit2allow/Makefile b/python/audit2allow/Makefile
index 15db5490..76bf4e37 100644
--- a/python/audit2allow/Makefile
+++ b/python/audit2allow/Makefile
@@ -19,7 +19,7 @@ endif
all: audit2why sepolgen-ifgen-attr-helper
sepolgen-ifgen-attr-helper: sepolgen-ifgen-attr-helper.o $(LIBSEPOLA)
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA)
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) -lselinux
audit2why:
ln -sf audit2allow audit2why
diff --git a/python/audit2allow/sepolgen-ifgen b/python/audit2allow/sepolgen-ifgen
index 4a71cda4..b7a04c71 100644
--- a/python/audit2allow/sepolgen-ifgen
+++ b/python/audit2allow/sepolgen-ifgen
@@ -27,7 +27,6 @@
import sys
-import os
import tempfile
import subprocess
@@ -65,37 +64,18 @@ def parse_options():
return options
-def get_policy():
- p = selinux.selinux_current_policy_path()
- if p and os.path.exists(p):
- return p
- i = selinux.security_policyvers()
- p = selinux.selinux_binary_policy_path() + "." + str(i)
- while i > 0 and not os.path.exists(p):
- i = i - 1
- p = selinux.selinux_binary_policy_path() + "." + str(i)
- if i > 0:
- return p
- return None
-
-
def get_attrs(policy_path, attr_helper):
try:
- if not policy_path:
- policy_path = get_policy()
- if not policy_path:
- sys.stderr.write("No installed policy to check\n")
- return None
outfile = tempfile.NamedTemporaryFile()
except IOError as e:
sys.stderr.write("could not open attribute output file\n")
return None
- except OSError:
- # SELinux Disabled Machine
- return None
fd = open("/dev/null", "w")
- ret = subprocess.Popen([attr_helper, policy_path, outfile.name], stdout=fd).wait()
+ if policy_path:
+ ret = subprocess.Popen([attr_helper, outfile.name, policy_path], stdout=fd).wait()
+ else:
+ ret = subprocess.Popen([attr_helper, outfile.name], stdout=fd).wait()
fd.close()
if ret != 0:
sys.stderr.write("could not run attribute helper\n")
diff --git a/python/audit2allow/sepolgen-ifgen-attr-helper.c b/python/audit2allow/sepolgen-ifgen-attr-helper.c
index 1ce37b0d..6f3ba962 100644
--- a/python/audit2allow/sepolgen-ifgen-attr-helper.c
+++ b/python/audit2allow/sepolgen-ifgen-attr-helper.c
@@ -26,6 +26,9 @@
#include <sepol/policydb/avtab.h>
#include <sepol/policydb/util.h>
+#include <selinux/selinux.h>
+
+#include <limits.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -53,7 +56,7 @@ static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data)
return 0;
}
-int render_access_mask(uint32_t av, avtab_key_t *key, policydb_t *policydbp,
+static int render_access_mask(uint32_t av, avtab_key_t *key, policydb_t *policydbp,
FILE *fp)
{
struct val_to_name v;
@@ -108,7 +111,7 @@ struct callback_data
FILE *fp;
};
-int output_avrule(avtab_key_t *key, avtab_datum_t *datum, void *args)
+static int output_avrule(avtab_key_t *key, avtab_datum_t *datum, void *args)
{
struct callback_data *cb_data = (struct callback_data *)args;
@@ -147,8 +150,36 @@ static policydb_t *load_policy(const char *filename)
policydb_t *policydb;
struct policy_file pf;
FILE *fp;
+ char pathname[PATH_MAX];
+ int suffix_ver;
int ret;
+ /* no explicit policy name given, try loaded policy on a SELinux enabled system */
+ if (!filename) {
+ filename = selinux_current_policy_path();
+ }
+
+ /*
+ * Fallback to default store paths with version suffixes,
+ * starting from the maximum supported policy version.
+ */
+ if (!filename) {
+ for (suffix_ver = sepol_policy_kern_vers_max(); suffix_ver > 0; suffix_ver--) {
+ snprintf(pathname, sizeof(pathname), "%s.%d", selinux_binary_policy_path(), suffix_ver);
+
+ if (access(pathname, F_OK) == 0) {
+ filename = pathname;
+ break;
+ }
+ }
+
+ if (!filename) {
+ fprintf(stderr, "Can't find any policy at '%s'\n",
+ selinux_binary_policy_path());
+ return NULL;
+ }
+ }
+
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Can't open '%s': %s\n",
@@ -186,9 +217,9 @@ static policydb_t *load_policy(const char *filename)
}
-void usage(char *progname)
+static void usage(char *progname)
{
- printf("usage: %s policy_file out_file\n", progname);
+ printf("usage: %s out_file [policy_file]\n", progname);
}
int main(int argc, char **argv)
@@ -197,18 +228,18 @@ int main(int argc, char **argv)
struct callback_data cb_data;
FILE *fp;
- if (argc != 3) {
+ if (argc != 2 && argc != 3) {
usage(argv[0]);
return -1;
}
/* Open the policy. */
- p = load_policy(argv[1]);
+ p = load_policy(argv[2]);
if (p == NULL)
return -1;
/* Open the output policy. */
- fp = fopen(argv[2], "w");
+ fp = fopen(argv[1], "w");
if (fp == NULL) {
fprintf(stderr, "error opening output file\n");
policydb_destroy(p);
diff --git a/python/semanage/semanage b/python/semanage/semanage
index b2fabea6..ff9fb66b 100644
--- a/python/semanage/semanage
+++ b/python/semanage/semanage
@@ -23,10 +23,13 @@
#
#
-import traceback
import argparse
+import os
+import re
import seobject
import sys
+import traceback
+
PROGNAME = "policycoreutils"
try:
import gettext
@@ -126,7 +129,7 @@ class SetImportFile(argparse.Action):
sys.exit(1)
setattr(namespace, self.dest, values)
-# define dictonary for seobject OBEJCTS
+# define dictionary for seobject OBEJCTS
object_dict = {
'login': seobject.loginRecords,
'user': seobject.seluserRecords,
@@ -143,7 +146,7 @@ object_dict = {
}
def generate_custom_usage(usage_text, usage_dict):
- # generate custom usage from given text and dictonary
+ # generate custom usage from given text and dictionary
sorted_keys = []
for i in usage_dict.keys():
sorted_keys.append(i)
@@ -157,7 +160,7 @@ def generate_custom_usage(usage_text, usage_dict):
def handle_opts(args, dict, target_key):
- # handle conflict and required options for given dictonary
+ # handle conflict and required options for given dictionary
# {action:[conflict_opts,require_opts]}
# first we need to catch conflicts
@@ -376,7 +379,7 @@ If you do not specify a file type, the file type will default to "all files".
parser_add_seuser(fcontextParser, "fcontext")
parser_add_type(fcontextParser, "fcontext")
parser_add_range(fcontextParser, "fcontext")
- fcontextParser.add_argument('file_spec', nargs='?', default=None, help=_('file_spec'))
+ fcontextParser.add_argument('file_spec', nargs='?', default=None, help=_('Path to be labeled (may be in the form of a Perl compatible regular expression)'))
fcontextParser.set_defaults(func=handleFcontext)
@@ -797,8 +800,6 @@ def setupExportParser(subparsers):
exportParser.add_argument('-f', '--output_file', dest='output_file', action=SetExportFile, help=_('Output file'))
exportParser.set_defaults(func=handleExport)
-import re
-
def mkargv(line):
dquote = "\""
@@ -945,6 +946,13 @@ def do_parser():
args = commandParser.parse_args(make_args(sys.argv))
args.func(args)
sys.exit(0)
+ except BrokenPipeError as e:
+ sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
+ # Python flushes standard streams on exit; redirect remaining output
+ # to devnull to avoid another BrokenPipeError at shutdown
+ devnull = os.open(os.devnull, os.O_WRONLY)
+ os.dup2(devnull, sys.stdout.fileno())
+ sys.exit(1)
except IOError as e:
sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
sys.exit(1)
diff --git a/python/semanage/semanage-bash-completion.sh b/python/semanage/semanage-bash-completion.sh
index 2d811c98..d0dd139f 100644
--- a/python/semanage/semanage-bash-completion.sh
+++ b/python/semanage/semanage-bash-completion.sh
@@ -54,6 +54,9 @@ __get_all_roles () {
__get_all_stores () {
dir -1 -F /etc/selinux/ | grep '/' | cut -d'/' -f 1
}
+__get_all_modules () {
+ semodule -l
+}
__get_import_opts () { echo '$ALL_OPTS --f --input_file' ; }
__get_export_opts () { echo '$ALL_OPTS --f --output_file' ; }
__get_boolean_opts () { echo '$ALL_OPTS --on -off -1 -0' ; }
@@ -88,6 +91,13 @@ _semanage () {
if [ "$prev" = "-a" -a "$command" = "permissive" ]; then
COMPREPLY=( $(compgen -W "$( __get_all_domains ) " -- "$cur") )
return 0
+ elif [ "$command" = "module" ]; then
+ if [ "$prev" = "-d" ] || [ "$prev" = "--disable" ] \
+ || [ "$prev" = "-e" ] || [ "$prev" = "--enable" ] \
+ || [ "$prev" = "-r" ] || [ "$prev" = "--remove" ]; then
+ COMPREPLY=( $(compgen -W "$( __get_all_modules ) " -- "$cur") )
+ return 0
+ fi
fi
if [ "$verb" = "" -a "$prev" = "semanage" ]; then
comps="${VERBS[*]}"
diff --git a/python/semanage/semanage-fcontext.8 b/python/semanage/semanage-fcontext.8
index 561123af..1ebf085f 100644
--- a/python/semanage/semanage-fcontext.8
+++ b/python/semanage/semanage-fcontext.8
@@ -3,7 +3,7 @@
semanage\-fcontext \- SELinux Policy Management file context tool
.SH "SYNOPSIS"
-.B semanage fcontext [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add ( \-t TYPE \-f FTYPE \-r RANGE \-s SEUSER | \-e EQUAL ) FILE_SPEC ) | \-\-delete ( \-t TYPE \-f FTYPE | \-e EQUAL ) FILE_SPEC ) | \-\-deleteall | \-\-extract | \-\-list [\-C] | \-\-modify ( \-t TYPE \-f FTYPE \-r RANGE \-s SEUSER | \-e EQUAL ) FILE_SPEC ) ]
+.B semanage fcontext [\-h] [\-n] [\-N] [\-S STORE] [ \-\-add ( \-t TYPE \-f FTYPE \-r RANGE \-s SEUSER | \-e EQUAL ) FILE_SPEC | \-\-delete ( \-t TYPE \-f FTYPE | \-e EQUAL ) FILE_SPEC | \-\-deleteall | \-\-extract | \-\-list [\-C] | \-\-modify ( \-t TYPE \-f FTYPE \-r RANGE \-s SEUSER | \-e EQUAL ) FILE_SPEC ]
.SH "DESCRIPTION"
semanage is used to configure certain elements of
@@ -11,6 +11,24 @@ SELinux policy without requiring modification to or recompilation
from policy sources. semanage fcontext is used to manage the default
file system labeling on an SELinux system. This command maps file paths using regular expressions to SELinux labels.
+FILE_SPEC may contain either a fully qualified path,
+or a Perl compatible regular expression (PCRE),
+describing fully qualified path(s). The only PCRE flag in use is PCRE2_DOTALL,
+which causes a wildcard '.' to match anything, including a new line.
+Strings representing paths are processed as bytes (as opposed to Unicode),
+meaning that non-ASCII characters are not matched by a single wildcard.
+
+Note, that file context definitions specified using 'semanage fcontext'
+(i.e. local file context modifications stored in file_contexts.local)
+have higher priority than those specified in policy modules.
+This means that whenever a match for given file path is found in
+file_contexts.local, no other file context definitions are considered.
+Entries in file_contexts.local are processed from most recent one to the oldest,
+with first match being used (as opposed to the most specific match,
+which is used when matching other file context definitions).
+All regular expressions should therefore be as specific as possible,
+to avoid unintentionally impacting other parts of the filesystem.
+
.SH "OPTIONS"
.TP
.I \-h, \-\-help
diff --git a/python/semanage/semanage-node.8 b/python/semanage/semanage-node.8
index e0b0e56c..a0098221 100644
--- a/python/semanage/semanage-node.8
+++ b/python/semanage/semanage-node.8
@@ -45,7 +45,7 @@ Extract customizable commands, for use within a transaction
Remove all local customizations
.TP
.I \-M NETMASK, \-\-netmask NETMASK
-Network Mask
+Network Mask, either in CIDR (/16) or address mask notation (255.255.0.0, ffff::)
.TP
.I \-t TYPE, \-\-type TYPE
SELinux type for the object
diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index 0e9ce290..21adbf6e 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -31,8 +31,9 @@ import socket
from semanage import *
PROGNAME = "policycoreutils"
import sepolicy
-import setools
-from IPy import IP
+from setools.policyrep import SELinuxPolicy
+from setools.typequery import TypeQuery
+import ipaddress
try:
import gettext
@@ -1339,7 +1340,7 @@ class ibpkeyRecords(semanageRecords):
def __init__(self, args = None):
semanageRecords.__init__(self, args)
try:
- q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_store_policy(self.store)), attrs=["ibpkey_type"])
+ q = TypeQuery(SELinuxPolicy(sepolicy.get_store_policy(self.store)), attrs=["ibpkey_type"])
self.valid_types = sorted(str(t) for t in q.results())
except:
pass
@@ -1599,7 +1600,7 @@ class ibendportRecords(semanageRecords):
def __init__(self, args = None):
semanageRecords.__init__(self, args)
try:
- q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_store_policy(self.store)), attrs=["ibendport_type"])
+ q = TypeQuery(SELinuxPolicy(sepolicy.get_store_policy(self.store)), attrs=["ibendport_type"])
self.valid_types = set(str(t) for t in q.results())
except:
pass
@@ -1858,25 +1859,34 @@ class nodeRecords(semanageRecords):
if addr == "":
raise ValueError(_("Node Address is required"))
- # verify valid combination
+ # verify that (addr, mask) is either a IP address (without a mask) or a valid network mask
if len(mask) == 0 or mask[0] == "/":
- i = IP(addr + mask)
- newaddr = i.strNormal(0)
- newmask = str(i.netmask())
- if newmask == "0.0.0.0" and i.version() == 6:
- newmask = "::"
-
- protocol = "ipv%d" % i.version()
+ i = ipaddress.ip_network(addr + mask)
+ newaddr = str(i.network_address)
+ newmask = str(i.netmask)
+ protocol = "ipv%d" % i.version
try:
newprotocol = self.protocol.index(protocol)
except:
raise ValueError(_("Unknown or missing protocol"))
- return newaddr, newmask, newprotocol
+ try:
+ audit_protocol = socket.getprotobyname(protocol)
+ except:
+ # Entry for "ipv4" not found in /etc/protocols on (at
+ # least) Debian? To ensure audit log compatibility, let's
+ # use the same numeric value as Fedora: 4, which is
+ # actually understood by kernel as IP over IP.
+ if (protocol == "ipv4"):
+ audit_protocol = socket.IPPROTO_IPIP
+ else:
+ raise ValueError(_("Unknown or missing protocol"))
+
+ return newaddr, newmask, newprotocol, audit_protocol
def __add(self, addr, mask, proto, serange, ctype):
- addr, mask, proto = self.validate(addr, mask, proto)
+ addr, mask, proto, audit_proto = self.validate(addr, mask, proto)
if is_mls_enabled == 1:
if serange == "":
@@ -1895,10 +1905,10 @@ class nodeRecords(semanageRecords):
(rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
if rc < 0:
raise ValueError(_("Could not create key for %s") % addr)
- if rc < 0:
- raise ValueError(_("Could not check if addr %s is defined") % addr)
(rc, exists) = semanage_node_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if addr %s is defined") % addr)
if exists:
raise ValueError(_("Addr %s already defined") % addr)
@@ -1945,7 +1955,7 @@ class nodeRecords(semanageRecords):
semanage_node_key_free(k)
semanage_node_free(node)
- self.mylog.log_change("resrc=node op=add laddr=%s netmask=%s proto=%s tcontext=%s:%s:%s:%s" % (addr, mask, socket.getprotobyname(self.protocol[proto]), "system_u", "object_r", ctype, serange))
+ self.mylog.log_change("resrc=node op=add laddr=%s netmask=%s proto=%s tcontext=%s:%s:%s:%s" % (addr, mask, audit_proto, "system_u", "object_r", ctype, serange))
def add(self, addr, mask, proto, serange, ctype):
self.begin()
@@ -1953,7 +1963,7 @@ class nodeRecords(semanageRecords):
self.commit()
def __modify(self, addr, mask, proto, serange, setype):
- addr, mask, proto = self.validate(addr, mask, proto)
+ addr, mask, proto, audit_proto = self.validate(addr, mask, proto)
if serange == "" and setype == "":
raise ValueError(_("Requires setype or serange"))
@@ -1990,7 +2000,7 @@ class nodeRecords(semanageRecords):
semanage_node_key_free(k)
semanage_node_free(node)
- self.mylog.log_change("resrc=node op=modify laddr=%s netmask=%s proto=%s tcontext=%s:%s:%s:%s" % (addr, mask, socket.getprotobyname(self.protocol[proto]), "system_u", "object_r", setype, serange))
+ self.mylog.log_change("resrc=node op=modify laddr=%s netmask=%s proto=%s tcontext=%s:%s:%s:%s" % (addr, mask, audit_proto, "system_u", "object_r", setype, serange))
def modify(self, addr, mask, proto, serange, setype):
self.begin()
@@ -1998,8 +2008,7 @@ class nodeRecords(semanageRecords):
self.commit()
def __delete(self, addr, mask, proto):
-
- addr, mask, proto = self.validate(addr, mask, proto)
+ addr, mask, proto, audit_proto = self.validate(addr, mask, proto)
(rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
if rc < 0:
@@ -2023,7 +2032,7 @@ class nodeRecords(semanageRecords):
semanage_node_key_free(k)
- self.mylog.log_change("resrc=node op=delete laddr=%s netmask=%s proto=%s" % (addr, mask, socket.getprotobyname(self.protocol[proto])))
+ self.mylog.log_change("resrc=node op=delete laddr=%s netmask=%s proto=%s" % (addr, mask, audit_proto))
def delete(self, addr, mask, proto):
self.begin()
diff --git a/python/semanage/test-semanage.py b/python/semanage/test-semanage.py
index c8f6ec23..d99e3fda 100644
--- a/python/semanage/test-semanage.py
+++ b/python/semanage/test-semanage.py
@@ -233,7 +233,7 @@ def semanage_custom_suite(test_list):
def semanage_run_test(suite):
- unittest.TextTestRunner(verbosity=2).run(suite)
+ return unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful()
class CheckTest(argparse.Action):
@@ -255,9 +255,9 @@ def semanage_args(args):
for i in semanage_test_list:
print(i)
if args.all:
- semanage_run_test(semanage_suite())
+ return semanage_run_test(semanage_suite())
if args.test:
- semanage_run_test(semanage_custom_suite(args.test))
+ return semanage_run_test(semanage_custom_suite(args.test))
def gen_semanage_test_args(parser):
@@ -281,8 +281,10 @@ if __name__ == "__main__":
gen_semanage_test_args(parser)
try:
args = parser.parse_args()
- args.func(args)
- sys.exit(0)
+ if args.func(args):
+ sys.exit(0)
+ else:
+ sys.exit(1)
except ValueError as e:
sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
sys.exit(1)
diff --git a/python/sepolgen/VERSION b/python/sepolgen/VERSION
index 9f55b2cc..eb39e538 100644
--- a/python/sepolgen/VERSION
+++ b/python/sepolgen/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/python/sepolgen/src/sepolgen/output.py b/python/sepolgen/src/sepolgen/output.py
index 3a21b64c..aeeaafc8 100644
--- a/python/sepolgen/src/sepolgen/output.py
+++ b/python/sepolgen/src/sepolgen/output.py
@@ -84,7 +84,7 @@ def avrule_cmp(a, b):
return ret
# At this point, who cares - just return something
- return cmp(len(a.perms), len(b.perms))
+ return 0
# Compare two interface calls
def ifcall_cmp(a, b):
@@ -100,7 +100,7 @@ def rule_cmp(a, b):
else:
return id_set_cmp([a.args[0]], b.src_types)
else:
- if isinstance(b, refpolicy.AVRule):
+ if isinstance(b, refpolicy.AVRule) or isinstance(b, refpolicy.AVExtRule):
return avrule_cmp(a,b)
else:
return id_set_cmp(a.src_types, [b.args[0]])
@@ -130,6 +130,7 @@ def sort_filter(module):
# we assume is the first argument for interfaces).
rules = []
rules.extend(node.avrules())
+ rules.extend(node.avextrules())
rules.extend(node.interface_calls())
rules.sort(key=util.cmp_to_key(rule_cmp))
diff --git a/python/sepolgen/src/sepolgen/refparser.py b/python/sepolgen/src/sepolgen/refparser.py
index 2e521a0f..1bb90564 100644
--- a/python/sepolgen/src/sepolgen/refparser.py
+++ b/python/sepolgen/src/sepolgen/refparser.py
@@ -126,6 +126,7 @@ tokens = (
'GEN_REQ',
'TEMPLATE',
'GEN_CONTEXT',
+ 'GEN_TUNABLE',
# m4
'IFELSE',
'IFDEF',
@@ -192,6 +193,7 @@ reserved = {
'gen_require' : 'GEN_REQ',
'template' : 'TEMPLATE',
'gen_context' : 'GEN_CONTEXT',
+ 'gen_tunable' : 'GEN_TUNABLE',
# M4
'ifelse' : 'IFELSE',
'ifndef' : 'IFNDEF',
@@ -259,7 +261,7 @@ def t_IDENTIFIER(t):
return t
def t_FILENAME(t):
- r'\"[a-zA-Z0-9_\-\+\.\$\*~ :]+\"'
+ r'\"[a-zA-Z0-9_\-\+\.\$\*~ :\[\]]+\"'
# Handle any keywords
t.type = reserved.get(t.value,'FILENAME')
return t
@@ -431,9 +433,9 @@ def p_ifelse(p):
def p_ifdef(p):
- '''ifdef : IFDEF OPAREN TICK IDENTIFIER SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN optional_semi
- | IFNDEF OPAREN TICK IDENTIFIER SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN optional_semi
- | IFDEF OPAREN TICK IDENTIFIER SQUOTE COMMA TICK interface_stmts SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN optional_semi
+ '''ifdef : IFDEF OPAREN TICK IDENTIFIER SQUOTE COMMA TICK statements SQUOTE CPAREN optional_semi
+ | IFNDEF OPAREN TICK IDENTIFIER SQUOTE COMMA TICK statements SQUOTE CPAREN optional_semi
+ | IFDEF OPAREN TICK IDENTIFIER SQUOTE COMMA TICK statements SQUOTE COMMA TICK statements SQUOTE CPAREN optional_semi
'''
x = refpolicy.IfDef(p[4])
if p[1] == 'ifdef':
@@ -518,6 +520,7 @@ def p_policy_stmt(p):
| range_transition_def
| role_transition_def
| bool
+ | gen_tunable
| define
| initial_sid
| genfscon
@@ -844,6 +847,17 @@ def p_bool(p):
b.state = False
p[0] = b
+def p_gen_tunable(p):
+ '''gen_tunable : GEN_TUNABLE OPAREN TICK IDENTIFIER SQUOTE COMMA TRUE CPAREN
+ | GEN_TUNABLE OPAREN TICK IDENTIFIER SQUOTE COMMA FALSE CPAREN'''
+ b = refpolicy.Bool()
+ b.name = p[4]
+ if p[7] == "true":
+ b.state = True
+ else:
+ b.state = False
+ p[0] = b
+
def p_conditional(p):
''' conditional : IF OPAREN cond_expr CPAREN OBRACE interface_stmts CBRACE
| IF OPAREN cond_expr CPAREN OBRACE interface_stmts CBRACE ELSE OBRACE interface_stmts CBRACE
@@ -1134,6 +1148,6 @@ def parse_headers(root, output=None, expand=True, debug=False):
status.step()
if len(failures):
- o("failed to parse some headers: %s" % ", ".join(failures))
+ o("failed to parse some headers: %s\n" % ", ".join(failures))
return headers
diff --git a/python/sepolgen/src/sepolgen/refpolicy.py b/python/sepolgen/src/sepolgen/refpolicy.py
index 43cecfc7..3e907e91 100644
--- a/python/sepolgen/src/sepolgen/refpolicy.py
+++ b/python/sepolgen/src/sepolgen/refpolicy.py
@@ -42,7 +42,7 @@ PERMS = 3
ROLE = 4
DEST_TYPE = 5
-# String represenations of the above constants
+# String representations of the above constants
field_to_str = ["source", "target", "object", "permission", "role", "destination" ]
str_to_field = { "source" : SRC_TYPE, "target" : TGT_TYPE, "object" : OBJ_CLASS,
"permission" : PERMS, "role" : ROLE, "destination" : DEST_TYPE }
@@ -407,10 +407,9 @@ class XpermSet():
# print single value without braces
if len(self.ranges) == 1 and self.ranges[0][0] == self.ranges[0][1]:
- return compl + str(self.ranges[0][0])
+ return compl + hex(self.ranges[0][0])
- vals = map(lambda x: str(x[0]) if x[0] == x[1] else "%s-%s" % x,
- self.ranges)
+ vals = map(lambda x: hex(x[0]) if x[0] == x[1] else "%s-%s" % (hex(x[0]), hex(x[1]), ), self.ranges)
return "%s{ %s }" % (compl, " ".join(vals))
diff --git a/python/sepolgen/src/sepolgen/yacc.py b/python/sepolgen/src/sepolgen/yacc.py
index 55c1ef7d..c1c79880 100644
--- a/python/sepolgen/src/sepolgen/yacc.py
+++ b/python/sepolgen/src/sepolgen/yacc.py
@@ -1502,7 +1502,7 @@ class Grammar(object):
self.Precedence = {} # Precedence rules for each terminal. Contains tuples of the
# form ('right',level) or ('nonassoc', level) or ('left',level)
- self.UsedPrecedence = set() # Precedence rules that were actually used by the grammer.
+ self.UsedPrecedence = set() # Precedence rules that were actually used by the grammar.
# This is only used to provide error checking and to generate
# a warning about unused precedence rules.
diff --git a/python/sepolgen/tests/test_access.py b/python/sepolgen/tests/test_access.py
index 73a5407d..623588e0 100644
--- a/python/sepolgen/tests/test_access.py
+++ b/python/sepolgen/tests/test_access.py
@@ -171,7 +171,7 @@ class TestAccessVector(unittest.TestCase):
a.merge(b)
self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"])
self.assertEqual(list(a.xperms.keys()), ["ioctl"])
- self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
+ self.assertEqual(a.xperms["ioctl"].to_string(), "{ 0x2a 0x3039 }")
def text_merge_xperm2(self):
"""Test merging AV that does not contain xperms with AV that does"""
@@ -185,7 +185,7 @@ class TestAccessVector(unittest.TestCase):
a.merge(b)
self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"])
self.assertEqual(list(a.xperms.keys()), ["ioctl"])
- self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
+ self.assertEqual(a.xperms["ioctl"].to_string(), "{ 0x2a 0x3039 }")
def test_merge_xperm_diff_op(self):
"""Test merging two AVs that contain xperms with different operation"""
@@ -203,8 +203,8 @@ class TestAccessVector(unittest.TestCase):
a.merge(b)
self.assertEqual(list(a.perms), ["read"])
self.assertEqual(sorted(list(a.xperms.keys())), ["asdf", "ioctl"])
- self.assertEqual(a.xperms["asdf"].to_string(), "23")
- self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
+ self.assertEqual(a.xperms["asdf"].to_string(), "0x17")
+ self.assertEqual(a.xperms["ioctl"].to_string(), "{ 0x2a 0x3039 }")
def test_merge_xperm_same_op(self):
"""Test merging two AVs that contain xperms with same operation"""
@@ -222,7 +222,7 @@ class TestAccessVector(unittest.TestCase):
a.merge(b)
self.assertEqual(list(a.perms), ["read"])
self.assertEqual(list(a.xperms.keys()), ["ioctl"])
- self.assertEqual(a.xperms["ioctl"].to_string(), "{ 23 42 12345 }")
+ self.assertEqual(a.xperms["ioctl"].to_string(), "{ 0x17 0x2a 0x3039 }")
class TestUtilFunctions(unittest.TestCase):
def test_is_idparam(self):
diff --git a/python/sepolgen/tests/test_refpolicy.py b/python/sepolgen/tests/test_refpolicy.py
index 4b50c8aa..c7219fd5 100644
--- a/python/sepolgen/tests/test_refpolicy.py
+++ b/python/sepolgen/tests/test_refpolicy.py
@@ -90,17 +90,17 @@ class TestXpermSet(unittest.TestCase):
a.complement = True
self.assertEqual(a.to_string(), "")
a.add(1234)
- self.assertEqual(a.to_string(), "~ 1234")
+ self.assertEqual(a.to_string(), "~ 0x4d2")
a.complement = False
- self.assertEqual(a.to_string(), "1234")
+ self.assertEqual(a.to_string(), "0x4d2")
a.add(2345)
- self.assertEqual(a.to_string(), "{ 1234 2345 }")
+ self.assertEqual(a.to_string(), "{ 0x4d2 0x929 }")
a.complement = True
- self.assertEqual(a.to_string(), "~ { 1234 2345 }")
+ self.assertEqual(a.to_string(), "~ { 0x4d2 0x929 }")
a.add(42,64)
- self.assertEqual(a.to_string(), "~ { 42-64 1234 2345 }")
+ self.assertEqual(a.to_string(), "~ { 0x2a-0x40 0x4d2 0x929 }")
a.complement = False
- self.assertEqual(a.to_string(), "{ 42-64 1234 2345 }")
+ self.assertEqual(a.to_string(), "{ 0x2a-0x40 0x4d2 0x929 }")
class TestSecurityContext(unittest.TestCase):
def test_init(self):
diff --git a/python/sepolicy/Makefile b/python/sepolicy/Makefile
index 69f29fa9..3361be4e 100644
--- a/python/sepolicy/Makefile
+++ b/python/sepolicy/Makefile
@@ -27,7 +27,7 @@ test:
@$(PYTHON) test_sepolicy.py -v
install:
- $(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)`
+ $(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` $(PYTHON_SETUP_ARGS)
[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
install -m 755 sepolicy.py $(DESTDIR)$(BINDIR)/sepolicy
(cd $(DESTDIR)$(BINDIR); ln -sf sepolicy sepolgen)
diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
index e4540977..e8654abb 100644
--- a/python/sepolicy/sepolicy/__init__.py
+++ b/python/sepolicy/sepolicy/__init__.py
@@ -4,7 +4,6 @@
import errno
import selinux
-import setools
import glob
import sepolgen.defaults as defaults
import sepolgen.interfaces as interfaces
@@ -13,6 +12,17 @@ import os
import re
import gzip
+from setools.boolquery import BoolQuery
+from setools.portconquery import PortconQuery
+from setools.policyrep import SELinuxPolicy
+from setools.objclassquery import ObjClassQuery
+from setools.rbacrulequery import RBACRuleQuery
+from setools.rolequery import RoleQuery
+from setools.terulequery import TERuleQuery
+from setools.typeattrquery import TypeAttributeQuery
+from setools.typequery import TypeQuery
+from setools.userquery import UserQuery
+
PROGNAME = "policycoreutils"
try:
import gettext
@@ -168,7 +178,7 @@ def policy(policy_file):
global _pol
try:
- _pol = setools.SELinuxPolicy(policy_file)
+ _pol = SELinuxPolicy(policy_file)
except:
raise ValueError(_("Failed to read %s policy file") % policy_file)
@@ -178,17 +188,17 @@ def load_store_policy(store):
return None
policy(policy_file)
-try:
+def init_policy():
policy_file = get_installed_policy()
policy(policy_file)
-except ValueError as e:
- if selinux.is_selinux_enabled() == 1:
- raise e
-
def info(setype, name=None):
+ global _pol
+ if not _pol:
+ init_policy()
+
if setype == TYPE:
- q = setools.TypeQuery(_pol)
+ q = TypeQuery(_pol)
q.name = name
results = list(q.results())
@@ -206,7 +216,7 @@ def info(setype, name=None):
} for x in results)
elif setype == ROLE:
- q = setools.RoleQuery(_pol)
+ q = RoleQuery(_pol)
if name:
q.name = name
@@ -217,7 +227,7 @@ def info(setype, name=None):
} for x in q.results())
elif setype == ATTRIBUTE:
- q = setools.TypeAttributeQuery(_pol)
+ q = TypeAttributeQuery(_pol)
if name:
q.name = name
@@ -227,7 +237,7 @@ def info(setype, name=None):
} for x in q.results())
elif setype == PORT:
- q = setools.PortconQuery(_pol)
+ q = PortconQuery(_pol)
if name:
ports = [int(i) for i in name.split("-")]
if len(ports) == 2:
@@ -251,7 +261,7 @@ def info(setype, name=None):
} for x in q.results())
elif setype == USER:
- q = setools.UserQuery(_pol)
+ q = UserQuery(_pol)
if name:
q.name = name
@@ -268,7 +278,7 @@ def info(setype, name=None):
} for x in q.results())
elif setype == BOOLEAN:
- q = setools.BoolQuery(_pol)
+ q = BoolQuery(_pol)
if name:
q.name = name
@@ -278,7 +288,7 @@ def info(setype, name=None):
} for x in q.results())
elif setype == TCLASS:
- q = setools.ObjClassQuery(_pol)
+ q = ObjClassQuery(_pol)
if name:
q.name = name
@@ -337,6 +347,9 @@ def _setools_rule_to_dict(rule):
def search(types, seinfo=None):
+ global _pol
+ if not _pol:
+ init_policy()
if not seinfo:
seinfo = {}
valid_types = set([ALLOW, AUDITALLOW, NEVERALLOW, DONTAUDIT, TRANSITION, ROLE_ALLOW])
@@ -369,11 +382,11 @@ def search(types, seinfo=None):
tertypes.append(DONTAUDIT)
if len(tertypes) > 0:
- q = setools.TERuleQuery(_pol,
- ruletype=tertypes,
- source=source,
- target=target,
- tclass=tclass)
+ q = TERuleQuery(_pol,
+ ruletype=tertypes,
+ source=source,
+ target=target,
+ tclass=tclass)
if PERMS in seinfo:
q.perms = seinfo[PERMS]
@@ -382,11 +395,11 @@ def search(types, seinfo=None):
if TRANSITION in types:
rtypes = ['type_transition', 'type_change', 'type_member']
- q = setools.TERuleQuery(_pol,
- ruletype=rtypes,
- source=source,
- target=target,
- tclass=tclass)
+ q = TERuleQuery(_pol,
+ ruletype=rtypes,
+ source=source,
+ target=target,
+ tclass=tclass)
if PERMS in seinfo:
q.perms = seinfo[PERMS]
@@ -395,11 +408,11 @@ def search(types, seinfo=None):
if ROLE_ALLOW in types:
ratypes = ['allow']
- q = setools.RBACRuleQuery(_pol,
- ruletype=ratypes,
- source=source,
- target=target,
- tclass=tclass)
+ q = RBACRuleQuery(_pol,
+ ruletype=ratypes,
+ source=source,
+ target=target,
+ tclass=tclass)
for r in q.results():
toret.append({'source': str(r.source),
@@ -717,11 +730,11 @@ def get_all_entrypoints():
def get_entrypoint_types(setype):
- q = setools.TERuleQuery(_pol,
- ruletype=[ALLOW],
- source=setype,
- tclass=["file"],
- perms=["entrypoint"])
+ q = TERuleQuery(_pol,
+ ruletype=[ALLOW],
+ source=setype,
+ tclass=["file"],
+ perms=["entrypoint"])
return [str(x.target) for x in q.results() if x.source == setype]
@@ -736,10 +749,10 @@ def get_init_transtype(path):
def get_init_entrypoint(transtype):
- q = setools.TERuleQuery(_pol,
- ruletype=["type_transition"],
- source="init_t",
- tclass=["process"])
+ q = TERuleQuery(_pol,
+ ruletype=["type_transition"],
+ source="init_t",
+ tclass=["process"])
entrypoints = []
for i in q.results():
try:
@@ -751,10 +764,10 @@ def get_init_entrypoint(transtype):
return entrypoints
def get_init_entrypoints_str():
- q = setools.TERuleQuery(_pol,
- ruletype=["type_transition"],
- source="init_t",
- tclass=["process"])
+ q = TERuleQuery(_pol,
+ ruletype=["type_transition"],
+ source="init_t",
+ tclass=["process"])
entrypoints = {}
for i in q.results():
try:
@@ -834,7 +847,7 @@ def get_all_role_allows():
return role_allows
role_allows = {}
- q = setools.RBACRuleQuery(_pol, ruletype=[ALLOW])
+ q = RBACRuleQuery(_pol, ruletype=[ALLOW])
for r in q.results():
src = str(r.source)
tgt = str(r.target)
@@ -916,7 +929,11 @@ def get_all_roles():
if roles:
return roles
- q = setools.RoleQuery(_pol)
+ global _pol
+ if not _pol:
+ init_policy()
+
+ q = RoleQuery(_pol)
roles = [str(x) for x in q.results() if str(x) != "object_r"]
return roles
@@ -1032,7 +1049,7 @@ def get_description(f, markup=markup):
return txt + "treat the files as %s key data." % prettyprint(f, "_key_t")
if f.endswith("_secret_t"):
- return txt + "treat the files as %s secret data." % prettyprint(f, "_key_t")
+ return txt + "treat the files as %s secret data." % prettyprint(f, "_secret_t")
if f.endswith("_ra_t"):
return txt + "treat the files as %s read/append content." % prettyprint(f, "_ra_t")
@@ -1064,7 +1081,7 @@ def get_description(f, markup=markup):
if f.endswith("_tmp_t"):
return txt + "store %s temporary files in the /tmp directories." % prettyprint(f, "_tmp_t")
if f.endswith("_etc_t"):
- return txt + "store %s files in the /etc directories." % prettyprint(f, "_tmp_t")
+ return txt + "store %s files in the /etc directories." % prettyprint(f, "_etc_t")
if f.endswith("_home_t"):
return txt + "store %s files in the users home directory." % prettyprint(f, "_home_t")
if f.endswith("_tmpfs_t"):
diff --git a/python/sepolicy/sepolicy/generate.py b/python/sepolicy/sepolicy/generate.py
index e8d07e7d..4e1ed4e9 100644
--- a/python/sepolicy/sepolicy/generate.py
+++ b/python/sepolicy/sepolicy/generate.py
@@ -340,7 +340,7 @@ class policy:
(self.generate_root_user_types, self.generate_root_user_rules),
(self.generate_new_types, self.generate_new_rules))
if not re.match(r"^[a-zA-Z0-9-_]+$", name):
- raise ValueError(_("Name must be alpha numeric with no spaces. Consider using option \"-n MODULENAME\""))
+ raise ValueError(_("Name must be alphanumeric with no spaces. Consider using option \"-n MODULENAME\""))
if type == CGI:
self.name = "httpd_%s_script" % name
@@ -438,7 +438,7 @@ class policy:
def set_init_script(self, initscript):
if self.type != DAEMON:
- raise ValueError(_("Only Daemon apps can use an init script.."))
+ raise ValueError(_("Only Daemon apps can use an init script."))
self.initscript = initscript
diff --git a/python/sepolicy/sepolicy/interface.py b/python/sepolicy/sepolicy/interface.py
index 187419fa..bdffb770 100644
--- a/python/sepolicy/sepolicy/interface.py
+++ b/python/sepolicy/sepolicy/interface.py
@@ -146,12 +146,12 @@ def get_interface_dict(path="/usr/share/selinux/devel/policy.xml"):
tree = xml.etree.ElementTree.fromstring(xml_path)
for l in tree.findall("layer"):
for m in l.findall("module"):
- for i in m.getiterator('interface'):
+ for i in m.iter('interface'):
for e in i.findall("param"):
param_list.append(e.get('name'))
interface_dict[(i.get("name"))] = [param_list, (i.find('summary').text), "interface"]
param_list = []
- for i in m.getiterator('template'):
+ for i in m.iter('template'):
for e in i.findall("param"):
param_list.append(e.get('name'))
interface_dict[(i.get("name"))] = [param_list, (i.find('summary').text), "template"]
@@ -198,7 +198,7 @@ def get_xml_file(if_file):
filename = os.path.basename(if_file).split(".")[0]
rc, output = getstatusoutput("/usr/bin/python3 /usr/share/selinux/devel/include/support/segenxml.py -w -m %s" % (basedir + filename))
if rc != 0:
- sys.stderr.write("\n Could not proceed selected interface file.\n")
+ sys.stderr.write("\n Could not process selected interface file.\n")
sys.stderr.write("\n%s" % output)
sys.exit(1)
else:
diff --git a/python/sepolicy/sepolicy/manpage.py b/python/sepolicy/sepolicy/manpage.py
index 44260819..3e61e333 100755
--- a/python/sepolicy/sepolicy/manpage.py
+++ b/python/sepolicy/sepolicy/manpage.py
@@ -39,6 +39,8 @@ typealias_types = {
equiv_dict = {"smbd": ["samba"], "httpd": ["apache"], "virtd": ["virt", "libvirt"], "named": ["bind"], "fsdaemon": ["smartmon"], "mdadm": ["raid"]}
equiv_dirs = ["/var"]
+man_date = time.strftime("%y-%m-%d", time.gmtime(
+ int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))))
modules_dict = None
@@ -569,7 +571,7 @@ class ManPage:
def _typealias(self,typealias):
self.fd.write('.TH "%(typealias)s_selinux" "8" "%(date)s" "%(typealias)s" "SELinux Policy %(typealias)s"'
- % {'typealias':typealias, 'date': time.strftime("%y-%m-%d")})
+ % {'typealias':typealias, 'date': man_date})
self.fd.write(r"""
.SH "NAME"
%(typealias)s_selinux \- Security Enhanced Linux Policy for the %(typealias)s processes
@@ -588,7 +590,7 @@ man page for more details.
def _header(self):
self.fd.write('.TH "%(domainname)s_selinux" "8" "%(date)s" "%(domainname)s" "SELinux Policy %(domainname)s"'
- % {'domainname': self.domainname, 'date': time.strftime("%y-%m-%d")})
+ % {'domainname': self.domainname, 'date': man_date})
self.fd.write(r"""
.SH "NAME"
%(domainname)s_selinux \- Security Enhanced Linux Policy for the %(domainname)s processes
@@ -795,7 +797,7 @@ SELinux %(domainname)s policy is very flexible allowing users to setup their %(d
.B STANDARD FILE CONTEXT
SELinux defines the file context types for the %(domainname)s, if you wanted to
-store files with these types in a diffent paths, you need to execute the semanage command to sepecify alternate labeling and then use restorecon to put the labels on disk.
+store files with these types in a diffent paths, you need to execute the semanage command to specify alternate labeling and then use restorecon to put the labels on disk.
.B semanage fcontext -a -t %(type)s '/srv/%(domainname)s/content(/.*)?'
.br
@@ -1074,7 +1076,7 @@ If you wanted to change the default user mapping to use the %(user)s_u user, you
.B semanage login -m -s %(user)s_u __default__
-""" % {'desc': self.desc, 'type': self.type, 'user': self.domainname, 'range': self._get_users_range()})
+""" % {'desc': self.desc, 'user': self.domainname, 'range': self._get_users_range()})
if "login_userdomain" in self.attributes and "login_userdomain" in self.all_attributes:
self.fd.write("""
@@ -1245,7 +1247,7 @@ Execute the following to see the types that the SELinux user %(type)s can execut
.B $ sesearch -A -s %(type)s -c process -p transition
-""" % {'user': self.domainname, 'type': self.type})
+""" % {'type': self.type})
def _role_header(self):
self.fd.write('.TH "%(user)s_selinux" "8" "%(user)s" "mgrepl@redhat.com" "%(user)s SELinux Policy documentation"'
diff --git a/python/sepolicy/sepolicy/network.py b/python/sepolicy/sepolicy/network.py
index ff308fad..d26a7ce6 100755
--- a/python/sepolicy/sepolicy/network.py
+++ b/python/sepolicy/sepolicy/network.py
@@ -49,15 +49,15 @@ def get_network_connect(src, protocol, perm, check_bools=False):
if "port_t" in tlist:
continue
if i == "port_t":
- d[(src, protocol, perm)].append((i, ["all ports with out defined types"]))
+ d[(src, protocol, perm)].append((i, ["all ports without defined types"]))
if i == "port_type":
d[(src, protocol, perm)].append((i, ["all ports"]))
elif i == "unreserved_port_type":
- d[(src, protocol, perm)].append((i, ["all ports > 1024"]))
+ d[(src, protocol, perm)].append((i, ["all ports >= 1024"]))
elif i == "reserved_port_type":
d[(src, protocol, perm)].append((i, ["all ports < 1024"]))
elif i == "rpc_port_type":
- d[(src, protocol, perm)].append((i, ["all ports > 500 and < 1024"]))
+ d[(src, protocol, perm)].append((i, ["all ports >= 512 and < 1024"]))
else:
try:
d[(src, protocol, perm)].append((i, portrecs[(i, protocol)]))
diff --git a/python/sepolicy/sepolicy/sedbus.py b/python/sepolicy/sepolicy/sedbus.py
index 76b259ae..39b53d47 100644
--- a/python/sepolicy/sepolicy/sedbus.py
+++ b/python/sepolicy/sepolicy/sedbus.py
@@ -2,7 +2,6 @@ import sys
import dbus
import dbus.service
import dbus.mainloop.glib
-from slip.dbus import polkit
class SELinuxDBus (object):
@@ -11,42 +10,34 @@ class SELinuxDBus (object):
self.bus = dbus.SystemBus()
self.dbus_object = self.bus.get_object("org.selinux", "/org/selinux/object")
- @polkit.enable_proxy
def semanage(self, buf):
ret = self.dbus_object.semanage(buf, dbus_interface="org.selinux")
return ret
- @polkit.enable_proxy
def restorecon(self, path):
ret = self.dbus_object.restorecon(path, dbus_interface="org.selinux")
return ret
- @polkit.enable_proxy
def setenforce(self, value):
ret = self.dbus_object.setenforce(value, dbus_interface="org.selinux")
return ret
- @polkit.enable_proxy
def customized(self):
ret = self.dbus_object.customized(dbus_interface="org.selinux")
return ret
- @polkit.enable_proxy
def semodule_list(self):
ret = self.dbus_object.semodule_list(dbus_interface="org.selinux")
return ret
- @polkit.enable_proxy
def relabel_on_boot(self, value):
ret = self.dbus_object.relabel_on_boot(value, dbus_interface="org.selinux")
return ret
- @polkit.enable_proxy
def change_default_mode(self, value):
ret = self.dbus_object.change_default_mode(value, dbus_interface="org.selinux")
return ret
- @polkit.enable_proxy
def change_default_policy(self, value):
ret = self.dbus_object.change_default_policy(value, dbus_interface="org.selinux")
return ret
diff --git a/python/sepolicy/sepolicy/sepolicy.glade b/python/sepolicy/sepolicy/sepolicy.glade
index 8f6ad650..52407887 100644
--- a/python/sepolicy/sepolicy/sepolicy.glade
+++ b/python/sepolicy/sepolicy/sepolicy.glade
@@ -2877,19 +2877,9 @@ Enabled</property>
</object>
</child>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn27">
- <child>
- <object class="GtkCellRendererText" id="cellrenderertext34"/>
- <attributes>
- <attribute name="text">1</attribute>
- </attributes>
- </child>
- </object>
- </child>
- <child>
<object class="GtkTreeViewColumn" id="executable_file_from">
<property name="resizable">True</property>
- <property name="title" translatable="yes">Boolean name</property>
+ <property name="title" translatable="yes">Executable File</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<property name="reorderable">True</property>
diff --git a/python/sepolicy/setup.py b/python/sepolicy/setup.py
index fa60ef6c..e81b6cc7 100644
--- a/python/sepolicy/setup.py
+++ b/python/sepolicy/setup.py
@@ -6,7 +6,7 @@ from distutils.core import setup
setup(
name="sepolicy",
- version="3.0",
+ version="3.3",
description="Python SELinux Policy Analyses bindings",
author="Daniel Walsh",
author_email="dwalsh@redhat.com",
diff --git a/restorecond/Makefile b/restorecond/Makefile
index 12452cd2..8e9a5ef1 100644
--- a/restorecond/Makefile
+++ b/restorecond/Makefile
@@ -7,19 +7,20 @@ SBINDIR ?= $(PREFIX)/sbin
MANDIR = $(PREFIX)/share/man
AUTOSTARTDIR = /etc/xdg/autostart
DBUSSERVICEDIR = $(PREFIX)/share/dbus-1/services
-SYSTEMDDIR ?= $(PREFIX)/lib/systemd
+SYSTEMDSYSTEMUNITDIR ?= $(shell $(PKG_CONFIG) --variable=systemdsystemunitdir systemd)
+SYSTEMDUSERUNITDIR ?= $(shell $(PKG_CONFIG) --variable=systemduserunitdir systemd)
autostart_DATA = sealertauto.desktop
INITDIR ?= /etc/rc.d/init.d
SELINUXDIR = /etc/selinux
-DBUSFLAGS = -DHAVE_DBUS $(shell $(PKG_CONFIG) --cflags dbus-glib-1)
-DBUSLIB = $(shell $(PKG_CONFIG) --libs dbus-glib-1)
+GIO_CFLAGS = -DHAVE_DBUS $(shell $(PKG_CONFIG) --cflags gio-2.0)
+GIO_LIBS = $(shell $(PKG_CONFIG) --libs gio-2.0)
CFLAGS ?= -g -Werror -Wall -W
-override CFLAGS += $(DBUSFLAGS)
+override CFLAGS += $(GIO_CFLAGS)
-override LDLIBS += -lselinux $(DBUSLIB)
+override LDLIBS += -lselinux $(GIO_LIBS)
all: restorecond
@@ -48,8 +49,10 @@ install: all
install -m 644 restorecond.desktop $(DESTDIR)$(AUTOSTARTDIR)/restorecond.desktop
-mkdir -p $(DESTDIR)$(DBUSSERVICEDIR)
install -m 644 org.selinux.Restorecond.service $(DESTDIR)$(DBUSSERVICEDIR)/org.selinux.Restorecond.service
- -mkdir -p $(DESTDIR)$(SYSTEMDDIR)/system
- install -m 644 restorecond.service $(DESTDIR)$(SYSTEMDDIR)/system/
+ -mkdir -p $(DESTDIR)$(SYSTEMDSYSTEMUNITDIR)
+ install -m 644 restorecond.service $(DESTDIR)$(SYSTEMDSYSTEMUNITDIR)
+ -mkdir -p $(DESTDIR)$(SYSTEMDUSERUNITDIR)
+ install -m 644 restorecond_user.service $(DESTDIR)$(SYSTEMDUSERUNITDIR)
relabel: install
/sbin/restorecon $(DESTDIR)$(SBINDIR)/restorecond
diff --git a/restorecond/VERSION b/restorecond/VERSION
index 9f55b2cc..eb39e538 100644
--- a/restorecond/VERSION
+++ b/restorecond/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/restorecond/org.selinux.Restorecond.service b/restorecond/org.selinux.Restorecond.service
index 0ef5f0b5..45aeb7aa 100644
--- a/restorecond/org.selinux.Restorecond.service
+++ b/restorecond/org.selinux.Restorecond.service
@@ -1,3 +1,4 @@
[D-BUS Service]
Name=org.selinux.Restorecond
Exec=/usr/sbin/restorecond -u
+SystemdService=restorecond_user.service
diff --git a/restorecond/restorecond.desktop b/restorecond/restorecond.desktop
index af728680..7df85472 100644
--- a/restorecond/restorecond.desktop
+++ b/restorecond/restorecond.desktop
@@ -5,3 +5,4 @@ Comment=Fix file context in owned by the user
Type=Application
StartupNotify=false
X-GNOME-Autostart-enabled=false
+X-GNOME-HiddenUnderSystemd=true
diff --git a/restorecond/restorecond_user.service b/restorecond/restorecond_user.service
new file mode 100644
index 00000000..28ca770f
--- /dev/null
+++ b/restorecond/restorecond_user.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Restorecon maintaining path file context (user service)
+Documentation=man:restorecond(8)
+ConditionPathExists=/etc/selinux/restorecond_user.conf
+ConditionSecurity=selinux
+
+[Service]
+Type=dbus
+BusName=org.selinux.Restorecond
+ExecStart=/usr/sbin/restorecond -u
diff --git a/restorecond/user.c b/restorecond/user.c
index 8f932307..47b86823 100644
--- a/restorecond/user.c
+++ b/restorecond/user.c
@@ -2,6 +2,7 @@
* restorecond
*
* Copyright (C) 2006-2009 Red Hat
+ * Copyright (C) 2020 Nicolas Iooss
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
@@ -21,7 +22,7 @@
*
* Authors:
* Dan Walsh <dwalsh@redhat.com>
- *
+ * Nicolas Iooss <nicolas.iooss@m4x.org>
*/
#define _GNU_SOURCE
@@ -33,73 +34,76 @@
#include <string.h>
#include <unistd.h>
#include <ctype.h>
+#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <limits.h>
#include <fcntl.h>
+#include <selinux/selinux.h>
+
#include "restorecond.h"
#include "stringslist.h"
#include <glib.h>
-#ifdef HAVE_DBUS
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
+#include <glib-unix.h>
-static DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data);
+static int local_lock_fd = -1;
-static const char *PATH="/org/selinux/Restorecond";
-//static const char *BUSNAME="org.selinux.Restorecond";
-static const char *INTERFACE="org.selinux.RestorecondIface";
-static const char *RULE="type='signal',interface='org.selinux.RestorecondIface'";
+#ifdef HAVE_DBUS
+#include <gio/gio.h>
-static int local_lock_fd = -1;
+static const char *DBUS_NAME = "org.selinux.Restorecond";
-static DBusHandlerResult
-signal_filter (DBusConnection *connection __attribute__ ((__unused__)), DBusMessage *message, void *user_data)
+static void on_name_acquired(GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *name,
+ gpointer user_data G_GNUC_UNUSED)
{
- /* User data is the event loop we are running in */
- GMainLoop *loop = user_data;
+ if (debug_mode)
+ g_print("D-Bus name acquired: %s\n", name);
+}
- /* A signal from the bus saying we are about to be disconnected */
- if (dbus_message_is_signal
- (message, INTERFACE, "Stop")) {
+static void on_name_lost(GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *name,
+ gpointer user_data)
+{
+ /* Exit when the D-Bus connection closes */
+ GMainLoop *loop = user_data;
- /* Tell the main loop to quit */
- g_main_loop_quit (loop);
- /* We have handled this message, don't pass it on */
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- /* A Ping signal on the com.burtonini.dbus.Signal interface */
- else if (dbus_message_is_signal (message, INTERFACE, "Start")) {
- DBusError error;
- dbus_error_init (&error);
- g_print("Start received\n");
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ if (debug_mode)
+ g_print("D-Bus name lost (%s), exiting\n", name);
+ g_main_loop_quit(loop);
}
-static int dbus_server(GMainLoop *loop) {
- DBusConnection *bus;
- DBusError error;
- dbus_error_init (&error);
- bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
- if (bus) {
- dbus_connection_setup_with_g_main (bus, NULL);
-
- /* listening to messages from all objects as no path is specified */
- dbus_bus_add_match (bus, RULE, &error); // see signals from the given interfacey
- dbus_connection_add_filter (bus, signal_filter, loop, NULL);
+/**
+ * Try starting a D-Bus server on the session bus.
+ * Returns -1 if the connection failed, so that a local server can be launched
+ */
+static int dbus_server(GMainLoop *loop)
+{
+ GDBusConnection *bus;
+ guint client_id;
+
+ bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
+ if (!bus)
+ return -1;
+
+ client_id = g_bus_own_name_on_connection(
+ bus,
+ DBUS_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_name_acquired,
+ on_name_lost,
+ loop,
+ NULL);
+ g_object_unref(bus);
+ if (client_id == 0)
+ return -1;
+
return 0;
- }
- return -1;
}
#endif
-#include <selinux/selinux.h>
-#include <sys/file.h>
/* size of the event structure, not counting name */
#define EVENT_SIZE (sizeof (struct inotify_event))
@@ -167,29 +171,42 @@ io_channel_callback
int start() {
#ifdef HAVE_DBUS
- DBusConnection *bus;
- DBusError error;
- DBusMessage *message;
+ GDBusConnection *bus;
+ GError *err = NULL;
+ GVariant *result;
/* Get a connection to the session bus */
- dbus_error_init (&error);
- bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
+ bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err);
if (!bus) {
if (debug_mode)
- g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
- dbus_error_free (&error);
+ g_warning("Failed to connect to the D-BUS daemon: %s", err->message);
+ g_error_free(err);
return 1;
}
-
- /* Create a new signal "Start" on the interface,
- * from the object */
- message = dbus_message_new_signal (PATH,
- INTERFACE, "Start");
- /* Send the signal */
- dbus_connection_send (bus, message, NULL);
- /* Free the signal now we have finished with it */
- dbus_message_unref (message);
+ /* Start restorecond D-Bus service by pinging its bus name
+ *
+ * https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-peer
+ */
+ result = g_dbus_connection_call_sync(bus,
+ DBUS_NAME, /* bus name */
+ "/", /* object path */
+ "org.freedesktop.DBus.Peer", /* interface */
+ "Ping", /* method */
+ NULL, /* parameters */
+ NULL, /* reply_type */
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, /* timeout_msec */
+ NULL,
+ &err);
+ if (!result) {
+ g_object_unref(bus);
+ if (debug_mode)
+ g_warning("Failed to start %s: %s", DBUS_NAME, err->message);
+ g_error_free(err);
+ return 1;
+ }
+ g_object_unref(bus);
#endif /* HAVE_DBUS */
return 0;
}
@@ -213,9 +230,10 @@ static int local_server(void) {
return -1;
}
if (flock(local_lock_fd, LOCK_EX | LOCK_NB) < 0) {
- close(local_lock_fd);
if (debug_mode)
perror("flock");
+ close(local_lock_fd);
+ local_lock_fd = -1;
return -1;
}
/* watch for stdin/terminal going away */
@@ -234,35 +252,54 @@ static void end_local_server(void) {
local_lock_fd = -1;
}
+static int sigterm_handler(gpointer user_data)
+{
+ GMainLoop *loop = user_data;
+
+ if (debug_mode)
+ g_print("Received SIGTERM, exiting\n");
+ g_main_loop_quit(loop);
+ return FALSE;
+}
+
+
int server(int master_fd, const char *watch_file) {
- GMainLoop *loop;
+ GMainLoop *loop;
- loop = g_main_loop_new (NULL, FALSE);
+ loop = g_main_loop_new (NULL, FALSE);
#ifdef HAVE_DBUS
- if (dbus_server(loop) != 0)
+ if (dbus_server(loop) != 0)
#endif /* HAVE_DBUS */
- if (local_server())
- goto end;
+ if (local_server())
+ goto end;
- read_config(master_fd, watch_file);
+ read_config(master_fd, watch_file);
- if (watch_list_isempty()) goto end;
+ if (watch_list_isempty())
+ goto end;
- set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
+ set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
- GIOChannel *c = g_io_channel_unix_new(master_fd);
+ GIOChannel *c = g_io_channel_unix_new(master_fd);
- g_io_add_watch_full( c,
- G_PRIORITY_HIGH,
- G_IO_IN|G_IO_ERR|G_IO_HUP,
- io_channel_callback, NULL, NULL);
+ g_io_add_watch_full(c,
+ G_PRIORITY_HIGH,
+ G_IO_IN|G_IO_ERR|G_IO_HUP,
+ io_channel_callback, NULL, NULL);
- g_main_loop_run (loop);
+ /* Handle SIGTERM */
+ g_unix_signal_add_full(G_PRIORITY_DEFAULT,
+ SIGTERM,
+ sigterm_handler,
+ loop,
+ NULL);
+
+ g_main_loop_run (loop);
end:
- end_local_server();
- g_main_loop_unref (loop);
- return 0;
+ end_local_server();
+ g_main_loop_unref (loop);
+ return 0;
}
diff --git a/sandbox/VERSION b/sandbox/VERSION
index 9f55b2cc..eb39e538 100644
--- a/sandbox/VERSION
+++ b/sandbox/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/sandbox/seunshare.c b/sandbox/seunshare.c
index 9707a456..8917a0f9 100644
--- a/sandbox/seunshare.c
+++ b/sandbox/seunshare.c
@@ -89,7 +89,7 @@ static int drop_privs(uid_t uid)
/**
* If the user sends a siginto to seunshare, kill the child's session
*/
-void handler(int sig) {
+static void handler(int sig) {
if (child > 0) kill(-child,sig);
}
@@ -431,13 +431,13 @@ static int cleanup_tmpdir(const char *tmpdir, const char *src,
* to clean it up.
*/
static char *create_tmpdir(const char *src, struct stat *src_st,
- struct stat *out_st, struct passwd *pwd, security_context_t execcon)
+ struct stat *out_st, struct passwd *pwd, const char *execcon)
{
char *tmpdir = NULL;
char *cmdbuf = NULL;
int fd_t = -1, fd_s = -1;
struct stat tmp_st;
- security_context_t con = NULL;
+ char *con = NULL;
/* get selinux context */
if (execcon) {
@@ -549,10 +549,10 @@ good:
#define PROC_BASE "/proc"
static int
-killall (security_context_t execcon)
+killall (const char *execcon)
{
DIR *dir;
- security_context_t scon;
+ char *scon;
struct dirent *de;
pid_t *pid_table, pid, self;
int i;
@@ -615,7 +615,7 @@ killall (security_context_t execcon)
int main(int argc, char **argv) {
int status = -1;
- security_context_t execcon = NULL;
+ const char *execcon = NULL;
int clflag; /* holds codes for command line flags */
int kill_all = 0;
diff --git a/scripts/ci/.gitignore b/scripts/ci/.gitignore
new file mode 100644
index 00000000..a977916f
--- /dev/null
+++ b/scripts/ci/.gitignore
@@ -0,0 +1 @@
+.vagrant/
diff --git a/scripts/ci/LICENSE b/scripts/ci/LICENSE
new file mode 100644
index 00000000..1f95d26c
--- /dev/null
+++ b/scripts/ci/LICENSE
@@ -0,0 +1,5 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/scripts/ci/README.md b/scripts/ci/README.md
new file mode 100644
index 00000000..04a134a4
--- /dev/null
+++ b/scripts/ci/README.md
@@ -0,0 +1,8 @@
+# Continuous Integration Scripts
+
+The scripts under `scripts/ci` are designed specifically
+for the Travis CI system. While nothing prevents you
+from mimicking that environment and using them locally,
+they are not applicable for general consumption. Any
+thing in this directory should never be considered as
+a stable API.
diff --git a/scripts/ci/Vagrantfile b/scripts/ci/Vagrantfile
new file mode 100644
index 00000000..20c523a0
--- /dev/null
+++ b/scripts/ci/Vagrantfile
@@ -0,0 +1,48 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+# Vagrant configuration file which creates a virtual machine that can run the
+# test suite using fedora-test-runner.sh, in an environment similar to the one
+# used for automated continuous integration tests (Travis-CI)
+#
+# To create a new virtual machine:
+#
+# vagrant up --provision
+#
+# To launch tests (for example after modifications to libsepol, libselinux... are made):
+#
+# vagrant rsync && echo ./run-selinux-test.sh | vagrant ssh
+#
+# To destroy the virtual machine (for example to start again from a clean environment):
+#
+# vagrant destroy
+
+# Create a helper script in the VM to run the testsuite as root from a clean environment
+$script = <<SCRIPT
+cat > /home/vagrant/run-selinux-test.sh << EOF
+#/bin/sh
+set -e -v
+
+# Run the tests
+sudo /root/selinux/scripts/ci/fedora-test-runner.sh
+echo 'All tests passed :)'
+EOF
+chmod +x /home/vagrant/run-selinux-test.sh
+SCRIPT
+
+# All Vagrant configuration is done below. The "2" in Vagrant.configure
+# configures the configuration version (we support older styles for
+# backwards compatibility). Please don't change it unless you know what
+# you're doing.
+Vagrant.configure("2") do |config|
+ config.vm.box = "fedora/34-cloud-base"
+ config.vm.synced_folder "../..", "/root/selinux"
+
+ config.vm.provider "virtualbox" do |v|
+ v.memory = 4096
+ end
+ config.vm.provider "libvirt" do |v|
+ v.memory = 4096
+ end
+
+ config.vm.provision :shell, inline: $script
+end
diff --git a/scripts/ci/fedora-test-runner.sh b/scripts/ci/fedora-test-runner.sh
new file mode 100755
index 00000000..3ce2c3a6
--- /dev/null
+++ b/scripts/ci/fedora-test-runner.sh
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: MIT
+set -ev
+
+#
+# We expect this to be set in the environment, but if it's not, most selinux projects
+# just have the same name as upstream, so choose that.
+#
+export SELINUX_DIR="${SELINUX_DIR:-/root/selinux}"
+
+# CI Debug output if things go squirrely.
+getenforce
+id -Z
+nproc
+pwd
+
+# Turn off enforcing for the setup to prevent any weirdness from breaking
+# the CI.
+setenforce 0
+
+dnf clean all -y
+dnf install -y \
+ --allowerasing \
+ --skip-broken \
+ git \
+ audit-libs-devel \
+ bison \
+ bzip2-devel \
+ CUnit-devel \
+ diffutils \
+ flex \
+ gcc \
+ gettext \
+ glib2-devel \
+ make \
+ libcap-devel \
+ libcap-ng-devel \
+ pam-devel \
+ pcre2-devel \
+ xmlto \
+ python3-devel \
+ ruby-devel \
+ swig \
+ perl-Test \
+ perl-Test-Harness \
+ perl-Test-Simple \
+ selinux-policy-devel \
+ gcc \
+ libselinux-devel \
+ net-tools \
+ netlabel_tools \
+ iptables \
+ lksctp-tools-devel \
+ attr \
+ libbpf-devel \
+ keyutils-libs-devel \
+ kernel-devel \
+ quota \
+ xfsprogs-devel \
+ libuuid-devel \
+ e2fsprogs \
+ jfsutils \
+ dosfstools \
+ kernel-devel-"$(uname -r)" \
+ kernel-modules-"$(uname -r)"
+
+#
+# Move to selinux code and build
+#
+cd "$SELINUX_DIR"
+
+# Show HEAD commit for sanity checking
+git log --oneline -1
+
+#
+# Build and replace userspace components
+#
+make clean distclean
+make -j"$(nproc)" LIBDIR=/usr/lib64 SHLIBDIR=/lib64 install
+make -j"$(nproc)" LIBDIR=/usr/lib64 SHLIBDIR=/lib64 install-pywrap
+make -j"$(nproc)" LIBDIR=/usr/lib64 SHLIBDIR=/lib64 relabel
+
+#
+# Get the selinux testsuite, but don't clone it in selinux git directory, move to $HOME
+# first.
+#
+cd "$HOME"
+rm -rf selinux-testsuite
+git clone --depth=1 https://github.com/SELinuxProject/selinux-testsuite.git
+cd selinux-testsuite
+
+# The testsuite must be run in enforcing mode
+setenforce 1
+
+#
+# Run the test suite
+#
+make test
diff --git a/scripts/ci/travis-kvm-setup.sh b/scripts/ci/travis-kvm-setup.sh
new file mode 100755
index 00000000..997ef73f
--- /dev/null
+++ b/scripts/ci/travis-kvm-setup.sh
@@ -0,0 +1,130 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: MIT
+set -ev
+
+TEST_RUNNER="scripts/ci/fedora-test-runner.sh"
+
+#
+# Variables for controlling the Fedora Image version and download URLs.
+#
+if [ -z "$FEDORA_MAJOR" ] || [ -z "$FEDORA_MINOR" ]; then
+ echo "$0: FEDORA_MAJOR and FEDORA_MINOR must be set!" 1>&2
+ exit 1
+fi
+
+BASE_URL="https://download.fedoraproject.org/pub/fedora/linux/releases"
+IMAGE_BASE_NAME="Fedora-Cloud-Base-$FEDORA_MAJOR-$FEDORA_MINOR.x86_64"
+IMAGE_URL="$BASE_URL/$FEDORA_MAJOR/Cloud/x86_64/images/$IMAGE_BASE_NAME.raw.xz"
+CHECK_URL="$BASE_URL/$FEDORA_MAJOR/Cloud/x86_64/images/Fedora-Cloud-$FEDORA_MAJOR-$FEDORA_MINOR-x86_64-CHECKSUM"
+GPG_URL="https://getfedora.org/static/fedora.gpg"
+
+#
+# Travis gives us 7.5GB of RAM and two cores:
+# https://docs.travis-ci.com/user/reference/overview/
+#
+MEMORY=4096
+VCPUS="$(nproc)"
+
+# Install these here so other builds don't have to wait on these deps to download and install
+sudo apt-get update
+sudo apt-get install qemu-kvm libvirt-bin virtinst bridge-utils cpu-checker libguestfs-tools
+
+sudo usermod -a -G kvm,libvirt,libvirt-qemu "$USER"
+
+# Verify that KVM is working, useful if Travis ever changes anything.
+kvm-ok
+
+sudo systemctl enable libvirtd
+sudo systemctl start libvirtd
+
+# Set up a key so we can ssh into the VM
+ssh-keygen -N "" -f "$HOME/.ssh/id_rsa"
+
+#
+# Get the Fedora Cloud Image, It is a base image that small and ready to go, extract it and modify it with virt-sysprep
+# - https://alt.fedoraproject.org/en/verify.html
+cd "$HOME"
+wget "$IMAGE_URL"
+
+# Verify the image
+curl "$GPG_URL" | gpg --import
+wget "$CHECK_URL"
+gpg --verify-files ./*-CHECKSUM
+sha256sum --ignore-missing -c ./*-CHECKSUM
+
+# Extract the image
+unxz -T0 "$IMAGE_BASE_NAME.raw.xz"
+
+# Search is needed for $HOME so virt service can access the image file.
+chmod a+x "$HOME"
+
+#
+# Modify the virtual image to:
+# - Enable a login, we just use root
+# - Enable passwordless login
+# - Force a relabel to fix labels on ssh keys
+#
+sudo virt-sysprep -a "$IMAGE_BASE_NAME.raw" \
+ --root-password password:123456 \
+ --hostname fedoravm \
+ --append-line '/etc/ssh/sshd_config:PermitRootLogin yes' \
+ --append-line '/etc/ssh/sshd_config:PubkeyAuthentication yes' \
+ --mkdir /root/.ssh \
+ --upload "$HOME/.ssh/id_rsa.pub:/root/.ssh/authorized_keys" \
+ --chmod '0600:/root/.ssh/authorized_keys' \
+ --run-command 'chown root:root /root/.ssh/authorized_keys' \
+ --copy-in "$TRAVIS_BUILD_DIR:/root" \
+ --network \
+ --selinux-relabel
+
+#
+# Now we create a domain by using virt-install. This not only creates the domain, but runs the VM as well
+# It should be ready to go for ssh, once ssh starts.
+#
+sudo virt-install \
+ --name fedoravm \
+ --memory $MEMORY \
+ --vcpus $VCPUS \
+ --disk "$IMAGE_BASE_NAME.raw" \
+ --import --noautoconsole
+
+#
+# Here comes the tricky part, we have to figure out when the VM comes up AND we need the ip address for ssh. So we
+# can check the net-dhcp leases, for our host. We have to poll, and we will poll for up to 3 minutes in 6 second
+# intervals, so 30 poll attempts (0-29 inclusive).
+#
+# We have a full reboot + relabel, so first sleep gets us close
+#
+sleep 30
+for i in $(seq 0 29); do
+ echo "loop $i"
+ sleep 6s
+ # Get the leases, but tee it so it's easier to debug
+ sudo virsh net-dhcp-leases default | tee dhcp-leases.txt
+
+ # get our ipaddress
+ ipaddy="$(grep fedoravm dhcp-leases.txt | awk '{print $5}' | cut -d'/' -f 1-1)"
+ if [ -n "$ipaddy" ]; then
+ # found it, we're done looking, print it for debug logs
+ echo "ipaddy: $ipaddy"
+ break
+ fi
+ # it's empty/not found, loop back and try again.
+done
+
+# Did we find it? If not die.
+if [ -z "$ipaddy" ]; then
+ echo "ipaddy zero length, exiting with error 1"
+ exit 1
+fi
+
+#
+# Great we have a host running, ssh into it. We specify -o so
+# we don't get blocked on asking to add the servers key to
+# our known_hosts. Also, we need to forward the project directory
+# so forks know where to go.
+#
+project_dir="$(basename "$TRAVIS_BUILD_DIR")"
+ssh -tt -o StrictHostKeyChecking=no -o LogLevel=QUIET "root@$ipaddy" "SELINUX_DIR=/root/$project_dir /root/$project_dir/$TEST_RUNNER"
+
+exit 0
diff --git a/scripts/env_use_destdir b/scripts/env_use_destdir
index 251987c2..8274013e 100755
--- a/scripts/env_use_destdir
+++ b/scripts/env_use_destdir
@@ -22,10 +22,35 @@ if [ -z "${DESTDIR:-}" ] ; then
fi
export LD_LIBRARY_PATH="$DESTDIR/usr/lib:$DESTDIR/lib"
+if [ -n "${PREFIX:-}" ] ; then
+ LD_LIBRARY_PATH="$DESTDIR$PREFIX/lib:$LD_LIBRARY_PATH"
+fi
+if [ -n "${LIBDIR:-}" ] ; then
+ LD_LIBRARY_PATH="$DESTDIR$LIBDIR:$LD_LIBRARY_PATH"
+fi
+if [ -n "${SHLIBDIR:-}" ] ; then
+ LD_LIBRARY_PATH="$DESTDIR$SHLIBDIR:$LD_LIBRARY_PATH"
+fi
+
export PATH="$DESTDIR/usr/sbin:$DESTDIR/usr/bin:$DESTDIR/sbin:$DESTDIR/bin:$PATH"
+if [ -n "${PREFIX:-}" ] ; then
+ PATH="$DESTDIR$PREFIX/sbin:$DESTDIR$PREFIX/bin:$LD_LIBRARY_PATH"
+fi
+if [ -n "${BINDIR:-}" ] ; then
+ PATH="$DESTDIR$BINDIR:$PATH"
+fi
+if [ -n "${SBINDIR:-}" ] ; then
+ PATH="$DESTDIR$SBINDIR:$PATH"
+fi
-# shellcheck disable=SC2155
-export PYTHONPATH="$DESTDIR$(${PYTHON:-python3} -c "from distutils.sysconfig import *;print(get_python_lib(prefix='/usr'))")"
+NEW_PYTHONPATH="$DESTDIR$(${PYTHON:-python3} -c "from distutils.sysconfig import *;print(get_python_lib(plat_specific=1, prefix='/usr'))"):$DESTDIR$(${PYTHON:-python3} -c "from distutils.sysconfig import *;print(get_python_lib(prefix='/usr'))")"
+if [ -n "${PYTHONPATH:-}" ] ; then
+ # Prefix the PYTHONPATH with the new directories
+ export PYTHONPATH="$NEW_PYTHONPATH:$PYTHONPATH"
+else
+ # Define PYTHONPATH
+ export PYTHONPATH="$NEW_PYTHONPATH"
+fi
# shellcheck disable=SC2155
export RUBYLIB="$DESTDIR/$(${RUBY:-ruby} -e 'puts RbConfig::CONFIG["vendorlibdir"]'):$DESTDIR/$(${RUBY:-ruby} -e 'puts RbConfig::CONFIG["vendorarchdir"]')"
diff --git a/scripts/oss-fuzz.sh b/scripts/oss-fuzz.sh
new file mode 100755
index 00000000..72d275e8
--- /dev/null
+++ b/scripts/oss-fuzz.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+# The script is used to build the fuzz targets run on ClusterFuzz. It has to be
+# compatible with the "build.sh" script described at
+# https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh
+# More precisely, it should use environment variables like OUT, LIB_FUZZING_ENGINE
+# and so on (https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh-script-environment),
+# and the fuzz targets have to be linked with $CXX even though the project is written
+# in C: https://google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements
+
+# To make it easier to build the fuzz targets locally, the script can also work in "local"
+# mode. To run secilc-fuzzer against a test case (named, say, CRASH) triggering an issue
+# the following commands should be run
+#
+# $ ./scripts/oss-fuzz.sh
+# $ ./out/secilc-fuzzer CRASH
+
+# To run the fuzzer against the corpus OSS-Fuzz has accumulated so far it should be
+# downloaded, unpacked and passed to the fuzzer:
+#
+# $ wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
+# $ unzip -d CORPUS public.zip
+# $ ./out/secilc-fuzzer CORPUS/
+
+set -eux
+
+cd "$(dirname -- "$0")/.."
+
+export DESTDIR=${DESTDIR:-$(pwd)/DESTDIR}
+
+SANITIZER=${SANITIZER:-address}
+flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link"
+
+export CC=${CC:-clang}
+export CFLAGS="${CFLAGS:-$flags} -I$DESTDIR/usr/include -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
+
+export CXX=${CXX:-clang++}
+export CXXFLAGS=${CXXFLAGS:-$flags}
+
+export OUT=${OUT:-$(pwd)/out}
+mkdir -p "$OUT"
+
+export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer}
+
+rm -rf "$DESTDIR"
+make -C libsepol clean
+# LIBSO and LIBMAP shouldn't be expanded here because their values are unknown until Makefile
+# has been read by make
+# shellcheck disable=SC2016
+make -C libsepol V=1 LD_SONAME_FLAGS='-soname,$(LIBSO),--version-script=$(LIBMAP)' -j"$(nproc)" install
+
+## secilc fuzzer ##
+
+# CFLAGS, CXXFLAGS and LIB_FUZZING_ENGINE have to be split to be accepted by
+# the compiler/linker so they shouldn't be quoted
+# shellcheck disable=SC2086
+$CC $CFLAGS -c -o secilc-fuzzer.o libsepol/fuzz/secilc-fuzzer.c
+# shellcheck disable=SC2086
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o "$DESTDIR/usr/lib/libsepol.a" -o "$OUT/secilc-fuzzer"
+
+zip -r "$OUT/secilc-fuzzer_seed_corpus.zip" secilc/test
+
+## binary policy fuzzer ##
+
+# CFLAGS, CXXFLAGS and LIB_FUZZING_ENGINE have to be split to be accepted by
+# the compiler/linker so they shouldn't be quoted
+# shellcheck disable=SC2086
+$CC $CFLAGS -c -o binpolicy-fuzzer.o libsepol/fuzz/binpolicy-fuzzer.c
+# shellcheck disable=SC2086
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE binpolicy-fuzzer.o "$DESTDIR/usr/lib/libsepol.a" -o "$OUT/binpolicy-fuzzer"
+
+zip -j "$OUT/binpolicy-fuzzer_seed_corpus.zip" libsepol/fuzz/policy.bin
diff --git a/scripts/release b/scripts/release
index 07813749..0d222a8f 100755
--- a/scripts/release
+++ b/scripts/release
@@ -1,49 +1,63 @@
#!/bin/bash
-PWD=`pwd`
-WIKIDIR=../selinux.wiki
-
-if [ \! -d $WIKIDIR ]; then
- git clone git@github.com:SELinuxProject/selinux.wiki.git $WIKIDIR
-fi
+# Fail when a command fails
+set -e
-RELEASE_TAG=$(date '+%Y%m%d')
-DEST=releases/$RELEASE_TAG
-DIRS="libsepol libselinux libsemanage checkpolicy secilc policycoreutils mcstrans restorecond semodule-utils"
-DIRS_NEED_PREFIX="dbus gui python sandbox"
+# Ensure the script is running from the top level directory
+cd "$(dirname -- "$0")/.."
-git tag -a $RELEASE_TAG -m "Release $RELEASE_TAG"
+WIKIDIR=../selinux.wiki
-rm -rf $DEST
-mkdir -p $DEST
+if ! [ -d "$WIKIDIR" ]; then
+ git clone git@github.com:SELinuxProject/selinux.wiki.git "$WIKIDIR"
+fi
-for i in $DIRS; do
- cd $i
- VERS=`cat VERSION`
- ARCHIVE=$i-$VERS.tar.gz
- git tag $i-$VERS > /dev/null 2>&1
- git archive --format=tar --prefix=$i-$VERS/ $i-$VERS | gzip > ../$DEST/$ARCHIVE
- cd ..
-done
+RELEASE_TAG="$(cat VERSION)"
+DEST="releases/$RELEASE_TAG"
+DIRS=(
+ checkpolicy
+ libselinux
+ libsemanage
+ libsepol
+ mcstrans
+ policycoreutils
+ restorecond
+ secilc
+ selinux-dbus
+ selinux-gui
+ selinux-python
+ selinux-sandbox
+ semodule-utils
+)
+
+if git rev-parse "$RELEASE_TAG" &> /dev/null ; then
+ echo "Warning: tag $RELEASE_TAG already exists"
+else
+ git tag -a "$RELEASE_TAG" -m "Release $RELEASE_TAG"
+fi
-for i in $DIRS_NEED_PREFIX; do
- cd $i
- VERS=`cat VERSION`
- ARCHIVE=selinux-$i-$VERS.tar.gz
- git tag selinux-$i-$VERS > /dev/null 2>&1
- git archive --format=tar --prefix=selinux-$i-$VERS/ selinux-$i-$VERS | gzip > ../$DEST/$ARCHIVE
- cd ..
+rm -rf "$DEST"
+mkdir -p "$DEST"
+
+for COMPONENT in "${DIRS[@]}"; do
+ DIR="${COMPONENT#selinux-}"
+ VERS="$(cat "$DIR/VERSION")"
+ TAG="$COMPONENT-$VERS"
+ if git rev-parse "$TAG" &> /dev/null ; then
+ echo "Warning: tag $TAG already exists"
+ else
+ git tag "$TAG" > /dev/null
+ fi
+ git -C "$DIR" archive -o "../$DEST/$TAG.tar.gz" --prefix="$TAG/" "$TAG"
done
-cd $DEST
-
-git add .
+git archive -o "$DEST/selinux-${RELEASE_TAG}.tar.gz" --prefix="selinux-${RELEASE_TAG}/" "${RELEASE_TAG}"
echo "Add the following to the $WIKIDIR/Releases.md wiki page:"
echo ""
-echo "## Release $(date '+%Y-%m-%d')"
+echo "## Release $RELEASE_TAG"
echo ""
@@ -54,13 +68,24 @@ echo ""
echo "[short log](https://github.com/SELinuxProject/selinux/releases/download/$RELEASE_TAG/shortlog-$RELEASE_TAG.txt)"
echo ""
-for i in *.tar.gz; do
-
- echo -n "[$i](https://github.com/SELinuxProject/selinux/releases/download/$RELEASE_TAG/$i) "
- sha256sum $i | cut -d " " -f 1
+for COMPONENT in "${DIRS[@]}"; do
+ DIR="${COMPONENT#selinux-}"
+ VERS="$(cat "$DIR/VERSION")"
+ TAG="$COMPONENT-$VERS"
+ tarball="$TAG.tar.gz"
+ echo -n "[$tarball](https://github.com/SELinuxProject/selinux/releases/download/$RELEASE_TAG/$tarball) "
+ sha256sum "$DEST/$tarball" | cut -d " " -f 1
echo ""
done
+echo "### Source repository snapshot"
+
+echo ""
+
+echo -n "[selinux-${RELEASE_TAG}.tar.gz](https://github.com/SELinuxProject/selinux/releases/download/$RELEASE_TAG/selinux-${RELEASE_TAG}.tar.gz) "
+sha256sum "$DEST/selinux-${RELEASE_TAG}.tar.gz" | cut -d " " -f 1
+echo ""
+
echo "And then run:"
echo " cd $WIKIDIR"
echo " git commit -m \"Release $RELEASE_TAG\" -a -s"
diff --git a/scripts/run-flake8 b/scripts/run-flake8
index 24b1202f..67cccfe9 100755
--- a/scripts/run-flake8
+++ b/scripts/run-flake8
@@ -7,7 +7,7 @@ if [ $# -eq 0 ] ; then
# Run on both files ending with .py and Python files without extension
# shellcheck disable=SC2046
- set -- $( (find . -name '*.py' ; grep --exclude-dir=.git -l -e '^#!\s*/usr/bin/python' -e '^#!/usr/bin/env python' -r .) | sort -u )
+ set -- $( (find . -name '*.py' ; grep -l -e '^#!\s*/usr/bin/python' -e '^#!/usr/bin/env python' -r .) | grep -v '^\./\.git/' | sort -u )
echo "Analyzing $# Python scripts"
fi
diff --git a/scripts/run-scan-build b/scripts/run-scan-build
index ae5aa48b..ef07fefc 100755
--- a/scripts/run-scan-build
+++ b/scripts/run-scan-build
@@ -1,6 +1,10 @@
#!/bin/sh
# Run clang's static analyzer (scan-build) and record its output in output-scan-build/
+# Allow overriding binariy names, like clang-12
+export CC=${CC:-clang}
+SCAN_BUILD=${SCAN_BUILD:-scan-build}
+
# Ensure the current directory is where this script is
cd "$(dirname -- "$0")" || exit $?
@@ -20,14 +24,24 @@ export PATH="$DESTDIR/usr/sbin:$DESTDIR/usr/bin:$DESTDIR/sbin:$DESTDIR/bin:$PATH
export PYTHONPATH="$DESTDIR$(${PYTHON:-python3} -c "from distutils.sysconfig import *;print(get_python_lib(prefix='/usr'))")"
export RUBYLIB="$DESTDIR/$(${RUBY:-ruby} -e 'puts RbConfig::CONFIG["vendorlibdir"]'):$DESTDIR/$(${RUBY:-ruby} -e 'puts RbConfig::CONFIG["vendorarchdir"]')"
+if [ -f /etc/debian_version ]; then
+ export PYTHON_SETUP_ARGS='--install-layout=deb'
+fi
+
# Build and analyze
-make -C .. CC=clang clean distclean -j"$(nproc)"
-scan-build -analyze-headers -o "$OUTPUTDIR" make -C .. \
- CC=clang \
+make -C .. clean distclean -j"$(nproc)"
+$SCAN_BUILD -analyze-headers -o "$OUTPUTDIR" make -C .. \
DESTDIR="$DESTDIR" \
- CFLAGS="-O2 -Wall -D__CHECKER__ -I$DESTDIR/usr/include" \
+ CFLAGS="-O2 -Wall -Wextra -D_FORTIFY_SOURCE=2 -D__CHECKER__ -I$DESTDIR/usr/include" \
+ -j"$(nproc)" \
install install-pywrap install-rubywrap all test
+if [ $? -eq 0 ]; then
+ echo "++ Build succeeded"
+else
+ echo "++ Build failed"
+fi
+
# Reduce the verbosity in order to keep the message from scan-build saying
# "scan-build: Run 'scan-view /.../output-scan-build/2018-...' to examine bug reports.
set +x
diff --git a/secilc/.gitignore b/secilc/.gitignore
index 2d3ff405..d2a3daf1 100644
--- a/secilc/.gitignore
+++ b/secilc/.gitignore
@@ -2,8 +2,12 @@ secilc
secilc.8
secil2conf
secil2conf.8
+secil2tree
+secil2tree.8
policy.*
file_contexts
docs/html
docs/pdf
docs/tmp
+opt-actual.bin
+opt-actual.cil
diff --git a/secilc/Makefile b/secilc/Makefile
index 16640098..94be0481 100644
--- a/secilc/Makefile
+++ b/secilc/Makefile
@@ -10,27 +10,42 @@ SECIL2CONF = secil2conf
SECIL2CONF_SRCS := secil2conf.c
SECIL2CONF_OBJS := $(patsubst %.c,%.o,$(SECIL2CONF_SRCS))
+SECIL2TREE = secil2tree
+SECIL2TREE_SRCS := secil2tree.c
+SECIL2TREE_OBJS := $(patsubst %.c,%.o,$(SECIL2TREE_SRCS))
+
SECILC_MANPAGE = secilc.8
SECIL2CONF_MANPAGE = secil2conf.8
+SECIL2TREE_MANPAGE = secil2tree.8
XMLTO = xmlto
+DIFF = diff
+
+CHECKPOLICY = checkpolicy
+POL_VERS = $(shell $(CHECKPOLICY) -V | cut -f 1 -d ' ')
CFLAGS ?= -Wall -Wshadow -Wextra -Wundef -Wmissing-format-attribute -Wcast-align -Wstrict-prototypes -Wpointer-arith -Wunused
override CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
override LDLIBS += -lsepol
-all: $(SECILC) $(SECIL2CONF) man
+all: $(SECILC) $(SECIL2CONF) $(SECIL2TREE) man
$(SECILC): $(SECILC_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
test: $(SECILC)
./$(SECILC) test/policy.cil
+ ./$(SECILC) -c $(POL_VERS) -O -M 1 -f /dev/null -o opt-actual.bin test/opt-input.cil
+ $(CHECKPOLICY) -b -C -M -o opt-actual.cil opt-actual.bin >/dev/null
+ $(DIFF) test/opt-expected.cil opt-actual.cil
$(SECIL2CONF): $(SECIL2CONF_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE)
+$(SECIL2TREE): $(SECIL2TREE_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE) $(SECIL2TREE_MANPAGE)
$(SECILC_MANPAGE): $(SECILC_MANPAGE).xml
$(XMLTO) man $(SECILC_MANPAGE).xml
@@ -38,13 +53,18 @@ $(SECILC_MANPAGE): $(SECILC_MANPAGE).xml
$(SECIL2CONF_MANPAGE): $(SECIL2CONF_MANPAGE).xml
$(XMLTO) man $(SECIL2CONF_MANPAGE).xml
+$(SECIL2TREE_MANPAGE): $(SECIL2TREE_MANPAGE).xml
+ $(XMLTO) man $(SECIL2TREE_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 644 $(SECILC_MANPAGE) $(DESTDIR)$(MANDIR)/man8
install -m 644 $(SECIL2CONF_MANPAGE) $(DESTDIR)$(MANDIR)/man8
+ install -m 644 $(SECIL2TREE_MANPAGE) $(DESTDIR)$(MANDIR)/man8
doc:
$(MAKE) -C docs
@@ -54,10 +74,15 @@ clean:
rm -f $(SECILC_OBJS)
rm -f $(SECIL2CONF)
rm -f $(SECIL2CONF_OBJS)
+ rm -f $(SECIL2TREE)
+ rm -f $(SECIL2TREE_OBJS)
rm -f policy.*
rm -f file_contexts
rm -f $(SECILC_MANPAGE)
rm -f $(SECIL2CONF_MANPAGE)
+ rm -f $(SECIL2TREE_MANPAGE)
+ rm -f opt-actual.cil
+ rm -f opt-actual.bin
$(MAKE) -C docs clean
relabel:
diff --git a/secilc/VERSION b/secilc/VERSION
index 9f55b2cc..eb39e538 100644
--- a/secilc/VERSION
+++ b/secilc/VERSION
@@ -1 +1 @@
-3.0
+3.3
diff --git a/secilc/docs/Makefile b/secilc/docs/Makefile
index 6b07ce7f..a03ebeed 100644
--- a/secilc/docs/Makefile
+++ b/secilc/docs/Makefile
@@ -1,8 +1,8 @@
-CWD ?= $(shell pwd)
-HTMLDIR ?= $(CWD)/html
-PDFDIR ?= $(CWD)/pdf
-TMPDIR ?= $(CWD)/tmp
-TESTDIR ?= $(CWD)/../test
+CWD = $(shell pwd)
+HTMLDIR = $(CWD)/html
+PDFDIR = $(CWD)/pdf
+TMPDIR = $(CWD)/tmp
+TESTDIR = $(CWD)/../test
# All the markdown files that make up the guide:
FILE_LIST ?= cil_introduction.md \
@@ -28,6 +28,8 @@ FILE_LIST ?= cil_introduction.md \
PANDOC_FILE_LIST = $(addprefix $(TMPDIR)/,$(FILE_LIST))
+PANDOC_HIGHLIGHT_STYLE="theme.theme"
+
PDF_OUT=CIL_Reference_Guide.pdf
HTML_OUT=CIL_Reference_Guide.html
PANDOC = pandoc
@@ -51,16 +53,16 @@ $(TMPDIR)/%.md: %.md | $(TMPDIR)
$(TMPDIR)/policy.cil: $(TESTDIR)/policy.cil
cp -f $< $@
@# add a title for the TOC to policy.cil. This is needed to play nicely with the PDF conversion.
- $(SED) -i '1i Example Policy\n=========\n```' $@
+ $(SED) -i '1i Example Policy\n=========\n```secil' $@
echo '```' >> $@
-html: $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil
+html: $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil secil.xml
mkdir -p $(HTMLDIR)
- $(PANDOC) -t html $^ -o $(HTMLDIR)/$(HTML_OUT)
+ $(PANDOC) --highlight-style=$(PANDOC_HIGHLIGHT_STYLE) --syntax-definition=secil.xml --standalone --metadata title="CIL Reference Guide" -t html $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil -o $(HTMLDIR)/$(HTML_OUT)
-pdf: $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil
+pdf: $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil secil.xml
mkdir -p $(PDFDIR)
- $(PANDOC) --standalone --toc $^ -o $(PDFDIR)/$(PDF_OUT)
+ $(PANDOC) --highlight-style=$(PANDOC_HIGHLIGHT_STYLE) --syntax-definition=secil.xml --standalone --toc $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil -o $(PDFDIR)/$(PDF_OUT)
clean:
rm -rf $(HTMLDIR)
diff --git a/secilc/docs/README.md b/secilc/docs/README.md
index 3f1838e6..efab2a71 100644
--- a/secilc/docs/README.md
+++ b/secilc/docs/README.md
@@ -126,6 +126,7 @@ CIL (Common Intermediate Language)
* [typealiasactual](cil_type_statements.md#typealiasactual)
* [typeattribute](cil_type_statements.md#typeattribute)
* [typeattributeset](cil_type_statements.md#typeattributeset)
+ * [expandtypeattribute](cil_type_statements.md#expandtypeattribute)
* [typebounds](cil_type_statements.md#typebounds)
* [typechange](cil_type_statements.md#typechange)
* [typemember](cil_type_statements.md#typemember)
diff --git a/secilc/docs/cil_access_vector_rules.md b/secilc/docs/cil_access_vector_rules.md
index 9c03c710..f0ba4a90 100644
--- a/secilc/docs/cil_access_vector_rules.md
+++ b/secilc/docs/cil_access_vector_rules.md
@@ -8,7 +8,9 @@ Specifies the access allowed between a source and target type. Note that access
**Rule definition:**
+```secil
(allow source_id target_id|self classpermissionset_id ...)
+```
**Where:**
@@ -42,6 +44,7 @@ Specifies the access allowed between a source and target type. Note that access
These examples show a selection of possible permutations of [`allow`](cil_access_vector_rules.md#allow) rules:
+```secil
(class binder (impersonate call set_context_mgr transfer receive))
(class property_service (set))
(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
@@ -84,6 +87,7 @@ These examples show a selection of possible permutations of [`allow`](cil_access
(allow type_5 type_5 (property_service (set)))
(allow type_1 all_types (property_service (set)))
)
+```
auditallow
----------
@@ -92,7 +96,9 @@ Audit the access rights defined if there is a valid allow rule. Note: It does NO
**Rule definition:**
+```secil
(auditallow source_id target_id|self classpermissionset_id ...)
+```
**Where:**
@@ -126,10 +132,11 @@ Audit the access rights defined if there is a valid allow rule. Note: It does NO
This example will log an audit event whenever the corresponding [`allow`](cil_access_vector_rules.md#allow) rule grants access to the specified permissions:
+```secil
(allow release_app.process secmark_demo.browser_packet (packet (send recv append bind)))
(auditallow release_app.process secmark_demo.browser_packet (packet (send recv)))
-
+```
dontaudit
---------
@@ -140,7 +147,9 @@ Note that these rules can be omitted by the CIL compiler command line parameter
**Rule definition:**
+```secil
(dontaudit source_id target_id|self classpermissionset_id ...)
+```
**Where:**
@@ -174,7 +183,9 @@ Note that these rules can be omitted by the CIL compiler command line parameter
This example will not audit the denied access:
+```secil
(dontaudit zygote.process self (capability (fsetid)))
+```
neverallow
----------
@@ -185,7 +196,9 @@ Note that these rules can be over-ridden by the CIL compiler command line parame
**Rule definition:**
+```secil
(neverallow source_id target_id|self classpermissionset_id ...)
+```
**Where:**
@@ -219,6 +232,7 @@ Note that these rules can be over-ridden by the CIL compiler command line parame
This example will not compile as `type_3` is not allowed to be a source type for the [`allow`](cil_access_vector_rules.md#allow) rule:
+```secil
(class property_service (set))
(block av_rules
@@ -232,15 +246,20 @@ This example will not compile as `type_3` is not allowed to be a source type for
; This rule will fail compilation:
(allow type_3 self (property_service (set)))
)
+```
allowx
------
Specifies the access allowed between a source and target type using extended permissions. Unlike the [`allow`](cil_access_vector_rules.md#allow) statement, the statements [`validatetrans`](cil_constraint_statements.md#validatetrans), [`mlsvalidatetrans`](cil_constraint_statements.md#mlsvalidatetrans), [`constrain`](cil_constraint_statements.md#constrain), and [`mlsconstrain`](cil_constraint_statements.md#mlsconstrain) do not limit accesses granted by [`allowx`](cil_access_vector_rules.md#allowx).
+Note that for this to work there must *also* be valid equivalent [`allow`](cil_access_vector_rules.md#allow) rules present.
+
**Rule definition:**
+```secil
(allowx source_id target_id|self permissionx_id)
+```
**Where:**
@@ -274,11 +293,14 @@ Specifies the access allowed between a source and target type using extended per
These examples show a selection of possible permutations of [`allowx`](cil_access_vector_rules.md#allowx) rules:
+```secil
+ (allow type_1 type_2 (tcp_socket (ioctl))) ;; pre-requisite
(allowx type_1 type_2 (ioctl tcp_socket (range 0x2000 0x20FF)))
(permissionx ioctl_nodebug (ioctl udp_socket (not (range 0x4000 0x4010))))
+ (allow type_3 type_4 (udp_socket (ioctl))) ;; pre-requisite
(allowx type_3 type_4 ioctl_nodebug)
-
+```
auditallowx
@@ -286,9 +308,13 @@ auditallowx
Audit the access rights defined if there is a valid [`allowx`](cil_access_vector_rules.md#allowx) rule. It does NOT allow access, it only audits the event.
+Note that for this to work there must *also* be valid equivalent [`auditallow`](cil_access_vector_rules.md#auditallow) rules present.
+
**Rule definition:**
+```secil
(auditallowx source_id target_id|self permissionx_id)
+```
**Where:**
@@ -322,21 +348,27 @@ Audit the access rights defined if there is a valid [`allowx`](cil_access_vector
This example will log an audit event whenever the corresponding [`allowx`](cil_access_vector_rules.md#allowx) rule grants access to the specified extended permissions:
+```secil
(allowx type_1 type_2 (ioctl tcp_socket (range 0x2000 0x20FF)))
+ (auditallow type_1 type_2 (tcp_socket (ioctl))) ;; pre-requisite
(auditallowx type_1 type_2 (ioctl tcp_socket (range 0x2005 0x2010)))
-
+```
dontauditx
----------
Do not audit the access rights defined when access denied. This stops excessive log entries for known events.
+Note that for this to work there must *also* be at least one [`allowx`](cil_access_vector_rules.md#allowx) rule associated with the target type.
+
Note that these rules can be omitted by the CIL compiler command line parameter `-D` or `--disable-dontaudit` flags.
**Rule definition:**
+```secil
(dontauditx source_id target_id|self permissionx_id)
+```
**Where:**
@@ -370,8 +402,10 @@ Note that these rules can be omitted by the CIL compiler command line parameter
This example will not audit the denied access:
+```secil
+ (allowx type_1 type_2 (ioctl tcp_socket (0x1))) ;; pre-requisite, just some irrelevant random ioctl
(dontauditx type_1 type_2 (ioctl tcp_socket (range 0x3000 0x30FF)))
-
+```
neverallowx
----------
@@ -381,7 +415,9 @@ Note that these rules can be over-ridden by the CIL compiler command line parame
**Rule definition:**
+```secil
(neverallowx source_id target_id|self permissionx_id)
+```
**Where:**
@@ -392,7 +428,7 @@ Note that these rules can be over-ridden by the CIL compiler command line parame
</colgroup>
<tbody>
<tr class="odd">
-<td align="left"><p><code>neverallows</code></p></td>
+<td align="left"><p><code>neverallowx</code></p></td>
<td align="left"><p>The <code>neverallowx</code> keyword.</p></td>
</tr>
<tr class="even">
@@ -415,6 +451,7 @@ Note that these rules can be over-ridden by the CIL compiler command line parame
This example will not compile as `type_3` is not allowed to be a source type and ioctl range for the [`allowx`](cil_access_vector_rules.md#allowx) rule:
+```secil
(class property_service (ioctl))
(block av_rules
(type type_1)
@@ -426,3 +463,4 @@ This example will not compile as `type_3` is not allowed to be a source type and
; This rule will fail compilation:
(allowx type_3 self (ioctl property_service (0x20A0)))
)
+```
diff --git a/secilc/docs/cil_call_macro_statements.md b/secilc/docs/cil_call_macro_statements.md
index 17c46ed9..dcc6139f 100644
--- a/secilc/docs/cil_call_macro_statements.md
+++ b/secilc/docs/cil_call_macro_statements.md
@@ -8,9 +8,23 @@ Instantiate a [macro](#macro) within the current namespace. There may be zero or
Each parameter passed contains an argument to be resolved by the [macro](#macro), these can be named or anonymous but must conform to the parameter types defined in the [`macro`](cil_call_macro_statements.md#macro) statement.
+Macro rules are resolved by searching in the following order:
+
+- The macro namespace (If found this means that the name was declared in the macro and is now declared in the namespace of one of the parents of the call.)
+
+- The call arguments
+
+- The parent namespaces of the macro being called (if any) with the exception of the global namespace.
+
+- The parent namespaces of the call (if any) with the exception of the global namespace.
+
+- The global namespace
+
**Statement definition:**
+```secil
(call macro_id [(param ...)])
+```
**Where:**
@@ -44,22 +58,18 @@ macro
Declare a macro in the current namespace with its associated parameters. The macro identifier is used by the [`call`](cil_call_macro_statements.md#call) statement to instantiate the macro and resolve any parameters. The call statement may be within the body of a macro.
-Note that when resolving macros the callers namespace is not checked, only the following places:
-
-- Items defined inside the macro
-
-- Items passed into the macro as arguments
-
-- Items defined in the same namespace of the macro
+[`tunable`](cil_conditional_statements.md#tunable), [`in`](cil_container_statements.md#in), [`block`](cil_container_statements.md#block), [`blockinherit`](cil_container_statements.md#blockinherit), [`blockabstract`](cil_container_statements.md#blockabstract), and other [`macro`](cil_call_macro_statements.md#macro) statements are not allowed in [`macro`](cil_call_macro_statements.md#macro) blocks.
-- Items defined in the global namespace
+Duplicate [`macro`](cil_call_macro_statements.md#macro) declarations in the same namespace will normally cause an error, but inheriting a macro into a namespace (with [`blockinherit`](cil_container_statements.md#blockinherit)) that already has a macro with the same name will only result in a warning message and not cause an error. This behavior allows inherited macros to be overridden with local ones.
**Statement definition:**
+```secil
(macro macro_id ([(param_type param_id) ...])
cil_statements
...
)
+```
**Where:**
@@ -80,7 +90,7 @@ Note that when resolving macros the callers namespace is not checked, only the f
<tr class="odd">
<td align="left"><p><code>param_type</code></p></td>
<td align="left"><p>Zero or more parameters that are passed to the macro. The <code>param_type</code> is a keyword used to determine the declaration type (e.g. <code>type</code>, <code>class</code>, <code>categoryset</code>).</p>
-<p>The list of valid <code>param_type</code> entries are: <code>type</code>, <code>typealias</code>, <code>role</code>, <code>user</code>, <code>sensitivity</code>, <code>sensitivityalias</code>, <code>category</code>, <code>categoryalias</code>, <code>categoryset</code> (named or anonymous), <code>level</code> (named or anonymous), <code>levelrange</code> (named or anonymous), <code>class</code>, <code>classpermission</code> (named or anonymous), <code>ipaddr</code> (named or anonymous), <code>block</code>, <code>name</code> (a string), <code>classmap</code></p></td>
+<p>The list of valid <code>param_type</code> entries are: <code>type</code>, <code>typealias</code>, <code>role</code>, <code>user</code>, <code>sensitivity</code>, <code>sensitivityalias</code>, <code>category</code>, <code>categoryalias</code>, <code>categoryset</code> (named or anonymous), <code>level</code> (named or anonymous), <code>levelrange</code> (named or anonymous), <code>class</code>, <code>classpermission</code> (named or anonymous), <code>ipaddr</code> (named or anonymous), <code>name</code> (a string), <code>classmap</code></p></td>
</tr>
<tr class="even">
<td align="left"><p><code>param_id</code></p></td>
@@ -97,6 +107,7 @@ Note that when resolving macros the callers namespace is not checked, only the f
This example will instantiate the `binder_call` macro in the calling namespace (`my_domain`) and replace `ARG1` with `appdomain` and `ARG2` with `binderservicedomain`:
+```secil
(block my_domain
(call binder_call (appdomain binderservicedomain))
)
@@ -106,9 +117,11 @@ This example will instantiate the `binder_call` macro in the calling namespace (
(allow ARG2 ARG1 (binder (transfer)))
(allow ARG1 ARG2 (fd (use)))
)
+```
This example does not pass any parameters to the macro but adds a [`type`](cil_type_statements.md#type) identifier to the current namespace:
+```secil
(block unconfined
(call add_type)
....
@@ -117,14 +130,17 @@ This example does not pass any parameters to the macro but adds a [`type`](cil_t
(type exec)
)
)
+```
This example passes an anonymous and named IP address to the macro:
+```secil
(ipaddr netmask_1 255.255.255.0)
- (context netlabel_1 (system.user object_r unconfined.object low_low)
+ (context netlabel_1 (system.user object_r unconfined.object low_low))
(call build_nodecon ((192.168.1.64) netmask_1))
(macro build_nodecon ((ipaddr ARG1) (ipaddr ARG2))
(nodecon ARG1 ARG2 netlabel_1)
)
+```
diff --git a/secilc/docs/cil_class_and_permission_statements.md b/secilc/docs/cil_class_and_permission_statements.md
index 308c86d6..368e3a4d 100644
--- a/secilc/docs/cil_class_and_permission_statements.md
+++ b/secilc/docs/cil_class_and_permission_statements.md
@@ -8,7 +8,9 @@ Declares a common identifier in the current namespace with a set of common permi
**Statement definition:**
+```secil
(common common_id (permission_id ...))
+```
**Where:**
@@ -37,7 +39,9 @@ Declares a common identifier in the current namespace with a set of common permi
This common statement will associate the [`common`](cil_class_and_permission_statements.md#common) identifier '`file`' with the list of permissions:
+```secil
(common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
+```
classcommon
-----------
@@ -46,7 +50,9 @@ Associate a [`class`](cil_class_and_permission_statements.md#class) identifier t
**Statement definition:**
+```secil
(classcommon class_id common_id)
+```
**Where:**
@@ -75,9 +81,11 @@ Associate a [`class`](cil_class_and_permission_statements.md#class) identifier t
This associates the `dir` class with the list of permissions declared by the `file common` identifier:
+```secil
(common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
(classcommon dir file)
+```
class
-----
@@ -86,7 +94,9 @@ Declares a class and zero or more permissions in the current namespace.
**Statement definition:**
+```secil
(class class_id (permission_id ...))
+```
**Where:**
@@ -115,29 +125,39 @@ Declares a class and zero or more permissions in the current namespace.
This example defines a set of permissions for the `binder` class identifier:
+```secil
(class binder (impersonate call set_context_mgr transfer receive))
+```
This example defines a common set of permissions to be used by the `sem` class, the `(class sem ())` does not define any other permissions (i.e. an empty list):
+```secil
(common ipc (create destroy getattr setattr read write associate unix_read unix_write))
(classcommon sem ipc)
(class sem ())
+```
and will produce the following set of permissions for the `sem` class identifier of:
+```secil
(class sem (create destroy getattr setattr read write associate unix_read unix_write))
+```
This example, with the following combination of the [`common`](cil_class_and_permission_statements.md#common), [`classcommon`](cil_class_and_permission_statements.md#classcommon) and [`class`](cil_class_and_permission_statements.md#class) statements:
+```secil
(common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
(classcommon dir file)
(class dir (add_name remove_name reparent search rmdir open audit_access execmod))
+```
will produce a set of permissions for the `dir` class identifier of:
+```secil
(class dir (add_name remove_name reparent search rmdir open audit_access execmod ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
+```
classorder
----------
@@ -146,7 +166,9 @@ Defines the order of [class](#class)'s. This is a mandatory statement. Multiple
**Statement definition:**
+```secil
(classorder (class_id ...))
+```
**Where:**
@@ -171,11 +193,13 @@ Defines the order of [class](#class)'s. This is a mandatory statement. Multiple
This will produce an ordered list of "`file dir process`"
+```secil
(class process)
(class file)
(class dir)
(classorder (file dir))
(classorder (dir process))
+```
**Unordered Classorder Statement:**
@@ -185,6 +209,7 @@ If users do not have knowledge of the existing [`classorder`](#classorder), the
This will produce an unordered list of "`file dir foo a bar baz`"
+```secil
(class file)
(class dir)
(class foo)
@@ -195,6 +220,7 @@ This will produce an unordered list of "`file dir foo a bar baz`"
(classorder (dir foo))
(classorder (unordered a))
(classorder (unordered bar foo baz))
+```
classpermission
---------------
@@ -203,7 +229,9 @@ Declares a class permission set identifier in the current namespace that can be
**Statement definition:**
+```secil
(classpermission classpermissionset_id)
+```
**Where:**
@@ -235,7 +263,9 @@ Defines a class permission set identifier in the current namespace that associat
**Statement definition:**
+```secil
(classpermissionset classpermissionset_id (class_id (permission_id | expr ...)))
+```
**Where:**
@@ -278,6 +308,7 @@ Defines a class permission set identifier in the current namespace that associat
These class permission set statements will resolve to the permission sets shown in the kernel policy language [`allow`](cil_access_vector_rules.md#allow) rules:
+```secil
(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
(type test_1)
@@ -322,6 +353,7 @@ These class permission set statements will resolve to the permission sets shown
(classpermissionset zygote_all_perms (zygote (all)))
(allow unconfined.process test_5 zygote_all_perms)
;; allow unconfined.process test_5 : zygote { specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo } ;
+```
classmap
--------
@@ -346,7 +378,9 @@ Declares a class map identifier in the current namespace and one or more class m
**Statement definition:**
+```secil
(classmap classmap_id (classmapping_id ...))
+```
**Where:**
@@ -382,7 +416,9 @@ Define sets of [`classpermissionset`](cil_class_and_permission_statements.md#cla
**Statement definition:**
+```secil
(classmapping classmap_id classmapping_id classpermissionset_id)
+```
**Where:**
@@ -415,6 +451,7 @@ Define sets of [`classpermissionset`](cil_class_and_permission_statements.md#cla
These class mapping statements will resolve to the permission sets shown in the kernel policy language [`allow`](cil_access_vector_rules.md#allow) rules:
+```secil
(class binder (impersonate call set_context_mgr transfer receive))
(class property_service (set))
(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
@@ -454,6 +491,7 @@ These class mapping statements will resolve to the permission sets shown in the
;; allow map_example.type_3 map_example.type_3 : binder { impersonate call set_context_mgr } ;
;; allow map_example.type_3 map_example.type_3 : zygote { specifyrlimits specifycapabilities specifyinvokewith specifyseinfo } ;
+```
permissionx
-----------
@@ -462,7 +500,9 @@ Defines a named extended permission, which can be used in the [`allowx`](cil_acc
**Statement definition:**
+```secil
(permissionx permissionx_id (kind class_id (permission ... | expr ...)))
+```
**Where:**
@@ -517,6 +557,8 @@ Defines a named extended permission, which can be used in the [`allowx`](cil_acc
**Examples:**
+```secil
(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)))))
+```
diff --git a/secilc/docs/cil_conditional_statements.md b/secilc/docs/cil_conditional_statements.md
index f30d2cce..9afd4153 100644
--- a/secilc/docs/cil_conditional_statements.md
+++ b/secilc/docs/cil_conditional_statements.md
@@ -6,9 +6,13 @@ boolean
Declares a run time boolean as true or false in the current namespace. The [`booleanif`](cil_conditional_statements.md#booleanif) statement contains the CIL code that will be in the binary policy file.
+[`boolean`](cil_conditional_statements.md#boolean) are not allowed in [`booleanif`](cil_conditional_statements.md#booleanif) blocks.
+
**Statement definition:**
+```secil
(boolean boolean_id true|false)
+```
**Where:**
@@ -46,7 +50,8 @@ Contains the run time conditional statements that are instantiated in the binary
**Statement definition:**
- (booleanif boolean_id | expr ...)
+```secil
+ (booleanif boolean_id | expr ...
(true
cil_statements
...)
@@ -54,6 +59,7 @@ Contains the run time conditional statements that are instantiated in the binary
cil_statements
...)
)
+```
**Where:**
@@ -74,12 +80,12 @@ Contains the run time conditional statements that are instantiated in the binary
<tr class="odd">
<td align="left"><p><code>expr</code></p></td>
<td align="left"><p>Zero or more <code>expr</code>'s, the valid operators and syntax are:</p>
-<p><code> (and (boolean_id boolean_id))</code></p>
-<p><code> (or (boolean_id boolean_id))</code></p>
-<p><code> (xor (boolean_id boolean_id))</code></p>
-<p><code> (eq (boolean_id boolean_id))</code></p>
-<p><code> (neq (boolean_id boolean_id))</code></p>
-<p><code> (not (boolean_id))</code></p></td>
+<p><code> (and boolean_id boolean_id)</code></p>
+<p><code> (or boolean_id boolean_id)</code></p>
+<p><code> (xor boolean_id boolean_id)</code></p>
+<p><code> (eq boolean_id boolean_id)</code></p>
+<p><code> (neq boolean_id boolean_id)</code></p>
+<p><code> (not boolean_id)</code></p></td>
</tr>
<tr class="even">
<td align="left"><p><code>true</code></p></td>
@@ -96,6 +102,7 @@ Contains the run time conditional statements that are instantiated in the binary
The second example also shows the kernel policy language equivalent:
+```secil
(boolean disableAudio false)
(booleanif disableAudio
@@ -112,6 +119,7 @@ The second example also shows the kernel policy language equivalent:
(allow process mediaserver.audio_capture_device (chr_file_set (rw_file_perms)))
)
)
+```
tunable
-------
@@ -120,9 +128,13 @@ Tunables are similar to booleans, however they are used to manage areas of CIL s
Note that tunables can be treated as booleans by the CIL compiler command line parameter `-P` or `--preserve-tunables` flags.
+Since [`tunableif`](cil_conditional_statements.md#tunableif) statements are resolved first, [`tunable`](cil_conditional_statements.md#tunable) statements are not allowed in [`in`](cil_container_statements.md#in), [`macro`](cil_call_macro_statements.md#macro), [`optional`](cil_container_statements.md#optional), and [`booleanif`](cil_conditional_statements.md#booleanif) blocks. To simplify processing, they are also not allowed in [`tunableif`](cil_conditional_statements.md#tunableif) blocks.
+
**Statement definition:**
+```secil
(tunable tunable_id true|false)
+```
**Where:**
@@ -156,9 +168,12 @@ tunableif
Compile time conditional statement that may or may not add CIL statements to be compiled.
+If tunables are being treated as booleans (by using the CIL compiler command line parameter `-P` or `--preserve-tunables` flag), then only the statements allowed in a [`booleanif`](cil_conditional_statements.md#booleanif) block are allowed in a [`tunableif`](cil_conditional_statements.md#tunableif) block. Otherwise, [`tunable`](cil_conditional_statements.md#tunable) statements are not allowed in a [`tunableif`](cil_conditional_statements.md#tunableif) block.
+
**Statement definition:**
- (tunableif tunable_id | expr ...)
+```secil
+ (tunableif tunable_id | expr ...
(true
cil_statements
...)
@@ -166,6 +181,7 @@ Compile time conditional statement that may or may not add CIL statements to be
cil_statements
...)
)
+```
**Where:**
@@ -186,12 +202,12 @@ Compile time conditional statement that may or may not add CIL statements to be
<tr class="odd">
<td align="left"><p><code>expr</code></p></td>
<td align="left"><p>Zero or more <code>expr</code>'s, the valid operators and syntax are:</p>
-<p><code> (and (tunable_id tunable_id))</code></p>
-<p><code> (or (tunable_id tunable_id))</code></p>
-<p><code> (xor (tunable_id tunable_id))</code></p>
-<p><code> (eq (tunable_id tunable_id))</code></p>
-<p><code> (neq (tunable_id tunable_id))</code></p>
-<p><code> (not (tunable_id))</code></p></td>
+<p><code> (and tunable_id tunable_id)</code></p>
+<p><code> (or tunable_id tunable_id)</code></p>
+<p><code> (xor tunable_id tunable_id)</code></p>
+<p><code> (eq tunable_id tunable_id)</code></p>
+<p><code> (neq tunable_id tunable_id)</code></p>
+<p><code> (not tunable_id)</code></p></td>
</tr>
<tr class="even">
<td align="left"><p><code>true</code></p></td>
@@ -208,6 +224,7 @@ Compile time conditional statement that may or may not add CIL statements to be
This example will not add the range transition rule to the binary policy:
+```secil
(tunable range_trans_rule false)
(block init
@@ -220,3 +237,4 @@ This example will not add the range transition rule to the binary policy:
)
) ; End tunableif
) ; End block
+```
diff --git a/secilc/docs/cil_constraint_statements.md b/secilc/docs/cil_constraint_statements.md
index df03ae6b..358927d6 100644
--- a/secilc/docs/cil_constraint_statements.md
+++ b/secilc/docs/cil_constraint_statements.md
@@ -8,7 +8,9 @@ Enable constraints to be placed on the specified permissions of the object class
**Statement definition:**
+```secil
(constrain classpermissionset_id ... expression | expr ...)
+```
**Where:**
@@ -32,12 +34,12 @@ Enable constraints to be placed on the specified permissions of the object class
<p><code> (op u1 u2)</code></p>
<p><code> (role_op r1 r2)</code></p>
<p><code> (op t1 t2)</code></p>
-<p><code> (op u1 user_id)</code></p>
-<p><code> (op u2 user_id)</code></p>
-<p><code> (op r1 role_id)</code></p>
-<p><code> (op r2 role_id)</code></p>
-<p><code> (op t1 type_id)</code></p>
-<p><code> (op t2 type_id)</code></p>
+<p><code> (op u1 user_id | (user_id ...))</code></p>
+<p><code> (op u2 user_id | (user_id ...))</code></p>
+<p><code> (op r1 role_id | (role_id ...))</code></p>
+<p><code> (op r2 role_id | (role_id ...))</code></p>
+<p><code> (op t1 type_id | (type_id ...))</code></p>
+<p><code> (op t2 type_id | (type_id ...))</code></p>
<p>where:</p>
<p><code> u1, r1, t1 = Source context: user, role or type</code></p>
<p><code> u2, r2, t2 = Target context: user, role or type</code></p>
@@ -62,6 +64,7 @@ Enable constraints to be placed on the specified permissions of the object class
Two constrain statements are shown with their equivalent kernel policy language statements:
+```secil
;; constrain { file } { write }
;; (( t1 == unconfined.process ) and ( t2 == unconfined.object ) or ( r1 eq r2 ));
(constrain (file (write))
@@ -87,6 +90,7 @@ Two constrain statements are shown with their equivalent kernel policy language
)
)
)
+```
validatetrans
-------------
@@ -95,7 +99,9 @@ The [`validatetrans`](cil_constraint_statements.md#validatetrans) statement is o
**Statement definition:**
+```secil
(validatetrans class_id expression | expr ...)
+```
**Where:**
@@ -153,9 +159,11 @@ The [`validatetrans`](cil_constraint_statements.md#validatetrans) statement is o
A validate transition statement with the equivalent kernel policy language statement:
+```secil
; validatetrans { file } ( t1 == unconfined.process );
(validatetrans file (eq t1 unconfined.process))
+```
mlsconstrain
------------
@@ -164,7 +172,9 @@ Enable MLS constraints to be placed on the specified permissions of the object c
**Statement definition:**
+```secil
(mlsconstrain classpermissionset_id ... expression | expr ...)
+```
**Where:**
@@ -224,6 +234,7 @@ Enable MLS constraints to be placed on the specified permissions of the object c
An MLS constrain statement with the equivalent kernel policy language statement:
+```secil
;; mlsconstrain { file } { open }
;; (( l1 eq l2 ) and ( u1 == u2 ) or ( r1 != r2 ));
@@ -236,6 +247,7 @@ An MLS constrain statement with the equivalent kernel policy language statement:
(neq r1 r2)
)
)
+```
mlsvalidatetrans
----------------
@@ -244,7 +256,9 @@ The [`mlsvalidatetrans`](cil_constraint_statements.md#mlsvalidatetrans) statemen
**Statement definition:**
+```secil
(mlsvalidatetrans class_id expression | expr ...)
+```
**Where:**
@@ -308,6 +322,8 @@ The [`mlsvalidatetrans`](cil_constraint_statements.md#mlsvalidatetrans) statemen
An MLS validate transition statement with the equivalent kernel policy language statement:
+```secil
;; mlsvalidatetrans { file } ( l1 domby h2 );
(mlsvalidatetrans file (domby l1 h2))
+```
diff --git a/secilc/docs/cil_container_statements.md b/secilc/docs/cil_container_statements.md
index a570cb23..f70160cb 100644
--- a/secilc/docs/cil_container_statements.md
+++ b/secilc/docs/cil_container_statements.md
@@ -4,14 +4,22 @@ Container Statements
block
-----
-Start a new namespace where any CIL statement is valid.
+Start a new namespace.
+
+Not allowed in [`macro`](cil_call_macro_statements.md#macro) and [`optional`](cil_container_statements.md#optional) blocks.
+
+[`sensitivity`](cil_mls_labeling_statements.md#sensitivity) and [`category`](cil_mls_labeling_statements.md#category) statements are not allowed in [`block`](cil_container_statements.md#block) blocks.
+
+Duplicate declarations of a [`block`](cil_container_statements.md#block) in the same namespace will normally cause an error, but inheriting a block into a namespace (with [`blockinherit`](cil_container_statements.md#blockinherit)) that already has a block with the same name will only result in a warning message and not cause an error. The policy from both blocks will end up in the binary policy. This behavior was used in the past to allow a block to be declared so that an [`in-statement`](cil_container_statements.md#in) could be used on it, but now an [`in-statement`](cil_container_statements.md#in) can be specified to occur after inheritance, so this behavior is not necessary (but is still allowed).
**Statement definition:**
+```secil
(block block_id
cil_statement
...
)
+```
**Where:**
@@ -45,13 +53,17 @@ blockabstract
Declares the namespace as a 'template' and does not generate code until instantiated by another namespace that has a [`blockinherit`](cil_container_statements.md#blockinherit) statement.
+Not allowed in [`macro`](cil_call_macro_statements.md#macro) and [`optional`](cil_container_statements.md#optional) blocks.
+
**Statement definition:**
+```secil
(block block_id
(blockabstract template_id)
cil_statement
...
)
+```
**Where:**
@@ -93,13 +105,25 @@ blockinherit
Used to add common policy rules to the current namespace via a template that has been defined with the [`blockabstract`](cil_container_statements.md#blockabstract) statement. All [`blockinherit`](cil_container_statements.md#blockinherit) statements are resolved first and then the contents of the block are copied. This is so that inherited blocks will not be inherited. For a concrete example, please see the examples section.
+Inherited rules are resolved by searching namespaces in the following order:
+
+- The parent namespaces (if any) where the [`blockinherit`](cil_container_statements.md#blockinherit) rule is located with the exception of the global namespace.
+
+- The parent namespaces of the block being inherited (but not that block's namespace) with the exception of the global namespace.
+
+- The global namespace.
+
+Not allowed in [`macro`](cil_call_macro_statements.md#macro) blocks.
+
**Statement definition:**
+```secil
(block block_id
(blockinherit template_id)
cil_statement
...
)
+```
**Where:**
@@ -136,6 +160,7 @@ Used to add common policy rules to the current namespace via a template that has
This example contains a template `client_server` that is instantiated in two blocks (`netserver_app` and `netclient_app`):
+```secil
; This is the template block:
(block client_server
(blockabstract client_server)
@@ -187,26 +212,25 @@ This example contains a template `client_server` that is instantiated in two blo
(block ab
(blockinherit b)
(blockinherit a))
+```
optional
--------
-Declare an [`optional`](cil_container_statements.md#optional) namespace. All CIL statements in the optional block must be satisfied before instantiation in the binary policy. [`tunableif`](cil_conditional_statements.md#tunableif) and [`macro`](cil_call_macro_statements.md#macro) statements are not allowed in optional containers. The same restrictions apply to CIL policy statements within [`optional`](cil_container_statements.md#optional)'s that apply to kernel policy statements, i.e. only the policy statements shown in the following table are valid:
+Declare an [`optional`](cil_container_statements.md#optional) namespace. All CIL statements in the optional block must be satisfied before instantiation in the binary policy.
+
+Not allowed in [`booleanif`](cil_conditional_statements.md#booleanif) blocks.
-| | | | |
-| ------------------- | -------------- | ------------------ | ------------------ |
-| [`allow`](cil_access_vector_rules.md#allow) | [`allowx`](cil_access_vector_rules.md#allowx) | [`auditallow`](cil_access_vector_rules.md#auditallow) | [`auditallowx`](cil_access_vector_rules.md#auditallowx) |
-| [`booleanif`](cil_conditional_statements.md#booleanif) | [`dontaudit`](cil_access_vector_rules.md#dontaudit) | [`dontauditx`](cil_access_vector_rules.md#dontauditx) | [`typepermissive`](cil_type_statements.md#typepermissive) |
-| [`rangetransition`](cil_mls_labeling_statements.md#rangetransition) | [`role`](cil_role_statements.md#role) | [`roleallow`](cil_role_statements.md#roleallow) | [`roleattribute`](cil_role_statements.md#roleattribute) |
-| [`roletransition`](cil_role_statements.md#roletransition) | [`type`](cil_type_statements.md#type) | [`typealias`](cil_type_statements.md#typealias) | [`typeattribute`](cil_type_statements.md#typeattribute) |
-| [`typechange`](cil_type_statements.md#typechange) | [`typemember`](cil_type_statements.md#typemember) | [`typetransition`](cil_type_statements.md#typetransition) | |
+[`tunable`](cil_conditional_statements.md#tunable), [`in`](cil_container_statements.md#in), [`block`](cil_container_statements.md#block), [`blockabstract`](cil_container_statements.md#blockabstract), and [`macro`](cil_call_macro_statements.md#macro) statements are not allowed in [`optional`](cil_container_statements.md#optional) blocks.
**Statement definition:**
+```secil
(optional optional_id
cil_statement
...
)
+```
**Where:**
@@ -235,6 +259,7 @@ Declare an [`optional`](cil_container_statements.md#optional) namespace. All CIL
This example will instantiate the optional block `ext_gateway.move_file` into policy providing all optional CIL statements can be resolved:
+```secil
(block ext_gateway
......
(optional move_file
@@ -250,18 +275,25 @@ This example will instantiate the optional block `ext_gateway.move_file` into po
.....
) ; End block
+```
in
--
-Allows the insertion of CIL statements into a named container ([`block`](cil_container_statements.md#block), [`optional`](cil_container_statements.md#optional) or [`macro`](cil_call_macro_statements.md#macro)). This statement is not allowed in [`booleanif`](cil_conditional_statements.md#booleanif) or [`tunableif`](cil_conditional_statements.md#tunableif) statements.
+Allows the insertion of CIL statements into a named container ([`block`](cil_container_statements.md#block), [`optional`](cil_container_statements.md#optional) or [`macro`](cil_call_macro_statements.md#macro)). This insertion can be specified to occur either before or after block inheritance has been resolved.
+
+Not allowed in [`macro`](cil_call_macro_statements.md#macro), [`booleanif`](cil_conditional_statements.md#booleanif), and other [`in`](cil_container_statements.md#in) blocks.
+
+[`tunable`](cil_conditional_statements.md#tunable) and [`in`](cil_container_statements.md#in) statements are not allowed in [`in`](cil_container_statements.md#in) blocks.
**Statement definition:**
- (in container_id
+```secil
+ (in [before|after] container_id
cil_statement
...
)
+```
**Where:**
@@ -276,10 +308,14 @@ Allows the insertion of CIL statements into a named container ([`block`](cil_con
<td align="left"><p>The <code>in</code> keyword.</p></td>
</tr>
<tr class="even">
+<td align="left"><p><code>before|after</code></p></td>
+<td align="left"><p>An optional value that specifies whether to process the [`in`](cil_container_statements.md#in) <code>before</code> or <code>after</code> block inheritance. If no value is specified, then the [`in`](cil_container_statements.md#in) will be processed before block inheritance.</p></td>
+</tr>
+<tr class="odd">
<td align="left"><p><code>container_id</code></p></td>
<td align="left"><p>A valid <code>block</code>, <code>optional</code> or <code>macro</code> namespace identifier.</p></td>
</tr>
-<tr class="odd">
+<tr class="even">
<td align="left"><p><code>cil_statement</code></p></td>
<td align="left"><p>Zero or more valid CIL statements.</p></td>
</tr>
@@ -290,7 +326,9 @@ Allows the insertion of CIL statements into a named container ([`block`](cil_con
This will add rules to the container named `system_server`:
+```secil
(in system_server
(dontaudit process secmark_demo.dns_packet (packet (send recv)))
(allow process secmark_demo.dns_packet (packet (send recv)))
)
+```
diff --git a/secilc/docs/cil_context_statement.md b/secilc/docs/cil_context_statement.md
index 60812751..caa7ff6b 100644
--- a/secilc/docs/cil_context_statement.md
+++ b/secilc/docs/cil_context_statement.md
@@ -16,7 +16,9 @@ Declare an SELinux security context identifier for labeling. The range (or curre
**Statement definition:**
+```secil
(context context_id (user_id role_id type_id levelrange_id)))
+```
**Where:**
@@ -57,21 +59,29 @@ Declare an SELinux security context identifier for labeling. The range (or curre
This example uses a named context definition:
+```secil
(context runas_exec_context (u object_r exec low_low))
(filecon "/system/bin/run-as" file runas_exec_context)
+```
to resolve/build a `file_contexts` entry of (assuming MLS enabled policy):
+```
/system/bin/run-as -- u:object_r:runas.exec:s0-s0
+```
This example uses an anonymous context where the previously declared `user role type levelrange` identifiers are used to specify two [`portcon`](cil_network_labeling_statements.md#portcon) statements:
+```secil
(portcon udp 1024 (test.user object_r test.process ((s0) (s1))))
(portcon tcp 1024 (test.user object_r test.process (system_low system_high)))
+```
This example uses an anonymous context for the first and named context for the second in a [`netifcon`](cil_network_labeling_statements.md#netifcon) statement:
+```secil
(context netif_context (test.user object_r test.process ((s0 (c0)) (s1 (c0)))))
(netifcon eth04 (test.user object_r test.process ((s0 (c0)) (s1 (c0)))) netif_context)
+```
diff --git a/secilc/docs/cil_default_object_statements.md b/secilc/docs/cil_default_object_statements.md
index 80ccabe7..be7facaf 100644
--- a/secilc/docs/cil_default_object_statements.md
+++ b/secilc/docs/cil_default_object_statements.md
@@ -10,7 +10,9 @@ Allows the default user to be taken from the source or target context when compu
**Statement definition:**
+```secil
(defaultuser class_id default)
+```
**Where:**
@@ -39,6 +41,7 @@ Allows the default user to be taken from the source or target context when compu
When creating new `binder`, `property_service`, `zygote` or `memprotect` objects the [`user`](cil_user_statements.md#user) component of the new security context will be taken from the `source` context:
+```secil
(class binder (impersonate call set_context_mgr transfer receive))
(class property_service (set))
(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
@@ -56,13 +59,16 @@ When creating new `binder`, `property_service`, `zygote` or `memprotect` objects
;; default_user zygote source;
;; default_user property_service source;
;; default_user memprotect source;
+```
defaultrole
-----------
Allows the default role to be taken from the source or target context when computing a new context for the object [`class`](cil_class_and_permission_statements.md#class) identifier. Requires policy version 27.
+```secil
(defaultrole class_id default)
+```
**Where:**
@@ -91,6 +97,7 @@ Allows the default role to be taken from the source or target context when compu
When creating new `binder`, `property_service` or `zygote` objects the [`role`](cil_role_statements.md#role) component of the new security context will be taken from the `target` context:
+```secil
(class binder (impersonate call set_context_mgr transfer receive))
(class property_service (set))
(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
@@ -101,6 +108,7 @@ When creating new `binder`, `property_service` or `zygote` objects the [`role`](
;; default_role binder target;
;; default_role zygote target;
;; default_role property_service target;
+```
defaulttype
-----------
@@ -109,7 +117,9 @@ Allows the default type to be taken from the source or target context when compu
**Statement definition:**
+```secil
(defaulttype class_id default)
+```
**Where:**
@@ -138,7 +148,9 @@ Allows the default type to be taken from the source or target context when compu
When creating a new `socket` object, the [`type`](cil_type_statements.md#type) component of the new security context will be taken from the `source` context:
+```secil
(defaulttype socket source)
+```
defaultrange
------------
@@ -147,7 +159,9 @@ Allows the default level or range to be taken from the source, target, or both c
**Statement definition:**
+```secil
(defaultrange class_id default <range>)
+```
**Where:**
@@ -180,8 +194,12 @@ Allows the default level or range to be taken from the source, target, or both c
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)
+```
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:
+```secil
(defaultrange db_table glblub)
+```
diff --git a/secilc/docs/cil_file_labeling_statements.md b/secilc/docs/cil_file_labeling_statements.md
index 3175ebca..73f73885 100644
--- a/secilc/docs/cil_file_labeling_statements.md
+++ b/secilc/docs/cil_file_labeling_statements.md
@@ -8,7 +8,9 @@ Define entries for labeling files. The compiler will produce these entries in a
**Statement definition:**
+```secil
(filecon "path" file_type context_id)
+```
**Where:**
@@ -34,11 +36,13 @@ Define entries for labeling files. The compiler will produce these entries in a
<col width="44%" />
<col width="55%" />
</colgroup>
-<tbody>
+<thead>
<tr class="odd">
<td align="left"><p><strong>keyword</strong></p></td>
<td align="left"><p><strong>file_contexts entry</strong></p></td>
</tr>
+</thead>
+<tbody>
<tr class="even">
<td align="left"><p><code>file</code></p></td>
<td align="left"><p><code>--</code></p></td>
@@ -89,17 +93,21 @@ Define entries for labeling files. The compiler will produce these entries in a
These examples use one named, one anonymous and one empty context definition:
+```secil
(context runas_exec_context (u object_r exec low_low))
(filecon "/system/bin/run-as" file runas_exec_context)
(filecon "/dev/socket/wpa_wlan[0-9]" any u:object_r:wpa.socket:s0-s0)
(filecon "/data/local/mine" dir ())
+```
to resolve/build `file_contexts` entries of (assuming MLS enabled policy):
+```
/system/bin/run-as -- u:object_r:runas.exec:s0
/dev/socket/wpa_wlan[0-9] u:object_r:wpa.socket:s0
/data/local/mine -d <<none>>
+```
fsuse
-----
@@ -108,7 +116,9 @@ Label filesystems that support SELinux security contexts.
**Statement definition:**
+```secil
(fsuse fstype fsname context_id)
+```
**Where:**
@@ -147,6 +157,7 @@ Label filesystems that support SELinux security contexts.
The [context](#context) identifiers are declared in the `file` namespace and the [`fsuse`](cil_file_labeling_statements.md#fsuse) statements in the global namespace:
+```secil
(block file
(type labeledfs)
(roletype object_r labeledfs)
@@ -166,6 +177,7 @@ The [context](#context) identifiers are declared in the `file` namespace and the
(fsuse trans devpts file.devpts_context)
(fsuse trans tmpfs file.tmpfs_context)
+```
genfscon
--------
@@ -174,7 +186,9 @@ Used to allocate a security context to filesystems that cannot support any of th
**Statement definition:**
- (genfscon fsname path context_id)
+```secil
+ (genfscon fsname path [file_type] context_id)
+```
**Where:**
@@ -197,6 +211,10 @@ Used to allocate a security context to filesystems that cannot support any of th
<td align="left"><p>If <code>fsname</code> is <code>proc</code>, then the partial path (see examples). For all other types this must be ‘<code>/</code>’.</p></td>
</tr>
<tr class="even">
+<td align="left"><p><code>file_type</code></p></td>
+<td align="left"><p>Optional keyword representing a file type. Valid values are the same as in [`filecon`](cil_file_labeling_statements.md#filecon) rules.</p></td>
+</tr>
+<tr class="odd">
<td align="left"><p><code>context_id</code></p></td>
<td align="left"><p>A previously declared <code>context</code> identifier or an anonymous security context (<code>user role type levelrange</code>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</p></td>
</tr>
@@ -207,6 +225,7 @@ Used to allocate a security context to filesystems that cannot support any of th
The [context](#context) identifiers are declared in the `file` namespace and the [`genfscon`](cil_file_labeling_statements.md#genfscon) statements are then inserted using the [`in`](cil_container_statements.md#in) container statement:
+```secil
(file
(type rootfs)
(roletype object_r rootfs)
@@ -226,3 +245,4 @@ The [context](#context) identifiers are declared in the `file` namespace and the
(genfscon proc /sysrq-trigger sysrq_proc_context)
(genfscon selinuxfs / selinuxfs_context)
)
+```
diff --git a/secilc/docs/cil_infiniband_statements.md b/secilc/docs/cil_infiniband_statements.md
index ba1d7101..0ba167cf 100644
--- a/secilc/docs/cil_infiniband_statements.md
+++ b/secilc/docs/cil_infiniband_statements.md
@@ -10,7 +10,9 @@ Label IB partition keys. This may be a single key or a range.
**Statement definition:**
+```secil
(ibpkeycon subnet pkey|(pkey_low pkey_high) context_id)
+```
**Where:**
@@ -43,8 +45,9 @@ Label IB partition keys. This may be a single key or a range.
An anonymous context for a partition key range of `0x0-0x10` assigned to an IPv6 subnet:
+```secil
(ibpkeycon fe80:: (0 0x10) (system_u system_r kernel_t (low (s3 (cats01 cats02)))))
-
+```
ibendportcon
------------
@@ -53,7 +56,9 @@ Label IB end ports.
**Statement definition:**
+```secil
(ibendportcon device_id port context_id)
+```
**Where:**
@@ -86,4 +91,6 @@ Label IB end ports.
A named context for device `mlx5_0` on port `1`:
+```secil
(ibendportcon mlx5_0 1 system_u_bin_t_l2h)
+```
diff --git a/secilc/docs/cil_mls_labeling_statements.md b/secilc/docs/cil_mls_labeling_statements.md
index 9b3a36a5..97d1459b 100644
--- a/secilc/docs/cil_mls_labeling_statements.md
+++ b/secilc/docs/cil_mls_labeling_statements.md
@@ -10,7 +10,9 @@ Declare a sensitivity identifier in the current namespace. Multiple [`sensitivit
**Statement definition:**
+```secil
(sensitivity sensitivity_id)
+```
**Where:**
@@ -35,9 +37,11 @@ Declare a sensitivity identifier in the current namespace. Multiple [`sensitivit
This example declares three [`sensitivity`](cil_mls_labeling_statements.md#sensitivity) identifiers:
+```secil
(sensitivity s0)
(sensitivity s1)
(sensitivity s2)
+```
sensitivityalias
----------------
@@ -46,7 +50,9 @@ Declares a sensitivity alias identifier in the current namespace. See the [`sens
**Statement definition:**
+```secil
(sensitivityalias sensitivityalias_id)
+```
**Where:**
@@ -78,7 +84,9 @@ Associates a previously declared [`sensitivityalias`](cil_mls_labeling_statement
**Statement definition:**
+```secil
(sensitivityaliasactual sensitivityalias_id sensitivity_id)
+```
**Where:**
@@ -107,11 +115,13 @@ Associates a previously declared [`sensitivityalias`](cil_mls_labeling_statement
This example will associate sensitivity `s0` with two sensitivity alias's:
+```secil
(sensitivity s0)
(sensitivityalias unclassified)
(sensitivityalias SystemLow)
(sensitivityaliasactual unclassified s0)
(sensitivityaliasactual SystemLow s0)
+```
sensitivityorder
----------------
@@ -120,7 +130,9 @@ Define the sensitivity order - lowest to highest. Multiple [`sensitivityorder`](
**Statement definition:**
+```secil
(sensitivityorder (sensitivity_id ...))
+```
**Where:**
@@ -145,6 +157,7 @@ Define the sensitivity order - lowest to highest. Multiple [`sensitivityorder`](
This example shows two [`sensitivityorder`](cil_mls_labeling_statements.md#sensitivityorder) statements that when compiled will form an ordered list. Note however that the second [`sensitivityorder`](cil_mls_labeling_statements.md#sensitivityorder) statement starts with `s2` so that the ordered list can be built.
+```secil
(sensitivity s0)
(sensitivityalias s0 SystemLow)
(sensitivity s1)
@@ -155,6 +168,7 @@ This example shows two [`sensitivityorder`](cil_mls_labeling_statements.md#sensi
(sensitivity s4)
(sensitivityalias s4 SystemHigh)
(sensitivityorder (s2 s3 SystemHigh))
+```
category
--------
@@ -163,7 +177,9 @@ Declare a category identifier in the current namespace. Multiple category statem
**Statement definition:**
+```secil
(category category_id)
+```
**Where:**
@@ -188,9 +204,11 @@ Declare a category identifier in the current namespace. Multiple category statem
This example declares a three [`category`](cil_mls_labeling_statements.md#category) identifiers:
+```secil
(category c0)
(category c1)
(category c2)
+```
categoryalias
-------------
@@ -199,7 +217,9 @@ Declares a category alias identifier in the current namespace. See the [`categor
**Statement definition:**
+```secil
(categoryalias categoryalias_id)
+```
**Where:**
@@ -227,7 +247,9 @@ Associates a previously declared [`categoryalias`](cil_mls_labeling_statements.m
**Statement definition:**
+```secil
(categoryaliasactual categoryalias_id category_id)
+```
**Where:**
@@ -256,9 +278,11 @@ Associates a previously declared [`categoryalias`](cil_mls_labeling_statements.m
Declares a category `c0`, a category alias of `documents`, and then associates them:
+```secil
(category c0)
(categoryalias documents)
(categoryaliasactual documents c0)
+```
categoryorder
-------------
@@ -267,7 +291,9 @@ Define the category order. Multiple [`categoryorder`](cil_mls_labeling_statement
**Statement definition:**
+```secil
(categoryorder (category_id ...))
+```
**Where:**
@@ -292,7 +318,9 @@ Define the category order. Multiple [`categoryorder`](cil_mls_labeling_statement
This example orders one category alias and nine categories:
+```secil
(categoryorder (documents c1 c2 c3 c4 c5 c6 c7 c8 c9)
+```
categoryset
-----------
@@ -307,7 +335,9 @@ Notes:
**Statement definition:**
+```secil
(categoryset categoryset_id (category_id ... | expr ...))
+```
**Where:**
@@ -347,6 +377,7 @@ Notes:
These examples show a selection of [`categoryset`](cil_mls_labeling_statements.md#categoryset) statements:
+```secil
; Declare categories with two alias's:
(category c0)
(categoryalias documents)
@@ -372,6 +403,7 @@ These examples show a selection of [`categoryset`](cil_mls_labeling_statements.m
(categoryset catset_3 (c4))
(categoryset just_c0 (xor (c1 c2) (documents c1 c2)))
+```
sensitivitycategory
-------------------
@@ -380,7 +412,9 @@ Associate a [`sensitivity`](cil_mls_labeling_statements.md#sensitivity) identifi
**Statement definition:**
+```secil
(sensitivitycategory sensitivity_id categoryset_id)
+```
**Where:**
@@ -409,11 +443,13 @@ Associate a [`sensitivity`](cil_mls_labeling_statements.md#sensitivity) identifi
These [`sensitivitycategory`](cil_mls_labeling_statements.md#sensitivitycategory) examples use a selection of [`category`](cil_mls_labeling_statements.md#category), [`categoryalias`](cil_mls_labeling_statements.md#categoryalias) and [`categoryset`](cil_mls_labeling_statements.md#categoryset)'s:
+```secil
(sensitivitycategory s0 catrange_1)
(sensitivitycategory s0 catset_1)
(sensitivitycategory s0 catset_3)
(sensitivitycategory s0 (all))
(sensitivitycategory unclassified (range documents c2))
+```
level
-----
@@ -422,7 +458,9 @@ Declare a [`level`](cil_mls_labeling_statements.md#level) identifier in the curr
**Statement definition:**
- level level_id (sensitivity_id [categoryset_id])
+```secil
+ (level level_id (sensitivity_id [categoryset_id]))
+```
**Where:**
@@ -455,11 +493,13 @@ Declare a [`level`](cil_mls_labeling_statements.md#level) identifier in the curr
These [`level`](cil_mls_labeling_statements.md#level) examples use a selection of [`category`](cil_mls_labeling_statements.md#category), [`categoryalias`](cil_mls_labeling_statements.md#categoryalias) and [`categoryset`](cil_mls_labeling_statements.md#categoryset)'s:
+```secil
(level systemLow (s0))
(level level_1 (s0))
(level level_2 (s0 (catrange_1)))
(level level_3 (s0 (all_cats)))
(level level_4 (unclassified (c2 c3 c4)))
+```
levelrange
----------
@@ -468,7 +508,9 @@ Declare a level range identifier in the current namespace and associate a curren
**Statement definition:**
+```secil
(levelrange levelrange_id (low_level_id high_level_id))
+```
**Where:**
@@ -501,6 +543,7 @@ Declare a level range identifier in the current namespace and associate a curren
This example policy shows [`levelrange`](cil_mls_labeling_statements.md#levelrange) statement and all the other MLS labeling statements discussed in this section and will compile as a standalone policy:
+```secil
(handleunknown allow)
(mls true)
@@ -581,6 +624,7 @@ This example policy shows [`levelrange`](cil_mls_labeling_statements.md#levelran
(context context_1 (user object_r object low_low))
) ; End unconfined namespace
+```
rangetransition
---------------
@@ -589,7 +633,9 @@ Allows an objects level to transition to a different level. Generally used to en
**Statement definition:**
+```secil
(rangetransition source_id target_id class_id new_range_id)
+```
**Where:**
@@ -626,13 +672,15 @@ Allows an objects level to transition to a different level. Generally used to en
This rule will transition the range of `sshd.exec` to `s0 - s1:c0.c3` on execution from the `init.process`:
+```secil
(sensitivity s0)
(sensitivity s1)
(sensitivityorder s0 s1)
(category c0)
...
- (level systemlow (s0)
+ (level systemlow (s0))
(level systemhigh (s1 (c0 c1 c2)))
(levelrange low_high (systemlow systemhigh))
(rangetransition init.process sshd.exec process low_high)
+```
diff --git a/secilc/docs/cil_network_labeling_statements.md b/secilc/docs/cil_network_labeling_statements.md
index 49a836c1..f92e2136 100644
--- a/secilc/docs/cil_network_labeling_statements.md
+++ b/secilc/docs/cil_network_labeling_statements.md
@@ -14,7 +14,9 @@ Notes:
**Statement definition:**
+```secil
(ipaddr ipaddr_id ip_address)
+```
**Where:**
@@ -43,13 +45,15 @@ Notes:
This example declares a named IP address and also passes an 'explicit anonymously declared' IP address to a macro:
+```secil
(ipaddr netmask_1 255.255.255.0)
- (context netlabel_1 (system.user object_r unconfined.object low_low)
+ (context netlabel_1 (system.user object_r unconfined.object low_low))
(call build_nodecon ((192.168.1.64) netmask_1))
(macro build_nodecon ((ipaddr ARG1) (ipaddr ARG2))
(nodecon ARG1 ARG2 netlabel_1))
+```
netifcon
--------
@@ -58,7 +62,9 @@ Label network interface objects (e.g. `eth0`).
**Statement definition:**
+```secil
(netifcon netif_name netif_context_id packet_context_id)
+```
**Where:**
@@ -93,12 +99,14 @@ Label network interface objects (e.g. `eth0`).
These examples show named and anonymous [`netifcon`](cil_network_labeling_statements.md#netifcon) statements:
+```secil
(context context_1 (unconfined.user object_r unconfined.object low_low))
(context context_2 (unconfined.user object_r unconfined.object (systemlow level_2)))
(netifcon eth0 context_1 (unconfined.user object_r unconfined.object levelrange_1))
(netifcon eth1 context_1 (unconfined.user object_r unconfined.object ((s0) level_1)))
(netifcon eth3 context_1 context_2)
+```
nodecon
-------
@@ -109,7 +117,9 @@ IP Addresses may be declared without a previous declaration by enclosing within
**Statement definition:**
+```secil
(nodecon subnet_id netmask_id context_id)
+```
**Where:**
@@ -142,15 +152,26 @@ IP Addresses may be declared without a previous declaration by enclosing within
These examples show named and anonymous [`nodecon`](cil_network_labeling_statements.md#nodecon) statements:
+```secil
(context context_1 (unconfined.user object_r unconfined.object low_low))
(context context_2 (unconfined.user object_r unconfined.object (systemlow level_2)))
- (ipaddr netmask_1 255.255.255.0)
- (ipaddr ipv4_1 192.168.1.64)
+ (ipaddr netmask_1 255.255.255.255)
+ (ipaddr ipv4_1 192.0.2.64)
+
+ (nodecon ipv4_1 netmask_1 context_2)
+ (nodecon (192.0.2.64) (255.255.255.255) context_1)
+ (nodecon (192.0.2.64) netmask_1 (unconfined.user object_r unconfined.object ((s0) (s0 (c0)))))
+
+ (context context_3 (sys.id sys.role my48prefix.node ((s0)(s0))))
+
+ (ipaddr netmask_2 ffff:ffff:ffff:0:0:0:0:0)
+ (ipaddr ipv6_2 2001:db8:1:0:0:0:0:0)
- (nodecon netmask_1 ipv4_1 context_2)
- (nodecon (255.255.255.0) (192.168.1.64) context_1)
- (nodecon netmask_1 (192.168.1.64) (unconfined.user object_r unconfined.object ((s0) (s0 (c0)))))
+ (nodecon ipv6_2 netmask_2 context_3)
+ (nodecon (2001:db8:1:0:0:0:0:0) (ffff:ffff:ffff:0:0:0:0:0) context_3)
+ (nodecon (2001:db8:1:0:0:0:0:0) netmask_2 (sys.id sys.role my48prefix.node ((s0)(s0))))
+```
portcon
-------
@@ -159,7 +180,9 @@ Label a udp, tcp, dccp or sctp port.
**Statement definition:**
+```secil
(portcon protocol port|(port_low port_high) context_id)
+```
**Where:**
@@ -194,6 +217,7 @@ Label a udp, tcp, dccp or sctp port.
These examples show named and anonymous [`portcon`](cil_network_labeling_statements.md#portcon) statements:
+```secil
(portcon tcp 1111 (unconfined.user object_r unconfined.object ((s0) (s0 (c0)))))
(portcon tcp 2222 (unconfined.user object_r unconfined.object levelrange_2))
(portcon tcp 3333 (unconfined.user object_r unconfined.object levelrange_1))
@@ -201,3 +225,4 @@ These examples show named and anonymous [`portcon`](cil_network_labeling_stateme
(portcon tcp (2000 20000) (unconfined.user object_r unconfined.object (systemlow level_3)))
(portcon dccp (6840 6880) (unconfined.user object_r unconfined.object ((s0) level_2)))
(portcon sctp (1024 1035) (unconfined.user object_r unconfined.object ((s0) level_2)))
+```
diff --git a/secilc/docs/cil_policy_config_statements.md b/secilc/docs/cil_policy_config_statements.md
index 48e29d67..0258b913 100644
--- a/secilc/docs/cil_policy_config_statements.md
+++ b/secilc/docs/cil_policy_config_statements.md
@@ -10,7 +10,9 @@ Note that this can be over-ridden by the CIL compiler command line parameter `-M
**Statement definition:**
+```secil
(mls boolean)
+```
**Where:**
@@ -33,7 +35,9 @@ Note that this can be over-ridden by the CIL compiler command line parameter `-M
**Example:**
+```secil
(mls true)
+```
handleunknown
-------------
@@ -44,7 +48,9 @@ Note that this can be over-ridden by the CIL compiler command line parameter `-U
**Statement definition:**
+```secil
(handleunknown action)
+```
**Where:**
@@ -72,7 +78,9 @@ Note that this can be over-ridden by the CIL compiler command line parameter `-U
This will allow unknown classes / permissions to be present in the policy:
+```secil
(handleunknown allow)
+```
policycap
---------
@@ -81,7 +89,9 @@ Allow policy capabilities to be enabled via policy. These should be declared in
**Statement definition:**
+```secil
(policycap policycap_id)
+```
**Where:**
@@ -106,8 +116,10 @@ Allow policy capabilities to be enabled via policy. These should be declared in
These set two valid policy capabilities:
+```secil
; Enable networking controls.
(policycap network_peer_controls)
; Enable open permission check.
(policycap open_perms)
+```
diff --git a/secilc/docs/cil_reference_guide.md b/secilc/docs/cil_reference_guide.md
index 1b1fccca..1e63e680 100644
--- a/secilc/docs/cil_reference_guide.md
+++ b/secilc/docs/cil_reference_guide.md
@@ -57,10 +57,12 @@ Declarations may be named or anonymous and have three different forms:
ipaddr
macro
policycap
+
2. Explicit anonymous declarations - These are currently restricted to IP addresses where they can be declared directly in statements by enclosing them within parentheses e.g. `(127.0.0.1)` or `(::1)`. See the [Network Labeling Statements](#network_labeling) section for examples.
3. Anonymous declarations - These have been previously declared and the object already exists, therefore they may be referenced by their name or identifier within statements. For example the following declare all the components required to specify a context:
+ ```secil
(sensitivity s0)
(category c0)
(role object_r)
@@ -69,10 +71,13 @@ Declarations may be named or anonymous and have three different forms:
(user user)
(type object)
)
+ ```
now a [`portcon`](cil_network_labeling_statements.md#portcon) statement can be defined that uses these individual components to build a context as follows:
+ ```secil
(portcon udp 12345 (unconfined.user object_r unconfined.object ((s0) (s0(c0)))))
+ ```
Definitions
-----------
@@ -113,6 +118,7 @@ Namespaces
CIL supports namespaces via containers such as the [`block`](cil_container_statements.md#block) statement. When a block is resolved to form the parent / child relationship a dot '`.`' is used, for example the following [`allow`](cil_access_vector_rules.md#allow) rule:
+```secil
(block example_ns
(type process)
(type object)
@@ -120,16 +126,20 @@ CIL supports namespaces via containers such as the [`block`](cil_container_state
(allow process object (file (open read getattr)))
)
+```
will resolve to the following kernel policy language statement:
+```
allow example_ns.process example_ns.object : example_ns.file { open read getattr };
+```
Global Namespace
----------------
CIL has a global namespace that is always present. Any symbol that is declared outside a container is in the global namespace. To reference a symbol in global namespace, the symbol should be prefixed with a dot '`.`' as shown in the following example:
+```secil
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This example has three namespace 'tmpfs' types declared:
; 1) Global .tmpfs
@@ -170,19 +180,22 @@ CIL has a global namespace that is always present. Any symbol that is declared o
(block other_ns
(type tmpfs)
)
+```
Should the symbol not be prefixed with a dot, the current namespace would be searched first and then the global namespace (provided there is not a symbol of that name in the current namespace).
Expressions
-----------
-Expressions may occur in the following CIL statements: [`booleanif`](cil_conditional_statements.md#booleanif), [`tunableif`](cil_conditional_statements.md#tunableif), [`classpermissionset`](cil_class_and_permission_statements.md#classpermissionset), [`typeattributeset`](cil_type_statements.md#typeattributeset), [`roleattributeset`](cil_role_statements.md#roleattributeset), [`categoryset`](cil_mls_labeling_statements.md#categoryset), [`constrain`](cil_constraint_statements.md#constrain), [`mlsconstrain`](cil_constraint_statements.md#mlsconstrain), [`validatetrans`](cil_constraint_statements.md#validatetrans), [`validatetrans`](cil_constraint_statements.md#validatetrans)
+Expressions may occur in the following CIL statements: [`booleanif`](cil_conditional_statements.md#booleanif), [`tunableif`](cil_conditional_statements.md#tunableif), [`classpermissionset`](cil_class_and_permission_statements.md#classpermissionset), [`typeattributeset`](cil_type_statements.md#typeattributeset), [`roleattributeset`](cil_role_statements.md#roleattributeset), [`categoryset`](cil_mls_labeling_statements.md#categoryset), [`constrain`](cil_constraint_statements.md#constrain), [`mlsconstrain`](cil_constraint_statements.md#mlsconstrain), [`validatetrans`](cil_constraint_statements.md#validatetrans), [`mlsvalidatetrans`](cil_constraint_statements.md#mlsvalidatetrans)
CIL expressions use the [prefix](http://www.cs.man.ac.uk/~pjj/cs212/fix.html) or Polish notation and may be nested (note that the kernel policy language uses postfix or reverse Polish notation). The syntax is as follows, where the parenthesis are part of the syntax:
+```
expr_set = (name ... | expr ...)
expr = (expr_key expr_set ...)
expr_key = and | or | xor | not | all | eq | neq | dom | domby | incomp | range
+```
The number of `expr_set`'s in an `expr` is dependent on the statement type (there are four different classes as defined below) that also influence the valid `expr_key` entries (e.g. `dom`, `domby`, `incomp` are only allowed in constraint statements).
@@ -204,6 +217,7 @@ The number of `expr_set`'s in an `expr` is dependent on the statement type (ther
This example includes all `fs_type type` entries except `file.usermodehelper` and `file.proc_security` in the associated [`typeattribute`](cil_type_statements.md#typeattribute) identifier `all_fs_type_except_usermodehelper_and_proc_security`:
+ ```secil
(typeattribute all_fs_type_except_usermodehelper_and_proc_security)
(typeattributeset all_fs_type_except_usermodehelper_and_proc_security
@@ -215,17 +229,21 @@ The number of `expr_set`'s in an `expr` is dependent on the statement type (ther
(not file.proc_security)
)
)
+ ```
The `cps_1 classpermissionset` identifier includes all permissions except `load_policy` and `setenforce`:
+ ```secil
(class security (compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot read_policy))
(classpermission cps_1)
(classpermissionset cps_1 (security (not (load_policy setenforce))))
+ ```
This example includes all permissions in the associated [`classpermissionset`](cil_class_and_permission_statements.md#classpermissionset) identifier `security_all_perms`:
+ ```secil
(class security (compute_av compute_create compute_member check_context load_policy
compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
read_policy)
@@ -234,6 +252,7 @@ The number of `expr_set`'s in an `expr` is dependent on the statement type (ther
(classpermission security_all_perms)
(classpermissionset security_all_perms (security (all)))
+ ```
2. The [`categoryset`](cil_mls_labeling_statements.md#categoryset) statement allows `expr_set` to mix names and `expr_key` values of: `and`, `or`, `not`, `xor`, `all`, `range` as shown in the examples.
@@ -241,6 +260,7 @@ The number of `expr_set`'s in an `expr` is dependent on the statement type (ther
3. The [`booleanif`](cil_conditional_statements.md#booleanif) and [`tunableif`](cil_conditional_statements.md#tunableif) statements only allow an `expr_set` to have one `name` or `expr` with `expr_key` values of `and`, `or`, `xor`, `not`, `eq`, `neq` as shown in the examples:
+ ```secil
(booleanif disableAudio
(false
(allow process device.audio_device (chr_file_set (rw_file_perms)))
@@ -252,9 +272,11 @@ The number of `expr_set`'s in an `expr` is dependent on the statement type (ther
(allow process device.audio_capture_device (chr_file_set (rw_file_perms)))
)
)
+ ```
4. The [`constrain`](cil_constraint_statements.md#constrain), [`mlsconstrain`](cil_constraint_statements.md#mlsconstrain), [`validatetrans`](cil_constraint_statements.md#validatetrans) and [`mlsvalidatetrans`](cil_constraint_statements.md#mlsvalidatetrans) statements only allow an `expr_set` to have one `name` or `expr` with `expr_key` values of `and`, `or`, `not`, `all`, `eq`, `neq`, `dom`, `domby`, `incomp`. When `expr_key` is `dom`, `domby` or `incomp`, it must be followed by a string (e.g. `h1`, `l2`) and another string or a set of `name`s. The following examples show CIL constraint statements and their policy language equivalents:
+ ```secil
; Process transition: Require equivalence unless the subject is trusted.
(mlsconstrain (process (transition dyntransition))
(or (and (eq h1 h2) (eq l1 l2)) (eq t1 mlstrustedsubject)))
@@ -270,29 +292,36 @@ The number of `expr_set`'s in an `expr` is dependent on the statement type (ther
; The equivalent policy language mlsconstrain statememt is:
;mlsconstrain process { getsched getsession getpgid getcap getattr ptrace share }
; (l1 dom l2 or t1 == mlstrustedsubject);
+ ```
Name String
-----------
Used to define [`macro`](cil_call_macro_statements.md#macro) statement parameter string types:
+```secil
(call macro1("__kmsg__"))
(macro macro1 ((string ARG1))
(typetransition audit.process device.device chr_file ARG1 device.klog_device)
)
+```
Alternatively:
+```secil
(call macro1("__kmsg__"))
(macro macro1 ((name ARG1))
(typetransition audit.process device.device chr_file ARG1 device.klog_device)
)
+```
self
----
The [`self`](cil_reference_guide.md#self) keyword may be used as the target in AVC rule statements, and means that the target is the same as the source as shown in the following example:.
+```secil
(allow unconfined.process self (file (read write)))
+```
diff --git a/secilc/docs/cil_role_statements.md b/secilc/docs/cil_role_statements.md
index c1e457a7..2e1b4047 100644
--- a/secilc/docs/cil_role_statements.md
+++ b/secilc/docs/cil_role_statements.md
@@ -8,7 +8,9 @@ Declares a role identifier in the current namespace.
**Statement definition:**
+```secil
(role role_id)
+```
**Where:**
@@ -33,11 +35,13 @@ Declares a role identifier in the current namespace.
This example declares two roles: `object_r` in the global namespace and `unconfined.role`:
+```secil
(role object_r)
(block unconfined
(role role)
)
+```
roletype
--------
@@ -46,7 +50,9 @@ Authorises a [`role`](cil_role_statements.md#role) to access a [`type`](cil_type
**Statement definition:**
+```secil
(role role_id type_id)
+```
**Where:**
@@ -75,11 +81,13 @@ Authorises a [`role`](cil_role_statements.md#role) to access a [`type`](cil_type
This example will declare [`role`](cil_role_statements.md#role) and [`type`](cil_type_statements.md#type) identifiers, then associate them:
+```secil
(block unconfined
(role role)
(type process)
(roletype role process)
)
+```
roleattribute
-------------
@@ -88,7 +96,9 @@ Declares a role attribute identifier in the current namespace. The identifier ma
**Statement definition:**
+```secil
(roleattribute roleattribute_id)
+```
**Where:**
@@ -113,9 +123,11 @@ Declares a role attribute identifier in the current namespace. The identifier ma
This example will declare a role attribute `roles.role_holder` that will have an empty set:
+```secil
(block roles
(roleattribute role_holder)
)
+```
roleattributeset
----------------
@@ -124,7 +136,9 @@ Allows the association of one or more previously declared [`role`](cil_role_stat
**Statement definition:**
+```secil
(roleattributeset roleattribute_id (role_id ... | expr ...))
+```
**Where:**
@@ -163,6 +177,7 @@ Allows the association of one or more previously declared [`role`](cil_role_stat
This example will declare three roles and two role attributes, then associate all the roles to them as shown:
+```secil
(block roles
(role role_1)
(role role_2)
@@ -174,6 +189,7 @@ This example will declare three roles and two role attributes, then associate al
(roleattribute role_holder_all)
(roleattributeset role_holder_all (all))
)
+```
roleallow
---------
@@ -188,7 +204,9 @@ Notes:
**Statement definition:**
+```secil
(roleallow current_role_id new_role_id)
+```
**Where:**
@@ -224,7 +242,9 @@ Specify a role transition from the current role to a new role when computing a c
**Statement definition:**
+```secil
(roletransition current_role_id target_type_id class_id new_role_id)
+```
**Where:**
@@ -261,6 +281,7 @@ Specify a role transition from the current role to a new role when computing a c
This example will authorise the `unconfined.role` to assume the `msg_filter.role` role, and then transition to that role:
+```secil
(block ext_gateway
(type process)
(type exec)
@@ -269,6 +290,7 @@ This example will authorise the `unconfined.role` to assume the `msg_filter.role
(roleallow unconfined.role msg_filter.role)
(roletransition unconfined.role exec process msg_filter.role)
)
+```
rolebounds
----------
@@ -283,7 +305,9 @@ Notes:
**Statement definition:**
+```secil
(rolebounds parent_role_id child_role_id)
+```
**Where:**
@@ -312,9 +336,11 @@ Notes:
In this example the role `test` cannot have greater privileges than `unconfined.role`:
+```secil
(role test)
- (unconfined
+ (block unconfined
(role role)
(rolebounds role .test)
)
+```
diff --git a/secilc/docs/cil_sid_statements.md b/secilc/docs/cil_sid_statements.md
index a9b25373..a5d21013 100644
--- a/secilc/docs/cil_sid_statements.md
+++ b/secilc/docs/cil_sid_statements.md
@@ -8,7 +8,9 @@ Declares a new SID identifier in the current namespace.
**Statement definition:**
+```secil
(sid sid_id)
+```
**Where:**
@@ -33,9 +35,11 @@ Declares a new SID identifier in the current namespace.
These examples show three [`sid`](cil_sid_statements.md#sid) declarations:
+```secil
(sid kernel)
(sid security)
(sid igmp_packet)
+```
sidorder
--------
@@ -44,7 +48,9 @@ Defines the order of [sid](#sid)'s. This is a mandatory statement when SIDs are
**Statement definition:**
+```secil
(sidorder (sid_id ...))
+```
**Where:**
@@ -69,11 +75,13 @@ Defines the order of [sid](#sid)'s. This is a mandatory statement when SIDs are
This will produce an ordered list of "`kernel security unlabeled`"
+```secil
(sid kernel)
(sid security)
(sid unlabeled)
(sidorder (kernel security))
(sidorder (security unlabeled))
+```
sidcontext
----------
@@ -82,7 +90,9 @@ Associates an SELinux security [context](#context) to a previously declared [`si
**Statement definition:**
+```secil
(sidcontext sid_id context_id)
+```
**Where:**
@@ -111,6 +121,7 @@ Associates an SELinux security [context](#context) to a previously declared [`si
This shows two named security context examples plus an anonymous context:
+```secil
; Two named context:
(sid kernel)
(context kernel_context (u r process low_low))
@@ -123,3 +134,4 @@ This shows two named security context examples plus an anonymous context:
; An anonymous context:
(sid unlabeled)
(sidcontext unlabeled (u object_r ((s0) (s0))))
+```
diff --git a/secilc/docs/cil_type_statements.md b/secilc/docs/cil_type_statements.md
index f9dd3a76..19438417 100644
--- a/secilc/docs/cil_type_statements.md
+++ b/secilc/docs/cil_type_statements.md
@@ -8,7 +8,9 @@ Declares a type identifier in the current namespace.
**Statement definition:**
+```secil
(type type_id)
+```
**Where:**
@@ -33,9 +35,11 @@ Declares a type identifier in the current namespace.
This example declares a type identifier `bluetooth.process`:
+```secil
(block bluetooth
(type process)
)
+```
typealias
---------
@@ -44,7 +48,9 @@ Declares a type alias in the current namespace.
**Statement definition:**
+```secil
(typealias typealias_id)
+```
**Where:**
@@ -76,7 +82,9 @@ Associates a previously declared [`typealias`](cil_type_statements.md#typealias)
**Statement definition:**
+```secil
(typealiasactual typealias_id type_id)
+```
**Where:**
@@ -105,12 +113,14 @@ Associates a previously declared [`typealias`](cil_type_statements.md#typealias)
This example will alias `unconfined.process` as `unconfined_t` in the global namespace:
+```secil
(typealias unconfined_t)
(typealiasactual unconfined_t unconfined.process)
(block unconfined
(type process)
)
+```
typeattribute
-------------
@@ -119,7 +129,9 @@ Declares a type attribute identifier in the current namespace. The identifier ma
**Statement definition:**
+```secil
(typeattribute typeattribute_id)
+```
**Where:**
@@ -144,7 +156,9 @@ Declares a type attribute identifier in the current namespace. The identifier ma
This example declares a type attribute `domain` in global namespace that will have an empty set:
+```secil
(typeattribute domain)
+```
typeattributeset
----------------
@@ -153,7 +167,9 @@ Allows the association of one or more previously declared [`type`](cil_type_stat
**Statement definition:**
+```secil
(typeattributeset typeattribute_id (type_id ... | expr ...))
+```
**Where:**
@@ -192,12 +208,15 @@ Allows the association of one or more previously declared [`type`](cil_type_stat
This example will take all the policy types and exclude those in `appdomain`. It is equivalent to `~appdomain` in the kernel policy language.
+```secil
(typeattribute not_in_appdomain)
(typeattributeset not_in_appdomain (not (appdomain)))
+```
This example is equivalent to `{ domain -kernel.process -ueventd.process -init.process }` in the kernel policy language:
+```secil
(typeattribute na_kernel_or_ueventd_or_init_in_domain)
(typeattributeset na_kernel_or_ueventd_or_init_in_domain
@@ -212,6 +231,64 @@ This example is equivalent to `{ domain -kernel.process -ueventd.process -init.p
(not (init.process))
)
)
+```
+
+expandtypeattribute
+-------------------
+
+Overrides the compiler defaults for the expansion of one or more
+previously declared [`typeattribute`](cil_type_statements.md#typeattribute)
+identifiers.
+
+This rule gives more control over type attribute expansion and
+removal. When the value is true, all rules involving the type
+attribute will be expanded and the type attribute will be removed from
+the policy. When the value is false, the type attribute will not be
+removed from the policy, even if the default expand rules or "-X"
+option cause the rules involving the type attribute to be expanded.
+
+**Statement definition:**
+
+```secil
+ (expandtypeattribute typeattribute_id expand_value)
+```
+
+**Where:**
+
+<table>
+<colgroup>
+<col width="25%" />
+<col width="75%" />
+</colgroup>
+<tbody>
+<tr class="odd">
+<td align="left"><p><code>expandtypeattribute</code></p></td>
+<td align="left"><p>The <code>expandtypeattribute</code> keyword.</p></td>
+</tr>
+<tr class="even">
+<td align="left"><p><code>typeattribute_id</code></p></td>
+<td align="left"><p>One or more previously declared <code>typeattribute</code> identifiers. Multiple entries consist of a space separated list enclosed in parentheses '()'.</p></td>
+</tr>
+<tr class="odd">
+<td align="left"><p><code>expand_value</code></p></td>
+<td align="left"><p>Either true or false.</p></td>
+</tr>
+</tbody>
+</table>
+
+**Examples:**
+
+This example uses the expandtypeattribute statement to forcibly expand a previously declared `domain` type attribute.
+
+```secil
+ (expandtypeattribute domain true)
+```
+
+This example uses the expandtypeattribute statement to not expand previously declared `file_type` and `port_type` type attributes regardless of compiler defaults.
+
+```secil
+ (expandtypeattribute (file_type port_type) false)
+```
typebounds
----------
@@ -222,7 +299,9 @@ Requires kernel 2.6.28 and above to control the security context associated to t
**Statement definition:**
+```secil
(typebounds parent_type_id child_type_id)
+```
**Where:**
@@ -251,6 +330,7 @@ Requires kernel 2.6.28 and above to control the security context associated to t
In this example the `httpd.child.process` cannot have `file (write)` due to lack of permissions on `httpd.process` which is the parent. It means the child domain will always have equal or less privileges than the parent:
+```secil
(class file (getattr read write))
(block httpd
@@ -269,6 +349,7 @@ In this example the `httpd.child.process` cannot have `file (write)` due to lack
(allow process httpd.object (file (read write)))
)
)
+```
typechange
----------
@@ -277,7 +358,9 @@ The type change rule is used to define a different label of an object for usersp
**Statement definition:**
+```secil
(typechange source_type_id target_type_id class_id change_type_id)
+```
**Where:**
@@ -320,6 +403,7 @@ the function will return a context of:
` unconfined.object:object_r:unconfined.change_label:s0`
+```secil
(class file (getattr read write))
(block unconfined
@@ -329,6 +413,7 @@ the function will return a context of:
(typechange object object file change_label)
)
+```
typemember
----------
@@ -337,7 +422,9 @@ The type member rule is used to define a new polyinstantiated label of an object
**Statement definition:**
+```secil
(typemember source_type_id target_type_id class_id member_type_id)
+```
**Where:**
@@ -380,6 +467,7 @@ the function will return a context of:
` unconfined.object:object_r:unconfined.member_label:s0`
+```secil
(class file (getattr read write))
(block unconfined
@@ -389,6 +477,7 @@ the function will return a context of:
(typemember object object file member_label)
)
+```
typetransition
--------------
@@ -397,7 +486,9 @@ The type transition rule specifies the labeling and object creation allowed betw
**Statement definition:**
+```secil
(typetransition source_type_id target_type_id class_id [object_name] default_type_id)
+```
**Where:**
@@ -438,29 +529,35 @@ The type transition rule specifies the labeling and object creation allowed betw
This example shows a process transition rule with its supporting [`allow`](cil_access_vector_rules.md#allow) rule:
+```secil
(macro domain_auto_trans ((type ARG1) (type ARG2) (type ARG3))
; Allow the necessary permissions.
(call domain_trans (ARG1 ARG2 ARG3))
; Make the transition occur by default.
(typetransition ARG1 ARG2 process ARG3)
)
+```
This example shows a file object transition rule with its supporting [`allow`](cil_access_vector_rules.md#allow) rule:
+```secil
(macro tmpfs_domain ((type ARG1))
(type tmpfs)
(typeattributeset file_type (tmpfs))
(typetransition ARG1 file.tmpfs file tmpfs)
(allow ARG1 tmpfs (file (read write execute execmod)))
)
+```
This example shows the 'name transition' rule with its supporting [`allow`](cil_access_vector_rules.md#allow) rule:
+```secil
(macro write_klog ((type ARG1))
(typetransition ARG1 device.device chr_file "__kmsg__" device.klog_device)
(allow ARG1 device.klog_device (chr_file (create open write unlink)))
(allow ARG1 device.device (dir (write add_name remove_name)))
)
+```
typepermissive
--------------
@@ -469,7 +566,9 @@ Policy database version 23 introduced the permissive statement to allow the name
**Statement definition:**
+```secil
(typepermissive source_type_id)
+```
**Where:**
@@ -494,9 +593,11 @@ Policy database version 23 introduced the permissive statement to allow the name
This example will allow SELinux to run the `healthd.process` domain in permissive mode even when enforcing is enabled:
+```secil
(block healthd
(type process)
(typepermissive process)
(allow ...)
)
+```
diff --git a/secilc/docs/cil_user_statements.md b/secilc/docs/cil_user_statements.md
index bbd76eff..d5674f12 100644
--- a/secilc/docs/cil_user_statements.md
+++ b/secilc/docs/cil_user_statements.md
@@ -8,7 +8,9 @@ Declares an SELinux user identifier in the current namespace.
**Statement definition:**
+```secil
(user user_id)
+```
**Where:**
@@ -33,9 +35,11 @@ Declares an SELinux user identifier in the current namespace.
This will declare an SELinux user as `unconfined.user`:
+```secil
(block unconfined
(user user)
)
+```
userrole
--------
@@ -44,7 +48,9 @@ Associates a previously declared [`user`](cil_user_statements.md#user) identifie
**Statement definition:**
+```secil
(userrole user_id role_id)
+```
**Where:**
@@ -73,11 +79,13 @@ Associates a previously declared [`user`](cil_user_statements.md#user) identifie
This example will associate `unconfined.user` to `unconfined.role`:
+```secil
(block unconfined
(user user)
(role role)
(userrole user role)
)
+```
userattribute
-------------
@@ -86,7 +94,9 @@ Declares a user attribute identifier in the current namespace. The identifier ma
**Statement definition:**
+```secil
(userattribute userattribute_id)
+```
**Where:**
@@ -111,9 +121,11 @@ Declares a user attribute identifier in the current namespace. The identifier ma
This example will declare a user attribute `users.user_holder` that will have an empty set:
+```secil
(block users
(userattribute user_holder)
)
+```
userattributeset
----------------
@@ -122,7 +134,9 @@ Allows the association of one or more previously declared [`user`](cil_user_stat
**Statement definition:**
+```secil
(userattributeset userattribute_id (user_id ... | expr ...))
+```
**Where:**
@@ -161,6 +175,7 @@ Allows the association of one or more previously declared [`user`](cil_user_stat
This example will declare three users and two user attributes, then associate all the users to them as shown:
+```secil
(block users
(user user_1)
(user user_2)
@@ -172,6 +187,7 @@ This example will declare three users and two user attributes, then associate al
(userattribute user_holder_all)
(userattributeset user_holder_all (all))
)
+```
userlevel
---------
@@ -180,7 +196,9 @@ Associates a previously declared [`user`](cil_user_statements.md#user) identifie
**Statement definition:**
+```secil
(userlevel user_id level_id)
+```
**Where:**
@@ -209,6 +227,7 @@ Associates a previously declared [`user`](cil_user_statements.md#user) identifie
This example will associate `unconfined.user` with a named [`level`](cil_mls_labeling_statements.md#level) of `systemlow`:
+```secil
(sensitivity s0)
(level systemlow (s0))
@@ -218,6 +237,7 @@ This example will associate `unconfined.user` with a named [`level`](cil_mls_lab
; An anonymous example:
;(userlevel user (s0))
)
+```
userrange
---------
@@ -226,7 +246,9 @@ Associates a previously declared [`user`](cil_user_statements.md#user) identifie
**Statement definition:**
+```secil
(userrange user_id levelrange_id)
+```
**Where:**
@@ -255,12 +277,13 @@ Associates a previously declared [`user`](cil_user_statements.md#user) identifie
This example will associate `unconfined.user` with a named [`levelrange`](cil_mls_labeling_statements.md#levelrange) of `low_high`, other anonymous examples are also shown:
+```secil
(category c0)
(category c1)
(categoryorder (c0 c1))
(sensitivity s0)
(sensitivity s1)
- (dominance (s0 s1))
+ (sensitivityorder (s0 s1))
(sensitivitycategory s0 (c0 c1))
(level systemLow (s0))
(level systemHigh (s0 (c0 c1)))
@@ -277,6 +300,7 @@ This example will associate `unconfined.user` with a named [`levelrange`](cil_ml
;(userrange user (systemLow (s0 (c0 c1))))
;(userrange user ((s0) (s0 (c0 c1))))
)
+```
userbounds
----------
@@ -291,7 +315,9 @@ Notes:
**Statement definition:**
+```secil
(userbounds parent_user_id child_user_id)
+```
**Where:**
@@ -320,12 +346,14 @@ Notes:
The user `test` cannot have greater privileges than `unconfined.user`:
+```secil
(user test)
(unconfined
(user user)
(userbounds user .test)
)
+```
userprefix
----------
@@ -334,7 +362,9 @@ Declare a user prefix that will be replaced by the file labeling utilities descr
**Statement definition:**
+```secil
(userprefix user_id prefix)
+```
**Where:**
@@ -363,10 +393,12 @@ Declare a user prefix that will be replaced by the file labeling utilities descr
This example will associate `unconfined.admin` user with a prefix of "[`user`](cil_user_statements.md#user)":
+```secil
(block unconfined
- (user admin
+ (user admin)
(userprefix admin user)
)
+```
selinuxuser
-----------
@@ -375,7 +407,9 @@ Associates a GNU/Linux user to a previously declared [`user`](cil_user_statement
**Statement definition:**
+```secil
(selinuxuser user_name user_id userrange_id)
+```
**Where:**
@@ -408,10 +442,12 @@ Associates a GNU/Linux user to a previously declared [`user`](cil_user_statement
This example will associate `unconfined.admin` user with a GNU / Linux user "`admin_1`":
+```secil
(block unconfined
(user admin)
(selinuxuser admin_1 admin low_low)
)
+```
selinuxuserdefault
------------------
@@ -420,7 +456,9 @@ Declares the default SELinux user. Only one [`selinuxuserdefault`](cil_user_stat
**Statement definition:**
+```secil
(selinuxuserdefault user_id userrange_id)
+```
**Where:**
@@ -449,7 +487,9 @@ Declares the default SELinux user. Only one [`selinuxuserdefault`](cil_user_stat
This example will define the `unconfined.user` as the default SELinux user:
+```secil
(block unconfined
(user user)
(selinuxuserdefault user low_low)
)
+```
diff --git a/secilc/docs/cil_xen_statements.md b/secilc/docs/cil_xen_statements.md
index 5ae03e6e..3cfc5dd2 100644
--- a/secilc/docs/cil_xen_statements.md
+++ b/secilc/docs/cil_xen_statements.md
@@ -12,7 +12,9 @@ Label i/o memory. This may be a single memory location or a range.
**Statement definition:**
+```secil
(iomemcon mem_addr|(mem_low mem_high) context_id)
+```
**Where:**
@@ -43,7 +45,9 @@ Label i/o memory. This may be a single memory location or a range.
An anonymous context for a memory address range of `0xfebe0-0xfebff`:
+```secil
(iomemcon (1043424 1043455) (unconfined.user object_r unconfined.object low_low))
+```
ioportcon
---------
@@ -52,7 +56,9 @@ Label i/o ports. This may be a single port or a range.
**Statement definition:**
+```secil
(ioportcon port|(port_low port_high) context_id)
+```
**Where:**
@@ -83,7 +89,9 @@ Label i/o ports. This may be a single port or a range.
An anonymous context for a single port of :`0xecc0`:
+```secil
(ioportcon 60608 (unconfined.user object_r unconfined.object low_low))
+```
pcidevicecon
------------
@@ -92,7 +100,9 @@ Label a PCI device.
**Statement definition:**
+```secil
(pcidevicecon device context_id)
+```
**Where:**
@@ -121,7 +131,9 @@ Label a PCI device.
An anonymous context for a pci device address of `0xc800`:
+```secil
(pcidevicecon 51200 (unconfined.user object_r unconfined.object low_low))
+```
pirqcon
-------
@@ -130,7 +142,9 @@ Label an interrupt level.
**Statement definition:**
+```secil
(pirqcon irq_level context_id)
+```
**Where:**
@@ -159,7 +173,9 @@ Label an interrupt level.
An anonymous context for IRQ 33:
+```secil
(pirqcon 33 (unconfined.user object_r unconfined.object low_low))
+```
devicetreecon
-------------
@@ -168,7 +184,9 @@ Label device tree nodes.
**Statement definition:**
+```secil
(devicetreecon path context_id)
+```
**Where:**
@@ -197,4 +215,6 @@ Label device tree nodes.
An anonymous context for the specified path:
+```secil
(devicetreecon "/this is/a/path" (unconfined.user object_r unconfined.object low_low))
+```
diff --git a/secilc/docs/secil.xml b/secilc/docs/secil.xml
new file mode 100644
index 00000000..b015490d
--- /dev/null
+++ b/secilc/docs/secil.xml
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- https://docs.kde.org/trunk5/en/applications/katepart/highlight.html#katehighlight-xml-format -->
+<!DOCTYPE language SYSTEM "language.dtd">
+<language name="secil" section="Sources" extensions="*.cil" version="1" kateversion="2.4">
+ <!--
+ The keywords where extracted from libsepol/cil/src/cil.c sorted into the
+ right lists and sorted alphabetically
+ -->
+ <list name="keywords_blockstart">
+ <item>allow</item>
+ <item>allowx</item>
+ <item>auditallow</item>
+ <item>auditallowx</item>
+ <item>block</item>
+ <item>blockabstract</item>
+ <item>boolean</item>
+ <item>booleanif</item>
+ <item>category</item>
+ <item>categoryalias</item>
+ <item>categoryaliasactual</item>
+ <item>categoryorder</item>
+ <item>categoryset</item>
+ <item>class</item>
+ <item>classcommon</item>
+ <item>classmap</item>
+ <item>classmapping</item>
+ <item>classorder</item>
+ <item>classpermission</item>
+ <item>classpermissionset</item>
+ <item>common</item>
+ <item>constrain</item>
+ <item>context</item>
+ <item>defaultrange</item>
+ <item>defaultrole</item>
+ <item>defaulttype</item>
+ <item>defaultuser</item>
+ <item>devicetreecon</item>
+ <item>dontaudit</item>
+ <item>dontauditx</item>
+ <item>expandtypeattribute</item>
+ <item>false</item>
+ <item>filecon</item>
+ <item>fsuse</item>
+ <item>genfscon</item>
+ <item>handleunknown</item>
+ <item>ibendportcon</item>
+ <item>ibpkeycon</item>
+ <item>ioctl</item>
+ <item>iomemcon</item>
+ <item>ioportcon</item>
+ <item>ipaddr</item>
+ <item>level</item>
+ <item>levelrange</item>
+ <item>mls</item>
+ <item>mlsconstrain</item>
+ <item>mlsvalidatetrans</item>
+ <item>netifcon</item>
+ <item>neverallow</item>
+ <item>neverallowx</item>
+ <item>nodecon</item>
+ <item>optional</item>
+ <item>pcidevicecon</item>
+ <item>perm</item>
+ <item>permissionx</item>
+ <item>pirqcon</item>
+ <item>policycap</item>
+ <item>portcon</item>
+ <item>rangetransition</item>
+ <item>role</item>
+ <item>roleallow</item>
+ <item>roleattribute</item>
+ <item>roleattributeset</item>
+ <item>rolebounds</item>
+ <item>roletransition</item>
+ <item>roletype</item>
+ <item>selinuxuser</item>
+ <item>selinuxuserdefault</item>
+ <item>sensitivity</item>
+ <item>sensitivityalias</item>
+ <item>sensitivityaliasactual</item>
+ <item>sensitivitycategory</item>
+ <item>sensitivityorder</item>
+ <item>sid</item>
+ <item>sidcontext</item>
+ <item>sidorder</item>
+ <item>true</item>
+ <item>tunable</item>
+ <item>tunableif</item>
+ <item>type</item>
+ <item>typealias</item>
+ <item>typealiasactual</item>
+ <item>typeattribute</item>
+ <item>typeattributeset</item>
+ <item>typebounds</item>
+ <item>typechange</item>
+ <item>typemember</item>
+ <item>typepermissive</item>
+ <item>typetransition</item>
+ <item>unordered</item>
+ <item>user</item>
+ <item>userattribute</item>
+ <item>userattributeset</item>
+ <item>userbounds</item>
+ <item>userlevel</item>
+ <item>userprefix</item>
+ <item>userrange</item>
+ <item>userrole</item>
+ <item>validatetrans</item>
+ </list>
+
+ <list name="function">
+ <item>blockinherit</item>
+ <item>call</item>
+ <item>in</item>
+ <item>macro</item>
+ </list>
+
+ <list name="operators">
+ <item>and</item>
+ <item>dom</item>
+ <item>domby</item>
+ <item>eq</item>
+ <item>incomp</item>
+ <item>neq</item>
+ <item>not</item>
+ <item>or</item>
+ <item>range</item>
+ <item>xor</item>
+ </list>
+
+ <!-- list of "magic" functions or values -->
+ <list name="builtins">
+ <item>*</item>
+ <item>all</item>
+ <item>dccp</item>
+ <item>false</item>
+ <item>h1</item>
+ <item>h2</item>
+ <item>l1</item>
+ <item>l2</item>
+ <item>object_r</item>
+ <item>r1</item>
+ <item>r2</item>
+ <item>r3</item>
+ <item>sctp</item>
+ <item>self</item>
+ <item>t1</item>
+ <item>t2</item>
+ <item>t3</item>
+ <item>tcp</item>
+ <item>true</item>
+ <item>u1</item>
+ <item>u2</item>
+ <item>u3</item>
+ <item>udp</item>
+
+ <!--
+ Excluded because they lead to a lot of false-positives
+ <item>allow</item>
+ <item>any</item>
+ <item>char</item>
+ <item>deny</item>
+ <item>dir</item>
+ <item>file</item>
+ <item>glblub</item>
+ <item>high</item>
+ <item>low-high</item>
+ <item>low</item>
+ <item>pipe</item>
+ <item>reject</item>
+ <item>socket</item>
+ <item>source</item>
+ <item>symlink</item>
+ <item>target</item>
+ <item>task</item>
+ <item>trans</item>
+ <item>xattr</item>
+ -->
+ </list>
+ <highlighting>
+ <contexts>
+ <context name="Normal" attribute="Normal" lineEndContext="#stay">
+ <DetectChar attribute="Brackets" context="BlockStart" char="("/>
+
+ <DetectChar attribute="Comment" context="Comment" char=";"/>
+ </context>
+ <context name="BlockStart" attribute="Normal" lineEndContext="#stay">
+ <keyword attribute="Keyword" context="Block" String="keywords_blockstart"/>
+ <keyword attribute="Function" context="Block" String="function"/>
+ <keyword attribute="Operator" context="Block" String="operators"/>
+
+ <DetectChar attribute="Comment" context="Comment" char=";"/>
+ </context>
+ <context name="Block" attribute="Normal" lineEndContext="#stay">
+ <keyword attribute="Builtin" context="#stay" String="builtins"/>
+
+ <DetectChar attribute="Comment" context="Comment" char=";"/>
+ <DetectChar attribute="String" context="String" char="&quot;"/>
+
+ <DetectChar attribute="Brackets" context="BlockStart" char="("/>
+ <DetectChar attribute="Brackets" context="#pop" char=")"/>
+ </context>
+
+ <!-- single line comment -->
+ <context name="Comment" attribute="Comment" lineEndContext="#pop"></context>
+
+ <!-- string / name -->
+ <context name="String" attribute="String" lineEndContext="#stay">
+ <RegExpr attribute="Char" context="#stay" String="#\\."/>
+
+ <!-- allow escaping " or similar -->
+ <HlCStringChar attribute="String Char" context="#stay"/>
+
+ <DetectChar attribute="String" context="#pop" char="&quot;"/>
+ </context>
+ </contexts>
+ <itemDatas>
+ <itemData name="Normal" defStyleNum="dsNormal" />
+ <itemData name="Keyword" defStyleNum="dsKeyword"/>
+ <itemData name="Function" defStyleNum="dsFunction"/>
+ <itemData name="Operator" defStyleNum="dsOperator"/>
+ <itemData name="Builtin" defStyleNum="dsBuiltIn"/>
+
+ <itemData name="Comment" defStyleNum="dsComment"/>
+
+ <itemData name="String" defStyleNum="dsString"/>
+ <itemData name="String Char" defStyleNum="dsSpecialChar"/>
+ </itemDatas>
+ </highlighting>
+ <general>
+ <comments>
+ <comment name="singleLine" start=";"/>
+ </comments>
+ <keywords casesensitive="1" weakDeliminator="."/>
+ </general>
+</language>
diff --git a/secilc/docs/theme.theme b/secilc/docs/theme.theme
new file mode 100644
index 00000000..5ffa9a65
--- /dev/null
+++ b/secilc/docs/theme.theme
@@ -0,0 +1,59 @@
+{
+ "text-color": null,
+ "background-color": null,
+ "line-number-color": null,
+ "line-number-background-color": null,
+ "text-styles": {
+ "String": {
+ "text-color": "#049b0a",
+ "background-color": null,
+ "bold": false,
+ "italic": false,
+ "underline": false
+ },
+ "SpecialChar": {
+ "text-color": "#049b0a",
+ "background-color": null,
+ "bold": false,
+ "italic": false,
+ "underline": false
+ },
+
+ "Function": {
+ "text-color": "#ff9358",
+ "background-color": null,
+ "bold": true,
+ "italic": false,
+ "underline": false
+ },
+
+ "Operator": {
+ "text-color": "#43a8ed",
+ "background-color": null,
+ "bold": true,
+ "italic": false,
+ "underline": false
+ },
+ "BuiltIn": {
+ "text-color": "#ff6dd3",
+ "background-color": null,
+ "bold": true,
+ "italic": false,
+ "underline": false
+ },
+ "Comment": {
+ "text-color": "#bc7a00",
+ "background-color": null,
+ "bold": false,
+ "italic": true,
+ "underline": false
+ },
+ "Keyword": {
+ "text-color": "#28648e",
+ "background-color": null,
+ "bold": true,
+ "italic": false,
+ "underline": false
+ }
+ }
+}
diff --git a/secilc/secil2conf.8.xml b/secilc/secil2conf.8.xml
index 59d87a54..33646f97 100644
--- a/secilc/secil2conf.8.xml
+++ b/secilc/secil2conf.8.xml
@@ -51,6 +51,11 @@
</varlistentry>
<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>-v, --verbose</option></term>
<listitem><para>Increment verbosity level.</para></listitem>
</varlistentry>
diff --git a/secilc/secil2conf.c b/secilc/secil2conf.c
index 4e97dd66..c49522e5 100644
--- a/secilc/secil2conf.c
+++ b/secilc/secil2conf.c
@@ -52,6 +52,9 @@ static __attribute__((__noreturn__)) void usage(const char *prog)
printf(" This will override the (mls boolean) statement\n");
printf(" if present in the policy\n");
printf(" -P, --preserve-tunables treat tunables as booleans\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(" -v, --verbose increment verbosity level\n");
printf(" -h, --help display usage information\n");
exit(1);
@@ -68,6 +71,7 @@ int main(int argc, char *argv[])
struct cil_db *db = NULL;
int mls = -1;
int preserve_tunables = 0;
+ int qualified_names = 0;
int opt_char;
int opt_index = 0;
enum cil_log_level log_level = CIL_ERR;
@@ -76,13 +80,14 @@ int main(int argc, char *argv[])
{"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}
};
int i;
while (1) {
- opt_char = getopt_long(argc, argv, "o:hvM:P", long_opts, &opt_index);
+ opt_char = getopt_long(argc, argv, "o:hvM:PQ", long_opts, &opt_index);
if (opt_char == -1) {
break;
}
@@ -102,7 +107,11 @@ int main(int argc, char *argv[])
case 'P':
preserve_tunables = 1;
break;
+ case 'Q':
+ qualified_names = 1;
+ break;
case 'o':
+ free(output);
output = strdup(optarg);
break;
case 'h':
@@ -123,6 +132,7 @@ int main(int argc, char *argv[])
cil_db_init(&db);
cil_set_preserve_tunables(db, preserve_tunables);
+ cil_set_qualified_names(db, qualified_names);
cil_set_mls(db, mls);
cil_set_attrs_expand_generated(db, 0);
cil_set_attrs_expand_size(db, 0);
diff --git a/secilc/secil2tree.8.xml b/secilc/secil2tree.8.xml
new file mode 100644
index 00000000..e95a8947
--- /dev/null
+++ b/secilc/secil2tree.8.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML//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>SECIL2TREE</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="date">05 April 2021</refmiscinfo>
+ <refmiscinfo class="source">secil2tree</refmiscinfo>
+ <refmiscinfo class="manual">SELinux CIL AST Writer</refmiscinfo>
+ </refmeta>
+ <refnamediv id="name">
+ <refname>secil2tree</refname>
+ <refpurpose>invoke the SELinux Common Intermediate Language (CIL) AST Writer </refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv id="synopsis">
+ <cmdsynopsis>
+ <command>secil2tree</command>
+ <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg>
+ <arg choice="plain"><replaceable>file</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="description"><title>DESCRIPTION</title>
+ <para><emphasis role="italic">secil2tree</emphasis> invokes the CIL AST Writer with the specified <emphasis role="italic">argument</emphasis>s.</para>
+ </refsect1>
+
+ <refsect1 id="options"><title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>-o, --output=&lt;file></option></term>
+ <listitem><para>Write AST to <emphasis role="italic">file</emphasis> (default: stdout)</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-P, --preserve-tunables</option></term>
+ <listitem><para>Treat tunables as booleans.</para></listitem>
+ </varlistentry>
+
+ <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>-A, --ast-phase=&lt;phase></option></term>
+ <listitem><para>Write AST of phase <emphasis role="italic">phase</emphasis>. Must be <emphasis role="bold">parse</emphasis>, <emphasis role="bold">build</emphasis>, or <emphasis role="bold">resolve</emphasis>. (default: <emphasis role="bold">resolve</emphasis>)</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>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 --git a/secilc/secil2tree.c b/secilc/secil2tree.c
new file mode 100644
index 00000000..e5cdf6bd
--- /dev/null
+++ b/secilc/secil2tree.c
@@ -0,0 +1,215 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/stat.h>
+
+#ifdef ANDROID
+#include <cil/cil.h>
+#else
+#include <sepol/cil/cil.h>
+#endif
+#include <sepol/policydb.h>
+
+enum write_ast_phase {
+ WRITE_AST_PHASE_PARSE = 0,
+ WRITE_AST_PHASE_BUILD,
+ WRITE_AST_PHASE_RESOLVE,
+};
+
+static __attribute__((__noreturn__)) void usage(const char *prog)
+{
+ printf("Usage: %s [OPTION]... FILE...\n", prog);
+ printf("\n");
+ printf("Options:\n");
+ printf(" -o, --output=<file> write AST to <file>. (default: stdout)\n");
+ printf(" -P, --preserve-tunables treat tunables as booleans\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(" -A, --ast-phase=<phase> write AST of phase <phase>. Phase must be parse, \n");
+ printf(" build, or resolve. (default: resolve)\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;
+ FILE *file = NULL;
+ char *buffer = NULL;
+ struct stat filedata;
+ uint32_t file_size;
+ char *output = NULL;
+ struct cil_db *db = NULL;
+ int preserve_tunables = 0;
+ int qualified_names = 0;
+ enum write_ast_phase write_ast = WRITE_AST_PHASE_RESOLVE;
+ int opt_char;
+ 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}
+ };
+ int i;
+
+ while (1) {
+ 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 {
+ 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]);
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "No cil files specified\n");
+ usage(argv[0]);
+ }
+
+ cil_set_log_level(log_level);
+
+ cil_db_init(&db);
+ cil_set_preserve_tunables(db, preserve_tunables);
+ cil_set_qualified_names(db, qualified_names);
+ cil_set_attrs_expand_generated(db, 0);
+ cil_set_attrs_expand_size(db, 0);
+
+ for (i = optind; i < argc; i++) {
+ file = fopen(argv[i], "r");
+ if (!file) {
+ fprintf(stderr, "Could not open file: %s\n", argv[i]);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ rc = stat(argv[i], &filedata);
+ if (rc == -1) {
+ fprintf(stderr, "Could not stat file: %s\n", argv[i]);
+ goto exit;
+ }
+ file_size = filedata.st_size;
+
+ buffer = malloc(file_size);
+ rc = fread(buffer, file_size, 1, file);
+ if (rc != 1) {
+ fprintf(stderr, "Failure reading file: %s\n", argv[i]);
+ goto exit;
+ }
+ fclose(file);
+ file = NULL;
+
+ rc = cil_add_file(db, argv[i], buffer, file_size);
+ if (rc != SEPOL_OK) {
+ fprintf(stderr, "Failure adding %s\n", argv[i]);
+ goto exit;
+ }
+
+ free(buffer);
+ buffer = NULL;
+ }
+
+ if (output == NULL) {
+ file = stdout;
+ } else {
+ file = fopen(output, "w");
+ if (file == NULL) {
+ fprintf(stderr, "Failure opening file %s for writing\n", output);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
+
+ switch (write_ast) {
+ case WRITE_AST_PHASE_PARSE:
+ rc = cil_write_parse_ast(file, db);
+ break;
+ case WRITE_AST_PHASE_BUILD:
+ rc = cil_write_build_ast(file, db);
+ break;
+ case WRITE_AST_PHASE_RESOLVE:
+ rc = cil_write_resolve_ast(file, db);
+ break;
+ }
+
+ if (rc != SEPOL_OK) {
+ fprintf(stderr, "Failed to write AST\n");
+ goto exit;
+ }
+
+exit:
+ if (file != NULL && file != stdin) {
+ fclose(file);
+ }
+ free(buffer);
+ free(output);
+ cil_db_destroy(&db);
+ return rc;
+}
diff --git a/secilc/secilc.8.xml b/secilc/secilc.8.xml
index 2b734f09..e9a121e2 100644
--- a/secilc/secilc.8.xml
+++ b/secilc/secilc.8.xml
@@ -76,6 +76,11 @@
</varlistentry>
<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>
diff --git a/secilc/secilc.c b/secilc/secilc.c
index 9c78e425..80d3583d 100644
--- a/secilc/secilc.c
+++ b/secilc/secilc.c
@@ -63,6 +63,9 @@ static __attribute__((__noreturn__)) void usage(const char *prog)
printf(" statement if present in the policy\n");
printf(" -D, --disable-dontaudit do not add dontaudit rules to the binary policy\n");
printf(" -P, --preserve-tunables treat tunables as booleans\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(" -N, --disable-neverallow do not check neverallow rules\n");
printf(" -G, --expand-generated Expand and remove auto-generated attributes\n");
@@ -94,6 +97,7 @@ int main(int argc, char *argv[])
int multiple_decls = 0;
int disable_neverallow = 0;
int preserve_tunables = 0;
+ int qualified_names = 0;
int handle_unknown = -1;
int policyvers = POLICYDB_VERSION_MAX;
int attrs_expand_generated = 0;
@@ -115,6 +119,7 @@ int main(int argc, char *argv[])
{"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'},
@@ -125,7 +130,7 @@ int main(int argc, char *argv[])
int i;
while (1) {
- opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDmNOc: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;
}
@@ -190,10 +195,15 @@ int main(int argc, char *argv[])
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':
@@ -238,6 +248,7 @@ int main(int argc, char *argv[])
cil_set_multiple_decls(db, multiple_decls);
cil_set_disable_neverallow(db, disable_neverallow);
cil_set_preserve_tunables(db, preserve_tunables);
+ cil_set_qualified_names(db, qualified_names);
if (handle_unknown != -1) {
rc = cil_set_handle_unknown(db, handle_unknown);
if (rc != SEPOL_OK) {
diff --git a/secilc/test/anonymous_arg_test.cil b/secilc/test/anonymous_arg_test.cil
new file mode 100644
index 00000000..46f8ce73
--- /dev/null
+++ b/secilc/test/anonymous_arg_test.cil
@@ -0,0 +1,106 @@
+;; Test anonymous args
+
+(mls true)
+(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))))
+
+(category c0)
+(category c1)
+(category c2)
+(category c3)
+(categoryorder (CAT c0 c1 c2 c3))
+(categoryset cs01 (c0 c1))
+(categoryset cs03 (range c0 c3))
+
+(sensitivity s0)
+(sensitivity s1)
+(sensitivity s2)
+(sensitivity s3)
+(sensitivityorder (SENS s0 s1 s2 s3))
+
+(sensitivitycategory s0 (cs01 c2 c3))
+(sensitivitycategory s1 (c0 c1 c2 c3))
+(sensitivitycategory s2 (c0 c1 c2 c3))
+(sensitivitycategory s3 (range c0 c3))
+
+(level lvl (s0 (c0)))
+(level lvl0 (s0))
+(level lvl3 (s3 (range c0 c3)))
+
+(levelrange rng ((s0) (s3 (c0 c1 c2 c3))))
+
+(user u1)
+(user u2)
+(user u3)
+(user u4)
+
+(userrole u1 ROLE)
+(userrole u2 ROLE)
+(userrole u3 ROLE)
+(userrole u4 ROLE)
+
+; Test categoryset
+(macro m1 ((user u)(sensitivity s)(categoryset cs))
+ (userlevel u (s (cs)))
+)
+(call m1 (u1 s1 (c0 c1)))
+(call m1 (u2 s2 cs01))
+
+; Test level
+(macro m2 ((user u)(level l))
+ (userlevel u l)
+)
+(call m2 (u3 (s3 (c2))))
+(call m2 (u4 lvl))
+
+; Test levelrange
+(macro m3 ((user u)(levelrange lr))
+ (userrange u lr)
+)
+(call m3 (u1 ((s0) (s3 (range c0 c3)))))
+(call m3 (u2 (lvl0 (s3 (cs03)))))
+(call m3 (u3 (lvl0 lvl3)))
+(call m3 (u4 rng))
+
+; Test ipaddr
+(macro m4 ((user u)(ipaddr nm)(ipaddr ip))
+ (nodecon ip nm (u ROLE TYPE ((s0) (s0))))
+)
+(ipaddr nm1 255.255.255.0)
+(ipaddr ip4 1.2.3.4)
+(call m4 (u1 nm1 192.25.35.200))
+(call m4 (u2 255.255.255.0 ip4))
+
+; Test classpermission
+(type t1)
+(type t2)
+(type t3)
+
+(classpermission cp1)
+(classpermissionset cp1 (CLASS (PERM)))
+
+(classmap cm1 (cm1p))
+(classmapping cm1 cm1p (CLASS (PERM)))
+
+(macro m5 ((type t)(classpermission cp))
+ (allow t self cp)
+)
+(call m5 (t1 (CLASS (PERM))))
+(call m5 (t2 cp1))
+(call m5 (t3 (cm1 (cm1p))))
diff --git a/secilc/test/block_test.cil b/secilc/test/block_test.cil
index 2dfcb899..2dd30c23 100644
--- a/secilc/test/block_test.cil
+++ b/secilc/test/block_test.cil
@@ -84,7 +84,7 @@
)
-;; Inherting the abstract block causes the allow rule to be in the policy
+;; Inheriting the abstract block causes the allow rule to be in the policy
(type t5)
(block b5
(blockabstract b5)
diff --git a/secilc/test/opt-expected.cil b/secilc/test/opt-expected.cil
new file mode 100644
index 00000000..14033f9b
--- /dev/null
+++ b/secilc/test/opt-expected.cil
@@ -0,0 +1,60 @@
+(handleunknown deny)
+(class cl01 (p01a p01b p11a p11b))
+(classorder (cl01))
+(sid kernel)
+(sidorder (kernel))
+(mls true)
+(sensitivity s01)
+(sensitivityorder (s01))
+(category c01)
+(categoryorder (c01))
+(sensitivitycategory s01 (c01))
+(typeattribute at01)
+(typeattribute at02)
+(boolean b01 false)
+(type tp01)
+(type tp02)
+(type tp04)
+(type tpr1)
+(type tpr2)
+(type tpr3)
+(type tpr4)
+(type tpr5)
+(typeattributeset at01 (tp01))
+(typeattributeset at02 (tp01 tp02))
+(allow at02 tpr1 (cl01 (p01a p01b p11a)))
+(allow at02 tpr3 (cl01 (p01a p01b p11a)))
+(allow tp01 at01 (cl01 (p11b)))
+(allow tp01 self (cl01 (p01a p01b p11a)))
+(allow tp01 tpr1 (cl01 (p11b)))
+(dontaudit at02 tpr2 (cl01 (p01a p01b p11a)))
+(dontaudit at02 tpr4 (cl01 (p01a p01b p11a)))
+(dontaudit tp01 tpr2 (cl01 (p11b)))
+(booleanif b01
+ (true
+ (allow tp01 tpr3 (cl01 (p11b)))
+ (allow tp01 tpr5 (cl01 (p01a p01b p11a p11b)))
+ (allow tp02 tpr5 (cl01 (p01a p11a)))
+ (dontaudit tp01 tpr4 (cl01 (p11b)))
+ )
+ (false
+ (allow at02 tpr5 (cl01 (p01a p01b p11a)))
+ )
+)
+(role object_r)
+(role rl01)
+(roletype rl01 tp01)
+(roletype object_r tp01)
+(roletype object_r tp02)
+(roletype object_r tp04)
+(roletype object_r tpr1)
+(roletype object_r tpr2)
+(roletype object_r tpr3)
+(roletype object_r tpr4)
+(roletype object_r tpr5)
+(user us01)
+(userrole us01 object_r)
+(userrole us01 rl01)
+(userlevel us01 (s01))
+(userrange us01 ((s01) (s01)))
+(sidcontext kernel (us01 rl01 tp01 ((s01) (s01))))
diff --git a/secilc/test/opt-input.cil b/secilc/test/opt-input.cil
new file mode 100644
index 00000000..5bb6c266
--- /dev/null
+++ b/secilc/test/opt-input.cil
@@ -0,0 +1,65 @@
+(handleunknown deny)
+(class cl01 (p01a p01b p11a p11b))
+(classorder (cl01))
+(sid kernel)
+(sidorder (kernel))
+(mls true)
+(sensitivity s01)
+(sensitivityorder (s01))
+(category c01)
+(categoryorder (c01))
+(sensitivitycategory s01 (c01))
+(typeattribute at01)
+(typeattribute at02)
+(boolean b01 false)
+(type tp01)
+(type tp02)
+(type tp04)
+(type tpr1)
+(type tpr2)
+(type tpr3)
+(type tpr4)
+(type tpr5)
+(typeattributeset at01 (tp01))
+(typeattributeset at02 (tp01 tp02))
+(allow at02 tpr1 (cl01 (p11a p01a p01b)))
+(allow at02 tpr3 (cl01 (p11a p01a p01b)))
+(allow tp01 at01 (cl01 (p11b)))
+(allow tp01 self (cl01 (p11a p01a)))
+(allow tp01 tp01 (cl01 (p01b)))
+(allow tp01 tpr1 (cl01 (p11a p11b p01a p01b)))
+(allow tp02 tpr1 (cl01 (p11a p01a)))
+(dontaudit at02 tpr2 (cl01 (p11a p01a p01b)))
+(dontaudit at02 tpr4 (cl01 (p11a p01a p01b)))
+(dontaudit tp01 tpr2 (cl01 (p11a p11b p01a p01b)))
+(dontaudit tp02 tpr2 (cl01 (p11a p01a)))
+(booleanif (b01)
+ (true
+ (allow tp01 tpr3 (cl01 (p11a p11b p01a p01b)))
+ (allow tp01 tpr5 (cl01 (p11a p11b p01a p01b)))
+ (allow tp02 tpr3 (cl01 (p11a p01a)))
+ (allow tp02 tpr5 (cl01 (p11a p01a)))
+ (dontaudit tp01 tpr4 (cl01 (p11a p11b p01a p01b)))
+ (dontaudit tp02 tpr4 (cl01 (p11a p01a)))
+ )
+ (false
+ (allow at02 tpr5 (cl01 (p11a p01a p01b)))
+ )
+)
+(role object_r)
+(role rl01)
+(roletype rl01 tp01)
+(roletype object_r tp01)
+(roletype object_r tp02)
+(roletype object_r tp04)
+(roletype object_r tpr1)
+(roletype object_r tpr2)
+(roletype object_r tpr3)
+(roletype object_r tpr4)
+(roletype object_r tpr5)
+(user us01)
+(userrole us01 object_r)
+(userrole us01 rl01)
+(userlevel us01 (s01))
+(userrange us01 ((s01) (s01)))
+(sidcontext kernel (us01 rl01 tp01 ((s01) (s01))))
diff --git a/semodule-utils/VERSION b/semodule-utils/VERSION
index 9f55b2cc..eb39e538 100644
--- a/semodule-utils/VERSION
+++ b/semodule-utils/VERSION
@@ -1 +1 @@
-3.0
+3.3