Skip to content

Commit 79e178a

Browse files
committed
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
2 parents 01d1dff + 341c1fd commit 79e178a

File tree

15 files changed

+526
-165
lines changed

15 files changed

+526
-165
lines changed

security/apparmor/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ config SECURITY_APPARMOR
66
select SECURITY_PATH
77
select SECURITYFS
88
select SECURITY_NETWORK
9+
select ZLIB_INFLATE
10+
select ZLIB_DEFLATE
911
default n
1012
help
1113
This enables the AppArmor security module.

security/apparmor/apparmorfs.c

Lines changed: 124 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/fs.h>
2222
#include <linux/fs_context.h>
2323
#include <linux/poll.h>
24+
#include <linux/zlib.h>
2425
#include <uapi/linux/major.h>
2526
#include <uapi/linux/magic.h>
2627

@@ -65,6 +66,35 @@
6566
* support fns
6667
*/
6768

69+
struct rawdata_f_data {
70+
struct aa_loaddata *loaddata;
71+
};
72+
73+
#define RAWDATA_F_DATA_BUF(p) (char *)(p + 1)
74+
75+
static void rawdata_f_data_free(struct rawdata_f_data *private)
76+
{
77+
if (!private)
78+
return;
79+
80+
aa_put_loaddata(private->loaddata);
81+
kvfree(private);
82+
}
83+
84+
static struct rawdata_f_data *rawdata_f_data_alloc(size_t size)
85+
{
86+
struct rawdata_f_data *ret;
87+
88+
if (size > SIZE_MAX - sizeof(*ret))
89+
return ERR_PTR(-EINVAL);
90+
91+
ret = kvzalloc(sizeof(*ret) + size, GFP_KERNEL);
92+
if (!ret)
93+
return ERR_PTR(-ENOMEM);
94+
95+
return ret;
96+
}
97+
6898
/**
6999
* aa_mangle_name - mangle a profile name to std profile layout form
70100
* @name: profile name to mangle (NOT NULL)
@@ -1280,36 +1310,117 @@ static int seq_rawdata_hash_show(struct seq_file *seq, void *v)
12801310
return 0;
12811311
}
12821312

1313+
static int seq_rawdata_compressed_size_show(struct seq_file *seq, void *v)
1314+
{
1315+
struct aa_loaddata *data = seq->private;
1316+
1317+
seq_printf(seq, "%zu\n", data->compressed_size);
1318+
1319+
return 0;
1320+
}
1321+
12831322
SEQ_RAWDATA_FOPS(abi);
12841323
SEQ_RAWDATA_FOPS(revision);
12851324
SEQ_RAWDATA_FOPS(hash);
1325+
SEQ_RAWDATA_FOPS(compressed_size);
1326+
1327+
static int deflate_decompress(char *src, size_t slen, char *dst, size_t dlen)
1328+
{
1329+
int error;
1330+
struct z_stream_s strm;
1331+
1332+
if (aa_g_rawdata_compression_level == 0) {
1333+
if (dlen < slen)
1334+
return -EINVAL;
1335+
memcpy(dst, src, slen);
1336+
return 0;
1337+
}
1338+
1339+
memset(&strm, 0, sizeof(strm));
1340+
1341+
strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
1342+
if (!strm.workspace)
1343+
return -ENOMEM;
1344+
1345+
strm.next_in = src;
1346+
strm.avail_in = slen;
1347+
1348+
error = zlib_inflateInit(&strm);
1349+
if (error != Z_OK) {
1350+
error = -ENOMEM;
1351+
goto fail_inflate_init;
1352+
}
1353+
1354+
strm.next_out = dst;
1355+
strm.avail_out = dlen;
1356+
1357+
error = zlib_inflate(&strm, Z_FINISH);
1358+
if (error != Z_STREAM_END)
1359+
error = -EINVAL;
1360+
else
1361+
error = 0;
1362+
1363+
zlib_inflateEnd(&strm);
1364+
fail_inflate_init:
1365+
kvfree(strm.workspace);
1366+
return error;
1367+
}
12861368

12871369
static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size,
12881370
loff_t *ppos)
12891371
{
1290-
struct aa_loaddata *rawdata = file->private_data;
1372+
struct rawdata_f_data *private = file->private_data;
12911373

1292-
return simple_read_from_buffer(buf, size, ppos, rawdata->data,
1293-
rawdata->size);
1374+
return simple_read_from_buffer(buf, size, ppos,
1375+
RAWDATA_F_DATA_BUF(private),
1376+
private->loaddata->size);
12941377
}
12951378

12961379
static int rawdata_release(struct inode *inode, struct file *file)
12971380
{
1298-
aa_put_loaddata(file->private_data);
1381+
rawdata_f_data_free(file->private_data);
12991382

13001383
return 0;
13011384
}
13021385

13031386
static int rawdata_open(struct inode *inode, struct file *file)
13041387
{
1388+
int error;
1389+
struct aa_loaddata *loaddata;
1390+
struct rawdata_f_data *private;
1391+
13051392
if (!policy_view_capable(NULL))
13061393
return -EACCES;
1307-
file->private_data = __aa_get_loaddata(inode->i_private);
1308-
if (!file->private_data)
1394+
1395+
loaddata = __aa_get_loaddata(inode->i_private);
1396+
if (!loaddata)
13091397
/* lost race: this entry is being reaped */
13101398
return -ENOENT;
13111399

1400+
private = rawdata_f_data_alloc(loaddata->size);
1401+
if (IS_ERR(private)) {
1402+
error = PTR_ERR(private);
1403+
goto fail_private_alloc;
1404+
}
1405+
1406+
private->loaddata = loaddata;
1407+
1408+
error = deflate_decompress(loaddata->data, loaddata->compressed_size,
1409+
RAWDATA_F_DATA_BUF(private),
1410+
loaddata->size);
1411+
if (error)
1412+
goto fail_decompress;
1413+
1414+
file->private_data = private;
13121415
return 0;
1416+
1417+
fail_decompress:
1418+
rawdata_f_data_free(private);
1419+
return error;
1420+
1421+
fail_private_alloc:
1422+
aa_put_loaddata(loaddata);
1423+
return error;
13131424
}
13141425

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

1502+
dent = aafs_create_file("compressed_size", S_IFREG | 0444, dir,
1503+
rawdata,
1504+
&seq_rawdata_compressed_size_fops);
1505+
if (IS_ERR(dent))
1506+
goto fail;
1507+
rawdata->dents[AAFS_LOADDATA_COMPRESSED_SIZE] = dent;
1508+
13911509
dent = aafs_create_file("raw_data", S_IFREG | 0444,
13921510
dir, rawdata, &rawdata_fops);
13931511
if (IS_ERR(dent))

