History

apparmor: add custom apparmorfs that will be used by policy namespace files

AppArmor policy needs to be able to be resolved based on the policy namespace a task is confined by. Add a base apparmorfs filesystem that (like nsfs) will exist as a kern mount and be accessed via jump_link through a securityfs file. Setup the base apparmorfs fns and data, but don't use it yet.

John Johansen committed 9 years ago

Commit a481f4d1 parent 64c86972 files · +338 −17Browse files

Unified · Split

2 files
  1. include/uapi/linux/magic.h +2 −0
  2. security/apparmor/apparmorfs.c +336 −17
include/uapi/linux/magic.h+2−0
@@ -80,6 +80,8 @@ · 79 unmodified lines
80#define BTRFS_TEST_MAGIC 0x7372727980#define BTRFS_TEST_MAGIC 0x73727279
81#define NSFS_MAGIC 0x6e73667381#define NSFS_MAGIC 0x6e736673
82#define BPF_FS_MAGIC 0xcafe4a1182#define BPF_FS_MAGIC 0xcafe4a11
83#define AAFS_MAGIC 0x5a3c69f0
84
83/* Since UDF 2.01 is ISO 13346 based... */85/* Since UDF 2.01 is ISO 13346 based... */
84#define UDF_SUPER_MAGIC 0x1501334686#define UDF_SUPER_MAGIC 0x15013346
85#define BALLOON_KVM_MAGIC 0x1366136687#define BALLOON_KVM_MAGIC 0x13661366
security/apparmor/apparmorfs.c+336−17
@@ -22,8 +22,9 @@ · 21 unmodified lines
22#include <linux/namei.h>22#include <linux/namei.h>
23#include <linux/capability.h>23#include <linux/capability.h>
24#include <linux/rcupdate.h>24#include <linux/rcupdate.h>
25#include <uapi/linux/major.h>
26#include <linux/fs.h>25#include <linux/fs.h>
26#include <uapi/linux/major.h>
27#include <uapi/linux/magic.h>
27 28
28#include "include/apparmor.h"29#include "include/apparmor.h"
29#include "include/apparmorfs.h"30#include "include/apparmorfs.h"
@@ -74,6 +75,265 @@ static int mangle_name(const char *name, char *target) · 44 unmodified lines
74 return t - target;75 return t - target;
75}76}
76 77
78
79/*
80 * aafs - core fns and data for the policy tree
81 */
82
83#define AAFS_NAME "apparmorfs"
84static struct vfsmount *aafs_mnt;
85static int aafs_count;
86
87
88static int aafs_show_path(struct seq_file *seq, struct dentry *dentry)
89{
90 struct inode *inode = d_inode(dentry);
91
92 seq_printf(seq, "%s:[%lu]", AAFS_NAME, inode->i_ino);
93 return 0;
94}
95
96static void aafs_evict_inode(struct inode *inode)
97{
98 truncate_inode_pages_final(&inode->i_data);
99 clear_inode(inode);
100 if (S_ISLNK(inode->i_mode))
101 kfree(inode->i_link);
102}
103
104static const struct super_operations aafs_super_ops = {
105 .statfs = simple_statfs,
106 .evict_inode = aafs_evict_inode,
107 .show_path = aafs_show_path,
108};
109
110static int fill_super(struct super_block *sb, void *data, int silent)
111{
112 static struct tree_descr files[] = { {""} };
113 int error;
114
115 error = simple_fill_super(sb, AAFS_MAGIC, files);
116 if (error)
117 return error;
118 sb->s_op = &aafs_super_ops;
119
120 return 0;
121}
122
123static struct dentry *aafs_mount(struct file_system_type *fs_type,
124 int flags, const char *dev_name, void *data)
125{
126 return mount_single(fs_type, flags, data, fill_super);
127}
128
129static struct file_system_type aafs_ops = {
130 .owner = THIS_MODULE,
131 .name = AAFS_NAME,
132 .mount = aafs_mount,
133 .kill_sb = kill_anon_super,
134};
135
136/**
137 * __aafs_setup_d_inode - basic inode setup for apparmorfs
138 * @dir: parent directory for the dentry
139 * @dentry: dentry we are seting the inode up for
140 * @mode: permissions the file should have
141 * @data: data to store on inode.i_private, available in open()
142 * @link: if symlink, symlink target string
143 * @fops: struct file_operations that should be used
144 * @iops: struct of inode_operations that should be used
145 */
146static int __aafs_setup_d_inode(struct inode *dir, struct dentry *dentry,
147 umode_t mode, void *data, char *link,
148 const struct file_operations *fops,
149 const struct inode_operations *iops)
150{
151 struct inode *inode = new_inode(dir->i_sb);
152
153 AA_BUG(!dir);
154 AA_BUG(!dentry);
155
156 if (!inode)
157 return -ENOMEM;
158
159 inode->i_ino = get_next_ino();
160 inode->i_mode = mode;
161 inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
162 inode->i_private = data;
163 if (S_ISDIR(mode)) {
164 inode->i_op = iops ? iops : &simple_dir_inode_operations;
165 inode->i_fop = &simple_dir_operations;
166 inc_nlink(inode);
167 inc_nlink(dir);
168 } else if (S_ISLNK(mode)) {
169 inode->i_op = iops ? iops : &simple_symlink_inode_operations;
170 inode->i_link = link;
171 } else {
172 inode->i_fop = fops;
173 }
174 d_instantiate(dentry, inode);
175 dget(dentry);
176
177 return 0;
178}
179
180/**
181 * aafs_create - create a dentry in the apparmorfs filesystem
182 *
183 * @name: name of dentry to create
184 * @mode: permissions the file should have
185 * @parent: parent directory for this dentry
186 * @data: data to store on inode.i_private, available in open()
187 * @link: if symlink, symlink target string
188 * @fops: struct file_operations that should be used for
189 * @iops: struct of inode_operations that should be used
190 *
191 * This is the basic "create a xxx" function for apparmorfs.
192 *
193 * Returns a pointer to a dentry if it succeeds, that must be free with
194 * aafs_remove(). Will return ERR_PTR on failure.
195 */
196static struct dentry *aafs_create(const char *name, umode_t mode,
197 struct dentry *parent, void *data, void *link,
198 const struct file_operations *fops,
199 const struct inode_operations *iops)
200{
201 struct dentry *dentry;
202 struct inode *dir;
203 int error;
204
205 AA_BUG(!name);
206 AA_BUG(!parent);
207
208 if (!(mode & S_IFMT))
209 mode = (mode & S_IALLUGO) | S_IFREG;
210
211 error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count);
212 if (error)
213 return ERR_PTR(error);
214
215 dir = d_inode(parent);
216
217 inode_lock(dir);
218 dentry = lookup_one_len(name, parent, strlen(name));
219 if (IS_ERR(dentry))
220 goto fail_lock;
221
222 if (d_really_is_positive(dentry)) {
223 error = -EEXIST;
224 goto fail_dentry;
225 }
226
227 error = __aafs_setup_d_inode(dir, dentry, mode, data, link, fops, iops);
228 if (error)
229 goto fail_dentry;
230 inode_unlock(dir);
231
232 return dentry;
233
234fail_dentry:
235 dput(dentry);
236
237fail_lock:
238 inode_unlock(dir);
239 simple_release_fs(&aafs_mnt, &aafs_count);
240
241 return ERR_PTR(error);
242}
243
244/**
245 * aafs_create_file - create a file in the apparmorfs filesystem
246 *
247 * @name: name of dentry to create
248 * @mode: permissions the file should have
249 * @parent: parent directory for this dentry
250 * @data: data to store on inode.i_private, available in open()
251 * @fops: struct file_operations that should be used for
252 *
253 * see aafs_create
254 */
255static struct dentry *aafs_create_file(const char *name, umode_t mode,
256 struct dentry *parent, void *data,
257 const struct file_operations *fops)
258{
259 return aafs_create(name, mode, parent, data, NULL, fops, NULL);
260}
261
262/**
263 * aafs_create_dir - create a directory in the apparmorfs filesystem
264 *
265 * @name: name of dentry to create
266 * @parent: parent directory for this dentry
267 *
268 * see aafs_create
269 */
270static struct dentry *aafs_create_dir(const char *name, struct dentry *parent)
271{
272 return aafs_create(name, S_IFDIR | 0755, parent, NULL, NULL, NULL,
273 NULL);
274}
275
276/**
277 * aafs_create_symlink - create a symlink in the apparmorfs filesystem
278 * @name: name of dentry to create
279 * @parent: parent directory for this dentry
280 * @target: if symlink, symlink target string
281 * @iops: struct of inode_operations that should be used
282 *
283 * If @target parameter is %NULL, then the @iops parameter needs to be
284 * setup to handle .readlink and .get_link inode_operations.
285 */
286static struct dentry *aafs_create_symlink(const char *name,
287 struct dentry *parent,
288 const char *target,
289 const struct inode_operations *iops)
290{
291 struct dentry *dent;
292 char *link = NULL;
293
294 if (target) {
295 link = kstrdup(target, GFP_KERNEL);
296 if (!link)
297 return ERR_PTR(-ENOMEM);
298 }
299 dent = aafs_create(name, S_IFLNK | 0444, parent, NULL, link, NULL,
300 iops);
301 if (IS_ERR(dent))
302 kfree(link);
303
304 return dent;
305}
306
307/**
308 * aafs_remove - removes a file or directory from the apparmorfs filesystem
309 *
310 * @dentry: dentry of the file/directory/symlink to removed.
311 */
312static void aafs_remove(struct dentry *dentry)
313{
314 struct inode *dir;
315
316 if (!dentry || IS_ERR(dentry))
317 return;
318
319 dir = d_inode(dentry->d_parent);
320 inode_lock(dir);
321 if (simple_positive(dentry)) {
322 if (d_is_dir(dentry))
323 simple_rmdir(dir, dentry);
324 else
325 simple_unlink(dir, dentry);
326 dput(dentry);
327 }
328 inode_unlock(dir);
329 simple_release_fs(&aafs_mnt, &aafs_count);
330}
331
332
333/*
334 * aa_fs - policy load/replace/remove
335 */
336
77/**337/**
78 * aa_simple_write_to_buffer - common routine for getting policy from user338 * aa_simple_write_to_buffer - common routine for getting policy from user
79 * @userbuf: user buffer to copy data from (NOT NULL)339 * @userbuf: user buffer to copy data from (NOT NULL)
@@ -1369,14 +1629,14 @@ static struct aa_fs_entry aa_fs_entry = · 1289 unmodified lines
1369 AA_FS_DIR("apparmor", aa_fs_entry_apparmor);1629 AA_FS_DIR("apparmor", aa_fs_entry_apparmor);
1370 1630
1371/**1631/**
1372 * aafs_create_file - create a file entry in the apparmor securityfs1632 * entry_create_file - create a file entry in the apparmor securityfs
1373 * @fs_file: aa_fs_entry to build an entry for (NOT NULL)1633 * @fs_file: aa_fs_entry to build an entry for (NOT NULL)
1374 * @parent: the parent dentry in the securityfs1634 * @parent: the parent dentry in the securityfs
1375 *1635 *
1376 * Use aafs_remove_file to remove entries created with this fn.1636 * Use entry_remove_file to remove entries created with this fn.
1377 */1637 */
1378static int __init aafs_create_file(struct aa_fs_entry *fs_file,1638static int __init entry_create_file(struct aa_fs_entry *fs_file,
1379 struct dentry *parent)1639 struct dentry *parent)
1380{1640{
1381 int error = 0;1641 int error = 0;
1382 1642
@@ -1391,15 +1651,15 @@ static int __init aafs_create_file(struct aa_fs_entry *fs_file, · 8 unmodified lines
1391 return error;1651 return error;
1392}1652}
1393 1653
1394static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir);1654static void __init entry_remove_dir(struct aa_fs_entry *fs_dir);
1395/**1655/**
1396 * aafs_create_dir - recursively create a directory entry in the securityfs1656 * entry_create_dir - recursively create a directory entry in the securityfs
1397 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)1657 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
1398 * @parent: the parent dentry in the securityfs1658 * @parent: the parent dentry in the securityfs
1399 *1659 *
1400 * Use aafs_remove_dir to remove entries created with this fn.1660 * Use entry_remove_dir to remove entries created with this fn.
1401 */1661 */
1402static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,1662static int __init entry_create_dir(struct aa_fs_entry *fs_dir,
1403 struct dentry *parent)1663 struct dentry *parent)
1404{1664{
1405 struct aa_fs_entry *fs_file;1665 struct aa_fs_entry *fs_file;
@@ -1413,9 +1673,9 @@ static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, · 7 unmodified lines
1413 1673
1414 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {1674 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
1415 if (fs_file->v_type == AA_FS_TYPE_DIR)1675 if (fs_file->v_type == AA_FS_TYPE_DIR)
1416 error = aafs_create_dir(fs_file, fs_dir->dentry);1676 error = entry_create_dir(fs_file, fs_dir->dentry);
1417 else1677 else
1418 error = aafs_create_file(fs_file, fs_dir->dentry);1678 error = entry_create_file(fs_file, fs_dir->dentry);
1419 if (error)1679 if (error)
1420 goto failed;1680 goto failed;
1421 }1681 }
@@ -1423,7 +1683,7 @@ static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, · 1 unmodified line
1423 return 0;1683 return 0;
1424 1684
1425failed:1685failed:
1426 aafs_remove_dir(fs_dir);1686 entry_remove_dir(fs_dir);
1427 1687
1428 return error;1688 return error;
1429}1689}
@@ -1442,16 +1702,16 @@ static void __init aafs_remove_file(struct aa_fs_entry *fs_file) · 12 unmodified lines
1442}1702}
1443 1703
1444/**1704/**
1445 * aafs_remove_dir - recursively drop a directory entry from the securityfs1705 * entry_remove_dir - recursively drop a directory entry from the securityfs
1446 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL)1706 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL)
1447 */1707 */
1448static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)1708static void __init entry_remove_dir(struct aa_fs_entry *fs_dir)
1449{1709{
1450 struct aa_fs_entry *fs_file;1710 struct aa_fs_entry *fs_file;
1451 1711
1452 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {1712 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
1453 if (fs_file->v_type == AA_FS_TYPE_DIR)1713 if (fs_file->v_type == AA_FS_TYPE_DIR)
1454 aafs_remove_dir(fs_file);1714 entry_remove_dir(fs_file);
1455 else1715 else
1456 aafs_remove_file(fs_file);1716 aafs_remove_file(fs_file);
1457 }1717 }
@@ -1466,7 +1726,7 @@ static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir) · 8 unmodified lines
1466 */1726 */
1467void __init aa_destroy_aafs(void)1727void __init aa_destroy_aafs(void)
1468{1728{
1469 aafs_remove_dir(&aa_fs_entry);1729 entry_remove_dir(&aa_fs_entry);
1470}1730}
1471 1731
1472 1732
@@ -1515,6 +1775,59 @@ out: · 42 unmodified lines
1515 return error;1775 return error;
1516}1776}
1517 1777
1778
1779
1780static const char *policy_get_link(struct dentry *dentry,
1781 struct inode *inode,
1782 struct delayed_call *done)
1783{
1784 struct aa_ns *ns;
1785 struct path path;
1786
1787 if (!dentry)
1788 return ERR_PTR(-ECHILD);
1789 ns = aa_get_current_ns();
1790 path.mnt = mntget(aafs_mnt);
1791 path.dentry = dget(ns_dir(ns));
1792 nd_jump_link(&path);
1793 aa_put_ns(ns);
1794
1795 return NULL;
1796}
1797
1798static int ns_get_name(char *buf, size_t size, struct aa_ns *ns,
1799 struct inode *inode)
1800{
1801 int res = snprintf(buf, size, "%s:[%lu]", AAFS_NAME, inode->i_ino);
1802
1803 if (res < 0 || res >= size)
1804 res = -ENOENT;
1805
1806 return res;
1807}
1808
1809static int policy_readlink(struct dentry *dentry, char __user *buffer,
1810 int buflen)
1811{
1812 struct aa_ns *ns;
1813 char name[32];
1814 int res;
1815
1816 ns = aa_get_current_ns();
1817 res = ns_get_name(name, sizeof(name), ns, d_inode(dentry));
1818 if (res >= 0)
1819 res = readlink_copy(buffer, buflen, name);
1820 aa_put_ns(ns);
1821
1822 return res;
1823}
1824
1825static const struct inode_operations policy_link_iops = {
1826 .readlink = policy_readlink,
1827 .get_link = policy_get_link,
1828};
1829
1830
1518/**1831/**
1519 * aa_create_aafs - create the apparmor security filesystem1832 * aa_create_aafs - create the apparmor security filesystem
1520 *1833 *
@@ -1535,8 +1848,14 @@ static int __init aa_create_aafs(void) · 14 unmodified lines
1535 return -EEXIST;1848 return -EEXIST;
1536 }1849 }
1537 1850
1851 /* setup apparmorfs used to virtualize policy/ */
1852 aafs_mnt = kern_mount(&aafs_ops);
1853 if (IS_ERR(aafs_mnt))
1854 panic("can't set apparmorfs up\n");
1855 aafs_mnt->mnt_sb->s_flags &= ~MS_NOUSER;
1856
1538 /* Populate fs tree. */1857 /* Populate fs tree. */
1539 error = aafs_create_dir(&aa_fs_entry, NULL);1858 error = entry_create_dir(&aa_fs_entry, NULL);
1540 if (error)1859 if (error)
1541 goto error;1860 goto error;
1542 1861

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t