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:
John Johansen 2014-09-03 15:57:17 -07:00 committed by Steve Beattie
parent 0005895e3d
commit 4f80b4d5ca
3 changed files with 112 additions and 84 deletions

View file

@ -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))

View file

@ -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);

View file

@ -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;