~mathiaz/apparmor/ubuntu-mathiaz

« back to all changes in this revision

Viewing changes to module/apparmor/apparmorfs.c

  • Committer: Mathias Gug
  • Date: 2008-02-04 18:57:00 UTC
  • mfrom: (885.1.5 apparmor)
  • Revision ID: mathiaz@ubuntu.com-20080204185700-wwlyq0ksssxclv8w
Merge  ubuntu branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *      Copyright (C) 2005 Novell/SUSE
3
 
 *
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
7
 
 *      License.
8
 
 *
9
 
 *      AppArmor filesystem (part of securityfs)
10
 
 */
11
 
 
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>
17
 
 
18
 
#include "apparmor.h"
19
 
#include "inline.h"
20
 
#include "match/match.h"
21
 
 
22
 
#define SECFS_AA "apparmor"
23
 
static struct dentry *aafs_dentry = NULL;
24
 
 
25
 
/* profile */
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);
29
 
 
30
 
static struct file_operations apparmorfs_profiles_fops = {
31
 
        .open =         aa_prof_open,
32
 
        .read =         seq_read,
33
 
        .llseek =       seq_lseek,
34
 
        .release =      aa_prof_release,
35
 
};
36
 
 
37
 
/* matching */
38
 
static ssize_t aa_matching_read(struct file *file, char __user *buf,
39
 
                               size_t size, loff_t *ppos);
40
 
 
41
 
static struct file_operations apparmorfs_matching_fops = {
42
 
        .read =         aa_matching_read,
43
 
};
44
 
 
45
 
 
46
 
/* interface */
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);
53
 
 
54
 
static struct file_operations apparmorfs_profile_load = {
55
 
        .write = aa_profile_load
56
 
};
57
 
 
58
 
static struct file_operations apparmorfs_profile_replace = {
59
 
        .write = aa_profile_replace
60
 
};
61
 
 
62
 
static struct file_operations apparmorfs_profile_remove = {
63
 
        .write = aa_profile_remove
64
 
};
65
 
 
66
 
 
67
 
/* control */
68
 
static u64 aa_control_get(void *data);
69
 
static void aa_control_set(void *data, u64 val);
70
 
 
71
 
DEFINE_SIMPLE_ATTRIBUTE(apparmorfs_control_fops, aa_control_get,
72
 
                        aa_control_set, "%lld\n");
73
 
 
74
 
 
75
 
 
76
 
/* table of static entries */
77
 
 
78
 
static struct root_entry {
79
 
        const char *name;
80
 
        int mode;
81
 
        int access;
82
 
        struct file_operations *fops;
83
 
        void *data;
84
 
 
85
 
        /* internal fields */
86
 
        struct dentry *dentry;
87
 
        int parent_index;
88
 
} root_entries[] = {
89
 
        /* our root, normally /sys/kernel/security/apparmor */
90
 
        {SECFS_AA,      S_IFDIR, 0550}, /* DO NOT EDIT/MOVE */
91
 
 
92
 
        /* interface for obtaining list of profiles currently loaded */
93
 
        {"profiles",    S_IFREG, 0440, &apparmorfs_profiles_fops,
94
 
                                       NULL},
95
 
 
96
 
        /* interface for obtaining matching features supported */
97
 
        {"matching",    S_IFREG, 0440, &apparmorfs_matching_fops,
98
 
                                       NULL},
99
 
 
100
 
        /* interface for loading/removing/replacing profiles */
101
 
        {".load",       S_IFREG, 0640, &apparmorfs_profile_load,
102
 
                                       NULL},
103
 
        {".replace",    S_IFREG, 0640, &apparmorfs_profile_replace,
104
 
                                       NULL},
105
 
        {".remove",     S_IFREG, 0640, &apparmorfs_profile_remove,
106
 
                                       NULL},
107
 
 
108
 
        /* interface for setting binary config values */
109
 
        {"control",     S_IFDIR, 0550},
110
 
        {"complain",    S_IFREG, 0640, &apparmorfs_control_fops,
111
 
                                       &apparmor_complain},
112
 
        {"audit",       S_IFREG, 0640, &apparmorfs_control_fops,
113
 
                                       &apparmor_audit},
114
 
        {"debug",       S_IFREG, 0640, &apparmorfs_control_fops,
115
 
                                       &apparmor_debug},
116
 
        {"logsyscall",  S_IFREG, 0640, &apparmorfs_control_fops,
117
 
                                       &apparmor_logsyscall},
118
 
        {NULL,          S_IFDIR, 0},
119
 
 
120
 
        /* root end */
121
 
        {NULL,          S_IFDIR, 0}
122
 
};
123
 
 
124
 
