Modern C compilers include support for tools to help find bugs in code. These tools, the sanitizers, add instrumentation to the generated code that can be compiled into the kernel to help the kernel developers. In early 2018 I became interested in using these in the FreeBSD kernel to assist bug finding and debugging. This talk will discuss the current state of kernel sanitizers on FreeBSD. This will include the kernel coverage sanitizer that can be used with fuzzers, the undefined behaviour sanitizer to warn when code relies on undefined behaviour, and the address sanitizer to detect out of bounds accesses. It will also discuss future work to port new sanitizers and the use hardware based acceleration. The main fuzzer to use these sanitizers is the syzkaller fuzzer from Google. I will talk about my experiences using this, bugs it has found, and future work to port other fuzzers to work with the kernel.
 I want to give a nice talk of the day in Sloom. I'm going to talk about Cooniel Fuzzing and the related things. I'm a research associate working on operating system related and security related things, and even the University of Cambridge. My team sometimes do free-dart software engineering. You want to come and pay for me money. So, at the start of, even though it's about fuzzing, we don't talk about sanitizers. Because sanitizers are useful for us. They're tools that will instrument, yes, they're sundry and they compile that. They will instrument your code so you can find some information about it. They do this by adding probably an inter-function call into your code somewhere. Some, not all of them do exactly this, but you can think of it as when your code is doing something that the centre is interested in, they all put it in a function call and do it somewhere else. It could be, these cases could be on every entry into a basic block. So, every time you put down a brace into your inner scene. It could be on every comparison operation. So, you want to see what values you're comparing in an in-depth statement, or in a switch statement, or similar. Or it could be on every memory access. So, you want to see some information about whereabouts your program, what mean where your program is reading, writing, or storing. And in one time, there was, there's one time at the user space for these. So, I'm not going to be talking about that. I don't really know much about those, those one times other than you probably just turn on the flags, it works. But, in the code that we need at home, so, I'll start by talking about these. So, the first sanitiser we'll talk about is, about undefined behaviour. So, you've all, you know, almost every piece of C code you can find, or probably in WC, because we have some undefined behaviour. And, luckily, there's a KUB saying for that. So, what it will do is, anytime the compiler thinks that there is some possibility for undefined behaviour, this piece of code, it will put in a function called to check if there's a lot. So, things like shifting, lift, and end, wider than the size of an end. And, oh, I can easily know that compile time, if that's true. Or, you know, the other side, you know, the, that's not I mean, yeah, or using, or no point of reference. It won't know, you can't tell, necessarily, it uses compile time, if this is undefined or not. Or, although the compiler thinks that it can prove it is, it could potentially do quite bad things. Luckily, maybe it's the, here's the micro UB saying, so that's just, this is the, the very minimal implementation of the undefined behaviour sanitiser runtime. It was imported last year into the next day, and then I decided, that looks quite good. I will do the same in previous day. And so, I did this, it was only in BSTKM last year, sort of Cambridge developer summit. And, the only problem is that it does increase the size, so, we do leave it off by default. It does make, it can all about 120 meg for the L file, for generic. And, yeah, nothing BSTM would have this year. So, you run it, and then you'll find this. Yeah, this is, this is my memory access. Yeah, no, you've been notified, no point in the reference is interesting. This is actually going to try to find the offset of an item inside of struct. So, it's the class null to a struct type, take the address of the field inside of structs. This turns it to be undefined. Use container of, or, have a similar, there was a, see, built, a, claim built in there. I think, probably modern GCC will follow you in it. And, yeah, the other one, the other one, you know, don't shift it 64, left by 64. The compiler can do anything at that point. And, you know, some, some, some, some, some compiler may just turn it into a instruction that will only look at the normal bits of the, the size and shift it left by that much. So, if it's out of bounds, at least it's too wide for that type, then, when you look at the normal bits of it, and so I won't shift this at all. And so, you, you could get unexpected results. So, if you make 0 over here, you may not get it though. So, this is good for just general code cleanliness. If you're doing a modern capacity, you'll get lots of errors. There's also warnings, I was just, what, you know, about that. So, you may take a lot of effort to, you know, actually find ones you're interested in. But then, there's a coverage synthesizer. So, this is one that, that will insert interesting, you know, insert calls into the, into your code on two points, you're interested in. And then, we start basic blocks. So, you call into, you, inside the start of a function, or inside an, of, of condition. It will put in some code, and a function called in there. And also, on comparison. So, when, when you run your, if statement, it will put in a call. It will also tell the compiler, as I said in the runtime, a little bit more information about the, the comparison. So, it will tell you what the two arguments are. And it will also tell you the, the width of the, the comparison, because it uses different functions depending on the width. And whether or not you've got a, when the values is constant. If both are constant, of course, it can optimize out, so you won't see this. Luckily, all, all OpenDST and FreeDST and EBSD have, we've all committed, got a version of this. And then, I think all, it all, it's been, and they implemented it. So, easy tracing. This is tracing with basic blocks. You get, what you do is you're allocating the buffer. So, this, the top here is the buffer. And then, the start, the first entry in the buffer, which entry is, depending exactly on the, on the operating system, is going to be the size, or the number of items, sorry, in the buffer. This is the number of items that have valid ID, valid entry, so not the size of it. Then, just a list of program counters, or what you would exactly want to call it. So, address that's, an address of somewhere inside, probably the start and base block. Where, so each of these is, FreeDST and EBSD, both put these 64-bit wide things. So, it makes it nice and easy for the next one. But, OpenBSDs use human pointer test, so 32-bit code will be, 32-bit, 64-bit code will be 64-bit. This is, this is like K for tracing, you find out all of the values, you don't necessarily find, no, why you're going here though. And this is where you get, this is where comparison tracing comes in. So, you'll get some number, so you still get the same count as the start, except in this case it's number of four, four entry items. So, the 348 there will be 348 by four entries by the range of entry. This one, you'll get some more information, so you get this type here. So, in the first example it's two, which basically means it's a size of, whatever size one means, which is a defined thing as 16 by, 16-bit per person. And the bottom bit is a const value, which means it's not const in this case, so that means the two arguments where both come from the variable somewhere. And then you'll get the PC as well. This turns out to be quite useful in that you now know why you're getting there, going there, rather than just where you're going. So, you can then potentially feed, if you see data in one of these steps, and then you can find it in your input file, or your input data, you can potentially modify, try modifying the input data to be the same as the other argument. You can try using that to find, you know, interesting paths through your code. And this is the same thing. I think BSD has your input point of T for each field, which means I'm not sure how it does comparisons with 64-bit types. I think it might just drop the top 32-bit architecture, which probably doesn't matter. You know, it's unlikely to be used there, isn't it? So, we can do this. It's a simple way. All you have to know is you've got a dev cake off, which is just a device that has in my layout, two interfaces that you can communicate with. You have to see the buffer size first, just because the kernel needs to allocate nearly. You can then map it. An interesting thing is, you can trace, when you trace it, you don't have to be, you just have to enable the tracing on the three that you're wanting to trace. So, it's only the kernel part of the thread. So, this is only going to trace a single thread as an interest kernel in returns. It doesn't even have to be in the same process on three, at least. You have to zero the first field just because you need to, just because it will be disappear to there otherwise. And then, do your operation and undo everything. You can keep rerunning this if you feel like, and you'd have to keep closing it. And this will become useful later when we talk about fuzzing, because this means that you've got some sort of feedback about what paths you've got through the code, what have you seen, and then you can then look at one, you can then try to infer how you can get through the code later in new and more malicious ways. But then, okay, so those are the two traces that covered the two synthesizers that I've accessed in all the VSTs at the moment. But then, so I've got these other ones, so A-SAN. This is the most useful one for checking if you've got memory that's, and making sure your memory is inbound, memory accesses. So what it's doing is when you allocate memory, or do some operations on the stack, it will have a piece of shadow memory, so it's just a malocated memory somewhere else in a fixed area, that it can say every 8-byte block of main memory of your KDA, or your connoisseur space, we will allocate one byte of this shadow memory. And then we can mark when we've got one, you know, we can say whenever the memory is invalid, we've got a value, and we can 1-8 bytes of valid, we can mark that, but the condition is that it has to be to form the first byte of the 8-byte block, and it has to be on the 8-byte boundary. So it can say no memory or any one of contiguous memory. So I've got a picture to explain this. So here we've got three bytes of valid, and then the trailing five bytes are all invalid. And that's when the study, the top of the shadow memory, are all in-bites. So this is saying if we say n is three, then three are valid, that's easy enough. If we say n is zero, then we can have all of them, and this is just what the KDA is saying, I would expect. And for other expressions, and if it's less than zero, it's then all invalid. And maybe we can also have certain less than zero values that are marked. This memory is invalid, but that's been previously allocated, for example, or we can give it some information about why it's invalid. The reason n is zero is because, and as the 8-byte is because when we do, we have the option to build a compiler to insert these values, for example, with a stack. So we have to make sure we stay compatible with that. So that's what it does in some ways. All allocations would now need to be to at least an 8-byte boundary, just like that's fine. And then it's up to another 8-byte boundary. So you can start another allocation within that boundary. But of course, trading memory can be marked as invalid, and we should hopefully catch that. And also, we should pay it out slightly more than just to the end of that ban, because what happens if I get my pointer and I give it, I accidentally move on to the next one. There's a limit to how much you want to, maybe you want to waste. But we could probably have one more 8-byte blocks after this, just to make sure that we don't accidentally go and weave it out of bounds. It's also useful because pointers to, if you do go right up to the end of your 8-byte boundary, you want to make sure there's at least another block that's invalid afterwards, and pointers to arrays are allowed to be pointed at the end of the array. So you don't want them to make some individual difference at the end of the array. So I've got a wee example. This is, if you're not used to fairly sees, allocator, as my knock, in the kernel, just the end of the 10-byte, you can ignore it. This means that's 10-byte values and is guaranteed to succeed, or awake, or asleep, until with the cancer team. So data is guaranteed to be long-long. I've got some function gitdata, which takes a pointer and an argument, and it's going to return the first item. So hopefully this doesn't have a buffer overflow in it. I don't think it does. And gitdata may have specified that. So we'll create this. We start thing off, memory goes up. So a lot of bottom is the lower address, the top is the higher address, and across to the right is the only. Oh, sorry. So I've allocated four bytes, and so I change it from being on-stack to a heap of allocation. We've allocated four bytes because I see an inside event, which is four. We have to pair this up to eight bytes. So we've got another four bytes to make sure that you don't accidentally get just past the end of the way. And then we'll put another eight bytes on the ingesting case, because we always put eight bytes on the ingest to make sure that you don't go out, you don't overflow. That means the first four bytes there, blue, data you can read and write to it without anything happening, basically. And so if you accidentally try reading any of the other values in Google, I'm sure there's one you that you're doing something that's silly. So put into your allocation these values, and it will say in the sharing map, I have four, which means four bytes, and if it means invalid. So that means we can load a store to 033 is fine, and 4355 will be detected. Anything past 15 I can say because that's outside of this allocation. It could be the IP to make for something there, it may be the end of the page, and so it's okay. We don't know. And so now we accidentally read from data one, and everything should, and we'll get that, or 20 of the venue and exactly your implementation. So this code, Google as a, NebisData has a version of the implementation of this, and I have a student who will be working on this in the sum of code. I have an initial patch that doesn't quite do everything to explain, but it should at least get the students started. There's a lot of us finding the allocation we've got, which is horrible in the code, trying to find the real-ear, which we may allocate mainly. So this is something which, then Google came out with a something interesting, a saying, the implementation, which is a hardware-assisted version. This is ARM64 specific, because it uses a patron ARM64 code top-byte ignore, which basically means it will ignore, you can put any value you want into the top 8 bits of your, of your points of your address that you're loading or storing through, and you'll just ignore it and pretend it's, it'll look at it, it looks at the bit 55, I think, of the address, and it extends that up. So it doesn't matter what you put in there, or you don't, the handiness of the value. So they say, well, what if we put a tag in there? And, you know, we've got two 15, six bits, two, two, six possible values. We could put more, we'll reserve a tag for an allocated memory. So we've got two 55 possible 8 bit bytes, two possible values we could have there. And then we'll just store the tag. We've got some way of allocating the shell space. We'll just store the tag there, two, four, that piece of valid memory. And so if we, now, if we come, we do a load of store. We check the tag, you can check the tag against the byte, the shell space, just to make sure that it's valid. So this does mean you, the previous one, you may, you're only just getting at bounds. This one, you may get a few other things, and it's a few different issues, find three different issues like, if you allocate three, allocate, you'll get use after we allocate, would hopefully be treated, be detected. So what does it do here? So we start off, no allocations, we make some allocations. So we've got a low allocation, and then we have two more. And then we try to load from address three. And because, but with a pointer from a blue pointer, so we've worked for one and two, that will not work through. So basically, it's, this is a slightly different way of doing it, rather than saying, rather than saying this byte, this is valid. We can say this is valid, but only with this pointer, which previously we couldn't detect this sort of thing. Because if we moved, accidentally moved from an allocation, the blue allocation to the gray, we would see just, well, we've still got valid memory. They also do a few more things, so they make it slightly more, slightly wider, because they want to be found on phones. This is a Google thing. So everything's 16 bytes and undecided. And you're not able to detect slightly out of bounds issues. Because the tag is per 16 bytes, you can't say if you're just, if you're still within a 16 byte, like, and you can't detect that. Yeah, so you've got a, and you've got problem elastic. This is, you sort of hope it. And there is now an MV 8.5, I mean, tagging extensions, which are similar to this, which with a small tag. But this, I mean, that's okay. It's useful for finding issues as well, I think. Not, slightly from classes of issues. But then, well, we've got this, this is the project we've gone on, where we have this, we've decided, well, once we take pointers and double the size of them, but then code some bands and permissions on the top bits, and make sure that they're non-forgeable. So you can't just get one from anywhere. And you have to derive them from other capabilities. So you can't just take one, and then try to expand it toward a memory. This should also be, you can consider this to be similar to a sanitizer. With your ABO, back all pointers, these capabilities. But come along tomorrow morning, I have to send two ebooks to tell you about this. I'm not going to go too much into this. So we should be able to, we will be able to get slightly out of bounds, if you point at, so we'll be able to get pointers that are slightly out of bounds, like K.A. saying. But we don't get the tags, things, but we don't get tagging, work, and doing with the hardware to your sanitizer. So you still get, potentially, the use after free. And there's a possible, there's research going on about no bounds, even more, so we can say, can you detect out of bounds accesses within the struct? Have you gotten the right, for example, you want to make sure that you don't, or another struct, within the struct, you don't want to make sure you don't accidentally go out of data and into the parent and do things that may not, ACN may not be good at finding. And then, okay, so this is all about address space. That was finding bounds and things. But the thing is, there's also the memory sanitizer. So this one is saying, I've got, I've got these in the memory. I've advocated that, and I've advocated that, but it's just, it could be random data in there. We want to make sure that you have at least written to the data before you try to read it. And, or you're initialised before you're using it. But, so use here is decided as you're using it for conditional. You're using it for, as I pointed to, dereference. Or you're copying it to user space. So the last one's important for finding, you're accidentally leaking some memory from, it's a kernel stack, say, or an unmercialised part of a struct into user space, which seems to be reasonably common, the thing that people have done. So, my example, we've got an int a, we haven't initialised that at this point. We've got int b, that's not a use, because it's not a good initial, it's not pointed to a different point of view reference, and we haven't yet copied the data to user space. When we do this copy yet, this is definitely a use theme, because we want to make sure that this is now our stack, we now have the king stack information to user space. So it's definitely an initialised use at that point. This is, turns out to not be. We've got an integer, which we haven't initialised. We see that only if the flag is set, some flag that was being passed in. If, and then we use it, well, we think it looks like it's used, but it's not. It's gone to propagate the fact that it has initialised to see. Then if the flag is set, or if the flag is set, then we use it. And because it's impossible, you can only get into the second case, if you've got into the first case. That flag, this is not going to be an initialised use. So you can probably, probably don't write this code, please, don't. You probably have something else in the middle though, and you can probably should warn you, but it's possible this sort of thing happens by accident. So you won't detect this sort of issue because it's not defined as a use in the same case. Other ones, if you're allocating some memory, you're doing de-referencing it. And the point of de-reference is not an initialised use. You also have the point of comparison, so. Now, because in this case, I have also, I don't think we mean me in the scene, it's okay to wait. So that's definitely not going to be a no point of de-reference, but it might be, but it's not initialised either. So this also, you know, these tend to use a show-down map, and it's one bit provide, so basically saying if the show-down map of this, so when we translate from between the two, so your caveat, you can already read the show-down map. If it's a set, it's poisoned, and so you can't use it, you can't read it. You will need to do things like you're poisoned by the fault. Mark will un-poison memory, so make sure you make it readable. If you set it in zero, which means zero memory, please. And writing constant days into it, one poison. Writing non-constant data will have to, it's been, you know, with this case, writing the state of world will propagate it back. So if flag is un-sets, it will still be the memory, see if it will be poisoned, and if flag is set, see if it will be un-poisoned. So knowing the commuted K, you can see how that can tell. But NBSD has got the K leak, which is a similar concept, and that it will find the similar sized memory. But it uses, so K, A-SAN, K-N-SAN use out-of-bounds signaling, so they have another piece of memory, which has a mapping between, some kind of maps between your main, your critical visual space and other bits of memory, whereas K leak has used a demand signaling, so on Mark, we'll just write all the memory out. We'll write with a known value, that's one byte value, to all the memory. And then when you do your copy out, we'll check, has any of this memory copying out containing that known value? If it does, then it's warned that there's a potential kernel disclosure going on. So that could be, you can have some false positives, and that would be obviously, because you made that value, you made the chip that they be in the memory. Now, there's a paper behind this, and they do explain how they chose this byte. It does change over time, from a pool of bytes where they found these ones were less likely to be used to be copied out. So there's certain values which are extremely likely, so if you use one of the unlikely ones, you're going to minimize false positives. You could. The other one is, it uses the coverage sanitizer type system to poison the stack, so every time you enter a basic block, it will just write it out, over it's need and pass the end of the stack. So that when you return from that, if you return from there and go into another function, but don't initialize something on the stack, it will, you'll detect it. So you, I think you could probably, it's been important to figure out, and they have been some vulnerabilities, or some memory issues reported in FACTS. I don't know if we want to import it though, I don't think we do, because I like the Emsen, the Clemsen Ruby. We do it. And lastly, there's the, a threading sanitizer, so that's what this, I don't know anything about this one, so I'm just putting it up here for completeness. There was a kind of version of the threading sanitizer, it may not be on hold, I couldn't really tell from my Google, Google aim, whether it's coming to being worked on. But it's just there to find databases. If anyone does find out that you know anything about this, I'm happy to, I'd like to know, because I'd like to know if it's something we should be looking at. But, okay, so we've got some sanitizers, but why, why do we want them? Well, the obvious one, is it makes, making bags easy to find, and hopefully fix, is good. I want to go to known, I'm doing something stupid, and make it easy to find, I'm doing something stupid. A pick off is good, it helps fuzzing. It means that we can find more bags, and hopefully, hopefully fix them. And they also, it makes it easier, and it makes it easier, and having the right parts of K-Corp makes, and the other sanitizers, makes fuzzing bags easier to find. So, we can find, you know, 3D-ST has, for example, has tools to find use after free issues. The problem is, the point at which you find out there was a use after free, is when you try to allocate the next, and there is, and you just happen to allocate, be allocating some memory that was previously written to, after being free. Which may, you know, that's okay, that's a good thing to know, but I would like to know when that happens. I don't want to know that I've got to use after free, and sometime in the past. I want to know, I've got to use after free now, so I know exactly what needs to come out to look at, in fact. But, yeah, so, that's really why I want the sanitizers, to make sure I know exactly when the code, I've got some code I'm looking at, I know that Scottie has to have the issue, I want to know exactly where it is. So, yeah, Fiskir, there's no, there's a system called Fuzzer, Google's page, well, other people will go down as well. It's written in Go. It supports free VST and open VST. It's very good at finding panics in the kernel. It will use, so it uses the coverage sanitizer to say, you give it, you know you have to find, it gives it some system calls, and it will use coverage sanitizers to say actually where it's gone. So, that's the main reason I wanted to take off, was for this. So, you can keep some of the thoughts out of this. So, this was the most recent issue that has happened. So, since Boston is the Google, it's just kind of running on Google's infrastructure. So, they've got a single instance, or sorry, single machine type, I'm not sure any instances they have of this. And then they found these bugs in this one, the bottom, which you can't really see because I didn't zoom enough. So, if you know anything about any of these, you might want to have a look at this. Some of them, so some of these, when you see these we've got, it means that it's got a reproducer, but since it's kind of forming it, some of them are also, it can generate C reproducers, if you want to try running on your local infrastructure. Okay, so we've got one type of machine, one instance type running. If we had the sanitizers, we may be able to get, this is the Linux example, and how many of them, they've got a few different types. Well, most of these are always San E, but they can, Google can then run and find issues. They can find the use after free issues easily because they've got K-San running, and they can find other things, when you may be releasing, and you can use the space because they've got versions with K-San running. It'd be nice if we could have these and then we could run a lot more and find even more bugs. So, yeah, what, how's this going to work? Well, they all try to, so what it does is it runs different system calls. It understands arguments. So it understands that this function, this system call will return, return a function point, return a file descriptor. It will then try to pass that file descriptor and something that takes a file descriptor. There may not be something that naturally goes together, you shouldn't probably, you know, you wouldn't write it this way, but we'll still do it because you could, because it's a file descriptor, it doesn't know anything more than that. And it turns out that's a good way of finding big bugs when you're passing something you really, you'll be expecting. You know, like I said, it's good to find panics, and it will find new producers for you if you wait long enough, and hope. And it says, it makes it easy. And yeah, so this is the example. This one here, we've got two new producers, so this one does actually have a senior producer. It will give you information, it will tell you the kernel panics and here's the trace. This just comes out previously, but for anyway, it just understands enough about this to print it to the recorder, and I think this one, yeah, this one, this is from a fixed user item issue, so I think Matt Johnson might have fixed this one. I can't remember. And he's found this one a few times. Yeah, I found this one five times, but it got in here five different ways. Join these mailing lists. They will tell you, they'll run it on their infrastructure, email it every time they see that issue. When people fix things, if you tag it, they'll tell you, put this reported by this address in the commit message, and it'll know, and it'll then check take it and say, oh, it must be fixed, and then check, make sure it's everything. And so, yeah, I can find the list of people interested. You get my emails fairly regularly about satisfying the new issue. The other one is, has anyone not heard of AFL? So it's a similar puzzle. It's a file format, it takes a file, modifies it, tries sending it. So it's really good things to do causing. For example, file system. It does this, you can look at this. It will take a hash of old pointer, and it will then send a new pointer. So basically, it wants a hash of some data, and then it will increment the value of the pointer in a buffer. So it can then say, I tried loading this thing, I got this hash at this map out, I read from here to here. It's not exactly this, I think there's, I think there's some shifting in the input as well, but you get the idea. So you're finding edges in your code, so places where you've gone from one place to another. So I didn't experiment with the patch to talk. So to get K-Cov to output this format, and for AFL to consume it, yeah, takes a long time. If anyone has any ideas on improving the performance, I can do about 30, I can mount it, it was creating an MD image, mounting, unmounting, killing or removing the MD image, about 30 mounts a second, which I think I calculated as 12 days, of just bit flips, because it will go through it so the way it works starts off just by bit flipping everything. So if anyone's got any ideas on how to improve the performance of this, I'd like to know. Hello, I'm Convin. Sanitizers, yeah, everyone's got, all three of the main VSCs have K-Cov and K-UVC, which is good. Nuby says K-A-C-N, and I can VSC, I suggest you have a look at this, and I used to think about it. We don't know anyone who's using the other sanitizers, well, Cherries did not sanitize, but no one else has the other ones, and they make bugs easy to find. And if you do this, Google your stuff, trying to break it on the infrastructure, and please look through these. It would be nice, there are people looking at them, but it would be nice if you've got some of the expertise in one part of the code, to look at this, just even if it's a period of time looking at it, to make sure there's nothing that you might understand. In our document, you might have got any ideas on making a file fast, you know, to give me a help with. Maybe putting, getting rid of the file system and use this as a space for something, I don't know. Any questions? So AFL can use a corpus, and I'm curious to know what was in your 128-kilobyte corpus. Have you tried it with file systems that were damaged in some way, or did you just start from an empty mount point? The question is, if you're taking corpus, and you want to know what was in it? Mine, I started with a valid file system image. The one of the issues I found was actually, we previously recently got checksum in support as it, which makes it more AFL isn't really good, very good at getting past checksums, because it now has to do a bit flip and modify the checksum to get past the checksum code, which I tried to save a little bit, and that didn't still take a long time. So I'm wondering if you maybe better tools there, a custom plaza would know that understands, you've modified this piece of memory, and now I'm seeing this other condition in failing, which wasn't failing before. Maybe I should look at that to say, what comparisons were there? Can I find one of those values in my corpus, change, modify, addix, their value to be the other value? Is it possible way of getting past checksum and checks? So, let's have a question or a comment, but it seems like this is a really good start to sanitize or run times and that kind of stuff inside of the kernel. I'm wondering if there's any interest to, since NetBSD and now OpenBSD are also interested in that kernel sanitizer on time, if there's any interest in sharing code bases and collaborating on that, one thing that I'd like to do is to implement a runtime that supports CFI in SafeStack in the kernel. So, there's no comment on sharing code bases. And, well, so, we do share the undefined behavior sanitize code base, because that's all based on, as far as I know, it's all based on the NetBSD micro-UBSAN code, which also works, at least on NetBSD, and it works in the user space as well. K, cov, I think, are three completely independent implementations. That's partly because that part of the code, I'm not sure how similar the code to talk to, to be on the kernel side of a device, is between the three BSDs. So, I suspect, K, NSAN, K, DemSAN, we could teach this year something there. A lot of it's just accounting. Yeah. And I haven't thought about CFI things in kernel yet. We need to teach CTF Convert the LLVM IRF code on that. So, yeah, comments about teaching, anyone who doesn't teach CTF Convert that LLVM the code for it. Talk to Sean. Yeah, let's get that. That's great. Is there a point? I didn't exactly understand how the fuzzing and the coverage pieces work together. Are you choosing fuzz targets based on places that have low coverage, or could you... The way the question is about how do they fit together. So, you don't need... There are two independent pieces of things, and you don't need one for the other, but they complement each other in that sanitizers make your bugs... If you manage to craft some input to the kernel, which hits a bug, which the sanitizer will trigger. So, if you've managed to send to run a system call, or a series of system calls, which causes something to... a buffer overflow to happen, that may not be detected at the moment, because which could be a buffer overflow, it may just be read in memory, and it's within the page. The sanitizers will make that a panic. The fuzzers are really good at finding, because they look at the code paths through your... that you've got. They're good at finding those issues. And then they will look at the... It will take to say, I've found this code path, now I've modified, I've got some information about that. I'm going to now try modifying my inputs slightly, and try and see if I get another code path. The modified input slightly, try another code path. So, it's more about... They're good at trying to find these sorts of issues. And the sanitizer is really good at detecting when you have that one. Without the sanitizer, you'll still... You'll still do this, but just won't detect it as easily. So, the idea is, I want sanitizers there just to make the... When you do get the issue, to make it easy to detect. Is that all the questions? Okay. Thank you. Thank you. Thank you.
 I want to give a nice talk of the day in Sloom.  I'm going to talk about Cooniel Fuzzing and the related things.  I'm a research associate working on operating system related and security related things,  and even the University of Cambridge.  My team sometimes do free-dart software engineering.  You want to come and pay for me money.  So, at the start of, even though it's about fuzzing, we don't talk about sanitizers.  Because sanitizers are useful for us.  They're tools that will instrument, yes, they're sundry and they compile that.  They will instrument your code so you can find some information about it.  They do this by adding probably an inter-function call into your code somewhere.  Some, not all of them do exactly this, but you can think of it as when your code is doing something that the centre is interested in,  they all put it in a function call and do it somewhere else.  It could be, these cases could be on every entry into a basic block.  So, every time you put down a brace into your inner scene.  It could be on every comparison operation.  So, you want to see what values you're comparing in an in-depth statement, or in a switch statement, or similar.  Or it could be on every memory access.  So, you want to see some information about whereabouts your program, what mean where your program is reading, writing, or storing.  And in one time, there was, there's one time at the user space for these.  So, I'm not going to be talking about that.  I don't really know much about those, those one times other than you probably just turn on the flags, it works.  But, in the code that we need at home, so, I'll start by talking about these.  So, the first sanitiser we'll talk about is, about undefined behaviour.  So, you've all, you know, almost every piece of C code you can find,  or probably in WC, because we have some undefined behaviour.  And, luckily, there's a KUB saying for that.  So, what it will do is, anytime the compiler thinks that there is some possibility for undefined behaviour,  this piece of code, it will put in a function called to check if there's a lot.  So, things like shifting, lift, and end, wider than the size of an end.  And, oh, I can easily know that compile time, if that's true.  Or, you know, the other side, you know, the, that's not I mean, yeah, or using, or no point of reference.  It won't know, you can't tell, necessarily, it uses compile time, if this is undefined or not.  Or, although the compiler thinks that it can prove it is, it could potentially do quite bad things.  Luckily, maybe it's the, here's the micro UB saying, so that's just, this is the,  the very minimal implementation of the undefined behaviour sanitiser runtime.  It was imported last year into the next day, and then I decided, that looks quite good.  I will do the same in previous day.  And so, I did this, it was only in BSTKM last year, sort of Cambridge developer summit.  And, the only problem is that it does increase the size, so, we do leave it off by default.  It does make, it can all about 120 meg for the L file, for generic.  And, yeah, nothing BSTM would have this year.  So, you run it, and then you'll find this.  Yeah, this is, this is my memory access.  Yeah, no, you've been notified, no point in the reference is interesting.  This is actually going to try to find the offset of an item inside of struct.  So, it's the class null to a struct type, take the address of the field inside of structs.  This turns it to be undefined.  Use container of, or, have a similar, there was a, see, built, a, claim built in there.  I think, probably modern GCC will follow you in it.  And, yeah, the other one, the other one, you know, don't shift it 64, left by 64.  The compiler can do anything at that point.  And, you know, some, some, some, some, some compiler may just turn it into a instruction  that will only look at the normal bits of the, the size and shift it left by that much.  So, if it's out of bounds, at least it's too wide for that type, then,  when you look at the normal bits of it, and so I won't shift this at all.  And so, you, you could get unexpected results.  So, if you make 0 over here, you may not get it though.  So, this is good for just general code cleanliness.  If you're doing a modern capacity, you'll get lots of errors.  There's also warnings, I was just, what, you know, about that.  So, you may take a lot of effort to, you know, actually find ones you're interested in.  But then, there's a coverage synthesizer.  So, this is one that, that will insert interesting, you know, insert calls into the, into your code  on two points, you're interested in.  And then, we start basic blocks. So, you call into, you, inside the start of a function,  or inside an, of, of condition.  It will put in some code, and a function called in there.  And also, on comparison.  So, when, when you run your, if statement, it will put in a call.  It will also tell the compiler, as I said in the runtime,  a little bit more information about the, the comparison.  So, it will tell you what the two arguments are.  And it will also tell you the, the width of the, the comparison,  because it uses different functions depending on the width.  And whether or not you've got a, when the values is constant.  If both are constant, of course, it can optimize out, so you won't see this.  Luckily, all, all OpenDST and FreeDST and EBSD have, we've all committed, got a version of this.  And then, I think all, it all, it's been, and they implemented it.  So, easy tracing. This is tracing with basic blocks.  You get, what you do is you're allocating the buffer.  So, this, the top here is the buffer.  And then, the start, the first entry in the buffer, which entry is,  depending exactly on the, on the operating system, is going to be the size,  or the number of items, sorry, in the buffer.  This is the number of items that have valid ID, valid entry, so not the size of it.  Then, just a list of program counters, or what you would exactly want to call it.  So, address that's, an address of somewhere inside, probably the start and base block.  Where, so each of these is, FreeDST and EBSD, both put these 64-bit wide things.  So, it makes it nice and easy for the next one.  But, OpenBSDs use human pointer test, so 32-bit code will be, 32-bit, 64-bit code will be 64-bit.  This is, this is like K for tracing, you find out all of the values,  you don't necessarily find, no, why you're going here though.  And this is where you get, this is where comparison tracing comes in.  So, you'll get some number, so you still get the same count as the start,  except in this case it's number of four, four entry items.  So, the 348 there will be 348 by four entries by the range of entry.  This one, you'll get some more information, so you get this type here.  So, in the first example it's two, which basically means it's a size of, whatever size one means,  which is a defined thing as 16 by, 16-bit per person.  And the bottom bit is a const value, which means it's not const in this case,  so that means the two arguments where both come from the variable somewhere.  And then you'll get the PC as well.  This turns out to be quite useful in that you now know why you're getting there,  going there, rather than just where you're going.  So, you can then potentially feed, if you see data in one of these steps,  and then you can find it in your input file, or your input data,  you can potentially modify, try modifying the input data to be the same as the other argument.  You can try using that to find, you know, interesting paths through your code.  And this is the same thing.  I think BSD has your input point of T for each field,  which means I'm not sure how it does comparisons with 64-bit types.  I think it might just drop the top 32-bit architecture, which probably doesn't matter.  You know, it's unlikely to be used there, isn't it?  So, we can do this.  It's a simple way. All you have to know is you've got a dev cake off,  which is just a device that has in my layout, two interfaces that you can communicate with.  You have to see the buffer size first, just because the kernel needs to allocate nearly.  You can then map it.  An interesting thing is, you can trace, when you trace it, you don't have to be,  you just have to enable the tracing on the three that you're wanting to trace.  So, it's only the kernel part of the thread.  So, this is only going to trace a single thread as an interest kernel in returns.  It doesn't even have to be in the same process on three, at least.  You have to zero the first field just because you need to,  just because it will be disappear to there otherwise.  And then, do your operation and undo everything.  You can keep rerunning this if you feel like, and you'd have to keep closing it.  And this will become useful later when we talk about fuzzing,  because this means that you've got some sort of feedback about what paths you've got through the code,  what have you seen, and then you can then look at one,  you can then try to infer how you can get through the code later in new and more malicious ways.  But then, okay, so those are the two traces that covered the two synthesizers  that I've accessed in all the VSTs at the moment.  But then, so I've got these other ones, so A-SAN.  This is the most useful one for checking if you've got memory that's,  and making sure your memory is inbound, memory accesses.  So what it's doing is when you allocate memory,  or do some operations on the stack, it will have a piece of shadow memory,  so it's just a malocated memory somewhere else in a fixed area,  that it can say every 8-byte block of main memory of your KDA, or your connoisseur space,  we will allocate one byte of this shadow memory.  And then we can mark when we've got one, you know, we can say  whenever the memory is invalid, we've got a value, and we can 1-8 bytes of valid,  we can mark that, but the condition is that it has to be to form the first byte of the 8-byte block,  and it has to be on the 8-byte boundary.  So it can say no memory or any one of contiguous memory.  So I've got a picture to explain this.  So here we've got three bytes of valid, and then the trailing five bytes are all invalid.  And that's when the study, the top of the shadow memory, are all in-bites.  So this is saying if we say n is three, then three are valid, that's easy enough.  If we say n is zero, then we can have all of them, and this is just what the KDA is saying, I would expect.  And for other expressions, and if it's less than zero, it's then all invalid.  And maybe we can also have certain less than zero values that are marked.  This memory is invalid, but that's been previously allocated, for example,  or we can give it some information about why it's invalid.  The reason n is zero is because, and as the 8-byte is because when we do,  we have the option to build a compiler to insert these values, for example, with a stack.  So we have to make sure we stay compatible with that.  So that's what it does in some ways.  All allocations would now need to be to at least an 8-byte boundary, just like that's fine.  And then it's up to another 8-byte boundary.  So you can start another allocation within that boundary.  But of course, trading memory can be marked as invalid, and we should hopefully catch that.  And also, we should pay it out slightly more than just to the end of that ban,  because what happens if I get my pointer and I give it, I accidentally move on to the next one.  There's a limit to how much you want to, maybe you want to waste.  But we could probably have one more 8-byte blocks after this,  just to make sure that we don't accidentally go and weave it out of bounds.  It's also useful because pointers to, if you do go right up to the end of your 8-byte boundary,  you want to make sure there's at least another block that's invalid afterwards,  and pointers to arrays are allowed to be pointed at the end of the array.  So you don't want them to make some individual difference at the end of the array.  So I've got a wee example.  This is, if you're not used to fairly sees, allocator, as my knock, in the kernel,  just the end of the 10-byte, you can ignore it.  This means that's 10-byte values and is guaranteed to succeed,  or awake, or asleep, until with the cancer team.  So data is guaranteed to be long-long.  I've got some function gitdata, which takes a pointer and an argument,  and it's going to return the first item.  So hopefully this doesn't have a buffer overflow in it.  I don't think it does.  And gitdata may have specified that.  So we'll create this.  We start thing off, memory goes up.  So a lot of bottom is the lower address, the top is the higher address,  and across to the right is the only.  Oh, sorry.  So I've allocated four bytes, and so I change it from being on-stack to a heap of allocation.  We've allocated four bytes because I see an inside event, which is four.  We have to pair this up to eight bytes.  So we've got another four bytes to make sure that you don't accidentally  get just past the end of the way.  And then we'll put another eight bytes on the ingesting case,  because we always put eight bytes on the ingest to make sure that you don't go out,  you don't overflow.  That means the first four bytes there, blue,  data you can read and write to it without anything happening, basically.  And so if you accidentally try reading any of the other values in Google,  I'm sure there's one you that you're doing something that's silly.  So put into your allocation these values,  and it will say in the sharing map,  I have four, which means four bytes, and if it means invalid.  So that means we can load a store to 033 is fine,  and 4355 will be detected.  Anything past 15 I can say because that's outside of this allocation.  It could be the IP to make for something there,  it may be the end of the page, and so it's okay.  We don't know.  And so now we accidentally read from data one,  and everything should, and we'll get that,  or 20 of the venue and exactly your implementation.  So this code, Google as a,  NebisData has a version of the implementation of this,  and I have a student who will be working on this in the sum of code.  I have an initial patch that doesn't quite do everything to explain,  but it should at least get the students started.  There's a lot of us finding the allocation we've got,  which is horrible in the code,  trying to find the real-ear, which we may allocate mainly.  So this is something which, then Google came out with  a something interesting, a saying, the implementation,  which is a hardware-assisted version.  This is ARM64 specific, because it uses a patron ARM64  code top-byte ignore, which basically means it will ignore,  you can put any value you want into the top 8 bits of your,  of your points of your address that you're loading or storing through,  and you'll just ignore it and pretend it's,  it'll look at it, it looks at the bit 55, I think, of the address,  and it extends that up.  So it doesn't matter what you put in there,  or you don't, the handiness of the value.  So they say, well, what if we put a tag in there?  And, you know, we've got two 15, six bits,  two, two, six possible values.  We could put more, we'll reserve a tag for an allocated memory.  So we've got two 55 possible 8 bit bytes,  two possible values we could have there.  And then we'll just store the tag.  We've got some way of allocating the shell space.  We'll just store the tag there,  two, four, that piece of valid memory.  And so if we, now, if we come, we do a load of store.  We check the tag, you can check the tag against the byte,  the shell space, just to make sure that it's valid.  So this does mean you, the previous one,  you may, you're only just getting at bounds.  This one, you may get a few other things,  and it's a few different issues,  find three different issues like,  if you allocate three, allocate,  you'll get use after we allocate,  would hopefully be treated, be detected.  So what does it do here?  So we start off, no allocations,  we make some allocations.  So we've got a low allocation,  and then we have two more.  And then we try to load from address three.  And because, but with a pointer from a blue pointer,  so we've worked for one and two,  that will not work through.  So basically, it's, this is a slightly different way of doing it,  rather than saying,  rather than saying this byte, this is valid.  We can say this is valid, but only with this pointer,  which previously we couldn't detect this sort of thing.  Because if we moved, accidentally moved from an allocation,  the blue allocation to the gray,  we would see just, well, we've still got valid memory.  They also do a few more things,  so they make it slightly more, slightly wider,  because they want to be found on phones.  This is a Google thing.  So everything's 16 bytes and undecided.  And you're not able to detect slightly out of bounds issues.  Because the tag is per 16 bytes,  you can't say if you're just,  if you're still within a 16 byte, like,  and you can't detect that.  Yeah, so you've got a, and you've got problem elastic.  This is, you sort of hope it.  And there is now an MV 8.5,  I mean, tagging extensions, which are similar to this,  which with a small tag.  But this, I mean, that's okay.  It's useful for finding issues as well, I think.  Not, slightly from classes of issues.  But then, well, we've got this,  this is the project we've gone on, where we have this,  we've decided, well, once we take pointers  and double the size of them,  but then code some bands and permissions on the top bits,  and make sure that they're non-forgeable.  So you can't just get one from anywhere.  And you have to derive them from other capabilities.  So you can't just take one,  and then try to expand it toward a memory.  This should also be, you can consider this to be similar to a sanitizer.  With your ABO, back all pointers, these capabilities.  But come along tomorrow morning,  I have to send two ebooks to tell you about this.  I'm not going to go too much into this.  So we should be able to, we will be able to get  slightly out of bounds, if you point at,  so we'll be able to get pointers that are slightly out of bounds,  like K.A. saying.  But we don't get the tags, things,  but we don't get tagging, work, and doing with the hardware  to your sanitizer.  So you still get, potentially, the use after free.  And there's a possible, there's research going on about  no bounds, even more, so we can say,  can you detect out of bounds accesses within the struct?  Have you gotten the right, for example,  you want to make sure that you don't,  or another struct, within the struct,  you don't want to make sure you don't accidentally go out of data  and into the parent and do things that may not,  ACN may not be good at finding.  And then, okay, so this is all about address space.  That was finding bounds and things.  But the thing is, there's also the memory sanitizer.  So this one is saying, I've got,  I've got these in the memory.  I've advocated that, and I've advocated that,  but it's just, it could be random data in there.  We want to make sure that you have at least written to the data  before you try to read it.  And, or you're initialised before you're using it.  But, so use here is decided as you're using it for conditional.  You're using it for, as I pointed to, dereference.  Or you're copying it to user space.  So the last one's important for finding,  you're accidentally leaking some memory from,  it's a kernel stack, say,  or an unmercialised part of a struct into user space,  which seems to be reasonably common,  the thing that people have done.  So, my example, we've got an int a,  we haven't initialised that at this point.  We've got int b, that's not a use,  because it's not a good initial,  it's not pointed to a different point of view reference,  and we haven't yet copied the data to user space.  When we do this copy yet, this is definitely a use theme,  because we want to make sure that this is now our stack,  we now have the king stack information to user space.  So it's definitely an initialised use at that point.  This is, turns out to not be.  We've got an integer, which we haven't initialised.  We see that only if the flag is set,  some flag that was being passed in.  If, and then we use it,  well, we think it looks like it's used, but it's not.  It's gone to propagate the fact that it has initialised to see.  Then if the flag is set, or if the flag is set, then we use it.  And because it's impossible,  you can only get into the second case,  if you've got into the first case.  That flag, this is not going to be an initialised use.  So you can probably,  probably don't write this code, please, don't.  You probably have something else in the middle though,  and you can probably should warn you,  but it's possible this sort of thing happens by accident.  So you won't detect this sort of issue  because it's not defined as a use in the same case.  Other ones, if you're allocating some memory,  you're doing de-referencing it.  And the point of de-reference is not an initialised use.  You also have the point of comparison, so.  Now, because in this case, I have also,  I don't think we mean me in the scene,  it's okay to wait.  So that's definitely not going to be a no point of de-reference,  but it might be, but it's not initialised either.  So this also, you know, these tend to use a show-down map,  and it's one bit provide,  so basically saying if the show-down map of this,  so when we translate from between the two,  so your caveat, you can already read the show-down map.  If it's a set, it's poisoned,  and so you can't use it, you can't read it.  You will need to do things like you're poisoned by the fault.  Mark will un-poison memory,  so make sure you make it readable.  If you set it in zero, which means zero memory, please.  And writing constant days into it, one poison.  Writing non-constant data will have to,  it's been, you know, with this case,  writing the state of world will propagate it back.  So if flag is un-sets,  it will still be the memory, see if it will be poisoned,  and if flag is set, see if it will be un-poisoned.  So knowing the commuted K,  you can see how that can tell.  But NBSD has got the K leak,  which is a similar concept,  and that it will find the similar sized memory.  But it uses, so K, A-SAN, K-N-SAN  use out-of-bounds signaling,  so they have another piece of memory,  which has a mapping between,  some kind of maps between your main,  your critical visual space and other bits of memory,  whereas K leak has used a demand signaling,  so on Mark, we'll just write all the memory out.  We'll write with a known value,  that's one byte value, to all the memory.  And then when you do your copy out,  we'll check, has any of this memory  copying out containing that known value?  If it does, then it's warned that there's a potential  kernel disclosure going on.  So that could be, you can have some false positives,  and that would be obviously,  because you made that value,  you made the chip that they be in the memory.  Now, there's a paper behind this,  and they do explain how they chose this byte.  It does change over time,  from a pool of bytes where they found  these ones were less likely to be used to be copied out.  So there's certain values which are extremely likely,  so if you use one of the unlikely ones,  you're going to minimize false positives.  You could.  The other one is, it uses the coverage sanitizer type  system to poison the stack,  so every time you enter a basic block,  it will just write it out,  over it's need and pass the end of the stack.  So that when you return from that,  if you return from there and go into another function,  but don't initialize something on the stack,  it will, you'll detect it.  So you, I think you could probably,  it's been important to figure out,  and they have been some vulnerabilities,  or some memory issues reported in FACTS.  I don't know if we want to import it though,  I don't think we do,  because I like the Emsen, the Clemsen Ruby.  We do it.  And lastly, there's the, a threading sanitizer,  so that's what this,  I don't know anything about this one,  so I'm just putting it up here for completeness.  There was a kind of version of the threading sanitizer,  it may not be on hold,  I couldn't really tell from my Google,  Google aim, whether it's coming to being worked on.  But it's just there to find databases.  If anyone does find out that you know anything about this,  I'm happy to, I'd like to know,  because I'd like to know if it's something  we should be looking at.  But, okay, so we've got some sanitizers,  but why, why do we want them?  Well, the obvious one,  is it makes, making bags easy to find,  and hopefully fix, is good.  I want to go to known,  I'm doing something stupid,  and make it easy to find, I'm doing something stupid.  A pick off is good, it helps fuzzing.  It means that we can find more bags,  and hopefully, hopefully fix them.  And they also, it makes it easier,  and it makes it easier,  and having the right parts of K-Corp makes,  and the other sanitizers,  makes fuzzing bags easier to find.  So, we can find, you know,  3D-ST has, for example,  has tools to find use after free issues.  The problem is, the point at which you find out  there was a use after free,  is when you try to allocate the next,  and there is, and you just happen to allocate,  be allocating some memory that was previously written to,  after being free.  Which may, you know, that's okay,  that's a good thing to know,  but I would like to know when that happens.  I don't want to know that I've got to use after free,  and sometime in the past.  I want to know, I've got to use after free now,  so I know exactly what needs to come out to look at, in fact.  But, yeah, so, that's really why I want the sanitizers,  to make sure I know exactly when the code,  I've got some code I'm looking at,  I know that Scottie has to have the issue,  I want to know exactly where it is.  So, yeah, Fiskir, there's no, there's a system called Fuzzer,  Google's page, well, other people will go down as well.  It's written in Go.  It supports free VST and open VST.  It's very good at finding panics in the kernel.  It will use, so it uses the coverage sanitizer to say,  you give it, you know you have to find,  it gives it some system calls, and it will use coverage sanitizers  to say actually where it's gone.  So, that's the main reason I wanted to take off, was for this.  So, you can keep some of the thoughts out of this.  So, this was the most recent issue that has happened.  So, since Boston is the Google,  it's just kind of running on Google's infrastructure.  So, they've got a single instance,  or sorry, single machine type, I'm not sure any instances they have of this.  And then they found these bugs in this one, the bottom,  which you can't really see because I didn't zoom enough.  So, if you know anything about any of these,  you might want to have a look at this.  Some of them, so some of these, when you see these we've got,  it means that it's got a reproducer, but since it's kind of forming it,  some of them are also, it can generate C reproducers,  if you want to try running on your local infrastructure.  Okay, so we've got one type of machine, one instance type running.  If we had the sanitizers,  we may be able to get, this is the Linux example,  and how many of them, they've got a few different types.  Well, most of these are always San E,  but they can, Google can then run and find issues.  They can find the use after free issues easily  because they've got K-San running,  and they can find other things,  when you may be releasing,  and you can use the space because they've got versions with K-San running.  It'd be nice if we could have these and then we could run a lot more  and find even more bugs.  So, yeah, what, how's this going to work?  Well, they all try to, so what it does is it runs different system calls.  It understands arguments.  So it understands that this function,  this system call will return, return a function point,  return a file descriptor.  It will then try to pass that file descriptor  and something that takes a file descriptor.  There may not be something that naturally goes together,  you shouldn't probably, you know, you wouldn't write it this way,  but we'll still do it because you could,  because it's a file descriptor,  it doesn't know anything more than that.  And it turns out that's a good way of finding big bugs  when you're passing something you really, you'll be expecting.  You know, like I said, it's good to find panics,  and it will find new producers for you if you wait long enough,  and hope.  And it says, it makes it easy.  And yeah, so this is the example.  This one here, we've got two new producers,  so this one does actually have a senior producer.  It will give you information,  it will tell you the kernel panics and here's the trace.  This just comes out previously, but for anyway,  it just understands enough about this to print it to the recorder,  and I think this one, yeah, this one,  this is from a fixed user item issue,  so I think Matt Johnson might have fixed this one.  I can't remember.  And he's found this one a few times.  Yeah, I found this one five times,  but it got in here five different ways.  Join these mailing lists.  They will tell you, they'll run it on their infrastructure,  email it every time they see that issue.  When people fix things, if you tag it,  they'll tell you, put this reported by this address  in the commit message, and it'll know,  and it'll then check take it and say,  oh, it must be fixed, and then check,  make sure it's everything.  And so, yeah, I can find the list of people interested.  You get my emails fairly regularly about  satisfying the new issue.  The other one is, has anyone not heard of AFL?  So it's a similar puzzle.  It's a file format, it takes a file,  modifies it, tries sending it.  So it's really good things to do causing.  For example, file system.  It does this, you can look at this.  It will take a hash of old pointer,  and it will then send a new pointer.  So basically, it wants a hash of some data,  and then it will increment the value of the pointer  in a buffer.  So it can then say, I tried loading this thing,  I got this hash at this map out,  I read from here to here.  It's not exactly this, I think there's,  I think there's some shifting in the input as well,  but you get the idea.  So you're finding edges in your code,  so places where you've gone from one place to another.  So I didn't experiment with the patch to talk.  So to get K-Cov to output this format,  and for AFL to consume it,  yeah, takes a long time.  If anyone has any ideas on improving the performance,  I can do about 30, I can mount it,  it was creating an MD image,  mounting, unmounting,  killing or removing the MD image,  about 30 mounts a second,  which I think I calculated as 12 days,  of just bit flips,  because it will go through it so the way it works  starts off just by bit flipping everything.  So if anyone's got any ideas on how to improve  the performance of this, I'd like to know.  Hello, I'm Convin.  Sanitizers, yeah, everyone's got,  all three of the main VSCs have K-Cov and K-UVC,  which is good.  Nuby says K-A-C-N, and I can VSC,  I suggest you have a look at this,  and I used to think about it.  We don't know anyone who's using the other sanitizers,  well, Cherries did not sanitize,  but no one else has the other ones,  and they make bugs easy to find.  And if you do this, Google your stuff,  trying to break it on the infrastructure,  and please look through these.  It would be nice, there are people looking at them,  but it would be nice if you've got  some of the expertise in one part of the code,  to look at this, just even if it's a period of time  looking at it, to make sure there's nothing  that you might understand.  In our document, you might have got any ideas  on making a file fast, you know,  to give me a help with.  Maybe putting, getting rid of the file system  and use this as a space for something, I don't know.  Any questions?  So AFL can use a corpus,  and I'm curious to know what was in your 128-kilobyte corpus.  Have you tried it with file systems  that were damaged in some way,  or did you just start from an empty mount point?  The question is, if you're taking corpus,  and you want to know what was in it?  Mine, I started with a valid file system image.  The one of the issues I found was actually,  we previously recently got checksum in support as it,  which makes it more AFL isn't really good,  very good at getting past checksums,  because it now has to do a bit flip  and modify the checksum to get past the checksum code,  which I tried to save a little bit,  and that didn't still take a long time.  So I'm wondering if you maybe better tools there,  a custom plaza would know that understands,  you've modified this piece of memory,  and now I'm seeing this other condition in failing,  which wasn't failing before.  Maybe I should look at that to say,  what comparisons were there?  Can I find one of those values in my corpus,  change, modify, addix,  their value to be the other value?  Is it possible way of getting past checksum and checks?  So, let's have a question or a comment,  but it seems like this is a really good start  to sanitize or run times and that kind of stuff  inside of the kernel.  I'm wondering if there's any interest to,  since NetBSD and now OpenBSD are also interested  in that kernel sanitizer on time,  if there's any interest in sharing code bases  and collaborating on that,  one thing that I'd like to do is to implement a runtime  that supports CFI in SafeStack in the kernel.  So, there's no comment on sharing code bases.  And, well, so, we do share the undefined behavior  sanitize code base, because that's all based on,  as far as I know, it's all based on the NetBSD micro-UBSAN code,  which also works, at least on NetBSD,  and it works in the user space as well.  K, cov, I think, are three completely independent implementations.  That's partly because that part of the code,  I'm not sure how similar the code to talk to,  to be on the kernel side of a device,  is between the three BSDs.  So, I suspect, K, NSAN, K, DemSAN,  we could teach this year something there.  A lot of it's just accounting.  Yeah.  And I haven't thought about CFI things in kernel yet.  We need to teach CTF Convert the LLVM IRF code on that.  So, yeah, comments about teaching, anyone who doesn't teach CTF Convert  that LLVM the code for it.  Talk to Sean.  Yeah, let's get that.  That's great.  Is there a point?  I didn't exactly understand how the fuzzing and the coverage pieces work together.  Are you choosing fuzz targets based on places that have low coverage,  or could you...  The way the question is about how do they fit together.  So, you don't need...  There are two independent pieces of things,  and you don't need one for the other,  but they complement each other in that  sanitizers make your bugs...  If you manage to craft some input to the kernel,  which hits a bug, which the sanitizer will trigger.  So, if you've managed to send to run a system call,  or a series of system calls,  which causes something to... a buffer overflow to happen,  that may not be detected at the moment,  because which could be a buffer overflow,  it may just be read in memory,  and it's within the page.  The sanitizers will make that a panic.  The fuzzers are really good at finding,  because they look at the code paths through your...  that you've got.  They're good at finding those issues.  And then they will look at the...  It will take to say, I've found this code path,  now I've modified, I've got some information about that.  I'm going to now try modifying my inputs slightly,  and try and see if I get another code path.  The modified input slightly, try another code path.  So, it's more about...  They're good at trying to find these sorts of issues.  And the sanitizer is really good at detecting  when you have that one.  Without the sanitizer, you'll still...  You'll still do this,  but just won't detect it as easily.  So, the idea is, I want sanitizers there  just to make the...  When you do get the issue,  to make it easy to detect.  Is that all the questions?  Okay.  Thank you.  Thank you.  Thank you.
Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_0_107.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_108_203.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_204_311.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_312_563.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_564_1103.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_1104_1259.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_1260_3719.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_3720_4127.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_4128_6767.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_6768_9167.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_9168_9311.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_9312_11339.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_11340_13247.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_13248_15947.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_15948_18167.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_18168_18479.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_18480_20423.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_20424_22331.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_22332_24287.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_24288_25439.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_25440_25499.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_25500_25847.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_25848_25943.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_25944_26027.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_26028_26087.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_26088_26219.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_26220_27059.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_27060_27131.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_27132_27563.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_27564_28211.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_28212_28487.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_28488_28535.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_28536_28583.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_28584_29303.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_29304_32171.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_32172_33383.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_33384_34835.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_34836_35975.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_35976_37463.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_37464_37667.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_37668_37715.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_37716_37847.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_37848_39203.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_39204_40103.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_40104_41615.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_41616_42743.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_42744_44039.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_44040_44603.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_44604_44675.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_44676_48671.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_48672_48779.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_48780_49559.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_49560_49799.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_49800_52583.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_52584_53771.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_55524_56495.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_56496_58223.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_59520_60599.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_60600_62687.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_62688_63767.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_63768_63863.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_63864_64631.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_64632_65699.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_65700_75191.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_75192_75323.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_75324_75371.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_75372_75443.png Fuzzing_the_kernel_Porting_the_Clang_Sanitizers_to_FreeBSD_1tYtT8Jk21c_75444_75448.png