mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00

The post_process() method is misnamed, it fires when the profile is finished parsing but fires before variable expansion. Rename it to better reflect what it does and move the trigger code into profile as a start of cleaning this stage up. Also document the order the hooks fire in Signed-off-by: John Johansen <john.johansen@canonical.com>
323 lines
6 KiB
C++
323 lines
6 KiB
C++
/*
|
|
* Copyright (c) 2012
|
|
* 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.
|
|
*/
|
|
#ifndef __AA_PROFILE_H
|
|
#define __AA_PROFILE_H
|
|
|
|
#include <set>
|
|
#include <string>
|
|
#include <iostream>
|
|
|
|
#include "capability.h"
|
|
#include "parser.h"
|
|
#include "rule.h"
|
|
#include "libapparmor_re/aare_rules.h"
|
|
#include "network.h"
|
|
|
|
class Profile;
|
|
|
|
class block {
|
|
public:
|
|
|
|
};
|
|
|
|
|
|
struct deref_profileptr_lt {
|
|
bool operator()(Profile * const &lhs, Profile * const &rhs) const;
|
|
};
|
|
|
|
class ProfileList {
|
|
public:
|
|
set<Profile *, deref_profileptr_lt> list;
|
|
|
|
typedef set<Profile *, deref_profileptr_lt>::iterator iterator;
|
|
iterator begin() { return list.begin(); }
|
|
iterator end() { return list.end(); }
|
|
|
|
ProfileList() { };
|
|
virtual ~ProfileList() { clear(); }
|
|
virtual bool empty(void) { return list.empty(); }
|
|
virtual pair<ProfileList::iterator,bool> insert(Profile *);
|
|
virtual void erase(ProfileList::iterator pos);
|
|
void clear(void);
|
|
void dump(void);
|
|
void dump_profile_names(bool children);
|
|
};
|
|
|
|
extern const char*profile_mode_table[];
|
|
/* use profile_mode_packed to convert to the packed representation */
|
|
enum profile_mode {
|
|
MODE_UNSPECIFIED = 0,
|
|
MODE_ENFORCE = 1,
|
|
MODE_COMPLAIN = 2,
|
|
MODE_KILL = 3,
|
|
MODE_UNCONFINED = 4,
|
|
MODE_CONFLICT = 5 /* greater than MODE_LAST */
|
|
};
|
|
#define MODE_LAST MODE_UNCONFINED
|
|
|
|
static inline enum profile_mode operator++(enum profile_mode &mode)
|
|
{
|
|
mode = (enum profile_mode)((int) mode + 1);
|
|
return mode;
|
|
}
|
|
|
|
static inline enum profile_mode merge_profile_mode(enum profile_mode l, enum profile_mode r)
|
|
{
|
|
if (l == r || r == MODE_UNSPECIFIED)
|
|
return l;
|
|
else if (l == MODE_UNSPECIFIED)
|
|
return r;
|
|
return MODE_CONFLICT;
|
|
}
|
|
|
|
static inline uint32_t profile_mode_packed(enum profile_mode mode)
|
|
{
|
|
/* kernel doesn't have an unspecified mode everything
|
|
* shifts down by 1
|
|
*/
|
|
if ((uint32_t) mode)
|
|
return (uint32_t) mode - 1;
|
|
/* unspecified defaults to same as enforce */
|
|
return 0;
|
|
}
|
|
|
|
static inline void mode_dump(ostream &os, enum profile_mode mode)
|
|
{
|
|
if (mode <= MODE_LAST)
|
|
os << profile_mode_table[(int) mode];
|
|
else
|
|
os << "unknown";
|
|
}
|
|
|
|
static inline enum profile_mode str_to_mode(const char *str)
|
|
{
|
|
for (enum profile_mode i = MODE_ENFORCE; i <= MODE_LAST; ++i) {
|
|
if (strcmp(profile_mode_table[i], str) == 0)
|
|
return i;
|
|
}
|
|
|
|
return MODE_UNSPECIFIED;
|
|
};
|
|
|
|
#define FLAG_HAT 1
|
|
#define FLAG_DEBUG1 2
|
|
#define FLAG_DEBUG2 4
|
|
|
|
class flagvals {
|
|
public:
|
|
int flags;
|
|
enum profile_mode mode;
|
|
int audit;
|
|
int path;
|
|
|
|
ostream &dump(ostream &os)
|
|
{
|
|
os << "Mode: ";
|
|
mode_dump(os, mode);
|
|
if (audit)
|
|
os << ", Audit";
|
|
|
|
if (flags & FLAG_HAT)
|
|
os << ", Hat";
|
|
|
|
os << "\n";
|
|
|
|
return os;
|
|
}
|
|
ostream &debug(ostream &os)
|
|
{
|
|
#ifdef DEBUG
|
|
return dump(os);
|
|
#else
|
|
return os;
|
|
#endif
|
|
}
|
|
|
|
};
|
|
|
|
struct capabilities {
|
|
uint64_t allow;
|
|
uint64_t audit;
|
|
uint64_t deny;
|
|
uint64_t quiet;
|
|
|
|
capabilities(void) { allow = audit = deny = quiet = 0; }
|
|
|
|
void dump()
|
|
{
|
|
if (allow != 0ull)
|
|
__debug_capabilities(allow, "Capabilities");
|
|
if (audit != 0ull)
|
|
__debug_capabilities(audit, "Audit Caps");
|
|
if (deny != 0ull)
|
|
__debug_capabilities(deny, "Deny Caps");
|
|
if (quiet != 0ull)
|
|
__debug_capabilities(quiet, "Quiet Caps");
|
|
};
|
|
};
|
|
|
|
struct dfa_stuff {
|
|
aare_rules *rules;
|
|
void *dfa;
|
|
size_t size;
|
|
|
|
dfa_stuff(void): rules(NULL), dfa(NULL), size(0) { }
|
|
};
|
|
|
|
class Profile {
|
|
public:
|
|
char *ns;
|
|
char *name;
|
|
char *attachment;
|
|
struct alt_name *altnames;
|
|
void *xmatch;
|
|
size_t xmatch_size;
|
|
int xmatch_len;
|
|
|
|
struct cond_entry_list xattrs;
|
|
|
|
/* char *sub_name; */ /* subdomain name or NULL */
|
|
/* int default_deny; */ /* TRUE or FALSE */
|
|
int local;
|
|
perms_t local_perms;
|
|
audit_t local_audit;
|
|
|
|
Profile *parent;
|
|
|
|
flagvals flags;
|
|
struct capabilities caps;
|
|
struct network net;
|
|
|
|
struct aa_rlimits rlimits;
|
|
|
|
char *exec_table[AA_EXEC_COUNT];
|
|
struct cod_entry *entries;
|
|
RuleList rule_ents;
|
|
|
|
ProfileList hat_table;
|
|
|
|
struct dfa_stuff dfa;
|
|
struct dfa_stuff policy;
|
|
|
|
Profile(void)
|
|
{
|
|
ns = name = attachment = NULL;
|
|
altnames = NULL;
|
|
xmatch = NULL;
|
|
xmatch_size = 0;
|
|
xmatch_len = 0;
|
|
|
|
xattrs.list = NULL;
|
|
xattrs.name = NULL;
|
|
|
|
local_perms = 0;
|
|
local = 0;
|
|
local_audit = AUDIT_UNSPECIFIED;
|
|
|
|
parent = NULL;
|
|
|
|
flags = { 0, MODE_UNSPECIFIED, 0, 0 };
|
|
rlimits = {0, {}};
|
|
|
|
std::fill(exec_table, exec_table + AA_EXEC_COUNT, (char *)NULL);
|
|
|
|
entries = NULL;
|
|
};
|
|
|
|
virtual ~Profile();
|
|
|
|
bool operator<(Profile const &rhs)const
|
|
{
|
|
if (ns) {
|
|
if (rhs.ns) {
|
|
int res = strcmp(ns, rhs.ns);
|
|
if (res != 0)
|
|
return res < 0;
|
|
} else
|
|
return false;
|
|
} else if (rhs.ns)
|
|
return true;
|
|
return strcmp(name, rhs.name) < 0;
|
|
}
|
|
|
|
void dump(void)
|
|
{
|
|
if (ns)
|
|
printf("Ns:\t\t%s\n", ns);
|
|
|
|
if (name)
|
|
printf("Name:\t\t%s\n", name);
|
|
else
|
|
printf("Name:\t\t<NULL>\n");
|
|
|
|
if (local) {
|
|
if (parent)
|
|
printf("Local To:\t%s\n", parent->name);
|
|
else
|
|
printf("Local To:\t<NULL>\n");
|
|
}
|
|
|
|
flags.dump(cerr);
|
|
caps.dump();
|
|
net.dump();
|
|
|
|
if (entries)
|
|
debug_cod_entries(entries);
|
|
|
|
for (RuleList::iterator i = rule_ents.begin(); i != rule_ents.end(); i++) {
|
|
(*i)->dump(cout);
|
|
}
|
|
|
|
printf("\n");
|
|
hat_table.dump();
|
|
}
|
|
|
|
bool alloc_net_table();
|
|
|
|
std::string hname(void)
|
|
{
|
|
if (!parent)
|
|
return name;
|
|
|
|
return parent->hname() + "//" + name;
|
|
}
|
|
|
|
/* assumes ns is set as part of profile creation */
|
|
std::string fqname(void)
|
|
{
|
|
if (parent)
|
|
return parent->fqname() + "//" + name;
|
|
else if (!ns)
|
|
return hname();
|
|
return ":" + std::string(ns) + "://" + hname();
|
|
}
|
|
|
|
std::string get_name(bool fqp)
|
|
{
|
|
if (fqp)
|
|
return fqname();
|
|
return hname();
|
|
}
|
|
|
|
void dump_name(bool fqp)
|
|
{
|
|
cout << get_name(fqp);;
|
|
}
|
|
|
|
void post_parse_profile(void);
|
|
void add_implied_rules(void);
|
|
};
|
|
|
|
|
|
#endif /* __AA_PROFILE_H */
|