Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restricting writes to just /tmp and cleaning /tmp after every worker #197

Closed
jakepruitt opened this issue May 21, 2018 · 2 comments
Closed

Comments

@jakepruitt
Copy link

As a stepping stone for the work that #188 attempted to prove, we should build a system that prevents workers from writing to any directory except the /tmp directory and removes all files in the /tmp directory after every worker finishes. This system should be built on top of #184.

Handy links/references

cc/ @mapbox/platform-engine-room

@jakepruitt
Copy link
Author

jakepruitt commented May 22, 2018

For restricting writes, I was able to prove that adding a random uid to a spawned child process, whether that uid maps to a real user or not, prevents that child process from writing to anywhere except /tmp 🎉 .

Experiment:

const child_process = require('child_process');

const child = async (uid, command) => {
  return new Promise((resolve, reject) => {
    const start = Date.now();

    const options = {
      shell: true,
      env: process.env,
      uid: uid,
      stdio: [process.stdin, 'pipe', 'pipe']
    };

    const child = child_process
      .spawn(command, options)
      .on('error', (err) => reject(err))
      .on('exit', (code, signal) => {
        const duration = Date.now() - start;
        resolve({ uid, code, signal, duration });
      });

    child.stdout.pipe(process.stdout);
    child.stderr.pipe(process.stderr);
  });
};

if (module === require.main) {
  console.log('Before we do anything, let\'s find out some info:');
  console.log(`process.gid: ${process.getgid()}`);
  console.log(`process.groups: ${process.getgroups()}`);
  console.log(`process.uid: ${process.getuid()}`);
  console.log(`process.euid: ${process.geteuid()}`);

  child(200, 'echo "Hello!" > /world-history.txt && cat /world-history.txt && rm /world-history.txt')
    .then((results) => {
      console.log(results);
    }).catch((err) => {
      console.log(err);
    });
}

Output on alpine linux:

Before we do anything, let's find out some info:
process.gid: 0
process.groups: 0,1,2,3,4,6,10,11,20,26,27
process.uid: 0
process.euid: 0
/bin/sh: can't create /world-history.txt: Permission denied
{ uid: 200, code: 1, signal: null, duration: 12 }

Output on ubuntu linux:

Before we do anything, let's find out some info:
process.gid: 0
process.groups: 0
process.uid: 0
process.euid: 0
/bin/sh: 1: cannot create /world-history.txt: Permission denied
{ uid: 200, code: 2, signal: null, duration: 11 }

Both of these experiments work when I change the file to /tmp/world-history.txt.

With that proven, I'll start writing tests on restriction. I think we will need to move tests to run inside of a container for this, since normal mac/linux users are not allowed to specify other users for sub-shells, but the root user of a container would.

@jakepruitt
Copy link
Author

This was done in #200

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant