xorl %eax, %eax

CVE-2009-1072: Linux Kernel NFSd Security Bypass

leave a comment »

This was reported by Igor Zhbanov on 11 March 2009 and it affects Linux kernel prior to 2.6.28.9 release. The code presented here is from 2.6.28.8 release of the kernel. The problem is when mknod(2) system call is being used. An unprivileged user is able to make new device nodes on a filesystem exported with NFS root_squash. This is because the capability defined at include/linux/capability.h for NFS is this:

385 # define CAP_NFSD_SET     ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
386                                        CAP_FS_MASK_B1 } })
387

To understand what do we see here, we have to now what CAP_TO_MASK() macro does, which is just this:

358 #define CAP_TO_MASK(x)      (1 << ((x) & 31)) /* mask for indexed __u32 */
359

And the rest of the flags being used are pretty self-explanatory. Just have a look at this:

369 # define CAP_FS_MASK_B0     (CAP_TO_MASK(CAP_CHOWN)             \
370                            | CAP_TO_MASK(CAP_DAC_OVERRIDE)     \
371                            | CAP_TO_MASK(CAP_DAC_READ_SEARCH)  \
372                            | CAP_TO_MASK(CAP_FOWNER)           \
373                            | CAP_TO_MASK(CAP_FSETID))
374
375 # define CAP_FS_MASK_B1     (CAP_TO_MASK(CAP_MAC_OVERRIDE))

It is easy to locate the missing capability. The capability for mknod(2) system call which is simply this:

318 /* Allow the privileged aspects of mknod() */
319
320 #define CAP_MKNOD            27

Because of this, unprivileged users where able to perform this operation. The patch was (of course):

  # define CAP_FS_SET       ((kernel_cap_t){{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } })
- # define CAP_NFSD_SET     ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
-                    CAP_FS_MASK_B1 } })
+ # define CAP_NFSD_SET     ((kernel_cap_t){{ CAP_FS_MASK_B0 \
+                         | CAP_TO_MASK(CAP_SYS_RESOURCE) \
+                         | CAP_TO_MASK(CAP_MKNOD), \
+                           CAP_FS_MASK_B1 } })

 #endif /* _KERNEL_CAPABILITY_U32S != 2 */

Written by xorl

March 30, 2009 at 15:19

Posted in bugs, linux

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