2 include/linux/audit.h | 5
3 include/linux/namespace.h | 3
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(-)
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);
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
45 #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
46 #define AUDIT_AVC_PATH 1402 /* dentry, vfsmount pair from avc */
48 +#define AUDIT_SD 1500 /* AppArmor (SubDomain) audit */
50 #define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
53 @@ -265,6 +267,9 @@ extern void audit_log(struct audit_
54 __attribute__((format(printf,4,5)));
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,
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
66 #include <linux/mount.h>
67 #include <linux/sched.h>
69 +/* exported for AppArmor (SubDomain) */
70 +extern struct rw_semaphore namespace_sem;
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,
83 +void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
88 @@ -895,3 +895,11 @@ void audit_log(struct audit_context *ctx
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
103 +# Makefile for AppArmor aamatch submodule
106 +obj-$(CONFIG_SECURITY_APPARMOR) += aamatch_pcre.o
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
113 + * Copyright (C) 2002-2005 Novell/SUSE
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
120 + * AppArmor submodule (match) prototypes
126 +#include "../module_interface.h"
127 +#include "../apparmor.h"
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").
136 + * sdmatch_serialize
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.
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.
148 +typedef int (*sdmatch_serializecb)
149 + (struct sd_ext *, enum sd_code, void *, const char *);
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)
156 +extern void* sdmatch_alloc(enum entry_t entry_type);
159 + * sdmatch_free: release data allocated by sdmatch_alloc
160 + * @entry_extradata: data previously allocated by sdmatch_alloc
162 +extern void sdmatch_free(void *entry_extradata);
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)
169 +extern const char* sdmatch_features(void);
172 + * sdmatch_serialize: serialize extradata
173 + * @entry_extradata: data previously allocated by sdmatch_alloc
175 + * @cb: callback fn (consume incoming data stream)
176 + * Return value: 0 success, -ve error
178 +extern int sdmatch_serialize(void *entry_extradata, struct sd_ext *e,
179 + sdmatch_serializecb cb);
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
189 +extern unsigned int sdmatch_match(const char *pathname, const char *entry_name,
190 + enum entry_t entry_type,
191 + void *entry_extradata);
195 + * sd_getentry_type - return string representation of entry_t
196 + * @etype: entry type
198 +static inline const char *sd_getentry_type(enum entry_t etype)
200 + const char *etype_names[] = {
201 + "sd_entry_literal",
202 + "sd_entry_tailglob",
203 + "sd_entry_pattern",
207 + if (etype >= sd_entry_invalid) {
208 + etype = sd_entry_invalid;
211 + return etype_names[etype];
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
221 +static inline int sdmatch_match_common(const char *path,
222 + const char *entry_name,
223 + enum entry_t etype)
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);
235 + SD_WARN("%s: Invalid entry_t %d\n", __FUNCTION__, etype);
240 + SD_DEBUG("%s(%d): %s %s [%s]\n",
241 + __FUNCTION__, retval, path, entry_name,
242 + sd_getentry_type(etype));
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
253 + * Copyright (C) 2002-2005 Novell/SUSE
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
260 + * http://forge.novell.com/modules/xfmod/project/?apparmor
262 + * AppArmor aamatch submodule (w/ pattern expansion).
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.
269 +#include <linux/module.h>
271 +#include "pcre_exec.h"
272 +#include "pcre_tables.h"
274 +static const char *features="literal tailglob pattern=pcre";
276 +struct sdmatch_entry
282 +void* sdmatch_alloc(enum entry_t entry_type)
286 + if (entry_type == sd_entry_pattern) {
287 + ptr = kmalloc(sizeof(struct sdmatch_entry), GFP_KERNEL);
289 + memset(ptr, 0, sizeof(struct sdmatch_entry));
291 + ptr=ERR_PTR(-ENOMEM);
292 + } else if (entry_type != sd_entry_literal &&
293 + entry_type != sd_entry_tailglob) {
294 + ptr = ERR_PTR(-EINVAL);
300 +void sdmatch_free(void *ptr)
303 + struct sdmatch_entry *ed = (struct sdmatch_entry *) ptr;
304 + kfree(ed->pattern);
305 + kfree(ed->compiled); /* allocated by SD_READ_X */
310 +const char *sdmatch_features(void)
315 +int sdmatch_serialize(void *entry_extradata, struct sd_ext *e,
316 + sdmatch_serializecb cb)
318 +#define SD_READ_X(E, C, D, N) \
320 + if (!cb((E), (C), (D), (N))) { \
327 + u32 size, magic, opts;
329 + struct sdmatch_entry *ed = (struct sdmatch_entry *) entry_extradata;
334 + SD_READ_X(e, SD_DYN_STRING, &ed->pattern, NULL);
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");
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) {
352 + memset(ed->compiled, 0, size + sizeof(pcre));
353 + ed->compiled->magic_number = magic;
354 + ed->compiled->size = size + sizeof(pcre);
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;
367 + SD_READ_X(e, SD_STATIC_BLOB, &ed->compiled->code[1], NULL);
369 + SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
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;
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;
386 +unsigned int sdmatch_match(const char *pathname, const char *entry_name,
387 + enum entry_t entry_type, void *entry_extradata)
391 + if (entry_type == sd_entry_pattern) {
393 + struct sdmatch_entry *ed =
394 + (struct sdmatch_entry *) entry_extradata;
396 + pcreret = pcre_exec(ed->compiled, NULL,
397 + pathname, strlen(pathname),
400 + ret = (pcreret >= 0);
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);
406 + ret = sdmatch_match_common(pathname, entry_name, entry_type);
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);
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
425 + * This is a modified version of pcre.c containing only the code/data
426 + * required to support pcre_exec()
430 +/*************************************************
431 +* Perl-Compatible Regular Expressions *
432 +*************************************************/
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.
439 +Written by: Philip Hazel <ph10@cam.ac.uk>
441 + Copyright (c) 1997-2001 University of Cambridge
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
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.
452 +2. The origin of this software must not be misrepresented, either by
453 + explicit claim or by omission.
455 +3. Altered versions must be plainly marked as such, and must not be
456 + misrepresented as being the original software.
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 +-----------------------------------------------------------------------------
465 +/* Define DEBUG to get debugging output on stdout. */
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... */
474 +#define DPRINTF(p) PCRE_PRINTF p
476 +#define DPRINTF(p) /*nothing*/
479 +/* Include the internals header, which itself includes Standard C headers plus
480 +the external pcre header. */
482 +#include "pcre_exec.h"
485 +/* ---- CODE DELETED ---- */
488 +/* Min and max values for the common repeats; for the maxima, 0 => infinity */
490 +static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
491 +static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
494 +/* ---- CODE DELETED ---- */
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. */
502 +typedef struct eptrblock {
503 + struct eptrblock *prev;
504 + const uschar *saved_eptr;
507 +/* Flag bits for the match() function */
509 +#define match_condassert 0x01 /* Called to check a condition assertion */
510 +#define match_isgroup 0x02 /* Set if start of bracketed group */
513 +/* ---- CODE DELETED ---- */
516 +/*************************************************
517 + * * Global variables *
518 + * *************************************************/
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. */
526 +static void *kern_malloc(size_t sz)
528 + return kmalloc(sz, GFP_KERNEL);
530 +void *(*pcre_malloc)(size_t) = kern_malloc;
531 +void (*pcre_free)(const void *) = kfree;
533 +void *(*pcre_malloc)(size_t) = malloc;
534 +void (*pcre_free)(const void *) = free;
538 +/*************************************************
539 + * * Macros and tables for character handling *
540 + * *************************************************/
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. */
546 +#ifndef SUPPORT_UTF8
547 +#define GETCHARINC(c, eptr) c = *eptr++;
548 +#define GETCHARLEN(c, eptr, len) c = *eptr;
549 +#define BACKCHAR(eptr)
552 +/* ---- CODE DELETED ---- */
555 +/*************************************************
556 +* Debugging function to print chars *
557 +*************************************************/
559 +/* Print a sequence of chars in printable format, stopping at the end of the
560 +subject if the requested.
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
572 +pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
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);
581 +/* ---- CODE DELETED ---- */
584 +/*************************************************
585 +* Match a back-reference *
586 +*************************************************/
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.
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
598 +Returns: TRUE if matched
602 +match_ref(int offset, register const uschar *eptr, int length, match_data *md,
603 + unsigned long int ims)
605 +const uschar *p = md->start_subject + md->offset_vector[offset];
608 +if (eptr >= md->end_subject)
609 + PCRE_PRINTF("matching subject <null>");
612 + PCRE_PRINTF("matching subject ");
613 + pchars(eptr, length, TRUE, md);
615 +PCRE_PRINTF(" against backref ");
616 +pchars(p, length, FALSE, md);
620 +/* Always fail if not enough characters left */
622 +if (length > md->end_subject - eptr) return FALSE;
624 +/* Separate the caselesss case for speed */
626 +if ((ims & PCRE_CASELESS) != 0)
628 + while (length-- > 0)
629 + if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
632 + { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
638 +/*************************************************
639 +* Match from current position *
640 +*************************************************/
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
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
656 + match_condassert - this is an assertion condition
657 + match_isgroup - this is the start of a bracketed group
659 +Returns: TRUE if matched
663 +match(register const uschar *eptr, register const uschar *ecode,
664 + int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
667 +unsigned long int original_ims = ims; /* Save for resetting on ')' */
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
675 +if ((flags & match_isgroup) != 0)
677 + newptrb.prev = eptrb;
678 + newptrb.saved_eptr = eptr;
682 +/* Now start processing the operations. */
686 + int op = (int)*ecode;
687 + int min, max, ctype;
690 + BOOL minimize = FALSE;
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
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
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. */
709 + int number = op - OP_BRA;
711 + /* For extended extraction brackets (large number), we have to fish out the
712 + number from a dummy opcode at the start. */
714 + if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5];
715 + offset = number << 1;
718 + PCRE_PRINTF("start bracket %d subject=", number);
719 + pchars(eptr, 16, TRUE, md);
723 + if (offset < md->offset_max)
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];
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;
734 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
736 + ecode += (ecode[1] << 8) + ecode[2];
738 + while (*ecode == OP_ALT);
740 + DPRINTF(("bracket %d failed\n", number));
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;
749 + /* Insufficient room for saving captured contents */
754 + /* Other types of node can be handled by a switch */
758 + case OP_BRA: /* Non-capturing bracket: optimized */
759 + DPRINTF(("start bracket 0\n"));
762 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
764 + ecode += (ecode[1] << 8) + ecode[2];
766 + while (*ecode == OP_ALT);
767 + DPRINTF(("bracket 0 failed\n"));
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. */
776 + if (ecode[3] == OP_CREF) /* Condition is extraction test */
778 + int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled ref number */
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);
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. */
790 + if (match(eptr, ecode+3, offset_top, md, ims, NULL,
791 + match_condassert | match_isgroup))
793 + ecode += 3 + (ecode[4] << 8) + ecode[5];
794 + while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
796 + else ecode += (ecode[1] << 8) + ecode[2];
797 + return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
799 + /* Control never reaches here */
801 + /* Skip over conditional reference or large extraction number data if
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. */
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 */
818 + /* Change option settings */
823 + DPRINTF(("ims set to %02lx\n", ims));
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. */
833 + case OP_ASSERTBACK:
836 + if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break;
837 + ecode += (ecode[1] << 8) + ecode[2];
839 + while (*ecode == OP_ALT);
840 + if (*ecode == OP_KET) return FALSE;
842 + /* If checking an assertion for a condition, return TRUE. */
844 + if ((flags & match_condassert) != 0) return TRUE;
846 + /* Continue from after the assertion, updating the offsets high water
847 + mark, since extracts may have been taken during the assertion. */
849 + do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
851 + offset_top = md->end_offset_top;
854 + /* Negative assertion: all branches must fail to match */
856 + case OP_ASSERT_NOT:
857 + case OP_ASSERTBACK_NOT:
860 + if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup))
862 + ecode += (ecode[1] << 8) + ecode[2];
864 + while (*ecode == OP_ALT);
866 + if ((flags & match_condassert) != 0) return TRUE;
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. */
878 + c = (ecode[1] << 8) + ecode[2];
879 + for (i = 0; i < c; i++)
885 + eptr -= (ecode[1] << 8) + ecode[2];
888 + if (eptr < md->start_subject) return FALSE;
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
910 + c = md->offset_max;
912 + if (c < 16) save = stacksave; else
914 + save = (int *)(pcre_malloc)((c+1) * sizeof(int));
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,
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;
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. */
935 + offset_top = md->end_offset_top;
936 + eptr = md->end_match_ptr;
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
950 + const uschar *prev = ecode;
951 + const uschar *saved_eptr = eptr;
955 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
957 + ecode += (ecode[1] << 8) + ecode[2];
959 + while (*ecode == OP_ALT);
961 + /* If hit the end of the group (which could be repeated), fail */
963 + if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
965 + /* Continue as from after the assertion, updating the offsets high water
966 + mark, since extracts may have been taken. */
968 + do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
970 + offset_top = md->end_offset_top;
971 + eptr = md->end_match_ptr;
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. */
979 + if (*ecode == OP_KET || eptr == saved_eptr)
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
990 + if (ecode[3] == OP_OPT)
992 + ims = (ims & ~PCRE_IMS) | ecode[4];
993 + DPRINTF(("ims set to %02lx at group repeat\n", ims));
996 + if (*ecode == OP_KETRMIN)
998 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
999 + match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
1002 + else /* OP_KETRMAX */
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;
1010 + /* An alternation is the end of a branch; scan along to find the end of the
1011 + bracketed group and go to there. */
1014 + do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
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. */
1025 + const uschar *next = ecode+1;
1026 + if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup))
1028 + do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
1033 + case OP_BRAMINZERO:
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))
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. */
1052 + const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
1053 + const uschar *saved_eptr = eptrb->saved_eptr;
1055 + eptrb = eptrb->prev; /* Back up the stack of bracket start pointers */
1057 + if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
1058 + *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
1061 + md->end_match_ptr = eptr; /* For ONCE */
1062 + md->end_offset_top = offset_top;
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. */
1070 + if (*prev != OP_COND)
1073 + int number = *prev - OP_BRA;
1075 + /* For extended extraction brackets (large number), we have to fish out
1076 + the number from a dummy opcode at the start. */
1078 + if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5];
1079 + offset = number << 1;
1082 + PCRE_PRINTF("end bracket %d", number);
1083 + PCRE_PRINTF("\n");
1088 + if (offset >= md->offset_max) md->offset_overflow = TRUE; else
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;
1098 + /* Reset the value of the ims flags, in case they got changed during
1101 + ims = original_ims;
1102 + DPRINTF(("ims reset to %02lx\n", ims));
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. */
1110 + if (*ecode == OP_KET || eptr == saved_eptr)
1116 + /* The repeating kets try the rest of the pattern or restart from the
1117 + preceding bracket, in the appropriate order. */
1119 + if (*ecode == OP_KETRMIN)
1121 + if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
1122 + match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
1125 + else /* OP_KETRMAX */
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;
1133 + /* Start of subject unless notbol, or after internal newline if multiline */
1136 + if (md->notbol && eptr == md->start_subject) return FALSE;
1137 + if ((ims & PCRE_MULTILINE) != 0)
1139 + if (eptr != md->start_subject && eptr[-1] != NEWLINE) return FALSE;
1143 + /* ... else fall through */
1145 + /* Start of subject assertion */
1148 + if (eptr != md->start_subject) return FALSE;
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. */
1156 + if ((ims & PCRE_MULTILINE) != 0)
1158 + if (eptr < md->end_subject) { if (*eptr != NEWLINE) return FALSE; }
1159 + else { if (md->noteol) return FALSE; }
1165 + if (md->noteol) return FALSE;
1168 + if (eptr < md->end_subject - 1 ||
1169 + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
1175 + /* ... else fall through */
1177 + /* End of subject assertion (\z) */
1180 + if (eptr < md->end_subject) return FALSE;
1184 + /* End of subject or ending \n assertion (\Z) */
1187 + if (eptr < md->end_subject - 1 ||
1188 + (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
1192 + /* Word boundary assertions */
1194 + case OP_NOT_WORD_BOUNDARY:
1195 + case OP_WORD_BOUNDARY:
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)
1207 + /* Match a single character type; inline for speed */
1210 + if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE)
1212 + if (eptr++ >= md->end_subject) return FALSE;
1213 +#ifdef SUPPORT_UTF8
1215 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1220 + case OP_NOT_DIGIT:
1221 + if (eptr >= md->end_subject ||
1222 + (md->ctypes[*eptr++] & ctype_digit) != 0)
1228 + if (eptr >= md->end_subject ||
1229 + (md->ctypes[*eptr++] & ctype_digit) == 0)
1234 + case OP_NOT_WHITESPACE:
1235 + if (eptr >= md->end_subject ||
1236 + (md->ctypes[*eptr++] & ctype_space) != 0)
1241 + case OP_WHITESPACE:
1242 + if (eptr >= md->end_subject ||
1243 + (md->ctypes[*eptr++] & ctype_space) == 0)
1248 + case OP_NOT_WORDCHAR:
1249 + if (eptr >= md->end_subject ||
1250 + (md->ctypes[*eptr++] & ctype_word) != 0)
1256 + if (eptr >= md->end_subject ||
1257 + (md->ctypes[*eptr++] & ctype_word) == 0)
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
1273 + int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */
1274 + ecode += 3; /* Advance past item */
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
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];
1285 + /* Set up for repetition, or handle the non-repeated case */
1290 + case OP_CRMINSTAR:
1292 + case OP_CRMINPLUS:
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;
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;
1311 + default: /* No repeat follows */
1312 + if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
1314 + continue; /* With the main loop */
1317 + /* If the length of the reference is zero, just continue with the
1320 + if (length == 0) continue;
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. */
1326 + for (i = 1; i <= min; i++)
1328 + if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
1332 + /* If min = max, continue at the same level without recursion.
1333 + They are not both allowed to be zero. */
1335 + if (min == max) continue;
1337 + /* If minimizing, keep trying and advancing the pointer */
1341 + for (i = min;; i++)
1343 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1345 + if (i >= max || !match_ref(offset, eptr, length, md, ims))
1349 + /* Control never gets here */
1352 + /* If maximizing, find the longest string and work backwards */
1356 + const uschar *pp = eptr;
1357 + for (i = min; i < max; i++)
1359 + if (!match_ref(offset, eptr, length, md, ims)) break;
1362 + while (eptr >= pp)
1364 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1371 + /* Control never gets here */
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. */
1381 + const uschar *data = ecode + 1; /* Save for matching */
1382 + ecode += 33; /* Advance past the item */
1387 + case OP_CRMINSTAR:
1389 + case OP_CRMINPLUS:
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;
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;
1408 + default: /* No repeat follows */
1413 + /* First, ensure the minimum number of matches are present. */
1415 + for (i = 1; i <= min; i++)
1417 + if (eptr >= md->end_subject) return FALSE;
1418 + GETCHARINC(c, eptr) /* Get character; increment eptr */
1420 +#ifdef SUPPORT_UTF8
1421 + /* We do not yet support class members > 255 */
1422 + if (c > 255) return FALSE;
1425 + if ((data[c/8] & (1 << (c&7))) != 0) continue;
1429 + /* If max == min we can continue with the main loop without the
1430 + need to recurse. */
1432 + if (min == max) continue;
1434 + /* If minimizing, keep testing the rest of the expression and advancing
1435 + the pointer while it matches the class. */
1439 + for (i = min;; i++)
1441 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1443 + if (i >= max || eptr >= md->end_subject) return FALSE;
1444 + GETCHARINC(c, eptr) /* Get character; increment eptr */
1446 +#ifdef SUPPORT_UTF8
1447 + /* We do not yet support class members > 255 */
1448 + if (c > 255) return FALSE;
1450 + if ((data[c/8] & (1 << (c&7))) != 0) continue;
1453 + /* Control never gets here */
1456 + /* If maximizing, find the longest possible run, then work backwards. */
1460 + const uschar *pp = eptr;
1462 + for (i = min; i < max; i++)
1464 + if (eptr >= md->end_subject) break;
1465 + GETCHARLEN(c, eptr, len) /* Get character, set length if UTF-8 */
1467 +#ifdef SUPPORT_UTF8
1468 + /* We do not yet support class members > 255 */
1469 + if (c > 255) break;
1471 + if ((data[c/8] & (1 << (c&7))) == 0) break;
1475 + while (eptr >= pp)
1477 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1480 +#ifdef SUPPORT_UTF8
1487 + /* Control never gets here */
1489 + /* Match a run of characters */
1493 + register int length = ecode[1];
1496 +#ifdef DEBUG /* Sigh. Some compilers never learn. */
1497 + if (eptr >= md->end_subject)
1498 + PCRE_PRINTF("matching subject <null> against pattern ");
1501 + PCRE_PRINTF("matching subject ");
1502 + pchars(eptr, length, TRUE, md);
1503 + PCRE_PRINTF(" against pattern ");
1505 + pchars(ecode, length, FALSE, md);
1506 + PCRE_PRINTF("\n");
1509 + if (length > md->end_subject - eptr) return FALSE;
1510 + if ((ims & PCRE_CASELESS) != 0)
1512 + while (length-- > 0)
1513 + if (md->lcc[*ecode++] != md->lcc[*eptr++])
1518 + while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
1523 + /* Match a single character repeatedly; different opcodes share code. */
1526 + min = max = (ecode[1] << 8) + ecode[2];
1533 + max = (ecode[1] << 8) + ecode[2];
1534 + minimize = *ecode == OP_MINUPTO;
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;
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
1555 + if (min > md->end_subject - eptr) return FALSE;
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. */
1566 + DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
1569 + if ((ims & PCRE_CASELESS) != 0)
1572 + for (i = 1; i <= min; i++)
1573 + if (c != md->lcc[*eptr++]) return FALSE;
1574 + if (min == max) continue;
1577 + for (i = min;; i++)
1579 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1581 + if (i >= max || eptr >= md->end_subject ||
1582 + c != md->lcc[*eptr++])
1585 + /* Control never gets here */
1589 + const uschar *pp = eptr;
1590 + for (i = min; i < max; i++)
1592 + if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
1595 + while (eptr >= pp)
1596 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1600 + /* Control never gets here */
1603 + /* Caseful comparisons */
1607 + for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
1608 + if (min == max) continue;
1611 + for (i = min;; i++)
1613 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1615 + if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
1617 + /* Control never gets here */
1621 + const uschar *pp = eptr;
1622 + for (i = min; i < max; i++)
1624 + if (eptr >= md->end_subject || c != *eptr) break;
1627 + while (eptr >= pp)
1628 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1633 + /* Control never gets here */
1635 + /* Match a negated single character */
1638 + if (eptr >= md->end_subject) return FALSE;
1640 + if ((ims & PCRE_CASELESS) != 0)
1642 + if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
1646 + if (*ecode++ == *eptr++) return FALSE;
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... */
1657 + min = max = (ecode[1] << 8) + ecode[2];
1659 + goto REPEATNOTCHAR;
1662 + case OP_NOTMINUPTO:
1664 + max = (ecode[1] << 8) + ecode[2];
1665 + minimize = *ecode == OP_NOTMINUPTO;
1667 + goto REPEATNOTCHAR;
1670 + case OP_NOTMINSTAR:
1672 + case OP_NOTMINPLUS:
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;
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
1686 + if (min > md->end_subject - eptr) return FALSE;
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. */
1697 + DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
1700 + if ((ims & PCRE_CASELESS) != 0)
1703 + for (i = 1; i <= min; i++)
1704 + if (c == md->lcc[*eptr++]) return FALSE;
1705 + if (min == max) continue;
1708 + for (i = min;; i++)
1710 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1712 + if (i >= max || eptr >= md->end_subject ||
1713 + c == md->lcc[*eptr++])
1716 + /* Control never gets here */
1720 + const uschar *pp = eptr;
1721 + for (i = min; i < max; i++)
1723 + if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
1726 + while (eptr >= pp)
1727 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1731 + /* Control never gets here */
1734 + /* Caseful comparisons */
1738 + for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
1739 + if (min == max) continue;
1742 + for (i = min;; i++)
1744 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
1746 + if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
1748 + /* Control never gets here */
1752 + const uschar *pp = eptr;
1753 + for (i = min; i < max; i++)
1755 + if (eptr >= md->end_subject || c == *eptr) break;
1758 + while (eptr >= pp)
1759 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
1764 + /* Control never gets here */
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. */
1770 + case OP_TYPEEXACT:
1771 + min = max = (ecode[1] << 8) + ecode[2];
1777 + case OP_TYPEMINUPTO:
1779 + max = (ecode[1] << 8) + ecode[2];
1780 + minimize = *ecode == OP_TYPEMINUPTO;
1785 + case OP_TYPEMINSTAR:
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;
1796 + /* Common code for all repeated single character type matches */
1799 + ctype = *ecode++; /* Code for the character type */
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. */
1808 + if (min > md->end_subject - eptr) return FALSE;
1809 + if (min > 0) switch(ctype)
1812 +#ifdef SUPPORT_UTF8
1815 + for (i = 1; i <= min; i++)
1817 + if (eptr >= md->end_subject ||
1818 + (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0))
1820 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1825 + /* Non-UTF8 can be faster */
1826 + if ((ims & PCRE_DOTALL) == 0)
1827 + { for (i = 1; i <= min; i++) if (*eptr++ == NEWLINE) return FALSE; }
1831 + case OP_NOT_DIGIT:
1832 + for (i = 1; i <= min; i++)
1833 + if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
1837 + for (i = 1; i <= min; i++)
1838 + if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
1841 + case OP_NOT_WHITESPACE:
1842 + for (i = 1; i <= min; i++)
1843 + if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
1846 + case OP_WHITESPACE:
1847 + for (i = 1; i <= min; i++)
1848 + if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
1851 + case OP_NOT_WORDCHAR:
1852 + for (i = 1; i <= min; i++)
1853 + if ((md->ctypes[*eptr++] & ctype_word) != 0)
1858 + for (i = 1; i <= min; i++)
1859 + if ((md->ctypes[*eptr++] & ctype_word) == 0)
1864 + /* If min = max, continue at the same level without recursing */
1866 + if (min == max) continue;
1868 + /* If minimizing, we have to test the rest of the pattern before each
1869 + subsequent match. */
1873 + for (i = min;; i++)
1875 + if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE;
1876 + if (i >= max || eptr >= md->end_subject) return FALSE;
1882 + if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return FALSE;
1883 +#ifdef SUPPORT_UTF8
1885 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1889 + case OP_NOT_DIGIT:
1890 + if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
1894 + if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
1897 + case OP_NOT_WHITESPACE:
1898 + if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
1901 + case OP_WHITESPACE:
1902 + if ((md->ctypes[c] & ctype_space) == 0) return FALSE;
1905 + case OP_NOT_WORDCHAR:
1906 + if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
1910 + if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
1914 + /* Control never gets here */
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). */
1922 + const uschar *pp = eptr;
1927 + /* Special code is required for UTF8, but when the maximum is unlimited
1928 + we don't need it. */
1930 +#ifdef SUPPORT_UTF8
1931 + if (md->utf8 && max < INT_MAX)
1933 + if ((ims & PCRE_DOTALL) == 0)
1935 + for (i = min; i < max; i++)
1937 + if (eptr >= md->end_subject || *eptr++ == NEWLINE) break;
1938 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1943 + for (i = min; i < max; i++)
1946 + while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
1952 + /* Non-UTF8 can be faster */
1953 + if ((ims & PCRE_DOTALL) == 0)
1955 + for (i = min; i < max; i++)
1957 + if (eptr >= md->end_subject || *eptr == NEWLINE) break;
1964 + if (c > md->end_subject - eptr) c = md->end_subject - eptr;
1969 + case OP_NOT_DIGIT:
1970 + for (i = min; i < max; i++)
1972 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
1979 + for (i = min; i < max; i++)
1981 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
1987 + case OP_NOT_WHITESPACE:
1988 + for (i = min; i < max; i++)
1990 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
1996 + case OP_WHITESPACE:
1997 + for (i = min; i < max; i++)
1999 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
2005 + case OP_NOT_WORDCHAR:
2006 + for (i = min; i < max; i++)
2008 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
2015 + for (i = min; i < max; i++)
2017 + if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
2024 + while (eptr >= pp)
2026 + if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
2028 +#ifdef SUPPORT_UTF8
2030 + while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--;
2035 + /* Control never gets here */
2037 + /* There's been some horrible disaster. */
2040 + DPRINTF(("Unknown opcode %d\n", *ecode));
2041 + md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
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
2049 + } /* End of main loop */
2050 +/* Control never reaches here */
2054 +/*************************************************
2055 +* Execute a Regular Expression *
2056 +*************************************************/
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.
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
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
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,
2083 +int resetcount, ocount;
2084 +int first_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;
2099 +if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
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;
2105 +anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
2106 +startline = (re->options & PCRE_STARTLINE) != 0;
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;
2113 +match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
2114 +match_block.utf8 = (re->options & PCRE_UTF8) != 0;
2116 +match_block.notbol = (options & PCRE_NOTBOL) != 0;
2117 +match_block.noteol = (options & PCRE_NOTEOL) != 0;
2118 +match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
2120 +match_block.errorcode = PCRE_ERROR_NOMATCH; /* Default error */
2122 +match_block.lcc = re->tables + lcc_offset;
2123 +match_block.ctypes = re->tables + ctypes_offset;
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. */
2129 +ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
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
2136 +ocount = offsetcount - (offsetcount % 3);
2138 +if (re->top_backref > 0 && re->top_backref >= ocount/3)
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"));
2146 +else match_block.offset_vector = offsets;
2148 +match_block.offset_end = ocount;
2149 +match_block.offset_max = (2*ocount)/3;
2150 +match_block.offset_overflow = FALSE;
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
2156 +resetcount = 2 + re->top_bracket * 2;
2157 +if (resetcount > offsetcount) resetcount = ocount;
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. */
2163 +if (match_block.offset_vector != NULL)
2165 + register int *iptr = match_block.offset_vector + ocount;
2166 + register int *iend = iptr - resetcount/2 + 1;
2167 + while (--iptr >= iend) *iptr = -1;
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. */
2178 + if ((re->options & PCRE_FIRSTSET) != 0)
2180 + first_char = re->first_char;
2181 + if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
2184 + if (!startline && extra != NULL &&
2185 + (extra->options & PCRE_STUDY_MAPPED) != 0)
2186 + start_bits = extra->start_bits;
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. */
2197 +if ((re->options & PCRE_REQCHSET) != 0)
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;
2204 +/* Loop for handling unanchored repeated matching attempts; for anchored regexs
2205 +the loop runs just once. */
2210 + register int *iptr = match_block.offset_vector;
2211 + register int *iend = iptr + resetcount;
2213 + /* Reset the maximum number of extractions we might see. */
2215 + while (iptr < iend) *iptr++ = -1;
2217 + /* Advance to a unique first char if possible */
2219 + if (first_char >= 0)
2221 + if ((ims & PCRE_CASELESS) != 0)
2222 + while (start_match < end_subject &&
2223 + match_block.lcc[*start_match] != first_char)
2226 + while (start_match < end_subject && *start_match != first_char)
2230 + /* Or to just after \n for a multiline match if possible */
2232 + else if (startline)
2234 + if (start_match > match_block.start_subject + start_offset)
2236 + while (start_match < end_subject && start_match[-1] != NEWLINE)
2241 + /* Or to a non-unique first char after study */
2243 + else if (start_bits != NULL)
2245 + while (start_match < end_subject)
2247 + register int c = *start_match;
2248 + if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
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");
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. */
2269 + if (req_char >= 0)
2271 + register const uschar *p = start_match + ((first_char >= 0)? 1 : 0);
2273 + /* We don't need to repeat the search if we haven't yet reached the
2274 + place we found it at last time. */
2276 + if (p > req_char_ptr)
2278 + /* Do a single test if no case difference is set up */
2280 + if (req_char == req_char2)
2282 + while (p < end_subject)
2284 + if (*p++ == req_char) { p--; break; }
2288 + /* Otherwise test for either case */
2292 + while (p < end_subject)
2294 + register int pp = *p++;
2295 + if (pp == req_char || pp == req_char2) { p--; break; }
2299 + /* If we can't find the required character, break the matching loop */
2301 + if (p >= end_subject) break;
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. */
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. */
2318 + match_block.start_match = start_match;
2319 + if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
2322 + /* Copy the offset information from temporary store if necessary */
2324 + if (using_temporary_offsets)
2326 + if (offsetcount >= 4)
2328 + memcpy(offsets + 2, match_block.offset_vector + 2,
2329 + (offsetcount - 2) * sizeof(int));
2330 + DPRINTF(("Copied offsets from temporary memory\n"));
2332 + if (match_block.end_offset_top > offsetcount)
2333 + match_block.offset_overflow = TRUE;
2335 + DPRINTF(("Freeing temporary memory\n"));
2336 + (pcre_free)(match_block.offset_vector);
2339 + rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
2341 + if (offsetcount < 2) rc = 0; else
2343 + offsets[0] = start_match - match_block.start_subject;
2344 + offsets[1] = match_block.end_match_ptr - match_block.start_subject;
2347 + DPRINTF((">>>> returning %d\n", rc));
2351 +/* This "while" is the end of the "do" above */
2353 +while (!anchored &&
2354 + match_block.errorcode == PCRE_ERROR_NOMATCH &&
2355 + start_match++ < end_subject);
2357 +if (using_temporary_offsets)
2359 + DPRINTF(("Freeing temporary memory\n"));
2360 + (pcre_free)(match_block.offset_vector);
2363 +DPRINTF((">>>> returning %d\n", match_block.errorcode));
2365 +return match_block.errorcode;
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
2373 + * This is a modified header file containing the definitions from
2374 + * pcre.h and internal.h required to support pcre_exec()
2378 +/*************************************************
2379 +* Perl-Compatible Regular Expressions *
2380 +*************************************************/
2382 +/* Copyright (c) 1997-2001 University of Cambridge */
2387 +/* ----- CODE ADDED ---- */
2390 +#include <linux/slab.h> // for kmalloc/kfree
2394 +#define PCRE_PRINTF printk
2395 +#define isprint(x) ((unsigned char)(x) >= 128 && (unsigned char)(x) <= 255)
2397 +#define PCRE_PRINTF printf
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. */
2405 +#define NEWLINE '\n'
2408 +/* ---- CODE DELETED ---- */
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
2425 +/* Exec-time and get-time error codes */
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)
2435 +/* ---- CODE DELETED ---- */
2439 +struct real_pcre; /* declaration; the definition is private */
2440 +struct real_pcre_extra; /* declaration; the definition is private */
2442 +typedef struct real_pcre pcre;
2443 +typedef struct real_pcre_extra pcre_extra;
2445 +/* ---- CODE DELETED ---- */
2447 +extern int pcre_exec(const pcre *, const pcre_extra *,
2448 + const char *, int, int, int, int *,
2451 +/* ---- CODE ADDED (from internal.h) ---- */
2453 +/* These are the public options that can change during matching. */
2455 +#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
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. */
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 */
2468 +/* Options for the "extra" block produced by pcre_study(). */
2470 +#define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */
2472 +/* Masks for identifying the public options which are permitted at compile
2473 +time, run time or study time, respectively. */
2475 +#define PUBLIC_EXEC_OPTIONS \
2476 + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
2478 +/* Magic number to provide a small check against being handed junk. */
2480 +#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
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. */
2492 + OP_END, /* End of pattern */
2494 + /* Values corresponding to backslashed metacharacters */
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 */
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 */
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 */
2521 + OP_UPTO, /* From 0 to n matches */
2523 + OP_EXACT, /* Exactly n matches */
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 */
2531 + OP_NOTUPTO, /* From 0 to n matches */
2533 + OP_NOTEXACT, /* Exactly n matches */
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 */
2541 + OP_TYPEUPTO, /* From 0 to n matches */
2543 + OP_TYPEEXACT, /* Exactly n matches */
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 */
2551 + OP_CRRANGE, /* These are different to the three seta above. */
2554 + OP_CLASS, /* Match a character class */
2555 + OP_REF, /* Match a back reference */
2556 + OP_RECURSE, /* Match this pattern recursively */
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. */
2563 + /* The assertions must come before ONCE and COND */
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 */
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. */
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) */
2578 + OP_BRAZERO, /* These two must remain together and in this */
2579 + OP_BRAMINZERO, /* order. */
2581 + OP_BRANUMBER, /* Used for extracting brackets whose number is greater
2582 + than can fit into an opcode. */
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. */
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
2595 +#define EXTRACT_BASIC_MAX 150
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. */
2604 +typedef unsigned char uschar;
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. */
2609 +typedef struct real_pcre {
2610 + unsigned long int magic_number;
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;
2621 +/* The real format of the extra block returned by pcre_study(). */
2623 +typedef struct real_pcre_extra {
2625 + uschar start_bits[32];
2628 +/* Structure for passing "static" information around between the functions
2629 +doing the matching, so that they are thread-safe. */
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 */
2652 +/* Bit definitions for entries in the pcre_ctypes table. */
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) */
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. */
2664 +#define cbit_length 320 /* Length of the cbits table */
2666 +/* Offsets of the various tables from the base tables pointer, and
2669 +#define lcc_offset 0
2670 +#define fcc_offset 256
2672 +#define fcc_offset 256
2673 +#define cbits_offset 512
2674 +#define ctypes_offset (cbits_offset + cbit_length)
2676 +/* ----- CODE ADDED ---- */
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
2684 +/*************************************************
2685 +* Perl-Compatible Regular Expressions *
2686 +*************************************************/
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.
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
2696 +static unsigned char pcre_default_tables[] = {
2698 +/* This table is a lower casing table. */
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,
2733 +/* This table is a case flipping table. */
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,
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. */
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
2824 +/* This table identifies various classes of character by individual bits:
2825 + 0x01 white space character
2827 + 0x04 decimal digit
2828 + 0x08 hexadecimal digit
2829 + 0x10 alphanumeric or '_'
2830 + 0x80 regular expression metacharacter or binary zero
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 */
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
2871 + * Copyright (C) 2005 Novell/SUSE
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
2878 + * AppArmor filesystem (part of securityfs)
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>
2887 +#include "apparmor.h"
2888 +#include "inline.h"
2889 +#include "aamatch/match.h"
2891 +#define SECFS_SD "apparmor"
2892 +static struct dentry *sdfs_dentry = NULL;
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);
2899 +static struct file_operations subdomainfs_profiles_fops = {
2900 + .open = sd_prof_open,
2902 + .llseek = seq_lseek,
2903 + .release = sd_prof_release,
2907 +static ssize_t sd_version_read(struct file *file, char __user *buf,
2908 + size_t size, loff_t *ppos);
2910 +static struct file_operations subdomainfs_version_fops = {
2911 + .read = sd_version_read,
2915 +static ssize_t sd_matching_read(struct file *file, char __user *buf,
2916 + size_t size, loff_t *ppos);
2918 +static struct file_operations subdomainfs_matching_fops = {
2919 + .read = sd_matching_read,
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);
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);
2935 +static struct file_operations subdomainfs_profile_load = {
2936 + .write = sd_profile_load
2939 +static struct file_operations subdomainfs_profile_replace = {
2940 + .write = sd_profile_replace
2943 +static struct file_operations subdomainfs_profile_remove = {
2944 + .write = sd_profile_remove
2949 +static u64 sd_control_get(void *data);
2950 +static void sd_control_set(void *data, u64 val);
2952 +DEFINE_SIMPLE_ATTRIBUTE(subdomainfs_control_fops, sd_control_get,
2953 + sd_control_set, "%lld\n");
2957 +/* table of static entries */
2959 +static struct root_entry {
2963 + struct file_operations *fops;
2966 + /* internal fields */
2967 + struct dentry *dentry;
2969 +} root_entries[] = {
2970 + /* our root, normally /sys/kernel/security/subdomain */
2971 + {SECFS_SD, S_IFDIR, 0550}, /* DO NOT EDIT/MOVE */
2973 + /* interface for obtaining list of profiles currently loaded */
2974 + {"profiles", S_IFREG, 0440, &subdomainfs_profiles_fops,
2977 + /* interface for obtaining version# of subdomain */
2978 + {"version", S_IFREG, 0440, &subdomainfs_version_fops,
2981 + /* interface for obtaining matching features supported */
2982 + {"matching", S_IFREG, 0440, &subdomainfs_matching_fops,
2985 + /* interface for loading/removing/replacing profiles */
2986 + {".load", S_IFREG, 0640, &subdomainfs_profile_load,
2988 + {".replace", S_IFREG, 0640, &subdomainfs_profile_replace,
2990 + {".remove", S_IFREG, 0640, &subdomainfs_profile_remove,
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},
3006 + {NULL, S_IFDIR, 0}
3009 +#define SDFS_DENTRY root_entries[0].dentry
3011 +static const unsigned int num_entries =
3012 + sizeof(root_entries) / sizeof(struct root_entry);
3016 +static int sd_prof_open(struct inode *inode, struct file *file)
3018 + return seq_open(file, &subdomainfs_profiles_op);
3022 +static int sd_prof_release(struct inode *inode, struct file *file)
3024 + return seq_release(inode, file);
3027 +static ssize_t sd_version_read(struct file *file, char __user *buf,
3028 + size_t size, loff_t *ppos)
3030 + const char *version = apparmor_version_nl();
3032 + return simple_read_from_buffer(buf, size, ppos, version,
3036 +static ssize_t sd_matching_read(struct file *file, char __user *buf,
3037 + size_t size, loff_t *ppos)
3039 + const char *matching = sdmatch_features();
3041 + return simple_read_from_buffer(buf, size, ppos, matching,
3042 + strlen(matching));
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)
3052 + /* only writes from pos 0, that is complete writes */
3053 + data = ERR_PTR(-ESPIPE);
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.
3061 + if (sd_is_confined()) {
3062 + struct subdomain *sd = SD_SUBDOMAIN(current->security);
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);
3069 + data = ERR_PTR(-EPERM);
3073 + data = vmalloc(alloc_size);
3074 + if (data == NULL) {
3075 + data = ERR_PTR(-ENOMEM);
3079 + if (copy_from_user(data, userbuf, copy_size)) {
3081 + data = ERR_PTR(-EFAULT);
3089 +static ssize_t sd_profile_load(struct file *f, const char __user *buf,
3090 + size_t size, loff_t *pos)
3095 + data = sd_simple_write_to_buffer(buf, size, size, pos, "load");
3097 + if (!IS_ERR(data)) {
3098 + error = sd_file_prof_add(data, size);
3101 + error = PTR_ERR(data);
3107 +static ssize_t sd_profile_replace(struct file *f, const char __user *buf,
3108 + size_t size, loff_t *pos)
3113 + data = sd_simple_write_to_buffer(buf, size, size, pos, "replacement");
3115 + if (!IS_ERR(data)) {
3116 + error = sd_file_prof_repl(data, size);
3119 + error = PTR_ERR(data);
3125 +static ssize_t sd_profile_remove(struct file *f, const char __user *buf,
3126 + size_t size, loff_t *pos)
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
3134 + data = sd_simple_write_to_buffer(buf, size+1, size, pos, "removal");
3136 + if (!IS_ERR(data)) {
3138 + error = sd_file_prof_remove(data, size);
3141 + error = PTR_ERR(data);
3147 +static u64 sd_control_get(void *data)
3149 + return *(int *)data;
3152 +static void sd_control_set(void *data, u64 val)
3157 + *(int*)data = (int)val;
3160 +static void clear_subdomainfs(void)
3164 + for (i=0; i < num_entries;i++) {
3165 + unsigned int index;
3167 + if (root_entries[i].mode == S_IFDIR) {
3168 + if (root_entries[i].name)
3169 + /* defer dir free till all sub-entries freed */
3172 + /* cleanup parent */
3173 + index = root_entries[i].parent_index;
3178 + if (root_entries[index].dentry) {
3179 + securityfs_remove(root_entries[index].dentry);
3181 + SD_DEBUG("%s: deleted subdomainfs entry name=%s "
3184 + root_entries[index].name,
3185 + root_entries[index].dentry);
3187 + root_entries[index].dentry = NULL;
3188 + root_entries[index].parent_index = 0;
3193 +static int populate_subdomainfs(struct dentry *root)
3195 + unsigned int i, parent_index, depth;
3197 +#define ENT root_entries[i]
3199 + for (i = 0; i < num_entries; i++) {
3200 + root_entries[i].dentry = NULL;
3201 + root_entries[i].parent_index = 0;
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",
3214 + /* 2. Verify table structure */
3218 + for (i = 1; i < num_entries; i++) {
3219 + ENT.parent_index = parent_index;
3221 + if (ENT.name && ENT.mode == S_IFDIR) {
3224 + } else if (!ENT.name) {
3225 + if (ENT.mode != S_IFDIR || depth == 0) {
3226 + SD_ERROR("%s: root_entry %d invalid (%u %d)",
3228 + ENT.mode, ENT.parent_index);
3233 + parent_index = root_entries[parent_index].parent_index;
3238 + SD_ERROR("%s: root_entry table not correctly terminated\n",
3243 + /* 3. Create root (parent=NULL) */
3246 + ENT.dentry = securityfs_create_file(ENT.name,
3247 + ENT.mode | ENT.access,
3248 + NULL, NULL, NULL);
3251 + SD_DEBUG("%s: created securityfs/subdomain [dentry=%p]\n",
3252 + __FUNCTION__, ENT.dentry);
3257 + /* 4. create remaining nodes */
3258 + for (i = 1; i < num_entries; i++) {
3259 + struct dentry *parent;
3261 + /* end of directory ? */
3265 + parent = root_entries[ENT.parent_index].dentry;
3267 + ENT.dentry = securityfs_create_file(ENT.name,
3268 + ENT.mode | ENT.access,
3270 + ENT.mode != S_IFDIR ? ENT.data : NULL,
3271 + ENT.mode != S_IFDIR ? ENT.fops : NULL);
3274 + goto cleanup_error;
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);
3285 + clear_subdomainfs();
3291 +int create_subdomainfs(void)
3294 + SD_ERROR("%s: Subdomain securityfs already exists\n",
3296 + else if (!populate_subdomainfs(sdfs_dentry))
3297 + SD_ERROR("%s: Error populating Subdomain securityfs\n",
3300 + return (SDFS_DENTRY != NULL);
3303 +int destroy_subdomainfs(void)
3306 + clear_subdomainfs();
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
3314 + * Copyright (C) 1998-2005 Novell/SUSE
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
3321 + * AppArmor internal prototypes
3324 +#ifndef __SUBDOMAIN_H
3325 +#define __SUBDOMAIN_H
3327 +/* defn of iattr */
3328 +#include <linux/fs.h>
3330 +/* defn of linux_binprm */
3331 +#include <linux/binfmts.h>
3333 +#include "shared.h"
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;
3342 +#define SD_UNCONSTRAINED "unconstrained"
3344 +/* $ echo -n subdomain.o | md5sum | cut -c -8 */
3345 +#define SD_ID_MAGIC 0x8c235e38
3347 +#define PROFILE_COMPLAIN(_profile) \
3348 + (subdomain_complain == 1 || ((_profile) && (_profile)->flags.complain))
3350 +#define SUBDOMAIN_COMPLAIN(_sd) \
3351 + (subdomain_complain == 1 || \
3352 + ((_sd) && (_sd)->active && (_sd)->active->flags.complain))
3354 +#define SUBDOMAIN_AUDIT(_sd) \
3355 + (subdomain_audit == 1 || \
3356 + ((_sd) && (_sd)->active && (_sd)->active->flags.audit))
3359 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
3360 + * which is not related to profile accesses.
3363 +#define SD_DEBUG(fmt, args...) \
3365 + if (subdomain_debug) \
3366 + printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
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)
3372 +/* basic AppArmor data structures */
3382 + sd_entry_tailglob,
3388 + * sd_entry - file ACL *
3389 + * Each entry describes a file and an allowed access mode.
3393 + int mode; /* mode is 'or' of READ, WRITE, EXECUTE,
3394 + * INHERIT, UNCONSTRAINED, and LIBRARY
3395 + * (meaning don't prefetch). */
3397 + enum entry_t entry_type;
3400 + struct list_head list;
3401 + struct list_head listp[POS_SD_FILE_MAX + 1];
3404 +#define SD_SECURE_EXEC_NEEDED 0x00000001
3406 +#define SD_EXEC_MODIFIER_MASK(mask) ((mask) & SD_EXEC_MODIFIERS)
3408 +#define SD_EXEC_MASK(mask) ((mask) & (SD_MAY_EXEC | SD_EXEC_MODIFIERS))
3410 +#define SD_EXEC_UNSAFE_MASK(mask) ((mask) & (SD_MAY_EXEC |\
3411 + SD_EXEC_MODIFIERS |\
3415 + * sdprofile - basic confinement data
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
3422 + char *name; /* profile name */
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 */
3430 + int isstale; /* is profile stale */
3432 + int num_file_entries;
3433 + int num_file_pentries[POS_SD_FILE_MAX + 1];
3435 + kernel_cap_t capabilities;
3437 + atomic_t count; /* reference count */
3446 + * sdfile - file pointer confinement data
3448 + * Data structure assigned to each open file (by subdomain_file_alloc_security)
3451 + enum sdfile_type type;
3452 + struct sdprofile *profile;
3456 + * subdomain - a task's subdomain
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.
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;
3471 +typedef int (*sd_iter) (struct subdomain *, void *);
3474 + * temp (cookie) data used by sd_path_* functions, see inline.h
3476 +struct sd_path_data {
3477 + struct dentry *root, *dentry;
3478 + struct namespace *namespace;
3479 + struct list_head *head, *pos;
3483 +#define SD_SUBDOMAIN(sec) ((struct subdomain*)(sec))
3484 +#define SD_PROFILE(sec) ((struct sdprofile*)(sec))
3486 +/* Lock protecting access to 'struct subdomain' accesses */
3487 +extern rwlock_t sd_lock;
3489 +extern struct sdprofile *null_profile;
3490 +extern struct sdprofile *null_complain_profile;
3494 + * Auditing structure
3498 + unsigned short type, flags;
3499 + unsigned int result;
3500 + unsigned int gfp_mask;
3504 + unsigned int ival;
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
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 */
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"
3532 +#define LOG_HINT(sd, gfp, hint, fmt, args...) \
3534 + sd_audit_message(sd, gfp, 0, \
3535 + "LOGPROF-HINT " hint " " fmt, ##args);\
3539 +#define SD_DIR_MKDIR 0
3540 +#define SD_DIR_RMDIR 1
3543 +#define SD_XATTR_GET 0
3544 +#define SD_XATTR_SET 1
3545 +#define SD_XATTR_LIST 2
3546 +#define SD_XATTR_REMOVE 3
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,
3555 +extern int sd_audit(struct subdomain *, const struct sd_audit *);
3556 +extern char *sd_get_name(struct dentry *dentry, struct vfsmount *mnt);
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,
3567 +extern int sd_perm_dentry(struct subdomain *sd, struct dentry *dentry,
3569 +extern int sd_perm_dir(struct subdomain *sd, struct dentry *dentry,
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);
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);
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);
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);
3604 +extern int create_subdomainfs(void);
3605 +extern int destroy_subdomainfs(void);
3607 +/* capabilities.c */
3608 +extern const char *capability_to_name(unsigned int cap);
3610 +/* apparmor_version.c */
3611 +extern const char *apparmor_version(void);
3612 +extern const char *apparmor_version_nl(void);
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
3619 + * Copyright (C) 2005 Novell/SUSE
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
3626 + * AppArmor version definition
3629 +#ifndef APPARMOR_VERSION
3630 +#error "-DAPPARMOR_VERSION must be specified when compiling this file"
3633 +#define APPARMOR_VERSION_STR_PFX "APPARMOR_VERSION="
3635 +#include <linux/module.h>
3636 +MODULE_VERSION(APPARMOR_VERSION);
3638 +/* apparmor_version_str exists to allow a strings on module to
3639 + * see APPARMOR_VERSION= prefix
3641 +static const char *apparmor_version_str =
3642 + APPARMOR_VERSION_STR_PFX APPARMOR_VERSION;
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
3647 +static const char *apparmor_version_str_nl = APPARMOR_VERSION "\n";
3649 +const char *apparmor_version(void)
3651 + const int len = sizeof(APPARMOR_VERSION_STR_PFX) - 1;
3653 + return apparmor_version_str + len;
3656 +const char *apparmor_version_nl(void)
3658 + return apparmor_version_str_nl;
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
3664 + * Copyright (C) 2005 Novell/SUSE
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
3671 + * AppArmor capability definitions
3674 +#include "apparmor.h"
3676 +static const char *capnames[] = {
3679 + "dac_read_search",
3686 + "linux_immutable",
3687 + "net_bind_service",
3708 +const char *capability_to_name(unsigned int cap)
3710 + const char *capname;
3712 + capname = (cap < (sizeof(capnames) / sizeof(char *))
3713 + ? capnames[cap] : "invalid-capability");
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
3721 + * Copyright (C) 2005 Novell/SUSE
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
3732 +#include <linux/namespace.h>
3734 +static inline int __sd_is_confined(struct subdomain *sd)
3738 + if (sd && sd->sd_magic == SD_ID_MAGIC && sd->profile) {
3739 + BUG_ON(!sd->active);
3750 + * Check if @sd is confined (contains a valid profile)
3751 + * Return 1 if confined, 0 otherwise.
3753 +static inline int sd_is_confined(void)
3755 + struct subdomain *sd = SD_SUBDOMAIN(current->security);
3756 + return __sd_is_confined(sd);
3759 +static inline int __sd_sub_defined(struct subdomain *sd)
3761 + return __sd_is_confined(sd) && !list_empty(&sd->profile->sub);
3768 + * Check if @sd has at least one subprofile
3769 + * Return 1 if true, 0 otherwise
3771 +static inline int sd_sub_defined(void)
3773 + struct subdomain *sd = SD_SUBDOMAIN(current->security);
3774 + return __sd_sub_defined(sd);
3781 + * Increment refcount on profile
3783 +static inline struct sdprofile *get_sdprofile(struct sdprofile *p)
3786 + atomic_inc(&p->count);
3794 + * Decrement refcount on profile
3796 +static inline void put_sdprofile(struct sdprofile *p)
3799 + if (atomic_dec_and_test(&p->count))
3800 + free_sdprofile(p);
3805 + * @sd: subdomain to switch
3806 + * @profile: new profile
3807 + * @active: new active
3809 + * Change subdomain to use new profiles.
3811 +static inline void sd_switch(struct subdomain *sd,
3812 + struct sdprofile *profile,
3813 + struct sdprofile *active)
3815 + /* noop if NULL */
3816 + put_sdprofile(sd->profile);
3817 + put_sdprofile(sd->active);
3819 + sd->profile = get_sdprofile(profile);
3820 + sd->active = get_sdprofile(active);
3824 + * sd_switch_unconfined
3825 + * @sd: subdomain to switch
3827 + * Change subdomain to unconfined
3829 +static inline void sd_switch_unconfined(struct subdomain *sd)
3831 + sd_switch(sd, NULL, NULL);
3833 + /* reset magic in case we were in a subhat before */
3834 + sd->sd_hat_magic = 0;
3839 + * @tsk: task struct
3841 + * Allocate a new subdomain including a backpointer to it's referring task.
3843 +static inline struct subdomain *alloc_subdomain(struct task_struct *tsk)
3845 + struct subdomain *sd;
3847 + sd = kmalloc(sizeof(struct subdomain), GFP_KERNEL);
3851 + /* zero it first */
3852 + memset(sd, 0, sizeof(struct subdomain));
3853 + sd->sd_magic = SD_ID_MAGIC;
3855 + /* back pointer to task */
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)
3861 + sd_subdomainlist_add(sd);
3871 + * Free a subdomain previously allocated by alloc_subdomain
3873 +static inline void free_subdomain(struct subdomain *sd)
3875 + sd_subdomainlist_remove(sd);
3882 + * Allocate, initialize and return a new zeroed profile.
3883 + * Returns NULL on failure.
3885 +static inline struct sdprofile *alloc_sdprofile(void)
3887 + struct sdprofile *profile;
3889 + profile = (struct sdprofile *)kmalloc(sizeof(struct sdprofile),
3891 + SD_DEBUG("%s(%p)\n", __FUNCTION__, profile);
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]);
3907 + * @name: name to release.
3909 + * Release space (free_page) allocated to hold pathname
3910 + * name may be NULL (checked for by free_page)
3912 +static inline void sd_put_name(const char *name)
3914 + free_page((unsigned long)name);
3917 +/** __sd_find_profile
3918 + * @name: name of profile to find
3919 + * @head: list to search
3921 + * Return reference counted copy of profile. NULL if not found
3922 + * Caller must hold any necessary locks
3924 +static inline struct sdprofile *__sd_find_profile(const char *name,
3925 + struct list_head *head)
3927 + struct sdprofile *p;
3929 + if (!name || !head)
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);
3939 + SD_DEBUG("%s: skipping %s\n", __FUNCTION__, p->name);
3945 +static inline struct subdomain *__get_sdcopy(struct subdomain *new,
3946 + struct task_struct *tsk)
3948 + struct subdomain *old, *temp = NULL;
3950 + old = SD_SUBDOMAIN(tsk->security);
3953 + new->sd_magic = old->sd_magic;
3954 + new->sd_hat_magic = old->sd_hat_magic;
3956 + new->active = get_sdprofile(old->active);
3958 + if (old->profile == old->active)
3959 + new->profile = new->active;
3961 + new->profile = get_sdprofile(old->profile);
3970 + * @new: subdomain to hold copy
3972 + * Make copy of current subdomain containing refcounted profile and active
3973 + * Used to protect readers against racing writers (changehat and profile
3976 +static inline struct subdomain *get_sdcopy(struct subdomain *new)
3978 + struct subdomain *temp;
3979 + unsigned long flags;
3981 + read_lock_irqsave(&sd_lock, flags);
3983 + temp = __get_sdcopy(new, current);
3985 + read_unlock_irqrestore(&sd_lock, flags);
3991 + * @temp: subdomain to drop refcounts on
3993 + * Drop refcounted profile/active in copy of subdomain made by get_sdcopy
3995 +static inline void put_sdcopy(struct subdomain *temp)
3998 + put_sdprofile(temp->active);
3999 + if (temp->active != temp->profile)
4000 + (void)put_sdprofile(temp->profile);
4005 + * @rdentry: filesystem root dentry (searching for vfsmnts matching this)
4006 + * @dentry: dentry object to obtain pathname from (relative to matched vfsmnt)
4008 + * Setup data for iterating over vfsmounts (in current tasks namespace).
4010 +static inline void sd_path_begin2(struct dentry *rdentry,
4011 + struct dentry *dentry,
4012 + struct sd_path_data *data)
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);
4022 + down_read(&namespace_sem);
4026 + * @dentry filesystem root dentry and object to obtain pathname from
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).
4031 +static inline void sd_path_begin(struct dentry *dentry,
4032 + struct sd_path_data *data)
4034 + sd_path_begin2(dentry, dentry, data);
4038 + * @data: data object previously initialized by sd_path_begin
4040 + * End iterating over vfsmounts.
4041 + * If an error occured in begin or get, it is returned. Otherwise 0.
4043 +static inline int sd_path_end(struct sd_path_data *data)
4045 + up_read(&namespace_sem);
4048 + return data->errno;
4051 +/** sd_path_getname
4052 + * @data: data object previously initialized by sd_path_begin
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)
4058 +static inline char *sd_path_getname(struct sd_path_data *data)
4060 + char *name = NULL;
4061 + struct vfsmount *mnt;
4063 + while (data->pos != data->head) {
4064 + mnt = list_entry(data->pos, struct vfsmount, mnt_list);
4066 + /* advance to next -- so that it is done before we break */
4067 + data->pos = data->pos->next;
4068 + prefetch(data->pos->next);
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);
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
4087 +# Makefile for AppArmor Linux Security Module
4089 +EXTRA_CFLAGS += -DAPPARMOR_VERSION=\"${APPARMOR_VER}\"
4091 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
4093 +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o capabilities.o \
4094 + module_interface.o apparmor_version.o
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
4100 +config SECURITY_APPARMOR
4101 + tristate "AppArmor support"
4102 + depends on SECURITY!=n
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
4113 + * Copyright (C) 1998-2005 Novell/SUSE
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
4120 + * AppArmor Profile List Management
4123 +#include <linux/seq_file.h>
4124 +#include "apparmor.h"
4125 +#include "inline.h"
4127 +/* list of all profiles and lock */
4128 +static LIST_HEAD(profile_list);
4129 +static rwlock_t profile_lock = RW_LOCK_UNLOCKED;
4131 +/* list of all subdomains and lock */
4132 +static LIST_HEAD(subdomain_list);
4133 +static rwlock_t subdomain_lock = RW_LOCK_UNLOCKED;
4136 + * sd_profilelist_find
4137 + * @name: profile name (program name)
4139 + * Search the profile list for profile @name. Return refcounted profile on
4140 + * success, NULL on failure.
4142 +struct sdprofile *sd_profilelist_find(const char *name)
4144 + struct sdprofile *p = NULL;
4146 + read_lock(&profile_lock);
4147 + p = __sd_find_profile(name, &profile_list);
4148 + read_unlock(&profile_lock);
4154 + * sd_profilelist_add
4155 + * @profile: new profile to add to list
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)
4160 +int sd_profilelist_add(struct sdprofile *profile)
4162 + struct sdprofile *old_profile;
4168 + write_lock(&profile_lock);
4169 + old_profile = __sd_find_profile(profile->name, &profile_list);
4170 + if (old_profile) {
4171 + put_sdprofile(old_profile);
4174 + profile = get_sdprofile(profile);
4176 + list_add(&profile->list, &profile_list);
4179 + write_unlock(&profile_lock);
4184 + * sd_profilelist_remove
4185 + * @name: name of profile to be removed
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
4191 +struct sdprofile *sd_profilelist_remove(const char *name)
4193 + struct sdprofile *profile = NULL;
4194 + struct sdprofile *p, *tmp;
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 */
4209 + write_unlock(&profile_lock);
4216 + * sd_profilelist_replace
4217 + * @profile - new profile
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.
4224 +struct sdprofile *sd_profilelist_replace(struct sdprofile *profile)
4226 + struct sdprofile *oldprofile;
4228 + write_lock(&profile_lock);
4229 + oldprofile = __sd_find_profile(profile->name, &profile_list);
4231 + list_del_init(&oldprofile->list);
4232 + /* mark old profile as stale */
4233 + oldprofile->isstale = 1;
4235 + /* __sd_find_profile incremented count, so adjust down */
4236 + put_sdprofile(oldprofile);
4238 + profile = get_sdprofile(profile);
4239 + list_add(&profile->list, &profile_list);
4240 + write_unlock(&profile_lock);
4242 + return oldprofile;
4246 + * sd_profilelist_release
4248 + * Remove all profiles from profile_list
4250 +void sd_profilelist_release(void)
4252 + struct sdprofile *p, *tmp;
4254 + write_lock(&profile_lock);
4255 + list_for_each_entry_safe(p, tmp, &profile_list, list) {
4256 + list_del_init(&p->list);
4259 + write_unlock(&profile_lock);
4263 + * sd_subdomainlist_add
4264 + * @sd: new subdomain
4266 + * Add subdomain to subdomain_list
4268 +void sd_subdomainlist_add(struct subdomain *sd)
4270 + unsigned long flags;
4273 + SD_INFO("%s: bad subdomain\n", __FUNCTION__);
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.
4281 + list_add_tail(&sd->list, &subdomain_list);
4282 + write_unlock_irqrestore(&subdomain_lock, flags);
4286 + * sd_subdomainlist_remove
4287 + * @sd: subdomain to be removed
4289 + * Remove subdomain from subdomain_list
4291 +void sd_subdomainlist_remove(struct subdomain *sd)
4293 + unsigned long flags;
4296 + write_lock_irqsave(&subdomain_lock, flags);
4297 + list_del_init(&sd->list);
4298 + write_unlock_irqrestore(&subdomain_lock, flags);
4303 + * sd_subdomainlist_iterate
4304 + * @func: method to be called for each element
4305 + * @cookie: user passed data
4307 + * Iterate over subdomain list, stop when sd_iter func returns non zero
4309 +void sd_subdomainlist_iterate(sd_iter func, void *cookie)
4311 + struct subdomain *node;
4313 + unsigned long flags;
4315 + read_lock_irqsave(&subdomain_lock, flags);
4316 + list_for_each_entry(node, &subdomain_list, list) {
4317 + ret = (*func) (node, cookie);
4321 + read_unlock_irqrestore(&subdomain_lock, flags);
4325 + * sd_subdomainlist_release
4327 + * Remove all subdomains from subdomain_list
4329 +void sd_subdomainlist_release()
4331 + struct subdomain *node, *tmp;
4332 + unsigned long flags;
4334 + write_lock_irqsave(&subdomain_lock, flags);
4335 + list_for_each_entry_safe(node, tmp, &subdomain_list, list) {
4336 + list_del_init(&node->list);
4338 + write_unlock_irqrestore(&subdomain_lock, flags);
4341 +/* seq_file helper routines
4342 + * Used by subdomainfs.c to iterate over profile_list
4344 +static void *p_start(struct seq_file *f, loff_t *pos)
4346 + struct sdprofile *node;
4349 + read_lock(&profile_lock);
4350 + list_for_each_entry(node, &profile_list, list)
4356 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
4358 + struct list_head *lh = ((struct sdprofile *)p)->list.next;
4360 + return lh == &profile_list ?
4361 + NULL : list_entry(lh, struct sdprofile, list);
4364 +static void p_stop(struct seq_file *f, void *v)
4366 + read_unlock(&profile_lock);
4369 +static int seq_show_profile(struct seq_file *f, void *v)
4371 + struct sdprofile *profile = (struct sdprofile *)v;
4372 + seq_printf(f, "%s (%s)\n", profile->name,
4373 + PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
4377 +struct seq_operations subdomainfs_profiles_op = {
4381 + .show = seq_show_profile,
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
4387 + * Copyright (C) 2002-2005 Novell/SUSE
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
4394 + * http://forge.novell.com/modules/xfmod/project/?apparmor
4396 + * Immunix AppArmor LSM interface (previously called "SubDomain")
4399 +#include <linux/security.h>
4400 +#include <linux/module.h>
4401 +#include <linux/mm.h>
4403 +/* superblock types */
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
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)
4416 +#include <asm/mman.h>
4418 +#include "apparmor.h"
4419 +#include "inline.h"
4421 +/* main SD lock [see get_sdcopy and put_sdcopy] */
4422 +rwlock_t sd_lock = RW_LOCK_UNLOCKED;
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. */
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");
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");
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");
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");
4450 +static int __init sd_getopt_complain(char *str)
4452 + get_option(&str, &subdomain_complain);
4455 +__setup("subdomain_complain=", sd_getopt_complain);
4457 +static int __init sd_getopt_debug(char *str)
4459 + get_option(&str, &subdomain_debug);
4462 +__setup("subdomain_debug=", sd_getopt_debug);
4464 +static int __init sd_getopt_audit(char *str)
4466 + get_option(&str, &subdomain_audit);
4469 +__setup("subdomain_audit=", sd_getopt_audit);
4471 +static int __init sd_getopt_logsyscall(char *str)
4473 + get_option(&str, &subdomain_logsyscall);
4476 +__setup("subdomain_logsyscall=", sd_getopt_logsyscall);
4479 +static int subdomain_ptrace(struct task_struct *parent,
4480 + struct task_struct *child)
4483 + struct subdomain *sd;
4484 + unsigned long flags;
4486 + error = cap_ptrace(parent, child);
4488 + if (error == 0 && parent->security) {
4489 + read_lock_irqsave(&sd_lock, flags);
4491 + sd = SD_SUBDOMAIN(parent->security);
4493 + if (__sd_is_confined(sd)) {
4494 + error = sd_audit_syscallreject(sd, GFP_ATOMIC,
4496 + WARN_ON(error != -EPERM);
4499 + read_unlock_irqrestore(&sd_lock, flags);
4505 +static int subdomain_capget(struct task_struct *target,
4506 + kernel_cap_t * effective,
4507 + kernel_cap_t * inheritable,
4508 + kernel_cap_t * permitted)
4510 + return cap_capget(target, effective, inheritable, permitted);
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)
4518 + return cap_capset_check(target, effective, inheritable, permitted);
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)
4526 + cap_capset_set(target, effective, inheritable, permitted);
4530 +static int subdomain_capable(struct task_struct *tsk, int cap)
4534 + /* cap_capable returns 0 on success, else -EPERM */
4535 + error = cap_capable(tsk, cap);
4537 + if (error == 0 && current->security) {
4538 + struct subdomain *sd, sdcopy;
4539 + unsigned long flags;
4541 + read_lock_irqsave(&sd_lock, flags);
4542 + sd = __get_sdcopy(&sdcopy, tsk);
4543 + read_unlock_irqrestore(&sd_lock, flags);
4545 + error = sd_capability(sd, cap);
4553 +static int subdomain_sysctl(struct ctl_table *table, int op)
4556 + struct subdomain *sd;
4557 + unsigned long flags;
4559 + if (!current->security)
4562 + read_lock_irqsave(&sd_lock, flags);
4564 + sd = SD_SUBDOMAIN(current->security);
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);
4572 + read_unlock_irqrestore(&sd_lock, flags);
4577 +static int subdomain_syslog(int type)
4579 + return cap_syslog(type);
4582 +static int subdomain_netlink_send(struct sock *sk, struct sk_buff *skb)
4584 + return cap_netlink_send(sk, skb);
4587 +static int subdomain_netlink_recv(struct sk_buff *skb)
4589 + return cap_netlink_recv(skb);
4592 +static void subdomain_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
4594 + cap_bprm_apply_creds(bprm, unsafe);
4598 +static int subdomain_bprm_set_security(struct linux_binprm *bprm)
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)
4605 + return sd_register(bprm);
4608 +static int subdomain_bprm_secureexec(struct linux_binprm *bprm)
4610 + int ret = cap_bprm_secureexec(bprm);
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);
4621 +static int subdomain_sb_mount(char *dev_name, struct nameidata *nd, char *type,
4622 + unsigned long flags, void *data)
4625 + struct subdomain *sd;
4626 + unsigned long lockflags;
4628 + if (!current->security)
4631 + read_lock_irqsave(&sd_lock, lockflags);
4633 + sd = SD_SUBDOMAIN(current->security);
4635 + if (__sd_is_confined(sd)) {
4636 + error = sd_audit_syscallreject(sd, GFP_ATOMIC, "mount");
4637 + WARN_ON(error != -EPERM);
4640 + read_unlock_irqrestore(&sd_lock, lockflags);
4645 +static int subdomain_umount(struct vfsmount *mnt, int flags)
4648 + struct subdomain *sd;
4649 + unsigned long lockflags;
4651 + if (!current->security)
4654 + read_lock_irqsave(&sd_lock, lockflags);
4656 + sd = SD_SUBDOMAIN(current->security);
4658 + if (__sd_is_confined(sd)) {
4659 + error = sd_audit_syscallreject(sd, GFP_ATOMIC, "umount");
4660 + WARN_ON(error != -EPERM);
4663 + read_unlock_irqrestore(&sd_lock, lockflags);
4668 +static int subdomain_inode_mkdir(struct inode *inode, struct dentry *dentry,
4671 + struct subdomain sdcopy, *sd;
4674 + if (!current->security)
4677 + sd = get_sdcopy(&sdcopy);
4679 + error = sd_perm_dir(sd, dentry, SD_DIR_MKDIR);
4686 +static int subdomain_inode_rmdir(struct inode *inode, struct dentry *dentry)
4688 + struct subdomain sdcopy, *sd;
4691 + if (!current->security)
4694 + sd = get_sdcopy(&sdcopy);
4696 + error = sd_perm_dir(sd, dentry, SD_DIR_RMDIR);
4703 +static int subdomain_inode_create(struct inode *inode, struct dentry *dentry,
4706 + struct subdomain sdcopy, *sd;
4709 + if (!current->security)
4712 + sd = get_sdcopy(&sdcopy);
4714 + /* At a minimum, need write perm to create */
4715 + error = sd_perm_dentry(sd, dentry, MAY_WRITE);
4722 +static int subdomain_inode_link(struct dentry *old_dentry, struct inode *inode,
4723 + struct dentry *new_dentry)
4726 + struct subdomain sdcopy, *sd;
4728 + if (!current->security)
4731 + sd = get_sdcopy(&sdcopy);
4732 + error = sd_link(sd, new_dentry, old_dentry);
4738 +static int subdomain_inode_unlink(struct inode *inode, struct dentry *dentry)
4740 + struct subdomain sdcopy, *sd;
4743 + if (!current->security)
4746 + sd = get_sdcopy(&sdcopy);
4748 + error = sd_perm_dentry(sd, dentry, MAY_WRITE);
4755 +static int subdomain_inode_mknod(struct inode *inode, struct dentry *dentry,
4756 + int mode, dev_t dev)
4758 + struct subdomain sdcopy, *sd;
4761 + if (!current->security)
4764 + sd = get_sdcopy(&sdcopy);
4766 + error = sd_perm_dentry(sd, dentry, MAY_WRITE);
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)
4778 + struct subdomain sdcopy, *sd;
4781 + if (!current->security)
4784 + sd = get_sdcopy(&sdcopy);
4786 + error = sd_perm_dentry(sd, old_dentry,
4787 + MAY_READ | MAY_WRITE);
4790 + error = sd_perm_dentry(sd, new_dentry, MAY_WRITE);
4797 +static int subdomain_inode_permission(struct inode *inode, int mask,
4798 + struct nameidata *nd)
4802 + /* Do not perform check on pipes or sockets
4803 + * Same as subdomain_file_permission
4805 + if (current->security && VALID_FSTYPE(inode)) {
4806 + struct subdomain sdcopy, *sd;
4808 + sd = get_sdcopy(&sdcopy);
4809 + error = sd_perm_nameidata(sd, nd, mask);
4816 +static int subdomain_inode_setattr(struct dentry *dentry, struct iattr *iattr)
4818 + struct subdomain sdcopy, *sd;
4821 + if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4823 + sd = get_sdcopy(&sdcopy);
4826 + * Mediate any attempt to change attributes of a file
4827 + * (chmod, chown, chgrp, etc)
4829 + error = sd_attr(sd, dentry, iattr);
4837 +static int subdomain_inode_setxattr(struct dentry *dentry, char *name,
4838 + void *value, size_t size, int flags)
4842 + if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4843 + struct subdomain sdcopy, *sd;
4845 + sd = get_sdcopy(&sdcopy);
4846 + error = sd_xattr(sd, dentry, name, SD_XATTR_SET);
4853 +static int subdomain_inode_getxattr(struct dentry *dentry, char *name)
4857 + if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4858 + struct subdomain sdcopy, *sd;
4860 + sd = get_sdcopy(&sdcopy);
4861 + error = sd_xattr(sd, dentry, name, SD_XATTR_GET);
4867 +static int subdomain_inode_listxattr(struct dentry *dentry)
4871 + if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4872 + struct subdomain sdcopy, *sd;
4874 + sd = get_sdcopy(&sdcopy);
4875 + error = sd_xattr(sd, dentry, NULL, SD_XATTR_LIST);
4882 +static int subdomain_inode_removexattr(struct dentry *dentry, char *name)
4886 + if (current->security && VALID_FSTYPE(dentry->d_inode)) {
4887 + struct subdomain sdcopy, *sd;
4889 + sd = get_sdcopy(&sdcopy);
4890 + error = sd_xattr(sd, dentry, name, SD_XATTR_REMOVE);
4897 +static int subdomain_file_permission(struct file *file, int mask)
4899 + struct subdomain sdcopy, *sd;
4900 + struct sdfile *sdf;
4903 + if (!current->security ||
4904 + !(sdf = (struct sdfile *)file->f_security) ||
4905 + !VALID_FSTYPE(file->f_dentry->d_inode))
4908 + sd = get_sdcopy(&sdcopy);
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));
4919 +static int subdomain_file_alloc_security(struct file *file)
4921 + struct subdomain sdcopy, *sd;
4924 + if (!current->security)
4927 + sd = get_sdcopy(&sdcopy);
4929 + if (__sd_is_confined(sd)) {
4930 + struct sdfile *sdf;
4932 + sdf = kmalloc(sizeof(struct sdfile), GFP_KERNEL);
4935 + sdf->type = sd_file_default;
4936 + sdf->profile = get_sdprofile(sd->active);
4941 + file->f_security = sdf;
4949 +static void subdomain_file_free_security(struct file *file)
4951 + struct sdfile *sdf = (struct sdfile *)file->f_security;
4954 + put_sdprofile(sdf->profile);
4959 +static inline int sd_mmap(struct file *file, unsigned long prot,
4960 + unsigned long flags)
4962 + int error = 0, mask = 0;
4963 + struct subdomain sdcopy, *sd;
4964 + struct sdfile *sdf;
4966 + if (!current->security || !file ||
4967 + !(sdf = (struct sdfile *)file->f_security) ||
4968 + sdf->type == sd_file_shmem)
4971 + sd = get_sdcopy(&sdcopy);
4973 + if (prot & PROT_READ)
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;
4981 + if (prot & PROT_EXEC)
4982 + mask |= SD_EXEC_MMAP;
4984 + SD_DEBUG("%s: 0x%x\n", __FUNCTION__, mask);
4987 + error = sd_perm(sd, file->f_dentry, file->f_vfsmnt, mask);
4994 +static int subdomain_file_mmap(struct file *file, unsigned long reqprot,
4995 + unsigned long prot, unsigned long flags)
4997 + return sd_mmap(file, prot, flags);
5000 +static int subdomain_file_mprotect(struct vm_area_struct* vma,
5001 + unsigned long reqprot, unsigned long prot)
5003 + return sd_mmap(vma->vm_file, prot,
5004 + !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
5007 +static int subdomain_task_alloc_security(struct task_struct *p)
5009 + return sd_fork(p);
5012 +static void subdomain_task_free_security(struct task_struct *p)
5018 +static int subdomain_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
5021 + return cap_task_post_setuid(id0, id1, id2, flags);
5024 +static void subdomain_task_reparent_to_init(struct task_struct *p)
5026 + cap_task_reparent_to_init(p);
5030 +static int subdomain_shm_shmat(struct shmid_kernel* shp, char __user *shmaddr,
5033 + struct sdfile *sdf = (struct sdfile *)shp->shm_file->f_security;
5036 + sdf->type = sd_file_shmem;
5041 +static int subdomain_getprocattr(struct task_struct *p, char *name, void *value,
5045 + struct subdomain sdcopy, *sd;
5046 + char *str = value;
5047 + unsigned long flags;
5049 + /* Subdomain only supports the "current" process attribute */
5050 + if (strcmp(name, "current") != 0) {
5060 + /* must be task querying itself or admin */
5061 + if (current != p && !capable(CAP_SYS_ADMIN)) {
5066 + read_lock_irqsave(&sd_lock, flags);
5068 + sd = __get_sdcopy(&sdcopy, p);
5070 + read_unlock_irqrestore(&sd_lock, flags);
5072 + error = sd_getprocattr(sd, str, size);
5079 +static int subdomain_setprocattr(struct task_struct *p, char *name, void *value,
5082 + const char *cmd_changehat = "changehat ",
5083 + *cmd_setprofile = "setprofile ";
5085 + int error = -EACCES; /* default to a perm denied */
5086 + char *cmd = (char *)value;
5088 + /* only support messages to current */
5089 + if (strcmp(name, "current") != 0) {
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);
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",
5120 + error = sd_setprocattr_changehat(hatinfo, infosize);
5122 + /* success, set return to #bytes in orig request */
5125 + /* SET NEW PROFILE */
5126 + } else if (size > strlen(cmd_setprofile) &&
5127 + strncmp(cmd, cmd_setprofile, strlen(cmd_setprofile)) == 0) {
5129 + unsigned long flags;
5131 + /* only an unconfined process with admin capabilities
5132 + * may change the profile of another task
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",
5148 + read_lock_irqsave(&sd_lock, flags);
5149 + confined = sd_is_confined();
5150 + read_unlock_irqrestore(&sd_lock, flags);
5153 + char *profile = cmd + strlen(cmd_setprofile);
5154 + size_t profilesize = size - strlen(cmd_setprofile);
5156 + error = sd_setprocattr_setprofile(p, profile, profilesize);
5159 + * set return to #bytes in orig request
5163 + SD_WARN("%s: Attempt by confined task %s(%d) "
5164 + "[user %d] to assign profile to task %s(%d)\n",
5175 + /* unknown operation */
5176 + SD_WARN("%s: Unknown setprocattr command '%.*s' by task %s(%d) "
5177 + "[user %d] for task %s(%d)\n",
5179 + size < 16 ? (int)size : 16,
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,
5203 + .netlink_send = subdomain_netlink_send,
5204 + .netlink_recv = subdomain_netlink_recv,
5206 + .bprm_apply_creds = subdomain_bprm_apply_creds,
5207 + .bprm_set_security = subdomain_bprm_set_security,
5208 + .bprm_secureexec = subdomain_bprm_secureexec,
5210 + .sb_mount = subdomain_sb_mount,
5211 + .sb_umount = subdomain_umount,
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,
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,
5237 + .shm_shmat = subdomain_shm_shmat,
5239 + .getprocattr = subdomain_getprocattr,
5240 + .setprocattr = subdomain_setprocattr,
5243 +static int __init subdomain_init(void)
5246 + const char *complainmsg = ": complainmode enabled";
5248 + if (!create_subdomainfs()) {
5249 + SD_ERROR("Unable to activate AppArmor filesystem\n");
5251 + goto createfs_out;
5254 + if (!alloc_nullprofiles()){
5255 + SD_ERROR("Unable to allocate null profiles\n");
5260 + if ((error = register_security(&subdomain_ops))) {
5261 + SD_WARN("Unable to load AppArmor\n");
5262 + goto register_security_out;
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 : "");
5275 +register_security_out:
5276 + free_nullprofiles();
5279 + (void)destroy_subdomainfs();
5286 +static int subdomain_exit_removeall_iter(struct subdomain *sd, void *cookie)
5288 + /* write_lock(&sd_lock) held here */
5290 + if (__sd_is_confined(sd)) {
5291 + SD_DEBUG("%s: Dropping profiles %s(%d) "
5292 + "profile %s(%p) active %s(%p)\n",
5294 + sd->task->comm, sd->task->pid,
5295 + sd->profile->name, sd->profile,
5296 + sd->active->name, sd->active);
5297 + sd_switch_unconfined(sd);
5303 +static void __exit subdomain_exit(void)
5305 + unsigned long flags;
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)
5311 + sd_profilelist_release();
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'
5319 + write_lock_irqsave(&sd_lock, flags);
5320 + sd_subdomainlist_iterate(subdomain_exit_removeall_iter, NULL);
5321 + write_unlock_irqrestore(&sd_lock, flags);
5323 + /* Free up list of active subdomain */
5324 + sd_subdomainlist_release();
5326 + free_nullprofiles();
5328 + if (!destroy_subdomainfs())
5329 + SD_WARN("Unable to properly deactivate AppArmor fs\n");
5331 + if (unregister_security(&subdomain_ops))
5332 + SD_WARN("Unable to properly unregister AppArmor\n");
5334 + SD_INFO("AppArmor protection removed\n");
5335 + sd_audit_message(NULL, GFP_KERNEL, 0,
5336 + "AppArmor protection removed\n");
5339 +module_init(subdomain_init);
5340 +module_exit(subdomain_exit);
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
5349 + * Copyright (C) 2002-2005 Novell/SUSE
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
5359 +#include <linux/security.h>
5360 +#include <linux/namei.h>
5361 +#include <linux/audit.h>
5363 +#include "apparmor.h"
5364 +#include "aamatch/match.h"
5366 +#include "inline.h"
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.
5375 + * Leaving the NULL profile is by either successfully changehatting
5376 + * into a sibling hat, or changehatting back to the parent (NULL hat).
5378 +struct sdprofile *null_profile;
5380 +/* NULL complain profile
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
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
5390 +struct sdprofile *null_complain_profile;
5392 +/***************************
5393 + * PRIVATE UTILITY FUNCTIONS
5394 + **************************/
5397 + * dentry_xlate_error
5398 + * @dentry: pointer to dentry
5399 + * @error: error number
5400 + * @dtype: type of dentry
5402 + * Display error message when a dentry translation error occured
5404 +static void dentry_xlate_error(struct dentry *dentry, int error, char *dtype)
5406 + const unsigned int len = 16;
5409 + if (dentry->d_inode) {
5410 + snprintf(buf, len, "%lu", dentry->d_inode->i_ino);
5412 + strncpy(buf, "<negative>", len);
5416 + SD_ERROR("An error occured while translating %s %p "
5417 + "inode# %s to a pathname. Error %d\n",
5425 + * sd_taskattr_access:
5426 + * @name: name of file to check permission
5427 + * @mask: permission mask requested for file
5429 + * Determine if request is for write access to /proc/self/attr/current
5431 +static inline int sd_taskattr_access(const char *procrelname)
5434 + * assumes a 32bit pid, which requires max 10 decimal digits to represent
5435 + * sizeof includes trailing \0
5437 + char buf[sizeof("/attr/current") + 10];
5438 + const int maxbuflen = sizeof(buf);
5440 + snprintf(buf, maxbuflen, "%d/attr/current", current->pid);
5441 + buf[maxbuflen - 1] = 0;
5443 + return strcmp(buf, procrelname) == 0;
5447 + * sd_file_mode - get full mode for file entry from profile
5448 + * @profile: profile
5451 +static inline int sd_file_mode(struct sdprofile *profile, const char *name)
5453 + struct sd_entry *entry;
5456 + SD_DEBUG("%s: %s\n", __FUNCTION__, name);
5458 + SD_DEBUG("%s: no name\n", __FUNCTION__);
5463 + SD_DEBUG("%s: no profile\n", __FUNCTION__);
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;
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
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
5491 + * Returns 1 (true):
5493 + * *xmod = SD_MAY_EXEC
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}
5499 + * *xmod = SD_MAY_EXEC
5500 + * unsafe = presence of unsafe flag
5502 +static inline int sd_get_execmode(struct subdomain *sd, const char *name,
5503 + int *xmod, int *unsafe)
5505 + struct sdprofile *profile;
5506 + struct sd_entry *entry;
5507 + struct sd_entry *match = NULL;
5509 + int pattern_match_invalid = 0, rc = 0;
5511 + /* not confined */
5512 + if (!__sd_is_confined(sd)) {
5513 + SD_DEBUG("%s: not confined\n", __FUNCTION__);
5514 + goto not_confined;
5517 + profile = sd->active;
5519 + /* search list of profiles with 'x' permission
5520 + * this will also include entries with 'p', 'u' and 'i'
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
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)) {
5536 + SD_EXEC_UNSAFE_MASK(entry->mode) !=
5537 + SD_EXEC_UNSAFE_MASK(match->mode))
5538 + pattern_match_invalid = 1;
5540 + /* keep searching for an exact match */
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
5553 + pattern_match_invalid = 0;
5557 + SD_EXEC_UNSAFE_MASK(entry->mode) !=
5558 + SD_EXEC_UNSAFE_MASK(match->mode))
5559 + pattern_match_invalid = 1;
5561 + /* got a tailglob match, keep searching
5562 + * for an exact match
5570 + rc = match && !pattern_match_invalid;
5573 + int mode = SD_EXEC_MASK(match->mode);
5575 + /* check for qualifiers, if present
5576 + * we just return the qualifier
5578 + if (mode & ~SD_MAY_EXEC)
5579 + mode = mode & ~SD_MAY_EXEC;
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",
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",
5600 + *xmod = SD_MAY_EXEC;
5607 + * @mask: requested mask
5608 + * @inode: potential directory inode
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.
5615 + * Returned value of 0 indicates no need to perform a perm check.
5617 +static inline int sd_filter_mask(int mask, struct inode *inode)
5620 + int elim = MAY_APPEND;
5622 + if (inode && S_ISDIR(inode->i_mode))
5623 + elim |= (MAY_EXEC | MAY_WRITE);
5631 +static inline void sd_permerror2result(int perm_result, struct sd_audit *sa)
5633 + if (perm_result == 0) { /* success */
5635 + sa->errorcode = 0;
5636 + } else { /* -ve internal error code or +ve mask of denied perms */
5638 + sa->errorcode = perm_result;
5642 +/*************************
5643 + * MAIN INTERNAL FUNCTIONS
5644 + ************************/
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
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.
5657 + * Return 0 on success, else mask of non-allowed permissions
5659 +static unsigned int sd_file_perm(struct subdomain *sd, const char *name,
5662 + struct sdprofile *profile;
5663 + int i, error = 0, mode;
5665 +#define PROCPFX "/proc/"
5666 +#define PROCLEN sizeof(PROCPFX) - 1
5668 + SD_DEBUG("%s: %s 0x%x\n", __FUNCTION__, name, mask);
5670 + /* should not enter with other than R/W/M/X/L */
5672 + ~(SD_MAY_READ | SD_MAY_WRITE | SD_MAY_EXEC |
5673 + SD_EXEC_MMAP | SD_MAY_LINK));
5675 + /* not confined */
5676 + if (!__sd_is_confined(sd)) {
5677 + /* exit with access allowed */
5678 + SD_DEBUG("%s: not confined\n", __FUNCTION__);
5682 + /* Special case access to /proc/self/attr/current
5683 + * Currently we only allow access if opened O_WRONLY
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))
5690 + profile = sd->active;
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;
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))
5703 + list_for_each_entry(entry, &profile->file_entryp[i],
5705 + if (sdmatch_match(name, entry->filename,
5706 + entry->entry_type, entry->extradata)) {
5707 + /* Shortcut, accumulate all bits present */
5708 + mode |= entry->mode;
5711 + * Mask bits are overloaded
5712 + * MAY_{EXEC,WRITE,READ,APPEND} are used by
5713 + * kernel, other values are used locally only.
5715 + if ((mode & mask) == mask) {
5716 + SD_DEBUG("MATCH! %s=0x%x [total mode=0x%x]\n",
5717 + name, mask, mode);
5725 + /* return permissions not satisfied */
5726 + error = mask & ~mode;
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
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.
5742 +static int sd_link_perm(struct subdomain *sd,
5743 + const char *link, const char *target)
5745 + int l_mode, t_mode, ret;
5746 + struct sdprofile *profile = sd->active;
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;
5753 + t_mode = sd_file_mode(profile, target);
5754 + t_mode &= ~SD_MAY_LINK;
5756 + ret = (l_mode == t_mode);
5766 + * @sd: current subdomain
5767 + * @dentry: requested dentry
5768 + * @mask: mask of requested operations
5769 + * @pname: pointer to hold matched pathname (if any)
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.
5778 + * Return 0 (success), +ve (mask of permissions not satisfied) or -ve (system
5779 + * error, most likely -ENOMEM).
5781 +static int _sd_perm_dentry(struct subdomain *sd, struct dentry *dentry,
5782 + int mask, const char **pname)
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);
5789 + /* search all paths to dentry */
5791 + sd_path_begin(dentry, &data);
5793 + name = sd_path_getname(&data);
5795 + /* error here is 0 (success) or +ve (mask of perms) */
5796 + error = sd_file_perm(sd, name, mask);
5798 + /* access via any path is enough */
5799 + if (sdcomplain || error == 0)
5800 + break; /* Caller must free name */
5802 + /* Already have an path that failed? */
5803 + if (failed_name) {
5804 + sd_put_name(name);
5806 + failed_name = name;
5807 + failed_error = error;
5812 + if ((sdpath_error = sd_path_end(&data)) != 0) {
5813 + dentry_xlate_error(dentry, sdpath_error, "dentry");
5815 + WARN_ON(name); /* name should not be set if error */
5816 + error = sdpath_error;
5818 + } else if (name) {
5820 + sd_put_name(failed_name);
5822 + name = failed_name;
5823 + error = failed_error;
5831 +/**************************
5832 + * GLOBAL UTILITY FUNCTIONS
5833 + *************************/
5836 + * alloc_nullprofiles - Allocate null profiles
5838 +int alloc_nullprofiles(void)
5840 + null_profile = alloc_sdprofile();
5841 + null_complain_profile = alloc_sdprofile();
5843 + if (!null_profile || !null_complain_profile)
5846 + null_profile->name = kstrdup("null-profile", GFP_KERNEL);
5847 + null_complain_profile->name =
5848 + kstrdup("null-complain-profile", GFP_KERNEL);
5850 + if (!null_profile->name ||
5851 + !null_complain_profile->name)
5854 + get_sdprofile(null_profile);
5855 + get_sdprofile(null_complain_profile);
5856 + null_complain_profile->flags.complain = 1;
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;
5869 + * free_nullprofiles - Free null profiles
5871 +void free_nullprofiles(void)
5873 + put_sdprofile(null_complain_profile);
5874 + put_sdprofile(null_profile);
5875 + null_profile = null_complain_profile = NULL;
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
5885 +int sd_audit_message(struct subdomain *sd, unsigned int gfp, int flags,
5886 + const char *fmt, ...)
5889 + struct sd_audit sa;
5891 + sa.type = SD_AUDITTYPE_MSG;
5893 + va_start(sa.vaval, fmt);
5895 + sa.gfp_mask = gfp;
5897 + sa.result = 0; /* fake failure: force message to be logged */
5899 + ret = sd_audit(sd, &sa);
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
5912 +int sd_audit_syscallreject(struct subdomain *sd, unsigned int gfp,
5915 + struct sd_audit sa;
5917 + sa.type = SD_AUDITTYPE_SYSCALL;
5920 + sa.gfp_mask = gfp;
5922 + sa.result = 0; /* failure */
5924 + return sd_audit(sd, &sa);
5928 + * sd_audit - Log an audit event to the audit subsystem
5929 + * @sd: current subdomain
5930 + * @sa: audit event
5932 +int sd_audit(struct subdomain *sd, const struct sd_audit *sa)
5934 + struct audit_buffer *ab = NULL;
5935 + struct audit_context *ctx;
5937 + const char *logcls;
5938 + unsigned int flags;
5942 + opspec_error = -EACCES;
5944 + const unsigned int gfp_mask = sa->gfp_mask;
5946 + WARN_ON(sa->type >= SD_AUDITTYPE__END);
5949 + * sa->result: 1 success, 0 failure
5950 + * sa->errorcode: success: 0
5951 + * failure: +ve mask of failed permissions or -ve
5955 + if (likely(sa->result)) {
5956 + if (likely(!SUBDOMAIN_AUDIT(sd))) {
5957 + /* nothing to log */
5962 + logcls = "AUDITING";
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;
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.
5976 + logcls = "REJECTING";
5978 + sdcomplain = SUBDOMAIN_COMPLAIN(sd);
5979 + logcls = sdcomplain ? "PERMITTING" : "REJECTING";
5982 + /* In future extend w/ per-profile flags
5983 + * (flags |= sa->active->flags)
5985 + flags = sa->flags;
5986 + if (subdomain_logsyscall)
5987 + flags |= SD_AUDITFLAG_AUDITSS_SYSCALL;
5990 + /* Force full audit syscall logging regardless of global setting if
5991 + * we are rejecting a syscall
5993 + if (sa->type == SD_AUDITTYPE_SYSCALL) {
5994 + ctx = current->audit_context;
5996 + ctx = (flags & SD_AUDITFLAG_AUDITSS_SYSCALL) ?
5997 + current->audit_context : NULL;
6000 + ab = audit_log_start(ctx, gfp_mask, AUDIT_SD);
6003 + SD_ERROR("Unable to log event (%d) to audit subsys\n",
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);
6018 + /* log operation */
6020 + audit_log_format(ab, "%s ", logcls); /* REJECTING/ALLOWING/etc */
6022 + if (sa->type == SD_AUDITTYPE_FILE) {
6023 + int perm = sdaudit ? sa->ival : sa->errorcode;
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" : "",
6033 + opspec_error = -EPERM;
6035 + } else if (sa->type == SD_AUDITTYPE_DIR) {
6036 + audit_log_format(ab, "%s on %s ",
6037 + sa->ival == SD_DIR_MKDIR ? "mkdir" : "rmdir",
6040 + } else if (sa->type == SD_AUDITTYPE_ATTR) {
6041 + struct iattr *iattr = (struct iattr*)sa->pval;
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," : "",
6056 + } else if (sa->type == SD_AUDITTYPE_XATTR) {
6058 + switch (sa->ival) {
6059 + case SD_XATTR_GET:
6060 + fmt = "xattr get";
6062 + case SD_XATTR_SET:
6063 + fmt = "xattr set";
6065 + case SD_XATTR_LIST:
6066 + fmt = "xattr list";
6068 + case SD_XATTR_REMOVE:
6069 + fmt = "xattr remove";
6072 + fmt = "xattr <unknown>";
6076 + audit_log_format(ab, "%s on %s ", fmt, sa->name);
6078 + } else if (sa->type == SD_AUDITTYPE_LINK) {
6079 + audit_log_format(ab,
6080 + "link access from %s to %s ",
6084 + } else if (sa->type == SD_AUDITTYPE_CAP) {
6085 + audit_log_format(ab,
6086 + "access to capability '%s' ",
6087 + capability_to_name(sa->ival));
6089 + opspec_error = -EPERM;
6090 + } else if (sa->type == SD_AUDITTYPE_SYSCALL) {
6091 + audit_log_format(ab, "access to syscall '%s' ", sa->name);
6093 + opspec_error = -EPERM;
6095 + /* -EINVAL -- will WARN_ON above */
6099 + audit_log_format(ab, "(%s(%d) profile %s active %s)",
6100 + current->comm, current->pid,
6101 + sd->profile->name, sd->active->name);
6103 + audit_log_end(ab);
6108 + error = sa->result ? 0 : opspec_error;
6115 + * sd_get_name - retrieve fully qualified path name
6116 + * @dentry: relative path element
6117 + * @mnt: where in tree
6119 + * Returns fully qualified path name on sucess, NULL on failure.
6120 + * sd_put_name must be used to free allocated buffer.
6122 +char *sd_get_name(struct dentry *dentry, struct vfsmount *mnt)
6124 + char *page, *name;
6126 + page = (char *)__get_free_page(GFP_KERNEL);
6128 + name = ERR_PTR(-ENOMEM);
6132 + name = d_path(dentry, mnt, page, PAGE_SIZE);
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.
6138 + if (IS_ERR(name)) {
6139 + free_page((unsigned long)page);
6141 + const char deleted_str[] = " (deleted)";
6142 + const size_t deleted_size = sizeof(deleted_str) - 1;
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';
6150 + SD_DEBUG("%s: full_path=%s\n", __FUNCTION__, name);
6157 +/***********************************
6158 + * GLOBAL PERMISSION CHECK FUNCTIONS
6159 + ***********************************/
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
6167 +int sd_attr(struct subdomain *sd, struct dentry *dentry, struct iattr *iattr)
6169 + int error = 0, permerror;
6170 + struct sd_audit sa;
6172 + if (!__sd_is_confined(sd))
6175 + sa.type = SD_AUDITTYPE_ATTR;
6178 + sa.gfp_mask = GFP_KERNEL;
6180 + permerror = _sd_perm_dentry(sd, dentry, MAY_WRITE, &sa.name);
6181 + sd_permerror2result(permerror, &sa);
6183 + error = sd_audit(sd, &sa);
6185 + sd_put_name(sa.name);
6191 +int sd_xattr(struct subdomain *sd, struct dentry *dentry, const char *xattr,
6194 + int error = 0, permerror, mask = 0;
6195 + struct sd_audit sa;
6197 + /* if not confined or empty mask permission granted */
6198 + if (!__sd_is_confined(sd))
6201 + if (xattroptype == SD_XATTR_GET || xattroptype == SD_XATTR_LIST)
6203 + else if (xattroptype == SD_XATTR_SET || xattroptype == SD_XATTR_REMOVE)
6206 + sa.type = SD_AUDITTYPE_XATTR;
6207 + sa.ival = xattroptype;
6210 + sa.gfp_mask = GFP_KERNEL;
6212 + permerror = _sd_perm_dentry(sd, dentry, mask, &sa.name);
6213 + sd_permerror2result(permerror, &sa);
6215 + error = sd_audit(sd, &sa);
6217 + sd_put_name(sa.name);
6224 + * sd_perm - basic subdomain permissions check
6225 + * @sd: subdomain to check against
6227 + * @mnt: mountpoint
6228 + * @mask: access mode requested
6230 + * Determine if access (mask) for dentry is authorized by subdomain sd.
6231 + * Result, 0 (success), -ve (error)
6233 +int sd_perm(struct subdomain *sd, struct dentry *dentry, struct vfsmount *mnt,
6236 + int error = 0, permerror;
6237 + struct sd_audit sa;
6239 + if (!__sd_is_confined(sd))
6242 + if ((mask = sd_filter_mask(mask, dentry->d_inode)) == 0)
6245 + sa.type = SD_AUDITTYPE_FILE;
6246 + sa.name = sd_get_name(dentry, mnt);
6249 + sa.gfp_mask = GFP_KERNEL;
6251 + if (IS_ERR(sa.name)) {
6252 + permerror = PTR_ERR(sa.name);
6255 + permerror = sd_file_perm(sd, sa.name, mask);
6258 + sd_permerror2result(permerror, &sa);
6260 + error = sd_audit(sd, &sa);
6262 + sd_put_name(sa.name);
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
6274 +int sd_perm_nameidata(struct subdomain *sd, struct nameidata *nd, int mask)
6279 + error = sd_perm(sd, nd->dentry, nd->mnt, mask);
6285 + * sd_perm_dentry - file permissions interface when no vfsmnt available
6286 + * @sd: current subdomain
6287 + * @dentry: requested dentry
6288 + * @mask: access mode requested
6290 + * Determine if access (mask) for dentry is authorized by subdomain sd.
6291 + * Result, 0 (success), -ve (error)
6293 +int sd_perm_dentry(struct subdomain *sd, struct dentry *dentry, int mask)
6295 + int error = 0, permerror;
6296 + struct sd_audit sa;
6298 + if (!__sd_is_confined(sd))
6301 + if ((mask = sd_filter_mask(mask, dentry->d_inode)) == 0)
6304 + sa.type = SD_AUDITTYPE_FILE;
6307 + sa.gfp_mask = GFP_KERNEL;
6309 + permerror = _sd_perm_dentry(sd, dentry, mask, &sa.name);
6310 + sd_permerror2result(permerror, &sa);
6312 + error = sd_audit(sd, &sa);
6314 + sd_put_name(sa.name);
6322 + * @sd: current subdomain
6323 + * @dentry: requested dentry
6324 + * @mode: SD_DIR_MKDIR or SD_DIR_RMDIR
6326 + * Determine if directory operation (make/remove) for dentry is authorized
6327 + * by subdomain sd.
6328 + * Result, 0 (success), -ve (error)
6330 +int sd_perm_dir(struct subdomain *sd, struct dentry *dentry, int diroptype)
6332 + int error = 0, permerror, mask;
6333 + struct sd_audit sa;
6335 + BUG_ON(diroptype != SD_DIR_MKDIR && diroptype != SD_DIR_RMDIR);
6337 + if (!__sd_is_confined(sd))
6342 + sa.type = SD_AUDITTYPE_DIR;
6343 + sa.ival = diroptype;
6345 + sa.gfp_mask = GFP_KERNEL;
6347 + permerror = _sd_perm_dentry(sd, dentry, mask, &sa.name);
6348 + sd_permerror2result(permerror, &sa);
6350 + error = sd_audit(sd, &sa);
6352 + sd_put_name(sa.name);
6359 + * sd_capability - test permission to use capability
6360 + * @sd: subdomain to check against
6361 + * @cap: capability to be tested
6363 + * Look up capability in active profile capability set.
6364 + * Return 0 (success), -EPERM (error)
6366 +int sd_capability(struct subdomain *sd, int cap)
6370 + if (__sd_is_confined(sd)) {
6371 + struct sd_audit sa;
6373 + sa.type = SD_AUDITTYPE_CAP;
6378 + sa.result = cap_raised(sd->active->capabilities, cap);
6379 + sa.gfp_mask = GFP_ATOMIC;
6381 + error = sd_audit(sd, &sa);
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
6393 + * Checks link permissions for all possible name combinations. This is
6394 + * particularly ugly. Returns 0 on sucess, error otherwise.
6396 +int sd_link(struct subdomain *sd, struct dentry *link, struct dentry *target)
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;
6406 + if (!__sd_is_confined(sd))
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
6416 + * Getting direct access to vfsmounts (via nameidata) for link and
6417 + * target would allow all this uglyness to go away.
6419 + * If more than one mountpoint matches but none satisfy the profile,
6420 + * only the first pathname (mountpoint) is logged.
6423 + sd_path_begin2(target, link, &odata);
6425 + oname = sd_path_getname(&odata);
6427 + sd_path_begin(target, &idata);
6429 + iname = sd_path_getname(&idata);
6431 + result = sd_link_perm(sd, oname, iname);
6433 + /* access via any path is enough */
6434 + if (result || sdcomplain) {
6439 + /* Already have an path that failed? */
6440 + if (failed_iname) {
6441 + sd_put_name(iname);
6443 + failed_iname = iname;
6444 + failed_oname = oname;
6447 + } while (iname && !match);
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]");
6454 + /* name should not be set if error */
6457 + errorcode = sdpath_error;
6460 + /* don't release if we're saving it */
6461 + if (!match && failed_oname != oname)
6462 + sd_put_name(oname);
6464 + } while (oname && !match);
6466 + if (errorcode != 0) {
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]");
6472 + errorcode = sdpath_error;
6475 + if (errorcode != 0) {
6476 + /* inner or outer error */
6478 + } else if (match) {
6481 + /* failed to match */
6486 + iname = failed_iname;
6487 + oname = failed_oname;
6490 + sa.type = SD_AUDITTYPE_LINK;
6491 + sa.name = oname; /* link */
6492 + sa.pval = iname; /* target */
6494 + sa.errorcode = errorcode;
6495 + sa.result = result;
6496 + sa.gfp_mask = GFP_KERNEL;
6498 + error = sd_audit(sd, &sa);
6500 + if (failed_oname != oname)
6501 + sd_put_name(failed_oname);
6502 + if (failed_iname != iname)
6503 + sd_put_name(failed_iname);
6505 + sd_put_name(oname);
6506 + sd_put_name(iname);
6511 +/**********************************
6512 + * GLOBAL PROCESS RELATED FUNCTIONS
6513 + *********************************/
6516 + * sd_fork - create a new subdomain
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.
6525 +int sd_fork(struct task_struct *p)
6527 + struct subdomain *sd = SD_SUBDOMAIN(current->security);
6528 + struct subdomain *newsd = NULL;
6530 + SD_DEBUG("%s\n", __FUNCTION__);
6532 + if (__sd_is_confined(sd)) {
6533 + unsigned long flags;
6535 + newsd = alloc_subdomain(p);
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
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);
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);
6556 + p->security = newsd;
6561 + * sd_register - register a new program
6562 + * @filp: file of program being registered
6564 + * Try to register a new program during execve(). This should give the
6565 + * new program a valid subdomain.
6567 + * This _used_ to be a really simple piece of code :-(
6570 +int sd_register(struct linux_binprm *bprm)
6573 + struct file *filp = bprm->file;
6574 + struct subdomain *sd, sdcopy;
6575 + struct sdprofile *newprofile = NULL, unconstrained_flag;
6576 + int error = -ENOMEM,
6579 + findprofile_mandatory = 0,
6583 + SD_DEBUG("%s\n", __FUNCTION__);
6585 + sd = get_sdcopy(&sdcopy);
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__);
6595 + if (!__sd_is_confined(sd)) {
6596 + /* Unconfined task, load profile if it exists */
6598 + goto find_profile;
6601 + complain = SUBDOMAIN_COMPLAIN(sd);
6603 + /* Confined task, determine what mode inherit, unconstrained or
6604 + * mandatory to load new profile
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
6612 + SD_DEBUG("%s: INHERIT %s\n",
6617 + case SD_EXEC_UNCONSTRAINED:
6618 + SD_DEBUG("%s: UNCONSTRAINED %s\n",
6622 + /* unload profile */
6623 + newprofile = &unconstrained_flag;
6626 + case SD_EXEC_PROFILE:
6627 + SD_DEBUG("%s: PROFILE %s\n",
6632 + findprofile_mandatory = 1;
6636 + /* this should not happen, entries
6637 + * with just EXEC only should be
6638 + * rejected at profile load time
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",
6645 + current->comm, current->pid,
6646 + sd->profile->name, sd->active->name);
6651 + SD_ERROR("%s: Rejecting exec(2) of image '%s'. "
6652 + "Unknown exec qualifier %x "
6653 + "(%s (pid %d) profile %s active %s)\n",
6657 + current->comm, current->pid,
6658 + sd->profile->name, sd->active->name);
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).
6668 + newprofile = get_sdprofile(null_complain_profile);
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",
6676 + current->comm, current->pid,
6677 + sd->profile->name, sd->active->name);
6684 + goto apply_profile;
6686 + /* Locate new profile */
6687 + newprofile = sd_profilelist_find(filename);
6689 + SD_DEBUG("%s: setting profile %s\n",
6690 + __FUNCTION__, newprofile->name);
6691 + } else if (findprofile_mandatory) {
6692 + /* Profile (mandatory) could not be found */
6695 + LOG_HINT(sd, GFP_KERNEL, HINT_MANDPROF,
6696 + "image=%s pid=%d profile=%s active=%s\n",
6699 + sd->profile->name,
6700 + sd->active->name);
6702 + newprofile = get_sdprofile(null_complain_profile);
6704 + SD_WARN("REJECTING exec(2) of image '%s'. "
6705 + "Profile mandatory and not found "
6706 + "(%s(%d) profile %s active %s)\n",
6708 + current->comm, current->pid,
6709 + sd->profile->name, sd->active->name);
6713 + /* Profile (non-mandatory) could not be found */
6715 + /* Only way we can get into this code is if task
6716 + * is unconstrained.
6719 + BUG_ON(__sd_is_confined(sd));
6721 + SD_DEBUG("%s: No profile found for exec image %s\n",
6724 + } /* newprofile */
6728 + /* Apply profile if necessary */
6730 + struct subdomain *latest_sd, *lazy_sd = NULL;
6731 + unsigned long flags;
6733 + if (newprofile == &unconstrained_flag)
6734 + newprofile = NULL;
6736 + /* grab a write lock
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.
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.
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.
6754 + lazy_sd = alloc_subdomain(current);
6757 + write_lock_irqsave(&sd_lock, flags);
6759 + latest_sd = SD_SUBDOMAIN(current->security);
6763 + /* raced by setprofile (created latest_sd) */
6764 + free_subdomain(lazy_sd);
6769 + latest_sd = lazy_sd;
6770 + current->security = lazy_sd;
6772 + SD_ERROR("%s: Failed to allocate subdomain\n",
6776 + write_unlock_irqrestore(&sd_lock, flags);
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.
6785 + if (newprofile && unlikely(newprofile->isstale)) {
6786 + BUG_ON(newprofile == null_complain_profile);
6788 + /* drop refcnt obtained from earlier get_sdprofile */
6789 + put_sdprofile(newprofile);
6791 + newprofile = sd_profilelist_find(filename);
6793 + if (!newprofile) {
6794 + /* Race, profile was removed, not replaced.
6795 + * Redo with error checking
6797 + write_unlock_irqrestore(&sd_lock, flags);
6798 + goto find_profile;
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
6808 + * Cases 2 and 3 are marked as requiring secure exec
6809 + * (unless policy specified "unsafe exec")
6811 + if (__sd_is_confined(latest_sd) && !unsafe_exec) {
6812 + unsigned long bprm_flags;
6814 + bprm_flags = SD_SECURE_EXEC_NEEDED;
6815 + bprm->security = (void*)
6816 + ((unsigned long)bprm->security | bprm_flags);
6819 + sd_switch(latest_sd, newprofile, newprofile);
6820 + put_sdprofile(newprofile);
6822 + if (complain && newprofile == null_complain_profile)
6823 + LOG_HINT(latest_sd, GFP_ATOMIC, HINT_CHGPROF,
6827 + write_unlock_irqrestore(&sd_lock, flags);
6831 + sd_put_name(filename);
6841 + * sd_release - release the task's subdomain
6842 + * @p: task being released
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.
6847 +void sd_release(struct task_struct *p)
6849 + struct subdomain *sd = SD_SUBDOMAIN(p->security);
6850 + p->security = NULL;
6852 + sd_subdomainlist_remove(sd);
6854 + /* release profiles */
6855 + put_sdprofile(sd->profile);
6856 + put_sdprofile(sd->active);
6861 +/*****************************
6862 + * GLOBAL SUBPROFILE FUNCTIONS
6863 + ****************************/
6866 + * do_change_hat - actually switch hats
6867 + * @name: name of hat to swtich to
6868 + * @sd: current subdomain
6870 + * Switch to a new hat. Return 0 on success, error otherwise.
6872 +static inline int do_change_hat(const char *hat_name, struct subdomain *sd)
6874 + struct sdprofile *sub;
6875 + struct sdprofile *p = sd->active;
6878 + sub = __sd_find_profile(hat_name, &sd->profile->sub);
6884 + /* There is no such subprofile change to a NULL profile.
6885 + * The NULL profile grants no file access.
6887 + * This feature is used by changehat_apache.
6889 + * N.B from the null-profile the task can still changehat back
6890 + * out to the parent profile (assuming magic != NULL)
6892 + if (SUBDOMAIN_COMPLAIN(sd)) {
6893 + LOG_HINT(sd, GFP_ATOMIC, HINT_UNKNOWN_HAT,
6895 + "profile=%s active=%s\n",
6898 + sd->profile->name,
6899 + sd->active->name);
6900 + sd->active = get_sdprofile(null_complain_profile);
6902 + SD_DEBUG("%s: Unknown hatname '%s'. "
6903 + "Changing to NULL profile "
6904 + "(%s(%d) profile %s active %s)\n",
6907 + current->comm, current->pid,
6908 + sd->profile->name, sd->active->name);
6910 + sd->active = get_sdprofile(null_profile);
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
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
6930 +#define IN_SUBPROFILE(sd) ((sd)->profile != (sd)->active)
6931 +int sd_change_hat(const char *hat_name, __u32 hat_magic)
6933 + struct subdomain *sd = SD_SUBDOMAIN(current->security);
6936 + SD_DEBUG("%s: %p, 0x%x (pid %d)\n",
6938 + hat_name, hat_magic,
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);
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. */
6953 + /* check to see if an unconfined process is doing a changehat. */
6954 + if (!__sd_is_confined(sd)) {
6959 + /* Check whether current domain is parent
6960 + * or one of the sibling children
6962 + if (sd->profile == sd->active) {
6967 + SD_DEBUG("%s: switching to %s, 0x%x\n",
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
6979 + sd->sd_hat_magic = hat_magic;
6980 + error = do_change_hat(hat_name, sd);
6982 + /* Got here via changehat(NULL, magic)
6984 + * We used to simply update the magic cookie.
6985 + * That's an odd behaviour, so just do nothing.
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
6995 + if (hat_magic == sd->sd_hat_magic && sd->sd_hat_magic) {
6998 + * Got here via changehat(NULL, magic)
6999 + * Return from subprofile, back to parent
7001 + put_sdprofile(sd->active);
7002 + sd->active = get_sdprofile(sd->profile);
7004 + /* Reset hat_magic to zero.
7005 + * New value will be passed on next changehat
7007 + sd->sd_hat_magic = 0;
7009 + /* change to another (sibling) profile */
7010 + error = do_change_hat(hat_name, sd);
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,
7018 + hat_name ? hat_name : "NULL",
7019 + sd->profile->name, sd->active->name);
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);
7030 + /* terminate current process */
7031 + (void)send_sig_info(SIGKILL, NULL, current);
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
7042 +# Makefile for AppArmor Linux Security Module (previously called "SubDomain")
7044 +# kernel build Makefile is the Kbuild file
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: //" ; \
7050 +ifeq ("${REPO_VERSION}", "")
7051 +REPO_VERSION := "unknown"
7054 +KERNELVER := $(shell uname -r)
7056 +KERNELDIR := /lib/modules/${KERNELVER}/build
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
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
7071 + * Copyright (C) 1998-2005 Novell/SUSE
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
7078 + * AppArmor userspace policy interface
7081 +#include <asm/unaligned.h>
7083 +#include "apparmor.h"
7084 +#include "inline.h"
7085 +#include "module_interface.h"
7086 +#include "aamatch/match.h"
7088 +/* sd_code defined in module_interface.h */
7090 +const int sdcode_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
7092 +struct sd_taskreplace_data {
7093 + struct sdprofile *old_profile;
7094 + struct sdprofile *new_profile;
7097 +/* inlines must be forward of there use in newer version of gcc,
7098 + just forward declaring with a prototype won't work anymore */
7100 +static inline void free_sd_entry(struct sd_entry *entry)
7103 + kfree(entry->filename);
7104 + sdmatch_free(entry->extradata);
7110 + * alloc_sd_entry - create new empty sd_entry
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.
7116 +static inline struct sd_entry *alloc_sd_entry(void)
7118 + struct sd_entry *entry;
7120 + SD_DEBUG("%s\n", __FUNCTION__);
7121 + entry = kmalloc(sizeof(struct sd_entry), GFP_KERNEL);
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]);
7134 + * free_sdprofile - free sdprofile structure
7136 +void free_sdprofile(struct sdprofile *profile)
7138 + struct sd_entry *sdent, *tmp;
7139 + struct sdprofile *p, *ptmp;
7141 + SD_DEBUG("%s(%p)\n", __FUNCTION__, profile);
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",
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);
7163 + list_for_each_entry_safe(p, ptmp, &profile->sub, list) {
7164 + list_del_init(&p->list);
7168 + if (profile->name) {
7169 + SD_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
7170 + kfree(profile->name);
7178 + * remove profile in a task's subdomain leaving the task unconfined
7180 + * @sd: task's subdomain
7182 +static inline void task_remove(struct subdomain *sd)
7184 + /* write_lock(&sd_lock) held here */
7185 + SD_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
7189 + sd->profile->name,
7190 + sd->active->name);
7192 + sd_switch_unconfined(sd);
7195 +/** taskremove_iter
7197 + * Iterate over all subdomains.
7199 + * If any matches old_profile, then call task_remove to remove it.
7200 + * This leaves the task (subdomain) unconfined.
7202 +static int taskremove_iter(struct subdomain *sd, void *cookie)
7204 + struct sdprofile *old_profile = (struct sdprofile *)cookie;
7205 + unsigned long flags;
7207 + write_lock_irqsave(&sd_lock, flags);
7209 + if (__sd_is_confined(sd) && sd->profile == old_profile)
7212 + write_unlock_irqrestore(&sd_lock, flags);
7219 + * replace profile in a task's subdomain with newly loaded profile
7221 + * @sd: task's subdomain
7222 + * @new: old profile
7224 +static inline void task_replace(struct subdomain *sd, struct sdprofile *new)
7226 + struct sdprofile *nactive = NULL;
7228 + SD_DEBUG("%s: replacing profile for task %s(%d) "
7229 + "profile=%s (%p) active=%s (%p)\n",
7231 + sd->task->comm, sd->task->pid,
7232 + sd->profile->name, sd->profile,
7233 + sd->active->name, sd->active);
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);
7242 + if (new->flags.complain)
7243 + nactive = get_sdprofile(null_complain_profile);
7245 + nactive = get_sdprofile(null_profile);
7248 + sd_switch(sd, new, nactive);
7250 + put_sdprofile(nactive);
7253 +/** taskreplace_iter
7255 + * Iterate over all subdomains.
7257 + * If any matches old_profile, then call task_replace to replace with
7260 +static int taskreplace_iter(struct subdomain *sd, void *cookie)
7262 + struct sd_taskreplace_data *data = (struct sd_taskreplace_data *)cookie;
7263 + unsigned long flags;
7265 + write_lock_irqsave(&sd_lock, flags);
7267 + if (__sd_is_confined(sd) && sd->profile == data->old_profile)
7268 + task_replace(sd, data->new_profile);
7270 + write_unlock_irqrestore(&sd_lock, flags);
7275 +static inline int sd_inbounds(struct sd_ext *e, size_t size)
7277 + return (e->pos + size <= e->end);
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
7288 +static void sdconvert(enum sd_code code, void *dest, void *src)
7292 + *(u8 *)dest = *(u8 *) src;
7296 + case SD_DYN_STRING:
7297 + *(u16 *)dest = le16_to_cpu(get_unaligned((u16 *)src));
7300 + case SD_STATIC_BLOB:
7301 + *(u32 *)dest = le32_to_cpu(get_unaligned((u32 *)src));
7304 + *(u64 *)dest = le64_to_cpu(get_unaligned((u64 *)src));
7307 + /* nop - all other type codes do not have a trailing value */
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
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
7325 +static u32 sd_is_X(struct sd_ext *e, enum sd_code code, void *data)
7327 + void *pos = e->pos;
7329 + if (!sd_inbounds(e, SD_CODE_BYTE + sdcode_datasize[code]))
7331 + if (code != *(u8 *)e->pos)
7333 + e->pos += SD_CODE_BYTE;
7334 + if (code == SD_NAME) {
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))
7341 + *(u16 *)data = size;
7342 + e->pos += sdcode_datasize[code];
7343 + ret = 1 + sdcode_datasize[code];
7344 + } else if (code == SD_DYN_STRING) {
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))
7353 + * (char **)data = NULL;
7354 + str = kmalloc(size, GFP_KERNEL);
7357 + memcpy(str, e->pos, (size_t) size);
7358 + str[size-1] = '\0';
7359 + * (char **)data = str;
7363 + } else if (code == SD_STATIC_BLOB) {
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))
7371 + memcpy(data, e->pos, (size_t) size);
7376 + sdconvert(code, data, e->pos);
7377 + e->pos += sdcode_datasize[code];
7378 + ret = 1 + sdcode_datasize[code];
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
7393 +static int sd_is_nameX(struct sd_ext *e, enum sd_code code, void *data,
7396 + void *pos = e->pos;
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)))
7408 + /* now check if data actually matches */
7409 + ret = sd_is_X(e, code, data);
7419 +/* macro to wrap error case to make a block of reads look nicer */
7420 +#define SD_READ_X(E, C, D, N) \
7423 + __ret = sd_is_nameX((E), (C), (D), (N)); \
7429 + * sd_activate_net_entry - ignores/skips net entries if the they are present
7430 + * in the data stream.
7431 + * @e: extent information
7433 +static inline int sd_activate_net_entry(struct sd_ext *e)
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);
7454 +static inline struct sd_entry *sd_activate_file_entry(struct sd_ext *e)
7456 + struct sd_entry *entry = NULL;
7458 + if (!(entry = alloc_sd_entry()))
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");
7466 + entry->extradata = sdmatch_alloc(entry->entry_type);
7467 + if (IS_ERR(entry->extradata)) {
7468 + entry->extradata = NULL;
7472 + if (entry->extradata &&
7473 + sdmatch_serialize(entry->extradata, e, sd_is_nameX) != 0) {
7476 + SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
7478 + switch (entry->entry_type) {
7479 + case sd_entry_literal:
7480 + SD_DEBUG("%s: %s [no pattern] mode=0x%x\n",
7485 + case sd_entry_tailglob:
7486 + SD_DEBUG("%s: %s [tailglob] mode=0x%x\n",
7491 + case sd_entry_pattern:
7492 + SD_DEBUG("%s: %s mode=0x%x\n",
7498 + SD_WARN("%s: INVALID entry_type %d\n",
7500 + (int)entry->entry_type);
7507 + sdmatch_free(entry->extradata);
7508 + free_sd_entry(entry);
7512 +static inline int check_rule_and_add(struct sd_entry *file_entry,
7513 + struct sdprofile *profile,
7514 + const char **message)
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);
7521 + if (mode && !(SD_MAY_EXEC & file_entry->mode)) {
7522 + *message = "inconsistent rule, x modifiers without x";
7526 + /* check that only 1 of the modifiers is set */
7527 + if (mode && (mode & (mode - 1))) {
7528 + *message = "inconsistent rule, multiple x modifiers";
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;
7536 + list_add(&file_entry->list, &profile->file_entry);
7537 + profile->num_file_entries++;
7539 + mode = file_entry->mode;
7541 + /* Handle partitioned lists
7542 + * Chain entries onto sublists based on individual
7543 + * permission bits. This allows more rapid searching.
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]);
7556 + free_sd_entry(file_entry);
7560 +#define SD_ENTRY_LIST(NAME) \
7562 + if (sd_is_nameX(e, SD_LIST, NULL, (NAME))) { \
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) \
7570 + if (!check_rule_and_add(file_entry, profile, \
7571 + &error_string)) { \
7572 + rulename = file_entry->filename; \
7579 +struct sdprofile *sd_activate_profile(struct sd_ext *e, ssize_t *error)
7581 + struct sdprofile *profile = NULL;
7582 + const char *rulename = "";
7583 + const char *error_string = "Invalid Profile";
7587 + profile = alloc_sdprofile();
7589 + error_string = "Could not allocate profile";
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);
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);
7607 + error_string = "Invalid capabilities";
7608 + SD_READ_X(e, SD_U32, &(profile->capabilities), "profile.capabilities");
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 */
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))
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);
7633 + get_sdprofile(subprofile);
7634 + list_add(&subprofile->list, &profile->sub);
7638 + error_string = "Invalid end of profile";
7639 + SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
7644 + SD_WARN("%s: %s %s in profile %s\n", INTERFACE_ID, rulename,
7645 + error_string, profile && profile->name ? profile->name
7649 + free_sdprofile(profile);
7656 +void *sd_activate_top_profile(struct sd_ext *e, ssize_t *error)
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;
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;
7673 + return sd_activate_profile(e, error);
7678 +ssize_t sd_file_prof_add(void *data, size_t size)
7680 + struct sdprofile *profile = NULL;
7682 + struct sd_ext e = { data, data + size, data };
7685 + profile = sd_activate_top_profile(&e, &error);
7687 + SD_DEBUG("couldn't activate profile\n");
7691 + if (!sd_profilelist_add(profile)) {
7692 + SD_WARN("trying to add profile (%s) that already exists.\n",
7694 + free_sdprofile(profile);
7701 +ssize_t sd_file_prof_repl(void *udata, size_t size)
7703 + struct sd_taskreplace_data data;
7704 + struct sd_ext e = { udata, udata + size, udata };
7707 + data.new_profile = sd_activate_top_profile(&e, &error);
7708 + if (!data.new_profile) {
7709 + SD_DEBUG("couldn't activate profile\n");
7712 + /* Grab reference to close race window (see comment below) */
7713 + get_sdprofile(data.new_profile);
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.
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.
7724 + data.old_profile = sd_profilelist_replace(data.new_profile);
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.
7738 + /* If there was an old profile, find all currently executing tasks
7739 + * using this profile and replace the old profile with the new.
7741 + if (data.old_profile) {
7742 + SD_DEBUG("%s: try to replace profile (%p)%s\n",
7745 + data.old_profile->name);
7747 + sd_subdomainlist_iterate(taskreplace_iter, (void *)&data);
7749 + /* it's off global list, and we are done replacing */
7750 + put_sdprofile(data.old_profile);
7753 + /* Free reference obtained above */
7754 + put_sdprofile(data.new_profile);
7759 +ssize_t sd_file_prof_remove(const char *name, size_t size)
7761 + struct sdprofile *old_profile;
7763 + /* if the old profile exists it will be removed from the list and
7764 + * a reference is returned.
7766 + old_profile = sd_profilelist_remove(name);
7768 + if (old_profile) {
7769 + /* remove profile from any tasks using it */
7770 + sd_subdomainlist_iterate(taskremove_iter, (void *)old_profile);
7772 + /* drop reference obtained by sd_profilelist_remove */
7773 + put_sdprofile(old_profile);
7775 + SD_WARN("%s: trying to remove profile (%s) that "
7776 + "doesn't exist - skipping.\n", __FUNCTION__, name);
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
7785 +#ifndef __MODULEINTERFACE_H
7786 +#define __MODULEINTERFACE_H
7788 +/* Codes of the types of basic structures that are understood */
7789 +#define SD_CODE_BYTE (sizeof(u8))
7790 +#define INTERFACE_ID "INTERFACE"
7792 +#define SUBDOMAIN_INTERFACE_VERSION 2
7799 + SD_NAME, /* same as string except it is items name */
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.
7817 + void *pos; /* pointer to current position in the buffer */
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
7826 + * Copyright (C) 2005 Novell/SUSE
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
7833 + * AppArmor /proc/pid/attr handling
7837 +#include <linux/ctype.h>
7839 +#include "apparmor.h"
7840 +#include "inline.h"
7842 +size_t sd_getprocattr(struct subdomain *sd, char *str, size_t size)
7844 + int error = -EACCES; /* default to a perm denied */
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;
7854 + lenm = strlen(mode_str);
7856 + lena = strlen(sd->active->name);
7859 + if (sd->active != sd->profile) {
7860 + lenp = strlen(sd->profile->name);
7861 + len += (lenp + 1); /* +1 for ^ */
7863 + /* DONT null terminate strings we output via proc */
7864 + len += (lenm + 1); /* for \n */
7866 + if (len <= size) {
7868 + memcpy(str, sd->profile->name, lenp);
7873 + memcpy(str, sd->active->name, lena);
7875 + memcpy(str, mode_str, lenm);
7883 + const char *unconstrained_str = SD_UNCONSTRAINED "\n";
7884 + len = strlen(unconstrained_str);
7886 + /* DONT null terminate strings we output via proc */
7887 + if (len <= size) {
7888 + memcpy(str, unconstrained_str, len);
7898 +int sd_setprocattr_changehat(char *hatinfo, size_t infosize)
7900 + int error = -EINVAL;
7901 + char *token = NULL, *hat, *smagic, *tmp;
7903 + int rc, len, consumed;
7904 + unsigned long flags;
7906 + SD_DEBUG("%s: %p %zd\n", __FUNCTION__, hatinfo, infosize);
7908 + /* strip leading white space */
7909 + while (infosize && isspace(*hatinfo)) {
7914 + if (infosize == 0)
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
7922 + token = kmalloc(infosize + 1, GFP_KERNEL);
7929 + memcpy(token, hatinfo, infosize);
7930 + token[infosize] = 0;
7932 + /* error is INVAL until we have at least parsed something */
7936 + while (*tmp && *tmp != '^') {
7940 + if (!*tmp || tmp == token) {
7941 + SD_WARN("%s: Invalid input '%s'\n", __FUNCTION__, token);
7945 + /* split magic and hat into two strings */
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.
7955 + consumed = len = strlen(smagic);
7957 + rc = sscanf(smagic, "%x%n", &magic, &consumed);
7959 + if (rc != 1 || consumed != len) {
7960 + SD_WARN("%s: Invalid hex magic %s\n",
7971 + if (!hat && !magic) {
7972 + SD_WARN("%s: Invalid input, NULL hat and NULL magic\n",
7977 + SD_DEBUG("%s: Magic 0x%x Hat '%s'\n",
7978 + __FUNCTION__, magic, hat ? hat : NULL);
7980 + write_lock_irqsave(&sd_lock, flags);
7981 + error = sd_change_hat(hat, magic);
7982 + write_unlock_irqrestore(&sd_lock, flags);
7986 + memset(token, 0, infosize);
7993 +int sd_setprocattr_setprofile(struct task_struct *p, char *profilename,
7994 + size_t profilesize)
7996 + int error = -EINVAL;
7997 + struct sdprofile *profile;
7998 + struct subdomain *sd;
7999 + char *name = NULL;
8000 + unsigned long flags;
8002 + SD_DEBUG("%s: current %s(%d)\n",
8003 + __FUNCTION__, current->comm, current->pid);
8005 + /* strip leading white space */
8006 + while (profilesize && isspace(*profilename)) {
8011 + if (profilesize == 0)
8015 + * Copy string to a new buffer so we guarantee it is zero
8018 + name = kmalloc(profilesize + 1, GFP_KERNEL);
8025 + strncpy(name, profilename, profilesize);
8026 + name[profilesize] = 0;
8029 + if (strcmp(name, SD_UNCONSTRAINED) == 0)
8030 + profile = null_profile;
8032 + profile = sd_profilelist_find(name);
8035 + SD_WARN("%s: Unable to switch task %s(%d) to profile '%s'. "
8036 + "No such profile.\n",
8046 + write_lock_irqsave(&sd_lock, flags);
8048 + sd = SD_SUBDOMAIN(p->security);
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",
8057 + sd->profile->name,
8058 + sd->active->name);
8060 + sd_switch_unconfined(sd);
8062 + SD_WARN("%s: task %s(%d) "
8063 + "is already unconstrained\n",
8064 + __FUNCTION__, p->comm, p->pid);
8068 + /* this task was created before module was
8069 + * loaded, allocate a subdomain
8071 + SD_WARN("%s: task %s(%d) has no subdomain\n",
8072 + __FUNCTION__, p->comm, p->pid);
8074 + /* unlock so we can safely GFP_KERNEL */
8075 + write_unlock_irqrestore(&sd_lock, flags);
8077 + sd = alloc_subdomain(p);
8079 + SD_WARN("%s: Unable to allocate subdomain for "
8080 + "task %s(%d). Cannot confine task to "
8087 + put_sdprofile(profile);
8092 + write_lock_irqsave(&sd_lock, flags);
8093 + if (!p->security) {
8095 + } else { /* race */
8096 + free_subdomain(sd);
8097 + sd = SD_SUBDOMAIN(p->security);
8101 + /* ensure the profile hasn't been replaced */
8103 + if (unlikely(profile->isstale)) {
8104 + WARN_ON(profile == null_complain_profile);
8106 + /* drop refcnt obtained from earlier get_sdprofile */
8107 + put_sdprofile(profile);
8108 + profile = sd_profilelist_find(name);
8111 + /* Race, profile was removed. */
8112 + write_unlock_irqrestore(&sd_lock, flags);
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.
8124 + SD_WARN("%s: Switching task %s(%d) "
8125 + "profile %s active %s to new profile %s\n",
8128 + sd->profile ? sd->profile->name : SD_UNCONSTRAINED,
8129 + sd->active ? sd->profile->name : SD_UNCONSTRAINED,
8132 + sd_switch(sd, profile, profile);
8134 + put_sdprofile(profile); /* drop ref we obtained above
8135 + * from sd_profilelist_find
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
8142 + sd->sd_hat_magic = 0;
8145 + write_unlock_irqrestore(&sd_lock, flags);
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
8158 + * Copyright (C) 2000, 2001, 2004, 2005 Novell/SUSE
8160 + * Immunix AppArmor LSM
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
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 */
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
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)
8199 +#define SD_EXEC_MODIFIERS (SD_EXEC_INHERIT | \
8200 + SD_EXEC_UNCONSTRAINED | \
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.
8209 source security/selinux/Kconfig
8210 +source security/apparmor/Kconfig
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
8218 obj-$(CONFIG_KEYS) += keys/
8219 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
8220 +obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
8222 # if we don't select a security model, use the default capabilities
8223 ifneq ($(CONFIG_SECURITY),y)