Are all BSDs created equally? - DEF CON CON 25/DEF CON 25... · 2020-05-16 · • SVR 4 streams...

Post on 18-Jul-2020

1 views 0 download

Transcript of Are all BSDs created equally? - DEF CON CON 25/DEF CON 25... · 2020-05-16 · • SVR 4 streams...

Are all BSDs created equally? A survey of BSD kernel vulnerabili9es.

IljavanSprundel<ivansprundel@ioac4ve.com>

Who Am I

•  IljavanSprundel•  ivansprundel@ioac4ve.com

•  DirectorofPenetra4onTes4ngatIOAc4ve•  Pentest•  Codereview•  BreakstuffforfunandprofitJ

Outline/Agenda

•  Intro•  Data!

•  vulnerabili4esovertheyears

•  Testbyaudit•  CommonaJacksurface•  SomewhatlesscommonaJacksurface

•  Someresults/conclusions

What is this talk about?

•  BSDkernelvulnerabili4es•  Comparison•  BetweendifferentBSDflavors

•  Audience•  Lowlevelsecurityenthusiasts•  UNIX/BSDgeeks

•  IsuspectLinuxfolksmightenjoythistoo

•  CuriouspeoplethatliketopokearoundinOSinternals

•  Knowledge•  SomebasicknowledgeofUNIX/BSDinternals

Standing on the shoulders

of giants

•  Previousinteres4ngBSDkernelsecurityresearchby:•  Silvio•  thenoir•  EsaEtelavuori•  Patroklos(argp)Argyroudis•  ChristerOberg•  JoelErikkson•  ClementLecigne

intro

Really? Got Data?

•  Somehowthatstatementhasalwaysbeenstuckinmyhead•  Isittrue?•  Canwelookatsomedata?

Source: hFps://www.cvedetails.com/product/47/Linux-Linux-Kernel.html

Data!

•  Goesfromcurrentbackto1999forLinuxkernelvulnerabili4es•  Cvedetails.comdoesn’tseemtoprovidedataforOBSD/NBSD/FBSD•  Manuallygrabitfrom

•  hJps://www.freebsd.org/security/advisories.html•  hJp://netbsd.org/support/security/advisory.html•  hJps://www.openbsd.org/errata*.html

BSD kernel vulnerabili9es over the years

•  Lookingatthesenumbers,thatwasanastuteobserva4onbyTheo.•  20wasaverylowes4mate

• Butarethesenumbersonequalfoo4ng?

• Manyeyeballs?•  Yea,yea,Iknow….Butistheresometruthtoitinthiscase?

FreeBSD NetBSD OpenBSD

1999 3 8XXXTODO

2000 8 4XXXTODO

2001 6 7XXXTODO

2002 11 6XXXTODO

2003 7 3XXXTODO

2004 8 5XXXTODO

2005 11 8XXXTODO

2006 9 15XXXTODO

2007 1 4XXXTODO

2008 8 6XXXTODO

2009 5 1XXXTODO

2010 3 6XXXTODO

2011 1 2XXXTODO

2012 2 1XXXTODO

2013 8 8XXXTODO

2014 7 6XXXTODO

2015 7 2XXXTODO

2016 12 1XXXTODO

2017 1 3XXXTODO

Total 118 96XXXTODO

Test by audit!

•  SilvioCesaredidsomeinteres4ngworkin~2002thatgivessomeanswers

•  hJps://www.blackhat.com/presenta4ons/bh-usa-03/bh-us-03-cesare.pdf

•  Hisresultsseemtoindicatethereisn’treallythatmuchofaqualitydifference.However:•  thatwaswelloveradecadeago.

•  Havethingschanged?

•  TimespendontheBSDswasonlyacoupleofdayscomparedtoLinux•  Ifmore4mewould’vebeenspend,wouldmorebugshavebeenfound?

•  bugsaremostlyintoverflowsandinfoleaks•  Otherkindsofissuesthatcan‘easily’befound?

Test by Audit redux. •  SpendApril-May-Juneaudi4ngBSDsourcecode.•  Askedmyself,“wherewouldthebugsbe?”•  AJacksurface

•  Verycommon•  Syscalls•  TCP/IPstack

•  Somewhatlesscommon(inascendingorder,moreorless)•  Drivers(ioctlinterface)•  compatcode•  Traphandlers•  Filesystems•  Othernetworking(BT,wifi,IrDA)

Syscalls

AFack surface entrypoint

•  TheobviousaJacksurface•  Syscallsarehowuserlandgetsanythingdonefromkernel•  Hundredsofthem

•  FreeBSD:~550•  OpenBSD:~330•  NetBSD:~480

•  Assump4on:giventhatthey’reobvious,andwelltested,lesslikelytocontainsecuritybugs

intsys_sendsyslog(structproc*p,void*v,register_t*retval){

structsys_sendsyslog_args/*{ syscallarg(constvoid*)buf; syscallarg(size_t)nbyte; syscallarg(int)flags;}*/*uap=v;interror;sta4cintdropped_count,orig_error;

...error=dosendsyslog(p,SCARG(uap,buf),

SCARG(uap,nbyte),SCARG(uap,flags),UIO_USERSPACE);

...return(error);

}

intdosendsyslog(structproc*p,constchar*buf,size_tnbyte,intflags,enumuio_segsflg){...

structiovecaiov;structuioauio;size_ti,len;

...aiov.iov_base=(char*)buf;aiov.iov_len=nbyte;ßusercontrolledsize_t.nevercappedanywhere

...auio.uio_resid=aiov.iov_len;

...len=auio.uio_resid;ßusercontrolledsize_tif(fp){

...}elseif(consJy||cn_devvp){

...}else{

... kbuf=malloc(len,M_TEMP,M_WAITOK);

...}

...}

Sample bug

•  sendsyslogsystemcall•  OpenBSD6.1

•  BeentheresinceOpenBSD6.0•  Unboundlengthpassedtomalloc()fromuserland• Willtriggerakernelpanic

•  Previousassump4onisnot[en4rely]true:bugsinsyscallsdooccurwithsomefrequency•  Especiallynewlyaddedsyscalls

TCP/IP stack

AFack surface entrypoint

•  TCP/IPstack•  Ipv4/6•  Udp/tcp/icmp•  Ipsec•  …

•  ObviousandwellknownaJacksurface•  Hasbeenaroundforever•  Assump4on:welltestedandlesslikelytofindbugsthere

structsecpolicy*key_msg2sp(

structsadb_x_policy*xpl0, size_tlen, int*error)

{...

switch(xpl0->sadb_x_policy_type){...

caseIPSEC_POLICY_IPSEC: {

... tlen=PFKEY_EXTLEN(xpl0)-sizeof(*xpl0); xisr=(structsadb_x_ipsecrequest*)(xpl0+1); while(tlen>0){

/*lengthcheck*/if(xisr->sadb_x_ipsecrequest_len<sizeof(*xisr)){

ipseclog((LOG_DEBUG,"key_msg2sp:""invalidipsecrequestlength.\n"));key_freesp(newsp,KEY_SADB_UNLOCKED);*error=EINVAL;returnNULL;

}

lengthcheckisincomplete.sadb_x_ipsecrequest_lencanbeinvalid

if(xisr->sadb_x_ipsecrequest_len>sizeof(*xisr)){structsockaddr*paddr; paddr=(structsockaddr*)(xisr+1); /*validitycheck*/if(paddr->sa_len >sizeof((*p_isr)->saidx.src)){ ipseclog((LOG_DEBUG,"key_msg2sp:invalidrequest" "addresslength.\n")); key_freesp(newsp,KEY_SADB_UNLOCKED); *error=EINVAL; returnNULL; }

lengthcheckisincomplete.sadb_x_ipsecrequest_lencanbeinvalid

lengthcheckisincomplete.paddr->sa_lencanbeinvalid

bcopy(paddr,&(*p_isr)->saidx.src,paddr->sa_len);

thiscopycanoutofboundreadonpaddr.AssumemalicioususerthatcontrolsheapchunkaÇerpaddr.couldmakeitsopaddr->sa_lenislargeandcausesmemorycorrup4on

Sample bug

•  IPSECsetsockopt()•  Outofboundread•  Canendupcorrup4ngmemory•  Affects:

•  FreeBSD11•  NetBSD7.1

•  Previousassump4onisnot[en4rely]true:bugsinTCP/IPstackdooccurwithsomefrequency•  newercode•  mbufhandlingiscomplicatedanderrorprone

Drivers

AFack surface entrypoint

•  Lotsandlotsofdrivers•  Forallsortsofthings•  UNIX:everythingisafile

•  Mostexposeentrypointsin/dev•  Fileopera4ons

•  Open•  Ioctl•  Read•  Write•  Close•  …

•  IoctliswheremostoftheaJacksurfaceis!

intcryptof_ioctl(structfile*fp,u_longcmd,void*data){...

switch(cmd){...

mutex_enter(&crypto_mtx); fcr->m4me=fcr->a4me; mutex_exit(&crypto_mtx); mkop=(structcrypt_mkop*)data; knop=kmem_alloc((mkop->count*sizeof(structcrypt_n_kop)), KM_SLEEP); error=copyin(mkop->reqs,knop, (mkop->count*sizeof(structcrypt_n_kop))); if(!error){ error=cryptodev_mkey(fcr,knop,mkop->count); if(!error) error=copyout(knop,mkop->reqs, (mkop->count*sizeof(structcrypt_n_kop))); } kmem_free(knop,(mkop->count*sizeof(structcrypt_n_kop))); break;

...}

Integeroverflow

Memorycorrup4onduetointoverflow

Sample bug

•  CryptodeviceCIOCNFKEYMioctl•  NetBSD7.1

•  BeentheresinceNetBSD4.0.1?ThuApr1022:48:422008•  Classicintegeroverflowàmemorycorrup4on

sta4cintksyms_open(structcdev*dev,intflags,intfmt__unused,structthread*td){...

structksyms_soÇc*sc; ...

sc=(structksyms_soÇc*)malloc(sizeof(*sc),M_KSYMS,M_NOWAIT|M_ZERO);

...sc->sc_proc=td->td_proc;sc->sc_pmap=&td->td_proc->p_vmspace->vm_pmap;ßwillbeusedind_mmapcallback.

...error=devfs_set_cdevpriv(sc,ksyms_cdevpriv_dtr);

…}

sta4cintksyms_mmap(structcdev*dev,vm_ooffset_toffset,vm_paddr_t*paddr,

intprot__unused,vm_memaJr_t*memaJr__unused){ structksyms_soÇc*sc;

interror;

error=devfs_get_cdevpriv((void**)&sc);if(error) return(error);

/**XXXmmap()willactuallymapthesymboltableintotheprocess*addressspaceagain.*/if(offset>round_page(sc->sc_usize)||(*paddr=pmap_extract(sc->sc_pmap,ßcanbeexpiredpointer!(vm_offset_t)sc->sc_uaddr+offset))==0) return(-1);

return(0);

}

Sample bug 2

•  Ksymsdevice•  FreeBSD11

•  BeentheresinceFreeBSD8.0TueMay2621:39:092009•  Expiredpointer•  open()callbacksavespointertopmaptoprivatefd/devicestorage•  mmap()callbackusessavedpointerinprivatefd/devicestorage•  Sohowisthisaproblem?

• Whatifwehandfdofftoanotherprocess(e.g.sendoversocketorfork/execve)•  Andthenweexit•  Ifotherprocessnowdoesmmap,itwillbeusinganexpiredpmap!

Compat code

AFack surface entrypoint

•  TheBSDshavebinarycompa4bility[compat]supportforsomebinaries:•  OlderversionsoftheOS•  32bitversionsofaprogram(ona64bitversionoftheOS)•  Otheropera4ngsystem(e.g.Linux)

•  Hastoemulateabunchofstuff(e.g.syscalls)

“The people who rely on the compat layers don't care enough to maintain it. The people who work on the mainline system don't care about the compat layers because they don't use them. The cultures aren't aligned in the same direction. Compat layers rot very quickly.” – Theo De Raadt

sta4cint4_bind(file_t*fp,intfd,structsvr4_strioctl*ioc,structlwp*l){...

structsvr4_strmcmdbnd;...

if(ioc->len>sizeof(bnd)) returnEINVAL;

if((error=copyin(NETBSD32PTR(ioc->buf),&bnd,ioc->len))!=0) returnerror;

...switch(st->s_family){caseAF_INET:

... netaddr_to_sockaddr_in(&sain,&bnd);

...}

...}

#defineSVR4_C_ADDROF(sc)(constvoid*)(((constchar*)(sc))+(sc)->offs)...sta4cvoidnetaddr_to_sockaddr_in

(structsockaddr_in*sain,conststructsvr4_strmcmd*sc){

conststructsvr4_netaddr_in*na;

na=SVR4_C_ADDROF(sc);ßcouldpointtoanywhereinmemorymemset(sain,0,sizeof(*sain));sain->sin_len=sizeof(*sain);sain->sin_family=na->family;ßcrashorinfoleaksain->sin_port=na->port;ßcrashorinfoleaksain->sin_addr.s_addr=na->addr;ßcrashorinfoleak

…} /*

*Pretendthatwehavestreams...*Yes,thisisgross....*/

Sample bug

•  SVR4streamscompatcode•  NetBSD7.1

•  BeentheresinceNetBSD1.2ThuApr1112:49:131996•  Usesoffsetthatcomesfromuserland

•  Withoutanyvalida4on

•  Canreadarbitrary(-ish)kernelmemory•  Panic•  Infoleak

Trap handlers

AFack surface entrypoint

•  Traphandlershandlesomekindofexcep4onorfault•  Divbyzero•  Syscall•  Breakpoint•  Invalidmemoryaccess•  …

•  Somecanbetriggeredbyuserland,andthekernelhastohandlethemcorrectly

•  duetotheirnature,theyareuglyandhighlyarchitecturespecific

Fuzz it!

•  whatwouldhappenifyousimplyexecutedabunchofrandombytesasinstruc4ons?•  Surelyabunchoftrapswillgetgenerated,andthekernelwouldhavetohandlethem

intrfd;voidexecute_code(unsignedchar*p){int(*fn)();fn=p;fn();return;}voidfuzz(){unsignedchar*code=mmap(NULL,lenbuf,PROT_EXEC|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);while(1){ read(rfd,code,lenbuf); intpid=fork(); if(pid==-1){ exit(0); }elseif(pid==0){ execute_code(code); }else{ intstatus; pid_tr; r=waitpid(pid,&status,0); if(r==-1){ kill(pid,9); sleep(1); waitpid(pid,&status,WNOHANG); } }}}intmain(void){rfd=open("/dev/urandom",O_RDONLY);fuzz();}

demo!

Hit xen trap

•  NULLderef

File systems

AFack surface entrypoint

•  FilesystemaJacksurfaceseemseasyenough.•  Maliciousfsimagethatgetsmounted

•  Alsodofileopera4onsonthemoncemounted•  IscertainlyaJacksurface

•  However,thereismore!•  Inrecentyearsall3BSDssupportfuse•  VFSlayernowhastodealwithmaliciousdatathatcomesfromuserland

•  Beforeitalwayscamefromatrustedfilesystemdriver

AFack surface entrypoint [fuse] •  FBSD/OBSD/NBSDallhavedifferentfuseimplementa4ons(nosharedcodewhatsoever)

•  NBSD:mostcomplete(allowsforthemostfileopera4ons)•  FBSD:mostcontrolledargumentspassedbackandforth(getaJr,readdir)lessopportunityforconsumerstomakemistakes,butmoreparsing/processinginfusefsitself,morepoten4alforbugsinfusecodeitself

•  OBSD:minimalfunc4onalimplementa4on(comparedtotheprevioustwo)

•  noneimplementioctl

•  alldo:•  read•  write•  readdir•  getaJr•  setaJr•  ...

intvfs_getcwd_scandir(structvnode**lvpp,structvnode**uvpp,char**bpp,char*bufp,structproc*p){

inteofflag,tries,dirbuflen,len,reclen,error=0;...

structvaJrva;...

error=VOP_GETATTR(lvp,&va,p->p_ucred,p);ßdatacancomefromfusefs...

dirbuflen=DIRBLKSIZ;

if(dirbuflen<va.va_blocksize) dirbuflen=va.va_blocksize;ßfusefscanmakethisreallybig

dirbuf=malloc(dirbuflen,M_TEMP,M_WAITOK);ßmalloc()willpaniconverylargevalues

...

error=VOP_READDIR(uvp,&uio,p->p_ucred,&eofflag);ßfusefscanprovidearbitrarycontent...cpos=dirbuf;...for(len=(dirbuflen-uio.uio_resid);len>0;len-=reclen){

dp=(structdirent*)cpos;reclen=dp->d_reclen;

/*Checkformalformeddirectory*/if(reclen<DIRENT_RECSIZE(1)){ error=EINVAL; gotoout;}

if(dp->d_fileno==fileno){ char*bp=*bpp; bp-=dp->d_namlen;ßfusefscanlieaboutd_namlen

if(bp<=bufp){ error=ERANGE; gotoout; }

memmove(bp,dp->d_name,dp->d_namlen);ßoutofboundread.

Sample bug

•  Unboundmallocandoutofboundread(couldpanicorinfoleak)•  OpenBSD6.1

•  BeentheresinceOpenBSD4.0FriApr2808:34:312006•  getcwdsyscallwhentakingdatafromfuse/userland

sta4cdaddr_text2_nodealloccg(structinode*ip,intcg,daddr_tipref,intmode){...

error=bread(ip->i_devvp,fsbtodb(fs,fs->e2fs_gd[cg].ext2bgd_i_bitmap),(int)fs->e2fs_bsize,NOCRED,&bp);ßreadfromfilesystem

...ibp=(char*)bp->b_data;

...len=howmany(fs->e2fs->e2fs_ipg-ipref,NBBY);loc=memcchr(&ibp[start],0xff,len);if(loc==NULL){ len=start+1; start=0; loc=memcchr(&ibp[start],0xff,len);ßlogicdrivenbyfsdata if(loc==NULL){ prinÜ("cg=%d,ipref=%lld,fs=%s\n", cg,(longlong)ipref,fs->e2fs_fsmnt); panic("ext2fs_nodealloccg:mapcorrupted");ßpanicdrivenbyfsdata /*NOTREACHED*/ }}

...}

Sample bug 2

•  panic()drivenbyfilesystemdata•  FreeBSD11

•  BeentheresinceFreeBSD8.1ThuJan1414:30:542010•  Ext2filesystemcode

Networking (bt, wifi, irda)

Wifi AFack surface entrypoint

•  Stackitself•  802.11networkdata•  Parsing•  Infoleaks

• Wifidrivers•  Datasendbydevicetohost

802.11 stack

•  One802.11stackforallwifidrivers•  Mucheasiertomaintain

•  Needtofixinonly1placeifbugsarefound•  ieee80211_input()ismainparsinginput

•  Calledfromallwifidrivers

ieee80211_eapol_key_input(structieee80211com*ic,structmbuf*m,structieee80211_node*ni){

structifnet*ifp=&ic->ic_if;structether_header*eh;structieee80211_eapol_key*key;

...eh=mtod(m,structether_header*);

...if(m->m_len<sizeof(*key)&&(m=m_pullup(m,sizeof(*key)))==NULL){ßguaranteesthattherearesizeof(structieee80211_eapol_key)con4nuousbytesinthembuf

..}

...key=mtod(m,structieee80211_eapol_key*);

...if(m->m_pkthdr.len<4+BE_READ_2(key->len))ßassumekey->lenislargerthankey->payload gotodone;

/*checkkeydatalength*/totlen=sizeof(*key)+BE_READ_2(key->paylen);ßassumekey->lenislargerthankey->payloadif(m->m_pkthdr.len<totlen||totlen>MCLBYTES) gotodone;

.../*makesurethekeydatafieldiscon4guous*/if(m->m_len<totlen&&(m=m_pullup(m,totlen))==NULL){ßnotenoughdatapulledupifkey->lenislargerthankey->payload!

…}key=mtod(m,structieee80211_eapol_key*);

... ieee80211_recv_4way_msg3(ic,key,ni);ßcancrashinhereifnotenoughdataispulledup.

...}

802.11 Stack sample bug

•  mbufmishandling,leadingtocrash•  Doesn’tguaranteeitpullsupenoughmbufdata

•  OpenBSD6.1•  Bughasbeenthereforalmost9years

•  ParsingEAPOLframes

802.11 Drivers

•  WifidriversareeitherPCIorUSB

•  Doyoutrusttheradio?•  Whatifitdoesgetcompromised?

•  AssumePCIcardscausetotalcompromise(theycandoDMA)•  Well,actually,withIOMMUthat’snolongerthecase…

•  USBispacketbasedprotocol•  HostUSBparsersshouldbeabletoparsesafely

•  CurrentlyBSDwifidriversdonotdothis!•  Leadstotrivialheapsmashes

voidrun_rx_frame(structrun_soÇc*sc,uint8_t*buf,intdmalen){...

structrt2860_rxwi*rxwi;...

uint16_tlen;...

rxwi=(structrt2860_rxwi*)buf;...

len=letoh16(rxwi->len)&0xfff;ßcanbeatmost4095...

/*couldusem_devgetbutnet80211wantscon4gmgmtframes*/MGETHDR(m,M_DONTWAIT,MT_DATA);if(__predict_false(m==NULL)){ ifp->if_ierrors++; return;}if(len>MHLEN){<--iflenis4095,comehere MCLGET(m,M_DONTWAIT);ßallocatesacluster,whichis2048byteslong if(__predict_false(!(m->m_flags&M_EXT))){ ifp->if_ierrors++; m_freem(m); return; }}

.../*finalizembuf*/memcpy(mtod(m,caddr_t),wh,len);ßmemorycorrup4on!m->m_pkthdr.len=m->m_len=len;

...}

/**Aframehasbeenuploaded:passtheresul4ngmbufchainupto*thehigherlevelprotocols.*/voidatu_rxeof(structusbd_xfer*xfer,void*priv,usbd_statusstatus){...

h=(structatu_rx_hdr*)c->atu_buf;len=UGETW(h->length)-4;/*XXXmagicnumber*/ßintegerunderflow

m=c->atu_mbuf;memcpy(mtod(m,char*),c->atu_buf+ATU_RX_HDRLEN,len);ßneedtovalidatelenbeforecopy.cancausememorycorrup4on

...usbd_setup_xfer(c->atu_xfer,sc->atu_ep[ATU_ENDPT_RX],c,c->atu_buf,ATU_RX_BUFSZ,USBD_SHORT_XFER_OK|USBD_NO_COPY,USBD_NO_TIMEOUT, atu_rxeof);usbd_transfer(c->atu_xfer);

}

voidotus_sub_rxeof(structotus_soÇc*sc,uint8_t*buf,intlen)ßlencomesfromusb.canbe~8k{...

uint8_t*plcp;...

plcp=buf;...

mlen=len-AR_PLCP_HDR_LEN-sizeof(*tail);...

mlen-=IEEE80211_CRC_LEN;/*strip802.11FCS*/

wh=(structieee80211_frame*)(plcp+AR_PLCP_HDR_LEN);...

MGETHDR(m,M_DONTWAIT,MT_DATA);if(__predict_false(m==NULL)){ ifp->if_ierrors++; return;}if(align+mlen>MHLEN){ MCLGET(m,M_DONTWAIT);ßallocatesacluster,whichis2048byteslong if(__predict_false(!(m->m_flags&M_EXT))){ ifp->if_ierrors++; m_freem(m); return; }}/*Finalizembuf.*/m->m_data+=align;memcpy(mtod(m,caddr_t),wh,mlen);ßmlencanbe~8k.cancausememorycorrup4on.

...}

voidrsu_event_survey(structrsu_soÇc*sc,uint8_t*buf,intlen){...

structndis_wlan_bssid_ex*bss;structmbuf*m;intpktlen;

...bss=(structndis_wlan_bssid_ex*)buf;

...if(__predict_false(len<sizeof(*bss)+letoh32(bss->ieslen)))ßcouldintoverflow return;

.../*Buildafakebeaconframetoletnet80211doalltheparsing.*/pktlen=sizeof(*wh)+letoh32(bss->ieslen);ßcouldintoverflowif(__predict_false(pktlen>MCLBYTES))ßsignednessissue return;MGETHDR(m,M_DONTWAIT,MT_DATA);if(__predict_false(m==NULL)) return;if(pktlen>MHLEN){ MCLGET(m,M_DONTWAIT); if(!(m->m_flags&M_EXT)){ m_free(m); return; }}wh=mtod(m,structieee80211_frame*);

...memcpy(&wh[1],(uint8_t*)&bss[1],letoh32(bss->ieslen));ßmemorycorrup4on

...}

802.11 drivers sample bug

• WideopenaJacksurface•  AtmelAT76C50xIEEE802.11bwirelessnetworkdevice[atu(4)]•  AtherosUSBIEEE802.11a/b/g/nwirelessnetworkdevice[otus(4)]•  RealtekRTL8188SU/RTL8192SUUSBIEEE802.11b/g/nwirelessnetworkdevice[rsu(4)]•  RalinkTechnology/MediaTekUSBIEEE802.11a/b/g/nwirelessnetworkdevice[run(4)]•  AtherosUSBIEEE802.11a/b/gwirelessnetworkdevice[uath(4)]

•  AcrossallBSDs

•  Theydidn’tthinkabouttheaJacksurfaceonthisone

Results •  results:

•  About~115kernelbugssofar•  FBSD:~30•  OBSD:25•  NBSD:~60

•  typesofbugsseen:•  Straightheap/stacksmash•  racecondi4ons•  expiredpointers•  Doublefrees•  recursionissues•  integerissues

•  Underflows,overflows,signedness•  infoleaks•  outofboundread•  NULLderef•  Divisionbyzero•  kernelpanicsdrivenbyuserland•  Memoryleaks

Conclusions •  Bugswerefoundinall3oftheexaminedBSDs

•  AmongalloftheaJacksurfacesmen4onedabove

•  Winner/loser•  OBSDclearwinner(theyhavemassivelyreducedtheiraJacksurfaceovertheyears):

•  AJacksurfacereduc4on•  noloadablemodules•  rela4velyfewdevices•  Virtuallynocompatcode(theyremovedLinuxacoupleofyearsago)•  removeden4reBluetoothstack•  Significantlylesssyscalls(e.g.200+syscallslessthanFBSD)•  Cutsupportforsomeolderarchitectures

•  CodeQuality•  intoverflows/signednessbugs,asgoodasgoneinmostplaces•  Fewinfoleaks

•  NBSDclearloser•  Tonsoflegacyandcompatcode(whothehells4llneedstheISOprotocols???Really?)•  seemstobelessconsistentwithsecuritycodequality

•  Toomanysignednessbugs.

•  FBSDissomewhereinbetween

More conclusions

•  Bugsares4lleasytofindinthosekernels.EvenOpenBSD.

•  Varyinglevelofqualitydependingonageandwhowroteit•  MostconsistentqualitywasobservedwithOpenBSD

•  ThemaintainersofvariousBSDsshouldtalkmoreamongeachother•  Severalbugsinonewerefixedintheother

•  OpenBSDexpiredprocpointerinmidiioctl()fixedinNetBSD•  NetBSDsignednessbuginac97_query_devinfo()fixedinOpenBSD

More conclusions

•  Codebasesize•  OpenBSD:2863505loc•  NetBSD:7330629loc•  FreeBSD:8997603loc

•  Obviouslythisplaysapart

•  Can’thaveabugincodeyoudon’thave•  Accidentalvs.planned

•  Haven’tgoJentoimplemen4ngsomethingyetor…•  Choicemadeonpurposetodeletecode

•  AJacksurfacereduc4on

More conclusions

•  Manyeyeballs…

•  Gutfeeling,Isuspectthisisafactor.

•  Basedonmyresult,codequalityalonecan’taccountforthediscrepancybetweenthebugnumbers(BSDvs.Linux).

•  SaywhatyouwillaboutthepeoplereviewingtheLinuxkernelcode,therearesimplyordersofmagnitudemoreofthem.Anditshowsinthenumbers.

Ques9ons ?