LCOV - code coverage report
Current view: top level - net/netlabel - netlabel_cipso_v4.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 201 0.0 %
Date: 2014-04-16 Functions: 0 11 0.0 %
Branches: 0 184 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * NetLabel CIPSO/IPv4 Support
       3                 :            :  *
       4                 :            :  * This file defines the CIPSO/IPv4 functions for the NetLabel system.  The
       5                 :            :  * NetLabel system manages static and dynamic label mappings for network
       6                 :            :  * protocols such as CIPSO and RIPSO.
       7                 :            :  *
       8                 :            :  * Author: Paul Moore <paul@paul-moore.com>
       9                 :            :  *
      10                 :            :  */
      11                 :            : 
      12                 :            : /*
      13                 :            :  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
      14                 :            :  *
      15                 :            :  * This program is free software;  you can redistribute it and/or modify
      16                 :            :  * it under the terms of the GNU General Public License as published by
      17                 :            :  * the Free Software Foundation; either version 2 of the License, or
      18                 :            :  * (at your option) any later version.
      19                 :            :  *
      20                 :            :  * This program is distributed in the hope that it will be useful,
      21                 :            :  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
      22                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
      23                 :            :  * the GNU General Public License for more details.
      24                 :            :  *
      25                 :            :  * You should have received a copy of the GNU General Public License
      26                 :            :  * along with this program;  if not, see <http://www.gnu.org/licenses/>.
      27                 :            :  *
      28                 :            :  */
      29                 :            : 
      30                 :            : #include <linux/types.h>
      31                 :            : #include <linux/socket.h>
      32                 :            : #include <linux/string.h>
      33                 :            : #include <linux/skbuff.h>
      34                 :            : #include <linux/audit.h>
      35                 :            : #include <linux/slab.h>
      36                 :            : #include <net/sock.h>
      37                 :            : #include <net/netlink.h>
      38                 :            : #include <net/genetlink.h>
      39                 :            : #include <net/netlabel.h>
      40                 :            : #include <net/cipso_ipv4.h>
      41                 :            : #include <linux/atomic.h>
      42                 :            : 
      43                 :            : #include "netlabel_user.h"
      44                 :            : #include "netlabel_cipso_v4.h"
      45                 :            : #include "netlabel_mgmt.h"
      46                 :            : #include "netlabel_domainhash.h"
      47                 :            : 
      48                 :            : /* Argument struct for cipso_v4_doi_walk() */
      49                 :            : struct netlbl_cipsov4_doiwalk_arg {
      50                 :            :         struct netlink_callback *nl_cb;
      51                 :            :         struct sk_buff *skb;
      52                 :            :         u32 seq;
      53                 :            : };
      54                 :            : 
      55                 :            : /* Argument struct for netlbl_domhsh_walk() */
      56                 :            : struct netlbl_domhsh_walk_arg {
      57                 :            :         struct netlbl_audit *audit_info;
      58                 :            :         u32 doi;
      59                 :            : };
      60                 :            : 
      61                 :            : /* NetLabel Generic NETLINK CIPSOv4 family */
      62                 :            : static struct genl_family netlbl_cipsov4_gnl_family = {
      63                 :            :         .id = GENL_ID_GENERATE,
      64                 :            :         .hdrsize = 0,
      65                 :            :         .name = NETLBL_NLTYPE_CIPSOV4_NAME,
      66                 :            :         .version = NETLBL_PROTO_VERSION,
      67                 :            :         .maxattr = NLBL_CIPSOV4_A_MAX,
      68                 :            : };
      69                 :            : 
      70                 :            : /* NetLabel Netlink attribute policy */
      71                 :            : static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
      72                 :            :         [NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
      73                 :            :         [NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
      74                 :            :         [NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
      75                 :            :         [NLBL_CIPSOV4_A_TAGLST] = { .type = NLA_NESTED },
      76                 :            :         [NLBL_CIPSOV4_A_MLSLVLLOC] = { .type = NLA_U32 },
      77                 :            :         [NLBL_CIPSOV4_A_MLSLVLREM] = { .type = NLA_U32 },
      78                 :            :         [NLBL_CIPSOV4_A_MLSLVL] = { .type = NLA_NESTED },
      79                 :            :         [NLBL_CIPSOV4_A_MLSLVLLST] = { .type = NLA_NESTED },
      80                 :            :         [NLBL_CIPSOV4_A_MLSCATLOC] = { .type = NLA_U32 },
      81                 :            :         [NLBL_CIPSOV4_A_MLSCATREM] = { .type = NLA_U32 },
      82                 :            :         [NLBL_CIPSOV4_A_MLSCAT] = { .type = NLA_NESTED },
      83                 :            :         [NLBL_CIPSOV4_A_MLSCATLST] = { .type = NLA_NESTED },
      84                 :            : };
      85                 :            : 
      86                 :            : /*
      87                 :            :  * Helper Functions
      88                 :            :  */
      89                 :            : 
      90                 :            : /**
      91                 :            :  * netlbl_cipsov4_add_common - Parse the common sections of a ADD message
      92                 :            :  * @info: the Generic NETLINK info block
      93                 :            :  * @doi_def: the CIPSO V4 DOI definition
      94                 :            :  *
      95                 :            :  * Description:
      96                 :            :  * Parse the common sections of a ADD message and fill in the related values
      97                 :            :  * in @doi_def.  Returns zero on success, negative values on failure.
      98                 :            :  *
      99                 :            :  */
     100                 :          0 : static int netlbl_cipsov4_add_common(struct genl_info *info,
     101                 :            :                                      struct cipso_v4_doi *doi_def)
     102                 :            : {
     103                 :          0 :         struct nlattr *nla;
     104                 :            :         int nla_rem;
     105                 :            :         u32 iter = 0;
     106                 :            : 
     107                 :          0 :         doi_def->doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
     108                 :            : 
     109         [ #  # ]:          0 :         if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_TAGLST],
     110                 :            :                                 NLBL_CIPSOV4_A_MAX,
     111                 :            :                                 netlbl_cipsov4_genl_policy) != 0)
     112                 :            :                 return -EINVAL;
     113                 :            : 
     114         [ #  # ]:          0 :         nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem)
     115         [ #  # ]:          0 :                 if (nla_type(nla) == NLBL_CIPSOV4_A_TAG) {
     116         [ #  # ]:          0 :                         if (iter >= CIPSO_V4_TAG_MAXCNT)
     117                 :            :                                 return -EINVAL;
     118                 :          0 :                         doi_def->tags[iter++] = nla_get_u8(nla);
     119                 :            :                 }
     120         [ #  # ]:          0 :         while (iter < CIPSO_V4_TAG_MAXCNT)
     121                 :          0 :                 doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID;
     122                 :            : 
     123                 :            :         return 0;
     124                 :            : }
     125                 :            : 
     126                 :            : /*
     127                 :            :  * NetLabel Command Handlers
     128                 :            :  */
     129                 :            : 
     130                 :            : /**
     131                 :            :  * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
     132                 :            :  * @info: the Generic NETLINK info block
     133                 :            :  * @audit_info: NetLabel audit information
     134                 :            :  *
     135                 :            :  * Description:
     136                 :            :  * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD
     137                 :            :  * message and add it to the CIPSO V4 engine.  Return zero on success and
     138                 :            :  * non-zero on error.
     139                 :            :  *
     140                 :            :  */
     141                 :          0 : static int netlbl_cipsov4_add_std(struct genl_info *info,
     142                 :            :                                   struct netlbl_audit *audit_info)
     143                 :            : {
     144                 :            :         int ret_val = -EINVAL;
     145                 :            :         struct cipso_v4_doi *doi_def = NULL;
     146                 :          0 :         struct nlattr *nla_a;
     147                 :          0 :         struct nlattr *nla_b;
     148                 :            :         int nla_a_rem;
     149                 :            :         int nla_b_rem;
     150                 :            :         u32 iter;
     151                 :            : 
     152 [ #  # ][ #  # ]:          0 :         if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
     153                 :          0 :             !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
     154                 :            :                 return -EINVAL;
     155                 :            : 
     156         [ #  # ]:          0 :         if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
     157                 :            :                                 NLBL_CIPSOV4_A_MAX,
     158                 :            :                                 netlbl_cipsov4_genl_policy) != 0)
     159                 :            :                 return -EINVAL;
     160                 :            : 
     161                 :            :         doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
     162         [ #  # ]:          0 :         if (doi_def == NULL)
     163                 :            :                 return -ENOMEM;
     164                 :          0 :         doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
     165         [ #  # ]:          0 :         if (doi_def->map.std == NULL) {
     166                 :            :                 ret_val = -ENOMEM;
     167                 :            :                 goto add_std_failure;
     168                 :            :         }
     169                 :          0 :         doi_def->type = CIPSO_V4_MAP_TRANS;
     170                 :            : 
     171                 :          0 :         ret_val = netlbl_cipsov4_add_common(info, doi_def);
     172         [ #  # ]:          0 :         if (ret_val != 0)
     173                 :            :                 goto add_std_failure;
     174                 :            :         ret_val = -EINVAL;
     175                 :            : 
     176         [ #  # ]:          0 :         nla_for_each_nested(nla_a,
     177                 :            :                             info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
     178                 :            :                             nla_a_rem)
     179         [ #  # ]:          0 :                 if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
     180         [ #  # ]:          0 :                         if (nla_validate_nested(nla_a,
     181                 :            :                                             NLBL_CIPSOV4_A_MAX,
     182                 :            :                                             netlbl_cipsov4_genl_policy) != 0)
     183                 :            :                                         goto add_std_failure;
     184         [ #  # ]:          0 :                         nla_for_each_nested(nla_b, nla_a, nla_b_rem)
     185      [ #  #  # ]:          0 :                                 switch (nla_type(nla_b)) {
     186                 :            :                                 case NLBL_CIPSOV4_A_MLSLVLLOC:
     187         [ #  # ]:          0 :                                         if (nla_get_u32(nla_b) >
     188                 :            :                                             CIPSO_V4_MAX_LOC_LVLS)
     189                 :            :                                                 goto add_std_failure;
     190         [ #  # ]:          0 :                                         if (nla_get_u32(nla_b) >=
     191                 :          0 :                                             doi_def->map.std->lvl.local_size)
     192                 :          0 :                                              doi_def->map.std->lvl.local_size =
     193                 :          0 :                                                      nla_get_u32(nla_b) + 1;
     194                 :            :                                         break;
     195                 :            :                                 case NLBL_CIPSOV4_A_MLSLVLREM:
     196         [ #  # ]:          0 :                                         if (nla_get_u32(nla_b) >
     197                 :            :                                             CIPSO_V4_MAX_REM_LVLS)
     198                 :            :                                                 goto add_std_failure;
     199         [ #  # ]:          0 :                                         if (nla_get_u32(nla_b) >=
     200                 :          0 :                                             doi_def->map.std->lvl.cipso_size)
     201                 :          0 :                                              doi_def->map.std->lvl.cipso_size =
     202                 :          0 :                                                      nla_get_u32(nla_b) + 1;
     203                 :            :                                         break;
     204                 :            :                                 }
     205                 :            :                 }
     206                 :          0 :         doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
     207                 :            :                                               sizeof(u32),
     208                 :            :                                               GFP_KERNEL);
     209         [ #  # ]:          0 :         if (doi_def->map.std->lvl.local == NULL) {
     210                 :            :                 ret_val = -ENOMEM;
     211                 :            :                 goto add_std_failure;
     212                 :            :         }
     213                 :          0 :         doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
     214                 :            :                                               sizeof(u32),
     215                 :            :                                               GFP_KERNEL);
     216         [ #  # ]:          0 :         if (doi_def->map.std->lvl.cipso == NULL) {
     217                 :            :                 ret_val = -ENOMEM;
     218                 :            :                 goto add_std_failure;
     219                 :            :         }
     220         [ #  # ]:          0 :         for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
     221                 :          0 :                 doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
     222         [ #  # ]:          0 :         for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
     223                 :          0 :                 doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
     224         [ #  # ]:          0 :         nla_for_each_nested(nla_a,
     225                 :            :                             info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
     226                 :            :                             nla_a_rem)
     227         [ #  # ]:          0 :                 if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSLVL) {
     228                 :            :                         struct nlattr *lvl_loc;
     229                 :            :                         struct nlattr *lvl_rem;
     230                 :            : 
     231                 :            :                         lvl_loc = nla_find_nested(nla_a,
     232                 :            :                                                   NLBL_CIPSOV4_A_MLSLVLLOC);
     233                 :            :                         lvl_rem = nla_find_nested(nla_a,
     234                 :            :                                                   NLBL_CIPSOV4_A_MLSLVLREM);
     235         [ #  # ]:          0 :                         if (lvl_loc == NULL || lvl_rem == NULL)
     236                 :            :                                 goto add_std_failure;
     237                 :          0 :                         doi_def->map.std->lvl.local[nla_get_u32(lvl_loc)] =
     238                 :            :                                 nla_get_u32(lvl_rem);
     239                 :          0 :                         doi_def->map.std->lvl.cipso[nla_get_u32(lvl_rem)] =
     240                 :            :                                 nla_get_u32(lvl_loc);
     241                 :            :                 }
     242                 :            : 
     243         [ #  # ]:          0 :         if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
     244         [ #  # ]:          0 :                 if (nla_validate_nested(info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
     245                 :            :                                         NLBL_CIPSOV4_A_MAX,
     246                 :            :                                         netlbl_cipsov4_genl_policy) != 0)
     247                 :            :                         goto add_std_failure;
     248                 :            : 
     249         [ #  # ]:          0 :                 nla_for_each_nested(nla_a,
     250                 :            :                                     info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
     251                 :            :                                     nla_a_rem)
     252         [ #  # ]:          0 :                         if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
     253         [ #  # ]:          0 :                                 if (nla_validate_nested(nla_a,
     254                 :            :                                               NLBL_CIPSOV4_A_MAX,
     255                 :            :                                               netlbl_cipsov4_genl_policy) != 0)
     256                 :            :                                         goto add_std_failure;
     257         [ #  # ]:          0 :                                 nla_for_each_nested(nla_b, nla_a, nla_b_rem)
     258      [ #  #  # ]:          0 :                                         switch (nla_type(nla_b)) {
     259                 :            :                                         case NLBL_CIPSOV4_A_MLSCATLOC:
     260         [ #  # ]:          0 :                                                 if (nla_get_u32(nla_b) >
     261                 :            :                                                     CIPSO_V4_MAX_LOC_CATS)
     262                 :            :                                                         goto add_std_failure;
     263         [ #  # ]:          0 :                                                 if (nla_get_u32(nla_b) >=
     264                 :          0 :                                               doi_def->map.std->cat.local_size)
     265                 :          0 :                                              doi_def->map.std->cat.local_size =
     266                 :          0 :                                                      nla_get_u32(nla_b) + 1;
     267                 :            :                                                 break;
     268                 :            :                                         case NLBL_CIPSOV4_A_MLSCATREM:
     269         [ #  # ]:          0 :                                                 if (nla_get_u32(nla_b) >
     270                 :            :                                                     CIPSO_V4_MAX_REM_CATS)
     271                 :            :                                                         goto add_std_failure;
     272         [ #  # ]:          0 :                                                 if (nla_get_u32(nla_b) >=
     273                 :          0 :                                               doi_def->map.std->cat.cipso_size)
     274                 :          0 :                                              doi_def->map.std->cat.cipso_size =
     275                 :          0 :                                                      nla_get_u32(nla_b) + 1;
     276                 :            :                                                 break;
     277                 :            :                                         }
     278                 :            :                         }
     279                 :          0 :                 doi_def->map.std->cat.local = kcalloc(
     280                 :          0 :                                               doi_def->map.std->cat.local_size,
     281                 :            :                                               sizeof(u32),
     282                 :            :                                               GFP_KERNEL);
     283         [ #  # ]:          0 :                 if (doi_def->map.std->cat.local == NULL) {
     284                 :            :                         ret_val = -ENOMEM;
     285                 :            :                         goto add_std_failure;
     286                 :            :                 }
     287                 :          0 :                 doi_def->map.std->cat.cipso = kcalloc(
     288                 :            :                                               doi_def->map.std->cat.cipso_size,
     289                 :            :                                               sizeof(u32),
     290                 :            :                                               GFP_KERNEL);
     291         [ #  # ]:          0 :                 if (doi_def->map.std->cat.cipso == NULL) {
     292                 :            :                         ret_val = -ENOMEM;
     293                 :            :                         goto add_std_failure;
     294                 :            :                 }
     295         [ #  # ]:          0 :                 for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
     296                 :          0 :                         doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
     297         [ #  # ]:          0 :                 for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
     298                 :          0 :                         doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
     299         [ #  # ]:          0 :                 nla_for_each_nested(nla_a,
     300                 :            :                                     info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
     301                 :            :                                     nla_a_rem)
     302         [ #  # ]:          0 :                         if (nla_type(nla_a) == NLBL_CIPSOV4_A_MLSCAT) {
     303                 :            :                                 struct nlattr *cat_loc;
     304                 :            :                                 struct nlattr *cat_rem;
     305                 :            : 
     306                 :            :                                 cat_loc = nla_find_nested(nla_a,
     307                 :            :                                                      NLBL_CIPSOV4_A_MLSCATLOC);
     308                 :            :                                 cat_rem = nla_find_nested(nla_a,
     309                 :            :                                                      NLBL_CIPSOV4_A_MLSCATREM);
     310         [ #  # ]:          0 :                                 if (cat_loc == NULL || cat_rem == NULL)
     311                 :            :                                         goto add_std_failure;
     312                 :          0 :                                 doi_def->map.std->cat.local[
     313                 :          0 :                                                         nla_get_u32(cat_loc)] =
     314                 :            :                                         nla_get_u32(cat_rem);
     315                 :          0 :                                 doi_def->map.std->cat.cipso[
     316                 :          0 :                                                         nla_get_u32(cat_rem)] =
     317                 :            :                                         nla_get_u32(cat_loc);
     318                 :            :                         }
     319                 :            :         }
     320                 :            : 
     321                 :          0 :         ret_val = cipso_v4_doi_add(doi_def, audit_info);
     322         [ #  # ]:          0 :         if (ret_val != 0)
     323                 :            :                 goto add_std_failure;
     324                 :            :         return 0;
     325                 :            : 
     326                 :            : add_std_failure:
     327         [ #  # ]:          0 :         if (doi_def)
     328                 :          0 :                 cipso_v4_doi_free(doi_def);
     329                 :          0 :         return ret_val;
     330                 :            : }
     331                 :            : 
     332                 :            : /**
     333                 :            :  * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
     334                 :            :  * @info: the Generic NETLINK info block
     335                 :            :  * @audit_info: NetLabel audit information
     336                 :            :  *
     337                 :            :  * Description:
     338                 :            :  * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
     339                 :            :  * and add it to the CIPSO V4 engine.  Return zero on success and non-zero on
     340                 :            :  * error.
     341                 :            :  *
     342                 :            :  */
     343                 :          0 : static int netlbl_cipsov4_add_pass(struct genl_info *info,
     344                 :            :                                    struct netlbl_audit *audit_info)
     345                 :            : {
     346                 :            :         int ret_val;
     347                 :            :         struct cipso_v4_doi *doi_def = NULL;
     348                 :            : 
     349         [ #  # ]:          0 :         if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
     350                 :            :                 return -EINVAL;
     351                 :            : 
     352                 :            :         doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
     353         [ #  # ]:          0 :         if (doi_def == NULL)
     354                 :            :                 return -ENOMEM;
     355                 :          0 :         doi_def->type = CIPSO_V4_MAP_PASS;
     356                 :            : 
     357                 :          0 :         ret_val = netlbl_cipsov4_add_common(info, doi_def);
     358         [ #  # ]:          0 :         if (ret_val != 0)
     359                 :            :                 goto add_pass_failure;
     360                 :            : 
     361                 :          0 :         ret_val = cipso_v4_doi_add(doi_def, audit_info);
     362         [ #  # ]:          0 :         if (ret_val != 0)
     363                 :            :                 goto add_pass_failure;
     364                 :            :         return 0;
     365                 :            : 
     366                 :            : add_pass_failure:
     367                 :          0 :         cipso_v4_doi_free(doi_def);
     368                 :          0 :         return ret_val;
     369                 :            : }
     370                 :            : 
     371                 :            : /**
     372                 :            :  * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition
     373                 :            :  * @info: the Generic NETLINK info block
     374                 :            :  * @audit_info: NetLabel audit information
     375                 :            :  *
     376                 :            :  * Description:
     377                 :            :  * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD
     378                 :            :  * message and add it to the CIPSO V4 engine.  Return zero on success and
     379                 :            :  * non-zero on error.
     380                 :            :  *
     381                 :            :  */
     382                 :          0 : static int netlbl_cipsov4_add_local(struct genl_info *info,
     383                 :            :                                     struct netlbl_audit *audit_info)
     384                 :            : {
     385                 :            :         int ret_val;
     386                 :            :         struct cipso_v4_doi *doi_def = NULL;
     387                 :            : 
     388         [ #  # ]:          0 :         if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
     389                 :            :                 return -EINVAL;
     390                 :            : 
     391                 :            :         doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
     392         [ #  # ]:          0 :         if (doi_def == NULL)
     393                 :            :                 return -ENOMEM;
     394                 :          0 :         doi_def->type = CIPSO_V4_MAP_LOCAL;
     395                 :            : 
     396                 :          0 :         ret_val = netlbl_cipsov4_add_common(info, doi_def);
     397         [ #  # ]:          0 :         if (ret_val != 0)
     398                 :            :                 goto add_local_failure;
     399                 :            : 
     400                 :          0 :         ret_val = cipso_v4_doi_add(doi_def, audit_info);
     401         [ #  # ]:          0 :         if (ret_val != 0)
     402                 :            :                 goto add_local_failure;
     403                 :            :         return 0;
     404                 :            : 
     405                 :            : add_local_failure:
     406                 :          0 :         cipso_v4_doi_free(doi_def);
     407                 :          0 :         return ret_val;
     408                 :            : }
     409                 :            : 
     410                 :            : /**
     411                 :            :  * netlbl_cipsov4_add - Handle an ADD message
     412                 :            :  * @skb: the NETLINK buffer
     413                 :            :  * @info: the Generic NETLINK info block
     414                 :            :  *
     415                 :            :  * Description:
     416                 :            :  * Create a new DOI definition based on the given ADD message and add it to the
     417                 :            :  * CIPSO V4 engine.  Returns zero on success, negative values on failure.
     418                 :            :  *
     419                 :            :  */
     420                 :          0 : static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
     421                 :            : 
     422                 :            : {
     423                 :            :         int ret_val = -EINVAL;
     424                 :            :         struct netlbl_audit audit_info;
     425                 :            : 
     426 [ #  # ][ #  # ]:          0 :         if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
     427                 :          0 :             !info->attrs[NLBL_CIPSOV4_A_MTYPE])
     428                 :            :                 return -EINVAL;
     429                 :            : 
     430                 :            :         netlbl_netlink_auditinfo(skb, &audit_info);
     431   [ #  #  #  # ]:          0 :         switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) {
     432                 :            :         case CIPSO_V4_MAP_TRANS:
     433                 :          0 :                 ret_val = netlbl_cipsov4_add_std(info, &audit_info);
     434                 :          0 :                 break;
     435                 :            :         case CIPSO_V4_MAP_PASS:
     436                 :          0 :                 ret_val = netlbl_cipsov4_add_pass(info, &audit_info);
     437                 :          0 :                 break;
     438                 :            :         case CIPSO_V4_MAP_LOCAL:
     439                 :          0 :                 ret_val = netlbl_cipsov4_add_local(info, &audit_info);
     440                 :          0 :                 break;
     441                 :            :         }
     442         [ #  # ]:          0 :         if (ret_val == 0)
     443                 :            :                 atomic_inc(&netlabel_mgmt_protocount);
     444                 :            : 
     445                 :          0 :         return ret_val;
     446                 :            : }
     447                 :            : 
     448                 :            : /**
     449                 :            :  * netlbl_cipsov4_list - Handle a LIST message
     450                 :            :  * @skb: the NETLINK buffer
     451                 :            :  * @info: the Generic NETLINK info block
     452                 :            :  *
     453                 :            :  * Description:
     454                 :            :  * Process a user generated LIST message and respond accordingly.  While the
     455                 :            :  * response message generated by the kernel is straightforward, determining
     456                 :            :  * before hand the size of the buffer to allocate is not (we have to generate
     457                 :            :  * the message to know the size).  In order to keep this function sane what we
     458                 :            :  * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
     459                 :            :  * that size, if we fail then we restart with a larger buffer and try again.
     460                 :            :  * We continue in this manner until we hit a limit of failed attempts then we
     461                 :            :  * give up and just send an error message.  Returns zero on success and
     462                 :            :  * negative values on error.
     463                 :            :  *
     464                 :            :  */
     465                 :          0 : static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
     466                 :            : {
     467                 :            :         int ret_val;
     468                 :            :         struct sk_buff *ans_skb = NULL;
     469                 :            :         u32 nlsze_mult = 1;
     470                 :            :         void *data;
     471                 :            :         u32 doi;
     472                 :            :         struct nlattr *nla_a;
     473                 :            :         struct nlattr *nla_b;
     474                 :            :         struct cipso_v4_doi *doi_def;
     475                 :            :         u32 iter;
     476                 :            : 
     477         [ #  # ]:          0 :         if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
     478                 :            :                 ret_val = -EINVAL;
     479                 :            :                 goto list_failure;
     480                 :            :         }
     481                 :            : 
     482                 :            : list_start:
     483                 :          0 :         ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL);
     484         [ #  # ]:          0 :         if (ans_skb == NULL) {
     485                 :            :                 ret_val = -ENOMEM;
     486                 :            :                 goto list_failure;
     487                 :            :         }
     488                 :            :         data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family,
     489                 :            :                                  0, NLBL_CIPSOV4_C_LIST);
     490         [ #  # ]:          0 :         if (data == NULL) {
     491                 :            :                 ret_val = -ENOMEM;
     492                 :            :                 goto list_failure;
     493                 :            :         }
     494                 :            : 
     495                 :          0 :         doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
     496                 :            : 
     497                 :            :         rcu_read_lock();
     498                 :          0 :         doi_def = cipso_v4_doi_getdef(doi);
     499         [ #  # ]:          0 :         if (doi_def == NULL) {
     500                 :            :                 ret_val = -EINVAL;
     501                 :            :                 goto list_failure_lock;
     502                 :            :         }
     503                 :            : 
     504                 :          0 :         ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
     505         [ #  # ]:          0 :         if (ret_val != 0)
     506                 :            :                 goto list_failure_lock;
     507                 :            : 
     508                 :            :         nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST);
     509         [ #  # ]:          0 :         if (nla_a == NULL) {
     510                 :            :                 ret_val = -ENOMEM;
     511                 :            :                 goto list_failure_lock;
     512                 :            :         }
     513         [ #  # ]:          0 :         for (iter = 0;
     514         [ #  # ]:          0 :              iter < CIPSO_V4_TAG_MAXCNT &&
     515                 :          0 :                doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
     516                 :          0 :              iter++) {
     517                 :            :                 ret_val = nla_put_u8(ans_skb,
     518                 :            :                                      NLBL_CIPSOV4_A_TAG,
     519                 :            :                                      doi_def->tags[iter]);
     520         [ #  # ]:          0 :                 if (ret_val != 0)
     521                 :            :                         goto list_failure_lock;
     522                 :            :         }
     523                 :            :         nla_nest_end(ans_skb, nla_a);
     524                 :            : 
     525         [ #  # ]:          0 :         switch (doi_def->type) {
     526                 :            :         case CIPSO_V4_MAP_TRANS:
     527                 :            :                 nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
     528         [ #  # ]:          0 :                 if (nla_a == NULL) {
     529                 :            :                         ret_val = -ENOMEM;
     530                 :            :                         goto list_failure_lock;
     531                 :            :                 }
     532         [ #  # ]:          0 :                 for (iter = 0;
     533                 :          0 :                      iter < doi_def->map.std->lvl.local_size;
     534                 :          0 :                      iter++) {
     535         [ #  # ]:          0 :                         if (doi_def->map.std->lvl.local[iter] ==
     536                 :            :                             CIPSO_V4_INV_LVL)
     537                 :          0 :                                 continue;
     538                 :            : 
     539                 :            :                         nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL);
     540         [ #  # ]:          0 :                         if (nla_b == NULL) {
     541                 :            :                                 ret_val = -ENOMEM;
     542                 :            :                                 goto list_retry;
     543                 :            :                         }
     544                 :            :                         ret_val = nla_put_u32(ans_skb,
     545                 :            :                                               NLBL_CIPSOV4_A_MLSLVLLOC,
     546                 :            :                                               iter);
     547         [ #  # ]:          0 :                         if (ret_val != 0)
     548                 :            :                                 goto list_retry;
     549                 :          0 :                         ret_val = nla_put_u32(ans_skb,
     550                 :            :                                             NLBL_CIPSOV4_A_MLSLVLREM,
     551                 :          0 :                                             doi_def->map.std->lvl.local[iter]);
     552         [ #  # ]:          0 :                         if (ret_val != 0)
     553                 :            :                                 goto list_retry;
     554                 :            :                         nla_nest_end(ans_skb, nla_b);
     555                 :            :                 }
     556                 :            :                 nla_nest_end(ans_skb, nla_a);
     557                 :            : 
     558                 :            :                 nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST);
     559         [ #  # ]:          0 :                 if (nla_a == NULL) {
     560                 :            :                         ret_val = -ENOMEM;
     561                 :            :                         goto list_retry;
     562                 :            :                 }
     563         [ #  # ]:          0 :                 for (iter = 0;
     564                 :          0 :                      iter < doi_def->map.std->cat.local_size;
     565                 :          0 :                      iter++) {
     566         [ #  # ]:          0 :                         if (doi_def->map.std->cat.local[iter] ==
     567                 :            :                             CIPSO_V4_INV_CAT)
     568                 :          0 :                                 continue;
     569                 :            : 
     570                 :            :                         nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT);
     571         [ #  # ]:          0 :                         if (nla_b == NULL) {
     572                 :            :                                 ret_val = -ENOMEM;
     573                 :            :                                 goto list_retry;
     574                 :            :                         }
     575                 :            :                         ret_val = nla_put_u32(ans_skb,
     576                 :            :                                               NLBL_CIPSOV4_A_MLSCATLOC,
     577                 :            :                                               iter);
     578         [ #  # ]:          0 :                         if (ret_val != 0)
     579                 :            :                                 goto list_retry;
     580                 :          0 :                         ret_val = nla_put_u32(ans_skb,
     581                 :            :                                             NLBL_CIPSOV4_A_MLSCATREM,
     582                 :          0 :                                             doi_def->map.std->cat.local[iter]);
     583         [ #  # ]:          0 :                         if (ret_val != 0)
     584                 :            :                                 goto list_retry;
     585                 :            :                         nla_nest_end(ans_skb, nla_b);
     586                 :            :                 }
     587                 :            :                 nla_nest_end(ans_skb, nla_a);
     588                 :            : 
     589                 :            :                 break;
     590                 :            :         }
     591                 :            :         rcu_read_unlock();
     592                 :            : 
     593                 :            :         genlmsg_end(ans_skb, data);
     594                 :          0 :         return genlmsg_reply(ans_skb, info);
     595                 :            : 
     596                 :            : list_retry:
     597                 :            :         /* XXX - this limit is a guesstimate */
     598         [ #  # ]:          0 :         if (nlsze_mult < 4) {
     599                 :            :                 rcu_read_unlock();
     600                 :          0 :                 kfree_skb(ans_skb);
     601                 :          0 :                 nlsze_mult *= 2;
     602                 :          0 :                 goto list_start;
     603                 :            :         }
     604                 :            : list_failure_lock:
     605                 :            :         rcu_read_unlock();
     606                 :            : list_failure:
     607                 :          0 :         kfree_skb(ans_skb);
     608                 :          0 :         return ret_val;
     609                 :            : }
     610                 :            : 
     611                 :            : /**
     612                 :            :  * netlbl_cipsov4_listall_cb - cipso_v4_doi_walk() callback for LISTALL
     613                 :            :  * @doi_def: the CIPSOv4 DOI definition
     614                 :            :  * @arg: the netlbl_cipsov4_doiwalk_arg structure
     615                 :            :  *
     616                 :            :  * Description:
     617                 :            :  * This function is designed to be used as a callback to the
     618                 :            :  * cipso_v4_doi_walk() function for use in generating a response for a LISTALL
     619                 :            :  * message.  Returns the size of the message on success, negative values on
     620                 :            :  * failure.
     621                 :            :  *
     622                 :            :  */
     623                 :          0 : static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg)
     624                 :            : {
     625                 :            :         int ret_val = -ENOMEM;
     626                 :            :         struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg;
     627                 :            :         void *data;
     628                 :            : 
     629                 :          0 :         data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
     630                 :            :                            cb_arg->seq, &netlbl_cipsov4_gnl_family,
     631                 :            :                            NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL);
     632         [ #  # ]:          0 :         if (data == NULL)
     633                 :            :                 goto listall_cb_failure;
     634                 :            : 
     635                 :          0 :         ret_val = nla_put_u32(cb_arg->skb, NLBL_CIPSOV4_A_DOI, doi_def->doi);
     636         [ #  # ]:          0 :         if (ret_val != 0)
     637                 :            :                 goto listall_cb_failure;
     638                 :          0 :         ret_val = nla_put_u32(cb_arg->skb,
     639                 :            :                               NLBL_CIPSOV4_A_MTYPE,
     640                 :            :                               doi_def->type);
     641         [ #  # ]:          0 :         if (ret_val != 0)
     642                 :            :                 goto listall_cb_failure;
     643                 :            : 
     644                 :          0 :         return genlmsg_end(cb_arg->skb, data);
     645                 :            : 
     646                 :            : listall_cb_failure:
     647                 :          0 :         genlmsg_cancel(cb_arg->skb, data);
     648                 :          0 :         return ret_val;
     649                 :            : }
     650                 :            : 
     651                 :            : /**
     652                 :            :  * netlbl_cipsov4_listall - Handle a LISTALL message
     653                 :            :  * @skb: the NETLINK buffer
     654                 :            :  * @cb: the NETLINK callback
     655                 :            :  *
     656                 :            :  * Description:
     657                 :            :  * Process a user generated LISTALL message and respond accordingly.  Returns
     658                 :            :  * zero on success and negative values on error.
     659                 :            :  *
     660                 :            :  */
     661                 :          0 : static int netlbl_cipsov4_listall(struct sk_buff *skb,
     662                 :            :                                   struct netlink_callback *cb)
     663                 :            : {
     664                 :            :         struct netlbl_cipsov4_doiwalk_arg cb_arg;
     665                 :          0 :         u32 doi_skip = cb->args[0];
     666                 :            : 
     667                 :          0 :         cb_arg.nl_cb = cb;
     668                 :          0 :         cb_arg.skb = skb;
     669                 :          0 :         cb_arg.seq = cb->nlh->nlmsg_seq;
     670                 :            : 
     671                 :          0 :         cipso_v4_doi_walk(&doi_skip, netlbl_cipsov4_listall_cb, &cb_arg);
     672                 :            : 
     673                 :          0 :         cb->args[0] = doi_skip;
     674                 :          0 :         return skb->len;
     675                 :            : }
     676                 :            : 
     677                 :            : /**
     678                 :            :  * netlbl_cipsov4_remove_cb - netlbl_cipsov4_remove() callback for REMOVE
     679                 :            :  * @entry: LSM domain mapping entry
     680                 :            :  * @arg: the netlbl_domhsh_walk_arg structure
     681                 :            :  *
     682                 :            :  * Description:
     683                 :            :  * This function is intended for use by netlbl_cipsov4_remove() as the callback
     684                 :            :  * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
     685                 :            :  * which are associated with the CIPSO DOI specified in @arg.  Returns zero on
     686                 :            :  * success, negative values on failure.
     687                 :            :  *
     688                 :            :  */
     689                 :          0 : static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg)
     690                 :            : {
     691                 :            :         struct netlbl_domhsh_walk_arg *cb_arg = arg;
     692                 :            : 
     693 [ #  # ][ #  # ]:          0 :         if (entry->def.type == NETLBL_NLTYPE_CIPSOV4 &&
     694                 :          0 :             entry->def.cipso->doi == cb_arg->doi)
     695                 :          0 :                 return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
     696                 :            : 
     697                 :            :         return 0;
     698                 :            : }
     699                 :            : 
     700                 :            : /**
     701                 :            :  * netlbl_cipsov4_remove - Handle a REMOVE message
     702                 :            :  * @skb: the NETLINK buffer
     703                 :            :  * @info: the Generic NETLINK info block
     704                 :            :  *
     705                 :            :  * Description:
     706                 :            :  * Process a user generated REMOVE message and respond accordingly.  Returns
     707                 :            :  * zero on success, negative values on failure.
     708                 :            :  *
     709                 :            :  */
     710                 :          0 : static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
     711                 :            : {
     712                 :            :         int ret_val = -EINVAL;
     713                 :            :         struct netlbl_domhsh_walk_arg cb_arg;
     714                 :            :         struct netlbl_audit audit_info;
     715                 :          0 :         u32 skip_bkt = 0;
     716                 :          0 :         u32 skip_chain = 0;
     717                 :            : 
     718         [ #  # ]:          0 :         if (!info->attrs[NLBL_CIPSOV4_A_DOI])
     719                 :            :                 return -EINVAL;
     720                 :            : 
     721                 :            :         netlbl_netlink_auditinfo(skb, &audit_info);
     722                 :          0 :         cb_arg.doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
     723                 :          0 :         cb_arg.audit_info = &audit_info;
     724                 :          0 :         ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
     725                 :            :                                      netlbl_cipsov4_remove_cb, &cb_arg);
     726         [ #  # ]:          0 :         if (ret_val == 0 || ret_val == -ENOENT) {
     727                 :          0 :                 ret_val = cipso_v4_doi_remove(cb_arg.doi, &audit_info);
     728         [ #  # ]:          0 :                 if (ret_val == 0)
     729                 :            :                         atomic_dec(&netlabel_mgmt_protocount);
     730                 :            :         }
     731                 :            : 
     732                 :          0 :         return ret_val;
     733                 :            : }
     734                 :            : 
     735                 :            : /*
     736                 :            :  * NetLabel Generic NETLINK Command Definitions
     737                 :            :  */
     738                 :            : 
     739                 :            : static const struct genl_ops netlbl_cipsov4_ops[] = {
     740                 :            :         {
     741                 :            :         .cmd = NLBL_CIPSOV4_C_ADD,
     742                 :            :         .flags = GENL_ADMIN_PERM,
     743                 :            :         .policy = netlbl_cipsov4_genl_policy,
     744                 :            :         .doit = netlbl_cipsov4_add,
     745                 :            :         .dumpit = NULL,
     746                 :            :         },
     747                 :            :         {
     748                 :            :         .cmd = NLBL_CIPSOV4_C_REMOVE,
     749                 :            :         .flags = GENL_ADMIN_PERM,
     750                 :            :         .policy = netlbl_cipsov4_genl_policy,
     751                 :            :         .doit = netlbl_cipsov4_remove,
     752                 :            :         .dumpit = NULL,
     753                 :            :         },
     754                 :            :         {
     755                 :            :         .cmd = NLBL_CIPSOV4_C_LIST,
     756                 :            :         .flags = 0,
     757                 :            :         .policy = netlbl_cipsov4_genl_policy,
     758                 :            :         .doit = netlbl_cipsov4_list,
     759                 :            :         .dumpit = NULL,
     760                 :            :         },
     761                 :            :         {
     762                 :            :         .cmd = NLBL_CIPSOV4_C_LISTALL,
     763                 :            :         .flags = 0,
     764                 :            :         .policy = netlbl_cipsov4_genl_policy,
     765                 :            :         .doit = NULL,
     766                 :            :         .dumpit = netlbl_cipsov4_listall,
     767                 :            :         },
     768                 :            : };
     769                 :            : 
     770                 :            : /*
     771                 :            :  * NetLabel Generic NETLINK Protocol Functions
     772                 :            :  */
     773                 :            : 
     774                 :            : /**
     775                 :            :  * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component
     776                 :            :  *
     777                 :            :  * Description:
     778                 :            :  * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK
     779                 :            :  * mechanism.  Returns zero on success, negative values on failure.
     780                 :            :  *
     781                 :            :  */
     782                 :          0 : int __init netlbl_cipsov4_genl_init(void)
     783                 :            : {
     784                 :          0 :         return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family,
     785                 :            :                                              netlbl_cipsov4_ops);
     786                 :            : }

Generated by: LCOV version 1.9