hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/security/apparmor/apparmorfs.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * AppArmor security module
34 *
....@@ -5,17 +6,12 @@
56 *
67 * Copyright (C) 1998-2008 Novell/SUSE
78 * Copyright 2009-2010 Canonical Ltd.
8
- *
9
- * This program is free software; you can redistribute it and/or
10
- * modify it under the terms of the GNU General Public License as
11
- * published by the Free Software Foundation, version 2 of the
12
- * License.
139 */
1410
1511 #include <linux/ctype.h>
1612 #include <linux/security.h>
1713 #include <linux/vmalloc.h>
18
-#include <linux/module.h>
14
+#include <linux/init.h>
1915 #include <linux/seq_file.h>
2016 #include <linux/uaccess.h>
2117 #include <linux/mount.h>
....@@ -23,7 +19,9 @@
2319 #include <linux/capability.h>
2420 #include <linux/rcupdate.h>
2521 #include <linux/fs.h>
22
+#include <linux/fs_context.h>
2623 #include <linux/poll.h>
24
+#include <linux/zlib.h>
2725 #include <uapi/linux/major.h>
2826 #include <uapi/linux/magic.h>
2927
....@@ -67,6 +65,35 @@
6765 /*
6866 * support fns
6967 */
68
+
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
+}
7097
7198 /**
7299 * aa_mangle_name - mangle a profile name to std profile layout form
....@@ -123,26 +150,20 @@
123150 return 0;
124151 }
125152
126
-static void aafs_i_callback(struct rcu_head *head)
153
+static void aafs_free_inode(struct inode *inode)
127154 {
128
- struct inode *inode = container_of(head, struct inode, i_rcu);
129155 if (S_ISLNK(inode->i_mode))
130156 kfree(inode->i_link);
131157 free_inode_nonrcu(inode);
132158 }
133159
134
-static void aafs_destroy_inode(struct inode *inode)
135
-{
136
- call_rcu(&inode->i_rcu, aafs_i_callback);
137
-}
138
-
139160 static const struct super_operations aafs_super_ops = {
140161 .statfs = simple_statfs,
141
- .destroy_inode = aafs_destroy_inode,
162
+ .free_inode = aafs_free_inode,
142163 .show_path = aafs_show_path,
143164 };
144165
145
-static int fill_super(struct super_block *sb, void *data, int silent)
166
+static int apparmorfs_fill_super(struct super_block *sb, struct fs_context *fc)
146167 {
147168 static struct tree_descr files[] = { {""} };
148169 int error;
....@@ -155,16 +176,25 @@
155176 return 0;
156177 }
157178
158
-static struct dentry *aafs_mount(struct file_system_type *fs_type,
159
- int flags, const char *dev_name, void *data)
179
+static int apparmorfs_get_tree(struct fs_context *fc)
160180 {
161
- return mount_single(fs_type, flags, data, fill_super);
181
+ return get_tree_single(fc, apparmorfs_fill_super);
182
+}
183
+
184
+static const struct fs_context_operations apparmorfs_context_ops = {
185
+ .get_tree = apparmorfs_get_tree,
186
+};
187
+
188
+static int apparmorfs_init_fs_context(struct fs_context *fc)
189
+{
190
+ fc->ops = &apparmorfs_context_ops;
191
+ return 0;
162192 }
163193
164194 static struct file_system_type aafs_ops = {
165195 .owner = THIS_MODULE,
166196 .name = AAFS_NAME,
167
- .mount = aafs_mount,
197
+ .init_fs_context = apparmorfs_init_fs_context,
168198 .kill_sb = kill_anon_super,
169199 };
170200
....@@ -311,38 +341,6 @@
311341 }
312342
313343 /**
314
- * aafs_create_symlink - create a symlink in the apparmorfs filesystem
315
- * @name: name of dentry to create
316
- * @parent: parent directory for this dentry
317
- * @target: if symlink, symlink target string
318
- * @private: private data
319
- * @iops: struct of inode_operations that should be used
320
- *
321
- * If @target parameter is %NULL, then the @iops parameter needs to be
322
- * setup to handle .readlink and .get_link inode_operations.
323
- */
324
-static struct dentry *aafs_create_symlink(const char *name,
325
- struct dentry *parent,
326
- const char *target,
327
- void *private,
328
- const struct inode_operations *iops)
329
-{
330
- struct dentry *dent;
331
- char *link = NULL;
332
-
333
- if (target) {
334
- if (!link)
335
- return ERR_PTR(-ENOMEM);
336
- }
337
- dent = aafs_create(name, S_IFLNK | 0444, parent, private, link, NULL,
338
- iops);
339
- if (IS_ERR(dent))
340
- kfree(link);
341
-
342
- return dent;
343
-}
344
-
345
-/**
346344 * aafs_remove - removes a file or directory from the apparmorfs filesystem
347345 *
348346 * @dentry: dentry of the file/directory/symlink to removed.
....@@ -403,7 +401,7 @@
403401
404402 data->size = copy_size;
405403 if (copy_from_user(data->data, userbuf, copy_size)) {
406
- kvfree(data);
404
+ aa_put_loaddata(data);
407405 return ERR_PTR(-EFAULT);
408406 }
409407
....@@ -594,7 +592,7 @@
594592
595593 void __aa_bump_ns_revision(struct aa_ns *ns)
596594 {
597
- WRITE_ONCE(ns->revision, ns->revision + 1);
595
+ WRITE_ONCE(ns->revision, READ_ONCE(ns->revision) + 1);
598596 wake_up_interruptible(&ns->wait);
599597 }
600598
....@@ -810,7 +808,7 @@
810808 struct multi_transaction {
811809 struct kref count;
812810 ssize_t size;
813
- char data[0];
811
+ char data[];
814812 };
815813
816814 #define MULTI_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct multi_transaction))
....@@ -869,8 +867,10 @@
869867 if (!t)
870868 return ERR_PTR(-ENOMEM);
871869 kref_init(&t->count);
872
- if (copy_from_user(t->data, buf, size))
870
+ if (copy_from_user(t->data, buf, size)) {
871
+ put_multi_transaction(t);
873872 return ERR_PTR(-EFAULT);
873
+ }
874874
875875 return t;
876876 }
....@@ -1281,36 +1281,117 @@
12811281 return 0;
12821282 }
12831283
1284
+static int seq_rawdata_compressed_size_show(struct seq_file *seq, void *v)
1285
+{
1286
+ struct aa_loaddata *data = seq->private;
1287
+
1288
+ seq_printf(seq, "%zu\n", data->compressed_size);
1289
+
1290
+ return 0;
1291
+}
1292
+
12841293 SEQ_RAWDATA_FOPS(abi);
12851294 SEQ_RAWDATA_FOPS(revision);
12861295 SEQ_RAWDATA_FOPS(hash);
1296
+SEQ_RAWDATA_FOPS(compressed_size);
1297
+
1298
+static int deflate_decompress(char *src, size_t slen, char *dst, size_t dlen)
1299
+{
1300
+ int error;
1301
+ struct z_stream_s strm;
1302
+
1303
+ if (aa_g_rawdata_compression_level == 0) {
1304
+ if (dlen < slen)
1305
+ return -EINVAL;
1306
+ memcpy(dst, src, slen);
1307
+ return 0;
1308
+ }
1309
+
1310
+ memset(&strm, 0, sizeof(strm));
1311
+
1312
+ strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
1313
+ if (!strm.workspace)
1314
+ return -ENOMEM;
1315
+
1316
+ strm.next_in = src;
1317
+ strm.avail_in = slen;
1318
+
1319
+ error = zlib_inflateInit(&strm);
1320
+ if (error != Z_OK) {
1321
+ error = -ENOMEM;
1322
+ goto fail_inflate_init;
1323
+ }
1324
+
1325
+ strm.next_out = dst;
1326
+ strm.avail_out = dlen;
1327
+
1328
+ error = zlib_inflate(&strm, Z_FINISH);
1329
+ if (error != Z_STREAM_END)
1330
+ error = -EINVAL;
1331
+ else
1332
+ error = 0;
1333
+
1334
+ zlib_inflateEnd(&strm);
1335
+fail_inflate_init:
1336
+ kvfree(strm.workspace);
1337
+ return error;
1338
+}
12871339
12881340 static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size,
12891341 loff_t *ppos)
12901342 {
1291
- struct aa_loaddata *rawdata = file->private_data;
1343
+ struct rawdata_f_data *private = file->private_data;
12921344
1293
- return simple_read_from_buffer(buf, size, ppos, rawdata->data,
1294
- rawdata->size);
1345
+ return simple_read_from_buffer(buf, size, ppos,
1346
+ RAWDATA_F_DATA_BUF(private),
1347
+ private->loaddata->size);
12951348 }
12961349
12971350 static int rawdata_release(struct inode *inode, struct file *file)
12981351 {
1299
- aa_put_loaddata(file->private_data);
1352
+ rawdata_f_data_free(file->private_data);
13001353
13011354 return 0;
13021355 }
13031356
13041357 static int rawdata_open(struct inode *inode, struct file *file)
13051358 {
1359
+ int error;
1360
+ struct aa_loaddata *loaddata;
1361
+ struct rawdata_f_data *private;
1362
+
13061363 if (!policy_view_capable(NULL))
13071364 return -EACCES;
1308
- file->private_data = __aa_get_loaddata(inode->i_private);
1309
- if (!file->private_data)
1365
+
1366
+ loaddata = __aa_get_loaddata(inode->i_private);
1367
+ if (!loaddata)
13101368 /* lost race: this entry is being reaped */
13111369 return -ENOENT;
13121370
1371
+ private = rawdata_f_data_alloc(loaddata->size);
1372
+ if (IS_ERR(private)) {
1373
+ error = PTR_ERR(private);
1374
+ goto fail_private_alloc;
1375
+ }
1376
+
1377
+ private->loaddata = loaddata;
1378
+
1379
+ error = deflate_decompress(loaddata->data, loaddata->compressed_size,
1380
+ RAWDATA_F_DATA_BUF(private),
1381
+ loaddata->size);
1382
+ if (error)
1383
+ goto fail_decompress;
1384
+
1385
+ file->private_data = private;
13131386 return 0;
1387
+
1388
+fail_decompress:
1389
+ rawdata_f_data_free(private);
1390
+ return error;
1391
+
1392
+fail_private_alloc:
1393
+ aa_put_loaddata(loaddata);
1394
+ return error;
13141395 }
13151396
13161397 static const struct file_operations rawdata_fops = {
....@@ -1388,6 +1469,13 @@
13881469 goto fail;
13891470 rawdata->dents[AAFS_LOADDATA_HASH] = dent;
13901471 }
1472
+
1473
+ dent = aafs_create_file("compressed_size", S_IFREG | 0444, dir,
1474
+ rawdata,
1475
+ &seq_rawdata_compressed_size_fops);
1476
+ if (IS_ERR(dent))
1477
+ goto fail;
1478
+ rawdata->dents[AAFS_LOADDATA_COMPRESSED_SIZE] = dent;
13911479
13921480 dent = aafs_create_file("raw_data", S_IFREG | 0444,
13931481 dir, rawdata, &rawdata_fops);
....@@ -1645,25 +1733,25 @@
16451733 }
16461734
16471735 if (profile->rawdata) {
1648
- dent = aafs_create_symlink("raw_sha1", dir, NULL,
1649
- profile->label.proxy,
1650
- &rawdata_link_sha1_iops);
1736
+ dent = aafs_create("raw_sha1", S_IFLNK | 0444, dir,
1737
+ profile->label.proxy, NULL, NULL,
1738
+ &rawdata_link_sha1_iops);
16511739 if (IS_ERR(dent))
16521740 goto fail;
16531741 aa_get_proxy(profile->label.proxy);
16541742 profile->dents[AAFS_PROF_RAW_HASH] = dent;
16551743
1656
- dent = aafs_create_symlink("raw_abi", dir, NULL,
1657
- profile->label.proxy,
1658
- &rawdata_link_abi_iops);
1744
+ dent = aafs_create("raw_abi", S_IFLNK | 0444, dir,
1745
+ profile->label.proxy, NULL, NULL,
1746
+ &rawdata_link_abi_iops);
16591747 if (IS_ERR(dent))
16601748 goto fail;
16611749 aa_get_proxy(profile->label.proxy);
16621750 profile->dents[AAFS_PROF_RAW_ABI] = dent;
16631751
1664
- dent = aafs_create_symlink("raw_data", dir, NULL,
1665
- profile->label.proxy,
1666
- &rawdata_link_data_iops);
1752
+ dent = aafs_create("raw_data", S_IFLNK | 0444, dir,
1753
+ profile->label.proxy, NULL, NULL,
1754
+ &rawdata_link_data_iops);
16671755 if (IS_ERR(dent))
16681756 goto fail;
16691757 aa_get_proxy(profile->label.proxy);
....@@ -1749,7 +1837,7 @@
17491837 if (error)
17501838 return error;
17511839
1752
- parent = aa_get_ns(dir->i_private);
1840
+ parent = aa_get_ns(dir->i_private);
17531841 /* rmdir calls the generic securityfs functions to remove files
17541842 * from the apparmor dir. It is up to the apparmor ns locking
17551843 * to avoid races.
....@@ -1959,6 +2047,9 @@
19592047
19602048 return error;
19612049 }
2050
+
2051
+
2052
+#define list_entry_is_head(pos, head, member) (&pos->member == (head))
19622053
19632054 /**
19642055 * __next_ns - find the next namespace to list
....@@ -2243,6 +2334,8 @@
22432334 static struct aa_sfs_entry aa_sfs_entry_policy[] = {
22442335 AA_SFS_DIR("versions", aa_sfs_entry_versions),
22452336 AA_SFS_FILE_BOOLEAN("set_load", 1),
2337
+ /* number of out of band transitions supported */
2338
+ AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED),
22462339 { }
22472340 };
22482341
....@@ -2453,16 +2546,18 @@
24532546 {
24542547 struct aa_ns *ns;
24552548 struct path path;
2549
+ int error;
24562550
24572551 if (!dentry)
24582552 return ERR_PTR(-ECHILD);
2553
+
24592554 ns = aa_get_current_ns();
24602555 path.mnt = mntget(aafs_mnt);
24612556 path.dentry = dget(ns_dir(ns));
2462
- nd_jump_link(&path);
2557
+ error = nd_jump_link(&path);
24632558 aa_put_ns(ns);
24642559
2465
- return NULL;
2560
+ return ERR_PTR(error);
24662561 }
24672562
24682563 static int policy_readlink(struct dentry *dentry, char __user *buffer,