Skip to content

Commit 5dbbaf2

Browse files
pcmooredavem330
authored andcommitted
tun: fix LSM/SELinux labeling of tun/tap devices
This patch corrects some problems with LSM/SELinux that were introduced with the multiqueue patchset. The problem stems from the fact that the multiqueue work changed the relationship between the tun device and its associated socket; before the socket persisted for the life of the device, however after the multiqueue changes the socket only persisted for the life of the userspace connection (fd open). For non-persistent devices this is not an issue, but for persistent devices this can cause the tun device to lose its SELinux label. We correct this problem by adding an opaque LSM security blob to the tun device struct which allows us to have the LSM security state, e.g. SELinux labeling information, persist for the lifetime of the tun device. In the process we tweak the LSM hooks to work with this new approach to TUN device/socket labeling and introduce a new LSM hook, security_tun_dev_attach_queue(), to approve requests to attach to a TUN queue via TUNSETQUEUE. The SELinux code has been adjusted to match the new LSM hooks, the other LSMs do not make use of the LSM TUN controls. This patch makes use of the recently added "tun_socket:attach_queue" permission to restrict access to the TUNSETQUEUE operation. On older SELinux policies which do not define the "tun_socket:attach_queue" permission the access control decision for TUNSETQUEUE will be handled according to the SELinux policy's unknown permission setting. Signed-off-by: Paul Moore <pmoore@redhat.com> Acked-by: Eric Paris <eparis@parisplace.org> Tested-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 6f96c14 commit 5dbbaf2

File tree

6 files changed

+151
-37
lines changed

6 files changed

+151
-37
lines changed

drivers/net/tun.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ struct tun_struct {
185185
unsigned long ageing_time;
186186
unsigned int numdisabled;
187187
struct list_head disabled;
188+
void *security;
188189
};
189190

190191
static inline u32 tun_hashfn(u32 rxhash)
@@ -490,6 +491,10 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
490491
struct tun_file *tfile = file->private_data;
491492
int err;
492493

494+
err = security_tun_dev_attach(tfile->socket.sk, tun->security);
495+
if (err < 0)
496+
goto out;
497+
493498
err = -EINVAL;
494499
if (rtnl_dereference(tfile->tun))
495500
goto out;
@@ -1373,6 +1378,7 @@ static void tun_free_netdev(struct net_device *dev)
13731378

13741379
BUG_ON(!(list_empty(&tun->disabled)));
13751380
tun_flow_uninit(tun);
1381+
security_tun_dev_free_security(tun->security);
13761382
free_netdev(dev);
13771383
}
13781384

@@ -1562,7 +1568,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
15621568

15631569
if (tun_not_capable(tun))
15641570
return -EPERM;
1565-
err = security_tun_dev_attach(tfile->socket.sk);
1571+
err = security_tun_dev_open(tun->security);
15661572
if (err < 0)
15671573
return err;
15681574

@@ -1619,7 +1625,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
16191625

16201626
spin_lock_init(&tun->lock);
16211627

1622-
security_tun_dev_post_create(&tfile->sk);
1628+
err = security_tun_dev_alloc_security(&tun->security);
1629+
if (err < 0)
1630+
goto err_free_dev;
16231631

16241632
tun_net_init(dev);
16251633

@@ -1789,10 +1797,14 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
17891797

17901798
if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
17911799
tun = tfile->detached;
1792-
if (!tun)
1800+
if (!tun) {
17931801
ret = -EINVAL;
1794-
else
1795-
ret = tun_attach(tun, file);
1802+
goto unlock;
1803+
}
1804+
ret = security_tun_dev_attach_queue(tun->security);
1805+
if (ret < 0)
1806+
goto unlock;
1807+
ret = tun_attach(tun, file);
17961808
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
17971809
tun = rtnl_dereference(tfile->tun);
17981810
if (!tun || !(tun->flags & TUN_TAP_MQ))
@@ -1802,6 +1814,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
18021814
} else
18031815
ret = -EINVAL;
18041816

1817+
unlock:
18051818
rtnl_unlock();
18061819
return ret;
18071820
}

