LCOV - code coverage report
Current view: top level - security/apparmor - policy.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 0 359 0.0 %
Date: 2020-09-30 20:25:01 Functions: 0 28 0.0 %
Branches: 0 234 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * AppArmor security module
       4                 :            :  *
       5                 :            :  * This file contains AppArmor policy manipulation functions
       6                 :            :  *
       7                 :            :  * Copyright (C) 1998-2008 Novell/SUSE
       8                 :            :  * Copyright 2009-2010 Canonical Ltd.
       9                 :            :  *
      10                 :            :  * AppArmor policy is based around profiles, which contain the rules a
      11                 :            :  * task is confined by.  Every task in the system has a profile attached
      12                 :            :  * to it determined either by matching "unconfined" tasks against the
      13                 :            :  * visible set of profiles or by following a profiles attachment rules.
      14                 :            :  *
      15                 :            :  * Each profile exists in a profile namespace which is a container of
      16                 :            :  * visible profiles.  Each namespace contains a special "unconfined" profile,
      17                 :            :  * which doesn't enforce any confinement on a task beyond DAC.
      18                 :            :  *
      19                 :            :  * Namespace and profile names can be written together in either
      20                 :            :  * of two syntaxes.
      21                 :            :  *      :namespace:profile - used by kernel interfaces for easy detection
      22                 :            :  *      namespace://profile - used by policy
      23                 :            :  *
      24                 :            :  * Profile names can not start with : or @ or ^ and may not contain \0
      25                 :            :  *
      26                 :            :  * Reserved profile names
      27                 :            :  *      unconfined - special automatically generated unconfined profile
      28                 :            :  *      inherit - special name to indicate profile inheritance
      29                 :            :  *      null-XXXX-YYYY - special automatically generated learning profiles
      30                 :            :  *
      31                 :            :  * Namespace names may not start with / or @ and may not contain \0 or :
      32                 :            :  * Reserved namespace names
      33                 :            :  *      user-XXXX - user defined profiles
      34                 :            :  *
      35                 :            :  * a // in a profile or namespace name indicates a hierarchical name with the
      36                 :            :  * name before the // being the parent and the name after the child.
      37                 :            :  *
      38                 :            :  * Profile and namespace hierarchies serve two different but similar purposes.
      39                 :            :  * The namespace contains the set of visible profiles that are considered
      40                 :            :  * for attachment.  The hierarchy of namespaces allows for virtualizing
      41                 :            :  * the namespace so that for example a chroot can have its own set of profiles
      42                 :            :  * which may define some local user namespaces.
      43                 :            :  * The profile hierarchy severs two distinct purposes,
      44                 :            :  * -  it allows for sub profiles or hats, which allows an application to run
      45                 :            :  *    subprograms under its own profile with different restriction than it
      46                 :            :  *    self, and not have it use the system profile.
      47                 :            :  *    eg. if a mail program starts an editor, the policy might make the
      48                 :            :  *        restrictions tighter on the editor tighter than the mail program,
      49                 :            :  *        and definitely different than general editor restrictions
      50                 :            :  * - it allows for binary hierarchy of profiles, so that execution history
      51                 :            :  *   is preserved.  This feature isn't exploited by AppArmor reference policy
      52                 :            :  *   but is allowed.  NOTE: this is currently suboptimal because profile
      53                 :            :  *   aliasing is not currently implemented so that a profile for each
      54                 :            :  *   level must be defined.
      55                 :            :  *   eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
      56                 :            :  *       from /bin/bash
      57                 :            :  *
      58                 :            :  *   A profile or namespace name that can contain one or more // separators
      59                 :            :  *   is referred to as an hname (hierarchical).
      60                 :            :  *   eg.  /bin/bash//bin/ls
      61                 :            :  *
      62                 :            :  *   An fqname is a name that may contain both namespace and profile hnames.
      63                 :            :  *   eg. :ns:/bin/bash//bin/ls
      64                 :            :  *
      65                 :            :  * NOTES:
      66                 :            :  *   - locking of profile lists is currently fairly coarse.  All profile
      67                 :            :  *     lists within a namespace use the namespace lock.
      68                 :            :  * FIXME: move profile lists to using rcu_lists
      69                 :            :  */
      70                 :            : 
      71                 :            : #include <linux/slab.h>
      72                 :            : #include <linux/spinlock.h>
      73                 :            : #include <linux/string.h>
      74                 :            : #include <linux/cred.h>
      75                 :            : #include <linux/rculist.h>
      76                 :            : #include <linux/user_namespace.h>
      77                 :            : 
      78                 :            : #include "include/apparmor.h"
      79                 :            : #include "include/capability.h"
      80                 :            : #include "include/cred.h"
      81                 :            : #include "include/file.h"
      82                 :            : #include "include/ipc.h"
      83                 :            : #include "include/match.h"
      84                 :            : #include "include/path.h"
      85                 :            : #include "include/policy.h"
      86                 :            : #include "include/policy_ns.h"
      87                 :            : #include "include/policy_unpack.h"
      88                 :            : #include "include/resource.h"
      89                 :            : 
      90                 :            : int unprivileged_userns_apparmor_policy = 1;
      91                 :            : 
      92                 :            : const char *const aa_profile_mode_names[] = {
      93                 :            :         "enforce",
      94                 :            :         "complain",
      95                 :            :         "kill",
      96                 :            :         "unconfined",
      97                 :            : };
      98                 :            : 
      99                 :            : 
     100                 :            : /**
     101                 :            :  * __add_profile - add a profiles to list and label tree
     102                 :            :  * @list: list to add it to  (NOT NULL)
     103                 :            :  * @profile: the profile to add  (NOT NULL)
     104                 :            :  *
     105                 :            :  * refcount @profile, should be put by __list_remove_profile
     106                 :            :  *
     107                 :            :  * Requires: namespace lock be held, or list not be shared
     108                 :            :  */
     109                 :          0 : static void __add_profile(struct list_head *list, struct aa_profile *profile)
     110                 :            : {
     111                 :            :         struct aa_label *l;
     112                 :            : 
     113                 :            :         AA_BUG(!list);
     114                 :            :         AA_BUG(!profile);
     115                 :            :         AA_BUG(!profile->ns);
     116                 :            :         AA_BUG(!mutex_is_locked(&profile->ns->lock));
     117                 :            : 
     118                 :          0 :         list_add_rcu(&profile->base.list, list);
     119                 :            :         /* get list reference */
     120                 :            :         aa_get_profile(profile);
     121                 :          0 :         l = aa_label_insert(&profile->ns->labels, &profile->label);
     122                 :            :         AA_BUG(l != &profile->label);
     123                 :            :         aa_put_label(l);
     124                 :          0 : }
     125                 :            : 
     126                 :            : /**
     127                 :            :  * __list_remove_profile - remove a profile from the list it is on
     128                 :            :  * @profile: the profile to remove  (NOT NULL)
     129                 :            :  *
     130                 :            :  * remove a profile from the list, warning generally removal should
     131                 :            :  * be done with __replace_profile as most profile removals are
     132                 :            :  * replacements to the unconfined profile.
     133                 :            :  *
     134                 :            :  * put @profile list refcount
     135                 :            :  *
     136                 :            :  * Requires: namespace lock be held, or list not have been live
     137                 :            :  */
     138                 :          0 : static void __list_remove_profile(struct aa_profile *profile)
     139                 :            : {
     140                 :            :         AA_BUG(!profile);
     141                 :            :         AA_BUG(!profile->ns);
     142                 :            :         AA_BUG(!mutex_is_locked(&profile->ns->lock));
     143                 :            : 
     144                 :            :         list_del_rcu(&profile->base.list);
     145                 :            :         aa_put_profile(profile);
     146                 :          0 : }
     147                 :            : 
     148                 :            : /**
     149                 :            :  * __remove_profile - remove old profile, and children
     150                 :            :  * @profile: profile to be replaced  (NOT NULL)
     151                 :            :  *
     152                 :            :  * Requires: namespace list lock be held, or list not be shared
     153                 :            :  */
     154                 :          0 : static void __remove_profile(struct aa_profile *profile)
     155                 :            : {
     156                 :            :         AA_BUG(!profile);
     157                 :            :         AA_BUG(!profile->ns);
     158                 :            :         AA_BUG(!mutex_is_locked(&profile->ns->lock));
     159                 :            : 
     160                 :            :         /* release any children lists first */
     161                 :          0 :         __aa_profile_list_release(&profile->base.profiles);
     162                 :            :         /* released by free_profile */
     163                 :          0 :         aa_label_remove(&profile->label);
     164                 :          0 :         __aafs_profile_rmdir(profile);
     165                 :          0 :         __list_remove_profile(profile);
     166                 :          0 : }
     167                 :            : 
     168                 :            : /**
     169                 :            :  * __aa_profile_list_release - remove all profiles on the list and put refs
     170                 :            :  * @head: list of profiles  (NOT NULL)
     171                 :            :  *
     172                 :            :  * Requires: namespace lock be held
     173                 :            :  */
     174                 :          0 : void __aa_profile_list_release(struct list_head *head)
     175                 :            : {
     176                 :            :         struct aa_profile *profile, *tmp;
     177         [ #  # ]:          0 :         list_for_each_entry_safe(profile, tmp, head, base.list)
     178                 :          0 :                 __remove_profile(profile);
     179                 :          0 : }
     180                 :            : 
     181                 :            : /**
     182                 :            :  * aa_free_data - free a data blob
     183                 :            :  * @ptr: data to free
     184                 :            :  * @arg: unused
     185                 :            :  */
     186                 :          0 : static void aa_free_data(void *ptr, void *arg)
     187                 :            : {
     188                 :            :         struct aa_data *data = ptr;
     189                 :            : 
     190                 :          0 :         kzfree(data->data);
     191                 :          0 :         kzfree(data->key);
     192                 :          0 :         kzfree(data);
     193                 :          0 : }
     194                 :            : 
     195                 :            : /**
     196                 :            :  * aa_free_profile - free a profile
     197                 :            :  * @profile: the profile to free  (MAYBE NULL)
     198                 :            :  *
     199                 :            :  * Free a profile, its hats and null_profile. All references to the profile,
     200                 :            :  * its hats and null_profile must have been put.
     201                 :            :  *
     202                 :            :  * If the profile was referenced from a task context, free_profile() will
     203                 :            :  * be called from an rcu callback routine, so we must not sleep here.
     204                 :            :  */
     205                 :          0 : void aa_free_profile(struct aa_profile *profile)
     206                 :            : {
     207                 :            :         struct rhashtable *rht;
     208                 :            :         int i;
     209                 :            : 
     210                 :            :         AA_DEBUG("%s(%p)\n", __func__, profile);
     211                 :            : 
     212         [ #  # ]:          0 :         if (!profile)
     213                 :          0 :                 return;
     214                 :            : 
     215                 :            :         /* free children profiles */
     216                 :          0 :         aa_policy_destroy(&profile->base);
     217                 :          0 :         aa_put_profile(rcu_access_pointer(profile->parent));
     218                 :            : 
     219                 :          0 :         aa_put_ns(profile->ns);
     220                 :          0 :         kzfree(profile->rename);
     221                 :            : 
     222                 :          0 :         aa_free_file_rules(&profile->file);
     223                 :            :         aa_free_cap_rules(&profile->caps);
     224                 :            :         aa_free_rlimit_rules(&profile->rlimits);
     225                 :            : 
     226         [ #  # ]:          0 :         for (i = 0; i < profile->xattr_count; i++)
     227                 :          0 :                 kzfree(profile->xattrs[i]);
     228                 :          0 :         kzfree(profile->xattrs);
     229         [ #  # ]:          0 :         for (i = 0; i < profile->secmark_count; i++)
     230                 :          0 :                 kzfree(profile->secmark[i].label);
     231                 :          0 :         kzfree(profile->secmark);
     232                 :          0 :         kzfree(profile->dirname);
     233                 :          0 :         aa_put_dfa(profile->xmatch);
     234                 :          0 :         aa_put_dfa(profile->policy.dfa);
     235                 :            : 
     236         [ #  # ]:          0 :         if (profile->data) {
     237                 :            :                 rht = profile->data;
     238                 :          0 :                 profile->data = NULL;
     239                 :          0 :                 rhashtable_free_and_destroy(rht, aa_free_data, NULL);
     240                 :          0 :                 kzfree(rht);
     241                 :            :         }
     242                 :            : 
     243                 :          0 :         kzfree(profile->hash);
     244                 :          0 :         aa_put_loaddata(profile->rawdata);
     245                 :            : 
     246                 :          0 :         kzfree(profile);
     247                 :            : }
     248                 :            : 
     249                 :            : /**
     250                 :            :  * aa_alloc_profile - allocate, initialize and return a new profile
     251                 :            :  * @hname: name of the profile  (NOT NULL)
     252                 :            :  * @gfp: allocation type
     253                 :            :  *
     254                 :            :  * Returns: refcount profile or NULL on failure
     255                 :            :  */
     256                 :          0 : struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy,
     257                 :            :                                     gfp_t gfp)
     258                 :            : {
     259                 :            :         struct aa_profile *profile;
     260                 :            : 
     261                 :            :         /* freed by free_profile - usually through aa_put_profile */
     262                 :          0 :         profile = kzalloc(sizeof(*profile) + sizeof(struct aa_profile *) * 2,
     263                 :            :                           gfp);
     264         [ #  # ]:          0 :         if (!profile)
     265                 :            :                 return NULL;
     266                 :            : 
     267         [ #  # ]:          0 :         if (!aa_policy_init(&profile->base, NULL, hname, gfp))
     268                 :            :                 goto fail;
     269         [ #  # ]:          0 :         if (!aa_label_init(&profile->label, 1, gfp))
     270                 :            :                 goto fail;
     271                 :            : 
     272                 :            :         /* update being set needed by fs interface */
     273         [ #  # ]:          0 :         if (!proxy) {
     274                 :          0 :                 proxy = aa_alloc_proxy(&profile->label, gfp);
     275         [ #  # ]:          0 :                 if (!proxy)
     276                 :            :                         goto fail;
     277                 :            :         } else
     278                 :            :                 aa_get_proxy(proxy);
     279                 :          0 :         profile->label.proxy = proxy;
     280                 :            : 
     281                 :          0 :         profile->label.hname = profile->base.hname;
     282                 :          0 :         profile->label.flags |= FLAG_PROFILE;
     283                 :          0 :         profile->label.vec[0] = profile;
     284                 :            : 
     285                 :            :         /* refcount released by caller */
     286                 :          0 :         return profile;
     287                 :            : 
     288                 :            : fail:
     289                 :          0 :         aa_free_profile(profile);
     290                 :            : 
     291                 :          0 :         return NULL;
     292                 :            : }
     293                 :            : 
     294                 :            : /* TODO: profile accounting - setup in remove */
     295                 :            : 
     296                 :            : /**
     297                 :            :  * __strn_find_child - find a profile on @head list using substring of @name
     298                 :            :  * @head: list to search  (NOT NULL)
     299                 :            :  * @name: name of profile (NOT NULL)
     300                 :            :  * @len: length of @name substring to match
     301                 :            :  *
     302                 :            :  * Requires: rcu_read_lock be held
     303                 :            :  *
     304                 :            :  * Returns: unrefcounted profile ptr, or NULL if not found
     305                 :            :  */
     306                 :            : static struct aa_profile *__strn_find_child(struct list_head *head,
     307                 :            :                                             const char *name, int len)
     308                 :            : {
     309                 :          0 :         return (struct aa_profile *)__policy_strn_find(head, name, len);
     310                 :            : }
     311                 :            : 
     312                 :            : /**
     313                 :            :  * __find_child - find a profile on @head list with a name matching @name
     314                 :            :  * @head: list to search  (NOT NULL)
     315                 :            :  * @name: name of profile (NOT NULL)
     316                 :            :  *
     317                 :            :  * Requires: rcu_read_lock be held
     318                 :            :  *
     319                 :            :  * Returns: unrefcounted profile ptr, or NULL if not found
     320                 :            :  */
     321                 :          0 : static struct aa_profile *__find_child(struct list_head *head, const char *name)
     322                 :            : {
     323                 :          0 :         return __strn_find_child(head, name, strlen(name));
     324                 :            : }
     325                 :            : 
     326                 :            : /**
     327                 :            :  * aa_find_child - find a profile by @name in @parent
     328                 :            :  * @parent: profile to search  (NOT NULL)
     329                 :            :  * @name: profile name to search for  (NOT NULL)
     330                 :            :  *
     331                 :            :  * Returns: a refcounted profile or NULL if not found
     332                 :            :  */
     333                 :          0 : struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
     334                 :            : {
     335                 :            :         struct aa_profile *profile;
     336                 :            : 
     337                 :            :         rcu_read_lock();
     338                 :            :         do {
     339                 :          0 :                 profile = __find_child(&parent->base.profiles, name);
     340   [ #  #  #  # ]:          0 :         } while (profile && !aa_get_profile_not0(profile));
     341                 :            :         rcu_read_unlock();
     342                 :            : 
     343                 :            :         /* refcount released by caller */
     344                 :          0 :         return profile;
     345                 :            : }
     346                 :            : 
     347                 :            : /**
     348                 :            :  * __lookup_parent - lookup the parent of a profile of name @hname
     349                 :            :  * @ns: namespace to lookup profile in  (NOT NULL)
     350                 :            :  * @hname: hierarchical profile name to find parent of  (NOT NULL)
     351                 :            :  *
     352                 :            :  * Lookups up the parent of a fully qualified profile name, the profile
     353                 :            :  * that matches hname does not need to exist, in general this
     354                 :            :  * is used to load a new profile.
     355                 :            :  *
     356                 :            :  * Requires: rcu_read_lock be held
     357                 :            :  *
     358                 :            :  * Returns: unrefcounted policy or NULL if not found
     359                 :            :  */
     360                 :          0 : static struct aa_policy *__lookup_parent(struct aa_ns *ns,
     361                 :            :                                          const char *hname)
     362                 :            : {
     363                 :            :         struct aa_policy *policy;
     364                 :            :         struct aa_profile *profile = NULL;
     365                 :            :         char *split;
     366                 :            : 
     367                 :          0 :         policy = &ns->base;
     368                 :            : 
     369         [ #  # ]:          0 :         for (split = strstr(hname, "//"); split;) {
     370                 :          0 :                 profile = __strn_find_child(&policy->profiles, hname,
     371                 :            :                                             split - hname);
     372         [ #  # ]:          0 :                 if (!profile)
     373                 :            :                         return NULL;
     374                 :          0 :                 policy = &profile->base;
     375                 :          0 :                 hname = split + 2;
     376                 :          0 :                 split = strstr(hname, "//");
     377                 :            :         }
     378         [ #  # ]:          0 :         if (!profile)
     379                 :            :                 return &ns->base;
     380                 :          0 :         return &profile->base;
     381                 :            : }
     382                 :            : 
     383                 :            : /**
     384                 :            :  * __lookupn_profile - lookup the profile matching @hname
     385                 :            :  * @base: base list to start looking up profile name from  (NOT NULL)
     386                 :            :  * @hname: hierarchical profile name  (NOT NULL)
     387                 :            :  * @n: length of @hname
     388                 :            :  *
     389                 :            :  * Requires: rcu_read_lock be held
     390                 :            :  *
     391                 :            :  * Returns: unrefcounted profile pointer or NULL if not found
     392                 :            :  *
     393                 :            :  * Do a relative name lookup, recursing through profile tree.
     394                 :            :  */
     395                 :          0 : static struct aa_profile *__lookupn_profile(struct aa_policy *base,
     396                 :            :                                             const char *hname, size_t n)
     397                 :            : {
     398                 :            :         struct aa_profile *profile = NULL;
     399                 :            :         const char *split;
     400                 :            : 
     401         [ #  # ]:          0 :         for (split = strnstr(hname, "//", n); split;
     402                 :          0 :              split = strnstr(hname, "//", n)) {
     403                 :          0 :                 profile = __strn_find_child(&base->profiles, hname,
     404                 :            :                                             split - hname);
     405         [ #  # ]:          0 :                 if (!profile)
     406                 :            :                         return NULL;
     407                 :            : 
     408                 :          0 :                 base = &profile->base;
     409                 :          0 :                 n -= split + 2 - hname;
     410                 :            :                 hname = split + 2;
     411                 :            :         }
     412                 :            : 
     413         [ #  # ]:          0 :         if (n)
     414                 :          0 :                 return __strn_find_child(&base->profiles, hname, n);
     415                 :            :         return NULL;
     416                 :            : }
     417                 :            : 
     418                 :          0 : static struct aa_profile *__lookup_profile(struct aa_policy *base,
     419                 :            :                                            const char *hname)
     420                 :            : {
     421                 :          0 :         return __lookupn_profile(base, hname, strlen(hname));
     422                 :            : }
     423                 :            : 
     424                 :            : /**
     425                 :            :  * aa_lookup_profile - find a profile by its full or partial name
     426                 :            :  * @ns: the namespace to start from (NOT NULL)
     427                 :            :  * @hname: name to do lookup on.  Does not contain namespace prefix (NOT NULL)
     428                 :            :  * @n: size of @hname
     429                 :            :  *
     430                 :            :  * Returns: refcounted profile or NULL if not found
     431                 :            :  */
     432                 :          0 : struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
     433                 :            :                                       size_t n)
     434                 :            : {
     435                 :            :         struct aa_profile *profile;
     436                 :            : 
     437                 :            :         rcu_read_lock();
     438                 :            :         do {
     439                 :          0 :                 profile = __lookupn_profile(&ns->base, hname, n);
     440   [ #  #  #  # ]:          0 :         } while (profile && !aa_get_profile_not0(profile));
     441                 :            :         rcu_read_unlock();
     442                 :            : 
     443                 :            :         /* the unconfined profile is not in the regular profile list */
     444   [ #  #  #  # ]:          0 :         if (!profile && strncmp(hname, "unconfined", n) == 0)
     445                 :          0 :                 profile = aa_get_newest_profile(ns->unconfined);
     446                 :            : 
     447                 :            :         /* refcount released by caller */
     448                 :          0 :         return profile;
     449                 :            : }
     450                 :            : 
     451                 :          0 : struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *hname)
     452                 :            : {
     453                 :          0 :         return aa_lookupn_profile(ns, hname, strlen(hname));
     454                 :            : }
     455                 :            : 
     456                 :          0 : struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
     457                 :            :                                         const char *fqname, size_t n)
     458                 :            : {
     459                 :            :         struct aa_profile *profile;
     460                 :            :         struct aa_ns *ns;
     461                 :            :         const char *name, *ns_name;
     462                 :            :         size_t ns_len;
     463                 :            : 
     464                 :          0 :         name = aa_splitn_fqname(fqname, n, &ns_name, &ns_len);
     465         [ #  # ]:          0 :         if (ns_name) {
     466                 :          0 :                 ns = aa_lookupn_ns(labels_ns(base), ns_name, ns_len);
     467         [ #  # ]:          0 :                 if (!ns)
     468                 :            :                         return NULL;
     469                 :            :         } else
     470                 :          0 :                 ns = aa_get_ns(labels_ns(base));
     471                 :            : 
     472         [ #  # ]:          0 :         if (name)
     473                 :          0 :                 profile = aa_lookupn_profile(ns, name, n - (name - fqname));
     474         [ #  # ]:          0 :         else if (ns)
     475                 :            :                 /* default profile for ns, currently unconfined */
     476                 :          0 :                 profile = aa_get_newest_profile(ns->unconfined);
     477                 :            :         else
     478                 :            :                 profile = NULL;
     479                 :          0 :         aa_put_ns(ns);
     480                 :            : 
     481                 :          0 :         return profile;
     482                 :            : }
     483                 :            : 
     484                 :            : /**
     485                 :            :  * aa_new_null_profile - create or find a null-X learning profile
     486                 :            :  * @parent: profile that caused this profile to be created (NOT NULL)
     487                 :            :  * @hat: true if the null- learning profile is a hat
     488                 :            :  * @base: name to base the null profile off of
     489                 :            :  * @gfp: type of allocation
     490                 :            :  *
     491                 :            :  * Find/Create a null- complain mode profile used in learning mode.  The
     492                 :            :  * name of the profile is unique and follows the format of parent//null-XXX.
     493                 :            :  * where XXX is based on the @name or if that fails or is not supplied
     494                 :            :  * a unique number
     495                 :            :  *
     496                 :            :  * null profiles are added to the profile list but the list does not
     497                 :            :  * hold a count on them so that they are automatically released when
     498                 :            :  * not in use.
     499                 :            :  *
     500                 :            :  * Returns: new refcounted profile else NULL on failure
     501                 :            :  */
     502                 :          0 : struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
     503                 :            :                                        const char *base, gfp_t gfp)
     504                 :            : {
     505                 :            :         struct aa_profile *p, *profile;
     506                 :            :         const char *bname;
     507                 :            :         char *name = NULL;
     508                 :            : 
     509                 :            :         AA_BUG(!parent);
     510                 :            : 
     511         [ #  # ]:          0 :         if (base) {
     512                 :          0 :                 name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base),
     513                 :            :                                gfp);
     514         [ #  # ]:          0 :                 if (name) {
     515                 :          0 :                         sprintf(name, "%s//null-%s", parent->base.hname, base);
     516                 :          0 :                         goto name;
     517                 :            :                 }
     518                 :            :                 /* fall through to try shorter uniq */
     519                 :            :         }
     520                 :            : 
     521                 :          0 :         name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp);
     522         [ #  # ]:          0 :         if (!name)
     523                 :            :                 return NULL;
     524                 :          0 :         sprintf(name, "%s//null-%x", parent->base.hname,
     525                 :          0 :                 atomic_inc_return(&parent->ns->uniq_null));
     526                 :            : 
     527                 :            : name:
     528                 :            :         /* lookup to see if this is a dup creation */
     529                 :          0 :         bname = basename(name);
     530                 :          0 :         profile = aa_find_child(parent, bname);
     531         [ #  # ]:          0 :         if (profile)
     532                 :            :                 goto out;
     533                 :            : 
     534                 :          0 :         profile = aa_alloc_profile(name, NULL, gfp);
     535         [ #  # ]:          0 :         if (!profile)
     536                 :            :                 goto fail;
     537                 :            : 
     538                 :          0 :         profile->mode = APPARMOR_COMPLAIN;
     539                 :          0 :         profile->label.flags |= FLAG_NULL;
     540         [ #  # ]:          0 :         if (hat)
     541                 :          0 :                 profile->label.flags |= FLAG_HAT;
     542                 :          0 :         profile->path_flags = parent->path_flags;
     543                 :            : 
     544                 :            :         /* released on free_profile */
     545                 :          0 :         rcu_assign_pointer(profile->parent, aa_get_profile(parent));
     546                 :          0 :         profile->ns = aa_get_ns(parent->ns);
     547                 :          0 :         profile->file.dfa = aa_get_dfa(nulldfa);
     548                 :          0 :         profile->policy.dfa = aa_get_dfa(nulldfa);
     549                 :            : 
     550                 :          0 :         mutex_lock_nested(&profile->ns->lock, profile->ns->level);
     551                 :          0 :         p = __find_child(&parent->base.profiles, bname);
     552         [ #  # ]:          0 :         if (p) {
     553                 :          0 :                 aa_free_profile(profile);
     554                 :            :                 profile = aa_get_profile(p);
     555                 :            :         } else {
     556                 :          0 :                 __add_profile(&parent->base.profiles, profile);
     557                 :            :         }
     558                 :          0 :         mutex_unlock(&profile->ns->lock);
     559                 :            : 
     560                 :            :         /* refcount released by caller */
     561                 :            : out:
     562                 :          0 :         kfree(name);
     563                 :            : 
     564                 :          0 :         return profile;
     565                 :            : 
     566                 :            : fail:
     567                 :          0 :         kfree(name);
     568                 :          0 :         aa_free_profile(profile);
     569                 :          0 :         return NULL;
     570                 :            : }
     571                 :            : 
     572                 :            : /**
     573                 :            :  * replacement_allowed - test to see if replacement is allowed
     574                 :            :  * @profile: profile to test if it can be replaced  (MAYBE NULL)
     575                 :            :  * @noreplace: true if replacement shouldn't be allowed but addition is okay
     576                 :            :  * @info: Returns - info about why replacement failed (NOT NULL)
     577                 :            :  *
     578                 :            :  * Returns: %0 if replacement allowed else error code
     579                 :            :  */
     580                 :            : static int replacement_allowed(struct aa_profile *profile, int noreplace,
     581                 :            :                                const char **info)
     582                 :            : {
     583         [ #  # ]:          0 :         if (profile) {
     584         [ #  # ]:          0 :                 if (profile->label.flags & FLAG_IMMUTIBLE) {
     585                 :          0 :                         *info = "cannot replace immutible profile";
     586                 :            :                         return -EPERM;
     587         [ #  # ]:          0 :                 } else if (noreplace) {
     588                 :          0 :                         *info = "profile already exists";
     589                 :            :                         return -EEXIST;
     590                 :            :                 }
     591                 :            :         }
     592                 :            :         return 0;
     593                 :            : }
     594                 :            : 
     595                 :            : /* audit callback for net specific fields */
     596                 :          0 : static void audit_cb(struct audit_buffer *ab, void *va)
     597                 :            : {
     598                 :            :         struct common_audit_data *sa = va;
     599                 :            : 
     600         [ #  # ]:          0 :         if (aad(sa)->iface.ns) {
     601                 :          0 :                 audit_log_format(ab, " ns=");
     602                 :          0 :                 audit_log_untrustedstring(ab, aad(sa)->iface.ns);
     603                 :            :         }
     604                 :          0 : }
     605                 :            : 
     606                 :            : /**
     607                 :            :  * audit_policy - Do auditing of policy changes
     608                 :            :  * @label: label to check if it can manage policy
     609                 :            :  * @op: policy operation being performed
     610                 :            :  * @ns_name: name of namespace being manipulated
     611                 :            :  * @name: name of profile being manipulated (NOT NULL)
     612                 :            :  * @info: any extra information to be audited (MAYBE NULL)
     613                 :            :  * @error: error code
     614                 :            :  *
     615                 :            :  * Returns: the error to be returned after audit is done
     616                 :            :  */
     617                 :          0 : static int audit_policy(struct aa_label *label, const char *op,
     618                 :            :                         const char *ns_name, const char *name,
     619                 :            :                         const char *info, int error)
     620                 :            : {
     621                 :          0 :         DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
     622                 :            : 
     623                 :          0 :         aad(&sa)->iface.ns = ns_name;
     624                 :          0 :         aad(&sa)->name = name;
     625                 :          0 :         aad(&sa)->info = info;
     626                 :          0 :         aad(&sa)->error = error;
     627                 :          0 :         aad(&sa)->label = label;
     628                 :            : 
     629                 :          0 :         aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, audit_cb);
     630                 :            : 
     631                 :          0 :         return error;
     632                 :            : }
     633                 :            : 
     634                 :            : /**
     635                 :            :  * policy_view_capable - check if viewing policy in at @ns is allowed
     636                 :            :  * ns: namespace being viewed by current task (may be NULL)
     637                 :            :  * Returns: true if viewing policy is allowed
     638                 :            :  *
     639                 :            :  * If @ns is NULL then the namespace being viewed is assumed to be the
     640                 :            :  * tasks current namespace.
     641                 :            :  */
     642                 :          0 : bool policy_view_capable(struct aa_ns *ns)
     643                 :            : {
     644                 :          0 :         struct user_namespace *user_ns = current_user_ns();
     645                 :          0 :         struct aa_ns *view_ns = aa_get_current_ns();
     646   [ #  #  #  # ]:          0 :         bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) ||
     647                 :          0 :                                in_egroup_p(make_kgid(user_ns, 0));
     648                 :            :         bool response = false;
     649         [ #  # ]:          0 :         if (!ns)
     650                 :            :                 ns = view_ns;
     651                 :            : 
     652   [ #  #  #  #  :          0 :         if (root_in_user_ns && aa_ns_visible(view_ns, ns, true) &&
                   #  # ]
     653         [ #  # ]:          0 :             (user_ns == &init_user_ns ||
     654         [ #  # ]:          0 :              (unprivileged_userns_apparmor_policy != 0 &&
     655                 :          0 :               user_ns->level == view_ns->level)))
     656                 :            :                 response = true;
     657                 :          0 :         aa_put_ns(view_ns);
     658                 :            : 
     659                 :          0 :         return response;
     660                 :            : }
     661                 :            : 
     662                 :          0 : bool policy_admin_capable(struct aa_ns *ns)
     663                 :            : {
     664                 :          0 :         struct user_namespace *user_ns = current_user_ns();
     665                 :          0 :         bool capable = ns_capable(user_ns, CAP_MAC_ADMIN);
     666                 :            : 
     667                 :            :         AA_DEBUG("cap_mac_admin? %d\n", capable);
     668                 :            :         AA_DEBUG("policy locked? %d\n", aa_g_lock_policy);
     669                 :            : 
     670   [ #  #  #  #  :          0 :         return policy_view_capable(ns) && capable && !aa_g_lock_policy;
                   #  # ]
     671                 :            : }
     672                 :            : 
     673                 :            : /**
     674                 :            :  * aa_may_manage_policy - can the current task manage policy
     675                 :            :  * @label: label to check if it can manage policy
     676                 :            :  * @op: the policy manipulation operation being done
     677                 :            :  *
     678                 :            :  * Returns: 0 if the task is allowed to manipulate policy else error
     679                 :            :  */
     680                 :          0 : int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask)
     681                 :            : {
     682                 :            :         const char *op;
     683                 :            : 
     684         [ #  # ]:          0 :         if (mask & AA_MAY_REMOVE_POLICY)
     685                 :            :                 op = OP_PROF_RM;
     686         [ #  # ]:          0 :         else if (mask & AA_MAY_REPLACE_POLICY)
     687                 :            :                 op = OP_PROF_REPL;
     688                 :            :         else
     689                 :            :                 op = OP_PROF_LOAD;
     690                 :            : 
     691                 :            :         /* check if loading policy is locked out */
     692         [ #  # ]:          0 :         if (aa_g_lock_policy)
     693                 :          0 :                 return audit_policy(label, op, NULL, NULL, "policy_locked",
     694                 :            :                                     -EACCES);
     695                 :            : 
     696         [ #  # ]:          0 :         if (!policy_admin_capable(ns))
     697                 :          0 :                 return audit_policy(label, op, NULL, NULL, "not policy admin",
     698                 :            :                                     -EACCES);
     699                 :            : 
     700                 :            :         /* TODO: add fine grained mediation of policy loads */
     701                 :            :         return 0;
     702                 :            : }
     703                 :            : 
     704                 :          0 : static struct aa_profile *__list_lookup_parent(struct list_head *lh,
     705                 :            :                                                struct aa_profile *profile)
     706                 :            : {
     707                 :          0 :         const char *base = basename(profile->base.hname);
     708                 :          0 :         long len = base - profile->base.hname;
     709                 :            :         struct aa_load_ent *ent;
     710                 :            : 
     711                 :            :         /* parent won't have trailing // so remove from len */
     712         [ #  # ]:          0 :         if (len <= 2)
     713                 :            :                 return NULL;
     714                 :          0 :         len -= 2;
     715                 :            : 
     716         [ #  # ]:          0 :         list_for_each_entry(ent, lh, list) {
     717         [ #  # ]:          0 :                 if (ent->new == profile)
     718                 :          0 :                         continue;
     719         [ #  # ]:          0 :                 if (strncmp(ent->new->base.hname, profile->base.hname, len) ==
     720         [ #  # ]:          0 :                     0 && ent->new->base.hname[len] == 0)
     721                 :          0 :                         return ent->new;
     722                 :            :         }
     723                 :            : 
     724                 :            :         return NULL;
     725                 :            : }
     726                 :            : 
     727                 :            : /**
     728                 :            :  * __replace_profile - replace @old with @new on a list
     729                 :            :  * @old: profile to be replaced  (NOT NULL)
     730                 :            :  * @new: profile to replace @old with  (NOT NULL)
     731                 :            :  * @share_proxy: transfer @old->proxy to @new
     732                 :            :  *
     733                 :            :  * Will duplicate and refcount elements that @new inherits from @old
     734                 :            :  * and will inherit @old children.
     735                 :            :  *
     736                 :            :  * refcount @new for list, put @old list refcount
     737                 :            :  *
     738                 :            :  * Requires: namespace list lock be held, or list not be shared
     739                 :            :  */
     740                 :          0 : static void __replace_profile(struct aa_profile *old, struct aa_profile *new)
     741                 :            : {
     742                 :            :         struct aa_profile *child, *tmp;
     743                 :            : 
     744         [ #  # ]:          0 :         if (!list_empty(&old->base.profiles)) {
     745                 :          0 :                 LIST_HEAD(lh);
     746                 :            :                 list_splice_init_rcu(&old->base.profiles, &lh, synchronize_rcu);
     747                 :            : 
     748         [ #  # ]:          0 :                 list_for_each_entry_safe(child, tmp, &lh, base.list) {
     749                 :            :                         struct aa_profile *p;
     750                 :            : 
     751                 :            :                         list_del_init(&child->base.list);
     752                 :          0 :                         p = __find_child(&new->base.profiles, child->base.name);
     753         [ #  # ]:          0 :                         if (p) {
     754                 :            :                                 /* @p replaces @child  */
     755                 :          0 :                                 __replace_profile(child, p);
     756                 :          0 :                                 continue;
     757                 :            :                         }
     758                 :            : 
     759                 :            :                         /* inherit @child and its children */
     760                 :            :                         /* TODO: update hname of inherited children */
     761                 :            :                         /* list refcount transferred to @new */
     762                 :            :                         p = aa_deref_parent(child);
     763                 :          0 :                         rcu_assign_pointer(child->parent, aa_get_profile(new));
     764                 :            :                         list_add_rcu(&child->base.list, &new->base.profiles);
     765                 :            :                         aa_put_profile(p);
     766                 :            :                 }
     767                 :            :         }
     768                 :            : 
     769         [ #  # ]:          0 :         if (!rcu_access_pointer(new->parent)) {
     770                 :            :                 struct aa_profile *parent = aa_deref_parent(old);
     771                 :          0 :                 rcu_assign_pointer(new->parent, aa_get_profile(parent));
     772                 :            :         }
     773                 :          0 :         aa_label_replace(&old->label, &new->label);
     774                 :            :         /* migrate dents must come after label replacement b/c update */
     775                 :          0 :         __aafs_profile_migrate_dents(old, new);
     776                 :            : 
     777         [ #  # ]:          0 :         if (list_empty(&new->base.list)) {
     778                 :            :                 /* new is not on a list already */
     779                 :            :                 list_replace_rcu(&old->base.list, &new->base.list);
     780                 :            :                 aa_get_profile(new);
     781                 :            :                 aa_put_profile(old);
     782                 :            :         } else
     783                 :          0 :                 __list_remove_profile(old);
     784                 :          0 : }
     785                 :            : 
     786                 :            : /**
     787                 :            :  * __lookup_replace - lookup replacement information for a profile
     788                 :            :  * @ns - namespace the lookup occurs in
     789                 :            :  * @hname - name of profile to lookup
     790                 :            :  * @noreplace - true if not replacing an existing profile
     791                 :            :  * @p - Returns: profile to be replaced
     792                 :            :  * @info - Returns: info string on why lookup failed
     793                 :            :  *
     794                 :            :  * Returns: profile to replace (no ref) on success else ptr error
     795                 :            :  */
     796                 :          0 : static int __lookup_replace(struct aa_ns *ns, const char *hname,
     797                 :            :                             bool noreplace, struct aa_profile **p,
     798                 :            :                             const char **info)
     799                 :            : {
     800                 :          0 :         *p = aa_get_profile(__lookup_profile(&ns->base, hname));
     801         [ #  # ]:          0 :         if (*p) {
     802                 :            :                 int error = replacement_allowed(*p, noreplace, info);
     803         [ #  # ]:          0 :                 if (error) {
     804                 :          0 :                         *info = "profile can not be replaced";
     805                 :          0 :                         return error;
     806                 :            :                 }
     807                 :            :         }
     808                 :            : 
     809                 :            :         return 0;
     810                 :            : }
     811                 :            : 
     812                 :          0 : static void share_name(struct aa_profile *old, struct aa_profile *new)
     813                 :            : {
     814                 :          0 :         aa_put_str(new->base.hname);
     815                 :          0 :         aa_get_str(old->base.hname);
     816                 :          0 :         new->base.hname = old->base.hname;
     817                 :          0 :         new->base.name = old->base.name;
     818                 :          0 :         new->label.hname = old->label.hname;
     819                 :          0 : }
     820                 :            : 
     821                 :            : /* Update to newest version of parent after previous replacements
     822                 :            :  * Returns: unrefcount newest version of parent
     823                 :            :  */
     824                 :          0 : static struct aa_profile *update_to_newest_parent(struct aa_profile *new)
     825                 :            : {
     826                 :            :         struct aa_profile *parent, *newest;
     827                 :            : 
     828                 :          0 :         parent = rcu_dereference_protected(new->parent,
     829                 :            :                                            mutex_is_locked(&new->ns->lock));
     830                 :          0 :         newest = aa_get_newest_profile(parent);
     831                 :            : 
     832                 :            :         /* parent replaced in this atomic set? */
     833         [ #  # ]:          0 :         if (newest != parent) {
     834                 :            :                 aa_put_profile(parent);
     835                 :          0 :                 rcu_assign_pointer(new->parent, newest);
     836                 :            :         } else
     837                 :            :                 aa_put_profile(newest);
     838                 :            : 
     839                 :          0 :         return newest;
     840                 :            : }
     841                 :            : 
     842                 :            : /**
     843                 :            :  * aa_replace_profiles - replace profile(s) on the profile list
     844                 :            :  * @policy_ns: namespace load is occurring on
     845                 :            :  * @label: label that is attempting to load/replace policy
     846                 :            :  * @mask: permission mask
     847                 :            :  * @udata: serialized data stream  (NOT NULL)
     848                 :            :  *
     849                 :            :  * unpack and replace a profile on the profile list and uses of that profile
     850                 :            :  * by any task creds via invalidating the old version of the profile, which
     851                 :            :  * tasks will notice to update their own cred.  If the profile does not exist
     852                 :            :  * on the profile list it is added.
     853                 :            :  *
     854                 :            :  * Returns: size of data consumed else error code on failure.
     855                 :            :  */
     856                 :          0 : ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label,
     857                 :            :                             u32 mask, struct aa_loaddata *udata)
     858                 :            : {
     859                 :          0 :         const char *ns_name, *info = NULL;
     860                 :            :         struct aa_ns *ns = NULL;
     861                 :            :         struct aa_load_ent *ent, *tmp;
     862                 :            :         struct aa_loaddata *rawdata_ent;
     863                 :            :         const char *op;
     864                 :            :         ssize_t count, error;
     865                 :          0 :         LIST_HEAD(lh);
     866                 :            : 
     867         [ #  # ]:          0 :         op = mask & AA_MAY_REPLACE_POLICY ? OP_PROF_REPL : OP_PROF_LOAD;
     868                 :            :         aa_get_loaddata(udata);
     869                 :            :         /* released below */
     870                 :          0 :         error = aa_unpack(udata, &lh, &ns_name);
     871         [ #  # ]:          0 :         if (error)
     872                 :            :                 goto out;
     873                 :            : 
     874                 :            :         /* ensure that profiles are all for the same ns
     875                 :            :          * TODO: update locking to remove this constaint. All profiles in
     876                 :            :          *       the load set must succeed as a set or the load will
     877                 :            :          *       fail. Sort ent list and take ns locks in hierarchy order
     878                 :            :          */
     879                 :            :         count = 0;
     880         [ #  # ]:          0 :         list_for_each_entry(ent, &lh, list) {
     881         [ #  # ]:          0 :                 if (ns_name) {
     882   [ #  #  #  # ]:          0 :                         if (ent->ns_name &&
     883                 :          0 :                             strcmp(ent->ns_name, ns_name) != 0) {
     884                 :          0 :                                 info = "policy load has mixed namespaces";
     885                 :            :                                 error = -EACCES;
     886                 :          0 :                                 goto fail;
     887                 :            :                         }
     888         [ #  # ]:          0 :                 } else if (ent->ns_name) {
     889         [ #  # ]:          0 :                         if (count) {
     890                 :          0 :                                 info = "policy load has mixed namespaces";
     891                 :            :                                 error = -EACCES;
     892                 :          0 :                                 goto fail;
     893                 :            :                         }
     894                 :          0 :                         ns_name = ent->ns_name;
     895                 :            :                 } else
     896                 :          0 :                         count++;
     897                 :            :         }
     898         [ #  # ]:          0 :         if (ns_name) {
     899         [ #  # ]:          0 :                 ns = aa_prepare_ns(policy_ns ? policy_ns : labels_ns(label),
     900                 :            :                                    ns_name);
     901         [ #  # ]:          0 :                 if (IS_ERR(ns)) {
     902                 :            :                         op = OP_PROF_LOAD;
     903                 :          0 :                         info = "failed to prepare namespace";
     904                 :            :                         error = PTR_ERR(ns);
     905                 :            :                         ns = NULL;
     906                 :            :                         ent = NULL;
     907                 :          0 :                         goto fail;
     908                 :            :                 }
     909                 :            :         } else
     910         [ #  # ]:          0 :                 ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(label));
     911                 :            : 
     912                 :          0 :         mutex_lock_nested(&ns->lock, ns->level);
     913                 :            :         /* check for duplicate rawdata blobs: space and file dedup */
     914         [ #  # ]:          0 :         list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) {
     915         [ #  # ]:          0 :                 if (aa_rawdata_eq(rawdata_ent, udata)) {
     916                 :            :                         struct aa_loaddata *tmp;
     917                 :            : 
     918                 :            :                         tmp = __aa_get_loaddata(rawdata_ent);
     919                 :            :                         /* check we didn't fail the race */
     920         [ #  # ]:          0 :                         if (tmp) {
     921                 :            :                                 aa_put_loaddata(udata);
     922                 :          0 :                                 udata = tmp;
     923                 :          0 :                                 break;
     924                 :            :                         }
     925                 :            :                 }
     926                 :            :         }
     927                 :            :         /* setup parent and ns info */
     928         [ #  # ]:          0 :         list_for_each_entry(ent, &lh, list) {
     929                 :            :                 struct aa_policy *policy;
     930                 :            : 
     931                 :          0 :                 ent->new->rawdata = aa_get_loaddata(udata);
     932                 :          0 :                 error = __lookup_replace(ns, ent->new->base.hname,
     933                 :            :                                          !(mask & AA_MAY_REPLACE_POLICY),
     934                 :            :                                          &ent->old, &info);
     935         [ #  # ]:          0 :                 if (error)
     936                 :            :                         goto fail_lock;
     937                 :            : 
     938         [ #  # ]:          0 :                 if (ent->new->rename) {
     939                 :          0 :                         error = __lookup_replace(ns, ent->new->rename,
     940                 :            :                                                 !(mask & AA_MAY_REPLACE_POLICY),
     941                 :            :                                                 &ent->rename, &info);
     942         [ #  # ]:          0 :                         if (error)
     943                 :            :                                 goto fail_lock;
     944                 :            :                 }
     945                 :            : 
     946                 :            :                 /* released when @new is freed */
     947                 :          0 :                 ent->new->ns = aa_get_ns(ns);
     948                 :            : 
     949   [ #  #  #  # ]:          0 :                 if (ent->old || ent->rename)
     950                 :          0 :                         continue;
     951                 :            : 
     952                 :            :                 /* no ref on policy only use inside lock */
     953                 :          0 :                 policy = __lookup_parent(ns, ent->new->base.hname);
     954         [ #  # ]:          0 :                 if (!policy) {
     955                 :            :                         struct aa_profile *p;
     956                 :          0 :                         p = __list_lookup_parent(&lh, ent->new);
     957         [ #  # ]:          0 :                         if (!p) {
     958                 :            :                                 error = -ENOENT;
     959                 :          0 :                                 info = "parent does not exist";
     960                 :          0 :                                 goto fail_lock;
     961                 :            :                         }
     962                 :          0 :                         rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
     963         [ #  # ]:          0 :                 } else if (policy != &ns->base) {
     964                 :            :                         /* released on profile replacement or free_profile */
     965                 :            :                         struct aa_profile *p = (struct aa_profile *) policy;
     966                 :          0 :                         rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
     967                 :            :                 }
     968                 :            :         }
     969                 :            : 
     970                 :            :         /* create new fs entries for introspection if needed */
     971         [ #  # ]:          0 :         if (!udata->dents[AAFS_LOADDATA_DIR]) {
     972                 :          0 :                 error = __aa_fs_create_rawdata(ns, udata);
     973         [ #  # ]:          0 :                 if (error) {
     974                 :          0 :                         info = "failed to create raw_data dir and files";
     975                 :            :                         ent = NULL;
     976                 :          0 :                         goto fail_lock;
     977                 :            :                 }
     978                 :            :         }
     979         [ #  # ]:          0 :         list_for_each_entry(ent, &lh, list) {
     980         [ #  # ]:          0 :                 if (!ent->old) {
     981                 :            :                         struct dentry *parent;
     982         [ #  # ]:          0 :                         if (rcu_access_pointer(ent->new->parent)) {
     983                 :            :                                 struct aa_profile *p;
     984                 :            :                                 p = aa_deref_parent(ent->new);
     985                 :          0 :                                 parent = prof_child_dir(p);
     986                 :            :                         } else
     987                 :          0 :                                 parent = ns_subprofs_dir(ent->new->ns);
     988                 :          0 :                         error = __aafs_profile_mkdir(ent->new, parent);
     989                 :            :                 }
     990                 :            : 
     991         [ #  # ]:          0 :                 if (error) {
     992                 :          0 :                         info = "failed to create";
     993                 :          0 :                         goto fail_lock;
     994                 :            :                 }
     995                 :            :         }
     996                 :            : 
     997                 :            :         /* Done with checks that may fail - do actual replacement */
     998                 :          0 :         __aa_bump_ns_revision(ns);
     999                 :          0 :         __aa_loaddata_update(udata, ns->revision);
    1000         [ #  # ]:          0 :         list_for_each_entry_safe(ent, tmp, &lh, list) {
    1001                 :            :                 list_del_init(&ent->list);
    1002   [ #  #  #  # ]:          0 :                 op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
    1003                 :            : 
    1004   [ #  #  #  # ]:          0 :                 if (ent->old && ent->old->rawdata == ent->new->rawdata) {
    1005                 :            :                         /* dedup actual profile replacement */
    1006                 :          0 :                         audit_policy(label, op, ns_name, ent->new->base.hname,
    1007                 :            :                                      "same as current profile, skipping",
    1008                 :            :                                      error);
    1009                 :            :                         /* break refcount cycle with proxy. */
    1010                 :          0 :                         aa_put_proxy(ent->new->label.proxy);
    1011                 :          0 :                         ent->new->label.proxy = NULL;
    1012                 :          0 :                         goto skip;
    1013                 :            :                 }
    1014                 :            : 
    1015                 :            :                 /*
    1016                 :            :                  * TODO: finer dedup based on profile range in data. Load set
    1017                 :            :                  * can differ but profile may remain unchanged
    1018                 :            :                  */
    1019                 :          0 :                 audit_policy(label, op, ns_name, ent->new->base.hname, NULL,
    1020                 :            :                              error);
    1021                 :            : 
    1022         [ #  # ]:          0 :                 if (ent->old) {
    1023                 :          0 :                         share_name(ent->old, ent->new);
    1024                 :          0 :                         __replace_profile(ent->old, ent->new);
    1025                 :            :                 } else {
    1026                 :            :                         struct list_head *lh;
    1027                 :            : 
    1028         [ #  # ]:          0 :                         if (rcu_access_pointer(ent->new->parent)) {
    1029                 :            :                                 struct aa_profile *parent;
    1030                 :            : 
    1031                 :          0 :                                 parent = update_to_newest_parent(ent->new);
    1032                 :          0 :                                 lh = &parent->base.profiles;
    1033                 :            :                         } else
    1034                 :          0 :                                 lh = &ns->base.profiles;
    1035                 :          0 :                         __add_profile(lh, ent->new);
    1036                 :            :                 }
    1037                 :            :         skip:
    1038                 :          0 :                 aa_load_ent_free(ent);
    1039                 :            :         }
    1040                 :          0 :         __aa_labelset_update_subtree(ns);
    1041                 :          0 :         mutex_unlock(&ns->lock);
    1042                 :            : 
    1043                 :            : out:
    1044                 :          0 :         aa_put_ns(ns);
    1045                 :            :         aa_put_loaddata(udata);
    1046                 :            : 
    1047         [ #  # ]:          0 :         if (error)
    1048                 :            :                 return error;
    1049                 :          0 :         return udata->size;
    1050                 :            : 
    1051                 :            : fail_lock:
    1052                 :          0 :         mutex_unlock(&ns->lock);
    1053                 :            : 
    1054                 :            :         /* audit cause of failure */
    1055   [ #  #  #  # ]:          0 :         op = (ent && !ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
    1056                 :            : fail:
    1057         [ #  # ]:          0 :           audit_policy(label, op, ns_name, ent ? ent->new->base.hname : NULL,
    1058                 :            :                        info, error);
    1059                 :            :         /* audit status that rest of profiles in the atomic set failed too */
    1060                 :          0 :         info = "valid profile in failed atomic policy load";
    1061         [ #  # ]:          0 :         list_for_each_entry(tmp, &lh, list) {
    1062         [ #  # ]:          0 :                 if (tmp == ent) {
    1063                 :          0 :                         info = "unchecked profile in failed atomic policy load";
    1064                 :            :                         /* skip entry that caused failure */
    1065                 :          0 :                         continue;
    1066                 :            :                 }
    1067         [ #  # ]:          0 :                 op = (!tmp->old) ? OP_PROF_LOAD : OP_PROF_REPL;
    1068                 :          0 :                 audit_policy(label, op, ns_name, tmp->new->base.hname, info,
    1069                 :            :                              error);
    1070                 :            :         }
    1071         [ #  # ]:          0 :         list_for_each_entry_safe(ent, tmp, &lh, list) {
    1072                 :            :                 list_del_init(&ent->list);
    1073                 :          0 :                 aa_load_ent_free(ent);
    1074                 :            :         }
    1075                 :            : 
    1076                 :            :         goto out;
    1077                 :            : }
    1078                 :            : 
    1079                 :            : /**
    1080                 :            :  * aa_remove_profiles - remove profile(s) from the system
    1081                 :            :  * @policy_ns: namespace the remove is being done from
    1082                 :            :  * @subj: label attempting to remove policy
    1083                 :            :  * @fqname: name of the profile or namespace to remove  (NOT NULL)
    1084                 :            :  * @size: size of the name
    1085                 :            :  *
    1086                 :            :  * Remove a profile or sub namespace from the current namespace, so that
    1087                 :            :  * they can not be found anymore and mark them as replaced by unconfined
    1088                 :            :  *
    1089                 :            :  * NOTE: removing confinement does not restore rlimits to preconfinement values
    1090                 :            :  *
    1091                 :            :  * Returns: size of data consume else error code if fails
    1092                 :            :  */
    1093                 :          0 : ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj,
    1094                 :            :                            char *fqname, size_t size)
    1095                 :            : {
    1096                 :            :         struct aa_ns *ns = NULL;
    1097                 :            :         struct aa_profile *profile = NULL;
    1098                 :            :         const char *name = fqname, *info = NULL;
    1099                 :          0 :         const char *ns_name = NULL;
    1100                 :            :         ssize_t error = 0;
    1101                 :            : 
    1102         [ #  # ]:          0 :         if (*fqname == 0) {
    1103                 :            :                 info = "no profile specified";
    1104                 :            :                 error = -ENOENT;
    1105                 :            :                 goto fail;
    1106                 :            :         }
    1107                 :            : 
    1108         [ #  # ]:          0 :         if (fqname[0] == ':') {
    1109                 :            :                 size_t ns_len;
    1110                 :            : 
    1111                 :          0 :                 name = aa_splitn_fqname(fqname, size, &ns_name, &ns_len);
    1112                 :            :                 /* released below */
    1113         [ #  # ]:          0 :                 ns = aa_lookupn_ns(policy_ns ? policy_ns : labels_ns(subj),
    1114                 :            :                                    ns_name, ns_len);
    1115         [ #  # ]:          0 :                 if (!ns) {
    1116                 :            :                         info = "namespace does not exist";
    1117                 :            :                         error = -ENOENT;
    1118                 :          0 :                         goto fail;
    1119                 :            :                 }
    1120                 :            :         } else
    1121                 :            :                 /* released below */
    1122         [ #  # ]:          0 :                 ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(subj));
    1123                 :            : 
    1124         [ #  # ]:          0 :         if (!name) {
    1125                 :            :                 /* remove namespace - can only happen if fqname[0] == ':' */
    1126                 :          0 :                 mutex_lock_nested(&ns->parent->lock, ns->level);
    1127                 :          0 :                 __aa_bump_ns_revision(ns);
    1128                 :          0 :                 __aa_remove_ns(ns);
    1129                 :          0 :                 mutex_unlock(&ns->parent->lock);
    1130                 :            :         } else {
    1131                 :            :                 /* remove profile */
    1132                 :          0 :                 mutex_lock_nested(&ns->lock, ns->level);
    1133                 :          0 :                 profile = aa_get_profile(__lookup_profile(&ns->base, name));
    1134         [ #  # ]:          0 :                 if (!profile) {
    1135                 :            :                         error = -ENOENT;
    1136                 :            :                         info = "profile does not exist";
    1137                 :            :                         goto fail_ns_lock;
    1138                 :            :                 }
    1139                 :          0 :                 name = profile->base.hname;
    1140                 :          0 :                 __aa_bump_ns_revision(ns);
    1141                 :          0 :                 __remove_profile(profile);
    1142                 :          0 :                 __aa_labelset_update_subtree(ns);
    1143                 :          0 :                 mutex_unlock(&ns->lock);
    1144                 :            :         }
    1145                 :            : 
    1146                 :            :         /* don't fail removal if audit fails */
    1147                 :          0 :         (void) audit_policy(subj, OP_PROF_RM, ns_name, name, info,
    1148                 :            :                             error);
    1149                 :          0 :         aa_put_ns(ns);
    1150                 :            :         aa_put_profile(profile);
    1151                 :          0 :         return size;
    1152                 :            : 
    1153                 :            : fail_ns_lock:
    1154                 :          0 :         mutex_unlock(&ns->lock);
    1155                 :          0 :         aa_put_ns(ns);
    1156                 :            : 
    1157                 :            : fail:
    1158                 :          0 :         (void) audit_policy(subj, OP_PROF_RM, ns_name, name, info,
    1159                 :            :                             error);
    1160                 :          0 :         return error;
    1161                 :            : }

Generated by: LCOV version 1.14