 As you know, this is the microkernel and component-based architecture-ish room. So I'm going to talk about microkernel. As can be expected, I do not know everything about that microkernel. So if you have questions, feel free to ask them. If I look stupid and then try to, when I try to answer, don't be surprised. So what's Redox? Redox is a microkernel. Yeah, big surprise. It's written in Rust and one of the leading objectives was to not compromise on safety. Also, an interesting thing about the design of Redox is that we are trying to be unics. Most of the microkernels I know of, not all of them, are trying to be not unics. They are trying to be their own thing, which is entirely fine. We went in the direction of trying to be kind of unics, not entirely unics, but kind of unics. What does this mean? It means basically that everything is a file, not necessarily a file based on disk, but it's a file. It's current state. It runs on existing hardware. I actually don't remember the list of architectures, not many of them, but at least x86, 64, and ARM. I don't remember the version of ARM. It's a clean slate implementation. As many projects around here, it's young. I don't remember exactly when it started, but I'm pretty sure it's less than one year old. So expect that more than one year old? Okay, fair enough. So the repos are less than one year old. So anyway, expect that there are steel holes in it. As you can see from my lack of knowledge of the history of Redox, I'm less than one year old in that project. As I say, it's young, so things are missing. It's fulfilled enough that there is a bare-bones browser working on it in graphical mode, but it's still pretty bare bones at the moment, and it's MIT licensed. I've gathered the list of about 40 contributors. I'm probably missing a few, but that's roughly the number of people who have contributed to the project. So just, yeah, it exists. It exists. You can take screen captures of it. The best demo being the web browser, but I'm not going to give it today. Too many changes of me screwing things up. Okay, so this is the microkernel room. I don't know whether people are here because they know about microkernels or because they want to know about microkernels. So just in case, I prepared a few slides for people who want to know about microkernels. I'm not going to say much about them, but I'm going to explain to you why microkernels are cool and in particular in the domain of IoT, which interests me. I mean, that's why I have these t-shirts. So the idea of a microkernel is to remove as many things as you can from the kernel and put it in user land. So regular processes. Some microkernels are extreme and managed to remove even memory and any kind of memory allocation from the kernel. We're not that far. We might reach that far someday possibly, but we're not there yet. In particular, this means that file systems are not privileged. They're just regular processes. Drivers are not privileged. They're regular processes. Some parts of the notion, the very notion of security can be processes. And microkernels are cool. Microkernels, I mean, there is of course the fact that microkernels are obviously cool. If you can remove something from a place where it's privileged and put it to where it's not privileged, of course it's good. Why? Well, one of the reasons it's cool is actually because you cannot upgrade your smartphone. I mean, most smartphones have, it cannot be upgraded for more than a few months, maybe two years. Why is that? They are, I think every single one of them based on a monolithic kernel, which pretty much always needs to be patched. I mean, unless you're Apple and you own the kernel, you are running a custom kernel because yeah, you probably need a patch from this version of Linux and another one from that version of Linux. They're not together in the upstream version, so you need to customize it. Also, you have an extremely exclusive licensing agreement with whichever manufacturer and you have some new camera, or maybe it's not a new camera, but it's just a camera that's not supported by your kernel. So, you need a device driver that's somehow not in the kernel. At this stage, you have lost, unless you are willing to hire people who can manage to get your code upstream. And that's a pretty smaller community than people who can put things together because typically you're going to write patches and they're going to stay in your custom version of the kernel, which is kind of okay until the kernel evolves because sometimes kernels are patched by upstream. That happens kind of often. If you need to deal with your patches and the upstream patches, okay, you have reached the stage where you need someone full-time just to deal with resolution of these patches. No, the drivers evolve in ways that may or may not be compatible with these various evolutions of the kernel. You have security issues of your own and pretty soon you need to become a kernel maintainer. You need to maintain a kernel maintainer for your device. That's true for smartphones. That's going to be also true for smart fridges, smart scary stuff that is looking at me when I'm taking my shower or smart whatever. You have a problem. I mean, okay, if you're a big company, you can do it. But if you're a small outfit, if you're a startup, if you're doing this on your own, if you want to provide support, you have lost at some point. You're not going to be able to track upstream patches and combine them with your patches. It's just too much effort. So one of the reasons why micro kernels are great is that they make things, these kinds of things possible, just the fact of tracking upstream fixes. So in the world of IoT, it's not necessarily just IoT, but that is exacerbated in the case of IoT. Oh, by the way, just one quote. A few months ago, we had the presentation, we had the Linux kernel recipes conference in our office in Paris. And one of the things they said, they are very aware of this problem. And one of the things they said is, the only reasons for which we do not have widespread attacks on smartphones at the moment, or smart devices at the moment, is that people throw away their smartphone faster than people write verses. That's a pretty bad reason. And that does not scale up to fridges, because the lifetime of your fridge is slightly higher than the lifetime of your smartphone. So back to micro kernels. Why are micro kernels great in that context? Because anything you have customized, okay, maybe not anything, but there are very good chances that the things that you have customized leave out of the kernel, they leave in user land. And suddenly things communicate using APIs that do not break when you upgrade something. So you can upgrade independently, the kernel, the drivers, your code, without friction. This has effects on live patching, too. And also this has effects on safety and security. And there is another reason, which is actually cool, too, is that since your kernel is small, since you can pretty much easily pick what you put in your distribution, well, you can probably trim your distribution to something small. I make no promise here, but that sounds reasonable. So other reason for which micro kernels are great, in terms of safety and security, micro kernel means that you have a much smaller trusted computing base. The kernel is easier to read, to audit, to check. It's easier to run static or dynamic analysis on it. And in many systems, the worst that can happen to your security is if your kernel is compromised. Since you have moved many things away from your kernel, a compromise in a driver is not the same thing anymore as a compromise in the kernel. Same thing for file systems. Even better than that, a compromise in a driver is not the same thing as a compromise in the file system and vice versa. So you have isolated stuff, which makes it much harder to attack, to grab a foothold in your system for an attacker. Also, having clear separation in processes means that if you invest in this, as in if you spend time tweaking your operating system for that, you can actually track more easily things like, how did the attacker break to the system? What did it compromise? What do I need to shut down? Can I survive away with shutting down these parts of the system with rebooting them? Can I track the taint of the attack? Okay, that was all about micro kernels. Let me tell you why Rust rocks. I'm trying not to make too much propaganda, so let me rephrase this. Let me tell you why Rust is a good candidate for people who are interested in writing code at the level of a micro kernel or generally operating system development. Rust is a new programming language. It has reached version 1.15, I think, this week. It's designed to be both safe, fast, and high level. Fast is one of the reasons for which it's fast. It manages to have zero-cost abstractions in most cases, not all of them, but most of them. I'll show you an example soon. Zero-cost safety in many cases, so safety is enforced by the compiler, by static analysis in really many cases, which saves you from having to implement things in your code, which also saves you from forgetting to check things. The objective of the Rust team is to provide an alternative to C++, not necessarily to C, but to C++ for a broad range of programming applications. Again, not all of them. And one of the nice things is that the compiler can be scripted to pretty high levels, which means that, for instance, in theory, I don't think that anyone has done it yet, but you could implement things like address space randomization and things like this in the compiler, which is also good for security. So here is a quick example of zero-cost abstraction. This, a bit contrived example. So we take the list of integers. Do we have some kind of pointer? No. This takes a list of integers from, yeah, not good, just succeed. Thank you. Ha-ha! Ha-ha! Ha-ha! List of integers from one to 100. Keep only the odd ones. Sorry, the even ones, sorry? One to 99. Fair enough, one to 99. Then divide by two everything, and then print them all. So not a very interesting example in super say, but if you disassemble it, you essentially realize that these lines take zero assembly instructions, and this line is basically the entire loop that runs this and that, which among other things means that there are no memory locations here, no hidden costs, and the four function calls are pretty much the printing stuff and converting a number to a string, and then displaying stuff on screen, which is pretty good. I mean, you can of course reach the same result in C, but having abstractions when you're using them correctly is very useful. Very short example of safety. It's pretty common to have process IDs in kernels. A process ID is typically an integer. If you use integers everywhere, you can screw this up by, I don't know, doing pythor arithmetic by accident on process IDs or whatever, anything can happen. So many programming languages, I mean, pretty much all programming languages provide at least some way of encapsulating your PID, of not addressing this exactly as integers. Well, this is how Rust does this. So the interesting part being is that this operation increment, which actually looks like it's creating a data structure to get a new value of the integers, is actually compiled exactly the same way as a plus equal one would be compiled in C. So the compiler will tell you if you mistake a PID for a general integers, but it's actually going to generate the same code. Again, you can do this in other languages. Rust is convenient, it makes this easy, but it's definitely not the only languages that will let you do that. Another example, this is an example of allocating a pointer. So this box new allocates the simplest kind of pointer in Rust, we put 42 in here. And in some case, we deallocate the pointer. The compiler will refuse to compile this because it's telling you that this value, the pointer, has actually been, so the term in Rust is moved. So drop, which has deallocated the pointer, has actually eaten the pointer. There is at least one path that has eaten the pointer, so this function called this expression makes no sense. And the compiler is going to reject that expression. And the same kind of mechanisms work very well to discuss thread safety. Here, you have located the same pointer and you are changing it in another thread. So in this example, because nobody else exists in the world, that might work. But in general, that's probably not good because who does this pointer belong to? Does it belong to this thread or to that thread? So you can specify that it belongs to the thread that you have just spawned, in which case the compiler would let you safely use it. So you have allocated it on one thread, but then you only use it on the other thread. That's okay. You have a zero cost here. You don't need a mutex or anything. And it's going to let you run your code. Of course, if you try to use it on the thread that has allocated it, it's going to tell you again, sorry, this has moved. This has been eaten by the thread. So please rewrite your code. You could, of course. There are also shared pointers, et cetera, but if you start having side effects, you will need a mutex or an atomic value, which is exactly what you expect. Okay, back to Redux. As I mentioned, so microkernel is all about moving things in user space. This being Unix family operating system. Well, everything is mostly a synonym of file systems and files. So, not very nice. As in many modern Unixes, you can have several file systems coexisting in the same world, on the same system. Redux supports this by plugging file systems. So the difference between, the main difference between this and say what happens in most Unixes or Linux, is that each file system is explicitly, sorry, each path is explicitly prefixed by a URL scheme that tells you which of the file systems handles this path. So, maybe you're interested in a file that's what people commonly call a file. So something that's on your hard drive. So it's the file scheme. Or maybe you want to pipe. It's a different scheme. Or maybe you are looking for the random number generator. It's a different scheme. Each of these schemes is implemented by a process. I mean, you could write a process that implements several of them, but that probably doesn't, well, what could be? That could happen. So, plug your processes in user space. The kernel itself tracks file descriptors. So it guarantees that file descriptors cannot be forged. It helps you, it issues fresh numbers for each process. It knows what each number, sorry. If you close, if a user land process closes a file with file descriptor 52, 42. It knows, ah, 42 for this process is implemented by that process. So it basically routes these calls to the corresponding processes. Most of the sys calls in Redox are actually implemented by a simple route to the, sorry, a simple check of memory and then a route that are routed to the implementation of the file system. So, again, the kernel only handles pretty much descriptors, registration and dispatching. Everything else is implemented by each process. So the actual notion of path can be widely different from one process to another one. Everything that's dealing with access control is implemented by the file, by the schema, sorry, so by the implementation of the file system. And that works nicely. So, if we look at drivers, no. So just as we have pluggable user space file systems, we have pluggable user space drivers. The kernel itself, basically the only thing it does is address mapping. So, as in, I want to use to map this physical address which corresponds to this physical device. And I want to be able to read and write it. That's basically all that the kernel does for drivers. And then there are interruptions. But since everything in the framework is a file, interruptions are just a file system. Drivers themselves, everything is a file. So a driver is a file system. So if you want to access the graphics card, you're going to use your, currently your visa file system to send instructions to a graphics card. Having everything as file system simplifies the life in a number of cases, such as not needing to introduce gazillions of new syscalls. We have simple tracking of who's using what again. One abstraction, having just one abstraction makes things easier. One of the things we are interested in, and that's, I'm working on this at the moment. So it's very much not landed yet, is capabilities. So quick overview of capabilities of, sorry, of capability-based security. So just for people who know about POSIX capabilities, that's not the same thing at all. Just happen to use the same name. The notion of capabilities is something that actually comes from programming languages initially. So a security capability is the affordable right to do something. Typically in a programming language, well, in an object-oriented programming language, you're going to have objects with private fields. And the capability to access something is if you have a handle on one of these objects, and there is a public method that lets you somehow affect the private data, or read the private data, then you have the capability to read that private, or to write that private data. Or if you're not doing a programming language with objects, but one with closures, exact same thing. Capabilities, you can use them to do something. You can, it's quite important, you can share them. So as soon as you have the ability, sorry, to read that data, well, you can read that data on behalf of someone else, and you can possibly give that ability to the other person. You can use it, you can share it, you can of course stop having it, and you can possibly weaken it. Maybe you have the ability to read and write that data, and just you want to only keep the ability to read it. That works too. That's the kind of thing if you need to implement this in a programming language, in whichever is your favorite programming language, you'll manage. If you want to use the, to do this in your favorite operating system, that's harder. There are a number of operating systems that offer capabilities. Several of them have been discussed today in this room. They're not that many of them in total. Oh, sorry, forgot. What's the point of having capabilities? The point of having capabilities, if you look at it from a point of view of safety and security, is that pretty much anything can serve as sandbox for anything. If there is, in other words in programming languages, if there are no global variables, but only local variables, then the function you're calling, if it does not have access to any global variable, there are limits to how bad it can behave. It cannot have side effects in safe language that are not on the arguments you pass to it, or you have some hope as to it. It's critical if you want to analyze the behavior of your code, both statically and globally, sorry, both statically and dynamically. And again, I mentioned that having a microkernel could help you with looking at tainting of compromised processes. Well, that's here also the same thing. The more you make dependencies explicit, the more you can analyze tainting. So in the Unix world, typical Unix implementations do not have these kind of capabilities. The closest thing you have is file descriptors, but then any of my applications by default, I mean, Unlinux can read any of my files. So that's a very, very broad capability. Restricting this is pretty hard. So there are attempts to make things finer, but the only implementation of capabilities, the only full implementation of capabilities for Unix that I know of is Capsicum, and it's pretty sophisticated, and it is all the entire network, the entire sorry kernel of Linux, or I think it's free BSD. One of the BSDs, I'm not sure which one. So let's look at how we could implement them in Redux. I mean, there are patches, well, there have been several prototypes, but nothing landed so far. So in the world of Unix, everything is a capability, great. Sorry, everything is a file descriptor, great. So a capability is a file descriptor. The file descriptor that opens readme.txt is the capability to read in that file descriptor or to write in that file descriptor. But we can extend this. Since, well, since Redux has a pretty open interpretation of what a file, what a path is, the idea here is to introduce path and file descriptors that represent the authorization to do something. So for instance, this path, so file, my directory, start.txt, read, well, it's a glob that says I have the authorization to read all the text files in this directory. That's something that would be interpreted by the file system. So not part of the kernel. So far we have not patched the kernel at all. Well, we actually have one patch, one patch which tells the kernel here. I can open this file because I have that capability. So this is using a capability or weakening capability into actually doing something. The only patch in the kernel at the moment is just rooting that information and checking that the file descriptors match. The file system is in charge of ensuring that this policy is a proof that you can do that. Again, delegate as much as possible of security to username. Then of course, we have the problem of distributing these capabilities in the first place. And for this, we introduce essentially a variant of pipes which currently have the name cables. And a cable is used to drag a file descriptor across processes. So that's something that you can do in POSIX using sockets. But this is a much more restricted version that also doesn't require your privileges. Trivially, you can exchange file descriptors with your children if you have a cable established. And well, since everybody is the child of someone and everybody is somehow the sibling or the cousin, et cetera, of someone, if you want to introduce a communication from point A to point B, if everybody in the path agrees, you can get one. Might take a few steps to establish the initial communication, but then after that, you have direct communication. And this, so I mentioned that we are, there are many things that are not implemented yet. So we do not have a full IPC yet, but this would probably be the first step of our IPC, at least for establishing the IPC. Okay, so I'm going to start wrapping up. So, Redux, it uses a microkernel to reduce the TCB because we want to be safe. It uses Rust to make the TCB more trustworthy because we want to be safe. There are many things to do left, and if you want to help us, you can find us over there. Thank you for having listened. And if you have any questions, I am over here. Yes? I'm sure correctly everything is file based in the interrupts. What is the performance, the speed, and is it tied to the VR heart? So, as far as I know, nobody has benchmarked it yet. I'm not optimistic, but I know that some people are optimistic. So, you get, you have all the information I have now. Yes? How do you manage the final column namespace? I mean, can a user, a simple user, invent another name there? How is it managed? So, if your route is easy, you can do anything. So, there is an implementation, I don't know how final it is, in which any user can locally, for the children of a specific process, install an implementation of a file system. So, you have a local implementation of a file system. Because all you know how to do is just attach, instead of having a specific name space, just use the file system. Sorry, I didn't hear you. You just use the file system name space, that is the user can attach to his phone directory or his file directory. It's much simpler, actually. In what, sorry? In what context? I missed half of your question, sorry. In Concern, what we do is that users attach to their phone. Yes? So, it's attached to your user instead of being attached to a process, is that what you're saying? Yes, what does it change? It means that you don't have to manage anything. But here, we want to be able to manage things. That's the thing. Yeah, I mean, it's just the same as home. Okay, so that specific example is home. But you could, of course, do something entirely different. You could, so are we still talking about installing file systems or are we talking about... Running your own file system. Oh, what is the reason? Okay, so for instance, let's say I change my hat and return to being a Firefox developer. Firefox, as any basically kind of operating system running inside an operating system, needs to be able to sandbox things internally. So, the boundary is not the home file system or the home directory. The boundary is things that can run on the web, things that can run as add-ons, things that can run as the browser, and these are entirely different boundaries. So, you typically might want some of your web stuff to access the font directory, for instance, for reading, but possibly not all of the web stuff, things like that. So, you want something extremely fine-grained. So, I think that Hertz has something for that, but I'm not sure. Yeah, okay, you're doing your jail. Is that it? Yeah, so that's a higher... It's a more heavy-handed approach in your case, which, again, it works. So, we're trying to do something more flexible. I believe that jails are more flexible. Oh, that's quite possible. Actually, I believe that we can implement jails using that, too. So, I'm not sure that maybe they're just equivalent, but we can discuss that offline. Yes? I suppose Rust has some kind of runtime library for support. So, yes? So, Rust has at least three... Not for the moment, too, but there is a third one distributed, layers of how much you can build in. So, you can either put the full kitchen sink, I mean, the full standard library, or you can get only the core library, which is designed for embedding, which is what we're using. And there is a proposal for something even smaller than the core library. But... Oh, nice, nice shade of blue. There are proposals for something even smaller. I don't think it's implemented yet. I don't think they have a fixed list of what it is. But the... I mean, I know people who actually do embedding with the embedding library. It works. Does this answer your question? Yeah, I guess. Because I could not give you the number of lines or anything. So, Rust, basically, the Rust compiler has something like a C compiler's freestanding mode? Something like that, yes. Yes. So, that's basically the difference between the core library and the standard library. But there is something even smaller than the core library, and I don't know... Don't remember exactly the difference. Maybe you want to provide your own preview. Exactly. Random. I forgot the question. Yes. There are many distributions with trace on Linux. Yes. Is there a chance to open up this possibility for write-outs as well? We are at version 0.0.7. So, yes, of course. So far, I mean, there is the Redux kernel. You can use the Redux kernel but there is the Redux kernel. You could put anything on top of it. We have a number of utilities on top of it. I don't think we have plans that go quite that far yet. I think anything can be changed at that stage. If you want to download an ISO, it's going to come with a few standard stuff, of course, but that's the best answer I can give you at the moment. Sorry, there was someone here. That's a good question. So, I actually have been out of touch for one month, so it's quite possible that everything has changed in the meantime. But there are things such as... So, going further into jail or capabilities or things in that direction, there are attempts to try to reduce the size of the kernel, micro kernel further, and reduce the number of syscalls. For instance, there is some magic involved in pipe at the moment, and we like to get rid of that magic, things like that. There was something else important in that direction. I don't remember exactly what... There are people who want to work on getting rid of memory allocations inside the kernel. I don't know if they are actually going to work on this, but they said they are interested. That's one direction. The other direction is we want to have a full-featured web server in Redux. And we are pretty close to this, actually, because we already have all the IO layers. Maybe it has been finished in the last month, I don't know. I mean, I think the person who wanted that told me and who's our benevolent dictator for life said he could have something done at the end of March. Maybe it's done already, I don't know. So these are the general ideas. Yes. All the platform stuff is well-asulated, so I know that it's supported on several platforms already. I have not even looked at these directories at all, so I cannot tell you the actual difficulty. I know it needs an MMU, things like that. I don't remember what MIPS has. I think MIPS has an MMU. MIPS has, I think MIPS, I mean, I haven't used MIPS in 10 years, but I think MIPS has everything that's needed, so I don't know. It has atomic operations, right? So I think that's all that's really needed. So you have my best guess. There was a question over there. I have two questions. What is the follow-up to the previous discussion? Will you at least roughly quantify the ratio between the kernel code written in Rust and the code written in something more or more like, I don't know, C or Ascender? Oh, that's very easy. 100% Rust. Oh, I mean, okay. Sorry. No, there isn't the architecture part. So it's like there are five files or something written in assembly. So no C in between? No, no C in between. No, no. Rust basically produces C code, so there is no reason to do C. The worst case you can do if you really want to do Rust is put everything, annotate everything as unsafe and actually write C code with Rust syntax. My second question would be maybe a follow-up. There have been some historical systems like Plan 9 or New World that have tried to push this Unix because everything is a file to the limit. So have you taken some inspiration from them or you are just going your own way? So for the most part, we're going our own way. We sometimes do read papers from other stuff, but it's mostly the idea, mostly we're... Let's not hide it. This is an open source project. We're having fun. So the objective is not to do the same thing, the exact same thing as someone else. We can draw inspiration, but that's... We're trying not to do the same thing. Thank you very much.