Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 69f287a

Browse files
committed
Smack: secmark support for netfilter
Smack uses CIPSO to label internet packets and thus provide for access control on delivery of packets. The netfilter facility was not used to allow for Smack to work properly without netfilter configuration. Smack does not need netfilter, however there are cases where it would be handy. As a side effect, the labeling of local IPv4 packets can be optimized and the handling of local IPv6 packets is just all out better. The best part is that the netfilter tools use "contexts" that are just strings, and they work just as well for Smack as they do for SELinux. All of the conditional compilation for IPv6 was implemented by Rafal Krypa <[email protected]> Signed-off-by: Casey Schaufler <[email protected]>
1 parent 5e7270a commit 69f287a

File tree

5 files changed

+196
-8
lines changed

5 files changed

+196
-8
lines changed

security/smack/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,15 @@ config SECURITY_SMACK_BRINGUP
2828
access rule set once the behavior is well understood.
2929
This is a superior mechanism to the oft abused
3030
"permissive" mode of other systems.
31+
If you are unsure how to answer this question, answer N.
32+
33+
config SECURITY_SMACK_NETFILTER
34+
bool "Packet marking using secmarks for netfilter"
35+
depends on SECURITY_SMACK
36+
depends on NETWORK_SECMARK
37+
depends on NETFILTER
38+
default n
39+
help
40+
This enables security marking of network packets using
41+
Smack labels.
42+
If you are unsure how to answer this question, answer N.

security/smack/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
obj-$(CONFIG_SECURITY_SMACK) := smack.o
66

77
smack-y := smack_lsm.o smack_access.o smackfs.o
8+
smack-$(CONFIG_NETFILTER) += smack_netfilter.o

security/smack/smack.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ struct smack_known *smk_find_entry(const char *);
248248
/*
249249
* Shared data.
250250
*/
251+
extern int smack_enabled;
251252
extern int smack_cipso_direct;
252253
extern int smack_cipso_mapped;
253254
extern struct smack_known *smack_net_ambient;

security/smack/smack_lsm.c

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@
5252
#define SMK_RECEIVING 1
5353
#define SMK_SENDING 2
5454

55+
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
5556
LIST_HEAD(smk_ipv6_port_list);
57+
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
5658
static struct kmem_cache *smack_inode_cache;
59+
int smack_enabled;
5760

5861
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
5962
static void smk_bu_mode(int mode, char *s)
@@ -2213,6 +2216,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
22132216
return smack_netlabel(sk, sk_lbl);
22142217
}
22152218

2219+
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
22162220
/**
22172221
* smk_ipv6_port_label - Smack port access table management
22182222
* @sock: socket
@@ -2362,6 +2366,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
23622366
rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);
23632367
return rc;
23642368
}
2369+
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
23652370

23662371
/**
23672372
* smack_inode_setsecurity - set smack xattrs
@@ -2422,8 +2427,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
24222427
} else
24232428
return -EOPNOTSUPP;
24242429

2430+
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
24252431
if (sock->sk->sk_family == PF_INET6)
24262432
smk_ipv6_port_label(sock, NULL);
2433+
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
24272434

24282435
return 0;
24292436
}
@@ -2451,6 +2458,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
24512458
return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
24522459
}
24532460

2461+
#ifndef CONFIG_SECURITY_SMACK_NETFILTER
24542462
/**
24552463
* smack_socket_bind - record port binding information.
24562464
* @sock: the socket
@@ -2464,11 +2472,14 @@ static int smack_socket_post_create(struct socket *sock, int family,
24642472
static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
24652473
int addrlen)
24662474
{
2475+
#if IS_ENABLED(CONFIG_IPV6)
24672476
if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
24682477
smk_ipv6_port_label(sock, address);
2478+
#endif
24692479

24702480
return 0;
24712481
}
2482+
#endif /* !CONFIG_SECURITY_SMACK_NETFILTER */
24722483

24732484
/**
24742485
* smack_socket_connect - connect access check
@@ -2497,8 +2508,10 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
24972508
case PF_INET6:
24982509
if (addrlen < sizeof(struct sockaddr_in6))
24992510
return -EINVAL;
2511+
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
25002512
rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap,
25012513
SMK_CONNECTING);
2514+
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
25022515
break;
25032516
}
25042517
return rc;
@@ -3381,7 +3394,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
33813394
int size)
33823395
{
33833396
struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
3397+
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
33843398
struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
3399+
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
33853400
int rc = 0;
33863401

33873402
/*
@@ -3395,7 +3410,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
33953410
rc = smack_netlabel_send(sock->sk, sip);
33963411
break;
33973412
case AF_INET6:
3413+
#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
33983414
rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
3415+
#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
33993416
break;
34003417
}
34013418
return rc;
@@ -3486,6 +3503,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
34863503
return smack_net_ambient;
34873504
}
34883505

3506+
#if IS_ENABLED(CONFIG_IPV6)
34893507
static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
34903508
{
34913509
u8 nexthdr;
@@ -3532,6 +3550,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
35323550
}
35333551
return proto;
35343552
}
3553+
#endif /* CONFIG_IPV6 */
35353554

