Implementing SECCOMP in OTP

Hi I’m implementing some security on OTP and this is my initial proposal https://pastebin.com/57GCTEc6 (this is the one I sent to the mailing list), I would love to hear what you people think about it.

I’m sending the pasetbin link because some of the ascII diagrams would not display properly here

— EDIT —

as OvermindDL1 pointed out I can keep the diagrams under markdown. So the text below is the one I’ve sent to the mailing list.

Hi,
 
  I've been working with erlang/elixir for the past year and I really miss
SECCOMP like features in the BEAM. So I started an implementation based on
https://github.com/erlang/otp and I wanted to know what you people think about
it.
 
  The idea is to provide a way to blacklist/whitelist function calls on a
process level, so for example if I'm evaluating human input for a calculation,
I can guarantee that no other function except the ones that are necessary are
called. Going further, in a case where my erlang cookie is leaked, I know
that only a limited set of functions are callable using rpc or node.spawn/2.
 
  The way I envision it (and I'm implementing it) is adding a byte to the
process struct with the following meaning:
 
   0 1 2 3 4 5 6 7
  +-+-+-+-+-+-+-+-+
  |E|M|S|I|U|U|U|U|
  +-+-+-+-+-+-+-+-+
 
  Where:
    E -> Whether the mechanism is active (0:Off/1:On)
    M -> Operation Mode (0:Whitelist/1:Blacklist)
    S -> Disable Spawn (0:Can spawn new process/1:Cannot spawn new process)
    I -> Whether a child process will inherit the
    U -> Unused
 
  There are some implicit rule in this byte:
    - M,S, and I are unused whether E is set to 0
    - I is unused if S is set to 1
 
  I choosed to use a byte because bitwise operation are cheap and are the least
expensive way I could think, and bitmasks can be combined in a meaningful way.
 
  The verification of this byte would occur at the apply function, so we can
check the byte every time a function is called. To know which function is
whitelisted/blacklisted I added an Eterm to the process struct. This Eterm is a
NIL terminated list of tuples, each tuple contains two atoms representing the
module name and the function name which is whitelisted/blacklisted.
 
  Probably a hashmap, or a binary tree of hashs would be quicker to search.
But I don't know if there is any good low level way to introduce it without
adding a lot of code to the code base.
 
  To implement process inherit capabilites, I added a verification on spawn,
but there are some possible bypasses that would need to be treated latter on.
 
  For example:
 
-------------------------------------------------------------------------------
 
  If there is a process running as a dynamic supervisor (P1), some other
process (P2) may send a message to spawn some worker (P5) and the father
process would be the supervisor (P1), which may not have the mechanism active.
 
Diagram below:
 
 
             |                              |
             |  P1 - Dynamic Supervisor     | P2 (With active mechanism)
             V                              |
      ===============                       |
      | P3   | P4                           V
      V      V
 
  When P2 asks P1 to spawn a new worker, the diagram will look like the
following:
 
 
             |                              |
             |  P1 - Dynamic Supervisor     | P2 (With active mechanism)
             V                              |
      ===============                       |
      | P3   | P4   | P5                    V
      V      V      V
 
  Where P3, P4, and P5 are spawned with P1 as a parent, so it will not inherit
any rules from P2. At this point P5 can execute any code and send a message to
P2, bypassing the mechanism.
 
-------------------------------------------------------------------------------
 
  On another case a process (P1) on Node 1 which is under this mechanism may
spawn another process (P2) to Node 2, and then P1 spawns another process (P3)
on Node 1. If process generated by spawns of other nodes are less secure than
the process that called the spawn function, it will lead to privilege
escalation.
 
Diagram below:
 
 +---------------+              +---------------+
 |               |              |               |
 |    Node 1     |              |    Node 2     |
 |               |              |               |
 |        P1     |   spawn/2    |               |
 |   ------------> -------------> --------+     |
 |       calls   |              |         |     |
 |               |              |         | P2  |
 |               |              |         |     |
 |        P3     |   spawn/2    |  calls  |     |
 |   <---------- <------------- <---------+     |
 |               |              |               |
 +---------------+              +---------------+
 
  If P3 restrictions are less strict than P1, then P1 escalated privilege.
 
-------------------------------------------------------------------------------
 
  The code that I'm working is at https://github.com/Supitto/OTP/tree/maint
and it is built upon the maint branch. It still quite imature and have some
edges to trim (I'm still figthing with allocations and Eterms). But if this
idea is apreciated I will implement everything on the main branch. Also if
you can think of some other scenario where this mechanism is defeated, please
infome me :D
 
Thanks,
 
Henrique Almeida Marcomini
 
Telegram -> @supitto
IRC (freenode) -> Supitto
 
Ps. The code on the repo may be not working (depends on the commit), but the
    idea is there.
 
Pps. I made everything in ASCII so to see it properly use monospace fonts
3 Likes

This site uses markdown for formatting, thus to keep ascii diagrams and so forth you just put them in markdown code fences like:

```
And the stuff here |    |
                   |    |
```

Will look like:

And the stuff here |    |
                   |    |

:slight_smile:

Can also use 4-spaces pre-indentation as well.

3 Likes

Thank you, I updated my post

1 Like

I changed the codefence to text mode, these forums default to elixir syntax highlighting, which doesn’t work well with text. ^.^

1 Like

Can we do that ourselves? Using the GitHub way of putting a language/mode after the first triple backticks doesn’t seem to work on this forum.

I haven’t read the proposal in detail yet, but FWIW this kind of thing is going to face a lot of pushback from core Erlang:

1 Like

Don’t know about the pushback, but I do feel misguided by the lack of responses on the mailinglist, IRC, Slack and the erlef security working group. I’ll be submitting the PR to the OTP project nevertheless with the minimum core of this functionality, full explanation, and benchmarks. Lets see what happens. It is a simple feature after all.

Yes, that’s the way to do it:

```text
def this is just text
```

Becomes:

def this is just text

And:

```elixir
def this is just text
```

Becomes:

def this is just text

The supported languages is pretty restricted, controlled by the server manager, to keep javascript loads down.

1 Like

I see, thanks. Now I remember that it did actually work properly here in the forum. It’s Slack that doesn’t accept the language tag after the first three backticks. Sorry. :slight_smile: And thanks.

1 Like