security/apparmor/domain.c

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
520520
label = &new_profile->label;
521521
continue;
522522
}
523-
label = aa_label_parse(&profile->label, *name, GFP_ATOMIC,
523+
label = aa_label_parse(&profile->label, *name, GFP_KERNEL,
524524
true, false);
525525
if (IS_ERR(label))
526526
label = NULL;
@@ -600,7 +600,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile,
600600
/* base the stack on post domain transition */
601601
struct aa_label *base = new;
602602

603-
new = aa_label_parse(base, stack, GFP_ATOMIC, true, false);
603+
new = aa_label_parse(base, stack, GFP_KERNEL, true, false);
604604
if (IS_ERR(new))
605605
new = NULL;
606606
aa_put_label(base);
@@ -685,20 +685,9 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
685685
} else if (COMPLAIN_MODE(profile)) {
686686
/* no exec permission - learning mode */
687687
struct aa_profile *new_profile = NULL;
688-
char *n = kstrdup(name, GFP_ATOMIC);
689-
690-
if (n) {
691-
/* name is ptr into buffer */
692-
long pos = name - buffer;
693-
/* break per cpu buffer hold */
694-
put_buffers(buffer);
695-
new_profile = aa_new_null_profile(profile, false, n,
696-
GFP_KERNEL);
697-
get_buffers(buffer);
698-
name = buffer + pos;
699-
strcpy((char *)name, n);
700-
kfree(n);
701-
}
688+
689+
new_profile = aa_new_null_profile(profile, false, name,
690+
GFP_KERNEL);
702691
if (!new_profile) {
703692
error = -ENOMEM;
704693
info = "could not create null profile";
@@ -719,7 +708,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
719708
if (DEBUG_ON) {
720709
dbg_printk("apparmor: scrubbing environment variables"
721710
" for %s profile=", name);
722-
aa_label_printk(new, GFP_ATOMIC);
711+
aa_label_printk(new, GFP_KERNEL);
723712
dbg_printk("\n");
724713
}
725714
*secure_exec = true;
@@ -795,7 +784,7 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
795784
if (DEBUG_ON) {
796785
dbg_printk("apparmor: scrubbing environment "
797786
"variables for %s label=", xname);
798-
aa_label_printk(onexec, GFP_ATOMIC);
787+
aa_label_printk(onexec, GFP_KERNEL);
799788
dbg_printk("\n");
800789
}
801790
*secure_exec = true;
@@ -829,7 +818,7 @@ static struct aa_label *handle_onexec(struct aa_label *label,
829818
bprm, buffer, cond, unsafe));
830819
if (error)
831820
return ERR_PTR(error);
832-
new = fn_label_build_in_ns(label, profile, GFP_ATOMIC,
821+
new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
833822
aa_get_newest_label(onexec),
834823
profile_transition(profile, bprm, buffer,
835824
cond, unsafe));
@@ -841,9 +830,9 @@ static struct aa_label *handle_onexec(struct aa_label *label,
841830
buffer, cond, unsafe));
842831
if (error)
843832
return ERR_PTR(error);
844-
new = fn_label_build_in_ns(label, profile, GFP_ATOMIC,
833+
new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
845834
aa_label_merge(&profile->label, onexec,
846-
GFP_ATOMIC),
835+
GFP_KERNEL),
847836
profile_transition(profile, bprm, buffer,
848837
cond, unsafe));
849838
}
@@ -903,13 +892,18 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
903892
ctx->nnp = aa_get_label(label);
904893

905894
/* buffer freed below, name is pointer into buffer */
906-
get_buffers(buffer);
895+
buffer = aa_get_buffer(false);
896+
if (!buffer) {
897+
error = -ENOMEM;
898+
goto done;
899+
}
900+
907901
/* Test for onexec first as onexec override other x transitions. */
908902
if (ctx->onexec)
909903
new = handle_onexec(label, ctx->onexec, ctx->token,
910904
bprm, buffer, &cond, &unsafe);
911905
else
912-
new = fn_label_build(label, profile, GFP_ATOMIC,
906+
new = fn_label_build(label, profile, GFP_KERNEL,
913907
profile_transition(profile, bprm, buffer,
914908
&cond, &unsafe));
915909

@@ -953,7 +947,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
953947
if (DEBUG_ON) {
954948
dbg_printk("scrubbing environment variables for %s "
955949
"label=", bprm->filename);
956-
aa_label_printk(new, GFP_ATOMIC);
950+
aa_label_printk(new, GFP_KERNEL);
957951
dbg_printk("\n");
958952
}
959953
bprm->secureexec = 1;
@@ -964,7 +958,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
964958
if (DEBUG_ON) {
965959
dbg_printk("apparmor: clearing unsafe personality "
966960
"bits. %s label=", bprm->filename);
967-
aa_label_printk(new, GFP_ATOMIC);
961+
aa_label_printk(new, GFP_KERNEL);
968962
dbg_printk("\n");
969963
}
970964
bprm->per_clear |= PER_CLEAR_ON_SETID;
@@ -975,7 +969,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
975969

976970
done:
977971
aa_put_label(label);
978-
put_buffers(buffer);
972+
aa_put_buffer(buffer);
979973

980974
return error;
981975

0 commit comments

Comments
 (0)