35363555
/**
35373556
* smack_socket_sock_rcv_skb - Smack packet delivery access check
@@ -3544,15 +3563,30 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
35443563
{
35453564
struct netlbl_lsm_secattr secattr;
35463565
struct socket_smack *ssp = sk->sk_security;
3547-
struct smack_known *skp;
3548-
struct sockaddr_in6 sadd;
3566+
struct smack_known *skp = NULL;
35493567
int rc = 0;
35503568
struct smk_audit_info ad;
35513569
#ifdef CONFIG_AUDIT
35523570
struct lsm_network_audit net;
35533571
#endif
3572+
#if IS_ENABLED(CONFIG_IPV6)
3573+
struct sockaddr_in6 sadd;
3574+
int proto;
3575+
#endif /* CONFIG_IPV6 */
3576+
35543577
switch (sk->sk_family) {
35553578
case PF_INET:
3579+
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
3580+
/*
3581+
* If there is a secmark use it rather than the CIPSO label.
3582+
* If there is no secmark fall back to CIPSO.
3583+
* The secmark is assumed to reflect policy better.
3584+
*/
3585+
if (skb && skb->secmark != 0) {
3586+
skp = smack_from_secid(skb->secmark);
3587+
goto access_check;
3588+
}
3589+
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
35563590
/*
35573591
* Translate what netlabel gave us.
35583592
*/
@@ -3566,6 +3600,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
35663600

35673601
netlbl_secattr_destroy(&secattr);
35683602

3603+
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
3604+
access_check:
3605+
#endif
35693606
#ifdef CONFIG_AUDIT
35703607
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
35713608
ad.a.u.net->family = sk->sk_family;
@@ -3584,14 +3621,32 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
35843621
if (rc != 0)
35853622
netlbl_skbuff_err(skb, rc, 0);
35863623
break;
3624+
#if IS_ENABLED(CONFIG_IPV6)
35873625
case PF_INET6:
3588-
rc = smk_skb_to_addr_ipv6(skb, &sadd);
3589-
if (rc == IPPROTO_UDP || rc == IPPROTO_TCP)
3590-
rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
3626+
proto = smk_skb_to_addr_ipv6(skb, &sadd);
3627+
if (proto != IPPROTO_UDP && proto != IPPROTO_TCP)
3628+
break;
3629+
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
3630+
if (skb && skb->secmark != 0)
3631+
skp = smack_from_secid(skb->secmark);
35913632
else
3592-
rc = 0;
3633+
skp = smack_net_ambient;
3634+
#ifdef CONFIG_AUDIT
3635+
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
3636+
ad.a.u.net->family = sk->sk_family;
3637+
ad.a.u.net->netif = skb->skb_iif;
3638+
ipv6_skb_to_auditdata(skb, &ad.a, NULL);
3639+
#endif /* CONFIG_AUDIT */
3640+
rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
3641+
rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in,
3642+
MAY_WRITE, rc);
3643+
#else /* CONFIG_SECURITY_SMACK_NETFILTER */
3644+
rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
3645+
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
35933646
break;
3647+
#endif /* CONFIG_IPV6 */
35943648
}
3649+
35953650
return rc;
35963651
}
35973652

@@ -3653,16 +3708,25 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
36533708
if (skb != NULL) {
36543709
if (skb->protocol == htons(ETH_P_IP))
36553710
family = PF_INET;
3711+
#if IS_ENABLED(CONFIG_IPV6)
36563712
else if (skb->protocol == htons(ETH_P_IPV6))
36573713
family = PF_INET6;
3714+
#endif /* CONFIG_IPV6 */
36583715
}
36593716
if (family == PF_UNSPEC && sock != NULL)
36603717
family = sock->sk->sk_family;
36613718

3662-
if (family == PF_UNIX) {
3719+
switch (family) {
3720+
case PF_UNIX:
36633721
ssp = sock->sk->sk_security;
36643722
s = ssp->smk_out->smk_secid;
3665-
} else if (family == PF_INET || family == PF_INET6) {
3723+
break;
3724+
case PF_INET:
3725+
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
3726+
s = skb->secmark;
3727+
if (s != 0)
3728+
break;
3729+
#endif
36663730
/*
36673731
* Translate what netlabel gave us.
36683732
*/
@@ -3675,6 +3739,14 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
36753739
s = skp->smk_secid;
36763740
}
36773741
netlbl_secattr_destroy(&secattr);
3742+
break;
3743+
#if IS_ENABLED(CONFIG_IPV6)
3744+
case PF_INET6:
3745+
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
3746+
s = skb->secmark;
3747+
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
3748+
break;
3749+
#endif /* CONFIG_IPV6 */
36783750
}
36793751
*secid = s;
36803752
if (s == 0)
@@ -3730,6 +3802,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
37303802
struct lsm_network_audit net;
37313803
#endif
37323804