include/linux/security.h

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -989,17 +989,29 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
989989
* tells the LSM to decrement the number of secmark labeling rules loaded
990990
* @req_classify_flow:
991991
* Sets the flow's sid to the openreq sid.
992+
* @tun_dev_alloc_security:
993+
* This hook allows a module to allocate a security structure for a TUN
994+
* device.
995+
* @security pointer to a security structure pointer.
996+
* Returns a zero on success, negative values on failure.
997+
* @tun_dev_free_security:
998+
* This hook allows a module to free the security structure for a TUN
999+
* device.
1000+
* @security pointer to the TUN device's security structure
9921001
* @tun_dev_create:
9931002
* Check permissions prior to creating a new TUN device.
994-
* @tun_dev_post_create:
995-
* This hook allows a module to update or allocate a per-socket security
996-
* structure.
997-
* @sk contains the newly created sock structure.
1003+
* @tun_dev_attach_queue:
1004+
* Check permissions prior to attaching to a TUN device queue.
1005+
* @security pointer to the TUN device's security structure.
9981006
* @tun_dev_attach:
999-
* Check permissions prior to attaching to a persistent TUN device. This
1000-
* hook can also be used by the module to update any security state
1007+
* This hook can be used by the module to update any security state
10011008
* associated with the TUN device's sock structure.
10021009
* @sk contains the existing sock structure.
1010+
* @security pointer to the TUN device's security structure.
1011+
* @tun_dev_open:
1012+
* This hook can be used by the module to update any security state
1013+
* associated with the TUN device's security structure.
1014+
* @security pointer to the TUN devices's security structure.
10031015
*
10041016
* Security hooks for XFRM operations.
10051017
*
@@ -1620,9 +1632,12 @@ struct security_operations {
16201632
void (*secmark_refcount_inc) (void);
16211633
void (*secmark_refcount_dec) (void);
16221634
void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
1623-
int (*tun_dev_create)(void);
1624-
void (*tun_dev_post_create)(struct sock *sk);
1625-
int (*tun_dev_attach)(struct sock *sk);
1635+
int (*tun_dev_alloc_security) (void **security);
1636+
void (*tun_dev_free_security) (void *security);
1637+
int (*tun_dev_create) (void);
1638+
int (*tun_dev_attach_queue) (void *security);
1639+
int (*tun_dev_attach) (struct sock *sk, void *security);
1640+
int (*tun_dev_open) (void *security);
16261641
#endif/* CONFIG_SECURITY_NETWORK */
16271642

16281643
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2566,9 +2581,12 @@ void security_inet_conn_established(struct sock *sk,
25662581
int security_secmark_relabel_packet(u32 secid);
25672582
void security_secmark_refcount_inc(void);
25682583
void security_secmark_refcount_dec(void);
2584+
int security_tun_dev_alloc_security(void **security);
2585+
void security_tun_dev_free_security(void *security);
25692586
int security_tun_dev_create(void);
2570-
void security_tun_dev_post_create(struct sock *sk);
2571-
int security_tun_dev_attach(struct sock *sk);
2587+
int security_tun_dev_attach_queue(void *security);
2588+
int security_tun_dev_attach(struct sock *sk, void *security);
2589+
int security_tun_dev_open(void *security);
25722590

25732591
#else/* CONFIG_SECURITY_NETWORK */
25742592
static inline int security_unix_stream_connect(struct sock *sock,
@@ -2733,16 +2751,31 @@ static inline void security_secmark_refcount_dec(void)
27332751
{
27342752
}
27352753

2754+
static inline int security_tun_dev_alloc_security(void **security)
2755+
{
2756+
return 0;
2757+
}
2758+
2759+
static inline void security_tun_dev_free_security(void *security)
2760+
{
2761+
}
2762+
27362763
static inline int security_tun_dev_create(void)
27372764
{
27382765
return 0;
27392766
}
27402767

2741-
static inline void security_tun_dev_post_create(struct sock *sk)
2768+
static inline int security_tun_dev_attach_queue(void *security)
2769+
{
2770+
return 0;
2771+
}
2772+
2773+
static inline int security_tun_dev_attach(struct sock *sk, void *security)
27422774
{
2775+
return 0;
27432776
}
27442777

2745-
static inline int security_tun_dev_attach(struct sock *sk)
2778+
static inline int security_tun_dev_open(void *security)
27462779
{
27472780
return 0;
27482781
}

security/capability.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -709,16 +709,31 @@ static void cap_req_classify_flow(const struct request_sock *req,
709709
{
710710
}
711711

712+
static int cap_tun_dev_alloc_security(void **security)
713+
{
714+
return 0;
715+
}
716+
717+
static void cap_tun_dev_free_security(void *security)
718+
{
719+
}
720+
712721
static int cap_tun_dev_create(void)
713722
{
714723
return 0;
715724
}
716725

717-
static void cap_tun_dev_post_create(struct sock *sk)
726+
static int cap_tun_dev_attach_queue(void *security)
727+
{
728+
return 0;
729+
}
730+
731+
static int cap_tun_dev_attach(struct sock *sk, void *security)
718732
{
733+
return 0;
719734
}
720735

721-
static int cap_tun_dev_attach(struct sock *sk)
736+
static int cap_tun_dev_open(void *security)
722737
{
723738
return 0;
724739
}
@@ -1050,8 +1065,11 @@ void __init security_fixup_ops(struct security_operations *ops)
10501065
set_to_cap_if_null(ops, secmark_refcount_inc);
10511066
set_to_cap_if_null(ops, secmark_refcount_dec);
10521067
set_to_cap_if_null(ops, req_classify_flow);
1068+
set_to_cap_if_null(ops, tun_dev_alloc_security);
1069+
set_to_cap_if_null(ops, tun_dev_free_security);
10531070
set_to_cap_if_null(ops, tun_dev_create);
1054-
set_to_cap_if_null(ops, tun_dev_post_create);
1071+
set_to_cap_if_null(ops, tun_dev_open);
1072+
set_to_cap_if_null(ops, tun_dev_attach_queue);
10551073
set_to_cap_if_null(ops, tun_dev_attach);
10561074
#endif/* CONFIG_SECURITY_NETWORK */
10571075
#ifdef CONFIG_SECURITY_NETWORK_XFRM

security/security.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,24 +1254,42 @@ void security_secmark_refcount_dec(void)
12541254
}
12551255
EXPORT_SYMBOL(security_secmark_refcount_dec);
12561256

1257+
int security_tun_dev_alloc_security(void **security)
1258+
{
1259+
return security_ops->tun_dev_alloc_security(security);
1260+
}
1261+
EXPORT_SYMBOL(security_tun_dev_alloc_security);
1262+
1263+
void security_tun_dev_free_security(void *security)
1264+
{
1265+
security_ops->tun_dev_free_security(security);
1266+
}
1267+
EXPORT_SYMBOL(security_tun_dev_free_security);
1268+
12571269
int security_tun_dev_create(void)
12581270
{
12591271
return security_ops->tun_dev_create();
12601272
}
12611273
EXPORT_SYMBOL(security_tun_dev_create);
12621274

1263-
void security_tun_dev_post_create(struct sock *sk)
1275+
int security_tun_dev_attach_queue(void *security)
12641276
{
1265-
return security_ops->tun_dev_post_create(sk);
1277+
return security_ops->tun_dev_attach_queue(security);
12661278
}
1267-
EXPORT_SYMBOL(security_tun_dev_post_create);
1279+
EXPORT_SYMBOL(security_tun_dev_attach_queue);
12681280

1269-
int security_tun_dev_attach(struct sock *sk)
1281+
int security_tun_dev_attach(struct sock *sk, void *security)
12701282
{
1271-
return security_ops->tun_dev_attach(sk);
1283+
return security_ops->tun_dev_attach(sk, security);
12721284
}
12731285
EXPORT_SYMBOL(security_tun_dev_attach);
12741286

1287+
int security_tun_dev_open(void *security)
1288+
{
1289+
return security_ops->tun_dev_open(security);
1290+
}
1291+
EXPORT_SYMBOL(security_tun_dev_open);
1292+
12751293
#endif/* CONFIG_SECURITY_NETWORK */
12761294

12771295
#ifdef CONFIG_SECURITY_NETWORK_XFRM

security/selinux/hooks.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4399,6 +4399,24 @@ static void selinux_req_classify_flow(const struct request_sock *req,
43994399
fl->flowi_secid = req->secid;
44004400
}
44014401

4402+
static int selinux_tun_dev_alloc_security(void **security)
4403+
{
4404+
struct tun_security_struct *tunsec;
4405+
4406+
tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4407+
if (!tunsec)
4408+
return -ENOMEM;
4409+
tunsec->sid = current_sid();
4410+
4411+
*security = tunsec;
4412+
return 0;
4413+
}
4414+
4415+
static void selinux_tun_dev_free_security(void *security)
4416+
{
4417+
kfree(security);
4418+
}
4419+
44024420
static int selinux_tun_dev_create(void)
44034421
{
44044422
u32 sid = current_sid();
@@ -4414,8 +4432,17 @@ static int selinux_tun_dev_create(void)
44144432
NULL);
44154433
}
44164434

4417-
static void selinux_tun_dev_post_create(struct sock *sk)
4435+
static int selinux_tun_dev_attach_queue(void *security)
44184436
{
4437+
struct tun_security_struct *tunsec = security;
4438+
4439+
return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4440+
TUN_SOCKET__ATTACH_QUEUE, NULL);
4441+
}
4442+
4443+
static int selinux_tun_dev_attach(struct sock *sk, void *security)
4444+
{
4445+
struct tun_security_struct *tunsec = security;
44194446
struct sk_security_struct *sksec = sk->sk_security;
44204447

44214448
/* we don't currently perform any NetLabel based labeling here and it
@@ -4425,29 +4452,27 @@ static void selinux_tun_dev_post_create(struct sock *sk)
44254452
* cause confusion to the TUN user that had no idea network labeling
44264453
* protocols were being used */
44274454

4428-
/* see the comments in selinux_tun_dev_create() about why we don't use
4429-
* the sockcreate SID here */
4430-
4431-
sksec->sid = current_sid();
4455+
sksec->sid = tunsec->sid;
44324456
sksec->sclass = SECCLASS_TUN_SOCKET;
4457+
4458+
return 0;
44334459
}
44344460

4435-
static int selinux_tun_dev_attach(struct sock *sk)
4461+
static int selinux_tun_dev_open(void *security)
44364462
{
4437-
struct sk_security_struct *sksec = sk->sk_security;
4463+
struct tun_security_struct *tunsec = security;
44384464
u32 sid = current_sid();
44394465
int err;
44404466

4441-
err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
4467+
err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
44424468
TUN_SOCKET__RELABELFROM, NULL);
44434469
if (err)
44444470
return err;
44454471
err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
44464472
TUN_SOCKET__RELABELTO, NULL);
44474473
if (err)
44484474
return err;
4449-
4450-
sksec->sid = sid;
4475+
tunsec->sid = sid;
44514476

