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
8080 #define BTRFS_TEST_MAGIC 0x73727279
8181 #define NSFS_MAGIC 0x6e736673
8282 #define BPF_FS_MAGIC 0xcafe4a11
83+#define AAFS_MAGIC 0x5a3c69f0
84+
8385 /* Since UDF 2.01 is ISO 13346 based... */
8486 #define UDF_SUPER_MAGIC 0x15013346
8587 #define BALLOON_KVM_MAGIC 0x13661366
security/apparmor/apparmorfs.c+336−17
@@ -22,8 +22,9 @@ · 21 unmodified lines
2222 #include <linux/namei.h>
2323 #include <linux/capability.h>
2424 #include <linux/rcupdate.h>
25−#include <uapi/linux/major.h>
2625 #include <linux/fs.h>
26+#include <uapi/linux/major.h>
27+#include <uapi/linux/magic.h>
2728
2829 #include "include/apparmor.h"
2930 #include "include/apparmorfs.h"
@@ -74,6 +75,265 @@ static int mangle_name(const char *name, char *target) · 44 unmodified lines
7475 return t - target;
7576 }
7677
78+
79+/*
80+ * aafs - core fns and data for the policy tree
81+ */
82+
83+#define AAFS_NAME "apparmorfs"
84+static struct vfsmount *aafs_mnt;
85+static int aafs_count;
86+
87+
88+static 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+
96+static 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+
104+static 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+
110+static 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+
123+static 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+
129+static 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+ */
146+static 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+ */
196+static 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+
234+fail_dentry:
235+ dput(dentry);
236+
237+fail_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+ */
255+static 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+ */
270+static 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+ */
286+static 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+ */
312+static 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+
77337 /**
78338 * aa_simple_write_to_buffer - common routine for getting policy from user
79339 * @userbuf: user buffer to copy data from (NOT NULL)
@@ -1369,14 +1629,14 @@ static struct aa_fs_entry aa_fs_entry = · 1289 unmodified lines
13691629 AA_FS_DIR("apparmor", aa_fs_entry_apparmor);
13701630
13711631 /**
1372− * aafs_create_file - create a file entry in the apparmor securityfs
1632+ * entry_create_file - create a file entry in the apparmor securityfs
13731633 * @fs_file: aa_fs_entry to build an entry for (NOT NULL)
13741634 * @parent: the parent dentry in the securityfs
13751635 *
1376− * Use aafs_remove_file to remove entries created with this fn.
1636+ * Use entry_remove_file to remove entries created with this fn.
13771637 */
1378−static int __init aafs_create_file(struct aa_fs_entry *fs_file,
1379− struct dentry *parent)
1638+static int __init entry_create_file(struct aa_fs_entry *fs_file,
1639+ struct dentry *parent)
13801640 {
13811641 int error = 0;
13821642
@@ -1391,15 +1651,15 @@ static int __init aafs_create_file(struct aa_fs_entry *fs_file, · 8 unmodified lines
13911651 return error;
13921652 }
13931653
1394−static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir);
1654+static void __init entry_remove_dir(struct aa_fs_entry *fs_dir);
13951655 /**
1396− * aafs_create_dir - recursively create a directory entry in the securityfs
1656+ * entry_create_dir - recursively create a directory entry in the securityfs
13971657 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
13981658 * @parent: the parent dentry in the securityfs
13991659 *
1400− * Use aafs_remove_dir to remove entries created with this fn.
1660+ * Use entry_remove_dir to remove entries created with this fn.
14011661 */
1402−static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
1662+static int __init entry_create_dir(struct aa_fs_entry *fs_dir,
14031663 struct dentry *parent)
14041664 {
14051665 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
14131673
14141674 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
14151675 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);
14171677 else
1418− error = aafs_create_file(fs_file, fs_dir->dentry);
1678+ error = entry_create_file(fs_file, fs_dir->dentry);
14191679 if (error)
14201680 goto failed;
14211681 }
@@ -1423,7 +1683,7 @@ static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, · 1 unmodified line
14231683 return 0;
14241684
14251685 failed:
1426− aafs_remove_dir(fs_dir);
1686+ entry_remove_dir(fs_dir);
14271687
14281688 return error;
14291689 }
@@ -1442,16 +1702,16 @@ static void __init aafs_remove_file(struct aa_fs_entry *fs_file) · 12 unmodified lines
14421702 }
14431703
14441704 /**
1445− * aafs_remove_dir - recursively drop a directory entry from the securityfs
1705+ * entry_remove_dir - recursively drop a directory entry from the securityfs
14461706 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL)
14471707 */
1448−static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)
1708+static void __init entry_remove_dir(struct aa_fs_entry *fs_dir)
14491709 {
14501710 struct aa_fs_entry *fs_file;
14511711
14521712 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
14531713 if (fs_file->v_type == AA_FS_TYPE_DIR)
1454− aafs_remove_dir(fs_file);
1714+ entry_remove_dir(fs_file);
14551715 else
14561716 aafs_remove_file(fs_file);
14571717 }
@@ -1466,7 +1726,7 @@ static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir) · 8 unmodified lines
14661726 */
14671727 void __init aa_destroy_aafs(void)
14681728 {
1469− aafs_remove_dir(&aa_fs_entry);
1729+ entry_remove_dir(&aa_fs_entry);
14701730 }
14711731
14721732
@@ -1515,6 +1775,59 @@ out: · 42 unmodified lines
15151775 return error;
15161776 }
15171777
1778+
1779+
1780+static 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+
1798+static 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+
1809+static 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+
1825+static const struct inode_operations policy_link_iops = {
1826+ .readlink = policy_readlink,
1827+ .get_link = policy_get_link,
1828+};
1829+
1830+
15181831 /**
15191832 * aa_create_aafs - create the apparmor security filesystem
15201833 *
@@ -1535,8 +1848,14 @@ static int __init aa_create_aafs(void) · 14 unmodified lines
15351848 return -EEXIST;
15361849 }
15371850
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+
15381857 /* Populate fs tree. */
1539− error = aafs_create_dir(&aa_fs_entry, NULL);
1858+ error = entry_create_dir(&aa_fs_entry, NULL);
15401859 if (error)
15411860 goto error;
15421861

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