[apparmor] [patch 01/26] Convert mount and dbus to be subclasses of a generic rule class
john.johansen at canonical.com
john.johansen at canonical.com
Thu Mar 27 15:45:14 UTC 2014
This will simplify add new features as most of the code can reside in
its own class. There are still things to improve but its a start.
Signed-off-by: John Johansen <john.johansen at canonical.com>
---
parser/Makefile | 13 -
parser/dbus.c | 405 +++++++++++++++++++++++++---------
parser/dbus.h | 32 ++
parser/mount.c | 551 +++++++++++++++++++++++++++++++++++++----------
parser/mount.h | 32 +-
parser/parser.h | 22 +
parser/parser_misc.c | 101 --------
parser/parser_policy.c | 29 --
parser/parser_regex.c | 489 -----------------------------------------
parser/parser_variable.c | 66 +----
parser/parser_yacc.y | 51 ++--
parser/profile.cc | 6
parser/profile.h | 7
parser/rule.c | 23 +
parser/rule.h | 51 ++++
15 files changed, 940 insertions(+), 938 deletions(-)
--- 2.9-test.orig/parser/Makefile
+++ 2.9-test/parser/Makefile
@@ -79,8 +79,8 @@
SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
parser_main.c parser_misc.c parser_merge.c parser_symtab.c \
parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \
- parser_alias.c mount.c dbus.c lib.c profile.cc
-HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h
+ parser_alias.c mount.c dbus.c lib.c profile.cc rule.c
+HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h rule.h
TOOLS = apparmor_parser
OBJECTS = $(SRCS:.c=.o)
@@ -188,7 +188,7 @@
parser_yacc.c parser_yacc.h: parser_yacc.y parser.h profile.h
$(YACC) $(YFLAGS) -o parser_yacc.c parser_yacc.y
-parser_lex.c: parser_lex.l parser_yacc.h parser.h profile.h
+parser_lex.c: parser_lex.l parser_yacc.h parser.h profile.h mount.h dbus.h
$(LEX) ${LEXFLAGS} -o$@ $<
parser_lex.o: parser_lex.c parser.h parser_yacc.h
@@ -230,18 +230,21 @@
parser_common.o: parser_common.c parser.h
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
-mount.o: mount.c mount.h parser.h immunix.h
+mount.o: mount.c mount.h parser.h immunix.h rule.h
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
lib.o: lib.c lib.h parser.h
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
-dbus.o: dbus.c dbus.h parser.h immunix.h parser_yacc.h $(APPARMOR_H)
+dbus.o: dbus.c dbus.h parser.h immunix.h parser_yacc.h rule.h $(APPARMOR_H)
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
profile.o: profile.cc profile.h parser.h
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
+rule.o: rule.c rule.h policydb.h
+ $(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
+
parser_version.h: Makefile
@echo \#define PARSER_VERSION \"$(VERSION)\" > .ver
@mv -f .ver $@
--- 2.9-test.orig/parser/dbus.c
+++ 2.9-test/parser/dbus.c
@@ -20,23 +20,91 @@
#include <string.h>
#include <sys/apparmor.h>
+#include <iomanip>
+#include <string>
+#include <iostream>
+#include <sstream>
+
#include "parser.h"
#include "profile.h"
#include "parser_yacc.h"
#include "dbus.h"
-void free_dbus_entry(struct dbus_entry *ent)
+#define _(s) gettext(s)
+
+static int parse_dbus_sub_mode(const char *str_mode, int *result, int fail, const char *mode_desc __unused)
{
- if (!ent)
- return;
- free(ent->bus);
- free(ent->name);
- free(ent->peer_label);
- free(ent->path);
- free(ent->interface);
- free(ent->member);
+ int mode = 0;
+ const char *p;
+
+ PDEBUG("Parsing DBus mode: %s\n", str_mode);
+
+ if (!str_mode)
+ return 0;
+
+ p = str_mode;
+ while (*p) {
+ char current = *p;
+ char lower;
+
+reeval:
+ switch (current) {
+ case COD_READ_CHAR:
+ PDEBUG("Parsing DBus mode: found %s READ\n", mode_desc);
+ mode |= AA_DBUS_RECEIVE;
+ break;
+
+ case COD_WRITE_CHAR:
+ PDEBUG("Parsing DBus mode: found %s WRITE\n",
+ mode_desc);
+ mode |= AA_DBUS_SEND;
+ break;
+
+ /* error cases */
+
+ default:
+ lower = tolower(current);
+ switch (lower) {
+ case COD_READ_CHAR:
+ case COD_WRITE_CHAR:
+ PDEBUG("Parsing DBus mode: found invalid upper case char %c\n",
+ current);
+ warn_uppercase();
+ current = lower;
+ goto reeval;
+ break;
+ default:
+ if (fail)
+ yyerror(_("Internal: unexpected DBus mode character '%c' in input"),
+ current);
+ else
+ return 0;
+ break;
+ }
+ break;
+ }
+ p++;
+ }
- free(ent);
+ PDEBUG("Parsed DBus mode: %s 0x%x\n", str_mode, mode);
+
+ *result = mode;
+ return 1;
+}
+
+int parse_dbus_mode(const char *str_mode, int *mode, int fail)
+{
+ *mode = 0;
+ if (!parse_dbus_sub_mode(str_mode, mode, fail, ""))
+ return 0;
+ if (*mode & ~AA_VALID_DBUS_PERMS) {
+ if (fail)
+ yyerror(_("Internal error generated invalid DBus perm 0x%x\n"),
+ mode);
+ else
+ return 0;
+ }
+ return 1;
}
static int list_len(struct value_list *v)
@@ -60,7 +128,7 @@
cond_ent->vals->value = NULL;
}
-static void move_conditionals(struct dbus_entry *ent, struct cond_entry *conds)
+void dbus_rule::move_conditionals(struct cond_entry *conds)
{
struct cond_entry *cond_ent;
@@ -73,17 +141,17 @@
cond_ent->name);
if (strcmp(cond_ent->name, "bus") == 0) {
- move_conditional_value(&ent->bus, cond_ent);
+ move_conditional_value(&bus, cond_ent);
} else if (strcmp(cond_ent->name, "name") == 0) {
- move_conditional_value(&ent->name, cond_ent);
+ move_conditional_value(&name, cond_ent);
} else if (strcmp(cond_ent->name, "label") == 0) {
- move_conditional_value(&ent->peer_label, cond_ent);
+ move_conditional_value(&peer_label, cond_ent);
} else if (strcmp(cond_ent->name, "path") == 0) {
- move_conditional_value(&ent->path, cond_ent);
+ move_conditional_value(&path, cond_ent);
} else if (strcmp(cond_ent->name, "interface") == 0) {
- move_conditional_value(&ent->interface, cond_ent);
+ move_conditional_value(&interface, cond_ent);
} else if (strcmp(cond_ent->name, "member") == 0) {
- move_conditional_value(&ent->member, cond_ent);
+ move_conditional_value(&member, cond_ent);
} else {
yyerror("invalid dbus conditional \"%s\"\n",
cond_ent->name);
@@ -91,129 +159,252 @@
}
}
-struct dbus_entry *new_dbus_entry(int mode, struct cond_entry *conds,
- struct cond_entry *peer_conds)
+dbus_rule::dbus_rule(int mode_p, struct cond_entry *conds,
+ struct cond_entry *peer_conds):
+ bus(NULL), name(NULL), peer_label(NULL), path(NULL), interface(NULL), member(NULL),
+ mode(0), audit(0), deny(0)
{
- struct dbus_entry *ent;
int name_is_subject_cond = 0, message_rule = 0, service_rule = 0;
- ent = (struct dbus_entry*) calloc(1, sizeof(struct dbus_entry));
- if (!ent)
- goto out;
-
/* Move the global/subject conditionals over & check the results */
- move_conditionals(ent, conds);
- if (ent->name)
+ move_conditionals(conds);
+ if (name)
name_is_subject_cond = 1;
- if (ent->peer_label)
+ if (peer_label)
yyerror("dbus \"label\" conditional can only be used inside of the \"peer=()\" grouping\n");
/* Move the peer conditionals */
- move_conditionals(ent, peer_conds);
+ move_conditionals(peer_conds);
- if (ent->path || ent->interface || ent->member || ent->peer_label ||
- (ent->name && !name_is_subject_cond))
+ if (path || interface || member || peer_label ||
+ (name && !name_is_subject_cond))
message_rule = 1;
- if (ent->name && name_is_subject_cond)
+ if (name && name_is_subject_cond)
service_rule = 1;
if (message_rule && service_rule)
yyerror("dbus rule contains message conditionals and service conditionals\n");
/* Copy mode. If no mode was specified, assign an implied mode. */
- if (mode) {
- ent->mode = mode;
- if (ent->mode & ~AA_VALID_DBUS_PERMS)
+ if (mode_p) {
+ mode = mode_p;
+ if (mode & ~AA_VALID_DBUS_PERMS)
yyerror("mode contains unknown dbus accesss\n");
- else if (message_rule && (ent->mode & AA_DBUS_BIND))
+ else if (message_rule && (mode & AA_DBUS_BIND))
yyerror("dbus \"bind\" access cannot be used with message rule conditionals\n");
- else if (service_rule && (ent->mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)))
+ else if (service_rule && (mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)))
yyerror("dbus \"send\" and/or \"receive\" accesses cannot be used with service rule conditionals\n");
- else if (ent->mode & AA_DBUS_EAVESDROP &&
- (ent->path || ent->interface || ent->member ||
- ent->peer_label || ent->name)) {
+ else if (mode & AA_DBUS_EAVESDROP &&
+ (path || interface || member ||
+ peer_label || name)) {
yyerror("dbus \"eavesdrop\" access can only contain a bus conditional\n");
}
} else {
if (message_rule)
- ent->mode = (AA_DBUS_SEND | AA_DBUS_RECEIVE);
+ mode = (AA_DBUS_SEND | AA_DBUS_RECEIVE);
else if (service_rule)
- ent->mode = (AA_DBUS_BIND);
+ mode = (AA_DBUS_BIND);
else
- ent->mode = AA_VALID_DBUS_PERMS;
+ mode = AA_VALID_DBUS_PERMS;
}
-out:
free_cond_list(conds);
free_cond_list(peer_conds);
- return ent;
}
-struct dbus_entry *dup_dbus_entry(struct dbus_entry *orig)
+ostream &dbus_rule::dump(ostream &os)
+{
+ if (audit)
+ os << "audit ";
+ if (deny)
+ os << "deny ";
+
+ os << "dbus ( ";
+
+ if (mode & AA_DBUS_SEND)
+ os << "send ";
+ if (mode & AA_DBUS_RECEIVE)
+ os << "receive ";
+ if (mode & AA_DBUS_BIND)
+ os << "bind ";
+ if (mode & AA_DBUS_EAVESDROP)
+ os << "eavesdrop ";
+ os << ")";
+
+ if (bus)
+ os << " bus=\"" << bus << "\"";
+ if ((mode & AA_DBUS_BIND) && name)
+ os << " name=\"" << name << "\"";
+ if (path)
+ os << " path=\"" << path << "\"";
+ if (interface)
+ os << " interface=\"" << interface << "\"";
+ if (member)
+ os << " member=\"" << member << os << "\"";
+
+ if (!(mode & AA_DBUS_BIND) && (peer_label || name)) {
+ os << " peer=( ";
+ if (peer_label)
+ os << "label=\"" << peer_label << "\" ";
+ if (name)
+ os << "name=\"" << name << "\" ";
+ os << ")";
+ }
+
+ os << ",\n";
+
+ return os;
+}
+
+int dbus_rule::expand_variables(void)
+{
+ int error = expand_entry_variables(&bus);
+ if (error)
+ return error;
+ error = expand_entry_variables(&name);
+ if (error)
+ return error;
+ error = expand_entry_variables(&peer_label);
+ if (error)
+ return error;
+ error = expand_entry_variables(&path);
+ if (error)
+ return error;
+ error = expand_entry_variables(&interface);
+ if (error)
+ return error;
+ error = expand_entry_variables(&member);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+/* do we want to warn once/profile or just once per compile?? */
+static void warn_once(const char *name)
+{
+ static const char *warned_name = NULL;
+
+ if (warned_name != name) {
+ cerr << "Warning from profile " << name << " (";
+ if (current_filename)
+ cerr << current_filename;
+ else
+ cerr << "stdin";
+ cerr << ") dbus rules not enforced\n";
+ warned_name = name;
+ }
+}
+
+int dbus_rule::gen_policy_re(Profile &prof)
{
- struct dbus_entry *ent = NULL;
- ent = (struct dbus_entry *) calloc(1, sizeof(struct dbus_entry));
- if (!ent)
- return NULL;
-
- DUP_STRING(orig, ent, bus, err);
- DUP_STRING(orig, ent, name, err);
- DUP_STRING(orig, ent, peer_label, err);
- DUP_STRING(orig, ent, path, err);
- DUP_STRING(orig, ent, interface, err);
- DUP_STRING(orig, ent, member, err);
- ent->mode = orig->mode;
- ent->audit = orig->audit;
- ent->deny = orig->deny;
-
- ent->next = orig->next;
-
- return ent;
-
-err:
- free_dbus_entry(ent);
- return NULL;
-}
-
-void print_dbus_entry(struct dbus_entry *ent)
-{
- if (ent->audit)
- fprintf(stderr, "audit ");
- if (ent->deny)
- fprintf(stderr, "deny ");
-
- fprintf(stderr, "dbus ( ");
-
- if (ent->mode & AA_DBUS_SEND)
- fprintf(stderr, "send ");
- if (ent->mode & AA_DBUS_RECEIVE)
- fprintf(stderr, "receive ");
- if (ent->mode & AA_DBUS_BIND)
- fprintf(stderr, "bind ");
- if (ent->mode & AA_DBUS_EAVESDROP)
- fprintf(stderr, "eavesdrop ");
- fprintf(stderr, ")");
-
- if (ent->bus)
- fprintf(stderr, " bus=\"%s\"", ent->bus);
- if ((ent->mode & AA_DBUS_BIND) && ent->name)
- fprintf(stderr, " name=\"%s\"", ent->name);
- if (ent->path)
- fprintf(stderr, " path=\"%s\"", ent->path);
- if (ent->interface)
- fprintf(stderr, " interface=\"%s\"", ent->interface);
- if (ent->member)
- fprintf(stderr, " member=\"%s\"", ent->member);
-
- if (!(ent->mode & AA_DBUS_BIND) && (ent->peer_label || ent->name)) {
- fprintf(stderr, " peer=( ");
- if (ent->peer_label)
- fprintf(stderr, "label=\"%s\" ", ent->peer_label);
- if (ent->name)
- fprintf(stderr, "name=\"%s\" ", ent->name);
- fprintf(stderr, ")");
+ std::string busbuf;
+ std::string namebuf;
+ std::string peer_labelbuf;
+ std::string pathbuf;
+ std::string ifacebuf;
+ std::string memberbuf;
+ std::ostringstream buffer;
+ const char *vec[6];
+
+ pattern_t ptype;
+ int pos;
+
+ if (!kernel_supports_dbus) {
+ warn_once(prof.name);
+ return RULE_NOT_SUPPORTED;
+ }
+
+ buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_DBUS;
+ busbuf.append(buffer.str());
+
+ if (bus) {
+ ptype = convert_aaregex_to_pcre(bus, 0, busbuf, &pos);
+ if (ptype == ePatternInvalid)
+ goto fail;
+ } else {
+ /* match any char except \000 0 or more times */
+ busbuf.append(default_match_pattern);
}
+ vec[0] = busbuf.c_str();
+
+ if (name) {
+ ptype = convert_aaregex_to_pcre(name, 0, namebuf, &pos);
+ if (ptype == ePatternInvalid)
+ goto fail;
+ vec[1] = namebuf.c_str();
+ } else {
+ /* match any char except \000 0 or more times */
+ vec[1] = default_match_pattern;
+ }
+
+ if (peer_label) {
+ ptype = convert_aaregex_to_pcre(peer_label, 0,
+ peer_labelbuf, &pos);
+ if (ptype == ePatternInvalid)
+ goto fail;
+ vec[2] = peer_labelbuf.c_str();
+ } else {
+ /* match any char except \000 0 or more times */
+ vec[2] = default_match_pattern;
+ }
+
+ if (path) {
+ ptype = convert_aaregex_to_pcre(path, 0, pathbuf, &pos);
+ if (ptype == ePatternInvalid)
+ goto fail;
+ vec[3] = pathbuf.c_str();
+ } else {
+ /* match any char except \000 0 or more times */
+ vec[3] = default_match_pattern;
+ }
+
+ if (interface) {
+ ptype = convert_aaregex_to_pcre(interface, 0, ifacebuf, &pos);
+ if (ptype == ePatternInvalid)
+ goto fail;
+ vec[4] = ifacebuf.c_str();
+ } else {
+ /* match any char except \000 0 or more times */
+ vec[4] = default_match_pattern;
+ }
+
+ if (member) {
+ ptype = convert_aaregex_to_pcre(member, 0, memberbuf, &pos);
+ if (ptype == ePatternInvalid)
+ goto fail;
+ vec[5] = memberbuf.c_str();
+ } else {
+ /* match any char except \000 0 or more times */
+ vec[5] = default_match_pattern;
+ }
+
+ if (mode & AA_DBUS_BIND) {
+ if (!aare_add_rule_vec(prof.policy.rules, deny,
+ mode & AA_DBUS_BIND,
+ audit & AA_DBUS_BIND,
+ 2, vec, dfaflags))
+ goto fail;
+ }
+ if (mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
+ if (!aare_add_rule_vec(prof.policy.rules, deny,
+ mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
+ audit & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
+ 6, vec, dfaflags))
+ goto fail;
+ }
+ if (mode & AA_DBUS_EAVESDROP) {
+ if (!aare_add_rule_vec(prof.policy.rules, deny,
+ mode & AA_DBUS_EAVESDROP,
+ audit & AA_DBUS_EAVESDROP,
+ 1, vec, dfaflags))
+ goto fail;
+ }
+
+ prof.policy.count++;
+ return RULE_OK;
- fprintf(stderr, ",\n");
+fail:
+ return RULE_ERROR;
}
--- 2.9-test.orig/parser/dbus.h
+++ 2.9-test/parser/dbus.h
@@ -20,8 +20,14 @@
#define __AA_DBUS_H
#include "parser.h"
+#include "rule.h"
+#include "profile.h"
-struct dbus_entry {
+extern int parse_dbus_mode(const char *str_mode, int *mode, int fail);
+
+class dbus_rule: public rule_t {
+ void move_conditionals(struct cond_entry *conds);
+public:
char *bus;
/**
* Be careful! ->name can be the subject or the peer name, depending on
@@ -37,13 +43,23 @@
int audit;
int deny;
- struct dbus_entry *next;
-};
+ dbus_rule(int mode_p, struct cond_entry *conds,
+ struct cond_entry *peer_conds);
+ virtual ~dbus_rule() {
+ free(bus);
+ free(name);
+ free(peer_label);
+ free(path);
+ free(interface);
+ free(member);
+ };
+
+ virtual ostream &dump(ostream &os);
+ virtual int expand_variables(void);
+ virtual int gen_policy_re(Profile &prof);
+ virtual void post_process(Profile &prof __unused) { };
-void free_dbus_entry(struct dbus_entry *ent);
-struct dbus_entry *new_dbus_entry(int mode, struct cond_entry *conds,
- struct cond_entry *peer_conds);
-struct dbus_entry *dup_dbus_entry(struct dbus_entry *ent);
-void print_dbus_entry(struct dbus_entry *ent);
+
+};
#endif /* __AA_DBUS_H */
--- 2.9-test.orig/parser/mount.c
+++ 2.9-test/parser/mount.c
@@ -215,8 +215,12 @@
#include <stdlib.h>
#include <string.h>
+#include <linux/limits.h>
+#include <iostream>
#include "parser.h"
+#include "policydb.h"
+#include "profile.h"
#include "mount.h"
struct mnt_keyword_table {
@@ -389,146 +393,471 @@
return list;
}
-struct mnt_entry *new_mnt_entry(struct cond_entry *src_conds, char *device,
- struct cond_entry *dst_conds __unused, char *mnt_point,
- int allow)
+mnt_rule::mnt_rule(struct cond_entry *src_conds, char *device_p,
+ struct cond_entry *dst_conds __unused, char *mnt_point_p,
+ int allow_p):
+ mnt_point(mnt_point_p), device(device_p), trans(NULL), opts(NULL),
+ audit(0), deny(0)
{
/* FIXME: dst_conds are ignored atm */
+ aa_class = AA_CLASS_MOUNT;
- struct mnt_entry *ent;
- ent = (struct mnt_entry *) calloc(1, sizeof(struct mnt_entry));
- if (ent) {
- ent->mnt_point = mnt_point;
- ent->device = device;
- ent->dev_type = extract_fstype(&src_conds);
-
- ent->flags = 0;
- ent->inv_flags = 0;
-
- if (src_conds) {
- unsigned int flags = 0, inv_flags = 0;
- struct value_list *list = extract_options(&src_conds, 0);
-
- ent->opts = extract_options(&src_conds, 1);
- if (ent->opts)
- ent->flags = extract_flags(&ent->opts,
- &ent->inv_flags);
-
- if (list) {
- flags = extract_flags(&list, &inv_flags);
- /* these flags are optional so set both */
- flags |= inv_flags;
- inv_flags |= flags;
-
- ent->flags |= flags;
- ent->inv_flags |= inv_flags;
-
- if (ent->opts)
- list_append(ent->opts, list);
- else if (list)
- ent->opts = list;
- }
- }
+ dev_type = extract_fstype(&src_conds);
- if (allow & AA_DUMMY_REMOUNT) {
- allow = AA_MAY_MOUNT;
- ent->flags |= MS_REMOUNT;
- ent->inv_flags = 0;
- } else if (!(ent->flags | ent->inv_flags)) {
- /* no flag options, and not remount, allow everything */
- ent->flags = MS_ALL_FLAGS;
- ent->inv_flags = MS_ALL_FLAGS;
- }
+ if (src_conds) {
+ struct value_list *list = extract_options(&src_conds, 0);
- ent->allow = allow;
+ opts = extract_options(&src_conds, 1);
+ if (opts)
+ flags = extract_flags(&opts, &inv_flags);
- if (src_conds) {
- PERROR(" unsupported mount conditions\n");
- exit(1);
+ if (list) {
+ unsigned int tmpflags, tmpinv_flags = 0;
+
+ tmpflags = extract_flags(&list, &tmpinv_flags);
+ /* these flags are optional so set both */
+ tmpflags |= tmpinv_flags;
+ tmpinv_flags |= tmpflags;
+
+ flags |= tmpflags;
+ inv_flags |= tmpinv_flags;
+
+ if (opts)
+ list_append(opts, list);
+ else if (list)
+ opts = list;
}
}
- return ent;
+ if (allow_p & AA_DUMMY_REMOUNT) {
+ allow_p = AA_MAY_MOUNT;
+ flags |= MS_REMOUNT;
+ inv_flags = 0;
+ } else if (!(flags | inv_flags)) {
+ /* no flag options, and not remount, allow everything */
+ flags = MS_ALL_FLAGS;
+ inv_flags = MS_ALL_FLAGS;
+ }
+
+ allow = allow_p;
+
+ if (src_conds) {
+ PERROR(" unsupported mount conditions\n");
+ exit(1);
+ }
}
-void free_mnt_entry(struct mnt_entry *ent)
+ostream &mnt_rule::dump(ostream &os)
{
- if (!ent)
- return;
+ if (allow & AA_MAY_MOUNT)
+ os << "mount";
+ else if (allow & AA_MAY_UMOUNT)
+ os << "umount";
+ else if (allow & AA_MAY_PIVOTROOT)
+ os << "pivotroot";
+ else
+ os << "error: unknonwn mount perm";
- free_mnt_entry(ent->next);
- free_value_list(ent->opts);
- free_value_list(ent->dev_type);
- free(ent->device);
- free(ent->mnt_point);
- free(ent->trans);
+ os << " (0x" << hex << flags << " - 0x" << inv_flags << ") ";
+ if (dev_type) {
+ os << " type=";
+ print_value_list(dev_type);
+ }
+ if (opts) {
+ os << " options=";
+ print_value_list(opts);
+ }
+ if (device)
+ os << " " << device;
+ if (mnt_point)
+ os << " -> " << mnt_point;
+ if (trans)
+ os << " -> " << trans;
+
+ const char *prefix = deny ? "deny" : "";
+ os << " " << prefix << "(0x" << hex << allow << "/0x" << audit << ")";
+ os << ",\n";
- free(ent);
+ return os;
}
-struct mnt_entry *dup_mnt_entry(struct mnt_entry *orig)
+/* does not currently support expansion of vars in options */
+int mnt_rule::expand_variables(void)
{
- struct mnt_entry *entry = NULL;
+ int error = 0;
- entry = (struct mnt_entry *) calloc(1, sizeof(struct mnt_entry));
- if (!entry)
- return NULL;
+ error = expand_entry_variables(&mnt_point);
+ if (error)
+ return error;
+ error = expand_entry_variables(&device);
+ if (error)
+ return error;
+ error = expand_entry_variables(&trans);
+ if (error)
+ return error;
- DUP_STRING(orig, entry, mnt_point, err);
- DUP_STRING(orig, entry, device, err);
- DUP_STRING(orig, entry, trans, err);
+ return 0;
+}
- entry->dev_type = dup_value_list(orig->dev_type);
- if (orig->dev_type && !(entry->dev_type))
- goto err;
+static int build_mnt_flags(char *buffer, int size, unsigned int flags,
+ unsigned int inv_flags)
+{
+ char *p = buffer;
+ int i, len = 0;
- entry->opts = dup_value_list(orig->opts);
- if (orig->opts && !(entry->opts))
- goto err;
+ if (flags == MS_ALL_FLAGS) {
+ /* all flags are optional */
+ len = snprintf(p, size, "%s", default_match_pattern);
+ if (len < 0 || len >= size)
+ return FALSE;
+ return TRUE;
+ }
+ for (i = 0; i <= 31; ++i) {
+ if ((flags & inv_flags) & (1 << i))
+ len = snprintf(p, size, "(\\x%02x|)", i + 1);
+ else if (flags & (1 << i))
+ len = snprintf(p, size, "\\x%02x", i + 1);
+ else /* no entry = not set */
+ continue;
+
+ if (len < 0 || len >= size)
+ return FALSE;
+ p += len;
+ size -= len;
+ }
- entry->flags = orig->flags;
- entry->inv_flags = orig->inv_flags;
+ /* this needs to go once the backend is updated. */
+ if (buffer == p) {
+ /* match nothing - use impossible 254 as regex parser doesn't
+ * like the empty string
+ */
+ if (size < 9)
+ return FALSE;
- entry->allow = orig->allow;
- entry->audit = orig->audit;
- entry->deny = orig->deny;
+ strcpy(p, "(\\xfe|)");
+ }
- entry->next = orig->next;
+ return TRUE;
+}
- return entry;
+static int build_mnt_opts(std::string& buffer, struct value_list *opts)
+{
+ struct value_list *ent;
+ pattern_t ptype;
+ int pos;
+
+ if (!opts) {
+ buffer.append(default_match_pattern);
+ return TRUE;
+ }
+
+ list_for_each(opts, ent) {
+ ptype = convert_aaregex_to_pcre(ent->value, 0, buffer, &pos);
+ if (ptype == ePatternInvalid)
+ return FALSE;
+
+ if (ent->next)
+ buffer.append(",");
+ }
-err:
- free_mnt_entry(entry);
- return NULL;
+ return TRUE;
}
-void print_mnt_entry(struct mnt_entry *entry)
+/* do we want to warn once/profile or just once per compile?? */
+static void warn_once(const char *name)
{
- if (entry->allow & AA_MAY_MOUNT)
- fprintf(stderr, "mount");
- else if (entry->allow & AA_MAY_UMOUNT)
- fprintf(stderr, "umount");
- else if (entry->allow & AA_MAY_PIVOTROOT)
- fprintf(stderr, "pivotroot");
- else
- fprintf(stderr, "error: unknonwn mount perm");
+ static const char *warned_name = NULL;
+
+ if (warned_name != name) {
+ cerr << "Warning from profile " << name << " (";
+ if (current_filename)
+ cerr << current_filename;
+ else
+ cerr << "stdin";
+ cerr << ") mount rules not enforced\n";
+ warned_name = name;
+ }
+}
+
+int mnt_rule::gen_policy_re(Profile &prof)
+{
+ std::string mntbuf;
+ std::string devbuf;
+ std::string typebuf;
+ char flagsbuf[PATH_MAX + 3];
+ std::string optsbuf;
+ char class_mount_hdr[64];
+ const char *vec[5];
+ int count = 0;
+ unsigned int tmpflags, tmpinv_flags;
+
+ if (!kernel_supports_mount) {
+ warn_once(prof.name);
+ return RULE_NOT_SUPPORTED;
+ }
+
+ sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
+
+ /* a single mount rule may result in multiple matching rules being
+ * created in the backend to cover all the possible choices
+ */
+
+ if ((allow & AA_MAY_MOUNT) && (flags & MS_REMOUNT)
+ && !device && !dev_type) {
+ int tmpallow;
+ /* remount can't be conditional on device and type */
+ /* rule class single byte header */
+ mntbuf.assign(class_mount_hdr);
+ if (mnt_point) {
+ /* both device && mnt_point or just mnt_point */
+ if (!convert_entry(mntbuf, mnt_point))
+ goto fail;
+ vec[0] = mntbuf.c_str();
+ } else {
+ if (!convert_entry(mntbuf, device))
+ goto fail;
+ vec[0] = mntbuf.c_str();
+ }
+ /* skip device */
+ vec[1] = default_match_pattern;
+ /* skip type */
+ vec[2] = default_match_pattern;
+
+ tmpflags = flags;
+ tmpinv_flags = inv_flags;
+ if (tmpflags != MS_ALL_FLAGS)
+ tmpflags &= MS_REMOUNT_FLAGS;
+ if (tmpinv_flags != MS_ALL_FLAGS)
+ tmpflags &= MS_REMOUNT_FLAGS;
+ if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+ goto fail;
+ vec[3] = flagsbuf;
+
+ if (opts)
+ tmpallow = AA_MATCH_CONT;
+ else
+ tmpallow = allow;
+
+ /* rule for match without required data || data MATCH_CONT */
+ if (!aare_add_rule_vec(prof.policy.rules, deny, tmpallow,
+ audit | AA_AUDIT_MNT_DATA, 4,
+ vec, dfaflags))
+ goto fail;
+ count++;
+
+ if (opts) {
+ /* rule with data match required */
+ optsbuf.clear();
+ if (!build_mnt_opts(optsbuf, opts))
+ goto fail;
+ vec[4] = optsbuf.c_str();
+ if (!aare_add_rule_vec(prof.policy.rules, deny,
+ allow,
+ audit | AA_AUDIT_MNT_DATA,
+ 5, vec, dfaflags))
+ goto fail;
+ count++;
+ }
+ }
+ if ((allow & AA_MAY_MOUNT) && (flags & MS_BIND)
+ && !dev_type && !opts) {
+ /* bind mount rules can't be conditional on dev_type or data */
+ /* rule class single byte header */
+ mntbuf.assign(class_mount_hdr);
+ if (!convert_entry(mntbuf, mnt_point))
+ goto fail;
+ vec[0] = mntbuf.c_str();
+ if (!clear_and_convert_entry(devbuf, device))
+ goto fail;
+ vec[1] = devbuf.c_str();
+ /* skip type */
+ vec[2] = default_match_pattern;
+
+ tmpflags = flags;
+ tmpinv_flags = inv_flags;
+ if (tmpflags != MS_ALL_FLAGS)
+ tmpflags &= MS_BIND_FLAGS;
+ if (tmpinv_flags != MS_ALL_FLAGS)
+ tmpflags &= MS_BIND_FLAGS;
+ if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+ goto fail;
+ vec[3] = flagsbuf;
+ if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+ audit, 4, vec, dfaflags))
+ goto fail;
+ count++;
+ }
+ if ((allow & AA_MAY_MOUNT) &&
+ (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED))
+ && !device && !dev_type && !opts) {
+ /* change type base rules can not be conditional on device,
+ * device type or data
+ */
+ /* rule class single byte header */
+ mntbuf.assign(class_mount_hdr);
+ if (!convert_entry(mntbuf, mnt_point))
+ goto fail;
+ vec[0] = mntbuf.c_str();
+ /* skip device and type */
+ vec[1] = default_match_pattern;
+ vec[2] = default_match_pattern;
+
+ tmpflags = flags;
+ tmpinv_flags = inv_flags;
+ if (tmpflags != MS_ALL_FLAGS)
+ tmpflags &= MS_MAKE_FLAGS;
+ if (tmpinv_flags != MS_ALL_FLAGS)
+ tmpflags &= MS_MAKE_FLAGS;
+ if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+ goto fail;
+ vec[3] = flagsbuf;
+ if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+ audit, 4, vec, dfaflags))
+ goto fail;
+ count++;
+ }
+ if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
+ && !dev_type && !opts) {
+ /* mount move rules can not be conditional on dev_type,
+ * or data
+ */
+ /* rule class single byte header */
+ mntbuf.assign(class_mount_hdr);
+ if (!convert_entry(mntbuf, mnt_point))
+ goto fail;
+ vec[0] = mntbuf.c_str();
+ if (!clear_and_convert_entry(devbuf, device))
+ goto fail;
+ vec[1] = devbuf.c_str();
+ /* skip type */
+ vec[2] = default_match_pattern;
+
+ tmpflags = flags;
+ tmpinv_flags = inv_flags;
+ if (tmpflags != MS_ALL_FLAGS)
+ tmpflags &= MS_MOVE_FLAGS;
+ if (tmpinv_flags != MS_ALL_FLAGS)
+ tmpflags &= MS_MOVE_FLAGS;
+ if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+ goto fail;
+ vec[3] = flagsbuf;
+ if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+ audit, 4, vec, dfaflags))
+ goto fail;
+ count++;
+ }
+ if ((allow & AA_MAY_MOUNT) &&
+ (flags | inv_flags) & ~MS_CMDS) {
+ int tmpallow;
+ /* generic mount if flags are set that are not covered by
+ * above commands
+ */
+ /* rule class single byte header */
+ mntbuf.assign(class_mount_hdr);
+ if (!convert_entry(mntbuf, mnt_point))
+ goto fail;
+ vec[0] = mntbuf.c_str();
+ if (!clear_and_convert_entry(devbuf, device))
+ goto fail;
+ vec[1] = devbuf.c_str();
+ typebuf.clear();
+ if (!build_list_val_expr(typebuf, dev_type))
+ goto fail;
+ vec[2] = typebuf.c_str();
+
+ tmpflags = flags;
+ tmpinv_flags = inv_flags;
+ if (tmpflags != MS_ALL_FLAGS)
+ tmpflags &= ~MS_CMDS;
+ if (tmpinv_flags != MS_ALL_FLAGS)
+ tmpinv_flags &= ~MS_CMDS;
+ if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+ goto fail;
+ vec[3] = flagsbuf;
+
+ if (opts)
+ tmpallow = AA_MATCH_CONT;
+ else
+ tmpallow = allow;
+
+ /* rule for match without required data || data MATCH_CONT */
+ if (!aare_add_rule_vec(prof.policy.rules, deny, tmpallow,
+ audit | AA_AUDIT_MNT_DATA, 4,
+ vec, dfaflags))
+ goto fail;
+ count++;
+
+ if (opts) {
+ /* rule with data match required */
+ optsbuf.clear();
+ if (!build_mnt_opts(optsbuf, opts))
+ goto fail;
+ vec[4] = optsbuf.c_str();
+ if (!aare_add_rule_vec(prof.policy.rules, deny,
+ allow,
+ audit | AA_AUDIT_MNT_DATA,
+ 5, vec, dfaflags))
+ goto fail;
+ count++;
+ }
+ }
+ if (allow & AA_MAY_UMOUNT) {
+ /* rule class single byte header */
+ mntbuf.assign(class_mount_hdr);
+ if (!convert_entry(mntbuf, mnt_point))
+ goto fail;
+ vec[0] = mntbuf.c_str();
+ if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+ audit, 1, vec, dfaflags))
+ goto fail;
+ count++;
+ }
+ if (allow & AA_MAY_PIVOTROOT) {
+ /* rule class single byte header */
+ mntbuf.assign(class_mount_hdr);
+ if (!convert_entry(mntbuf, mnt_point))
+ goto fail;
+ vec[0] = mntbuf.c_str();
+ if (!clear_and_convert_entry(devbuf, device))
+ goto fail;
+ vec[1] = devbuf.c_str();
+ if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+ audit, 2, vec, dfaflags))
+ goto fail;
+ count++;
+ }
- fprintf(stderr, " (0x%x - 0x%x) ", entry->flags, entry->inv_flags);
- if (entry->dev_type) {
- fprintf(stderr, " type=");
- print_value_list(entry->dev_type);
- }
- if (entry->opts) {
- fprintf(stderr, " options=");
- print_value_list(entry->opts);
- }
- if (entry->device)
- fprintf(stderr, " %s", entry->device);
- if (entry->mnt_point)
- fprintf(stderr, " -> %s", entry->mnt_point);
- if (entry->trans)
- fprintf(stderr, " -> %s", entry->trans);
+ if (!count)
+ /* didn't actually encode anything */
+ goto fail;
+
+ prof.policy.count++;
+ return RULE_OK;
+
+fail:
+ PERROR("Enocoding of mount rule failed\n");
+ return RULE_ERROR;
+}
- fprintf(stderr, " %s (0x%x/0x%x)", entry->deny ? "deny" : "", entry->allow, entry->audit);
- fprintf(stderr, ",\n");
+void mnt_rule::post_process(Profile &prof)
+{
+ if (trans) {
+ unsigned int mode = 0;
+ int n = add_entry_to_x_table(&prof, trans);
+ if (!n) {
+ PERROR("Profile %s has too many specified profile transitions.\n", prof.name);
+ exit(1);
+ }
+
+ if (allow & AA_USER_EXEC)
+ mode |= SHIFT_MODE(n << 10, AA_USER_SHIFT);
+ if (allow & AA_OTHER_EXEC)
+ mode |= SHIFT_MODE(n << 10, AA_OTHER_SHIFT);
+ allow = ((allow & ~AA_ALL_EXEC_MODIFIERS) |
+ (mode & AA_ALL_EXEC_MODIFIERS));
+
+ trans = NULL;
+ }
}
+
+
--- 2.9-test.orig/parser/mount.h
+++ 2.9-test/parser/mount.h
@@ -19,7 +19,11 @@
#ifndef __AA_MOUNT_H
#define __AA_MOUNT_H
+#include <ostream>
+
#include "parser.h"
+#include "rule.h"
+
#define MS_RDONLY (1 << 0)
#define MS_RW 0
@@ -109,7 +113,8 @@
* remapped to a mount option*/
-struct mnt_entry {
+class mnt_rule: public rule_t {
+public:
char *mnt_point;
char *device;
char *trans;
@@ -120,17 +125,26 @@
int allow, audit;
int deny;
- struct mnt_entry *next;
-};
-void print_mnt_entry(struct mnt_entry *entry);
+ mnt_rule(struct cond_entry *src_conds, char *device_p,
+ struct cond_entry *dst_conds __unused, char *mnt_point_p,
+ int allow_p);
+ virtual ~mnt_rule()
+ {
+ free_value_list(opts);
+ free_value_list(dev_type);
+ free(device);
+ free(mnt_point);
+ free(trans);
+ }
+
+ virtual ostream &dump(ostream &os);
+ virtual int expand_variables(void);
+ virtual int gen_policy_re(Profile &prof);
+ virtual void post_process(Profile &prof __unused);
+};
int is_valid_mnt_cond(const char *name, int src);
-struct mnt_entry *new_mnt_entry(struct cond_entry *sconds, char *device,
- struct cond_entry *dconds, char *mnt_point,
- int mode);
-struct mnt_entry *dup_mnt_entry(struct mnt_entry *orig);
-void free_mnt_entry(struct mnt_entry *ent);
#endif /* __AA_MOUNT_H */
--- 2.9-test.orig/parser/parser.h
+++ 2.9-test/parser/parser.h
@@ -30,12 +30,13 @@
#include "libapparmor_re/apparmor_re.h"
#include "libapparmor_re/aare_rules.h"
+#include <string>
+
using namespace std;
#include <set>
class Profile;
-
-struct mnt_ent;
+class rule_t;
/* Global variable to pass token to lexer. Will be replaced by parameter
* when lexer and parser are made reentrant
@@ -256,9 +257,14 @@
extern const char *basedir;
/* parser_regex.c */
+extern const char *default_match_pattern;
+extern pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
+ std::string& pcre, int *first_re_pos);
+extern int build_list_val_expr(std::string& buffer, struct value_list *list);
+extern int convert_entry(std::string& buffer, char *entry);
+extern int clear_and_convert_entry(std::string& buffer, char *entry);
extern int process_regex(Profile *prof);
extern int post_process_entry(struct cod_entry *entry);
-extern int process_dbus(Profile *prof);
extern void reset_regex(void);
@@ -267,11 +273,13 @@
extern int process_policy_ents(Profile *prof);
/* parser_variable.c */
+int expand_entry_variables(char **name);
extern int process_variables(Profile *prof);
extern struct var_string *split_out_var(const char *string);
extern void free_var_string(struct var_string *var);
/* parser_misc.c */
+extern void warn_uppercase(void);
extern int is_blacklisted(const char *name, const char *path);
extern struct value_list *new_value_list(char *value);
extern struct value_list *dup_value_list(struct value_list *list);
@@ -289,7 +297,6 @@
extern int get_rlimit(const char *name);
extern char *process_var(const char *var);
extern int parse_mode(const char *mode);
-extern int parse_dbus_mode(const char *str_mode, int *mode, int fail);
extern struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id);
extern struct aa_network_entry *new_network_ent(unsigned int family,
unsigned int type,
@@ -303,15 +310,13 @@
extern int str_to_boolean(const char* str);
extern struct cod_entry *copy_cod_entry(struct cod_entry *cod);
extern void free_cod_entries(struct cod_entry *list);
-extern void free_mnt_entries(struct mnt_entry *list);
-extern void free_dbus_entries(struct dbus_entry *list);
extern void __debug_capabilities(uint64_t capset, const char *name);
void __debug_network(unsigned int *array, const char *name);
void debug_cod_entries(struct cod_entry *list);
/* parser_symtab.c */
-struct set_value {;
+struct set_value {
char *val;
struct set_value *next;
};
@@ -345,9 +350,10 @@
/* parser_policy.c */
extern void add_to_list(Profile *profile);
extern void add_hat_to_policy(Profile *policy, Profile *hat);
+extern int add_entry_to_x_table(Profile *prof, char *name);
extern void add_entry_to_policy(Profile *policy, struct cod_entry *entry);
extern void post_process_file_entries(Profile *prof);
-extern void post_process_mnt_entries(Profile *prof);
+extern void post_process_rule_entries(Profile *prof);
extern int post_process_policy(int debug_only);
extern int process_profile_regex(Profile *prof);
extern int process_profile_variables(Profile *prof);
--- 2.9-test.orig/parser/parser_misc.c
+++ 2.9-test/parser/parser_misc.c
@@ -596,7 +596,7 @@
static int warned_uppercase = 0;
-static void warn_uppercase(void)
+void warn_uppercase(void)
{
if (!warned_uppercase) {
pwarn(_("Uppercase qualifiers \"RWLIMX\" are deprecated, please convert to lowercase\n"
@@ -792,81 +792,6 @@
return mode;
}
-static int parse_dbus_sub_mode(const char *str_mode, int *result, int fail, const char *mode_desc __unused)
-{
- int mode = 0;
- const char *p;
-
- PDEBUG("Parsing DBus mode: %s\n", str_mode);
-
- if (!str_mode)
- return 0;
-
- p = str_mode;
- while (*p) {
- char current = *p;
- char lower;
-
-reeval:
- switch (current) {
- case COD_READ_CHAR:
- PDEBUG("Parsing DBus mode: found %s READ\n", mode_desc);
- mode |= AA_DBUS_RECEIVE;
- break;
-
- case COD_WRITE_CHAR:
- PDEBUG("Parsing DBus mode: found %s WRITE\n",
- mode_desc);
- mode |= AA_DBUS_SEND;
- break;
-
- /* error cases */
-
- default:
- lower = tolower(current);
- switch (lower) {
- case COD_READ_CHAR:
- case COD_WRITE_CHAR:
- PDEBUG("Parsing DBus mode: found invalid upper case char %c\n",
- current);
- warn_uppercase();
- current = lower;
- goto reeval;
- break;
- default:
- if (fail)
- yyerror(_("Internal: unexpected DBus mode character '%c' in input"),
- current);
- else
- return 0;
- break;
- }
- break;
- }
- p++;
- }
-
- PDEBUG("Parsed DBus mode: %s 0x%x\n", str_mode, mode);
-
- *result = mode;
- return 1;
-}
-
-int parse_dbus_mode(const char *str_mode, int *mode, int fail)
-{
- *mode = 0;
- if (!parse_dbus_sub_mode(str_mode, mode, fail, ""))
- return 0;
- if (*mode & ~AA_VALID_DBUS_PERMS) {
- if (fail)
- yyerror(_("Internal error generated invalid DBus perm 0x%x\n"),
- mode);
- else
- return 0;
- }
- return 1;
-}
-
struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id)
{
struct cod_entry *entry = NULL;
@@ -938,30 +863,6 @@
free(list);
}
-void free_mnt_entries(struct mnt_entry *list)
-{
- if (!list)
- return;
- if (list->next)
- free_mnt_entries(list->next);
- free(list->mnt_point);
- free(list->device);
- free_value_list(list->dev_type);
- free_value_list(list->opts);
-
- free(list);
-}
-
-void free_dbus_entries(struct dbus_entry *list)
-{
- if (!list)
- return;
- if (list->next)
- free_dbus_entries(list->next);
-
- free_dbus_entry(list);
-}
-
static void debug_base_perm_mask(int mask)
{
if (HAS_MAY_READ(mask))
--- 2.9-test.orig/parser/parser_policy.c
+++ 2.9-test/parser/parser_policy.c
@@ -32,8 +32,6 @@
#include "parser.h"
#include "profile.h"
-#include "mount.h"
-#include "dbus.h"
#include "parser_yacc.h"
/* #define DEBUG */
@@ -70,7 +68,7 @@
}
}
-static int add_entry_to_x_table(Profile *prof, char *name)
+int add_entry_to_x_table(Profile *prof, char *name)
{
int i;
for (i = (AA_EXEC_LOCAL >> 10) + 1; i < AA_EXEC_COUNT; i++) {
@@ -192,29 +190,10 @@
}
}
-void post_process_mnt_entries(Profile *prof)
+void post_process_rule_entries(Profile *prof)
{
- struct mnt_entry *entry;
-
- list_for_each(prof->mnt_ents, entry) {
- if (entry->trans) {
- unsigned int mode = 0;
- int n = add_entry_to_x_table(prof, entry->trans);
- if (!n) {
- PERROR("Profile %s has too many specified profile transitions.\n", prof->name);
- exit(1);
- }
-
- if (entry->allow & AA_USER_EXEC)
- mode |= SHIFT_MODE(n << 10, AA_USER_SHIFT);
- if (entry->allow & AA_OTHER_EXEC)
- mode |= SHIFT_MODE(n << 10, AA_OTHER_SHIFT);
- entry->allow = ((entry->allow & ~AA_ALL_EXEC_MODIFIERS) |
- (mode & AA_ALL_EXEC_MODIFIERS));
-
- entry->trans = NULL;
- }
- }
+ for (RuleList::iterator i = prof->rule_ents.begin(); i != prof->rule_ents.end(); i++)
+ (*i)->post_process(*prof);
}
--- 2.9-test.orig/parser/parser_regex.c
+++ 2.9-test/parser/parser_regex.c
@@ -35,9 +35,8 @@
#include "profile.h"
#include "libapparmor_re/apparmor_re.h"
#include "libapparmor_re/aare_rules.h"
-#include "mount.h"
-#include "dbus.h"
#include "policydb.h"
+#include "rule.h"
enum error_type {
e_no_error,
@@ -45,7 +44,7 @@
};
/* match any char except \000 0 or more times */
-static const char *default_match_pattern = "[^\\000]*";
+const char *default_match_pattern = "[^\\000]*";
/* Filters out multiple slashes (except if the first two are slashes,
* that's a distinct namespace in linux) and trailing slashes.
@@ -90,8 +89,8 @@
/* converts the apparmor regex in aare and appends pcre regex output
* to pcre string */
-static pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
- std::string& pcre, int *first_re_pos)
+pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
+ std::string& pcre, int *first_re_pos)
{
#define update_re_pos(X) if (!(*first_re_pos)) { *first_re_pos = (X); }
#define MAX_ALT_DEPTH 50
@@ -612,7 +611,7 @@
return error;
}
-static int build_list_val_expr(std::string& buffer, struct value_list *list)
+int build_list_val_expr(std::string& buffer, struct value_list *list)
{
struct value_list *ent;
pattern_t ptype;
@@ -642,7 +641,7 @@
return FALSE;
}
-static int convert_entry(std::string& buffer, char *entry)
+int convert_entry(std::string& buffer, char *entry)
{
pattern_t ptype;
int pos;
@@ -658,487 +657,19 @@
return TRUE;
}
-static int clear_and_convert_entry(std::string& buffer, char *entry)
+int clear_and_convert_entry(std::string& buffer, char *entry)
{
buffer.clear();
return convert_entry(buffer, entry);
}
-static int build_mnt_flags(char *buffer, int size, unsigned int flags,
- unsigned int inv_flags)
+int post_process_policydb_ents(Profile *prof)
{
- char *p = buffer;
- int i, len = 0;
-
- if (flags == MS_ALL_FLAGS) {
- /* all flags are optional */
- len = snprintf(p, size, "%s", default_match_pattern);
- if (len < 0 || len >= size)
- return FALSE;
- return TRUE;
- }
- for (i = 0; i <= 31; ++i) {
- if ((flags & inv_flags) & (1 << i))
- len = snprintf(p, size, "(\\x%02x|)", i + 1);
- else if (flags & (1 << i))
- len = snprintf(p, size, "\\x%02x", i + 1);
- else /* no entry = not set */
- continue;
-
- if (len < 0 || len >= size)
+ for (RuleList::iterator i = prof->rule_ents.begin(); i != prof->rule_ents.end(); i++) {
+ if ((*i)->gen_policy_re(*prof) == RULE_ERROR)
return FALSE;
- p += len;
- size -= len;
- }
-
- /* this needs to go once the backend is updated. */
- if (buffer == p) {
- /* match nothing - use impossible 254 as regex parser doesn't
- * like the empty string
- */
- if (size < 9)
- return FALSE;
-
- strcpy(p, "(\\xfe|)");
- }
-
- return TRUE;
-}
-
-static int build_mnt_opts(std::string& buffer, struct value_list *opts)
-{
- struct value_list *ent;
- pattern_t ptype;
- int pos;
-
- if (!opts) {
- buffer.append(default_match_pattern);
- return TRUE;
}
- list_for_each(opts, ent) {
- ptype = convert_aaregex_to_pcre(ent->value, 0, buffer, &pos);
- if (ptype == ePatternInvalid)
- return FALSE;
-
- if (ent->next)
- buffer.append(",");
- }
-
- return TRUE;
-}
-
-static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
-{
- std::string mntbuf;
- std::string devbuf;
- std::string typebuf;
- char flagsbuf[PATH_MAX + 3];
- std::string optsbuf;
- char class_mount_hdr[64];
- const char *vec[5];
- int count = 0;
- unsigned int flags, inv_flags;
-
- sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
-
- /* a single mount rule may result in multiple matching rules being
- * created in the backend to cover all the possible choices
- */
-
- if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_REMOUNT)
- && !entry->device && !entry->dev_type) {
- int allow;
- /* remount can't be conditional on device and type */
- /* rule class single byte header */
- mntbuf.assign(class_mount_hdr);
- if (entry->mnt_point) {
- /* both device && mnt_point or just mnt_point */
- if (!convert_entry(mntbuf, entry->mnt_point))
- goto fail;
- vec[0] = mntbuf.c_str();
- } else {
- if (!convert_entry(mntbuf, entry->device))
- goto fail;
- vec[0] = mntbuf.c_str();
- }
- /* skip device */
- vec[1] = default_match_pattern;
- /* skip type */
- vec[2] = default_match_pattern;
-
- flags = entry->flags;
- inv_flags = entry->inv_flags;
- if (flags != MS_ALL_FLAGS)
- flags &= MS_REMOUNT_FLAGS;
- if (inv_flags != MS_ALL_FLAGS)
- flags &= MS_REMOUNT_FLAGS;
- if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
- goto fail;
- vec[3] = flagsbuf;
-
- if (entry->opts)
- allow = AA_MATCH_CONT;
- else
- allow = entry->allow;
-
- /* rule for match without required data || data MATCH_CONT */
- if (!aare_add_rule_vec(dfarules, entry->deny, allow,
- entry->audit | AA_AUDIT_MNT_DATA, 4,
- vec, dfaflags))
- goto fail;
- count++;
-
- if (entry->opts) {
- /* rule with data match required */
- optsbuf.clear();
- if (!build_mnt_opts(optsbuf, entry->opts))
- goto fail;
- vec[4] = optsbuf.c_str();
- if (!aare_add_rule_vec(dfarules, entry->deny,
- entry->allow,
- entry->audit | AA_AUDIT_MNT_DATA,
- 5, vec, dfaflags))
- goto fail;
- count++;
- }
- }
- if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_BIND)
- && !entry->dev_type && !entry->opts) {
- /* bind mount rules can't be conditional on dev_type or data */
- /* rule class single byte header */
- mntbuf.assign(class_mount_hdr);
- if (!convert_entry(mntbuf, entry->mnt_point))
- goto fail;
- vec[0] = mntbuf.c_str();
- if (!clear_and_convert_entry(devbuf, entry->device))
- goto fail;
- vec[1] = devbuf.c_str();
- /* skip type */
- vec[2] = default_match_pattern;
-
- flags = entry->flags;
- inv_flags = entry->inv_flags;
- if (flags != MS_ALL_FLAGS)
- flags &= MS_BIND_FLAGS;
- if (inv_flags != MS_ALL_FLAGS)
- flags &= MS_BIND_FLAGS;
- if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
- goto fail;
- vec[3] = flagsbuf;
- if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
- entry->audit, 4, vec, dfaflags))
- goto fail;
- count++;
- }
- if ((entry->allow & AA_MAY_MOUNT) &&
- (entry->flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED))
- && !entry->device && !entry->dev_type && !entry->opts) {
- /* change type base rules can not be conditional on device,
- * device type or data
- */
- /* rule class single byte header */
- mntbuf.assign(class_mount_hdr);
- if (!convert_entry(mntbuf, entry->mnt_point))
- goto fail;
- vec[0] = mntbuf.c_str();
- /* skip device and type */
- vec[1] = default_match_pattern;
- vec[2] = default_match_pattern;
-
- flags = entry->flags;
- inv_flags = entry->inv_flags;
- if (flags != MS_ALL_FLAGS)
- flags &= MS_MAKE_FLAGS;
- if (inv_flags != MS_ALL_FLAGS)
- flags &= MS_MAKE_FLAGS;
- if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
- goto fail;
- vec[3] = flagsbuf;
- if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
- entry->audit, 4, vec, dfaflags))
- goto fail;
- count++;
- }
- if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_MOVE)
- && !entry->dev_type && !entry->opts) {
- /* mount move rules can not be conditional on dev_type,
- * or data
- */
- /* rule class single byte header */
- mntbuf.assign(class_mount_hdr);
- if (!convert_entry(mntbuf, entry->mnt_point))
- goto fail;
- vec[0] = mntbuf.c_str();
- if (!clear_and_convert_entry(devbuf, entry->device))
- goto fail;
- vec[1] = devbuf.c_str();
- /* skip type */
- vec[2] = default_match_pattern;
-
- flags = entry->flags;
- inv_flags = entry->inv_flags;
- if (flags != MS_ALL_FLAGS)
- flags &= MS_MOVE_FLAGS;
- if (inv_flags != MS_ALL_FLAGS)
- flags &= MS_MOVE_FLAGS;
- if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
- goto fail;
- vec[3] = flagsbuf;
- if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
- entry->audit, 4, vec, dfaflags))
- goto fail;
- count++;
- }
- if ((entry->allow & AA_MAY_MOUNT) &&
- (entry->flags | entry->inv_flags) & ~MS_CMDS) {
- int allow;
- /* generic mount if flags are set that are not covered by
- * above commands
- */
- /* rule class single byte header */
- mntbuf.assign(class_mount_hdr);
- if (!convert_entry(mntbuf, entry->mnt_point))
- goto fail;
- vec[0] = mntbuf.c_str();
- if (!clear_and_convert_entry(devbuf, entry->device))
- goto fail;
- vec[1] = devbuf.c_str();
- typebuf.clear();
- if (!build_list_val_expr(typebuf, entry->dev_type))
- goto fail;
- vec[2] = typebuf.c_str();
-
- flags = entry->flags;
- inv_flags = entry->inv_flags;
- if (flags != MS_ALL_FLAGS)
- flags &= ~MS_CMDS;
- if (inv_flags != MS_ALL_FLAGS)
- flags &= ~MS_CMDS;
- if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
- goto fail;
- vec[3] = flagsbuf;
-
- if (entry->opts)
- allow = AA_MATCH_CONT;
- else
- allow = entry->allow;
-
- /* rule for match without required data || data MATCH_CONT */
- if (!aare_add_rule_vec(dfarules, entry->deny, allow,
- entry->audit | AA_AUDIT_MNT_DATA, 4,
- vec, dfaflags))
- goto fail;
- count++;
-
- if (entry->opts) {
- /* rule with data match required */
- optsbuf.clear();
- if (!build_mnt_opts(optsbuf, entry->opts))
- goto fail;
- vec[4] = optsbuf.c_str();
- if (!aare_add_rule_vec(dfarules, entry->deny,
- entry->allow,
- entry->audit | AA_AUDIT_MNT_DATA,
- 5, vec, dfaflags))
- goto fail;
- count++;
- }
- }
- if (entry->allow & AA_MAY_UMOUNT) {
- /* rule class single byte header */
- mntbuf.assign(class_mount_hdr);
- if (!convert_entry(mntbuf, entry->mnt_point))
- goto fail;
- vec[0] = mntbuf.c_str();
- if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
- entry->audit, 1, vec, dfaflags))
- goto fail;
- count++;
- }
- if (entry->allow & AA_MAY_PIVOTROOT) {
- /* rule class single byte header */
- mntbuf.assign(class_mount_hdr);
- if (!convert_entry(mntbuf, entry->mnt_point))
- goto fail;
- vec[0] = mntbuf.c_str();
- if (!clear_and_convert_entry(devbuf, entry->device))
- goto fail;
- vec[1] = devbuf.c_str();
- if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
- entry->audit, 2, vec, dfaflags))
- goto fail;
- count++;
- }
-
- if (!count)
- /* didn't actually encode anything */
- goto fail;
-
- return TRUE;
-
-fail:
- PERROR("Enocoding of mount rule failed\n");
- return FALSE;
-}
-
-
-static int process_dbus_entry(aare_ruleset_t *dfarules, struct dbus_entry *entry)
-{
- std::string busbuf;
- std::string namebuf;
- std::string peer_labelbuf;
- std::string pathbuf;
- std::string ifacebuf;
- std::string memberbuf;
- std::ostringstream buffer;
- const char *vec[6];
-
- pattern_t ptype;
- int pos;
-
- if (!entry) /* shouldn't happen */
- return TRUE;
-
- buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_DBUS;
- busbuf.append(buffer.str());
-
- if (entry->bus) {
- ptype = convert_aaregex_to_pcre(entry->bus, 0, busbuf, &pos);
- if (ptype == ePatternInvalid)
- goto fail;
- } else {
- /* match any char except \000 0 or more times */
- busbuf.append(default_match_pattern);
- }
- vec[0] = busbuf.c_str();
-
- if (entry->name) {
- ptype = convert_aaregex_to_pcre(entry->name, 0, namebuf, &pos);
- if (ptype == ePatternInvalid)
- goto fail;
- vec[1] = namebuf.c_str();
- } else {
- /* match any char except \000 0 or more times */
- vec[1] = default_match_pattern;
- }
-
- if (entry->peer_label) {
- ptype = convert_aaregex_to_pcre(entry->peer_label, 0,
- peer_labelbuf, &pos);
- if (ptype == ePatternInvalid)
- goto fail;
- vec[2] = peer_labelbuf.c_str();
- } else {
- /* match any char except \000 0 or more times */
- vec[2] = default_match_pattern;
- }
-
- if (entry->path) {
- ptype = convert_aaregex_to_pcre(entry->path, 0, pathbuf, &pos);
- if (ptype == ePatternInvalid)
- goto fail;
- vec[3] = pathbuf.c_str();
- } else {
- /* match any char except \000 0 or more times */
- vec[3] = default_match_pattern;
- }
-
- if (entry->interface) {
- ptype = convert_aaregex_to_pcre(entry->interface, 0, ifacebuf, &pos);
- if (ptype == ePatternInvalid)
- goto fail;
- vec[4] = ifacebuf.c_str();
- } else {
- /* match any char except \000 0 or more times */
- vec[4] = default_match_pattern;
- }
-
- if (entry->member) {
- ptype = convert_aaregex_to_pcre(entry->member, 0, memberbuf, &pos);
- if (ptype == ePatternInvalid)
- goto fail;
- vec[5] = memberbuf.c_str();
- } else {
- /* match any char except \000 0 or more times */
- vec[5] = default_match_pattern;
- }
-
- if (entry->mode & AA_DBUS_BIND) {
- if (!aare_add_rule_vec(dfarules, entry->deny,
- entry->mode & AA_DBUS_BIND,
- entry->audit & AA_DBUS_BIND,
- 2, vec, dfaflags))
- goto fail;
- }
- if (entry->mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
- if (!aare_add_rule_vec(dfarules, entry->deny,
- entry->mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
- entry->audit & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
- 6, vec, dfaflags))
- goto fail;
- }
- if (entry->mode & AA_DBUS_EAVESDROP) {
- if (!aare_add_rule_vec(dfarules, entry->deny,
- entry->mode & AA_DBUS_EAVESDROP,
- entry->audit & AA_DBUS_EAVESDROP,
- 1, vec, dfaflags))
- goto fail;
- }
- return TRUE;
-
-fail:
- return FALSE;
-}
-
-static int post_process_mnt_ents(Profile *prof)
-{
- int ret = TRUE;
- int count = 0;
-
- /* Add fns for rules that should be added to policydb here */
- if (prof->mnt_ents && kernel_supports_mount) {
- struct mnt_entry *entry;
- list_for_each(prof->mnt_ents, entry) {
- if (!process_mnt_entry(prof->policy.rules, entry))
- ret = FALSE;
- count++;
- }
- } else if (prof->mnt_ents && !kernel_supports_mount)
- pwarn("profile %s mount rules not enforced\n", prof->name);
-
- prof->policy.count += count;
-
- return ret;
-}
-
-static int post_process_dbus_ents(Profile *prof)
-{
- int ret = TRUE;
- int count = 0;
-
- if (prof->dbus_ents && kernel_supports_dbus) {
- struct dbus_entry *entry;
-
- list_for_each(prof->dbus_ents, entry) {
- if (!process_dbus_entry(prof->policy.rules, entry))
- ret = FALSE;
- count++;
- }
- } else if (prof->dbus_ents && !kernel_supports_dbus)
- pwarn("profile %s dbus rules not enforced\n", prof->name);
-
- prof->policy.count += count;
- return ret;
-}
-
-int post_process_policydb_ents(Profile *prof)
-{
- if (!post_process_mnt_ents(prof))
- return FALSE;
- if (!post_process_dbus_ents(prof))
- return FALSE;
-
return TRUE;
}
--- 2.9-test.orig/parser/parser_variable.c
+++ 2.9-test/parser/parser_variable.c
@@ -15,6 +15,7 @@
* along with this program; if not, contact Novell, Inc.
*/
+#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
@@ -213,13 +214,15 @@
}
/* doesn't handle variables in options atm */
-static int expand_entry_variables(char **name, void *entry)
+int expand_entry_variables(char **name)
{
struct set_value *valuelist;
struct var_string *split_var;
int ret;
- if (!entry) /* can happen when entry is optional */
+ assert(name);
+
+ if (!*name) /* can happen when entry is optional */
return 0;
while ((split_var = split_out_var(*name))) {
@@ -251,7 +254,7 @@
struct cod_entry *entry;
list_for_each(entry_list, entry) {
- error = expand_entry_variables(&entry->name, entry);
+ error = expand_entry_variables(&entry->name);
if (error)
return error;
}
@@ -259,69 +262,24 @@
return 0;
}
-/* does not currently support expansion of vars in options */
-static int process_variables_in_mnt_entries(struct mnt_entry *entry_list)
+static int process_variables_in_rules(Profile &prof)
{
- int error = 0;
- struct mnt_entry *entry;
-
- list_for_each(entry_list, entry) {
- error = expand_entry_variables(&entry->mnt_point, entry);
+ for(RuleList::iterator i = prof.rule_ents.begin(); i != prof.rule_ents.end(); i++) {
+ int error = (*i)->expand_variables();
if (error)
return error;
- error = expand_entry_variables(&entry->device, entry);
- if (error)
- return error;
- error = expand_entry_variables(&entry->trans, entry);
- if (error)
- return error;
-
}
return 0;
}
-static int process_dbus_variables(struct dbus_entry *entry_list)
-{
- int error = 0;
- struct dbus_entry *entry;
-
- list_for_each(entry_list, entry) {
- error = expand_entry_variables(&entry->bus, entry);
- if (error)
- return error;
- error = expand_entry_variables(&entry->name, entry);
- if (error)
- return error;
- error = expand_entry_variables(&entry->peer_label, entry);
- if (error)
- return error;
- error = expand_entry_variables(&entry->path, entry);
- if (error)
- return error;
- error = expand_entry_variables(&entry->interface, entry);
- if (error)
- return error;
- error = expand_entry_variables(&entry->member, entry);
- if (error)
- return error;
-
- }
-
- return 0;
-}
int process_profile_variables(Profile *prof)
{
int error = 0;
-
- error = process_variables_in_entries(prof->entries);
-
- if (!error)
- error = process_variables_in_mnt_entries(prof->mnt_ents);
-
- if (!error)
- error = process_dbus_variables(prof->dbus_ents);
+ error = process_variables_in_entries(prof->entries);
+ if (!error)
+ error = process_variables_in_rules(*prof);
return error;
}
--- 2.9-test.orig/parser/parser_yacc.y
+++ 2.9-test/parser/parser_yacc.y
@@ -72,11 +72,11 @@
struct cod_entry *do_file_rule(char *ns, char *id, int mode,
char *link_id, char *nt);
-struct mnt_entry *do_mnt_rule(struct cond_entry *src_conds, char *src,
- struct cond_entry *dst_conds, char *dst,
- int mode);
-struct mnt_entry *do_pivot_rule(struct cond_entry *old, char *root,
- char *transition);
+mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
+ struct cond_entry *dst_conds, char *dst,
+ int mode);
+mnt_rule *do_pivot_rule(struct cond_entry *old, char *root,
+ char *transition);
void add_local_entry(Profile *prof);
@@ -162,6 +162,12 @@
/* debug flag values */
%token TOK_FLAGS
+%code requires {
+ #include "profile.h"
+ #include "mount.h"
+ #include "dbus.h"
+}
+
%union {
char *id;
char *flag_id;
@@ -170,8 +176,9 @@
Profile *prof;
struct cod_net_entry *net_entry;
struct cod_entry *user_entry;
- struct mnt_entry *mnt_entry;
- struct dbus_entry *dbus_entry;
+
+ mnt_rule *mnt_entry;
+ dbus_rule *dbus_entry;
flagvals flags;
int fmode;
@@ -281,7 +288,7 @@
prof->flags.complain = 1;
post_process_file_entries(prof);
- post_process_mnt_entries(prof);
+ post_process_rule_entries(prof);
PDEBUG("%s: flags='%s%s'\n",
$2,
prof->flags.complain ? "complain, " : "",
@@ -667,8 +674,8 @@
} else if ($2.audit) {
$3->audit = $3->allow;
}
- $3->next = $1->mnt_ents;
- $1->mnt_ents = $3;
+
+ $1->rule_ents.push_back($3);
$$ = $1;
}
@@ -684,8 +691,7 @@
} else if ($2.audit) {
$3->audit = $3->mode;
}
- $3->next = $1->dbus_ents;
- $1->dbus_ents = $3;
+ $1->rule_ents.push_back($3);
$$ = $1;
}
@@ -1196,9 +1202,9 @@
dbus_rule: TOK_DBUS opt_dbus_perm opt_conds opt_cond_list TOK_END_OF_RULE
{
- struct dbus_entry *ent;
+ dbus_rule *ent;
- ent = new_dbus_entry($2, $3, $4);
+ ent = new dbus_rule($2, $3, $4);
if (!ent) {
yyerror(_("Memory allocation error."));
}
@@ -1366,12 +1372,10 @@
return error;
}
-struct mnt_entry *do_mnt_rule(struct cond_entry *src_conds, char *src,
- struct cond_entry *dst_conds, char *dst,
- int mode)
+mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
+ struct cond_entry *dst_conds, char *dst,
+ int mode)
{
- struct mnt_entry *ent;
-
if (verify_mnt_conds(src_conds, MNT_SRC_OPT) != 0)
yyerror(_("bad mount rule"));
@@ -1382,7 +1386,7 @@
if (dst_conds)
yyerror(_("mount point conditions not currently supported"));
- ent = new_mnt_entry(src_conds, src, dst_conds, dst, mode);
+ mnt_rule *ent = new mnt_rule(src_conds, src, dst_conds, dst, mode);
if (!ent) {
yyerror(_("Memory allocation error."));
}
@@ -1390,10 +1394,8 @@
return ent;
}
-struct mnt_entry *do_pivot_rule(struct cond_entry *old, char *root,
- char *transition)
+mnt_rule *do_pivot_rule(struct cond_entry *old, char *root, char *transition)
{
- struct mnt_entry *ent = NULL;
char *device = NULL;
if (old) {
if (strcmp(old->name, "oldroot") != 0)
@@ -1405,8 +1407,7 @@
free_cond_entry(old);
}
- ent = new_mnt_entry(NULL, device, NULL, root,
- AA_MAY_PIVOTROOT);
+ mnt_rule *ent = new mnt_rule(NULL, device, NULL, root, AA_MAY_PIVOTROOT);
ent->trans = transition;
return ent;
--- 2.9-test.orig/parser/profile.cc
+++ 2.9-test/parser/profile.cc
@@ -13,6 +13,7 @@
*/
#include "profile.h"
+#include "rule.h"
#include <stdio.h>
#include <stdlib.h>
@@ -62,8 +63,9 @@
{
hat_table.clear();
free_cod_entries(entries);
- free_mnt_entries(mnt_ents);
- free_dbus_entries(dbus_ents);
+
+ for (RuleList::iterator i = rule_ents.begin(); i != rule_ents.end(); i++)
+ delete *i;
if (dfa.rules)
aare_delete_ruleset(dfa.rules);
if (dfa.dfa)
--- 2.9-test.orig/parser/profile.h
+++ 2.9-test/parser/profile.h
@@ -17,6 +17,7 @@
#include <set>
#include "parser.h"
+#include "rule.h"
class Profile;
@@ -153,8 +154,7 @@
char *exec_table[AA_EXEC_COUNT];
struct cod_entry *entries;
- struct mnt_entry *mnt_ents;
- struct dbus_entry *dbus_ents;
+ RuleList rule_ents;
ProfileList hat_table;
@@ -179,9 +179,6 @@
std::fill(exec_table, exec_table + AA_EXEC_COUNT, (char *)NULL);
entries = NULL;
- mnt_ents = NULL;
- dbus_ents = NULL;
-
};
virtual ~Profile();
--- /dev/null
+++ 2.9-test/parser/rule.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014
+ * Canonical Ltd. (All rights reserved)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact Novell, Inc. or Canonical
+ * Ltd.
+ */
+#include "rule.h"
+
+std::ostream &operator<<(std::ostream &os, rule_t &rule)
+{
+ return rule.dump(os);
+};
--- /dev/null
+++ 2.9-test/parser/rule.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014
+ * Canonical Ltd. (All rights reserved)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact Novell, Inc. or Canonical
+ * Ltd.
+ */
+#ifndef __AA_RULE_H
+#define __AA_RULE_H
+
+#include <list>
+#include <ostream>
+
+#include "policydb.h"
+
+class Profile;
+
+#define RULE_NOT_SUPPORTED 0
+#define RULE_ERROR -1
+#define RULE_OK 1
+
+class rule_t {
+public:
+ int aa_class;
+
+ rule_t(void): aa_class(AA_CLASS_UNKNOWN) { };
+ virtual ~rule_t() { };
+
+ //virtual bool operator<(rule_t const &rhs)const = 0;
+ virtual std::ostream &dump(std::ostream &os) = 0;
+ virtual int expand_variables(void) = 0;
+ virtual int gen_policy_re(Profile &prof) = 0;
+ virtual void post_process(Profile &prof) = 0;
+};
+
+std::ostream &operator<<(std::ostream &os, rule_t &rule);
+
+typedef std::list<rule_t *> RuleList;
+
+#endif /* __AA_RULE_H */
+
More information about the AppArmor
mailing list