]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.apparmor/apparmor-module_interface.diff
Revert "Move xen patchset to new version's subdir."
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.apparmor / apparmor-module_interface.diff
CommitLineData
8f69975d
BS
1From: John Johansen <jjohansen@suse.de>
2Subject: AppArmor: Profile loading and manipulation, pathname matching
3
4Pathname matching, transition table loading, profile loading and
5manipulation.
6
7Signed-off-by: John Johansen <jjohansen@suse.de>
8Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
9
10---
11 security/apparmor/match.c | 364 ++++++++++++++
12 security/apparmor/match.h | 87 +++
13 security/apparmor/module_interface.c | 875 +++++++++++++++++++++++++++++++++++
14 3 files changed, 1326 insertions(+)
15
16--- /dev/null
17+++ b/security/apparmor/match.c
18@@ -0,0 +1,364 @@
19+/*
20+ * Copyright (C) 2007 Novell/SUSE
21+ *
22+ * This program is free software; you can redistribute it and/or
23+ * modify it under the terms of the GNU General Public License as
24+ * published by the Free Software Foundation, version 2 of the
25+ * License.
26+ *
27+ * Regular expression transition table matching
28+ */
29+
30+#include <linux/kernel.h>
31+#include <linux/slab.h>
32+#include <linux/errno.h>
33+#include "apparmor.h"
34+#include "match.h"
35+#include "inline.h"
36+
37+static struct table_header *unpack_table(void *blob, size_t bsize)
38+{
39+ struct table_header *table = NULL;
40+ struct table_header th;
41+ size_t tsize;
42+
43+ if (bsize < sizeof(struct table_header))
44+ goto out;
45+
46+ th.td_id = be16_to_cpu(*(u16 *) (blob));
47+ th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
48+ th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
49+ blob += sizeof(struct table_header);
50+
51+ if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
52+ th.td_flags == YYTD_DATA8))
53+ goto out;
54+
55+ tsize = table_size(th.td_lolen, th.td_flags);
56+ if (bsize < tsize)
57+ goto out;
58+
59+ table = kmalloc(tsize, GFP_KERNEL);
60+ if (table) {
61+ *table = th;
62+ if (th.td_flags == YYTD_DATA8)
63+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
64+ u8, byte_to_byte);
65+ else if (th.td_flags == YYTD_DATA16)
66+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
67+ u16, be16_to_cpu);
68+ else
69+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
70+ u32, be32_to_cpu);
71+ }
72+
73+out:
74+ return table;
75+}
76+
77+int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
78+{
79+ int hsize, i;
80+ int error = -ENOMEM;
81+
82+ /* get dfa table set header */
83+ if (size < sizeof(struct table_set_header))
84+ goto fail;
85+
86+ if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
87+ goto fail;
88+
89+ hsize = ntohl(*(u32 *)(blob + 4));
90+ if (size < hsize)
91+ goto fail;
92+
93+ blob += hsize;
94+ size -= hsize;
95+
96+ error = -EPROTO;
97+ while (size > 0) {
98+ struct table_header *table;
99+ table = unpack_table(blob, size);
100+ if (!table)
101+ goto fail;
102+
103+ switch(table->td_id) {
104+ case YYTD_ID_ACCEPT:
105+ case YYTD_ID_ACCEPT2:
106+ case YYTD_ID_BASE:
107+ dfa->tables[table->td_id - 1] = table;
108+ if (table->td_flags != YYTD_DATA32)
109+ goto fail;
110+ break;
111+ case YYTD_ID_DEF:
112+ case YYTD_ID_NXT:
113+ case YYTD_ID_CHK:
114+ dfa->tables[table->td_id - 1] = table;
115+ if (table->td_flags != YYTD_DATA16)
116+ goto fail;
117+ break;
118+ case YYTD_ID_EC:
119+ dfa->tables[table->td_id - 1] = table;
120+ if (table->td_flags != YYTD_DATA8)
121+ goto fail;
122+ break;
123+ default:
124+ kfree(table);
125+ goto fail;
126+ }
127+
128+ blob += table_size(table->td_lolen, table->td_flags);
129+ size -= table_size(table->td_lolen, table->td_flags);
130+ }
131+
132+ return 0;
133+
134+fail:
135+ for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
136+ if (dfa->tables[i]) {
137+ kfree(dfa->tables[i]);
138+ dfa->tables[i] = NULL;
139+ }
140+ }
141+ return error;
142+}
143+
144+/**
145+ * verify_dfa - verify that all the transitions and states in the dfa tables
146+ * are in bounds.
147+ * @dfa: dfa to test
148+ *
149+ * assumes dfa has gone through the verification done by unpacking
150+ */
151+int verify_dfa(struct aa_dfa *dfa)
152+{
153+ size_t i, state_count, trans_count;
154+ int error = -EPROTO;
155+
156+ /* check that required tables exist */
157+ if (!(dfa->tables[YYTD_ID_ACCEPT - 1] &&
158+ dfa->tables[YYTD_ID_ACCEPT2 - 1] &&
159+ dfa->tables[YYTD_ID_DEF - 1] &&
160+ dfa->tables[YYTD_ID_BASE - 1] &&
161+ dfa->tables[YYTD_ID_NXT - 1] &&
162+ dfa->tables[YYTD_ID_CHK - 1]))
163+ goto out;
164+
165+ /* accept.size == default.size == base.size */
166+ state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
167+ if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
168+ state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen &&
169+ state_count == dfa->tables[YYTD_ID_ACCEPT2 - 1]->td_lolen))
170+ goto out;
171+
172+ /* next.size == chk.size */
173+ trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
174+ if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
175+ goto out;
176+
177+ /* if equivalence classes then its table size must be 256 */
178+ if (dfa->tables[YYTD_ID_EC - 1] &&
179+ dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
180+ goto out;
181+
182+ for (i = 0; i < state_count; i++) {
183+ if (DEFAULT_TABLE(dfa)[i] >= state_count)
184+ goto out;
185+ if (BASE_TABLE(dfa)[i] >= trans_count + 256)
186+ goto out;
187+ }
188+
189+ for (i = 0; i < trans_count ; i++) {
190+ if (NEXT_TABLE(dfa)[i] >= state_count)
191+ goto out;
192+ if (CHECK_TABLE(dfa)[i] >= state_count)
193+ goto out;
194+ }
195+
196+ /* verify accept permissions */
197+ for (i = 0; i < state_count; i++) {
198+ int mode = ACCEPT_TABLE(dfa)[i];
199+
200+ if (mode & ~AA_VALID_PERM_MASK)
201+ goto out;
202+ if (ACCEPT_TABLE2(dfa)[i] & ~AA_VALID_PERM2_MASK)
203+ goto out;
204+
205+ /* if any exec modifier is set MAY_EXEC must be set */
206+ if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC))
207+ goto out;
208+ if ((mode & AA_OTHER_EXEC_TYPE) && !(mode & AA_OTHER_EXEC))
209+ goto out;
210+ }
211+
212+ error = 0;
213+out:
214+ return error;
215+}
216+
217+struct aa_dfa *aa_match_alloc(void)
218+{
219+ return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
220+}
221+
222+void aa_match_free(struct aa_dfa *dfa)
223+{
224+ if (dfa) {
225+ int i;
226+
227+ for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
228+ kfree(dfa->tables[i]);
229+ }
230+ kfree(dfa);
231+}
232+
233+/**
234+ * aa_dfa_next_state_len - traverse @dfa to find state @str stops at
235+ * @dfa: the dfa to match @str against
236+ * @start: the state of the dfa to start matching in
237+ * @str: the string of bytes to match against the dfa
238+ * @len: length of the string of bytes to match
239+ *
240+ * aa_dfa_next_state will match @str against the dfa and return the state it
241+ * finished matching in. The final state can be used to look up the accepting
242+ * label, or as the start state of a continuing match.
243+ *
244+ * aa_dfa_next_state could be implement using this function by doing
245+ * return aa_dfa_next_state_len(dfa, start, str, strlen(str));
246+ * but that would require traversing the string twice and be slightly
247+ * slower.
248+ */
249+unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start,
250+ const char *str, int len)
251+{
252+ u16 *def = DEFAULT_TABLE(dfa);
253+ u32 *base = BASE_TABLE(dfa);
254+ u16 *next = NEXT_TABLE(dfa);
255+ u16 *check = CHECK_TABLE(dfa);
256+ unsigned int state = start, pos;
257+
258+ if (state == 0)
259+ return 0;
260+
261+ /* current state is <state>, matching character *str */
262+ if (dfa->tables[YYTD_ID_EC - 1]) {
263+ u8 *equiv = EQUIV_TABLE(dfa);
264+ for (; len; len--) {
265+ pos = base[state] + equiv[(u8)*str++];
266+ if (check[pos] == state)
267+ state = next[pos];
268+ else
269+ state = def[state];
270+ }
271+ } else {
272+ for (; len; len--) {
273+ pos = base[state] + (u8)*str++;
274+ if (check[pos] == state)
275+ state = next[pos];
276+ else
277+ state = def[state];
278+ }
279+ }
280+ return state;
281+}
282+
283+/**
284+ * aa_dfa_next_state - traverse @dfa to find state @str stops at
285+ * @dfa: the dfa to match @str against
286+ * @start: the state of the dfa to start matching in
287+ * @str: the null terminated string of bytes to match against the dfa
288+ *
289+ * aa_dfa_next_state will match @str against the dfa and return the state it
290+ * finished matching in. The final state can be used to look up the accepting
291+ * label, or as the start state of a continuing match.
292+ */
293+unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
294+ const char *str)
295+{
296+ u16 *def = DEFAULT_TABLE(dfa);
297+ u32 *base = BASE_TABLE(dfa);
298+ u16 *next = NEXT_TABLE(dfa);
299+ u16 *check = CHECK_TABLE(dfa);
300+ unsigned int state = start, pos;
301+
302+ if (state == 0)
303+ return 0;
304+
305+ /* current state is <state>, matching character *str */
306+ if (dfa->tables[YYTD_ID_EC - 1]) {
307+ u8 *equiv = EQUIV_TABLE(dfa);
308+ while (*str) {
309+ pos = base[state] + equiv[(u8)*str++];
310+ if (check[pos] == state)
311+ state = next[pos];
312+ else
313+ state = def[state];
314+ }
315+ } else {
316+ while (*str) {
317+ pos = base[state] + (u8)*str++;
318+ if (check[pos] == state)
319+ state = next[pos];
320+ else
321+ state = def[state];
322+ }
323+ }
324+ return state;
325+}
326+
327+/**
328+ * aa_dfa_null_transition - step to next state after null character
329+ * @dfa: the dfa to match against
330+ * @start: the state of the dfa to start matching in
331+ *
332+ * aa_dfa_null_transition transitions to the next state after a null
333+ * character which is not used in standard matching and is only
334+ * used to seperate pairs.
335+ */
336+unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
337+{
338+ return aa_dfa_next_state_len(dfa, start, "", 1);
339+}
340+
341+/**
342+ * aa_dfa_match - find accept perm for @str in @dfa
343+ * @dfa: the dfa to match @str against
344+ * @str: the string to match against the dfa
345+ * @audit_mask: the audit_mask for the final state
346+ *
347+ * aa_dfa_match will match @str and return the accept perms for the
348+ * final state.
349+ */
350+unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *audit_mask)
351+{
352+ int state = aa_dfa_next_state(dfa, DFA_START, str);
353+ if (audit_mask)
354+ *audit_mask = dfa_audit_mask(dfa, state);
355+ return ACCEPT_TABLE(dfa)[state];
356+}
357+
358+/**
359+ * aa_match_state - find accept perm and state for @str in @dfa
360+ * @dfa: the dfa to match @str against
361+ * @start: the state to start the match from
362+ * @str: the string to match against the dfa
363+ * @final: the state that the match finished in
364+ *
365+ * aa_match_state will match @str and return the accept perms, and @final
366+ * state, the match occured in.
367+ */
368+unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
369+ const char *str, unsigned int *final)
370+{
371+ unsigned int state;
372+ if (dfa) {
373+ state = aa_dfa_next_state(dfa, start, str);
374+ if (final)
375+ *final = state;
376+ return ACCEPT_TABLE(dfa)[state];
377+ }
378+ if (final)
379+ *final = 0;
380+ return 0;
381+}
382+
383--- /dev/null
384+++ b/security/apparmor/match.h
385@@ -0,0 +1,87 @@
386+/*
387+ * Copyright (C) 2007 Novell/SUSE
388+ *
389+ * This program is free software; you can redistribute it and/or
390+ * modify it under the terms of the GNU General Public License as
391+ * published by the Free Software Foundation, version 2 of the
392+ * License.
393+ *
394+ * AppArmor submodule (match) prototypes
395+ */
396+
397+#ifndef __MATCH_H
398+#define __MATCH_H
399+
400+#define DFA_START 1
401+
402+/**
403+ * The format used for transition tables is based on the GNU flex table
404+ * file format (--tables-file option; see Table File Format in the flex
405+ * info pages and the flex sources for documentation). The magic number
406+ * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
407+ * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
408+ * slightly differently (see the apparmor-parser package).
409+ */
410+
411+#define YYTH_MAGIC 0x1B5E783D
412+
413+struct table_set_header {
414+ u32 th_magic; /* YYTH_MAGIC */
415+ u32 th_hsize;
416+ u32 th_ssize;
417+ u16 th_flags;
418+ char th_version[];
419+};
420+
421+#define YYTD_ID_ACCEPT 1
422+#define YYTD_ID_BASE 2
423+#define YYTD_ID_CHK 3
424+#define YYTD_ID_DEF 4
425+#define YYTD_ID_EC 5
426+#define YYTD_ID_META 6
427+#define YYTD_ID_ACCEPT2 7
428+#define YYTD_ID_NXT 8
429+
430+
431+#define YYTD_DATA8 1
432+#define YYTD_DATA16 2
433+#define YYTD_DATA32 4
434+
435+struct table_header {
436+ u16 td_id;
437+ u16 td_flags;
438+ u32 td_hilen;
439+ u32 td_lolen;
440+ char td_data[];
441+};
442+
443+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
444+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
445+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
446+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
447+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
448+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
449+#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 -1]->td_data))
450+
451+struct aa_dfa {
452+ struct table_header *tables[YYTD_ID_NXT];
453+};
454+
455+#define byte_to_byte(X) (X)
456+
457+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
458+ do { \
459+ typeof(LEN) __i; \
460+ TYPE *__t = (TYPE *) TABLE; \
461+ TYPE *__b = (TYPE *) BLOB; \
462+ for (__i = 0; __i < LEN; __i++) { \
463+ __t[__i] = NTOHX(__b[__i]); \
464+ } \
465+ } while (0)
466+
467+static inline size_t table_size(size_t len, size_t el_size)
468+{
469+ return ALIGN(sizeof(struct table_header) + len * el_size, 8);
470+}
471+
472+#endif /* __MATCH_H */
473--- /dev/null
474+++ b/security/apparmor/module_interface.c
475@@ -0,0 +1,875 @@
476+/*
477+ * Copyright (C) 1998-2007 Novell/SUSE
478+ *
479+ * This program is free software; you can redistribute it and/or
480+ * modify it under the terms of the GNU General Public License as
481+ * published by the Free Software Foundation, version 2 of the
482+ * License.
483+ *
484+ * AppArmor userspace policy interface
485+ */
486+
487+#include <asm/unaligned.h>
488+
489+#include "apparmor.h"
490+#include "inline.h"
491+
492+/*
493+ * This mutex is used to synchronize profile adds, replacements, and
494+ * removals: we only allow one of these operations at a time.
495+ * We do not use the profile list lock here in order to avoid blocking
496+ * exec during those operations. (Exec involves a profile list lookup
497+ * for named-profile transitions.)
498+ */
499+DEFINE_MUTEX(aa_interface_lock);
500+
501+/*
502+ * The AppArmor interface treats data as a type byte followed by the
503+ * actual data. The interface has the notion of a a named entry
504+ * which has a name (AA_NAME typecode followed by name string) followed by
505+ * the entries typecode and data. Named types allow for optional
506+ * elements and extensions to be added and tested for without breaking
507+ * backwards compatability.
508+ */
509+
510+enum aa_code {
511+ AA_U8,
512+ AA_U16,
513+ AA_U32,
514+ AA_U64,
515+ AA_NAME, /* same as string except it is items name */
516+ AA_STRING,
517+ AA_BLOB,
518+ AA_STRUCT,
519+ AA_STRUCTEND,
520+ AA_LIST,
521+ AA_LISTEND,
522+ AA_ARRAY,
523+ AA_ARRAYEND,
524+};
525+
526+/*
527+ * aa_ext is the read of the buffer containing the serialized profile. The
528+ * data is copied into a kernel buffer in apparmorfs and then handed off to
529+ * the unpack routines.
530+ */
531+struct aa_ext {
532+ void *start;
533+ void *end;
534+ void *pos; /* pointer to current position in the buffer */
535+ u32 version;
536+ char *ns_name;
537+};
538+
539+static inline int aa_inbounds(struct aa_ext *e, size_t size)
540+{
541+ return (size <= e->end - e->pos);
542+}
543+
544+/**
545+ * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
546+ * @e: serialized data read head
547+ * @chunk: start address for chunk of data
548+ *
549+ * return the size of chunk found with the read head at the end of
550+ * the chunk.
551+ */
552+static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
553+{
554+ void *pos = e->pos;
555+ size_t size = 0;
556+
557+ if (!aa_inbounds(e, sizeof(u16)))
558+ goto fail;
559+ size = le16_to_cpu(get_unaligned((u16 *)e->pos));
560+ e->pos += sizeof(u16);
561+ if (!aa_inbounds(e, size))
562+ goto fail;
563+ *chunk = e->pos;
564+ e->pos += size;
565+ return size;
566+
567+fail:
568+ e->pos = pos;
569+ return 0;
570+}
571+
572+static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
573+{
574+ if (!aa_inbounds(e, 1))
575+ return 0;
576+ if (*(u8 *) e->pos != code)
577+ return 0;
578+ e->pos++;
579+ return 1;
580+}
581+
582+/**
583+ * aa_is_nameX - check is the next element is of type X with a name of @name
584+ * @e: serialized data extent information
585+ * @code: type code
586+ * @name: name to match to the serialized element.
587+ *
588+ * check that the next serialized data element is of type X and has a tag
589+ * name @name. If @name is specified then there must be a matching
590+ * name element in the stream. If @name is NULL any name element will be
591+ * skipped and only the typecode will be tested.
592+ * returns 1 on success (both type code and name tests match) and the read
593+ * head is advanced past the headers
594+ * returns %0 if either match failes, the read head does not move
595+ */
596+static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
597+{
598+ void *pos = e->pos;
599+ /*
600+ * Check for presence of a tagname, and if present name size
601+ * AA_NAME tag value is a u16.
602+ */
603+ if (aa_is_X(e, AA_NAME)) {
604+ char *tag;
605+ size_t size = aa_is_u16_chunk(e, &tag);
606+ /* if a name is specified it must match. otherwise skip tag */
607+ if (name && (!size || strcmp(name, tag)))
608+ goto fail;
609+ } else if (name) {
610+ /* if a name is specified and there is no name tag fail */
611+ goto fail;
612+ }
613+
614+ /* now check if type code matches */
615+ if (aa_is_X(e, code))
616+ return 1;
617+
618+fail:
619+ e->pos = pos;
620+ return 0;
621+}
622+
623+static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
624+{
625+ void *pos = e->pos;
626+ if (aa_is_nameX(e, AA_U16, name)) {
627+ if (!aa_inbounds(e, sizeof(u16)))
628+ goto fail;
629+ if (data)
630+ *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
631+ e->pos += sizeof(u16);
632+ return 1;
633+ }
634+fail:
635+ e->pos = pos;
636+ return 0;
637+}
638+
639+static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
640+{
641+ void *pos = e->pos;
642+ if (aa_is_nameX(e, AA_U32, name)) {
643+ if (!aa_inbounds(e, sizeof(u32)))
644+ goto fail;
645+ if (data)
646+ *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
647+ e->pos += sizeof(u32);
648+ return 1;
649+ }
650+fail:
651+ e->pos = pos;
652+ return 0;
653+}
654+
655+static size_t aa_is_array(struct aa_ext *e, const char *name)
656+{
657+ void *pos = e->pos;
658+ if (aa_is_nameX(e, AA_ARRAY, name)) {
659+ int size;
660+ if (!aa_inbounds(e, sizeof(u16)))
661+ goto fail;
662+ size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
663+ e->pos += sizeof(u16);
664+ return size;
665+ }
666+fail:
667+ e->pos = pos;
668+ return 0;
669+}
670+
671+static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
672+{
673+ void *pos = e->pos;
674+ if (aa_is_nameX(e, AA_BLOB, name)) {
675+ u32 size;
676+ if (!aa_inbounds(e, sizeof(u32)))
677+ goto fail;
678+ size = le32_to_cpu(get_unaligned((u32 *)e->pos));
679+ e->pos += sizeof(u32);
680+ if (aa_inbounds(e, (size_t) size)) {
681+ * blob = e->pos;
682+ e->pos += size;
683+ return size;
684+ }
685+ }
686+fail:
687+ e->pos = pos;
688+ return 0;
689+}
690+
691+static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
692+{
693+ char *src_str;
694+ size_t size = 0;
695+ void *pos = e->pos;
696+ *string = NULL;
697+ if (aa_is_nameX(e, AA_STRING, name) &&
698+ (size = aa_is_u16_chunk(e, &src_str))) {
699+ char *str;
700+ if (!(str = kmalloc(size, GFP_KERNEL)))
701+ goto fail;
702+ memcpy(str, src_str, size);
703+ *string = str;
704+ }
705+
706+ return size;
707+
708+fail:
709+ e->pos = pos;
710+ return 0;
711+}
712+
713+/**
714+ * aa_unpack_dfa - unpack a file rule dfa
715+ * @e: serialized data extent information
716+ *
717+ * returns dfa or ERR_PTR
718+ */
719+static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
720+{
721+ char *blob = NULL;
722+ size_t size, error = 0;
723+ struct aa_dfa *dfa = NULL;
724+
725+ size = aa_is_blob(e, &blob, "aadfa");
726+ if (size) {
727+ dfa = aa_match_alloc();
728+ if (dfa) {
729+ /*
730+ * The dfa is aligned with in the blob to 8 bytes
731+ * from the beginning of the stream.
732+ */
733+ size_t sz = blob - (char *) e->start;
734+ size_t pad = ALIGN(sz, 8) - sz;
735+ error = unpack_dfa(dfa, blob + pad, size - pad);
736+ if (!error)
737+ error = verify_dfa(dfa);
738+ } else {
739+ error = -ENOMEM;
740+ }
741+
742+ if (error) {
743+ aa_match_free(dfa);
744+ dfa = ERR_PTR(error);
745+ }
746+ }
747+
748+ return dfa;
749+}
750+
751+static int aa_unpack_exec_table(struct aa_ext *e, struct aa_profile *profile)
752+{
753+ void *pos = e->pos;
754+
755+ /* exec table is optional */
756+ if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
757+ int i, size;
758+
759+ size = aa_is_array(e, NULL);
760+ /* currently 4 exec bits and entries 0-3 are reserved iupcx */
761+ if (size > 16 - 4)
762+ goto fail;
763+ profile->exec_table = kzalloc(sizeof(char *) * size,
764+ GFP_KERNEL);
765+ if (!profile->exec_table)
766+ goto fail;
767+
768+ for (i = 0; i < size; i++) {
769+ char *tmp;
770+ if (!aa_is_dynstring(e, &tmp, NULL))
771+ goto fail;
772+ /* note: strings beginning with a : have an embedded
773+ \0 seperating the profile ns name from the profile
774+ name */
775+ profile->exec_table[i] = tmp;
776+ }
777+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
778+ goto fail;
779+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
780+ goto fail;
781+ profile->exec_table_size = size;
782+ }
783+ return 1;
784+
785+fail:
786+ e->pos = pos;
787+ return 0;
788+}
789+
790+/**
791+ * aa_unpack_profile - unpack a serialized profile
792+ * @e: serialized data extent information
793+ * @sa: audit struct for the operation
794+ */
795+static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
796+ struct aa_audit *sa)
797+{
798+ struct aa_profile *profile = NULL;
799+
800+ int error = -EPROTO;
801+
802+ profile = alloc_aa_profile();
803+ if (!profile)
804+ return ERR_PTR(-ENOMEM);
805+
806+ /* check that we have the right struct being passed */
807+ if (!aa_is_nameX(e, AA_STRUCT, "profile"))
808+ goto fail;
809+ if (!aa_is_dynstring(e, &profile->name, NULL))
810+ goto fail;
811+
812+ /* per profile debug flags (complain, audit) */
813+ if (!aa_is_nameX(e, AA_STRUCT, "flags"))
814+ goto fail;
815+ if (!aa_is_u32(e, &(profile->flags.hat), NULL))
816+ goto fail;
817+ if (!aa_is_u32(e, &(profile->flags.complain), NULL))
818+ goto fail;
819+ if (!aa_is_u32(e, &(profile->flags.audit), NULL))
820+ goto fail;
821+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
822+ goto fail;
823+
824+ if (!aa_is_u32(e, &(profile->capabilities), NULL))
825+ goto fail;
826+ if (!aa_is_u32(e, &(profile->audit_caps), NULL))
827+ goto fail;
828+ if (!aa_is_u32(e, &(profile->quiet_caps), NULL))
829+ goto fail;
830+ if (!aa_is_u32(e, &(profile->set_caps), NULL))
831+ goto fail;
832+
833+ /* get file rules */
834+ profile->file_rules = aa_unpack_dfa(e);
835+ if (IS_ERR(profile->file_rules)) {
836+ error = PTR_ERR(profile->file_rules);
837+ profile->file_rules = NULL;
838+ goto fail;
839+ }
840+
841+ if (!aa_unpack_exec_table(e, profile))
842+ goto fail;
843+
844+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
845+ goto fail;
846+
847+ return profile;
848+
849+fail:
850+ sa->name = profile && profile->name ? profile->name : "unknown";
851+ if (!sa->info)
852+ sa->info = "failed to unpack profile";
853+ aa_audit_status(NULL, sa);
854+
855+ if (profile)
856+ free_aa_profile(profile);
857+
858+ return ERR_PTR(error);
859+}
860+
861+/**
862+ * aa_verify_head - unpack serialized stream header
863+ * @e: serialized data read head
864+ * @operation: operation header is being verified for
865+ *
866+ * returns error or 0 if header is good
867+ */
868+static int aa_verify_header(struct aa_ext *e, struct aa_audit *sa)
869+{
870+ /* get the interface version */
871+ if (!aa_is_u32(e, &e->version, "version")) {
872+ sa->info = "invalid profile format";
873+ aa_audit_status(NULL, sa);
874+ return -EPROTONOSUPPORT;
875+ }
876+
877+ /* check that the interface version is currently supported */
878+ if (e->version != 5) {
879+ sa->info = "unsupported interface version";
880+ aa_audit_status(NULL, sa);
881+ return -EPROTONOSUPPORT;
882+ }
883+
884+ /* read the namespace if present */
885+ if (!aa_is_dynstring(e, &e->ns_name, "namespace")) {
886+ e->ns_name = NULL;
887+ }
888+
889+ return 0;
890+}
891+
892+/**
893+ * aa_add_profile - Unpack and add a new profile to the profile list
894+ * @data: serialized data stream
895+ * @size: size of the serialized data stream
896+ */
897+ssize_t aa_add_profile(void *data, size_t size)
898+{
899+ struct aa_profile *profile = NULL;
900+ struct aa_namespace *ns = NULL;
901+ struct aa_ext e = {
902+ .start = data,
903+ .end = data + size,
904+ .pos = data,
905+ .ns_name = NULL
906+ };
907+ ssize_t error;
908+ struct aa_audit sa;
909+ memset(&sa, 0, sizeof(sa));
910+ sa.operation = "profile_load";
911+ sa.gfp_mask = GFP_KERNEL;
912+
913+ error = aa_verify_header(&e, &sa);
914+ if (error)
915+ return error;
916+
917+ profile = aa_unpack_profile(&e, &sa);
918+ if (IS_ERR(profile))
919+ return PTR_ERR(profile);
920+
921+ mutex_lock(&aa_interface_lock);
922+ write_lock(&profile_ns_list_lock);
923+ if (e.ns_name)
924+ ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
925+ else
926+ ns = default_namespace;
927+ if (!ns) {
928+ struct aa_namespace *new_ns;
929+ write_unlock(&profile_ns_list_lock);
930+ new_ns = alloc_aa_namespace(e.ns_name);
931+ if (!new_ns) {
932+ mutex_unlock(&aa_interface_lock);
933+ return -ENOMEM;
934+ }
935+ write_lock(&profile_ns_list_lock);
936+ ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
937+ if (!ns) {
938+ list_add(&new_ns->list, &profile_ns_list);
939+ ns = new_ns;
940+ } else
941+ free_aa_namespace(new_ns);
942+ }
943+
944+ write_lock(&ns->lock);
945+ if (__aa_find_profile(profile->name, &ns->profiles)) {
946+ /* A profile with this name exists already. */
947+ write_unlock(&ns->lock);
948+ write_unlock(&profile_ns_list_lock);
949+ sa.name = profile->name;
950+ sa.name2 = ns->name;
951+ sa.info = "failed: profile already loaded";
952+ aa_audit_status(NULL, &sa);
953+ mutex_unlock(&aa_interface_lock);
954+ aa_put_profile(profile);
955+ return -EEXIST;
956+ }
957+ profile->ns = aa_get_namespace(ns);
958+ ns->profile_count++;
959+ list_add(&profile->list, &ns->profiles);
960+ write_unlock(&ns->lock);
961+ write_unlock(&profile_ns_list_lock);
962+
963+ sa.name = profile->name;
964+ sa.name2 = ns->name;
965+ aa_audit_status(NULL, &sa);
966+ mutex_unlock(&aa_interface_lock);
967+ return size;
968+}
969+
970+/**
971+ * task_replace - replace a task's profile
972+ * @task: task to replace profile on
973+ * @new_cxt: new aa_task_context to do replacement with
974+ * @new_profile: new profile
975+ */
976+static inline void task_replace(struct task_struct *task,
977+ struct aa_task_context *new_cxt,
978+ struct aa_profile *new_profile)
979+{
980+ struct aa_task_context *cxt = aa_task_context(task);
981+
982+ AA_DEBUG("%s: replacing profile for task %d "
983+ "profile=%s (%p)\n",
984+ __FUNCTION__,
985+ cxt->task->pid,
986+ cxt->profile->name, cxt->profile);
987+
988+ aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
989+ cxt->previous_profile);
990+}
991+
992+/**
993+ * aa_replace_profile - replace a profile on the profile list
994+ * @udata: serialized data stream
995+ * @size: size of the serialized data stream
996+ *
997+ * unpack and replace a profile on the profile list and uses of that profile
998+ * by any aa_task_context. If the profile does not exist on the profile list
999+ * it is added. Return %0 or error.
1000+ */
1001+ssize_t aa_replace_profile(void *udata, size_t size)
1002+{
1003+ struct aa_profile *old_profile, *new_profile;
1004+ struct aa_namespace *ns;
1005+ struct aa_task_context *new_cxt;
1006+ struct aa_ext e = {
1007+ .start = udata,
1008+ .end = udata + size,
1009+ .pos = udata,
1010+ .ns_name = NULL
1011+ };
1012+ ssize_t error;
1013+ struct aa_audit sa;
1014+ memset(&sa, 0, sizeof(sa));
1015+ sa.operation = "profile_replace";
1016+ sa.gfp_mask = GFP_KERNEL;
1017+
1018+ error = aa_verify_header(&e, &sa);
1019+ if (error)
1020+ return error;
1021+
1022+ new_profile = aa_unpack_profile(&e, &sa);
1023+ if (IS_ERR(new_profile))
1024+ return PTR_ERR(new_profile);
1025+
1026+ mutex_lock(&aa_interface_lock);
1027+ write_lock(&profile_ns_list_lock);
1028+ if (e.ns_name)
1029+ ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
1030+ else
1031+ ns = default_namespace;
1032+ if (!ns) {
1033+ struct aa_namespace *new_ns;
1034+ write_unlock(&profile_ns_list_lock);
1035+ new_ns = alloc_aa_namespace(e.ns_name);
1036+ if (!new_ns) {
1037+ mutex_unlock(&aa_interface_lock);
1038+ return -ENOMEM;
1039+ }
1040+ write_lock(&profile_ns_list_lock);
1041+ ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
1042+ if (!ns) {
1043+ list_add(&new_ns->list, &profile_ns_list);
1044+ ns = new_ns;
1045+ } else
1046+ free_aa_namespace(new_ns);
1047+ }
1048+
1049+ write_lock(&ns->lock);
1050+ old_profile = __aa_find_profile(new_profile->name, &ns->profiles);
1051+ if (old_profile) {
1052+ lock_profile(old_profile);
1053+ old_profile->isstale = 1;
1054+ list_del_init(&old_profile->list);
1055+ unlock_profile(old_profile);
1056+ ns->profile_count--;
1057+ }
1058+ new_profile->ns = aa_get_namespace(ns);
1059+ ns->profile_count++;
1060+ /* not don't need an extra ref count to keep new_profile as
1061+ * it is protect by the interface mutex */
1062+ list_add(&new_profile->list, &ns->profiles);
1063+ write_unlock(&ns->lock);
1064+ write_unlock(&profile_ns_list_lock);
1065+
1066+ if (!old_profile) {
1067+ sa.operation = "profile_load";
1068+ goto out;
1069+ }
1070+ /*
1071+ * Replacement needs to allocate a new aa_task_context for each
1072+ * task confined by old_profile. To do this the profile locks
1073+ * are only held when the actual switch is done per task. While
1074+ * looping to allocate a new aa_task_context the old_task list
1075+ * may get shorter if tasks exit/change their profile but will
1076+ * not get longer as new task will not use old_profile detecting
1077+ * that is stale.
1078+ */
1079+ do {
1080+ new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
1081+
1082+ lock_both_profiles(old_profile, new_profile);
1083+ if (!list_empty(&old_profile->task_contexts)) {
1084+ struct task_struct *task =
1085+ list_entry(old_profile->task_contexts.next,
1086+ struct aa_task_context, list)->task;
1087+ task_lock(task);
1088+ task_replace(task, new_cxt, new_profile);
1089+ task_unlock(task);
1090+ new_cxt = NULL;
1091+ }
1092+ unlock_both_profiles(old_profile, new_profile);
1093+ } while (!new_cxt);
1094+ aa_free_task_context(new_cxt);
1095+ aa_put_profile(old_profile);
1096+
1097+out:
1098+ sa.name = new_profile->name;
1099+ sa.name2 = ns->name;
1100+ aa_audit_status(NULL, &sa);
1101+ mutex_unlock(&aa_interface_lock);
1102+ return size;
1103+}
1104+
1105+/**
1106+ * aa_remove_profile - remove a profile from the system
1107+ * @name: name of the profile to remove
1108+ * @size: size of the name
1109+ *
1110+ * remove a profile from the profile list and all aa_task_context references
1111+ * to said profile.
1112+ */
1113+ssize_t aa_remove_profile(char *name, size_t size)
1114+{
1115+ struct aa_namespace *ns;
1116+ struct aa_profile *profile;
1117+ struct aa_audit sa;
1118+ memset(&sa, 0, sizeof(sa));
1119+ sa.operation = "profile_remove";
1120+ sa.gfp_mask = GFP_KERNEL;
1121+
1122+ mutex_lock(&aa_interface_lock);
1123+ write_lock(&profile_ns_list_lock);
1124+
1125+ if (name[0] == ':') {
1126+ char *split = strchr(name + 1, ':');
1127+ if (!split)
1128+ goto noent;
1129+ *split = 0;
1130+ ns = __aa_find_namespace(name + 1, &profile_ns_list);
1131+ name = split + 1;
1132+ } else {
1133+ ns = default_namespace;
1134+ }
1135+
1136+ if (!ns)
1137+ goto noent;
1138+ sa.name2 = ns->name;
1139+ write_lock(&ns->lock);
1140+ profile = __aa_find_profile(name, &ns->profiles);
1141+ if (!profile) {
1142+ write_unlock(&ns->lock);
1143+ goto noent;
1144+ }
1145+ sa.name = profile->name;
1146+
1147+ /* Remove the profile from each task context it is on. */
1148+ lock_profile(profile);
1149+ profile->isstale = 1;
1150+ aa_unconfine_tasks(profile);
1151+ list_del_init(&profile->list);
1152+ ns->profile_count--;
1153+ unlock_profile(profile);
1154+ /* Release the profile itself. */
1155+ write_unlock(&ns->lock);
1156+ /* check to see if the namespace has become stale */
1157+ if (ns != default_namespace && ns->profile_count == 0) {
1158+ list_del_init(&ns->list);
1159+ aa_put_namespace(ns);
1160+ }
1161+ write_unlock(&profile_ns_list_lock);
1162+
1163+ aa_audit_status(NULL, &sa);
1164+ mutex_unlock(&aa_interface_lock);
1165+ aa_put_profile(profile);
1166+
1167+ return size;
1168+
1169+noent:
1170+ write_unlock(&profile_ns_list_lock);
1171+ sa.info = "failed: profile does not exist";
1172+ aa_audit_status(NULL, &sa);
1173+ mutex_unlock(&aa_interface_lock);
1174+ return -ENOENT;
1175+}
1176+
1177+/**
1178+ * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
1179+ * @kr: kref callback for freeing of a namespace
1180+ */
1181+void free_aa_namespace_kref(struct kref *kref)
1182+{
1183+ struct aa_namespace *ns=container_of(kref, struct aa_namespace, count);
1184+
1185+ free_aa_namespace(ns);
1186+}
1187+
1188+/**
1189+ * alloc_aa_namespace - allocate, initialize and return a new namespace
1190+ * @name: a preallocated name
1191+ * Returns NULL on failure.
1192+ */
1193+struct aa_namespace *alloc_aa_namespace(char *name)
1194+{
1195+ struct aa_namespace *ns;
1196+
1197+ ns = kzalloc(sizeof(*ns), GFP_KERNEL);
1198+ AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
1199+ if (ns) {
1200+ ns->name = name;
1201+ INIT_LIST_HEAD(&ns->list);
1202+ INIT_LIST_HEAD(&ns->profiles);
1203+ kref_init(&ns->count);
1204+ rwlock_init(&ns->lock);
1205+
1206+ ns->null_complain_profile = alloc_aa_profile();
1207+ if (!ns->null_complain_profile) {
1208+ if (!name)
1209+ kfree(ns->name);
1210+ kfree(ns);
1211+ return NULL;
1212+ }
1213+ ns->null_complain_profile->name =
1214+ kstrdup("null-complain-profile", GFP_KERNEL);
1215+ if (!ns->null_complain_profile->name) {
1216+ free_aa_profile(ns->null_complain_profile);
1217+ if (!name)
1218+ kfree(ns->name);
1219+ kfree(ns);
1220+ return NULL;
1221+ }
1222+ ns->null_complain_profile->flags.complain = 1;
1223+ /* null_complain_profile doesn't contribute to ns ref count */
1224+ ns->null_complain_profile->ns = ns;
1225+ }
1226+ return ns;
1227+}
1228+
1229+/**
1230+ * free_aa_namespace - free a profile namespace
1231+ * @namespace: the namespace to free
1232+ *
1233+ * Free a namespace. All references to the namespace must have been put.
1234+ * If the namespace was referenced by a profile confining a task,
1235+ * free_aa_namespace will be called indirectly (through free_aa_profile)
1236+ * from an rcu callback routine, so we must not sleep here.
1237+ */
1238+void free_aa_namespace(struct aa_namespace *ns)
1239+{
1240+ AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
1241+
1242+ if (!ns)
1243+ return;
1244+
1245+ /* namespace still contains profiles -- invalid */
1246+ if (!list_empty(&ns->profiles)) {
1247+ AA_ERROR("%s: internal error, "
1248+ "namespace '%s' still contains profiles\n",
1249+ __FUNCTION__,
1250+ ns->name);
1251+ BUG();
1252+ }
1253+ if (!list_empty(&ns->list)) {
1254+ AA_ERROR("%s: internal error, "
1255+ "namespace '%s' still on list\n",
1256+ __FUNCTION__,
1257+ ns->name);
1258+ BUG();
1259+ }
1260+ /* null_complain_profile doesn't contribute to ns ref counting */
1261+ ns->null_complain_profile->ns = NULL;
1262+ aa_put_profile(ns->null_complain_profile);
1263+ kfree(ns->name);
1264+ kfree(ns);
1265+}
1266+
1267+/**
1268+ * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
1269+ * @kr: kref callback for freeing of a profile
1270+ */
1271+void free_aa_profile_kref(struct kref *kref)
1272+{
1273+ struct aa_profile *p=container_of(kref, struct aa_profile, count);
1274+
1275+ free_aa_profile(p);
1276+}
1277+
1278+/**
1279+ * alloc_aa_profile - allocate, initialize and return a new profile
1280+ * Returns NULL on failure.
1281+ */
1282+struct aa_profile *alloc_aa_profile(void)
1283+{
1284+ struct aa_profile *profile;
1285+
1286+ profile = kzalloc(sizeof(*profile), GFP_KERNEL);
1287+ AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
1288+ if (profile) {
1289+ INIT_LIST_HEAD(&profile->list);
1290+ kref_init(&profile->count);
1291+ INIT_LIST_HEAD(&profile->task_contexts);
1292+ spin_lock_init(&profile->lock);
1293+ }
1294+ return profile;
1295+}
1296+
1297+/**
1298+ * free_aa_profile - free a profile
1299+ * @profile: the profile to free
1300+ *
1301+ * Free a profile, its hats and null_profile. All references to the profile,
1302+ * its hats and null_profile must have been put.
1303+ *
1304+ * If the profile was referenced from a task context, free_aa_profile() will
1305+ * be called from an rcu callback routine, so we must not sleep here.
1306+ */
1307+void free_aa_profile(struct aa_profile *profile)
1308+{
1309+ AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
1310+
1311+ if (!profile)
1312+ return;
1313+
1314+ /* profile is still on profile namespace list -- invalid */
1315+ if (!list_empty(&profile->list)) {
1316+ AA_ERROR("%s: internal error, "
1317+ "profile '%s' still on global list\n",
1318+ __FUNCTION__,
1319+ profile->name);
1320+ BUG();
1321+ }
1322+ aa_put_namespace(profile->ns);
1323+
1324+ aa_match_free(profile->file_rules);
1325+
1326+ if (profile->name) {
1327+ AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
1328+ kfree(profile->name);
1329+ }
1330+
1331+ kfree(profile);
1332+}
1333+
1334+/**
1335+ * aa_unconfine_tasks - remove tasks on a profile's task context list
1336+ * @profile: profile to remove tasks from
1337+ *
1338+ * Assumes that @profile lock is held.
1339+ */
1340+void aa_unconfine_tasks(struct aa_profile *profile)
1341+{
1342+ while (!list_empty(&profile->task_contexts)) {
1343+ struct task_struct *task =
1344+ list_entry(profile->task_contexts.next,
1345+ struct aa_task_context, list)->task;
1346+ task_lock(task);
1347+ aa_change_task_context(task, NULL, NULL, 0, NULL);
1348+ task_unlock(task);
1349+ }
1350+}