unos-repository

APK repository for unos
git clone git://git.finwo.net/misc/unos-repository
Log | Files | Refs | README

commit 1dc19d4a300de03bc7bf0d9472297438e3a0eb54
parent 4efa6149ed102c9dccaa63907a52463d9975e45e
Author: finwo <finwo@pm.me>
Date:   Mon, 14 Sep 2026 17:58:49 +0200

Added kernel packages

Diffstat:
Mmk/build.sh | 187++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Amk/kernel.inc | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmk/rootfs.sh | 24++++++++++++++++++++----
Mpackages/README.md | 15+++++++++++++++
Mpackages/iproute2/template | 41++++++++++++++++++++++++-----------------
Apackages/linux-longterm/files/post-install.linux | 9+++++++++
Apackages/linux-longterm/template | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackages/linux-mainline/files/post-install.linux | 9+++++++++
Apackages/linux-mainline/template | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackages/linux-stable/files/post-install.linux | 9+++++++++
Apackages/linux-stable/template | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 486 insertions(+), 85 deletions(-)

diff --git a/mk/build.sh b/mk/build.sh @@ -29,6 +29,7 @@ checksum= depends= provides= replaces= +subpackages= FILESDIR="${ROOT}/packages/${PKG}/files" WORK="${ROOT}/build/work/${PKG}" @@ -36,6 +37,10 @@ SRCDEST="${ROOT}/build/work/sources" DESTDIR="${WORK}/dest" WRKSRC= OUTDIR="${ROOT}/build/repo" +# shared build logic for templates; set before the template is sourced so +# templates can `. "${MKDIR}/kernel.inc"` at the top level +MKDIR="${HERE}" +export MKDIR # Build-time sysroot (generated, never committed): libraries that other # packages build against install twice - once into DESTDIR (the shipped # .apk) and once into SYSROOT (headers + .so + prefix-fixed .pc files). @@ -104,7 +109,7 @@ if [ -n "${distfiles}" ]; then patch -d "${WRKSRC}" -p1 --no-backup-if-mismatch -i "${p}" done fi -export DESTDIR WRKSRC FILESDIR WORK SYSROOT +export DESTDIR WRKSRC FILESDIR WORK SYSROOT MKDIR # host-built tools first (muon), target sysroot visible to pkg-config. # Both are additive only; system cc/patch/curl/pkg-config resolve as before. export PATH="${ROOT}/build/host/bin:${PATH}" @@ -127,8 +132,6 @@ do_install KEY=$(resolve_sign_key) || die "no signing key (mk/keymgmt.sh use)" # --- emit signed .apk (v2): shell + pax-tar + openssl, no other languages --- -msg "${pkgname}: packing ${PKGVER}" - # fixed timestamp for the whole artifact (reproducible when pinned) : "${SOURCE_DATE_EPOCH:=$(date +%s)}" export SOURCE_DATE_EPOCH @@ -139,65 +142,121 @@ if [ ! -x "${HERE}/pax-tar" ] || [ "${HERE}/pax-tar.c" -nt "${HERE}/pax-tar" ]; cc -std=c99 -O2 -Wall -Wextra -o "${HERE}/pax-tar" "${HERE}/pax-tar.c" fi -CTRL="${WORK}/ctrl" -rm -rf "${CTRL}" -mkdir -p "${CTRL}" - -{ - printf 'pkgname = %s\n' "${pkgname}" - printf 'pkgver = %s\n' "${PKGVER}" - printf 'pkgdesc = %s\n' "${short_desc}" - printf 'url = %s\n' "${homepage}" - printf 'builddate = %s\n' "${SOURCE_DATE_EPOCH}" - printf 'packager = %s\n' "UNOS build driver (mk/build.sh)" - printf 'size = %s\n' "$(find "${DESTDIR}" -type f -printf '%s\n' | awk '{s+=$1} END {print s+0}')" - printf 'arch = %s\n' "x86_64" - printf 'origin = %s\n' "${pkgname}" - printf 'maintainer = %s\n' "${maintainer}" - printf 'license = %s\n' "${license}" - for d in ${depends}; do printf 'depend = %s\n' "${d}"; done - for p in ${provides}; do printf 'provides = %s\n' "${p}"; done - for r in ${replaces}; do printf 'replaces = %s\n' "${r}"; done -} > "${CTRL}/.PKGINFO" - -for s in pre-install post-install pre-deinstall post-deinstall pre-upgrade post-upgrade trigger; do - if [ -f "${FILESDIR}/${s}" ]; then - cp "${FILESDIR}/${s}" "${CTRL}/.${s}" - chmod 755 "${CTRL}/.${s}" +# spick <relpath>... : move staged paths from DESTDIR into the current +# SUBDEST (split staging). Only valid inside a sub_<name>() function. +spick() { + [ -n "${SUBDEST:-}" ] || die "spick outside a subpackage split" + [ $# -ge 1 ] || die "spick needs paths" + for _p in "$@"; do + [ -e "${DESTDIR}/${_p}" ] || die "spick: no such staged path: ${_p}" + mkdir -p "${SUBDEST}/$(dirname "${_p}")" + mv "${DESTDIR}/${_p}" "${SUBDEST}/${_p}" + done + # moves leave empty parent dirs behind; prune them so the remainder + # assert below sees real leftovers only (never DESTDIR itself) + find "${DESTDIR}" -mindepth 1 -depth -type d -empty -delete +} + +# emit_apk <stage> <pkgname> <desc> <depends> <provides> <replaces> <suffix> +# suffix "" = primary (scripts from FILESDIR/<s>); otherwise per-subpackage +# scripts from FILESDIR/<s>.<suffix>. +emit_apk() { + _stage=$1; _name=$2; _desc=$3; _depends=$4; _provides=$5; _replaces=$6; _sfx=$7 + _ctrl="${WORK}/ctrl.${_name}" + rm -rf "${_ctrl}" + mkdir -p "${_ctrl}" + + { + printf 'pkgname = %s\n' "${_name}" + printf 'pkgver = %s\n' "${PKGVER}" + printf 'pkgdesc = %s\n' "${_desc}" + printf 'url = %s\n' "${homepage}" + printf 'builddate = %s\n' "${SOURCE_DATE_EPOCH}" + printf 'packager = %s\n' "UNOS build driver (mk/build.sh)" + printf 'size = %s\n' "$(find "${_stage}" -type f -printf '%s\n' | awk '{s+=$1} END {print s+0}')" + printf 'arch = %s\n' "x86_64" + printf 'origin = %s\n' "${pkgname}" + printf 'maintainer = %s\n' "${maintainer}" + printf 'license = %s\n' "${license}" + for d in ${_depends}; do printf 'depend = %s\n' "${d}"; done + for p in ${_provides}; do printf 'provides = %s\n' "${p}"; done + for r in ${_replaces}; do printf 'replaces = %s\n' "${r}"; done + } > "${_ctrl}/.PKGINFO" + + for s in pre-install post-install pre-deinstall post-deinstall pre-upgrade post-upgrade trigger; do + if [ -z "${_sfx}" ]; then _f="${FILESDIR}/${s}"; else _f="${FILESDIR}/${s}.${_sfx}"; fi + if [ -f "${_f}" ]; then + cp "${_f}" "${_ctrl}/.${s}" + chmod 755 "${_ctrl}/.${s}" + fi + done + + # data segment (pax-tar: sorted, root-owned, per-file SHA1 headers). + # The data tar KEEPS its end-of-tar markers: it terminates the archive. + "${HERE}/pax-tar" "${_stage}" "${WORK}/data.${_name}.tar" + gzip -n -9 -f "${WORK}/data.${_name}.tar" + datahash=$(sha256sum "${WORK}/data.${_name}.tar.gz" | cut -d' ' -f1) + printf 'datahash = %s\n' "${datahash}" >> "${_ctrl}/.PKGINFO" + + # control segment (pax-tar without checksum records; host tar not trusted). + # The control tar must NOT carry end-of-tar markers: gunzipped, the package + # is one continuous tar stream (sig record, control files, data files) and + # only the data segment terminates it. This is the abuild-sign layout. + "${HERE}/pax-tar" --no-checksum "${_ctrl}" "${WORK}/control.${_name}.tar" + ctlsiz=$(stat -c%s "${WORK}/control.${_name}.tar") + head -c $((ctlsiz - 1024)) "${WORK}/control.${_name}.tar" > "${WORK}/controlnotr.${_name}.tar" + gzip -n -9 -f "${WORK}/controlnotr.${_name}.tar" + mv "${WORK}/controlnotr.${_name}.tar.gz" "${WORK}/control.${_name}.tar.gz" + + # signature segment: RSA/SHA1 over the control gzip stream bytes, single tar + # record with NO end-of-tar blocks, prepended to control.tar.gz in place + # (abuild-sign layout: .apk = signed-control + data = 3 gzip members). + KEYNAME=$(basename "${KEY}" .rsa) + openssl dgst -sha1 -sign "${KEY}" -out "${WORK}/sig.${_name}.bin" "${WORK}/control.${_name}.tar.gz" + mkdir -p "${WORK}/sigdir.${_name}" + cp "${WORK}/sig.${_name}.bin" "${WORK}/sigdir.${_name}/.SIGN.RSA.${KEYNAME}.rsa.pub" + "${HERE}/pax-tar" --no-checksum "${WORK}/sigdir.${_name}" "${WORK}/sig.${_name}.tar" + sigsiz=$(stat -c%s "${WORK}/sig.${_name}.tar") + head -c $((sigsiz - 1024)) "${WORK}/sig.${_name}.tar" > "${WORK}/signo.${_name}.tar" + gzip -n -9 -f "${WORK}/signo.${_name}.tar" + cat "${WORK}/signo.${_name}.tar.gz" "${WORK}/control.${_name}.tar.gz" > "${WORK}/signed-control.${_name}.tar.gz" + + cat "${WORK}/signed-control.${_name}.tar.gz" "${WORK}/data.${_name}.tar.gz" \ + > "${OUTDIR}/${_name}-${PKGVER}.apk" + + msg "done: ${OUTDIR}/${_name}-${PKGVER}.apk" +} + +# --- subpackages: one template, several .apks --- +# Template declares: subpackages="name ..." (hyphens fine), per-sub +# short_desc_<underscored>/depends_<underscored> (provides/replaces optional), +# and sub_<underscored>() splitting DESTDIR into SUBDEST via spick (move +# semantics: the tree is partitioned, never duplicated). After all splits +# DESTDIR must be empty - the primary packs the remainder, so for meta +# primaries this asserts the meta carries no files by construction. +if [ -n "${subpackages}" ]; then + for _sub in ${subpackages}; do + _u=$(printf '%s' "${_sub}" | tr '-' '_') + command -v "sub_${_u}" >/dev/null 2>&1 || die "no sub_${_u}() for subpackage ${_sub}" + eval "_sd=\${short_desc_${_u}:-}" + [ -n "${_sd}" ] || die "template sets no short_desc_${_u}" + eval "_dd=\${depends_${_u}:-}" + eval "_pv=\${provides_${_u}:-}" + eval "_rp=\${replaces_${_u}:-}" + SUBDEST="${WORK}/split/${_sub}" + rm -rf "${SUBDEST}" + mkdir -p "${SUBDEST}" + export SUBDEST + msg "${pkgname}: split ${_sub}" + "sub_${_u}" + unset SUBDEST + msg "${pkgname}: packing ${_sub} ${PKGVER}" + emit_apk "${WORK}/split/${_sub}" "${_sub}" "${_sd}" "${_dd}" "${_pv}" "${_rp}" "${_sub}" + done + if [ -n "$(ls -A "${DESTDIR}")" ]; then + die "unpartitioned files remain for primary ${pkgname}: $(ls -A "${DESTDIR}" | head)" fi -done - -# data segment (pax-tar: sorted, root-owned, per-file SHA1 headers). -# The data tar KEEPS its end-of-tar markers: it terminates the archive. -"${HERE}/pax-tar" "${DESTDIR}" "${WORK}/data.tar" -gzip -n -9 -f "${WORK}/data.tar" -datahash=$(sha256sum "${WORK}/data.tar.gz" | cut -d' ' -f1) -printf 'datahash = %s\n' "${datahash}" >> "${CTRL}/.PKGINFO" - -# control segment (pax-tar without checksum records; host tar not trusted). -# The control tar must NOT carry end-of-tar markers: gunzipped, the package -# is one continuous tar stream (sig record, control files, data files) and -# only the data segment terminates it. This is the abuild-sign layout. -"${HERE}/pax-tar" --no-checksum "${CTRL}" "${WORK}/control.tar" -ctlsiz=$(stat -c%s "${WORK}/control.tar") -head -c $((ctlsiz - 1024)) "${WORK}/control.tar" > "${WORK}/controlnotr.tar" -gzip -n -9 -f "${WORK}/controlnotr.tar" -mv "${WORK}/controlnotr.tar.gz" "${WORK}/control.tar.gz" - -# signature segment: RSA/SHA1 over the control gzip stream bytes, single tar -# record with NO end-of-tar blocks, prepended to control.tar.gz in place -# (abuild-sign layout: .apk = signed-control + data = 3 gzip members). -KEYNAME=$(basename "${KEY}" .rsa) -openssl dgst -sha1 -sign "${KEY}" -out "${WORK}/sig.bin" "${WORK}/control.tar.gz" -mkdir -p "${WORK}/sigdir" -cp "${WORK}/sig.bin" "${WORK}/sigdir/.SIGN.RSA.${KEYNAME}.rsa.pub" -"${HERE}/pax-tar" --no-checksum "${WORK}/sigdir" "${WORK}/sig.tar" -sigsiz=$(stat -c%s "${WORK}/sig.tar") -head -c $((sigsiz - 1024)) "${WORK}/sig.tar" > "${WORK}/signo.tar" -gzip -n -9 -f "${WORK}/signo.tar" -cat "${WORK}/signo.tar.gz" "${WORK}/control.tar.gz" > "${WORK}/signed-control.tar.gz" - -cat "${WORK}/signed-control.tar.gz" "${WORK}/data.tar.gz" \ - > "${OUTDIR}/${pkgname}-${PKGVER}.apk" - -msg "done: ${OUTDIR}/${pkgname}-${PKGVER}.apk" +fi + +msg "${pkgname}: packing ${PKGVER}" +emit_apk "${DESTDIR}" "${pkgname}" "${short_desc}" "${depends}" "${provides}" "${replaces}" "" diff --git a/mk/kernel.inc b/mk/kernel.inc @@ -0,0 +1,95 @@ +#!/bin/sh +# mk/kernel.inc - shared kbuild recipe for the linux-{longterm,stable, +# mainline} templates. Sourced at template top level via +# . "${MKDIR}/kernel.inc" (MKDIR is exported by the driver before the +# template is sourced). +# +# The template sets variables, then the standard phases call in: +# version=... (checksum, distfiles as usual) +# KDELTA_ENABLE="IKCONFIG IKCONFIG_PROC" (forced =y, no CONFIG_ prefix) +# KDELTA_MODULE="NET_VRF" (forced =m) +# KDELTA_DISABLE="MODULE_SIG" (forced n) +# KASSERT_Y="IPV6 ..." KASSERT_M="NET_VRF" KASSERT_N="MODULE_SIG" +# do_configure() { kernel_configure; } +# do_build() { kernel_build; } +# do_install() { kernel_install; } +# sub_linux() { spick boot "lib/modules"; } # linux +# sub_linux_headers() { spick usr/include; } # linux-headers +# empty sub functions (`:`) for the two metas. +# +# Conventions (locked here, not per template): +# - defconfig + explicit deltas + olddefconfig. Deltas and asserts are +# fail-loud: a renamed/vanished symbol breaks the build, never the boot. +# - modules_install with INSTALL_MOD_STRIP=1; build/source symlinks removed +# (absolute links into the build tree must never ship). Module dependency +# maps are generated at build time with host kmod depmod -b (explicit +# version: uname lies in containers) and asserted present. +# - headers = sanitized `headers_install` (user API). A module-build tree +# (full source for out-of-tree .ko like openbcm) is a separate follow-up, +# not silently half-shipped here. +# - KREL (e.g. 6.18.51, 7.3.0-rc3) is derived via `make kernelrelease`, +# never assumed from ${version}: pre-release trees differ (7.3_rc3 apk +# version vs 7.3.0-rc3 uname). All install paths use KREL. +# - Reproducibility: KBUILD_BUILD_USER/HOST/TIMESTAMP (from +# SOURCE_DATE_EPOCH, driver-exported). + +kernel_configure() { + cd "${WRKSRC}" + [ -f scripts/config ] || die "kernel: scripts/config missing" + msg "kernel: defconfig" + make ARCH=x86_64 defconfig >/dev/null || die "kernel: defconfig failed" + for s in ${KDELTA_ENABLE:-}; do + ./scripts/config --enable "CONFIG_${s}" || die "kernel: cannot enable CONFIG_${s}" + done + for s in ${KDELTA_MODULE:-}; do + ./scripts/config --module "CONFIG_${s}" || die "kernel: cannot modularize CONFIG_${s}" + done + for s in ${KDELTA_DISABLE:-}; do + ./scripts/config --disable "CONFIG_${s}" || die "kernel: cannot disable CONFIG_${s}" + done + if [ -n "${KDELTA_ENABLE:-}${KDELTA_MODULE:-}${KDELTA_DISABLE:-}" ]; then + make ARCH=x86_64 olddefconfig >/dev/null || die "kernel: olddefconfig failed" + fi + for s in ${KASSERT_Y:-}; do + grep -qx "CONFIG_${s}=y" .config || die "kernel: CONFIG_${s} is not =y" + done + for s in ${KASSERT_M:-}; do + grep -qx "CONFIG_${s}=m" .config || die "kernel: CONFIG_${s} is not =m" + done + for s in ${KASSERT_N:-}; do + grep -qx "# CONFIG_${s} is not set" .config || die "kernel: CONFIG_${s} is set" + done + KREL=$(make -s ARCH=x86_64 kernelrelease) || die "kernel: kernelrelease failed" + [ -n "${KREL}" ] || die "kernel: empty KREL" + export KREL + msg "kernel: release ${KREL}" +} + +kernel_build() { + cd "${WRKSRC}" + make ARCH=x86_64 -j"$(nproc)" \ + KBUILD_BUILD_USER=unos \ + KBUILD_BUILD_HOST=unos \ + KBUILD_BUILD_TIMESTAMP="$(date -u -d "@${SOURCE_DATE_EPOCH}" '+%Y-%m-%d %H:%M:%S')" \ + bzImage modules || die "kernel: build failed" + [ -f arch/x86/boot/bzImage ] || die "kernel: bzImage missing" +} + +kernel_install() { + cd "${WRKSRC}" + install -D -m 644 arch/x86/boot/bzImage "${DESTDIR}/boot/vmlinuz-${KREL}" + install -D -m 644 System.map "${DESTDIR}/boot/System.map-${KREL}" + install -D -m 644 .config "${DESTDIR}/boot/config-${KREL}" + make ARCH=x86_64 INSTALL_MOD_PATH="${DESTDIR}" INSTALL_MOD_STRIP=1 \ + modules_install >/dev/null || die "kernel: modules_install failed" + # absolute build-tree symlinks must never ship + rm -f "${DESTDIR}/lib/modules/${KREL}/build" "${DESTDIR}/lib/modules/${KREL}/source" + make ARCH=x86_64 INSTALL_HDR_PATH="${DESTDIR}/usr" \ + headers_install >/dev/null || die "kernel: headers_install failed" + # dependency maps at build time (explicit version: uname lies in userns) + command -v depmod >/dev/null 2>&1 || die "kernel: host depmod missing" + depmod -b "${DESTDIR}" "${KREL}" || die "kernel: depmod failed" + [ -d "${DESTDIR}/lib/modules/${KREL}" ] || die "kernel: no modules dir" + [ -f "${DESTDIR}/lib/modules/${KREL}/modules.dep" ] || die "kernel: no modules.dep" + [ -f "${DESTDIR}/usr/include/linux/version.h" ] || die "kernel: no headers" +} diff --git a/mk/rootfs.sh b/mk/rootfs.sh @@ -21,17 +21,33 @@ if [ -d "${ROOTFS}" ]; then [ "${1:-}" = "--force" ] || { echo "rootfs.sh: ${ROOTFS} exists (use --force)" >&2; exit 1; } rm -rf "${ROOTFS}" fi -mkdir -p "${ROOTFS}" "${CACHE}" +mkdir -p "${ROOTFS}" "${CACHE}" "${ROOTFS}/proc" + +# apk executes control scripts chrooted via memfd (/proc/self/fd), so the +# target needs /proc mounted or every post-install fails with ENOENT - +# even though install order/dep wiring is otherwise correct. Bind host +# /proc in a private namespace for the transactions (same unshare pattern +# as mk/chroot.sh; the --pid flag is what makes the proc mount permitted). +# Namespace evaporates on exit; repo/cache stay visible (same fs view). +apk_ns() { + unshare --user --map-root-user --mount --propagation private --pid --fork \ + sh -c 'mount -t proc proc "$1/proc" && shift && "$@"' \ + _ "${ROOTFS}" "$@" +} echo "==> trust seed: unos-keys via explicit --allow-untrusted" -"${APK}" --root "${ROOTFS}" --initdb --usermode \ +# NOTE: no --usermode here (apk refuses it as root, and we are mapped root +# inside the namespace). Ownership maps back to the invoking user outside, +# and no shipped package carries device nodes or setuid bits that would +# behave differently - if one ever does, assembly needs a second look. +apk_ns "${APK}" --root "${ROOTFS}" --initdb \ --cache-dir "${CACHE}" --repository "${REPO}" \ --allow-untrusted add unos-keys echo "==> UNOS system (fully trusted from here on)" -"${APK}" --root "${ROOTFS}" --usermode \ +apk_ns "${APK}" --root "${ROOTFS}" \ --cache-dir "${CACHE}" --repository "${REPO}" \ - add base-files glibc busybox unos-firstboot tinyssh libmnl zlib openssl iproute2 apk-tools + add base-files glibc busybox unos-firstboot tinyssh libmnl zlib openssl iproute2 apk-tools linux-longterm # Deterministic loader cache: package post-installs refresh it during the # transaction, but assembly must not depend on script-execution order. diff --git a/packages/README.md b/packages/README.md @@ -67,3 +67,18 @@ directory is ever built by hand on a target switch. (`/bin/sh` must exist before apk runs their scripts). `mk/rootfs.sh` additionally runs `ldconfig` explicitly after assembly so the chroot cache never depends on script-execution order. +- **Subpackages: one template, several .apks.** A template may declare + `subpackages="name ..."` with per-sub `short_desc_<underscored>` / + `depends_<underscored>` (provides/replaces optional) and a + `sub_<underscored>()` function partitioning `DESTDIR` into `SUBDEST` + via `spick` (move semantics - never duplicated). Per-subpackage control + scripts live at `files/<script>.<subname>` (e.g. + `post-install.linux`). After all splits `DESTDIR` must be empty: the + primary packs the remainder, so meta primaries are empty by + construction. Version pins between outputs must carry the full pkgver + incl. `-r` (`depends="linux=${version}-r${revision}"`) - apk's `=` + never matches a bare version. Single-output templates are unaffected. +- **Control scripts run chrooted via memfd.** apk v3 executes scripts + through `/proc/self/fd`, so any `apk add` that runs scripts needs + `/proc` mounted in the target (live systems always have it; + `mk/rootfs.sh` binds it for assembly; the installer must too). diff --git a/packages/iproute2/template b/packages/iproute2/template @@ -1,7 +1,7 @@ # Template file for 'iproute2' pkgname=iproute2 version=6.19.0 -revision=2 +revision=3 short_desc="IP routing and network device configuration tools" maintainer="finwo <finwo@pm.me>" license="GPL-2.0-only" @@ -11,11 +11,14 @@ checksum=9332213d35480b647086a70c302de8568de83455a98774d35de216c4ce191006 depends="libmnl libcap" # Notes: -# - `ip` ONLY (PLAN section 10): the top-level `install: all` would build -# every subdir (tc needs flex/bison/xtables/elf), so the template builds -# SUBDIRS="lib ip" and cherry-picks the `ip` binary plus the iproute2 -# config files (rt_tables symbolic names live there). tc/bridge/misc -# (ss!)/rtmon land as separate design decisions, not silent extras. +# - `ip` + `rtmon` + `ss` ONLY (PLAN section 10): the top-level +# `install: all` would build every subdir (tc needs flex/bison/xtables/elf), +# so the template builds SUBDIRS="lib ip misc" and cherry-picks the three +# binaries plus the iproute2 config files (rt_tables symbolic names live +# there). tc/bridge/nstat/ifstat/rtacct/lnstat land as separate design +# decisions, not silent extras. misc needs host bison/flex (build-only +# code generators, same category as perl for openssl); its libbpf/rpc +# includes are already gated off by the scrub below. # - libmnl comes from the sysroot (extended-error-ack decoding) and libcap # (drop_cap ambient-capability hygiene); configure finds both via the # driver-exported PKG_CONFIG_PATH. @@ -50,23 +53,27 @@ do_build() { cd "${WRKSRC}" # iproute2 has no kbuild-style flag tracking: objects from a previous # configure do not rebuild when config.mk flags change. Clean - # unconditionally (cheap for lib+ip; full-tree cost is why SUBDIRS is - # limited here too). - make SUBDIRS="lib ip" clean >/dev/null - make -j"$(nproc)" SUBDIRS="lib ip" - [ -x ip/ip ] || die "iproute2: ip binary missing after build" - needed=$(readelf -d ip/ip | sed -n 's/^.*NEEDED.*\[\(.*\)\].*$/\1/p' | sort) - for lib in ${needed}; do - case "${lib}" in - libmnl.so.*|libcap.so.*|libc.so.*) : ;; - *) die "iproute2: unexpected NEEDED entry: ${lib}" ;; - esac + # unconditionally (cheap for lib+ip+misc; full-tree cost is why SUBDIRS + # is limited here too). + make SUBDIRS="lib ip misc" clean >/dev/null + make -j"$(nproc)" SUBDIRS="lib ip misc" + for bin in ip/ip ip/rtmon misc/ss; do + [ -x "${bin}" ] || die "iproute2: ${bin} missing after build" + needed=$(readelf -d "${bin}" | sed -n 's/^.*NEEDED.*\[\(.*\)\].*$/\1/p' | sort) + for lib in ${needed}; do + case "${lib}" in + libmnl.so.*|libcap.so.*|libc.so.*) : ;; + *) die "iproute2: ${bin}: unexpected NEEDED entry: ${lib}" ;; + esac + done done } do_install() { cd "${WRKSRC}" install -D -m 755 ip/ip "${DESTDIR}/sbin/ip" + install -D -m 755 ip/rtmon "${DESTDIR}/sbin/rtmon" + install -D -m 755 misc/ss "${DESTDIR}/sbin/ss" for f in etc/iproute2/*; do [ -f "${f}" ] || continue install -D -m 644 "${f}" "${DESTDIR}/usr/share/iproute2/$(basename "${f}")" diff --git a/packages/linux-longterm/files/post-install.linux b/packages/linux-longterm/files/post-install.linux @@ -0,0 +1,9 @@ +#!/bin/sh +# linux post-install: refresh module maps for the RUNNING kernel. +# On live targets uname matches and this regenerates; at assembly time +# (userns, host uname) /lib/modules/<running> is absent and this is a +# no-op - the build-time maps generated with explicit -b/-version ship in +# the package and are always present. Never bare-depmod unconditionally: +# uname lies in containers. +ver=$(uname -r) +if [ -d "/lib/modules/${ver}" ]; then exec depmod; fi diff --git a/packages/linux-longterm/template b/packages/linux-longterm/template @@ -0,0 +1,64 @@ +# Template file for 'linux-longterm' +# +# One template, four outputs (driver subpackages): +# linux-longterm meta, depends linux=<version> +# linux-longterm-headers meta, depends linux-headers=<version> +# linux image + modules + maps (post-install: depmod) +# linux-headers sanitized headers_install (user API only - +# NOT a module-build tree; openbcm needs a +# follow-up, see mk/kernel.inc) +pkgname=linux-longterm +version=6.18.51 +revision=0 +short_desc="UNOS kernel meta - longterm line" +maintainer="finwo <finwo@pm.me>" +license="GPL-2.0-only" +homepage="https://www.kernel.org" +distfiles="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.18.51.tar.xz" +checksum=ba2f60f858bf4d1f929101faa356c93dc8b925b17aaa9f95eabd4627758df613 +# the meta points at this line's kernel build (exact pin incl. revision - +# apk's `=` only matches the full pkgver, so a bare version never matches) +depends="linux=${version}-r${revision}" +subpackages="linux-longterm-headers linux linux-headers" + +short_desc_linux_longterm_headers="UNOS kernel headers meta - longterm line" +depends_linux_longterm_headers="linux-headers=${version}-r${revision}" +short_desc_linux="Linux kernel image and modules" +depends_linux="busybox" +short_desc_linux_headers="Linux kernel sanitized headers" +depends_linux_headers= + +# Notes: +# - defconfig + deltas (see mk/kernel.inc for the shared mechanics). +# Verified against 6.18 defconfig: everything load-bearing except VRF +# (absent) and IKCONFIG (off) already defaults right; NEXTHOP is not a +# symbol at all (nexthop objects are unconditional core). MODULE_SIG +# already defaults off (no ephemeral signing keys). VRF's full dep +# chain (IP_MULTIPLE_TABLES + NET_L3_MASTER_DEV + IPV6_MULTIPLE_TABLES) +# is enabled explicitly - olddefconfig silently drops symbols whose +# deps are unmet, which is exactly what the asserts guard against. +# - linux needs busybox first: its post-install runs under /bin/sh +# (same ordering rule as the library packages). + +# shellcheck disable=SC1091 +. "${MKDIR}/kernel.inc" + +KDELTA_ENABLE="IKCONFIG IKCONFIG_PROC NET_L3_MASTER_DEV IPV6_MULTIPLE_TABLES" +KDELTA_MODULE="NET_VRF" +KDELTA_DISABLE="" +KASSERT_Y="IPV6 IP_MULTIPLE_TABLES IPV6_MULTIPLE_TABLES NET_L3_MASTER_DEV DEVTMPFS_MOUNT BLK_DEV_INITRD SERIAL_8250_CONSOLE MODULES IKCONFIG IKCONFIG_PROC" +KASSERT_M="NET_VRF" +KASSERT_N="MODULE_SIG" + +do_configure() { kernel_configure; } +do_build() { kernel_build; } +do_install() { kernel_install; } + +sub_linux_longterm_headers() { :; } +sub_linux() { + spick boot + spick lib/modules +} +sub_linux_headers() { + spick usr/include +} diff --git a/packages/linux-mainline/files/post-install.linux b/packages/linux-mainline/files/post-install.linux @@ -0,0 +1,9 @@ +#!/bin/sh +# linux post-install: refresh module maps for the RUNNING kernel. +# On live targets uname matches and this regenerates; at assembly time +# (userns, host uname) /lib/modules/<running> is absent and this is a +# no-op - the build-time maps generated with explicit -b/-version ship in +# the package and are always present. Never bare-depmod unconditionally: +# uname lies in containers. +ver=$(uname -r) +if [ -d "/lib/modules/${ver}" ]; then exec depmod; fi diff --git a/packages/linux-mainline/template b/packages/linux-mainline/template @@ -0,0 +1,62 @@ +# Template file for 'linux-mainline' +# +# One template, four outputs (driver subpackages): +# linux-mainline meta, depends linux=<version> +# linux-mainline-headers meta, depends linux-headers=<version> +# linux image + modules + maps (post-install: depmod) +# linux-headers sanitized headers_install (user API only - +# NOT a module-build tree; openbcm needs a +# follow-up, see mk/kernel.inc) +# +# NOTE: mainline is a moving target by design (rc snapshots weekly). The +# pin below is TOFU: git.kernel.org publishes no sha256 for the torvalds +# snapshots (only .tar.sign PGP). Re-pin every bump, verify the tag out +# of band. +pkgname=linux-mainline +version=7.3_rc3 +revision=0 +short_desc="UNOS kernel meta - mainline snapshot" +maintainer="finwo <finwo@pm.me>" +license="GPL-2.0-only" +homepage="https://www.kernel.org" +distfiles="https://git.kernel.org/torvalds/t/linux-7.3-rc3.tar.gz" +checksum=49b24119d7b92da75bba0daf5da4f7735c8cb948757a282e849092dcc681d8dd +# the meta points at this line's kernel build (exact pin incl. revision - +# apk's `=` only matches the full pkgver, so a bare version never matches) +depends="linux=${version}-r${revision}" +subpackages="linux-mainline-headers linux linux-headers" + +short_desc_linux_mainline_headers="UNOS kernel headers meta - mainline snapshot" +depends_linux_mainline_headers="linux-headers=${version}-r${revision}" +short_desc_linux="Linux kernel image and modules" +depends_linux="busybox" +short_desc_linux_headers="Linux kernel sanitized headers" +depends_linux_headers= + +# Notes: same recipe as linux-longterm (defconfig + deltas, mk/kernel.inc). +# Deltas re-verified per line - symbols move between releases, the asserts +# fail loud if this list rots. KREL here is 7.3.0-rc3 (derived, not equal +# to the 7.3_rc3 apk version) - all install paths use KREL. + +# shellcheck disable=SC1091 +. "${MKDIR}/kernel.inc" + +KDELTA_ENABLE="IKCONFIG IKCONFIG_PROC NET_L3_MASTER_DEV IPV6_MULTIPLE_TABLES" +KDELTA_MODULE="NET_VRF" +KDELTA_DISABLE="" +KASSERT_Y="IPV6 IP_MULTIPLE_TABLES IPV6_MULTIPLE_TABLES NET_L3_MASTER_DEV DEVTMPFS_MOUNT BLK_DEV_INITRD SERIAL_8250_CONSOLE MODULES IKCONFIG IKCONFIG_PROC" +KASSERT_M="NET_VRF" +KASSERT_N="MODULE_SIG" + +do_configure() { kernel_configure; } +do_build() { kernel_build; } +do_install() { kernel_install; } + +sub_linux_mainline_headers() { :; } +sub_linux() { + spick boot + spick lib/modules +} +sub_linux_headers() { + spick usr/include +} diff --git a/packages/linux-stable/files/post-install.linux b/packages/linux-stable/files/post-install.linux @@ -0,0 +1,9 @@ +#!/bin/sh +# linux post-install: refresh module maps for the RUNNING kernel. +# On live targets uname matches and this regenerates; at assembly time +# (userns, host uname) /lib/modules/<running> is absent and this is a +# no-op - the build-time maps generated with explicit -b/-version ship in +# the package and are always present. Never bare-depmod unconditionally: +# uname lies in containers. +ver=$(uname -r) +if [ -d "/lib/modules/${ver}" ]; then exec depmod; fi diff --git a/packages/linux-stable/template b/packages/linux-stable/template @@ -0,0 +1,56 @@ +# Template file for 'linux-stable' +# +# One template, four outputs (driver subpackages): +# linux-stable meta, depends linux=<version> +# linux-stable-headers meta, depends linux-headers=<version> +# linux image + modules + maps (post-install: depmod) +# linux-headers sanitized headers_install (user API only - +# NOT a module-build tree; openbcm needs a +# follow-up, see mk/kernel.inc) +pkgname=linux-stable +version=7.2.5 +revision=0 +short_desc="UNOS kernel meta - stable line" +maintainer="finwo <finwo@pm.me>" +license="GPL-2.0-only" +homepage="https://www.kernel.org" +distfiles="https://cdn.kernel.org/pub/linux/kernel/v7.x/linux-7.2.5.tar.xz" +checksum=55ddf0df8325d9dad96fcff7bd93977d22e3f50af06527572af59b77c7632b78 +# the meta points at this line's kernel build (exact pin incl. revision - +# apk's `=` only matches the full pkgver, so a bare version never matches) +depends="linux=${version}-r${revision}" +subpackages="linux-stable-headers linux linux-headers" + +short_desc_linux_stable_headers="UNOS kernel headers meta - stable line" +depends_linux_stable_headers="linux-headers=${version}-r${revision}" +short_desc_linux="Linux kernel image and modules" +depends_linux="busybox" +short_desc_linux_headers="Linux kernel sanitized headers" +depends_linux_headers= + +# Notes: same recipe as linux-longterm (defconfig + deltas, mk/kernel.inc). +# Deltas re-verified per line - symbols move between releases, the asserts +# fail loud if this list rots. + +# shellcheck disable=SC1091 +. "${MKDIR}/kernel.inc" + +KDELTA_ENABLE="IKCONFIG IKCONFIG_PROC NET_L3_MASTER_DEV IPV6_MULTIPLE_TABLES" +KDELTA_MODULE="NET_VRF" +KDELTA_DISABLE="" +KASSERT_Y="IPV6 IP_MULTIPLE_TABLES IPV6_MULTIPLE_TABLES NET_L3_MASTER_DEV DEVTMPFS_MOUNT BLK_DEV_INITRD SERIAL_8250_CONSOLE MODULES IKCONFIG IKCONFIG_PROC" +KASSERT_M="NET_VRF" +KASSERT_N="MODULE_SIG" + +do_configure() { kernel_configure; } +do_build() { kernel_build; } +do_install() { kernel_install; } + +sub_linux_stable_headers() { :; } +sub_linux() { + spick boot + spick lib/modules +} +sub_linux_headers() { + spick usr/include +}