LCOV - code coverage report
Current view: top level - security/apparmor - policy_unpack.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 273 0.0 %
Date: 2014-02-18 Functions: 0 19 0.0 %
Branches: 0 250 0.0 %

           Branch data     Line data    Source code
       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                 :            : /*
      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                 :            : 
      41                 :            : enum 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                 :            :  */
      62                 :            : struct 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 */
      70                 :          0 : static void audit_cb(struct audit_buffer *ab, void *va)
      71                 :            : {
      72                 :            :         struct common_audit_data *sa = va;
      73         [ #  # ]:          0 :         if (sa->aad->iface.target) {
      74                 :            :                 struct aa_profile *name = sa->aad->iface.target;
      75                 :          0 :                 audit_log_format(ab, " name=");
      76                 :          0 :                 audit_log_untrustedstring(ab, name->base.hname);
      77                 :            :         }
      78         [ #  # ]:          0 :         if (sa->aad->iface.pos)
      79                 :          0 :                 audit_log_format(ab, " offset=%ld", sa->aad->iface.pos);
      80                 :          0 : }
      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
      88                 :            :  * @error: error code
      89                 :            :  *
      90                 :            :  * Returns: %0 or error
      91                 :            :  */
      92                 :          0 : static 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                 :          0 :         struct apparmor_audit_data aad = {0,};
      98                 :          0 :         sa.type = LSM_AUDIT_DATA_NONE;
      99                 :          0 :         sa.aad = &aad;
     100         [ #  # ]:          0 :         if (e)
     101                 :          0 :                 aad.iface.pos = e->pos - e->start;
     102                 :          0 :         aad.iface.target = new;
     103                 :          0 :         aad.name = name;
     104                 :          0 :         aad.info = info;
     105                 :          0 :         aad.error = error;
     106                 :            : 
     107                 :          0 :         return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
     108                 :            :                         audit_cb);
     109                 :            : }
     110                 :            : 
     111                 :            : /* test if read will be in packed data bounds */
     112                 :            : static bool inbounds(struct aa_ext *e, size_t size)
     113                 :            : {
     114                 :          0 :         return (size <= e->end - e->pos);
     115                 :            : }
     116                 :            : 
     117                 :            : /**
     118                 :            :  * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
     119                 :            :  * @e: serialized data read head (NOT NULL)
     120                 :            :  * @chunk: start address for chunk of data (NOT NULL)
     121                 :            :  *
     122                 :            :  * Returns: the size of chunk found with the read head at the end of the chunk.
     123                 :            :  */
     124                 :          0 : static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
     125                 :            : {
     126                 :            :         size_t size = 0;
     127                 :            : 
     128 [ #  # ][ #  # ]:          0 :         if (!inbounds(e, sizeof(u16)))
     129                 :            :                 return 0;
     130                 :          0 :         size = le16_to_cpu(get_unaligned((u16 *) e->pos));
     131                 :          0 :         e->pos += sizeof(u16);
     132 [ #  # ][ #  # ]:          0 :         if (!inbounds(e, size))
     133                 :            :                 return 0;
     134                 :            :         *chunk = e->pos;
     135                 :          0 :         e->pos += size;
     136                 :            :         return size;
     137                 :            : }
     138                 :            : 
     139                 :            : /* unpack control byte */
     140                 :          0 : static bool unpack_X(struct aa_ext *e, enum aa_code code)
     141                 :            : {
     142 [ #  # ][ #  # ]:          0 :         if (!inbounds(e, 1))
     143                 :            :                 return 0;
     144 [ #  # ][ #  # ]:          0 :         if (*(u8 *) e->pos != code)
     145                 :            :                 return 0;
     146                 :          0 :         e->pos++;
     147                 :            :         return 1;
     148                 :            : }
     149                 :            : 
     150                 :            : /**
     151                 :            :  * unpack_nameX - check is the next element is of type X with a name of @name
     152                 :            :  * @e: serialized data extent information  (NOT NULL)
     153                 :            :  * @code: type code
     154                 :            :  * @name: name to match to the serialized element.  (MAYBE NULL)
     155                 :            :  *
     156                 :            :  * check that the next serialized data element is of type X and has a tag
     157                 :            :  * name @name.  If @name is specified then there must be a matching
     158                 :            :  * name element in the stream.  If @name is NULL any name element will be
     159                 :            :  * skipped and only the typecode will be tested.
     160                 :            :  *
     161                 :            :  * Returns 1 on success (both type code and name tests match) and the read
     162                 :            :  * head is advanced past the headers
     163                 :            :  *
     164                 :            :  * Returns: 0 if either match fails, the read head does not move
     165                 :            :  */
     166                 :          0 : static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
     167                 :            : {
     168                 :            :         /*
     169                 :            :          * May need to reset pos if name or type doesn't match
     170                 :            :          */
     171                 :          0 :         void *pos = e->pos;
     172                 :            :         /*
     173                 :            :          * Check for presence of a tagname, and if present name size
     174                 :            :          * AA_NAME tag value is a u16.
     175                 :            :          */
     176         [ #  # ]:          0 :         if (unpack_X(e, AA_NAME)) {
     177                 :            :                 char *tag = NULL;
     178                 :            :                 size_t size = unpack_u16_chunk(e, &tag);
     179                 :            :                 /* if a name is specified it must match. otherwise skip tag */
     180 [ #  # ][ #  # ]:          0 :                 if (name && (!size || strcmp(name, tag)))
                 [ #  # ]
     181                 :            :                         goto fail;
     182         [ #  # ]:          0 :         } else if (name) {
     183                 :            :                 /* if a name is specified and there is no name tag fail */
     184                 :            :                 goto fail;
     185                 :            :         }
     186                 :            : 
     187                 :            :         /* now check if type code matches */
     188         [ #  # ]:          0 :         if (unpack_X(e, code))
     189                 :            :                 return 1;
     190                 :            : 
     191                 :            : fail:
     192                 :          0 :         e->pos = pos;
     193                 :          0 :         return 0;
     194                 :            : }
     195                 :            : 
     196                 :          0 : static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
     197                 :            : {
     198         [ #  # ]:          0 :         if (unpack_nameX(e, AA_U32, name)) {
     199         [ #  # ]:          0 :                 if (!inbounds(e, sizeof(u32)))
     200                 :            :                         return 0;
     201         [ #  # ]:          0 :                 if (data)
     202                 :          0 :                         *data = le32_to_cpu(get_unaligned((u32 *) e->pos));
     203                 :          0 :                 e->pos += sizeof(u32);
     204                 :          0 :                 return 1;
     205                 :            :         }
     206                 :            :         return 0;
     207                 :            : }
     208                 :            : 
     209                 :          0 : static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name)
     210                 :            : {
     211         [ #  # ]:          0 :         if (unpack_nameX(e, AA_U64, name)) {
     212         [ #  # ]:          0 :                 if (!inbounds(e, sizeof(u64)))
     213                 :            :                         return 0;
     214         [ #  # ]:          0 :                 if (data)
     215                 :          0 :                         *data = le64_to_cpu(get_unaligned((u64 *) e->pos));
     216                 :          0 :                 e->pos += sizeof(u64);
     217                 :          0 :                 return 1;
     218                 :            :         }
     219                 :            :         return 0;
     220                 :            : }
     221                 :            : 
     222                 :          0 : static size_t unpack_array(struct aa_ext *e, const char *name)
     223                 :            : {
     224         [ #  # ]:          0 :         if (unpack_nameX(e, AA_ARRAY, name)) {
     225                 :            :                 int size;
     226         [ #  # ]:          0 :                 if (!inbounds(e, sizeof(u16)))
     227                 :            :                         return 0;
     228                 :            :                 size = (int)le16_to_cpu(get_unaligned((u16 *) e->pos));
     229                 :          0 :                 e->pos += sizeof(u16);
     230                 :          0 :                 return size;
     231                 :            :         }
     232                 :            :         return 0;
     233                 :            : }
     234                 :            : 
     235                 :          0 : static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
     236                 :            : {
     237         [ #  # ]:          0 :         if (unpack_nameX(e, AA_BLOB, name)) {
     238                 :            :                 u32 size;
     239         [ #  # ]:          0 :                 if (!inbounds(e, sizeof(u32)))
     240                 :            :                         return 0;
     241                 :            :                 size = le32_to_cpu(get_unaligned((u32 *) e->pos));
     242                 :          0 :                 e->pos += sizeof(u32);
     243         [ #  # ]:          0 :                 if (inbounds(e, (size_t) size)) {
     244                 :          0 :                         *blob = e->pos;
     245                 :          0 :                         e->pos += size;
     246                 :          0 :                         return size;
     247                 :            :                 }
     248                 :            :         }
     249                 :            :         return 0;
     250                 :            : }
     251                 :            : 
     252                 :          0 : static int unpack_str(struct aa_ext *e, const char **string, const char *name)
     253                 :            : {
     254                 :            :         char *src_str;
     255                 :            :         size_t size = 0;
     256                 :          0 :         void *pos = e->pos;
     257                 :          0 :         *string = NULL;
     258         [ #  # ]:          0 :         if (unpack_nameX(e, AA_STRING, name)) {
     259                 :            :                 size = unpack_u16_chunk(e, &src_str);
     260         [ #  # ]:          0 :                 if (size) {
     261                 :            :                         /* strings are null terminated, length is size - 1 */
     262         [ #  # ]:          0 :                         if (src_str[size - 1] != 0)
     263                 :            :                                 goto fail;
     264                 :          0 :                         *string = src_str;
     265                 :            :                 }
     266                 :            :         }
     267                 :          0 :         return size;
     268                 :            : 
     269                 :            : fail:
     270                 :          0 :         e->pos = pos;
     271                 :          0 :         return 0;
     272                 :            : }
     273                 :            : 
     274                 :          0 : static int unpack_strdup(struct aa_ext *e, char **string, const char *name)
     275                 :            : {
     276                 :            :         const char *tmp;
     277                 :          0 :         void *pos = e->pos;
     278                 :          0 :         int res = unpack_str(e, &tmp, name);
     279                 :          0 :         *string = NULL;
     280                 :            : 
     281         [ #  # ]:          0 :         if (!res)
     282                 :            :                 return 0;
     283                 :            : 
     284                 :          0 :         *string = kmemdup(tmp, res, GFP_KERNEL);
     285         [ #  # ]:          0 :         if (!*string) {
     286                 :          0 :                 e->pos = pos;
     287                 :          0 :                 return 0;
     288                 :            :         }
     289                 :            : 
     290                 :            :         return res;
     291                 :            : }
     292                 :            : 
     293                 :            : #define DFA_VALID_PERM_MASK             0xffffffff
     294                 :            : #define DFA_VALID_PERM2_MASK            0xffffffff
     295                 :            : 
     296                 :            : /**
     297                 :            :  * verify_accept - verify the accept tables of a dfa
     298                 :            :  * @dfa: dfa to verify accept tables of (NOT NULL)
     299                 :            :  * @flags: flags governing dfa
     300                 :            :  *
     301                 :            :  * Returns: 1 if valid accept tables else 0 if error
     302                 :            :  */
     303                 :            : static bool verify_accept(struct aa_dfa *dfa, int flags)
     304                 :            : {
     305                 :            :         int i;
     306                 :            : 
     307                 :            :         /* verify accept permissions */
     308         [ #  # ]:          0 :         for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
     309                 :            :                 int mode = ACCEPT_TABLE(dfa)[i];
     310                 :            : 
     311                 :            :                 if (mode & ~DFA_VALID_PERM_MASK)
     312                 :            :                         return 0;
     313                 :            : 
     314                 :            :                 if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
     315                 :            :                         return 0;
     316                 :            :         }
     317                 :            :         return 1;
     318                 :            : }
     319                 :            : 
     320                 :            : /**
     321                 :            :  * unpack_dfa - unpack a file rule dfa
     322                 :            :  * @e: serialized data extent information (NOT NULL)
     323                 :            :  *
     324                 :            :  * returns dfa or ERR_PTR or NULL if no dfa
     325                 :            :  */
     326                 :          0 : static struct aa_dfa *unpack_dfa(struct aa_ext *e)
     327                 :            : {
     328                 :          0 :         char *blob = NULL;
     329                 :            :         size_t size;
     330                 :          0 :         struct aa_dfa *dfa = NULL;
     331                 :            : 
     332                 :          0 :         size = unpack_blob(e, &blob, "aadfa");
     333         [ #  # ]:          0 :         if (size) {
     334                 :            :                 /*
     335                 :            :                  * The dfa is aligned with in the blob to 8 bytes
     336                 :            :                  * from the beginning of the stream.
     337                 :            :                  * alignment adjust needed by dfa unpack
     338                 :            :                  */
     339                 :          0 :                 size_t sz = blob - (char *) e->start -
     340                 :          0 :                         ((e->pos - e->start) & 7);
     341                 :          0 :                 size_t pad = ALIGN(sz, 8) - sz;
     342                 :            :                 int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
     343                 :            :                         TO_ACCEPT2_FLAG(YYTD_DATA32);
     344                 :            : 
     345                 :            : 
     346         [ #  # ]:          0 :                 if (aa_g_paranoid_load)
     347                 :            :                         flags |= DFA_FLAG_VERIFY_STATES;
     348                 :            : 
     349                 :          0 :                 dfa = aa_dfa_unpack(blob + pad, size - pad, flags);
     350                 :            : 
     351         [ #  # ]:          0 :                 if (IS_ERR(dfa))
     352                 :            :                         return dfa;
     353                 :            : 
     354                 :            :                 if (!verify_accept(dfa, flags))
     355                 :            :                         goto fail;
     356                 :            :         }
     357                 :            : 
     358                 :          0 :         return dfa;
     359                 :            : 
     360                 :            : fail:
     361                 :            :         aa_put_dfa(dfa);
     362                 :            :         return ERR_PTR(-EPROTO);
     363                 :            : }
     364                 :            : 
     365                 :            : /**
     366                 :            :  * unpack_trans_table - unpack a profile transition table
     367                 :            :  * @e: serialized data extent information  (NOT NULL)
     368                 :            :  * @profile: profile to add the accept table to (NOT NULL)
     369                 :            :  *
     370                 :            :  * Returns: 1 if table successfully unpacked
     371                 :            :  */
     372                 :          0 : static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
     373                 :            : {
     374                 :          0 :         void *pos = e->pos;
     375                 :            : 
     376                 :            :         /* exec table is optional */
     377         [ #  # ]:          0 :         if (unpack_nameX(e, AA_STRUCT, "xtable")) {
     378                 :            :                 int i, size;
     379                 :            : 
     380                 :          0 :                 size = unpack_array(e, NULL);
     381                 :            :                 /* currently 4 exec bits and entries 0-3 are reserved iupcx */
     382         [ #  # ]:          0 :                 if (size > 16 - 4)
     383                 :            :                         goto fail;
     384                 :          0 :                 profile->file.trans.table = kzalloc(sizeof(char *) * size,
     385                 :            :                                                     GFP_KERNEL);
     386         [ #  # ]:          0 :                 if (!profile->file.trans.table)
     387                 :            :                         goto fail;
     388                 :            : 
     389                 :          0 :                 profile->file.trans.size = size;
     390         [ #  # ]:          0 :                 for (i = 0; i < size; i++) {
     391                 :            :                         char *str;
     392                 :          0 :                         int c, j, size2 = unpack_strdup(e, &str, NULL);
     393                 :            :                         /* unpack_strdup verifies that the last character is
     394                 :            :                          * null termination byte.
     395                 :            :                          */
     396         [ #  # ]:          0 :                         if (!size2)
     397                 :            :                                 goto fail;
     398                 :          0 :                         profile->file.trans.table[i] = str;
     399                 :            :                         /* verify that name doesn't start with space */
     400         [ #  # ]:          0 :                         if (isspace(*str))
     401                 :            :                                 goto fail;
     402                 :            : 
     403                 :            :                         /* count internal #  of internal \0 */
     404         [ #  # ]:          0 :                         for (c = j = 0; j < size2 - 2; j++) {
     405         [ #  # ]:          0 :                                 if (!str[j])
     406                 :          0 :                                         c++;
     407                 :            :                         }
     408         [ #  # ]:          0 :                         if (*str == ':') {
     409                 :            :                                 /* beginning with : requires an embedded \0,
     410                 :            :                                  * verify that exactly 1 internal \0 exists
     411                 :            :                                  * trailing \0 already verified by unpack_strdup
     412                 :            :                                  */
     413         [ #  # ]:          0 :                                 if (c != 1)
     414                 :            :                                         goto fail;
     415                 :            :                                 /* first character after : must be valid */
     416         [ #  # ]:          0 :                                 if (!str[1])
     417                 :            :                                         goto fail;
     418         [ #  # ]:          0 :                         } else if (c)
     419                 :            :                                 /* fail - all other cases with embedded \0 */
     420                 :            :                                 goto fail;
     421                 :            :                 }
     422         [ #  # ]:          0 :                 if (!unpack_nameX(e, AA_ARRAYEND, NULL))
     423                 :            :                         goto fail;
     424         [ #  # ]:          0 :                 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
     425                 :            :                         goto fail;
     426                 :            :         }
     427                 :            :         return 1;
     428                 :            : 
     429                 :            : fail:
     430                 :          0 :         aa_free_domain_entries(&profile->file.trans);
     431                 :          0 :         e->pos = pos;
     432                 :          0 :         return 0;
     433                 :            : }
     434                 :            : 
     435                 :          0 : static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
     436                 :            : {
     437                 :          0 :         void *pos = e->pos;
     438                 :            : 
     439                 :            :         /* rlimits are optional */
     440         [ #  # ]:          0 :         if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
     441                 :            :                 int i, size;
     442                 :          0 :                 u32 tmp = 0;
     443         [ #  # ]:          0 :                 if (!unpack_u32(e, &tmp, NULL))
     444                 :            :                         goto fail;
     445                 :          0 :                 profile->rlimits.mask = tmp;
     446                 :            : 
     447                 :          0 :                 size = unpack_array(e, NULL);
     448         [ #  # ]:          0 :                 if (size > RLIM_NLIMITS)
     449                 :            :                         goto fail;
     450         [ #  # ]:          0 :                 for (i = 0; i < size; i++) {
     451                 :          0 :                         u64 tmp2 = 0;
     452                 :          0 :                         int a = aa_map_resource(i);
     453         [ #  # ]:          0 :                         if (!unpack_u64(e, &tmp2, NULL))
     454                 :            :                                 goto fail;
     455                 :          0 :                         profile->rlimits.limits[a].rlim_max = tmp2;
     456                 :            :                 }
     457         [ #  # ]:          0 :                 if (!unpack_nameX(e, AA_ARRAYEND, NULL))
     458                 :            :                         goto fail;
     459         [ #  # ]:          0 :                 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
     460                 :            :                         goto fail;
     461                 :            :         }
     462                 :            :         return 1;
     463                 :            : 
     464                 :            : fail:
     465                 :          0 :         e->pos = pos;
     466                 :          0 :         return 0;
     467                 :            : }
     468                 :            : 
     469                 :            : /**
     470                 :            :  * unpack_profile - unpack a serialized profile
     471                 :            :  * @e: serialized data extent information (NOT NULL)
     472                 :            :  *
     473                 :            :  * NOTE: unpack profile sets audit struct if there is a failure
     474                 :            :  */
     475                 :          0 : static struct aa_profile *unpack_profile(struct aa_ext *e)
     476                 :            : {
     477                 :            :         struct aa_profile *profile = NULL;
     478                 :          0 :         const char *name = NULL;
     479                 :            :         int i, error = -EPROTO;
     480                 :            :         kernel_cap_t tmpcap;
     481                 :            :         u32 tmp;
     482                 :            : 
     483                 :            :         /* check that we have the right struct being passed */
     484         [ #  # ]:          0 :         if (!unpack_nameX(e, AA_STRUCT, "profile"))
     485                 :            :                 goto fail;
     486         [ #  # ]:          0 :         if (!unpack_str(e, &name, NULL))
     487                 :            :                 goto fail;
     488                 :            : 
     489                 :          0 :         profile = aa_alloc_profile(name);
     490         [ #  # ]:          0 :         if (!profile)
     491                 :            :                 return ERR_PTR(-ENOMEM);
     492                 :            : 
     493                 :            :         /* profile renaming is optional */
     494                 :          0 :         (void) unpack_str(e, &profile->rename, "rename");
     495                 :            : 
     496                 :            :         /* attachment string is optional */
     497                 :          0 :         (void) unpack_str(e, &profile->attach, "attach");
     498                 :            : 
     499                 :            :         /* xmatch is optional and may be NULL */
     500                 :          0 :         profile->xmatch = unpack_dfa(e);
     501         [ #  # ]:          0 :         if (IS_ERR(profile->xmatch)) {
     502                 :            :                 error = PTR_ERR(profile->xmatch);
     503                 :          0 :                 profile->xmatch = NULL;
     504                 :          0 :                 goto fail;
     505                 :            :         }
     506                 :            :         /* xmatch_len is not optional if xmatch is set */
     507         [ #  # ]:          0 :         if (profile->xmatch) {
     508         [ #  # ]:          0 :                 if (!unpack_u32(e, &tmp, NULL))
     509                 :            :                         goto fail;
     510                 :          0 :                 profile->xmatch_len = tmp;
     511                 :            :         }
     512                 :            : 
     513                 :            :         /* per profile debug flags (complain, audit) */
     514         [ #  # ]:          0 :         if (!unpack_nameX(e, AA_STRUCT, "flags"))
     515                 :            :                 goto fail;
     516         [ #  # ]:          0 :         if (!unpack_u32(e, &tmp, NULL))
     517                 :            :                 goto fail;
     518         [ #  # ]:          0 :         if (tmp & PACKED_FLAG_HAT)
     519                 :          0 :                 profile->flags |= PFLAG_HAT;
     520         [ #  # ]:          0 :         if (!unpack_u32(e, &tmp, NULL))
     521                 :            :                 goto fail;
     522         [ #  # ]:          0 :         if (tmp == PACKED_MODE_COMPLAIN)
     523                 :          0 :                 profile->mode = APPARMOR_COMPLAIN;
     524         [ #  # ]:          0 :         else if (tmp == PACKED_MODE_KILL)
     525                 :          0 :                 profile->mode = APPARMOR_KILL;
     526         [ #  # ]:          0 :         else if (tmp == PACKED_MODE_UNCONFINED)
     527                 :          0 :                 profile->mode = APPARMOR_UNCONFINED;
     528         [ #  # ]:          0 :         if (!unpack_u32(e, &tmp, NULL))
     529                 :            :                 goto fail;
     530         [ #  # ]:          0 :         if (tmp)
     531                 :          0 :                 profile->audit = AUDIT_ALL;
     532                 :            : 
     533         [ #  # ]:          0 :         if (!unpack_nameX(e, AA_STRUCTEND, NULL))
     534                 :            :                 goto fail;
     535                 :            : 
     536                 :            :         /* path_flags is optional */
     537         [ #  # ]:          0 :         if (unpack_u32(e, &profile->path_flags, "path_flags"))
     538                 :          0 :                 profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED;
     539                 :            :         else
     540                 :            :                 /* set a default value if path_flags field is not present */
     541                 :          0 :                 profile->path_flags = PFLAG_MEDIATE_DELETED;
     542                 :            : 
     543         [ #  # ]:          0 :         if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL))
     544                 :            :                 goto fail;
     545         [ #  # ]:          0 :         if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
     546                 :            :                 goto fail;
     547         [ #  # ]:          0 :         if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL))
     548                 :            :                 goto fail;
     549         [ #  # ]:          0 :         if (!unpack_u32(e, &tmpcap.cap[0], NULL))
     550                 :            :                 goto fail;
     551                 :            : 
     552         [ #  # ]:          0 :         if (unpack_nameX(e, AA_STRUCT, "caps64")) {
     553                 :            :                 /* optional upper half of 64 bit caps */
     554         [ #  # ]:          0 :                 if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL))
     555                 :            :                         goto fail;
     556         [ #  # ]:          0 :                 if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL))
     557                 :            :                         goto fail;
     558         [ #  # ]:          0 :                 if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL))
     559                 :            :                         goto fail;
     560         [ #  # ]:          0 :                 if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
     561                 :            :                         goto fail;
     562         [ #  # ]:          0 :                 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
     563                 :            :                         goto fail;
     564                 :            :         }
     565                 :            : 
     566         [ #  # ]:          0 :         if (unpack_nameX(e, AA_STRUCT, "capsx")) {
     567                 :            :                 /* optional extended caps mediation mask */
     568         [ #  # ]:          0 :                 if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
     569                 :            :                         goto fail;
     570         [ #  # ]:          0 :                 if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
     571                 :            :                         goto fail;
     572         [ #  # ]:          0 :                 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
     573                 :            :                         goto fail;
     574                 :            :         }
     575                 :            : 
     576         [ #  # ]:          0 :         if (!unpack_rlimits(e, profile))
     577                 :            :                 goto fail;
     578                 :            : 
     579         [ #  # ]:          0 :         if (unpack_nameX(e, AA_STRUCT, "policydb")) {
     580                 :            :                 /* generic policy dfa - optional and may be NULL */
     581                 :          0 :                 profile->policy.dfa = unpack_dfa(e);
     582         [ #  # ]:          0 :                 if (IS_ERR(profile->policy.dfa)) {
     583                 :            :                         error = PTR_ERR(profile->policy.dfa);
     584                 :          0 :                         profile->policy.dfa = NULL;
     585                 :          0 :                         goto fail;
     586                 :            :                 }
     587         [ #  # ]:          0 :                 if (!unpack_u32(e, &profile->policy.start[0], "start"))
     588                 :            :                         /* default start state */
     589                 :          0 :                         profile->policy.start[0] = DFA_START;
     590                 :            :                 /* setup class index */
     591         [ #  # ]:          0 :                 for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) {
     592                 :          0 :                         profile->policy.start[i] =
     593                 :          0 :                                 aa_dfa_next(profile->policy.dfa,
     594                 :            :                                             profile->policy.start[0],
     595                 :            :                                             i);
     596                 :            :                 }
     597         [ #  # ]:          0 :                 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
     598                 :            :                         goto fail;
     599                 :            :         }
     600                 :            : 
     601                 :            :         /* get file rules */
     602                 :          0 :         profile->file.dfa = unpack_dfa(e);
     603         [ #  # ]:          0 :         if (IS_ERR(profile->file.dfa)) {
     604                 :            :                 error = PTR_ERR(profile->file.dfa);
     605                 :          0 :                 profile->file.dfa = NULL;
     606                 :          0 :                 goto fail;
     607                 :            :         }
     608                 :            : 
     609         [ #  # ]:          0 :         if (!unpack_u32(e, &profile->file.start, "dfa_start"))
     610                 :            :                 /* default start state */
     611                 :          0 :                 profile->file.start = DFA_START;
     612                 :            : 
     613         [ #  # ]:          0 :         if (!unpack_trans_table(e, profile))
     614                 :            :                 goto fail;
     615                 :            : 
     616         [ #  # ]:          0 :         if (!unpack_nameX(e, AA_STRUCTEND, NULL))
     617                 :            :                 goto fail;
     618                 :            : 
     619                 :            :         return profile;
     620                 :            : 
     621                 :            : fail:
     622         [ #  # ]:          0 :         if (profile)
     623                 :          0 :                 name = NULL;
     624         [ #  # ]:          0 :         else if (!name)
     625                 :          0 :                 name = "unknown";
     626                 :          0 :         audit_iface(profile, name, "failed to unpack profile", e, error);
     627                 :          0 :         aa_free_profile(profile);
     628                 :            : 
     629                 :          0 :         return ERR_PTR(error);
     630                 :            : }
     631                 :            : 
     632                 :            : /**
     633                 :            :  * verify_head - unpack serialized stream header
     634                 :            :  * @e: serialized data read head (NOT NULL)
     635                 :            :  * @required: whether the header is required or optional
     636                 :            :  * @ns: Returns - namespace if one is specified else NULL (NOT NULL)
     637                 :            :  *
     638                 :            :  * Returns: error or 0 if header is good
     639                 :            :  */
     640                 :          0 : static int verify_header(struct aa_ext *e, int required, const char **ns)
     641                 :            : {
     642                 :            :         int error = -EPROTONOSUPPORT;
     643                 :          0 :         const char *name = NULL;
     644                 :          0 :         *ns = NULL;
     645                 :            : 
     646                 :            :         /* get the interface version */
     647         [ #  # ]:          0 :         if (!unpack_u32(e, &e->version, "version")) {
     648         [ #  # ]:          0 :                 if (required) {
     649                 :          0 :                         audit_iface(NULL, NULL, "invalid profile format", e,
     650                 :            :                                     error);
     651                 :          0 :                         return error;
     652                 :            :                 }
     653                 :            : 
     654                 :            :                 /* check that the interface version is currently supported */
     655         [ #  # ]:          0 :                 if (e->version != 5) {
     656                 :          0 :                         audit_iface(NULL, NULL, "unsupported interface version",
     657                 :            :                                     e, error);
     658                 :          0 :                         return error;
     659                 :            :                 }
     660                 :            :         }
     661                 :            : 
     662                 :            : 
     663                 :            :         /* read the namespace if present */
     664         [ #  # ]:          0 :         if (unpack_str(e, &name, "namespace")) {
     665 [ #  # ][ #  # ]:          0 :                 if (*ns && strcmp(*ns, name))
     666                 :          0 :                         audit_iface(NULL, NULL, "invalid ns change", e, error);
     667         [ #  # ]:          0 :                 else if (!*ns)
     668                 :          0 :                         *ns = name;
     669                 :            :         }
     670                 :            : 
     671                 :            :         return 0;
     672                 :            : }
     673                 :            : 
     674                 :            : static bool verify_xindex(int xindex, int table_size)
     675                 :            : {
     676                 :            :         int index, xtype;
     677                 :          0 :         xtype = xindex & AA_X_TYPE_MASK;
     678                 :          0 :         index = xindex & AA_X_INDEX_MASK;
     679 [ #  # ][ #  # ]:          0 :         if (xtype == AA_X_TABLE && index > table_size)
     680                 :            :                 return 0;
     681                 :            :         return 1;
     682                 :            : }
     683                 :            : 
     684                 :            : /* verify dfa xindexes are in range of transition tables */
     685                 :          0 : static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
     686                 :            : {
     687                 :            :         int i;
     688         [ #  # ]:          0 :         for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
     689         [ #  # ]:          0 :                 if (!verify_xindex(dfa_user_xindex(dfa, i), table_size))
     690                 :            :                         return 0;
     691         [ #  # ]:          0 :                 if (!verify_xindex(dfa_other_xindex(dfa, i), table_size))
     692                 :            :                         return 0;
     693                 :            :         }
     694                 :            :         return 1;
     695                 :            : }
     696                 :            : 
     697                 :            : /**
     698                 :            :  * verify_profile - Do post unpack analysis to verify profile consistency
     699                 :            :  * @profile: profile to verify (NOT NULL)
     700                 :            :  *
     701                 :            :  * Returns: 0 if passes verification else error
     702                 :            :  */
     703                 :          0 : static int verify_profile(struct aa_profile *profile)
     704                 :            : {
     705         [ #  # ]:          0 :         if (aa_g_paranoid_load) {
     706   [ #  #  #  # ]:          0 :                 if (profile->file.dfa &&
     707                 :          0 :                     !verify_dfa_xindex(profile->file.dfa,
     708                 :            :                                        profile->file.trans.size)) {
     709                 :          0 :                         audit_iface(profile, NULL, "Invalid named transition",
     710                 :            :                                     NULL, -EPROTO);
     711                 :          0 :                         return -EPROTO;
     712                 :            :                 }
     713                 :            :         }
     714                 :            : 
     715                 :            :         return 0;
     716                 :            : }
     717                 :            : 
     718                 :          0 : void aa_load_ent_free(struct aa_load_ent *ent)
     719                 :            : {
     720         [ #  # ]:          0 :         if (ent) {
     721                 :          0 :                 aa_put_profile(ent->rename);
     722                 :          0 :                 aa_put_profile(ent->old);
     723                 :          0 :                 aa_put_profile(ent->new);
     724                 :          0 :                 kzfree(ent);
     725                 :            :         }
     726                 :          0 : }
     727                 :            : 
     728                 :          0 : struct aa_load_ent *aa_load_ent_alloc(void)
     729                 :            : {
     730                 :            :         struct aa_load_ent *ent = kzalloc(sizeof(*ent), GFP_KERNEL);
     731         [ #  # ]:          0 :         if (ent)
     732                 :          0 :                 INIT_LIST_HEAD(&ent->list);
     733                 :          0 :         return ent;
     734                 :            : }
     735                 :            : 
     736                 :            : /**
     737                 :            :  * aa_unpack - unpack packed binary profile(s) data loaded from user space
     738                 :            :  * @udata: user data copied to kmem  (NOT NULL)
     739                 :            :  * @size: the size of the user data
     740                 :            :  * @lh: list to place unpacked profiles in a aa_repl_ws
     741                 :            :  * @ns: Returns namespace profile is in if specified else NULL (NOT NULL)
     742                 :            :  *
     743                 :            :  * Unpack user data and return refcounted allocated profile(s) stored in
     744                 :            :  * @lh in order of discovery, with the list chain stored in base.list
     745                 :            :  * or error
     746                 :            :  *
     747                 :            :  * Returns: profile(s) on @lh else error pointer if fails to unpack
     748                 :            :  */
     749                 :          0 : int aa_unpack(void *udata, size_t size, struct list_head *lh, const char **ns)
     750                 :            : {
     751                 :            :         struct aa_load_ent *tmp, *ent;
     752                 :            :         struct aa_profile *profile = NULL;
     753                 :            :         int error;
     754                 :          0 :         struct aa_ext e = {
     755                 :            :                 .start = udata,
     756                 :          0 :                 .end = udata + size,
     757                 :            :                 .pos = udata,
     758                 :            :         };
     759                 :            : 
     760                 :          0 :         *ns = NULL;
     761         [ #  # ]:          0 :         while (e.pos < e.end) {
     762                 :            :                 void *start;
     763                 :          0 :                 error = verify_header(&e, e.pos == e.start, ns);
     764         [ #  # ]:          0 :                 if (error)
     765                 :            :                         goto fail;
     766                 :            : 
     767                 :          0 :                 start = e.pos;
     768                 :          0 :                 profile = unpack_profile(&e);
     769         [ #  # ]:          0 :                 if (IS_ERR(profile)) {
     770                 :            :                         error = PTR_ERR(profile);
     771                 :          0 :                         goto fail;
     772                 :            :                 }
     773                 :            : 
     774                 :          0 :                 error = verify_profile(profile);
     775         [ #  # ]:          0 :                 if (error)
     776                 :            :                         goto fail_profile;
     777                 :            : 
     778                 :          0 :                 error = aa_calc_profile_hash(profile, e.version, start,
     779                 :          0 :                                              e.pos - start);
     780         [ #  # ]:          0 :                 if (error)
     781                 :            :                         goto fail_profile;
     782                 :            : 
     783                 :          0 :                 ent = aa_load_ent_alloc();
     784         [ #  # ]:          0 :                 if (!ent) {
     785                 :            :                         error = -ENOMEM;
     786                 :            :                         goto fail_profile;
     787                 :            :                 }
     788                 :            : 
     789                 :          0 :                 ent->new = profile;
     790                 :          0 :                 list_add_tail(&ent->list, lh);
     791                 :            :         }
     792                 :            : 
     793                 :            :         return 0;
     794                 :            : 
     795                 :            : fail_profile:
     796                 :            :         aa_put_profile(profile);
     797                 :            : 
     798                 :            : fail:
     799         [ #  # ]:          0 :         list_for_each_entry_safe(ent, tmp, lh, list) {
     800                 :            :                 list_del_init(&ent->list);
     801                 :          0 :                 aa_load_ent_free(ent);
     802                 :            :         }
     803                 :            : 
     804                 :            :         return error;
     805                 :            : }

Generated by: LCOV version 1.9