summaryrefslogtreecommitdiff
path: root/security/apparmor/file.c
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2019-09-14 13:34:06 +0300
committerJohn Johansen <john.johansen@canonical.com>2019-11-23 03:41:08 +0300
commit341c1fda5e17156619fb71acfc7082b2669b4b72 (patch)
treee5fbbd464835c19aec5fa16ce4bd325a4667fa05 /security/apparmor/file.c
parentbce4e7e9c45ef97ac1e30b9cb4adc25b5b5a7cfa (diff)
downloadlinux-341c1fda5e17156619fb71acfc7082b2669b4b72.tar.xz
apparmor: make it so work buffers can be allocated from atomic context
In some situations AppArmor needs to be able to use its work buffers from atomic context. Add the ability to specify when in atomic context and hold a set of work buffers in reserve for atomic context to reduce the chance that a large work buffer allocation will need to be done. Fixes: df323337e507 ("apparmor: Use a memory pool instead per-CPU caches") Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security/apparmor/file.c')
-rw-r--r--security/apparmor/file.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 37d62ecec29d..b520fdfc3504 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -336,7 +336,7 @@ int aa_path_perm(const char *op, struct aa_label *label,
flags |= PATH_DELEGATE_DELETED | (S_ISDIR(cond->mode) ? PATH_IS_DIR :
0);
- buffer = aa_get_buffer();
+ buffer = aa_get_buffer(false);
if (!buffer)
return -ENOMEM;
error = fn_for_each_confined(label, profile,
@@ -481,8 +481,8 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
int error;
/* buffer freed below, lname is pointer in buffer */
- buffer = aa_get_buffer();
- buffer2 = aa_get_buffer();
+ buffer = aa_get_buffer(false);
+ buffer2 = aa_get_buffer(false);
error = -ENOMEM;
if (!buffer || !buffer2)
goto out;
@@ -519,7 +519,7 @@ static void update_file_ctx(struct aa_file_ctx *fctx, struct aa_label *label,
static int __file_path_perm(const char *op, struct aa_label *label,
struct aa_label *flabel, struct file *file,
- u32 request, u32 denied)
+ u32 request, u32 denied, bool in_atomic)
{
struct aa_profile *profile;
struct aa_perms perms = {};
@@ -536,7 +536,7 @@ static int __file_path_perm(const char *op, struct aa_label *label,
return 0;
flags = PATH_DELEGATE_DELETED | (S_ISDIR(cond.mode) ? PATH_IS_DIR : 0);
- buffer = aa_get_buffer();
+ buffer = aa_get_buffer(in_atomic);
if (!buffer)
return -ENOMEM;
@@ -604,11 +604,12 @@ static int __file_sock_perm(const char *op, struct aa_label *label,
* @label: label being enforced (NOT NULL)
* @file: file to revalidate access permissions on (NOT NULL)
* @request: requested permissions
+ * @in_atomic: whether allocations need to be done in atomic context
*
* Returns: %0 if access allowed else error
*/
int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
- u32 request)
+ u32 request, bool in_atomic)
{
struct aa_file_ctx *fctx;
struct aa_label *flabel;
@@ -641,7 +642,7 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry))
error = __file_path_perm(op, label, flabel, file, request,
- denied);
+ denied, in_atomic);
else if (S_ISSOCK(file_inode(file)->i_mode))
error = __file_sock_perm(op, label, flabel, file, request,
@@ -669,7 +670,8 @@ static void revalidate_tty(struct aa_label *label)
struct tty_file_private, list);
file = file_priv->file;
- if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE))
+ if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE,
+ IN_ATOMIC))
drop_tty = 1;
}
spin_unlock(&tty->files_lock);
@@ -683,7 +685,8 @@ static int match_file(const void *p, struct file *file, unsigned int fd)
{
struct aa_label *label = (struct aa_label *)p;
- if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file)))
+ if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file),
+ IN_ATOMIC))
return fd + 1;
return 0;
}