mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-31 14:25:52 +00:00
Add the m permission bit and change the way exec permissions for mmap are handled
This commit is contained in:
@@ -153,6 +153,21 @@ struct aaprofile {
|
||||
struct kref count;
|
||||
};
|
||||
|
||||
enum aafile_type {
|
||||
aa_file_default,
|
||||
aa_file_shmem
|
||||
};
|
||||
|
||||
/**
|
||||
* aafile - file pointer confinement data
|
||||
*
|
||||
* Data structure assigned to each open file (by apparmor_file_alloc_security)
|
||||
*/
|
||||
struct aafile {
|
||||
enum aafile_type type;
|
||||
struct aaprofile *profile;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct subdomain - primary label for confined tasks
|
||||
* @active: the current active profile
|
||||
|
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <linux/security.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
|
||||
#include "apparmor.h"
|
||||
@@ -459,16 +460,16 @@ static int apparmor_inode_removexattr(struct dentry *dentry, char *name)
|
||||
static int apparmor_file_permission(struct file *file, int mask)
|
||||
{
|
||||
struct aaprofile *active;
|
||||
struct aaprofile *f_profile;
|
||||
struct aafile *aaf;
|
||||
int error = 0;
|
||||
|
||||
f_profile = AA_PROFILE(file->f_security);
|
||||
aaf = (struct aafile *)file->f_security;
|
||||
/* bail out early if this isn't a mediated file */
|
||||
if (!(f_profile && VALID_FSTYPE(file->f_dentry->d_inode)))
|
||||
if (!aaf || !VALID_FSTYPE(file->f_dentry->d_inode))
|
||||
goto out;
|
||||
|
||||
active = get_active_aaprofile();
|
||||
if (active && f_profile != active)
|
||||
if (active && aaf->profile != active)
|
||||
error = aa_perm(active, file->f_dentry, file->f_vfsmnt,
|
||||
mask & (MAY_EXEC | MAY_WRITE | MAY_READ));
|
||||
put_aaprofile(active);
|
||||
@@ -480,43 +481,62 @@ out:
|
||||
static int apparmor_file_alloc_security(struct file *file)
|
||||
{
|
||||
struct aaprofile *active;
|
||||
int error = 0;
|
||||
|
||||
active = get_active_aaprofile();
|
||||
file->f_security = get_aaprofile(active);
|
||||
if (active) {
|
||||
struct aafile *aaf;
|
||||
aaf = kmalloc(sizeof(struct aafile), GFP_KERNEL);
|
||||
|
||||
if (aaf) {
|
||||
aaf->type = aa_file_default;
|
||||
aaf->profile = get_aaprofile(active);
|
||||
} else {
|
||||
error = -ENOMEM;
|
||||
}
|
||||
}
|
||||
put_aaprofile(active);
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static void apparmor_file_free_security(struct file *file)
|
||||
{
|
||||
struct aaprofile *p = AA_PROFILE(file->f_security);
|
||||
put_aaprofile(p);
|
||||
struct aafile *aaf = (struct aafile *)file->f_security;
|
||||
|
||||
if (aaf) {
|
||||
put_aaprofile(aaf->profile);
|
||||
kfree(aaf);
|
||||
}
|
||||
}
|
||||
|
||||
static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags)
|
||||
static inline int aa_mmap(struct file *file, unsigned long prot,
|
||||
unsigned long flags)
|
||||
{
|
||||
int error = 0, mask = 0;
|
||||
struct aaprofile *active;
|
||||
|
||||
if (!file)
|
||||
goto out;
|
||||
struct aafile *aaf;
|
||||
|
||||
active = get_active_aaprofile();
|
||||
if (!active || !file ||
|
||||
!(aaf = (struct aafile *)file->f_security) ||
|
||||
aaf->type == aa_file_shmem)
|
||||
goto out;
|
||||
|
||||
if (prot & PROT_READ)
|
||||
mask |= MAY_READ;
|
||||
|
||||
/* Private mappings don't require write perms since they don't
|
||||
* write back to the files */
|
||||
if (prot & PROT_WRITE && !(flags & MAP_PRIVATE))
|
||||
if (prot & PROT_WRITE && (!flags & MAP_PRIVATE))
|
||||
mask |= MAY_WRITE;
|
||||
if (prot & PROT_EXEC)
|
||||
mask |= MAY_EXEC;
|
||||
mask |= AA_EXEC_MMAP;
|
||||
|
||||
AA_DEBUG("%s: 0x%x\n", __FUNCTION__, mask);
|
||||
|
||||
error = aa_perm(active, file->f_dentry, file->f_vfsmnt, mask);
|
||||
if (mask)
|
||||
error = aa_perm(active, file->f_dentry, file->f_vfsmnt, mask);
|
||||
|
||||
put_aaprofile(active);
|
||||
|
||||
@@ -524,6 +544,19 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags)
|
||||
{
|
||||
return aa_mmap(file, prot, flags);
|
||||
}
|
||||
|
||||
static int apparmor_file_mprotect(struct vm_area_struct *vma,
|
||||
unsigned long reqprot, unsigned long prot)
|
||||
{
|
||||
return aa_mmap(vma->vm_file, prot,
|
||||
!(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
|
||||
}
|
||||
|
||||
static int apparmor_task_alloc_security(struct task_struct *p)
|
||||
{
|
||||
return aa_fork(p);
|
||||
@@ -535,7 +568,7 @@ static void apparmor_task_free_security(struct task_struct *p)
|
||||
}
|
||||
|
||||
static int apparmor_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
|
||||
int flags)
|
||||
int flags)
|
||||
{
|
||||
return cap_task_post_setuid(id0, id1, id2, flags);
|
||||
}
|
||||
@@ -546,8 +579,19 @@ static void apparmor_task_reparent_to_init(struct task_struct *p)
|
||||
return;
|
||||
}
|
||||
|
||||
static int apparmor_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
|
||||
int shmflg)
|
||||
{
|
||||
struct aafile *aaf = (struct aafile *)shp->shm_file->f_security;
|
||||
|
||||
if (aaf)
|
||||
aaf->type = aa_file_shmem;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apparmor_getprocattr(struct task_struct *p, char *name, void *value,
|
||||
size_t size)
|
||||
size_t size)
|
||||
{
|
||||
int error;
|
||||
struct aaprofile *active;
|
||||
@@ -725,12 +769,15 @@ struct security_operations apparmor_ops = {
|
||||
.file_alloc_security = apparmor_file_alloc_security,
|
||||
.file_free_security = apparmor_file_free_security,
|
||||
.file_mmap = apparmor_file_mmap,
|
||||
.file_mprotect = apparmor_file_mprotect,
|
||||
|
||||
.task_alloc_security = apparmor_task_alloc_security,
|
||||
.task_free_security = apparmor_task_free_security,
|
||||
.task_post_setuid = apparmor_task_post_setuid,
|
||||
.task_reparent_to_init = apparmor_task_reparent_to_init,
|
||||
|
||||
.shm_shmat = apparmor_shm_shmat,
|
||||
|
||||
.getprocattr = apparmor_getprocattr,
|
||||
.setprocattr = apparmor_setprocattr,
|
||||
};
|
||||
|
@@ -288,9 +288,10 @@ static unsigned int aa_file_perm(struct aaprofile *active, const char *name,
|
||||
|
||||
AA_DEBUG("%s: %s 0x%x\n", __FUNCTION__, name, mask);
|
||||
|
||||
/* should not enter with other than R/W/X/L */
|
||||
/* should not enter with other than R/W/M/X/L */
|
||||
WARN_ON(mask &
|
||||
~(AA_MAY_READ | AA_MAY_WRITE | AA_MAY_EXEC | AA_MAY_LINK));
|
||||
~(AA_MAY_READ | AA_MAY_WRITE | AA_MAY_EXEC | AA_EXEC_MMAP |
|
||||
AA_MAY_LINK));
|
||||
|
||||
/* Special case access to /proc/self/attr/current
|
||||
* Currently we only allow access if opened O_WRONLY
|
||||
@@ -664,12 +665,13 @@ int aa_audit(struct aaprofile *active, const struct aa_audit *sa)
|
||||
if (sa->type == AA_AUDITTYPE_FILE) {
|
||||
int perm = audit ? sa->ival : sa->error_code;
|
||||
|
||||
audit_log_format(ab, "%s%s%s%s access to %s ",
|
||||
perm & AA_MAY_READ ? "r" : "",
|
||||
perm & AA_MAY_WRITE ? "w" : "",
|
||||
perm & AA_MAY_EXEC ? "x" : "",
|
||||
perm & AA_MAY_LINK ? "l" : "",
|
||||
sa->name);
|
||||
audit_log_format(ab, "%s%s%s%s%s access to %s ",
|
||||
perm & AA_EXEC_MMAP ? "m" : "",
|
||||
perm & AA_MAY_READ ? "r" : "",
|
||||
perm & AA_MAY_WRITE ? "w" : "",
|
||||
perm & AA_MAY_EXEC ? "x" : "",
|
||||
perm & AA_MAY_LINK ? "l" : "",
|
||||
sa->name);
|
||||
|
||||
opspec_error = -EPERM;
|
||||
|
||||
|
@@ -465,6 +465,10 @@ static inline int check_rule_and_add(struct aa_entry *file_entry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* ix -> m (required so that target exec binary may map itself) */
|
||||
if (mode & AA_EXEC_INHERIT)
|
||||
file_entry->mode |= AA_EXEC_MMAP;
|
||||
|
||||
list_add(&file_entry->list, &profile->file_entry);
|
||||
profile->num_file_entries++;
|
||||
|
||||
|
@@ -24,7 +24,8 @@
|
||||
#define POS_AA_EXEC_INHERIT (POS_AA_MAY_LINK + 1)
|
||||
#define POS_AA_EXEC_UNCONSTRAINED (POS_AA_EXEC_INHERIT + 1)
|
||||
#define POS_AA_EXEC_PROFILE (POS_AA_EXEC_UNCONSTRAINED + 1)
|
||||
#define POS_AA_FILE_MAX POS_AA_EXEC_PROFILE
|
||||
#define POS_AA_EXEC_MMAP (POS_AA_EXEC_PROFILE + 1)
|
||||
#define POS_AA_FILE_MAX POS_AA_EXEC_MMAP
|
||||
|
||||
/* Modeled after MAY_READ, MAY_WRITE, MAY_EXEC def'ns */
|
||||
#define AA_MAY_EXEC (0x01 << POS_AA_MAY_EXEC)
|
||||
@@ -34,6 +35,7 @@
|
||||
#define AA_EXEC_INHERIT (0x01 << POS_AA_EXEC_INHERIT)
|
||||
#define AA_EXEC_UNCONSTRAINED (0x01 << POS_AA_EXEC_UNCONSTRAINED)
|
||||
#define AA_EXEC_PROFILE (0x01 << POS_AA_EXEC_PROFILE)
|
||||
#define AA_EXEC_MMAP (0x01 << POS_AA_EXEC_MMAP)
|
||||
#define AA_EXEC_MODIFIERS(X) (X & (AA_EXEC_INHERIT | \
|
||||
A_EXEC_UNCONSTRAINED | \
|
||||
AA_EXEC_PROFILE))
|
||||
|
Reference in New Issue
Block a user