mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
apparmor: convert duplicated dfa transitions to match_char()
For historical reasons several matchers duplicate the dfa character transition instead of using match_char(). This is because aa_dfa_match_until() and aa_dfa_matchn_until() were written on a branch that did not yet have match_char(), and copied code from aa_dfa_match(). leftmatch_fb() used the same pattern. When match_char() added support for diff-encoded states, the change was never ported to these copies. match_char() resolves a diff encoded state by using def[state] and retrying the same character, until it reaches a state with a valid transition. The copies instead do a simple `state = def[state];` after the character is consumed, so on a diff encoded state one byte is dropped and the walk continues from the diff parent in the wrong state. This makes an unnamed px/Px/cx/Cx transition resolve to no profile, and exec fails with apparmor="DENIED" operation="exec" info="profile transition not found" Convert the three copies to match_char(). For a dfa with no diff encoded state this is a no-op. This bug is latent until the kernel advertises policy/diff-encode. Closes: https://gitlab.com/apparmor/apparmor/-/work_items/663 Fixes:21f6066105("apparmor: improve overlapping domain attachment resolution") Fixes:031dcc8f4e("apparmor: dfa add support for state differential encoding") Signed-off-by: Maxime Bélair <maxime.belair@canonical.com> Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
449195a4bb
commit
e667fc72f7
|
|
@ -617,7 +617,7 @@ aa_state_t aa_dfa_match_until(const struct aa_dfa *dfa, aa_state_t start,
|
|||
u32 *next = NEXT_TABLE(dfa);
|
||||
u32 *check = CHECK_TABLE(dfa);
|
||||
u32 *accept = ACCEPT_TABLE(dfa);
|
||||
aa_state_t state = start, pos;
|
||||
aa_state_t state = start;
|
||||
|
||||
if (state == DFA_NOMATCH)
|
||||
return DFA_NOMATCH;
|
||||
|
|
@ -628,22 +628,18 @@ aa_state_t aa_dfa_match_until(const struct aa_dfa *dfa, aa_state_t start,
|
|||
u8 *equiv = EQUIV_TABLE(dfa);
|
||||
/* default is direct to next state */
|
||||
while (*str) {
|
||||
pos = base_idx(base[state]) + equiv[(u8) *str++];
|
||||
if (check[pos] == state)
|
||||
state = next[pos];
|
||||
else
|
||||
state = def[state];
|
||||
u8 c = equiv[(u8) *str++];
|
||||
|
||||
match_char(state, def, base, next, check, c);
|
||||
if (accept[state])
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* default is direct to next state */
|
||||
while (*str) {
|
||||
pos = base_idx(base[state]) + (u8) *str++;
|
||||
if (check[pos] == state)
|
||||
state = next[pos];
|
||||
else
|
||||
state = def[state];
|
||||
u8 c = (u8) *str++;
|
||||
|
||||
match_char(state, def, base, next, check, c);
|
||||
if (accept[state])
|
||||
break;
|
||||
}
|
||||
|
|
@ -678,7 +674,7 @@ aa_state_t aa_dfa_matchn_until(const struct aa_dfa *dfa, aa_state_t start,
|
|||
u32 *next = NEXT_TABLE(dfa);
|
||||
u32 *check = CHECK_TABLE(dfa);
|
||||
u32 *accept = ACCEPT_TABLE(dfa);
|
||||
aa_state_t state = start, pos;
|
||||
aa_state_t state = start;
|
||||
|
||||
*retpos = NULL;
|
||||
if (state == DFA_NOMATCH)
|
||||
|
|
@ -690,22 +686,18 @@ aa_state_t aa_dfa_matchn_until(const struct aa_dfa *dfa, aa_state_t start,
|
|||
u8 *equiv = EQUIV_TABLE(dfa);
|
||||
/* default is direct to next state */
|
||||
for (; n; n--) {
|
||||
pos = base_idx(base[state]) + equiv[(u8) *str++];
|
||||
if (check[pos] == state)
|
||||
state = next[pos];
|
||||
else
|
||||
state = def[state];
|
||||
u8 c = equiv[(u8) *str++];
|
||||
|
||||
match_char(state, def, base, next, check, c);
|
||||
if (accept[state])
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* default is direct to next state */
|
||||
for (; n; n--) {
|
||||
pos = base_idx(base[state]) + (u8) *str++;
|
||||
if (check[pos] == state)
|
||||
state = next[pos];
|
||||
else
|
||||
state = def[state];
|
||||
u8 c = (u8) *str++;
|
||||
|
||||
match_char(state, def, base, next, check, c);
|
||||
if (accept[state])
|
||||
break;
|
||||
}
|
||||
|
|
@ -754,7 +746,7 @@ static aa_state_t leftmatch_fb(const struct aa_dfa *dfa, aa_state_t start,
|
|||
u32 *base = BASE_TABLE(dfa);
|
||||
u32 *next = NEXT_TABLE(dfa);
|
||||
u32 *check = CHECK_TABLE(dfa);
|
||||
aa_state_t state = start, pos;
|
||||
aa_state_t state = start;
|
||||
|
||||
AA_BUG(!dfa);
|
||||
AA_BUG(!str);
|
||||
|
|
@ -772,13 +764,10 @@ static aa_state_t leftmatch_fb(const struct aa_dfa *dfa, aa_state_t start,
|
|||
/* default is direct to next state */
|
||||
while (*str) {
|
||||
unsigned int adjust;
|
||||
u8 c = equiv[(u8) *str++];
|
||||
|
||||
wb->history[wb->pos] = state;
|
||||
pos = base_idx(base[state]) + equiv[(u8) *str++];
|
||||
if (check[pos] == state)
|
||||
state = next[pos];
|
||||
else
|
||||
state = def[state];
|
||||
match_char(state, def, base, next, check, c);
|
||||
if (is_loop(wb, state, &adjust)) {
|
||||
state = aa_dfa_match(dfa, state, str);
|
||||
*count -= adjust;
|
||||
|
|
@ -791,13 +780,10 @@ static aa_state_t leftmatch_fb(const struct aa_dfa *dfa, aa_state_t start,
|
|||
/* default is direct to next state */
|
||||
while (*str) {
|
||||
unsigned int adjust;
|
||||
u8 c = (u8) *str++;
|
||||
|
||||
wb->history[wb->pos] = state;
|
||||
pos = base_idx(base[state]) + (u8) *str++;
|
||||
if (check[pos] == state)
|
||||
state = next[pos];
|
||||
else
|
||||
state = def[state];
|
||||
match_char(state, def, base, next, check, c);
|
||||
if (is_loop(wb, state, &adjust)) {
|
||||
state = aa_dfa_match(dfa, state, str);
|
||||
*count -= adjust;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user