LCOV - code coverage report
Current view: top level - net/netlabel - netlabel_cipso_v4.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 2 317 0.6 %
Date: 2022-04-01 13:59:58 Functions: 1 10 10.0 %
Branches: 0 184 0.0 %

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

Generated by: LCOV version 1.14