From a9494f55238da46afe84d6fdbcd5ffecfd3b3509 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Mon, 21 Aug 2023 11:51:42 -0700 Subject: [PATCH] parser: add kill.signal=XXX flag support Add a flag that allows setting the signal used to kill the process. This should not be normally used but can be very useful when debugging applications, interaction with apparmor. Signed-off-by: John Johansen --- parser/apparmor.d.pod | 5 ++++- parser/parser.h | 1 + parser/parser_common.c | 1 + parser/parser_interface.c | 4 ++++ parser/parser_main.c | 3 +++ parser/profile.cc | 5 +++++ parser/profile.h | 20 +++++++++++++++++++ parser/signal.cc | 2 +- parser/signal.h | 1 + .../simple_tests/profile/flags/flags_bad67.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_bad68.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_bad69.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok40.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok41.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok42.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok43.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok44.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok45.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok46.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok47.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok48.sd | 10 ++++++++++ .../simple_tests/profile/flags/flags_ok49.sd | 12 +++++++++++ .../simple_tests/profile/flags/flags_ok50.sd | 12 +++++++++++ utils/test/test-parser-simple-tests.py | 3 +++ 24 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 parser/tst/simple_tests/profile/flags/flags_bad67.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_bad68.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_bad69.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok40.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok41.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok42.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok43.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok44.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok45.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok46.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok47.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok48.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok49.sd create mode 100644 parser/tst/simple_tests/profile/flags/flags_ok50.sd diff --git a/parser/apparmor.d.pod b/parser/apparmor.d.pod index 235c0c7e1..d13a46371 100644 --- a/parser/apparmor.d.pod +++ b/parser/apparmor.d.pod @@ -115,7 +115,7 @@ B = [ 'flags=' ] '(' comma or white space separated list of B = I | I | 'mediate_deleted' | 'attach_disconnected' | 'attach_disconneced.path='I | 'chroot_relative' -| 'debug' | 'interruptible' +| 'debug' | 'interruptible' | 'kill.signal='I B = 'enforce' | 'complain' | 'kill' | 'unconfined' | 'prompt' @@ -508,6 +508,9 @@ to debug kernel or policy problems. =item B Enables interrupts for prompt upcall to userspace. +=item B=I This changes the signal that will be +sent by AppArmor when in kill mode or a kill rule has been violated. + =back =head2 Access Modes diff --git a/parser/parser.h b/parser/parser.h index f3f4ac165..7cb89a139 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -354,6 +354,7 @@ extern int features_supports_posix_mqueue; extern int features_supports_sysv_mqueue; extern int features_supports_io_uring; extern int features_supports_flag_interruptible; +extern int features_supports_flag_signal; extern int kernel_supports_oob; extern int conf_verbose; extern int conf_quiet; diff --git a/parser/parser_common.c b/parser/parser_common.c index c7aac5f90..ff245d057 100644 --- a/parser/parser_common.c +++ b/parser/parser_common.c @@ -83,6 +83,7 @@ int features_supports_posix_mqueue = 0; /* kernel supports mqueue rules */ int features_supports_sysv_mqueue = 0; /* kernel supports mqueue rules */ int features_supports_io_uring = 0; /* kernel supports io_uring rules */ int features_supports_flag_interruptible = 0; +int features_supports_flag_signal = 0; int kernel_supports_oob = 0; /* out of band transitions */ int conf_verbose = 0; int conf_quiet = 0; diff --git a/parser/parser_interface.c b/parser/parser_interface.c index c7e478f92..8dc65923a 100644 --- a/parser/parser_interface.c +++ b/parser/parser_interface.c @@ -426,6 +426,10 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile, "disconnected"); } + if (profile->flags.signal && features_supports_flag_signal) { + sd_write_name(buf, "kill"); + sd_write_uint32(buf, profile->flags.signal); + } sd_write_struct(buf, "flags"); /* used to be flags.debug, but that's no longer supported */ sd_write_uint32(buf, profile->flags.flags); diff --git a/parser/parser_main.c b/parser/parser_main.c index 62c364cfb..936017c12 100644 --- a/parser/parser_main.c +++ b/parser/parser_main.c @@ -954,6 +954,9 @@ void set_supported_features() features_supports_flag_interruptible = features_intersect(kernel_features, policy_features, "policy/profile/interruptible"); + features_supports_flag_signal = features_intersect(kernel_features, + policy_features, + "policy/profile/kill.signal"); } static bool do_print_cache_dir(aa_features *features, int dirfd, const char *path) diff --git a/parser/profile.cc b/parser/profile.cc index 111e9ae38..d82330f15 100644 --- a/parser/profile.cc +++ b/parser/profile.cc @@ -355,6 +355,11 @@ void Profile::post_parse_profile(void) flags.flags &= ~FLAG_INTERRUPTIBLE; } } + if (flags.signal) { + if (!features_supports_flag_signal) { + warn_once(name, "kill.signal not supported. Ignoring"); + } + } post_process_file_entries(this); post_process_rule_entries(this); } diff --git a/parser/profile.h b/parser/profile.h index 72be7ec71..3c8f2c1e3 100644 --- a/parser/profile.h +++ b/parser/profile.h @@ -23,6 +23,7 @@ #include "rule.h" #include "libapparmor_re/aare_rules.h" #include "network.h" +#include "signal.h" class Profile; @@ -124,6 +125,7 @@ public: int audit; int path; char *disconnected_path; + int signal; // stupid not constructor constructors void init(void) @@ -133,6 +135,7 @@ public: audit = 0; path = 0; disconnected_path = NULL; + signal = 0; } void init(const char *str) { @@ -166,6 +169,11 @@ public: /* TODO: make this a proper parse */ path |= PATH_ATTACH; disconnected_path = strdup(str + 25); + } else if (strncmp(str, "kill.signal=", 12) == 0) { + /* TODO: make this a proper parse */ + signal = find_signal_mapping(str + 12); + if (signal == -1) + yyerror("unknown signal specified for kill.signal=\'%s\'\n", str + 12); } else if (strcmp(str, "interruptible") == 0) { flags |= FLAG_INTERRUPTIBLE; } else { @@ -185,6 +193,8 @@ public: if (disconnected_path) os << ", attach_disconnected.path=" << disconnected_path; + if (signal) + os << ", kill.signal=" << signal; os << "\n"; return os; @@ -235,6 +245,16 @@ public: disconnected_path = rhs.disconnected_path; } } + if (rhs.signal) { + if (signal) { + if (signal != rhs.signal) { + yyerror(_("Profile flag kill.signal set to conflicting values: '%d' and '%d'"), signal, rhs.signal); + } + // same so do nothing + } else { + signal = rhs.signal; + } + } /* if we move to dupping disconnected_path will need to have * an assignment and copy constructor and a destructor diff --git a/parser/signal.cc b/parser/signal.cc index 09e144ba0..15fc5a17a 100644 --- a/parser/signal.cc +++ b/parser/signal.cc @@ -121,7 +121,7 @@ int parse_signal_perms(const char *str_perms, perms_t *perms, int fail) return parse_X_perms("signal", AA_VALID_SIGNAL_PERMS, str_perms, perms, fail); } -static int find_signal_mapping(const char *sig) +int find_signal_mapping(const char *sig) { if (strncmp("rtmin+", sig, 6) == 0) { char *end; diff --git a/parser/signal.h b/parser/signal.h index e5df3d2a7..4cb4411f9 100644 --- a/parser/signal.h +++ b/parser/signal.h @@ -31,6 +31,7 @@ typedef set Signals; +int find_signal_mapping(const char *sig); int parse_signal_perms(const char *str_perms, perms_t *perms, int fail); class signal_rule: public perms_rule_t { diff --git a/parser/tst/simple_tests/profile/flags/flags_bad67.sd b/parser/tst/simple_tests/profile/flags/flags_bad67.sd new file mode 100644 index 000000000..163f30bc1 --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_bad67.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure bad signal value +#=EXRESULT FAIL +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=0) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_bad68.sd b/parser/tst/simple_tests/profile/flags/flags_bad68.sd new file mode 100644 index 000000000..03a617a1a --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_bad68.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure bad signal value +#=EXRESULT FAIL +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=foo) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_bad69.sd b/parser/tst/simple_tests/profile/flags/flags_bad69.sd new file mode 100644 index 000000000..cb5a8a81d --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_bad69.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure bad signal value +#=EXRESULT FAIL +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=hup.) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok40.sd b/parser/tst/simple_tests/profile/flags/flags_ok40.sd new file mode 100644 index 000000000..6706655b2 --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok40.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure conflicting mode flags cause an error +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(prompt, kill.signal=hup) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok41.sd b/parser/tst/simple_tests/profile/flags/flags_ok41.sd new file mode 100644 index 000000000..8f1115468 --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok41.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure signal.kill works with different flags and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(enforce, kill.signal=kill) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok42.sd b/parser/tst/simple_tests/profile/flags/flags_ok42.sd new file mode 100644 index 000000000..3631b500e --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok42.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure kill.signal works with different flags and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=int, unconfined) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok43.sd b/parser/tst/simple_tests/profile/flags/flags_ok43.sd new file mode 100644 index 000000000..daf788f4b --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok43.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure kill.signal works with different modes and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=quit, kill) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok44.sd b/parser/tst/simple_tests/profile/flags/flags_ok44.sd new file mode 100644 index 000000000..4dae342a8 --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok44.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure kill.signal works with different modes and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=hup, complain) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok45.sd b/parser/tst/simple_tests/profile/flags/flags_ok45.sd new file mode 100644 index 000000000..507d612db --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok45.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure kill.signal works with different modes and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=ill, enforce) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok46.sd b/parser/tst/simple_tests/profile/flags/flags_ok46.sd new file mode 100644 index 000000000..d3bf3f40b --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok46.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure kill.signal works with different modes and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill, kill.signal=trap) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok47.sd b/parser/tst/simple_tests/profile/flags/flags_ok47.sd new file mode 100644 index 000000000..55fc7341f --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok47.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure kill.signal works with different modes and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(complain, kill.signal=bus) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok48.sd b/parser/tst/simple_tests/profile/flags/flags_ok48.sd new file mode 100644 index 000000000..f54c492eb --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok48.sd @@ -0,0 +1,10 @@ +# +#=DESCRIPTION Ensure kill.signal works with different flags and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(enforce, kill.signal=usr1) { + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok49.sd b/parser/tst/simple_tests/profile/flags/flags_ok49.sd new file mode 100644 index 000000000..dec0314b3 --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok49.sd @@ -0,0 +1,12 @@ +# +#=DESCRIPTION Ensure kill.signals works with different flags and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=stop audit) { + #include + + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/parser/tst/simple_tests/profile/flags/flags_ok50.sd b/parser/tst/simple_tests/profile/flags/flags_ok50.sd new file mode 100644 index 000000000..aa5629823 --- /dev/null +++ b/parser/tst/simple_tests/profile/flags/flags_ok50.sd @@ -0,0 +1,12 @@ +# +#=DESCRIPTION Ensure kill.signal works with different flags and signals +#=EXRESULT PASS +# vim:syntax=subdomain +# Last Modified: Sun Apr 17 19:44:44 2005 +# +/does/not/exist flags=(kill.signal=emt) { + #include + + /usr/X11R6/lib/lib*so* r, + /does/not/exist r, +} diff --git a/utils/test/test-parser-simple-tests.py b/utils/test/test-parser-simple-tests.py index a28e75bfa..33eec798c 100644 --- a/utils/test/test-parser-simple-tests.py +++ b/utils/test/test-parser-simple-tests.py @@ -167,6 +167,9 @@ exception_not_raised = ( 'profile/flags/flags_bad64.sd', 'profile/flags/flags_bad65.sd', 'profile/flags/flags_bad66.sd', + 'profile/flags/flags_bad67.sd', + 'profile/flags/flags_bad68.sd', + 'profile/flags/flags_bad69.sd', 'profile/flags/flags_bad_disconnected_path1.sd', 'profile/flags/flags_bad_disconnected_path2.sd', 'profile/flags/flags_bad_disconnected_path3.sd',