aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor/apparmorfs.c
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2010-07-29 17:48:03 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:35:13 -0400
commit63e2b423771ab0bc7ad4d407f3f6517c6d05cdc0 (patch)
treee50efc9593c7558d3700ec55869f9ddbac283a1d /security/apparmor/apparmorfs.c
parente06f75a6a2b43bd3a7a197bd21466f9da130e4af (diff)
AppArmor: userspace interfaces
The /proc/<pid>/attr/* interface is used for process introspection and commands. While the apparmorfs interface is used for global introspection and loading and removing policy. The interface currently only contains the files necessary for loading policy, and will be extended in the future to include sysfs style single per file introspection inteface. The old AppArmor 2.4 interface files have been removed into a compatibility patch, that distros can use to maintain backwards compatibility. Signed-off-by: John Johansen <john.johansen@canonical.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/apparmor/apparmorfs.c')
-rw-r--r--security/apparmor/apparmorfs.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
new file mode 100644
index 000000000000..7320331b44ab
--- /dev/null
+++ b/security/apparmor/apparmorfs.c
@@ -0,0 +1,239 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor /sys/kernel/security/apparmor interface functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * 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.
13 */
14
15#include <linux/security.h>
16#include <linux/vmalloc.h>
17#include <linux/module.h>
18#include <linux/seq_file.h>
19#include <linux/uaccess.h>
20#include <linux/namei.h>
21
22#include "include/apparmor.h"
23#include "include/apparmorfs.h"
24#include "include/audit.h"
25#include "include/context.h"
26#include "include/policy.h"
27
28/**
29 * aa_simple_write_to_buffer - common routine for getting policy from user
30 * @op: operation doing the user buffer copy
31 * @userbuf: user buffer to copy data from (NOT NULL)
32 * @alloc_size: size of user buffer
33 * @copy_size: size of data to copy from user buffer
34 * @pos: position write is at in the file (NOT NULL)
35 *
36 * Returns: kernel buffer containing copy of user buffer data or an
37 * ERR_PTR on failure.
38 */
39static char *aa_simple_write_to_buffer(int op, const char __user *userbuf,
40 size_t alloc_size, size_t copy_size,
41 loff_t *pos)
42{
43 char *data;
44
45 if (*pos != 0)
46 /* only writes from pos 0, that is complete writes */
47 return ERR_PTR(-ESPIPE);
48
49 /*
50 * Don't allow profile load/replace/remove from profiles that don't
51 * have CAP_MAC_ADMIN
52 */
53 if (!aa_may_manage_policy(op))
54 return ERR_PTR(-EACCES);
55
56 /* freed by caller to simple_write_to_buffer */
57 data = kvmalloc(alloc_size);
58 if (data == NULL)
59 return ERR_PTR(-ENOMEM);
60
61 if (copy_from_user(data, userbuf, copy_size)) {
62 kvfree(data);
63 return ERR_PTR(-EFAULT);
64 }
65
66 return data;
67}
68
69
70/* .load file hook fn to load policy */
71static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
72 loff_t *pos)
73{
74 char *data;
75 ssize_t error;
76
77 data = aa_simple_write_to_buffer(OP_PROF_LOAD, buf, size, size, pos);
78
79 error = PTR_ERR(data);
80 if (!IS_ERR(data)) {
81 error = aa_replace_profiles(data, size, PROF_ADD);
82 kvfree(data);
83 }
84
85 return error;
86}
87
88static const struct file_operations aa_fs_profile_load = {
89 .write = profile_load
90};
91
92/* .replace file hook fn to load and/or replace policy */
93static ssize_t profile_replace(struct file *f, const char __user *buf,
94 size_t size, loff_t *pos)
95{
96 char *data;
97 ssize_t error;
98
99 data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos);
100 error = PTR_ERR(data);
101 if (!IS_ERR(data)) {
102 error = aa_replace_profiles(data, size, PROF_REPLACE);
103 kvfree(data);
104 }
105
106 return error;
107}
108
109static const struct file_operations aa_fs_profile_replace = {
110 .write = profile_replace
111};
112
113/* .remove file hook fn to remove loaded policy */
114static ssize_t profile_remove(struct file *f, const char __user *buf,
115 size_t size, loff_t *pos)
116{
117 char *data;
118 ssize_t error;
119
120 /*
121 * aa_remove_profile needs a null terminated string so 1 extra
122 * byte is allocated and the copied data is null terminated.
123 */
124 data = aa_simple_write_to_buffer(OP_PROF_RM, buf, size + 1, size, pos);
125
126 error = PTR_ERR(data);
127 if (!IS_ERR(data)) {
128 data[size] = 0;
129 error = aa_remove_profiles(data, size);
130 kvfree(data);
131 }
132
133 return error;
134}
135
136static const struct file_operations aa_fs_profile_remove = {
137 .write = profile_remove
138};
139
140/** Base file system setup **/
141
142static struct dentry *aa_fs_dentry __initdata;
143
144static void __init aafs_remove(const char *name)
145{
146 struct dentry *dentry;
147
148 dentry = lookup_one_len(name, aa_fs_dentry, strlen(name));
149 if (!IS_ERR(dentry)) {
150 securityfs_remove(dentry);
151 dput(dentry);
152 }
153}
154
155/**
156 * aafs_create - create an entry in the apparmor filesystem
157 * @name: name of the entry (NOT NULL)
158 * @mask: file permission mask of the file
159 * @fops: file operations for the file (NOT NULL)
160 *
161 * Used aafs_remove to remove entries created with this fn.
162 */
163static int __init aafs_create(const char *name, int mask,
164 const struct file_operations *fops)
165{
166 struct dentry *dentry;
167
168 dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry,
169 NULL, fops);
170
171 return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
172}
173
174/**
175 * aa_destroy_aafs - cleanup and free aafs
176 *
177 * releases dentries allocated by aa_create_aafs
178 */
179void __init aa_destroy_aafs(void)
180{
181 if (aa_fs_dentry) {
182 aafs_remove(".remove");
183 aafs_remove(".replace");
184 aafs_remove(".load");
185
186 securityfs_remove(aa_fs_dentry);
187 aa_fs_dentry = NULL;
188 }
189}
190
191/**
192 * aa_create_aafs - create the apparmor security filesystem
193 *
194 * dentries created here are released by aa_destroy_aafs
195 *
196 * Returns: error on failure
197 */
198int __init aa_create_aafs(void)
199{
200 int error;
201
202 if (!apparmor_initialized)
203 return 0;
204
205 if (aa_fs_dentry) {
206 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
207 return -EEXIST;
208 }
209
210 aa_fs_dentry = securityfs_create_dir("apparmor", NULL);
211 if (IS_ERR(aa_fs_dentry)) {
212 error = PTR_ERR(aa_fs_dentry);
213 aa_fs_dentry = NULL;
214 goto error;
215 }
216
217 error = aafs_create(".load", 0640, &aa_fs_profile_load);
218 if (error)
219 goto error;
220 error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
221 if (error)
222 goto error;
223 error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
224 if (error)
225 goto error;
226
227 /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
228
229 /* Report that AppArmor fs is enabled */
230 aa_info_message("AppArmor Filesystem Enabled");
231 return 0;
232
233error:
234 aa_destroy_aafs();
235 AA_ERROR("Error creating AppArmor securityfs\n");
236 return error;
237}
238
239fs_initcall(aa_create_aafs);