UBUNTU: SAUCE: apparmor4.0.0 [66/90]: prompt - add support for advanced filtering of notifications

BugLink: http://bugs.launchpad.net/bugs/2028253

Simple filtering based off of type (ALLOWED, DENIED, ...) is
insufficient for several user cases.

Allow for a dfa based filter that can be combined with type
to further screen notifications to specific labels, classes
of mediation and even the permission request.

BugLink: http://bugs.launchpad.net/bugs/2032602
Signed-off-by: John Johansen <john.johansen@canonical.com>
(cherry picked from https://gitlab.com/jjohansen/apparmor-kernel)
Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
(cherry picked from commit 60b7d6660330beee97539ed233854a81f30aabd2
https://git.launchpad.net/~apparmor-dev/ubuntu-kernel-next)
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
This commit is contained in:
John Johansen
2023-08-22 09:27:57 -07:00
committed by Paolo Pisati
parent 285748e335
commit 177a32ef2d
3 changed files with 57 additions and 9 deletions
+24 -6
View File
@@ -652,14 +652,15 @@ static long notify_set_filter(struct aa_listener *listener,
return -EFAULT;
if (size < sizeof(unotif))
return -EINVAL;
/* todo upper limit on allocation size */
/* size is capped at U16_MAX by data type */
unotif = kzalloc(size, GFP_KERNEL);
if (!unotif)
return -ENOMEM;
if (copy_from_user(unotif, buf, size))
return -EFAULT;
if (copy_from_user(unotif, buf, size)) {
ret = -EFAULT;
goto out;
}
ret = size;
/* todo validate to known modes */
@@ -668,11 +669,28 @@ static long notify_set_filter(struct aa_listener *listener,
if (unotif->ns)
/* todo */
ns = NULL;
if (unotif->filter)
; /* todo */
if (unotif->filter) {
struct aa_dfa *dfa;
void *pos = (void *) unotif + unotif->filter;
if (unotif->filter >= size ||
ALIGN((size_t) pos, 8) != (size_t)pos) {
ret = -EINVAL;
goto out;
}
dfa = aa_dfa_unpack(pos, size - ((void *) unotif - pos),
DFA_FLAG_VERIFY_STATES |
TO_ACCEPT1_FLAG(YYTD_DATA32));
if (IS_ERR(dfa)) {
ret = PTR_ERR(dfa);
goto out;
}
listener->filter = dfa;
}
if (!aa_register_listener_proxy(listener, ns))
ret = -ENOMEM;
out:
kfree(unotif);
return ret;
+8
View File
@@ -118,6 +118,14 @@ static inline aa_state_t aa_dfa_null_transition(struct aa_dfa *dfa,
return aa_dfa_next(dfa, start, 0);
}
static inline aa_state_t aa_dfa_match_u16(struct aa_dfa *dfa, aa_state_t state,
u16 data)
{
__be16 buffer = cpu_to_be16(data);
return aa_dfa_match_len(dfa, state, (char *) &buffer, 2);
}
static inline bool path_mediated_fs(struct dentry *dentry)
{
return !(dentry->d_sb->s_flags & SB_NOUSER);
+25 -3
View File
@@ -357,16 +357,38 @@ struct aa_knotif *__del_and_hold_user_pending(struct aa_listener *listener,
*/
/* TODO: allow registering on multiple namespaces */
/* TODO: make filter access read side lockless */
static bool notification_match(struct aa_listener *listener,
struct aa_audit_node *ad)
{
if (!(listener->mask & (1 << ad->data.type)))
return false;
if (!listener->filter)
return true;
if (listener->filter) {
aa_state_t state;
unsigned int mask;
AA_DEBUG(DEBUG_UPCALL, "using filter");
if (!aa_ns_visible(listener->ns, labels_ns(ad->data.subj_label),
false))
return false;
state = aa_dfa_next(listener->filter, DFA_START, ad->data.type);
state = aa_dfa_match(listener->filter, state, ad->data.subj_label->hname);
if (!state)
return false;
state = aa_dfa_null_transition(listener->filter, state);
state = aa_dfa_match_u16(listener->filter, state, ad->data.class);
mask = ACCEPT_TABLE(listener->filter)[state];
if (ad->data.request & mask)
return true;
/* allow for enhanced match conditions in the future
* if (mask & AA_MATCH_CONT) {
* // TODO: match extensions
* }
*/
return false;
}
AA_DEBUG(DEBUG_UPCALL, "matched type mask filter");
return true;
}