mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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. Signed-off-by: John Johansen <john.johansen@canonical.com> Reviewed-by: Seth Arnold <seth.arnold@canonical.com> Reviewed-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
		
							parent
							
								
									64c8697045
								
							
						
					
					
						commit
						a481f4d917
					
				
					 2 changed files with 338 additions and 17 deletions
				
			
		| 
						 | 
					@ -80,6 +80,8 @@
 | 
				
			||||||
#define BTRFS_TEST_MAGIC	0x73727279
 | 
					#define BTRFS_TEST_MAGIC	0x73727279
 | 
				
			||||||
#define NSFS_MAGIC		0x6e736673
 | 
					#define NSFS_MAGIC		0x6e736673
 | 
				
			||||||
#define BPF_FS_MAGIC		0xcafe4a11
 | 
					#define BPF_FS_MAGIC		0xcafe4a11
 | 
				
			||||||
 | 
					#define AAFS_MAGIC		0x5a3c69f0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Since UDF 2.01 is ISO 13346 based... */
 | 
					/* Since UDF 2.01 is ISO 13346 based... */
 | 
				
			||||||
#define UDF_SUPER_MAGIC		0x15013346
 | 
					#define UDF_SUPER_MAGIC		0x15013346
 | 
				
			||||||
#define BALLOON_KVM_MAGIC	0x13661366
 | 
					#define BALLOON_KVM_MAGIC	0x13661366
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,8 +22,9 @@
 | 
				
			||||||
#include <linux/namei.h>
 | 
					#include <linux/namei.h>
 | 
				
			||||||
#include <linux/capability.h>
 | 
					#include <linux/capability.h>
 | 
				
			||||||
#include <linux/rcupdate.h>
 | 
					#include <linux/rcupdate.h>
 | 
				
			||||||
#include <uapi/linux/major.h>
 | 
					 | 
				
			||||||
#include <linux/fs.h>
 | 
					#include <linux/fs.h>
 | 
				
			||||||
 | 
					#include <uapi/linux/major.h>
 | 
				
			||||||
 | 
					#include <uapi/linux/magic.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "include/apparmor.h"
 | 
					#include "include/apparmor.h"
 | 
				
			||||||
#include "include/apparmorfs.h"
 | 
					#include "include/apparmorfs.h"
 | 
				
			||||||
