aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-08-08 16:01:01 -0400
committerJohn Johansen <john.johansen@canonical.com>2018-02-09 14:30:02 -0500
commitd901d6a298dc6e9105b9dc091d65b043e9f8c9a6 (patch)
treea57465d5598a1dbdba3f165e85f74b0a4d407326
parent031dcc8f4e84fea37dc6f78fdc7288aa7f8386c3 (diff)
apparmor: dfa split verification of table headers
separate the different types of verification so they are logically separate and can be reused separate of each other. Signed-off-by: John Johansen <john.johansen@canonical.com>
-rw-r--r--security/apparmor/match.c116
1 files changed, 68 insertions, 48 deletions
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 70cdcb3c3b25..7ae6ed9d69dd 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -136,8 +136,8 @@ fail:
136} 136}
137 137
138/** 138/**
139 * verify_dfa - verify that transitions and states in the tables are in bounds. 139 * verify_table_headers - verify that the tables headers are as expected
140 * @dfa: dfa to test (NOT NULL) 140 * @tables - array of dfa tables to check (NOT NULL)
141 * @flags: flags controlling what type of accept table are acceptable 141 * @flags: flags controlling what type of accept table are acceptable
142 * 142 *
143 * Assumes dfa has gone through the first pass verification done by unpacking 143 * Assumes dfa has gone through the first pass verification done by unpacking
@@ -145,83 +145,98 @@ fail:
145 * 145 *
146 * Returns: %0 else error code on failure to verify 146 * Returns: %0 else error code on failure to verify
147 */ 147 */
148static int verify_dfa(struct aa_dfa *dfa, int flags) 148static int verify_table_headers(struct table_header **tables, int flags)
149{ 149{
150 size_t i, state_count, trans_count; 150 size_t state_count, trans_count;
151 int error = -EPROTO; 151 int error = -EPROTO;
152 152
153 /* check that required tables exist */ 153 /* check that required tables exist */
154 if (!(dfa->tables[YYTD_ID_DEF] && 154 if (!(tables[YYTD_ID_DEF] && tables[YYTD_ID_BASE] &&
155 dfa->tables[YYTD_ID_BASE] && 155 tables[YYTD_ID_NXT] && tables[YYTD_ID_CHK]))
156 dfa->tables[YYTD_ID_NXT] && dfa->tables[YYTD_ID_CHK]))
157 goto out; 156 goto out;
158 157
159 /* accept.size == default.size == base.size */ 158 /* accept.size == default.size == base.size */
160 state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; 159 state_count = tables[YYTD_ID_BASE]->td_lolen;
161 if (ACCEPT1_FLAGS(flags)) { 160 if (ACCEPT1_FLAGS(flags)) {
162 if (!dfa->tables[YYTD_ID_ACCEPT]) 161 if (!tables[YYTD_ID_ACCEPT])
163 goto out; 162 goto out;
164 if (state_count != dfa->tables[YYTD_ID_ACCEPT]->td_lolen) 163 if (state_count != tables[YYTD_ID_ACCEPT]->td_lolen)
165 goto out; 164 goto out;
166 } 165 }
167 if (ACCEPT2_FLAGS(flags)) { 166 if (ACCEPT2_FLAGS(flags)) {
168 if (!dfa->tables[YYTD_ID_ACCEPT2]) 167 if (!tables[YYTD_ID_ACCEPT2])
169 goto out; 168 goto out;
170 if (state_count != dfa->tables[YYTD_ID_ACCEPT2]->td_lolen) 169 if (state_count != tables[YYTD_ID_ACCEPT2]->td_lolen)
171 goto out; 170 goto out;
172 } 171 }
173 if (state_count != dfa->tables[YYTD_ID_DEF]->td_lolen) 172 if (state_count != tables[YYTD_ID_DEF]->td_lolen)
174 goto out; 173 goto out;
175 174
176 /* next.size == chk.size */ 175 /* next.size == chk.size */
177 trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen; 176 trans_count = tables[YYTD_ID_NXT]->td_lolen;
178 if (trans_count != dfa->tables[YYTD_ID_CHK]->td_lolen) 177 if (trans_count != tables[YYTD_ID_CHK]->td_lolen)
179 goto out; 178 goto out;
180 179
181 /* if equivalence classes then its table size must be 256 */ 180 /* if equivalence classes then its table size must be 256 */
182 if (dfa->tables[YYTD_ID_EC] && 181 if (tables[YYTD_ID_EC] && tables[YYTD_ID_EC]->td_lolen != 256)
183 dfa->tables[YYTD_ID_EC]->td_lolen != 256)
184 goto out; 182 goto out;
185 183
186 if (flags & DFA_FLAG_VERIFY_STATES) { 184 error = 0;
187 for (i = 0; i < state_count; i++) { 185out:
188 if (!(BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE) && 186 return error;
189 (DEFAULT_TABLE(dfa)[i] >= state_count)) 187}
190 goto out;
191 if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) {
192 printk(KERN_ERR "AppArmor DFA next/check upper "
193 "bounds error\n");
194 goto out;
195 }
196 }
197 188
198 for (i = 0; i < trans_count; i++) { 189/**
199 if (NEXT_TABLE(dfa)[i] >= state_count) 190 * verify_dfa - verify that transitions and states in the tables are in bounds.
200 goto out; 191 * @dfa: dfa to test (NOT NULL)
201 if (CHECK_TABLE(dfa)[i] >= state_count) 192 *
202 goto out; 193 * Assumes dfa has gone through the first pass verification done by unpacking
194 * NOTE: this does not valid accept table values
195 *
196 * Returns: %0 else error code on failure to verify
197 */
198static int verify_dfa(struct aa_dfa *dfa)
199{
200 size_t i, state_count, trans_count;
201 int error = EPROTO;
202
203 state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
204 trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen;
205 for (i = 0; i < state_count; i++) {
206 if (!(BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE) &&
207 (DEFAULT_TABLE(dfa)[i] >= state_count))
208 goto out;
209 if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) {
210 pr_err("AppArmor DFA next/check upper bounds error\n");
211 goto out;
203 } 212 }
204 } 213 }
205 214
215 for (i = 0; i < trans_count; i++) {
216 if (NEXT_TABLE(dfa)[i] >= state_count)
217 goto out;
218 if (CHECK_TABLE(dfa)[i] >= state_count)
219 goto out;
220 }
221
206 /* Now that all the other tables are verified, verify diffencoding */ 222 /* Now that all the other tables are verified, verify diffencoding */
207 if (flags & DFA_FLAG_VERIFY_STATES) { 223 for (i = 0; i < state_count; i++) {
208 size_t j, k; 224 size_t j, k;
209 225
210 for (i = 0; i < state_count; i++) { 226 for (j = i;
211 for (j = i; 227 (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) &&
212 (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) && 228 !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE);
213 !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE); 229 j = k) {
214 j = k) { 230 k = DEFAULT_TABLE(dfa)[j];
215 k = DEFAULT_TABLE(dfa)[j]; 231 if (j == k)
216 if (j == k) 232 goto out;
217 goto out; 233 if (k < j)
218 if (k < j) 234 break; /* already verified */
219 break; /* already verified */ 235 BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE;
220 BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE;
221 }
222 } 236 }
223 } 237 }
224 error = 0; 238 error = 0;
239
225out: 240out:
226 return error; 241 return error;
227} 242}
@@ -338,11 +353,16 @@ struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
338 size -= table_size(table->td_lolen, table->td_flags); 353 size -= table_size(table->td_lolen, table->td_flags);
339 table = NULL; 354 table = NULL;
340 } 355 }
341 356 error = verify_table_headers(dfa->tables, flags);
342 error = verify_dfa(dfa, flags);
343 if (error) 357 if (error)
344 goto fail; 358 goto fail;
345 359
360 if (flags & DFA_FLAG_VERIFY_STATES) {
361 error = verify_dfa(dfa);
362 if (error)
363 goto fail;
364 }
365
346 return dfa; 366 return dfa;
347 367
348fail: 368fail: