Good morning, everybody. I want to make sure that we get some decent questions here. So I have a little bit of an incentive. Yeah, I have a raspberry pie. It's a two, or three, or something. I don't know. I've never used it. That's why I'm giving it away. In great fine. Yeah, nobody gets it then. No, best question gets the raspberry pie. And that includes the questions asked while other people are actually presenting. So we've got 90 minutes. The only reason why I'm doing this is because I've never had the opportunity to speak uninterrupted for 90 minutes before. I hope you'll ask questions as they come to you because we've got a lot of information to cover. It's not the simplest situation in the world. So feel free to interrupt, and we won't cover everything, but we'll try to get you sufficiently intrigued that you'll want to go off and make the world better for security. So he said, making sure that his finished thing is working. It helps if you plug in the dongle. This time, for sure. Nothing up my sleeve. Presto. So why do you want to write a Linux security module? I mean, we've got great ones already. We've got SMAC, NSE Linux, and App Armor, and Tomoyo, and Yama, Loadpin, Safe Set SID. We've got a couple more that are coming down the pike. And so really, why would you want to do it? And of course, writing a kernel code is hard. You have to deal with all those community people. So there are times when a Linux security module is actually the easiest way to accomplish the things that you want to do. OK, I just want to let everybody know that that is annoying me as much as it's annoying you, the bandsaw in the next room. All right, so when is a Linux security module the right choice? I hear you cry. If you want to add access control decisions and access control restrictions to your existing system, that's what a Linux security module is for. And you want to do it to things that are controlled by the kernel, things like files and processes, system 5.IPC objects, socket delivery. And if you want to do mandatory access control, this is about the only place you can do it, because it's the only place where we actually have all the information about all of the things you might want to deal with. So one of the most important things to realize about security modules is that they implement restrictive controls. So the traditional controls are still done. You still have to pass the mode bit checks. If you have access control lists, you still have to pass those. But you can base your access control checks on any of that information. So the UID checks are based. Capability checks are still done. If there are other LSMs, you may have to wait and see that their checks are done. And you can't override a denial. So you cannot write an LSM that says, I know that any user ID that's an odd number is OK. So in spite of the fact that that user ID wouldn't have access to a file, go ahead and let it happen anyway. You can't do that with an LSM. LSMs are restrictive checks. So when is a Linux security module the wrong choice? If you want to change the access control restrictions of the system, you can't do that with an LSM. The best example of this are POSIX access control lists, which you cannot implement as an LSM because they actually change the behavior of the mode bits. So if you tried to do access control lists as an LSM, you would discover that there were denials coming and you weren't expecting. Because they'd get to the mode bits, the mode bits would say, no, you can't do that. And then you get to the access control list, which would have granted you access. And you will never have gotten there. The other thing is readily done in user space. How many of you remember D-Bus? Remember K-D-Bus, excuse me. K-D-Bus. OK, yeah, there's a smattering of people over here. You don't do K-D-Bus in the kernel because it's readily done in user space. It's a lot easier to do things that you can do in user space, typically, in user space. And there are a lot of other advantages to doing them in user space. So if you can readily do it in user space, if it's the kind of thing that you would do in user space, don't try to put it in the kernel. So what are the alternatives? Now, there are a lot of security mechanisms, believe it or not, in the Linux kernel. Some people even say there might be too many. Sometimes you run into conflicts. So one of the alternatives is special purpose file systems. If you want to encrypt your files, you don't do that in an LSM. You write a put it into your file system code, or you have a file system, eCrypt FS that sits on top of everybody else, or you do it in the block layer. You just don't do it in an LSM. We also have these cool things called namespaces, which offer a variety of ways to do separation. So you can have processes that are isolated from each other. And because there are enough people talking about containers and other things, we won't go into that too deeply. But that's one of the alternatives. You can do network namespaces. You can do file system namespaces. You can do username spaces. There's all kinds of good stuff you can do with that. We also have a mechanism called seccomp. And if what you want to do is stuff that is oriented towards system calls, seccomp is the way to go. And if you want to do bizarre and unnatural things with seccomp that it doesn't already do, and there are a few, that would be a place to enhance if you want to do it at the system called granularity, because that's where it's oriented. If you want to do packet filtering, we have net filter, whereby packet comes in the system. You can do virtually anything you want to it under virtually any circumstances. It's really magic. And then we have BPF and EBPF, which are brand new. And I don't really understand as well as I ought to. But they're new and cool and magical thingies that you can use in some circumstances in order to do things that are oriented towards small programs embedded in the kernel. So security module don'ts. And I apologize profusely that the picture is missing. I couldn't find a really good picture for this. So you don't want to duplicate an existing security module. We do have several. Again, we have generic Mac systems. We have three generic Mac systems. We have SE Linux, which is granular. We have SMAC, which is simpler. And we have App Armor, which is oriented more toward usability than it is toward objects and subjects and provable correctness. Did that sound about right? OK, sure, whatever. That's the nice thing about John is he's amenable to just about saying just about anything. Another thing you want to be really careful with if you're going to do a security module is don't count on a user mode helper. Really, if you're going to make a security decision, think about how many of those you can make in a second. If you're going to make a security decision, you're going to call up to a helper and say, hey, a helper, what should I do? And the helper's got a gigabyte database. It's going boom. It's going here. I know how to make my decisions based on all this learned data that I've accumulated over the past 10 years. And I'm going to think about it for about 10 seconds and say yes. Your system is going to come to a screeching halt, and you're going to have all kinds of locking issues, and nobody's going to love you. So don't put a whole lot of faith in user space helpers. We've seen several things suggested that do that. And they all have this problem where they end up getting locked as soon as the second process starts. The other thing is don't inflame the community. And there are lots of good ways to do that. It's actually pretty easy.  Wacky things don't get a lot of good coverage. Wacky things tend to get a lot of derisive response. Good example. Somebody recently proposed a security module that would do nothing but look at the path names. And if there was a space in the path name, reject it. Actually, very, very useful. But a lot of the people in the community thought that this, because this violated POSIX semantics and other trivial things, that this was probably not a good idea. So when you're going to propose something, you make sure that it makes a modicum of sense, not just for your particular use case, but in general. So that said, let's talk about designing your security module. Because really, it kind of makes sense to do that. I know that in a lot of fields in software development these days, we don't design things. We just throw stuff onto the disk. And if we like it two weeks afterwards, then we try to publish it, put it out on GitHub. But it really does make sense when you're dealing with security to design what it is you want it to accomplish. So the first thing you have to figure out is, what do you want to protect? Kind of an obvious thing, but what matters? Do you want to protect objects on the file system? Do you want to restrict path names like this one LSM proposed doing? Do you want to protect the interaction between processes? Do you want to protect what a individual process can and can't do under circumstances? Do you want to do things like keep track of the number of times a program accesses the number of things in Etsy? And if it looks at things in Etsy more than twice, then you say, yeah, no, I don't trust this program anymore. Do you want to trust hunks of data? This is getting to be more interesting as we start having things like Intel's SGX, where the data that you're putting into what they call an enclave is a program, but you might want to actually say things about what circumstances you want to be in force when you allow a program to do that. And then there are just basic resources, like the clock. Do I want to protect the clock? There are some cases where the current permissions on the clock just aren't adequate. So you might want to do things on resources or other system resources, memory pages, things like that. And then what do you want to protect it from? This is kind of an interesting point, because you might say, I want ultimate file security. And it's like, OK, we'll put ultimate file security in place, but who are you protecting it from? Well, do you want to protect it from people?  Or the other thing we're seeing these days, and believe me, when I started out in the computer industry, we never even thought about this, not till Mr. Morris put his worm out, which is that applications themselves can be written to be malicious. It's like it's not some person doing this. There's nobody sitting out there driving this, but this bit of code, regardless of where it came from, is going to do bad things to your system. And we also have, believe it or not, one or two applications out there in the environment today that are badly written. I won't say no JS, but some of the things that are included in there are actually not especially well done. And this isn't news, I wouldn't think.   The other thing you might want to think about is network access. What is networking and the behavior of packets coming in and going out of your system mean for the things you want to protect? The nice thing about network packets is that they don't have any attribute information associated with them usually. So you don't know who they came from or who they're going to. They're just blobby things. So how do you want to protect against that or do you? So given that, now I'm going to shift gears. And this will happen throughout the talk, because my coherency editor was off this week. And that is, well, we know what we want to protect. We know what we want to protect it from. What do we have to do to protect? How do we actually go about do that? Well, we have two elements that we use for protecting things. Hooks and blobs. A hook is the bits of code that you implement. For a particular place in the kernel, and it's going around doing some usually access control checks for other things, but sometimes not, we'll call a security hook. And this is a bit of code that will take some set of information and then make a decision, in addition to what the rest of the kernel is doing, and say, yeah, you can do this or no, you can't. And they're sprinkled about the system in a well thought out and structured way. So my example here is with inode permission. If you want to check and see whether a process has access to a particular inode, it calls security inode permission. And because you have a security module registered in here, which we'll call sample, the sample LSM, it will call sample inode permission, which we'll then look at the security blob, which in this case is inode I security and say, then your security module will use that information combined with the fact that it's that hook and say, I'm going to make this decision this way, yes or no. You can also use any of the other inode information, by the way, in this case. You could use user IDs, group IDs, anything else that's in the inode to decide whether to make the X control check as well. But this is the basic model here. You've got a hook, which is your bit of code. You've got the security blob, which is the information that you're maintaining about that. And again, you can put just about anything you want in there. So the first kind of hooks that are really important are access control hooks. These are the hooks we actually make decisions. Generally, these are passed as pass relevant security pointers, which will have blobs hung off of them. Usually they're in the current context, not, of course, always, because that would be too easy. So you don't have to have, yeah, yeah, Steven's laughing at me, and that's just fine. Usually, well, OK, so you don't have to use all the LSM hooks. You only have to supply those that actually are relevant to what you're trying to accomplish. So if you're not looking at file system objects, if you're only looking at network packets, for example, you don't have to use any of the inode hooks. If you're only looking at file system objects, you don't have to use any of the networking hooks. If you're only looking at system 5IPC, you don't need networking hooks. Or inode hooks, you just need the ones that are relative to system 5IPC. So you just need the hooks that you actually need. You don't need to supply any of the others. The system is just fine if you have a limited number. And then they return the access decision. So if you decide that, well, if, for example, your hook needs to allocate memory for some reason, and it fails, you return returns to that. Or you might say, yes, I like this. Return E-axis. I don't like a return access. Yes, I do return 0. So the hooks are bail on fail, which means that if you have a list of hooks, and they're kept in a list, the first error that's encountered is returned. So just as the discretionary access control, the normal DAC checks are made first. If they fail, then you never get called, because it's already known that access is going to be denied. If there's another security module ahead of you that's actually also making a check on that, and it fails, you don't get called. But if everybody else ahead of you succeeds, then you get called. You say, yay, it's my turn. And then you can say, I approve of this action, or I don't, and everybody's happy there. And then it goes on to the next one, if there is a next one. So you have to be careful with the state engine, because you have to realize that it's entirely possible that you won't get called, even though you're at the point. I know permission gets called. Your security module may never get called, because something may be denied ahead of you in the list. So it's just a matter of state engines need to be aware of that. We also have state maintenance hooks. And these are used to keep the security blobs and other security and other state consistent. So for example, when a file is out, is opened the first time, and I know it is allocated, a hook is called so that the security module can allocate its blob or initialize it in the modern case. Sometimes calls are made. For example, if you exec a program, you're going to have to change the credential. Or you may have to change the credential, in which case you need to do some maintenance on the credential. Also, when an Inode goes away, you need to tear down or free the information that's available there. And we also have hooks for mapping between security contexts and security IDs, which I'll talk about in a later slide, which is in the wrong order. So access control can return values. In general, these are the only four values that they should return. There are exceptions. But on the whole, they should either return 0 if they're happy and they want to allow the access. Enomem is one of those veins of the C runtime environment where you have to allocate memory explicitly, and you can't be guaranteed that it will succeed. Eaccess says, no, I don't want you to do this. And ePerm is, you needed to have privilege to do this, and you didn't. People often get Eaccess and ePerm confused, but it's actually pretty simple. I am denying you access based on my policy. ePerm is, no one should be able to do that. Why did you ask to do that? Oh, and you didn't have Capsis admin. OK, that's the distinction there. Security blobs. Let's talk some about security blobs. A security blob is just a chunk of information. The kernel outside of your security module doesn't care about what's in the blob. You care about what's in the blob. You can put essentially anything you want in a blob. So they're referenced by kernel data structures. OK, so that's on the next slide. They're managed by the infrastructure mostly. Not all of them are managed by the infrastructure, but we're getting pretty close to that. And so what that means is the infrastructure will allocate it, tell you where it is, and you can then manipulate it as you like. There are a few cases where the modules are actually required to do the allocation and freeing of these explicitly. We're in a transition state where we used to do it all where the modules did all the allocation of blobs, but now we're making it so the infrastructure does it so you can have more than one module at a time. As of 5.3, the infrastructure managed ones are actually most of them. And the ones that are module managed are ones that we haven't actually hit a conflict on yet, but we will be soon. Most of what you'll be doing with most security modules are on the infrastructure managed ones. So you should actually be pretty happy there. OK, and as I said, the infrastructure managed blobs are allocated and freed by the infrastructure, so you don't have to worry about it. If you have a linked list inside your security blob, yeah, you're going to have to manage that yourself. When you set up your security module, when you register it with the system, you're going to tell it how much space you need for each of your blobs. And then when you register, it's going to tell you where the offset is in the blob. So that's a little bit of detail on that. When you want to, and we said we were going to tell you how to write a security module here. We're not going to hit every detail, we're going to hit some of them pretty hard. So, module details. When you want to define an LSM, you have to tell it a few things. You have to tell everybody its name. Here we're calling it sample. You have to tell it where your blob sizes are, and so we have a structure for that. And you have to say the name of the function that you're going to use to initialize it so you can register it all. The flags, in a lot of cases you won't need any of them. But the two flags we have are legacy major, which means that on the boot line, if you say security equals this security module, you'll get that one and none of the other legacy major modules. And if you say exclusive, that means that you're using security blobs that are not infrastructure managed. And so you can't run two of those at once. So only the first one of those that's registered is going to get used. As we go further into this stacking notion, that becomes less important. But for now, that's how you make sure that you don't conflict with anybody. So when you want to set the blob sizes, we have a structure here. It's called, believe it or not, LSM blob sizes. And you tell it for each of the blobs you use, how much space you want. And then when you register your module, it will keep track of all the modules that are allocating blobs and say, all right, you get this much. And then it refills this structure with the offsets. So you say, I want 45 bytes. Bad number. I want 48 bytes. And at the end of registration, it'll put in here the offset of your 48 bytes in the blob that's off of that particular kernel data structure. Often this will be 0, which is great, because that means you're the only one there probably. So we're going to talk a little bit now about the blob, the sec ID, and the sec context. Again, we're hitting the detail here. I didn't promise coherency. With the blob, security blob is just this chunk of data that you've got. So conceptually, you should be able to access that. You should be able to reference it. So we have two ways to reference it. The first one is the sec context. The context is actually a name, a character string, that your module uses to reference that particular set of data. Now, the sec ID is a 32-bit number, which references the same data. But that's kept completely inside the kernel. That is never exported. There's one per sec context, and they're valid. So you don't put that out on the disk and reboot the system and expect that to be meaningful. If you're going to actually, the sec context is the thing that is actually the data. And then the blob itself can have whatever you want linked lists off into iNode tables, whatever. OK. So the lifecycle management of the sec context is kind of important, because these are strings. They show up in auto records. Probably the best example for them. When you send one out, if you have a sec context, a sec ID or a sec ID to sec context, or any of the LSM hooks that generates a sec context, that puts a string out into the rest of the kernel code. So the audit system says, oh, I have a sec ID, which I got from the iNode of something. So I've got that, and now I'm going to convert it to a string so I can print it out. And then when I've got that, well, what do I do with it? Well, then I release it. And you do have to do a release, because the different LSMs treat the allocation of these things differently. SC Linux, for example, will always generate a new text string and pass you a pointer to it for a sec context. SMAC always has all of its label names in memory, so it doesn't do that. It simply returns you the pointer to it. It says, here's the string you're going to use. So when you release an SC Linux context, it does a k-free. When you release a SMAC context, it says, yep, did that, because there's nothing to release. So it's important to note that callers will always use security release context, or people who try to do it otherwise get harangued rather nationally by people like me, because then LSMs start breaking. So process attributes. Processes have attributes. Everybody figured that one out? OK, good. Most important process attributes are credentials. Now, credential is a shared thing. So a number of processes, a number of tasks, will actually point to the same credential. This is done for a number of reasons. They're copy on write, so if the user ID changes on a process, then you're just going to get a new credential. If the SMAC label changes, it's going to get a new credential. If the SC Linux context changes, it's going to get a new credential. So there's quite a number of things you have to do here to manage a credential. But it's actually fairly straightforward. You just have to realize that it's not that every process has its own credential. This is where the cred security is actually where the information that you're going to add to LSM is going to live. That's where your security blob is going to be. And current cred security is actually used in a lot of cases, because a lot of these, again, a lot of the hooks are done in the current context. The important thing here is that the cred blob has to be prepared when it gets duplicated, has to be set when it's duplicated. And that happens in places other than within your LSM.  So a task, we also have a security blob on tasks, which are different from credentials in that they're actually information about this task. And so you're not sharing that. So you can have two tasks with the same credential that have the same credential blob. They will have different task blobs. And again, these are both infrastructure managed credential blobs. So you don't have to allocate them or deallocate them. So if you want to see any of these things, if you're outside the kernel and you say, I would like very much to know what my credential blob, what my security context of my process is, we actually have interfaces in proc, in slash proc. The adder subdirectory, or the adder subdirectory, actually contains information about your process. Current is used by SC Linux, App Armor, and SMAC today. And it will tell you one of the three, which of the three depends on which one is actually first in the stack. And that's kind of a problem. So moving forward, we have a mechanism we're adding subdirectories in adder. SMAC is the first adopter on that. App Armor is actually moving away from slash proc to sysfs, is that correct? No, OK. He'll tell you about moving away from. OK, they're doing a subdirectory too. So if you're writing in LSM, the important message here, if you're writing in LSM, use a subdirectory. The mechanisms, oh, I see a question. Yay! OK, we can now have a best question by definition. OK, so the question is, is proc adder only used by LSMs? And I believe it is. And if you want to write a new LSM to present something new in proc adder, that would be something you could do, although there's nothing to restrict it to that. You could use that for other things. OK, one of the important things is they're only writable if the process ID, the PID there, is self. So you can, under some circumstances, write to these files and change your process attributes, provided the LSM involved allows you to do that. But you can't write to anybody else's process using this mechanism. You can, however, read the information for other processes provided the security modules allow that. And important, again, these are defined in proc fs. You can add them there and use a subdirectory because nobody wants to be confused when they read current. Was there a question? Current, yeah, proc self adder current, yeah, OK. If you're on a SMAC system, you'll get one value from an SC Linux system, you'll get the SC Linux value. App armor system, you'll get the app armor value. And if your user space code doesn't know which it is, it could get very confused. So now we're going to talk about some of the object-based or object-based hooks. So object-based hooks, they're affiliated with kernel objects. Now, how many of you are familiar with subject-object models? Is there anybody who isn't? Good, good, good. Education time. So a kernel object, in a subject-object model, you have subjects which are the active entities and objects which are the passive entities. So the objects we're talking about here are the passive entities. And the definitions are very dependent on what qualifies as an object varies, depending on who you talk to. But so object hooks are based, affiliated with kernel objects, things like files, IPC objects. Access is based on attributes that are attached to the objects. So if you want to access a file, it's information off the i-node. If you want to access something that's file descriptor-based, you want to do it off the file structure. If it's an IPC object, it's the IPC perm structure. So it's all about things that are hooked up to the object, attributes of the object. And the downside on this is these things can be hard for humans to identify. If, for example, you have a file, somebody opens it, it gets unlinked, what's the name of it? The name is actually the i-node number, which is still there, and the device it's on, which is the true name. That's not real helpful for most people. Most people say, I just want to know what the file name was on it. But you don't have that because you're just dealing with the real object down at the bottom, which, again, doesn't have the name. So object attributes, again, information, I think. For an i-node, you have the file system object information. You have the input. Again, the blob is infrastructure managed. So if you're writing a module, you don't have to allocate that. It'll get allocated for you. We have traditional attributes like user IDs. And you have extended attributes, which are attributes that you've decided to add, things like smack labels, SC Linux, contexts, all kinds of things that you can add. You can add essentially anything you want with an extended attribute, which we'll get to in a second. We also have a file structure. And this is information again. It's relative to the file descriptor rather than the i-node. It includes an i-node pointer, thank heavens. Again, it's infrastructure managed. And you can get at the traditional attributes and the extended attributes as well. So you can actually use this. You also get a little bit more information about the open state of the file. So you can use that there. So traditional file security attributes. Again, you can use these at will. So you can use the user IDs. You can use the access modes. You can use the file types. You can say, yeah, I don't want people to be able to read sim links.  You can say, oh, look, this file has a link count of more than two. Well, that means it's dangerous, so I'm not going to allow anybody to use it. One of the more interesting aspects here are locks. Locks are hard. If you want to write Nellison that deals with file system locking, I would recommend that you think really hard about it because locks have different semantics as far as accessibility than just about anything else. You can set a read lock on a file you don't have access to. That's always fun. And the other thing is, yeah, don't overload the attributes.  I'm not going to use them to differentiate users anymore. There's a famous system did that. And then they said, well, we're a single user system, so we're just going to co-op these IDs and use them for other purposes. And then somebody said, hey, this is a great device. We love it. Can we please have multiple users on them? And the developers went, huh, because that meant they had to implement profiles on top of their system instead of having multiple users. That's a bad, bad idea. Back in the Unix days, there was a system that implemented mandatory access control by stealing the groups. Nobody uses groups, so we're going to make the group be the mandatory access control label. That was good fun. They changed the semantics to groups and it led to tiers. So extended attributes. We have four kinds of extended attributes on Linux. How many people knew that? Four, but there are four. How many people knew that we actually only used two? OK, good. We have user attributes, which anybody can add to their files. And the system doesn't care about these. It's just a bit of information you can put on. The original purpose of these was actually what kind of icon you would display when the GUI was running and you wanted to do an LS equivalent. Oh, look, I can put the little gif out there. It shows me what kind of file it is. There's the security attributes. The security attributes are actually used by the LSMs and actually supported throughout the system. These are only used by the LSMs, by the way. So you set the LSMs in complete control of who can access these and under what circumstances. We also have system attributes and trusted attributes and other of which are used. But it seemed a good idea at the time when the extended attribute system was being put in. So they're maintained by file systems. Not all file systems support them. Not all file systems support them the same way. Some file systems have severe limitations on them. Others, you can have attributes that are as big as the file. It's a matter of, again, it's an implementation detail. Most file systems, most reasonable file systems, these support them. And if you want your LSM to deal with file systems that don't support extended attributes, that's up to you. So system five IPC objects and keys, we're just going to talk about these just ever so briefly. What they have, they have their own namespace for the objects. When you allocate one of these things, it creates its own internal data. They actually have security blobs associated with them as well. You can actually do whatever policy you want on these. They're not file systems namespace. You can't use the file system semantics on them. No I-nodes. But we do have blobs on those. It's just another area where you have to do special work to make them work. So at this point, I'm going to invoke my very first guest speaker. We're going to have John Johansson, who is the app armor maintainer. He's going to talk about path hooks because path-based hooks are really interesting. And he's the only one who knows how they work. So the path-based hooks. There's a config that you have to enable in the kernel to use them. They're not there by default with just security, LSM hooks. This is the list of hooks. They're not sufficient. If you're going to use them, there's cases you can use them in for sure, and you'll get the information from them. But they are not sufficient enough themselves. You're going to have to be doing other stuff in this LSM. They don't mediate every file access. It's more at the syscall level. Not exactly syscall, but there is kernel accesses that will access files that bypass them. They don't pick those up. They don't mediate open files. So you're going to have to use some of the other hooks. Some of those are like, there's file hooks. There's inode hooks. Mount hooks are really important when you're talking about file system path accesses, because mounts can make aliases. So what do you get with the path hooks? Basically, you're going to get a struct path. You don't get the file name directly. And the file names, even if you do get a file name, they're not unique to the system. They're not a per object thing. They could be alias, depending on namespacing and everything else in there.  Kernel provides a couple. DentryPath does a reverse walk up to the mount, sort of. So it's just within the device. So you're just walking up a little bit. You're not going to find the full path in the system at the namespace. And the D-Path does a reverse walk all the way up to the root of your namespace. So you can reconstruct these paths that are passed into the kernel. So what happens with, like I said, these security hooks, the path hooks are at this kind of the syscall level, but it's after it's done the lookup, right? So the kernel has already walked and found the object. And now we have the VFS mount and the dentry for that object. And now we're going to walk back and reconstruct a path. And it may actually not be the same path that the lookup, the syscall used to get to this object. Because, like I said, you can have multiple paths to an object, but also because the reverse lookup is going to take out to simlinks. So if you had a simlink in that path walk that the syscall did, the reverse lookup doesn't see that simlink. So those are things to consider with this. Doing these D-path calls, it has locking on it. So there is performance considerations. Everywhere you have a security path hook, you can do these. The locking is OK to do that. But it is something to consider, so you might want to cache when you're using them. And you also need a big buffer to look up the path name, right? If you have the dentry VFS mount, that's small. But the path, you don't know how long it's going to be. And path names can be really huge. And so you might be allocating a buffer every time you go in these. Ideally, what you want to do is you actually want some buffer that you have, a working buffer, that you can reuse. You don't have to reallocate it all the time. So aliases really are the big problem with using the path hooks. You have simlinks, you have hardlinks, you have mounts, charoots, and namespaces. All of them make aliases. And so when you are looking at these, you really have to think hard about your model and what you're trying to achieve. Now, that doesn't mean you can't use these, but you really have to think hard about it. And I would caution you that you have to take these into consideration, all of these. And some of these are really hard problems. Simlinks are actually the easiest, because like I said, the path hooks actually, the kernel lookup, resolves that first. And then you don't actually see the simlink, not on the reverse walk anyways. So you don't have to worry about the aliases. The simlink is taking there as long as you're treating it as a separate object. So you treat it as two objects. Your simlink object, so you'll mediate a simlink creation of the simlink. Maybe what's being put in the simlink there is a hook to mediate walking or following simlinks. You don't get the full path. You're just going to get an inode dentury with that. But you can do some stuff with that as long as you're working with multiple hook types. And then you have the target. And what you're really doing is you're mediating. If you're doing D-path, you're mediating post-simlink resolution. Hard links, these are a lot harder. They're a permanent alias, right? They're stored on the file system. You need to really think about these. Now, you can find that you have a link count on these. I've got a link count of two, so I know that this is a hard-linked file. But the system doesn't store what the aliases are in the link. Now, it's potentially possible you could do that yourself in your security, et cetera, attribute or something. You have to figure this out. You also have to figure out what your threat model is here because with hard links, because they're a permanent alias, are you only worrying about something being an online attack? So I could prevent the hard links from being created. Or am I worried also about somebody coming along offline attack and changing the file system and adding hard links? And then that alias is there. And I can't deal with it, right? When you're dealing with these aliases, you have to think about, if I create this link, this alias, and I'm mediating based on these, does it expand the permission set for this task? Or also, potentially, does it expand it for any other task or any other part of the system? And that's where the aliases are really dangerous. And you have to come up with a way to deal with this in your model. Or at the very least, say, that this really doesn't matter to my model. You have to think about it. Mounts, they have basically all the same issues as hard links, except for their runtime only. They're not gonna be stored well.  And you can, again, those mounts are made every time you boot up. So if you're in there from the start, you can do things, mediate mounts to help mitigate aliases. And you really do wanna be mediating mounts if you're looking at the path names and doing any kind of mediation based off of them. Cherutes, turns out, cheroots can be bad depending on how you wanna use them, but the system does provide a deabsolute path, which is a variant of de-path, and it will walk past the cheroot back up to the actual namespace route. So it is one way you can deal with cheroots without having to put in any extra whole bunch of effort to deal with aliases. The real killer, though, is mount namespaces. There is no mount hierarchy with mount namespaces. They're just flat. They can be anywhere. They can be disassociated from each other. They can share. There is no mapping.  Different objects for the same paths at the same location. And then you have the issue where you will get files, you will get requests, not in the path hook itself, but when you're trying to deal with stuff at the path level, coming through the file hooks if you're working with the file hooks because you're working with those in conjunction with the path hooks, where these objects don't exist in your mount namespace. And so you have to know how you're gonna deal with those. You can figure out whether an object is in your mount namespace by using another call called rmount. And then you're gonna have to figure out from there what you're gonna do for these objects that aren't in your path mediations. Things like delegation models would work. All right, Paul. Let's get this fancy little clicker, which means I'm gonna screw something up, so patience please. Anyway, so the networking access hooks. There's basically two levels of hooks. The one first one, the easiest one to use is the socket level hooks. These map very well to the socket related system calls. We have hooks for doing a bind operation, doing a connect, listening. Pretty much every major socket, syscall has a socket level hook. And this is a good way if you want your LSM to be able to control accesses between the processes and the sockets themselves. Because keep in mind, you can have a socket that's shared, so it's not always going to be guaranteed to be exclusive to your application. The next type of networking access control hooks are what I call the packet level hooks, or the per packet hooks. These are low level controls that actually take place on the network traffic itself. Very low level. These allow you to do a number of things. These allow you to control access between the network interfaces and the packet, the sockets and the packet. If you wanna look at the IP addresses, you can do that. Pretty much anything that's in the packet itself is fair game. So there's a number of things. In SCLinks, for example, we can compare against the incoming network interface. This is where we do all our labeled networking controls and whatnot. So there's a good deal of flexibility here. Although we've heard locking challenges come up a few times, there are definitely some locking challenges that you need to be aware of, both on the inbound and the outbound side, because you are getting called from the networking stack and the networking folks have gone to a lot of effort to make the networking stack extremely performant. So you need to be careful not to completely mess things up. So just keep that in mind. The other big thing, we've talked about, there's hooks and then there's labels. So network labels, I'm pretty confident when I say that networking is a little special in the case that we actually allow you to have multiple labels for a single packet, which can be challenging sometimes to get your head around. And it's maybe not the best thing to do, but it's what we've got. So one of the first ones is the secmark label. Sometimes you might hear somebody talk about the net filter label, but we pretty much call it the secmark label these days. These are packet labels that are actually set based on your net filter configuration. So you write an IP tables command line and you can use that to set a secmark label on your traffic. And you can set this for incoming traffic, outgoing traffic, forwarded traffic, basically anything that you can write an IP tables command is fair game. So the one thing to keep in mind, said this before, this is for the local configuration, right? So this doesn't give you any real information from the remote node other than what might be available in the packet or the stream itself, you know, like the source address and the source port, but you'd have no real way of getting any information about the security attributes of the remote system. Like you're not necessarily gonna be able to determine, you know, what was the process running at? What was the label associated with the process on the remote host with the secmark labels? But anyway, one kind of easy quick way to think of the secmark labels is if you're familiar with SC Linux and that app armor might support context mounting, same with smack, I apologize, I don't know, but if you're familiar with the idea of a context mount, which is where you can basically mount a file system and say, okay, everything on this file system treat with this particular labels, that's kind of at a very high level, that's a fairly good analogy for the secmark labels, if that helps you think of it. Next one is net label. Net label isn't one particular labeling protocol or packet label, it's kind of a bit of a framework. It supports two of the standardized labeling protocols, explicit labeling protocols. We've got Sipso for IPv4 and we've got Clipso for IPv6. We also support kind of a static fallback labeling mechanism which allows you to treat unlabeled hosts or unlabeled networks the same way you might treat a Sipso or a Clipso host. Basically allows you to say, okay, if I get network traffic from this particular host over this particular interface, go ahead and treat it as if it came in as a labeled host. So it's great if you need to talk to things like an unlabeled DNS server, if you have Windows or Mac clients you wanna talk to. It's a nice way to do that and have everything on your, all the network traffic coming into your system, it'll look to your LSM as if it's labeled. So it's a nice little fallback. The one kind of got you to be aware of all of the on the wire protocols, so Sipso and Clipso, they only support MLS attributes. So this is a sensitivity level, top secret, secret, and then a compartment or a category bitmap. So there's no standardized provision for doing more than that. We do have for local traffic, so things that go over loopback, we do have some kind of clever cheats, if you will, where we can actually send the full LSM label, but once again, that only works for loopback. We actually kind of intentionally break the format so that it won't pass, check some verification if you send it off the box, so that kind of as an extra protection to prevent you from doing that. Once again, keep that in mind. The other thing we have is labeled IPsec. Similar to NetLabel, this is an on the wire format for communicating security labels over the network. It's currently SELing specific, but the good news is where I said that Sipso and Clipso can only send MLS information. Labeled IPsec can send arbitrary labels. It's basically you're just passing a string back and forth. There has been some effort to standardize this at the IETF. There was an effort many years ago, which kind of petered out, and I just saw something recently. It's being, there's another renewed effort. I'm not part of this renewed effort, so I don't know all the gory details, but there is some effort going on there. Some of what I'm gonna tell you now is a little subjective based on my experience, so take this with a grain of salt, but having spent several years on this, I would say there's a little bit of experience behind these subjective comments. IPsec granularity is typically a very poor fit for LSMs, and if you want, I don't wanna take it the rest of our time talking about that, but if you're familiar with IPsec and how the selectors work and how the LSMs work typically with the access controls, it's just not a good fit, and it leads to some problems. I'll talk about a little bit later. However, it's hard to ignore the encryption and the integrity checking and the authentication that comes with IPsec. It's a very nice thing to have, and it works in a lot of scenarios, so if you want that benefit, I would encourage you to look at some of the other things like SIPSO and Calypso, and running that over a standard IPsec tunnel or transport, depending on the protocol and what your needs are. That's a much more standard approach. It works a lot better, and it gives you many of the same advantages that you would get with labeled IPsec. The only real thing you lose is you don't have an arbitrary string, but in some ways, if you're talking over the network to a remote host, that might actually be good. MLS is a much more standardized label format. It's not an arbitrary string that could be misinterpreted. Okay, and so now we get off network labeling and we'll go back to the local system. SOPyrsec and IPpasssec, these are socket options that allow you to get these network label information up into your application, because there will be times when you might want to have a network daemon, some sort of service on the system that is label-aware and that you want to understand, okay, who am I talking to on the other end of this connection? Nice part about it is these are normal socket options with libse linux, we do provide an API for getting this information, so you don't have to do the setsockop, getsockop sort of thing, but you can roll your own. These are standard linux socket options, there's nothing special. It does obviously require that you have that labeling information in the kernel for the connection in the first place, so you are gonna have to use either netlabel with one of those different protocols or the fallback or labeled IPsec to get that information, otherwise there's no label to give you. The one positive of that is if you're on the local system and you're using AF local or AF unix sockets, you can have that information automatically because it's easy for us in the kernel to go look at the other end and see, okay, this is who you're talking to. So now I just want to touch few more slides on just some, I guess, lessons learned or hidden dangers to watch out for. If you're playing around with LSMs and want to do your own thing, probably the biggest thing that we see or that I've seen people try to do is try to reject connections on the accept hook. And accept is way too late. By the time a connection gets into the socket's connection queue so that you can pull it off with accept, basically you've already finished the handshake with the remote node and you've said that, yep, we can talk, life is good. And you're basically just waiting for the application to come along and say, yeah, I'm ready to start talking to you, I'm gonna pull this connection out of the queue and get going.  So that's kind of the equivalent. So, but what you can do is you can in the accept level hook basically say that I don't want to allow this application to pull that connection off the incoming connection queue, which that's perfectly valid. The connection still stays there and presumably at some point, depending on the underlying protocols, it would time out, I would imagine, but anyway. If you want to reject incoming connections during the handshake process, use the packet level access controls. There are hooks specifically for that, you get an incoming connection, you can drop it, it's safely, it's the equivalent of you basically never opening the door to your house. So that's the polite way to go about doing it. The other thing, struct SKBuff. We have no security blob in the packets themselves and for a long, there's a huge history as to why this is and I'm just gonna say that it's unlikely that we'll ever get one. There is potentially ways we might be able to fake it and if you're really interested in doing that work, come talk to me, but if you're writing your own LSM, you're gonna have enough challenges in the beginning. Don't take this one on. Once again, a little subjective comment, but I've got a lot of battle scars to scare you off on this one. I guess the one exception is SecMark does have a 32-bit field in the SKBuff. If it was 64-bit, this would be a totally different slide, but it's not, so you do have that and this kind of gets to this point of why we have two labels on a packet because the SecMark is kind of separate from everything else. To get around this, NetLabel has some kind of clever workarounds because NetLabel uses explicit packet labeling protocols for the most part. We actually treat the IP option headers as our security blob. We just go in and look at the option header and recalculate the label each time you ask for it. So if you're looking at NetLabel, there's a caching mechanism in there. Strongly suggest you use that because that will help get rid of a lot of the overhead of having to go back into the option header and convert the label format for you. Labeled IPsec works around this because it uses the security associations themselves for the labeling information. It's very convenient in this case, but it's also one of the reasons why labeled IPsec is kind of a poor fit for a lot of LSM security models. So anyway, it's tough to keep in mind. And one of the last few slides, actually sorry, the last slide for the networking stuff is the labeling protocols themselves. Sipso uses IPv4 options and I don't know how familiar most of you are with IPv4, but the IPv4 options is looking back at it. I mean, I think what IPv4 is, 40-some years old, probably made great sense at the time, but nowadays it's perhaps not the best way to do optional information. And a lot of network infrastructure will go ahead and eat IPv4 options. However, in the sense of Sipso, this is probably not a bad thing. It might actually end up protecting you from yourself because the IPv4 options are not, in the sense of Sipso anyway, they're not protected by any sort of cryptography or any sort of integrity verification checks. So if you're not certain about your network infrastructure and if it's going to be stripping off these Sipso IP options, that's a good indicator that you don't have a secured network infrastructure. So you should really, in that case, if you're using Sipso, you'll be running it through some sort of secure tunnel IPsec or whatnot, in which case it's going to preserve your IP options and life will be fine. Similar thing with Calypso, except because Calypso is IPv6, IPv6 has much better option handling. Calypso happens to be a hop-by-hop option if you guys know what that means. But similar thing, if you really want to secure that, secure it inside an IPsec tunnel, life will be much better. Labeled IPsec, once again, I want to go into too much of the gory details, but labeled IPsec, if you're not careful, can result in a pretty badly exponential explosion of essays on your system. This kind of goes back to what I was saying before about it using the essays themselves to contain the labels. So in your normal IPsec configuration, you might have a single tunnel between two nodes. You turn on labeled IPsec, that could easily go into the thousands. And that's just between two nodes. If you're talking between three or four nodes, you can see how it gets out of hand pretty quickly. It's also not offload friendly, no matter what you do, because the label is in the essay, this means that you need to do Ike between the two systems because that's when the label information actually gets communicated. And if that essay is on the local systems, that means you also need to do your AHE or your ESP encapsulation on that system too. So there's nothing saying you can't have nested IPsec. If you have some requirement where you need an on the wire, bump on the wire and crypto or whatnot, you can do that, that's fine, but know that you're still gonna have to run IPsec on your host. That's it for networking. I can see by the next slide, I'm still up here for audit, but before I jump into that, does anybody have any questions about networking? Okay, crickets. All right, audit. So audit versus traditional logging. One of the questions we get a lot is why do I care about audit? I can do a print K, we've got the ring buffer. The basic reason for this is that audit is intended for security-relevant events. These are access control decisions, configuration changes, trying to think of anything that your LSM could do that could impact the ability for it to enforce access control decisions on the system. It also happens to record not just that particular information, not just subject-object-verb sort of thing, but it also records important relevant information for that event. For example, if you're trying to access a file, it's also gonna give you information about the device, the iNode, path name that was used, current working directory, that sort of stuff. And this was primarily developed for the various security certification efforts that Linux has been put through over the years, namely common criteria, but there's others that audit solves as well. And this kind of gets at to the real reason why we don't necessarily want to use dMessage and print K, is that audit provides us kind of a nice, secure path for generating these audit records and storing them on the system. If you're familiar with varlog audit, audit daemon, you kind of get an idea of what they're going there. It also takes care of managing and handling backlog, overflows, exhausting your varlog audit partition, so on and so forth. There's a lot of knobs up in the audit daemon and the kernel to handle all that. So once again, probably more information that we can go into today, but feel free to get in touch with me if you have any questions. So what is audit basically? Well, audit is a bunch of records that make up a singular audit event. The number of records for any given event can vary. So for example, I mentioned on the past slide, you're trying to access a file in the LSM, you're obviously gonna have some LSM specific information like the subject and the object labeling, as well as the access itself. But you're also gonna get another number of other records. One's gonna be a path record, which like I said, it's gonna give you information about the device, the inode, the path name. We'll also give you a syscall record, which will actually give you, okay, what's the syscall that was used to do this? Is it an open, is it a read, is it right? We'll give you the syscall arguments, so on and so forth. And there's others as well. The good news is that the audit subsystem should handle a lot of this extra work for you. It'll take care of bundling all of these individual records up into a single event from an LSM perspective, in this case of the file access. Really, all you need to do is to supply your LSM specific information. If auditing is configured and turned on, you'll get that syscall record. You'll get those path records, without you having to do any work. And there's actually even some discussion right now in the case of some of these things, possibly even allowing the LSM to maybe audit some additional information or to indicate to the audit subsystem that you want to have this extra information, even if the system's not configured that way. But this is work in progress, so maybe it doesn't happen, we'll have to see. So that last line, audit log format, I think the key is, through that first argument, instead of sending null, send audit context, that basically is a hint to the audit subsystem to say that this information is associated with the current task and things that it's doing. That's the clue to the audit subsystem to go ahead and bundle this with the other records. If you leave that as null, the audit subsystem will treat this as a standalone record, a standalone event, and won't necessarily associate it with that syscall and the path records. So from an LSM's perspective, I think 99% of the time, you're gonna wanna have that audit context in there. The one exception might be for some networking events because you don't necessarily have that. It could be running out of an ISR sort of thing. But there's other problems if you're gonna be auditing on the per packet level hooks. All right, so what to audit? I mean, I think we already covered some of this. Primarily comes down to access control decisions. I don't wanna make too many assumptions about your LSM, but like I said, I'm gonna assume you're gonna have a subject and object and a verb. You definitely wanna record that information. Configuration changes. For us in Linux, for example, we have a loadable policy that you can change. So obviously, when you load a new policy, that's something that you wanna record in the audit log. Yeah, so it's gonna be very LSM dependent, I guess, is what I'm getting at because each LSM's gonna have a different approach to securing the system. But think about if it's something that you feel is important for the LSM because it's affecting how your LSM operates or how it affects the system, you probably wanna log it. The other thing is make sure that you're auditing both your success and your failures because a lot of the time, if somebody tries to access that file, you wanna know if they succeed, you also wanna know if they fail because that could be an indication that something not great is going on in the system. Might just be poorly written code or an accident, but it also might be malicious. So logging your failures is just as important as logging your successes. And the final point I'll mention is be careful not to log too much. People that really care about audit logging that turn on a lot of things and that run a log aggregator that collects from a whole network of systems, I mean they can get several gigabytes if not more a day of audit logs. And not only does that prevent a storage problem over a long period of time, but also people that are usually generally, people that are usually collecting that much audit information also have heuristics and business analytics that dig through those audit logs looking for certain things. And the bigger that log file is, the harder that becomes.  If it doesn't need to be in the audit log, if it's not security relevant, there's plenty of other locking mechanisms out there that you should probably be using. And I think the last slide, then I'll hand you back off to Casey. A few tips that will keep the audit people happy with what you do. Don't change the order of fields in a record. That's a quick way to get an immediate knack for me. Nothing personal, just the way it is. Try to leverage existing field names whenever possible. Audit's been around, it records a number of different things. We already have a subject and object in an operation field. Go ahead and reuse those. We also have lsmaudit.c under the security directory, which is handy for auditing various objects on the system. Go ahead and reuse that. You don't have to reinvent the wheel every time. If you're creating your own LSM, once you have enough challenges, you're gonna be inventing a lot of new stuff anyway. Feel free to use that stuff, make your life a little bit easier. And the last two things, if you're doing audit changes, if you're using audit in your code, please CCLinux audit on your patch submissions. That helps us help you, make sure that you're doing all the right things so that you won't run into any audit problems. It also lets us know that you're doing stuff so that we can make sure that the proper numbers are reserved and the header files for you. It just makes everybody's life easier. So if we find out after the fact, then there's potentially issues because once it ends up in Linus's tree and goes out, you can't ever change it, right? So please CCLinux audit. And finally, write test cases. I'm not gonna say that we have a full CI infrastructure, but we do try to test things regularly and we'll help you make sure that your auditing continues to work and that if something else happens in the kernel, it won't break your auditing. But we can only do that if you write test cases. So please do that if you have any questions about that. Once again, Linux audit, send mail. We're happy to work with you there. So like I said, this is my last slide on audit. Before I hand you back over to Casey, does anybody have any questions? Is everybody still awake? Okay, all right, thanks. Oh, sorry, we do have one question. So it depends a lot on what you're doing. So for example, in SCLinux, we have the ability to, you know, we look at and we say if there's no labeled networking configuration in the kernel, such that basically all we'd be doing is comparing unlabeled to unlabeled, we just don't even bother. We bail at the top of the hooks because it's all gonna be the same comparison. However, if we do have any labeled networking configuration installed, then we go ahead and do the checks because it's not always gonna be an unlabeled check. And that seems to work pretty well. Performance is pretty minimal. Beyond that, then it's gonna depend a lot on what you have the configuration set up as. Like for example, I mentioned for net label, there's a caching mechanism on there. You know, the first time you see that on the wire label and you have to translate it into the SCLinux label, there is some overhead, but then after that, it's extremely quick because it translates it right into SCLinux's sec ID. So if you're looking at lots of traffic, but it's from one or two long running streams, you know, for example, in the case of not an aggregator where it's, you know, it opens up the channel and then it just keeps firing events over. The overhead's gonna be a lot less than if you've got, you know, if you're bringing up a lot of individual connections, you know, if you've got millions of clients connecting for short lived things and sending back, the overhead might be a little bit more if they're coming at you with different labels. Labeled IP sec, you're already paying a pretty substantial overhead because of all the cryptographic operations. So while I haven't done any exact performance measurements on there, my guess is the labeling overhead is noise in that particular case. So yeah, there's no hard and fast numbers to give you, but it's easy enough to configure your system the way you want it and, you know, run NEPRF, run NIPRF over it. It's a pretty easy thing to benchmark. So, sorry for that non-answer. Yeah. When you say overlap, are you talking like, the difference between like Sipso and Clipso versus labeled IP sec? Or what overlap exactly are you talking about? Oh, so you mean like the hooking, basically. Yeah, okay, so a lot of the, in order we're rapidly gonna get into a really technical discussion here, so I might punt you to, let's have this discussion in the hallway, but the, so the socket level hooks, that's an easy one. It happens, you know, in the per socket. That's not all that interesting. Most of the per packet stuff is either through a net filter hook or through the socket filter hook. So basically the same, you know, BPF is kind of cool and trendy. We kind of hook in the old school way of, you know, where you could actually load a BPF socket filter on there.  That's where the receive hook is. Last call? All right, thanks everybody. Thank you Paul. Okay, so, excellent. Thank you both. All right, so we got a few more things to talk about here. So security module interfaces here. So what if you have a security module and you want to be able to dynamically configure it? You need to have some mechanism to do that. You might want to tune things. You might want to say, oh yeah, I'm doing a whole lot of controls and I haven't seen a problem in three days, so I'm gonna lower the amount of checking I'm going to do. Or you might want to keep statistics of about the number of things that you've denied or number of things you've permitted. So we do have mechanisms for doing that. Generally what we've been using for security modules and what we'd recommend is that you either use security FS or a CISFS special purple file, special purpose, not purple, special file system. And you can create these. They're easy, relatively easy to do. Easiest way to go about it. Of course, find, go look at an existing one. And that way you can use the file system interface to update your configuration, gather your statistics as you would choose. We want you to avoid using adding system calls, PR controls, F controls, I octals. Because they are difficult to integrate, they consume namespace in those mechanisms and they require more application change. One of the things that if you're writing a security module you'll want to be aware of is that people don't change their applications to suit your LSM usually. They might do it eventually. You might be able to get things upstream for that but in general people won't change and they certainly don't want to change their programs just to suit your LSM. So if you use this mechanism, you can do it in scripts and that's a whole lot easier. Mechanics versus FS, they're actually mechanisms where you can create a new mount point, register with the file system and do a Kern mount. All automatically so your magic file system shows up without having to do any work in the configuration of the system and that's always really kind of handy. Something you might actually come across and just about everybody who does an LSM scratches their chin and hits this one. It's like, I really want to have a hook here. There is no hook here. I need a new hook here. What do I do? It's actually not that hard. It's, we add them all the time. You do want to check and see if there's an existing hook that you might be able to put flags on or use in a different way, a way that might not have been anticipated earlier but generally it's acceptable to request a new hook. In general you pass the thing, not the thing.security. So if you're doing something on an iNode you pass the iNode, not the iNode security blob. If you just pass the security blob then it makes it really difficult for other LSMs that might be interested in using that hook to use other bits of information. So that's, and be generic wherever possible. It's really unpleasant when you're reading the insecurity.c and you see a hook that is specific not only to IPv6 but IPv6 over this kind of device on Tuesday. So we have a boot line. Let's say you've got your LSM. You want to put it in. You want to try it out without making it boot by default so that you can boot your system. So when your LSM fails you can then boot your system without it. So we have three important mechanisms. Security equals. That will run one of the major legacy LSMs plus any of the minor ones. So you'll still get Yama even though you say security equals SE Linux. If you really want to specify the entire list of security modules that gets used you can say LSM equals and then give it the list and it will only use those modules. It won't automatically bring in anything else. So I wouldn't be aware of that. And then there's a nice little boot option have LSM.debug which will show you information about how the LSM configuration is set up at boot time.  If you have conflicts with legacy modules it will tell you which ones are enabled and which ones were disabled and why. So it's about time we did this, about time we had to wrap up. So first thing, have a good reason for doing your LSM. Do something useful. Academic exercises are kind of fun but really we want these things to be valuable. You want to add value to the system and do something the kernel should to do. If you can do it up in user space just as easily go do it there. We don't really need Java parsers or XML parsers or any of that kind of stuff down in the kernel. We want to keep it as monolithic and small as we can. We want to keep that under control. So don't do things that you shouldn't do in the kernel and follow up with user space support and documentation and as Paul mentioned test suites too. It's really annoying when you try to use something and you have to actually go read the code in order to figure out what it's doing. Don't reinvent the wheel. We have lots of wheels. Show us something new. Give us something that will make us exciting. Something that Jake will write about in Linux weekly news. Nobody's done time based controls. It's like and this has been on the table for like 40 years. If I could only run this, if I made it so I could only run this program between 8 a.m. and 5 p.m. So that it doesn't get abused by people who are moonlighting, it would be a great thing. Location controls, it's a modern, a new thing, right? I'm sorry. I'm in the office. I can't run my rogue program. I'm out of my office. I can't run my calendar program, my work calendar program. That would be really cool. And it doesn't have to be dull. It's like, do something fun. Access controls based on, gosh, whether you're on a boat. Because we're in an era now where we actually have module stacking, at least to some extent, getting better every day now. You don't have to say, well, we're running SELinux so we can't do that. Well, you can. So, come up with good things and let's just make things better. And with that, we'll open up to general questions. I know we're running just a little bit late, but, any questions? Kasia, could you give us some examples of when the hooks are called not in the current process context? I assume probably incoming. Networking hooks. Only networking. That's the, right. Incoming packet, obviously, we don't know. Those are the ones I know of off the top of my head. I haven't investigated some of the things like the tunes. Okay. Okay. All process hooks work, exactly. Generally, yeah. All right. Yeah, you'll find out if you're not. All right, exactly, but I don't know. Thanks. Kasia, we're into the break now. So, perhaps there could be a bof if people are interested. Okay, so here's the deal. Everybody who asks the question, come forward here and we will have a contest to who gets the Raspberry Pi. If you didn't get to ask a question and you wanted to, and you want to be in the contest, come up and we'll do the same. Okay, great. Thank you very much, everybody. And just to mention the coffee situation is now that we are sharing coffee from next door, so just go in next door. I'm not sure if this is an upgrade or a downgrade. We'll have to see.