 All right. Hello, everyone. My name is Daniel, and I'll be talking about Cascade, which is a new high-level language for implementing SE Linux policy. So, as just said, my name is Daniel. I'm a senior software engineer at Microsoft. I've been there since COVID has, and there's my email address. I'll also, I think, have my email address in the last slide, but my slides are up on the schedule site, too, so if you want to grab my email address. There's the GitHub page for the Cascade repository, and also this is a Rust project, so it's available on crates.io. I just made a new release last night, so the current state of the code as of this presentation is up on crates.io. If you want to download it and play with it. So what I'm going to talk about is I'm going to start with the motivations and goals behind why we made a high-level language for SE Linux and what we're trying to achieve with it, and then I'm going to talk about the language itself in terms of what it looks like, how to use it. It's going to be more of a quick overview than a thorough teach yourself. I don't have enough time for the really in-depth nitty-gritty, but I'll refer you to the documentation if you want to learn more, and then we'll talk about kind of future plans, daydreams, where we'd like to go with this. So anyone who's interacted with SE Linux has probably heard the complaint that SE Linux is hard, comes up a lot. A lot of the perceived challenge of SE Linux has to do with the fact that systems are complicated. I regularly get people being like, oh my gosh, SE Linux is so confusing. What's it doing? I don't understand. My code's not doing this. SE Linux is reporting a denial. Clearly it's a bug in SE Linux, and then it turns out that they're calling some library that's doing something they didn't expect that actually has real security consequences, and they go, oh my gosh, I didn't know that library was doing it. And so in order to write good SE Linux policy, you really have a lot of different things you need to understand. You need to understand the details of how the application you're writing policy for works. You need to understand a lot of the implementation details of the underlying library, of the underlying kernel and system that this is built on top of. You need to understand language details, both of the language that the application is written in in a lot of cases, as well as the language that you're writing the SE Linux policy in. And of course, you need to understand the security goals of your system. And so this is something that, in most contexts, I think one person does not have all this knowledge, at least easily. And abstractions can help. We can abstract away some of these language details and these kernel details. But in my opinion, the current state of SE Linux is that the discovery and usability of the available abstractions is not where it needs to be. So when we write policy, we have a number of challenges. And I'm going to, for most of this talk, I'm going to focus specifically on writing your M4 macro reference policies, style of policy writing, because I think that's what most people are using today, as in terms of how I contrast to Cascade. So if you're writing in reference policy, you have at least four different syntaxes to learn by my account. You've got your, like, your base policy language, you've got your M4 macros on top. If you want to add a fifth, you can say that it's the specific ref policy usage of the M4 macros, the way they've defined interfaces and templates, et cetera. You've got the file context file has its own special syntax. And the constraints was the fourth one I was counting has its own syntax. Because reference policy is architected with a preprocessor first, and then we compile the base policy language into Cil, and then we compile the Cil. And there wasn't a lot of checking earlier. So the Cil could still have errors in it. We get these error messages that you're like, I wrote a macro, I'm getting an error in Cil, what's going on? There's not a lot of checking against policy developer error. And traceability from, hey, I have this ABC denial, or I have this result from my static analysis tool on my binary policy, tracing that back up to a line of source code is extremely difficult. So what we'd like to do is focus our time and development effort on our system functional behavior and security goals. Those are the hard parts, those are the interesting parts, and not be focusing our time on language limitations. So we want to build on top of some prior work, specifically a project called Cil Common Intermediate Language. And this is a quote from the Cil Wiki here, the SC Linux Common Intermediate Language is designed to be a language that sits between one or more high level policy languages, such as the current module language, and the low level kernel policy representation. I think it's, you know, an interesting claim to say that the current module language is a high level language in many senses, but it is. And so Cil is designed exactly for our use case. We want to take a high level language with advanced features, compile it into Cil, and then let Cil handle the low level details for us. And so my understanding from having talked to some of the people who originally implemented Cil is that they envisioned a future with a whole bunch of different high level languages that everyone could go write their own high level language, compile into Cil. We'd have a robust ecosystem. And so far, that has not necessarily materialized yet, but we're hoping to change that. So and let me another note on Cil is as I said a moment ago, I'm generally speaking when I say, you know, cascade adds this, I mean, in comparison to reference policy, Cil has a number of the functionalities here available in native Cil already. So our model that we're using as we develop policy at Microsoft is that we have a relatively small number of quote, policy experts who kind of handle some of the core functionality of the system. We create abstractions, build things that other people can use. We verify the security goals of the policy, we review the policy that comes in, we run static analysis tools, we enhance static analysis tools. We also have a lot of application developers who are writing various applications, and they want to we would like them at least to write some of the policy for their applications because they know what their application does. And so they should use the abstractions created by the policy of developers and need minimal to no policy knowledge. This is the model we're working to get to. And it's had some challenges in terms of the existing language. But that's what we're targeting with cascade. And I think that's a model that's kind of extensible to a lot of people's use cases. So our goals with cascade, the number one goal is we want to improve the usability of writing policy. And specifically, we want to have a very consistent syntax. We want to have a pattern where the simple option is typically the best option. In existing reference policy, your simple option is to write an allow rule. And that is very, very rarely the thing you actually want to do to solve your problems. We want to make the things that you actually want to do look very simple. We want to support mapping our information all the way down from what we get at the end of the binary level up to where that came in source. And where possible, we'd like to abstract away implementation details. That always gets tricky when you start talking to security people and they say, oh, but my security goal really cares about this particular detail. And so there's some of that becomes create the ability for those policy experts to abstract away the implementation details as they desire and move some of that into policy. In some cases, it is abstract away implementation details. For example, the object classes, some of these object classes have overflowed their number of permissions past 32. So we've got capability to process to, et cetera. Cascade just has capability and it knows which permissions are capability to and handles that mapping for you, for example. So we'd like to provide support for a model where our application developers are actually writing policy and that works easy for them and they say, oh, hey, this is not as bad as I thought. Why does SC Linux have this representation? Rep, what's the word? Reputation. Thank you. Okay. And we'd like to also though provide full expressiveness for high assurance just because we're a high level language doesn't mean that we want to abstract things away so much that you're not actually having control of your security goals. So think rust as opposed to like Python. And so we want to also be not by a foundation on which to build additional high level tooling. So this is supposed to be a building block, not the end all be all. And we have some ideas about what that high level tooling will look like. We also would like to check as much as possible at compile time. Obviously you can't turn every single runtime error into a compile error. It would be really nice if we lived in a world where that was possible. But there's a lot of things that in our current ecosystem, both the threat policy and still you can write policy that is correct, compiles, installs, and is just never what you would have wanted on any system. And we're trying to check as much of that as possible as well as providing the ability to add checks in a more featureful way. That exists now. And so ultimately we want to be a high level language. We want to abstract patterns. We want to provide syntactic sugar. We want to do what we can to hand hold and make things easy. So in terms of the external tooling, our core language is built as a library. The last talk I think teed me up really well highlighting how Clang's building as a library enabled him to plug in and do all sorts of interesting things. And that's exactly what we're trying to do, kind of emulating Clang there. That almost all of the Cascade implementation is in a library. We've got this really thin front end to provide a binary compiler. And then we could, we or others, could write additional front ends to do things like integrate with IDEs, create analysis tools, talk to them about automated incident response tools, a bunch of stuff. Now obviously Cascade being a Rust project at the moment that means those tools would need to be written in Rust, which is certainly a deal breaker for like existing IDEs that would like a plug-in written in C. So we'll need to add FFI bindings for C. That's coming soon. That'll be, that'll be the tagline for this talk in a lot of ways. But so we want to make the, all of the, Cascade has the ability to represent kind of intent and meaning in the policy directly in the policy and documentation in terms of documentation comments and then make all that available to the tools so that you can take advantage of the richness of Cascade and whatever tooling you're doing. So far we're focusing just on type enforcement for now. We do want to support all the security models of SE Linux. So currently when Cascade writes a policy it generates two roles. System R and Object R, one user, and it handles all that for you. It does not build MLS-enabled policy. That's coming but not in the near term we got to get type enforcement working better first. We've got a growing fairly robust test suite it now. We want to make sure that future compiler enhancements are safe, regression free, easy to do. These test suites also provide simple functional examples. If you want to look at, here's some working and some non-working Cascade policy. That's a decent set of examples to start with and this is the path there is in the Cascade repository in the data directory. We've got hopefully the names policies and air policies are intuitive. Okay current status so as of yesterday I released version 0.0.2. That's basically just a line in the sand of this is where the project was as of the time of this presentation. If you want to see exactly the details of that there's a change log in the repository. And we've got support for declaring types, AV rules, except never allow it's not implemented yet. And we have inheritance, we have a thing called resource association, I'll talk about that in a little bit. We've got a number of the abstractions and features that you would desire if you're going to implement say a full policy. Many of those are done, many of them those are in progress. And we're still working on some of the the nitty gritty low-level details of stuff that you have to have but like you know port labeling for example not currently supported in Cascade needs to get there. We'll get there in a few months. So we're going to hopefully in a month or two here release 0.1 which will give you a clean build of a sufficiently complex kind of comprehensive policy. And then the goal later this year is going to be we're going to call it 1.0 for a sufficiently comprehensive support for hey I've written something that's you know roughly functionally equivalent to say targeted policy or any existing policy. It's not necessarily as fully featured full but it's kind of done enough that I would say hey go ahead and start using it write your policies in it. So that's coming at that point is when I would aim to make any kind of backwards compatibility promises about hey you write policy that compiles now I intend to compile it for all time or at least until 2.0. And so right now you know if you write policy I do reserve the right at this point to change how the language works and break it. I actually have a pull request open right now that does that. So we're we're changing things I mean it's it's stable-ish but reserve the right to change things. And if you want to see you know the the nitty gritty details of all that I've got a roadmap.md file in the cascade repository that kind of walks through all of our future plans up to 1.0 passed it to 1.1 and 2 and 3 and things that are in the the pipeline down the road. So and we're very open to modifying that that's not this is the dictated plan we must follow. So if there's something that you say hey I would love to adopt cascade I need feature x let me know and we can modify it. So let's go into the details of how the policy language works. So a general rule that I think is an absolute is uh declarations or blocks with curly braces and rules or statements that in in semicolons. So we declared types with either the domain or resource keyword that definitely should have had quotes around domain and quotes around resource. Um and so this is kind of an interesting thing that's I think different from existing precedent that we've put in the language the fact that some of these types refer to processes and some of these refer to resources which maybe is a controversial decision I think it's a feature not a bug that types are types are types in se linux and they're all types. But this really allows us to do some things at the compiler level to make various assumptions about how people are using these things and add additional compile time checking and functionality. Um so we also declare functions with the function keyword and we'll talk about functions in a moment so here's an example to declare a domain called foo this is a type named foo it's just the type that I'm promising to use as a process and I can only use as a process the language will enforce that for me um and it's got a function in it and then we can call it down at the bottom you can see you know in domain bar we're calling foo.sum function probably you know in most cases you'd be calling functions on resources is more of your common but maybe some function is signaling or IPC or whatever and then obviously you got various rules in the function domains can also have rules maybe calls to other domains or built-ins like allow etc. So functions um functions do support full type checking on their arguments that includes the se linux types so if you want to create a type or it's it would technically be an attribute under the hood but in cascade that's now a virtual domain or a virtual resource um if you want to create a virtual resource that's you know some abstraction for say temp files and then you want to say this function only takes temp files then it can take any kind of temp file and you'll get that enforced at compile time these functions are all automatically derivable via inheritance that means that we can define kind of a high level interface that you know all all domains or all all files for example are required to support you know a read function etc and that way we can kind of predictably go in and say if i know that this is a file type i can call read on it i know it'll work and we also don't have boilerplate we've done a couple of kind of ad hoc studies of looking at like if we take this ref policy module and reimplement it in cascade how much is the number of lines of code go down and the big win there is there were 300 lines of interfaces that become essentially zero lines because those interfaces all got derived from a parent type and then going forward we really want to have automated documentation generation on these functions that's it's something that's in progress and integrate with external tooling in all sorts of interesting ways so this is what this is a built-in function actually the allow function here it takes four arguments so you'll know this is one of those uses of the domain and resource separation here because i mean i've made the mistake before writing se linux policy where i accidentally you know say a fu t instead of fu exec t on my target and then everything compiles i get the rule on my system it didn't do what i want to do obviously astute viewers will notice that some allow rules can take a resource as their source and so that's a an asterisk on that that we've got to handle that some other way the details are tbd but we'll figure out something there there's a couple of good options the the square brackets around perm here are a list so the the permissions in this case are a list of permissions at some point i'd like to add some syntactic sugar support for letting you do lists on all of these things but at least in the first cut for now it's just the permissions are a list everything else is single so for now you have to write multiple allow rules if you need say multiple object classes obviously you could write a native cascade wrapper function that would allow that and we'll we'll add some extra sugar at some point so yeah and then the curly brackets at the end obviously would be the contents of this function in the allow case this is a built-in function so it doesn't have any cascade contents it compiles directly down to a still allow rule annotations so a cascade supports all of the things we've talked about so far all the declarations and the statements everything can be annotated so what is an annotation an annotation provides additional metadata about various items that can be used by tooling and by tooling i do mean very generally and broadly now obviously right now the only tooling that exists is the compiler but in the long term we would like to have you know various cascade aware pieces of tooling maybe some of the current tooling can be expanded to be cast get aware in some cases I think we'll write new tooling and anytime we want to have some piece of tooling understand something about cascade we can pass that through in an annotation so so far we've implemented four annotations the associated associated call I'll talk about in a little bit alias is the way in cascade to provide type aliases just a different name for something we also have alias symbol functions which I don't think exist in anything currently so you can provide a new name for a function this is cool for like if you want to refer to directory reads as either read or list because both terms have been around you implement one function you alias it to list make list controls the ability to coerce things into lists so by default kind of under the hood for you permissions are declared with make list so that if when you pass if you want to say allow something something something read it'll coerce that and do a list for you this is kind of one of those compile checking things that we want to say we want to do list coercion to be nice but we don't want to like do it without you kind of opting in because it's a security language we would like to be very predictable so if you intended to pass a list and you can put this on anything and it will get automatically convert coerced into a list if it's used in a list context we've also got some planned ones I'm actually glad to see I put derive and plan I thought I'd put it in currently implemented but I don't actually have a pull request open for it yet it's work in progress I was working on the plan on the way over here and it's almost done derive is the ability to automatically derive your apparent your parent functions it takes a couple of arguments one argument is a list of which parent functions you would like to derive including an option for all if you just want to derive every function your parent has which I think would be the normal thing to use but if you want to say I just want to derive read and write or I want to manually list every function that's up to you the second argument is a strategy argument and so that's a you guys may be familiar with the diamond problem and multiple inheritance the diamond problem is just if I'm a child class I've got two parents and they both provide different implementations of say a read function then how do I know which implementation to use and in traditional programming languages this is a very hard problem we have one huge advantage here in the selenix is broadly not ordered dependent and so just do both is a really reasonable option because it doesn't matter what order we do both in which is why that would normally be a problem so one of the derived strategies available is the union strategy where you just union together the permissions in every parent function and then you also have the option to specify a particular parent name that if there's a naming conflict give me these parents functions if there's some other strategy you're writing cascade and you're like oh I want another strategy let me know happy to implement more strategies there hint and ignore so hint is something I think is going to be really cool but it's very much vaporware at this point and the idea is that we can provide hinting about things that will be used by analysis tooling when you get an ABC denial it can pop up this hint that says hey this is access on say a temp file you probably wanted to create your own new derived temp file that's a you know your specific type temp file you probably didn't want to access temp directly and you can use these things for like you know hey this we think this permission if you encountered this kind of denial that's probably an attack like this really shouldn't happen I'd like to have hint support kind of machine readable and human readable things so that you could then plug that into some kind of incident response thing we'll see we need to flesh out the details of what hints going to look like the other one that we've talked about a lot is ignore which once we add compiler warning support which is also not there yet then ignore will be the way to ignore a compiler warning okay so resource association so it's a very common pattern where policies have some domain say ip tables t and it's got various resource files that are used by it ip tables temp t ip tables conf t ip tables exec t etc in your m4 based policies you'd have to do a whole template setup it's complicated it's confusing if you want to like automate this and so most people don't they just kind of manually do this every time at least in my experience in sill you can set this up via block inheritance that's lacking syntactic sugar and I think for you know someone coming into it going oh my gosh what's this sill block inheritance context concept it's a little kind of confusing so this is kind of a core feature in cascade that I think is going to be more usable for people is what it looks like so I gave the temp file example here you create a virtual resource a virtual resource is just a resource or a domain you can have virtual domain that does not result in a specific type instantiation on the system under the hood it becomes an attribute and so we have this virtual resource temp it's got a associated call which is in this case the manage call because that's what you typically want to do and the associated call every time we associate a resource with the virtual or associated domain with that resource rather then we're going to call that on our new derived resource so when we associate temp with my app it's going to create a resource an actual real resource not a virtual one named my app dot temp and then it's going to call my app dot temp dot manage for you for free and so this is basically we just say we've got this idea of temp files we want to be able to create new temp files and when you create your own new temp file you want to be able to manage it whatever that means you can define that yeah and so this associate you know this takes a list so you can associate multiple different things yeah so here's an example of what that looks like compared to reference policy so this is a pretty common pattern you'll see I've got you know my app I give it the domain type attribute then I declare various resource files associated with it like my app temp t give those the temp attribute etc and then I give out these permissions in the case of a temp file it's typically you know managing files there's in sim links you probably need to know like how I intend to use it right in a comp file it's going to be reading etc and then you've got your rules so in cascade we've declared temp other elsewhere we've stored the knowledge that what we do is manage temp files in the general temp file declaration so we don't need to repeat it every time and so all we do is associate that's actually wrong that should have said associate temp is what that should have said and then it would create the my app t.temp so sorry type on the slides and then we put our rules in there so it gets a lot shorter a lot of the redundant stuff is kind of carried up to generic implementations all right inheritance so we inherit using the inherits keyword and this creates a actual type that is associated with the attribute that is the parent so in this case we've got ip tables temp t that is a child of temp file so again typically I would say you maybe use you should create ip tables temp t of the association but if you wanted to manually create it the inheritance you could do it this way yeah so let's see inheritance has a number of effects so all of the rules from the parent get applied to the child everything rules to the parent gets applied through attributes and the functions the parent functions are required to be implemented right so this is a known interface that people can then rely on as they're writing other policy and if you would like to write those yourself you are free to do so if you say I don't really want exactly what my parent function looks like great and you can derive them automatically which I think will be the common case if your parent has associated resources you get your own associated resources that are used there so you can create like a a generic like application domain that associates various you know temp comp files that everyone needs and then your specific application doesn't even need to worry about the association it just gets a temp file and then we we call associated calls on those copies of our associated resources just like you would with any kind of association so I was told in a someone that was looking over these slides that that was the difference was confusing so I'm trying to clarify the difference here so inheritance is creating a hierarchy of types this domain is a more specific form of this domain so you know IP tables is a more specific sort of application resource association creates a relationship between domains and resources this domain owns this resource by the way when you're building like modules and stuff and saying okay this domain goes in this module all of its resources travel with the domain for free so I don't need to like enumerate all of the different things associated with the IP tables domain that goes in the IP tables module that just comes along for free and associations are carried through inheritance okay conditionals you guys may be familiar with this XKCD cartoon this could probably apply to most cascade terminology decisions that these terms are all kind of interesting and now I'm like I'm going to solve it all and now we've got new usages of the terms SCLIN is conditional terminology is kind of confusing because of historical reasons and there's there's bullions and there's tunables and tunables mean something a little bit different depending on if you're in SIL or if you're in reference policy there's reference policy compiled time macros I was going to like get a whole confusing chart of like here's how everything does and I was like I'm just going to make mistakes so it's complicated so in cascade we've got one kind of conditional and we're calling that a Boolean just to add to the complication of everything because now Boolean means something else in cascade than it does in actual SC Linux world cascade Booleans are either runtime setable or compile time setable so that means that if you have a runtime setable Boolean that is an actual SC Linux Boolean that gets passed through into your source and if you have a compile time setable Boolean then that gets compiled out you can mix and match those Booleans freely and the compiler will handle that for you and take out the compile time ones from the final policy if you're following along in the slides I uploaded sorry the slides not there I added it this morning so that's why you're confused okay flexible build system shout out to Angelina who's a summer intern on our team this year who's currently working on this and so this is this is work in progress as is the conditionals on the last slide if you download the latest and greatest cascade you're gonna go ah conditionals don't work actually you may not notice because they silently don't work which is the best kind of not working so build multi yeah so we want to support a use case where you have multiple systems to find in the same repository with really easy configuration in reference policy-based systems you got to add a bunch of gross shell script rapping around your build system to handle this we also obviously want to have support for building individual modules and we want to be able to really handle a clean dependency resolution I know I've struggled a lot with flipping stuff in modules.com and rest policy and seeing things break and fighting with it for days and it's pretty painful so hopefully we can improve that I'd like to improve optional policy support this is something I've chatted with a few people in the community about a few times I've got a slide on that later so anyways we're gonna have a pretty flexible build system lets you say I've got various systems this is what they contain I can build all of them at once I can build just one and Cascade will kind of handle all that for you nicely under the hood one thing we want to really focus in on is helpful error handling so currently our focus has really been biased towards making sure that if you've written valid Cascade policy it compiles correctly and so the errors are definitely a work in progress and I was looking at setting up a demo and generating some errors and I like generate an error thing I was like ooh that error message is really bad I don't want to put that up on the screen so some of our errors are really good I'm gonna show you one on the next slide that I'm a little proud of but generally speaking so far our errors are a work in progress but that's a really key focus area going forward and I'm like putting up all the bad things our errors are here let me put up here's an error in Cascade so this is it shows you what file we're in and what line number is on it points exactly at where the error was so this is a a one line file that says domain foo inherits bar and when you compile that by itself it says I don't know what bar is something I would like to add in the future that we don't have yet is the kind of spell checking stuff where it says oh bar did you mean bra or whatever because you have a type named that but in this case it says hey bar's not a valid type gives you a thing at the top so going back to the last slide one of the things that I really want to add is the ability to point at multiple code points I was just writing the error message yesterday for if you have a duplicate declaration I try to declare a function named foo and there's already a function named foo and then I was like well I can only point at one code point that's kind of worthless to be like this is a duplicate and you're like of what so that's coming very soon but not there yet but so generally speaking our error messages are inspired by rust error messages if you have written rust code you'll notice this looks basically just like a rust error message there's a library that gives us all this which is awesome and yeah so hopefully these guys are going to be really helpful and they support all these kind of hints that say you know this is what your problem is this is how you should fix it hand holds you a lot more the other thing is definitely a philosophical approach is that if the sill doesn't compile that we generate that's a cascade bug so reference policy will often spit out non-compiling sill and then you get all these gross sill warnings and so yeah our goal is to say we should theoretically if we're bug free we should never compile non-compiling sill code obviously we'll fail at that at times but that's what we're shooting for cross language interaction so sill gives us a lot of this for free and basically if you want to call into cascade stuff from another language say maybe a hypothetical not yet existing high-level language or existing ref policy or whatever we try to pass down as much of our information as we possibly can into sill so that you can call in via sill there's a couple of caveats and gotchas in there we can talk about offline if you want to do that we do need to add additional support in cascade which we haven't done yet but intend to for calling in to say reference policy interfaces or sill macros that are defined elsewhere outside of cascade like an extra in statement or something like that that is on the to-do list so let me jump over and do a really brief demo and wow I cannot see this at all so um I'm in my cascade directory I'm going to go into data policies and these are our test policies so far I'm going to run cast see is this big enough can you guys see it do you want me to get okay I'm saying not it's cool I don't know there's a lot I can do about that unfortunately okay cool um here's a here's a brightness button I don't know if that's going to help at all okay so um cast see you got a nice help string tells you there's not a ton of options so far we're working on that but it generates by default out.sil as it's generated file and let's compile something and show you what it looks like so I just compiled this is associate.cast which is one of our test files it tests the resource association feature it's got a bunch of cascade policy in here and then when I ran the cast see we generated this out.sil file so where are we in the file as you'll notice at the top I didn't write anything about object classes and permissions cascade did our full kernel set of object classes and permissions at the top there's a bunch of stuff that's required to have a compliant policy that cascade kind of put in all this boiler plate for you you get down to the bottom and I wouldn't expect users to generally look at this too much but we got domain and resource here and then we start actually saying and these are the things that we actually declared in our policy and this is the still compilation of the policy that we wrote it's not necessarily very structured still but it's also generated so it's not really intended to be human readable it's intended to be easy for a compiler to generate oh so the other thing I was going to show while we're in here I think let me show you an error let me show you an error message I think is the other thing I want to do I'm just going to do some other stuff but I think we're short on time so I was going to do this one and you can see this is what error messages look like so in this case we said that it foo inherited I can't read this at all it's not bright okay so foo inherited foo parent but it was required to implement foo funk as a result of inheriting foo parent and it didn't do that let me you can see what the the cascade here that generated this error looked like so in this case foo parent defines some function named foo funk and foo inherited it and did not derive or override foo funk and so the users of foo would expect because this is a well-defined interface that foo wouldn't hear it would have a foo funk function and so we get a compiler error that tells us hey we didn't do that okay so that's the end of my very brief brief demo for the sake of having a demo if you would like to try it yourself you can download the github repo also and build from source that's really easy just cargo build you can also get it off of crates.io so if you have cargo installed you can run cargo install sce linux cascade and the name cascade was already taken then you run cast-c you give it your list of source files and then I didn't show I guess let me jump back to the demo really quick once we've built this out.sil file we can then compile it with sce sil-c I do hope that at some point cascade will just do this for you under the hood but right now you've got to run that manually so you can see we got that policy.32 file there which is obviously my sce sil-c is a little bit older it's not generating policy.33 yet but we generated our full system policy we could install that on a system and then watch our system very much not boot because this policy is not really defining what we need to have our system it probably would boot in permissive mode actually but I would certainly not build boot in enforcing mode we'd have to relabel and we don't have any file context statements in our policy so um yeah try it out yourself and have fun all right so I got about five minutes left so I'm going to try to blaze through these future plans pretty quick try to leave a moment for questions at the end so this is kind of where we would like to go so one thing I would really like to add in is better file context support so file context take regexes and types to associate with those regexes and a little bit of other stuff but that's the the bulk of it the thing is these regexes represent paths so if we actually treat them as paths that embed regexes that can let us evaluate our runtime logic a little bit better and say hey you know this this regex can never be applied because there's another path with a more specific regex or you know this isn't possibly a real path like there's no path here that evaluates this way I would love to you mean we use a kind of very small subset of regex patterns and we need it but stuff like .star that we use all the time we can maybe just make that some kind of generic so I think that can become more usable and also oh yeah compile time expansions of so things like what's a good example here um if we want to say that we we want to have something apply to like specifically just files and directories but not simlinks in the current policy languages for that so I think it'd be very reasonable to like take a list for of what object classes you want this to apply to and then expand at compile time into multiple file context to get some more flexible support optional policy I have complained about optional policy quite a bit lately so optional policy is a functionality that's supposed to say if I have a some kind of type that it definitely needs certain access and there's other access that if certain policy is present I should have access to that policy if it's not present that's okay don't break the problem is that's a wonderful intent but in my experience what actually happens when policy developers write this is this is a way to make the compiler happy and so our code doesn't end up reflecting what our tool actually needs to have versus optionally can have it ends up reflecting the particular environment how my compiler was set up when I happened to compile it which makes our policy a lot less portable and a lot harder to change things if my actual policy situation changes and now I took out some module that should have been optional and things are breaking because those things weren't marked optional so one suggestion and this was suggested to me by someone in the community and sadly I forgotten who it was so I apologize to you whoever you are one suggestion is to say that all of our rules by default would be optional but we can opt in with maybe an annotation for what's required so you can see annotation up there then we have this apache.conf.read that would just be optional if apache goes away that's fine the rule goes away but then one use case that we really do want to have is have a block of rules that are optional together and so in this case we've got this hypothetical example that if squid which is a proxy is present on this system I want to call this squid debush chat function and I also need sysadmin for whatever reason right because squid's present I use the sysadmin capability so if we just have every line be optional by default then suddenly sysadmin is something I have unconditionally when I'd really rather not have it if squid's not present I know I need it in that particular case but I don't want to have it because it's really privileged obviously and so have the ability to have a block that says these things need to be optional together in this example here I've written in like an explicit like optional based on the presence of squid rather than existing languages I think infer optional based on what's in the block I think the explicit might be clear so this is an idea I have a boff session at 4pm and this is one of the key things I would like to discuss that I am really low on time so I'm gonna keep trying to move okay so integrations with other security mechanisms is something we've talked about our focus for now and for the next six months to a year is definitely SC Linux first and foremost is our primary thing but at the end of the day we've built up this security model to describe our system and there's no reason we couldn't supplement it to output other security mechanism so I have a hypothetical example of what an IP tables thing might look like that when I declare this port type in SC Linux I have a port con rule that associates it with certain ports that should do with a semi colon sorry just throwing this slide together last night and then we maybe annotate it to say hey I'd like to generate an IP tables rule and then in addition to my still output I could have some IP tables rules output along the sides I had a very brief conversation yesterday with some of the IMA folks about whether we could use this for IMA policy I don't know could we use this for sec comp policy probably not I'm not sure so but this would be really I think an interesting area to explore going forward delete so we've always for a sense before I was involved in SC Linux people have talked about delete as something that I want to be able to delete rules I'm not going to go into all the complexities and it gets weird and complicated and what do you mean and there's a user expectation thing about hey why do I have a denial for this I can see the allow rule I'm looking at the allow rule here not being aware that that allow rule was deleted elsewhere there's complexities there's an idea for like a local delete that wouldn't need any sill integration and would work locally in cascade that might be sufficient for cascade use case but I need to dig more into exactly what cascades use cases plus what broader people in the community want out of delete that's something else to maybe discuss in the bof all right I do want to land on this this is my last bit here audit to cascade so there's a tool called audit to allow that is widely misused and also widely used and the problem with audit to allow and including audit to allow dash R which generates your reference policy interfaces is that adding allow rules is seldom the right answer now right is very context dependent it might your mileage may vary but often you want to change code you want to fix labeling issues a lot of times you want to rerun in permissive mode if your denial says permissive equals one it was the first thing that blocked and you're probably just going to add this allow rule and rerun it sometimes you want to don't audit these things we've been noticing a lot in our environment system D really wants to claim it needs cap net admin and it normally does not need cap net admin and that would be a good hint thing right to say hint you don't actually need cap net admin probably right maybe you want to worry about an attack right if you get in this pattern of every time I see a denial I'm going to blindly allow audit to allow and deny it well there's your path for the attacker to get past your sce linux policy just wait a little bit after for you to allow their attack pattern and so what I would love to do is audit to cascade is to say we've got all this a lot of information about policy intent we've got documentation comments eventually and so we'd like to make a kind of pluggable heuristics engine that looks at ABC denials and gives it a little bit more thought in a machine sense right it follows some kind of heuristics to guess which of those previous things is most likely to be the thing based on your specific denial this would require probably passing a lot of our policy information through is some sort of debug symbols that would end up landing on your target system whether that gets in in sill in the policy binary et cetera or whether that lives in a separate file we'd have to figure out expose all of our cascade documentation directly in audit to cascade and so then what you can get is hey I'm a developer I know nothing about sce linux let me run on to cascade and you get a whole write up about okay I got this denial here's what's going on let me tell you what each of these types are in human readable terms and let me tell you here's five different ways you could fix it in order of preference and if you want to just say I want kind of existing audit to allow behavior just give me something like that you know give it a mode for that that would use cascade functions so that's that's I think the number one place that I'm interested in going with cascade is to be able to kind of add that sort of support I think the base policy language is the platform on which to build that and because the base policy language is built as a library this tool actually can just live on top of that library directly parse your cascade policy and it'll be relatively much easier to write as a result so if you want more info here's my email address again here's the cascade github I would highly recommend if you're looking to learn more about it there's a read me in the cascade github the change log will give you and the roadmap gives you like the really nitty gritty details of what that I just said we do we actually do and what we just said we do I have a pull request open for and we got a docs directory that goes into more detail on how you use the language so thank you very much for your time I'm two minutes over any questions in your negative two minutes yes yeah so that's a great question the question was you know we've got a lot of policy already is there a plan for migration and interoperability with existing policy so I did talk briefly about interoperability I very much want to add some kind of like extern support for cascade so that you can have right cascade modules to inter plug with your existing policy and that's something that's on the plan and we're going to do in the near term and then in terms of migration path I've had a few discussions with some people at Microsoft about automated tooling to migrate policies the the challenge there is that you know with there's a few places where I kind of we kind of go I really would prefer if you write your policy in a much more cascady style rather than kind of blindly migrating it so specifically what that would look like is unclear we already have a couple of non-public yet shell scripts or Python scripts or something that does a little bit of automated migration I think I haven't worked on that directly but yes we would like to have automated migration things and a migration pathway is something we definitely need to have I think so I don't have a great answer yet but I need to so we're working on it hopefully that was helpful great any other questions in the back yep have a virtual question great what GUI programs are helpful to write SE Linux policies and show dependencies sometimes we have some issues with SE Linux policies for Android and edit it in notepad which is very painful and how do you debug SE Linux policies and runtime without audit logs those are a couple of big questions so I guess I don't need to repeat that because that was just said over a mic so the first question is what GUI tools do we have there a long time ago was an IDE plugin for Eclipse called Slide I tried running that on a recent version of Eclipse and it didn't work so I think it's pretty unmaintained at this point other people would probably better people to ask for me I'm not aware of any kind of GUI IDE plugins for SE Linux that are actively maintained and used at this point that's something I hope to change with Cascade because we're building Cascade as this library should be relatively easy to write a really featureful plugin for an IDE but that's not something we have yet so stay tuned in terms of your Cascade policy I think I'm going to maybe decline to take the debug policy denials without an Android question just because of time and it's not necessarily Cascade related so sorry I recommend emailing the SE Linux list for help with those sorts of questions so sorry people who will respond to that on the SE Linux list if you didn't want that question all right I think I'm over time so thank you guys very much for your time