1. 14
  1.  

  2. 8

    I really wish Linux hadn’t decided to call a permissions system capabilities. It leads to a load of people being confused about either what capabilities are or about why this Linux thing is not a capability system even though it has capabilities in its name.

    1. 3

      Permissions, privileges, capabilities, policies, access control, authentication, authorization, trust mechanism, ownership policies, domains policies, yep this can get confusing when this type of jargon intermixes.

      EDIT: a great overview of system protection

      1. 2

        I blame posix’s capabilities, which are very wrongly named too.

        1. 1

          In all fairness, “capabilities” is actually a pretty good term for this sort of thing. As a user, you are giving capabilities to a binary. A capability is an action; a permission is what? It’s more vague.

          1. 8

            In security, a capability has a well-defined meaning. A capability is an unforgeable token of authority that can be delegated and, when presented, authorises an action. Linux ‘capabilities’ are not capabilities because they don’t implement the principle of intentionality. They are permissions that apply to the process. If a process holds a Linux ‘capability’, it can exercise the right without having to present the capability.

            UNIX file descriptors are much closer to capabilities. They are unforgeable (they’re identified by integer values, but those integers index into a table managed by the OS, you can’t just create an entry in the table without the kernel being involved). They can be delegated by passing them over UNIX domain sockets. They must be presented explicitly to system calls such as read / write / ioctl to use them. The rights conveyed by them are independent of the subject, you can hold a read-only and write-only capability to the same file and the read or write operation will fail if you use the wrong one. The file may be one that the user running the program does not have the rights to access via the file’s ACLs, but you received the capability to access the file because a differently privileged process passed the file descriptor to you over a UNIX domain socket. The changes required for Capsicum to turn POSIX into a capability system were very small (a mode that completely removes access to all global namespaces and finer-grained permissions on file descriptors).

            1. 2

              Linux ‘capabilities’ are not capabilities because they don’t implement the principle of intentionality

              Really? Given the example in the article:

              If a task asks to perform a privileged operation (like binding on ports < 1024), the kernel checks Effective bounding set to see if CAP_NET_BIND_SERVICE is set.

              It sounds like the intention is to give the binary the capability to do this action?

              Could you please link me to a reputable source giving the meaning? I’m not looking to argue, just explaining my thoughts. ☺

              1. 7

                Could you please link me to a reputable source giving the meaning?

                The best references are books, many of which predate Linux entirely, but the Wikipedia article is not too bad (and explicitly state that Linux capabilities are not a capability system) and has a bunch of good resources in the ‘further reading’ section.

                It sounds like the intention is to give the binary the capability to do this action?

                I think you are misunderstanding the principle of intentionality. The process does a bind system call. It does not require elevated privilege to bind to port 1234 but it does to bind to port 123. The system call is identical in both places. In a capability system, it would have to present a capability authorising it to bind to privileged ports in the second case, but would not have to in the first. This makes it much harder for an attacker to trick the process into doing a privileged operation. With Linux ‘capabilities’ the process has no way of saying ‘do this operation using this capability’, it just says ‘do this operation with ambient authority’ and if its ambient authority is sufficient then the operation succeeds. You never explicitly have to express the intention to use the right that you have, it happens automatically, even when you don’t want it to (for example, if you bind a socket on behalf of some other entity and forget to do the check that the port number that it provided you is <1024).

                With a capability system, you never exercise privilege without explicitly presenting the capability that you intend to use. If you open two directories on behalf of two different clients and one gives you a path for the other client’s directory, the capability that you hold for that client doesn’t let you access the directory and so you don’t accidentally use a privilege that you hold, but don’t intend to use.

                1. 2

                  Thank you, your explanation was very good :) I think I understand now. It sounds like Linux got close but didn’t go all the way for some reason…

                2. 3

                  https://en.wikipedia.org/wiki/Capability-based_security

                  For a really good introduction to the concept, I recommend:

                  http://habitatchronicles.com/2017/05/what-are-capabilities/

                  The article addresses your terminology objection early on:

                  The first thing to confront is that term, “capabilities”, itself. It’s confusing. The word has a perfectly useful everyday meaning, even in the context of software engineering.

                  That said, capabilities (in the narrow security sense) are an incredibly useful concept that isn’t nearly as well-known as it should be. As the article above goes into, it’s also deeply related to more general concepts of OO design.

                  1. 3

                    it can exercise the right without having to present the capability.

                    It’s sort of funky, but this is the key to understanding. I guess one could argue the PID # is the capability, but that’s not actually what’s happening. To access CAP_NET_BIND_SERVICE in a capability model you have to say hey Mr, Kernel, I want CAP_NET_BIND_SERVICE, and here is my token. so the function call would look something like:

                    kernel_bind_port(captoken,port80)

                    where with “linux capabilities” you would do something like:

                    kernel_bind_port(80)

                    and the authorization look up would happen behind the scenes, based on the PID for instance.

                    (obviously contrived example, using not real code).

                    The upside of a capability system:

                    • By requiring the token to go along with the request, one can pass the token along somewhere else if needed to do that 1 thing.
                    • The Token can be thrown away/forgotten after doing the binding it needs, essentially giving away the permission, so if I get compromised, I can’t then go bind port 53 and screw with DNS also.
                    • the token capability can be VERY fine-grained, and an app might have 100 of them if needed, making throwing away a permission when done a lot easier.
                    • You can easily make a service saying here is my cap proof(token) with perms X,Y and Z but I need a new one with permissions to only Z, and then I can hand Z out to a subprocess, it can now handle Z, but will have no ability to do X or Y.

                    etc, etc.

                    In an authorization setting(i.e. linux capabliities), I can’t do those things easily, because the proof of access doesn’t go with the access request.

                    1. 3

                      Wow thank you, your explanation was very nice! It really points out why Linux capabilities are not “capabilities”.

                    2. 2

                      This is a really good overview of the concept of system protection.