mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
apparmor: push inet mediation into profile callbacks, and improve auditing
Continue preparing for fine grained inet mediation by setting up the stacked mediation callback. This lifts address mapping and audit context setup out of the stacking loop and pushing the mediation down into the callback fn. While this patch sets up the structure for fine grained mediation it does not change mediation and the callback fns only call the default mediation that will be used when fine grained inet mediation is not available. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
4f0cafcb28
commit
89ac6aa752
|
|
@ -21,61 +21,545 @@
|
|||
#include "include/cred.h"
|
||||
|
||||
|
||||
static inline aa_state_t RULE_MEDIATES_SK(struct aa_ruleset *rules,
|
||||
const struct sock *sk)
|
||||
{
|
||||
return RULE_MEDIATES_NET(rules);
|
||||
}
|
||||
|
||||
|
||||
enum addr_type {
|
||||
ADDR_LOCAL = 0,
|
||||
ADDR_LOCAL_PRIV = 1,
|
||||
ADDR_REMOTE = 2,
|
||||
};
|
||||
|
||||
struct match_addr {
|
||||
const char *addrp;
|
||||
enum addr_type addrtype;
|
||||
int len;
|
||||
__be16 port;
|
||||
};
|
||||
|
||||
struct stored_match_addr {
|
||||
union {
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_in addr4;
|
||||
struct sockaddr_in6 addr6;
|
||||
};
|
||||
int addrlen;
|
||||
struct match_addr maddr;
|
||||
};
|
||||
|
||||
static void set_ad_create(struct apparmor_audit_data *ad,
|
||||
int family, int type, int protocol)
|
||||
{
|
||||
ad->common.u.net->family = family;
|
||||
ad->net.type = type;
|
||||
ad->net.protocol = protocol;
|
||||
}
|
||||
|
||||
static int set_ad_addr(struct apparmor_audit_data *ad,
|
||||
u16 family, bool source, struct match_addr *maddr)
|
||||
{
|
||||
ad->common.u.net->family = family;
|
||||
|
||||
if (source) {
|
||||
ad->common.u.net->sport = maddr->port;
|
||||
if (maddr->addrp) {
|
||||
if (family == AF_INET)
|
||||
/* ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; */
|
||||
ad->common.u.net->v4info.saddr = *(__be32 *)maddr->addrp;
|
||||
else
|
||||
/* ad.u.net->v4info.saddr = addr6->sin6_addr.s6_addr; */
|
||||
ad->common.u.net->v6info.saddr = *(struct in6_addr *)maddr->addrp;
|
||||
}
|
||||
} else {
|
||||
ad->common.u.net->dport = maddr->port;
|
||||
if (maddr->addrp) {
|
||||
if (family == AF_INET)
|
||||
/* ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; */
|
||||
ad->common.u.net->v4info.daddr = *(__be32 *)maddr->addrp;
|
||||
else
|
||||
/* ad.u.net->v4info.saddr = addr6->sin6_addr.s6_addr; */
|
||||
ad->common.u.net->v6info.daddr = *(struct in6_addr *)maddr->addrp;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns 0 on success
|
||||
* raw_port - if set raw_port (protocol) when SOCK_RAW */
|
||||
static int map_addr(struct sockaddr *addr, int addrlen, u16 raw_port,
|
||||
enum addr_type addrtype, struct match_addr *maddr,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
struct sockaddr_in *addr4 = NULL;
|
||||
struct sockaddr_in6 *addr6 = NULL;
|
||||
|
||||
AA_BUG(!addr);
|
||||
AA_BUG(!maddr);
|
||||
|
||||
maddr->addrtype = addrtype;
|
||||
if (!addr || addrlen < offsetofend(struct sockaddr, sa_family)) {
|
||||
maddr->addrp = NULL;
|
||||
maddr->port = 0;
|
||||
maddr->len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* its possibly to have sk->sk_family == PF_INET6 and
|
||||
* addr->sa_family == AF_INET. sk_family is used for socket
|
||||
* mediation, sa_family for when we have address ...
|
||||
*/
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
addr4 = (struct sockaddr_in *)addr;
|
||||
if (addrlen < sizeof(struct sockaddr_in))
|
||||
return -EINVAL;
|
||||
maddr->port = addr4->sin_port;
|
||||
maddr->addrp = (char *)&addr4->sin_addr.s_addr;
|
||||
maddr->len = 4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
addr6 = (struct sockaddr_in6 *)addr;
|
||||
if (addrlen < SIN6_LEN_RFC2133)
|
||||
return -EINVAL;
|
||||
maddr->port = addr6->sin6_port;
|
||||
maddr->addrp = (char *)&addr6->sin6_addr.s6_addr;
|
||||
maddr->len = 16;
|
||||
break;
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
/* per ip spec, && sk->sk_type == SOCK_RAW*/
|
||||
if (raw_port && addrtype != ADDR_REMOTE)
|
||||
maddr->port = htons(raw_port);
|
||||
if (ad)
|
||||
set_ad_addr(ad, addr->sa_family, addrtype != ADDR_REMOTE, maddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -ENOTCONN if not connected */
|
||||
static int map_sock_addr(struct socket *sock, enum addr_type addrtype,
|
||||
struct stored_match_addr *maddr,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
/* do we need early bailout for !family ... */
|
||||
maddr->addrlen = sock->ops->getname(sock, (struct sockaddr *) &maddr->addr, addrtype != ADDR_REMOTE ? 0 : 1);
|
||||
if (maddr->addrlen == -ENOTCONN) {
|
||||
maddr->addrlen = 0;
|
||||
return map_addr(NULL, 0, 0, addrtype, &maddr->maddr, ad);
|
||||
} else if (maddr->addrlen < 0)
|
||||
return maddr->addrlen;
|
||||
return map_addr(&maddr->addr, maddr->addrlen, 0, addrtype,
|
||||
&maddr->maddr, ad);
|
||||
}
|
||||
|
||||
/* TODO: combine with connect map addr */
|
||||
/* TODO: raw_port */
|
||||
static int bind_map_addr(const struct sock *sk, struct sockaddr *addr,
|
||||
int addrlen,
|
||||
struct match_addr *maddr,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
struct sockaddr_in *addr4 = NULL;
|
||||
struct sockaddr_in6 *addr6 = NULL;
|
||||
u16 family;
|
||||
|
||||
AA_BUG(!sk);
|
||||
AA_BUG(!addr);
|
||||
AA_BUG(!maddr);
|
||||
|
||||
if (addrlen < offsetofend(struct sockaddr, sa_family))
|
||||
return -EINVAL;
|
||||
|
||||
maddr->addrtype = ADDR_LOCAL;
|
||||
/*
|
||||
* its possibly to have sk->sk_family == PF_INET6 and
|
||||
* addr->sa_family == AF_INET. sk_family is used for socket
|
||||
* mediation, sa_family for when we have address ...
|
||||
*/
|
||||
family = addr->sa_family;
|
||||
switch (addr->sa_family) {
|
||||
case AF_UNSPEC:
|
||||
if (sk->sk_family == PF_INET6) {
|
||||
/* Length check from inet6_bind_sk() */
|
||||
if (addrlen < SIN6_LEN_RFC2133)
|
||||
return -EINVAL;
|
||||
/* Family check from __inet6_bind() */
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
/* see __inet_bind(), we only want to allow
|
||||
* AF_UNSPEC if the address is INADDR_ANY
|
||||
*/
|
||||
addr4 = (struct sockaddr_in *)addr;
|
||||
if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
|
||||
return -EAFNOSUPPORT;
|
||||
family = AF_INET;
|
||||
fallthrough;
|
||||
case AF_INET:
|
||||
addr4 = (struct sockaddr_in *)addr;
|
||||
if (addrlen < sizeof(struct sockaddr_in))
|
||||
return -EINVAL;
|
||||
maddr->port = addr4->sin_port;
|
||||
maddr->addrp = (char *)&addr4->sin_addr.s_addr;
|
||||
maddr->len = 4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
addr6 = (struct sockaddr_in6 *)addr;
|
||||
if (addrlen < SIN6_LEN_RFC2133)
|
||||
return -EINVAL;
|
||||
maddr->port = addr6->sin6_port;
|
||||
maddr->addrp = (char *)&addr6->sin6_addr.s6_addr;
|
||||
maddr->len = 16;
|
||||
break;
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
if (ad)
|
||||
set_ad_addr(ad, family, true, maddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int profile_sk_perm(struct aa_profile *profile, u32 request,
|
||||
const struct sock *sk,
|
||||
struct match_addr *maddr,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
AA_BUG(!profile);
|
||||
AA_BUG(!sk);
|
||||
|
||||
return aa_profile_af_sk_perm(profile, ad, request, sk);
|
||||
}
|
||||
|
||||
/* no kernel_t bailout */
|
||||
static int profile_create_perm(struct aa_profile *profile, int family,
|
||||
int type, int protocol,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
AA_BUG(!profile);
|
||||
|
||||
return aa_profile_af_perm(profile, ad, AA_MAY_CREATE, family, type,
|
||||
protocol);
|
||||
}
|
||||
|
||||
|
||||
/* sendmsg/rcvmsg/connect */
|
||||
static int profile_remote_perm(struct aa_profile *profile,
|
||||
const struct sock *sk,
|
||||
u32 request, struct match_addr *raddr,
|
||||
struct match_addr *laddr,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
AA_BUG(!profile);
|
||||
AA_BUG(!sk);
|
||||
AA_BUG(!raddr);
|
||||
AA_BUG(!laddr);
|
||||
AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
||||
"family=%d", sk->sk_family);
|
||||
|
||||
return aa_profile_af_sk_perm(profile, ad, request, sk);
|
||||
}
|
||||
|
||||
static int profile_bind_perm(struct aa_profile *profile,
|
||||
const struct sock *sk,
|
||||
struct match_addr *maddr,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
return aa_profile_af_sk_perm(profile, ad, AA_MAY_BIND, sk);
|
||||
|
||||
}
|
||||
|
||||
static int profile_listen_perm(struct aa_profile *profile,
|
||||
const struct sock *sk,
|
||||
struct match_addr *maddr, int backlog,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
AA_BUG(!profile);
|
||||
AA_BUG(!sk);
|
||||
AA_BUG(!maddr);
|
||||
AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
||||
"family=%d", sk->sk_family);
|
||||
|
||||
return aa_profile_af_sk_perm(profile, ad, AA_MAY_LISTEN, sk);
|
||||
}
|
||||
|
||||
static inline int profile_accept_perm(struct aa_profile *profile,
|
||||
const struct sock *sk,
|
||||
struct match_addr *maddr,
|
||||
const struct sock *newsk,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
AA_BUG(!profile);
|
||||
AA_BUG(!sk);
|
||||
/* AA_BUG(!newsk); newsk can be null here, since not using atm ... */
|
||||
AA_BUG(!maddr);
|
||||
AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
||||
"family=%d", sk->sk_family);
|
||||
|
||||
return aa_profile_af_sk_perm(profile, ad, AA_MAY_ACCEPT, sk);
|
||||
}
|
||||
|
||||
/* getopt/setopt */
|
||||
static int profile_opt_perm(struct aa_profile *profile, u32 request,
|
||||
const struct sock *sk, struct match_addr *maddr,
|
||||
int level, int optname,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
AA_BUG(!profile);
|
||||
AA_BUG(!sk);
|
||||
AA_BUG(!maddr);
|
||||
AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
||||
"family=%d", sk->sk_family);
|
||||
|
||||
return aa_profile_af_sk_perm(profile, ad, request, sk);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
// TODO: cleanup init to use recursion, so we can have N init fns, in 1 macro
|
||||
// TODO: lift DEFINE_AUDIT out of macro into init fn???
|
||||
|
||||
/* no kernel_t bailout */
|
||||
#define label_sk_has_perm2(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, XXXX, YYYY, CALLBACKFN) \
|
||||
({ \
|
||||
int __EERROR = 0; \
|
||||
if (label_mediates(LABEL, AA_CLASS_NET)) { \
|
||||
struct aa_profile *PROFILE; \
|
||||
DEFINE_AUDIT_SK(AAD, OP, CRED, SOCKSK); \
|
||||
(AAD).subj_cred = (CRED); \
|
||||
(AAD).request = (REQUEST); \
|
||||
__EERROR = (XXXX); \
|
||||
if (__EERROR == 0) { \
|
||||
__EERROR = (YYYY); \
|
||||
if (__EERROR == 0) { \
|
||||
__EERROR = fn_for_each(LABEL, PROFILE, \
|
||||
(CALLBACKFN)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
__EERROR; \
|
||||
})
|
||||
|
||||
/* no kernel_t bailout */
|
||||
#define label_sk_has_perm(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, CALLBACKFN) \
|
||||
label_sk_has_perm2(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, \
|
||||
0, 0, CALLBACKFN)
|
||||
|
||||
/* no kernel_t bailout */
|
||||
#define label_sk_has_perm1(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, XXXX, CALLBACKFN) \
|
||||
label_sk_has_perm2(CRED, LABEL, SOCKSK, OP, REQUEST, PROFILE, AAD, \
|
||||
XXXX, 0, CALLBACKFN)
|
||||
|
||||
|
||||
/* Early bailout for kernel_t - 2 init args before callback */
|
||||
#define sk_has_perm2(SOCKSK, OP, REQUEST, PROFILE, AAD, XXXXY, YYYYX, CALLBACKFN) \
|
||||
({ \
|
||||
struct aa_label *__label; \
|
||||
struct aa_sk_ctx *__ctx = aa_sock(SOCKSK); \
|
||||
int __ERROR = 0; \
|
||||
bool __needput; \
|
||||
if (rcu_access_pointer(__ctx->label) != kernel_t) { \
|
||||
\
|
||||
__label = begin_current_label_crit_section(&__needput); \
|
||||
__ERROR = label_sk_has_perm2(current_cred(), __label, SOCKSK, OP, REQUEST, PROFILE, AAD, XXXXY, YYYYX, CALLBACKFN); \
|
||||
end_current_label_crit_section(__label, __needput); \
|
||||
} \
|
||||
__ERROR; \
|
||||
})
|
||||
|
||||
/* Early bailout for kernel_t - no init args before callback */
|
||||
#define sk_has_perm(SOCKSK, OP, REQUEST, PROFILE, AAD, CALLBACKFN) \
|
||||
sk_has_perm2(SOCKSK, OP, REQUEST, PROFILE, AAD, 0, 0, CALLBACKFN)
|
||||
|
||||
|
||||
/* Early bailout for kernel_t - 1 init arg before callback */
|
||||
#define sk_has_perm1(SOCKSK, OP, REQUEST, PROFILE, AAD, XXXXY, CALLBACKFN) \
|
||||
sk_has_perm2(SOCKSK, OP, REQUEST, PROFILE, AAD, XXXXY, 0, CALLBACKFN)
|
||||
|
||||
|
||||
|
||||
/* no kernel_t early bailout */
|
||||
/* NOTE: already lifted label_mediates into lsm.c */
|
||||
int aa_inet_create_perm(struct aa_label *label, int family, int type,
|
||||
int protocol)
|
||||
{
|
||||
return aa_af_perm(current_cred(), label, OP_CREATE,
|
||||
AA_MAY_CREATE, family, type,
|
||||
protocol);
|
||||
struct aa_profile *profile;
|
||||
int error = 0;
|
||||
DEFINE_AUDIT_NET(ad, OP_CREATE, current_cred(), NULL, family, type,
|
||||
protocol);
|
||||
|
||||
ad.subj_cred = current_cred();
|
||||
set_ad_create(&ad, family, type, protocol);
|
||||
error = fn_for_each(label, profile,
|
||||
profile_create_perm(profile, family, type,
|
||||
protocol, &ad));
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int aa_inet_bind_perm(struct socket *sock, struct sockaddr *addr,
|
||||
int addrlen)
|
||||
{
|
||||
return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk);
|
||||
struct match_addr maddr;
|
||||
|
||||
return sk_has_perm1(sock->sk, OP_BIND, AA_MAY_BIND, profile, ad,
|
||||
bind_map_addr(sock->sk, addr, addrlen, &maddr,
|
||||
&ad),
|
||||
profile_bind_perm(profile, sock->sk, &maddr, &ad));
|
||||
}
|
||||
|
||||
int aa_inet_connect_perm(struct socket *sock, struct sockaddr *addr,
|
||||
int addrlen)
|
||||
{
|
||||
return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
|
||||
struct stored_match_addr laddr;
|
||||
struct match_addr raddr;
|
||||
|
||||
/* disconnect socket */
|
||||
if (addrlen < offsetofend(struct sockaddr, sa_family))
|
||||
return -EINVAL;
|
||||
if (addr->sa_family == AF_UNSPEC)
|
||||
return 0;
|
||||
|
||||
/* do we need early bailout for !family ... */
|
||||
return sk_has_perm2(sock->sk, OP_CONNECT, AA_MAY_CONNECT, profile, ad,
|
||||
map_sock_addr(sock, ADDR_LOCAL, &laddr, &ad),
|
||||
map_addr(addr, addrlen, 0, ADDR_REMOTE, &raddr,
|
||||
&ad),
|
||||
profile_remote_perm(profile, sock->sk,
|
||||
AA_MAY_CONNECT, &raddr,
|
||||
&laddr.maddr, &ad));
|
||||
}
|
||||
|
||||
int aa_inet_listen_perm(struct socket *sock, int backlog)
|
||||
{
|
||||
return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk);
|
||||
struct stored_match_addr maddr;
|
||||
|
||||
/* do we need early bailout for !family ... */
|
||||
return sk_has_perm1(sock->sk, OP_LISTEN, AA_MAY_LISTEN, profile, ad,
|
||||
map_sock_addr(sock, ADDR_LOCAL, &maddr, &ad),
|
||||
profile_listen_perm(profile, sock->sk, &maddr.maddr,
|
||||
backlog, &ad));
|
||||
}
|
||||
|
||||
/* ability of sock to connect, not peer address binding */
|
||||
int aa_inet_accept_perm(struct socket *sock, struct socket *newsock)
|
||||
{
|
||||
return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk);
|
||||
struct stored_match_addr maddr;
|
||||
int error;
|
||||
|
||||
error = sk_has_perm1(sock->sk, OP_ACCEPT, AA_MAY_ACCEPT, profile, ad,
|
||||
map_sock_addr(sock, ADDR_LOCAL, &maddr, &ad),
|
||||
profile_accept_perm(profile, sock->sk,
|
||||
&maddr.maddr,
|
||||
newsock->sk, &ad));
|
||||
|
||||
/* selinux updates inode - need to investigate this more */
|
||||
return error;
|
||||
}
|
||||
|
||||
/* sendmsg, recvmsg. */
|
||||
int aa_inet_msg_perm(const char *op, u32 request, struct socket *sock,
|
||||
struct msghdr *msg, int size)
|
||||
{
|
||||
return aa_sk_perm(op, request, sock->sk);
|
||||
struct stored_match_addr laddr;
|
||||
struct match_addr raddr;
|
||||
|
||||
/* do we need early bailout for !family ... */
|
||||
return sk_has_perm2(sock->sk, op, request, profile, ad,
|
||||
map_sock_addr(sock, ADDR_LOCAL, &laddr, &ad),
|
||||
map_addr(msg->msg_name, msg->msg_namelen, 0,
|
||||
ADDR_REMOTE, &raddr, &ad),
|
||||
profile_remote_perm(profile, sock->sk, request,
|
||||
&raddr, &laddr.maddr, &ad));
|
||||
}
|
||||
|
||||
/* getopt, setopt */
|
||||
int aa_inet_opt_perm(const char *op, u32 request, struct socket *sock,
|
||||
int level, int optname)
|
||||
{
|
||||
return aa_sk_perm(op, request, sock->sk);
|
||||
struct stored_match_addr maddr;
|
||||
|
||||
return sk_has_perm1(sock->sk, op, request, profile, ad,
|
||||
map_sock_addr(sock, ADDR_LOCAL, &maddr, &ad),
|
||||
profile_opt_perm(profile, request, sock->sk,
|
||||
&maddr.maddr, level, optname, &ad));
|
||||
}
|
||||
|
||||
/* revaliation, get/set attr/getsockname/peername */
|
||||
static int inet_label_sock_perm(const struct cred *cred, struct aa_label *label,
|
||||
const char *op, u32 request,
|
||||
struct socket *sock)
|
||||
{
|
||||
struct stored_match_addr maddr;
|
||||
|
||||
return label_sk_has_perm1(cred, label, sock->sk, op, request, profile,
|
||||
ad,
|
||||
map_sock_addr(sock, ADDR_LOCAL, &maddr, &ad),
|
||||
profile_sk_perm(profile, request, sock->sk,
|
||||
&maddr.maddr, &ad));
|
||||
}
|
||||
|
||||
/* revalidation, get/set attr/getsockname/peername */
|
||||
int aa_inet_sock_perm(const char *op, u32 request, struct socket *sock)
|
||||
{
|
||||
return aa_sk_perm(op, request, sock->sk);
|
||||
struct aa_sk_ctx *ctx = aa_sock(sock->sk);
|
||||
struct aa_label *label;
|
||||
bool needput;
|
||||
int error;
|
||||
|
||||
if (rcu_access_pointer(ctx->label) == kernel_t)
|
||||
return 0;
|
||||
|
||||
label = begin_current_label_crit_section(&needput);
|
||||
error = inet_label_sock_perm(current_cred(), label, op, request, sock);
|
||||
end_current_label_crit_section(label, needput);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int aa_inet_file_perm(const struct cred *subj_cred, struct aa_label *label,
|
||||
const char *op, u32 request, struct socket *sock)
|
||||
{
|
||||
return aa_label_sk_perm(subj_cred, label, op, request, sock->sk);
|
||||
u32 sk_req = request & ~NET_PEER_MASK;
|
||||
struct stored_match_addr laddr;
|
||||
const struct sock *sk = sock->sk;
|
||||
int error = 0;
|
||||
|
||||
AA_BUG(!label);
|
||||
AA_BUG(!sock);
|
||||
AA_BUG(!sock->sk);
|
||||
AA_BUG(sk->sk_family != PF_INET && sk->sk_family != PF_INET6,
|
||||
"family=%d", sk->sk_family);
|
||||
|
||||
/* access to the local sock */
|
||||
error = label_sk_has_perm1(subj_cred, label, sock->sk, op, request,
|
||||
profile, ad,
|
||||
map_sock_addr(sock, ADDR_LOCAL, &laddr, &ad),
|
||||
profile_sk_perm(profile, sk_req, sock->sk, &laddr.maddr,
|
||||
&ad));
|
||||
|
||||
if (!error) {
|
||||
struct stored_match_addr raddr;
|
||||
|
||||
/* TODO: have ad here: instead of in CB so we do have to redo */
|
||||
error = map_sock_addr(sock, ADDR_REMOTE, &raddr, NULL);
|
||||
if (!error && raddr.maddr.addrp) {
|
||||
error = label_sk_has_perm1(subj_cred, label, sock->sk,
|
||||
op, request, profile, ad,
|
||||
set_ad_addr(&ad, raddr.addr.sa_family,
|
||||
false, &raddr.maddr),
|
||||
profile_remote_perm(profile, sock->sk,
|
||||
request,
|
||||
&raddr.maddr,
|
||||
&laddr.maddr, &ad));
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static const char *const aa_class_names[] = {
|
|||
"unknown",
|
||||
"unknown",
|
||||
"net",
|
||||
"unknown",
|
||||
"netv9",
|
||||
"label",
|
||||
"posix_mqueue",
|
||||
"io_uring",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user