Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
16th Feb 2001 [SBWID-141]
COMMAND
	    kernel
SYSTEMS AFFECTED
	    NetBSD
PROBLEM
	    Bill Sommerfeld found  following.  A  subtle bug in  validation of
	    user-supplied  arguments  to  a  syscall  can  allow  allow   user
	    applications on the i386 platform to transfer control to arbitrary
	    addresses in kernel memory, bypassing normal system protections.
	    This problem is only present  on the i386 platform, and  only when
	    the USER_LDT  kernel configuration  option is  enabled at  compile
	    time.  Unfortunately,  this option is  present in the  GENERIC and
	    GENERIC_LAPTOP kernel configurations shipped with NetBSD releases,
	    as well as several examples, so many users will be affected.
	    The  problem  stems  from  the  complexity  of  the  x86 processor
	    architecture memory protection system, and other systems are known
	    to be  affected.   This includes  systems with  code derived  from
	    NetBSD as well as other independently-written systems,  indicating
	    that the same mistake may have been repeated elsewhere as well.
	    The  Intel  i386  architecture  supports  a  complex and confusing
	    protection  and  segmentation  model  relying  on  rings,  segment
	    selectors, segment descriptors,  gates, descriptor tables  and the
	    like.
	    The Local Descriptor Table (LDT) is usually a per-process segment;
	    most  unix   OS's  provide   system  calls   allowing  application
	    processes to add new segments to the LDT.  In NetBSD, this  option
	    is enabled  with "options  USER_LDT" in  the kernel  configuration
	    file, and is generally enabled for the WINE Windows emulator.
	    One segment  type is  a "call  gate", which  allows code  in outer
	    rings to  make calls  to code  in inner,  more priviledged  rings.
	    Call  gates  are  one  of  the  three (or more?) different ways to
	    implement system calls on the x86.  The segment descriptor in  the
	    LDT for a call gate  contains a segment selector and  offset; when
	    a program running  in an outer  ring executes a  "ljmp" or "lcall"
	    instruction which specifies the  segment selector of a  call gate,
	    control is transferred  to the specified  offset of the  specified
	    code segment.  If the  gate target is an inner-ring  code segment,
	    a ring  transition occurs;  therefore it  is vital  for code which
	    creates call gate descriptors to validate that the target  segment
	    and offset of the gate is appropriate.
	    While reviewing code in NetBSD, it was discovered that the  NetBSD
	    "i386_set_ldt" syscall did not  do appropriate validation of  call
	    gate targets;  in short,  it's possible  to create  a call gate in
	    the LDT  which transfers  control to  an arbitrary  address in the
	    kernel.
	    The problem affects other Operating Systems also:
	    * OpenBSD has the same bug, in code inherited directly from NetBSD
	    * FreeBSD also once had the bug, but it was eliminated a couple of
	      years ago as part of a change to disable setting call gates.
	    * Sun Solaris/x86 has the same bug, in a different  implementation
	      of a similar mechanism.
	    * The problem is not necessarily  limited to unix; any OS for  the
	      x86  which  allows  an  unprivileged  program  to  create   gate
	      descriptors in its LDT could have this bug.
	    A common misunderstanding of how gate descriptors work may  result
	    in the programmer believing  they've defended against this  attack
	    (by checking the gate's DPL)  without having done so (you  need to
	    check the DPL of the code segment that the gate targets).
	    Note that this  behaviour is not  restricted to Intel  processors;
	    the  bug  applies  to  implementations  of the x86 architecture by
	    other manufacturers as well.
SOLUTION
	    Systems  running  NetBSD/i386  with  the  USER_LDT  kernel  option
	    enabled are vulnerable.   This includes users running  the GENERIC
	    kernel configurations distributed with releases, or users who have
	    built their  own kernel  configurations based  on GENERIC  and not
	    removed  the  USER_LDT  option.   The  most effective and simplest
	    workaround,  for  users  not  requiring  this  option  for Wine or
	    similar  emulators,  is  to   build  a  kernel  without   "options
	    USER_LDT".  For users who need this option enabled, kernel sources
	    must be updated and a new kernel built and installed.
	    Systems running releases older than NetBSD 1.4 should be  upgraded
	    to NetBSD 1.4.3 before applying the fixes described here.  Systems
	    running  NetBSD-current  dated  from  before  2001-01-17 should be
	    upgraded to  NetBSD-current dated  2001-01-17 or  later.   Systems
	    running NetBSD-release-1-4 or NetBSD-release-1-5 dated from before
	    2001-01-18 should be upgraded to 2001-01-18 later.
	    The following patch to /sys/arch/i386/i386/sys_machdep.c should be
	    applied  before  rebuilding  a  new  kernel with USER_LDT enabled.
	    This  patch   can  be   applied  (with   offset  differences)   to
	    NetBSD-1.4.x, NetBSD-1.5 or NetBSD-current kernel sources.
	
	    Index: sys_machdep.c
	    ===================================================================
	    RCS file: /cvsroot/syssrc/sys/arch/i386/i386/sys_machdep.c,v
	    retrieving revision 1.54
	    retrieving revision 1.55
	    diff -c -r1.54 -r1.55
	    *** sys_machdep.c	2001/01/16 01:50:36	1.54
	    --- sys_machdep.c	2001/01/16 23:32:21	1.55
	    ***************
	    *** 222,227 ****
	    --- 222,238 ----
	  			    break;
	  		    case SDT_SYS286CGT:
	  		    case SDT_SYS386CGT:
	    + 			/*
	    + 			 * Only allow call gates targeting a segment
	    + 			 * in the LDT or a user segment in the fixed
	    + 			 * part of the gdt.  Segments in the LDT are
	    + 			 * constrained (below) to be user segments.
	    + 			 */
	    + 			if (desc.gd.gd_p != 0 && !ISLDT(desc.gd.gd_selector) &&
	    + 			    ((IDXSEL(desc.gd.gd_selector) >= NGDT) ||
	    + 			     (gdt[IDXSEL(desc.gd.gd_selector)].sd.sd_dpl !=
	    + 				 SEL_UPL)))
	    + 				return (EACCES);
	  			    /* Can't replace in use descriptor with gate. */
	  			    if (n == fsslot || n == gsslot)
	  				    return (EBUSY);
	
	

Internet highlights