summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2013-02-18 16:12:34 -0800
committerJohn Johansen <john.johansen@canonical.com>2013-04-28 00:37:32 -0700
commited686308c6837ff67f56e4115d0fd6bdc65a4313 (patch)
treef883525ee2c10d846c0f9f4c6fcb01208bee5a26
parent4da05cc08da3f2058cecbe42ed9f4803d669730a (diff)
apparmor: reserve and mask off the top 8 bits of the base field
The top 8 bits of the base field have never been used, in fact can't be used, by the current 'dfa16' format. However they will be used in the future as flags, so mask them off when using base as an index value. Note: the use of the top 8 bits, without masking is trapped by the verify checks that base entries are within the size bounds. Signed-off-by: John Johansen <john.johansen@canonical.com> Acked-by: Kees Cook <kees@ubuntu.com>
-rw-r--r--security/apparmor/match.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 1ff823031c73..727eb4200d5c 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -23,6 +23,8 @@
#include "include/apparmor.h"
#include "include/match.h"
+#define base_idx(X) ((X) & 0xffffff)
+
/**
* unpack_table - unpack a dfa table (one of accept, default, base, next check)
* @blob: data to unpack (NOT NULL)
@@ -137,7 +139,7 @@ static int verify_dfa(struct aa_dfa *dfa, int flags)
for (i = 0; i < state_count; i++) {
if (DEFAULT_TABLE(dfa)[i] >= state_count)
goto out;
- if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
+ if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) {
printk(KERN_ERR "AppArmor DFA next/check upper "
"bounds error\n");
goto out;
@@ -313,7 +315,7 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
u8 *equiv = EQUIV_TABLE(dfa);
/* default is direct to next state */
for (; len; len--) {
- pos = base[state] + equiv[(u8) *str++];
+ pos = base_idx(base[state]) + equiv[(u8) *str++];
if (check[pos] == state)
state = next[pos];
else
@@ -322,7 +324,7 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
} else {
/* default is direct to next state */
for (; len; len--) {
- pos = base[state] + (u8) *str++;
+ pos = base_idx(base[state]) + (u8) *str++;
if (check[pos] == state)
state = next[pos];
else
@@ -363,7 +365,7 @@ unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
u8 *equiv = EQUIV_TABLE(dfa);
/* default is direct to next state */
while (*str) {
- pos = base[state] + equiv[(u8) *str++];
+ pos = base_idx(base[state]) + equiv[(u8) *str++];
if (check[pos] == state)
state = next[pos];
else
@@ -372,7 +374,7 @@ unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
} else {
/* default is direct to next state */
while (*str) {
- pos = base[state] + (u8) *str++;
+ pos = base_idx(base[state]) + (u8) *str++;
if (check[pos] == state)
state = next[pos];
else
@@ -408,14 +410,14 @@ unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
u8 *equiv = EQUIV_TABLE(dfa);
/* default is direct to next state */
- pos = base[state] + equiv[(u8) c];
+ pos = base_idx(base[state]) + equiv[(u8) c];
if (check[pos] == state)
state = next[pos];
else
state = def[state];
} else {
/* default is direct to next state */
- pos = base[state] + (u8) c;
+ pos = base_idx(base[state]) + (u8) c;
if (check[pos] == state)
state = next[pos];
else