LCOV - code coverage report
Current view: top level - security/apparmor - policy.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 362 0.6 %
Date: 2014-02-18 Functions: 2 38 5.3 %
Branches: 2 216 0.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * AppArmor security module
       3                 :            :  *
       4                 :            :  * This file contains AppArmor policy manipulation functions
       5                 :            :  *
       6                 :            :  * Copyright (C) 1998-2008 Novell/SUSE
       7                 :            :  * Copyright 2009-2010 Canonical Ltd.
       8                 :            :  *
       9                 :            :  * This program is free software; you can redistribute it and/or
      10                 :            :  * modify it under the terms of the GNU General Public License as
      11                 :            :  * published by the Free Software Foundation, version 2 of the
      12                 :            :  * License.
      13                 :            :  *
      14                 :            :  *
      15                 :            :  * AppArmor policy is based around profiles, which contain the rules a
      16                 :            :  * task is confined by.  Every task in the system has a profile attached
      17                 :            :  * to it determined either by matching "unconfined" tasks against the
      18                 :            :  * visible set of profiles or by following a profiles attachment rules.
      19                 :            :  *
      20                 :            :  * Each profile exists in a profile namespace which is a container of
      21                 :            :  * visible profiles.  Each namespace contains a special "unconfined" profile,
      22                 :            :  * which doesn't enforce any confinement on a task beyond DAC.
      23                 :            :  *
      24                 :            :  * Namespace and profile names can be written together in either
      25                 :            :  * of two syntaxes.
      26                 :            :  *      :namespace:profile - used by kernel interfaces for easy detection
      27                 :            :  *      namespace://profile - used by policy
      28                 :            :  *
      29                 :            :  * Profile names can not start with : or @ or ^ and may not contain \0
      30                 :            :  *
      31                 :            :  * Reserved profile names
      32                 :            :  *      unconfined - special automatically generated unconfined profile
      33                 :            :  *      inherit - special name to indicate profile inheritance
      34                 :            :  *      null-XXXX-YYYY - special automatically generated learning profiles
      35                 :            :  *
      36                 :            :  * Namespace names may not start with / or @ and may not contain \0 or :
      37                 :            :  * Reserved namespace names
      38                 :            :  *      user-XXXX - user defined profiles
      39                 :            :  *
      40                 :            :  * a // in a profile or namespace name indicates a hierarchical name with the
      41                 :            :  * name before the // being the parent and the name after the child.
      42                 :            :  *
      43                 :            :  * Profile and namespace hierarchies serve two different but similar purposes.
      44                 :            :  * The namespace contains the set of visible profiles that are considered
      45                 :            :  * for attachment.  The hierarchy of namespaces allows for virtualizing
      46                 :            :  * the namespace so that for example a chroot can have its own set of profiles
      47                 :            :  * which may define some local user namespaces.
      48                 :            :  * The profile hierarchy severs two distinct purposes,
      49                 :            :  * -  it allows for sub profiles or hats, which allows an application to run
      50                 :            :  *    subprograms under its own profile with different restriction than it
      51                 :            :  *    self, and not have it use the system profile.
      52                 :            :  *    eg. if a mail program starts an editor, the policy might make the
      53                 :            :  *        restrictions tighter on the editor tighter than the mail program,
      54                 :            :  *        and definitely different than general editor restrictions
      55                 :            :  * - it allows for binary hierarchy of profiles, so that execution history
      56                 :            :  *   is preserved.  This feature isn't exploited by AppArmor reference policy
      57                 :            :  *   but is allowed.  NOTE: this is currently suboptimal because profile
      58                 :            :  *   aliasing is not currently implemented so that a profile for each
      59                 :            :  *   level must be defined.
      60                 :            :  *   eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
      61                 :            :  *       from /bin/bash
      62                 :            :  *
      63                 :            :  *   A profile or namespace name that can contain one or more // separators
      64                 :            :  *   is referred to as an hname (hierarchical).
      65                 :            :  *   eg.  /bin/bash//bin/ls
      66                 :            :  *
      67                 :            :  *   An fqname is a name that may contain both namespace and profile hnames.
      68                 :            :  *   eg. :ns:/bin/bash//bin/ls
      69                 :            :  *
      70                 :            :  * NOTES:
      71                 :            :  *   - locking of profile lists is currently fairly coarse.  All profile
      72                 :            :  *     lists within a namespace use the namespace lock.
      73                 :            :  * FIXME: move profile lists to using rcu_lists
      74                 :            :  */
      75                 :            : 
      76                 :            : #include <linux/slab.h>
      77                 :            : #include <linux/spinlock.h>
      78                 :            : #include <linux/string.h>
      79                 :            : 
      80                 :            : #include "include/apparmor.h"
      81                 :            : #include "include/capability.h"
      82                 :            : #include "include/context.h"
      83                 :            : #include "include/file.h"
      84                 :            : #include "include/ipc.h"
      85                 :            : #include "include/match.h"
      86                 :            : #include "include/path.h"
      87                 :            : #include "include/policy.h"
      88                 :            : #include "include/policy_unpack.h"
      89                 :            : #include "include/resource.h"
      90                 :            : 
      91                 :            : 
      92                 :            : /* root profile namespace */
      93                 :            : struct aa_namespace *root_ns;
      94                 :            : 
      95                 :            : const char *const aa_profile_mode_names[] = {
      96                 :            :         "enforce",
      97                 :            :         "complain",
      98                 :            :         "kill",
      99                 :            :         "unconfined",
     100                 :            : };
     101                 :            : 
     102                 :            : /**
     103                 :            :  * hname_tail - find the last component of an hname
     104                 :            :  * @name: hname to find the base profile name component of  (NOT NULL)
     105                 :            :  *
     106                 :            :  * Returns: the tail (base profile name) name component of an hname
     107                 :            :  */
     108                 :          0 : static const char *hname_tail(const char *hname)
     109                 :            : {
     110                 :            :         char *split;
     111                 :          0 :         hname = strim((char *)hname);
     112         [ #  # ]:          0 :         for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
     113                 :          0 :                 hname = split + 2;
     114                 :            : 
     115                 :          0 :         return hname;
     116                 :            : }
     117                 :            : 
     118                 :            : /**
     119                 :            :  * policy_init - initialize a policy structure
     120                 :            :  * @policy: policy to initialize  (NOT NULL)
     121                 :            :  * @prefix: prefix name if any is required.  (MAYBE NULL)
     122                 :            :  * @name: name of the policy, init will make a copy of it  (NOT NULL)
     123                 :            :  *
     124                 :            :  * Note: this fn creates a copy of strings passed in
     125                 :            :  *
     126                 :            :  * Returns: true if policy init successful
     127                 :            :  */
     128                 :          0 : static bool policy_init(struct aa_policy *policy, const char *prefix,
     129                 :            :                         const char *name)
     130                 :            : {
     131                 :            :         /* freed by policy_free */
     132         [ #  # ]:          0 :         if (prefix) {
     133                 :          0 :                 policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3,
     134                 :            :                                         GFP_KERNEL);
     135         [ #  # ]:          0 :                 if (policy->hname)
     136                 :          0 :                         sprintf(policy->hname, "%s//%s", prefix, name);
     137                 :            :         } else
     138                 :          0 :                 policy->hname = kstrdup(name, GFP_KERNEL);
     139         [ #  # ]:          0 :         if (!policy->hname)
     140                 :            :                 return 0;
     141                 :            :         /* base.name is a substring of fqname */
     142                 :          0 :         policy->name = (char *)hname_tail(policy->hname);
     143                 :          0 :         INIT_LIST_HEAD(&policy->list);
     144                 :          0 :         INIT_LIST_HEAD(&policy->profiles);
     145                 :            : 
     146                 :          0 :         return 1;
     147                 :            : }
     148                 :            : 
     149                 :            : /**
     150                 :            :  * policy_destroy - free the elements referenced by @policy
     151                 :            :  * @policy: policy that is to have its elements freed  (NOT NULL)
     152                 :            :  */
     153                 :          0 : static void policy_destroy(struct aa_policy *policy)
     154                 :            : {
     155                 :            :         /* still contains profiles -- invalid */
     156 [ #  # ][ #  # ]:          0 :         if (on_list_rcu(&policy->profiles)) {
     157         [ #  # ]:          0 :                 AA_ERROR("%s: internal error, "
     158                 :            :                          "policy '%s' still contains profiles\n",
     159                 :            :                          __func__, policy->name);
     160                 :          0 :                 BUG();
     161                 :            :         }
     162 [ #  # ][ #  # ]:          0 :         if (on_list_rcu(&policy->list)) {
     163         [ #  # ]:          0 :                 AA_ERROR("%s: internal error, policy '%s' still on list\n",
     164                 :            :                          __func__, policy->name);
     165                 :          0 :                 BUG();
     166                 :            :         }
     167                 :            : 
     168                 :            :         /* don't free name as its a subset of hname */
     169                 :          0 :         kzfree(policy->hname);
     170                 :          0 : }
     171                 :            : 
     172                 :            : /**
     173                 :            :  * __policy_find - find a policy by @name on a policy list
     174                 :            :  * @head: list to search  (NOT NULL)
     175                 :            :  * @name: name to search for  (NOT NULL)
     176                 :            :  *
     177                 :            :  * Requires: rcu_read_lock be held
     178                 :            :  *
     179                 :            :  * Returns: unrefcounted policy that match @name or NULL if not found
     180                 :            :  */
     181                 :          0 : static struct aa_policy *__policy_find(struct list_head *head, const char *name)
     182                 :            : {
     183                 :            :         struct aa_policy *policy;
     184                 :            : 
     185         [ #  # ]:          0 :         list_for_each_entry_rcu(policy, head, list) {
     186         [ #  # ]:          0 :                 if (!strcmp(policy->name, name))
     187                 :            :                         return policy;
     188                 :            :         }
     189                 :            :         return NULL;
     190                 :            : }
     191                 :            : 
     192                 :            : /**
     193                 :            :  * __policy_strn_find - find a policy that's name matches @len chars of @str
     194                 :            :  * @head: list to search  (NOT NULL)
     195                 :            :  * @str: string to search for  (NOT NULL)
     196                 :            :  * @len: length of match required
     197                 :            :  *
     198                 :            :  * Requires: rcu_read_lock be held
     199                 :            :  *
     200                 :            :  * Returns: unrefcounted policy that match @str or NULL if not found
     201                 :            :  *
     202                 :            :  * if @len == strlen(@strlen) then this is equiv to __policy_find
     203                 :            :  * other wise it allows searching for policy by a partial match of name
     204                 :            :  */
     205                 :          0 : static struct aa_policy *__policy_strn_find(struct list_head *head,
     206                 :            :                                             const char *str, int len)
     207                 :            : {
     208                 :            :         struct aa_policy *policy;
     209                 :            : 
     210         [ #  # ]:          0 :         list_for_each_entry_rcu(policy, head, list) {
     211         [ #  # ]:          0 :                 if (aa_strneq(policy->name, str, len))
     212                 :            :                         return policy;
     213                 :            :         }
     214                 :            : 
     215                 :            :         return NULL;
     216                 :            : }
     217                 :            : 
     218                 :            : /*
     219                 :            :  * Routines for AppArmor namespaces
     220                 :            :  */
     221                 :            : 
     222                 :            : static const char *hidden_ns_name = "---";
     223                 :            : /**
     224                 :            :  * aa_ns_visible - test if @view is visible from @curr
     225                 :            :  * @curr: namespace to treat as the parent (NOT NULL)
     226                 :            :  * @view:  namespace to test if visible from @curr (NOT NULL)
     227                 :            :  *
     228                 :            :  * Returns: true if @view is visible from @curr else false
     229                 :            :  */
     230                 :          0 : bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view)
     231                 :            : {
     232 [ #  # ][ -  + ]:          8 :         if (curr == view)
     233                 :            :                 return true;
     234                 :            : 
     235 [ #  # ][ #  # ]:          0 :         for ( ; view; view = view->parent) {
     236 [ #  # ][ #  # ]:          0 :                 if (view->parent == curr)
     237                 :            :                         return true;
     238                 :            :         }
     239                 :            :         return false;
     240                 :            : }
     241                 :            : 
     242                 :            : /**
     243                 :            :  * aa_na_name - Find the ns name to display for @view from @curr
     244                 :            :  * @curr - current namespace (NOT NULL)
     245                 :            :  * @view - namespace attempting to view (NOT NULL)
     246                 :            :  *
     247                 :            :  * Returns: name of @view visible from @curr
     248                 :            :  */
     249                 :          0 : const char *aa_ns_name(struct aa_namespace *curr, struct aa_namespace *view)
     250                 :            : {
     251                 :            :         /* if view == curr then the namespace name isn't displayed */
     252         [ +  - ]:          4 :         if (curr == view)
     253                 :            :                 return "";
     254                 :            : 
     255         [ #  # ]:          0 :         if (aa_ns_visible(curr, view)) {
     256                 :            :                 /* at this point if a ns is visible it is in a view ns
     257                 :            :                  * thus the curr ns.hname is a prefix of its name.
     258                 :            :                  * Only output the virtualized portion of the name
     259                 :            :                  * Add + 2 to skip over // separating curr hname prefix
     260                 :            :                  * from the visible tail of the views hname
     261                 :            :                  */
     262                 :          0 :                 return view->base.hname + strlen(curr->base.hname) + 2;
     263                 :            :         } else
     264                 :          0 :                 return hidden_ns_name;
     265                 :            : }
     266                 :            : 
     267                 :            : /**
     268                 :            :  * alloc_namespace - allocate, initialize and return a new namespace
     269                 :            :  * @prefix: parent namespace name (MAYBE NULL)
     270                 :            :  * @name: a preallocated name  (NOT NULL)
     271                 :            :  *
     272                 :            :  * Returns: refcounted namespace or NULL on failure.
     273                 :            :  */
     274                 :          0 : static struct aa_namespace *alloc_namespace(const char *prefix,
     275                 :            :                                             const char *name)
     276                 :            : {
     277                 :            :         struct aa_namespace *ns;
     278                 :            : 
     279                 :            :         ns = kzalloc(sizeof(*ns), GFP_KERNEL);
     280 [ #  # ][ #  # ]:          0 :         AA_DEBUG("%s(%p)\n", __func__, ns);
     281         [ #  # ]:          0 :         if (!ns)
     282                 :            :                 return NULL;
     283         [ #  # ]:          0 :         if (!policy_init(&ns->base, prefix, name))
     284                 :            :                 goto fail_ns;
     285                 :            : 
     286                 :          0 :         INIT_LIST_HEAD(&ns->sub_ns);
     287                 :          0 :         mutex_init(&ns->lock);
     288                 :            : 
     289                 :            :         /* released by free_namespace */
     290                 :          0 :         ns->unconfined = aa_alloc_profile("unconfined");
     291         [ #  # ]:          0 :         if (!ns->unconfined)
     292                 :            :                 goto fail_unconfined;
     293                 :            : 
     294                 :          0 :         ns->unconfined->flags = PFLAG_IX_ON_NAME_ERROR |
     295                 :            :                 PFLAG_IMMUTABLE | PFLAG_NS_COUNT;
     296                 :          0 :         ns->unconfined->mode = APPARMOR_UNCONFINED;
     297                 :            : 
     298                 :            :         /* ns and ns->unconfined share ns->unconfined refcount */
     299                 :          0 :         ns->unconfined->ns = ns;
     300                 :            : 
     301                 :          0 :         atomic_set(&ns->uniq_null, 0);
     302                 :            : 
     303                 :          0 :         return ns;
     304                 :            : 
     305                 :            : fail_unconfined:
     306                 :          0 :         kzfree(ns->base.hname);
     307                 :            : fail_ns:
     308                 :          0 :         kzfree(ns);
     309                 :          0 :         return NULL;
     310                 :            : }
     311                 :            : 
     312                 :            : /**
     313                 :            :  * free_namespace - free a profile namespace
     314                 :            :  * @ns: the namespace to free  (MAYBE NULL)
     315                 :            :  *
     316                 :            :  * Requires: All references to the namespace must have been put, if the
     317                 :            :  *           namespace was referenced by a profile confining a task,
     318                 :            :  */
     319                 :          0 : static void free_namespace(struct aa_namespace *ns)
     320                 :            : {
     321         [ #  # ]:          0 :         if (!ns)
     322                 :          0 :                 return;
     323                 :            : 
     324                 :          0 :         policy_destroy(&ns->base);
     325                 :          0 :         aa_put_namespace(ns->parent);
     326                 :            : 
     327                 :          0 :         ns->unconfined->ns = NULL;
     328                 :          0 :         aa_free_profile(ns->unconfined);
     329                 :          0 :         kzfree(ns);
     330                 :            : }
     331                 :            : 
     332                 :            : /**
     333                 :            :  * __aa_find_namespace - find a namespace on a list by @name
     334                 :            :  * @head: list to search for namespace on  (NOT NULL)
     335                 :            :  * @name: name of namespace to look for  (NOT NULL)
     336                 :            :  *
     337                 :            :  * Returns: unrefcounted namespace
     338                 :            :  *
     339                 :            :  * Requires: rcu_read_lock be held
     340                 :            :  */
     341                 :            : static struct aa_namespace *__aa_find_namespace(struct list_head *head,
     342                 :            :                                                 const char *name)
     343                 :            : {
     344                 :          0 :         return (struct aa_namespace *)__policy_find(head, name);
     345                 :            : }
     346                 :            : 
     347                 :            : /**
     348                 :            :  * aa_find_namespace  -  look up a profile namespace on the namespace list
     349                 :            :  * @root: namespace to search in  (NOT NULL)
     350                 :            :  * @name: name of namespace to find  (NOT NULL)
     351                 :            :  *
     352                 :            :  * Returns: a refcounted namespace on the list, or NULL if no namespace
     353                 :            :  *          called @name exists.
     354                 :            :  *
     355                 :            :  * refcount released by caller
     356                 :            :  */
     357                 :          0 : struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
     358                 :            :                                        const char *name)
     359                 :            : {
     360                 :            :         struct aa_namespace *ns = NULL;
     361                 :            : 
     362                 :            :         rcu_read_lock();
     363                 :          0 :         ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
     364                 :            :         rcu_read_unlock();
     365                 :            : 
     366                 :          0 :         return ns;
     367                 :            : }
     368                 :            : 
     369                 :            : /**
     370                 :            :  * aa_prepare_namespace - find an existing or create a new namespace of @name
     371                 :            :  * @name: the namespace to find or add  (MAYBE NULL)
     372                 :            :  *
     373                 :            :  * Returns: refcounted namespace or NULL if failed to create one
     374                 :            :  */
     375                 :          0 : static struct aa_namespace *aa_prepare_namespace(const char *name)
     376                 :            : {
     377                 :            :         struct aa_namespace *ns, *root;
     378                 :            : 
     379                 :          0 :         root = aa_current_profile()->ns;
     380                 :            : 
     381                 :          0 :         mutex_lock(&root->lock);
     382                 :            : 
     383                 :            :         /* if name isn't specified the profile is loaded to the current ns */
     384         [ #  # ]:          0 :         if (!name) {
     385                 :            :                 /* released by caller */
     386                 :            :                 ns = aa_get_namespace(root);
     387                 :          0 :                 goto out;
     388                 :            :         }
     389                 :            : 
     390                 :            :         /* try and find the specified ns and if it doesn't exist create it */
     391                 :            :         /* released by caller */
     392                 :          0 :         ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
     393         [ #  # ]:          0 :         if (!ns) {
     394                 :          0 :                 ns = alloc_namespace(root->base.hname, name);
     395         [ #  # ]:          0 :                 if (!ns)
     396                 :            :                         goto out;
     397         [ #  # ]:          0 :                 if (__aa_fs_namespace_mkdir(ns, ns_subns_dir(root), name)) {
     398         [ #  # ]:          0 :                         AA_ERROR("Failed to create interface for ns %s\n",
     399                 :            :                                  ns->base.name);
     400                 :          0 :                         free_namespace(ns);
     401                 :            :                         ns = NULL;
     402                 :          0 :                         goto out;
     403                 :            :                 }
     404                 :          0 :                 ns->parent = aa_get_namespace(root);
     405                 :          0 :                 list_add_rcu(&ns->base.list, &root->sub_ns);
     406                 :            :                 /* add list ref */
     407                 :            :                 aa_get_namespace(ns);
     408                 :            :         }
     409                 :            : out:
     410                 :          0 :         mutex_unlock(&root->lock);
     411                 :            : 
     412                 :            :         /* return ref */
     413                 :          0 :         return ns;
     414                 :            : }
     415                 :            : 
     416                 :            : /**
     417                 :            :  * __list_add_profile - add a profile to a list
     418                 :            :  * @list: list to add it to  (NOT NULL)
     419                 :            :  * @profile: the profile to add  (NOT NULL)
     420                 :            :  *
     421                 :            :  * refcount @profile, should be put by __list_remove_profile
     422                 :            :  *
     423                 :            :  * Requires: namespace lock be held, or list not be shared
     424                 :            :  */
     425                 :          0 : static void __list_add_profile(struct list_head *list,
     426                 :            :                                struct aa_profile *profile)
     427                 :            : {
     428                 :          0 :         list_add_rcu(&profile->base.list, list);
     429                 :            :         /* get list reference */
     430                 :            :         aa_get_profile(profile);
     431                 :          0 : }
     432                 :            : 
     433                 :            : /**
     434                 :            :  * __list_remove_profile - remove a profile from the list it is on
     435                 :            :  * @profile: the profile to remove  (NOT NULL)
     436                 :            :  *
     437                 :            :  * remove a profile from the list, warning generally removal should
     438                 :            :  * be done with __replace_profile as most profile removals are
     439                 :            :  * replacements to the unconfined profile.
     440                 :            :  *
     441                 :            :  * put @profile list refcount
     442                 :            :  *
     443                 :            :  * Requires: namespace lock be held, or list not have been live
     444                 :            :  */
     445                 :          0 : static void __list_remove_profile(struct aa_profile *profile)
     446                 :            : {
     447                 :            :         list_del_rcu(&profile->base.list);
     448                 :            :         aa_put_profile(profile);
     449                 :          0 : }
     450                 :            : 
     451                 :            : static void __profile_list_release(struct list_head *head);
     452                 :            : 
     453                 :            : /**
     454                 :            :  * __remove_profile - remove old profile, and children
     455                 :            :  * @profile: profile to be replaced  (NOT NULL)
     456                 :            :  *
     457                 :            :  * Requires: namespace list lock be held, or list not be shared
     458                 :            :  */
     459                 :          0 : static void __remove_profile(struct aa_profile *profile)
     460                 :            : {
     461                 :            :         /* release any children lists first */
     462                 :          0 :         __profile_list_release(&profile->base.profiles);
     463                 :            :         /* released by free_profile */
     464                 :          0 :         __aa_update_replacedby(profile, profile->ns->unconfined);
     465                 :          0 :         __aa_fs_profile_rmdir(profile);
     466                 :          0 :         __list_remove_profile(profile);
     467                 :          0 : }
     468                 :            : 
     469                 :            : /**
     470                 :            :  * __profile_list_release - remove all profiles on the list and put refs
     471                 :            :  * @head: list of profiles  (NOT NULL)
     472                 :            :  *
     473                 :            :  * Requires: namespace lock be held
     474                 :            :  */
     475                 :          0 : static void __profile_list_release(struct list_head *head)
     476                 :            : {
     477                 :            :         struct aa_profile *profile, *tmp;
     478 [ #  # ][ #  # ]:          0 :         list_for_each_entry_safe(profile, tmp, head, base.list)
     479                 :          0 :                 __remove_profile(profile);
     480                 :          0 : }
     481                 :            : 
     482                 :            : static void __ns_list_release(struct list_head *head);
     483                 :            : 
     484                 :            : /**
     485                 :            :  * destroy_namespace - remove everything contained by @ns
     486                 :            :  * @ns: namespace to have it contents removed  (NOT NULL)
     487                 :            :  */
     488                 :          0 : static void destroy_namespace(struct aa_namespace *ns)
     489                 :            : {
     490         [ #  # ]:          0 :         if (!ns)
     491                 :          0 :                 return;
     492                 :            : 
     493                 :          0 :         mutex_lock(&ns->lock);
     494                 :            :         /* release all profiles in this namespace */
     495                 :          0 :         __profile_list_release(&ns->base.profiles);
     496                 :            : 
     497                 :            :         /* release all sub namespaces */
     498                 :          0 :         __ns_list_release(&ns->sub_ns);
     499                 :            : 
     500         [ #  # ]:          0 :         if (ns->parent)
     501                 :          0 :                 __aa_update_replacedby(ns->unconfined, ns->parent->unconfined);
     502                 :          0 :         __aa_fs_namespace_rmdir(ns);
     503                 :          0 :         mutex_unlock(&ns->lock);
     504                 :            : }
     505                 :            : 
     506                 :            : /**
     507                 :            :  * __remove_namespace - remove a namespace and all its children
     508                 :            :  * @ns: namespace to be removed  (NOT NULL)
     509                 :            :  *
     510                 :            :  * Requires: ns->parent->lock be held and ns removed from parent.
     511                 :            :  */
     512                 :          0 : static void __remove_namespace(struct aa_namespace *ns)
     513                 :            : {
     514                 :            :         /* remove ns from namespace list */
     515                 :            :         list_del_rcu(&ns->base.list);
     516                 :          0 :         destroy_namespace(ns);
     517                 :            :         aa_put_namespace(ns);
     518                 :          0 : }
     519                 :            : 
     520                 :            : /**
     521                 :            :  * __ns_list_release - remove all profile namespaces on the list put refs
     522                 :            :  * @head: list of profile namespaces  (NOT NULL)
     523                 :            :  *
     524                 :            :  * Requires: namespace lock be held
     525                 :            :  */
     526                 :          0 : static void __ns_list_release(struct list_head *head)
     527                 :            : {
     528                 :            :         struct aa_namespace *ns, *tmp;
     529         [ #  # ]:          0 :         list_for_each_entry_safe(ns, tmp, head, base.list)
     530                 :          0 :                 __remove_namespace(ns);
     531                 :            : 
     532                 :          0 : }
     533                 :            : 
     534                 :            : /**
     535                 :            :  * aa_alloc_root_ns - allocate the root profile namespace
     536                 :            :  *
     537                 :            :  * Returns: %0 on success else error
     538                 :            :  *
     539                 :            :  */
     540                 :          0 : int __init aa_alloc_root_ns(void)
     541                 :            : {
     542                 :            :         /* released by aa_free_root_ns - used as list ref*/
     543                 :          0 :         root_ns = alloc_namespace(NULL, "root");
     544         [ #  # ]:          0 :         if (!root_ns)
     545                 :            :                 return -ENOMEM;
     546                 :            : 
     547                 :          0 :         return 0;
     548                 :            : }
     549                 :            : 
     550                 :            :  /**
     551                 :            :   * aa_free_root_ns - free the root profile namespace
     552                 :            :   */
     553                 :          0 : void __init aa_free_root_ns(void)
     554                 :            :  {
     555                 :          0 :          struct aa_namespace *ns = root_ns;
     556                 :          0 :          root_ns = NULL;
     557                 :            : 
     558                 :          0 :          destroy_namespace(ns);
     559                 :            :          aa_put_namespace(ns);
     560                 :          0 : }
     561                 :            : 
     562                 :            : 
     563                 :          0 : static void free_replacedby(struct aa_replacedby *r)
     564                 :            : {
     565         [ #  # ]:          0 :         if (r) {
     566                 :            :                 /* r->profile will not be updated any more as r is dead */
     567                 :          0 :                 aa_put_profile(rcu_dereference_protected(r->profile, true));
     568                 :          0 :                 kzfree(r);
     569                 :            :         }
     570                 :          0 : }
     571                 :            : 
     572                 :            : 
     573                 :          0 : void aa_free_replacedby_kref(struct kref *kref)
     574                 :            : {
     575                 :            :         struct aa_replacedby *r = container_of(kref, struct aa_replacedby,
     576                 :            :                                                count);
     577                 :          0 :         free_replacedby(r);
     578                 :          0 : }
     579                 :            : 
     580                 :            : /**
     581                 :            :  * aa_free_profile - free a profile
     582                 :            :  * @profile: the profile to free  (MAYBE NULL)
     583                 :            :  *
     584                 :            :  * Free a profile, its hats and null_profile. All references to the profile,
     585                 :            :  * its hats and null_profile must have been put.
     586                 :            :  *
     587                 :            :  * If the profile was referenced from a task context, free_profile() will
     588                 :            :  * be called from an rcu callback routine, so we must not sleep here.
     589                 :            :  */
     590                 :          0 : void aa_free_profile(struct aa_profile *profile)
     591                 :            : {
     592 [ #  # ][ #  # ]:          0 :         AA_DEBUG("%s(%p)\n", __func__, profile);
     593                 :            : 
     594         [ #  # ]:          0 :         if (!profile)
     595                 :          0 :                 return;
     596                 :            : 
     597                 :            :         /* free children profiles */
     598                 :          0 :         policy_destroy(&profile->base);
     599                 :          0 :         aa_put_profile(rcu_access_pointer(profile->parent));
     600                 :            : 
     601                 :          0 :         aa_put_namespace(profile->ns);
     602                 :          0 :         kzfree(profile->rename);
     603                 :            : 
     604                 :            :         aa_free_file_rules(&profile->file);
     605                 :            :         aa_free_cap_rules(&profile->caps);
     606                 :            :         aa_free_rlimit_rules(&profile->rlimits);
     607                 :            : 
     608                 :          0 :         kzfree(profile->dirname);
     609                 :          0 :         aa_put_dfa(profile->xmatch);
     610                 :          0 :         aa_put_dfa(profile->policy.dfa);
     611                 :          0 :         aa_put_replacedby(profile->replacedby);
     612                 :            : 
     613                 :          0 :         kzfree(profile->hash);
     614                 :          0 :         kzfree(profile);
     615                 :            : }
     616                 :            : 
     617                 :            : /**
     618                 :            :  * aa_free_profile_rcu - free aa_profile by rcu (called by aa_free_profile_kref)
     619                 :            :  * @head: rcu_head callback for freeing of a profile  (NOT NULL)
     620                 :            :  */
     621                 :          0 : static void aa_free_profile_rcu(struct rcu_head *head)
     622                 :            : {
     623                 :          0 :         struct aa_profile *p = container_of(head, struct aa_profile, rcu);
     624         [ #  # ]:          0 :         if (p->flags & PFLAG_NS_COUNT)
     625                 :          0 :                 free_namespace(p->ns);
     626                 :            :         else
     627                 :          0 :                 aa_free_profile(p);
     628                 :          0 : }
     629                 :            : 
     630                 :            : /**
     631                 :            :  * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile)
     632                 :            :  * @kr: kref callback for freeing of a profile  (NOT NULL)
     633                 :            :  */
     634                 :          0 : void aa_free_profile_kref(struct kref *kref)
     635                 :            : {
     636                 :            :         struct aa_profile *p = container_of(kref, struct aa_profile, count);
     637                 :          0 :         call_rcu(&p->rcu, aa_free_profile_rcu);
     638                 :          0 : }
     639                 :            : 
     640                 :            : /**
     641                 :            :  * aa_alloc_profile - allocate, initialize and return a new profile
     642                 :            :  * @hname: name of the profile  (NOT NULL)
     643                 :            :  *
     644                 :            :  * Returns: refcount profile or NULL on failure
     645                 :            :  */
     646                 :          0 : struct aa_profile *aa_alloc_profile(const char *hname)
     647                 :            : {
     648                 :            :         struct aa_profile *profile;
     649                 :            : 
     650                 :            :         /* freed by free_profile - usually through aa_put_profile */
     651                 :            :         profile = kzalloc(sizeof(*profile), GFP_KERNEL);
     652         [ #  # ]:          0 :         if (!profile)
     653                 :            :                 return NULL;
     654                 :            : 
     655                 :          0 :         profile->replacedby = kzalloc(sizeof(struct aa_replacedby), GFP_KERNEL);
     656         [ #  # ]:          0 :         if (!profile->replacedby)
     657                 :            :                 goto fail;
     658                 :            :         kref_init(&profile->replacedby->count);
     659                 :            : 
     660         [ #  # ]:          0 :         if (!policy_init(&profile->base, NULL, hname))
     661                 :            :                 goto fail;
     662                 :            :         kref_init(&profile->count);
     663                 :            : 
     664                 :            :         /* refcount released by caller */
     665                 :          0 :         return profile;
     666                 :            : 
     667                 :            : fail:
     668                 :          0 :         kzfree(profile->replacedby);
     669                 :          0 :         kzfree(profile);
     670                 :            : 
     671                 :          0 :         return NULL;
     672                 :            : }
     673                 :            : 
     674                 :            : /**
     675                 :            :  * aa_new_null_profile - create a new null-X learning profile
     676                 :            :  * @parent: profile that caused this profile to be created (NOT NULL)
     677                 :            :  * @hat: true if the null- learning profile is a hat
     678                 :            :  *
     679                 :            :  * Create a null- complain mode profile used in learning mode.  The name of
     680                 :            :  * the profile is unique and follows the format of parent//null-<uniq>.
     681                 :            :  *
     682                 :            :  * null profiles are added to the profile list but the list does not
     683                 :            :  * hold a count on them so that they are automatically released when
     684                 :            :  * not in use.
     685                 :            :  *
     686                 :            :  * Returns: new refcounted profile else NULL on failure
     687                 :            :  */
     688                 :          0 : struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
     689                 :            : {
     690                 :            :         struct aa_profile *profile = NULL;
     691                 :            :         char *name;
     692                 :          0 :         int uniq = atomic_inc_return(&parent->ns->uniq_null);
     693                 :            : 
     694                 :            :         /* freed below */
     695                 :          0 :         name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL);
     696         [ #  # ]:          0 :         if (!name)
     697                 :            :                 goto fail;
     698                 :          0 :         sprintf(name, "%s//null-%x", parent->base.hname, uniq);
     699                 :            : 
     700                 :          0 :         profile = aa_alloc_profile(name);
     701                 :          0 :         kfree(name);
     702         [ #  # ]:          0 :         if (!profile)
     703                 :            :                 goto fail;
     704                 :            : 
     705                 :          0 :         profile->mode = APPARMOR_COMPLAIN;
     706                 :          0 :         profile->flags = PFLAG_NULL;
     707         [ #  # ]:          0 :         if (hat)
     708                 :          0 :                 profile->flags |= PFLAG_HAT;
     709                 :            : 
     710                 :            :         /* released on free_profile */
     711                 :          0 :         rcu_assign_pointer(profile->parent, aa_get_profile(parent));
     712                 :          0 :         profile->ns = aa_get_namespace(parent->ns);
     713                 :            : 
     714                 :          0 :         mutex_lock(&profile->ns->lock);
     715                 :          0 :         __list_add_profile(&parent->base.profiles, profile);
     716                 :          0 :         mutex_unlock(&profile->ns->lock);
     717                 :            : 
     718                 :            :         /* refcount released by caller */
     719                 :          0 :         return profile;
     720                 :            : 
     721                 :            : fail:
     722                 :            :         return NULL;
     723                 :            : }
     724                 :            : 
     725                 :            : /* TODO: profile accounting - setup in remove */
     726                 :            : 
     727                 :            : /**
     728                 :            :  * __find_child - find a profile on @head list with a name matching @name
     729                 :            :  * @head: list to search  (NOT NULL)
     730                 :            :  * @name: name of profile (NOT NULL)
     731                 :            :  *
     732                 :            :  * Requires: rcu_read_lock be held
     733                 :            :  *
     734                 :            :  * Returns: unrefcounted profile ptr, or NULL if not found
     735                 :            :  */
     736                 :            : static struct aa_profile *__find_child(struct list_head *head, const char *name)
     737                 :            : {
     738                 :          0 :         return (struct aa_profile *)__policy_find(head, name);
     739                 :            : }
     740                 :            : 
     741                 :            : /**
     742                 :            :  * __strn_find_child - find a profile on @head list using substring of @name
     743                 :            :  * @head: list to search  (NOT NULL)
     744                 :            :  * @name: name of profile (NOT NULL)
     745                 :            :  * @len: length of @name substring to match
     746                 :            :  *
     747                 :            :  * Requires: rcu_read_lock be held
     748                 :            :  *
     749                 :            :  * Returns: unrefcounted profile ptr, or NULL if not found
     750                 :            :  */
     751                 :            : static struct aa_profile *__strn_find_child(struct list_head *head,
     752                 :            :                                             const char *name, int len)
     753                 :            : {
     754                 :          0 :         return (struct aa_profile *)__policy_strn_find(head, name, len);
     755                 :            : }
     756                 :            : 
     757                 :            : /**
     758                 :            :  * aa_find_child - find a profile by @name in @parent
     759                 :            :  * @parent: profile to search  (NOT NULL)
     760                 :            :  * @name: profile name to search for  (NOT NULL)
     761                 :            :  *
     762                 :            :  * Returns: a refcounted profile or NULL if not found
     763                 :            :  */
     764                 :          0 : struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
     765                 :            : {
     766                 :            :         struct aa_profile *profile;
     767                 :            : 
     768                 :            :         rcu_read_lock();
     769                 :          0 :         profile = aa_get_profile(__find_child(&parent->base.profiles, name));
     770                 :            :         rcu_read_unlock();
     771                 :            : 
     772                 :            :         /* refcount released by caller */
     773                 :          0 :         return profile;
     774                 :            : }
     775                 :            : 
     776                 :            : /**
     777                 :            :  * __lookup_parent - lookup the parent of a profile of name @hname
     778                 :            :  * @ns: namespace to lookup profile in  (NOT NULL)
     779                 :            :  * @hname: hierarchical profile name to find parent of  (NOT NULL)
     780                 :            :  *
     781                 :            :  * Lookups up the parent of a fully qualified profile name, the profile
     782                 :            :  * that matches hname does not need to exist, in general this
     783                 :            :  * is used to load a new profile.
     784                 :            :  *
     785                 :            :  * Requires: rcu_read_lock be held
     786                 :            :  *
     787                 :            :  * Returns: unrefcounted policy or NULL if not found
     788                 :            :  */
     789                 :          0 : static struct aa_policy *__lookup_parent(struct aa_namespace *ns,
     790                 :            :                                          const char *hname)
     791                 :            : {
     792                 :            :         struct aa_policy *policy;
     793                 :            :         struct aa_profile *profile = NULL;
     794                 :            :         char *split;
     795                 :            : 
     796                 :          0 :         policy = &ns->base;
     797                 :            : 
     798         [ #  # ]:          0 :         for (split = strstr(hname, "//"); split;) {
     799                 :          0 :                 profile = __strn_find_child(&policy->profiles, hname,
     800                 :            :                                             split - hname);
     801         [ #  # ]:          0 :                 if (!profile)
     802                 :            :                         return NULL;
     803                 :          0 :                 policy = &profile->base;
     804                 :          0 :                 hname = split + 2;
     805                 :          0 :                 split = strstr(hname, "//");
     806                 :            :         }
     807         [ #  # ]:          0 :         if (!profile)
     808                 :            :                 return &ns->base;
     809                 :          0 :         return &profile->base;
     810                 :            : }
     811                 :            : 
     812                 :            : /**
     813                 :            :  * __lookup_profile - lookup the profile matching @hname
     814                 :            :  * @base: base list to start looking up profile name from  (NOT NULL)
     815                 :            :  * @hname: hierarchical profile name  (NOT NULL)
     816                 :            :  *
     817                 :            :  * Requires: rcu_read_lock be held
     818                 :            :  *
     819                 :            :  * Returns: unrefcounted profile pointer or NULL if not found
     820                 :            :  *
     821                 :            :  * Do a relative name lookup, recursing through profile tree.
     822                 :            :  */
     823                 :          0 : static struct aa_profile *__lookup_profile(struct aa_policy *base,
     824                 :            :                                            const char *hname)
     825                 :            : {
     826                 :            :         struct aa_profile *profile = NULL;
     827                 :            :         char *split;
     828                 :            : 
     829         [ #  # ]:          0 :         for (split = strstr(hname, "//"); split;) {
     830                 :          0 :                 profile = __strn_find_child(&base->profiles, hname,
     831                 :            :                                             split - hname);
     832         [ #  # ]:          0 :                 if (!profile)
     833                 :            :                         return NULL;
     834                 :            : 
     835                 :          0 :                 base = &profile->base;
     836                 :          0 :                 hname = split + 2;
     837                 :          0 :                 split = strstr(hname, "//");
     838                 :            :         }
     839                 :            : 
     840                 :          0 :         profile = __find_child(&base->profiles, hname);
     841                 :            : 
     842                 :          0 :         return profile;
     843                 :            : }
     844                 :            : 
     845                 :            : /**
     846                 :            :  * aa_lookup_profile - find a profile by its full or partial name
     847                 :            :  * @ns: the namespace to start from (NOT NULL)
     848                 :            :  * @hname: name to do lookup on.  Does not contain namespace prefix (NOT NULL)
     849                 :            :  *
     850                 :            :  * Returns: refcounted profile or NULL if not found
     851                 :            :  */
     852                 :          0 : struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname)
     853                 :            : {
     854                 :            :         struct aa_profile *profile;
     855                 :            : 
     856                 :            :         rcu_read_lock();
     857                 :            :         do {
     858                 :          0 :                 profile = __lookup_profile(&ns->base, hname);
     859 [ #  # ][ #  # ]:          0 :         } while (profile && !aa_get_profile_not0(profile));
     860                 :            :         rcu_read_unlock();
     861                 :            : 
     862                 :            :         /* the unconfined profile is not in the regular profile list */
     863 [ #  # ][ #  # ]:          0 :         if (!profile && strcmp(hname, "unconfined") == 0)
     864                 :          0 :                 profile = aa_get_newest_profile(ns->unconfined);
     865                 :            : 
     866                 :            :         /* refcount released by caller */
     867                 :          0 :         return profile;
     868                 :            : }
     869                 :            : 
     870                 :            : /**
     871                 :            :  * replacement_allowed - test to see if replacement is allowed
     872                 :            :  * @profile: profile to test if it can be replaced  (MAYBE NULL)
     873                 :            :  * @noreplace: true if replacement shouldn't be allowed but addition is okay
     874                 :            :  * @info: Returns - info about why replacement failed (NOT NULL)
     875                 :            :  *
     876                 :            :  * Returns: %0 if replacement allowed else error code
     877                 :            :  */
     878                 :            : static int replacement_allowed(struct aa_profile *profile, int noreplace,
     879                 :            :                                const char **info)
     880                 :            : {
     881         [ #  # ]:          0 :         if (profile) {
     882         [ #  # ]:          0 :                 if (profile->flags & PFLAG_IMMUTABLE) {
     883                 :          0 :                         *info = "cannot replace immutible profile";
     884                 :            :                         return -EPERM;
     885         [ #  # ]:          0 :                 } else if (noreplace) {
     886                 :          0 :                         *info = "profile already exists";
     887                 :            :                         return -EEXIST;
     888                 :            :                 }
     889                 :            :         }
     890                 :            :         return 0;
     891                 :            : }
     892                 :            : 
     893                 :            : /**
     894                 :            :  * aa_audit_policy - Do auditing of policy changes
     895                 :            :  * @op: policy operation being performed
     896                 :            :  * @gfp: memory allocation flags
     897                 :            :  * @name: name of profile being manipulated (NOT NULL)
     898                 :            :  * @info: any extra information to be audited (MAYBE NULL)
     899                 :            :  * @error: error code
     900                 :            :  *
     901                 :            :  * Returns: the error to be returned after audit is done
     902                 :            :  */
     903                 :          0 : static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
     904                 :            :                         int error)
     905                 :            : {
     906                 :            :         struct common_audit_data sa;
     907                 :          0 :         struct apparmor_audit_data aad = {0,};
     908                 :          0 :         sa.type = LSM_AUDIT_DATA_NONE;
     909                 :          0 :         sa.aad = &aad;
     910                 :          0 :         aad.op = op;
     911                 :          0 :         aad.name = name;
     912                 :          0 :         aad.info = info;
     913                 :          0 :         aad.error = error;
     914                 :            : 
     915                 :          0 :         return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
     916                 :            :                         &sa, NULL);
     917                 :            : }
     918                 :            : 
     919                 :            : /**
     920                 :            :  * aa_may_manage_policy - can the current task manage policy
     921                 :            :  * @op: the policy manipulation operation being done
     922                 :            :  *
     923                 :            :  * Returns: true if the task is allowed to manipulate policy
     924                 :            :  */
     925                 :          0 : bool aa_may_manage_policy(int op)
     926                 :            : {
     927                 :            :         /* check if loading policy is locked out */
     928         [ #  # ]:          0 :         if (aa_g_lock_policy) {
     929                 :          0 :                 audit_policy(op, GFP_KERNEL, NULL, "policy_locked", -EACCES);
     930                 :          0 :                 return 0;
     931                 :            :         }
     932                 :            : 
     933         [ #  # ]:          0 :         if (!capable(CAP_MAC_ADMIN)) {
     934                 :          0 :                 audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES);
     935                 :          0 :                 return 0;
     936                 :            :         }
     937                 :            : 
     938                 :            :         return 1;
     939                 :            : }
     940                 :            : 
     941                 :          0 : static struct aa_profile *__list_lookup_parent(struct list_head *lh,
     942                 :            :                                                struct aa_profile *profile)
     943                 :            : {
     944                 :          0 :         const char *base = hname_tail(profile->base.hname);
     945                 :          0 :         long len = base - profile->base.hname;
     946                 :            :         struct aa_load_ent *ent;
     947                 :            : 
     948                 :            :         /* parent won't have trailing // so remove from len */
     949         [ #  # ]:          0 :         if (len <= 2)
     950                 :            :                 return NULL;
     951                 :          0 :         len -= 2;
     952                 :            : 
     953         [ #  # ]:          0 :         list_for_each_entry(ent, lh, list) {
     954         [ #  # ]:          0 :                 if (ent->new == profile)
     955                 :          0 :                         continue;
     956         [ #  # ]:          0 :                 if (strncmp(ent->new->base.hname, profile->base.hname, len) ==
     957         [ #  # ]:          0 :                     0 && ent->new->base.hname[len] == 0)
     958                 :            :                         return ent->new;
     959                 :            :         }
     960                 :            : 
     961                 :            :         return NULL;
     962                 :            : }
     963                 :            : 
     964                 :            : /**
     965                 :            :  * __replace_profile - replace @old with @new on a list
     966                 :            :  * @old: profile to be replaced  (NOT NULL)
     967                 :            :  * @new: profile to replace @old with  (NOT NULL)
     968                 :            :  * @share_replacedby: transfer @old->replacedby to @new
     969                 :            :  *
     970                 :            :  * Will duplicate and refcount elements that @new inherits from @old
     971                 :            :  * and will inherit @old children.
     972                 :            :  *
     973                 :            :  * refcount @new for list, put @old list refcount
     974                 :            :  *
     975                 :            :  * Requires: namespace list lock be held, or list not be shared
     976                 :            :  */
     977                 :          0 : static void __replace_profile(struct aa_profile *old, struct aa_profile *new,
     978                 :            :                               bool share_replacedby)
     979                 :            : {
     980                 :          0 :         struct aa_profile *child, *tmp;
     981                 :            : 
     982         [ #  # ]:          0 :         if (!list_empty(&old->base.profiles)) {
     983                 :          0 :                 LIST_HEAD(lh);
     984                 :            :                 list_splice_init_rcu(&old->base.profiles, &lh, synchronize_rcu);
     985                 :            : 
     986         [ #  # ]:          0 :                 list_for_each_entry_safe(child, tmp, &lh, base.list) {
     987                 :            :                         struct aa_profile *p;
     988                 :            : 
     989                 :            :                         list_del_init(&child->base.list);
     990                 :          0 :                         p = __find_child(&new->base.profiles, child->base.name);
     991         [ #  # ]:          0 :                         if (p) {
     992                 :            :                                 /* @p replaces @child  */
     993                 :          0 :                                 __replace_profile(child, p, share_replacedby);
     994                 :          0 :                                 continue;
     995                 :            :                         }
     996                 :            : 
     997                 :            :                         /* inherit @child and its children */
     998                 :            :                         /* TODO: update hname of inherited children */
     999                 :            :                         /* list refcount transferred to @new */
    1000                 :            :                         p = aa_deref_parent(child);
    1001                 :          0 :                         rcu_assign_pointer(child->parent, aa_get_profile(new));
    1002                 :            :                         list_add_rcu(&child->base.list, &new->base.profiles);
    1003                 :            :                         aa_put_profile(p);
    1004                 :            :                 }
    1005                 :            :         }
    1006                 :            : 
    1007         [ #  # ]:          0 :         if (!rcu_access_pointer(new->parent)) {
    1008                 :            :                 struct aa_profile *parent = aa_deref_parent(old);
    1009                 :          0 :                 rcu_assign_pointer(new->parent, aa_get_profile(parent));
    1010                 :            :         }
    1011                 :            :         __aa_update_replacedby(old, new);
    1012         [ #  # ]:          0 :         if (share_replacedby) {
    1013                 :          0 :                 aa_put_replacedby(new->replacedby);
    1014                 :          0 :                 new->replacedby = aa_get_replacedby(old->replacedby);
    1015         [ #  # ]:          0 :         } else if (!rcu_access_pointer(new->replacedby->profile))
    1016                 :            :                 /* aafs interface uses replacedby */
    1017                 :          0 :                 rcu_assign_pointer(new->replacedby->profile,
    1018                 :            :                                    aa_get_profile(new));
    1019                 :          0 :         __aa_fs_profile_migrate_dents(old, new);
    1020                 :            : 
    1021         [ #  # ]:          0 :         if (list_empty(&new->base.list)) {
    1022                 :            :                 /* new is not on a list already */
    1023                 :            :                 list_replace_rcu(&old->base.list, &new->base.list);
    1024                 :            :                 aa_get_profile(new);
    1025                 :            :                 aa_put_profile(old);
    1026                 :            :         } else
    1027                 :          0 :                 __list_remove_profile(old);
    1028                 :          0 : }
    1029                 :            : 
    1030                 :            : /**
    1031                 :            :  * __lookup_replace - lookup replacement information for a profile
    1032                 :            :  * @ns - namespace the lookup occurs in
    1033                 :            :  * @hname - name of profile to lookup
    1034                 :            :  * @noreplace - true if not replacing an existing profile
    1035                 :            :  * @p - Returns: profile to be replaced
    1036                 :            :  * @info - Returns: info string on why lookup failed
    1037                 :            :  *
    1038                 :            :  * Returns: profile to replace (no ref) on success else ptr error
    1039                 :            :  */
    1040                 :          0 : static int __lookup_replace(struct aa_namespace *ns, const char *hname,
    1041                 :            :                             bool noreplace, struct aa_profile **p,
    1042                 :            :                             const char **info)
    1043                 :            : {
    1044                 :          0 :         *p = aa_get_profile(__lookup_profile(&ns->base, hname));
    1045         [ #  # ]:          0 :         if (*p) {
    1046                 :            :                 int error = replacement_allowed(*p, noreplace, info);
    1047         [ #  # ]:          0 :                 if (error) {
    1048                 :          0 :                         *info = "profile can not be replaced";
    1049                 :          0 :                         return error;
    1050                 :            :                 }
    1051                 :            :         }
    1052                 :            : 
    1053                 :            :         return 0;
    1054                 :            : }
    1055                 :            : 
    1056                 :            : /**
    1057                 :            :  * aa_replace_profiles - replace profile(s) on the profile list
    1058                 :            :  * @udata: serialized data stream  (NOT NULL)
    1059                 :            :  * @size: size of the serialized data stream
    1060                 :            :  * @noreplace: true if only doing addition, no replacement allowed
    1061                 :            :  *
    1062                 :            :  * unpack and replace a profile on the profile list and uses of that profile
    1063                 :            :  * by any aa_task_cxt.  If the profile does not exist on the profile list
    1064                 :            :  * it is added.
    1065                 :            :  *
    1066                 :            :  * Returns: size of data consumed else error code on failure.
    1067                 :            :  */
    1068                 :          0 : ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
    1069                 :            : {
    1070                 :          0 :         const char *ns_name, *name = NULL, *info = NULL;
    1071                 :            :         struct aa_namespace *ns = NULL;
    1072                 :            :         struct aa_load_ent *ent, *tmp;
    1073                 :            :         int op = OP_PROF_REPL;
    1074                 :            :         ssize_t error;
    1075                 :          0 :         LIST_HEAD(lh);
    1076                 :            : 
    1077                 :            :         /* released below */
    1078                 :          0 :         error = aa_unpack(udata, size, &lh, &ns_name);
    1079         [ #  # ]:          0 :         if (error)
    1080                 :            :                 goto out;
    1081                 :            : 
    1082                 :            :         /* released below */
    1083                 :          0 :         ns = aa_prepare_namespace(ns_name);
    1084         [ #  # ]:          0 :         if (!ns) {
    1085                 :          0 :                 info = "failed to prepare namespace";
    1086                 :            :                 error = -ENOMEM;
    1087                 :          0 :                 name = ns_name;
    1088                 :          0 :                 goto fail;
    1089                 :            :         }
    1090                 :            : 
    1091                 :          0 :         mutex_lock(&ns->lock);
    1092                 :            :         /* setup parent and ns info */
    1093         [ #  # ]:          0 :         list_for_each_entry(ent, &lh, list) {
    1094                 :            :                 struct aa_policy *policy;
    1095                 :            : 
    1096                 :          0 :                 name = ent->new->base.hname;
    1097                 :          0 :                 error = __lookup_replace(ns, ent->new->base.hname, noreplace,
    1098                 :            :                                          &ent->old, &info);
    1099         [ #  # ]:          0 :                 if (error)
    1100                 :            :                         goto fail_lock;
    1101                 :            : 
    1102         [ #  # ]:          0 :                 if (ent->new->rename) {
    1103                 :          0 :                         error = __lookup_replace(ns, ent->new->rename,
    1104                 :            :                                                  noreplace, &ent->rename,
    1105                 :            :                                                  &info);
    1106         [ #  # ]:          0 :                         if (error)
    1107                 :            :                                 goto fail_lock;
    1108                 :            :                 }
    1109                 :            : 
    1110                 :            :                 /* released when @new is freed */
    1111                 :          0 :                 ent->new->ns = aa_get_namespace(ns);
    1112                 :            : 
    1113 [ #  # ][ #  # ]:          0 :                 if (ent->old || ent->rename)
    1114                 :          0 :                         continue;
    1115                 :            : 
    1116                 :            :                 /* no ref on policy only use inside lock */
    1117                 :          0 :                 policy = __lookup_parent(ns, ent->new->base.hname);
    1118         [ #  # ]:          0 :                 if (!policy) {
    1119                 :            :                         struct aa_profile *p;
    1120                 :          0 :                         p = __list_lookup_parent(&lh, ent->new);
    1121         [ #  # ]:          0 :                         if (!p) {
    1122                 :            :                                 error = -ENOENT;
    1123                 :          0 :                                 info = "parent does not exist";
    1124                 :          0 :                                 name = ent->new->base.hname;
    1125                 :          0 :                                 goto fail_lock;
    1126                 :            :                         }
    1127                 :          0 :                         rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
    1128         [ #  # ]:          0 :                 } else if (policy != &ns->base) {
    1129                 :            :                         /* released on profile replacement or free_profile */
    1130                 :            :                         struct aa_profile *p = (struct aa_profile *) policy;
    1131                 :          0 :                         rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
    1132                 :            :                 }
    1133                 :            :         }
    1134                 :            : 
    1135                 :            :         /* create new fs entries for introspection if needed */
    1136         [ #  # ]:          0 :         list_for_each_entry(ent, &lh, list) {
    1137         [ #  # ]:          0 :                 if (ent->old) {
    1138                 :            :                         /* inherit old interface files */
    1139                 :            : 
    1140                 :            :                         /* if (ent->rename)
    1141                 :            :                                 TODO: support rename */
    1142                 :            :                 /* } else if (ent->rename) {
    1143                 :            :                         TODO: support rename */
    1144                 :            :                 } else {
    1145                 :            :                         struct dentry *parent;
    1146         [ #  # ]:          0 :                         if (rcu_access_pointer(ent->new->parent)) {
    1147                 :            :                                 struct aa_profile *p;
    1148                 :            :                                 p = aa_deref_parent(ent->new);
    1149                 :          0 :                                 parent = prof_child_dir(p);
    1150                 :            :                         } else
    1151                 :          0 :                                 parent = ns_subprofs_dir(ent->new->ns);
    1152                 :          0 :                         error = __aa_fs_profile_mkdir(ent->new, parent);
    1153                 :            :                 }
    1154                 :            : 
    1155         [ #  # ]:          0 :                 if (error) {
    1156                 :          0 :                         info = "failed to create ";
    1157                 :          0 :                         goto fail_lock;
    1158                 :            :                 }
    1159                 :            :         }
    1160                 :            : 
    1161                 :            :         /* Done with checks that may fail - do actual replacement */
    1162         [ #  # ]:          0 :         list_for_each_entry_safe(ent, tmp, &lh, list) {
    1163                 :            :                 list_del_init(&ent->list);
    1164 [ #  # ][ #  # ]:          0 :                 op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
    1165                 :            : 
    1166                 :          0 :                 audit_policy(op, GFP_ATOMIC, ent->new->base.name, NULL, error);
    1167                 :            : 
    1168         [ #  # ]:          0 :                 if (ent->old) {
    1169                 :          0 :                         __replace_profile(ent->old, ent->new, 1);
    1170         [ #  # ]:          0 :                         if (ent->rename) {
    1171                 :            :                                 /* aafs interface uses replacedby */
    1172                 :          0 :                                 struct aa_replacedby *r = ent->new->replacedby;
    1173                 :          0 :                                 rcu_assign_pointer(r->profile,
    1174                 :            :                                                    aa_get_profile(ent->new));
    1175                 :          0 :                                 __replace_profile(ent->rename, ent->new, 0);
    1176                 :            :                         }
    1177         [ #  # ]:          0 :                 } else if (ent->rename) {
    1178                 :            :                         /* aafs interface uses replacedby */
    1179                 :          0 :                         rcu_assign_pointer(ent->new->replacedby->profile,
    1180                 :            :                                            aa_get_profile(ent->new));
    1181                 :          0 :                         __replace_profile(ent->rename, ent->new, 0);
    1182         [ #  # ]:          0 :                 } else if (ent->new->parent) {
    1183                 :            :                         struct aa_profile *parent, *newest;
    1184                 :            :                         parent = aa_deref_parent(ent->new);
    1185                 :            :                         newest = aa_get_newest_profile(parent);
    1186                 :            : 
    1187                 :            :                         /* parent replaced in this atomic set? */
    1188         [ #  # ]:          0 :                         if (newest != parent) {
    1189                 :            :                                 aa_get_profile(newest);
    1190                 :            :                                 aa_put_profile(parent);
    1191                 :          0 :                                 rcu_assign_pointer(ent->new->parent, newest);
    1192                 :            :                         } else
    1193                 :            :                                 aa_put_profile(newest);
    1194                 :            :                         /* aafs interface uses replacedby */
    1195                 :          0 :                         rcu_assign_pointer(ent->new->replacedby->profile,
    1196                 :            :                                            aa_get_profile(ent->new));
    1197                 :          0 :                         __list_add_profile(&parent->base.profiles, ent->new);
    1198                 :            :                 } else {
    1199                 :            :                         /* aafs interface uses replacedby */
    1200                 :          0 :                         rcu_assign_pointer(ent->new->replacedby->profile,
    1201                 :            :                                            aa_get_profile(ent->new));
    1202                 :          0 :                         __list_add_profile(&ns->base.profiles, ent->new);
    1203                 :            :                 }
    1204                 :          0 :                 aa_load_ent_free(ent);
    1205                 :            :         }
    1206                 :          0 :         mutex_unlock(&ns->lock);
    1207                 :            : 
    1208                 :            : out:
    1209                 :            :         aa_put_namespace(ns);
    1210                 :            : 
    1211         [ #  # ]:          0 :         if (error)
    1212                 :            :                 return error;
    1213                 :          0 :         return size;
    1214                 :            : 
    1215                 :            : fail_lock:
    1216                 :          0 :         mutex_unlock(&ns->lock);
    1217                 :            : fail:
    1218                 :          0 :         error = audit_policy(op, GFP_KERNEL, name, info, error);
    1219                 :            : 
    1220         [ #  # ]:          0 :         list_for_each_entry_safe(ent, tmp, &lh, list) {
    1221                 :            :                 list_del_init(&ent->list);
    1222                 :          0 :                 aa_load_ent_free(ent);
    1223                 :            :         }
    1224                 :            : 
    1225                 :            :         goto out;
    1226                 :            : }
    1227                 :            : 
    1228                 :            : /**
    1229                 :            :  * aa_remove_profiles - remove profile(s) from the system
    1230                 :            :  * @fqname: name of the profile or namespace to remove  (NOT NULL)
    1231                 :            :  * @size: size of the name
    1232                 :            :  *
    1233                 :            :  * Remove a profile or sub namespace from the current namespace, so that
    1234                 :            :  * they can not be found anymore and mark them as replaced by unconfined
    1235                 :            :  *
    1236                 :            :  * NOTE: removing confinement does not restore rlimits to preconfinemnet values
    1237                 :            :  *
    1238                 :            :  * Returns: size of data consume else error code if fails
    1239                 :            :  */
    1240                 :          0 : ssize_t aa_remove_profiles(char *fqname, size_t size)
    1241                 :            : {
    1242                 :            :         struct aa_namespace *root, *ns = NULL;
    1243                 :            :         struct aa_profile *profile = NULL;
    1244                 :            :         const char *name = fqname, *info = NULL;
    1245                 :            :         ssize_t error = 0;
    1246                 :            : 
    1247         [ #  # ]:          0 :         if (*fqname == 0) {
    1248                 :            :                 info = "no profile specified";
    1249                 :            :                 error = -ENOENT;
    1250                 :            :                 goto fail;
    1251                 :            :         }
    1252                 :            : 
    1253                 :          0 :         root = aa_current_profile()->ns;
    1254                 :            : 
    1255         [ #  # ]:          0 :         if (fqname[0] == ':') {
    1256                 :            :                 char *ns_name;
    1257                 :          0 :                 name = aa_split_fqname(fqname, &ns_name);
    1258                 :            :                 /* released below */
    1259                 :          0 :                 ns = aa_find_namespace(root, ns_name);
    1260         [ #  # ]:          0 :                 if (!ns) {
    1261                 :            :                         info = "namespace does not exist";
    1262                 :            :                         error = -ENOENT;
    1263                 :          0 :                         goto fail;
    1264                 :            :                 }
    1265                 :            :         } else
    1266                 :            :                 /* released below */
    1267                 :            :                 ns = aa_get_namespace(root);
    1268                 :            : 
    1269         [ #  # ]:          0 :         if (!name) {
    1270                 :            :                 /* remove namespace - can only happen if fqname[0] == ':' */
    1271                 :          0 :                 mutex_lock(&ns->parent->lock);
    1272                 :          0 :                 __remove_namespace(ns);
    1273                 :          0 :                 mutex_unlock(&ns->parent->lock);
    1274                 :            :         } else {
    1275                 :            :                 /* remove profile */
    1276                 :          0 :                 mutex_lock(&ns->lock);
    1277                 :          0 :                 profile = aa_get_profile(__lookup_profile(&ns->base, name));
    1278         [ #  # ]:          0 :                 if (!profile) {
    1279                 :            :                         error = -ENOENT;
    1280                 :            :                         info = "profile does not exist";
    1281                 :            :                         goto fail_ns_lock;
    1282                 :            :                 }
    1283                 :          0 :                 name = profile->base.hname;
    1284                 :          0 :                 __remove_profile(profile);
    1285                 :          0 :                 mutex_unlock(&ns->lock);
    1286                 :            :         }
    1287                 :            : 
    1288                 :            :         /* don't fail removal if audit fails */
    1289                 :          0 :         (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
    1290                 :            :         aa_put_namespace(ns);
    1291                 :            :         aa_put_profile(profile);
    1292                 :          0 :         return size;
    1293                 :            : 
    1294                 :            : fail_ns_lock:
    1295                 :          0 :         mutex_unlock(&ns->lock);
    1296                 :            :         aa_put_namespace(ns);
    1297                 :            : 
    1298                 :            : fail:
    1299                 :          0 :         (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
    1300                 :          0 :         return error;
    1301                 :            : }

Generated by: LCOV version 1.9