#define AAFS_DENTRY root_entries[0].dentry
125
 
 
126
 
static const unsigned int num_entries =
127
 
        sizeof(root_entries) / sizeof(struct root_entry);
128
 
 
129
 
 
130
 
 
131
 
static int aa_prof_open(struct inode *inode, struct file *file)
132
 
{
133
 
        return seq_open(file, &apparmorfs_profiles_op);
134
 
}
135
 
 
136
 
 
137
 
static int aa_prof_release(struct inode *inode, struct file *file)
138
 
{
139
 
        return seq_release(inode, file);
140
 
}
141
 
 
142
 
static ssize_t aa_matching_read(struct file *file, char __user *buf,
143
 
                               size_t size, loff_t *ppos)
144
 
{
145
 
        const char *matching = aamatch_features();
146
 
 
147
 
        return simple_read_from_buffer(buf, size, ppos, matching,
148
 
                                       strlen(matching));
149
 
}
150
 
 
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)
154
 
{
155
 
        struct aaprofile *active;
156
 
        char *data;
157
 
 
158
 
        if (*pos != 0) {
159
 
                /* only writes from pos 0, that is complete writes */
160
 
                data = ERR_PTR(-ESPIPE);
161
 
                goto out;
162
 
        }
163
 
 
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.
167
 
         */
168
 
        rcu_read_lock();
169
 
        active = get_activeptr_rcu();
170
 
        if (active) {
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);
175
 
 
176
 
                data = ERR_PTR(-EPERM);
177
 
                goto out;
178
 
        }
179
 
        rcu_read_unlock();
180
 
 
181
 
        data = vmalloc(alloc_size);
182
 
        if (data == NULL) {
183
 
                data = ERR_PTR(-ENOMEM);
184
 
                goto out;
185
 
        }
186
 
 
187
 
        if (copy_from_user(data, userbuf, copy_size)) {
188
 
                vfree(data);
189
 
                data = ERR_PTR(-EFAULT);
190
 
                goto out;
191
 
        }
192
 
 
193
 
out:
194
 
        return data;
195
 
}
196
 
 
197
 
static ssize_t aa_profile_load(struct file *f, const char __user *buf,
198
 
                               size_t size, loff_t *pos)
199
 
{
200
 
        char *data;
201
 
        ssize_t error;
202
 
 
203
 
        data = aa_simple_write_to_buffer(buf, size, size, pos, "load");
204
 
 
205
 
        if (!IS_ERR(data)) {
206
 
                error = aa_file_prof_add(data, size);
207
 
                vfree(data);
208
 
        } else {
209
 
                error = PTR_ERR(data);
210
 
        }
211
 
 
212
 
        return error;
213
 
}
214
 
 
215
 
static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
216
 
                                  size_t size, loff_t *pos)
217
 
{
218
 
        char *data;
219
 
        ssize_t error;
220
 
 
221
 
        data = aa_simple_write_to_buffer(buf, size, size, pos, "replacement");
222
 
 
223
 
        if (!IS_ERR(data)) {
224
 
                error = aa_file_prof_repl(data, size);
225
 
                vfree(data);
226
 
        } else {
227
 
                error = PTR_ERR(data);
228
 
        }
229
 
 
230
 
        return error;
231
 
}
232
 
 
233
 
static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
234
 
                                  size_t size, loff_t *pos)
235
 
{
236
 
        char *data;
237
 
        ssize_t error;
238
 
 
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
241
 
         */
242
 
        data = aa_simple_write_to_buffer(buf, size+1, size, pos, "removal");
243
 
 
244
 
        if (!IS_ERR(data)) {
245
 
                data[size] = 0;
246
 
                error = aa_file_prof_remove(data, size);
247
 
                vfree(data);
248
 
        } else {
249
 
                error = PTR_ERR(data);
250
 
        }
251
 
 
252
 
        return error;
253
 
}
254
 
 
255
 
static u64 aa_control_get(void *data)
256
 
{
257
 
        return *(int *)data;
258
 
}
259
 
 
260
 
static void aa_control_set(void *data, u64 val)
261
 
{
262
 
        if (val > 1)
263
 
                val = 1;
264
 
 
265
 
        *(int*)data = (int)val;
266
 
}
267
 
 
268
 
static void clear_apparmorfs(void)
269
 