44524477
return 0;
44534478
}
@@ -5642,9 +5667,12 @@ static struct security_operations selinux_ops = {
56425667
.secmark_refcount_inc =selinux_secmark_refcount_inc,
56435668
.secmark_refcount_dec =selinux_secmark_refcount_dec,
56445669
.req_classify_flow =selinux_req_classify_flow,
5670+
.tun_dev_alloc_security =selinux_tun_dev_alloc_security,
5671+
.tun_dev_free_security =selinux_tun_dev_free_security,
56455672
.tun_dev_create =selinux_tun_dev_create,
5646-
.tun_dev_post_create = selinux_tun_dev_post_create,
5673+
.tun_dev_attach_queue =selinux_tun_dev_attach_queue,
56475674
.tun_dev_attach =selinux_tun_dev_attach,
5675+
.tun_dev_open =selinux_tun_dev_open,
56485676

56495677
#ifdef CONFIG_SECURITY_NETWORK_XFRM
56505678
.xfrm_policy_alloc_security =selinux_xfrm_policy_alloc,

security/selinux/include/objsec.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ struct sk_security_struct {
110110
u16 sclass;/* sock security class */
111111
};
112112

113+
struct tun_security_struct {
114+
u32 sid;/* SID for the tun device sockets */
115+
};
116+
113117
struct key_security_struct {
114118
u32 sid;/* SID of key */
115119
};

0 commit comments

Comments
 (0)