diff options
author | John Johansen <john.johansen@canonical.com> | 2017-12-12 10:02:13 +0100 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2018-02-09 20:30:01 +0100 |
commit | 3dc6b1ce6861ebf40b68ab4b752a05584a1f99bf (patch) | |
tree | 243c6b0514015415805b60cd183ea9e25ac0747b /security | |
parent | security: apparmor: remove duplicate includes (diff) | |
download | linux-3dc6b1ce6861ebf40b68ab4b752a05584a1f99bf.tar.xz linux-3dc6b1ce6861ebf40b68ab4b752a05584a1f99bf.zip |
apparmor: make signal label match work when matching stacked labels
Given a label with a profile stack of
A//&B or A//&C ...
A ptrace rule should be able to specify a generic trace pattern with
a rule like
signal send A//&**,
however this is failing because while the correct label match routine
is called, it is being done post label decomposition so it is always
being done against a profile instead of the stacked label.
To fix this refactor the cross check to pass the full peer label in to
the label_match.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/ipc.c | 40 |
1 files changed, 12 insertions, 28 deletions
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index 586facd35f7c..754f2ff8d355 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -184,50 +184,34 @@ static void audit_signal_cb(struct audit_buffer *ab, void *va) FLAGS_NONE, GFP_ATOMIC); } -/* TODO: update to handle compound name&name2, conditionals */ -static void profile_match_signal(struct aa_profile *profile, const char *label, - int signal, struct aa_perms *perms) -{ - unsigned int state; - - /* TODO: secondary cache check <profile, profile, perm> */ - state = aa_dfa_next(profile->policy.dfa, - profile->policy.start[AA_CLASS_SIGNAL], - signal); - state = aa_dfa_match(profile->policy.dfa, state, label); - aa_compute_perms(profile->policy.dfa, state, perms); -} - static int profile_signal_perm(struct aa_profile *profile, - struct aa_profile *peer, u32 request, + struct aa_label *peer, u32 request, struct common_audit_data *sa) { struct aa_perms perms; + unsigned int state; if (profile_unconfined(profile) || !PROFILE_MEDIATES(profile, AA_CLASS_SIGNAL)) return 0; - aad(sa)->peer = &peer->label; - profile_match_signal(profile, peer->base.hname, aad(sa)->signal, - &perms); + aad(sa)->peer = peer; + /* TODO: secondary cache check <profile, profile, perm> */ + state = aa_dfa_next(profile->policy.dfa, + profile->policy.start[AA_CLASS_SIGNAL], + aad(sa)->signal); + aa_label_match(profile, peer, state, false, request, &perms); aa_apply_modes_to_perms(profile, &perms); return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); } -static int aa_signal_cross_perm(struct aa_profile *sender, - struct aa_profile *target, - struct common_audit_data *sa) -{ - return xcheck(profile_signal_perm(sender, target, MAY_WRITE, sa), - profile_signal_perm(target, sender, MAY_READ, sa)); -} - int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig) { + struct aa_profile *profile; DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SIGNAL); aad(&sa)->signal = map_signal_num(sig); - return xcheck_labels_profiles(sender, target, aa_signal_cross_perm, - &sa); + return xcheck_labels(sender, target, profile, + profile_signal_perm(profile, target, MAY_WRITE, &sa), + profile_signal_perm(profile, sender, MAY_READ, &sa)); } |