2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-02 23:35:37 +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; 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 * struct subdomain - primary label for confined tasks
* @active: the current active profile * @active: the current active profile

View File

@@ -13,6 +13,7 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h>
#include <linux/mman.h> #include <linux/mman.h>
#include "apparmor.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) static int apparmor_file_permission(struct file *file, int mask)
{ {
struct aaprofile *active; struct aaprofile *active;
struct aaprofile *f_profile; struct aafile *aaf;
int error = 0; 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 */ /* 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; goto out;
active = get_active_aaprofile(); active = get_active_aaprofile();
if (active && f_profile != active) if (active && aaf->profile != active)
error = aa_perm(active, file->f_dentry, file->f_vfsmnt, error = aa_perm(active, file->f_dentry, file->f_vfsmnt,
mask & (MAY_EXEC | MAY_WRITE | MAY_READ)); mask & (MAY_EXEC | MAY_WRITE | MAY_READ));
put_aaprofile(active); put_aaprofile(active);
@@ -480,43 +481,62 @@ out:
static int apparmor_file_alloc_security(struct file *file) static int apparmor_file_alloc_security(struct file *file)
{ {
struct aaprofile *active; struct aaprofile *active;
int error = 0;
active = get_active_aaprofile(); 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); put_aaprofile(active);
return 0; return error;
} }
static void apparmor_file_free_security(struct file *file) static void apparmor_file_free_security(struct file *file)
{ {
struct aaprofile *p = AA_PROFILE(file->f_security); struct aafile *aaf = (struct aafile *)file->f_security;
put_aaprofile(p);
if (aaf) {
put_aaprofile(aaf->profile);
kfree(aaf);
}
} }
static int apparmor_file_mmap(struct file *file, unsigned long reqprot, static inline int aa_mmap(struct file *file, unsigned long prot,
unsigned long prot, unsigned long flags) unsigned long flags)
{ {
int error = 0, mask = 0; int error = 0, mask = 0;
struct aaprofile *active; struct aaprofile *active;
struct aafile *aaf;
if (!file)
goto out;
active = get_active_aaprofile(); active = get_active_aaprofile();
if (!active || !file ||
!(aaf = (struct aafile *)file->f_security) ||
aaf->type == aa_file_shmem)
goto out;
if (prot & PROT_READ) if (prot & PROT_READ)
mask |= MAY_READ; mask |= MAY_READ;
/* Private mappings don't require write perms since they don't /* Private mappings don't require write perms since they don't
* write back to the files */ * write back to the files */
if (prot & PROT_WRITE && !(flags & MAP_PRIVATE)) if (prot & PROT_WRITE && (!flags & MAP_PRIVATE))
mask |= MAY_WRITE; mask |= MAY_WRITE;
if (prot & PROT_EXEC) if (prot & PROT_EXEC)
mask |= MAY_EXEC; mask |= AA_EXEC_MMAP;
AA_DEBUG("%s: 0x%x\n", __FUNCTION__, mask); 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); put_aaprofile(active);
@@ -524,6 +544,19 @@ out:
return error; 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) static int apparmor_task_alloc_security(struct task_struct *p)
{ {
return aa_fork(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, 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); 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; 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, static int apparmor_getprocattr(struct task_struct *p, char *name, void *value,
size_t size) size_t size)
{ {
int error; int error;
struct aaprofile *active; struct aaprofile *active;
@@ -725,12 +769,15 @@ struct security_operations apparmor_ops = {
.file_alloc_security = apparmor_file_alloc_security, .file_alloc_security = apparmor_file_alloc_security,
.file_free_security = apparmor_file_free_security, .file_free_security = apparmor_file_free_security,
.file_mmap = apparmor_file_mmap, .file_mmap = apparmor_file_mmap,
.file_mprotect = apparmor_file_mprotect,
.task_alloc_security = apparmor_task_alloc_security, .task_alloc_security = apparmor_task_alloc_security,
.task_free_security = apparmor_task_free_security, .task_free_security = apparmor_task_free_security,
.task_post_setuid = apparmor_task_post_setuid, .task_post_setuid = apparmor_task_post_setuid,
.task_reparent_to_init = apparmor_task_reparent_to_init, .task_reparent_to_init = apparmor_task_reparent_to_init,
.shm_shmat = apparmor_shm_shmat,
.getprocattr = apparmor_getprocattr, .getprocattr = apparmor_getprocattr,
.setprocattr = apparmor_setprocattr, .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); 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 & 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 /* Special case access to /proc/self/attr/current
* Currently we only allow access if opened O_WRONLY * 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) { if (sa->type == AA_AUDITTYPE_FILE) {
int perm = audit ? sa->ival : sa->error_code; int perm = audit ? sa->ival : sa->error_code;
audit_log_format(ab, "%s%s%s%s access to %s ", audit_log_format(ab, "%s%s%s%s%s access to %s ",
perm & AA_MAY_READ ? "r" : "", perm & AA_EXEC_MMAP ? "m" : "",
perm & AA_MAY_WRITE ? "w" : "", perm & AA_MAY_READ ? "r" : "",
perm & AA_MAY_EXEC ? "x" : "", perm & AA_MAY_WRITE ? "w" : "",
perm & AA_MAY_LINK ? "l" : "", perm & AA_MAY_EXEC ? "x" : "",
sa->name); perm & AA_MAY_LINK ? "l" : "",
sa->name);
opspec_error = -EPERM; opspec_error = -EPERM;

View File

@@ -465,6 +465,10 @@ static inline int check_rule_and_add(struct aa_entry *file_entry,
goto out; 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); list_add(&file_entry->list, &profile->file_entry);
profile->num_file_entries++; profile->num_file_entries++;

View File

@@ -24,7 +24,8 @@
#define POS_AA_EXEC_INHERIT (POS_AA_MAY_LINK + 1) #define POS_AA_EXEC_INHERIT (POS_AA_MAY_LINK + 1)
#define POS_AA_EXEC_UNCONSTRAINED (POS_AA_EXEC_INHERIT + 1) #define POS_AA_EXEC_UNCONSTRAINED (POS_AA_EXEC_INHERIT + 1)
#define POS_AA_EXEC_PROFILE (POS_AA_EXEC_UNCONSTRAINED + 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 */ /* Modeled after MAY_READ, MAY_WRITE, MAY_EXEC def'ns */
#define AA_MAY_EXEC (0x01 << POS_AA_MAY_EXEC) #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_INHERIT (0x01 << POS_AA_EXEC_INHERIT)
#define AA_EXEC_UNCONSTRAINED (0x01 << POS_AA_EXEC_UNCONSTRAINED) #define AA_EXEC_UNCONSTRAINED (0x01 << POS_AA_EXEC_UNCONSTRAINED)
#define AA_EXEC_PROFILE (0x01 << POS_AA_EXEC_PROFILE) #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 | \ #define AA_EXEC_MODIFIERS(X) (X & (AA_EXEC_INHERIT | \
A_EXEC_UNCONSTRAINED | \ A_EXEC_UNCONSTRAINED | \
AA_EXEC_PROFILE)) AA_EXEC_PROFILE))