| 
						 | 
					@ -74,6 +75,265 @@ static int mangle_name(const char *name, char *target)
 | 
				
			||||||
	return t - target;
 | 
						return t - target;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * aafs - core fns and data for the policy tree
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define AAFS_NAME		"apparmorfs"
 | 
				
			||||||
 | 
					static struct vfsmount *aafs_mnt;
 | 
				
			||||||
 | 
					static int aafs_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int aafs_show_path(struct seq_file *seq, struct dentry *dentry)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct inode *inode = d_inode(dentry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						seq_printf(seq, "%s:[%lu]", AAFS_NAME, inode->i_ino);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void aafs_evict_inode(struct inode *inode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						truncate_inode_pages_final(&inode->i_data);
 | 
				
			||||||
 | 
						clear_inode(inode);
 | 
				
			||||||
 | 
						if (S_ISLNK(inode->i_mode))
 | 
				
			||||||
 | 
							kfree(inode->i_link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct super_operations aafs_super_ops = {
 | 
				
			||||||
 | 
						.statfs = simple_statfs,
 | 
				
			||||||
 | 
						.evict_inode = aafs_evict_inode,
 | 
				
			||||||
 | 
						.show_path = aafs_show_path,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int fill_super(struct super_block *sb, void *data, int silent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static struct tree_descr files[] = { {""} };
 | 
				
			||||||
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						error = simple_fill_super(sb, AAFS_MAGIC, files);
 | 
				
			||||||
 | 
						if (error)
 | 
				
			||||||
 | 
							return error;
 | 
				
			||||||
 | 
						sb->s_op = &aafs_super_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct dentry *aafs_mount(struct file_system_type *fs_type,
 | 
				
			||||||
 | 
									 int flags, const char *dev_name, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return mount_single(fs_type, flags, data, fill_super);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct file_system_type aafs_ops = {
 | 
				
			||||||
 | 
						.owner = THIS_MODULE,
 | 
				
			||||||
 | 
						.name = AAFS_NAME,
 | 
				
			||||||
 | 
						.mount = aafs_mount,
 | 
				
			||||||
 | 
						.kill_sb = kill_anon_super,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * __aafs_setup_d_inode - basic inode setup for apparmorfs
 | 
				
			||||||
 | 
					 * @dir: parent directory for the dentry
 | 
				
			||||||
 | 
					 * @dentry: dentry we are seting the inode up for
 | 
				
			||||||
 | 
					 * @mode: permissions the file should have
 | 
				
			||||||
 | 
					 * @data: data to store on inode.i_private, available in open()
 | 
				
			||||||
 | 
					 * @link: if symlink, symlink target string
 | 
				
			||||||
 | 
					 * @fops: struct file_operations that should be used
 | 
				
			||||||
 | 
					 * @iops: struct of inode_operations that should be used
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int __aafs_setup_d_inode(struct inode *dir, struct dentry *dentry,
 | 
				
			||||||
 | 
								       umode_t mode, void *data, char *link,
 | 
				
			||||||
 | 
								       const struct file_operations *fops,
 | 
				
			||||||
 | 
								       const struct inode_operations *iops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct inode *inode = new_inode(dir->i_sb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AA_BUG(!dir);
 | 
				
			||||||
 | 
						AA_BUG(!dentry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!inode)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inode->i_ino = get_next_ino();
 | 
				
			||||||
 | 
						inode->i_mode = mode;
 | 
				
			||||||
 | 
						inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
 | 
				
			||||||
 | 
						inode->i_private = data;
 | 
				
			||||||
 | 
						if (S_ISDIR(mode)) {
 | 
				
			||||||
 | 
							inode->i_op = iops ? iops : &simple_dir_inode_operations;
 | 
				
			||||||
 | 
							inode->i_fop = &simple_dir_operations;
 | 
				
			||||||
 | 
							inc_nlink(inode);
 | 
				
			||||||
 | 
							inc_nlink(dir);
 | 
				
			||||||
 | 
						} else if (S_ISLNK(mode)) {
 | 
				
			||||||
 | 
							inode->i_op = iops ? iops : &simple_symlink_inode_operations;
 | 
				
			||||||
 | 
							inode->i_link = link;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							inode->i_fop = fops;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						d_instantiate(dentry, inode);
 | 
				
			||||||
 | 
						dget(dentry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * aafs_create - create a dentry in the apparmorfs filesystem
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @name: name of dentry to create
 | 
				
			||||||
 | 
					 * @mode: permissions the file should have
 | 
				
			||||||
 | 
					 * @parent: parent directory for this dentry
 | 
				
			||||||
 | 
					 * @data: data to store on inode.i_private, available in open()
 | 
				
			||||||
 | 
					 * @link: if symlink, symlink target string
 | 
				
			||||||
 | 
					 * @fops: struct file_operations that should be used for
 | 
				
			||||||
 | 
					 * @iops: struct of inode_operations that should be used
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This is the basic "create a xxx" function for apparmorfs.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns a pointer to a dentry if it succeeds, that must be free with
 | 
				
			||||||
 | 
					 * aafs_remove(). Will return ERR_PTR on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static struct dentry *aafs_create(const char *name, umode_t mode,
 | 
				
			||||||
 | 
									  struct dentry *parent, void *data, void *link,
 | 
				
			||||||
 | 
									  const struct file_operations *fops,
 | 
				
			||||||
 | 
									  const struct inode_operations *iops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dentry *dentry;
 | 
				
			||||||
 | 
						struct inode *dir;
 | 
				
			||||||
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AA_BUG(!name);
 | 
				
			||||||
 | 
						AA_BUG(!parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(mode & S_IFMT))
 | 
				
			||||||
 | 
							mode = (mode & S_IALLUGO) | S_IFREG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count);
 | 
				
			||||||
 | 
						if (error)
 | 
				
			||||||
 | 
							return ERR_PTR(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dir = d_inode(parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inode_lock(dir);
 | 
				
			||||||
 | 
						dentry = lookup_one_len(name, parent, strlen(name));
 | 
				
			||||||
 | 
						if (IS_ERR(dentry))
 | 
				
			||||||
 | 
							goto fail_lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (d_really_is_positive(dentry)) {
 | 
				
			||||||
 | 
							error = -EEXIST;
 | 
				
			||||||
 | 
							goto fail_dentry;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						error = __aafs_setup_d_inode(dir, dentry, mode, data, link, fops, iops);
 | 
				
			||||||
 | 
						if (error)
 | 
				
			||||||
 | 
							goto fail_dentry;
 | 
				
			||||||
 | 
						inode_unlock(dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dentry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fail_dentry:
 | 
				
			||||||
 | 
						dput(dentry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fail_lock:
 | 
				
			||||||
 | 
						inode_unlock(dir);
 | 
				
			||||||
 | 
						simple_release_fs(&aafs_mnt, &aafs_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ERR_PTR(error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * aafs_create_file - create a file in the apparmorfs filesystem
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @name: name of dentry to create
 | 
				
			||||||
 | 
					 * @mode: permissions the file should have
 | 
				
			||||||
 | 
					 * @parent: parent directory for this dentry
 | 
				
			||||||
 | 
					 * @data: data to store on inode.i_private, available in open()
 | 
				
			||||||
 | 
					 * @fops: struct file_operations that should be used for
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * see aafs_create
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static struct dentry *aafs_create_file(const char *name, umode_t mode,
 | 
				
			||||||
 | 
									       struct dentry *parent, void *data,
 | 
				
			||||||
 | 
									       const struct file_operations *fops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return aafs_create(name, mode, parent, data, NULL, fops, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * aafs_create_dir - create a directory in the apparmorfs filesystem
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @name: name of dentry to create
 | 
				
			||||||
 | 
					 * @parent: parent directory for this dentry
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * see aafs_create
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static struct dentry *aafs_create_dir(const char *name, struct dentry *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return aafs_create(name, S_IFDIR | 0755, parent, NULL, NULL, NULL,
 | 
				
			||||||
 | 
								   NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * aafs_create_symlink - create a symlink in the apparmorfs filesystem
 | 
				
			||||||
 | 
					 * @name: name of dentry to create
 | 
				
			||||||
 | 
					 * @parent: parent directory for this dentry
 | 
				
			||||||
 | 
					 * @target: if symlink, symlink target string
 | 
				
			||||||
 | 
					 * @iops: struct of inode_operations that should be used
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If @target parameter is %NULL, then the @iops parameter needs to be
 | 
				
			||||||
 | 
					 * setup to handle .readlink and .get_link inode_operations.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static struct dentry *aafs_create_symlink(const char *name,
 | 
				
			||||||
 | 
										  struct dentry *parent,
 | 
				
			||||||
 | 
										  const char *target,
 | 
				
			||||||
 | 
										  const struct inode_operations *iops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dentry *dent;
 | 
				
			||||||
 | 
						char *link = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (target) {
 | 
				
			||||||
 | 
							link = kstrdup(target, GFP_KERNEL);
 | 
				
			||||||
 | 
							if (!link)
 | 
				
			||||||
 | 
								return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dent = aafs_create(name, S_IFLNK | 0444, parent, NULL, link, NULL,
 | 
				
			||||||
 | 
								   iops);
 | 
				
			||||||
 | 
						if (IS_ERR(dent))
 | 
				
			||||||
 | 
							kfree(link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * aafs_remove - removes a file or directory from the apparmorfs filesystem
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @dentry: dentry of the file/directory/symlink to removed.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void aafs_remove(struct dentry *dentry)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct inode *dir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!dentry || IS_ERR(dentry))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dir = d_inode(dentry->d_parent);
 | 
				
			||||||
 | 
						inode_lock(dir);
 | 
				
			||||||
 | 
						if (simple_positive(dentry)) {
 | 
				
			||||||
 | 
							if (d_is_dir(dentry))
 | 
				
			||||||
 | 
								simple_rmdir(dir, dentry);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								simple_unlink(dir, dentry);
 | 
				
			||||||
 | 
							dput(dentry);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inode_unlock(dir);
 | 
				
			||||||
 | 
						simple_release_fs(&aafs_mnt, &aafs_count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * aa_fs - policy load/replace/remove
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * aa_simple_write_to_buffer - common routine for getting policy from user
 | 
					 * aa_simple_write_to_buffer - common routine for getting policy from user
 | 
				
			||||||
 * @userbuf: user buffer to copy data from  (NOT NULL)
 | 
					 * @userbuf: user buffer to copy data from  (NOT NULL)
 | 
				
			||||||
| 
						 | 
					@ -1369,14 +1629,14 @@ static struct aa_fs_entry aa_fs_entry =
 | 
				
			||||||
	AA_FS_DIR("apparmor", aa_fs_entry_apparmor);
 | 
						AA_FS_DIR("apparmor", aa_fs_entry_apparmor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * aafs_create_file - create a file entry in the apparmor securityfs
 | 
					 * entry_create_file - create a file entry in the apparmor securityfs
 | 
				
			||||||
 * @fs_file: aa_fs_entry to build an entry for (NOT NULL)
 | 
					 * @fs_file: aa_fs_entry to build an entry for (NOT NULL)
 | 
				
			||||||
 * @parent: the parent dentry in the securityfs
 | 
					 * @parent: the parent dentry in the securityfs
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Use aafs_remove_file to remove entries created with this fn.
 | 
					 * Use entry_remove_file to remove entries created with this fn.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int __init aafs_create_file(struct aa_fs_entry *fs_file,
 | 
					static int __init entry_create_file(struct aa_fs_entry *fs_file,
 | 
				
			||||||
				   struct dentry *parent)
 | 
									    struct dentry *parent)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int error = 0;
 | 
						int error = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1391,15 +1651,15 @@ static int __init aafs_create_file(struct aa_fs_entry *fs_file,
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir);
 | 
					static void __init entry_remove_dir(struct aa_fs_entry *fs_dir);
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * aafs_create_dir - recursively create a directory entry in the securityfs
 | 
					 * entry_create_dir - recursively create a directory entry in the securityfs
 | 
				
			||||||
 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
 | 
					 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
 | 
				
			||||||
 * @parent: the parent dentry in the securityfs
 | 
					 * @parent: the parent dentry in the securityfs
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Use aafs_remove_dir to remove entries created with this fn.
 | 
					 * Use entry_remove_dir to remove entries created with this fn.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
 | 
					static int __init entry_create_dir(struct aa_fs_entry *fs_dir,
 | 
				
			||||||
				  struct dentry *parent)
 | 
									  struct dentry *parent)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct aa_fs_entry *fs_file;
 | 
						struct aa_fs_entry *fs_file;
 | 
				
			||||||
| 
						 | 
					@ -1413,9 +1673,9 @@ static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
 | 
						for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
 | 
				
			||||||
		if (fs_file->v_type == AA_FS_TYPE_DIR)
 | 
							if (fs_file->v_type == AA_FS_TYPE_DIR)
 | 
				
			||||||
			error = aafs_create_dir(fs_file, fs_dir->dentry);
 | 
								error = entry_create_dir(fs_file, fs_dir->dentry);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			error = aafs_create_file(fs_file, fs_dir->dentry);
 | 
								error = entry_create_file(fs_file, fs_dir->dentry);
 | 
				
			||||||
		if (error)
 | 
							if (error)
 | 
				
			||||||
			goto failed;
 | 
								goto failed;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1423,7 +1683,7 @@ static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
failed:
 | 
					failed:
 | 
				
			||||||
	aafs_remove_dir(fs_dir);
 | 
						entry_remove_dir(fs_dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1442,16 +1702,16 @@ static void __init aafs_remove_file(struct aa_fs_entry *fs_file)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * aafs_remove_dir - recursively drop a directory entry from the securityfs
 | 
					 * entry_remove_dir - recursively drop a directory entry from the securityfs
 | 
				
			||||||
 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL)
 | 
					 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)
 | 
					static void __init entry_remove_dir(struct aa_fs_entry *fs_dir)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct aa_fs_entry *fs_file;
 | 
						struct aa_fs_entry *fs_file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
 | 
						for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
 | 
				
			||||||
		if (fs_file->v_type == AA_FS_TYPE_DIR)
 | 
							if (fs_file->v_type == AA_FS_TYPE_DIR)
 | 
				
			||||||
			aafs_remove_dir(fs_file);
 | 
								entry_remove_dir(fs_file);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			aafs_remove_file(fs_file);
 | 
								aafs_remove_file(fs_file);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1466,7 +1726,7 @@ static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void __init aa_destroy_aafs(void)
 | 
					void __init aa_destroy_aafs(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	aafs_remove_dir(&aa_fs_entry);
 | 
						entry_remove_dir(&aa_fs_entry);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1515,6 +1775,59 @@ static int aa_mk_null_file(struct dentry *parent)
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *policy_get_link(struct dentry *dentry,
 | 
				
			||||||
 | 
									   struct inode *inode,
 | 
				
			||||||
 | 
									   struct delayed_call *done)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct aa_ns *ns;
 | 
				
			||||||
 | 
						struct path path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!dentry)
 | 
				
			||||||
 | 
							return ERR_PTR(-ECHILD);
 | 
				
			||||||
 | 
						ns = aa_get_current_ns();
 | 
				
			||||||
 | 
						path.mnt = mntget(aafs_mnt);
 | 
				
			||||||
 | 
						path.dentry = dget(ns_dir(ns));
 | 
				
			||||||
 | 
						nd_jump_link(&path);
 | 
				
			||||||
 | 
						aa_put_ns(ns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ns_get_name(char *buf, size_t size, struct aa_ns *ns,
 | 
				
			||||||
 | 
							       struct inode *inode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int res = snprintf(buf, size, "%s:[%lu]", AAFS_NAME, inode->i_ino);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (res < 0 || res >= size)
 | 
				
			||||||
 | 
							res = -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int policy_readlink(struct dentry *dentry, char __user *buffer,
 | 
				
			||||||
 | 
								   int buflen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct aa_ns *ns;
 | 
				
			||||||
 | 
						char name[32];
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ns = aa_get_current_ns();
 | 
				
			||||||
 | 
						res = ns_get_name(name, sizeof(name), ns, d_inode(dentry));
 | 
				
			||||||
 | 
						if (res >= 0)
 | 
				
			||||||
 | 
							res = readlink_copy(buffer, buflen, name);
 | 
				
			||||||
 | 
						aa_put_ns(ns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct inode_operations policy_link_iops = {
 | 
				
			||||||
 | 
						.readlink	= policy_readlink,
 | 
				
			||||||
 | 
						.get_link	= policy_get_link,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * aa_create_aafs - create the apparmor security filesystem
 | 
					 * aa_create_aafs - create the apparmor security filesystem
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -1535,8 +1848,14 @@ static int __init aa_create_aafs(void)
 | 
				
			||||||
		return -EEXIST;
 | 
							return -EEXIST;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* setup apparmorfs used to virtualize policy/ */
 | 
				
			||||||
 | 
						aafs_mnt = kern_mount(&aafs_ops);
 | 
				
			||||||
 | 
						if (IS_ERR(aafs_mnt))
 | 
				
			||||||
 | 
							panic("can't set apparmorfs up\n");
 | 
				
			||||||
 | 
						aafs_mnt->mnt_sb->s_flags &= ~MS_NOUSER;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Populate fs tree. */
 | 
						/* Populate fs tree. */
 | 
				
			||||||
	error = aafs_create_dir(&aa_fs_entry, NULL);
 | 
						error = entry_create_dir(&aa_fs_entry, NULL);
 | 
				
			||||||
	if (error)
 | 
						if (error)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue