|
21 | 21 | #include <linux/fs.h>
|
22 | 22 | #include <linux/fs_context.h>
|
23 | 23 | #include <linux/poll.h>
|
24 |
| -#include <linux/zlib.h> |
| 24 | +#include <linux/zstd.h> |
25 | 25 | #include <uapi/linux/major.h>
|
26 | 26 | #include <uapi/linux/magic.h>
|
27 | 27 |
|
@@ -611,29 +611,30 @@ static const struct file_operations aa_fs_ns_revision_fops = {
|
611 | 611 | static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
|
612 | 612 | const char *match_str, size_t match_len)
|
613 | 613 | {
|
| 614 | + struct aa_ruleset *rules = list_first_entry(&profile->rules, |
| 615 | + typeof(*rules), list); |
614 | 616 | struct aa_perms tmp = { };
|
615 |
| - struct aa_dfa *dfa; |
616 |
| - unsigned int state = 0; |
| 617 | + aa_state_t state = DFA_NOMATCH; |
617 | 618 |
|
618 | 619 | if (profile_unconfined(profile))
|
619 | 620 | return;
|
620 |
| - if (profile->file.dfa && *match_str == AA_CLASS_FILE) { |
621 |
| - dfa = profile->file.dfa; |
622 |
| - state = aa_dfa_match_len(dfa, profile->file.start, |
| 621 | + if (rules->file.dfa && *match_str == AA_CLASS_FILE) { |
| 622 | + state = aa_dfa_match_len(rules->file.dfa, |
| 623 | + rules->file.start[AA_CLASS_FILE], |
623 | 624 | match_str + 1, match_len - 1);
|
624 | 625 | if (state) {
|
625 | 626 | struct path_cond cond = { };
|
626 | 627 |
|
627 |
| - tmp = aa_compute_fperms(dfa, state, &cond); |
| 628 | + tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); |
628 | 629 | }
|
629 |
| - } else if (profile->policy.dfa) { |
630 |
| - if (!PROFILE_MEDIATES(profile, *match_str)) |
| 630 | + } else if (rules->policy.dfa) { |
| 631 | + if (!RULE_MEDIATES(rules, *match_str)) |
631 | 632 | return; /* no change to current perms */
|
632 |
| - dfa = profile->policy.dfa; |
633 |
| - state = aa_dfa_match_len(dfa, profile->policy.start[0], |
| 633 | + state = aa_dfa_match_len(rules->policy.dfa, |
| 634 | + rules->policy.start[0], |
634 | 635 | match_str, match_len);
|
635 | 636 | if (state)
|
636 |
| - aa_compute_perms(dfa, state, &tmp); |
| 637 | + tmp = *aa_lookup_perms(&rules->policy, state); |
637 | 638 | }
|
638 | 639 | aa_apply_modes_to_perms(profile, &tmp);
|
639 | 640 | aa_perms_accum_raw(perms, &tmp);
|
@@ -868,8 +869,10 @@ static struct multi_transaction *multi_transaction_new(struct file *file,
|
868 | 869 | if (!t)
|
869 | 870 | return ERR_PTR(-ENOMEM);
|
870 | 871 | kref_init(&t->count);
|
871 |
| - if (copy_from_user(t->data, buf, size)) |
| 872 | + if (copy_from_user(t->data, buf, size)) { |
| 873 | + put_multi_transaction(t); |
872 | 874 | return ERR_PTR(-EFAULT);
|
| 875 | + } |
873 | 876 |
|
874 | 877 | return t;
|
875 | 878 | }
|
@@ -1090,9 +1093,9 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v)
|
1090 | 1093 | struct aa_proxy *proxy = seq->private;
|
1091 | 1094 | struct aa_label *label = aa_get_label_rcu(&proxy->label);
|
1092 | 1095 | struct aa_profile *profile = labels_profile(label);
|
1093 |
| - if (profile->attach) |
1094 |
| - seq_printf(seq, "%s\n", profile->attach); |
1095 |
| - else if (profile->xmatch) |
| 1096 | + if (profile->attach.xmatch_str) |
| 1097 | + seq_printf(seq, "%s\n", profile->attach.xmatch_str); |
| 1098 | + else if (profile->attach.xmatch.dfa) |
1096 | 1099 | seq_puts(seq, "<unknown>\n");
|
1097 | 1100 | else
|
1098 | 1101 | seq_printf(seq, "%s\n", profile->base.name);
|
@@ -1197,10 +1200,24 @@ static int seq_ns_name_show(struct seq_file *seq, void *v)
|
1197 | 1200 | return 0;
|
1198 | 1201 | }
|
1199 | 1202 |
|
| 1203 | +static int seq_ns_compress_min_show(struct seq_file *seq, void *v) |
| 1204 | +{ |
| 1205 | + seq_printf(seq, "%d\n", AA_MIN_CLEVEL); |
| 1206 | + return 0; |
| 1207 | +} |
| 1208 | + |
| 1209 | +static int seq_ns_compress_max_show(struct seq_file *seq, void *v) |
| 1210 | +{ |
| 1211 | + seq_printf(seq, "%d\n", AA_MAX_CLEVEL); |
| 1212 | + return 0; |
| 1213 | +} |
| 1214 | + |
1200 | 1215 | SEQ_NS_FOPS(stacked);
|
1201 | 1216 | SEQ_NS_FOPS(nsstacked);
|
1202 | 1217 | SEQ_NS_FOPS(level);
|
1203 | 1218 | SEQ_NS_FOPS(name);
|
| 1219 | +SEQ_NS_FOPS(compress_min); |
| 1220 | +SEQ_NS_FOPS(compress_max); |
1204 | 1221 |
|
1205 | 1222 |
|
1206 | 1223 | /* policy/raw_data/ * file ops */
|
@@ -1295,42 +1312,34 @@ SEQ_RAWDATA_FOPS(revision);
|
1295 | 1312 | SEQ_RAWDATA_FOPS(hash);
|
1296 | 1313 | SEQ_RAWDATA_FOPS(compressed_size);
|
1297 | 1314 |
|
1298 |
| -static int deflate_decompress(char *src, size_t slen, char *dst, size_t dlen) |
| 1315 | +static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen) |
1299 | 1316 | {
|
1300 | 1317 | #ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
|
1301 |
| - if (aa_g_rawdata_compression_level != 0) { |
1302 |
| - int error = 0; |
1303 |
| - struct z_stream_s strm; |
1304 |
| - |
1305 |
| - memset(&strm, 0, sizeof(strm)); |
1306 |
| - |
1307 |
| - strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); |
1308 |
| - if (!strm.workspace) |
1309 |
| - return -ENOMEM; |
1310 |
| - |
1311 |
| - strm.next_in = src; |
1312 |
| - strm.avail_in = slen; |
1313 |
| - |
1314 |
| - error = zlib_inflateInit(&strm); |
1315 |
| - if (error != Z_OK) { |
1316 |
| - error = -ENOMEM; |
1317 |
| - goto fail_inflate_init; |
| 1318 | + if (slen < dlen) { |
| 1319 | + const size_t wksp_len = zstd_dctx_workspace_bound(); |
| 1320 | + zstd_dctx *ctx; |
| 1321 | + void *wksp; |
| 1322 | + size_t out_len; |
| 1323 | + int ret = 0; |
| 1324 | + |
| 1325 | + wksp = kvzalloc(wksp_len, GFP_KERNEL); |
| 1326 | + if (!wksp) { |
| 1327 | + ret = -ENOMEM; |
| 1328 | + goto cleanup; |
1318 | 1329 | }
|
1319 |
| - |
1320 |
| - strm.next_out = dst; |
1321 |
| - strm.avail_out = dlen; |
1322 |
| - |
1323 |
| - error = zlib_inflate(&strm, Z_FINISH); |
1324 |
| - if (error != Z_STREAM_END) |
1325 |
| - error = -EINVAL; |
1326 |
| - else |
1327 |
| - error = 0; |
1328 |
| - |
1329 |
| - zlib_inflateEnd(&strm); |
1330 |
| -fail_inflate_init: |
1331 |
| - kvfree(strm.workspace); |
1332 |
| - |
1333 |
| - return error; |
| 1330 | + ctx = zstd_init_dctx(wksp, wksp_len); |
| 1331 | + if (ctx == NULL) { |
| 1332 | + ret = -ENOMEM; |
| 1333 | + goto cleanup; |
| 1334 | + } |
| 1335 | + out_len = zstd_decompress_dctx(ctx, dst, dlen, src, slen); |
| 1336 | + if (zstd_is_error(out_len)) { |
| 1337 | + ret = -EINVAL; |
| 1338 | + goto cleanup; |
| 1339 | + } |
| 1340 | +cleanup: |
| 1341 | + kvfree(wksp); |
| 1342 | + return ret; |
1334 | 1343 | }
|
1335 | 1344 | #endif
|
1336 | 1345 |
|
@@ -1379,9 +1388,9 @@ static int rawdata_open(struct inode *inode, struct file *file)
|
1379 | 1388 |
|
1380 | 1389 | private->loaddata = loaddata;
|
1381 | 1390 |
|
1382 |
| - error = deflate_decompress(loaddata->data, loaddata->compressed_size, |
1383 |
| - RAWDATA_F_DATA_BUF(private), |
1384 |
| - loaddata->size); |
| 1391 | + error = decompress_zstd(loaddata->data, loaddata->compressed_size, |
| 1392 | + RAWDATA_F_DATA_BUF(private), |
| 1393 | + loaddata->size); |
1385 | 1394 | if (error)
|
1386 | 1395 | goto fail_decompress;
|
1387 | 1396 |
|
@@ -2392,6 +2401,8 @@ static struct aa_sfs_entry aa_sfs_entry_apparmor[] = {
|
2392 | 2401 | AA_SFS_FILE_FOPS(".ns_level", 0444, &seq_ns_level_fops),
|
2393 | 2402 | AA_SFS_FILE_FOPS(".ns_name", 0444, &seq_ns_name_fops),
|
2394 | 2403 | AA_SFS_FILE_FOPS("profiles", 0444, &aa_sfs_profiles_fops),
|
| 2404 | + AA_SFS_FILE_FOPS("raw_data_compression_level_min", 0444, &seq_ns_compress_min_fops), |
| 2405 | + AA_SFS_FILE_FOPS("raw_data_compression_level_max", 0444, &seq_ns_compress_max_fops), |
2395 | 2406 | AA_SFS_DIR("features", aa_sfs_entry_features),
|
2396 | 2407 | { }
|
2397 | 2408 | };
|
|
0 commit comments