Re: 2.2.15 + IPv6: serious bug when removing aliased interfaces

From: Kurt Roeckx (Q@ping.be)
Date: Mon May 22 2000 - 16:42:16 EST


On Mon, May 22, 2000 at 01:38:38PM +0200, Peter T. Breuer wrote:
>
> But it really is probable that this is a kernel bug wrt sockets when the
> address family != AF_INET. The above usually avoids triggering it.
>

I took a look at the kernel now, and found this in
net/ipv4/devinet.c:devinet_ioctl():

#ifdef CONFIG_IP_ALIAS
        char *colon;
#endif
...
#ifdef CONFIG_IP_ALIAS
        colon = strchr(ifr.ifr_name, ':');
        if (colon)
                *colon = 0;
#endif
...
dev = dev_get(ifr.ifr_name);
...
#ifdef CONFIG_IP_ALIAS
        if (colon)
                *colon = ':';
#endif
...
        if ((in_dev=dev->ip_ptr) != NULL) {
                for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
                        if (strcmp(ifr.ifr_name, ifa->ifa_label) == 0)
                                break;
        }
 ...
                case SIOCSIFFLAGS:
#ifdef CONFIG_IP_ALIAS
                        if (colon) {
                                if (ifa == NULL) {
                                        ret = -EADDRNOTAVAIL;
                                        break;
                                }
                                if (!(ifr.ifr_flags&IFF_UP))
                                        inet_del_ifa(in_dev, ifap, 1);
                                break;
                        }
#endif
                        ret = dev_change_flags(dev, ifr.ifr_flags);
                        break;

If I understand it correctly, this is called for AF_INET only, and will
call inet_del_ifa() if it's an alias, and not the dev_change_flags().

in_dev probably to the correct alias here.

In net/core/dev.c in dev_ioctl() it does:

        ifr.ifr_name[IFNAMSIZ-1] = 0;

        colon = strchr(ifr.ifr_name, ':');
        if (colon)
                *colon = 0;
...
                        dev_load(ifr.ifr_name);
                        ret = dev_ifsioc(&ifr, cmd);
                        if (!ret) {
                                if (colon)
                                        *colon = ':';
                                if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
                                        return -EFAULT;
                        }
                        return ret;

And in dev_ifsioc() it does:

dev = dev_get(ifr->ifr_name);
...
return dev_change_flags(dev, ifr->ifr_flags);

This looks wrong to me, this one downs the whole interface.

Note that there is no #ifdef CONFIG_IP_ALIAS here, it just assumes it's
on.

Why are there even 2 functions doing as good as the same? I think that
from the ipv4 dir should be done in the core dir instead, and from the
ipv4 dir removed.

Kurt

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue May 23 2000 - 21:00:22 EST