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