Messages in this thread |  | | Date | Wed, 18 Oct 2000 11:24:56 -0600 | From | Matt Peterson <> | Subject | bind() allowed to non-local addresses |
| |
Using linux-2.4.0-test9, bind() incorrectly allows a bind to a non-local address. The correct behavior should be a return code of -1 with errno set to EADDRNOTAVAIL. (Simple snippet to reproduce/debug the problem is available on request)
There appears to be significant differences between the net/ipv4/af_inet.c:inet_bind() in the 2.2 and 2.4 sources. The inet_bind() in the 2.2 sources contains a check to ensure that the value returned by inet_addr_type() is RTN_LOCAL as well as a #ifdef'ed check to allow the bind in certain cases if the kernel was compiled with transparent proxy is enabled. In inet_bind() of the 2.4 tree all of these checks are conspicuously absent.
The following patch fixes the problem for me, but I am still concerned possibly breaking transparent proxy. Basically the patch is nothing more than the addition of a simple check for RTN_LOCAL. (Moving call to inet_addr_type() is a *very* nit-picky "optimization" that eliminates wasted time in the call in the event that subsequent port and capability check fails).
*** af_inet.c Wed Oct 18 11:06:15 2000 --- af_inet.c.orig Mon Sep 18 16:04:13 2000 *************** *** 459,471 **** if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL;
snum = ntohs(addr->sin_port); if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) return -EACCES;
! chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); ! /* We keep a pair of addresses. rcv_saddr is the one * used by hash lookups, and saddr is used for transmit. * * In the BSD API these are the same except where it --- 459,471 ---- if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL;
+ chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); + snum = ntohs(addr->sin_port); if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) return -EACCES;
/* We keep a pair of addresses. rcv_saddr is the one * used by hash lookups, and saddr is used for transmit. * * In the BSD API these are the same except where it *************** *** 483,493 **** sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr; if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ ! else if(chk_addr_ret != RTN_LOCAL){ ! err = -EADDERNOTAVAIL; ! goto out; ! } ! /* Make sure we are allowed to bind here. */ if (sk->prot->get_port(sk, snum) != 0) { sk->saddr = sk->rcv_saddr = 0; --- 483,489 ---- sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr; if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ ! /* Make sure we are allowed to bind here. */ if (sk->prot->get_port(sk, snum) != 0) { sk->saddr = sk->rcv_saddr = 0;
Discussion? Please personally CC me <mpeterson@caldera.com> as I am not currently subscribed to the linux-kernel list.
Thanks.
-- Matthew Peterson Software Engineer Caldera Systems, Inc - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/
|  |