Skip to content

Commit

Permalink
Merge tag 'apparmor-pr-2023-11-03' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/jj/linux-apparmor

Pull apparmor updates from John Johansen:
 "This adds initial support for mediating io_uring and userns creation.
  Adds a new restriction that tightens the use of change_profile, and a
  couple of optimizations to reduce performance bottle necks that have
  been found when retrieving the current task's secid and allocating
  work buffers.

  The majority of the patch set continues cleaning up and simplifying
  the code (fixing comments, removing now dead functions, and macros
  etc). Finally there are 4 bug fixes, with the regression fix having
  had a couple months of testing.

  Features:
   - optimize retrieving current task secid
   - add base io_uring mediation
   - add base userns mediation
   - improve buffer allocation
   - allow restricting unprivilege change_profile

  Cleanups:
   - Fix kernel doc comments
   - remove unused declarations
   - remove unused functions
   - remove unneeded #ifdef
   - remove unused macros
   - mark fns static
   - cleanup fn with unused return values
   - cleanup audit data
   - pass cred through to audit data
   - refcount the pdb instead of using duplicates
   - make SK_CTX macro an inline fn
   - some comment cleanups

  Bug fixes:
   - fix regression in mount mediation
   - fix invalid refenece
   - use passed in gfp flags
   - advertise avaiability of extended perms and disconnected.path"

* tag 'apparmor-pr-2023-11-03' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: (39 commits)
  apparmor: Fix some kernel-doc comments
  apparmor: Fix one kernel-doc comment
  apparmor: Fix some kernel-doc comments
  apparmor: mark new functions static
  apparmor: Fix regression in mount mediation
  apparmor: cache buffers on percpu list if there is lock contention
  apparmor: add io_uring mediation
  apparmor: add user namespace creation mediation
  apparmor: allow restricting unprivileged change_profile
  apparmor: advertise disconnected.path is available
  apparmor: refcount the pdb
  apparmor: provide separate audit messages for file and policy checks
  apparmor: pass cred through to audit info.
  apparmor: rename audit_data->label to audit_data->subj_label
  apparmor: combine common_audit_data and apparmor_audit_data
  apparmor: rename SK_CTX() to aa_sock and make it an inline fn
  apparmor: Optimize retrieving current task secid
  apparmor: remove unused functions in policy_ns.c/.h
  apparmor: remove unneeded #ifdef in decompress_zstd()
  apparmor: fix invalid reference on profile->disconnected
  ...
  • Loading branch information
torvalds committed Nov 3, 2023
2 parents 136cc1e + 6cede10 commit 6bdfe2d
Show file tree
Hide file tree
Showing 32 changed files with 1,336 additions and 848 deletions.
49 changes: 34 additions & 15 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 @@ -618,23 +619,23 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,

