Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * AppArmor security module
4 : : *
5 : : * This file contains AppArmor functions for unpacking policy loaded from
6 : : * userspace.
7 : : *
8 : : * Copyright (C) 1998-2008 Novell/SUSE
9 : : * Copyright 2009-2010 Canonical Ltd.
10 : : *
11 : : * AppArmor uses a serialized binary format for loading policy. To find
12 : : * policy format documentation see Documentation/admin-guide/LSM/apparmor.rst
13 : : * All policy is validated before it is used.
14 : : */
15 : :
16 : : #include <asm/unaligned.h>
17 : : #include <linux/ctype.h>
18 : : #include <linux/errno.h>
19 : :
20 : : #include "include/apparmor.h"
21 : : #include "include/audit.h"
22 : : #include "include/cred.h"
23 : : #include "include/crypto.h"
24 : : #include "include/match.h"
25 : : #include "include/path.h"
26 : : #include "include/policy.h"
27 : : #include "include/policy_unpack.h"
28 : :
29 : : #define K_ABI_MASK 0x3ff
30 : : #define FORCE_COMPLAIN_FLAG 0x800
31 : : #define VERSION_LT(X, Y) (((X) & K_ABI_MASK) < ((Y) & K_ABI_MASK))
32 : : #define VERSION_GT(X, Y) (((X) & K_ABI_MASK) > ((Y) & K_ABI_MASK))
33 : :
34 : : #define v5 5 /* base version */
35 : : #define v6 6 /* per entry policydb mediation check */
36 : : #define v7 7
37 : : #define v8 8 /* full network masking */
38 : :
39 : : /*
40 : : * The AppArmor interface treats data as a type byte followed by the
41 : : * actual data. The interface has the notion of a a named entry
42 : : * which has a name (AA_NAME typecode followed by name string) followed by
43 : : * the entries typecode and data. Named types allow for optional
44 : : * elements and extensions to be added and tested for without breaking
45 : : * backwards compatibility.
46 : : */
47 : :
48 : : enum aa_code {
49 : : AA_U8,
50 : : AA_U16,
51 : : AA_U32,
52 : : AA_U64,
53 : : AA_NAME, /* same as string except it is items name */
54 : : AA_STRING,
55 : : AA_BLOB,
56 : : AA_STRUCT,
57 : : AA_STRUCTEND,
58 : : AA_LIST,
59 : : AA_LISTEND,
60 : : AA_ARRAY,
61 : : AA_ARRAYEND,
62 : : };
63 : :
64 : : /*
65 : : * aa_ext is the read of the buffer containing the serialized profile. The
66 : : * data is copied into a kernel buffer in apparmorfs and then handed off to
67 : : * the unpack routines.
68 : : */
69 : : struct aa_ext {
70 : : void *start;
71 : : void *end;
72 : : void *pos; /* pointer to current position in the buffer */
73 : : u32 version;
74 : : };
75 : :
76 : : /* audit callback for unpack fields */
77 : 0 : static void audit_cb(struct audit_buffer *ab, void *va)
78 : : {
79 : : struct common_audit_data *sa = va;
80 : :
81 [ # # ]: 0 : if (aad(sa)->iface.ns) {
82 : 0 : audit_log_format(ab, " ns=");
83 : 0 : audit_log_untrustedstring(ab, aad(sa)->iface.ns);
84 : : }
85 [ # # ]: 0 : if (aad(sa)->name) {
86 : 0 : audit_log_format(ab, " name=");
87 : 0 : audit_log_untrustedstring(ab, aad(sa)->name);
88 : : }
89 [ # # ]: 0 : if (aad(sa)->iface.pos)
90 : 0 : audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos);
91 : 0 : }
92 : :
93 : : /**
94 : : * audit_iface - do audit message for policy unpacking/load/replace/remove
95 : : * @new: profile if it has been allocated (MAYBE NULL)
96 : : * @ns_name: name of the ns the profile is to be loaded to (MAY BE NULL)
97 : : * @name: name of the profile being manipulated (MAYBE NULL)
98 : : * @info: any extra info about the failure (MAYBE NULL)
99 : : * @e: buffer position info
100 : : * @error: error code
101 : : *
102 : : * Returns: %0 or error
103 : : */
104 : 0 : static int audit_iface(struct aa_profile *new, const char *ns_name,
105 : : const char *name, const char *info, struct aa_ext *e,
106 : : int error)
107 : : {
108 : 0 : struct aa_profile *profile = labels_profile(aa_current_raw_label());
109 : 0 : DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL);
110 [ # # ]: 0 : if (e)
111 : 0 : aad(&sa)->iface.pos = e->pos - e->start;
112 : 0 : aad(&sa)->iface.ns = ns_name;
113 [ # # ]: 0 : if (new)
114 : 0 : aad(&sa)->name = new->base.hname;
115 : : else
116 : 0 : aad(&sa)->name = name;
117 : 0 : aad(&sa)->info = info;
118 : 0 : aad(&sa)->error = error;
119 : :
120 : 0 : return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb);
121 : : }
122 : :
123 : 0 : void __aa_loaddata_update(struct aa_loaddata *data, long revision)
124 : : {
125 : : AA_BUG(!data);
126 : : AA_BUG(!data->ns);
127 : : AA_BUG(!data->dents[AAFS_LOADDATA_REVISION]);
128 : : AA_BUG(!mutex_is_locked(&data->ns->lock));
129 : : AA_BUG(data->revision > revision);
130 : :
131 : 0 : data->revision = revision;
132 : 0 : d_inode(data->dents[AAFS_LOADDATA_DIR])->i_mtime =
133 : : current_time(d_inode(data->dents[AAFS_LOADDATA_DIR]));
134 : 0 : d_inode(data->dents[AAFS_LOADDATA_REVISION])->i_mtime =
135 : : current_time(d_inode(data->dents[AAFS_LOADDATA_REVISION]));
136 : 0 : }
137 : :
138 : 0 : bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r)
139 : : {
140 [ # # ]: 0 : if (l->size != r->size)
141 : : return false;
142 [ # # # # ]: 0 : if (aa_g_hash_policy && memcmp(l->hash, r->hash, aa_hash_size()) != 0)
143 : : return false;
144 : 0 : return memcmp(l->data, r->data, r->size) == 0;
145 : : }
146 : :
147 : : /*
148 : : * need to take the ns mutex lock which is NOT safe most places that
149 : : * put_loaddata is called, so we have to delay freeing it
150 : : */
151 : 0 : static void do_loaddata_free(struct work_struct *work)
152 : : {
153 : 0 : struct aa_loaddata *d = container_of(work, struct aa_loaddata, work);
154 : 0 : struct aa_ns *ns = aa_get_ns(d->ns);
155 : :
156 [ # # ]: 0 : if (ns) {
157 : 0 : mutex_lock_nested(&ns->lock, ns->level);
158 : 0 : __aa_fs_remove_rawdata(d);
159 : 0 : mutex_unlock(&ns->lock);
160 : 0 : aa_put_ns(ns);
161 : : }
162 : :
163 : 0 : kzfree(d->hash);
164 : 0 : kzfree(d->name);
165 : 0 : kvfree(d->data);
166 : 0 : kzfree(d);
167 : 0 : }
168 : :
169 : 0 : void aa_loaddata_kref(struct kref *kref)
170 : : {
171 : : struct aa_loaddata *d = container_of(kref, struct aa_loaddata, count);
172 : :
173 [ # # ]: 0 : if (d) {
174 : 0 : INIT_WORK(&d->work, do_loaddata_free);
175 : 0 : schedule_work(&d->work);
176 : : }
177 : 0 : }
178 : :
179 : 0 : struct aa_loaddata *aa_loaddata_alloc(size_t size)
180 : : {
181 : : struct aa_loaddata *d;
182 : :
183 : 0 : d = kzalloc(sizeof(*d), GFP_KERNEL);
184 [ # # ]: 0 : if (d == NULL)
185 : : return ERR_PTR(-ENOMEM);
186 : 0 : d->data = kvzalloc(size, GFP_KERNEL);
187 [ # # ]: 0 : if (!d->data) {
188 : 0 : kfree(d);
189 : 0 : return ERR_PTR(-ENOMEM);
190 : : }
191 : : kref_init(&d->count);
192 : 0 : INIT_LIST_HEAD(&d->list);
193 : :
194 : 0 : return d;
195 : : }
196 : :
197 : : /* test if read will be in packed data bounds */
198 : : static bool inbounds(struct aa_ext *e, size_t size)
199 : : {
200 : 0 : return (size <= e->end - e->pos);
201 : : }
202 : :
203 : 0 : static void *kvmemdup(const void *src, size_t len)
204 : : {
205 : : void *p = kvmalloc(len, GFP_KERNEL);
206 : :
207 [ # # ]: 0 : if (p)
208 : 0 : memcpy(p, src, len);
209 : 0 : return p;
210 : : }
211 : :
212 : : /**
213 : : * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
214 : : * @e: serialized data read head (NOT NULL)
215 : : * @chunk: start address for chunk of data (NOT NULL)
216 : : *
217 : : * Returns: the size of chunk found with the read head at the end of the chunk.
218 : : */
219 : : static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
220 : : {
221 : : size_t size = 0;
222 : 0 : void *pos = e->pos;
223 : :
224 [ # # # # ]: 0 : if (!inbounds(e, sizeof(u16)))
225 : : goto fail;
226 : 0 : size = le16_to_cpu(get_unaligned((__le16 *) e->pos));
227 : 0 : e->pos += sizeof(__le16);
228 [ # # # # ]: 0 : if (!inbounds(e, size))
229 : : goto fail;
230 : : *chunk = e->pos;
231 : 0 : e->pos += size;
232 : : return size;
233 : :
234 : : fail:
235 : 0 : e->pos = pos;
236 : : return 0;
237 : : }
238 : :
239 : : /* unpack control byte */
240 : : static bool unpack_X(struct aa_ext *e, enum aa_code code)
241 : : {
242 [ # # # # ]: 0 : if (!inbounds(e, 1))
243 : : return 0;
244 [ # # # # ]: 0 : if (*(u8 *) e->pos != code)
245 : : return 0;
246 : 0 : e->pos++;
247 : : return 1;
248 : : }
249 : :
250 : : /**
251 : : * unpack_nameX - check is the next element is of type X with a name of @name
252 : : * @e: serialized data extent information (NOT NULL)
253 : : * @code: type code
254 : : * @name: name to match to the serialized element. (MAYBE NULL)
255 : : *
256 : : * check that the next serialized data element is of type X and has a tag
257 : : * name @name. If @name is specified then there must be a matching
258 : : * name element in the stream. If @name is NULL any name element will be
259 : : * skipped and only the typecode will be tested.
260 : : *
261 : : * Returns 1 on success (both type code and name tests match) and the read
262 : : * head is advanced past the headers
263 : : *
264 : : * Returns: 0 if either match fails, the read head does not move
265 : : */
266 : 0 : static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
267 : : {
268 : : /*
269 : : * May need to reset pos if name or type doesn't match
270 : : */
271 : 0 : void *pos = e->pos;
272 : : /*
273 : : * Check for presence of a tagname, and if present name size
274 : : * AA_NAME tag value is a u16.
275 : : */
276 [ # # ]: 0 : if (unpack_X(e, AA_NAME)) {
277 : : char *tag = NULL;
278 : : size_t size = unpack_u16_chunk(e, &tag);
279 : : /* if a name is specified it must match. otherwise skip tag */
280 [ # # # # : 0 : if (name && (!size || tag[size-1] != '\0' || strcmp(name, tag)))
# # # # ]
281 : : goto fail;
282 [ # # ]: 0 : } else if (name) {
283 : : /* if a name is specified and there is no name tag fail */
284 : : goto fail;
285 : : }
286 : :
287 : : /* now check if type code matches */
288 [ # # ]: 0 : if (unpack_X(e, code))
289 : : return 1;
290 : :
291 : : fail:
292 : 0 : e->pos = pos;
293 : 0 : return 0;
294 : : }
295 : :
296 : 0 : static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name)
297 : : {
298 : 0 : void *pos = e->pos;
299 : :
300 [ # # ]: 0 : if (unpack_nameX(e, AA_U8, name)) {
301 [ # # ]: 0 : if (!inbounds(e, sizeof(u8)))
302 : : goto fail;
303 [ # # ]: 0 : if (data)
304 : 0 : *data = get_unaligned((u8 *)e->pos);
305 : 0 : e->pos += sizeof(u8);
306 : 0 : return 1;
307 : : }
308 : :
309 : : fail:
310 : 0 : e->pos = pos;
311 : 0 : return 0;
312 : : }
313 : :
314 : 0 : static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
315 : : {
316 : 0 : void *pos = e->pos;
317 : :
318 [ # # ]: 0 : if (unpack_nameX(e, AA_U32, name)) {
319 [ # # ]: 0 : if (!inbounds(e, sizeof(u32)))
320 : : goto fail;
321 [ # # ]: 0 : if (data)
322 : 0 : *data = le32_to_cpu(get_unaligned((__le32 *) e->pos));
323 : 0 : e->pos += sizeof(u32);
324 : 0 : return 1;
325 : : }
326 : :
327 : : fail:
328 : 0 : e->pos = pos;
329 : 0 : return 0;
330 : : }
331 : :
332 : 0 : static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name)
333 : : {
334 : 0 : void *pos = e->pos;
335 : :
336 [ # # ]: 0 : if (unpack_nameX(e, AA_U64, name)) {
337 [ # # ]: 0 : if (!inbounds(e, sizeof(u64)))
338 : : goto fail;
339 [ # # ]: 0 : if (data)
340 : 0 : *data = le64_to_cpu(get_unaligned((__le64 *) e->pos));
341 : 0 : e->pos += sizeof(u64);
342 : 0 : return 1;
343 : : }
344 : :
345 : : fail:
346 : 0 : e->pos = pos;
347 : 0 : return 0;
348 : : }
349 : :
350 : 0 : static size_t unpack_array(struct aa_ext *e, const char *name)
351 : : {
352 : 0 : void *pos = e->pos;
353 : :
354 [ # # ]: 0 : if (unpack_nameX(e, AA_ARRAY, name)) {
355 : : int size;
356 [ # # ]: 0 : if (!inbounds(e, sizeof(u16)))
357 : : goto fail;
358 : : size = (int)le16_to_cpu(get_unaligned((__le16 *) e->pos));
359 : 0 : e->pos += sizeof(u16);
360 : 0 : return size;
361 : : }
362 : :
363 : : fail:
364 : 0 : e->pos = pos;
365 : 0 : return 0;
366 : : }
367 : :
368 : 0 : static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
369 : : {
370 : 0 : void *pos = e->pos;
371 : :
372 [ # # ]: 0 : if (unpack_nameX(e, AA_BLOB, name)) {
373 : : u32 size;
374 [ # # ]: 0 : if (!inbounds(e, sizeof(u32)))
375 : : goto fail;
376 : : size = le32_to_cpu(get_unaligned((__le32 *) e->pos));
377 : 0 : e->pos += sizeof(u32);
378 [ # # ]: 0 : if (inbounds(e, (size_t) size)) {
379 : 0 : *blob = e->pos;
380 : 0 : e->pos += size;
381 : 0 : return size;
382 : : }
383 : : }
384 : :
385 : : fail:
386 : 0 : e->pos = pos;
387 : 0 : return 0;
388 : : }
389 : :
390 : 0 : static int unpack_str(struct aa_ext *e, const char **string, const char *name)
391 : : {
392 : : char *src_str;
393 : : size_t size = 0;
394 : 0 : void *pos = e->pos;
395 : 0 : *string = NULL;
396 [ # # ]: 0 : if (unpack_nameX(e, AA_STRING, name)) {
397 : : size = unpack_u16_chunk(e, &src_str);
398 [ # # ]: 0 : if (size) {
399 : : /* strings are null terminated, length is size - 1 */
400 [ # # ]: 0 : if (src_str[size - 1] != 0)
401 : : goto fail;
402 : 0 : *string = src_str;
403 : :
404 : 0 : return size;
405 : : }
406 : : }
407 : :
408 : : fail:
409 : 0 : e->pos = pos;
410 : 0 : return 0;
411 : : }
412 : :
413 : 0 : static int unpack_strdup(struct aa_ext *e, char **string, const char *name)
414 : : {
415 : : const char *tmp;
416 : 0 : void *pos = e->pos;
417 : 0 : int res = unpack_str(e, &tmp, name);
418 : 0 : *string = NULL;
419 : :
420 [ # # ]: 0 : if (!res)
421 : : return 0;
422 : :
423 : 0 : *string = kmemdup(tmp, res, GFP_KERNEL);
424 [ # # ]: 0 : if (!*string) {
425 : 0 : e->pos = pos;
426 : 0 : return 0;
427 : : }
428 : :
429 : : return res;
430 : : }
431 : :
432 : :
433 : : /**
434 : : * unpack_dfa - unpack a file rule dfa
435 : : * @e: serialized data extent information (NOT NULL)
436 : : *
437 : : * returns dfa or ERR_PTR or NULL if no dfa
438 : : */
439 : 0 : static struct aa_dfa *unpack_dfa(struct aa_ext *e)
440 : : {
441 : 0 : char *blob = NULL;
442 : : size_t size;
443 : : struct aa_dfa *dfa = NULL;
444 : :
445 : 0 : size = unpack_blob(e, &blob, "aadfa");
446 [ # # ]: 0 : if (size) {
447 : : /*
448 : : * The dfa is aligned with in the blob to 8 bytes
449 : : * from the beginning of the stream.
450 : : * alignment adjust needed by dfa unpack
451 : : */
452 : 0 : size_t sz = blob - (char *) e->start -
453 : 0 : ((e->pos - e->start) & 7);
454 : 0 : size_t pad = ALIGN(sz, 8) - sz;
455 : : int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
456 : : TO_ACCEPT2_FLAG(YYTD_DATA32) | DFA_FLAG_VERIFY_STATES;
457 : 0 : dfa = aa_dfa_unpack(blob + pad, size - pad, flags);
458 : :
459 [ # # ]: 0 : if (IS_ERR(dfa))
460 : : return dfa;
461 : :
462 : : }
463 : :
464 : 0 : return dfa;
465 : : }
466 : :
467 : : /**
468 : : * unpack_trans_table - unpack a profile transition table
469 : : * @e: serialized data extent information (NOT NULL)
470 : : * @profile: profile to add the accept table to (NOT NULL)
471 : : *
472 : : * Returns: 1 if table successfully unpacked
473 : : */
474 : 0 : static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
475 : : {
476 : 0 : void *saved_pos = e->pos;
477 : :
478 : : /* exec table is optional */
479 [ # # ]: 0 : if (unpack_nameX(e, AA_STRUCT, "xtable")) {
480 : : int i, size;
481 : :
482 : 0 : size = unpack_array(e, NULL);
483 : : /* currently 4 exec bits and entries 0-3 are reserved iupcx */
484 [ # # ]: 0 : if (size > 16 - 4)
485 : : goto fail;
486 : 0 : profile->file.trans.table = kcalloc(size, sizeof(char *),
487 : : GFP_KERNEL);
488 [ # # ]: 0 : if (!profile->file.trans.table)
489 : : goto fail;
490 : :
491 : 0 : profile->file.trans.size = size;
492 [ # # ]: 0 : for (i = 0; i < size; i++) {
493 : : char *str;
494 : 0 : int c, j, pos, size2 = unpack_strdup(e, &str, NULL);
495 : : /* unpack_strdup verifies that the last character is
496 : : * null termination byte.
497 : : */
498 [ # # ]: 0 : if (!size2)
499 : : goto fail;
500 : 0 : profile->file.trans.table[i] = str;
501 : : /* verify that name doesn't start with space */
502 [ # # ]: 0 : if (isspace(*str))
503 : : goto fail;
504 : :
505 : : /* count internal # of internal \0 */
506 [ # # ]: 0 : for (c = j = 0; j < size2 - 1; j++) {
507 [ # # ]: 0 : if (!str[j]) {
508 : : pos = j;
509 : 0 : c++;
510 : : }
511 : : }
512 [ # # ]: 0 : if (*str == ':') {
513 : : /* first character after : must be valid */
514 [ # # ]: 0 : if (!str[1])
515 : : goto fail;
516 : : /* beginning with : requires an embedded \0,
517 : : * verify that exactly 1 internal \0 exists
518 : : * trailing \0 already verified by unpack_strdup
519 : : *
520 : : * convert \0 back to : for label_parse
521 : : */
522 [ # # ]: 0 : if (c == 1)
523 : 0 : str[pos] = ':';
524 [ # # ]: 0 : else if (c > 1)
525 : : goto fail;
526 [ # # ]: 0 : } else if (c)
527 : : /* fail - all other cases with embedded \0 */
528 : : goto fail;
529 : : }
530 [ # # ]: 0 : if (!unpack_nameX(e, AA_ARRAYEND, NULL))
531 : : goto fail;
532 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL))
533 : : goto fail;
534 : : }
535 : : return 1;
536 : :
537 : : fail:
538 : 0 : aa_free_domain_entries(&profile->file.trans);
539 : 0 : e->pos = saved_pos;
540 : 0 : return 0;
541 : : }
542 : :
543 : 0 : static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile)
544 : : {
545 : 0 : void *pos = e->pos;
546 : :
547 [ # # ]: 0 : if (unpack_nameX(e, AA_STRUCT, "xattrs")) {
548 : : int i, size;
549 : :
550 : 0 : size = unpack_array(e, NULL);
551 : 0 : profile->xattr_count = size;
552 : 0 : profile->xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL);
553 [ # # ]: 0 : if (!profile->xattrs)
554 : : goto fail;
555 [ # # ]: 0 : for (i = 0; i < size; i++) {
556 [ # # ]: 0 : if (!unpack_strdup(e, &profile->xattrs[i], NULL))
557 : : goto fail;
558 : : }
559 [ # # ]: 0 : if (!unpack_nameX(e, AA_ARRAYEND, NULL))
560 : : goto fail;
561 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL))
562 : : goto fail;
563 : : }
564 : :
565 : : return 1;
566 : :
567 : : fail:
568 : 0 : e->pos = pos;
569 : 0 : return 0;
570 : : }
571 : :
572 : 0 : static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile)
573 : : {
574 : 0 : void *pos = e->pos;
575 : : int i, size;
576 : :
577 [ # # ]: 0 : if (unpack_nameX(e, AA_STRUCT, "secmark")) {
578 : 0 : size = unpack_array(e, NULL);
579 : :
580 : 0 : profile->secmark = kcalloc(size, sizeof(struct aa_secmark),
581 : : GFP_KERNEL);
582 [ # # ]: 0 : if (!profile->secmark)
583 : : goto fail;
584 : :
585 : 0 : profile->secmark_count = size;
586 : :
587 [ # # ]: 0 : for (i = 0; i < size; i++) {
588 [ # # ]: 0 : if (!unpack_u8(e, &profile->secmark[i].audit, NULL))
589 : : goto fail;
590 [ # # ]: 0 : if (!unpack_u8(e, &profile->secmark[i].deny, NULL))
591 : : goto fail;
592 [ # # ]: 0 : if (!unpack_strdup(e, &profile->secmark[i].label, NULL))
593 : : goto fail;
594 : : }
595 [ # # ]: 0 : if (!unpack_nameX(e, AA_ARRAYEND, NULL))
596 : : goto fail;
597 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL))
598 : : goto fail;
599 : : }
600 : :
601 : : return 1;
602 : :
603 : : fail:
604 [ # # ]: 0 : if (profile->secmark) {
605 [ # # ]: 0 : for (i = 0; i < size; i++)
606 : 0 : kfree(profile->secmark[i].label);
607 : 0 : kfree(profile->secmark);
608 : 0 : profile->secmark_count = 0;
609 : 0 : profile->secmark = NULL;
610 : : }
611 : :
612 : 0 : e->pos = pos;
613 : 0 : return 0;
614 : : }
615 : :
616 : 0 : static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
617 : : {
618 : 0 : void *pos = e->pos;
619 : :
620 : : /* rlimits are optional */
621 [ # # ]: 0 : if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
622 : : int i, size;
623 : 0 : u32 tmp = 0;
624 [ # # ]: 0 : if (!unpack_u32(e, &tmp, NULL))
625 : : goto fail;
626 : 0 : profile->rlimits.mask = tmp;
627 : :
628 : 0 : size = unpack_array(e, NULL);
629 [ # # ]: 0 : if (size > RLIM_NLIMITS)
630 : : goto fail;
631 [ # # ]: 0 : for (i = 0; i < size; i++) {
632 : 0 : u64 tmp2 = 0;
633 : 0 : int a = aa_map_resource(i);
634 [ # # ]: 0 : if (!unpack_u64(e, &tmp2, NULL))
635 : : goto fail;
636 : 0 : profile->rlimits.limits[a].rlim_max = tmp2;
637 : : }
638 [ # # ]: 0 : if (!unpack_nameX(e, AA_ARRAYEND, NULL))
639 : : goto fail;
640 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL))
641 : : goto fail;
642 : : }
643 : : return 1;
644 : :
645 : : fail:
646 : 0 : e->pos = pos;
647 : 0 : return 0;
648 : : }
649 : :
650 : 0 : static u32 strhash(const void *data, u32 len, u32 seed)
651 : : {
652 : : const char * const *key = data;
653 : :
654 : 0 : return jhash(*key, strlen(*key), seed);
655 : : }
656 : :
657 : 0 : static int datacmp(struct rhashtable_compare_arg *arg, const void *obj)
658 : : {
659 : : const struct aa_data *data = obj;
660 : 0 : const char * const *key = arg->key;
661 : :
662 : 0 : return strcmp(data->key, *key);
663 : : }
664 : :
665 : : /**
666 : : * unpack_profile - unpack a serialized profile
667 : : * @e: serialized data extent information (NOT NULL)
668 : : *
669 : : * NOTE: unpack profile sets audit struct if there is a failure
670 : : */
671 : 0 : static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
672 : : {
673 : : struct aa_profile *profile = NULL;
674 : 0 : const char *tmpname, *tmpns = NULL, *name = NULL;
675 : : const char *info = "failed to unpack profile";
676 : : size_t ns_len;
677 : 0 : struct rhashtable_params params = { 0 };
678 : 0 : char *key = NULL;
679 : : struct aa_data *data;
680 : : int i, error = -EPROTO;
681 : : kernel_cap_t tmpcap;
682 : : u32 tmp;
683 : :
684 : 0 : *ns_name = NULL;
685 : :
686 : : /* check that we have the right struct being passed */
687 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCT, "profile"))
688 : : goto fail;
689 [ # # ]: 0 : if (!unpack_str(e, &name, NULL))
690 : : goto fail;
691 [ # # ]: 0 : if (*name == '\0')
692 : : goto fail;
693 : :
694 : 0 : tmpname = aa_splitn_fqname(name, strlen(name), &tmpns, &ns_len);
695 [ # # ]: 0 : if (tmpns) {
696 : 0 : *ns_name = kstrndup(tmpns, ns_len, GFP_KERNEL);
697 [ # # ]: 0 : if (!*ns_name) {
698 : : info = "out of memory";
699 : : goto fail;
700 : : }
701 : 0 : name = tmpname;
702 : : }
703 : :
704 : 0 : profile = aa_alloc_profile(name, NULL, GFP_KERNEL);
705 [ # # ]: 0 : if (!profile)
706 : : return ERR_PTR(-ENOMEM);
707 : :
708 : : /* profile renaming is optional */
709 : 0 : (void) unpack_str(e, &profile->rename, "rename");
710 : :
711 : : /* attachment string is optional */
712 : 0 : (void) unpack_str(e, &profile->attach, "attach");
713 : :
714 : : /* xmatch is optional and may be NULL */
715 : 0 : profile->xmatch = unpack_dfa(e);
716 [ # # ]: 0 : if (IS_ERR(profile->xmatch)) {
717 : : error = PTR_ERR(profile->xmatch);
718 : 0 : profile->xmatch = NULL;
719 : : info = "bad xmatch";
720 : 0 : goto fail;
721 : : }
722 : : /* xmatch_len is not optional if xmatch is set */
723 [ # # ]: 0 : if (profile->xmatch) {
724 [ # # ]: 0 : if (!unpack_u32(e, &tmp, NULL)) {
725 : : info = "missing xmatch len";
726 : : goto fail;
727 : : }
728 : 0 : profile->xmatch_len = tmp;
729 : : }
730 : :
731 : : /* disconnected attachment string is optional */
732 : 0 : (void) unpack_str(e, &profile->disconnected, "disconnected");
733 : :
734 : : /* per profile debug flags (complain, audit) */
735 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCT, "flags")) {
736 : : info = "profile missing flags";
737 : : goto fail;
738 : : }
739 : : info = "failed to unpack profile flags";
740 [ # # ]: 0 : if (!unpack_u32(e, &tmp, NULL))
741 : : goto fail;
742 [ # # ]: 0 : if (tmp & PACKED_FLAG_HAT)
743 : 0 : profile->label.flags |= FLAG_HAT;
744 [ # # ]: 0 : if (!unpack_u32(e, &tmp, NULL))
745 : : goto fail;
746 [ # # # # ]: 0 : if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG))
747 : 0 : profile->mode = APPARMOR_COMPLAIN;
748 [ # # ]: 0 : else if (tmp == PACKED_MODE_KILL)
749 : 0 : profile->mode = APPARMOR_KILL;
750 [ # # ]: 0 : else if (tmp == PACKED_MODE_UNCONFINED)
751 : 0 : profile->mode = APPARMOR_UNCONFINED;
752 [ # # ]: 0 : if (!unpack_u32(e, &tmp, NULL))
753 : : goto fail;
754 [ # # ]: 0 : if (tmp)
755 : 0 : profile->audit = AUDIT_ALL;
756 : :
757 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL))
758 : : goto fail;
759 : :
760 : : /* path_flags is optional */
761 [ # # ]: 0 : if (unpack_u32(e, &profile->path_flags, "path_flags"))
762 : 0 : profile->path_flags |= profile->label.flags &
763 : : PATH_MEDIATE_DELETED;
764 : : else
765 : : /* set a default value if path_flags field is not present */
766 : 0 : profile->path_flags = PATH_MEDIATE_DELETED;
767 : :
768 : : info = "failed to unpack profile capabilities";
769 [ # # ]: 0 : if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL))
770 : : goto fail;
771 [ # # ]: 0 : if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
772 : : goto fail;
773 [ # # ]: 0 : if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL))
774 : : goto fail;
775 [ # # ]: 0 : if (!unpack_u32(e, &tmpcap.cap[0], NULL))
776 : : goto fail;
777 : :
778 : : info = "failed to unpack upper profile capabilities";
779 [ # # ]: 0 : if (unpack_nameX(e, AA_STRUCT, "caps64")) {
780 : : /* optional upper half of 64 bit caps */
781 [ # # ]: 0 : if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL))
782 : : goto fail;
783 [ # # ]: 0 : if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL))
784 : : goto fail;
785 [ # # ]: 0 : if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL))
786 : : goto fail;
787 [ # # ]: 0 : if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
788 : : goto fail;
789 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL))
790 : : goto fail;
791 : : }
792 : :
793 : : info = "failed to unpack extended profile capabilities";
794 [ # # ]: 0 : if (unpack_nameX(e, AA_STRUCT, "capsx")) {
795 : : /* optional extended caps mediation mask */
796 [ # # ]: 0 : if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
797 : : goto fail;
798 [ # # ]: 0 : if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
799 : : goto fail;
800 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL))
801 : : goto fail;
802 : : }
803 : :
804 [ # # ]: 0 : if (!unpack_xattrs(e, profile)) {
805 : : info = "failed to unpack profile xattrs";
806 : : goto fail;
807 : : }
808 : :
809 [ # # ]: 0 : if (!unpack_rlimits(e, profile)) {
810 : : info = "failed to unpack profile rlimits";
811 : : goto fail;
812 : : }
813 : :
814 [ # # ]: 0 : if (!unpack_secmark(e, profile)) {
815 : : info = "failed to unpack profile secmark rules";
816 : : goto fail;
817 : : }
818 : :
819 [ # # ]: 0 : if (unpack_nameX(e, AA_STRUCT, "policydb")) {
820 : : /* generic policy dfa - optional and may be NULL */
821 : : info = "failed to unpack policydb";
822 : 0 : profile->policy.dfa = unpack_dfa(e);
823 [ # # ]: 0 : if (IS_ERR(profile->policy.dfa)) {
824 : : error = PTR_ERR(profile->policy.dfa);
825 : 0 : profile->policy.dfa = NULL;
826 : 0 : goto fail;
827 [ # # ]: 0 : } else if (!profile->policy.dfa) {
828 : : error = -EPROTO;
829 : : goto fail;
830 : : }
831 [ # # ]: 0 : if (!unpack_u32(e, &profile->policy.start[0], "start"))
832 : : /* default start state */
833 : 0 : profile->policy.start[0] = DFA_START;
834 : : /* setup class index */
835 [ # # ]: 0 : for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) {
836 : 0 : profile->policy.start[i] =
837 : 0 : aa_dfa_next(profile->policy.dfa,
838 : : profile->policy.start[0],
839 : : i);
840 : : }
841 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL))
842 : : goto fail;
843 : : } else
844 : 0 : profile->policy.dfa = aa_get_dfa(nulldfa);
845 : :
846 : : /* get file rules */
847 : 0 : profile->file.dfa = unpack_dfa(e);
848 [ # # ]: 0 : if (IS_ERR(profile->file.dfa)) {
849 : : error = PTR_ERR(profile->file.dfa);
850 : 0 : profile->file.dfa = NULL;
851 : : info = "failed to unpack profile file rules";
852 : 0 : goto fail;
853 [ # # ]: 0 : } else if (profile->file.dfa) {
854 [ # # ]: 0 : if (!unpack_u32(e, &profile->file.start, "dfa_start"))
855 : : /* default start state */
856 : 0 : profile->file.start = DFA_START;
857 [ # # # # ]: 0 : } else if (profile->policy.dfa &&
858 : 0 : profile->policy.start[AA_CLASS_FILE]) {
859 : 0 : profile->file.dfa = aa_get_dfa(profile->policy.dfa);
860 : 0 : profile->file.start = profile->policy.start[AA_CLASS_FILE];
861 : : } else
862 : 0 : profile->file.dfa = aa_get_dfa(nulldfa);
863 : :
864 [ # # ]: 0 : if (!unpack_trans_table(e, profile)) {
865 : : info = "failed to unpack profile transition table";
866 : : goto fail;
867 : : }
868 : :
869 [ # # ]: 0 : if (unpack_nameX(e, AA_STRUCT, "data")) {
870 : : info = "out of memory";
871 : 0 : profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL);
872 [ # # ]: 0 : if (!profile->data)
873 : : goto fail;
874 : :
875 : 0 : params.nelem_hint = 3;
876 : 0 : params.key_len = sizeof(void *);
877 : 0 : params.key_offset = offsetof(struct aa_data, key);
878 : 0 : params.head_offset = offsetof(struct aa_data, head);
879 : 0 : params.hashfn = strhash;
880 : 0 : params.obj_cmpfn = datacmp;
881 : :
882 [ # # ]: 0 : if (rhashtable_init(profile->data, ¶ms)) {
883 : : info = "failed to init key, value hash table";
884 : : goto fail;
885 : : }
886 : :
887 [ # # ]: 0 : while (unpack_strdup(e, &key, NULL)) {
888 : 0 : data = kzalloc(sizeof(*data), GFP_KERNEL);
889 [ # # ]: 0 : if (!data) {
890 : 0 : kzfree(key);
891 : 0 : goto fail;
892 : : }
893 : :
894 : 0 : data->key = key;
895 : 0 : data->size = unpack_blob(e, &data->data, NULL);
896 : 0 : data->data = kvmemdup(data->data, data->size);
897 [ # # # # ]: 0 : if (data->size && !data->data) {
898 : 0 : kzfree(data->key);
899 : 0 : kzfree(data);
900 : 0 : goto fail;
901 : : }
902 : :
903 : 0 : rhashtable_insert_fast(profile->data, &data->head,
904 : 0 : profile->data->p);
905 : : }
906 : :
907 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL)) {
908 : : info = "failed to unpack end of key, value data table";
909 : : goto fail;
910 : : }
911 : : }
912 : :
913 [ # # ]: 0 : if (!unpack_nameX(e, AA_STRUCTEND, NULL)) {
914 : : info = "failed to unpack end of profile";
915 : : goto fail;
916 : : }
917 : :
918 : : return profile;
919 : :
920 : : fail:
921 [ # # ]: 0 : if (profile)
922 : 0 : name = NULL;
923 [ # # ]: 0 : else if (!name)
924 : 0 : name = "unknown";
925 : 0 : audit_iface(profile, NULL, name, info, e, error);
926 : 0 : aa_free_profile(profile);
927 : :
928 : 0 : return ERR_PTR(error);
929 : : }
930 : :
931 : : /**
932 : : * verify_head - unpack serialized stream header
933 : : * @e: serialized data read head (NOT NULL)
934 : : * @required: whether the header is required or optional
935 : : * @ns: Returns - namespace if one is specified else NULL (NOT NULL)
936 : : *
937 : : * Returns: error or 0 if header is good
938 : : */
939 : 0 : static int verify_header(struct aa_ext *e, int required, const char **ns)
940 : : {
941 : : int error = -EPROTONOSUPPORT;
942 : 0 : const char *name = NULL;
943 : 0 : *ns = NULL;
944 : :
945 : : /* get the interface version */
946 [ # # ]: 0 : if (!unpack_u32(e, &e->version, "version")) {
947 [ # # ]: 0 : if (required) {
948 : 0 : audit_iface(NULL, NULL, NULL, "invalid profile format",
949 : : e, error);
950 : 0 : return error;
951 : : }
952 : : }
953 : :
954 : : /* Check that the interface version is currently supported.
955 : : * if not specified use previous version
956 : : * Mask off everything that is not kernel abi version
957 : : */
958 [ # # ]: 0 : if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v7)) {
959 : 0 : audit_iface(NULL, NULL, NULL, "unsupported interface version",
960 : : e, error);
961 : 0 : return error;
962 : : }
963 : :
964 : : /* read the namespace if present */
965 [ # # ]: 0 : if (unpack_str(e, &name, "namespace")) {
966 [ # # ]: 0 : if (*name == '\0') {
967 : 0 : audit_iface(NULL, NULL, NULL, "invalid namespace name",
968 : : e, error);
969 : 0 : return error;
970 : : }
971 [ # # # # ]: 0 : if (*ns && strcmp(*ns, name))
972 : 0 : audit_iface(NULL, NULL, NULL, "invalid ns change", e,
973 : : error);
974 [ # # ]: 0 : else if (!*ns)
975 : 0 : *ns = name;
976 : : }
977 : :
978 : : return 0;
979 : : }
980 : :
981 : : static bool verify_xindex(int xindex, int table_size)
982 : : {
983 : : int index, xtype;
984 : 0 : xtype = xindex & AA_X_TYPE_MASK;
985 : 0 : index = xindex & AA_X_INDEX_MASK;
986 [ # # # # ]: 0 : if (xtype == AA_X_TABLE && index >= table_size)
987 : : return 0;
988 : : return 1;
989 : : }
990 : :
991 : : /* verify dfa xindexes are in range of transition tables */
992 : 0 : static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
993 : : {
994 : : int i;
995 [ # # ]: 0 : for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
996 [ # # ]: 0 : if (!verify_xindex(dfa_user_xindex(dfa, i), table_size))
997 : : return 0;
998 [ # # ]: 0 : if (!verify_xindex(dfa_other_xindex(dfa, i), table_size))
999 : : return 0;
1000 : : }
1001 : : return 1;
1002 : : }
1003 : :
1004 : : /**
1005 : : * verify_profile - Do post unpack analysis to verify profile consistency
1006 : : * @profile: profile to verify (NOT NULL)
1007 : : *
1008 : : * Returns: 0 if passes verification else error
1009 : : */
1010 : 0 : static int verify_profile(struct aa_profile *profile)
1011 : : {
1012 [ # # # # ]: 0 : if (profile->file.dfa &&
1013 : 0 : !verify_dfa_xindex(profile->file.dfa,
1014 : : profile->file.trans.size)) {
1015 : 0 : audit_iface(profile, NULL, NULL, "Invalid named transition",
1016 : : NULL, -EPROTO);
1017 : 0 : return -EPROTO;
1018 : : }
1019 : :
1020 : : return 0;
1021 : : }
1022 : :
1023 : 0 : void aa_load_ent_free(struct aa_load_ent *ent)
1024 : : {
1025 [ # # ]: 0 : if (ent) {
1026 : 0 : aa_put_profile(ent->rename);
1027 : 0 : aa_put_profile(ent->old);
1028 : 0 : aa_put_profile(ent->new);
1029 : 0 : kfree(ent->ns_name);
1030 : 0 : kzfree(ent);
1031 : : }
1032 : 0 : }
1033 : :
1034 : 0 : struct aa_load_ent *aa_load_ent_alloc(void)
1035 : : {
1036 : 0 : struct aa_load_ent *ent = kzalloc(sizeof(*ent), GFP_KERNEL);
1037 [ # # ]: 0 : if (ent)
1038 : 0 : INIT_LIST_HEAD(&ent->list);
1039 : 0 : return ent;
1040 : : }
1041 : :
1042 : : /**
1043 : : * aa_unpack - unpack packed binary profile(s) data loaded from user space
1044 : : * @udata: user data copied to kmem (NOT NULL)
1045 : : * @lh: list to place unpacked profiles in a aa_repl_ws
1046 : : * @ns: Returns namespace profile is in if specified else NULL (NOT NULL)
1047 : : *
1048 : : * Unpack user data and return refcounted allocated profile(s) stored in
1049 : : * @lh in order of discovery, with the list chain stored in base.list
1050 : : * or error
1051 : : *
1052 : : * Returns: profile(s) on @lh else error pointer if fails to unpack
1053 : : */
1054 : 0 : int aa_unpack(struct aa_loaddata *udata, struct list_head *lh,
1055 : : const char **ns)
1056 : : {
1057 : : struct aa_load_ent *tmp, *ent;
1058 : : struct aa_profile *profile = NULL;
1059 : : int error;
1060 : 0 : struct aa_ext e = {
1061 : 0 : .start = udata->data,
1062 : 0 : .end = udata->data + udata->size,
1063 : : .pos = udata->data,
1064 : : };
1065 : :
1066 : 0 : *ns = NULL;
1067 [ # # ]: 0 : while (e.pos < e.end) {
1068 : 0 : char *ns_name = NULL;
1069 : : void *start;
1070 : 0 : error = verify_header(&e, e.pos == e.start, ns);
1071 [ # # ]: 0 : if (error)
1072 : : goto fail;
1073 : :
1074 : 0 : start = e.pos;
1075 : 0 : profile = unpack_profile(&e, &ns_name);
1076 [ # # ]: 0 : if (IS_ERR(profile)) {
1077 : : error = PTR_ERR(profile);
1078 : 0 : goto fail;
1079 : : }
1080 : :
1081 : 0 : error = verify_profile(profile);
1082 [ # # ]: 0 : if (error)
1083 : : goto fail_profile;
1084 : :
1085 [ # # ]: 0 : if (aa_g_hash_policy)
1086 : 0 : error = aa_calc_profile_hash(profile, e.version, start,
1087 : 0 : e.pos - start);
1088 [ # # ]: 0 : if (error)
1089 : : goto fail_profile;
1090 : :
1091 : 0 : ent = aa_load_ent_alloc();
1092 [ # # ]: 0 : if (!ent) {
1093 : : error = -ENOMEM;
1094 : : goto fail_profile;
1095 : : }
1096 : :
1097 : 0 : ent->new = profile;
1098 : 0 : ent->ns_name = ns_name;
1099 : 0 : list_add_tail(&ent->list, lh);
1100 : : }
1101 : 0 : udata->abi = e.version & K_ABI_MASK;
1102 [ # # ]: 0 : if (aa_g_hash_policy) {
1103 : 0 : udata->hash = aa_calc_hash(udata->data, udata->size);
1104 [ # # ]: 0 : if (IS_ERR(udata->hash)) {
1105 : : error = PTR_ERR(udata->hash);
1106 : 0 : udata->hash = NULL;
1107 : 0 : goto fail;
1108 : : }
1109 : : }
1110 : : return 0;
1111 : :
1112 : : fail_profile:
1113 : : aa_put_profile(profile);
1114 : :
1115 : : fail:
1116 [ # # ]: 0 : list_for_each_entry_safe(ent, tmp, lh, list) {
1117 : : list_del_init(&ent->list);
1118 : 0 : aa_load_ent_free(ent);
1119 : : }
1120 : :
1121 : : return error;
1122 : : }
|