Makefile changes, usage message changes, README updates
This commit is contained in:
parent
34a0a81ed2
commit
7adff40839
22
Makefile
22
Makefile
@ -6,15 +6,13 @@ LDFLAGS =
|
|||||||
INSTALL = /usr/bin/env install
|
INSTALL = /usr/bin/env install
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
|
|
||||||
all: voidnsrun voidnsundo
|
|
||||||
|
|
||||||
test: testserver testclient
|
test: testserver testclient
|
||||||
|
|
||||||
voidnsrun: voidnsrun.o utils.o
|
run: voidnsrun.o utils.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
$(CC) $(CFLAGS) -o voidnsrun $^ $(LDFLAGS)
|
||||||
|
|
||||||
voidnsundo: voidnsundo.o utils.o
|
undo: voidnsundo.o utils.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
$(CC) $(CFLAGS) -o voidnsundo $^ $(LDFLAGS)
|
||||||
|
|
||||||
testserver: test/testserver.o utils.o
|
testserver: test/testserver.o utils.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||||
@ -22,9 +20,13 @@ testserver: test/testserver.o utils.o
|
|||||||
testclient: test/testclient.o utils.o
|
testclient: test/testclient.o utils.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
install: voidnsrun voidnsundo
|
install-run: run
|
||||||
$(INSTALL) voidnsrun voidnsundo $(PREFIX)/bin
|
$(INSTALL) voidnsrun $(PREFIX)/bin
|
||||||
chmod u+s $(PREFIX)/bin/voidnsrun $(PREFIX)/bin/voidnsundo
|
chmod u+s $(PREFIX)/bin/voidnsrun
|
||||||
|
|
||||||
|
install-undo: undo
|
||||||
|
$(INSTALL) voidnsundo $(PREFIX)/bin
|
||||||
|
chmod u+s $(PREFIX)/bin/voidnsundo
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o test/*.o voidnsrun voidnsundo testserver testclient
|
rm -f *.o test/*.o voidnsrun voidnsundo testserver testclient
|
||||||
@ -32,4 +34,4 @@ clean:
|
|||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) -c $^ -I. -o $@
|
$(CC) $(CFLAGS) -c $^ -I. -o $@
|
||||||
|
|
||||||
.PHONY: all install clean distclean
|
.PHONY: run undo install-run install-undo clean
|
275
README.md
275
README.md
@ -1,86 +1,168 @@
|
|||||||
# voidnsrun
|
# voidnsrun
|
||||||
|
|
||||||
**voidnsrun** is utility for launching programs in an isolated namespace with
|
**voidnsrun** is utility for launching programs in an isolated mount namespace
|
||||||
alternative `/usr` tree. Its primary goal is to run glibc programs in
|
with alternative `/usr` tree. Its primary goal is to run glibc programs in
|
||||||
musl-libc Void Linux environments or vice-versa.
|
musl-libc Void Linux environments (or vice-versa, but who needs that?).
|
||||||
|
|
||||||
It creates a new private mount namespace, transparently substitutes `/usr` and
|
It creates a new private mount namespace, transparently substitutes `/usr` and
|
||||||
some other directories with directories from your alternative root using bind
|
some other directories with directories from your glibc container using bind
|
||||||
mounts, and launches your program.
|
mounts, and launches your program.
|
||||||
|
|
||||||
|
**voidnsundo**, to the contrary, is utility for launching programs in the parent
|
||||||
|
mount namespace from within the mount namespace created by **voidnsrun**.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Just clone the repo, and then:
|
### Creating glibc container
|
||||||
|
|
||||||
```
|
As per the [Void documentation](https://docs.voidlinux.org/installation/musl.html#glibc-chroot),
|
||||||
$ make
|
perform glibc base system installation to a separate new directory:
|
||||||
$ sudo make install
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that installed binary must be owned by root and have suid bit. `make install`
|
|
||||||
should handle it.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
voidnsrun [OPTIONS] PROGRAM [ARGS]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-m <path>: add bind mount
|
|
||||||
-r <path>: altroot path. If this option is not present,
|
|
||||||
VOIDNSRUN_DIR environment variable is used.
|
|
||||||
-h: print this help
|
|
||||||
-v: print version
|
|
||||||
```
|
|
||||||
|
|
||||||
**voidnsrun** needs to know the path to your alternative root directory and it can
|
|
||||||
read it from the `VOIDNSRUN_DIR` environment variable or you can use `-r`
|
|
||||||
argument to specify it.
|
|
||||||
|
|
||||||
You may want to add something like this to your `~/.bashrc` or similar script:
|
|
||||||
|
|
||||||
```
|
|
||||||
export VOIDNSRUN_DIR=/glibc
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, **voidnsrun** binds these paths from alternative root to the new
|
|
||||||
namespace:
|
|
||||||
- `/usr`
|
|
||||||
- `/var/db/xbps`
|
|
||||||
- `/etc/xbps.d`
|
|
||||||
|
|
||||||
But if you're launching `xbps-install`, `xbps-remove` or `xbps-reconfigure`
|
|
||||||
and using **voidnsrun** version 1.1 or newer, this is what it will bind:
|
|
||||||
- `/usr`
|
|
||||||
- `/var`
|
|
||||||
- `/etc`
|
|
||||||
|
|
||||||
If you want to bind something else, use the `-m` argument.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Let's imagine you want to use some proprietary glibc app on your
|
|
||||||
musl-libc Void Linux box. Let it be Vivaldi browser for the example. You
|
|
||||||
unpacked it to `/opt/vivaldi` and it doesn't work, obviously.
|
|
||||||
|
|
||||||
First, you need to perform an alternative glibc base system installation to a
|
|
||||||
separate new directory:
|
|
||||||
```
|
```
|
||||||
# mkdir /glibc
|
# mkdir /glibc
|
||||||
# XBPS_ARCH=x86_64 xbps-install --repository=http://alpha.de.repo.voidlinux.org/current -r /glibc -S base-voidstrap
|
# XBPS_ARCH=x86_64 xbps-install --repository=http://alpha.de.repo.voidlinux.org/current -r /glibc -S base-voidstrap
|
||||||
```
|
```
|
||||||
|
|
||||||
Export path to this installation for **voidnsrun**:
|
### Installing voidnsrun
|
||||||
|
|
||||||
|
Clone the repo, and then:
|
||||||
|
|
||||||
|
```
|
||||||
|
make run
|
||||||
|
sudo make install-run
|
||||||
|
```
|
||||||
|
|
||||||
|
This will install **voidnsrun** to `/usr/local/bin`.
|
||||||
|
|
||||||
|
Export path to the container:
|
||||||
```
|
```
|
||||||
export VOIDNSRUN_DIR=/glibc
|
export VOIDNSRUN_DIR=/glibc
|
||||||
```
|
```
|
||||||
|
|
||||||
Try launching your app:
|
Also export path to **voidnsundo**:
|
||||||
```
|
```
|
||||||
voidnsrun /opt/vivaldi/vivaldi
|
export VOIDNSUNDO_BIN=/usr/local/bin/voidnsundo
|
||||||
```
|
```
|
||||||
|
|
||||||
It won't work just yet:
|
You may want to add these exports to your `~/.bashrc` or similar script.
|
||||||
|
|
||||||
|
### Installing voidnsundo
|
||||||
|
|
||||||
|
**voidnsundo** is supposed to be used from within the glibc container, so it has
|
||||||
|
to be linked with glibc. First, let's use just installed **voidnsrun** to install
|
||||||
|
build dependencies into the container:
|
||||||
|
```
|
||||||
|
sudo voidnsrun -r /glibc xbps-install -Su
|
||||||
|
sudo voidnsrun -r /glibc xbps-install make gcc
|
||||||
|
```
|
||||||
|
|
||||||
|
Then enter the container (the current working directory will be preserved by
|
||||||
|
**voidnsrun** 1.2 or higher) and build, then install **voidnsundo**:
|
||||||
|
```
|
||||||
|
voidnsrun bash
|
||||||
|
make clean
|
||||||
|
make undo
|
||||||
|
sudo make install-undo
|
||||||
|
```
|
||||||
|
|
||||||
|
This will install **voidnsundo** to `/usr/local/bin` in the container (which is
|
||||||
|
`/glibc/usr/local/bin` in reality).
|
||||||
|
|
||||||
|
Type `exit` or `Ctrl+D` to exit the container.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### voidnsrun
|
||||||
|
```
|
||||||
|
Usage: voidnsrun [OPTIONS] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-r <path>: Container path. When this option is not present,
|
||||||
|
VOIDNSRUN_DIR environment variable is used.
|
||||||
|
-m <path>: Add bind mount. You can add up to 50 paths.
|
||||||
|
-u <path>: Add undo bind mount. You can add up to 50 paths.
|
||||||
|
-U <path>: Path to voidnsundo. When this option is not present,
|
||||||
|
VOIDNSUNDO_BIN environment variable is used.
|
||||||
|
-i: Don't treat missing source or target for added mounts as error.
|
||||||
|
-V: Enable verbose output.
|
||||||
|
-h: Print this help.
|
||||||
|
-v: Print version.
|
||||||
|
```
|
||||||
|
|
||||||
|
**voidnsrun** needs to know the path to your glibc installation directory (or
|
||||||
|
"container"), it can read it from the `VOIDNSRUN_DIR` environment variable or
|
||||||
|
you can use `-r` argument to specify it.
|
||||||
|
|
||||||
|
By default, **voidnsrun** binds only `/usr` from the container. But if you're
|
||||||
|
launching `xbps-install`, `xbps-remove` or `xbps-reconfigure`and using
|
||||||
|
**voidnsrun** version 1.1 or higher, it will bind `/usr`, `/var` and `/etc`.
|
||||||
|
|
||||||
|
To bind something else, use the `-m` option. You can add up to 50 binds as of
|
||||||
|
version 1.2.
|
||||||
|
|
||||||
|
There's also the `-u` option. It adds bind mounts of the **voidnsundo** binary
|
||||||
|
inside the namespace. See more about this below in the **voidnsundo** bind mode
|
||||||
|
section. Just like with the `-m` option, you can add up to 50 binds as of version
|
||||||
|
1.2.
|
||||||
|
|
||||||
|
To bind the **voidnsundo** binary, **voidnsrun** has to know its path, and, like
|
||||||
|
with the container's path, it reads it from the `VOIDNSUNDO_BIN` environment
|
||||||
|
variable and from the `-U` option.
|
||||||
|
|
||||||
|
### voidnsundo
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage: voidnsundo [OPTIONS] PROGRAM [ARGS]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-V: Enable verbose output.
|
||||||
|
-h: Print this help.
|
||||||
|
-v: Print version.
|
||||||
|
```
|
||||||
|
|
||||||
|
**voidnsundo** can be used in two modes.
|
||||||
|
|
||||||
|
One is the **"normal" node**, when you invoke it like `voidnsundo <PROGRAM> [ARGS]`
|
||||||
|
and your `PROGRAM` will be launched from and in the original mount namespace.
|
||||||
|
|
||||||
|
For example, if you don't have a glibc version of firefox installed (so there's
|
||||||
|
no `/usr/bin/firefox` in the container), but you want to launch the "real" (the
|
||||||
|
one installed in your root musl system) firefox while being in the mount
|
||||||
|
namespace, just do `voidnsundo /usr/bin/firefox`.
|
||||||
|
|
||||||
|
The other mode is the **"bind" mode**. While in the container, and therefore in
|
||||||
|
the new mount namespace, you can bind mount **voidnsundo** to any path (don't
|
||||||
|
worry: it won't be visible outside the namespace), and, when invoked by that
|
||||||
|
path, it will launch the corresponding executable in your parent (root)
|
||||||
|
namespace.
|
||||||
|
|
||||||
|
For example, being in the container, you can do this:
|
||||||
|
```
|
||||||
|
touch /usr/bin/firefox
|
||||||
|
mount --bind /usr/local/bin/voidnsundo /usr/bin/firefox
|
||||||
|
```
|
||||||
|
and while there was no `/usr/bin/firefox` in the glibc container, after this,
|
||||||
|
when you'll launch `/usr/bin/firefox`, the "real" firefox from the root musl
|
||||||
|
system will be launched.
|
||||||
|
|
||||||
|
The creation of this bind mounts of **voidnsundo** can be automated by using
|
||||||
|
`-u` option of **voidnsrun**.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
This section contains some real examples of how to use some proprietary glibc
|
||||||
|
apps on your musl-libc Void Linux box.
|
||||||
|
|
||||||
|
### Vivaldi
|
||||||
|
|
||||||
|
The first example is the Vivaldi browser. Let's assume you unpacked it to
|
||||||
|
`/opt/vivaldi` (from rpm or deb package) and, obviously, it doesn't work.
|
||||||
|
|
||||||
|
Try launching it with **voidnsrun**:
|
||||||
|
```
|
||||||
|
$ voidnsrun /opt/vivaldi/vivaldi
|
||||||
|
```
|
||||||
|
|
||||||
|
It won't work just yet, but it's a start:
|
||||||
```
|
```
|
||||||
/opt/vivaldi/vivaldi: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory
|
/opt/vivaldi/vivaldi: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory
|
||||||
```
|
```
|
||||||
@ -99,7 +181,7 @@ glib-devel-2.66.2_1 /usr/share/gdb/auto-load/usr/lib/libgobject-2.0.so.0.6600.2-
|
|||||||
libglib-devel-2.66.2_1 /usr/lib/libgobject-2.0.so -> /usr/lib/libgobject-2.0.so.0
|
libglib-devel-2.66.2_1 /usr/lib/libgobject-2.0.so -> /usr/lib/libgobject-2.0.so.0
|
||||||
```
|
```
|
||||||
|
|
||||||
Sync repos and install `glib`. You can use **voidnsrun** for this purpose too.
|
Sync repos and install `glib`:
|
||||||
```
|
```
|
||||||
$ sudo voidnsrun -r /glibc xbps-install -Su
|
$ sudo voidnsrun -r /glibc xbps-install -Su
|
||||||
$ sudo voidnsrun -r /glibc xbps-install glib
|
$ sudo voidnsrun -r /glibc xbps-install glib
|
||||||
@ -113,9 +195,46 @@ $ voidnsrun /opt/vivaldi/vivaldi
|
|||||||
|
|
||||||
As you can see, it no longer complains about missing `libgobject-2.0.so.0`, now
|
As you can see, it no longer complains about missing `libgobject-2.0.so.0`, now
|
||||||
it's `libnss3.so`. Repeat steps above for all missing dependencies, and in the
|
it's `libnss3.so`. Repeat steps above for all missing dependencies, and in the
|
||||||
end, it will work. (If it's not, then something's still missing. In particular,
|
end, it will work.
|
||||||
make sure to install fonts related packages: `xorg-fonts`, `freetype`,
|
|
||||||
`fontconfig`, `libXft`.)
|
Note that, for some reason, it doesn't complain about missing font related
|
||||||
|
libraries, such as freetype, so make sure to install them too, as well as some
|
||||||
|
base fonts:
|
||||||
|
```
|
||||||
|
$ sudo voidnsrun -r /glibc xbps-install freetype fontconfig libXft xorg-fonts
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're noticing performance issues with Vivaldi, check the `vivaldi://gpu`
|
||||||
|
page. If it turns out that hardware acceleration is unavailable, you're missing
|
||||||
|
some packages again. I don't know which ones exactly, but installing `xorg-minimal`
|
||||||
|
should fix it.
|
||||||
|
|
||||||
|
### PhpStorm
|
||||||
|
|
||||||
|
**PhpStorm** and other JetBrains IDEs should just work like this (of course,
|
||||||
|
replace `/opt/PhpStorm` with real path on your machine):
|
||||||
|
```
|
||||||
|
voidnsrun /opt/PhpStorm/bin/phpstorm.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
But it is only at first glance, everything works. After some time you may
|
||||||
|
notice all kinds of weird stuff caused by the fact that it runs inside the
|
||||||
|
"container" with different `/usr`. For instance, if you open built-in terminal
|
||||||
|
window, it will work, but... it will not be the shell you expect, it will be
|
||||||
|
glibc-linked shell from the container. Some programs that you have
|
||||||
|
installed on your root musl system will not be available there (like, it won't be
|
||||||
|
able to launch a browser because there's no browser), other may not work as
|
||||||
|
expected.
|
||||||
|
|
||||||
|
In general, all programs that launch other programs will suffer from this. To
|
||||||
|
overcome this, the **voidnsundo** utility has been written and `-u` option added
|
||||||
|
to **voidnsrun**.
|
||||||
|
|
||||||
|
To fix the built-in PhpStorm's terminal and the ability to launch browser as shown
|
||||||
|
in the above example, launch it like so:
|
||||||
|
```
|
||||||
|
voidnsrun -u /bin/bash -u /usr/bin/firefox /opt/PhpStorm/bin/phpstorm.sh
|
||||||
|
```
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
@ -130,10 +249,32 @@ Defaults env_keep += "VOIDNSRUN_DIR"
|
|||||||
|
|
||||||
A: If you installed fonts on your main system, applications that run in the mount
|
A: If you installed fonts on your main system, applications that run in the mount
|
||||||
namespace can't see them because of custom `/usr` directory. You need to install
|
namespace can't see them because of custom `/usr` directory. You need to install
|
||||||
them again into the altroot directory.
|
them again into the container directory.
|
||||||
|
|
||||||
|
Some workaround to bind-mount `/usr/share/fonts` from the root system to the
|
||||||
|
namespace may be introduced in future, if Linux will allow such hacks.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
**voidnsrun** and **voidnsundo** are setuid applications, meaning they are
|
||||||
|
actually started as root and then dropping privileges when they can. setuid is
|
||||||
|
generally bad, it's a common attack vector that allows local privilege
|
||||||
|
escalation by exploiting unsafe code of setuid programs.
|
||||||
|
|
||||||
|
While these utilities have been written with this thought in mind, don't trust
|
||||||
|
me. Read the code, it's not too big. Place yourself in attacker's shoes and try
|
||||||
|
to find a hole. For every new discovered vulnerability in these utilities that
|
||||||
|
would allow privilege escalation or something similar I promise to pay $25 in
|
||||||
|
Bitcoin. Contact me if you find something.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
#### 1.2
|
||||||
|
|
||||||
|
- Added **voidnsundo** utility for spawning programs in the parent mount
|
||||||
|
namespace from withing the namespace created by **voidnsrun**.
|
||||||
|
- Restore current working directory after changing namespace.
|
||||||
|
|
||||||
#### 1.1
|
#### 1.1
|
||||||
|
|
||||||
- Bind whole `/etc` and `/var` when launching `xbps-install`, `xbps-remove` or
|
- Bind whole `/etc` and `/var` when launching `xbps-install`, `xbps-remove` or
|
||||||
|
@ -34,12 +34,11 @@ void usage(const char *progname)
|
|||||||
" -r <path>: Container path. When this option is not present,\n"
|
" -r <path>: Container path. When this option is not present,\n"
|
||||||
" " CONTAINER_DIR_VAR " environment variable is used.\n"
|
" " CONTAINER_DIR_VAR " environment variable is used.\n"
|
||||||
" -m <path>: Add bind mount. You can add up to %d paths.\n"
|
" -m <path>: Add bind mount. You can add up to %d paths.\n"
|
||||||
" -u <path>: Add undo utility bind mount. You can add up to %d paths.\n"
|
" -u <path>: Add undo bind mount. You can add up to %d paths.\n"
|
||||||
" -U <path>: Undo program path. When this option is not present,\n"
|
" -U <path>: Path to " VOIDNSUNDO_NAME ". When this option is not present,\n"
|
||||||
" " UNDO_BIN_VAR " environment variable is used.\n"
|
" " UNDO_BIN_VAR " environment variable is used.\n"
|
||||||
" -i: Don't treat missing source or target for an added mount\n"
|
" -i: Don't treat missing source or target for added mounts as error.\n"
|
||||||
" as an error.\n"
|
" -V: Enable verbose output.\n"
|
||||||
" -V: Verbose output.\n"
|
|
||||||
" -h: Print this help.\n"
|
" -h: Print this help.\n"
|
||||||
" -v: Print version.\n",
|
" -v: Print version.\n",
|
||||||
USER_LISTS_MAX, USER_LISTS_MAX);
|
USER_LISTS_MAX, USER_LISTS_MAX);
|
||||||
|
@ -24,9 +24,9 @@ void usage(const char *progname)
|
|||||||
printf("Usage: %s [OPTIONS] PROGRAM [ARGS]\n", progname);
|
printf("Usage: %s [OPTIONS] PROGRAM [ARGS]\n", progname);
|
||||||
printf("\n"
|
printf("\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -V: Verbose output.\n"
|
" -V: Enable verbose output.\n"
|
||||||
" -h: Print this help.\n"
|
" -h: Print this help.\n"
|
||||||
" -v: Print version.\n");
|
" -v: Print version.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user