2
0
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:
John Johansen
2006-08-30 00:40:36 +00:00
parent a9e9d7fe1d
commit 802ba1fad1
5 changed files with 97 additions and 27 deletions

View File

@@ -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

View File

@@ -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,
};

View File

@@ -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;

View File

@@ -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++;

View File

@@ -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))