Commit 190a9518 authored by John Johansen's avatar John Johansen

apparmor: move aa_file_perm() to use labels

Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent 290f458a
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "include/match.h" #include "include/match.h"
#include "include/path.h" #include "include/path.h"
#include "include/policy.h" #include "include/policy.h"
#include "include/label.h"
static u32 map_mask_to_chr_mask(u32 mask) static u32 map_mask_to_chr_mask(u32 mask)
{ {
...@@ -433,22 +434,55 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, ...@@ -433,22 +434,55 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
/** /**
* aa_file_perm - do permission revalidation check & audit for @file * aa_file_perm - do permission revalidation check & audit for @file
* @op: operation being checked * @op: operation being checked
* @profile: profile being enforced (NOT NULL) * @label: label being enforced (NOT NULL)
* @file: file to revalidate access permissions on (NOT NULL) * @file: file to revalidate access permissions on (NOT NULL)
* @request: requested permissions * @request: requested permissions
* *
* Returns: %0 if access allowed else error * Returns: %0 if access allowed else error
*/ */
int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
u32 request) u32 request)
{ {
struct path_cond cond = { struct path_cond cond = {
.uid = file_inode(file)->i_uid, .uid = file_inode(file)->i_uid,
.mode = file_inode(file)->i_mode .mode = file_inode(file)->i_mode
}; };
struct aa_file_ctx *fctx;
struct aa_label *flabel;
u32 denied;
int error = 0;
AA_BUG(!label);
AA_BUG(!file);
fctx = file_ctx(file);
rcu_read_lock();
flabel = rcu_dereference(fctx->label);
AA_BUG(!flabel);
/* revalidate access, if task is unconfined, or the cached cred
* doesn't match or if the request is for more permissions than
* was granted.
*
* Note: the test for !unconfined(flabel) is to handle file
* delegation from unconfined tasks
*/
denied = request & ~fctx->allow;
if (unconfined(label) || unconfined(flabel) ||
(!denied && aa_label_is_subset(flabel, label)))
goto done;
/* TODO: label cross check */
if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry))
error = aa_path_perm(op, labels_profile(label), &file->f_path,
PATH_DELEGATE_DELETED, request, &cond);
return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED, done:
request, &cond); rcu_read_unlock();
return error;
} }
static void revalidate_tty(struct aa_label *label) static void revalidate_tty(struct aa_label *label)
...@@ -469,8 +503,7 @@ static void revalidate_tty(struct aa_label *label) ...@@ -469,8 +503,7 @@ static void revalidate_tty(struct aa_label *label)
struct tty_file_private, list); struct tty_file_private, list);
file = file_priv->file; file = file_priv->file;
if (aa_file_perm(OP_INHERIT, labels_profile(label), file, if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE))
MAY_READ | MAY_WRITE))
drop_tty = 1; drop_tty = 1;
} }
spin_unlock(&tty->files_lock); spin_unlock(&tty->files_lock);
...@@ -484,8 +517,7 @@ static int match_file(const void *p, struct file *file, unsigned int fd) ...@@ -484,8 +517,7 @@ static int match_file(const void *p, struct file *file, unsigned int fd)
{ {
struct aa_label *label = (struct aa_label *)p; struct aa_label *label = (struct aa_label *)p;
if (aa_file_perm(OP_INHERIT, labels_profile(label), file, if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file)))
aa_map_file_to_perms(file)))
return fd + 1; return fd + 1;
return 0; return 0;
} }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#ifndef __AA_FILE_H #ifndef __AA_FILE_H
#define __AA_FILE_H #define __AA_FILE_H
#include <linux/spinlock.h>
#include "domain.h" #include "domain.h"
#include "match.h" #include "match.h"
#include "perms.h" #include "perms.h"
...@@ -33,13 +35,13 @@ struct path; ...@@ -33,13 +35,13 @@ struct path;
#define file_ctx(X) ((struct aa_file_ctx *)(X)->f_security) #define file_ctx(X) ((struct aa_file_ctx *)(X)->f_security)
/* struct aa_file_ctx - the AppArmor context the file was opened in /* struct aa_file_ctx - the AppArmor context the file was opened in
* @lock: lock to update the ctx
* @label: label currently cached on the ctx
* @perms: the permission the file was opened with * @perms: the permission the file was opened with
*
* The file_ctx could currently be directly stored in file->f_security
* as the profile reference is now stored in the f_cred. However the
* ctx struct will expand in the future so we keep the struct.
*/ */
struct aa_file_ctx { struct aa_file_ctx {
spinlock_t lock;
struct aa_label __rcu *label;
u32 allow; u32 allow;
}; };
...@@ -50,12 +52,16 @@ struct aa_file_ctx { ...@@ -50,12 +52,16 @@ struct aa_file_ctx {
* *
* Returns: file_ctx or NULL on failure * Returns: file_ctx or NULL on failure
*/ */
static inline struct aa_file_ctx *aa_alloc_file_ctx(gfp_t gfp) static inline struct aa_file_ctx *aa_alloc_file_ctx(struct aa_label *label,
gfp_t gfp)
{ {
struct aa_file_ctx *ctx; struct aa_file_ctx *ctx;
ctx = kzalloc(sizeof(struct aa_file_ctx), gfp); ctx = kzalloc(sizeof(struct aa_file_ctx), gfp);
if (ctx) {
spin_lock_init(&ctx->lock);
rcu_assign_pointer(ctx->label, aa_get_label(label));
}
return ctx; return ctx;
} }
...@@ -65,8 +71,15 @@ static inline struct aa_file_ctx *aa_alloc_file_ctx(gfp_t gfp) ...@@ -65,8 +71,15 @@ static inline struct aa_file_ctx *aa_alloc_file_ctx(gfp_t gfp)
*/ */
static inline void aa_free_file_ctx(struct aa_file_ctx *ctx) static inline void aa_free_file_ctx(struct aa_file_ctx *ctx)
{ {
if (ctx) if (ctx) {
aa_put_label(rcu_access_pointer(ctx->label));
kzfree(ctx); kzfree(ctx);
}
}
static inline struct aa_label *aa_get_file_label(struct aa_file_ctx *ctx)
{
return aa_get_label_rcu(&ctx->label);
} }
/* /*
...@@ -183,7 +196,7 @@ int aa_path_perm(const char *op, struct aa_profile *profile, ...@@ -183,7 +196,7 @@ int aa_path_perm(const char *op, struct aa_profile *profile,
int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
const struct path *new_dir, struct dentry *new_dentry); const struct path *new_dir, struct dentry *new_dentry);
int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
u32 request); u32 request);
void aa_inherit_files(const struct cred *cred, struct files_struct *files); void aa_inherit_files(const struct cred *cred, struct files_struct *files);
......
...@@ -433,7 +433,7 @@ static int apparmor_file_alloc_security(struct file *file) ...@@ -433,7 +433,7 @@ static int apparmor_file_alloc_security(struct file *file)
/* freed by apparmor_file_free_security */ /* freed by apparmor_file_free_security */
struct aa_label *label = begin_current_label_crit_section(); struct aa_label *label = begin_current_label_crit_section();
file->f_security = aa_alloc_file_ctx(GFP_KERNEL); file->f_security = aa_alloc_file_ctx(label, GFP_KERNEL);
if (!file_ctx(file)) if (!file_ctx(file))
error = -ENOMEM; error = -ENOMEM;
end_current_label_crit_section(label); end_current_label_crit_section(label);
...@@ -448,33 +448,15 @@ static void apparmor_file_free_security(struct file *file) ...@@ -448,33 +448,15 @@ static void apparmor_file_free_security(struct file *file)
static int common_file_perm(const char *op, struct file *file, u32 mask) static int common_file_perm(const char *op, struct file *file, u32 mask)
{ {
struct aa_file_ctx *fctx = file->f_security; struct aa_label *label;
struct aa_label *label, *flabel;
int error = 0; int error = 0;
/* don't reaudit files closed during inheritance */ /* don't reaudit files closed during inheritance */
if (file->f_path.dentry == aa_null.dentry) if (file->f_path.dentry == aa_null.dentry)
return -EACCES; return -EACCES;
flabel = aa_cred_raw_label(file->f_cred);
AA_BUG(!flabel);
if (!file->f_path.mnt ||
!path_mediated_fs(file->f_path.dentry))
return 0;
label = __begin_current_label_crit_section(); label = __begin_current_label_crit_section();
error = aa_file_perm(op, label, file, mask);
/* revalidate access, if task is unconfined, or the cached cred
* doesn't match or if the request is for more permissions than
* was granted.
*
* Note: the test for !unconfined(fprofile) is to handle file
* delegation from unconfined tasks
*/
if (!unconfined(label) && !unconfined(flabel) &&
((flabel != label) || (mask & ~fctx->allow)))
error = aa_file_perm(op, labels_profile(label), file, mask);
__end_current_label_crit_section(label); __end_current_label_crit_section(label);
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment