mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-06 09:21:00 +01:00
561 lines
17 KiB
Diff
561 lines
17 KiB
Diff
---
|
|
security/apparmor/apparmor.h | 60 +++++++---
|
|
security/apparmor/apparmorfs.c | 2
|
|
security/apparmor/lsm.c | 2
|
|
security/apparmor/main.c | 193 +++++++++++++++++++++++------------
|
|
security/apparmor/match.c | 8 -
|
|
security/apparmor/module_interface.c | 3
|
|
6 files changed, 179 insertions(+), 89 deletions(-)
|
|
|
|
--- a/security/apparmor/apparmor.h
|
|
+++ b/security/apparmor/apparmor.h
|
|
@@ -26,22 +26,50 @@
|
|
#define AA_MAY_LINK 0x0010
|
|
#define AA_MAY_LOCK 0x0020
|
|
#define AA_EXEC_MMAP 0x0040
|
|
+#define AA_EXEC_UNSAFE 0x0080
|
|
+#define AA_EXEC_MOD_0 0x0100
|
|
+#define AA_EXEC_MOD_1 0x0200
|
|
+#define AA_BASE_PERMS (MAY_READ | MAY_WRITE | MAY_EXEC | \
|
|
+ MAY_APPEND | AA_MAY_LINK | \
|
|
+ AA_MAY_LOCK | AA_EXEC_MMAP | \
|
|
+ AA_EXEC_UNSAFE | AA_EXEC_MOD_0 | \
|
|
+ AA_EXEC_MOD_1)
|
|
|
|
-#define AA_CHANGE_PROFILE 0x04000000
|
|
-#define AA_EXEC_INHERIT 0x08000000
|
|
-#define AA_EXEC_UNCONFINED 0x10000000
|
|
-#define AA_EXEC_PROFILE 0x20000000
|
|
-#define AA_EXEC_UNSAFE 0x40000000
|
|
-
|
|
-#define AA_EXEC_MODIFIERS (AA_EXEC_INHERIT | \
|
|
- AA_EXEC_UNCONFINED | \
|
|
- AA_EXEC_PROFILE)
|
|
+#define AA_EXEC_UNCONFINED 0
|
|
+#define AA_EXEC_INHERIT AA_EXEC_MOD_0
|
|
+#define AA_EXEC_PROFILE AA_EXEC_MOD_1
|
|
+#define AA_EXEC_PIX (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
|
|
|
|
-#define AA_VALID_PERM_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | \
|
|
- MAY_APPEND | AA_MAY_LINK | \
|
|
- AA_MAY_LOCK | \
|
|
- AA_EXEC_MODIFIERS | AA_EXEC_MMAP | \
|
|
- AA_EXEC_UNSAFE | AA_CHANGE_PROFILE)
|
|
+#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
|
|
+
|
|
+#define AA_USER_SHIFT 0
|
|
+#define AA_OTHER_SHIFT 10
|
|
+
|
|
+#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT)
|
|
+#define AA_OTHER_PERMS (AA_BASE_PERMS << AA_OTHER_SHIFT)
|
|
+
|
|
+#define AA_FILE_PERMS (AA_USER_PERMS | AA_OTHER_PERMS)
|
|
+
|
|
+#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \
|
|
+ (AA_MAY_LINK << AA_OTHER_SHIFT))
|
|
+
|
|
+#define AA_USER_EXEC (MAY_EXEC << AA_USER_SHIFT)
|
|
+#define AA_OTHER_EXEC (MAY_EXEC << AA_OTHER_SHIFT)
|
|
+
|
|
+#define AA_USER_EXEC_MODS (AA_EXEC_MODIFIERS << AA_USER_SHIFT)
|
|
+#define AA_OTHER_EXEC_MODS (AA_EXEC_MODIFIERS << AA_OTHER_SHIFT)
|
|
+
|
|
+#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
|
|
+
|
|
+#define AA_ALL_EXEC_MODS (AA_USER_EXEC_MODS | \
|
|
+ AA_OTHER_EXEC_MODS)
|
|
+
|
|
+/* shared permissions that are not duplicated in user:group:other */
|
|
+#define AA_CHANGE_PROFILE 0x40000000
|
|
+
|
|
+#define AA_SHARED_PERMS (AA_CHANGE_PROFILE)
|
|
+
|
|
+#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_SHARED_PERMS)
|
|
|
|
#define AA_SECURE_EXEC_NEEDED 1
|
|
|
|
@@ -183,7 +211,7 @@ struct aa_audit {
|
|
const char *name;
|
|
const char *name2;
|
|
const char *name3;
|
|
- int requested_mask, denied_mask;
|
|
+ int request_mask, denied_mask;
|
|
struct iattr *iattr;
|
|
pid_t task, parent;
|
|
int family, type, protocol;
|
|
@@ -226,7 +254,7 @@ extern int aa_perm_dir(struct aa_profile
|
|
struct dentry *dentry, struct vfsmount *mnt,
|
|
int mask);
|
|
extern int aa_perm_path(struct aa_profile *, const char *operation,
|
|
- const char *name, int);
|
|
+ const char *name, int mask, uid_t uid);
|
|
extern int aa_link(struct aa_profile *profile,
|
|
struct dentry *link, struct vfsmount *link_mnt,
|
|
struct dentry *target, struct vfsmount *target_mnt);
|
|
--- a/security/apparmor/apparmorfs.c
|
|
+++ b/security/apparmor/apparmorfs.c
|
|
@@ -89,7 +89,7 @@ static struct file_operations apparmorfs
|
|
static ssize_t aa_matching_read(struct file *file, char __user *buf,
|
|
size_t size, loff_t *ppos)
|
|
{
|
|
- const char *matching = "pattern=aadfa perms=rwxamlz";
|
|
+ const char *matching = "pattern=aadfa perms=rwxamlz user:other";
|
|
|
|
return simple_read_from_buffer(buf, size, ppos, matching,
|
|
strlen(matching));
|
|
--- a/security/apparmor/lsm.c
|
|
+++ b/security/apparmor/lsm.c
|
|
@@ -199,7 +199,7 @@ static int apparmor_sysctl(struct ctl_ta
|
|
if (name && name - buffer >= 5) {
|
|
name -= 5;
|
|
memcpy(name, "/proc", 5);
|
|
- error = aa_perm_path(profile, "sysctl", name, mask);
|
|
+ error = aa_perm_path(profile, "sysctl", name, mask, 0);
|
|
}
|
|
free_page((unsigned long)buffer);
|
|
}
|
|
--- a/security/apparmor/main.c
|
|
+++ b/security/apparmor/main.c
|
|
@@ -31,6 +31,14 @@ static const char *capability_names[] =
|
|
|
|
struct aa_namespace *default_namespace;
|
|
|
|
+static int aa_inode_mode(struct inode *inode)
|
|
+{
|
|
+ /* if the inode doesn't exist the user is creating it */
|
|
+ if (!inode || current->fsuid == inode->i_uid)
|
|
+ return AA_USER_SHIFT;
|
|
+ return AA_OTHER_SHIFT;
|
|
+}
|
|
+
|
|
/**
|
|
* aa_file_denied - check for @mask access on a file
|
|
* @profile: profile to check against
|
|
@@ -51,39 +59,52 @@ static int aa_file_denied(struct aa_prof
|
|
* @profile: profile to check against
|
|
* @link: pathname of link being created
|
|
* @target: pathname of target to be linked to
|
|
+ * @target_mode: UGO shift for target inode
|
|
* @request_mask: the permissions subset valid only if link succeeds
|
|
* Return %0 on success, or else the permissions that the profile denies.
|
|
*/
|
|
static int aa_link_denied(struct aa_profile *profile, const char *link,
|
|
- const char *target, int *request_mask)
|
|
+ const char *target, int target_mode,
|
|
+ int *request_mask)
|
|
{
|
|
int l_mode, t_mode, denied_mask;
|
|
+ int link_mask = AA_MAY_LINK << target_mode;
|
|
|
|
l_mode = aa_match(profile->file_rules, link);
|
|
t_mode = aa_match(profile->file_rules, target);
|
|
|
|
/* Ignore valid-profile-transition flags. */
|
|
- l_mode &= ~AA_CHANGE_PROFILE;
|
|
- t_mode &= ~AA_CHANGE_PROFILE;
|
|
+ l_mode &= ~AA_SHARED_PERMS;
|
|
+ t_mode &= ~AA_SHARED_PERMS;
|
|
|
|
- *request_mask = l_mode | AA_MAY_LINK;
|
|
-
|
|
- /* Link always requires 'l' on the link, a subset of the
|
|
- * target's 'r', 'w', 'x', 'a', 'z', and 'm' permissions on the link,
|
|
- * and if the link has 'x', an exact match of all the execute flags
|
|
- * ('i', 'u', 'U', 'p', 'P').
|
|
- */
|
|
-#define RWXAZM (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND | AA_MAY_LOCK | \
|
|
- AA_EXEC_MMAP)
|
|
- denied_mask = ~l_mode & AA_MAY_LINK;
|
|
- if (l_mode & RWXAZM)
|
|
- denied_mask |= (l_mode & ~ AA_MAY_LINK) & ~t_mode;
|
|
- else
|
|
- denied_mask |= t_mode | AA_MAY_LINK;
|
|
- if (denied_mask & AA_EXEC_MODIFIERS)
|
|
- denied_mask |= MAY_EXEC;
|
|
+ *request_mask = l_mode | link_mask;
|
|
|
|
-#undef RWXAZM
|
|
+ /* Link always requires 'l' on the link, a subset for user:other
|
|
+ * of the target's 'r', 'w', 'x', 'a', 'z', and 'm' permissions on
|
|
+ * the link, and if the link has 'x', an exact match of all the
|
|
+ * execute flags ('i', 'u', 'U', 'p', 'P').
|
|
+ */
|
|
+#define SUBSET_PERMS (AA_FILE_PERMS & ~AA_LINK_BITS)
|
|
+ denied_mask = ~l_mode & link_mask;
|
|
+ if (l_mode & SUBSET_PERMS) {
|
|
+ denied_mask |= (l_mode & SUBSET_PERMS) & ~t_mode;
|
|
+ if (denied_mask & AA_EXEC_BITS)
|
|
+ denied_mask |= l_mode & AA_ALL_EXEC_MODS;
|
|
+ else if (l_mode & AA_EXEC_BITS) {
|
|
+ if (l_mode & AA_USER_EXEC &&
|
|
+ (l_mode & AA_USER_EXEC_MODS) !=
|
|
+ (t_mode & AA_USER_EXEC_MODS))
|
|
+ denied_mask |= AA_USER_EXEC |
|
|
+ (l_mode & AA_USER_EXEC_MODS);
|
|
+ if (l_mode & AA_OTHER_EXEC &&
|
|
+ (l_mode & AA_OTHER_EXEC_MODS) !=
|
|
+ (t_mode & AA_OTHER_EXEC_MODS))
|
|
+ denied_mask |= AA_OTHER_EXEC |
|
|
+ (l_mode & AA_OTHER_EXEC_MODS);
|
|
+ }
|
|
+ } else
|
|
+ denied_mask |= t_mode | link_mask;
|
|
+#undef SUBSET_PERMS
|
|
|
|
return denied_mask;
|
|
}
|
|
@@ -173,7 +194,7 @@ static int aa_perm_dentry(struct aa_prof
|
|
char *buffer = NULL;
|
|
|
|
sa->name = aa_get_name(dentry, mnt, &buffer, check);
|
|
-
|
|
+ sa->request_mask <<= aa_inode_mode(dentry->d_inode);
|
|
if (IS_ERR(sa->name)) {
|
|
/*
|
|
* deleted files are given a pass on permission checks when
|
|
@@ -182,13 +203,13 @@ static int aa_perm_dentry(struct aa_prof
|
|
if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
|
|
sa->denied_mask = 0;
|
|
else {
|
|
- sa->denied_mask = sa->requested_mask;
|
|
+ sa->denied_mask = sa->request_mask;
|
|
sa->error_code = PTR_ERR(sa->name);
|
|
}
|
|
sa->name = NULL;
|
|
} else
|
|
sa->denied_mask = aa_file_denied(profile, sa->name,
|
|
- sa->requested_mask);
|
|
+ sa->request_mask);
|
|
|
|
if (!sa->denied_mask)
|
|
sa->error_code = 0;
|
|
@@ -229,10 +250,10 @@ void free_default_namespace(void)
|
|
default_namespace = NULL;
|
|
}
|
|
|
|
-static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
|
|
- int mask)
|
|
+static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
|
|
+ int mask)
|
|
{
|
|
- char mask_str[10], *m = mask_str;
|
|
+ char *m = buffer;
|
|
|
|
if (mask & AA_EXEC_MMAP)
|
|
*m++ = 'm';
|
|
@@ -242,32 +263,58 @@ static void aa_audit_file_mask(struct au
|
|
*m++ = 'w';
|
|
else if (mask & MAY_APPEND)
|
|
*m++ = 'a';
|
|
- if (mask & (MAY_EXEC | AA_EXEC_MODIFIERS)) {
|
|
+ if (mask & MAY_EXEC) {
|
|
if (mask & AA_EXEC_UNSAFE) {
|
|
- if (mask & AA_EXEC_INHERIT)
|
|
- *m++ = 'i';
|
|
- if (mask & AA_EXEC_UNCONFINED)
|
|
+ switch(mask & AA_EXEC_MODIFIERS) {
|
|
+ case AA_EXEC_UNCONFINED:
|
|
*m++ = 'u';
|
|
- if (mask & AA_EXEC_PROFILE)
|
|
+ break;
|
|
+ case AA_EXEC_PIX:
|
|
+ *m++ = 'p';
|
|
+ /* fall through */
|
|
+ case AA_EXEC_INHERIT:
|
|
+ *m++ = 'i';
|
|
+ break;
|
|
+ case AA_EXEC_PROFILE:
|
|
*m++ = 'p';
|
|
+ break;
|
|
+ }
|
|
} else {
|
|
- if (mask & AA_EXEC_INHERIT)
|
|
- *m++ = 'I';
|
|
- if (mask & AA_EXEC_UNCONFINED)
|
|
+ switch(mask & AA_EXEC_MODIFIERS) {
|
|
+ case AA_EXEC_UNCONFINED:
|
|
*m++ = 'U';
|
|
- if (mask & AA_EXEC_PROFILE)
|
|
+ break;
|
|
+ case AA_EXEC_PIX:
|
|
*m++ = 'P';
|
|
+ /* fall through */
|
|
+ case AA_EXEC_INHERIT:
|
|
+ *m++ = 'I';
|
|
+ break;
|
|
+ case AA_EXEC_PROFILE:
|
|
+ *m++ = 'P';
|
|
+ break;
|
|
+ }
|
|
}
|
|
- if (mask & MAY_EXEC)
|
|
- *m++ = 'x';
|
|
+ *m++ = 'x';
|
|
}
|
|
if (mask & AA_MAY_LINK)
|
|
*m++ = 'l';
|
|
if (mask & AA_MAY_LOCK)
|
|
*m++ = 'k';
|
|
*m++ = '\0';
|
|
+}
|
|
+
|
|
+static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
|
|
+ int mask)
|
|
+{
|
|
+ char user[10], other[10];
|
|
|
|
- audit_log_format(ab, " %s=\"%s\"", name, mask_str);
|
|
+ aa_audit_file_sub_mask(ab, user,
|
|
+ (mask & AA_USER_PERMS) >> AA_USER_SHIFT);
|
|
+ aa_audit_file_sub_mask(ab, other,
|
|
+ (mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT);
|
|
+
|
|
+ audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
|
|
}
|
|
|
|
static const char *address_families[] = {
|
|
@@ -316,8 +363,8 @@ static int aa_audit_base(struct aa_profi
|
|
if (sa->info)
|
|
audit_log_format(ab, " info=\"%s\"", sa->info);
|
|
|
|
- if (sa->requested_mask)
|
|
- aa_audit_file_mask(ab, "requested_mask", sa->requested_mask);
|
|
+ if (sa->request_mask)
|
|
+ aa_audit_file_mask(ab, "request_mask", sa->request_mask);
|
|
|
|
if (sa->denied_mask)
|
|
aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
|
|
@@ -472,7 +519,7 @@ int aa_attr(struct aa_profile *profile,
|
|
sa.operation = "setattr";
|
|
sa.gfp_mask = GFP_KERNEL;
|
|
sa.iattr = iattr;
|
|
- sa.requested_mask = MAY_WRITE;
|
|
+ sa.request_mask = MAY_WRITE;
|
|
sa.error_code = -EACCES;
|
|
|
|
check = 0;
|
|
@@ -506,7 +553,7 @@ int aa_perm_xattr(struct aa_profile *pro
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.operation = operation;
|
|
sa.gfp_mask = GFP_KERNEL;
|
|
- sa.requested_mask = mask;
|
|
+ sa.request_mask = mask;
|
|
sa.error_code = -EACCES;
|
|
|
|
if (inode && S_ISDIR(inode->i_mode))
|
|
@@ -540,7 +587,7 @@ int aa_perm(struct aa_profile *profile,
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.operation = operation;
|
|
sa.gfp_mask = GFP_KERNEL;
|
|
- sa.requested_mask = mask;
|
|
+ sa.request_mask = mask;
|
|
sa.error_code = -EACCES;
|
|
|
|
error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
|
|
@@ -569,24 +616,28 @@ int aa_perm_dir(struct aa_profile *profi
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.operation = operation;
|
|
sa.gfp_mask = GFP_KERNEL;
|
|
- sa.requested_mask = mask;
|
|
+ sa.request_mask = mask;
|
|
sa.error_code = -EACCES;
|
|
|
|
return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR);
|
|
}
|
|
|
|
int aa_perm_path(struct aa_profile *profile, const char *operation,
|
|
- const char *name, int mask)
|
|
+ const char *name, int mask, uid_t uid)
|
|
{
|
|
struct aa_audit sa;
|
|
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.operation = operation;
|
|
sa.gfp_mask = GFP_KERNEL;
|
|
- sa.requested_mask = mask;
|
|
+ sa.request_mask = mask;
|
|
sa.name = name;
|
|
+ if (current->fsuid == uid)
|
|
+ sa.request_mask = mask << AA_USER_SHIFT;
|
|
+ else
|
|
+ sa.request_mask = mask << AA_OTHER_SHIFT;
|
|
|
|
- sa.denied_mask = aa_file_denied(profile, name, mask);
|
|
+ sa.denied_mask = aa_file_denied(profile, name, sa.request_mask) ;
|
|
sa.error_code = sa.denied_mask ? -EACCES : 0;
|
|
|
|
return aa_audit(profile, &sa);
|
|
@@ -672,9 +723,10 @@ int aa_link(struct aa_profile *profile,
|
|
}
|
|
|
|
if (sa.name && sa.name2) {
|
|
- sa.requested_mask = AA_MAY_LINK;
|
|
+ sa.request_mask = AA_MAY_LINK;
|
|
sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
|
|
- &sa.requested_mask);
|
|
+ aa_inode_mode(target->d_inode),
|
|
+ &sa.request_mask);
|
|
sa.error_code = sa.denied_mask ? -EACCES : 0;
|
|
}
|
|
|
|
@@ -818,7 +870,7 @@ aa_register_find(struct aa_profile *prof
|
|
__FUNCTION__, new_profile->name);
|
|
} else if (mandatory && profile) {
|
|
sa->info = "mandatory profile missing";
|
|
- sa->denied_mask = MAY_EXEC;
|
|
+ sa->denied_mask = sa->request_mask; /* shifted MAY_EXEC */
|
|
if (complain) {
|
|
aa_audit_hint(profile, sa);
|
|
new_profile =
|
|
@@ -829,7 +881,7 @@ aa_register_find(struct aa_profile *prof
|
|
}
|
|
} else {
|
|
/* Only way we can get into this code is if task
|
|
- * is unconfined.
|
|
+ * is unconfined, or pix.
|
|
*/
|
|
AA_DEBUG("%s: No profile found for exec image '%s'\n",
|
|
__FUNCTION__,
|
|
@@ -851,7 +903,7 @@ int aa_register(struct linux_binprm *bpr
|
|
char *buffer = NULL;
|
|
struct file *filp = bprm->file;
|
|
struct aa_profile *profile, *old_profile, *new_profile = NULL;
|
|
- int exec_mode = AA_EXEC_UNSAFE, complain = 0;
|
|
+ int exec_mode, complain = 0, shift;
|
|
struct aa_audit sa;
|
|
|
|
AA_DEBUG("%s\n", __FUNCTION__);
|
|
@@ -862,11 +914,14 @@ int aa_register(struct linux_binprm *bpr
|
|
return -ENOENT;
|
|
}
|
|
|
|
+ shift = aa_inode_mode(filp->f_dentry->d_inode);
|
|
+ exec_mode = AA_EXEC_UNSAFE << shift;
|
|
+
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.operation = "exec";
|
|
sa.gfp_mask = GFP_KERNEL;
|
|
sa.name = filename;
|
|
- sa.requested_mask = MAY_EXEC;
|
|
+ sa.request_mask = MAY_EXEC << shift;
|
|
|
|
repeat:
|
|
profile = aa_get_profile(current);
|
|
@@ -878,16 +933,16 @@ repeat:
|
|
*/
|
|
exec_mode = aa_match(profile->file_rules, filename);
|
|
|
|
- if (exec_mode & (MAY_EXEC | AA_EXEC_MODIFIERS)) {
|
|
- switch (exec_mode & (MAY_EXEC | AA_EXEC_MODIFIERS)) {
|
|
- case MAY_EXEC | AA_EXEC_INHERIT:
|
|
+ if (exec_mode & sa.request_mask) {
|
|
+ switch ((exec_mode >> shift) & AA_EXEC_MODIFIERS) {
|
|
+ case AA_EXEC_INHERIT:
|
|
AA_DEBUG("%s: INHERIT %s\n",
|
|
__FUNCTION__,
|
|
filename);
|
|
/* nothing to be done here */
|
|
goto cleanup;
|
|
|
|
- case MAY_EXEC | AA_EXEC_UNCONFINED:
|
|
+ case AA_EXEC_UNCONFINED:
|
|
AA_DEBUG("%s: UNCONFINED %s\n",
|
|
__FUNCTION__,
|
|
filename);
|
|
@@ -896,7 +951,7 @@ repeat:
|
|
new_profile = NULL;
|
|
break;
|
|
|
|
- case MAY_EXEC | AA_EXEC_PROFILE:
|
|
+ case AA_EXEC_PROFILE:
|
|
AA_DEBUG("%s: PROFILE %s\n",
|
|
__FUNCTION__,
|
|
filename);
|
|
@@ -905,6 +960,18 @@ repeat:
|
|
1, complain,
|
|
&sa);
|
|
break;
|
|
+ case AA_EXEC_PIX:
|
|
+ AA_DEBUG("%s: PROFILE %s\n",
|
|
+ __FUNCTION__,
|
|
+ filename);
|
|
+ new_profile = aa_register_find(profile,
|
|
+ filename,
|
|
+ 0, complain,
|
|
+ &sa);
|
|
+ if (!new_profile)
|
|
+ /* inherit - nothing to be done here */
|
|
+ goto cleanup;
|
|
+ break;
|
|
}
|
|
|
|
} else if (complain) {
|
|
@@ -914,9 +981,9 @@ repeat:
|
|
*/
|
|
new_profile =
|
|
aa_dup_profile(profile->ns->null_complain_profile);
|
|
- exec_mode |= AA_EXEC_UNSAFE;
|
|
+ exec_mode |= AA_EXEC_UNSAFE << shift;
|
|
} else {
|
|
- sa.denied_mask = MAY_EXEC;
|
|
+ sa.denied_mask = sa.request_mask;
|
|
aa_audit_reject(profile, &sa);
|
|
new_profile = ERR_PTR(-EPERM);
|
|
}
|
|
@@ -937,7 +1004,7 @@ repeat:
|
|
if (PTR_ERR(old_profile) == -ESTALE)
|
|
goto repeat;
|
|
if (PTR_ERR(old_profile) == -EPERM) {
|
|
- sa.denied_mask = MAY_EXEC;
|
|
+ sa.denied_mask = sa.request_mask;
|
|
sa.info = "unable to set profile due to ptrace";
|
|
sa.task = current->parent->pid;
|
|
aa_audit_reject(profile, &sa);
|
|
@@ -957,7 +1024,7 @@ repeat:
|
|
* Cases 2 and 3 are marked as requiring secure exec
|
|
* (unless policy specified "unsafe exec")
|
|
*/
|
|
- if (!(exec_mode & AA_EXEC_UNSAFE)) {
|
|
+ if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) {
|
|
unsigned long bprm_flags;
|
|
|
|
bprm_flags = AA_SECURE_EXEC_NEEDED;
|
|
@@ -967,7 +1034,7 @@ repeat:
|
|
|
|
if (complain && new_profile &&
|
|
new_profile == new_profile->ns->null_complain_profile) {
|
|
- sa.requested_mask = 0;
|
|
+ sa.request_mask = 0;
|
|
sa.name = NULL;
|
|
sa.info = "set profile";
|
|
aa_audit_hint(new_profile, &sa);
|
|
--- a/security/apparmor/match.c
|
|
+++ b/security/apparmor/match.c
|
|
@@ -175,14 +175,8 @@ int verify_dfa(struct aa_dfa *dfa)
|
|
for (i = 0; i < state_count; i++) {
|
|
int mode = ACCEPT_TABLE(dfa)[i];
|
|
|
|
- if (mode & ~AA_VALID_PERM_MASK)
|
|
+ if (mode & ~AA_VALID_PERM_MASK) {
|
|
goto out;
|
|
-
|
|
- /* if MAY_EXEC, exactly one exec modifier must be set */
|
|
- if (mode & MAY_EXEC) {
|
|
- mode &= AA_EXEC_MODIFIERS;
|
|
- if (mode & (mode - 1))
|
|
- goto out;
|
|
}
|
|
}
|
|
|
|
--- a/security/apparmor/module_interface.c
|
|
+++ b/security/apparmor/module_interface.c
|
|
@@ -349,7 +349,8 @@ fail:
|
|
sa.operation = operation;
|
|
sa.gfp_mask = GFP_KERNEL;
|
|
sa.name = profile && profile->name ? profile->name : "unknown";
|
|
- sa.info = "failed to unpack profile";
|
|
+ if (!sa.info)
|
|
+ sa.info = "failed to unpack profile";
|
|
aa_audit_status(NULL, &sa);
|
|
|
|
if (profile)
|