[Music]
good morning everyone um hi i'm betsy
and i'm going to be your mc today in
kaya theater um and tomorrow as well so
um wasn't that an amazing keynote i've
like noted down a lot of things to look
up and read and so on
but we have so many more exciting talks
today
and i should um also
uh in introducing myself mention that i
am
working on this conference
for you today i'm from the lands of the
yagara people in brisbane um and i
acknowledge their elders past and
present
um
and
yeah it's a beautiful day outside here i
hope it's lovely conference day where
you all are as well
so first up today
um we have case cook
so case has been working with free
software since 1994 has been a debian
developer since 2007 and has been a
member of the linux kernel technical
advisory board since 2019 he is
currently employed as a linux kernel
security engineer by google focusing on
upstream kernel security defenses
so case will be taking questions today
so if you'd like to put your questions
during the talk in the little questions
tab at the top of the chat in venulis
there um the questions are moderated so
your question will appear right away
you've got to wait for one of us
volunteers to manage to approve it
and also check in with that questions
tab regularly during the talk because
you can upload questions that you want
answered
um so i'll see you back at the end of
the talk to pass on your questions um
case we're looking forward to hearing
from you
awesome thanks for having me
um
hi uh as i said i'm case cook uh here to
talk to you about uh some of the work
we're doing in linux kernel uh for
actually doing some meaningful bounce
checking
um
i'll just dive in
so i
got
more and more irritated by some of the
flaws that were cropping up
in the kernel around buffer overflows
and i wanted to
see if there was a way we could actually
put a stop to this
so i
as a sort of data analysis step i looked
at the last you know three years or so
of any of this kernel cvs that mentioned
buffer overflow and tried to root cause
them and figure that out
so the
you know one of the largest not the
largest but i'll get through it first is
the array index overflows
and looking at that there were seven out
of those 25
that we looked at and the the good news
is like using example here
that these are pretty well solvable
so if you look at this example oops
you've got
you've got this algorithm name that was
64 bytes long and
if you were to access it
beyond the 64-bit if there's no
instrumentation it would just happily
access memory beyond the end of of that
buffer and
you know badness would ensue
but
if you actually
build the kernel with ubison bounds um
and either trap or the panic on warrants
this control set
this doesn't happen anymore all these
kinds of things
on
unknown sized array
indexing
get caught um for example you can see a
little summary of what would happen here
if you get you actually get an array
index out of bounds at runtime
and it would either
trap that process or trap that threat of
execution with ubisone trap or would
panic the whole system if you set panic
on warren
though
in the in this particular example
that got changed from a fixed size array
to a flexible array
uh which means you actually lose any
kind of bounce checking that the
compiler can do
so that's not the best
fix for it but uh it's it's it's a
reasonable example for showing what that
would have looked like um so all these
just go away if if the kernel is
compiled ub sandbounds so
that array index overflow section sort
of goes away you don't have buffer
overflows like that anymore
and so what's left is
this the huge section where mem copy is
used against a buffer
and looking through
those 11 the one that set me off
really was this one which was called
bleeding tooth which
was a bluetooth vulnerability
and
it just annoyed me to no end because
again the compiler knows how big this
buffer is and yet it does no bounce
checking whatsoever
and if we look through the others you
sort of see this same pattern over and
over here's an entire structure we know
how big it is and we're going to copy
into it
but it's unchecked at run time
here's another one where we know the
size of that buffer and there's no
runtime checking
and again
these just sort of continue
and you you see the pattern over and
over
um in fact this became
so common in the last couple of years
that uh
there's a couple
at the end
where
you see we've got ssids people started
looking at this as a common overflow
place
and now we've got ssid overflow and
another one this one doesn't even have a
cve assigned but it's fixed
and another one so that's three in a row
of exactly the same flaw
all of which the compiler knows how big
this buffer is and yet it happily just
clobbers past the end of it
um
so
some of you may be thinking well wait a
second i thought config fortify source
solved this
um
and
well let's answer that question
if you take a look at what the fortified
mem copy
looks like
this top part is
where we
basically get the size of the object
what's the destination size what's the
source size
this next chunk is the compile time
portion that says hey if we know the
size that we're going to be copying at
compile time then it's a fixed size we
can actually do the checking immediately
and throw a compile time warning rather
than doing a runtime warning
and then finally if those weren't if it
wasn't a built-in constant then we can
do the runtime checking
and
if everything is fine we go on and
actually do the mem copy
so the
problem actually lies in this which is
the built-in object size call which
we're where we say how big is our
destination
um and so we dive into built in object
size a little bit more that last
parameter is what mode to be using
in mode 0
we're actually measuring the outer
structure not what's being referenced
directly not the member itself
as an example
we can see here in this structure
if we ask for
a built-in object size of count
in mode 0
we actually get the answer of 16 because
that's the full size of the remaining
everything after from count on
is how much is left and this is to block
having a mem copy go beyond the end of a
structure
but it doesn't help a mem copy block
going beyond the end of a structure
member
but you see in mode one we actually get
the true size of count as four and we
can see all our you know each of these
as an example here you know i say well
how big is name well it's not eight as
far as in mode 0 it's 12 which means
well we could clobber or read the secret
value that follows it
whereas in mode 1 we'd actually limit it
and if we have a dynamically sized array
at the end or what's called a flexible
array
a built-in object size refuses to know
anything about it it says i don't know
minus one i don't know how big this is
at all
and what actually happened with the
bleeding tooth attack is uh it was
attacking stuff within the same
composite structure just past the end of
the the buffer that was uh being used by
the mem copy so specifically this last
uh advertised uh advertised data
it wrote past it and clobbered the
the list head for next and continued its
attack
so that's an example of you know going
past one and hitting some secret thing
that you didn't want to expose but the
memcap was perfectly happy to do it
because it wasn't past the end of the
hci dev structure itself
so back to fortified mem copy obviously
the solution here is we need to fix the
built-in object size and switch the
modes
and actually have it say mode one
that's obviously what we need to do so i
guess we're done
so here's my wall of text
if we look at the mem copy calls on a
recent x86 64 all mod config build
which doesn't really represent
uh
i don't know a real world case it mostly
represents worst case this is all the
code that could be built there's about
35 000 m copy calls in total
22 000 where we don't know the buffer
destination buffer size at all
uh 12 000 where we know both so we can
actually validate them at compile time
so we know that those 33 percent are
always going to be correct
and then about you know 1200
only 3 percent where the destination
buffer size is known but the copy size
is dynamic and you know evaluated
runtime
and going through that list of cves
all 11 of them were in this
three percent so if we actually can fix
this we would have solved all of those
buffer overflows
which
was very exciting because when i first
ran these numbers it was it seemed like
we were going to run into trouble and
that we wouldn't actually fix the big
the big problem but uh it turns out the
bulk of it comes from this case
uh but of course that would be too easy
to switch to mode one
um of those twelve thousands or so uh
known buffer size and known copy size um
some of those actually need to be fixed
because the kernel would intentionally
overflow member targets
the good news if there is some in that
was that they would appear at compile
time so it was easy to sort of catch
them all
and so what do i mean by intentional
cross member overflows
uh what we'd have is
uh this kind of example where
we've we've got a mem copy that's
targeting um this key material member so
that's what the compiler sees that's
what it looks at and when the
built-in object size runs with mode 1 it
says ok key material is max anchor key
length long
and then it looks at key m len and it
sees you know oh we've actually asked
for
all three of these fields because we're
going to copy out of some source
and
intentionally overwrite you know do
three writes at once is basically what's
going on here
and the kernel had kind of a lot of
these and we can't move on to doing
runtime checking if we can't even build
the kernel in the first place to deal
with these cases either
so
sort of the traditional solution is you
let the compiler have some new way to
refer to
all three of these members under one
name
this is an example of adding a name
structure around these three and then
suddenly you can say okay
we're going to target the tkip
and you know the length we're copying in
is correct everything's everything's
fine we're good
but when we add a named structure like
this because we again we need to be able
to name it so that the mem copy has a
target in mind for its destination
suddenly we have to remove all the
references to the key material member
and replace it with its now full name
which is the you know the the added
structure name dot key material
and doing that for every instance
of each of those members for every
member that gets wrapped in a structure
was going to be
unpalatable shall we say to to upstream
it would be an enormous amount of churn
so
with uh with keith pather keith
packard's help uh i
added struct group as a macro that would
actually give us both you could refer to
things either
by its original name
or by its wrapped name so you'd have
both
both ways of referring to things you
could change you could add your mem copy
but you wouldn't have to rewrite the
rest of all the references to it
uh this works through an interesting uh
trick
uh which is
it's the struct group is actually a
macro that creates a union
of both an anonymous struct and a named
structure but they have identical
members so they'd have the same
locations so each of them the they're
basically alias to each other
and this this works really well
there are some additional helpers for
adding
attributes and tags to to the created
union
and the structures within them stuff
like that
but this solves a problem of getting us
a name a single name that we can use to
refer to a group of sub-members within a
structure without disrupting the rest of
the kernel
so
now we can say all right we've got
you know
m-copy runtime checking is now possible
we can just do this we can do the
built-in object size
with mode 1
just like we thought we could do
and
what happens here then is again at
compile time we're looking at the size
uh and for the for those cases they're
the size is known at compile time
and we get the correct
uh we you know pass the read and write
overflows uh chat tests here and we can
move on to actually
triggering stuff at runtime
the problem of course here is that
we need to
[Music]
deal with similar multi-member
overwrites at runtime there are those in
the kernel as well that aren't visible
at compile time
and that means that instead of just
panicking
we actually have to compare
the mode 0
object size and the mode 1 object size
and if we have encountered a you know a
new version of this with mode 1
uh you know the the more constrained
version
we can't panic the system anymore
because it used to work and now if we
just suddenly say never mind we'll panic
the system every time you're doing the
thing that you've been doing for forever
since memcop used to allow it
that's not going to fly either
so
the now we've had to split these tests
and say if it's a mode 0 failure go
ahead and panic because that's what
we've been doing forever
and on mode 1 we can issue a warning
and the idea is
as we make our way through
a development process and running these
kernels and under real world workloads
we can collect those warnings find the
places where that's happening
and fix them up
the other thing is we can instrument
these and find them in advance
so that's some of the work that i've
been doing is trying to go through and
find these cases where it's happening at
run time and differentiate them from the
places that are where we don't know the
size of the buffer at all
and getting people to find these on
their own rather than just being
surprised by a warning that suddenly
appears
another approach to this has been
running these kinds of instrumented
kernels under sis collar under fuzzing
things like that
so we have a
an advanced warning about getting
getting and fixing these cases
so we don't end up with the surprises
so now we're done oh but no wait a
second let's go back and look at that
list again
so
while we've handled this you know the
what looked like this tiny case of you
know three percent or so
um but that did cover all the cvs in the
past three years
we realistically can't ignore the fact
that more than half of these memcapa
uses are against
destinations sizes
buffer sizes that aren't known to the
compiler they're entirely dynamic
and we
really to you know
to seriously deal with buffer overflows
we need to address this as well
so that's
a big part of that are the the flexible
array case that i talked about a little
bit earlier
and in those cases if you remember built
an object size returns minus one it says
i don't know how big this is
um so these cases
where i'm showing that i've got
highlighted with this with the
destination and source sizes are are are
never true because
we can't know the size for the
destination and it'll just fall straight
through to the underlying mem copy
um
to give you sort of an example of this
and talk a little bit about the flexible
flexible arrays you know here's an
example of some bitmap image and we've
got a count of pixels and then we've got
our pixel data which is not byte size
it's u32
and if we ask built an object size how
big is pixel data it says i don't know
and you can't even you can't even use
sizeof on it this is actually considered
an invalid expression because it's a
flexible array and can't be noted
compile time and sizeof needs to be
evaluatable at compile time
our flexible arrays are a relatively
recent addition to the c
language standard
and before that there were fake flexible
arrays and the kernel of course is
filled to that because it has an old
code base
and the one of them the most the more
recent fake flexible arrays is the zero
element array so this is a new
c extension
but built in object size also considers
this to be a flexible array so we can't
even detect these very easily however
sizeof happily considers this to be zero
bytes long so even if we could somehow
manage use sizeof it would freak out
before that
was the really old style which was a one
element array
and this was what you know what c did
before that and just totally stepped on
itself and
but built an object size again says i
don't know this looks like it's probably
a flexible array so i refuse to believe
how big it is even though size of again
is happily says oh yeah it's uh u32 cool
cool that's that's four bytes
but of course
if i change this to some large value
it is also treated as a flexible array
so any array at the end of a structure
is treated as a flexible array which is
really frustrating because it limits the
ability of
our kernel to be able to do any kind of
bounce checking on something that isn't
a flexible array so the goal here is as
this corner case exists is to fix this
by basically
switching built-in object size around to
refuse to
believe that trailing arrays are
flexible arrays only true flexible
arrays are flexible arrays this doesn't
exist yet for the compiler
the expectation is we're we can add this
option
and
gain back some coverage for things so in
the meantime
if you have an array that you want
protected in your data structure please
don't put it at the end of your
structure
um
right so continuing to use that um
we need to be able to solve dynamically
sized destination overflows
the good news is that the bounds of
these things are stored somewhere
it just takes checking it
and the better news with flexible arrays
is that that is usually stored somewhere
nearby usually in the same structure as
as the flexible array itself
and certainly many call sites already
try to check the bounds but there's
always going to be bugs in open coded
checks
and even within that how many of these
places are remembering to check the
storage size of the variable that
contains the bounds like in this example
the pixels count is a u16 that's not a
size t it's not a 64-bit value it's
small so what happens if you try to
store something that's too big in it
what i'd really like to see in the
future for the c standard is to actually
provide the compiler with a way to
reason about the bounds
so they can do things in a dynamic
fashion this exists in some other
languages
where you can actually hint to the
compiler what is being used to track to
track the size of flexible array
for example this style of syntax
has been proposed
you say pixel data but it's controlled
you know its size is going to be found
in the pixels
member
and then the compiler can actually
reason about the bounds and do sanity
checking and other things
where the other options already exist to
do sanity checking it can extend it and
cover
the flexible array cases too
so
instead of
relying on the compiler and um and these
other missing c features uh we're
basically forced to create a new api
and then disallow
mem copy for destinations that aren't a
constant size there aren't a size known
at compile time
to really cut that sixty percent down uh
dramatically by by replacing the api and
not use mem copy and
move on to new things
so continuing to use this bitmap um
image example
you know here's sort of
what things look like if it's open coded
we've got some
some counts uh we're going to allocate
storage for it we're going to assign
how you know how many pixels there are
and we're going to copy
the screen data off into this
but of course every single one of these
steps
this count that could overflow what are
those types who knows
at least for this example is using
struct size which should do the right
thing as far as calculating a correct
size but if count has already overflowed
that's not going to do the right thing
here we've got a size t count being
assigned to a u16 pixels so that could
go wrong
and then our mem copy is going to do
another open coded
multiplication of
the data size of that of that member
times a count
so each one of these pieces can go wrong
and there's you know in this example no
checking of any of those cases
so if we can replace all of this with a
standard api that actually does all of
that
all of those checks we can actually um
just get rid of a whole bunch of this
and just collapse it into what is
effectively deserialization we're taking
some string of bits
out of memory
and stuffing it into
this you know array of some data type so
it's it's a form of deserialization
and then we can throw out this all the
open coded stuff and um and get it of
course
i've left the
width times height overflow for the
future
since we want to be able to
we need to be able to catch integer
overflows too but that's a whole
separate talk
so there's other helpers that we can add
as well for cases where the allocation
has already occurred so here's an
allocation that has occurred and we've
got the size you know how many
of those members exist is already part
of the structure and we can just do the
deserialization again
but instead of doing the allocation we
can actually check the size and do other
things it's actually more work to do
this uh than than to do the allocation
because we already did the checks on the
allocation size
so
what does that look like
so
the first part is
creating a helper to actually deal with
clamping the size of the data type to
the data type storage for a given member
and just walking through here really
quickly we we
extract uh or rather get a 64-bit
representation of the counts that we've
got
we use another existing macro
to actually find out how large
a value the given member can can store
so it you know it actually goes through
and says oh is this a signed 16
bit value well it can't store
the the full
two bytes it's one bit short of that
because it's signed and basically it
does it has all that logic involved
so we can actually extract that and says
hey if you're trying to store a count
that exceeds the storage
of this member
we're going to freak out and truncate it
and you know warn about it and return a
safe value that can actually be
represented
by that by that one
and i showed that first because it's
basically the first thing that the mem
deflects dupe would do is we've got this
pointer
we're gonna make sure we have a safe
value that we can store we're going to
calculate using struct size helper again
how many bytes it will take to
store
the beginning of the structure plus
you know source count many members
following it
and then we're going to try to allocate
that size if an overflow in in this
occurs uh struct size uh
becomes a size t max and k malek will
refuse to
excuse me we'll refuse to allocate that
so we will not get the allocation
in the next in the test which is why
we're
checking for that
and then we can figure out how many
bytes you want to copy
and we wipe the beginning
of the structure and then copy over uh
what we want
that we're deserializing and then set
the member count
if you're very astute you may notice
in the setting of the member count we're
using this from cpu function that got
passed into the macro
sometimes these
flexible arrays are stored
their their bounds are stored not in
native cpu
[Music]
storage
because they're being used they're being
passed to you know
devices or being passed over the network
or doing other things so the bounds are
tend to be stored not necessarily in cpu
native formats so we actually have to
pass in a conversion
function here that's not the general
case but that
is needed for enough of them that it's
it's a it's now an option for this
and then the big one which doesn't do
the allocation but it has to actually
verify
the sizes of things
it's going to copy
so this does the same clamping at the
beginning
figures out destination
you know how many can we actually store
and this one does a 2 cpu because it may
not be stored in in cpu native form
so we know how many count
we can store to the destination we
calculate the full size of the structure
plus its trailing members
and then we do the same again for the
source and compare the destination and
source and yell very loudly if it's
overflowed and and truncate it if it
were going to overflow
then we can do the mem copy which you
know we've safely we've actually
verified now
and then set the the new member
to the current size
and then return that pointer again
so that does the bulk of that work
and that should get us through
that other 66 percent uh pretty pretty
well it won't cover everything in there
because we'll still have open strings
and other stuff but the
vast majority of the problem is is the
flexible array members um
there's other cases where there are
other bounds you know a single string
allocation has a bounds somewhere so
we'll
as we make our way through the remaining
remainder of that 66 percent we'll
probably
add more apis as we go
but this is what's on the schedule uh as
far as
protecting the kernel
um and i say schedule because
here we are sort of looking at where
things are and
and
what it takes to get things converted
so 5.16 was released uh january 9th and
that has the strut group macro and its
related helpers are in it
and almost all of the flexible array
conversions where we converted from the
ancient style you know
one element array being used you know
being lied to
and zero element arrays uh being
converted to a proper flexible array so
we can actually the compiler can start
to reason about it
better
those are almost almost completely
landed there
for 5.17
which the merge window is open right now
all the struct group conversions using
that new macro
i have landed so we can start adding
the next step would of course be
enforcement but um
and then there's array bounds which i
haven't mentioned until now
this is another case of compiler being
able to check the size of objects for
things beyond just mem copy
it'll actually do
direct
direct accesses on structures it'll
check to see where how large the
allocation or how large it thinks the
object is
so it's related to the built-in object
size almost all those are finally fixed
so we can turn that back on
so hopefully by 5.8
in may
we can enable the compile-time m-copy
enforcement
so we don't have any more of those
cross-member or beyond member
overflows sneaking their way into the
kernel
and hopefully the flexible array
helpers that i talked about in the
previous three slides
will start landing there
and those conversions can begin
and then hopefully on in july for 5.19
uh we can enable the runtime m-copy
enforcement uh so we would have had a
release where
we can get through finding a bunch of
those and fixing them so we can turn
them on
and hopefully then we will come out of
this year with a vastly improved
buffer overflow defense in the kernel
that everyone can actually use when they
turn on fortify source my goal would
actually be make fortify souls fortify
source a default there's no good reason
not to have it on
it's like if you don't have it on you
just want to get owned for some
reason um
so i've got a little bit of time left
over um i've got any questions or
feedback uh now's a good time i think
we're gonna go through any questions
that came up or answer anything
that's there so thank you for your
attention um
you can
get the slides here and email me or see
me on twitter so thank you
hi thank you kate um i tried my best to
to follow that i haven't even looked at
c in years so it was a challenge but it
was eye-opening so thank you so much and
judging from the chat there were quite a
lot of people who were able to follow it
much better than i was um so there are
quite a few questions here so everyone
please go um upload the questions you
want to make sure we get time for
and i'll start in on them
so the top question right now is what is
the actual use case for built-in object
size foo zero i'm struggling to imagine
what the use case for mode zero is um so
mode zero
difference was inter object and intra
object so being able to block
a mem copy beyond the edge of a
structure so you wouldn't have an
overflow from an m copy from one
structure into the next structure
mostly it's there for the reasons i
outlined and all the gotchas we had
within the kernel is that the c source
like c sources have been abusing them
copy for so long
by doing this intentional overflow um
but overflow didn't tend to go beyond
the end of a structure
um so
you'd had you know this you know inexact
form where you'd say sure sure we can
know the size of it for this but we
can't go beyond it
and then we can tighten it and once
we've you know eliminated
all of the cases in a in a given
tree
uh of of that kind of thing and that was
if i'm remembering correctly i think
that for
user space builds um like glib c
stuff like that where fortify source had
two modes which was uh fortify source
equals one which would actually be mode
zero for uh the bos
and fortify starts equals two would
actually be mode one for bos so it was
mostly about
having a migration path towards a
stricter code base
it's amazing how um
hearing about i guess historical
patterns of use and misuse kind of
influence
all of the the really
technical details of things and how
changes are made painful it's
fascinating
um
all right next question
how did you find and categorize these 30
000 or so uses of mem copy
yeah that's a good question
that's probably probably the easiest
part of it um
but let's see if i can go up through
slides and show
if we look at the here we go
uh in in the in the mem copy
fortified mem copy we can actually see
the the different states we can see when
we have a dynamic size versus a constant
size when we know the size or not
so
we can emit warnings
in each of these cases because this is
an inline function so for e if we if we
add a warning like we do for the
the write overflow and read overflow
functions here um we'll actually
throw a compile time
well that those will throw compile time
error but if you do a compile time
warning
you can actually build build the entire
tree and then you just catch all the
warnings and collate them at the end and
just look at them because you'll have
one warning for each use of memcapi in
each of the different states
so that that's actually pretty
straightforward but it's also i said for
the all mod config build isn't strictly
a representation of the real world but
it is the worst case scenario
great it's yeah
that does sound easier than i was
expecting it to be
um okay
how do you enforce the usage of the new
macros like struct group and new code
um
so
this is one of the painful parts of of
making these migrations in the kernel
uh is
there isn't really a good way to enforce
it until everything's done um
so really it's mostly a matter of uh
educating people
adding checks where
where it's possible in in the compiler
as we slowly make our way through
various subsystems
um
adding because there's a check patch
perl script that tries to do some sanity
checks on patches that are being uh
proposed for the kernel so that could
you know
warn about hey it looks like this isn't
known or something
um you should try using the new api so
it's mostly about education and other
things but once you get to a
tipping point really you can we can
actually modify this mem copy again to
say oh hey
i have a destination size out of
built-in object size that says -1
we don't even allow that to build
anymore and then suddenly you the only
thing you can do is use that api
i don't expect that to happen
anytime soon
but we can use similar instrumentation
to how i pulled the numbers on on uses
and see like how much you know how how
much further do we have what's missing
what else can we fill in
okay our next question
is are distribution kernels usually
compiled with fortify source currently
yes um as far as i know every
distribution i've seen has fortify
source enabled for their uh for their
kernels um
almost no one is using um config ubison
bounds right now the only one i know of
is android so the kernel on android is
is you know blocking
array index overflows but no one else is
yet um i've been kind of uh
harassing the the ubuntu kernel team
nicely
to turn that on um they ran into
problems with uh out of tree modules
actually doing the wrong thing like they
were they had bugs in them so they had
to turn it off you know that some some
driver that people would load would
instantly crash a system because
they were
actually accessing their own stuff
with the wrong indexes
but as those get fixed we can hopefully
more distros will turn that on
somewhat related is there any particular
list news site etc to follow for new
safer copy semantics as they land in the
kernel
um
i would say
lwn
usually has a lot of write-ups on on new
developments as they're coming um
there's also uh
some kernel documentation
in the process docs on on deprecated
um interfaces and apis and language
forms
and that's probably a good place to look
as
as we remove stuff
from the kernel
like disallowing variable length arrays
and doing other stuff that ends up going
into the deprecated
documentations it says you know you
can't can't do these things anymore and
most them get enforced
by compiler options
we've still got a few more questions and
we've got i think just under five
minutes to go so we'll just keep going
with your questions thanks everyone for
posting so many questions you've got a
really really
interested audience there case okay um
all right
i'll be in the other the post talk chat
room as well um since i couldn't watch
chat while doing this but i'll be in
that that one uh so if there's if we run
out of time i'm happy to keep talking
there
yeah we've still got time for uh
a couple more questions live
um
rapidly being uploaded right now
is what is the overall performance
impact of turning all the safeties on
um almost nothing
the
the sizes are
i mean most of the stuff is compile time
and then adding a check
like this tends to
end up with one one compare added which
gets
totally lost um in in the overall
the work because you're about to do a
mem copy usually
in into
you know an area you've you know the
memory is already hot there's all these
other things and even the branches
don't don't appear to be measurably
different
it adds a tiny
amount of image size because you're
adding a couple bytes for the
instructions to do the checks but it's
it's almost nothing which is kind of
nice because it's a it's a very very low
cost
and it's deterministic
that that's great when um
such significant improvements like that
don't come at too much of a cost yeah
it's so good
um okay
what's next i noticed one of the copy
macros included a memset call zeroing
the dust is this a behavior change
um
it might be it depends on
on what the uh
what the prior code was doing um
the
i would argue that it's a correct it's a
it's a correctness change and that if it
is if it is a behavior change that's a
problem because that means something was
depending on an old value that wasn't
being cleared uh since we're uh
since what's being allocated is the
entire structure plus the trailing
arrays
you want to have initialized
the rest of the structure
and if you haven't that's a problem
and a flaw in itself normally when you
look at
the code for these things you'll have an
allocation and then it'll set a whole
bunch of members within the structure
and then i'll do the copy et cetera
so adding the memset
would seem like it might be redundant in
these cases but luckily that stuff will
get elided by the compiler when the
compiler tries to do the compile because
it sees a mem set but then it sees later
rights uh that are that are being put
into the same place
and i'll just get rid of the zeroing
that happens in all the places that it
can
so you usually end up with absolutely no
difference in the final binary output
so i'm just grinning wildly because i
have definitely myself both written and
fixed code that has been unknowingly
dependent on on bugs or gaps in the in
the language itself
very familiar with that
um okay we've got time for one more
question live
what is the second most common cause of
cds
second most common i'm not sure this is
even the most common but um
i haven't gone through to to analyze
them lately um i'd say
i'd say probably
this may be the second most common uh
i'd say probably one of the largest
issues that the colonel is still dealing
with is use after free
so just dealing with temporal problems
with
bad code freeing a portion of memory
that it thinks uh is no longer being
used but something else is using it
um
there's a lot of causes for that some of
that is arithmetic overflow which is
gonna be another piece that we're gonna
take a look at once once this is nailed
down
but yeah i would say use after free
arithmetic overflow and buffer overflows
are
related they're interrelated and
the some of the major problems
with c generally
hit the tricky ones from my limited
memory of c
all right okay we are out of time
so there are still a couple more
questions in the questions tab uh
we will copy them over to the
the
post talk chat kaya theater text channel
which is over in the in venulis in the
in the tab if it's not appearing for you
in the channel list um click the browse
all channels and find post talk chat
kaya theater and join that um case we'll
head over to there for a bit of a chat
during the break
um
so thank you very much for your talk
case i'm pretty sure you're gonna get a
lot of questions in the chat um
and have have a have a good quick break
everyone and we will be back shortly
awesome thank you bye