1. 17
  1.  

  2. 2

    From the outside, they look like really good ideas, and it’s a shame they haven’t come across to the Linux world.

    1. 1

      Is it just me, or is unveil a terrible choice of name? It normally means “remove a veil”, “disclose” or “reveal”. Its function is almost exactly the opposite - it removes access to things! As the author says:

      Let’s start with unveil. Initially a process has access to the whole file system with the usual restrictions. On the first call to unveil it’s immediately restricted to some subset of the tree.

      Reading the first line of the man page I can see how it might make sense in some original context, but this is the opposite of the kind of naming you want for security functions…

      1. 3

        Is it just me, or is unveil a terrible choice of name? It normally means “remove a veil”, “disclose” or “reveal”. Its function is almost exactly the opposite - it removes access to things!

        It explicitly grants access to a list of things, starting from the empty set. If it’s not called, everything is unveiled by default.

        1. 3

          I am not a native speaker, so I cannot comment if the verb itself is a good choice or not :)

          As a programmer who uses unveil() in his own programs, the name makes total sense. You basically unveil selected path to the program. If you then change your code to work with other files, you also have to unveil these files to your program.

          1. 2

            OK, I understand - it’s only for the first usage it actually restricts, and immediately also unveils, after that it continues to unveil.

          2. 2

            “Veiling” is not a standard idea in capability theory, but borrowed from legal practice. A veiled fact or object is ambient, but access to it is still explicit and tamed. Ideally, filesystems would be veiled by default, and programs would have to statically register which paths they intend to access without further permission. (Dynamic access would be delegated by the user as usual.)

            I think that the main problem is that pledges and unveiling are performed as syscalls after a process has started, but there is no corresponding phase before the process starts where pledges are loaded from the process’s binary and the filesystem is veiled.

            1. 1

              Doing it as part of normal execution implements separate phases of pledge/unveil boundaries in a flexible way. The article gives the example of opening a log file, and then pledging away your ability to open files, and it’s easy to imagine a similar process for, say, a file server unveiling only the public root directory in between loading its configuration and opening a listen socket.

              1. 1

                I think that the main problem is that pledges and unveiling are performed as syscalls after a process has started, but there is no corresponding phase before the process starts where pledges are loaded from the process’s binary and the filesystem is veiled.

                Well the process comes from somewhere. Having a chain-loader process/executable that sanitises the inherited environment and sets up for the next fits well with the established execution model. It’s explicitly prepared for this in pledge(, execpromises).

                1. 2

                  You could put it in e.g. an elf header, or fs-level metadata (like suid). Which also fits well with the existing execution model.

                  Suid is a good comparison, despite being such an abomination, because under that model the same mechanism can double as a sandbox.

                  Chainloader approach is good, but complexity becomes harder to wrangle with explicit pledges if you want to do djb-style many communicating processes. On the other hand, file permissions are distant from the code, and do not have an answer for ‘I need to wait until runtime to figure out what permissions I need’.

                  1. 1

                    Not going too far into the static/dynamic swamp shenanigans (say setting a different PT_INTERP and dlsym:ing out a __constructor pledge/unveil) - there’s two immediate reasons why I’d prefer not to see it as a file-meta property.

                    1. Filesystem legacy is not pretty, and accidental stripping of meta on a move to incompatible file-system would have a fail-silent-dangerous (stripping sudo is not dangerous versus stripping pledge setup).
                    2. Pledge- violations go kaboom, then you need to know that this was what happened (dmesg etc.) and you land in core_pattern like setups. The choice of chain-loader meanwhile takes the responsibility of attribution/communication so x11 gets its dialog or whatever, isatty() a fprintf and others a syslog and so on.
              2. 1

                Like Linux’s unshare