Merge tag 'apparmor-pr-2019-12-03' of git://git.kernel.org/pub/scm/linux/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
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
@@ -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 = {
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user