Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 349188
b: refs/heads/master
c: 5dbbaf2
h: refs/heads/master
v: v3
  • Loading branch information
Paul Moore authored and David S. Miller committed Jan 14, 2013
1 parent d77ee43 commit 07a7d1f
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 38 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6f96c142f77c96a34ac377a3616ee7abcd77fb4d
refs/heads/master: 5dbbaf2de89613d19a9286d4db0a535ca2735d26
23 changes: 18 additions & 5 deletions trunk/drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ struct tun_struct {
unsigned long ageing_time;
unsigned int numdisabled;
struct list_head disabled;
void *security;
};

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

err = security_tun_dev_attach(tfile->socket.sk, tun->security);
if (err < 0)
goto out;

err = -EINVAL;
if (rtnl_dereference(tfile->tun))
goto out;
Expand Down Expand Up @@ -1373,6 +1378,7 @@ static void tun_free_netdev(struct net_device *dev)

BUG_ON(!(list_empty(&tun->disabled)));
tun_flow_uninit(tun);
security_tun_dev_free_security(tun->security);
free_netdev(dev);
}

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

if (tun_not_capable(tun))
return -EPERM;
err = security_tun_dev_attach(tfile->socket.sk);
err = security_tun_dev_open(tun->security);
if (err < 0)
return err;

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

spin_lock_init(&tun->lock);

security_tun_dev_post_create(&tfile->sk);
err = security_tun_dev_alloc_security(&tun->security);
if (err < 0)
goto err_free_dev;

tun_net_init(dev);

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

if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
tun = tfile->detached;
if (!tun)
if (!tun) {
ret = -EINVAL;
else
ret = tun_attach(tun, file);
goto unlock;
}
ret = security_tun_dev_attach_queue(tun->security);
if (ret < 0)
goto unlock;
ret = tun_attach(tun, file);
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
tun = rtnl_dereference(tfile->tun);
if (!tun || !(tun->flags & TUN_TAP_MQ))
Expand All @@ -1802,6 +1814,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
} else
ret = -EINVAL;

unlock:
rtnl_unlock();
return ret;
}
Expand Down
59 changes: 46 additions & 13 deletions trunk/include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -989,17 +989,29 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* tells the LSM to decrement the number of secmark labeling rules loaded
* @req_classify_flow:
* Sets the flow's sid to the openreq sid.
* @tun_dev_alloc_security:
* This hook allows a module to allocate a security structure for a TUN
* device.
* @security pointer to a security structure pointer.
* Returns a zero on success, negative values on failure.
* @tun_dev_free_security:
* This hook allows a module to free the security structure for a TUN
* device.
* @security pointer to the TUN device's security structure
* @tun_dev_create:
* Check permissions prior to creating a new TUN device.
* @tun_dev_post_create:
* This hook allows a module to update or allocate a per-socket security
* structure.
* @sk contains the newly created sock structure.
* @tun_dev_attach_queue:
* Check permissions prior to attaching to a TUN device queue.
* @security pointer to the TUN device's security structure.
* @tun_dev_attach:
* Check permissions prior to attaching to a persistent TUN device. This
* hook can also be used by the module to update any security state
* This hook can be used by the module to update any security state
* associated with the TUN device's sock structure.
* @sk contains the existing sock structure.
* @security pointer to the TUN device's security structure.
* @tun_dev_open:
* This hook can be used by the module to update any security state
* associated with the TUN device's security structure.
* @security pointer to the TUN devices's security structure.
*
* Security hooks for XFRM operations.
*
Expand Down Expand Up @@ -1620,9 +1632,12 @@ struct security_operations {
void (*secmark_refcount_inc) (void);
void (*secmark_refcount_dec) (void);
void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
int (*tun_dev_create)(void);
void (*tun_dev_post_create)(struct sock *sk);
int (*tun_dev_attach)(struct sock *sk);
int (*tun_dev_alloc_security) (void **security);
void (*tun_dev_free_security) (void *security);
int (*tun_dev_create) (void);
int (*tun_dev_attach_queue) (void *security);
int (*tun_dev_attach) (struct sock *sk, void *security);
int (*tun_dev_open) (void *security);
#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down Expand Up @@ -2566,9 +2581,12 @@ void security_inet_conn_established(struct sock *sk,
int security_secmark_relabel_packet(u32 secid);
void security_secmark_refcount_inc(void);
void security_secmark_refcount_dec(void);
int security_tun_dev_alloc_security(void **security);
void security_tun_dev_free_security(void *security);
int security_tun_dev_create(void);
void security_tun_dev_post_create(struct sock *sk);
int security_tun_dev_attach(struct sock *sk);
int security_tun_dev_attach_queue(void *security);
int security_tun_dev_attach(struct sock *sk, void *security);
int security_tun_dev_open(void *security);

#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct sock *sock,
Expand Down Expand Up @@ -2733,16 +2751,31 @@ static inline void security_secmark_refcount_dec(void)
{
}

static inline int security_tun_dev_alloc_security(void **security)
{
return 0;
}

static inline void security_tun_dev_free_security(void *security)
{
}

static inline int security_tun_dev_create(void)
{
return 0;
}

static inline void security_tun_dev_post_create(struct sock *sk)
static inline int security_tun_dev_attach_queue(void *security)
{
return 0;
}

static inline int security_tun_dev_attach(struct sock *sk, void *security)
{
return 0;
}

static inline int security_tun_dev_attach(struct sock *sk)
static inline int security_tun_dev_open(void *security)
{
return 0;
}
Expand Down
24 changes: 21 additions & 3 deletions trunk/security/capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,16 +709,31 @@ static void cap_req_classify_flow(const struct request_sock *req,
{
}

static int cap_tun_dev_alloc_security(void **security)
{
return 0;
}

static void cap_tun_dev_free_security(void *security)
{
}

static int cap_tun_dev_create(void)
{
return 0;
}

static void cap_tun_dev_post_create(struct sock *sk)
static int cap_tun_dev_attach_queue(void *security)
{
return 0;
}

static int cap_tun_dev_attach(struct sock *sk, void *security)
{
return 0;
}

static int cap_tun_dev_attach(struct sock *sk)
static int cap_tun_dev_open(void *security)
{
return 0;
}
Expand Down Expand Up @@ -1050,8 +1065,11 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, secmark_refcount_inc);
set_to_cap_if_null(ops, secmark_refcount_dec);
set_to_cap_if_null(ops, req_classify_flow);
set_to_cap_if_null(ops, tun_dev_alloc_security);
set_to_cap_if_null(ops, tun_dev_free_security);
set_to_cap_if_null(ops, tun_dev_create);
set_to_cap_if_null(ops, tun_dev_post_create);
set_to_cap_if_null(ops, tun_dev_open);
set_to_cap_if_null(ops, tun_dev_attach_queue);
set_to_cap_if_null(ops, tun_dev_attach);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down
28 changes: 23 additions & 5 deletions trunk/security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -1254,24 +1254,42 @@ void security_secmark_refcount_dec(void)
}
EXPORT_SYMBOL(security_secmark_refcount_dec);

