2 include/linux/audit.h | 5
3 include/linux/mnt_namespace.h | 3
7 security/apparmor/Kbuild | 10
8 security/apparmor/Kconfig | 9
9 security/apparmor/Makefile | 28
10 security/apparmor/apparmor.h | 356 +++++
11 security/apparmor/apparmorfs.c | 432 +++++++
12 security/apparmor/capabilities.c | 71 +
13 security/apparmor/inline.h | 393 ++++++
14 security/apparmor/list.c | 268 ++++
15 security/apparmor/lsm.c | 894 ++++++++++++++
16 security/apparmor/main.c | 1702 ++++++++++++++++++++++++++++
17 security/apparmor/match/Kbuild | 6
18 security/apparmor/match/Makefile | 5
19 security/apparmor/match/match.h | 132 ++
20 security/apparmor/match/match_default.c | 57
21 security/apparmor/match/match_pcre.c | 169 ++
22 security/apparmor/match/pcre_exec.c | 1945 ++++++++++++++++++++++++++++++++
23 security/apparmor/match/pcre_exec.h | 308 +++++
24 security/apparmor/match/pcre_tables.h | 184 +++
25 security/apparmor/module_interface.c | 845 +++++++++++++
26 security/apparmor/module_interface.h | 37
27 security/apparmor/procattr.c | 332 +++++
28 security/apparmor/shared.h | 46
29 28 files changed, 8245 insertions(+), 3 deletions(-)
30 Index: b/include/linux/audit.h
31 ===================================================================
32 --- a/include/linux/audit.h
33 +++ b/include/linux/audit.h
35 #define AUDIT_LAST_KERN_ANOM_MSG 1799
36 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
38 +#define AUDIT_SD 1500 /* AppArmor (SubDomain) audit */
40 #define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
43 @@ -478,6 +480,9 @@ extern void audit_log(struct audit_
44 __attribute__((format(printf,4,5)));
46 extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
47 +extern void audit_log_vformat(struct audit_buffer *ab,
48 + const char *fmt, va_list args)
49 + __attribute__((format(printf,2,0)));
50 extern void audit_log_format(struct audit_buffer *ab,
52 __attribute__((format(printf,2,3)));
53 Index: b/kernel/audit.c
54 ===================================================================
57 @@ -956,8 +956,7 @@ static inline int audit_expand(struct au
58 * will be called a second time. Currently, we assume that a printk
59 * can't format message larger than 1024 bytes, so we don't either.
61 -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
63 +void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
67 @@ -1213,3 +1212,6 @@ EXPORT_SYMBOL(audit_log_start);
68 EXPORT_SYMBOL(audit_log_end);
69 EXPORT_SYMBOL(audit_log_format);
70 EXPORT_SYMBOL(audit_log);
71 +EXPORT_SYMBOL_GPL(audit_log_vformat);
72 +EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
73 +EXPORT_SYMBOL_GPL(audit_log_d_path);
74 Index: b/fs/namespace.c
75 ===================================================================
78 @@ -37,7 +37,8 @@ static int event;
79 static struct list_head *mount_hashtable __read_mostly;
80 static int hash_mask __read_mostly, hash_bits __read_mostly;
81 static struct kmem_cache *mnt_cache __read_mostly;
82 -static struct rw_semaphore namespace_sem;
83 +struct rw_semaphore namespace_sem;
84 +EXPORT_SYMBOL_GPL(namespace_sem);
87 decl_subsys(fs, NULL, NULL);
88 Index: b/include/linux/mnt_namespace.h
89 ===================================================================
90 --- a/include/linux/mnt_namespace.h
91 +++ b/include/linux/mnt_namespace.h
93 #include <linux/sched.h>
94 #include <linux/nsproxy.h>
96 +/* exported for AppArmor (SubDomain) */
97 +extern struct rw_semaphore namespace_sem;
99 struct mnt_namespace {
101 struct vfsmount * root;
102 Index: b/security/Makefile
103 ===================================================================
104 --- a/security/Makefile
105 +++ b/security/Makefile
108 obj-$(CONFIG_KEYS) += keys/
109 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
110 +obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
112 # if we don't select a security model, use the default capabilities
113 ifneq ($(CONFIG_SECURITY),y)
114 Index: b/security/Kconfig
115 ===================================================================
116 --- a/security/Kconfig
117 +++ b/security/Kconfig
118 @@ -94,6 +94,7 @@ config SECURITY_ROOTPLUG
119 If you are unsure how to answer this question, answer N.
121 source security/selinux/Kconfig
122 +source security/apparmor/Kconfig
126 Index: b/security/apparmor/Kbuild
127 ===================================================================
129 +++ b/security/apparmor/Kbuild
131 +# Makefile for AppArmor Linux Security Module
133 +EXTRA_CFLAGS += -DAPPARMOR_VERSION=\"${APPARMOR_VER}\"
135 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
137 +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o capabilities.o \
140 +obj-$(CONFIG_SECURITY_APPARMOR) += match/
141 Index: b/security/apparmor/Kconfig
142 ===================================================================
144 +++ b/security/apparmor/Kconfig
146 +config SECURITY_APPARMOR
147 + tristate "AppArmor support"
148 + depends on SECURITY!=n
150 + This enables the AppArmor security module.
151 + Required userspace tools (if they are not included in your
152 + distribution) and further information may be found at
153 + <http://forge.novell.com/modules/xfmod/project/?apparmor>
154 + If you are unsure how to answer this question, answer N.
155 Index: b/security/apparmor/Makefile
156 ===================================================================
158 +++ b/security/apparmor/Makefile
160 +# Makefile for AppArmor Linux Security Module
162 +# kernel build Makefile is the Kbuild file
164 +REPO_VERSION := $(shell if [ -x /usr/bin/svn ] ; then \
165 + /usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
168 +ifeq ("${REPO_VERSION}", "")
169 +REPO_VERSION := "unknown"
172 +KERNELVER := $(shell uname -r)
174 +KERNELDIR := /lib/modules/${KERNELVER}/build
177 + $(MAKE) -C $(KERNELDIR) M=`pwd` modules CONFIG_SECURITY_APPARMOR=m \
178 + APPARMOR_VER=${REPO_VERSION}
179 + mv apparmor.ko apparmor-${KERNELVER}.ko
180 + mv match/aamatch_pcre.ko aamatch_pcre-${KERNELVER}.ko
183 + rm -f *~ *.o *.ko *.mod.c .*.cmd Module{s,}.symvers \
184 + match/*~ match/*.o match/*.ko match/.*.cmd match/*.mod.c
185 + rm -rf .tmp_versions
188 Index: b/security/apparmor/apparmor.h
189 ===================================================================
191 +++ b/security/apparmor/apparmor.h
194 + * Copyright (C) 1998-2005 Novell/SUSE
196 + * This program is free software; you can redistribute it and/or
197 + * modify it under the terms of the GNU General Public License as
198 + * published by the Free Software Foundation, version 2 of the
201 + * AppArmor internal prototypes
204 +#ifndef __APPARMOR_H
205 +#define __APPARMOR_H
207 +#include <linux/fs.h> /* Include for defn of iattr */
208 +#include <linux/binfmts.h> /* defn of linux_binprm */
209 +#include <linux/rcupdate.h>
213 +/* Control parameters (0 or 1), settable thru module/boot flags or
214 + * via /sys/kernel/security/apparmor/control */
215 +extern int apparmor_complain;
216 +extern int apparmor_debug;
217 +extern int apparmor_audit;
218 +extern int apparmor_logsyscall;
221 +#include <linux/pipe_fs_i.h>
222 +/* from net/socket.c */
223 +#define SOCKFS_MAGIC 0x534F434B
224 +/* from inotify.c */
225 +#define INOTIFYFS_MAGIC 0xBAD1DEA
227 +#define VALID_FSTYPE(inode) ((inode)->i_sb->s_magic != PIPEFS_MAGIC && \
228 + (inode)->i_sb->s_magic != SOCKFS_MAGIC && \
229 + (inode)->i_sb->s_magic != INOTIFYFS_MAGIC)
231 +#define PROFILE_COMPLAIN(_profile) \
232 + (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
234 +#define SUBDOMAIN_COMPLAIN(_sd) \
235 + (apparmor_complain == 1 || \
236 + ((_sd) && (_sd)->active && (_sd)->active->flags.complain))
238 +#define PROFILE_AUDIT(_profile) \
239 + (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
241 +#define SUBDOMAIN_AUDIT(_sd) \
242 + (apparmor_audit == 1 || \
243 + ((_sd) && (_sd)->active && (_sd)->active->flags.audit))
246 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
247 + * which is not related to profile accesses.
250 +#define AA_DEBUG(fmt, args...) \
252 + if (apparmor_debug) \
253 + printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
255 +#define AA_INFO(fmt, args...) printk(KERN_INFO "AppArmor: " fmt, ##args)
256 +#define AA_WARN(fmt, args...) printk(KERN_WARNING "AppArmor: " fmt, ##args)
257 +#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
260 +/* apparmor logged syscall reject caching */
263 + AA_SYSCALL_SYSCTL_WRITE,
268 +#define AA_SYSCALL_TO_MASK(X) (1 << (X))
271 +/* basic AppArmor data structures */
279 +enum entry_match_type {
286 +/* struct aa_entry - file ACL *
287 + * @filename: filename controlled by this ACL
288 + * @mode: permissions granted by ACL
289 + * @type: type of match to perform against @filename
290 + * @extradata: any extra data needed by an extended matching type
291 + * @list: list the ACL is on
292 + * @listp: permission partitioned lists this ACL is on.
294 + * Each entry describes a file and an allowed access mode.
298 + int mode; /* mode is 'or' of READ, WRITE, EXECUTE,
299 + * INHERIT, UNCONSTRAINED, and LIBRARY
300 + * (meaning don't prefetch). */
302 + enum entry_match_type type;
305 + struct list_head list;
306 + struct list_head listp[POS_AA_FILE_MAX + 1];
309 +#define AA_SECURE_EXEC_NEEDED 0x00000001
311 +#define AA_EXEC_MODIFIER_MASK(mask) ((mask) & AA_EXEC_MODIFIERS)
312 +#define AA_EXEC_MASK(mask) ((mask) & (AA_MAY_EXEC | AA_EXEC_MODIFIERS))
313 +#define AA_EXEC_UNSAFE_MASK(mask) ((mask) & (AA_MAY_EXEC | AA_EXEC_MODIFIERS |\
316 +/* struct aaprofile - basic confinement data
317 + * @parent: non refcounted pointer to parent profile
318 + * @name: the profiles name
319 + * @file_entry: file ACL
320 + * @file_entryp: vector of file ACL by permission granted
321 + * @list: list this profile is on
322 + * @sub: profiles list of subprofiles (HATS)
323 + * @flags: flags controlling profile behavior
324 + * @null_profile: if needed per profile learning and null confinement profile
325 + * @isstale: flag to indicate the profile is stale
326 + * @num_file_entries: number of file entries the profile contains
327 + * @num_file_pentries: number of file entries for each partitioned list
328 + * @capabilities: capabilities granted by the process
329 + * @rcu: rcu head used when freeing the profile
330 + * @count: reference count of the profile
332 + * The AppArmor profile contains the basic confinement data. Each profile
333 + * has a name and potentially a list of profile entries. The profiles are
334 + * connected in a list
337 + struct aaprofile *parent;
340 + struct list_head file_entry;
341 + struct list_head file_entryp[POS_AA_FILE_MAX + 1];
342 + struct list_head list;
343 + struct list_head sub;
344 + struct flagval flags;
345 + struct aaprofile *null_profile;
348 + int num_file_entries;
349 + int num_file_pentries[POS_AA_FILE_MAX + 1];
351 + kernel_cap_t capabilities;
353 + struct rcu_head rcu;
364 + * aafile - file pointer confinement data
366 + * Data structure assigned to each open file (by apparmor_file_alloc_security)
369 + enum aafile_type type;
370 + struct aaprofile *profile;
374 + * struct subdomain - primary label for confined tasks
375 + * @active: the current active profile
376 + * @hat_magic: the magic token controling the ability to leave a hat
377 + * @list: list this subdomain is on
378 + * @task: task that the subdomain confines
379 + * @cached_caps: caps that have previously generated log entries
380 + * @cached_syscalls: mediated syscalls that have previously been logged
382 + * Contains the tasks current active profile (which could change due to
383 + * change_hat). Plus the hat_magic needed during change_hat.
385 + * N.B AppArmor's previous product name SubDomain was derived from the name
386 + * of this structure/concept (changehat reducing a task into a sub-domain).
389 + struct aaprofile *active; /* The current active profile */
390 + u32 hat_magic; /* used with change_hat */
391 + struct list_head list; /* list of subdomains */
392 + struct task_struct *task;
394 + kernel_cap_t cached_caps;
395 + unsigned int cached_syscalls;
398 +typedef int (*aa_iter) (struct subdomain *, void *);
401 + * temp (cookie) data used by aa_path_* functions, see inline.h
403 +struct aa_path_data {
404 + struct dentry *root, *dentry;
405 + struct mnt_namespace *mnt_namespace;
406 + struct list_head *head, *pos;
410 +#define AA_SUBDOMAIN(sec) ((struct subdomain*)(sec))
411 +#define AA_PROFILE(sec) ((struct aaprofile*)(sec))
413 +/* Lock protecting access to 'struct subdomain' accesses */
414 +extern spinlock_t sd_lock;
416 +extern struct aaprofile *null_complain_profile;
418 +/* aa_audit - AppArmor auditing structure
419 + * Structure is populated by access control code and passed to aa_audit which
420 + * provides for a single point of logging.
424 + unsigned short type, flags;
425 + unsigned int result;
438 +#define AA_AUDITTYPE_FILE 1
439 +#define AA_AUDITTYPE_DIR 2
440 +#define AA_AUDITTYPE_ATTR 3
441 +#define AA_AUDITTYPE_XATTR 4
442 +#define AA_AUDITTYPE_LINK 5
443 +#define AA_AUDITTYPE_CAP 6
444 +#define AA_AUDITTYPE_MSG 7
445 +#define AA_AUDITTYPE_SYSCALL 8
446 +#define AA_AUDITTYPE__END 9
449 +#define AA_AUDITFLAG_AUDITSS_SYSCALL 1 /* log syscall context */
450 +#define AA_AUDITFLAG_LOGERR 2 /* log operations that failed due to
451 + non permission errors */
453 +#define HINT_UNKNOWN_HAT "unknown_hat"
454 +#define HINT_FORK "fork"
455 +#define HINT_MANDPROF "missing_mandatory_profile"
456 +#define HINT_CHGPROF "changing_profile"
458 +#define LOG_HINT(p, gfp, hint, fmt, args...) \
460 + aa_audit_message(p, gfp, 0, \
461 + "LOGPROF-HINT " hint " " fmt, ##args);\
464 +/* directory op type, for aa_perm_dir */
470 +/* xattr op type, for aa_xattr */
471 +enum aa_xattroptype {
478 +#define BASE_PROFILE(p) ((p)->parent ? (p)->parent : (p))
479 +#define IN_SUBPROFILE(p) ((p)->parent)
482 +extern int alloc_null_complain_profile(void);
483 +extern void free_null_complain_profile(void);
484 +extern int attach_nullprofile(struct aaprofile *profile);
485 +extern int aa_audit_message(struct aaprofile *active, gfp_t gfp, int,
486 + const char *, ...);
487 +extern int aa_audit_syscallreject(struct aaprofile *active, gfp_t gfp,
488 + enum aasyscall call);
489 +extern int aa_audit(struct aaprofile *active, const struct aa_audit *);
490 +extern char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt);
492 +extern int aa_attr(struct aaprofile *active, struct dentry *dentry,
493 + struct iattr *iattr);
494 +extern int aa_xattr(struct aaprofile *active, struct dentry *dentry,
495 + const char *xattr, enum aa_xattroptype xattroptype);
496 +extern int aa_capability(struct aaprofile *active, int cap);
497 +extern int aa_perm(struct aaprofile *active, struct dentry *dentry,
498 + struct vfsmount *mnt, int mask);
499 +extern int aa_perm_nameidata(struct aaprofile *active, struct nameidata *nd,
501 +extern int aa_perm_dentry(struct aaprofile *active, struct dentry *dentry,
503 +extern int aa_perm_dir(struct aaprofile *active, struct dentry *dentry,
504 + enum aa_diroptype diroptype);
505 +extern int aa_link(struct aaprofile *active,
506 + struct dentry *link, struct dentry *target);
507 +extern int aa_fork(struct task_struct *p);
508 +extern int aa_register(struct linux_binprm *bprm);
509 +extern void aa_release(struct task_struct *p);
510 +extern int aa_change_hat(const char *id, u32 hat_magic);
511 +extern int aa_associate_filp(struct file *filp);
514 +extern struct aaprofile *aa_profilelist_find(const char *name);
515 +extern int aa_profilelist_add(struct aaprofile *profile);
516 +extern struct aaprofile *aa_profilelist_remove(const char *name);
517 +extern void aa_profilelist_release(void);
518 +extern struct aaprofile *aa_profilelist_replace(struct aaprofile *profile);
519 +extern void aa_profile_dump(struct aaprofile *);
520 +extern void aa_profilelist_dump(void);
521 +extern void aa_subdomainlist_add(struct subdomain *);
522 +extern void aa_subdomainlist_remove(struct subdomain *);
523 +extern void aa_subdomainlist_iterate(aa_iter, void *);
524 +extern void aa_subdomainlist_iterateremove(aa_iter, void *);
525 +extern void aa_subdomainlist_release(void);
527 +/* module_interface.c */
528 +extern ssize_t aa_file_prof_add(void *, size_t);
529 +extern ssize_t aa_file_prof_repl(void *, size_t);
530 +extern ssize_t aa_file_prof_remove(const char *, size_t);
531 +extern void free_aaprofile(struct aaprofile *profile);
532 +extern void free_aaprofile_kref(struct kref *kref);
535 +extern size_t aa_getprocattr(struct aaprofile *active, char *str, size_t size);
536 +extern int aa_setprocattr_changehat(char *hatinfo, size_t infosize);
537 +extern int aa_setprocattr_setprofile(struct task_struct *p, char *profilename,
538 + size_t profilesize);
541 +extern int create_apparmorfs(void);
542 +extern void destroy_apparmorfs(void);
544 +/* capabilities.c */
545 +extern const char *capability_to_name(unsigned int cap);
546 +extern const char *syscall_to_name(enum aasyscall call);
548 +#endif /* __APPARMOR_H */
549 Index: b/security/apparmor/apparmorfs.c
550 ===================================================================
552 +++ b/security/apparmor/apparmorfs.c
555 + * Copyright (C) 2005 Novell/SUSE
557 + * This program is free software; you can redistribute it and/or
558 + * modify it under the terms of the GNU General Public License as
559 + * published by the Free Software Foundation, version 2 of the
562 + * AppArmor filesystem (part of securityfs)
565 +#include <linux/security.h>
566 +#include <linux/vmalloc.h>
567 +#include <linux/module.h>
568 +#include <linux/seq_file.h>
569 +#include <asm/uaccess.h>
571 +#include "apparmor.h"
573 +#include "match/match.h"
575 +#define SECFS_AA "apparmor"
576 +static struct dentry *aafs_dentry = NULL;
579 +extern struct seq_operations apparmorfs_profiles_op;
580 +static int aa_prof_open(struct inode *inode, struct file *file);
581 +static int aa_prof_release(struct inode *inode, struct file *file);
583 +static struct file_operations apparmorfs_profiles_fops = {
584 + .open = aa_prof_open,
586 + .llseek = seq_lseek,
587 + .release = aa_prof_release,
591 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
592 + size_t size, loff_t *ppos);
594 +static struct file_operations apparmorfs_matching_fops = {
595 + .read = aa_matching_read,
600 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
601 + size_t size, loff_t *pos);
602 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
603 + size_t size, loff_t *pos);
604 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
605 + size_t size, loff_t *pos);
607 +static struct file_operations apparmorfs_profile_load = {
608 + .write = aa_profile_load
611 +static struct file_operations apparmorfs_profile_replace = {
612 + .write = aa_profile_replace
615 +static struct file_operations apparmorfs_profile_remove = {
616 + .write = aa_profile_remove
621 +static u64 aa_control_get(void *data);
622 +static void aa_control_set(void *data, u64 val);
624 +DEFINE_SIMPLE_ATTRIBUTE(apparmorfs_control_fops, aa_control_get,
625 + aa_control_set, "%lld\n");
629 +/* table of static entries */
631 +static struct root_entry {
635 + struct file_operations *fops;
638 + /* internal fields */
639 + struct dentry *dentry;
641 +} root_entries[] = {
642 + /* our root, normally /sys/kernel/security/apparmor */
643 + {SECFS_AA, S_IFDIR, 0550}, /* DO NOT EDIT/MOVE */
645 + /* interface for obtaining list of profiles currently loaded */
646 + {"profiles", S_IFREG, 0440, &apparmorfs_profiles_fops,
649 + /* interface for obtaining matching features supported */
650 + {"matching", S_IFREG, 0440, &apparmorfs_matching_fops,
653 + /* interface for loading/removing/replacing profiles */
654 + {".load", S_IFREG, 0640, &apparmorfs_profile_load,
656 + {".replace", S_IFREG, 0640, &apparmorfs_profile_replace,
658 + {".remove", S_IFREG, 0640, &apparmorfs_profile_remove,
661 + /* interface for setting binary config values */
662 + {"control", S_IFDIR, 0550},
663 + {"complain", S_IFREG, 0640, &apparmorfs_control_fops,
664 + &apparmor_complain},
665 + {"audit", S_IFREG, 0640, &apparmorfs_control_fops,
667 + {"debug", S_IFREG, 0640, &apparmorfs_control_fops,
669 + {"logsyscall", S_IFREG, 0640, &apparmorfs_control_fops,
670 + &apparmor_logsyscall},
671 + {NULL, S_IFDIR, 0},
677 +#define AAFS_DENTRY root_entries[0].dentry
679 +static const unsigned int num_entries =
680 + sizeof(root_entries) / sizeof(struct root_entry);
684 +static int aa_prof_open(struct inode *inode, struct file *file)
686 + return seq_open(file, &apparmorfs_profiles_op);
690 +static int aa_prof_release(struct inode *inode, struct file *file)
692 + return seq_release(inode, file);
695 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
696 + size_t size, loff_t *ppos)
698 + const char *matching = aamatch_features();
700 + return simple_read_from_buffer(buf, size, ppos, matching,
704 +static char *aa_simple_write_to_buffer(const char __user *userbuf,
705 + size_t alloc_size, size_t copy_size,
706 + loff_t *pos, const char *msg)
708 + struct aaprofile *active;
712 + /* only writes from pos 0, that is complete writes */
713 + data = ERR_PTR(-ESPIPE);
717 + /* Don't allow confined processes to load/replace/remove profiles.
718 + * No sane person would add rules allowing this to a profile
719 + * but we enforce the restriction anyways.
722 + active = get_activeptr_rcu();
724 + AA_WARN("REJECTING access to profile %s (%s(%d) "
725 + "profile %s active %s)\n",
726 + msg, current->comm, current->pid,
727 + BASE_PROFILE(active)->name, active->name);
729 + data = ERR_PTR(-EPERM);
734 + data = vmalloc(alloc_size);
735 + if (data == NULL) {
736 + data = ERR_PTR(-ENOMEM);
740 + if (copy_from_user(data, userbuf, copy_size)) {
742 + data = ERR_PTR(-EFAULT);
750 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
751 + size_t size, loff_t *pos)
756 + data = aa_simple_write_to_buffer(buf, size, size, pos, "load");
758 + if (!IS_ERR(data)) {
759 + error = aa_file_prof_add(data, size);
762 + error = PTR_ERR(data);
768 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
769 + size_t size, loff_t *pos)
774 + data = aa_simple_write_to_buffer(buf, size, size, pos, "replacement");
776 + if (!IS_ERR(data)) {
777 + error = aa_file_prof_repl(data, size);
780 + error = PTR_ERR(data);
786 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
787 + size_t size, loff_t *pos)
792 + /* aa_file_prof_remove needs a null terminated string so 1 extra
793 + * byte is allocated and null the copied data is then null terminated
795 + data = aa_simple_write_to_buffer(buf, size+1, size, pos, "removal");
797 + if (!IS_ERR(data)) {
799 + error = aa_file_prof_remove(data, size);
802 + error = PTR_ERR(data);
808 +static u64 aa_control_get(void *data)
810 + return *(int *)data;
813 +static void aa_control_set(void *data, u64 val)
818 + *(int*)data = (int)val;
821 +static void clear_apparmorfs(void)
825 + for (i=0; i < num_entries;i++) {
826 + unsigned int index;
828 + if (root_entries[i].mode == S_IFDIR) {
829 + if (root_entries[i].name)
830 + /* defer dir free till all sub-entries freed */
833 + /* cleanup parent */
834 + index = root_entries[i].parent_index;
839 + if (root_entries[index].dentry) {
840 + securityfs_remove(root_entries[index].dentry);
842 + AA_DEBUG("%s: deleted apparmorfs entry name=%s "
845 + root_entries[index].name,
846 + root_entries[index].dentry);
848 + root_entries[index].dentry = NULL;
849 + root_entries[index].parent_index = 0;
854 +static int populate_apparmorfs(struct dentry *root)
856 + unsigned int i, parent_index, depth;
858 + for (i = 0; i < num_entries; i++) {
859 + root_entries[i].dentry = NULL;
860 + root_entries[i].parent_index = 0;
863 + /* 1. Verify entry 0 is valid [sanity check] */
864 + if (num_entries == 0 ||
865 + !root_entries[0].name ||
866 + strcmp(root_entries[0].name, SECFS_AA) != 0 ||
867 + root_entries[0].mode != S_IFDIR) {
868 + AA_ERROR("%s: root entry 0 is not SECFS_AA/dir\n",
873 + /* 2. Build back pointers */
877 + for (i = 1; i < num_entries; i++) {
878 + root_entries[i].parent_index = parent_index;
880 + if (root_entries[i].name &&
881 + root_entries[i].mode == S_IFDIR) {
884 + } else if (!root_entries[i].name) {
885 + if (root_entries[i].mode != S_IFDIR || depth == 0) {
886 + AA_ERROR("%s: root_entry %d invalid (%u %d)",
888 + root_entries[i].mode,
889 + root_entries[i].parent_index);
894 + parent_index = root_entries[parent_index].parent_index;
899 + AA_ERROR("%s: root_entry table not correctly terminated\n",
904 + /* 3. Create root (parent=NULL) */
905 + root_entries[0].dentry = securityfs_create_file(
906 + root_entries[0].name,
907 + root_entries[0].mode |
908 + root_entries[0].access,
911 + if (IS_ERR(root_entries[0].dentry))
914 + AA_DEBUG("%s: created securityfs/apparmor [dentry=%p]\n",
915 + __FUNCTION__, root_entries[0].dentry);
918 + /* 4. create remaining nodes */
919 + for (i = 1; i < num_entries; i++) {
920 + struct dentry *parent;
922 + struct file_operations *fops = NULL;
924 + /* end of directory ? */
925 + if (!root_entries[i].name)
928 + parent = root_entries[root_entries[i].parent_index].dentry;
930 + if (root_entries[i].mode != S_IFDIR) {
931 + data = root_entries[i].data;
932 + fops = root_entries[i].fops;
935 + root_entries[i].dentry = securityfs_create_file(
936 + root_entries[i].name,
937 + root_entries[i].mode |
938 + root_entries[i].access,
943 + if (IS_ERR(root_entries[i].dentry))
944 + goto cleanup_error;
946 + AA_DEBUG("%s: added apparmorfs entry "
947 + "name=%s mode=%x dentry=%p [parent %p]\n",
948 + __FUNCTION__, root_entries[i].name,
949 + root_entries[i].mode|root_entries[i].access,
950 + root_entries[i].dentry, parent);
956 + clear_apparmorfs();
962 +int create_apparmorfs(void)
968 + AA_ERROR("%s: AppArmor securityfs already exists\n",
971 + error = populate_apparmorfs(aafs_dentry);
973 + AA_ERROR("%s: Error populating AppArmor securityfs\n",
981 +void destroy_apparmorfs(void)
984 + clear_apparmorfs();
986 Index: b/security/apparmor/capabilities.c
987 ===================================================================
989 +++ b/security/apparmor/capabilities.c
992 + * Copyright (C) 2005 Novell/SUSE
994 + * This program is free software; you can redistribute it and/or
995 + * modify it under the terms of the GNU General Public License as
996 + * published by the Free Software Foundation, version 2 of the
999 + * AppArmor capability definitions
1002 +#include "apparmor.h"
1004 +static const char *cap_names[] = {
1007 + "dac_read_search",
1014 + "linux_immutable",
1015 + "net_bind_service",
1038 +const char *capability_to_name(unsigned int cap)
1042 + name = (cap < (sizeof(cap_names) / sizeof(char *))
1043 + ? cap_names[cap] : "invalid-capability");
1048 +static const char *syscall_names[] = {
1055 +const char *syscall_to_name(enum aasyscall call)
1058 + name = (call < (sizeof(syscall_names) / sizeof(char *))
1059 + ? syscall_names[call] : "invalid-syscall");
1062 Index: b/security/apparmor/inline.h
1063 ===================================================================
1065 +++ b/security/apparmor/inline.h
1068 + * Copyright (C) 2005 Novell/SUSE
1070 + * This program is free software; you can redistribute it and/or
1071 + * modify it under the terms of the GNU General Public License as
1072 + * published by the Free Software Foundation, version 2 of the
1079 +#include <linux/mnt_namespace.h>
1081 +static inline int __aa_is_confined(struct subdomain *sd)
1083 + return (sd && sd->active);
1088 + * Determine whether current task contains a valid profile (confined).
1089 + * Return %1 if confined, %0 otherwise.
1091 +static inline int aa_is_confined(void)
1093 + struct subdomain *sd = AA_SUBDOMAIN(current->security);
1094 + return __aa_is_confined(sd);
1097 +static inline int __aa_sub_defined(struct subdomain *sd)
1099 + return __aa_is_confined(sd) && !list_empty(&BASE_PROFILE(sd->active)->sub);
1103 + * aa_sub_defined - check to see if current task has any subprofiles
1104 + * Return 1 if true, 0 otherwise
1106 +static inline int aa_sub_defined(void)
1108 + struct subdomain *sd = AA_SUBDOMAIN(current->security);
1109 + return __aa_sub_defined(sd);
1113 + * get_aaprofile - increment refcount on profile @p
1116 +static inline struct aaprofile *get_aaprofile(struct aaprofile *p)
1119 + kref_get(&(BASE_PROFILE(p)->count));
1125 + * put_aaprofile - decrement refcount on profile @p
1128 +static inline void put_aaprofile(struct aaprofile *p)
1131 + kref_put(&BASE_PROFILE(p)->count, free_aaprofile_kref);
1135 + * get_task_activeptr_rcu - get pointer to @tsk's active profile.
1136 + * @tsk: task to get active profile from
1138 + * Requires rcu_read_lock is held
1140 +static inline struct aaprofile *get_task_activeptr_rcu(struct task_struct *tsk)
1142 + struct subdomain *sd = AA_SUBDOMAIN(tsk->security);
1143 + struct aaprofile *active = NULL;
1146 + active = (struct aaprofile *) rcu_dereference(sd->active);
1152 + * get_activeptr_rcu - get pointer to current task's active profile
1153 + * Requires rcu_read_lock is held
1155 +static inline struct aaprofile *get_activeptr_rcu(void)
1157 + return get_task_activeptr_rcu(current);
1161 + * get_task_active_aaprofile - get a reference to tsk's active profile.
1162 + * @tsk: the task to get the active profile reference for
1164 +static inline struct aaprofile *get_task_active_aaprofile(struct task_struct *tsk)
1166 + struct aaprofile *active;
1169 + active = get_aaprofile(get_task_activeptr_rcu(tsk));
1170 + rcu_read_unlock();
1176 + * get_active_aaprofile - get a reference to the current tasks active profile
1178 +static inline struct aaprofile *get_active_aaprofile(void)
1180 + return get_task_active_aaprofile(current);
1184 + * cap_is_cached - check if @cap access has already been logged for current
1185 + * @cap: capability to test if cached
1187 +static inline int cap_is_cached(int cap)
1189 + struct subdomain *sd = AA_SUBDOMAIN(current->security);
1190 + return cap_raised(sd->cached_caps, cap);
1194 + * add_to_cached_caps - add a capability to the tasks logged capabilities cache
1195 + * @cap: the capability to add
1197 +static inline void add_to_cached_caps(int cap)
1199 + struct subdomain *sd = AA_SUBDOMAIN(current->security);
1200 + sd->cached_caps = cap_combine(sd->cached_caps, CAP_TO_MASK(cap));
1204 + * clear_cached_caps - clear the tasks logged capabilities cache
1206 +static inline void clear_cached_caps(struct subdomain *sd)
1208 + sd->cached_caps = CAP_EMPTY_SET;
1212 + * syscall_is_cached - check if @call access has already been logged
1213 + * @call: syscall to test if cached
1215 +static inline int syscall_is_cached(enum aasyscall call)
1217 + struct subdomain *sd = AA_SUBDOMAIN(current->security);
1218 + return sd->cached_syscalls & AA_SYSCALL_TO_MASK(call);
1222 + * add_to_cached_syscalls - add a syscall to the tasks logged syscalls cache
1223 + * @call: the syscall to add
1225 +static inline void add_to_cached_syscalls(enum aasyscall call)
1227 + struct subdomain *sd = AA_SUBDOMAIN(current->security);
1228 + sd->cached_syscalls |= AA_SYSCALL_TO_MASK(call);
1232 + * clear_cached_syscalls - clear the tasks logged syscalls cache
1234 +static inline void clear_cached_syscalls(struct subdomain *sd)
1236 + sd->cached_syscalls = 0;
1240 + * aa_switch - change subdomain to use a new profile
1241 + * @sd: subdomain to switch the active profile on
1242 + * @newactive: new active profile
1244 + * aa_switch handles the changing of a subdomain's active profile. The
1245 + * sd_lock must be held to ensure consistency against other writers.
1246 + * Some write paths (ex. aa_register) require sd->active not to change
1247 + * over several operations, so the calling function is responsible
1248 + * for grabing the sd_lock to meet its consistency constraints before
1249 + * calling aa_switch
1251 +static inline void aa_switch(struct subdomain *sd, struct aaprofile *newactive)
1253 + struct aaprofile *oldactive = sd->active;
1255 + /* noop if NULL */
1256 + rcu_assign_pointer(sd->active, get_aaprofile(newactive));
1257 + clear_cached_caps(sd);
1258 + clear_cached_syscalls(sd);
1259 + put_aaprofile(oldactive);
1263 + * aa_switch_unconfined - change subdomain to be unconfined (no profile)
1264 + * @sd: subdomain to switch
1266 + * aa_switch_unconfined handles the removal of a subdomain's active profile.
1267 + * The sd_lock must be held to ensure consistency against other writers.
1268 + * Like aa_switch the sd_lock is used to maintain consistency.
1270 +static inline void aa_switch_unconfined(struct subdomain *sd)
1272 + aa_switch(sd, NULL);
1274 + /* reset magic in case we were in a subhat before */
1275 + sd->hat_magic = 0;
1279 + * alloc_subdomain - allocate a new subdomain
1280 + * @tsk: task struct
1282 + * Allocate a new subdomain including a backpointer to it's referring task.
1284 +static inline struct subdomain *alloc_subdomain(struct task_struct *tsk)
1286 + struct subdomain *sd;
1288 + sd = kzalloc(sizeof(struct subdomain), GFP_KERNEL);
1292 + /* back pointer to task */
1295 + /* any readers of the list must make sure that they can handle
1296 + * case where sd->active is not yet set (null)
1298 + aa_subdomainlist_add(sd);
1305 + * free_subdomain - Free a subdomain previously allocated by alloc_subdomain
1308 +static inline void free_subdomain(struct subdomain *sd)
1310 + aa_subdomainlist_remove(sd);
1315 + * alloc_aaprofile - Allocate, initialize and return a new zeroed profile.
1316 + * Returns NULL on failure.
1318 +static inline struct aaprofile *alloc_aaprofile(void)
1320 + struct aaprofile *profile;
1322 + profile = (struct aaprofile *)kzalloc(sizeof(struct aaprofile),
1324 + AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
1328 + INIT_LIST_HEAD(&profile->list);
1329 + INIT_LIST_HEAD(&profile->sub);
1330 + INIT_LIST_HEAD(&profile->file_entry);
1331 + for (i = 0; i <= POS_AA_FILE_MAX; i++) {
1332 + INIT_LIST_HEAD(&profile->file_entryp[i]);
1334 + INIT_RCU_HEAD(&profile->rcu);
1335 + kref_init(&profile->count);
1342 + * @name: name to release.
1344 + * Release space (free_page) allocated to hold pathname
1345 + * name may be NULL (checked for by free_page)
1347 +static inline void aa_put_name(const char *name)
1349 + free_page((unsigned long)name);
1352 +/** __aa_find_profile
1353 + * @name: name of profile to find
1354 + * @head: list to search
1356 + * Return reference counted copy of profile. NULL if not found
1357 + * Caller must hold any necessary locks
1359 +static inline struct aaprofile *__aa_find_profile(const char *name,
1360 + struct list_head *head)
1362 + struct aaprofile *p;
1364 + if (!name || !head)
1367 + AA_DEBUG("%s: finding profile %s\n", __FUNCTION__, name);
1368 + list_for_each_entry(p, head, list) {
1369 + if (!strcmp(p->name, name)) {
1370 + /* return refcounted object */
1371 + p = get_aaprofile(p);
1374 + AA_DEBUG("%s: skipping %s\n", __FUNCTION__, p->name);
1380 +/** __aa_path_begin
1381 + * @rdentry: filesystem root dentry (searching for vfsmnts matching this)
1382 + * @dentry: dentry object to obtain pathname from (relative to matched vfsmnt)
1384 + * Setup data for iterating over vfsmounts (in current tasks namespace).
1386 +static inline void __aa_path_begin(struct dentry *rdentry,
1387 + struct dentry *dentry,
1388 + struct aa_path_data *data)
1390 + data->dentry = dentry;
1391 + data->root = dget(rdentry->d_sb->s_root);
1392 + data->mnt_namespace = current->nsproxy->mnt_ns;
1393 + data->head = &data->mnt_namespace->list;
1394 + data->pos = data->head->next;
1395 + prefetch(data->pos->next);
1398 + down_read(&namespace_sem);
1402 + * @dentry: filesystem root dentry and object to obtain pathname from
1404 + * Utility function for calling _aa_path_begin for when the dentry we are
1405 + * looking for and the root are the same (this is the usual case).
1407 +static inline void aa_path_begin(struct dentry *dentry,
1408 + struct aa_path_data *data)
1410 + __aa_path_begin(dentry, dentry, data);
1414 + * @data: data object previously initialized by aa_path_begin
1416 + * End iterating over vfsmounts.
1417 + * If an error occured in begin or get, it is returned. Otherwise 0.
1419 +static inline int aa_path_end(struct aa_path_data *data)
1421 + up_read(&namespace_sem);
1424 + return data->errno;
1427 +/** aa_path_getname
1428 + * @data: data object previously initialized by aa_path_begin
1430 + * Return the next mountpoint which has the same root dentry as data->root.
1431 + * If no more mount points exist (or in case of error) NULL is returned
1432 + * (caller should call aa_path_end() and inspect return code to differentiate)
1434 +static inline char *aa_path_getname(struct aa_path_data *data)
1436 + char *name = NULL;
1437 + struct vfsmount *mnt;
1439 + while (data->pos != data->head) {
1440 + mnt = list_entry(data->pos, struct vfsmount, mnt_list);
1442 + /* advance to next -- so that it is done before we break */
1443 + data->pos = data->pos->next;
1444 + prefetch(data->pos->next);
1446 + if (mnt->mnt_root == data->root) {
1447 + name = aa_get_name(data->dentry, mnt);
1448 + if (IS_ERR(name)) {
1449 + data->errno = PTR_ERR(name);
1459 +#endif /* __INLINE_H__ */
1460 Index: b/security/apparmor/list.c
1461 ===================================================================
1463 +++ b/security/apparmor/list.c
1466 + * Copyright (C) 1998-2005 Novell/SUSE
1468 + * This program is free software; you can redistribute it and/or
1469 + * modify it under the terms of the GNU General Public License as
1470 + * published by the Free Software Foundation, version 2 of the
1473 + * AppArmor Profile List Management
1476 +#include <linux/seq_file.h>
1477 +#include "apparmor.h"
1478 +#include "inline.h"
1480 +/* list of all profiles and lock */
1481 +static LIST_HEAD(profile_list);
1482 +static rwlock_t profile_lock = RW_LOCK_UNLOCKED;
1484 +/* list of all subdomains and lock */
1485 +static LIST_HEAD(subdomain_list);
1486 +static rwlock_t subdomain_lock = RW_LOCK_UNLOCKED;
1489 + * aa_profilelist_find
1490 + * @name: profile name (program name)
1492 + * Search the profile list for profile @name. Return refcounted profile on
1493 + * success, NULL on failure.
1495 +struct aaprofile *aa_profilelist_find(const char *name)
1497 + struct aaprofile *p = NULL;
1499 + read_lock(&profile_lock);
1500 + p = __aa_find_profile(name, &profile_list);
1501 + read_unlock(&profile_lock);
1507 + * aa_profilelist_add - add new profile to list
1508 + * @profile: new profile to add to list
1510 + * NOTE: Caller must allocate necessary reference count that will be used
1511 + * by the profile_list. This is because profile allocation alloc_aaprofile()
1512 + * returns an unreferenced object with a initial count of %1.
1514 + * Return %1 on success, %0 on failure (already exists)
1516 +int aa_profilelist_add(struct aaprofile *profile)
1518 + struct aaprofile *old_profile;
1524 + write_lock(&profile_lock);
1525 + old_profile = __aa_find_profile(profile->name, &profile_list);
1526 + if (old_profile) {
1527 + put_aaprofile(old_profile);
1531 + list_add(&profile->list, &profile_list);
1534 + write_unlock(&profile_lock);
1539 + * aa_profilelist_remove - remove a profile from the list by name
1540 + * @name: name of profile to be removed
1542 + * If the profile exists remove profile from list and return its reference.
1543 + * The reference count on profile is not decremented and should be decremented
1544 + * when the profile is no longer needed
1546 +struct aaprofile *aa_profilelist_remove(const char *name)
1548 + struct aaprofile *profile = NULL;
1549 + struct aaprofile *p, *tmp;
1554 + write_lock(&profile_lock);
1555 + list_for_each_entry_safe(p, tmp, &profile_list, list) {
1556 + if (!strcmp(p->name, name)) {
1557 + list_del_init(&p->list);
1558 + /* mark old profile as stale */
1564 + write_unlock(&profile_lock);
1571 + * aa_profilelist_replace - replace a profile on the list
1572 + * @profile: new profile
1574 + * Replace a profile on the profile list. Find the old profile by name in
1575 + * the list, and replace it with the new profile. NOTE: Caller must allocate
1576 + * necessary initial reference count for new profile as aa_profilelist_add().
1578 + * This is an atomic list operation. Returns the old profile (which is still
1579 + * refcounted) if there was one, or NULL.
1581 +struct aaprofile *aa_profilelist_replace(struct aaprofile *profile)
1583 + struct aaprofile *oldprofile;
1585 + write_lock(&profile_lock);
1586 + oldprofile = __aa_find_profile(profile->name, &profile_list);
1588 + list_del_init(&oldprofile->list);
1589 + /* mark old profile as stale */
1590 + oldprofile->isstale = 1;
1592 + /* __aa_find_profile incremented count, so adjust down */
1593 + put_aaprofile(oldprofile);
1596 + list_add(&profile->list, &profile_list);
1597 + write_unlock(&profile_lock);
1599 + return oldprofile;
1603 + * aa_profilelist_release - Remove all profiles from profile_list
1605 +void aa_profilelist_release(void)
1607 + struct aaprofile *p, *tmp;
1609 + write_lock(&profile_lock);
1610 + list_for_each_entry_safe(p, tmp, &profile_list, list) {
1611 + list_del_init(&p->list);
1614 + write_unlock(&profile_lock);
1618 + * aa_subdomainlist_add - Add subdomain to subdomain_list
1619 + * @sd: new subdomain
1621 +void aa_subdomainlist_add(struct subdomain *sd)
1623 + unsigned long flags;
1626 + AA_INFO("%s: bad subdomain\n", __FUNCTION__);
1630 + write_lock_irqsave(&subdomain_lock, flags);
1631 + /* new subdomains must be added to the end of the list due to a
1632 + * subtle interaction between fork and profile replacement.
1634 + list_add_tail(&sd->list, &subdomain_list);
1635 + write_unlock_irqrestore(&subdomain_lock, flags);
1639 + * aa_subdomainlist_remove - Remove subdomain from subdomain_list
1640 + * @sd: subdomain to be removed
1642 +void aa_subdomainlist_remove(struct subdomain *sd)
1644 + unsigned long flags;
1647 + write_lock_irqsave(&subdomain_lock, flags);
1648 + list_del_init(&sd->list);
1649 + write_unlock_irqrestore(&subdomain_lock, flags);
1654 + * aa_subdomainlist_iterate - iterate over the subdomain list applying @func
1655 + * @func: method to be called for each element
1656 + * @cookie: user passed data
1658 + * Iterate over subdomain list applying @func, stop when @func returns
1661 +void aa_subdomainlist_iterate(aa_iter func, void *cookie)
1663 + struct subdomain *node;
1665 + unsigned long flags;
1667 + read_lock_irqsave(&subdomain_lock, flags);
1668 + list_for_each_entry(node, &subdomain_list, list) {
1669 + ret = (*func) (node, cookie);
1673 + read_unlock_irqrestore(&subdomain_lock, flags);
1677 + * aa_subdomainlist_release - Remove all subdomains from subdomain_list
1679 +void aa_subdomainlist_release(void)
1681 + struct subdomain *node, *tmp;
1682 + unsigned long flags;
1684 + write_lock_irqsave(&subdomain_lock, flags);
1685 + list_for_each_entry_safe(node, tmp, &subdomain_list, list) {
1686 + list_del_init(&node->list);
1688 + write_unlock_irqrestore(&subdomain_lock, flags);
1691 +/* seq_file helper routines
1692 + * Used by apparmorfs.c to iterate over profile_list
1694 +static void *p_start(struct seq_file *f, loff_t *pos)
1696 + struct aaprofile *node;
1699 + read_lock(&profile_lock);
1700 + list_for_each_entry(node, &profile_list, list)
1706 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
1708 + struct list_head *lh = ((struct aaprofile *)p)->list.next;
1710 + return lh == &profile_list ?
1711 + NULL : list_entry(lh, struct aaprofile, list);
1714 +static void p_stop(struct seq_file *f, void *v)
1716 + read_unlock(&profile_lock);
1719 +static int seq_show_profile(struct seq_file *f, void *v)
1721 + struct aaprofile *profile = (struct aaprofile *)v;
1722 + seq_printf(f, "%s (%s)\n", profile->name,
1723 + PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
1727 +struct seq_operations apparmorfs_profiles_op = {
1731 + .show = seq_show_profile,
1733 Index: b/security/apparmor/lsm.c
1734 ===================================================================
1736 +++ b/security/apparmor/lsm.c
1739 + * Copyright (C) 2002-2005 Novell/SUSE
1741 + * This program is free software; you can redistribute it and/or
1742 + * modify it under the terms of the GNU General Public License as
1743 + * published by the Free Software Foundation, version 2 of the
1746 + * http://forge.novell.com/modules/xfmod/project/?apparmor
1748 + * Immunix AppArmor LSM interface
1751 +#include <linux/security.h>
1752 +#include <linux/module.h>
1753 +#include <linux/mm.h>
1754 +#include <linux/mman.h>
1756 +#include "apparmor.h"
1757 +#include "inline.h"
1759 +/* struct subdomain write update lock (read side is RCU). */
1760 +spinlock_t sd_lock = SPIN_LOCK_UNLOCKED;
1762 +/* Flag values, also controllable via apparmorfs/control.
1763 + * We explicitly do not allow these to be modifiable when exported via
1764 + * /sys/modules/parameters, as we want to do additional mediation and
1765 + * don't want to add special path code. */
1767 +/* Complain mode -- in complain mode access failures result in auditing only
1768 + * and task is allowed access. audit events are processed by userspace to
1769 + * generate policy. Default is 'enforce' (0).
1770 + * Value is also togglable per profile and referenced when global value is
1773 +int apparmor_complain = 0;
1774 +module_param_named(complain, apparmor_complain, int, S_IRUSR);
1775 +MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
1778 +int apparmor_debug = 0;
1779 +module_param_named(debug, apparmor_debug, int, S_IRUSR);
1780 +MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
1783 +int apparmor_audit = 0;
1784 +module_param_named(audit, apparmor_audit, int, S_IRUSR);
1785 +MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
1787 +/* Syscall logging mode */
1788 +int apparmor_logsyscall = 0;
1789 +module_param_named(logsyscall, apparmor_logsyscall, int, S_IRUSR);
1790 +MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
1793 +static int __init aa_getopt_complain(char *str)
1795 + get_option(&str, &apparmor_complain);
1798 +__setup("apparmor_complain=", aa_getopt_complain);
1800 +static int __init aa_getopt_debug(char *str)
1802 + get_option(&str, &apparmor_debug);
1805 +__setup("apparmor_debug=", aa_getopt_debug);
1807 +static int __init aa_getopt_audit(char *str)
1809 + get_option(&str, &apparmor_audit);
1812 +__setup("apparmor_audit=", aa_getopt_audit);
1814 +static int __init aa_getopt_logsyscall(char *str)
1816 + get_option(&str, &apparmor_logsyscall);
1819 +__setup("apparmor_logsyscall=", aa_getopt_logsyscall);
1822 +static int apparmor_ptrace(struct task_struct *parent,
1823 + struct task_struct *child)
1826 + struct aaprofile *active;
1828 + error = cap_ptrace(parent, child);
1830 + active = get_task_active_aaprofile(parent);
1832 + if (!error && active)
1833 + error = aa_audit_syscallreject(active, GFP_ATOMIC,
1834 + AA_SYSCALL_PTRACE);
1836 + put_aaprofile(active);
1841 +static int apparmor_capget(struct task_struct *target,
1842 + kernel_cap_t *effective,
1843 + kernel_cap_t *inheritable,
1844 + kernel_cap_t *permitted)
1846 + return cap_capget(target, effective, inheritable, permitted);
1849 +static int apparmor_capset_check(struct task_struct *target,
1850 + kernel_cap_t *effective,
1851 + kernel_cap_t *inheritable,
1852 + kernel_cap_t *permitted)
1854 + return cap_capset_check(target, effective, inheritable, permitted);
1857 +static void apparmor_capset_set(struct task_struct *target,
1858 + kernel_cap_t *effective,
1859 + kernel_cap_t *inheritable,
1860 + kernel_cap_t *permitted)
1862 + cap_capset_set(target, effective, inheritable, permitted);
1866 +static int apparmor_capable(struct task_struct *tsk, int cap)
1870 + /* cap_capable returns 0 on success, else -EPERM */
1871 + error = cap_capable(tsk, cap);
1874 + struct aaprofile *active;
1876 + active = get_task_active_aaprofile(tsk);
1879 + error = aa_capability(active, cap);
1881 + put_aaprofile(active);
1887 +static int apparmor_sysctl(struct ctl_table *table, int op)
1890 + struct aaprofile *active;
1892 + active = get_active_aaprofile();
1894 + if ((op & 002) && active && !capable(CAP_SYS_ADMIN))
1895 + error = aa_audit_syscallreject(active, GFP_ATOMIC,
1896 + AA_SYSCALL_SYSCTL_WRITE);
1898 + put_aaprofile(active);
1903 +static int apparmor_syslog(int type)
1905 + return cap_syslog(type);
1908 +static int apparmor_netlink_send(struct sock *sk, struct sk_buff *skb)
1910 + return cap_netlink_send(sk, skb);
1913 +static int apparmor_netlink_recv(struct sk_buff *skb, int cap)
1915 + return cap_netlink_recv(skb, cap);
1918 +static void apparmor_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
1920 + cap_bprm_apply_creds(bprm, unsafe);
1924 +static int apparmor_bprm_set_security(struct linux_binprm *bprm)
1926 + /* handle capability bits with setuid, etc */
1927 + cap_bprm_set_security(bprm);
1928 + /* already set based on script name */
1929 + if (bprm->sh_bang)
1931 + return aa_register(bprm);
1934 +static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
1936 + int ret = cap_bprm_secureexec(bprm);
1939 + (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
1940 + AA_DEBUG("%s: secureexec required for %s\n",
1941 + __FUNCTION__, bprm->filename);
1948 +static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
1949 + unsigned long flags, void *data)
1952 + struct aaprofile *active;
1954 + active = get_active_aaprofile();
1957 + error = aa_audit_syscallreject(active, GFP_ATOMIC,
1958 + AA_SYSCALL_MOUNT);
1960 + put_aaprofile(active);
1965 +static int apparmor_umount(struct vfsmount *mnt, int flags)
1968 + struct aaprofile *active;
1970 + active = get_active_aaprofile();
1973 + error = aa_audit_syscallreject(active, GFP_ATOMIC,
1974 + AA_SYSCALL_UMOUNT);
1976 + put_aaprofile(active);
1981 +static int apparmor_inode_mkdir(struct inode *inode, struct dentry *dentry,
1984 + struct aaprofile *active;
1987 + active = get_active_aaprofile();
1990 + error = aa_perm_dir(active, dentry, aa_dir_mkdir);
1992 + put_aaprofile(active);
1997 +static int apparmor_inode_rmdir(struct inode *inode, struct dentry *dentry)
1999 + struct aaprofile *active;
2002 + active = get_active_aaprofile();
2005 + error = aa_perm_dir(active, dentry, aa_dir_rmdir);
2007 + put_aaprofile(active);
2012 +static int apparmor_inode_create(struct inode *inode, struct dentry *dentry,
2015 + struct aaprofile *active;
2018 + active = get_active_aaprofile();
2020 + /* At a minimum, need write perm to create */
2022 + error = aa_perm_dentry(active, dentry, MAY_WRITE);
2024 + put_aaprofile(active);
2029 +static int apparmor_inode_link(struct dentry *old_dentry, struct inode *inode,
2030 + struct dentry *new_dentry)
2033 + struct aaprofile *active;
2035 + active = get_active_aaprofile();
2038 + error = aa_link(active, new_dentry, old_dentry);
2040 + put_aaprofile(active);
2045 +static int apparmor_inode_unlink(struct inode *inode, struct dentry *dentry)
2047 + struct aaprofile *active;
2050 + active = get_active_aaprofile();
2053 + error = aa_perm_dentry(active, dentry, MAY_WRITE);
2055 + put_aaprofile(active);
2060 +static int apparmor_inode_mknod(struct inode *inode, struct dentry *dentry,
2061 + int mode, dev_t dev)
2063 + struct aaprofile *active;
2066 + active = get_active_aaprofile();
2069 + error = aa_perm_dentry(active, dentry, MAY_WRITE);
2071 + put_aaprofile(active);
2076 +static int apparmor_inode_rename(struct inode *old_inode,
2077 + struct dentry *old_dentry,
2078 + struct inode *new_inode,
2079 + struct dentry *new_dentry)
2081 + struct aaprofile *active;
2084 + active = get_active_aaprofile();
2087 + error = aa_perm_dentry(active, old_dentry, MAY_READ |
2091 + error = aa_perm_dentry(active, new_dentry,
2095 + put_aaprofile(active);
2100 +static int apparmor_inode_permission(struct inode *inode, int mask,
2101 + struct nameidata *nd)
2105 + /* Do not perform check on pipes or sockets
2106 + * Same as apparmor_file_permission
2108 + if (VALID_FSTYPE(inode)) {
2109 + struct aaprofile *active;
2111 + active = get_active_aaprofile();
2113 + error = aa_perm_nameidata(active, nd, mask);
2114 + put_aaprofile(active);
2120 +static int apparmor_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2124 + if (VALID_FSTYPE(dentry->d_inode)) {
2125 + struct aaprofile *active;
2127 + active = get_active_aaprofile();
2129 + * Mediate any attempt to change attributes of a file
2130 + * (chmod, chown, chgrp, etc)
2133 + error = aa_attr(active, dentry, iattr);
2135 + put_aaprofile(active);
2141 +static int apparmor_inode_setxattr(struct dentry *dentry, char *name,
2142 + void *value, size_t size, int flags)
2146 + if (VALID_FSTYPE(dentry->d_inode)) {
2147 + struct aaprofile *active;
2149 + active = get_active_aaprofile();
2151 + error = aa_xattr(active, dentry, name, aa_xattr_set);
2152 + put_aaprofile(active);
2158 +static int apparmor_inode_getxattr(struct dentry *dentry, char *name)
2162 + if (VALID_FSTYPE(dentry->d_inode)) {
2163 + struct aaprofile *active;
2165 + active = get_active_aaprofile();
2167 + error = aa_xattr(active, dentry, name, aa_xattr_get);
2168 + put_aaprofile(active);
2173 +static int apparmor_inode_listxattr(struct dentry *dentry)
2177 + if (VALID_FSTYPE(dentry->d_inode)) {
2178 + struct aaprofile *active;
2180 + active = get_active_aaprofile();
2182 + error = aa_xattr(active, dentry, NULL, aa_xattr_list);
2183 + put_aaprofile(active);
2189 +static int apparmor_inode_removexattr(struct dentry *dentry, char *name)
2193 + if (VALID_FSTYPE(dentry->d_inode)) {
2194 + struct aaprofile *active;
2196 + active = get_active_aaprofile();
2198 + error = aa_xattr(active, dentry, name,
2200 + put_aaprofile(active);
2206 +static int apparmor_file_permission(struct file *file, int mask)
2208 + struct aaprofile *active;
2209 + struct aafile *aaf;
2212 + aaf = (struct aafile *)file->f_security;
2213 + /* bail out early if this isn't a mediated file */
2214 + if (!aaf || !VALID_FSTYPE(file->f_dentry->d_inode))
2217 + active = get_active_aaprofile();
2218 + if (active && aaf->profile != active)
2219 + error = aa_perm(active, file->f_dentry, file->f_vfsmnt,
2220 + mask & (MAY_EXEC | MAY_WRITE | MAY_READ));
2221 + put_aaprofile(active);
2227 +static int apparmor_file_alloc_security(struct file *file)
2229 + struct aaprofile *active;
2232 + active = get_active_aaprofile();
2234 + struct aafile *aaf;
2235 + aaf = kmalloc(sizeof(struct aafile), GFP_KERNEL);
2238 + aaf->type = aa_file_default;
2239 + aaf->profile = get_aaprofile(active);
2243 + file->f_security = aaf;
2245 + put_aaprofile(active);
2250 +static void apparmor_file_free_security(struct file *file)
2252 + struct aafile *aaf = (struct aafile *)file->f_security;
2255 + put_aaprofile(aaf->profile);
2260 +static inline int aa_mmap(struct file *file, unsigned long prot,
2261 + unsigned long flags)
2263 + int error = 0, mask = 0;
2264 + struct aaprofile *active;
2265 + struct aafile *aaf;
2267 + active = get_active_aaprofile();
2268 + if (!active || !file ||
2269 + !(aaf = (struct aafile *)file->f_security) ||
2270 + aaf->type == aa_file_shmem)
2273 + if (prot & PROT_READ)
2276 + /* Private mappings don't require write perms since they don't
2277 + * write back to the files */
2278 + if (prot & PROT_WRITE && !(flags & MAP_PRIVATE))
2279 + mask |= MAY_WRITE;
2280 + if (prot & PROT_EXEC)
2281 + mask |= AA_EXEC_MMAP;
2283 + AA_DEBUG("%s: 0x%x\n", __FUNCTION__, mask);
2286 + error = aa_perm(active, file->f_dentry, file->f_vfsmnt, mask);
2288 + put_aaprofile(active);
2294 +static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
2295 + unsigned long prot, unsigned long flags)
2297 + return aa_mmap(file, prot, flags);
2300 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
2301 + unsigned long reqprot, unsigned long prot)
2303 + return aa_mmap(vma->vm_file, prot,
2304 + !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
2307 +static int apparmor_task_alloc_security(struct task_struct *p)
2309 + return aa_fork(p);
2312 +static void apparmor_task_free_security(struct task_struct *p)
2317 +static int apparmor_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
2320 + return cap_task_post_setuid(id0, id1, id2, flags);
2323 +static void apparmor_task_reparent_to_init(struct task_struct *p)
2325 + cap_task_reparent_to_init(p);
2329 +static int apparmor_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
2332 + struct aafile *aaf = (struct aafile *)shp->shm_file->f_security;
2335 + aaf->type = aa_file_shmem;
2340 +static int apparmor_getprocattr(struct task_struct *p, char *name, void *value,
2344 + struct aaprofile *active;
2345 + char *str = value;
2347 + /* AppArmor only supports the "current" process attribute */
2348 + if (strcmp(name, "current") != 0) {
2353 + /* must be task querying itself or admin */
2354 + if (current != p && !capable(CAP_SYS_ADMIN)) {
2359 + active = get_task_active_aaprofile(p);
2360 + error = aa_getprocattr(active, str, size);
2361 + put_aaprofile(active);
2367 +static int apparmor_setprocattr(struct task_struct *p, char *name, void *value,
2370 + const char *cmd_changehat = "changehat ",
2371 + *cmd_setprofile = "setprofile ";
2373 + int error = -EACCES; /* default to a perm denied */
2374 + char *cmd = (char *)value;
2376 + /* only support messages to current */
2377 + if (strcmp(name, "current") != 0) {
2387 + /* CHANGE HAT -- switch task into a subhat (subprofile) if defined */
2388 + if (size > strlen(cmd_changehat) &&
2389 + strncmp(cmd, cmd_changehat, strlen(cmd_changehat)) == 0) {
2390 + char *hatinfo = cmd + strlen(cmd_changehat);
2391 + size_t infosize = size - strlen(cmd_changehat);
2393 + /* Only the current process may change it's hat */
2394 + if (current != p) {
2395 + AA_WARN("%s: Attempt by foreign task %s(%d) "
2396 + "[user %d] to changehat of task %s(%d)\n",
2408 + error = aa_setprocattr_changehat(hatinfo, infosize);
2410 + /* success, set return to #bytes in orig request */
2413 + /* SET NEW PROFILE */
2414 + } else if (size > strlen(cmd_setprofile) &&
2415 + strncmp(cmd, cmd_setprofile, strlen(cmd_setprofile)) == 0) {
2416 + struct aaprofile *active;
2418 + /* only an unconfined process with admin capabilities
2419 + * may change the profile of another task
2422 + if (!capable(CAP_SYS_ADMIN)) {
2423 + AA_WARN("%s: Unprivileged attempt by task %s(%d) "
2424 + "[user %d] to assign profile to task %s(%d)\n",
2435 + active = get_active_aaprofile();
2437 + char *profile = cmd + strlen(cmd_setprofile);
2438 + size_t profilesize = size - strlen(cmd_setprofile);
2440 + error = aa_setprocattr_setprofile(p, profile, profilesize);
2443 + * set return to #bytes in orig request
2447 + AA_WARN("%s: Attempt by confined task %s(%d) "
2448 + "[user %d] to assign profile to task %s(%d)\n",
2458 + put_aaprofile(active);
2460 + /* unknown operation */
2461 + AA_WARN("%s: Unknown setprocattr command '%.*s' by task %s(%d) "
2462 + "[user %d] for task %s(%d)\n",
2464 + size < 16 ? (int)size : 16,
2479 +struct security_operations apparmor_ops = {
2480 + .ptrace = apparmor_ptrace,
2481 + .capget = apparmor_capget,
2482 + .capset_check = apparmor_capset_check,
2483 + .capset_set = apparmor_capset_set,
2484 + .sysctl = apparmor_sysctl,
2485 + .capable = apparmor_capable,
2486 + .syslog = apparmor_syslog,
2488 + .netlink_send = apparmor_netlink_send,
2489 + .netlink_recv = apparmor_netlink_recv,
2491 + .bprm_apply_creds = apparmor_bprm_apply_creds,
2492 + .bprm_set_security = apparmor_bprm_set_security,
2493 + .bprm_secureexec = apparmor_bprm_secureexec,
2495 + .sb_mount = apparmor_sb_mount,
2496 + .sb_umount = apparmor_umount,
2498 + .inode_mkdir = apparmor_inode_mkdir,
2499 + .inode_rmdir = apparmor_inode_rmdir,
2500 + .inode_create = apparmor_inode_create,
2501 + .inode_link = apparmor_inode_link,
2502 + .inode_unlink = apparmor_inode_unlink,
2503 + .inode_mknod = apparmor_inode_mknod,
2504 + .inode_rename = apparmor_inode_rename,
2505 + .inode_permission = apparmor_inode_permission,
2506 + .inode_setattr = apparmor_inode_setattr,
2507 + .inode_setxattr = apparmor_inode_setxattr,
2508 + .inode_getxattr = apparmor_inode_getxattr,
2509 + .inode_listxattr = apparmor_inode_listxattr,
2510 + .inode_removexattr = apparmor_inode_removexattr,
2511 + .file_permission = apparmor_file_permission,
2512 + .file_alloc_security = apparmor_file_alloc_security,
2513 + .file_free_security = apparmor_file_free_security,
2514 + .file_mmap = apparmor_file_mmap,
2515 + .file_mprotect = apparmor_file_mprotect,
2517 + .task_alloc_security = apparmor_task_alloc_security,
2518 + .task_free_security = apparmor_task_free_security,
2519 + .task_post_setuid = apparmor_task_post_setuid,
2520 + .task_reparent_to_init = apparmor_task_reparent_to_init,
2522 + .shm_shmat = apparmor_shm_shmat,
2524 + .getprocattr = apparmor_getprocattr,
2525 + .setprocattr = apparmor_setprocattr,
2528 +static int __init apparmor_init(void)
2531 + const char *complainmsg = ": complainmode enabled";
2533 + if ((error = create_apparmorfs())) {
2534 + AA_ERROR("Unable to activate AppArmor filesystem\n");
2535 + goto createfs_out;
2538 + if ((error = alloc_null_complain_profile())){
2539 + AA_ERROR("Unable to allocate null complain profile\n");
2543 + if ((error = register_security(&apparmor_ops))) {
2544 + AA_ERROR("Unable to load AppArmor\n");
2545 + goto register_security_out;
2548 + AA_INFO("AppArmor initialized%s\n",
2549 + apparmor_complain ? complainmsg : "");
2550 + aa_audit_message(NULL, GFP_KERNEL, 0,
2551 + "AppArmor initialized%s\n",
2552 + apparmor_complain ? complainmsg : "");
2556 +register_security_out:
2557 + free_null_complain_profile();
2560 + (void)destroy_apparmorfs();
2567 +static int apparmor_exit_removeall_iter(struct subdomain *sd, void *cookie)
2569 + /* spin_lock(&sd_lock) held here */
2571 + if (__aa_is_confined(sd)) {
2572 + AA_DEBUG("%s: Dropping profiles %s(%d) "
2573 + "profile %s(%p) active %s(%p)\n",
2575 + sd->task->comm, sd->task->pid,
2576 + BASE_PROFILE(sd->active)->name,
2577 + BASE_PROFILE(sd->active),
2578 + sd->active->name, sd->active);
2579 + aa_switch_unconfined(sd);
2585 +static void __exit apparmor_exit(void)
2587 + unsigned long flags;
2589 + /* Remove profiles from the global profile list.
2590 + * This is just for tidyness as there is no way to reference this
2591 + * list once the AppArmor lsm hooks are detached (below)
2593 + aa_profilelist_release();
2595 + /* Remove profiles from active tasks
2596 + * If this is not done, if module is reloaded after being removed,
2597 + * old profiles (still refcounted in memory) will become 'magically'
2601 + spin_lock_irqsave(&sd_lock, flags);
2602 + aa_subdomainlist_iterate(apparmor_exit_removeall_iter, NULL);
2603 + spin_unlock_irqrestore(&sd_lock, flags);
2605 + /* Free up list of active subdomain */
2606 + aa_subdomainlist_release();
2608 + free_null_complain_profile();
2610 + destroy_apparmorfs();
2612 + if (unregister_security(&apparmor_ops))
2613 + AA_WARN("Unable to properly unregister AppArmor\n");
2615 + /* delay for an rcu cycle to make ensure that profiles pending
2616 + * destruction in the rcu callback are freed.
2618 + synchronize_rcu();
2620 + AA_INFO("AppArmor protection removed\n");
2621 + aa_audit_message(NULL, GFP_KERNEL, 0,
2622 + "AppArmor protection removed\n");
2625 +module_init(apparmor_init);
2626 +module_exit(apparmor_exit);
2628 +MODULE_VERSION(APPARMOR_VERSION);
2629 +MODULE_DESCRIPTION("AppArmor process confinement");
2630 +MODULE_AUTHOR("Tony Jones <tonyj@suse.de>");
2631 +MODULE_LICENSE("GPL");
2632 Index: b/security/apparmor/main.c
2633 ===================================================================
2635 +++ b/security/apparmor/main.c
2638 + * Copyright (C) 2002-2005 Novell/SUSE
2640 + * This program is free software; you can redistribute it and/or
2641 + * modify it under the terms of the GNU General Public License as
2642 + * published by the Free Software Foundation, version 2 of the
2648 +#include <linux/security.h>
2649 +#include <linux/namei.h>
2650 +#include <linux/audit.h>
2652 +#include "apparmor.h"
2653 +#include "match/match.h"
2655 +#include "inline.h"
2657 +/* NULL complain profile
2659 + * Used when in complain mode, to emit Permitting messages for non-existant
2660 + * profiles and hats. This is necessary because of selective mode, in which
2661 + * case we need a complain null_profile and enforce null_profile
2663 + * The null_complain_profile cannot be statically allocated, because it
2664 + * can be associated to files which keep their reference even if apparmor is
2667 +struct aaprofile *null_complain_profile;
2669 +/***************************
2670 + * Private utility functions
2671 + **************************/
2674 + * dentry_xlate_error
2675 + * @dentry: pointer to dentry
2676 + * @error: error number
2677 + * @dtype: type of dentry
2679 + * Display error message when a dentry translation error occured
2681 +static void dentry_xlate_error(struct dentry *dentry, int error, char *dtype)
2683 + const unsigned int len = 16;
2686 + if (dentry->d_inode) {
2687 + snprintf(buf, len, "%lu", dentry->d_inode->i_ino);
2689 + strncpy(buf, "<negative>", len);
2693 + AA_ERROR("An error occured while translating %s %p "
2694 + "inode# %s to a pathname. Error %d\n",
2702 + * aa_taskattr_access
2703 + * @procrelname: name of file to check permission
2705 + * Determine if request is for write access to /proc/self/attr/current
2706 + * This file is the usermode iterface for changing it's hat.
2708 +static inline int aa_taskattr_access(const char *procrelname)
2710 + char buf[sizeof("/attr/current") + 10];
2711 + const int maxbuflen = sizeof(buf);
2712 + /* assumption, 32bit pid (10 decimal digits incl \0) */
2714 + snprintf(buf, maxbuflen, "%d/attr/current", current->pid);
2715 + buf[maxbuflen - 1] = 0;
2717 + return strcmp(buf, procrelname) == 0;
2721 + * aa_file_mode - get full mode for file entry from profile
2722 + * @profile: profile
2725 +static inline int aa_file_mode(struct aaprofile *profile, const char *name)
2727 + struct aa_entry *entry;
2730 + AA_DEBUG("%s: %s\n", __FUNCTION__, name);
2732 + AA_DEBUG("%s: no name\n", __FUNCTION__);
2737 + AA_DEBUG("%s: no profile\n", __FUNCTION__);
2740 + list_for_each_entry(entry, &profile->file_entry, list) {
2741 + if (aamatch_match(name, entry->filename,
2742 + entry->type, entry->extradata))
2743 + mode |= entry->mode;
2750 + * aa_get_execmode - calculate what qualifier to apply to an exec
2751 + * @active: profile to search
2752 + * @name: name of file to exec
2753 + * @xmod: pointer to a execution mode bit for the rule that was matched
2754 + * if the rule has no execuition qualifier {pui} then
2755 + * %AA_MAY_EXEC is returned indicating a naked x
2756 + * if the has an exec qualifier then only the qualifier bit {pui}
2757 + * is returned (%AA_MAY_EXEC) is not set.
2758 + * @unsafe: true if secure_exec should be overriden
2759 + * Returns %0 (false):
2760 + * if unable to find profile or there are conflicting pattern matches.
2761 + * *xmod - is not modified
2762 + * *unsafe - is not modified
2764 + * Returns %1 (true):
2765 + * if exec rule matched
2766 + * if the rule has an execution mode qualifier {pui} then
2767 + * *xmod = the execution qualifier of the rule {pui}
2769 + * *xmod = %AA_MAY_EXEC
2770 + * unsafe = presence of unsage flag
2772 +static inline int aa_get_execmode(struct aaprofile *active, const char *name,
2773 + int *xmod, int *unsafe)
2775 + struct aa_entry *entry;
2776 + struct aa_entry *match = NULL;
2778 + int pattern_match_invalid = 0, rc = 0;
2780 + /* search list of profiles with 'x' permission
2781 + * this will also include entries with 'p', 'u' and 'i'
2784 + * If we find a pattern match we will keep looking for an exact match
2785 + * If we find conflicting pattern matches we will flag (while still
2786 + * looking for an exact match). If all we have is a conflict, FALSE
2790 + list_for_each_entry(entry, &active->file_entryp[POS_AA_MAY_EXEC],
2791 + listp[POS_AA_MAY_EXEC]) {
2792 + if (!pattern_match_invalid &&
2793 + entry->type == aa_entry_pattern &&
2794 + aamatch_match(name, entry->filename,
2795 + entry->type, entry->extradata)) {
2797 + AA_EXEC_UNSAFE_MASK(entry->mode) !=
2798 + AA_EXEC_UNSAFE_MASK(match->mode))
2799 + pattern_match_invalid = 1;
2801 + /* keep searching for an exact match */
2803 + } else if ((entry->type == aa_entry_literal ||
2804 + (!pattern_match_invalid &&
2805 + entry->type == aa_entry_tailglob)) &&
2806 + aamatch_match(name, entry->filename,
2808 + entry->extradata)) {
2809 + if (entry->type == aa_entry_literal) {
2810 + /* got an exact match -- there can be only
2811 + * one, asserted at profile load time
2814 + pattern_match_invalid = 0;
2818 + AA_EXEC_UNSAFE_MASK(entry->mode) !=
2819 + AA_EXEC_UNSAFE_MASK(match->mode))
2820 + pattern_match_invalid = 1;
2822 + /* got a tailglob match, keep searching
2823 + * for an exact match
2831 + rc = match && !pattern_match_invalid;
2834 + int mode = AA_EXEC_MASK(match->mode);
2836 + /* check for qualifiers, if present
2837 + * we just return the qualifier
2839 + if (mode & ~AA_MAY_EXEC)
2840 + mode = mode & ~AA_MAY_EXEC;
2843 + *unsafe = (match->mode & AA_EXEC_UNSAFE);
2844 + } else if (!match) {
2845 + AA_DEBUG("%s: Unable to find execute entry in profile "
2846 + "for image '%s'\n",
2849 + } else if (pattern_match_invalid) {
2850 + AA_WARN("%s: Inconsistency in profile %s. "
2851 + "Two (or more) patterns specify conflicting exec "
2852 + "qualifiers ('u', 'i' or 'p') for image %s\n",
2863 + * @mask: requested mask
2864 + * @inode: potential directory inode
2866 + * This fn performs pre-verification of the requested mask
2867 + * We ignore append. Previously we required 'w' on a dir to add a file.
2868 + * No longer. Now we require 'w' on just the file itself. Traversal 'x' is
2869 + * also ignored for directories.
2871 + * Returned value of %0 indicates no need to perform a perm check.
2873 +static inline int aa_filter_mask(int mask, struct inode *inode)
2876 + int elim = MAY_APPEND;
2878 + if (inode && S_ISDIR(inode->i_mode))
2879 + elim |= (MAY_EXEC | MAY_WRITE);
2887 +static inline void aa_permerror2result(int perm_result, struct aa_audit *sa)
2889 + if (perm_result == 0) { /* success */
2891 + sa->error_code = 0;
2892 + } else { /* -ve internal error code or +ve mask of denied perms */
2894 + sa->error_code = perm_result;
2898 +/*************************
2899 + * Main internal functions
2900 + ************************/
2903 + * aa_file_perm - calculate access mode for file
2904 + * @active: profile to check against
2905 + * @name: name of file to calculate mode for
2906 + * @mask: permission mask requested for file
2908 + * Search the aa_entry list in @active.
2909 + * Search looking to verify all permissions passed in mask.
2910 + * Perform the search by looking at the partitioned list of entries, one
2911 + * partition per permission bit.
2913 + * Return %0 on success, else mask of non-allowed permissions
2915 +static unsigned int aa_file_perm(struct aaprofile *active, const char *name,
2918 + int i, error = 0, mode;
2920 +#define PROCPFX "/proc/"
2921 +#define PROCLEN sizeof(PROCPFX) - 1
2923 + AA_DEBUG("%s: %s 0x%x\n", __FUNCTION__, name, mask);
2925 + /* should not enter with other than R/W/M/X/L */
2927 + ~(AA_MAY_READ | AA_MAY_WRITE | AA_MAY_EXEC | AA_EXEC_MMAP |
2930 + /* Special case access to /proc/self/attr/current
2931 + * Currently we only allow access if opened O_WRONLY
2933 + if (mask == MAY_WRITE && strncmp(PROCPFX, name, PROCLEN) == 0 &&
2934 + aa_taskattr_access(name + PROCLEN))
2939 + /* iterate over partition, one permission bit at a time */
2940 + for (i = 0; i <= POS_AA_FILE_MAX; i++) {
2941 + struct aa_entry *entry;
2943 + /* do we have to accumulate this bit?
2944 + * or have we already accumulated it (shortcut below)? */
2945 + if (!(mask & (1 << i)) || mode & (1 << i))
2948 + list_for_each_entry(entry, &active->file_entryp[i],
2950 + if (aamatch_match(name, entry->filename,
2951 + entry->type, entry->extradata)) {
2952 + /* Shortcut, accumulate all bits present */
2953 + mode |= entry->mode;
2955 + /* Mask bits are overloaded
2956 + * MAY_{EXEC,WRITE,READ,APPEND} are used by
2957 + * kernel, other values are used locally only.
2959 + if ((mode & mask) == mask) {
2960 + AA_DEBUG("MATCH! %s=0x%x [total mode=0x%x]\n",
2961 + name, mask, mode);
2969 + /* return permissions not satisfied */
2970 + error = mask & ~mode;
2977 + * aa_link_perm - test permission to link to a file
2978 + * @active: profile to check against
2979 + * @link: name of link being created
2980 + * @target: name of target to be linked to
2982 + * Look up permission mode on both @link and @target. @link must have same
2983 + * permission mode as @target. At least @link must have the link bit enabled.
2984 + * Return %0 on success, error otherwise.
2986 +static int aa_link_perm(struct aaprofile *active,
2987 + const char *link, const char *target)
2989 + int l_mode, t_mode, ret;
2991 + l_mode = aa_file_mode(active, link);
2992 + if (l_mode & AA_MAY_LINK) {
2993 + /* mask off link bit */
2994 + l_mode &= ~AA_MAY_LINK;
2996 + t_mode = aa_file_mode(active, target);
2997 + t_mode &= ~AA_MAY_LINK;
2999 + ret = (l_mode == t_mode);
3009 + * @active: profile to check against
3010 + * @dentry: requested dentry
3011 + * @mask: mask of requested operations
3012 + * @pname: pointer to hold matched pathname (if any)
3014 + * Helper function. Obtain pathname for specified dentry. Verify if profile
3015 + * authorizes mask operations on pathname (due to lack of vfsmnt it is sadly
3016 + * necessary to search mountpoints in namespace -- when nameidata is passed
3017 + * more fully, this code can go away). If more than one mountpoint matches
3018 + * but none satisfy the profile, only the first pathname (mountpoint) is
3019 + * returned for subsequent logging.
3021 + * Return %0 (success), +ve (mask of permissions not satisfied) or -ve (system
3022 + * error, most likely -%ENOMEM).
3024 +static int _aa_perm_dentry(struct aaprofile *active, struct dentry *dentry,
3025 + int mask, const char **pname)
3027 + char *name = NULL, *failed_name = NULL;
3028 + struct aa_path_data data;
3029 + int error = 0, failed_error = 0, path_error,
3030 + complain = PROFILE_COMPLAIN(active);
3032 + /* search all paths to dentry */
3034 + aa_path_begin(dentry, &data);
3036 + name = aa_path_getname(&data);
3038 + /* error here is 0 (success) or +ve (mask of perms) */
3039 + error = aa_file_perm(active, name, mask);
3041 + /* access via any path is enough */
3042 + if (complain || error == 0)
3043 + break; /* Caller must free name */
3045 + /* Already have an path that failed? */
3046 + if (failed_name) {
3047 + aa_put_name(name);
3049 + failed_name = name;
3050 + failed_error = error;
3055 + if ((path_error = aa_path_end(&data)) != 0) {
3056 + dentry_xlate_error(dentry, path_error, "dentry");
3057 + WARN_ON(name); /* name should not be set if error */
3058 + error = path_error;
3060 + } else if (name) {
3062 + aa_put_name(failed_name);
3064 + name = failed_name;
3065 + error = failed_error;
3073 +/**************************
3074 + * Global utility functions
3075 + *************************/
3078 + * attach_nullprofile - allocate and attach a null_profile hat to profile
3079 + * @profile: profile to attach a null_profile hat to.
3081 + * Return %0 (success) or error (-%ENOMEM)
3083 +int attach_nullprofile(struct aaprofile *profile)
3085 + struct aaprofile *hat = NULL;
3086 + char *hatname = NULL;
3088 + hat = alloc_aaprofile();
3091 + if (profile->flags.complain)
3092 + hatname = kstrdup("null-complain-profile", GFP_KERNEL);
3094 + hatname = kstrdup("null-profile", GFP_KERNEL);
3098 + hat->flags.complain = profile->flags.complain;
3099 + hat->name = hatname;
3100 + hat->parent = profile;
3102 + profile->null_profile = hat;
3108 + free_aaprofile(hat);
3115 + * alloc_null_complain_profile - Allocate the global null_complain_profile.
3117 + * Return %0 (success) or error (-%ENOMEM)
3119 +int alloc_null_complain_profile(void)
3121 + null_complain_profile = alloc_aaprofile();
3122 + if (!null_complain_profile)
3125 + null_complain_profile->name =
3126 + kstrdup("null-complain-profile", GFP_KERNEL);
3128 + if (!null_complain_profile->name)
3131 + null_complain_profile->flags.complain = 1;
3132 + if (attach_nullprofile(null_complain_profile))
3138 + /* free_aaprofile is safe for freeing partially constructed objects */
3139 + free_aaprofile(null_complain_profile);
3140 + null_complain_profile = NULL;
3146 + * free_null_complain_profile - Free null profiles
3148 +void free_null_complain_profile(void)
3150 + put_aaprofile(null_complain_profile);
3151 + null_complain_profile = NULL;
3155 + * aa_audit_message - Log a message to the audit subsystem
3156 + * @active: profile to check against
3157 + * @gfp: allocation flags
3158 + * @flags: audit flags
3159 + * @fmt: varargs fmt
3161 +int aa_audit_message(struct aaprofile *active, gfp_t gfp, int flags,
3162 + const char *fmt, ...)
3165 + struct aa_audit sa;
3167 + sa.type = AA_AUDITTYPE_MSG;
3169 + va_start(sa.vaval, fmt);
3171 + sa.gfp_mask = gfp;
3172 + sa.error_code = 0;
3173 + sa.result = 0; /* fake failure: force message to be logged */
3175 + ret = aa_audit(active, &sa);
3183 + * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem
3184 + * @active: profile to check against
3185 + * @gfp: memory allocation flags
3186 + * @call: aa syscall cache bit number
3188 +int aa_audit_syscallreject(struct aaprofile *active, gfp_t gfp,
3189 + enum aasyscall call)
3191 + struct aa_audit sa;
3192 + int error = -EPERM;
3194 + if (!syscall_is_cached(call)) {
3195 + sa.type = AA_AUDITTYPE_SYSCALL;
3196 + sa.name = syscall_to_name(call);
3198 + sa.gfp_mask = gfp;
3199 + sa.error_code = 0;
3200 + sa.result = 0; /* failure */
3202 + error = aa_audit(active, &sa);
3203 + if (error == -EPERM)
3204 + add_to_cached_syscalls(call);
3210 + * aa_audit - Log an audit event to the audit subsystem
3211 + * @active: profile to check against
3212 + * @sa: audit event
3214 +int aa_audit(struct aaprofile *active, const struct aa_audit *sa)
3216 + struct audit_buffer *ab = NULL;
3217 + struct audit_context *ctx;
3219 + const char *logcls;
3220 + unsigned int flags;
3224 + opspec_error = -EACCES;
3226 + const gfp_t gfp_mask = sa->gfp_mask;
3228 + WARN_ON(sa->type >= AA_AUDITTYPE__END);
3231 + * sa->result: 1 success, 0 failure
3232 + * sa->error_code: success: 0
3233 + * failure: +ve mask of failed permissions or -ve
3237 + if (likely(sa->result)) {
3238 + if (likely(!PROFILE_AUDIT(active))) {
3239 + /* nothing to log */
3244 + logcls = "AUDITING";
3246 + } else if (sa->error_code < 0) {
3247 + audit_log(current->audit_context, gfp_mask, AUDIT_SD,
3248 + "Internal error auditing event type %d (error %d)",
3249 + sa->type, sa->error_code);
3250 + AA_ERROR("Internal error auditing event type %d (error %d)\n",
3251 + sa->type, sa->error_code);
3252 + error = sa->error_code;
3254 + } else if (sa->type == AA_AUDITTYPE_SYSCALL) {
3255 + /* Currently AA_AUDITTYPE_SYSCALL is for rejects only.
3256 + * Values set by aa_audit_syscallreject will get us here.
3258 + logcls = "REJECTING";
3260 + complain = PROFILE_COMPLAIN(active);
3261 + logcls = complain ? "PERMITTING" : "REJECTING";
3264 + /* test if event has already been logged and cached used to log
3265 + * only first time event occurs.
3267 + if (sa->type == AA_AUDITTYPE_CAP) {
3268 + if (cap_is_cached(sa->ival)) {
3269 + opspec_error = -EPERM;
3270 + goto skip_logging;
3274 + /* In future extend w/ per-profile flags
3275 + * (flags |= sa->active->flags)
3277 + flags = sa->flags;
3278 + if (apparmor_logsyscall)
3279 + flags |= AA_AUDITFLAG_AUDITSS_SYSCALL;
3282 + /* Force full audit syscall logging regardless of global setting if
3283 + * we are rejecting a syscall
3285 + if (sa->type == AA_AUDITTYPE_SYSCALL) {
3286 + ctx = current->audit_context;
3288 + ctx = (flags & AA_AUDITFLAG_AUDITSS_SYSCALL) ?
3289 + current->audit_context : NULL;
3292 + ab = audit_log_start(ctx, gfp_mask, AUDIT_SD);
3295 + AA_ERROR("Unable to log event (%d) to audit subsys\n",
3302 + /* messages get special handling */
3303 + if (sa->type == AA_AUDITTYPE_MSG) {
3304 + audit_log_vformat(ab, sa->name, sa->vaval);
3305 + audit_log_end(ab);
3310 + /* log operation */
3312 + audit_log_format(ab, "%s ", logcls); /* REJECTING/ALLOWING/etc */
3314 + if (sa->type == AA_AUDITTYPE_FILE) {
3315 + int perm = audit ? sa->ival : sa->error_code;
3317 + audit_log_format(ab, "%s%s%s%s%s access to %s ",
3318 + perm & AA_EXEC_MMAP ? "m" : "",
3319 + perm & AA_MAY_READ ? "r" : "",
3320 + perm & AA_MAY_WRITE ? "w" : "",
3321 + perm & AA_MAY_EXEC ? "x" : "",
3322 + perm & AA_MAY_LINK ? "l" : "",
3325 + opspec_error = -EPERM;
3327 + } else if (sa->type == AA_AUDITTYPE_DIR) {
3328 + audit_log_format(ab, "%s on %s ",
3329 + sa->ival == aa_dir_mkdir ? "mkdir" : "rmdir",
3332 + } else if (sa->type == AA_AUDITTYPE_ATTR) {
3333 + struct iattr *iattr = (struct iattr*)sa->pval;
3335 + audit_log_format(ab,
3336 + "attribute (%s%s%s%s%s%s%s) change to %s ",
3337 + iattr->ia_valid & ATTR_MODE ? "mode," : "",
3338 + iattr->ia_valid & ATTR_UID ? "uid," : "",
3339 + iattr->ia_valid & ATTR_GID ? "gid," : "",
3340 + iattr->ia_valid & ATTR_SIZE ? "size," : "",
3341 + ((iattr->ia_valid & ATTR_ATIME_SET) ||
3342 + (iattr->ia_valid & ATTR_ATIME)) ? "atime," : "",
3343 + ((iattr->ia_valid & ATTR_MTIME_SET) ||
3344 + (iattr->ia_valid & ATTR_MTIME)) ? "mtime," : "",
3345 + iattr->ia_valid & ATTR_CTIME ? "ctime," : "",
3348 + } else if (sa->type == AA_AUDITTYPE_XATTR) {
3350 + switch (sa->ival) {
3351 + case aa_xattr_get:
3352 + fmt = "xattr get";
3354 + case aa_xattr_set:
3355 + fmt = "xattr set";
3357 + case aa_xattr_list:
3358 + fmt = "xattr list";
3360 + case aa_xattr_remove:
3361 + fmt = "xattr remove";
3364 + fmt = "xattr <unknown>";
3368 + audit_log_format(ab, "%s on %s ", fmt, sa->name);
3370 + } else if (sa->type == AA_AUDITTYPE_LINK) {
3371 + audit_log_format(ab,
3372 + "link access from %s to %s ",
3376 + } else if (sa->type == AA_AUDITTYPE_CAP) {
3377 + audit_log_format(ab,
3378 + "access to capability '%s' ",
3379 + capability_to_name(sa->ival));
3380 + add_to_cached_caps(sa->ival);
3381 + opspec_error = -EPERM;
3382 + } else if (sa->type == AA_AUDITTYPE_SYSCALL) {
3383 + audit_log_format(ab, "access to syscall '%s' ", sa->name);
3385 + opspec_error = -EPERM;
3387 + /* -EINVAL -- will WARN_ON above */
3391 + audit_log_format(ab, "(%s(%d) profile %s active %s)",
3392 + current->comm, current->pid,
3393 + BASE_PROFILE(active)->name, active->name);
3395 + audit_log_end(ab);
3401 + error = sa->result ? 0 : opspec_error;
3408 + * aa_get_name - retrieve fully qualified path name
3409 + * @dentry: relative path element
3410 + * @mnt: where in tree
3412 + * Returns fully qualified path name on sucess, NULL on failure.
3413 + * aa_put_name must be used to free allocated buffer.
3415 +char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt)
3417 + char *page, *name;
3419 + page = (char *)__get_free_page(GFP_KERNEL);
3421 + name = ERR_PTR(-ENOMEM);
3425 + name = d_path(dentry, mnt, page, PAGE_SIZE);
3426 + /* check for (deleted) that d_path appends to pathnames if the dentry
3427 + * has been removed from the cache.
3428 + * The size > deleted_size and strcmp checks are redundant safe guards.
3430 + if (IS_ERR(name)) {
3431 + free_page((unsigned long)page);
3433 + const char deleted_str[] = " (deleted)";
3434 + const size_t deleted_size = sizeof(deleted_str) - 1;
3436 + size = strlen(name);
3437 + if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
3438 + size > deleted_size &&
3439 + strcmp(name + size - deleted_size, deleted_str) == 0)
3440 + name[size - deleted_size] = '\0';
3441 + AA_DEBUG("%s: full_path=%s\n", __FUNCTION__, name);
3448 +/***********************************
3449 + * Global permission check functions
3450 + ***********************************/
3453 + * aa_attr - check whether attribute change allowed
3454 + * @active: profile to check against
3455 + * @dentry: file to check
3456 + * @iattr: attribute changes requested
3458 +int aa_attr(struct aaprofile *active, struct dentry *dentry,
3459 + struct iattr *iattr)
3461 + int error = 0, permerror;
3462 + struct aa_audit sa;
3464 + sa.type = AA_AUDITTYPE_ATTR;
3467 + sa.gfp_mask = GFP_KERNEL;
3469 + permerror = _aa_perm_dentry(active, dentry, MAY_WRITE, &sa.name);
3470 + aa_permerror2result(permerror, &sa);
3472 + error = aa_audit(active, &sa);
3474 + aa_put_name(sa.name);
3480 + * aa_xattr - check whether xattr attribute change allowed
3481 + * @active: profile to check against
3482 + * @dentry: file to check
3483 + * @xattr: xattr to check
3484 + * @xattroptype: type of xattr operation
3486 +int aa_xattr(struct aaprofile *active, struct dentry *dentry,
3487 + const char *xattr, enum aa_xattroptype xattroptype)
3489 + int error = 0, permerror, mask = 0;
3490 + struct aa_audit sa;
3492 + /* if not confined or empty mask permission granted */
3496 + if (xattroptype == aa_xattr_get || xattroptype == aa_xattr_list)
3498 + else if (xattroptype == aa_xattr_set || xattroptype == aa_xattr_remove)
3501 + sa.type = AA_AUDITTYPE_XATTR;
3502 + sa.ival = xattroptype;
3505 + sa.gfp_mask = GFP_KERNEL;
3507 + permerror = _aa_perm_dentry(active, dentry, mask, &sa.name);
3508 + aa_permerror2result(permerror, &sa);
3510 + error = aa_audit(active, &sa);
3512 + aa_put_name(sa.name);
3519 + * aa_perm - basic apparmor permissions check
3520 + * @active: profile to check against
3522 + * @mnt: mountpoint
3523 + * @mask: access mode requested
3525 + * Determine if access (mask) for dentry is authorized by active
3526 + * profile. Result, %0 (success), -ve (error)
3528 +int aa_perm(struct aaprofile *active, struct dentry *dentry,
3529 + struct vfsmount *mnt, int mask)
3531 + int error = 0, permerror;
3532 + struct aa_audit sa;
3537 + if ((mask = aa_filter_mask(mask, dentry->d_inode)) == 0)
3540 + sa.type = AA_AUDITTYPE_FILE;
3541 + sa.name = aa_get_name(dentry, mnt);
3544 + sa.gfp_mask = GFP_KERNEL;
3546 + if (IS_ERR(sa.name)) {
3547 + permerror = PTR_ERR(sa.name);
3550 + permerror = aa_file_perm(active, sa.name, mask);
3553 + aa_permerror2result(permerror, &sa);
3555 + error = aa_audit(active, &sa);
3557 + aa_put_name(sa.name);
3564 + * aa_perm_nameidata: interface to sd_perm accepting nameidata
3565 + * @active: profile to check against
3566 + * @nd: namespace data (for vfsmnt and dentry)
3567 + * @mask: access mode requested
3569 +int aa_perm_nameidata(struct aaprofile *active, struct nameidata *nd, int mask)
3574 + error = aa_perm(active, nd->dentry, nd->mnt, mask);
3580 + * aa_perm_dentry - file permissions interface when no vfsmnt available
3581 + * @active: profile to check against
3582 + * @dentry: requested dentry
3583 + * @mask: access mode requested
3585 + * Determine if access (mask) for dentry is authorized by active profile.
3586 + * Result, %0 (success), -ve (error)
3588 +int aa_perm_dentry(struct aaprofile *active, struct dentry *dentry, int mask)
3590 + int error = 0, permerror;
3591 + struct aa_audit sa;
3596 + if ((mask = aa_filter_mask(mask, dentry->d_inode)) == 0)
3599 + sa.type = AA_AUDITTYPE_FILE;
3602 + sa.gfp_mask = GFP_KERNEL;
3604 + permerror = _aa_perm_dentry(active, dentry, mask, &sa.name);
3605 + aa_permerror2result(permerror, &sa);
3607 + error = aa_audit(active, &sa);
3609 + aa_put_name(sa.name);
3617 + * @active: profile to check against
3618 + * @dentry: requested dentry
3619 + * @diroptype: aa_dir_mkdir or aa_dir_rmdir
3621 + * Determine if directory operation (make/remove) for dentry is authorized
3622 + * by @active profile.
3623 + * Result, %0 (success), -ve (error)
3625 +int aa_perm_dir(struct aaprofile *active, struct dentry *dentry,
3626 + enum aa_diroptype diroptype)
3628 + int error = 0, permerror, mask;
3629 + struct aa_audit sa;
3631 + WARN_ON(diroptype != aa_dir_mkdir && diroptype != aa_dir_rmdir);
3638 + sa.type = AA_AUDITTYPE_DIR;
3639 + sa.ival = diroptype;
3641 + sa.gfp_mask = GFP_KERNEL;
3643 + permerror = _aa_perm_dentry(active, dentry, mask, &sa.name);
3644 + aa_permerror2result(permerror, &sa);
3646 + error = aa_audit(active, &sa);
3648 + aa_put_name(sa.name);
3655 + * aa_capability - test permission to use capability
3656 + * @active: profile to check against
3657 + * @cap: capability to be tested
3659 + * Look up capability in active profile capability set.
3660 + * Return %0 (success), -%EPERM (error)
3662 +int aa_capability(struct aaprofile *active, int cap)
3666 + struct aa_audit sa;
3668 + sa.type = AA_AUDITTYPE_CAP;
3672 + sa.error_code = 0;
3673 + sa.result = cap_raised(active->capabilities, cap);
3674 + sa.gfp_mask = GFP_ATOMIC;
3676 + error = aa_audit(active, &sa);
3682 + * aa_link - hard link check
3683 + * @active: profile to check against
3684 + * @link: dentry for link being created
3685 + * @target: dentry for link target
3687 + * Checks link permissions for all possible name combinations. This is
3688 + * particularly ugly. Returns %0 on sucess, error otherwise.
3690 +int aa_link(struct aaprofile *active, struct dentry *link,
3691 + struct dentry *target)
3693 + char *iname = NULL, *oname = NULL,
3694 + *failed_iname = NULL, *failed_oname = NULL;
3695 + unsigned int result = 0;
3696 + int error, path_error, error_code = 0, match = 0,
3697 + complain = PROFILE_COMPLAIN(active);
3698 + struct aa_path_data idata, odata;
3699 + struct aa_audit sa;
3704 + /* Perform nested lookup for names.
3705 + * This is necessary in the case where /dev/block is mounted
3706 + * multiple times, i.e /dev/block->/a and /dev/block->/b
3707 + * This allows us to detect links where src/dest are on different
3708 + * mounts. N.B no support yet for links across bind mounts of
3709 + * the form mount -bind /mnt/subpath /mnt2
3711 + * Getting direct access to vfsmounts (via nameidata) for link and
3712 + * target would allow all this uglyness to go away.
3714 + * If more than one mountpoint matches but none satisfy the profile,
3715 + * only the first pathname (mountpoint) is logged.
3718 + __aa_path_begin(target, link, &odata);
3720 + oname = aa_path_getname(&odata);
3722 + aa_path_begin(target, &idata);
3724 + iname = aa_path_getname(&idata);
3726 + result = aa_link_perm(active, oname,
3729 + /* access via any path is enough */
3730 + if (result || complain) {
3735 + /* Already have an path that failed? */
3736 + if (failed_iname) {
3737 + aa_put_name(iname);
3739 + failed_iname = iname;
3740 + failed_oname = oname;
3743 + } while (iname && !match);
3745 + /* should not be possible if we matched */
3746 + if ((path_error = aa_path_end(&idata)) != 0) {
3747 + dentry_xlate_error(target, path_error,
3748 + "inner dentry [link]");
3750 + /* name should not be set if error */
3753 + error_code = path_error;
3756 + /* don't release if we're saving it */
3757 + if (!match && failed_oname != oname)
3758 + aa_put_name(oname);
3760 + } while (oname && !match);
3762 + if (error_code != 0) {
3764 + (void)aa_path_end(&odata);
3765 + } else if ((path_error = aa_path_end(&odata)) != 0) {
3766 + dentry_xlate_error(link, path_error, "outer dentry [link]");
3767 + error_code = path_error;
3770 + if (error_code != 0) {
3771 + /* inner or outer error */
3773 + } else if (!match) {
3774 + /* failed to match */
3779 + iname = failed_iname;
3780 + oname = failed_oname;
3783 + sa.type = AA_AUDITTYPE_LINK;
3784 + sa.name = oname; /* link */
3785 + sa.pval = iname; /* target */
3787 + sa.error_code = error_code;
3788 + sa.result = result;
3789 + sa.gfp_mask = GFP_KERNEL;
3791 + error = aa_audit(active, &sa);
3793 + if (failed_oname != oname)
3794 + aa_put_name(failed_oname);
3795 + if (failed_iname != iname)
3796 + aa_put_name(failed_iname);
3798 + aa_put_name(oname);
3799 + aa_put_name(iname);
3804 +/*******************************
3805 + * Global task related functions
3806 + *******************************/
3809 + * aa_fork - create a new subdomain
3812 + * Create a new subdomain for newly created process @p if it's parent
3813 + * is already confined. Otherwise a subdomain will be lazily allocated
3814 + * will get one with NULL values. Return 0 on sucess.
3815 + * for the child if it subsequently execs (in aa_register).
3816 + * Return 0 on sucess.
3818 + * The sd_lock is used to maintain consistency against profile
3819 + * replacement/removal.
3822 +int aa_fork(struct task_struct *p)
3824 + struct subdomain *sd = AA_SUBDOMAIN(current->security);
3825 + struct subdomain *newsd = NULL;
3827 + AA_DEBUG("%s\n", __FUNCTION__);
3829 + if (__aa_is_confined(sd)) {
3830 + unsigned long flags;
3832 + newsd = alloc_subdomain(p);
3837 + /* Use locking here instead of getting the reference
3838 + * because we need both the old reference and the
3839 + * new reference to be consistent.
3841 + spin_lock_irqsave(&sd_lock, flags);
3842 + aa_switch(newsd, sd->active);
3843 + newsd->hat_magic = sd->hat_magic;
3844 + spin_unlock_irqrestore(&sd_lock, flags);
3846 + if (SUBDOMAIN_COMPLAIN(sd) &&
3847 + sd->active == null_complain_profile)
3848 + LOG_HINT(sd->active, GFP_KERNEL, HINT_FORK,
3849 + "pid=%d child=%d\n",
3850 + current->pid, p->pid);
3852 + p->security = newsd;
3857 + * aa_register - register a new program
3858 + * @bprm: binprm of program being registered
3860 + * Try to register a new program during execve(). This should give the
3861 + * new program a valid subdomain.
3863 +int aa_register(struct linux_binprm *bprm)
3866 + struct file *filp = bprm->file;
3867 + struct aaprofile *active;
3868 + struct aaprofile *newprofile = NULL, unconstrained_flag;
3869 + int error = -ENOMEM,
3872 + find_profile_mandatory = 0,
3876 + AA_DEBUG("%s\n", __FUNCTION__);
3878 + filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt);
3879 + if (IS_ERR(filename)) {
3880 + AA_WARN("%s: Failed to get filename\n", __FUNCTION__);
3886 + active = get_active_aaprofile();
3889 + /* Unconfined task, load profile if it exists */
3891 + goto find_profile;
3894 + complain = PROFILE_COMPLAIN(active);
3896 + /* Confined task, determine what mode inherit, unconstrained or
3897 + * mandatory to load new profile
3899 + if (aa_get_execmode(active, filename, &exec_mode, &unsafe_exec)) {
3900 + switch (exec_mode) {
3901 + case AA_EXEC_INHERIT:
3902 + /* do nothing - setting of profile
3903 + * already handed in aa_fork
3905 + AA_DEBUG("%s: INHERIT %s\n",
3910 + case AA_EXEC_UNCONSTRAINED:
3911 + AA_DEBUG("%s: UNCONSTRAINED %s\n",
3915 + /* unload profile */
3916 + newprofile = &unconstrained_flag;
3919 + case AA_EXEC_PROFILE:
3920 + AA_DEBUG("%s: PROFILE %s\n",
3925 + find_profile_mandatory = 1;
3929 + /* this should not happen, entries
3930 + * with just EXEC only should be
3931 + * rejected at profile load time
3933 + AA_ERROR("%s: Rejecting exec(2) of image '%s'. "
3934 + "AA_MAY_EXEC without exec qualifier invalid "
3935 + "(%s(%d) profile %s active %s\n",
3938 + current->comm, current->pid,
3939 + BASE_PROFILE(active)->name, active->name);
3944 + AA_ERROR("%s: Rejecting exec(2) of image '%s'. "
3945 + "Unknown exec qualifier %x "
3946 + "(%s (pid %d) profile %s active %s)\n",
3950 + current->comm, current->pid,
3951 + BASE_PROFILE(active)->name, active->name);
3956 + } else if (complain) {
3957 + /* There was no entry in calling profile
3958 + * describing mode to execute image in.
3959 + * Drop into null-profile (disabling secure exec).
3961 + newprofile = get_aaprofile(null_complain_profile);
3964 + AA_WARN("%s: Rejecting exec(2) of image '%s'. "
3965 + "Unable to determine exec qualifier "
3966 + "(%s (pid %d) profile %s active %s)\n",
3969 + current->comm, current->pid,
3970 + BASE_PROFILE(active)->name, active->name);
3976 + if (!find_profile)
3977 + goto apply_profile;
3979 + /* Locate new profile */
3980 + newprofile = aa_profilelist_find(filename);
3982 + AA_DEBUG("%s: setting profile %s\n",
3983 + __FUNCTION__, newprofile->name);
3984 + } else if (find_profile_mandatory) {
3985 + /* Profile (mandatory) could not be found */
3988 + LOG_HINT(active, GFP_KERNEL, HINT_MANDPROF,
3989 + "image=%s pid=%d profile=%s active=%s\n",
3992 + BASE_PROFILE(active)->name, active->name);
3994 + newprofile = get_aaprofile(null_complain_profile);
3996 + AA_WARN("REJECTING exec(2) of image '%s'. "
3997 + "Profile mandatory and not found "
3998 + "(%s(%d) profile %s active %s)\n",
4000 + current->comm, current->pid,
4001 + BASE_PROFILE(active)->name, active->name);
4005 + /* Profile (non-mandatory) could not be found */
4007 + /* Only way we can get into this code is if task
4008 + * is unconstrained.
4013 + AA_DEBUG("%s: No profile found for exec image %s\n",
4016 + } /* newprofile */
4020 + /* Apply profile if necessary */
4022 + struct subdomain *sd, *lazy_sd = NULL;
4023 + unsigned long flags;
4025 + if (newprofile == &unconstrained_flag)
4026 + newprofile = NULL;
4028 + /* grab a lock - this is to guarentee consistency against
4029 + * other writers of subdomain (replacement/removal)
4031 + * Several things may have changed since the code above
4033 + * - Task may be presently unconfined (have no sd). In which
4034 + * case we have to lazily allocate one. Note we may be raced
4035 + * to this allocation by a setprofile.
4037 + * - If we are a confined process, active is a refcounted copy
4038 + * of the profile that was on the subdomain at entry.
4039 + * This allows us to not have to hold a lock around
4040 + * all this code. If profile replacement has taken place
4041 + * our active may not equal sd->active any more.
4042 + * This is okay since the operation is treated as if
4043 + * the transition occured before replacement.
4045 + * - If newprofile points to an actual profile (result of
4046 + * aa_profilelist_find above), this profile may have been
4047 + * replaced. We need to fix it up. Doing this to avoid
4048 + * having to hold a lock around all this code.
4051 + if (!active && !(sd = AA_SUBDOMAIN(current->security))) {
4052 + lazy_sd = alloc_subdomain(current);
4054 + AA_ERROR("%s: Failed to allocate subdomain\n",
4061 + spin_lock_irqsave(&sd_lock, flags);
4063 + sd = AA_SUBDOMAIN(current->security);
4066 + /* raced by setprofile - created sd */
4067 + free_subdomain(lazy_sd);
4070 + /* Not rcu used to get the write barrier
4072 + rcu_assign_pointer(current->security, lazy_sd);
4077 + /* Determine if profile we found earlier is stale.
4078 + * If so, reobtain it. N.B stale flag should never be
4079 + * set on null_complain profile.
4081 + if (newprofile && unlikely(newprofile->isstale)) {
4082 + WARN_ON(newprofile == null_complain_profile);
4084 + /* drop refcnt obtained from earlier get_aaprofile */
4085 + put_aaprofile(newprofile);
4087 + newprofile = aa_profilelist_find(filename);
4089 + if (!newprofile) {
4090 + /* Race, profile was removed, not replaced.
4091 + * Redo with error checking
4093 + spin_unlock_irqrestore(&sd_lock, flags);
4094 + goto find_profile;
4098 + /* Handle confined exec.
4099 + * Can be at this point for the following reasons:
4100 + * 1. unconfined switching to confined
4101 + * 2. confined switching to different confinement
4102 + * 3. confined switching to unconfined
4104 + * Cases 2 and 3 are marked as requiring secure exec
4105 + * (unless policy specified "unsafe exec")
4107 + if (__aa_is_confined(sd) && !unsafe_exec) {
4108 + unsigned long bprm_flags;
4110 + bprm_flags = AA_SECURE_EXEC_NEEDED;
4111 + bprm->security = (void*)
4112 + ((unsigned long)bprm->security | bprm_flags);
4115 + aa_switch(sd, newprofile);
4116 + put_aaprofile(newprofile);
4118 + if (complain && newprofile == null_complain_profile)
4119 + LOG_HINT(newprofile, GFP_ATOMIC, HINT_CHGPROF,
4123 + spin_unlock_irqrestore(&sd_lock, flags);
4127 + aa_put_name(filename);
4129 + put_aaprofile(active);
4136 + * aa_release - release the task's subdomain
4137 + * @p: task being released
4139 + * This is called after a task has exited and the parent has reaped it.
4140 + * @p->security blob is freed.
4142 + * This is the one case where we don't need to hold the sd_lock before
4143 + * removing a profile from a subdomain. Once the subdomain has been
4144 + * removed from the subdomain_list, we are no longer racing other writers.
4145 + * There may still be other readers so we must still use aa_switch
4146 + * to put the subdomain's reference safely.
4148 +void aa_release(struct task_struct *p)
4150 + struct subdomain *sd = AA_SUBDOMAIN(p->security);
4152 + p->security = NULL;
4154 + aa_subdomainlist_remove(sd);
4155 + aa_switch_unconfined(sd);
4161 +/*****************************
4162 + * global subprofile functions
4163 + ****************************/
4166 + * do_change_hat - actually switch hats
4167 + * @hat_name: name of hat to swtich to
4168 + * @sd: current subdomain
4170 + * Switch to a new hat. Return %0 on success, error otherwise.
4172 +static inline int do_change_hat(const char *hat_name, struct subdomain *sd)
4174 + struct aaprofile *sub;
4177 + sub = __aa_find_profile(hat_name, &BASE_PROFILE(sd->active)->sub);
4181 + aa_switch(sd, sub);
4182 + put_aaprofile(sub);
4184 + /* There is no such subprofile change to a NULL profile.
4185 + * The NULL profile grants no file access.
4187 + * This feature is used by changehat_apache.
4189 + * N.B from the null-profile the task can still changehat back
4190 + * out to the parent profile (assuming magic != NULL)
4192 + if (SUBDOMAIN_COMPLAIN(sd)) {
4193 + LOG_HINT(sd->active, GFP_ATOMIC, HINT_UNKNOWN_HAT,
4195 + "profile=%s active=%s\n",
4198 + BASE_PROFILE(sd->active)->name,
4199 + sd->active->name);
4201 + AA_DEBUG("%s: Unknown hatname '%s'. "
4202 + "Changing to NULL profile "
4203 + "(%s(%d) profile %s active %s)\n",
4206 + current->comm, current->pid,
4207 + BASE_PROFILE(sd->active)->name,
4208 + sd->active->name);
4211 + aa_switch(sd, sd->active->null_profile);
4218 + * aa_change_hat - change hat to/from subprofile
4219 + * @hat_name: specifies hat to change to
4220 + * @hat_magic: token to validate hat change
4222 + * Change to new @hat_name when current hat is top level profile, and store
4223 + * the @hat_magic in the current subdomain. If the new @hat_name is
4224 + * %NULL, and the @hat_magic matches that stored in the current subdomain
4225 + * return to original top level profile. Returns %0 on success, error
4228 +int aa_change_hat(const char *hat_name, u32 hat_magic)
4230 + struct subdomain *sd = AA_SUBDOMAIN(current->security);
4233 + AA_DEBUG("%s: %p, 0x%x (pid %d)\n",
4235 + hat_name, hat_magic,
4238 + /* Dump out above debugging in WARN mode if we are in AUDIT mode */
4239 + if (SUBDOMAIN_AUDIT(sd)) {
4240 + AA_WARN("%s: %s, 0x%x (pid %d)\n",
4241 + __FUNCTION__, hat_name ? hat_name : "NULL",
4242 + hat_magic, current->pid);
4245 + /* check to see if an unconfined process is doing a changehat. */
4246 + if (!__aa_is_confined(sd)) {
4251 + /* check to see if the confined process has any hats. */
4252 + if (list_empty(&BASE_PROFILE(sd->active)->sub) &&
4253 + !PROFILE_COMPLAIN(sd->active)) {
4258 + /* Check whether current domain is parent
4259 + * or one of the sibling children
4261 + if (!IN_SUBPROFILE(sd->active)) {
4266 + AA_DEBUG("%s: switching to %s, 0x%x\n",
4272 + * N.B hat_magic == 0 has a special meaning
4273 + * this indicates that the task may never changehat
4274 + * back to it's parent, it will stay in this subhat
4275 + * (or null-profile, if the hat doesn't exist) until
4276 + * the task terminates
4278 + sd->hat_magic = hat_magic;
4279 + error = do_change_hat(hat_name, sd);
4281 + /* Got here via changehat(NULL, magic)
4283 + * We used to simply update the magic cookie.
4284 + * That's an odd behaviour, so just do nothing.
4289 + * child -- check to make sure magic is same as what was
4290 + * passed when we switched into this profile,
4291 + * Handle special casing of NULL magic which confines task
4292 + * to subprofile and prohibits further changehats
4294 + if (hat_magic == sd->hat_magic && sd->hat_magic) {
4297 + * Got here via changehat(NULL, magic)
4298 + * Return from subprofile, back to parent
4300 + aa_switch(sd, sd->active->parent);
4302 + /* Reset hat_magic to zero.
4303 + * New value will be passed on next changehat
4305 + sd->hat_magic = 0;
4307 + /* change to another (sibling) profile */
4308 + error = do_change_hat(hat_name, sd);
4310 + } else if (sd->hat_magic) {
4311 + AA_ERROR("KILLING process %s(%d) "
4312 + "Invalid change_hat() magic# 0x%x "
4313 + "(hatname %s profile %s active %s)\n",
4314 + current->comm, current->pid,
4316 + hat_name ? hat_name : "NULL",
4317 + BASE_PROFILE(sd->active)->name,
4318 + sd->active->name);
4320 + /* terminate current process */
4321 + (void)send_sig_info(SIGKILL, NULL, current);
4322 + } else { /* sd->hat_magic == NULL */
4323 + AA_ERROR("KILLING process %s(%d) "
4324 + "Task was confined to current subprofile "
4325 + "(profile %s active %s)\n",
4326 + current->comm, current->pid,
4327 + BASE_PROFILE(sd->active)->name,
4328 + sd->active->name);
4330 + /* terminate current process */
4331 + (void)send_sig_info(SIGKILL, NULL, current);
4339 Index: b/security/apparmor/match/Kbuild
4340 ===================================================================
4342 +++ b/security/apparmor/match/Kbuild
4344 +# Makefile for AppArmor aamatch submodule
4347 +obj-$(CONFIG_SECURITY_APPARMOR) += aamatch_pcre.o
4349 +aamatch_pcre-y := match_pcre.o pcre_exec.o
4350 Index: b/security/apparmor/match/Makefile
4351 ===================================================================
4353 +++ b/security/apparmor/match/Makefile
4355 +# Makefile for AppArmor aamatch submodule
4357 +obj-$(CONFIG_SECURITY_APPARMOR) += aamatch_pcre.o
4359 +aamatch_pcre-y := match_pcre.o pcre_exec.o
4360 Index: b/security/apparmor/match/match.h
4361 ===================================================================
4363 +++ b/security/apparmor/match/match.h
4366 + * Copyright (C) 2002-2005 Novell/SUSE
4368 + * This program is free software; you can redistribute it and/or
4369 + * modify it under the terms of the GNU General Public License as
4370 + * published by the Free Software Foundation, version 2 of the
4373 + * AppArmor submodule (match) prototypes
4379 +#include "../module_interface.h"
4380 +#include "../apparmor.h"
4382 +/* The following functions implement an interface used by the primary
4383 + * AppArmor module to perform name matching (n.b. "AppArmor" was previously
4384 + * called "SubDomain").
4388 + * aamatch_features
4389 + * aamatch_serialize
4392 + * The intent is for the primary module to export (via virtual fs entries)
4393 + * the features provided by the submodule (aamatch_features) so that the
4394 + * parser may only load policy that can be supported.
4396 + * The primary module will call aamatch_serialize to allow the submodule
4397 + * to consume submodule specific data from parser data stream and will call
4398 + * aamatch_match to determine if a pathname matches an aa_entry.
4401 +typedef int (*aamatch_serializecb)
4402 + (struct aa_ext *, enum aa_code, void *, const char *);
4405 + * aamatch_alloc: allocate extradata (if necessary)
4406 + * @type: type of entry being allocated
4407 + * Return value: NULL indicates no data was allocated (ERR_PTR(x) on error)
4409 +extern void* aamatch_alloc(enum entry_match_type type);
4412 + * aamatch_free: release data allocated by aamatch_alloc
4413 + * @entry_extradata: data previously allocated by aamatch_alloc
4415 +extern void aamatch_free(void *entry_extradata);
4418 + * aamatch_features: return match types supported
4419 + * Return value: space seperated string (of types supported - use type=value
4420 + * to indicate variants of a type)
4422 +extern const char* aamatch_features(void);
4425 + * aamatch_serialize: serialize extradata
4426 + * @entry_extradata: data previously allocated by aamatch_alloc
4427 + * @e: input stream
4428 + * @cb: callback fn (consume incoming data stream)
4429 + * Return value: 0 success, -ve error
4431 +extern int aamatch_serialize(void *entry_extradata, struct aa_ext *e,
4432 + aamatch_serializecb cb);
4435 + * aamatch_match: determine if pathname matches entry
4436 + * @pathname: pathname to verify
4437 + * @entry_name: entry name
4438 + * @type: type of entry
4439 + * @entry_extradata: data previously allocated by aamatch_alloc
4440 + * Return value: 1 match, 0 othersise
4442 +extern unsigned int aamatch_match(const char *pathname, const char *entry_name,
4443 + enum entry_match_type type,
4444 + void *entry_extradata);
4448 + * sd_getmatch_type - return string representation of entry_match_type
4449 + * @type: entry match type
4451 +static inline const char *sd_getmatch_type(enum entry_match_type type)
4453 + const char *names[] = {
4454 + "aa_entry_literal",
4455 + "aa_entry_tailglob",
4456 + "aa_entry_pattern",
4457 + "aa_entry_invalid"
4460 + if (type >= aa_entry_invalid) {
4461 + type = aa_entry_invalid;
4464 + return names[type];
4468 + * aamatch_match_common - helper function to check if a pathname matches
4469 + * a literal/tailglob
4470 + * @path: path requested to search for
4471 + * @entry_name: name from aa_entry
4472 + * @type: type of entry
4474 +static inline int aamatch_match_common(const char *path,
4475 + const char *entry_name,
4476 + enum entry_match_type type)
4480 + /* literal, no pattern matching characters */
4481 + if (type == aa_entry_literal) {
4482 + retval = (strcmp(entry_name, path) == 0);
4483 + /* trailing ** glob pattern */
4484 + } else if (type == aa_entry_tailglob) {
4485 + retval = (strncmp(entry_name, path,
4486 + strlen(entry_name) - 2) == 0);
4488 + AA_WARN("%s: Invalid entry_match_type %d\n",
4489 + __FUNCTION__, type);
4496 +#endif /* __MATCH_H */
4497 Index: b/security/apparmor/match/match_default.c
4498 ===================================================================
4500 +++ b/security/apparmor/match/match_default.c
4503 + * Copyright (C) 2002-2005 Novell/SUSE
4505 + * This program is free software; you can redistribute it and/or
4506 + * modify it under the terms of the GNU General Public License as
4507 + * published by the Free Software Foundation, version 2 of the
4510 + * http://forge.novell.com/modules/xfmod/project/?apparmor
4512 + * AppArmor default match submodule (literal and tailglob)
4515 +#include <linux/module.h>
4518 +static const char *features="literal tailglob";
4520 +void* aamatch_alloc(enum entry_match_type type)
4525 +void aamatch_free(void *ptr)
4529 +const char *aamatch_features(void)
4534 +int aamatch_serialize(void *entry_extradata, struct aa_ext *e,
4535 + aamatch_serializecb cb)
4540 +unsigned int aamatch_match(const char *pathname, const char *entry_name,
4541 + enum entry_match_type type, void *entry_extradata)
4545 + ret = aamatch_match_common(pathname, entry_name, type);
4550 +EXPORT_SYMBOL_GPL(aamatch_alloc);
4551 +EXPORT_SYMBOL_GPL(aamatch_free);
4552 +EXPORT_SYMBOL_GPL(aamatch_features);
4553 +EXPORT_SYMBOL_GPL(aamatch_serialize);
4554 +EXPORT_SYMBOL_GPL(aamatch_match);
4556 +MODULE_DESCRIPTION("AppArmor match module (aamatch) [default]");
4557 +MODULE_AUTHOR("Tony Jones <tonyj@suse.de>");
4558 +MODULE_LICENSE("GPL");
4559 Index: b/security/apparmor/match/match_pcre.c
4560 ===================================================================
4562 +++ b/security/apparmor/match/match_pcre.c
4565 + * Copyright (C) 2002-2005 Novell/SUSE
4567 + * This program is free software; you can redistribute it and/or
4568 + * modify it under the terms of the GNU General Public License as
4569 + * published by the Free Software Foundation, version 2 of the
4572 + * http://forge.novell.com/modules/xfmod/project/?apparmor
4574 + * AppArmor aamatch submodule (w/ pattern expansion).
4576 + * This module makes use of a slightly modified version of the PCRE
4577 + * library developed by Philip Hazel <ph10@cam.ac.uk>. See the files
4578 + * pcre_* in this directory.
4581 +#include <linux/module.h>
4583 +#include "pcre_exec.h"
4584 +#include "pcre_tables.h"
4586 +static const char *features="literal tailglob pattern=pcre";
4588 +struct aamatch_entry
4594 +void* aamatch_alloc(enum entry_match_type entry_type)
4598 + if (entry_type == aa_entry_pattern) {
4599 + ptr = kmalloc(sizeof(struct aamatch_entry), GFP_KERNEL);
4601 + memset(ptr, 0, sizeof(struct aamatch_entry));
4603 + ptr=ERR_PTR(-ENOMEM);
4604 + } else if (entry_type != aa_entry_literal &&
4605 + entry_type != aa_entry_tailglob) {
4606 + ptr = ERR_PTR(-EINVAL);
4612 +void aamatch_free(void *ptr)
4615 + struct aamatch_entry *ed = (struct aamatch_entry *) ptr;
4616 + kfree(ed->pattern);
4617 + kfree(ed->compiled); /* allocated by AA_READ_X */
4622 +const char *aamatch_features(void)
4627 +int aamatch_serialize(void *entry_extradata, struct aa_ext *e,
4628 + aamatch_serializecb cb)
4630 +#define AA_READ_X(E, C, D, N) \
4632 + if (!cb((E), (C), (D), (N))) { \
4633 + error = -EINVAL; \
4639 + u32 size, magic, opts;
4641 + struct aamatch_entry *ed = (struct aamatch_entry *) entry_extradata;
4646 + AA_READ_X(e, AA_DYN_STRING, &ed->pattern, NULL);
4648 + /* size determines the real size of the pcre struct,
4649 + it is size_t - sizeof(pcre) on user side.
4650 + uschar must be the same in user and kernel space */
4651 + /* check that we are processing the correct structure */
4652 + AA_READ_X(e, AA_STRUCT, NULL, "pcre");
4653 + AA_READ_X(e, AA_U32, &size, NULL);
4654 + AA_READ_X(e, AA_U32, &magic, NULL);
4656 + /* the allocation of pcre is delayed because it depends on the size
4657 + * of the pattern */
4658 + ed->compiled = (pcre *) kmalloc(size + sizeof(pcre), GFP_KERNEL);
4659 + if (!ed->compiled) {
4664 + memset(ed->compiled, 0, size + sizeof(pcre));
4665 + ed->compiled->magic_number = magic;
4666 + ed->compiled->size = size + sizeof(pcre);
4668 + AA_READ_X(e, AA_U32, &opts, NULL);
4669 + ed->compiled->options = opts;
4670 + AA_READ_X(e, AA_U16, &ed->compiled->top_bracket, NULL);
4671 + AA_READ_X(e, AA_U16, &ed->compiled->top_backref, NULL);
4672 + AA_READ_X(e, AA_U8, &t_char, NULL);
4673 + ed->compiled->first_char = t_char;
4674 + AA_READ_X(e, AA_U8, &t_char, NULL);
4675 + ed->compiled->req_char = t_char;
4676 + AA_READ_X(e, AA_U8, &t_char, NULL);
4677 + ed->compiled->code[0] = t_char;
4679 + AA_READ_X(e, AA_STATIC_BLOB, &ed->compiled->code[1], NULL);
4681 + AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
4683 + /* stitch in pcre patterns, it was NULLed out by parser
4684 + * pcre_default_tables defined in pcre_tables.h */
4685 + ed->compiled->tables = pcre_default_tables;
4688 + if (error != 0 && ed) {
4689 + kfree(ed->pattern); /* allocated by AA_READ_X */
4690 + kfree(ed->compiled);
4691 + ed->pattern = NULL;
4692 + ed->compiled = NULL;
4698 +unsigned int aamatch_match(const char *pathname, const char *entry_name,
4699 + enum entry_match_type entry_type, void *entry_extradata)
4703 + if (entry_type == aa_entry_pattern) {
4705 + struct aamatch_entry *ed =
4706 + (struct aamatch_entry *) entry_extradata;
4708 + pcreret = pcre_exec(ed->compiled, NULL,
4709 + pathname, strlen(pathname),
4712 + ret = (pcreret >= 0);
4714 + // XXX - this needs access to subdomain_debug, hmmm
4715 + //AA_DEBUG("%s(%d): %s %s %d\n", __FUNCTION__,
4716 + // ret, pathname, ed->pattern, pcreret);
4718 + ret = aamatch_match_common(pathname, entry_name, entry_type);
4724 +EXPORT_SYMBOL_GPL(aamatch_alloc);
4725 +EXPORT_SYMBOL_GPL(aamatch_free);
4726 +EXPORT_SYMBOL_GPL(aamatch_features);
4727 +EXPORT_SYMBOL_GPL(aamatch_serialize);
4728 +EXPORT_SYMBOL_GPL(aamatch_match);
4730 +MODULE_DESCRIPTION("AppArmor aa_match module [pcre]");
4731 +MODULE_AUTHOR("Tony Jones <tonyj@suse.de>");
4732 +MODULE_LICENSE("GPL");
4733 Index: b/security/apparmor/match/pcre_exec.c
4734 ===================================================================
4736 +++ b/security/apparmor/match/pcre_exec.c
4739 + * This is a modified version of pcre.c containing only the code/data
4740 + * required to support pcre_exec()
4744 +/*************************************************
4745 +* Perl-Compatible Regular Expressions *
4746 +*************************************************/
4749 +This is a library of functions to support regular expressions whose syntax
4750 +and semantics are as close as possible to those of the Perl 5 language. See
4751 +the file Tech.Notes for some information on the internals.
4753 +Written by: Philip Hazel <ph10@cam.ac.uk>
4755 + Copyright (c) 1997-2001 University of Cambridge
4757 +-----------------------------------------------------------------------------
4758 +Permission is granted to anyone to use this software for any purpose on any
4759 +computer system, and to redistribute it freely, subject to the following
4762 +1. This software is distributed in the hope that it will be useful,
4763 + but WITHOUT ANY WARRANTY; without even the implied warranty of
4764 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4766 +2. The origin of this software must not be misrepresented, either by
4767 + explicit claim or by omission.
4769 +3. Altered versions must be plainly marked as such, and must not be
4770 + misrepresented as being the original software.
4772 +4. If PCRE is embedded in any software that is released under the GNU
4773 + General Purpose Licence (GPL), then the terms of that licence shall
4774 + supersede any condition above with which it is incompatible.
4775 +-----------------------------------------------------------------------------
4779 +/* Define DEBUG to get debugging output on stdout. */
4781 +/* #define DEBUG */
4783 +/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
4784 +inline, and there are *still* stupid compilers about that don't like indented
4785 +pre-processor statements. I suppose it's only been 10 years... */
4788 +#define DPRINTF(p) PCRE_PRINTF p
4790 +#define DPRINTF(p) /*nothing*/
4793 +/* Include the internals header, which itself includes Standard C headers plus
4794 +the external pcre header. */
4796 +#include "pcre_exec.h"
4799 +/* ---- CODE DELETED ---- */
4802 +/* Min and max values for the common repeats; for the maxima, 0 => infinity */
4804 +static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
4805 +static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
4808 +/* ---- CODE DELETED ---- */
4811 +/* Structure for building a chain of data that actually lives on the
4812 + * stack, for holding the values of the subject pointer at the start of each
4813 + * subpattern, so as to detect when an empty string has been matched by a
4814 + * subpattern - to break infinite loops. */
4816 +typedef struct eptrblock {
4817 + struct eptrblock *prev;
4818 + const uschar *saved_eptr;
4821 +/* Flag bits for the match() function */
4823 +#define match_condassert 0x01 /* Called to check a condition assertion */
4824 +#define match_isgroup 0x02 /* Set if start of bracketed group */
4827 +/* ---- CODE DELETED ---- */
4830 +/*************************************************
4831 + * * Global variables *
4832 + * *************************************************/
4834 +/* PCRE is thread-clean and doesn't use any global variables in the normal
4835 + * sense. However, it calls memory allocation and free functions via the two
4836 + * indirections below, which are can be changed by the caller, but are shared
4837 + * between all threads. */
4840 +static void *kern_malloc(size_t sz)
4842 + return kmalloc(sz, GFP_KERNEL);
4844 +void *(*pcre_malloc)(size_t) = kern_malloc;
4845 +void (*pcre_free)(const void *) = kfree;
4847 +void *(*pcre_malloc)(size_t) = malloc;
4848 +void (*pcre_free)(const void *) = free;
4852 +/*************************************************
4853 + * * Macros and tables for character handling *
4854 + * *************************************************/
4856 +/* When UTF-8 encoding is being used, a character is no longer just a single
4857 + * byte. The macros for character handling generate simple sequences when used in
4858 + * byte-mode, and more complicated ones for UTF-8 characters. */
4860 +#ifndef SUPPORT_UTF8
4861 +#define GETCHARINC(c, eptr) c = *eptr++;
4862 +#define GETCHARLEN(c, eptr, len) c = *eptr;
4863 +#define BACKCHAR(eptr)
4866 +/* ---- CODE DELETED ---- */
4869 +/*************************************************
4870 +* Debugging function to print chars *
4871 +*************************************************/
4873 +/* Print a sequence of chars in printable format, stopping at the end of the
4874 +subject if the requested.
4877 + p points to characters
4878 + length number to print
4879 + is_subject TRUE if printing from within md->start_subject
4880 + md pointer to matching data block, if is_subject is TRUE
4886 +pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
4889 +if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
4890 +while (length-- > 0)
4891 + if (isprint(c = *(p++))) PCRE_PRINTF("%c", c); else PCRE_PRINTF("\\x%02x", c);
4895 +/* ---- CODE DELETED ---- */
4898 +/*************************************************
4899 +* Match a back-reference *
4900 +*************************************************/
4902 +/* If a back reference hasn't been set, the length that is passed is greater
4903 +than the number of characters left in the string, so the match fails.
4906 + offset index into the offset vector
4907 + eptr points into the subject
4908 + length length to be matched
4909 + md points to match data block
4912 +Returns: TRUE if matched
4916 +match_ref(int offset, register const uschar *eptr, int length, match_data *md,
4917 + unsigned long int ims)
4919 +const uschar *p = md->start_subject + md->offset_vector[offset];
4922 +if (eptr >= md->end_subject)
4923 + PCRE_PRINTF("matching subject <null>");
4926 + PCRE_PRINTF("matching subject ");
4927 + pchars(eptr, length, TRUE, md);
4929 +PCRE_PRINTF(" against backref ");
4930 +pchars(p, length, FALSE, md);
4934 +/* Always fail if not enough characters left */
4936 +if (length > md->end_subject - eptr) return FALSE;
4938 +/* Separate the caselesss case for speed */
4940 +if ((ims & PCRE_CASELESS) != 0)
4942 + while (length-- > 0)
4943 + if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
4946 + { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
4952 +/*************************************************
4953 +* Match from current position *
4954 +*************************************************/
4956 +/* On entry ecode points to the first opcode, and eptr to the first character
4957 +in the subject string, while eptrb holds the value of eptr at the start of the
4958 +last bracketed group - used for breaking infinite loops matching zero-length
4962 + eptr pointer in subject
4963 + ecode position in code
4964 + offset_top current top pointer
4965 + md pointer to "static" info for the match
4966 + ims current /i, /m, and /s options
4967 + eptrb pointer to chain of blocks containing eptr at start of
4968 + brackets - for testing for empty matches
4970 + match_condassert - this is an assertion condition
4971 + match_isgroup - this is the start of a bracketed group
4973 +Returns: TRUE if matched
4977 +match(register const uschar *eptr, register const uschar *ecode,
4978 + int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
4981 +unsigned long int original_ims = ims; /* Save for resetting on ')' */
4984 +/* At the start of a bracketed group, add the current subject pointer to the
4985 +stack of such pointers, to be re-instated at the end of the group when we hit
4986 +the closing ket. When match() is called in other circumstances, we don't add to
4989 +if ((flags & match_isgroup) != 0)
4991 + newptrb.prev = eptrb;
4992 + newptrb.saved_eptr = eptr;
4996 +/* Now start processing the operations. */
5000 + int op = (int)*ecode;
5001 + int min, max, ctype;
5004 + BOOL minimize = FALSE;
5006 + /* Opening capturing bracket. If there is space in the offset vector, save
5007 + the current subject position in the working slot at the top of the vector. We
5008 + mustn't change the current values of the data slot, because they may be set
5009 + from a previous iteration of this group, and be referred to by a reference
5012 + If the bracket fails to match, we need to restore this value and also the
5013 + values of the final offsets, in case they were set by a previous iteration of
5016 + If there isn't enough space in the offset vector, treat this as if it were a
5017 + non-capturing bracket. Don't worry about setting the flag for the error case
5018 + here; that is handled in the code for KET. */
5023 + int number = op - OP_BRA;
5025 + /* For extended extraction brackets (large number), we have to fish out the
5026 + number from a dummy opcode at the start. */
5028 + if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5];
5029 + offset = number << 1;
5032 + PCRE_PRINTF("start bracket %d subject=", number);
5033 + pchars(eptr, 16, TRUE, md);
5034 + PCRE_PRINTF("\n");
5037 + if (offset < md->offset_max)
5039 + int save_offset1 = md->offset_vector[offset];
5040 + int save_offset2 = md->offset_vector[offset+1];
5041 + int save_offset3 = md->offset_vector[md->offset_end - number];
5043 + DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
5044 + md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
5048 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
5050 + ecode += (ecode[1] << 8) + ecode[2];
5052 + while (*ecode == OP_ALT);
5054 + DPRINTF(("bracket %d failed\n", number));
5056 + md->offset_vector[offset] = save_offset1;
5057 + md->offset_vector[offset+1] = save_offset2;
5058 + md->offset_vector[md->offset_end - number] = save_offset3;
5063 + /* Insufficient room for saving captured contents */
5068 + /* Other types of node can be handled by a switch */
5072 + case OP_BRA: /* Non-capturing bracket: optimized */
5073 + DPRINTF(("start bracket 0\n"));
5076 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
5078 + ecode += (ecode[1] << 8) + ecode[2];
5080 + while (*ecode == OP_ALT);
5081 + DPRINTF(("bracket 0 failed\n"));
5084 + /* Conditional group: compilation checked that there are no more than
5085 + two branches. If the condition is false, skipping the first branch takes us
5086 + past the end if there is only one branch, but that's OK because that is
5087 + exactly what going to the ket would do. */
5090 + if (ecode[3] == OP_CREF) /* Condition is extraction test */
5092 + int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled ref number */
5093 + return match(eptr,
5094 + ecode + ((offset < offset_top && md->offset_vector[offset] >= 0)?
5095 + 6 : 3 + (ecode[1] << 8) + ecode[2]),
5096 + offset_top, md, ims, eptrb, match_isgroup);
5099 + /* The condition is an assertion. Call match() to evaluate it - setting
5100 + the final argument TRUE causes it to stop at the end of an assertion. */
5104 + if (match(eptr, ecode+3, offset_top, md, ims, NULL,
5105 + match_condassert | match_isgroup))
5107 + ecode += 3 + (ecode[4] << 8) + ecode[5];
5108 + while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
5110 + else ecode += (ecode[1] << 8) + ecode[2];
5111 + return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
5113 + /* Control never reaches here */
5115 + /* Skip over conditional reference or large extraction number data if
5119 + case OP_BRANUMBER:
5123 + /* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched
5124 + an empty string - recursion will then try other alternatives, if any. */
5127 + if (md->notempty && eptr == md->start_match) return FALSE;
5128 + md->end_match_ptr = eptr; /* Record where we ended */
5129 + md->end_offset_top = offset_top; /* and how many extracts were taken */
5132 + /* Change option settings */
5137 + DPRINTF(("ims set to %02lx\n", ims));
5140 + /* Assertion brackets. Check the alternative branches in turn - the
5141 + matching won't pass the KET for an assertion. If any one branch matches,
5142 + the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
5143 + start of each branch to move the current point backwards, so the code at
5144 + this level is identical to the lookahead case. */
5147 + case OP_ASSERTBACK:
5150 + if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break;
5151 + ecode += (ecode[1] << 8) + ecode[2];
5153 + while (*ecode == OP_ALT);
5154 + if (*ecode == OP_KET) return FALSE;
5156 + /* If checking an assertion for a condition, return TRUE. */
5158 + if ((flags & match_condassert) != 0) return TRUE;
5160 + /* Continue from after the assertion, updating the offsets high water
5161 + mark, since extracts may have been taken during the assertion. */
5163 + do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
5165 + offset_top = md->end_offset_top;
5168 + /* Negative assertion: all branches must fail to match */
5170 + case OP_ASSERT_NOT:
5171 + case OP_ASSERTBACK_NOT:
5174 + if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup))
5176 + ecode += (ecode[1] << 8) + ecode[2];
5178 + while (*ecode == OP_ALT);
5180 + if ((flags & match_condassert) != 0) return TRUE;
5185 + /* Move the subject pointer back. This occurs only at the start of
5186 + each branch of a lookbehind assertion. If we are too close to the start to
5187 + move back, this match function fails. When working with UTF-8 we move
5188 + back a number of characters, not bytes. */
5191 +#ifdef SUPPORT_UTF8
5192 + c = (ecode[1] << 8) + ecode[2];
5193 + for (i = 0; i < c; i++)
5199 + eptr -= (ecode[1] << 8) + ecode[2];
5202 + if (eptr < md->start_subject) return FALSE;
5206 + /* Recursion matches the current regex, nested. If there are any capturing
5207 + brackets started but not finished, we have to save their starting points
5208 + and reinstate them after the recursion. However, we don't know how many
5209 + such there are (offset_top records the completed total) so we just have
5210 + to save all the potential data. There may be up to 99 such values, which
5211 + is a bit large to put on the stack, but using malloc for small numbers
5212 + seems expensive. As a compromise, the stack is used when there are fewer
5213 + than 16 values to store; otherwise malloc is used. A problem is what to do
5214 + if the malloc fails ... there is no way of returning to the top level with
5215 + an error. Save the top 15 values on the stack, and accept that the rest
5222 + int stacksave[15];
5224 + c = md->offset_max;
5226 + if (c < 16) save = stacksave; else
5228 + save = (int *)(pcre_malloc)((c+1) * sizeof(int));
5236 + for (i = 1; i <= c; i++)
5237 + save[i] = md->offset_vector[md->offset_end - i];
5238 + rc = match(eptr, md->start_pattern, offset_top, md, ims, eptrb,
5240 + for (i = 1; i <= c; i++)
5241 + md->offset_vector[md->offset_end - i] = save[i];
5242 + if (save != stacksave) (pcre_free)(save);
5243 + if (!rc) return FALSE;
5245 + /* In case the recursion has set more capturing values, save the final
5246 + number, then move along the subject till after the recursive match,
5247 + and advance one byte in the pattern code. */
5249 + offset_top = md->end_offset_top;
5250 + eptr = md->end_match_ptr;
5255 + /* "Once" brackets are like assertion brackets except that after a match,
5256 + the point in the subject string is not moved back. Thus there can never be
5257 + a move back into the brackets. Check the alternative branches in turn - the
5258 + matching won't pass the KET for this kind of subpattern. If any one branch
5259 + matches, we carry on as at the end of a normal bracket, leaving the subject
5264 + const uschar *prev = ecode;
5265 + const uschar *saved_eptr = eptr;
5269 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
5271 + ecode += (ecode[1] << 8) + ecode[2];
5273 + while (*ecode == OP_ALT);
5275 + /* If hit the end of the group (which could be repeated), fail */
5277 + if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
5279 + /* Continue as from after the assertion, updating the offsets high water
5280 + mark, since extracts may have been taken. */
5282 + do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
5284 + offset_top = md->end_offset_top;
5285 + eptr = md->end_match_ptr;
5287 + /* For a non-repeating ket, just continue at this level. This also
5288 + happens for a repeating ket if no characters were matched in the group.
5289 + This is the forcible breaking of infinite loops as implemented in Perl
5290 + 5.005. If there is an options reset, it will get obeyed in the normal
5291 + course of events. */
5293 + if (*ecode == OP_KET || eptr == saved_eptr)
5299 + /* The repeating kets try the rest of the pattern or restart from the
5300 + preceding bracket, in the appropriate order. We need to reset any options
5301 + that changed within the bracket before re-running it, so check the next
5304 + if (ecode[3] == OP_OPT)
5306 + ims = (ims & ~PCRE_IMS) | ecode[4];
5307 + DPRINTF(("ims set to %02lx at group repeat\n", ims));
5310 + if (*ecode == OP_KETRMIN)
5312 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
5313 + match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
5316 + else /* OP_KETRMAX */
5318 + if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
5319 + match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
5324 + /* An alternation is the end of a branch; scan along to find the end of the
5325 + bracketed group and go to there. */
5328 + do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
5331 + /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
5332 + that it may occur zero times. It may repeat infinitely, or not at all -
5333 + i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
5334 + repeat limits are compiled as a number of copies, with the optional ones
5335 + preceded by BRAZERO or BRAMINZERO. */
5339 + const uschar *next = ecode+1;
5340 + if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup))
5342 + do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
5347 + case OP_BRAMINZERO:
5349 + const uschar *next = ecode+1;
5350 + do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
5351 + if (match(eptr, next+3, offset_top, md, ims, eptrb, match_isgroup))
5357 + /* End of a group, repeated or non-repeating. If we are at the end of
5358 + an assertion "group", stop matching and return TRUE, but record the
5359 + current high water mark for use by positive assertions. Do this also
5360 + for the "once" (not-backup up) groups. */
5366 + const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
5367 + const uschar *saved_eptr = eptrb->saved_eptr;
5369 + eptrb = eptrb->prev; /* Back up the stack of bracket start pointers */
5371 + if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
5372 + *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
5375 + md->end_match_ptr = eptr; /* For ONCE */
5376 + md->end_offset_top = offset_top;
5380 + /* In all other cases except a conditional group we have to check the
5381 + group number back at the start and if necessary complete handling an
5382 + extraction by setting the offsets and bumping the high water mark. */
5384 + if (*prev != OP_COND)
5387 + int number = *prev - OP_BRA;
5389 + /* For extended extraction brackets (large number), we have to fish out
5390 + the number from a dummy opcode at the start. */
5392 + if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5];
5393 + offset = number << 1;
5396 + PCRE_PRINTF("end bracket %d", number);
5397 + PCRE_PRINTF("\n");
5402 + if (offset >= md->offset_max) md->offset_overflow = TRUE; else
5404 + md->offset_vector[offset] =
5405 + md->offset_vector[md->offset_end - number];
5406 + md->offset_vector[offset+1] = eptr - md->start_subject;
5407 + if (offset_top <= offset) offset_top = offset + 2;
5412 + /* Reset the value of the ims flags, in case they got changed during
5415 + ims = original_ims;
5416 + DPRINTF(("ims reset to %02lx\n", ims));
5418 + /* For a non-repeating ket, just continue at this level. This also
5419 + happens for a repeating ket if no characters were matched in the group.
5420 + This is the forcible breaking of infinite loops as implemented in Perl
5421 + 5.005. If there is an options reset, it will get obeyed in the normal
5422 + course of events. */
5424 + if (*ecode == OP_KET || eptr == saved_eptr)
5430 + /* The repeating kets try the rest of the pattern or restart from the
5431 + preceding bracket, in the appropriate order. */
5433 + if (*ecode == OP_KETRMIN)
5435 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
5436 + match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
5439 + else /* OP_KETRMAX */
5441 + if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
5442 + match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
5447 + /* Start of subject unless notbol, or after internal newline if multiline */
5450 + if (md->notbol && eptr == md->start_subject) return FALSE;
5451 + if ((ims & PCRE_MULTILINE) != 0)
5453 + if (eptr != md->start_subject && eptr[-1] != NEWLINE) return FALSE;
5457 + /* ... else fall through */
5459 + /* Start of subject assertion */
5462 + if (eptr != md->start_subject) return FALSE;
5466 + /* Assert before internal newline if multiline, or before a terminating
5467 + newline unless endonly is set, else end of subject unless noteol is set. */
5470 + if ((ims & PCRE_MULTILINE) != 0)
5472 + if (eptr < md->end_subject) { if (*eptr != NEWLINE) return FALSE; }
5473 + else { if (md->noteol) return FALSE; }
5479 + if (md->noteol) return FALSE;
5482 + if (eptr < md->end_subject - 1 ||
5483 + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
5489 + /* ... else fall through */
5491 + /* End of subject assertion (\z) */
5494 + if (eptr < md->end_subject) return FALSE;
5498 + /* End of subject or ending \n assertion (\Z) */
5501 + if (eptr < md->end_subject - 1 ||
5502 + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
5506 + /* Word boundary assertions */
5508 + case OP_NOT_WORD_BOUNDARY:
5509 + case OP_WORD_BOUNDARY:
5511 + BOOL prev_is_word = (eptr != md->start_subject) &&
5512 + ((md->ctypes[eptr[-1]] & ctype_word) != 0);
5513 + BOOL cur_is_word = (eptr < md->end_subject) &&
5514 + ((md->ctypes[*eptr] & ctype_word) != 0);
5515 + if ((*ecode++ == OP_WORD_BOUNDARY)?
5516 + cur_is_word == prev_is_word : cur_is_word != prev_is_word)
5521 + /* Match a single character type; inline for speed */
5524 + if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE)
5526 + if (eptr++ >= md->end_subject) return FALSE;
5527 +#ifdef SUPPORT_UTF8
5529 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
5534 + case OP_NOT_DIGIT:
5535 + if (eptr >= md->end_subject ||
5536 + (md->ctypes[*eptr++] & ctype_digit) != 0)
5542 + if (eptr >= md->end_subject ||
5543 + (md->ctypes[*eptr++] & ctype_digit) == 0)
5548 + case OP_NOT_WHITESPACE:
5549 + if (eptr >= md->end_subject ||
5550 + (md->ctypes[*eptr++] & ctype_space) != 0)
5555 + case OP_WHITESPACE:
5556 + if (eptr >= md->end_subject ||
5557 + (md->ctypes[*eptr++] & ctype_space) == 0)
5562 + case OP_NOT_WORDCHAR:
5563 + if (eptr >= md->end_subject ||
5564 + (md->ctypes[*eptr++] & ctype_word) != 0)
5570 + if (eptr >= md->end_subject ||
5571 + (md->ctypes[*eptr++] & ctype_word) == 0)
5576 + /* Match a back reference, possibly repeatedly. Look past the end of the
5577 + item to see if there is repeat information following. The code is similar
5578 + to that for character classes, but repeated for efficiency. Then obey
5579 + similar code to character type repeats - written out again for speed.
5580 + However, if the referenced string is the empty string, always treat
5581 + it as matched, any number of times (otherwise there could be infinite
5587 + int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */
5588 + ecode += 3; /* Advance past item */
5590 + /* If the reference is unset, set the length to be longer than the amount
5591 + of subject left; this ensures that every attempt at a match fails. We
5592 + can't just fail here, because of the possibility of quantifiers with zero
5595 + length = (offset >= offset_top || md->offset_vector[offset] < 0)?
5596 + md->end_subject - eptr + 1 :
5597 + md->offset_vector[offset+1] - md->offset_vector[offset];
5599 + /* Set up for repetition, or handle the non-repeated case */
5604 + case OP_CRMINSTAR:
5606 + case OP_CRMINPLUS:
5608 + case OP_CRMINQUERY:
5609 + c = *ecode++ - OP_CRSTAR;
5610 + minimize = (c & 1) != 0;
5611 + min = rep_min[c]; /* Pick up values from tables; */
5612 + max = rep_max[c]; /* zero for max => infinity */
5613 + if (max == 0) max = INT_MAX;
5617 + case OP_CRMINRANGE:
5618 + minimize = (*ecode == OP_CRMINRANGE);
5619 + min = (ecode[1] << 8) + ecode[2];
5620 + max = (ecode[3] << 8) + ecode[4];
5621 + if (max == 0) max = INT_MAX;
5625 + default: /* No repeat follows */
5626 + if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
5628 + continue; /* With the main loop */
5631 + /* If the length of the reference is zero, just continue with the
5634 + if (length == 0) continue;
5636 + /* First, ensure the minimum number of matches are present. We get back
5637 + the length of the reference string explicitly rather than passing the
5638 + address of eptr, so that eptr can be a register variable. */
5640 + for (i = 1; i <= min; i++)
5642 + if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
5646 + /* If min = max, continue at the same level without recursion.
5647 + They are not both allowed to be zero. */
5649 + if (min == max) continue;
5651 + /* If minimizing, keep trying and advancing the pointer */
5655 + for (i = min;; i++)
5657 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5659 + if (i >= max || !match_ref(offset, eptr, length, md, ims))
5663 + /* Control never gets here */
5666 + /* If maximizing, find the longest string and work backwards */
5670 + const uschar *pp = eptr;
5671 + for (i = min; i < max; i++)
5673 + if (!match_ref(offset, eptr, length, md, ims)) break;
5676 + while (eptr >= pp)
5678 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5685 + /* Control never gets here */
5689 + /* Match a character class, possibly repeatedly. Look past the end of the
5690 + item to see if there is repeat information following. Then obey similar
5691 + code to character type repeats - written out again for speed. */
5695 + const uschar *data = ecode + 1; /* Save for matching */
5696 + ecode += 33; /* Advance past the item */
5701 + case OP_CRMINSTAR:
5703 + case OP_CRMINPLUS:
5705 + case OP_CRMINQUERY:
5706 + c = *ecode++ - OP_CRSTAR;
5707 + minimize = (c & 1) != 0;
5708 + min = rep_min[c]; /* Pick up values from tables; */
5709 + max = rep_max[c]; /* zero for max => infinity */
5710 + if (max == 0) max = INT_MAX;
5714 + case OP_CRMINRANGE:
5715 + minimize = (*ecode == OP_CRMINRANGE);
5716 + min = (ecode[1] << 8) + ecode[2];
5717 + max = (ecode[3] << 8) + ecode[4];
5718 + if (max == 0) max = INT_MAX;
5722 + default: /* No repeat follows */
5727 + /* First, ensure the minimum number of matches are present. */
5729 + for (i = 1; i <= min; i++)
5731 + if (eptr >= md->end_subject) return FALSE;
5732 + GETCHARINC(c, eptr) /* Get character; increment eptr */
5734 +#ifdef SUPPORT_UTF8
5735 + /* We do not yet support class members > 255 */
5736 + if (c > 255) return FALSE;
5739 + if ((data[c/8] & (1 << (c&7))) != 0) continue;
5743 + /* If max == min we can continue with the main loop without the
5744 + need to recurse. */
5746 + if (min == max) continue;
5748 + /* If minimizing, keep testing the rest of the expression and advancing
5749 + the pointer while it matches the class. */
5753 + for (i = min;; i++)
5755 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5757 + if (i >= max || eptr >= md->end_subject) return FALSE;
5758 + GETCHARINC(c, eptr) /* Get character; increment eptr */
5760 +#ifdef SUPPORT_UTF8
5761 + /* We do not yet support class members > 255 */
5762 + if (c > 255) return FALSE;
5764 + if ((data[c/8] & (1 << (c&7))) != 0) continue;
5767 + /* Control never gets here */
5770 + /* If maximizing, find the longest possible run, then work backwards. */
5774 + const uschar *pp = eptr;
5776 + for (i = min; i < max; i++)
5778 + if (eptr >= md->end_subject) break;
5779 + GETCHARLEN(c, eptr, len) /* Get character, set length if UTF-8 */
5781 +#ifdef SUPPORT_UTF8
5782 + /* We do not yet support class members > 255 */
5783 + if (c > 255) break;
5785 + if ((data[c/8] & (1 << (c&7))) == 0) break;
5789 + while (eptr >= pp)
5791 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
5794 +#ifdef SUPPORT_UTF8
5801 + /* Control never gets here */
5803 + /* Match a run of characters */
5807 + register int length = ecode[1];
5810 +#ifdef DEBUG /* Sigh. Some compilers never learn. */
5811 + if (eptr >= md->end_subject)
5812 + PCRE_PRINTF("matching subject <null> against pattern ");
5815 + PCRE_PRINTF("matching subject ");
5816 + pchars(eptr, length, TRUE, md);
5817 + PCRE_PRINTF(" against pattern ");
5819 + pchars(ecode, length, FALSE, md);
5820 + PCRE_PRINTF("\n");
5823 + if (length > md->end_subject - eptr) return FALSE;
5824 + if ((ims & PCRE_CASELESS) != 0)
5826 + while (length-- > 0)
5827 + if (md->lcc[*ecode++] != md->lcc[*eptr++])
5832 + while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
5837 + /* Match a single character repeatedly; different opcodes share code. */
5840 + min = max = (ecode[1] << 8) + ecode[2];
5847 + max = (ecode[1] << 8) + ecode[2];
5848 + minimize = *ecode == OP_MINUPTO;
5858 + c = *ecode++ - OP_STAR;
5859 + minimize = (c & 1) != 0;
5860 + min = rep_min[c]; /* Pick up values from tables; */
5861 + max = rep_max[c]; /* zero for max => infinity */
5862 + if (max == 0) max = INT_MAX;
5864 + /* Common code for all repeated single-character matches. We can give
5865 + up quickly if there are fewer than the minimum number of characters left in
5869 + if (min > md->end_subject - eptr) return FALSE;
5872 + /* The code is duplicated for the caseless and caseful cases, for speed,
5873 + since matching characters is likely to be quite common. First, ensure the
5874 + minimum number of matches are present. If min = max, continue at the same
5875 + level without recursing. Otherwise, if minimizing, keep trying the rest of
5876 + the expression and advancing one matching character if failing, up to the
5877 + maximum. Alternatively, if maximizing, find the maximum number of
5878 + characters and work backwards. */
5880 + DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
5883 + if ((ims & PCRE_CASELESS) != 0)
5886 + for (i = 1; i <= min; i++)
5887 + if (c != md->lcc[*eptr++]) return FALSE;
5888 + if (min == max) continue;
5891 + for (i = min;; i++)
5893 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5895 + if (i >= max || eptr >= md->end_subject ||
5896 + c != md->lcc[*eptr++])
5899 + /* Control never gets here */
5903 + const uschar *pp = eptr;
5904 + for (i = min; i < max; i++)
5906 + if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
5909 + while (eptr >= pp)
5910 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
5914 + /* Control never gets here */
5917 + /* Caseful comparisons */
5921 + for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
5922 + if (min == max) continue;
5925 + for (i = min;; i++)
5927 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5929 + if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
5931 + /* Control never gets here */
5935 + const uschar *pp = eptr;
5936 + for (i = min; i < max; i++)
5938 + if (eptr >= md->end_subject || c != *eptr) break;
5941 + while (eptr >= pp)
5942 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
5947 + /* Control never gets here */
5949 + /* Match a negated single character */
5952 + if (eptr >= md->end_subject) return FALSE;
5954 + if ((ims & PCRE_CASELESS) != 0)
5956 + if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
5960 + if (*ecode++ == *eptr++) return FALSE;
5964 + /* Match a negated single character repeatedly. This is almost a repeat of
5965 + the code for a repeated single character, but I haven't found a nice way of
5966 + commoning these up that doesn't require a test of the positive/negative
5967 + option for each character match. Maybe that wouldn't add very much to the
5968 + time taken, but character matching *is* what this is all about... */
5971 + min = max = (ecode[1] << 8) + ecode[2];
5973 + goto REPEATNOTCHAR;
5976 + case OP_NOTMINUPTO:
5978 + max = (ecode[1] << 8) + ecode[2];
5979 + minimize = *ecode == OP_NOTMINUPTO;
5981 + goto REPEATNOTCHAR;
5984 + case OP_NOTMINSTAR:
5986 + case OP_NOTMINPLUS:
5988 + case OP_NOTMINQUERY:
5989 + c = *ecode++ - OP_NOTSTAR;
5990 + minimize = (c & 1) != 0;
5991 + min = rep_min[c]; /* Pick up values from tables; */
5992 + max = rep_max[c]; /* zero for max => infinity */
5993 + if (max == 0) max = INT_MAX;
5995 + /* Common code for all repeated single-character matches. We can give
5996 + up quickly if there are fewer than the minimum number of characters left in
6000 + if (min > md->end_subject - eptr) return FALSE;
6003 + /* The code is duplicated for the caseless and caseful cases, for speed,
6004 + since matching characters is likely to be quite common. First, ensure the
6005 + minimum number of matches are present. If min = max, continue at the same
6006 + level without recursing. Otherwise, if minimizing, keep trying the rest of
6007 + the expression and advancing one matching character if failing, up to the
6008 + maximum. Alternatively, if maximizing, find the maximum number of
6009 + characters and work backwards. */
6011 + DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
6014 + if ((ims & PCRE_CASELESS) != 0)
6017 + for (i = 1; i <= min; i++)
6018 + if (c == md->lcc[*eptr++]) return FALSE;
6019 + if (min == max) continue;
6022 + for (i = min;; i++)
6024 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
6026 + if (i >= max || eptr >= md->end_subject ||
6027 + c == md->lcc[*eptr++])
6030 + /* Control never gets here */
6034 + const uschar *pp = eptr;
6035 + for (i = min; i < max; i++)
6037 + if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
6040 + while (eptr >= pp)
6041 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
6045 + /* Control never gets here */
6048 + /* Caseful comparisons */
6052 + for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
6053 + if (min == max) continue;
6056 + for (i = min;; i++)
6058 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
6060 + if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
6062 + /* Control never gets here */
6066 + const uschar *pp = eptr;
6067 + for (i = min; i < max; i++)
6069 + if (eptr >= md->end_subject || c == *eptr) break;
6072 + while (eptr >= pp)
6073 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
6078 + /* Control never gets here */
6080 + /* Match a single character type repeatedly; several different opcodes
6081 + share code. This is very similar to the code for single characters, but we
6082 + repeat it in the interests of efficiency. */
6084 + case OP_TYPEEXACT:
6085 + min = max = (ecode[1] << 8) + ecode[2];
6091 + case OP_TYPEMINUPTO:
6093 + max = (ecode[1] << 8) + ecode[2];
6094 + minimize = *ecode == OP_TYPEMINUPTO;
6099 + case OP_TYPEMINSTAR:
6101 + case OP_TYPEMINPLUS:
6102 + case OP_TYPEQUERY:
6103 + case OP_TYPEMINQUERY:
6104 + c = *ecode++ - OP_TYPESTAR;
6105 + minimize = (c & 1) != 0;
6106 + min = rep_min[c]; /* Pick up values from tables; */
6107 + max = rep_max[c]; /* zero for max => infinity */
6108 + if (max == 0) max = INT_MAX;
6110 + /* Common code for all repeated single character type matches */
6113 + ctype = *ecode++; /* Code for the character type */
6115 + /* First, ensure the minimum number of matches are present. Use inline
6116 + code for maximizing the speed, and do the type test once at the start
6117 + (i.e. keep it out of the loop). Also we can test that there are at least
6118 + the minimum number of bytes before we start, except when doing '.' in
6119 + UTF8 mode. Leave the test in in all cases; in the special case we have
6120 + to test after each character. */
6122 + if (min > md->end_subject - eptr) return FALSE;
6123 + if (min > 0) switch(ctype)
6126 +#ifdef SUPPORT_UTF8
6129 + for (i = 1; i <= min; i++)
6131 + if (eptr >= md->end_subject ||
6132 + (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0))
6134 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
6139 + /* Non-UTF8 can be faster */
6140 + if ((ims & PCRE_DOTALL) == 0)
6141 + { for (i = 1; i <= min; i++) if (*eptr++ == NEWLINE) return FALSE; }
6145 + case OP_NOT_DIGIT:
6146 + for (i = 1; i <= min; i++)
6147 + if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
6151 + for (i = 1; i <= min; i++)
6152 + if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
6155 + case OP_NOT_WHITESPACE:
6156 + for (i = 1; i <= min; i++)
6157 + if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
6160 + case OP_WHITESPACE:
6161 + for (i = 1; i <= min; i++)
6162 + if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
6165 + case OP_NOT_WORDCHAR:
6166 + for (i = 1; i <= min; i++)
6167 + if ((md->ctypes[*eptr++] & ctype_word) != 0)
6172 + for (i = 1; i <= min; i++)
6173 + if ((md->ctypes[*eptr++] & ctype_word) == 0)
6178 + /* If min = max, continue at the same level without recursing */
6180 + if (min == max) continue;
6182 + /* If minimizing, we have to test the rest of the pattern before each
6183 + subsequent match. */
6187 + for (i = min;; i++)
6189 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE;
6190 + if (i >= max || eptr >= md->end_subject) return FALSE;
6196 + if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return FALSE;
6197 +#ifdef SUPPORT_UTF8
6199 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
6203 + case OP_NOT_DIGIT:
6204 + if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
6208 + if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
6211 + case OP_NOT_WHITESPACE:
6212 + if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
6215 + case OP_WHITESPACE:
6216 + if ((md->ctypes[c] & ctype_space) == 0) return FALSE;
6219 + case OP_NOT_WORDCHAR:
6220 + if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
6224 + if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
6228 + /* Control never gets here */
6231 + /* If maximizing it is worth using inline code for speed, doing the type
6232 + test once at the start (i.e. keep it out of the loop). */
6236 + const uschar *pp = eptr;
6241 + /* Special code is required for UTF8, but when the maximum is unlimited
6242 + we don't need it. */
6244 +#ifdef SUPPORT_UTF8
6245 + if (md->utf8 && max < INT_MAX)
6247 + if ((ims & PCRE_DOTALL) == 0)
6249 + for (i = min; i < max; i++)
6251 + if (eptr >= md->end_subject || *eptr++ == NEWLINE) break;
6252 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
6257 + for (i = min; i < max; i++)
6260 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
6266 + /* Non-UTF8 can be faster */
6267 + if ((ims & PCRE_DOTALL) == 0)
6269 + for (i = min; i < max; i++)
6271 + if (eptr >= md->end_subject || *eptr == NEWLINE) break;
6278 + if (c > md->end_subject - eptr) c = md->end_subject - eptr;
6283 + case OP_NOT_DIGIT:
6284 + for (i = min; i < max; i++)
6286 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
6293 + for (i = min; i < max; i++)
6295 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
6301 + case OP_NOT_WHITESPACE:
6302 + for (i = min; i < max; i++)
6304 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
6310 + case OP_WHITESPACE:
6311 + for (i = min; i < max; i++)
6313 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
6319 + case OP_NOT_WORDCHAR:
6320 + for (i = min; i < max; i++)
6322 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
6329 + for (i = min; i < max; i++)
6331 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
6338 + while (eptr >= pp)
6340 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
6342 +#ifdef SUPPORT_UTF8
6344 + while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--;
6349 + /* Control never gets here */
6351 + /* There's been some horrible disaster. */
6354 + DPRINTF(("Unknown opcode %d\n", *ecode));
6355 + md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
6359 + /* Do not stick any code in here without much thought; it is assumed
6360 + that "continue" in the code above comes out to here to repeat the main
6363 + } /* End of main loop */
6364 +/* Control never reaches here */
6368 +/*************************************************
6369 +* Execute a Regular Expression *
6370 +*************************************************/
6372 +/* This function applies a compiled re to a subject string and picks out
6373 +portions of the string if it matches. Two elements in the vector are set for
6374 +each substring: the offsets to the start and end of the substring.
6377 + external_re points to the compiled expression
6378 + external_extra points to "hints" from pcre_study() or is NULL
6379 + subject points to the subject string
6380 + length length of subject string (may contain binary zeros)
6381 + start_offset where to start in the subject string
6382 + options option bits
6383 + offsets points to a vector of ints to be filled in with offsets
6384 + offsetcount the number of elements in the vector
6386 +Returns: > 0 => success; value is the number of elements filled in
6387 + = 0 => success, but offsets is not big enough
6388 + -1 => failed to match
6389 + < -1 => some kind of unexpected problem
6393 +pcre_exec(const pcre *external_re, const pcre_extra *external_extra,
6394 + const char *subject, int length, int start_offset, int options, int *offsets,
6397 +int resetcount, ocount;
6398 +int first_char = -1;
6400 +int req_char2 = -1;
6401 +unsigned long int ims = 0;
6402 +match_data match_block;
6403 +const uschar *start_bits = NULL;
6404 +const uschar *start_match = (const uschar *)subject + start_offset;
6405 +const uschar *end_subject;
6406 +const uschar *req_char_ptr = start_match - 1;
6407 +const real_pcre *re = (const real_pcre *)external_re;
6408 +const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
6409 +BOOL using_temporary_offsets = FALSE;
6413 +if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
6415 +if (re == NULL || subject == NULL ||
6416 + (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
6417 +if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
6419 +anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
6420 +startline = (re->options & PCRE_STARTLINE) != 0;
6422 +match_block.start_pattern = re->code;
6423 +match_block.start_subject = (const uschar *)subject;
6424 +match_block.end_subject = match_block.start_subject + length;
6425 +end_subject = match_block.end_subject;
6427 +match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
6428 +match_block.utf8 = (re->options & PCRE_UTF8) != 0;
6430 +match_block.notbol = (options & PCRE_NOTBOL) != 0;
6431 +match_block.noteol = (options & PCRE_NOTEOL) != 0;
6432 +match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
6434 +match_block.errorcode = PCRE_ERROR_NOMATCH; /* Default error */
6436 +match_block.lcc = re->tables + lcc_offset;
6437 +match_block.ctypes = re->tables + ctypes_offset;
6439 +/* The ims options can vary during the matching as a result of the presence
6440 +of (?ims) items in the pattern. They are kept in a local variable so that
6441 +restoring at the exit of a group is easy. */
6443 +ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
6445 +/* If the expression has got more back references than the offsets supplied can
6446 +hold, we get a temporary bit of working store to use during the matching.
6447 +Otherwise, we can use the vector supplied, rounding down its size to a multiple
6450 +ocount = offsetcount - (offsetcount % 3);
6452 +if (re->top_backref > 0 && re->top_backref >= ocount/3)
6454 + ocount = re->top_backref * 3 + 3;
6455 + match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int));
6456 + if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
6457 + using_temporary_offsets = TRUE;
6458 + DPRINTF(("Got memory to hold back references\n"));
6460 +else match_block.offset_vector = offsets;
6462 +match_block.offset_end = ocount;
6463 +match_block.offset_max = (2*ocount)/3;
6464 +match_block.offset_overflow = FALSE;
6466 +/* Compute the minimum number of offsets that we need to reset each time. Doing
6467 +this makes a huge difference to execution time when there aren't many brackets
6470 +resetcount = 2 + re->top_bracket * 2;
6471 +if (resetcount > offsetcount) resetcount = ocount;
6473 +/* Reset the working variable associated with each extraction. These should
6474 +never be used unless previously set, but they get saved and restored, and so we
6475 +initialize them to avoid reading uninitialized locations. */
6477 +if (match_block.offset_vector != NULL)
6479 + register int *iptr = match_block.offset_vector + ocount;
6480 + register int *iend = iptr - resetcount/2 + 1;
6481 + while (--iptr >= iend) *iptr = -1;
6484 +/* Set up the first character to match, if available. The first_char value is
6485 +never set for an anchored regular expression, but the anchoring may be forced
6486 +at run time, so we have to test for anchoring. The first char may be unset for
6487 +an unanchored pattern, of course. If there's no first char and the pattern was
6488 +studied, there may be a bitmap of possible first characters. */
6492 + if ((re->options & PCRE_FIRSTSET) != 0)
6494 + first_char = re->first_char;
6495 + if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
6498 + if (!startline && extra != NULL &&
6499 + (extra->options & PCRE_STUDY_MAPPED) != 0)
6500 + start_bits = extra->start_bits;
6503 +/* For anchored or unanchored matches, there may be a "last known required
6504 +character" set. If the PCRE_CASELESS is set, implying that the match starts
6505 +caselessly, or if there are any changes of this flag within the regex, set up
6506 +both cases of the character. Otherwise set the two values the same, which will
6507 +avoid duplicate testing (which takes significant time). This covers the vast
6508 +majority of cases. It will be suboptimal when the case flag changes in a regex
6509 +and the required character in fact is caseful. */
6511 +if ((re->options & PCRE_REQCHSET) != 0)
6513 + req_char = re->req_char;
6514 + req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0)?
6515 + (re->tables + fcc_offset)[req_char] : req_char;
6518 +/* Loop for handling unanchored repeated matching attempts; for anchored regexs
6519 +the loop runs just once. */
6524 + register int *iptr = match_block.offset_vector;
6525 + register int *iend = iptr + resetcount;
6527 + /* Reset the maximum number of extractions we might see. */
6529 + while (iptr < iend) *iptr++ = -1;
6531 + /* Advance to a unique first char if possible */
6533 + if (first_char >= 0)
6535 + if ((ims & PCRE_CASELESS) != 0)
6536 + while (start_match < end_subject &&
6537 + match_block.lcc[*start_match] != first_char)
6540 + while (start_match < end_subject && *start_match != first_char)
6544 + /* Or to just after \n for a multiline match if possible */
6546 + else if (startline)
6548 + if (start_match > match_block.start_subject + start_offset)
6550 + while (start_match < end_subject && start_match[-1] != NEWLINE)
6555 + /* Or to a non-unique first char after study */
6557 + else if (start_bits != NULL)
6559 + while (start_match < end_subject)
6561 + register int c = *start_match;
6562 + if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
6566 +#ifdef DEBUG /* Sigh. Some compilers never learn. */
6567 + PCRE_PRINTF(">>>> Match against: ");
6568 + pchars(start_match, end_subject - start_match, TRUE, &match_block);
6569 + PCRE_PRINTF("\n");
6572 + /* If req_char is set, we know that that character must appear in the subject
6573 + for the match to succeed. If the first character is set, req_char must be
6574 + later in the subject; otherwise the test starts at the match point. This
6575 + optimization can save a huge amount of backtracking in patterns with nested
6576 + unlimited repeats that aren't going to match. We don't know what the state of
6577 + case matching may be when this character is hit, so test for it in both its
6578 + cases if necessary. However, the different cased versions will not be set up
6579 + unless PCRE_CASELESS was given or the casing state changes within the regex.
6580 + Writing separate code makes it go faster, as does using an autoincrement and
6581 + backing off on a match. */
6583 + if (req_char >= 0)
6585 + register const uschar *p = start_match + ((first_char >= 0)? 1 : 0);
6587 + /* We don't need to repeat the search if we haven't yet reached the
6588 + place we found it at last time. */
6590 + if (p > req_char_ptr)
6592 + /* Do a single test if no case difference is set up */
6594 + if (req_char == req_char2)
6596 + while (p < end_subject)
6598 + if (*p++ == req_char) { p--; break; }
6602 + /* Otherwise test for either case */
6606 + while (p < end_subject)
6608 + register int pp = *p++;
6609 + if (pp == req_char || pp == req_char2) { p--; break; }
6613 + /* If we can't find the required character, break the matching loop */
6615 + if (p >= end_subject) break;
6617 + /* If we have found the required character, save the point where we
6618 + found it, so that we don't search again next time round the loop if
6619 + the start hasn't passed this character yet. */
6625 + /* When a match occurs, substrings will be set for all internal extractions;
6626 + we just need to set up the whole thing as substring 0 before returning. If
6627 + there were too many extractions, set the return code to zero. In the case
6628 + where we had to get some local store to hold offsets for backreferences, copy
6629 + those back references that we can. In this case there need not be overflow
6630 + if certain parts of the pattern were not used. */
6632 + match_block.start_match = start_match;
6633 + if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
6636 + /* Copy the offset information from temporary store if necessary */
6638 + if (using_temporary_offsets)
6640 + if (offsetcount >= 4)
6642 + memcpy(offsets + 2, match_block.offset_vector + 2,
6643 + (offsetcount - 2) * sizeof(int));
6644 + DPRINTF(("Copied offsets from temporary memory\n"));
6646 + if (match_block.end_offset_top > offsetcount)
6647 + match_block.offset_overflow = TRUE;
6649 + DPRINTF(("Freeing temporary memory\n"));
6650 + (pcre_free)(match_block.offset_vector);
6653 + rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
6655 + if (offsetcount < 2) rc = 0; else
6657 + offsets[0] = start_match - match_block.start_subject;
6658 + offsets[1] = match_block.end_match_ptr - match_block.start_subject;
6661 + DPRINTF((">>>> returning %d\n", rc));
6665 +/* This "while" is the end of the "do" above */
6667 +while (!anchored &&
6668 + match_block.errorcode == PCRE_ERROR_NOMATCH &&
6669 + start_match++ < end_subject);
6671 +if (using_temporary_offsets)
6673 + DPRINTF(("Freeing temporary memory\n"));
6674 + (pcre_free)(match_block.offset_vector);
6677 +DPRINTF((">>>> returning %d\n", match_block.errorcode));
6679 +return match_block.errorcode;
6682 +/* End of pcre.c */
6683 Index: b/security/apparmor/match/pcre_exec.h
6684 ===================================================================
6686 +++ b/security/apparmor/match/pcre_exec.h
6689 + * This is a modified header file containing the definitions from
6690 + * pcre.h and internal.h required to support pcre_exec()
6694 +/*************************************************
6695 +* Perl-Compatible Regular Expressions *
6696 +*************************************************/
6698 +/* Copyright (c) 1997-2001 University of Cambridge */
6703 +/* ----- CODE ADDED ---- */
6706 +#include <linux/slab.h> // for kmalloc/kfree
6710 +#define PCRE_PRINTF printk
6711 +#define isprint(x) ((unsigned char)(x) >= 128 && (unsigned char)(x) <= 255)
6713 +#define PCRE_PRINTF printf
6716 +/* The value of NEWLINE determines the newline character. The default is to
6717 + * leave it up to the compiler, but some sites want to force a particular value.
6718 + * On Unix systems, "configure" can be used to override this default. */
6721 +#define NEWLINE '\n'
6724 +/* ---- CODE DELETED ---- */
6728 +#define PCRE_CASELESS 0x0001
6729 +#define PCRE_MULTILINE 0x0002
6730 +#define PCRE_DOTALL 0x0004
6731 +#define PCRE_EXTENDED 0x0008
6732 +#define PCRE_ANCHORED 0x0010
6733 +#define PCRE_DOLLAR_ENDONLY 0x0020
6734 +#define PCRE_EXTRA 0x0040
6735 +#define PCRE_NOTBOL 0x0080
6736 +#define PCRE_NOTEOL 0x0100
6737 +#define PCRE_UNGREEDY 0x0200
6738 +#define PCRE_NOTEMPTY 0x0400
6739 +#define PCRE_UTF8 0x0800
6741 +/* Exec-time and get-time error codes */
6743 +#define PCRE_ERROR_NOMATCH (-1)
6744 +#define PCRE_ERROR_NULL (-2)
6745 +#define PCRE_ERROR_BADOPTION (-3)
6746 +#define PCRE_ERROR_BADMAGIC (-4)
6747 +#define PCRE_ERROR_UNKNOWN_NODE (-5)
6748 +#define PCRE_ERROR_NOMEMORY (-6)
6749 +#define PCRE_ERROR_NOSUBSTRING (-7)
6751 +/* ---- CODE DELETED ---- */
6755 +struct real_pcre; /* declaration; the definition is private */
6756 +struct real_pcre_extra; /* declaration; the definition is private */
6758 +typedef struct real_pcre pcre;
6759 +typedef struct real_pcre_extra pcre_extra;
6761 +/* ---- CODE DELETED ---- */
6763 +extern int pcre_exec(const pcre *, const pcre_extra *,
6764 + const char *, int, int, int, int *,
6767 +/* ---- CODE ADDED (from internal.h) ---- */
6769 +/* These are the public options that can change during matching. */
6771 +#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
6773 +/* Private options flags start at the most significant end of the four bytes,
6774 +but skip the top bit so we can use ints for convenience without getting tangled
6775 +with negative values. The public options defined in pcre.h start at the least
6776 +significant end. Make sure they don't overlap, though now that we have expanded
6777 +to four bytes there is plenty of space. */
6779 +#define PCRE_FIRSTSET 0x40000000 /* first_char is set */
6780 +#define PCRE_REQCHSET 0x20000000 /* req_char is set */
6781 +#define PCRE_STARTLINE 0x10000000 /* start after \n for multiline */
6782 +#define PCRE_ICHANGED 0x04000000 /* i option changes within regex */
6784 +/* Options for the "extra" block produced by pcre_study(). */
6786 +#define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */
6788 +/* Masks for identifying the public options which are permitted at compile
6789 +time, run time or study time, respectively. */
6791 +#define PUBLIC_EXEC_OPTIONS \
6792 + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
6794 +/* Magic number to provide a small check against being handed junk. */
6796 +#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
6803 +/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
6804 +that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
6805 +OP_EOD must correspond in order to the list of escapes immediately above. */
6808 + OP_END, /* End of pattern */
6810 + /* Values corresponding to backslashed metacharacters */
6812 + OP_SOD, /* Start of data: \A */
6813 + OP_NOT_WORD_BOUNDARY, /* \B */
6814 + OP_WORD_BOUNDARY, /* \b */
6815 + OP_NOT_DIGIT, /* \D */
6816 + OP_DIGIT, /* \d */
6817 + OP_NOT_WHITESPACE, /* \S */
6818 + OP_WHITESPACE, /* \s */
6819 + OP_NOT_WORDCHAR, /* \W */
6820 + OP_WORDCHAR, /* \w */
6821 + OP_EODN, /* End of data or \n at end of data: \Z. */
6822 + OP_EOD, /* End of data: \z */
6824 + OP_OPT, /* Set runtime options */
6825 + OP_CIRC, /* Start of line - varies with multiline switch */
6826 + OP_DOLL, /* End of line - varies with multiline switch */
6827 + OP_ANY, /* Match any character */
6828 + OP_CHARS, /* Match string of characters */
6829 + OP_NOT, /* Match anything but the following char */
6831 + OP_STAR, /* The maximizing and minimizing versions of */
6832 + OP_MINSTAR, /* all these opcodes must come in pairs, with */
6833 + OP_PLUS, /* the minimizing one second. */
6834 + OP_MINPLUS, /* This first set applies to single characters */
6837 + OP_UPTO, /* From 0 to n matches */
6839 + OP_EXACT, /* Exactly n matches */
6841 + OP_NOTSTAR, /* The maximizing and minimizing versions of */
6842 + OP_NOTMINSTAR, /* all these opcodes must come in pairs, with */
6843 + OP_NOTPLUS, /* the minimizing one second. */
6844 + OP_NOTMINPLUS, /* This first set applies to "not" single characters */
6847 + OP_NOTUPTO, /* From 0 to n matches */
6849 + OP_NOTEXACT, /* Exactly n matches */
6851 + OP_TYPESTAR, /* The maximizing and minimizing versions of */
6852 + OP_TYPEMINSTAR, /* all these opcodes must come in pairs, with */
6853 + OP_TYPEPLUS, /* the minimizing one second. These codes must */
6854 + OP_TYPEMINPLUS, /* be in exactly the same order as those above. */
6855 + OP_TYPEQUERY, /* This set applies to character types such as \d */
6857 + OP_TYPEUPTO, /* From 0 to n matches */
6859 + OP_TYPEEXACT, /* Exactly n matches */
6861 + OP_CRSTAR, /* The maximizing and minimizing versions of */
6862 + OP_CRMINSTAR, /* all these opcodes must come in pairs, with */
6863 + OP_CRPLUS, /* the minimizing one second. These codes must */
6864 + OP_CRMINPLUS, /* be in exactly the same order as those above. */
6865 + OP_CRQUERY, /* These are for character classes and back refs */
6867 + OP_CRRANGE, /* These are different to the three seta above. */
6870 + OP_CLASS, /* Match a character class */
6871 + OP_REF, /* Match a back reference */
6872 + OP_RECURSE, /* Match this pattern recursively */
6874 + OP_ALT, /* Start of alternation */
6875 + OP_KET, /* End of group that doesn't have an unbounded repeat */
6876 + OP_KETRMAX, /* These two must remain together and in this */
6877 + OP_KETRMIN, /* order. They are for groups the repeat for ever. */
6879 + /* The assertions must come before ONCE and COND */
6881 + OP_ASSERT, /* Positive lookahead */
6882 + OP_ASSERT_NOT, /* Negative lookahead */
6883 + OP_ASSERTBACK, /* Positive lookbehind */
6884 + OP_ASSERTBACK_NOT, /* Negative lookbehind */
6885 + OP_REVERSE, /* Move pointer back - used in lookbehind assertions */
6887 + /* ONCE and COND must come after the assertions, with ONCE first, as there's
6888 + a test for >= ONCE for a subpattern that isn't an assertion. */
6890 + OP_ONCE, /* Once matched, don't back up into the subpattern */
6891 + OP_COND, /* Conditional group */
6892 + OP_CREF, /* Used to hold an extraction string number (cond ref) */
6894 + OP_BRAZERO, /* These two must remain together and in this */
6895 + OP_BRAMINZERO, /* order. */
6897 + OP_BRANUMBER, /* Used for extracting brackets whose number is greater
6898 + than can fit into an opcode. */
6900 + OP_BRA /* This and greater values are used for brackets that
6901 + extract substrings up to a basic limit. After that,
6902 + use is made of OP_BRANUMBER. */
6905 +/* The highest extraction number before we have to start using additional
6906 +bytes. (Originally PCRE didn't have support for extraction counts highter than
6907 +this number.) The value is limited by the number of opcodes left after OP_BRA,
6908 +i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional
6911 +#define EXTRACT_BASIC_MAX 150
6913 +/* All character handling must be done as unsigned characters. Otherwise there
6914 +are problems with top-bit-set characters and functions such as isspace().
6915 +However, we leave the interface to the outside world as char *, because that
6916 +should make things easier for callers. We define a short type for unsigned char
6917 +to save lots of typing. I tried "uchar", but it causes problems on Digital
6918 +Unix, where it is defined in sys/types, so use "uschar" instead. */
6920 +typedef unsigned char uschar;
6922 +/* The real format of the start of the pcre block; the actual code vector
6923 +runs on as long as necessary after the end. */
6925 +typedef struct real_pcre {
6926 + unsigned long int magic_number;
6928 + const unsigned char *tables;
6929 + unsigned long int options;
6930 + unsigned short int top_bracket;
6931 + unsigned short int top_backref;
6932 + uschar first_char;
6937 +/* The real format of the extra block returned by pcre_study(). */
6939 +typedef struct real_pcre_extra {
6941 + uschar start_bits[32];
6944 +/* Structure for passing "static" information around between the functions
6945 +doing the matching, so that they are thread-safe. */
6947 +typedef struct match_data {
6948 + int errorcode; /* As it says */
6949 + int *offset_vector; /* Offset vector */
6950 + int offset_end; /* One past the end */
6951 + int offset_max; /* The maximum usable for return data */
6952 + const uschar *lcc; /* Points to lower casing table */
6953 + const uschar *ctypes; /* Points to table of type maps */
6954 + BOOL offset_overflow; /* Set if too many extractions */
6955 + BOOL notbol; /* NOTBOL flag */
6956 + BOOL noteol; /* NOTEOL flag */
6957 + BOOL utf8; /* UTF8 flag */
6958 + BOOL endonly; /* Dollar not before final \n */
6959 + BOOL notempty; /* Empty string match not wanted */
6960 + const uschar *start_pattern; /* For use when recursing */
6961 + const uschar *start_subject; /* Start of the subject string */
6962 + const uschar *end_subject; /* End of the subject string */
6963 + const uschar *start_match; /* Start of this match attempt */
6964 + const uschar *end_match_ptr; /* Subject position at end match */
6965 + int end_offset_top; /* Highwater mark at end of match */
6968 +/* Bit definitions for entries in the pcre_ctypes table. */
6970 +#define ctype_space 0x01
6971 +#define ctype_letter 0x02
6972 +#define ctype_digit 0x04
6973 +#define ctype_xdigit 0x08
6974 +#define ctype_word 0x10 /* alphameric or '_' */
6975 +#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */
6977 +/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
6978 +of bits for a class map. Some classes are built by combining these tables. */
6980 +#define cbit_length 320 /* Length of the cbits table */
6982 +/* Offsets of the various tables from the base tables pointer, and
6985 +#define lcc_offset 0
6986 +#define fcc_offset 256
6988 +#define fcc_offset 256
6989 +#define cbits_offset 512
6990 +#define ctypes_offset (cbits_offset + cbit_length)
6992 +/* ----- CODE ADDED ---- */
6995 + /* End of pcre.h */
6996 Index: b/security/apparmor/match/pcre_tables.h
6997 ===================================================================
6999 +++ b/security/apparmor/match/pcre_tables.h
7002 +/*************************************************
7003 +* Perl-Compatible Regular Expressions *
7004 +*************************************************/
7006 +/* This file is automatically written by the dftables auxiliary
7007 +program. If you edit it by hand, you might like to edit the Makefile to
7008 +prevent its ever being regenerated.
7010 +This file is #included in the compilation of pcre.c to build the default
7011 +character tables which are used when no tables are passed to the compile
7014 +static unsigned char pcre_default_tables[] = {
7016 +/* This table is a lower casing table. */
7018 + 0, 1, 2, 3, 4, 5, 6, 7,
7019 + 8, 9, 10, 11, 12, 13, 14, 15,
7020 + 16, 17, 18, 19, 20, 21, 22, 23,
7021 + 24, 25, 26, 27, 28, 29, 30, 31,
7022 + 32, 33, 34, 35, 36, 37, 38, 39,
7023 + 40, 41, 42, 43, 44, 45, 46, 47,
7024 + 48, 49, 50, 51, 52, 53, 54, 55,
7025 + 56, 57, 58, 59, 60, 61, 62, 63,
7026 + 64, 97, 98, 99,100,101,102,103,
7027 + 104,105,106,107,108,109,110,111,
7028 + 112,113,114,115,116,117,118,119,
7029 + 120,121,122, 91, 92, 93, 94, 95,
7030 + 96, 97, 98, 99,100,101,102,103,
7031 + 104,105,106,107,108,109,110,111,
7032 + 112,113,114,115,116,117,118,119,
7033 + 120,121,122,123,124,125,126,127,
7034 + 128,129,130,131,132,133,134,135,
7035 + 136,137,138,139,140,141,142,143,
7036 + 144,145,146,147,148,149,150,151,
7037 + 152,153,154,155,156,157,158,159,
7038 + 160,161,162,163,164,165,166,167,
7039 + 168,169,170,171,172,173,174,175,
7040 + 176,177,178,179,180,181,182,183,
7041 + 184,185,186,187,188,189,190,191,
7042 + 192,193,194,195,196,197,198,199,
7043 + 200,201,202,203,204,205,206,207,
7044 + 208,209,210,211,212,213,214,215,
7045 + 216,217,218,219,220,221,222,223,
7046 + 224,225,226,227,228,229,230,231,
7047 + 232,233,234,235,236,237,238,239,
7048 + 240,241,242,243,244,245,246,247,
7049 + 248,249,250,251,252,253,254,255,
7051 +/* This table is a case flipping table. */
7053 + 0, 1, 2, 3, 4, 5, 6, 7,
7054 + 8, 9, 10, 11, 12, 13, 14, 15,
7055 + 16, 17, 18, 19, 20, 21, 22, 23,
7056 + 24, 25, 26, 27, 28, 29, 30, 31,
7057 + 32, 33, 34, 35, 36, 37, 38, 39,
7058 + 40, 41, 42, 43, 44, 45, 46, 47,
7059 + 48, 49, 50, 51, 52, 53, 54, 55,
7060 + 56, 57, 58, 59, 60, 61, 62, 63,
7061 + 64, 97, 98, 99,100,101,102,103,
7062 + 104,105,106,107,108,109,110,111,
7063 + 112,113,114,115,116,117,118,119,
7064 + 120,121,122, 91, 92, 93, 94, 95,
7065 + 96, 65, 66, 67, 68, 69, 70, 71,
7066 + 72, 73, 74, 75, 76, 77, 78, 79,
7067 + 80, 81, 82, 83, 84, 85, 86, 87,
7068 + 88, 89, 90,123,124,125,126,127,
7069 + 128,129,130,131,132,133,134,135,
7070 + 136,137,138,139,140,141,142,143,
7071 + 144,145,146,147,148,149,150,151,
7072 + 152,153,154,155,156,157,158,159,
7073 + 160,161,162,163,164,165,166,167,
7074 + 168,169,170,171,172,173,174,175,
7075 + 176,177,178,179,180,181,182,183,
7076 + 184,185,186,187,188,189,190,191,
7077 + 192,193,194,195,196,197,198,199,
7078 + 200,201,202,203,204,205,206,207,
7079 + 208,209,210,211,212,213,214,215,
7080 + 216,217,218,219,220,221,222,223,
7081 + 224,225,226,227,228,229,230,231,
7082 + 232,233,234,235,236,237,238,239,
7083 + 240,241,242,243,244,245,246,247,
7084 + 248,249,250,251,252,253,254,255,
7086 +/* This table contains bit maps for various character classes.
7087 +Each map is 32 bytes long and the bits run from the least
7088 +significant end of each byte. The classes that have their own
7089 +maps are: space, xdigit, digit, upper, lower, word, graph
7090 +print, punct, and cntrl. Other classes are built from combinations. */
7092 + 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
7093 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7094 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7095 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7097 + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
7098 + 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
7099 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7100 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7102 + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
7103 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7104 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7105 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7107 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7108 + 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
7109 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7110 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7112 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7113 + 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
7114 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7115 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7117 + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
7118 + 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
7119 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7120 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7122 + 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
7123 + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
7124 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7125 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7127 + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
7128 + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
7129 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7130 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7132 + 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
7133 + 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
7134 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7135 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7137 + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
7138 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
7139 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7140 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
7142 +/* This table identifies various classes of character by individual bits:
7143 + 0x01 white space character
7145 + 0x04 decimal digit
7146 + 0x08 hexadecimal digit
7147 + 0x10 alphanumeric or '_'
7148 + 0x80 regular expression metacharacter or binary zero
7151 + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
7152 + 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */
7153 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
7154 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
7155 + 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */
7156 + 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */
7157 + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
7158 + 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */
7159 + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */
7160 + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */
7161 + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */
7162 + 0x12,0x12,0x12,0x80,0x00,0x00,0x80,0x10, /* X - _ */
7163 + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */
7164 + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */
7165 + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */
7166 + 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */
7167 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
7168 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
7169 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
7170 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
7171 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
7172 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
7173 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
7174 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
7175 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
7176 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
7177 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
7178 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
7179 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
7180 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
7181 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
7182 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
7184 +/* End of chartables.c */
7185 Index: b/security/apparmor/module_interface.c
7186 ===================================================================
7188 +++ b/security/apparmor/module_interface.c
7191 + * Copyright (C) 1998-2005 Novell/SUSE
7193 + * This program is free software; you can redistribute it and/or
7194 + * modify it under the terms of the GNU General Public License as
7195 + * published by the Free Software Foundation, version 2 of the
7198 + * AppArmor userspace policy interface
7201 +#include <asm/unaligned.h>
7203 +#include "apparmor.h"
7204 +#include "inline.h"
7205 +#include "module_interface.h"
7206 +#include "match/match.h"
7208 +/* aa_code defined in module_interface.h */
7210 +const int aacode_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
7212 +struct aa_taskreplace_data {
7213 + struct aaprofile *old_profile;
7214 + struct aaprofile *new_profile;
7217 +/* inlines must be forward of there use in newer version of gcc,
7218 + just forward declaring with a prototype won't work anymore */
7220 +static inline void free_aa_entry(struct aa_entry *entry)
7223 + kfree(entry->filename);
7224 + aamatch_free(entry->extradata);
7230 + * alloc_aa_entry - create new empty aa_entry
7231 + * This routine allocates, initializes, and returns a new aa_entry
7232 + * file entry structure. Structure is zeroed. Returns new structure on
7233 + * success, %NULL on failure.
7235 +static inline struct aa_entry *alloc_aa_entry(void)
7237 + struct aa_entry *entry;
7239 + AA_DEBUG("%s\n", __FUNCTION__);
7240 + entry = kzalloc(sizeof(struct aa_entry), GFP_KERNEL);
7243 + INIT_LIST_HEAD(&entry->list);
7244 + for (i = 0; i <= POS_AA_FILE_MAX; i++) {
7245 + INIT_LIST_HEAD(&entry->listp[i]);
7252 + * free_aaprofile_rcu - rcu callback for free profiles
7253 + * @head: rcu_head struct of the profile whose reference is being put.
7255 + * the rcu callback routine, which delays the freeing of a profile when
7256 + * its last reference is put.
7258 +static void free_aaprofile_rcu(struct rcu_head *head)
7260 + struct aaprofile *p = container_of(head, struct aaprofile, rcu);
7261 + free_aaprofile(p);
7265 + * task_remove - remove profile from a task's subdomain
7266 + * @sd: task's subdomain
7268 + * remove the active profile from a task's subdomain, switching the task
7269 + * to an unconfined state.
7271 +static inline void task_remove(struct subdomain *sd)
7273 + /* spin_lock(&sd_lock) held here */
7274 + AA_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
7278 + BASE_PROFILE(sd->active)->name,
7279 + sd->active->name);
7281 + aa_switch_unconfined(sd);
7284 +/** taskremove_iter - Iterator to unconfine subdomains which match cookie
7285 + * @sd: subdomain to consider for profile removal
7286 + * @cookie: pointer to the oldprofile which is being removed
7288 + * If the subdomain's active profile matches old_profile, then call
7289 + * task_remove() to remove the profile leaving the task (subdomain) unconfined.
7291 +static int taskremove_iter(struct subdomain *sd, void *cookie)
7293 + struct aaprofile *old_profile = (struct aaprofile *)cookie;
7294 + unsigned long flags;
7296 + spin_lock_irqsave(&sd_lock, flags);
7298 + if (__aa_is_confined(sd) && BASE_PROFILE(sd->active) == old_profile) {
7302 + spin_unlock_irqrestore(&sd_lock, flags);
7307 +/** task_replace - replace subdomain's current profile with a new profile
7308 + * @sd: subdomain to replace the profile on
7309 + * @new: new profile
7311 + * Replace a task's (subdomain's) active profile with a new profile. If
7312 + * task was in a hat then the new profile will also be in the equivalent
7313 + * hat in the new profile if it exists. If it doesn't exist the
7314 + * task will be placed in the special null_profile state.
7316 +static inline void task_replace(struct subdomain *sd, struct aaprofile *new)
7318 + AA_DEBUG("%s: replacing profile for task %s(%d) "
7319 + "profile=%s (%p) active=%s (%p)\n",
7321 + sd->task->comm, sd->task->pid,
7322 + BASE_PROFILE(sd->active)->name, BASE_PROFILE(sd->active),
7323 + sd->active->name, sd->active);
7328 + if (IN_SUBPROFILE(sd->active)) {
7329 + struct aaprofile *nactive;
7331 + /* The old profile was in a hat, check to see if the new
7332 + * profile has an equivalent hat */
7333 + nactive = __aa_find_profile(sd->active->name, &new->sub);
7336 + nactive = get_aaprofile(new->null_profile);
7338 + aa_switch(sd, nactive);
7339 + put_aaprofile(nactive);
7341 + aa_switch(sd, new);
7348 +/** taskreplace_iter - Iterator to replace a subdomain's profile
7349 + * @sd: subdomain to consider for profile replacement
7350 + * @cookie: pointer to the old profile which is being replaced.
7352 + * If the subdomain's active profile matches old_profile call
7353 + * task_replace() to replace with the subdomain's active profile with
7354 + * the new profile.
7356 +static int taskreplace_iter(struct subdomain *sd, void *cookie)
7358 + struct aa_taskreplace_data *data = (struct aa_taskreplace_data *)cookie;
7359 + unsigned long flags;
7361 + spin_lock_irqsave(&sd_lock, flags);
7363 + if (__aa_is_confined(sd) &&
7364 + BASE_PROFILE(sd->active) == data->old_profile)
7365 + task_replace(sd, data->new_profile);
7367 + spin_unlock_irqrestore(&sd_lock, flags);
7372 +static inline int aa_inbounds(struct aa_ext *e, size_t size)
7374 + return (e->pos + size <= e->end);
7378 + * aaconvert - convert trailing values of serialized type codes
7379 + * @code: type code
7380 + * @dest: pointer to object to receive the converted value
7381 + * @src: pointer to value to convert
7383 + * for serialized type codes which have a trailing value, convert it
7384 + * and place it in @dest. If a code does not have a trailing value nop.
7386 +static void aaconvert(enum aa_code code, void *dest, void *src)
7390 + *(u8 *)dest = *(u8 *) src;
7394 + case AA_DYN_STRING:
7395 + *(u16 *)dest = le16_to_cpu(get_unaligned((u16 *)src));
7398 + case AA_STATIC_BLOB:
7399 + *(u32 *)dest = le32_to_cpu(get_unaligned((u32 *)src));
7402 + *(u64 *)dest = le64_to_cpu(get_unaligned((u64 *)src));
7405 + /* nop - all other type codes do not have a trailing value */
7411 + * aa_is_X - check if the next element is of type X
7412 + * @e: serialized data extent information
7413 + * @code: type code
7414 + * @data: object located at @e->pos (of type @code) is written into @data
7415 + * if @data is non-null. if data is null it means skip this
7417 + * check to see if the next element in the serialized data stream is of type
7418 + * X and check that it is with in bounds, if so put the associated value in
7420 + * return the size of bytes associated with the returned data
7421 + * for complex object like blob and string a pointer to the allocated
7422 + * data is returned in data, but the size of the blob or string is
7425 +static u32 aa_is_X(struct aa_ext *e, enum aa_code code, void *data)
7427 + void *pos = e->pos;
7429 + if (!aa_inbounds(e, AA_CODE_BYTE + aacode_datasize[code]))
7431 + if (code != *(u8 *)e->pos)
7433 + e->pos += AA_CODE_BYTE;
7434 + if (code == AA_NAME) {
7436 + /* name codes are followed by X bytes */
7437 + size = le16_to_cpu(get_unaligned((u16 *)e->pos));
7438 + if (!aa_inbounds(e, (size_t) size))
7441 + *(u16 *)data = size;
7442 + e->pos += aacode_datasize[code];
7443 + ret = 1 + aacode_datasize[code];
7444 + } else if (code == AA_DYN_STRING) {
7447 + /* strings codes are followed by X bytes */
7448 + size = le16_to_cpu(get_unaligned((u16 *)e->pos));
7449 + e->pos += aacode_datasize[code];
7450 + if (!aa_inbounds(e, (size_t) size))
7453 + * (char **)data = NULL;
7454 + str = kmalloc(size, GFP_KERNEL);
7457 + memcpy(str, e->pos, (size_t) size);
7458 + str[size-1] = '\0';
7459 + * (char **)data = str;
7463 + } else if (code == AA_STATIC_BLOB) {
7465 + /* blobs are followed by X bytes, that can be 2^32 */
7466 + size = le32_to_cpu(get_unaligned((u32 *)e->pos));
7467 + e->pos += aacode_datasize[code];
7468 + if (!aa_inbounds(e, (size_t) size))
7471 + memcpy(data, e->pos, (size_t) size);
7476 + aaconvert(code, data, e->pos);
7477 + e->pos += aacode_datasize[code];
7478 + ret = 1 + aacode_datasize[code];
7488 + * aa_is_nameX - check is the next element is of type X with a name of @name
7489 + * @e: serialized data extent information
7490 + * @code: type code
7491 + * @data: location to store deserialized data if match isX criteria
7492 + * @name: name to match to the serialized element.
7494 + * check that the next serialized data element is of type X and has a tag
7495 + * name @name. If the code matches and name (if specified) matches then
7496 + * the packed data is unpacked into *data. (Note for strings this is the
7497 + * size, and the next data in the stream is the string data)
7498 + * returns %0 if either match failes
7500 +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, void *data,
7503 + void *pos = e->pos;
7506 + /* check for presence of a tagname, and if present name size
7507 + * AA_NAME tag value is a u16 */
7508 + if (aa_is_X(e, AA_NAME, &size)) {
7509 + /* if a name is specified it must match. otherwise skip tag */
7510 + if (name && ((strlen(name) != size-1) ||
7511 + strncmp(name, (char *)e->pos, (size_t)size-1)))
7514 + } else if (name) {
7518 + /* now check if data actually matches */
7519 + ret = aa_is_X(e, code, data);
7529 +/* macro to wrap error case to make a block of reads look nicer */
7530 +#define AA_READ_X(E, C, D, N) \
7533 + __ret = aa_is_nameX((E), (C), (D), (N)); \
7539 + * aa_activate_net_entry - unpacked serialized net entries
7540 + * @e: serialized data extent information
7542 + * Ignore/skips net entries if they are present in the serialized data
7543 + * stream. Network confinement rules are currently unsupported but some
7544 + * user side tools can generate them so they are currently ignored.
7546 +static inline int aa_activate_net_entry(struct aa_ext *e)
7548 + AA_READ_X(e, AA_STRUCT, NULL, "ne");
7549 + AA_READ_X(e, AA_U32, NULL, NULL);
7550 + AA_READ_X(e, AA_U32, NULL, NULL);
7551 + AA_READ_X(e, AA_U32, NULL, NULL);
7552 + AA_READ_X(e, AA_U16, NULL, NULL);
7553 + AA_READ_X(e, AA_U16, NULL, NULL);
7554 + AA_READ_X(e, AA_U32, NULL, NULL);
7555 + AA_READ_X(e, AA_U32, NULL, NULL);
7556 + AA_READ_X(e, AA_U16, NULL, NULL);
7557 + AA_READ_X(e, AA_U16, NULL, NULL);
7558 + /* interface name is optional so just ignore return code */
7559 + aa_is_nameX(e, AA_DYN_STRING, NULL, NULL);
7560 + AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
7568 + * aa_activate_file_entry - unpack serialized file entry
7569 + * @e: serialized data extent information
7571 + * unpack the information used for a file ACL entry.
7573 +static inline struct aa_entry *aa_activate_file_entry(struct aa_ext *e)
7575 + struct aa_entry *entry = NULL;
7577 + if (!(entry = alloc_aa_entry()))
7580 + AA_READ_X(e, AA_STRUCT, NULL, "fe");
7581 + AA_READ_X(e, AA_DYN_STRING, &entry->filename, NULL);
7582 + AA_READ_X(e, AA_U32, &entry->mode, NULL);
7583 + AA_READ_X(e, AA_U32, &entry->type, NULL);
7585 + entry->extradata = aamatch_alloc(entry->type);
7586 + if (IS_ERR(entry->extradata)) {
7587 + entry->extradata = NULL;
7591 + if (entry->extradata &&
7592 + aamatch_serialize(entry->extradata, e, aa_is_nameX) != 0) {
7595 + AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
7597 + switch (entry->type) {
7598 + case aa_entry_literal:
7599 + AA_DEBUG("%s: %s [no pattern] mode=0x%x\n",
7604 + case aa_entry_tailglob:
7605 + AA_DEBUG("%s: %s [tailglob] mode=0x%x\n",
7610 + case aa_entry_pattern:
7611 + AA_DEBUG("%s: %s mode=0x%x\n",
7617 + AA_WARN("%s: INVALID entry_match_type %d\n",
7619 + (int)entry->type);
7626 + free_aa_entry(entry);
7631 + * check_rule_and_add - check a file rule is valid and add to a profile
7632 + * @file_entry: file rule to add
7633 + * @profile: profile to add the rule to
7634 + * @message: error message returned if the addition failes.
7636 + * perform consistency check to ensure that a file rule entry is valid.
7637 + * If the rule is valid it is added to the profile.
7639 +static inline int check_rule_and_add(struct aa_entry *file_entry,
7640 + struct aaprofile *profile,
7641 + const char **message)
7643 + /* verify consistency of x, px, ix, ux for entry against
7644 + possible duplicates for this entry */
7645 + int mode = AA_EXEC_MODIFIER_MASK(file_entry->mode);
7648 + if (mode && !(AA_MAY_EXEC & file_entry->mode)) {
7649 + *message = "inconsistent rule, x modifiers without x";
7653 + /* check that only 1 of the modifiers is set */
7654 + if (mode && (mode & (mode - 1))) {
7655 + *message = "inconsistent rule, multiple x modifiers";
7659 + /* ix -> m (required so that target exec binary may map itself) */
7660 + if (mode & AA_EXEC_INHERIT)
7661 + file_entry->mode |= AA_EXEC_MMAP;
7663 + list_add(&file_entry->list, &profile->file_entry);
7664 + profile->num_file_entries++;
7666 + mode = file_entry->mode;
7668 + /* Handle partitioned lists
7669 + * Chain entries onto sublists based on individual
7670 + * permission bits. This allows more rapid searching.
7672 + for (i = 0; i <= POS_AA_FILE_MAX; i++) {
7673 + if (mode & (1 << i))
7674 + /* profile->file_entryp[i] initially set to
7675 + * NULL in alloc_aaprofile() */
7676 + list_add(&file_entry->listp[i],
7677 + &profile->file_entryp[i]);
7683 + free_aa_entry(file_entry);
7687 +#define AA_ENTRY_LIST(NAME) \
7689 + if (aa_is_nameX(e, AA_LIST, NULL, (NAME))) { \
7691 + error_string = "Invalid file entry"; \
7692 + while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) { \
7693 + struct aa_entry *file_entry; \
7694 + file_entry = aa_activate_file_entry(e); \
7695 + if (!file_entry) \
7697 + if (!check_rule_and_add(file_entry, profile, \
7698 + &error_string)) { \
7699 + rulename = file_entry->filename; \
7707 + * aa_activate_profile - unpack a serialized profile
7708 + * @e: serialized data extent information
7709 + * @error: error code returned if unpacking fails
7711 +static struct aaprofile *aa_activate_profile(struct aa_ext *e, ssize_t *error)
7713 + struct aaprofile *profile = NULL;
7714 + const char *rulename = "";
7715 + const char *error_string = "Invalid Profile";
7719 + profile = alloc_aaprofile();
7721 + error_string = "Could not allocate profile";
7726 + /* check that we have the right struct being passed */
7727 + AA_READ_X(e, AA_STRUCT, NULL, "profile");
7728 + AA_READ_X(e, AA_DYN_STRING, &profile->name, NULL);
7730 + error_string = "Invalid flags";
7731 + /* per profile debug flags (debug, complain, audit) */
7732 + AA_READ_X(e, AA_STRUCT, NULL, "flags");
7733 + AA_READ_X(e, AA_U32, &(profile->flags.debug), NULL);
7734 + AA_READ_X(e, AA_U32, &(profile->flags.complain), NULL);
7735 + AA_READ_X(e, AA_U32, &(profile->flags.audit), NULL);
7736 + AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
7738 + error_string = "Invalid capabilities";
7739 + AA_READ_X(e, AA_U32, &(profile->capabilities), NULL);
7741 + /* get the file entries. */
7742 + AA_ENTRY_LIST("pgent"); /* pcre rules */
7743 + AA_ENTRY_LIST("sgent"); /* simple globs */
7744 + AA_ENTRY_LIST("fent"); /* regular file entries */
7746 + /* get the net entries */
7747 + if (aa_is_nameX(e, AA_LIST, NULL, "net")) {
7748 + error_string = "Invalid net entry";
7749 + while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) {
7750 + if (!aa_activate_net_entry(e))
7756 + /* get subprofiles */
7757 + if (aa_is_nameX(e, AA_LIST, NULL, "hats")) {
7758 + error_string = "Invalid profile hat";
7759 + while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) {
7760 + struct aaprofile *subprofile;
7761 + subprofile = aa_activate_profile(e, error);
7764 + subprofile->parent = profile;
7765 + list_add(&subprofile->list, &profile->sub);
7769 + error_string = "Invalid end of profile";
7770 + AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
7775 + AA_WARN("%s: %s %s in profile %s\n", INTERFACE_ID, rulename,
7776 + error_string, profile && profile->name ? profile->name
7780 + free_aaprofile(profile);
7788 + * aa_activate_top_profile - unpack a serialized base profile
7789 + * @e: serialized data extent information
7790 + * @error: error code returned if unpacking fails
7792 + * check interface version unpack a profile and all its hats and patch
7793 + * in any extra information that the profile needs.
7795 +static void *aa_activate_top_profile(struct aa_ext *e, ssize_t *error)
7797 + struct aaprofile *profile = NULL;
7799 + /* get the interface version */
7800 + if (!aa_is_nameX(e, AA_U32, &e->version, "version")) {
7801 + AA_WARN("%s: version missing\n", INTERFACE_ID);
7802 + *error = -EPROTONOSUPPORT;
7806 + /* check that the interface version is currently supported */
7807 + if (e->version != 2) {
7808 + AA_WARN("%s: unsupported interface version (%d)\n",
7809 + INTERFACE_ID, e->version);
7810 + *error = -EPROTONOSUPPORT;
7814 + profile = aa_activate_profile(e, error);
7818 + if (!list_empty(&profile->sub) || profile->flags.complain) {
7819 + if (attach_nullprofile(profile))
7825 + free_aaprofile(profile);
7830 + * aa_file_prof_add - add a new profile to the profile list
7831 + * @data: serialized data stream
7832 + * @size: size of the serialized data stream
7834 + * unpack and add a profile to the profile list. Return %0 or error
7836 +ssize_t aa_file_prof_add(void *data, size_t size)
7838 + struct aaprofile *profile = NULL;
7840 + struct aa_ext e = {
7842 + .end = data + size,
7847 + profile = aa_activate_top_profile(&e, &error);
7849 + AA_DEBUG("couldn't activate profile\n");
7853 + /* aa_activate_top_profile allocates profile with initial 1 count
7854 + * aa_profilelist_add transfers that ref to profile list without
7855 + * further incrementing
7857 + if (aa_profilelist_add(profile)) {
7860 + AA_WARN("trying to add profile (%s) that already exists.\n",
7862 + put_aaprofile(profile);
7871 + * aa_file_prof_repl - replace a profile on the profile list
7872 + * @udata: serialized data stream
7873 + * @size: size of the serialized data stream
7875 + * unpack and replace a profile on the profile list and uses of that profile
7876 + * by any subdomain. If the profile does not exist on the profile list
7877 + * it is added. Return %0 or error.
7879 +ssize_t aa_file_prof_repl(void *udata, size_t size)
7881 + struct aa_taskreplace_data data;
7882 + struct aa_ext e = {
7884 + .end = udata + size,
7890 + data.new_profile = aa_activate_top_profile(&e, &error);
7891 + if (!data.new_profile) {
7892 + AA_DEBUG("couldn't activate profile\n");
7896 + /* Refcount on data.new_profile is 1 (aa_activate_top_profile).
7898 + * This reference will be inherited by aa_profilelist_replace for it's
7899 + * profile list reference but this isn't sufficient.
7901 + * Another replace (*for-same-profile*) may race us here.
7902 + * Task A calls aa_profilelist_replace(new_profile) and is interrupted.
7903 + * Task B old_profile = aa_profilelist_replace() will return task A's
7904 + * new_profile with the count of 1. If task B proceeeds to put this
7905 + * profile it will dissapear from under task A.
7907 + * Grab extra reference on new_profile to prevent this
7910 + get_aaprofile(data.new_profile);
7912 + data.old_profile = aa_profilelist_replace(data.new_profile);
7914 + /* If there was an old profile, find all currently executing tasks
7915 + * using this profile and replace the old profile with the new.
7917 + if (data.old_profile) {
7918 + AA_DEBUG("%s: try to replace profile (%p)%s\n",
7921 + data.old_profile->name);
7923 + aa_subdomainlist_iterate(taskreplace_iter, (void *)&data);
7925 + /* it's off global list, and we are done replacing */
7926 + put_aaprofile(data.old_profile);
7929 + /* release extra reference obtained above (race) */
7930 + put_aaprofile(data.new_profile);
7939 + * aa_file_prof_remove - remove a profile from the system
7940 + * @name: name of the profile to remove
7941 + * @size: size of the name
7943 + * remove a profile from the profile list and all subdomain references
7944 + * to said profile. Return %0 on success, else error.
7946 +ssize_t aa_file_prof_remove(const char *name, size_t size)
7948 + struct aaprofile *old_profile;
7950 + /* if the old profile exists it will be removed from the list and
7951 + * a reference is returned.
7953 + old_profile = aa_profilelist_remove(name);
7955 + if (old_profile) {
7956 + /* remove profile from any tasks using it */
7957 + aa_subdomainlist_iterate(taskremove_iter, (void *)old_profile);
7959 + /* drop reference obtained by aa_profilelist_remove */
7960 + put_aaprofile(old_profile);
7962 + AA_WARN("%s: trying to remove profile (%s) that "
7963 + "doesn't exist - skipping.\n", __FUNCTION__, name);
7971 + * free_aaprofile_kref - free aaprofile by kref (called by put_aaprofile)
7972 + * @kr: kref callback for freeing of a profile
7974 +void free_aaprofile_kref(struct kref *kr)
7976 + struct aaprofile *p=container_of(kr, struct aaprofile, count);
7978 + call_rcu(&p->rcu, free_aaprofile_rcu);
7982 + * free_aaprofile - free aaprofile structure
7983 + * @profile: the profile to free
7985 + * free a profile, its file entries hats and null_profile. All references
7986 + * to the profile, its hats and null_profile must have been put.
7987 + * If the profile was referenced by a subdomain free_aaprofile should be
7988 + * called from an rcu callback routine.
7990 +void free_aaprofile(struct aaprofile *profile)
7992 + struct aa_entry *ent, *tmp;
7993 + struct aaprofile *p, *ptmp;
7995 + AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8000 + /* profile is still on global profile list -- invalid */
8001 + if (!list_empty(&profile->list)) {
8002 + AA_ERROR("%s: internal error, "
8003 + "profile '%s' still on global list\n",
8009 + list_for_each_entry_safe(ent, tmp, &profile->file_entry, list) {
8010 + if (ent->filename)
8011 + AA_DEBUG("freeing aa_entry: %p %s\n",
8012 + ent->filename, ent->filename);
8013 + list_del_init(&ent->list);
8014 + free_aa_entry(ent);
8017 + /* use free_aaprofile instead of put_aaprofile to destroy the
8018 + * null_profile, because the null_profile use the same reference
8019 + * counting as hats, ie. the count goes to the base profile.
8021 + free_aaprofile(profile->null_profile);
8022 + list_for_each_entry_safe(p, ptmp, &profile->sub, list) {
8023 + list_del_init(&p->list);
8028 + if (profile->name) {
8029 + AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
8030 + kfree(profile->name);
8035 Index: b/security/apparmor/module_interface.h
8036 ===================================================================
8038 +++ b/security/apparmor/module_interface.h
8040 +#ifndef __MODULEINTERFACE_H
8041 +#define __MODULEINTERFACE_H
8043 +/* Codes of the types of basic structures that are understood */
8044 +#define AA_CODE_BYTE (sizeof(u8))
8045 +#define INTERFACE_ID "INTERFACE"
8047 +#define APPARMOR_INTERFACE_VERSION 2
8054 + AA_NAME, /* same as string except it is items name */
8065 +/* aa_ext tracks the kernel buffer and read position in it. The interface
8066 + * data is copied into a kernel buffer in apparmorfs and then handed off to
8067 + * the activate routines.
8072 + void *pos; /* pointer to current position in the buffer */
8076 +#endif /* __MODULEINTERFACE_H */
8077 Index: b/security/apparmor/procattr.c
8078 ===================================================================
8080 +++ b/security/apparmor/procattr.c
8083 + * Copyright (C) 2005 Novell/SUSE
8085 + * This program is free software; you can redistribute it and/or
8086 + * modify it under the terms of the GNU General Public License as
8087 + * published by the Free Software Foundation, version 2 of the
8090 + * AppArmor /proc/pid/attr handling
8094 +#include <linux/ctype.h>
8096 +#include "apparmor.h"
8097 +#include "inline.h"
8099 +size_t aa_getprocattr(struct aaprofile *active, char *str, size_t size)
8101 + int error = -EACCES; /* default to a perm denied */
8105 + size_t lena, lenm, lenp = 0;
8106 + const char *enforce_str = " (enforce)";
8107 + const char *complain_str = " (complain)";
8108 + const char *mode_str =
8109 + PROFILE_COMPLAIN(active) ? complain_str : enforce_str;
8111 + lenm = strlen(mode_str);
8113 + lena = strlen(active->name);
8116 + if (IN_SUBPROFILE(active)) {
8117 + lenp = strlen(BASE_PROFILE(active)->name);
8118 + len += (lenp + 1); /* +1 for ^ */
8120 + /* DONT null terminate strings we output via proc */
8121 + len += (lenm + 1); /* for \n */
8123 + if (len <= size) {
8125 + memcpy(str, BASE_PROFILE(active)->name,
8131 + memcpy(str, active->name, lena);
8133 + memcpy(str, mode_str, lenm);
8137 + } else if (size == 0) {
8143 + const char *unconstrained_str = "unconstrained\n";
8144 + len = strlen(unconstrained_str);
8146 + /* DONT null terminate strings we output via proc */
8147 + if (len <= size) {
8148 + memcpy(str, unconstrained_str, len);
8150 + } else if (size == 0) {
8161 +int aa_setprocattr_changehat(char *hatinfo, size_t infosize)
8163 + int error = -EINVAL;
8164 + char *token = NULL, *hat, *smagic, *tmp;
8166 + int rc, len, consumed;
8167 + unsigned long flags;
8169 + AA_DEBUG("%s: %p %zd\n", __FUNCTION__, hatinfo, infosize);
8171 + /* strip leading white space */
8172 + while (infosize && isspace(*hatinfo)) {
8177 + if (infosize == 0)
8181 + * Copy string to a new buffer so we can play with it
8182 + * It may be zero terminated but we add a trailing 0
8185 + token = kmalloc(infosize + 1, GFP_KERNEL);
8192 + memcpy(token, hatinfo, infosize);
8193 + token[infosize] = 0;
8195 + /* error is INVAL until we have at least parsed something */
8199 + while (*tmp && *tmp != '^') {
8203 + if (!*tmp || tmp == token) {
8204 + AA_WARN("%s: Invalid input '%s'\n", __FUNCTION__, token);
8208 + /* split magic and hat into two strings */
8213 + * Initially set consumed=strlen(magic), as if sscanf
8214 + * consumes all input via the %x it will not process the %n
8215 + * directive. Otherwise, if sscanf does not consume all the
8216 + * input it will process the %n and update consumed.
8218 + consumed = len = strlen(smagic);
8220 + rc = sscanf(smagic, "%x%n", &magic, &consumed);
8222 + if (rc != 1 || consumed != len) {
8223 + AA_WARN("%s: Invalid hex magic %s\n",
8234 + if (!hat && !magic) {
8235 + AA_WARN("%s: Invalid input, NULL hat and NULL magic\n",
8240 + AA_DEBUG("%s: Magic 0x%x Hat '%s'\n",
8241 + __FUNCTION__, magic, hat ? hat : NULL);
8243 + spin_lock_irqsave(&sd_lock, flags);
8244 + error = aa_change_hat(hat, magic);
8245 + spin_unlock_irqrestore(&sd_lock, flags);
8249 + memset(token, 0, infosize);
8256 +int aa_setprocattr_setprofile(struct task_struct *p, char *profilename,
8257 + size_t profilesize)
8259 + int error = -EINVAL;
8260 + struct aaprofile *profile = NULL;
8261 + struct subdomain *sd;
8262 + char *name = NULL;
8263 + unsigned long flags;
8265 + AA_DEBUG("%s: current %s(%d)\n",
8266 + __FUNCTION__, current->comm, current->pid);
8268 + /* strip leading white space */
8269 + while (profilesize && isspace(*profilename)) {
8274 + if (profilesize == 0)
8278 + * Copy string to a new buffer so we guarantee it is zero
8281 + name = kmalloc(profilesize + 1, GFP_KERNEL);
8288 + strncpy(name, profilename, profilesize);
8289 + name[profilesize] = 0;
8292 + if (strcmp(name, "unconstrained") != 0) {
8293 + profile = aa_profilelist_find(name);
8295 + AA_WARN("%s: Unable to switch task %s(%d) to profile"
8296 + "'%s'. No such profile.\n",
8306 + spin_lock_irqsave(&sd_lock, flags);
8308 + sd = AA_SUBDOMAIN(p->security);
8310 + /* switch to unconstrained */
8312 + if (__aa_is_confined(sd)) {
8313 + AA_WARN("%s: Unconstraining task %s(%d) "
8314 + "profile %s active %s\n",
8317 + BASE_PROFILE(sd->active)->name,
8318 + sd->active->name);
8320 + aa_switch_unconfined(sd);
8322 + AA_WARN("%s: task %s(%d) "
8323 + "is already unconstrained\n",
8324 + __FUNCTION__, p->comm, p->pid);
8328 + /* this task was created before module was
8329 + * loaded, allocate a subdomain
8331 + AA_WARN("%s: task %s(%d) has no subdomain\n",
8332 + __FUNCTION__, p->comm, p->pid);
8334 + /* unlock so we can safely GFP_KERNEL */
8335 + spin_unlock_irqrestore(&sd_lock, flags);
8337 + sd = alloc_subdomain(p);
8339 + AA_WARN("%s: Unable to allocate subdomain for "
8340 + "task %s(%d). Cannot confine task to "
8347 + put_aaprofile(profile);
8352 + spin_lock_irqsave(&sd_lock, flags);
8353 + if (!AA_SUBDOMAIN(p->security)) {
8355 + } else { /* race */
8356 + free_subdomain(sd);
8357 + sd = AA_SUBDOMAIN(p->security);
8361 + /* ensure the profile hasn't been replaced */
8363 + if (unlikely(profile->isstale)) {
8364 + WARN_ON(profile == null_complain_profile);
8366 + /* drop refcnt obtained from earlier get_aaprofile */
8367 + put_aaprofile(profile);
8368 + profile = aa_profilelist_find(name);
8371 + /* Race, profile was removed. */
8372 + spin_unlock_irqrestore(&sd_lock, flags);
8377 + /* we do not do a normal task replace since we are not
8378 + * replacing with the same profile.
8379 + * If existing process is in a hat, it will be moved
8380 + * into the new parent profile, even if this new
8381 + * profile has a identical named hat.
8384 + AA_WARN("%s: Switching task %s(%d) "
8385 + "profile %s active %s to new profile %s\n",
8388 + sd->active ? BASE_PROFILE(sd->active)->name :
8390 + sd->active ? sd->active->name : "unconstrained",
8393 + aa_switch(sd, profile);
8395 + put_aaprofile(profile); /* drop ref we obtained above
8396 + * from aa_profilelist_find
8399 + /* Reset magic in case we were in a subhat before
8400 + * This is the only case where we zero the magic after
8401 + * calling aa_switch
8403 + sd->hat_magic = 0;
8406 + spin_unlock_irqrestore(&sd_lock, flags);
8414 Index: b/security/apparmor/shared.h
8415 ===================================================================
8417 +++ b/security/apparmor/shared.h
8420 + * Copyright (C) 2000, 2001, 2004, 2005 Novell/SUSE
8422 + * Immunix AppArmor LSM
8424 + * This program is free software; you can redistribute it and/or
8425 + * modify it under the terms of the GNU General Public License as
8426 + * published by the Free Software Foundation, version 2 of the
8433 +/* start of system offsets */
8434 +#define POS_AA_FILE_MIN 0
8435 +#define POS_AA_MAY_EXEC POS_AA_FILE_MIN
8436 +#define POS_AA_MAY_WRITE (POS_AA_MAY_EXEC + 1)
8437 +#define POS_AA_MAY_READ (POS_AA_MAY_WRITE + 1)
8438 +#define POS_AA_MAY_APPEND (POS_AA_MAY_READ + 1)
8439 +/* end of system offsets */
8441 +#define POS_AA_MAY_LINK (POS_AA_MAY_APPEND + 1)
8442 +#define POS_AA_EXEC_INHERIT (POS_AA_MAY_LINK + 1)
8443 +#define POS_AA_EXEC_UNCONSTRAINED (POS_AA_EXEC_INHERIT + 1)
8444 +#define POS_AA_EXEC_PROFILE (POS_AA_EXEC_UNCONSTRAINED + 1)
8445 +#define POS_AA_EXEC_MMAP (POS_AA_EXEC_PROFILE + 1)
8446 +#define POS_AA_EXEC_UNSAFE (POS_AA_EXEC_MMAP + 1)
8447 +#define POS_AA_FILE_MAX POS_AA_EXEC_UNSAFE
8449 +/* Modeled after MAY_READ, MAY_WRITE, MAY_EXEC def'ns */
8450 +#define AA_MAY_EXEC (0x01 << POS_AA_MAY_EXEC)
8451 +#define AA_MAY_WRITE (0x01 << POS_AA_MAY_WRITE)
8452 +#define AA_MAY_READ (0x01 << POS_AA_MAY_READ)
8453 +#define AA_MAY_LINK (0x01 << POS_AA_MAY_LINK)
8454 +#define AA_EXEC_INHERIT (0x01 << POS_AA_EXEC_INHERIT)
8455 +#define AA_EXEC_UNCONSTRAINED (0x01 << POS_AA_EXEC_UNCONSTRAINED)
8456 +#define AA_EXEC_PROFILE (0x01 << POS_AA_EXEC_PROFILE)
8457 +#define AA_EXEC_MMAP (0x01 << POS_AA_EXEC_MMAP)
8458 +#define AA_EXEC_UNSAFE (0x01 << POS_AA_EXEC_UNSAFE)
8460 +#define AA_EXEC_MODIFIERS (AA_EXEC_INHERIT | \
8461 + AA_EXEC_UNCONSTRAINED | \
8464 +#endif /* _SHARED_H */