diff options
| author | Paul Moore <paul.moore@hp.com> | 2009-03-27 17:10:54 -0400 |
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2009-03-28 00:01:37 -0400 |
| commit | 07feee8f812f7327a46186f7604df312c8c81962 (patch) | |
| tree | 73eac643b60532aa82d7680a7de193ba2b62eddd | |
| parent | 8651d5c0b1f874c5b8307ae2b858bc40f9f02482 (diff) | |
netlabel: Cleanup the Smack/NetLabel code to fix incoming TCP connections
This patch cleans up a lot of the Smack network access control code. The
largest changes are to fix the labeling of incoming TCP connections in a
manner similar to the recent SELinux changes which use the
security_inet_conn_request() hook to label the request_sock and let the label
move to the child socket via the normal network stack mechanisms. In addition
to the incoming TCP connection fixes this patch also removes the smk_labled
field from the socket_smack struct as the minor optimization advantage was
outweighed by the difficulty in maintaining it's proper state.
Signed-off-by: Paul Moore <paul.moore@hp.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: James Morris <jmorris@namei.org>
| -rw-r--r-- | include/net/netlabel.h | 5 | ||||
| -rw-r--r-- | net/netlabel/netlabel_kapi.c | 13 | ||||
| -rw-r--r-- | security/smack/smack.h | 1 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 260 |
4 files changed, 161 insertions, 118 deletions
diff --git a/include/net/netlabel.h b/include/net/netlabel.h index bdb10e5183d5..60ebbc1fef46 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h | |||
| @@ -417,6 +417,7 @@ int netlbl_conn_setattr(struct sock *sk, | |||
| 417 | const struct netlbl_lsm_secattr *secattr); | 417 | const struct netlbl_lsm_secattr *secattr); |
| 418 | int netlbl_req_setattr(struct request_sock *req, | 418 | int netlbl_req_setattr(struct request_sock *req, |
| 419 | const struct netlbl_lsm_secattr *secattr); | 419 | const struct netlbl_lsm_secattr *secattr); |
| 420 | void netlbl_req_delattr(struct request_sock *req); | ||
| 420 | int netlbl_skbuff_setattr(struct sk_buff *skb, | 421 | int netlbl_skbuff_setattr(struct sk_buff *skb, |
| 421 | u16 family, | 422 | u16 family, |
| 422 | const struct netlbl_lsm_secattr *secattr); | 423 | const struct netlbl_lsm_secattr *secattr); |
| @@ -547,6 +548,10 @@ static inline int netlbl_req_setattr(struct request_sock *req, | |||
| 547 | { | 548 | { |
| 548 | return -ENOSYS; | 549 | return -ENOSYS; |
| 549 | } | 550 | } |
| 551 | static inline void netlbl_req_delattr(struct request_sock *req) | ||
| 552 | { | ||
| 553 | return; | ||
| 554 | } | ||
| 550 | static inline int netlbl_skbuff_setattr(struct sk_buff *skb, | 555 | static inline int netlbl_skbuff_setattr(struct sk_buff *skb, |
| 551 | u16 family, | 556 | u16 family, |
| 552 | const struct netlbl_lsm_secattr *secattr) | 557 | const struct netlbl_lsm_secattr *secattr) |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index cae2f5f4cac0..b0e582f2d37a 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
| @@ -861,6 +861,19 @@ req_setattr_return: | |||
| 861 | } | 861 | } |
| 862 | 862 | ||
| 863 | /** | 863 | /** |
| 864 | * netlbl_req_delattr - Delete all the NetLabel labels on a socket | ||
| 865 | * @req: the socket | ||
| 866 | * | ||
| 867 | * Description: | ||
| 868 | * Remove all the NetLabel labeling from @req. | ||
| 869 | * | ||
| 870 | */ | ||
| 871 | void netlbl_req_delattr(struct request_sock *req) | ||
| 872 | { | ||
| 873 | cipso_v4_req_delattr(req); | ||
| 874 | } | ||
| 875 | |||
| 876 | /** | ||
| 864 | * netlbl_skbuff_setattr - Label a packet using the correct protocol | 877 | * netlbl_skbuff_setattr - Label a packet using the correct protocol |
| 865 | * @skb: the packet | 878 | * @skb: the packet |
| 866 | * @family: protocol family | 879 | * @family: protocol family |
diff --git a/security/smack/smack.h b/security/smack/smack.h index 64164f8fde70..5e5a3bcb599a 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
| @@ -42,7 +42,6 @@ struct superblock_smack { | |||
| 42 | struct socket_smack { | 42 | struct socket_smack { |
| 43 | char *smk_out; /* outbound label */ | 43 | char *smk_out; /* outbound label */ |
| 44 | char *smk_in; /* inbound label */ | 44 | char *smk_in; /* inbound label */ |
| 45 | int smk_labeled; /* label scheme */ | ||
| 46 | char smk_packet[SMK_LABELLEN]; /* TCP peer label */ | 45 | char smk_packet[SMK_LABELLEN]; /* TCP peer label */ |
| 47 | }; | 46 | }; |
| 48 | 47 | ||
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 23ad420a49aa..8ed502c2ad45 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | * Casey Schaufler <casey@schaufler-ca.com> | 7 | * Casey Schaufler <casey@schaufler-ca.com> |
| 8 | * | 8 | * |
| 9 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> | 9 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> |
| 10 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | ||
| 11 | * Paul Moore <paul.moore@hp.com> | ||
| 10 | * | 12 | * |
| 11 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 12 | * it under the terms of the GNU General Public License version 2, | 14 | * it under the terms of the GNU General Public License version 2, |
| @@ -20,6 +22,7 @@ | |||
| 20 | #include <linux/ext2_fs.h> | 22 | #include <linux/ext2_fs.h> |
| 21 | #include <linux/kd.h> | 23 | #include <linux/kd.h> |
| 22 | #include <asm/ioctls.h> | 24 | #include <asm/ioctls.h> |
| 25 | #include <linux/ip.h> | ||
| 23 | #include <linux/tcp.h> | 26 | #include <linux/tcp.h> |
| 24 | #include <linux/udp.h> | 27 | #include <linux/udp.h> |
| 25 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
| @@ -1275,7 +1278,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | |||
| 1275 | 1278 | ||
| 1276 | ssp->smk_in = csp; | 1279 | ssp->smk_in = csp; |
| 1277 | ssp->smk_out = csp; | 1280 | ssp->smk_out = csp; |
| 1278 | ssp->smk_labeled = SMACK_CIPSO_SOCKET; | ||
| 1279 | ssp->smk_packet[0] = '\0'; | 1281 | ssp->smk_packet[0] = '\0'; |
| 1280 | 1282 | ||
| 1281 | sk->sk_security = ssp; | 1283 | sk->sk_security = ssp; |
| @@ -1295,6 +1297,39 @@ static void smack_sk_free_security(struct sock *sk) | |||
| 1295 | } | 1297 | } |
| 1296 | 1298 | ||
| 1297 | /** | 1299 | /** |
| 1300 | * smack_host_label - check host based restrictions | ||
| 1301 | * @sip: the object end | ||
| 1302 | * | ||
| 1303 | * looks for host based access restrictions | ||
| 1304 | * | ||
| 1305 | * This version will only be appropriate for really small sets of single label | ||
| 1306 | * hosts. The caller is responsible for ensuring that the RCU read lock is | ||
| 1307 | * taken before calling this function. | ||
| 1308 | * | ||
| 1309 | * Returns the label of the far end or NULL if it's not special. | ||
| 1310 | */ | ||
| 1311 | static char *smack_host_label(struct sockaddr_in *sip) | ||
| 1312 | { | ||
| 1313 | struct smk_netlbladdr *snp; | ||
| 1314 | struct in_addr *siap = &sip->sin_addr; | ||
| 1315 | |||
| 1316 | if (siap->s_addr == 0) | ||
| 1317 | return NULL; | ||
| 1318 | |||
| 1319 | list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) | ||
| 1320 | /* | ||
| 1321 | * we break after finding the first match because | ||
| 1322 | * the list is sorted from longest to shortest mask | ||
| 1323 | * so we have found the most specific match | ||
| 1324 | */ | ||
| 1325 | if ((&snp->smk_host.sin_addr)->s_addr == | ||
| 1326 | (siap->s_addr & (&snp->smk_mask)->s_addr)) | ||
| 1327 | return snp->smk_label; | ||
| 1328 | |||
| 1329 | return NULL; | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | /** | ||
| 1298 | * smack_set_catset - convert a capset to netlabel mls categories | 1333 | * smack_set_catset - convert a capset to netlabel mls categories |
| 1299 | * @catset: the Smack categories | 1334 | * @catset: the Smack categories |
| 1300 | * @sap: where to put the netlabel categories | 1335 | * @sap: where to put the netlabel categories |
| @@ -1365,11 +1400,10 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) | |||
| 1365 | */ | 1400 | */ |
| 1366 | static int smack_netlabel(struct sock *sk, int labeled) | 1401 | static int smack_netlabel(struct sock *sk, int labeled) |
| 1367 | { | 1402 | { |
| 1368 | struct socket_smack *ssp; | 1403 | struct socket_smack *ssp = sk->sk_security; |
| 1369 | struct netlbl_lsm_secattr secattr; | 1404 | struct netlbl_lsm_secattr secattr; |
| 1370 | int rc = 0; | 1405 | int rc = 0; |
| 1371 | 1406 | ||
| 1372 | ssp = sk->sk_security; | ||
| 1373 | /* | 1407 | /* |
| 1374 | * Usually the netlabel code will handle changing the | 1408 | * Usually the netlabel code will handle changing the |
| 1375 | * packet labeling based on the label. | 1409 | * packet labeling based on the label. |
| @@ -1393,21 +1427,45 @@ static int smack_netlabel(struct sock *sk, int labeled) | |||
| 1393 | 1427 | ||
| 1394 | bh_unlock_sock(sk); | 1428 | bh_unlock_sock(sk); |
| 1395 | local_bh_enable(); | 1429 | local_bh_enable(); |
| 1396 | /* | ||
| 1397 | * Remember the label scheme used so that it is not | ||
| 1398 | * necessary to do the netlabel setting if it has not | ||
| 1399 | * changed the next time through. | ||
| 1400 | * | ||
| 1401 | * The -EDESTADDRREQ case is an indication that there's | ||
| 1402 | * a single level host involved. | ||
| 1403 | */ | ||
| 1404 | if (rc == 0) | ||
| 1405 | ssp->smk_labeled = labeled; | ||
| 1406 | 1430 | ||
| 1407 | return rc; | 1431 | return rc; |
| 1408 | } | 1432 | } |
| 1409 | 1433 | ||
| 1410 | /** | 1434 | /** |
| 1435 | * smack_netlbel_send - Set the secattr on a socket and perform access checks | ||
| 1436 | * @sk: the socket | ||
| 1437 | * @sap: the destination address | ||
| 1438 | * | ||
| 1439 | * Set the correct secattr for the given socket based on the destination | ||
| 1440 | * address and perform any outbound access checks needed. | ||
| 1441 | * | ||
| 1442 | * Returns 0 on success or an error code. | ||
| 1443 | * | ||
| 1444 | */ | ||
| 1445 | static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | ||
| 1446 | { | ||
| 1447 | int rc; | ||
| 1448 | int sk_lbl; | ||
| 1449 | char *hostsp; | ||
| 1450 | struct socket_smack *ssp = sk->sk_security; | ||
| 1451 | |||
| 1452 | rcu_read_lock(); | ||
| 1453 | hostsp = smack_host_label(sap); | ||
| 1454 | if (hostsp != NULL) { | ||
| 1455 | sk_lbl = SMACK_UNLABELED_SOCKET; | ||
| 1456 | rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE); | ||
| 1457 | } else { | ||
| 1458 | sk_lbl = SMACK_CIPSO_SOCKET; | ||
| 1459 | rc = 0; | ||
| 1460 | } | ||
| 1461 | rcu_read_unlock(); | ||
| 1462 | if (rc != 0) | ||
| 1463 | return rc; | ||
| 1464 | |||
| 1465 | return smack_netlabel(sk, sk_lbl); | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | /** | ||
| 1411 | * smack_inode_setsecurity - set smack xattrs | 1469 | * smack_inode_setsecurity - set smack xattrs |
| 1412 | * @inode: the object | 1470 | * @inode: the object |
| 1413 | * @name: attribute name | 1471 | * @name: attribute name |
| @@ -1488,43 +1546,6 @@ static int smack_socket_post_create(struct socket *sock, int family, | |||
| 1488 | return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | 1546 | return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
| 1489 | } | 1547 | } |
| 1490 | 1548 | ||
| 1491 | |||
| 1492 | /** | ||
| 1493 | * smack_host_label - check host based restrictions | ||
| 1494 | * @sip: the object end | ||
| 1495 | * | ||
| 1496 | * looks for host based access restrictions | ||
| 1497 | * | ||
| 1498 | * This version will only be appropriate for really small | ||
| 1499 | * sets of single label hosts. | ||
| 1500 | * | ||
| 1501 | * Returns the label of the far end or NULL if it's not special. | ||
| 1502 | */ | ||
| 1503 | static char *smack_host_label(struct sockaddr_in *sip) | ||
| 1504 | { | ||
| 1505 | struct smk_netlbladdr *snp; | ||
| 1506 | struct in_addr *siap = &sip->sin_addr; | ||
| 1507 | |||
| 1508 | if (siap->s_addr == 0) | ||
| 1509 | return NULL; | ||
| 1510 | |||
| 1511 | rcu_read_lock(); | ||
| 1512 | list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) { | ||
| 1513 | /* | ||
| 1514 | * we break after finding the first match because | ||
| 1515 | * the list is sorted from longest to shortest mask | ||
| 1516 | * so we have found the most specific match | ||
| 1517 | */ | ||
| 1518 | if ((&snp->smk_host.sin_addr)->s_addr == | ||
| 1519 | (siap->s_addr & (&snp->smk_mask)->s_addr)) { | ||
| 1520 | rcu_read_unlock(); | ||
| 1521 | return snp->smk_label; | ||
| 1522 | } | ||
| 1523 | } | ||
| 1524 | rcu_read_unlock(); | ||
| 1525 | return NULL; | ||
| 1526 | } | ||
| 1527 | |||
| 1528 | /** | 1549 | /** |
| 1529 | * smack_socket_connect - connect access check | 1550 | * smack_socket_connect - connect access check |
| 1530 | * @sock: the socket | 1551 | * @sock: the socket |
| @@ -1538,30 +1559,12 @@ static char *smack_host_label(struct sockaddr_in *sip) | |||
| 1538 | static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, | 1559 | static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, |
| 1539 | int addrlen) | 1560 | int addrlen) |
| 1540 | { | 1561 | { |
| 1541 | struct socket_smack *ssp = sock->sk->sk_security; | ||
| 1542 | char *hostsp; | ||
| 1543 | int rc; | ||
| 1544 | |||
| 1545 | if (sock->sk == NULL || sock->sk->sk_family != PF_INET) | 1562 | if (sock->sk == NULL || sock->sk->sk_family != PF_INET) |
| 1546 | return 0; | 1563 | return 0; |
| 1547 | |||
| 1548 | if (addrlen < sizeof(struct sockaddr_in)) | 1564 | if (addrlen < sizeof(struct sockaddr_in)) |
| 1549 | return -EINVAL; | 1565 | return -EINVAL; |
| 1550 | 1566 | ||
| 1551 | hostsp = smack_host_label((struct sockaddr_in *)sap); | 1567 | return smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap); |
| 1552 | if (hostsp == NULL) { | ||
| 1553 | if (ssp->smk_labeled != SMACK_CIPSO_SOCKET) | ||
| 1554 | return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | ||
| 1555 | return 0; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE); | ||
| 1559 | if (rc != 0) | ||
| 1560 | return rc; | ||
| 1561 | |||
| 1562 | if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET) | ||
| 1563 | return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET); | ||
| 1564 | return 0; | ||
| 1565 | } | 1568 | } |
| 1566 | 1569 | ||
| 1567 | /** | 1570 | /** |
| @@ -2262,9 +2265,6 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
| 2262 | int size) | 2265 | int size) |
| 2263 | { | 2266 | { |
| 2264 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; | 2267 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; |
| 2265 | struct socket_smack *ssp = sock->sk->sk_security; | ||
| 2266 | char *hostsp; | ||
| 2267 | int rc; | ||
| 2268 | 2268 | ||
| 2269 | /* | 2269 | /* |
| 2270 | * Perfectly reasonable for this to be NULL | 2270 | * Perfectly reasonable for this to be NULL |
| @@ -2272,22 +2272,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
| 2272 | if (sip == NULL || sip->sin_family != PF_INET) | 2272 | if (sip == NULL || sip->sin_family != PF_INET) |
| 2273 | return 0; | 2273 | return 0; |
| 2274 | 2274 | ||
| 2275 | hostsp = smack_host_label(sip); | 2275 | return smack_netlabel_send(sock->sk, sip); |
| 2276 | if (hostsp == NULL) { | ||
| 2277 | if (ssp->smk_labeled != SMACK_CIPSO_SOCKET) | ||
| 2278 | return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | ||
| 2279 | return 0; | ||
| 2280 | } | ||
| 2281 | |||
| 2282 | rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE); | ||
| 2283 | if (rc != 0) | ||
| 2284 | return rc; | ||
| 2285 | |||
| 2286 | if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET) | ||
| 2287 | return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET); | ||
| 2288 | |||
| 2289 | return 0; | ||
| 2290 | |||
| 2291 | } | 2276 | } |
| 2292 | 2277 | ||
| 2293 | 2278 | ||
| @@ -2492,31 +2477,24 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
| 2492 | } | 2477 | } |
| 2493 | 2478 | ||
| 2494 | /** | 2479 | /** |
| 2495 | * smack_sock_graft - graft access state between two sockets | 2480 | * smack_sock_graft - Initialize a newly created socket with an existing sock |
| 2496 | * @sk: fresh sock | 2481 | * @sk: child sock |
| 2497 | * @parent: donor socket | 2482 | * @parent: parent socket |
| 2498 | * | 2483 | * |
| 2499 | * Sets the netlabel socket state on sk from parent | 2484 | * Set the smk_{in,out} state of an existing sock based on the process that |
| 2485 | * is creating the new socket. | ||
| 2500 | */ | 2486 | */ |
| 2501 | static void smack_sock_graft(struct sock *sk, struct socket *parent) | 2487 | static void smack_sock_graft(struct sock *sk, struct socket *parent) |
| 2502 | { | 2488 | { |
| 2503 | struct socket_smack *ssp; | 2489 | struct socket_smack *ssp; |
| 2504 | int rc; | ||
| 2505 | |||
| 2506 | if (sk == NULL) | ||
| 2507 | return; | ||
| 2508 | 2490 | ||
| 2509 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | 2491 | if (sk == NULL || |
| 2492 | (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)) | ||
| 2510 | return; | 2493 | return; |
| 2511 | 2494 | ||
| 2512 | ssp = sk->sk_security; | 2495 | ssp = sk->sk_security; |
| 2513 | ssp->smk_in = ssp->smk_out = current_security(); | 2496 | ssp->smk_in = ssp->smk_out = current_security(); |
| 2514 | ssp->smk_packet[0] = '\0'; | 2497 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ |
| 2515 | |||
| 2516 | rc = smack_netlabel(sk, SMACK_CIPSO_SOCKET); | ||
| 2517 | if (rc != 0) | ||
| 2518 | printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | ||
| 2519 | __func__, -rc); | ||
| 2520 | } | 2498 | } |
| 2521 | 2499 | ||
| 2522 | /** | 2500 | /** |
| @@ -2531,35 +2509,82 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) | |||
| 2531 | static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | 2509 | static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, |
| 2532 | struct request_sock *req) | 2510 | struct request_sock *req) |
| 2533 | { | 2511 | { |
| 2534 | struct netlbl_lsm_secattr skb_secattr; | 2512 | u16 family = sk->sk_family; |
| 2535 | struct socket_smack *ssp = sk->sk_security; | 2513 | struct socket_smack *ssp = sk->sk_security; |
| 2514 | struct netlbl_lsm_secattr secattr; | ||
| 2515 | struct sockaddr_in addr; | ||
| 2516 | struct iphdr *hdr; | ||
| 2536 | char smack[SMK_LABELLEN]; | 2517 | char smack[SMK_LABELLEN]; |
| 2537 | int rc; | 2518 | int rc; |
| 2538 | 2519 | ||
| 2539 | if (skb == NULL) | 2520 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ |
| 2540 | return -EACCES; | 2521 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) |
| 2522 | family = PF_INET; | ||
| 2541 | 2523 | ||
| 2542 | netlbl_secattr_init(&skb_secattr); | 2524 | netlbl_secattr_init(&secattr); |
| 2543 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr); | 2525 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
| 2544 | if (rc == 0) | 2526 | if (rc == 0) |
| 2545 | smack_from_secattr(&skb_secattr, smack); | 2527 | smack_from_secattr(&secattr, smack); |
| 2546 | else | 2528 | else |
| 2547 | strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); | 2529 | strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); |
| 2548 | netlbl_secattr_destroy(&skb_secattr); | 2530 | netlbl_secattr_destroy(&secattr); |
| 2531 | |||
| 2549 | /* | 2532 | /* |
| 2550 | * Receiving a packet requires that the other end | 2533 | * Receiving a packet requires that the other end be able to write |
| 2551 | * be able to write here. Read access is not required. | 2534 | * here. Read access is not required. |
| 2552 | * | ||
| 2553 | * If the request is successful save the peer's label | ||
| 2554 | * so that SO_PEERCRED can report it. | ||
| 2555 | */ | 2535 | */ |
| 2556 | rc = smk_access(smack, ssp->smk_in, MAY_WRITE); | 2536 | rc = smk_access(smack, ssp->smk_in, MAY_WRITE); |
| 2557 | if (rc == 0) | 2537 | if (rc != 0) |
| 2558 | strncpy(ssp->smk_packet, smack, SMK_MAXLEN); | 2538 | return rc; |
| 2539 | |||
| 2540 | /* | ||
| 2541 | * Save the peer's label in the request_sock so we can later setup | ||
| 2542 | * smk_packet in the child socket so that SO_PEERCRED can report it. | ||
| 2543 | */ | ||
| 2544 | req->peer_secid = smack_to_secid(smack); | ||
| 2545 | |||
| 2546 | /* | ||
| 2547 | * We need to decide if we want to label the incoming connection here | ||
| 2548 | * if we do we only need to label the request_sock and the stack will | ||
| 2549 | * propogate the wire-label to the sock when it is created. | ||
| 2550 | */ | ||
| 2551 | hdr = ip_hdr(skb); | ||
| 2552 | addr.sin_addr.s_addr = hdr->saddr; | ||
| 2553 | rcu_read_lock(); | ||
| 2554 | if (smack_host_label(&addr) == NULL) { | ||
| 2555 | rcu_read_unlock(); | ||
| 2556 | netlbl_secattr_init(&secattr); | ||
| 2557 | smack_to_secattr(smack, &secattr); | ||
| 2558 | rc = netlbl_req_setattr(req, &secattr); | ||
| 2559 | netlbl_secattr_destroy(&secattr); | ||
| 2560 | } else { | ||
| 2561 | rcu_read_unlock(); | ||
| 2562 | netlbl_req_delattr(req); | ||
| 2563 | } | ||
| 2559 | 2564 | ||
| 2560 | return rc; | 2565 | return rc; |
| 2561 | } | 2566 | } |
| 2562 | 2567 | ||
| 2568 | /** | ||
| 2569 | * smack_inet_csk_clone - Copy the connection information to the new socket | ||
| 2570 | * @sk: the new socket | ||
| 2571 | * @req: the connection's request_sock | ||
| 2572 | * | ||
| 2573 | * Transfer the connection's peer label to the newly created socket. | ||
| 2574 | */ | ||
| 2575 | static void smack_inet_csk_clone(struct sock *sk, | ||
| 2576 | const struct request_sock *req) | ||
| 2577 | { | ||
| 2578 | struct socket_smack *ssp = sk->sk_security; | ||
| 2579 | char *smack; | ||
| 2580 | |||
| 2581 | if (req->peer_secid != 0) { | ||
| 2582 | smack = smack_from_secid(req->peer_secid); | ||
| 2583 | strncpy(ssp->smk_packet, smack, SMK_MAXLEN); | ||
| 2584 | } else | ||
| 2585 | ssp->smk_packet[0] = '\0'; | ||
| 2586 | } | ||
| 2587 | |||
| 2563 | /* | 2588 | /* |
| 2564 | * Key management security hooks | 2589 | * Key management security hooks |
| 2565 | * | 2590 | * |
| @@ -2911,6 +2936,7 @@ struct security_operations smack_ops = { | |||
| 2911 | .sk_free_security = smack_sk_free_security, | 2936 | .sk_free_security = smack_sk_free_security, |
| 2912 | .sock_graft = smack_sock_graft, | 2937 | .sock_graft = smack_sock_graft, |
| 2913 | .inet_conn_request = smack_inet_conn_request, | 2938 | .inet_conn_request = smack_inet_conn_request, |
| 2939 | .inet_csk_clone = smack_inet_csk_clone, | ||
| 2914 | 2940 | ||
| 2915 | /* key management security hooks */ | 2941 | /* key management security hooks */ |
| 2916 | #ifdef CONFIG_KEYS | 2942 | #ifdef CONFIG_KEYS |