3805+
#if IS_ENABLED(CONFIG_IPV6)
37333806
if (family == PF_INET6) {
37343807
/*
37353808
* Handle mapped IPv4 packets arriving
@@ -3741,6 +3814,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
37413814
else
37423815
return 0;
37433816
}
3817+
#endif /* CONFIG_IPV6 */
37443818

37453819
netlbl_secattr_init(&secattr);
37463820
rc = netlbl_skbuff_getattr(skb, family, &secattr);
@@ -4199,7 +4273,9 @@ struct security_operations smack_ops = {
41994273
.unix_may_send = smack_unix_may_send,
42004274

42014275
.socket_post_create = smack_socket_post_create,
4276+
#ifndef CONFIG_SECURITY_SMACK_NETFILTER
42024277
.socket_bind = smack_socket_bind,
4278+
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
42034279
.socket_connect = smack_socket_connect,
42044280
.socket_sendmsg = smack_socket_sendmsg,
42054281
.socket_sock_rcv_skb = smack_socket_sock_rcv_skb,
@@ -4280,6 +4356,8 @@ static __init int smack_init(void)
42804356
if (!security_module_enable(&smack_ops))
42814357
return 0;
42824358

4359+
smack_enabled = 1;
4360+
42834361
smack_inode_cache = KMEM_CACHE(inode_smack, 0);
42844362
if (!smack_inode_cache)
42854363
return -ENOMEM;

security/smack/smack_netfilter.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Simplified MAC Kernel (smack) security module
3+
*
4+
* This file contains the Smack netfilter implementation
5+
*
6+
* Author:
7+
* Casey Schaufler <[email protected]>
8+
*
9+
* Copyright (C) 2014 Casey Schaufler <[email protected]>
10+
* Copyright (C) 2014 Intel Corporation.
11+
*
12+
* This program is free software; you can redistribute it and/or modify
13+
* it under the terms of the GNU General Public License version 2,
14+
* as published by the Free Software Foundation.
15+
*/
16+
17+
#include <linux/netfilter_ipv4.h>
18+
#include <linux/netfilter_ipv6.h>
19+
#include <linux/netdevice.h>
20+
#include "smack.h"
21+
22+
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
23+
24+
static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops,
25+
struct sk_buff *skb,
26+
const struct net_device *in,
27+
const struct net_device *out,
28+
int (*okfn)(struct sk_buff *))
29+
{
30+
struct socket_smack *ssp;
31+
struct smack_known *skp;
32+
33+
if (skb && skb->sk && skb->sk->sk_security) {
34+
ssp = skb->sk->sk_security;
35+
skp = ssp->smk_out;
36+
skb->secmark = skp->smk_secid;
37+
}
38+
39+
return NF_ACCEPT;
40+
}
41+
#endif /* IPV6 */
42+
43+
static unsigned int smack_ipv4_output(const struct nf_hook_ops *ops,
44+
struct sk_buff *skb,
45+
const struct net_device *in,
46+
const struct net_device *out,
47+
int (*okfn)(struct sk_buff *))
48+
{
49+
struct socket_smack *ssp;
50+
struct smack_known *skp;
51+
52+
if (skb && skb->sk && skb->sk->sk_security) {
53+
ssp = skb->sk->sk_security;
54+
skp = ssp->smk_out;
55+
skb->secmark = skp->smk_secid;
56+
}
57+
58+
return NF_ACCEPT;
59+
}
60+
61+
static struct nf_hook_ops smack_nf_ops[] = {
62+
{
63+
.hook = smack_ipv4_output,
64+
.owner = THIS_MODULE,
65+
.pf = NFPROTO_IPV4,
66+
.hooknum = NF_INET_LOCAL_OUT,
67+
.priority = NF_IP_PRI_SELINUX_FIRST,
68+
},
69+
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
70+
{
71+
.hook = smack_ipv6_output,
72+
.owner = THIS_MODULE,
73+
.pf = NFPROTO_IPV6,
74+
.hooknum = NF_INET_LOCAL_OUT,
75+
.priority = NF_IP6_PRI_SELINUX_FIRST,
76+
},
77+
#endif /* IPV6 */
78+
};
79+
80+
static int __init smack_nf_ip_init(void)
81+
{
82+
int err;
83+
84+
if (smack_enabled == 0)
85+
return 0;
86+
87+
printk(KERN_DEBUG "Smack: Registering netfilter hooks\n");
88+
89+
err = nf_register_hooks(smack_nf_ops, ARRAY_SIZE(smack_nf_ops));
90+
if (err)
91+
pr_info("Smack: nf_register_hooks: error %d\n", err);
92+
93+
return 0;
94+
}
95+
96+
__initcall(smack_nf_ip_init);

0 commit comments

Comments
 (0)