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

Generated by: LCOV version 1.9