hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
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))
....@@ -1281,36 +1279,117 @@
12811279 return 0;
12821280 }
12831281
1282
+static int seq_rawdata_compressed_size_show(struct seq_file *seq, void *v)
1283
+{
1284
+ struct aa_loaddata *data = seq->private;
1285
+
1286
+ seq_printf(seq, "%zu\n", data->compressed_size);
1287
+
1288
+ return 0;
1289
+}
1290
+
12841291 SEQ_RAWDATA_FOPS(abi);
12851292 SEQ_RAWDATA_FOPS(revision);
12861293 SEQ_RAWDATA_FOPS(hash);
1294
+SEQ_RAWDATA_FOPS(compressed_size);
1295
+
1296
+static int deflate_decompress(char *src, size_t slen, char *dst, size_t dlen)
1297
+{
1298
+ int error;
1299
+ struct z_stream_s strm;
1300
+
1301
+ if (aa_g_rawdata_compression_level == 0) {
1302
+ if (dlen < slen)
1303
+ return -EINVAL;
1304
+ memcpy(dst, src, slen);
1305
+ return 0;
1306
+ }
1307
+
1308
+ memset(&strm, 0, sizeof(strm));
1309
+
1310
+ strm.workspace = kvzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
1311
+ if (!strm.workspace)
1312
+ return -ENOMEM;
1313
+
1314
+ strm.next_in = src;
1315
+ strm.avail_in = slen;
1316
+
1317
+ error = zlib_inflateInit(&strm);
1318
+ if (error != Z_OK) {
1319
+ error = -ENOMEM;
1320
+ goto fail_inflate_init;
1321
+ }
1322
+
1323
+ strm.next_out = dst;
1324
+ strm.avail_out = dlen;
1325
+
1326
+ error = zlib_inflate(&strm, Z_FINISH);
1327
+ if (error != Z_STREAM_END)
1328
+ error = -EINVAL;
1329
+ else
1330
+ error = 0;
1331
+
1332
+ zlib_inflateEnd(&strm);
1333
+fail_inflate_init:
1334
+ kvfree(strm.workspace);
1335
+ return error;
1336
+}
12871337
12881338 static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size,
12891339 loff_t *ppos)
12901340 {
1291
- struct aa_loaddata *rawdata = file->private_data;
1341
+ struct rawdata_f_data *private = file->private_data;
12921342
1293
- return simple_read_from_buffer(buf, size, ppos, rawdata->data,
1294
- rawdata->size);
1343
+ return simple_read_from_buffer(buf, size, ppos,
1344
+ RAWDATA_F_DATA_BUF(private),
1345
+ private->loaddata->size);
12951346 }
12961347
12971348 static int rawdata_release(struct inode *inode, struct file *file)
12981349 {
1299
- aa_put_loaddata(file->private_data);
1350
+ rawdata_f_data_free(file->private_data);
13001351
13011352 return 0;
13021353 }
13031354
13041355 static int rawdata_open(struct inode *inode, struct file *file)
13051356 {
1357
+ int error;
1358
+ struct aa_loaddata *loaddata;
1359
+ struct rawdata_f_data *private;
1360
+
13061361 if (!policy_view_capable(NULL))
13071362 return -EACCES;
1308
- file->private_data = __aa_get_loaddata(inode->i_private);
1309
- if (!file->private_data)
1363
+
1364
+ loaddata = __aa_get_loaddata(inode->i_private);
1365
+ if (!loaddata)
13101366 /* lost race: this entry is being reaped */
13111367 return -ENOENT;
13121368
1369
+ private = rawdata_f_data_alloc(loaddata->size);
1370
+ if (IS_ERR(private)) {
1371
+ error = PTR_ERR(private);
1372
+ goto fail_private_alloc;
1373
+ }
1374
+
1375
+ private->loaddata = loaddata;
1376
+
1377
+ error = deflate_decompress(loaddata->data, loaddata->compressed_size,
1378
+ RAWDATA_F_DATA_BUF(private),
1379
+ loaddata->size);
1380
+ if (error)
1381
+ goto fail_decompress;
1382
+
1383
+ file->private_data = private;
13131384 return 0;
1385
+
1386
+fail_decompress:
1387
+ rawdata_f_data_free(private);
1388
+ return error;
1389
+
1390
+fail_private_alloc:
1391
+ aa_put_loaddata(loaddata);
1392
+ return error;
13141393 }
13151394
13161395 static const struct file_operations rawdata_fops = {
....@@ -1388,6 +1467,13 @@
13881467 goto fail;
13891468 rawdata->dents[AAFS_LOADDATA_HASH] = dent;
13901469 }
1470
+
1471
+ dent = aafs_create_file("compressed_size", S_IFREG | 0444, dir,
1472
+ rawdata,
1473
+ &seq_rawdata_compressed_size_fops);
1474
+ if (IS_ERR(dent))
1475
+ goto fail;
1476
+ rawdata->dents[AAFS_LOADDATA_COMPRESSED_SIZE] = dent;
13911477
13921478 dent = aafs_create_file("raw_data", S_IFREG | 0444,
13931479 dir, rawdata, &rawdata_fops);
....@@ -1645,25 +1731,25 @@
16451731 }
16461732
16471733 if (profile->rawdata) {
1648
- dent = aafs_create_symlink("raw_sha1", dir, NULL,
1649
- profile->label.proxy,
1650
- &rawdata_link_sha1_iops);
1734
+ dent = aafs_create("raw_sha1", S_IFLNK | 0444, dir,
1735
+ profile->label.proxy, NULL, NULL,
1736
+ &rawdata_link_sha1_iops);
16511737 if (IS_ERR(dent))
16521738 goto fail;
16531739 aa_get_proxy(profile->label.proxy);
16541740 profile->dents[AAFS_PROF_RAW_HASH] = dent;
16551741
1656
- dent = aafs_create_symlink("raw_abi", dir, NULL,
1657
- profile->label.proxy,
1658
- &rawdata_link_abi_iops);
1742
+ dent = aafs_create("raw_abi", S_IFLNK | 0444, dir,
1743
+ profile->label.proxy, NULL, NULL,
1744
+ &rawdata_link_abi_iops);
16591745 if (IS_ERR(dent))
16601746 goto fail;
16611747 aa_get_proxy(profile->label.proxy);
16621748 profile->dents[AAFS_PROF_RAW_ABI] = dent;
16631749
1664
- dent = aafs_create_symlink("raw_data", dir, NULL,
1665
- profile->label.proxy,
1666
- &rawdata_link_data_iops);
1750
+ dent = aafs_create("raw_data", S_IFLNK | 0444, dir,
1751
+ profile->label.proxy, NULL, NULL,
1752
+ &rawdata_link_data_iops);
16671753 if (IS_ERR(dent))
16681754 goto fail;
16691755 aa_get_proxy(profile->label.proxy);
....@@ -1749,7 +1835,7 @@
17491835 if (error)
17501836 return error;
17511837
1752
- parent = aa_get_ns(dir->i_private);
1838
+ parent = aa_get_ns(dir->i_private);
17531839 /* rmdir calls the generic securityfs functions to remove files
17541840 * from the apparmor dir. It is up to the apparmor ns locking
17551841 * to avoid races.
....@@ -1959,6 +2045,9 @@
19592045
19602046 return error;
19612047 }
2048
+
2049
+
2050
+#define list_entry_is_head(pos, head, member) (&pos->member == (head))
19622051
19632052 /**
19642053 * __next_ns - find the next namespace to list
....@@ -2243,6 +2332,8 @@
22432332 static struct aa_sfs_entry aa_sfs_entry_policy[] = {
22442333 AA_SFS_DIR("versions", aa_sfs_entry_versions),
22452334 AA_SFS_FILE_BOOLEAN("set_load", 1),
2335
+ /* number of out of band transitions supported */
2336
+ AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED),
22462337 { }
22472338 };
22482339
....@@ -2453,16 +2544,18 @@
24532544 {
24542545 struct aa_ns *ns;
24552546 struct path path;
2547
+ int error;
24562548
24572549 if (!dentry)
24582550 return ERR_PTR(-ECHILD);
2551
+
24592552 ns = aa_get_current_ns();
24602553 path.mnt = mntget(aafs_mnt);
24612554 path.dentry = dget(ns_dir(ns));
2462
- nd_jump_link(&path);
2555
+ error = nd_jump_link(&path);
24632556 aa_put_ns(ns);
24642557
2465
- return NULL;
2558
+ return ERR_PTR(error);
24662559 }
24672560
24682561 static int policy_readlink(struct dentry *dentry, char __user *buffer,