apparmor: add io_uring mediation
For now, the io_uring mediation is limited to sqpoll and override_creds. Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com> Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
fa9b63adab
commit
c4371d9063
|
@ -2390,6 +2390,12 @@ static struct aa_sfs_entry aa_sfs_entry_query[] = {
|
||||||
AA_SFS_DIR("label", aa_sfs_entry_query_label),
|
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[] = {
|
static struct aa_sfs_entry aa_sfs_entry_features[] = {
|
||||||
AA_SFS_DIR("policy", aa_sfs_entry_policy),
|
AA_SFS_DIR("policy", aa_sfs_entry_policy),
|
||||||
AA_SFS_DIR("domain", aa_sfs_entry_domain),
|
AA_SFS_DIR("domain", aa_sfs_entry_domain),
|
||||||
|
@ -2403,6 +2409,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
|
||||||
AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace),
|
AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace),
|
||||||
AA_SFS_DIR("signal", aa_sfs_entry_signal),
|
AA_SFS_DIR("signal", aa_sfs_entry_signal),
|
||||||
AA_SFS_DIR("query", aa_sfs_entry_query),
|
AA_SFS_DIR("query", aa_sfs_entry_query),
|
||||||
|
AA_SFS_DIR("io_uring", aa_sfs_entry_io_uring),
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ static const char *const aa_class_names[] = {
|
||||||
"module",
|
"module",
|
||||||
"lsm",
|
"lsm",
|
||||||
"namespace",
|
"namespace",
|
||||||
"unknown",
|
"io_uring",
|
||||||
"unknown",
|
"unknown",
|
||||||
"unknown",
|
"unknown",
|
||||||
"unknown",
|
"unknown",
|
||||||
|
|
|
@ -30,10 +30,10 @@
|
||||||
#define AA_CLASS_NET 14
|
#define AA_CLASS_NET 14
|
||||||
#define AA_CLASS_LABEL 16
|
#define AA_CLASS_LABEL 16
|
||||||
#define AA_CLASS_POSIX_MQUEUE 17
|
#define AA_CLASS_POSIX_MQUEUE 17
|
||||||
#define AA_CLASS_IO_URING 18
|
|
||||||
#define AA_CLASS_MODULE 19
|
#define AA_CLASS_MODULE 19
|
||||||
#define AA_CLASS_DISPLAY_LSM 20
|
#define AA_CLASS_DISPLAY_LSM 20
|
||||||
#define AA_CLASS_NS 21
|
#define AA_CLASS_NS 21
|
||||||
|
#define AA_CLASS_IO_URING 22
|
||||||
|
|
||||||
#define AA_CLASS_X 31
|
#define AA_CLASS_X 31
|
||||||
#define AA_CLASS_DBUS 32
|
#define AA_CLASS_DBUS 32
|
||||||
|
|
|
@ -105,6 +105,9 @@ enum audit_type {
|
||||||
|
|
||||||
#define OP_USERNS_CREATE "userns_create"
|
#define OP_USERNS_CREATE "userns_create"
|
||||||
|
|
||||||
|
#define OP_URING_OVERRIDE "uring_override"
|
||||||
|
#define OP_URING_SQPOLL "uring_sqpoll"
|
||||||
|
|
||||||
struct apparmor_audit_data {
|
struct apparmor_audit_data {
|
||||||
int error;
|
int error;
|
||||||
int type;
|
int type;
|
||||||
|
@ -153,6 +156,9 @@ struct apparmor_audit_data {
|
||||||
const char *data;
|
const char *data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
} mnt;
|
} mnt;
|
||||||
|
struct {
|
||||||
|
struct aa_label *target;
|
||||||
|
} uring;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct common_audit_data common;
|
struct common_audit_data common;
|
||||||
|
|
|
@ -48,6 +48,9 @@
|
||||||
|
|
||||||
#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
|
#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
|
||||||
|
|
||||||
|
#define AA_MAY_CREATE_SQPOLL AA_MAY_CREATE
|
||||||
|
#define AA_MAY_OVERRIDE_CRED AA_MAY_APPEND
|
||||||
|
#define AA_URING_PERM_MASK (AA_MAY_OVERRIDE_CRED | AA_MAY_CREATE_SQPOLL)
|
||||||
|
|
||||||
#define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE | \
|
#define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE | \
|
||||||
AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK | \
|
AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK | \
|
||||||
|
|
|
@ -582,6 +582,114 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_IO_URING
|
||||||
|
static const char *audit_uring_mask(u32 mask)
|
||||||
|
{
|
||||||
|
if (mask & AA_MAY_CREATE_SQPOLL)
|
||||||
|
return "sqpoll";
|
||||||
|
if (mask & AA_MAY_OVERRIDE_CRED)
|
||||||
|
return "override_creds";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void audit_uring_cb(struct audit_buffer *ab, void *va)
|
||||||
|
{
|
||||||
|
struct apparmor_audit_data *ad = aad_of_va(va);
|
||||||
|
|
||||||
|
if (ad->request & AA_URING_PERM_MASK) {
|
||||||
|
audit_log_format(ab, " requested=\"%s\"",
|
||||||
|
audit_uring_mask(ad->request));
|
||||||
|
if (ad->denied & AA_URING_PERM_MASK) {
|
||||||
|
audit_log_format(ab, " denied=\"%s\"",
|
||||||
|
audit_uring_mask(ad->denied));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ad->uring.target) {
|
||||||
|
audit_log_format(ab, " tcontext=");
|
||||||
|
aa_label_xaudit(ab, labels_ns(ad->subj_label),
|
||||||
|
ad->uring.target,
|
||||||
|
FLAGS_NONE, GFP_ATOMIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int profile_uring(struct aa_profile *profile, u32 request,
|
||||||
|
struct aa_label *new, int cap,
|
||||||
|
struct apparmor_audit_data *ad)
|
||||||
|
{
|
||||||
|
unsigned int state;
|
||||||
|
struct aa_ruleset *rules;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
AA_BUG(!profile);
|
||||||
|
|
||||||
|
rules = list_first_entry(&profile->rules, typeof(*rules), list);
|
||||||
|
state = RULE_MEDIATES(rules, AA_CLASS_IO_URING);
|
||||||
|
if (state) {
|
||||||
|
struct aa_perms perms = { };
|
||||||
|
|
||||||
|
if (new) {
|
||||||
|
aa_label_match(profile, rules, new, state,
|
||||||
|
false, request, &perms);
|
||||||
|
} else {
|
||||||
|
perms = *aa_lookup_perms(rules->policy, state);
|
||||||
|
}
|
||||||
|
aa_apply_modes_to_perms(profile, &perms);
|
||||||
|
error = aa_check_perms(profile, &perms, request, ad,
|
||||||
|
audit_uring_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apparmor_uring_override_creds - check the requested cred override
|
||||||
|
* @new: the target creds
|
||||||
|
*
|
||||||
|
* Check to see if the current task is allowed to override it's credentials
|
||||||
|
* to service an io_uring operation.
|
||||||
|
*/
|
||||||
|
int apparmor_uring_override_creds(const struct cred *new)
|
||||||
|
{
|
||||||
|
struct aa_profile *profile;
|
||||||
|
struct aa_label *label;
|
||||||
|
int error;
|
||||||
|
DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING,
|
||||||
|
OP_URING_OVERRIDE);
|
||||||
|
|
||||||
|
ad.uring.target = cred_label(new);
|
||||||
|
label = __begin_current_label_crit_section();
|
||||||
|
error = fn_for_each(label, profile,
|
||||||
|
profile_uring(profile, AA_MAY_OVERRIDE_CRED,
|
||||||
|
cred_label(new), CAP_SYS_ADMIN, &ad));
|
||||||
|
__end_current_label_crit_section(label);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apparmor_uring_sqpoll - check if a io_uring polling thread can be created
|
||||||
|
*
|
||||||
|
* Check to see if the current task is allowed to create a new io_uring
|
||||||
|
* kernel polling thread.
|
||||||
|
*/
|
||||||
|
int apparmor_uring_sqpoll(void)
|
||||||
|
{
|
||||||
|
struct aa_profile *profile;
|
||||||
|
struct aa_label *label;
|
||||||
|
int error;
|
||||||
|
DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING,
|
||||||
|
OP_URING_SQPOLL);
|
||||||
|
|
||||||
|
label = __begin_current_label_crit_section();
|
||||||
|
error = fn_for_each(label, profile,
|
||||||
|
profile_uring(profile, AA_MAY_CREATE_SQPOLL,
|
||||||
|
NULL, CAP_SYS_ADMIN, &ad));
|
||||||
|
__end_current_label_crit_section(label);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IO_URING */
|
||||||
|
|
||||||
static int apparmor_sb_mount(const char *dev_name, const struct path *path,
|
static int apparmor_sb_mount(const char *dev_name, const struct path *path,
|
||||||
const char *type, unsigned long flags, void *data)
|
const char *type, unsigned long flags, void *data)
|
||||||
{
|
{
|
||||||
|
@ -1346,6 +1454,11 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = {
|
||||||
LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx),
|
LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx),
|
||||||
LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid),
|
LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid),
|
||||||
LSM_HOOK_INIT(release_secctx, apparmor_release_secctx),
|
LSM_HOOK_INIT(release_secctx, apparmor_release_secctx),
|
||||||
|
|
||||||
|
#ifdef CONFIG_IO_URING
|
||||||
|
LSM_HOOK_INIT(uring_override_creds, apparmor_uring_override_creds),
|
||||||
|
LSM_HOOK_INIT(uring_sqpoll, apparmor_uring_sqpoll),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue