Apparmor on musl


(Jordan) #1

Hi guys,

So I’ve gotten apparmor-2.13 working on musl; I had to do a fair bit of rebasing patches from alpine, gentoo and the apparmor gitlab.

It seems to be working fine but before I submit a PR I was going to do a bit of work to the template - just had a couple of questions!

Firstly, how do you apply patches to only musl archs?

Secondly, the current apparmor package in void-packages doesn’t copy over the runit files from {FILESDIR} > /etc/sv, how is this conventionally done in the template?

Many thanks.

In case anyone wants to use it in the current form, here are the template and patches:

[jord@bebop apparmor]$ cat template

# Template file for 'apparmor'
pkgname=apparmor
version=2.13.0
revision=1
_short_ver=${version%\.*}
wrksrc="${pkgname}-v${_short_ver}"
configure_args="--prefix=/usr --with-perl --with-python"
patch_args="-Np1"
hostmakedepends="bison flex autoconf automake libtool"
makedepends="perl python3-devel swig"
depends="runit-void-apparmor python3 libapparmor"
only_for_archs="x86_64-musl i686"
short_desc="Mandatory access control to restrict programs"
maintainer="Olivier Mauras <olivier@mauras.ch>"
license="GPL-3"
homepage="https://gitlab.com/apparmor/apparmor"
distfiles="https://gitlab.com/apparmor/apparmor/-/archive/v${_short_ver}/apparmor-v${_short_ver}.tar.gz"
checksum="fdafa0b71cbf574cce76a1ea1542b4540fa1c1040f80d0f0866fc0056ec37747"

pre_build() {
	# Replace release profiles by our owns
	cd ${wrksrc}

	# Put in place our own profiles
	cp ${FILESDIR}/profiles/* profiles/apparmor.d/
	mv profiles/apparmor.d/usr.bin.iputils-ping profiles/apparmor/profiles/extras/
}

do_build() {
	cd ${wrksrc}/libraries/libapparmor
	NOCONFIGURE=1 ./autogen.sh
	./configure ${configure_args}
	make ${makejobs}

	export CFLAGS+=" -fPIC"
	export LDFLAGS+=" -fPIE -pie"

	cd ${wrksrc}/binutils
	make ${makejobs}

	cd ${wrksrc}/utils
	make ${makejobs}

	cd ${wrksrc}/parser
	sed -i 's#$(DESTDIR)/sbin#$(DESTDIR)/usr/bin#g' Makefile
	sed -i 's#${DESTDIR}/lib#${DESTDIR}/usr/lib#g' Makefile
	make ${makejobs}

	cd ${wrksrc}/profiles
	make ${makejobs}
}

do_install() {
	cd ${wrksrc}/libraries/libapparmor
	make DESTDIR=${DESTDIR} install

	cd ${wrksrc}/binutils
	make DESTDIR=${DESTDIR} install

	cd ${wrksrc}/utils
	make DESTDIR=${DESTDIR} BINDIR=${DESTDIR}/usr/bin install

	cd ${wrksrc}/parser
	make DESTDIR=${DESTDIR} install

	cd ${wrksrc}/profiles
	make DESTDIR=${DESTDIR} install
}

post_install() {
	# Put Vim syntax in the correct place
	mkdir -p ${DESTDIR}/usr/share/vim/vim80/syntax/
	mv ${DESTDIR}/usr/share/apparmor/apparmor.vim ${DESTDIR}/usr/share/vim/vim80/syntax/

	# We want to keep this empty directory
	touch ${DESTDIR}/etc/apparmor.d/disable/.empty
}

apparmor-vim_package() {
	short_desc+=" - Vim syntax"
	depends="vim"
	pkg_install() {
		vmove usr/share/vim/vim80/syntax/apparmor.vim
		vmove usr/share/man/man5/apparmor.vim.5
	}
}

libapparmor_package() {
	short_desc+=" - Library"
	pkg_install() {
		vmove "usr/lib/libapparmor.so*"
		vmove usr/lib/perl5
		vmove "usr/lib/python3.6/site-packages/LibAppArmor*"
		vmove usr/share/man/man2
		vmove usr/share/man/man3
	}
}

libapparmor-devel_package() {
	short_desc+=" - Library development files"
	depends="${sourcepkg}-${version}_${revision}"
	pkg_install() {
		vmove usr/include/
		vmove "usr/lib/*.a"
		vmove usr/lib/pkgconfig
	}
}

[jord@bebop apparmor]$ cat patches/apparmor-2.13-musl.patch

--- /dev/null
+++ b/parser/missingdefs.h
@@ -0,0 +1,9 @@
+#ifndef PARSER_MISSINGDEFS_H
+#define PARSER_MISSINGDEFS_H
+
+typedef int (*__compar_fn_t) (const void *, const void *);
+typedef __compar_fn_t comparison_fn_t;
+typedef void (*__free_fn_t) (void *__nodep);
+
+#endif
+
--- a/binutils/Makefile
+++ b/binutils/Makefile
@@ -52,7 +52,7 @@ SRCS = aa_enabled.c
 HDRS =
 TOOLS = aa-enabled aa-exec
 
-AALIB = -Wl,-Bstatic -lapparmor  -Wl,-Bdynamic -lpthread
+AALIB = -Wl,-Bstatic -lapparmor  -Wl,-Bdynamic -lpthread -lintl
 
 ifdef USE_SYSTEM
   # Using the system libapparmor so Makefile dependencies can't be used
--- a/parser/Makefile
+++ b/parser/Makefile
@@ -90,7 +90,7 @@ AAREDIR= libapparmor_re
 AAREOBJECT = ${AAREDIR}/libapparmor_re.a
 AAREOBJECTS = $(AAREOBJECT)
 AARE_LDFLAGS = -static-libgcc -static-libstdc++ -L. $(LDFLAGS)
-AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
+AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread -lintl

 ifdef USE_SYSTEM
   # Using the system libapparmor so Makefile dependencies can't be used
--- a/parser/parser_alias.c
+++ b/parser/parser_alias.c
@@ -24,6 +24,7 @@
 #include "immunix.h"
 #include "parser.h"
 #include "profile.h"
+#include "missingdefs.h"
 
 struct alias_rule {
 	char *from;
--- a/parser/parser_symtab.c
+++ b/parser/parser_symtab.c
@@ -24,6 +24,7 @@
 
 #include "immunix.h"
 #include "parser.h"
+#include "missingdefs.h"
 
 enum var_type {
 	sd_boolean,

[jord@bebop apparmor]$ cat patches/libapparmor-2.13-musl.patch

--- a/libraries/libapparmor/configure.ac
+++ b/libraries/libapparmor/configure.ac
@@ -81,7 +81,7 @@ AM_CONDITIONAL(HAVE_RUBY, test x$with_ruby = xyes)
 AC_HEADER_STDC
 AC_CHECK_HEADERS(unistd.h stdint.h syslog.h)
 
-AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv])
+AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv scandirat reallocarray])
 
 AM_PROG_CC_C_O
 AC_C_CONST
--- a/libraries/libapparmor/src/Makefile.am
+++ b/libraries/libapparmor/src/Makefile.am
@@ -46,9 +46,9 @@ af_protos.h: /usr/include/netinet/in.h
 	 LC_ALL=C  sed  -n -e "/IPPROTO_MAX/d"  -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" $< > $@
 
 lib_LTLIBRARIES = libapparmor.la
-noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
+noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h secure_getenv.h scandirat.h private.h PMurHash.h
 
-libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c PMurHash.c
+libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c secure_getenv.c scandirat.c private.c features.c kernel_interface.c policy_cache.c PMurHash.c
 libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
 	-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
 
--- a/libraries/libapparmor/src/libapparmor.map
+++ b/libraries/libapparmor/src/libapparmor.map
@@ -115,6 +115,7 @@ PRIVATE {
 		_aa_autoclose;
 		_aa_autofclose;
 		_aa_dirat_for_each;
+		_aa_asprintf;
 	local:
 		*;
 };
--- /dev/null
+++ b/libraries/libapparmor/src/scandirat.c
@@ -0,0 +1,62 @@
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#include "scandirat.h"
+
+#ifndef HAVE_SCANDIRAT
+
+int scandirat(int dir_fd, const char *dirp, struct dirent ***namelist,
+	int (*filter)(const struct dirent *),
+	int (*compar)(const struct dirent **, const struct dirent **))
+{
+	int fd;
+	DIR *d;
+	struct dirent *de, **names=0, **tmp;
+	size_t cnt=0, len=0;
+	int old_errno = errno;
+
+
+	fd = openat(dir_fd, dirp, O_RDONLY|O_CLOEXEC);
+	if (fd == -1) return -1;
+
+	d = fdopendir(fd);
+
+	if (!d) {
+		close(fd);
+		return -1;
+	}
+
+	while ((errno=0), (de = readdir(d))) {
+		if (filter && !filter(de)) continue;
+		if (cnt >= len) {
+			len = 2*len+1;
+			if (len > SIZE_MAX/sizeof *names) break;
+			tmp = realloc(names, len * sizeof *names);
+			if (!tmp) break;
+			names = tmp;
+		}
+		names[cnt] = malloc(de->d_reclen);
+		if (!names[cnt]) break;
+		memcpy(names[cnt++], de, de->d_reclen);
+	}
+
+	closedir(d);
+
+	if (errno) {
+		if (names) while (cnt-->0) free(names[cnt]);
+		free(names);
+		return -1;
+	}
+	errno = old_errno;
+
+	if (compar) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))compar);
+	*namelist = names;
+	return cnt;
+}
+
+#endif
--- /dev/null
+++ b/libraries/libapparmor/src/scandirat.h
@@ -0,0 +1,13 @@
+#ifndef LIBAPPARMOR_SCANDIRAT_H
+#define LIBAPPARMOR_SCANDIRAT_H
+
+#include <dirent.h>
+
+#ifndef HAVE_SCANDIRAT
+int scandirat(int dir_fd, const char *dirp, struct dirent ***namelist,
+	int (*filter)(const struct dirent *),
+	int (*compar)(const struct dirent **, const struct dirent **));
+#endif
+
+#endif
+
--- /dev/null
+++ b/libraries/libapparmor/src/secure_getenv.c
@@ -0,0 +1,15 @@
+#include <stdlib.h>
+#include <sys/auxv.h>
+
+#include "secure_getenv.h"
+
+#ifndef HAVE_SECURE_GETENV
+char *secure_getenv(const char *name)
+{
+	if (!getauxval(AT_SECURE)) {
+		return getenv(name);
+	}
+	return NULL;
+}
+#endif
+
--- /dev/null
+++ b/libraries/libapparmor/src/secure_getenv.h
@@ -0,0 +1,8 @@
+#ifndef LIBAPPARMOR_SECURE_GETENV_H
+#define LIBAPPARMOR_SECURE_GETENV_H
+
+#ifndef HAVE_SECURE_GETENV
+char *secure_getenv(const char *name);
+#endif
+
+#endif
--- a/libraries/libapparmor/src/private.c
+++ b/libraries/libapparmor/src/private.c
@@ -39,10 +39,25 @@
  #ifdef HAVE___SECURE_GETENV
   #define secure_getenv __secure_getenv
  #else
-  #error neither secure_getenv nor __secure_getenv is available
+  #include "secure_getenv.h"
  #endif
 #endif
 
+#ifndef HAVE_SCANDIRAT
+ #include "scandirat.h"
+#endif
+
+/**
+ * Allow libapparmor to build on older glibcs and other libcs that do
+ * not support reallocarray.
+ */
+#ifndef HAVE_REALLOCARRY
+void *reallocarray(void *ptr, size_t nmemb, size_t size)
+{
+	return realloc(ptr, nmemb * size);
+}
+#endif
+
 struct ignored_suffix_t {
 	const char * text;
 	int len;

(maxice8 alter) #2

prefer not to (make portable patches) but if you need drop them on FILESDIR and

case $XBPS_TARGET_MACHINE in
  *-musl) patch -p1 < ${FILESDIR}/*.patch
esac

(maxice8 alter) #3

vsv <service which is in FILESDIR>


(Jordan) #4

@north1, many thanks! I’ll submit a PR in the morning