From e3a2e14ffa6a5842bc836d5809fcbb0494cbbfdd Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen Date: Wed, 5 Apr 2017 16:28:13 +0300 Subject: [PATCH] abuild: build in chroot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch is based on earlier work by Timo Teräs. --- Makefile | 2 +- abuild-rmtemp.c | 49 ++++++++++++++++++++++ abuild-sudo.c | 1 + abuild.conf | 4 +- abuild.in | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 abuild-rmtemp.c diff --git a/Makefile b/Makefile index a87d16f..ee11d19 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ datadir ?= $(prefix)/share/$(PACKAGE) SCRIPTS := abuild abuild-keygen abuild-sign newapkbuild \ abump apkgrel buildlab apkbuild-cpan checkapk \ apkbuild-gem-resolver -USR_BIN_FILES := $(SCRIPTS) abuild-tar abuild-gzsplit abuild-sudo abuild-fetch +USR_BIN_FILES := $(SCRIPTS) abuild-tar abuild-gzsplit abuild-sudo abuild-fetch abuild-rmtemp SAMPLES := sample.APKBUILD sample.initd sample.confd \ sample.pre-install sample.post-install AUTOTOOLS_TOOLCHAIN_FILES := config.sub config.guess diff --git a/abuild-rmtemp.c b/abuild-rmtemp.c new file mode 100644 index 0000000..36a12ec --- /dev/null +++ b/abuild-rmtemp.c @@ -0,0 +1,49 @@ +/* + * abuild-rmtemp + * Copyright (c) 2017 Kaarle Ritvanen + * Distributed under GPL-2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PREFIX "/var/tmp/abuild." + +static void fail() { + errx(1, "%s", strerror(errno)); +} + +static int handler(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { + return remove(fpath); +} + +int main(int argc, char **argv) { + if (argc < 2) return 0; + + if (getuid()) { + argv[0] = "-abuild-rmtemp"; + execv("/usr/bin/abuild-sudo", argv); + } + + if (strncmp(argv[1], PREFIX, strlen(PREFIX)) || \ + strchr(argv[1] + strlen(PREFIX), '/')) + errx(1, "Invalid path: %s", argv[1]); + + struct stat s; + if (lstat(argv[1], &s)) fail(); + struct passwd *p = getpwnam(getenv("USER")); + if (!p) errx(1, "Incorrect user"); + if (s.st_uid != p->pw_uid) errx(1, "Permission denied"); + + if (nftw(argv[1], handler, 512, FTW_DEPTH)) fail(); + + return 0; +} diff --git a/abuild-sudo.c b/abuild-sudo.c index c877e7a..2d691e8 100644 --- a/abuild-sudo.c +++ b/abuild-sudo.c @@ -27,6 +27,7 @@ static const char* valid_cmds[] = { "/bin/addgroup", "/usr/sbin/addgroup", "/sbin/apk", + "/usr/bin/abuild-rmtemp", NULL }; diff --git a/abuild.conf b/abuild.conf index a0d9f0b..3b6636e 100644 --- a/abuild.conf +++ b/abuild.conf @@ -22,7 +22,7 @@ REPODEST=$HOME/packages/ #MAINTAINER="$PACKAGER" # what to clean up after a successful build -CLEANUP="srcdir pkgdir deps" +CLEANUP="srcdir bldroot pkgdir deps" # what to cleanup after a failed build -ERROR_CLEANUP="deps" +ERROR_CLEANUP="bldroot deps" diff --git a/abuild.in b/abuild.in index 8e3b87c..2698ed4 100644 --- a/abuild.in +++ b/abuild.in @@ -83,6 +83,11 @@ cleanup() { fi for i; do case $i in + bldroot) + if [ "$BUILD_ROOT" ]; then + msg "Cleaning up build chroot" + abuild-rmtemp "$BUILD_ROOT" + fi;; pkgdir) msg "Cleaning up pkgdir"; rm -rf "$pkgbasedir";; srcdir) msg "Cleaning up srcdir"; rm -rf "$srcdir";; deps) @@ -1992,6 +1997,106 @@ checksum() { echo "sha512sums=\"$sha512sums\"" >>"$APKBUILD" } +subst() { + ( + for key in $(git config --list --name-only); do + k=${key#abuild.} + [ $k != $key ] && \ + eval "export $k=\"$(git config --get $key)\"" + done + + export mirror version + [ "$mirror" ] || mirror=http://dl-cdn.alpinelinux.org/alpine + + if [ -z "$version" ]; then + version=$(git symbolic-ref --short HEAD) + [ "$version" ] && \ + version=$(expr "$version" : '\([0-9]\+\(\.[0-9]\+\)*\)-') && \ + version=v${version} + [ "$version" ] || version=edge + fi + + envsubst + ) +} + +rootbld() { + if apk_up2date && [ -z "$force" ]; then + msg "Package is up to date" + return + fi + + [ "$CBUILD" = "$CHOST" ] || die "rootbld: cross-building not supported currently" + + local cmd + for cmd in bwrap git; do + [ -x "$(which $cmd)" ] || die "rootbld: $cmd not installed" + done + + logcmd "chroot building building $repo/$pkgname-$pkgver-r$pkgrel" + + # check early if we have abuild key + abuild-sign --installed + + # networking business + sanitycheck + clean + fetch + verify + + msg "Preparing build chroot..." + + BUILD_ROOT=$(mktemp -d /var/tmp/abuild.XXXXXXXXXX) + local aportsgit=${APORTSDIR:-${startdir}} + + mkdir -p "$BUILD_ROOT/proc" "$BUILD_ROOT/etc/apk/keys" \ + "$BUILD_ROOT/$HOME/.abuild" "$BUILD_ROOT/$aportsgit" \ + "$BUILD_ROOT/$SRCDEST" "$BUILD_ROOT/$REPODEST" \ + "$BUILD_ROOT/tmp/pkg" "$BUILD_ROOT/tmp/src" \ + "$BUILD_ROOT/usr/bin" "$pkgbasedir" "$REPODEST" \ + "$srcdir" + + cp /etc/abuild.conf "$BUILD_ROOT/etc" + cp /etc/apk/keys/* "$BUILD_ROOT/etc/apk/keys" + + local repo_template=$aportsgit/$repo/.rootbld-repositories + local repofile=$BUILD_ROOT/etc/apk/repositories + if [ -s "$repo_template" ]; then + subst < "$repo_template" + else + local prefix='$mirror/$version' + subst <<-EOF + $prefix/main + $prefix/community + EOF + fi > "$repofile" + echo "$REPODEST/$repo" >> "$repofile" + + calcdeps + $SUDO_APK add --initdb --root "$BUILD_ROOT" --update \ + abuild alpine-base build-base git $hostdeps $builddeps + + local bwrap_opts="" + options_has "net" || bwrap_opts="$bwrap_opts --unshare-net" + bwrap --unshare-ipc --unshare-uts $bwrap_opts \ + --ro-bind "$BUILD_ROOT" / \ + --proc /proc \ + --dev-bind /dev /dev \ + --ro-bind "$HOME/.abuild" "$HOME/.abuild" \ + --ro-bind "$aportsgit" "$aportsgit" \ + --bind "$SRCDEST" "$SRCDEST" \ + --bind "$BUILD_ROOT/tmp/src" "$srcdir" \ + --bind "$BUILD_ROOT/tmp/pkg" "$pkgbasedir" \ + --bind "$BUILD_ROOT/tmp" /tmp \ + --bind "$REPODEST" "$REPODEST" \ + --hostname "build-edge-$CARCH" \ + --chdir "$startdir" \ + --setenv PATH /bin:/usr/bin:/sbin:/usr/sbin \ + /usr/bin/abuild $force symlinksrc unpack prepare mkusers build rootpkg + update_abuildrepo_index + cleanup $CLEANUP +} + stripbin() { local bin if options_has "!strip" || [ "${subpkgarch:-$pkgarch}" = "noarch" ]; then @@ -2241,6 +2346,7 @@ usage() { listpkg List target packages package Create package in \$REPODEST prepare Apply patches + rootbld Build package in clean chroot rootpkg Run 'package', the split functions and create apks as fakeroot sanitycheck Basic sanity check of APKBUILD snapshot Create a \$giturl or \$svnurl snapshot and upload to \$disturl @@ -2308,6 +2414,8 @@ repo=${repo##*/} SRCDEST=${SRCDEST:-$startdir} +BUILD_ROOT= + # set a default CC : ${CC:=gcc} export CC