int security_tun_dev_alloc_security(void **security)
{
return security_ops->tun_dev_alloc_security(security);
}
EXPORT_SYMBOL(security_tun_dev_alloc_security);

void security_tun_dev_free_security(void *security)
{
security_ops->tun_dev_free_security(security);
}
EXPORT_SYMBOL(security_tun_dev_free_security);

int security_tun_dev_create(void)
{
return security_ops->tun_dev_create();
}
EXPORT_SYMBOL(security_tun_dev_create);

void security_tun_dev_post_create(struct sock *sk)
int security_tun_dev_attach_queue(void *security)
{
return security_ops->tun_dev_post_create(sk);
return security_ops->tun_dev_attach_queue(security);
}
EXPORT_SYMBOL(security_tun_dev_post_create);
EXPORT_SYMBOL(security_tun_dev_attach_queue);

int security_tun_dev_attach(struct sock *sk)
int security_tun_dev_attach(struct sock *sk, void *security)
{
return security_ops->tun_dev_attach(sk);
return security_ops->tun_dev_attach(sk, security);
}
EXPORT_SYMBOL(security_tun_dev_attach);

int security_tun_dev_open(void *security)
{
return security_ops->tun_dev_open(security);
}
EXPORT_SYMBOL(security_tun_dev_open);

#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down
50 changes: 39 additions & 11 deletions trunk/security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -4399,6 +4399,24 @@ static void selinux_req_classify_flow(const struct request_sock *req,
fl->flowi_secid = req->secid;
}

static int selinux_tun_dev_alloc_security(void **security)
{
struct tun_security_struct *tunsec;

tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
if (!tunsec)
return -ENOMEM;
tunsec->sid = current_sid();

*security = tunsec;
return 0;
}

static void selinux_tun_dev_free_security(void *security)
{
kfree(security);
}

static int selinux_tun_dev_create(void)
{
u32 sid = current_sid();
Expand All @@ -4414,8 +4432,17 @@ static int selinux_tun_dev_create(void)
NULL);
}

static void selinux_tun_dev_post_create(struct sock *sk)
static int selinux_tun_dev_attach_queue(void *security)
{
struct tun_security_struct *tunsec = security;

return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
TUN_SOCKET__ATTACH_QUEUE, NULL);
}

static int selinux_tun_dev_attach(struct sock *sk, void *security)
{
struct tun_security_struct *tunsec = security;
struct sk_security_struct *sksec = sk->sk_security;

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

/* see the comments in selinux_tun_dev_create() about why we don't use
* the sockcreate SID here */

sksec->sid = current_sid();
sksec->sid = tunsec->sid;
sksec->sclass = SECCLASS_TUN_SOCKET;

return 0;
}

static int selinux_tun_dev_attach(struct sock *sk)
static int selinux_tun_dev_open(void *security)
{
struct sk_security_struct *sksec = sk->sk_security;
struct tun_security_struct *tunsec = security;
u32 sid = current_sid();
int err;

err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
TUN_SOCKET__RELABELFROM, NULL);
if (err)
return err;
err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
TUN_SOCKET__RELABELTO, NULL);
if (err)
return err;

sksec->sid = sid;
tunsec->sid = sid;

return 0;
}
Expand Down Expand Up @@ -5642,9 +5667,12 @@ static struct security_operations selinux_ops = {
.secmark_refcount_inc = selinux_secmark_refcount_inc,
.secmark_refcount_dec = selinux_secmark_refcount_dec,
.req_classify_flow = selinux_req_classify_flow,
.tun_dev_alloc_security = selinux_tun_dev_alloc_security,
.tun_dev_free_security = selinux_tun_dev_free_security,
.tun_dev_create = selinux_tun_dev_create,
.tun_dev_post_create = selinux_tun_dev_post_create,
.tun_dev_attach_queue = selinux_tun_dev_attach_queue,
.tun_dev_attach = selinux_tun_dev_attach,
.tun_dev_open = selinux_tun_dev_open,

#ifdef CONFIG_SECURITY_NETWORK_XFRM
.xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
Expand Down
4 changes: 4 additions & 0 deletions trunk/security/selinux/include/objsec.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ struct sk_security_struct {
u16 sclass; /* sock security class */
};

struct tun_security_struct {
u32 sid; /* SID for the tun device sockets */
};

struct key_security_struct {
u32 sid; /* SID of key */
};
Expand Down

0 comments on commit 07a7d1f

Please sign in to comment.