aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2010-07-29 17:48:02 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:38:36 -0400
commit736ec752d95e91e77cc0e8c97c057ab076ac2f51 (patch)
tree128d330ecff67c5d83862062825b7975c92fee96 /security
parent0ed3b28ab8bf460a3a026f3f1782bf4c53840184 (diff)
AppArmor: policy routines for loading and unpacking policy
AppArmor policy is loaded in a platform independent flattened binary stream. Verify and unpack the data converting it to the internal format needed for enforcement. Signed-off-by: John Johansen <john.johansen@canonical.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/include/policy_unpack.h20
-rw-r--r--security/apparmor/policy_unpack.c703
2 files changed, 723 insertions, 0 deletions
diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
new file mode 100644
index 000000000000..a2dcccac45aa
--- /dev/null
+++ b/security/apparmor/include/policy_unpack.h
@@ -0,0 +1,20 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy loading interface function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __POLICY_INTERFACE_H
16#define __POLICY_INTERFACE_H
17
18struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns);
19
20#endif /* __POLICY_INTERFACE_H */
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
new file mode 100644
index 000000000000..eb3700e9fd37
--- /dev/null
+++ b/security/apparmor/policy_unpack.c
@@ -0,0 +1,703 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor functions for unpacking policy loaded from
5 * userspace.
6 *
7 * Copyright (C) 1998-2008 Novell/SUSE
8 * Copyright 2009-2010 Canonical Ltd.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2 of the
13 * License.
14 *
15 * AppArmor uses a serialized binary format for loading policy.
16 * To find policy format documentation look in Documentation/apparmor.txt
17 * All policy is validated before it is used.
18 */
19
20#include <asm/unaligned.h>
21#include <linux/ctype.h>
22#include <linux/errno.h>
23
24#include "include/apparmor.h"
25#include "include/audit.h"
26#include "include/context.h"
27#include "include/match.h"
28#include "include/policy.h"
29#include "include/policy_unpack.h"
30#include "include/sid.h"
31
32/*
33 * The AppArmor interface treats data as a type byte followed by the
34 * actual data. The interface has the notion of a a named entry
35 * which has a name (AA_NAME typecode followed by name string) followed by
36 * the entries typecode and data. Named types allow for optional
37 * elements and extensions to be added and tested for without breaking
38 * backwards compatibility.
39 */
40
41enum aa_code {
42 AA_U8,
43 AA_U16,
44 AA_U32,
45 AA_U64,
46 AA_NAME, /* same as string except it is items name */
47 AA_STRING,
48 AA_BLOB,
49 AA_STRUCT,
50 AA_STRUCTEND,
51 AA_LIST,
52 AA_LISTEND,
53 AA_ARRAY,
54 AA_ARRAYEND,
55};
56
57/*
58 * aa_ext is the read of the buffer containing the serialized profile. The
59 * data is copied into a kernel buffer in apparmorfs and then handed off to
60 * the unpack routines.
61 */
62struct aa_ext {
63 void *start;
64 void *end;
65 void *pos; /* pointer to current position in the buffer */
66 u32 version;
67};
68
69/* audit callback for unpack fields */
70static void audit_cb(struct audit_buffer *ab, void *va)
71{
72 struct common_audit_data *sa = va;
73 if (sa->aad.iface.target) {
74 struct aa_profile *name = sa->aad.iface.target;
75 audit_log_format(ab, " name=");
76 audit_log_untrustedstring(ab, name->base.hname);
77 }
78 if (sa->aad.iface.pos)
79 audit_log_format(ab, " offset=%ld", sa->aad.iface.pos);
80}
81
82/**
83 * audit_iface - do audit message for policy unpacking/load/replace/remove
84 * @new: profile if it has been allocated (MAYBE NULL)
85 * @name: name of the profile being manipulated (MAYBE NULL)
86 * @info: any extra info about the failure (MAYBE NULL)
87 * @e: buffer position info (NOT NULL)
88 * @error: error code
89 *
90 * Returns: %0 or error
91 */
92static int audit_iface(struct aa_profile *new, const char *name,
93 const char *info, struct aa_ext *e, int error)
94{
95 struct aa_profile *profile = __aa_current_profile();
96 struct common_audit_data sa;
97 COMMON_AUDIT_DATA_INIT(&sa, NONE);
98 sa.aad.iface.pos = e->pos - e->start;
99 sa.aad.iface.target = new;
100 sa.aad.name = name;
101 sa.aad.info = info;
102 sa.aad.error = error;
103
104 return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
105 audit_cb);
106}
107
108/* test if read will be in packed data bounds */
109static bool inbounds(struct aa_ext *e, size_t size)
110{
111 return (size <= e->end - e->pos);
112}
113
114/**
115 * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
116 * @e: serialized data read head (NOT NULL)
117 * @chunk: start address for chunk of data (NOT NULL)
118 *
119 * Returns: the size of chunk found with the read head at the end of the chunk.
120 */
121static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
122{
123 size_t size = 0;
124
125 if (!inbounds(e, sizeof(u16)))
126 return 0;
127 size = le16_to_cpu(get_unaligned((u16 *) e->pos));
128 e->pos += sizeof(u16);
129 if (!inbounds(e, size))
130 return 0;
131 *chunk = e->pos;
132 e->pos += size;
133 return size;
134}
135
136/* unpack control byte */
137static bool unpack_X(struct aa_ext *e, enum aa_code code)
138{
139 if (!inbounds(e, 1))
140 return 0;
141 if (*(u8 *) e->pos != code)
142 return 0;
143 e->pos++;
144 return 1;
145}
146
147/**
148 * unpack_nameX - check is the next element is of type X with a name of @name
149 * @e: serialized data extent information (NOT NULL)
150 * @code: type code
151 * @name: name to match to the serialized element. (MAYBE NULL)
152 *
153 * check that the next serialized data element is of type X and has a tag
154 * name @name. If @name is specified then there must be a matching
155 * name element in the stream. If @name is NULL any name element will be
156 * skipped and only the typecode will be tested.
157 *
158 * Returns 1 on success (both type code and name tests match) and the read
159 * head is advanced past the headers
160 *
161 * Returns: 0 if either match fails, the read head does not move
162 */
163static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
164{
165 /*
166 * May need to reset pos if name or type doesn't match
167 */
168 void *pos = e->pos;
169 /*