]> git.pld-linux.org Git - packages/kernel.git/blob - apparmor-2.6.20.3-v405-fullseries.diff
- blah, not needed on HEAD
[packages/kernel.git] / apparmor-2.6.20.3-v405-fullseries.diff
1  fs/namespace.c                          |    3 
2  include/linux/audit.h                   |    5 
3  include/linux/mnt_namespace.h           |    3 
4  kernel/audit.c                          |    6 
5  security/Kconfig                        |    1 
6  security/Makefile                       |    1 
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
34 @@ -110,6 +110,8 @@
35  #define AUDIT_LAST_KERN_ANOM_MSG    1799
36  #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
37  
38 +#define AUDIT_SD               1500    /* AppArmor (SubDomain) audit */
39 +
40  #define AUDIT_KERNEL           2000    /* Asynchronous audit record. NOT A REQUEST. */
41  
42  /* Rule flags */
43 @@ -478,6 +480,9 @@ extern void             audit_log(struct audit_
44                                       __attribute__((format(printf,4,5)));
45  
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,
51                                              const char *fmt, ...)
52                             __attribute__((format(printf,2,3)));
53 Index: b/kernel/audit.c
54 ===================================================================
55 --- a/kernel/audit.c
56 +++ b/kernel/audit.c
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.
60   */
61 -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
62 -                             va_list args)
63 +void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
64  {
65         int len, avail;
66         struct sk_buff *skb;
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 ===================================================================
76 --- a/fs/namespace.c
77 +++ b/fs/namespace.c
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);
85  
86  /* /sys/fs */
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
92 @@ -6,6 +6,9 @@
93  #include <linux/sched.h>
94  #include <linux/nsproxy.h>
95  
96 +/* exported for AppArmor (SubDomain) */
97 +extern struct rw_semaphore namespace_sem;
98 +
99  struct mnt_namespace {
100         atomic_t                count;
101         struct vfsmount *       root;
102 Index: b/security/Makefile
103 ===================================================================
104 --- a/security/Makefile
105 +++ b/security/Makefile
106 @@ -4,6 +4,7 @@
107  
108  obj-$(CONFIG_KEYS)                     += keys/
109  subdir-$(CONFIG_SECURITY_SELINUX)      += selinux
110 +obj-$(CONFIG_SECURITY_APPARMOR)                += commoncap.o apparmor/
111  
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.
120  
121  source security/selinux/Kconfig
122 +source security/apparmor/Kconfig
123  
124  endmenu
125  
126 Index: b/security/apparmor/Kbuild
127 ===================================================================
128 --- /dev/null
129 +++ b/security/apparmor/Kbuild
130 @@ -0,0 +1,10 @@
131 +# Makefile for AppArmor Linux Security Module
132 +#
133 +EXTRA_CFLAGS += -DAPPARMOR_VERSION=\"${APPARMOR_VER}\"
134 +
135 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
136 +
137 +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o capabilities.o \
138 +             module_interface.o
139 +
140 +obj-$(CONFIG_SECURITY_APPARMOR) += match/
141 Index: b/security/apparmor/Kconfig
142 ===================================================================
143 --- /dev/null
144 +++ b/security/apparmor/Kconfig
145 @@ -0,0 +1,9 @@
146 +config SECURITY_APPARMOR
147 +       tristate "AppArmor support"
148 +       depends on SECURITY!=n
149 +       help
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 ===================================================================
157 --- /dev/null
158 +++ b/security/apparmor/Makefile
159 @@ -0,0 +1,28 @@
160 +# Makefile for AppArmor Linux Security Module
161 +#
162 +# kernel build Makefile is the Kbuild file
163 +
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: //" ; \
166 +       fi)
167 +
168 +ifeq ("${REPO_VERSION}", "")
169 +REPO_VERSION := "unknown"
170 +endif
171 +
172 +KERNELVER := $(shell uname -r)
173 +
174 +KERNELDIR := /lib/modules/${KERNELVER}/build
175 +
176 +all:
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
181 +
182 +clean:
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
186 +
187 +
188 Index: b/security/apparmor/apparmor.h
189 ===================================================================
190 --- /dev/null
191 +++ b/security/apparmor/apparmor.h
192 @@ -0,0 +1,356 @@
193 +/*
194 + *     Copyright (C) 1998-2005 Novell/SUSE
195 + *
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
199 + *     License.
200 + *
201 + *     AppArmor internal prototypes
202 + */
203 +
204 +#ifndef __APPARMOR_H
205 +#define __APPARMOR_H
206 +
207 +#include <linux/fs.h>  /* Include for defn of iattr */
208 +#include <linux/binfmts.h>     /* defn of linux_binprm */
209 +#include <linux/rcupdate.h>
210 +
211 +#include "shared.h"
212 +
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;
219 +
220 +/* PIPEFS_MAGIC */
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
226 +
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)
230 +
231 +#define PROFILE_COMPLAIN(_profile) \
232 +       (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
233 +
234 +#define SUBDOMAIN_COMPLAIN(_sd) \
235 +       (apparmor_complain == 1 || \
236 +        ((_sd) && (_sd)->active && (_sd)->active->flags.complain))
237 +
238 +#define PROFILE_AUDIT(_profile) \
239 +       (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
240 +
241 +#define SUBDOMAIN_AUDIT(_sd) \
242 +       (apparmor_audit == 1 || \
243 +        ((_sd) && (_sd)->active && (_sd)->active->flags.audit))
244 +
245 +/*
246 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
247 + * which is not related to profile accesses.
248 + */
249 +
250 +#define AA_DEBUG(fmt, args...)                                         \
251 +       do {                                                            \
252 +               if (apparmor_debug)                                     \
253 +                       printk(KERN_DEBUG "AppArmor: " fmt, ##args);    \
254 +       } while (0)
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)
258 +
259 +
260 +/* apparmor logged syscall reject caching */
261 +enum aasyscall {
262 +       AA_SYSCALL_PTRACE,
263 +       AA_SYSCALL_SYSCTL_WRITE,
264 +       AA_SYSCALL_MOUNT,
265 +       AA_SYSCALL_UMOUNT
266 +};
267 +
268 +#define AA_SYSCALL_TO_MASK(X) (1 << (X))
269 +
270 +
271 +/* basic AppArmor data structures */
272 +
273 +struct flagval {
274 +       int debug;
275 +       int complain;
276 +       int audit;
277 +};
278 +
279 +enum entry_match_type {
280 +       aa_entry_literal,
281 +       aa_entry_tailglob,
282 +       aa_entry_pattern,
283 +       aa_entry_invalid
284 +};
285 +
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.
293 + *
294 + * Each entry describes a file and an allowed access mode.
295 + */
296 +struct aa_entry {
297 +       char *filename;
298 +       int mode;               /* mode is 'or' of READ, WRITE, EXECUTE,
299 +                                * INHERIT, UNCONSTRAINED, and LIBRARY
300 +                                * (meaning don't prefetch). */
301 +
302 +       enum entry_match_type type;
303 +       void *extradata;
304 +
305 +       struct list_head list;
306 +       struct list_head listp[POS_AA_FILE_MAX + 1];
307 +};
308 +
309 +#define AA_SECURE_EXEC_NEEDED 0x00000001
310 +
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 |\
314 +                                            AA_EXEC_UNSAFE))
315 +
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
331 + *
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
335 + */
336 +struct aaprofile {
337 +       struct aaprofile *parent;
338 +       char *name;
339 +
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;
346 +       int isstale;
347 +
348 +       int num_file_entries;
349 +       int num_file_pentries[POS_AA_FILE_MAX + 1];
350 +
351 +       kernel_cap_t capabilities;
352 +
353 +       struct rcu_head rcu;
354 +
355 +       struct kref count;
356 +};
357 +
358 +enum aafile_type {
359 +       aa_file_default,
360 +       aa_file_shmem
361 +};
362 +
363 +/**
364 + * aafile - file pointer confinement data
365 + *
366 + * Data structure assigned to each open file (by apparmor_file_alloc_security)
367 + */
368 +struct aafile {
369 +       enum aafile_type type;
370 +       struct aaprofile *profile;
371 +};
372 +
373 +/**
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
381 + *
382 + * Contains the tasks current active profile (which could change due to
383 + * change_hat).  Plus the hat_magic needed during change_hat.
384 + *
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).
387 + */
388 +struct subdomain {
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;
393 +
394 +       kernel_cap_t cached_caps;
395 +       unsigned int cached_syscalls;
396 +};
397 +
398 +typedef int (*aa_iter) (struct subdomain *, void *);
399 +
400 +/* aa_path_data
401 + * temp (cookie) data used by aa_path_* functions, see inline.h
402 + */
403 +struct aa_path_data {
404 +       struct dentry *root, *dentry;
405 +       struct mnt_namespace *mnt_namespace;
406 +       struct list_head *head, *pos;
407 +       int errno;
408 +};
409 +
410 +#define AA_SUBDOMAIN(sec)      ((struct subdomain*)(sec))
411 +#define AA_PROFILE(sec)                ((struct aaprofile*)(sec))
412 +
413 +/* Lock protecting access to 'struct subdomain' accesses */
414 +extern spinlock_t sd_lock;
415 +
416 +extern struct aaprofile *null_complain_profile;
417 +
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.
421 + */
422 +
423 +struct aa_audit {
424 +       unsigned short type, flags;
425 +       unsigned int result;
426 +       gfp_t gfp_mask;
427 +       int error_code;
428 +
429 +       const char *name;
430 +       unsigned int ival;
431 +       union {
432 +               const void *pval;
433 +               va_list vaval;
434 +       };
435 +};
436 +
437 +/* audit types */
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
447 +
448 +/* audit flags */
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  */
452 +
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"
457 +
458 +#define LOG_HINT(p, gfp, hint, fmt, args...) \
459 +       do {\
460 +               aa_audit_message(p, gfp, 0, \
461 +                       "LOGPROF-HINT " hint " " fmt, ##args);\
462 +       } while(0)
463 +
464 +/* directory op type, for aa_perm_dir */
465 +enum aa_diroptype {
466 +       aa_dir_mkdir,
467 +       aa_dir_rmdir
468 +};
469 +
470 +/* xattr op type, for aa_xattr */
471 +enum aa_xattroptype {
472 +       aa_xattr_get,
473 +       aa_xattr_set,
474 +       aa_xattr_list,
475 +       aa_xattr_remove
476 +};
477 +
478 +#define BASE_PROFILE(p) ((p)->parent ? (p)->parent : (p))
479 +#define IN_SUBPROFILE(p) ((p)->parent)
480 +
481 +/* main.c */
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);
491 +
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,
500 +                            int mask);
501 +extern int aa_perm_dentry(struct aaprofile *active, struct dentry *dentry,
502 +                         int mask);
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);
512 +
513 +/* list.c */
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);
526 +
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);
533 +
534 +/* procattr.c */
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);
539 +
540 +/* apparmorfs.c */
541 +extern int create_apparmorfs(void);
542 +extern void destroy_apparmorfs(void);
543 +
544 +/* capabilities.c */
545 +extern const char *capability_to_name(unsigned int cap);
546 +extern const char *syscall_to_name(enum aasyscall call);
547 +
548 +#endif                         /* __APPARMOR_H */
549 Index: b/security/apparmor/apparmorfs.c
550 ===================================================================
551 --- /dev/null
552 +++ b/security/apparmor/apparmorfs.c
553 @@ -0,0 +1,432 @@
554 +/*
555 + *     Copyright (C) 2005 Novell/SUSE
556 + *
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
560 + *     License.
561 + *
562 + *     AppArmor filesystem (part of securityfs)
563 + */
564 +
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>
570 +
571 +#include "apparmor.h"
572 +#include "inline.h"
573 +#include "match/match.h"
574 +
575 +#define SECFS_AA "apparmor"
576 +static struct dentry *aafs_dentry = NULL;
577 +
578 +/* profile */
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);
582 +
583 +static struct file_operations apparmorfs_profiles_fops = {
584 +       .open =         aa_prof_open,
585 +       .read =         seq_read,
586 +       .llseek =       seq_lseek,
587 +       .release =      aa_prof_release,
588 +};
589 +
590 +/* matching */
591 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
592 +                              size_t size, loff_t *ppos);
593 +
594 +static struct file_operations apparmorfs_matching_fops = {
595 +       .read =         aa_matching_read,
596 +};
597 +
598 +
599 +/* interface */
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);
606 +
607 +static struct file_operations apparmorfs_profile_load = {
608 +       .write = aa_profile_load
609 +};
610 +
611 +static struct file_operations apparmorfs_profile_replace = {
612 +       .write = aa_profile_replace
613 +};
614 +
615 +static struct file_operations apparmorfs_profile_remove = {
616 +       .write = aa_profile_remove
617 +};
618 +
619 +
620 +/* control */
621 +static u64 aa_control_get(void *data);
622 +static void aa_control_set(void *data, u64 val);
623 +
624 +DEFINE_SIMPLE_ATTRIBUTE(apparmorfs_control_fops, aa_control_get,
625 +                       aa_control_set, "%lld\n");
626 +
627 +
628 +
629 +/* table of static entries */
630 +
631 +static struct root_entry {
632 +       const char *name;
633 +       int mode;
634 +       int access;
635 +       struct file_operations *fops;
636 +       void *data;
637 +
638 +       /* internal fields */
639 +       struct dentry *dentry;
640 +       int parent_index;
641 +} root_entries[] = {
642 +       /* our root, normally /sys/kernel/security/apparmor */
643 +       {SECFS_AA,      S_IFDIR, 0550}, /* DO NOT EDIT/MOVE */
644 +
645 +       /* interface for obtaining list of profiles currently loaded */
646 +       {"profiles",    S_IFREG, 0440, &apparmorfs_profiles_fops,
647 +                                      NULL},
648 +
649 +       /* interface for obtaining matching features supported */
650 +       {"matching",    S_IFREG, 0440, &apparmorfs_matching_fops,
651 +                                      NULL},
652 +
653 +       /* interface for loading/removing/replacing profiles */
654 +       {".load",       S_IFREG, 0640, &apparmorfs_profile_load,
655 +                                      NULL},
656 +       {".replace",    S_IFREG, 0640, &apparmorfs_profile_replace,
657 +                                      NULL},
658 +       {".remove",     S_IFREG, 0640, &apparmorfs_profile_remove,
659 +                                      NULL},
660 +
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,
666 +                                      &apparmor_audit},
667 +       {"debug",       S_IFREG, 0640, &apparmorfs_control_fops,
668 +                                      &apparmor_debug},
669 +       {"logsyscall",  S_IFREG, 0640, &apparmorfs_control_fops,
670 +                                      &apparmor_logsyscall},
671 +       {NULL,          S_IFDIR, 0},
672 +
673 +       /* root end */
674 +       {NULL,          S_IFDIR, 0}
675 +};
676 +
677 +#define AAFS_DENTRY root_entries[0].dentry
678 +
679 +static const unsigned int num_entries =
680 +       sizeof(root_entries) / sizeof(struct root_entry);
681 +
682 +
683 +
684 +static int aa_prof_open(struct inode *inode, struct file *file)
685 +{
686 +       return seq_open(file, &apparmorfs_profiles_op);
687 +}
688 +
689 +
690 +static int aa_prof_release(struct inode *inode, struct file *file)
691 +{
692 +       return seq_release(inode, file);
693 +}
694 +
695 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
696 +                              size_t size, loff_t *ppos)
697 +{
698 +       const char *matching = aamatch_features();
699 +
700 +       return simple_read_from_buffer(buf, size, ppos, matching,
701 +                                      strlen(matching));
702 +}
703 +
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)
707 +{
708 +       struct aaprofile *active;
709 +       char *data;
710 +
711 +       if (*pos != 0) {
712 +               /* only writes from pos 0, that is complete writes */
713 +               data = ERR_PTR(-ESPIPE);
714 +               goto out;
715 +       }
716 +
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.
720 +        */
721 +       rcu_read_lock();
722 +       active = get_activeptr_rcu();
723 +       if (active) {
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);
728 +
729 +               data = ERR_PTR(-EPERM);
730 +               goto out;
731 +       }
732 +       rcu_read_unlock();
733 +
734 +       data = vmalloc(alloc_size);
735 +       if (data == NULL) {
736 +               data = ERR_PTR(-ENOMEM);
737 +               goto out;
738 +       }
739 +
740 +       if (copy_from_user(data, userbuf, copy_size)) {
741 +               vfree(data);
742 +               data = ERR_PTR(-EFAULT);
743 +               goto out;
744 +       }
745 +
746 +out:
747 +       return data;
748 +}
749 +
750 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
751 +                              size_t size, loff_t *pos)
752 +{
753 +       char *data;
754 +       ssize_t error;
755 +
756 +       data = aa_simple_write_to_buffer(buf, size, size, pos, "load");
757 +
758 +       if (!IS_ERR(data)) {
759 +               error = aa_file_prof_add(data, size);
760 +               vfree(data);
761 +       } else {
762 +               error = PTR_ERR(data);
763 +       }
764 +
765 +       return error;
766 +}
767 +
768 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
769 +                                 size_t size, loff_t *pos)
770 +{
771 +       char *data;
772 +       ssize_t error;
773 +
774 +       data = aa_simple_write_to_buffer(buf, size, size, pos, "replacement");
775 +
776 +       if (!IS_ERR(data)) {
777 +               error = aa_file_prof_repl(data, size);
778 +               vfree(data);
779 +       } else {
780 +               error = PTR_ERR(data);
781 +       }
782 +
783 +       return error;
784 +}
785 +
786 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
787 +                                 size_t size, loff_t *pos)
788 +{
789 +       char *data;
790 +       ssize_t error;
791 +
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
794 +        */
795 +       data = aa_simple_write_to_buffer(buf, size+1, size, pos, "removal");
796 +
797 +       if (!IS_ERR(data)) {
798 +               data[size] = 0;
799 +               error = aa_file_prof_remove(data, size);
800 +               vfree(data);
801 +       } else {
802 +               error = PTR_ERR(data);
803 +       }
804 +
805 +       return error;
806 +}
807 +
808 +static u64 aa_control_get(void *data)
809 +{
810 +       return *(int *)data;
811 +}
812 +
813 +static void aa_control_set(void *data, u64 val)
814 +{
815 +       if (val > 1)
816 +               val = 1;
817 +
818 +       *(int*)data = (int)val;
819 +}
820 +
821 +static void clear_apparmorfs(void)
822 +{
823 +       unsigned int i;
824 +
825 +       for (i=0; i < num_entries;i++) {
826 +               unsigned int index;
827 +
828 +               if (root_entries[i].mode == S_IFDIR) {
829 +                       if (root_entries[i].name)
830 +                               /* defer dir free till all sub-entries freed */
831 +                               continue;
832 +                       else
833 +                               /* cleanup parent */
834 +                               index = root_entries[i].parent_index;
835 +               } else {
836 +                       index = i;
837 +               }
838 +
839 +               if (root_entries[index].dentry) {
840 +                       securityfs_remove(root_entries[index].dentry);
841 +
842 +                       AA_DEBUG("%s: deleted apparmorfs entry name=%s "
843 +                                "dentry=%p\n",
844 +                               __FUNCTION__,
845 +                               root_entries[index].name,
846 +                               root_entries[index].dentry);
847 +
848 +                       root_entries[index].dentry = NULL;
849 +                       root_entries[index].parent_index = 0;
850 +               }
851 +       }
852 +}
853 +
854 +static int populate_apparmorfs(struct dentry *root)
855 +{
856 +       unsigned int i, parent_index, depth;
857 +
858 +       for (i = 0; i < num_entries; i++) {
859 +               root_entries[i].dentry = NULL;
860 +               root_entries[i].parent_index = 0;
861 +       }
862 +
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",
869 +                       __FUNCTION__);
870 +               goto error;
871 +       }
872 +
873 +       /* 2. Build back pointers */
874 +       parent_index = 0;
875 +       depth = 1;
876 +
877 +       for (i = 1; i < num_entries; i++) {
878 +               root_entries[i].parent_index = parent_index;
879 +
880 +               if (root_entries[i].name &&
881 +                   root_entries[i].mode == S_IFDIR) {
882 +                       depth++;
883 +                       parent_index = i;
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)",
887 +                                        __FUNCTION__, i,
888 +                                        root_entries[i].mode,
889 +                                        root_entries[i].parent_index);
890 +                               goto error;
891 +                       }
892 +
893 +                       depth--;
894 +                       parent_index = root_entries[parent_index].parent_index;
895 +               }
896 +       }
897 +
898 +       if (depth != 0) {
899 +               AA_ERROR("%s: root_entry table not correctly terminated\n",
900 +                       __FUNCTION__);
901 +               goto error;
902 +       }
903 +
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,
909 +                                       NULL, NULL, NULL);
910 +
911 +       if (IS_ERR(root_entries[0].dentry))
912 +               goto error;
913 +       else
914 +               AA_DEBUG("%s: created securityfs/apparmor [dentry=%p]\n",
915 +                       __FUNCTION__, root_entries[0].dentry);
916 +
917 +
918 +       /* 4. create remaining nodes */
919 +       for (i = 1; i < num_entries; i++) {
920 +               struct dentry *parent;
921 +               void *data = NULL;
922 +               struct file_operations *fops = NULL;
923 +
924 +               /* end of directory ? */
925 +               if (!root_entries[i].name)
926 +                       continue;
927 +
928 +               parent = root_entries[root_entries[i].parent_index].dentry;
929 +
930 +               if (root_entries[i].mode != S_IFDIR) {
931 +                       data = root_entries[i].data;
932 +                       fops = root_entries[i].fops;
933 +               }
934 +
935 +               root_entries[i].dentry = securityfs_create_file(
936 +                                               root_entries[i].name,
937 +                                               root_entries[i].mode |
938 +                                                       root_entries[i].access,
939 +                                               parent,
940 +                                               data,
941 +                                               fops);
942 +
943 +               if (IS_ERR(root_entries[i].dentry))
944 +                       goto cleanup_error;
945 +
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);
951 +       }
952 +
953 +       return 0;
954 +
955 +cleanup_error:
956 +       clear_apparmorfs();
957 +
958 +error:
959 +       return -EINVAL;
960 +}
961 +
962 +int create_apparmorfs(void)
963 +{
964 +       int error = 0;
965 +
966 +       if (AAFS_DENTRY) {
967 +               error = -EEXIST;
968 +               AA_ERROR("%s: AppArmor securityfs already exists\n",
969 +                       __FUNCTION__);
970 +       } else {
971 +               error = populate_apparmorfs(aafs_dentry);
972 +               if (error != 0) {
973 +                       AA_ERROR("%s: Error populating AppArmor securityfs\n",
974 +                               __FUNCTION__);
975 +               }
976 +       }
977 +
978 +       return error;
979 +}
980 +
981 +void destroy_apparmorfs(void)
982 +{
983 +       if (AAFS_DENTRY)
984 +               clear_apparmorfs();
985 +}
986 Index: b/security/apparmor/capabilities.c
987 ===================================================================
988 --- /dev/null
989 +++ b/security/apparmor/capabilities.c
990 @@ -0,0 +1,71 @@
991 +/*
992 + *     Copyright (C) 2005 Novell/SUSE
993 + *
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
997 + *     License.
998 + *
999 + *     AppArmor capability definitions
1000 + */
1001 +
1002 +#include "apparmor.h"
1003 +
1004 +static const char *cap_names[] = {
1005 +       "chown",
1006 +       "dac_override",
1007 +       "dac_read_search",
1008 +       "fowner",
1009 +       "fsetid",
1010 +       "kill",
1011 +       "setgid",
1012 +       "setuid",
1013 +       "setpcap",
1014 +       "linux_immutable",
1015 +       "net_bind_service",
1016 +       "net_broadcast",
1017 +       "net_admin",
1018 +       "net_raw",
1019 +       "ipc_lock",
1020 +       "ipc_owner",
1021 +       "sys_module",
1022 +       "sys_rawio",
1023 +       "sys_chroot",
1024 +       "sys_ptrace",
1025 +       "sys_pacct",
1026 +       "sys_admin",
1027 +       "sys_boot",
1028 +       "sys_nice",
1029 +       "sys_resource",
1030 +       "sys_time",
1031 +       "sys_tty_config",
1032 +       "mknod",
1033 +       "lease",
1034 +       "audit_write",
1035 +       "audit_control"
1036 +};
1037 +
1038 +const char *capability_to_name(unsigned int cap)
1039 +{
1040 +       const char *name;
1041 +
1042 +       name = (cap < (sizeof(cap_names) / sizeof(char *))
1043 +                  ? cap_names[cap] : "invalid-capability");
1044 +
1045 +       return name;
1046 +}
1047 +
1048 +static const char *syscall_names[] = {
1049 +       "ptrace",
1050 +       "sysctl (write)",
1051 +       "mount",
1052 +       "umount"
1053 +};
1054 +
1055 +const char *syscall_to_name(enum aasyscall call)
1056 +{
1057 +       const char *name;
1058 +       name = (call < (sizeof(syscall_names) / sizeof(char *))
1059 +               ? syscall_names[call] : "invalid-syscall");
1060 +       return name;
1061 +}
1062 Index: b/security/apparmor/inline.h
1063 ===================================================================
1064 --- /dev/null
1065 +++ b/security/apparmor/inline.h
1066 @@ -0,0 +1,393 @@
1067 +/*
1068 + *     Copyright (C) 2005 Novell/SUSE
1069 + *
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
1073 + *     License.
1074 + */
1075 +
1076 +#ifndef __INLINE_H
1077 +#define __INLINE_H
1078 +
1079 +#include <linux/mnt_namespace.h>
1080 +
1081 +static inline int __aa_is_confined(struct subdomain *sd)
1082 +{
1083 +       return (sd && sd->active);
1084 +}
1085 +
1086 +/**
1087 + *  aa_is_confined
1088 + *  Determine whether current task contains a valid profile (confined).
1089 + *  Return %1 if confined, %0 otherwise.
1090 + */
1091 +static inline int aa_is_confined(void)
1092 +{
1093 +       struct subdomain *sd = AA_SUBDOMAIN(current->security);
1094 +       return __aa_is_confined(sd);
1095 +}
1096 +
1097 +static inline int __aa_sub_defined(struct subdomain *sd)
1098 +{
1099 +    return __aa_is_confined(sd) && !list_empty(&BASE_PROFILE(sd->active)->sub);
1100 +}
1101 +
1102 +/**
1103 + * aa_sub_defined - check to see if current task has any subprofiles
1104 + * Return 1 if true, 0 otherwise
1105 + */
1106 +static inline int aa_sub_defined(void)
1107 +{
1108 +       struct subdomain *sd = AA_SUBDOMAIN(current->security);
1109 +       return __aa_sub_defined(sd);
1110 +}
1111 +
1112 +/**
1113 + * get_aaprofile - increment refcount on profile @p
1114 + * @p: profile
1115 + */
1116 +static inline struct aaprofile *get_aaprofile(struct aaprofile *p)
1117 +{
1118 +       if (p)
1119 +               kref_get(&(BASE_PROFILE(p)->count));
1120 +
1121 +       return p;
1122 +}
1123 +
1124 +/**
1125 + * put_aaprofile - decrement refcount on profile @p
1126 + * @p: profile
1127 + */
1128 +static inline void put_aaprofile(struct aaprofile *p)
1129 +{
1130 +       if (p)
1131 +               kref_put(&BASE_PROFILE(p)->count, free_aaprofile_kref);
1132 +}
1133 +
1134 +/**
1135 + * get_task_activeptr_rcu - get pointer to @tsk's active profile.
1136 + * @tsk: task to get active profile from
1137 + *
1138 + * Requires rcu_read_lock is held
1139 + */
1140 +static inline struct aaprofile *get_task_activeptr_rcu(struct task_struct *tsk)
1141 +{
1142 +       struct subdomain *sd = AA_SUBDOMAIN(tsk->security);
1143 +       struct aaprofile *active = NULL;
1144 +
1145 +       if (sd)
1146 +               active = (struct aaprofile *) rcu_dereference(sd->active);
1147 +
1148 +       return active;
1149 +}
1150 +
1151 +/**
1152 + * get_activeptr_rcu - get pointer to current task's active profile
1153 + * Requires rcu_read_lock is held
1154 + */
1155 +static inline struct aaprofile *get_activeptr_rcu(void)
1156 +{
1157 +       return get_task_activeptr_rcu(current);
1158 +}
1159 +
1160 +/**
1161 + * get_task_active_aaprofile - get a reference to tsk's active profile.
1162 + * @tsk: the task to get the active profile reference for
1163 + */
1164 +static inline struct aaprofile *get_task_active_aaprofile(struct task_struct *tsk)
1165 +{
1166 +       struct aaprofile *active;
1167 +
1168 +       rcu_read_lock();
1169 +       active = get_aaprofile(get_task_activeptr_rcu(tsk));
1170 +       rcu_read_unlock();
1171 +
1172 +       return active;
1173 +}
1174 +
1175 +/**
1176 + * get_active_aaprofile - get a reference to the current tasks active profile
1177 + */
1178 +static inline struct aaprofile *get_active_aaprofile(void)
1179 +{
1180 +       return get_task_active_aaprofile(current);
1181 +}
1182 +
1183 +/**
1184 + * cap_is_cached - check if @cap access has already been logged for current
1185 + * @cap: capability to test if cached
1186 + */
1187 +static inline int cap_is_cached(int cap)
1188 +{
1189 +       struct subdomain *sd = AA_SUBDOMAIN(current->security);
1190 +       return cap_raised(sd->cached_caps, cap);
1191 +}
1192 +
1193 +/**
1194 + * add_to_cached_caps - add a capability to the tasks logged capabilities cache
1195 + * @cap: the capability to add
1196 + */
1197 +static inline void add_to_cached_caps(int cap)
1198 +{
1199 +       struct subdomain *sd = AA_SUBDOMAIN(current->security);
1200 +       sd->cached_caps = cap_combine(sd->cached_caps, CAP_TO_MASK(cap));
1201 +}
1202 +
1203 +/**
1204 + * clear_cached_caps - clear the tasks logged capabilities cache
1205 + */
1206 +static inline void clear_cached_caps(struct subdomain *sd)
1207 +{
1208 +       sd->cached_caps = CAP_EMPTY_SET;
1209 +}
1210 +
1211 +/**
1212 + * syscall_is_cached - check if @call access has already been logged
1213 + * @call: syscall to test if cached
1214 + */
1215 +static inline int syscall_is_cached(enum aasyscall call)
1216 +{
1217 +       struct subdomain *sd = AA_SUBDOMAIN(current->security);
1218 +       return sd->cached_syscalls & AA_SYSCALL_TO_MASK(call);
1219 +}
1220 +
1221 +/**
1222 + * add_to_cached_syscalls - add a syscall to the tasks logged syscalls cache
1223 + * @call: the syscall to add
1224 + */
1225 +static inline void add_to_cached_syscalls(enum aasyscall call)
1226 +{
1227 +       struct subdomain *sd = AA_SUBDOMAIN(current->security);
1228 +       sd->cached_syscalls |= AA_SYSCALL_TO_MASK(call);
1229 +}
1230 +
1231 +/**
1232 + * clear_cached_syscalls - clear the tasks logged syscalls cache
1233 + */
1234 +static inline void clear_cached_syscalls(struct subdomain *sd)
1235 +{
1236 +       sd->cached_syscalls = 0;
1237 +}
1238 +
1239 +/**
1240 + * aa_switch - change subdomain to use a new profile
1241 + * @sd: subdomain to switch the active profile on
1242 + * @newactive: new active profile
1243 + *
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
1250 + */
1251 +static inline void aa_switch(struct subdomain *sd, struct aaprofile *newactive)
1252 +{
1253 +       struct aaprofile *oldactive = sd->active;
1254 +
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);
1260 +}
1261 +
1262 +/**
1263 + * aa_switch_unconfined - change subdomain to be unconfined (no profile)
1264 + * @sd: subdomain to switch
1265 + *
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.
1269 + */
1270 +static inline void aa_switch_unconfined(struct subdomain *sd)
1271 +{
1272 +       aa_switch(sd, NULL);
1273 +
1274 +       /* reset magic in case we were in a subhat before */
1275 +       sd->hat_magic = 0;
1276 +}
1277 +
1278 +/**
1279 + * alloc_subdomain - allocate a new subdomain
1280 + * @tsk: task struct
1281 + *
1282 + * Allocate a new subdomain including a backpointer to it's referring task.
1283 + */
1284 +static inline struct subdomain *alloc_subdomain(struct task_struct *tsk)
1285 +{
1286 +       struct subdomain *sd;
1287 +
1288 +       sd = kzalloc(sizeof(struct subdomain), GFP_KERNEL);
1289 +       if (!sd)
1290 +               goto out;
1291 +
1292 +       /* back pointer to task */
1293 +       sd->task = tsk;
1294 +
1295 +       /* any readers of the list must make sure that they can handle
1296 +        * case where sd->active is not yet set (null)
1297 +        */
1298 +       aa_subdomainlist_add(sd);
1299 +
1300 +out:
1301 +       return sd;
1302 +}
1303 +
1304 +/**
1305 + * free_subdomain - Free a subdomain previously allocated by alloc_subdomain
1306 + * @sd: subdomain
1307 + */
1308 +static inline void free_subdomain(struct subdomain *sd)
1309 +{
1310 +       aa_subdomainlist_remove(sd);
1311 +       kfree(sd);
1312 +}
1313 +
1314 +/**
1315 + * alloc_aaprofile - Allocate, initialize and return a new zeroed profile.
1316 + * Returns NULL on failure.
1317 + */
1318 +static inline struct aaprofile *alloc_aaprofile(void)
1319 +{
1320 +       struct aaprofile *profile;
1321 +
1322 +       profile = (struct aaprofile *)kzalloc(sizeof(struct aaprofile),
1323 +                                             GFP_KERNEL);
1324 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
1325 +       if (profile) {
1326 +               int i;
1327 +
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]);
1333 +               }
1334 +               INIT_RCU_HEAD(&profile->rcu);
1335 +               kref_init(&profile->count);
1336 +       }
1337 +       return profile;
1338 +}
1339 +
1340 +/**
1341 + * aa_put_name
1342 + * @name: name to release.
1343 + *
1344 + * Release space (free_page) allocated to hold pathname
1345 + * name may be NULL (checked for by free_page)
1346 + */
1347 +static inline void aa_put_name(const char *name)
1348 +{
1349 +       free_page((unsigned long)name);
1350 +}
1351 +
1352 +/** __aa_find_profile
1353 + * @name: name of profile to find
1354 + * @head: list to search
1355 + *
1356 + * Return reference counted copy of profile. NULL if not found
1357 + * Caller must hold any necessary locks
1358 + */
1359 +static inline struct aaprofile *__aa_find_profile(const char *name,
1360 +                                                 struct list_head *head)
1361 +{
1362 +       struct aaprofile *p;
1363 +
1364 +       if (!name || !head)
1365 +               return NULL;
1366 +
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);
1372 +                       return p;
1373 +               } else {
1374 +                       AA_DEBUG("%s: skipping %s\n", __FUNCTION__, p->name);
1375 +               }
1376 +       }
1377 +       return NULL;
1378 +}
1379 +
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)
1383 + *
1384 + * Setup data for iterating over vfsmounts (in current tasks namespace).
1385 + */
1386 +static inline void __aa_path_begin(struct dentry *rdentry,
1387 +                                  struct dentry *dentry,
1388 +                                  struct aa_path_data *data)
1389 +{
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);
1396 +       data->errno = 0;
1397 +
1398 +       down_read(&namespace_sem);
1399 +}
1400 +
1401 +/** aa_path_begin
1402 + * @dentry: filesystem root dentry and object to obtain pathname from
1403 + *
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).
1406 + */
1407 +static inline void aa_path_begin(struct dentry *dentry,
1408 +                                    struct aa_path_data *data)
1409 +{
1410 +       __aa_path_begin(dentry, dentry, data);
1411 +}
1412 +
1413 +/** aa_path_end
1414 + * @data: data object previously initialized by aa_path_begin
1415 + *
1416 + * End iterating over vfsmounts.
1417 + * If an error occured in begin or get, it is returned. Otherwise 0.
1418 + */
1419 +static inline int aa_path_end(struct aa_path_data *data)
1420 +{
1421 +       up_read(&namespace_sem);
1422 +       dput(data->root);
1423 +
1424 +       return data->errno;
1425 +}
1426 +
1427 +/** aa_path_getname
1428 + * @data: data object previously initialized by aa_path_begin
1429 + *
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)
1433 + */
1434 +static inline char *aa_path_getname(struct aa_path_data *data)
1435 +{
1436 +       char *name = NULL;
1437 +       struct vfsmount *mnt;
1438 +
1439 +       while (data->pos != data->head) {
1440 +               mnt = list_entry(data->pos, struct vfsmount, mnt_list);
1441 +
1442 +               /* advance to next -- so that it is done before we break */
1443 +               data->pos = data->pos->next;
1444 +               prefetch(data->pos->next);
1445 +
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);
1450 +                               name = NULL;
1451 +                       }
1452 +                       break;
1453 +               }
1454 +       }
1455 +
1456 +       return name;
1457 +}
1458 +
1459 +#endif /* __INLINE_H__ */
1460 Index: b/security/apparmor/list.c
1461 ===================================================================
1462 --- /dev/null
1463 +++ b/security/apparmor/list.c
1464 @@ -0,0 +1,268 @@
1465 +/*
1466 + *     Copyright (C) 1998-2005 Novell/SUSE
1467 + *
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
1471 + *     License.
1472 + *
1473 + *     AppArmor Profile List Management
1474 + */
1475 +
1476 +#include <linux/seq_file.h>
1477 +#include "apparmor.h"
1478 +#include "inline.h"
1479 +
1480 +/* list of all profiles and lock */
1481 +static LIST_HEAD(profile_list);
1482 +static rwlock_t profile_lock = RW_LOCK_UNLOCKED;
1483 +
1484 +/* list of all subdomains and lock */
1485 +static LIST_HEAD(subdomain_list);
1486 +static rwlock_t subdomain_lock = RW_LOCK_UNLOCKED;
1487 +
1488 +/**
1489 + * aa_profilelist_find
1490 + * @name: profile name (program name)
1491 + *
1492 + * Search the profile list for profile @name.  Return refcounted profile on
1493 + * success, NULL on failure.
1494 + */
1495 +struct aaprofile *aa_profilelist_find(const char *name)
1496 +{
1497 +       struct aaprofile *p = NULL;
1498 +       if (name) {
1499 +               read_lock(&profile_lock);
1500 +               p = __aa_find_profile(name, &profile_list);
1501 +               read_unlock(&profile_lock);
1502 +       }
1503 +       return p;
1504 +}
1505 +
1506 +/**
1507 + * aa_profilelist_add - add new profile to list
1508 + * @profile: new profile to add to list
1509 + *
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.
1513 + *
1514 + * Return %1 on success, %0 on failure (already exists)
1515 + */
1516 +int aa_profilelist_add(struct aaprofile *profile)
1517 +{
1518 +       struct aaprofile *old_profile;
1519 +       int ret = 0;
1520 +
1521 +       if (!profile)
1522 +               goto out;
1523 +
1524 +       write_lock(&profile_lock);
1525 +       old_profile = __aa_find_profile(profile->name, &profile_list);
1526 +       if (old_profile) {
1527 +               put_aaprofile(old_profile);
1528 +               goto out;
1529 +       }
1530 +
1531 +       list_add(&profile->list, &profile_list);
1532 +       ret = 1;
1533 + out:
1534 +       write_unlock(&profile_lock);
1535 +       return ret;
1536 +}
1537 +
1538 +/**
1539 + * aa_profilelist_remove - remove a profile from the list by name
1540 + * @name: name of profile to be removed
1541 + *
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
1545 + */
1546 +struct aaprofile *aa_profilelist_remove(const char *name)
1547 +{
1548 +       struct aaprofile *profile = NULL;
1549 +       struct aaprofile *p, *tmp;
1550 +
1551 +       if (!name)
1552 +               goto out;
1553 +
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 */
1559 +                       p->isstale = 1;
1560 +                       profile = p;
1561 +                       break;
1562 +               }
1563 +       }
1564 +       write_unlock(&profile_lock);
1565 +
1566 +out:
1567 +       return profile;
1568 +}
1569 +
1570 +/**
1571 + * aa_profilelist_replace - replace a profile on the list
1572 + * @profile: new profile
1573 + *
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().
1577 + *
1578 + * This is an atomic list operation.  Returns the old profile (which is still
1579 + * refcounted) if there was one, or NULL.
1580 + */
1581 +struct aaprofile *aa_profilelist_replace(struct aaprofile *profile)
1582 +{
1583 +       struct aaprofile *oldprofile;
1584 +
1585 +       write_lock(&profile_lock);
1586 +       oldprofile = __aa_find_profile(profile->name, &profile_list);
1587 +       if (oldprofile) {
1588 +               list_del_init(&oldprofile->list);
1589 +               /* mark old profile as stale */
1590 +               oldprofile->isstale = 1;
1591 +
1592 +               /* __aa_find_profile incremented count, so adjust down */
1593 +               put_aaprofile(oldprofile);
1594 +       }
1595 +
1596 +       list_add(&profile->list, &profile_list);
1597 +       write_unlock(&profile_lock);
1598 +
1599 +       return oldprofile;
1600 +}
1601 +
1602 +/**
1603 + * aa_profilelist_release - Remove all profiles from profile_list
1604 + */
1605 +void aa_profilelist_release(void)
1606 +{
1607 +       struct aaprofile *p, *tmp;
1608 +
1609 +       write_lock(&profile_lock);
1610 +       list_for_each_entry_safe(p, tmp, &profile_list, list) {
1611 +               list_del_init(&p->list);
1612 +               put_aaprofile(p);
1613 +       }
1614 +       write_unlock(&profile_lock);
1615 +}
1616 +
1617 +/**
1618 + * aa_subdomainlist_add - Add subdomain to subdomain_list
1619 + * @sd: new subdomain
1620 + */
1621 +void aa_subdomainlist_add(struct subdomain *sd)
1622 +{
1623 +       unsigned long flags;
1624 +
1625 +       if (!sd) {
1626 +               AA_INFO("%s: bad subdomain\n", __FUNCTION__);
1627 +               return;
1628 +       }
1629 +
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.
1633 +        */
1634 +       list_add_tail(&sd->list, &subdomain_list);
1635 +       write_unlock_irqrestore(&subdomain_lock, flags);
1636 +}
1637 +
1638 +/**
1639 + * aa_subdomainlist_remove - Remove subdomain from subdomain_list
1640 + * @sd: subdomain to be removed
1641 + */
1642 +void aa_subdomainlist_remove(struct subdomain *sd)
1643 +{
1644 +       unsigned long flags;
1645 +
1646 +       if (sd) {
1647 +               write_lock_irqsave(&subdomain_lock, flags);
1648 +               list_del_init(&sd->list);
1649 +               write_unlock_irqrestore(&subdomain_lock, flags);
1650 +       }
1651 +}
1652 +
1653 +/**
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
1657 + *
1658 + * Iterate over subdomain list applying @func, stop when @func returns
1659 + * non zero
1660 + */
1661 +void aa_subdomainlist_iterate(aa_iter func, void *cookie)
1662 +{
1663 +       struct subdomain *node;
1664 +       int ret = 0;
1665 +       unsigned long flags;
1666 +
1667 +       read_lock_irqsave(&subdomain_lock, flags);
1668 +       list_for_each_entry(node, &subdomain_list, list) {
1669 +               ret = (*func) (node, cookie);
1670 +               if (ret != 0)
1671 +                       break;
1672 +       }
1673 +       read_unlock_irqrestore(&subdomain_lock, flags);
1674 +}
1675 +
1676 +/**
1677 + * aa_subdomainlist_release - Remove all subdomains from subdomain_list
1678 + */
1679 +void aa_subdomainlist_release(void)
1680 +{
1681 +       struct subdomain *node, *tmp;
1682 +       unsigned long flags;
1683 +
1684 +       write_lock_irqsave(&subdomain_lock, flags);
1685 +       list_for_each_entry_safe(node, tmp, &subdomain_list, list) {
1686 +               list_del_init(&node->list);
1687 +       }
1688 +       write_unlock_irqrestore(&subdomain_lock, flags);
1689 +}
1690 +
1691 +/* seq_file helper routines
1692 + * Used by apparmorfs.c to iterate over profile_list
1693 + */
1694 +static void *p_start(struct seq_file *f, loff_t *pos)
1695 +{
1696 +       struct aaprofile *node;
1697 +       loff_t l = *pos;
1698 +
1699 +       read_lock(&profile_lock);
1700 +       list_for_each_entry(node, &profile_list, list)
1701 +               if (!l--)
1702 +                       return node;
1703 +       return NULL;
1704 +}
1705 +
1706 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
1707 +{
1708 +       struct list_head *lh = ((struct aaprofile *)p)->list.next;
1709 +       (*pos)++;
1710 +       return lh == &profile_list ?
1711 +                       NULL : list_entry(lh, struct aaprofile, list);
1712 +}
1713 +
1714 +static void p_stop(struct seq_file *f, void *v)
1715 +{
1716 +       read_unlock(&profile_lock);
1717 +}
1718 +
1719 +static int seq_show_profile(struct seq_file *f, void *v)
1720 +{
1721 +       struct aaprofile *profile = (struct aaprofile *)v;
1722 +       seq_printf(f, "%s (%s)\n", profile->name,
1723 +                  PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
1724 +       return 0;
1725 +}
1726 +
1727 +struct seq_operations apparmorfs_profiles_op = {
1728 +       .start =        p_start,
1729 +       .next =         p_next,
1730 +       .stop =         p_stop,
1731 +       .show =         seq_show_profile,
1732 +};
1733 Index: b/security/apparmor/lsm.c
1734 ===================================================================
1735 --- /dev/null
1736 +++ b/security/apparmor/lsm.c
1737 @@ -0,0 +1,894 @@
1738 +/*
1739 + *     Copyright (C) 2002-2005 Novell/SUSE
1740 + *
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
1744 + *     License.
1745 + *
1746 + *     http://forge.novell.com/modules/xfmod/project/?apparmor
1747 + *
1748 + *     Immunix AppArmor LSM interface
1749 + */
1750 +
1751 +#include <linux/security.h>
1752 +#include <linux/module.h>
1753 +#include <linux/mm.h>
1754 +#include <linux/mman.h>
1755 +
1756 +#include "apparmor.h"
1757 +#include "inline.h"
1758 +
1759 +/* struct subdomain write update lock (read side is RCU). */
1760 +spinlock_t sd_lock = SPIN_LOCK_UNLOCKED;
1761 +
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. */
1766 +
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
1771 + * enforce.
1772 + */
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");
1776 +
1777 +/* Debug 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");
1781 +
1782 +/* Audit 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");
1786 +
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");
1791 +
1792 +#ifndef MODULE
1793 +static int __init aa_getopt_complain(char *str)
1794 +{
1795 +       get_option(&str, &apparmor_complain);
1796 +       return 1;
1797 +}
1798 +__setup("apparmor_complain=", aa_getopt_complain);
1799 +
1800 +static int __init aa_getopt_debug(char *str)
1801 +{
1802 +       get_option(&str, &apparmor_debug);
1803 +       return 1;
1804 +}
1805 +__setup("apparmor_debug=", aa_getopt_debug);
1806 +
1807 +static int __init aa_getopt_audit(char *str)
1808 +{
1809 +       get_option(&str, &apparmor_audit);
1810 +       return 1;
1811 +}
1812 +__setup("apparmor_audit=", aa_getopt_audit);
1813 +
1814 +static int __init aa_getopt_logsyscall(char *str)
1815 +{
1816 +       get_option(&str, &apparmor_logsyscall);
1817 +       return 1;
1818 +}
1819 +__setup("apparmor_logsyscall=", aa_getopt_logsyscall);
1820 +#endif
1821 +
1822 +static int apparmor_ptrace(struct task_struct *parent,
1823 +                           struct task_struct *child)
1824 +{
1825 +       int error;
1826 +       struct aaprofile *active;
1827 +
1828 +       error = cap_ptrace(parent, child);
1829 +
1830 +       active = get_task_active_aaprofile(parent);
1831 +
1832 +       if (!error && active)
1833 +               error = aa_audit_syscallreject(active, GFP_ATOMIC,
1834 +                                              AA_SYSCALL_PTRACE);
1835 +
1836 +       put_aaprofile(active);
1837 +
1838 +       return error;
1839 +}
1840 +
1841 +static int apparmor_capget(struct task_struct *target,
1842 +                           kernel_cap_t *effective,
1843 +                           kernel_cap_t *inheritable,
1844 +                           kernel_cap_t *permitted)
1845 +{
1846 +       return cap_capget(target, effective, inheritable, permitted);
1847 +}
1848 +
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)
1853 +{
1854 +       return cap_capset_check(target, effective, inheritable, permitted);
1855 +}
1856 +
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)
1861 +{
1862 +       cap_capset_set(target, effective, inheritable, permitted);
1863 +       return;
1864 +}
1865 +
1866 +static int apparmor_capable(struct task_struct *tsk, int cap)
1867 +{
1868 +       int error;
1869 +
1870 +       /* cap_capable returns 0 on success, else -EPERM */
1871 +       error = cap_capable(tsk, cap);
1872 +
1873 +       if (error == 0) {
1874 +               struct aaprofile *active;
1875 +
1876 +               active = get_task_active_aaprofile(tsk);
1877 +
1878 +               if (active)
1879 +                       error = aa_capability(active, cap);
1880 +
1881 +               put_aaprofile(active);
1882 +       }
1883 +
1884 +       return error;
1885 +}
1886 +
1887 +static int apparmor_sysctl(struct ctl_table *table, int op)
1888 +{
1889 +       int error = 0;
1890 +       struct aaprofile *active;
1891 +
1892 +       active = get_active_aaprofile();
1893 +
1894 +       if ((op & 002) && active && !capable(CAP_SYS_ADMIN))
1895 +               error = aa_audit_syscallreject(active, GFP_ATOMIC,
1896 +                                              AA_SYSCALL_SYSCTL_WRITE);
1897 +
1898 +       put_aaprofile(active);
1899 +
1900 +       return error;
1901 +}
1902 +
1903 +static int apparmor_syslog(int type)
1904 +{
1905 +       return cap_syslog(type);
1906 +}
1907 +
1908 +static int apparmor_netlink_send(struct sock *sk, struct sk_buff *skb)
1909 +{
1910 +       return cap_netlink_send(sk, skb);
1911 +}
1912 +
1913 +static int apparmor_netlink_recv(struct sk_buff *skb, int cap)
1914 +{
1915 +       return cap_netlink_recv(skb, cap);
1916 +}
1917 +
1918 +static void apparmor_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
1919 +{
1920 +       cap_bprm_apply_creds(bprm, unsafe);
1921 +       return;
1922 +}
1923 +
1924 +static int apparmor_bprm_set_security(struct linux_binprm *bprm)
1925 +{
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)
1930 +               return 0;
1931 +       return aa_register(bprm);
1932 +}
1933 +
1934 +static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
1935 +{
1936 +       int ret = cap_bprm_secureexec(bprm);
1937 +
1938 +       if (ret == 0 &&
1939 +           (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
1940 +               AA_DEBUG("%s: secureexec required for %s\n",
1941 +                        __FUNCTION__, bprm->filename);
1942 +               ret = 1;
1943 +       }
1944 +
1945 +       return ret;
1946 +}
1947 +
1948 +static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
1949 +                             unsigned long flags, void *data)
1950 +{
1951 +       int error = 0;
1952 +       struct aaprofile *active;
1953 +
1954 +       active = get_active_aaprofile();
1955 +
1956 +       if (active)
1957 +               error = aa_audit_syscallreject(active, GFP_ATOMIC,
1958 +                                              AA_SYSCALL_MOUNT);
1959 +
1960 +       put_aaprofile(active);
1961 +
1962 +       return error;
1963 +}
1964 +
1965 +static int apparmor_umount(struct vfsmount *mnt, int flags)
1966 +{
1967 +       int error = 0;
1968 +       struct aaprofile *active;
1969 +
1970 +       active = get_active_aaprofile();
1971 +
1972 +       if (active)
1973 +               error = aa_audit_syscallreject(active, GFP_ATOMIC,
1974 +                                              AA_SYSCALL_UMOUNT);
1975 +
1976 +       put_aaprofile(active);
1977 +
1978 +       return error;
1979 +}
1980 +
1981 +static int apparmor_inode_mkdir(struct inode *inode, struct dentry *dentry,
1982 +                                int mask)
1983 +{
1984 +       struct aaprofile *active;
1985 +       int error = 0;
1986 +
1987 +       active = get_active_aaprofile();
1988 +
1989 +       if (active)
1990 +               error = aa_perm_dir(active, dentry, aa_dir_mkdir);
1991 +
1992 +       put_aaprofile(active);
1993 +
1994 +       return error;
1995 +}
1996 +
1997 +static int apparmor_inode_rmdir(struct inode *inode, struct dentry *dentry)
1998 +{
1999 +       struct aaprofile *active;
2000 +       int error = 0;
2001 +
2002 +       active = get_active_aaprofile();
2003 +
2004 +       if (active)
2005 +               error = aa_perm_dir(active, dentry, aa_dir_rmdir);
2006 +
2007 +       put_aaprofile(active);
2008 +
2009 +       return error;
2010 +}
2011 +
2012 +static int apparmor_inode_create(struct inode *inode, struct dentry *dentry,
2013 +                                 int mask)
2014 +{
2015 +       struct aaprofile *active;
2016 +       int error = 0;
2017 +
2018 +       active = get_active_aaprofile();
2019 +
2020 +       /* At a minimum, need write perm to create */
2021 +       if (active)
2022 +               error = aa_perm_dentry(active, dentry, MAY_WRITE);
2023 +
2024 +       put_aaprofile(active);
2025 +
2026 +       return error;
2027 +}
2028 +
2029 +static int apparmor_inode_link(struct dentry *old_dentry, struct inode *inode,
2030 +                               struct dentry *new_dentry)
2031 +{
2032 +       int error = 0;
2033 +       struct aaprofile *active;
2034 +
2035 +       active = get_active_aaprofile();
2036 +
2037 +       if (active)
2038 +               error = aa_link(active, new_dentry, old_dentry);
2039 +
2040 +       put_aaprofile(active);
2041 +
2042 +       return error;
2043 +}
2044 +
2045 +static int apparmor_inode_unlink(struct inode *inode, struct dentry *dentry)
2046 +{
2047 +       struct aaprofile *active;
2048 +       int error = 0;
2049 +
2050 +       active = get_active_aaprofile();
2051 +
2052 +       if (active)
2053 +               error = aa_perm_dentry(active, dentry, MAY_WRITE);
2054 +
2055 +       put_aaprofile(active);
2056 +
2057 +       return error;
2058 +}
2059 +
2060 +static int apparmor_inode_mknod(struct inode *inode, struct dentry *dentry,
2061 +                                int mode, dev_t dev)
2062 +{
2063 +       struct aaprofile *active;
2064 +       int error = 0;
2065 +
2066 +       active = get_active_aaprofile();
2067 +
2068 +       if (active)
2069 +               error = aa_perm_dentry(active, dentry, MAY_WRITE);
2070 +
2071 +       put_aaprofile(active);
2072 +
2073 +       return error;
2074 +}
2075 +
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)
2080 +{
2081 +       struct aaprofile *active;
2082 +       int error = 0;
2083 +
2084 +       active = get_active_aaprofile();
2085 +
2086 +       if (active) {
2087 +               error = aa_perm_dentry(active, old_dentry, MAY_READ |
2088 +                                      MAY_WRITE);
2089 +
2090 +               if (!error)
2091 +                       error = aa_perm_dentry(active, new_dentry,
2092 +                                              MAY_WRITE);
2093 +       }
2094 +
2095 +       put_aaprofile(active);
2096 +
2097 +       return error;
2098 +}
2099 +
2100 +static int apparmor_inode_permission(struct inode *inode, int mask,
2101 +                                     struct nameidata *nd)
2102 +{
2103 +       int error = 0;
2104 +
2105 +       /* Do not perform check on pipes or sockets
2106 +        * Same as apparmor_file_permission
2107 +        */
2108 +       if (VALID_FSTYPE(inode)) {
2109 +               struct aaprofile *active;
2110 +
2111 +               active = get_active_aaprofile();
2112 +               if (active)
2113 +                       error = aa_perm_nameidata(active, nd, mask);
2114 +               put_aaprofile(active);
2115 +       }
2116 +
2117 +       return error;
2118 +}
2119 +
2120 +static int apparmor_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2121 +{
2122 +       int error = 0;
2123 +
2124 +       if (VALID_FSTYPE(dentry->d_inode)) {
2125 +               struct aaprofile *active;
2126 +
2127 +               active = get_active_aaprofile();
2128 +               /*
2129 +                * Mediate any attempt to change attributes of a file
2130 +                * (chmod, chown, chgrp, etc)
2131 +                */
2132 +               if (active)
2133 +                       error = aa_attr(active, dentry, iattr);
2134 +
2135 +               put_aaprofile(active);
2136 +       }
2137 +
2138 +       return error;
2139 +}
2140 +
2141 +static int apparmor_inode_setxattr(struct dentry *dentry, char *name,
2142 +                                   void *value, size_t size, int flags)
2143 +{
2144 +       int error = 0;
2145 +
2146 +       if (VALID_FSTYPE(dentry->d_inode)) {
2147 +               struct aaprofile *active;
2148 +
2149 +               active = get_active_aaprofile();
2150 +               if (active)
2151 +                       error = aa_xattr(active, dentry, name, aa_xattr_set);
2152 +               put_aaprofile(active);
2153 +       }
2154 +
2155 +       return error;
2156 +}
2157 +
2158 +static int apparmor_inode_getxattr(struct dentry *dentry, char *name)
2159 +{
2160 +       int error = 0;
2161 +
2162 +       if (VALID_FSTYPE(dentry->d_inode)) {
2163 +               struct aaprofile *active;
2164 +
2165 +               active = get_active_aaprofile();
2166 +               if (active)
2167 +                       error = aa_xattr(active, dentry, name, aa_xattr_get);
2168 +               put_aaprofile(active);
2169 +       }
2170 +
2171 +       return error;
2172 +}
2173 +static int apparmor_inode_listxattr(struct dentry *dentry)
2174 +{
2175 +       int error = 0;
2176 +
2177 +       if (VALID_FSTYPE(dentry->d_inode)) {
2178 +               struct aaprofile *active;
2179 +
2180 +               active = get_active_aaprofile();
2181 +               if (active)
2182 +                       error = aa_xattr(active, dentry, NULL, aa_xattr_list);
2183 +               put_aaprofile(active);
2184 +       }
2185 +
2186 +       return error;
2187 +}
2188 +
2189 +static int apparmor_inode_removexattr(struct dentry *dentry, char *name)
2190 +{
2191 +       int error = 0;
2192 +
2193 +       if (VALID_FSTYPE(dentry->d_inode)) {
2194 +               struct aaprofile *active;
2195 +
2196 +               active = get_active_aaprofile();
2197 +               if (active)
2198 +                       error = aa_xattr(active, dentry, name,
2199 +                                        aa_xattr_remove);
2200 +               put_aaprofile(active);
2201 +       }
2202 +
2203 +       return error;
2204 +}
2205 +
2206 +static int apparmor_file_permission(struct file *file, int mask)
2207 +{
2208 +       struct aaprofile *active;
2209 +       struct aafile *aaf;
2210 +       int error = 0;
2211 +
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))
2215 +               goto out;
2216 +
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);
2222 +
2223 +out:
2224 +       return error;
2225 +}
2226 +
2227 +static int apparmor_file_alloc_security(struct file *file)
2228 +{
2229 +       struct aaprofile *active;
2230 +       int error = 0;
2231 +
2232 +       active = get_active_aaprofile();
2233 +       if (active) {
2234 +               struct aafile *aaf;
2235 +               aaf = kmalloc(sizeof(struct aafile), GFP_KERNEL);
2236 +
2237 +               if (aaf) {
2238 +                       aaf->type = aa_file_default;
2239 +                       aaf->profile = get_aaprofile(active);
2240 +               } else {
2241 +                       error = -ENOMEM;
2242 +               }
2243 +               file->f_security = aaf;
2244 +       }
2245 +       put_aaprofile(active);
2246 +
2247 +       return error;
2248 +}
2249 +
2250 +static void apparmor_file_free_security(struct file *file)
2251 +{
2252 +       struct aafile *aaf = (struct aafile *)file->f_security;
2253 +
2254 +       if (aaf) {
2255 +               put_aaprofile(aaf->profile);
2256 +               kfree(aaf);
2257 +       }
2258 +}
2259 +
2260 +static inline int aa_mmap(struct file *file, unsigned long prot,
2261 +                         unsigned long flags)
2262 +{
2263 +       int error = 0, mask = 0;
2264 +       struct aaprofile *active;
2265 +       struct aafile *aaf;
2266 +
2267 +       active = get_active_aaprofile();
2268 +       if (!active || !file ||
2269 +           !(aaf = (struct aafile *)file->f_security) ||
2270 +           aaf->type == aa_file_shmem)
2271 +               goto out;
2272 +
2273 +       if (prot & PROT_READ)
2274 +               mask |= MAY_READ;
2275 +
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;
2282 +
2283 +       AA_DEBUG("%s: 0x%x\n", __FUNCTION__, mask);
2284 +
2285 +       if (mask)
2286 +               error = aa_perm(active, file->f_dentry, file->f_vfsmnt, mask);
2287 +
2288 +       put_aaprofile(active);
2289 +
2290 +out:
2291 +       return error;
2292 +}
2293 +
2294 +static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
2295 +                              unsigned long prot, unsigned long flags)
2296 +{
2297 +       return aa_mmap(file, prot, flags);
2298 +}
2299 +
2300 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
2301 +                                 unsigned long reqprot, unsigned long prot)
2302 +{
2303 +       return aa_mmap(vma->vm_file, prot,
2304 +                      !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
2305 +}
2306 +
2307 +static int apparmor_task_alloc_security(struct task_struct *p)
2308 +{
2309 +       return aa_fork(p);
2310 +}
2311 +
2312 +static void apparmor_task_free_security(struct task_struct *p)
2313 +{
2314 +       aa_release(p);
2315 +}
2316 +
2317 +static int apparmor_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
2318 +                                    int flags)
2319 +{
2320 +       return cap_task_post_setuid(id0, id1, id2, flags);
2321 +}
2322 +
2323 +static void apparmor_task_reparent_to_init(struct task_struct *p)
2324 +{
2325 +       cap_task_reparent_to_init(p);
2326 +       return;
2327 +}
2328 +
2329 +static int apparmor_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
2330 +                             int shmflg)
2331 +{
2332 +       struct aafile *aaf = (struct aafile *)shp->shm_file->f_security;
2333 +
2334 +       if (aaf)
2335 +               aaf->type = aa_file_shmem;
2336 +
2337 +       return 0;
2338 +}
2339 +
2340 +static int apparmor_getprocattr(struct task_struct *p, char *name, void *value,
2341 +                               size_t size)
2342 +{
2343 +       int error;
2344 +       struct aaprofile *active;
2345 +       char *str = value;
2346 +
2347 +       /* AppArmor only supports the "current" process attribute */
2348 +       if (strcmp(name, "current") != 0) {
2349 +               error = -EINVAL;
2350 +               goto out;
2351 +       }
2352 +
2353 +       /* must be task querying itself or admin */
2354 +       if (current != p && !capable(CAP_SYS_ADMIN)) {
2355 +               error = -EPERM;
2356 +               goto out;
2357 +       }
2358 +
2359 +       active = get_task_active_aaprofile(p);
2360 +       error = aa_getprocattr(active, str, size);
2361 +       put_aaprofile(active);
2362 +
2363 +out:
2364 +       return error;
2365 +}
2366 +
2367 +static int apparmor_setprocattr(struct task_struct *p, char *name, void *value,
2368 +                                size_t size)
2369 +{
2370 +       const char *cmd_changehat = "changehat ",
2371 +                  *cmd_setprofile = "setprofile ";
2372 +
2373 +       int error = -EACCES;    /* default to a perm denied */
2374 +       char *cmd = (char *)value;
2375 +
2376 +       /* only support messages to current */
2377 +       if (strcmp(name, "current") != 0) {
2378 +               error = -EINVAL;
2379 +               goto out;
2380 +       }
2381 +
2382 +       if (!size) {
2383 +               error = -ERANGE;
2384 +               goto out;
2385 +       }
2386 +
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);
2392 +
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",
2397 +                               __FUNCTION__,
2398 +                               current->comm,
2399 +                               current->pid,
2400 +                               current->uid,
2401 +                               p->comm,
2402 +                               p->pid);
2403 +
2404 +                       error = -EACCES;
2405 +                       goto out;
2406 +               }
2407 +
2408 +               error = aa_setprocattr_changehat(hatinfo, infosize);
2409 +               if (error == 0)
2410 +                       /* success, set return to #bytes in orig request */
2411 +                       error = size;
2412 +
2413 +       /* SET NEW PROFILE */
2414 +       } else if (size > strlen(cmd_setprofile) &&
2415 +                  strncmp(cmd, cmd_setprofile, strlen(cmd_setprofile)) == 0) {
2416 +               struct aaprofile *active;
2417 +
2418 +               /* only an unconfined process with admin capabilities
2419 +                * may change the profile of another task
2420 +                */
2421 +
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",
2425 +                               __FUNCTION__,
2426 +                               current->comm,
2427 +                               current->pid,
2428 +                               current->uid,
2429 +                               p->comm,
2430 +                               p->pid);
2431 +                       error = -EACCES;
2432 +                       goto out;
2433 +               }
2434 +
2435 +               active = get_active_aaprofile();
2436 +               if (!active) {
2437 +                       char *profile = cmd + strlen(cmd_setprofile);
2438 +                       size_t profilesize = size - strlen(cmd_setprofile);
2439 +
2440 +                       error = aa_setprocattr_setprofile(p, profile, profilesize);
2441 +                       if (error == 0)
2442 +                               /* success,
2443 +                                * set return to #bytes in orig request
2444 +                                */
2445 +                               error = size;
2446 +               } else {
2447 +                       AA_WARN("%s: Attempt by confined task %s(%d) "
2448 +                               "[user %d] to assign profile to task %s(%d)\n",
2449 +                               __FUNCTION__,
2450 +                               current->comm,
2451 +                               current->pid,
2452 +                               current->uid,
2453 +                               p->comm,
2454 +                               p->pid);
2455 +
2456 +                       error = -EACCES;
2457 +               }
2458 +               put_aaprofile(active);
2459 +       } else {
2460 +               /* unknown operation */
2461 +               AA_WARN("%s: Unknown setprocattr command '%.*s' by task %s(%d) "
2462 +                       "[user %d] for task %s(%d)\n",
2463 +                       __FUNCTION__,
2464 +                       size < 16 ? (int)size : 16,
2465 +                       cmd,
2466 +                       current->comm,
2467 +                       current->pid,
2468 +                       current->uid,
2469 +                       p->comm,
2470 +                       p->pid);
2471 +
2472 +               error = -EINVAL;
2473 +       }
2474 +
2475 +out:
2476 +       return error;
2477 +}
2478 +
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,
2487 +
2488 +       .netlink_send =                 apparmor_netlink_send,
2489 +       .netlink_recv =                 apparmor_netlink_recv,
2490 +
2491 +       .bprm_apply_creds =             apparmor_bprm_apply_creds,
2492 +       .bprm_set_security =            apparmor_bprm_set_security,
2493 +       .bprm_secureexec =              apparmor_bprm_secureexec,
2494 +
2495 +       .sb_mount =                     apparmor_sb_mount,
2496 +       .sb_umount =                    apparmor_umount,
2497 +
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,
2516 +
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,
2521 +
2522 +       .shm_shmat =                    apparmor_shm_shmat,
2523 +
2524 +       .getprocattr =                  apparmor_getprocattr,
2525 +       .setprocattr =                  apparmor_setprocattr,
2526 +};
2527 +
2528 +static int __init apparmor_init(void)
2529 +{
2530 +       int error;
2531 +       const char *complainmsg = ": complainmode enabled";
2532 +
2533 +       if ((error = create_apparmorfs())) {
2534 +               AA_ERROR("Unable to activate AppArmor filesystem\n");
2535 +               goto createfs_out;
2536 +       }
2537 +
2538 +       if ((error = alloc_null_complain_profile())){
2539 +               AA_ERROR("Unable to allocate null complain profile\n");
2540 +               goto alloc_out;
2541 +       }
2542 +
2543 +       if ((error = register_security(&apparmor_ops))) {
2544 +               AA_ERROR("Unable to load AppArmor\n");
2545 +               goto register_security_out;
2546 +       }
2547 +
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 : "");
2553 +
2554 +       return error;
2555 +
2556 +register_security_out:
2557 +       free_null_complain_profile();
2558 +
2559 +alloc_out:
2560 +       (void)destroy_apparmorfs();
2561 +
2562 +createfs_out:
2563 +       return error;
2564 +
2565 +}
2566 +
2567 +static int apparmor_exit_removeall_iter(struct subdomain *sd, void *cookie)
2568 +{
2569 +       /* spin_lock(&sd_lock) held here */
2570 +
2571 +       if (__aa_is_confined(sd)) {
2572 +               AA_DEBUG("%s: Dropping profiles %s(%d) "
2573 +                        "profile %s(%p) active %s(%p)\n",
2574 +                        __FUNCTION__,
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);
2580 +       }
2581 +
2582 +       return 0;
2583 +}
2584 +
2585 +static void __exit apparmor_exit(void)
2586 +{
2587 +       unsigned long flags;
2588 +
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)
2592 +        */
2593 +       aa_profilelist_release();
2594 +
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'
2598 +        * reattached
2599 +        */
2600 +
2601 +       spin_lock_irqsave(&sd_lock, flags);
2602 +       aa_subdomainlist_iterate(apparmor_exit_removeall_iter, NULL);
2603 +       spin_unlock_irqrestore(&sd_lock, flags);
2604 +
2605 +       /* Free up list of active subdomain */
2606 +       aa_subdomainlist_release();
2607 +
2608 +       free_null_complain_profile();
2609 +
2610 +       destroy_apparmorfs();
2611 +
2612 +       if (unregister_security(&apparmor_ops))
2613 +               AA_WARN("Unable to properly unregister AppArmor\n");
2614 +
2615 +       /* delay for an rcu cycle to make ensure that profiles pending
2616 +        * destruction in the rcu callback are freed.
2617 +        */
2618 +       synchronize_rcu();
2619 +
2620 +       AA_INFO("AppArmor protection removed\n");
2621 +       aa_audit_message(NULL, GFP_KERNEL, 0,
2622 +               "AppArmor protection removed\n");
2623 +}
2624 +
2625 +module_init(apparmor_init);
2626 +module_exit(apparmor_exit);
2627 +
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 ===================================================================
2634 --- /dev/null
2635 +++ b/security/apparmor/main.c
2636 @@ -0,0 +1,1702 @@
2637 +/*
2638 + *     Copyright (C) 2002-2005 Novell/SUSE
2639 + *
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
2643 + *     License.
2644 + *
2645 + *     AppArmor Core
2646 + */
2647 +
2648 +#include <linux/security.h>
2649 +#include <linux/namei.h>
2650 +#include <linux/audit.h>
2651 +
2652 +#include "apparmor.h"
2653 +#include "match/match.h"
2654 +
2655 +#include "inline.h"
2656 +
2657 +/* NULL complain profile
2658 + *
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
2662 + *
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
2665 + * unloaded
2666 + */
2667 +struct aaprofile *null_complain_profile;
2668 +
2669 +/***************************
2670 + * Private utility functions
2671 + **************************/
2672 +
2673 +/**
2674 + * dentry_xlate_error
2675 + * @dentry: pointer to dentry
2676 + * @error: error number
2677 + * @dtype: type of dentry
2678 + *
2679 + * Display error message when a dentry translation error occured
2680 + */
2681 +static void dentry_xlate_error(struct dentry *dentry, int error, char *dtype)
2682 +{
2683 +       const unsigned int len = 16;
2684 +       char buf[len];
2685 +
2686 +       if (dentry->d_inode) {
2687 +               snprintf(buf, len, "%lu", dentry->d_inode->i_ino);
2688 +       } else {
2689 +               strncpy(buf, "<negative>", len);
2690 +               buf[len-1]=0;
2691 +       }
2692 +
2693 +       AA_ERROR("An error occured while translating %s %p "
2694 +                "inode# %s to a pathname. Error %d\n",
2695 +                dtype,
2696 +                dentry,
2697 +                buf,
2698 +                error);
2699 +}
2700 +
2701 +/**
2702 + * aa_taskattr_access
2703 + * @procrelname: name of file to check permission
2704 + *
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.
2707 + */
2708 +static inline int aa_taskattr_access(const char *procrelname)
2709 +{
2710 +       char buf[sizeof("/attr/current") + 10];
2711 +       const int maxbuflen = sizeof(buf);
2712 +       /* assumption, 32bit pid (10 decimal digits incl \0) */
2713 +
2714 +       snprintf(buf, maxbuflen, "%d/attr/current", current->pid);
2715 +       buf[maxbuflen - 1] = 0;
2716 +
2717 +       return strcmp(buf, procrelname) == 0;
2718 +}
2719 +
2720 +/**
2721 + * aa_file_mode - get full mode for file entry from profile
2722 + * @profile: profile
2723 + * @name: filename
2724 + */
2725 +static inline int aa_file_mode(struct aaprofile *profile, const char *name)
2726 +{
2727 +       struct aa_entry *entry;
2728 +       int mode = 0;
2729 +
2730 +       AA_DEBUG("%s: %s\n", __FUNCTION__, name);
2731 +       if (!name) {
2732 +               AA_DEBUG("%s: no name\n", __FUNCTION__);
2733 +               goto out;
2734 +       }
2735 +
2736 +       if (!profile) {
2737 +               AA_DEBUG("%s: no profile\n", __FUNCTION__);
2738 +               goto out;
2739 +       }
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;
2744 +       }
2745 +out:
2746 +       return mode;
2747 +}
2748 +
2749 +/**
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
2763 + *
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}
2768 + *       else
2769 + *          *xmod = %AA_MAY_EXEC
2770 + *       unsafe = presence of unsage flag
2771 + */
2772 +static inline int aa_get_execmode(struct aaprofile *active, const char *name,
2773 +                                 int *xmod, int *unsafe)
2774 +{
2775 +       struct aa_entry *entry;
2776 +       struct aa_entry *match = NULL;
2777 +
2778 +       int pattern_match_invalid = 0, rc = 0;
2779 +
2780 +       /* search list of profiles with 'x' permission
2781 +        * this will also include entries with 'p', 'u' and 'i'
2782 +        * qualifiers.
2783 +        *
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
2787 +        * is returned.
2788 +        */
2789 +
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)) {
2796 +                       if (match &&
2797 +                           AA_EXEC_UNSAFE_MASK(entry->mode) !=
2798 +                           AA_EXEC_UNSAFE_MASK(match->mode))
2799 +                               pattern_match_invalid = 1;
2800 +                       else
2801 +                               /* keep searching for an exact match */
2802 +                               match = entry;
2803 +               } else if ((entry->type == aa_entry_literal ||
2804 +                           (!pattern_match_invalid &&
2805 +                            entry->type == aa_entry_tailglob)) &&
2806 +                           aamatch_match(name, entry->filename,
2807 +                                         entry->type,
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
2812 +                                */
2813 +                               match = entry;
2814 +                               pattern_match_invalid = 0;
2815 +                               break;
2816 +                       } else {
2817 +                               if (match &&
2818 +                                   AA_EXEC_UNSAFE_MASK(entry->mode) !=
2819 +                                   AA_EXEC_UNSAFE_MASK(match->mode))
2820 +                                       pattern_match_invalid = 1;
2821 +                               else
2822 +                                       /* got a tailglob match, keep searching
2823 +                                        * for an exact match
2824 +                                        */
2825 +                                       match = entry;
2826 +                       }
2827 +               }
2828 +
2829 +       }
2830 +
2831 +       rc = match && !pattern_match_invalid;
2832 +
2833 +       if (rc) {
2834 +               int mode = AA_EXEC_MASK(match->mode);
2835 +
2836 +               /* check for qualifiers, if present
2837 +                * we just return the qualifier
2838 +                */
2839 +               if (mode & ~AA_MAY_EXEC)
2840 +                       mode = mode & ~AA_MAY_EXEC;
2841 +
2842 +               *xmod = mode;
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",
2847 +                        __FUNCTION__,
2848 +                        name);
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",
2853 +                       __FUNCTION__,
2854 +                       active->name,
2855 +                       name);
2856 +       }
2857 +
2858 +       return rc;
2859 +}
2860 +
2861 +/**
2862 + * aa_filter_mask
2863 + * @mask: requested mask
2864 + * @inode: potential directory inode
2865 + *
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.
2870 + *
2871 + * Returned value of %0 indicates no need to perform a perm check.
2872 + */
2873 +static inline int aa_filter_mask(int mask, struct inode *inode)
2874 +{
2875 +       if (mask) {
2876 +               int elim = MAY_APPEND;
2877 +
2878 +               if (inode && S_ISDIR(inode->i_mode))
2879 +                       elim |= (MAY_EXEC | MAY_WRITE);
2880 +
2881 +               mask &= ~elim;
2882 +       }
2883 +
2884 +       return mask;
2885 +}
2886 +
2887 +static inline void aa_permerror2result(int perm_result, struct aa_audit *sa)
2888 +{
2889 +       if (perm_result == 0) { /* success */
2890 +               sa->result = 1;
2891 +               sa->error_code = 0;
2892 +       } else { /* -ve internal error code or +ve mask of denied perms */
2893 +               sa->result = 0;
2894 +               sa->error_code = perm_result;
2895 +       }
2896 +}
2897 +
2898 +/*************************
2899 + * Main internal functions
2900 + ************************/
2901 +
2902 +/**
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
2907 + *
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.
2912 + *
2913 + * Return %0 on success, else mask of non-allowed permissions
2914 + */
2915 +static unsigned int aa_file_perm(struct aaprofile *active, const char *name,
2916 +                                int mask)
2917 +{
2918 +       int i, error = 0, mode;
2919 +
2920 +#define PROCPFX "/proc/"
2921 +#define PROCLEN sizeof(PROCPFX) - 1
2922 +
2923 +       AA_DEBUG("%s: %s 0x%x\n", __FUNCTION__, name, mask);
2924 +
2925 +       /* should not enter with other than R/W/M/X/L */
2926 +       WARN_ON(mask &
2927 +              ~(AA_MAY_READ | AA_MAY_WRITE | AA_MAY_EXEC | AA_EXEC_MMAP |
2928 +                AA_MAY_LINK));
2929 +
2930 +       /* Special case access to /proc/self/attr/current
2931 +        * Currently we only allow access if opened O_WRONLY
2932 +        */
2933 +       if (mask == MAY_WRITE && strncmp(PROCPFX, name, PROCLEN) == 0 &&
2934 +           aa_taskattr_access(name + PROCLEN))
2935 +               goto done;
2936 +
2937 +       mode = 0;
2938 +
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;
2942 +
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))
2946 +                       continue;
2947 +
2948 +               list_for_each_entry(entry, &active->file_entryp[i],
2949 +                                   listp[i]) {
2950 +                       if (aamatch_match(name, entry->filename,
2951 +                               entry->type, entry->extradata)) {
2952 +                               /* Shortcut, accumulate all bits present */
2953 +                               mode |= entry->mode;
2954 +
2955 +                               /* Mask bits are overloaded
2956 +                                * MAY_{EXEC,WRITE,READ,APPEND} are used by
2957 +                                * kernel, other values are used locally only.
2958 +                                */
2959 +                               if ((mode & mask) == mask) {
2960 +                                       AA_DEBUG("MATCH! %s=0x%x [total mode=0x%x]\n",
2961 +                                                name, mask, mode);
2962 +
2963 +                                       goto done;
2964 +                               }
2965 +                       }
2966 +               }
2967 +       }
2968 +
2969 +       /* return permissions not satisfied */
2970 +       error = mask & ~mode;
2971 +
2972 +done:
2973 +       return error;
2974 +}
2975 +
2976 +/**
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
2981 + *
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.
2985 + */
2986 +static int aa_link_perm(struct aaprofile *active,
2987 +                       const char *link, const char *target)
2988 +{
2989 +       int l_mode, t_mode, ret;
2990 +
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;
2995 +
2996 +               t_mode = aa_file_mode(active, target);
2997 +               t_mode &= ~AA_MAY_LINK;
2998 +
2999 +               ret = (l_mode == t_mode);
3000 +       } else {
3001 +               ret = 0;
3002 +       }
3003 +
3004 +       return ret;
3005 +}
3006 +
3007 +/**
3008 + * _aa_perm_dentry
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)
3013 + *
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.
3020 + *
3021 + * Return %0 (success), +ve (mask of permissions not satisfied) or -ve (system
3022 + * error, most likely -%ENOMEM).
3023 + */
3024 +static int _aa_perm_dentry(struct aaprofile *active, struct dentry *dentry,
3025 +                          int mask, const char **pname)
3026 +{
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);
3031 +
3032 +       /* search all paths to dentry */
3033 +
3034 +       aa_path_begin(dentry, &data);
3035 +       do {
3036 +               name = aa_path_getname(&data);
3037 +               if (name) {
3038 +                       /* error here is 0 (success) or +ve (mask of perms) */
3039 +                       error = aa_file_perm(active, name, mask);
3040 +
3041 +                       /* access via any path is enough */
3042 +                       if (complain || error == 0)
3043 +                               break; /* Caller must free name */
3044 +
3045 +                       /* Already have an path that failed? */
3046 +                       if (failed_name) {
3047 +                               aa_put_name(name);
3048 +                       } else {
3049 +                               failed_name = name;
3050 +                               failed_error = error;
3051 +                       }
3052 +               }
3053 +       } while (name);
3054 +
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;
3059 +               name = NULL;
3060 +       } else if (name) {
3061 +               if (failed_name)
3062 +                       aa_put_name(failed_name);
3063 +       } else {
3064 +               name = failed_name;
3065 +               error = failed_error;
3066 +       }
3067 +
3068 +       *pname = name;
3069 +
3070 +       return error;
3071 +}
3072 +
3073 +/**************************
3074 + * Global utility functions
3075 + *************************/
3076 +
3077 +/**
3078 + * attach_nullprofile - allocate and attach a null_profile hat to profile
3079 + * @profile: profile to attach a null_profile hat to.
3080 + *
3081 + * Return %0 (success) or error (-%ENOMEM)
3082 + */
3083 +int attach_nullprofile(struct aaprofile *profile)
3084 +{
3085 +       struct aaprofile *hat = NULL;
3086 +       char *hatname = NULL;
3087 +
3088 +       hat = alloc_aaprofile();
3089 +       if (!hat)
3090 +               goto fail;
3091 +       if (profile->flags.complain)
3092 +               hatname = kstrdup("null-complain-profile", GFP_KERNEL);
3093 +       else
3094 +               hatname = kstrdup("null-profile", GFP_KERNEL);
3095 +       if (!hatname)
3096 +               goto fail;
3097 +
3098 +       hat->flags.complain = profile->flags.complain;
3099 +       hat->name = hatname;
3100 +       hat->parent = profile;
3101 +
3102 +       profile->null_profile = hat;
3103 +
3104 +       return 0;
3105 +
3106 +fail:
3107 +       kfree(hatname);
3108 +       free_aaprofile(hat);
3109 +
3110 +       return -ENOMEM;
3111 +}
3112 +
3113 +
3114 +/**
3115 + * alloc_null_complain_profile - Allocate the global null_complain_profile.
3116 + *
3117 + * Return %0 (success) or error (-%ENOMEM)
3118 + */
3119 +int alloc_null_complain_profile(void)
3120 +{
3121 +       null_complain_profile = alloc_aaprofile();
3122 +       if (!null_complain_profile)
3123 +               goto fail;
3124 +
3125 +       null_complain_profile->name =
3126 +               kstrdup("null-complain-profile", GFP_KERNEL);
3127 +
3128 +       if (!null_complain_profile->name)
3129 +               goto fail;
3130 +
3131 +       null_complain_profile->flags.complain = 1;
3132 +       if (attach_nullprofile(null_complain_profile))
3133 +               goto fail;
3134 +
3135 +       return 0;
3136 +
3137 +fail:
3138 +       /* free_aaprofile is safe for freeing partially constructed objects */
3139 +       free_aaprofile(null_complain_profile);
3140 +       null_complain_profile = NULL;
3141 +
3142 +       return -ENOMEM;
3143 +}
3144 +
3145 +/**
3146 + * free_null_complain_profile - Free null profiles
3147 + */
3148 +void free_null_complain_profile(void)
3149 +{
3150 +       put_aaprofile(null_complain_profile);
3151 +       null_complain_profile = NULL;
3152 +}
3153 +
3154 +/**
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
3160 + */
3161 +int aa_audit_message(struct aaprofile *active, gfp_t gfp, int flags,
3162 +                    const char *fmt, ...)
3163 +{
3164 +       int ret;
3165 +       struct aa_audit sa;
3166 +
3167 +       sa.type = AA_AUDITTYPE_MSG;
3168 +       sa.name = fmt;
3169 +       va_start(sa.vaval, fmt);
3170 +       sa.flags = flags;
3171 +       sa.gfp_mask = gfp;
3172 +       sa.error_code = 0;
3173 +       sa.result = 0;  /* fake failure: force message to be logged */
3174 +
3175 +       ret = aa_audit(active, &sa);
3176 +
3177 +       va_end(sa.vaval);
3178 +
3179 +       return ret;
3180 +}
3181 +
3182 +/**
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
3187 + */
3188 +int aa_audit_syscallreject(struct aaprofile *active, gfp_t gfp,
3189 +                          enum aasyscall call)
3190 +{
3191 +       struct aa_audit sa;
3192 +       int error = -EPERM;
3193 +
3194 +       if (!syscall_is_cached(call)) {
3195 +               sa.type = AA_AUDITTYPE_SYSCALL;
3196 +               sa.name = syscall_to_name(call);
3197 +               sa.flags = 0;
3198 +               sa.gfp_mask = gfp;
3199 +               sa.error_code = 0;
3200 +               sa.result = 0; /* failure */
3201 +
3202 +               error = aa_audit(active, &sa);
3203 +               if (error == -EPERM)
3204 +                       add_to_cached_syscalls(call);
3205 +       }
3206 +       return error;
3207 +}
3208 +
3209 +/**
3210 + * aa_audit - Log an audit event to the audit subsystem
3211 + * @active: profile to check against
3212 + * @sa: audit event
3213 + */
3214 +int aa_audit(struct aaprofile *active, const struct aa_audit *sa)
3215 +{
3216 +       struct audit_buffer *ab = NULL;
3217 +       struct audit_context *ctx;
3218 +
3219 +       const char *logcls;
3220 +       unsigned int flags;
3221 +       int audit = 0,
3222 +           complain = 0,
3223 +           error = -EINVAL,
3224 +           opspec_error = -EACCES;
3225 +
3226 +       const gfp_t gfp_mask = sa->gfp_mask;
3227 +
3228 +       WARN_ON(sa->type >= AA_AUDITTYPE__END);
3229 +
3230 +       /*
3231 +        * sa->result:    1 success, 0 failure
3232 +        * sa->error_code: success: 0
3233 +        *                failure: +ve mask of failed permissions or -ve
3234 +        *                system error
3235 +        */
3236 +
3237 +       if (likely(sa->result)) {
3238 +               if (likely(!PROFILE_AUDIT(active))) {
3239 +                       /* nothing to log */
3240 +                       error = 0;
3241 +                       goto out;
3242 +               } else {
3243 +                       audit = 1;
3244 +                       logcls = "AUDITING";
3245 +               }
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;
3253 +               goto out;
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.
3257 +                */
3258 +               logcls = "REJECTING";
3259 +       } else {
3260 +               complain = PROFILE_COMPLAIN(active);
3261 +               logcls = complain ? "PERMITTING" : "REJECTING";
3262 +       }
3263 +
3264 +       /* test if event has already been logged and cached used to log
3265 +        * only first time event occurs.
3266 +        */
3267 +       if (sa->type == AA_AUDITTYPE_CAP) {
3268 +               if (cap_is_cached(sa->ival)) {
3269 +                       opspec_error = -EPERM;
3270 +                       goto skip_logging;
3271 +               }
3272 +       }
3273 +
3274 +       /* In future extend w/ per-profile flags
3275 +        * (flags |= sa->active->flags)
3276 +        */
3277 +       flags = sa->flags;
3278 +       if (apparmor_logsyscall)
3279 +               flags |= AA_AUDITFLAG_AUDITSS_SYSCALL;
3280 +
3281 +
3282 +       /* Force full audit syscall logging regardless of global setting if
3283 +        * we are rejecting a syscall
3284 +        */
3285 +       if (sa->type == AA_AUDITTYPE_SYSCALL) {
3286 +               ctx = current->audit_context;
3287 +       } else {
3288 +               ctx = (flags & AA_AUDITFLAG_AUDITSS_SYSCALL) ?
3289 +                       current->audit_context : NULL;
3290 +       }
3291 +
3292 +       ab = audit_log_start(ctx, gfp_mask, AUDIT_SD);
3293 +
3294 +       if (!ab) {
3295 +               AA_ERROR("Unable to log event (%d) to audit subsys\n",
3296 +                       sa->type);
3297 +               if (complain)
3298 +                       error = 0;
3299 +               goto out;
3300 +       }
3301 +
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);
3306 +               error = 0;
3307 +               goto out;
3308 +       }
3309 +
3310 +       /* log operation */
3311 +
3312 +       audit_log_format(ab, "%s ", logcls);    /* REJECTING/ALLOWING/etc */
3313 +
3314 +       if (sa->type == AA_AUDITTYPE_FILE) {
3315 +               int perm = audit ? sa->ival : sa->error_code;
3316 +
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" : "",
3323 +                                sa->name);
3324 +
3325 +               opspec_error = -EPERM;
3326 +
3327 +       } else if (sa->type == AA_AUDITTYPE_DIR) {
3328 +               audit_log_format(ab, "%s on %s ",
3329 +                       sa->ival == aa_dir_mkdir ? "mkdir" : "rmdir",
3330 +                       sa->name);
3331 +
3332 +       } else if (sa->type == AA_AUDITTYPE_ATTR) {
3333 +               struct iattr *iattr = (struct iattr*)sa->pval;
3334 +
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," : "",
3346 +                       sa->name);
3347 +
3348 +       } else if (sa->type == AA_AUDITTYPE_XATTR) {
3349 +               const char *fmt;
3350 +               switch (sa->ival) {
3351 +                       case aa_xattr_get:
3352 +                               fmt = "xattr get";
3353 +                               break;
3354 +                       case aa_xattr_set:
3355 +                               fmt = "xattr set";
3356 +                               break;
3357 +                       case aa_xattr_list:
3358 +                               fmt = "xattr list";
3359 +                               break;
3360 +                       case aa_xattr_remove:
3361 +                               fmt = "xattr remove";
3362 +                               break;
3363 +                       default:
3364 +                               fmt = "xattr <unknown>";
3365 +                               break;
3366 +               }
3367 +
3368 +               audit_log_format(ab, "%s on %s ", fmt, sa->name);
3369 +
3370 +       } else if (sa->type == AA_AUDITTYPE_LINK) {
3371 +               audit_log_format(ab,
3372 +                       "link access from %s to %s ",
3373 +                       sa->name,
3374 +                       (char*)sa->pval);
3375 +
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);
3384 +
3385 +               opspec_error = -EPERM;
3386 +       } else {
3387 +               /* -EINVAL -- will WARN_ON above */
3388 +               goto out;
3389 +       }
3390 +
3391 +       audit_log_format(ab, "(%s(%d) profile %s active %s)",
3392 +                        current->comm, current->pid,
3393 +                        BASE_PROFILE(active)->name, active->name);
3394 +
3395 +       audit_log_end(ab);
3396 +
3397 +skip_logging:
3398 +       if (complain)
3399 +               error = 0;
3400 +       else
3401 +               error = sa->result ? 0 : opspec_error;
3402 +
3403 +out:
3404 +       return error;
3405 +}
3406 +
3407 +/**
3408 + * aa_get_name - retrieve fully qualified path name
3409 + * @dentry: relative path element
3410 + * @mnt: where in tree
3411 + *
3412 + * Returns fully qualified path name on sucess, NULL on failure.
3413 + * aa_put_name must be used to free allocated buffer.
3414 + */
3415 +char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt)
3416 +{
3417 +       char *page, *name;
3418 +
3419 +       page = (char *)__get_free_page(GFP_KERNEL);
3420 +       if (!page) {
3421 +               name = ERR_PTR(-ENOMEM);
3422 +               goto out;
3423 +       }
3424 +
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.
3429 +        */
3430 +       if (IS_ERR(name)) {
3431 +               free_page((unsigned long)page);
3432 +       } else {
3433 +               const char deleted_str[] = " (deleted)";
3434 +               const size_t deleted_size = sizeof(deleted_str) - 1;
3435 +               size_t size;
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);
3442 +       }
3443 +
3444 +out:
3445 +       return name;
3446 +}
3447 +
3448 +/***********************************
3449 + * Global permission check functions
3450 + ***********************************/
3451 +
3452 +/**
3453 + * aa_attr - check whether attribute change allowed
3454 + * @active: profile to check against
3455 + * @dentry: file to check
3456 + * @iattr: attribute changes requested
3457 + */
3458 +int aa_attr(struct aaprofile *active, struct dentry *dentry,
3459 +           struct iattr *iattr)
3460 +{
3461 +       int error = 0, permerror;
3462 +       struct aa_audit sa;
3463 +
3464 +       sa.type = AA_AUDITTYPE_ATTR;
3465 +       sa.pval = iattr;
3466 +       sa.flags = 0;
3467 +       sa.gfp_mask = GFP_KERNEL;
3468 +
3469 +       permerror = _aa_perm_dentry(active, dentry, MAY_WRITE, &sa.name);
3470 +       aa_permerror2result(permerror, &sa);
3471 +
3472 +       error = aa_audit(active, &sa);
3473 +
3474 +       aa_put_name(sa.name);
3475 +
3476 +       return error;
3477 +}
3478 +
3479 +/**
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
3485 + */
3486 +int aa_xattr(struct aaprofile *active, struct dentry *dentry,
3487 +            const char *xattr, enum aa_xattroptype xattroptype)
3488 +{
3489 +       int error = 0, permerror, mask = 0;
3490 +       struct aa_audit sa;
3491 +
3492 +       /* if not confined or empty mask permission granted */
3493 +       if (!active)
3494 +               goto out;
3495 +
3496 +       if (xattroptype == aa_xattr_get || xattroptype == aa_xattr_list)
3497 +               mask = MAY_READ;
3498 +       else if (xattroptype == aa_xattr_set || xattroptype == aa_xattr_remove)
3499 +               mask = MAY_WRITE;
3500 +
3501 +       sa.type = AA_AUDITTYPE_XATTR;
3502 +       sa.ival = xattroptype;
3503 +       sa.pval = xattr;
3504 +       sa.flags = 0;
3505 +       sa.gfp_mask = GFP_KERNEL;
3506 +
3507 +       permerror = _aa_perm_dentry(active, dentry, mask, &sa.name);
3508 +       aa_permerror2result(permerror, &sa);
3509 +
3510 +       error = aa_audit(active, &sa);
3511 +
3512 +       aa_put_name(sa.name);
3513 +
3514 +out:
3515 +       return error;
3516 +}
3517 +
3518 +/**
3519 + * aa_perm - basic apparmor permissions check
3520 + * @active: profile to check against
3521 + * @dentry: dentry
3522 + * @mnt: mountpoint
3523 + * @mask: access mode requested
3524 + *
3525 + * Determine if access (mask) for dentry is authorized by active
3526 + * profile.  Result, %0 (success), -ve (error)
3527 + */
3528 +int aa_perm(struct aaprofile *active, struct dentry *dentry,
3529 +           struct vfsmount *mnt, int mask)
3530 +{
3531 +       int error = 0, permerror;
3532 +       struct aa_audit sa;
3533 +
3534 +       if (!active)
3535 +               goto out;
3536 +
3537 +       if ((mask = aa_filter_mask(mask, dentry->d_inode)) == 0)
3538 +               goto out;
3539 +
3540 +       sa.type = AA_AUDITTYPE_FILE;
3541 +       sa.name = aa_get_name(dentry, mnt);
3542 +       sa.ival = mask;
3543 +       sa.flags = 0;
3544 +       sa.gfp_mask = GFP_KERNEL;
3545 +
3546 +       if (IS_ERR(sa.name)) {
3547 +               permerror = PTR_ERR(sa.name);
3548 +               sa.name = NULL;
3549 +       } else {
3550 +               permerror = aa_file_perm(active, sa.name, mask);
3551 +       }
3552 +
3553 +       aa_permerror2result(permerror, &sa);
3554 +
3555 +       error = aa_audit(active, &sa);
3556 +
3557 +       aa_put_name(sa.name);
3558 +
3559 +out:
3560 +       return error;
3561 +}
3562 +
3563 +/**
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
3568 + */
3569 +int aa_perm_nameidata(struct aaprofile *active, struct nameidata *nd, int mask)
3570 +{
3571 +       int error = 0;
3572 +
3573 +       if (nd)
3574 +               error = aa_perm(active, nd->dentry, nd->mnt, mask);
3575 +
3576 +       return error;
3577 +}
3578 +
3579 +/**
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
3584 + *
3585 + * Determine if access (mask) for dentry is authorized by active profile.
3586 + * Result, %0 (success), -ve (error)
3587 + */
3588 +int aa_perm_dentry(struct aaprofile *active, struct dentry *dentry, int mask)
3589 +{
3590 +       int error = 0, permerror;
3591 +       struct aa_audit sa;
3592 +
3593 +       if (!active)
3594 +               goto out;
3595 +
3596 +       if ((mask = aa_filter_mask(mask, dentry->d_inode)) == 0)
3597 +               goto out;
3598 +
3599 +       sa.type = AA_AUDITTYPE_FILE;
3600 +       sa.ival = mask;
3601 +       sa.flags = 0;
3602 +       sa.gfp_mask = GFP_KERNEL;
3603 +
3604 +       permerror = _aa_perm_dentry(active, dentry, mask, &sa.name);
3605 +       aa_permerror2result(permerror, &sa);
3606 +
3607 +       error = aa_audit(active, &sa);
3608 +
3609 +       aa_put_name(sa.name);
3610 +
3611 +out:
3612 +       return error;
3613 +}
3614 +
3615 +/**
3616 + * aa_perm_dir
3617 + * @active: profile to check against
3618 + * @dentry: requested dentry
3619 + * @diroptype: aa_dir_mkdir or aa_dir_rmdir
3620 + *
3621 + * Determine if directory operation (make/remove) for dentry is authorized
3622 + * by @active profile.
3623 + * Result, %0 (success), -ve (error)
3624 + */
3625 +int aa_perm_dir(struct aaprofile *active, struct dentry *dentry,
3626 +               enum aa_diroptype diroptype)
3627 +{
3628 +       int error = 0, permerror, mask;
3629 +       struct aa_audit sa;
3630 +
3631 +       WARN_ON(diroptype != aa_dir_mkdir && diroptype != aa_dir_rmdir);
3632 +
3633 +       if (!active)
3634 +               goto out;
3635 +
3636 +       mask = MAY_WRITE;
3637 +
3638 +       sa.type = AA_AUDITTYPE_DIR;
3639 +       sa.ival = diroptype;
3640 +       sa.flags = 0;
3641 +       sa.gfp_mask = GFP_KERNEL;
3642 +
3643 +       permerror = _aa_perm_dentry(active, dentry, mask, &sa.name);
3644 +       aa_permerror2result(permerror, &sa);
3645 +
3646 +       error = aa_audit(active, &sa);
3647 +
3648 +       aa_put_name(sa.name);
3649 +
3650 +out:
3651 +       return error;
3652 +}
3653 +
3654 +/**
3655 + * aa_capability - test permission to use capability
3656 + * @active: profile to check against
3657 + * @cap: capability to be tested
3658 + *
3659 + * Look up capability in active profile capability set.
3660 + * Return %0 (success), -%EPERM (error)
3661 + */
3662 +int aa_capability(struct aaprofile *active, int cap)
3663 +{
3664 +       int error = 0;
3665 +
3666 +       struct aa_audit sa;
3667 +
3668 +       sa.type = AA_AUDITTYPE_CAP;
3669 +       sa.name = NULL;
3670 +       sa.ival = cap;
3671 +       sa.flags = 0;
3672 +       sa.error_code = 0;
3673 +       sa.result = cap_raised(active->capabilities, cap);
3674 +       sa.gfp_mask = GFP_ATOMIC;
3675 +
3676 +       error = aa_audit(active, &sa);
3677 +
3678 +       return error;
3679 +}
3680 +
3681 +/**
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
3686 + *
3687 + * Checks link permissions for all possible name combinations.  This is
3688 + * particularly ugly.  Returns %0 on sucess, error otherwise.
3689 + */
3690 +int aa_link(struct aaprofile *active, struct dentry *link,
3691 +           struct dentry *target)
3692 +{
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;
3700 +
3701 +       if (!active)
3702 +               return 0;
3703 +
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
3710 +        *
3711 +        * Getting direct access to vfsmounts (via nameidata) for link and
3712 +        * target would allow all this uglyness to go away.
3713 +        *
3714 +        * If more than one mountpoint matches but none satisfy the profile,
3715 +        * only the first pathname (mountpoint) is logged.
3716 +        */
3717 +
3718 +       __aa_path_begin(target, link, &odata);
3719 +       do {
3720 +               oname = aa_path_getname(&odata);
3721 +               if (oname) {
3722 +                       aa_path_begin(target, &idata);
3723 +                       do {
3724 +                               iname = aa_path_getname(&idata);
3725 +                               if (iname) {
3726 +                                       result = aa_link_perm(active, oname,
3727 +                                                             iname);
3728 +
3729 +                                       /* access via any path is enough */
3730 +                                       if (result || complain) {
3731 +                                               match = 1;
3732 +                                               break;
3733 +                                       }
3734 +
3735 +                                       /* Already have an path that failed? */
3736 +                                       if (failed_iname) {
3737 +                                               aa_put_name(iname);
3738 +                                       } else {
3739 +                                               failed_iname = iname;
3740 +                                               failed_oname = oname;
3741 +                                       }
3742 +                               }
3743 +                       } while (iname && !match);
3744 +
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]");
3749 +
3750 +                               /* name should not be set if error */
3751 +                               WARN_ON(iname);
3752 +
3753 +                               error_code = path_error;
3754 +                       }
3755 +
3756 +                       /* don't release if we're saving it */
3757 +                       if (!match && failed_oname != oname)
3758 +                               aa_put_name(oname);
3759 +               }
3760 +       } while (oname && !match);
3761 +
3762 +       if (error_code != 0) {
3763 +               /* inner error */
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;
3768 +       }
3769 +
3770 +       if (error_code != 0) {
3771 +               /* inner or outer error */
3772 +               result = 0;
3773 +       } else if (!match) {
3774 +               /* failed to match */
3775 +               WARN_ON(iname);
3776 +               WARN_ON(oname);
3777 +
3778 +               result = 0;
3779 +               iname = failed_iname;
3780 +               oname = failed_oname;
3781 +       }
3782 +
3783 +       sa.type = AA_AUDITTYPE_LINK;
3784 +       sa.name = oname;        /* link */
3785 +       sa.pval = iname;        /* target */
3786 +       sa.flags = 0;
3787 +       sa.error_code = error_code;
3788 +       sa.result = result;
3789 +       sa.gfp_mask = GFP_KERNEL;
3790 +
3791 +       error = aa_audit(active, &sa);
3792 +
3793 +       if (failed_oname != oname)
3794 +               aa_put_name(failed_oname);
3795 +       if (failed_iname != iname)
3796 +               aa_put_name(failed_iname);
3797 +
3798 +       aa_put_name(oname);
3799 +       aa_put_name(iname);
3800 +
3801 +       return error;
3802 +}
3803 +
3804 +/*******************************
3805 + * Global task related functions
3806 + *******************************/
3807 +
3808 +/**
3809 + * aa_fork - create a new subdomain
3810 + * @p: new process
3811 + *
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.
3817 + *
3818 + * The sd_lock is used to maintain consistency against profile
3819 + * replacement/removal.
3820 + */
3821 +
3822 +int aa_fork(struct task_struct *p)
3823 +{
3824 +       struct subdomain *sd = AA_SUBDOMAIN(current->security);
3825 +       struct subdomain *newsd = NULL;
3826 +
3827 +       AA_DEBUG("%s\n", __FUNCTION__);
3828 +
3829 +       if (__aa_is_confined(sd)) {
3830 +               unsigned long flags;
3831 +
3832 +               newsd = alloc_subdomain(p);
3833 +
3834 +               if (!newsd)
3835 +                       return -ENOMEM;
3836 +
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.
3840 +                */
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);
3845 +
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);
3851 +       }
3852 +       p->security = newsd;
3853 +       return 0;
3854 +}
3855 +
3856 +/**
3857 + * aa_register - register a new program
3858 + * @bprm: binprm of program being registered
3859 + *
3860 + * Try to register a new program during execve().  This should give the
3861 + * new program a valid subdomain.
3862 + */
3863 +int aa_register(struct linux_binprm *bprm)
3864 +{
3865 +       char *filename;
3866 +       struct file *filp = bprm->file;
3867 +       struct aaprofile *active;
3868 +       struct aaprofile *newprofile = NULL, unconstrained_flag;
3869 +       int     error = -ENOMEM,
3870 +               exec_mode = 0,
3871 +               find_profile = 0,
3872 +               find_profile_mandatory = 0,
3873 +               unsafe_exec = 0,
3874 +               complain = 0;
3875 +
3876 +       AA_DEBUG("%s\n", __FUNCTION__);
3877 +
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__);
3881 +               goto out;
3882 +       }
3883 +
3884 +       error = 0;
3885 +
3886 +       active = get_active_aaprofile();
3887 +
3888 +       if (!active) {
3889 +               /* Unconfined task, load profile if it exists */
3890 +               find_profile = 1;
3891 +               goto find_profile;
3892 +       }
3893 +
3894 +       complain = PROFILE_COMPLAIN(active);
3895 +
3896 +       /* Confined task, determine what mode inherit, unconstrained or
3897 +        * mandatory to load new profile
3898 +        */
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
3904 +                        */
3905 +                       AA_DEBUG("%s: INHERIT %s\n",
3906 +                                __FUNCTION__,
3907 +                                filename);
3908 +                       break;
3909 +
3910 +               case AA_EXEC_UNCONSTRAINED:
3911 +                       AA_DEBUG("%s: UNCONSTRAINED %s\n",
3912 +                                __FUNCTION__,
3913 +                                filename);
3914 +
3915 +                       /* unload profile */
3916 +                       newprofile = &unconstrained_flag;
3917 +                       break;
3918 +
3919 +               case AA_EXEC_PROFILE:
3920 +                       AA_DEBUG("%s: PROFILE %s\n",
3921 +                                __FUNCTION__,
3922 +                                filename);
3923 +
3924 +                       find_profile = 1;
3925 +                       find_profile_mandatory = 1;
3926 +                       break;
3927 +
3928 +               case AA_MAY_EXEC:
3929 +                       /* this should not happen, entries
3930 +                        * with just EXEC only should be
3931 +                        * rejected at profile load time
3932 +                        */
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",
3936 +                                __FUNCTION__,
3937 +                                filename,
3938 +                                current->comm, current->pid,
3939 +                                BASE_PROFILE(active)->name, active->name);
3940 +                       error = -EPERM;
3941 +                       break;
3942 +
3943 +               default:
3944 +                       AA_ERROR("%s: Rejecting exec(2) of image '%s'. "
3945 +                                "Unknown exec qualifier %x "
3946 +                                "(%s (pid %d) profile %s active %s)\n",
3947 +                                __FUNCTION__,
3948 +                                filename,
3949 +                                exec_mode,
3950 +                                current->comm, current->pid,
3951 +                                BASE_PROFILE(active)->name, active->name);
3952 +                       error = -EPERM;
3953 +                       break;
3954 +               }
3955 +
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).
3960 +                */
3961 +               newprofile = get_aaprofile(null_complain_profile);
3962 +               unsafe_exec = 1;
3963 +       } else {
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",
3967 +                       __FUNCTION__,
3968 +                       filename,
3969 +                       current->comm, current->pid,
3970 +                       BASE_PROFILE(active)->name, active->name);
3971 +               error = -EPERM;
3972 +       }
3973 +
3974 +
3975 +find_profile:
3976 +       if (!find_profile)
3977 +               goto apply_profile;
3978 +
3979 +       /* Locate new profile */
3980 +       newprofile = aa_profilelist_find(filename);
3981 +       if (newprofile) {
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 */
3986 +
3987 +               if (complain) {
3988 +                       LOG_HINT(active, GFP_KERNEL, HINT_MANDPROF,
3989 +                               "image=%s pid=%d profile=%s active=%s\n",
3990 +                               filename,
3991 +                               current->pid,
3992 +                               BASE_PROFILE(active)->name, active->name);
3993 +
3994 +                       newprofile = get_aaprofile(null_complain_profile);
3995 +               } else {
3996 +                       AA_WARN("REJECTING exec(2) of image '%s'. "
3997 +                               "Profile mandatory and not found "
3998 +                               "(%s(%d) profile %s active %s)\n",
3999 +                               filename,
4000 +                               current->comm, current->pid,
4001 +                               BASE_PROFILE(active)->name, active->name);
4002 +                       error = -EPERM;
4003 +               }
4004 +       } else {
4005 +               /* Profile (non-mandatory) could not be found */
4006 +
4007 +               /* Only way we can get into this code is if task
4008 +                * is unconstrained.
4009 +                */
4010 +
4011 +               WARN_ON(active);
4012 +
4013 +               AA_DEBUG("%s: No profile found for exec image %s\n",
4014 +                        __FUNCTION__,
4015 +                        filename);
4016 +       } /* newprofile */
4017 +
4018 +
4019 +apply_profile:
4020 +       /* Apply profile if necessary */
4021 +       if (newprofile) {
4022 +               struct subdomain *sd, *lazy_sd = NULL;
4023 +               unsigned long flags;
4024 +
4025 +               if (newprofile == &unconstrained_flag)
4026 +                       newprofile = NULL;
4027 +
4028 +               /* grab a lock - this is to guarentee consistency against
4029 +                * other writers of subdomain (replacement/removal)
4030 +                *
4031 +                * Several things may have changed since the code above
4032 +                *
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.
4036 +                *
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.
4044 +                *
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.
4049 +                */
4050 +
4051 +               if (!active && !(sd = AA_SUBDOMAIN(current->security))) {
4052 +                       lazy_sd = alloc_subdomain(current);
4053 +                       if (!lazy_sd) {
4054 +                               AA_ERROR("%s: Failed to allocate subdomain\n",
4055 +                                        __FUNCTION__);
4056 +                               error = -ENOMEM;
4057 +                               goto cleanup;
4058 +                       }
4059 +               }
4060 +
4061 +               spin_lock_irqsave(&sd_lock, flags);
4062 +
4063 +               sd = AA_SUBDOMAIN(current->security);
4064 +               if (lazy_sd) {
4065 +                       if (sd) {
4066 +                               /* raced by setprofile - created sd */
4067 +                               free_subdomain(lazy_sd);
4068 +                               lazy_sd = NULL;
4069 +                       } else {
4070 +                               /* Not rcu used to get the write barrier
4071 +                                * correct */
4072 +                               rcu_assign_pointer(current->security, lazy_sd);
4073 +                               sd = lazy_sd;
4074 +                       }
4075 +               }
4076 +
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.
4080 +                */
4081 +               if (newprofile && unlikely(newprofile->isstale)) {
4082 +                       WARN_ON(newprofile == null_complain_profile);
4083 +
4084 +                       /* drop refcnt obtained from earlier get_aaprofile */
4085 +                       put_aaprofile(newprofile);
4086 +
4087 +                       newprofile = aa_profilelist_find(filename);
4088 +
4089 +                       if (!newprofile) {
4090 +                               /* Race, profile was removed, not replaced.
4091 +                                * Redo with error checking
4092 +                                */
4093 +                               spin_unlock_irqrestore(&sd_lock, flags);
4094 +                               goto find_profile;
4095 +                       }
4096 +               }
4097 +
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
4103 +                *
4104 +                * Cases 2 and 3 are marked as requiring secure exec
4105 +                * (unless policy specified "unsafe exec")
4106 +                */
4107 +               if (__aa_is_confined(sd) && !unsafe_exec) {
4108 +                       unsigned long bprm_flags;
4109 +
4110 +                       bprm_flags = AA_SECURE_EXEC_NEEDED;
4111 +                       bprm->security = (void*)
4112 +                               ((unsigned long)bprm->security | bprm_flags);
4113 +               }
4114 +
4115 +               aa_switch(sd, newprofile);
4116 +               put_aaprofile(newprofile);
4117 +
4118 +               if (complain && newprofile == null_complain_profile)
4119 +                       LOG_HINT(newprofile, GFP_ATOMIC, HINT_CHGPROF,
4120 +                               "pid=%d\n",
4121 +                               current->pid);
4122 +
4123 +               spin_unlock_irqrestore(&sd_lock, flags);
4124 +       }
4125 +
4126 +cleanup:
4127 +       aa_put_name(filename);
4128 +
4129 +       put_aaprofile(active);
4130 +
4131 +out:
4132 +       return error;
4133 +}
4134 +
4135 +/**
4136 + * aa_release - release the task's subdomain
4137 + * @p: task being released
4138 + *
4139 + * This is called after a task has exited and the parent has reaped it.
4140 + * @p->security blob is freed.
4141 + *
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.
4147 + */
4148 +void aa_release(struct task_struct *p)
4149 +{
4150 +       struct subdomain *sd = AA_SUBDOMAIN(p->security);
4151 +       if (sd) {
4152 +               p->security = NULL;
4153 +
4154 +               aa_subdomainlist_remove(sd);
4155 +               aa_switch_unconfined(sd);
4156 +
4157 +               kfree(sd);
4158 +       }
4159 +}
4160 +
4161 +/*****************************
4162 + * global subprofile functions
4163 + ****************************/
4164 +
4165 +/**
4166 + * do_change_hat - actually switch hats
4167 + * @hat_name: name of hat to swtich to
4168 + * @sd: current subdomain
4169 + *
4170 + * Switch to a new hat.  Return %0 on success, error otherwise.
4171 + */
4172 +static inline int do_change_hat(const char *hat_name, struct subdomain *sd)
4173 +{
4174 +       struct aaprofile *sub;
4175 +       int error = 0;
4176 +
4177 +       sub = __aa_find_profile(hat_name, &BASE_PROFILE(sd->active)->sub);
4178 +
4179 +       if (sub) {
4180 +               /* change hat */
4181 +               aa_switch(sd, sub);
4182 +               put_aaprofile(sub);
4183 +       } else {
4184 +               /* There is no such subprofile change to a NULL profile.
4185 +                * The NULL profile grants no file access.
4186 +                *
4187 +                * This feature is used by changehat_apache.
4188 +                *
4189 +                * N.B from the null-profile the task can still changehat back
4190 +                * out to the parent profile (assuming magic != NULL)
4191 +                */
4192 +               if (SUBDOMAIN_COMPLAIN(sd)) {
4193 +                       LOG_HINT(sd->active, GFP_ATOMIC, HINT_UNKNOWN_HAT,
4194 +                               "%s pid=%d "
4195 +                               "profile=%s active=%s\n",
4196 +                               hat_name,
4197 +                               current->pid,
4198 +                               BASE_PROFILE(sd->active)->name,
4199 +                               sd->active->name);
4200 +               } else {
4201 +                       AA_DEBUG("%s: Unknown hatname '%s'. "
4202 +                               "Changing to NULL profile "
4203 +                               "(%s(%d) profile %s active %s)\n",
4204 +                                __FUNCTION__,
4205 +                                hat_name,
4206 +                                current->comm, current->pid,
4207 +                                BASE_PROFILE(sd->active)->name,
4208 +                                sd->active->name);
4209 +                       error = -EACCES;
4210 +               }
4211 +               aa_switch(sd, sd->active->null_profile);
4212 +       }
4213 +
4214 +       return error;
4215 +}
4216 +
4217 +/**
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
4221 + *
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
4226 + * otherwise.
4227 + */
4228 +int aa_change_hat(const char *hat_name, u32 hat_magic)
4229 +{
4230 +       struct subdomain *sd = AA_SUBDOMAIN(current->security);
4231 +       int error = 0;
4232 +
4233 +       AA_DEBUG("%s: %p, 0x%x (pid %d)\n",
4234 +                __FUNCTION__,
4235 +                hat_name, hat_magic,
4236 +                current->pid);
4237 +
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);
4243 +       }
4244 +
4245 +       /* check to see if an unconfined process is doing a changehat. */
4246 +       if (!__aa_is_confined(sd)) {
4247 +               error = -EPERM;
4248 +               goto out;
4249 +       }
4250 +
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)) {
4254 +               error = -ECHILD;
4255 +               goto out;
4256 +       }
4257 +
4258 +       /* Check whether current domain is parent
4259 +        * or one of the sibling children
4260 +        */
4261 +       if (!IN_SUBPROFILE(sd->active)) {
4262 +               /*
4263 +                * parent
4264 +                */
4265 +               if (hat_name) {
4266 +                       AA_DEBUG("%s: switching to %s, 0x%x\n",
4267 +                                __FUNCTION__,
4268 +                                hat_name,
4269 +                                hat_magic);
4270 +
4271 +                       /*
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
4277 +                        */
4278 +                       sd->hat_magic = hat_magic;
4279 +                       error = do_change_hat(hat_name, sd);
4280 +               } else {
4281 +                       /* Got here via changehat(NULL, magic)
4282 +                        *
4283 +                        * We used to simply update the magic cookie.
4284 +                        * That's an odd behaviour, so just do nothing.
4285 +                        */
4286 +               }
4287 +       } else {
4288 +               /*
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
4293 +                */
4294 +               if (hat_magic == sd->hat_magic && sd->hat_magic) {
4295 +                       if (!hat_name) {
4296 +                               /*
4297 +                                * Got here via changehat(NULL, magic)
4298 +                                * Return from subprofile, back to parent
4299 +                                */
4300 +                               aa_switch(sd, sd->active->parent);
4301 +
4302 +                               /* Reset hat_magic to zero.
4303 +                                * New value will be passed on next changehat
4304 +                                */
4305 +                               sd->hat_magic = 0;
4306 +                       } else {
4307 +                               /* change to another (sibling) profile */
4308 +                               error = do_change_hat(hat_name, sd);
4309 +                       }
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,
4315 +                                hat_magic,
4316 +                                hat_name ? hat_name : "NULL",
4317 +                                BASE_PROFILE(sd->active)->name,
4318 +                                sd->active->name);
4319 +
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);
4329 +
4330 +                       /* terminate current process */
4331 +                       (void)send_sig_info(SIGKILL, NULL, current);
4332 +               }
4333 +
4334 +       }
4335 +
4336 +out:
4337 +       return error;
4338 +}
4339 Index: b/security/apparmor/match/Kbuild
4340 ===================================================================
4341 --- /dev/null
4342 +++ b/security/apparmor/match/Kbuild
4343 @@ -0,0 +1,6 @@
4344 +# Makefile for AppArmor aamatch submodule
4345 +#
4346 +
4347 +obj-$(CONFIG_SECURITY_APPARMOR) += aamatch_pcre.o
4348 +
4349 +aamatch_pcre-y := match_pcre.o pcre_exec.o
4350 Index: b/security/apparmor/match/Makefile
4351 ===================================================================
4352 --- /dev/null
4353 +++ b/security/apparmor/match/Makefile
4354 @@ -0,0 +1,5 @@
4355 +# Makefile for AppArmor aamatch submodule
4356 +#
4357 +obj-$(CONFIG_SECURITY_APPARMOR) += aamatch_pcre.o
4358 +
4359 +aamatch_pcre-y := match_pcre.o pcre_exec.o
4360 Index: b/security/apparmor/match/match.h
4361 ===================================================================
4362 --- /dev/null
4363 +++ b/security/apparmor/match/match.h
4364 @@ -0,0 +1,132 @@
4365 +/*
4366 + *     Copyright (C) 2002-2005 Novell/SUSE
4367 + *
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
4371 + *     License.
4372 + *
4373 + *     AppArmor submodule (match) prototypes
4374 + */
4375 +
4376 +#ifndef __MATCH_H
4377 +#define __MATCH_H
4378 +
4379 +#include "../module_interface.h"
4380 +#include "../apparmor.h"
4381 +
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").
4385 +
4386 + * aamatch_alloc
4387 + * aamatch_free
4388 + * aamatch_features
4389 + * aamatch_serialize
4390 + * aamatch_match
4391 + *
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.
4395 + *
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.
4399 + */
4400 +
4401 +typedef int (*aamatch_serializecb)
4402 +       (struct aa_ext *, enum aa_code, void *, const char *);
4403 +
4404 +/**
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)
4408 + */
4409 +extern void* aamatch_alloc(enum entry_match_type type);
4410 +
4411 +/**
4412 + * aamatch_free: release data allocated by aamatch_alloc
4413 + * @entry_extradata: data previously allocated by aamatch_alloc
4414 + */
4415 +extern void aamatch_free(void *entry_extradata);
4416 +
4417 +/**
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)
4421 + */
4422 +extern const char* aamatch_features(void);
4423 +
4424 +/**
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
4430 + */
4431 +extern int aamatch_serialize(void *entry_extradata, struct aa_ext *e,
4432 +                            aamatch_serializecb cb);
4433 +
4434 +/**
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
4441 + */
4442 +extern unsigned int aamatch_match(const char *pathname, const char *entry_name,
4443 +                                 enum entry_match_type type,
4444 +                                 void *entry_extradata);
4445 +
4446 +
4447 +/**
4448 + * sd_getmatch_type - return string representation of entry_match_type
4449 + * @type: entry match type
4450 + */
4451 +static inline const char *sd_getmatch_type(enum entry_match_type type)
4452 +{
4453 +       const char *names[] = {
4454 +               "aa_entry_literal",
4455 +               "aa_entry_tailglob",
4456 +               "aa_entry_pattern",
4457 +               "aa_entry_invalid"
4458 +       };
4459 +
4460 +       if (type >= aa_entry_invalid) {
4461 +               type = aa_entry_invalid;
4462 +       }
4463 +
4464 +       return names[type];
4465 +}
4466 +
4467 +/**
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
4473 + */
4474 +static inline int aamatch_match_common(const char *path,
4475 +                                          const char *entry_name,
4476 +                                          enum entry_match_type type)
4477 +{
4478 +       int retval;
4479 +
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);
4487 +       } else {
4488 +               AA_WARN("%s: Invalid entry_match_type %d\n",
4489 +                       __FUNCTION__, type);
4490 +               retval = 0;
4491 +       }
4492 +
4493 +       return retval;
4494 +}
4495 +
4496 +#endif /* __MATCH_H */
4497 Index: b/security/apparmor/match/match_default.c
4498 ===================================================================
4499 --- /dev/null
4500 +++ b/security/apparmor/match/match_default.c
4501 @@ -0,0 +1,57 @@
4502 +/*
4503 + *     Copyright (C) 2002-2005 Novell/SUSE
4504 + *
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
4508 + *     License.
4509 + *
4510 + *     http://forge.novell.com/modules/xfmod/project/?apparmor
4511 + *
4512 + *     AppArmor default match submodule (literal and tailglob)
4513 + */
4514 +
4515 +#include <linux/module.h>
4516 +#include "match.h"
4517 +
4518 +static const char *features="literal tailglob";
4519 +
4520 +void* aamatch_alloc(enum entry_match_type type)
4521 +{
4522 +       return NULL;
4523 +}
4524 +
4525 +void aamatch_free(void *ptr)
4526 +{
4527 +}
4528 +
4529 +const char *aamatch_features(void)
4530 +{
4531 +       return features;
4532 +}
4533 +
4534 +int aamatch_serialize(void *entry_extradata, struct aa_ext *e,
4535 +                     aamatch_serializecb cb)
4536 +{
4537 +       return 0;
4538 +}
4539 +
4540 +unsigned int aamatch_match(const char *pathname, const char *entry_name,
4541 +                          enum entry_match_type type, void *entry_extradata)
4542 +{
4543 +       int ret;
4544 +
4545 +       ret = aamatch_match_common(pathname, entry_name, type);
4546 +
4547 +       return ret;
4548 +}
4549 +
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);
4555 +
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 ===================================================================
4561 --- /dev/null
4562 +++ b/security/apparmor/match/match_pcre.c
4563 @@ -0,0 +1,169 @@
4564 +/*
4565 + *     Copyright (C) 2002-2005 Novell/SUSE
4566 + *
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
4570 + *     License.
4571 + *
4572 + *     http://forge.novell.com/modules/xfmod/project/?apparmor
4573 + *
4574 + *     AppArmor aamatch submodule (w/ pattern expansion).
4575 + *
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.
4579 + */
4580 +
4581 +#include <linux/module.h>
4582 +#include "match.h"
4583 +#include "pcre_exec.h"
4584 +#include "pcre_tables.h"
4585 +
4586 +static const char *features="literal tailglob pattern=pcre";
4587 +
4588 +struct aamatch_entry
4589 +{
4590 +       char *pattern;
4591 +       pcre *compiled;
4592 +};
4593 +
4594 +void* aamatch_alloc(enum entry_match_type entry_type)
4595 +{
4596 +void *ptr=NULL;
4597 +
4598 +       if (entry_type == aa_entry_pattern) {
4599 +               ptr = kmalloc(sizeof(struct aamatch_entry), GFP_KERNEL);
4600 +               if (ptr)
4601 +                       memset(ptr, 0, sizeof(struct aamatch_entry));
4602 +               else
4603 +                       ptr=ERR_PTR(-ENOMEM);
4604 +       } else if (entry_type != aa_entry_literal &&
4605 +                  entry_type != aa_entry_tailglob) {
4606 +               ptr = ERR_PTR(-EINVAL);
4607 +       }
4608 +
4609 +       return ptr;
4610 +}
4611 +
4612 +void aamatch_free(void *ptr)
4613 +{
4614 +       if (ptr) {
4615 +               struct aamatch_entry *ed = (struct aamatch_entry *) ptr;
4616 +               kfree(ed->pattern);
4617 +               kfree(ed->compiled);    /* allocated by AA_READ_X */
4618 +       }
4619 +       kfree(ptr);
4620 +}
4621 +
4622 +const char *aamatch_features(void)
4623 +{
4624 +       return features;
4625 +}
4626 +
4627 +int aamatch_serialize(void *entry_extradata, struct aa_ext *e,
4628 +                     aamatch_serializecb cb)
4629 +{
4630 +#define AA_READ_X(E, C, D, N) \
4631 +       do { \
4632 +               if (!cb((E), (C), (D), (N))) { \
4633 +                       error = -EINVAL; \
4634 +                       goto done; \
4635 +               }\
4636 +       } while (0)
4637 +
4638 +       int error = 0;
4639 +       u32 size, magic, opts;
4640 +       u8 t_char;
4641 +       struct aamatch_entry *ed = (struct aamatch_entry *) entry_extradata;
4642 +
4643 +       if (ed == NULL)
4644 +               goto done;
4645 +
4646 +       AA_READ_X(e, AA_DYN_STRING, &ed->pattern, NULL);
4647 +
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);
4655 +
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) {
4660 +               error = -ENOMEM;
4661 +               goto done;
4662 +       }
4663 +
4664 +       memset(ed->compiled, 0, size + sizeof(pcre));
4665 +       ed->compiled->magic_number = magic;
4666 +       ed->compiled->size = size + sizeof(pcre);
4667 +
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;
4678 +
4679 +       AA_READ_X(e, AA_STATIC_BLOB, &ed->compiled->code[1], NULL);
4680 +
4681 +       AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
4682 +
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;
4686 +
4687 +done:
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;
4693 +       }
4694 +
4695 +       return error;
4696 +}
4697 +
4698 +unsigned int aamatch_match(const char *pathname, const char *entry_name,
4699 +                          enum entry_match_type entry_type, void *entry_extradata)
4700 +{
4701 +       int ret;
4702 +
4703 +       if (entry_type == aa_entry_pattern) {
4704 +               int pcreret;
4705 +               struct aamatch_entry *ed =
4706 +                       (struct aamatch_entry *) entry_extradata;
4707 +
4708 +               pcreret = pcre_exec(ed->compiled, NULL,
4709 +                                   pathname, strlen(pathname),
4710 +                                   0, 0, NULL, 0);
4711 +
4712 +               ret = (pcreret >= 0);
4713 +
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);
4717 +       } else {
4718 +               ret = aamatch_match_common(pathname, entry_name, entry_type);
4719 +       }
4720 +
4721 +        return ret;
4722 +}
4723 +
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);
4729 +
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 ===================================================================
4735 --- /dev/null
4736 +++ b/security/apparmor/match/pcre_exec.c
4737 @@ -0,0 +1,1945 @@
4738 +/*
4739 + *  This is a modified version of pcre.c containing only the code/data
4740 + *  required to support pcre_exec()
4741 + */
4742 +
4743 +
4744 +/*************************************************
4745 +*      Perl-Compatible Regular Expressions       *
4746 +*************************************************/
4747 +
4748 +/*
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.
4752 +
4753 +Written by: Philip Hazel <ph10@cam.ac.uk>
4754 +
4755 +           Copyright (c) 1997-2001 University of Cambridge
4756 +
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
4760 +restrictions:
4761 +
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.
4765 +
4766 +2. The origin of this software must not be misrepresented, either by
4767 +   explicit claim or by omission.
4768 +
4769 +3. Altered versions must be plainly marked as such, and must not be
4770 +   misrepresented as being the original software.
4771 +
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 +-----------------------------------------------------------------------------
4776 +*/
4777 +
4778 +
4779 +/* Define DEBUG to get debugging output on stdout. */
4780 +
4781 +/* #define DEBUG */
4782 +
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... */
4786 +
4787 +#ifdef DEBUG
4788 +#define DPRINTF(p) PCRE_PRINTF p
4789 +#else
4790 +#define DPRINTF(p) /*nothing*/
4791 +#endif
4792 +
4793 +/* Include the internals header, which itself includes Standard C headers plus
4794 +the external pcre header. */
4795 +
4796 +#include "pcre_exec.h"
4797 +
4798 +
4799 +/* ----  CODE DELETED ---- */
4800 +
4801 +
4802 +/* Min and max values for the common repeats; for the maxima, 0 => infinity */
4803 +
4804 +static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
4805 +static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
4806 +
4807 +
4808 +/* ----  CODE DELETED ---- */
4809 +
4810 +
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. */
4815 +
4816 +typedef struct eptrblock {
4817 +         struct eptrblock *prev;
4818 +           const uschar *saved_eptr;
4819 +} eptrblock;
4820 +
4821 +/* Flag bits for the match() function */
4822 +
4823 +#define match_condassert   0x01    /* Called to check a condition assertion */
4824 +#define match_isgroup      0x02    /* Set if start of bracketed group */
4825 +
4826 +
4827 +/* ----  CODE DELETED ---- */
4828 +
4829 +
4830 +/*************************************************
4831 + * *               Global variables                 *
4832 + * *************************************************/
4833 +
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. */
4838 +
4839 +#ifdef __KERNEL__
4840 +static void *kern_malloc(size_t sz)
4841 +{
4842 +               return kmalloc(sz, GFP_KERNEL);
4843 +}
4844 +void  *(*pcre_malloc)(size_t) = kern_malloc;
4845 +void  (*pcre_free)(const void *) = kfree;
4846 +#else
4847 +void  *(*pcre_malloc)(size_t) = malloc;
4848 +void  (*pcre_free)(const void *) = free;
4849 +#endif
4850 +
4851 +
4852 +/*************************************************
4853 + * *    Macros and tables for character handling    *
4854 + * *************************************************/
4855 +
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. */
4859 +
4860 +#ifndef SUPPORT_UTF8
4861 +#define GETCHARINC(c, eptr) c = *eptr++;
4862 +#define GETCHARLEN(c, eptr, len) c = *eptr;
4863 +#define BACKCHAR(eptr)
4864 +#endif
4865 +
4866 +/* ----  CODE DELETED ---- */
4867 +
4868 +#ifdef DEBUG
4869 +/*************************************************
4870 +*        Debugging function to print chars       *
4871 +*************************************************/
4872 +
4873 +/* Print a sequence of chars in printable format, stopping at the end of the
4874 +subject if the requested.
4875 +
4876 +Arguments:
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
4881 +
4882 +Returns:     nothing
4883 +*/
4884 +
4885 +static void
4886 +pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
4887 +{
4888 +int c;
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);
4892 +}
4893 +#endif /* DEBUG */
4894 +
4895 +/* ----  CODE DELETED ---- */
4896 +
4897 +
4898 +/*************************************************
4899 +*          Match a back-reference                *
4900 +*************************************************/
4901 +
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.
4904 +
4905 +Arguments:
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
4910 +  ims         the ims flags
4911 +
4912 +Returns:      TRUE if matched
4913 +*/
4914 +
4915 +static BOOL
4916 +match_ref(int offset, register const uschar *eptr, int length, match_data *md,
4917 +  unsigned long int ims)
4918 +{
4919 +const uschar *p = md->start_subject + md->offset_vector[offset];
4920 +
4921 +#ifdef DEBUG
4922 +if (eptr >= md->end_subject)
4923 +  PCRE_PRINTF("matching subject <null>");
4924 +else
4925 +  {
4926 +  PCRE_PRINTF("matching subject ");
4927 +  pchars(eptr, length, TRUE, md);
4928 +  }
4929 +PCRE_PRINTF(" against backref ");
4930 +pchars(p, length, FALSE, md);
4931 +PCRE_PRINTF("\n");
4932 +#endif
4933 +
4934 +/* Always fail if not enough characters left */
4935 +
4936 +if (length > md->end_subject - eptr) return FALSE;
4937 +
4938 +/* Separate the caselesss case for speed */
4939 +
4940 +if ((ims & PCRE_CASELESS) != 0)
4941 +  {
4942 +  while (length-- > 0)
4943 +    if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
4944 +  }
4945 +else
4946 +  { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
4947 +
4948 +return TRUE;
4949 +}
4950 +
4951 +
4952 +/*************************************************
4953 +*         Match from current position            *
4954 +*************************************************/
4955 +
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
4959 +strings.
4960 +
4961 +Arguments:
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
4969 +   flags       can contain
4970 +                 match_condassert - this is an assertion condition
4971 +                 match_isgroup - this is the start of a bracketed group
4972 +
4973 +Returns:       TRUE if matched
4974 +*/
4975 +
4976 +static BOOL
4977 +match(register const uschar *eptr, register const uschar *ecode,
4978 +  int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
4979 +  int flags)
4980 +{
4981 +unsigned long int original_ims = ims;   /* Save for resetting on ')' */
4982 +eptrblock newptrb;
4983 +
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
4987 +the stack. */
4988 +
4989 +if ((flags & match_isgroup) != 0)
4990 +  {
4991 +  newptrb.prev = eptrb;
4992 +  newptrb.saved_eptr = eptr;
4993 +  eptrb = &newptrb;
4994 +  }
4995 +
4996 +/* Now start processing the operations. */
4997 +
4998 +for (;;)
4999 +  {
5000 +  int op = (int)*ecode;
5001 +  int min, max, ctype;
5002 +  register int i;
5003 +  register int c;
5004 +  BOOL minimize = FALSE;
5005 +
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
5010 +  inside the group.
5011 +
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
5014 +  the same bracket.
5015 +
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. */
5019 +
5020 +  if (op > OP_BRA)
5021 +    {
5022 +    int offset;
5023 +    int number = op - OP_BRA;
5024 +
5025 +    /* For extended extraction brackets (large number), we have to fish out the
5026 +    number from a dummy opcode at the start. */
5027 +
5028 +    if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5];
5029 +    offset = number << 1;
5030 +
5031 +#ifdef DEBUG
5032 +    PCRE_PRINTF("start bracket %d subject=", number);
5033 +    pchars(eptr, 16, TRUE, md);
5034 +    PCRE_PRINTF("\n");
5035 +#endif
5036 +
5037 +    if (offset < md->offset_max)
5038 +      {
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];
5042 +
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;
5045 +
5046 +      do
5047 +        {
5048 +        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
5049 +          return TRUE;
5050 +        ecode += (ecode[1] << 8) + ecode[2];
5051 +        }
5052 +      while (*ecode == OP_ALT);
5053 +
5054 +      DPRINTF(("bracket %d failed\n", number));
5055 +
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;
5059 +
5060 +      return FALSE;
5061 +      }
5062 +
5063 +    /* Insufficient room for saving captured contents */
5064 +
5065 +    else op = OP_BRA;
5066 +    }
5067 +
5068 +  /* Other types of node can be handled by a switch */
5069 +
5070 +  switch(op)
5071 +    {
5072 +    case OP_BRA:     /* Non-capturing bracket: optimized */
5073 +    DPRINTF(("start bracket 0\n"));
5074 +    do
5075 +      {
5076 +      if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
5077 +        return TRUE;
5078 +      ecode += (ecode[1] << 8) + ecode[2];
5079 +      }
5080 +    while (*ecode == OP_ALT);
5081 +    DPRINTF(("bracket 0 failed\n"));
5082 +    return FALSE;
5083 +
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. */
5088 +
5089 +    case OP_COND:
5090 +    if (ecode[3] == OP_CREF)         /* Condition is extraction test */
5091 +      {
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);
5097 +      }
5098 +
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. */
5101 +
5102 +    else
5103 +      {
5104 +      if (match(eptr, ecode+3, offset_top, md, ims, NULL,
5105 +          match_condassert | match_isgroup))
5106 +        {
5107 +        ecode += 3 + (ecode[4] << 8) + ecode[5];
5108 +        while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
5109 +        }
5110 +      else ecode += (ecode[1] << 8) + ecode[2];
5111 +      return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
5112 +      }
5113 +    /* Control never reaches here */
5114 +
5115 +    /* Skip over conditional reference or large extraction number data if
5116 +    encountered. */
5117 +
5118 +    case OP_CREF:
5119 +    case OP_BRANUMBER:
5120 +    ecode += 3;
5121 +    break;
5122 +
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. */
5125 +
5126 +    case OP_END:
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 */
5130 +    return TRUE;
5131 +
5132 +    /* Change option settings */
5133 +
5134 +    case OP_OPT:
5135 +    ims = ecode[1];
5136 +    ecode += 2;
5137 +    DPRINTF(("ims set to %02lx\n", ims));
5138 +    break;
5139 +
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. */
5145 +
5146 +    case OP_ASSERT:
5147 +    case OP_ASSERTBACK:
5148 +    do
5149 +      {
5150 +      if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break;
5151 +      ecode += (ecode[1] << 8) + ecode[2];
5152 +      }
5153 +    while (*ecode == OP_ALT);
5154 +    if (*ecode == OP_KET) return FALSE;
5155 +
5156 +    /* If checking an assertion for a condition, return TRUE. */
5157 +
5158 +    if ((flags & match_condassert) != 0) return TRUE;
5159 +
5160 +    /* Continue from after the assertion, updating the offsets high water
5161 +    mark, since extracts may have been taken during the assertion. */
5162 +
5163 +    do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
5164 +    ecode += 3;
5165 +    offset_top = md->end_offset_top;
5166 +    continue;
5167 +
5168 +    /* Negative assertion: all branches must fail to match */
5169 +
5170 +    case OP_ASSERT_NOT:
5171 +    case OP_ASSERTBACK_NOT:
5172 +    do
5173 +      {
5174 +      if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup))
5175 +        return FALSE;
5176 +      ecode += (ecode[1] << 8) + ecode[2];
5177 +      }
5178 +    while (*ecode == OP_ALT);
5179 +
5180 +    if ((flags & match_condassert) != 0) return TRUE;
5181 +
5182 +    ecode += 3;
5183 +    continue;
5184 +
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. */
5189 +
5190 +    case OP_REVERSE:
5191 +#ifdef SUPPORT_UTF8
5192 +    c = (ecode[1] << 8) + ecode[2];
5193 +    for (i = 0; i < c; i++)
5194 +      {
5195 +      eptr--;
5196 +      BACKCHAR(eptr)
5197 +      }
5198 +#else
5199 +    eptr -= (ecode[1] << 8) + ecode[2];
5200 +#endif
5201 +
5202 +    if (eptr < md->start_subject) return FALSE;
5203 +    ecode += 3;
5204 +    break;
5205 +
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
5216 +    may be wrong. */
5217 +
5218 +    case OP_RECURSE:
5219 +      {
5220 +      BOOL rc;
5221 +      int *save;
5222 +      int stacksave[15];
5223 +
5224 +      c = md->offset_max;
5225 +
5226 +      if (c < 16) save = stacksave; else
5227 +        {
5228 +        save = (int *)(pcre_malloc)((c+1) * sizeof(int));
5229 +        if (save == NULL)
5230 +          {
5231 +          save = stacksave;
5232 +          c = 15;
5233 +          }
5234 +        }
5235 +
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,
5239 +        match_isgroup);
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;
5244 +
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. */
5248 +
5249 +      offset_top = md->end_offset_top;
5250 +      eptr = md->end_match_ptr;
5251 +      ecode++;
5252 +      }
5253 +    break;
5254 +
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
5260 +    pointer. */
5261 +
5262 +    case OP_ONCE:
5263 +      {
5264 +      const uschar *prev = ecode;
5265 +      const uschar *saved_eptr = eptr;
5266 +
5267 +      do
5268 +        {
5269 +        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
5270 +          break;
5271 +        ecode += (ecode[1] << 8) + ecode[2];
5272 +        }
5273 +      while (*ecode == OP_ALT);
5274 +
5275 +      /* If hit the end of the group (which could be repeated), fail */
5276 +
5277 +      if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
5278 +
5279 +      /* Continue as from after the assertion, updating the offsets high water
5280 +      mark, since extracts may have been taken. */
5281 +
5282 +      do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
5283 +
5284 +      offset_top = md->end_offset_top;
5285 +      eptr = md->end_match_ptr;
5286 +
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. */
5292 +
5293 +      if (*ecode == OP_KET || eptr == saved_eptr)
5294 +        {
5295 +        ecode += 3;
5296 +        break;
5297 +        }
5298 +
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
5302 +      opcode. */
5303 +
5304 +      if (ecode[3] == OP_OPT)
5305 +        {
5306 +        ims = (ims & ~PCRE_IMS) | ecode[4];
5307 +        DPRINTF(("ims set to %02lx at group repeat\n", ims));
5308 +        }
5309 +
5310 +      if (*ecode == OP_KETRMIN)
5311 +        {
5312 +        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
5313 +            match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
5314 +              return TRUE;
5315 +        }
5316 +      else  /* OP_KETRMAX */
5317 +        {
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;
5320 +        }
5321 +      }
5322 +    return FALSE;
5323 +
5324 +    /* An alternation is the end of a branch; scan along to find the end of the
5325 +    bracketed group and go to there. */
5326 +
5327 +    case OP_ALT:
5328 +    do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
5329 +    break;
5330 +
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. */
5336 +
5337 +    case OP_BRAZERO:
5338 +      {
5339 +      const uschar *next = ecode+1;
5340 +      if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup))
5341 +        return TRUE;
5342 +      do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
5343 +      ecode = next + 3;
5344 +      }
5345 +    break;
5346 +
5347 +    case OP_BRAMINZERO:
5348 +      {
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))
5352 +        return TRUE;
5353 +      ecode++;
5354 +      }
5355 +    break;
5356 +
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. */
5361 +
5362 +    case OP_KET:
5363 +    case OP_KETRMIN:
5364 +    case OP_KETRMAX:
5365 +      {
5366 +      const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
5367 +      const uschar *saved_eptr = eptrb->saved_eptr;
5368 +
5369 +      eptrb = eptrb->prev;    /* Back up the stack of bracket start pointers */
5370 +
5371 +      if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
5372 +          *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
5373 +          *prev == OP_ONCE)
5374 +        {
5375 +        md->end_match_ptr = eptr;      /* For ONCE */
5376 +        md->end_offset_top = offset_top;
5377 +        return TRUE;
5378 +        }
5379 +
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. */
5383 +
5384 +      if (*prev != OP_COND)
5385 +        {
5386 +        int offset;
5387 +        int number = *prev - OP_BRA;
5388 +
5389 +        /* For extended extraction brackets (large number), we have to fish out
5390 +        the number from a dummy opcode at the start. */
5391 +
5392 +        if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5];
5393 +        offset = number << 1;
5394 +
5395 +#ifdef DEBUG
5396 +        PCRE_PRINTF("end bracket %d", number);
5397 +        PCRE_PRINTF("\n");
5398 +#endif
5399 +
5400 +        if (number > 0)
5401 +          {
5402 +          if (offset >= md->offset_max) md->offset_overflow = TRUE; else
5403 +            {
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;
5408 +            }
5409 +          }
5410 +        }
5411 +
5412 +      /* Reset the value of the ims flags, in case they got changed during
5413 +      the group. */
5414 +
5415 +      ims = original_ims;
5416 +      DPRINTF(("ims reset to %02lx\n", ims));
5417 +
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. */
5423 +
5424 +      if (*ecode == OP_KET || eptr == saved_eptr)
5425 +        {
5426 +        ecode += 3;
5427 +        break;
5428 +        }
5429 +
5430 +      /* The repeating kets try the rest of the pattern or restart from the
5431 +      preceding bracket, in the appropriate order. */
5432 +
5433 +      if (*ecode == OP_KETRMIN)
5434 +        {
5435 +        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
5436 +            match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
5437 +              return TRUE;
5438 +        }
5439 +      else  /* OP_KETRMAX */
5440 +        {
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;
5443 +        }
5444 +      }
5445 +    return FALSE;
5446 +
5447 +    /* Start of subject unless notbol, or after internal newline if multiline */
5448 +
5449 +    case OP_CIRC:
5450 +    if (md->notbol && eptr == md->start_subject) return FALSE;
5451 +    if ((ims & PCRE_MULTILINE) != 0)
5452 +      {
5453 +      if (eptr != md->start_subject && eptr[-1] != NEWLINE) return FALSE;
5454 +      ecode++;
5455 +      break;
5456 +      }
5457 +    /* ... else fall through */
5458 +
5459 +    /* Start of subject assertion */
5460 +
5461 +    case OP_SOD:
5462 +    if (eptr != md->start_subject) return FALSE;
5463 +    ecode++;
5464 +    break;
5465 +
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. */
5468 +
5469 +    case OP_DOLL:
5470 +    if ((ims & PCRE_MULTILINE) != 0)
5471 +      {
5472 +      if (eptr < md->end_subject) { if (*eptr != NEWLINE) return FALSE; }
5473 +        else { if (md->noteol) return FALSE; }
5474 +      ecode++;
5475 +      break;
5476 +      }
5477 +    else
5478 +      {
5479 +      if (md->noteol) return FALSE;
5480 +      if (!md->endonly)
5481 +        {
5482 +        if (eptr < md->end_subject - 1 ||
5483 +           (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
5484 +
5485 +        ecode++;
5486 +        break;
5487 +        }
5488 +      }
5489 +    /* ... else fall through */
5490 +
5491 +    /* End of subject assertion (\z) */
5492 +
5493 +    case OP_EOD:
5494 +    if (eptr < md->end_subject) return FALSE;
5495 +    ecode++;
5496 +    break;
5497 +
5498 +    /* End of subject or ending \n assertion (\Z) */
5499 +
5500 +    case OP_EODN:
5501 +    if (eptr < md->end_subject - 1 ||
5502 +       (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
5503 +    ecode++;
5504 +    break;
5505 +
5506 +    /* Word boundary assertions */
5507 +
5508 +    case OP_NOT_WORD_BOUNDARY:
5509 +    case OP_WORD_BOUNDARY:
5510 +      {
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)
5517 +        return FALSE;
5518 +      }
5519 +    break;
5520 +
5521 +    /* Match a single character type; inline for speed */
5522 +
5523 +    case OP_ANY:
5524 +    if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE)
5525 +      return FALSE;
5526 +    if (eptr++ >= md->end_subject) return FALSE;
5527 +#ifdef SUPPORT_UTF8
5528 +    if (md->utf8)
5529 +      while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
5530 +#endif
5531 +    ecode++;
5532 +    break;
5533 +
5534 +    case OP_NOT_DIGIT:
5535 +    if (eptr >= md->end_subject ||
5536 +       (md->ctypes[*eptr++] & ctype_digit) != 0)
5537 +      return FALSE;
5538 +    ecode++;
5539 +    break;
5540 +
5541 +    case OP_DIGIT:
5542 +    if (eptr >= md->end_subject ||
5543 +       (md->ctypes[*eptr++] & ctype_digit) == 0)
5544 +      return FALSE;
5545 +    ecode++;
5546 +    break;
5547 +
5548 +    case OP_NOT_WHITESPACE:
5549 +    if (eptr >= md->end_subject ||
5550 +       (md->ctypes[*eptr++] & ctype_space) != 0)
5551 +      return FALSE;
5552 +    ecode++;
5553 +    break;
5554 +
5555 +    case OP_WHITESPACE:
5556 +    if (eptr >= md->end_subject ||
5557 +       (md->ctypes[*eptr++] & ctype_space) == 0)
5558 +      return FALSE;
5559 +    ecode++;
5560 +    break;
5561 +
5562 +    case OP_NOT_WORDCHAR:
5563 +    if (eptr >= md->end_subject ||
5564 +       (md->ctypes[*eptr++] & ctype_word) != 0)
5565 +      return FALSE;
5566 +    ecode++;
5567 +    break;
5568 +
5569 +    case OP_WORDCHAR:
5570 +    if (eptr >= md->end_subject ||
5571 +       (md->ctypes[*eptr++] & ctype_word) == 0)
5572 +      return FALSE;
5573 +    ecode++;
5574 +    break;
5575 +
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
5582 +    loops). */
5583 +
5584 +    case OP_REF:
5585 +      {
5586 +      int length;
5587 +      int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */
5588 +      ecode += 3;                                     /* Advance past item */
5589 +
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
5593 +      minima. */
5594 +
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];
5598 +
5599 +      /* Set up for repetition, or handle the non-repeated case */
5600 +
5601 +      switch (*ecode)
5602 +        {
5603 +        case OP_CRSTAR:
5604 +        case OP_CRMINSTAR:
5605 +        case OP_CRPLUS:
5606 +        case OP_CRMINPLUS:
5607 +        case OP_CRQUERY:
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;
5614 +        break;
5615 +
5616 +        case OP_CRRANGE:
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;
5622 +        ecode += 5;
5623 +        break;
5624 +
5625 +        default:               /* No repeat follows */
5626 +        if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
5627 +        eptr += length;
5628 +        continue;              /* With the main loop */
5629 +        }
5630 +
5631 +      /* If the length of the reference is zero, just continue with the
5632 +      main loop. */
5633 +
5634 +      if (length == 0) continue;
5635 +
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. */
5639 +
5640 +      for (i = 1; i <= min; i++)
5641 +        {
5642 +        if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
5643 +        eptr += length;
5644 +        }
5645 +
5646 +      /* If min = max, continue at the same level without recursion.
5647 +      They are not both allowed to be zero. */
5648 +
5649 +      if (min == max) continue;
5650 +
5651 +      /* If minimizing, keep trying and advancing the pointer */
5652 +
5653 +      if (minimize)
5654 +        {
5655 +        for (i = min;; i++)
5656 +          {
5657 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5658 +            return TRUE;
5659 +          if (i >= max || !match_ref(offset, eptr, length, md, ims))
5660 +            return FALSE;
5661 +          eptr += length;
5662 +          }
5663 +        /* Control never gets here */
5664 +        }
5665 +
5666 +      /* If maximizing, find the longest string and work backwards */
5667 +
5668 +      else
5669 +        {
5670 +        const uschar *pp = eptr;
5671 +        for (i = min; i < max; i++)
5672 +          {
5673 +          if (!match_ref(offset, eptr, length, md, ims)) break;
5674 +          eptr += length;
5675 +          }
5676 +        while (eptr >= pp)
5677 +          {
5678 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5679 +            return TRUE;
5680 +          eptr -= length;
5681 +          }
5682 +        return FALSE;
5683 +        }
5684 +      }
5685 +    /* Control never gets here */
5686 +
5687 +
5688 +
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. */
5692 +
5693 +    case OP_CLASS:
5694 +      {
5695 +      const uschar *data = ecode + 1;  /* Save for matching */
5696 +      ecode += 33;                     /* Advance past the item */
5697 +
5698 +      switch (*ecode)
5699 +        {
5700 +        case OP_CRSTAR:
5701 +        case OP_CRMINSTAR:
5702 +        case OP_CRPLUS:
5703 +        case OP_CRMINPLUS:
5704 +        case OP_CRQUERY:
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;
5711 +        break;
5712 +
5713 +        case OP_CRRANGE:
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;
5719 +        ecode += 5;
5720 +        break;
5721 +
5722 +        default:               /* No repeat follows */
5723 +        min = max = 1;
5724 +        break;
5725 +        }
5726 +
5727 +      /* First, ensure the minimum number of matches are present. */
5728 +
5729 +      for (i = 1; i <= min; i++)
5730 +        {
5731 +        if (eptr >= md->end_subject) return FALSE;
5732 +        GETCHARINC(c, eptr)         /* Get character; increment eptr */
5733 +
5734 +#ifdef SUPPORT_UTF8
5735 +        /* We do not yet support class members > 255 */
5736 +        if (c > 255) return FALSE;
5737 +#endif
5738 +
5739 +        if ((data[c/8] & (1 << (c&7))) != 0) continue;
5740 +        return FALSE;
5741 +        }
5742 +
5743 +      /* If max == min we can continue with the main loop without the
5744 +      need to recurse. */
5745 +
5746 +      if (min == max) continue;
5747 +
5748 +      /* If minimizing, keep testing the rest of the expression and advancing
5749 +      the pointer while it matches the class. */
5750 +
5751 +      if (minimize)
5752 +        {
5753 +        for (i = min;; i++)
5754 +          {
5755 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5756 +            return TRUE;
5757 +          if (i >= max || eptr >= md->end_subject) return FALSE;
5758 +          GETCHARINC(c, eptr)       /* Get character; increment eptr */
5759 +
5760 +#ifdef SUPPORT_UTF8
5761 +          /* We do not yet support class members > 255 */
5762 +          if (c > 255) return FALSE;
5763 +#endif
5764 +          if ((data[c/8] & (1 << (c&7))) != 0) continue;
5765 +          return FALSE;
5766 +          }
5767 +        /* Control never gets here */
5768 +        }
5769 +
5770 +      /* If maximizing, find the longest possible run, then work backwards. */
5771 +
5772 +      else
5773 +        {
5774 +        const uschar *pp = eptr;
5775 +        int len = 1;
5776 +        for (i = min; i < max; i++)
5777 +          {
5778 +          if (eptr >= md->end_subject) break;
5779 +          GETCHARLEN(c, eptr, len)  /* Get character, set length if UTF-8 */
5780 +
5781 +#ifdef SUPPORT_UTF8
5782 +          /* We do not yet support class members > 255 */
5783 +          if (c > 255) break;
5784 +#endif
5785 +          if ((data[c/8] & (1 << (c&7))) == 0) break;
5786 +          eptr += len;
5787 +          }
5788 +
5789 +        while (eptr >= pp)
5790 +          {
5791 +          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
5792 +            return TRUE;
5793 +
5794 +#ifdef SUPPORT_UTF8
5795 +          BACKCHAR(eptr)
5796 +#endif
5797 +          }
5798 +        return FALSE;
5799 +        }
5800 +      }
5801 +    /* Control never gets here */
5802 +
5803 +    /* Match a run of characters */
5804 +
5805 +    case OP_CHARS:
5806 +      {
5807 +      register int length = ecode[1];
5808 +      ecode += 2;
5809 +
5810 +#ifdef DEBUG    /* Sigh. Some compilers never learn. */
5811 +      if (eptr >= md->end_subject)
5812 +        PCRE_PRINTF("matching subject <null> against pattern ");
5813 +      else
5814 +        {
5815 +        PCRE_PRINTF("matching subject ");
5816 +        pchars(eptr, length, TRUE, md);
5817 +        PCRE_PRINTF(" against pattern ");
5818 +        }
5819 +      pchars(ecode, length, FALSE, md);
5820 +      PCRE_PRINTF("\n");
5821 +#endif
5822 +
5823 +      if (length > md->end_subject - eptr) return FALSE;
5824 +      if ((ims & PCRE_CASELESS) != 0)
5825 +        {
5826 +        while (length-- > 0)
5827 +          if (md->lcc[*ecode++] != md->lcc[*eptr++])
5828 +            return FALSE;
5829 +        }
5830 +      else
5831 +        {
5832 +        while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
5833 +        }
5834 +      }
5835 +    break;
5836 +
5837 +    /* Match a single character repeatedly; different opcodes share code. */
5838 +
5839 +    case OP_EXACT:
5840 +    min = max = (ecode[1] << 8) + ecode[2];
5841 +    ecode += 3;
5842 +    goto REPEATCHAR;
5843 +
5844 +    case OP_UPTO:
5845 +    case OP_MINUPTO:
5846 +    min = 0;
5847 +    max = (ecode[1] << 8) + ecode[2];
5848 +    minimize = *ecode == OP_MINUPTO;
5849 +    ecode += 3;
5850 +    goto REPEATCHAR;
5851 +
5852 +    case OP_STAR:
5853 +    case OP_MINSTAR:
5854 +    case OP_PLUS:
5855 +    case OP_MINPLUS:
5856 +    case OP_QUERY:
5857 +    case OP_MINQUERY:
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;
5863 +
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
5866 +    the subject. */
5867 +
5868 +    REPEATCHAR:
5869 +    if (min > md->end_subject - eptr) return FALSE;
5870 +    c = *ecode++;
5871 +
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. */
5879 +
5880 +    DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
5881 +      max, eptr));
5882 +
5883 +    if ((ims & PCRE_CASELESS) != 0)
5884 +      {
5885 +      c = md->lcc[c];
5886 +      for (i = 1; i <= min; i++)
5887 +        if (c != md->lcc[*eptr++]) return FALSE;
5888 +      if (min == max) continue;
5889 +      if (minimize)
5890 +        {
5891 +        for (i = min;; i++)
5892 +          {
5893 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5894 +            return TRUE;
5895 +          if (i >= max || eptr >= md->end_subject ||
5896 +              c != md->lcc[*eptr++])
5897 +            return FALSE;
5898 +          }
5899 +        /* Control never gets here */
5900 +        }
5901 +      else
5902 +        {
5903 +        const uschar *pp = eptr;
5904 +        for (i = min; i < max; i++)
5905 +          {
5906 +          if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
5907 +          eptr++;
5908 +          }
5909 +        while (eptr >= pp)
5910 +          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
5911 +            return TRUE;
5912 +        return FALSE;
5913 +        }
5914 +      /* Control never gets here */
5915 +      }
5916 +
5917 +    /* Caseful comparisons */
5918 +
5919 +    else
5920 +      {
5921 +      for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
5922 +      if (min == max) continue;
5923 +      if (minimize)
5924 +        {
5925 +        for (i = min;; i++)
5926 +          {
5927 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
5928 +            return TRUE;
5929 +          if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
5930 +          }
5931 +        /* Control never gets here */
5932 +        }
5933 +      else
5934 +        {
5935 +        const uschar *pp = eptr;
5936 +        for (i = min; i < max; i++)
5937 +          {
5938 +          if (eptr >= md->end_subject || c != *eptr) break;
5939 +          eptr++;
5940 +          }
5941 +        while (eptr >= pp)
5942 +         if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
5943 +           return TRUE;
5944 +        return FALSE;
5945 +        }
5946 +      }
5947 +    /* Control never gets here */
5948 +
5949 +    /* Match a negated single character */
5950 +
5951 +    case OP_NOT:
5952 +    if (eptr >= md->end_subject) return FALSE;
5953 +    ecode++;
5954 +    if ((ims & PCRE_CASELESS) != 0)
5955 +      {
5956 +      if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
5957 +      }
5958 +    else
5959 +      {
5960 +      if (*ecode++ == *eptr++) return FALSE;
5961 +      }
5962 +    break;
5963 +
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... */
5969 +
5970 +    case OP_NOTEXACT:
5971 +    min = max = (ecode[1] << 8) + ecode[2];
5972 +    ecode += 3;
5973 +    goto REPEATNOTCHAR;
5974 +
5975 +    case OP_NOTUPTO:
5976 +    case OP_NOTMINUPTO:
5977 +    min = 0;
5978 +    max = (ecode[1] << 8) + ecode[2];
5979 +    minimize = *ecode == OP_NOTMINUPTO;
5980 +    ecode += 3;
5981 +    goto REPEATNOTCHAR;
5982 +
5983 +    case OP_NOTSTAR:
5984 +    case OP_NOTMINSTAR:
5985 +    case OP_NOTPLUS:
5986 +    case OP_NOTMINPLUS:
5987 +    case OP_NOTQUERY:
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;
5994 +
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
5997 +    the subject. */
5998 +
5999 +    REPEATNOTCHAR:
6000 +    if (min > md->end_subject - eptr) return FALSE;
6001 +    c = *ecode++;
6002 +
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. */
6010 +
6011 +    DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
6012 +      max, eptr));
6013 +
6014 +    if ((ims & PCRE_CASELESS) != 0)
6015 +      {
6016 +      c = md->lcc[c];
6017 +      for (i = 1; i <= min; i++)
6018 +        if (c == md->lcc[*eptr++]) return FALSE;
6019 +      if (min == max) continue;
6020 +      if (minimize)
6021 +        {
6022 +        for (i = min;; i++)
6023 +          {
6024 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
6025 +            return TRUE;
6026 +          if (i >= max || eptr >= md->end_subject ||
6027 +              c == md->lcc[*eptr++])
6028 +            return FALSE;
6029 +          }
6030 +        /* Control never gets here */
6031 +        }
6032 +      else
6033 +        {
6034 +        const uschar *pp = eptr;
6035 +        for (i = min; i < max; i++)
6036 +          {
6037 +          if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
6038 +          eptr++;
6039 +          }
6040 +        while (eptr >= pp)
6041 +          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
6042 +            return TRUE;
6043 +        return FALSE;
6044 +        }
6045 +      /* Control never gets here */
6046 +      }
6047 +
6048 +    /* Caseful comparisons */
6049 +
6050 +    else
6051 +      {
6052 +      for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
6053 +      if (min == max) continue;
6054 +      if (minimize)
6055 +        {
6056 +        for (i = min;; i++)
6057 +          {
6058 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
6059 +            return TRUE;
6060 +          if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
6061 +          }
6062 +        /* Control never gets here */
6063 +        }
6064 +      else
6065 +        {
6066 +        const uschar *pp = eptr;
6067 +        for (i = min; i < max; i++)
6068 +          {
6069 +          if (eptr >= md->end_subject || c == *eptr) break;
6070 +          eptr++;
6071 +          }
6072 +        while (eptr >= pp)
6073 +         if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
6074 +           return TRUE;
6075 +        return FALSE;
6076 +        }
6077 +      }
6078 +    /* Control never gets here */
6079 +
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. */
6083 +
6084 +    case OP_TYPEEXACT:
6085 +    min = max = (ecode[1] << 8) + ecode[2];
6086 +    minimize = TRUE;
6087 +    ecode += 3;
6088 +    goto REPEATTYPE;
6089 +
6090 +    case OP_TYPEUPTO:
6091 +    case OP_TYPEMINUPTO:
6092 +    min = 0;
6093 +    max = (ecode[1] << 8) + ecode[2];
6094 +    minimize = *ecode == OP_TYPEMINUPTO;
6095 +    ecode += 3;
6096 +    goto REPEATTYPE;
6097 +
6098 +    case OP_TYPESTAR:
6099 +    case OP_TYPEMINSTAR:
6100 +    case OP_TYPEPLUS:
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;
6109 +
6110 +    /* Common code for all repeated single character type matches */
6111 +
6112 +    REPEATTYPE:
6113 +    ctype = *ecode++;      /* Code for the character type */
6114 +
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. */
6121 +
6122 +    if (min > md->end_subject - eptr) return FALSE;
6123 +    if (min > 0) switch(ctype)
6124 +      {
6125 +      case OP_ANY:
6126 +#ifdef SUPPORT_UTF8
6127 +      if (md->utf8)
6128 +        {
6129 +        for (i = 1; i <= min; i++)
6130 +          {
6131 +          if (eptr >= md->end_subject ||
6132 +             (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0))
6133 +            return FALSE;
6134 +          while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
6135 +          }
6136 +        break;
6137 +        }
6138 +#endif
6139 +      /* Non-UTF8 can be faster */
6140 +      if ((ims & PCRE_DOTALL) == 0)
6141 +        { for (i = 1; i <= min; i++) if (*eptr++ == NEWLINE) return FALSE; }
6142 +      else eptr += min;
6143 +      break;
6144 +
6145 +      case OP_NOT_DIGIT:
6146 +      for (i = 1; i <= min; i++)
6147 +        if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
6148 +      break;
6149 +
6150 +      case OP_DIGIT:
6151 +      for (i = 1; i <= min; i++)
6152 +        if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
6153 +      break;
6154 +
6155 +      case OP_NOT_WHITESPACE:
6156 +      for (i = 1; i <= min; i++)
6157 +        if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
6158 +      break;
6159 +
6160 +      case OP_WHITESPACE:
6161 +      for (i = 1; i <= min; i++)
6162 +        if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
6163 +      break;
6164 +
6165 +      case OP_NOT_WORDCHAR:
6166 +      for (i = 1; i <= min; i++)
6167 +        if ((md->ctypes[*eptr++] & ctype_word) != 0)
6168 +          return FALSE;
6169 +      break;
6170 +
6171 +      case OP_WORDCHAR:
6172 +      for (i = 1; i <= min; i++)
6173 +        if ((md->ctypes[*eptr++] & ctype_word) == 0)
6174 +          return FALSE;
6175 +      break;
6176 +      }
6177 +
6178 +    /* If min = max, continue at the same level without recursing */
6179 +
6180 +    if (min == max) continue;
6181 +
6182 +    /* If minimizing, we have to test the rest of the pattern before each
6183 +    subsequent match. */
6184 +
6185 +    if (minimize)
6186 +      {
6187 +      for (i = min;; i++)
6188 +        {
6189 +        if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE;
6190 +        if (i >= max || eptr >= md->end_subject) return FALSE;
6191 +
6192 +        c = *eptr++;
6193 +        switch(ctype)
6194 +          {
6195 +          case OP_ANY:
6196 +          if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return FALSE;
6197 +#ifdef SUPPORT_UTF8
6198 +          if (md->utf8)
6199 +            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
6200 +#endif
6201 +          break;
6202 +
6203 +          case OP_NOT_DIGIT:
6204 +          if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
6205 +          break;
6206 +
6207 +          case OP_DIGIT:
6208 +          if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
6209 +          break;
6210 +
6211 +          case OP_NOT_WHITESPACE:
6212 +          if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
6213 +          break;
6214 +
6215 +          case OP_WHITESPACE:
6216 +          if  ((md->ctypes[c] & ctype_space) == 0) return FALSE;
6217 +          break;
6218 +
6219 +          case OP_NOT_WORDCHAR:
6220 +          if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
6221 +          break;
6222 +
6223 +          case OP_WORDCHAR:
6224 +          if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
6225 +          break;
6226 +          }
6227 +        }
6228 +      /* Control never gets here */
6229 +      }
6230 +
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). */
6233 +
6234 +    else
6235 +      {
6236 +      const uschar *pp = eptr;
6237 +      switch(ctype)
6238 +        {
6239 +        case OP_ANY:
6240 +
6241 +        /* Special code is required for UTF8, but when the maximum is unlimited
6242 +        we don't need it. */
6243 +
6244 +#ifdef SUPPORT_UTF8
6245 +        if (md->utf8 && max < INT_MAX)
6246 +          {
6247 +          if ((ims & PCRE_DOTALL) == 0)
6248 +            {
6249 +            for (i = min; i < max; i++)
6250 +              {
6251 +              if (eptr >= md->end_subject || *eptr++ == NEWLINE) break;
6252 +              while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
6253 +              }
6254 +            }
6255 +          else
6256 +            {
6257 +            for (i = min; i < max; i++)
6258 +              {
6259 +              eptr++;
6260 +              while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
6261 +              }
6262 +            }
6263 +          break;
6264 +          }
6265 +#endif
6266 +        /* Non-UTF8 can be faster */
6267 +        if ((ims & PCRE_DOTALL) == 0)
6268 +          {
6269 +          for (i = min; i < max; i++)
6270 +            {
6271 +            if (eptr >= md->end_subject || *eptr == NEWLINE) break;
6272 +            eptr++;
6273 +            }
6274 +          }
6275 +        else
6276 +          {
6277 +          c = max - min;
6278 +          if (c > md->end_subject - eptr) c = md->end_subject - eptr;
6279 +          eptr += c;
6280 +          }
6281 +        break;
6282 +
6283 +        case OP_NOT_DIGIT:
6284 +        for (i = min; i < max; i++)
6285 +          {
6286 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
6287 +            break;
6288 +          eptr++;
6289 +          }
6290 +        break;
6291 +
6292 +        case OP_DIGIT:
6293 +        for (i = min; i < max; i++)
6294 +          {
6295 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
6296 +            break;
6297 +          eptr++;
6298 +          }
6299 +        break;
6300 +
6301 +        case OP_NOT_WHITESPACE:
6302 +        for (i = min; i < max; i++)
6303 +          {
6304 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
6305 +            break;
6306 +          eptr++;
6307 +          }
6308 +        break;
6309 +
6310 +        case OP_WHITESPACE:
6311 +        for (i = min; i < max; i++)
6312 +          {
6313 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
6314 +            break;
6315 +          eptr++;
6316 +          }
6317 +        break;
6318 +
6319 +        case OP_NOT_WORDCHAR:
6320 +        for (i = min; i < max; i++)
6321 +          {
6322 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
6323 +            break;
6324 +          eptr++;
6325 +          }
6326 +        break;
6327 +
6328 +        case OP_WORDCHAR:
6329 +        for (i = min; i < max; i++)
6330 +          {
6331 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
6332 +            break;
6333 +          eptr++;
6334 +          }
6335 +        break;
6336 +        }
6337 +
6338 +      while (eptr >= pp)
6339 +        {
6340 +        if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
6341 +          return TRUE;
6342 +#ifdef SUPPORT_UTF8
6343 +        if (md->utf8)
6344 +          while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--;
6345 +#endif
6346 +        }
6347 +      return FALSE;
6348 +      }
6349 +    /* Control never gets here */
6350 +
6351 +    /* There's been some horrible disaster. */
6352 +
6353 +    default:
6354 +    DPRINTF(("Unknown opcode %d\n", *ecode));
6355 +    md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
6356 +    return FALSE;
6357 +    }
6358 +
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
6361 +  loop. */
6362 +
6363 +  }             /* End of main loop */
6364 +/* Control never reaches here */
6365 +}
6366 +
6367 +
6368 +/*************************************************
6369 +*         Execute a Regular Expression           *
6370 +*************************************************/
6371 +
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.
6375 +
6376 +Arguments:
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
6385 +
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
6390 +*/
6391 +
6392 +int
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,
6395 +  int offsetcount)
6396 +{
6397 +int resetcount, ocount;
6398 +int first_char = -1;
6399 +int req_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;
6410 +BOOL anchored;
6411 +BOOL startline;
6412 +
6413 +if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
6414 +
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;
6418 +
6419 +anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
6420 +startline = (re->options & PCRE_STARTLINE) != 0;
6421 +
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;
6426 +
6427 +match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
6428 +match_block.utf8 = (re->options & PCRE_UTF8) != 0;
6429 +
6430 +match_block.notbol = (options & PCRE_NOTBOL) != 0;
6431 +match_block.noteol = (options & PCRE_NOTEOL) != 0;
6432 +match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
6433 +
6434 +match_block.errorcode = PCRE_ERROR_NOMATCH;     /* Default error */
6435 +
6436 +match_block.lcc = re->tables + lcc_offset;
6437 +match_block.ctypes = re->tables + ctypes_offset;
6438 +
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. */
6442 +
6443 +ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
6444 +
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
6448 +of 3. */
6449 +
6450 +ocount = offsetcount - (offsetcount % 3);
6451 +
6452 +if (re->top_backref > 0 && re->top_backref >= ocount/3)
6453 +  {
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"));
6459 +  }
6460 +else match_block.offset_vector = offsets;
6461 +
6462 +match_block.offset_end = ocount;
6463 +match_block.offset_max = (2*ocount)/3;
6464 +match_block.offset_overflow = FALSE;
6465 +
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
6468 +in the pattern. */
6469 +
6470 +resetcount = 2 + re->top_bracket * 2;
6471 +if (resetcount > offsetcount) resetcount = ocount;
6472 +
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. */
6476 +
6477 +if (match_block.offset_vector != NULL)
6478 +  {
6479 +  register int *iptr = match_block.offset_vector + ocount;
6480 +  register int *iend = iptr - resetcount/2 + 1;
6481 +  while (--iptr >= iend) *iptr = -1;
6482 +  }
6483 +
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. */
6489 +
6490 +if (!anchored)
6491 +  {
6492 +  if ((re->options & PCRE_FIRSTSET) != 0)
6493 +    {
6494 +    first_char = re->first_char;
6495 +    if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
6496 +    }
6497 +  else
6498 +    if (!startline && extra != NULL &&
6499 +      (extra->options & PCRE_STUDY_MAPPED) != 0)
6500 +        start_bits = extra->start_bits;
6501 +  }
6502 +
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. */
6510 +
6511 +if ((re->options & PCRE_REQCHSET) != 0)
6512 +  {
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;
6516 +  }
6517 +
6518 +/* Loop for handling unanchored repeated matching attempts; for anchored regexs
6519 +the loop runs just once. */
6520 +
6521 +do
6522 +  {
6523 +  int rc;
6524 +  register int *iptr = match_block.offset_vector;
6525 +  register int *iend = iptr + resetcount;
6526 +
6527 +  /* Reset the maximum number of extractions we might see. */
6528 +
6529 +  while (iptr < iend) *iptr++ = -1;
6530 +
6531 +  /* Advance to a unique first char if possible */
6532 +
6533 +  if (first_char >= 0)
6534 +    {
6535 +    if ((ims & PCRE_CASELESS) != 0)
6536 +      while (start_match < end_subject &&
6537 +             match_block.lcc[*start_match] != first_char)
6538 +        start_match++;
6539 +    else
6540 +      while (start_match < end_subject && *start_match != first_char)
6541 +        start_match++;
6542 +    }
6543 +
6544 +  /* Or to just after \n for a multiline match if possible */
6545 +
6546 +  else if (startline)
6547 +    {
6548 +    if (start_match > match_block.start_subject + start_offset)
6549 +      {
6550 +      while (start_match < end_subject && start_match[-1] != NEWLINE)
6551 +        start_match++;
6552 +      }
6553 +    }
6554 +
6555 +  /* Or to a non-unique first char after study */
6556 +
6557 +  else if (start_bits != NULL)
6558 +    {
6559 +    while (start_match < end_subject)
6560 +      {
6561 +      register int c = *start_match;
6562 +      if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
6563 +      }
6564 +    }
6565 +
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");
6570 +#endif
6571 +
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. */
6582 +
6583 +  if (req_char >= 0)
6584 +    {
6585 +    register const uschar *p = start_match + ((first_char >= 0)? 1 : 0);
6586 +
6587 +    /* We don't need to repeat the search if we haven't yet reached the
6588 +    place we found it at last time. */
6589 +
6590 +    if (p > req_char_ptr)
6591 +      {
6592 +      /* Do a single test if no case difference is set up */
6593 +
6594 +      if (req_char == req_char2)
6595 +        {
6596 +        while (p < end_subject)
6597 +          {
6598 +          if (*p++ == req_char) { p--; break; }
6599 +          }
6600 +        }
6601 +
6602 +      /* Otherwise test for either case */
6603 +
6604 +      else
6605 +        {
6606 +        while (p < end_subject)
6607 +          {
6608 +          register int pp = *p++;
6609 +          if (pp == req_char || pp == req_char2) { p--; break; }
6610 +          }
6611 +        }
6612 +
6613 +      /* If we can't find the required character, break the matching loop */
6614 +
6615 +      if (p >= end_subject) break;
6616 +
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. */
6620 +
6621 +      req_char_ptr = p;
6622 +      }
6623 +    }
6624 +
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. */
6631 +
6632 +  match_block.start_match = start_match;
6633 +  if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
6634 +    continue;
6635 +
6636 +  /* Copy the offset information from temporary store if necessary */
6637 +
6638 +  if (using_temporary_offsets)
6639 +    {
6640 +    if (offsetcount >= 4)
6641 +      {
6642 +      memcpy(offsets + 2, match_block.offset_vector + 2,
6643 +        (offsetcount - 2) * sizeof(int));
6644 +      DPRINTF(("Copied offsets from temporary memory\n"));
6645 +      }
6646 +    if (match_block.end_offset_top > offsetcount)
6647 +      match_block.offset_overflow = TRUE;
6648 +
6649 +    DPRINTF(("Freeing temporary memory\n"));
6650 +    (pcre_free)(match_block.offset_vector);
6651 +    }
6652 +
6653 +  rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
6654 +
6655 +  if (offsetcount < 2) rc = 0; else
6656 +    {
6657 +    offsets[0] = start_match - match_block.start_subject;
6658 +    offsets[1] = match_block.end_match_ptr - match_block.start_subject;
6659 +    }
6660 +
6661 +  DPRINTF((">>>> returning %d\n", rc));
6662 +  return rc;
6663 +  }
6664 +
6665 +/* This "while" is the end of the "do" above */
6666 +
6667 +while (!anchored &&
6668 +       match_block.errorcode == PCRE_ERROR_NOMATCH &&
6669 +       start_match++ < end_subject);
6670 +
6671 +if (using_temporary_offsets)
6672 +  {
6673 +  DPRINTF(("Freeing temporary memory\n"));
6674 +  (pcre_free)(match_block.offset_vector);
6675 +  }
6676 +
6677 +DPRINTF((">>>> returning %d\n", match_block.errorcode));
6678 +
6679 +return match_block.errorcode;
6680 +}
6681 +
6682 +/* End of pcre.c */
6683 Index: b/security/apparmor/match/pcre_exec.h
6684 ===================================================================
6685 --- /dev/null
6686 +++ b/security/apparmor/match/pcre_exec.h
6687 @@ -0,0 +1,308 @@
6688 +/*
6689 + *  This is a modified header file containing the definitions from
6690 + *  pcre.h and internal.h required to support pcre_exec()
6691 + */
6692 +
6693 +
6694 +/*************************************************
6695 +*       Perl-Compatible Regular Expressions      *
6696 +*************************************************/
6697 +
6698 +/* Copyright (c) 1997-2001 University of Cambridge */
6699 +
6700 +#ifndef _PCRE_H
6701 +#define _PCRE_H
6702 +
6703 +/* ----- CODE ADDED ---- */
6704 +
6705 +#ifdef __KERNEL__
6706 +#include <linux/slab.h>        // for kmalloc/kfree
6707 +#endif
6708 +
6709 +#ifdef __KERNEL__
6710 +#define PCRE_PRINTF printk
6711 +#define isprint(x) ((unsigned char)(x) >= 128 && (unsigned char)(x) <= 255)
6712 +#else
6713 +#define PCRE_PRINTF printf
6714 +#endif
6715 +
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. */
6719 +
6720 +#ifndef NEWLINE
6721 +#define NEWLINE '\n'
6722 +#endif
6723 +
6724 +/* ----  CODE DELETED ---- */
6725 +
6726 +/* Options */
6727 +
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
6740 +
6741 +/* Exec-time and get-time error codes */
6742 +
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)
6750 +
6751 +/* ----  CODE DELETED ---- */
6752 +
6753 +/* Types */
6754 +
6755 +struct real_pcre;        /* declaration; the definition is private  */
6756 +struct real_pcre_extra;  /* declaration; the definition is private */
6757 +
6758 +typedef struct real_pcre pcre;
6759 +typedef struct real_pcre_extra pcre_extra;
6760 +
6761 +/* ----  CODE DELETED ---- */
6762 +
6763 +extern int pcre_exec(const pcre *, const pcre_extra *,
6764 +                    const char *, int, int, int, int *,
6765 +                    int);
6766 +
6767 +/* ----  CODE ADDED (from internal.h) ---- */
6768 +
6769 +/* These are the public options that can change during matching. */
6770 +
6771 +#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
6772 +
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. */
6778 +
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 */
6783 +
6784 +/* Options for the "extra" block produced by pcre_study(). */
6785 +
6786 +#define PCRE_STUDY_MAPPED   0x01     /* a map of starting chars exists */
6787 +
6788 +/* Masks for identifying the public options which are permitted at compile
6789 +time, run time or study time, respectively. */
6790 +
6791 +#define PUBLIC_EXEC_OPTIONS \
6792 +    (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
6793 +
6794 +/* Magic number to provide a small check against being handed junk. */
6795 +
6796 +#define MAGIC_NUMBER  0x50435245UL   /* 'PCRE' */
6797 +
6798 +typedef int BOOL;
6799 +
6800 +#define FALSE   0
6801 +#define TRUE    1
6802 +
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. */
6806 +
6807 +enum {
6808 +  OP_END,            /* End of pattern */
6809 +
6810 +  /* Values corresponding to backslashed metacharacters */
6811 +
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 */
6823 +
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 */
6830 +
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 */
6835 +  OP_QUERY,
6836 +  OP_MINQUERY,
6837 +  OP_UPTO,           /* From 0 to n matches */
6838 +  OP_MINUPTO,
6839 +  OP_EXACT,          /* Exactly n matches */
6840 +
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 */
6845 +  OP_NOTQUERY,
6846 +  OP_NOTMINQUERY,
6847 +  OP_NOTUPTO,        /* From 0 to n matches */
6848 +  OP_NOTMINUPTO,
6849 +  OP_NOTEXACT,       /* Exactly n matches */
6850 +
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 */
6856 +  OP_TYPEMINQUERY,
6857 +  OP_TYPEUPTO,       /* From 0 to n matches */
6858 +  OP_TYPEMINUPTO,
6859 +  OP_TYPEEXACT,      /* Exactly n matches */
6860 +
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 */
6866 +  OP_CRMINQUERY,
6867 +  OP_CRRANGE,        /* These are different to the three seta above. */
6868 +  OP_CRMINRANGE,
6869 +
6870 +  OP_CLASS,          /* Match a character class */
6871 +  OP_REF,            /* Match a back reference */
6872 +  OP_RECURSE,        /* Match this pattern recursively */
6873 +
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. */
6878 +
6879 +  /* The assertions must come before ONCE and COND */
6880 +
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 */
6886 +
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. */
6889 +
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) */
6893 +
6894 +  OP_BRAZERO,        /* These two must remain together and in this */
6895 +  OP_BRAMINZERO,     /* order. */
6896 +
6897 +  OP_BRANUMBER,      /* Used for extracting brackets whose number is greater
6898 +                        than can fit into an opcode. */
6899 +
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. */
6903 +};
6904 +
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
6909 +opcodes. */
6910 +
6911 +#define EXTRACT_BASIC_MAX  150
6912 +
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. */
6919 +
6920 +typedef unsigned char uschar;
6921 +
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. */
6924 +
6925 +typedef struct real_pcre {
6926 +  unsigned long int magic_number;
6927 +  size_t size;
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;
6933 +  uschar req_char;
6934 +  uschar code[1];
6935 +} real_pcre;
6936 +
6937 +/* The real format of the extra block returned by pcre_study(). */
6938 +
6939 +typedef struct real_pcre_extra {
6940 +  uschar options;
6941 +  uschar start_bits[32];
6942 +} real_pcre_extra;
6943 +
6944 +/* Structure for passing "static" information around between the functions
6945 +doing the matching, so that they are thread-safe. */
6946 +
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 */
6966 +} match_data;
6967 +
6968 +/* Bit definitions for entries in the pcre_ctypes table. */
6969 +
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) */
6976 +
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. */
6979 +
6980 +#define cbit_length  320      /* Length of the cbits table */
6981 +
6982 +/* Offsets of the various tables from the base tables pointer, and
6983 +total length. */
6984 +
6985 +#define lcc_offset      0
6986 +#define fcc_offset    256
6987 +
6988 +#define fcc_offset    256
6989 +#define cbits_offset  512
6990 +#define ctypes_offset (cbits_offset + cbit_length)
6991 +
6992 +/* ----- CODE ADDED ---- */
6993 +
6994 +#endif // _PCRE_H
6995 + /* End of pcre.h */
6996 Index: b/security/apparmor/match/pcre_tables.h
6997 ===================================================================
6998 --- /dev/null
6999 +++ b/security/apparmor/match/pcre_tables.h
7000 @@ -0,0 +1,184 @@
7001 +
7002 +/*************************************************
7003 +*      Perl-Compatible Regular Expressions       *
7004 +*************************************************/
7005 +
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.
7009 +
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
7012 +function. */
7013 +
7014 +static unsigned char pcre_default_tables[] = {
7015 +
7016 +/* This table is a lower casing table. */
7017 +
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,
7050 +
7051 +/* This table is a case flipping table. */
7052 +
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,
7085 +
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. */
7091 +
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,
7096 +
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,
7101 +
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,
7106 +
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,
7111 +
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,
7116 +
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,
7121 +
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,
7126 +
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,
7131 +
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,
7136 +
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,
7141 +
7142 +/* This table identifies various classes of character by individual bits:
7143 +  0x01   white space character
7144 +  0x02   letter
7145 +  0x04   decimal digit
7146 +  0x08   hexadecimal digit
7147 +  0x10   alphanumeric or '_'
7148 +  0x80   regular expression metacharacter or binary zero
7149 +*/
7150 +
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 */
7183 +
7184 +/* End of chartables.c */
7185 Index: b/security/apparmor/module_interface.c
7186 ===================================================================
7187 --- /dev/null
7188 +++ b/security/apparmor/module_interface.c
7189 @@ -0,0 +1,845 @@
7190 +/*
7191 + *     Copyright (C) 1998-2005 Novell/SUSE
7192 + *
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
7196 + *     License.
7197 + *
7198 + *     AppArmor userspace policy interface
7199 + */
7200 +
7201 +#include <asm/unaligned.h>
7202 +
7203 +#include "apparmor.h"
7204 +#include "inline.h"
7205 +#include "module_interface.h"
7206 +#include "match/match.h"
7207 +
7208 +/* aa_code defined in module_interface.h */
7209 +
7210 +const int aacode_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
7211 +
7212 +struct aa_taskreplace_data {
7213 +       struct aaprofile *old_profile;
7214 +       struct aaprofile *new_profile;
7215 +};
7216 +
7217 +/* inlines must be forward of there use in newer version of gcc,
7218 +   just forward declaring with a prototype won't work anymore */
7219 +
7220 +static inline void free_aa_entry(struct aa_entry *entry)
7221 +{
7222 +       if (entry) {
7223 +               kfree(entry->filename);
7224 +               aamatch_free(entry->extradata);
7225 +               kfree(entry);
7226 +       }
7227 +}
7228 +
7229 +/**
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.
7234 + */
7235 +static inline struct aa_entry *alloc_aa_entry(void)
7236 +{
7237 +       struct aa_entry *entry;
7238 +
7239 +       AA_DEBUG("%s\n", __FUNCTION__);
7240 +       entry = kzalloc(sizeof(struct aa_entry), GFP_KERNEL);
7241 +       if (entry) {
7242 +               int i;
7243 +               INIT_LIST_HEAD(&entry->list);
7244 +               for (i = 0; i <= POS_AA_FILE_MAX; i++) {
7245 +                       INIT_LIST_HEAD(&entry->listp[i]);
7246 +               }
7247 +       }
7248 +       return entry;
7249 +}
7250 +
7251 +/**
7252 + * free_aaprofile_rcu - rcu callback for free profiles
7253 + * @head: rcu_head struct of the profile whose reference is being put.
7254 + *
7255 + * the rcu callback routine, which delays the freeing of a profile when
7256 + * its last reference is put.
7257 + */
7258 +static void free_aaprofile_rcu(struct rcu_head *head)
7259 +{
7260 +       struct aaprofile *p = container_of(head, struct aaprofile, rcu);
7261 +       free_aaprofile(p);
7262 +}
7263 +
7264 +/**
7265 + * task_remove - remove profile from a task's subdomain
7266 + * @sd: task's subdomain
7267 + *
7268 + * remove the active profile from a task's subdomain, switching the task
7269 + * to an unconfined state.
7270 + */
7271 +static inline void task_remove(struct subdomain *sd)
7272 +{
7273 +       /* spin_lock(&sd_lock) held here */
7274 +       AA_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
7275 +                __FUNCTION__,
7276 +                sd->task->comm,
7277 +                sd->task->pid,
7278 +                BASE_PROFILE(sd->active)->name,
7279 +                sd->active->name);
7280 +
7281 +       aa_switch_unconfined(sd);
7282 +}
7283 +
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
7287 + *
7288 + * If the subdomain's active profile matches old_profile,  then call
7289 + * task_remove() to remove the profile leaving the task (subdomain) unconfined.
7290 + */
7291 +static int taskremove_iter(struct subdomain *sd, void *cookie)
7292 +{
7293 +       struct aaprofile *old_profile = (struct aaprofile *)cookie;
7294 +       unsigned long flags;
7295 +
7296 +       spin_lock_irqsave(&sd_lock, flags);
7297 +
7298 +       if (__aa_is_confined(sd) && BASE_PROFILE(sd->active) == old_profile) {
7299 +               task_remove(sd);
7300 +       }
7301 +
7302 +       spin_unlock_irqrestore(&sd_lock, flags);
7303 +
7304 +       return 0;
7305 +}
7306 +
7307 +/** task_replace - replace subdomain's current profile with a new profile
7308 + * @sd: subdomain to replace the profile on
7309 + * @new: new profile
7310 + *
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.
7315 + */
7316 +static inline void task_replace(struct subdomain *sd, struct aaprofile *new)
7317 +{
7318 +       AA_DEBUG("%s: replacing profile for task %s(%d) "
7319 +                "profile=%s (%p) active=%s (%p)\n",
7320 +                __FUNCTION__,
7321 +                sd->task->comm, sd->task->pid,
7322 +                BASE_PROFILE(sd->active)->name, BASE_PROFILE(sd->active),
7323 +                sd->active->name, sd->active);
7324 +
7325 +       if (!sd->active)
7326 +               goto out;
7327 +
7328 +       if (IN_SUBPROFILE(sd->active)) {
7329 +               struct aaprofile *nactive;
7330 +
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);
7334 +
7335 +               if (!nactive)
7336 +                       nactive = get_aaprofile(new->null_profile);
7337 +
7338 +               aa_switch(sd, nactive);
7339 +               put_aaprofile(nactive);
7340 +       } else {
7341 +               aa_switch(sd, new);
7342 +       }
7343 +
7344 + out:
7345 +       return;
7346 +}
7347 +
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.
7351 + *
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.
7355 + */
7356 +static int taskreplace_iter(struct subdomain *sd, void *cookie)
7357 +{
7358 +       struct aa_taskreplace_data *data = (struct aa_taskreplace_data *)cookie;
7359 +       unsigned long flags;
7360 +
7361 +       spin_lock_irqsave(&sd_lock, flags);
7362 +
7363 +       if (__aa_is_confined(sd) &&
7364 +           BASE_PROFILE(sd->active) == data->old_profile)
7365 +               task_replace(sd, data->new_profile);
7366 +
7367 +       spin_unlock_irqrestore(&sd_lock, flags);
7368 +
7369 +       return 0;
7370 +}
7371 +
7372 +static inline int aa_inbounds(struct aa_ext *e, size_t size)
7373 +{
7374 +       return (e->pos + size <= e->end);
7375 +}
7376 +
7377 +/**
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
7382 + *
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.
7385 + */
7386 +static void aaconvert(enum aa_code code, void *dest, void *src)
7387 +{
7388 +       switch (code) {
7389 +       case AA_U8:
7390 +               *(u8 *)dest = *(u8 *) src;
7391 +               break;
7392 +       case AA_U16:
7393 +       case AA_NAME:
7394 +       case AA_DYN_STRING:
7395 +               *(u16 *)dest = le16_to_cpu(get_unaligned((u16 *)src));
7396 +               break;
7397 +       case AA_U32:
7398 +       case AA_STATIC_BLOB:
7399 +               *(u32 *)dest = le32_to_cpu(get_unaligned((u32 *)src));
7400 +               break;
7401 +       case AA_U64:
7402 +               *(u64 *)dest = le64_to_cpu(get_unaligned((u64 *)src));
7403 +               break;
7404 +       default:
7405 +               /* nop - all other type codes do not have a trailing value */
7406 +               ;
7407 +       }
7408 +}
7409 +
7410 +/**
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
7416 + *        entry
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
7419 + * @data.
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
7423 + *        returned.
7424 + */
7425 +static u32 aa_is_X(struct aa_ext *e, enum aa_code code, void *data)
7426 +{
7427 +       void *pos = e->pos;
7428 +       int ret = 0;
7429 +       if (!aa_inbounds(e, AA_CODE_BYTE + aacode_datasize[code]))
7430 +               goto fail;
7431 +       if (code != *(u8 *)e->pos)
7432 +               goto out;
7433 +       e->pos += AA_CODE_BYTE;
7434 +       if (code == AA_NAME) {
7435 +               u16 size;
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))
7439 +                       goto fail;
7440 +               if (data)
7441 +                       *(u16 *)data = size;
7442 +               e->pos += aacode_datasize[code];
7443 +               ret = 1 + aacode_datasize[code];
7444 +       } else if (code == AA_DYN_STRING) {
7445 +               u16 size;
7446 +               char *str;
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))
7451 +                       goto fail;
7452 +               if (data) {
7453 +                       * (char **)data = NULL;
7454 +                       str = kmalloc(size, GFP_KERNEL);
7455 +                       if (!str)
7456 +                               goto fail;
7457 +                       memcpy(str, e->pos, (size_t) size);
7458 +                       str[size-1] = '\0';
7459 +                       * (char **)data = str;
7460 +               }
7461 +               e->pos += size;
7462 +               ret = size;
7463 +       } else if (code == AA_STATIC_BLOB) {
7464 +               u32 size;
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))
7469 +                       goto fail;
7470 +               if (data)
7471 +                       memcpy(data, e->pos, (size_t) size);
7472 +               e->pos += size;
7473 +               ret = size;
7474 +       } else {
7475 +               if (data)
7476 +                       aaconvert(code, data, e->pos);
7477 +               e->pos += aacode_datasize[code];
7478 +               ret = 1 + aacode_datasize[code];
7479 +       }
7480 +out:
7481 +       return ret;
7482 +fail:
7483 +       e->pos = pos;
7484 +       return 0;
7485 +}
7486 +
7487 +/**
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.
7493 + *
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
7499 + */
7500 +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, void *data,
7501 +                      const char *name)
7502 +{
7503 +       void *pos = e->pos;
7504 +       u16 size;
7505 +       u32 ret;
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)))
7512 +                       goto fail;
7513 +               e->pos += size;
7514 +       } else if (name) {
7515 +               goto fail;
7516 +       }
7517 +
7518 +       /* now check if data actually matches */
7519 +       ret = aa_is_X(e, code, data);
7520 +       if (!ret)
7521 +               goto fail;
7522 +       return ret;
7523 +
7524 +fail:
7525 +       e->pos = pos;
7526 +       return 0;
7527 +}
7528 +
7529 +/* macro to wrap error case to make a block of reads look nicer */
7530 +#define AA_READ_X(E, C, D, N) \
7531 +       do { \
7532 +               u32 __ret; \
7533 +               __ret = aa_is_nameX((E), (C), (D), (N)); \
7534 +               if (!__ret) \
7535 +                       goto fail; \
7536 +       } while (0)
7537 +
7538 +/**
7539 + * aa_activate_net_entry - unpacked serialized net entries
7540 + * @e: serialized data extent information
7541 + *
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.
7545 + */
7546 +static inline int aa_activate_net_entry(struct aa_ext *e)
7547 +{
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);
7561 +
7562 +       return 1;
7563 +fail:
7564 +       return 0;
7565 +}
7566 +
7567 +/**
7568 + * aa_activate_file_entry - unpack serialized file entry
7569 + * @e: serialized data extent information
7570 + *
7571 + * unpack the information used for a file ACL entry.
7572 + */
7573 +static inline struct aa_entry *aa_activate_file_entry(struct aa_ext *e)
7574 +{
7575 +       struct aa_entry *entry = NULL;
7576 +
7577 +       if (!(entry = alloc_aa_entry()))
7578 +               goto fail;
7579 +
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);
7584 +
7585 +       entry->extradata = aamatch_alloc(entry->type);
7586 +       if (IS_ERR(entry->extradata)) {
7587 +               entry->extradata = NULL;
7588 +               goto fail;
7589 +       }
7590 +
7591 +       if (entry->extradata &&
7592 +           aamatch_serialize(entry->extradata, e, aa_is_nameX) != 0) {
7593 +               goto fail;
7594 +       }
7595 +       AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
7596 +
7597 +       switch (entry->type) {
7598 +       case aa_entry_literal:
7599 +               AA_DEBUG("%s: %s [no pattern] mode=0x%x\n",
7600 +                        __FUNCTION__,
7601 +                        entry->filename,
7602 +                        entry->mode);
7603 +               break;
7604 +       case aa_entry_tailglob:
7605 +               AA_DEBUG("%s: %s [tailglob] mode=0x%x\n",
7606 +                        __FUNCTION__,
7607 +                        entry->filename,
7608 +                        entry->mode);
7609 +               break;
7610 +       case aa_entry_pattern:
7611 +               AA_DEBUG("%s: %s mode=0x%x\n",
7612 +                        __FUNCTION__,
7613 +                        entry->filename,
7614 +                        entry->mode);
7615 +               break;
7616 +       default:
7617 +               AA_WARN("%s: INVALID entry_match_type %d\n",
7618 +                       __FUNCTION__,
7619 +                       (int)entry->type);
7620 +               goto fail;
7621 +       }
7622 +
7623 +       return entry;
7624 +
7625 +fail:
7626 +       free_aa_entry(entry);
7627 +       return NULL;
7628 +}
7629 +
7630 +/**
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.
7635 + *
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.
7638 + */
7639 +static inline int check_rule_and_add(struct aa_entry *file_entry,
7640 +                                    struct aaprofile *profile,
7641 +                                    const char **message)
7642 +{
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);
7646 +       int i;
7647 +
7648 +       if (mode && !(AA_MAY_EXEC & file_entry->mode)) {
7649 +               *message = "inconsistent rule, x modifiers without x";
7650 +               goto out;
7651 +       }
7652 +
7653 +       /* check that only 1 of the modifiers is set */
7654 +       if (mode && (mode & (mode - 1))) {
7655 +               *message = "inconsistent rule, multiple x modifiers";
7656 +               goto out;
7657 +       }
7658 +
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;
7662 +
7663 +       list_add(&file_entry->list, &profile->file_entry);
7664 +       profile->num_file_entries++;
7665 +
7666 +       mode = file_entry->mode;
7667 +
7668 +       /* Handle partitioned lists
7669 +        * Chain entries onto sublists based on individual
7670 +        * permission bits. This allows more rapid searching.
7671 +        */
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]);
7678 +       }
7679 +
7680 +       return 1;
7681 +
7682 +out:
7683 +       free_aa_entry(file_entry);
7684 +       return 0;
7685 +}
7686 +
7687 +#define AA_ENTRY_LIST(NAME) \
7688 +       do { \
7689 +       if (aa_is_nameX(e, AA_LIST, NULL, (NAME))) { \
7690 +               rulename = ""; \
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) \
7696 +                               goto fail; \
7697 +                       if (!check_rule_and_add(file_entry, profile, \
7698 +                                               &error_string)) { \
7699 +                               rulename = file_entry->filename; \
7700 +                               goto fail; \
7701 +                       } \
7702 +               } \
7703 +       } \
7704 +       } while (0)
7705 +
7706 +/**
7707 + * aa_activate_profile - unpack a serialized profile
7708 + * @e: serialized data extent information
7709 + * @error: error code returned if unpacking fails
7710 + */
7711 +static struct aaprofile *aa_activate_profile(struct aa_ext *e, ssize_t *error)
7712 +{
7713 +       struct aaprofile *profile = NULL;
7714 +       const char *rulename = "";
7715 +       const char *error_string = "Invalid Profile";
7716 +
7717 +       *error = -EPROTO;
7718 +
7719 +       profile = alloc_aaprofile();
7720 +       if (!profile) {
7721 +               error_string = "Could not allocate profile";
7722 +               *error = -ENOMEM;
7723 +               goto fail;
7724 +       }
7725 +
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);
7729 +
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);
7737 +
7738 +       error_string = "Invalid capabilities";
7739 +       AA_READ_X(e, AA_U32, &(profile->capabilities), NULL);
7740 +
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 */
7745 +
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))
7751 +                               goto fail;
7752 +               }
7753 +       }
7754 +       rulename = "";
7755 +
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);
7762 +                       if (!subprofile)
7763 +                               goto fail;
7764 +                       subprofile->parent = profile;
7765 +                       list_add(&subprofile->list, &profile->sub);
7766 +               }
7767 +       }
7768 +
7769 +       error_string = "Invalid end of profile";
7770 +       AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
7771 +
7772 +       return profile;
7773 +
7774 +fail:
7775 +       AA_WARN("%s: %s %s in profile %s\n", INTERFACE_ID, rulename,
7776 +               error_string, profile && profile->name ? profile->name
7777 +               : "unknown");
7778 +
7779 +       if (profile) {
7780 +               free_aaprofile(profile);
7781 +               profile = NULL;
7782 +       }
7783 +
7784 +       return NULL;
7785 +}
7786 +
7787 +/**
7788 + * aa_activate_top_profile - unpack a serialized base profile
7789 + * @e: serialized data extent information
7790 + * @error: error code returned if unpacking fails
7791 + *
7792 + * check interface version unpack a profile and all its hats and patch
7793 + * in any extra information that the profile needs.
7794 + */
7795 +static void *aa_activate_top_profile(struct aa_ext *e, ssize_t *error)
7796 +{
7797 +       struct aaprofile *profile = NULL;
7798 +
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;
7803 +               goto fail;
7804 +       }
7805 +
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;
7811 +               goto fail;
7812 +       }
7813 +
7814 +       profile = aa_activate_profile(e, error);
7815 +       if (!profile)
7816 +               goto fail;
7817 +
7818 +       if (!list_empty(&profile->sub) || profile->flags.complain) {
7819 +               if (attach_nullprofile(profile))
7820 +                       goto fail;
7821 +       }
7822 +       return profile;
7823 +
7824 +fail:
7825 +       free_aaprofile(profile);
7826 +       return NULL;
7827 +}
7828 +
7829 +/**
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
7833 + *
7834 + * unpack and add a profile to the profile list.  Return %0 or error
7835 + */
7836 +ssize_t aa_file_prof_add(void *data, size_t size)
7837 +{
7838 +       struct aaprofile *profile = NULL;
7839 +
7840 +       struct aa_ext e = {
7841 +               .start = data,
7842 +               .end = data + size,
7843 +               .pos = data
7844 +       };
7845 +       ssize_t error;
7846 +
7847 +       profile = aa_activate_top_profile(&e, &error);
7848 +       if (!profile) {
7849 +               AA_DEBUG("couldn't activate profile\n");
7850 +               goto out;
7851 +       }
7852 +
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
7856 +        */
7857 +       if (aa_profilelist_add(profile)) {
7858 +               error = size;
7859 +       } else {
7860 +               AA_WARN("trying to add profile (%s) that already exists.\n",
7861 +                       profile->name);
7862 +               put_aaprofile(profile);
7863 +               error = -EEXIST;
7864 +       }
7865 +
7866 +out:
7867 +       return error;
7868 +}
7869 +
7870 +/**
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
7874 + *
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.
7878 + */
7879 +ssize_t aa_file_prof_repl(void *udata, size_t size)
7880 +{
7881 +       struct aa_taskreplace_data data;
7882 +       struct aa_ext e = {
7883 +               .start = udata,
7884 +               .end = udata + size,
7885 +               .pos = udata
7886 +       };
7887 +
7888 +       ssize_t error;
7889 +
7890 +       data.new_profile = aa_activate_top_profile(&e, &error);
7891 +       if (!data.new_profile) {
7892 +               AA_DEBUG("couldn't activate profile\n");
7893 +               goto out;
7894 +       }
7895 +
7896 +       /* Refcount on data.new_profile is 1 (aa_activate_top_profile).
7897 +        *
7898 +        * This reference will be inherited by aa_profilelist_replace for it's
7899 +        * profile list reference but this isn't sufficient.
7900 +        *
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.
7906 +        *
7907 +        * Grab extra reference on new_profile to prevent this
7908 +        */
7909 +
7910 +       get_aaprofile(data.new_profile);
7911 +
7912 +       data.old_profile = aa_profilelist_replace(data.new_profile);
7913 +
7914 +       /* If there was an old profile,  find all currently executing tasks
7915 +        * using this profile and replace the old profile with the new.
7916 +        */
7917 +       if (data.old_profile) {
7918 +               AA_DEBUG("%s: try to replace profile (%p)%s\n",
7919 +                        __FUNCTION__,
7920 +                        data.old_profile,
7921 +                        data.old_profile->name);
7922 +
7923 +               aa_subdomainlist_iterate(taskreplace_iter, (void *)&data);
7924 +
7925 +               /* it's off global list, and we are done replacing */
7926 +               put_aaprofile(data.old_profile);
7927 +       }
7928 +
7929 +       /* release extra reference obtained above (race) */
7930 +       put_aaprofile(data.new_profile);
7931 +
7932 +       error = size;
7933 +
7934 +out:
7935 +       return error;
7936 +}
7937 +
7938 +/**
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
7942 + *
7943 + * remove a profile from the profile list and all subdomain references
7944 + * to said profile.  Return %0 on success, else error.
7945 + */
7946 +ssize_t aa_file_prof_remove(const char *name, size_t size)
7947 +{
7948 +       struct aaprofile *old_profile;
7949 +
7950 +       /* if the old profile exists it will be removed from the list and
7951 +        * a reference is returned.
7952 +        */
7953 +       old_profile = aa_profilelist_remove(name);
7954 +
7955 +       if (old_profile) {
7956 +               /* remove profile from any tasks using it */
7957 +               aa_subdomainlist_iterate(taskremove_iter, (void *)old_profile);
7958 +
7959 +               /* drop reference obtained by aa_profilelist_remove */
7960 +               put_aaprofile(old_profile);
7961 +       } else {
7962 +               AA_WARN("%s: trying to remove profile (%s) that "
7963 +                       "doesn't exist - skipping.\n", __FUNCTION__, name);
7964 +               return -ENOENT;
7965 +       }
7966 +
7967 +       return size;
7968 +}
7969 +
7970 +/**
7971 + * free_aaprofile_kref - free aaprofile by kref (called by put_aaprofile)
7972 + * @kr: kref callback for freeing of a profile
7973 + */
7974 +void free_aaprofile_kref(struct kref *kr)
7975 +{
7976 +       struct aaprofile *p=container_of(kr, struct aaprofile, count);
7977 +
7978 +       call_rcu(&p->rcu, free_aaprofile_rcu);
7979 +}
7980 +
7981 +/**
7982 + * free_aaprofile - free aaprofile structure
7983 + * @profile: the profile to free
7984 + *
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.
7989 + */
7990 +void free_aaprofile(struct aaprofile *profile)
7991 +{
7992 +       struct aa_entry *ent, *tmp;
7993 +       struct aaprofile *p, *ptmp;
7994 +
7995 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
7996 +
7997 +       if (!profile)
7998 +               return;
7999 +
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",
8004 +                        __FUNCTION__,
8005 +                        profile->name);
8006 +               BUG();
8007 +       }
8008 +
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);
8015 +       }
8016 +
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.
8020 +        */
8021 +       free_aaprofile(profile->null_profile);
8022 +       list_for_each_entry_safe(p, ptmp, &profile->sub, list) {
8023 +               list_del_init(&p->list);
8024 +               p->parent = NULL;
8025 +               put_aaprofile(p);
8026 +       }
8027 +
8028 +       if (profile->name) {
8029 +               AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
8030 +               kfree(profile->name);
8031 +       }
8032 +
8033 +       kfree(profile);
8034 +}
8035 Index: b/security/apparmor/module_interface.h
8036 ===================================================================
8037 --- /dev/null
8038 +++ b/security/apparmor/module_interface.h
8039 @@ -0,0 +1,37 @@
8040 +#ifndef __MODULEINTERFACE_H
8041 +#define __MODULEINTERFACE_H
8042 +
8043 +/* Codes of the types of basic structures that are understood */
8044 +#define AA_CODE_BYTE (sizeof(u8))
8045 +#define INTERFACE_ID "INTERFACE"
8046 +
8047 +#define APPARMOR_INTERFACE_VERSION 2
8048 +
8049 +enum aa_code {
8050 +       AA_U8,
8051 +       AA_U16,
8052 +       AA_U32,
8053 +       AA_U64,
8054 +       AA_NAME,        /* same as string except it is items name */
8055 +       AA_DYN_STRING,
8056 +       AA_STATIC_BLOB,
8057 +       AA_STRUCT,
8058 +       AA_STRUCTEND,
8059 +       AA_LIST,
8060 +       AA_LISTEND,
8061 +       AA_OFFSET,
8062 +       AA_BAD
8063 +};
8064 +
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.
8068 + */
8069 +struct aa_ext {
8070 +       void *start;
8071 +       void *end;
8072 +       void *pos;      /* pointer to current position in the buffer */
8073 +       u32 version;
8074 +};
8075 +
8076 +#endif /* __MODULEINTERFACE_H */
8077 Index: b/security/apparmor/procattr.c
8078 ===================================================================
8079 --- /dev/null
8080 +++ b/security/apparmor/procattr.c
8081 @@ -0,0 +1,332 @@
8082 +/*
8083 + *     Copyright (C) 2005 Novell/SUSE
8084 + *
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
8088 + *     License.
8089 + *
8090 + *     AppArmor /proc/pid/attr handling
8091 + */
8092 +
8093 +/* for isspace */
8094 +#include <linux/ctype.h>
8095 +
8096 +#include "apparmor.h"
8097 +#include "inline.h"
8098 +
8099 +size_t aa_getprocattr(struct aaprofile *active, char *str, size_t size)
8100 +{
8101 +       int error = -EACCES;    /* default to a perm denied */
8102 +       size_t len;
8103 +
8104 +       if (active) {
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;
8110 +
8111 +               lenm = strlen(mode_str);
8112 +
8113 +               lena = strlen(active->name);
8114 +
8115 +               len = lena;
8116 +               if (IN_SUBPROFILE(active)) {
8117 +                       lenp = strlen(BASE_PROFILE(active)->name);
8118 +                       len += (lenp + 1);      /* +1 for ^ */
8119 +               }
8120 +               /* DONT null terminate strings we output via proc */
8121 +               len += (lenm + 1);      /* for \n */
8122 +
8123 +               if (len <= size) {
8124 +                       if (lenp) {
8125 +                               memcpy(str, BASE_PROFILE(active)->name,
8126 +                                      lenp);
8127 +                               str += lenp;
8128 +                               *str++ = '^';
8129 +                       }
8130 +
8131 +                       memcpy(str, active->name, lena);
8132 +                       str += lena;
8133 +                       memcpy(str, mode_str, lenm);
8134 +                       str += lenm;
8135 +                       *str++ = '\n';
8136 +                       error = len;
8137 +               } else if (size == 0) {
8138 +                       error = len;
8139 +               } else {
8140 +                       error = -ERANGE;
8141 +               }
8142 +       } else {
8143 +               const char *unconstrained_str = "unconstrained\n";
8144 +               len = strlen(unconstrained_str);
8145 +
8146 +               /* DONT null terminate strings we output via proc */
8147 +               if (len <= size) {
8148 +                       memcpy(str, unconstrained_str, len);
8149 +                       error = len;
8150 +               } else if (size == 0) {
8151 +                       error = len;
8152 +               } else {
8153 +                       error = -ERANGE;
8154 +               }
8155 +       }
8156 +
8157 +       return error;
8158 +
8159 +}
8160 +
8161 +int aa_setprocattr_changehat(char *hatinfo, size_t infosize)
8162 +{
8163 +       int error = -EINVAL;
8164 +       char *token = NULL, *hat, *smagic, *tmp;
8165 +       u32 magic;
8166 +       int rc, len, consumed;
8167 +       unsigned long flags;
8168 +
8169 +       AA_DEBUG("%s: %p %zd\n", __FUNCTION__, hatinfo, infosize);
8170 +
8171 +       /* strip leading white space */
8172 +       while (infosize && isspace(*hatinfo)) {
8173 +               hatinfo++;
8174 +               infosize--;
8175 +       }
8176 +
8177 +       if (infosize == 0)
8178 +               goto out;
8179 +
8180 +       /*
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
8183 +        * for 100% safety
8184 +        */
8185 +       token = kmalloc(infosize + 1, GFP_KERNEL);
8186 +
8187 +       if (!token) {
8188 +               error = -ENOMEM;
8189 +               goto out;
8190 +       }
8191 +
8192 +       memcpy(token, hatinfo, infosize);
8193 +       token[infosize] = 0;
8194 +
8195 +       /* error is INVAL until we have at least parsed something */
8196 +       error = -EINVAL;
8197 +
8198 +       tmp = token;
8199 +       while (*tmp && *tmp != '^') {
8200 +               tmp++;
8201 +       }
8202 +
8203 +       if (!*tmp || tmp == token) {
8204 +               AA_WARN("%s: Invalid input '%s'\n", __FUNCTION__, token);
8205 +               goto out;
8206 +       }
8207 +
8208 +       /* split magic and hat into two strings */
8209 +       *tmp = 0;
8210 +       smagic = token;
8211 +
8212 +       /*
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.
8217 +        */
8218 +       consumed = len = strlen(smagic);
8219 +
8220 +       rc = sscanf(smagic, "%x%n", &magic, &consumed);
8221 +
8222 +       if (rc != 1 || consumed != len) {
8223 +               AA_WARN("%s: Invalid hex magic %s\n",
8224 +                       __FUNCTION__,
8225 +                       smagic);
8226 +               goto out;
8227 +       }
8228 +
8229 +       hat = tmp + 1;
8230 +
8231 +       if (!*hat)
8232 +               hat = NULL;
8233 +
8234 +       if (!hat && !magic) {
8235 +               AA_WARN("%s: Invalid input, NULL hat and NULL magic\n",
8236 +                       __FUNCTION__);
8237 +               goto out;
8238 +       }
8239 +
8240 +       AA_DEBUG("%s: Magic 0x%x Hat '%s'\n",
8241 +                __FUNCTION__, magic, hat ? hat : NULL);
8242 +
8243 +       spin_lock_irqsave(&sd_lock, flags);
8244 +       error = aa_change_hat(hat, magic);
8245 +       spin_unlock_irqrestore(&sd_lock, flags);
8246 +
8247 +out:
8248 +       if (token) {
8249 +               memset(token, 0, infosize);
8250 +               kfree(token);
8251 +       }
8252 +
8253 +       return error;
8254 +}
8255 +
8256 +int aa_setprocattr_setprofile(struct task_struct *p, char *profilename,
8257 +                             size_t profilesize)
8258 +{
8259 +       int error = -EINVAL;
8260 +       struct aaprofile *profile = NULL;
8261 +       struct subdomain *sd;
8262 +       char *name = NULL;
8263 +       unsigned long flags;
8264 +
8265 +       AA_DEBUG("%s: current %s(%d)\n",
8266 +                __FUNCTION__, current->comm, current->pid);
8267 +
8268 +       /* strip leading white space */
8269 +       while (profilesize && isspace(*profilename)) {
8270 +               profilename++;
8271 +               profilesize--;
8272 +       }
8273 +
8274 +       if (profilesize == 0)
8275 +               goto out;
8276 +
8277 +       /*
8278 +        * Copy string to a new buffer so we guarantee it is zero
8279 +        * terminated
8280 +        */
8281 +       name = kmalloc(profilesize + 1, GFP_KERNEL);
8282 +
8283 +       if (!name) {
8284 +               error = -ENOMEM;
8285 +               goto out;
8286 +       }
8287 +
8288 +       strncpy(name, profilename, profilesize);
8289 +       name[profilesize] = 0;
8290 +
8291 + repeat:
8292 +       if (strcmp(name, "unconstrained") != 0) {
8293 +               profile = aa_profilelist_find(name);
8294 +               if (!profile) {
8295 +                       AA_WARN("%s: Unable to switch task %s(%d) to profile"
8296 +                               "'%s'. No such profile.\n",
8297 +                               __FUNCTION__,
8298 +                               p->comm, p->pid,
8299 +                               name);
8300 +
8301 +                       error = -EINVAL;
8302 +                       goto out;
8303 +               }
8304 +       }
8305 +
8306 +       spin_lock_irqsave(&sd_lock, flags);
8307 +
8308 +       sd = AA_SUBDOMAIN(p->security);
8309 +
8310 +       /* switch to unconstrained */
8311 +       if (!profile) {
8312 +               if (__aa_is_confined(sd)) {
8313 +                       AA_WARN("%s: Unconstraining task %s(%d) "
8314 +                               "profile %s active %s\n",
8315 +                               __FUNCTION__,
8316 +                               p->comm, p->pid,
8317 +                               BASE_PROFILE(sd->active)->name,
8318 +                               sd->active->name);
8319 +
8320 +                       aa_switch_unconfined(sd);
8321 +               } else {
8322 +                       AA_WARN("%s: task %s(%d) "
8323 +                               "is already unconstrained\n",
8324 +                               __FUNCTION__, p->comm, p->pid);
8325 +               }
8326 +       } else {
8327 +               if (!sd) {
8328 +                       /* this task was created before module was
8329 +                        * loaded, allocate a subdomain
8330 +                        */
8331 +                       AA_WARN("%s: task %s(%d) has no subdomain\n",
8332 +                               __FUNCTION__, p->comm, p->pid);
8333 +
8334 +                       /* unlock so we can safely GFP_KERNEL */
8335 +                       spin_unlock_irqrestore(&sd_lock, flags);
8336 +
8337 +                       sd = alloc_subdomain(p);
8338 +                       if (!sd) {
8339 +                               AA_WARN("%s: Unable to allocate subdomain for "
8340 +                                       "task %s(%d). Cannot confine task to "
8341 +                                       "profile %s\n",
8342 +                                       __FUNCTION__,
8343 +                                       p->comm, p->pid,
8344 +                                       name);
8345 +
8346 +                               error = -ENOMEM;
8347 +                               put_aaprofile(profile);
8348 +
8349 +                               goto out;
8350 +                       }
8351 +
8352 +                       spin_lock_irqsave(&sd_lock, flags);
8353 +                       if (!AA_SUBDOMAIN(p->security)) {
8354 +                               p->security = sd;
8355 +                       } else { /* race */
8356 +                               free_subdomain(sd);
8357 +                               sd = AA_SUBDOMAIN(p->security);
8358 +                       }
8359 +               }
8360 +
8361 +               /* ensure the profile hasn't been replaced */
8362 +
8363 +               if (unlikely(profile->isstale)) {
8364 +                       WARN_ON(profile == null_complain_profile);
8365 +
8366 +                       /* drop refcnt obtained from earlier get_aaprofile */
8367 +                       put_aaprofile(profile);
8368 +                       profile = aa_profilelist_find(name);
8369 +
8370 +                       if (!profile) {
8371 +                               /* Race, profile was removed. */
8372 +                               spin_unlock_irqrestore(&sd_lock, flags);
8373 +                               goto repeat;
8374 +                       }
8375 +               }
8376 +
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.
8382 +                */
8383 +
8384 +               AA_WARN("%s: Switching task %s(%d) "
8385 +                       "profile %s active %s to new profile %s\n",
8386 +                       __FUNCTION__,
8387 +                       p->comm, p->pid,
8388 +                       sd->active ? BASE_PROFILE(sd->active)->name :
8389 +                               "unconstrained",
8390 +                       sd->active ? sd->active->name : "unconstrained",
8391 +                       name);
8392 +
8393 +               aa_switch(sd, profile);
8394 +
8395 +               put_aaprofile(profile); /* drop ref we obtained above
8396 +                                        * from aa_profilelist_find
8397 +                                        */
8398 +
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
8402 +                */
8403 +               sd->hat_magic = 0;
8404 +       }
8405 +
8406 +       spin_unlock_irqrestore(&sd_lock, flags);
8407 +
8408 +       error = 0;
8409 +out:
8410 +       kfree(name);
8411 +
8412 +       return error;
8413 +}
8414 Index: b/security/apparmor/shared.h
8415 ===================================================================
8416 --- /dev/null
8417 +++ b/security/apparmor/shared.h
8418 @@ -0,0 +1,46 @@
8419 +/*
8420 + *     Copyright (C) 2000, 2001, 2004, 2005 Novell/SUSE
8421 + *
8422 + *     Immunix AppArmor LSM
8423 + *
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
8427 + *     License.
8428 + */
8429 +
8430 +#ifndef _SHARED_H
8431 +#define _SHARED_H
8432 +
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 */
8440 +
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
8448 +
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)
8459 +
8460 +#define AA_EXEC_MODIFIERS              (AA_EXEC_INHERIT | \
8461 +                                        AA_EXEC_UNCONSTRAINED | \
8462 +                                        AA_EXEC_PROFILE)
8463 +
8464 +#endif /* _SHARED_H */
This page took 0.766628 seconds and 3 git commands to generate.