xorl %eax, %eax

Solaris IP(7p) Minor Number Allocation DoS

leave a comment »

This issue was disclosed by Sun Microsystems on 30 January 2009 and affects Sun Solaris 8 to 10 for both SPARC and x86 platforms as well as OpenSolaris based builds from snv_01 through snv_81. The provided code here was taken from OpenSolaris web CVS system. The vulnerable function can be found under usr/src/uts/common/inet/inet_common.c and it’s named inet_minor_alloc(). Here is the vulnerable function:

81 dev_t
82 inet_minor_alloc(void *a)
83 {
84    inet_arena_t *arena = (inet_arena_t *)a;
85    dev_t dev;
87    while ((dev = (dev_t)vmem_alloc(arena->ineta_arena, 1,
88            VM_NOSLEEP)) == 0) {
89        if (arena->ineta_maxminor >= inet_maxminor)
90            return (0);
91        if (vmem_add(arena->ineta_arena,
92            (void *)(uintptr_t)(arena->ineta_maxminor + 1),
93            inet_maxminor - arena->ineta_maxminor, VM_NOSLEEP) == NULL)
94            return (0);
95        arena->ineta_maxminor = inet_maxminor;
96    }
97    return (dev);
98 }
99

This function is used to obtain a minor number for the requested socket. As you can see at lines 89-90 if the max minor number is reached, it just returns 0. This value is a static minor_t variable which is declared as:

47 /* Maximum minor number to use */
48 static minor_t inet_maxminor = INET_MAXMINOR;

And this data type as we can see from sys/types.h is:

299 /* Typedefs for dev_t components */
300 
301 #if !defined(_LP64) && defined(__cplusplus)
302 typedef ulong_t major_t;    /* major part of device number */
303 typedef ulong_t minor_t;    /* minor part of device number */
304 #else
305 typedef uint_t major_t;
306 typedef uint_t minor_t;
307 #endif

Which means that on 32bit CPUs it’s of type unsigned integer. The value that is used to initialize it was taken from common.h and it’s this:

97 #define INET_MAXMINOR   MAXMIN    /* maximum device minor number */

Which according to sys/mkdev.h is simply:

55 #define MAXMIN32       0x3fffful    /* SVR4 max minor value */
    ...
57 #ifdef _LP64
    ...
69 #else /* !_LP64 */
70
    ...
74 #define  MAXMIN       MAXMIN32
    ...
76 #endif /* !_LP64 */

Thus, the maximum value is 0x3FFF. If we are able to consume this resource by creating multiple sockets we can make inet_minor_alloc() fail since the check at lines 89-90 will immediately return 0 and using this we can deny socket creation on legit applications of other users. Trigger of this code is trivial, just create enough sockets to reach INET_MAXMINOR.

Written by xorl

February 3, 2009 at 14:12

Posted in bugs, solaris

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s