aboutsummaryrefslogtreecommitdiff
path: root/net/netlabel/netlabel_kapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlabel/netlabel_kapi.c')
-rw-r--r--net/netlabel/netlabel_kapi.c271
1 files changed, 193 insertions, 78 deletions
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index fd9229db075..3045a964f39 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -5,7 +5,7 @@
* system manages static and dynamic label mappings for network protocols such
* as CIPSO and RIPSO.
*
- * Author: Paul Moore <paul.moore@hp.com>
+ * Author: Paul Moore <paul@paul-moore.com>
*
*/
@@ -23,13 +23,13 @@
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/slab.h>
#include <linux/audit.h>
#include <linux/in.h>
#include <linux/in6.h>
@@ -38,7 +38,7 @@
#include <net/netlabel.h>
#include <net/cipso_ipv4.h>
#include <asm/bug.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "netlabel_domainhash.h"
#include "netlabel_unlabeled.h"
@@ -110,8 +110,6 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
struct netlbl_domaddr_map *addrmap = NULL;
struct netlbl_domaddr4_map *map4 = NULL;
struct netlbl_domaddr6_map *map6 = NULL;
- const struct in_addr *addr4, *mask4;
- const struct in6_addr *addr6, *mask6;
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL)
@@ -123,7 +121,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
}
if (addr == NULL && mask == NULL)
- entry->type = NETLBL_NLTYPE_UNLABELED;
+ entry->def.type = NETLBL_NLTYPE_UNLABELED;
else if (addr != NULL && mask != NULL) {
addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
if (addrmap == NULL)
@@ -132,13 +130,13 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
INIT_LIST_HEAD(&addrmap->list6);
switch (family) {
- case AF_INET:
- addr4 = addr;
- mask4 = mask;
+ case AF_INET: {
+ const struct in_addr *addr4 = addr;
+ const struct in_addr *mask4 = mask;
map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
if (map4 == NULL)
goto cfg_unlbl_map_add_failure;
- map4->type = NETLBL_NLTYPE_UNLABELED;
+ map4->def.type = NETLBL_NLTYPE_UNLABELED;
map4->list.addr = addr4->s_addr & mask4->s_addr;
map4->list.mask = mask4->s_addr;
map4->list.valid = 1;
@@ -147,32 +145,36 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
if (ret_val != 0)
goto cfg_unlbl_map_add_failure;
break;
- case AF_INET6:
- addr6 = addr;
- mask6 = mask;
+ }
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6: {
+ const struct in6_addr *addr6 = addr;
+ const struct in6_addr *mask6 = mask;
map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
- if (map4 == NULL)
+ if (map6 == NULL)
goto cfg_unlbl_map_add_failure;
- map6->type = NETLBL_NLTYPE_UNLABELED;
- ipv6_addr_copy(&map6->list.addr, addr6);
+ map6->def.type = NETLBL_NLTYPE_UNLABELED;
+ map6->list.addr = *addr6;
map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
- ipv6_addr_copy(&map6->list.mask, mask6);
+ map6->list.mask = *mask6;
map6->list.valid = 1;
- ret_val = netlbl_af4list_add(&map4->list,
- &addrmap->list4);
+ ret_val = netlbl_af6list_add(&map6->list,
+ &addrmap->list6);
if (ret_val != 0)
goto cfg_unlbl_map_add_failure;
break;
+ }
+#endif /* IPv6 */
default:
goto cfg_unlbl_map_add_failure;
break;
}
- entry->type_def.addrsel = addrmap;
- entry->type = NETLBL_NLTYPE_ADDRSELECT;
+ entry->def.addrsel = addrmap;
+ entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
} else {
ret_val = -EINVAL;
goto cfg_unlbl_map_add_failure;
@@ -185,8 +187,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
return 0;
cfg_unlbl_map_add_failure:
- if (entry != NULL)
- kfree(entry->domain);
+ kfree(entry->domain);
kfree(entry);
kfree(addrmap);
kfree(map4);
@@ -225,9 +226,11 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
case AF_INET:
addr_len = sizeof(struct in_addr);
break;
+#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
addr_len = sizeof(struct in6_addr);
break;
+#endif /* IPv6 */
default:
return -EPFNOSUPPORT;
}
@@ -266,9 +269,11 @@ int netlbl_cfg_unlbl_static_del(struct net *net,
case AF_INET:
addr_len = sizeof(struct in_addr);
break;
+#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
addr_len = sizeof(struct in6_addr);
break;
+#endif /* IPv6 */
default:
return -EPFNOSUPPORT;
}
@@ -341,28 +346,28 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL)
- return -ENOMEM;
+ goto out_entry;
if (domain != NULL) {
entry->domain = kstrdup(domain, GFP_ATOMIC);
if (entry->domain == NULL)
- goto cfg_cipsov4_map_add_failure;
+ goto out_domain;
}
if (addr == NULL && mask == NULL) {
- entry->type_def.cipsov4 = doi_def;
- entry->type = NETLBL_NLTYPE_CIPSOV4;
+ entry->def.cipso = doi_def;
+ entry->def.type = NETLBL_NLTYPE_CIPSOV4;
} else if (addr != NULL && mask != NULL) {
addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
if (addrmap == NULL)
- goto cfg_cipsov4_map_add_failure;
+ goto out_addrmap;
INIT_LIST_HEAD(&addrmap->list4);
INIT_LIST_HEAD(&addrmap->list6);
addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
if (addrinfo == NULL)
- goto cfg_cipsov4_map_add_failure;
- addrinfo->type_def.cipsov4 = doi_def;
- addrinfo->type = NETLBL_NLTYPE_CIPSOV4;
+ goto out_addrinfo;
+ addrinfo->def.cipso = doi_def;
+ addrinfo->def.type = NETLBL_NLTYPE_CIPSOV4;
addrinfo->list.addr = addr->s_addr & mask->s_addr;
addrinfo->list.mask = mask->s_addr;
addrinfo->list.valid = 1;
@@ -370,11 +375,11 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
if (ret_val != 0)
goto cfg_cipsov4_map_add_failure;
- entry->type_def.addrsel = addrmap;
- entry->type = NETLBL_NLTYPE_ADDRSELECT;
+ entry->def.addrsel = addrmap;
+ entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
} else {
ret_val = -EINVAL;
- goto cfg_cipsov4_map_add_failure;
+ goto out_addrmap;
}
ret_val = netlbl_domhsh_add(entry, audit_info);
@@ -384,12 +389,15 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
return 0;
cfg_cipsov4_map_add_failure:
- cipso_v4_doi_putdef(doi_def);
- if (entry != NULL)
- kfree(entry->domain);
- kfree(entry);
- kfree(addrmap);
kfree(addrinfo);
+out_addrinfo:
+ kfree(addrmap);
+out_addrmap:
+ kfree(entry->domain);
+out_domain:
+ kfree(entry);
+out_entry:
+ cipso_v4_doi_putdef(doi_def);
return ret_val;
}
@@ -588,7 +596,7 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
iter = iter->next;
iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
}
- ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC);
+ ret_val = netlbl_secattr_catmap_setbit(iter, spot, flags);
}
return ret_val;
@@ -619,8 +627,9 @@ int netlbl_enabled(void)
}
/**
- * netlbl_socket_setattr - Label a socket using the correct protocol
+ * netlbl_sock_setattr - Label a socket using the correct protocol
* @sk: the socket to label
+ * @family: protocol family
* @secattr: the security attributes
*
* Description:
@@ -633,29 +642,45 @@ int netlbl_enabled(void)
*
*/
int netlbl_sock_setattr(struct sock *sk,
+ u16 family,
const struct netlbl_lsm_secattr *secattr)
{
- int ret_val = -ENOENT;
+ int ret_val;
struct netlbl_dom_map *dom_entry;
rcu_read_lock();
dom_entry = netlbl_domhsh_getentry(secattr->domain);
- if (dom_entry == NULL)
+ if (dom_entry == NULL) {
+ ret_val = -ENOENT;
goto socket_setattr_return;
- switch (dom_entry->type) {
- case NETLBL_NLTYPE_ADDRSELECT:
- ret_val = -EDESTADDRREQ;
- break;
- case NETLBL_NLTYPE_CIPSOV4:
- ret_val = cipso_v4_sock_setattr(sk,
- dom_entry->type_def.cipsov4,
- secattr);
+ }
+ switch (family) {
+ case AF_INET:
+ switch (dom_entry->def.type) {
+ case NETLBL_NLTYPE_ADDRSELECT:
+ ret_val = -EDESTADDRREQ;
+ break;
+ case NETLBL_NLTYPE_CIPSOV4:
+ ret_val = cipso_v4_sock_setattr(sk,
+ dom_entry->def.cipso,
+ secattr);
+ break;
+ case NETLBL_NLTYPE_UNLABELED:
+ ret_val = 0;
+ break;
+ default:
+ ret_val = -ENOENT;
+ }
break;
- case NETLBL_NLTYPE_UNLABELED:
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6:
+ /* since we don't support any IPv6 labeling protocols right
+ * now we can optimize everything away until we do */
ret_val = 0;
break;
+#endif /* IPv6 */
default:
- ret_val = -ENOENT;
+ ret_val = -EPROTONOSUPPORT;
}
socket_setattr_return:
@@ -689,9 +714,25 @@ void netlbl_sock_delattr(struct sock *sk)
* on failure.
*
*/
-int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
+int netlbl_sock_getattr(struct sock *sk,
+ struct netlbl_lsm_secattr *secattr)
{
- return cipso_v4_sock_getattr(sk, secattr);
+ int ret_val;
+
+ switch (sk->sk_family) {
+ case AF_INET:
+ ret_val = cipso_v4_sock_getattr(sk, secattr);
+ break;
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6:
+ ret_val = -ENOMSG;
+ break;
+#endif /* IPv6 */
+ default:
+ ret_val = -EPROTONOSUPPORT;
+ }
+
+ return ret_val;
}
/**
@@ -712,23 +753,22 @@ int netlbl_conn_setattr(struct sock *sk,
{
int ret_val;
struct sockaddr_in *addr4;
- struct netlbl_domaddr4_map *af4_entry;
+ struct netlbl_dommap_def *entry;
rcu_read_lock();
switch (addr->sa_family) {
case AF_INET:
addr4 = (struct sockaddr_in *)addr;
- af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
- addr4->sin_addr.s_addr);
- if (af4_entry == NULL) {
+ entry = netlbl_domhsh_getentry_af4(secattr->domain,
+ addr4->sin_addr.s_addr);
+ if (entry == NULL) {
ret_val = -ENOENT;
goto conn_setattr_return;
}
- switch (af4_entry->type) {
+ switch (entry->type) {
case NETLBL_NLTYPE_CIPSOV4:
ret_val = cipso_v4_sock_setattr(sk,
- af4_entry->type_def.cipsov4,
- secattr);
+ entry->cipso, secattr);
break;
case NETLBL_NLTYPE_UNLABELED:
/* just delete the protocols we support for right now
@@ -740,7 +780,7 @@ int netlbl_conn_setattr(struct sock *sk,
ret_val = -ENOENT;
}
break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
/* since we don't support any IPv6 labeling protocols right
* now we can optimize everything away until we do */
@@ -748,7 +788,7 @@ int netlbl_conn_setattr(struct sock *sk,
break;
#endif /* IPv6 */
default:
- ret_val = 0;
+ ret_val = -EPROTONOSUPPORT;
}
conn_setattr_return:
@@ -757,6 +797,75 @@ conn_setattr_return:
}
/**
+ * netlbl_req_setattr - Label a request socket using the correct protocol
+ * @req: the request socket to label
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Attach the correct label to the given socket using the security attributes
+ * specified in @secattr. Returns zero on success, negative values on failure.
+ *
+ */
+int netlbl_req_setattr(struct request_sock *req,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val;
+ struct netlbl_dommap_def *entry;
+
+ rcu_read_lock();
+ switch (req->rsk_ops->family) {
+ case AF_INET:
+ entry = netlbl_domhsh_getentry_af4(secattr->domain,
+ inet_rsk(req)->ir_rmt_addr);
+ if (entry == NULL) {
+ ret_val = -ENOENT;
+ goto req_setattr_return;
+ }
+ switch (entry->type) {
+ case NETLBL_NLTYPE_CIPSOV4:
+ ret_val = cipso_v4_req_setattr(req,
+ entry->cipso, secattr);
+ break;
+ case NETLBL_NLTYPE_UNLABELED:
+ /* just delete the protocols we support for right now
+ * but we could remove other protocols if needed */
+ cipso_v4_req_delattr(req);
+ ret_val = 0;
+ break;
+ default:
+ ret_val = -ENOENT;
+ }
+ break;
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6:
+ /* since we don't support any IPv6 labeling protocols right
+ * now we can optimize everything away until we do */
+ ret_val = 0;
+ break;
+#endif /* IPv6 */
+ default:
+ ret_val = -EPROTONOSUPPORT;
+ }
+
+req_setattr_return:
+ rcu_read_unlock();
+ return ret_val;
+}
+
+/**
+* netlbl_req_delattr - Delete all the NetLabel labels on a socket
+* @req: the socket
+*
+* Description:
+* Remove all the NetLabel labeling from @req.
+*
+*/
+void netlbl_req_delattr(struct request_sock *req)
+{
+ cipso_v4_req_delattr(req);
+}
+
+/**
* netlbl_skbuff_setattr - Label a packet using the correct protocol
* @skb: the packet
* @family: protocol family
@@ -773,23 +882,21 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
{
int ret_val;
struct iphdr *hdr4;
- struct netlbl_domaddr4_map *af4_entry;
+ struct netlbl_dommap_def *entry;
rcu_read_lock();
switch (family) {
case AF_INET:
hdr4 = ip_hdr(skb);
- af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
- hdr4->daddr);
- if (af4_entry == NULL) {
+ entry = netlbl_domhsh_getentry_af4(secattr->domain,hdr4->daddr);
+ if (entry == NULL) {
ret_val = -ENOENT;
goto skbuff_setattr_return;
}
- switch (af4_entry->type) {
+ switch (entry->type) {
case NETLBL_NLTYPE_CIPSOV4:
- ret_val = cipso_v4_skbuff_setattr(skb,
- af4_entry->type_def.cipsov4,
- secattr);
+ ret_val = cipso_v4_skbuff_setattr(skb, entry->cipso,
+ secattr);
break;
case NETLBL_NLTYPE_UNLABELED:
/* just delete the protocols we support for right now
@@ -800,7 +907,7 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
ret_val = -ENOENT;
}
break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
/* since we don't support any IPv6 labeling protocols right
* now we can optimize everything away until we do */
@@ -808,7 +915,7 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
break;
#endif /* IPv6 */
default:
- ret_val = 0;
+ ret_val = -EPROTONOSUPPORT;
}
skbuff_setattr_return:
@@ -833,9 +940,17 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
u16 family,
struct netlbl_lsm_secattr *secattr)
{
- if (CIPSO_V4_OPTEXIST(skb) &&
- cipso_v4_skbuff_getattr(skb, secattr) == 0)
- return 0;
+ switch (family) {
+ case AF_INET:
+ if (CIPSO_V4_OPTEXIST(skb) &&
+ cipso_v4_skbuff_getattr(skb, secattr) == 0)
+ return 0;
+ break;
+#if IS_ENABLED(CONFIG_IPV6)
+ case AF_INET6:
+ break;
+#endif /* IPv6 */
+ }
return netlbl_unlabel_getattr(skb, family, secattr);
}