Bug 7362

Summary: tun/tap device needs root permission for TUNSETIFF ioctl
Product: Drivers Reporter: Daniel Murgu (murguia)
Component: NetworkAssignee: Jeff Garzik (jgarzik)
Status: REJECTED WILL_NOT_FIX    
Severity: normal CC: daniel4321
Priority: P2    
Hardware: i386   
OS: Linux   
Kernel Version: 2.6.18 Subsystem:
Regression: --- Bisected commit-id:

Description Daniel Murgu 2006-10-13 14:10:47 UTC
Most recent kernel where this bug did not occur: 2.6.17.13

Distribution: Slackware 10.2

Problem Description:
Applying TUNSETIFF ioctl needs root permissions that wasn't needed in previous
versions. I was using qemu 0.8.2 (a virtual machine emulator) which uses a tap
device to emulate a network between the guest and host operating system. 

The relevant part of the patch-2.6.18 file says:

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a1ed2d9..329d9fe 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -39,7 +39,6 @@ #define DRV_VERSION   "1.6"
 #define DRV_DESCRIPTION        "Universal TUN/TAP device driver"
 #define DRV_COPYRIGHT  "(C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>"

-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -490,6 +489,9 @@ static int tun_set_iff(struct file *file

                err = -EINVAL;

+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+
                /* Set dev type */
                if (ifr->ifr_flags & IFF_TUN) {
                        /* TUN device */ 
...

I was handling security by limiting access to /dev/net/tun from a privileged
unix group, but now even if I can open the /dev/net/tun device, I need
CAP_NET_ADMIN to use the TUNSETIFF ioctl.
Comment 1 Andrew Morton 2006-10-13 14:31:29 UTC
On Fri, 13 Oct 2006 14:22:48 -0700
bugme-daemon@bugzilla.kernel.org wrote:

> http://bugzilla.kernel.org/show_bug.cgi?id=7362
> 
>            Summary: tun/tap device needs root permission for TUNSETIFF ioctl
>     Kernel Version: 2.6.18
>             Status: NEW
>           Severity: normal
>              Owner: jgarzik@pobox.com
>          Submitter: murguia@acm.org
> 
> 
> Most recent kernel where this bug did not occur: 2.6.17.13
> 
> Distribution: Slackware 10.2
> 
> Problem Description:
> Applying TUNSETIFF ioctl needs root permissions that wasn't needed in previous
> versions. I was using qemu 0.8.2 (a virtual machine emulator) which uses a tap
> device to emulate a network between the guest and host operating system. 
> 
> The relevant part of the patch-2.6.18 file says:
> 
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index a1ed2d9..329d9fe 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -39,7 +39,6 @@ #define DRV_VERSION   "1.6"
>  #define DRV_DESCRIPTION        "Universal TUN/TAP device driver"
>  #define DRV_COPYRIGHT  "(C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>"
> 
> -#include <linux/config.h>
>  #include <linux/module.h>
>  #include <linux/errno.h>
>  #include <linux/kernel.h>
> @@ -490,6 +489,9 @@ static int tun_set_iff(struct file *file
> 
>                 err = -EINVAL;
> 
> +               if (!capable(CAP_NET_ADMIN))
> +                       return -EPERM;
> +
>                 /* Set dev type */
>                 if (ifr->ifr_flags & IFF_TUN) {
>                         /* TUN device */ 
> ...
> 
> I was handling security by limiting access to /dev/net/tun from a privileged
> unix group, but now even if I can open the /dev/net/tun device, I need
> CAP_NET_ADMIN to use the TUNSETIFF ioctl.
> 

Changelog for ca6bb5d7ab22ac79f608fe6cbc6b12de6a5a19f0 says

    The tuntap driver allows an admin to create persistent devices and
    assign ownership of them to individual users. Unfortunately, relaxing
    the permissions on the /dev/net/tun device node so that they can
    actually use those devices will _also_ allow those users to create
    arbitrary new devices of their own. This patch corrects that, and
    adjusts the recommended permissions for the device node accordingly.

So I suspect you're out of luck.

Comment 2 Daniel Murgu 2006-10-13 18:45:54 UTC
Ok. It's a sound security reason. I'll try to use a workaround like creating the
persistent device as root and using it as a standard user. I am closing the bug.
Comment 3 David Woodhouse 2006-10-14 02:11:17 UTC
On Fri, 2006-10-13 at 14:43 -0700, Andrew Morton wrote:
> > Problem Description:
> > Applying TUNSETIFF ioctl needs root permissions that wasn't needed in previous
> > versions. I was using qemu 0.8.2 (a virtual machine emulator) which uses a tap
> > device to emulate a network between the guest and host operating system. 
> > 
 ...
> > I was handling security by limiting access to /dev/net/tun from a privileged
> > unix group, but now even if I can open the /dev/net/tun device, I need
> > CAP_NET_ADMIN to use the TUNSETIFF ioctl.
> > 
> 
> Changelog for ca6bb5d7ab22ac79f608fe6cbc6b12de6a5a19f0 says
> 
>     The tuntap driver allows an admin to create persistent devices and
>     assign ownership of them to individual users. Unfortunately, relaxing
>     the permissions on the /dev/net/tun device node so that they can
>     actually use those devices will _also_ allow those users to create
>     arbitrary new devices of their own. This patch corrects that, and
>     adjusts the recommended permissions for the device node accordingly.
> 
> So I suspect you're out of luck.

You can create the device in advance, as root. Use TUNSETPERSIST and
TUNSETOWNER ioctls to make it persistent and assign ownership of it to
the user who runs qemu. This functionality probably ought to be in
iproute2 but afaict isn't.

'ip tuntap create mode tap owner 500 persist dev tap0' would do
something like this...

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <string.h>

#include <linux/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>

char dev[IFNAMSIZ] = "tap0";

int main(void)
{
        struct ifreq ifr;
        int fd, err;

        if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
                perror("open");
                return fd;
        }

        memset(&ifr, 0, sizeof(ifr));

        /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
         *        IFF_TAP   - TAP device
         *
         *        IFF_NO_PI - Do not provide packet information
         */
        ifr.ifr_flags = IFF_TAP;
        if( *dev )
                strncpy(ifr.ifr_name, dev, IFNAMSIZ);

        if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
                close(fd);
                return err;
        }
        if( (err = ioctl(fd, TUNSETPERSIST, 1)) < 0 ) {
                    perror("TUNSETPERSIST");
                close(fd);
                return err;
        }
        if( (err = ioctl(fd, TUNSETOWNER, 500)) < 0 ){
                perror("TUNSETOWNER");
                close(fd);
                return err;
        }
        strcpy(dev, ifr.ifr_name);
        printf("%s\n", ifr.ifr_name);
        sleep(10);
        return fd;
}