Skip to content

Commit

Permalink
Merge tag 'apparmor-pr-2019-12-03' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/jj/linux-apparmor

Pull apparmor updates from John Johansen:
 "Features:

   - increase left match history buffer size to provide improved
     conflict resolution in overlapping execution rules.

   - switch buffer allocation to use a memory pool and GFP_KERNEL where
     possible.

   - add compression of policy blobs to reduce memory usage.

  Cleanups:

   - fix spelling mistake "immutible" -> "immutable"

  Bug fixes:

   - fix unsigned len comparison in update_for_len macro

   - fix sparse warning for type-casting of current->real_cred"

* tag 'apparmor-pr-2019-12-03' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
  apparmor: make it so work buffers can be allocated from atomic context
  apparmor: reduce rcu_read_lock scope for aa_file_perm mediation
  apparmor: fix wrong buffer allocation in aa_new_mount
  apparmor: fix unsigned len comparison with less than zero
  apparmor: increase left match history buffer size
  apparmor: Switch to GFP_KERNEL where possible
  apparmor: Use a memory pool instead per-CPU caches
  apparmor: Force type-casting of current->real_cred
  apparmor: fix spelling mistake "immutible" -> "immutable"
  apparmor: fix blob compression when ns is forced on a policy load
  apparmor: fix missing ZLIB defines
  apparmor: fix blob compression build failure on ppc
  apparmor: Initial implementation of raw policy blob compression
  • Loading branch information
torvalds committed Dec 3, 2019
2 parents 01d1dff + 341c1fd commit 79e178a
Show file tree
Hide file tree
Showing 15 changed files with 526 additions and 165 deletions.
2 changes: 2 additions & 0 deletions security/apparmor/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ config SECURITY_APPARMOR
select SECURITY_PATH
select SECURITYFS
select SECURITY_NETWORK
select ZLIB_INFLATE
select ZLIB_DEFLATE
default n
help
This enables the AppArmor security module.
Expand Down
130 changes: 124 additions & 6 deletions security/apparmor/apparmorfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/fs.h>
#include <linux/fs_context.h>
#include <linux/poll.h>
#include <linux/zlib.h>
#include <uapi/linux/major.h>
#include <uapi/linux/magic.h>

Expand Down Expand Up @@ -65,6 +66,35 @@
* support fns
*/

struct rawdata_f_data {
struct aa_loaddata *loaddata;
};

#define RAWDATA_F_DATA_BUF(p) (char *)(p + 1)

static void rawdata_f_data_free(struct rawdata_f_data *private)
{
if (!private)
return;

aa_put_loaddata(private->loaddata);
kvfree(private);
}

static struct rawdata_f_data *rawdata_f_data_alloc(size_t size)
{
struct rawdata_f_data *ret;

if (size > SIZE_MAX - sizeof(*ret))
return ERR_PTR(-EINVAL);

ret = kvzalloc(sizeof(*ret) + size, GFP_KERNEL);
if (!ret)
return ERR_PTR(-ENOMEM);

return ret;
}

/**
* aa_mangle_name - mangle a profile name to std profile layout form
* @name: profile name to mangle (NOT NULL)
Expand Down Expand Up @@ -1280,36 +1310,117 @@ static int seq_rawdata_hash_show(struct seq_file *seq, void *v)
return 0;
}

static int seq_rawdata_compressed_size_show(struct seq_file *seq, void *v)
{
struct aa_loaddata *data = seq->private;

seq_printf(seq, "%zu\n", data->compressed_size);

return 0;
}

SEQ_RAWDATA_FOPS(abi);
SEQ_RAWDATA_FOPS(revision);
SEQ_RAWDATA_FOPS(hash);
SEQ_RAWDATA_FOPS(compressed_size);

static int deflate_decompress(char *src, size_t slen, char *dst, size_t dlen)
{
int error;
struct z_stream_s strm;

if (aa_g_rawdata_compression_level == 0) {
if (dlen < slen)
return -EINVAL;
memcpy(dst, src, slen);
return 0;
}

memset(&strm, 0, sizeof(strm));

strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
if (!strm.workspace)
return -ENOMEM;

strm.next_in = src;
strm.avail_in = slen;

error = zlib_inflateInit(&strm);
if (error != Z_OK) {
error = -ENOMEM;
goto fail_inflate_init;
}

strm.next_out = dst;
strm.avail_out = dlen;

error = zlib_inflate(&strm, Z_FINISH);
if (error != Z_STREAM_END)
error = -EINVAL;
else
error = 0;

zlib_inflateEnd(&strm);
fail_inflate_init:
kvfree(strm.workspace);
return error;
}

static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size,
loff_t *ppos)
{
struct aa_loaddata *rawdata = file->private_data;
struct rawdata_f_data *private = file->private_data;

return simple_read_from_buffer(buf, size, ppos, rawdata->data,
rawdata->size);
return simple_read_from_buffer(buf, size, ppos,
RAWDATA_F_DATA_BUF(private),
private->loaddata->size);
}

static int rawdata_release(struct inode *inode, struct file *file)
{
aa_put_loaddata(file->private_data);
rawdata_f_data_free(file->private_data);

return 0;
}

static int rawdata_open(struct inode *inode, struct file *file)
{
int error;
struct aa_loaddata *loaddata;
struct rawdata_f_data *private;

if (!policy_view_capable(NULL))
return -EACCES;
file->private_data = __aa_get_loaddata(inode->i_private);
if (!file->private_data)

loaddata = __aa_get_loaddata(inode->i_private);
if (!loaddata)
/* lost race: this entry is being reaped */
return -ENOENT;

private = rawdata_f_data_alloc(loaddata->size);
if (IS_ERR(private)) {
error = PTR_ERR(private);
goto fail_private_alloc;
}

private->loaddata = loaddata;

error = deflate_decompress(loaddata->data, loaddata->compressed_size,
RAWDATA_F_DATA_BUF(private),
loaddata->size);
if (error)
goto fail_decompress;

file->private_data = private;
return 0;

fail_decompress:
rawdata_f_data_free(private);
return error;

fail_private_alloc:
aa_put_loaddata(loaddata);
return error;
}

static const struct file_operations rawdata_fops = {
Expand Down Expand Up @@ -1388,6 +1499,13 @@ int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata)
rawdata->dents[AAFS_LOADDATA_HASH] = dent;
}

dent = aafs_create_file("compressed_size", S_IFREG | 0444, dir,
rawdata,
&seq_rawdata_compressed_size_fops);
if (IS_ERR(dent))
goto fail;
rawdata->dents[AAFS_LOADDATA_COMPRESSED_SIZE] = dent;

dent = aafs_create_file("raw_data", S_IFREG | 0444,
dir, rawdata, &rawdata_fops);
if (IS_ERR(dent))
Expand Down
46 changes: 20 additions & 26 deletions security/apparmor/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
label = &new_profile->label;
continue;
}
label = aa_label_parse(&profile->label, *name, GFP_ATOMIC,
label = aa_label_parse(&profile->label, *name, GFP_KERNEL,
true, false);
if (IS_ERR(label))
label = NULL;
Expand Down Expand Up @@ -600,7 +600,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
/* base the stack on post domain transition */
struct aa_label *base = new;

new = aa_label_parse(base, stack, GFP_ATOMIC, true, false);
new = aa_label_parse(base, stack, GFP_KERNEL, true, false);
if (IS_ERR(new))
new = NULL;
aa_put_label(base);
Expand Down Expand Up @@ -685,20 +685,9 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
} else if (COMPLAIN_MODE(profile)) {
/* no exec permission - learning mode */
struct aa_profile *new_profile = NULL;
char *n = kstrdup(name, GFP_ATOMIC);

if (n) {
/* name is ptr into buffer */
long pos = name - buffer;
/* break per cpu buffer hold */
put_buffers(buffer);
new_profile = aa_new_null_profile(profile, false, n,
GFP_KERNEL);
get_buffers(buffer);
name = buffer + pos;
strcpy((char *)name, n);
kfree(n);
}

new_profile = aa_new_null_profile(profile, false, name,
GFP_KERNEL);
if (!new_profile) {
error = -ENOMEM;
info = "could not create null profile";
Expand All @@ -719,7 +708,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
if (DEBUG_ON) {
dbg_printk("apparmor: scrubbing environment variables"
" for %s profile=", name);
aa_label_printk(new, GFP_ATOMIC);
aa_label_printk(new, GFP_KERNEL);
dbg_printk("\n");
}
*secure_exec = true;
Expand Down Expand Up @@ -795,7 +784,7 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
if (DEBUG_ON) {
dbg_printk("apparmor: scrubbing environment "
"variables for %s label=", xname);
aa_label_printk(onexec, GFP_ATOMIC);
aa_label_printk(onexec, GFP_KERNEL);
dbg_printk("\n");
}
*secure_exec = true;
Expand Down Expand Up @@ -829,7 +818,7 @@ static struct aa_label *handle_onexec(struct aa_label *label,
bprm, buffer, cond, unsafe));
if (error)
return ERR_PTR(error);
new = fn_label_build_in_ns(label, profile, GFP_ATOMIC,
new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
aa_get_newest_label(onexec),
profile_transition(profile, bprm, buffer,
cond, unsafe));
Expand All @@ -841,9 +830,9 @@ static struct aa_label *handle_onexec(struct aa_label *label,
buffer, cond, unsafe));
if (error)
return ERR_PTR(error);
new = fn_label_build_in_ns(label, profile, GFP_ATOMIC,
new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
aa_label_merge(&profile->label, onexec,
GFP_ATOMIC),
GFP_KERNEL),
profile_transition(profile, bprm, buffer,
cond, unsafe));
}
Expand Down Expand Up @@ -903,13 +892,18 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
ctx->nnp = aa_get_label(label);

/* buffer freed below, name is pointer into buffer */
get_buffers(buffer);
buffer = aa_get_buffer(false);
if (!buffer) {
error = -ENOMEM;
goto done;
}

/* Test for onexec first as onexec override other x transitions. */
if (ctx->onexec)
new = handle_onexec(label, ctx->onexec, ctx->token,
bprm, buffer, &cond, &unsafe);
else
new = fn_label_build(label, profile, GFP_ATOMIC,
new = fn_label_build(label, profile, GFP_KERNEL,
profile_transition(profile, bprm, buffer,
&cond, &unsafe));

Expand Down Expand Up @@ -953,7 +947,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
if (DEBUG_ON) {
dbg_printk("scrubbing environment variables for %s "
"label=", bprm->filename);
aa_label_printk(new, GFP_ATOMIC);
aa_label_printk(new, GFP_KERNEL);
dbg_printk("\n");
}
bprm->secureexec = 1;
Expand All @@ -964,7 +958,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
if (DEBUG_ON) {
dbg_printk("apparmor: clearing unsafe personality "
"bits. %s label=", bprm->filename);
aa_label_printk(new, GFP_ATOMIC);
aa_label_printk(new, GFP_KERNEL);
dbg_printk("\n");
}
bprm->per_clear |= PER_CLEAR_ON_SETID;
Expand All @@ -975,7 +969,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)

done:
aa_put_label(label);
put_buffers(buffer);
aa_put_buffer(buffer);

return error;

Expand Down
Loading

0 comments on commit 79e178a

Please sign in to comment.