if (profile_unconfined(profile))
return;
if (rules->file.dfa && *match_str == AA_CLASS_FILE) {
state = aa_dfa_match_len(rules->file.dfa,
rules->file.start[AA_CLASS_FILE],
if (rules->file->dfa && *match_str == AA_CLASS_FILE) {
state = aa_dfa_match_len(rules->file->dfa,
rules->file->start[AA_CLASS_FILE],
match_str + 1, match_len - 1);
if (state) {
struct path_cond cond = { };

tmp = *(aa_lookup_fperms(&(rules->file), state, &cond));
tmp = *(aa_lookup_fperms(rules->file, state, &cond));
}
} else if (rules->policy.dfa) {
} else if (rules->policy->dfa) {
if (!RULE_MEDIATES(rules, *match_str))
return; /* no change to current perms */
state = aa_dfa_match_len(rules->policy.dfa,
rules->policy.start[0],
state = aa_dfa_match_len(rules->policy->dfa,
rules->policy->start[0],
match_str, match_len);
if (state)
tmp = *aa_lookup_perms(&rules->policy, state);
tmp = *aa_lookup_perms(rules->policy, state);
}
aa_apply_modes_to_perms(profile, &tmp);
aa_perms_accum_raw(perms, &tmp);
Expand Down Expand Up @@ -1095,7 +1096,7 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v)
struct aa_profile *profile = labels_profile(label);
if (profile->attach.xmatch_str)
seq_printf(seq, "%s\n", profile->attach.xmatch_str);
else if (profile->attach.xmatch.dfa)
else if (profile->attach.xmatch->dfa)
seq_puts(seq, "<unknown>\n");
else
seq_printf(seq, "%s\n", profile->base.name);
Expand Down Expand Up @@ -1314,7 +1315,6 @@ SEQ_RAWDATA_FOPS(compressed_size);

static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen)
{
#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
if (slen < dlen) {
const size_t wksp_len = zstd_dctx_workspace_bound();
zstd_dctx *ctx;
Expand All @@ -1341,7 +1341,6 @@ static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen)
kvfree(wksp);
return ret;
}
#endif

if (dlen < slen)
return -EINVAL;
Expand Down Expand Up @@ -1806,7 +1805,8 @@ static int ns_mkdir_op(struct mnt_idmap *idmap, 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 @@ -1855,7 +1855,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 Expand Up @@ -2339,10 +2340,16 @@ static struct aa_sfs_entry aa_sfs_entry_domain[] = {
AA_SFS_FILE_BOOLEAN("post_nnp_subset", 1),
AA_SFS_FILE_BOOLEAN("computed_longest_left", 1),
AA_SFS_DIR("attach_conditions", aa_sfs_entry_attach),
AA_SFS_FILE_BOOLEAN("disconnected.path", 1),
AA_SFS_FILE_STRING("version", "1.2"),
{ }
};

static struct aa_sfs_entry aa_sfs_entry_unconfined[] = {
AA_SFS_FILE_BOOLEAN("change_profile", 1),
{ }
};

static struct aa_sfs_entry aa_sfs_entry_versions[] = {
AA_SFS_FILE_BOOLEAN("v5", 1),
AA_SFS_FILE_BOOLEAN("v6", 1),
Expand All @@ -2352,11 +2359,15 @@ static struct aa_sfs_entry aa_sfs_entry_versions[] = {
{ }
};

#define PERMS32STR "allow deny subtree cond kill complain prompt audit quiet hide xindex tag label"
static struct aa_sfs_entry aa_sfs_entry_policy[] = {
AA_SFS_DIR("versions", aa_sfs_entry_versions),
AA_SFS_FILE_BOOLEAN("set_load", 1),
/* number of out of band transitions supported */
AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED),
AA_SFS_FILE_U64("permstable32_version", 1),
AA_SFS_FILE_STRING("permstable32", PERMS32STR),
AA_SFS_DIR("unconfined_restrictions", aa_sfs_entry_unconfined),
{ }
};

Expand All @@ -2368,6 +2379,7 @@ static struct aa_sfs_entry aa_sfs_entry_mount[] = {
static struct aa_sfs_entry aa_sfs_entry_ns[] = {
AA_SFS_FILE_BOOLEAN("profile", 1),
AA_SFS_FILE_BOOLEAN("pivot_root", 0),
AA_SFS_FILE_STRING("mask", "userns_create"),
{ }
};

Expand All @@ -2382,6 +2394,12 @@ static struct aa_sfs_entry aa_sfs_entry_query[] = {
AA_SFS_DIR("label", aa_sfs_entry_query_label),
{ }
};

static struct aa_sfs_entry aa_sfs_entry_io_uring[] = {
AA_SFS_FILE_STRING("mask", "sqpoll override_creds"),
{ }
};

static struct aa_sfs_entry aa_sfs_entry_features[] = {
AA_SFS_DIR("policy", aa_sfs_entry_policy),
AA_SFS_DIR("domain", aa_sfs_entry_domain),
Expand All @@ -2395,6 +2413,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace),
AA_SFS_DIR("signal", aa_sfs_entry_signal),
AA_SFS_DIR("query", aa_sfs_entry_query),
AA_SFS_DIR("io_uring", aa_sfs_entry_io_uring),
{ }
};

Expand Down
75 changes: 38 additions & 37 deletions security/apparmor/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ static const char *const aa_class_names[] = {
"io_uring",
"module",
"lsm",
"unknown",
"unknown",
"namespace",
"io_uring",
"unknown",
"unknown",
"unknown",
Expand All @@ -85,37 +85,36 @@ static const char *const aa_class_names[] = {
/**
* audit_pre() - core AppArmor function.
* @ab: audit buffer to fill (NOT NULL)
* @ca: audit structure containing data to audit (NOT NULL)
* @va: audit structure containing data to audit (NOT NULL)
*
* Record common AppArmor audit data from @sa
* Record common AppArmor audit data from @va
*/
static void audit_pre(struct audit_buffer *ab, void *ca)
static void audit_pre(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = ca;
struct apparmor_audit_data *ad = aad_of_va(va);

if (aa_g_audit_header) {
audit_log_format(ab, "apparmor=\"%s\"",
aa_audit_type[aad(sa)->type]);
aa_audit_type[ad->type]);
}

if (aad(sa)->op) {
audit_log_format(ab, " operation=\"%s\"", aad(sa)->op);
}
if (ad->op)
audit_log_format(ab, " operation=\"%s\"", ad->op);

if (aad(sa)->class)
if (ad->class)
audit_log_format(ab, " class=\"%s\"",
aad(sa)->class <= AA_CLASS_LAST ?
aa_class_names[aad(sa)->class] :
ad->class <= AA_CLASS_LAST ?
aa_class_names[ad->class] :
"unknown");

if (aad(sa)->info) {
audit_log_format(ab, " info=\"%s\"", aad(sa)->info);
if (aad(sa)->error)
audit_log_format(ab, " error=%d", aad(sa)->error);
if (ad->info) {
audit_log_format(ab, " info=\"%s\"", ad->info);
if (ad->error)
audit_log_format(ab, " error=%d", ad->error);
}

if (aad(sa)->label) {
struct aa_label *label = aad(sa)->label;
if (ad->subj_label) {
struct aa_label *label = ad->subj_label;

if (label_isprofile(label)) {
struct aa_profile *profile = labels_profile(label);
Expand All @@ -134,42 +133,44 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
}
}

if (aad(sa)->name) {
if (ad->name) {
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, aad(sa)->name);
audit_log_untrustedstring(ab, ad->name);
}
}

/**
* aa_audit_msg - Log a message to the audit subsystem
* @sa: audit event structure (NOT NULL)
* @type: audit type for the message
* @ad: audit event structure (NOT NULL)
* @cb: optional callback fn for type specific fields (MAYBE NULL)
*/
void aa_audit_msg(int type, struct common_audit_data *sa,
void aa_audit_msg(int type, struct apparmor_audit_data *ad,
void (*cb) (struct audit_buffer *, void *))
{
aad(sa)->type = type;
common_lsm_audit(sa, audit_pre, cb);
ad->type = type;
common_lsm_audit(&ad->common, audit_pre, cb);
}

/**
* aa_audit - Log a profile based audit event to the audit subsystem
* @type: audit type for the message
* @profile: profile to check against (NOT NULL)
* @sa: audit event (NOT NULL)
* @ad: audit event (NOT NULL)
* @cb: optional callback fn for type specific fields (MAYBE NULL)
*
* Handle default message switching based off of audit mode flags
*
* Returns: error on failure
*/
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
int aa_audit(int type, struct aa_profile *profile,
struct apparmor_audit_data *ad,
void (*cb) (struct audit_buffer *, void *))
{
AA_BUG(!profile);

if (type == AUDIT_APPARMOR_AUTO) {
if (likely(!aad(sa)->error)) {
if (likely(!ad->error)) {
if (AUDIT_MODE(profile) != AUDIT_ALL)
return 0;
type = AUDIT_APPARMOR_AUDIT;
Expand All @@ -181,24 +182,24 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
if (AUDIT_MODE(profile) == AUDIT_QUIET ||
(type == AUDIT_APPARMOR_DENIED &&
AUDIT_MODE(profile) == AUDIT_QUIET_DENIED))
return aad(sa)->error;
return ad->error;

if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
type = AUDIT_APPARMOR_KILL;

aad(sa)->label = &profile->label;
ad->subj_label = &profile->label;

aa_audit_msg(type, sa, cb);
aa_audit_msg(type, ad, cb);

if (aad(sa)->type == AUDIT_APPARMOR_KILL)
if (ad->type == AUDIT_APPARMOR_KILL)
(void)send_sig_info(SIGKILL, NULL,
sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
sa->u.tsk : current);
ad->common.type == LSM_AUDIT_DATA_TASK &&
ad->common.u.tsk ? ad->common.u.tsk : current);

if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED)
return complain_error(aad(sa)->error);
if (ad->type == AUDIT_APPARMOR_ALLOWED)
return complain_error(ad->error);

return aad(sa)->error;
return ad->error;
}

struct aa_audit_rule {
Expand Down
Loading

0 comments on commit 6bdfe2d

Please sign in to comment.