]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
cipso: Add support for native local labeling and fixup mapping names
authorPaul Moore <paul.moore@hp.com>
Fri, 10 Oct 2008 14:16:34 +0000 (10:16 -0400)
committerPaul Moore <paul.moore@hp.com>
Fri, 10 Oct 2008 14:16:34 +0000 (10:16 -0400)
This patch accomplishes three minor tasks: add a new tag type for local
labeling, rename the CIPSO_V4_MAP_STD define to CIPSO_V4_MAP_TRANS and
replace some of the CIPSO "magic numbers" with constants from the header
file.  The first change allows CIPSO to support full LSM labels/contexts,
not just MLS attributes.  The second change brings the mapping names inline
with what userspace is using, compatibility is preserved since we don't
actually change the value.  The last change is to aid readability and help
prevent mistakes.

Signed-off-by: Paul Moore <paul.moore@hp.com>
include/net/cipso_ipv4.h
net/ipv4/cipso_ipv4.c
net/ipv4/ip_options.c
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_cipso_v4.h
net/netlabel/netlabel_kapi.c

index 811febf97caf3e094e106200c4a9066223708092..9909774eb998d973532d629a90d9017f11eacd90 100644 (file)
@@ -45,7 +45,7 @@
 /* known doi values */
 #define CIPSO_V4_DOI_UNKNOWN          0x00000000
 
-/* tag types */
+/* standard tag types */
 #define CIPSO_V4_TAG_INVALID          0
 #define CIPSO_V4_TAG_RBITMAP          1
 #define CIPSO_V4_TAG_ENUM             2
 #define CIPSO_V4_TAG_PBITMAP          6
 #define CIPSO_V4_TAG_FREEFORM         7
 
+/* non-standard tag types (tags > 127) */
+#define CIPSO_V4_TAG_LOCAL            128
+
 /* doi mapping types */
 #define CIPSO_V4_MAP_UNKNOWN          0
-#define CIPSO_V4_MAP_STD              1
+#define CIPSO_V4_MAP_TRANS            1
 #define CIPSO_V4_MAP_PASS             2
+#define CIPSO_V4_MAP_LOCAL            3
 
 /* limits */
 #define CIPSO_V4_MAX_REM_LVLS         255
@@ -215,7 +219,7 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb,
 int cipso_v4_skbuff_delattr(struct sk_buff *skb);
 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
                            struct netlbl_lsm_secattr *secattr);
-int cipso_v4_validate(unsigned char **option);
+int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
 #else
 static inline void cipso_v4_error(struct sk_buff *skb,
                                  int error,
@@ -259,7 +263,8 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
        return -ENOSYS;
 }
 
-static inline int cipso_v4_validate(unsigned char **option)
+static inline int cipso_v4_validate(const struct sk_buff *skb,
+                                   unsigned char **option)
 {
        return -ENOSYS;
 }
index 23768b9d6b64143da35b6c925e0094695939e022..490e035c6d90d231aee5514ac8d4a3f262ef0a4d 100644 (file)
@@ -109,6 +109,19 @@ int cipso_v4_rbm_strictvalid = 1;
  * be omitted. */
 #define CIPSO_V4_TAG_RNG_CAT_MAX      8
 
+/* Base length of the local tag (non-standard tag).
+ *  Tag definition (may change between kernel versions)
+ *
+ * 0          8          16         24         32
+ * +----------+----------+----------+----------+
+ * | 10000000 | 00000110 | 32-bit secid value  |
+ * +----------+----------+----------+----------+
+ * | in (host byte order)|
+ * +----------+----------+
+ *
+ */
+#define CIPSO_V4_TAG_LOC_BLEN         6
+
 /*
  * Helper Functions
  */
@@ -467,6 +480,10 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
                        if (doi_def->type != CIPSO_V4_MAP_PASS)
                                return -EINVAL;
                        break;
+               case CIPSO_V4_TAG_LOCAL:
+                       if (doi_def->type != CIPSO_V4_MAP_LOCAL)
+                               return -EINVAL;
+                       break;
                default:
                        return -EINVAL;
                }
