mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-05 08:45:22 +00:00
Compare commits
27 Commits
v2.7.99
...
v2.8-beta3
Author | SHA1 | Date | |
---|---|---|---|
|
c50858a877 | ||
|
a11efe838a | ||
|
d6dc04d737 | ||
|
feeea88a58 | ||
|
36d44a3b25 | ||
|
fc5f4dc86f | ||
|
59c0bb0f46 | ||
|
fae11e12cf | ||
|
e0a74881bf | ||
|
ce38857061 | ||
|
c8e134930f | ||
|
3876299fa0 | ||
|
b0b2bde160 | ||
|
3a1b7bb54c | ||
|
04ef92ca94 | ||
|
d7a6860a23 | ||
|
5e361a4a05 | ||
|
cf5f7ef9c2 | ||
|
811d8aefa3 | ||
|
37f446dd79 | ||
|
1a01b5c296 | ||
|
b47197b881 | ||
|
3e5ae57164 | ||
|
a0048ec064 | ||
|
c35e10f875 | ||
|
46d9aae952 | ||
|
bd67bb909a |
@@ -1 +1 @@
|
||||
2.7.99
|
||||
2.7.100
|
||||
|
@@ -200,6 +200,9 @@ parser_alias.o: parser_alias.c parser.h
|
||||
parser_common.o: parser_common.c parser.h
|
||||
$(CC) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
mount.o: mount.c mount.h parser.h immunix.h
|
||||
$(CC) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||
|
||||
parser_version.h: Makefile
|
||||
@echo \#define PARSER_VERSION \"$(VERSION)\" > .ver
|
||||
@mv -f .ver $@
|
||||
|
@@ -96,6 +96,9 @@
|
||||
|
||||
#define ALL_AA_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
|
||||
|
||||
#define ALL_USER_EXEC (AA_USER_EXEC | AA_USER_EXEC_TYPE)
|
||||
#define ALL_OTHER_EXEC (AA_OTHER_EXEC | AA_OTHER_EXEC_TYPE)
|
||||
|
||||
#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \
|
||||
(AA_MAY_LINK << AA_OTHER_SHIFT))
|
||||
|
||||
|
@@ -223,7 +223,7 @@ extern "C" int aare_add_rule_vec(aare_ruleset_t *rules, int deny,
|
||||
tree->dump(cerr);
|
||||
if (deny)
|
||||
cerr << " deny";
|
||||
cerr << " (" << hex << allow <<"/" << audit << dec << ")";
|
||||
cerr << " (0x" << hex << allow <<"/" << audit << dec << ")";
|
||||
accept->dump(cerr);
|
||||
cerr << "\n\n";
|
||||
}
|
||||
|
@@ -187,14 +187,22 @@ void normalize_tree(Node *t, int dir)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
if ((&epsnode == t->child[dir]) &&
|
||||
(&epsnode != t->child[!dir]) &&
|
||||
dynamic_cast<TwoChildNode *>(t)) {
|
||||
if (dynamic_cast<TwoChildNode *>(t) &&
|
||||
(&epsnode == t->child[dir]) &&
|
||||
(&epsnode != t->child[!dir])) {
|
||||
// (E | a) -> (a | E)
|
||||
// Ea -> aE
|
||||
Node *c = t->child[dir];
|
||||
t->child[dir] = t->child[!dir];
|
||||
t->child[!dir] = c;
|
||||
// Test for E | (E | E) and E . (E . E) which will
|
||||
// result in an infinite loop
|
||||
Node *c = t->child[!dir];
|
||||
if (dynamic_cast<TwoChildNode *>(c) &&
|
||||
&epsnode == c->child[dir] &&
|
||||
&epsnode == c->child[!dir]) {
|
||||
c->release();
|
||||
c = &epsnode;
|
||||
}
|
||||
t->child[dir] = c;
|
||||
t->child[!dir] = &epsnode;
|
||||
// Don't break here as 'a' may be a tree that
|
||||
// can be pulled up.
|
||||
} else if ((dynamic_cast<AltNode *>(t) &&
|
||||
|
@@ -431,7 +431,7 @@ int DFA::apply_and_clear_deny(void)
|
||||
/* minimize the number of dfa states */
|
||||
void DFA::minimize(dfaflags_t flags)
|
||||
{
|
||||
map<size_t, Partition *> perm_map;
|
||||
map<pair<uint64_t, size_t>, Partition *> perm_map;
|
||||
list<Partition *> partitions;
|
||||
|
||||
/* Set up the initial partitions
|
||||
@@ -448,20 +448,18 @@ void DFA::minimize(dfaflags_t flags)
|
||||
int final_accept = 0;
|
||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||
size_t hash = 0;
|
||||
if (!(*i)->perms.is_null())
|
||||
/* combine all states carrying accept info together
|
||||
into an single initial parition */
|
||||
hash = 1;
|
||||
uint64_t permtype = ((uint64_t) (PACK_AUDIT_CTL((*i)->perms.audit, (*i)->perms.quiet & (*i)->perms.deny)) << 32) | (uint64_t) (*i)->perms.allow;
|
||||
if (flags & DFA_CONTROL_MINIMIZE_HASH_TRANS)
|
||||
hash |= hash_trans(*i) << 1;
|
||||
map<size_t, Partition *>::iterator p = perm_map.find(hash);
|
||||
hash |= hash_trans(*i);
|
||||
pair<uint64_t, size_t> group = make_pair(permtype, hash);
|
||||
map<pair<uint64_t, size_t>, Partition *>::iterator p = perm_map.find(group);
|
||||
if (p == perm_map.end()) {
|
||||
Partition *part = new Partition();
|
||||
part->push_back(*i);
|
||||
perm_map.insert(make_pair(hash, part));
|
||||
perm_map.insert(make_pair(group, part));
|
||||
partitions.push_back(part);
|
||||
(*i)->partition = part;
|
||||
if (hash & 1)
|
||||
if (permtype)
|
||||
accept_count++;
|
||||
} else {
|
||||
(*i)->partition = p->second;
|
||||
@@ -633,12 +631,12 @@ void DFA::dump(ostream & os)
|
||||
if (*i == start || !(*i)->perms.is_null()) {
|
||||
os << **i;
|
||||
if (*i == start)
|
||||
os << " <==";
|
||||
if ((*i)->perms.allow) {
|
||||
os << " (0x" << hex << (*i)->perms.allow << " "
|
||||
<< (*i)->perms.deny << " "
|
||||
<< (*i)->perms.audit << " "
|
||||
<< (*i)->perms.audit << dec << ')';
|
||||
os << " <== (allow/deny/audit/quiet)";
|
||||
if (!(*i)->perms.is_null()) {
|
||||
os << " (0x " << hex << (*i)->perms.allow << "/"
|
||||
<< (*i)->perms.deny << "/"
|
||||
<< (*i)->perms.audit << "/"
|
||||
<< (*i)->perms.quiet << ')';
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
@@ -646,12 +644,34 @@ void DFA::dump(ostream & os)
|
||||
os << "\n";
|
||||
|
||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||
if ((*i)->otherwise != nonmatching)
|
||||
os << **i << " -> " << (*i)->otherwise << "\n";
|
||||
Chars excluded;
|
||||
|
||||
for (StateTrans::iterator j = (*i)->trans.begin();
|
||||
j != (*i)->trans.end(); j++) {
|
||||
os << **i << " -> " << j->second << ": "
|
||||
<< j->first << "\n";
|
||||
if (j->second == nonmatching) {
|
||||
excluded.insert(j->first);
|
||||
} else {
|
||||
os << **i << " -> " << *(j)->second << ": 0x"
|
||||
<< hex << (int) j->first;
|
||||
if (isprint(j->first))
|
||||
os << " " << j->first;
|
||||
os << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ((*i)->otherwise != nonmatching) {
|
||||
os << **i << " -> " << *(*i)->otherwise << ": [";
|
||||
if (!excluded.empty()) {
|
||||
os << "^";
|
||||
for (Chars::iterator k = excluded.begin();
|
||||
k != excluded.end(); k++) {
|
||||
if (isprint(*k))
|
||||
os << *k;
|
||||
else
|
||||
os << "\\0x" << hex << (int) *k;
|
||||
}
|
||||
}
|
||||
os << "]\n";
|
||||
}
|
||||
}
|
||||
os << "\n";
|
||||
@@ -672,10 +692,12 @@ void DFA::dump_dot_graph(ostream & os)
|
||||
if (*i == start) {
|
||||
os << "\t\tstyle=bold" << "\n";
|
||||
}
|
||||
uint32_t perms = (*i)->perms.allow;
|
||||
if (perms) {
|
||||
os << "\t\tlabel=\"" << **i << "\\n("
|
||||
<< perms << ")\"" << "\n";
|
||||
if (!(*i)->perms.is_null()) {
|
||||
os << "\t\tlabel=\"" << **i << "\\n(0x " << hex
|
||||
<< (*i)->perms.allow << "/"
|
||||
<< (*i)->perms.deny << "/"
|
||||
<< (*i)->perms.audit << "/"
|
||||
<< (*i)->perms.quiet << ")\"\n";
|
||||
}
|
||||
os << "\t]" << "\n";
|
||||
}
|
||||
@@ -688,18 +710,26 @@ void DFA::dump_dot_graph(ostream & os)
|
||||
else {
|
||||
os << "\t\"" << **i << "\" -> \"" << *j->second
|
||||
<< "\" [" << "\n";
|
||||
os << "\t\tlabel=\"" << j->first << "\"\n";
|
||||
os << "\t]" << "\n";
|
||||
os << "\t\tlabel=\"";
|
||||
if (isprint(j->first))
|
||||
os << j->first;
|
||||
else
|
||||
os << "\\0xhex" << (int) j->first;
|
||||
|
||||
os << "\"\n\t]" << "\n";
|
||||
}
|
||||
}
|
||||
if ((*i)->otherwise != nonmatching) {
|
||||
os << "\t\"" << **i << "\" -> \"" << *(*i)->otherwise
|
||||
os << "\t\"" << **i << "\" -> \"" << *(*i)->otherwise
|
||||
<< "\" [" << "\n";
|
||||
if (!excluded.empty()) {
|
||||
os << "\t\tlabel=\"[^";
|
||||
for (Chars::iterator i = excluded.begin();
|
||||
i != excluded.end(); i++) {
|
||||
os << *i;
|
||||
if (isprint(*i))
|
||||
os << *i;
|
||||
else
|
||||
os << "\\0x" << hex << (int) *i;
|
||||
}
|
||||
os << "]\"" << "\n";
|
||||
}
|
||||
|
@@ -50,8 +50,8 @@ public:
|
||||
{
|
||||
deny |= rhs.deny;
|
||||
|
||||
if (!is_merged_x_consistent(allow & AA_USER_EXEC_TYPE,
|
||||
rhs.allow & AA_USER_EXEC_TYPE)) {
|
||||
if (!is_merged_x_consistent(allow & ALL_USER_EXEC,
|
||||
rhs.allow & ALL_USER_EXEC)) {
|
||||
if ((exact & AA_USER_EXEC_TYPE) &&
|
||||
!(rhs.exact & AA_USER_EXEC_TYPE)) {
|
||||
/* do nothing */
|
||||
@@ -64,8 +64,8 @@ public:
|
||||
} else
|
||||
allow |= rhs.allow & AA_USER_EXEC_TYPE;
|
||||
|
||||
if (!is_merged_x_consistent(allow & AA_OTHER_EXEC_TYPE,
|
||||
rhs.allow & AA_OTHER_EXEC_TYPE)) {
|
||||
if (!is_merged_x_consistent(allow & ALL_OTHER_EXEC,
|
||||
rhs.allow & ALL_OTHER_EXEC)) {
|
||||
if ((exact & AA_OTHER_EXEC_TYPE) &&
|
||||
!(rhs.exact & AA_OTHER_EXEC_TYPE)) {
|
||||
/* do nothing */
|
||||
@@ -79,10 +79,10 @@ public:
|
||||
allow |= rhs.allow & AA_OTHER_EXEC_TYPE;
|
||||
|
||||
|
||||
allow = (allow | (rhs.allow & ~ALL_AA_EXEC_TYPE)) & ~deny;
|
||||
allow = (allow | (rhs.allow & ~ALL_AA_EXEC_TYPE));
|
||||
audit |= rhs.audit;
|
||||
quiet = (quiet | rhs.quiet) & deny;
|
||||
|
||||
quiet = (quiet | rhs.quiet);
|
||||
|
||||
/*
|
||||
if (exec & AA_USER_EXEC_TYPE &&
|
||||
(exec & AA_USER_EXEC_TYPE) != (allow & AA_USER_EXEC_TYPE))
|
||||
|
@@ -190,8 +190,6 @@
|
||||
* mount options=ro /dev/foo, #allow mounting /dev/foo as read only
|
||||
* mount options=(ro,foo) /dev/foo,
|
||||
* mount options=ro options=foo /dev/foo,
|
||||
* mount -> /mnt/**, # allow any mount on dirs under /mnt/
|
||||
* mount options=ro -> /mnt/**, # allow any read only mount under /mnt/
|
||||
* mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -277,7 +275,7 @@ static struct mnt_keyword_table mnt_opts_table[] = {
|
||||
{"user", 0, MS_NOUSER},
|
||||
{"nouser", MS_NOUSER, 0},
|
||||
|
||||
{ }
|
||||
{NULL, 0, 0}
|
||||
};
|
||||
|
||||
static struct mnt_keyword_table mnt_conds_table[] = {
|
||||
@@ -286,7 +284,7 @@ static struct mnt_keyword_table mnt_conds_table[] = {
|
||||
{"fstype", MNT_SRC_OPT | MNT_DST_OPT, MNT_COND_FSTYPE},
|
||||
{"vfstype", MNT_SRC_OPT | MNT_DST_OPT, MNT_COND_FSTYPE},
|
||||
|
||||
{ }
|
||||
{NULL, 0, 0}
|
||||
};
|
||||
|
||||
static int find_mnt_keyword(struct mnt_keyword_table *table, const char *name)
|
||||
@@ -391,7 +389,7 @@ static struct value_list *extract_options(struct cond_entry **conds)
|
||||
}
|
||||
|
||||
struct mnt_entry *new_mnt_entry(struct cond_entry *src_conds, char *device,
|
||||
struct cond_entry *dst_conds, char *mnt_point,
|
||||
struct cond_entry *dst_conds __unused, char *mnt_point,
|
||||
int allow)
|
||||
{
|
||||
/* FIXME: dst_conds are ignored atm */
|
||||
@@ -399,8 +397,6 @@ struct mnt_entry *new_mnt_entry(struct cond_entry *src_conds, char *device,
|
||||
struct mnt_entry *ent;
|
||||
ent = (struct mnt_entry *) calloc(1, sizeof(struct mnt_entry));
|
||||
if (ent) {
|
||||
unsigned int rclear, aclear;
|
||||
|
||||
ent->mnt_point = mnt_point;
|
||||
ent->device = device;
|
||||
ent->dev_type = extract_fstype(&src_conds);
|
||||
@@ -420,8 +416,8 @@ struct mnt_entry *new_mnt_entry(struct cond_entry *src_conds, char *device,
|
||||
ent->inv_flags = 0;
|
||||
} else if (!(ent->flags | ent->inv_flags)) {
|
||||
/* no flag options, and not remount, allow everything */
|
||||
ent->flags = 0xffffffff;
|
||||
ent->inv_flags = 0xffffffff;
|
||||
ent->flags = MS_ALL_FLAGS;
|
||||
ent->inv_flags = MS_ALL_FLAGS;
|
||||
}
|
||||
|
||||
ent->allow = allow;
|
||||
|
@@ -103,8 +103,10 @@
|
||||
#define AA_MAY_PIVOTROOT 1
|
||||
#define AA_MAY_MOUNT 2
|
||||
#define AA_MAY_UMOUNT 4
|
||||
#define AA_DUMMY_REMOUNT 32 /* dummy perm for remount rule - is remapped
|
||||
* to a mount option*/
|
||||
#define AA_MATCH_CONT 0x40
|
||||
#define AA_AUDIT_MNT_DATA AA_MATCH_CONT
|
||||
#define AA_DUMMY_REMOUNT 0x40000000 /* dummy perm for remount rule - is
|
||||
* remapped to a mount option*/
|
||||
|
||||
|
||||
struct mnt_entry {
|
||||
|
@@ -768,7 +768,7 @@ static char *handle_features_dir(const char *filename, char **buffer, int size,
|
||||
|
||||
}
|
||||
|
||||
pos = snprintf_buffer(*buffer, pos, size, " }\n");
|
||||
pos = snprintf_buffer(*buffer, pos, size, "}\n");
|
||||
}
|
||||
if (dirent_path)
|
||||
free(dirent_path);
|
||||
@@ -844,6 +844,7 @@ out:
|
||||
static void get_flags_string(char **flags, char *flags_file) {
|
||||
char *pos;
|
||||
FILE *f = NULL;
|
||||
size_t size;
|
||||
|
||||
/* abort if missing or already set */
|
||||
if (!flags || *flags)
|
||||
@@ -857,8 +858,10 @@ static void get_flags_string(char **flags, char *flags_file) {
|
||||
if (!*flags)
|
||||
goto fail;
|
||||
|
||||
if (!fgets(*flags, FLAGS_STRING_SIZE, f))
|
||||
size = fread(*flags, 1, FLAGS_STRING_SIZE - 1, f);
|
||||
if (!size || ferror(f))
|
||||
goto fail;
|
||||
(*flags)[size] = 0;
|
||||
|
||||
fclose(f);
|
||||
pos = strstr(*flags, "change_hat=");
|
||||
|
@@ -83,7 +83,7 @@ static struct keyword_table keyword_table[] = {
|
||||
{"remount", TOK_REMOUNT},
|
||||
{"umount", TOK_UMOUNT},
|
||||
{"unmount", TOK_UMOUNT},
|
||||
{"pivotroot", TOK_PIVOTROOT},
|
||||
{"pivot_root", TOK_PIVOTROOT},
|
||||
/* terminate */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
@@ -692,7 +692,7 @@ static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
||||
char *p = buffer;
|
||||
int i, len = 0;
|
||||
|
||||
if (flags == 0xffffffff) {
|
||||
if (flags == MS_ALL_FLAGS) {
|
||||
/* all flags are optional */
|
||||
len = snprintf(p, size, "[^\\000]*");
|
||||
if (len < 0 || len >= size)
|
||||
@@ -704,7 +704,8 @@ static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
||||
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 */
|
||||
else /* no entry = not set */
|
||||
continue;
|
||||
|
||||
if (len < 0 || len >= size)
|
||||
return FALSE;
|
||||
@@ -712,6 +713,7 @@ static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
||||
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
|
||||
@@ -719,7 +721,7 @@ static int build_mnt_flags(char *buffer, int size, unsigned int flags,
|
||||
if (size < 9)
|
||||
return FALSE;
|
||||
|
||||
strcpy(p, "(\\0xfe|)");
|
||||
strcpy(p, "(\\xfe|)");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -774,6 +776,7 @@ static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
|
||||
char optsbuf[PATH_MAX + 3];
|
||||
char *p, *vec[5];
|
||||
int count = 0;
|
||||
unsigned int flags, inv_flags;
|
||||
|
||||
/* a single mount rule may result in multiple matching rules being
|
||||
* created in the backend to cover all the possible choices
|
||||
@@ -781,6 +784,7 @@ static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
|
||||
|
||||
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 */
|
||||
p = mntbuf;
|
||||
/* rule class single byte header */
|
||||
@@ -801,18 +805,43 @@ static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
|
||||
vec[1] = devbuf;
|
||||
/* skip type */
|
||||
vec[2] = devbuf;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX,
|
||||
entry->flags & MS_REMOUNT_FLAGS,
|
||||
entry->inv_flags & MS_REMOUNT_FLAGS))
|
||||
|
||||
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 (!build_mnt_opts(optsbuf, PATH_MAX, entry->opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf;
|
||||
if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
|
||||
entry->audit, 5, vec, dfaflags))
|
||||
|
||||
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 */
|
||||
if (!build_mnt_opts(optsbuf, PATH_MAX, entry->opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf;
|
||||
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) {
|
||||
@@ -829,9 +858,14 @@ static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
|
||||
if (!convert_entry(typebuf, PATH_MAX +3, NULL))
|
||||
goto fail;
|
||||
vec[2] = typebuf;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX,
|
||||
entry->flags & MS_BIND_FLAGS,
|
||||
entry->inv_flags & MS_BIND_FLAGS))
|
||||
|
||||
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,
|
||||
@@ -856,9 +890,14 @@ static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
|
||||
goto fail;
|
||||
vec[1] = devbuf;
|
||||
vec[2] = devbuf;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX,
|
||||
entry->flags & MS_MAKE_FLAGS,
|
||||
entry->inv_flags & MS_MAKE_FLAGS))
|
||||
|
||||
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,
|
||||
@@ -884,9 +923,14 @@ static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
|
||||
if (!convert_entry(typebuf, PATH_MAX +3, NULL))
|
||||
goto fail;
|
||||
vec[2] = typebuf;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX,
|
||||
entry->flags & MS_MOVE_FLAGS,
|
||||
entry->inv_flags & MS_MOVE_FLAGS))
|
||||
|
||||
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,
|
||||
@@ -896,6 +940,7 @@ static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
|
||||
}
|
||||
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
|
||||
*/
|
||||
@@ -911,18 +956,41 @@ static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
|
||||
if (!build_list_val_expr(typebuf, PATH_MAX+2, entry->dev_type))
|
||||
goto fail;
|
||||
vec[2] = typebuf;
|
||||
if (!build_mnt_flags(flagsbuf, PATH_MAX,
|
||||
entry->flags & ~MS_CMDS,
|
||||
entry->inv_flags & ~MS_CMDS))
|
||||
|
||||
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 (!build_mnt_opts(optsbuf, PATH_MAX, entry->opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf;
|
||||
if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
|
||||
entry->audit, 5, vec, dfaflags))
|
||||
|
||||
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 */
|
||||
if (!build_mnt_opts(optsbuf, PATH_MAX, entry->opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf;
|
||||
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) {
|
||||
p = mntbuf;
|
||||
|
@@ -435,10 +435,6 @@ flagvals: flagvals flagval
|
||||
(PATH_CHROOT_REL | PATH_NS_REL))
|
||||
yyerror(_("Profile flag chroot_relative conflicts with namespace_relative"));
|
||||
|
||||
if (!($1.path & PATH_NS_REL))
|
||||
/* default to chroot relative profiles */
|
||||
$1.path |= PATH_CHROOT_REL;
|
||||
|
||||
if (($1.path & (PATH_MEDIATE_DELETED | PATH_DELEGATE_DELETED)) ==
|
||||
(PATH_MEDIATE_DELETED | PATH_DELEGATE_DELETED))
|
||||
yyerror(_("Profile flag mediate_deleted conflicts with delegate_deleted"));
|
||||
@@ -963,12 +959,14 @@ frule: file_mode opt_subset_flag id_or_var opt_named_transition TOK_END_OF_RULE
|
||||
|
||||
file_rule: TOK_FILE TOK_END_OF_RULE
|
||||
{
|
||||
char *path = strdup("/**");
|
||||
char *path = strdup("/{**,}");
|
||||
int perms = ((AA_BASE_PERMS & ~AA_EXEC_TYPE) |
|
||||
(AA_EXEC_INHERIT | AA_MAY_EXEC));
|
||||
/* duplicate to other permission set */
|
||||
perms |= perms << AA_OTHER_SHIFT;
|
||||
if (!path)
|
||||
yyerror(_("Memory allocation error."));
|
||||
$$ = do_file_rule(NULL, path, ((AA_BASE_PERMS & ~AA_EXEC_TYPE) |
|
||||
(AA_EXEC_INHERIT | AA_MAY_EXEC)),
|
||||
NULL, NULL);
|
||||
$$ = do_file_rule(NULL, path, perms, NULL, NULL);
|
||||
}
|
||||
| opt_file file_rule_tail { $$ = $2; }
|
||||
|
||||
@@ -1114,14 +1112,23 @@ mnt_rule: TOK_UMOUNT opt_conds opt_id TOK_END_OF_RULE
|
||||
$$ = do_mnt_rule($2, NULL, NULL, $3, AA_MAY_UMOUNT);
|
||||
}
|
||||
|
||||
mnt_rule: TOK_PIVOTROOT opt_conds opt_id TOK_END_OF_RULE
|
||||
mnt_rule: TOK_PIVOTROOT opt_conds opt_id opt_named_transition TOK_END_OF_RULE
|
||||
{
|
||||
$$ = do_pivot_rule($2, $3, NULL);
|
||||
}
|
||||
char *name = NULL;
|
||||
if ($4.present && $4.namespace) {
|
||||
name = malloc(strlen($4.namespace) +
|
||||
strlen($4.name) + 3);
|
||||
if (!name) {
|
||||
PERROR("Memory allocation error\n");
|
||||
exit(1);
|
||||
}
|
||||
sprintf(name, ":%s:%s", $4.namespace, $4.name);
|
||||
free($4.namespace);
|
||||
free($4.name);
|
||||
} else if ($4.present)
|
||||
name = $4.name;
|
||||
|
||||
mnt_rule: TOK_PIVOTROOT opt_conds opt_id TOK_ARROW TOK_ID TOK_END_OF_RULE
|
||||
{
|
||||
$$ = do_pivot_rule($2, $3, $5);
|
||||
$$ = do_pivot_rule($2, $3, name);
|
||||
}
|
||||
|
||||
hat_start: TOK_CARET {}
|
||||
@@ -1313,18 +1320,20 @@ struct mnt_entry *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)
|
||||
yyerror(_("invalid pivotroot conditional '%s'"), old->name);
|
||||
if (old->vals) {
|
||||
device = old->vals->value;
|
||||
old->vals->value = NULL;
|
||||
}
|
||||
free_cond_entry(old);
|
||||
}
|
||||
|
||||
ent = new_mnt_entry(NULL, old->vals->value, NULL, root,
|
||||
ent = new_mnt_entry(NULL, device, NULL, root,
|
||||
AA_MAY_PIVOTROOT);
|
||||
ent->trans = transition;
|
||||
|
||||
old->vals->value = NULL;
|
||||
free_cond_entry(old);
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
@@ -12,8 +12,8 @@ endif
|
||||
|
||||
all: tests
|
||||
|
||||
.PHONY: tests error_output gen_xtrans parser_sanity caching
|
||||
tests: error_output gen_xtrans parser_sanity caching
|
||||
.PHONY: tests error_output gen_xtrans parser_sanity caching minimize
|
||||
tests: error_output gen_xtrans parser_sanity caching minimize
|
||||
|
||||
GEN_TRANS_DIRS=simple_tests/generated_x/ simple_tests/generated_perms_leading/ simple_tests/generated_perms_safe/
|
||||
|
||||
@@ -41,6 +41,9 @@ parser_sanity: $(PARSER)
|
||||
caching: $(PARSER)
|
||||
LANG=C ./caching.sh
|
||||
|
||||
minimize: $(PARSER)
|
||||
LANG=C ./minimize.sh
|
||||
|
||||
$(PARSER):
|
||||
make -C $(PARSER_DIR) $(PARSER_BIN)
|
||||
|
||||
|
@@ -49,11 +49,34 @@ echo -n "Profiles are cached when requested: "
|
||||
[ ! -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile does not exist)" && exit 1
|
||||
echo "ok"
|
||||
|
||||
read_features_dir()
|
||||
{
|
||||
directory="$1"
|
||||
if [ ! -d "$directory" ] ; then
|
||||
return
|
||||
fi
|
||||
for f in `ls -AU "$directory"` ; do
|
||||
if [ -f "$directory/$f" ] ; then
|
||||
read -r -d "" KF < "$directory/$f" || true
|
||||
echo -e "$f {$KF\n}"
|
||||
elif [ -d "$directory/$f" ] ; then
|
||||
echo -n "$f {"
|
||||
KF=`read_features_dir "$directory/$f" "$KF"` || true
|
||||
echo "$KF"
|
||||
echo -e "}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
echo -n "Kernel features are written to cache: "
|
||||
[ ! -f $basedir/cache/.features ] && echo "FAIL ($basedir/cache/.features missing)" && exit 1
|
||||
read CF < $basedir/cache/.features || true
|
||||
read KF < /sys/kernel/security/apparmor/features || true
|
||||
[ "$CF" != "$KF" ] && echo "FAIL (feature text mismatch: cache '$CF' vs kernel '$KF')" && exit 1
|
||||
read -r -d "" CF < $basedir/cache/.features || true
|
||||
if [ -d /sys/kernel/security/apparmor/features ] ; then
|
||||
KF=`read_features_dir /sys/kernel/security/apparmor/features`
|
||||
else
|
||||
read -r -d "" KF < /sys/kernel/security/apparmor/features || true
|
||||
fi
|
||||
[ "$CF" != "$KF" ] && echo -e "FAIL (feature text mismatch:\n cache '$CF'\nvs\n kernel '$KF')" && exit 1
|
||||
echo "ok"
|
||||
|
||||
echo -n "Cache is loaded when it exists and features match: "
|
||||
|
199
parser/tst/minimize.sh
Executable file
199
parser/tst/minimize.sh
Executable file
@@ -0,0 +1,199 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Format of -D dfa-states
|
||||
# dfa-states output is split into 2 parts:
|
||||
# the accept state infomation
|
||||
# {state} (allow deny audit XXX) ignore XXX for now
|
||||
# followed by the transition table information
|
||||
# {Y} -> {Z}: 0xXX Char #0xXX is the hex dump of Char
|
||||
# where the start state is always shown as
|
||||
# {1} <==
|
||||
#
|
||||
# Eg. echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ./apparmor_parser -QT -O minimize -D dfa-states --quiet
|
||||
#
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 0/2800a/0/2800a)
|
||||
# {4} (0x 10004/2800a/0/2800a)
|
||||
# {7} (0x 40010/2800a/0/2800a)
|
||||
# {8} (0x 80020/2800a/0/2800a)
|
||||
# {9} (0x 100040/2800a/0/2800a)
|
||||
# {c} (0x 40030/0/0/0)
|
||||
#
|
||||
# {1} -> {2}: 0x2f /
|
||||
# {2} -> {4}: 0x61 a
|
||||
# {2} -> {3}: 0x62 b
|
||||
# {2} -> {3}: 0x63 c
|
||||
# {2} -> {7}: 0x64 d
|
||||
# {2} -> {8}: 0x65 e
|
||||
# {2} -> {9}: 0x66 f
|
||||
# {2} -> {3}: [^\0x0/]
|
||||
# {3} -> {3}: [^\0x0]
|
||||
# {4} -> {3}: [^\0x0]
|
||||
# {7} -> {a}: 0x0
|
||||
# {7} -> {3}: []
|
||||
# {8} -> {3}: [^\0x0]
|
||||
# {9} -> {3}: [^\0x0]
|
||||
# {a} -> {b}: 0x2f /
|
||||
# {b} -> {c}: [^/]
|
||||
# {c} -> {c}: []
|
||||
#
|
||||
# These tests currently only look at the accept state permissions
|
||||
#
|
||||
# To view any of these DFAs as graphs replace --D dfa-states with -D dfa-graph
|
||||
# strip of the test stuff around the parser command and use the the dot
|
||||
# command to convert
|
||||
# Eg.
|
||||
# echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ./apparmor_parser -QT -O minimize -D dfa-graph --quiet 2>min.graph
|
||||
# dot -T png -o min.png min.graph
|
||||
# and then view min.png in your favorite viewer
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
# test to see if minimization is eliminating non-redundant accept state
|
||||
# Test xtrans and regular perms separately. The are the same basic failure
|
||||
# but can xtrans has an extra code path.
|
||||
#
|
||||
# The permission test is setup to have all the none xtrans permissions show
|
||||
# up once on unique paths and have a global write permission that adds to
|
||||
# it.
|
||||
# This should result in a un-minimized dump looking like. Notice it has 6
|
||||
# states with accept information, 1 for each rule except for the 'w'
|
||||
# permission which is combined into a single state for /b and /**
|
||||
#
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 2800a/0/0/0)
|
||||
# {4} (0x 3800e/0/0/0)
|
||||
# {5} (0x 6801a/0/0/0)
|
||||
# {6} (0x a802a/0/0/0)
|
||||
# {7} (0x 12804a/0/0/0)
|
||||
# {a} (0x 40030/0/0/0)
|
||||
# A dump of minimization that is not respecting the uniqueness of the
|
||||
# permissions on the states looks like below. Notice it has only 3 states
|
||||
# with accept information
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 1b806e/0/0/0)
|
||||
# {5} (0x 6801a/0/0/0)
|
||||
# {a} (0x 40030/0/0/0)
|
||||
|
||||
echo -n "Minimize profiles basic perms "
|
||||
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, /** w, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
# same test as above except with audit perms added
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 2800a/0/2800a/0)
|
||||
# {4} (0x 3800e/0/2800a/0)
|
||||
# {7} (0x 6801a/0/2800a/0)
|
||||
# {8} (0x a802a/0/2800a/0)
|
||||
# {9} (0x 12804a/0/2800a/0)
|
||||
# {c} (0x 40030/0/0/0)
|
||||
echo -n "Minimize profiles audit perms "
|
||||
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit /** w, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
# same test as above except with deny 'w' perm added to /**, this does not
|
||||
# elimnates the states with 'w' and 'a' because the quiet information is
|
||||
# being carried
|
||||
#
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 0/2800a/0/2800a)
|
||||
# {4} (0x 10004/2800a/0/2800a)
|
||||
# {7} (0x 40010/2800a/0/2800a)
|
||||
# {8} (0x 80020/2800a/0/2800a)
|
||||
# {9} (0x 100040/2800a/0/2800a)
|
||||
# {c} (0x 40030/0/0/0)
|
||||
|
||||
echo -n "Minimize profiles deny perms "
|
||||
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
# same test as above except with audit deny 'w' perm added to /**, with the
|
||||
# parameter this elimnates the states with 'w' and 'a' because
|
||||
# the quiet information is NOT being carried
|
||||
#
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {4} (0x 10004/0/0/0)
|
||||
# {7} (0x 40010/0/0/0)
|
||||
# {8} (0x 80020/0/0/0)
|
||||
# {9} (0x 100040/0/0/0)
|
||||
# {c} (0x 40030/0/0/0)
|
||||
|
||||
echo -n "Minimize profiles audit deny perms "
|
||||
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
|
||||
# The x transition test profile is setup so that there are 3 conflicting x
|
||||
# permissions, two are on paths that won't collide during dfa creation. The
|
||||
# 3rd is a generic permission that should be overriden during dfa creation.
|
||||
#
|
||||
# This should result in a dfa that specifies transitions on 'a' and 'b' to
|
||||
# unique states that store the alternate accept information. However
|
||||
# minimization can remove the unique accept permission states if x permissions
|
||||
# are treated as a single accept state.
|
||||
#
|
||||
# The minimized dump should retain the 'a' and 'b' transitions accept states.
|
||||
# notice the below dump has 3 states with accept information {3}, {4}, {5}
|
||||
#
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 2914a45/0/0/0)
|
||||
# {4} (0x 4115045/0/0/0)
|
||||
# {5} (0x 2514945/0/0/0)
|
||||
#
|
||||
# A dump of minimization that is not respecting the uniqueness of the
|
||||
# permissions on the states transitioned to by 'a' and 'b' looks like
|
||||
# below. Notice that only state {3} has accept information
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 2514945/0/0/0)
|
||||
#
|
||||
|
||||
echo -n "Minimize profiles xtrans "
|
||||
if [ `echo "/t { /b px, /* Pixr, /a Cx -> foo, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
# same test as above + audit
|
||||
echo -n "Minimize profiles audit xtrans "
|
||||
if [ `echo "/t { /b px, audit /* Pixr, /a Cx -> foo, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
|
||||
# now try denying x and make sure perms are cleared
|
||||
# notice that only deny and quiet information is being carried
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 0/fe17f85/0/14005)
|
||||
|
||||
echo -n "Minimize profiles deny xtrans "
|
||||
if [ `echo "/t { /b px, deny /* xr, /a Cx -> foo, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 1 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
# now try audit + denying x and make sure perms are cleared
|
||||
# notice that the deny info is being carried, by an artifical trap state
|
||||
# {1} <== (allow/deny/audit/quiet)
|
||||
# {3} (0x 0/fe17f85/0/0)
|
||||
|
||||
echo -n "Minimize profiles audit deny xtrans "
|
||||
if [ `echo "/t { /b px, audit deny /* xr, /a Cx -> foo, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 1 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
@@ -1,11 +1,13 @@
|
||||
#
|
||||
#=DESCRIPTION test for conflict resolution in minimization phase of dfa gen
|
||||
#=EXRESULT FAIL
|
||||
#=EXRESULT PASS
|
||||
#=TODO
|
||||
#
|
||||
/usr/bin/foo {
|
||||
|
||||
# need to build minimal test for this yet
|
||||
/b px,
|
||||
/* Pixr,
|
||||
/a Cx -> foo,
|
||||
|
||||
}
|
||||
|
||||
|
11
parser/tst/simple_tests/xtrans/x-conflict.sd
Normal file
11
parser/tst/simple_tests/xtrans/x-conflict.sd
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
#=DESCRIPTION test for conflict resolution in minimization phase of dfa gen
|
||||
#=EXRESULT FAIL
|
||||
#=TODO
|
||||
#
|
||||
/usr/bin/foo {
|
||||
/b* px,
|
||||
/* Pixr,
|
||||
/a* Cx -> foo,
|
||||
}
|
||||
|
@@ -36,6 +36,8 @@
|
||||
/usr/lib{,32,64}/dri/** mr,
|
||||
/usr/lib/@{multiarch}/dri/** mr,
|
||||
/dev/dri/** rw,
|
||||
/etc/drirc r,
|
||||
owner @{HOME}/.drirc r,
|
||||
|
||||
# mouse themes
|
||||
/etc/X11/cursors/ r,
|
||||
|
@@ -30,7 +30,7 @@
|
||||
/usr/share/a2ps/fonts/** r,
|
||||
/usr/share/xfce/fonts/** r,
|
||||
/usr/share/ghostscript/fonts/** r,
|
||||
/usr/share/texmf/*/fonts/** r,
|
||||
/usr/share/texmf/{,*/}fonts/** r,
|
||||
/var/lib/ghostscript/** r,
|
||||
|
||||
@{HOME}/.fonts.conf r,
|
||||
|
@@ -4,8 +4,9 @@
|
||||
owner @{HOME}/.java/deployment/deployment.properties k,
|
||||
/etc/java-*/ r,
|
||||
/etc/java-*/** r,
|
||||
/usr/lib/jvm/java-6-openjdk/jre/lib/*/IcedTeaPlugin.so mr,
|
||||
/usr/lib/jvm/java-6-openjdk*/jre/lib/*/IcedTeaPlugin.so mr,
|
||||
/usr/lib/jvm/java-6-openjdk/jre/bin/java cx -> browser_openjdk,
|
||||
/usr/lib/jvm/java-6-openjdk-{amd64,armel,armhf,i386,powerpc}/jre/bin/java cx -> browser_openjdk,
|
||||
/usr/lib/jvm/java-*-sun-1.*/jre/bin/java{,_vm} cx -> browser_java,
|
||||
/usr/lib/jvm/java-*-sun-1.*/jre/lib/*/libnp*.so cx -> browser_java,
|
||||
/usr/lib/j2*-ibm/jre/bin/java cx -> browser_java,
|
||||
@@ -43,8 +44,8 @@
|
||||
/var/lib/dbus/machine-id r,
|
||||
|
||||
/usr/bin/env ix,
|
||||
/usr/lib/jvm/java-6-openjdk/jre/bin/java ix,
|
||||
/usr/lib/jvm/java-6-openjdk/jre/lib/i386/client/classes.jsa m,
|
||||
/usr/lib/jvm/java-6-openjdk*/jre/bin/java ix,
|
||||
/usr/lib/jvm/java-6-openjdk*/jre/lib/i386/client/classes.jsa m,
|
||||
|
||||
# Why would java need this?
|
||||
deny /usr/bin/gconftool-2 x,
|
||||
|
@@ -164,9 +164,10 @@ sub gen_file($) {
|
||||
my $rule = shift;
|
||||
my @rules = split (/:/, $rule);
|
||||
# default: file rules
|
||||
if (@rules != 2) {
|
||||
(!$nowarn) && print STDERR "Warning: invalid file access '$rule', ignored\n";
|
||||
} else {
|
||||
if (@rules == 1) {
|
||||
# support raw rules
|
||||
push (@{$output_rules{$hat}}, " $rules[0],\n");
|
||||
} elsif (@rules == 2) {
|
||||
if ($escape) {
|
||||
$rules[0]=~ s/(["[\]{}\\\:\#])/\\$1/g;
|
||||
$rules[0]=~ s/(\#)/\\043/g;
|
||||
@@ -176,6 +177,8 @@ sub gen_file($) {
|
||||
} else {
|
||||
push (@{$output_rules{$hat}}, " $rules[0] $rules[1],\n");
|
||||
}
|
||||
} else {
|
||||
(!$nowarn) && print STDERR "Warning: invalid file access '$rule', ignored\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -54,3 +54,15 @@ runchecktest "OPEN R+dac_override" fail $file
|
||||
rm -f ${file}
|
||||
genprofile $file:$badperm2
|
||||
runchecktest "OPEN W (create)" fail $file
|
||||
|
||||
# This is a test where using just a raw 'file,' rule allowing all file
|
||||
# access
|
||||
genprofile file
|
||||
runchecktest "OPEN 'file' RW" pass $file
|
||||
|
||||
# this test is to make sure the raw 'file' rule allows access to things
|
||||
# that are not covered by the owner rule
|
||||
chown nobody $file
|
||||
chmod 666 $file
|
||||
genprofile file
|
||||
runchecktest "OPEN 'file' RW" pass $file
|
||||
|
Reference in New Issue
Block a user