 Thank you everybody. Thank you for coming today. I'm going to be talking to you today about some work I've been doing on system calls for the Linux security module infrastructure. So those of you who don't know me, I suspect there are some of you out there. I've been doing, I'm Casey Schoffler, I've been doing kernel development since the 1970s, starting out on Unix systems. I've been working on operating system security since the mid-1980s. I'm the author of the SMAC Linux security module, which I did in a fit of peak after a discussion with some messy Linux people about a topic I don't even remember anymore. I've been working on the LSA infrastructure for a bit here, and throughout this process I've had periods including the current one where I'm a hobbyist. I'm doing this just for the sheer joy of it and the sheer pleasure of having patches reviewed. I also haven't done a presentation live in three years and I forgot my clicker and it's bugging me. So I'm going to start off with just a touch of Linux security module history because I think this is a little bit of an important background. In the 1990s operating system security was in a very turbulent period. In the mid-80s President Ronald Reagan had, oh, no, that would be your clicker and that would drive me even crazier than not having one at all. It was a very turbulent time. In the mid-80s, no, thank you. That would make me even crazier still. There's going to be a joke here, a running gag here for the entire presentation. They had introduced this executive order that said all U.S. government computer systems had to have a particular level of security and have been evaluated by the National Security Agency to have that level of security by 1992. It was called C2 and 92. So all the UNIX vendors went out and crazily implemented features to meet these standards and had gone through the evaluation process and spent millions of dollars doing this. And then 1992 came and the government said, eh, we don't really care about that. So there was a lot of turbulence. A lot of people had done a lot of work on security and they lost their funding because nobody was going to pay for it anymore. Now at the same time, Linux was coming along. Linux was brand new in the early 90s. It was establishing itself as a legitimate alternative to the proprietary systems that were available otherwise. So as we had this combination of a lot of security developers who were out of work who still wanted to work on security and we had Linux coming in and we had a bunch of security people with operating systems development experience and we had this wonderful turbulence situation where we had a bunch of people who knew a whole bunch about what was going on how to do operating system security and no place to do it except in Linux. So there were a lot of different viewpoints about what should be done and what shouldn't be done. And in response to this when Linux actually got around to the point where it was actually going to deal with the possibility of doing some of these advanced security features Linux decided that what he really wanted was a framework for it rather than a particular implementation. And so that led to the Linux security modules mechanism. Now the mechanism is really pretty simple. Many of you are familiar with it but for those of you who aren't, the mainline code calls something called security food. And security food may or may not actually make any decisions based on that but it's going to go out and it's going to call SE Linux hook for this or maybe an app armor or maybe a Yama or whatever security modules you have it's going to go out and say I'm just going to call all of the ones that I've got listed here and if any of them say that I shouldn't do it then it's going to return an access failure and so implement an additional restriction not replacing the existing policy, the existing security mechanism it's an additional thing instead. So very much like our castle here we have the high walls and the moat. So you have to swim out and then climb up as opposed to just climbing up from the ground which would be too easy. So LSMs are really kind of at this point a bolt on thing. It doesn't actually use the mechanisms that are there otherwise it's something, it's its own little thing. It's pretty much self-contained. So traditionally the way LSMs interact with user space when you have to do a configuration issue or a change of things is through file system interfaces. So one set of interfaces are going to be completely LSM specific. For example, SC Linux, SMAC have their own file systems that you mount to get mounted when you start the system that you go off and interact with. App armor uses SysFX or security FS. So you use that. And there's also a mechanism in slash proc to get LSM based attributes. So if you can read one of these interfaces it'll get you the set of information. Current is the one that's used most frequently. And that tells you the current security attributes provided by the LSM for that for your current process. And it's a LSM specific implementation. So for example, App Armor puts a new line at the end because when you cat that interface is much more convenient that way. SC Linux doesn't, SMAC doesn't because it's just the raw information. So there's no consistency there. And there's certainly no guarantee of consistency there. And this is fine. We've got a bunch of these interfaces. But how would you use them? How do you actually help get the real values out for the application user space to use? Well, when I did SMAC I made a bit of a mistake. I decided to reuse proc self-adder current, which was what SC Linux used for the current security information. And the rationale was very simple. If I do a ps-Z, I'm going to get the information because all the ps is going to go out and it's going to read proc self-adder current for each of the processes. And for that it'll all be really easy. And it'll work for ID too, right? Well, unfortunately ID is compiled in such a way as to only do that if you actually have SC Linux involved. But that's a small matter of programming there. But it means that you can, ideally you're thinking in terms of it doesn't matter what LSM you have if you're using current because it's going to give you the information. You can do whatever you're going to do with that. Unfortunately, a lot of applications then say, all right, now I'm going to go into a function in SELinux and it's going to tell me what to do with this. And that doesn't really work very well if it's a SMAC label. It turns out the same thing works with SO-PeerSec, which is the mechanism to get the peer credentials from the socket. If you just pass the context without any information about what LSM it is, it's generally going to assume it's SELinux because that's the way a lot of the applications have been written. And you may or may not get the results you're after. It's unfortunate that as I made this mistake, it was adopted as conventional. So App Armor did the same thing, adopting current as the current context. So now we've got a case where we have what I'm going to call the current conflict here. So in the picture, this is a grand mistake I made, another grand mistake I made. I was having a party for a friend's birthday. He was turning 60. So he put 60 candles on the cake. It's possible. Yes, it's not recommended. Nicely caramelized the icing on the top. The flames went three feet high. And we did manage to get it out. So just kind of a mistake on the same order here. So we could stick with Slashproc. We don't have to get away from Slashproc. There are ways to address it. We can address the current conflict. One way is to create a subdirectory in Adder for each of the LSMs. And that would work really, really fine. It would be very smooth and very, very obvious. Everybody switches their applications to use an appropriate subdirectory, depending on which LSM they're expecting. But you still have the base entries to deal with. And so that doesn't really solve the problem until everybody has switched over to it. Another mechanism is to have a mechanism and say, I want to change what which LSM might be displayed there in current. Well, that's going to be awkward. At best, that's going to be awkward. Or we can say, let's add entries so that in addition to having current, we're going to have context and it's going to come out and it's going to have information about all the LSMs in it. Well, that leads to the question of how are you going to format that. And we actually put a good deal of effort into discussions with user space community about how that should be displayed. And in the end, we ended up with, and this is used in some other places where there are multiple entries for information. What I refer to you as the hideous format. It's not really that bad, but it requires a careful application in order to use it. That's a blob fish, by the way. So the format would be LSM name terminating null attribute value. LSM terminating null. And this would work, but really this isn't very pleasant to deal with. So, extending into slash proc, although we could do it, it's probably time we did something different. So we want to change the mindset. The mindset of I have an LSM, it's responsible for everything. It's going to have its own user interface. I'm going to have a file system that meets my idiosyncratic ideas as to what should be done or shouldn't be done. Let's actually put some LSM independent interfaces in place. Let's do it differently. Let's admit that we've got multiple LSMs here that we're going to have different LSMs on different systems. Let's just kind of do this better. Introduce a little consistency too. Not a bad idea. And because what I've been working on for the past 10 years or so is Linux security module stacking, I really want to make that part of what it is we're going to achieve here. So now, why do we want to use system calls instead of proc entries or a special file system or some other mechanism? A system call is generally an atomic operation, at least from the viewpoint of the application. You're going to do one thing. You're not going to have to open a file, read the data, close the file. You're not going to use the file descriptors this way either. They're better suited for binary data. It's traditional or conventional rather that file system interfaces use text strings. And text strings are really nice unless what you're doing is a big glob of data that you then have to parse or produce in the correct format. System calls also have ABI stability. Anybody here like ABI stability? Okay, there are at least a couple of you. That's good. And again, you're not having special file systems required. It means you don't have to mount them. You don't have to know the path name. You don't have to do any of that. You can just do it. So that's why I think we want to do system calls as opposed to some of the other mechanisms that we could possibly use. So if we're going to do system calls here, what system calls are we going to do? I hear you cry. We're going to do the ones that we need to have for stacking because that's what I need to get done. That's what I'm trying to get done. That's what I'm trying to accomplish. Perfectly willing to go beyond this. But for right now, this is the set that I'm working on. So what we want to do is we want to replace the things that you're getting from proc self-adder about the information about your own process and the list of LSMs. Because you need the list of LSMs if you're then going to decide what to do based on what LSMs you're using. And so we're going to actually have an API. Finally, an LSM API. So as we're designing this, one of the key elements is how do we make sure that it'll work when we have multiple LSMs? And how do we make it so that it's generally useful and extensible as we go forward? So we're coming in with a structure LSM context, LSM CTX. And we've got a bunch of data in this in order to make it generally useful. All right, so the first thing is the LSM ID. This is a new thing, newly introduced for the system calls. To date, you have always referred to the LSM by the text of its name. If you want to do something with SC Linux, you're saying SC Linux, you want to do something with SMAC, you're dealing with SMAC. By introducing an LSM identifier, we now have a numerical value that you can use to identify the data that's coming out with an LSM. This is fairly important if you're going to have a user interface because you don't want to have multiple variable size entities in your structure, in your data. If you have multiple variable size data, somebody's going to break it. It's much harder to deal with than if you just have a single value. So the LSM ID, again, identifies the security module. It's a number. It's reserved in LSM.h. We've reserved the first 90, 0 is defined to be undefined, and we've reserved 1 through 99 for future use. What that future use is, if I could read the future, then I could read the future as opposed to not being able to read the future. It might be used for containers. If you want to have a mechanism to return all the traditional attributes, that could be interesting. One of the things that's been bantied about a long time is the notion of how can I get all the security attributes at once without doing multiple system calls. It'll happen at multiple times and give me different instance system data. That's one possibility, not actually implementing that yet, but that sort of thing. Next thing would be flags. These are things that are special about this set of data. Possibility is that it's transient. There's, oh yeah, I'm giving you this data, but beware that it's in the process of changing and you might want to do something about that. Or another one that came up is what happens if I find a value and I'm going to give it to you, but I know that it's invalid in the policy you've defined. Again, not something that's being implemented today, but the kind of thing that you might use of flags for in the future. And of course, if we don't have it now, then we have to add a layer that would be a rev of the API. We also decided it was important to have the total length of the object, the whole LSM CTX structure, including all the data that it contains. And it gets padded out to 64 bits because we want it to be API friendly, regardless of what architecture you're running on. The context, when, is the length of the actual data, the actual attribute data that you're returning. And in a major win for API commonality, it includes the trailing null byte. Now, if it's a text string, of course. Now, why is this important? Well, because since we've been introducing LSMs, we have been very inconsistent about whether, when you get the information about the attribute, whether if it's a string, are we giving you the length, are we including the null or not? It's been sometimes yes, sometimes no. And so we're just saying, fine, we are going to do it. And then finally, there's the data itself. Yay, we want to have the data. So it's the attribute data. Again, it contains the trailing null if it's a string, but it can be binary. Now, this is something we actually had a very thorough discussion about. Like, do we want to, at this point, put our foot down and say, all of these are going to be text strings. And although some of us, some people said yes, some people said no. The argument for allowing binaries are things like if you were implementing a traditional Bell and La Pagela model, you might want to have a security label which is a data structure rather than a text string that then has to be parsed by the kernel into a data structure. So allowing a binary, again, gives us maximum flexibility. We want flexibility going forward because we want everybody to use this. So I'm now going to talk about the system calls that we're actually implementing. There are three. The first one is LSM list modules. This simply gives you a list of the LSM IDs of the security modules that are active on the system. Not necessarily the ones that are compiled in. You may compile in a bunch of them, but only activate a particular set. And so you get the list of LSM IDs for the ones that are active. You send it a buffer. You send it the size of the buffer. You send it flags. Again, this is something that it's currently not supported, but I'm sure that if you wanted to report them in alphabetical order as opposed to numeric order instead of order registered, you could do that. But I'm not planning to support anything like that right now. And it returns the number of IDs received. So in this case, it would return four. So I've got four security modules. So the next one, and this is kind of the biggie as far as the multiple modules ID is concerned, is LSM self-get adder. So you pass it the attribute that you want. So we actually have to introduce, in addition to the LSM ID, we need to introduce an attribute ID, which matches, for example, if you want the current attribute or the pre-issue attribute. We have a different ID for each of those. And so you pass it that and a buffer and the size of the buffer and flags, which we've got one defined for. We'll get to that in just a second. And it will tell you, it returns you LSM contexts for each of the LSMs that support that attribute on your system. And it gives you them in order. And it returns the number of them that it's received and it resets the size parameter to the actual size that it's returned. Now, this brings up something that I forgot slightly earlier, which was that the reason we have a size and a contact size because ideally you should really only need one, well, if somehow you wanted to have additional information as well as the context. If the size is bigger than the size of the structure plus the size of the attribute, then you can have, sneak some more information in there for a particular LSM and still maintain the API. I don't know that I would want anybody to do that, but it is feasible and you could then do that. We have a flag, which is LSM flag single. Somebody said, you know, it would be really handy if I could, in my buffer, if I put the LSM that I want in the ID field and pass a single flag, then it would only give me that one. So I don't have to get all of them. I can only get the one that I really want at this point. So we implemented that flag. So this points out that having flags really is valuable. Because there are use cases that are slightly different that crop up. Now, LSM self-get adder returns you as many attributes as are available for that particular attribute ID. LSM self-set adder is a little bit different here. It only lets you send one. And the reason for this is that if you try to send in three attributes and the third one fails to set because it's invalid or policy doesn't allow it or some other reason, you then have to unwind the first two. And that means that every system, every LSM that implements that attribute has to be able to unwind it safely. And that seems like a heroic task. So it's much better to say, we're just going to set them one at a time because they might fail. Getting them is much less likely to fail than setting them is. And again, you're going to tell them which attribute it is and then you're going to have the LSM context in a buffer. You're going to send the size of the buffer just to make sure that everybody's happy. And we don't have any flags and it returns zero when it's done. So these are the first three. In the future, we are also going to think in terms of using this structure as our primary representation for security attributes when they're coming out into user space. So we have SO peer sec today, which gets you the security context of the other side and that works as long as you only have one. If you have two, you need a mechanism for getting more. And rather than trying to fiddle with SO peer sec and have it provide something like the hideous format, we want to introduce SO peer context. Again, future work that would actually, again, return LSM CTX structures, which then are a common format. Everybody knows how to use that. And of course, in the future, anything that we want to have do extended security attributes, we want to use LSM context structures for just to make sure that we actually do things rationally so that people know how to do it. We don't just arbitrarily change the API. Now, arbitrary APIs because, well, that's kind of fun because it isn't. So we have some potential future LSM and I apologize profusely in that as I was writing the slides, I forgot my conventions and so I put the get instead of putting the down first and then the verb, I put the verb first in the noun. But you can transpose that in your head if you're so inclined. So one obvious system call is to get the security attribute of another process rather than the current process. That's actually a reasonably common thing for people, for programs to do. It has, you know, one of the advantages to it is you can, rather than having to open the entry in slash proc and then have the process go away while you're in the process of reading it, it's, again, it's atomic operation. You go do it, it comes back, it's all done. Similarly, how about the attributes on files? It would be real nice if I've got multiple sets of security attributes on a file if I could get them all at once rather than having to guess about whether they're there or not and pull them in. This is actually fairly different from getting it for a process but, again, potentially very useful if you want to support that kind of thing. You want to support that information on a more general basis. Another one, access. Well, let's say I want to pass in a bunch of attributes and say, hey, this file over here, if I had these attributes, could I access that file? I can access system call which does that sort of for UIDs but we don't really have anything like that that you can use in general for LSM. SMAC actually has a mechanism to do that but this isn't available as just kind of a general thing. So, we've got some other potential system calls here but we've got the ones that we're defining out right now. Maybe it's time we had liblsm. What would liblsm provide? Well, it would, of course, provide interface names for the system calls but you could also use it to create emulations of those system calls for systems that don't have those system calls yet because we're currently replacing the functionality of existing interfaces, the PROC interfaces. This is kernel security interface. We can do that using those interfaces and the application can write to the new modern forward looking APIs without having to have a kernel that's really fresh and squeaky clean. You can actually use that 419 kernel that pops up every so often these days. Another thing we can have put in liblsm are functions to parse the LSM context structure to fill in an LSM context structure to allocate one to deal with them in general and then some people prefer to use functions rather than to actually deal with the data directly. So where are we here? Well, that's about all we're talking about. I've got to say about the matter at this point. It's a dramatic juncture in the narrative. LSM systems really are overdue. At some point it looked like there was just going to be one security module and everything was going to go that way and then that broadened that. We have more options here. It also looked like initially security modules were going to be rare. You weren't going to use them very often. Well, Android kind of blew through that one. The only people who are not using LSMs at this point are developers. Production systems all have LSMs of one flavor or another. System calls are better than the Kluge-PROC interfaces we have today or the security FS interfaces. As we're coming out with a few system calls now, we're going to set the ground rules, the direction that we're going to do for LSM independent application spaces going forward. I think that's really, again, it's something that's overdue. That's what I've got to say. I'm happy to have some questions here. I have a question from online. Someone is asking, is there an estimate for within major LSMs and how they can be stacked? Is there an estimate for... For within major LSMs? For when major LSMs can be stacked? Okay. In 2010, I made a comment that ended up on Linux weekly news and it was like stacking, yeah, I used to be against it but now I'm kind of for it and really all we need to do is buy somebody a case of the beverage of their choice and turn them loose on the problem. I still haven't gotten my case of beverage. I think that the code's been done for years. It's been getting polished one way, this way and that way. I have no idea. I would like to say I expected in a year but I can't say. Next? Hi Casey, it's Mike. You'll have to forgive me if this is a bit of a tangent. Maybe I'm starting a bit of a flame war. Oh, good. I tend to do that sort of thing. I heard you talk about maybe having a little extra space at the end of the buying format where you can maybe put some extra information. You'd rather people not use that space but it's going to be there. I got to thinking about a topic that's come to mind a few times for me in the past and that is that we have a concept of something that has a schema where you could optionally have members of the schema. This is this notion of a protocol buffer and there are very efficient binary formats for such a structure like CAPM and PROTO. You also talked about having a library that's going to be the element that interfaces with the kernel in order to parse the information. I start asking questions. Is this a great example of something where we're going to have a stable ABI? We're going to have an interface? Would we want to think about using something like PROTO buffs where you have a schema and you have optional fields in order to help deal with this problem of funny extra space at the end of a structure? So let me think myself on this. I think that that's really more technology than the problem requires. I would encourage people who write new LSMs to, when they do so, actually make their attributes fit in, make all the information they need fit in their context. If they can't do that, then the mechanism is available to use more space afterwards, but I really wouldn't encourage them to do that. I really want them to use the context the way it's defined, and if they can't, yes, there are people who are going to do things wrong and are going to come on and say, oops, I need to redo my API to include this additional information, but I would really prefer that they think about it in advance and not do that. And I don't want to put a big mechanism in place to allow them to make it easy for them to do that because that's a bad thing, or that can be a flame war if we want. Yeah, that's my position on that, is I'd really like it to use it right. If I can maybe add to that a little bit. I know we've had other discussions about protobufs in the past and other contexts if we can overuse that term. We've got, what, it's in the 400s, the number of system calls that we have right now in Linux kernel, I can't remember the exact number, but I don't believe any of them make use of protobuf currently, and I understand protobuf offers some things which would be attractive here. However, the LSM needs to be relatively careful with what we do with kernel because there was a joke that Casey made about the only people that aren't using LSMs are developers, and I would say to reword that, I would say the only people not using LSMs are core kernel developers. The LSM is not particularly loved in big sections of the kernel, and I think simply introducing syscalls for the first time, in case you mentioned, we're only starting with three, and that's somewhat intentional, because we don't want to spend a whole lot of time on something until we know that there's some buy-in at the top levels. And I don't want to introduce system calls and also being protobuf into the Linux kernel at the same time. I feel that that might be a bit too much, and I think what we have should be sufficiently for limited needs that we don't necessarily need to go the protobuf route. If protobuf had been in the kernel for several years and people had been using it, maybe this discussion would be different, but as it stands right now, I don't know that we want to take on system calls and protobuf at the same time. We've got enough headaches. Hi Casey, thanks for the presentation. I didn't follow the discussion regarding the choice of the system call. I was thinking, for example, when you have a file, a file inherently supports multiple SM because you can have extended attributes, one for Syrinx, one for SMAC. Actually, you might have three for SMAC. Okay, yes, yes, of course. What if you present the same interface for current? For example, you implement virtually extended attribute methods where you say, okay, if you do least etc., I get the active lsm, and when you do get xatra, you get the value for current for that particular lsm. So part of what's important here is that there's no reason you have to implement your attributes as extended attributes. You could, for example, remap the group ID to a mandatory access control label. And before anybody says, why would anybody do that? It has been done. It was the least painful way on that system to implement mandatory access control without changing the file system format. There are other mechanisms to implement the extended attributes that don't use xatters. In fact, xatters are a relative newcomer in that mechanism. So when you say, I'll get the xatters, well, you can't necessarily say that those are in fact the security attributes or that those xatters are exactly the security attributes. You can conceive of an lsm that would read the attribute off the disk and say, ah, I'm on an arm architecture and on arm architectures I perform this transformation on that data to make the actual security attribute. Or on an x86, I do another transformation to make that security attribute. So when you're actually asking what is the security attribute, you're not asking what is the data of the security attribute. You're asking what is the attribute? What do I want to present to the application space, which may or may not be what you actually have out on the disk or in the backing store or on the tape somewhere. It's a different problem and that's one of the problems that we can address with the system calls. Thank you very much. It's a great, you can address the issue of abstract, of taking the representation issue out of the problem and just providing the attribute. Did I answer your question? Yes, yes, thank you. Anyone else? I still have a question about the interface. Why have to be a system call? I think the file maybe looks better for me because the IO control function pointer is also very expressive and we can treat the RSM as a module, keep the design style. IOctl is always, yes, would have been an option for files. The problem is you'd have to use a PR control in order to get the information for a process. And then you'd need an IOctl to do things for files or an F control for files and it's not nearly so clean. Thank you. Okay, well, thank you very much for paying attention. John, you can wake up from your nap now. Thank you.