Are all BSDs created equally? - DEF CON CON 25/DEF CON 25... · 2020-05-16 · • SVR 4 streams...
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<[email protected]>
Who Am I
• IljavanSprundel• [email protected]
• 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 ?