Re: [PATCHv2 bluetooth-next 1/4] mac802154: fix hold rtnl while ioctl

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

 



On Tue, May 26, 2015 at 10:23:44AM +0200, Alexander Aring wrote:

> > > > > static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
> > > > >                               unsigned int cmd, struct iw_request_info *info,
> > > > >                               wext_ioctl_func standard,
> > > > >                               wext_ioctl_func private)
> > > > > {
> > > > >        int ret = wext_permission_check(cmd);
> > > > > 
> > > > >        if (ret)
> > > > >                return ret;
> > > > > 
> > > > >        dev_load(net, ifr->ifr_name);
> > > > >        rtnl_lock();
> > > > >        ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private);
> > > > >        rtnl_unlock();
> > > > > 
> > > > >        return ret;
> > > > > }
> > > > > 
> > > > > leading to a double rtnl lock in mac802154_wpan_ioctl().
> > > > > 
> > > > > The easy fix would be to have mac802154_wpan_ioctl() check the ioctl
> > > > > cmd before taking the rtnl -- I'm not too happy about the rtnl being
> > > > > held or not held upon entry to a device ioctl depending on the ioctl
> > > > > cmd and/or on who the caller is, but we might not be easily able to
> > > > > change this...
> > > > 
> > > > I think the ioctl handler should just first check which are its valid
> > > > ioctl and also enforce permission in that run without the RTNL lock
> > > > held. Return -EINVAL or -ENOIOCTLCMD when it gets a cmd that this
> > > > function does not handle. And then have the function actually take
> > > > the RTNL lock and process its two ioctl that it supports.
> > > > 
> > > > That way we should avoid the nasty with taking the RTNL lock for
> > > > unsupported ioctl.
> > > 
> > > Something like the below?  (Alexander?)  (I verified that it fixes
> > > the problem for me.)
> > > 
> > 
> > I can suggest also other solutions which are:
> > 
> >  - Remove the ndo_do_ioctl callback? If somebody wants to set address
> >    things, they should use netlink. There is also some warn notice in the
> >    callback "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n",
> >    which reports the user that he is not doing the right thing when
> >    setting addresses via ioctl. That's very trustful.
> > 
> >    I know currently there is some function "mac802154_wpan_update_llsec"
> >    which makes the security layer to work, because it's not called
> >    when setting short/panid anywhere else. I would be happy if we can
> >    "deactivate" the security layer -> removing old netlink interface and
> >    then try to making an easy to use interface over nl802154 to access
> >    the mib security entries. (I have started somewhere, but this is also
> >    another thread to talk about access security attributes over
> >    nl802154.
> > 
> > - Hold the rtnl lock only when the socket code is called. I insert this
> >   code because somebody tried to ioctl a 802.15.4 socket and the lock
> >   wasn't held. Maybe we can hold the rtnl lock in the caller, see [0].
> 
> besides I don't know why they use a check on ARPHRD there, a 802.15.4
> socket can also be created on wpan intefaces only, which should be
> checked at creating the socket or somewhere.

If you're talking about this code in net/ieee802154/socket.c:

===
static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg,
                                unsigned int cmd)
{
        struct ifreq ifr;
        int ret = -ENOIOCTLCMD;
        struct net_device *dev;

        if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
                return -EFAULT;

        ifr.ifr_name[IFNAMSIZ-1] = 0;

        dev_load(sock_net(sk), ifr.ifr_name);
        dev = dev_get_by_name(sock_net(sk), ifr.ifr_name);

        if (!dev)
                return -ENODEV;

        if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl)
                ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd);

        if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
                ret = -EFAULT;
        dev_put(dev);

        return ret;
}

static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd,
                                 unsigned long arg)
{
        struct sock *sk = sock->sk;

        switch (cmd) {
        case SIOCGSTAMP:
                return sock_get_timestamp(sk, (struct timeval __user *)arg);
        case SIOCGSTAMPNS:
                return sock_get_timestampns(sk, (struct timespec __user *)arg);
        case SIOCGIFADDR:
        case SIOCSIFADDR:
                return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg,
                                cmd);
        default:
                if (!sk->sk_prot->ioctl)
                        return -ENOIOCTLCMD;
                return sk->sk_prot->ioctl(sk, cmd, arg);
        }
}
===

The network namespace is taken from the 802.15.4 socket, but the device
name is taken from the struct ifreq that's passed in, which does not
necessarily refer to a 802.15.4 device.


> A general question and sorry for this unknowledge is that: is it normal
> than a socket ioctl will call the netdev ioctl?

netdevice(7) has a note about this.  I think it's probably just because
of historical reasons, because there is no 'dedicated' way of calling a
netdev ioctl other than going through the socket (which, historically,
means PF_INET) layer.  Not very clean at all, but this is unlikely to
ever change at this point. :-/
--
To unsubscribe from this list: send the line "unsubscribe linux-wpan" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux