pmbootstrap/pmb/helpers
Oliver Smith 3666388619
Properly escape commands in pmb.chroot.user() (#1316)
## Introduction
In #1302 we noticed that `pmb.chroot.user()` does not escape commands
properly: When passing one string with spaces, it would pass them as
two strings to the chroot. The use case is passing a description with
a space inside to `newapkbuild` with `pmboostrap newapkbuild`.

This is not a security issue, as we don't pass strings from untrusted
input to this function.

## Functions for running commands in pmbootstrap
To put the rest of the description in context: We have four high level
functions that run commands:
* `pmb.helpers.run.user()`
* `pmb.helpers.run.root()`
* `pmb.chroot.root()`
* `pmb.chroot.user()`

In addition, one low level function that the others invoke:
* `pmb.helpers.run.core()`

## Flawed test case
The issue described above did not get detected for so long, because we
have a test case in place since day one, which verifies that all of the
functions above escape everything properly:
* `test/test_shell_escape.py`

So the test case ran a given command through all these functions, and
compared the result each time. However, `pmb.chroot.root()`
modified the command variable (passed by reference) and did the
escaping already, which means `pmb.chroot.user()` running directly
afterwards only returns the right output when *not* doing any escaping.

Without questioning the accuracy of the test case, I've escaped
commands and environment variables with `shlex.quote()` *before*
passing them to `pmb.chroot.user()`. In retrospective this does not
make sense at all and is reverted with this commit.

## Environment variables
By coincidence, we have only passed custom environment variables to
`pmb.chroot.user()`, never to the other high level functions. This only
worked, because we did not do any escaping and the passed line gets
executed as shell command:
```
$ MYENV=test echo test2
test 2
```
If it was properly escaped as one shell command:
```
$ 'MYENV=test echo test2'
sh: MYENV=test echo test2: not found
```
So doing that clearly doesn't work anymore. I have added a new `env`
parameter to `pmb.chroot.user()` (and to all other high level functions
for consistency), where environment variables can be passed as a
dictionary. Then the function knows what to do and we end up with
properly escaped commands and environment variables.

## Details
* Add new `env` parameter to all high level command execution functions
* New `pmb.helpers.run.flat_cmd()` function, that takes a command as
  list and environment variables as dict, and creates a properly escaped
  flat string from the input.
* Use that function for proper escaping in all high level exec funcs
* Don't escape commands *before* passing them to `pmb.chroot.user()`
* Describe parameters of the command execution functions
* `pmbootstrap -v` writes the exact command to the log that was
  executed (in addition to the simplified form we always write down for
  readability)
* `test_shell_escape.py`: verify that the command passed by reference
  has not been modified, add a new test for strings with spaces, add
  tests for new function `pmb.helpers.run.flat_cmd()`
* Remove obsolete commend in `pmb.chroot.distccd` about environment
  variables, because we don't use any there anymore
* Add `TERM=xterm` to default environment variables in the chroot,
  so running ncurses applications like `menuconfig` and `nano` works out of
  the box
2018-03-10 22:58:39 +00:00
..
__init__.py Happy new year! (update copyright to 2018) 2018-01-04 04:53:35 +01:00
cli.py Happy new year! (update copyright to 2018) 2018-01-04 04:53:35 +01:00
devices.py Happy new year! (update copyright to 2018) 2018-01-04 04:53:35 +01:00
file.py Happy new year! (update copyright to 2018) 2018-01-04 04:53:35 +01:00
frontend.py pmbootstrap zap -m: delete outdated packages too (#1306) 2018-03-10 12:08:02 +00:00
git.py Remove timestamp based rebuilds (#1174) 2018-01-28 23:27:33 +00:00
http.py Happy new year! (update copyright to 2018) 2018-01-04 04:53:35 +01:00
logging.py Happy new year! (update copyright to 2018) 2018-01-04 04:53:35 +01:00
mount.py pmbootstrap build --src: override source for any package (#1210) 2018-02-19 22:04:01 +00:00
other.py Add a check for binfmt_misc (#1236) 2018-02-17 20:41:54 +00:00
pkgrel_bump.py Index parser: support multiple package providers (#1202) 2018-02-20 19:52:28 +00:00
repo.py Only download APKINDEX for relevant architectures (#1201) 2018-03-04 13:44:27 +00:00
run.py Properly escape commands in pmb.chroot.user() (#1316) 2018-03-10 22:58:39 +00:00
ui.py Show UI selection ordered by name, `none` remains at the beginning (#1092) 2018-01-07 03:55:27 +00:00