]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.6-apparmor.patch
- addedd Linux-ABI support. Bcond, default disabled.
[packages/kernel.git] / linux-2.6-apparmor.patch
1  fs/namespace.c                          |    3 
2  include/linux/audit.h                   |    5 
3  include/linux/namespace.h               |    3 
4  kernel/audit.c                          |   12 
5  security/Kconfig                        |    1 
6  security/Makefile                       |    1 
7  security/apparmor/Kbuild                |   10 
8  security/apparmor/Kconfig               |    9 
9  security/apparmor/Makefile              |   25 
10  security/apparmor/aamatch/Kbuild        |    6 
11  security/apparmor/aamatch/match.h       |  137 ++
12  security/apparmor/aamatch/match_pcre.c  |  169 ++
13  security/apparmor/aamatch/pcre_exec.c   | 1945 ++++++++++++++++++++++++++++++++
14  security/apparmor/aamatch/pcre_exec.h   |  308 +++++
15  security/apparmor/aamatch/pcre_tables.h |  184 +++
16  security/apparmor/apparmor.h            |  302 ++++
17  security/apparmor/apparmor_version.c    |   42 
18  security/apparmor/apparmorfs.c          |  440 +++++++
19  security/apparmor/capabilities.c        |   54 
20  security/apparmor/inline.h              |  364 +++++
21  security/apparmor/list.c                |  271 ++++
22  security/apparmor/lsm.c                 |  959 +++++++++++++++
23  security/apparmor/main.c                | 1691 +++++++++++++++++++++++++++
24  security/apparmor/module_interface.c    |  712 +++++++++++
25  security/apparmor/module_interface.h    |   37 
26  security/apparmor/procattr.c            |  329 +++++
27  security/apparmor/shared.h              |   47 
28  27 files changed, 8063 insertions(+), 3 deletions(-)
29
30 --- linux-2.6.16.29.orig/fs/namespace.c 2006-10-12 21:11:17.000000000 -0700
31 +++ linux-2.6.16.29/fs/namespace.c      2006-10-12 21:11:14.000000000 -0700
32 @@ -46,7 +46,8 @@ static int event;
33  static struct list_head *mount_hashtable;
34  static int hash_mask __read_mostly, hash_bits __read_mostly;
35  static kmem_cache_t *mnt_cache;
36 -static struct rw_semaphore namespace_sem;
37 +struct rw_semaphore namespace_sem;
38 +EXPORT_SYMBOL_GPL(namespace_sem);
39  
40  /* /sys/fs */
41  decl_subsys(fs, NULL, NULL);
42 --- linux-2.6.16.29.orig/include/linux/audit.h  2006-10-12 21:11:17.000000000 -0700
43 +++ linux-2.6.16.29/include/linux/audit.h       2006-10-12 21:11:14.000000000 -0700
44 @@ -73,6 +73,8 @@
45  #define AUDIT_SELINUX_ERR      1401    /* Internal SE Linux Errors */
46  #define AUDIT_AVC_PATH         1402    /* dentry, vfsmount pair from avc */
47  
48 +#define AUDIT_SD               1500    /* AppArmor (SubDomain) audit */
49 +
50  #define AUDIT_KERNEL           2000    /* Asynchronous audit record. NOT A REQUEST. */
51  
52  /* Rule flags */
53 @@ -265,6 +267,9 @@ extern void             audit_log(struct audit_
54                                       __attribute__((format(printf,4,5)));
55  
56  extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
57 +extern void                audit_log_vformat(struct audit_buffer *ab, 
58 +                                             const char *fmt, va_list args)
59 +                           __attribute__((format(printf,2,0)));
60  extern void                audit_log_format(struct audit_buffer *ab,
61                                              const char *fmt, ...)
62                             __attribute__((format(printf,2,3)));
63 --- linux-2.6.16.29.orig/include/linux/namespace.h      2006-10-12 21:11:17.000000000 -0700
64 +++ linux-2.6.16.29/include/linux/namespace.h   2006-10-12 21:11:14.000000000 -0700
65 @@ -5,6 +5,9 @@
66  #include <linux/mount.h>
67  #include <linux/sched.h>
68  
69 +/* exported for AppArmor (SubDomain) */
70 +extern struct rw_semaphore namespace_sem;
71 +
72  struct namespace {
73         atomic_t                count;
74         struct vfsmount *       root;
75 --- linux-2.6.16.29.orig/kernel/audit.c 2006-10-12 21:11:17.000000000 -0700
76 +++ linux-2.6.16.29/kernel/audit.c      2006-10-12 21:11:14.000000000 -0700
77 @@ -733,8 +733,8 @@ static inline int audit_expand(struct au
78   * room in the audit buffer, more room will be allocated and vsnprint
79   * will be called a second time.  Currently, we assume that a printk
80   * can't format message larger than 1024 bytes, so we don't either. */
81 -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
82 -                             va_list args)
83 +void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
84 +                      va_list args)
85  {
86         int len, avail;
87         struct sk_buff *skb;
88 @@ -895,3 +895,11 @@ void audit_log(struct audit_context *ctx
89                 audit_log_end(ab);
90         }
91  }
92 +
93 +EXPORT_SYMBOL_GPL(audit_log_start);
94 +EXPORT_SYMBOL_GPL(audit_log_vformat);
95 +EXPORT_SYMBOL_GPL(audit_log_format);
96 +EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
97 +EXPORT_SYMBOL_GPL(audit_log_d_path);
98 +EXPORT_SYMBOL_GPL(audit_log_end);
99 +EXPORT_SYMBOL_GPL(audit_log);
100 --- linux-2.6.16.29.orig/security/apparmor/aamatch/Kbuild       1969-12-31 16:00:00.000000000 -0800
101 +++ linux-2.6.16.29/security/apparmor/aamatch/Kbuild    2006-10-12 21:11:15.000000000 -0700
102 @@ -0,0 +1,6 @@
103 +# Makefile for AppArmor aamatch submodule
104 +#
105 +
106 +obj-$(CONFIG_SECURITY_APPARMOR) += aamatch_pcre.o
107 +
108 +aamatch_pcre-y := match_pcre.o pcre_exec.o
109 --- linux-2.6.16.29.orig/security/apparmor/aamatch/match.h      1969-12-31 16:00:00.000000000 -0800
110 +++ linux-2.6.16.29/security/apparmor/aamatch/match.h   2006-10-12 21:11:15.000000000 -0700
111 @@ -0,0 +1,137 @@
112 +/*
113 + *     Copyright (C) 2002-2005 Novell/SUSE
114 + *
115 + *     This program is free software; you can redistribute it and/or
116 + *     modify it under the terms of the GNU General Public License as
117 + *     published by the Free Software Foundation, version 2 of the
118 + *     License.
119 + *
120 + *     AppArmor submodule (match) prototypes
121 + */
122 +
123 +#ifndef __MATCH_H
124 +#define __MATCH_H
125 +
126 +#include "../module_interface.h"
127 +#include "../apparmor.h"
128 +
129 +/* The following functions implement an interface used by the primary
130 + * AppArmor module to perform name matching (n.b. "AppArmor" was previously
131 + * called "SubDomain").
132 +
133 + * sdmatch_alloc
134 + * sdmatch_free
135 + * sdmatch_features
136 + * sdmatch_serialize
137 + * sdmatch_match
138 + *
139 + * The intent is for the primary module to export (via virtual fs entries)
140 + * the features provided by the submodule (sdmatch_features) so that the
141 + * parser may only load policy that can be supported.
142 + *
143 + * The primary module will call sdmatch_serialize to allow the submodule
144 + * to consume submodule specific data from parser data stream and will call
145 + * sdmatch_match to determine if a pathname matches an sd_entry.
146 + */
147 +
148 +typedef int (*sdmatch_serializecb)
149 +       (struct sd_ext *, enum sd_code, void *, const char *);
150 +
151 +/**
152 + * sdmatch_alloc: allocate extradata (if necessary)
153 + * @entry_type: type of entry being allocated
154 + * Return value: NULL indicates no data was allocated (ERR_PTR(x) on error)
155 + */
156 +extern void* sdmatch_alloc(enum entry_t entry_type);
157 +
158 +/**
159 + * sdmatch_free: release data allocated by sdmatch_alloc
160 + * @entry_extradata: data previously allocated by sdmatch_alloc
161 + */
162 +extern void sdmatch_free(void *entry_extradata);
163 +
164 +/**
165 + * sdmatch_features: return match types supported
166 + * Return value: space seperated string (of types supported - use type=value
167 + * to indicate variants of a type)
168 + */
169 +extern const char* sdmatch_features(void);
170 +
171 +/**
172 + * sdmatch_serialize: serialize extradata
173 + * @entry_extradata: data previously allocated by sdmatch_alloc
174 + * @e: input stream
175 + * @cb: callback fn (consume incoming data stream)
176 + * Return value: 0 success, -ve error
177 + */
178 +extern int sdmatch_serialize(void *entry_extradata, struct sd_ext *e,
179 +                            sdmatch_serializecb cb);
180 +
181 +/**
182 + * sdmatch_match: determine if pathname matches entry
183 + * @pathname: pathname to verify
184 + * @entry_name: entry name
185 + * @entry_type: type of entry
186 + * @entry_extradata: data previously allocated by sdmatch_alloc
187 + * Return value: 1 match, 0 othersise
188 + */
189 +extern unsigned int sdmatch_match(const char *pathname, const char *entry_name,
190 +                                 enum entry_t entry_type,
191 +                                 void *entry_extradata);
192 +
193 +
194 +/**
195 + * sd_getentry_type - return string representation of entry_t
196 + * @etype: entry type
197 + */
198 +static inline const char *sd_getentry_type(enum entry_t etype)
199 +{
200 +       const char *etype_names[] = {
201 +               "sd_entry_literal",
202 +               "sd_entry_tailglob",
203 +               "sd_entry_pattern",
204 +               "sd_entry_invalid"
205 +       };
206 +
207 +       if (etype >= sd_entry_invalid) {
208 +               etype = sd_entry_invalid;
209 +       }
210 +
211 +       return etype_names[etype];
212 +}
213 +
214 +/**
215 + * sdmatch_match_common - helper function to check if a pathname matches
216 + * a literal/tailglob
217 + * @path: path requested to search for
218 + * @entry_name: name from sd_entry
219 + * @etype: type of entry
220 + */
221 +static inline int sdmatch_match_common(const char *path,
222 +                                          const char *entry_name,
223 +                                          enum entry_t etype)
224 +{
225 +       int retval;
226 +
227 +       /* literal, no pattern matching characters */
228 +       if (etype == sd_entry_literal) {
229 +               retval = (strcmp(entry_name, path) == 0);
230 +       /* trailing ** glob pattern */
231 +       } else if (etype == sd_entry_tailglob) {
232 +               retval = (strncmp(entry_name, path,
233 +                                 strlen(entry_name) - 2) == 0);
234 +       } else {
235 +               SD_WARN("%s: Invalid entry_t %d\n", __FUNCTION__, etype);
236 +               retval = 0;
237 +       }
238 +
239 +#if 0
240 +       SD_DEBUG("%s(%d): %s %s [%s]\n",
241 +               __FUNCTION__, retval, path, entry_name,
242 +               sd_getentry_type(etype));
243 +#endif
244 +
245 +       return retval;
246 +}
247 +
248 +#endif /* __MATCH_H */
249 --- linux-2.6.16.29.orig/security/apparmor/aamatch/match_pcre.c 1969-12-31 16:00:00.000000000 -0800
250 +++ linux-2.6.16.29/security/apparmor/aamatch/match_pcre.c      2006-10-12 21:11:15.000000000 -0700
251 @@ -0,0 +1,169 @@
252 +/*
253 + *     Copyright (C) 2002-2005 Novell/SUSE
254 + *
255 + *     This program is free software; you can redistribute it and/or
256 + *     modify it under the terms of the GNU General Public License as
257 + *     published by the Free Software Foundation, version 2 of the
258 + *     License.
259 + *
260 + *     http://forge.novell.com/modules/xfmod/project/?apparmor
261 + *
262 + *     AppArmor aamatch submodule (w/ pattern expansion).
263 + *
264 + *     This module makes use of a slightly modified version of the PCRE
265 + *     library developed by Philip Hazel <ph10@cam.ac.uk>.  See the files
266 + *     pcre_* in this directory.
267 + */
268 +
269 +#include <linux/module.h>
270 +#include "match.h"
271 +#include "pcre_exec.h"
272 +#include "pcre_tables.h"
273 +
274 +static const char *features="literal tailglob pattern=pcre";
275 +
276 +struct sdmatch_entry
277 +{
278 +       char *pattern;
279 +       pcre *compiled;
280 +};
281 +
282 +void* sdmatch_alloc(enum entry_t entry_type)
283 +{
284 +void *ptr=NULL;
285 +
286 +       if (entry_type == sd_entry_pattern) {
287 +               ptr = kmalloc(sizeof(struct sdmatch_entry), GFP_KERNEL);
288 +               if (ptr)
289 +                       memset(ptr, 0, sizeof(struct sdmatch_entry));
290 +               else
291 +                       ptr=ERR_PTR(-ENOMEM);
292 +       } else if (entry_type != sd_entry_literal &&
293 +                  entry_type != sd_entry_tailglob) {
294 +               ptr = ERR_PTR(-EINVAL);
295 +       }
296 +
297 +       return ptr;
298 +}
299 +
300 +void sdmatch_free(void *ptr)
301 +{
302 +       if (ptr) {
303 +               struct sdmatch_entry *ed = (struct sdmatch_entry *) ptr;
304 +               kfree(ed->pattern);
305 +               kfree(ed->compiled);    /* allocated by SD_READ_X */
306 +       }
307 +       kfree(ptr);
308 +}
309 +
310 +const char *sdmatch_features(void)
311 +{
312 +       return features;
313 +}
314 +
315 +int sdmatch_serialize(void *entry_extradata, struct sd_ext *e,
316 +                     sdmatch_serializecb cb)
317 +{
318 +#define SD_READ_X(E, C, D, N) \
319 +       do { \
320 +               if (!cb((E), (C), (D), (N))) { \
321 +                       error = -EINVAL; \
322 +                       goto done; \
323 +               }\
324 +       } while (0)
325 +
326 +       int error = 0;
327 +       u32 size, magic, opts;
328 +       u8 t_char;
329 +       struct sdmatch_entry *ed = (struct sdmatch_entry *) entry_extradata;
330 +
331 +       if (ed == NULL)
332 +               goto done;
333 +
334 +       SD_READ_X(e, SD_DYN_STRING, &ed->pattern, NULL);
335 +
336 +       /* size determines the real size of the pcre struct,
337 +          it is size_t - sizeof(pcre) on user side.
338 +          uschar must be the same in user and kernel space */
339 +       /* check that we are processing the correct structure */
340 +       SD_READ_X(e, SD_STRUCT, NULL, "pcre");
341 +       SD_READ_X(e, SD_U32, &size, "pattern.size");
342 +       SD_READ_X(e, SD_U32, &magic, "pattern.magic");
343 +
344 +       /* the allocation of pcre is delayed because it depends on the size
345 +        * of the pattern */
346 +       ed->compiled = (pcre *) kmalloc(size + sizeof(pcre), GFP_KERNEL);
347 +       if (!ed->compiled) {
348 +               error = -ENOMEM;
349 +               goto done;
350 +       }
351 +
352 +       memset(ed->compiled, 0, size + sizeof(pcre));
353 +       ed->compiled->magic_number = magic;
354 +       ed->compiled->size = size + sizeof(pcre);
355 +
356 +       SD_READ_X(e, SD_U32, &opts, "pattern.options");
357 +       ed->compiled->options = opts;
358 +       SD_READ_X(e, SD_U16, &ed->compiled->top_bracket, "pattern.top_bracket");
359 +       SD_READ_X(e, SD_U16, &ed->compiled->top_backref, "pattern.top_backref");
360 +       SD_READ_X(e, SD_U8, &t_char, "pattern.first_char");
361 +       ed->compiled->first_char = t_char;
362 +       SD_READ_X(e, SD_U8, &t_char, "pattern.req_char");
363 +       ed->compiled->req_char = t_char;
364 +       SD_READ_X(e, SD_U8, &t_char, "pattern.code[0]");
365 +       ed->compiled->code[0] = t_char;
366 +
367 +       SD_READ_X(e, SD_STATIC_BLOB, &ed->compiled->code[1], NULL);
368 +
369 +       SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
370 +
371 +       /* stitch in pcre patterns, it was NULLed out by parser
372 +        * pcre_default_tables defined in pcre_tables.h */
373 +       ed->compiled->tables = pcre_default_tables;
374 +
375 +done:
376 +       if (error != 0 && ed) {
377 +               kfree(ed->pattern); /* allocated by SD_READ_X */
378 +               kfree(ed->compiled);
379 +               ed->pattern = NULL;
380 +               ed->compiled = NULL;
381 +       }
382 +
383 +       return error;
384 +}
385 +
386 +unsigned int sdmatch_match(const char *pathname, const char *entry_name,
387 +                          enum entry_t entry_type, void *entry_extradata)
388 +{
389 +       int ret;
390 +
391 +       if (entry_type == sd_entry_pattern) {
392 +               int pcreret;
393 +               struct sdmatch_entry *ed =
394 +                       (struct sdmatch_entry *) entry_extradata;
395 +
396 +               pcreret = pcre_exec(ed->compiled, NULL,
397 +                                   pathname, strlen(pathname),
398 +                                   0, 0, NULL, 0);
399 +
400 +               ret = (pcreret >= 0);
401 +
402 +               // XXX - this needs access to subdomain_debug,  hmmm
403 +               //SD_DEBUG("%s(%d): %s %s %d\n", __FUNCTION__,
404 +               //       ret, pathname, ed->pattern, pcreret);
405 +       } else {
406 +               ret = sdmatch_match_common(pathname, entry_name, entry_type);
407 +       }
408 +
409 +        return ret;
410 +}
411 +
412 +EXPORT_SYMBOL_GPL(sdmatch_alloc);
413 +EXPORT_SYMBOL_GPL(sdmatch_free);
414 +EXPORT_SYMBOL_GPL(sdmatch_features);
415 +EXPORT_SYMBOL_GPL(sdmatch_serialize);
416 +EXPORT_SYMBOL_GPL(sdmatch_match);
417 +
418 +MODULE_DESCRIPTION("AppArmor aa_match module [pcre]");
419 +MODULE_AUTHOR("Tony Jones <tonyj@suse.de>");
420 +MODULE_LICENSE("GPL");
421 --- linux-2.6.16.29.orig/security/apparmor/aamatch/pcre_exec.c  1969-12-31 16:00:00.000000000 -0800
422 +++ linux-2.6.16.29/security/apparmor/aamatch/pcre_exec.c       2006-10-12 21:11:15.000000000 -0700
423 @@ -0,0 +1,1945 @@
424 +/*
425 + *  This is a modified version of pcre.c containing only the code/data
426 + *  required to support pcre_exec()
427 + */
428 +
429 +
430 +/*************************************************
431 +*      Perl-Compatible Regular Expressions       *
432 +*************************************************/
433 +
434 +/*
435 +This is a library of functions to support regular expressions whose syntax
436 +and semantics are as close as possible to those of the Perl 5 language. See
437 +the file Tech.Notes for some information on the internals.
438 +
439 +Written by: Philip Hazel <ph10@cam.ac.uk>
440 +
441 +           Copyright (c) 1997-2001 University of Cambridge
442 +
443 +-----------------------------------------------------------------------------
444 +Permission is granted to anyone to use this software for any purpose on any
445 +computer system, and to redistribute it freely, subject to the following
446 +restrictions:
447 +
448 +1. This software is distributed in the hope that it will be useful,
449 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
450 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
451 +
452 +2. The origin of this software must not be misrepresented, either by
453 +   explicit claim or by omission.
454 +
455 +3. Altered versions must be plainly marked as such, and must not be
456 +   misrepresented as being the original software.
457 +
458 +4. If PCRE is embedded in any software that is released under the GNU
459 +   General Purpose Licence (GPL), then the terms of that licence shall
460 +   supersede any condition above with which it is incompatible.
461 +-----------------------------------------------------------------------------
462 +*/
463 +
464 +
465 +/* Define DEBUG to get debugging output on stdout. */
466 +
467 +/* #define DEBUG */
468 +
469 +/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
470 +inline, and there are *still* stupid compilers about that don't like indented
471 +pre-processor statements. I suppose it's only been 10 years... */
472 +
473 +#ifdef DEBUG
474 +#define DPRINTF(p) PCRE_PRINTF p
475 +#else
476 +#define DPRINTF(p) /*nothing*/
477 +#endif
478 +
479 +/* Include the internals header, which itself includes Standard C headers plus
480 +the external pcre header. */
481 +
482 +#include "pcre_exec.h"
483 +
484 +
485 +/* ----  CODE DELETED ---- */
486 +
487 +
488 +/* Min and max values for the common repeats; for the maxima, 0 => infinity */
489 +
490 +static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
491 +static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
492 +
493 +
494 +/* ----  CODE DELETED ---- */
495 +
496 +
497 +/* Structure for building a chain of data that actually lives on the
498 + * stack, for holding the values of the subject pointer at the start of each
499 + * subpattern, so as to detect when an empty string has been matched by a
500 + * subpattern - to break infinite loops. */
501 +
502 +typedef struct eptrblock {
503 +         struct eptrblock *prev;
504 +           const uschar *saved_eptr;
505 +} eptrblock;
506 +
507 +/* Flag bits for the match() function */
508 +
509 +#define match_condassert   0x01    /* Called to check a condition assertion */
510 +#define match_isgroup      0x02    /* Set if start of bracketed group */
511 +
512 +
513 +/* ----  CODE DELETED ---- */
514 +
515 +
516 +/*************************************************
517 + * *               Global variables                 *
518 + * *************************************************/
519 +
520 +/* PCRE is thread-clean and doesn't use any global variables in the normal
521 + * sense. However, it calls memory allocation and free functions via the two
522 + * indirections below, which are can be changed by the caller, but are shared
523 + * between all threads. */
524 +
525 +#ifdef __KERNEL__
526 +static void *kern_malloc(size_t sz)
527 +{
528 +               return kmalloc(sz, GFP_KERNEL);
529 +}
530 +void  *(*pcre_malloc)(size_t) = kern_malloc;
531 +void  (*pcre_free)(const void *) = kfree;
532 +#else
533 +void  *(*pcre_malloc)(size_t) = malloc;
534 +void  (*pcre_free)(const void *) = free;
535 +#endif
536 +
537 +
538 +/*************************************************
539 + * *    Macros and tables for character handling    *
540 + * *************************************************/
541 +
542 +/* When UTF-8 encoding is being used, a character is no longer just a single
543 + * byte. The macros for character handling generate simple sequences when used in
544 + * byte-mode, and more complicated ones for UTF-8 characters. */
545 +
546 +#ifndef SUPPORT_UTF8
547 +#define GETCHARINC(c, eptr) c = *eptr++;
548 +#define GETCHARLEN(c, eptr, len) c = *eptr;
549 +#define BACKCHAR(eptr)
550 +#endif
551 +
552 +/* ----  CODE DELETED ---- */
553 +
554 +#ifdef DEBUG
555 +/*************************************************
556 +*        Debugging function to print chars       *
557 +*************************************************/
558 +
559 +/* Print a sequence of chars in printable format, stopping at the end of the
560 +subject if the requested.
561 +
562 +Arguments:
563 +  p           points to characters
564 +  length      number to print
565 +  is_subject  TRUE if printing from within md->start_subject
566 +  md          pointer to matching data block, if is_subject is TRUE
567 +
568 +Returns:     nothing
569 +*/
570 +
571 +static void
572 +pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
573 +{
574 +int c;
575 +if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
576 +while (length-- > 0)
577 +  if (isprint(c = *(p++))) PCRE_PRINTF("%c", c); else PCRE_PRINTF("\\x%02x", c);
578 +}
579 +#endif /* DEBUG */
580 +
581 +/* ----  CODE DELETED ---- */
582 +
583 +
584 +/*************************************************
585 +*          Match a back-reference                *
586 +*************************************************/
587 +
588 +/* If a back reference hasn't been set, the length that is passed is greater
589 +than the number of characters left in the string, so the match fails.
590 +
591 +Arguments:
592 +  offset      index into the offset vector
593 +  eptr        points into the subject
594 +  length      length to be matched
595 +  md          points to match data block
596 +  ims         the ims flags
597 +
598 +Returns:      TRUE if matched
599 +*/
600 +
601 +static BOOL
602 +match_ref(int offset, register const uschar *eptr, int length, match_data *md,
603 +  unsigned long int ims)
604 +{
605 +const uschar *p = md->start_subject + md->offset_vector[offset];
606 +
607 +#ifdef DEBUG
608 +if (eptr >= md->end_subject)
609 +  PCRE_PRINTF("matching subject <null>");
610 +else
611 +  {
612 +  PCRE_PRINTF("matching subject ");
613 +  pchars(eptr, length, TRUE, md);
614 +  }
615 +PCRE_PRINTF(" against backref ");
616 +pchars(p, length, FALSE, md);
617 +PCRE_PRINTF("\n");
618 +#endif
619 +
620 +/* Always fail if not enough characters left */
621 +
622 +if (length > md->end_subject - eptr) return FALSE;
623 +
624 +/* Separate the caselesss case for speed */
625 +
626 +if ((ims & PCRE_CASELESS) != 0)
627 +  {
628 +  while (length-- > 0)
629 +    if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
630 +  }
631 +else
632 +  { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
633 +
634 +return TRUE;
635 +}
636 +
637 +
638 +/*************************************************
639 +*         Match from current position            *
640 +*************************************************/
641 +
642 +/* On entry ecode points to the first opcode, and eptr to the first character
643 +in the subject string, while eptrb holds the value of eptr at the start of the
644 +last bracketed group - used for breaking infinite loops matching zero-length
645 +strings.
646 +
647 +Arguments:
648 +   eptr        pointer in subject
649 +   ecode       position in code
650 +   offset_top  current top pointer
651 +   md          pointer to "static" info for the match
652 +   ims         current /i, /m, and /s options
653 +   eptrb       pointer to chain of blocks containing eptr at start of
654 +                 brackets - for testing for empty matches
655 +   flags       can contain
656 +                 match_condassert - this is an assertion condition
657 +                 match_isgroup - this is the start of a bracketed group
658 +
659 +Returns:       TRUE if matched
660 +*/
661 +
662 +static BOOL
663 +match(register const uschar *eptr, register const uschar *ecode,
664 +  int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
665 +  int flags)
666 +{
667 +unsigned long int original_ims = ims;   /* Save for resetting on ')' */
668 +eptrblock newptrb;
669 +
670 +/* At the start of a bracketed group, add the current subject pointer to the
671 +stack of such pointers, to be re-instated at the end of the group when we hit
672 +the closing ket. When match() is called in other circumstances, we don't add to
673 +the stack. */
674 +
675 +if ((flags & match_isgroup) != 0)
676 +  {
677 +  newptrb.prev = eptrb;
678 +  newptrb.saved_eptr = eptr;
679 +  eptrb = &newptrb;
680 +  }
681 +
682 +/* Now start processing the operations. */
683 +
684 +for (;;)
685 +  {
686 +  int op = (int)*ecode;
687 +  int min, max, ctype;
688 +  register int i;
689 +  register int c;
690 +  BOOL minimize = FALSE;
691 +
692 +  /* Opening capturing bracket. If there is space in the offset vector, save
693 +  the current subject position in the working slot at the top of the vector. We
694 +  mustn't change the current values of the data slot, because they may be set
695 +  from a previous iteration of this group, and be referred to by a reference
696 +  inside the group.
697 +
698 +  If the bracket fails to match, we need to restore this value and also the
699 +  values of the final offsets, in case they were set by a previous iteration of
700 +  the same bracket.
701 +
702 +  If there isn't enough space in the offset vector, treat this as if it were a
703 +  non-capturing bracket. Don't worry about setting the flag for the error case
704 +  here; that is handled in the code for KET. */
705 +
706 +  if (op > OP_BRA)
707 +    {
708 +    int offset;
709 +    int number = op - OP_BRA;
710 +
711 +    /* For extended extraction brackets (large number), we have to fish out the
712 +    number from a dummy opcode at the start. */
713 +
714 +    if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5];
715 +    offset = number << 1;
716 +
717 +#ifdef DEBUG
718 +    PCRE_PRINTF("start bracket %d subject=", number);
719 +    pchars(eptr, 16, TRUE, md);
720 +    PCRE_PRINTF("\n");
721 +#endif
722 +
723 +    if (offset < md->offset_max)
724 +      {
725 +      int save_offset1 = md->offset_vector[offset];
726 +      int save_offset2 = md->offset_vector[offset+1];
727 +      int save_offset3 = md->offset_vector[md->offset_end - number];
728 +
729 +      DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
730 +      md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
731 +
732 +      do
733 +        {
734 +        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
735 +          return TRUE;
736 +        ecode += (ecode[1] << 8) + ecode[2];
737 +        }
738 +      while (*ecode == OP_ALT);
739 +
740 +      DPRINTF(("bracket %d failed\n", number));
741 +
742 +      md->offset_vector[offset] = save_offset1;
743 +      md->offset_vector[offset+1] = save_offset2;
744 +      md->offset_vector[md->offset_end - number] = save_offset3;
745 +
746 +      return FALSE;
747 +      }
748 +
749 +    /* Insufficient room for saving captured contents */
750 +
751 +    else op = OP_BRA;
752 +    }
753 +
754 +  /* Other types of node can be handled by a switch */
755 +
756 +  switch(op)
757 +    {
758 +    case OP_BRA:     /* Non-capturing bracket: optimized */
759 +    DPRINTF(("start bracket 0\n"));
760 +    do
761 +      {
762 +      if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
763 +        return TRUE;
764 +      ecode += (ecode[1] << 8) + ecode[2];
765 +      }
766 +    while (*ecode == OP_ALT);
767 +    DPRINTF(("bracket 0 failed\n"));
768 +    return FALSE;
769 +
770 +    /* Conditional group: compilation checked that there are no more than
771 +    two branches. If the condition is false, skipping the first branch takes us
772 +    past the end if there is only one branch, but that's OK because that is
773 +    exactly what going to the ket would do. */
774 +
775 +    case OP_COND:
776 +    if (ecode[3] == OP_CREF)         /* Condition is extraction test */
777 +      {
778 +      int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled ref number */
779 +      return match(eptr,
780 +        ecode + ((offset < offset_top && md->offset_vector[offset] >= 0)?
781 +          6 : 3 + (ecode[1] << 8) + ecode[2]),
782 +        offset_top, md, ims, eptrb, match_isgroup);
783 +      }
784 +
785 +    /* The condition is an assertion. Call match() to evaluate it - setting
786 +    the final argument TRUE causes it to stop at the end of an assertion. */
787 +
788 +    else
789 +      {
790 +      if (match(eptr, ecode+3, offset_top, md, ims, NULL,
791 +          match_condassert | match_isgroup))
792 +        {
793 +        ecode += 3 + (ecode[4] << 8) + ecode[5];
794 +        while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
795 +        }
796 +      else ecode += (ecode[1] << 8) + ecode[2];
797 +      return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
798 +      }
799 +    /* Control never reaches here */
800 +
801 +    /* Skip over conditional reference or large extraction number data if
802 +    encountered. */
803 +
804 +    case OP_CREF:
805 +    case OP_BRANUMBER:
806 +    ecode += 3;
807 +    break;
808 +
809 +    /* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched
810 +    an empty string - recursion will then try other alternatives, if any. */
811 +
812 +    case OP_END:
813 +    if (md->notempty && eptr == md->start_match) return FALSE;
814 +    md->end_match_ptr = eptr;          /* Record where we ended */
815 +    md->end_offset_top = offset_top;   /* and how many extracts were taken */
816 +    return TRUE;
817 +
818 +    /* Change option settings */
819 +
820 +    case OP_OPT:
821 +    ims = ecode[1];
822 +    ecode += 2;
823 +    DPRINTF(("ims set to %02lx\n", ims));
824 +    break;
825 +
826 +    /* Assertion brackets. Check the alternative branches in turn - the
827 +    matching won't pass the KET for an assertion. If any one branch matches,
828 +    the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
829 +    start of each branch to move the current point backwards, so the code at
830 +    this level is identical to the lookahead case. */
831 +
832 +    case OP_ASSERT:
833 +    case OP_ASSERTBACK:
834 +    do
835 +      {
836 +      if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break;
837 +      ecode += (ecode[1] << 8) + ecode[2];
838 +      }
839 +    while (*ecode == OP_ALT);
840 +    if (*ecode == OP_KET) return FALSE;
841 +
842 +    /* If checking an assertion for a condition, return TRUE. */
843 +
844 +    if ((flags & match_condassert) != 0) return TRUE;
845 +
846 +    /* Continue from after the assertion, updating the offsets high water
847 +    mark, since extracts may have been taken during the assertion. */
848 +
849 +    do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
850 +    ecode += 3;
851 +    offset_top = md->end_offset_top;
852 +    continue;
853 +
854 +    /* Negative assertion: all branches must fail to match */
855 +
856 +    case OP_ASSERT_NOT:
857 +    case OP_ASSERTBACK_NOT:
858 +    do
859 +      {
860 +      if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup))
861 +        return FALSE;
862 +      ecode += (ecode[1] << 8) + ecode[2];
863 +      }
864 +    while (*ecode == OP_ALT);
865 +
866 +    if ((flags & match_condassert) != 0) return TRUE;
867 +
868 +    ecode += 3;
869 +    continue;
870 +
871 +    /* Move the subject pointer back. This occurs only at the start of
872 +    each branch of a lookbehind assertion. If we are too close to the start to
873 +    move back, this match function fails. When working with UTF-8 we move
874 +    back a number of characters, not bytes. */
875 +
876 +    case OP_REVERSE:
877 +#ifdef SUPPORT_UTF8
878 +    c = (ecode[1] << 8) + ecode[2];
879 +    for (i = 0; i < c; i++)
880 +      {
881 +      eptr--;
882 +      BACKCHAR(eptr)
883 +      }
884 +#else
885 +    eptr -= (ecode[1] << 8) + ecode[2];
886 +#endif
887 +
888 +    if (eptr < md->start_subject) return FALSE;
889 +    ecode += 3;
890 +    break;
891 +
892 +    /* Recursion matches the current regex, nested. If there are any capturing
893 +    brackets started but not finished, we have to save their starting points
894 +    and reinstate them after the recursion. However, we don't know how many
895 +    such there are (offset_top records the completed total) so we just have
896 +    to save all the potential data. There may be up to 99 such values, which
897 +    is a bit large to put on the stack, but using malloc for small numbers
898 +    seems expensive. As a compromise, the stack is used when there are fewer
899 +    than 16 values to store; otherwise malloc is used. A problem is what to do
900 +    if the malloc fails ... there is no way of returning to the top level with
901 +    an error. Save the top 15 values on the stack, and accept that the rest
902 +    may be wrong. */
903 +
904 +    case OP_RECURSE:
905 +      {
906 +      BOOL rc;
907 +      int *save;
908 +      int stacksave[15];
909 +
910 +      c = md->offset_max;
911 +
912 +      if (c < 16) save = stacksave; else
913 +        {
914 +        save = (int *)(pcre_malloc)((c+1) * sizeof(int));
915 +        if (save == NULL)
916 +          {
917 +          save = stacksave;
918 +          c = 15;
919 +          }
920 +        }
921 +
922 +      for (i = 1; i <= c; i++)
923 +        save[i] = md->offset_vector[md->offset_end - i];
924 +      rc = match(eptr, md->start_pattern, offset_top, md, ims, eptrb,
925 +        match_isgroup);
926 +      for (i = 1; i <= c; i++)
927 +        md->offset_vector[md->offset_end - i] = save[i];
928 +      if (save != stacksave) (pcre_free)(save);
929 +      if (!rc) return FALSE;
930 +
931 +      /* In case the recursion has set more capturing values, save the final
932 +      number, then move along the subject till after the recursive match,
933 +      and advance one byte in the pattern code. */
934 +
935 +      offset_top = md->end_offset_top;
936 +      eptr = md->end_match_ptr;
937 +      ecode++;
938 +      }
939 +    break;
940 +
941 +    /* "Once" brackets are like assertion brackets except that after a match,
942 +    the point in the subject string is not moved back. Thus there can never be
943 +    a move back into the brackets. Check the alternative branches in turn - the
944 +    matching won't pass the KET for this kind of subpattern. If any one branch
945 +    matches, we carry on as at the end of a normal bracket, leaving the subject
946 +    pointer. */
947 +
948 +    case OP_ONCE:
949 +      {
950 +      const uschar *prev = ecode;
951 +      const uschar *saved_eptr = eptr;
952 +
953 +      do
954 +        {
955 +        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
956 +          break;
957 +        ecode += (ecode[1] << 8) + ecode[2];
958 +        }
959 +      while (*ecode == OP_ALT);
960 +
961 +      /* If hit the end of the group (which could be repeated), fail */
962 +
963 +      if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
964 +
965 +      /* Continue as from after the assertion, updating the offsets high water
966 +      mark, since extracts may have been taken. */
967 +
968 +      do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
969 +
970 +      offset_top = md->end_offset_top;
971 +      eptr = md->end_match_ptr;
972 +
973 +      /* For a non-repeating ket, just continue at this level. This also
974 +      happens for a repeating ket if no characters were matched in the group.
975 +      This is the forcible breaking of infinite loops as implemented in Perl
976 +      5.005. If there is an options reset, it will get obeyed in the normal
977 +      course of events. */
978 +
979 +      if (*ecode == OP_KET || eptr == saved_eptr)
980 +        {
981 +        ecode += 3;
982 +        break;
983 +        }
984 +
985 +      /* The repeating kets try the rest of the pattern or restart from the
986 +      preceding bracket, in the appropriate order. We need to reset any options
987 +      that changed within the bracket before re-running it, so check the next
988 +      opcode. */
989 +
990 +      if (ecode[3] == OP_OPT)
991 +        {
992 +        ims = (ims & ~PCRE_IMS) | ecode[4];
993 +        DPRINTF(("ims set to %02lx at group repeat\n", ims));
994 +        }
995 +
996 +      if (*ecode == OP_KETRMIN)
997 +        {
998 +        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
999 +            match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
1000 +              return TRUE;
1001 +        }
1002 +      else  /* OP_KETRMAX */
1003 +        {
1004 +        if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
1005 +            match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
1006 +        }
1007 +      }
1008 +    return FALSE;
1009 +
1010 +    /* An alternation is the end of a branch; scan along to find the end of the
1011 +    bracketed group and go to there. */
1012 +
1013 +    case OP_ALT:
1014 +    do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
1015 +    break;
1016 +
1017 +    /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
1018 +    that it may occur zero times. It may repeat infinitely, or not at all -
1019 +    i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
1020 +    repeat limits are compiled as a number of copies, with the optional ones
1021 +    preceded by BRAZERO or BRAMINZERO. */
1022 +
1023 +    case OP_BRAZERO:
1024 +      {
1025 +      const uschar *next = ecode+1;
1026 +      if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup))
1027 +        return TRUE;
1028 +      do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
1029 +      ecode = next + 3;
1030 +      }
1031 +    break;
1032 +
1033 +    case OP_BRAMINZERO:
1034 +      {
1035 +      const uschar *next = ecode+1;
1036 +      do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
1037 +      if (match(eptr, next+3, offset_top, md, ims, eptrb, match_isgroup))
1038 +        return TRUE;
1039 +      ecode++;
1040 +      }
1041 +    break;
1042 +
1043 +    /* End of a group, repeated or non-repeating. If we are at the end of
1044 +    an assertion "group", stop matching and return TRUE, but record the
1045 +    current high water mark for use by positive assertions. Do this also
1046 +    for the "once" (not-backup up) groups. */
1047 +
1048 +    case OP_KET:
1049 +    case OP_KETRMIN:
1050 +    case OP_KETRMAX:
1051 +      {
1052 +      const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
1053 +      const uschar *saved_eptr = eptrb->saved_eptr;
1054 +
1055 +      eptrb = eptrb->prev;    /* Back up the stack of bracket start pointers */
1056 +
1057 +      if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
1058 +          *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
1059 +          *prev == OP_ONCE)
1060 +        {
1061 +        md->end_match_ptr = eptr;      /* For ONCE */
1062 +        md->end_offset_top = offset_top;
1063 +        return TRUE;
1064 +        }
1065 +
1066 +      /* In all other cases except a conditional group we have to check the
1067 +      group number back at the start and if necessary complete handling an
1068 +      extraction by setting the offsets and bumping the high water mark. */
1069 +
1070 +      if (*prev != OP_COND)
1071 +        {
1072 +        int offset;
1073 +        int number = *prev - OP_BRA;
1074 +
1075 +        /* For extended extraction brackets (large number), we have to fish out
1076 +        the number from a dummy opcode at the start. */
1077 +
1078 +        if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5];
1079 +        offset = number << 1;
1080 +
1081 +#ifdef DEBUG
1082 +        PCRE_PRINTF("end bracket %d", number);
1083 +        PCRE_PRINTF("\n");
1084 +#endif
1085 +
1086 +        if (number > 0)
1087 +          {
1088 +          if (offset >= md->offset_max) md->offset_overflow = TRUE; else
1089 +            {
1090 +            md->offset_vector[offset] =
1091 +              md->offset_vector[md->offset_end - number];
1092 +            md->offset_vector[offset+1] = eptr - md->start_subject;
1093 +            if (offset_top <= offset) offset_top = offset + 2;
1094 +            }
1095 +          }
1096 +        }
1097 +
1098 +      /* Reset the value of the ims flags, in case they got changed during
1099 +      the group. */
1100 +
1101 +      ims = original_ims;
1102 +      DPRINTF(("ims reset to %02lx\n", ims));
1103 +
1104 +      /* For a non-repeating ket, just continue at this level. This also
1105 +      happens for a repeating ket if no characters were matched in the group.
1106 +      This is the forcible breaking of infinite loops as implemented in Perl
1107 +      5.005. If there is an options reset, it will get obeyed in the normal
1108 +      course of events. */
1109 +
1110 +      if (*ecode == OP_KET || eptr == saved_eptr)
1111 +        {
1112 +        ecode += 3;
1113 +        break;
1114 +        }
1115 +
1116 +      /* The repeating kets try the rest of the pattern or restart from the
1117 +      preceding bracket, in the appropriate order. */
1118 +
1119 +      if (*ecode == OP_KETRMIN)
1120 +        {
1121 +        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
1122 +            match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
1123 +              return TRUE;
1124 +        }
1125 +      else  /* OP_KETRMAX */
1126 +        {
1127 +        if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
1128 +            match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
1129 +        }
1130 +      }
1131 +    return FALSE;
1132 +
1133 +    /* Start of subject unless notbol, or after internal newline if multiline */
1134 +
1135 +    case OP_CIRC:
1136 +    if (md->notbol && eptr == md->start_subject) return FALSE;
1137 +    if ((ims & PCRE_MULTILINE) != 0)
1138 +      {
1139 +      if (eptr != md->start_subject && eptr[-1] != NEWLINE) return FALSE;
1140 +      ecode++;
1141 +      break;
1142 +      }
1143 +    /* ... else fall through */
1144 +
1145 +    /* Start of subject assertion */
1146 +
1147 +    case OP_SOD:
1148 +    if (eptr != md->start_subject) return FALSE;
1149 +    ecode++;
1150 +    break;
1151 +
1152 +    /* Assert before internal newline if multiline, or before a terminating
1153 +    newline unless endonly is set, else end of subject unless noteol is set. */
1154 +
1155 +    case OP_DOLL:
1156 +    if ((ims & PCRE_MULTILINE) != 0)
1157 +      {
1158 +      if (eptr < md->end_subject) { if (*eptr != NEWLINE) return FALSE; }
1159 +        else { if (md->noteol) return FALSE; }
1160 +      ecode++;
1161 +      break;
1162 +      }
1163 +    else
1164 +      {
1165 +      if (md->noteol) return FALSE;
1166 +      if (!md->endonly)
1167 +        {
1168 +        if (eptr < md->end_subject - 1 ||
1169 +           (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
1170 +
1171 +        ecode++;
1172 +        break;
1173 +        }
1174 +      }
1175 +    /* ... else fall through */
1176 +
1177 +    /* End of subject assertion (\z) */
1178 +
1179 +    case OP_EOD:
1180 +    if (eptr < md->end_subject) return FALSE;
1181 +    ecode++;
1182 +    break;
1183 +
1184 +    /* End of subject or ending \n assertion (\Z) */
1185 +
1186 +    case OP_EODN:
1187 +    if (eptr < md->end_subject - 1 ||
1188 +       (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
1189 +    ecode++;
1190 +    break;
1191 +
1192 +    /* Word boundary assertions */
1193 +
1194 +    case OP_NOT_WORD_BOUNDARY:
1195 +    case OP_WORD_BOUNDARY:
1196 +      {
1197 +      BOOL prev_is_word = (eptr != md->start_subject) &&
1198 +        ((md->ctypes[eptr[-1]] & ctype_word) != 0);
1199 +      BOOL cur_is_word = (eptr < md->end_subject) &&
1200 +        ((md->ctypes[*eptr] & ctype_word) != 0);
1201 +      if ((*ecode++ == OP_WORD_BOUNDARY)?
1202 +           cur_is_word == prev_is_word : cur_is_word != prev_is_word)
1203 +        return FALSE;
1204 +      }
1205 +    break;
1206 +
1207 +    /* Match a single character type; inline for speed */
1208 +
1209 +    case OP_ANY:
1210 +    if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE)
1211 +      return FALSE;
1212 +    if (eptr++ >= md->end_subject) return FALSE;
1213 +#ifdef SUPPORT_UTF8
1214 +    if (md->utf8)
1215 +      while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1216 +#endif
1217 +    ecode++;
1218 +    break;
1219 +
1220 +    case OP_NOT_DIGIT:
1221 +    if (eptr >= md->end_subject ||
1222 +       (md->ctypes[*eptr++] & ctype_digit) != 0)
1223 +      return FALSE;
1224 +    ecode++;
1225 +    break;
1226 +
1227 +    case OP_DIGIT:
1228 +    if (eptr >= md->end_subject ||
1229 +       (md->ctypes[*eptr++] & ctype_digit) == 0)
1230 +      return FALSE;
1231 +    ecode++;
1232 +    break;
1233 +
1234 +    case OP_NOT_WHITESPACE:
1235 +    if (eptr >= md->end_subject ||
1236 +       (md->ctypes[*eptr++] & ctype_space) != 0)
1237 +      return FALSE;
1238 +    ecode++;
1239 +    break;
1240 +
1241 +    case OP_WHITESPACE:
1242 +    if (eptr >= md->end_subject ||
1243 +       (md->ctypes[*eptr++] & ctype_space) == 0)
1244 +      return FALSE;
1245 +    ecode++;
1246 +    break;
1247 +
1248 +    case OP_NOT_WORDCHAR:
1249 +    if (eptr >= md->end_subject ||
1250 +       (md->ctypes[*eptr++] & ctype_word) != 0)
1251 +      return FALSE;
1252 +    ecode++;
1253 +    break;
1254 +
1255 +    case OP_WORDCHAR:
1256 +    if (eptr >= md->end_subject ||
1257 +       (md->ctypes[*eptr++] & ctype_word) == 0)
1258 +      return FALSE;
1259 +    ecode++;
1260 +    break;
1261 +
1262 +    /* Match a back reference, possibly repeatedly. Look past the end of the
1263 +    item to see if there is repeat information following. The code is similar
1264 +    to that for character classes, but repeated for efficiency. Then obey
1265 +    similar code to character type repeats - written out again for speed.
1266 +    However, if the referenced string is the empty string, always treat
1267 +    it as matched, any number of times (otherwise there could be infinite
1268 +    loops). */
1269 +
1270 +    case OP_REF:
1271 +      {
1272 +      int length;
1273 +      int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */
1274 +      ecode += 3;                                     /* Advance past item */
1275 +
1276 +      /* If the reference is unset, set the length to be longer than the amount
1277 +      of subject left; this ensures that every attempt at a match fails. We
1278 +      can't just fail here, because of the possibility of quantifiers with zero
1279 +      minima. */
1280 +
1281 +      length = (offset >= offset_top || md->offset_vector[offset] < 0)?
1282 +        md->end_subject - eptr + 1 :
1283 +        md->offset_vector[offset+1] - md->offset_vector[offset];
1284 +
1285 +      /* Set up for repetition, or handle the non-repeated case */
1286 +
1287 +      switch (*ecode)
1288 +        {
1289 +        case OP_CRSTAR:
1290 +        case OP_CRMINSTAR:
1291 +        case OP_CRPLUS:
1292 +        case OP_CRMINPLUS:
1293 +        case OP_CRQUERY:
1294 +        case OP_CRMINQUERY:
1295 +        c = *ecode++ - OP_CRSTAR;
1296 +        minimize = (c & 1) != 0;
1297 +        min = rep_min[c];                 /* Pick up values from tables; */
1298 +        max = rep_max[c];                 /* zero for max => infinity */
1299 +        if (max == 0) max = INT_MAX;
1300 +        break;
1301 +
1302 +        case OP_CRRANGE:
1303 +        case OP_CRMINRANGE:
1304 +        minimize = (*ecode == OP_CRMINRANGE);
1305 +        min = (ecode[1] << 8) + ecode[2];
1306 +        max = (ecode[3] << 8) + ecode[4];
1307 +        if (max == 0) max = INT_MAX;
1308 +        ecode += 5;
1309 +        break;
1310 +
1311 +        default:               /* No repeat follows */
1312 +        if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
1313 +        eptr += length;
1314 +        continue;              /* With the main loop */
1315 +        }
1316 +
1317 +      /* If the length of the reference is zero, just continue with the
1318 +      main loop. */
1319 +
1320 +      if (length == 0) continue;
1321 +
1322 +      /* First, ensure the minimum number of matches are present. We get back
1323 +      the length of the reference string explicitly rather than passing the
1324 +      address of eptr, so that eptr can be a register variable. */
1325 +
1326 +      for (i = 1; i <= min; i++)
1327 +        {
1328 +        if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
1329 +        eptr += length;
1330 +        }
1331 +
1332 +      /* If min = max, continue at the same level without recursion.
1333 +      They are not both allowed to be zero. */
1334 +
1335 +      if (min == max) continue;
1336 +
1337 +      /* If minimizing, keep trying and advancing the pointer */
1338 +
1339 +      if (minimize)
1340 +        {
1341 +        for (i = min;; i++)
1342 +          {
1343 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1344 +            return TRUE;
1345 +          if (i >= max || !match_ref(offset, eptr, length, md, ims))
1346 +            return FALSE;
1347 +          eptr += length;
1348 +          }
1349 +        /* Control never gets here */
1350 +        }
1351 +
1352 +      /* If maximizing, find the longest string and work backwards */
1353 +
1354 +      else
1355 +        {
1356 +        const uschar *pp = eptr;
1357 +        for (i = min; i < max; i++)
1358 +          {
1359 +          if (!match_ref(offset, eptr, length, md, ims)) break;
1360 +          eptr += length;
1361 +          }
1362 +        while (eptr >= pp)
1363 +          {
1364 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1365 +            return TRUE;
1366 +          eptr -= length;
1367 +          }
1368 +        return FALSE;
1369 +        }
1370 +      }
1371 +    /* Control never gets here */
1372 +
1373 +
1374 +
1375 +    /* Match a character class, possibly repeatedly. Look past the end of the
1376 +    item to see if there is repeat information following. Then obey similar
1377 +    code to character type repeats - written out again for speed. */
1378 +
1379 +    case OP_CLASS:
1380 +      {
1381 +      const uschar *data = ecode + 1;  /* Save for matching */
1382 +      ecode += 33;                     /* Advance past the item */
1383 +
1384 +      switch (*ecode)
1385 +        {
1386 +        case OP_CRSTAR:
1387 +        case OP_CRMINSTAR:
1388 +        case OP_CRPLUS:
1389 +        case OP_CRMINPLUS:
1390 +        case OP_CRQUERY:
1391 +        case OP_CRMINQUERY:
1392 +        c = *ecode++ - OP_CRSTAR;
1393 +        minimize = (c & 1) != 0;
1394 +        min = rep_min[c];                 /* Pick up values from tables; */
1395 +        max = rep_max[c];                 /* zero for max => infinity */
1396 +        if (max == 0) max = INT_MAX;
1397 +        break;
1398 +
1399 +        case OP_CRRANGE:
1400 +        case OP_CRMINRANGE:
1401 +        minimize = (*ecode == OP_CRMINRANGE);
1402 +        min = (ecode[1] << 8) + ecode[2];
1403 +        max = (ecode[3] << 8) + ecode[4];
1404 +        if (max == 0) max = INT_MAX;
1405 +        ecode += 5;
1406 +        break;
1407 +
1408 +        default:               /* No repeat follows */
1409 +        min = max = 1;
1410 +        break;
1411 +        }
1412 +
1413 +      /* First, ensure the minimum number of matches are present. */
1414 +
1415 +      for (i = 1; i <= min; i++)
1416 +        {
1417 +        if (eptr >= md->end_subject) return FALSE;
1418 +        GETCHARINC(c, eptr)         /* Get character; increment eptr */
1419 +
1420 +#ifdef SUPPORT_UTF8
1421 +        /* We do not yet support class members > 255 */
1422 +        if (c > 255) return FALSE;
1423 +#endif
1424 +
1425 +        if ((data[c/8] & (1 << (c&7))) != 0) continue;
1426 +        return FALSE;
1427 +        }
1428 +
1429 +      /* If max == min we can continue with the main loop without the
1430 +      need to recurse. */
1431 +
1432 +      if (min == max) continue;
1433 +
1434 +      /* If minimizing, keep testing the rest of the expression and advancing
1435 +      the pointer while it matches the class. */
1436 +
1437 +      if (minimize)
1438 +        {
1439 +        for (i = min;; i++)
1440 +          {
1441 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1442 +            return TRUE;
1443 +          if (i >= max || eptr >= md->end_subject) return FALSE;
1444 +          GETCHARINC(c, eptr)       /* Get character; increment eptr */
1445 +
1446 +#ifdef SUPPORT_UTF8
1447 +          /* We do not yet support class members > 255 */
1448 +          if (c > 255) return FALSE;
1449 +#endif
1450 +          if ((data[c/8] & (1 << (c&7))) != 0) continue;
1451 +          return FALSE;
1452 +          }
1453 +        /* Control never gets here */
1454 +        }
1455 +
1456 +      /* If maximizing, find the longest possible run, then work backwards. */
1457 +
1458 +      else
1459 +        {
1460 +        const uschar *pp = eptr;
1461 +        int len = 1;
1462 +        for (i = min; i < max; i++)
1463 +          {
1464 +          if (eptr >= md->end_subject) break;
1465 +          GETCHARLEN(c, eptr, len)  /* Get character, set length if UTF-8 */
1466 +
1467 +#ifdef SUPPORT_UTF8
1468 +          /* We do not yet support class members > 255 */
1469 +          if (c > 255) break;
1470 +#endif
1471 +          if ((data[c/8] & (1 << (c&7))) == 0) break;
1472 +          eptr += len;
1473 +          }
1474 +
1475 +        while (eptr >= pp)
1476 +          {
1477 +          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1478 +            return TRUE;
1479 +
1480 +#ifdef SUPPORT_UTF8
1481 +          BACKCHAR(eptr)
1482 +#endif
1483 +          }
1484 +        return FALSE;
1485 +        }
1486 +      }
1487 +    /* Control never gets here */
1488 +
1489 +    /* Match a run of characters */
1490 +
1491 +    case OP_CHARS:
1492 +      {
1493 +      register int length = ecode[1];
1494 +      ecode += 2;
1495 +
1496 +#ifdef DEBUG    /* Sigh. Some compilers never learn. */
1497 +      if (eptr >= md->end_subject)
1498 +        PCRE_PRINTF("matching subject <null> against pattern ");
1499 +      else
1500 +        {
1501 +        PCRE_PRINTF("matching subject ");
1502 +        pchars(eptr, length, TRUE, md);
1503 +        PCRE_PRINTF(" against pattern ");
1504 +        }
1505 +      pchars(ecode, length, FALSE, md);
1506 +      PCRE_PRINTF("\n");
1507 +#endif
1508 +
1509 +      if (length > md->end_subject - eptr) return FALSE;
1510 +      if ((ims & PCRE_CASELESS) != 0)
1511 +        {
1512 +        while (length-- > 0)
1513 +          if (md->lcc[*ecode++] != md->lcc[*eptr++])
1514 +            return FALSE;
1515 +        }
1516 +      else
1517 +        {
1518 +        while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
1519 +        }
1520 +      }
1521 +    break;
1522 +
1523 +    /* Match a single character repeatedly; different opcodes share code. */
1524 +
1525 +    case OP_EXACT:
1526 +    min = max = (ecode[1] << 8) + ecode[2];
1527 +    ecode += 3;
1528 +    goto REPEATCHAR;
1529 +
1530 +    case OP_UPTO:
1531 +    case OP_MINUPTO:
1532 +    min = 0;
1533 +    max = (ecode[1] << 8) + ecode[2];
1534 +    minimize = *ecode == OP_MINUPTO;
1535 +    ecode += 3;
1536 +    goto REPEATCHAR;
1537 +
1538 +    case OP_STAR:
1539 +    case OP_MINSTAR:
1540 +    case OP_PLUS:
1541 +    case OP_MINPLUS:
1542 +    case OP_QUERY:
1543 +    case OP_MINQUERY:
1544 +    c = *ecode++ - OP_STAR;
1545 +    minimize = (c & 1) != 0;
1546 +    min = rep_min[c];                 /* Pick up values from tables; */
1547 +    max = rep_max[c];                 /* zero for max => infinity */
1548 +    if (max == 0) max = INT_MAX;
1549 +
1550 +    /* Common code for all repeated single-character matches. We can give
1551 +    up quickly if there are fewer than the minimum number of characters left in
1552 +    the subject. */
1553 +
1554 +    REPEATCHAR:
1555 +    if (min > md->end_subject - eptr) return FALSE;
1556 +    c = *ecode++;
1557 +
1558 +    /* The code is duplicated for the caseless and caseful cases, for speed,
1559 +    since matching characters is likely to be quite common. First, ensure the
1560 +    minimum number of matches are present. If min = max, continue at the same
1561 +    level without recursing. Otherwise, if minimizing, keep trying the rest of
1562 +    the expression and advancing one matching character if failing, up to the
1563 +    maximum. Alternatively, if maximizing, find the maximum number of
1564 +    characters and work backwards. */
1565 +
1566 +    DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
1567 +      max, eptr));
1568 +
1569 +    if ((ims & PCRE_CASELESS) != 0)
1570 +      {
1571 +      c = md->lcc[c];
1572 +      for (i = 1; i <= min; i++)
1573 +        if (c != md->lcc[*eptr++]) return FALSE;
1574 +      if (min == max) continue;
1575 +      if (minimize)
1576 +        {
1577 +        for (i = min;; i++)
1578 +          {
1579 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1580 +            return TRUE;
1581 +          if (i >= max || eptr >= md->end_subject ||
1582 +              c != md->lcc[*eptr++])
1583 +            return FALSE;
1584 +          }
1585 +        /* Control never gets here */
1586 +        }
1587 +      else
1588 +        {
1589 +        const uschar *pp = eptr;
1590 +        for (i = min; i < max; i++)
1591 +          {
1592 +          if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
1593 +          eptr++;
1594 +          }
1595 +        while (eptr >= pp)
1596 +          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1597 +            return TRUE;
1598 +        return FALSE;
1599 +        }
1600 +      /* Control never gets here */
1601 +      }
1602 +
1603 +    /* Caseful comparisons */
1604 +
1605 +    else
1606 +      {
1607 +      for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
1608 +      if (min == max) continue;
1609 +      if (minimize)
1610 +        {
1611 +        for (i = min;; i++)
1612 +          {
1613 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1614 +            return TRUE;
1615 +          if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
1616 +          }
1617 +        /* Control never gets here */
1618 +        }
1619 +      else
1620 +        {
1621 +        const uschar *pp = eptr;
1622 +        for (i = min; i < max; i++)
1623 +          {
1624 +          if (eptr >= md->end_subject || c != *eptr) break;
1625 +          eptr++;
1626 +          }
1627 +        while (eptr >= pp)
1628 +         if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1629 +           return TRUE;
1630 +        return FALSE;
1631 +        }
1632 +      }
1633 +    /* Control never gets here */
1634 +
1635 +    /* Match a negated single character */
1636 +
1637 +    case OP_NOT:
1638 +    if (eptr >= md->end_subject) return FALSE;
1639 +    ecode++;
1640 +    if ((ims & PCRE_CASELESS) != 0)
1641 +      {
1642 +      if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
1643 +      }
1644 +    else
1645 +      {
1646 +      if (*ecode++ == *eptr++) return FALSE;
1647 +      }
1648 +    break;
1649 +
1650 +    /* Match a negated single character repeatedly. This is almost a repeat of
1651 +    the code for a repeated single character, but I haven't found a nice way of
1652 +    commoning these up that doesn't require a test of the positive/negative
1653 +    option for each character match. Maybe that wouldn't add very much to the
1654 +    time taken, but character matching *is* what this is all about... */
1655 +
1656 +    case OP_NOTEXACT:
1657 +    min = max = (ecode[1] << 8) + ecode[2];
1658 +    ecode += 3;
1659 +    goto REPEATNOTCHAR;
1660 +
1661 +    case OP_NOTUPTO:
1662 +    case OP_NOTMINUPTO:
1663 +    min = 0;
1664 +    max = (ecode[1] << 8) + ecode[2];
1665 +    minimize = *ecode == OP_NOTMINUPTO;
1666 +    ecode += 3;
1667 +    goto REPEATNOTCHAR;
1668 +
1669 +    case OP_NOTSTAR:
1670 +    case OP_NOTMINSTAR:
1671 +    case OP_NOTPLUS:
1672 +    case OP_NOTMINPLUS:
1673 +    case OP_NOTQUERY:
1674 +    case OP_NOTMINQUERY:
1675 +    c = *ecode++ - OP_NOTSTAR;
1676 +    minimize = (c & 1) != 0;
1677 +    min = rep_min[c];                 /* Pick up values from tables; */
1678 +    max = rep_max[c];                 /* zero for max => infinity */
1679 +    if (max == 0) max = INT_MAX;
1680 +
1681 +    /* Common code for all repeated single-character matches. We can give
1682 +    up quickly if there are fewer than the minimum number of characters left in
1683 +    the subject. */
1684 +
1685 +    REPEATNOTCHAR:
1686 +    if (min > md->end_subject - eptr) return FALSE;
1687 +    c = *ecode++;
1688 +
1689 +    /* The code is duplicated for the caseless and caseful cases, for speed,
1690 +    since matching characters is likely to be quite common. First, ensure the
1691 +    minimum number of matches are present. If min = max, continue at the same
1692 +    level without recursing. Otherwise, if minimizing, keep trying the rest of
1693 +    the expression and advancing one matching character if failing, up to the
1694 +    maximum. Alternatively, if maximizing, find the maximum number of
1695 +    characters and work backwards. */
1696 +
1697 +    DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
1698 +      max, eptr));
1699 +
1700 +    if ((ims & PCRE_CASELESS) != 0)
1701 +      {
1702 +      c = md->lcc[c];
1703 +      for (i = 1; i <= min; i++)
1704 +        if (c == md->lcc[*eptr++]) return FALSE;
1705 +      if (min == max) continue;
1706 +      if (minimize)
1707 +        {
1708 +        for (i = min;; i++)
1709 +          {
1710 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1711 +            return TRUE;
1712 +          if (i >= max || eptr >= md->end_subject ||
1713 +              c == md->lcc[*eptr++])
1714 +            return FALSE;
1715 +          }
1716 +        /* Control never gets here */
1717 +        }
1718 +      else
1719 +        {
1720 +        const uschar *pp = eptr;
1721 +        for (i = min; i < max; i++)
1722 +          {
1723 +          if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
1724 +          eptr++;
1725 +          }
1726 +        while (eptr >= pp)
1727 +          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1728 +            return TRUE;
1729 +        return FALSE;
1730 +        }
1731 +      /* Control never gets here */
1732 +      }
1733 +
1734 +    /* Caseful comparisons */
1735 +
1736 +    else
1737 +      {
1738 +      for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
1739 +      if (min == max) continue;
1740 +      if (minimize)
1741 +        {
1742 +        for (i = min;; i++)
1743 +          {
1744 +          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1745 +            return TRUE;
1746 +          if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
1747 +          }
1748 +        /* Control never gets here */
1749 +        }
1750 +      else
1751 +        {
1752 +        const uschar *pp = eptr;
1753 +        for (i = min; i < max; i++)
1754 +          {
1755 +          if (eptr >= md->end_subject || c == *eptr) break;
1756 +          eptr++;
1757 +          }
1758 +        while (eptr >= pp)
1759 +         if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1760 +           return TRUE;
1761 +        return FALSE;
1762 +        }
1763 +      }
1764 +    /* Control never gets here */
1765 +
1766 +    /* Match a single character type repeatedly; several different opcodes
1767 +    share code. This is very similar to the code for single characters, but we
1768 +    repeat it in the interests of efficiency. */
1769 +
1770 +    case OP_TYPEEXACT:
1771 +    min = max = (ecode[1] << 8) + ecode[2];
1772 +    minimize = TRUE;
1773 +    ecode += 3;
1774 +    goto REPEATTYPE;
1775 +
1776 +    case OP_TYPEUPTO:
1777 +    case OP_TYPEMINUPTO:
1778 +    min = 0;
1779 +    max = (ecode[1] << 8) + ecode[2];
1780 +    minimize = *ecode == OP_TYPEMINUPTO;
1781 +    ecode += 3;
1782 +    goto REPEATTYPE;
1783 +
1784 +    case OP_TYPESTAR:
1785 +    case OP_TYPEMINSTAR:
1786 +    case OP_TYPEPLUS:
1787 +    case OP_TYPEMINPLUS:
1788 +    case OP_TYPEQUERY:
1789 +    case OP_TYPEMINQUERY:
1790 +    c = *ecode++ - OP_TYPESTAR;
1791 +    minimize = (c & 1) != 0;
1792 +    min = rep_min[c];                 /* Pick up values from tables; */
1793 +    max = rep_max[c];                 /* zero for max => infinity */
1794 +    if (max == 0) max = INT_MAX;
1795 +
1796 +    /* Common code for all repeated single character type matches */
1797 +
1798 +    REPEATTYPE:
1799 +    ctype = *ecode++;      /* Code for the character type */
1800 +
1801 +    /* First, ensure the minimum number of matches are present. Use inline
1802 +    code for maximizing the speed, and do the type test once at the start
1803 +    (i.e. keep it out of the loop). Also we can test that there are at least
1804 +    the minimum number of bytes before we start, except when doing '.' in
1805 +    UTF8 mode. Leave the test in in all cases; in the special case we have
1806 +    to test after each character. */
1807 +
1808 +    if (min > md->end_subject - eptr) return FALSE;
1809 +    if (min > 0) switch(ctype)
1810 +      {
1811 +      case OP_ANY:
1812 +#ifdef SUPPORT_UTF8
1813 +      if (md->utf8)
1814 +        {
1815 +        for (i = 1; i <= min; i++)
1816 +          {
1817 +          if (eptr >= md->end_subject ||
1818 +             (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0))
1819 +            return FALSE;
1820 +          while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1821 +          }
1822 +        break;
1823 +        }
1824 +#endif
1825 +      /* Non-UTF8 can be faster */
1826 +      if ((ims & PCRE_DOTALL) == 0)
1827 +        { for (i = 1; i <= min; i++) if (*eptr++ == NEWLINE) return FALSE; }
1828 +      else eptr += min;
1829 +      break;
1830 +
1831 +      case OP_NOT_DIGIT:
1832 +      for (i = 1; i <= min; i++)
1833 +        if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
1834 +      break;
1835 +
1836 +      case OP_DIGIT:
1837 +      for (i = 1; i <= min; i++)
1838 +        if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
1839 +      break;
1840 +
1841 +      case OP_NOT_WHITESPACE:
1842 +      for (i = 1; i <= min; i++)
1843 +        if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
1844 +      break;
1845 +
1846 +      case OP_WHITESPACE:
1847 +      for (i = 1; i <= min; i++)
1848 +        if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
1849 +      break;
1850 +
1851 +      case OP_NOT_WORDCHAR:
1852 +      for (i = 1; i <= min; i++)
1853 +        if ((md->ctypes[*eptr++] & ctype_word) != 0)
1854 +          return FALSE;
1855 +      break;
1856 +
1857 +      case OP_WORDCHAR:
1858 +      for (i = 1; i <= min; i++)
1859 +        if ((md->ctypes[*eptr++] & ctype_word) == 0)
1860 +          return FALSE;
1861 +      break;
1862 +      }
1863 +
1864 +    /* If min = max, continue at the same level without recursing */
1865 +
1866 +    if (min == max) continue;
1867 +
1868 +    /* If minimizing, we have to test the rest of the pattern before each
1869 +    subsequent match. */
1870 +
1871 +    if (minimize)
1872 +      {
1873 +      for (i = min;; i++)
1874 +        {
1875 +        if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE;
1876 +        if (i >= max || eptr >= md->end_subject) return FALSE;
1877 +
1878 +        c = *eptr++;
1879 +        switch(ctype)
1880 +          {
1881 +          case OP_ANY:
1882 +          if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return FALSE;
1883 +#ifdef SUPPORT_UTF8
1884 +          if (md->utf8)
1885 +            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1886 +#endif
1887 +          break;
1888 +
1889 +          case OP_NOT_DIGIT:
1890 +          if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
1891 +          break;
1892 +
1893 +          case OP_DIGIT:
1894 +          if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
1895 +          break;
1896 +
1897 +          case OP_NOT_WHITESPACE:
1898 +          if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
1899 +          break;
1900 +
1901 +          case OP_WHITESPACE:
1902 +          if  ((md->ctypes[c] & ctype_space) == 0) return FALSE;
1903 +          break;
1904 +
1905 +          case OP_NOT_WORDCHAR:
1906 +          if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
1907 +          break;
1908 +
1909 +          case OP_WORDCHAR:
1910 +          if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
1911 +          break;
1912 +          }
1913 +        }
1914 +      /* Control never gets here */
1915 +      }
1916 +
1917 +    /* If maximizing it is worth using inline code for speed, doing the type
1918 +    test once at the start (i.e. keep it out of the loop). */
1919 +
1920 +    else
1921 +      {
1922 +      const uschar *pp = eptr;
1923 +      switch(ctype)
1924 +        {
1925 +        case OP_ANY:
1926 +
1927 +        /* Special code is required for UTF8, but when the maximum is unlimited
1928 +        we don't need it. */
1929 +
1930 +#ifdef SUPPORT_UTF8
1931 +        if (md->utf8 && max < INT_MAX)
1932 +          {
1933 +          if ((ims & PCRE_DOTALL) == 0)
1934 +            {
1935 +            for (i = min; i < max; i++)
1936 +              {
1937 +              if (eptr >= md->end_subject || *eptr++ == NEWLINE) break;
1938 +              while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1939 +              }
1940 +            }
1941 +          else
1942 +            {
1943 +            for (i = min; i < max; i++)
1944 +              {
1945 +              eptr++;
1946 +              while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1947 +              }
1948 +            }
1949 +          break;
1950 +          }
1951 +#endif
1952 +        /* Non-UTF8 can be faster */
1953 +        if ((ims & PCRE_DOTALL) == 0)
1954 +          {
1955 +          for (i = min; i < max; i++)
1956 +            {
1957 +            if (eptr >= md->end_subject || *eptr == NEWLINE) break;
1958 +            eptr++;
1959 +            }
1960 +          }
1961 +        else
1962 +          {
1963 +          c = max - min;
1964 +          if (c > md->end_subject - eptr) c = md->end_subject - eptr;
1965 +          eptr += c;
1966 +          }
1967 +        break;
1968 +
1969 +        case OP_NOT_DIGIT:
1970 +        for (i = min; i < max; i++)
1971 +          {
1972 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
1973 +            break;
1974 +          eptr++;
1975 +          }
1976 +        break;
1977 +
1978 +        case OP_DIGIT:
1979 +        for (i = min; i < max; i++)
1980 +          {
1981 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
1982 +            break;
1983 +          eptr++;
1984 +          }
1985 +        break;
1986 +
1987 +        case OP_NOT_WHITESPACE:
1988 +        for (i = min; i < max; i++)
1989 +          {
1990 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
1991 +            break;
1992 +          eptr++;
1993 +          }
1994 +        break;
1995 +
1996 +        case OP_WHITESPACE:
1997 +        for (i = min; i < max; i++)
1998 +          {
1999 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
2000 +            break;
2001 +          eptr++;
2002 +          }
2003 +        break;
2004 +
2005 +        case OP_NOT_WORDCHAR:
2006 +        for (i = min; i < max; i++)
2007 +          {
2008 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
2009 +            break;
2010 +          eptr++;
2011 +          }
2012 +        break;
2013 +
2014 +        case OP_WORDCHAR:
2015 +        for (i = min; i < max; i++)
2016 +          {
2017 +          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
2018 +            break;
2019 +          eptr++;
2020 +          }
2021 +        break;
2022 +        }
2023 +
2024 +      while (eptr >= pp)
2025 +        {
2026 +        if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
2027 +          return TRUE;
2028 +#ifdef SUPPORT_UTF8
2029 +        if (md->utf8)
2030 +          while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--;
2031 +#endif
2032 +        }
2033 +      return FALSE;
2034 +      }
2035 +    /* Control never gets here */
2036 +
2037 +    /* There's been some horrible disaster. */
2038 +
2039 +    default:
2040 +    DPRINTF(("Unknown opcode %d\n", *ecode));
2041 +    md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
2042 +    return FALSE;
2043 +    }
2044 +
2045 +  /* Do not stick any code in here without much thought; it is assumed
2046 +  that "continue" in the code above comes out to here to repeat the main
2047 +  loop. */
2048 +
2049 +  }             /* End of main loop */
2050 +/* Control never reaches here */
2051 +}
2052 +
2053 +
2054 +/*************************************************
2055 +*         Execute a Regular Expression           *
2056 +*************************************************/
2057 +
2058 +/* This function applies a compiled re to a subject string and picks out
2059 +portions of the string if it matches. Two elements in the vector are set for
2060 +each substring: the offsets to the start and end of the substring.
2061 +
2062 +Arguments:
2063 +  external_re     points to the compiled expression
2064 +  external_extra  points to "hints" from pcre_study() or is NULL
2065 +  subject         points to the subject string
2066 +  length          length of subject string (may contain binary zeros)
2067 +  start_offset    where to start in the subject string
2068 +  options         option bits
2069 +  offsets         points to a vector of ints to be filled in with offsets
2070 +  offsetcount     the number of elements in the vector
2071 +
2072 +Returns:          > 0 => success; value is the number of elements filled in
2073 +                  = 0 => success, but offsets is not big enough
2074 +                   -1 => failed to match
2075 +                 < -1 => some kind of unexpected problem
2076 +*/
2077 +
2078 +int
2079 +pcre_exec(const pcre *external_re, const pcre_extra *external_extra,
2080 +  const char *subject, int length, int start_offset, int options, int *offsets,
2081 +  int offsetcount)
2082 +{
2083 +int resetcount, ocount;
2084 +int first_char = -1;
2085 +int req_char = -1;
2086 +int req_char2 = -1;
2087 +unsigned long int ims = 0;
2088 +match_data match_block;
2089 +const uschar *start_bits = NULL;
2090 +const uschar *start_match = (const uschar *)subject + start_offset;
2091 +const uschar *end_subject;
2092 +const uschar *req_char_ptr = start_match - 1;
2093 +const real_pcre *re = (const real_pcre *)external_re;
2094 +const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
2095 +BOOL using_temporary_offsets = FALSE;
2096 +BOOL anchored;
2097 +BOOL startline;
2098 +
2099 +if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
2100 +
2101 +if (re == NULL || subject == NULL ||
2102 +   (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
2103 +if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
2104 +
2105 +anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
2106 +startline = (re->options & PCRE_STARTLINE) != 0;
2107 +
2108 +match_block.start_pattern = re->code;
2109 +match_block.start_subject = (const uschar *)subject;
2110 +match_block.end_subject = match_block.start_subject + length;
2111 +end_subject = match_block.end_subject;
2112 +
2113 +match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
2114 +match_block.utf8 = (re->options & PCRE_UTF8) != 0;
2115 +
2116 +match_block.notbol = (options & PCRE_NOTBOL) != 0;
2117 +match_block.noteol = (options & PCRE_NOTEOL) != 0;
2118 +match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
2119 +
2120 +match_block.errorcode = PCRE_ERROR_NOMATCH;     /* Default error */
2121 +
2122 +match_block.lcc = re->tables + lcc_offset;
2123 +match_block.ctypes = re->tables + ctypes_offset;
2124 +
2125 +/* The ims options can vary during the matching as a result of the presence
2126 +of (?ims) items in the pattern. They are kept in a local variable so that
2127 +restoring at the exit of a group is easy. */
2128 +
2129 +ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
2130 +
2131 +/* If the expression has got more back references than the offsets supplied can
2132 +hold, we get a temporary bit of working store to use during the matching.
2133 +Otherwise, we can use the vector supplied, rounding down its size to a multiple
2134 +of 3. */
2135 +
2136 +ocount = offsetcount - (offsetcount % 3);
2137 +
2138 +if (re->top_backref > 0 && re->top_backref >= ocount/3)
2139 +  {
2140 +  ocount = re->top_backref * 3 + 3;
2141 +  match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int));
2142 +  if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
2143 +  using_temporary_offsets = TRUE;
2144 +  DPRINTF(("Got memory to hold back references\n"));
2145 +  }
2146 +else match_block.offset_vector = offsets;
2147 +
2148 +match_block.offset_end = ocount;
2149 +match_block.offset_max = (2*ocount)/3;
2150 +match_block.offset_overflow = FALSE;
2151 +
2152 +/* Compute the minimum number of offsets that we need to reset each time. Doing
2153 +this makes a huge difference to execution time when there aren't many brackets
2154 +in the pattern. */
2155 +
2156 +resetcount = 2 + re->top_bracket * 2;
2157 +if (resetcount > offsetcount) resetcount = ocount;
2158 +
2159 +/* Reset the working variable associated with each extraction. These should
2160 +never be used unless previously set, but they get saved and restored, and so we
2161 +initialize them to avoid reading uninitialized locations. */
2162 +
2163 +if (match_block.offset_vector != NULL)
2164 +  {
2165 +  register int *iptr = match_block.offset_vector + ocount;
2166 +  register int *iend = iptr - resetcount/2 + 1;
2167 +  while (--iptr >= iend) *iptr = -1;
2168 +  }
2169 +
2170 +/* Set up the first character to match, if available. The first_char value is
2171 +never set for an anchored regular expression, but the anchoring may be forced
2172 +at run time, so we have to test for anchoring. The first char may be unset for
2173 +an unanchored pattern, of course. If there's no first char and the pattern was
2174 +studied, there may be a bitmap of possible first characters. */
2175 +
2176 +if (!anchored)
2177 +  {
2178 +  if ((re->options & PCRE_FIRSTSET) != 0)
2179 +    {
2180 +    first_char = re->first_char;
2181 +    if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
2182 +    }
2183 +  else
2184 +    if (!startline && extra != NULL &&
2185 +      (extra->options & PCRE_STUDY_MAPPED) != 0)
2186 +        start_bits = extra->start_bits;
2187 +  }
2188 +
2189 +/* For anchored or unanchored matches, there may be a "last known required
2190 +character" set. If the PCRE_CASELESS is set, implying that the match starts
2191 +caselessly, or if there are any changes of this flag within the regex, set up
2192 +both cases of the character. Otherwise set the two values the same, which will
2193 +avoid duplicate testing (which takes significant time). This covers the vast
2194 +majority of cases. It will be suboptimal when the case flag changes in a regex
2195 +and the required character in fact is caseful. */
2196 +
2197 +if ((re->options & PCRE_REQCHSET) != 0)
2198 +  {
2199 +  req_char = re->req_char;
2200 +  req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0)?
2201 +    (re->tables + fcc_offset)[req_char] : req_char;
2202 +  }
2203 +
2204 +/* Loop for handling unanchored repeated matching attempts; for anchored regexs
2205 +the loop runs just once. */
2206 +
2207 +do
2208 +  {
2209 +  int rc;
2210 +  register int *iptr = match_block.offset_vector;
2211 +  register int *iend = iptr + resetcount;
2212 +
2213 +  /* Reset the maximum number of extractions we might see. */
2214 +
2215 +  while (iptr < iend) *iptr++ = -1;
2216 +
2217 +  /* Advance to a unique first char if possible */
2218 +
2219 +  if (first_char >= 0)
2220 +    {
2221 +    if ((ims & PCRE_CASELESS) != 0)
2222 +      while (start_match < end_subject &&
2223 +             match_block.lcc[*start_match] != first_char)
2224 +        start_match++;
2225 +    else
2226 +      while (start_match < end_subject && *start_match != first_char)
2227 +        start_match++;
2228 +    }
2229 +
2230 +  /* Or to just after \n for a multiline match if possible */
2231 +
2232 +  else if (startline)
2233 +    {
2234 +    if (start_match > match_block.start_subject + start_offset)
2235 +      {
2236 +      while (start_match < end_subject && start_match[-1] != NEWLINE)
2237 +        start_match++;
2238 +      }
2239 +    }
2240 +
2241 +  /* Or to a non-unique first char after study */
2242 +
2243 +  else if (start_bits != NULL)
2244 +    {
2245 +    while (start_match < end_subject)
2246 +      {
2247 +      register int c = *start_match;
2248 +      if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
2249 +      }
2250 +    }
2251 +
2252 +#ifdef DEBUG  /* Sigh. Some compilers never learn. */
2253 +  PCRE_PRINTF(">>>> Match against: ");
2254 +  pchars(start_match, end_subject - start_match, TRUE, &match_block);
2255 +  PCRE_PRINTF("\n");
2256 +#endif
2257 +
2258 +  /* If req_char is set, we know that that character must appear in the subject
2259 +  for the match to succeed. If the first character is set, req_char must be
2260 +  later in the subject; otherwise the test starts at the match point. This
2261 +  optimization can save a huge amount of backtracking in patterns with nested
2262 +  unlimited repeats that aren't going to match. We don't know what the state of
2263 +  case matching may be when this character is hit, so test for it in both its
2264 +  cases if necessary. However, the different cased versions will not be set up
2265 +  unless PCRE_CASELESS was given or the casing state changes within the regex.
2266 +  Writing separate code makes it go faster, as does using an autoincrement and
2267 +  backing off on a match. */
2268 +
2269 +  if (req_char >= 0)
2270 +    {
2271 +    register const uschar *p = start_match + ((first_char >= 0)? 1 : 0);
2272 +
2273 +    /* We don't need to repeat the search if we haven't yet reached the
2274 +    place we found it at last time. */
2275 +
2276 +    if (p > req_char_ptr)
2277 +      {
2278 +      /* Do a single test if no case difference is set up */
2279 +
2280 +      if (req_char == req_char2)
2281 +        {
2282 +        while (p < end_subject)
2283 +          {
2284 +          if (*p++ == req_char) { p--; break; }
2285 +          }
2286 +        }
2287 +
2288 +      /* Otherwise test for either case */
2289 +
2290 +      else
2291 +        {
2292 +        while (p < end_subject)
2293 +          {
2294 +          register int pp = *p++;
2295 +          if (pp == req_char || pp == req_char2) { p--; break; }
2296 +          }
2297 +        }
2298 +
2299 +      /* If we can't find the required character, break the matching loop */
2300 +
2301 +      if (p >= end_subject) break;
2302 +
2303 +      /* If we have found the required character, save the point where we
2304 +      found it, so that we don't search again next time round the loop if
2305 +      the start hasn't passed this character yet. */
2306 +
2307 +      req_char_ptr = p;
2308 +      }
2309 +    }
2310 +
2311 +  /* When a match occurs, substrings will be set for all internal extractions;
2312 +  we just need to set up the whole thing as substring 0 before returning. If
2313 +  there were too many extractions, set the return code to zero. In the case
2314 +  where we had to get some local store to hold offsets for backreferences, copy
2315 +  those back references that we can. In this case there need not be overflow
2316 +  if certain parts of the pattern were not used. */
2317 +
2318 +  match_block.start_match = start_match;
2319 +  if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
2320 +    continue;
2321 +
2322 +  /* Copy the offset information from temporary store if necessary */
2323 +
2324 +  if (using_temporary_offsets)
2325 +    {
2326 +    if (offsetcount >= 4)
2327 +      {
2328 +      memcpy(offsets + 2, match_block.offset_vector + 2,
2329 +        (offsetcount - 2) * sizeof(int));
2330 +      DPRINTF(("Copied offsets from temporary memory\n"));
2331 +      }
2332 +    if (match_block.end_offset_top > offsetcount)
2333 +      match_block.offset_overflow = TRUE;
2334 +
2335 +    DPRINTF(("Freeing temporary memory\n"));
2336 +    (pcre_free)(match_block.offset_vector);
2337 +    }
2338 +
2339 +  rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
2340 +
2341 +  if (offsetcount < 2) rc = 0; else
2342 +    {
2343 +    offsets[0] = start_match - match_block.start_subject;
2344 +    offsets[1] = match_block.end_match_ptr - match_block.start_subject;
2345 +    }
2346 +
2347 +  DPRINTF((">>>> returning %d\n", rc));
2348 +  return rc;
2349 +  }
2350 +
2351 +/* This "while" is the end of the "do" above */
2352 +
2353 +while (!anchored &&
2354 +       match_block.errorcode == PCRE_ERROR_NOMATCH &&
2355 +       start_match++ < end_subject);
2356 +
2357 +if (using_temporary_offsets)
2358 +  {
2359 +  DPRINTF(("Freeing temporary memory\n"));
2360 +  (pcre_free)(match_block.offset_vector);
2361 +  }
2362 +
2363 +DPRINTF((">>>> returning %d\n", match_block.errorcode));
2364 +
2365 +return match_block.errorcode;
2366 +}
2367 +
2368 +/* End of pcre.c */
2369 --- linux-2.6.16.29.orig/security/apparmor/aamatch/pcre_exec.h  1969-12-31 16:00:00.000000000 -0800
2370 +++ linux-2.6.16.29/security/apparmor/aamatch/pcre_exec.h       2006-10-12 21:11:15.000000000 -0700
2371 @@ -0,0 +1,308 @@
2372 +/*
2373 + *  This is a modified header file containing the definitions from
2374 + *  pcre.h and internal.h required to support pcre_exec()
2375 + */
2376 +
2377 +
2378 +/*************************************************
2379 +*       Perl-Compatible Regular Expressions      *
2380 +*************************************************/
2381 +
2382 +/* Copyright (c) 1997-2001 University of Cambridge */
2383 +
2384 +#ifndef _PCRE_H
2385 +#define _PCRE_H
2386 +
2387 +/* ----- CODE ADDED ---- */
2388 +
2389 +#ifdef __KERNEL__
2390 +#include <linux/slab.h>        // for kmalloc/kfree
2391 +#endif
2392 +
2393 +#ifdef __KERNEL__
2394 +#define PCRE_PRINTF printk
2395 +#define isprint(x) ((unsigned char)(x) >= 128 && (unsigned char)(x) <= 255)
2396 +#else
2397 +#define PCRE_PRINTF printf
2398 +#endif
2399 +
2400 +/* The value of NEWLINE determines the newline character. The default is to
2401 + * leave it up to the compiler, but some sites want to force a particular value.
2402 + * On Unix systems, "configure" can be used to override this default. */
2403 +
2404 +#ifndef NEWLINE
2405 +#define NEWLINE '\n'
2406 +#endif
2407 +
2408 +/* ----  CODE DELETED ---- */
2409 +
2410 +/* Options */
2411 +
2412 +#define PCRE_CASELESS        0x0001
2413 +#define PCRE_MULTILINE       0x0002
2414 +#define PCRE_DOTALL          0x0004
2415 +#define PCRE_EXTENDED        0x0008
2416 +#define PCRE_ANCHORED        0x0010
2417 +#define PCRE_DOLLAR_ENDONLY  0x0020
2418 +#define PCRE_EXTRA           0x0040
2419 +#define PCRE_NOTBOL          0x0080
2420 +#define PCRE_NOTEOL          0x0100
2421 +#define PCRE_UNGREEDY        0x0200
2422 +#define PCRE_NOTEMPTY        0x0400
2423 +#define PCRE_UTF8            0x0800
2424 +
2425 +/* Exec-time and get-time error codes */
2426 +
2427 +#define PCRE_ERROR_NOMATCH        (-1)
2428 +#define PCRE_ERROR_NULL           (-2)
2429 +#define PCRE_ERROR_BADOPTION      (-3)
2430 +#define PCRE_ERROR_BADMAGIC       (-4)
2431 +#define PCRE_ERROR_UNKNOWN_NODE   (-5)
2432 +#define PCRE_ERROR_NOMEMORY       (-6)
2433 +#define PCRE_ERROR_NOSUBSTRING    (-7)
2434 +
2435 +/* ----  CODE DELETED ---- */
2436 +
2437 +/* Types */
2438 +
2439 +struct real_pcre;        /* declaration; the definition is private  */
2440 +struct real_pcre_extra;  /* declaration; the definition is private */
2441 +
2442 +typedef struct real_pcre pcre;
2443 +typedef struct real_pcre_extra pcre_extra;
2444 +
2445 +/* ----  CODE DELETED ---- */
2446 +
2447 +extern int pcre_exec(const pcre *, const pcre_extra *,
2448 +                    const char *, int, int, int, int *,
2449 +                    int);
2450 +
2451 +/* ----  CODE ADDED (from internal.h) ---- */
2452 +
2453 +/* These are the public options that can change during matching. */
2454 +
2455 +#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
2456 +
2457 +/* Private options flags start at the most significant end of the four bytes,
2458 +but skip the top bit so we can use ints for convenience without getting tangled
2459 +with negative values. The public options defined in pcre.h start at the least
2460 +significant end. Make sure they don't overlap, though now that we have expanded
2461 +to four bytes there is plenty of space. */
2462 +
2463 +#define PCRE_FIRSTSET      0x40000000  /* first_char is set */
2464 +#define PCRE_REQCHSET      0x20000000  /* req_char is set */
2465 +#define PCRE_STARTLINE     0x10000000  /* start after \n for multiline */
2466 +#define PCRE_ICHANGED      0x04000000  /* i option changes within regex */
2467 +
2468 +/* Options for the "extra" block produced by pcre_study(). */
2469 +
2470 +#define PCRE_STUDY_MAPPED   0x01     /* a map of starting chars exists */
2471 +
2472 +/* Masks for identifying the public options which are permitted at compile
2473 +time, run time or study time, respectively. */
2474 +
2475 +#define PUBLIC_EXEC_OPTIONS \
2476 +    (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
2477 +
2478 +/* Magic number to provide a small check against being handed junk. */
2479 +
2480 +#define MAGIC_NUMBER  0x50435245UL   /* 'PCRE' */
2481 +
2482 +typedef int BOOL;
2483 +
2484 +#define FALSE   0
2485 +#define TRUE    1
2486 +
2487 +/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
2488 +that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
2489 +OP_EOD must correspond in order to the list of escapes immediately above. */
2490 +
2491 +enum {
2492 +  OP_END,            /* End of pattern */
2493 +
2494 +  /* Values corresponding to backslashed metacharacters */
2495 +
2496 +  OP_SOD,            /* Start of data: \A */
2497 +  OP_NOT_WORD_BOUNDARY,  /* \B */
2498 +  OP_WORD_BOUNDARY,      /* \b */
2499 +  OP_NOT_DIGIT,          /* \D */
2500 +  OP_DIGIT,              /* \d */
2501 +  OP_NOT_WHITESPACE,     /* \S */
2502 +  OP_WHITESPACE,         /* \s */
2503 +  OP_NOT_WORDCHAR,       /* \W */
2504 +  OP_WORDCHAR,           /* \w */
2505 +  OP_EODN,           /* End of data or \n at end of data: \Z. */
2506 +  OP_EOD,            /* End of data: \z */
2507 +
2508 +  OP_OPT,            /* Set runtime options */
2509 +  OP_CIRC,           /* Start of line - varies with multiline switch */
2510 +  OP_DOLL,           /* End of line - varies with multiline switch */
2511 +  OP_ANY,            /* Match any character */
2512 +  OP_CHARS,          /* Match string of characters */
2513 +  OP_NOT,            /* Match anything but the following char */
2514 +
2515 +  OP_STAR,           /* The maximizing and minimizing versions of */
2516 +  OP_MINSTAR,        /* all these opcodes must come in pairs, with */
2517 +  OP_PLUS,           /* the minimizing one second. */
2518 +  OP_MINPLUS,        /* This first set applies to single characters */
2519 +  OP_QUERY,
2520 +  OP_MINQUERY,
2521 +  OP_UPTO,           /* From 0 to n matches */
2522 +  OP_MINUPTO,
2523 +  OP_EXACT,          /* Exactly n matches */
2524 +
2525 +  OP_NOTSTAR,        /* The maximizing and minimizing versions of */
2526 +  OP_NOTMINSTAR,     /* all these opcodes must come in pairs, with */
2527 +  OP_NOTPLUS,        /* the minimizing one second. */
2528 +  OP_NOTMINPLUS,     /* This first set applies to "not" single characters */
2529 +  OP_NOTQUERY,
2530 +  OP_NOTMINQUERY,
2531 +  OP_NOTUPTO,        /* From 0 to n matches */
2532 +  OP_NOTMINUPTO,
2533 +  OP_NOTEXACT,       /* Exactly n matches */
2534 +
2535 +  OP_TYPESTAR,       /* The maximizing and minimizing versions of */
2536 +  OP_TYPEMINSTAR,    /* all these opcodes must come in pairs, with */
2537 +  OP_TYPEPLUS,       /* the minimizing one second. These codes must */
2538 +  OP_TYPEMINPLUS,    /* be in exactly the same order as those above. */
2539 +  OP_TYPEQUERY,      /* This set applies to character types such as \d */
2540 +  OP_TYPEMINQUERY,
2541 +  OP_TYPEUPTO,       /* From 0 to n matches */
2542 +  OP_TYPEMINUPTO,
2543 +  OP_TYPEEXACT,      /* Exactly n matches */
2544 +
2545 +  OP_CRSTAR,         /* The maximizing and minimizing versions of */
2546 +  OP_CRMINSTAR,      /* all these opcodes must come in pairs, with */
2547 +  OP_CRPLUS,         /* the minimizing one second. These codes must */
2548 +  OP_CRMINPLUS,      /* be in exactly the same order as those above. */
2549 +  OP_CRQUERY,        /* These are for character classes and back refs */
2550 +  OP_CRMINQUERY,
2551 +  OP_CRRANGE,        /* These are different to the three seta above. */
2552 +  OP_CRMINRANGE,
2553 +
2554 +  OP_CLASS,          /* Match a character class */
2555 +  OP_REF,            /* Match a back reference */
2556 +  OP_RECURSE,        /* Match this pattern recursively */
2557 +
2558 +  OP_ALT,            /* Start of alternation */
2559 +  OP_KET,            /* End of group that doesn't have an unbounded repeat */
2560 +  OP_KETRMAX,        /* These two must remain together and in this */
2561 +  OP_KETRMIN,        /* order. They are for groups the repeat for ever. */
2562 +
2563 +  /* The assertions must come before ONCE and COND */
2564 +
2565 +  OP_ASSERT,         /* Positive lookahead */
2566 +  OP_ASSERT_NOT,     /* Negative lookahead */
2567 +  OP_ASSERTBACK,     /* Positive lookbehind */
2568 +  OP_ASSERTBACK_NOT, /* Negative lookbehind */
2569 +  OP_REVERSE,        /* Move pointer back - used in lookbehind assertions */
2570 +
2571 +  /* ONCE and COND must come after the assertions, with ONCE first, as there's
2572 +  a test for >= ONCE for a subpattern that isn't an assertion. */
2573 +
2574 +  OP_ONCE,           /* Once matched, don't back up into the subpattern */
2575 +  OP_COND,           /* Conditional group */
2576 +  OP_CREF,           /* Used to hold an extraction string number (cond ref) */
2577 +
2578 +  OP_BRAZERO,        /* These two must remain together and in this */
2579 +  OP_BRAMINZERO,     /* order. */
2580 +
2581 +  OP_BRANUMBER,      /* Used for extracting brackets whose number is greater
2582 +                        than can fit into an opcode. */
2583 +
2584 +  OP_BRA             /* This and greater values are used for brackets that
2585 +                        extract substrings up to a basic limit. After that,
2586 +                        use is made of OP_BRANUMBER. */
2587 +};
2588 +
2589 +/* The highest extraction number before we have to start using additional
2590 +bytes. (Originally PCRE didn't have support for extraction counts highter than
2591 +this number.) The value is limited by the number of opcodes left after OP_BRA,
2592 +i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional
2593 +opcodes. */
2594 +
2595 +#define EXTRACT_BASIC_MAX  150
2596 +
2597 +/* All character handling must be done as unsigned characters. Otherwise there
2598 +are problems with top-bit-set characters and functions such as isspace().
2599 +However, we leave the interface to the outside world as char *, because that
2600 +should make things easier for callers. We define a short type for unsigned char
2601 +to save lots of typing. I tried "uchar", but it causes problems on Digital
2602 +Unix, where it is defined in sys/types, so use "uschar" instead. */
2603 +
2604 +typedef unsigned char uschar;
2605 +
2606 +/* The real format of the start of the pcre block; the actual code vector
2607 +runs on as long as necessary after the end. */
2608 +
2609 +typedef struct real_pcre {
2610 +  unsigned long int magic_number;
2611 +  size_t size;
2612 +  const unsigned char *tables;
2613 +  unsigned long int options;
2614 +  unsigned short int top_bracket;
2615 +  unsigned short int top_backref;
2616 +  uschar first_char;
2617 +  uschar req_char;
2618 +  uschar code[1];
2619 +} real_pcre;
2620 +
2621 +/* The real format of the extra block returned by pcre_study(). */
2622 +
2623 +typedef struct real_pcre_extra {
2624 +  uschar options;
2625 +  uschar start_bits[32];
2626 +} real_pcre_extra;
2627 +
2628 +/* Structure for passing "static" information around between the functions
2629 +doing the matching, so that they are thread-safe. */
2630 +
2631 +typedef struct match_data {
2632 +  int    errorcode;             /* As it says */
2633 +  int   *offset_vector;         /* Offset vector */
2634 +  int    offset_end;            /* One past the end */
2635 +  int    offset_max;            /* The maximum usable for return data */
2636 +  const uschar *lcc;            /* Points to lower casing table */
2637 +  const uschar *ctypes;         /* Points to table of type maps */
2638 +  BOOL   offset_overflow;       /* Set if too many extractions */
2639 +  BOOL   notbol;                /* NOTBOL flag */
2640 +  BOOL   noteol;                /* NOTEOL flag */
2641 +  BOOL   utf8;                  /* UTF8 flag */
2642 +  BOOL   endonly;               /* Dollar not before final \n */
2643 +  BOOL   notempty;              /* Empty string match not wanted */
2644 +  const uschar *start_pattern;  /* For use when recursing */
2645 +  const uschar *start_subject;  /* Start of the subject string */
2646 +  const uschar *end_subject;    /* End of the subject string */
2647 +  const uschar *start_match;    /* Start of this match attempt */
2648 +  const uschar *end_match_ptr;  /* Subject position at end match */
2649 +  int    end_offset_top;        /* Highwater mark at end of match */
2650 +} match_data;
2651 +
2652 +/* Bit definitions for entries in the pcre_ctypes table. */
2653 +
2654 +#define ctype_space   0x01
2655 +#define ctype_letter  0x02
2656 +#define ctype_digit   0x04
2657 +#define ctype_xdigit  0x08
2658 +#define ctype_word    0x10   /* alphameric or '_' */
2659 +#define ctype_meta    0x80   /* regexp meta char or zero (end pattern) */
2660 +
2661 +/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
2662 +of bits for a class map. Some classes are built by combining these tables. */
2663 +
2664 +#define cbit_length  320      /* Length of the cbits table */
2665 +
2666 +/* Offsets of the various tables from the base tables pointer, and
2667 +total length. */
2668 +
2669 +#define lcc_offset      0
2670 +#define fcc_offset    256
2671 +
2672 +#define fcc_offset    256
2673 +#define cbits_offset  512
2674 +#define ctypes_offset (cbits_offset + cbit_length)
2675 +
2676 +/* ----- CODE ADDED ---- */
2677 +
2678 +#endif // _PCRE_H
2679 + /* End of pcre.h */
2680 --- linux-2.6.16.29.orig/security/apparmor/aamatch/pcre_tables.h        1969-12-31 16:00:00.000000000 -0800
2681 +++ linux-2.6.16.29/security/apparmor/aamatch/pcre_tables.h     2006-10-12 21:11:15.000000000 -0700
2682 @@ -0,0 +1,184 @@
2683 +
2684 +/*************************************************
2685 +*      Perl-Compatible Regular Expressions       *
2686 +*************************************************/
2687 +
2688 +/* This file is automatically written by the dftables auxiliary
2689 +program. If you edit it by hand, you might like to edit the Makefile to
2690 +prevent its ever being regenerated.
2691 +
2692 +This file is #included in the compilation of pcre.c to build the default
2693 +character tables which are used when no tables are passed to the compile
2694 +function. */
2695 +
2696 +static unsigned char pcre_default_tables[] = {
2697 +
2698 +/* This table is a lower casing table. */
2699 +
2700 +    0,  1,  2,  3,  4,  5,  6,  7,
2701 +    8,  9, 10, 11, 12, 13, 14, 15,
2702 +   16, 17, 18, 19, 20, 21, 22, 23,
2703 +   24, 25, 26, 27, 28, 29, 30, 31,
2704 +   32, 33, 34, 35, 36, 37, 38, 39,
2705 +   40, 41, 42, 43, 44, 45, 46, 47,
2706 +   48, 49, 50, 51, 52, 53, 54, 55,
2707 +   56, 57, 58, 59, 60, 61, 62, 63,
2708 +   64, 97, 98, 99,100,101,102,103,
2709 +  104,105,106,107,108,109,110,111,
2710 +  112,113,114,115,116,117,118,119,
2711 +  120,121,122, 91, 92, 93, 94, 95,
2712 +   96, 97, 98, 99,100,101,102,103,
2713 +  104,105,106,107,108,109,110,111,
2714 +  112,113,114,115,116,117,118,119,
2715 +  120,121,122,123,124,125,126,127,
2716 +  128,129,130,131,132,133,134,135,
2717 +  136,137,138,139,140,141,142,143,
2718 +  144,145,146,147,148,149,150,151,
2719 +  152,153,154,155,156,157,158,159,
2720 +  160,161,162,163,164,165,166,167,
2721 +  168,169,170,171,172,173,174,175,
2722 +  176,177,178,179,180,181,182,183,
2723 +  184,185,186,187,188,189,190,191,
2724 +  192,193,194,195,196,197,198,199,
2725 +  200,201,202,203,204,205,206,207,
2726 +  208,209,210,211,212,213,214,215,
2727 +  216,217,218,219,220,221,222,223,
2728 +  224,225,226,227,228,229,230,231,
2729 +  232,233,234,235,236,237,238,239,
2730 +  240,241,242,243,244,245,246,247,
2731 +  248,249,250,251,252,253,254,255,
2732 +
2733 +/* This table is a case flipping table. */
2734 +
2735 +    0,  1,  2,  3,  4,  5,  6,  7,
2736 +    8,  9, 10, 11, 12, 13, 14, 15,
2737 +   16, 17, 18, 19, 20, 21, 22, 23,
2738 +   24, 25, 26, 27, 28, 29, 30, 31,
2739 +   32, 33, 34, 35, 36, 37, 38, 39,
2740 +   40, 41, 42, 43, 44, 45, 46, 47,
2741 +   48, 49, 50, 51, 52, 53, 54, 55,
2742 +   56, 57, 58, 59, 60, 61, 62, 63,
2743 +   64, 97, 98, 99,100,101,102,103,
2744 +  104,105,106,107,108,109,110,111,
2745 +  112,113,114,115,116,117,118,119,
2746 +  120,121,122, 91, 92, 93, 94, 95,
2747 +   96, 65, 66, 67, 68, 69, 70, 71,
2748 +   72, 73, 74, 75, 76, 77, 78, 79,
2749 +   80, 81, 82, 83, 84, 85, 86, 87,
2750 +   88, 89, 90,123,124,125,126,127,
2751 +  128,129,130,131,132,133,134,135,
2752 +  136,137,138,139,140,141,142,143,
2753 +  144,145,146,147,148,149,150,151,
2754 +  152,153,154,155,156,157,158,159,
2755 +  160,161,162,163,164,165,166,167,
2756 +  168,169,170,171,172,173,174,175,
2757 +  176,177,178,179,180,181,182,183,
2758 +  184,185,186,187,188,189,190,191,
2759 +  192,193,194,195,196,197,198,199,
2760 +  200,201,202,203,204,205,206,207,
2761 +  208,209,210,211,212,213,214,215,
2762 +  216,217,218,219,220,221,222,223,
2763 +  224,225,226,227,228,229,230,231,
2764 +  232,233,234,235,236,237,238,239,
2765 +  240,241,242,243,244,245,246,247,
2766 +  248,249,250,251,252,253,254,255,
2767 +
2768 +/* This table contains bit maps for various character classes.
2769 +Each map is 32 bytes long and the bits run from the least
2770 +significant end of each byte. The classes that have their own
2771 +maps are: space, xdigit, digit, upper, lower, word, graph
2772 +print, punct, and cntrl. Other classes are built from combinations. */
2773 +
2774 +  0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
2775 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2776 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2777 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2778 +
2779 +  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
2780 +  0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
2781 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2782 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2783 +
2784 +  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
2785 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2786 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2787 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2788 +
2789 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2790 +  0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
2791 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2792 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2793 +
2794 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2795 +  0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
2796 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2797 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2798 +
2799 +  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
2800 +  0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
2801 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2802 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2803 +
2804 +  0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
2805 +  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
2806 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2807 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2808 +
2809 +  0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
2810 +  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
2811 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2812 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2813 +
2814 +  0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
2815 +  0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
2816 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2817 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2818 +
2819 +  0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
2820 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
2821 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2822 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
2823 +
2824 +/* This table identifies various classes of character by individual bits:
2825 +  0x01   white space character
2826 +  0x02   letter
2827 +  0x04   decimal digit
2828 +  0x08   hexadecimal digit
2829 +  0x10   alphanumeric or '_'
2830 +  0x80   regular expression metacharacter or binary zero
2831 +*/
2832 +
2833 +  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   0-  7 */
2834 +  0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /*   8- 15 */
2835 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  16- 23 */
2836 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  24- 31 */
2837 +  0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /*    - '  */
2838 +  0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /*  ( - /  */
2839 +  0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /*  0 - 7  */
2840 +  0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /*  8 - ?  */
2841 +  0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /*  @ - G  */
2842 +  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  H - O  */
2843 +  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  P - W  */
2844 +  0x12,0x12,0x12,0x80,0x00,0x00,0x80,0x10, /*  X - _  */
2845 +  0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /*  ` - g  */
2846 +  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  h - o  */
2847 +  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  p - w  */
2848 +  0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /*  x -127 */
2849 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
2850 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
2851 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
2852 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
2853 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
2854 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
2855 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
2856 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
2857 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
2858 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
2859 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
2860 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
2861 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
2862 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
2863 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
2864 +  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
2865 +
2866 +/* End of chartables.c */
2867 --- linux-2.6.16.29.orig/security/apparmor/apparmorfs.c 1969-12-31 16:00:00.000000000 -0800
2868 +++ linux-2.6.16.29/security/apparmor/apparmorfs.c      2006-10-12 21:11:15.000000000 -0700
2869 @@ -0,0 +1,440 @@
2870 +/*
2871 + *     Copyright (C) 2005 Novell/SUSE
2872 + *
2873 + *     This program is free software; you can redistribute it and/or
2874 + *     modify it under the terms of the GNU General Public License as
2875 + *     published by the Free Software Foundation, version 2 of the
2876 + *     License.
2877 + *
2878 + *     AppArmor filesystem (part of securityfs)
2879 + */
2880 +
2881 +#include <linux/security.h>
2882 +#include <linux/vmalloc.h>
2883 +#include <linux/module.h>
2884 +#include <linux/seq_file.h>
2885 +#include <asm/uaccess.h>
2886 +
2887 +#include "apparmor.h"
2888 +#include "inline.h"
2889 +#include "aamatch/match.h"
2890 +
2891 +#define SECFS_SD "apparmor"
2892 +static struct dentry *sdfs_dentry = NULL;
2893 +
2894 +/* profile */
2895 +extern struct seq_operations subdomainfs_profiles_op;
2896 +static int sd_prof_open(struct inode *inode, struct file *file);
2897 +static int sd_prof_release(struct inode *inode, struct file *file);
2898 +
2899 +static struct file_operations subdomainfs_profiles_fops = {
2900 +       .open =         sd_prof_open,
2901 +       .read =         seq_read,
2902 +       .llseek =       seq_lseek,
2903 +       .release =      sd_prof_release,
2904 +};
2905 +
2906 +/* version */
2907 +static ssize_t sd_version_read(struct file *file, char __user *buf,
2908 +                              size_t size, loff_t *ppos);
2909 +
2910 +static struct file_operations subdomainfs_version_fops = {
2911 +       .read =         sd_version_read,
2912 +};
2913 +
2914 +/* matching */
2915 +static ssize_t sd_matching_read(struct file *file, char __user *buf,
2916 +                              size_t size, loff_t *ppos);
2917 +
2918 +static struct file_operations subdomainfs_matching_fops = {
2919 +       .read =         sd_matching_read,
2920 +};
2921 +
2922 +
2923 +/* interface */
2924 +extern ssize_t sd_file_prof_add(void *, size_t);
2925 +extern ssize_t sd_file_prof_repl(void *, size_t);
2926 +extern ssize_t sd_file_prof_remove(const char *, int);
2927 +
2928 +static ssize_t sd_profile_load(struct file *f, const char __user *buf,
2929 +                              size_t size, loff_t *pos);
2930 +static ssize_t sd_profile_replace(struct file *f, const char __user *buf,
2931 +                                 size_t size, loff_t *pos);
2932 +static ssize_t sd_profile_remove(struct file *f, const char __user *buf,
2933 +                                size_t size, loff_t *pos);
2934 +
2935 +static struct file_operations subdomainfs_profile_load = {
2936 +       .write = sd_profile_load
2937 +};
2938 +
2939 +static struct file_operations subdomainfs_profile_replace = {
2940 +       .write = sd_profile_replace
2941 +};
2942 +
2943 +static struct file_operations subdomainfs_profile_remove = {
2944 +       .write = sd_profile_remove
2945 +};
2946 +
2947 +
2948 +/* control */
2949 +static u64 sd_control_get(void *data);
2950 +static void sd_control_set(void *data, u64 val);
2951 +
2952 +DEFINE_SIMPLE_ATTRIBUTE(subdomainfs_control_fops, sd_control_get,
2953 +                       sd_control_set, "%lld\n");
2954 +
2955 +
2956 +
2957 +/* table of static entries */
2958 +
2959 +static struct root_entry {
2960 +       const char *name;
2961 +       int mode;
2962 +       int access;
2963 +       struct file_operations *fops;
2964 +       void *data;
2965 +
2966 +       /* internal fields */
2967 +       struct dentry *dentry;
2968 +       int parent_index;
2969 +} root_entries[] = {
2970 +       /* our root, normally /sys/kernel/security/subdomain */
2971 +       {SECFS_SD,      S_IFDIR, 0550}, /* DO NOT EDIT/MOVE */
2972 +
2973 +       /* interface for obtaining list of profiles currently loaded */
2974 +       {"profiles",    S_IFREG, 0440, &subdomainfs_profiles_fops,
2975 +                                      NULL},
2976 +
2977 +       /* interface for obtaining version# of subdomain */
2978 +       {"version",     S_IFREG, 0440, &subdomainfs_version_fops,
2979 +                                      NULL},
2980 +
2981 +       /* interface for obtaining matching features supported */
2982 +       {"matching",    S_IFREG, 0440, &subdomainfs_matching_fops,
2983 +                                      NULL},
2984 +
2985 +       /* interface for loading/removing/replacing profiles */
2986 +       {".load",       S_IFREG, 0640, &subdomainfs_profile_load,
2987 +                                      NULL},
2988 +       {".replace",    S_IFREG, 0640, &subdomainfs_profile_replace,
2989 +                                      NULL},
2990 +       {".remove",     S_IFREG, 0640, &subdomainfs_profile_remove,
2991 +                                      NULL},
2992 +
2993 +       /* interface for setting binary config values */
2994 +       {"control",     S_IFDIR, 0550},
2995 +       {"complain",    S_IFREG, 0640, &subdomainfs_control_fops,
2996 +                                      &subdomain_complain},
2997 +       {"audit",       S_IFREG, 0640, &subdomainfs_control_fops,
2998 +                                      &subdomain_audit},
2999 +       {"debug",       S_IFREG, 0640, &subdomainfs_control_fops,
3000 +                                      &subdomain_debug},
3001 +       {"logsyscall",  S_IFREG, 0640, &subdomainfs_control_fops,
3002 +                                      &subdomain_logsyscall},
3003 +       {NULL,          S_IFDIR, 0},
3004 +
3005 +       /* root end */
3006 +       {NULL,          S_IFDIR, 0}
3007 +};
3008 +
3009 +#define SDFS_DENTRY root_entries[0].dentry
3010 +
3011 +static const unsigned int num_entries =
3012 +       sizeof(root_entries) / sizeof(struct root_entry);
3013 +
3014 +
3015 +
3016 +static int sd_prof_open(struct inode *inode, struct file *file)
3017 +{
3018 +       return seq_open(file, &subdomainfs_profiles_op);
3019 +}
3020 +
3021 +
3022 +static int sd_prof_release(struct inode *inode, struct file *file)
3023 +{
3024 +       return seq_release(inode, file);
3025 +}
3026 +
3027 +static ssize_t sd_version_read(struct file *file, char __user *buf,
3028 +                              size_t size, loff_t *ppos)
3029 +{
3030 +       const char *version = apparmor_version_nl();
3031 +
3032 +       return simple_read_from_buffer(buf, size, ppos, version,
3033 +                                      strlen(version));
3034 +}
3035 +
3036 +static ssize_t sd_matching_read(struct file *file, char __user *buf,
3037 +                              size_t size, loff_t *ppos)
3038 +{
3039 +       const char *matching = sdmatch_features();
3040 +
3041 +       return simple_read_from_buffer(buf, size, ppos, matching,
3042 +                                      strlen(matching));
3043 +}
3044 +
3045 +static char *sd_simple_write_to_buffer(const char __user *userbuf,
3046 +                                      size_t alloc_size, size_t copy_size,
3047 +                                      loff_t *pos, const char *msg)
3048 +{
3049 +       char *data;
3050 +
3051 +       if (*pos != 0) {
3052 +               /* only writes from pos 0, that is complete writes */
3053 +               data = ERR_PTR(-ESPIPE);
3054 +               goto out;
3055 +       }
3056 +
3057 +       /* Don't allow confined processes to load/replace/remove profiles.
3058 +        * No sane person would add rules allowing this to a profile
3059 +        * but we enforce the restriction anyways.
3060 +        */
3061 +       if (sd_is_confined()) {
3062 +               struct subdomain *sd = SD_SUBDOMAIN(current->security);
3063 +
3064 +               SD_WARN("REJECTING access to profile %s (%s(%d) "
3065 +                       "profile %s active %s)\n",
3066 +                       msg, current->comm, current->pid,
3067 +                       sd->profile->name, sd->active->name);
3068 +
3069 +               data = ERR_PTR(-EPERM);
3070 +               goto out;
3071 +       }
3072 +
3073 +       data = vmalloc(alloc_size);
3074 +       if (data == NULL) {
3075 +               data = ERR_PTR(-ENOMEM);
3076 +               goto out;
3077 +       }
3078 +
3079 +       if (copy_from_user(data, userbuf, copy_size)) {
3080 +               vfree(data);
3081 +               data = ERR_PTR(-EFAULT);
3082 +               goto out;
3083 +       }
3084 +
3085 +out:
3086 +       return data;
3087 +}
3088 +
3089 +static ssize_t sd_profile_load(struct file *f, const char __user *buf,
3090 +                              size_t size, loff_t *pos)
3091 +{
3092 +       char *data;
3093 +       ssize_t error;
3094 +
3095 +       data = sd_simple_write_to_buffer(buf, size, size, pos, "load");
3096 +
3097 +       if (!IS_ERR(data)) {
3098 +               error = sd_file_prof_add(data, size);
3099 +               vfree(data);
3100 +       } else {
3101 +               error = PTR_ERR(data);
3102 +       }
3103 +
3104 +       return error;
3105 +}
3106 +
3107 +static ssize_t sd_profile_replace(struct file *f, const char __user *buf,
3108 +                                 size_t size, loff_t *pos)
3109 +{
3110 +       char *data;
3111 +       ssize_t error;
3112 +
3113 +       data = sd_simple_write_to_buffer(buf, size, size, pos, "replacement");
3114 +
3115 +       if (!IS_ERR(data)) {
3116 +               error = sd_file_prof_repl(data, size);
3117 +               vfree(data);
3118 +       } else {
3119 +               error = PTR_ERR(data);
3120 +       }
3121 +
3122 +       return error;
3123 +}
3124 +
3125 +static ssize_t sd_profile_remove(struct file *f, const char __user *buf,
3126 +                                 size_t size, loff_t *pos)
3127 +{
3128 +       char *data;
3129 +       ssize_t error;
3130 +
3131 +       /* sd_file_prof_remove needs a null terminated string so 1 extra
3132 +        * byte is allocated and null the copied data is then null terminated
3133 +        */
3134 +       data = sd_simple_write_to_buffer(buf, size+1, size, pos, "removal");
3135 +
3136 +       if (!IS_ERR(data)) {
3137 +               data[size] = 0;
3138 +               error = sd_file_prof_remove(data, size);
3139 +               vfree(data);
3140 +       } else {
3141 +               error = PTR_ERR(data);
3142 +       }
3143 +
3144 +       return error;
3145 +}
3146 +
3147 +static u64 sd_control_get(void *data)
3148 +{
3149 +       return *(int *)data;
3150 +}
3151 +
3152 +static void sd_control_set(void *data, u64 val)
3153 +{
3154 +       if (val > 1)
3155 +               val = 1;
3156 +
3157 +       *(int*)data = (int)val;
3158 +}
3159 +
3160 +static void clear_subdomainfs(void)
3161 +{
3162 +       unsigned int i;
3163 +
3164 +       for (i=0; i < num_entries;i++) {
3165 +               unsigned int index;
3166 +
3167 +               if (root_entries[i].mode == S_IFDIR) {
3168 +                       if (root_entries[i].name)
3169 +                               /* defer dir free till all sub-entries freed */
3170 +                               continue;
3171 +                       else
3172 +                               /* cleanup parent */
3173 +                               index = root_entries[i].parent_index;
3174 +               } else {
3175 +                       index = i;
3176 +               }
3177 +
3178 +               if (root_entries[index].dentry) {
3179 +                       securityfs_remove(root_entries[index].dentry);
3180 +
3181 +                       SD_DEBUG("%s: deleted subdomainfs entry name=%s "
3182 +                                "dentry=%p\n",
3183 +                               __FUNCTION__,
3184 +                               root_entries[index].name,
3185 +                               root_entries[index].dentry);
3186 +
3187 +                       root_entries[index].dentry = NULL;
3188 +                       root_entries[index].parent_index = 0;
3189 +               }
3190 +       }
3191 +}
3192 +
3193 +static int populate_subdomainfs(struct dentry *root)
3194 +{
3195 +       unsigned int i, parent_index, depth;
3196 +
3197 +#define ENT root_entries[i]
3198 +
3199 +       for (i = 0; i < num_entries; i++) {
3200 +               root_entries[i].dentry = NULL;
3201 +               root_entries[i].parent_index = 0;
3202 +       }
3203 +
3204 +       /* 1. Verify entry 0 is valid [sanity check] */
3205 +       if (num_entries == 0 ||
3206 +           !root_entries[0].name ||
3207 +           strcmp(root_entries[0].name, SECFS_SD) != 0 ||
3208 +           root_entries[0].mode != S_IFDIR) {
3209 +               SD_ERROR("%s: root entry 0 is not SECFS_SD/dir\n",
3210 +                       __FUNCTION__);
3211 +               goto error;
3212 +       }
3213 +
3214 +       /* 2. Verify table structure */
3215 +       parent_index = 0;
3216 +       depth = 1;
3217 +
3218 +       for (i = 1; i < num_entries; i++) {
3219 +               ENT.parent_index = parent_index;
3220 +
3221 +               if (ENT.name && ENT.mode == S_IFDIR) {
3222 +                       depth++;
3223 +                       parent_index = i;
3224 +               } else if (!ENT.name) {
3225 +                       if (ENT.mode != S_IFDIR || depth == 0) {
3226 +                               SD_ERROR("%s: root_entry %d invalid (%u %d)",
3227 +                                        __FUNCTION__, i,
3228 +                                        ENT.mode, ENT.parent_index);
3229 +                               goto error;
3230 +                       }
3231 +
3232 +                       depth--;
3233 +                       parent_index = root_entries[parent_index].parent_index;
3234 +               }
3235 +       }
3236 +
3237 +       if (depth != 0) {
3238 +               SD_ERROR("%s: root_entry table not correctly terminated\n",
3239 +                       __FUNCTION__);
3240 +               goto error;
3241 +       }
3242 +
3243 +       /* 3. Create root (parent=NULL) */
3244 +       i=0;
3245 +
3246 +       ENT.dentry = securityfs_create_file(ENT.name,
3247 +                                       ENT.mode | ENT.access,
3248 +                                       NULL, NULL, NULL);
3249 +
3250 +       if (ENT.dentry)
3251 +               SD_DEBUG("%s: created securityfs/subdomain [dentry=%p]\n",
3252 +                       __FUNCTION__, ENT.dentry);
3253 +       else
3254 +               goto error;
3255 +
3256 +
3257 +       /* 4. create remaining nodes */
3258 +       for (i = 1; i < num_entries; i++) {
3259 +               struct dentry *parent;
3260 +
3261 +               /* end of directory ? */
3262 +               if (!ENT.name)
3263 +                       continue;
3264 +
3265 +               parent = root_entries[ENT.parent_index].dentry;
3266 +
3267 +               ENT.dentry = securityfs_create_file(ENT.name,
3268 +                                       ENT.mode | ENT.access,
3269 +                                       parent,
3270 +                                       ENT.mode != S_IFDIR ? ENT.data : NULL,
3271 +                                       ENT.mode != S_IFDIR ? ENT.fops : NULL);
3272 +
3273 +               if (!ENT.dentry)
3274 +                       goto cleanup_error;
3275 +
3276 +               SD_DEBUG("%s: added subdomainfs entry "
3277 +                        "name=%s mode=%x dentry=%p [parent %p]\n",
3278 +                       __FUNCTION__, ENT.name, ENT.mode|ENT.access,
3279 +                       ENT.dentry, parent);
3280 +       }
3281 +
3282 +       return 1;
3283 +
3284 +cleanup_error:
3285 +       clear_subdomainfs();
3286 +
3287 +error:
3288 +       return 0;
3289 +}
3290 +
3291 +int create_subdomainfs(void)
3292 +{
3293 +       if (SDFS_DENTRY)
3294 +               SD_ERROR("%s: Subdomain securityfs already exists\n",
3295 +                       __FUNCTION__);
3296 +       else if (!populate_subdomainfs(sdfs_dentry))
3297 +               SD_ERROR("%s: Error populating Subdomain securityfs\n",
3298 +                       __FUNCTION__);
3299 +
3300 +       return (SDFS_DENTRY != NULL);
3301 +}
3302 +
3303 +int destroy_subdomainfs(void)
3304 +{
3305 +       if (SDFS_DENTRY)
3306 +               clear_subdomainfs();
3307 +
3308 +       return 1;
3309 +}
3310 --- linux-2.6.16.29.orig/security/apparmor/apparmor.h   1969-12-31 16:00:00.000000000 -0800
3311 +++ linux-2.6.16.29/security/apparmor/apparmor.h        2006-10-12 21:11:15.000000000 -0700
3312 @@ -0,0 +1,302 @@
3313 +/*
3314 + *     Copyright (C) 1998-2005 Novell/SUSE
3315 + *
3316 + *     This program is free software; you can redistribute it and/or
3317 + *     modify it under the terms of the GNU General Public License as
3318 + *     published by the Free Software Foundation, version 2 of the
3319 + *     License.
3320 + *
3321 + *     AppArmor internal prototypes
3322 + */
3323 +
3324 +#ifndef __SUBDOMAIN_H
3325 +#define __SUBDOMAIN_H
3326 +
3327 +/* defn of iattr */
3328 +#include <linux/fs.h>
3329 +
3330 +/* defn of linux_binprm */
3331 +#include <linux/binfmts.h>
3332 +
3333 +#include "shared.h"
3334 +
3335 +/* Control parameters (0 or 1), settable thru module/boot flags or
3336 + * via /sys/kernel/security/subdomain/control */
3337 +extern int subdomain_complain;
3338 +extern int subdomain_debug;
3339 +extern int subdomain_audit;
3340 +extern int subdomain_logsyscall;
3341 +
3342 +#define SD_UNCONSTRAINED "unconstrained"
3343 +
3344 +/* $ echo -n subdomain.o | md5sum | cut -c -8 */
3345 +#define  SD_ID_MAGIC           0x8c235e38
3346 +
3347 +#define PROFILE_COMPLAIN(_profile) \
3348 +       (subdomain_complain == 1 || ((_profile) && (_profile)->flags.complain))
3349 +
3350 +#define SUBDOMAIN_COMPLAIN(_sd) \
3351 +       (subdomain_complain == 1 || \
3352 +        ((_sd) && (_sd)->active && (_sd)->active->flags.complain))
3353 +
3354 +#define SUBDOMAIN_AUDIT(_sd) \
3355 +       (subdomain_audit == 1 || \
3356 +        ((_sd) && (_sd)->active && (_sd)->active->flags.audit))
3357 +
3358 +/*
3359 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
3360 + * which is not related to profile accesses.
3361 + */
3362 +
3363 +#define SD_DEBUG(fmt, args...)                                         \
3364 +       do {                                                            \
3365 +               if (subdomain_debug)                                    \
3366 +                       printk(KERN_DEBUG "AppArmor: " fmt, ##args);    \
3367 +       } while (0)
3368 +#define SD_INFO(fmt, args...)  printk(KERN_INFO "AppArmor: " fmt, ##args)
3369 +#define SD_WARN(fmt, args...)  printk(KERN_WARNING "AppArmor: " fmt, ##args)
3370 +#define SD_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
3371 +
3372 +/* basic AppArmor data structures */
3373 +
3374 +struct flagval {
3375 +       int debug;
3376 +       int complain;
3377 +       int audit;
3378 +};
3379 +
3380 +enum entry_t {
3381 +       sd_entry_literal,
3382 +       sd_entry_tailglob,
3383 +       sd_entry_pattern,
3384 +       sd_entry_invalid
3385 +};
3386 +
3387 +/**
3388 + * sd_entry - file ACL *
3389 + * Each entry describes a file and an allowed access mode.
3390 + */
3391 +struct sd_entry {
3392 +       char *filename;
3393 +       int mode;               /* mode is 'or' of READ, WRITE, EXECUTE,
3394 +                                * INHERIT, UNCONSTRAINED, and LIBRARY
3395 +                                * (meaning don't prefetch). */
3396 +
3397 +       enum entry_t entry_type;
3398 +       void *extradata;
3399 +
3400 +       struct list_head list;
3401 +       struct list_head listp[POS_SD_FILE_MAX + 1];
3402 +};
3403 +
3404 +#define SD_SECURE_EXEC_NEEDED 0x00000001
3405 +
3406 +#define SD_EXEC_MODIFIER_MASK(mask) ((mask) & SD_EXEC_MODIFIERS)
3407 +
3408 +#define SD_EXEC_MASK(mask) ((mask) & (SD_MAY_EXEC | SD_EXEC_MODIFIERS))
3409 +
3410 +#define SD_EXEC_UNSAFE_MASK(mask) ((mask) & (SD_MAY_EXEC |\
3411 +                                            SD_EXEC_MODIFIERS |\
3412 +                                            SD_EXEC_UNSAFE))
3413 +
3414 +/**
3415 + * sdprofile - basic confinement data
3416 + *
3417 + * The AppArmor profile contains the basic confinement data.  Each profile
3418 + * has a name and potentially a list of subdomain entries. The profiles are
3419 + * connected in a list
3420 + */
3421 +struct sdprofile {
3422 +       char *name;                     /* profile name */
3423 +
3424 +       struct list_head file_entry;    /* file ACL */
3425 +       struct list_head file_entryp[POS_SD_FILE_MAX + 1];
3426 +       struct list_head list;          /* list of profiles */
3427 +       struct list_head sub;           /* sub profiles, for change_hat */
3428 +       struct flagval flags;           /* per profile debug flags */
3429 +
3430 +       int isstale;                    /* is profile stale */
3431 +
3432 +       int num_file_entries;
3433 +       int num_file_pentries[POS_SD_FILE_MAX + 1];
3434 +
3435 +       kernel_cap_t capabilities;
3436 +
3437 +       atomic_t count;                 /* reference count */
3438 +};
3439 +
3440 +enum sdfile_type {
3441 +       sd_file_default,
3442 +       sd_file_shmem
3443 +};
3444 +
3445 +/**
3446 + * sdfile - file pointer confinement data
3447 + *
3448 + * Data structure assigned to each open file (by subdomain_file_alloc_security)
3449 + */
3450 +struct sdfile {
3451 +       enum sdfile_type type;
3452 +       struct sdprofile *profile;
3453 +};
3454 +
3455 +/**
3456 + * subdomain - a task's subdomain
3457 + *
3458 + * Contains the original profile obtained from execve() as well as the
3459 + * current active profile (which could change due to change_hat).  Plus
3460 + * the hat_magic needed during change_hat.
3461 + */
3462 +struct subdomain {
3463 +       __u32 sd_magic;                 /* magic value to distinguish blobs */
3464 +       struct sdprofile *profile;      /* The profile obtained from execve() */
3465 +       struct sdprofile *active;       /* The current active profile */
3466 +       __u32 sd_hat_magic;             /* used with change_hat */
3467 +       struct list_head list;          /* list of subdomains */
3468 +       struct task_struct *task;
3469 +};
3470 +
3471 +typedef int (*sd_iter) (struct subdomain *, void *);
3472 +
3473 +/* sd_path_data
3474 + * temp (cookie) data used by sd_path_* functions, see inline.h
3475 + */
3476 +struct sd_path_data {
3477 +       struct dentry *root, *dentry;
3478 +       struct namespace *namespace;
3479 +       struct list_head *head, *pos;
3480 +       int errno;
3481 +};
3482 +
3483 +#define SD_SUBDOMAIN(sec)      ((struct subdomain*)(sec))
3484 +#define SD_PROFILE(sec)                ((struct sdprofile*)(sec))
3485 +
3486 +/* Lock protecting access to 'struct subdomain' accesses */
3487 +extern rwlock_t sd_lock;
3488 +
3489 +extern struct sdprofile *null_profile;
3490 +extern struct sdprofile *null_complain_profile;
3491 +
3492 +/** sd_audit
3493 + *
3494 + * Auditing structure
3495 + */
3496 +
3497 +struct sd_audit {
3498 +       unsigned short type, flags;
3499 +       unsigned int result;
3500 +       unsigned int gfp_mask;
3501 +       int errorcode;
3502 +
3503 +       const char *name;
3504 +       unsigned int ival;
3505 +       union{
3506 +               const void *pval;
3507 +               va_list vaval;
3508 +       };
3509 +};
3510 +
3511 +/* audit types */
3512 +#define SD_AUDITTYPE_FILE      1
3513 +#define SD_AUDITTYPE_DIR       2
3514 +#define SD_AUDITTYPE_ATTR      3
3515 +#define SD_AUDITTYPE_XATTR     4
3516 +#define SD_AUDITTYPE_LINK      5
3517 +#define SD_AUDITTYPE_CAP       6
3518 +#define SD_AUDITTYPE_MSG       7
3519 +#define SD_AUDITTYPE_SYSCALL   8
3520 +#define SD_AUDITTYPE__END      9
3521 +
3522 +/* audit flags */
3523 +#define SD_AUDITFLAG_AUDITSS_SYSCALL 1 /* log syscall context */
3524 +#define SD_AUDITFLAG_LOGERR         2 /* log operations that failed due to
3525 +                                          non permission errors  */
3526 +
3527 +#define HINT_UNKNOWN_HAT "unknown_hat"
3528 +#define HINT_FORK "fork"
3529 +#define HINT_MANDPROF "missing_mandatory_profile"
3530 +#define HINT_CHGPROF "changing_profile"
3531 +
3532 +#define LOG_HINT(sd, gfp, hint, fmt, args...) \
3533 +       do {\
3534 +               sd_audit_message(sd, gfp, 0, \
3535 +                       "LOGPROF-HINT " hint " " fmt, ##args);\
3536 +       } while(0)
3537 +
3538 +/* diroptype */
3539 +#define SD_DIR_MKDIR 0
3540 +#define SD_DIR_RMDIR 1
3541 +
3542 +/* xattroptype */
3543 +#define SD_XATTR_GET    0
3544 +#define SD_XATTR_SET    1
3545 +#define SD_XATTR_LIST   2
3546 +#define SD_XATTR_REMOVE 3
3547 +
3548 +/* main.c */
3549 +extern int alloc_nullprofiles(void);
3550 +extern void free_nullprofiles(void);
3551 +extern int sd_audit_message(struct subdomain *, unsigned int gfp, int,
3552 +                           const char *, ...);
3553 +extern int sd_audit_syscallreject(struct subdomain *, unsigned int gfp,
3554 +                                 const char *);
3555 +extern int sd_audit(struct subdomain *, const struct sd_audit *);
3556 +extern char *sd_get_name(struct dentry *dentry, struct vfsmount *mnt);
3557 +
3558 +extern int sd_attr(struct subdomain *sd, struct dentry *dentry,
3559 +                  struct iattr *iattr);
3560 +extern int sd_xattr(struct subdomain *sd, struct dentry *dentry,
3561 +                   const char *xattr, int xattroptype);
3562 +extern int sd_capability(struct subdomain *sd, int cap);
3563 +extern int sd_perm(struct subdomain *sd, struct dentry *dentry,
3564 +                  struct vfsmount *mnt, int mask);
3565 +extern int sd_perm_nameidata(struct subdomain *sd, struct nameidata *nd,
3566 +                            int mask);
3567 +extern int sd_perm_dentry(struct subdomain *sd, struct dentry *dentry,
3568 +                         int mask);
3569 +extern int sd_perm_dir(struct subdomain *sd, struct dentry *dentry,
3570 +                      int diroptype);
3571 +extern int sd_link(struct subdomain *sd,
3572 +                  struct dentry *link, struct dentry *target);
3573 +extern int sd_fork(struct task_struct *p);
3574 +extern int sd_register(struct linux_binprm *bprm);
3575 +extern void sd_release(struct task_struct *p);
3576 +extern int sd_change_hat(const char *id, __u32 hat_magic);
3577 +extern int sd_associate_filp(struct file *filp);
3578 +
3579 +/* list.c */
3580 +extern struct sdprofile *sd_profilelist_find(const char *name);
3581 +extern int sd_profilelist_add(struct sdprofile *profile);
3582 +extern struct sdprofile *sd_profilelist_remove(const char *name);
3583 +extern void sd_profilelist_release(void);
3584 +extern struct sdprofile *sd_profilelist_replace(struct sdprofile *profile);
3585 +extern void sd_profile_dump(struct sdprofile *);
3586 +extern void sd_profilelist_dump(void);
3587 +extern void sd_subdomainlist_add(struct subdomain *);
3588 +extern void sd_subdomainlist_remove(struct subdomain *);
3589 +extern void sd_subdomainlist_iterate(sd_iter, void *);
3590 +extern void sd_subdomainlist_iterateremove(sd_iter, void *);
3591 +extern void sd_subdomainlist_release(void);
3592 +
3593 +/* subdomain_interface.c */
3594 +extern void free_sdprofile(struct sdprofile *profile);
3595 +extern int sd_sys_security(unsigned int id, unsigned call, unsigned long *args);
3596 +
3597 +/* procattr.c */
3598 +extern size_t sd_getprocattr(struct subdomain *sd, char *str, size_t size);
3599 +extern int sd_setprocattr_changehat(char *hatinfo, size_t infosize);
3600 +extern int sd_setprocattr_setprofile(struct task_struct *p, char *profilename,
3601 +                                    size_t profilesize);
3602 +
3603 +/* apparmorfs.c */
3604 +extern int create_subdomainfs(void);
3605 +extern int destroy_subdomainfs(void);
3606 +
3607 +/* capabilities.c */
3608 +extern const char *capability_to_name(unsigned int cap);
3609 +
3610 +/* apparmor_version.c */
3611 +extern const char *apparmor_version(void);
3612 +extern const char *apparmor_version_nl(void);
3613 +
3614 +#endif                         /* __SUBDOMAIN_H */
3615 --- linux-2.6.16.29.orig/security/apparmor/apparmor_version.c   1969-12-31 16:00:00.000000000 -0800
3616 +++ linux-2.6.16.29/security/apparmor/apparmor_version.c        2006-10-12 21:11:15.000000000 -0700
3617 @@ -0,0 +1,42 @@
3618 +/*
3619 + *     Copyright (C) 2005 Novell/SUSE
3620 + *
3621 + *     This program is free software; you can redistribute it and/or
3622 + *     modify it under the terms of the GNU General Public License as
3623 + *     published by the Free Software Foundation, version 2 of the
3624 + *     License.
3625 + *
3626 + *     AppArmor version definition
3627 + */
3628 +
3629 +#ifndef APPARMOR_VERSION
3630 +#error "-DAPPARMOR_VERSION must be specified when compiling this file"
3631 +#endif
3632 +
3633 +#define APPARMOR_VERSION_STR_PFX "APPARMOR_VERSION="
3634 +
3635 +#include <linux/module.h>
3636 +MODULE_VERSION(APPARMOR_VERSION);
3637 +
3638 +/* apparmor_version_str exists to allow a strings on module to
3639 + * see APPARMOR_VERSION= prefix
3640 + */
3641 +static const char *apparmor_version_str =
3642 +               APPARMOR_VERSION_STR_PFX APPARMOR_VERSION;
3643 +
3644 +/* apparmor_version_str_nl exists to allow an easy way to get a newline
3645 + * terminated string without having to do dynamic memory allocation
3646 + */
3647 +static const char *apparmor_version_str_nl = APPARMOR_VERSION "\n";
3648 +
3649 +const char *apparmor_version(void)
3650 +{
3651 +       const int len = sizeof(APPARMOR_VERSION_STR_PFX) - 1;
3652 +
3653 +       return apparmor_version_str + len;
3654 +}
3655 +
3656 +const char *apparmor_version_nl(void)
3657 +{
3658 +       return apparmor_version_str_nl;
3659 +}
3660 --- linux-2.6.16.29.orig/security/apparmor/capabilities.c       1969-12-31 16:00:00.000000000 -0800
3661 +++ linux-2.6.16.29/security/apparmor/capabilities.c    2006-10-12 21:11:15.000000000 -0700
3662 @@ -0,0 +1,54 @@
3663 +/*
3664 + *     Copyright (C) 2005 Novell/SUSE
3665 + *
3666 + *     This program is free software; you can redistribute it and/or
3667 + *     modify it under the terms of the GNU General Public License as
3668 + *     published by the Free Software Foundation, version 2 of the
3669 + *     License.
3670 + *
3671 + *     AppArmor capability definitions
3672 + */
3673 +
3674 +#include "apparmor.h"
3675 +
3676 +static const char *capnames[] = {
3677 +       "chown",
3678 +       "dac_override",
3679 +       "dac_read_search",
3680 +       "fowner",
3681 +       "fsetid",
3682 +       "kill",
3683 +       "setgid",
3684 +       "setuid",
3685 +       "setpcap",
3686 +       "linux_immutable",
3687 +       "net_bind_service",
3688 +       "net_broadcast",
3689 +       "net_admin",
3690 +       "net_raw",
3691 +       "ipc_lock",
3692 +       "ipc_owner",
3693 +       "sys_module",
3694 +       "sys_rawio",
3695 +       "sys_chroot",
3696 +       "sys_ptrace",
3697 +       "sys_pacct",
3698 +       "sys_admin",
3699 +       "sys_boot",
3700 +       "sys_nice",
3701 +       "sys_resource",
3702 +       "sys_time",
3703 +       "sys_tty_config",
3704 +       "mknod",
3705 +       "lease"
3706 +};
3707 +
3708 +const char *capability_to_name(unsigned int cap)
3709 +{
3710 +       const char *capname;
3711 +
3712 +       capname = (cap < (sizeof(capnames) / sizeof(char *))
3713 +                  ? capnames[cap] : "invalid-capability");
3714 +
3715 +       return capname;
3716 +}
3717 --- linux-2.6.16.29.orig/security/apparmor/inline.h     1969-12-31 16:00:00.000000000 -0800
3718 +++ linux-2.6.16.29/security/apparmor/inline.h  2006-10-12 21:11:15.000000000 -0700
3719 @@ -0,0 +1,364 @@
3720 +/*
3721 + *     Copyright (C) 2005 Novell/SUSE
3722 + *
3723 + *     This program is free software; you can redistribute it and/or
3724 + *     modify it under the terms of the GNU General Public License as
3725 + *     published by the Free Software Foundation, version 2 of the
3726 + *     License.
3727 + */
3728 +
3729 +#ifndef __INLINE_H
3730 +#define __INLINE_H
3731 +
3732 +#include <linux/namespace.h>
3733 +
3734 +static inline int __sd_is_confined(struct subdomain *sd)
3735 +{
3736 +       int rc = 0;
3737 +
3738 +       if (sd && sd->sd_magic == SD_ID_MAGIC && sd->profile) {
3739 +               BUG_ON(!sd->active);
3740 +               rc = 1;
3741 +       }
3742 +
3743 +       return rc;
3744 +}
3745 +
3746 +/**
3747 + *  sd_is_confined
3748 + *  @sd: subdomain
3749 + *
3750 + *  Check if @sd is confined (contains a valid profile)
3751 + *  Return 1 if confined, 0 otherwise.
3752 + */
3753 +static inline int sd_is_confined(void)
3754 +{
3755 +       struct subdomain *sd = SD_SUBDOMAIN(current->security);
3756 +       return __sd_is_confined(sd);
3757 +}
3758 +
3759 +static inline int __sd_sub_defined(struct subdomain *sd)
3760 +{
3761 +       return __sd_is_confined(sd) && !list_empty(&sd->profile->sub);
3762 +}
3763 +
3764 +/**
3765 + * sd_sub_defined
3766 + * @sd: subdomain
3767 + *
3768 + * Check if @sd has at least one subprofile
3769 + * Return 1 if true, 0 otherwise
3770 + */
3771 +static inline int sd_sub_defined(void)
3772 +{
3773 +       struct subdomain *sd = SD_SUBDOMAIN(current->security);
3774 +       return __sd_sub_defined(sd);
3775 +}
3776 +
3777 +/**
3778 + * get_sdprofile
3779 + * @p: profile
3780 + *
3781 + * Increment refcount on profile
3782 + */
3783 +static inline struct sdprofile *get_sdprofile(struct sdprofile *p)
3784 +{
3785 +       if (p)
3786 +               atomic_inc(&p->count);
3787 +       return p;
3788 +}
3789 +
3790 +/**
3791 + * put_sdprofile
3792 + * @p: profile
3793 + *
3794 + * Decrement refcount on profile
3795 + */
3796 +static inline void put_sdprofile(struct sdprofile *p)
3797 +{
3798 +       if (p)
3799 +               if (atomic_dec_and_test(&p->count))
3800 +                       free_sdprofile(p);
3801 +}
3802 +
3803 +/**
3804 + * sd_switch
3805 + * @sd: subdomain to switch
3806 + * @profile: new profile
3807 + * @active:  new active
3808 + *
3809 + * Change subdomain to use new profiles.
3810 + */
3811 +static inline void sd_switch(struct subdomain *sd,
3812 +                                struct sdprofile *profile,
3813 +                                struct sdprofile *active)
3814 +{
3815 +       /* noop if NULL */
3816 +       put_sdprofile(sd->profile);
3817 +       put_sdprofile(sd->active);
3818 +
3819 +       sd->profile = get_sdprofile(profile);
3820 +       sd->active = get_sdprofile(active);
3821 +}
3822 +
3823 +/**
3824 + * sd_switch_unconfined
3825 + * @sd: subdomain to switch
3826 + *
3827 + * Change subdomain to unconfined
3828 + */
3829 +static inline void sd_switch_unconfined(struct subdomain *sd)
3830 +{
3831 +       sd_switch(sd, NULL, NULL);
3832 +
3833 +       /* reset magic in case we were in a subhat before */
3834 +       sd->sd_hat_magic = 0;
3835 +}
3836 +
3837 +/**
3838 + * alloc_subdomain
3839 + * @tsk: task struct
3840 + *
3841 + * Allocate a new subdomain including a backpointer to it's referring task.
3842 + */
3843 +static inline struct subdomain *alloc_subdomain(struct task_struct *tsk)
3844 +{
3845 +       struct subdomain *sd;
3846 +
3847 +       sd = kmalloc(sizeof(struct subdomain), GFP_KERNEL);
3848 +       if (!sd)
3849 +               goto out;
3850 +
3851 +       /* zero it first */
3852 +       memset(sd, 0, sizeof(struct subdomain));
3853 +       sd->sd_magic = SD_ID_MAGIC;
3854 +
3855 +       /* back pointer to task */
3856 +       sd->task = tsk;
3857 +
3858 +       /* any readers of the list must make sure that they can handle
3859 +        * case where sd->profile and sd->active are not yet set (null)
3860 +        */
3861 +       sd_subdomainlist_add(sd);
3862 +
3863 +out:
3864 +       return sd;
3865 +}
3866 +
3867 +/**
3868 + * free_subdomain
3869 + * @sd: subdomain
3870 + *
3871 + * Free a subdomain previously allocated by alloc_subdomain
3872 + */
3873 +static inline void free_subdomain(struct subdomain *sd)
3874 +{
3875 +       sd_subdomainlist_remove(sd);
3876 +       kfree(sd);
3877 +}
3878 +
3879 +/**
3880 + * alloc_sdprofile
3881 + *
3882 + * Allocate, initialize and return a new zeroed profile.
3883 + * Returns NULL on failure.
3884 + */
3885 +static inline struct sdprofile *alloc_sdprofile(void)
3886 +{
3887 +       struct sdprofile *profile;
3888 +
3889 +       profile = (struct sdprofile *)kmalloc(sizeof(struct sdprofile),
3890 +                                             GFP_KERNEL);
3891 +       SD_DEBUG("%s(%p)\n", __FUNCTION__, profile);
3892 +       if (profile) {
3893 +               int i;
3894 +               memset(profile, 0, sizeof(struct sdprofile));
3895 +               INIT_LIST_HEAD(&profile->list);
3896 +               INIT_LIST_HEAD(&profile->sub);
3897 +               INIT_LIST_HEAD(&profile->file_entry);
3898 +               for (i = 0; i <= POS_SD_FILE_MAX; i++) {
3899 +                       INIT_LIST_HEAD(&profile->file_entryp[i]);
3900 +               }
3901 +       }
3902 +       return profile;
3903 +}
3904 +
3905 +/**
3906 + * sd_put_name
3907 + * @name: name to release.
3908 + *
3909 + * Release space (free_page) allocated to hold pathname
3910 + * name may be NULL (checked for by free_page)
3911 + */
3912 +static inline void sd_put_name(const char *name)
3913 +{
3914 +       free_page((unsigned long)name);
3915 +}
3916 +
3917 +/** __sd_find_profile
3918 + * @name: name of profile to find
3919 + * @head: list to search
3920 + *
3921 + * Return reference counted copy of profile. NULL if not found
3922 + * Caller must hold any necessary locks
3923 + */
3924 +static inline struct sdprofile *__sd_find_profile(const char *name,
3925 +                                                     struct list_head *head)
3926 +{
3927 +       struct sdprofile *p;
3928 +
3929 +       if (!name || !head)
3930 +               return NULL;
3931 +
3932 +       SD_DEBUG("%s: finding profile %s\n", __FUNCTION__, name);
3933 +       list_for_each_entry(p, head, list) {
3934 +               if (!strcmp(p->name, name)) {
3935 +                       /* return refcounted object */
3936 +                       p = get_sdprofile(p);
3937 +                       return p;
3938 +               } else {
3939 +                       SD_DEBUG("%s: skipping %s\n", __FUNCTION__, p->name);
3940 +               }
3941 +       }
3942 +       return NULL;
3943 +}
3944 +
3945 +static inline struct subdomain *__get_sdcopy(struct subdomain *new,
3946 +                                                struct task_struct *tsk)
3947 +{
3948 +       struct subdomain *old, *temp = NULL;
3949 +
3950 +       old = SD_SUBDOMAIN(tsk->security);
3951 +
3952 +       if (old) {
3953 +               new->sd_magic = old->sd_magic;
3954 +               new->sd_hat_magic = old->sd_hat_magic;
3955 +
3956 +               new->active = get_sdprofile(old->active);
3957 +
3958 +               if (old->profile == old->active)
3959 +                       new->profile = new->active;
3960 +               else
3961 +                       new->profile = get_sdprofile(old->profile);
3962 +
3963 +               temp = new;
3964 +       }
3965 +
3966 +       return temp;
3967 +}
3968 +
3969 +/** get_sdcopy
3970 + * @new: subdomain to hold copy
3971 + *
3972 + * Make copy of current subdomain containing refcounted profile and active
3973 + * Used to protect readers against racing writers (changehat and profile
3974 + * replacement).
3975 + */
3976 +static inline struct subdomain *get_sdcopy(struct subdomain *new)
3977 +{
3978 +       struct subdomain *temp;
3979 +       unsigned long flags;
3980 +
3981 +       read_lock_irqsave(&sd_lock, flags);
3982 +
3983 +       temp = __get_sdcopy(new, current);
3984 +
3985 +       read_unlock_irqrestore(&sd_lock, flags);
3986 +
3987 +       return temp;
3988 +}
3989 +
3990 +/** get_sdcopy
3991 + * @temp: subdomain to drop refcounts on
3992 + *
3993 + * Drop refcounted profile/active in copy of subdomain made by get_sdcopy
3994 + */
3995 +static inline void put_sdcopy(struct subdomain *temp)
3996 +{
3997 +       if (temp) {
3998 +               put_sdprofile(temp->active);
3999 +               if (temp->active != temp->profile)
4000 +                       (void)put_sdprofile(temp->profile);
4001 +       }
4002 +}
4003 +
4004 +/** sd_path_begin2
4005 + * @rdentry: filesystem root dentry (searching for vfsmnts matching this)
4006 + * @dentry: dentry object to obtain pathname from (relative to matched vfsmnt)
4007 + *
4008 + * Setup data for iterating over vfsmounts (in current tasks namespace).
4009 + */
4010 +static inline void sd_path_begin2(struct dentry *rdentry,
4011 +                                     struct dentry *dentry,
4012 +                                     struct sd_path_data *data)
4013 +{
4014 +       data->dentry = dentry;
4015 +       data->root = dget(rdentry->d_sb->s_root);
4016 +       data->namespace = current->namespace;
4017 +       data->head = &data->namespace->list;
4018 +       data->pos = data->head->next;
4019 +       prefetch(data->pos->next);
4020 +       data->errno = 0;
4021 +
4022 +       down_read(&namespace_sem);
4023 +}
4024 +
4025 +/** sd_path_begin
4026 + * @dentry filesystem root dentry and object to obtain pathname from
4027 + *
4028 + * Utility function for calling _sd_path_begin for when the dentry we are
4029 + * looking for and the root are the same (this is the usual case).
4030 + */
4031 +static inline void sd_path_begin(struct dentry *dentry,
4032 +                                    struct sd_path_data *data)
4033 +{
4034 +       sd_path_begin2(dentry, dentry, data);
4035 +}
4036 +
4037 +/** sd_path_end
4038 + * @data: data object previously initialized by sd_path_begin
4039 + *
4040 + * End iterating over vfsmounts.
4041 + * If an error occured in begin or get, it is returned. Otherwise 0.
4042 + */
4043 +static inline int sd_path_end(struct sd_path_data *data)
4044 +{
4045 +       up_read(&namespace_sem);
4046 +       dput(data->root);
4047 +
4048 +       return data->errno;
4049 +}
4050 +
4051 +/** sd_path_getname
4052 + * @data: data object previously initialized by sd_path_begin
4053 + *
4054 + * Return the next mountpoint which has the same root dentry as data->root.
4055 + * If no more mount points exist (or in case of error) NULL is returned
4056 + * (caller should call sd_path_end() and inspect return code to differentiate)
4057 + */
4058 +static inline char *sd_path_getname(struct sd_path_data *data)
4059 +{
4060 +       char *name = NULL;
4061 +       struct vfsmount *mnt;
4062 +
4063 +       while (data->pos != data->head) {
4064 +               mnt = list_entry(data->pos, struct vfsmount, mnt_list);
4065 +
4066 +               /* advance to next -- so that it is done before we break */
4067 +               data->pos = data->pos->next;
4068 +               prefetch(data->pos->next);
4069 +
4070 +               if (mnt->mnt_root == data->root) {
4071 +                       name = sd_get_name(data->dentry, mnt);
4072 +                       if (IS_ERR(name)) {
4073 +                               data->errno = PTR_ERR(name);
4074 +                               name = NULL;
4075 +                       }
4076 +                       break;
4077 +               }
4078 +       }
4079 +
4080 +       return name;
4081 +}
4082 +
4083 +#endif /* __INLINE_H__ */
4084 --- linux-2.6.16.29.orig/security/apparmor/Kbuild       1969-12-31 16:00:00.000000000 -0800
4085 +++ linux-2.6.16.29/security/apparmor/Kbuild    2006-10-12 21:11:15.000000000 -0700
4086 @@ -0,0 +1,10 @@
4087 +# Makefile for AppArmor Linux Security Module
4088 +#
4089 +EXTRA_CFLAGS += -DAPPARMOR_VERSION=\"${APPARMOR_VER}\"
4090 +
4091 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
4092 +
4093 +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o capabilities.o \
4094 +             module_interface.o apparmor_version.o
4095 +
4096 +obj-$(CONFIG_SECURITY_APPARMOR) += aamatch/
4097 --- linux-2.6.16.29.orig/security/apparmor/Kconfig      1969-12-31 16:00:00.000000000 -0800
4098 +++ linux-2.6.16.29/security/apparmor/Kconfig   2006-10-12 21:11:15.000000000 -0700
4099 @@ -0,0 +1,9 @@
4100 +config SECURITY_APPARMOR
4101 +       tristate "AppArmor support"
4102 +       depends on SECURITY!=n
4103 +       help
4104 +         This enables the AppArmor security module.
4105 +         Required userspace tools (if they are not included in your
4106 +         distribution) and further information may be found at
4107 +         <http://forge.novell.com/modules/xfmod/project/?apparmor>
4108 +         If you are unsure how to answer this question, answer N.
4109 --- linux-2.6.16.29.orig/security/apparmor/list.c       1969-12-31 16:00:00.000000000 -0800
4110 +++ linux-2.6.16.29/security/apparmor/list.c    2006-10-12 21:11:15.000000000 -0700
4111 @@ -0,0 +1,271 @@
4112 +/*
4113 + *     Copyright (C) 1998-2005 Novell/SUSE
4114 + *
4115 + *     This program is free software; you can redistribute it and/or
4116 + *     modify it under the terms of the GNU General Public License as
4117 + *     published by the Free Software Foundation, version 2 of the
4118 + *     License.
4119 + *
4120 + *     AppArmor Profile List Management
4121 + */
4122 +
4123 +#include <linux/seq_file.h>
4124 +#include "apparmor.h"
4125 +#include "inline.h"
4126 +
4127 +/* list of all profiles and lock */
4128 +static LIST_HEAD(profile_list);
4129 +static rwlock_t profile_lock = RW_LOCK_UNLOCKED;
4130 +
4131 +/* list of all subdomains and lock */
4132 +static LIST_HEAD(subdomain_list);
4133 +static rwlock_t subdomain_lock = RW_LOCK_UNLOCKED;
4134 +
4135 +/**
4136 + * sd_profilelist_find
4137 + * @name: profile name (program name)
4138 + *
4139 + * Search the profile list for profile @name.  Return refcounted profile on
4140 + * success, NULL on failure.
4141 + */
4142 +struct sdprofile *sd_profilelist_find(const char *name)
4143 +{
4144 +       struct sdprofile *p = NULL;
4145 +       if (name) {
4146 +               read_lock(&profile_lock);
4147 +               p = __sd_find_profile(name, &profile_list);
4148 +               read_unlock(&profile_lock);
4149 +       }
4150 +       return p;
4151 +}
4152 +
4153 +/**
4154 + * sd_profilelist_add
4155 + * @profile: new profile to add to list
4156 + *
4157 + * Add new profile to list.  Reference count on profile is incremented.
4158 + * Return 1 on success, 0 on failure (bad profile or already exists)
4159 + */
4160 +int sd_profilelist_add(struct sdprofile *profile)
4161 +{
4162 +       struct sdprofile *old_profile;
4163 +       int ret = 0;
4164 +
4165 +       if (!profile)
4166 +               goto out;
4167 +
4168 +       write_lock(&profile_lock);
4169 +       old_profile = __sd_find_profile(profile->name, &profile_list);
4170 +       if (old_profile) {
4171 +               put_sdprofile(old_profile);
4172 +               goto out;
4173 +       }
4174 +       profile = get_sdprofile(profile);
4175 +
4176 +       list_add(&profile->list, &profile_list);
4177 +       ret = 1;
4178 + out:
4179 +       write_unlock(&profile_lock);
4180 +       return ret;
4181 +}
4182 +
4183 +/**
4184 + * sd_profilelist_remove
4185 + * @name: name of profile to be removed
4186 + *
4187 + * If the profile exists remove profile from list and return its reference.
4188 + * The reference count on profile is not decremented and should be decremented
4189 + * when the profile is no longer needed
4190 + */
4191 +struct sdprofile *sd_profilelist_remove(const char *name)
4192 +{
4193 +       struct sdprofile *profile = NULL;
4194 +       struct sdprofile *p, *tmp;
4195 +
4196 +       if (!name)
4197 +               goto out;
4198 +
4199 +       write_lock(&profile_lock);
4200 +       list_for_each_entry_safe(p, tmp, &profile_list, list) {
4201 +               if (!strcmp(p->name, name)) {
4202 +                       list_del_init(&p->list);
4203 +                       /* mark old profile as stale */
4204 +                       p->isstale = 1;
4205 +                       profile = p;
4206 +                       break;
4207 +               }
4208 +       }
4209 +       write_unlock(&profile_lock);
4210 +
4211 +out:
4212 +       return profile;
4213 +}
4214 +
4215 +/**
4216 + * sd_profilelist_replace
4217 + * @profile - new profile
4218 + *
4219 + * Replace a profile on the profile list.  Find the old profile by name in
4220 + * the list, and replace it with the new profile.  This is an atomic
4221 + * list operation.  Returns the old profile (which is still refcounted) if
4222 + * there was one, or NULL.
4223 + */
4224 +struct sdprofile *sd_profilelist_replace(struct sdprofile *profile)
4225 +{
4226 +       struct sdprofile *oldprofile;
4227 +
4228 +       write_lock(&profile_lock);
4229 +       oldprofile = __sd_find_profile(profile->name, &profile_list);
4230 +       if (oldprofile) {
4231 +               list_del_init(&oldprofile->list);
4232 +               /* mark old profile as stale */
4233 +               oldprofile->isstale = 1;
4234 +
4235 +               /* __sd_find_profile incremented count, so adjust down */
4236 +               put_sdprofile(oldprofile);
4237 +       }
4238 +       profile = get_sdprofile(profile);
4239 +       list_add(&profile->list, &profile_list);
4240 +       write_unlock(&profile_lock);
4241 +
4242 +       return oldprofile;
4243 +}
4244 +
4245 +/**
4246 + * sd_profilelist_release
4247 + *
4248 + * Remove all profiles from profile_list
4249 + */
4250 +void sd_profilelist_release(void)
4251 +{
4252 +       struct sdprofile *p, *tmp;
4253 +
4254 +       write_lock(&profile_lock);
4255 +       list_for_each_entry_safe(p, tmp, &profile_list, list) {
4256 +               list_del_init(&p->list);
4257 +               put_sdprofile(p);
4258 +       }
4259 +       write_unlock(&profile_lock);
4260 +}
4261 +
4262 +/**
4263 + * sd_subdomainlist_add
4264 + * @sd: new subdomain
4265 + *
4266 + * Add subdomain to subdomain_list
4267 + */
4268 +void sd_subdomainlist_add(struct subdomain *sd)
4269 +{
4270 +       unsigned long flags;
4271 +
4272 +       if (!sd) {
4273 +               SD_INFO("%s: bad subdomain\n", __FUNCTION__);
4274 +               return;
4275 +       }
4276 +
4277 +       write_lock_irqsave(&subdomain_lock, flags);
4278 +       /* new subdomains must be added to the end of the list due to a
4279 +        * subtle interaction between fork and profile replacement.
4280 +        */
4281 +       list_add_tail(&sd->list, &subdomain_list);
4282 +       write_unlock_irqrestore(&subdomain_lock, flags);
4283 +}
4284 +
4285 +/**
4286 + * sd_subdomainlist_remove
4287 + * @sd: subdomain to be removed
4288 + *
4289 + * Remove subdomain from subdomain_list
4290 + */
4291 +void sd_subdomainlist_remove(struct subdomain *sd)
4292 +{
4293 +       unsigned long flags;
4294 +
4295 +       if (sd) {
4296 +               write_lock_irqsave(&subdomain_lock, flags);
4297 +               list_del_init(&sd->list);
4298 +               write_unlock_irqrestore(&subdomain_lock, flags);
4299 +       }
4300 +}
4301 +
4302 +/**
4303 + * sd_subdomainlist_iterate
4304 + * @func: method to be called for each element
4305 + * @cookie: user passed data
4306 + *
4307 + * Iterate over subdomain list, stop when sd_iter func returns non zero
4308 + */
4309 +void sd_subdomainlist_iterate(sd_iter func, void *cookie)
4310 +{
4311 +       struct subdomain *node;
4312 +       int ret = 0;
4313 +       unsigned long flags;
4314 +
4315 +       read_lock_irqsave(&subdomain_lock, flags);
4316 +       list_for_each_entry(node, &subdomain_list, list) {
4317 +               ret = (*func) (node, cookie);
4318 +               if (ret != 0)
4319 +                       break;
4320 +       }
4321 +       read_unlock_irqrestore(&subdomain_lock, flags);
4322 +}
4323 +
4324 +/**
4325 + * sd_subdomainlist_release
4326 + *
4327 + * Remove all subdomains from subdomain_list
4328 + */
4329 +void sd_subdomainlist_release()
4330 +{
4331 +       struct subdomain *node, *tmp;
4332 +       unsigned long flags;
4333 +
4334 +       write_lock_irqsave(&subdomain_lock, flags);
4335 +       list_for_each_entry_safe(node, tmp, &subdomain_list, list) {
4336 +               list_del_init(&node->list);
4337 +       }
4338 +       write_unlock_irqrestore(&subdomain_lock, flags);
4339 +}
4340 +
4341 +/* seq_file helper routines
4342 + * Used by subdomainfs.c to iterate over profile_list
4343 + */
4344 +static void *p_start(struct seq_file *f, loff_t *pos)
4345 +{
4346 +       struct sdprofile *node;
4347 +       loff_t l = *pos;
4348 +
4349 +       read_lock(&profile_lock);
4350 +       list_for_each_entry(node, &profile_list, list)
4351 +               if (!l--)
4352 +                       return node;
4353 +       return NULL;
4354 +}
4355 +
4356 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
4357 +{
4358 +       struct list_head *lh = ((struct sdprofile *)p)->list.next;
4359 +       (*pos)++;
4360 +       return lh == &profile_list ?
4361 +                       NULL : list_entry(lh, struct sdprofile, list);
4362 +}
4363 +
4364 +static void p_stop(struct seq_file *f, void *v)
4365 +{
4366 +       read_unlock(&profile_lock);
4367 +}
4368 +
4369 +static int seq_show_profile(struct seq_file *f, void *v)
4370 +{
4371 +       struct sdprofile *profile = (struct sdprofile *)v;
4372 +       seq_printf(f, "%s (%s)\n", profile->name,
4373 +                  PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
4374 +       return 0;
4375 +}
4376 +
4377 +struct seq_operations subdomainfs_profiles_op = {
4378 +       .start =        p_start,
4379 +       .next =         p_next,
4380 +       .stop =         p_stop,
4381 +       .show =         seq_show_profile,
4382 +};
4383 --- linux-2.6.16.29.orig/security/apparmor/lsm.c        1969-12-31 16:00:00.000000000 -0800
4384 +++ linux-2.6.16.29/security/apparmor/lsm.c     2006-10-12 21:11:15.000000000 -0700
4385 @@ -0,0 +1,959 @@
4386 +/*
4387 + *     Copyright (C) 2002-2005 Novell/SUSE
4388 + *
4389 + *     This program is free software; you can redistribute it and/or
4390 + *     modify it under the terms of the GNU General Public License as
4391 + *     published by the Free Software Foundation, version 2 of the
4392 + *     License.
4393 + *
4394 + *     http://forge.novell.com/modules/xfmod/project/?apparmor
4395 + *
4396 + *     Immunix AppArmor LSM interface (previously called "SubDomain")
4397 + */
4398 +
4399 +#include <linux/security.h>
4400 +#include <linux/module.h>
4401 +#include <linux/mm.h>
4402 +
4403 +/* superblock types */
4404 +
4405 +/* PIPEFS_MAGIC */
4406 +#include <linux/pipe_fs_i.h>
4407 +/* from net/socket.c */
4408 +#define SOCKFS_MAGIC 0x534F434B
4409 +/* from inotify.c  */
4410 +#define INOTIFYFS_MAGIC 0xBAD1DEA
4411 +
4412 +#define VALID_FSTYPE(inode) ((inode)->i_sb->s_magic != PIPEFS_MAGIC && \
4413 +                             (inode)->i_sb->s_magic != SOCKFS_MAGIC && \
4414 +                             (inode)->i_sb->s_magic != INOTIFYFS_MAGIC)
4415 +
4416 +#include <asm/mman.h>
4417 +
4418 +#include "apparmor.h"
4419 +#include "inline.h"
4420 +
4421 +/* main SD lock [see get_sdcopy and put_sdcopy] */
4422 +rwlock_t sd_lock = RW_LOCK_UNLOCKED;
4423 +
4424 +/* Flag values, also controllable via subdomainfs/control.
4425 + * We explicitly do not allow these to be modifiable when exported via
4426 + * /sys/modules/parameters, as we want to do additional mediation and
4427 + * don't want to add special path code. */
4428 +
4429 +/* Complain mode (used to be 'bitch' mode) */
4430 +int subdomain_complain = 0;
4431 +module_param_named(complain, subdomain_complain, int, S_IRUSR);
4432 +MODULE_PARM_DESC(subdomain_complain, "Toggle AppArmor complain mode");
4433 +
4434 +/* Debug mode */
4435 +int subdomain_debug = 0;
4436 +module_param_named(debug, subdomain_debug, int, S_IRUSR);
4437 +MODULE_PARM_DESC(subdomain_debug, "Toggle AppArmor debug mode");
4438 +
4439 +/* Audit mode */
4440 +int subdomain_audit = 0;
4441 +module_param_named(audit, subdomain_audit, int, S_IRUSR);
4442 +MODULE_PARM_DESC(subdomain_audit, "Toggle AppArmor audit mode");
4443 +
4444 +/* Syscall logging mode */
4445 +int subdomain_logsyscall = 0;
4446 +module_param_named(logsyscall, subdomain_logsyscall, int, S_IRUSR);
4447 +MODULE_PARM_DESC(subdomain_logsyscall, "Toggle AppArmor logsyscall mode");
4448 +
4449 +#ifndef MODULE
4450 +static int __init sd_getopt_complain(char *str)
4451 +{
4452 +       get_option(&str, &subdomain_complain);
4453 +       return 1;
4454 +}
4455 +__setup("subdomain_complain=", sd_getopt_complain);
4456 +
4457 +static int __init sd_getopt_debug(char *str)
4458 +{
4459 +       get_option(&str, &subdomain_debug);
4460 +       return 1;
4461 +}
4462 +__setup("subdomain_debug=", sd_getopt_debug);
4463 +
4464 +static int __init sd_getopt_audit(char *str)
4465 +{
4466 +       get_option(&str, &subdomain_audit);
4467 +       return 1;
4468 +}
4469 +__setup("subdomain_audit=", sd_getopt_audit);
4470 +
4471 +static int __init sd_getopt_logsyscall(char *str)
4472 +{
4473 +       get_option(&str, &subdomain_logsyscall);
4474 +       return 1;
4475 +}
4476 +__setup("subdomain_logsyscall=", sd_getopt_logsyscall);
4477 +#endif
4478 +
4479 +static int subdomain_ptrace(struct task_struct *parent,
4480 +                           struct task_struct *child)
4481 +{
4482 +       int error;
4483 +       struct subdomain *sd;
4484 +       unsigned long flags;
4485 +
4486 +       error = cap_ptrace(parent, child);
4487 +
4488 +       if (error == 0 && parent->security) {
4489 +               read_lock_irqsave(&sd_lock, flags);
4490 +
4491 +               sd = SD_SUBDOMAIN(parent->security);
4492 +
4493 +               if (__sd_is_confined(sd)) {
4494 +                       error = sd_audit_syscallreject(sd, GFP_ATOMIC,
4495 +                                                      "ptrace");
4496 +                       WARN_ON(error != -EPERM);
4497 +               }
4498 +
4499 +               read_unlock_irqrestore(&sd_lock, flags);
4500 +       }
4501 +
4502 +       return error;
4503 +}
4504 +
4505 +static int subdomain_capget(struct task_struct *target,
4506 +                           kernel_cap_t * effective,
4507 +                           kernel_cap_t * inheritable,
4508 +                           kernel_cap_t * permitted)
4509 +{
4510 +       return cap_capget(target, effective, inheritable, permitted);
4511 +}
4512 +
4513 +static int subdomain_capset_check(struct task_struct *target,
4514 +                                 kernel_cap_t *effective,
4515 +                                 kernel_cap_t *inheritable,
4516 +                                 kernel_cap_t *permitted)
4517 +{
4518 +       return cap_capset_check(target, effective, inheritable, permitted);
4519 +}
4520 +
4521 +static void subdomain_capset_set(struct task_struct *target,
4522 +                                kernel_cap_t *effective,
4523 +                                kernel_cap_t *inheritable,
4524 +                                kernel_cap_t *permitted)
4525 +{
4526 +       cap_capset_set(target, effective, inheritable, permitted);
4527 +       return;
4528 +}
4529 +
4530 +static int subdomain_capable(struct task_struct *tsk, int cap)
4531 +{
4532 +       int error;
4533 +
4534 +       /* cap_capable returns 0 on success, else -EPERM */
4535 +       error = cap_capable(tsk, cap);
4536 +
4537 +       if (error == 0 && current->security) {
4538 +               struct subdomain *sd, sdcopy;
4539 +               unsigned long flags;
4540 +
4541 +               read_lock_irqsave(&sd_lock, flags);
4542 +               sd = __get_sdcopy(&sdcopy, tsk);
4543 +               read_unlock_irqrestore(&sd_lock, flags);
4544 +
4545 +               error = sd_capability(sd, cap);
4546 +
4547 +               put_sdcopy(sd);
4548 +       }
4549 +
4550 +       return error;
4551 +}
4552 +
4553 +static int subdomain_sysctl(struct ctl_table *table, int op)
4554 +{
4555 +       int error = 0;
4556 +       struct subdomain *sd;
4557 +       unsigned long flags;
4558 +
4559 +       if (!current->security)
4560 +               return 0;
4561 +
4562 +       read_lock_irqsave(&sd_lock, flags);
4563 +
4564 +       sd = SD_SUBDOMAIN(current->security);
4565 +
4566 +       if ((op & 002) && __sd_is_confined(sd) && !capable(CAP_SYS_ADMIN)) {
4567 +               error = sd_audit_syscallreject(sd, GFP_ATOMIC,
4568 +                                              "sysctl (write)");
4569 +               WARN_ON(error != -EPERM);
4570 +       }
4571 +
4572 +       read_unlock_irqrestore(&sd_lock, flags);
4573 +
4574 +       return error;
4575 +}
4576 +
4577 +static int subdomain_syslog(int type)
4578 +{
4579 +       return cap_syslog(type);
4580 +}
4581 +
4582 +static int subdomain_netlink_send(struct sock *sk, struct sk_buff *skb)
4583 +{
4584 +       return cap_netlink_send(sk, skb);
4585 +}
4586 +
4587 +static int subdomain_netlink_recv(struct sk_buff *skb)
4588 +{
4589 +       return cap_netlink_recv(skb);
4590 +}
4591 +
4592 +static void subdomain_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
4593 +{
4594 +       cap_bprm_apply_creds(bprm, unsafe);
4595 +       return;
4596 +}
4597 +
4598 +static int subdomain_bprm_set_security(struct linux_binprm *bprm)
4599 +{
4600 +       /* handle capability bits with setuid, etc */
4601 +       cap_bprm_set_security(bprm);
4602 +       /* already set based on script name */
4603 +       if (bprm->sh_bang)
4604 +               return 0;
4605 +       return sd_register(bprm);
4606 +}
4607 +
4608 +static int subdomain_bprm_secureexec(struct linux_binprm *bprm)
4609 +{
4610 +       int ret = cap_bprm_secureexec(bprm);
4611 +
4612 +       if (ret == 0 && (unsigned long)bprm->security & SD_SECURE_EXEC_NEEDED) {
4613 +               SD_DEBUG("%s: secureexec required for %s\n",
4614 +                       __FUNCTION__, bprm->filename);
4615 +               ret = 1;
4616 +       }
4617 +
4618 +       return ret;
4619 +}
4620 +
4621 +static int subdomain_sb_mount(char *dev_name, struct nameidata *nd, char *type,
4622 +                             unsigned long flags, void *data)
4623 +{
4624 +       int error = 0;
4625 +       struct subdomain *sd;
4626 +       unsigned long lockflags;
4627 +
4628 +       if (!current->security)
4629 +               return 0;
4630 +
4631 +       read_lock_irqsave(&sd_lock, lockflags);
4632 +
4633 +       sd = SD_SUBDOMAIN(current->security);
4634 +
4635 +       if (__sd_is_confined(sd)) {
4636 +               error = sd_audit_syscallreject(sd, GFP_ATOMIC, "mount");
4637 +               WARN_ON(error != -EPERM);
4638 +       }
4639 +
4640 +       read_unlock_irqrestore(&sd_lock, lockflags);
4641 +
4642 +       return error;
4643 +}
4644 +
4645 +static int subdomain_umount(struct vfsmount *mnt, int flags)
4646 +{
4647 +       int error = 0;
4648 +       struct subdomain *sd;
4649 +       unsigned long lockflags;
4650 +
4651 +       if (!current->security)
4652 +               return 0;
4653 +
4654 +       read_lock_irqsave(&sd_lock, lockflags);
4655 +
4656 +       sd = SD_SUBDOMAIN(current->security);
4657 +
4658 +       if (__sd_is_confined(sd)) {
4659 +               error = sd_audit_syscallreject(sd, GFP_ATOMIC, "umount");
4660 +               WARN_ON(error != -EPERM);
4661 +       }
4662 +
4663 +       read_unlock_irqrestore(&sd_lock, lockflags);
4664 +
4665 +       return error;
4666 +}
4667 +
4668 +static int subdomain_inode_mkdir(struct inode *inode, struct dentry *dentry,
4669 +                                int mask)
4670 +{
4671 +       struct subdomain sdcopy, *sd;
4672 +       int error;
4673 +
4674 +       if (!current->security)
4675 +               return 0;
4676 +
4677 +       sd = get_sdcopy(&sdcopy);
4678 +
4679 +       error = sd_perm_dir(sd, dentry, SD_DIR_MKDIR);
4680 +
4681 +       put_sdcopy(sd);
4682 +
4683 +       return error;
4684 +}
4685 +
4686 +static int subdomain_inode_rmdir(struct inode *inode, struct dentry *dentry)
4687 +{
4688 +       struct subdomain sdcopy, *sd;
4689 +       int error;
4690 +
4691 +       if (!current->security)
4692 +               return 0;
4693 +
4694 +       sd = get_sdcopy(&sdcopy);
4695 +
4696 +       error = sd_perm_dir(sd, dentry, SD_DIR_RMDIR);
4697 +
4698 +       put_sdcopy(sd);
4699 +
4700 +       return error;
4701 +}
4702 +
4703 +static int subdomain_inode_create(struct inode *inode, struct dentry *dentry,
4704 +                                 int mask)
4705 +{
4706 +       struct subdomain sdcopy, *sd;
4707 +       int error;
4708 +
4709 +       if (!current->security)
4710 +               return 0;
4711 +
4712 +       sd = get_sdcopy(&sdcopy);
4713 +
4714 +       /* At a minimum, need write perm to create */
4715 +       error = sd_perm_dentry(sd, dentry, MAY_WRITE);
4716 +
4717 +       put_sdcopy(sd);
4718 +
4719 +       return error;
4720 +}
4721 +
4722 +static int subdomain_inode_link(struct dentry *old_dentry, struct inode *inode,
4723 +                               struct dentry *new_dentry)
4724 +{
4725 +       int error = 0;
4726 +       struct subdomain sdcopy, *sd;
4727 +
4728 +       if (!current->security)
4729 +               return 0;
4730 +
4731 +       sd = get_sdcopy(&sdcopy);
4732 +       error = sd_link(sd, new_dentry, old_dentry);
4733 +       put_sdcopy(sd);
4734 +
4735 +       return error;
4736 +}
4737 +
4738 +static int subdomain_inode_unlink(struct inode *inode, struct dentry *dentry)
4739 +{
4740 +       struct subdomain sdcopy, *sd;
4741 +       int error;
4742 +
4743 +       if (!current->security)
4744 +               return 0;
4745 +
4746 +       sd = get_sdcopy(&sdcopy);
4747 +
4748 +       error = sd_perm_dentry(sd, dentry, MAY_WRITE);
4749 +
4750 +       put_sdcopy(sd);
4751 +
4752 +       return error;
4753 +}
4754 +
4755 +static int subdomain_inode_mknod(struct inode *inode, struct dentry *dentry,
4756 +                                int mode, dev_t dev)
4757 +{
4758 +       struct subdomain sdcopy, *sd;
4759 +       int error = 0;
4760 +
4761 +       if (!current->security)
4762 +               return 0;
4763 +
4764 +       sd = get_sdcopy(&sdcopy);
4765 +
4766 +       error = sd_perm_dentry(sd, dentry, MAY_WRITE);
4767 +
4768 +       put_sdcopy(sd);
4769 +
4770 +       return error;
4771 +}
4772 +
4773 +static int subdomain_inode_rename(struct inode *old_inode,
4774 +                                 struct dentry *old_dentry,
4775 +                                 struct inode *new_inode,
4776 +                                 struct dentry *new_dentry)
4777 +{
4778 +       struct subdomain sdcopy, *sd;
4779 +       int error = 0;
4780 +
4781 +       if (!current->security)
4782 +               return 0;
4783 +
4784 +       sd = get_sdcopy(&sdcopy);
4785 +
4786 +       error = sd_perm_dentry(sd, old_dentry,
4787 +                              MAY_READ | MAY_WRITE);
4788 +
4789 +       if (!error)
4790 +               error = sd_perm_dentry(sd, new_dentry, MAY_WRITE);
4791 +
4792 +       put_sdcopy(sd);
4793 +
4794 +       return error;
4795 +}
4796 +
4797 +static int subdomain_inode_permission(struct inode *inode, int mask,
4798 +                                     struct nameidata *nd)
4799 +{
4800 +       int error = 0;
4801 +
4802 +       /* Do not perform check on pipes or sockets
4803 +        * Same as subdomain_file_permission
4804 +        */
4805 +       if (current->security && VALID_FSTYPE(inode)) {
4806 +               struct subdomain sdcopy, *sd;
4807 +
4808 +               sd = get_sdcopy(&sdcopy);
4809 +               error = sd_perm_nameidata(sd, nd, mask);
4810 +               put_sdcopy(sd);
4811 +       }
4812 +
4813 +       return error;
4814 +}
4815 +
4816 +static int subdomain_inode_setattr(struct dentry *dentry, struct iattr *iattr)
4817 +{
4818 +       struct subdomain sdcopy, *sd;
4819 +       int error = 0;
4820 +
4821 +       if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4822 +
4823 +               sd = get_sdcopy(&sdcopy);
4824 +
4825 +               /*
4826 +                * Mediate any attempt to change attributes of a file
4827 +                * (chmod, chown, chgrp, etc)
4828 +                */
4829 +               error = sd_attr(sd, dentry, iattr);
4830 +
4831 +               put_sdcopy(sd);
4832 +       }
4833 +
4834 +       return error;
4835 +}
4836 +
4837 +static int subdomain_inode_setxattr(struct dentry *dentry, char *name,
4838 +                                   void *value, size_t size, int flags)
4839 +{
4840 +       int error = 0;
4841 +
4842 +       if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4843 +               struct subdomain sdcopy, *sd;
4844 +
4845 +               sd = get_sdcopy(&sdcopy);
4846 +               error = sd_xattr(sd, dentry, name, SD_XATTR_SET);
4847 +               put_sdcopy(sd);
4848 +       }
4849 +
4850 +       return error;
4851 +}
4852 +
4853 +static int subdomain_inode_getxattr(struct dentry *dentry, char *name)
4854 +{
4855 +       int error = 0;
4856 +
4857 +       if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4858 +               struct subdomain sdcopy, *sd;
4859 +
4860 +               sd = get_sdcopy(&sdcopy);
4861 +               error = sd_xattr(sd, dentry, name, SD_XATTR_GET);
4862 +               put_sdcopy(sd);
4863 +       }
4864 +
4865 +       return error;
4866 +}
4867 +static int subdomain_inode_listxattr(struct dentry *dentry)
4868 +{
4869 +       int error = 0;
4870 +
4871 +       if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4872 +               struct subdomain sdcopy, *sd;
4873 +
4874 +               sd = get_sdcopy(&sdcopy);
4875 +               error = sd_xattr(sd, dentry, NULL, SD_XATTR_LIST);
4876 +               put_sdcopy(sd);
4877 +       }
4878 +
4879 +       return error;
4880 +}
4881 +
4882 +static int subdomain_inode_removexattr(struct dentry *dentry, char *name)
4883 +{
4884 +       int error = 0;
4885 +
4886 +       if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4887 +               struct subdomain sdcopy, *sd;
4888 +
4889 +               sd = get_sdcopy(&sdcopy);
4890 +               error = sd_xattr(sd, dentry, name, SD_XATTR_REMOVE);
4891 +               put_sdcopy(sd);
4892 +       }
4893 +
4894 +       return error;
4895 +}
4896 +
4897 +static int subdomain_file_permission(struct file *file, int mask)
4898 +{
4899 +       struct subdomain sdcopy, *sd;
4900 +       struct sdfile *sdf;
4901 +       int error = 0;
4902 +
4903 +       if (!current->security ||
4904 +           !(sdf = (struct sdfile *)file->f_security) ||
4905 +           !VALID_FSTYPE(file->f_dentry->d_inode))
4906 +               return 0;
4907 +
4908 +       sd = get_sdcopy(&sdcopy);
4909 +
4910 +       if (__sd_is_confined(sd) && sdf->profile != sd->active)
4911 +               error = sd_perm(sd, file->f_dentry, file->f_vfsmnt,
4912 +                               mask & (MAY_EXEC | MAY_WRITE | MAY_READ));
4913 +
4914 +       put_sdcopy(sd);
4915 +
4916 +       return error;
4917 +}
4918 +
4919 +static int subdomain_file_alloc_security(struct file *file)
4920 +{
4921 +       struct subdomain sdcopy, *sd;
4922 +       int error = 0;
4923 +
4924 +       if (!current->security)
4925 +               return 0;
4926 +
4927 +       sd = get_sdcopy(&sdcopy);
4928 +
4929 +       if (__sd_is_confined(sd)) {
4930 +               struct sdfile *sdf;
4931 +
4932 +               sdf = kmalloc(sizeof(struct sdfile), GFP_KERNEL);
4933 +
4934 +               if (sdf) {
4935 +                       sdf->type = sd_file_default;
4936 +                       sdf->profile = get_sdprofile(sd->active);
4937 +               } else {
4938 +                       error = -ENOMEM;
4939 +               }
4940 +
4941 +               file->f_security = sdf;
4942 +       }
4943 +
4944 +       put_sdcopy(sd);
4945 +
4946 +       return error;
4947 +}
4948 +
4949 +static void subdomain_file_free_security(struct file *file)
4950 +{
4951 +       struct sdfile *sdf = (struct sdfile *)file->f_security;
4952 +
4953 +       if (sdf) {
4954 +               put_sdprofile(sdf->profile);
4955 +               kfree(sdf);
4956 +       }
4957 +}
4958 +
4959 +static inline int sd_mmap(struct file *file, unsigned long prot,
4960 +                                unsigned long flags)
4961 +{
4962 +       int error = 0, mask = 0;
4963 +       struct subdomain sdcopy, *sd;
4964 +       struct sdfile *sdf;
4965 +
4966 +       if (!current->security || !file ||
4967 +           !(sdf = (struct sdfile *)file->f_security) ||
4968 +           sdf->type == sd_file_shmem)
4969 +               return 0;
4970 +
4971 +       sd = get_sdcopy(&sdcopy);
4972 +
4973 +       if (prot & PROT_READ)
4974 +               mask |= MAY_READ;
4975 +
4976 +       /* Private mappings don't require write perms since they don't
4977 +        * write back to the files */
4978 +       if (prot & PROT_WRITE && !(flags & MAP_PRIVATE))
4979 +               mask |= MAY_WRITE;
4980 +
4981 +       if (prot & PROT_EXEC)
4982 +               mask |= SD_EXEC_MMAP;
4983 +
4984 +       SD_DEBUG("%s: 0x%x\n", __FUNCTION__, mask);
4985 +
4986 +       if (mask)
4987 +               error = sd_perm(sd, file->f_dentry, file->f_vfsmnt, mask);
4988 +
4989 +       put_sdcopy(sd);
4990 +
4991 +       return error;
4992 +}
4993 +
4994 +static int subdomain_file_mmap(struct file *file, unsigned long reqprot,
4995 +                              unsigned long prot, unsigned long flags)
4996 +{
4997 +       return sd_mmap(file, prot, flags);
4998 +}
4999 +
5000 +static int subdomain_file_mprotect(struct vm_area_struct* vma,
5001 +                                  unsigned long reqprot, unsigned long prot)
5002 +{
5003 +       return sd_mmap(vma->vm_file, prot,
5004 +               !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
5005 +}
5006 +
5007 +static int subdomain_task_alloc_security(struct task_struct *p)
5008 +{
5009 +       return sd_fork(p);
5010 +}
5011 +
5012 +static void subdomain_task_free_security(struct task_struct *p)
5013 +{
5014 +       if (p->security)
5015 +               sd_release(p);
5016 +}
5017 +
5018 +static int subdomain_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
5019 +                                     int flags)
5020 +{
5021 +       return cap_task_post_setuid(id0, id1, id2, flags);
5022 +}
5023 +
5024 +static void subdomain_task_reparent_to_init(struct task_struct *p)
5025 +{
5026 +       cap_task_reparent_to_init(p);
5027 +       return;
5028 +}
5029 +
5030 +static int subdomain_shm_shmat(struct shmid_kernel* shp, char __user *shmaddr,
5031 +                              int shmflg)
5032 +{
5033 +       struct sdfile *sdf = (struct sdfile *)shp->shm_file->f_security;
5034 +
5035 +       if (sdf)
5036 +               sdf->type = sd_file_shmem;
5037 +
5038 +       return 0;
5039 +}
5040 +
5041 +static int subdomain_getprocattr(struct task_struct *p, char *name, void *value,
5042 +                                size_t size)
5043 +{
5044 +       int error;
5045 +       struct subdomain sdcopy, *sd;
5046 +       char *str = value;
5047 +       unsigned long flags;
5048 +
5049 +       /* Subdomain only supports the "current" process attribute */
5050 +       if (strcmp(name, "current") != 0) {
5051 +               error = -EINVAL;
5052 +               goto out;
5053 +       }
5054 +
5055 +       if (!size) {
5056 +               error = -ERANGE;
5057 +               goto out;
5058 +       }
5059 +
5060 +       /* must be task querying itself or admin */
5061 +       if (current != p && !capable(CAP_SYS_ADMIN)) {
5062 +               error = -EPERM;
5063 +               goto out;
5064 +       }
5065 +
5066 +       read_lock_irqsave(&sd_lock, flags);
5067 +
5068 +       sd = __get_sdcopy(&sdcopy, p);
5069 +
5070 +       read_unlock_irqrestore(&sd_lock, flags);
5071 +
5072 +       error = sd_getprocattr(sd, str, size);
5073 +       put_sdcopy(sd);
5074 +
5075 +out:
5076 +       return error;
5077 +}
5078 +
5079 +static int subdomain_setprocattr(struct task_struct *p, char *name, void *value,
5080 +                                size_t size)
5081 +{
5082 +       const char *cmd_changehat = "changehat ",
5083 +                  *cmd_setprofile = "setprofile ";
5084 +
5085 +       int error = -EACCES;    /* default to a perm denied */
5086 +       char *cmd = (char *)value;
5087 +
5088 +       /* only support messages to current */
5089 +       if (strcmp(name, "current") != 0) {
5090 +               error = -EINVAL;
5091 +               goto out;
5092 +       }
5093 +
5094 +       if (!size) {
5095 +               error = -ERANGE;
5096 +               goto out;
5097 +       }
5098 +
5099 +       /* CHANGE HAT */
5100 +       if (size > strlen(cmd_changehat) &&
5101 +           strncmp(cmd, cmd_changehat, strlen(cmd_changehat)) == 0) {
5102 +               char *hatinfo = cmd + strlen(cmd_changehat);
5103 +               size_t infosize = size - strlen(cmd_changehat);
5104 +
5105 +               /* Only the current process may change it's hat */
5106 +               if (current != p) {
5107 +                       SD_WARN("%s: Attempt by foreign task %s(%d) "
5108 +                               "[user %d] to changehat of task %s(%d)\n",
5109 +                               __FUNCTION__,
5110 +                               current->comm,
5111 +                               current->pid,
5112 +                               current->uid,
5113 +                               p->comm,
5114 +                               p->pid);
5115 +
5116 +                       error = -EACCES;
5117 +                       goto out;
5118 +               }
5119 +
5120 +               error = sd_setprocattr_changehat(hatinfo, infosize);
5121 +               if (error == 0)
5122 +                       /* success, set return to #bytes in orig request */
5123 +                       error = size;
5124 +
5125 +       /* SET NEW PROFILE */
5126 +       } else if (size > strlen(cmd_setprofile) &&
5127 +                  strncmp(cmd, cmd_setprofile, strlen(cmd_setprofile)) == 0) {
5128 +               int confined;
5129 +               unsigned long flags;
5130 +
5131 +               /* only an unconfined process with admin capabilities
5132 +                * may change the profile of another task
5133 +                */
5134 +
5135 +               if (!capable(CAP_SYS_ADMIN)) {
5136 +                       SD_WARN("%s: Unprivileged attempt by task %s(%d) "
5137 +                               "[user %d] to assign profile to task %s(%d)\n",
5138 +                               __FUNCTION__,
5139 +                               current->comm,
5140 +                               current->pid,
5141 +                               current->uid,
5142 +                               p->comm,
5143 +                               p->pid);
5144 +                       error = -EACCES;
5145 +                       goto out;
5146 +               }
5147 +
5148 +               read_lock_irqsave(&sd_lock, flags);
5149 +               confined = sd_is_confined();
5150 +               read_unlock_irqrestore(&sd_lock, flags);
5151 +
5152 +               if (!confined) {
5153 +                       char *profile = cmd + strlen(cmd_setprofile);
5154 +                       size_t profilesize = size - strlen(cmd_setprofile);
5155 +
5156 +                       error = sd_setprocattr_setprofile(p, profile, profilesize);
5157 +                       if (error == 0)
5158 +                               /* success,
5159 +                                * set return to #bytes in orig request
5160 +                                */
5161 +                               error = size;
5162 +               } else {
5163 +                       SD_WARN("%s: Attempt by confined task %s(%d) "
5164 +                               "[user %d] to assign profile to task %s(%d)\n",
5165 +                               __FUNCTION__,
5166 +                               current->comm,
5167 +                               current->pid,
5168 +                               current->uid,
5169 +                               p->comm,
5170 +                               p->pid);
5171 +
5172 +                       error = -EACCES;
5173 +               }
5174 +       } else {
5175 +               /* unknown operation */
5176 +               SD_WARN("%s: Unknown setprocattr command '%.*s' by task %s(%d) "
5177 +                       "[user %d] for task %s(%d)\n",
5178 +                       __FUNCTION__,
5179 +                       size < 16 ? (int)size : 16,
5180 +                       cmd,
5181 +                       current->comm,
5182 +                       current->pid,
5183 +                       current->uid,
5184 +                       p->comm,
5185 +                       p->pid);
5186 +
5187 +               error = -EINVAL;
5188 +       }
5189 +
5190 +out:
5191 +       return error;
5192 +}
5193 +
5194 +struct security_operations subdomain_ops = {
5195 +       .ptrace =                       subdomain_ptrace,
5196 +       .capget =                       subdomain_capget,
5197 +       .capset_check =                 subdomain_capset_check,
5198 +       .capset_set =                   subdomain_capset_set,
5199 +       .sysctl =                       subdomain_sysctl,
5200 +       .capable =                      subdomain_capable,
5201 +       .syslog =                       subdomain_syslog,
5202 +
5203 +       .netlink_send =                 subdomain_netlink_send,
5204 +       .netlink_recv =                 subdomain_netlink_recv,
5205 +
5206 +       .bprm_apply_creds =             subdomain_bprm_apply_creds,
5207 +       .bprm_set_security =            subdomain_bprm_set_security,
5208 +       .bprm_secureexec =              subdomain_bprm_secureexec,
5209 +
5210 +       .sb_mount =                     subdomain_sb_mount,
5211 +       .sb_umount =                    subdomain_umount,
5212 +
5213 +       .inode_mkdir =                  subdomain_inode_mkdir,
5214 +       .inode_rmdir =                  subdomain_inode_rmdir,
5215 +       .inode_create =                 subdomain_inode_create,
5216 +       .inode_link =                   subdomain_inode_link,
5217 +       .inode_unlink =                 subdomain_inode_unlink,
5218 +       .inode_mknod =                  subdomain_inode_mknod,
5219 +       .inode_rename =                 subdomain_inode_rename,
5220 +       .inode_permission =             subdomain_inode_permission,
5221 +       .inode_setattr =                subdomain_inode_setattr,
5222 +       .inode_setxattr =               subdomain_inode_setxattr,
5223 +       .inode_getxattr =               subdomain_inode_getxattr,
5224 +       .inode_listxattr =              subdomain_inode_listxattr,
5225 +       .inode_removexattr =            subdomain_inode_removexattr,
5226 +       .file_permission =              subdomain_file_permission,
5227 +       .file_alloc_security =          subdomain_file_alloc_security,
5228 +       .file_free_security =           subdomain_file_free_security,
5229 +       .file_mmap =                    subdomain_file_mmap,
5230 +       .file_mprotect =                subdomain_file_mprotect,
5231 +
5232 +       .task_alloc_security =          subdomain_task_alloc_security,
5233 +       .task_free_security =           subdomain_task_free_security,
5234 +       .task_post_setuid =             subdomain_task_post_setuid,
5235 +       .task_reparent_to_init =        subdomain_task_reparent_to_init,
5236 +
5237 +       .shm_shmat =                    subdomain_shm_shmat,
5238 +
5239 +       .getprocattr =                  subdomain_getprocattr,
5240 +       .setprocattr =                  subdomain_setprocattr,
5241 +};
5242 +
5243 +static int __init subdomain_init(void)
5244 +{
5245 +       int error = 0;
5246 +       const char *complainmsg = ": complainmode enabled";
5247 +
5248 +       if (!create_subdomainfs()) {
5249 +               SD_ERROR("Unable to activate AppArmor filesystem\n");
5250 +               error = -ENOENT;
5251 +               goto createfs_out;
5252 +       }
5253 +
5254 +       if (!alloc_nullprofiles()){
5255 +               SD_ERROR("Unable to allocate null profiles\n");
5256 +               error = -ENOMEM;
5257 +               goto alloc_out;
5258 +       }
5259 +
5260 +       if ((error = register_security(&subdomain_ops))) {
5261 +               SD_WARN("Unable to load AppArmor\n");
5262 +               goto register_security_out;
5263 +       }
5264 +
5265 +       SD_INFO("AppArmor (version %s) initialized%s\n",
5266 +               apparmor_version(),
5267 +               subdomain_complain ? complainmsg : "");
5268 +       sd_audit_message(NULL, GFP_KERNEL, 0,
5269 +               "AppArmor (version %s) initialized%s\n",
5270 +               apparmor_version(),
5271 +               subdomain_complain ? complainmsg : "");
5272 +
5273 +       return error;
5274 +
5275 +register_security_out:
5276 +       free_nullprofiles();
5277 +
5278 +alloc_out:
5279 +       (void)destroy_subdomainfs();
5280 +
5281 +createfs_out:
5282 +       return error;
5283 +
5284 +}
5285 +
5286 +static int subdomain_exit_removeall_iter(struct subdomain *sd, void *cookie)
5287 +{
5288 +       /* write_lock(&sd_lock) held here */
5289 +
5290 +       if (__sd_is_confined(sd)) {
5291 +               SD_DEBUG("%s: Dropping profiles %s(%d) "
5292 +                        "profile %s(%p) active %s(%p)\n",
5293 +                        __FUNCTION__,
5294 +                        sd->task->comm, sd->task->pid,
5295 +                        sd->profile->name, sd->profile,
5296 +                        sd->active->name, sd->active);
5297 +               sd_switch_unconfined(sd);
5298 +       }
5299 +
5300 +       return 0;
5301 +}
5302 +
5303 +static void __exit subdomain_exit(void)
5304 +{
5305 +       unsigned long flags;
5306 +
5307 +       /* Remove profiles from the global profile list.
5308 +        * This is just for tidyness as there is no way to reference this
5309 +        * list once the AppArmor lsm hooks are detached (below)
5310 +        */
5311 +       sd_profilelist_release();
5312 +
5313 +       /* Remove profiles from active tasks
5314 +        * If this is not done,  if module is reloaded after being removed,
5315 +        * old profiles (still refcounted in memory) will become 'magically'
5316 +        * reattached
5317 +        */
5318 +
5319 +       write_lock_irqsave(&sd_lock, flags);
5320 +       sd_subdomainlist_iterate(subdomain_exit_removeall_iter, NULL);
5321 +       write_unlock_irqrestore(&sd_lock, flags);
5322 +
5323 +       /* Free up list of active subdomain */
5324 +       sd_subdomainlist_release();
5325 +
5326 +       free_nullprofiles();
5327 +
5328 +       if (!destroy_subdomainfs())
5329 +               SD_WARN("Unable to properly deactivate AppArmor fs\n");
5330 +
5331 +       if (unregister_security(&subdomain_ops))
5332 +               SD_WARN("Unable to properly unregister AppArmor\n");
5333 +
5334 +       SD_INFO("AppArmor protection removed\n");
5335 +       sd_audit_message(NULL, GFP_KERNEL, 0,
5336 +               "AppArmor protection removed\n");
5337 +}
5338 +
5339 +module_init(subdomain_init);
5340 +module_exit(subdomain_exit);
5341 +
5342 +MODULE_DESCRIPTION("AppArmor process confinement");
5343 +MODULE_AUTHOR("Tony Jones <tonyj@suse.de>");
5344 +MODULE_LICENSE("GPL");
5345 --- linux-2.6.16.29.orig/security/apparmor/main.c       1969-12-31 16:00:00.000000000 -0800
5346 +++ linux-2.6.16.29/security/apparmor/main.c    2006-10-12 21:11:15.000000000 -0700
5347 @@ -0,0 +1,1691 @@
5348 +/*
5349 + *     Copyright (C) 2002-2005 Novell/SUSE
5350 + *
5351 + *     This program is free software; you can redistribute it and/or
5352 + *     modify it under the terms of the GNU General Public License as
5353 + *     published by the Free Software Foundation, version 2 of the
5354 + *     License.
5355 + *
5356 + *     AppArmor Core
5357 + */
5358 +
5359 +#include <linux/security.h>
5360 +#include <linux/namei.h>
5361 +#include <linux/audit.h>
5362 +
5363 +#include "apparmor.h"
5364 +#include "aamatch/match.h"
5365 +
5366 +#include "inline.h"
5367 +
5368 +/* NULL profile
5369 + *
5370 + * Used when an attempt is made to changehat into a non-existant
5371 + * subhat.   In the NULL profile,  no file access is allowed
5372 + * (currently full network access is allowed).  Using a NULL
5373 + * profile ensures that active is always non zero.
5374 + *
5375 + * Leaving the NULL profile is by either successfully changehatting
5376 + * into a sibling hat, or changehatting back to the parent (NULL hat).
5377 + */
5378 +struct sdprofile *null_profile;
5379 +
5380 +/* NULL complain profile
5381 + *
5382 + * Used when in complain mode, to emit Permitting messages for non-existant
5383 + * profiles and hats.  This is necessary because of selective mode, in which
5384 + * case we need a complain null_profile and enforce null_profile
5385 + *
5386 + * The null_complain_profile cannot be statically allocated, because it
5387 + * can be associated to files which keep their reference even if subdomain is
5388 + * unloaded
5389 + */
5390 +struct sdprofile *null_complain_profile;
5391 +
5392 +/***************************
5393 + * PRIVATE UTILITY FUNCTIONS
5394 + **************************/
5395 +
5396 +/**
5397 + * dentry_xlate_error
5398 + * @dentry: pointer to dentry
5399 + * @error: error number
5400 + * @dtype: type of dentry
5401 + *
5402 + * Display error message when a dentry translation error occured
5403 + */
5404 +static void dentry_xlate_error(struct dentry *dentry, int error, char *dtype)
5405 +{
5406 +       const unsigned int len = 16;
5407 +       char buf[len];
5408 +
5409 +       if (dentry->d_inode) {
5410 +               snprintf(buf, len, "%lu", dentry->d_inode->i_ino);
5411 +       } else {
5412 +               strncpy(buf, "<negative>", len);
5413 +               buf[len-1]=0;
5414 +       }
5415 +
5416 +       SD_ERROR("An error occured while translating %s %p "
5417 +                "inode# %s to a pathname. Error %d\n",
5418 +                dtype,
5419 +                dentry,
5420 +                buf,
5421 +                error);
5422 +}
5423 +
5424 +/**
5425 + * sd_taskattr_access:
5426 + * @name: name of file to check permission
5427 + * @mask: permission mask requested for file
5428 + *
5429 + * Determine if request is for write access to /proc/self/attr/current
5430 + */
5431 +static inline int sd_taskattr_access(const char *procrelname)
5432 +{
5433 +/*
5434 + * assumes a 32bit pid, which requires max 10 decimal digits to represent
5435 + * sizeof includes trailing \0
5436 + */
5437 +       char buf[sizeof("/attr/current") + 10];
5438 +       const int maxbuflen = sizeof(buf);
5439 +
5440 +       snprintf(buf, maxbuflen, "%d/attr/current", current->pid);
5441 +       buf[maxbuflen - 1] = 0;
5442 +
5443 +       return strcmp(buf, procrelname) == 0;
5444 +}
5445 +
5446 +/**
5447 + * sd_file_mode - get full mode for file entry from profile
5448 + * @profile: profile
5449 + * @name: filename
5450 + */
5451 +static inline int sd_file_mode(struct sdprofile *profile, const char *name)
5452 +{
5453 +       struct sd_entry *entry;
5454 +       int mode = 0;
5455 +
5456 +       SD_DEBUG("%s: %s\n", __FUNCTION__, name);
5457 +       if (!name) {
5458 +               SD_DEBUG("%s: no name\n", __FUNCTION__);
5459 +               goto out;
5460 +       }
5461 +
5462 +       if (!profile) {
5463 +               SD_DEBUG("%s: no profile\n", __FUNCTION__);
5464 +               goto out;
5465 +       }
5466 +       list_for_each_entry(entry, &profile->file_entry, list) {
5467 +               if (sdmatch_match(name, entry->filename,
5468 +                                 entry->entry_type, entry->extradata))
5469 +                       mode |= entry->mode;
5470 +       }
5471 +out:
5472 +       return mode;
5473 +}
5474 +
5475 +/**
5476 + * sd_get_execmode - calculate what qualifier to apply to an exec
5477 + * @sd: subdomain to search
5478 + * @name: name of file to exec
5479 + * @xmod: pointer to a execution mode bit for the rule that was matched
5480 + *         if the rule has no execuition qualifier {pui} then
5481 + *         SD_MAY_EXEC is returned indicating a naked x
5482 + *         if the has an exec qualifier then only the qualifier bit {pui}
5483 + *         is returned (SD_MAY_EXEC) is not set.
5484 + * @unsafe: true if secure_exec should be overridden
5485 + *
5486 + * Returns 0 (false):
5487 + *    if unable to find profile or there are conflicting pattern matches.
5488 + *       *xmod - is not modified
5489 + *       *unsafe - is not modified
5490 + *
5491 + * Returns 1 (true):
5492 + *    if not confined
5493 + *       *xmod = SD_MAY_EXEC
5494 + *       *unsafe = 0
5495 + *    if exec rule matched
5496 + *       if the rule has an execution mode qualifier {pui} then
5497 + *          *xmod = the execution qualifier of the rule {pui}
5498 + *       else
5499 + *          *xmod = SD_MAY_EXEC
5500 + *       unsafe = presence of unsafe flag
5501 + */
5502 +static inline int sd_get_execmode(struct subdomain *sd, const char *name,
5503 +                                 int *xmod, int *unsafe)
5504 +{
5505 +       struct sdprofile *profile;
5506 +       struct sd_entry *entry;
5507 +       struct sd_entry *match = NULL;
5508 +
5509 +       int pattern_match_invalid = 0, rc = 0;
5510 +
5511 +       /* not confined */
5512 +       if (!__sd_is_confined(sd)) {
5513 +               SD_DEBUG("%s: not confined\n", __FUNCTION__);
5514 +               goto not_confined;
5515 +       }
5516 +
5517 +       profile = sd->active;
5518 +
5519 +       /* search list of profiles with 'x' permission
5520 +        * this will also include entries with 'p', 'u' and 'i'
5521 +        * qualifiers.
5522 +        *
5523 +        * If we find a pattern match we will keep looking for an exact match
5524 +        * If we find conflicting pattern matches we will flag (while still
5525 +        * looking for an exact match).  If all we have is a conflict, FALSE
5526 +        * is returned.
5527 +        */
5528 +
5529 +       list_for_each_entry(entry, &profile->file_entryp[POS_SD_MAY_EXEC],
5530 +                           listp[POS_SD_MAY_EXEC]) {
5531 +               if (!pattern_match_invalid &&
5532 +                   entry->entry_type == sd_entry_pattern &&
5533 +                   sdmatch_match(name, entry->filename,
5534 +                                 entry->entry_type, entry->extradata)) {
5535 +                       if (match &&
5536 +                           SD_EXEC_UNSAFE_MASK(entry->mode) !=
5537 +                           SD_EXEC_UNSAFE_MASK(match->mode))
5538 +                               pattern_match_invalid = 1;
5539 +                       else
5540 +                               /* keep searching for an exact match */
5541 +                               match = entry;
5542 +               } else if ((entry->entry_type == sd_entry_literal ||
5543 +                           (!pattern_match_invalid &&
5544 +                            entry->entry_type == sd_entry_tailglob)) &&
5545 +                           sdmatch_match(name, entry->filename,
5546 +                                         entry->entry_type,
5547 +                                         entry->extradata)) {
5548 +                       if (entry->entry_type == sd_entry_literal) {
5549 +                               /* got an exact match -- there can be only
5550 +                                * one, asserted at profile load time
5551 +                                */
5552 +                               match = entry;
5553 +                               pattern_match_invalid = 0;
5554 +                               break;
5555 +                       } else {
5556 +                               if (match &&
5557 +                                   SD_EXEC_UNSAFE_MASK(entry->mode) !=
5558 +                                   SD_EXEC_UNSAFE_MASK(match->mode))
5559 +                                       pattern_match_invalid = 1;
5560 +                               else
5561 +                                       /* got a tailglob match, keep searching
5562 +                                        * for an exact match
5563 +                                        */
5564 +                                       match = entry;
5565 +                       }
5566 +               }
5567 +
5568 +       }
5569 +
5570 +       rc = match && !pattern_match_invalid;
5571 +
5572 +       if (rc) {
5573 +               int mode = SD_EXEC_MASK(match->mode);
5574 +
5575 +               /* check for qualifiers, if present
5576 +                * we just return the qualifier
5577 +                */
5578 +               if (mode & ~SD_MAY_EXEC)
5579 +                       mode = mode & ~SD_MAY_EXEC;
5580 +
5581 +               *xmod = mode;
5582 +               *unsafe = (match->mode & SD_EXEC_UNSAFE);
5583 +       } else if (!match) {
5584 +               SD_DEBUG("%s: Unable to find execute entry in profile "
5585 +                        "for image '%s'\n",
5586 +                        __FUNCTION__,
5587 +                        name);
5588 +       } else if (pattern_match_invalid) {
5589 +               SD_WARN("%s: Inconsistency in profile %s. "
5590 +                       "Two (or more) patterns specify conflicting exec "
5591 +                       "qualifiers ('u', 'i' or 'p') for image %s\n",
5592 +                       __FUNCTION__,
5593 +                       sd->active->name,
5594 +                       name);
5595 +       }
5596 +
5597 +       return rc;
5598 +
5599 +not_confined:
5600 +       *xmod = SD_MAY_EXEC;
5601 +       *unsafe = 0;
5602 +       return 1;
5603 +}
5604 +
5605 +/**
5606 + * sd_filter_mask
5607 + * @mask: requested mask
5608 + * @inode: potential directory inode
5609 + *
5610 + * This fn performs pre-verification of the requested mask
5611 + * We ignore append. Previously we required 'w' on a dir to add a file.
5612 + * No longer. Now we require 'w' on just the file itself. Traversal 'x' is
5613 + * also ignored for directories.
5614 + *
5615 + * Returned value of 0 indicates no need to perform a perm check.
5616 + */
5617 +static inline int sd_filter_mask(int mask, struct inode *inode)
5618 +{
5619 +       if (mask) {
5620 +               int elim = MAY_APPEND;
5621 +
5622 +               if (inode && S_ISDIR(inode->i_mode))
5623 +                       elim |= (MAY_EXEC | MAY_WRITE);
5624 +
5625 +               mask &= ~elim;
5626 +       }
5627 +
5628 +       return mask;
5629 +}
5630 +
5631 +static inline void sd_permerror2result(int perm_result, struct sd_audit *sa)
5632 +{
5633 +       if (perm_result == 0) { /* success */
5634 +               sa->result = 1;
5635 +               sa->errorcode = 0;
5636 +       } else { /* -ve internal error code or +ve mask of denied perms */
5637 +               sa->result = 0;
5638 +               sa->errorcode = perm_result;
5639 +       }
5640 +}
5641 +
5642 +/*************************
5643 + * MAIN INTERNAL FUNCTIONS
5644 + ************************/
5645 +
5646 +/**
5647 + * sd_file_perm - calculate access mode for file
5648 + * @subdomain: current subdomain
5649 + * @name: name of file to calculate mode for
5650 + * @mask: permission mask requested for file
5651 + *
5652 + * Search the sd_entry list in @profile.
5653 + * Search looking to verify all permissions passed in mask.
5654 + * Perform the search by looking at the partitioned list of entries, one
5655 + * partition per permission bit.
5656 + *
5657 + * Return 0 on success, else mask of non-allowed permissions
5658 + */
5659 +static unsigned int sd_file_perm(struct subdomain *sd, const char *name,
5660 +                                int mask)
5661 +{
5662 +       struct sdprofile *profile;
5663 +       int i, error = 0, mode;
5664 +
5665 +#define PROCPFX "/proc/"
5666 +#define PROCLEN sizeof(PROCPFX) - 1
5667 +
5668 +       SD_DEBUG("%s: %s 0x%x\n", __FUNCTION__, name, mask);
5669 +
5670 +       /* should not enter with other than R/W/M/X/L */
5671 +       BUG_ON(mask &
5672 +              ~(SD_MAY_READ | SD_MAY_WRITE | SD_MAY_EXEC |
5673 +                SD_EXEC_MMAP | SD_MAY_LINK));
5674 +
5675 +       /* not confined */
5676 +       if (!__sd_is_confined(sd)) {
5677 +               /* exit with access allowed */
5678 +               SD_DEBUG("%s: not confined\n", __FUNCTION__);
5679 +               goto done;
5680 +       }
5681 +
5682 +       /* Special case access to /proc/self/attr/current
5683 +        * Currently we only allow access if opened O_WRONLY
5684 +        */
5685 +       if (mask == MAY_WRITE && strncmp(PROCPFX, name, PROCLEN) == 0 &&
5686 +           (!list_empty(&sd->profile->sub) || SUBDOMAIN_COMPLAIN(sd)) &&
5687 +           sd_taskattr_access(name + PROCLEN))
5688 +               goto done;
5689 +
5690 +       profile = sd->active;
5691 +
5692 +       mode = 0;
5693 +
5694 +       /* iterate over partition, one permission bit at a time */
5695 +       for (i = 0; i <= POS_SD_FILE_MAX; i++) {
5696 +               struct sd_entry *entry;
5697 +
5698 +               /* do we have to accumulate this bit?
5699 +                * or have we already accumulated it (shortcut below)? */
5700 +               if (!(mask & (1 << i)) || mode & (1 << i))
5701 +                       continue;
5702 +
5703 +               list_for_each_entry(entry, &profile->file_entryp[i],
5704 +                                   listp[i]) {
5705 +                       if (sdmatch_match(name, entry->filename,
5706 +                               entry->entry_type, entry->extradata)) {
5707 +                               /* Shortcut, accumulate all bits present */
5708 +                               mode |= entry->mode;
5709 +
5710 +                               /*
5711 +                                * Mask bits are overloaded
5712 +                                * MAY_{EXEC,WRITE,READ,APPEND} are used by
5713 +                                * kernel, other values are used locally only.
5714 +                                */
5715 +                               if ((mode & mask) == mask) {
5716 +                                       SD_DEBUG("MATCH! %s=0x%x [total mode=0x%x]\n",
5717 +                                                name, mask, mode);
5718 +
5719 +                                       goto done;
5720 +                               }
5721 +                       }
5722 +               }
5723 +       }
5724 +
5725 +       /* return permissions not satisfied */
5726 +       error = mask & ~mode;
5727 +
5728 +done:
5729 +       return error;
5730 +}
5731 +
5732 +/**
5733 + * sd_link_perm - test permission to link to a file
5734 + * @sd: current subdomain
5735 + * @link: name of link being created
5736 + * @target: name of target to be linked to
5737 + *
5738 + * Look up permission mode on both @link and @target.  @link must have same
5739 + * permission mode as @target.  At least @link must have the link bit enabled.
5740 + * Return 0 on success, error otherwise.
5741 + */
5742 +static int sd_link_perm(struct subdomain *sd,
5743 +                       const char *link, const char *target)
5744 +{
5745 +       int l_mode, t_mode, ret;
5746 +       struct sdprofile *profile = sd->active;
5747 +
5748 +       l_mode = sd_file_mode(profile, link);
5749 +       if (l_mode & SD_MAY_LINK) {
5750 +               /* mask off link bit */
5751 +               l_mode &= ~SD_MAY_LINK;
5752 +
5753 +               t_mode = sd_file_mode(profile, target);
5754 +               t_mode &= ~SD_MAY_LINK;
5755 +
5756 +               ret = (l_mode == t_mode);
5757 +       } else {
5758 +               ret = 0;
5759 +       }
5760 +
5761 +       return ret;
5762 +}
5763 +
5764 +/**
5765 + * _sd_perm_dentry
5766 + * @sd: current subdomain
5767 + * @dentry: requested dentry
5768 + * @mask: mask of requested operations
5769 + * @pname: pointer to hold matched pathname (if any)
5770 + *
5771 + * Helper function.  Obtain pathname for specified dentry. Verify if profile
5772 + * authorizes mask operations on pathname (due to lack of vfsmnt it is sadly
5773 + * necessary to search mountpoints in namespace -- when nameidata is passed
5774 + * more fully, this code can go away).  If more than one mountpoint matches
5775 + * but none satisfy the profile, only the first pathname (mountpoint) is
5776 + * returned for subsequent logging.
5777 + *
5778 + * Return 0 (success), +ve (mask of permissions not satisfied) or -ve (system
5779 + * error, most likely -ENOMEM).
5780 + */
5781 +static int _sd_perm_dentry(struct subdomain *sd, struct dentry *dentry,
5782 +                          int mask, const char **pname)
5783 +{
5784 +       char *name = NULL, *failed_name = NULL;
5785 +       struct sd_path_data data;
5786 +       int error = 0, failed_error = 0, sdpath_error,
5787 +           sdcomplain = SUBDOMAIN_COMPLAIN(sd);
5788 +
5789 +       /* search all paths to dentry */
5790 +
5791 +       sd_path_begin(dentry, &data);
5792 +       do {
5793 +               name = sd_path_getname(&data);
5794 +               if (name) {
5795 +                       /* error here is 0 (success) or +ve (mask of perms) */
5796 +                       error = sd_file_perm(sd, name, mask);
5797 +
5798 +                       /* access via any path is enough */
5799 +                       if (sdcomplain || error == 0)
5800 +                               break; /* Caller must free name */
5801 +
5802 +                       /* Already have an path that failed? */
5803 +                       if (failed_name) {
5804 +                               sd_put_name(name);
5805 +                       } else {
5806 +                               failed_name = name;
5807 +                               failed_error = error;
5808 +                       }
5809 +               }
5810 +       } while (name);
5811 +
5812 +       if ((sdpath_error = sd_path_end(&data)) != 0) {
5813 +               dentry_xlate_error(dentry, sdpath_error, "dentry");
5814 +
5815 +               WARN_ON(name);  /* name should not be set if error */
5816 +               error = sdpath_error;
5817 +               name = NULL;
5818 +       } else if (name) {
5819 +               if (failed_name)
5820 +                       sd_put_name(failed_name);
5821 +       } else {
5822 +               name = failed_name;
5823 +               error = failed_error;
5824 +       }
5825 +
5826 +       *pname = name;
5827 +
5828 +       return error;
5829 +}
5830 +
5831 +/**************************
5832 + * GLOBAL UTILITY FUNCTIONS
5833 + *************************/
5834 +
5835 +/**
5836 + * alloc_nullprofiles - Allocate null profiles
5837 + */
5838 +int alloc_nullprofiles(void)
5839 +{
5840 +       null_profile = alloc_sdprofile();
5841 +       null_complain_profile = alloc_sdprofile();
5842 +
5843 +       if (!null_profile || !null_complain_profile)
5844 +               goto fail;
5845 +
5846 +       null_profile->name = kstrdup("null-profile", GFP_KERNEL);
5847 +       null_complain_profile->name =
5848 +               kstrdup("null-complain-profile", GFP_KERNEL);
5849 +
5850 +       if (!null_profile->name ||
5851 +           !null_complain_profile->name)
5852 +               goto fail;
5853 +
5854 +       get_sdprofile(null_profile);
5855 +       get_sdprofile(null_complain_profile);
5856 +       null_complain_profile->flags.complain = 1;
5857 +
5858 +       return 1;
5859 +
5860 +fail:
5861 +       /* free_sdprofile is safe for freeing partially constructed objects */
5862 +       free_sdprofile(null_profile);
5863 +       free_sdprofile(null_complain_profile);
5864 +       null_profile = null_complain_profile = NULL;
5865 +       return 0;
5866 +}
5867 +
5868 +/**
5869 + * free_nullprofiles - Free null profiles
5870 + */
5871 +void free_nullprofiles(void)
5872 +{
5873 +       put_sdprofile(null_complain_profile);
5874 +       put_sdprofile(null_profile);
5875 +       null_profile = null_complain_profile = NULL;
5876 +}
5877 +
5878 +/**
5879 + * sd_audit_message - Log a message to the audit subsystem
5880 + * @sd: current subdomain
5881 + * @gfp: allocation flags
5882 + * @flags: audit flags
5883 + * @fmt: varargs fmt
5884 + */
5885 +int sd_audit_message(struct subdomain *sd, unsigned int gfp, int flags,
5886 +                    const char *fmt, ...)
5887 +{
5888 +       int ret;
5889 +       struct sd_audit sa;
5890 +
5891 +       sa.type = SD_AUDITTYPE_MSG;
5892 +       sa.name = fmt;
5893 +       va_start(sa.vaval, fmt);
5894 +       sa.flags = flags;
5895 +       sa.gfp_mask = gfp;
5896 +       sa.errorcode = 0;
5897 +       sa.result = 0;  /* fake failure: force message to be logged */
5898 +
5899 +       ret = sd_audit(sd, &sa);
5900 +
5901 +       va_end(sa.vaval);
5902 +
5903 +       return ret;
5904 +}
5905 +
5906 +/**
5907 + * sd_audit_syscallreject - Log a syscall rejection to the audit subsystem
5908 + * @sd: current subdomain
5909 + * @msg: string describing syscall being rejected
5910 + * @gfp: memory allocation flags
5911 + */
5912 +int sd_audit_syscallreject(struct subdomain *sd, unsigned int gfp,
5913 +                          const char *msg)
5914 +{
5915 +       struct sd_audit sa;
5916 +
5917 +       sa.type = SD_AUDITTYPE_SYSCALL;
5918 +       sa.name = msg;
5919 +       sa.flags = 0;
5920 +       sa.gfp_mask = gfp;
5921 +       sa.errorcode = 0;
5922 +       sa.result = 0; /* failure */
5923 +
5924 +       return sd_audit(sd, &sa);
5925 +}
5926 +
5927 +/**
5928 + * sd_audit - Log an audit event to the audit subsystem
5929 + * @sd: current subdomain
5930 + * @sa: audit event
5931 + */
5932 +int sd_audit(struct subdomain *sd, const struct sd_audit *sa)
5933 +{
5934 +       struct audit_buffer *ab = NULL;
5935 +       struct audit_context *ctx;
5936 +
5937 +       const char *logcls;
5938 +       unsigned int flags;
5939 +       int sdaudit = 0,
5940 +           sdcomplain = 0,
5941 +           error = -EINVAL,
5942 +           opspec_error = -EACCES;
5943 +
5944 +       const unsigned int gfp_mask = sa->gfp_mask;
5945 +
5946 +       WARN_ON(sa->type >= SD_AUDITTYPE__END);
5947 +
5948 +       /*
5949 +        * sa->result:    1 success, 0 failure
5950 +        * sa->errorcode: success: 0
5951 +        *                failure: +ve mask of failed permissions or -ve
5952 +        *                system error
5953 +        */
5954 +
5955 +       if (likely(sa->result)) {
5956 +               if (likely(!SUBDOMAIN_AUDIT(sd))) {
5957 +                       /* nothing to log */
5958 +                       error = 0;
5959 +                       goto out;
5960 +               } else {
5961 +                       sdaudit = 1;
5962 +                       logcls = "AUDITING";
5963 +               }
5964 +       } else if (sa->errorcode < 0) {
5965 +               audit_log(current->audit_context, gfp_mask, AUDIT_SD,
5966 +                       "Internal error auditing event type %d (error %d)",
5967 +                       sa->type, sa->errorcode);
5968 +               SD_ERROR("Internal error auditing event type %d (error %d)\n",
5969 +                       sa->type, sa->errorcode);
5970 +               error = sa->errorcode;
5971 +               goto out;
5972 +       } else if (sa->type == SD_AUDITTYPE_SYSCALL) {
5973 +               /* Currently SD_AUDITTYPE_SYSCALL is for rejects only.
5974 +                * Values set by sd_audit_syscallreject will get us here.
5975 +                */
5976 +               logcls = "REJECTING";
5977 +       } else {
5978 +               sdcomplain = SUBDOMAIN_COMPLAIN(sd);
5979 +               logcls = sdcomplain ? "PERMITTING" : "REJECTING";
5980 +       }
5981 +
5982 +       /* In future extend w/ per-profile flags
5983 +        * (flags |= sa->active->flags)
5984 +        */
5985 +       flags = sa->flags;
5986 +       if (subdomain_logsyscall)
5987 +               flags |= SD_AUDITFLAG_AUDITSS_SYSCALL;
5988 +
5989 +
5990 +       /* Force full audit syscall logging regardless of global setting if
5991 +        * we are rejecting a syscall
5992 +        */
5993 +       if (sa->type == SD_AUDITTYPE_SYSCALL) {
5994 +               ctx = current->audit_context;
5995 +       } else {
5996 +               ctx = (flags & SD_AUDITFLAG_AUDITSS_SYSCALL) ?
5997 +                       current->audit_context : NULL;
5998 +       }
5999 +
6000 +       ab = audit_log_start(ctx, gfp_mask, AUDIT_SD);
6001 +
6002 +       if (!ab) {
6003 +               SD_ERROR("Unable to log event (%d) to audit subsys\n",
6004 +                       sa->type);
6005 +               if (sdcomplain)
6006 +                       error = 0;
6007 +               goto out;
6008 +       }
6009 +
6010 +       /* messages get special handling */
6011 +       if (sa->type == SD_AUDITTYPE_MSG) {
6012 +               audit_log_vformat(ab, sa->name, sa->vaval);
6013 +               audit_log_end(ab);
6014 +               error = 0;
6015 +               goto out;
6016 +       }
6017 +
6018 +       /* log operation */
6019 +
6020 +       audit_log_format(ab, "%s ", logcls);    /* REJECTING/ALLOWING/etc */
6021 +
6022 +       if (sa->type == SD_AUDITTYPE_FILE) {
6023 +               int perm = sdaudit ? sa->ival : sa->errorcode;
6024 +
6025 +               audit_log_format(ab, "%s%s%s%s%s access to %s ",
6026 +                       perm & SD_EXEC_MMAP ? "m" : "",
6027 +                       perm & SD_MAY_READ  ? "r" : "",
6028 +                       perm & SD_MAY_WRITE ? "w" : "",
6029 +                       perm & SD_MAY_EXEC  ? "x" : "",
6030 +                       perm & SD_MAY_LINK  ? "l" : "",
6031 +                       sa->name);
6032 +
6033 +               opspec_error = -EPERM;
6034 +
6035 +       } else if (sa->type == SD_AUDITTYPE_DIR) {
6036 +               audit_log_format(ab, "%s on %s ",
6037 +                       sa->ival == SD_DIR_MKDIR ? "mkdir" : "rmdir",
6038 +                       sa->name);
6039 +
6040 +       } else if (sa->type == SD_AUDITTYPE_ATTR) {
6041 +               struct iattr *iattr = (struct iattr*)sa->pval;
6042 +
6043 +               audit_log_format(ab,
6044 +                       "attribute (%s%s%s%s%s%s%s) change to %s ",
6045 +                       iattr->ia_valid & ATTR_MODE ? "mode," : "",
6046 +                       iattr->ia_valid & ATTR_UID ? "uid," : "",
6047 +                       iattr->ia_valid & ATTR_GID ? "gid," : "",
6048 +                       iattr->ia_valid & ATTR_SIZE ? "size," : "",
6049 +                       ((iattr->ia_valid & ATTR_ATIME_SET) ||
6050 +                        (iattr->ia_valid & ATTR_ATIME)) ? "atime," : "",
6051 +                       ((iattr->ia_valid & ATTR_MTIME_SET) ||
6052 +                        (iattr->ia_valid & ATTR_MTIME)) ? "mtime," : "",
6053 +                       iattr->ia_valid & ATTR_CTIME ? "ctime," : "",
6054 +                       sa->name);
6055 +
6056 +       } else if (sa->type == SD_AUDITTYPE_XATTR) {
6057 +               const char *fmt;
6058 +               switch (sa->ival) {
6059 +                       case SD_XATTR_GET:
6060 +                               fmt = "xattr get";
6061 +                               break;
6062 +                       case SD_XATTR_SET:
6063 +                               fmt = "xattr set";
6064 +                               break;
6065 +                       case SD_XATTR_LIST:
6066 +                               fmt = "xattr list";
6067 +                               break;
6068 +                       case SD_XATTR_REMOVE:
6069 +                               fmt = "xattr remove";
6070 +                               break;
6071 +                       default:
6072 +                               fmt = "xattr <unknown>";
6073 +                               break;
6074 +               }
6075 +
6076 +               audit_log_format(ab, "%s on %s ", fmt, sa->name);
6077 +
6078 +       } else if (sa->type == SD_AUDITTYPE_LINK) {
6079 +               audit_log_format(ab,
6080 +                       "link access from %s to %s ",
6081 +                       sa->name,
6082 +                       (char*)sa->pval);
6083 +
6084 +       } else if (sa->type == SD_AUDITTYPE_CAP) {
6085 +               audit_log_format(ab,
6086 +                       "access to capability '%s' ",
6087 +                       capability_to_name(sa->ival));
6088 +
6089 +               opspec_error = -EPERM;
6090 +       } else if (sa->type == SD_AUDITTYPE_SYSCALL) {
6091 +               audit_log_format(ab, "access to syscall '%s' ", sa->name);
6092 +
6093 +               opspec_error = -EPERM;
6094 +       } else {
6095 +               /* -EINVAL -- will WARN_ON above */
6096 +               goto out;
6097 +       }
6098 +
6099 +       audit_log_format(ab, "(%s(%d) profile %s active %s)",
6100 +               current->comm, current->pid,
6101 +               sd->profile->name, sd->active->name);
6102 +
6103 +       audit_log_end(ab);
6104 +
6105 +       if (sdcomplain)
6106 +               error = 0;
6107 +       else
6108 +               error = sa->result ? 0 : opspec_error;
6109 +
6110 +out:
6111 +       return error;
6112 +}
6113 +
6114 +/**
6115 + * sd_get_name - retrieve fully qualified path name
6116 + * @dentry: relative path element
6117 + * @mnt: where in tree
6118 + *
6119 + * Returns fully qualified path name on sucess, NULL on failure.
6120 + * sd_put_name must be used to free allocated buffer.
6121 + */
6122 +char *sd_get_name(struct dentry *dentry, struct vfsmount *mnt)
6123 +{
6124 +       char *page, *name;
6125 +
6126 +       page = (char *)__get_free_page(GFP_KERNEL);
6127 +       if (!page) {
6128 +               name = ERR_PTR(-ENOMEM);
6129 +               goto out;
6130 +       }
6131 +
6132 +       name = d_path(dentry, mnt, page, PAGE_SIZE);
6133 +
6134 +       /* check for (deleted) that d_path appends to pathnames if the dentry
6135 +        * has been removed from the cache.
6136 +        * The size > deleted_size and strcmp checks are redundant safe guards.
6137 +        */
6138 +       if (IS_ERR(name)) {
6139 +               free_page((unsigned long)page);
6140 +       } else {
6141 +               const char deleted_str[] = " (deleted)";
6142 +               const size_t deleted_size = sizeof(deleted_str) - 1;
6143 +               size_t size;
6144 +               size = strlen(name);
6145 +               if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
6146 +                   size > deleted_size &&
6147 +                   strcmp(name + size - deleted_size, deleted_str) == 0)
6148 +                       name[size - deleted_size] = '\0';
6149 +
6150 +               SD_DEBUG("%s: full_path=%s\n", __FUNCTION__, name);
6151 +       }
6152 +
6153 +out:
6154 +       return name;
6155 +}
6156 +
6157 +/***********************************
6158 + * GLOBAL PERMISSION CHECK FUNCTIONS
6159 + ***********************************/
6160 +
6161 +/**
6162 + * sd_attr - check whether attribute change allowed
6163 + * @sd: subdomain to check against to check against
6164 + * @dentry: file to check
6165 + * @iattr: attribute changes requested
6166 + */
6167 +int sd_attr(struct subdomain *sd, struct dentry *dentry, struct iattr *iattr)
6168 +{
6169 +       int error = 0, permerror;
6170 +       struct sd_audit sa;
6171 +
6172 +       if (!__sd_is_confined(sd))
6173 +               goto out;
6174 +
6175 +       sa.type = SD_AUDITTYPE_ATTR;
6176 +       sa.pval = iattr;
6177 +       sa.flags = 0;
6178 +       sa.gfp_mask = GFP_KERNEL;
6179 +
6180 +       permerror = _sd_perm_dentry(sd, dentry, MAY_WRITE, &sa.name);
6181 +       sd_permerror2result(permerror, &sa);
6182 +
6183 +       error = sd_audit(sd, &sa);
6184 +
6185 +       sd_put_name(sa.name);
6186 +
6187 +out:
6188 +       return error;
6189 +}
6190 +
6191 +int sd_xattr(struct subdomain *sd, struct dentry *dentry, const char *xattr,
6192 +            int xattroptype)
6193 +{
6194 +       int error = 0, permerror, mask = 0;
6195 +       struct sd_audit sa;
6196 +
6197 +       /* if not confined or empty mask permission granted */
6198 +       if (!__sd_is_confined(sd))
6199 +               goto out;
6200 +
6201 +       if (xattroptype == SD_XATTR_GET || xattroptype == SD_XATTR_LIST)
6202 +               mask = MAY_READ;
6203 +       else if (xattroptype == SD_XATTR_SET || xattroptype == SD_XATTR_REMOVE)
6204 +               mask = MAY_WRITE;
6205 +
6206 +       sa.type = SD_AUDITTYPE_XATTR;
6207 +       sa.ival = xattroptype;
6208 +       sa.pval = xattr;
6209 +       sa.flags = 0;
6210 +       sa.gfp_mask = GFP_KERNEL;
6211 +
6212 +       permerror = _sd_perm_dentry(sd, dentry, mask, &sa.name);
6213 +       sd_permerror2result(permerror, &sa);
6214 +
6215 +       error = sd_audit(sd, &sa);
6216 +
6217 +       sd_put_name(sa.name);
6218 +
6219 +out:
6220 +       return error;
6221 +}
6222 +
6223 +/**
6224 + * sd_perm - basic subdomain permissions check
6225 + * @sd: subdomain to check against
6226 + * @dentry: dentry
6227 + * @mnt: mountpoint
6228 + * @mask: access mode requested
6229 + *
6230 + * Determine if access (mask) for dentry is authorized by subdomain sd.
6231 + * Result, 0 (success), -ve (error)
6232 + */
6233 +int sd_perm(struct subdomain *sd, struct dentry *dentry, struct vfsmount *mnt,
6234 +           int mask)
6235 +{
6236 +       int error = 0, permerror;
6237 +       struct sd_audit sa;
6238 +
6239 +       if (!__sd_is_confined(sd))
6240 +               goto out;
6241 +
6242 +       if ((mask = sd_filter_mask(mask, dentry->d_inode)) == 0)
6243 +               goto out;
6244 +
6245 +       sa.type = SD_AUDITTYPE_FILE;
6246 +       sa.name = sd_get_name(dentry, mnt);
6247 +       sa.ival = mask;
6248 +       sa.flags = 0;
6249 +       sa.gfp_mask = GFP_KERNEL;
6250 +
6251 +       if (IS_ERR(sa.name)) {
6252 +               permerror = PTR_ERR(sa.name);
6253 +               sa.name = NULL;
6254 +       } else {
6255 +               permerror = sd_file_perm(sd, sa.name, mask);
6256 +       }
6257 +
6258 +       sd_permerror2result(permerror, &sa);
6259 +
6260 +       error = sd_audit(sd, &sa);
6261 +
6262 +       sd_put_name(sa.name);
6263 +
6264 +out:
6265 +       return error;
6266 +}
6267 +
6268 +/**
6269 + * sd_perm_nameidata: interface to sd_perm accepting nameidata
6270 + * @sd: subdomain to check against
6271 + * @nd: namespace data (for vfsmnt and dentry)
6272 + * @mask: access mode requested
6273 + */
6274 +int sd_perm_nameidata(struct subdomain *sd, struct nameidata *nd, int mask)
6275 +{
6276 +       int error = 0;
6277 +
6278 +       if (nd)
6279 +               error = sd_perm(sd, nd->dentry, nd->mnt, mask);
6280 +
6281 +       return error;
6282 +}
6283 +
6284 +/**
6285 + * sd_perm_dentry - file permissions interface when no vfsmnt available
6286 + * @sd: current subdomain
6287 + * @dentry: requested dentry
6288 + * @mask: access mode requested
6289 + *
6290 + * Determine if access (mask) for dentry is authorized by subdomain sd.
6291 + * Result, 0 (success), -ve (error)
6292 + */
6293 +int sd_perm_dentry(struct subdomain *sd, struct dentry *dentry, int mask)
6294 +{
6295 +       int error = 0, permerror;
6296 +       struct sd_audit sa;
6297 +
6298 +       if (!__sd_is_confined(sd))
6299 +               goto out;
6300 +
6301 +       if ((mask = sd_filter_mask(mask, dentry->d_inode)) == 0)
6302 +               goto out;
6303 +
6304 +       sa.type = SD_AUDITTYPE_FILE;
6305 +       sa.ival = mask;
6306 +       sa.flags = 0;
6307 +       sa.gfp_mask = GFP_KERNEL;
6308 +
6309 +       permerror = _sd_perm_dentry(sd, dentry, mask, &sa.name);
6310 +       sd_permerror2result(permerror, &sa);
6311 +
6312 +       error = sd_audit(sd, &sa);
6313 +
6314 +       sd_put_name(sa.name);
6315 +
6316 +out:
6317 +       return error;
6318 +}
6319 +
6320 +/**
6321 + * sd_perm_dir
6322 + * @sd: current subdomain
6323 + * @dentry: requested dentry
6324 + * @mode: SD_DIR_MKDIR or SD_DIR_RMDIR
6325 + *
6326 + * Determine if directory operation (make/remove) for dentry is authorized
6327 + * by subdomain sd.
6328 + * Result, 0 (success), -ve (error)
6329 + */
6330 +int sd_perm_dir(struct subdomain *sd, struct dentry *dentry, int diroptype)
6331 +{
6332 +       int error = 0, permerror, mask;
6333 +       struct sd_audit sa;
6334 +
6335 +       BUG_ON(diroptype != SD_DIR_MKDIR && diroptype != SD_DIR_RMDIR);
6336 +
6337 +       if (!__sd_is_confined(sd))
6338 +               goto out;
6339 +
6340 +       mask = MAY_WRITE;
6341 +
6342 +       sa.type = SD_AUDITTYPE_DIR;
6343 +       sa.ival = diroptype;
6344 +       sa.flags = 0;
6345 +       sa.gfp_mask = GFP_KERNEL;
6346 +
6347 +       permerror = _sd_perm_dentry(sd, dentry, mask, &sa.name);
6348 +       sd_permerror2result(permerror, &sa);
6349 +
6350 +       error = sd_audit(sd, &sa);
6351 +
6352 +       sd_put_name(sa.name);
6353 +
6354 +out:
6355 +       return error;
6356 +}
6357 +
6358 +/**
6359 + * sd_capability - test permission to use capability
6360 + * @sd: subdomain to check against
6361 + * @cap: capability to be tested
6362 + *
6363 + * Look up capability in active profile capability set.
6364 + * Return 0 (success), -EPERM (error)
6365 + */
6366 +int sd_capability(struct subdomain *sd, int cap)
6367 +{
6368 +       int error = 0;
6369 +
6370 +       if (__sd_is_confined(sd)) {
6371 +               struct sd_audit sa;
6372 +
6373 +               sa.type = SD_AUDITTYPE_CAP;
6374 +               sa.name = NULL;
6375 +               sa.ival = cap;
6376 +               sa.flags = 0;
6377 +               sa.errorcode = 0;
6378 +               sa.result = cap_raised(sd->active->capabilities, cap);
6379 +               sa.gfp_mask = GFP_ATOMIC;
6380 +
6381 +               error = sd_audit(sd, &sa);
6382 +       }
6383 +
6384 +       return error;
6385 +}
6386 +
6387 +/**
6388 + * sd_link - hard link check
6389 + * @link: dentry for link being created
6390 + * @target: dentry for link target
6391 + * @sd: subdomain to check against
6392 + *
6393 + * Checks link permissions for all possible name combinations.  This is
6394 + * particularly ugly.  Returns 0 on sucess, error otherwise.
6395 + */
6396 +int sd_link(struct subdomain *sd, struct dentry *link, struct dentry *target)
6397 +{
6398 +       char *iname = NULL, *oname = NULL,
6399 +            *failed_iname = NULL, *failed_oname = NULL;
6400 +       unsigned int result = 0;
6401 +       int error, sdpath_error, errorcode = 0, match = 0,
6402 +           sdcomplain = SUBDOMAIN_COMPLAIN(sd);
6403 +       struct sd_path_data idata, odata;
6404 +       struct sd_audit sa;
6405 +
6406 +       if (!__sd_is_confined(sd))
6407 +               return 0;
6408 +
6409 +       /* Perform nested lookup for names.
6410 +        * This is necessary in the case where /dev/block is mounted
6411 +        * multiple times,  i.e /dev/block->/a and /dev/block->/b
6412 +        * This allows us to detect links where src/dest are on different
6413 +        * mounts.   N.B no support yet for links across bind mounts of
6414 +        * the form mount -bind /mnt/subpath /mnt2
6415 +        *
6416 +        * Getting direct access to vfsmounts (via nameidata) for link and
6417 +        * target would allow all this uglyness to go away.
6418 +        *
6419 +        * If more than one mountpoint matches but none satisfy the profile,
6420 +        * only the first pathname (mountpoint) is logged.
6421 +        */
6422 +
6423 +       sd_path_begin2(target, link, &odata);
6424 +       do {
6425 +               oname = sd_path_getname(&odata);
6426 +               if (oname) {
6427 +                       sd_path_begin(target, &idata);
6428 +                       do {
6429 +                               iname = sd_path_getname(&idata);
6430 +                               if (iname) {
6431 +                                       result = sd_link_perm(sd, oname, iname);
6432 +
6433 +                                       /* access via any path is enough */
6434 +                                       if (result || sdcomplain) {
6435 +                                               match = 1;
6436 +                                               break;
6437 +                                       }
6438 +
6439 +                                       /* Already have an path that failed? */
6440 +                                       if (failed_iname) {
6441 +                                               sd_put_name(iname);
6442 +                                       } else {
6443 +                                               failed_iname = iname;
6444 +                                               failed_oname = oname;
6445 +                                       }
6446 +                               }
6447 +                       } while (iname && !match);
6448 +
6449 +                       /* should not be possible if we matched */
6450 +                       if ((sdpath_error = sd_path_end(&idata)) != 0) {
6451 +                               dentry_xlate_error(target, sdpath_error,
6452 +                                                  "inner dentry [link]");
6453 +
6454 +                               /* name should not be set if error */
6455 +                               WARN_ON(iname);
6456 +
6457 +                               errorcode = sdpath_error;
6458 +                       }
6459 +
6460 +                       /* don't release if we're saving it */
6461 +                       if (!match && failed_oname != oname)
6462 +                               sd_put_name(oname);
6463 +               }
6464 +       } while (oname && !match);
6465 +
6466 +       if (errorcode != 0) {
6467 +               /* inner error */
6468 +               (void)sd_path_end(&odata);
6469 +       } else if ((sdpath_error = sd_path_end(&odata)) != 0) {
6470 +               dentry_xlate_error(link, sdpath_error, "outer dentry [link]");
6471 +
6472 +               errorcode = sdpath_error;
6473 +       }
6474 +
6475 +       if (errorcode != 0) {
6476 +               /* inner or outer error */
6477 +               result = 0;
6478 +       } else if (match) {
6479 +               result = 1;
6480 +       } else {
6481 +               /* failed to match */
6482 +               WARN_ON(iname);
6483 +               WARN_ON(oname);
6484 +
6485 +               result = 0;
6486 +               iname = failed_iname;
6487 +               oname = failed_oname;
6488 +       }
6489 +
6490 +       sa.type = SD_AUDITTYPE_LINK;
6491 +       sa.name = oname;        /* link */
6492 +       sa.pval = iname;        /* target */
6493 +       sa.flags = 0;
6494 +       sa.errorcode = errorcode;
6495 +       sa.result = result;
6496 +       sa.gfp_mask = GFP_KERNEL;
6497 +
6498 +       error = sd_audit(sd, &sa);
6499 +
6500 +       if (failed_oname != oname)
6501 +               sd_put_name(failed_oname);
6502 +       if (failed_iname != iname)
6503 +               sd_put_name(failed_iname);
6504 +
6505 +       sd_put_name(oname);
6506 +       sd_put_name(iname);
6507 +
6508 +       return error;
6509 +}
6510 +
6511 +/**********************************
6512 + * GLOBAL PROCESS RELATED FUNCTIONS
6513 + *********************************/
6514 +
6515 +/**
6516 + * sd_fork - create a new subdomain
6517 + * @p: new process
6518 + *
6519 + * Create a new subdomain for newly created process @p if it's parent
6520 + * is already confined.  Otherwise a subdomain will be lazily allocated
6521 + * for the child if it subsequently execs (in sd_register).
6522 + * Return 0 on sucess.
6523 + */
6524 +
6525 +int sd_fork(struct task_struct *p)
6526 +{
6527 +       struct subdomain *sd = SD_SUBDOMAIN(current->security);
6528 +       struct subdomain *newsd = NULL;
6529 +
6530 +       SD_DEBUG("%s\n", __FUNCTION__);
6531 +
6532 +       if (__sd_is_confined(sd)) {
6533 +               unsigned long flags;
6534 +
6535 +               newsd = alloc_subdomain(p);
6536 +
6537 +               if (!newsd)
6538 +                       return -ENOMEM;
6539 +
6540 +               /* Can get away with a read rather than write lock here
6541 +                * as we just allocated newsd above, so we can guarantee
6542 +                * that it's active/profile are null and therefore a replace
6543 +                * cannot happen.
6544 +                */
6545 +               read_lock_irqsave(&sd_lock, flags);
6546 +               sd_switch(newsd, sd->profile, sd->active);
6547 +               newsd->sd_hat_magic = sd->sd_hat_magic;
6548 +               read_unlock_irqrestore(&sd_lock, flags);
6549 +
6550 +               if (SUBDOMAIN_COMPLAIN(sd) &&
6551 +                   sd->active == null_complain_profile)
6552 +                       LOG_HINT(sd, GFP_KERNEL, HINT_FORK,
6553 +                               "pid=%d child=%d\n",
6554 +                               current->pid, p->pid);
6555 +       }
6556 +       p->security = newsd;
6557 +       return 0;
6558 +}
6559 +
6560 +/**
6561 + * sd_register - register a new program
6562 + * @filp: file of program being registered
6563 + *
6564 + * Try to register a new program during execve().  This should give the
6565 + * new program a valid subdomain.
6566 + *
6567 + * This _used_ to be a really simple piece of code :-(
6568 + *
6569 + */
6570 +int sd_register(struct linux_binprm *bprm)
6571 +{
6572 +       char *filename;
6573 +       struct file *filp = bprm->file;
6574 +       struct subdomain *sd, sdcopy;
6575 +       struct sdprofile *newprofile = NULL, unconstrained_flag;
6576 +       int     error = -ENOMEM,
6577 +               exec_mode = 0,
6578 +               findprofile = 0,
6579 +               findprofile_mandatory = 0,
6580 +               unsafe_exec = 0,
6581 +               complain = 0;
6582 +
6583 +       SD_DEBUG("%s\n", __FUNCTION__);
6584 +
6585 +       sd = get_sdcopy(&sdcopy);
6586 +
6587 +       filename = sd_get_name(filp->f_dentry, filp->f_vfsmnt);
6588 +       if (IS_ERR(filename)) {
6589 +               SD_WARN("%s: Failed to get filename\n", __FUNCTION__);
6590 +               goto out;
6591 +       }
6592 +
6593 +       error = 0;
6594 +
6595 +       if (!__sd_is_confined(sd)) {
6596 +               /* Unconfined task, load profile if it exists */
6597 +               findprofile = 1;
6598 +               goto find_profile;
6599 +       }
6600 +
6601 +       complain = SUBDOMAIN_COMPLAIN(sd);
6602 +
6603 +       /* Confined task, determine what mode inherit, unconstrained or
6604 +        * mandatory to load new profile
6605 +        */
6606 +       if (sd_get_execmode(sd, filename, &exec_mode, &unsafe_exec)) {
6607 +               switch (exec_mode) {
6608 +               case SD_EXEC_INHERIT:
6609 +                       /* do nothing - setting of profile
6610 +                        * already handed in sd_fork
6611 +                        */
6612 +                       SD_DEBUG("%s: INHERIT %s\n",
6613 +                                __FUNCTION__,
6614 +                                filename);
6615 +                       break;
6616 +
6617 +               case SD_EXEC_UNCONSTRAINED:
6618 +                       SD_DEBUG("%s: UNCONSTRAINED %s\n",
6619 +                                __FUNCTION__,
6620 +                                filename);
6621 +
6622 +                       /* unload profile */
6623 +                       newprofile = &unconstrained_flag;
6624 +                       break;
6625 +
6626 +               case SD_EXEC_PROFILE:
6627 +                       SD_DEBUG("%s: PROFILE %s\n",
6628 +                                __FUNCTION__,
6629 +                                filename);
6630 +
6631 +                       findprofile = 1;
6632 +                       findprofile_mandatory = 1;
6633 +                       break;
6634 +
6635 +               case SD_MAY_EXEC:
6636 +                       /* this should not happen, entries
6637 +                        * with just EXEC only should be
6638 +                        * rejected at profile load time
6639 +                        */
6640 +                       SD_ERROR("%s: Rejecting exec(2) of image '%s'. "
6641 +                               "SD_MAY_EXEC without exec qualifier invalid "
6642 +                               "(%s(%d) profile %s active %s\n",
6643 +                                __FUNCTION__,
6644 +                                filename,
6645 +                                current->comm, current->pid,
6646 +                                sd->profile->name, sd->active->name);
6647 +                       error = -EPERM;
6648 +                       break;
6649 +
6650 +               default:
6651 +                       SD_ERROR("%s: Rejecting exec(2) of image '%s'. "
6652 +                                "Unknown exec qualifier %x "
6653 +                                "(%s (pid %d) profile %s active %s)\n",
6654 +                                __FUNCTION__,
6655 +                                filename,
6656 +                                exec_mode,
6657 +                                current->comm, current->pid,
6658 +                                sd->profile->name, sd->active->name);
6659 +                       error = -EPERM;
6660 +                       break;
6661 +               }
6662 +
6663 +       } else if (complain) {
6664 +               /* There was no entry in calling profile
6665 +                * describing mode to execute image in.
6666 +                * Drop into null-profile (disabling secure exec).
6667 +                */
6668 +               newprofile = get_sdprofile(null_complain_profile);
6669 +               unsafe_exec = 1;
6670 +       } else {
6671 +               SD_WARN("%s: Rejecting exec(2) of image '%s'. "
6672 +                       "Unable to determine exec qualifier "
6673 +                       "(%s (pid %d) profile %s active %s)\n",
6674 +                       __FUNCTION__,
6675 +                       filename,
6676 +                       current->comm, current->pid,
6677 +                       sd->profile->name, sd->active->name);
6678 +               error = -EPERM;
6679 +       }
6680 +
6681 +
6682 +find_profile:
6683 +       if (!findprofile)
6684 +               goto apply_profile;
6685 +
6686 +       /* Locate new profile */
6687 +       newprofile = sd_profilelist_find(filename);
6688 +       if (newprofile) {
6689 +               SD_DEBUG("%s: setting profile %s\n",
6690 +                        __FUNCTION__, newprofile->name);
6691 +       } else if (findprofile_mandatory) {
6692 +               /* Profile (mandatory) could not be found */
6693 +
6694 +               if (complain) {
6695 +                       LOG_HINT(sd, GFP_KERNEL, HINT_MANDPROF,
6696 +                               "image=%s pid=%d profile=%s active=%s\n",
6697 +                               filename,
6698 +                               current->pid,
6699 +                               sd->profile->name,
6700 +                               sd->active->name);
6701 +
6702 +                       newprofile = get_sdprofile(null_complain_profile);
6703 +               } else {
6704 +                       SD_WARN("REJECTING exec(2) of image '%s'. "
6705 +                               "Profile mandatory and not found "
6706 +                               "(%s(%d) profile %s active %s)\n",
6707 +                               filename,
6708 +                               current->comm, current->pid,
6709 +                               sd->profile->name, sd->active->name);
6710 +                       error = -EPERM;
6711 +               }
6712 +       } else {
6713 +               /* Profile (non-mandatory) could not be found */
6714 +
6715 +               /* Only way we can get into this code is if task
6716 +                * is unconstrained.
6717 +                */
6718 +
6719 +               BUG_ON(__sd_is_confined(sd));
6720 +
6721 +               SD_DEBUG("%s: No profile found for exec image %s\n",
6722 +                        __FUNCTION__,
6723 +                        filename);
6724 +       } /* newprofile */
6725 +
6726 +
6727 +apply_profile:
6728 +       /* Apply profile if necessary */
6729 +       if (newprofile) {
6730 +               struct subdomain *latest_sd, *lazy_sd = NULL;
6731 +               unsigned long flags;
6732 +
6733 +               if (newprofile == &unconstrained_flag)
6734 +                       newprofile = NULL;
6735 +
6736 +               /* grab a write lock
6737 +                *
6738 +                * - Task may be presently unconfined (have no sd). In which
6739 +                *   case we have to lazily allocate one.  Note we may be raced
6740 +                *   to this allocation by a setprofile.
6741 +                *
6742 +                * - sd is a refcounted copy of the subdomain (get_sdcopy) and
6743 +                *   not the actual subdomain. This allows us to not have to
6744 +                *   hold a read lock around all this code. However, we need to
6745 +                *   change the actual subdomain, not the copy.
6746 +                *
6747 +                * - If newprofile points to an actual profile (result of
6748 +                *   sd_profilelist_find above), this profile may have been
6749 +                *   replaced.  We need to fix it up.  Doing this to avoid
6750 +                *   having to hold a write lock around all this code.
6751 +                */
6752 +
6753 +               if (!sd) {
6754 +                       lazy_sd = alloc_subdomain(current);
6755 +               }
6756 +
6757 +               write_lock_irqsave(&sd_lock, flags);
6758 +
6759 +               latest_sd = SD_SUBDOMAIN(current->security);
6760 +
6761 +               if (latest_sd) {
6762 +                       if (lazy_sd) {
6763 +                               /* raced by setprofile (created latest_sd) */
6764 +                               free_subdomain(lazy_sd);
6765 +                               lazy_sd = NULL;
6766 +                       }
6767 +               } else {
6768 +                       if (lazy_sd) {
6769 +                               latest_sd = lazy_sd;
6770 +                               current->security = lazy_sd;
6771 +                       } else {
6772 +                               SD_ERROR("%s: Failed to allocate subdomain\n",
6773 +                                       __FUNCTION__);
6774 +
6775 +                               error = -ENOMEM;
6776 +                               write_unlock_irqrestore(&sd_lock, flags);
6777 +                               goto done;
6778 +                       }
6779 +               }
6780 +
6781 +               /* Determine if profile we found earlier is stale.
6782 +                * If so, reobtain it.  N.B stale flag should never be
6783 +                * set on null_complain profile.
6784 +                */
6785 +               if (newprofile && unlikely(newprofile->isstale)) {
6786 +                       BUG_ON(newprofile == null_complain_profile);
6787 +
6788 +                       /* drop refcnt obtained from earlier get_sdprofile */
6789 +                       put_sdprofile(newprofile);
6790 +
6791 +                       newprofile = sd_profilelist_find(filename);
6792 +
6793 +                       if (!newprofile) {
6794 +                               /* Race, profile was removed, not replaced.
6795 +                                * Redo with error checking
6796 +                                */
6797 +                               write_unlock_irqrestore(&sd_lock, flags);
6798 +                               goto find_profile;
6799 +                       }
6800 +               }
6801 +
6802 +               /* Handle confined exec.
6803 +                * Can be at this point for the following reasons:
6804 +                * 1. unconfined switching to confined
6805 +                * 2. confined switching to different confinement
6806 +                * 3. confined switching to unconfined
6807 +                *
6808 +                * Cases 2 and 3 are marked as requiring secure exec
6809 +                * (unless policy specified "unsafe exec")
6810 +                */
6811 +               if (__sd_is_confined(latest_sd) && !unsafe_exec) {
6812 +                       unsigned long bprm_flags;
6813 +
6814 +                       bprm_flags = SD_SECURE_EXEC_NEEDED;
6815 +                       bprm->security = (void*)
6816 +                               ((unsigned long)bprm->security | bprm_flags);
6817 +               }
6818 +
6819 +               sd_switch(latest_sd, newprofile, newprofile);
6820 +               put_sdprofile(newprofile);
6821 +
6822 +               if (complain && newprofile == null_complain_profile)
6823 +                       LOG_HINT(latest_sd, GFP_ATOMIC, HINT_CHGPROF,
6824 +                               "pid=%d\n",
6825 +                               current->pid);
6826 +
6827 +               write_unlock_irqrestore(&sd_lock, flags);
6828 +       }
6829 +
6830 +done:
6831 +       sd_put_name(filename);
6832 +
6833 +       if (sd)
6834 +               put_sdcopy(sd);
6835 +
6836 +out:
6837 +       return error;
6838 +}
6839 +
6840 +/**
6841 + * sd_release - release the task's subdomain
6842 + * @p: task being released
6843 + *
6844 + * This is called after a task has exited and the parent has reaped it.
6845 + * p->security must be !NULL. The @p->security blob is freed.
6846 + */
6847 +void sd_release(struct task_struct *p)
6848 +{
6849 +       struct subdomain *sd = SD_SUBDOMAIN(p->security);
6850 +       p->security = NULL;
6851 +
6852 +       sd_subdomainlist_remove(sd);
6853 +
6854 +       /* release profiles */
6855 +       put_sdprofile(sd->profile);
6856 +       put_sdprofile(sd->active);
6857 +
6858 +       kfree(sd);
6859 +}
6860 +
6861 +/*****************************
6862 + * GLOBAL SUBPROFILE FUNCTIONS
6863 + ****************************/
6864 +
6865 +/**
6866 + * do_change_hat - actually switch hats
6867 + * @name: name of hat to swtich to
6868 + * @sd: current subdomain
6869 + *
6870 + * Switch to a new hat.  Return 0 on success, error otherwise.
6871 + */
6872 +static inline int do_change_hat(const char *hat_name, struct subdomain *sd)
6873 +{
6874 +       struct sdprofile *sub;
6875 +       struct sdprofile *p = sd->active;
6876 +       int error = 0;
6877 +
6878 +       sub = __sd_find_profile(hat_name, &sd->profile->sub);
6879 +
6880 +       if (sub) {
6881 +               /* change hat */
6882 +               sd->active = sub;
6883 +       } else {
6884 +               /* There is no such subprofile change to a NULL profile.
6885 +                * The NULL profile grants no file access.
6886 +                *
6887 +                * This feature is used by changehat_apache.
6888 +                *
6889 +                * N.B from the null-profile the task can still changehat back
6890 +                * out to the parent profile (assuming magic != NULL)
6891 +                */
6892 +               if (SUBDOMAIN_COMPLAIN(sd)) {
6893 +                       LOG_HINT(sd, GFP_ATOMIC, HINT_UNKNOWN_HAT,
6894 +                               "%s pid=%d "
6895 +                               "profile=%s active=%s\n",
6896 +                               hat_name,
6897 +                               current->pid,
6898 +                               sd->profile->name,
6899 +                               sd->active->name);
6900 +                       sd->active = get_sdprofile(null_complain_profile);
6901 +               } else {
6902 +                       SD_DEBUG("%s: Unknown hatname '%s'. "
6903 +                               "Changing to NULL profile "
6904 +                               "(%s(%d) profile %s active %s)\n",
6905 +                                __FUNCTION__,
6906 +                                hat_name,
6907 +                                current->comm, current->pid,
6908 +                                sd->profile->name, sd->active->name);
6909 +
6910 +                       sd->active = get_sdprofile(null_profile);
6911 +                       error = -EACCES;
6912 +               }
6913 +       }
6914 +       put_sdprofile(p);
6915 +
6916 +       return error;
6917 +}
6918 +
6919 +/**
6920 + * sd_change_hat - change hat to/from subprofile
6921 + * @hat_name: specifies hat to change to
6922 + * @hat_magic: token to validate hat change
6923 + *
6924 + * Change to new @hat_name when current hat is top level profile, and store
6925 + * the @hat_magic in the current subdomain.  If the new @hat_name is
6926 + * NULL, and the @hat_magic matches that stored in the current subdomain
6927 + * return to original top level profile.  Returns 0 on success, error
6928 + * otherwise.
6929 + */
6930 +#define IN_SUBPROFILE(sd)      ((sd)->profile != (sd)->active)
6931 +int sd_change_hat(const char *hat_name, __u32 hat_magic)
6932 +{
6933 +       struct subdomain *sd = SD_SUBDOMAIN(current->security);
6934 +       int error = 0;
6935 +
6936 +       SD_DEBUG("%s: %p, 0x%x (pid %d)\n",
6937 +                __FUNCTION__,
6938 +                hat_name, hat_magic,
6939 +                current->pid);
6940 +
6941 +       /* Dump out above debugging in WARN mode if we are in AUDIT mode */
6942 +       if (SUBDOMAIN_AUDIT(sd)) {
6943 +               SD_WARN("%s: %s, 0x%x (pid %d)\n",
6944 +                       __FUNCTION__, hat_name ? hat_name : "NULL",
6945 +                       hat_magic, current->pid);
6946 +       }
6947 +
6948 +       /* no subdomain: changehat into the null_profile, since the process
6949 +          has no subdomain do_change_hat won't find a match which will cause
6950 +          a changehat to null_profile.  We could short circuit this but since
6951 +          the subdprofile (hat) list is empty we would save very little. */
6952 +
6953 +       /* check to see if an unconfined process is doing a changehat. */
6954 +       if (!__sd_is_confined(sd)) {
6955 +               error = -EACCES;
6956 +               goto out;
6957 +       }
6958 +
6959 +       /* Check whether current domain is parent
6960 +        * or one of the sibling children
6961 +        */
6962 +       if (sd->profile == sd->active) {
6963 +               /*
6964 +                * parent
6965 +                */
6966 +               if (hat_name) {
6967 +                       SD_DEBUG("%s: switching to %s, 0x%x\n",
6968 +                                __FUNCTION__,
6969 +                                hat_name,
6970 +                                hat_magic);
6971 +
6972 +                       /*
6973 +                        * N.B hat_magic == 0 has a special meaning
6974 +                        * this indicates that the task may never changehat
6975 +                        * back to it's parent, it will stay in this subhat
6976 +                        * (or null-profile, if the hat doesn't exist) until
6977 +                        * the task terminates
6978 +                        */
6979 +                       sd->sd_hat_magic = hat_magic;
6980 +                       error = do_change_hat(hat_name, sd);
6981 +               } else {
6982 +                       /* Got here via changehat(NULL, magic)
6983 +                        *
6984 +                        * We used to simply update the magic cookie.
6985 +                        * That's an odd behaviour, so just do nothing.
6986 +                        */
6987 +               }
6988 +       } else {
6989 +               /*
6990 +                * child -- check to make sure magic is same as what was
6991 +                * passed when we switched into this profile,
6992 +                * Handle special casing of NULL magic which confines task
6993 +                * to subprofile and prohibits further changehats
6994 +                */
6995 +               if (hat_magic == sd->sd_hat_magic && sd->sd_hat_magic) {
6996 +                       if (!hat_name) {
6997 +                               /*
6998 +                                * Got here via changehat(NULL, magic)
6999 +                                * Return from subprofile, back to parent
7000 +                                */
7001 +                               put_sdprofile(sd->active);
7002 +                               sd->active = get_sdprofile(sd->profile);
7003 +
7004 +                               /* Reset hat_magic to zero.
7005 +                                * New value will be passed on next changehat
7006 +                                */
7007 +                               sd->sd_hat_magic = 0;
7008 +                       } else {
7009 +                               /* change to another (sibling) profile */
7010 +                               error = do_change_hat(hat_name, sd);
7011 +                       }
7012 +               } else if (sd->sd_hat_magic) {
7013 +                       SD_ERROR("KILLING process %s(%d) "
7014 +                                "Invalid change_hat() magic# 0x%x "
7015 +                                "(hatname %s profile %s active %s)\n",
7016 +                                current->comm, current->pid,
7017 +                                hat_magic,
7018 +                                hat_name ? hat_name : "NULL",
7019 +                                sd->profile->name, sd->active->name);
7020 +
7021 +                       /* terminate current process */
7022 +                       (void)send_sig_info(SIGKILL, NULL, current);
7023 +               } else {        /* sd->sd_hat_magic == NULL */
7024 +                       SD_ERROR("KILLING process %s(%d) "
7025 +                                "Task was confined to current subprofile "
7026 +                                "(profile %s active %s)\n",
7027 +                                current->comm, current->pid,
7028 +                                sd->profile->name, sd->active->name);
7029 +
7030 +                       /* terminate current process */
7031 +                       (void)send_sig_info(SIGKILL, NULL, current);
7032 +               }
7033 +
7034 +       }
7035 +
7036 +out:
7037 +       return error;
7038 +}
7039 --- linux-2.6.16.29.orig/security/apparmor/Makefile     1969-12-31 16:00:00.000000000 -0800
7040 +++ linux-2.6.16.29/security/apparmor/Makefile  2006-10-12 21:11:15.000000000 -0700
7041 @@ -0,0 +1,25 @@
7042 +# Makefile for AppArmor Linux Security Module (previously called "SubDomain")
7043 +#
7044 +# kernel build Makefile is the Kbuild file
7045 +
7046 +REPO_VERSION := $(shell if [ -x /usr/bin/svn ] ; then \
7047 +       /usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
7048 +       fi)
7049 +
7050 +ifeq ("${REPO_VERSION}", "")
7051 +REPO_VERSION := "unknown"
7052 +endif
7053 +
7054 +KERNELVER := $(shell uname -r)
7055 +
7056 +KERNELDIR := /lib/modules/${KERNELVER}/build
7057 +
7058 +all:
7059 +       $(MAKE) -C $(KERNELDIR) M=`pwd` APPARMOR_VER=${REPO_VERSION} $@
7060 +       mv apparmor.ko apparmor-${KERNELVER}.ko
7061 +       mv aamatch/aamatch_pcre.ko aamatch_pcre-${KERNELVER}.ko
7062 +
7063 +clean:
7064 +       rm -f *.o *.ko *.mod.c .*.cmd Modules.symvers \
7065 +               aamatch/*.o aamatch/*.ko aamatch/.*.cmd aamatch/*.mod.c
7066 +       rm -rf .tmp_versions
7067 --- linux-2.6.16.29.orig/security/apparmor/module_interface.c   1969-12-31 16:00:00.000000000 -0800
7068 +++ linux-2.6.16.29/security/apparmor/module_interface.c        2006-10-12 21:11:15.000000000 -0700
7069 @@ -0,0 +1,712 @@
7070 +/*
7071 + *     Copyright (C) 1998-2005 Novell/SUSE
7072 + *
7073 + *     This program is free software; you can redistribute it and/or
7074 + *     modify it under the terms of the GNU General Public License as
7075 + *     published by the Free Software Foundation, version 2 of the
7076 + *     License.
7077 + *
7078 + *     AppArmor userspace policy interface
7079 + */
7080 +
7081 +#include <asm/unaligned.h>
7082 +
7083 +#include "apparmor.h"
7084 +#include "inline.h"
7085 +#include "module_interface.h"
7086 +#include "aamatch/match.h"
7087 +
7088 +/* sd_code defined in module_interface.h */
7089 +
7090 +const int sdcode_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
7091 +
7092 +struct sd_taskreplace_data {
7093 +       struct sdprofile *old_profile;
7094 +       struct sdprofile *new_profile;
7095 +};
7096 +
7097 +/* inlines must be forward of there use in newer version of gcc,
7098 +   just forward declaring with a prototype won't work anymore */
7099 +
7100 +static inline void free_sd_entry(struct sd_entry *entry)
7101 +{
7102 +       if (entry) {
7103 +               kfree(entry->filename);
7104 +               sdmatch_free(entry->extradata);
7105 +               kfree(entry);
7106 +       }
7107 +}
7108 +
7109 +/**
7110 + * alloc_sd_entry - create new empty sd_entry
7111 + *
7112 + * This routine allocates, initializes, and returns a new subdomain
7113 + * file entry structure.  Structure is zeroed.  Returns new structure on
7114 + * success, NULL on failure.
7115 + */
7116 +static inline struct sd_entry *alloc_sd_entry(void)
7117 +{
7118 +       struct sd_entry *entry;
7119 +
7120 +       SD_DEBUG("%s\n", __FUNCTION__);
7121 +       entry = kmalloc(sizeof(struct sd_entry), GFP_KERNEL);
7122 +       if (entry) {
7123 +               int i;
7124 +               memset(entry, 0, sizeof(struct sd_entry));
7125 +               INIT_LIST_HEAD(&entry->list);
7126 +               for (i = 0; i <= POS_SD_FILE_MAX; i++) {
7127 +                       INIT_LIST_HEAD(&entry->listp[i]);
7128 +               }
7129 +       }
7130 +       return entry;
7131 +}
7132 +
7133 +/**
7134 + * free_sdprofile - free sdprofile structure
7135 + */
7136 +void free_sdprofile(struct sdprofile *profile)
7137 +{
7138 +       struct sd_entry *sdent, *tmp;
7139 +       struct sdprofile *p, *ptmp;
7140 +
7141 +       SD_DEBUG("%s(%p)\n", __FUNCTION__, profile);
7142 +
7143 +       if (!profile)
7144 +               return;
7145 +
7146 +       /* profile is still on global profile list -- invalid */
7147 +       if (!list_empty(&profile->list)) {
7148 +               SD_ERROR("%s: internal error, "
7149 +                        "profile '%s' still on global list\n",
7150 +                        __FUNCTION__,
7151 +                        profile->name);
7152 +               BUG();
7153 +       }
7154 +
7155 +       list_for_each_entry_safe(sdent, tmp, &profile->file_entry, list) {
7156 +               if (sdent->filename)
7157 +                       SD_DEBUG("freeing sd_entry: %p %s\n",
7158 +                                sdent->filename, sdent->filename);
7159 +               list_del_init(&sdent->list);
7160 +               free_sd_entry(sdent);
7161 +       }
7162 +
7163 +       list_for_each_entry_safe(p, ptmp, &profile->sub, list) {
7164 +               list_del_init(&p->list);
7165 +               put_sdprofile(p);
7166 +       }
7167 +
7168 +       if (profile->name) {
7169 +               SD_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
7170 +               kfree(profile->name);
7171 +       }
7172 +
7173 +       kfree(profile);
7174 +}
7175 +
7176 +/** task_remove
7177 + *
7178 + * remove profile in a task's subdomain leaving the task unconfined
7179 + *
7180 + * @sd: task's subdomain
7181 + */
7182 +static inline void task_remove(struct subdomain *sd)
7183 +{
7184 +       /* write_lock(&sd_lock) held here */
7185 +       SD_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
7186 +                __FUNCTION__,
7187 +                sd->task->comm,
7188 +                sd->task->pid,
7189 +                sd->profile->name,
7190 +                sd->active->name);
7191 +
7192 +       sd_switch_unconfined(sd);
7193 +}
7194 +
7195 +/** taskremove_iter
7196 + *
7197 + * Iterate over all subdomains.
7198 + *
7199 + * If any matches old_profile,  then call task_remove to remove it.
7200 + * This leaves the task (subdomain) unconfined.
7201 + */
7202 +static int taskremove_iter(struct subdomain *sd, void *cookie)
7203 +{
7204 +       struct sdprofile *old_profile = (struct sdprofile *)cookie;
7205 +       unsigned long flags;
7206 +
7207 +       write_lock_irqsave(&sd_lock, flags);
7208 +
7209 +       if (__sd_is_confined(sd) && sd->profile == old_profile)
7210 +               task_remove(sd);
7211 +
7212 +       write_unlock_irqrestore(&sd_lock, flags);
7213 +
7214 +       return 0;
7215 +}
7216 +
7217 +/** task_replace
7218 + *
7219 + * replace profile in a task's subdomain with newly loaded profile
7220 + *
7221 + * @sd: task's subdomain
7222 + * @new: old profile
7223 + */
7224 +static inline void task_replace(struct subdomain *sd, struct sdprofile *new)
7225 +{
7226 +       struct sdprofile *nactive = NULL;
7227 +
7228 +       SD_DEBUG("%s: replacing profile for task %s(%d) "
7229 +                "profile=%s (%p) active=%s (%p)\n",
7230 +                __FUNCTION__,
7231 +                sd->task->comm, sd->task->pid,
7232 +                sd->profile->name, sd->profile,
7233 +                sd->active->name, sd->active);
7234 +
7235 +       if (sd->profile == sd->active)
7236 +               nactive = get_sdprofile(new);
7237 +       else if (sd->active) {
7238 +               /* old in hat, new profile has hats */
7239 +               nactive = __sd_find_profile(sd->active->name, &new->sub);
7240 +
7241 +               if (!nactive) {
7242 +                       if (new->flags.complain)
7243 +                               nactive = get_sdprofile(null_complain_profile);
7244 +                       else
7245 +                               nactive = get_sdprofile(null_profile);
7246 +               }
7247 +       }
7248 +       sd_switch(sd, new, nactive);
7249 +
7250 +       put_sdprofile(nactive);
7251 +}
7252 +
7253 +/** taskreplace_iter
7254 + *
7255 + * Iterate over all subdomains.
7256 + *
7257 + * If any matches old_profile,  then call task_replace to replace with
7258 + * new_profile
7259 + */
7260 +static int taskreplace_iter(struct subdomain *sd, void *cookie)
7261 +{
7262 +       struct sd_taskreplace_data *data = (struct sd_taskreplace_data *)cookie;
7263 +       unsigned long flags;
7264 +
7265 +       write_lock_irqsave(&sd_lock, flags);
7266 +
7267 +       if (__sd_is_confined(sd) && sd->profile == data->old_profile)
7268 +               task_replace(sd, data->new_profile);
7269 +
7270 +       write_unlock_irqrestore(&sd_lock, flags);
7271 +
7272 +       return 0;
7273 +}
7274 +
7275 +static inline int sd_inbounds(struct sd_ext *e, size_t size)
7276 +{
7277 +       return (e->pos + size <= e->end);
7278 +}
7279 +
7280 +/**
7281 + * sdconvert - for codes that have a trailing value, convert that value
7282 + *             and put it in dest.
7283 + *             if a code does not have a trailing value nop
7284 + * @code: type code
7285 + * @dest: pointer to object to receive the converted value
7286 + * @src:  pointer to value to convert
7287 + */
7288 +static void sdconvert(enum sd_code code, void *dest, void *src)
7289 +{
7290 +       switch (code) {
7291 +       case SD_U8:
7292 +               *(u8 *)dest = *(u8 *) src;
7293 +               break;
7294 +       case SD_U16:
7295 +       case SD_NAME:
7296 +       case SD_DYN_STRING:
7297 +               *(u16 *)dest = le16_to_cpu(get_unaligned((u16 *)src));
7298 +               break;
7299 +       case SD_U32:
7300 +       case SD_STATIC_BLOB:
7301 +               *(u32 *)dest = le32_to_cpu(get_unaligned((u32 *)src));
7302 +               break;
7303 +       case SD_U64:
7304 +               *(u64 *)dest = le64_to_cpu(get_unaligned((u64 *)src));
7305 +               break;
7306 +       default:
7307 +               /* nop - all other type codes do not have a trailing value */
7308 +               ;
7309 +       }
7310 +}
7311 +
7312 +/**
7313 + * sd_is_X - check if the next element is of type X and if it is within
7314 + *           bounds.  If it is put the associated value in data.
7315 + * @e: extent information
7316 + * @code: type code
7317 + * @data: object located at @e->pos (of type @code) is written into @data
7318 + *        if @data is non-null.  if data is null it means skip this
7319 + *        entry
7320 + * return the size of bytes associated with the returned data
7321 + *        for complex object like blob and string a pointer to the allocated
7322 + *        data is returned in data, but the size of the blob or string is
7323 + *        returned.
7324 + */
7325 +static u32 sd_is_X(struct sd_ext *e, enum sd_code code, void *data)
7326 +{
7327 +       void *pos = e->pos;
7328 +       int ret = 0;
7329 +       if (!sd_inbounds(e, SD_CODE_BYTE + sdcode_datasize[code]))
7330 +               goto fail;
7331 +       if (code != *(u8 *)e->pos)
7332 +               goto out;
7333 +       e->pos += SD_CODE_BYTE;
7334 +       if (code == SD_NAME) {
7335 +               u16 size;
7336 +               /* name codes are followed by X bytes */
7337 +               size = le16_to_cpu(get_unaligned((u16 *)e->pos));
7338 +               if (!sd_inbounds(e, (size_t) size))
7339 +                       goto fail;
7340 +               if (data)
7341 +                       *(u16 *)data = size;
7342 +               e->pos += sdcode_datasize[code];
7343 +               ret = 1 + sdcode_datasize[code];
7344 +       } else if (code == SD_DYN_STRING) {
7345 +               u16 size;
7346 +               char *str;
7347 +               /* strings codes are followed by X bytes */
7348 +               size = le16_to_cpu(get_unaligned((u16 *)e->pos));
7349 +               e->pos += sdcode_datasize[code];
7350 +               if (!sd_inbounds(e, (size_t) size))
7351 +                       goto fail;
7352 +               if (data) {
7353 +                       * (char **)data = NULL;
7354 +                       str = kmalloc(size, GFP_KERNEL);
7355 +                       if (!str)
7356 +                               goto fail;
7357 +                       memcpy(str, e->pos, (size_t) size);
7358 +                       str[size-1] = '\0';
7359 +                       * (char **)data = str;
7360 +               }
7361 +               e->pos += size;
7362 +               ret = size;
7363 +       } else if (code == SD_STATIC_BLOB) {
7364 +               u32 size;
7365 +               /* blobs are followed by X bytes, that can be 2^32 */
7366 +               size = le32_to_cpu(get_unaligned((u32 *)e->pos));
7367 +               e->pos += sdcode_datasize[code];
7368 +               if (!sd_inbounds(e, (size_t) size))
7369 +                       goto fail;
7370 +               if (data)
7371 +                       memcpy(data, e->pos, (size_t) size);
7372 +               e->pos += size;
7373 +               ret = size;
7374 +       } else {
7375 +               if (data)
7376 +                       sdconvert(code, data, e->pos);
7377 +               e->pos += sdcode_datasize[code];
7378 +               ret = 1 + sdcode_datasize[code];
7379 +       }
7380 +out:
7381 +       return ret;
7382 +fail:
7383 +       e->pos = pos;
7384 +       return 0;
7385 +}
7386 +
7387 +/* sd_is_nameX - check is the next element is X, and its tag is name.
7388 + * if the code matches and name (if specified) matches then the packed data
7389 + * is unpacked into *data.  (Note for strings this is the size, and the next
7390 + * data in the stream is the string data)
7391 + * returns 0 if either match failes
7392 + */
7393 +static int sd_is_nameX(struct sd_ext *e, enum sd_code code, void *data,
7394 +                      const char *name)
7395 +{
7396 +       void *pos = e->pos;
7397 +       u16 size;
7398 +       u32 ret;
7399 +       /* check for presence of a tagname, and if present name size
7400 +        * SD_NAME tag value is a u16 */
7401 +       if (sd_is_X(e, SD_NAME, &size)) {
7402 +               /* if a name is specified it must match. otherwise skip tag */
7403 +               if (name && ((strlen(name) != size-1) ||
7404 +                            strncmp(name, (char *)e->pos, (size_t)size-1)))
7405 +                       goto fail;
7406 +               e->pos += size;
7407 +       }
7408 +       /* now check if data actually matches */
7409 +       ret = sd_is_X(e, code, data);
7410 +       if (!ret)
7411 +               goto fail;
7412 +       return ret;
7413 +
7414 +fail:
7415 +       e->pos = pos;
7416 +       return 0;
7417 +}
7418 +
7419 +/* macro to wrap error case to make a block of reads look nicer */
7420 +#define SD_READ_X(E, C, D, N) \
7421 +       do { \
7422 +               u32 __ret; \
7423 +               __ret = sd_is_nameX((E), (C), (D), (N)); \
7424 +               if (!__ret) \
7425 +                       goto fail; \
7426 +       } while (0)
7427 +
7428 +/**
7429 + * sd_activate_net_entry - ignores/skips net entries if the they are present
7430 + * in the data stream.
7431 + * @e: extent information
7432 + */
7433 +static inline int sd_activate_net_entry(struct sd_ext *e)
7434 +{
7435 +       SD_READ_X(e, SD_STRUCT, NULL, "ne");
7436 +       SD_READ_X(e, SD_U32, NULL, NULL);
7437 +       SD_READ_X(e, SD_U32, NULL, NULL);
7438 +       SD_READ_X(e, SD_U32, NULL, NULL);
7439 +       SD_READ_X(e, SD_U16, NULL, NULL);
7440 +       SD_READ_X(e, SD_U16, NULL, NULL);
7441 +       SD_READ_X(e, SD_U32, NULL, NULL);
7442 +       SD_READ_X(e, SD_U32, NULL, NULL);
7443 +       SD_READ_X(e, SD_U16, NULL, NULL);
7444 +       SD_READ_X(e, SD_U16, NULL, NULL);
7445 +       /* interface name is optional so just ignore return code */
7446 +       sd_is_nameX(e, SD_DYN_STRING, NULL, NULL);
7447 +       SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
7448 +
7449 +       return 1;
7450 +fail:
7451 +       return 0;
7452 +}
7453 +
7454 +static inline struct sd_entry *sd_activate_file_entry(struct sd_ext *e)
7455 +{
7456 +       struct sd_entry *entry = NULL;
7457 +
7458 +       if (!(entry = alloc_sd_entry()))
7459 +               goto fail;
7460 +
7461 +       SD_READ_X(e, SD_STRUCT, NULL, "fe");
7462 +       SD_READ_X(e, SD_DYN_STRING, &entry->filename, NULL);
7463 +       SD_READ_X(e, SD_U32, &entry->mode, "file.mode");
7464 +       SD_READ_X(e, SD_U32, &entry->entry_type, "file.pattern_type");
7465 +
7466 +       entry->extradata = sdmatch_alloc(entry->entry_type);
7467 +       if (IS_ERR(entry->extradata)) {
7468 +               entry->extradata = NULL;
7469 +               goto fail;
7470 +       }
7471 +
7472 +       if (entry->extradata &&
7473 +           sdmatch_serialize(entry->extradata, e, sd_is_nameX) != 0) {
7474 +               goto fail;
7475 +       }
7476 +       SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
7477 +
7478 +       switch (entry->entry_type) {
7479 +       case sd_entry_literal:
7480 +               SD_DEBUG("%s: %s [no pattern] mode=0x%x\n",
7481 +                        __FUNCTION__,
7482 +                        entry->filename,
7483 +                        entry->mode);
7484 +               break;
7485 +       case sd_entry_tailglob:
7486 +               SD_DEBUG("%s: %s [tailglob] mode=0x%x\n",
7487 +                        __FUNCTION__,
7488 +                        entry->filename,
7489 +                        entry->mode);
7490 +               break;
7491 +       case sd_entry_pattern:
7492 +               SD_DEBUG("%s: %s mode=0x%x\n",
7493 +                        __FUNCTION__,
7494 +                        entry->filename,
7495 +                        entry->mode);
7496 +               break;
7497 +       default:
7498 +               SD_WARN("%s: INVALID entry_type %d\n",
7499 +                       __FUNCTION__,
7500 +                       (int)entry->entry_type);
7501 +               goto fail;
7502 +       }
7503 +
7504 +       return entry;
7505 +
7506 +fail:
7507 +       sdmatch_free(entry->extradata);
7508 +       free_sd_entry(entry);
7509 +       return NULL;
7510 +}
7511 +
7512 +static inline int check_rule_and_add(struct sd_entry *file_entry,
7513 +                                    struct sdprofile *profile,
7514 +                                    const char **message)
7515 +{
7516 +       /* verify consistency of x, px, ix, ux for entry against
7517 +          possible duplicates for this entry */
7518 +       int mode = SD_EXEC_MODIFIER_MASK(file_entry->mode);
7519 +       int i;
7520 +
7521 +       if (mode && !(SD_MAY_EXEC & file_entry->mode)) {
7522 +               *message = "inconsistent rule, x modifiers without x";
7523 +               goto out;
7524 +       }
7525 +
7526 +       /* check that only 1 of the modifiers is set */
7527 +       if (mode && (mode & (mode - 1))) {
7528 +               *message = "inconsistent rule, multiple x modifiers";
7529 +               goto out;
7530 +       }
7531 +
7532 +       /* ix -> m (required so that target exec binary may map itself) */
7533 +       if (mode & SD_EXEC_INHERIT)
7534 +               file_entry->mode |= SD_EXEC_MMAP;
7535 +
7536 +       list_add(&file_entry->list, &profile->file_entry);
7537 +       profile->num_file_entries++;
7538 +
7539 +       mode = file_entry->mode;
7540 +
7541 +       /* Handle partitioned lists
7542 +        * Chain entries onto sublists based on individual
7543 +        * permission bits. This allows more rapid searching.
7544 +        */
7545 +       for (i = 0; i <= POS_SD_FILE_MAX; i++) {
7546 +               if (mode & (1 << i))
7547 +                       /* profile->file_entryp[i] initially set to
7548 +                        * NULL in alloc_sdprofile() */
7549 +                       list_add(&file_entry->listp[i],
7550 +                                &profile->file_entryp[i]);
7551 +       }
7552 +
7553 +       return 1;
7554 +
7555 +out:
7556 +       free_sd_entry(file_entry);
7557 +       return 0;
7558 +}
7559 +
7560 +#define SD_ENTRY_LIST(NAME) \
7561 +       do { \
7562 +       if (sd_is_nameX(e, SD_LIST, NULL, (NAME))) { \
7563 +               rulename = ""; \
7564 +               error_string = "Invalid file entry"; \
7565 +               while (!sd_is_nameX(e, SD_LISTEND, NULL, NULL)) { \
7566 +                       struct sd_entry *file_entry; \
7567 +                       file_entry = sd_activate_file_entry(e); \
7568 +                       if (!file_entry) \
7569 +                               goto fail; \
7570 +                       if (!check_rule_and_add(file_entry, profile, \
7571 +                                               &error_string)) { \
7572 +                               rulename = file_entry->filename; \
7573 +                               goto fail; \
7574 +                       } \
7575 +               } \
7576 +       } \
7577 +       } while (0)
7578 +
7579 +struct sdprofile *sd_activate_profile(struct sd_ext *e, ssize_t *error)
7580 +{
7581 +       struct sdprofile *profile = NULL;
7582 +       const char *rulename = "";
7583 +       const char *error_string = "Invalid Profile";
7584 +
7585 +       *error = -EPROTO;
7586 +
7587 +       profile = alloc_sdprofile();
7588 +       if (!profile) {
7589 +               error_string = "Could not allocate profile";
7590 +               *error = -ENOMEM;
7591 +               goto fail;
7592 +       }
7593 +
7594 +       /* check that we have the right struct being passed */
7595 +       SD_READ_X(e, SD_STRUCT, NULL, "profile");
7596 +       SD_READ_X(e, SD_DYN_STRING, &profile->name, NULL);
7597 +
7598 +       error_string = "Invalid flags";
7599 +       /* per profile debug flags (debug, complain, audit) */
7600 +       SD_READ_X(e, SD_STRUCT, NULL, "flags");
7601 +       SD_READ_X(e, SD_U32, &(profile->flags.debug), "profile.flags.debug");
7602 +       SD_READ_X(e, SD_U32, &(profile->flags.complain),
7603 +                 "profile.flags.complain");
7604 +       SD_READ_X(e, SD_U32, &(profile->flags.audit), "profile.flags.audit");
7605 +       SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
7606 +
7607 +       error_string = "Invalid capabilities";
7608 +       SD_READ_X(e, SD_U32, &(profile->capabilities), "profile.capabilities");
7609 +
7610 +       /* get the file entries. */
7611 +       SD_ENTRY_LIST("pgent");         /* pcre rules */
7612 +       SD_ENTRY_LIST("sgent");         /* simple globs */
7613 +       SD_ENTRY_LIST("fent");          /* regular file entries */
7614 +
7615 +       /* get the net entries */
7616 +       if (sd_is_nameX(e, SD_LIST, NULL, "net")) {
7617 +               error_string = "Invalid net entry";
7618 +               while (!sd_is_nameX(e, SD_LISTEND, NULL, NULL)) {
7619 +                       if (!sd_activate_net_entry(e))
7620 +                               goto fail;
7621 +               }
7622 +       }
7623 +       rulename = "";
7624 +
7625 +       /* get subprofiles */
7626 +       if (sd_is_nameX(e, SD_LIST, NULL, "hats")) {
7627 +               error_string = "Invalid profile hat";
7628 +               while (!sd_is_nameX(e, SD_LISTEND, NULL, NULL)) {
7629 +                       struct sdprofile *subprofile;
7630 +                       subprofile = sd_activate_profile(e, error);
7631 +                       if (!subprofile)
7632 +                               goto fail;
7633 +                       get_sdprofile(subprofile);
7634 +                       list_add(&subprofile->list, &profile->sub);
7635 +               }
7636 +       }
7637 +
7638 +       error_string = "Invalid end of profile";
7639 +       SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
7640 +
7641 +       return profile;
7642 +
7643 +fail:
7644 +       SD_WARN("%s: %s %s in profile %s\n", INTERFACE_ID, rulename,
7645 +               error_string, profile && profile->name ? profile->name
7646 +               : "unknown");
7647 +
7648 +       if (profile) {
7649 +               free_sdprofile(profile);
7650 +               profile = NULL;
7651 +       }
7652 +
7653 +       return NULL;
7654 +}
7655 +
7656 +void *sd_activate_top_profile(struct sd_ext *e, ssize_t *error)
7657 +{
7658 +       /* get the interface version */
7659 +       if (!sd_is_nameX(e, SD_U32, &e->version, "version")) {
7660 +               SD_WARN("%s: version missing\n", INTERFACE_ID);
7661 +               *error = -EPROTONOSUPPORT;
7662 +               goto out;
7663 +       }
7664 +
7665 +       /* check that the interface version is currently supported */
7666 +       if (e->version != 2) {
7667 +               SD_WARN("%s: unsupported interface version (%d)\n",
7668 +                       INTERFACE_ID, e->version);
7669 +               *error = -EPROTONOSUPPORT;
7670 +               goto out;
7671 +       }
7672 +
7673 +       return sd_activate_profile(e, error);
7674 +out:
7675 +       return NULL;
7676 +}
7677 +
7678 +ssize_t sd_file_prof_add(void *data, size_t size)
7679 +{
7680 +       struct sdprofile *profile = NULL;
7681 +
7682 +       struct sd_ext e = { data, data + size, data };
7683 +       ssize_t error;
7684 +
7685 +       profile = sd_activate_top_profile(&e, &error);
7686 +       if (!profile) {
7687 +               SD_DEBUG("couldn't activate profile\n");
7688 +               return error;
7689 +       }
7690 +
7691 +       if (!sd_profilelist_add(profile)) {
7692 +               SD_WARN("trying to add profile (%s) that already exists.\n",
7693 +                       profile->name);
7694 +               free_sdprofile(profile);
7695 +               return -EEXIST;
7696 +       }
7697 +
7698 +       return size;
7699 +}
7700 +
7701 +ssize_t sd_file_prof_repl(void *udata, size_t size)
7702 +{
7703 +       struct sd_taskreplace_data data;
7704 +       struct sd_ext e = { udata, udata + size, udata };
7705 +       ssize_t error;
7706 +
7707 +       data.new_profile = sd_activate_top_profile(&e, &error);
7708 +       if (!data.new_profile) {
7709 +               SD_DEBUG("couldn't activate profile\n");
7710 +               return error;
7711 +       }
7712 +       /* Grab reference to close race window (see comment below) */
7713 +       get_sdprofile(data.new_profile);
7714 +
7715 +       /* Replace the profile on the global profile list.
7716 +        * This list is used by all new exec's to find the correct profile.
7717 +        * If there was a previous profile, it is returned, else NULL.
7718 +        *
7719 +        * N.B sd_profilelist_replace does not drop the refcnt on
7720 +        * old_profile when removing it from the global list, otherwise it
7721 +        * could reach zero and be automatically free'd. We nust manually
7722 +        * drop it at the end of this function when we are finished with it.
7723 +        */
7724 +       data.old_profile = sd_profilelist_replace(data.new_profile);
7725 +
7726 +       /* RACE window here.
7727 +        * At this point another task could preempt us trying to replace
7728 +        * the SAME profile. If it makes it to this point,  it has removed
7729 +        * the original tasks new_profile from the global list and holds a
7730 +        * reference of 1 to it in it's old_profile.  If the new task
7731 +        * reaches the end of the function it will put old_profile causing
7732 +        * the profile to be deleted.
7733 +        * When the original task is rescheduled it will continue calling
7734 +        * sd_subdomainlist_iterate relabelling tasks with a profile
7735 +        * which points to free'd memory.
7736 +        */
7737 +
7738 +       /* If there was an old profile,  find all currently executing tasks
7739 +        * using this profile and replace the old profile with the new.
7740 +        */
7741 +       if (data.old_profile) {
7742 +               SD_DEBUG("%s: try to replace profile (%p)%s\n",
7743 +                        __FUNCTION__,
7744 +                        data.old_profile,
7745 +                        data.old_profile->name);
7746 +
7747 +               sd_subdomainlist_iterate(taskreplace_iter, (void *)&data);
7748 +
7749 +               /* it's off global list, and we are done replacing */
7750 +               put_sdprofile(data.old_profile);
7751 +       }
7752 +
7753 +       /* Free reference obtained above */
7754 +       put_sdprofile(data.new_profile);
7755 +
7756 +       return size;
7757 +}
7758 +
7759 +ssize_t sd_file_prof_remove(const char *name, size_t size)
7760 +{
7761 +       struct sdprofile *old_profile;
7762 +
7763 +       /* if the old profile exists it will be removed from the list and
7764 +        * a reference is returned.
7765 +        */
7766 +       old_profile = sd_profilelist_remove(name);
7767 +
7768 +       if (old_profile) {
7769 +               /* remove profile from any tasks using it */
7770 +               sd_subdomainlist_iterate(taskremove_iter, (void *)old_profile);
7771 +
7772 +               /* drop reference obtained by sd_profilelist_remove */
7773 +               put_sdprofile(old_profile);
7774 +       } else {
7775 +               SD_WARN("%s: trying to remove profile (%s) that "
7776 +                       "doesn't exist - skipping.\n", __FUNCTION__, name);
7777 +               return -ENOENT;
7778 +       }
7779 +
7780 +       return size;
7781 +}
7782 --- linux-2.6.16.29.orig/security/apparmor/module_interface.h   1969-12-31 16:00:00.000000000 -0800
7783 +++ linux-2.6.16.29/security/apparmor/module_interface.h        2006-10-12 21:11:15.000000000 -0700
7784 @@ -0,0 +1,37 @@
7785 +#ifndef __MODULEINTERFACE_H
7786 +#define __MODULEINTERFACE_H
7787 +
7788 +/* Codes of the types of basic structures that are understood */
7789 +#define SD_CODE_BYTE (sizeof(u8))
7790 +#define INTERFACE_ID "INTERFACE"
7791 +
7792 +#define SUBDOMAIN_INTERFACE_VERSION 2
7793 +
7794 +enum sd_code {
7795 +       SD_U8,
7796 +       SD_U16,
7797 +       SD_U32,
7798 +       SD_U64,
7799 +       SD_NAME,        /* same as string except it is items name */
7800 +       SD_DYN_STRING,
7801 +       SD_STATIC_BLOB,
7802 +       SD_STRUCT,
7803 +       SD_STRUCTEND,
7804 +       SD_LIST,
7805 +       SD_LISTEND,
7806 +       SD_OFFSET,
7807 +       SD_BAD
7808 +};
7809 +
7810 +/* sd_ext tracks the kernel buffer and read position in it.  The interface
7811 + * data is copied into a kernel buffer in subdomainfs and then handed off to
7812 + * the activate routines.
7813 + */
7814 +struct sd_ext {
7815 +       void *start;
7816 +       void *end;
7817 +       void *pos;      /* pointer to current position in the buffer */
7818 +       u32 version;
7819 +};
7820 +
7821 +#endif /* __MODULEINTERFACE_H */
7822 --- linux-2.6.16.29.orig/security/apparmor/procattr.c   1969-12-31 16:00:00.000000000 -0800
7823 +++ linux-2.6.16.29/security/apparmor/procattr.c        2006-10-12 21:11:15.000000000 -0700
7824 @@ -0,0 +1,329 @@
7825 +/*
7826 + *     Copyright (C) 2005 Novell/SUSE
7827 + *
7828 + *     This program is free software; you can redistribute it and/or
7829 + *     modify it under the terms of the GNU General Public License as
7830 + *     published by the Free Software Foundation, version 2 of the
7831 + *     License.
7832 + *
7833 + *     AppArmor /proc/pid/attr handling
7834 + */
7835 +
7836 +/* for isspace */
7837 +#include <linux/ctype.h>
7838 +
7839 +#include "apparmor.h"
7840 +#include "inline.h"
7841 +
7842 +size_t sd_getprocattr(struct subdomain *sd, char *str, size_t size)
7843 +{
7844 +       int error = -EACCES;    /* default to a perm denied */
7845 +       size_t len;
7846 +
7847 +       if (__sd_is_confined(sd)) {
7848 +               size_t lena, lenm, lenp = 0;
7849 +               const char *enforce_str = " (enforce)";
7850 +               const char *complain_str = " (complain)";
7851 +               const char *mode_str =
7852 +                       SUBDOMAIN_COMPLAIN(sd) ? complain_str : enforce_str;
7853 +
7854 +               lenm = strlen(mode_str);
7855 +
7856 +               lena = strlen(sd->active->name);
7857 +
7858 +               len = lena;
7859 +               if (sd->active != sd->profile) {
7860 +                       lenp = strlen(sd->profile->name);
7861 +                       len += (lenp + 1);      /* +1 for ^ */
7862 +               }
7863 +               /* DONT null terminate strings we output via proc */
7864 +               len += (lenm + 1);      /* for \n */
7865 +
7866 +               if (len <= size) {
7867 +                       if (lenp) {
7868 +                               memcpy(str, sd->profile->name, lenp);
7869 +                               str += lenp;
7870 +                               *str++ = '^';
7871 +                       }
7872 +
7873 +                       memcpy(str, sd->active->name, lena);
7874 +                       str += lena;
7875 +                       memcpy(str, mode_str, lenm);
7876 +                       str += lenm;
7877 +                       *str++ = '\n';
7878 +                       error = len;
7879 +               } else {
7880 +                       error = -ERANGE;
7881 +               }
7882 +       } else {
7883 +               const char *unconstrained_str = SD_UNCONSTRAINED "\n";
7884 +               len = strlen(unconstrained_str);
7885 +
7886 +               /* DONT null terminate strings we output via proc */
7887 +               if (len <= size) {
7888 +                       memcpy(str, unconstrained_str, len);
7889 +                       error = len;
7890 +               } else {
7891 +                       error = -ERANGE;
7892 +               }
7893 +       }
7894 +
7895 +       return error;
7896 +
7897 +}
7898 +int sd_setprocattr_changehat(char *hatinfo, size_t infosize)
7899 +{
7900 +       int error = -EINVAL;
7901 +       char *token = NULL, *hat, *smagic, *tmp;
7902 +       __u32 magic;
7903 +       int rc, len, consumed;
7904 +       unsigned long flags;
7905 +
7906 +       SD_DEBUG("%s: %p %zd\n", __FUNCTION__, hatinfo, infosize);
7907 +
7908 +       /* strip leading white space */
7909 +       while (infosize && isspace(*hatinfo)) {
7910 +               hatinfo++;
7911 +               infosize--;
7912 +       }
7913 +
7914 +       if (infosize == 0)
7915 +               goto out;
7916 +
7917 +       /*
7918 +        * Copy string to a new buffer so we can play with it
7919 +        * It may be zero terminated but we add a trailing 0
7920 +        * for 100% safety
7921 +        */
7922 +       token = kmalloc(infosize + 1, GFP_KERNEL);
7923 +
7924 +       if (!token) {
7925 +               error = -ENOMEM;
7926 +               goto out;
7927 +       }
7928 +
7929 +       memcpy(token, hatinfo, infosize);
7930 +       token[infosize] = 0;
7931 +
7932 +       /* error is INVAL until we have at least parsed something */
7933 +       error = -EINVAL;
7934 +
7935 +       tmp = token;
7936 +       while (*tmp && *tmp != '^') {
7937 +               tmp++;
7938 +       }
7939 +
7940 +       if (!*tmp || tmp == token) {
7941 +               SD_WARN("%s: Invalid input '%s'\n", __FUNCTION__, token);
7942 +               goto out;
7943 +       }
7944 +
7945 +       /* split magic and hat into two strings */
7946 +       *tmp = 0;
7947 +       smagic = token;
7948 +
7949 +       /*
7950 +        * Initially set consumed=strlen(magic), as if sscanf
7951 +        * consumes all input via the %x it will not process the %n
7952 +        * directive. Otherwise, if sscanf does not consume all the
7953 +        * input it will process the %n and update consumed.
7954 +        */
7955 +       consumed = len = strlen(smagic);
7956 +
7957 +       rc = sscanf(smagic, "%x%n", &magic, &consumed);
7958 +
7959 +       if (rc != 1 || consumed != len) {
7960 +               SD_WARN("%s: Invalid hex magic %s\n",
7961 +                       __FUNCTION__,
7962 +                       smagic);
7963 +               goto out;
7964 +       }
7965 +
7966 +       hat = tmp + 1;
7967 +
7968 +       if (!*hat)
7969 +               hat = NULL;
7970 +
7971 +       if (!hat && !magic) {
7972 +               SD_WARN("%s: Invalid input, NULL hat and NULL magic\n",
7973 +                       __FUNCTION__);
7974 +               goto out;
7975 +       }
7976 +
7977 +       SD_DEBUG("%s: Magic 0x%x Hat '%s'\n",
7978 +                __FUNCTION__, magic, hat ? hat : NULL);
7979 +
7980 +       write_lock_irqsave(&sd_lock, flags);
7981 +       error = sd_change_hat(hat, magic);
7982 +       write_unlock_irqrestore(&sd_lock, flags);
7983 +
7984 +out:
7985 +       if (token) {
7986 +               memset(token, 0, infosize);
7987 +               kfree(token);
7988 +       }
7989 +
7990 +       return error;
7991 +}
7992 +
7993 +int sd_setprocattr_setprofile(struct task_struct *p, char *profilename,
7994 +                             size_t profilesize)
7995 +{
7996 +       int error = -EINVAL;
7997 +       struct sdprofile *profile;
7998 +       struct subdomain *sd;
7999 +       char *name = NULL;
8000 +       unsigned long flags;
8001 +
8002 +       SD_DEBUG("%s: current %s(%d)\n",
8003 +                __FUNCTION__, current->comm, current->pid);
8004 +
8005 +       /* strip leading white space */
8006 +       while (profilesize && isspace(*profilename)) {
8007 +               profilename++;
8008 +               profilesize--;
8009 +       }
8010 +
8011 +       if (profilesize == 0)
8012 +               goto out;
8013 +
8014 +       /*
8015 +        * Copy string to a new buffer so we guarantee it is zero
8016 +        * terminated
8017 +        */
8018 +       name = kmalloc(profilesize + 1, GFP_KERNEL);
8019 +
8020 +       if (!name) {
8021 +               error = -ENOMEM;
8022 +               goto out;
8023 +       }
8024 +
8025 +       strncpy(name, profilename, profilesize);
8026 +       name[profilesize] = 0;
8027 +
8028 + repeat:
8029 +       if (strcmp(name, SD_UNCONSTRAINED) == 0)
8030 +               profile = null_profile;
8031 +       else
8032 +               profile = sd_profilelist_find(name);
8033 +
8034 +       if (!profile) {
8035 +               SD_WARN("%s: Unable to switch task %s(%d) to profile '%s'. "
8036 +                       "No such profile.\n",
8037 +                       __FUNCTION__,
8038 +                       p->comm, p->pid,
8039 +                       name);
8040 +
8041 +               error = -EINVAL;
8042 +               goto out;
8043 +       }
8044 +
8045 +
8046 +       write_lock_irqsave(&sd_lock, flags);
8047 +
8048 +       sd = SD_SUBDOMAIN(p->security);
8049 +
8050 +       /* switch to unconstrained */
8051 +       if (profile == null_profile) {
8052 +               if (__sd_is_confined(sd)) {
8053 +                       SD_WARN("%s: Unconstraining task %s(%d) "
8054 +                               "profile %s active %s\n",
8055 +                               __FUNCTION__,
8056 +                               p->comm, p->pid,
8057 +                               sd->profile->name,
8058 +                               sd->active->name);
8059 +
8060 +                       sd_switch_unconfined(sd);
8061 +               } else {
8062 +                       SD_WARN("%s: task %s(%d) "
8063 +                               "is already unconstrained\n",
8064 +                               __FUNCTION__, p->comm, p->pid);
8065 +               }
8066 +       } else {
8067 +               if (!sd) {
8068 +                       /* this task was created before module was
8069 +                        * loaded, allocate a subdomain
8070 +                        */
8071 +                       SD_WARN("%s: task %s(%d) has no subdomain\n",
8072 +                               __FUNCTION__, p->comm, p->pid);
8073 +
8074 +                       /* unlock so we can safely GFP_KERNEL */
8075 +                       write_unlock_irqrestore(&sd_lock, flags);
8076 +
8077 +                       sd = alloc_subdomain(p);
8078 +                       if (!sd) {
8079 +                               SD_WARN("%s: Unable to allocate subdomain for "
8080 +                                       "task %s(%d). Cannot confine task to "
8081 +                                       "profile %s\n",
8082 +                                       __FUNCTION__,
8083 +                                       p->comm, p->pid,
8084 +                                       name);
8085 +
8086 +                               error = -ENOMEM;
8087 +                               put_sdprofile(profile);
8088 +
8089 +                               goto out;
8090 +                       }
8091 +
8092 +                       write_lock_irqsave(&sd_lock, flags);
8093 +                       if (!p->security) {
8094 +                               p->security = sd;
8095 +                       } else { /* race */
8096 +                               free_subdomain(sd);
8097 +                               sd = SD_SUBDOMAIN(p->security);
8098 +                       }
8099 +               }
8100 +
8101 +               /* ensure the profile hasn't been replaced */
8102 +
8103 +               if (unlikely(profile->isstale)) {
8104 +                       WARN_ON(profile == null_complain_profile);
8105 +
8106 +                       /* drop refcnt obtained from earlier get_sdprofile */
8107 +                       put_sdprofile(profile);
8108 +                       profile = sd_profilelist_find(name);
8109 +
8110 +                       if (!profile) {
8111 +                               /* Race, profile was removed. */
8112 +                               write_unlock_irqrestore(&sd_lock, flags);
8113 +                               goto repeat;
8114 +                       }
8115 +               }
8116 +
8117 +               /* we do not do a normal task replace since we are not
8118 +                * replacing with the same profile.
8119 +                * If existing process is in a hat, it will be moved
8120 +                * into the new parent profile, even if this new
8121 +                * profile has a identical named hat.
8122 +                */
8123 +
8124 +               SD_WARN("%s: Switching task %s(%d) "
8125 +                       "profile %s active %s to new profile %s\n",
8126 +                       __FUNCTION__,
8127 +                       p->comm, p->pid,
8128 +                       sd->profile ? sd->profile->name : SD_UNCONSTRAINED,
8129 +                       sd->active ? sd->profile->name : SD_UNCONSTRAINED,
8130 +                       name);
8131 +
8132 +               sd_switch(sd, profile, profile);
8133 +
8134 +               put_sdprofile(profile); /* drop ref we obtained above
8135 +                                        * from sd_profilelist_find
8136 +                                        */
8137 +
8138 +               /* Reset magic in case we were in a subhat before
8139 +                * This is the only case where we zero the magic after
8140 +                * calling sd_switch
8141 +                */
8142 +               sd->sd_hat_magic = 0;
8143 +       }
8144 +
8145 +       write_unlock_irqrestore(&sd_lock, flags);
8146 +
8147 +       error = 0;
8148 +
8149 +out:
8150 +       kfree(name);
8151 +
8152 +       return error;
8153 +}
8154 --- linux-2.6.16.29.orig/security/apparmor/shared.h     1969-12-31 16:00:00.000000000 -0800
8155 +++ linux-2.6.16.29/security/apparmor/shared.h  2006-10-12 21:11:15.000000000 -0700
8156 @@ -0,0 +1,47 @@
8157 +/*
8158 + *     Copyright (C) 2000, 2001, 2004, 2005 Novell/SUSE
8159 + *
8160 + *     Immunix AppArmor LSM
8161 + *
8162 + *     This program is free software; you can redistribute it and/or
8163 + *     modify it under the terms of the GNU General Public License as
8164 + *     published by the Free Software Foundation, version 2 of the
8165 + *     License.
8166 + */
8167 +
8168 +#ifndef _SHARED_H
8169 +#define _SHARED_H
8170 +
8171 +/* start of system offsets */
8172 +#define POS_SD_FILE_MIN                        0
8173 +#define POS_SD_MAY_EXEC                        POS_SD_FILE_MIN
8174 +#define POS_SD_MAY_WRITE               (POS_SD_MAY_EXEC + 1)
8175 +#define POS_SD_MAY_READ                        (POS_SD_MAY_WRITE + 1)
8176 +/* not used by Subdomain */
8177 +#define POS_SD_MAY_APPEND              (POS_SD_MAY_READ + 1)
8178 +/* end of system offsets */
8179 +
8180 +#define POS_SD_MAY_LINK                        (POS_SD_MAY_APPEND + 1)
8181 +#define POS_SD_EXEC_INHERIT            (POS_SD_MAY_LINK + 1)
8182 +#define POS_SD_EXEC_UNCONSTRAINED      (POS_SD_EXEC_INHERIT + 1)
8183 +#define POS_SD_EXEC_PROFILE            (POS_SD_EXEC_UNCONSTRAINED + 1)
8184 +#define POS_SD_EXEC_MMAP               (POS_SD_EXEC_PROFILE + 1)
8185 +#define POS_SD_EXEC_UNSAFE             (POS_SD_EXEC_MMAP + 1)
8186 +#define POS_SD_FILE_MAX                        POS_SD_EXEC_UNSAFE
8187 +
8188 +/* Modeled after MAY_READ, MAY_WRITE, MAY_EXEC def'ns */
8189 +#define SD_MAY_EXEC                    (0x01 << POS_SD_MAY_EXEC)
8190 +#define SD_MAY_WRITE                   (0x01 << POS_SD_MAY_WRITE)
8191 +#define SD_MAY_READ                    (0x01 << POS_SD_MAY_READ)
8192 +#define SD_MAY_LINK                    (0x01 << POS_SD_MAY_LINK)
8193 +#define SD_EXEC_INHERIT                        (0x01 << POS_SD_EXEC_INHERIT)
8194 +#define SD_EXEC_UNCONSTRAINED          (0x01 << POS_SD_EXEC_UNCONSTRAINED)
8195 +#define SD_EXEC_PROFILE                        (0x01 << POS_SD_EXEC_PROFILE)
8196 +#define SD_EXEC_MMAP                   (0x01 << POS_SD_EXEC_MMAP)
8197 +#define SD_EXEC_UNSAFE                 (0x01 << POS_SD_EXEC_UNSAFE)
8198 +
8199 +#define SD_EXEC_MODIFIERS              (SD_EXEC_INHERIT | \
8200 +                                        SD_EXEC_UNCONSTRAINED | \
8201 +                                        SD_EXEC_PROFILE)
8202 +
8203 +#endif /* _SHARED_H */
8204 --- linux-2.6.16.29.orig/security/Kconfig       2006-10-12 21:11:17.000000000 -0700
8205 +++ linux-2.6.16.29/security/Kconfig    2006-10-12 21:11:14.000000000 -0700
8206 @@ -100,6 +100,7 @@ config SECURITY_SECLVL
8207           If you are unsure how to answer this question, answer N.
8208  
8209  source security/selinux/Kconfig
8210 +source security/apparmor/Kconfig
8211  
8212  endmenu
8213  
8214 --- linux-2.6.16.29.orig/security/Makefile      2006-10-12 21:11:17.000000000 -0700
8215 +++ linux-2.6.16.29/security/Makefile   2006-10-12 21:11:14.000000000 -0700
8216 @@ -4,6 +4,7 @@
8217  
8218  obj-$(CONFIG_KEYS)                     += keys/
8219  subdir-$(CONFIG_SECURITY_SELINUX)      += selinux
8220 +obj-$(CONFIG_SECURITY_APPARMOR)                += commoncap.o apparmor/
8221  
8222  # if we don't select a security model, use the default capabilities
8223  ifneq ($(CONFIG_SECURITY),y)
This page took 0.719695 seconds and 3 git commands to generate.