On Fri, Jul 22, 2016 at 11:26:57AM +0200, Mark Kettenis wrote:
> > From: Tim Newsham <[email protected]>
> > Date: Fri, 22 Jul 2016 08:32:04 +0000
> > 
> > Here's a new one we just found:
> > 
> > /*
> >  * sysctl_tmpfs_panic.c
> >  *    Demonstrate a panic in UFS through the getdents system call.
> >  *
> >  * gcc -g sysctl_tmpfs_panic.c -o sysctl_tmpfs_panic
> >  */
> > 
> > #ifdef BUG_WRITEUP //---------------------------------------------------
> > Any user can panic the kernel with the sysctl call.
> > 
> > Impact:
> > Any user can panic the kernel by using the sysctl call.  If a
> > user can manage to map a page at address zero, they may be able
> > to gain kernel code execution and escalate privileges.
> > 
> > Description:
> > When processing sysctl calls, OpenBSD dispatches through a number
> > of intermediate helper functions.  For example, if the first integer
> > in the path is 10, sys_sysctl() will call through vfs_sysctl() for
> > further processing.  vfs_sysctl() performs a table lookup based on
> > the second byte, and if the byte is 19, it selects the tmpfs_vfsops
> > table and dispatches further processing through the vfs_sysctl method:
> > 
> >     if (name[0] != VFS_GENERIC) {
> >         for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
> >             if (vfsp->vfc_typenum == name[0])
> >                 break;
> > 
> >         if (vfsp == NULL)
> >             return (EOPNOTSUPP);
> > 
> >         return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1,
> >             oldp, oldlenp, newp, newlen, p));
> >     }
> > 
> > Unfortunately, the definition for tmpfs_vfsops leaves this method NULL:
> > 
> > struct vfsops tmpfs_vfsops = {
> >     tmpfs_mount,            /* vfs_mount */
> >     tmpfs_start,            /* vfs_start */
> >     tmpfs_unmount,          /* vfs_unmount */
> >     tmpfs_root,         /* vfs_root */
> >     (void *)eopnotsupp,     /* vfs_quotactl */
> >     tmpfs_statfs,           /* vfs_statfs */
> >     tmpfs_sync,         /* vfs_sync */
> >     tmpfs_vget,         /* vfs_vget */
> >     tmpfs_fhtovp,           /* vfs_fhtovp */
> >     tmpfs_vptofh,           /* vfs_vptofh */
> >     tmpfs_init,         /* vfs_init */
> >     NULL,               /* vfs_sysctl */
> >     (void *)eopnotsupp,
> > };
> > 
> > Trying to read or write a sysctl path starting with (10,19) results
> > in a NULL pointer access and a panic of
> > "attempt to execute user address 0x0 in supervisor mode".
> > Since any user can perform a sysctl read, this issue can be abused
> > by any logged in user to panic the system.
> > 
> > OpenBSD intentionally prevents users from attempting to map a page
> > at the NULL address.  If an attacker is able to get such a mapping,
> > they may be able to cause the kernel to jump to code mapped at this
> > address (if other security protections such as SMEP aren't in place).
> > This would allow an attacker to gain kernel code execution and
> > escalate their privileges.
> > 
> > Reproduction:
> > Run the attached sysctl_tmpfs_panic.c program. It will pccess
> > the (10,19,0) sysctl path and trigger a panic of
> > "attempt to execute user address 0x0 in supervisor mode".
> > NCC Group was able to reproduce this issue on OpenBSD 5.9 release 
> > running amd64.
> > 
> > Recommendation:
> > Include a NULL-pointer check in vfs_sysctl() before dispatching to
> > the vfs_sysctl method.  Alternately, include a vfs_sysctl method
> > in the tmpfs_vfsops table.
> 
> Thanks Tim,
> 
> I'd say adding the check in vfs_sysctl() is the way to go as this will
> prevent this from happening again in the future.
> 
> ok?
> 
> 
> Index: vfs_subr.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/vfs_subr.c,v
> retrieving revision 1.248
> diff -u -p -r1.248 vfs_subr.c
> --- vfs_subr.c        19 Jun 2016 11:54:33 -0000      1.248
> +++ vfs_subr.c        22 Jul 2016 09:23:52 -0000
> @@ -1290,7 +1290,7 @@ vfs_sysctl(int *name, u_int namelen, voi
>                       if (vfsp->vfc_typenum == name[0])
>                               break;
>  
> -             if (vfsp == NULL)
> +             if (vfsp == NULL || vfsp->vfc_vfsops->vfs_sysctl == NULL)
>                       return (EOPNOTSUPP);
>  
>               return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1,
> 

I made the same change in my tree. So OK claudio@

-- 
:wq Claudio

Reply via email to