@@ -502,7 +519,7 @@ void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
                return;
 
        switch (doi_def->type) {
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                kfree(doi_def->map.std->lvl.cipso);
                kfree(doi_def->map.std->lvl.local);
                kfree(doi_def->map.std->cat.cipso);
@@ -673,7 +690,7 @@ static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level)
        switch (doi_def->type) {
        case CIPSO_V4_MAP_PASS:
                return 0;
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
                        return 0;
                break;
@@ -702,7 +719,7 @@ static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
        case CIPSO_V4_MAP_PASS:
                *net_lvl = host_lvl;
                return 0;
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                if (host_lvl < doi_def->map.std->lvl.local_size &&
                    doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) {
                        *net_lvl = doi_def->map.std->lvl.local[host_lvl];
@@ -736,7 +753,7 @@ static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
        case CIPSO_V4_MAP_PASS:
                *host_lvl = net_lvl;
                return 0;
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                map_tbl = doi_def->map.std;
                if (net_lvl < map_tbl->lvl.cipso_size &&
                    map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
@@ -773,7 +790,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
        switch (doi_def->type) {
        case CIPSO_V4_MAP_PASS:
                return 0;
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                cipso_cat_size = doi_def->map.std->cat.cipso_size;
                cipso_array = doi_def->map.std->cat.cipso;
                for (;;) {
@@ -821,7 +838,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
        u32 host_cat_size = 0;
        u32 *host_cat_array = NULL;
 
-       if (doi_def->type == CIPSO_V4_MAP_STD) {
+       if (doi_def->type == CIPSO_V4_MAP_TRANS) {
                host_cat_size = doi_def->map.std->cat.local_size;
                host_cat_array = doi_def->map.std->cat.local;
        }
@@ -836,7 +853,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
                case CIPSO_V4_MAP_PASS:
                        net_spot = host_spot;
                        break;
-               case CIPSO_V4_MAP_STD:
+               case CIPSO_V4_MAP_TRANS:
                        if (host_spot >= host_cat_size)
                                return -EPERM;
                        net_spot = host_cat_array[host_spot];
@@ -882,7 +899,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
        u32 net_cat_size = 0;
        u32 *net_cat_array = NULL;
 
-       if (doi_def->type == CIPSO_V4_MAP_STD) {
+       if (doi_def->type == CIPSO_V4_MAP_TRANS) {
                net_cat_size = doi_def->map.std->cat.cipso_size;
                net_cat_array = doi_def->map.std->cat.cipso;
        }
@@ -902,7 +919,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
                case CIPSO_V4_MAP_PASS:
                        host_spot = net_spot;
                        break;
-               case CIPSO_V4_MAP_STD:
+               case CIPSO_V4_MAP_TRANS:
                        if (net_spot >= net_cat_size)
                                return -EPERM;
                        host_spot = net_cat_array[net_spot];
@@ -1238,7 +1255,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
        } else
                tag_len = 4;
 
-       buffer[0] = 0x01;
+       buffer[0] = CIPSO_V4_TAG_RBITMAP;
        buffer[1] = tag_len;
        buffer[3] = level;
 
@@ -1334,7 +1351,7 @@ static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
        } else
                tag_len = 4;
 
-       buffer[0] = 0x02;
+       buffer[0] = CIPSO_V4_TAG_ENUM;
        buffer[1] = tag_len;
        buffer[3] = level;
 
@@ -1430,7 +1447,7 @@ static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
        } else
                tag_len = 4;
 
-       buffer[0] = 0x05;
+       buffer[0] = CIPSO_V4_TAG_RANGE;
        buffer[1] = tag_len;
        buffer[3] = level;
 
@@ -1483,6 +1500,54 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
        return 0;
 }
 
+/**
+ * cipso_v4_gentag_loc - Generate a CIPSO local tag (non-standard)
+ * @doi_def: the DOI definition
+ * @secattr: the security attributes
+ * @buffer: the option buffer
+ * @buffer_len: length of buffer in bytes
+ *
+ * Description:
+ * Generate a CIPSO option using the local tag.  Returns the size of the tag
+ * on success, negative values on failure.
+ *
+ */
+static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def,
+                              const struct netlbl_lsm_secattr *secattr,
+                              unsigned char *buffer,
+                              u32 buffer_len)
+{
+       if (!(secattr->flags & NETLBL_SECATTR_SECID))
+               return -EPERM;
+
+       buffer[0] = CIPSO_V4_TAG_LOCAL;
+       buffer[1] = CIPSO_V4_TAG_LOC_BLEN;
+       *(u32 *)&buffer[2] = secattr->attr.secid;
+
+       return CIPSO_V4_TAG_LOC_BLEN;
+}
+
+/**
+ * cipso_v4_parsetag_loc - Parse a CIPSO local tag
+ * @doi_def: the DOI definition
+ * @tag: the CIPSO tag
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Parse a CIPSO local tag and return the security attributes in @secattr.
+ * Return zero on success, negatives values on failure.
+ *
+ */
+static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
+                                const unsigned char *tag,
+                                struct netlbl_lsm_secattr *secattr)
+{
+       secattr->attr.secid = *(u32 *)&tag[2];
+       secattr->flags |= NETLBL_SECATTR_SECID;
+
+       return 0;
+}
+
 /**
  * cipso_v4_validate - Validate a CIPSO option
  * @option: the start of the option, on error it is set to point to the error
@@ -1502,7 +1567,7 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
  *   that is unrecognized."
  *
  */
-int cipso_v4_validate(unsigned char **option)
+int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
 {
        unsigned char *opt = *option;
        unsigned char *tag;
@@ -1527,7 +1592,7 @@ int cipso_v4_validate(unsigned char **option)
                goto validate_return_locked;
        }
 
-       opt_iter = 6;
+       opt_iter = CIPSO_V4_HDR_LEN;
        tag = opt + opt_iter;
        while (opt_iter < opt_len) {
                for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
@@ -1545,7 +1610,7 @@ int cipso_v4_validate(unsigned char **option)
 
                switch (tag[0]) {
                case CIPSO_V4_TAG_RBITMAP:
-                       if (tag_len < 4) {
+                       if (tag_len < CIPSO_V4_TAG_RBM_BLEN) {
                                err_offset = opt_iter + 1;
                                goto validate_return_locked;
                        }
@@ -1563,7 +1628,7 @@ int cipso_v4_validate(unsigned char **option)
                                        err_offset = opt_iter + 3;
                                        goto validate_return_locked;
                                }
-                               if (tag_len > 4 &&
+                               if (tag_len > CIPSO_V4_TAG_RBM_BLEN &&
                                    cipso_v4_map_cat_rbm_valid(doi_def,
                                                            &tag[4],
                                                            tag_len - 4) < 0) {
@@ -1573,7 +1638,7 @@ int cipso_v4_validate(unsigned char **option)
                        }
                        break;
                case CIPSO_V4_TAG_ENUM:
-                       if (tag_len < 4) {
+                       if (tag_len < CIPSO_V4_TAG_ENUM_BLEN) {
                                err_offset = opt_iter + 1;
                                goto validate_return_locked;
                        }
@@ -1583,7 +1648,7 @@ int cipso_v4_validate(unsigned char **option)
                                err_offset = opt_iter + 3;
                                goto validate_return_locked;
                        }
-                       if (tag_len > 4 &&
+                       if (tag_len > CIPSO_V4_TAG_ENUM_BLEN &&
                            cipso_v4_map_cat_enum_valid(doi_def,
                                                        &tag[4],
                                                        tag_len - 4) < 0) {
@@ -1592,7 +1657,7 @@ int cipso_v4_validate(unsigned char **option)
                        }
                        break;
                case CIPSO_V4_TAG_RANGE:
-                       if (tag_len < 4) {
+                       if (tag_len < CIPSO_V4_TAG_RNG_BLEN) {
                                err_offset = opt_iter + 1;
                                goto validate_return_locked;
                        }
@@ -1602,7 +1667,7 @@ int cipso_v4_validate(unsigned char **option)
                                err_offset = opt_iter + 3;
                                goto validate_return_locked;
                        }
-                       if (tag_len > 4 &&
+                       if (tag_len > CIPSO_V4_TAG_RNG_BLEN &&
                            cipso_v4_map_cat_rng_valid(doi_def,
                                                       &tag[4],
                                                       tag_len - 4) < 0) {
@@ -1610,6 +1675,19 @@ int cipso_v4_validate(unsigned char **option)
                                goto validate_return_locked;
                        }
                        break;
+               case CIPSO_V4_TAG_LOCAL:
+                       /* This is a non-standard tag that we only allow for
+                        * local connections, so if the incoming interface is
+                        * not the loopback device drop the packet. */
+                       if (!(skb->dev->flags & IFF_LOOPBACK)) {
+                               err_offset = opt_iter;
+                               goto validate_return_locked;
+                       }
+                       if (tag_len != CIPSO_V4_TAG_LOC_BLEN) {
+                               err_offset = opt_iter + 1;
+                               goto validate_return_locked;
+                       }
+                       break;
                default:
                        err_offset = opt_iter;
                        goto validate_return_locked;
@@ -1712,6 +1790,12 @@ static int cipso_v4_genopt(unsigned char *buf, u32 buf_len,
                                                   &buf[CIPSO_V4_HDR_LEN],
                                                   buf_len - CIPSO_V4_HDR_LEN);
                        break;
+               case CIPSO_V4_TAG_LOCAL:
+                       ret_val = cipso_v4_gentag_loc(doi_def,
+                                                  secattr,
+                                                  &buf[CIPSO_V4_HDR_LEN],
+                                                  buf_len - CIPSO_V4_HDR_LEN);
+                       break;
                default:
                        return -EPERM;
                }
@@ -1921,6 +2005,9 @@ static int cipso_v4_getattr(const unsigned char *cipso,
        case CIPSO_V4_TAG_RANGE:
                ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr);
                break;
+       case CIPSO_V4_TAG_LOCAL:
+               ret_val = cipso_v4_parsetag_loc(doi_def, &cipso[6], secattr);
+               break;
        }
        if (ret_val == 0)
                secattr->type = NETLBL_NLTYPE_CIPSOV4;
index be3f18a7a40ebbbf4f40ef90bfea8702fd4f1fae..2c88da6e7862f2b49d4d9ba17197eb9d10205fe8 100644 (file)
@@ -438,7 +438,7 @@ int ip_options_compile(struct net *net,
                                goto error;
                        }
                        opt->cipso = optptr - iph;
-                       if (cipso_v4_validate(&optptr)) {
+                       if (cipso_v4_validate(skb, &optptr)) {
                                pp_ptr = optptr;
                                goto error;
                        }
index 5c4f60bbc82dd3ddf3018eac78d676f6ae8b0b1c..db83a67cbc7516e8e449ac44d7ae07440d57f29f 100644 (file)
@@ -132,9 +132,9 @@ static int netlbl_cipsov4_add_common(struct genl_info *info,
  * @info: the Generic NETLINK info block
  *
  * Description:
- * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
- * and add it to the CIPSO V4 engine.  Return zero on success and non-zero on
- * error.
+ * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD
+ * message and add it to the CIPSO V4 engine.  Return zero on success and
+ * non-zero on error.
  *
  */
 static int netlbl_cipsov4_add_std(struct genl_info *info)
@@ -164,7 +164,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
                ret_val = -ENOMEM;
                goto add_std_failure;
        }
-       doi_def->type = CIPSO_V4_MAP_STD;
+       doi_def->type = CIPSO_V4_MAP_TRANS;
 
        ret_val = netlbl_cipsov4_add_common(info, doi_def);
        if (ret_val != 0)
@@ -393,8 +393,8 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
 
        type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
        switch (type) {
-       case CIPSO_V4_MAP_STD:
-               type_str = "std";
+       case CIPSO_V4_MAP_TRANS:
+               type_str = "trans";
                ret_val = netlbl_cipsov4_add_std(info);
                break;
        case CIPSO_V4_MAP_PASS:
@@ -497,7 +497,7 @@ list_start:
        nla_nest_end(ans_skb, nla_a);
 
        switch (doi_def->type) {
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
                if (nla_a == NULL) {
                        ret_val = -ENOMEM;
index 220cb9d06b496d315d30c1041a03525421b4a9e2..fb3957f1d69a38476c737bed10e6b51b88c9dae0 100644 (file)
@@ -45,7 +45,7 @@
  *     NLBL_CIPSOV4_A_MTYPE
  *     NLBL_CIPSOV4_A_TAGLST
  *
- *   If using CIPSO_V4_MAP_STD the following attributes are required:
+ *   If using CIPSO_V4_MAP_TRANS the following attributes are required:
  *
  *     NLBL_CIPSOV4_A_MLSLVLLST
  *     NLBL_CIPSOV4_A_MLSCATLST
@@ -76,7 +76,7 @@
  *     NLBL_CIPSOV4_A_MTYPE
  *     NLBL_CIPSOV4_A_TAGLST
  *
- *   If using CIPSO_V4_MAP_STD the following attributes are required:
+ *   If using CIPSO_V4_MAP_TRANS the following attributes are required:
  *
  *     NLBL_CIPSOV4_A_MLSLVLLST
  *     NLBL_CIPSOV4_A_MLSCATLST
index 78fc557689b2ad19bc6f40ba396147b9a3078157..8435b15c3f7da495d7969f84e4ffbb446e8cc975 100644 (file)
@@ -157,8 +157,8 @@ cfg_cipsov4_add_map_return:
                                              audit_info);
        if (audit_buf != NULL) {
                switch (doi_type) {
-               case CIPSO_V4_MAP_STD:
-                       type_str = "std";
+               case CIPSO_V4_MAP_TRANS:
+                       type_str = "trans";
                        break;
                case CIPSO_V4_MAP_PASS:
                        type_str = "pass";