-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 006dc63
Showing
34 changed files
with
2,461 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
FROM debian | ||
COPY pkgs.list / | ||
RUN apt-get update \ | ||
&& apt-get install -y --no-install-recommends $(cat /pkgs.list) \ | ||
&& rm /pkgs.list | ||
RUN chmod -s /usr/bin/newuidmap \ | ||
&& setcap cap_setuid=ep /usr/bin/newuidmap \ | ||
&& chmod -s /usr/bin/newgidmap \ | ||
&& setcap cap_setgid=ep /usr/bin/newgidmap | ||
RUN groupadd --gid 1000 dev \ | ||
&& useradd --uid 1000 --gid 1000 --shell /bin/bash --create-home \ | ||
-K SUB_UID_MIN=32768 \ | ||
-K SUB_UID_MAX=49151 \ | ||
-K SUB_UID_COUNT=2048 \ | ||
-K SUB_GID_MIN=32768 \ | ||
-K SUB_GID_MAX=49151 \ | ||
-K SUB_GID_COUNT=2048 \ | ||
dev | ||
USER dev | ||
WORKDIR /home/dev |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "dev", | ||
"build": { | ||
"dockerfile": "Containerfile" | ||
}, | ||
"customizations": { | ||
"vscode": { | ||
"extensions": [ | ||
"ms-vscode.cpptools" | ||
] | ||
} | ||
}, | ||
"runArgs": [ "--security-opt", "seccomp=unconfined", "--security-opt", "label=disable", "--security-opt", "apparmor=unconfined" ] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
attr | ||
binutils | ||
ca-certificates | ||
debootstrap | ||
gcc | ||
gcc-aarch64-linux-gnu | ||
gcc-x86-64-linux-gnu | ||
git | ||
htop | ||
libc6-dev | ||
libc6-dev-amd64-cross | ||
libc6-dev-arm64-cross | ||
libcap2-bin | ||
make | ||
man-db | ||
openssl | ||
patchelf | ||
procps | ||
strace | ||
uidmap | ||
wesperanto |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
name: build | ||
on: push | ||
jobs: | ||
build: | ||
strategy: | ||
matrix: | ||
arch: | ||
- x86_64 | ||
- aarch64 | ||
fail-fast: false | ||
name: ${{ matrix.arch }} | ||
runs-on: ${{ matrix.arch == 'aarch64' && 'ubuntu-latest-arm' || 'ubuntu-latest' }} | ||
steps: | ||
- name: setup arm runner | ||
if: matrix.arch == 'aarch64' | ||
run: | | ||
sudo apt-get update | ||
sudo apt-get install -y --no-install-recommends podman uidmap slirp4netns dbus-user-session | ||
id="$(id -u)" | ||
sudo systemctl start user@$id | ||
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$id/bus | ||
systemctl --user start dbus | ||
mkdir -p "$HOME/.config/containers" | ||
echo 'unqualified-search-registries = ["docker.io"]' > "$HOME/.config/containers/registries.conf" | ||
- uses: actions/checkout@v4 | ||
- name: build dev container | ||
run: podman build -t dev -f .devcontainer/Containerfile .devcontainer | ||
- name: start dev container | ||
run: >- | ||
podman run --rm | ||
--security-opt seccomp=unconfined | ||
--security-opt label=disable | ||
--security-opt apparmor=unconfined | ||
--uidmap 0:1:1000 | ||
--uidmap 1000:0:1 | ||
--uidmap 1001:1001:64536 | ||
--gidmap 0:1:1000 | ||
--gidmap 1000:0:1 | ||
--gidmap 1001:1001:64536 | ||
-v "$PWD:/workdir" | ||
-w /workdir | ||
-d --name dev | ||
dev tail -f /dev/null | ||
- name: build | ||
run: podman exec dev make all | ||
- name: test | ||
run: podman exec dev make test | ||
- name: stop dev container | ||
run: podman stop dev | ||
- name: upload artifact | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: fake_xattr_${{ matrix.arch }} | ||
path: fake_xattr | ||
release: | ||
if: github.ref == 'refs/heads/main' | ||
needs: build | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: download artifact (x86_64) | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: fake_xattr_x86_64 | ||
path: fake_xattr_x86_64 | ||
- name: download artifact (aarch64) | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: fake_xattr_aarch64 | ||
path: fake_xattr_aarch64 | ||
- name: setup env context | ||
run: | | ||
repo='${{ github.repository }}' | ||
commit='${{ github.sha }}' | ||
echo "artifact_prefix=${repo#*/}-${commit::8}" | tee -a "$GITHUB_ENV" | ||
- name: pack artifacts | ||
run: | | ||
for arch in x86_64 aarch64; do | ||
tar -c --transform "s|^fake_xattr_|${artifact_prefix}-|" "fake_xattr_$arch" | gzip > "${artifact_prefix}-${arch}.tar.gz" | ||
done | ||
- name: publish release | ||
run: | | ||
if gh release view latest > /dev/null 2>&1; then | ||
gh release delete -y latest | ||
fi | ||
git tag --force latest | ||
git push --force origin latest | ||
gh release create latest \ | ||
--verify-tag \ | ||
--notes "created by GitHub actions run [${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" \ | ||
"${artifact_prefix}-x86_64.tar.gz" \ | ||
"${artifact_prefix}-aarch64.tar.gz" \ | ||
env: | ||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
*.o | ||
|
||
# generated | ||
syscall_lookup.c | ||
|
||
# executables | ||
fake_xattr | ||
do_syscall | ||
|
||
# tests | ||
test_xattr_db | ||
test_seccomp_unotify | ||
|
||
.tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
MAKEFLAGS += --no-builtin-rules | ||
|
||
.DELETE_ON_ERROR: | ||
.SILENT: | ||
.SECONDEXPANSION: | ||
|
||
CFLAGS := -std=c11 -Wall -Wextra -Wshadow -Wdeclaration-after-statement -Wno-multichar -Werror -O2 | ||
|
||
ifdef TEST_DEBUG | ||
CFLAGS += -DTEST_DEBUG=$(TEST_DEBUG) | ||
endif | ||
|
||
generated := syscall_lookup.c | ||
executables := fake_xattr do_syscall | ||
tests := test_xattr_db test_seccomp_unotify | ||
|
||
xattr_db_objects := xattr_db.o zalloc.o | ||
seccomp_unotify_objects := seccomp_unotify.o clone_vfork.o syscall_lookup.o | ||
test_objects := mem_account.o fd_account.o child_account.o | ||
|
||
fake_xattr_objects := main.o mem_account.o $(seccomp_unotify_objects) $(xattr_db_objects) | ||
do_syscall_objects := do_syscall.o syscall_lookup.o zalloc.o | ||
|
||
test_xattr_db_objects := test_xattr_db.o $(xattr_db_objects) $(test_objects) | ||
test_seccomp_unotify_objects := test_seccomp_unotify.o $(seccomp_unotify_objects) $(test_objects) | ||
|
||
objects := $(foreach executable,$(executables) $(tests),$($(executable)_objects)) | ||
uniq_objects := | ||
$(foreach object,$(objects),$(if $(filter $(object),$(uniq_objects)),,$(eval uniq_objects += $(object)))) | ||
|
||
outputs := $(generated) $(objects) $(executables) $(tests) | ||
|
||
.PHONY: all clean test $(addprefix @,$(tests)) | ||
|
||
all: $(executables) | ||
|
||
clean: | ||
echo rm $(outputs) | ||
rm -rf "$$(readlink .tmp)" | ||
rm -f $(outputs) .tmp | ||
|
||
@test_seccomp_unotify: do_syscall .tmp .tmp/chroot | ||
|
||
define test_target | ||
@$(1): $(1) | ||
unshare --map-root-user --map-auto ./$$< | ||
endef | ||
|
||
$(foreach test,$(tests),$(eval $(call test_target,$(test)))) | ||
|
||
test: integration_test $(addprefix @,$(tests)) all .tmp | ||
./$< | ||
|
||
$(foreach object,$(filter-out $(generated),$(objects:.o=.c)),$(eval $(shell $(CC) -MM $(object) | tr -d '\\'))) | ||
|
||
.tmp: | ||
echo MKTEMP $@ | ||
ln -sf "$$(mktemp -d)" $@ | ||
|
||
.tmp/chroot: test_chroot_import_bin do_syscall | .tmp | ||
[ -e $@ ] || mkdir $@ | ||
./$< $@ $(wordlist 2,$(words $^),$^) $$(command -v sh) $$(command -v cat) $$(command -v head) $$(command -v tail) | ||
|
||
$(executables) $(tests): %: $$($$@_objects) | ||
echo LINK $^ '->' $@ | ||
$(CC) $(CFLAGS) -o $@ $^ | ||
|
||
$(generated): %.c: gen_% | ||
echo GEN $@ | ||
CC=$(CC) ./$< > $@ | ||
|
||
$(uniq_objects): %.o: %.c | ||
echo CC $< '->' $@ | ||
$(CC) $(CFLAGS) -o $@ -c $< |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# seccomp_fake_xattr | ||
|
||
Emulate extended attribute ([xattr](https://man7.org/linux/man-pages/man7/xattr.7.html)) operations in user space. | ||
|
||
All xattr related syscalls are intercepted using the seccomp user-space notification mechanism ([seccomp_unotify](https://man7.org/linux/man-pages/man2/seccomp_unotify.2.html)) and their results emulated by a user-space handler. | ||
The handler stores its own xattr database in memory, without ever accessing extended attributes on the underlying file system. | ||
|
||
The main use of this is for system / distribution image builds. | ||
It allows the build to set extended attributes that it would normally not have access to (i.e. if the build is running inside an unprivileged container or on a host with security modules loaded) in such a way that later tar archive / disk image / etc creation steps see and includes these attributes correctly. | ||
|
||
|
||
## Usage | ||
|
||
``` | ||
./fake_xattr [command] [args...] | ||
``` | ||
|
||
`[command]` and all of its child processes will then run with their xattr syscalls intercepted and emulated. | ||
|
||
> [!IMPORTANT] | ||
> In order to install seccomp filters for its child processes, `fake_xattr` needs the `CAP_SYS_ADMIN` capability in its user namspace. | ||
> Therefore, as an unprivileged user, it is necessary to run it with `unshare --map-root-user --map-auto ./fake_xattr` or similar means. | ||
|
||
## Build | ||
|
||
To build the main tool run | ||
|
||
``` | ||
make fake_xattr | ||
``` | ||
|
||
This requires a standard linux build environment to be present. See [Dev Container](#dev-container) for the recommended way of setting this up. | ||
|
||
### Test | ||
|
||
To build and run the unit and integration tests run | ||
|
||
``` | ||
make test | ||
``` | ||
|
||
## Dev Container | ||
|
||
To simplify the build process this project includes a dev container. This can either be used directly by [VS Code](https://code.visualstudio.com/docs/devcontainers/containers) and [GitHub Codespaces](https://docs.github.com/en/codespaces) or as a regular container. | ||
|
||
To use it as a regular container run | ||
|
||
``` | ||
podman build -t dev .devcontainer | ||
podman run --rm \ | ||
--security-opt seccomp=unconfined \ | ||
--security-opt label=disable \ | ||
--security-opt apparmor=unconfined \ | ||
--userns keep-id:uid=1000,gid=1000 \ | ||
-v "$PWD:/home/dev/workdir" \ | ||
-w /home/dev/workdir \ | ||
-it dev | ||
``` | ||
|
||
> [!NOTE] | ||
> The `--userns keep-id:uid=1000,gid=1000` is needed because the dev container is configured to drop privileges to a dev user (`uid=1000 gid=1000`), while podman by default will map your host system user to `uid=0 gid=0`. | ||
> Thus the work directory would not otherwise be writable by the dev user. | ||
> [!TIP] | ||
> Older versions of podman do not support the `--userns keep-id:uid=1000,gid=1000` parameter. | ||
> For these versions you will need to use the long form: | ||
> `--uidmap 0:1:1000 --uidmap 1000:0:1 --uidmap 1001:1001:64536 --gidmap 0:1:1000 --gidmap 1000:0:1 --gidmap 1001:1001:64536` | ||
> This does exactly the same, just in a more verbose format. | ||
> [!TIP] | ||
> Running the dev container with docker instead of podman may work, but is not supported and you will need to setup a uid_map from your host user to the dev user inside the container. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#define array_size(X) (sizeof(X) / sizeof(*X)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include <stdio.h> | ||
|
||
#include "child_account.h" | ||
|
||
size_t get_children(int *list, size_t size) | ||
{ | ||
FILE *file; | ||
size_t len; | ||
|
||
file = fopen("/proc/thread-self/children", "r"); | ||
len = 0; | ||
for (int child; fscanf(file, "%d", &child) != EOF; ++len) if (len < size) list[len] = child; | ||
fclose(file); | ||
return len; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#include <stddef.h> | ||
|
||
size_t get_children(int *list, size_t size); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#define _GNU_SOURCE | ||
#include <linux/sched.h> | ||
#include <sched.h> | ||
#include <sys/mman.h> | ||
|
||
#include "clone_vfork.h" | ||
|
||
#define CLONE_STACK_SIZE 0x100000 | ||
|
||
pid_t clone_vfork(int (*func)(void *), void *arg, int flags) | ||
{ | ||
void *clone_stack; | ||
pid_t pid; | ||
|
||
clone_stack = mmap( | ||
NULL, | ||
CLONE_STACK_SIZE, | ||
PROT_READ | PROT_WRITE, | ||
MAP_PRIVATE | MAP_ANONYMOUS, | ||
-1, | ||
0 | ||
); | ||
|
||
if (!clone_stack) return -1; | ||
|
||
pid = clone(func, clone_stack + CLONE_STACK_SIZE, CLONE_VM | CLONE_VFORK | CLONE_CLEAR_SIGHAND | flags, arg); | ||
munmap(clone_stack, CLONE_STACK_SIZE); | ||
|
||
return pid; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#include <sys/types.h> | ||
|
||
pid_t clone_vfork(int (*func)(void *), void *arg, int flags); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#include <stdio.h> | ||
#include <unistd.h> | ||
|
||
extern int debug; | ||
|
||
#define __STR(x) #x | ||
#define _STR(x) __STR(x) | ||
#define debug_printf(fmt, ...) if (debug) fprintf(stderr, "\033[2mdebug: " __FILE__ ":" _STR(__LINE__) " (%s) [%d]: " fmt "\033[0m\n", __func__, getpid(), ##__VA_ARGS__) |
Oops, something went wrong.