Re: [RFC PATCH v2 1/2] lsm: Add hooks to the TUN driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Quoting Paul Moore (paul.moore@xxxxxx):
> 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
> ---

Acked-by: Serge Hallyn <serue@xxxxxxxxxx>

> 
>  drivers/net/tun.c        |   22 +++++++++++++++-------
>  include/linux/security.h |   31 +++++++++++++++++++++++++++++++
>  security/capability.c    |   19 +++++++++++++++++++
>  security/security.c      |   18 ++++++++++++++++++
>  4 files changed, 83 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index 027f7ab..e6667ce 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -130,17 +130,10 @@ static inline struct tun_sock *tun_sk(struct sock *sk)
>  static int tun_attach(struct tun_struct *tun, struct file *file)
>  {
>  	struct tun_file *tfile = file->private_data;
> -	const struct cred *cred = current_cred();
>  	int err;
> 
>  	ASSERT_RTNL();
> 
> -	/* Check permissions */
> -	if (((tun->owner != -1 && cred->euid != tun->owner) ||
> -	     (tun->group != -1 && !in_egroup_p(tun->group))) &&
> -		!capable(CAP_NET_ADMIN))
> -		return -EPERM;
> -
>  	netif_tx_lock_bh(tun->dev);
> 
>  	err = -EINVAL;
> @@ -926,6 +919,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
> 
>  	dev = __dev_get_by_name(net, ifr->ifr_name);
>  	if (dev) {
> +		const struct cred *cred = current_cred();
> +
>  		if (ifr->ifr_flags & IFF_TUN_EXCL)
>  			return -EBUSY;
>  		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)
>  		else
>  			return -EINVAL;
> 
> +		if (((tun->owner != -1 && cred->euid != tun->owner) ||
> +		     (tun->group != -1 && !in_egroup_p(tun->group))) &&
> +		    !capable(CAP_NET_ADMIN))
> +			return -EPERM;
> +		err = security_tun_dev_attach(tun->sk);
> +		if (err < 0)
> +			return err;
> +
>  		err = tun_attach(tun, file);
>  		if (err < 0)
>  			return err;
> @@ -947,6 +950,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
> 
>  		if (!capable(CAP_NET_ADMIN))
>  			return -EPERM;
> +		err = security_tun_dev_create();
> +		if (err < 0)
> +			return err;
> 
>  		/* Set dev type */
>  		if (ifr->ifr_flags & IFF_TUN) {
> @@ -989,6 +995,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
>  		tun->sk = sk;
>  		container_of(sk, struct tun_sock, sk)->tun = tun;
> 
> +		security_tun_dev_post_create(sk);
> +
>  		tun_net_init(dev);
> 
>  		if (strchr(dev->name, '%')) {
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 5eff459..d8efc35 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -974,6 +974,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
>   *	Sets the connection's peersid to the secmark on skb.
>   * @req_classify_flow:
>   *	Sets the flow's sid to the openreq sid.
> + * @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:
> + *	Check permissions prior to attaching to a persistent TUN device.  This
> + *	hook can also 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 hooks for XFRM operations.
>   *
> @@ -1572,6 +1583,9 @@ struct security_operations {
>  	void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
>  	void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
>  	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);
>  #endif	/* CONFIG_SECURITY_NETWORK */
> 
>  #ifdef CONFIG_SECURITY_NETWORK_XFRM
> @@ -2557,6 +2571,9 @@ void security_inet_csk_clone(struct sock *newsk,
>  			const struct request_sock *req);
>  void security_inet_conn_established(struct sock *sk,
>  			struct sk_buff *skb);
> +int security_tun_dev_create(void);
> +void security_tun_dev_post_create(struct sock *sk);
> +int security_tun_dev_attach(struct sock *sk);
> 
>  #else	/* CONFIG_SECURITY_NETWORK */
>  static inline int security_unix_stream_connect(struct socket *sock,
> @@ -2707,6 +2724,20 @@ static inline void security_inet_conn_established(struct sock *sk,
>  			struct sk_buff *skb)
>  {
>  }
> +
> +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(struct sock *sk)
> +{
> +	return 0;
> +}
>  #endif	/* CONFIG_SECURITY_NETWORK */
> 
>  #ifdef CONFIG_SECURITY_NETWORK_XFRM
> diff --git a/security/capability.c b/security/capability.c
> index 21b6cea..a10a44a 100644
> --- a/security/capability.c
> +++ b/security/capability.c
> @@ -710,10 +710,26 @@ static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb)
>  {
>  }
> 
> +
> +
>  static void cap_req_classify_flow(const struct request_sock *req,
>  				  struct flowi *fl)
>  {
>  }
> +
> +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(struct sock *sk)
> +{
> +	return 0;
> +}
>  #endif	/* CONFIG_SECURITY_NETWORK */
> 
>  #ifdef CONFIG_SECURITY_NETWORK_XFRM
> @@ -1029,6 +1045,9 @@ void security_fixup_ops(struct security_operations *ops)
>  	set_to_cap_if_null(ops, inet_csk_clone);
>  	set_to_cap_if_null(ops, inet_conn_established);
>  	set_to_cap_if_null(ops, req_classify_flow);
> +	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_attach);
>  #endif	/* CONFIG_SECURITY_NETWORK */
>  #ifdef CONFIG_SECURITY_NETWORK_XFRM
>  	set_to_cap_if_null(ops, xfrm_policy_alloc_security);
> diff --git a/security/security.c b/security/security.c
> index dc7674f..dc6953c 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1112,6 +1112,24 @@ void security_inet_conn_established(struct sock *sk,
>  	security_ops->inet_conn_established(sk, skb);
>  }
> 
> +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)
> +{
> +	return security_ops->tun_dev_post_create(sk);
> +}
> +EXPORT_SYMBOL(security_tun_dev_post_create);
> +
> +int security_tun_dev_attach(struct sock *sk)
> +{
> +	return security_ops->tun_dev_attach(sk);
> +}
> +EXPORT_SYMBOL(security_tun_dev_attach);
> +
>  #endif	/* CONFIG_SECURITY_NETWORK */
> 
>  #ifdef CONFIG_SECURITY_NETWORK_XFRM
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux