~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/apparmor/policy_unpack.c

Version: ~ [ linux-5.3-rc5 ] ~ [ linux-5.2.9 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.67 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.139 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.72 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp