mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
parser: change/fix the encoding for unix socket rules.
This changes/fixes the encoding for unix socket rules. The changes look larger than they are because it refactors the code, instead of duplicating. The major changes are: - it changes where the accept perm is stored - it moves anyone_match_pattern to default_match_pattern - it fixes the layout of the local addr only being written when local perms are present Signed-off-by: John Johansen <john.johansen@canonical.com> Acked-by: Steve Beattie <steve@nxnw.org>
This commit is contained in:
parent
0005895e3d
commit
4f80b4d5ca
3 changed files with 112 additions and 84 deletions
|
@ -226,13 +226,99 @@ static uint32_t map_perms(uint32_t mask)
|
||||||
((mask & (AA_NET_SETOPT | AA_NET_GETOPT)) >> 5); /* 5 + (AA_OTHER_SHIFT - 24) */
|
((mask & (AA_NET_SETOPT | AA_NET_GETOPT)) >> 5); /* 5 + (AA_OTHER_SHIFT - 24) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unix_rule::write_to_prot(std::ostringstream &buffer)
|
||||||
|
{
|
||||||
|
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NET;
|
||||||
|
writeu16(buffer, AF_UNIX);
|
||||||
|
if (sock_type)
|
||||||
|
writeu16(buffer, sock_type_n);
|
||||||
|
else
|
||||||
|
buffer << "..";
|
||||||
|
if (proto)
|
||||||
|
writeu16(buffer, proto_n);
|
||||||
|
else
|
||||||
|
buffer << "..";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unix_rule::write_addr(std::ostringstream &buffer, const char *addr)
|
||||||
|
{
|
||||||
|
std::string buf;
|
||||||
|
pattern_t ptype;
|
||||||
|
|
||||||
|
if (addr) {
|
||||||
|
int pos;
|
||||||
|
if (strcmp(addr, "none") == 0) {
|
||||||
|
/* anonymous */
|
||||||
|
buffer << "\\x01";
|
||||||
|
} else {
|
||||||
|
/* skip leading @ */
|
||||||
|
ptype = convert_aaregex_to_pcre(addr + 1, 0, buf, &pos);
|
||||||
|
if (ptype == ePatternInvalid)
|
||||||
|
return false;
|
||||||
|
/* kernel starts abstract with \0 */
|
||||||
|
buffer << "\\x00";
|
||||||
|
buffer << buf;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
/* match any addr or anonymous */
|
||||||
|
buffer << ".*";
|
||||||
|
|
||||||
|
/* todo: change to out of band separator */
|
||||||
|
buffer << "\\x00";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unix_rule::write_label(std::ostringstream &buffer, const char *label)
|
||||||
|
{
|
||||||
|
std::string buf;
|
||||||
|
pattern_t ptype;
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
int pos;
|
||||||
|
ptype = convert_aaregex_to_pcre(label, 0, buf, &pos);
|
||||||
|
if (ptype == ePatternInvalid)
|
||||||
|
return false;
|
||||||
|
/* kernel starts abstract with \0 */
|
||||||
|
buffer << buf;
|
||||||
|
} else
|
||||||
|
buffer << default_match_pattern;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* General Layout
|
||||||
|
*
|
||||||
|
* Local socket end point perms
|
||||||
|
* CLASS_NET AF TYPE PROTO local (addr\0label) \0 cmd cmd_option
|
||||||
|
* ^ ^ ^ ^ ^
|
||||||
|
* | | | | |
|
||||||
|
* stub perm | | | |
|
||||||
|
* | | | |
|
||||||
|
* sub stub perm | | |
|
||||||
|
* | | |
|
||||||
|
* create perm | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* bind, accept, get/set attr |
|
||||||
|
* |
|
||||||
|
* listen, set/get opt perm
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* peer socket end point perms
|
||||||
|
* CLASS_NET AF TYPE PROTO local(addr\0label\0) cmd_addr peer(addr\0label )
|
||||||
|
* ^
|
||||||
|
* |
|
||||||
|
* send/receive connect/accept perm
|
||||||
|
*
|
||||||
|
* NOTE: accept is encoded twice, locally to check if a socket is allowed
|
||||||
|
* to accept, and then as a pair to test that it can accept the pair.
|
||||||
|
*/
|
||||||
int unix_rule::gen_policy_re(Profile &prof)
|
int unix_rule::gen_policy_re(Profile &prof)
|
||||||
{
|
{
|
||||||
std::ostringstream buffer, tmp;
|
std::ostringstream buffer, tmp;
|
||||||
std::string buf;
|
std::string buf;
|
||||||
|
|
||||||
pattern_t ptype;
|
|
||||||
int pos;
|
|
||||||
int mask = mode;
|
int mask = mode;
|
||||||
|
|
||||||
/* always generate a downgraded rule. This doesn't change generated
|
/* always generate a downgraded rule. This doesn't change generated
|
||||||
|
@ -253,18 +339,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
return RULE_NOT_SUPPORTED;
|
return RULE_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write_to_prot(buffer);
|
||||||
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NET;
|
|
||||||
writeu16(buffer, AF_UNIX);
|
|
||||||
if (sock_type)
|
|
||||||
writeu16(buffer, sock_type_n);
|
|
||||||
else
|
|
||||||
buffer << "..";
|
|
||||||
if (proto)
|
|
||||||
writeu16(buffer, proto_n);
|
|
||||||
else
|
|
||||||
buffer << "..";
|
|
||||||
|
|
||||||
if (mask & AA_NET_CREATE) {
|
if (mask & AA_NET_CREATE) {
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
||||||
|
@ -275,35 +350,14 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
mask &= ~AA_NET_CREATE;
|
mask &= ~AA_NET_CREATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* local addr */
|
if (mask) {
|
||||||
if (addr) {
|
/* local addr */
|
||||||
if (strcmp(addr, "none") == 0) {
|
if (!write_addr(buffer, addr))
|
||||||
buffer << "\\x01";
|
goto fail;
|
||||||
} else {
|
|
||||||
/* skip leading @ */
|
|
||||||
ptype = convert_aaregex_to_pcre(addr + 1, 0, buf, &pos);
|
|
||||||
if (ptype == ePatternInvalid)
|
|
||||||
goto fail;
|
|
||||||
/* kernel starts abstract with \0 */
|
|
||||||
buffer << "\\x00";
|
|
||||||
buffer << buf;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
buffer << ".*";
|
|
||||||
|
|
||||||
/* change to out of band separator */
|
|
||||||
buffer << "\\x00";
|
|
||||||
|
|
||||||
if (mask & AA_LOCAL_NET_PERMS) {
|
|
||||||
/* local label option */
|
/* local label option */
|
||||||
if (label) {
|
if (!write_label(buffer, label))
|
||||||
ptype = convert_aaregex_to_pcre(label, 0, buf, &pos);
|
goto fail;
|
||||||
if (ptype == ePatternInvalid)
|
/* seperator */
|
||||||
goto fail;
|
|
||||||
/* kernel starts abstract with \0 */
|
|
||||||
buffer << buf;
|
|
||||||
} else
|
|
||||||
tmp << anyone_match_pattern;
|
|
||||||
buffer << "\\x00";
|
buffer << "\\x00";
|
||||||
|
|
||||||
/* create already masked off */
|
/* create already masked off */
|
||||||
|
@ -316,21 +370,10 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cmd selector - drop accept??? */
|
|
||||||
if (mask & AA_NET_ACCEPT) {
|
|
||||||
tmp.str(buffer.str());
|
|
||||||
tmp << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ACCEPT;
|
|
||||||
buf = tmp.str();
|
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
|
||||||
map_perms(AA_NET_ACCEPT),
|
|
||||||
map_perms(audit & AA_NET_ACCEPT),
|
|
||||||
dfaflags))
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (mask & AA_NET_LISTEN) {
|
if (mask & AA_NET_LISTEN) {
|
||||||
tmp.str(buffer.str());
|
tmp.str(buffer.str());
|
||||||
tmp << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_LISTEN;
|
tmp << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_LISTEN;
|
||||||
/* TODO: backlog conditional */
|
/* TODO: backlog conditional: for now match anything*/
|
||||||
tmp << "..";
|
tmp << "..";
|
||||||
buf = tmp.str();
|
buf = tmp.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
||||||
|
@ -342,7 +385,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
if (mask & AA_NET_OPT) {
|
if (mask & AA_NET_OPT) {
|
||||||
tmp.str(buffer.str());
|
tmp.str(buffer.str());
|
||||||
tmp << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_OPT;
|
tmp << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_OPT;
|
||||||
/* TODO: sockopt conditional */
|
/* TODO: sockopt conditional: for now match anything */
|
||||||
tmp << "..";
|
tmp << "..";
|
||||||
buf = tmp.str();
|
buf = tmp.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
||||||
|
@ -351,38 +394,19 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
dfaflags))
|
dfaflags))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mask &= ~AA_LOCAL_NET_PERMS;
|
mask &= ~AA_LOCAL_NET_PERMS | AA_NET_ACCEPT;
|
||||||
}
|
} /* if (mask) */
|
||||||
|
|
||||||
if (mask & AA_PEER_NET_PERMS) {
|
if (mask & AA_PEER_NET_PERMS) {
|
||||||
/* cmd selector */
|
/* cmd selector */
|
||||||
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ADDR;
|
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ADDR;
|
||||||
|
|
||||||
/* peer addr */
|
/* local addr */
|
||||||
if (peer_addr) {
|
if (!write_addr(buffer, peer_addr))
|
||||||
if (strcmp(peer_addr, "none") == 0) {
|
goto fail;
|
||||||
buffer << "\\x01";
|
/* local label option */
|
||||||
} else {
|
if (!write_label(buffer, peer_label))
|
||||||
/* skip leading @ */
|
goto fail;
|
||||||
ptype = convert_aaregex_to_pcre(peer_addr + 1, 0, buf, &pos);
|
|
||||||
if (ptype == ePatternInvalid)
|
|
||||||
goto fail;
|
|
||||||
/* kernel starts abstract with \0 */
|
|
||||||
buffer << "\\x00";
|
|
||||||
buffer << buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* change to out of band separator */
|
|
||||||
buffer << "\\x00";
|
|
||||||
|
|
||||||
if (peer_label) {
|
|
||||||
ptype = convert_aaregex_to_pcre(peer_label, 0, buf, &pos);
|
|
||||||
if (ptype == ePatternInvalid)
|
|
||||||
goto fail;
|
|
||||||
buffer << buf;
|
|
||||||
} else {
|
|
||||||
buffer << anyone_match_pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), deny, map_perms(mode & AA_PEER_NET_PERMS), map_perms(audit), dfaflags))
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny, map_perms(mode & AA_PEER_NET_PERMS), map_perms(audit), dfaflags))
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
int parse_unix_mode(const char *str_mode, int *mode, int fail);
|
int parse_unix_mode(const char *str_mode, int *mode, int fail);
|
||||||
|
|
||||||
class unix_rule: public af_rule {
|
class unix_rule: public af_rule {
|
||||||
|
void write_to_prot(std::ostringstream &buffer);
|
||||||
|
bool write_addr(std::ostringstream &buffer, const char *addr);
|
||||||
|
bool write_label(std::ostringstream &buffer, const char *label);
|
||||||
void move_conditionals(struct cond_entry *conds);
|
void move_conditionals(struct cond_entry *conds);
|
||||||
void move_peer_conditionals(struct cond_entry *conds);
|
void move_peer_conditionals(struct cond_entry *conds);
|
||||||
void downgrade_rule(Profile &prof);
|
void downgrade_rule(Profile &prof);
|
||||||
|
|
|
@ -70,8 +70,9 @@
|
||||||
AA_NET_GETATTR | AA_NET_BIND | AA_NET_ACCEPT | \
|
AA_NET_GETATTR | AA_NET_BIND | AA_NET_ACCEPT | \
|
||||||
AA_NET_LISTEN | AA_NET_SETOPT | AA_NET_GETOPT)
|
AA_NET_LISTEN | AA_NET_SETOPT | AA_NET_GETOPT)
|
||||||
#define AA_NET_OPT (AA_NET_SETOPT | AA_NET_GETOPT)
|
#define AA_NET_OPT (AA_NET_SETOPT | AA_NET_GETOPT)
|
||||||
#define AA_LOCAL_NET_CMD (AA_NET_ACCEPT | AA_NET_LISTEN | AA_NET_OPT)
|
#define AA_LOCAL_NET_CMD (AA_NET_LISTEN | AA_NET_OPT)
|
||||||
#define AA_PEER_NET_PERMS (AA_VALID_NET_PERMS & ~AA_LOCAL_NET_PERMS)
|
#define AA_PEER_NET_PERMS (AA_VALID_NET_PERMS & (~AA_LOCAL_NET_PERMS | \
|
||||||
|
AA_NET_ACCEPT))
|
||||||
|
|
||||||
struct network_tuple {
|
struct network_tuple {
|
||||||
const char *family_name;
|
const char *family_name;
|
||||||
|
|
Loading…
Add table
Reference in a new issue