Skip to content

Commit 2b980db

Browse files
pcmooreJames Morris
authored andcommitted
lsm: Add hooks to the TUN driver
The TUN driver lacks any LSM hooks which makes it difficult for LSM modules, such as SELinux, to enforce access controls on network traffic generated by TUN users; this is particularly problematic for virtualization apps such as QEMU and KVM. This patch adds three new LSM hooks designed to control the creation and attachment of TUN devices, the hooks are: * security_tun_dev_create() Provides access control for the creation of new TUN devices * security_tun_dev_post_create() Provides the ability to create the necessary socket LSM state for newly created TUN devices * security_tun_dev_attach() Provides access control for attaching to existing, persistent TUN devices and the ability to update the TUN device's socket LSM state as necessary Signed-off-by: Paul Moore <paul.moore@hp.com> Acked-by: Eric Paris <eparis@parisplace.org> Acked-by: Serge Hallyn <serue@us.ibm.com> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: James Morris <jmorris@namei.org>
1 parent d8e180d commit 2b980db

File tree

4 files changed

+83
-7
lines changed

4 files changed

+83
-7
lines changed

drivers/net/tun.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,10 @@ static inline struct tun_sock *tun_sk(struct sock *sk)
130130
static int tun_attach(struct tun_struct *tun, struct file *file)
131131
{
132132
struct tun_file *tfile = file->private_data;
133-
const struct cred *cred = current_cred();
134133
int err;
135134

136135
ASSERT_RTNL();
137136

138-
/* Check permissions */
139-
if (((tun->owner != -1 && cred->euid != tun->owner) ||
140-
(tun->group != -1 && !in_egroup_p(tun->group))) &&
141-
!capable(CAP_NET_ADMIN))
142-
return -EPERM;
143-
144137
netif_tx_lock_bh(tun->dev);
145138

146139
err = -EINVAL;
@@ -926,6 +919,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
926919

927920
dev = __dev_get_by_name(net, ifr->ifr_name);
928921
if (dev) {
922+
const struct cred *cred = current_cred();
923+
929924
if (ifr->ifr_flags & IFF_TUN_EXCL)
930925
return -EBUSY;
931926
if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
@@ -935,6 +930,14 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
935930
else
936931
return -EINVAL;
937932

933+
if (((tun->owner != -1 && cred->euid != tun->owner) ||
934+
(tun->group != -1 && !in_egroup_p(tun->group))) &&
935+
!capable(CAP_NET_ADMIN))
936+
return -EPERM;
937+
err = security_tun_dev_attach(tun->sk);
938+
if (err < 0)
939+
return err;
940+
938941
err = tun_attach(tun, file);
939942
if (err < 0)
940943
return err;
@@ -947,6 +950,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
947950

948951
if (!capable(CAP_NET_ADMIN))
949952
return -EPERM;
953+
err = security_tun_dev_create();
954+
if (err < 0)
955+
return err;
950956

951957
/* Set dev type */
952958
if (ifr->ifr_flags & IFF_TUN) {
@@ -989,6 +995,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
989995
tun->sk = sk;
990996
container_of(sk, struct tun_sock, sk)->tun = tun;
991997

998+
security_tun_dev_post_create(sk);
999+
9921000
tun_net_init(dev);
9931001

9941002
if (strchr(dev->name, '%')) {

include/linux/security.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
998998
* Sets the connection's peersid to the secmark on skb.
999999
* @req_classify_flow:
10001000
* Sets the flow's sid to the openreq sid.
1001+
* @tun_dev_create:
1002+
* Check permissions prior to creating a new TUN device.
1003+
* @tun_dev_post_create:
1004+
* This hook allows a module to update or allocate a per-socket security
1005+
* structure.
1006+
* @sk contains the newly created sock structure.
1007+
* @tun_dev_attach:
1008+
* Check permissions prior to attaching to a persistent TUN device. This
1009+
* hook can also be used by the module to update any security state
1010+
* associated with the TUN device's sock structure.
1011+
* @sk contains the existing sock structure.
10011012
*
10021013
* Security hooks for XFRM operations.
10031014
*
@@ -1597,6 +1608,9 @@ struct security_operations {
15971608
void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
15981609
void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
15991610
void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
1611+
int (*tun_dev_create)(void);
1612+
void (*tun_dev_post_create)(struct sock *sk);
1613+
int (*tun_dev_attach)(struct sock *sk);
16001614
#endif/* CONFIG_SECURITY_NETWORK */
16011615

16021616
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2586,6 +2600,9 @@ void security_inet_csk_clone(struct sock *newsk,
25862600
const struct request_sock *req);
25872601
void security_inet_conn_established(struct sock *sk,
25882602
struct sk_buff *skb);
2603+
int security_tun_dev_create(void);
2604+
void security_tun_dev_post_create(struct sock *sk);
2605+
int security_tun_dev_attach(struct sock *sk);
25892606

25902607
#else/* CONFIG_SECURITY_NETWORK */
25912608
static inline int security_unix_stream_connect(struct socket *sock,
@@ -2736,6 +2753,20 @@ static inline void security_inet_conn_established(struct sock *sk,
27362753
struct sk_buff *skb)
27372754
{
27382755
}
2756+
2757+
static inline int security_tun_dev_create(void)
2758+
{
2759+
return 0;
2760+
}
2761+
2762+
static inline void security_tun_dev_post_create(struct sock *sk)
2763+
{
2764+
}
2765+
2766+
static inline int security_tun_dev_attach(struct sock *sk)
2767+
{
2768+
return 0;
2769+
}
27392770
#endif/* CONFIG_SECURITY_NETWORK */
27402771

27412772
#ifdef CONFIG_SECURITY_NETWORK_XFRM

security/capability.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,10 +706,26 @@ static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb)
706706
{
707707
}
708708

709+
710+
709711
static void cap_req_classify_flow(const struct request_sock *req,
710712
struct flowi *fl)
711713
{
712714
}
715+
716+
static int cap_tun_dev_create(void)
717+
{
718+
return 0;
719+
}
720+
721+
static void cap_tun_dev_post_create(struct sock *sk)
722+
{
723+
}
724+
725+
static int cap_tun_dev_attach(struct sock *sk)
726+
{
727+
return 0;
728+
}
713729
#endif/* CONFIG_SECURITY_NETWORK */
714730

715731
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1026,6 +1042,9 @@ void security_fixup_ops(struct security_operations *ops)
10261042
set_to_cap_if_null(ops, inet_csk_clone);
10271043
set_to_cap_if_null(ops, inet_conn_established);
10281044
set_to_cap_if_null(ops, req_classify_flow);
1045+
set_to_cap_if_null(ops, tun_dev_create);
1046+
set_to_cap_if_null(ops, tun_dev_post_create);
1047+
set_to_cap_if_null(ops, tun_dev_attach);
10291048
#endif/* CONFIG_SECURITY_NETWORK */
10301049
#ifdef CONFIG_SECURITY_NETWORK_XFRM
10311050
set_to_cap_if_null(ops, xfrm_policy_alloc_security);

security/security.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,24 @@ void security_inet_conn_established(struct sock *sk,
11171117
security_ops->inet_conn_established(sk, skb);
11181118
}
11191119

1120+
int security_tun_dev_create(void)
1121+
{
1122+
return security_ops->tun_dev_create();
1123+
}
1124+
EXPORT_SYMBOL(security_tun_dev_create);
1125+
1126+
void security_tun_dev_post_create(struct sock *sk)
1127+
{
1128+
return security_ops->tun_dev_post_create(sk);
1129+
}
1130+
EXPORT_SYMBOL(security_tun_dev_post_create);
1131+
1132+
int security_tun_dev_attach(struct sock *sk)
1133+
{
1134+
return security_ops->tun_dev_attach(sk);
1135+
}
1136+
EXPORT_SYMBOL(security_tun_dev_attach);
1137+
11201138
#endif/* CONFIG_SECURITY_NETWORK */
11211139

11221140
#ifdef CONFIG_SECURITY_NETWORK_XFRM

0 commit comments

Comments
 (0)