2011-03-13 05:49:15 -07:00
|
|
|
/*
|
|
|
|
* (C) 2006, 2007 Andreas Gruenbacher <agruen@suse.de>
|
|
|
|
* Copyright (c) 2003-2008 Novell, Inc. (All rights reserved)
|
2013-10-14 14:36:05 -07:00
|
|
|
* Copyright 2009-2013 Canonical Ltd. (All rights reserved)
|
2011-03-13 05:49:15 -07:00
|
|
|
*
|
|
|
|
* The libapparmor library is licensed under the terms of the GNU
|
|
|
|
* Lesser General Public License, version 2.1. Please see the file
|
|
|
|
* COPYING.LGPL.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Wrapper around the dfa to convert aa rules into a dfa
|
|
|
|
*/
|
|
|
|
|
2011-03-13 05:50:34 -07:00
|
|
|
#include <ostream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
2011-03-13 05:49:15 -07:00
|
|
|
#include <sstream>
|
|
|
|
#include <ext/stdio_filebuf.h>
|
2011-03-13 05:50:34 -07:00
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
2011-03-13 05:49:15 -07:00
|
|
|
|
|
|
|
#include "aare_rules.h"
|
|
|
|
#include "expr-tree.h"
|
|
|
|
#include "parse.h"
|
|
|
|
#include "hfa.h"
|
2011-12-15 05:06:32 -08:00
|
|
|
#include "chfa.h"
|
2011-03-13 05:50:34 -07:00
|
|
|
#include "../immunix.h"
|
2011-03-13 05:49:15 -07:00
|
|
|
|
|
|
|
|
2014-04-23 10:57:16 -07:00
|
|
|
aare_rules::~aare_rules(void)
|
2011-03-13 05:49:15 -07:00
|
|
|
{
|
2014-04-23 10:57:16 -07:00
|
|
|
if (root)
|
|
|
|
root->release();
|
2012-12-10 17:08:19 -08:00
|
|
|
|
2015-06-25 14:08:55 -06:00
|
|
|
unique_perms.clear();
|
2015-06-25 16:38:02 -06:00
|
|
|
expr_map.clear();
|
2011-03-13 05:49:15 -07:00
|
|
|
}
|
|
|
|
|
2024-05-10 03:06:22 -07:00
|
|
|
bool aare_rules::add_rule(const char *rule, int priority, rule_mode_t mode,
|
|
|
|
perm32_t perms, perm32_t audit, optflags const &opts)
|
2011-03-13 05:49:15 -07:00
|
|
|
{
|
2024-05-10 03:06:22 -07:00
|
|
|
return add_rule_vec(priority, mode, perms, audit, 1, &rule, opts,
|
|
|
|
false);
|
2011-03-13 05:49:15 -07:00
|
|
|
}
|
|
|
|
|
2014-09-03 14:24:37 -07:00
|
|
|
void aare_rules::add_to_rules(Node *tree, Node *perms)
|
|
|
|
{
|
|
|
|
if (reverse)
|
|
|
|
flip_tree(tree);
|
2015-06-25 16:38:02 -06:00
|
|
|
Node *base = expr_map[perms];
|
|
|
|
if (base)
|
|
|
|
expr_map[perms] = new AltNode(base, tree);
|
2014-09-03 14:24:37 -07:00
|
|
|
else
|
2015-06-25 16:38:02 -06:00
|
|
|
expr_map[perms] = tree;
|
2014-09-03 14:24:37 -07:00
|
|
|
}
|
|
|
|
|
2020-11-19 12:37:13 -08:00
|
|
|
static Node *cat_with_null_separator(Node *l, Node *r)
|
2014-09-03 14:24:37 -07:00
|
|
|
{
|
2015-10-14 13:49:26 -07:00
|
|
|
return new CatNode(new CatNode(l, new CharNode(0)), r);
|
2014-09-03 14:24:37 -07:00
|
|
|
}
|
|
|
|
|
2020-11-19 12:37:13 -08:00
|
|
|
static Node *cat_with_oob_separator(Node *l, Node *r)
|
2019-08-11 06:18:27 -07:00
|
|
|
{
|
|
|
|
return new CatNode(new CatNode(l, new CharNode(transchar(-1, true))), r);
|
|
|
|
}
|
|
|
|
|
2024-05-10 03:06:22 -07:00
|
|
|
bool aare_rules::add_rule_vec(int priority, rule_mode_t mode, perm32_t perms,
|
|
|
|
perm32_t audit, int count, const char **rulev,
|
|
|
|
optflags const &opts, bool oob)
|
2014-09-03 14:40:08 -07:00
|
|
|
{
|
|
|
|
Node *tree = NULL, *accept;
|
|
|
|
int exact_match;
|
|
|
|
|
|
|
|
if (regex_parse(&tree, rulev[0]))
|
|
|
|
return false;
|
|
|
|
for (int i = 1; i < count; i++) {
|
|
|
|
Node *subtree = NULL;
|
|
|
|
if (regex_parse(&subtree, rulev[i]))
|
2019-12-05 14:01:50 -08:00
|
|
|
goto err;
|
2019-08-11 06:18:27 -07:00
|
|
|
if (oob)
|
2020-11-19 12:37:13 -08:00
|
|
|
tree = cat_with_oob_separator(tree, subtree);
|
2019-08-11 06:18:27 -07:00
|
|
|
else
|
2020-11-19 12:37:13 -08:00
|
|
|
tree = cat_with_null_separator(tree, subtree);
|
2014-09-03 14:40:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if we have an expression with or without wildcards. This
|
|
|
|
* determines how exec modifiers are merged in accept_perms() based
|
|
|
|
* on how we split permission bitmasks here.
|
|
|
|
*/
|
|
|
|
exact_match = 1;
|
|
|
|
for (depth_first_traversal i(tree); i && exact_match; i++) {
|
parser: replace dynamic_cast with is_type method
The dynamic_cast operator is slow as it needs to look at RTTI
information and even does some string comparisons, especially in deep
hierarchies like the one for Node. Profiling with callgrind showed
that dynamic_cast can eat a huge portion of the running time, as it
takes most of the time that is spent in the simplify_tree()
function. For some complex profiles, the number of calls to
dynamic_cast can be in the range of millions.
This commit replaces the use of dynamic_cast in the Node hierarchy
with a method called is_type(), which returns true if the pointer can
be casted to the specified type. It works by looking at a Node object
field that is an integer with bits set for each type up in the
hierarchy. Therefore, dynamic_cast is replaced by a simple bits
operation.
This change can reduce the compilation times for some profiles more
that 50%, especially in arm/arm64 arch. This opens the door to maybe
avoid "-O no-expr-simplify" in the snapd daemon, as now that option
would make the compilation slower in almost all cases.
This is the example profile used in some of my tests, with this change
the run-time is around 1/3 of what it was before on an x86 laptop:
profile "test" (attach_disconnected,mediate_deleted) {
dbus send
bus={fcitx,session}
path=/inputcontext_[0-9]*
interface=org.fcitx.Fcitx.InputContext
member="{Close,Destroy,Enable}IC"
peer=(label=unconfined),
dbus send
bus={fcitx,session}
path=/inputcontext_[0-9]*
interface=org.fcitx.Fcitx.InputContext
member=Reset
peer=(label=unconfined),
dbus receive
bus=fcitx
peer=(label=unconfined),
dbus receive
bus=session
interface=org.fcitx.Fcitx.*
peer=(label=unconfined),
dbus send
bus={fcitx,session}
path=/inputcontext_[0-9]*
interface=org.fcitx.Fcitx.InputContext
member="Focus{In,Out}"
peer=(label=unconfined),
dbus send
bus={fcitx,session}
path=/inputcontext_[0-9]*
interface=org.fcitx.Fcitx.InputContext
member="{CommitPreedit,Set*}"
peer=(label=unconfined),
dbus send
bus={fcitx,session}
path=/inputcontext_[0-9]*
interface=org.fcitx.Fcitx.InputContext
member="{MouseEvent,ProcessKeyEvent}"
peer=(label=unconfined),
dbus send
bus={fcitx,session}
path=/inputcontext_[0-9]*
interface=org.freedesktop.DBus.Properties
member=GetAll
peer=(label=unconfined),
dbus (send)
bus=session
path=/org/a11y/bus
interface=org.a11y.Bus
member=GetAddress
peer=(label=unconfined),
dbus (send)
bus=session
path=/org/a11y/bus
interface=org.freedesktop.DBus.Properties
member=Get{,All}
peer=(label=unconfined),
dbus (receive, send)
bus=accessibility
path=/org/a11y/atspi/**
peer=(label=unconfined),
dbus (send)
bus=system
path=/org/freedesktop/Accounts
interface=org.freedesktop.DBus.Introspectable
member=Introspect
peer=(label=unconfined),
dbus (send)
bus=system
path=/org/freedesktop/Accounts
interface=org.freedesktop.Accounts
member=FindUserById
peer=(label=unconfined),
dbus (receive, send)
bus=system
path=/org/freedesktop/Accounts/User[0-9]*
interface=org.freedesktop.DBus.Properties
member={Get,PropertiesChanged}
peer=(label=unconfined),
dbus (send)
bus=session
interface=org.gtk.Actions
member=Changed
peer=(name=org.freedesktop.DBus, label=unconfined),
dbus (receive)
bus=session
interface=org.gtk.Actions
member={Activate,DescribeAll,SetState}
peer=(label=unconfined),
dbus (receive)
bus=session
interface=org.gtk.Menus
member={Start,End}
peer=(label=unconfined),
dbus (send)
bus=session
interface=org.gtk.Menus
member=Changed
peer=(name=org.freedesktop.DBus, label=unconfined),
dbus (send)
bus=session
path="/com/ubuntu/MenuRegistrar"
interface="com.ubuntu.MenuRegistrar"
member="{Register,Unregister}{App,Surface}Menu"
peer=(label=unconfined),
}
2021-02-15 16:26:18 +01:00
|
|
|
if ((*i)->is_type(NODE_TYPE_STAR) ||
|
|
|
|
(*i)->is_type(NODE_TYPE_PLUS) ||
|
|
|
|
(*i)->is_type(NODE_TYPE_ANYCHAR) ||
|
|
|
|
(*i)->is_type(NODE_TYPE_NOTCHARSET))
|
2014-09-03 14:40:08 -07:00
|
|
|
exact_match = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reverse)
|
|
|
|
flip_tree(tree);
|
|
|
|
|
2024-05-10 03:06:22 -07:00
|
|
|
accept = unique_perms.insert(priority, mode, perms, audit, exact_match);
|
2014-09-03 14:40:08 -07:00
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_RULE_EXPR) {
|
2020-11-19 12:37:13 -08:00
|
|
|
const char *separator;
|
2019-08-11 06:18:27 -07:00
|
|
|
if (oob)
|
2020-11-19 12:37:13 -08:00
|
|
|
separator = "\\-x01";
|
2019-08-11 06:18:27 -07:00
|
|
|
else
|
2020-11-19 12:37:13 -08:00
|
|
|
separator = "\\x00";
|
2011-03-13 05:53:08 -07:00
|
|
|
cerr << "rule: ";
|
|
|
|
cerr << rulev[0];
|
|
|
|
for (int i = 1; i < count; i++) {
|
2020-11-19 12:37:13 -08:00
|
|
|
cerr << separator;
|
2011-03-13 05:53:08 -07:00
|
|
|
cerr << rulev[i];
|
|
|
|
}
|
|
|
|
cerr << " -> ";
|
|
|
|
tree->dump(cerr);
|
2023-04-23 19:03:38 -07:00
|
|
|
// TODO: split out from prefixes class
|
2024-05-10 03:06:22 -07:00
|
|
|
cerr << " priority=" << priority;
|
2023-04-23 19:03:38 -07:00
|
|
|
if (mode == RULE_DENY)
|
2012-02-24 04:17:19 -08:00
|
|
|
cerr << " deny";
|
2023-04-23 19:03:38 -07:00
|
|
|
else if (mode == RULE_PROMPT)
|
|
|
|
cerr << " prompt";
|
2014-09-03 14:40:08 -07:00
|
|
|
cerr << " (0x" << hex << perms <<"/" << audit << dec << ")";
|
2012-02-24 04:17:19 -08:00
|
|
|
accept->dump(cerr);
|
|
|
|
cerr << "\n\n";
|
2011-03-13 05:49:15 -07:00
|
|
|
}
|
2011-03-13 05:53:08 -07:00
|
|
|
|
2014-09-03 14:24:37 -07:00
|
|
|
add_to_rules(tree, accept);
|
2011-03-13 05:53:08 -07:00
|
|
|
|
2014-04-23 10:57:16 -07:00
|
|
|
rule_count++;
|
2011-03-13 05:49:15 -07:00
|
|
|
|
2014-04-23 10:57:16 -07:00
|
|
|
return true;
|
2019-12-05 14:01:50 -08:00
|
|
|
|
|
|
|
err:
|
|
|
|
delete tree;
|
|
|
|
return false;
|
2011-03-13 05:49:15 -07:00
|
|
|
}
|
|
|
|
|
2018-12-06 10:54:46 -08:00
|
|
|
/*
|
|
|
|
* append_rule is like add_rule, but appends the rule to any existing rules
|
2019-08-16 02:36:59 -07:00
|
|
|
* with a separating transition. The appended rule matches with the same
|
2019-12-05 14:01:50 -08:00
|
|
|
* permissions as the rule it's appended to. If there are no existing rules
|
|
|
|
* append_rule returns true.
|
2018-12-06 10:54:46 -08:00
|
|
|
*
|
|
|
|
* This is used by xattrs matching where, after matching the path, the DFA is
|
|
|
|
* advanced by a null character for each xattr.
|
|
|
|
*/
|
2019-09-06 02:08:57 -07:00
|
|
|
bool aare_rules::append_rule(const char *rule, bool oob, bool with_perm,
|
2023-07-06 16:41:56 -07:00
|
|
|
optflags const &opts)
|
2018-12-06 10:54:46 -08:00
|
|
|
{
|
|
|
|
Node *tree = NULL;
|
|
|
|
if (regex_parse(&tree, rule))
|
|
|
|
return false;
|
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_RULE_EXPR) {
|
2018-12-06 10:54:46 -08:00
|
|
|
cerr << "rule: ";
|
|
|
|
cerr << rule;
|
|
|
|
cerr << " -> ";
|
|
|
|
tree->dump(cerr);
|
|
|
|
cerr << "\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For each matching state, we want to create an optional path
|
2019-08-16 02:36:59 -07:00
|
|
|
* separated by a separating character.
|
2018-12-06 10:54:46 -08:00
|
|
|
*
|
|
|
|
* When matching xattrs, the DFA must end up in an accepting state for
|
|
|
|
* the path, then each value of the xattrs. Using an optional node
|
|
|
|
* lets each rule end up in an accepting state.
|
|
|
|
*/
|
2019-09-06 02:08:57 -07:00
|
|
|
tree = new CatNode(oob ? new CharNode(transchar(-1, true)) : new CharNode(0), tree);
|
2019-12-05 14:01:50 -08:00
|
|
|
if (expr_map.size() == 0) {
|
|
|
|
// There's nothing to append to. Free the tree reference.
|
|
|
|
delete tree;
|
|
|
|
return true;
|
|
|
|
}
|
2018-12-06 10:54:46 -08:00
|
|
|
PermExprMap::iterator it;
|
|
|
|
for (it = expr_map.begin(); it != expr_map.end(); it++) {
|
2019-09-06 02:08:57 -07:00
|
|
|
if (with_perm)
|
|
|
|
expr_map[it->first] = new CatNode(it->second, new AltNode(it->first, tree));
|
|
|
|
else
|
|
|
|
expr_map[it->first] = new CatNode(it->second, tree);
|
2018-12-06 10:54:46 -08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-04-20 08:31:12 -07:00
|
|
|
/* create a chfa from the ruleset
|
2011-03-13 05:49:15 -07:00
|
|
|
* returns: buffer contain dfa tables, @size set to the size of the tables
|
2019-02-08 11:32:16 -08:00
|
|
|
* else NULL on failure, @min_match_len set to the shortest string
|
|
|
|
* that can match the dfa for determining xmatch priority.
|
2011-03-13 05:49:15 -07:00
|
|
|
*/
|
2023-04-20 08:31:12 -07:00
|
|
|
CHFA *aare_rules::create_chfa(int *min_match_len,
|
|
|
|
vector <aa_perms> &perms_table,
|
2023-04-23 20:27:51 -07:00
|
|
|
optflags const &opts, bool filedfa,
|
|
|
|
bool extended_perms, bool prompt)
|
2011-03-13 05:49:15 -07:00
|
|
|
{
|
2015-06-25 16:38:02 -06:00
|
|
|
/* finish constructing the expr tree from the different permission
|
|
|
|
* set nodes */
|
|
|
|
PermExprMap::iterator i = expr_map.begin();
|
|
|
|
if (i != expr_map.end()) {
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.control & CONTROL_DFA_TREE_SIMPLE) {
|
2023-07-06 16:41:56 -07:00
|
|
|
Node *tmp = simplify_tree(i->second, opts);
|
2015-06-25 16:38:04 -06:00
|
|
|
root = new CatNode(tmp, i->first);
|
|
|
|
} else
|
|
|
|
root = new CatNode(i->second, i->first);
|
2015-06-25 16:38:02 -06:00
|
|
|
for (i++; i != expr_map.end(); i++) {
|
2015-06-25 16:38:04 -06:00
|
|
|
Node *tmp;
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.control & CONTROL_DFA_TREE_SIMPLE) {
|
2023-07-06 16:41:56 -07:00
|
|
|
tmp = simplify_tree(i->second, opts);
|
2015-06-25 16:38:04 -06:00
|
|
|
} else
|
|
|
|
tmp = i->second;
|
|
|
|
root = new AltNode(root, new CatNode(tmp, i->first));
|
2015-06-25 16:38:02 -06:00
|
|
|
}
|
|
|
|
}
|
2019-02-08 11:32:16 -08:00
|
|
|
*min_match_len = root->min_match_len();
|
2015-06-25 16:38:02 -06:00
|
|
|
|
2015-06-25 16:38:04 -06:00
|
|
|
/* dumping of the none simplified tree without -O no-expr-simplify
|
|
|
|
* is broken because we need to build the tree above first, and
|
|
|
|
* simplification is woven into the build. Reevaluate how to fix
|
|
|
|
* this debug dump.
|
|
|
|
*/
|
2014-04-23 10:57:16 -07:00
|
|
|
label_nodes(root);
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_TREE) {
|
2011-03-13 05:53:08 -07:00
|
|
|
cerr << "\nDFA: Expression Tree\n";
|
2014-04-23 10:57:16 -07:00
|
|
|
root->dump(cerr);
|
2011-03-13 05:53:08 -07:00
|
|
|
cerr << "\n\n";
|
|
|
|
}
|
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.control & CONTROL_DFA_TREE_SIMPLE) {
|
2015-06-25 16:38:04 -06:00
|
|
|
/* This is old total tree, simplification point
|
|
|
|
* For now just do simplification up front. It gets most
|
|
|
|
* of the benefit running on the smaller chains, and is
|
|
|
|
* overall faster because there are less nodes. Reevaluate
|
|
|
|
* once tree simplification is rewritten
|
|
|
|
*/
|
2023-07-06 16:41:56 -07:00
|
|
|
//root = simplify_tree(root, opts);
|
2011-03-13 05:53:08 -07:00
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_SIMPLE_TREE) {
|
2011-03-13 05:53:08 -07:00
|
|
|
cerr << "\nDFA: Simplified Expression Tree\n";
|
2014-04-23 10:57:16 -07:00
|
|
|
root->dump(cerr);
|
2011-03-13 05:53:08 -07:00
|
|
|
cerr << "\n\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-20 08:31:12 -07:00
|
|
|
CHFA *chfa = NULL;
|
2011-03-13 05:53:08 -07:00
|
|
|
try {
|
2023-07-06 16:41:56 -07:00
|
|
|
DFA dfa(root, opts, filedfa);
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_UNIQ_PERMS)
|
2011-03-13 05:53:08 -07:00
|
|
|
dfa.dump_uniq_perms("dfa");
|
|
|
|
|
2024-05-10 03:06:22 -07:00
|
|
|
/* since we are building a chfa, use the info about
|
|
|
|
* whether the chfa supports extended perms to help
|
|
|
|
* determine whether we clear the deny info.
|
|
|
|
* This will let us build the minimal dfa for the
|
|
|
|
* information supported by the backed
|
|
|
|
*/
|
|
|
|
if (!extended_perms ||
|
|
|
|
// TODO: we should drop DFA_MINIMIZE check here but doing
|
|
|
|
// so changes behavior. Do as a separate patch and fixup
|
|
|
|
// tests, etc.
|
|
|
|
((opts.control & CONTROL_DFA_FILTER_DENY) &&
|
|
|
|
(opts.control & CONTROL_DFA_MINIMIZE)))
|
|
|
|
dfa.apply_and_clear_deny();
|
2012-02-16 07:41:40 -08:00
|
|
|
|
2024-05-10 03:06:22 -07:00
|
|
|
if (opts.control & CONTROL_DFA_MINIMIZE) {
|
2023-07-06 16:41:56 -07:00
|
|
|
dfa.minimize(opts);
|
2012-02-16 07:41:40 -08:00
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_MIN_UNIQ_PERMS)
|
2012-02-16 07:41:40 -08:00
|
|
|
dfa.dump_uniq_perms("minimized dfa");
|
|
|
|
}
|
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE)
|
2023-07-06 16:41:56 -07:00
|
|
|
dfa.remove_unreachable(opts);
|
2011-03-13 05:53:08 -07:00
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_STATES)
|
2011-03-13 05:53:08 -07:00
|
|
|
dfa.dump(cerr);
|
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_GRAPH)
|
2011-03-13 05:53:08 -07:00
|
|
|
dfa.dump_dot_graph(cerr);
|
|
|
|
|
2019-08-08 00:41:57 -07:00
|
|
|
map<transchar, transchar> eq;
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.control & CONTROL_DFA_EQUIV) {
|
2023-07-06 16:41:56 -07:00
|
|
|
eq = dfa.equivalence_classes(opts);
|
2011-03-13 05:53:08 -07:00
|
|
|
dfa.apply_equivalence_classes(eq);
|
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_EQUIV) {
|
2011-03-13 05:53:08 -07:00
|
|
|
cerr << "\nDFA equivalence class\n";
|
|
|
|
dump_equivalence_classes(cerr, eq);
|
|
|
|
}
|
2023-07-08 19:49:34 -07:00
|
|
|
} else if (opts.dump & DUMP_DFA_EQUIV)
|
2011-03-13 05:53:08 -07:00
|
|
|
cerr << "\nDFA did not generate an equivalence class\n";
|
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.control & CONTROL_DFA_DIFF_ENCODE) {
|
2023-07-06 16:41:56 -07:00
|
|
|
dfa.diff_encode(opts);
|
2014-01-09 16:55:55 -08:00
|
|
|
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_DIFF_ENCODE)
|
2014-01-09 16:55:55 -08:00
|
|
|
dfa.dump_diff_encode(cerr);
|
|
|
|
}
|
|
|
|
|
2020-06-18 05:49:20 -07:00
|
|
|
//cerr << "Checking extended perms " << extended_perms << "\n";
|
|
|
|
if (extended_perms) {
|
|
|
|
//cerr << "creating permstable\n";
|
2023-04-23 20:27:51 -07:00
|
|
|
dfa.compute_perms_table(perms_table, prompt);
|
2020-06-18 05:49:20 -07:00
|
|
|
}
|
2023-04-23 20:27:51 -07:00
|
|
|
chfa = new CHFA(dfa, eq, opts, extended_perms, prompt);
|
2023-07-08 19:49:34 -07:00
|
|
|
if (opts.dump & DUMP_DFA_TRANS_TABLE)
|
2023-04-20 08:31:12 -07:00
|
|
|
chfa->dump(cerr);
|
|
|
|
}
|
|
|
|
catch(int error) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return chfa;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create a dfa from the ruleset
|
|
|
|
* returns: buffer contain dfa tables, @size set to the size of the tables
|
|
|
|
* else NULL on failure, @min_match_len set to the shortest string
|
|
|
|
* that can match the dfa for determining xmatch priority.
|
|
|
|
*/
|
|
|
|
void *aare_rules::create_dfablob(size_t *size, int *min_match_len,
|
|
|
|
vector <aa_perms> &perms_table,
|
|
|
|
optflags const &opts, bool filedfa,
|
2023-04-23 20:27:51 -07:00
|
|
|
bool extended_perms, bool prompt)
|
2023-04-20 08:31:12 -07:00
|
|
|
{
|
|
|
|
char *buffer = NULL;
|
|
|
|
stringstream stream;
|
|
|
|
|
|
|
|
try {
|
|
|
|
CHFA *chfa = create_chfa(min_match_len, perms_table,
|
2023-04-23 20:27:51 -07:00
|
|
|
opts, filedfa, extended_perms,
|
|
|
|
prompt);
|
2023-04-20 08:31:12 -07:00
|
|
|
if (!chfa) {
|
|
|
|
*size = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
2024-08-14 08:57:08 -07:00
|
|
|
chfa->flex_table(stream, opts);
|
2023-04-20 08:31:12 -07:00
|
|
|
delete (chfa);
|
2011-03-13 05:53:08 -07:00
|
|
|
}
|
|
|
|
catch(int error) {
|
|
|
|
*size = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
stringbuf *buf = stream.rdbuf();
|
|
|
|
|
|
|
|
buf->pubseekpos(0);
|
|
|
|
*size = buf->in_avail();
|
|
|
|
|
|
|
|
buffer = (char *)malloc(*size);
|
|
|
|
if (!buffer)
|
|
|
|
return NULL;
|
|
|
|
buf->sgetn(buffer, *size);
|
2023-04-20 08:31:12 -07:00
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* create a dfa from the ruleset
|
|
|
|
* returns: buffer contain dfa tables, @size set to the size of the tables
|
|
|
|
* else NULL on failure, @min_match_len set to the shortest string
|
|
|
|
* that can match the dfa for determining xmatch priority.
|
|
|
|
*/
|
|
|
|
void *aare_rules::create_welded_dfablob(aare_rules *file_rules,
|
|
|
|
size_t *size, int *min_match_len,
|
|
|
|
size_t *new_start,
|
|
|
|
vector <aa_perms> &perms_table,
|
|
|
|
optflags const &opts,
|
2023-04-23 20:27:51 -07:00
|
|
|
bool extended_perms, bool prompt)
|
2023-04-20 08:31:12 -07:00
|
|
|
{
|
|
|
|
int file_min_len;
|
|
|
|
vector <aa_perms> file_perms;
|
|
|
|
CHFA *file_chfa;
|
|
|
|
try {
|
|
|
|
file_chfa = file_rules->create_chfa(&file_min_len,
|
|
|
|
file_perms, opts,
|
2023-04-23 20:27:51 -07:00
|
|
|
true, extended_perms, prompt);
|
2023-04-20 08:31:12 -07:00
|
|
|
if (!file_chfa) {
|
|
|
|
*size = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(int error) {
|
|
|
|
*size = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
CHFA *policy_chfa;
|
|
|
|
try {
|
|
|
|
policy_chfa = create_chfa(min_match_len,
|
|
|
|
perms_table, opts,
|
2023-04-23 20:27:51 -07:00
|
|
|
false, extended_perms, prompt);
|
2023-04-20 08:31:12 -07:00
|
|
|
if (!policy_chfa) {
|
|
|
|
delete file_chfa;
|
|
|
|
*size = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(int error) {
|
|
|
|
delete file_chfa;
|
|
|
|
*size = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
stringstream stream;
|
|
|
|
try {
|
|
|
|
policy_chfa->weld_file_to_policy(*file_chfa, *new_start,
|
2023-04-23 20:27:51 -07:00
|
|
|
extended_perms, prompt,
|
2023-04-20 08:31:12 -07:00
|
|
|
perms_table, file_perms);
|
2024-08-14 08:57:08 -07:00
|
|
|
policy_chfa->flex_table(stream, opts);
|
2023-04-20 08:31:12 -07:00
|
|
|
}
|
|
|
|
catch(int error) {
|
|
|
|
delete (file_chfa);
|
|
|
|
delete (policy_chfa);
|
|
|
|
*size = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
delete file_chfa;
|
|
|
|
delete policy_chfa;
|
|
|
|
|
|
|
|
/* write blob to buffer */
|
|
|
|
stringbuf *buf = stream.rdbuf();
|
|
|
|
|
|
|
|
buf->pubseekpos(0);
|
|
|
|
*size = buf->in_avail();
|
|
|
|
if (file_min_len < *min_match_len)
|
|
|
|
*min_match_len = file_min_len;
|
|
|
|
|
|
|
|
char *buffer = (char *)malloc(*size);
|
|
|
|
if (!buffer)
|
|
|
|
return NULL;
|
|
|
|
buf->sgetn(buffer, *size);
|
|
|
|
|
2011-03-13 05:53:08 -07:00
|
|
|
return buffer;
|
2011-03-13 05:49:15 -07:00
|
|
|
}
|