mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 00:14:44 +01:00
add ability to use out of band transitions
Currently the NULL character is used as an out of band transition for string/path elements. This works for them as the NULL character is not valid for this data. However this does not work for binary data that can contain a NULL character. So far we have only dealt with fixed length fields of binary data making the NULL separator either unnecessary. However binary data like in the xattr match and mount data field are variable length and can contain NULL characters. To deal with this add the ability to specify out of band transitions, that can only be triggered by code not input data. The out of band transition can be used to separate variable length data fields just as the NULL transition has been used to separate variable length strings. In the compressed hfa out of band transitions are expressed as a negative offset from the states base. This leaves us room to expand the character match range in the future if desired and on average makes the range between the out of band transition and the input transitions smaller than would be had if the out of band transition had been stored after the valid input transitions. Out of band transitions in the dfa will not break old kernels that don't know about them, but they won't be able to trigger the out of band transition match. So they should not be used unless the kernel indicates that it supports them. It should be noted that this patch only adds support for a single out of band transition. If multiple out of band transitions are required. It is trivial to extend. - Add a tag indicating support in the kernel - add a oob max range field to the dfa header so the kernel knows what the max range that needs verifying is. - extend oob generation fns to generate oob based on value instead of a fixed -1. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
6062262ccd
commit
16b67ddbd6
11 changed files with 186 additions and 74 deletions
|
@ -291,21 +291,21 @@ int dbus_rule::gen_policy_re(Profile &prof)
|
|||
if (mode & AA_DBUS_BIND) {
|
||||
if (!prof.policy.rules->add_rule_vec(deny, mode & AA_DBUS_BIND,
|
||||
audit & AA_DBUS_BIND,
|
||||
2, vec, dfaflags))
|
||||
2, vec, dfaflags, false))
|
||||
goto fail;
|
||||
}
|
||||
if (mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
|
||||
if (!prof.policy.rules->add_rule_vec(deny,
|
||||
mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
|
||||
audit & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
|
||||
6, vec, dfaflags))
|
||||
6, vec, dfaflags, false))
|
||||
goto fail;
|
||||
}
|
||||
if (mode & AA_DBUS_EAVESDROP) {
|
||||
if (!prof.policy.rules->add_rule_vec(deny,
|
||||
mode & AA_DBUS_EAVESDROP,
|
||||
audit & AA_DBUS_EAVESDROP,
|
||||
1, vec, dfaflags))
|
||||
1, vec, dfaflags, false))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ aare_rules::~aare_rules(void)
|
|||
bool aare_rules::add_rule(const char *rule, int deny, uint32_t perms,
|
||||
uint32_t audit, dfaflags_t flags)
|
||||
{
|
||||
return add_rule_vec(deny, perms, audit, 1, &rule, flags);
|
||||
return add_rule_vec(deny, perms, audit, 1, &rule, flags, false);
|
||||
}
|
||||
|
||||
void aare_rules::add_to_rules(Node *tree, Node *perms)
|
||||
|
@ -66,8 +66,14 @@ static Node *cat_with_null_seperator(Node *l, Node *r)
|
|||
return new CatNode(new CatNode(l, new CharNode(0)), r);
|
||||
}
|
||||
|
||||
static Node *cat_with_oob_seperator(Node *l, Node *r)
|
||||
{
|
||||
return new CatNode(new CatNode(l, new CharNode(transchar(-1, true))), r);
|
||||
}
|
||||
|
||||
bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
||||
int count, const char **rulev, dfaflags_t flags)
|
||||
int count, const char **rulev, dfaflags_t flags,
|
||||
bool oob)
|
||||
{
|
||||
Node *tree = NULL, *accept;
|
||||
int exact_match;
|
||||
|
@ -78,7 +84,10 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
|||
Node *subtree = NULL;
|
||||
if (regex_parse(&subtree, rulev[i]))
|
||||
return false;
|
||||
tree = cat_with_null_seperator(tree, subtree);
|
||||
if (oob)
|
||||
tree = cat_with_oob_seperator(tree, subtree);
|
||||
else
|
||||
tree = cat_with_null_seperator(tree, subtree);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -102,10 +111,15 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
|||
accept = unique_perms.insert(deny, perms, audit, exact_match);
|
||||
|
||||
if (flags & DFA_DUMP_RULE_EXPR) {
|
||||
const char *seperator;
|
||||
if (oob)
|
||||
seperator = "\\-x01";
|
||||
else
|
||||
seperator = "\\x00";
|
||||
cerr << "rule: ";
|
||||
cerr << rulev[0];
|
||||
for (int i = 1; i < count; i++) {
|
||||
cerr << "\\x00";
|
||||
cerr << seperator;
|
||||
cerr << rulev[i];
|
||||
}
|
||||
cerr << " -> ";
|
||||
|
|
|
@ -103,7 +103,7 @@ class aare_rules {
|
|||
bool add_rule(const char *rule, int deny, uint32_t perms,
|
||||
uint32_t audit, dfaflags_t flags);
|
||||
bool add_rule_vec(int deny, uint32_t perms, uint32_t audit, int count,
|
||||
const char **rulev, dfaflags_t flags);
|
||||
const char **rulev, dfaflags_t flags, bool oob);
|
||||
bool append_rule(const char *rule, dfaflags_t flags);
|
||||
void *create_dfa(size_t *size, int *min_match_len, dfaflags_t flags);
|
||||
};
|
||||
|
|
|
@ -54,10 +54,11 @@ CHFA::CHFA(DFA &dfa, map<transchar, transchar> &eq, dfaflags_t flags): eq(eq)
|
|||
if (flags & DFA_DUMP_TRANS_PROGRESS)
|
||||
fprintf(stderr, "Compressing HFA:\r");
|
||||
|
||||
chfaflags = 0;
|
||||
if (dfa.diffcount)
|
||||
chfaflags = YYTH_FLAG_DIFF_ENCODE;
|
||||
else
|
||||
chfaflags = 0;
|
||||
chfaflags |= YYTH_FLAG_DIFF_ENCODE;
|
||||
if (dfa.oob_range)
|
||||
chfaflags |= YYTH_FLAG_OOB_TRANS;
|
||||
|
||||
if (eq.empty())
|
||||
max_eq = 255;
|
||||
|
@ -87,7 +88,7 @@ CHFA::CHFA(DFA &dfa, map<transchar, transchar> &eq, dfaflags_t flags): eq(eq)
|
|||
range =
|
||||
(*i)->trans.rbegin()->first.c -
|
||||
(*i)->trans.begin()->first.c;
|
||||
size_t ord = ((256 - (*i)->trans.size()) << 8) | (256 - range);
|
||||
size_t ord = ((dfa.max_range - (*i)->trans.size()) << dfa.ord_range) | (dfa.max_range - range);
|
||||
/* reverse sort by entry count, most entries first */
|
||||
order.insert(make_pair(ord, *i));
|
||||
}
|
||||
|
@ -100,7 +101,7 @@ CHFA::CHFA(DFA &dfa, map<transchar, transchar> &eq, dfaflags_t flags): eq(eq)
|
|||
|
||||
accept.resize(max(dfa.states.size(), (size_t) 2));
|
||||
accept2.resize(max(dfa.states.size(), (size_t) 2));
|
||||
next_check.resize(max(optimal, (size_t) 256));
|
||||
next_check.resize(max(optimal, (size_t) dfa.max_range));
|
||||
free_list.resize(next_check.size());
|
||||
|
||||
accept[0] = 0;
|
||||
|
@ -166,12 +167,15 @@ bool CHFA::fits_in(vector<pair<size_t, size_t> > &free_list
|
|||
__attribute__ ((unused)), size_t pos,
|
||||
StateTrans &trans)
|
||||
{
|
||||
size_t c, base = pos - trans.begin()->first.c;
|
||||
ssize_t c, base = pos - trans.begin()->first.c;
|
||||
|
||||
if (base < 0)
|
||||
return false;
|
||||
for (StateTrans::iterator i = trans.begin(); i != trans.end(); i++) {
|
||||
c = base + i->first.c;
|
||||
/* if it overflows the next_check array it fits in as we will
|
||||
* resize */
|
||||
if (c >= next_check.size())
|
||||
if (c >= (ssize_t) next_check.size())
|
||||
return true;
|
||||
if (next_check[c].second)
|
||||
return false;
|
||||
|
@ -187,13 +191,13 @@ void CHFA::insert_state(vector<pair<size_t, size_t> > &free_list,
|
|||
State *from, DFA &dfa)
|
||||
{
|
||||
State *default_state = dfa.nonmatching;
|
||||
size_t base = 0;
|
||||
ssize_t base = 0;
|
||||
int resize;
|
||||
|
||||
StateTrans &trans = from->trans;
|
||||
size_t c = trans.begin()->first.c;
|
||||
size_t prev = 0;
|
||||
size_t x = first_free;
|
||||
ssize_t c = trans.begin()->first.c;
|
||||
ssize_t prev = 0;
|
||||
ssize_t x = first_free;
|
||||
|
||||
if (from->otherwise)
|
||||
default_state = from->otherwise;
|
||||
|
@ -203,7 +207,7 @@ void CHFA::insert_state(vector<pair<size_t, size_t> > &free_list,
|
|||
repeat:
|
||||
resize = 0;
|
||||
/* get the first free entry that won't underflow */
|
||||
while (x && (x < c)) {
|
||||
while (x && ((x < c) || (x + c < 0))) {
|
||||
prev = x;
|
||||
x = free_list[x].second;
|
||||
}
|
||||
|
@ -214,17 +218,17 @@ repeat:
|
|||
x = free_list[x].second;
|
||||
}
|
||||
if (!x) {
|
||||
resize = 256 - trans.begin()->first.c;
|
||||
resize = dfa.upper_bound - c;
|
||||
x = free_list.size();
|
||||
/* set prev to last free */
|
||||
} else if (x + 255 - trans.begin()->first.c >= next_check.size()) {
|
||||
resize = (255 - trans.begin()->first.c - (next_check.size() - 1 - x));
|
||||
} else if (x + (dfa.upper_bound - 1) - c >= (ssize_t) next_check.size()) {
|
||||
resize = ((dfa.upper_bound -1) - c - (next_check.size() - 1 - x));
|
||||
for (size_t y = x; y; y = free_list[y].second)
|
||||
prev = y;
|
||||
}
|
||||
if (resize) {
|
||||
/* expand next_check and free_list */
|
||||
size_t old_size = free_list.size();
|
||||
ssize_t old_size = free_list.size();
|
||||
next_check.resize(next_check.size() + resize);
|
||||
free_list.resize(free_list.size() + resize);
|
||||
init_free_list(free_list, prev, old_size);
|
||||
|
@ -248,6 +252,9 @@ repeat:
|
|||
}
|
||||
|
||||
do_insert:
|
||||
if (c < 0) {
|
||||
base |= MATCH_FLAG_OOB_TRANSITION;
|
||||
}
|
||||
if (from->flags & DiffEncodeFlag)
|
||||
base |= DiffEncodeBit32;
|
||||
default_base.push_back(make_pair(default_state, base));
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#define BASE32_FLAGS 0xff000000
|
||||
#define DiffEncodeBit32 0x80000000
|
||||
#define MATCH_FLAG_OOB_TRANSITION 0x20000000
|
||||
#define base_mask_size(X) ((X) & ~BASE32_FLAGS)
|
||||
|
||||
using namespace std;
|
||||
|
@ -54,7 +55,7 @@ class CHFA {
|
|||
map<const State *, size_t> num;
|
||||
map<transchar, transchar> &eq;
|
||||
transchar max_eq;
|
||||
size_t first_free;
|
||||
ssize_t first_free;
|
||||
unsigned int chfaflags;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,11 +45,69 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* transchar - representative input character for state transitions
|
||||
*
|
||||
* the transchar is used as the leaf node in the expr tree created
|
||||
* by parsing an input regex (parse.y), and is used to build both the
|
||||
* states and the transitions for a state machine (hfa.{h,cc}) built
|
||||
* from the expression tree.
|
||||
*
|
||||
* While the state machine is currently based on byte inputs the
|
||||
* transchar abstraction allows for flexibility and the option of
|
||||
* moving to a larger input in the future. It also allows the ability
|
||||
* to specify out of band transitions.
|
||||
*
|
||||
* Out of band transitions allow for code to specify special transitions
|
||||
* that can not be triggered by an input byte stream. As such out of
|
||||
* band transitions can be used to separate logical units of a match.
|
||||
*
|
||||
* eg.
|
||||
* you need to allow an arbitrary data match (.*) followed by an arbitrary
|
||||
* string match ([^\x00]*), and make an acceptance dission based
|
||||
* on both matches.
|
||||
*
|
||||
* One way to do this is to chain the two matches in a single state
|
||||
* machine. However without an out of band transition, the matche pattern
|
||||
* for the data match (.*) could also consume the input for the string match.
|
||||
* To ensure the data pattern match cannot consume characters for the second
|
||||
* match a special character is used. This prevents state machine
|
||||
* generation from intermixing the two expressions. For string matches
|
||||
* this can be achieved with the pattern.
|
||||
* ([^\x00]*)\x00([\x00]*)
|
||||
* since \x00 can not be matched by the first expression (and is not a
|
||||
* valid character in a C string), the nul character can be used to
|
||||
* separate the string match. This however is not possible when matching
|
||||
* arbitrary data that can have any input character.
|
||||
*
|
||||
* Out of band transitions replace the \x00 transition in the string
|
||||
* example with a new input transition that comes from the driver
|
||||
* code. Once the first match is done, the driver supplies the non-input
|
||||
* character, causing the state machine to transition to the second
|
||||
* match pattern.
|
||||
*
|
||||
* Out of band transitions are specified using negative integers
|
||||
* (-1..-32k). They llow for different transitions if needed (currently
|
||||
* only -1 is used).
|
||||
*
|
||||
* Negative integers were chosen to represent out of band transitions
|
||||
* because it makes the run time match simple, and also keeps the
|
||||
* upper positive integer range open for future input character
|
||||
* expansion.
|
||||
*
|
||||
* When a chfa is built, the out of band transition is encoded as
|
||||
* a negative offset of the same value specified in the transchar from the
|
||||
* state base base value. The check value at the negative offset will
|
||||
* contain the owning state value. The chfa state machine is constructed
|
||||
* in such a way that this value will always be in bounds, and only an
|
||||
* unpack time verification is needed.
|
||||
*/
|
||||
class transchar {
|
||||
public:
|
||||
short c;
|
||||
|
||||
transchar(unsigned char a): c((unsigned short) a) {}
|
||||
transchar(short a, bool oob __attribute__((unused))): c(a) {}
|
||||
transchar(const transchar &a): c(a.c) {}
|
||||
transchar(): c(0) {}
|
||||
|
||||
|
@ -341,7 +399,7 @@ public:
|
|||
{
|
||||
NodeSet **x = &cases.cases[c];
|
||||
if (!*x) {
|
||||
if (cases.otherwise)
|
||||
if (cases.otherwise && c.c >= 0)
|
||||
*x = new NodeSet(*cases.otherwise);
|
||||
else
|
||||
*x = new NodeSet;
|
||||
|
@ -384,7 +442,7 @@ public:
|
|||
for (Chars::iterator i = chars.begin(); i != chars.end(); i++) {
|
||||
NodeSet **x = &cases.cases[*i];
|
||||
if (!*x) {
|
||||
if (cases.otherwise)
|
||||
if (cases.otherwise && i->c >= 0)
|
||||
*x = new NodeSet(*cases.otherwise);
|
||||
else
|
||||
*x = new NodeSet;
|
||||
|
@ -453,7 +511,8 @@ public:
|
|||
cases.otherwise->insert(followpos.begin(), followpos.end());
|
||||
for (Cases::iterator i = cases.begin(); i != cases.end();
|
||||
i++) {
|
||||
if (chars.find(i->first) == chars.end())
|
||||
/* does not match oob transition chars */
|
||||
if (i->first.c >=0 && chars.find(i->first) == chars.end())
|
||||
i->second->insert(followpos.begin(),
|
||||
followpos.end());
|
||||
}
|
||||
|
@ -511,7 +570,9 @@ public:
|
|||
cases.otherwise->insert(followpos.begin(), followpos.end());
|
||||
for (Cases::iterator i = cases.begin(); i != cases.end();
|
||||
i++)
|
||||
i->second->insert(followpos.begin(), followpos.end());
|
||||
/* does not match oob transition chars */
|
||||
if (i->first.c >= 0)
|
||||
i->second->insert(followpos.begin(), followpos.end());
|
||||
}
|
||||
int eq(Node *other)
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#define YYTH_MAGIC 0xF13C57B1
|
||||
#define YYTH_FLAG_DIFF_ENCODE 1
|
||||
#define YYTH_FLAG_OOB_TRANS 2
|
||||
|
||||
struct table_set_header {
|
||||
uint32_t th_magic; /* TH_MAGIC */
|
||||
|
|
|
@ -100,9 +100,10 @@ ostream &operator<<(ostream &os, State &state)
|
|||
*
|
||||
* Should be applied after state minimization
|
||||
*/
|
||||
int State::diff_weight(State *rel)
|
||||
int State::diff_weight(State *rel, int max_range, int upper_bound)
|
||||
{
|
||||
int weight = 0;
|
||||
int first = 0;
|
||||
|
||||
if (this == rel)
|
||||
return 0;
|
||||
|
@ -117,8 +118,10 @@ int State::diff_weight(State *rel)
|
|||
} else if (rel->diff->depth >= this->diff->depth)
|
||||
return 0;
|
||||
|
||||
if (rel->trans.begin()->first.c < first)
|
||||
first = rel->trans.begin()->first.c;
|
||||
if (rel->flags & DiffEncodeFlag) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
for (int i = first; i < upper_bound; i++) {
|
||||
State *state = rel->next(i);
|
||||
StateTrans::iterator j = trans.find(i);
|
||||
if (j != trans.end()) {
|
||||
|
@ -184,7 +187,7 @@ int State::diff_weight(State *rel)
|
|||
/* rel default transitions have to be masked with transitions
|
||||
* This covers all transitions not covered above
|
||||
*/
|
||||
weight -= 256 - (rel->trans.size() + this_count);
|
||||
weight -= (max_range) - (rel->trans.size() + this_count);
|
||||
}
|
||||
|
||||
return weight;
|
||||
|
@ -193,12 +196,14 @@ int State::diff_weight(State *rel)
|
|||
/**
|
||||
* make_relative - Make this state relative to @rel
|
||||
* @rel: state to make this state relative too
|
||||
* @upper_bound: the largest value for an input transition (256 for a byte).
|
||||
*
|
||||
* @rel can be a relative (differentially compressed state)
|
||||
*/
|
||||
int State::make_relative(State *rel)
|
||||
int State::make_relative(State *rel, int upper_bound)
|
||||
{
|
||||
int weight = 0;
|
||||
int first = 0;
|
||||
|
||||
if (this == rel || !rel)
|
||||
return 0;
|
||||
|
@ -206,9 +211,12 @@ int State::make_relative(State *rel)
|
|||
if (flags & DiffEncodeFlag)
|
||||
return 0;
|
||||
|
||||
if (rel->trans.begin()->first.c < 0)
|
||||
first = rel->trans.begin()->first.c;
|
||||
|
||||
flags |= DiffEncodeFlag;
|
||||
|
||||
for (int i = 0; i < 256 ; i++) {
|
||||
for (int i = first; i < upper_bound ; i++) {
|
||||
State *next = rel->next(i);
|
||||
|
||||
StateTrans::iterator j = trans.find(i);
|
||||
|
@ -236,27 +244,33 @@ int State::make_relative(State *rel)
|
|||
|
||||
/**
|
||||
* flatten_differential - remove differential encode from this state
|
||||
* @nonmatching: the nonmatching state for the state machine
|
||||
* @upper_bound: the largest value for an input transition (256 for a byte).
|
||||
*/
|
||||
void State::flatten_relative(void)
|
||||
void State::flatten_relative(State *nonmatching, int upper_bound)
|
||||
{
|
||||
if (!(flags & DiffEncodeFlag))
|
||||
return;
|
||||
|
||||
map<State *, int> count;
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
int first = 0;
|
||||
if (next(-1) != nonmatching)
|
||||
first = -1;
|
||||
|
||||
for (int i = first; i < upper_bound; i++)
|
||||
count[next(i)] += 1;
|
||||
|
||||
int j = 0;
|
||||
State *def = next(0);
|
||||
for (int i = 1; i < 256; i++) {
|
||||
int j = first;
|
||||
State *def = next(first);
|
||||
for (int i = first + 1; i < upper_bound; i++) {
|
||||
if (count[next(i)] > count[next(j)]) {
|
||||
j = i;
|
||||
def = next(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
for (int i = first; i < upper_bound; i++) {
|
||||
if (trans.find(i) != trans.end()) {
|
||||
if (trans[i] == def)
|
||||
trans.erase(i);
|
||||
|
@ -357,8 +371,11 @@ void DFA::update_state_transitions(State *state)
|
|||
/* Don't insert transition that the otherwise transition
|
||||
* already covers
|
||||
*/
|
||||
if (target != state->otherwise)
|
||||
if (target != state->otherwise) {
|
||||
state->trans[j->first] = target;
|
||||
if (j->first.c < 0 && -j->first.c > oob_range)
|
||||
oob_range = -j->first.c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,6 +423,10 @@ void DFA::process_work_queue(const char *header, dfaflags_t flags)
|
|||
DFA::DFA(Node *root, dfaflags_t flags): root(root)
|
||||
{
|
||||
diffcount = 0; /* set by diff_encode */
|
||||
max_range = 256;
|
||||
upper_bound = 256;
|
||||
oob_range = 0;
|
||||
ord_range = 8;
|
||||
|
||||
if (flags & DFA_DUMP_PROGRESS)
|
||||
fprintf(stderr, "Creating dfa:\r");
|
||||
|
@ -437,7 +458,10 @@ DFA::DFA(Node *root, dfaflags_t flags): root(root)
|
|||
*/
|
||||
work_queue.push_back(start);
|
||||
process_work_queue("Creating dfa", flags);
|
||||
|
||||
max_range += oob_range;
|
||||
/* if oob_range is ever greater than 256 need to move to computing this */
|
||||
if (oob_range)
|
||||
ord_range = 9;
|
||||
/* cleanup Sets of nodes used computing the DFA as they are no longer
|
||||
* needed.
|
||||
*/
|
||||
|
@ -755,12 +779,9 @@ void DFA::minimize(dfaflags_t flags)
|
|||
c = rep->trans.erase(c);
|
||||
}
|
||||
|
||||
//if ((*p)->size() > 1)
|
||||
//cerr << rep->label << ": ";
|
||||
/* clear the state label for all non representative states,
|
||||
* and accumulate permissions */
|
||||
for (Partition::iterator i = ++(*p)->begin(); i != (*p)->end(); i++) {
|
||||
//cerr << " " << (*i)->label;
|
||||
if (flags & DFA_DUMP_MIN_PARTS)
|
||||
cerr << **i << ", ";
|
||||
(*i)->label = -1;
|
||||
|
@ -768,8 +789,6 @@ void DFA::minimize(dfaflags_t flags)
|
|||
}
|
||||
if (rep->perms.is_accept())
|
||||
final_accept++;
|
||||
//if ((*p)->size() > 1)
|
||||
//cerr << "\n";
|
||||
if (flags & DFA_DUMP_MIN_PARTS)
|
||||
cerr << "\n";
|
||||
}
|
||||
|
@ -836,7 +855,7 @@ static unsigned int add_to_dag(DiffDag *dag, State *state,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int diff_partition(State *state, Partition &part, State **candidate)
|
||||
static int diff_partition(State *state, Partition &part, int max_range, int upper_bound, State **candidate)
|
||||
{
|
||||
int weight = 0;
|
||||
*candidate = NULL;
|
||||
|
@ -845,7 +864,7 @@ static int diff_partition(State *state, Partition &part, State **candidate)
|
|||
if (*i == state)
|
||||
continue;
|
||||
|
||||
int tmp = state->diff_weight(*i);
|
||||
int tmp = state->diff_weight(*i, max_range, upper_bound);
|
||||
if (tmp > weight) {
|
||||
weight = tmp;
|
||||
*candidate = *i;
|
||||
|
@ -932,14 +951,14 @@ void DFA::diff_encode(dfaflags_t flags)
|
|||
State *candidate = NULL;
|
||||
|
||||
int weight = diff_partition(state,
|
||||
state->otherwise->diff->parents,
|
||||
&candidate);
|
||||
state->otherwise->diff->parents, max_range,
|
||||
upper_bound, &candidate);
|
||||
|
||||
for (StateTrans::iterator j = state->trans.begin(); j != state->trans.end(); j++) {
|
||||
State *tmp_candidate;
|
||||
int tmp = diff_partition(state,
|
||||
j->second->diff->parents,
|
||||
&tmp_candidate);
|
||||
j->second->diff->parents, max_range,
|
||||
upper_bound, &tmp_candidate);
|
||||
if (tmp > weight) {
|
||||
weight = tmp;
|
||||
candidate = tmp_candidate;
|
||||
|
@ -967,7 +986,7 @@ void DFA::diff_encode(dfaflags_t flags)
|
|||
diffcount = 0;
|
||||
for (int i = tail - 1; i > 1; i--) {
|
||||
if (dag[i].rel) {
|
||||
int weight = dag[i].state->make_relative(dag[i].rel);
|
||||
int weight = dag[i].state->make_relative(dag[i].rel, upper_bound);
|
||||
aweight += weight;
|
||||
diffcount++;
|
||||
}
|
||||
|
@ -1000,7 +1019,7 @@ void DFA::diff_encode(dfaflags_t flags)
|
|||
void DFA::undiff_encode(void)
|
||||
{
|
||||
for (Partition::iterator i = states.begin(); i != states.end(); i++)
|
||||
(*i)->flatten_relative();
|
||||
(*i)->flatten_relative(nonmatching, upper_bound);
|
||||
diffcount = 0;
|
||||
}
|
||||
|
||||
|
@ -1183,9 +1202,11 @@ map<transchar, transchar> DFA::equivalence_classes(dfaflags_t flags)
|
|||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||
/* Group edges to the same next state together */
|
||||
map<const State *, Chars> node_sets;
|
||||
for (StateTrans::iterator j = (*i)->trans.begin(); j != (*i)->trans.end(); j++)
|
||||
for (StateTrans::iterator j = (*i)->trans.begin(); j != (*i)->trans.end(); j++) {
|
||||
if (j->first.c < 0)
|
||||
continue;
|
||||
node_sets[j->second].insert(j->first);
|
||||
|
||||
}
|
||||
for (map<const State *, Chars>::iterator j = node_sets.begin();
|
||||
j != node_sets.end(); j++) {
|
||||
/* Group edges to the same next state together by class */
|
||||
|
@ -1271,8 +1292,11 @@ void DFA::apply_equivalence_classes(map<transchar, transchar> &eq)
|
|||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||
map<transchar, State *> tmp;
|
||||
tmp.swap((*i)->trans);
|
||||
for (StateTrans::iterator j = tmp.begin(); j != tmp.end(); j++)
|
||||
for (StateTrans::iterator j = tmp.begin(); j != tmp.end(); j++) {
|
||||
if (j->first.c < 0)
|
||||
continue;
|
||||
(*i)->trans.insert(make_pair(eq[j->first], j->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -241,9 +241,9 @@ public:
|
|||
return os;
|
||||
}
|
||||
|
||||
int diff_weight(State *rel);
|
||||
int make_relative(State *rel);
|
||||
void flatten_relative(void);
|
||||
int diff_weight(State *rel, int max_range, int upper_bound);
|
||||
int make_relative(State *rel, int upper_bound);
|
||||
void flatten_relative(State *, int upper_bound);
|
||||
|
||||
int apply_and_clear_deny(void) { return perms.apply_and_clear_deny(); }
|
||||
|
||||
|
@ -340,6 +340,10 @@ public:
|
|||
void apply_equivalence_classes(map<transchar, transchar> &eq);
|
||||
|
||||
unsigned int diffcount;
|
||||
int oob_range;
|
||||
int max_range;
|
||||
int ord_range;
|
||||
int upper_bound;
|
||||
Node *root;
|
||||
State *nonmatching, *start;
|
||||
Partition states;
|
||||
|
|
|
@ -643,7 +643,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
/* rule for match without required data || data MATCH_CONT */
|
||||
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
||||
audit | AA_AUDIT_MNT_DATA, 4,
|
||||
vec, dfaflags))
|
||||
vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
|
@ -655,7 +655,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
vec[4] = optsbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
||||
audit | AA_AUDIT_MNT_DATA,
|
||||
5, vec, dfaflags))
|
||||
5, vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
@ -684,7 +684,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags))
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
@ -713,7 +713,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags))
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
@ -743,7 +743,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 4, vec,
|
||||
dfaflags))
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
@ -784,7 +784,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
/* rule for match without required data || data MATCH_CONT */
|
||||
if (!prof.policy.rules->add_rule_vec(deny, tmpallow,
|
||||
audit | AA_AUDIT_MNT_DATA, 4,
|
||||
vec, dfaflags))
|
||||
vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
|
@ -796,7 +796,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
vec[4] = optsbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow,
|
||||
audit | AA_AUDIT_MNT_DATA,
|
||||
5, vec, dfaflags))
|
||||
5, vec, dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
@ -808,7 +808,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 1, vec,
|
||||
dfaflags))
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
@ -822,7 +822,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
goto fail;
|
||||
vec[1] = devbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(deny, allow, audit, 2, vec,
|
||||
dfaflags))
|
||||
dfaflags, false))
|
||||
goto fail;
|
||||
count++;
|
||||
}
|
||||
|
|
|
@ -613,7 +613,7 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
perms |= LINK_TO_LINK_SUBSET(perms);
|
||||
vec[1] = "/[^/].*";
|
||||
}
|
||||
if (!dfarules->add_rule_vec(entry->deny, perms, entry->audit & AA_LINK_BITS, 2, vec, dfaflags))
|
||||
if (!dfarules->add_rule_vec(entry->deny, perms, entry->audit & AA_LINK_BITS, 2, vec, dfaflags, false))
|
||||
return FALSE;
|
||||
}
|
||||
if (is_change_profile_mode(entry->mode)) {
|
||||
|
@ -666,12 +666,12 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
/* regular change_profile rule */
|
||||
if (!dfarules->add_rule_vec(entry->deny,
|
||||
AA_CHANGE_PROFILE | onexec_perms,
|
||||
0, index - 1, &vec[1], dfaflags))
|
||||
0, index - 1, &vec[1], dfaflags, false))
|
||||
return FALSE;
|
||||
|
||||
/* onexec rules - both rules are needed for onexec */
|
||||
if (!dfarules->add_rule_vec(entry->deny, onexec_perms,
|
||||
0, 1, vec, dfaflags))
|
||||
0, 1, vec, dfaflags, false))
|
||||
return FALSE;
|
||||
|
||||
/**
|
||||
|
@ -680,7 +680,7 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
*/
|
||||
onexec_perms |= (entry->mode & (AA_EXEC_BITS | ALL_AA_EXEC_UNSAFE));
|
||||
if (!dfarules->add_rule_vec(entry->deny, onexec_perms,
|
||||
0, index, vec, dfaflags))
|
||||
0, index, vec, dfaflags, false))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
|
Loading…
Add table
Reference in a new issue