diff options
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 113 |
1 files changed, 53 insertions, 60 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 23a968f754be..a056278ad626 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -958,35 +958,28 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, | |||
958 | * Protocol Handling Functions | 958 | * Protocol Handling Functions |
959 | */ | 959 | */ |
960 | 960 | ||
961 | #define CIPSO_V4_OPT_LEN_MAX 40 | ||
961 | #define CIPSO_V4_HDR_LEN 6 | 962 | #define CIPSO_V4_HDR_LEN 6 |
962 | 963 | ||
963 | /** | 964 | /** |
964 | * cipso_v4_gentag_hdr - Generate a CIPSO option header | 965 | * cipso_v4_gentag_hdr - Generate a CIPSO option header |
965 | * @doi_def: the DOI definition | 966 | * @doi_def: the DOI definition |
966 | * @len: the total tag length in bytes | 967 | * @len: the total tag length in bytes, not including this header |
967 | * @buf: the CIPSO option buffer | 968 | * @buf: the CIPSO option buffer |
968 | * | 969 | * |
969 | * Description: | 970 | * Description: |
970 | * Write a CIPSO header into the beginning of @buffer. Return zero on success, | 971 | * Write a CIPSO header into the beginning of @buffer. |
971 | * negative values on failure. | ||
972 | * | 972 | * |
973 | */ | 973 | */ |
974 | static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, | 974 | static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, |
975 | u32 len, | 975 | unsigned char *buf, |
976 | unsigned char *buf) | 976 | u32 len) |
977 | { | 977 | { |
978 | if (CIPSO_V4_HDR_LEN + len > 40) | ||
979 | return -ENOSPC; | ||
980 | |||
981 | buf[0] = IPOPT_CIPSO; | 978 | buf[0] = IPOPT_CIPSO; |
982 | buf[1] = CIPSO_V4_HDR_LEN + len; | 979 | buf[1] = CIPSO_V4_HDR_LEN + len; |
983 | *(__be32 *)&buf[2] = htonl(doi_def->doi); | 980 | *(__be32 *)&buf[2] = htonl(doi_def->doi); |
984 | |||
985 | return 0; | ||
986 | } | 981 | } |
987 | 982 | ||
988 | #define CIPSO_V4_TAG1_CAT_LEN 30 | ||
989 | |||
990 | /** | 983 | /** |
991 | * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) | 984 | * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) |
992 | * @doi_def: the DOI definition | 985 | * @doi_def: the DOI definition |
@@ -997,71 +990,50 @@ static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, | |||
997 | * Description: | 990 | * Description: |
998 | * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The | 991 | * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The |
999 | * actual buffer length may be larger than the indicated size due to | 992 | * actual buffer length may be larger than the indicated size due to |
1000 | * translation between host and network category bitmaps. Returns zero on | 993 | * translation between host and network category bitmaps. Returns the size of |
1001 | * success, negative values on failure. | 994 | * the tag on success, negative values on failure. |
1002 | * | 995 | * |
1003 | */ | 996 | */ |
1004 | static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, | 997 | static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, |
1005 | const struct netlbl_lsm_secattr *secattr, | 998 | const struct netlbl_lsm_secattr *secattr, |
1006 | unsigned char **buffer, | 999 | unsigned char *buffer, |
1007 | u32 *buffer_len) | 1000 | u32 buffer_len) |
1008 | { | 1001 | { |
1009 | int ret_val; | 1002 | int ret_val; |
1010 | unsigned char *buf = NULL; | 1003 | u32 tag_len; |
1011 | u32 buf_len; | ||
1012 | u32 level; | 1004 | u32 level; |
1013 | 1005 | ||
1014 | if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0) | 1006 | if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0) |
1015 | return -EPERM; | 1007 | return -EPERM; |
1016 | 1008 | ||
1017 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { | 1009 | ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); |
1018 | buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, | 1010 | if (ret_val != 0) |
1019 | GFP_ATOMIC); | 1011 | return ret_val; |
1020 | if (buf == NULL) | ||
1021 | return -ENOMEM; | ||
1022 | 1012 | ||
1013 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { | ||
1023 | ret_val = cipso_v4_map_cat_rbm_hton(doi_def, | 1014 | ret_val = cipso_v4_map_cat_rbm_hton(doi_def, |
1024 | secattr->mls_cat, | 1015 | secattr->mls_cat, |
1025 | secattr->mls_cat_len, | 1016 | secattr->mls_cat_len, |
1026 | &buf[CIPSO_V4_HDR_LEN + 4], | 1017 | &buffer[4], |
1027 | CIPSO_V4_TAG1_CAT_LEN); | 1018 | buffer_len - 4); |
1028 | if (ret_val < 0) | 1019 | if (ret_val < 0) |
1029 | goto gentag_failure; | 1020 | return ret_val; |
1030 | 1021 | ||
1031 | /* This will send packets using the "optimized" format when | 1022 | /* This will send packets using the "optimized" format when |
1032 | * possibile as specified in section 3.4.2.6 of the | 1023 | * possibile as specified in section 3.4.2.6 of the |
1033 | * CIPSO draft. */ | 1024 | * CIPSO draft. */ |
1034 | if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) | 1025 | if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) |
1035 | buf_len = 14; | 1026 | tag_len = 14; |
1036 | else | 1027 | else |
1037 | buf_len = 4 + ret_val; | 1028 | tag_len = 4 + ret_val; |
1038 | } else { | 1029 | } else |
1039 | buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); | 1030 | tag_len = 4; |
1040 | if (buf == NULL) | ||
1041 | return -ENOMEM; | ||
1042 | buf_len = 4; | ||
1043 | } | ||
1044 | |||
1045 | ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); | ||
1046 | if (ret_val != 0) | ||
1047 | goto gentag_failure; | ||
1048 | |||
1049 | ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf); | ||
1050 | if (ret_val != 0) | ||
1051 | goto gentag_failure; | ||
1052 | |||
1053 | buf[CIPSO_V4_HDR_LEN] = 0x01; | ||
1054 | buf[CIPSO_V4_HDR_LEN + 1] = buf_len; | ||
1055 | buf[CIPSO_V4_HDR_LEN + 3] = level; | ||
1056 | 1031 | ||
1057 | *buffer = buf; | 1032 | buffer[0] = 0x01; |
1058 | *buffer_len = CIPSO_V4_HDR_LEN + buf_len; | 1033 | buffer[1] = tag_len; |
1034 | buffer[3] = level; | ||
1059 | 1035 | ||
1060 | return 0; | 1036 | return tag_len; |
1061 | |||
1062 | gentag_failure: | ||
1063 | kfree(buf); | ||
1064 | return ret_val; | ||
1065 | } | 1037 | } |
1066 | 1038 | ||
1067 | /** | 1039 | /** |
@@ -1284,7 +1256,7 @@ int cipso_v4_socket_setattr(const struct socket *sock, | |||
1284 | { | 1256 | { |
1285 | int ret_val = -EPERM; | 1257 | int ret_val = -EPERM; |
1286 | u32 iter; | 1258 | u32 iter; |
1287 | unsigned char *buf = NULL; | 1259 | unsigned char *buf; |
1288 | u32 buf_len = 0; | 1260 | u32 buf_len = 0; |
1289 | u32 opt_len; | 1261 | u32 opt_len; |
1290 | struct ip_options *opt = NULL; | 1262 | struct ip_options *opt = NULL; |
@@ -1300,17 +1272,28 @@ int cipso_v4_socket_setattr(const struct socket *sock, | |||
1300 | if (sk == NULL) | 1272 | if (sk == NULL) |
1301 | return 0; | 1273 | return 0; |
1302 | 1274 | ||
1275 | /* We allocate the maximum CIPSO option size here so we are probably | ||
1276 | * being a little wasteful, but it makes our life _much_ easier later | ||
1277 | * on and after all we are only talking about 40 bytes. */ | ||
1278 | buf_len = CIPSO_V4_OPT_LEN_MAX; | ||
1279 | buf = kmalloc(buf_len, GFP_ATOMIC); | ||
1280 | if (buf == NULL) { | ||
1281 | ret_val = -ENOMEM; | ||
1282 | goto socket_setattr_failure; | ||
1283 | } | ||
1284 | |||
1303 | /* XXX - This code assumes only one tag per CIPSO option which isn't | 1285 | /* XXX - This code assumes only one tag per CIPSO option which isn't |
1304 | * really a good assumption to make but since we only support the MAC | 1286 | * really a good assumption to make but since we only support the MAC |
1305 | * tags right now it is a safe assumption. */ | 1287 | * tags right now it is a safe assumption. */ |
1306 | iter = 0; | 1288 | iter = 0; |
1307 | do { | 1289 | do { |
1290 | memset(buf, 0, buf_len); | ||
1308 | switch (doi_def->tags[iter]) { | 1291 | switch (doi_def->tags[iter]) { |
1309 | case CIPSO_V4_TAG_RBITMAP: | 1292 | case CIPSO_V4_TAG_RBITMAP: |
1310 | ret_val = cipso_v4_gentag_rbm(doi_def, | 1293 | ret_val = cipso_v4_gentag_rbm(doi_def, |
1311 | secattr, | 1294 | secattr, |
1312 | &buf, | 1295 | &buf[CIPSO_V4_HDR_LEN], |
1313 | &buf_len); | 1296 | buf_len - CIPSO_V4_HDR_LEN); |
1314 | break; | 1297 | break; |
1315 | default: | 1298 | default: |
1316 | ret_val = -EPERM; | 1299 | ret_val = -EPERM; |
@@ -1318,11 +1301,13 @@ int cipso_v4_socket_setattr(const struct socket *sock, | |||
1318 | } | 1301 | } |
1319 | 1302 | ||
1320 | iter++; | 1303 | iter++; |
1321 | } while (ret_val != 0 && | 1304 | } while (ret_val < 0 && |
1322 | iter < CIPSO_V4_TAG_MAXCNT && | 1305 | iter < CIPSO_V4_TAG_MAXCNT && |
1323 | doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); | 1306 | doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); |
1324 | if (ret_val != 0) | 1307 | if (ret_val < 0) |
1325 | goto socket_setattr_failure; | 1308 | goto socket_setattr_failure; |
1309 | cipso_v4_gentag_hdr(doi_def, buf, ret_val); | ||
1310 | buf_len = CIPSO_V4_HDR_LEN + ret_val; | ||
1326 | 1311 | ||
1327 | /* We can't use ip_options_get() directly because it makes a call to | 1312 | /* We can't use ip_options_get() directly because it makes a call to |
1328 | * ip_options_get_alloc() which allocates memory with GFP_KERNEL and | 1313 | * ip_options_get_alloc() which allocates memory with GFP_KERNEL and |
@@ -1396,6 +1381,10 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) | |||
1396 | rcu_read_unlock(); | 1381 | rcu_read_unlock(); |
1397 | return -ENOMSG; | 1382 | return -ENOMSG; |
1398 | } | 1383 | } |
1384 | |||
1385 | /* XXX - This code assumes only one tag per CIPSO option which isn't | ||
1386 | * really a good assumption to make but since we only support the MAC | ||
1387 | * tags right now it is a safe assumption. */ | ||
1399 | switch (cipso_ptr[6]) { | 1388 | switch (cipso_ptr[6]) { |
1400 | case CIPSO_V4_TAG_RBITMAP: | 1389 | case CIPSO_V4_TAG_RBITMAP: |
1401 | ret_val = cipso_v4_parsetag_rbm(doi_def, | 1390 | ret_val = cipso_v4_parsetag_rbm(doi_def, |
@@ -1458,6 +1447,10 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | |||
1458 | doi_def = cipso_v4_doi_getdef(doi); | 1447 | doi_def = cipso_v4_doi_getdef(doi); |
1459 | if (doi_def == NULL) | 1448 | if (doi_def == NULL) |
1460 | goto skbuff_getattr_return; | 1449 | goto skbuff_getattr_return; |
1450 | |||
1451 | /* XXX - This code assumes only one tag per CIPSO option which isn't | ||
1452 | * really a good assumption to make but since we only support the MAC | ||
1453 | * tags right now it is a safe assumption. */ | ||
1461 | switch (cipso_ptr[6]) { | 1454 | switch (cipso_ptr[6]) { |
1462 | case CIPSO_V4_TAG_RBITMAP: | 1455 | case CIPSO_V4_TAG_RBITMAP: |
1463 | ret_val = cipso_v4_parsetag_rbm(doi_def, | 1456 | ret_val = cipso_v4_parsetag_rbm(doi_def, |