What kind of security abstractions over capabilities are sufficiently orthogonal and pervasive as to fall under BuildInPervasiveAndOrthogonalAttributes? * PermissionFlags, which includes ** Revocation * Versioning (see GarbageCollectionUnderVersioning) ---- From PermissionFlags '''How many legitimate variations on permission flags can we expect?''' Building an additional layer of security abstraction (proxies) above capabilities is pointless because there aren't any legitimate alternative permission flag schemes. There's only one scheme which is powerful, secure, simple, elegant, coherent and self-consistent. So it might as well be sunk into the lowest layer and forgotten. ''In most cases, there are several variations of the abstraction that make sense. The point of inventing an additional layer is to avoid baking in a particular policy at a low level, i.e. to separate PolicyAndMechanism. I've also been thinking about this intensively for years on end, and I am absolutely convinced that there are several useful variations of each of the fundamental abstractions at the level we're talking about (revocation, versioning, permissions, etc.)'' Then you don't have a very good imagination. I have difficulty coming up with one policy that's completely and totally self-consistent ''in all circumstances''. The problem is that I can imagine a lot of circumstances. ''A system does not need to handle all circumstances. It does need to handle a range of circumstances that is too wide to be handled by a fixed set of policies specified in advance.'' Again, you simply don't have a very good imagination. While I can't come up with alternate policies to fit all the circumstances that I can imagine, I can come up with one. ---- '''On the necessity of standard permission flags''' If you don't build permission flags into capabilities, you can end up putting them within a higher layer, mixed in with stuff that's very different in nature. This is dangerous because the permission flags will invariably be unused because of laziness, misused because of stupidity and abused because of sheer perversity. If you don't build permission flags into capabilities, you can end up making very serious mistakes. The consequences depend on which of the many wrong ways you've chosen to do things you happen to pick. But they include: * ''ugliness'' due to having completely different abstractions (proxy vs raw reference) for different security concepts (limited vs unlimited -- see TwoKindsOfCapabilities) * ''difficulty'' due to making it complicated to perform a trivial and routine operation (switching from unlimited to limited) * ''fuckups'' due to when users don't understand your byzantine system and make mistakes as a result ''Careful design of the layering is certainly necessary. It's not a good idea to mix abstractions that will be required for the security of all objects with unrelated things, agreed.'' Standard permission flags are required for the security of all objects. There's no legitimate reason to avoid them. ''The question is not whether permission flags are needed; we agree on that. The question is simply whether they should be built into the lowest layer.'' * "having two different abstractions (proxy vs raw reference)." ''The layered approach does '''not''' have two different abstractions. It has only references. The fact that some references are to raw objects is only visible in the implementation of the security abstractions.'' * "making it complicated to [...] switch from unlimited to limited." ''Nonsense. From the point of view of applications, this is just a standard library function.'' * "when users don't understand your byzantine system." ''The two approaches look exactly the same to most users. They don't look the same to programmers who want to add or change security abstractions -- in your approach, they can't do that without changing the system TCB.'' [It is useful to have a 'standard' set of permission flags with common semantics and lower-layer implementation. With that much I agree. Standardization helps programmers know what to expect. However, I also think it useful that programmers or system designers be able to include their own ad-hoc set of permissions and check permissions at higher layers. This might allow the 'byzantine' insane permissions systems that RK fears, but it also allows for flexible policies to be developed as needed. Usefully, programmer-defined 'flags' effectively serve in place of environment variables that are implicitly handed down the communications pipeline (unless explicitly removed) to the objects that eventually consume them (see ExplicitManagementOfImplicitContext).] ---- From GarbageCollectionUnderVersioning Since refs are fairly high level objects themselves (they keep track of which versions of an object they point to) instead of just pointers, it makes sense that this is a CapabilitySecurityScheme. And not just any cap scheme but one with high level capabilities like GrandUnifiedCapabilities. And in that case, only 'override' (ownership) permission allows one to change a ref's reprieval condition. ''See BuildSecurityAbstractionsIntoCapabilities for a discussion relevant to whether GrandUnifiedCapabilities are actually needed for this. The range of options for versioning further reinforces my opinion that this kind of thing should be implemented in a separate abstraction layer by use of proxies. --dh'' Proxies bite. Especially so if you don't have true delegation in your language. ''Why do proxies bite? I agree that languages should have true delegation.'' Apparently you've never had to forego using the debugger because it blows up due to your redefining DoesNotUnderstand. And even when it works correctly, the fact that you've fucked with DNU leaves traces in the system. And that's not even mentioning the abstraction inversion that is using a high level mechanism like DNU to implement a very basic mechanism like delegation. ''That would be a broken debugger. I'm assuming a language with an object model specifically designed to support proxying (for example OzLanguage, EeLanguage, or JouleLanguage), and development tools to match. DoesNotUnderstand is intended as an error reporting mechanism, not a proxying mechanism.'' Do you realize how stupid it makes you sound to me when you slam Smalltalk? ''I didn't "slam Smalltalk"; I simply pointed out that DoesNotUnderstand is intended for error reporting, not proxying. Also, that any debugger that "blows up" is broken. The latter is an implementation issue, not a language issue.'' Oh, and for fuck's sake, stop inserting your comments into my paragraphs! ''No.'' In that case, this will have to be our last discussion. ---- '''SyntaxVsSemantics''' The FacetPattern is meant for special cases where the ''semantics'' of particular objects are concerned. It isn't meant for the generic case where the ''syntax'' of objects (the object graph that underlies them) is concerned. By semantics of particular objects I mean the particular factoring of objects in a component and the distribution of powers between them. If my hard_disk component does not export a HD_block object, there can be no security based on that abstraction. How to create an HD_block capability with the powers you want, that's all syntax. What the HD_block (as opposed to log_segment, or storage_object) ''does'' for users with a particular capability, that's semantics. ''In a capability system, connectivity constraints on the object graph can be enforced by static program analysis (e.g. auditors in EeLanguage), or confinement mechanisms such as the KeyKos/ErosOs Factory design, or dynamically using the MembranePattern, for example. Is that the kind of thing you mean?'' I hold code verification in contempt. It's an optimization detail that should be of no concern to OS designers. Instead, it's treated as if it were some fundamental security concept. Bleh! I do not refer to the membrane pattern because membranes are also fundamental syntactic objects little different from primitive capabilities. And to preemptively answer "what kind of syntax are membranes", they're NestedProcesses' syntax. Because processes are syntax and only components, the object graphs which processes export, are semantics. ''I don't see that NestedProcesses (similar to HierarchicalScheduling or the process model that was used by CapOs), have much to do with membranes.'' If you think processes have anything to do with scheduling then no you wouldn't. Because you wouldn't know what processes are. ''The term "process" has been used by many different systems to mean different things, but most of them had a lot to do with scheduling. If you mean something else ("protection domain", maybe?), then I suggest not using the term "process".'' The term process no longer means anything related to scheduling, except insofar as it refers to a protection domain '''plus''' a '''thread'''. Since I do not mean just protection domains, I choose to use the term process and choose it to mean a protection domain with relevant subprocess management machinery and ''zero'' or more threads. IOW, something that has nothing to do with scheduling. Get with it, the terminology's heading in this direction anyways. ''I never liked that usage of "process", since it conflicts with process calculi. To get back to the point, CapOs had NestedProcesses in the sense you mean (way ahead of its time, and probably the hardware wasn't powerful enough to make significant use of this facility). From LevyBookCapabilityBasedComputerSystems:'' CAP's designers chose to use the process tree mechanism to eliminate the need for a privileged mode of operation. Each CAP process can control the addressing environment and execution of its subprocesses without special privilege or operating systems intervention. ''This is certainly a good idea. In a language-based system, it corresponds to "refraction" -- the ability to efficiently create recursive virtual machines to execute and reflect on subcomputations. However, I still don't see what it has to do with membranes. Membranes are an entirely different mechanism/pattern.'' ''(EditHint: move to NestedProcesses.)'' Process calculi is something only language designers, not OS designers, care about. It's becoming obvious you're the former. ''They are not mutually exclusive. How can someone be competent to design a language-based OS without being a language designer? And designers of operating systems of all kinds should care about process calculi; they could learn a lot from them.'' Membranes have to do with processes. They're ALL about process boundaries. Meanwhile, non-programmer end-users don't give a good goddamn about processes. And you know, I don't think nested processes (as opposed to just processes) have anything to do with membranes. They were just something I was thinking about at the time. Pretty much the same reason you brought up membranes in the first place. ---- '''ExoKernel''' That permission flags are universal abstractions necessary for the security of all objects everywhere and orthogonal to all objects might not be obvious in broken systems where capabilities are centralized in the kernel, which is probably any system ''with'' a kernel. Eros' centralized capabilities makes it uninteresting. ''In any cap system there has to be a security kernel: the component that is responsible for enforcing the capability model. There are disadvantages to memory-protection-based cap systems, but I don't see that this is one of them.'' It's false that there has to be a central process table. NestedProcesses is based on the idea that each process can maintain a table of its own children. * ''I didn't say that there has to be a central process table. As I said above, the model described in NestedProcesses is similar to the model that was used by CapOs, and CapOs certainly had a kernel.'' * If you're not gonna have an exokernel, what the hell's the point of having nested processes??? ** ''An exokernel OS does have a kernel, and a TCB. They're just smaller. The paper that introduced exokernels (http://www.cs.ucsd.edu/classes/fa99/cse221/exokernel-sosp95.pdf) agrees with me: ''"In this architecture, a minimal kernel -- which we call an exokernel -- securely multiplexes available hardware resources." ** Do you seriously think I care what that bunch of wankers think the word means? They're under some delusion that exokernels are good for optimization, which concern doesn't speak to their sanity, never mind their credibility. (Did you seriously expect an argument from authority to work on someone with the overweening hubris to consider themselves the final authority in the field?) *** I was half expecting you to call that an argument from authority :-) If you don't agree with what the people who introduced the term "exokernel" think it means, then why are you using that term at all? *** ''To communicate. Overloading terms is better than rampant neologisms. Especially when you hold every alternate meaning of the term in contempt.'' ** If you think that exokernels are kernels or TCBs, then you really, really don't understand security. *** '''''All''' security systems have a system TCB, defined as the minimal subsystem that is relied on to maintain the security model. At the very least, in computer-based security systems it includes the hardware, and the lowest level of software needed to multiplex the hardware. It may include more than that. And if you read what I wrote more carefully, you would see that I didn't say that an exokernel '''is''' the TCB. Typically, the TCB will be larger than the exokernel.'' *** Oh you poor sap. In a nested process system, the TCB is whatever subset of the entire system you rely on. If you're the sole user, it's the entirety of the system. There is no such thing as "the security model" distinct from the system itself, the model extends at the same rate that the object graph extends. Any other meaning of the term is trivial and uninteresting. **** ''Of course there are multiple TCBs. I was specifically referring to the system TCB. No, if you are the sole user your TCB is '''not''' the entirety of the system (at least, not if the system has any chance of being secure from your point of view). And yes, there is such a thing as "the security model", which is fixed by the system design.'' It's false that there has to be a central capability store. My cap scheme is based on the idea that each process implements and exports its own set of caps. * ''In such a system, the security kernel is implemented by the root of the process tree.'' * This is not inevitable. In my scheme, each process implements its own capabilities within itself and provides exactly one capability to each of its children. It's false that there has to be a kernel of anything. ExoKernel puts the lie to that. Eros is a kernel system, therefore Eros is bad and its cap scheme with it. ''Anyway, if you think that exokernels are a good idea, why do you want to hard-wire so much policy into your system at a low level? The exokernel approach is more consistent with my position than with yours.'' Because none of it's policy. It's all mechanism. It's just that I require my mechanisms to be clean, elegant and self-consistent. In addition, exokernels provide '''secure''' multiplexing of underlying abstractions. And how do you suppose security should be done if not by capabilities? Virtualizing can only go so far before you have to produce abstractions to allocate and distribute the virtualized resources. Once you do that, you need caps. ''Well, the distinction between mechanism and policy is not entirely well-defined. However, the point is that implementations of the security abstractions we're talking about cannot avoid building in some aspects of policy. Some of the design decisions on GarbageCollectionUnderVersioning and PermissionFlags are certainly policy, for instance.'' This page defines the difference between mechanism and policy. If you don't see that then you're really missing the point. The point being that these things you claim "are certainly policy" are certainly '''not''' policy as far as I'm concerned. -- "It's false that there has to be a kernel of anything. ExoKernel puts the lie to that. Eros is a kernel system, therefore Eros is bad and its cap scheme with it." ''This is simply fuzzy thinking. EROS is a MicroKernel system, so it goes at least part-way toward accepting the reasoning behind exokernels. You could argue that its kernel is still too big, but that doesn't have much to do with its cap scheme. It's perfectly possible to implement an EROS-like, memory-protection-based cap scheme on top of an exokernel.'' ''There are much better arguments against memory-protection-based implementations of capabilities. The strongest one IMHO is that to write secure applications you need to use a high-level language anyway, and so you want to minimize the ImpedanceMismatch between the OS interface and the language interface. The easiest and most effective way to do that is for the OS interface to be the language interface. Provided that the language is expressive enough (and can therefore support multiple ProgrammingParadigm''''''s and surface syntaxes), there's no justification for separating them.'' You don't seem to understand the essential difference between an operating system and a language. Or perhaps you simply don't understand languages. An OS must do much more than simply run an expressive language. It has to be able to run other languages. It has to be able to run assembly even. The fact that you're even thinking in terms of "memory protection vs in the language protection" tells me how narrow-minded and warped your thinking on caps is. My caps scheme transcends such petty distinctions. Unlike you, I'm not concerned whether EROS made the right or wrong choice regarding its caps, the fact that you can even distinguish between memory-protection and language protection is sufficient for me to condemn it. ''What makes you think that assembly isn't a language? Or that it is not possible to translate several languages into one? Or that it is not possible to view several languages as one simply by tagging programs? Or that it is not possible to view '''any''' virtual machine as a language?'' More legalisms. ''They are not just legalisms. Think about them more carefully, you might learn something.'' As already explained, this was the last discussion I'm having. That's too bad since I very much enjoy talking about my field of expertise, for once. ''Is the hardware memory protection used to enforce protection domains, or is it not used? That's a pretty clear distinction. Of course it's strictly speaking a property of the implementation, but in practice it affects the design so much that systems that expect different answers to this question look very different in other respects.'' In practice, operating systems writers are morons incapable of any design. In practice, operating systems researchers don't do any research. In practice, operating systems design is a dead field. What do YOU know about OS design? And where the hell would you have ever learned it? And don't bother claiming that you taught yourself because it's clear that you're not even a designer, let alone an OS designer. ---- '''Simulation vs Reality''' Unix's permissions are absolutely horrible. Execute is meaningless for almost every file, then there are the unused and useless permissions in ext2fs (append-only, compress). But at least Unix ''has'' permissions. In most implementations of the CapabilitySecurityModel, permissions seem to be absent. ''Permissions are supported primitively in most ObjectCapabilityOperatingSystem''''''s based on memory protection (HydraOs, etc.). They are not supported primitively in most language-based cap systems. That's because these systems typically try to look as much like conventional ObjectOrientedLanguage''''''s as possible, and because it is easy to simulate permission flags using a variation of FacetPattern (in which the facet interface can be controlled dynamically).'' It seems that language designers are almost as retarded as systems programmers. LanguagesAreOperatingSystems, and if you don't include the lessons learned in OS research then your language is worthless. You ''have'' to include permissions at a low level. * ''Well obviously you don't ''have'' to, since some systems don't, and seem to work well without doing this.'' And the kicker is that you don't have to change the user's experience of the language to do so, except in a good way like garbage collection does. The user's (programmer's) experience of your program is far more important than the irrelevant implementation details which programmers (language designers) are so obsessed with. * ''That's a bit of a sweeping generalisation about language designers (although it's not so unreasonable that designers want their languages to be feasible to implement). In this case, though, the issue is the complexity of the language, not the whether it would be possible to include permissions at a low level.'' * The complexity is there no matter what. Either it's built in or it's in a library somewhere. ** ''The advantage of layering is that each layer can be understood separately.'' ** The advantage to building it in is that you don't need to understand a lower layer at all. It doesn't exist. * And in the latter case, the user has to worry about whether or not to use it. Furthermore, if caps are implemented on top of objects then the user ends up seeing their internal implementation when they go digging through the system. ** ''Yes, iff they have authority to see it ''and'' they have chosen to see it. This is a feature, not a problem.'' * This makes the system visibly more complicated and hence more difficult to reason about. Building in the caps eliminates those problems by making the system more uniform (every object reference is a cap) and making caps opaque to users (high level caps are fundamental). ** ''Where is the evidence that it would be more difficult to reason about? Anyway, in a system that uses proxies, every object reference is still a cap; that is not a difference between the two approaches.'' ** They're only ''low-level'' caps, so they're worthless. And if people had to provide evidence for every gut feeling and design decision that goes into an OS, none of them would ever get written. *** ''The ones that correspond to your high-level caps look exactly like high-level caps. An application program cannot tell the difference, as long as it uses the abstractions provided in libraries. However, it can '''also''' extend those abstractions.'' * When you open a browser on your system, you end up seeing all of the caps everywhere. If you've got low level caps with proxies littered everywhere, then that's exactly what you end up seeing. The best you could do would be to program the browser to hide the proxies from view, but you'd need to resort to something like grand unified capabilities as what you'd show the user. So that's the problem, every sane system always ends up showing the user the same thing. The difference is that I don't have to do the runaround since my high-level abstractions are ''real'', not sleight of hand. ** ''Having the browser hide proxies by default is precisely what I would do. I don't see any problem with this.'' Finally, memory protection is worthless as a capability system. It's coarse-grained, inflexible, and insufficiently general. ''There's something to that argument; I'm also much more interested in language-based systems, although I wouldn't call memory-protection-based systems worthless.'' ---- From TwoKindsOfCapabilities The clean implementation treats unlimited caps as exceptions. Message dispatch occurs as usual except that at every reference, the VM performs an OR between the 'unlimited bit' on the message and that on the reference. When the message gets to its destination, only then does the VM decide whether to check the permission bits (if the unlimited bit is unset). ''I don't see why this needs to interact with primitive message dispatch. Another way to do it is to use a membrane between user domains (again, using an abstraction layer rather than trying to cram every aspect of policy into the primitive mechanisms).'' That's because you don't want every object reference to be a useful security abstraction, a high level capability. In my scheme you have a fundamental object (capability) which you can set in any of various pre-defined modes. In other schemes, you have a "secure" reference (a "raw" or unlimited capability) which you shield by building a proxy to access it. You can simulate my modal caps scheme by having a standard set of proxies which you can instantiate at will on any object. But my imagination is not so strong that I can ignore what's actually happening. What I call capabilities mostly refers to the proxies which are at the same level of abstraction. Since the raw capabilities are subcomponents of the proxies, I can't think of them as being at the same level of abstraction as the proxies themselves. This would be more obvious if there existed null proxies which permitted all operations. Kinda pointless except that it would make the system uniform. ''There is no loss of security in using proxies, and they have some important advantages:'' * ''The basic computation model is simpler.'' ** It's already straightforward, there's no need to make it simpler. * ''New proxies can be defined outside the system TCB. A proxy implementation needs to be trusted by the objects that will use it, but not by the system.'' ** You know, this is what makes me hurl. You've got higher level proxies outside the [system] TCB while caps are confined within the [system] TCB. Do you understand why ACLs are a bad idea? They're a bad idea because they separate information about who owns a resource from who determines how it would be used. Do you see how this applies to your caps and proxies? *** ''You'll have to define what you mean by "own", since that is a term with a specific technical meaning in ACL systems, but not in most capability systems. ACLs are a bad idea because they separate designation of a resource from authority to access it. The proxy-based approach does not separate designation from authority, nor does it violate any of the other design principles of capability systems.'' * ''The fact that proxies are defined outside the system TCB makes them easier to change.'' ** I won't need to change my standard perms because they will be secure. And extending the perm system will be far simpler for my users than your own. All my users have to do is declare a new permission flag and use it. Yours would have to define new proxies, instantiate them and pass them around. *** ''No, they don't. In cases where a new permission flag is all that is needed, that's as simple in my approach as in yours. The difference is only in cases where a new abstraction can't be expressed simply by applying parameters to existing abstractions.'' I need to redefine message dispatch to handle these permission interactions because this construct is really too basic and much too universal to bother dealing with. I also don't think you appreciate just how distributed and decentralized my cap scheme is, how dynamic while remaining completely uniform and elegant it all is. * ''No, I don't, because you haven't explained it.'' * Oh, right. There's only a half dozen pages about it. Oh, and I do have something resembling membranes called portals. They're for interprocess caps. But hey, same goes for membrane pattern, doesn't it? And let me emphasize here: user domains have NOTHING to do with processes. A user domain can encompass multiple nested components (the object graphs exported by processes), or only a fraction of a single one, or fractions of multiple ones. They simply have nothing to do with each other. Actually, I do want to thank you for raising the issue of what I'll have to put into the VM. ---- CategorySecurityPatterns CategoryAbstraction