{
270
 
        unsigned int i;
271
 
 
272
 
        for (i=0; i < num_entries;i++) {
273
 
                unsigned int index;
274
 
 
275
 
                if (root_entries[i].mode == S_IFDIR) {
276
 
                        if (root_entries[i].name)
277
 
                                /* defer dir free till all sub-entries freed */
278
 
                                continue;
279
 
                        else
280
 
                                /* cleanup parent */
281
 
                                index = root_entries[i].parent_index;
282
 
                } else {
283
 
                        index = i;
284
 
                }
285
 
 
286
 
                if (root_entries[index].dentry) {
287
 
                        securityfs_remove(root_entries[index].dentry);
288
 
 
289
 
                        AA_DEBUG("%s: deleted apparmorfs entry name=%s "
290
 
                                 "dentry=%p\n",
291
 
                                __FUNCTION__,
292
 
                                root_entries[index].name,
293
 
                                root_entries[index].dentry);
294
 
 
295
 
                        root_entries[index].dentry = NULL;
296
 
                        root_entries[index].parent_index = 0;
297
 
                }
298
 
        }
299
 
}
300
 
 
301
 
static int populate_apparmorfs(struct dentry *root)
302
 
{
303
 
        unsigned int i, parent_index, depth;
304
 
 
305
 
        for (i = 0; i < num_entries; i++) {
306
 
                root_entries[i].dentry = NULL;
307
 
                root_entries[i].parent_index = 0;
308
 
        }
309
 
 
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",
316
 
                        __FUNCTION__);
317
 
                goto error;
318
 
        }
319
 
 
320
 
        /* 2. Build back pointers */
321
 
        parent_index = 0;
322
 
        depth = 1;
323
 
 
324
 
        for (i = 1; i < num_entries; i++) {
325
 
                root_entries[i].parent_index = parent_index;
326
 
 
327
 
                if (root_entries[i].name &&
328
 
                    root_entries[i].mode == S_IFDIR) {
329
 
                        depth++;
330
 
                        parent_index = i;
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)",
334
 
                                         __FUNCTION__, i,
335
 
                                         root_entries[i].mode,
336
 
                                         root_entries[i].parent_index);
337
 
                                goto error;
338
 
                        }
339
 
 
340
 
                        depth--;
341
 
                        parent_index = root_entries[parent_index].parent_index;
342
 
                }
343
 
        }
344
 
 
345
 
        if (depth != 0) {
346
 
                AA_ERROR("%s: root_entry table not correctly terminated\n",
347
 
                        __FUNCTION__);
348
 
                goto error;
349
 
        }
350
 
 
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,
356
 
                                        NULL, NULL, NULL);
357
 
 
358
 
        if (IS_ERR(root_entries[0].dentry))
359
 
                goto error;
360
 
        else
361
 
                AA_DEBUG("%s: created securityfs/apparmor [dentry=%p]\n",
362
 
                        __FUNCTION__, root_entries[0].dentry);
363
 
 
364
 
 
365
 
        /* 4. create remaining nodes */
366
 
        for (i = 1; i < num_entries; i++) {
367
 
                struct dentry *parent;
368
 
                void *data = NULL;
369
 
                struct file_operations *fops = NULL;
370
 
 
371
 
                /* end of directory ? */
372
 
                if (!root_entries[i].name)
373
 
                        continue;
374
 
 
375
 
                parent = root_entries[root_entries[i].parent_index].dentry;
376
 
 
377
 
                if (root_entries[i].mode != S_IFDIR) {
378
 
                        data = root_entries[i].data;
379
 
                        fops = root_entries[i].fops;
380
 
                }
381
 
 
382
 
                root_entries[i].dentry = securityfs_create_file(
383
 
                                                root_entries[i].name,
384
 
                                                root_entries[i].mode |
385
 
                                                        root_entries[i].access,
386
 
                                                parent,
387
 
                                                data,
388
 
                                                fops);
389
 
 
390
 
                if (IS_ERR(root_entries[i].dentry))
391
 
                        goto cleanup_error;
392
 
 
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);
398
 
        }
399
 
 
400
 
        return 0;
401
 
 
402
 
cleanup_error:
403
 
        clear_apparmorfs();
404
 
 
405
 
error:
406
 
        return -EINVAL;
407
 
}
408
 
 
409
 
int create_apparmorfs(void)
410
 
{
411
 
        int error = 0;
412
 
 
413
 
        if (AAFS_DENTRY) {
414
 
                error = -EEXIST;
415
 
                AA_ERROR("%s: AppArmor securityfs already exists\n",
416
 
                        __FUNCTION__);
417
 
        } else {
418
 
                error = populate_apparmorfs(aafs_dentry);
419
 
                if (error != 0) {
420
 
                        AA_ERROR("%s: Error populating AppArmor securityfs\n",
421
 
                                __FUNCTION__);
422
 
                }
423
 
        }
424
 
 
425
 
        return error;
426
 
}
427
 
 
428
 
void destroy_apparmorfs(void)
429
 
{
430
 
        if (AAFS_DENTRY)
431
 
                clear_apparmorfs();
432
 
}