]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.apparmor/apparmor-lsm.diff
Add a patch to fix Intel E100 wake-on-lan problems.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.apparmor / apparmor-lsm.diff
CommitLineData
6a930a95
BS
1From: John Johansen <jjohansen@suse.de>
2Subject: AppArmor: Module and LSM hooks
3
4Module parameters, LSM hooks, initialization and teardown.
5
6Signed-off-by: John Johansen <jjohansen@suse.de>
7Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
8
9---
10 security/apparmor/lsm.c | 895 ++++++++++++++++++++++++++++++++++++++++++++++++
11 1 file changed, 895 insertions(+)
12
13--- /dev/null
14+++ b/security/apparmor/lsm.c
15@@ -0,0 +1,895 @@
16+/*
17+ * Copyright (C) 1998-2007 Novell/SUSE
18+ *
19+ * This program is free software; you can redistribute it and/or
20+ * modify it under the terms of the GNU General Public License as
21+ * published by the Free Software Foundation, version 2 of the
22+ * License.
23+ *
24+ * AppArmor LSM interface
25+ */
26+
27+#include <linux/security.h>
28+#include <linux/module.h>
29+#include <linux/mm.h>
30+#include <linux/mman.h>
31+#include <linux/mount.h>
32+#include <linux/namei.h>
33+#include <linux/ctype.h>
34+#include <linux/sysctl.h>
35+#include <linux/audit.h>
36+
37+#include "apparmor.h"
38+#include "inline.h"
39+
40+/* Flag indicating whether initialization completed */
41+int apparmor_initialized = 0;
42+
43+static int param_set_aabool(const char *val, struct kernel_param *kp);
44+static int param_get_aabool(char *buffer, struct kernel_param *kp);
45+#define param_check_aabool(name, p) __param_check(name, p, int)
46+
47+static int param_set_aauint(const char *val, struct kernel_param *kp);
48+static int param_get_aauint(char *buffer, struct kernel_param *kp);
49+#define param_check_aauint(name, p) __param_check(name, p, int)
50+
51+/* Flag values, also controllable via /sys/module/apparmor/parameters
52+ * We define special types as we want to do additional mediation.
53+ *
54+ * Complain mode -- in complain mode access failures result in auditing only
55+ * and task is allowed access. audit events are processed by userspace to
56+ * generate policy. Default is 'enforce' (0).
57+ * Value is also togglable per profile and referenced when global value is
58+ * enforce.
59+ */
60+int apparmor_complain = 0;
61+module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
62+MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
63+
64+/* Debug mode */
65+int apparmor_debug = 0;
66+module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
67+MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
68+
69+/* Audit mode */
70+int apparmor_audit = 0;
71+module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
72+MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
73+
74+/* Syscall logging mode */
75+int apparmor_logsyscall = 0;
76+module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
77+MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
78+
79+/* Maximum pathname length before accesses will start getting rejected */
80+unsigned int apparmor_path_max = 2 * PATH_MAX;
81+module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
82+MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
83+
84+/* Boot time disable flag */
85+#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
86+#define AA_ENABLED_PERMS 0600
87+#else
88+#define AA_ENABLED_PERMS 0400
89+#endif
90+static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
91+unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
92+module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
93+ &apparmor_enabled, AA_ENABLED_PERMS);
94+MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
95+
96+static int __init apparmor_enabled_setup(char *str)
97+{
98+ apparmor_enabled = simple_strtol(str, NULL, 0);
99+ return 1;
100+}
101+__setup("apparmor=", apparmor_enabled_setup);
102+
103+static int param_set_aabool(const char *val, struct kernel_param *kp)
104+{
105+ if (aa_task_context(current))
106+ return -EPERM;
107+ return param_set_bool(val, kp);
108+}
109+
110+static int param_get_aabool(char *buffer, struct kernel_param *kp)
111+{
112+ if (aa_task_context(current))
113+ return -EPERM;
114+ return param_get_bool(buffer, kp);
115+}
116+
117+static int param_set_aauint(const char *val, struct kernel_param *kp)
118+{
119+ if (aa_task_context(current))
120+ return -EPERM;
121+ return param_set_uint(val, kp);
122+}
123+
124+static int param_get_aauint(char *buffer, struct kernel_param *kp)
125+{
126+ if (aa_task_context(current))
127+ return -EPERM;
128+ return param_get_uint(buffer, kp);
129+}
130+
131+/* allow run time disabling of apparmor */
132+static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
133+{
134+ char *endp;
135+ unsigned long l;
136+
137+ if (!apparmor_initialized) {
138+ apparmor_enabled = 0;
139+ return 0;
140+ }
141+
142+ if (aa_task_context(current))
143+ return -EPERM;
144+
145+ if (!apparmor_enabled)
146+ return -EINVAL;
147+
148+ if (!val)
149+ return -EINVAL;
150+
151+ l = simple_strtoul(val, &endp, 0);
152+ if (endp == val || l != 0)
153+ return -EINVAL;
154+
155+ apparmor_enabled = 0;
156+ apparmor_disable();
157+ return 0;
158+}
159+
160+static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
161+ const char *name)
162+{
163+ struct aa_profile *profile = aa_get_profile(task);
164+ int error = 0;
165+
166+ if (profile) {
167+ error = aa_audit_syscallreject(profile, flags, name);
168+ aa_put_profile(profile);
169+ }
170+
171+ return error;
172+}
173+
174+static int apparmor_ptrace(struct task_struct *parent,
175+ struct task_struct *child, unsigned int mode)
176+{
177+ struct aa_task_context *cxt;
178+ int error = 0;
179+
180+ /*
181+ * parent can ptrace child when
182+ * - parent is unconfined
183+ * - parent & child are in the same namespace &&
184+ * - parent is in complain mode
185+ * - parent and child are confined by the same profile
186+ * - parent profile has CAP_SYS_PTRACE
187+ */
188+
189+ rcu_read_lock();
190+ cxt = aa_task_context(parent);
191+ if (cxt) {
192+ if (parent->nsproxy != child->nsproxy) {
193+ struct aa_audit sa;
194+ memset(&sa, 0, sizeof(sa));
195+ sa.operation = "ptrace";
196+ sa.gfp_mask = GFP_ATOMIC;
197+ sa.parent = parent->pid;
198+ sa.task = child->pid;
199+ sa.info = "different namespaces";
200+ aa_audit_reject(cxt->profile, &sa);
201+ error = -EPERM;
202+ } else {
203+ struct aa_task_context *child_cxt =
204+ aa_task_context(child);
205+
206+ error = aa_may_ptrace(cxt, child_cxt ?
207+ child_cxt->profile : NULL);
208+ if (PROFILE_COMPLAIN(cxt->profile)) {
209+ struct aa_audit sa;
210+ memset(&sa, 0, sizeof(sa));
211+ sa.operation = "ptrace";
212+ sa.gfp_mask = GFP_ATOMIC;
213+ sa.parent = parent->pid;
214+ sa.task = child->pid;
215+ aa_audit_hint(cxt->profile, &sa);
216+ }
217+ }
218+ }
219+ rcu_read_unlock();
220+
221+ return error;
222+}
223+
224+static int apparmor_capable(struct task_struct *task, int cap)
225+{
226+ int error;
227+ struct aa_task_context *cxt;
228+
229+ /* cap_capable returns 0 on success, else -EPERM */
230+ error = cap_capable(task, cap);
231+
232+ rcu_read_lock();
233+ cxt = aa_task_context(task);
234+ if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
235+ error = aa_capability(cxt, cap);
236+ rcu_read_unlock();
237+
238+ return error;
239+}
240+
241+static int apparmor_sysctl(struct ctl_table *table, int op)
242+{
243+ struct aa_profile *profile = aa_get_profile(current);
244+ int error = 0;
245+
246+ if (profile) {
247+ char *buffer, *name;
248+ int mask;
249+
250+ mask = 0;
251+ if (op & 4)
252+ mask |= MAY_READ;
253+ if (op & 2)
254+ mask |= MAY_WRITE;
255+
256+ error = -ENOMEM;
257+ buffer = (char*)__get_free_page(GFP_KERNEL);
258+ if (!buffer)
259+ goto out;
260+ name = sysctl_pathname(table, buffer, PAGE_SIZE);
261+ if (name && name - buffer >= 5) {
262+ name -= 5;
263+ memcpy(name, "/proc", 5);
264+ error = aa_perm_path(profile, "sysctl", name, mask, 0);
265+ }
266+ free_page((unsigned long)buffer);
267+ }
268+
269+out:
270+ aa_put_profile(profile);
271+ return error;
272+}
273+
274+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
275+{
276+ /* handle capability bits with setuid, etc */
277+ cap_bprm_set_security(bprm);
278+ /* already set based on script name */
279+ if (bprm->sh_bang)
280+ return 0;
281+ return aa_register(bprm);
282+}
283+
284+static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
285+{
286+ int ret = cap_bprm_secureexec(bprm);
287+
288+ if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
289+ AA_DEBUG("%s: secureexec required for %s\n",
290+ __FUNCTION__, bprm->filename);
291+ ret = 1;
292+ }
293+
294+ return ret;
295+}
296+
297+static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
298+ unsigned long flags, void *data)
299+{
300+ return aa_reject_syscall(current, GFP_KERNEL, "mount");
301+}
302+
303+static int apparmor_umount(struct vfsmount *mnt, int flags)
304+{
305+ return aa_reject_syscall(current, GFP_KERNEL, "umount");
306+}
307+
308+static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
309+ struct vfsmount *mnt, int mask)
310+{
311+ struct aa_profile *profile;
312+ int error = 0;
313+
314+ if (!mnt || !mediated_filesystem(dir))
315+ goto out;
316+
317+ profile = aa_get_profile(current);
318+
319+ if (profile)
320+ error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
321+ MAY_WRITE);
322+
323+ aa_put_profile(profile);
324+
325+out:
326+ return error;
327+}
328+
329+static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
330+ struct vfsmount *mnt)
331+{
332+ struct aa_profile *profile;
333+ int error = 0;
334+
335+ if (!mnt || !mediated_filesystem(dir))
336+ goto out;
337+
338+ profile = aa_get_profile(current);
339+
340+ if (profile)
341+ error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
342+ MAY_WRITE);
343+
344+ aa_put_profile(profile);
345+
346+out:
347+ return error;
348+}
349+
350+static int aa_permission(const char *operation, struct inode *inode,
351+ struct dentry *dentry, struct vfsmount *mnt,
352+ int mask, int check)
353+{
354+ int error = 0;
355+
356+ if (mnt && mediated_filesystem(inode)) {
357+ struct aa_profile *profile;
358+
359+ profile = aa_get_profile(current);
360+ if (profile)
361+ error = aa_perm(profile, operation, dentry, mnt, mask,
362+ check);
363+ aa_put_profile(profile);
364+ }
365+ return error;
366+}
367+
368+static inline int aa_mask_permissions(int mask)
369+{
370+ if (mask & MAY_APPEND)
371+ mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
372+ else
373+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
374+ return mask;
375+}
376+
377+static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
378+ struct vfsmount *mnt, int mask)
379+{
380+ return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
381+}
382+
383+static int apparmor_inode_link(struct dentry *old_dentry,
384+ struct vfsmount *old_mnt, struct inode *dir,
385+ struct dentry *new_dentry,
386+ struct vfsmount *new_mnt)
387+{
388+ int error = 0;
389+ struct aa_profile *profile;
390+
391+ if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
392+ goto out;
393+
394+ profile = aa_get_profile(current);
395+
396+ if (profile)
397+ error = aa_link(profile, new_dentry, new_mnt,
398+ old_dentry, old_mnt);
399+
400+ aa_put_profile(profile);
401+
402+out:
403+ return error;
404+}
405+
406+static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
407+ struct vfsmount *mnt)
408+{
409+ int check = 0;
410+
411+ if (S_ISDIR(dentry->d_inode->i_mode))
412+ check |= AA_CHECK_DIR;
413+ return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
414+ check);
415+}
416+
417+static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
418+ struct vfsmount *mnt, const char *old_name)
419+{
420+ return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
421+}
422+
423+static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
424+ struct vfsmount *mnt, int mode, dev_t dev)
425+{
426+ return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
427+}
428+
429+static int apparmor_inode_rename(struct inode *old_dir,
430+ struct dentry *old_dentry,
431+ struct vfsmount *old_mnt,
432+ struct inode *new_dir,
433+ struct dentry *new_dentry,
434+ struct vfsmount *new_mnt)
435+{
436+ struct aa_profile *profile;
437+ int error = 0;
438+
439+ if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
440+ goto out;
441+
442+ profile = aa_get_profile(current);
443+
444+ if (profile) {
445+ struct inode *inode = old_dentry->d_inode;
446+ int check = 0;
447+
448+ if (inode && S_ISDIR(inode->i_mode))
449+ check |= AA_CHECK_DIR;
450+ if (old_mnt)
451+ error = aa_perm(profile, "inode_rename", old_dentry,
452+ old_mnt, MAY_READ | MAY_WRITE, check);
453+
454+ if (!error && new_mnt) {
455+ error = aa_perm(profile, "inode_rename", new_dentry,
456+ new_mnt, MAY_WRITE, check);
457+ }
458+ }
459+
460+ aa_put_profile(profile);
461+
462+out:
463+ return error;
464+}
465+
466+static int apparmor_inode_permission(struct inode *inode, int mask,
467+ struct nameidata *nd)
468+{
469+ int check = 0;
470+
471+ if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
472+ return 0;
473+ mask = aa_mask_permissions(mask);
474+ if (S_ISDIR(inode->i_mode)) {
475+ check |= AA_CHECK_DIR;
476+ /* allow traverse accesses to directories */
477+ mask &= ~MAY_EXEC;
478+ }
479+ return aa_permission("inode_permission", inode, nd->dentry, nd->mnt,
480+ mask, check);
481+}
482+
483+static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
484+ struct iattr *iattr)
485+{
486+ int error = 0;
487+
488+ if (!mnt)
489+ goto out;
490+
491+ if (mediated_filesystem(dentry->d_inode)) {
492+ struct aa_profile *profile;
493+
494+ profile = aa_get_profile(current);
495+ /*
496+ * Mediate any attempt to change attributes of a file
497+ * (chmod, chown, chgrp, etc)
498+ */
499+ if (profile)
500+ error = aa_attr(profile, dentry, mnt, iattr);
501+
502+ aa_put_profile(profile);
503+ }
504+
505+out:
506+ return error;
507+}
508+
509+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
510+ const char *operation, int mask,
511+ struct file *file)
512+{
513+ int error = 0;
514+
515+ if (mnt && mediated_filesystem(dentry->d_inode)) {
516+ struct aa_profile *profile = aa_get_profile(current);
517+ int check = file ? AA_CHECK_FD : 0;
518+
519+ if (profile)
520+ error = aa_perm_xattr(profile, operation, dentry, mnt,
521+ mask, check);
522+ aa_put_profile(profile);
523+ }
524+
525+ return error;
526+}
527+
528+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
529+ const char *name, const void *value,
530+ size_t size, int flags, struct file *file)
531+{
532+ int error = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
533+ file);
534+
535+ if (!error)
536+ error = aa_xattr_permission(dentry, mnt, "xattr set",
537+ MAY_WRITE, file);
538+ return error;
539+}
540+
541+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
542+ const char *name, struct file *file)
543+{
544+ return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
545+}
546+
547+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
548+ struct file *file)
549+{
550+ return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
551+}
552+
553+static int apparmor_inode_removexattr(struct dentry *dentry,
554+ struct vfsmount *mnt, const char *name,
555+ struct file *file)
556+{
557+ return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
558+ file);
559+}
560+
561+static int aa_file_permission(const char *op, struct file *file, int mask)
562+{
563+ struct aa_profile *profile;
564+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
565+ int error = 0;
566+
567+ if (!file_profile)
568+ goto out;
569+
570+ /*
571+ * If this file was opened under a different profile, we
572+ * revalidate the access against the current profile.
573+ */
574+ profile = aa_get_profile(current);
575+ if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
576+ struct dentry *dentry = file->f_dentry;
577+ struct vfsmount *mnt = file->f_vfsmnt;
578+ struct inode *inode = dentry->d_inode;
579+ int check = AA_CHECK_FD;
580+
581+ /*
582+ * FIXME: We should remember which profiles we revalidated
583+ * against.
584+ */
585+ if (S_ISDIR(inode->i_mode))
586+ check |= AA_CHECK_DIR;
587+ error = aa_permission(op, inode, dentry, mnt, mask, check);
588+ }
589+ aa_put_profile(profile);
590+
591+out:
592+ return error;
593+}
594+
595+static int apparmor_file_permission(struct file *file, int mask)
596+{
597+ return aa_file_permission("file_permission", file,
598+ aa_mask_permissions(mask));
599+}
600+
601+static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
602+{
603+ int mask = AA_MAY_LOCK;
604+ if (cmd == F_WRLCK)
605+ mask |= MAY_WRITE;
606+ return aa_file_permission("file_lock", file, mask);
607+}
608+
609+static int apparmor_file_alloc_security(struct file *file)
610+{
611+ struct aa_profile *profile;
612+
613+ profile = aa_get_profile(current);
614+ if (profile)
615+ file->f_security = profile;
616+
617+ return 0;
618+}
619+
620+static void apparmor_file_free_security(struct file *file)
621+{
622+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
623+
624+ aa_put_profile(file_profile);
625+}
626+
627+static inline int aa_mmap(struct file *file, const char *operation,
628+ unsigned long prot, unsigned long flags)
629+{
630+ struct dentry *dentry;
631+ int mask = 0;
632+
633+ if (!file || !file->f_security)
634+ return 0;
635+
636+ if (prot & PROT_READ)
637+ mask |= MAY_READ;
638+ /* Private mappings don't require write perms since they don't
639+ * write back to the files */
640+ if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
641+ mask |= MAY_WRITE;
642+ if (prot & PROT_EXEC)
643+ mask |= AA_EXEC_MMAP;
644+
645+ dentry = file->f_dentry;
646+ return aa_permission(operation, dentry->d_inode, dentry,
647+ file->f_vfsmnt, mask, AA_CHECK_FD);
648+}
649+
650+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
651+ unsigned long prot, unsigned long flags,
652+ unsigned long addr, unsigned long addr_only)
653+{
654+ if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
655+ struct aa_profile *profile = aa_get_profile(current);
656+ if (profile)
657+ /* future control check here */
658+ return -EACCES;
659+ else
660+ return -EACCES;
661+ aa_put_profile(profile);
662+ }
663+
664+ return aa_mmap(file, "file_mmap", prot, flags);
665+}
666+
667+static int apparmor_file_mprotect(struct vm_area_struct *vma,
668+ unsigned long reqprot, unsigned long prot)
669+{
670+ return aa_mmap(vma->vm_file, "file_mprotect", prot,
671+ !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
672+}
673+
674+static int apparmor_task_alloc_security(struct task_struct *task)
675+{
676+ return aa_clone(task);
677+}
678+
679+/*
680+ * Called from IRQ context from RCU callback.
681+ */
682+static void apparmor_task_free_security(struct task_struct *task)
683+{
684+ aa_release(task);
685+}
686+
687+static int apparmor_getprocattr(struct task_struct *task, char *name,
688+ char **value)
689+{
690+ unsigned len;
691+ int error;
692+ struct aa_profile *profile;
693+
694+ /* AppArmor only supports the "current" process attribute */
695+ if (strcmp(name, "current") != 0)
696+ return -EINVAL;
697+
698+ /* must be task querying itself or admin */
699+ if (current != task && !capable(CAP_SYS_ADMIN))
700+ return -EPERM;
701+
702+ profile = aa_get_profile(task);
703+ error = aa_getprocattr(profile, value, &len);
704+ aa_put_profile(profile);
705+ if (!error)
706+ error = len;
707+
708+ return error;
709+}
710+
711+static int apparmor_setprocattr(struct task_struct *task, char *name,
712+ void *value, size_t size)
713+{
714+ char *command, *args;
715+ int error;
716+
717+ if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
718+ return -EINVAL;
719+ args = value;
720+ args[size] = '\0';
721+ args = strstrip(args);
722+ command = strsep(&args, " ");
723+ if (!args)
724+ return -EINVAL;
725+ while (isspace(*args))
726+ args++;
727+ if (!*args)
728+ return -EINVAL;
729+
730+ if (strcmp(command, "changehat") == 0) {
731+ if (current != task)
732+ return -EACCES;
733+ error = aa_setprocattr_changehat(args);
734+ } else if (strcmp(command, "changeprofile") == 0) {
735+ if (current != task)
736+ return -EACCES;
737+ error = aa_setprocattr_changeprofile(args);
738+ } else if (strcmp(command, "setprofile") == 0) {
739+ struct aa_profile *profile;
740+
741+ /* Only an unconfined process with admin capabilities
742+ * may change the profile of another task.
743+ */
744+
745+ if (!capable(CAP_SYS_ADMIN))
746+ return -EACCES;
747+
748+ profile = aa_get_profile(current);
749+ if (profile) {
750+ struct aa_audit sa;
751+ memset(&sa, 0, sizeof(sa));
752+ sa.operation = "profile_set";
753+ sa.gfp_mask = GFP_KERNEL;
754+ sa.task = task->pid;
755+ sa.info = "from confined process";
756+ aa_audit_reject(profile, &sa);
757+ aa_put_profile(profile);
758+ return -EACCES;
759+ }
760+ error = aa_setprocattr_setprofile(task, args);
761+ } else {
762+ struct aa_audit sa;
763+ memset(&sa, 0, sizeof(sa));
764+ sa.operation = "setprocattr";
765+ sa.gfp_mask = GFP_KERNEL;
766+ sa.info = "invalid command";
767+ sa.name = command;
768+ sa.task = task->pid;
769+ aa_audit_reject(NULL, &sa);
770+ return -EINVAL;
771+ }
772+
773+ if (!error)
774+ error = size;
775+ return error;
776+}
777+
778+struct security_operations apparmor_ops = {
779+ .ptrace = apparmor_ptrace,
780+ .capget = cap_capget,
781+ .capset_check = cap_capset_check,
782+ .capset_set = cap_capset_set,
783+ .sysctl = apparmor_sysctl,
784+ .capable = apparmor_capable,
785+ .syslog = cap_syslog,
786+
787+ .netlink_send = cap_netlink_send,
788+ .netlink_recv = cap_netlink_recv,
789+
790+ .bprm_apply_creds = cap_bprm_apply_creds,
791+ .bprm_set_security = apparmor_bprm_set_security,
792+ .bprm_secureexec = apparmor_bprm_secureexec,
793+
794+ .sb_mount = apparmor_sb_mount,
795+ .sb_umount = apparmor_umount,
796+
797+ .inode_mkdir = apparmor_inode_mkdir,
798+ .inode_rmdir = apparmor_inode_rmdir,
799+ .inode_create = apparmor_inode_create,
800+ .inode_link = apparmor_inode_link,
801+ .inode_unlink = apparmor_inode_unlink,
802+ .inode_symlink = apparmor_inode_symlink,
803+ .inode_mknod = apparmor_inode_mknod,
804+ .inode_rename = apparmor_inode_rename,
805+ .inode_permission = apparmor_inode_permission,
806+ .inode_setattr = apparmor_inode_setattr,
807+ .inode_setxattr = apparmor_inode_setxattr,
808+ .inode_getxattr = apparmor_inode_getxattr,
809+ .inode_listxattr = apparmor_inode_listxattr,
810+ .inode_removexattr = apparmor_inode_removexattr,
811+ .file_permission = apparmor_file_permission,
812+ .file_alloc_security = apparmor_file_alloc_security,
813+ .file_free_security = apparmor_file_free_security,
814+ .file_mmap = apparmor_file_mmap,
815+ .file_mprotect = apparmor_file_mprotect,
816+ .file_lock = apparmor_file_lock,
817+
818+ .task_alloc_security = apparmor_task_alloc_security,
819+ .task_free_security = apparmor_task_free_security,
820+ .task_post_setuid = cap_task_post_setuid,
821+ .task_reparent_to_init = cap_task_reparent_to_init,
822+
823+ .getprocattr = apparmor_getprocattr,
824+ .setprocattr = apparmor_setprocattr,
825+};
826+
827+void info_message(const char *str)
828+{
829+ struct aa_audit sa;
830+ memset(&sa, 0, sizeof(sa));
831+ sa.gfp_mask = GFP_KERNEL;
832+ sa.info = str;
833+ printk(KERN_INFO "AppArmor: %s\n", str);
834+ if (audit_enabled)
835+ aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
836+}
837+
838+static int __init apparmor_init(void)
839+{
840+ int error;
841+
842+ if (!apparmor_enabled) {
843+ info_message("AppArmor disabled by boottime parameter\n");
844+ return 0;
845+ }
846+
847+ if ((error = create_apparmorfs())) {
848+ AA_ERROR("Unable to activate AppArmor filesystem\n");
849+ goto createfs_out;
850+ }
851+
852+ if ((error = alloc_default_namespace())){
853+ AA_ERROR("Unable to allocate default profile namespace\n");
854+ goto alloc_out;
855+ }
856+
857+ if ((error = register_security(&apparmor_ops))) {
858+ AA_ERROR("Unable to register AppArmor\n");
859+ goto register_security_out;
860+ }
861+
862+ /* Report that AppArmor successfully initialized */
863+ apparmor_initialized = 1;
864+ if (apparmor_complain)
865+ info_message("AppArmor initialized: complainmode enabled");
866+ else
867+ info_message("AppArmor initialized");
868+
869+ return error;
870+
871+register_security_out:
872+ free_default_namespace();
873+
874+alloc_out:
875+ destroy_apparmorfs();
876+
877+createfs_out:
878+ return error;
879+
880+}
881+
882+security_initcall(apparmor_init);
883+
884+void apparmor_disable(void)
885+{
886+ /* Remove and release all the profiles on the profile list. */
887+ mutex_lock(&aa_interface_lock);
888+ aa_profile_ns_list_release();
889+
890+ /* FIXME: cleanup profiles references on files */
891+ free_default_namespace();
892+
893+ /*
894+ * Delay for an rcu cycle to make sure that all active task
895+ * context readers have finished, and all profiles have been
896+ * freed by their rcu callbacks.
897+ */
898+ synchronize_rcu();
899+
900+ destroy_apparmorfs();
901+ mutex_unlock(&aa_interface_lock);
902+
903+ apparmor_initialized = 0;
904+
905+ info_message("AppArmor protection removed");
906+}
907+
908+MODULE_DESCRIPTION("AppArmor process confinement");
909+MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
910+MODULE_LICENSE("GPL");