kern/79342: When looking for an unused port number for bind or connect, if low & high port range are equal, kernel can trap in divide by zero error

Anjali Kulkarni anjali at juniper.net
Tue Mar 29 12:50:02 PST 2005


>Number:         79342
>Category:       kern
>Synopsis:       When looking for an unused port number for bind or connect, if low & high port range are equal, kernel can trap in divide by zero error
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 29 20:50:01 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Anjali Kulkarni
>Release:        4.10
>Organization:
Juniper Networks
>Environment:
4.10-RELEASE-p2
>Description:
In src/sys/netinet/in_pcb.c, in the function in_pcbbind(), when trying to find an unused port number in the range of ports allowed to be used, there are cases to handle upper port limit > lower port limit and upper port limit < lower port limit, but no case to handle when they are equal. Consequently, if they are equal, the kernel will have a divide by zero trap when the line 
*lastport = first - (arc4random() % (first - last)) 
OR the line
*lastport = first + (arc4random() % (last - first))
is executed, where first and last are the port ranges in which we check for an unused port number.

>How-To-Repeat:

set

net.inet.ip.portrange.first = net.inet.ip.portrange.last. (say 1024)

Now do a bind or a connect with a port number of 0.
>Fix:
In in_pcbbind(), there should be a check for the case when first & last are equal as follows:
                /*
                 * Simple check to ensure all ports are not used up causing
                 * a deadlock here.
                 *
                 * We split the two cases (up and down) so that the direction
                 * is not being tested on each round of the loop.   
                 */
+                 if (first == last) {
+                         inp->inp_laddr.s_addr = INADDR_ANY;
+                         return (EADDRNOTAVAIL);
+                 } else if (first > last) {
-                 if (first > last) {


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list