2
* Copyright (C) 2005 Novell/SUSE
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation, version 2 of the
9
* AppArmor filesystem (part of securityfs)
12
#include <linux/security.h>
13
#include <linux/vmalloc.h>
14
#include <linux/module.h>
15
#include <linux/seq_file.h>
16
#include <asm/uaccess.h>
20
#include "match/match.h"
22
#define SECFS_AA "apparmor"
23
static struct dentry *aafs_dentry = NULL;
26
extern struct seq_operations apparmorfs_profiles_op;
27
static int aa_prof_open(struct inode *inode, struct file *file);
28
static int aa_prof_release(struct inode *inode, struct file *file);
30
static struct file_operations apparmorfs_profiles_fops = {
34
.release = aa_prof_release,
38
static ssize_t aa_matching_read(struct file *file, char __user *buf,
39
size_t size, loff_t *ppos);
41
static struct file_operations apparmorfs_matching_fops = {
42
.read = aa_matching_read,
47
static ssize_t aa_profile_load(struct file *f, const char __user *buf,
48
size_t size, loff_t *pos);
49
static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
50
size_t size, loff_t *pos);
51
static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
52
size_t size, loff_t *pos);
54
static struct file_operations apparmorfs_profile_load = {
55
.write = aa_profile_load
58
static struct file_operations apparmorfs_profile_replace = {
59
.write = aa_profile_replace
62
static struct file_operations apparmorfs_profile_remove = {
63
.write = aa_profile_remove
68
static u64 aa_control_get(void *data);
69
static void aa_control_set(void *data, u64 val);
71
DEFINE_SIMPLE_ATTRIBUTE(apparmorfs_control_fops, aa_control_get,
72
aa_control_set, "%lld\n");
76
/* table of static entries */
78
static struct root_entry {
82
struct file_operations *fops;
86
struct dentry *dentry;
89
/* our root, normally /sys/kernel/security/apparmor */
90
{SECFS_AA, S_IFDIR, 0550}, /* DO NOT EDIT/MOVE */
92
/* interface for obtaining list of profiles currently loaded */
93
{"profiles", S_IFREG, 0440, &apparmorfs_profiles_fops,
96
/* interface for obtaining matching features supported */
97
{"matching", S_IFREG, 0440, &apparmorfs_matching_fops,
100
/* interface for loading/removing/replacing profiles */
101
{".load", S_IFREG, 0640, &apparmorfs_profile_load,
103
{".replace", S_IFREG, 0640, &apparmorfs_profile_replace,
105
{".remove", S_IFREG, 0640, &apparmorfs_profile_remove,
108
/* interface for setting binary config values */
109
{"control", S_IFDIR, 0550},
110
{"complain", S_IFREG, 0640, &apparmorfs_control_fops,
112
{"audit", S_IFREG, 0640, &apparmorfs_control_fops,
114
{"debug", S_IFREG, 0640, &apparmorfs_control_fops,
116
{"logsyscall", S_IFREG, 0640, &apparmorfs_control_fops,
117
&apparmor_logsyscall},
124
#define AAFS_DENTRY root_entries[0].dentry
126
static const unsigned int num_entries =
127
sizeof(root_entries) / sizeof(struct root_entry);
131
static int aa_prof_open(struct inode *inode, struct file *file)
133
return seq_open(file, &apparmorfs_profiles_op);
137
static int aa_prof_release(struct inode *inode, struct file *file)
139
return seq_release(inode, file);
142
static ssize_t aa_matching_read(struct file *file, char __user *buf,
143
size_t size, loff_t *ppos)
145
const char *matching = aamatch_features();
147
return simple_read_from_buffer(buf, size, ppos, matching,
151
static char *aa_simple_write_to_buffer(const char __user *userbuf,
152
size_t alloc_size, size_t copy_size,
153
loff_t *pos, const char *msg)
155
struct aaprofile *active;
159
/* only writes from pos 0, that is complete writes */
160
data = ERR_PTR(-ESPIPE);
164
/* Don't allow confined processes to load/replace/remove profiles.
165
* No sane person would add rules allowing this to a profile
166
* but we enforce the restriction anyways.
169
active = get_activeptr_rcu();
171
AA_WARN("REJECTING access to profile %s (%s(%d) "
172
"profile %s active %s)\n",
173
msg, current->comm, current->pid,
174
BASE_PROFILE(active)->name, active->name);
176
data = ERR_PTR(-EPERM);
181
data = vmalloc(alloc_size);
183
data = ERR_PTR(-ENOMEM);
187
if (copy_from_user(data, userbuf, copy_size)) {
189
data = ERR_PTR(-EFAULT);
197
static ssize_t aa_profile_load(struct file *f, const char __user *buf,
198
size_t size, loff_t *pos)
203
data = aa_simple_write_to_buffer(buf, size, size, pos, "load");
206
error = aa_file_prof_add(data, size);
209
error = PTR_ERR(data);
215
static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
216
size_t size, loff_t *pos)
221
data = aa_simple_write_to_buffer(buf, size, size, pos, "replacement");
224
error = aa_file_prof_repl(data, size);
227
error = PTR_ERR(data);
233
static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
234
size_t size, loff_t *pos)
239
/* aa_file_prof_remove needs a null terminated string so 1 extra
240
* byte is allocated and null the copied data is then null terminated
242
data = aa_simple_write_to_buffer(buf, size+1, size, pos, "removal");
246
error = aa_file_prof_remove(data, size);
249
error = PTR_ERR(data);
255
static u64 aa_control_get(void *data)
260
static void aa_control_set(void *data, u64 val)
265
*(int*)data = (int)val;
268
static void clear_apparmorfs(void)
272
for (i=0; i < num_entries;i++) {
275
if (root_entries[i].mode == S_IFDIR) {
276
if (root_entries[i].name)
277
/* defer dir free till all sub-entries freed */
281
index = root_entries[i].parent_index;
286
if (root_entries[index].dentry) {
287
securityfs_remove(root_entries[index].dentry);
289
AA_DEBUG("%s: deleted apparmorfs entry name=%s "
292
root_entries[index].name,
293
root_entries[index].dentry);
295
root_entries[index].dentry = NULL;
296
root_entries[index].parent_index = 0;
301
static int populate_apparmorfs(struct dentry *root)
303
unsigned int i, parent_index, depth;
305
for (i = 0; i < num_entries; i++) {
306
root_entries[i].dentry = NULL;
307
root_entries[i].parent_index = 0;
310
/* 1. Verify entry 0 is valid [sanity check] */
311
if (num_entries == 0 ||
312
!root_entries[0].name ||
313
strcmp(root_entries[0].name, SECFS_AA) != 0 ||
314
root_entries[0].mode != S_IFDIR) {
315
AA_ERROR("%s: root entry 0 is not SECFS_AA/dir\n",
320
/* 2. Build back pointers */
324
for (i = 1; i < num_entries; i++) {
325
root_entries[i].parent_index = parent_index;
327
if (root_entries[i].name &&
328
root_entries[i].mode == S_IFDIR) {
331
} else if (!root_entries[i].name) {
332
if (root_entries[i].mode != S_IFDIR || depth == 0) {
333
AA_ERROR("%s: root_entry %d invalid (%u %d)",
335
root_entries[i].mode,
336
root_entries[i].parent_index);
341
parent_index = root_entries[parent_index].parent_index;
346
AA_ERROR("%s: root_entry table not correctly terminated\n",
351
/* 3. Create root (parent=NULL) */
352
root_entries[0].dentry = securityfs_create_file(
353
root_entries[0].name,
354
root_entries[0].mode |
355
root_entries[0].access,
358
if (IS_ERR(root_entries[0].dentry))
361
AA_DEBUG("%s: created securityfs/apparmor [dentry=%p]\n",
362
__FUNCTION__, root_entries[0].dentry);
365
/* 4. create remaining nodes */
366
for (i = 1; i < num_entries; i++) {
367
struct dentry *parent;
369
struct file_operations *fops = NULL;
371
/* end of directory ? */
372
if (!root_entries[i].name)
375
parent = root_entries[root_entries[i].parent_index].dentry;
377
if (root_entries[i].mode != S_IFDIR) {
378
data = root_entries[i].data;
379
fops = root_entries[i].fops;
382
root_entries[i].dentry = securityfs_create_file(
383
root_entries[i].name,
384
root_entries[i].mode |
385
root_entries[i].access,
390
if (IS_ERR(root_entries[i].dentry))
393
AA_DEBUG("%s: added apparmorfs entry "
394
"name=%s mode=%x dentry=%p [parent %p]\n",
395
__FUNCTION__, root_entries[i].name,
396
root_entries[i].mode|root_entries[i].access,
397
root_entries[i].dentry, parent);
409
int create_apparmorfs(void)
415
AA_ERROR("%s: AppArmor securityfs already exists\n",
418
error = populate_apparmorfs(aafs_dentry);
420
AA_ERROR("%s: Error populating AppArmor securityfs\n",
428
void destroy_apparmorfs(void)