Welcome. I'll give this talk about static code analysis in the kernel. So last year, I did
just talk about hardware uploading through network caps and using internal kernel APIs
to push rules into hardware. I didn't talk much about last year, but this actually led
to discovery of some performance issues in the kernel, which then fixed shortly after. So this
was in 610 where we implemented a TC bypass feature, which is then refined further in the
next release, which is essentially only enables software processing of TC rules, if all
the rules don't require. It's only enabled if any rules require software processing. And
then after I did this, I also worked a bit on trying to make sure that the validation of
these rules were done properly, whether they could be hard to upload it or not. And this
set me to poke around in five few different drivers. So one of the drivers that I poke
around was the quid driver from Qilotik. And in that I found something like this, where
this looks like a normal static helper function and a current current zero and a current
turn two different error codes. I then had to propagate in any argument to this function.
And that led me to edit all the call sites. And then I discovered the call site looked
like this. So it just checked for none, several X code, and always returned the same error
code. So the unabsuppe would not be possible to get exported from this function and
out into use space. And all's used in this sense in turn on in the kernel. In some
case where you don't specify if you use software hardware, then it will try to do hardware.
If it can, it will say that it's hard to upload it. And otherwise it'll just influence
the software. And it depends on getting the unabsuppe for that to work. So then I found
three different bugs of this kind within this driver, where they had all been there from
the initial commit off this functionality. And in some of the cases, it wasn't an issue yet
because the helper function only did return one error code. And therefore it was fine that
it was all written for the out. But in another case, it did cause an issue later on because
the reviewers didn't really catch that adding a new return code in a function didn't
necessarily propagate all the way through. So I don't blame the review for not catching this.
And in general, if you intend on to use a function in this sense, it's better to have it
be able to enroll you by it only has two extra codes when you just have it in a simple
if statement. So they have been a bunch of other research on this topic. Unfortunately,
the research team from Reconcentre University that have done this have focused only on
the file system and the block layer. So they haven't looked into other subsystems. And
they're not active anymore. And this book that I found was in Houston, Susan 18, but still
been there for quite some time. So therefore I thought it was fun to see if I could do some
static analyzes and detect these because they seem pretty simple to detect. So for doing that,
I've looked into a tool called SPAS, SPAS. It's a tool written by Lune Souss, way back in order
to help him vet patches for the Lune's kernel. And it is also standalone static analyzes tool
that has some building checks. And more or less, the whole Lune's kernel today is clean in this
tool. And by using this code base for doing this, I also know that this code base works well
with the kernel. So I know that it works with the whole code base and all this special ways
that the kernel abuses GCC. So it has a bunch of binaries in the code base, which are useful
inspiration. And the initial commit was this from, yeah. It's not so simple anymore, but it's very
easy to run with K-built. So you can just do a check equals SPAS. And then it will run SPAS for
area of single source file. And this is frequently done in the kernel tree. But it's also very easy
to replace SPAS here with your own SPAS base tool that will do some analyzes. So that's the way
I hooked it in. Unfortunately, this runs one per source file and we'll come back to that data.
But yeah, SPAS has a function looks like this within SPAS. If you dump the instructions,
this is internally we represent a lot of structs and unions that are all in the find with a lot of
pointers, which makes it a bit hard to dump. But more in the later. But this is basically a
returned step in the bottom that returns a register. Then register is set to zero or to an error
code. And up top is a code to a register, which a register is a time from a code for a static function.
And then based on the return code, we choose which branch to take. So this is a simple case
where we can analyze that we only have two possible return codes from this function. This is the
only the brief part of the function that this mentioned on top to fit on this slide.
This is a more complicated code where it's a function pointer that's called where you need to know
which structs is reading in and of which offset you have the different functions defined.
Which is a bit more interesting to, so I've left that as a later exercise.
But basically in order to do an analysis of this, I haven't completely finished yet, unfortunately.
The way I've gotten is that, you know, because this is called once the source file,
then I need to dump all of the information that I need and then retrieve it again in a later processing
stage. And most of it worrying, it's like 95% done. So probably in a week or two, I will publish
how many other bugs I found, unfortunately, life happened. And there was enough time to finish it for this.
But basically it's turned into a big civilisation, deceleration task in order to
be able to do the analysis at a later stage, combining all of the knowledge that was found
in the initial processing stage. But it does show promise and the way I've implemented those two
focus on finding the stages where I know that a bug, like the ones that I have fixed already,
and I will also welcome you to have this website here, where I'll post updates. And I will
welcome you all to look at this a few weeks and see if there are some bugs that you can fix,
because it would be awesome to get newcomers to help contribute some of those fixes back.
So yeah, any questions?
So I love what you're doing. This is fantastic work. Having newcomers do it may be problematic,
because it does require a certain amount of big picture understanding that newcomers may not
have. So the code that we have today in the tree has been tested and does work. And you may find
that in some of these cases returning e-overflow or all over the other, I think that was actually
great user space, because it's not expecting to get blacks. It's not been tested.
We just terrified. So and we may well have situations where we are deliberately throwing away
an error code and returning a different error code. We actually go to all the time in the file system
world. We guess back some very specific errors from scuzzi devices. The scuzzi error return
code, I think in return like 300 different errors. And 99% of the get mapped EIO. And that is
entirely on purpose, because user space cannot cope with, oh well what's actually going on here is
that there's a medium error and blah blah blah, you space can't cope. It just needs to know EIO
this didn't work. Of course. And there are many cases like that. But part of the minimizing
false positives is also to begin with just focusing on taking a looking at this function,
this helper functions, how many places are called. It's all of the places that it's calling
only treating it as a blur. Then it's worth looking into if that can be changed over the return
isably in. If there's only one core site like the functions that I have here, then it should
return by the whole spectrum off them, otherwise it's a bug. So I'm trying to minimize the
amount of false positives by not targeting finding all the bugs, but targeting finding the
bugs that I find are actually probably bugs. And this was in a driver. And when different drivers
are not returning right error codes as the rest of drivers do, then use space which normal
support multiple drivers will normally expect to do the bad thing. That actually sets my mind
disease to a large extent. Thank you. The other thing about trying to get more people to submit
the patches is that if I submit all the patches, then I get blamed by not doing enough reviews.
Any other questions?
It's basically continuous. Can you add a comment? So it stires that you can overwrite
is that you say here, the other code is okay. Yeah. Okay, you have certain.
I don't have that yet. It is a little bit problematic to do because what I can see in sparse
is only the actual code after the preposterous have run. So I might be able to see attributes,
but I haven't looked into that, but yeah, good system. Okay, save me as close in error.
Yeah. It all means that it needs to be run on many different configurations.
Anything else?
All right, thank you.