Skip to content

Commit

Permalink
UBUNTU: SAUCE: apparmor: pass cred through to audit info.
Browse files Browse the repository at this point in the history
BugLink: https://bugs.launchpad.net/bugs/2012136

The cred is needed to properly audit some messages, and will be needed
in the future for uid conditional mediation. So pass it through to
where the apparmor_audit_data struct gets defined.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
  • Loading branch information
John Johansen authored and Andrea Righi committed Mar 23, 2023
1 parent cf01c39 commit d1e594a
Show file tree
Hide file tree
Showing 22 changed files with 477 additions and 266 deletions.
82 changes: 51 additions & 31 deletions security/apparmor/af_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ static umode_t sock_i_mode(struct sock *sk)
return mode;
}

static inline int unix_fs_perm(const char *op, u32 mask, struct aa_label *label,
static inline int unix_fs_perm(const char *op, u32 mask,
const struct cred *subj_cred,
struct aa_label *label,
struct unix_sock *u, int flags)
{
AA_BUG(!label);
Expand All @@ -63,14 +65,16 @@ static inline int unix_fs_perm(const char *op, u32 mask, struct aa_label *label,
struct aa_sk_ctx *ctx = aa_sock(&u->sk);

if (ctx->path.dentry)
return aa_path_perm(op, label, &ctx->path, flags, mask,
return aa_path_perm(op, subj_cred, label, &ctx->path,
flags, mask,
&cond);
return fn_for_each_confined(label, profile,
((flags | profile->path_flags) & PATH_MEDIATE_DELETED) ?
__aa_path_perm(op, profile,
__aa_path_perm(op, subj_cred, profile,
u->addr->name->sun_path, mask,
&cond, flags, &perms) :
aa_audit_file(profile, &nullperms, op, mask,
aa_audit_file(subj_cred, profile, &nullperms,
op, mask,
u->addr->name->sun_path, NULL,
NULL, cond.uid,
"Failed name lookup - deleted entry",
Expand All @@ -81,7 +85,8 @@ static inline int unix_fs_perm(const char *op, u32 mask, struct aa_label *label,
u->path.dentry->d_inode->i_mode
};

return aa_path_perm(op, label, &u->path, flags, mask, &cond);
return aa_path_perm(op, subj_cred, label, &u->path, flags,
mask, &cond);
}

return 0;
Expand Down Expand Up @@ -259,14 +264,14 @@ int aa_unix_create_perm(struct aa_label *label, int family, int type,
}


static inline int profile_sk_perm(struct aa_profile *profile, const char *op,
static inline int profile_sk_perm(struct aa_profile *profile,
struct apparmor_audit_data *ad,
u32 request, struct sock *sk)
{
struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules),
list);
unsigned int state;
DEFINE_AUDIT_SK(ad, op, sk);

AA_BUG(!profile);
AA_BUG(!sk);
Expand All @@ -276,31 +281,39 @@ static inline int profile_sk_perm(struct aa_profile *profile, const char *op,
state = RULE_MEDIATES_AF(rules, AF_UNIX);
if (state) {
state = match_to_sk(rules->policy.dfa, state, unix_sk(sk),
&ad.info);
return do_perms(profile, rules, state, request, &ad);
&ad->info);
return do_perms(profile, rules, state, request, ad);
}

return aa_profile_af_sk_perm(profile, &ad, request, sk);
return aa_profile_af_sk_perm(profile, ad, request, sk);
}

int aa_unix_label_sk_perm(struct aa_label *label, const char *op, u32 request,
int aa_unix_label_sk_perm(const struct cred *subj_cred,
struct aa_label *label, const char *op, u32 request,
struct sock *sk)
{
struct aa_profile *profile;
if (!unconfined(label)) {
struct aa_profile *profile;
DEFINE_AUDIT_SK(ad, op, sk);

return fn_for_each_confined(label, profile,
profile_sk_perm(profile, op, request, sk));
ad.subj_cred = subj_cred;
return fn_for_each_confined(label, profile,
profile_sk_perm(profile, &ad, request, sk));
}
return 0;
}

static int unix_label_sock_perm(struct aa_label *label, const char *op, u32 request,
struct socket *sock)
static int unix_label_sock_perm(const struct cred *subj_cred,
struct aa_label *label, const char *op,
u32 request, struct socket *sock)
{
if (unconfined(label))
return 0;
if (UNIX_FS(sock->sk))
return unix_fs_perm(op, request, label, unix_sk(sock->sk), 0);
return unix_fs_perm(op, request, subj_cred, label,
unix_sk(sock->sk), 0);

return aa_unix_label_sk_perm(label, op, request, sock->sk);
return aa_unix_label_sk_perm(subj_cred, label, op, request, sock->sk);
}

/* revaliation, get/set attr */
Expand All @@ -310,7 +323,7 @@ int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock)
int error;

label = begin_current_label_crit_section();
error = unix_label_sock_perm(label, op, request, sock);
error = unix_label_sock_perm(current_cred(), label, op, request, sock);
end_current_label_crit_section(label);

return error;
Expand All @@ -324,6 +337,7 @@ static int profile_bind_perm(struct aa_profile *profile, struct sock *sk,
unsigned int state;
DEFINE_AUDIT_SK(ad, OP_BIND, sk);

ad.subj_cred = current_cred();
AA_BUG(!profile);
AA_BUG(!sk);
AA_BUG(addr->sa_family != AF_UNIX);
Expand Down Expand Up @@ -566,7 +580,8 @@ static int profile_peer_perm(struct aa_profile *profile, const char *op, u32 req
*
* Requires: lock held on both @sk and @peer_sk
*/
int aa_unix_peer_perm(struct aa_label *label, const char *op, u32 request,
int aa_unix_peer_perm(const struct cred *subj_cred,
struct aa_label *label, const char *op, u32 request,
struct sock *sk, struct sock *peer_sk,
struct aa_label *peer_label)
{
Expand All @@ -578,15 +593,15 @@ int aa_unix_peer_perm(struct aa_label *label, const char *op, u32 request,
AA_BUG(!peer_sk);

if (UNIX_FS(aa_unix_sk(peeru))) {
return unix_fs_perm(op, request, label, peeru, 0);
return unix_fs_perm(op, request, subj_cred, label, peeru, 0);
} else if (UNIX_FS(aa_unix_sk(u))) {
return unix_fs_perm(op, request, label, u, 0);
return unix_fs_perm(op, request, subj_cred, label, u, 0);
} else {
struct aa_profile *profile;
DEFINE_AUDIT_SK(ad, op, sk);

ad.net.peer_sk = peer_sk;
ad.net.peer_sk = peer_sk;
ad.subj_cred = subj_cred;
/* TODO: ns!!! */
if (!net_eq(sock_net(sk), sock_net(peer_sk)))
;
Expand Down Expand Up @@ -627,8 +642,8 @@ static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
unix_state_unlock(sk2);
}

int aa_unix_file_perm(struct aa_label *label, const char *op, u32 request,
struct socket *sock)
int aa_unix_file_perm(const struct cred *subj_cred, struct aa_label *label,
const char *op, u32 request, struct socket *sock)
{
struct sock *peer_sk = NULL;
u32 sk_req = request & ~NET_PEER_MASK;
Expand All @@ -645,7 +660,8 @@ int aa_unix_file_perm(struct aa_label *label, const char *op, u32 request,
if (peer_sk)
sock_hold(peer_sk);
if (!unix_connected(sock) && sk_req) {
error = unix_label_sock_perm(label, op, sk_req, sock);
error = unix_label_sock_perm(subj_cred, label, op, sk_req,
sock);
if (!error)
; // TODO: update label
}
Expand All @@ -655,22 +671,26 @@ int aa_unix_file_perm(struct aa_label *label, const char *op, u32 request,

unix_state_double_lock(sock->sk, peer_sk);
if (UNIX_FS(sock->sk)) {
error = unix_fs_perm(op, request, label, unix_sk(sock->sk),
error = unix_fs_perm(op, request, subj_cred, label,
unix_sk(sock->sk),
PATH_SOCK_COND);
} else if (UNIX_FS(peer_sk)) {
error = unix_fs_perm(op, request, label, unix_sk(peer_sk),
error = unix_fs_perm(op, request, subj_cred, label,
unix_sk(peer_sk),
PATH_SOCK_COND);
} else {
struct aa_sk_ctx *pctx = aa_sock(peer_sk);

if (sk_req)
error = aa_unix_label_sk_perm(label, op, sk_req,
error = aa_unix_label_sk_perm(subj_cred,
label, op, sk_req,
sock->sk);
last_error(error,
xcheck(aa_unix_peer_perm(label, op,
xcheck(aa_unix_peer_perm(subj_cred, label, op,
MAY_READ | MAY_WRITE,
sock->sk, peer_sk, NULL),
aa_unix_peer_perm(pctx->label, op,
aa_unix_peer_perm(sock->file ? sock->file->f_cred : NULL,
pctx->label, op,
MAY_READ | MAY_WRITE,
peer_sk, sock->sk, label)));
}
Expand Down
11 changes: 7 additions & 4 deletions security/apparmor/apparmorfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
/* high level check about policy management - fine grained in
* below after unpack
*/
error = aa_may_manage_policy(label, ns, mask);
error = aa_may_manage_policy(current_cred(), label, ns, mask);
if (error)
goto end_section;

Expand Down Expand Up @@ -486,7 +486,8 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
/* high level check about policy management - fine grained in
* below after unpack
*/
error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY);
error = aa_may_manage_policy(current_cred(), label, ns,
AA_MAY_REMOVE_POLICY);
if (error)
goto out;

Expand Down Expand Up @@ -1802,7 +1803,8 @@ static int ns_mkdir_op(struct user_namespace *mnt_userns, struct inode *dir,
int error;

label = begin_current_label_crit_section();
error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
error = aa_may_manage_policy(current_cred(), label, NULL,
AA_MAY_LOAD_POLICY);
end_current_label_crit_section(label);
if (error)
return error;
Expand Down Expand Up @@ -1851,7 +1853,8 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
int error;

label = begin_current_label_crit_section();
error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
error = aa_may_manage_policy(current_cred(), label, NULL,
AA_MAY_LOAD_POLICY);
end_current_label_crit_section(label);
if (error)
return error;
Expand Down
5 changes: 4 additions & 1 deletion security/apparmor/capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ static int profile_capable(struct aa_profile *profile, int cap,

/**
* aa_capable - test permission to use capability
* @subj_cread: cred we are testing capability against
* @label: label being tested for capability (NOT NULL)
* @cap: capability to be tested
* @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
Expand All @@ -148,12 +149,14 @@ static int profile_capable(struct aa_profile *profile, int cap,
*
* Returns: 0 on success, or else an error code.
*/
int aa_capable(struct aa_label *label, int cap, unsigned int opts)
int aa_capable(const struct cred *subj_cred, struct aa_label *label,
int cap, unsigned int opts)
{
struct aa_profile *profile;
int error = 0;
DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE);

ad.subj_cred = subj_cred;
ad.common.u.cap = cap;
error = fn_for_each_confined(label, profile,
profile_capable(profile, cap, opts, &ad));
Expand Down
Loading

0 comments on commit d1e594a

Please sign in to comment.