From f5297cee8a2960782ed4061774b2b555c154ce85 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 12 Aug 2026 18:45:57 -0400 Subject: [PATCH 01/28] nix+patchset: build kernels from upstream tarballs + an IGLOO patch series Replaces the Docker + submodule build with a Nix flake sourcing the kernel as a pristine kernel.org tarball plus an explicit IGLOO patch series. Why: - Toolchains were unversioned `wget https://musl.cc/*-cross.tgz` downloads, so shipped kernels had no recorded compiler identity. kernelsmith resolves the (kernel version, arch) -> toolchain mapping from pinned Bootlin SDKs instead. - .gitmodules named the WRONG branches: it declared main_6.7 for linux/6.13 while the pin was the head of main_6.13 -- trees 89,775 commits apart. A `git submodule update --remote` would have silently regressed the kernel. Basing on a release tag makes that class of drift unrepresentable. - Taking the kernel as a derivation input is what makes MODVERSIONS CRC skew between vmlinux and igloo.ko unrepresentable rather than merely detectable. Series, verified by scripts/verify-series.sh against the branches they replace: - 4.10: 38 patches on v4.10; matches new_4.10 except four upstream export-ignore'd paths absent from every release tarball (.gitattributes, .get_maintainer.ignore, two arch/sh linker scripts) -- none build-affecting. - 6.13: 33 patches on v6.13; tree a1e70bc2 is byte-identical to main_6.13. The four non-IGLOO commits main_6.13 carried are all upstream: it forked immediately before the final x86_urgent merge and cherry-picked them back. Only 5 of the 23 same-subject patches are byte-identical across versions -- the new-file additions -- so core/ holds 5 and the rest are per-version. Shared files were never shared patches; hook-site code differs because its context does. configs/ is unchanged: the cpp -P -undef assembly runs inside the derivation, so no linuxManualConfig migration is needed. 18 of 20 cells build; loongarch64 and riscv64 await kernelsmith arch support and are listed as `missingArches` rather than silently dropped. --- flake.lock | 66 + flake.nix | 108 + nix/config.nix | 30 + nix/kernel.nix | 168 + nix/matrix.nix | 36 + nix/source.nix | 49 + ...nging-bridge-mac-addrs-from-firmadyn.patch | 26 + .../0003-reboot.c-add-igloo_block_halt.patch | 66 + .../0004-socket.c-add-igloo_socket_hc.patch | 55 + .../4.10/0006-open.c-add-igloo_open_hc.patch | 36 + .../0007-sys.c-add-igloo_hc_newuname.patch | 39 + ...space.c-add-igloo_should_block_mount.patch | 38 + .../0009-ioctl.c-add-igloo_ioctl_hc.patch | 37 + patches/4.10/0010-igloobase-add-driver.patch | 723 +++++ .../0011-exec.c-add-igloo_task_size.patch | 32 + .../0012-mmap.c-add-igloo_task_size.patch | 36 + patches/4.10/0014-add-syscalls.h.patch | 141 + patches/4.10/0015-syscalls.h-fixes.patch | 67 + .../0016-syscals.h-fix-sname-in-define0.patch | 22 + ...mt_elf.c-add-igloo_task_size-support.patch | 42 + .../4.10/0018-compat.h-syscalls-support.patch | 110 + ...-on-gcc-ilog2-constant-optimizations.patch | 124 + .../0020-extern-yylloc-so-gcc-is-happy.patch | 36 + ...with-GCC-versions-8-for-some-targets.patch | 24 + ...gloo_weaksyms-fix-igloo_hc_open-type.patch | 29 + ...aksyms-forward-proper-types-for-4.10.patch | 53 + .../0024-igloobase.c-4.10-compliance.patch | 23 + .../0025-osi_notifier-4.10-compliance.patch | 27 + ...syscalls_info_report-4.10-compliance.patch | 70 + .../4.10/0027-socket.c-add-config_igloo.patch | 35 + ...loo_weaksyms-fix-up-passed-arguments.patch | 28 + ..._report-handle-different-4.10-issues.patch | 30 + ...pat.h-formatting-and-forward-declare.patch | 48 + ...ebug-calls-now-pr_emerg-when-enabled.patch | 83 + ...33-open.c-fix-fd-in-igloo_open_hc-29.patch | 36 + patches/4.10/0034-kprobe-options.patch | 50 + .../4.10/0035-igloo-fix-igloo_task_size.patch | 407 +++ .../4.10/0037-igloo-move-into-procfs.patch | 194 ++ .../0038-igloo-move-into-signal-handler.patch | 69 + patches/4.10/series | 38 + ...nging-bridge-mac-addrs-from-firmadyn.patch | 26 + .../0007-reboot.c-add-igloo_block_halt.patch | 66 + .../0008-socket.c-add-igloo_socket_hc.patch | 52 + .../6.13/0010-open.c-add-igloo_open_hc.patch | 36 + .../0011-sys.c-add-igloo_hc_newuname.patch | 33 + ...space.c-add-igloo_should_block_mount.patch | 39 + .../0013-ioctl.c-add-igloo_ioctl_hc.patch | 52 + patches/6.13/0014-igloobase-add-driver.patch | 723 +++++ .../0015-exec.c-add-igloo_task_size.patch | 32 + .../0016-mmap.c-add-igloo_task_size.patch | 36 + .../0017-util.c-add-igloo_task_size.patch | 36 + patches/6.13/0019-add-syscalls.h.patch | 2729 +++++++++++++++++ ...0020-syscall_wrapper-add-x86-support.patch | 152 + ...-syscall_wrapper.h-add-arm64-support.patch | 169 + ...-syscall_wrapper.h-add-riscv-support.patch | 166 + ...mt_elf.c-add-igloo_task_size-support.patch | 42 + .../6.13/0024-compat.h-syscalls-support.patch | 93 + patches/6.13/0025-compat.h-add-define0.patch | 79 + ...loo_weaksyms-fix-up-igloo_ioctl-type.patch | 28 + .../6.13/0028-socket.c-add-CONFIG_IGLOO.patch | 52 + ...029-compat.h-add-forward-declaration.patch | 21 + ...ebug-calls-now-pr_emerg-when-enabled.patch | 55 + ...31-open.c-fix-fd-in-igloo_open_hc-30.patch | 35 + patches/6.13/0032-kprobe-options.patch | 78 + ...-kprobes-fix-single-step-bug-on-mips.patch | 126 + .../6.13/0034-igloo-fix-igloo_task_size.patch | 280 ++ .../6.13/0036-igloo-move-into-procfs.patch | 180 ++ .../0037-igloo-move-into-signal-handler.patch | 69 + patches/6.13/series | 33 + patches/README.md | 70 + patches/base.json | 10 + patches/core/add-hypercall.h.patch | 358 +++ patches/core/add-igloo.h.patch | 44 + patches/core/add-igloo_syscall_macros.h.patch | 116 + ...eclarations-for-forward-declarations.patch | 23 + patches/core/update-hypercall.h.patch | 424 +++ scripts/export-series.sh | 42 + scripts/import-series.sh | 46 + scripts/verify-series.sh | 72 + 79 files changed, 10054 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/config.nix create mode 100644 nix/kernel.nix create mode 100644 nix/matrix.nix create mode 100644 nix/source.nix create mode 100644 patches/4.10/0001-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch create mode 100644 patches/4.10/0003-reboot.c-add-igloo_block_halt.patch create mode 100644 patches/4.10/0004-socket.c-add-igloo_socket_hc.patch create mode 100644 patches/4.10/0006-open.c-add-igloo_open_hc.patch create mode 100644 patches/4.10/0007-sys.c-add-igloo_hc_newuname.patch create mode 100644 patches/4.10/0008-namespace.c-add-igloo_should_block_mount.patch create mode 100644 patches/4.10/0009-ioctl.c-add-igloo_ioctl_hc.patch create mode 100644 patches/4.10/0010-igloobase-add-driver.patch create mode 100644 patches/4.10/0011-exec.c-add-igloo_task_size.patch create mode 100644 patches/4.10/0012-mmap.c-add-igloo_task_size.patch create mode 100644 patches/4.10/0014-add-syscalls.h.patch create mode 100644 patches/4.10/0015-syscalls.h-fixes.patch create mode 100644 patches/4.10/0016-syscals.h-fix-sname-in-define0.patch create mode 100644 patches/4.10/0017-binfmt_elf.c-add-igloo_task_size-support.patch create mode 100644 patches/4.10/0018-compat.h-syscalls-support.patch create mode 100644 patches/4.10/0019-give-up-on-gcc-ilog2-constant-optimizations.patch create mode 100644 patches/4.10/0020-extern-yylloc-so-gcc-is-happy.patch create mode 100644 patches/4.10/0021-Fix-build-with-GCC-versions-8-for-some-targets.patch create mode 100644 patches/4.10/0022-igloo_weaksyms-fix-igloo_hc_open-type.patch create mode 100644 patches/4.10/0023-igloo_weaksyms-forward-proper-types-for-4.10.patch create mode 100644 patches/4.10/0024-igloobase.c-4.10-compliance.patch create mode 100644 patches/4.10/0025-osi_notifier-4.10-compliance.patch create mode 100644 patches/4.10/0026-syscalls_info_report-4.10-compliance.patch create mode 100644 patches/4.10/0027-socket.c-add-config_igloo.patch create mode 100644 patches/4.10/0029-igloo_weaksyms-fix-up-passed-arguments.patch create mode 100644 patches/4.10/0030-syscalls_info_report-handle-different-4.10-issues.patch create mode 100644 patches/4.10/0031-compat.h-formatting-and-forward-declare.patch create mode 100644 patches/4.10/0032-igloo-debug-calls-now-pr_emerg-when-enabled.patch create mode 100644 patches/4.10/0033-open.c-fix-fd-in-igloo_open_hc-29.patch create mode 100644 patches/4.10/0034-kprobe-options.patch create mode 100644 patches/4.10/0035-igloo-fix-igloo_task_size.patch create mode 100644 patches/4.10/0037-igloo-move-into-procfs.patch create mode 100644 patches/4.10/0038-igloo-move-into-signal-handler.patch create mode 100644 patches/4.10/series create mode 100644 patches/6.13/0005-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch create mode 100644 patches/6.13/0007-reboot.c-add-igloo_block_halt.patch create mode 100644 patches/6.13/0008-socket.c-add-igloo_socket_hc.patch create mode 100644 patches/6.13/0010-open.c-add-igloo_open_hc.patch create mode 100644 patches/6.13/0011-sys.c-add-igloo_hc_newuname.patch create mode 100644 patches/6.13/0012-namespace.c-add-igloo_should_block_mount.patch create mode 100644 patches/6.13/0013-ioctl.c-add-igloo_ioctl_hc.patch create mode 100644 patches/6.13/0014-igloobase-add-driver.patch create mode 100644 patches/6.13/0015-exec.c-add-igloo_task_size.patch create mode 100644 patches/6.13/0016-mmap.c-add-igloo_task_size.patch create mode 100644 patches/6.13/0017-util.c-add-igloo_task_size.patch create mode 100644 patches/6.13/0019-add-syscalls.h.patch create mode 100644 patches/6.13/0020-syscall_wrapper-add-x86-support.patch create mode 100644 patches/6.13/0021-syscall_wrapper.h-add-arm64-support.patch create mode 100644 patches/6.13/0022-syscall_wrapper.h-add-riscv-support.patch create mode 100644 patches/6.13/0023-binfmt_elf.c-add-igloo_task_size-support.patch create mode 100644 patches/6.13/0024-compat.h-syscalls-support.patch create mode 100644 patches/6.13/0025-compat.h-add-define0.patch create mode 100644 patches/6.13/0026-igloo_weaksyms-fix-up-igloo_ioctl-type.patch create mode 100644 patches/6.13/0028-socket.c-add-CONFIG_IGLOO.patch create mode 100644 patches/6.13/0029-compat.h-add-forward-declaration.patch create mode 100644 patches/6.13/0030-igloo-debug-calls-now-pr_emerg-when-enabled.patch create mode 100644 patches/6.13/0031-open.c-fix-fd-in-igloo_open_hc-30.patch create mode 100644 patches/6.13/0032-kprobe-options.patch create mode 100644 patches/6.13/0033-kprobes-fix-single-step-bug-on-mips.patch create mode 100644 patches/6.13/0034-igloo-fix-igloo_task_size.patch create mode 100644 patches/6.13/0036-igloo-move-into-procfs.patch create mode 100644 patches/6.13/0037-igloo-move-into-signal-handler.patch create mode 100644 patches/6.13/series create mode 100644 patches/README.md create mode 100644 patches/base.json create mode 100644 patches/core/add-hypercall.h.patch create mode 100644 patches/core/add-igloo.h.patch create mode 100644 patches/core/add-igloo_syscall_macros.h.patch create mode 100644 patches/core/igloo.h-drop-declarations-for-forward-declarations.patch create mode 100644 patches/core/update-hypercall.h.patch create mode 100755 scripts/export-series.sh create mode 100755 scripts/import-series.sh create mode 100755 scripts/verify-series.sh diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..2396fee --- /dev/null +++ b/flake.lock @@ -0,0 +1,66 @@ +{ + "nodes": { + "kernelsmith": { + "inputs": { + "musl-cross-make": "musl-cross-make", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1783346134, + "narHash": "sha256-1izwxPuWd5+fSDbjbNjXLOGG1sGKq3UsQFbeDQYNP3Q=", + "owner": "rehosting", + "repo": "kernelsmith", + "rev": "7c5bb897c635f81b5077d32f2fb8a8ad4eb9ad6a", + "type": "github" + }, + "original": { + "owner": "rehosting", + "repo": "kernelsmith", + "type": "github" + } + }, + "musl-cross-make": { + "flake": false, + "locked": { + "lastModified": 1781646546, + "narHash": "sha256-ZGkLvkred/sDa2Mw2/1N+Nh8bvUyujxxOLTZDfd2qN4=", + "owner": "richfelker", + "repo": "musl-cross-make", + "rev": "227df8b99103f9c59f6570babf892978e293082f", + "type": "github" + }, + "original": { + "owner": "richfelker", + "repo": "musl-cross-make", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1735563628, + "narHash": "sha256-OnSAY7XDSx7CtDoqNh8jwVwh4xNL/2HaJxGjryLWzX8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b134951a4c9f3c995fd7be05f3243f8ecd65d798", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "kernelsmith": "kernelsmith", + "nixpkgs": [ + "kernelsmith", + "nixpkgs" + ] + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..ffd5e2a --- /dev/null +++ b/flake.nix @@ -0,0 +1,108 @@ +{ + description = "IGLOO kernels: pristine upstream tarball + IGLOO patch series, cross-built by kernelsmith"; + + nixConfig = { + extra-substituters = [ "https://rehosting-tools.cachix.org" ]; + extra-trusted-public-keys = [ + "rehosting-tools.cachix.org-1:iNKSaFwG7MfGn6Fk7oTmIcLHqfffQ+cQIE5gWc6MlY0=" + ]; + }; + + inputs = { + # Provides the (kernel version, arch) -> cross toolchain resolver. Replaces + # the embedded-toolchains Docker image, whose toolchains were unversioned + # `wget https://musl.cc/*-cross.tgz` downloads -- i.e. today's shipped + # kernels have no recorded compiler identity. + kernelsmith.url = "github:rehosting/kernelsmith"; + nixpkgs.follows = "kernelsmith/nixpkgs"; + }; + + outputs = + { self, nixpkgs, kernelsmith }: + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + inherit (pkgs) lib; + + # Upstream bases. These are REAL RELEASE TAGS -- the point of the patchset + # migration. Previously linux/6.13 was pinned to a tree based on v6.13~5 + # with three upstream commits cherry-picked forward, which no one would + # choose deliberately; those three are now simply present in the tarball. + bases = { + "4.10" = { + tag = "4.10"; + hash = "sha256-PJXZ8Em9CF5cNG0sd/BjuEJfGRRg/NOun+fpTgR33Es="; + }; + "6.13" = { + tag = "6.13"; + hash = "sha256-553Mbrhmlca6v7B8KGGRK2NdUHXGzRzQVn0eoVX4DW4="; + }; + }; + + matrix = import ./nix/matrix.nix; + configLib = import ./nix/config.nix { inherit pkgs; }; + sourceLib = import ./nix/source.nix { inherit pkgs; }; + mkKernel = import ./nix/kernel.nix { inherit pkgs kernelsmith; }; + + # kernelsmith's arch table covers 12 arches; these two are ours and not + # yet in it. Listed explicitly rather than silently dropped -- see draft 34 + # Slice 2, which lands them upstream instead of forking the table. + kernelsmithMissing = [ "loongarch64" "riscv64" ]; + + buildable = version: builtins.filter (t: !(builtins.elem t kernelsmithMissing)) matrix.${version}; + + kernelSrcFor = version: sourceLib.kernelSource { + patchesRoot = ./patches; + inherit version; + base = bases.${version}; + }; + + # Memoise per version: one patched source tree feeds every target. + sources = lib.genAttrs (builtins.attrNames matrix) kernelSrcFor; + + cellFor = version: target: mkKernel { + inherit version target; + src = sources.${version}; + config = configLib.rawConfig { + configsSrc = ./configs; + inherit version target; + }; + }; + + cells = lib.listToAttrs (lib.concatMap + (version: map + (target: lib.nameValuePair "kernel-${version}-${target}" (cellFor version target)) + (buildable version)) + (builtins.attrNames matrix)); + + in + { + packages.${system} = cells // { + default = cells."kernel-6.13-armel"; + + # Everything buildable today, in one derivation, for CI. + all = pkgs.linkFarm "igloo-kernels-all" + (lib.mapAttrsToList (n: v: { name = n; path = v; }) cells); + }; + + # The patched source trees, so `nix build .#sources.x86_64-linux."6.13"` + # gives you exactly what the kernel builds from -- useful for inspecting + # what the series produces without a full kernel build. + inherit sources; + + # Cells we cannot build until kernelsmith gains these arches. + missingArches = kernelsmithMissing; + + devShells.${system}.default = pkgs.mkShell { + packages = with pkgs; [ gnumake bc bison flex openssl elfutils git ]; + shellHook = '' + echo "linux_builder (nix-patchset)" + # NB: cell names contain a '.', which nix would parse as an attrpath + # separator -- quote the attribute or the build fails to resolve. + echo ' nix build .#packages.x86_64-linux."kernel-6.13-armel" one cell' + echo " nix build .#all every buildable cell" + echo " ./scripts/verify-series.sh ... prove a series matches its fork branch" + ''; + }; + }; +} diff --git a/nix/config.nix b/nix/config.nix new file mode 100644 index 0000000..ee1a2d6 --- /dev/null +++ b/nix/config.nix @@ -0,0 +1,30 @@ +# .config assembly -- deliberately identical to what _in_container_build.sh does: +# +# cpp -P -undef configs// -> .config +# make olddefconfig +# +# configs/ is UNCHANGED by the nix migration. The `#include "arm-common.inc"` +# fragments resolve relative to the including file, so pointing cpp at the +# config inside the copied configs tree is all that's needed. +# +# This is why the linuxManualConfig-vs-nixpkgs-config-machinery design fork +# never arises: we keep our own assembly, and nix only has to run it. +{ pkgs }: + +{ + # Just the cpp step. The `olddefconfig` half needs the kernel tree + toolchain, + # so it happens inside the kernel derivation (see kernel.nix). + rawConfig = + { configsSrc, version, target }: + pkgs.runCommand "igloo-config-${version}-${target}" + { + nativeBuildInputs = [ pkgs.stdenv.cc ]; + } + '' + if [ ! -f ${configsSrc}/${version}/${target} ]; then + echo "no config for ${target} at version ${version}" >&2 + exit 1 + fi + cpp -P -undef ${configsSrc}/${version}/${target} -o $out + ''; +} diff --git a/nix/kernel.nix b/nix/kernel.nix new file mode 100644 index 0000000..280b412 --- /dev/null +++ b/nix/kernel.nix @@ -0,0 +1,168 @@ +# One IGLOO kernel cell: (version, target) -> vmlinux + boot image + kernel-devel. +# +# This is a faithful port of _in_container_build.sh's per-target build, with the +# toolchain resolved by kernelsmith instead of an unpinned musl.cc download. +# +# Two outputs: +# out -- vmlinux, the arch's boot artifact, Module.symvers +# devel -- the kernel-devel tree out-of-tree modules build against +# +# The `devel` output is the point of the whole exercise: igloo_driver consumes +# it as a DERIVATION INPUT, so a different kernel is a different hash and a +# stale-CRC .ko cannot be produced. Note kernelsmith's own buildKernel installs +# `headers_install` output as kernel-devel -- those are UAPI headers, NOT the +# modules_prepare build tree. Hence this builds its own (see draft 34, Slice 3: +# upstream a build-tree output + buildModule to kernelsmith). +{ pkgs, kernelsmith }: + +let + inherit (pkgs) lib; + + # linux_builder TARGET -> kernel ARCH=, matching _in_container_build.sh's + # short_arch derivation (strip trailing el/eb, then collapse families). + shortArch = { + armel = "arm"; + arm64 = "arm64"; + mipseb = "mips"; + mipsel = "mips"; + mips64eb = "mips"; + mips64el = "mips"; + powerpc = "powerpc"; + powerpcle = "powerpc"; + powerpc64 = "powerpc"; + powerpc64le = "powerpc"; + loongarch64 = "loongarch"; + riscv64 = "riscv"; + x86_64 = "x86_64"; + }; + + # Extra make target beyond vmlinux, and where the artifact lands / ships as. + # arm64 deliberately ships Image.gz under the name zImage.arm64 -- preserving + # the existing consumer-visible naming, quirk and all. + bootArtifact = { + armel = { target = "zImage"; src = "arch/arm/boot/zImage"; dst = "zImage"; }; + arm64 = { target = "Image.gz"; src = "arch/arm64/boot/Image.gz"; dst = "zImage"; }; + x86_64 = { target = "bzImage"; src = "arch/x86/boot/bzImage"; dst = "bzImage"; }; + loongarch64 = { target = "vmlinuz.efi"; src = "arch/loongarch/boot/vmlinuz.efi"; dst = "vmlinuz.efi"; }; + riscv64 = { target = "Image"; src = "arch/riscv/boot/Image"; dst = "Image"; }; + }; + + # vmlinux is the deliverable boot artifact for these families. + deliversVmlinux = target: lib.hasPrefix "mips" target || lib.hasPrefix "powerpc" target; + +in +{ version, target, src, config }: + +let + arch = shortArch.${target} or (throw "kernel.nix: no ARCH mapping for target ${target}"); + boot = bootArtifact.${target} or null; + toolchain = kernelsmith.toolchainFor version target; + crossPrefix = "${toolchain.target}-"; + + # Trailing -Wno-error beats any -Werror the tree injects, at any depth. + # Same technique kernelsmith's kernel.nix uses; it subsumes the ad-hoc + # KCFLAGS/HOSTCFLAGS juggling _in_container_build.sh does for 4.10/powerpc. + ccShim = pkgs.runCommand "igloo-ccshim-${target}" { } '' + mkdir -p $out/bin + for n in gcc cc; do + if [ -x ${toolchain}/bin/${crossPrefix}$n ]; then + printf '#!%s\nexec %s/bin/%s%s "$@" -Wno-error\n' \ + ${pkgs.runtimeShell} ${toolchain} ${crossPrefix} "$n" > $out/bin/${crossPrefix}$n + chmod +x $out/bin/${crossPrefix}$n + fi + done + ''; + +in +pkgs.stdenv.mkDerivation { + pname = "igloo-kernel-${version}"; + inherit version; + name = "igloo-kernel-${version}-${target}"; + + outputs = [ "out" "devel" ]; + dontUnpack = true; + enableParallelBuilding = true; + + nativeBuildInputs = with pkgs; [ + ccShim toolchain + gnumake bc bison flex perl python3 rsync cpio kmod which + openssl elfutils pkg-config ubootTools util-linux zstd + ]; + + buildPhase = '' + runHook preBuild + export ARCH=${arch} + export CROSS_COMPILE=${crossPrefix} + export KBUILD_BUILD_TIMESTAMP="@0" + export KBUILD_BUILD_USER=nix + export KBUILD_BUILD_HOST=nix + + cp -r ${src} linux && chmod -R u+w linux + mkdir -p build + + echo ">>> .config (cpp-assembled fragment + olddefconfig)" + cp ${config} build/.config + make -C linux O=$PWD/build olddefconfig + + echo ">>> vmlinux ${lib.optionalString (boot != null) boot.target}" + make -C linux O=$PWD/build vmlinux ${lib.optionalString (boot != null) boot.target} -j$NIX_BUILD_CORES + + echo ">>> modules_prepare + modules (Module.symvers)" + make -C linux O=$PWD/build modules_prepare + make -C linux O=$PWD/build modules -j$NIX_BUILD_CORES + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + mkdir -p $out + + # vmlinux is always kept for analysis (osi/cosi extraction downstream); it + # is additionally the shipped boot artifact for mips*/powerpc*. + cp build/vmlinux $out/vmlinux.${target} + ${lib.optionalString (deliversVmlinux target) '' + ${crossPrefix}strip $out/vmlinux.${target} || true + ''} + ${lib.optionalString (boot != null) '' + cp build/${boot.src} $out/${boot.dst}.${target} + ''} + cp build/Module.symvers $out/ + + # --- kernel-devel: the modules_prepare result, source+build merged ------- + # Port of _in_container_build.sh's minimal-devel staging. An out-of-tree + # build (make -C $KDIR M=$PWD modules) needs Makefile/.config/Module.symvers, + # headers, arch Makefiles and scripts/ host tools -- not boot images or the + # bulk of tools/. + D=$devel + mkdir -p $D + cp build/.config build/Module.symvers $D/ + cp linux/Makefile linux/Kconfig $D/ || true + cp -r linux/include $D/ 2>/dev/null || true + cp -r build/include $D/ 2>/dev/null || true + mkdir -p $D/arch + for a in ${arch} ${lib.optionalString (arch == "x86_64") "x86"}; do + cp -r linux/arch/$a $D/arch/ 2>/dev/null || true + cp -r build/arch/$a $D/arch/ 2>/dev/null || true + done + cp -r linux/scripts $D/ 2>/dev/null || true + cp -r build/scripts $D/ 2>/dev/null || true + cp -r linux/tools $D/ 2>/dev/null || true + cp -r build/tools $D/ 2>/dev/null || true + + chmod -R u+w $D + # Slim: boot images and realmode are never read by a module build. + rm -rf $D/arch/*/boot $D/arch/*/realmode || true + # Keep tools/objtool (kbuild may run it on module objects); drop the rest. + if [ -d $D/tools ]; then + find $D/tools -mindepth 1 -maxdepth 1 ! -name objtool -exec rm -rf {} + || true + fi + runHook postInstall + ''; + + passthru = { inherit toolchain crossPrefix arch target version; }; + + meta = { + description = "IGLOO kernel ${version} for ${target} (kernelsmith toolchain, patch-series source)"; + platforms = [ "x86_64-linux" ]; + }; +} diff --git a/nix/matrix.nix b/nix/matrix.nix new file mode 100644 index 0000000..bdd0dc4 --- /dev/null +++ b/nix/matrix.nix @@ -0,0 +1,36 @@ +# The build matrix: kernel version -> targets. +# +# Targets are the linux_builder TARGET names (which are also kernelsmith's arch +# keys, deliberately -- they were already aligned). Sourced from configs//, +# excluding *.inc (fragments) and *.unused (retired targets). +# +# NOTE 4.10 is 7 targets, not 13: every powerpc* config is .unused, and +# loongarch64/riscv64 don't exist for that version. The full matrix is 20 cells, +# not the 26 a naive 2x13 suggests. +{ + "4.10" = [ + "armel" + "arm64" + "mipseb" + "mipsel" + "mips64eb" + "mips64el" + "x86_64" + ]; + + "6.13" = [ + "armel" + "arm64" + "mipseb" + "mipsel" + "mips64eb" + "mips64el" + "powerpc" + "powerpcle" + "powerpc64" + "powerpc64le" + "loongarch64" + "riscv64" + "x86_64" + ]; +} diff --git a/nix/source.nix b/nix/source.nix new file mode 100644 index 0000000..d0b1157 --- /dev/null +++ b/nix/source.nix @@ -0,0 +1,49 @@ +# Kernel source = PRISTINE UPSTREAM TARBALL + the IGLOO patch series. +# +# This is the change that removes the submodules. Previously the source was two +# long-lived fork branches of rehosting/linux, pinned by SHA in .gitmodules -- +# and .gitmodules named the WRONG branches (it declared main_6.7 for linux/6.13 +# while the pin was actually main_6.13, a tree 89,775 commits apart). Basing on +# a real upstream tag makes that class of drift unrepresentable. +# +# Each version's series file lists patch paths relative to patches/, so core +# patches and per-version adapters can interleave in a defined order: +# +# patches/6.13/series +# core/0001-add-hypercall.h.patch +# 6.13/0001-syscall_wrapper-add-x86-support.patch +{ pkgs }: + +let + inherit (pkgs) lib; + + # "4.10" -> "v4.x", "6.13" -> "v6.x" + seriesDir = version: "v${lib.versions.major version}.x"; + + # Read a series file into an ordered list of patch paths, ignoring blank lines + # and # comments (quilt convention). + readSeries = + patchesRoot: version: + let + file = "${patchesRoot}/${version}/series"; + lines = lib.splitString "\n" (builtins.readFile file); + keep = l: l != "" && !(lib.hasPrefix "#" l); + in + map (l: "${patchesRoot}/${l}") (builtins.filter keep (map lib.trim lines)); + +in +{ + inherit readSeries; + + # bases: { "4.10" = { tag = "4.10"; hash = "sha256-..."; }; ... } + kernelSource = + { patchesRoot, version, base }: + pkgs.applyPatches { + name = "linux-${base.tag}-igloo"; + src = pkgs.fetchurl { + url = "https://cdn.kernel.org/pub/linux/kernel/${seriesDir base.tag}/linux-${base.tag}.tar.xz"; + inherit (base) hash; + }; + patches = readSeries patchesRoot version; + }; +} diff --git a/patches/4.10/0001-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch b/patches/4.10/0001-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch new file mode 100644 index 0000000..648c8fd --- /dev/null +++ b/patches/4.10/0001-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch @@ -0,0 +1,26 @@ +From 45ce3c636a9d7cc71d2107b557168cd07de7838f Mon Sep 17 00:00:00 2001 +From: Andrew Fasano +Date: Mon, 18 Dec 2023 09:59:33 -0500 +Subject: [PATCH 01/38] Net: disallow changing bridge mac addrs (from + firmadyne. Unnecessary?) + +--- + net/core/dev.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 29101c9839..36c24d6100 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6595,6 +6595,11 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) + const struct net_device_ops *ops = dev->netdev_ops; + int err; + ++ if (dev->priv_flags & IFF_EBRIDGE) { ++ //Changing bridge mac-addrs only causes issues ++ return 0; ++ } ++ + if (!ops->ndo_set_mac_address) + return -EOPNOTSUPP; + if (sa->sa_family != dev->type) diff --git a/patches/4.10/0003-reboot.c-add-igloo_block_halt.patch b/patches/4.10/0003-reboot.c-add-igloo_block_halt.patch new file mode 100644 index 0000000..8ba93d8 --- /dev/null +++ b/patches/4.10/0003-reboot.c-add-igloo_block_halt.patch @@ -0,0 +1,66 @@ +From c5703859c7164c76dd2f875b00a378abe91a9b6a Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 17 Mar 2025 16:02:48 -0400 +Subject: [PATCH 03/38] reboot.c: add igloo_block_halt + +--- + kernel/reboot.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/kernel/reboot.c b/kernel/reboot.c +index bd30a973fe..c1a451d401 100644 +--- a/kernel/reboot.c ++++ b/kernel/reboot.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + /* + * this indicates whether you can reboot with ctrl-alt-del: the default is yes +@@ -213,6 +214,10 @@ void migrate_to_reboot_cpu(void) + */ + void kernel_restart(char *cmd) + { ++ if (igloo_block_halt) { ++ printk("IGLOO: refusing to restart\n"); ++ return; ++ } + kernel_restart_prepare(cmd); + migrate_to_reboot_cpu(); + syscore_shutdown(); +@@ -240,6 +245,10 @@ static void kernel_shutdown_prepare(enum system_states state) + */ + void kernel_halt(void) + { ++ if (igloo_block_halt) { ++ printk("IGLOO: refusing to halt\n"); ++ return; ++ } + kernel_shutdown_prepare(SYSTEM_HALT); + migrate_to_reboot_cpu(); + syscore_shutdown(); +@@ -256,6 +265,10 @@ EXPORT_SYMBOL_GPL(kernel_halt); + */ + void kernel_power_off(void) + { ++ if (igloo_block_halt) { ++ printk("IGLOO: refusing to power off\n"); ++ return; ++ } + kernel_shutdown_prepare(SYSTEM_POWER_OFF); + if (pm_power_off_prepare) + pm_power_off_prepare(); +@@ -284,6 +297,11 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, + char buffer[256]; + int ret = 0; + ++ if (igloo_block_halt) { ++ printk("IGLOO: refusing to reboot\n"); ++ return -EPERM; ++ } ++ + /* We only trust the superuser with rebooting the system. */ + if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT)) + return -EPERM; diff --git a/patches/4.10/0004-socket.c-add-igloo_socket_hc.patch b/patches/4.10/0004-socket.c-add-igloo_socket_hc.patch new file mode 100644 index 0000000..b1003cc --- /dev/null +++ b/patches/4.10/0004-socket.c-add-igloo_socket_hc.patch @@ -0,0 +1,55 @@ +From 6ad9f96f9f4634b8c4c80ff76faedb28de50c72a Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Tue, 29 Jul 2025 13:39:22 -0400 +Subject: [PATCH 04/38] socket.c: add igloo_socket_hc + +--- + net/socket.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/net/socket.c b/net/socket.c +index 0758e13754..75aa88e267 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -582,6 +582,9 @@ struct socket *sock_alloc(void) + } + EXPORT_SYMBOL(sock_alloc); + ++// forward declare igloo_sock_release ++void igloo_sock_release(struct socket *sock); ++ + /** + * sock_release - close a socket + * @sock: socket to close +@@ -593,6 +596,7 @@ EXPORT_SYMBOL(sock_alloc); + + void sock_release(struct socket *sock) + { ++ igloo_sock_release(sock); + if (sock->ops) { + struct module *owner = sock->ops->owner; + +@@ -1388,6 +1392,9 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, + return err; + } + ++// forward declare igloo_sock_bind ++void igloo_sock_bind(struct socket *sock, struct sockaddr_storage *address); ++ + /* + * Bind a name to a socket. Nothing much to do here since it's + * the protocol's responsibility to handle the local address. +@@ -1409,10 +1416,12 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) + err = security_socket_bind(sock, + (struct sockaddr *)&address, + addrlen); +- if (!err) ++ if (!err){ + err = sock->ops->bind(sock, + (struct sockaddr *) + &address, addrlen); ++ igloo_sock_bind(sock, address); ++ } + } + fput_light(sock->file, fput_needed); + } diff --git a/patches/4.10/0006-open.c-add-igloo_open_hc.patch b/patches/4.10/0006-open.c-add-igloo_open_hc.patch new file mode 100644 index 0000000..e3336fd --- /dev/null +++ b/patches/4.10/0006-open.c-add-igloo_open_hc.patch @@ -0,0 +1,36 @@ +From 41af0e8a2447242bdbaedbfc119af83842619a61 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 17 Mar 2025 15:13:19 -0400 +Subject: [PATCH 06/38] open.c: add igloo_open_hc + +--- + fs/open.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fs/open.c b/fs/open.c +index 9921f70bc5..309a355ef8 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -1035,6 +1035,11 @@ struct file *filp_clone_open(struct file *oldfile) + } + EXPORT_SYMBOL(filp_clone_open); + ++#ifdef CONFIG_IGLOO ++// forward declare for igloo_hc_open ++void igloo_hc_open(int dfd, struct filename *tmp, int fd); ++#endif ++ + long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) + { + struct open_flags op; +@@ -1048,6 +1053,10 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + ++#ifdef CONFIG_IGLOO ++ igloo_hc_open(dfd, tmp, fd); ++#endif ++ + fd = get_unused_fd_flags(flags); + if (fd >= 0) { + struct file *f = do_filp_open(dfd, tmp, &op); diff --git a/patches/4.10/0007-sys.c-add-igloo_hc_newuname.patch b/patches/4.10/0007-sys.c-add-igloo_hc_newuname.patch new file mode 100644 index 0000000..ce8d5d6 --- /dev/null +++ b/patches/4.10/0007-sys.c-add-igloo_hc_newuname.patch @@ -0,0 +1,39 @@ +From 70e12bb9d545ba3a5e20f7091285aee7aa20e059 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Tue, 29 Jul 2025 13:39:56 -0400 +Subject: [PATCH 07/38] sys.c: add igloo_hc_newuname + +--- + kernel/sys.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/kernel/sys.c b/kernel/sys.c +index 842914ef7d..f019b9cd50 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -1138,15 +1138,23 @@ static int override_release(char __user *release, size_t len) + return ret; + } + ++// forward declare make_igloo_utsname ++void igloo_hc_newuname(struct new_utsname *name); ++ + SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) + { + int errno = 0; ++ struct new_utsname tmp; + + down_read(&uts_sem); +- if (copy_to_user(name, utsname(), sizeof *name)) +- errno = -EFAULT; ++ memcpy(&tmp, utsname(), sizeof(tmp)); + up_read(&uts_sem); + ++ igloo_hc_newuname(&tmp); ++ ++ if (copy_to_user(name, utsname(), sizeof *name)) ++ errno = -EFAULT; ++ + if (!errno && override_release(name->release, sizeof(name->release))) + errno = -EFAULT; + if (!errno && override_architecture(name)) diff --git a/patches/4.10/0008-namespace.c-add-igloo_should_block_mount.patch b/patches/4.10/0008-namespace.c-add-igloo_should_block_mount.patch new file mode 100644 index 0000000..7d357b2 --- /dev/null +++ b/patches/4.10/0008-namespace.c-add-igloo_should_block_mount.patch @@ -0,0 +1,38 @@ +From 9b98cc9d5fc5e6b641c829cb5213ac05d1ae8bc7 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Tue, 29 Jul 2025 13:41:02 -0400 +Subject: [PATCH 08/38] namespace.c: add igloo_should_block_mount + +--- + fs/namespace.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 487ba30bb5..5c4c3fdbb9 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -2721,6 +2721,11 @@ char *copy_mount_string(const void __user *data) + return data ? strndup_user(data, PAGE_SIZE) : NULL; + } + ++#ifdef CONFIG_IGLOO ++// forward declare igloo_should_block_mount ++bool igloo_should_block_mount(struct path *path); ++#endif ++ + /* + * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to + * be given to the mount() call (ie: read-only, no-dev, no-suid etc). +@@ -2754,6 +2759,12 @@ long do_mount(const char *dev_name, const char __user *dir_name, + retval = user_path(dir_name, &path); + if (retval) + return retval; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_should_block_mount(&path)) { ++ return 0; ++ } ++#endif + + retval = security_sb_mount(dev_name, &path, + type_page, flags, data_page); diff --git a/patches/4.10/0009-ioctl.c-add-igloo_ioctl_hc.patch b/patches/4.10/0009-ioctl.c-add-igloo_ioctl_hc.patch new file mode 100644 index 0000000..ef8f990 --- /dev/null +++ b/patches/4.10/0009-ioctl.c-add-igloo_ioctl_hc.patch @@ -0,0 +1,37 @@ +From ef26bd547c0c66380faab13ef3c9eac27a07f5e8 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 17 Mar 2025 15:12:52 -0400 +Subject: [PATCH 09/38] ioctl.c: add igloo_ioctl_hc + +--- + fs/ioctl.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/fs/ioctl.c b/fs/ioctl.c +index cb9b029408..de77adea04 100644 +--- a/fs/ioctl.c ++++ b/fs/ioctl.c +@@ -612,6 +612,11 @@ static int ioctl_file_dedupe_range(struct file *file, void __user *arg) + return ret; + } + ++#ifdef CONFIG_IGLOO ++// forward declare igloo_ioctl ++void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user * argp); ++#endif ++ + /* + * When you add any new common ioctls to the switches above and below + * please update compat_sys_ioctl() too. +@@ -683,6 +688,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, + error = vfs_ioctl(filp, cmd, arg); + break; + } ++ ++#ifdef CONFIG_IGLOO ++ igloo_ioctl(error, inode, filp, cmd, argp); ++#endif ++ + return error; + } + diff --git a/patches/4.10/0010-igloobase-add-driver.patch b/patches/4.10/0010-igloobase-add-driver.patch new file mode 100644 index 0000000..454eeba --- /dev/null +++ b/patches/4.10/0010-igloobase-add-driver.patch @@ -0,0 +1,723 @@ +From c52cb61c3939876165143f28b07634bc918f13ac Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:10:02 -0400 +Subject: [PATCH 10/38] igloobase: add driver + +--- + drivers/Kconfig | 2 + + drivers/Makefile | 3 + + drivers/igloobase/Kconfig | 5 + + drivers/igloobase/Makefile | 2 + + drivers/igloobase/igloo_args.c | 118 ++++++++++ + drivers/igloobase/igloo_weaksyms.c | 112 +++++++++ + drivers/igloobase/igloobase.c | 28 +++ + drivers/igloobase/igloobase.h | 2 + + drivers/igloobase/igloobasehypercalls.h | 6 + + drivers/igloobase/osi_notifier.c | 55 +++++ + drivers/igloobase/syscalls_info_report.c | 281 +++++++++++++++++++++++ + 11 files changed, 614 insertions(+) + create mode 100644 drivers/igloobase/Kconfig + create mode 100644 drivers/igloobase/Makefile + create mode 100644 drivers/igloobase/igloo_args.c + create mode 100644 drivers/igloobase/igloo_weaksyms.c + create mode 100644 drivers/igloobase/igloobase.c + create mode 100644 drivers/igloobase/igloobase.h + create mode 100644 drivers/igloobase/igloobasehypercalls.h + create mode 100644 drivers/igloobase/osi_notifier.c + create mode 100644 drivers/igloobase/syscalls_info_report.c + +diff --git a/drivers/Kconfig b/drivers/Kconfig +index e1e2066cec..cc7f36cfff 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -202,4 +202,6 @@ source "drivers/hwtracing/intel_th/Kconfig" + + source "drivers/fpga/Kconfig" + ++source "drivers/igloobase/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 060026a02f..a299da7780 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -173,3 +173,6 @@ obj-$(CONFIG_STM) += hwtracing/stm/ + obj-$(CONFIG_ANDROID) += android/ + obj-$(CONFIG_NVMEM) += nvmem/ + obj-$(CONFIG_FPGA) += fpga/ ++ ++# Added ++obj-y += igloobase/ +\ No newline at end of file +diff --git a/drivers/igloobase/Kconfig b/drivers/igloobase/Kconfig +new file mode 100644 +index 0000000000..b20c5df509 +--- /dev/null ++++ b/drivers/igloobase/Kconfig +@@ -0,0 +1,5 @@ ++config IGLOO ++ bool "IGLOO module support" ++ default y ++ help ++ Support for IGLOO analysis +\ No newline at end of file +diff --git a/drivers/igloobase/Makefile b/drivers/igloobase/Makefile +new file mode 100644 +index 0000000000..1865aadfbb +--- /dev/null ++++ b/drivers/igloobase/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_IGLOO) += osi_notifier.o syscalls_info_report.o \ ++ igloobase.o igloo_weaksyms.o igloo_args.o +\ No newline at end of file +diff --git a/drivers/igloobase/igloo_args.c b/drivers/igloobase/igloo_args.c +new file mode 100644 +index 0000000000..bdb65d1fbc +--- /dev/null ++++ b/drivers/igloobase/igloo_args.c +@@ -0,0 +1,118 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "igloo_syscall_macros.h" ++#include "igloo.h" ++ ++ ++/** ++ * Early params originally from igloo_hc.c in the module ++ */ ++unsigned long igloo_task_size = 0; ++static int __init early_igloo_task_size(char *p) ++{ ++ unsigned long task_size; ++ if (kstrtoul(p, 0, &task_size) < 0 ) { ++ pr_warn("Could not parse igloo_task_size parameter %s\n", p); ++ return -1; ++ } ++ igloo_task_size = task_size; ++ pr_warn_once("Using igloo_task_size: 0x%lx\n", igloo_task_size); ++ return 0; ++} ++early_param("igloo_task_size", early_igloo_task_size); ++EXPORT_SYMBOL(igloo_task_size); ++ ++bool igloo_block_halt=false; ++ ++static int __init early_igloo_block_halt(char *p) ++{ ++ unsigned long block_halt; ++ if (kstrtoul(p, 0, &block_halt) < 0 ) { ++ pr_warn("Could not parse igloo_block_halt parameter %s. Set to 0 (default) or 1\n", p); ++ return -1; ++ } ++ igloo_block_halt = (block_halt > 0); ++ pr_warn_once("Using igloo_block_halt: %d\n", igloo_block_halt); ++ return 0; ++} ++ ++early_param("igloo_block_halt", early_igloo_block_halt); ++EXPORT_SYMBOL(igloo_block_halt); ++ ++// Debug logging configuration for each module ++struct igloo_debug_config { ++ bool portal; // Enable debug for portal module ++ bool uprobe; // Enable debug for uprobe module ++ bool vma; // Enable debug for VMA tracking ++ bool syscall; // Enable debug for syscall tracking ++ bool osi; // Enable debug for OSI features ++}; ++ ++// Global debug configuration ++struct igloo_debug_config igloo_debug = { ++ .portal = false, ++ .uprobe = false, ++ .vma = false, ++ .syscall = false, ++ .osi = false, ++}; ++ ++// Parse comma-separated list of modules to enable debug logging for ++static int __init early_igloo_debug_modules(char *p) ++{ ++ char *token; ++ ++ // By default, all modules have debug disabled ++ memset(&igloo_debug, 0, sizeof(igloo_debug)); ++ ++ // Special case: "all" enables all modules ++ if (!strcmp(p, "all")) { ++ memset(&igloo_debug, 1, sizeof(igloo_debug)); ++ pr_warn_once("IGLOO: Debug enabled for all modules\n"); ++ return 0; ++ } ++ ++ // Special case: "none" disables all modules (default) ++ if (!strcmp(p, "none")) { ++ memset(&igloo_debug, 0, sizeof(igloo_debug)); ++ pr_warn_once("IGLOO: Debug disabled for all modules\n"); ++ return 0; ++ } ++ ++ // Parse comma-separated module list ++ while ((token = strsep(&p, ",")) != NULL) { ++ if (!strcmp(token, "portal")) ++ igloo_debug.portal = true; ++ else if (!strcmp(token, "uprobe")) ++ igloo_debug.uprobe = true; ++ else if (!strcmp(token, "vma")) ++ igloo_debug.vma = true; ++ else if (!strcmp(token, "syscall")) ++ igloo_debug.syscall = true; ++ else if (!strcmp(token, "osi")) ++ igloo_debug.osi = true; ++ else if (!strcmp(token, "all")){ ++ memset(&igloo_debug, 1, sizeof(igloo_debug)); ++ pr_warn_once("IGLOO: Debug enabled for all modules\n"); ++ return 0; ++ } ++ else ++ pr_warn("IGLOO: Unknown debug module: %s\n", token); ++ } ++ ++ pr_warn_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d\n", ++ igloo_debug.portal, igloo_debug.uprobe, igloo_debug.vma, ++ igloo_debug.syscall, igloo_debug.osi); ++ ++ return 0; ++} ++ ++early_param("igloo_debug", early_igloo_debug_modules); ++EXPORT_SYMBOL(igloo_debug); +\ No newline at end of file +diff --git a/drivers/igloobase/igloo_weaksyms.c b/drivers/igloobase/igloo_weaksyms.c +new file mode 100644 +index 0000000000..8498d15500 +--- /dev/null ++++ b/drivers/igloobase/igloo_weaksyms.c +@@ -0,0 +1,112 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "igloo_syscall_macros.h" ++#include "igloo.h" ++ ++/* Syscall hooks */ ++igloo_syscall_enter_t igloo_syscall_enter_hook = NULL; ++igloo_syscall_return_t igloo_syscall_return_hook = NULL; ++EXPORT_SYMBOL(igloo_syscall_enter_hook); ++EXPORT_SYMBOL(igloo_syscall_return_hook); ++ ++// Function pointer for override ++bool (*igloo_should_block_mount_module)(struct path *path); ++bool igloo_should_block_mount(struct path *path); ++bool igloo_should_block_mount(struct path *path) ++{ ++ if (igloo_should_block_mount_module) { ++ return igloo_should_block_mount_module(path); ++ } else { ++ // printk(KERN_INFO "igloo_should_block_mount: default implementation called\n"); ++ return false; ++ } ++} ++EXPORT_SYMBOL(igloo_should_block_mount); ++ ++void (*igloo_sock_release_module)(struct socket *sock); ++void igloo_sock_release(struct socket *sock) ++{ ++ if (igloo_sock_release_module) { ++ igloo_sock_release_module(sock); ++ } else { ++ // printk(KERN_EMERG "igloo_sock_release: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_sock_release); ++ ++void (*igloo_sock_bind_module)(struct socket *sock, struct sockaddr_storage *address); ++void igloo_sock_bind(struct socket *sock, struct sockaddr_storage *address) ++{ ++ if (igloo_sock_bind_module) { ++ igloo_sock_bind_module(sock, address); ++ } else { ++ // printk(KERN_EMERG "igloo_sock_bind: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_sock_bind); ++ ++void (*igloo_hc_newuname_module)(struct new_utsname *name) = NULL; ++void igloo_hc_newuname(struct new_utsname *name) ++{ ++ if (igloo_hc_newuname_module) { ++ igloo_hc_newuname_module(name); ++ } else { ++ // printk(KERN_EMERG "igloo_hc_newuname: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_hc_newuname); ++ ++void (*igloo_hc_open_module)(int dfd, const char __user *filename, struct open_how *how); ++void igloo_hc_open(int dfd, const char __user *filename, struct open_how *how); ++void igloo_hc_open(int dfd, const char __user *filename, struct open_how *how) ++{ ++ if (igloo_hc_open_module) { ++ igloo_hc_open_module(dfd, filename, how); ++ } else { ++ // printk(KERN_EMERG "igloo_hc_open: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_hc_open); ++ ++void (*igloo_ioctl_module)(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp); ++void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp); ++void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) ++{ ++ if (igloo_ioctl_module) { ++ igloo_ioctl_module(error, inode, filp, cmd, argp); ++ } else { ++ // printk(KERN_EMERG "igloo_ioctl: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_ioctl); ++ ++/* Export internal symbols needed for introspection research */ ++ ++// Symbol lookup functions - now pulled in by trace/syscall.h ++EXPORT_SYMBOL(kallsyms_lookup); ++ ++extern unsigned long kallsyms_lookup_name(const char *name); ++EXPORT_SYMBOL(kallsyms_lookup_name); ++ ++// Architecture-specific functions ++extern const char *arch_vma_name(struct vm_area_struct *vma); ++EXPORT_SYMBOL(arch_vma_name); ++ ++// Process management ++extern pid_t kernel_clone(struct kernel_clone_args *args); ++EXPORT_SYMBOL(kernel_clone); ++ ++extern int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid); ++EXPORT_SYMBOL(kill_pid_info); ++ ++// Memory access ++extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, ++ void *buf, int len, unsigned int gup_flags); ++EXPORT_SYMBOL(access_remote_vm); +\ No newline at end of file +diff --git a/drivers/igloobase/igloobase.c b/drivers/igloobase/igloobase.c +new file mode 100644 +index 0000000000..005835633c +--- /dev/null ++++ b/drivers/igloobase/igloobase.c +@@ -0,0 +1,28 @@ ++#include ++#include ++#include ++#include "igloo.h" ++#include "igloobase.h" ++ ++ ++/* Register probes for mmap and munmap */ ++static int __init igloo_base_init(void) { ++ printk(KERN_EMERG "IGLOOBase: Initializing\n"); ++ int ret = 0; ++ if ((ret = osi_notifier_init()) != 0) { ++ printk(KERN_ERR "Failed to register osi_notifier_init\n"); ++ } ++ if ((ret = syscalls_info_report()) != 0) { ++ printk(KERN_ERR "Failed to register syscalls_hc returning %d\n", ret); ++ } ++ return 0; ++} ++ ++/* Unregister probes */ ++static void __exit igloo_base_exit(void) { ++ // Unreachable, module is built in ++ printk(KERN_ERR "TODO\n"); ++} ++ ++module_init(igloo_base_init); ++module_exit(igloo_base_exit); +\ No newline at end of file +diff --git a/drivers/igloobase/igloobase.h b/drivers/igloobase/igloobase.h +new file mode 100644 +index 0000000000..3fe72b89a0 +--- /dev/null ++++ b/drivers/igloobase/igloobase.h +@@ -0,0 +1,2 @@ ++int osi_notifier_init(void); ++int syscalls_info_report(void); +\ No newline at end of file +diff --git a/drivers/igloobase/igloobasehypercalls.h b/drivers/igloobase/igloobasehypercalls.h +new file mode 100644 +index 0000000000..f7fa8b985e +--- /dev/null ++++ b/drivers/igloobase/igloobasehypercalls.h +@@ -0,0 +1,6 @@ ++// This should be a relatively small file as most functionality should be ++// implemented in the core igloo driver ++ ++enum igloo_base_hypercalls { ++ IGLOO_HYP_SETUP_SYSCALL = 0x1337, ++}; +\ No newline at end of file +diff --git a/drivers/igloobase/osi_notifier.c b/drivers/igloobase/osi_notifier.c +new file mode 100644 +index 0000000000..b9ed55d799 +--- /dev/null ++++ b/drivers/igloobase/osi_notifier.c +@@ -0,0 +1,55 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hypercall.h" ++#include ++#include ++#include ++#include ++#include /* Needed by all modules */ ++#include /* Needed for KERN_INFO */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "igloo.h" ++#include "igloobase.h" ++ ++#define IGLOO_HYP_OSI_TASK_SWITCH 0x3337 ++ ++// Define a tracepoint probe function for sched_switch with the correct signature ++static void probe_sched_switch(void *data, bool preempt, struct task_struct *prev, ++ struct task_struct *next, unsigned int prev_state) ++{ ++ // Notify hypervisor about task switch using task pointers ++ igloo_hypercall2(IGLOO_HYP_OSI_TASK_SWITCH, (unsigned long)prev, (unsigned long)next); ++} ++ ++int osi_notifier_init(void) { ++ int ret = 0; ++ ++ // Register the sched_switch tracepoint ++ ret = register_trace_sched_switch(probe_sched_switch, NULL); ++ if (ret) { ++ printk(KERN_ERR "IGLOO: Failed to register sched_switch tracepoint, returned %d\n", ret); ++ } else { ++ printk(KERN_INFO "IGLOO: Successfully registered sched_switch tracepoint\n"); ++ } ++ return 0; ++} +\ No newline at end of file +diff --git a/drivers/igloobase/syscalls_info_report.c b/drivers/igloobase/syscalls_info_report.c +new file mode 100644 +index 0000000000..9927c02e3e +--- /dev/null ++++ b/drivers/igloobase/syscalls_info_report.c +@@ -0,0 +1,281 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hypercall.h" // Content is now included directly below ++#include "igloo.h" ++#include "igloobase.h" ++#include "igloobasehypercalls.h" ++ ++extern struct syscall_metadata *__start_syscalls_metadata[]; ++extern struct syscall_metadata *__stop_syscalls_metadata[]; ++ ++#ifndef ARCH_HAS_SYSCALL_MATCH_SYM_NAME ++static inline bool arch_syscall_match_sym_name(const char *sym, const char *name) ++{ ++ /* ++ * Only compare after the "sys" prefix. Archs that use ++ * syscall wrappers may have syscalls symbols aliases prefixed ++ * with ".SyS" or ".sys" instead of "sys", leading to an unwanted ++ * mismatch. ++ */ ++ return !strcmp(sym + 3, name + 3); ++} ++#endif ++ ++/* Normalize syscall names by removing common prefixes like 'sys_', '_sys_', 'compat_sys_' */ ++static inline const char *normalize_syscall_name(const char *name) ++{ ++ if (!name) ++ return NULL; ++ ++ /* Skip leading underscores (e.g. _sys_) */ ++ while (*name == '_') ++ name++; ++ ++ /* Check for 'sys_' prefix */ ++ if (strncmp(name, "sys_", 4) == 0) ++ return name + 4; ++ ++ /* Check for 'compat_sys_' prefix */ ++ if (strncmp(name, "compat_sys_", 11) == 0) ++ return name + 11; ++ ++ /* Check for other arch-specific prefixes */ ++ if (strncmp(name, "arm64_sys_", 10) == 0) ++ return name + 10; ++ ++ if (strncmp(name, "riscv_sys_", 10) == 0) ++ return name + 10; ++ ++ return name; ++} ++ ++// copied from trace_syscalls.c ++static struct syscall_metadata * ++find_syscall_meta_copy(unsigned long syscall); ++static struct syscall_metadata * ++find_syscall_meta_copy(unsigned long syscall) ++{ ++ struct syscall_metadata **start; ++ struct syscall_metadata **stop; ++ char str[KSYM_SYMBOL_LEN]; ++ ++ ++ start = __start_syscalls_metadata; ++ stop = __stop_syscalls_metadata; ++ kallsyms_lookup(syscall, NULL, NULL, NULL, str); ++ ++ if (arch_syscall_match_sym_name(str, "sys_ni_syscall")) ++ return NULL; ++ ++ for ( ; start < stop; start++) { ++ if ((*start)->name && arch_syscall_match_sym_name(str, (*start)->name)) ++ return *start; ++ } ++ return NULL; ++} ++ ++static void report_syscall(char * buffer, struct syscall_metadata *meta){ ++ if (!meta || !meta->name) { ++ return; // Skip invalid metadata ++ } ++ // Prepare JSON metadata for hypercall (ensure buffer is large enough) ++ int x = snprintf(buffer, PAGE_SIZE, ++ "{\"name\": \"%s\", \"args\":[", ++ normalize_syscall_name(meta->name)); ++ ++ for (int j = 0; j < meta->nb_args && x > 0 && x < PAGE_SIZE; j++) { ++ // Append args safely, checking remaining buffer space ++ x += snprintf((char*)buffer + x, PAGE_SIZE - x, "[\"%s\", \"%s\"]%s", ++ meta->types[j] ? meta->types[j] : "?", // Handle potential NULL type/arg names ++ meta->args[j] ? meta->args[j] : "?", ++ j + 1 < meta->nb_args ? ", " : ""); ++ } ++ ++ if (x > 0 && x < PAGE_SIZE) { ++ x += snprintf((char*)buffer + x, PAGE_SIZE - x, "]}"); ++ } ++ ++ if (x <= 0 || x >= PAGE_SIZE) { ++ // DBG_PRINTK( "IGLOO: Failed to format JSON for syscall %s (nr %d) - buffer overflow or snprintf error.\n", meta->name, meta->syscall_nr); ++ // Decide how to handle: skip this probe or abort? Skipping for now. ++ return; ++ } ++ // Send metadata via hypercall (call returns value, but it's ignored here) ++ igloo_hypercall(IGLOO_HYP_SETUP_SYSCALL, (unsigned long)buffer); ++} ++ ++// normalize_syscall_name is now defined in syscalls_hc.h ++ ++#ifdef CONFIG_COMPAT ++/* For ARM64 */ ++#if defined(CONFIG_ARM64) ++extern const syscall_fn_t compat_sys_call_table[]; ++/* Don't redeclare sys_call_table as it's already in syscall.h with correct type */ ++#define COMPAT_TABLE_SIZE __NR_compat32_syscalls ++ ++/* For x86_64 */ ++// #elif defined(CONFIG_X86_64) ++// /* Use void* instead of syscall_fn_t for broader compatibility */ ++// extern const void * const ia32_sys_call_table[]; ++// #define compat_sys_call_table ia32_sys_call_table ++// #define COMPAT_TABLE_SIZE IA32_NR_syscalls ++ ++/* For MIPS64 */ ++#elif defined(CONFIG_MIPS) && defined(CONFIG_64BIT) ++/* Use the correct declaration that matches what's in syscall.h */ ++#include /* Ensure we get the right declaration */ ++#define compat_sys_call_table sys32_call_table ++#define COMPAT_TABLE_SIZE NR_syscalls /* Use NR_syscalls instead of __NR_syscalls */ ++ ++/* For PPC64 */ ++// #elif defined(CONFIG_PPC64) ++// extern void *sys32_call_table[]; ++// #define compat_sys_call_table sys32_call_table ++// #define COMPAT_TABLE_SIZE __NR_syscalls ++ ++/* For RISC-V64 */ ++#elif defined(CONFIG_RISCV) && defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) ++/* Use the correct declaration for RISC-V - it's already properly declared in syscall.h */ ++#define COMPAT_TABLE_SIZE __NR_syscalls ++#endif ++#endif ++ ++/* Get syscall name from a function pointer */ ++#ifdef CONFIG_COMPAT ++static const char *get_syscall_name_from_func(void *func_ptr) { ++ char sym[KSYM_SYMBOL_LEN]; ++ ++ if (!func_ptr || IS_ERR(func_ptr)) ++ return NULL; ++ ++ kallsyms_lookup((unsigned long)func_ptr, NULL, NULL, NULL, sym); ++ ++ /* Skip if we couldn't identify the symbol */ ++ if (!sym[0]) ++ return NULL; ++ ++ /* Skip the "sys_" or similar prefix */ ++ if (strncmp(sym, "sys_", 4) == 0) ++ return kstrdup(sym, GFP_KERNEL); ++ else if (strncmp(sym, "compat_sys_", 11) == 0) ++ return kstrdup(sym + 7, GFP_KERNEL); /* Return without the "compat_" prefix */ ++ else if (strncmp(sym, "__arm64_", 8) == 0) ++ return kstrdup(sym + 8, GFP_KERNEL); /* Return without the "__arm64_" prefix */ ++ else if (strncmp(sym, "__loongarch_", 12) == 0) ++ return kstrdup(sym + 12, GFP_KERNEL); /* Return without the "__loongarch_" prefix */ ++ else if (strncmp(sym, "__riscv_", 8) == 0) ++ return kstrdup(sym + 8, GFP_KERNEL); /* Return without the "__riscv_" prefix */ ++ else if (strncmp(sym, "__se_", 5) == 0) ++ return kstrdup(sym + 5, GFP_KERNEL); /* Return without the "__se_" prefix */ ++ ++ return kstrdup(sym, GFP_KERNEL); ++} ++ ++static void report_syscall_from_func(char *buffer, void *func_ptr, int syscall_nr) { ++ const char *name; ++ int x; ++ ++ if (!func_ptr || IS_ERR(func_ptr)) ++ return; ++ ++ name = get_syscall_name_from_func(func_ptr); ++ if (!name) ++ return; ++ ++ /* Create a simplified metadata report for compat syscalls */ ++ x = snprintf(buffer, PAGE_SIZE, "{\"name\": \"%s\", \"compat\": true, \"args\":\"unknown\"}", ++ normalize_syscall_name(name)); ++ ++ if (x > 0 && x < PAGE_SIZE) { ++ /* Send this metadata via hypercall */ ++ igloo_hypercall(IGLOO_HYP_SETUP_SYSCALL, (unsigned long)buffer); ++ } ++ ++ kfree(name); ++} ++#endif ++ ++int syscalls_info_report(void) { ++ printk(KERN_EMERG "IGLOO: Initializing syscall hypercalls\n"); ++ struct syscall_metadata **p = __start_syscalls_metadata; ++ struct syscall_metadata **end = __stop_syscalls_metadata; ++ ++ void *buffer = kzalloc(PAGE_SIZE, GFP_KERNEL); ++ ++ if (!buffer) { ++ printk(KERN_ERR "IGLOO: Failed to allocate memory for syscall metadata buffer\n"); ++ return -ENOMEM; ++ } ++ ++ // Count the number of syscalls ++ int num_syscall_probes = end - p; ++ if (num_syscall_probes <= 0) { ++ printk(KERN_WARNING "IGLOO: No syscall metadata found.\n"); ++ return -EINVAL; ++ } ++ ++ // Process regular syscalls first ++ int i; ++ for (i = 0; i < NR_syscalls+1000; i++) { ++ struct syscall_metadata *meta; ++ unsigned long addr; ++ addr = arch_syscall_addr(i); ++ meta = find_syscall_meta_copy(addr); ++ if (!meta) ++ continue; ++ meta->syscall_nr = i; ++ report_syscall(buffer, meta); ++ } ++ ++ for (p = __start_syscalls_metadata; p < end; p++) { ++ struct syscall_metadata *meta = *p; ++ if (!meta) { ++ continue; // Skip invalid metadata ++ } ++ report_syscall(buffer, meta); ++ } ++ ++ // Process compat syscalls ++#ifdef CONFIG_COMPAT ++#ifdef COMPAT_TABLE_SIZE ++ printk(KERN_INFO "IGLOO: Processing compat syscall table with %d entries\n", COMPAT_TABLE_SIZE); ++ ++ for (i = 0; i < COMPAT_TABLE_SIZE; i++) { ++#if defined(CONFIG_RISCV) && defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) ++ /* For RISC-V, use the already declared variable without casting */ ++ void *func_ptr = compat_sys_call_table[i]; ++#elif defined(CONFIG_MIPS) && defined(CONFIG_64BIT) ++ /* For MIPS64, handle the unsigned long array correctly */ ++ void *func_ptr = (void *)(unsigned long)compat_sys_call_table[i]; ++#else ++ /* For other architectures, use proper casting based on architecture pointer size */ ++ void *func_ptr = (void *)(uintptr_t)compat_sys_call_table[i]; ++#endif ++ ++ /* Skip non-existent syscalls (usually NULL) */ ++ if (!func_ptr || IS_ERR(func_ptr)) { ++ continue; ++ } ++ ++ report_syscall_from_func(buffer, func_ptr, i); ++ } ++#else ++ printk(KERN_INFO "IGLOO: No compat syscall table found for this architecture\n"); ++#endif ++#endif ++ ++ kfree(buffer); ++ return 0; ++} +\ No newline at end of file diff --git a/patches/4.10/0011-exec.c-add-igloo_task_size.patch b/patches/4.10/0011-exec.c-add-igloo_task_size.patch new file mode 100644 index 0000000..c9ddb71 --- /dev/null +++ b/patches/4.10/0011-exec.c-add-igloo_task_size.patch @@ -0,0 +1,32 @@ +From 0a80e99b2d992a8a46df90217374f4de03a7f529 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:15:02 -0400 +Subject: [PATCH 11/38] exec.c: add igloo_task_size + +--- + fs/exec.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/exec.c b/fs/exec.c +index e579466107..ab8a94d669 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -61,6 +61,7 @@ + #include + #include + #include ++#include + + #include + #include "internal.h" +@@ -1323,6 +1324,10 @@ void setup_new_exec(struct linux_binprm * bprm) + * some architectures like powerpc + */ + current->mm->task_size = TASK_SIZE; ++ #ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ current->mm->task_size = igloo_task_size; ++ #endif + + /* install the new credentials */ + if (!uid_eq(bprm->cred->uid, current_euid()) || diff --git a/patches/4.10/0012-mmap.c-add-igloo_task_size.patch b/patches/4.10/0012-mmap.c-add-igloo_task_size.patch new file mode 100644 index 0000000..64cfaa2 --- /dev/null +++ b/patches/4.10/0012-mmap.c-add-igloo_task_size.patch @@ -0,0 +1,36 @@ +From e1c3ea60d03bf7551aa37c08cbea9f52f79c0337 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:16:06 -0400 +Subject: [PATCH 12/38] mmap.c: add igloo_task_size + +--- + arch/x86/mm/mmap.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index d2dc0438d6..9ed4b0b5f1 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + struct va_alignment __read_mostly va_align = { + .flags = -1, +@@ -89,6 +90,14 @@ static unsigned long mmap_base(unsigned long rnd) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; ++ ++ #ifdef CONFIG_IGLOO ++ if(igloo_task_size) { ++ return PAGE_ALIGN(igloo_task_size - gap - rnd); ++ } else { ++ return PAGE_ALIGN(TASK_SIZE - gap - rnd); ++ } ++ #endif + + return PAGE_ALIGN(TASK_SIZE - gap - rnd); + } diff --git a/patches/4.10/0014-add-syscalls.h.patch b/patches/4.10/0014-add-syscalls.h.patch new file mode 100644 index 0000000..eeeec4d --- /dev/null +++ b/patches/4.10/0014-add-syscalls.h.patch @@ -0,0 +1,141 @@ +From 0dfb25514522421228bc6a27f4c02a72b955317c Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:22:08 -0400 +Subject: [PATCH 14/38] add syscalls.h + +--- + include/linux/syscalls.h | 111 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 100 insertions(+), 11 deletions(-) + +diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h +index 91a740f6b8..1a7f4688f3 100644 +--- a/include/linux/syscalls.h ++++ b/include/linux/syscalls.h +@@ -175,9 +175,58 @@ extern struct trace_event_functions exit_syscall_print_funcs; + #define SYSCALL_METADATA(sname, nb, ...) + #endif + +-#define SYSCALL_DEFINE0(sname) \ +- SYSCALL_METADATA(_##sname, 0); \ +- asmlinkage long sys_##sname(void) ++#ifdef CONFIG_IGLOO ++#include ++/* === Igloo Interception Hooks and Helpers === */ ++ ++/* Pointers to the actual hook functions */ ++extern igloo_syscall_enter_t igloo_syscall_enter_hook; ++extern igloo_syscall_return_t igloo_syscall_return_hook; ++#else /* CONFIG_IGLOO not defined */ ++ ++/* Define stubs or original macros if Igloo is disabled */ ++#define igloo_syscall_enter_hook NULL ++#define igloo_syscall_return_hook NULL ++#endif /* CONFIG_IGLOO */ ++ ++#define SYSCALL_DEFINE0(sname) \ ++ SYSCALL_METADATA(_##sname, 0); \ ++ asmlinkage long sys_##sname(void) \ ++ { \ ++ const char *syscall_basename = __stringify(name); /* Base name */ \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ /* Array for arguments (empty for 0 args) */ \ ++ unsigned long args_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ \ ++ /* === Igloo Enter Hook === */ \ ++ if (igloo_syscall_enter_hook) \ ++ { \ ++ /* Pass NULL for setter func for 0-arg syscalls */ \ ++ skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, 0, args_array, NULL); \ ++ } \ ++ \ ++ if (skip) \ ++ { \ ++ ret = skip_ret; \ ++ } \ ++ else \ ++ { \ ++ ret = __do_sys_##sname(); \ ++ } \ ++ \ ++ /* === Igloo Return Hook === */ \ ++ if (igloo_syscall_return_hook) \ ++ { \ ++ ret = igloo_syscall_return_hook(syscall_basename, ret, 0, args_array); \ ++ } \ ++ \ ++ /* Argument protection and final return */ \ ++ __PROTECT(0, ret); /* Protect for 0 args */ \ ++ return ret ; \ ++ } \ ++ static inline long __do_sys_##sname(void) + + #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) + #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) +@@ -191,17 +240,57 @@ extern struct trace_event_functions exit_syscall_print_funcs; + __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) + + #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) +-#define __SYSCALL_DEFINEx(x, name, ...) \ ++#define __SYSCALL_DEFINEx(x, name, ...) \ + asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ + __attribute__((alias(__stringify(SyS##name)))); \ +- static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ +- asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ +- asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { \ ++ __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); \ ++ } \ ++ static inline long SYSC##name(__MAP(x, __SC_DECL, __VA_ARGS__)); \ ++ asmlinkage long SyS##name(__MAP(x, __SC_LONG, __VA_ARGS__)); \ ++ asmlinkage long SyS##name(__MAP(x, __SC_LONG, __VA_ARGS__)) \ + { \ +- long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ +- __MAP(x,__SC_TEST,__VA_ARGS__); \ +- __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ +- return ret; \ ++ const char *syscall_basename = __stringify(name); \ ++ long ret = 0; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ \ ++ /* Populate args_ptr_array with ADDRESSES for the enter hook */ \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_array, __VA_ARGS__); \ ++ \ ++ /* === Igloo Enter Hook === */ \ ++ if (igloo_syscall_enter_hook) { \ ++ /* Pass setter function pointer unconditionally (except for 0 args) */ \ ++ /* The hook is responsible for handling const args correctly. */ \ ++ skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, x, \ ++ args_ptr_array, __igloo_set_args##name); \ ++ } \ ++ \ ++ if (skip) { \ ++ /* Syscall skipped by hook */ \ ++ ret = skip_ret; \ ++ } else { \ ++ /* Execute actual syscall implementation */ \ ++ /* Arguments used here are potentially modified */ \ ++ /* by the enter hook via the setter function */ \ ++ ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ ++ } \ ++ \ ++ /* Original type tests */ \ ++ __MAP(x,__SC_TEST,__VA_ARGS__); \ ++ \ ++ /* === Igloo Return Hook === */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(syscall_basename, ret, x, \ ++ args_ptr_array); \ ++ } \ ++ \ ++ /* Argument protection and final return */ \ ++ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ ++ return ret; \ + } \ + static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + diff --git a/patches/4.10/0015-syscalls.h-fixes.patch b/patches/4.10/0015-syscalls.h-fixes.patch new file mode 100644 index 0000000..8525a31 --- /dev/null +++ b/patches/4.10/0015-syscalls.h-fixes.patch @@ -0,0 +1,67 @@ +From 450f40b0d9bcfbbab7a033395835ed9ab7a1e2c2 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 20 Sep 2025 18:09:59 -0400 +Subject: [PATCH 15/38] syscalls.h: fixes + +--- + include/linux/syscalls.h | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h +index 1a7f4688f3..f7d0ac1d9a 100644 +--- a/include/linux/syscalls.h ++++ b/include/linux/syscalls.h +@@ -191,6 +191,7 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + + #define SYSCALL_DEFINE0(sname) \ + SYSCALL_METADATA(_##sname, 0); \ ++ static inline long __do_sys_##sname(void); \ + asmlinkage long sys_##sname(void) \ + { \ + const char *syscall_basename = __stringify(name); /* Base name */ \ +@@ -198,15 +199,14 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + bool skip = false; \ + long skip_ret = 0; \ + /* Array for arguments (empty for 0 args) */ \ +- unsigned long args_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ + \ + /* === Igloo Enter Hook === */ \ + if (igloo_syscall_enter_hook) \ + { \ + /* Pass NULL for setter func for 0-arg syscalls */ \ +- skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, 0, args_array, NULL); \ ++ skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, 0, args_ptr_array, NULL); \ + } \ +- \ + if (skip) \ + { \ + ret = skip_ret; \ +@@ -219,12 +219,12 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + /* === Igloo Return Hook === */ \ + if (igloo_syscall_return_hook) \ + { \ +- ret = igloo_syscall_return_hook(syscall_basename, ret, 0, args_array); \ ++ ret = igloo_syscall_return_hook(syscall_basename, ret, 0, args_ptr_array); \ + } \ + \ + /* Argument protection and final return */ \ + __PROTECT(0, ret); /* Protect for 0 args */ \ +- return ret ; \ ++ return ret; \ + } \ + static inline long __do_sys_##sname(void) + +@@ -256,10 +256,10 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + long ret = 0; \ + bool skip = false; \ + long skip_ret = 0; \ +- unsigned long args_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ + \ + /* Populate args_ptr_array with ADDRESSES for the enter hook */ \ +- __SC_ASSIGN_ADDR_WRAPPER(x, args_array, __VA_ARGS__); \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ + \ + /* === Igloo Enter Hook === */ \ + if (igloo_syscall_enter_hook) { \ diff --git a/patches/4.10/0016-syscals.h-fix-sname-in-define0.patch b/patches/4.10/0016-syscals.h-fix-sname-in-define0.patch new file mode 100644 index 0000000..81f97e7 --- /dev/null +++ b/patches/4.10/0016-syscals.h-fix-sname-in-define0.patch @@ -0,0 +1,22 @@ +From fb76ed1995743218dc4a0d8ac2e343ffd666b2e3 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 22 Sep 2025 09:04:08 -0400 +Subject: [PATCH 16/38] syscals.h: fix sname in define0 + +--- + include/linux/syscalls.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h +index f7d0ac1d9a..f916d83569 100644 +--- a/include/linux/syscalls.h ++++ b/include/linux/syscalls.h +@@ -194,7 +194,7 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + static inline long __do_sys_##sname(void); \ + asmlinkage long sys_##sname(void) \ + { \ +- const char *syscall_basename = __stringify(name); /* Base name */ \ ++ const char *syscall_basename = __stringify(sname); /* Base name */ \ + long ret; \ + bool skip = false; \ + long skip_ret = 0; \ diff --git a/patches/4.10/0017-binfmt_elf.c-add-igloo_task_size-support.patch b/patches/4.10/0017-binfmt_elf.c-add-igloo_task_size-support.patch new file mode 100644 index 0000000..4d25688 --- /dev/null +++ b/patches/4.10/0017-binfmt_elf.c-add-igloo_task_size-support.patch @@ -0,0 +1,42 @@ +From b404b7c4531145e2f99c36c993c955384b8f8dfc Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:29:33 -0400 +Subject: [PATCH 17/38] binfmt_elf.c: add igloo_task_size support + +--- + fs/binfmt_elf.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 422370293c..af32087f08 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #ifndef user_long_t + #define user_long_t long +@@ -857,8 +858,19 @@ static int load_elf_binary(struct linux_binprm *bprm) + + /* Do this so that we can load the interpreter, if need be. We will + change some of these later */ ++ #ifdef CONFIG_IGLOO ++ //Begin for igloo: if we moved the stack, we have to move mmap ++ if(igloo_task_size) { ++ retval = setup_arg_pages(bprm, randomize_stack_top(igloo_task_size), ++ executable_stack); ++ } else { ++ retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), ++ executable_stack); ++ } ++ #else + retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), +- executable_stack); ++ executable_stack); ++ #endif + if (retval < 0) + goto out_free_dentry; + diff --git a/patches/4.10/0018-compat.h-syscalls-support.patch b/patches/4.10/0018-compat.h-syscalls-support.patch new file mode 100644 index 0000000..3e85330 --- /dev/null +++ b/patches/4.10/0018-compat.h-syscalls-support.patch @@ -0,0 +1,110 @@ +From 1b1fd64f0454df20e119055e9ec0d9a3e19ae682 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:31:18 -0400 +Subject: [PATCH 18/38] compat.h: syscalls support + +--- + include/linux/compat.h | 79 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 77 insertions(+), 2 deletions(-) + +diff --git a/include/linux/compat.h b/include/linux/compat.h +index 63609398ef..8c02fb57e2 100644 +--- a/include/linux/compat.h ++++ b/include/linux/compat.h +@@ -30,8 +30,45 @@ + #define __SC_DELOUSE(t,v) ((t)(unsigned long)(v)) + #endif + ++// === Igloo Interception Support === ++#include ++ ++#ifdef CONFIG_IGLOO ++extern igloo_syscall_enter_t igloo_syscall_enter_hook; ++extern igloo_syscall_return_t igloo_syscall_return_hook; ++#endif ++ + #define COMPAT_SYSCALL_DEFINE0(name) \ +- asmlinkage long compat_sys_##name(void) ++ asmlinkage long compat_sys_##name(void) \ ++ { \ ++ const char *syscall_basename = __stringify(name); /* Base name */ \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ /* Array for arguments (empty for 0 args) */ \ ++ unsigned long args_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ ++ /* === Igloo Enter Hook === */ \ ++ if (igloo_syscall_enter_hook) { \ ++ /* Pass NULL for setter func for 0-arg syscalls */ \ ++ skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, 0, args_array, NULL); \ ++ } \ ++ \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_compat_sys_##name(); \ ++ } \ ++ \ ++ /* === Igloo Return Hook === */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(syscall_basename, ret, 0, args_array); \ ++ } \ ++ \ ++ return ret ; \ ++ } ++ static inline long __do_compat_sys_##name(void) ++ + + #define COMPAT_SYSCALL_DEFINE1(name, ...) \ + COMPAT_SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) +@@ -50,10 +87,48 @@ + asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))\ + __attribute__((alias(__stringify(compat_SyS##name)))); \ + static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ ++ /* Setter function definition: Body generated using __SC_GEN_SETTER_BODY_WRAPPER */ \ ++ void __compat_igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __compat_igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { \ ++ __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); \ ++ } + asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));\ + asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\ + { \ +- return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ ++ const char *syscall_basename = __stringify(name); /* Base name */ \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ /* Declare ONE array for argument pointers */ \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ \ ++ /* Populate args_ptr_array with ADDRESSES for the enter hook */ \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ \ ++ /* === Igloo Enter Hook === */ \ ++ if (igloo_syscall_enter_hook) { \ ++ /* Pass setter function pointer unconditionally (except for 0 args) */ \ ++ /* The hook is responsible for handling const args correctly. */ \ ++ skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, x, \ ++ args_ptr_array, __compat_igloo_set_args##name); \ ++ } \ ++ if (skip) { \ ++ /* Syscall skipped by hook */ \ ++ ret = skip_ret; \ ++ } else { \ ++ /* Execute actual syscall implementation */ \ ++ /* Arguments used here are potentially modified */ \ ++ /* by the enter hook via the setter function */ \ ++ ret = C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ ++ } \ ++ \ ++ /* === Igloo Return Hook === */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(syscall_basename, ret, x, \ ++ args_ptr_array); \ ++ } \ ++ return ret; \ + } \ + static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + diff --git a/patches/4.10/0019-give-up-on-gcc-ilog2-constant-optimizations.patch b/patches/4.10/0019-give-up-on-gcc-ilog2-constant-optimizations.patch new file mode 100644 index 0000000..ce48318 --- /dev/null +++ b/patches/4.10/0019-give-up-on-gcc-ilog2-constant-optimizations.patch @@ -0,0 +1,124 @@ +From c88c463900ffefdd82a0d149e3c05626f2841101 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Thu, 2 Mar 2017 12:17:22 -0800 +Subject: [PATCH 19/38] give up on gcc ilog2() constant optimizations + +gcc-7 has an "optimization" pass that completely screws up, and +generates the code expansion for the (impossible) case of calling +ilog2() with a zero constant, even when the code gcc compiles does not +actually have a zero constant. + +And we try to generate a compile-time error for anybody doing ilog2() on +a constant where that doesn't make sense (be it zero or negative). So +now gcc7 will fail the build due to our sanity checking, because it +created that constant-zero case that didn't actually exist in the source +code. + +There's a whole long discussion on the kernel mailing about how to work +around this gcc bug. The gcc people themselevs have discussed their +"feature" in + + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72785 + +but it's all water under the bridge, because while it looked at one +point like it would be solved by the time gcc7 was released, that was +not to be. + +So now we have to deal with this compiler braindamage. + +And the only simple approach seems to be to just delete the code that +tries to warn about bad uses of ilog2(). + +So now "ilog2()" will just return 0 not just for the value 1, but for +any non-positive value too. + +It's not like I can recall anybody having ever actually tried to use +this function on any invalid value, but maybe the sanity check just +meant that such code never made it out in public. + +Reported-by: Laura Abbott +Cc: John Stultz , +Cc: Thomas Gleixner +Cc: Ard Biesheuvel +Signed-off-by: Linus Torvalds +--- + include/linux/log2.h | 13 ++----------- + tools/include/linux/log2.h | 13 ++----------- + 2 files changed, 4 insertions(+), 22 deletions(-) + +diff --git a/include/linux/log2.h b/include/linux/log2.h +index ef3d4f6711..c373295f35 100644 +--- a/include/linux/log2.h ++++ b/include/linux/log2.h +@@ -15,12 +15,6 @@ + #include + #include + +-/* +- * deal with unrepresentable constant logarithms +- */ +-extern __attribute__((const, noreturn)) +-int ____ilog2_NaN(void); +- + /* + * non-constant log of base 2 calculators + * - the arch may override these in asm/bitops.h if they can be implemented +@@ -85,7 +79,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n) + #define ilog2(n) \ + ( \ + __builtin_constant_p(n) ? ( \ +- (n) < 1 ? ____ilog2_NaN() : \ ++ (n) < 2 ? 0 : \ + (n) & (1ULL << 63) ? 63 : \ + (n) & (1ULL << 62) ? 62 : \ + (n) & (1ULL << 61) ? 61 : \ +@@ -148,10 +142,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n) + (n) & (1ULL << 4) ? 4 : \ + (n) & (1ULL << 3) ? 3 : \ + (n) & (1ULL << 2) ? 2 : \ +- (n) & (1ULL << 1) ? 1 : \ +- (n) & (1ULL << 0) ? 0 : \ +- ____ilog2_NaN() \ +- ) : \ ++ 1 ) : \ + (sizeof(n) <= 4) ? \ + __ilog2_u32(n) : \ + __ilog2_u64(n) \ +diff --git a/tools/include/linux/log2.h b/tools/include/linux/log2.h +index 41446668cc..d5677d39c1 100644 +--- a/tools/include/linux/log2.h ++++ b/tools/include/linux/log2.h +@@ -12,12 +12,6 @@ + #ifndef _TOOLS_LINUX_LOG2_H + #define _TOOLS_LINUX_LOG2_H + +-/* +- * deal with unrepresentable constant logarithms +- */ +-extern __attribute__((const, noreturn)) +-int ____ilog2_NaN(void); +- + /* + * non-constant log of base 2 calculators + * - the arch may override these in asm/bitops.h if they can be implemented +@@ -78,7 +72,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n) + #define ilog2(n) \ + ( \ + __builtin_constant_p(n) ? ( \ +- (n) < 1 ? ____ilog2_NaN() : \ ++ (n) < 2 ? 0 : \ + (n) & (1ULL << 63) ? 63 : \ + (n) & (1ULL << 62) ? 62 : \ + (n) & (1ULL << 61) ? 61 : \ +@@ -141,10 +135,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n) + (n) & (1ULL << 4) ? 4 : \ + (n) & (1ULL << 3) ? 3 : \ + (n) & (1ULL << 2) ? 2 : \ +- (n) & (1ULL << 1) ? 1 : \ +- (n) & (1ULL << 0) ? 0 : \ +- ____ilog2_NaN() \ +- ) : \ ++ 1 ) : \ + (sizeof(n) <= 4) ? \ + __ilog2_u32(n) : \ + __ilog2_u64(n) \ diff --git a/patches/4.10/0020-extern-yylloc-so-gcc-is-happy.patch b/patches/4.10/0020-extern-yylloc-so-gcc-is-happy.patch new file mode 100644 index 0000000..b32ab7d --- /dev/null +++ b/patches/4.10/0020-extern-yylloc-so-gcc-is-happy.patch @@ -0,0 +1,36 @@ +From c3d9eca87969dc8e071252ce410ef15e3679d5ae Mon Sep 17 00:00:00 2001 +From: Andrew Fasano +Date: Fri, 21 Oct 2022 10:29:23 -0400 +Subject: [PATCH 20/38] extern yylloc so gcc is happy + +--- + scripts/dtc/dtc-lexer.l | 2 +- + scripts/dtc/dtc-lexer.lex.c_shipped | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l +index 790fbf6cf2..e7eab4d7c5 100644 +--- a/scripts/dtc/dtc-lexer.l ++++ b/scripts/dtc/dtc-lexer.l +@@ -38,7 +38,7 @@ LINECOMMENT "//".*\n + #include "srcpos.h" + #include "dtc-parser.tab.h" + +-YYLTYPE yylloc; ++extern YYLTYPE yylloc; + extern bool treesource_error; + + /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ +diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped +index ba525c2f9f..a2fe8dbc0f 100644 +--- a/scripts/dtc/dtc-lexer.lex.c_shipped ++++ b/scripts/dtc/dtc-lexer.lex.c_shipped +@@ -637,7 +637,7 @@ char *yytext; + #include "srcpos.h" + #include "dtc-parser.tab.h" + +-YYLTYPE yylloc; ++extern YYLTYPE yylloc; + extern bool treesource_error; + + /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ diff --git a/patches/4.10/0021-Fix-build-with-GCC-versions-8-for-some-targets.patch b/patches/4.10/0021-Fix-build-with-GCC-versions-8-for-some-targets.patch new file mode 100644 index 0000000..4a83512 --- /dev/null +++ b/patches/4.10/0021-Fix-build-with-GCC-versions-8-for-some-targets.patch @@ -0,0 +1,24 @@ +From 0978e0e13bc13561ff026dd7989aecf948469d7b Mon Sep 17 00:00:00 2001 +From: Benjamin Levy +Date: Wed, 17 Jan 2024 15:53:36 -0500 +Subject: [PATCH 21/38] Fix build with GCC versions >=8 for some targets + +--- + Makefile | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/Makefile b/Makefile +index f1e6a02a0c..160e3393ac 100644 +--- a/Makefile ++++ b/Makefile +@@ -401,6 +401,10 @@ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ + -Wno-format-security \ + -std=gnu89 $(call cc-option,-fno-PIE) + ++# IGLOO ++# Fix build with GCC versions >=8 for some targets ++# https://github.com/torvalds/linux/commit/bee2003 ++KBUILD_CFLAGS += -Wno-attribute-alias + + KBUILD_AFLAGS_KERNEL := + KBUILD_CFLAGS_KERNEL := diff --git a/patches/4.10/0022-igloo_weaksyms-fix-igloo_hc_open-type.patch b/patches/4.10/0022-igloo_weaksyms-fix-igloo_hc_open-type.patch new file mode 100644 index 0000000..8cec627 --- /dev/null +++ b/patches/4.10/0022-igloo_weaksyms-fix-igloo_hc_open-type.patch @@ -0,0 +1,29 @@ +From 9e0524b6f487ec769fee9532685d9d62af677248 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 20 Sep 2025 18:08:14 -0400 +Subject: [PATCH 22/38] igloo_weaksyms: fix igloo_hc_open type + +--- + drivers/igloobase/igloo_weaksyms.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/igloobase/igloo_weaksyms.c b/drivers/igloobase/igloo_weaksyms.c +index 8498d15500..9e7e5c6639 100644 +--- a/drivers/igloobase/igloo_weaksyms.c ++++ b/drivers/igloobase/igloo_weaksyms.c +@@ -63,12 +63,11 @@ void igloo_hc_newuname(struct new_utsname *name) + } + EXPORT_SYMBOL(igloo_hc_newuname); + +-void (*igloo_hc_open_module)(int dfd, const char __user *filename, struct open_how *how); +-void igloo_hc_open(int dfd, const char __user *filename, struct open_how *how); +-void igloo_hc_open(int dfd, const char __user *filename, struct open_how *how) ++void (*igloo_hc_open_module)(int dfd, struct filename *tmp, int fd); ++void igloo_hc_open(int dfd, struct filename *tmp, int fd) + { + if (igloo_hc_open_module) { +- igloo_hc_open_module(dfd, filename, how); ++ igloo_hc_open_module(dfd, tmp, fd); + } else { + // printk(KERN_EMERG "igloo_hc_open: unimplemented\n"); + } diff --git a/patches/4.10/0023-igloo_weaksyms-forward-proper-types-for-4.10.patch b/patches/4.10/0023-igloo_weaksyms-forward-proper-types-for-4.10.patch new file mode 100644 index 0000000..9d15551 --- /dev/null +++ b/patches/4.10/0023-igloo_weaksyms-forward-proper-types-for-4.10.patch @@ -0,0 +1,53 @@ +From c115ca46444956b69960b85abeed3a112d6e17a8 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 20 Sep 2025 18:08:32 -0400 +Subject: [PATCH 23/38] igloo_weaksyms: forward proper types for 4.10 + +--- + drivers/igloobase/igloo_weaksyms.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/igloobase/igloo_weaksyms.c b/drivers/igloobase/igloo_weaksyms.c +index 9e7e5c6639..3057659f1a 100644 +--- a/drivers/igloobase/igloo_weaksyms.c ++++ b/drivers/igloobase/igloo_weaksyms.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include "igloo_syscall_macros.h" +@@ -91,18 +92,31 @@ EXPORT_SYMBOL(igloo_ioctl); + // Symbol lookup functions - now pulled in by trace/syscall.h + EXPORT_SYMBOL(kallsyms_lookup); + ++ ++// version not confirmed ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) + extern unsigned long kallsyms_lookup_name(const char *name); + EXPORT_SYMBOL(kallsyms_lookup_name); ++#endif + + // Architecture-specific functions + extern const char *arch_vma_name(struct vm_area_struct *vma); + EXPORT_SYMBOL(arch_vma_name); + ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) + // Process management + extern pid_t kernel_clone(struct kernel_clone_args *args); + EXPORT_SYMBOL(kernel_clone); ++#else ++// we will need another version here ++#endif + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,20,0) + extern int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid); ++#else ++extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid); ++#endif + EXPORT_SYMBOL(kill_pid_info); + + // Memory access diff --git a/patches/4.10/0024-igloobase.c-4.10-compliance.patch b/patches/4.10/0024-igloobase.c-4.10-compliance.patch new file mode 100644 index 0000000..f1ef823 --- /dev/null +++ b/patches/4.10/0024-igloobase.c-4.10-compliance.patch @@ -0,0 +1,23 @@ +From a824f3d1d264a2cccaa724a01f20eaec42174835 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 20 Sep 2025 18:08:44 -0400 +Subject: [PATCH 24/38] igloobase.c: 4.10 compliance + +--- + drivers/igloobase/igloobase.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/igloobase/igloobase.c b/drivers/igloobase/igloobase.c +index 005835633c..7462e9ee4c 100644 +--- a/drivers/igloobase/igloobase.c ++++ b/drivers/igloobase/igloobase.c +@@ -7,8 +7,8 @@ + + /* Register probes for mmap and munmap */ + static int __init igloo_base_init(void) { ++ int ret; + printk(KERN_EMERG "IGLOOBase: Initializing\n"); +- int ret = 0; + if ((ret = osi_notifier_init()) != 0) { + printk(KERN_ERR "Failed to register osi_notifier_init\n"); + } diff --git a/patches/4.10/0025-osi_notifier-4.10-compliance.patch b/patches/4.10/0025-osi_notifier-4.10-compliance.patch new file mode 100644 index 0000000..f7c72bf --- /dev/null +++ b/patches/4.10/0025-osi_notifier-4.10-compliance.patch @@ -0,0 +1,27 @@ +From ececf18586bf592e75f5a044e65fce1eebc672a4 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 20 Sep 2025 18:08:55 -0400 +Subject: [PATCH 25/38] osi_notifier: 4.10 compliance + +--- + drivers/igloobase/osi_notifier.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/igloobase/osi_notifier.c b/drivers/igloobase/osi_notifier.c +index b9ed55d799..9d02d2f8ae 100644 +--- a/drivers/igloobase/osi_notifier.c ++++ b/drivers/igloobase/osi_notifier.c +@@ -34,8 +34,13 @@ + #define IGLOO_HYP_OSI_TASK_SWITCH 0x3337 + + // Define a tracepoint probe function for sched_switch with the correct signature ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,18,0) + static void probe_sched_switch(void *data, bool preempt, struct task_struct *prev, + struct task_struct *next, unsigned int prev_state) ++#else ++static void probe_sched_switch(void *data, bool preempt, struct task_struct *prev, ++ struct task_struct *next) ++#endif + { + // Notify hypervisor about task switch using task pointers + igloo_hypercall2(IGLOO_HYP_OSI_TASK_SWITCH, (unsigned long)prev, (unsigned long)next); diff --git a/patches/4.10/0026-syscalls_info_report-4.10-compliance.patch b/patches/4.10/0026-syscalls_info_report-4.10-compliance.patch new file mode 100644 index 0000000..47dc82f --- /dev/null +++ b/patches/4.10/0026-syscalls_info_report-4.10-compliance.patch @@ -0,0 +1,70 @@ +From 9d99675cfd40640912a06efe548526e0059f8cd6 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 20 Sep 2025 18:09:34 -0400 +Subject: [PATCH 26/38] syscalls_info_report: 4.10 compliance + +--- + drivers/igloobase/syscalls_info_report.c | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +diff --git a/drivers/igloobase/syscalls_info_report.c b/drivers/igloobase/syscalls_info_report.c +index 9927c02e3e..1f447bcc95 100644 +--- a/drivers/igloobase/syscalls_info_report.c ++++ b/drivers/igloobase/syscalls_info_report.c +@@ -87,15 +87,15 @@ find_syscall_meta_copy(unsigned long syscall) + } + + static void report_syscall(char * buffer, struct syscall_metadata *meta){ ++ int x, j; + if (!meta || !meta->name) { + return; // Skip invalid metadata + } + // Prepare JSON metadata for hypercall (ensure buffer is large enough) +- int x = snprintf(buffer, PAGE_SIZE, ++ x = snprintf(buffer, PAGE_SIZE, + "{\"name\": \"%s\", \"args\":[", + normalize_syscall_name(meta->name)); +- +- for (int j = 0; j < meta->nb_args && x > 0 && x < PAGE_SIZE; j++) { ++ for (j = 0; j < meta->nb_args && x > 0 && x < PAGE_SIZE; j++) { + // Append args safely, checking remaining buffer space + x += snprintf((char*)buffer + x, PAGE_SIZE - x, "[\"%s\", \"%s\"]%s", + meta->types[j] ? meta->types[j] : "?", // Handle potential NULL type/arg names +@@ -207,27 +207,29 @@ static void report_syscall_from_func(char *buffer, void *func_ptr, int syscall_n + } + #endif + +-int syscalls_info_report(void) { +- printk(KERN_EMERG "IGLOO: Initializing syscall hypercalls\n"); +- struct syscall_metadata **p = __start_syscalls_metadata; +- struct syscall_metadata **end = __stop_syscalls_metadata; +- +- void *buffer = kzalloc(PAGE_SIZE, GFP_KERNEL); ++int __init syscalls_info_report(void) { ++ struct syscall_metadata **p, **end; // Fix declaration ++ int num_syscall_probes, i; // Move declarations to top ++ void *buffer; + ++ p = __start_syscalls_metadata; ++ end = __stop_syscalls_metadata; ++ ++ buffer = kzalloc(PAGE_SIZE, GFP_KERNEL); ++ + if (!buffer) { + printk(KERN_ERR "IGLOO: Failed to allocate memory for syscall metadata buffer\n"); + return -ENOMEM; + } + + // Count the number of syscalls +- int num_syscall_probes = end - p; ++ num_syscall_probes = end - p; + if (num_syscall_probes <= 0) { + printk(KERN_WARNING "IGLOO: No syscall metadata found.\n"); + return -EINVAL; + } + + // Process regular syscalls first +- int i; + for (i = 0; i < NR_syscalls+1000; i++) { + struct syscall_metadata *meta; + unsigned long addr; diff --git a/patches/4.10/0027-socket.c-add-config_igloo.patch b/patches/4.10/0027-socket.c-add-config_igloo.patch new file mode 100644 index 0000000..6f7cb24 --- /dev/null +++ b/patches/4.10/0027-socket.c-add-config_igloo.patch @@ -0,0 +1,35 @@ +From 757a088b0305f5aa512b02150ed01a60206ccf89 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 20 Sep 2025 18:09:48 -0400 +Subject: [PATCH 27/38] socket.c: add config_igloo + +--- + net/socket.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/socket.c b/net/socket.c +index 75aa88e267..47ffdfc03a 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -1392,8 +1392,10 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, + return err; + } + ++#ifdef CONFIG_IGLOO + // forward declare igloo_sock_bind + void igloo_sock_bind(struct socket *sock, struct sockaddr_storage *address); ++#endif + + /* + * Bind a name to a socket. Nothing much to do here since it's +@@ -1420,7 +1422,9 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) + err = sock->ops->bind(sock, + (struct sockaddr *) + &address, addrlen); +- igloo_sock_bind(sock, address); ++ #ifdef CONFIG_IGLOO ++ igloo_sock_bind(sock, &address); ++ #endif + } + } + fput_light(sock->file, fput_needed); diff --git a/patches/4.10/0029-igloo_weaksyms-fix-up-passed-arguments.patch b/patches/4.10/0029-igloo_weaksyms-fix-up-passed-arguments.patch new file mode 100644 index 0000000..4ff9a2c --- /dev/null +++ b/patches/4.10/0029-igloo_weaksyms-fix-up-passed-arguments.patch @@ -0,0 +1,28 @@ +From f5ea95cc58d79e1684e9deded48fbb49a388ac4b Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 22 Sep 2025 09:03:56 -0400 +Subject: [PATCH 29/38] igloo_weaksyms: fix up passed arguments + +--- + drivers/igloobase/igloo_weaksyms.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/igloobase/igloo_weaksyms.c b/drivers/igloobase/igloo_weaksyms.c +index 3057659f1a..2fa239ea76 100644 +--- a/drivers/igloobase/igloo_weaksyms.c ++++ b/drivers/igloobase/igloo_weaksyms.c +@@ -75,12 +75,12 @@ void igloo_hc_open(int dfd, struct filename *tmp, int fd) + } + EXPORT_SYMBOL(igloo_hc_open); + +-void (*igloo_ioctl_module)(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp); ++void (*igloo_ioctl_module)(int error, struct file *filp, unsigned int cmd); + void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp); + void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) + { + if (igloo_ioctl_module) { +- igloo_ioctl_module(error, inode, filp, cmd, argp); ++ igloo_ioctl_module(error, filp, cmd); + } else { + // printk(KERN_EMERG "igloo_ioctl: unimplemented\n"); + } diff --git a/patches/4.10/0030-syscalls_info_report-handle-different-4.10-issues.patch b/patches/4.10/0030-syscalls_info_report-handle-different-4.10-issues.patch new file mode 100644 index 0000000..7757e9c --- /dev/null +++ b/patches/4.10/0030-syscalls_info_report-handle-different-4.10-issues.patch @@ -0,0 +1,30 @@ +From 2a7c6f4c78a884f385d23e21f01f3330d796e131 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 22 Sep 2025 10:57:59 -0400 +Subject: [PATCH 30/38] syscalls_info_report: handle different 4.10 issues + +--- + drivers/igloobase/syscalls_info_report.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/igloobase/syscalls_info_report.c b/drivers/igloobase/syscalls_info_report.c +index 1f447bcc95..917a1041e1 100644 +--- a/drivers/igloobase/syscalls_info_report.c ++++ b/drivers/igloobase/syscalls_info_report.c +@@ -121,9 +121,16 @@ static void report_syscall(char * buffer, struct syscall_metadata *meta){ + #ifdef CONFIG_COMPAT + /* For ARM64 */ + #if defined(CONFIG_ARM64) ++#ifndef syscall_fn_t ++typedef void* syscall_fn_t; ++#endif + extern const syscall_fn_t compat_sys_call_table[]; + /* Don't redeclare sys_call_table as it's already in syscall.h with correct type */ ++#ifdef __NR_compat32_syscalls + #define COMPAT_TABLE_SIZE __NR_compat32_syscalls ++#else ++#define COMPAT_TABLE_SIZE __NR_compat_syscalls ++#endif + + /* For x86_64 */ + // #elif defined(CONFIG_X86_64) diff --git a/patches/4.10/0031-compat.h-formatting-and-forward-declare.patch b/patches/4.10/0031-compat.h-formatting-and-forward-declare.patch new file mode 100644 index 0000000..ff2bf35 --- /dev/null +++ b/patches/4.10/0031-compat.h-formatting-and-forward-declare.patch @@ -0,0 +1,48 @@ +From 9eeec2a5ceb7c677a7096ff1e4f2fd789ec516a7 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 22 Sep 2025 10:58:13 -0400 +Subject: [PATCH 31/38] compat.h: formatting and forward declare + +--- + include/linux/compat.h | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/include/linux/compat.h b/include/linux/compat.h +index 8c02fb57e2..941faf7ac2 100644 +--- a/include/linux/compat.h ++++ b/include/linux/compat.h +@@ -39,6 +39,7 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + #endif + + #define COMPAT_SYSCALL_DEFINE0(name) \ ++ static inline long __do_compat_sys_##name(void); \ + asmlinkage long compat_sys_##name(void) \ + { \ + const char *syscall_basename = __stringify(name); /* Base name */ \ +@@ -47,7 +48,7 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + long skip_ret = 0; \ + /* Array for arguments (empty for 0 args) */ \ + unsigned long args_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ +- ++ \ + /* === Igloo Enter Hook === */ \ + if (igloo_syscall_enter_hook) { \ + /* Pass NULL for setter func for 0-arg syscalls */ \ +@@ -66,7 +67,7 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + } \ + \ + return ret ; \ +- } ++ } \ + static inline long __do_compat_sys_##name(void) + + +@@ -92,7 +93,7 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + void __compat_igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ + { \ + __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); \ +- } ++ } \ + asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));\ + asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\ + { \ diff --git a/patches/4.10/0032-igloo-debug-calls-now-pr_emerg-when-enabled.patch b/patches/4.10/0032-igloo-debug-calls-now-pr_emerg-when-enabled.patch new file mode 100644 index 0000000..a302286 --- /dev/null +++ b/patches/4.10/0032-igloo-debug-calls-now-pr_emerg-when-enabled.patch @@ -0,0 +1,83 @@ +From adf994aaca52a4043ffe38fa11b38a43bbc23dd3 Mon Sep 17 00:00:00 2001 +From: Zak Estrada +Date: Fri, 24 Oct 2025 16:20:21 -0400 +Subject: [PATCH 32/38] igloo debug calls now pr_emerg when enabled + +--- + drivers/igloobase/igloo_args.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/igloobase/igloo_args.c b/drivers/igloobase/igloo_args.c +index bdb65d1fbc..3adc5b7b67 100644 +--- a/drivers/igloobase/igloo_args.c ++++ b/drivers/igloobase/igloo_args.c +@@ -19,11 +19,11 @@ static int __init early_igloo_task_size(char *p) + { + unsigned long task_size; + if (kstrtoul(p, 0, &task_size) < 0 ) { +- pr_warn("Could not parse igloo_task_size parameter %s\n", p); ++ pr_emerg("Could not parse igloo_task_size parameter %s\n", p); + return -1; + } + igloo_task_size = task_size; +- pr_warn_once("Using igloo_task_size: 0x%lx\n", igloo_task_size); ++ pr_emerg_once("Using igloo_task_size: 0x%lx\n", igloo_task_size); + return 0; + } + early_param("igloo_task_size", early_igloo_task_size); +@@ -35,11 +35,11 @@ static int __init early_igloo_block_halt(char *p) + { + unsigned long block_halt; + if (kstrtoul(p, 0, &block_halt) < 0 ) { +- pr_warn("Could not parse igloo_block_halt parameter %s. Set to 0 (default) or 1\n", p); ++ pr_emerg("Could not parse igloo_block_halt parameter %s. Set to 0 (default) or 1\n", p); + return -1; + } + igloo_block_halt = (block_halt > 0); +- pr_warn_once("Using igloo_block_halt: %d\n", igloo_block_halt); ++ pr_emerg_once("Using igloo_block_halt: %d\n", igloo_block_halt); + return 0; + } + +@@ -75,14 +75,14 @@ static int __init early_igloo_debug_modules(char *p) + // Special case: "all" enables all modules + if (!strcmp(p, "all")) { + memset(&igloo_debug, 1, sizeof(igloo_debug)); +- pr_warn_once("IGLOO: Debug enabled for all modules\n"); ++ pr_emerg_once("IGLOO: Debug enabled for all modules\n"); + return 0; + } + + // Special case: "none" disables all modules (default) + if (!strcmp(p, "none")) { + memset(&igloo_debug, 0, sizeof(igloo_debug)); +- pr_warn_once("IGLOO: Debug disabled for all modules\n"); ++ pr_emerg_once("IGLOO: Debug disabled for all modules\n"); + return 0; + } + +@@ -100,14 +100,14 @@ static int __init early_igloo_debug_modules(char *p) + igloo_debug.osi = true; + else if (!strcmp(token, "all")){ + memset(&igloo_debug, 1, sizeof(igloo_debug)); +- pr_warn_once("IGLOO: Debug enabled for all modules\n"); ++ pr_emerg_once("IGLOO: Debug enabled for all modules\n"); + return 0; + } + else +- pr_warn("IGLOO: Unknown debug module: %s\n", token); ++ pr_emerg("IGLOO: Unknown debug module: %s\n", token); + } + +- pr_warn_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d\n", ++ pr_emerg_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d\n", + igloo_debug.portal, igloo_debug.uprobe, igloo_debug.vma, + igloo_debug.syscall, igloo_debug.osi); + +@@ -115,4 +115,4 @@ static int __init early_igloo_debug_modules(char *p) + } + + early_param("igloo_debug", early_igloo_debug_modules); +-EXPORT_SYMBOL(igloo_debug); +\ No newline at end of file ++EXPORT_SYMBOL(igloo_debug); diff --git a/patches/4.10/0033-open.c-fix-fd-in-igloo_open_hc-29.patch b/patches/4.10/0033-open.c-fix-fd-in-igloo_open_hc-29.patch new file mode 100644 index 0000000..527661a --- /dev/null +++ b/patches/4.10/0033-open.c-fix-fd-in-igloo_open_hc-29.patch @@ -0,0 +1,36 @@ +From aa8b9774e5b75703481d819796a31f27fe3fe28c Mon Sep 17 00:00:00 2001 +From: Benjamin Levy <153011444+be32826@users.noreply.github.com> +Date: Fri, 7 Nov 2025 13:52:38 -0500 +Subject: [PATCH 33/38] open.c: fix fd in igloo_open_hc() (#29) + +--- + fs/open.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/fs/open.c b/fs/open.c +index 309a355ef8..c58f172980 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -1053,10 +1053,6 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + +-#ifdef CONFIG_IGLOO +- igloo_hc_open(dfd, tmp, fd); +-#endif +- + fd = get_unused_fd_flags(flags); + if (fd >= 0) { + struct file *f = do_filp_open(dfd, tmp, &op); +@@ -1068,6 +1064,11 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) + fd_install(fd, f); + } + } ++ ++#ifdef CONFIG_IGLOO ++ igloo_hc_open(dfd, tmp, fd); ++#endif ++ + putname(tmp); + return fd; + } diff --git a/patches/4.10/0034-kprobe-options.patch b/patches/4.10/0034-kprobe-options.patch new file mode 100644 index 0000000..80683c5 --- /dev/null +++ b/patches/4.10/0034-kprobe-options.patch @@ -0,0 +1,50 @@ +From da9f5b3d380f3f4784624c8faabd42ed1ac9d1a8 Mon Sep 17 00:00:00 2001 +From: Zak Estrada +Date: Tue, 6 Jan 2026 12:22:54 -0500 +Subject: [PATCH 34/38] kprobe options + +--- + drivers/igloobase/igloo_args.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/igloobase/igloo_args.c b/drivers/igloobase/igloo_args.c +index 3adc5b7b67..3674da3f42 100644 +--- a/drivers/igloobase/igloo_args.c ++++ b/drivers/igloobase/igloo_args.c +@@ -53,6 +53,7 @@ struct igloo_debug_config { + bool vma; // Enable debug for VMA tracking + bool syscall; // Enable debug for syscall tracking + bool osi; // Enable debug for OSI features ++ bool kprobe; // Enable debug for kprobe module + }; + + // Global debug configuration +@@ -62,6 +63,7 @@ struct igloo_debug_config igloo_debug = { + .vma = false, + .syscall = false, + .osi = false, ++ .kprobe = false, + }; + + // Parse comma-separated list of modules to enable debug logging for +@@ -98,6 +100,8 @@ static int __init early_igloo_debug_modules(char *p) + igloo_debug.syscall = true; + else if (!strcmp(token, "osi")) + igloo_debug.osi = true; ++ else if (!strcmp(token, "kprobe")) ++ igloo_debug.kprobe = true; + else if (!strcmp(token, "all")){ + memset(&igloo_debug, 1, sizeof(igloo_debug)); + pr_emerg_once("IGLOO: Debug enabled for all modules\n"); +@@ -107,9 +111,9 @@ static int __init early_igloo_debug_modules(char *p) + pr_emerg("IGLOO: Unknown debug module: %s\n", token); + } + +- pr_emerg_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d\n", ++ pr_emerg_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d kprobe: %d\n", + igloo_debug.portal, igloo_debug.uprobe, igloo_debug.vma, +- igloo_debug.syscall, igloo_debug.osi); ++ igloo_debug.syscall, igloo_debug.osi, igloo_debug.kprobe); + + return 0; + } diff --git a/patches/4.10/0035-igloo-fix-igloo_task_size.patch b/patches/4.10/0035-igloo-fix-igloo_task_size.patch new file mode 100644 index 0000000..1c460fe --- /dev/null +++ b/patches/4.10/0035-igloo-fix-igloo_task_size.patch @@ -0,0 +1,407 @@ +From d19918576cb9bf1a30e0d68f9b7271188cb4c7a3 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 9 May 2026 16:53:37 -0400 +Subject: [PATCH 35/38] igloo: fix igloo_task_size + +--- + arch/arm/mm/mmap.c | 35 ++++++++++++++++++++++++++++------- + arch/arm64/mm/mmap.c | 11 ++++++++++- + arch/mips/mm/mmap.c | 25 ++++++++++++++++++++----- + arch/powerpc/mm/mmap.c | 35 ++++++++++++++++++++++++++++------- + arch/x86/kernel/module.c | 2 ++ + fs/binfmt_elf.c | 18 +++++++++++------- + 6 files changed, 99 insertions(+), 27 deletions(-) + +diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c +index 66353caa35..265bd61527 100644 +--- a/arch/arm/mm/mmap.c ++++ b/arch/arm/mm/mmap.c +@@ -10,6 +10,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + + #define COLOUR_ALIGN(addr,pgoff) \ + ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ +@@ -33,13 +36,19 @@ static int mmap_is_legacy(void) + static unsigned long mmap_base(unsigned long rnd) + { + unsigned long gap = rlimit(RLIMIT_STACK); ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + +- return PAGE_ALIGN(TASK_SIZE - gap - rnd); ++ return PAGE_ALIGN(task_size - gap - rnd); + } + + /* +@@ -60,6 +69,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); + struct vm_unmapped_area_info info; ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + + /* + * We only need to do colour alignment if either the I or D +@@ -78,7 +93,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + return addr; + } + +- if (len > TASK_SIZE) ++ if (len > task_size) + return -ENOMEM; + + if (addr) { +@@ -88,7 +103,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && ++ if (task_size - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } +@@ -96,7 +111,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + info.flags = 0; + info.length = len; + info.low_limit = mm->mmap_base; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; + info.align_offset = pgoff << PAGE_SHIFT; + return vm_unmapped_area(&info); +@@ -113,6 +128,12 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); + struct vm_unmapped_area_info info; ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + + /* + * We only need to do colour alignment if either the I or D +@@ -122,7 +143,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + do_align = filp || (flags & MAP_SHARED); + + /* requested length too big for entire address space */ +- if (len > TASK_SIZE) ++ if (len > task_size) + return -ENOMEM; + + if (flags & MAP_FIXED) { +@@ -139,7 +160,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + else + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && ++ if (task_size - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } +@@ -162,7 +183,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + VM_BUG_ON(addr != -ENOMEM); + info.flags = 0; + info.low_limit = mm->mmap_base; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + addr = vm_unmapped_area(&info); + } + +diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c +index 01c171723b..e3451ed3fe 100644 +--- a/arch/arm64/mm/mmap.c ++++ b/arch/arm64/mm/mmap.c +@@ -26,6 +26,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + + #include + +@@ -63,13 +66,19 @@ unsigned long arch_mmap_rnd(void) + static unsigned long mmap_base(unsigned long rnd) + { + unsigned long gap = rlimit(RLIMIT_STACK); ++ unsigned long stack_top = STACK_TOP; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ stack_top = igloo_task_size; ++#endif + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + +- return PAGE_ALIGN(STACK_TOP - gap - rnd); ++ return PAGE_ALIGN(stack_top - gap - rnd); + } + + /* +diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c +index d08ea3ff0f..c9bd771a86 100644 +--- a/arch/mips/mm/mmap.c ++++ b/arch/mips/mm/mmap.c +@@ -14,6 +14,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + + unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ + EXPORT_SYMBOL(shm_align_mask); +@@ -36,13 +39,19 @@ static int mmap_is_legacy(void) + static unsigned long mmap_base(unsigned long rnd) + { + unsigned long gap = rlimit(RLIMIT_STACK); ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + +- return PAGE_ALIGN(TASK_SIZE - gap - rnd); ++ return PAGE_ALIGN(task_size - gap - rnd); + } + + #define COLOUR_ALIGN(addr, pgoff) \ +@@ -60,13 +69,19 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + unsigned long addr = addr0; + int do_color_align; + struct vm_unmapped_area_info info; ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + +- if (unlikely(len > TASK_SIZE)) ++ if (unlikely(len > task_size)) + return -ENOMEM; + + if (flags & MAP_FIXED) { + /* Even MAP_FIXED mappings must reside within TASK_SIZE */ +- if (TASK_SIZE - len < addr) ++ if (task_size - len < addr) + return -EINVAL; + + /* +@@ -91,7 +106,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && ++ if (task_size - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } +@@ -119,7 +134,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + + info.flags = 0; + info.low_limit = mm->mmap_base; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + return vm_unmapped_area(&info); + } + +diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c +index 2f1e443621..922de13121 100644 +--- a/arch/powerpc/mm/mmap.c ++++ b/arch/powerpc/mm/mmap.c +@@ -29,6 +29,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + + /* + * Top of mmap area (just below the process stack). +@@ -72,13 +75,19 @@ unsigned long arch_mmap_rnd(void) + static inline unsigned long mmap_base(unsigned long rnd) + { + unsigned long gap = rlimit(RLIMIT_STACK); ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + +- return PAGE_ALIGN(TASK_SIZE - gap - rnd); ++ return PAGE_ALIGN(task_size - gap - rnd); + } + + #ifdef CONFIG_PPC_RADIX_MMU +@@ -95,8 +104,14 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr, + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + struct vm_unmapped_area_info info; ++ unsigned long task_size = TASK_SIZE; + +- if (len > TASK_SIZE - mmap_min_addr) ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif ++ ++ if (len > task_size - mmap_min_addr) + return -ENOMEM; + + if (flags & MAP_FIXED) +@@ -105,7 +120,7 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr, + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && ++ if (task_size - len >= addr && addr >= mmap_min_addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } +@@ -113,7 +128,7 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr, + info.flags = 0; + info.length = len; + info.low_limit = mm->mmap_base; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + info.align_mask = 0; + return vm_unmapped_area(&info); + } +@@ -129,9 +144,15 @@ radix__arch_get_unmapped_area_topdown(struct file *filp, + struct mm_struct *mm = current->mm; + unsigned long addr = addr0; + struct vm_unmapped_area_info info; ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + + /* requested length too big for entire address space */ +- if (len > TASK_SIZE - mmap_min_addr) ++ if (len > task_size - mmap_min_addr) + return -ENOMEM; + + if (flags & MAP_FIXED) +@@ -141,7 +162,7 @@ radix__arch_get_unmapped_area_topdown(struct file *filp, + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && ++ if (task_size - len >= addr && addr >= mmap_min_addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } +@@ -163,7 +184,7 @@ radix__arch_get_unmapped_area_topdown(struct file *filp, + VM_BUG_ON(addr != -ENOMEM); + info.flags = 0; + info.low_limit = TASK_UNMAPPED_BASE; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + addr = vm_unmapped_area(&info); + } + +diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c +index 477ae806c2..bce156d6e9 100644 +--- a/arch/x86/kernel/module.c ++++ b/arch/x86/kernel/module.c +@@ -199,6 +199,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, + } + return 0; + ++invalid_relocation: ++ return -ENOEXEC; + overflow: + pr_err("overflow in relocation type %d val %Lx\n", + (int)ELF64_R_TYPE(rel[i].r_info), val); +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index af32087f08..2911b2670d 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -39,7 +39,14 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO + #include ++#define BAD_ADDR(x) ((unsigned long)(x) >= (igloo_task_size ? igloo_task_size : TASK_SIZE)) ++#define IGLOO_TASK_SIZE (igloo_task_size ? igloo_task_size : TASK_SIZE) ++#else ++#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE) ++#define IGLOO_TASK_SIZE TASK_SIZE ++#endif + + #ifndef user_long_t + #define user_long_t long +@@ -90,8 +97,6 @@ static struct linux_binfmt elf_format = { + .min_coredump = ELF_EXEC_PAGESIZE, + }; + +-#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE) +- + static int set_brk(unsigned long start, unsigned long end) + { + start = ELF_PAGEALIGN(start); +@@ -588,8 +593,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, + k = load_addr + eppnt->p_vaddr; + if (BAD_ADDR(k) || + eppnt->p_filesz > eppnt->p_memsz || +- eppnt->p_memsz > TASK_SIZE || +- TASK_SIZE - eppnt->p_memsz < k) { ++ eppnt->p_memsz > IGLOO_TASK_SIZE || ++ IGLOO_TASK_SIZE - eppnt->p_memsz < k) { + error = -ENOMEM; + goto out; + } +@@ -972,9 +977,8 @@ static int load_elf_binary(struct linux_binprm *bprm) + * <= p_memsz so it is only necessary to check p_memsz. + */ + if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz || +- elf_ppnt->p_memsz > TASK_SIZE || +- TASK_SIZE - elf_ppnt->p_memsz < k) { +- /* set_brk can never work. Avoid overflows. */ ++ elf_ppnt->p_memsz > IGLOO_TASK_SIZE || ++ IGLOO_TASK_SIZE - elf_ppnt->p_memsz < k) { /* set_brk can never work. Avoid overflows. */ + retval = -EINVAL; + goto out_free_dentry; + } diff --git a/patches/4.10/0037-igloo-move-into-procfs.patch b/patches/4.10/0037-igloo-move-into-procfs.patch new file mode 100644 index 0000000..c324992 --- /dev/null +++ b/patches/4.10/0037-igloo-move-into-procfs.patch @@ -0,0 +1,194 @@ +From 602218358ca6762cbcb9e0b018ebbc1999b9eb8f Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sun, 17 May 2026 13:21:12 -0400 +Subject: [PATCH 37/38] igloo: move into procfs + +--- + fs/proc/base.c | 143 +++++++++++++++++++++++++++++++++++++++- + include/linux/proc_fs.h | 5 ++ + 2 files changed, 146 insertions(+), 2 deletions(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 87c9a9aacd..b32679c1a0 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -70,6 +70,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -116,6 +117,125 @@ struct pid_entry { + union proc_op op; + }; + ++#ifdef CONFIG_IGLOO ++struct igloo_proc_pid_entry { ++ struct list_head list; ++ struct proc_dir_entry *pde; ++ const struct file_operations *fop; ++}; ++ ++static LIST_HEAD(igloo_proc_pid_entries); ++static DEFINE_MUTEX(igloo_proc_pid_entries_lock); ++ ++struct proc_dir_entry *igloo_proc_create_pid_data(const char *name, umode_t mode, ++ const struct file_operations *fop, ++ void *data) ++{ ++ struct igloo_proc_pid_entry *entry; ++ struct proc_dir_entry *pde; ++ size_t len; ++ ++ if (!name || !name[0] || strchr(name, '/')) ++ return NULL; ++ if ((mode & S_IFMT) == 0) ++ mode |= S_IFREG; ++ if ((mode & S_IALLUGO) == 0) ++ mode |= S_IRUGO; ++ if (!S_ISREG(mode) || !fop) ++ return NULL; ++ ++ len = strlen(name); ++ if (len >= 256) ++ return NULL; ++ ++ mutex_lock(&igloo_proc_pid_entries_lock); ++ list_for_each_entry(entry, &igloo_proc_pid_entries, list) { ++ pde = entry->pde; ++ if (pde->namelen == len && !memcmp(pde->name, name, len)) { ++ pde->mode = mode; ++ pde->data = data; ++ entry->fop = fop; ++ mutex_unlock(&igloo_proc_pid_entries_lock); ++ return pde; ++ } ++ } ++ mutex_unlock(&igloo_proc_pid_entries_lock); ++ ++ entry = kzalloc(sizeof(*entry), GFP_KERNEL); ++ if (!entry) ++ return NULL; ++ pde = kzalloc(sizeof(*pde) + len + 1, GFP_KERNEL); ++ if (!pde) { ++ kfree(entry); ++ return NULL; ++ } ++ ++ memcpy(pde->name, name, len + 1); ++ pde->namelen = len; ++ pde->mode = mode; ++ pde->nlink = 1; ++ pde->data = data; ++ pde->subdir = RB_ROOT; ++ atomic_set(&pde->count, 1); ++ spin_lock_init(&pde->pde_unload_lock); ++ INIT_LIST_HEAD(&pde->pde_openers); ++ ++ entry->pde = pde; ++ entry->fop = fop; ++ ++ mutex_lock(&igloo_proc_pid_entries_lock); ++ list_add(&entry->list, &igloo_proc_pid_entries); ++ mutex_unlock(&igloo_proc_pid_entries_lock); ++ ++ return pde; ++} ++EXPORT_SYMBOL_GPL(igloo_proc_create_pid_data); ++ ++static int igloo_proc_pid_instantiate(struct inode *dir, struct dentry *dentry, ++ struct task_struct *task, ++ struct igloo_proc_pid_entry *entry) ++{ ++ struct inode *inode; ++ struct proc_dir_entry *pde = entry->pde; ++ ++ inode = proc_pid_make_inode(dir->i_sb, task, pde->mode); ++ if (!inode) ++ return -ENOENT; ++ ++ pde_get(pde); ++ PROC_I(inode)->pde = pde; ++ inode->i_fop = entry->fop; ++ if (pde->size) ++ inode->i_size = pde->size; ++ d_set_d_op(dentry, &pid_dentry_operations); ++ d_add(dentry, inode); ++ if (pid_revalidate(dentry, 0)) ++ return 0; ++ return -ENOENT; ++} ++ ++static int igloo_proc_pid_lookup(struct inode *dir, struct dentry *dentry, ++ struct task_struct *task) ++{ ++ struct igloo_proc_pid_entry *entry; ++ int error = -ENOENT; ++ ++ mutex_lock(&igloo_proc_pid_entries_lock); ++ list_for_each_entry(entry, &igloo_proc_pid_entries, list) { ++ if (entry->pde->namelen != dentry->d_name.len) ++ continue; ++ if (!memcmp(entry->pde->name, dentry->d_name.name, ++ dentry->d_name.len)) { ++ error = igloo_proc_pid_instantiate(dir, dentry, task, ++ entry); ++ break; ++ } ++ } ++ mutex_unlock(&igloo_proc_pid_entries_lock); ++ return error; ++} ++#endif ++ + #define NOD(NAME, MODE, IOP, FOP, OP) { \ + .name = (NAME), \ + .len = sizeof(NAME) - 1, \ +@@ -2956,8 +3076,27 @@ static const struct file_operations proc_tgid_base_operations = { + + static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) + { +- return proc_pident_lookup(dir, dentry, +- tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); ++ struct dentry *res; ++#ifdef CONFIG_IGLOO ++ struct task_struct *task; ++ int error; ++#endif ++ ++ res = proc_pident_lookup(dir, dentry, ++ tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); ++#ifdef CONFIG_IGLOO ++ if (!IS_ERR(res) || PTR_ERR(res) != -ENOENT) ++ return res; ++ ++ task = get_proc_task(dir); ++ if (!task) ++ return res; ++ error = igloo_proc_pid_lookup(dir, dentry, task); ++ put_task_struct(task); ++ if (!error) ++ return NULL; ++#endif ++ return res; + } + + static const struct inode_operations proc_tgid_base_inode_operations = { +diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h +index 2d2bf592d9..b421adfb99 100644 +--- a/include/linux/proc_fs.h ++++ b/include/linux/proc_fs.h +@@ -27,6 +27,11 @@ extern struct proc_dir_entry *proc_create_data(const char *, umode_t, + struct proc_dir_entry *, + const struct file_operations *, + void *); ++#ifdef CONFIG_IGLOO ++extern struct proc_dir_entry *igloo_proc_create_pid_data(const char *, umode_t, ++ const struct file_operations *, ++ void *); ++#endif + + static inline struct proc_dir_entry *proc_create( + const char *name, umode_t mode, struct proc_dir_entry *parent, diff --git a/patches/4.10/0038-igloo-move-into-signal-handler.patch b/patches/4.10/0038-igloo-move-into-signal-handler.patch new file mode 100644 index 0000000..d73818f --- /dev/null +++ b/patches/4.10/0038-igloo-move-into-signal-handler.patch @@ -0,0 +1,69 @@ +From 68996875436ed6bd835047465f364916d468d394 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sun, 17 May 2026 13:21:20 -0400 +Subject: [PATCH 38/38] igloo: move into signal handler + +--- + include/linux/igloo_signal.h | 12 ++++++++++++ + kernel/signal.c | 15 +++++++++++++++ + 2 files changed, 27 insertions(+) + create mode 100644 include/linux/igloo_signal.h + +diff --git a/include/linux/igloo_signal.h b/include/linux/igloo_signal.h +new file mode 100644 +index 0000000000..375b5ee68b +--- /dev/null ++++ b/include/linux/igloo_signal.h +@@ -0,0 +1,12 @@ ++#ifndef _LINUX_IGLOO_SIGNAL_H ++#define _LINUX_IGLOO_SIGNAL_H ++ ++#include ++ ++struct task_struct; ++ ++typedef bool (*igloo_signal_deliver_hook_t)(int sig, struct task_struct *task); ++ ++extern igloo_signal_deliver_hook_t igloo_signal_deliver_hook; ++ ++#endif /* _LINUX_IGLOO_SIGNAL_H */ +diff --git a/kernel/signal.c b/kernel/signal.c +index 3603d93a19..72976c1210 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -34,6 +34,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + + #define CREATE_TRACE_POINTS + #include +@@ -51,6 +54,11 @@ + + static struct kmem_cache *sigqueue_cachep; + ++#ifdef CONFIG_IGLOO ++igloo_signal_deliver_hook_t igloo_signal_deliver_hook; ++EXPORT_SYMBOL_GPL(igloo_signal_deliver_hook); ++#endif ++ + int print_fatal_signals __read_mostly; + + static void __user *sig_handler(struct task_struct *t, int sig) +@@ -986,6 +994,13 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, + assert_spin_locked(&t->sighand->siglock); + + result = TRACE_SIGNAL_IGNORED; ++#ifdef CONFIG_IGLOO ++ if (sig && igloo_signal_deliver_hook && ++ igloo_signal_deliver_hook(sig, t)) { ++ ret = 0; ++ goto ret; ++ } ++#endif + if (!prepare_signal(sig, t, + from_ancestor_ns || (info == SEND_SIG_FORCED))) + goto ret; diff --git a/patches/4.10/series b/patches/4.10/series new file mode 100644 index 0000000..05d0ffb --- /dev/null +++ b/patches/4.10/series @@ -0,0 +1,38 @@ +4.10/0001-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch +core/add-hypercall.h.patch +4.10/0003-reboot.c-add-igloo_block_halt.patch +4.10/0004-socket.c-add-igloo_socket_hc.patch +core/add-igloo.h.patch +4.10/0006-open.c-add-igloo_open_hc.patch +4.10/0007-sys.c-add-igloo_hc_newuname.patch +4.10/0008-namespace.c-add-igloo_should_block_mount.patch +4.10/0009-ioctl.c-add-igloo_ioctl_hc.patch +4.10/0010-igloobase-add-driver.patch +4.10/0011-exec.c-add-igloo_task_size.patch +4.10/0012-mmap.c-add-igloo_task_size.patch +core/add-igloo_syscall_macros.h.patch +4.10/0014-add-syscalls.h.patch +4.10/0015-syscalls.h-fixes.patch +4.10/0016-syscals.h-fix-sname-in-define0.patch +4.10/0017-binfmt_elf.c-add-igloo_task_size-support.patch +4.10/0018-compat.h-syscalls-support.patch +4.10/0019-give-up-on-gcc-ilog2-constant-optimizations.patch +4.10/0020-extern-yylloc-so-gcc-is-happy.patch +4.10/0021-Fix-build-with-GCC-versions-8-for-some-targets.patch +4.10/0022-igloo_weaksyms-fix-igloo_hc_open-type.patch +4.10/0023-igloo_weaksyms-forward-proper-types-for-4.10.patch +4.10/0024-igloobase.c-4.10-compliance.patch +4.10/0025-osi_notifier-4.10-compliance.patch +4.10/0026-syscalls_info_report-4.10-compliance.patch +4.10/0027-socket.c-add-config_igloo.patch +core/igloo.h-drop-declarations-for-forward-declarations.patch +4.10/0029-igloo_weaksyms-fix-up-passed-arguments.patch +4.10/0030-syscalls_info_report-handle-different-4.10-issues.patch +4.10/0031-compat.h-formatting-and-forward-declare.patch +4.10/0032-igloo-debug-calls-now-pr_emerg-when-enabled.patch +4.10/0033-open.c-fix-fd-in-igloo_open_hc-29.patch +4.10/0034-kprobe-options.patch +4.10/0035-igloo-fix-igloo_task_size.patch +core/update-hypercall.h.patch +4.10/0037-igloo-move-into-procfs.patch +4.10/0038-igloo-move-into-signal-handler.patch diff --git a/patches/6.13/0005-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch b/patches/6.13/0005-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch new file mode 100644 index 0000000..af161b8 --- /dev/null +++ b/patches/6.13/0005-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch @@ -0,0 +1,26 @@ +From bd7d61d4636fb7a5b18d99c3a3bf718bbbf600ff Mon Sep 17 00:00:00 2001 +From: Andrew Fasano +Date: Mon, 18 Dec 2023 09:59:33 -0500 +Subject: [PATCH 05/37] Net: disallow changing bridge mac addrs (from + firmadyne. Unnecessary?) + +--- + net/core/dev.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/core/dev.c b/net/core/dev.c +index a9f62f5aeb..7888f2e4ff 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -9213,6 +9213,11 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa, + const struct net_device_ops *ops = dev->netdev_ops; + int err; + ++ if (dev->priv_flags & IFF_EBRIDGE) { ++ //Changing bridge mac-addrs only causes issues ++ return 0; ++ } ++ + if (!ops->ndo_set_mac_address) + return -EOPNOTSUPP; + if (sa->sa_family != dev->type) diff --git a/patches/6.13/0007-reboot.c-add-igloo_block_halt.patch b/patches/6.13/0007-reboot.c-add-igloo_block_halt.patch new file mode 100644 index 0000000..396db19 --- /dev/null +++ b/patches/6.13/0007-reboot.c-add-igloo_block_halt.patch @@ -0,0 +1,66 @@ +From cb27eddec82f6f126fa9f034eb1139774155cdd6 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 17 Mar 2025 16:02:48 -0400 +Subject: [PATCH 07/37] reboot.c: add igloo_block_halt + +--- + kernel/reboot.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/kernel/reboot.c b/kernel/reboot.c +index a701000bab..463a08b3f9 100644 +--- a/kernel/reboot.c ++++ b/kernel/reboot.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + /* + * this indicates whether you can reboot with ctrl-alt-del: the default is yes +@@ -281,6 +282,10 @@ static void do_kernel_restart_prepare(void) + */ + void kernel_restart(char *cmd) + { ++ if (igloo_block_halt) { ++ printk("IGLOO: refusing to restart\n"); ++ return; ++ } + kernel_restart_prepare(cmd); + do_kernel_restart_prepare(); + migrate_to_reboot_cpu(); +@@ -309,6 +314,10 @@ static void kernel_shutdown_prepare(enum system_states state) + */ + void kernel_halt(void) + { ++ if (igloo_block_halt) { ++ printk("IGLOO: refusing to halt\n"); ++ return; ++ } + kernel_shutdown_prepare(SYSTEM_HALT); + migrate_to_reboot_cpu(); + syscore_shutdown(); +@@ -699,6 +708,10 @@ EXPORT_SYMBOL_GPL(kernel_can_power_off); + */ + void kernel_power_off(void) + { ++ if (igloo_block_halt) { ++ printk("IGLOO: refusing to power off\n"); ++ return; ++ } + kernel_shutdown_prepare(SYSTEM_POWER_OFF); + do_kernel_power_off_prepare(); + migrate_to_reboot_cpu(); +@@ -726,6 +739,11 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, + char buffer[256]; + int ret = 0; + ++ if (igloo_block_halt) { ++ printk("IGLOO: refusing to reboot\n"); ++ return -EPERM; ++ } ++ + /* We only trust the superuser with rebooting the system. */ + if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT)) + return -EPERM; diff --git a/patches/6.13/0008-socket.c-add-igloo_socket_hc.patch b/patches/6.13/0008-socket.c-add-igloo_socket_hc.patch new file mode 100644 index 0000000..a2e8303 --- /dev/null +++ b/patches/6.13/0008-socket.c-add-igloo_socket_hc.patch @@ -0,0 +1,52 @@ +From 6570978cf237237b111d0e40c9b4908fcb15b201 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Tue, 29 Jul 2025 13:39:22 -0400 +Subject: [PATCH 08/37] socket.c: add igloo_socket_hc + +--- + net/socket.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/net/socket.c b/net/socket.c +index 9a117248f1..b69372eef4 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -628,10 +628,13 @@ struct socket *sock_alloc(void) + } + EXPORT_SYMBOL(sock_alloc); + ++// forward declare igloo_sock_release ++void igloo_sock_release(struct socket *sock); ++ + static void __sock_release(struct socket *sock, struct inode *inode) + { + const struct proto_ops *ops = READ_ONCE(sock->ops); +- ++ igloo_sock_release(sock); + if (ops) { + struct module *owner = ops->owner; + +@@ -1816,6 +1819,9 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, + return __sys_socketpair(family, type, protocol, usockvec); + } + ++// forward declare igloo_sock_bind ++void igloo_sock_bind(struct socket *sock, struct sockaddr_storage *address); ++ + int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address, + int addrlen) + { +@@ -1823,10 +1829,12 @@ int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address, + + err = security_socket_bind(sock, (struct sockaddr *)address, + addrlen); +- if (!err) ++ if (!err){ + err = READ_ONCE(sock->ops)->bind(sock, + (struct sockaddr *)address, + addrlen); ++ igloo_sock_bind(sock, address); ++ } + return err; + } + diff --git a/patches/6.13/0010-open.c-add-igloo_open_hc.patch b/patches/6.13/0010-open.c-add-igloo_open_hc.patch new file mode 100644 index 0000000..a321aae --- /dev/null +++ b/patches/6.13/0010-open.c-add-igloo_open_hc.patch @@ -0,0 +1,36 @@ +From 3ac86bbf533d2651f5ac02fa09fccd73596cb77e Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 17 Mar 2025 15:13:19 -0400 +Subject: [PATCH 10/37] open.c: add igloo_open_hc + +--- + fs/open.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/fs/open.c b/fs/open.c +index e6911101fe..ed0828cb91 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -1383,6 +1383,11 @@ struct file *file_open_root(const struct path *root, + } + EXPORT_SYMBOL(file_open_root); + ++#ifdef CONFIG_IGLOO ++// forward declare for igloo_hc_open ++void igloo_hc_open(int dfd, struct filename *tmp, int fd); ++#endif ++ + static long do_sys_openat2(int dfd, const char __user *filename, + struct open_how *how) + { +@@ -1396,7 +1401,9 @@ static long do_sys_openat2(int dfd, const char __user *filename, + tmp = getname(filename); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); +- ++ #ifdef CONFIG_IGLOO ++ igloo_hc_open(dfd, tmp, fd); ++ #endif + fd = get_unused_fd_flags(how->flags); + if (fd >= 0) { + struct file *f = do_filp_open(dfd, tmp, &op); diff --git a/patches/6.13/0011-sys.c-add-igloo_hc_newuname.patch b/patches/6.13/0011-sys.c-add-igloo_hc_newuname.patch new file mode 100644 index 0000000..56aa936 --- /dev/null +++ b/patches/6.13/0011-sys.c-add-igloo_hc_newuname.patch @@ -0,0 +1,33 @@ +From c483bc707544112873947e211b355de09d639f37 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Tue, 29 Jul 2025 13:39:56 -0400 +Subject: [PATCH 11/37] sys.c: add igloo_hc_newuname + +--- + kernel/sys.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/kernel/sys.c b/kernel/sys.c +index c4c701c6f0..c472abafbf 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -1312,6 +1312,9 @@ static int override_release(char __user *release, size_t len) + return ret; + } + ++// forward declare make_igloo_utsname ++void igloo_hc_newuname(struct new_utsname *name); ++ + SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) + { + struct new_utsname tmp; +@@ -1319,6 +1322,9 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) + down_read(&uts_sem); + memcpy(&tmp, utsname(), sizeof(tmp)); + up_read(&uts_sem); ++ ++ igloo_hc_newuname(&tmp); ++ + if (copy_to_user(name, &tmp, sizeof(tmp))) + return -EFAULT; + diff --git a/patches/6.13/0012-namespace.c-add-igloo_should_block_mount.patch b/patches/6.13/0012-namespace.c-add-igloo_should_block_mount.patch new file mode 100644 index 0000000..79d40b5 --- /dev/null +++ b/patches/6.13/0012-namespace.c-add-igloo_should_block_mount.patch @@ -0,0 +1,39 @@ +From b578a0161e836943a169f95655e70bf61bd40db4 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Tue, 29 Jul 2025 13:41:02 -0400 +Subject: [PATCH 12/37] namespace.c: add igloo_should_block_mount + +--- + fs/namespace.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index eac057e569..921c99f2c7 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -3746,6 +3746,11 @@ static char *copy_mount_string(const void __user *data) + return data ? strndup_user(data, PATH_MAX) : NULL; + } + ++#ifdef CONFIG_IGLOO ++// forward declare igloo_should_block_mount ++bool igloo_should_block_mount(struct path *path); ++#endif ++ + /* + * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to + * be given to the mount() call (ie: read-only, no-dev, no-suid etc). +@@ -3784,7 +3789,12 @@ int path_mount(const char *dev_name, struct path *path, + return -EPERM; + if (flags & SB_MANDLOCK) + warn_mandlock(); +- ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_should_block_mount(path)){ ++ return 0; ++ } ++#endif + /* Default to relatime unless overriden */ + if (!(flags & MS_NOATIME)) + mnt_flags |= MNT_RELATIME; diff --git a/patches/6.13/0013-ioctl.c-add-igloo_ioctl_hc.patch b/patches/6.13/0013-ioctl.c-add-igloo_ioctl_hc.patch new file mode 100644 index 0000000..2b5423b --- /dev/null +++ b/patches/6.13/0013-ioctl.c-add-igloo_ioctl_hc.patch @@ -0,0 +1,52 @@ +From eb2e953c1def35bb92deeec5763667ddbc9e31ec Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 17 Mar 2025 15:12:52 -0400 +Subject: [PATCH 13/37] ioctl.c: add igloo_ioctl_hc + +--- + fs/ioctl.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/fs/ioctl.c b/fs/ioctl.c +index 638a36be31..270ad13437 100644 +--- a/fs/ioctl.c ++++ b/fs/ioctl.c +@@ -789,6 +789,11 @@ static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp) + return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0; + } + ++#ifdef CONFIG_IGLOO ++// forward declare igloo_ioctl ++void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user * argp); ++#endif ++ + /* + * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. + * It's just a simple helper for sys_ioctl and compat_sys_ioctl. +@@ -799,8 +804,8 @@ static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp) + * The LSM mailing list should also be notified of any command additions or + * changes, as specific LSMs may be affected. + */ +-static int do_vfs_ioctl(struct file *filp, unsigned int fd, +- unsigned int cmd, unsigned long arg) ++static int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, ++ unsigned long arg) + { + void __user *argp = (void __user *)arg; + struct inode *inode = file_inode(filp); +@@ -881,8 +886,13 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd, + return ioctl_get_fs_sysfs_path(filp, argp); + + default: +- if (S_ISREG(inode->i_mode)) +- return file_ioctl(filp, cmd, argp); ++ if (S_ISREG(inode->i_mode)){ ++ int error = file_ioctl(filp, cmd, argp); ++ #ifdef CONFIG_IGLOO ++ igloo_ioctl(error, inode, filp, cmd, argp); ++ #endif ++ return error; ++ } + break; + } + diff --git a/patches/6.13/0014-igloobase-add-driver.patch b/patches/6.13/0014-igloobase-add-driver.patch new file mode 100644 index 0000000..e038eb6 --- /dev/null +++ b/patches/6.13/0014-igloobase-add-driver.patch @@ -0,0 +1,723 @@ +From 9aaca4d6a58568055ae73955430756b9a70fc55f Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:10:02 -0400 +Subject: [PATCH 14/37] igloobase: add driver + +--- + drivers/Kconfig | 2 + + drivers/Makefile | 3 + + drivers/igloobase/Kconfig | 5 + + drivers/igloobase/Makefile | 2 + + drivers/igloobase/igloo_args.c | 118 ++++++++++ + drivers/igloobase/igloo_weaksyms.c | 112 +++++++++ + drivers/igloobase/igloobase.c | 28 +++ + drivers/igloobase/igloobase.h | 2 + + drivers/igloobase/igloobasehypercalls.h | 6 + + drivers/igloobase/osi_notifier.c | 55 +++++ + drivers/igloobase/syscalls_info_report.c | 281 +++++++++++++++++++++++ + 11 files changed, 614 insertions(+) + create mode 100644 drivers/igloobase/Kconfig + create mode 100644 drivers/igloobase/Makefile + create mode 100644 drivers/igloobase/igloo_args.c + create mode 100644 drivers/igloobase/igloo_weaksyms.c + create mode 100644 drivers/igloobase/igloobase.c + create mode 100644 drivers/igloobase/igloobase.h + create mode 100644 drivers/igloobase/igloobasehypercalls.h + create mode 100644 drivers/igloobase/osi_notifier.c + create mode 100644 drivers/igloobase/syscalls_info_report.c + +diff --git a/drivers/Kconfig b/drivers/Kconfig +index 7bdad836fc..f08fe9f627 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -245,4 +245,6 @@ source "drivers/cdx/Kconfig" + + source "drivers/dpll/Kconfig" + ++source "drivers/igloobase/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 45d1c3e630..02d636d913 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -195,3 +195,6 @@ obj-$(CONFIG_CDX_BUS) += cdx/ + obj-$(CONFIG_DPLL) += dpll/ + + obj-$(CONFIG_S390) += s390/ ++ ++# Added ++obj-y += igloobase/ +\ No newline at end of file +diff --git a/drivers/igloobase/Kconfig b/drivers/igloobase/Kconfig +new file mode 100644 +index 0000000000..b20c5df509 +--- /dev/null ++++ b/drivers/igloobase/Kconfig +@@ -0,0 +1,5 @@ ++config IGLOO ++ bool "IGLOO module support" ++ default y ++ help ++ Support for IGLOO analysis +\ No newline at end of file +diff --git a/drivers/igloobase/Makefile b/drivers/igloobase/Makefile +new file mode 100644 +index 0000000000..1865aadfbb +--- /dev/null ++++ b/drivers/igloobase/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_IGLOO) += osi_notifier.o syscalls_info_report.o \ ++ igloobase.o igloo_weaksyms.o igloo_args.o +\ No newline at end of file +diff --git a/drivers/igloobase/igloo_args.c b/drivers/igloobase/igloo_args.c +new file mode 100644 +index 0000000000..bdb65d1fbc +--- /dev/null ++++ b/drivers/igloobase/igloo_args.c +@@ -0,0 +1,118 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "igloo_syscall_macros.h" ++#include "igloo.h" ++ ++ ++/** ++ * Early params originally from igloo_hc.c in the module ++ */ ++unsigned long igloo_task_size = 0; ++static int __init early_igloo_task_size(char *p) ++{ ++ unsigned long task_size; ++ if (kstrtoul(p, 0, &task_size) < 0 ) { ++ pr_warn("Could not parse igloo_task_size parameter %s\n", p); ++ return -1; ++ } ++ igloo_task_size = task_size; ++ pr_warn_once("Using igloo_task_size: 0x%lx\n", igloo_task_size); ++ return 0; ++} ++early_param("igloo_task_size", early_igloo_task_size); ++EXPORT_SYMBOL(igloo_task_size); ++ ++bool igloo_block_halt=false; ++ ++static int __init early_igloo_block_halt(char *p) ++{ ++ unsigned long block_halt; ++ if (kstrtoul(p, 0, &block_halt) < 0 ) { ++ pr_warn("Could not parse igloo_block_halt parameter %s. Set to 0 (default) or 1\n", p); ++ return -1; ++ } ++ igloo_block_halt = (block_halt > 0); ++ pr_warn_once("Using igloo_block_halt: %d\n", igloo_block_halt); ++ return 0; ++} ++ ++early_param("igloo_block_halt", early_igloo_block_halt); ++EXPORT_SYMBOL(igloo_block_halt); ++ ++// Debug logging configuration for each module ++struct igloo_debug_config { ++ bool portal; // Enable debug for portal module ++ bool uprobe; // Enable debug for uprobe module ++ bool vma; // Enable debug for VMA tracking ++ bool syscall; // Enable debug for syscall tracking ++ bool osi; // Enable debug for OSI features ++}; ++ ++// Global debug configuration ++struct igloo_debug_config igloo_debug = { ++ .portal = false, ++ .uprobe = false, ++ .vma = false, ++ .syscall = false, ++ .osi = false, ++}; ++ ++// Parse comma-separated list of modules to enable debug logging for ++static int __init early_igloo_debug_modules(char *p) ++{ ++ char *token; ++ ++ // By default, all modules have debug disabled ++ memset(&igloo_debug, 0, sizeof(igloo_debug)); ++ ++ // Special case: "all" enables all modules ++ if (!strcmp(p, "all")) { ++ memset(&igloo_debug, 1, sizeof(igloo_debug)); ++ pr_warn_once("IGLOO: Debug enabled for all modules\n"); ++ return 0; ++ } ++ ++ // Special case: "none" disables all modules (default) ++ if (!strcmp(p, "none")) { ++ memset(&igloo_debug, 0, sizeof(igloo_debug)); ++ pr_warn_once("IGLOO: Debug disabled for all modules\n"); ++ return 0; ++ } ++ ++ // Parse comma-separated module list ++ while ((token = strsep(&p, ",")) != NULL) { ++ if (!strcmp(token, "portal")) ++ igloo_debug.portal = true; ++ else if (!strcmp(token, "uprobe")) ++ igloo_debug.uprobe = true; ++ else if (!strcmp(token, "vma")) ++ igloo_debug.vma = true; ++ else if (!strcmp(token, "syscall")) ++ igloo_debug.syscall = true; ++ else if (!strcmp(token, "osi")) ++ igloo_debug.osi = true; ++ else if (!strcmp(token, "all")){ ++ memset(&igloo_debug, 1, sizeof(igloo_debug)); ++ pr_warn_once("IGLOO: Debug enabled for all modules\n"); ++ return 0; ++ } ++ else ++ pr_warn("IGLOO: Unknown debug module: %s\n", token); ++ } ++ ++ pr_warn_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d\n", ++ igloo_debug.portal, igloo_debug.uprobe, igloo_debug.vma, ++ igloo_debug.syscall, igloo_debug.osi); ++ ++ return 0; ++} ++ ++early_param("igloo_debug", early_igloo_debug_modules); ++EXPORT_SYMBOL(igloo_debug); +\ No newline at end of file +diff --git a/drivers/igloobase/igloo_weaksyms.c b/drivers/igloobase/igloo_weaksyms.c +new file mode 100644 +index 0000000000..8498d15500 +--- /dev/null ++++ b/drivers/igloobase/igloo_weaksyms.c +@@ -0,0 +1,112 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "igloo_syscall_macros.h" ++#include "igloo.h" ++ ++/* Syscall hooks */ ++igloo_syscall_enter_t igloo_syscall_enter_hook = NULL; ++igloo_syscall_return_t igloo_syscall_return_hook = NULL; ++EXPORT_SYMBOL(igloo_syscall_enter_hook); ++EXPORT_SYMBOL(igloo_syscall_return_hook); ++ ++// Function pointer for override ++bool (*igloo_should_block_mount_module)(struct path *path); ++bool igloo_should_block_mount(struct path *path); ++bool igloo_should_block_mount(struct path *path) ++{ ++ if (igloo_should_block_mount_module) { ++ return igloo_should_block_mount_module(path); ++ } else { ++ // printk(KERN_INFO "igloo_should_block_mount: default implementation called\n"); ++ return false; ++ } ++} ++EXPORT_SYMBOL(igloo_should_block_mount); ++ ++void (*igloo_sock_release_module)(struct socket *sock); ++void igloo_sock_release(struct socket *sock) ++{ ++ if (igloo_sock_release_module) { ++ igloo_sock_release_module(sock); ++ } else { ++ // printk(KERN_EMERG "igloo_sock_release: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_sock_release); ++ ++void (*igloo_sock_bind_module)(struct socket *sock, struct sockaddr_storage *address); ++void igloo_sock_bind(struct socket *sock, struct sockaddr_storage *address) ++{ ++ if (igloo_sock_bind_module) { ++ igloo_sock_bind_module(sock, address); ++ } else { ++ // printk(KERN_EMERG "igloo_sock_bind: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_sock_bind); ++ ++void (*igloo_hc_newuname_module)(struct new_utsname *name) = NULL; ++void igloo_hc_newuname(struct new_utsname *name) ++{ ++ if (igloo_hc_newuname_module) { ++ igloo_hc_newuname_module(name); ++ } else { ++ // printk(KERN_EMERG "igloo_hc_newuname: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_hc_newuname); ++ ++void (*igloo_hc_open_module)(int dfd, const char __user *filename, struct open_how *how); ++void igloo_hc_open(int dfd, const char __user *filename, struct open_how *how); ++void igloo_hc_open(int dfd, const char __user *filename, struct open_how *how) ++{ ++ if (igloo_hc_open_module) { ++ igloo_hc_open_module(dfd, filename, how); ++ } else { ++ // printk(KERN_EMERG "igloo_hc_open: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_hc_open); ++ ++void (*igloo_ioctl_module)(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp); ++void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp); ++void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) ++{ ++ if (igloo_ioctl_module) { ++ igloo_ioctl_module(error, inode, filp, cmd, argp); ++ } else { ++ // printk(KERN_EMERG "igloo_ioctl: unimplemented\n"); ++ } ++} ++EXPORT_SYMBOL(igloo_ioctl); ++ ++/* Export internal symbols needed for introspection research */ ++ ++// Symbol lookup functions - now pulled in by trace/syscall.h ++EXPORT_SYMBOL(kallsyms_lookup); ++ ++extern unsigned long kallsyms_lookup_name(const char *name); ++EXPORT_SYMBOL(kallsyms_lookup_name); ++ ++// Architecture-specific functions ++extern const char *arch_vma_name(struct vm_area_struct *vma); ++EXPORT_SYMBOL(arch_vma_name); ++ ++// Process management ++extern pid_t kernel_clone(struct kernel_clone_args *args); ++EXPORT_SYMBOL(kernel_clone); ++ ++extern int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid); ++EXPORT_SYMBOL(kill_pid_info); ++ ++// Memory access ++extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, ++ void *buf, int len, unsigned int gup_flags); ++EXPORT_SYMBOL(access_remote_vm); +\ No newline at end of file +diff --git a/drivers/igloobase/igloobase.c b/drivers/igloobase/igloobase.c +new file mode 100644 +index 0000000000..005835633c +--- /dev/null ++++ b/drivers/igloobase/igloobase.c +@@ -0,0 +1,28 @@ ++#include ++#include ++#include ++#include "igloo.h" ++#include "igloobase.h" ++ ++ ++/* Register probes for mmap and munmap */ ++static int __init igloo_base_init(void) { ++ printk(KERN_EMERG "IGLOOBase: Initializing\n"); ++ int ret = 0; ++ if ((ret = osi_notifier_init()) != 0) { ++ printk(KERN_ERR "Failed to register osi_notifier_init\n"); ++ } ++ if ((ret = syscalls_info_report()) != 0) { ++ printk(KERN_ERR "Failed to register syscalls_hc returning %d\n", ret); ++ } ++ return 0; ++} ++ ++/* Unregister probes */ ++static void __exit igloo_base_exit(void) { ++ // Unreachable, module is built in ++ printk(KERN_ERR "TODO\n"); ++} ++ ++module_init(igloo_base_init); ++module_exit(igloo_base_exit); +\ No newline at end of file +diff --git a/drivers/igloobase/igloobase.h b/drivers/igloobase/igloobase.h +new file mode 100644 +index 0000000000..3fe72b89a0 +--- /dev/null ++++ b/drivers/igloobase/igloobase.h +@@ -0,0 +1,2 @@ ++int osi_notifier_init(void); ++int syscalls_info_report(void); +\ No newline at end of file +diff --git a/drivers/igloobase/igloobasehypercalls.h b/drivers/igloobase/igloobasehypercalls.h +new file mode 100644 +index 0000000000..f7fa8b985e +--- /dev/null ++++ b/drivers/igloobase/igloobasehypercalls.h +@@ -0,0 +1,6 @@ ++// This should be a relatively small file as most functionality should be ++// implemented in the core igloo driver ++ ++enum igloo_base_hypercalls { ++ IGLOO_HYP_SETUP_SYSCALL = 0x1337, ++}; +\ No newline at end of file +diff --git a/drivers/igloobase/osi_notifier.c b/drivers/igloobase/osi_notifier.c +new file mode 100644 +index 0000000000..b9ed55d799 +--- /dev/null ++++ b/drivers/igloobase/osi_notifier.c +@@ -0,0 +1,55 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hypercall.h" ++#include ++#include ++#include ++#include ++#include /* Needed by all modules */ ++#include /* Needed for KERN_INFO */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "igloo.h" ++#include "igloobase.h" ++ ++#define IGLOO_HYP_OSI_TASK_SWITCH 0x3337 ++ ++// Define a tracepoint probe function for sched_switch with the correct signature ++static void probe_sched_switch(void *data, bool preempt, struct task_struct *prev, ++ struct task_struct *next, unsigned int prev_state) ++{ ++ // Notify hypervisor about task switch using task pointers ++ igloo_hypercall2(IGLOO_HYP_OSI_TASK_SWITCH, (unsigned long)prev, (unsigned long)next); ++} ++ ++int osi_notifier_init(void) { ++ int ret = 0; ++ ++ // Register the sched_switch tracepoint ++ ret = register_trace_sched_switch(probe_sched_switch, NULL); ++ if (ret) { ++ printk(KERN_ERR "IGLOO: Failed to register sched_switch tracepoint, returned %d\n", ret); ++ } else { ++ printk(KERN_INFO "IGLOO: Successfully registered sched_switch tracepoint\n"); ++ } ++ return 0; ++} +\ No newline at end of file +diff --git a/drivers/igloobase/syscalls_info_report.c b/drivers/igloobase/syscalls_info_report.c +new file mode 100644 +index 0000000000..9927c02e3e +--- /dev/null ++++ b/drivers/igloobase/syscalls_info_report.c +@@ -0,0 +1,281 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hypercall.h" // Content is now included directly below ++#include "igloo.h" ++#include "igloobase.h" ++#include "igloobasehypercalls.h" ++ ++extern struct syscall_metadata *__start_syscalls_metadata[]; ++extern struct syscall_metadata *__stop_syscalls_metadata[]; ++ ++#ifndef ARCH_HAS_SYSCALL_MATCH_SYM_NAME ++static inline bool arch_syscall_match_sym_name(const char *sym, const char *name) ++{ ++ /* ++ * Only compare after the "sys" prefix. Archs that use ++ * syscall wrappers may have syscalls symbols aliases prefixed ++ * with ".SyS" or ".sys" instead of "sys", leading to an unwanted ++ * mismatch. ++ */ ++ return !strcmp(sym + 3, name + 3); ++} ++#endif ++ ++/* Normalize syscall names by removing common prefixes like 'sys_', '_sys_', 'compat_sys_' */ ++static inline const char *normalize_syscall_name(const char *name) ++{ ++ if (!name) ++ return NULL; ++ ++ /* Skip leading underscores (e.g. _sys_) */ ++ while (*name == '_') ++ name++; ++ ++ /* Check for 'sys_' prefix */ ++ if (strncmp(name, "sys_", 4) == 0) ++ return name + 4; ++ ++ /* Check for 'compat_sys_' prefix */ ++ if (strncmp(name, "compat_sys_", 11) == 0) ++ return name + 11; ++ ++ /* Check for other arch-specific prefixes */ ++ if (strncmp(name, "arm64_sys_", 10) == 0) ++ return name + 10; ++ ++ if (strncmp(name, "riscv_sys_", 10) == 0) ++ return name + 10; ++ ++ return name; ++} ++ ++// copied from trace_syscalls.c ++static struct syscall_metadata * ++find_syscall_meta_copy(unsigned long syscall); ++static struct syscall_metadata * ++find_syscall_meta_copy(unsigned long syscall) ++{ ++ struct syscall_metadata **start; ++ struct syscall_metadata **stop; ++ char str[KSYM_SYMBOL_LEN]; ++ ++ ++ start = __start_syscalls_metadata; ++ stop = __stop_syscalls_metadata; ++ kallsyms_lookup(syscall, NULL, NULL, NULL, str); ++ ++ if (arch_syscall_match_sym_name(str, "sys_ni_syscall")) ++ return NULL; ++ ++ for ( ; start < stop; start++) { ++ if ((*start)->name && arch_syscall_match_sym_name(str, (*start)->name)) ++ return *start; ++ } ++ return NULL; ++} ++ ++static void report_syscall(char * buffer, struct syscall_metadata *meta){ ++ if (!meta || !meta->name) { ++ return; // Skip invalid metadata ++ } ++ // Prepare JSON metadata for hypercall (ensure buffer is large enough) ++ int x = snprintf(buffer, PAGE_SIZE, ++ "{\"name\": \"%s\", \"args\":[", ++ normalize_syscall_name(meta->name)); ++ ++ for (int j = 0; j < meta->nb_args && x > 0 && x < PAGE_SIZE; j++) { ++ // Append args safely, checking remaining buffer space ++ x += snprintf((char*)buffer + x, PAGE_SIZE - x, "[\"%s\", \"%s\"]%s", ++ meta->types[j] ? meta->types[j] : "?", // Handle potential NULL type/arg names ++ meta->args[j] ? meta->args[j] : "?", ++ j + 1 < meta->nb_args ? ", " : ""); ++ } ++ ++ if (x > 0 && x < PAGE_SIZE) { ++ x += snprintf((char*)buffer + x, PAGE_SIZE - x, "]}"); ++ } ++ ++ if (x <= 0 || x >= PAGE_SIZE) { ++ // DBG_PRINTK( "IGLOO: Failed to format JSON for syscall %s (nr %d) - buffer overflow or snprintf error.\n", meta->name, meta->syscall_nr); ++ // Decide how to handle: skip this probe or abort? Skipping for now. ++ return; ++ } ++ // Send metadata via hypercall (call returns value, but it's ignored here) ++ igloo_hypercall(IGLOO_HYP_SETUP_SYSCALL, (unsigned long)buffer); ++} ++ ++// normalize_syscall_name is now defined in syscalls_hc.h ++ ++#ifdef CONFIG_COMPAT ++/* For ARM64 */ ++#if defined(CONFIG_ARM64) ++extern const syscall_fn_t compat_sys_call_table[]; ++/* Don't redeclare sys_call_table as it's already in syscall.h with correct type */ ++#define COMPAT_TABLE_SIZE __NR_compat32_syscalls ++ ++/* For x86_64 */ ++// #elif defined(CONFIG_X86_64) ++// /* Use void* instead of syscall_fn_t for broader compatibility */ ++// extern const void * const ia32_sys_call_table[]; ++// #define compat_sys_call_table ia32_sys_call_table ++// #define COMPAT_TABLE_SIZE IA32_NR_syscalls ++ ++/* For MIPS64 */ ++#elif defined(CONFIG_MIPS) && defined(CONFIG_64BIT) ++/* Use the correct declaration that matches what's in syscall.h */ ++#include /* Ensure we get the right declaration */ ++#define compat_sys_call_table sys32_call_table ++#define COMPAT_TABLE_SIZE NR_syscalls /* Use NR_syscalls instead of __NR_syscalls */ ++ ++/* For PPC64 */ ++// #elif defined(CONFIG_PPC64) ++// extern void *sys32_call_table[]; ++// #define compat_sys_call_table sys32_call_table ++// #define COMPAT_TABLE_SIZE __NR_syscalls ++ ++/* For RISC-V64 */ ++#elif defined(CONFIG_RISCV) && defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) ++/* Use the correct declaration for RISC-V - it's already properly declared in syscall.h */ ++#define COMPAT_TABLE_SIZE __NR_syscalls ++#endif ++#endif ++ ++/* Get syscall name from a function pointer */ ++#ifdef CONFIG_COMPAT ++static const char *get_syscall_name_from_func(void *func_ptr) { ++ char sym[KSYM_SYMBOL_LEN]; ++ ++ if (!func_ptr || IS_ERR(func_ptr)) ++ return NULL; ++ ++ kallsyms_lookup((unsigned long)func_ptr, NULL, NULL, NULL, sym); ++ ++ /* Skip if we couldn't identify the symbol */ ++ if (!sym[0]) ++ return NULL; ++ ++ /* Skip the "sys_" or similar prefix */ ++ if (strncmp(sym, "sys_", 4) == 0) ++ return kstrdup(sym, GFP_KERNEL); ++ else if (strncmp(sym, "compat_sys_", 11) == 0) ++ return kstrdup(sym + 7, GFP_KERNEL); /* Return without the "compat_" prefix */ ++ else if (strncmp(sym, "__arm64_", 8) == 0) ++ return kstrdup(sym + 8, GFP_KERNEL); /* Return without the "__arm64_" prefix */ ++ else if (strncmp(sym, "__loongarch_", 12) == 0) ++ return kstrdup(sym + 12, GFP_KERNEL); /* Return without the "__loongarch_" prefix */ ++ else if (strncmp(sym, "__riscv_", 8) == 0) ++ return kstrdup(sym + 8, GFP_KERNEL); /* Return without the "__riscv_" prefix */ ++ else if (strncmp(sym, "__se_", 5) == 0) ++ return kstrdup(sym + 5, GFP_KERNEL); /* Return without the "__se_" prefix */ ++ ++ return kstrdup(sym, GFP_KERNEL); ++} ++ ++static void report_syscall_from_func(char *buffer, void *func_ptr, int syscall_nr) { ++ const char *name; ++ int x; ++ ++ if (!func_ptr || IS_ERR(func_ptr)) ++ return; ++ ++ name = get_syscall_name_from_func(func_ptr); ++ if (!name) ++ return; ++ ++ /* Create a simplified metadata report for compat syscalls */ ++ x = snprintf(buffer, PAGE_SIZE, "{\"name\": \"%s\", \"compat\": true, \"args\":\"unknown\"}", ++ normalize_syscall_name(name)); ++ ++ if (x > 0 && x < PAGE_SIZE) { ++ /* Send this metadata via hypercall */ ++ igloo_hypercall(IGLOO_HYP_SETUP_SYSCALL, (unsigned long)buffer); ++ } ++ ++ kfree(name); ++} ++#endif ++ ++int syscalls_info_report(void) { ++ printk(KERN_EMERG "IGLOO: Initializing syscall hypercalls\n"); ++ struct syscall_metadata **p = __start_syscalls_metadata; ++ struct syscall_metadata **end = __stop_syscalls_metadata; ++ ++ void *buffer = kzalloc(PAGE_SIZE, GFP_KERNEL); ++ ++ if (!buffer) { ++ printk(KERN_ERR "IGLOO: Failed to allocate memory for syscall metadata buffer\n"); ++ return -ENOMEM; ++ } ++ ++ // Count the number of syscalls ++ int num_syscall_probes = end - p; ++ if (num_syscall_probes <= 0) { ++ printk(KERN_WARNING "IGLOO: No syscall metadata found.\n"); ++ return -EINVAL; ++ } ++ ++ // Process regular syscalls first ++ int i; ++ for (i = 0; i < NR_syscalls+1000; i++) { ++ struct syscall_metadata *meta; ++ unsigned long addr; ++ addr = arch_syscall_addr(i); ++ meta = find_syscall_meta_copy(addr); ++ if (!meta) ++ continue; ++ meta->syscall_nr = i; ++ report_syscall(buffer, meta); ++ } ++ ++ for (p = __start_syscalls_metadata; p < end; p++) { ++ struct syscall_metadata *meta = *p; ++ if (!meta) { ++ continue; // Skip invalid metadata ++ } ++ report_syscall(buffer, meta); ++ } ++ ++ // Process compat syscalls ++#ifdef CONFIG_COMPAT ++#ifdef COMPAT_TABLE_SIZE ++ printk(KERN_INFO "IGLOO: Processing compat syscall table with %d entries\n", COMPAT_TABLE_SIZE); ++ ++ for (i = 0; i < COMPAT_TABLE_SIZE; i++) { ++#if defined(CONFIG_RISCV) && defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) ++ /* For RISC-V, use the already declared variable without casting */ ++ void *func_ptr = compat_sys_call_table[i]; ++#elif defined(CONFIG_MIPS) && defined(CONFIG_64BIT) ++ /* For MIPS64, handle the unsigned long array correctly */ ++ void *func_ptr = (void *)(unsigned long)compat_sys_call_table[i]; ++#else ++ /* For other architectures, use proper casting based on architecture pointer size */ ++ void *func_ptr = (void *)(uintptr_t)compat_sys_call_table[i]; ++#endif ++ ++ /* Skip non-existent syscalls (usually NULL) */ ++ if (!func_ptr || IS_ERR(func_ptr)) { ++ continue; ++ } ++ ++ report_syscall_from_func(buffer, func_ptr, i); ++ } ++#else ++ printk(KERN_INFO "IGLOO: No compat syscall table found for this architecture\n"); ++#endif ++#endif ++ ++ kfree(buffer); ++ return 0; ++} +\ No newline at end of file diff --git a/patches/6.13/0015-exec.c-add-igloo_task_size.patch b/patches/6.13/0015-exec.c-add-igloo_task_size.patch new file mode 100644 index 0000000..31511ca --- /dev/null +++ b/patches/6.13/0015-exec.c-add-igloo_task_size.patch @@ -0,0 +1,32 @@ +From ca6ce59643e2995add53445a7f05ee8ee117b017 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:15:02 -0400 +Subject: [PATCH 15/37] exec.c: add igloo_task_size + +--- + fs/exec.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/exec.c b/fs/exec.c +index 98cb7ba998..db46361140 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -72,6 +72,7 @@ + #include + #include + #include ++#include + + #include + #include "internal.h" +@@ -1432,6 +1433,10 @@ void setup_new_exec(struct linux_binprm * bprm) + * some architectures like powerpc + */ + me->mm->task_size = TASK_SIZE; ++ #ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ current->mm->task_size = igloo_task_size; ++ #endif + up_write(&me->signal->exec_update_lock); + mutex_unlock(&me->signal->cred_guard_mutex); + } diff --git a/patches/6.13/0016-mmap.c-add-igloo_task_size.patch b/patches/6.13/0016-mmap.c-add-igloo_task_size.patch new file mode 100644 index 0000000..6698701 --- /dev/null +++ b/patches/6.13/0016-mmap.c-add-igloo_task_size.patch @@ -0,0 +1,36 @@ +From 6d3cbdd1be758a91954340c66f6f3647bf23f9be Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:16:06 -0400 +Subject: [PATCH 16/37] mmap.c: add igloo_task_size + +--- + arch/x86/mm/mmap.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index b8a6ffffb4..d8a767a046 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include "physaddr.h" + +@@ -102,7 +103,13 @@ static unsigned long mmap_base(unsigned long rnd, unsigned long task_size, + else if (gap > gap_max) + gap = gap_max; + +- return PAGE_ALIGN(task_size - gap - rnd); ++ #ifdef CONFIG_IGLOO ++ if(igloo_task_size) { ++ return PAGE_ALIGN(igloo_task_size - gap - rnd); ++ } else { ++ return PAGE_ALIGN(TASK_SIZE - gap - rnd); ++ } ++ #endif + } + + static unsigned long mmap_legacy_base(unsigned long rnd, diff --git a/patches/6.13/0017-util.c-add-igloo_task_size.patch b/patches/6.13/0017-util.c-add-igloo_task_size.patch new file mode 100644 index 0000000..852348d --- /dev/null +++ b/patches/6.13/0017-util.c-add-igloo_task_size.patch @@ -0,0 +1,36 @@ +From 55f001f78b3a7febc729457685856a4b168ab626 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:16:19 -0400 +Subject: [PATCH 17/37] util.c: add igloo_task_size + +--- + mm/util.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/mm/util.c b/mm/util.c +index 60aa40f612..f5d5f5dac3 100644 +--- a/mm/util.c ++++ b/mm/util.c +@@ -25,6 +25,7 @@ + #include + + #include ++#include + + #include + +@@ -437,7 +438,13 @@ static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) + * task. mmap_base starts directly below the stack and grows + * downwards. + */ +- return PAGE_ALIGN_DOWN(mmap_upper_limit(rlim_stack) - rnd); ++ #ifdef CONFIG_IGLOO ++ if(igloo_task_size) { ++ return PAGE_ALIGN_DOWN(igloo_task_size - rnd); ++ } else { ++ return PAGE_ALIGN_DOWN(mmap_upper_limit(rlim_stack) - rnd); ++ } ++ #endif + #else + unsigned long gap = rlim_stack->rlim_cur; + unsigned long pad = stack_guard_gap; diff --git a/patches/6.13/0019-add-syscalls.h.patch b/patches/6.13/0019-add-syscalls.h.patch new file mode 100644 index 0000000..58a0ec2 --- /dev/null +++ b/patches/6.13/0019-add-syscalls.h.patch @@ -0,0 +1,2729 @@ +From cda5584e72c3325d41ba492b58672968e896c7ad Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:22:08 -0400 +Subject: [PATCH 19/37] add syscalls.h + +--- + include/linux/syscalls.h | 2701 ++++++++++++++++++++------------------ + 1 file changed, 1400 insertions(+), 1301 deletions(-) + +diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h +index c6333204d4..71394c3e30 100644 +--- a/include/linux/syscalls.h ++++ b/include/linux/syscalls.h +@@ -6,1314 +6,1413 @@ + * Copyright (c) 2004 Open Source Development Labs + */ + +-#ifndef _LINUX_SYSCALLS_H +-#define _LINUX_SYSCALLS_H +- +-struct __aio_sigset; +-struct epoll_event; +-struct iattr; +-struct inode; +-struct iocb; +-struct io_event; +-struct iovec; +-struct __kernel_old_itimerval; +-struct kexec_segment; +-struct linux_dirent; +-struct linux_dirent64; +-struct list_head; +-struct mmap_arg_struct; +-struct msgbuf; +-struct user_msghdr; +-struct mmsghdr; +-struct msqid_ds; +-struct new_utsname; +-struct nfsctl_arg; +-struct __old_kernel_stat; +-struct oldold_utsname; +-struct old_utsname; +-struct pollfd; +-struct rlimit; +-struct rlimit64; +-struct rusage; +-struct sched_param; +-struct sched_attr; +-struct sel_arg_struct; +-struct semaphore; +-struct sembuf; +-struct shmid_ds; +-struct sockaddr; +-struct stat; +-struct stat64; +-struct statfs; +-struct statfs64; +-struct statx; +-struct sysinfo; +-struct timespec; +-struct __kernel_old_timeval; +-struct __kernel_timex; +-struct timezone; +-struct tms; +-struct utimbuf; +-struct mq_attr; +-struct compat_stat; +-struct old_timeval32; +-struct robust_list_head; +-struct futex_waitv; +-struct getcpu_cache; +-struct old_linux_dirent; +-struct perf_event_attr; +-struct file_handle; +-struct sigaltstack; +-struct rseq; +-union bpf_attr; +-struct io_uring_params; +-struct clone_args; +-struct open_how; +-struct mount_attr; +-struct landlock_ruleset_attr; +-struct lsm_ctx; +-enum landlock_rule_type; +-struct cachestat_range; +-struct cachestat; +-struct statmount; +-struct mnt_id_req; +-struct xattr_args; +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER +-/* +- * It may be useful for an architecture to override the definitions of the +- * SYSCALL_DEFINE0() and __SYSCALL_DEFINEx() macros, in particular to use a +- * different calling convention for syscalls. To allow for that, the prototypes +- * for the sys_*() functions below will *not* be included if +- * CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled. +- */ +-#include +-#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ +- +-/* +- * __MAP - apply a macro to syscall arguments +- * __MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to +- * m(t1, a1), m(t2, a2), ..., m(tn, an) +- * The first argument must be equal to the amount of type/name +- * pairs given. Note that this list of pairs (i.e. the arguments +- * of __MAP starting at the third one) is in the same format as +- * for SYSCALL_DEFINE/COMPAT_SYSCALL_DEFINE +- */ +-#define __MAP0(m,...) +-#define __MAP1(m,t,a,...) m(t,a) +-#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__) +-#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__) +-#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__) +-#define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__) +-#define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__) +-#define __MAP(n,...) __MAP##n(__VA_ARGS__) +- +-#define __SC_DECL(t, a) t a +-#define __TYPE_AS(t, v) __same_type((__force t)0, v) +-#define __TYPE_IS_L(t) (__TYPE_AS(t, 0L)) +-#define __TYPE_IS_UL(t) (__TYPE_AS(t, 0UL)) +-#define __TYPE_IS_LL(t) (__TYPE_AS(t, 0LL) || __TYPE_AS(t, 0ULL)) +-#define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a +-#define __SC_CAST(t, a) (__force t) a +-#define __SC_TYPE(t, a) t +-#define __SC_ARGS(t, a) a +-#define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long)) +- +-#ifdef CONFIG_FTRACE_SYSCALLS +-#define __SC_STR_ADECL(t, a) #a +-#define __SC_STR_TDECL(t, a) #t +- +-extern struct trace_event_class event_class_syscall_enter; +-extern struct trace_event_class event_class_syscall_exit; +-extern struct trace_event_functions enter_syscall_print_funcs; +-extern struct trace_event_functions exit_syscall_print_funcs; +- +-#define SYSCALL_TRACE_ENTER_EVENT(sname) \ +- static struct syscall_metadata __syscall_meta_##sname; \ +- static struct trace_event_call __used \ +- event_enter_##sname = { \ +- .class = &event_class_syscall_enter, \ +- { \ +- .name = "sys_enter"#sname, \ +- }, \ +- .event.funcs = &enter_syscall_print_funcs, \ +- .data = (void *)&__syscall_meta_##sname,\ +- .flags = TRACE_EVENT_FL_CAP_ANY, \ +- }; \ +- static struct trace_event_call __used \ +- __section("_ftrace_events") \ +- *__event_enter_##sname = &event_enter_##sname; +- +-#define SYSCALL_TRACE_EXIT_EVENT(sname) \ +- static struct syscall_metadata __syscall_meta_##sname; \ +- static struct trace_event_call __used \ +- event_exit_##sname = { \ +- .class = &event_class_syscall_exit, \ +- { \ +- .name = "sys_exit"#sname, \ +- }, \ +- .event.funcs = &exit_syscall_print_funcs, \ +- .data = (void *)&__syscall_meta_##sname,\ +- .flags = TRACE_EVENT_FL_CAP_ANY, \ +- }; \ +- static struct trace_event_call __used \ +- __section("_ftrace_events") \ +- *__event_exit_##sname = &event_exit_##sname; +- +-#define SYSCALL_METADATA(sname, nb, ...) \ +- static const char *types_##sname[] = { \ +- __MAP(nb,__SC_STR_TDECL,__VA_ARGS__) \ +- }; \ +- static const char *args_##sname[] = { \ +- __MAP(nb,__SC_STR_ADECL,__VA_ARGS__) \ +- }; \ +- SYSCALL_TRACE_ENTER_EVENT(sname); \ +- SYSCALL_TRACE_EXIT_EVENT(sname); \ +- static struct syscall_metadata __used \ +- __syscall_meta_##sname = { \ +- .name = "sys"#sname, \ +- .syscall_nr = -1, /* Filled in at boot */ \ +- .nb_args = nb, \ +- .types = nb ? types_##sname : NULL, \ +- .args = nb ? args_##sname : NULL, \ +- .enter_event = &event_enter_##sname, \ +- .exit_event = &event_exit_##sname, \ +- .enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \ +- }; \ +- static struct syscall_metadata __used \ +- __section("__syscalls_metadata") \ +- *__p_syscall_meta_##sname = &__syscall_meta_##sname; +- +-static inline int is_syscall_trace_event(struct trace_event_call *tp_event) +-{ +- return tp_event->class == &event_class_syscall_enter || +- tp_event->class == &event_class_syscall_exit; +-} +- +-#else +-#define SYSCALL_METADATA(sname, nb, ...) +- +-static inline int is_syscall_trace_event(struct trace_event_call *tp_event) +-{ +- return 0; +-} +-#endif +- +-#ifndef SYSCALL_DEFINE0 +-#define SYSCALL_DEFINE0(sname) \ +- SYSCALL_METADATA(_##sname, 0); \ +- asmlinkage long sys_##sname(void); \ +- ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \ +- asmlinkage long sys_##sname(void) +-#endif /* SYSCALL_DEFINE0 */ +- +-#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) +-#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) +-#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) +-#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__) +-#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__) +-#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) +- +-#define SYSCALL_DEFINE_MAXARGS 6 +- +-#define SYSCALL_DEFINEx(x, sname, ...) \ +- SYSCALL_METADATA(sname, x, __VA_ARGS__) \ +- __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) +- ++ #ifndef _LINUX_SYSCALLS_H ++ #define _LINUX_SYSCALLS_H ++ ++ struct __aio_sigset; ++ struct epoll_event; ++ struct iattr; ++ struct inode; ++ struct iocb; ++ struct io_event; ++ struct iovec; ++ struct __kernel_old_itimerval; ++ struct kexec_segment; ++ struct linux_dirent; ++ struct linux_dirent64; ++ struct list_head; ++ struct mmap_arg_struct; ++ struct msgbuf; ++ struct user_msghdr; ++ struct mmsghdr; ++ struct msqid_ds; ++ struct new_utsname; ++ struct nfsctl_arg; ++ struct __old_kernel_stat; ++ struct oldold_utsname; ++ struct old_utsname; ++ struct pollfd; ++ struct rlimit; ++ struct rlimit64; ++ struct rusage; ++ struct sched_param; ++ struct sched_attr; ++ struct sel_arg_struct; ++ struct semaphore; ++ struct sembuf; ++ struct shmid_ds; ++ struct sockaddr; ++ struct stat; ++ struct stat64; ++ struct statfs; ++ struct statfs64; ++ struct statx; ++ struct sysinfo; ++ struct timespec; ++ struct __kernel_old_timeval; ++ struct __kernel_timex; ++ struct timezone; ++ struct tms; ++ struct utimbuf; ++ struct mq_attr; ++ struct compat_stat; ++ struct old_timeval32; ++ struct robust_list_head; ++ struct futex_waitv; ++ struct getcpu_cache; ++ struct old_linux_dirent; ++ struct perf_event_attr; ++ struct file_handle; ++ struct sigaltstack; ++ struct rseq; ++ union bpf_attr; ++ struct io_uring_params; ++ struct clone_args; ++ struct open_how; ++ struct mount_attr; ++ struct landlock_ruleset_attr; ++ struct lsm_ctx; ++ enum landlock_rule_type; ++ struct cachestat_range; ++ struct cachestat; ++ struct statmount; ++ struct mnt_id_req; ++ struct xattr_args; ++ ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ ++ #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER ++ /* ++ * It may be useful for an architecture to override the definitions of the ++ * SYSCALL_DEFINE0() and __SYSCALL_DEFINEx() macros, in particular to use a ++ * different calling convention for syscalls. To allow for that, the prototypes ++ * for the sys_*() functions below will *not* be included if ++ * CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled. ++ */ ++ #include ++ #endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ ++ ++ /* ++ * __MAP - apply a macro to syscall arguments ++ * __MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to ++ * m(t1, a1), m(t2, a2), ..., m(tn, an) ++ * The first argument must be equal to the amount of type/name ++ * pairs given. Note that this list of pairs (i.e. the arguments ++ * of __MAP starting at the third one) is in the same format as ++ * for SYSCALL_DEFINE/COMPAT_SYSCALL_DEFINE ++ */ ++ #define __MAP0(m,...) ++ #define __MAP1(m,t,a,...) m(t,a) ++ #define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__) ++ #define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__) ++ #define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__) ++ #define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__) ++ #define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__) ++ #define __MAP(n,...) __MAP##n(__VA_ARGS__) ++ ++ #define __SC_DECL(t, a) t a ++ #define __TYPE_AS(t, v) __same_type((__force t)0, v) ++ #define __TYPE_IS_L(t) (__TYPE_AS(t, 0L)) ++ #define __TYPE_IS_UL(t) (__TYPE_AS(t, 0UL)) ++ #define __TYPE_IS_LL(t) (__TYPE_AS(t, 0LL) || __TYPE_AS(t, 0ULL)) ++ #define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a ++ #define __SC_CAST(t, a) (__force t) a ++ #define __SC_TYPE(t, a) t ++ #define __SC_ARGS(t, a) a ++ #define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long)) ++ ++ #ifdef CONFIG_FTRACE_SYSCALLS ++ #define __SC_STR_ADECL(t, a) #a ++ #define __SC_STR_TDECL(t, a) #t ++ ++ extern struct trace_event_class event_class_syscall_enter; ++ extern struct trace_event_class event_class_syscall_exit; ++ extern struct trace_event_functions enter_syscall_print_funcs; ++ extern struct trace_event_functions exit_syscall_print_funcs; ++ ++ #define SYSCALL_TRACE_ENTER_EVENT(sname) \ ++ static struct syscall_metadata __syscall_meta_##sname; \ ++ static struct trace_event_call __used \ ++ event_enter_##sname = { \ ++ .class = &event_class_syscall_enter, \ ++ { \ ++ .name = "sys_enter"#sname, \ ++ }, \ ++ .event.funcs = &enter_syscall_print_funcs, \ ++ .data = (void *)&__syscall_meta_##sname,\ ++ .flags = TRACE_EVENT_FL_CAP_ANY, \ ++ }; \ ++ static struct trace_event_call __used \ ++ __section("_ftrace_events") \ ++ *__event_enter_##sname = &event_enter_##sname; ++ ++ #define SYSCALL_TRACE_EXIT_EVENT(sname) \ ++ static struct syscall_metadata __syscall_meta_##sname; \ ++ static struct trace_event_call __used \ ++ event_exit_##sname = { \ ++ .class = &event_class_syscall_exit, \ ++ { \ ++ .name = "sys_exit"#sname, \ ++ }, \ ++ .event.funcs = &exit_syscall_print_funcs, \ ++ .data = (void *)&__syscall_meta_##sname,\ ++ .flags = TRACE_EVENT_FL_CAP_ANY, \ ++ }; \ ++ static struct trace_event_call __used \ ++ __section("_ftrace_events") \ ++ *__event_exit_##sname = &event_exit_##sname; ++ ++ #define SYSCALL_METADATA(sname, nb, ...) \ ++ static const char *types_##sname[] = { \ ++ __MAP(nb,__SC_STR_TDECL,__VA_ARGS__) \ ++ }; \ ++ static const char *args_##sname[] = { \ ++ __MAP(nb,__SC_STR_ADECL,__VA_ARGS__) \ ++ }; \ ++ SYSCALL_TRACE_ENTER_EVENT(sname); \ ++ SYSCALL_TRACE_EXIT_EVENT(sname); \ ++ static struct syscall_metadata __used \ ++ __syscall_meta_##sname = { \ ++ .name = "sys"#sname, \ ++ .syscall_nr = -1, /* Filled in at boot */ \ ++ .nb_args = nb, \ ++ .types = nb ? types_##sname : NULL, \ ++ .args = nb ? args_##sname : NULL, \ ++ .enter_event = &event_enter_##sname, \ ++ .exit_event = &event_exit_##sname, \ ++ .enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \ ++ }; \ ++ static struct syscall_metadata __used \ ++ __section("__syscalls_metadata") \ ++ *__p_syscall_meta_##sname = &__syscall_meta_##sname; ++ ++ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) ++ { ++ return tp_event->class == &event_class_syscall_enter || ++ tp_event->class == &event_class_syscall_exit; ++ } ++ ++ #else ++ #define SYSCALL_METADATA(sname, nb, ...) ++ ++ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) ++ { ++ return 0; ++ } ++ #endif ++ ++#ifdef CONFIG_IGLOO ++#include ++/* === Igloo Interception Hooks and Helpers === */ ++ ++/* Pointers to the actual hook functions */ ++extern igloo_syscall_enter_t igloo_syscall_enter_hook; ++extern igloo_syscall_return_t igloo_syscall_return_hook; ++#else /* CONFIG_IGLOO not defined */ ++ ++/* Define stubs or original macros if Igloo is disabled */ ++#define igloo_syscall_enter_hook NULL ++#define igloo_syscall_return_hook NULL ++#endif /* CONFIG_IGLOO */ ++ ++ ++/* --- Definition for __PROTECT --- */ ++#ifndef __PROTECT + #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) +- +-/* +- * The asmlinkage stub is aliased to a function named __se_sys_*() which +- * sign-extends 32-bit ints to longs whenever needed. The actual work is +- * done within __do_sys_*(). +- */ +-#ifndef __SYSCALL_DEFINEx +-#define __SYSCALL_DEFINEx(x, name, ...) \ +- __diag_push(); \ +- __diag_ignore(GCC, 8, "-Wattribute-alias", \ +- "Type aliasing is used to sanitize syscall arguments");\ +- asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ +- __attribute__((alias(__stringify(__se_sys##name)))); \ +- ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ +- static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ +- asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ +- asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ ++#endif /* __PROTECT */ ++ #ifndef SYSCALL_DEFINE0 ++ #define SYSCALL_DEFINE0(name) \ ++ SYSCALL_METADATA(_##name, 0); \ ++ asmlinkage long sys_##name(void); \ ++ ALLOW_ERROR_INJECTION(sys_##name, ERRNO); \ ++ static inline long __do_sys_##name(void); /* Declare impl */ \ ++ asmlinkage long sys_##name(void) \ + { \ +- long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\ +- __MAP(x,__SC_TEST,__VA_ARGS__); \ +- __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ ++ const char *syscall_basename = __stringify(name); /* Base name */ \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ /* Array for arguments (empty for 0 args) */ \ ++ unsigned long args_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ \ ++ /* === Igloo Enter Hook === */ \ ++ if (igloo_syscall_enter_hook) { \ ++ /* Pass NULL for setter func for 0-arg syscalls */ \ ++ skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, 0, args_array, NULL); \ ++ } \ ++ \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_sys_##name(); \ ++ } \ ++ \ ++ /* === Igloo Return Hook === */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(syscall_basename, ret, 0, args_array); \ ++ } \ ++ \ ++ /* Argument protection and final return */ \ ++ __PROTECT(0, ret); /* Protect for 0 args */ \ + return ret; \ + } \ +- __diag_pop(); \ +- static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) +-#endif /* __SYSCALL_DEFINEx */ +- +-/* For split 64-bit arguments on 32-bit architectures */ +-#ifdef __LITTLE_ENDIAN +-#define SC_ARG64(name) u32, name##_lo, u32, name##_hi +-#else +-#define SC_ARG64(name) u32, name##_hi, u32, name##_lo +-#endif +-#define SC_VAL64(type, name) ((type) name##_hi << 32 | name##_lo) +- +-#ifdef CONFIG_COMPAT +-#define SYSCALL32_DEFINE0 COMPAT_SYSCALL_DEFINE0 +-#define SYSCALL32_DEFINE1 COMPAT_SYSCALL_DEFINE1 +-#define SYSCALL32_DEFINE2 COMPAT_SYSCALL_DEFINE2 +-#define SYSCALL32_DEFINE3 COMPAT_SYSCALL_DEFINE3 +-#define SYSCALL32_DEFINE4 COMPAT_SYSCALL_DEFINE4 +-#define SYSCALL32_DEFINE5 COMPAT_SYSCALL_DEFINE5 +-#define SYSCALL32_DEFINE6 COMPAT_SYSCALL_DEFINE6 +-#else +-#define SYSCALL32_DEFINE0 SYSCALL_DEFINE0 +-#define SYSCALL32_DEFINE1 SYSCALL_DEFINE1 +-#define SYSCALL32_DEFINE2 SYSCALL_DEFINE2 +-#define SYSCALL32_DEFINE3 SYSCALL_DEFINE3 +-#define SYSCALL32_DEFINE4 SYSCALL_DEFINE4 +-#define SYSCALL32_DEFINE5 SYSCALL_DEFINE5 +-#define SYSCALL32_DEFINE6 SYSCALL_DEFINE6 +-#endif +- +-/* +- * These syscall function prototypes are kept in the same order as +- * include/uapi/asm-generic/unistd.h. Architecture specific entries go below, +- * followed by deprecated or obsolete system calls. +- * +- * Please note that these prototypes here are only provided for information +- * purposes, for static analysis, and for linking from the syscall table. +- * These functions should not be called elsewhere from kernel code. +- * +- * As the syscall calling convention may be different from the default +- * for architectures overriding the syscall calling convention, do not +- * include the prototypes if CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled. +- */ +-#ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER +-asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t __user *ctx); +-asmlinkage long sys_io_destroy(aio_context_t ctx); +-asmlinkage long sys_io_submit(aio_context_t, long, +- struct iocb __user * __user *); +-asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, +- struct io_event __user *result); +-asmlinkage long sys_io_getevents(aio_context_t ctx_id, +- long min_nr, +- long nr, +- struct io_event __user *events, +- struct __kernel_timespec __user *timeout); +-asmlinkage long sys_io_getevents_time32(__u32 ctx_id, +- __s32 min_nr, +- __s32 nr, +- struct io_event __user *events, +- struct old_timespec32 __user *timeout); +-asmlinkage long sys_io_pgetevents(aio_context_t ctx_id, +- long min_nr, +- long nr, +- struct io_event __user *events, +- struct __kernel_timespec __user *timeout, +- const struct __aio_sigset __user *sig); +-asmlinkage long sys_io_pgetevents_time32(aio_context_t ctx_id, +- long min_nr, +- long nr, +- struct io_event __user *events, +- struct old_timespec32 __user *timeout, +- const struct __aio_sigset __user *sig); +-asmlinkage long sys_io_uring_setup(u32 entries, +- struct io_uring_params __user *p); +-asmlinkage long sys_io_uring_enter(unsigned int fd, u32 to_submit, +- u32 min_complete, u32 flags, +- const void __user *argp, size_t argsz); +-asmlinkage long sys_io_uring_register(unsigned int fd, unsigned int op, +- void __user *arg, unsigned int nr_args); +-asmlinkage long sys_setxattr(const char __user *path, const char __user *name, +- const void __user *value, size_t size, int flags); +-asmlinkage long sys_setxattrat(int dfd, const char __user *path, unsigned int at_flags, +- const char __user *name, +- const struct xattr_args __user *args, size_t size); +-asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name, +- const void __user *value, size_t size, int flags); +-asmlinkage long sys_fsetxattr(int fd, const char __user *name, +- const void __user *value, size_t size, int flags); +-asmlinkage long sys_getxattr(const char __user *path, const char __user *name, +- void __user *value, size_t size); +-asmlinkage long sys_getxattrat(int dfd, const char __user *path, unsigned int at_flags, +- const char __user *name, +- struct xattr_args __user *args, size_t size); +-asmlinkage long sys_lgetxattr(const char __user *path, const char __user *name, +- void __user *value, size_t size); +-asmlinkage long sys_fgetxattr(int fd, const char __user *name, +- void __user *value, size_t size); +-asmlinkage long sys_listxattr(const char __user *path, char __user *list, +- size_t size); +-asmlinkage long sys_listxattrat(int dfd, const char __user *path, +- unsigned int at_flags, +- char __user *list, size_t size); +-asmlinkage long sys_llistxattr(const char __user *path, char __user *list, +- size_t size); +-asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size); +-asmlinkage long sys_removexattr(const char __user *path, +- const char __user *name); +-asmlinkage long sys_removexattrat(int dfd, const char __user *path, +- unsigned int at_flags, +- const char __user *name); +-asmlinkage long sys_lremovexattr(const char __user *path, ++ /* User's syscall code defines the __do_sys_##name function */ \ ++ static inline long __do_sys_##name(void) ++ #endif /* SYSCALL_DEFINE0 */ ++ ++ ++/* --- Modified SYSCALL_DEFINE1..6 & SYSCALL_DEFINEx --- */ ++/* Pass base name AND internal (_name) to SYSCALL_DEFINEx */ ++ #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) ++ #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) ++ #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) ++ #define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__) ++ #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__) ++ #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) ++ ++ #define SYSCALL_DEFINE_MAXARGS 6 ++ #define SYSCALL_DEFINEx(x, name, ...) \ ++ SYSCALL_METADATA(name, x, __VA_ARGS__) \ ++ __SYSCALL_DEFINEx(x, name, __VA_ARGS__) ++ ++ ++/* --- Modified __SYSCALL_DEFINEx --- */ ++/* Note: Added 'name' (base name) parameter */ ++ ++ /* ++ * The asmlinkage stub is aliased to a function named __se_sys_*() which ++ * sign-extends 32-bit ints to longs whenever needed. The actual work is ++ * done within __do_sys_*(). ++ */ ++ #ifndef __SYSCALL_DEFINEx ++ #define __SYSCALL_DEFINEx(x, name, ...) \ ++ __diag_push(); \ ++ __diag_ignore(GCC, 8, "-Wattribute-alias", \ ++ "Type aliasing is used to sanitize syscall arguments");\ ++ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ ++ __attribute__((alias(__stringify(__se_sys##name)))); \ ++ ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ ++ /* Implementation function declaration */ \ ++ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ ++ /* Setter function definition: Body generated using __SC_GEN_SETTER_BODY_WRAPPER */ \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { \ ++ __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); \ ++ } \ ++ /* Sign-extended wrapper function definition */ \ ++ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ ++ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ ++ { \ ++ const char *syscall_basename = __stringify(name); /* Base name */ \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ /* Declare ONE array for argument pointers */ \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ \ ++ /* Populate args_ptr_array with ADDRESSES for the enter hook */ \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ \ ++ /* === Igloo Enter Hook === */ \ ++ if (igloo_syscall_enter_hook) { \ ++ /* Pass setter function pointer unconditionally (except for 0 args) */ \ ++ /* The hook is responsible for handling const args correctly. */ \ ++ skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, x, \ ++ args_ptr_array, __igloo_set_args##name); \ ++ } \ ++ \ ++ if (skip) { \ ++ /* Syscall skipped by hook */ \ ++ ret = skip_ret; \ ++ } else { \ ++ /* Execute actual syscall implementation */ \ ++ /* Arguments used here are potentially modified */ \ ++ /* by the enter hook via the setter function */ \ ++ ret = __do_sys##name(__MAP(x, __SC_CAST, __VA_ARGS__));\ ++ } \ ++ \ ++ /* Original type tests */ \ ++ __MAP(x,__SC_TEST,__VA_ARGS__); \ ++ \ ++ /* === Igloo Return Hook === */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(syscall_basename, ret, x, \ ++ args_ptr_array); \ ++ } \ ++ \ ++ /* Argument protection and final return */ \ ++ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ ++ return ret; \ ++ } \ ++ __diag_pop(); \ ++ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) ++ #endif /* __SYSCALL_DEFINEx */ ++ ++ /* For split 64-bit arguments on 32-bit architectures */ ++ #ifdef __LITTLE_ENDIAN ++ #define SC_ARG64(name) u32, name##_lo, u32, name##_hi ++ #else ++ #define SC_ARG64(name) u32, name##_hi, u32, name##_lo ++ #endif ++ #define SC_VAL64(type, name) ((type) name##_hi << 32 | name##_lo) ++ ++ #ifdef CONFIG_COMPAT ++ #define SYSCALL32_DEFINE0 COMPAT_SYSCALL_DEFINE0 ++ #define SYSCALL32_DEFINE1 COMPAT_SYSCALL_DEFINE1 ++ #define SYSCALL32_DEFINE2 COMPAT_SYSCALL_DEFINE2 ++ #define SYSCALL32_DEFINE3 COMPAT_SYSCALL_DEFINE3 ++ #define SYSCALL32_DEFINE4 COMPAT_SYSCALL_DEFINE4 ++ #define SYSCALL32_DEFINE5 COMPAT_SYSCALL_DEFINE5 ++ #define SYSCALL32_DEFINE6 COMPAT_SYSCALL_DEFINE6 ++ #else ++ #define SYSCALL32_DEFINE0 SYSCALL_DEFINE0 ++ #define SYSCALL32_DEFINE1 SYSCALL_DEFINE1 ++ #define SYSCALL32_DEFINE2 SYSCALL_DEFINE2 ++ #define SYSCALL32_DEFINE3 SYSCALL_DEFINE3 ++ #define SYSCALL32_DEFINE4 SYSCALL_DEFINE4 ++ #define SYSCALL32_DEFINE5 SYSCALL_DEFINE5 ++ #define SYSCALL32_DEFINE6 SYSCALL_DEFINE6 ++ #endif ++ ++ /* ++ * These syscall function prototypes are kept in the same order as ++ * include/uapi/asm-generic/unistd.h. Architecture specific entries go below, ++ * followed by deprecated or obsolete system calls. ++ * ++ * Please note that these prototypes here are only provided for information ++ * purposes, for static analysis, and for linking from the syscall table. ++ * These functions should not be called elsewhere from kernel code. ++ * ++ * As the syscall calling convention may be different from the default ++ * for architectures overriding the syscall calling convention, do not ++ * include the prototypes if CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled. ++ */ ++ #ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER ++ asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t __user *ctx); ++ asmlinkage long sys_io_destroy(aio_context_t ctx); ++ asmlinkage long sys_io_submit(aio_context_t, long, ++ struct iocb __user * __user *); ++ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, ++ struct io_event __user *result); ++ asmlinkage long sys_io_getevents(aio_context_t ctx_id, ++ long min_nr, ++ long nr, ++ struct io_event __user *events, ++ struct __kernel_timespec __user *timeout); ++ asmlinkage long sys_io_getevents_time32(__u32 ctx_id, ++ __s32 min_nr, ++ __s32 nr, ++ struct io_event __user *events, ++ struct old_timespec32 __user *timeout); ++ asmlinkage long sys_io_pgetevents(aio_context_t ctx_id, ++ long min_nr, ++ long nr, ++ struct io_event __user *events, ++ struct __kernel_timespec __user *timeout, ++ const struct __aio_sigset __user *sig); ++ asmlinkage long sys_io_pgetevents_time32(aio_context_t ctx_id, ++ long min_nr, ++ long nr, ++ struct io_event __user *events, ++ struct old_timespec32 __user *timeout, ++ const struct __aio_sigset __user *sig); ++ asmlinkage long sys_io_uring_setup(u32 entries, ++ struct io_uring_params __user *p); ++ asmlinkage long sys_io_uring_enter(unsigned int fd, u32 to_submit, ++ u32 min_complete, u32 flags, ++ const void __user *argp, size_t argsz); ++ asmlinkage long sys_io_uring_register(unsigned int fd, unsigned int op, ++ void __user *arg, unsigned int nr_args); ++ asmlinkage long sys_setxattr(const char __user *path, const char __user *name, ++ const void __user *value, size_t size, int flags); ++ asmlinkage long sys_setxattrat(int dfd, const char __user *path, unsigned int at_flags, ++ const char __user *name, ++ const struct xattr_args __user *args, size_t size); ++ asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name, ++ const void __user *value, size_t size, int flags); ++ asmlinkage long sys_fsetxattr(int fd, const char __user *name, ++ const void __user *value, size_t size, int flags); ++ asmlinkage long sys_getxattr(const char __user *path, const char __user *name, ++ void __user *value, size_t size); ++ asmlinkage long sys_getxattrat(int dfd, const char __user *path, unsigned int at_flags, ++ const char __user *name, ++ struct xattr_args __user *args, size_t size); ++ asmlinkage long sys_lgetxattr(const char __user *path, const char __user *name, ++ void __user *value, size_t size); ++ asmlinkage long sys_fgetxattr(int fd, const char __user *name, ++ void __user *value, size_t size); ++ asmlinkage long sys_listxattr(const char __user *path, char __user *list, ++ size_t size); ++ asmlinkage long sys_listxattrat(int dfd, const char __user *path, ++ unsigned int at_flags, ++ char __user *list, size_t size); ++ asmlinkage long sys_llistxattr(const char __user *path, char __user *list, ++ size_t size); ++ asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size); ++ asmlinkage long sys_removexattr(const char __user *path, + const char __user *name); +-asmlinkage long sys_fremovexattr(int fd, const char __user *name); +-asmlinkage long sys_getcwd(char __user *buf, unsigned long size); +-asmlinkage long sys_eventfd2(unsigned int count, int flags); +-asmlinkage long sys_epoll_create1(int flags); +-asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, +- struct epoll_event __user *event); +-asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, +- int maxevents, int timeout, +- const sigset_t __user *sigmask, +- size_t sigsetsize); +-asmlinkage long sys_epoll_pwait2(int epfd, struct epoll_event __user *events, +- int maxevents, +- const struct __kernel_timespec __user *timeout, ++ asmlinkage long sys_removexattrat(int dfd, const char __user *path, ++ unsigned int at_flags, ++ const char __user *name); ++ asmlinkage long sys_lremovexattr(const char __user *path, ++ const char __user *name); ++ asmlinkage long sys_fremovexattr(int fd, const char __user *name); ++ asmlinkage long sys_getcwd(char __user *buf, unsigned long size); ++ asmlinkage long sys_eventfd2(unsigned int count, int flags); ++ asmlinkage long sys_epoll_create1(int flags); ++ asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, ++ struct epoll_event __user *event); ++ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, ++ int maxevents, int timeout, + const sigset_t __user *sigmask, + size_t sigsetsize); +-asmlinkage long sys_dup(unsigned int fildes); +-asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags); +-asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); +-#if BITS_PER_LONG == 32 +-asmlinkage long sys_fcntl64(unsigned int fd, +- unsigned int cmd, unsigned long arg); +-#endif +-asmlinkage long sys_inotify_init1(int flags); +-asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, +- u32 mask); +-asmlinkage long sys_inotify_rm_watch(int fd, __s32 wd); +-asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, +- unsigned long arg); +-asmlinkage long sys_ioprio_set(int which, int who, int ioprio); +-asmlinkage long sys_ioprio_get(int which, int who); +-asmlinkage long sys_flock(unsigned int fd, unsigned int cmd); +-asmlinkage long sys_mknodat(int dfd, const char __user * filename, umode_t mode, +- unsigned dev); +-asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, umode_t mode); +-asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag); +-asmlinkage long sys_symlinkat(const char __user * oldname, +- int newdfd, const char __user * newname); +-asmlinkage long sys_linkat(int olddfd, const char __user *oldname, +- int newdfd, const char __user *newname, int flags); +-asmlinkage long sys_renameat(int olddfd, const char __user * oldname, +- int newdfd, const char __user * newname); +-asmlinkage long sys_umount(char __user *name, int flags); +-asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name, +- char __user *type, unsigned long flags, +- void __user *data); +-asmlinkage long sys_pivot_root(const char __user *new_root, +- const char __user *put_old); +-asmlinkage long sys_statfs(const char __user * path, +- struct statfs __user *buf); +-asmlinkage long sys_statfs64(const char __user *path, size_t sz, +- struct statfs64 __user *buf); +-asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf); +-asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, +- struct statfs64 __user *buf); +-asmlinkage long sys_statmount(const struct mnt_id_req __user *req, +- struct statmount __user *buf, size_t bufsize, +- unsigned int flags); +-asmlinkage long sys_listmount(const struct mnt_id_req __user *req, +- u64 __user *mnt_ids, size_t nr_mnt_ids, +- unsigned int flags); +-asmlinkage long sys_truncate(const char __user *path, long length); +-asmlinkage long sys_ftruncate(unsigned int fd, off_t length); +-#if BITS_PER_LONG == 32 +-asmlinkage long sys_truncate64(const char __user *path, loff_t length); +-asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length); +-#endif +-asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len); +-asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode); +-asmlinkage long sys_faccessat2(int dfd, const char __user *filename, int mode, +- int flags); +-asmlinkage long sys_chdir(const char __user *filename); +-asmlinkage long sys_fchdir(unsigned int fd); +-asmlinkage long sys_chroot(const char __user *filename); +-asmlinkage long sys_fchmod(unsigned int fd, umode_t mode); +-asmlinkage long sys_fchmodat(int dfd, const char __user *filename, +- umode_t mode); +-asmlinkage long sys_fchmodat2(int dfd, const char __user *filename, +- umode_t mode, unsigned int flags); +-asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, +- gid_t group, int flag); +-asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group); +-asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, +- umode_t mode); +-asmlinkage long sys_openat2(int dfd, const char __user *filename, +- struct open_how __user *how, size_t size); +-asmlinkage long sys_close(unsigned int fd); +-asmlinkage long sys_close_range(unsigned int fd, unsigned int max_fd, +- unsigned int flags); +-asmlinkage long sys_vhangup(void); +-asmlinkage long sys_pipe2(int __user *fildes, int flags); +-asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, +- qid_t id, void __user *addr); +-asmlinkage long sys_quotactl_fd(unsigned int fd, unsigned int cmd, qid_t id, +- void __user *addr); +-asmlinkage long sys_getdents64(unsigned int fd, +- struct linux_dirent64 __user *dirent, +- unsigned int count); +-asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, +- unsigned long offset_low, loff_t __user *result, +- unsigned int whence); +-asmlinkage long sys_lseek(unsigned int fd, off_t offset, +- unsigned int whence); +-asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count); +-asmlinkage long sys_write(unsigned int fd, const char __user *buf, +- size_t count); +-asmlinkage long sys_readv(unsigned long fd, +- const struct iovec __user *vec, +- unsigned long vlen); +-asmlinkage long sys_writev(unsigned long fd, ++ asmlinkage long sys_epoll_pwait2(int epfd, struct epoll_event __user *events, ++ int maxevents, ++ const struct __kernel_timespec __user *timeout, ++ const sigset_t __user *sigmask, ++ size_t sigsetsize); ++ asmlinkage long sys_dup(unsigned int fildes); ++ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags); ++ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); ++ #if BITS_PER_LONG == 32 ++ asmlinkage long sys_fcntl64(unsigned int fd, ++ unsigned int cmd, unsigned long arg); ++ #endif ++ asmlinkage long sys_inotify_init1(int flags); ++ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, ++ u32 mask); ++ asmlinkage long sys_inotify_rm_watch(int fd, __s32 wd); ++ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, ++ unsigned long arg); ++ asmlinkage long sys_ioprio_set(int which, int who, int ioprio); ++ asmlinkage long sys_ioprio_get(int which, int who); ++ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd); ++ asmlinkage long sys_mknodat(int dfd, const char __user * filename, umode_t mode, ++ unsigned dev); ++ asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, umode_t mode); ++ asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag); ++ asmlinkage long sys_symlinkat(const char __user * oldname, ++ int newdfd, const char __user * newname); ++ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, ++ int newdfd, const char __user *newname, int flags); ++ asmlinkage long sys_renameat(int olddfd, const char __user * oldname, ++ int newdfd, const char __user * newname); ++ asmlinkage long sys_umount(char __user *name, int flags); ++ asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name, ++ char __user *type, unsigned long flags, ++ void __user *data); ++ asmlinkage long sys_pivot_root(const char __user *new_root, ++ const char __user *put_old); ++ asmlinkage long sys_statfs(const char __user * path, ++ struct statfs __user *buf); ++ asmlinkage long sys_statfs64(const char __user *path, size_t sz, ++ struct statfs64 __user *buf); ++ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf); ++ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, ++ struct statfs64 __user *buf); ++ asmlinkage long sys_statmount(const struct mnt_id_req __user *req, ++ struct statmount __user *buf, size_t bufsize, ++ unsigned int flags); ++ asmlinkage long sys_listmount(const struct mnt_id_req __user *req, ++ u64 __user *mnt_ids, size_t nr_mnt_ids, ++ unsigned int flags); ++ asmlinkage long sys_truncate(const char __user *path, long length); ++ asmlinkage long sys_ftruncate(unsigned int fd, off_t length); ++ #if BITS_PER_LONG == 32 ++ asmlinkage long sys_truncate64(const char __user *path, loff_t length); ++ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length); ++ #endif ++ asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len); ++ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode); ++ asmlinkage long sys_faccessat2(int dfd, const char __user *filename, int mode, ++ int flags); ++ asmlinkage long sys_chdir(const char __user *filename); ++ asmlinkage long sys_fchdir(unsigned int fd); ++ asmlinkage long sys_chroot(const char __user *filename); ++ asmlinkage long sys_fchmod(unsigned int fd, umode_t mode); ++ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, ++ umode_t mode); ++ asmlinkage long sys_fchmodat2(int dfd, const char __user *filename, ++ umode_t mode, unsigned int flags); ++ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, ++ gid_t group, int flag); ++ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group); ++ asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, ++ umode_t mode); ++ asmlinkage long sys_openat2(int dfd, const char __user *filename, ++ struct open_how __user *how, size_t size); ++ asmlinkage long sys_close(unsigned int fd); ++ asmlinkage long sys_close_range(unsigned int fd, unsigned int max_fd, ++ unsigned int flags); ++ asmlinkage long sys_vhangup(void); ++ asmlinkage long sys_pipe2(int __user *fildes, int flags); ++ asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, ++ qid_t id, void __user *addr); ++ asmlinkage long sys_quotactl_fd(unsigned int fd, unsigned int cmd, qid_t id, ++ void __user *addr); ++ asmlinkage long sys_getdents64(unsigned int fd, ++ struct linux_dirent64 __user *dirent, ++ unsigned int count); ++ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, ++ unsigned long offset_low, loff_t __user *result, ++ unsigned int whence); ++ asmlinkage long sys_lseek(unsigned int fd, off_t offset, ++ unsigned int whence); ++ asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count); ++ asmlinkage long sys_write(unsigned int fd, const char __user *buf, ++ size_t count); ++ asmlinkage long sys_readv(unsigned long fd, + const struct iovec __user *vec, + unsigned long vlen); +-asmlinkage long sys_pread64(unsigned int fd, char __user *buf, +- size_t count, loff_t pos); +-asmlinkage long sys_pwrite64(unsigned int fd, const char __user *buf, +- size_t count, loff_t pos); +-asmlinkage long sys_preadv(unsigned long fd, const struct iovec __user *vec, +- unsigned long vlen, unsigned long pos_l, unsigned long pos_h); +-asmlinkage long sys_pwritev(unsigned long fd, const struct iovec __user *vec, +- unsigned long vlen, unsigned long pos_l, unsigned long pos_h); +-asmlinkage long sys_sendfile64(int out_fd, int in_fd, +- loff_t __user *offset, size_t count); +-asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, +- fd_set __user *, struct __kernel_timespec __user *, +- void __user *); +-asmlinkage long sys_pselect6_time32(int, fd_set __user *, fd_set __user *, +- fd_set __user *, struct old_timespec32 __user *, +- void __user *); +-asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int, +- struct __kernel_timespec __user *, const sigset_t __user *, +- size_t); +-asmlinkage long sys_ppoll_time32(struct pollfd __user *, unsigned int, +- struct old_timespec32 __user *, const sigset_t __user *, +- size_t); +-asmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, int flags); +-asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov, +- unsigned long nr_segs, unsigned int flags); +-asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, +- int fd_out, loff_t __user *off_out, +- size_t len, unsigned int flags); +-asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags); +-asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, +- int bufsiz); +-asmlinkage long sys_newfstatat(int dfd, const char __user *filename, +- struct stat __user *statbuf, int flag); +-asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf); +-#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) +-asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf); +-asmlinkage long sys_fstatat64(int dfd, const char __user *filename, +- struct stat64 __user *statbuf, int flag); +-#endif +-asmlinkage long sys_sync(void); +-asmlinkage long sys_fsync(unsigned int fd); +-asmlinkage long sys_fdatasync(unsigned int fd); +-asmlinkage long sys_sync_file_range2(int fd, unsigned int flags, +- loff_t offset, loff_t nbytes); +-asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, +- unsigned int flags); +-asmlinkage long sys_timerfd_create(int clockid, int flags); +-asmlinkage long sys_timerfd_settime(int ufd, int flags, +- const struct __kernel_itimerspec __user *utmr, +- struct __kernel_itimerspec __user *otmr); +-asmlinkage long sys_timerfd_gettime(int ufd, struct __kernel_itimerspec __user *otmr); +-asmlinkage long sys_timerfd_gettime32(int ufd, +- struct old_itimerspec32 __user *otmr); +-asmlinkage long sys_timerfd_settime32(int ufd, int flags, +- const struct old_itimerspec32 __user *utmr, +- struct old_itimerspec32 __user *otmr); +-asmlinkage long sys_utimensat(int dfd, const char __user *filename, +- struct __kernel_timespec __user *utimes, +- int flags); +-asmlinkage long sys_utimensat_time32(unsigned int dfd, +- const char __user *filename, +- struct old_timespec32 __user *t, int flags); +-asmlinkage long sys_acct(const char __user *name); +-asmlinkage long sys_capget(cap_user_header_t header, +- cap_user_data_t dataptr); +-asmlinkage long sys_capset(cap_user_header_t header, +- const cap_user_data_t data); +-asmlinkage long sys_personality(unsigned int personality); +-asmlinkage long sys_exit(int error_code); +-asmlinkage long sys_exit_group(int error_code); +-asmlinkage long sys_waitid(int which, pid_t pid, +- struct siginfo __user *infop, +- int options, struct rusage __user *ru); +-asmlinkage long sys_set_tid_address(int __user *tidptr); +-asmlinkage long sys_unshare(unsigned long unshare_flags); +-asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, +- const struct __kernel_timespec __user *utime, +- u32 __user *uaddr2, u32 val3); +-asmlinkage long sys_futex_time32(u32 __user *uaddr, int op, u32 val, +- const struct old_timespec32 __user *utime, +- u32 __user *uaddr2, u32 val3); +-asmlinkage long sys_get_robust_list(int pid, +- struct robust_list_head __user * __user *head_ptr, +- size_t __user *len_ptr); +-asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, +- size_t len); +- +-asmlinkage long sys_futex_waitv(struct futex_waitv __user *waiters, +- unsigned int nr_futexes, unsigned int flags, +- struct __kernel_timespec __user *timeout, clockid_t clockid); +- +-asmlinkage long sys_futex_wake(void __user *uaddr, unsigned long mask, int nr, unsigned int flags); +- +-asmlinkage long sys_futex_wait(void __user *uaddr, unsigned long val, unsigned long mask, +- unsigned int flags, struct __kernel_timespec __user *timespec, +- clockid_t clockid); +- +-asmlinkage long sys_futex_requeue(struct futex_waitv __user *waiters, +- unsigned int flags, int nr_wake, int nr_requeue); +- +-asmlinkage long sys_nanosleep(struct __kernel_timespec __user *rqtp, +- struct __kernel_timespec __user *rmtp); +-asmlinkage long sys_nanosleep_time32(struct old_timespec32 __user *rqtp, +- struct old_timespec32 __user *rmtp); +-asmlinkage long sys_getitimer(int which, struct __kernel_old_itimerval __user *value); +-asmlinkage long sys_setitimer(int which, +- struct __kernel_old_itimerval __user *value, +- struct __kernel_old_itimerval __user *ovalue); +-asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, +- struct kexec_segment __user *segments, +- unsigned long flags); +-asmlinkage long sys_init_module(void __user *umod, unsigned long len, +- const char __user *uargs); +-asmlinkage long sys_delete_module(const char __user *name_user, +- unsigned int flags); +-asmlinkage long sys_timer_create(clockid_t which_clock, +- struct sigevent __user *timer_event_spec, +- timer_t __user * created_timer_id); +-asmlinkage long sys_timer_gettime(timer_t timer_id, +- struct __kernel_itimerspec __user *setting); +-asmlinkage long sys_timer_getoverrun(timer_t timer_id); +-asmlinkage long sys_timer_settime(timer_t timer_id, int flags, +- const struct __kernel_itimerspec __user *new_setting, +- struct __kernel_itimerspec __user *old_setting); +-asmlinkage long sys_timer_delete(timer_t timer_id); +-asmlinkage long sys_clock_settime(clockid_t which_clock, +- const struct __kernel_timespec __user *tp); +-asmlinkage long sys_clock_gettime(clockid_t which_clock, +- struct __kernel_timespec __user *tp); +-asmlinkage long sys_clock_getres(clockid_t which_clock, +- struct __kernel_timespec __user *tp); +-asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags, +- const struct __kernel_timespec __user *rqtp, +- struct __kernel_timespec __user *rmtp); +-asmlinkage long sys_timer_gettime32(timer_t timer_id, +- struct old_itimerspec32 __user *setting); +-asmlinkage long sys_timer_settime32(timer_t timer_id, int flags, +- struct old_itimerspec32 __user *new, +- struct old_itimerspec32 __user *old); +-asmlinkage long sys_clock_settime32(clockid_t which_clock, +- struct old_timespec32 __user *tp); +-asmlinkage long sys_clock_gettime32(clockid_t which_clock, +- struct old_timespec32 __user *tp); +-asmlinkage long sys_clock_getres_time32(clockid_t which_clock, +- struct old_timespec32 __user *tp); +-asmlinkage long sys_clock_nanosleep_time32(clockid_t which_clock, int flags, +- struct old_timespec32 __user *rqtp, +- struct old_timespec32 __user *rmtp); +-asmlinkage long sys_syslog(int type, char __user *buf, int len); +-asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, +- unsigned long data); +-asmlinkage long sys_sched_setparam(pid_t pid, +- struct sched_param __user *param); +-asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, +- struct sched_param __user *param); +-asmlinkage long sys_sched_getscheduler(pid_t pid); +-asmlinkage long sys_sched_getparam(pid_t pid, +- struct sched_param __user *param); +-asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, +- unsigned long __user *user_mask_ptr); +-asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, +- unsigned long __user *user_mask_ptr); +-asmlinkage long sys_sched_yield(void); +-asmlinkage long sys_sched_get_priority_max(int policy); +-asmlinkage long sys_sched_get_priority_min(int policy); +-asmlinkage long sys_sched_rr_get_interval(pid_t pid, +- struct __kernel_timespec __user *interval); +-asmlinkage long sys_sched_rr_get_interval_time32(pid_t pid, +- struct old_timespec32 __user *interval); +-asmlinkage long sys_restart_syscall(void); +-asmlinkage long sys_kill(pid_t pid, int sig); +-asmlinkage long sys_tkill(pid_t pid, int sig); +-asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig); +-asmlinkage long sys_sigaltstack(const struct sigaltstack __user *uss, +- struct sigaltstack __user *uoss); +-asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize); +-#ifndef CONFIG_ODD_RT_SIGACTION +-asmlinkage long sys_rt_sigaction(int, +- const struct sigaction __user *, +- struct sigaction __user *, +- size_t); +-#endif +-asmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set, +- sigset_t __user *oset, size_t sigsetsize); +-asmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize); +-asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese, +- siginfo_t __user *uinfo, +- const struct __kernel_timespec __user *uts, +- size_t sigsetsize); +-asmlinkage long sys_rt_sigtimedwait_time32(const sigset_t __user *uthese, +- siginfo_t __user *uinfo, +- const struct old_timespec32 __user *uts, +- size_t sigsetsize); +-asmlinkage long sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo); +-asmlinkage long sys_setpriority(int which, int who, int niceval); +-asmlinkage long sys_getpriority(int which, int who); +-asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, +- void __user *arg); +-asmlinkage long sys_setregid(gid_t rgid, gid_t egid); +-asmlinkage long sys_setgid(gid_t gid); +-asmlinkage long sys_setreuid(uid_t ruid, uid_t euid); +-asmlinkage long sys_setuid(uid_t uid); +-asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); +-asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid); +-asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); +-asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid); +-asmlinkage long sys_setfsuid(uid_t uid); +-asmlinkage long sys_setfsgid(gid_t gid); +-asmlinkage long sys_times(struct tms __user *tbuf); +-asmlinkage long sys_setpgid(pid_t pid, pid_t pgid); +-asmlinkage long sys_getpgid(pid_t pid); +-asmlinkage long sys_getsid(pid_t pid); +-asmlinkage long sys_setsid(void); +-asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist); +-asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist); +-asmlinkage long sys_newuname(struct new_utsname __user *name); +-asmlinkage long sys_sethostname(char __user *name, int len); +-asmlinkage long sys_setdomainname(char __user *name, int len); +-asmlinkage long sys_getrlimit(unsigned int resource, +- struct rlimit __user *rlim); +-asmlinkage long sys_setrlimit(unsigned int resource, +- struct rlimit __user *rlim); +-asmlinkage long sys_getrusage(int who, struct rusage __user *ru); +-asmlinkage long sys_umask(int mask); +-asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, +- unsigned long arg4, unsigned long arg5); +-asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache); +-asmlinkage long sys_gettimeofday(struct __kernel_old_timeval __user *tv, +- struct timezone __user *tz); +-asmlinkage long sys_settimeofday(struct __kernel_old_timeval __user *tv, +- struct timezone __user *tz); +-asmlinkage long sys_adjtimex(struct __kernel_timex __user *txc_p); +-asmlinkage long sys_adjtimex_time32(struct old_timex32 __user *txc_p); +-asmlinkage long sys_getpid(void); +-asmlinkage long sys_getppid(void); +-asmlinkage long sys_getuid(void); +-asmlinkage long sys_geteuid(void); +-asmlinkage long sys_getgid(void); +-asmlinkage long sys_getegid(void); +-asmlinkage long sys_gettid(void); +-asmlinkage long sys_sysinfo(struct sysinfo __user *info); +-asmlinkage long sys_mq_open(const char __user *name, int oflag, umode_t mode, struct mq_attr __user *attr); +-asmlinkage long sys_mq_unlink(const char __user *name); +-asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec __user *abs_timeout); +-asmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct __kernel_timespec __user *abs_timeout); +-asmlinkage long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *notification); +-asmlinkage long sys_mq_getsetattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat); +-asmlinkage long sys_mq_timedreceive_time32(mqd_t mqdes, +- char __user *u_msg_ptr, +- unsigned int msg_len, unsigned int __user *u_msg_prio, +- const struct old_timespec32 __user *u_abs_timeout); +-asmlinkage long sys_mq_timedsend_time32(mqd_t mqdes, +- const char __user *u_msg_ptr, +- unsigned int msg_len, unsigned int msg_prio, +- const struct old_timespec32 __user *u_abs_timeout); +-asmlinkage long sys_msgget(key_t key, int msgflg); +-asmlinkage long sys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); +-asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); +-asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, +- size_t msgsz, long msgtyp, int msgflg); +-asmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp, +- size_t msgsz, int msgflg); +-asmlinkage long sys_semget(key_t key, int nsems, int semflg); +-asmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg); +-asmlinkage long sys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); +-asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops, +- unsigned nsops, +- const struct __kernel_timespec __user *timeout); +-asmlinkage long sys_semtimedop_time32(int semid, struct sembuf __user *sops, +- unsigned nsops, +- const struct old_timespec32 __user *timeout); +-asmlinkage long sys_semop(int semid, struct sembuf __user *sops, +- unsigned nsops); +-asmlinkage long sys_shmget(key_t key, size_t size, int flag); +-asmlinkage long sys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); +-asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); +-asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg); +-asmlinkage long sys_shmdt(char __user *shmaddr); +-asmlinkage long sys_socket(int, int, int); +-asmlinkage long sys_socketpair(int, int, int, int __user *); +-asmlinkage long sys_bind(int, struct sockaddr __user *, int); +-asmlinkage long sys_listen(int, int); +-asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); +-asmlinkage long sys_connect(int, struct sockaddr __user *, int); +-asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); +-asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); +-asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, +- struct sockaddr __user *, int); +-asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, +- struct sockaddr __user *, int __user *); +-asmlinkage long sys_setsockopt(int fd, int level, int optname, +- char __user *optval, int optlen); +-asmlinkage long sys_getsockopt(int fd, int level, int optname, +- char __user *optval, int __user *optlen); +-asmlinkage long sys_shutdown(int, int); +-asmlinkage long sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags); +-asmlinkage long sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags); +-asmlinkage long sys_readahead(int fd, loff_t offset, size_t count); +-asmlinkage long sys_brk(unsigned long brk); +-asmlinkage long sys_munmap(unsigned long addr, size_t len); +-asmlinkage long sys_mremap(unsigned long addr, +- unsigned long old_len, unsigned long new_len, +- unsigned long flags, unsigned long new_addr); +-asmlinkage long sys_add_key(const char __user *_type, +- const char __user *_description, +- const void __user *_payload, +- size_t plen, +- key_serial_t destringid); +-asmlinkage long sys_request_key(const char __user *_type, +- const char __user *_description, +- const char __user *_callout_info, +- key_serial_t destringid); +-asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, +- unsigned long arg4, unsigned long arg5); +-#ifdef CONFIG_CLONE_BACKWARDS +-asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, unsigned long, +- int __user *); +-#else +-#ifdef CONFIG_CLONE_BACKWARDS3 +-asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *, +- int __user *, unsigned long); +-#else +-asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, +- int __user *, unsigned long); +-#endif +-#endif +- +-asmlinkage long sys_clone3(struct clone_args __user *uargs, size_t size); +- +-asmlinkage long sys_execve(const char __user *filename, +- const char __user *const __user *argv, +- const char __user *const __user *envp); +-asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); +- +-/* CONFIG_MMU only */ +-asmlinkage long sys_swapon(const char __user *specialfile, int swap_flags); +-asmlinkage long sys_swapoff(const char __user *specialfile); +-asmlinkage long sys_mprotect(unsigned long start, size_t len, +- unsigned long prot); +-asmlinkage long sys_msync(unsigned long start, size_t len, int flags); +-asmlinkage long sys_mlock(unsigned long start, size_t len); +-asmlinkage long sys_munlock(unsigned long start, size_t len); +-asmlinkage long sys_mlockall(int flags); +-asmlinkage long sys_munlockall(void); +-asmlinkage long sys_mincore(unsigned long start, size_t len, +- unsigned char __user * vec); +-asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); +-asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec, +- size_t vlen, int behavior, unsigned int flags); +-asmlinkage long sys_process_mrelease(int pidfd, unsigned int flags); +-asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, +- unsigned long prot, unsigned long pgoff, +- unsigned long flags); +-asmlinkage long sys_mseal(unsigned long start, size_t len, unsigned long flags); +-asmlinkage long sys_mbind(unsigned long start, unsigned long len, +- unsigned long mode, +- const unsigned long __user *nmask, +- unsigned long maxnode, +- unsigned flags); +-asmlinkage long sys_get_mempolicy(int __user *policy, +- unsigned long __user *nmask, +- unsigned long maxnode, +- unsigned long addr, unsigned long flags); +-asmlinkage long sys_set_mempolicy(int mode, const unsigned long __user *nmask, +- unsigned long maxnode); +-asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, +- const unsigned long __user *from, +- const unsigned long __user *to); +-asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, +- const void __user * __user *pages, +- const int __user *nodes, +- int __user *status, +- int flags); +-asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, +- siginfo_t __user *uinfo); +-asmlinkage long sys_perf_event_open( +- struct perf_event_attr __user *attr_uptr, +- pid_t pid, int cpu, int group_fd, unsigned long flags); +-asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int); +-asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg, +- unsigned int vlen, unsigned flags, +- struct __kernel_timespec __user *timeout); +-asmlinkage long sys_recvmmsg_time32(int fd, struct mmsghdr __user *msg, +- unsigned int vlen, unsigned flags, +- struct old_timespec32 __user *timeout); +-asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, ++ asmlinkage long sys_writev(unsigned long fd, ++ const struct iovec __user *vec, ++ unsigned long vlen); ++ asmlinkage long sys_pread64(unsigned int fd, char __user *buf, ++ size_t count, loff_t pos); ++ asmlinkage long sys_pwrite64(unsigned int fd, const char __user *buf, ++ size_t count, loff_t pos); ++ asmlinkage long sys_preadv(unsigned long fd, const struct iovec __user *vec, ++ unsigned long vlen, unsigned long pos_l, unsigned long pos_h); ++ asmlinkage long sys_pwritev(unsigned long fd, const struct iovec __user *vec, ++ unsigned long vlen, unsigned long pos_l, unsigned long pos_h); ++ asmlinkage long sys_sendfile64(int out_fd, int in_fd, ++ loff_t __user *offset, size_t count); ++ asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, ++ fd_set __user *, struct __kernel_timespec __user *, ++ void __user *); ++ asmlinkage long sys_pselect6_time32(int, fd_set __user *, fd_set __user *, ++ fd_set __user *, struct old_timespec32 __user *, ++ void __user *); ++ asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int, ++ struct __kernel_timespec __user *, const sigset_t __user *, ++ size_t); ++ asmlinkage long sys_ppoll_time32(struct pollfd __user *, unsigned int, ++ struct old_timespec32 __user *, const sigset_t __user *, ++ size_t); ++ asmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, int flags); ++ asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov, ++ unsigned long nr_segs, unsigned int flags); ++ asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, ++ int fd_out, loff_t __user *off_out, ++ size_t len, unsigned int flags); ++ asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags); ++ asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, ++ int bufsiz); ++ asmlinkage long sys_newfstatat(int dfd, const char __user *filename, ++ struct stat __user *statbuf, int flag); ++ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf); ++ #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) ++ asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf); ++ asmlinkage long sys_fstatat64(int dfd, const char __user *filename, ++ struct stat64 __user *statbuf, int flag); ++ #endif ++ asmlinkage long sys_sync(void); ++ asmlinkage long sys_fsync(unsigned int fd); ++ asmlinkage long sys_fdatasync(unsigned int fd); ++ asmlinkage long sys_sync_file_range2(int fd, unsigned int flags, ++ loff_t offset, loff_t nbytes); ++ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, ++ unsigned int flags); ++ asmlinkage long sys_timerfd_create(int clockid, int flags); ++ asmlinkage long sys_timerfd_settime(int ufd, int flags, ++ const struct __kernel_itimerspec __user *utmr, ++ struct __kernel_itimerspec __user *otmr); ++ asmlinkage long sys_timerfd_gettime(int ufd, struct __kernel_itimerspec __user *otmr); ++ asmlinkage long sys_timerfd_gettime32(int ufd, ++ struct old_itimerspec32 __user *otmr); ++ asmlinkage long sys_timerfd_settime32(int ufd, int flags, ++ const struct old_itimerspec32 __user *utmr, ++ struct old_itimerspec32 __user *otmr); ++ asmlinkage long sys_utimensat(int dfd, const char __user *filename, ++ struct __kernel_timespec __user *utimes, ++ int flags); ++ asmlinkage long sys_utimensat_time32(unsigned int dfd, ++ const char __user *filename, ++ struct old_timespec32 __user *t, int flags); ++ asmlinkage long sys_acct(const char __user *name); ++ asmlinkage long sys_capget(cap_user_header_t header, ++ cap_user_data_t dataptr); ++ asmlinkage long sys_capset(cap_user_header_t header, ++ const cap_user_data_t data); ++ asmlinkage long sys_personality(unsigned int personality); ++ asmlinkage long sys_exit(int error_code); ++ asmlinkage long sys_exit_group(int error_code); ++ asmlinkage long sys_waitid(int which, pid_t pid, ++ struct siginfo __user *infop, + int options, struct rusage __user *ru); +-asmlinkage long sys_prlimit64(pid_t pid, unsigned int resource, +- const struct rlimit64 __user *new_rlim, +- struct rlimit64 __user *old_rlim); +-asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags); +-#if defined(CONFIG_ARCH_SPLIT_ARG64) +-asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, +- unsigned int mask_1, unsigned int mask_2, +- int dfd, const char __user * pathname); +-#else +-asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, +- u64 mask, int fd, +- const char __user *pathname); +-#endif +-asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name, +- struct file_handle __user *handle, +- void __user *mnt_id, int flag); +-asmlinkage long sys_open_by_handle_at(int mountdirfd, +- struct file_handle __user *handle, +- int flags); +-asmlinkage long sys_clock_adjtime(clockid_t which_clock, +- struct __kernel_timex __user *tx); +-asmlinkage long sys_clock_adjtime32(clockid_t which_clock, +- struct old_timex32 __user *tx); +-asmlinkage long sys_syncfs(int fd); +-asmlinkage long sys_setns(int fd, int nstype); +-asmlinkage long sys_pidfd_open(pid_t pid, unsigned int flags); +-asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, +- unsigned int vlen, unsigned flags); +-asmlinkage long sys_process_vm_readv(pid_t pid, +- const struct iovec __user *lvec, +- unsigned long liovcnt, +- const struct iovec __user *rvec, +- unsigned long riovcnt, +- unsigned long flags); +-asmlinkage long sys_process_vm_writev(pid_t pid, +- const struct iovec __user *lvec, +- unsigned long liovcnt, +- const struct iovec __user *rvec, +- unsigned long riovcnt, +- unsigned long flags); +-asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, +- unsigned long idx1, unsigned long idx2); +-asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); +-asmlinkage long sys_sched_setattr(pid_t pid, +- struct sched_attr __user *attr, +- unsigned int flags); +-asmlinkage long sys_sched_getattr(pid_t pid, +- struct sched_attr __user *attr, +- unsigned int size, +- unsigned int flags); +-asmlinkage long sys_renameat2(int olddfd, const char __user *oldname, +- int newdfd, const char __user *newname, +- unsigned int flags); +-asmlinkage long sys_seccomp(unsigned int op, unsigned int flags, +- void __user *uargs); +-asmlinkage long sys_getrandom(char __user *buf, size_t count, +- unsigned int flags); +-asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags); +-asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int size); +-asmlinkage long sys_execveat(int dfd, const char __user *filename, +- const char __user *const __user *argv, +- const char __user *const __user *envp, int flags); +-asmlinkage long sys_userfaultfd(int flags); +-asmlinkage long sys_membarrier(int cmd, unsigned int flags, int cpu_id); +-asmlinkage long sys_mlock2(unsigned long start, size_t len, int flags); +-asmlinkage long sys_copy_file_range(int fd_in, loff_t __user *off_in, +- int fd_out, loff_t __user *off_out, +- size_t len, unsigned int flags); +-asmlinkage long sys_preadv2(unsigned long fd, const struct iovec __user *vec, +- unsigned long vlen, unsigned long pos_l, unsigned long pos_h, +- rwf_t flags); +-asmlinkage long sys_pwritev2(unsigned long fd, const struct iovec __user *vec, +- unsigned long vlen, unsigned long pos_l, unsigned long pos_h, +- rwf_t flags); +-asmlinkage long sys_pkey_mprotect(unsigned long start, size_t len, +- unsigned long prot, int pkey); +-asmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val); +-asmlinkage long sys_pkey_free(int pkey); +-asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, +- unsigned mask, struct statx __user *buffer); +-asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len, +- int flags, uint32_t sig); +-asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags); +-asmlinkage long sys_move_mount(int from_dfd, const char __user *from_path, +- int to_dfd, const char __user *to_path, +- unsigned int ms_flags); +-asmlinkage long sys_mount_setattr(int dfd, const char __user *path, +- unsigned int flags, +- struct mount_attr __user *uattr, size_t usize); +-asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags); +-asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, +- const void __user *value, int aux); +-asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags); +-asmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags); +-asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, +- siginfo_t __user *info, +- unsigned int flags); +-asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags); +-asmlinkage long sys_landlock_create_ruleset(const struct landlock_ruleset_attr __user *attr, +- size_t size, __u32 flags); +-asmlinkage long sys_landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type, +- const void __user *rule_attr, __u32 flags); +-asmlinkage long sys_landlock_restrict_self(int ruleset_fd, __u32 flags); +-asmlinkage long sys_memfd_secret(unsigned int flags); +-asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long len, +- unsigned long home_node, +- unsigned long flags); +-asmlinkage long sys_cachestat(unsigned int fd, +- struct cachestat_range __user *cstat_range, +- struct cachestat __user *cstat, unsigned int flags); +-asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); +-asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, +- u32 __user *size, u32 flags); +-asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, +- u32 size, u32 flags); +-asmlinkage long sys_lsm_list_modules(u64 __user *ids, u32 __user *size, u32 flags); +- +-/* +- * Architecture-specific system calls +- */ +- +-/* x86 */ +-asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on); +- +-asmlinkage long sys_uretprobe(void); +- +-/* pciconfig: alpha, arm, arm64, ia64, sparc */ +-asmlinkage long sys_pciconfig_read(unsigned long bus, unsigned long dfn, +- unsigned long off, unsigned long len, +- void __user *buf); +-asmlinkage long sys_pciconfig_write(unsigned long bus, unsigned long dfn, +- unsigned long off, unsigned long len, +- void __user *buf); +-asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn); +- +-/* powerpc */ +-asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, +- __u32 __user *ustatus); +-asmlinkage long sys_spu_create(const char __user *name, +- unsigned int flags, umode_t mode, int fd); +- +- +-/* +- * Deprecated system calls which are still defined in +- * include/uapi/asm-generic/unistd.h and wanted by >= 1 arch +- */ +- +-/* __ARCH_WANT_SYSCALL_NO_AT */ +-asmlinkage long sys_open(const char __user *filename, +- int flags, umode_t mode); +-asmlinkage long sys_link(const char __user *oldname, +- const char __user *newname); +-asmlinkage long sys_unlink(const char __user *pathname); +-asmlinkage long sys_mknod(const char __user *filename, umode_t mode, +- unsigned dev); +-asmlinkage long sys_chmod(const char __user *filename, umode_t mode); +-asmlinkage long sys_chown(const char __user *filename, +- uid_t user, gid_t group); +-asmlinkage long sys_mkdir(const char __user *pathname, umode_t mode); +-asmlinkage long sys_rmdir(const char __user *pathname); +-asmlinkage long sys_lchown(const char __user *filename, +- uid_t user, gid_t group); +-asmlinkage long sys_access(const char __user *filename, int mode); +-asmlinkage long sys_rename(const char __user *oldname, +- const char __user *newname); +-asmlinkage long sys_symlink(const char __user *old, const char __user *new); +-#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) +-asmlinkage long sys_stat64(const char __user *filename, +- struct stat64 __user *statbuf); +-asmlinkage long sys_lstat64(const char __user *filename, +- struct stat64 __user *statbuf); +-#endif +- +-/* __ARCH_WANT_SYSCALL_NO_FLAGS */ +-asmlinkage long sys_pipe(int __user *fildes); +-asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd); +-asmlinkage long sys_epoll_create(int size); +-asmlinkage long sys_inotify_init(void); +-asmlinkage long sys_eventfd(unsigned int count); +-asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask); +- +-/* __ARCH_WANT_SYSCALL_OFF_T */ +-asmlinkage long sys_sendfile(int out_fd, int in_fd, +- off_t __user *offset, size_t count); +-asmlinkage long sys_newstat(const char __user *filename, +- struct stat __user *statbuf); +-asmlinkage long sys_newlstat(const char __user *filename, +- struct stat __user *statbuf); +-asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice); +- +-/* __ARCH_WANT_SYSCALL_DEPRECATED */ +-asmlinkage long sys_alarm(unsigned int seconds); +-asmlinkage long sys_getpgrp(void); +-asmlinkage long sys_pause(void); +-asmlinkage long sys_time(__kernel_old_time_t __user *tloc); +-asmlinkage long sys_time32(old_time32_t __user *tloc); +-#ifdef __ARCH_WANT_SYS_UTIME +-asmlinkage long sys_utime(char __user *filename, +- struct utimbuf __user *times); +-asmlinkage long sys_utimes(char __user *filename, +- struct __kernel_old_timeval __user *utimes); +-asmlinkage long sys_futimesat(int dfd, const char __user *filename, +- struct __kernel_old_timeval __user *utimes); +-#endif +-asmlinkage long sys_futimesat_time32(unsigned int dfd, +- const char __user *filename, +- struct old_timeval32 __user *t); +-asmlinkage long sys_utime32(const char __user *filename, +- struct old_utimbuf32 __user *t); +-asmlinkage long sys_utimes_time32(const char __user *filename, +- struct old_timeval32 __user *t); +-asmlinkage long sys_creat(const char __user *pathname, umode_t mode); +-asmlinkage long sys_getdents(unsigned int fd, +- struct linux_dirent __user *dirent, +- unsigned int count); +-asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, +- fd_set __user *exp, struct __kernel_old_timeval __user *tvp); +-asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, +- int timeout); +-asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, +- int maxevents, int timeout); +-asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf); +-asmlinkage long sys_vfork(void); +-asmlinkage long sys_recv(int, void __user *, size_t, unsigned); +-asmlinkage long sys_send(int, void __user *, size_t, unsigned); +-asmlinkage long sys_oldumount(char __user *name); +-asmlinkage long sys_uselib(const char __user *library); +-asmlinkage long sys_sysfs(int option, +- unsigned long arg1, unsigned long arg2); +-asmlinkage long sys_fork(void); +- +-/* obsolete */ +-asmlinkage long sys_stime(__kernel_old_time_t __user *tptr); +-asmlinkage long sys_stime32(old_time32_t __user *tptr); +- +-/* obsolete */ +-asmlinkage long sys_sigpending(old_sigset_t __user *uset); +-asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set, +- old_sigset_t __user *oset); +-#ifdef CONFIG_OLD_SIGSUSPEND +-asmlinkage long sys_sigsuspend(old_sigset_t mask); +-#endif +- +-#ifdef CONFIG_OLD_SIGSUSPEND3 +-asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask); +-#endif +- +-#ifdef CONFIG_OLD_SIGACTION +-asmlinkage long sys_sigaction(int, const struct old_sigaction __user *, +- struct old_sigaction __user *); +-#endif +-asmlinkage long sys_sgetmask(void); +-asmlinkage long sys_ssetmask(int newmask); +-asmlinkage long sys_signal(int sig, __sighandler_t handler); +- +-/* obsolete */ +-asmlinkage long sys_nice(int increment); +- +-/* obsolete */ +-asmlinkage long sys_kexec_file_load(int kernel_fd, int initrd_fd, +- unsigned long cmdline_len, +- const char __user *cmdline_ptr, +- unsigned long flags); +- +-/* obsolete */ +-asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options); +- +-/* obsolete */ +-#ifdef CONFIG_HAVE_UID16 +-asmlinkage long sys_chown16(const char __user *filename, +- old_uid_t user, old_gid_t group); +-asmlinkage long sys_lchown16(const char __user *filename, +- old_uid_t user, old_gid_t group); +-asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group); +-asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid); +-asmlinkage long sys_setgid16(old_gid_t gid); +-asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid); +-asmlinkage long sys_setuid16(old_uid_t uid); +-asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid); +-asmlinkage long sys_getresuid16(old_uid_t __user *ruid, +- old_uid_t __user *euid, old_uid_t __user *suid); +-asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid); +-asmlinkage long sys_getresgid16(old_gid_t __user *rgid, +- old_gid_t __user *egid, old_gid_t __user *sgid); +-asmlinkage long sys_setfsuid16(old_uid_t uid); +-asmlinkage long sys_setfsgid16(old_gid_t gid); +-asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist); +-asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist); +-asmlinkage long sys_getuid16(void); +-asmlinkage long sys_geteuid16(void); +-asmlinkage long sys_getgid16(void); +-asmlinkage long sys_getegid16(void); +-#endif +- +-/* obsolete */ +-asmlinkage long sys_socketcall(int call, unsigned long __user *args); +- +-/* obsolete */ +-asmlinkage long sys_stat(const char __user *filename, +- struct __old_kernel_stat __user *statbuf); +-asmlinkage long sys_lstat(const char __user *filename, +- struct __old_kernel_stat __user *statbuf); +-asmlinkage long sys_fstat(unsigned int fd, +- struct __old_kernel_stat __user *statbuf); +-asmlinkage long sys_readlink(const char __user *path, +- char __user *buf, int bufsiz); +- +-/* obsolete */ +-asmlinkage long sys_old_select(struct sel_arg_struct __user *arg); +- +-/* obsolete */ +-asmlinkage long sys_old_readdir(unsigned int, struct old_linux_dirent __user *, unsigned int); +- +-/* obsolete */ +-asmlinkage long sys_gethostname(char __user *name, int len); +-asmlinkage long sys_uname(struct old_utsname __user *); +-asmlinkage long sys_olduname(struct oldold_utsname __user *); +-#ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT +-asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim); +-#endif +- +-/* obsolete */ +-asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, +- unsigned long third, void __user *ptr, long fifth); +- +-/* obsolete */ +-asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, +- unsigned long prot, unsigned long flags, +- unsigned long fd, unsigned long pgoff); +-asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg); +- +- +-/* +- * Not a real system call, but a placeholder for syscalls which are +- * not implemented -- see kernel/sys_ni.c +- */ +-asmlinkage long sys_ni_syscall(void); +- +-#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ +- +-asmlinkage long sys_ni_posix_timers(void); +- +-/* +- * Kernel code should not call syscalls (i.e., sys_xyzyyz()) directly. +- * Instead, use one of the functions which work equivalently, such as +- * the ksys_xyzyyz() functions prototyped below. +- */ +-ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); +-int ksys_fchown(unsigned int fd, uid_t user, gid_t group); +-ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count); +-void ksys_sync(void); +-int ksys_unshare(unsigned long unshare_flags); +-int ksys_setsid(void); +-int ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes, +- unsigned int flags); +-ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count, +- loff_t pos); +-ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf, +- size_t count, loff_t pos); +-int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len); +-#ifdef CONFIG_ADVISE_SYSCALLS +-int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); +-#else +-static inline int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, +- int advice) +-{ +- return -EINVAL; +-} +-#endif +-unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, +- unsigned long prot, unsigned long flags, +- unsigned long fd, unsigned long pgoff); +-ssize_t ksys_readahead(int fd, loff_t offset, size_t count); +-int ksys_ipc(unsigned int call, int first, unsigned long second, +- unsigned long third, void __user * ptr, long fifth); +-int compat_ksys_ipc(u32 call, int first, int second, +- u32 third, u32 ptr, u32 fifth); +- +-/* +- * The following kernel syscall equivalents are just wrappers to fs-internal +- * functions. Therefore, provide stubs to be inlined at the callsites. +- */ +-extern int do_fchownat(int dfd, const char __user *filename, uid_t user, +- gid_t group, int flag); +- +-static inline long ksys_chown(const char __user *filename, uid_t user, +- gid_t group) +-{ +- return do_fchownat(AT_FDCWD, filename, user, group, 0); +-} +- +-static inline long ksys_lchown(const char __user *filename, uid_t user, +- gid_t group) +-{ +- return do_fchownat(AT_FDCWD, filename, user, group, +- AT_SYMLINK_NOFOLLOW); +-} +- +-extern long do_sys_ftruncate(unsigned int fd, loff_t length, int small); +- +-static inline long ksys_ftruncate(unsigned int fd, loff_t length) +-{ +- return do_sys_ftruncate(fd, length, 1); +-} +- +-extern long do_sys_truncate(const char __user *pathname, loff_t length); +- +-static inline long ksys_truncate(const char __user *pathname, loff_t length) +-{ +- return do_sys_truncate(pathname, length); +-} +- +-static inline unsigned int ksys_personality(unsigned int personality) +-{ +- unsigned int old = current->personality; +- +- if (personality != 0xffffffff) +- set_personality(personality); +- +- return old; +-} +- +-/* for __ARCH_WANT_SYS_IPC */ +-long ksys_semtimedop(int semid, struct sembuf __user *tsops, +- unsigned int nsops, +- const struct __kernel_timespec __user *timeout); +-long ksys_semget(key_t key, int nsems, int semflg); +-long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); +-long ksys_msgget(key_t key, int msgflg); +-long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); +-long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, +- long msgtyp, int msgflg); +-long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, +- int msgflg); +-long ksys_shmget(key_t key, size_t size, int shmflg); +-long ksys_shmdt(char __user *shmaddr); +-long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); +-long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, +- unsigned int nsops, +- const struct old_timespec32 __user *timeout); +-long __do_semtimedop(int semid, struct sembuf *tsems, unsigned int nsops, +- const struct timespec64 *timeout, +- struct ipc_namespace *ns); +- +-int __sys_getsockopt(int fd, int level, int optname, char __user *optval, +- int __user *optlen); +-int __sys_setsockopt(int fd, int level, int optname, char __user *optval, +- int optlen); +-#endif ++ asmlinkage long sys_set_tid_address(int __user *tidptr); ++ asmlinkage long sys_unshare(unsigned long unshare_flags); ++ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, ++ const struct __kernel_timespec __user *utime, ++ u32 __user *uaddr2, u32 val3); ++ asmlinkage long sys_futex_time32(u32 __user *uaddr, int op, u32 val, ++ const struct old_timespec32 __user *utime, ++ u32 __user *uaddr2, u32 val3); ++ asmlinkage long sys_get_robust_list(int pid, ++ struct robust_list_head __user * __user *head_ptr, ++ size_t __user *len_ptr); ++ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, ++ size_t len); ++ ++ asmlinkage long sys_futex_waitv(struct futex_waitv __user *waiters, ++ unsigned int nr_futexes, unsigned int flags, ++ struct __kernel_timespec __user *timeout, clockid_t clockid); ++ ++ asmlinkage long sys_futex_wake(void __user *uaddr, unsigned long mask, int nr, unsigned int flags); ++ ++ asmlinkage long sys_futex_wait(void __user *uaddr, unsigned long val, unsigned long mask, ++ unsigned int flags, struct __kernel_timespec __user *timespec, ++ clockid_t clockid); ++ ++ asmlinkage long sys_futex_requeue(struct futex_waitv __user *waiters, ++ unsigned int flags, int nr_wake, int nr_requeue); ++ ++ asmlinkage long sys_nanosleep(struct __kernel_timespec __user *rqtp, ++ struct __kernel_timespec __user *rmtp); ++ asmlinkage long sys_nanosleep_time32(struct old_timespec32 __user *rqtp, ++ struct old_timespec32 __user *rmtp); ++ asmlinkage long sys_getitimer(int which, struct __kernel_old_itimerval __user *value); ++ asmlinkage long sys_setitimer(int which, ++ struct __kernel_old_itimerval __user *value, ++ struct __kernel_old_itimerval __user *ovalue); ++ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, ++ struct kexec_segment __user *segments, ++ unsigned long flags); ++ asmlinkage long sys_init_module(void __user *umod, unsigned long len, ++ const char __user *uargs); ++ asmlinkage long sys_delete_module(const char __user *name_user, ++ unsigned int flags); ++ asmlinkage long sys_timer_create(clockid_t which_clock, ++ struct sigevent __user *timer_event_spec, ++ timer_t __user * created_timer_id); ++ asmlinkage long sys_timer_gettime(timer_t timer_id, ++ struct __kernel_itimerspec __user *setting); ++ asmlinkage long sys_timer_getoverrun(timer_t timer_id); ++ asmlinkage long sys_timer_settime(timer_t timer_id, int flags, ++ const struct __kernel_itimerspec __user *new_setting, ++ struct __kernel_itimerspec __user *old_setting); ++ asmlinkage long sys_timer_delete(timer_t timer_id); ++ asmlinkage long sys_clock_settime(clockid_t which_clock, ++ const struct __kernel_timespec __user *tp); ++ asmlinkage long sys_clock_gettime(clockid_t which_clock, ++ struct __kernel_timespec __user *tp); ++ asmlinkage long sys_clock_getres(clockid_t which_clock, ++ struct __kernel_timespec __user *tp); ++ asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags, ++ const struct __kernel_timespec __user *rqtp, ++ struct __kernel_timespec __user *rmtp); ++ asmlinkage long sys_timer_gettime32(timer_t timer_id, ++ struct old_itimerspec32 __user *setting); ++ asmlinkage long sys_timer_settime32(timer_t timer_id, int flags, ++ struct old_itimerspec32 __user *new, ++ struct old_itimerspec32 __user *old); ++ asmlinkage long sys_clock_settime32(clockid_t which_clock, ++ struct old_timespec32 __user *tp); ++ asmlinkage long sys_clock_gettime32(clockid_t which_clock, ++ struct old_timespec32 __user *tp); ++ asmlinkage long sys_clock_getres_time32(clockid_t which_clock, ++ struct old_timespec32 __user *tp); ++ asmlinkage long sys_clock_nanosleep_time32(clockid_t which_clock, int flags, ++ struct old_timespec32 __user *rqtp, ++ struct old_timespec32 __user *rmtp); ++ asmlinkage long sys_syslog(int type, char __user *buf, int len); ++ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, ++ unsigned long data); ++ asmlinkage long sys_sched_setparam(pid_t pid, ++ struct sched_param __user *param); ++ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, ++ struct sched_param __user *param); ++ asmlinkage long sys_sched_getscheduler(pid_t pid); ++ asmlinkage long sys_sched_getparam(pid_t pid, ++ struct sched_param __user *param); ++ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, ++ unsigned long __user *user_mask_ptr); ++ asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, ++ unsigned long __user *user_mask_ptr); ++ asmlinkage long sys_sched_yield(void); ++ asmlinkage long sys_sched_get_priority_max(int policy); ++ asmlinkage long sys_sched_get_priority_min(int policy); ++ asmlinkage long sys_sched_rr_get_interval(pid_t pid, ++ struct __kernel_timespec __user *interval); ++ asmlinkage long sys_sched_rr_get_interval_time32(pid_t pid, ++ struct old_timespec32 __user *interval); ++ asmlinkage long sys_restart_syscall(void); ++ asmlinkage long sys_kill(pid_t pid, int sig); ++ asmlinkage long sys_tkill(pid_t pid, int sig); ++ asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig); ++ asmlinkage long sys_sigaltstack(const struct sigaltstack __user *uss, ++ struct sigaltstack __user *uoss); ++ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize); ++ #ifndef CONFIG_ODD_RT_SIGACTION ++ asmlinkage long sys_rt_sigaction(int, ++ const struct sigaction __user *, ++ struct sigaction __user *, ++ size_t); ++ #endif ++ asmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set, ++ sigset_t __user *oset, size_t sigsetsize); ++ asmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize); ++ asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese, ++ siginfo_t __user *uinfo, ++ const struct __kernel_timespec __user *uts, ++ size_t sigsetsize); ++ asmlinkage long sys_rt_sigtimedwait_time32(const sigset_t __user *uthese, ++ siginfo_t __user *uinfo, ++ const struct old_timespec32 __user *uts, ++ size_t sigsetsize); ++ asmlinkage long sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo); ++ asmlinkage long sys_setpriority(int which, int who, int niceval); ++ asmlinkage long sys_getpriority(int which, int who); ++ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, ++ void __user *arg); ++ asmlinkage long sys_setregid(gid_t rgid, gid_t egid); ++ asmlinkage long sys_setgid(gid_t gid); ++ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid); ++ asmlinkage long sys_setuid(uid_t uid); ++ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); ++ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid); ++ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); ++ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid); ++ asmlinkage long sys_setfsuid(uid_t uid); ++ asmlinkage long sys_setfsgid(gid_t gid); ++ asmlinkage long sys_times(struct tms __user *tbuf); ++ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid); ++ asmlinkage long sys_getpgid(pid_t pid); ++ asmlinkage long sys_getsid(pid_t pid); ++ asmlinkage long sys_setsid(void); ++ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist); ++ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist); ++ asmlinkage long sys_newuname(struct new_utsname __user *name); ++ asmlinkage long sys_sethostname(char __user *name, int len); ++ asmlinkage long sys_setdomainname(char __user *name, int len); ++ asmlinkage long sys_getrlimit(unsigned int resource, ++ struct rlimit __user *rlim); ++ asmlinkage long sys_setrlimit(unsigned int resource, ++ struct rlimit __user *rlim); ++ asmlinkage long sys_getrusage(int who, struct rusage __user *ru); ++ asmlinkage long sys_umask(int mask); ++ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, ++ unsigned long arg4, unsigned long arg5); ++ asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache); ++ asmlinkage long sys_gettimeofday(struct __kernel_old_timeval __user *tv, ++ struct timezone __user *tz); ++ asmlinkage long sys_settimeofday(struct __kernel_old_timeval __user *tv, ++ struct timezone __user *tz); ++ asmlinkage long sys_adjtimex(struct __kernel_timex __user *txc_p); ++ asmlinkage long sys_adjtimex_time32(struct old_timex32 __user *txc_p); ++ asmlinkage long sys_getpid(void); ++ asmlinkage long sys_getppid(void); ++ asmlinkage long sys_getuid(void); ++ asmlinkage long sys_geteuid(void); ++ asmlinkage long sys_getgid(void); ++ asmlinkage long sys_getegid(void); ++ asmlinkage long sys_gettid(void); ++ asmlinkage long sys_sysinfo(struct sysinfo __user *info); ++ asmlinkage long sys_mq_open(const char __user *name, int oflag, umode_t mode, struct mq_attr __user *attr); ++ asmlinkage long sys_mq_unlink(const char __user *name); ++ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec __user *abs_timeout); ++ asmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct __kernel_timespec __user *abs_timeout); ++ asmlinkage long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *notification); ++ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat); ++ asmlinkage long sys_mq_timedreceive_time32(mqd_t mqdes, ++ char __user *u_msg_ptr, ++ unsigned int msg_len, unsigned int __user *u_msg_prio, ++ const struct old_timespec32 __user *u_abs_timeout); ++ asmlinkage long sys_mq_timedsend_time32(mqd_t mqdes, ++ const char __user *u_msg_ptr, ++ unsigned int msg_len, unsigned int msg_prio, ++ const struct old_timespec32 __user *u_abs_timeout); ++ asmlinkage long sys_msgget(key_t key, int msgflg); ++ asmlinkage long sys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); ++ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); ++ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, ++ size_t msgsz, long msgtyp, int msgflg); ++ asmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp, ++ size_t msgsz, int msgflg); ++ asmlinkage long sys_semget(key_t key, int nsems, int semflg); ++ asmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg); ++ asmlinkage long sys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); ++ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops, ++ unsigned nsops, ++ const struct __kernel_timespec __user *timeout); ++ asmlinkage long sys_semtimedop_time32(int semid, struct sembuf __user *sops, ++ unsigned nsops, ++ const struct old_timespec32 __user *timeout); ++ asmlinkage long sys_semop(int semid, struct sembuf __user *sops, ++ unsigned nsops); ++ asmlinkage long sys_shmget(key_t key, size_t size, int flag); ++ asmlinkage long sys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); ++ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); ++ asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg); ++ asmlinkage long sys_shmdt(char __user *shmaddr); ++ asmlinkage long sys_socket(int, int, int); ++ asmlinkage long sys_socketpair(int, int, int, int __user *); ++ asmlinkage long sys_bind(int, struct sockaddr __user *, int); ++ asmlinkage long sys_listen(int, int); ++ asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); ++ asmlinkage long sys_connect(int, struct sockaddr __user *, int); ++ asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); ++ asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); ++ asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, ++ struct sockaddr __user *, int); ++ asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, ++ struct sockaddr __user *, int __user *); ++ asmlinkage long sys_setsockopt(int fd, int level, int optname, ++ char __user *optval, int optlen); ++ asmlinkage long sys_getsockopt(int fd, int level, int optname, ++ char __user *optval, int __user *optlen); ++ asmlinkage long sys_shutdown(int, int); ++ asmlinkage long sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags); ++ asmlinkage long sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags); ++ asmlinkage long sys_readahead(int fd, loff_t offset, size_t count); ++ asmlinkage long sys_brk(unsigned long brk); ++ asmlinkage long sys_munmap(unsigned long addr, size_t len); ++ asmlinkage long sys_mremap(unsigned long addr, ++ unsigned long old_len, unsigned long new_len, ++ unsigned long flags, unsigned long new_addr); ++ asmlinkage long sys_add_key(const char __user *_type, ++ const char __user *_description, ++ const void __user *_payload, ++ size_t plen, ++ key_serial_t destringid); ++ asmlinkage long sys_request_key(const char __user *_type, ++ const char __user *_description, ++ const char __user *_callout_info, ++ key_serial_t destringid); ++ asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, ++ unsigned long arg4, unsigned long arg5); ++ #ifdef CONFIG_CLONE_BACKWARDS ++ asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, unsigned long, ++ int __user *); ++ #else ++ #ifdef CONFIG_CLONE_BACKWARDS3 ++ asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *, ++ int __user *, unsigned long); ++ #else ++ asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, ++ int __user *, unsigned long); ++ #endif ++ #endif ++ ++ asmlinkage long sys_clone3(struct clone_args __user *uargs, size_t size); ++ ++ asmlinkage long sys_execve(const char __user *filename, ++ const char __user *const __user *argv, ++ const char __user *const __user *envp); ++ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); ++ ++ /* CONFIG_MMU only */ ++ asmlinkage long sys_swapon(const char __user *specialfile, int swap_flags); ++ asmlinkage long sys_swapoff(const char __user *specialfile); ++ asmlinkage long sys_mprotect(unsigned long start, size_t len, ++ unsigned long prot); ++ asmlinkage long sys_msync(unsigned long start, size_t len, int flags); ++ asmlinkage long sys_mlock(unsigned long start, size_t len); ++ asmlinkage long sys_munlock(unsigned long start, size_t len); ++ asmlinkage long sys_mlockall(int flags); ++ asmlinkage long sys_munlockall(void); ++ asmlinkage long sys_mincore(unsigned long start, size_t len, ++ unsigned char __user * vec); ++ asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); ++ asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec, ++ size_t vlen, int behavior, unsigned int flags); ++ asmlinkage long sys_process_mrelease(int pidfd, unsigned int flags); ++ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, ++ unsigned long prot, unsigned long pgoff, ++ unsigned long flags); ++ asmlinkage long sys_mseal(unsigned long start, size_t len, unsigned long flags); ++ asmlinkage long sys_mbind(unsigned long start, unsigned long len, ++ unsigned long mode, ++ const unsigned long __user *nmask, ++ unsigned long maxnode, ++ unsigned flags); ++ asmlinkage long sys_get_mempolicy(int __user *policy, ++ unsigned long __user *nmask, ++ unsigned long maxnode, ++ unsigned long addr, unsigned long flags); ++ asmlinkage long sys_set_mempolicy(int mode, const unsigned long __user *nmask, ++ unsigned long maxnode); ++ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, ++ const unsigned long __user *from, ++ const unsigned long __user *to); ++ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, ++ const void __user * __user *pages, ++ const int __user *nodes, ++ int __user *status, ++ int flags); ++ asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, ++ siginfo_t __user *uinfo); ++ asmlinkage long sys_perf_event_open( ++ struct perf_event_attr __user *attr_uptr, ++ pid_t pid, int cpu, int group_fd, unsigned long flags); ++ asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int); ++ asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg, ++ unsigned int vlen, unsigned flags, ++ struct __kernel_timespec __user *timeout); ++ asmlinkage long sys_recvmmsg_time32(int fd, struct mmsghdr __user *msg, ++ unsigned int vlen, unsigned flags, ++ struct old_timespec32 __user *timeout); ++ asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, ++ int options, struct rusage __user *ru); ++ asmlinkage long sys_prlimit64(pid_t pid, unsigned int resource, ++ const struct rlimit64 __user *new_rlim, ++ struct rlimit64 __user *old_rlim); ++ asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags); ++ #if defined(CONFIG_ARCH_SPLIT_ARG64) ++ asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, ++ unsigned int mask_1, unsigned int mask_2, ++ int dfd, const char __user * pathname); ++ #else ++ asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, ++ u64 mask, int fd, ++ const char __user *pathname); ++ #endif ++ asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name, ++ struct file_handle __user *handle, ++ void __user *mnt_id, int flag); ++ asmlinkage long sys_open_by_handle_at(int mountdirfd, ++ struct file_handle __user *handle, ++ int flags); ++ asmlinkage long sys_clock_adjtime(clockid_t which_clock, ++ struct __kernel_timex __user *tx); ++ asmlinkage long sys_clock_adjtime32(clockid_t which_clock, ++ struct old_timex32 __user *tx); ++ asmlinkage long sys_syncfs(int fd); ++ asmlinkage long sys_setns(int fd, int nstype); ++ asmlinkage long sys_pidfd_open(pid_t pid, unsigned int flags); ++ asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, ++ unsigned int vlen, unsigned flags); ++ asmlinkage long sys_process_vm_readv(pid_t pid, ++ const struct iovec __user *lvec, ++ unsigned long liovcnt, ++ const struct iovec __user *rvec, ++ unsigned long riovcnt, ++ unsigned long flags); ++ asmlinkage long sys_process_vm_writev(pid_t pid, ++ const struct iovec __user *lvec, ++ unsigned long liovcnt, ++ const struct iovec __user *rvec, ++ unsigned long riovcnt, ++ unsigned long flags); ++ asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, ++ unsigned long idx1, unsigned long idx2); ++ asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); ++ asmlinkage long sys_sched_setattr(pid_t pid, ++ struct sched_attr __user *attr, ++ unsigned int flags); ++ asmlinkage long sys_sched_getattr(pid_t pid, ++ struct sched_attr __user *attr, ++ unsigned int size, ++ unsigned int flags); ++ asmlinkage long sys_renameat2(int olddfd, const char __user *oldname, ++ int newdfd, const char __user *newname, ++ unsigned int flags); ++ asmlinkage long sys_seccomp(unsigned int op, unsigned int flags, ++ void __user *uargs); ++ asmlinkage long sys_getrandom(char __user *buf, size_t count, ++ unsigned int flags); ++ asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags); ++ asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int size); ++ asmlinkage long sys_execveat(int dfd, const char __user *filename, ++ const char __user *const __user *argv, ++ const char __user *const __user *envp, int flags); ++ asmlinkage long sys_userfaultfd(int flags); ++ asmlinkage long sys_membarrier(int cmd, unsigned int flags, int cpu_id); ++ asmlinkage long sys_mlock2(unsigned long start, size_t len, int flags); ++ asmlinkage long sys_copy_file_range(int fd_in, loff_t __user *off_in, ++ int fd_out, loff_t __user *off_out, ++ size_t len, unsigned int flags); ++ asmlinkage long sys_preadv2(unsigned long fd, const struct iovec __user *vec, ++ unsigned long vlen, unsigned long pos_l, unsigned long pos_h, ++ rwf_t flags); ++ asmlinkage long sys_pwritev2(unsigned long fd, const struct iovec __user *vec, ++ unsigned long vlen, unsigned long pos_l, unsigned long pos_h, ++ rwf_t flags); ++ asmlinkage long sys_pkey_mprotect(unsigned long start, size_t len, ++ unsigned long prot, int pkey); ++ asmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val); ++ asmlinkage long sys_pkey_free(int pkey); ++ asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, ++ unsigned mask, struct statx __user *buffer); ++ asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len, ++ int flags, uint32_t sig); ++ asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags); ++ asmlinkage long sys_move_mount(int from_dfd, const char __user *from_path, ++ int to_dfd, const char __user *to_path, ++ unsigned int ms_flags); ++ asmlinkage long sys_mount_setattr(int dfd, const char __user *path, ++ unsigned int flags, ++ struct mount_attr __user *uattr, size_t usize); ++ asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags); ++ asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, ++ const void __user *value, int aux); ++ asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags); ++ asmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags); ++ asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, ++ siginfo_t __user *info, ++ unsigned int flags); ++ asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags); ++ asmlinkage long sys_landlock_create_ruleset(const struct landlock_ruleset_attr __user *attr, ++ size_t size, __u32 flags); ++ asmlinkage long sys_landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type, ++ const void __user *rule_attr, __u32 flags); ++ asmlinkage long sys_landlock_restrict_self(int ruleset_fd, __u32 flags); ++ asmlinkage long sys_memfd_secret(unsigned int flags); ++ asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long len, ++ unsigned long home_node, ++ unsigned long flags); ++ asmlinkage long sys_cachestat(unsigned int fd, ++ struct cachestat_range __user *cstat_range, ++ struct cachestat __user *cstat, unsigned int flags); ++ asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); ++ asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, ++ u32 __user *size, u32 flags); ++ asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, ++ u32 size, u32 flags); ++ asmlinkage long sys_lsm_list_modules(u64 __user *ids, u32 __user *size, u32 flags); ++ ++ /* ++ * Architecture-specific system calls ++ */ ++ ++ /* x86 */ ++ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on); ++ ++ asmlinkage long sys_uretprobe(void); ++ ++ /* pciconfig: alpha, arm, arm64, ia64, sparc */ ++ asmlinkage long sys_pciconfig_read(unsigned long bus, unsigned long dfn, ++ unsigned long off, unsigned long len, ++ void __user *buf); ++ asmlinkage long sys_pciconfig_write(unsigned long bus, unsigned long dfn, ++ unsigned long off, unsigned long len, ++ void __user *buf); ++ asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn); ++ ++ /* powerpc */ ++ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, ++ __u32 __user *ustatus); ++ asmlinkage long sys_spu_create(const char __user *name, ++ unsigned int flags, umode_t mode, int fd); ++ ++ ++ /* ++ * Deprecated system calls which are still defined in ++ * include/uapi/asm-generic/unistd.h and wanted by >= 1 arch ++ */ ++ ++ /* __ARCH_WANT_SYSCALL_NO_AT */ ++ asmlinkage long sys_open(const char __user *filename, ++ int flags, umode_t mode); ++ asmlinkage long sys_link(const char __user *oldname, ++ const char __user *newname); ++ asmlinkage long sys_unlink(const char __user *pathname); ++ asmlinkage long sys_mknod(const char __user *filename, umode_t mode, ++ unsigned dev); ++ asmlinkage long sys_chmod(const char __user *filename, umode_t mode); ++ asmlinkage long sys_chown(const char __user *filename, ++ uid_t user, gid_t group); ++ asmlinkage long sys_mkdir(const char __user *pathname, umode_t mode); ++ asmlinkage long sys_rmdir(const char __user *pathname); ++ asmlinkage long sys_lchown(const char __user *filename, ++ uid_t user, gid_t group); ++ asmlinkage long sys_access(const char __user *filename, int mode); ++ asmlinkage long sys_rename(const char __user *oldname, ++ const char __user *newname); ++ asmlinkage long sys_symlink(const char __user *old, const char __user *new); ++ #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) ++ asmlinkage long sys_stat64(const char __user *filename, ++ struct stat64 __user *statbuf); ++ asmlinkage long sys_lstat64(const char __user *filename, ++ struct stat64 __user *statbuf); ++ #endif ++ ++ /* __ARCH_WANT_SYSCALL_NO_FLAGS */ ++ asmlinkage long sys_pipe(int __user *fildes); ++ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd); ++ asmlinkage long sys_epoll_create(int size); ++ asmlinkage long sys_inotify_init(void); ++ asmlinkage long sys_eventfd(unsigned int count); ++ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask); ++ ++ /* __ARCH_WANT_SYSCALL_OFF_T */ ++ asmlinkage long sys_sendfile(int out_fd, int in_fd, ++ off_t __user *offset, size_t count); ++ asmlinkage long sys_newstat(const char __user *filename, ++ struct stat __user *statbuf); ++ asmlinkage long sys_newlstat(const char __user *filename, ++ struct stat __user *statbuf); ++ asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice); ++ ++ /* __ARCH_WANT_SYSCALL_DEPRECATED */ ++ asmlinkage long sys_alarm(unsigned int seconds); ++ asmlinkage long sys_getpgrp(void); ++ asmlinkage long sys_pause(void); ++ asmlinkage long sys_time(__kernel_old_time_t __user *tloc); ++ asmlinkage long sys_time32(old_time32_t __user *tloc); ++ #ifdef __ARCH_WANT_SYS_UTIME ++ asmlinkage long sys_utime(char __user *filename, ++ struct utimbuf __user *times); ++ asmlinkage long sys_utimes(char __user *filename, ++ struct __kernel_old_timeval __user *utimes); ++ asmlinkage long sys_futimesat(int dfd, const char __user *filename, ++ struct __kernel_old_timeval __user *utimes); ++ #endif ++ asmlinkage long sys_futimesat_time32(unsigned int dfd, ++ const char __user *filename, ++ struct old_timeval32 __user *t); ++ asmlinkage long sys_utime32(const char __user *filename, ++ struct old_utimbuf32 __user *t); ++ asmlinkage long sys_utimes_time32(const char __user *filename, ++ struct old_timeval32 __user *t); ++ asmlinkage long sys_creat(const char __user *pathname, umode_t mode); ++ asmlinkage long sys_getdents(unsigned int fd, ++ struct linux_dirent __user *dirent, ++ unsigned int count); ++ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, ++ fd_set __user *exp, struct __kernel_old_timeval __user *tvp); ++ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, ++ int timeout); ++ asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, ++ int maxevents, int timeout); ++ asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf); ++ asmlinkage long sys_vfork(void); ++ asmlinkage long sys_recv(int, void __user *, size_t, unsigned); ++ asmlinkage long sys_send(int, void __user *, size_t, unsigned); ++ asmlinkage long sys_oldumount(char __user *name); ++ asmlinkage long sys_uselib(const char __user *library); ++ asmlinkage long sys_sysfs(int option, ++ unsigned long arg1, unsigned long arg2); ++ asmlinkage long sys_fork(void); ++ ++ /* obsolete */ ++ asmlinkage long sys_stime(__kernel_old_time_t __user *tptr); ++ asmlinkage long sys_stime32(old_time32_t __user *tptr); ++ ++ /* obsolete */ ++ asmlinkage long sys_sigpending(old_sigset_t __user *uset); ++ asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set, ++ old_sigset_t __user *oset); ++ #ifdef CONFIG_OLD_SIGSUSPEND ++ asmlinkage long sys_sigsuspend(old_sigset_t mask); ++ #endif ++ ++ #ifdef CONFIG_OLD_SIGSUSPEND3 ++ asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask); ++ #endif ++ ++ #ifdef CONFIG_OLD_SIGACTION ++ asmlinkage long sys_sigaction(int, const struct old_sigaction __user *, ++ struct old_sigaction __user *); ++ #endif ++ asmlinkage long sys_sgetmask(void); ++ asmlinkage long sys_ssetmask(int newmask); ++ asmlinkage long sys_signal(int sig, __sighandler_t handler); ++ ++ /* obsolete */ ++ asmlinkage long sys_nice(int increment); ++ ++ /* obsolete */ ++ asmlinkage long sys_kexec_file_load(int kernel_fd, int initrd_fd, ++ unsigned long cmdline_len, ++ const char __user *cmdline_ptr, ++ unsigned long flags); ++ ++ /* obsolete */ ++ asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options); ++ ++ /* obsolete */ ++ #ifdef CONFIG_HAVE_UID16 ++ asmlinkage long sys_chown16(const char __user *filename, ++ old_uid_t user, old_gid_t group); ++ asmlinkage long sys_lchown16(const char __user *filename, ++ old_uid_t user, old_gid_t group); ++ asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group); ++ asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid); ++ asmlinkage long sys_setgid16(old_gid_t gid); ++ asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid); ++ asmlinkage long sys_setuid16(old_uid_t uid); ++ asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid); ++ asmlinkage long sys_getresuid16(old_uid_t __user *ruid, ++ old_uid_t __user *euid, old_uid_t __user *suid); ++ asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid); ++ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, ++ old_gid_t __user *egid, old_gid_t __user *sgid); ++ asmlinkage long sys_setfsuid16(old_uid_t uid); ++ asmlinkage long sys_setfsgid16(old_gid_t gid); ++ asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist); ++ asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist); ++ asmlinkage long sys_getuid16(void); ++ asmlinkage long sys_geteuid16(void); ++ asmlinkage long sys_getgid16(void); ++ asmlinkage long sys_getegid16(void); ++ #endif ++ ++ /* obsolete */ ++ asmlinkage long sys_socketcall(int call, unsigned long __user *args); ++ ++ /* obsolete */ ++ asmlinkage long sys_stat(const char __user *filename, ++ struct __old_kernel_stat __user *statbuf); ++ asmlinkage long sys_lstat(const char __user *filename, ++ struct __old_kernel_stat __user *statbuf); ++ asmlinkage long sys_fstat(unsigned int fd, ++ struct __old_kernel_stat __user *statbuf); ++ asmlinkage long sys_readlink(const char __user *path, ++ char __user *buf, int bufsiz); ++ ++ /* obsolete */ ++ asmlinkage long sys_old_select(struct sel_arg_struct __user *arg); ++ ++ /* obsolete */ ++ asmlinkage long sys_old_readdir(unsigned int, struct old_linux_dirent __user *, unsigned int); ++ ++ /* obsolete */ ++ asmlinkage long sys_gethostname(char __user *name, int len); ++ asmlinkage long sys_uname(struct old_utsname __user *); ++ asmlinkage long sys_olduname(struct oldold_utsname __user *); ++ #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT ++ asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim); ++ #endif ++ ++ /* obsolete */ ++ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, ++ unsigned long third, void __user *ptr, long fifth); ++ ++ /* obsolete */ ++ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, ++ unsigned long prot, unsigned long flags, ++ unsigned long fd, unsigned long pgoff); ++ asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg); ++ ++ ++ /* ++ * Not a real system call, but a placeholder for syscalls which are ++ * not implemented -- see kernel/sys_ni.c ++ */ ++ asmlinkage long sys_ni_syscall(void); ++ ++ #endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ ++ ++ asmlinkage long sys_ni_posix_timers(void); ++ ++ /* ++ * Kernel code should not call syscalls (i.e., sys_xyzyyz()) directly. ++ * Instead, use one of the functions which work equivalently, such as ++ * the ksys_xyzyyz() functions prototyped below. ++ */ ++ ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); ++ int ksys_fchown(unsigned int fd, uid_t user, gid_t group); ++ ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count); ++ void ksys_sync(void); ++ int ksys_unshare(unsigned long unshare_flags); ++ int ksys_setsid(void); ++ int ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes, ++ unsigned int flags); ++ ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count, ++ loff_t pos); ++ ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf, ++ size_t count, loff_t pos); ++ int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len); ++ #ifdef CONFIG_ADVISE_SYSCALLS ++ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); ++ #else ++ static inline int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, ++ int advice) ++ { ++ return -EINVAL; ++ } ++ #endif ++ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, ++ unsigned long prot, unsigned long flags, ++ unsigned long fd, unsigned long pgoff); ++ ssize_t ksys_readahead(int fd, loff_t offset, size_t count); ++ int ksys_ipc(unsigned int call, int first, unsigned long second, ++ unsigned long third, void __user * ptr, long fifth); ++ int compat_ksys_ipc(u32 call, int first, int second, ++ u32 third, u32 ptr, u32 fifth); ++ ++ /* ++ * The following kernel syscall equivalents are just wrappers to fs-internal ++ * functions. Therefore, provide stubs to be inlined at the callsites. ++ */ ++ extern int do_fchownat(int dfd, const char __user *filename, uid_t user, ++ gid_t group, int flag); ++ ++ static inline long ksys_chown(const char __user *filename, uid_t user, ++ gid_t group) ++ { ++ return do_fchownat(AT_FDCWD, filename, user, group, 0); ++ } ++ ++ static inline long ksys_lchown(const char __user *filename, uid_t user, ++ gid_t group) ++ { ++ return do_fchownat(AT_FDCWD, filename, user, group, ++ AT_SYMLINK_NOFOLLOW); ++ } ++ ++ extern long do_sys_ftruncate(unsigned int fd, loff_t length, int small); ++ ++ static inline long ksys_ftruncate(unsigned int fd, loff_t length) ++ { ++ return do_sys_ftruncate(fd, length, 1); ++ } ++ ++ extern long do_sys_truncate(const char __user *pathname, loff_t length); ++ ++ static inline long ksys_truncate(const char __user *pathname, loff_t length) ++ { ++ return do_sys_truncate(pathname, length); ++ } ++ ++ static inline unsigned int ksys_personality(unsigned int personality) ++ { ++ unsigned int old = current->personality; ++ ++ if (personality != 0xffffffff) ++ set_personality(personality); ++ ++ return old; ++ } ++ ++ /* for __ARCH_WANT_SYS_IPC */ ++ long ksys_semtimedop(int semid, struct sembuf __user *tsops, ++ unsigned int nsops, ++ const struct __kernel_timespec __user *timeout); ++ long ksys_semget(key_t key, int nsems, int semflg); ++ long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); ++ long ksys_msgget(key_t key, int msgflg); ++ long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); ++ long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, ++ long msgtyp, int msgflg); ++ long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, ++ int msgflg); ++ long ksys_shmget(key_t key, size_t size, int shmflg); ++ long ksys_shmdt(char __user *shmaddr); ++ long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); ++ long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, ++ unsigned int nsops, ++ const struct old_timespec32 __user *timeout); ++ long __do_semtimedop(int semid, struct sembuf *tsems, unsigned int nsops, ++ const struct timespec64 *timeout, ++ struct ipc_namespace *ns); ++ ++ int __sys_getsockopt(int fd, int level, int optname, char __user *optval, ++ int __user *optlen); ++ int __sys_setsockopt(int fd, int level, int optname, char __user *optval, ++ int optlen); ++ #endif +\ No newline at end of file diff --git a/patches/6.13/0020-syscall_wrapper-add-x86-support.patch b/patches/6.13/0020-syscall_wrapper-add-x86-support.patch new file mode 100644 index 0000000..0ff322f --- /dev/null +++ b/patches/6.13/0020-syscall_wrapper-add-x86-support.patch @@ -0,0 +1,152 @@ +From 7320d35c161e6f562f0d3bb7a924e23010d1d6c1 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:23:18 -0400 +Subject: [PATCH 20/37] syscall_wrapper: add x86 support + +--- + arch/x86/include/asm/syscall_wrapper.h | 101 +++++++++++++++++++++++-- + 1 file changed, 94 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h +index 7e88705e90..341f635fa6 100644 +--- a/arch/x86/include/asm/syscall_wrapper.h ++++ b/arch/x86/include/asm/syscall_wrapper.h +@@ -192,21 +192,64 @@ extern long __ia32_sys_ni_syscall(const struct pt_regs *regs); + * of them. + */ + #define COMPAT_SYSCALL_DEFINE0(name) \ +- static long \ +- __do_compat_sys_##name(const struct pt_regs *__unused); \ ++ static inline long ___do_compat_sys_##name(const struct pt_regs *__unused); \ ++ static long __do_compat_sys_##name(const struct pt_regs *__unused);\ + __IA32_COMPAT_SYS_STUB0(name) \ + __X32_COMPAT_SYS_STUB0(name) \ +- static long \ +- __do_compat_sys_##name(const struct pt_regs *__unused) ++ static long __do_compat_sys_##name(const struct pt_regs *__unused) \ ++ { \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(name), &skip_ret, 0, \ ++ args_ptr_array, NULL); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = ___do_compat_sys_##name(__unused); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(name), ret, 0, args_ptr_array); \ ++ } \ ++ return ret; \ ++ } \ ++ static inline long ___do_compat_sys_##name(const struct pt_regs *__unused) + + #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ + static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ ++ void __igloo_set_args_compat##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args_compat##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); } \ + __IA32_COMPAT_SYS_STUBx(x, name, __VA_ARGS__) \ + __X32_COMPAT_SYS_STUBx(x, name, __VA_ARGS__) \ + static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ +- return __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(name), &skip_ret, x, \ ++ args_ptr_array, __igloo_set_args_compat##name); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(name), ret, x, args_ptr_array); \ ++ } \ ++ return ret; \ + } \ + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + +@@ -223,11 +266,32 @@ extern long __ia32_sys_ni_syscall(const struct pt_regs *regs); + #define __SYSCALL_DEFINEx(x, name, ...) \ + static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); } \ + __X64_SYS_STUBx(x, name, __VA_ARGS__) \ + __IA32_SYS_STUBx(x, name, __VA_ARGS__) \ + static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ +- long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(name), &skip_ret, x, \ ++ args_ptr_array, __igloo_set_args##name); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(name), ret, x, args_ptr_array); \ ++ } \ + __MAP(x,__SC_TEST,__VA_ARGS__); \ + __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ + return ret; \ +@@ -243,10 +307,33 @@ extern long __ia32_sys_ni_syscall(const struct pt_regs *regs); + */ + #define SYSCALL_DEFINE0(sname) \ + SYSCALL_METADATA(_##sname, 0); \ ++ static inline long ___do_sys_##sname(const struct pt_regs *__unused); \ + static long __do_sys_##sname(const struct pt_regs *__unused); \ + __X64_SYS_STUB0(sname) \ + __IA32_SYS_STUB0(sname) \ +- static long __do_sys_##sname(const struct pt_regs *__unused) ++ static long __do_sys_##sname(const struct pt_regs *__unused) \ ++ { \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(sname), &skip_ret, 0, \ ++ args_ptr_array, NULL); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = ___do_sys_##sname(__unused); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(sname), ret, 0, args_ptr_array); \ ++ } \ ++ return ret; \ ++ } \ ++ static inline long ___do_sys_##sname(const struct pt_regs *__unused) + + #define COND_SYSCALL(name) \ + __X64_COND_SYSCALL(name) \ diff --git a/patches/6.13/0021-syscall_wrapper.h-add-arm64-support.patch b/patches/6.13/0021-syscall_wrapper.h-add-arm64-support.patch new file mode 100644 index 0000000..a20e425 --- /dev/null +++ b/patches/6.13/0021-syscall_wrapper.h-add-arm64-support.patch @@ -0,0 +1,169 @@ +From 249761eb3875931ac67b6f9bd847692ba3c5fd63 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:24:00 -0400 +Subject: [PATCH 21/37] syscall_wrapper.h: add arm64 support + +--- + arch/arm64/include/asm/syscall_wrapper.h | 108 +++++++++++++++++++++-- + 1 file changed, 102 insertions(+), 6 deletions(-) + +diff --git a/arch/arm64/include/asm/syscall_wrapper.h b/arch/arm64/include/asm/syscall_wrapper.h +index abb57bc543..943a10213e 100644 +--- a/arch/arm64/include/asm/syscall_wrapper.h ++++ b/arch/arm64/include/asm/syscall_wrapper.h +@@ -9,6 +9,13 @@ + #define __ASM_SYSCALL_WRAPPER_H + + #include ++// === Igloo Interception Support === ++#include ++ ++#ifdef CONFIG_IGLOO ++extern igloo_syscall_enter_t igloo_syscall_enter_hook; ++extern igloo_syscall_return_t igloo_syscall_return_hook; ++#endif + + #define SC_ARM64_REGS_TO_ARGS(x, ...) \ + __MAP(x,__SC_ARGS \ +@@ -20,6 +27,9 @@ + #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ + asmlinkage long __arm64_compat_sys##name(const struct pt_regs *regs); \ + ALLOW_ERROR_INJECTION(__arm64_compat_sys##name, ERRNO); \ ++ void __igloo_set_args_compat##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args_compat##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); } \ + static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ + asmlinkage long __arm64_compat_sys##name(const struct pt_regs *regs) \ +@@ -28,14 +38,56 @@ + } \ + static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ +- return __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(name), &skip_ret, x, \ ++ args_ptr_array, __igloo_set_args_compat##name); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(name), ret, x, args_ptr_array); \ ++ } \ ++ return ret; \ + } \ + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + + #define COMPAT_SYSCALL_DEFINE0(sname) \ +- asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused); \ ++ asmlinkage inline long ___arm64_compat_sys_##sname(const struct pt_regs *__unused); \ + ALLOW_ERROR_INJECTION(__arm64_compat_sys_##sname, ERRNO); \ +- asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused) ++ asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused);\ ++ asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused) \ ++ { \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(sname), &skip_ret, 0, \ ++ args_ptr_array, NULL); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = ___arm64_compat_sys_##sname(__unused); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(sname), ret, 0, args_ptr_array); \ ++ } \ ++ return ret; \ ++ } \ ++ asmlinkage inline long ___arm64_compat_sys_##sname(const struct pt_regs *__unused) + + #define COND_SYSCALL_COMPAT(name) \ + asmlinkage long __arm64_compat_sys_##name(const struct pt_regs *regs); \ +@@ -49,6 +101,9 @@ + #define __SYSCALL_DEFINEx(x, name, ...) \ + asmlinkage long __arm64_sys##name(const struct pt_regs *regs); \ + ALLOW_ERROR_INJECTION(__arm64_sys##name, ERRNO); \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); } \ + static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ + asmlinkage long __arm64_sys##name(const struct pt_regs *regs) \ +@@ -57,7 +112,25 @@ + } \ + static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ +- long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(name), &skip_ret, x, \ ++ args_ptr_array, __igloo_set_args##name); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(name), ret, x, args_ptr_array); \ ++ } \ + __MAP(x,__SC_TEST,__VA_ARGS__); \ + __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ + return ret; \ +@@ -66,9 +139,32 @@ + + #define SYSCALL_DEFINE0(sname) \ + SYSCALL_METADATA(_##sname, 0); \ +- asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused); \ ++ asmlinkage inline long ___arm64_sys_##sname(const struct pt_regs *__unused); \ + ALLOW_ERROR_INJECTION(__arm64_sys_##sname, ERRNO); \ +- asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused) ++ asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused);\ ++ asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused) \ ++ { \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(sname), &skip_ret, 0, \ ++ args_ptr_array, NULL); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = ___arm64_sys_##sname(__unused); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(sname), ret, 0, args_ptr_array); \ ++ } \ ++ return ret; \ ++ } \ ++ asmlinkage inline long ___arm64_sys_##sname(const struct pt_regs *__unused) + + #define COND_SYSCALL(name) \ + asmlinkage long __arm64_sys_##name(const struct pt_regs *regs); \ diff --git a/patches/6.13/0022-syscall_wrapper.h-add-riscv-support.patch b/patches/6.13/0022-syscall_wrapper.h-add-riscv-support.patch new file mode 100644 index 0000000..b3783a1 --- /dev/null +++ b/patches/6.13/0022-syscall_wrapper.h-add-riscv-support.patch @@ -0,0 +1,166 @@ +From 23f42b21b0638b85f0dd27a369cb23ae55084e73 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:24:36 -0400 +Subject: [PATCH 22/37] syscall_wrapper.h: add riscv support + +--- + arch/riscv/include/asm/syscall_wrapper.h | 109 +++++++++++++++++++++-- + 1 file changed, 103 insertions(+), 6 deletions(-) + +diff --git a/arch/riscv/include/asm/syscall_wrapper.h b/arch/riscv/include/asm/syscall_wrapper.h +index ac80216549..01393a6574 100644 +--- a/arch/riscv/include/asm/syscall_wrapper.h ++++ b/arch/riscv/include/asm/syscall_wrapper.h +@@ -10,6 +10,14 @@ + + #include + ++// === Igloo Interception Support === ++#include ++ ++#ifdef CONFIG_IGLOO ++extern igloo_syscall_enter_t igloo_syscall_enter_hook; ++extern igloo_syscall_return_t igloo_syscall_return_hook; ++#endif ++ + asmlinkage long __riscv_sys_ni_syscall(const struct pt_regs *); + + #ifdef CONFIG_64BIT +@@ -50,10 +58,32 @@ asmlinkage long __riscv_sys_ni_syscall(const struct pt_regs *); + #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ + asmlinkage long __riscv_compat_sys##name(const struct pt_regs *regs); \ + ALLOW_ERROR_INJECTION(__riscv_compat_sys##name, ERRNO); \ ++ void __igloo_set_args_compat##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args_compat##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); } \ + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ + __SYSCALL_SE_DEFINEx(x, compat_sys, name, __VA_ARGS__) \ + { \ +- return __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(name), &skip_ret, x, \ ++ args_ptr_array, __igloo_set_args_compat##name); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(name), ret, x, args_ptr_array); \ ++ } \ ++ return ret; \ + } \ + asmlinkage long __riscv_compat_sys##name(const struct pt_regs *regs) \ + { \ +@@ -62,9 +92,32 @@ asmlinkage long __riscv_sys_ni_syscall(const struct pt_regs *); + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + + #define COMPAT_SYSCALL_DEFINE0(sname) \ +- asmlinkage long __riscv_compat_sys_##sname(const struct pt_regs *__unused); \ ++ asmlinkage inline long ___riscv_compat_sys_##sname(const struct pt_regs *__unused); \ + ALLOW_ERROR_INJECTION(__riscv_compat_sys_##sname, ERRNO); \ +- asmlinkage long __riscv_compat_sys_##sname(const struct pt_regs *__unused) ++ asmlinkage long __riscv_compat_sys_##sname(const struct pt_regs *__unused); \ ++ asmlinkage long __riscv_compat_sys_##sname(const struct pt_regs *__unused) \ ++ { \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(sname), &skip_ret, 0, \ ++ args_ptr_array, NULL); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = ___riscv_compat_sys_##sname(__unused); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(sname), ret, 0, args_ptr_array); \ ++ } \ ++ return ret; \ ++ } \ ++ asmlinkage inline long ___riscv_compat_sys_##sname(const struct pt_regs *__unused) + + #define COND_SYSCALL_COMPAT(name) \ + asmlinkage long __weak __riscv_compat_sys_##name(const struct pt_regs *regs); \ +@@ -78,11 +131,32 @@ asmlinkage long __riscv_sys_ni_syscall(const struct pt_regs *); + #define __SYSCALL_DEFINEx(x, name, ...) \ + asmlinkage long __riscv_sys##name(const struct pt_regs *regs); \ + ALLOW_ERROR_INJECTION(__riscv_sys##name, ERRNO); \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); } \ + static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ + __SYSCALL_SE_DEFINEx(x, sys, name, __VA_ARGS__) \ + { \ +- long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(name), &skip_ret, x, \ ++ args_ptr_array, __igloo_set_args##name); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ ++ } \ + __MAP(x,__SC_TEST,__VA_ARGS__); \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(name), ret, x, args_ptr_array); \ ++ } \ + __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ + return ret; \ + } \ +@@ -94,9 +168,32 @@ asmlinkage long __riscv_sys_ni_syscall(const struct pt_regs *); + + #define SYSCALL_DEFINE0(sname) \ + SYSCALL_METADATA(_##sname, 0); \ +- asmlinkage long __riscv_sys_##sname(const struct pt_regs *__unused); \ ++ asmlinkage inline long ___riscv_sys_##sname(const struct pt_regs *__unused); \ + ALLOW_ERROR_INJECTION(__riscv_sys_##sname, ERRNO); \ +- asmlinkage long __riscv_sys_##sname(const struct pt_regs *__unused) ++ asmlinkage long __riscv_sys_##sname(const struct pt_regs *__unused);\ ++ asmlinkage long __riscv_sys_##sname(const struct pt_regs *__unused) \ ++ { \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook(__stringify(sname), &skip_ret, 0, \ ++ args_ptr_array, NULL); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = ___riscv_sys_##sname(__unused); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(__stringify(sname), ret, 0, args_ptr_array); \ ++ } \ ++ return ret; \ ++ } \ ++ asmlinkage inline long ___riscv_sys_##sname(const struct pt_regs *__unused) + + #define COND_SYSCALL(name) \ + asmlinkage long __weak __riscv_sys_##name(const struct pt_regs *regs); \ diff --git a/patches/6.13/0023-binfmt_elf.c-add-igloo_task_size-support.patch b/patches/6.13/0023-binfmt_elf.c-add-igloo_task_size-support.patch new file mode 100644 index 0000000..3efb6c7 --- /dev/null +++ b/patches/6.13/0023-binfmt_elf.c-add-igloo_task_size-support.patch @@ -0,0 +1,42 @@ +From 1589ba3d2809d326412cfe5fe963f9c05529a535 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:29:33 -0400 +Subject: [PATCH 23/37] binfmt_elf.c: add igloo_task_size support + +--- + fs/binfmt_elf.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 106f0e8af1..b3d0003ccb 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + + #ifndef ELF_COMPAT + #define ELF_COMPAT 0 +@@ -1017,8 +1018,19 @@ static int load_elf_binary(struct linux_binprm *bprm) + + /* Do this so that we can load the interpreter, if need be. We will + change some of these later */ ++ #ifdef CONFIG_IGLOO ++ //Begin for igloo: if we moved the stack, we have to move mmap ++ if(igloo_task_size) { ++ retval = setup_arg_pages(bprm, randomize_stack_top(igloo_task_size), ++ executable_stack); ++ } else { ++ retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), ++ executable_stack); ++ } ++ #else + retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), +- executable_stack); ++ executable_stack); ++ #endif + if (retval < 0) + goto out_free_dentry; + diff --git a/patches/6.13/0024-compat.h-syscalls-support.patch b/patches/6.13/0024-compat.h-syscalls-support.patch new file mode 100644 index 0000000..75b85b7 --- /dev/null +++ b/patches/6.13/0024-compat.h-syscalls-support.patch @@ -0,0 +1,93 @@ +From 0e1b11774302462f841142fb9dc261dcbd12e180 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:31:18 -0400 +Subject: [PATCH 24/37] compat.h: syscalls support + +--- + include/linux/compat.h | 67 ++++++++++++++++++++++++++++++++---------- + 1 file changed, 52 insertions(+), 15 deletions(-) + +diff --git a/include/linux/compat.h b/include/linux/compat.h +index 56cebaff0c..5121820555 100644 +--- a/include/linux/compat.h ++++ b/include/linux/compat.h +@@ -62,27 +62,64 @@ + #define COMPAT_SYSCALL_DEFINE6(name, ...) \ + COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) + ++ ++// === Igloo Interception Support === ++#include ++ ++#ifdef CONFIG_IGLOO ++extern igloo_syscall_enter_t igloo_syscall_enter_hook; ++extern igloo_syscall_return_t igloo_syscall_return_hook; ++#endif ++ + /* + * The asmlinkage stub is aliased to a function named __se_compat_sys_*() which + * sign-extends 32-bit ints to longs whenever needed. The actual work is + * done within __do_compat_sys_*(). + */ + #ifndef COMPAT_SYSCALL_DEFINEx +-#define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ +- __diag_push(); \ +- __diag_ignore(GCC, 8, "-Wattribute-alias", \ +- "Type aliasing is used to sanitize syscall arguments");\ +- asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ +- __attribute__((alias(__stringify(__se_compat_sys##name)))); \ +- ALLOW_ERROR_INJECTION(compat_sys##name, ERRNO); \ +- static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ +- asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ +- asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ +- { \ +- long ret = __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\ +- __MAP(x,__SC_TEST,__VA_ARGS__); \ +- return ret; \ +- } \ ++#define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ ++ __diag_push(); \ ++ __diag_ignore(GCC, 8, "-Wattribute-alias", \ ++ "Type aliasing is used to sanitize syscall arguments"); \ ++ asmlinkage long compat_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__)) \ ++ __attribute__((alias(__stringify(__se_compat_sys##name)))); \ ++ ALLOW_ERROR_INJECTION(compat_sys##name, ERRNO); \ ++ void __igloo_set_args_compat##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ ++ void __igloo_set_args_compat##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ ++ { __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); } \ ++ static inline long __do_compat_sys##name( \ ++ __MAP(x, __SC_DECL, __VA_ARGS__)); \ ++ asmlinkage long __se_compat_sys##name( \ ++ __MAP(x, __SC_LONG, __VA_ARGS__)); \ ++ asmlinkage long __se_compat_sys##name( \ ++ __MAP(x, __SC_LONG, __VA_ARGS__)) \ ++ { \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ unsigned long args_ptr_array[IGLOO_SYSCALL_MAXARGS] = { 0 }; \ ++ __SC_ASSIGN_ADDR_WRAPPER(x, args_ptr_array, __VA_ARGS__); \ ++ /* Igloo enter hook */ \ ++ if (igloo_syscall_enter_hook) { \ ++ skip = igloo_syscall_enter_hook( \ ++ __stringify(name), &skip_ret, x, \ ++ args_ptr_array, \ ++ __igloo_set_args_compat##name); \ ++ } \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_compat_sys##name( \ ++ __MAP(x, __SC_DELOUSE, __VA_ARGS__)); \ ++ } \ ++ /* Igloo return hook */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook( \ ++ __stringify(name), ret, x, args_ptr_array); \ ++ } \ ++ __MAP(x,__SC_TEST, __VA_ARGS__); \ ++ return ret; \ ++} \ + __diag_pop(); \ + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + #endif /* COMPAT_SYSCALL_DEFINEx */ diff --git a/patches/6.13/0025-compat.h-add-define0.patch b/patches/6.13/0025-compat.h-add-define0.patch new file mode 100644 index 0000000..02e23a0 --- /dev/null +++ b/patches/6.13/0025-compat.h-add-define0.patch @@ -0,0 +1,79 @@ +From eb4971ad09ede9ff4f669fa6a692e58e9c9a05b2 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 19 Sep 2025 16:57:21 -0400 +Subject: [PATCH 25/37] compat.h: add define0 + +--- + include/linux/compat.h | 48 +++++++++++++++++++++++++++++++++--------- + 1 file changed, 38 insertions(+), 10 deletions(-) + +diff --git a/include/linux/compat.h b/include/linux/compat.h +index 5121820555..c9df1bacd8 100644 +--- a/include/linux/compat.h ++++ b/include/linux/compat.h +@@ -42,11 +42,48 @@ + #define __SC_DELOUSE(t,v) ((__force t)(unsigned long)(v)) + #endif + ++ ++// === Igloo Interception Support === ++#include ++ ++#ifdef CONFIG_IGLOO ++extern igloo_syscall_enter_t igloo_syscall_enter_hook; ++extern igloo_syscall_return_t igloo_syscall_return_hook; ++#endif ++ + #ifndef COMPAT_SYSCALL_DEFINE0 + #define COMPAT_SYSCALL_DEFINE0(name) \ + asmlinkage long compat_sys_##name(void); \ + ALLOW_ERROR_INJECTION(compat_sys_##name, ERRNO); \ +- asmlinkage long compat_sys_##name(void) ++ asmlinkage long compat_sys_##name(void) \ ++ { \ ++ const char *syscall_basename = __stringify(name); /* Base name */ \ ++ long ret; \ ++ bool skip = false; \ ++ long skip_ret = 0; \ ++ /* Array for arguments (empty for 0 args) */ \ ++ unsigned long args_array[IGLOO_SYSCALL_MAXARGS] = {0}; \ ++ /* === Igloo Enter Hook === */ \ ++ if (igloo_syscall_enter_hook) { \ ++ /* Pass NULL for setter func for 0-arg syscalls */ \ ++ skip = igloo_syscall_enter_hook(syscall_basename, &skip_ret, 0, args_array, NULL); \ ++ } \ ++ \ ++ if (skip) { \ ++ ret = skip_ret; \ ++ } else { \ ++ ret = __do_compat_sys_##name(); \ ++ } \ ++ \ ++ /* === Igloo Return Hook === */ \ ++ if (igloo_syscall_return_hook) { \ ++ ret = igloo_syscall_return_hook(syscall_basename, ret, 0, args_array); \ ++ } \ ++ \ ++ return ret ; \ ++ } \ ++ static inline long __do_compat_sys_##name(void) ++ + #endif /* COMPAT_SYSCALL_DEFINE0 */ + + #define COMPAT_SYSCALL_DEFINE1(name, ...) \ +@@ -62,15 +99,6 @@ + #define COMPAT_SYSCALL_DEFINE6(name, ...) \ + COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) + +- +-// === Igloo Interception Support === +-#include +- +-#ifdef CONFIG_IGLOO +-extern igloo_syscall_enter_t igloo_syscall_enter_hook; +-extern igloo_syscall_return_t igloo_syscall_return_hook; +-#endif +- + /* + * The asmlinkage stub is aliased to a function named __se_compat_sys_*() which + * sign-extends 32-bit ints to longs whenever needed. The actual work is diff --git a/patches/6.13/0026-igloo_weaksyms-fix-up-igloo_ioctl-type.patch b/patches/6.13/0026-igloo_weaksyms-fix-up-igloo_ioctl-type.patch new file mode 100644 index 0000000..0ccab2a --- /dev/null +++ b/patches/6.13/0026-igloo_weaksyms-fix-up-igloo_ioctl-type.patch @@ -0,0 +1,28 @@ +From 4799b41002283a8608f919dd775d2945839ff168 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 22 Sep 2025 10:58:40 -0400 +Subject: [PATCH 26/37] igloo_weaksyms: fix up igloo_ioctl type + +--- + drivers/igloobase/igloo_weaksyms.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/igloobase/igloo_weaksyms.c b/drivers/igloobase/igloo_weaksyms.c +index 8498d15500..33e83342d2 100644 +--- a/drivers/igloobase/igloo_weaksyms.c ++++ b/drivers/igloobase/igloo_weaksyms.c +@@ -75,12 +75,12 @@ void igloo_hc_open(int dfd, const char __user *filename, struct open_how *how) + } + EXPORT_SYMBOL(igloo_hc_open); + +-void (*igloo_ioctl_module)(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp); ++void (*igloo_ioctl_module)(int error, struct file *filp, unsigned int cmd); + void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp); + void igloo_ioctl(int error, struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) + { + if (igloo_ioctl_module) { +- igloo_ioctl_module(error, inode, filp, cmd, argp); ++ igloo_ioctl_module(error, filp, cmd); + } else { + // printk(KERN_EMERG "igloo_ioctl: unimplemented\n"); + } diff --git a/patches/6.13/0028-socket.c-add-CONFIG_IGLOO.patch b/patches/6.13/0028-socket.c-add-CONFIG_IGLOO.patch new file mode 100644 index 0000000..beff637 --- /dev/null +++ b/patches/6.13/0028-socket.c-add-CONFIG_IGLOO.patch @@ -0,0 +1,52 @@ +From 0c2a6e83a8a90559251c0f559d0400eaa3eb2ada Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Mon, 22 Sep 2025 11:01:31 -0400 +Subject: [PATCH 28/37] socket.c: add CONFIG_IGLOO + +--- + net/socket.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/socket.c b/net/socket.c +index b69372eef4..a3c64a8773 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -628,13 +628,17 @@ struct socket *sock_alloc(void) + } + EXPORT_SYMBOL(sock_alloc); + ++#ifdef CONFIG_IGLOO + // forward declare igloo_sock_release + void igloo_sock_release(struct socket *sock); ++#endif + + static void __sock_release(struct socket *sock, struct inode *inode) + { + const struct proto_ops *ops = READ_ONCE(sock->ops); ++ #ifdef CONFIG_IGLOO + igloo_sock_release(sock); ++ #endif + if (ops) { + struct module *owner = ops->owner; + +@@ -1819,8 +1823,10 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, + return __sys_socketpair(family, type, protocol, usockvec); + } + ++#ifdef CONFIG_IGLOO + // forward declare igloo_sock_bind + void igloo_sock_bind(struct socket *sock, struct sockaddr_storage *address); ++#endif + + int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address, + int addrlen) +@@ -1833,7 +1839,9 @@ int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address, + err = READ_ONCE(sock->ops)->bind(sock, + (struct sockaddr *)address, + addrlen); ++#ifdef CONFIG_IGLOO + igloo_sock_bind(sock, address); ++#endif + } + return err; + } diff --git a/patches/6.13/0029-compat.h-add-forward-declaration.patch b/patches/6.13/0029-compat.h-add-forward-declaration.patch new file mode 100644 index 0000000..eaf786c --- /dev/null +++ b/patches/6.13/0029-compat.h-add-forward-declaration.patch @@ -0,0 +1,21 @@ +From 774d5b6e347ab2d4e251f1bc80f967244343e1e9 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Tue, 23 Sep 2025 11:28:33 -0400 +Subject: [PATCH 29/37] compat.h: add forward declaration + +--- + include/linux/compat.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/linux/compat.h b/include/linux/compat.h +index c9df1bacd8..89a9dd5563 100644 +--- a/include/linux/compat.h ++++ b/include/linux/compat.h +@@ -53,6 +53,7 @@ extern igloo_syscall_return_t igloo_syscall_return_hook; + + #ifndef COMPAT_SYSCALL_DEFINE0 + #define COMPAT_SYSCALL_DEFINE0(name) \ ++ static inline long __do_compat_sys_##name(void); \ + asmlinkage long compat_sys_##name(void); \ + ALLOW_ERROR_INJECTION(compat_sys_##name, ERRNO); \ + asmlinkage long compat_sys_##name(void) \ diff --git a/patches/6.13/0030-igloo-debug-calls-now-pr_emerg-when-enabled.patch b/patches/6.13/0030-igloo-debug-calls-now-pr_emerg-when-enabled.patch new file mode 100644 index 0000000..c0080ff --- /dev/null +++ b/patches/6.13/0030-igloo-debug-calls-now-pr_emerg-when-enabled.patch @@ -0,0 +1,55 @@ +From 996b6807416e345bd242774ef7808c63e274b524 Mon Sep 17 00:00:00 2001 +From: Zak Estrada +Date: Fri, 24 Oct 2025 16:21:37 -0400 +Subject: [PATCH 30/37] igloo debug calls now pr_emerg when enabled + +--- + drivers/igloobase/igloo_args.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/igloobase/igloo_args.c b/drivers/igloobase/igloo_args.c +index bdb65d1fbc..2f274130b2 100644 +--- a/drivers/igloobase/igloo_args.c ++++ b/drivers/igloobase/igloo_args.c +@@ -75,14 +75,14 @@ static int __init early_igloo_debug_modules(char *p) + // Special case: "all" enables all modules + if (!strcmp(p, "all")) { + memset(&igloo_debug, 1, sizeof(igloo_debug)); +- pr_warn_once("IGLOO: Debug enabled for all modules\n"); ++ pr_emerg_once("IGLOO: Debug enabled for all modules\n"); + return 0; + } + + // Special case: "none" disables all modules (default) + if (!strcmp(p, "none")) { + memset(&igloo_debug, 0, sizeof(igloo_debug)); +- pr_warn_once("IGLOO: Debug disabled for all modules\n"); ++ pr_emerg_once("IGLOO: Debug disabled for all modules\n"); + return 0; + } + +@@ -100,14 +100,14 @@ static int __init early_igloo_debug_modules(char *p) + igloo_debug.osi = true; + else if (!strcmp(token, "all")){ + memset(&igloo_debug, 1, sizeof(igloo_debug)); +- pr_warn_once("IGLOO: Debug enabled for all modules\n"); ++ pr_emerg_once("IGLOO: Debug enabled for all modules\n"); + return 0; + } + else +- pr_warn("IGLOO: Unknown debug module: %s\n", token); ++ pr_emerg("IGLOO: Unknown debug module: %s\n", token); + } + +- pr_warn_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d\n", ++ pr_emerg_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d\n", + igloo_debug.portal, igloo_debug.uprobe, igloo_debug.vma, + igloo_debug.syscall, igloo_debug.osi); + +@@ -115,4 +115,4 @@ static int __init early_igloo_debug_modules(char *p) + } + + early_param("igloo_debug", early_igloo_debug_modules); +-EXPORT_SYMBOL(igloo_debug); +\ No newline at end of file ++EXPORT_SYMBOL(igloo_debug); diff --git a/patches/6.13/0031-open.c-fix-fd-in-igloo_open_hc-30.patch b/patches/6.13/0031-open.c-fix-fd-in-igloo_open_hc-30.patch new file mode 100644 index 0000000..471032e --- /dev/null +++ b/patches/6.13/0031-open.c-fix-fd-in-igloo_open_hc-30.patch @@ -0,0 +1,35 @@ +From add8c7c3c723a8d301c9860154150259f2d0f5ec Mon Sep 17 00:00:00 2001 +From: Benjamin Levy <153011444+be32826@users.noreply.github.com> +Date: Fri, 7 Nov 2025 13:52:24 -0500 +Subject: [PATCH 31/37] open.c: fix fd in igloo_open_hc() (#30) + +--- + fs/open.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/fs/open.c b/fs/open.c +index ed0828cb91..621a52d310 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -1401,9 +1401,6 @@ static long do_sys_openat2(int dfd, const char __user *filename, + tmp = getname(filename); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); +- #ifdef CONFIG_IGLOO +- igloo_hc_open(dfd, tmp, fd); +- #endif + fd = get_unused_fd_flags(how->flags); + if (fd >= 0) { + struct file *f = do_filp_open(dfd, tmp, &op); +@@ -1414,6 +1411,11 @@ static long do_sys_openat2(int dfd, const char __user *filename, + fd_install(fd, f); + } + } ++ ++ #ifdef CONFIG_IGLOO ++ igloo_hc_open(dfd, tmp, fd); ++ #endif ++ + putname(tmp); + return fd; + } diff --git a/patches/6.13/0032-kprobe-options.patch b/patches/6.13/0032-kprobe-options.patch new file mode 100644 index 0000000..82260af --- /dev/null +++ b/patches/6.13/0032-kprobe-options.patch @@ -0,0 +1,78 @@ +From e50e45a458ab04a5ba6fbab41ecce787785b21f5 Mon Sep 17 00:00:00 2001 +From: Zak Estrada +Date: Tue, 6 Jan 2026 12:24:32 -0500 +Subject: [PATCH 32/37] kprobe options + +--- + drivers/igloobase/igloo_args.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/igloobase/igloo_args.c b/drivers/igloobase/igloo_args.c +index 2f274130b2..3674da3f42 100644 +--- a/drivers/igloobase/igloo_args.c ++++ b/drivers/igloobase/igloo_args.c +@@ -19,11 +19,11 @@ static int __init early_igloo_task_size(char *p) + { + unsigned long task_size; + if (kstrtoul(p, 0, &task_size) < 0 ) { +- pr_warn("Could not parse igloo_task_size parameter %s\n", p); ++ pr_emerg("Could not parse igloo_task_size parameter %s\n", p); + return -1; + } + igloo_task_size = task_size; +- pr_warn_once("Using igloo_task_size: 0x%lx\n", igloo_task_size); ++ pr_emerg_once("Using igloo_task_size: 0x%lx\n", igloo_task_size); + return 0; + } + early_param("igloo_task_size", early_igloo_task_size); +@@ -35,11 +35,11 @@ static int __init early_igloo_block_halt(char *p) + { + unsigned long block_halt; + if (kstrtoul(p, 0, &block_halt) < 0 ) { +- pr_warn("Could not parse igloo_block_halt parameter %s. Set to 0 (default) or 1\n", p); ++ pr_emerg("Could not parse igloo_block_halt parameter %s. Set to 0 (default) or 1\n", p); + return -1; + } + igloo_block_halt = (block_halt > 0); +- pr_warn_once("Using igloo_block_halt: %d\n", igloo_block_halt); ++ pr_emerg_once("Using igloo_block_halt: %d\n", igloo_block_halt); + return 0; + } + +@@ -53,6 +53,7 @@ struct igloo_debug_config { + bool vma; // Enable debug for VMA tracking + bool syscall; // Enable debug for syscall tracking + bool osi; // Enable debug for OSI features ++ bool kprobe; // Enable debug for kprobe module + }; + + // Global debug configuration +@@ -62,6 +63,7 @@ struct igloo_debug_config igloo_debug = { + .vma = false, + .syscall = false, + .osi = false, ++ .kprobe = false, + }; + + // Parse comma-separated list of modules to enable debug logging for +@@ -98,6 +100,8 @@ static int __init early_igloo_debug_modules(char *p) + igloo_debug.syscall = true; + else if (!strcmp(token, "osi")) + igloo_debug.osi = true; ++ else if (!strcmp(token, "kprobe")) ++ igloo_debug.kprobe = true; + else if (!strcmp(token, "all")){ + memset(&igloo_debug, 1, sizeof(igloo_debug)); + pr_emerg_once("IGLOO: Debug enabled for all modules\n"); +@@ -107,9 +111,9 @@ static int __init early_igloo_debug_modules(char *p) + pr_emerg("IGLOO: Unknown debug module: %s\n", token); + } + +- pr_emerg_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d\n", ++ pr_emerg_once("IGLOO: Debug modules - portal:%d uprobe:%d vma:%d syscall:%d osi:%d kprobe: %d\n", + igloo_debug.portal, igloo_debug.uprobe, igloo_debug.vma, +- igloo_debug.syscall, igloo_debug.osi); ++ igloo_debug.syscall, igloo_debug.osi, igloo_debug.kprobe); + + return 0; + } diff --git a/patches/6.13/0033-kprobes-fix-single-step-bug-on-mips.patch b/patches/6.13/0033-kprobes-fix-single-step-bug-on-mips.patch new file mode 100644 index 0000000..a4065a1 --- /dev/null +++ b/patches/6.13/0033-kprobes-fix-single-step-bug-on-mips.patch @@ -0,0 +1,126 @@ +From e4e7363c0635ef64e11d16168b8e228e7b977481 Mon Sep 17 00:00:00 2001 +From: Zak Estrada +Date: Sat, 10 Jan 2026 13:28:57 -0500 +Subject: [PATCH 33/37] kprobes: fix single step bug on mips + +--- + arch/mips/kernel/kprobes.c | 85 +++++++++++++++++++++++++++++++++++++- + 1 file changed, 83 insertions(+), 2 deletions(-) + +diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c +index dc39f5b3fb..35db842b47 100644 +--- a/arch/mips/kernel/kprobes.c ++++ b/arch/mips/kernel/kprobes.c +@@ -25,6 +25,63 @@ + + #include "probes-common.h" + ++/* BEGIN IGLOO PATCH */ ++#include ++#include ++ ++struct kprobe_slot_map { ++ struct hlist_node hnode; ++ unsigned long slot1; /* &p->ainsn.insn[1] */ ++ struct kprobe *kp; ++}; ++ ++static DEFINE_HASHTABLE(kprobe_slot_ht, 10); /* 1024 buckets */ ++static DEFINE_SPINLOCK(kprobe_slot_lock); ++ ++static void kprobe_slot_add(struct kprobe *p) ++{ ++ struct kprobe_slot_map *e; ++ ++ e = kmalloc(sizeof(*e), GFP_KERNEL); /* registration context, safe */ ++ if (!e) ++ return; ++ ++ e->slot1 = (unsigned long)&p->ainsn.insn[1]; ++ e->kp = p; ++ ++ spin_lock(&kprobe_slot_lock); ++ hash_add(kprobe_slot_ht, &e->hnode, e->slot1); ++ spin_unlock(&kprobe_slot_lock); ++} ++ ++static void kprobe_slot_del(struct kprobe *p) ++{ ++ unsigned long key = (unsigned long)&p->ainsn.insn[1]; ++ struct kprobe_slot_map *e; ++ ++ spin_lock(&kprobe_slot_lock); ++ hash_for_each_possible(kprobe_slot_ht, e, hnode, key) { ++ if (e->slot1 == key && e->kp == p) { ++ hash_del(&e->hnode); ++ kfree(e); ++ break; ++ } ++ } ++ spin_unlock(&kprobe_slot_lock); ++} ++ ++static struct kprobe *kprobe_slot_lookup(unsigned long slot1) ++{ ++ struct kprobe_slot_map *e; ++ ++ hash_for_each_possible(kprobe_slot_ht, e, hnode, slot1) { ++ if (e->slot1 == slot1) ++ return e->kp; ++ } ++ return NULL; ++} ++/* END IGLOO PATCH */ ++ + static const union mips_instruction breakpoint_insn = { + .b_format = { + .opcode = spec_op, +@@ -109,6 +166,7 @@ int arch_prepare_kprobe(struct kprobe *p) + ret = -ENOMEM; + goto out; + } ++ kprobe_slot_add(p); /* IGLOO PATCH */ + + /* + * In the kprobe->ainsn.insn[] array we store the original +@@ -153,6 +211,7 @@ NOKPROBE_SYMBOL(arch_disarm_kprobe); + void arch_remove_kprobe(struct kprobe *p) + { + if (p->ainsn.insn) { ++ kprobe_slot_del(p); /* IGLOO PATCH */ + free_insn_slot(p->ainsn.insn, 0); + p->ainsn.insn = NULL; + } +@@ -381,8 +440,30 @@ static inline int post_kprobe_handler(struct pt_regs *regs) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + +- if (!cur) +- return 0; ++ /* BEGIN IGLOO PATCH ++ * // Replaces this: ++ * if (!cur) ++ * return 0; ++ * ++ */ ++ if (!cur) { ++ /* Recover probe from slot1 address (SSTEPBP happens at &ainsn[1]) */ ++ struct kprobe *p = kprobe_slot_lookup(regs->cp0_epc); ++ if (p) { ++ __this_cpu_write(current_kprobe, p); ++ cur = p; ++ ++ /* ++ * Make sure status is consistent for resume_execution(). ++ * We were in SS mode anyway per your logs. ++ */ ++ if (!(kcb->kprobe_status & KPROBE_HIT_SS)) ++ kcb->kprobe_status = KPROBE_HIT_SS; ++ } else { ++ return 0; /* truly not ours */ ++ } ++ } ++ /* END IGLOO PATCH */ + + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; diff --git a/patches/6.13/0034-igloo-fix-igloo_task_size.patch b/patches/6.13/0034-igloo-fix-igloo_task_size.patch new file mode 100644 index 0000000..d572128 --- /dev/null +++ b/patches/6.13/0034-igloo-fix-igloo_task_size.patch @@ -0,0 +1,280 @@ +From f5bc757c51854c2b571bc44b5441a21afb05ee15 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 9 May 2026 16:53:34 -0400 +Subject: [PATCH 34/37] igloo: fix igloo_task_size + +--- + arch/arm/mm/mmap.c | 27 +++++++++++++++++++++------ + arch/loongarch/mm/mmap.c | 17 +++++++++++++---- + arch/mips/mm/mmap.c | 17 +++++++++++++---- + fs/binfmt_elf.c | 17 +++++++++++------ + mm/util.c | 5 +++++ + 5 files changed, 63 insertions(+), 20 deletions(-) + +diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c +index 3dbb383c26..d34983be00 100644 +--- a/arch/arm/mm/mmap.c ++++ b/arch/arm/mm/mmap.c +@@ -12,6 +12,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + + #define COLOUR_ALIGN(addr,pgoff) \ + ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ +@@ -36,6 +39,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); + struct vm_unmapped_area_info info = {}; ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + + /* + * We only need to do colour alignment if either the I or D +@@ -54,7 +63,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + return addr; + } + +- if (len > TASK_SIZE) ++ if (len > task_size) + return -ENOMEM; + + if (addr) { +@@ -64,14 +73,14 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && ++ if (task_size - len >= addr && + (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + + info.length = len; + info.low_limit = mm->mmap_base; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; + info.align_offset = pgoff << PAGE_SHIFT; + return vm_unmapped_area(&info); +@@ -88,6 +97,12 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); + struct vm_unmapped_area_info info = {}; ++ unsigned long task_size = TASK_SIZE; ++ ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif + + /* + * We only need to do colour alignment if either the I or D +@@ -97,7 +112,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + do_align = filp || (flags & MAP_SHARED); + + /* requested length too big for entire address space */ +- if (len > TASK_SIZE) ++ if (len > task_size) + return -ENOMEM; + + if (flags & MAP_FIXED) { +@@ -114,7 +129,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + else + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && ++ if (task_size - len >= addr && + (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } +@@ -137,7 +152,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + VM_BUG_ON(addr != -ENOMEM); + info.flags = 0; + info.low_limit = mm->mmap_base; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + addr = vm_unmapped_area(&info); + } + +diff --git a/arch/loongarch/mm/mmap.c b/arch/loongarch/mm/mmap.c +index 914e82ff3f..b1e9d97685 100644 +--- a/arch/loongarch/mm/mmap.c ++++ b/arch/loongarch/mm/mmap.c +@@ -8,6 +8,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + + #define SHM_ALIGN_MASK (SHMLBA - 1) + +@@ -26,13 +29,19 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + unsigned long addr = addr0; + int do_color_align; + struct vm_unmapped_area_info info = {}; ++ unsigned long task_size = TASK_SIZE; + +- if (unlikely(len > TASK_SIZE)) ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif ++ ++ if (unlikely(len > task_size)) + return -ENOMEM; + + if (flags & MAP_FIXED) { + /* Even MAP_FIXED mappings must reside within TASK_SIZE */ +- if (TASK_SIZE - len < addr) ++ if (task_size - len < addr) + return -EINVAL; + + /* +@@ -57,7 +66,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && ++ if (task_size - len >= addr && + (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } +@@ -84,7 +93,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + } + + info.low_limit = mm->mmap_base; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + return vm_unmapped_area(&info); + } + +diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c +index 5d2a122578..af7b3d6b2b 100644 +--- a/arch/mips/mm/mmap.c ++++ b/arch/mips/mm/mmap.c +@@ -16,6 +16,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + + unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ + EXPORT_SYMBOL(shm_align_mask); +@@ -35,13 +38,19 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + unsigned long addr = addr0; + int do_color_align; + struct vm_unmapped_area_info info = {}; ++ unsigned long task_size = TASK_SIZE; + +- if (unlikely(len > TASK_SIZE)) ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ task_size = igloo_task_size; ++#endif ++ ++ if (unlikely(len > task_size)) + return -ENOMEM; + + if (flags & MAP_FIXED) { + /* Even MAP_FIXED mappings must reside within TASK_SIZE */ +- if (TASK_SIZE - len < addr) ++ if (task_size - len < addr) + return -EINVAL; + + /* +@@ -66,7 +75,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && ++ if (task_size - len >= addr && + (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } +@@ -93,7 +102,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + } + + info.low_limit = mm->mmap_base; +- info.high_limit = TASK_SIZE; ++ info.high_limit = task_size; + return vm_unmapped_area(&info); + } + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index b3d0003ccb..cafdebcad6 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -49,7 +49,14 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO + #include ++#define BAD_ADDR(x) (unlikely((unsigned long)(x) >= (igloo_task_size ? igloo_task_size : TASK_SIZE))) ++#define IGLOO_TASK_SIZE (igloo_task_size ? igloo_task_size : TASK_SIZE) ++#else ++#define BAD_ADDR(x) (unlikely((unsigned long)(x) >= TASK_SIZE)) ++#define IGLOO_TASK_SIZE TASK_SIZE ++#endif + + #ifndef ELF_COMPAT + #define ELF_COMPAT 0 +@@ -109,8 +116,6 @@ static struct linux_binfmt elf_format = { + #endif + }; + +-#define BAD_ADDR(x) (unlikely((unsigned long)(x) >= TASK_SIZE)) +- + /* + * We need to explicitly zero any trailing portion of the page that follows + * p_filesz when it ends before the page ends (e.g. bss), otherwise this +@@ -700,8 +705,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, + k = load_addr + eppnt->p_vaddr; + if (BAD_ADDR(k) || + eppnt->p_filesz > eppnt->p_memsz || +- eppnt->p_memsz > TASK_SIZE || +- TASK_SIZE - eppnt->p_memsz < k) { ++ eppnt->p_memsz > IGLOO_TASK_SIZE || ++ IGLOO_TASK_SIZE - eppnt->p_memsz < k) { + error = -ENOMEM; + goto out; + } +@@ -1221,8 +1226,8 @@ static int load_elf_binary(struct linux_binprm *bprm) + * <= p_memsz so it is only necessary to check p_memsz. + */ + if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz || +- elf_ppnt->p_memsz > TASK_SIZE || +- TASK_SIZE - elf_ppnt->p_memsz < k) { ++ elf_ppnt->p_memsz > IGLOO_TASK_SIZE || ++ IGLOO_TASK_SIZE - elf_ppnt->p_memsz < k) { + /* set_brk can never work. Avoid overflows. */ + retval = -EINVAL; + goto out_free_dentry; +diff --git a/mm/util.c b/mm/util.c +index f5d5f5dac3..72386af4b7 100644 +--- a/mm/util.c ++++ b/mm/util.c +@@ -462,6 +462,11 @@ static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) + else if (gap > MAX_GAP) + gap = MAX_GAP; + ++#ifdef CONFIG_IGLOO ++ if (igloo_task_size) ++ return PAGE_ALIGN(igloo_task_size - gap - rnd); ++#endif ++ + return PAGE_ALIGN(STACK_TOP - gap - rnd); + #endif + } diff --git a/patches/6.13/0036-igloo-move-into-procfs.patch b/patches/6.13/0036-igloo-move-into-procfs.patch new file mode 100644 index 0000000..5b1c7b5 --- /dev/null +++ b/patches/6.13/0036-igloo-move-into-procfs.patch @@ -0,0 +1,180 @@ +From f21401b2552d26ff3c30ff83cf50dfc7ca3d70ff Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sun, 17 May 2026 13:21:30 -0400 +Subject: [PATCH 36/37] igloo: move into procfs + +--- + fs/proc/base.c | 129 +++++++++++++++++++++++++++++++++++++++- + include/linux/proc_fs.h | 5 ++ + 2 files changed, 131 insertions(+), 3 deletions(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 0edf14a984..e4f691768e 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -71,6 +71,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -160,6 +161,112 @@ struct pid_entry { + union proc_op op; + }; + ++#ifdef CONFIG_IGLOO ++struct igloo_proc_pid_entry { ++ struct list_head list; ++ struct proc_dir_entry *pde; ++ const struct file_operations *fop; ++}; ++ ++static LIST_HEAD(igloo_proc_pid_entries); ++static DEFINE_MUTEX(igloo_proc_pid_entries_lock); ++ ++struct proc_dir_entry *igloo_proc_create_pid_data(const char *name, umode_t mode, ++ const struct file_operations *fop, ++ void *data) ++{ ++ struct proc_dir_entry *parent = NULL; ++ struct igloo_proc_pid_entry *entry; ++ struct proc_dir_entry *pde; ++ size_t len; ++ ++ if (!name || !name[0] || strchr(name, '/')) ++ return NULL; ++ if ((mode & S_IFMT) == 0) ++ mode |= S_IFREG; ++ if ((mode & S_IALLUGO) == 0) ++ mode |= S_IRUGO; ++ if (!S_ISREG(mode) || !fop) ++ return NULL; ++ ++ len = strlen(name); ++ ++ mutex_lock(&igloo_proc_pid_entries_lock); ++ list_for_each_entry(entry, &igloo_proc_pid_entries, list) { ++ pde = entry->pde; ++ if (pde->namelen == len && !memcmp(pde->name, name, len)) { ++ pde->mode = mode; ++ pde->data = data; ++ entry->fop = fop; ++ mutex_unlock(&igloo_proc_pid_entries_lock); ++ return pde; ++ } ++ } ++ mutex_unlock(&igloo_proc_pid_entries_lock); ++ ++ entry = kzalloc(sizeof(*entry), GFP_KERNEL); ++ if (!entry) ++ return NULL; ++ pde = proc_create_reg(name, mode, &parent, data); ++ if (!pde) { ++ kfree(entry); ++ return NULL; ++ } ++ ++ entry->pde = pde; ++ entry->fop = fop; ++ ++ mutex_lock(&igloo_proc_pid_entries_lock); ++ list_add(&entry->list, &igloo_proc_pid_entries); ++ mutex_unlock(&igloo_proc_pid_entries_lock); ++ ++ return pde; ++} ++EXPORT_SYMBOL_GPL(igloo_proc_create_pid_data); ++ ++static struct dentry *igloo_proc_pid_instantiate(struct dentry *dentry, ++ struct task_struct *task, ++ struct igloo_proc_pid_entry *entry) ++{ ++ struct proc_dir_entry *pde = entry->pde; ++ struct inode *inode; ++ ++ inode = proc_pid_make_inode(dentry->d_sb, task, pde->mode); ++ if (!inode) ++ return ERR_PTR(-ENOENT); ++ ++ pde_get(pde); ++ PROC_I(inode)->pde = pde; ++ inode->i_private = pde->data; ++ inode->i_fop = entry->fop; ++ if (pde->size) ++ inode->i_size = pde->size; ++ pid_update_inode(task, inode); ++ d_set_d_op(dentry, &pid_dentry_operations); ++ return d_splice_alias(inode, dentry); ++} ++ ++static struct dentry *igloo_proc_pid_lookup(struct dentry *dentry, ++ struct task_struct *task) ++{ ++ struct igloo_proc_pid_entry *entry; ++ struct dentry *res = ERR_PTR(-ENOENT); ++ ++ mutex_lock(&igloo_proc_pid_entries_lock); ++ list_for_each_entry(entry, &igloo_proc_pid_entries, list) { ++ if (entry->pde->namelen != dentry->d_name.len) ++ continue; ++ if (!memcmp(entry->pde->name, dentry->d_name.name, ++ dentry->d_name.len)) { ++ res = igloo_proc_pid_instantiate(dentry, task, entry); ++ break; ++ } ++ } ++ mutex_unlock(&igloo_proc_pid_entries_lock); ++ return res; ++} ++#endif ++ + #define NOD(NAME, MODE, IOP, FOP, OP) { \ + .name = (NAME), \ + .len = sizeof(NAME) - 1, \ +@@ -3442,9 +3549,25 @@ struct pid *tgid_pidfd_to_pid(const struct file *file) + + static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) + { +- return proc_pident_lookup(dir, dentry, +- tgid_base_stuff, +- tgid_base_stuff + ARRAY_SIZE(tgid_base_stuff)); ++ struct dentry *res; ++#ifdef CONFIG_IGLOO ++ struct task_struct *task; ++#endif ++ ++ res = proc_pident_lookup(dir, dentry, ++ tgid_base_stuff, ++ tgid_base_stuff + ARRAY_SIZE(tgid_base_stuff)); ++#ifdef CONFIG_IGLOO ++ if (!IS_ERR(res) || PTR_ERR(res) != -ENOENT) ++ return res; ++ ++ task = get_proc_task(dir); ++ if (!task) ++ return res; ++ res = igloo_proc_pid_lookup(dentry, task); ++ put_task_struct(task); ++#endif ++ return res; + } + + static const struct inode_operations proc_tgid_base_inode_operations = { +diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h +index 0b2a898544..43c1f9cf33 100644 +--- a/include/linux/proc_fs.h ++++ b/include/linux/proc_fs.h +@@ -107,6 +107,11 @@ extern struct proc_dir_entry *proc_create_data(const char *, umode_t, + struct proc_dir_entry *, + const struct proc_ops *, + void *); ++#ifdef CONFIG_IGLOO ++struct proc_dir_entry *igloo_proc_create_pid_data(const char *, umode_t, ++ const struct file_operations *, ++ void *); ++#endif + + struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops); + extern void proc_set_size(struct proc_dir_entry *, loff_t); diff --git a/patches/6.13/0037-igloo-move-into-signal-handler.patch b/patches/6.13/0037-igloo-move-into-signal-handler.patch new file mode 100644 index 0000000..012f954 --- /dev/null +++ b/patches/6.13/0037-igloo-move-into-signal-handler.patch @@ -0,0 +1,69 @@ +From 8f25e989e12e2fca57aec18413ad157efb452ee4 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sun, 17 May 2026 13:21:37 -0400 +Subject: [PATCH 37/37] igloo: move into signal handler + +--- + include/linux/igloo_signal.h | 12 ++++++++++++ + kernel/signal.c | 15 +++++++++++++++ + 2 files changed, 27 insertions(+) + create mode 100644 include/linux/igloo_signal.h + +diff --git a/include/linux/igloo_signal.h b/include/linux/igloo_signal.h +new file mode 100644 +index 0000000000..375b5ee68b +--- /dev/null ++++ b/include/linux/igloo_signal.h +@@ -0,0 +1,12 @@ ++#ifndef _LINUX_IGLOO_SIGNAL_H ++#define _LINUX_IGLOO_SIGNAL_H ++ ++#include ++ ++struct task_struct; ++ ++typedef bool (*igloo_signal_deliver_hook_t)(int sig, struct task_struct *task); ++ ++extern igloo_signal_deliver_hook_t igloo_signal_deliver_hook; ++ ++#endif /* _LINUX_IGLOO_SIGNAL_H */ +diff --git a/kernel/signal.c b/kernel/signal.c +index a2afd54303..50a618bd5d 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -43,6 +43,9 @@ + #include + #include + #include ++#ifdef CONFIG_IGLOO ++#include ++#endif + #include + #include + #include +@@ -67,6 +70,11 @@ + + static struct kmem_cache *sigqueue_cachep; + ++#ifdef CONFIG_IGLOO ++igloo_signal_deliver_hook_t igloo_signal_deliver_hook; ++EXPORT_SYMBOL_GPL(igloo_signal_deliver_hook); ++#endif ++ + int print_fatal_signals __read_mostly; + + static void __user *sig_handler(struct task_struct *t, int sig) +@@ -1049,6 +1057,13 @@ static int __send_signal_locked(int sig, struct kernel_siginfo *info, + lockdep_assert_held(&t->sighand->siglock); + + result = TRACE_SIGNAL_IGNORED; ++#ifdef CONFIG_IGLOO ++ if (sig && igloo_signal_deliver_hook && ++ igloo_signal_deliver_hook(sig, t)) { ++ ret = 0; ++ goto ret; ++ } ++#endif + if (!prepare_signal(sig, t, force)) + goto ret; + diff --git a/patches/6.13/series b/patches/6.13/series new file mode 100644 index 0000000..19fae24 --- /dev/null +++ b/patches/6.13/series @@ -0,0 +1,33 @@ +6.13/0005-Net-disallow-changing-bridge-mac-addrs-from-firmadyn.patch +core/add-hypercall.h.patch +6.13/0007-reboot.c-add-igloo_block_halt.patch +6.13/0008-socket.c-add-igloo_socket_hc.patch +core/add-igloo.h.patch +6.13/0010-open.c-add-igloo_open_hc.patch +6.13/0011-sys.c-add-igloo_hc_newuname.patch +6.13/0012-namespace.c-add-igloo_should_block_mount.patch +6.13/0013-ioctl.c-add-igloo_ioctl_hc.patch +6.13/0014-igloobase-add-driver.patch +6.13/0015-exec.c-add-igloo_task_size.patch +6.13/0016-mmap.c-add-igloo_task_size.patch +6.13/0017-util.c-add-igloo_task_size.patch +core/add-igloo_syscall_macros.h.patch +6.13/0019-add-syscalls.h.patch +6.13/0020-syscall_wrapper-add-x86-support.patch +6.13/0021-syscall_wrapper.h-add-arm64-support.patch +6.13/0022-syscall_wrapper.h-add-riscv-support.patch +6.13/0023-binfmt_elf.c-add-igloo_task_size-support.patch +6.13/0024-compat.h-syscalls-support.patch +6.13/0025-compat.h-add-define0.patch +6.13/0026-igloo_weaksyms-fix-up-igloo_ioctl-type.patch +core/igloo.h-drop-declarations-for-forward-declarations.patch +6.13/0028-socket.c-add-CONFIG_IGLOO.patch +6.13/0029-compat.h-add-forward-declaration.patch +6.13/0030-igloo-debug-calls-now-pr_emerg-when-enabled.patch +6.13/0031-open.c-fix-fd-in-igloo_open_hc-30.patch +6.13/0032-kprobe-options.patch +6.13/0033-kprobes-fix-single-step-bug-on-mips.patch +6.13/0034-igloo-fix-igloo_task_size.patch +core/update-hypercall.h.patch +6.13/0036-igloo-move-into-procfs.patch +6.13/0037-igloo-move-into-signal-handler.patch diff --git a/patches/README.md b/patches/README.md new file mode 100644 index 0000000..f76f3d8 --- /dev/null +++ b/patches/README.md @@ -0,0 +1,70 @@ +# The IGLOO kernel patch series + +The IGLOO kernel delta, carried as an explicit patch series applied to pristine +upstream release tarballs — replacing the two long-lived fork branches of +`rehosting/linux` that used to arrive as git submodules. + +## Layout + +``` +base.json upstream base tag + tarball hash per version +core/ patches byte-identical across every version (5) +4.10/ 6.13/ per-version patches + the `series` file +``` + +Each `series` file lists patch paths relative to `patches/`, in apply order, so +core patches and version-specific ones interleave where the ordering requires. +Blank lines and `#` comments are ignored (quilt convention). + +| version | base | patches | of which shared | +|---|---|---|---| +| 4.10 | `v4.10` | 38 | 5 | +| 6.13 | `v6.13` | 33 | 5 | + +## How much is really shared — read this before assuming + +Of the 23 patches that carry the **same subject** in both versions, only **5 are +byte-identical**. Those 5 are precisely the ones that add *new files* +(`include/hypercall.h`, `include/igloo.h`, `include/igloo_syscall_macros.h`). +Every patch that modifies existing kernel code differs between 4.10 and 6.13, +because the surrounding code differs. + +So the series does **not** collapse the two versions into one maintained copy. +What it does deliver: + +- **Additive work is written once.** New files under `drivers/igloobase/` and + `include/` go in `core/` and apply to every version — this is the class that + igloo_driver #918 falls into. +- **Hook-site work stays per-version**, as it must; it is now visibly per-version + instead of silently duplicated across two branches. +- The old failure mode — fixing a bug on one branch and forgetting the other — + becomes a visible diff between two series rather than an invisible omission. + (It happened: the same fix shipped as PR #29 on 4.10 and #30 on 6.13.) + +## Two things the migration uncovered + +**The 6.13 fork was not based on a release.** `main_6.13` branched five commits +before `v6.13` and then cherry-picked four of them back — `x86: Disable +EXECMEM_ROX support`, `x86/fred: …`, `x86/asm: Make serialize() always_inline`, +and the `Linux 6.13` version commit. All four are upstream, so basing on the +`v6.13` tarball reproduces the same tree with none of them carried locally. + +**`.gitmodules` named the wrong branches.** It declared `branch = main_6.7` for +`linux/6.13` while the pin was actually the head of `main_6.13` — trees 89,775 +commits apart. `git submodule update --remote` would have silently regressed the +kernel. Basing on a tag makes that class of drift unrepresentable. + +## Working on the kernel + +```bash +./scripts/import-series.sh 6.13 /tmp/k613 # tarball + series -> a git tree +cd /tmp/k613 && git commit ... # develop normally +./scripts/export-series.sh 6.13 /tmp/k613 # write the series back +./scripts/verify-series.sh 6.13 refs/remotes/origin/main_6.13 +``` + +`verify-series.sh` is the gate: it applies the series to the pristine tarball and +asserts the result matches the fork branch. Note release tarballs are `git +archive` output and honour `export-ignore`, so they legitimately lack +`.gitattributes`, `.get_maintainer.ignore`, and two `arch/sh` linker scripts — +the check allows exactly those paths and fails on anything else. diff --git a/patches/base.json b/patches/base.json new file mode 100644 index 0000000..5ab6367 --- /dev/null +++ b/patches/base.json @@ -0,0 +1,10 @@ +{ + "4.10": { + "tag": "4.10", + "hash": "sha256-PJXZ8Em9CF5cNG0sd/BjuEJfGRRg/NOun+fpTgR33Es=" + }, + "6.13": { + "tag": "6.13", + "hash": "sha256-553Mbrhmlca6v7B8KGGRK2NdUHXGzRzQVn0eoVX4DW4=" + } +} diff --git a/patches/core/add-hypercall.h.patch b/patches/core/add-hypercall.h.patch new file mode 100644 index 0000000..40ed30a --- /dev/null +++ b/patches/core/add-hypercall.h.patch @@ -0,0 +1,358 @@ +From babe02e6a05eac84f10a6791eca430363cac6220 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 10:59:23 -0400 +Subject: [PATCH 02/38] add hypercall.h + +--- + include/hypercall.h | 341 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 341 insertions(+) + create mode 100644 include/hypercall.h + +diff --git a/include/hypercall.h b/include/hypercall.h +new file mode 100644 +index 0000000000..b3c308a596 +--- /dev/null ++++ b/include/hypercall.h +@@ -0,0 +1,341 @@ ++#ifndef HYPERCALL_H ++#define HYPERCALL_H ++#include // Use standard include path ++ ++static inline unsigned long igloo_hypercall(unsigned long num, unsigned long arg1) { ++#if defined(CONFIG_MIPS) ++ register unsigned long reg0 asm("v0") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ ++ asm volatile( ++ "movz $0, $0, $0" ++ : "+r"(reg0) ++ : "r"(reg1) // num in register v0 ++ : "memory" ++ ); ++ ++ return reg0; ++ ++#elif defined(CONFIG_ARM64) ++ register unsigned long reg0 asm("x8") = num; ++ register unsigned long reg1 asm("x0") = arg1; ++ asm volatile( ++ "msr S0_0_c5_c0_0, xzr \n" ++ : "+r"(reg1) ++ : "r"(reg0) ++ : "memory" ++ ); ++ ++ return reg1; ++ ++#elif defined(CONFIG_ARM) ++ register unsigned long reg0 asm("r7") = num; ++ register unsigned long reg1 asm("r0") = arg1; ++ ++ asm volatile( ++ "mcr p7, 0, r0, c0, c0, 0" ++ : "+r"(reg1) ++ : "r"(reg0) ++ : "memory" ++ ); ++ ++ return reg1; ++ ++#elif defined(CONFIG_X86_64) ++ register unsigned long reg0 asm("rax") = num; ++ register unsigned long reg1 asm("rdi") = arg1; ++ ++ asm volatile( ++ "cpuid" ++ : "+r"(reg0) // hypercall num + return value in rax ++ : "r"(reg1) // arguments ++ : "memory", "rbx", "rcx", "rdx" // No clobber ++ ); ++ ++ return reg0; ++ ++#elif defined(CONFIG_I386) ++ register unsigned long reg0 asm("eax") = num; ++ register unsigned long reg1 asm("edi") = arg1; ++ ++ asm volatile( ++ "cpuid" ++ : "+r"(reg0) // hypercall num + return value in rax ++ : "r"(reg1) // arguments ++ : "memory", "ebx", "ecx", "edx" ++ ); ++ ++ return reg0; ++ ++#elif defined(CONFIG_LOONGARCH) ++ register unsigned long reg0 asm("a7") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ ++ asm volatile( ++ "cpucfg $r0, $r0" ++ : "+r"(reg0) ++ : "r"(reg1) ++ : "memory" // No clobber ++ ); ++ ++ return reg0; ++ ++#elif defined(CONFIG_PPC) ++ register unsigned long reg0 asm("r0") = num; ++ register unsigned long reg1 asm("r3") = arg1; ++ ++ asm volatile( ++ "xori 10, 10, 0" // User-specified instruction - ASSUMED CORRECT TRIGGER ++ : "+r"(reg0) // Input num in r0, Output retval in r0 ++ : "r"(reg1) // Input arg1 in r3 ++ : "memory", "lr", "ctr", // CRITICAL: clobber link and count registers ++ // Clobber volatile condition register fields: ++ "cr0", "cr1", "cr5", "cr6", "cr7", ++ // Clobber volatile GPRs (r4-r12) - r0,r3 handled by constraints: ++ "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ++ // Note: r2 (TOC) and r13 (thread ptr) are usually non-volatile but check hypervisor docs ++ ); ++ ++ return reg0; ++ ++#elif defined(CONFIG_RISCV) ++ register unsigned long reg0 asm("a7") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ ++ asm volatile( ++ "xori x0, x0, 0" ++ : "+r"(reg1) /* Modified: a0/reg1 is both input and output */ ++ : "r"(reg0) ++ : "memory" ++ ); ++ ++ return reg1; ++ ++#else ++#error "No igloo_hypercall support for architecture" ++#endif ++} ++ ++static inline unsigned long igloo_hypercall2(unsigned long num, unsigned long arg1, unsigned long arg2) { ++#if defined(CONFIG_ARM64) ++ register unsigned long reg0 asm("x8") = num; ++ register unsigned long reg1 asm("x0") = arg1; ++ register unsigned long reg2 asm("x1") = arg2; ++ asm volatile( ++ "msr S0_0_c5_c0_0, xzr \n" ++ : "+r"(reg1) // Input and output ++ : "r"(reg0), "r"(reg2) ++ : "memory" ++ ); ++ return reg1; ++#elif defined(CONFIG_ARM) ++ register unsigned long reg0 asm("r7") = num; ++ register unsigned long reg1 asm("r0") = arg1; ++ register unsigned long reg2 asm("r1") = arg2; ++ ++ asm volatile( ++ "mcr p7, 0, r0, c0, c0, 0" ++ : "+r"(reg1) // Input and output ++ : "r"(reg0), "r"(reg2) ++ : "memory" ++ ); ++ ++ return reg1; ++ ++#elif defined(CONFIG_MIPS) ++ register unsigned long reg0 asm("v0") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ register unsigned long reg2 asm("a1") = arg2; ++ ++ asm volatile( ++ "movz $0, $0, $0" ++ : "+r"(reg0) // Input and output in v0 ++ : "r"(reg1), "r"(reg2) ++ : "memory" ++ ); ++ return reg0; ++#elif defined(CONFIG_X86_64) ++ register unsigned long reg0 asm("rax") = num; ++ register unsigned long reg1 asm("rdi") = arg1; ++ register unsigned long reg2 asm("rsi") = arg2; ++ ++ asm volatile( ++ "cpuid" ++ : "+r"(reg0) // hypercall num + return value in rax ++ : "r"(reg1), "r"(reg2) // arguments ++ : "memory", "rbx", "rcx", "rdx" ++ ); ++ ++ return reg0; ++#elif defined(CONFIG_I386) ++ register unsigned long reg0 asm("eax") = num; ++ register unsigned long reg1 asm("edi") = arg1; ++ register unsigned long reg2 asm("esi") = arg2; ++ ++ asm volatile( ++ "cpuid" ++ : "+r"(reg0) // hypercall num + return value in rax ++ : "r"(reg1), "r"(reg2) // arguments ++ : "memory", "ebx", "ecx", "edx" ++ ); ++ ++ return reg0; ++#elif defined(CONFIG_LOONGARCH) ++ register unsigned long reg0 asm("a7") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ register unsigned long reg2 asm("a1") = arg2; ++ ++ asm volatile( ++ "cpucfg $r0, $r0" ++ : "+r"(reg1) /* a0/reg1 is both input and output */ ++ : "r"(reg0), "r"(reg2) ++ : "memory" ++ ); ++ return reg1; /* Return reg1 (a0) which contains the return value from the hypervisor */ ++#elif defined(CONFIG_PPC) || defined(CONFIG_PPC64) ++ register unsigned long reg0 asm("r0") = num; ++ register unsigned long reg1 asm("r3") = arg1; ++ register unsigned long reg2 asm("r4") = arg2; // Second arg in r4 ++ ++ asm volatile( ++ "xori 10, 10, 0" // User-specified instruction ++ : "+r"(reg1) // Input and output in r3 ++ : "r"(reg0), "r"(reg2) ++ : "memory", "lr", "ctr", ++ "cr0", "cr1", "cr5", "cr6", "cr7", ++ "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ++ ); ++ return reg1; /* Return reg1 (r3) which contains the return value from the hypervisor */ ++#elif defined(CONFIG_RISCV) ++ register unsigned long reg0 asm("a7") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ register unsigned long reg2 asm("a1") = arg2; ++ ++ asm volatile( ++ "xori x0, x0, 0" ++ : "+r"(reg1) /* a0/reg1 is both input and output */ ++ : "r"(reg0), "r"(reg2) ++ : "memory" ++ ); ++ return reg1; /* Return reg1 (a0) which contains the return value from the hypervisor */ ++#else ++#error "No igloo_hypercall2 support for architecture" ++#endif ++} ++ ++static inline unsigned long igloo_hypercall3(unsigned long num, unsigned long arg1, unsigned long arg2, unsigned long arg3) { ++#if defined(CONFIG_ARM64) ++ register unsigned long reg0 asm("x8") = num; ++ register unsigned long reg1 asm("x0") = arg1; ++ register unsigned long reg2 asm("x1") = arg2; ++ register unsigned long reg3 asm("x2") = arg3; ++ asm volatile( ++ "msr S0_0_c5_c0_0, xzr \n" ++ : "+r"(reg1) // Input and output ++ : "r"(reg0), "r"(reg2), "r"(reg3) ++ : "memory" ++ ); ++ return reg1; ++#elif defined(CONFIG_ARM) ++ register unsigned long reg0 asm("r7") = num; ++ register unsigned long reg1 asm("r0") = arg1; ++ register unsigned long reg2 asm("r1") = arg2; ++ register unsigned long reg3 asm("r2") = arg3; ++ ++ asm volatile( ++ "mcr p7, 0, r0, c0, c0, 0" ++ : "+r"(reg1) // Input and output ++ : "r"(reg0), "r"(reg2), "r"(reg3) ++ : "memory" ++ ); ++ ++ return reg1; ++ ++#elif defined(CONFIG_MIPS) ++ register unsigned long reg0 asm("v0") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ register unsigned long reg2 asm("a1") = arg2; ++ register unsigned long reg3 asm("a2") = arg3; ++ ++ asm volatile( ++ "movz $0, $0, $0" ++ : "+r"(reg0) // Input and output in v0 ++ : "r"(reg1), "r"(reg2), "r"(reg3) ++ : "memory" ++ ); ++ return reg0; ++#elif defined(CONFIG_X86_64) ++ register unsigned long reg0 asm("rax") = num; ++ register unsigned long reg1 asm("rdi") = arg1; ++ register unsigned long reg2 asm("rsi") = arg2; ++ register unsigned long reg3 asm("rdx") = arg3; ++ ++ asm volatile( ++ "cpuid" ++ : "+r"(reg0) // hypercall num + return value in rax ++ : "r"(reg1), "r"(reg2), "r"(reg3) // arguments ++ : "memory", "rbx", "rcx" ++ ); ++ ++ return reg0; ++#elif defined(CONFIG_I386) ++ register unsigned long reg0 asm("eax") = num; ++ register unsigned long reg1 asm("edi") = arg1; ++ register unsigned long reg2 asm("esi") = arg2; ++ register unsigned long reg3 asm("edx") = arg3; ++ ++ asm volatile( ++ "cpuid" ++ : "+r"(reg0) // hypercall num + return value in eax ++ : "r"(reg1), "r"(reg2), "r"(reg3) // arguments ++ : "memory", "ebx", "ecx" ++ ); ++ ++ return reg0; ++#elif defined(CONFIG_LOONGARCH) ++ register unsigned long reg0 asm("a7") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ register unsigned long reg2 asm("a1") = arg2; ++ register unsigned long reg3 asm("a2") = arg3; ++ ++ asm volatile( ++ "cpucfg $r0, $r0" ++ : "+r"(reg1) /* a0/reg1 is both input and output */ ++ : "r"(reg0), "r"(reg2), "r"(reg3) ++ : "memory" ++ ); ++ return reg1; /* Return reg1 (a0) which contains the return value from the hypervisor */ ++#elif defined(CONFIG_PPC) || defined(CONFIG_PPC64) ++ register unsigned long reg0 asm("r0") = num; ++ register unsigned long reg1 asm("r3") = arg1; ++ register unsigned long reg2 asm("r4") = arg2; ++ register unsigned long reg3 asm("r5") = arg3; ++ ++ asm volatile( ++ "xori 10, 10, 0" // User-specified instruction ++ : "+r"(reg1) // Input and output in r3 ++ : "r"(reg0), "r"(reg2), "r"(reg3) ++ : "memory", "lr", "ctr", ++ "cr0", "cr1", "cr5", "cr6", "cr7", ++ "r6", "r7", "r8", "r9", "r10", "r11", "r12" ++ ); ++ return reg1; /* Return reg1 (r3) which contains the return value from the hypervisor */ ++#elif defined(CONFIG_RISCV) ++ register unsigned long reg0 asm("a7") = num; ++ register unsigned long reg1 asm("a0") = arg1; ++ register unsigned long reg2 asm("a1") = arg2; ++ register unsigned long reg3 asm("a2") = arg3; ++ ++ asm volatile( ++ "xori x0, x0, 0" ++ : "+r"(reg1) /* a0/reg1 is both input and output */ ++ : "r"(reg0), "r"(reg2), "r"(reg3) ++ : "memory" ++ ); ++ return reg1; /* Return reg1 (a0) which contains the return value from the hypervisor */ ++#else ++#error "No igloo_hypercall3 support for architecture" ++#endif ++} ++ ++#endif +\ No newline at end of file diff --git a/patches/core/add-igloo.h.patch b/patches/core/add-igloo.h.patch new file mode 100644 index 0000000..b2f78da --- /dev/null +++ b/patches/core/add-igloo.h.patch @@ -0,0 +1,44 @@ +From cf5d2fddb7ae35b113fd61410c363896be1c011e Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Thu, 31 Jul 2025 23:15:33 -0400 +Subject: [PATCH 05/38] add igloo.h + +--- + include/igloo.h | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + create mode 100644 include/igloo.h + +diff --git a/include/igloo.h b/include/igloo.h +new file mode 100644 +index 0000000000..45e1dcd81c +--- /dev/null ++++ b/include/igloo.h +@@ -0,0 +1,27 @@ ++#ifndef _LINUX_IGLOO_H ++#define _LINUX_IGLOO_H ++#include ++#include ++#include ++ ++extern unsigned long igloo_task_size; // mmap.c ++extern bool igloo_block_halt; // reboot.c ++ ++struct user_arg_ptr; // Forward declaration ++struct syscall_metadata; // Forward declaration for syscall metadata functions ++ ++void igloo_sock_release(struct socket *sock); ++void igloo_sock_bind(struct socket *sock, struct sockaddr_storage *address); ++void igloo_hc_newuname(struct new_utsname *name); ++unsigned long igloo_arch_syscall_addr(int nr); ++ ++/* Syscall metadata access functions */ ++struct syscall_metadata *igloo_get_syscall_metadata(int nr); ++int igloo_get_nr_syscalls(void); ++struct syscall_metadata *igloo_get_syscall_metadata_by_index(int index); ++int igloo_get_syscall_metadata_count(void); ++struct syscall_metadata *igloo_get_syscall_metadata_copy(int nr); ++int igloo_get_syscall_metadata_count_copy(void); ++struct syscall_metadata *igloo_get_syscall_metadata_by_index_copy(int index); ++ ++#endif /* _LINUX_IGLOO_H */ +\ No newline at end of file diff --git a/patches/core/add-igloo_syscall_macros.h.patch b/patches/core/add-igloo_syscall_macros.h.patch new file mode 100644 index 0000000..ad6e2e6 --- /dev/null +++ b/patches/core/add-igloo_syscall_macros.h.patch @@ -0,0 +1,116 @@ +From ca08ed92a85242800be647ed485386d871dc9736 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Fri, 1 Aug 2025 11:18:27 -0400 +Subject: [PATCH 13/38] add igloo_syscall_macros.h + +--- + include/igloo_syscall_macros.h | 99 ++++++++++++++++++++++++++++++++++ + 1 file changed, 99 insertions(+) + create mode 100644 include/igloo_syscall_macros.h + +diff --git a/include/igloo_syscall_macros.h b/include/igloo_syscall_macros.h +new file mode 100644 +index 0000000000..e8f41b20fb +--- /dev/null ++++ b/include/igloo_syscall_macros.h +@@ -0,0 +1,99 @@ ++#ifndef _IGLOO_SYSCALL_MACROS_H ++ ++/** ++ * igloo_syscall_setter_t - Typedef for the syscall argument setter function. ++ * @args_ptr_array: Array containing the ADDRESSES of the original syscall ++ * arguments, each cast to unsigned long. ++ * @new_args_le64: Array containing the new argument values, provided as ++ * little-endian 64-bit values. ++ * ++ * This function, generated per syscall, casts the pointers and new values ++ * to the correct types and updates the original arguments. ++ * NOTE: This function is generated even for syscalls with const args ++ * (using a (void *) cast to bypass compile errors). The hook MUST NOT ++ * call this setter with modified values for const arguments. ++ */ ++typedef void (*igloo_syscall_setter_t)(const unsigned long args_ptr_array[], ++ const __le64 new_args_le64[]); ++ ++ ++/** ++ * igloo_syscall_enter_t - Typedef for the enter hook function. ++ * @syscall_name: The string name ("read", "openat", etc.) of the syscall. ++ * @skip_ret_val: Pointer to store the return value if skipping the syscall. ++ * @argc: Number of arguments passed to the syscall. ++ * @args_ptr_array: Array containing the ADDRESSES of the syscall arguments. ++ * @setter_func: Pointer to the type-safe setter function for this specific ++ * syscall, or NULL if argc is 0. The hook can call this ++ * function if it decides to modify arguments, but MUST respect ++ * the const nature of arguments. ++ * ++ * Returns: true to skip the actual syscall execution, false to proceed. ++ */ ++typedef bool (*igloo_syscall_enter_t)(const char *syscall_name, ++ long *skip_ret_val, ++ int argc, ++ const unsigned long args_ptr_array[], ++ igloo_syscall_setter_t setter_func); ++ ++/** ++ * igloo_syscall_return_t - Typedef for the return hook function. ++ * @syscall_name: The string name ("read", "openat", etc.) of the syscall. ++ * @orig_ret: The original return value from the syscall (or skip value). ++ * @argc: Number of arguments passed to the syscall. ++ * @args_val_array: Array containing the final VALUES of the syscall arguments ++ * (after potential modification by enter hook), each cast ++ * to unsigned long. ++ * ++ * Returns: The potentially modified return value for the syscall. ++ */ ++typedef long (*igloo_syscall_return_t)(const char *syscall_name, ++ long retval, int argc, ++ const unsigned long args[]); ++ ++#ifdef CONFIG_IGLOO ++extern igloo_syscall_enter_t igloo_syscall_enter_hook; ++extern igloo_syscall_return_t igloo_syscall_return_hook; ++#endif ++ ++ ++#define IGLOO_SYSCALL_MAXARGS 6 ++ ++#define __SC_ASSIGN_ADDR_ITER_0(arr, ...) ++#define __SC_ASSIGN_ADDR_ITER_1(arr, t1, a1) arr[0] = (unsigned long)&a1; ++#define __SC_ASSIGN_ADDR_ITER_2(arr, t1, a1, t2, a2) arr[0] = (unsigned long)&a1; arr[1] = (unsigned long)&a2; ++#define __SC_ASSIGN_ADDR_ITER_3(arr, t1, a1, t2, a2, t3, a3) arr[0] = (unsigned long)&a1; arr[1] = (unsigned long)&a2; arr[2] = (unsigned long)&a3; ++#define __SC_ASSIGN_ADDR_ITER_4(arr, t1, a1, t2, a2, t3, a3, t4, a4) arr[0] = (unsigned long)&a1; arr[1] = (unsigned long)&a2; arr[2] = (unsigned long)&a3; arr[3] = (unsigned long)&a4; ++#define __SC_ASSIGN_ADDR_ITER_5(arr, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) arr[0] = (unsigned long)&a1; arr[1] = (unsigned long)&a2; arr[2] = (unsigned long)&a3; arr[3] = (unsigned long)&a4; arr[4] = (unsigned long)&a5; ++#define __SC_ASSIGN_ADDR_ITER_6(arr, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) arr[0] = (unsigned long)&a1; arr[1] = (unsigned long)&a2; arr[2] = (unsigned long)&a3; arr[3] = (unsigned long)&a4; arr[4] = (unsigned long)&a5; arr[5] = (unsigned long)&a6; ++ ++ ++ ++#define __SC_CONDITIONAL_ASSIGN(idx, type) \ ++ { type __temp_val = (type)(uintptr_t)(new_args_le64[idx]); \ ++ memcpy((void *)(uintptr_t)args_ptr_array[idx], &__temp_val, sizeof(type)); \ ++ (void)0; } ++ ++#define __SC_GEN_SETTER_BODY_ITER_0(...) ++#define __SC_GEN_SETTER_BODY_ITER_1(t1, a1) __SC_CONDITIONAL_ASSIGN(0, t1); ++#define __SC_GEN_SETTER_BODY_ITER_2(t1, a1, t2, a2) __SC_CONDITIONAL_ASSIGN(0, t1); __SC_CONDITIONAL_ASSIGN(1, t2); ++#define __SC_GEN_SETTER_BODY_ITER_3(t1, a1, t2, a2, t3, a3) __SC_CONDITIONAL_ASSIGN(0, t1); __SC_CONDITIONAL_ASSIGN(1, t2); __SC_CONDITIONAL_ASSIGN(2, t3); ++#define __SC_GEN_SETTER_BODY_ITER_4(t1, a1, t2, a2, t3, a3, t4, a4) __SC_CONDITIONAL_ASSIGN(0, t1); __SC_CONDITIONAL_ASSIGN(1, t2); __SC_CONDITIONAL_ASSIGN(2, t3); __SC_CONDITIONAL_ASSIGN(3, t4); ++#define __SC_GEN_SETTER_BODY_ITER_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) __SC_CONDITIONAL_ASSIGN(0, t1); __SC_CONDITIONAL_ASSIGN(1, t2); __SC_CONDITIONAL_ASSIGN(2, t3); __SC_CONDITIONAL_ASSIGN(3, t4); __SC_CONDITIONAL_ASSIGN(4, t5); ++#define __SC_GEN_SETTER_BODY_ITER_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) __SC_CONDITIONAL_ASSIGN(0, t1); __SC_CONDITIONAL_ASSIGN(1, t2); __SC_CONDITIONAL_ASSIGN(2, t3); __SC_CONDITIONAL_ASSIGN(3, t4); __SC_CONDITIONAL_ASSIGN(4, t5); __SC_CONDITIONAL_ASSIGN(5, t6); ++ ++ ++#ifndef CONFIG_IGLOO ++#define igloo_syscall_enter_hook NULL ++#define igloo_syscall_return_hook NULL ++#define __SC_ASSIGN_ADDR_WRAPPER(nr, arr, ...) do {} while (0) ++#define __SC_GEN_SETTER_BODY_WRAPPER(nr, ...) do {} while (0) ++#else ++#define __SC_ASSIGN_ADDR_WRAPPER(nr, arr, ...) \ ++ __SC_ASSIGN_ADDR_ITER_##nr(arr, __VA_ARGS__) ++#define __SC_GEN_SETTER_BODY_WRAPPER(nr, ...) \ ++ __SC_GEN_SETTER_BODY_ITER_##nr(__VA_ARGS__) ++ ++#endif ++ ++#endif +\ No newline at end of file diff --git a/patches/core/igloo.h-drop-declarations-for-forward-declarations.patch b/patches/core/igloo.h-drop-declarations-for-forward-declarations.patch new file mode 100644 index 0000000..ab12474 --- /dev/null +++ b/patches/core/igloo.h-drop-declarations-for-forward-declarations.patch @@ -0,0 +1,23 @@ +From 3f0f02b4c0872f1d7cf61a6282800e9b98c233b4 Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sat, 20 Sep 2025 18:10:12 -0400 +Subject: [PATCH 28/38] igloo.h: drop declarations for forward declarations + +--- + include/igloo.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/include/igloo.h b/include/igloo.h +index 45e1dcd81c..1de6832e81 100644 +--- a/include/igloo.h ++++ b/include/igloo.h +@@ -10,9 +10,6 @@ extern bool igloo_block_halt; // reboot.c + struct user_arg_ptr; // Forward declaration + struct syscall_metadata; // Forward declaration for syscall metadata functions + +-void igloo_sock_release(struct socket *sock); +-void igloo_sock_bind(struct socket *sock, struct sockaddr_storage *address); +-void igloo_hc_newuname(struct new_utsname *name); + unsigned long igloo_arch_syscall_addr(int nr); + + /* Syscall metadata access functions */ diff --git a/patches/core/update-hypercall.h.patch b/patches/core/update-hypercall.h.patch new file mode 100644 index 0000000..5515b86 --- /dev/null +++ b/patches/core/update-hypercall.h.patch @@ -0,0 +1,424 @@ +From 341a2d7402d62274d6ec4c615f6833e14658feba Mon Sep 17 00:00:00 2001 +From: Luke Craig +Date: Sun, 17 May 2026 09:09:26 -0400 +Subject: [PATCH 36/38] update hypercall.h + +--- + include/hypercall.h | 334 +++++++++----------------------------------- + 1 file changed, 69 insertions(+), 265 deletions(-) + +diff --git a/include/hypercall.h b/include/hypercall.h +index b3c308a596..0986c4da38 100644 +--- a/include/hypercall.h ++++ b/include/hypercall.h +@@ -1,238 +1,25 @@ + #ifndef HYPERCALL_H + #define HYPERCALL_H +-#include // Use standard include path + +-static inline unsigned long igloo_hypercall(unsigned long num, unsigned long arg1) { +-#if defined(CONFIG_MIPS) +- register unsigned long reg0 asm("v0") = num; +- register unsigned long reg1 asm("a0") = arg1; +- +- asm volatile( +- "movz $0, $0, $0" +- : "+r"(reg0) +- : "r"(reg1) // num in register v0 +- : "memory" +- ); +- +- return reg0; +- +-#elif defined(CONFIG_ARM64) +- register unsigned long reg0 asm("x8") = num; +- register unsigned long reg1 asm("x0") = arg1; +- asm volatile( +- "msr S0_0_c5_c0_0, xzr \n" +- : "+r"(reg1) +- : "r"(reg0) +- : "memory" +- ); +- +- return reg1; +- +-#elif defined(CONFIG_ARM) +- register unsigned long reg0 asm("r7") = num; +- register unsigned long reg1 asm("r0") = arg1; +- +- asm volatile( +- "mcr p7, 0, r0, c0, c0, 0" +- : "+r"(reg1) +- : "r"(reg0) +- : "memory" +- ); +- +- return reg1; +- +-#elif defined(CONFIG_X86_64) +- register unsigned long reg0 asm("rax") = num; +- register unsigned long reg1 asm("rdi") = arg1; +- +- asm volatile( +- "cpuid" +- : "+r"(reg0) // hypercall num + return value in rax +- : "r"(reg1) // arguments +- : "memory", "rbx", "rcx", "rdx" // No clobber +- ); +- +- return reg0; +- +-#elif defined(CONFIG_I386) +- register unsigned long reg0 asm("eax") = num; +- register unsigned long reg1 asm("edi") = arg1; +- +- asm volatile( +- "cpuid" +- : "+r"(reg0) // hypercall num + return value in rax +- : "r"(reg1) // arguments +- : "memory", "ebx", "ecx", "edx" +- ); +- +- return reg0; +- +-#elif defined(CONFIG_LOONGARCH) +- register unsigned long reg0 asm("a7") = num; +- register unsigned long reg1 asm("a0") = arg1; +- +- asm volatile( +- "cpucfg $r0, $r0" +- : "+r"(reg0) +- : "r"(reg1) +- : "memory" // No clobber +- ); +- +- return reg0; +- +-#elif defined(CONFIG_PPC) +- register unsigned long reg0 asm("r0") = num; +- register unsigned long reg1 asm("r3") = arg1; +- +- asm volatile( +- "xori 10, 10, 0" // User-specified instruction - ASSUMED CORRECT TRIGGER +- : "+r"(reg0) // Input num in r0, Output retval in r0 +- : "r"(reg1) // Input arg1 in r3 +- : "memory", "lr", "ctr", // CRITICAL: clobber link and count registers +- // Clobber volatile condition register fields: +- "cr0", "cr1", "cr5", "cr6", "cr7", +- // Clobber volatile GPRs (r4-r12) - r0,r3 handled by constraints: +- "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" +- // Note: r2 (TOC) and r13 (thread ptr) are usually non-volatile but check hypervisor docs +- ); +- +- return reg0; +- +-#elif defined(CONFIG_RISCV) +- register unsigned long reg0 asm("a7") = num; +- register unsigned long reg1 asm("a0") = arg1; ++#include + +- asm volatile( +- "xori x0, x0, 0" +- : "+r"(reg1) /* Modified: a0/reg1 is both input and output */ +- : "r"(reg0) +- : "memory" +- ); +- +- return reg1; +- +-#else +-#error "No igloo_hypercall support for architecture" +-#endif +-} +- +-static inline unsigned long igloo_hypercall2(unsigned long num, unsigned long arg1, unsigned long arg2) { +-#if defined(CONFIG_ARM64) +- register unsigned long reg0 asm("x8") = num; +- register unsigned long reg1 asm("x0") = arg1; +- register unsigned long reg2 asm("x1") = arg2; +- asm volatile( +- "msr S0_0_c5_c0_0, xzr \n" +- : "+r"(reg1) // Input and output +- : "r"(reg0), "r"(reg2) +- : "memory" +- ); +- return reg1; +-#elif defined(CONFIG_ARM) +- register unsigned long reg0 asm("r7") = num; +- register unsigned long reg1 asm("r0") = arg1; +- register unsigned long reg2 asm("r1") = arg2; +- +- asm volatile( +- "mcr p7, 0, r0, c0, c0, 0" +- : "+r"(reg1) // Input and output +- : "r"(reg0), "r"(reg2) +- : "memory" +- ); +- +- return reg1; +- +-#elif defined(CONFIG_MIPS) +- register unsigned long reg0 asm("v0") = num; +- register unsigned long reg1 asm("a0") = arg1; +- register unsigned long reg2 asm("a1") = arg2; +- +- asm volatile( +- "movz $0, $0, $0" +- : "+r"(reg0) // Input and output in v0 +- : "r"(reg1), "r"(reg2) +- : "memory" +- ); +- return reg0; +-#elif defined(CONFIG_X86_64) +- register unsigned long reg0 asm("rax") = num; +- register unsigned long reg1 asm("rdi") = arg1; +- register unsigned long reg2 asm("rsi") = arg2; +- +- asm volatile( +- "cpuid" +- : "+r"(reg0) // hypercall num + return value in rax +- : "r"(reg1), "r"(reg2) // arguments +- : "memory", "rbx", "rcx", "rdx" +- ); +- +- return reg0; +-#elif defined(CONFIG_I386) +- register unsigned long reg0 asm("eax") = num; +- register unsigned long reg1 asm("edi") = arg1; +- register unsigned long reg2 asm("esi") = arg2; +- +- asm volatile( +- "cpuid" +- : "+r"(reg0) // hypercall num + return value in rax +- : "r"(reg1), "r"(reg2) // arguments +- : "memory", "ebx", "ecx", "edx" +- ); +- +- return reg0; +-#elif defined(CONFIG_LOONGARCH) +- register unsigned long reg0 asm("a7") = num; +- register unsigned long reg1 asm("a0") = arg1; +- register unsigned long reg2 asm("a1") = arg2; +- +- asm volatile( +- "cpucfg $r0, $r0" +- : "+r"(reg1) /* a0/reg1 is both input and output */ +- : "r"(reg0), "r"(reg2) +- : "memory" +- ); +- return reg1; /* Return reg1 (a0) which contains the return value from the hypervisor */ +-#elif defined(CONFIG_PPC) || defined(CONFIG_PPC64) +- register unsigned long reg0 asm("r0") = num; +- register unsigned long reg1 asm("r3") = arg1; +- register unsigned long reg2 asm("r4") = arg2; // Second arg in r4 +- +- asm volatile( +- "xori 10, 10, 0" // User-specified instruction +- : "+r"(reg1) // Input and output in r3 +- : "r"(reg0), "r"(reg2) +- : "memory", "lr", "ctr", +- "cr0", "cr1", "cr5", "cr6", "cr7", +- "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" +- ); +- return reg1; /* Return reg1 (r3) which contains the return value from the hypervisor */ +-#elif defined(CONFIG_RISCV) +- register unsigned long reg0 asm("a7") = num; +- register unsigned long reg1 asm("a0") = arg1; +- register unsigned long reg2 asm("a1") = arg2; +- +- asm volatile( +- "xori x0, x0, 0" +- : "+r"(reg1) /* a0/reg1 is both input and output */ +- : "r"(reg0), "r"(reg2) +- : "memory" +- ); +- return reg1; /* Return reg1 (a0) which contains the return value from the hypervisor */ +-#else +-#error "No igloo_hypercall2 support for architecture" +-#endif +-} +- +-static inline unsigned long igloo_hypercall3(unsigned long num, unsigned long arg1, unsigned long arg2, unsigned long arg3) { ++static inline unsigned long igloo_hypercall4(unsigned long num, ++ unsigned long arg1, ++ unsigned long arg2, ++ unsigned long arg3, ++ unsigned long arg4) ++{ + #if defined(CONFIG_ARM64) + register unsigned long reg0 asm("x8") = num; + register unsigned long reg1 asm("x0") = arg1; + register unsigned long reg2 asm("x1") = arg2; + register unsigned long reg3 asm("x2") = arg3; ++ register unsigned long reg4 asm("x3") = arg4; ++ + asm volatile( +- "msr S0_0_c5_c0_0, xzr \n" +- : "+r"(reg1) // Input and output +- : "r"(reg0), "r"(reg2), "r"(reg3) ++ "msr S0_0_c5_c0_0, xzr \n" ++ : "+r"(reg1) ++ : "r"(reg0), "r"(reg2), "r"(reg3), "r"(reg4) + : "memory" + ); + return reg1; +@@ -241,101 +28,118 @@ static inline unsigned long igloo_hypercall3(unsigned long num, unsigned long ar + register unsigned long reg1 asm("r0") = arg1; + register unsigned long reg2 asm("r1") = arg2; + register unsigned long reg3 asm("r2") = arg3; ++ register unsigned long reg4 asm("r3") = arg4; + + asm volatile( +- "mcr p7, 0, r0, c0, c0, 0" +- : "+r"(reg1) // Input and output +- : "r"(reg0), "r"(reg2), "r"(reg3) ++ "mcr p7, 0, r0, c0, c0, 0" ++ : "+r"(reg1) ++ : "r"(reg0), "r"(reg2), "r"(reg3), "r"(reg4) + : "memory" + ); +- + return reg1; +- + #elif defined(CONFIG_MIPS) + register unsigned long reg0 asm("v0") = num; + register unsigned long reg1 asm("a0") = arg1; + register unsigned long reg2 asm("a1") = arg2; + register unsigned long reg3 asm("a2") = arg3; ++ register unsigned long reg4 asm("a3") = arg4; + + asm volatile( +- "movz $0, $0, $0" +- : "+r"(reg0) // Input and output in v0 +- : "r"(reg1), "r"(reg2), "r"(reg3) ++ "movz $0, $0, $0" ++ : "+r"(reg0) ++ : "r"(reg1), "r"(reg2), "r"(reg3), "r"(reg4) + : "memory" + ); + return reg0; + #elif defined(CONFIG_X86_64) +- register unsigned long reg0 asm("rax") = num; +- register unsigned long reg1 asm("rdi") = arg1; +- register unsigned long reg2 asm("rsi") = arg2; +- register unsigned long reg3 asm("rdx") = arg3; ++ unsigned long reg0 = num; ++ register unsigned long reg4 asm("r10") = arg4; + + asm volatile( +- "cpuid" +- : "+r"(reg0) // hypercall num + return value in rax +- : "r"(reg1), "r"(reg2), "r"(reg3) // arguments +- : "memory", "rbx", "rcx" ++ "outl %%eax, $0x88" ++ : "+a"(reg0) ++ : "D"(arg1), "S"(arg2), "d"(arg3), "r"(reg4) ++ : "memory" + ); +- + return reg0; + #elif defined(CONFIG_I386) +- register unsigned long reg0 asm("eax") = num; +- register unsigned long reg1 asm("edi") = arg1; +- register unsigned long reg2 asm("esi") = arg2; +- register unsigned long reg3 asm("edx") = arg3; ++ unsigned long reg0 = num; + + asm volatile( +- "cpuid" +- : "+r"(reg0) // hypercall num + return value in eax +- : "r"(reg1), "r"(reg2), "r"(reg3) // arguments +- : "memory", "ebx", "ecx" ++ "outl %%eax, $0x88" ++ : "+a"(reg0) ++ : "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4) ++ : "memory" + ); +- + return reg0; + #elif defined(CONFIG_LOONGARCH) + register unsigned long reg0 asm("a7") = num; + register unsigned long reg1 asm("a0") = arg1; + register unsigned long reg2 asm("a1") = arg2; + register unsigned long reg3 asm("a2") = arg3; ++ register unsigned long reg4 asm("a3") = arg4; + + asm volatile( + "cpucfg $r0, $r0" +- : "+r"(reg1) /* a0/reg1 is both input and output */ +- : "r"(reg0), "r"(reg2), "r"(reg3) ++ : "+r"(reg1) ++ : "r"(reg0), "r"(reg2), "r"(reg3), "r"(reg4) + : "memory" + ); +- return reg1; /* Return reg1 (a0) which contains the return value from the hypervisor */ ++ return reg1; + #elif defined(CONFIG_PPC) || defined(CONFIG_PPC64) + register unsigned long reg0 asm("r0") = num; + register unsigned long reg1 asm("r3") = arg1; + register unsigned long reg2 asm("r4") = arg2; + register unsigned long reg3 asm("r5") = arg3; +- ++ register unsigned long reg4 asm("r6") = arg4; ++ + asm volatile( +- "xori 10, 10, 0" // User-specified instruction +- : "+r"(reg1) // Input and output in r3 +- : "r"(reg0), "r"(reg2), "r"(reg3) ++ "xori 10, 10, 0" ++ : "+r"(reg1) ++ : "r"(reg0), "r"(reg2), "r"(reg3), "r"(reg4) + : "memory", "lr", "ctr", + "cr0", "cr1", "cr5", "cr6", "cr7", +- "r6", "r7", "r8", "r9", "r10", "r11", "r12" ++ "r7", "r8", "r9", "r10", "r11", "r12" + ); +- return reg1; /* Return reg1 (r3) which contains the return value from the hypervisor */ ++ return reg1; + #elif defined(CONFIG_RISCV) + register unsigned long reg0 asm("a7") = num; + register unsigned long reg1 asm("a0") = arg1; + register unsigned long reg2 asm("a1") = arg2; + register unsigned long reg3 asm("a2") = arg3; ++ register unsigned long reg4 asm("a3") = arg4; + + asm volatile( + "xori x0, x0, 0" +- : "+r"(reg1) /* a0/reg1 is both input and output */ +- : "r"(reg0), "r"(reg2), "r"(reg3) ++ : "+r"(reg1) ++ : "r"(reg0), "r"(reg2), "r"(reg3), "r"(reg4) + : "memory" + ); +- return reg1; /* Return reg1 (a0) which contains the return value from the hypervisor */ ++ return reg1; + #else +-#error "No igloo_hypercall3 support for architecture" ++#error "No igloo_hypercall4 support for architecture" + #endif + } + +-#endif +\ No newline at end of file ++static inline unsigned long igloo_hypercall(unsigned long num, ++ unsigned long arg1) ++{ ++ return igloo_hypercall4(num, arg1, 0, 0, 0); ++} ++ ++static inline unsigned long igloo_hypercall2(unsigned long num, ++ unsigned long arg1, ++ unsigned long arg2) ++{ ++ return igloo_hypercall4(num, arg1, arg2, 0, 0); ++} ++ ++static inline unsigned long igloo_hypercall3(unsigned long num, ++ unsigned long arg1, ++ unsigned long arg2, ++ unsigned long arg3) ++{ ++ return igloo_hypercall4(num, arg1, arg2, arg3, 0); ++} ++ ++#endif diff --git a/scripts/export-series.sh b/scripts/export-series.sh new file mode 100755 index 0000000..71472ee --- /dev/null +++ b/scripts/export-series.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Write a development tree back out as the committed patch series. +# +# ./scripts/export-series.sh 6.13 /path/to/workdir +# +# Regenerates patches//*.patch and the series file from every commit +# above base-. Patches whose content is byte-identical to an existing +# core/ patch keep referencing core/ rather than being duplicated per version. +set -euo pipefail + +VERSION="${1:?usage: export-series.sh }" +WORKDIR="${2:?}" + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +PATCHES="$REPO_ROOT/patches" +BASE_TAG=$(python3 -c "import json;print(json.load(open('$PATCHES/base.json'))['$VERSION']['tag'])") + +STAGE=$(mktemp -d); trap 'rm -rf "$STAGE"' EXIT +git -C "$WORKDIR" format-patch --no-signature -o "$STAGE" "base-${BASE_TAG}..HEAD" >/dev/null + +norm() { sed -e '/^From [0-9a-f]\{40\}/d' -e '/^index [0-9a-f]/d' -e '/^From: /d' -e '/^Date: /d' "$1"; } + +rm -f "$PATCHES/$VERSION"/*.patch +: > "$PATCHES/$VERSION/series" + +for f in "$STAGE"/*.patch; do + n=$(basename "$f") + matched="" + for c in "$PATCHES"/core/*.patch; do + [ -e "$c" ] || continue + if diff -q <(norm "$f") <(norm "$c") >/dev/null 2>&1; then matched="core/$(basename "$c")"; break; fi + done + if [ -n "$matched" ]; then + echo "$matched" >> "$PATCHES/$VERSION/series" + else + cp "$f" "$PATCHES/$VERSION/$n" + echo "$VERSION/$n" >> "$PATCHES/$VERSION/series" + fi +done + +echo "OK: exported $(wc -l < "$PATCHES/$VERSION/series") patches for $VERSION" +echo " verify with: ./scripts/verify-series.sh $VERSION " diff --git a/scripts/import-series.sh b/scripts/import-series.sh new file mode 100755 index 0000000..353c626 --- /dev/null +++ b/scripts/import-series.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Git-as-workspace: materialise a version's series as a real git tree you can +# develop in, bisect within, and rebase. +# +# ./scripts/import-series.sh 6.13 /path/to/workdir +# +# Develop there as normal (commit on top), then run export-series.sh to write +# the series back. The committed patches remain the source of truth; this tree +# is a regenerated convenience, not a long-lived branch -- which is the whole +# point of the migration away from main_4.10 / main_6.13. +set -euo pipefail + +VERSION="${1:?usage: import-series.sh }" +WORKDIR="${2:?}" + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +PATCHES="$REPO_ROOT/patches" + +[ -f "$PATCHES/$VERSION/series" ] || { echo "no series for $VERSION" >&2; exit 1; } + +BASE_TAG=$(python3 -c "import json;print(json.load(open('$PATCHES/base.json'))['$VERSION']['tag'])") +MAJOR="${BASE_TAG%%.*}" +URL="https://cdn.kernel.org/pub/linux/kernel/v${MAJOR}.x/linux-${BASE_TAG}.tar.xz" + +mkdir -p "$WORKDIR" +if [ ! -e "$WORKDIR/Makefile" ]; then + echo ">>> fetching $URL" + TARBALL=$(nix-prefetch-url --print-path "$URL" 2>/dev/null | tail -1) + echo ">>> extracting into $WORKDIR" + tar xf "$TARBALL" -C "$WORKDIR" --strip-components=1 + git -C "$WORKDIR" init -q . + git -C "$WORKDIR" add -A + git -C "$WORKDIR" -c user.email=igloo@local -c user.name=igloo \ + commit -qm "linux ${BASE_TAG} (pristine upstream tarball)" + git -C "$WORKDIR" tag "base-${BASE_TAG}" +fi + +echo ">>> applying series" +while read -r p; do + case "$p" in ''|\#*) continue ;; esac + git -C "$WORKDIR" -c user.email=igloo@local -c user.name=igloo \ + am -q "$PATCHES/$p" +done < "$PATCHES/$VERSION/series" + +echo "OK: $WORKDIR is linux ${BASE_TAG} + the IGLOO ${VERSION} series" +echo " base tag: base-${BASE_TAG} (export with: export-series.sh $VERSION $WORKDIR)" diff --git a/scripts/verify-series.sh b/scripts/verify-series.sh new file mode 100755 index 0000000..6c07dce --- /dev/null +++ b/scripts/verify-series.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Slice 1 acceptance test. +# +# Applies patches//series to the PRISTINE kernel.org tarball and proves +# the result matches the fork branch we are replacing. +# +# ./scripts/verify-series.sh 4.10 +# +# NOTE ON THE BASELINE. kernel.org release tarballs are `git archive` output and +# therefore honour .gitattributes `export-ignore`, so they are NOT byte-identical +# to the git tag: v4.10's tarball lacks .gitattributes, .get_maintainer.ignore, +# and two arch/sh linker scripts. None are build-affecting and none are touched +# by the IGLOO series. +# +# So the test is not "tree hashes are equal" (they can't be) but the stronger, +# checkable claim: the patched tree differs from the fork branch ONLY by that +# known export-ignore set. Any other path appearing in the diff is a real +# regression and fails the run. +set -euo pipefail + +VERSION="${1:?usage: verify-series.sh }" +TARBALL="${2:?}" +FORK_REF="${3:?}" +GIT_DIR="${4:?path to a clone of rehosting/linux holding }" + +# Paths upstream marks export-ignore, so they are absent from release tarballs. +# Anything else in the final diff is a genuine mismatch. +EXPORT_IGNORED='^(\.gitattributes|\.get_maintainer\.ignore|arch/sh/boot/(compressed|romimage)/vmlinux\.scr)$' + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +PATCHES="$REPO_ROOT/patches" +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +echo ">>> extracting $(basename "$TARBALL")" +mkdir -p "$WORK/src" +tar xf "$TARBALL" -C "$WORK/src" --strip-components=1 + +cd "$WORK/src" +git init -q . +git add -A +git -c user.email=nix@local -c user.name=nix commit -qm "pristine upstream" +BASE_TREE=$(git rev-parse HEAD^{tree}) +echo ">>> pristine tree: $BASE_TREE" + +echo ">>> applying $(grep -cv '^\s*\(#.*\)\?$' "$PATCHES/$VERSION/series") patches" +n=0 +while read -r p; do + case "$p" in ''|\#*) continue ;; esac + n=$((n + 1)) + if ! git -c user.email=nix@local -c user.name=nix am -q "$PATCHES/$p" 2>/dev/null; then + echo "FAIL: patch $n did not apply: $p" >&2 + git am --abort 2>/dev/null || true + exit 1 + fi +done < "$PATCHES/$VERSION/series" + +echo ">>> patched tree: $(git rev-parse HEAD^{tree})" + +git remote add fork "$GIT_DIR" +git fetch -q --depth 60 fork "+${FORK_REF}:refs/heads/forkref" + +UNEXPECTED=$(git diff --name-only forkref HEAD | grep -Ev "$EXPORT_IGNORED" || true) + +if [ -z "$UNEXPECTED" ]; then + echo "PASS: $n patches applied cleanly; tree matches $FORK_REF" + echo " (differs only by upstream export-ignored paths, as expected)" +else + echo "MISMATCH: unexpected differences vs $FORK_REF:" >&2 + echo "$UNEXPECTED" >&2 + exit 1 +fi From d8538f31906c1a37ceb3a6e35d5b0e982aa4fb55 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 12 Aug 2026 19:00:55 -0400 Subject: [PATCH 02/28] kernel.nix: name the kernel-devel output `dev`, not `devel` nixpkgs' multiple-outputs setup hook relocates include/ to `outputDev`, which falls back to "out" when no output is literally named "dev". Calling it "devel" therefore moved the kernel headers into $out and left a kernel-devel tree that looked complete in a directory listing but could not build a module. Found by building igloo.ko against the output rather than inspecting it; the dev closure goes 34M -> 91M once include/ actually lands there. --- nix/kernel.nix | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/nix/kernel.nix b/nix/kernel.nix index 280b412..632e65f 100644 --- a/nix/kernel.nix +++ b/nix/kernel.nix @@ -4,10 +4,15 @@ # toolchain resolved by kernelsmith instead of an unpinned musl.cc download. # # Two outputs: -# out -- vmlinux, the arch's boot artifact, Module.symvers -# devel -- the kernel-devel tree out-of-tree modules build against +# out -- vmlinux, the arch's boot artifact, Module.symvers +# dev -- the kernel-devel tree out-of-tree modules build against # -# The `devel` output is the point of the whole exercise: igloo_driver consumes +# The dev output MUST be called "dev": nixpkgs' multiple-outputs setup hook +# relocates include/ to `outputDev`, which falls back to "out" when no output is +# literally named "dev". Naming it "devel" therefore silently moved include/ +# into $out and produced a devel tree that could not build a module. +# +# The `dev` output is the point of the whole exercise: igloo_driver consumes # it as a DERIVATION INPUT, so a different kernel is a different hash and a # stale-CRC .ko cannot be produced. Note kernelsmith's own buildKernel installs # `headers_install` output as kernel-devel -- those are UAPI headers, NOT the @@ -79,7 +84,7 @@ pkgs.stdenv.mkDerivation { inherit version; name = "igloo-kernel-${version}-${target}"; - outputs = [ "out" "devel" ]; + outputs = [ "out" "dev" ]; dontUnpack = true; enableParallelBuilding = true; @@ -133,7 +138,7 @@ pkgs.stdenv.mkDerivation { # build (make -C $KDIR M=$PWD modules) needs Makefile/.config/Module.symvers, # headers, arch Makefiles and scripts/ host tools -- not boot images or the # bulk of tools/. - D=$devel + D=$dev mkdir -p $D cp build/.config build/Module.symvers $D/ cp linux/Makefile linux/Kconfig $D/ || true From cfffba3fafc722511d0565bcb1518ca21a41f6f6 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 12 Aug 2026 19:07:42 -0400 Subject: [PATCH 03/28] kernel.nix: make old trees build in the Nix sandbox (4.10 now green) Kernel 4.10 validates its O= output directory with `cd $dir && /bin/pwd`, and there is no /bin/pwd in the sandbox, so the build died as: Makefile:141: *** failed to create output directory "/build/build" which points nowhere near the cause. The Docker build only worked because the Ubuntu image happens to ship coreutils at /bin. Also patchShebangs the kbuild helpers, whose #!/usr/bin/awk-style shebangs otherwise fail "not found" and cascade into Kconfig syntax errors. Both fixes live in the builder, NOT the patch series: they are environment adaptations rather than IGLOO changes, and the series has to remain a faithful description of the fork branch for verify-series.sh to mean anything. 4.10/armel now builds end to end on kernelsmith's k4 band (Bootlin gcc 9.3.0): 240M vmlinux + 7.1M zImage + Module.symvers, ARM EABI5. This was the plan's biggest unretired risk; the compiler era was never the problem. --- nix/kernel.nix | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/nix/kernel.nix b/nix/kernel.nix index 632e65f..ff376e2 100644 --- a/nix/kernel.nix +++ b/nix/kernel.nix @@ -105,6 +105,19 @@ pkgs.stdenv.mkDerivation { cp -r ${src} linux && chmod -R u+w linux mkdir -p build + # Old trees vs. the Nix sandbox. Both of these work in the Docker build only + # because an Ubuntu image happens to have the paths; neither is an IGLOO + # change, so they are fixed here in the builder rather than in the patch + # series (which must stay a faithful description of the fork branch). + # + # 4.10's Makefile validates KBUILD_OUTPUT with `cd $dir && /bin/pwd`, and + # there is no /bin/pwd in the sandbox -- it fails with the profoundly + # unhelpful "failed to create output directory". + sed -i 's|/bin/pwd|pwd|g' linux/Makefile + # Kbuild helpers carry shebangs like #!/usr/bin/awk that don't exist here; + # unpatched they fail "not found" and cascade into Kconfig syntax errors. + patchShebangs linux/scripts linux/tools 2>/dev/null || true + echo ">>> .config (cpp-assembled fragment + olddefconfig)" cp ${config} build/.config make -C linux O=$PWD/build olddefconfig From a3fc984ca92d2656e00c6e7e2122509706c217c1 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 12 Aug 2026 19:15:53 -0400 Subject: [PATCH 04/28] ci: gate the patch series, and make the fork comparison optional "The series applies cleanly to the pinned upstream tarball" is the permanent invariant: without it enforced, someone edits a tree, forgets to export, and the committed series quietly stops describing reality. Comparing against the fork branch is a MIGRATION check -- once main_4.10 and main_6.13 are retired there is nothing to compare against -- so it is now an optional 3rd/4th argument rather than required. The workflow has NOT been exercised on the self-hosted runners; treat the runner and Cachix wiring as a first draft. It does push to Cachix from PRs, not only releases, since PR builds never populating the cache is why cross-toolchain closures get rebuilt from source elsewhere in this stack. --- .github/workflows/nix.yml | 75 +++++++++++++++++++++++++++++++++++++++ scripts/verify-series.sh | 15 ++++++-- 2 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/nix.yml diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml new file mode 100644 index 0000000..2ceb81e --- /dev/null +++ b/.github/workflows/nix.yml @@ -0,0 +1,75 @@ +# The patch-series gate, plus a representative build per version. +# +# Without this gate the series model degrades silently: someone edits a tree, +# forgets to export, and the committed series stops describing reality. "The +# series applies cleanly to the pinned upstream tarball" is the invariant that +# makes patches-as-source-of-truth safe. +# +# NOTE: not yet exercised on the self-hosted runners -- treat the runner and +# cache wiring as a first draft to be confirmed on the first real run. +name: nix (patch series + kernels) + +on: + pull_request: + push: + branches: [main, nix-patchset] + workflow_dispatch: + +concurrency: + group: nix-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + series: + name: series applies (${{ matrix.version }}) + runs-on: rehosting-arc + strategy: + fail-fast: false + matrix: + version: ["4.10", "6.13"] + steps: + - uses: actions/checkout@v4 + + # install-nix-action trips over root-owned /nix on these runners. + - uses: rehosting/nix-setup@v1 + + - name: Fetch the pinned upstream tarball + id: tarball + run: | + set -euo pipefail + TAG=$(python3 -c "import json;print(json.load(open('patches/${{ matrix.version }}/../base.json'))['${{ matrix.version }}']['tag'])") + MAJOR="${TAG%%.*}" + URL="https://cdn.kernel.org/pub/linux/kernel/v${MAJOR}.x/linux-${TAG}.tar.xz" + echo "path=$(nix-prefetch-url --print-path "$URL" | tail -1)" >> "$GITHUB_OUTPUT" + + - name: Series applies cleanly to pristine upstream + run: ./scripts/verify-series.sh "${{ matrix.version }}" "${{ steps.tarball.outputs.path }}" + + build: + name: build ${{ matrix.cell }} + runs-on: rehosting-arc + needs: series + strategy: + fail-fast: false + matrix: + # One cell per version keeps the gate fast; `nix build .#all` covers the + # full 18-cell matrix on dispatch/release. + cell: ["kernel-4.10-armel", "kernel-6.13-armel"] + steps: + - uses: actions/checkout@v4 + - uses: rehosting/nix-setup@v1 + + - name: Build + run: nix build --print-out-paths ".#packages.x86_64-linux.\"${{ matrix.cell }}\"" + + # Populate the cache from PRs too. Pushing only on release is why cross + # toolchain closures get rebuilt from source (~68 min observed elsewhere + # in this stack) instead of substituted. + - name: Push to Cachix + if: ${{ env.CACHIX_AUTH_TOKEN != '' }} + env: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + run: | + nix profile install nixpkgs#cachix + nix build --print-out-paths ".#packages.x86_64-linux.\"${{ matrix.cell }}\"" \ + | cachix push rehosting-tools diff --git a/scripts/verify-series.sh b/scripts/verify-series.sh index 6c07dce..86c2d6d 100755 --- a/scripts/verify-series.sh +++ b/scripts/verify-series.sh @@ -18,10 +18,13 @@ # regression and fails the run. set -euo pipefail -VERSION="${1:?usage: verify-series.sh }" +VERSION="${1:?usage: verify-series.sh [ ]}" TARBALL="${2:?}" -FORK_REF="${3:?}" -GIT_DIR="${4:?path to a clone of rehosting/linux holding }" +# Optional: compare against the fork branch being replaced. This is a MIGRATION +# check -- once the branches are retired there is nothing to compare to, and the +# permanent invariant CI enforces is simply "the series applies cleanly". +FORK_REF="${3:-}" +GIT_DIR="${4:-}" # Paths upstream marks export-ignore, so they are absent from release tarballs. # Anything else in the final diff is a genuine mismatch. @@ -57,6 +60,12 @@ done < "$PATCHES/$VERSION/series" echo ">>> patched tree: $(git rev-parse HEAD^{tree})" +if [ -z "$FORK_REF" ]; then + echo "PASS: $n patches applied cleanly to pristine linux-${VERSION}" + echo " (no fork ref given; skipping migration comparison)" + exit 0 +fi + git remote add fork "$GIT_DIR" git fetch -q --depth 60 fork "+${FORK_REF}:refs/heads/forkref" From b0df4af47aa9eb9064fc6153b4aa130421514a31 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 12 Aug 2026 19:57:42 -0400 Subject: [PATCH 05/28] nix: build osi/cosi from PINNED extractors, and split out an unstripped vmlinux Adds the two analysis artifacts shipped alongside every kernel, and the release seam that reassembles the tarballs penguin already consumes. The packaging was the easy half; the finding is provenance. Both extractors are unpinned fetches of a default branch at image-build time: * extract_kernelinfo -- wget'd from refs/heads/main of panda-re/panda-ng, a repo this stack is retiring in favour of qemu/. * dwarf2json -- `git clone --depth 1` of the default branch of rehosting/dwarf2json, a FORK. nixpkgs ships UPSTREAM volatility's tool under the same attribute name, so reaching for pkgs.dwarf2json would silently produce different ISFs -- and penguin loads them at runtime (pyplugins/apis/kffi.py reads cosi..json.xz). The fork is packaged with buildGoModule from a pinned rev instead. Every osi.config and COSI ISF shipped to date was produced by whatever those two branches said on image-build day. kernel.nix gains a third output, `vmlinux`, holding the UNSTRIPPED image. _in_container_build.sh extracts osi/cosi from the build-tree vmlinux and strips the shipped copy afterwards; a derivation cannot reproduce that ordering, so stripping in place left the analysis derivations reading a vmlinux with no debug info on exactly the mips*/powerpc* targets that ship one. $out now carries a vmlinux only where it is the deliverable, matching build.sh more closely than before. Named `vmlinux` and not `debug`, which nixpkgs' multiple-outputs machinery treats specially -- the same trap class as the earlier dev/devel mistake. VALIDATED against the profile shipped in rehosting/penguin:latest, for 6.13/armel: 61 lines both, identical key set, and every value identical except two: - task.per_cpu_offsets_addr, off by 8 bytes - name, which embeds the kernel build timestamp; ours is '@0' because the build sets KBUILD_BUILD_TIMESTAMP for reproducibility. Self-consistent, since the kernel and its profile come from the same derivation. Every other struct offset and address matches exactly, across a completely different toolchain. Known contract gap: perf. is not reproduced. build.sh swallows its failure, so the shipped tarball already contains whatever compiled that day; no consumer was found in penguin. See nix/release.nix. --- flake.nix | 49 +++++++++++++++++++-- nix/analysis.nix | 108 +++++++++++++++++++++++++++++++++++++++++++++++ nix/kernel.nix | 32 +++++++++++--- nix/release.nix | 89 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+), 11 deletions(-) create mode 100644 nix/analysis.nix create mode 100644 nix/release.nix diff --git a/flake.nix b/flake.nix index ffd5e2a..6557d4f 100644 --- a/flake.nix +++ b/flake.nix @@ -44,10 +44,16 @@ sourceLib = import ./nix/source.nix { inherit pkgs; }; mkKernel = import ./nix/kernel.nix { inherit pkgs kernelsmith; }; - # kernelsmith's arch table covers 12 arches; these two are ours and not - # yet in it. Listed explicitly rather than silently dropped -- see draft 34 - # Slice 2, which lands them upstream instead of forking the table. - kernelsmithMissing = [ "loongarch64" "riscv64" ]; + # Arches kernelsmith cannot resolve a toolchain for yet. Listed explicitly + # rather than silently dropped, so `nix build .#all` never quietly ships a + # smaller matrix than build.sh does. + # + # Now empty: riscv64 landed as a Bootlin k6 pin, and loongarch64 as a + # kernel-only gcc 13.3 (no libc toolchain exists for it from any source -- + # see kernelsmith's matrix.k6LoongarchKernel). Kept as a mechanism rather + # than deleted, so a future arch gap is declared here instead of silently + # shrinking `nix build .#all` below what build.sh covers. + kernelsmithMissing = [ ]; buildable = version: builtins.filter (t: !(builtins.elem t kernelsmithMissing)) matrix.${version}; @@ -75,6 +81,25 @@ (buildable version)) (builtins.attrNames matrix)); + # ---- the release seam --------------------------------------------- + # Keep emitting the two tarballs penguin consumes today, so switching + # linux_builder to nix does not require touching penguin at all. Moving + # penguin to a flake input is a separate, later change. + analysisLib = import ./nix/analysis.nix { inherit pkgs; }; + releaseLib = import ./nix/release.nix { inherit pkgs; }; + + # Per-cell record carrying everything the assembly needs. + cellRecords = version: map + (target: + let kernel = cells."kernel-${version}-${target}"; in { + inherit version target kernel; + osi = analysisLib.osiConfig { inherit kernel version target; }; + cosi = analysisLib.cosiJson { inherit kernel version target; }; + }) + (buildable version); + + allRecords = lib.concatMap cellRecords (builtins.attrNames matrix); + in { packages.${system} = cells // { @@ -83,6 +108,22 @@ # Everything buildable today, in one derivation, for CI. all = pkgs.linkFarm "igloo-kernels-all" (lib.mapAttrsToList (n: v: { name = n; path = v; }) cells); + + # Drop-in replacements for the Docker build's release artifacts. + kernels-latest = releaseLib.kernelsTarball { + versions = map + (version: { + inherit version; + dir = releaseLib.kernelsDir { inherit version; cells = cellRecords version; }; + }) + (builtins.attrNames matrix); + }; + kernel-devel-all = releaseLib.develTarball { cells = allRecords; }; + + # The analysis tools, pinned. Exposed so their provenance is inspectable + # and so igloo_driver can reuse dwarf2json for its own ISF (it runs the + # same fork over igloo.ko) instead of re-deriving the pin. + inherit (analysisLib) dwarf2json extractKernelinfo; }; # The patched source trees, so `nix build .#sources.x86_64-linux."6.13"` diff --git a/nix/analysis.nix b/nix/analysis.nix new file mode 100644 index 0000000..c75f4d9 --- /dev/null +++ b/nix/analysis.nix @@ -0,0 +1,108 @@ +# The two analysis artifacts shipped alongside each kernel: +# +# osi..config -- PANDA osi_linux kernel profile (struct offsets), +# extracted by running gdb over the DEBUGGABLE vmlinux +# cosi..json.xz -- volatility-style symbol table from the same vmlinux +# +# Both read the UNSTRIPPED build-tree vmlinux. That is why kernel.nix exposes a +# separate `vmlinux` output and does not strip in place: _in_container_build.sh +# gets away with it only by ordering (extract first, strip the shipped copy +# afterwards), which a derivation cannot reproduce once the kernel is realised. +# +# PROVENANCE NOTE -- both tools are fetched unpinned today. +# +# * extract_kernelinfo: the Dockerfile wgets it from `refs/heads/main` of +# panda-re/panda-ng at image-build time, from a repo the stack is actively +# retiring (CLAUDE.md: panda-ng is on the way out, new work goes to qemu/). +# * dwarf2json: embedded-toolchains' Dockerfile does `git clone --depth 1` of +# the DEFAULT BRANCH of rehosting/dwarf2json -- a FORK, not upstream +# volatilityfoundation. nixpkgs ships the upstream tool under that name; using +# it would silently produce different ISFs, and penguin consumes them at +# runtime (pyplugins/apis/kffi.py reads cosi..json.xz). So build the +# fork from a pinned rev. +# +# Every osi.config and cosi ISF shipped to date was produced by "whatever the +# default branch said that day". Both are pinned to commits here. +{ pkgs }: + +let + inherit (pkgs) lib; + + # rehosting/dwarf2json @ main. Sole dependency is spf13/pflag, so the vendor + # tree is tiny -- but it must still be a fixed-output vendor derivation. + dwarf2json = pkgs.buildGoModule { + pname = "dwarf2json"; + version = "unstable-2026-rehosting-fork"; + src = pkgs.fetchFromGitHub { + owner = "rehosting"; + repo = "dwarf2json"; + rev = "45f9343560b7ece6be23415695fe4d0c2678759d"; + hash = "sha256-cFIXDmVv58DBtj89Wb77ZjtK6vz5LTF/wKPpEd88t9M="; + }; + vendorHash = "sha256-3PnXB8AfZtgmYEPJuh0fwvG38dtngoS/lxyx3H+rvFs="; + meta.description = "rehosting fork of dwarf2json (produces the COSI ISFs penguin loads)"; + }; + + # panda-re/panda-ng, plugins/osi_linux/utils/kernelinfo_gdb. + # Last touched 2025-04-14 ("try pcpu_hot"); pinned rather than tracking main. + kernelinfoRev = "1764d2efe73712944996647b582862522f36efc9"; + kernelinfoUrl = f: + "https://raw.githubusercontent.com/panda-re/panda-ng/${kernelinfoRev}/plugins/osi_linux/utils/kernelinfo_gdb/${f}"; + + extractKernelinfo = pkgs.runCommand "extract-kernelinfo-${lib.substring 0 8 kernelinfoRev}" + { + py = pkgs.fetchurl { + url = kernelinfoUrl "extract_kernelinfo.py"; + hash = "sha256-CO9UYvk+WwZHo2zGVNYwHgy6TUR9D7Ysn/FYNH/yGfA="; + }; + sh = pkgs.fetchurl { + url = kernelinfoUrl "run.sh"; + hash = "sha256-Df4GI32UmioUc5/830XglQ8Er50Kj4md1y6uyOAt2ZU="; + }; + } '' + mkdir -p $out + cp $py $out/extract_kernelinfo.py + cp $sh $out/run.sh + chmod +x $out/run.sh + # run.sh is `#!/bin/bash`, which does not exist in the sandbox -- the same + # class of breakage as 4.10's `/bin/pwd` in kernel.nix. Unpatched it fails + # with the deeply unhelpful "cannot execute: required file not found". + patchShebangs $out/run.sh + ''; + +in +rec { + inherit extractKernelinfo dwarf2json; + + # gdb reads a foreign-arch vmlinux fine: nixpkgs builds it --enable-targets=all, + # so no per-arch gdb is needed (the Docker build relies on Ubuntu's multiarch + # gdb for the same reason, just without saying so). + osiConfig = { kernel, version, target }: + pkgs.runCommand "igloo-osi-${version}-${target}" + { + nativeBuildInputs = [ pkgs.gdb pkgs.bash ]; + meta.description = "PANDA osi_linux profile for ${version}/${target}"; + } '' + vmlinux=${kernel.vmlinux}/vmlinux.${target} + test -f "$vmlinux" || { echo "no unstripped vmlinux at $vmlinux"; exit 1; } + + # Faithful to _in_container_build.sh: the [target] section header is + # written FIRST, then the extractor's output is appended to it. + echo "[${target}]" > $out + ${extractKernelinfo}/run.sh "$vmlinux" profile.out + test -s profile.out || { echo "extract_kernelinfo produced nothing"; exit 1; } + cat profile.out >> $out + ''; + + cosiJson = { kernel, version, target }: + pkgs.runCommand "igloo-cosi-${version}-${target}" + { + # NOT pkgs.dwarf2json -- that is upstream volatility's, not our fork. + nativeBuildInputs = [ dwarf2json pkgs.xz ]; + meta.description = "COSI symbol table for ${version}/${target}"; + } '' + vmlinux=${kernel.vmlinux}/vmlinux.${target} + test -f "$vmlinux" || { echo "no unstripped vmlinux at $vmlinux"; exit 1; } + dwarf2json linux --elf "$vmlinux" | xz -c > $out + ''; +} diff --git a/nix/kernel.nix b/nix/kernel.nix index ff376e2..1051387 100644 --- a/nix/kernel.nix +++ b/nix/kernel.nix @@ -3,9 +3,22 @@ # This is a faithful port of _in_container_build.sh's per-target build, with the # toolchain resolved by kernelsmith instead of an unpinned musl.cc download. # -# Two outputs: -# out -- vmlinux, the arch's boot artifact, Module.symvers -# dev -- the kernel-devel tree out-of-tree modules build against +# Three outputs: +# out -- the arch's boot artifact, Module.symvers, and (mips*/powerpc* +# only, matching build.sh) a STRIPPED vmlinux +# dev -- the kernel-devel tree out-of-tree modules build against +# vmlinux -- the UNSTRIPPED vmlinux, for osi/cosi extraction +# +# The vmlinux split is not tidiness. _in_container_build.sh runs the osi/cosi +# extractors against the build-tree vmlinux and only THEN strips the copy it +# ships -- an ordering a derivation cannot reproduce, because by the time +# anything downstream sees the kernel it is already realised. Stripping in place +# would leave the analysis derivations reading a vmlinux with no debug info, on +# exactly the mips*/powerpc* targets that ship one. +# +# Named `vmlinux` and not `debug`: `debug` is a name nixpkgs' multiple-outputs +# machinery attaches meaning to, and this file already lost a day to `dev` vs +# `devel` (see below). # # The dev output MUST be called "dev": nixpkgs' multiple-outputs setup hook # relocates include/ to `outputDev`, which falls back to "out" when no output is @@ -84,7 +97,7 @@ pkgs.stdenv.mkDerivation { inherit version; name = "igloo-kernel-${version}-${target}"; - outputs = [ "out" "dev" ]; + outputs = [ "out" "dev" "vmlinux" ]; dontUnpack = true; enableParallelBuilding = true; @@ -135,10 +148,15 @@ pkgs.stdenv.mkDerivation { runHook preInstall mkdir -p $out - # vmlinux is always kept for analysis (osi/cosi extraction downstream); it - # is additionally the shipped boot artifact for mips*/powerpc*. - cp build/vmlinux $out/vmlinux.${target} + # The unstripped vmlinux always goes to its own output -- osi/cosi need the + # debug info, and nothing downstream can un-strip it later. + mkdir -p $vmlinux + cp build/vmlinux $vmlinux/vmlinux.${target} + + # $out gets a vmlinux ONLY where it is the deliverable boot artifact, which + # is what build.sh does; every other target ships just its boot image. ${lib.optionalString (deliversVmlinux target) '' + cp build/vmlinux $out/vmlinux.${target} ${crossPrefix}strip $out/vmlinux.${target} || true ''} ${lib.optionalString (boot != null) '' diff --git a/nix/release.nix b/nix/release.nix new file mode 100644 index 0000000..f85ba4a --- /dev/null +++ b/nix/release.nix @@ -0,0 +1,89 @@ +# The release seam: reassemble the two tarballs penguin already consumes, so a +# nix-built linux_builder is a drop-in for the Docker one. +# +# kernels-latest.tar.gz entries under `kernels//` +# (penguin untars it into /igloo_static/, and +# src/penguin/utils.py globs /igloo_static/kernels/*/) +# kernel-devel-all.tar.gz entries under `././` +# +# Tarballs are built reproducibly (sorted, epoch mtimes, numeric root owner, +# gzip -n). The Docker build stamps `Built by linux_builder on $(date)` into +# README.txt, which alone would make every archive byte-different; the date is +# dropped rather than faked, and the provenance that matters -- the store path +# each artifact came from -- is recorded instead. +# +# KNOWN CONTRACT GAP: perf.. build.sh cross-builds a static perf per +# cell, but its failure is swallowed (`|| echo "Warning: Failed to build perf"`, +# then a `[ -f ]` guard), so the shipped tarball already contains whatever +# happened to compile that day -- perf coverage is unstated and unenforced. No +# consumer of perf.* was found in penguin. It is omitted here rather than +# reproduced half-working; if it turns out to matter, it needs a target libc, +# which loongarch64's kernel-only toolchain does not have (see kernelsmith's +# matrix.k6LoongarchKernel), so that cell could never ship one anyway. +{ pkgs }: + +let + inherit (pkgs) lib; + + # tar flags that make an archive a function of its contents only. + reproTar = "--sort=name --mtime=@0 --owner=0 --group=0 --numeric-owner"; + +in +rec { + # One version's worth of /kernels/: boot artifacts + analysis output. + kernelsDir = { version, cells }: + pkgs.runCommand "igloo-kernels-dir-${version}" { } '' + mkdir -p $out + ${lib.concatMapStringsSep "\n" + (c: '' + # Boot artifacts (zImage./bzImage./Image./vmlinuz.efi./vmlinux.). + # Module.symvers is a build input, not a shipped artifact -- skip it. + for f in ${c.kernel}/*; do + b=$(basename "$f") + [ "$b" = "Module.symvers" ] && continue + cp -a "$f" $out/"$b" + done + cp ${c.osi} $out/osi.${c.target}.config + cp ${c.cosi} $out/cosi.${c.target}.json.xz + '') + cells} + + # Aggregate profile, concatenated in a STABLE order. The shell relies on + # glob order, which is locale-dependent; sort explicitly. + for f in $(ls $out/osi.*.config | sort); do cat "$f" >> $out/osi.config; done + ''; + + kernelsTarball = { versions }: + pkgs.runCommand "kernels-latest.tar.gz" { nativeBuildInputs = [ pkgs.gzip ]; } '' + mkdir -p stage/kernels + ${lib.concatMapStringsSep "\n" + (v: ''cp -a ${v.dir} stage/kernels/${v.version}'') + versions} + chmod -R u+w stage + + # Deliberately not the Docker build's `Built by linux_builder on $(date)`: + # a timestamp would make the archive non-reproducible for no benefit. + # Written with printf rather than a heredoc so the Nix indentation of this + # file does not end up inside the shipped file. + printf '%s\n' \ + 'Built by linux_builder (nix + patch series).' \ + "" \ + 'Provenance is the store path of each input, not a build date -- these' \ + 'artifacts are a pure function of the pinned kernel tarball, the patch' \ + 'series in patches/, the config in configs/, and the kernelsmith toolchain.' \ + > stage/kernels/README.txt + + tar ${reproTar} -cf - -C stage kernels | gzip -9n > $out + ''; + + develTarball = { cells }: + pkgs.runCommand "kernel-devel-all.tar.gz" { nativeBuildInputs = [ pkgs.gzip ]; } '' + mkdir -p stage + ${lib.concatMapStringsSep "\n" + # The Docker layout is ., not /. + (c: ''cp -a ${c.kernel.dev} stage/${c.target}.${c.version}'') + cells} + chmod -R u+w stage + tar ${reproTar} -cf - -C stage . | gzip -9n > $out + ''; +} From 1d4f64a87e2cec54b7f9b5eb30ab9b08cb55362a Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Wed, 12 Aug 2026 20:19:59 -0400 Subject: [PATCH 06/28] kernel.nix: build the whole powerpc family with one biarch powerpc64 toolchain 6.13/powerpc64le did not build: CONFIG_COMPAT (a defconfig default we never chose -- configs/6.13/powerpc64le sets only CONFIG_CPU_LITTLE_ENDIAN) makes kbuild compile a 32-bit vDSO, and the build died with cc1: error: '-m32' not supported in this configuration The cause is structural. get_cc compiles EVERY powerpc* target with a single powerpc64 big-endian toolchain -- bitness and endianness come from the kernel's own arch Makefile via Kconfig, not from the triple. kernelsmith models the four variants as four independent arches, and the per-variant Bootlin toolchains are not equivalent: powerpc64 (BE, power8): -m32 OK -m64 OK -mlittle/-mbig OK powerpc64le (LE, power8): -m32 FAIL Production confirms the arrangement: the shipped ppc64le kernel in rehosting/penguin:latest reports 'powerpc64-linux-musl-gcc (GCC) 11.2.1' -- a big-endian-triple compiler built the little-endian kernel. So this is a fidelity fix, not a workaround. Verified the obvious hazard -- a BE-default compiler emitting a big-endian vDSO into an LE kernel -- does NOT occur: -mlittle-endian comes from KBUILD_CPPFLAGS/cflags for CONFIG_CPU_LITTLE_ENDIAN and vdso32's CC32FLAGSREMOVE strips only -mcmodel=/-mabi=/-mcall-aixdesc, so -m32 lands on top of it. The built artifacts are ELF32 little endian: sigtramp32-32.o Class: ELF32 Data: little endian vdso32.so.dbg Class: ELF32 Data: little endian All four powerpc cells now build. Bonus: powerpcle no longer needs a from-source musl-cross-make toolchain (Bootlin ships no powerpcle at all), so the matrix got cheaper. TODO(kernelsmith): upstream this as a kernel-specific resolver (kernelToolchainFor), NOT as a change to toolchainFor -- userland musl for powerpc64le should still use the powerpc64le triple. --- nix/kernel.nix | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/nix/kernel.nix b/nix/kernel.nix index 1051387..665fd6d 100644 --- a/nix/kernel.nix +++ b/nix/kernel.nix @@ -68,13 +68,42 @@ let # vmlinux is the deliverable boot artifact for these families. deliversVmlinux = target: lib.hasPrefix "mips" target || lib.hasPrefix "powerpc" target; + # Which arch's TOOLCHAIN a target builds with, where that differs from the + # target itself. + # + # The whole powerpc family builds with ONE biarch powerpc64 big-endian + # compiler, exactly as _in_container_build.sh's get_cc does (every powerpc* + # target there resolves to powerpc64-linux-musl-, or powerpc64-linux-gnu- on + # 4.10). Bitness and endianness come from the kernel's own arch Makefile + # driven by Kconfig -- NOT from the triple. + # + # This is not cosmetic. kernelsmith models the four powerpc variants as four + # independent arches with four separate toolchains, and the per-variant + # powerpc64LE toolchain is 64-bit only: + # + # powerpc64 (BE, Bootlin power8): -m32 OK -m64 OK -mlittle/-mbig OK + # powerpc64le (LE, Bootlin power8): -m32 FAIL + # + # 6.13/powerpc64le sets CONFIG_COMPAT, so kbuild builds a 32-bit vDSO + # (VDSO32A ... sigtramp32-32.o) and the LE-only compiler dies with + # "cc1: error: '-m32' not supported in this configuration". Aligning the + # family to powerpc64 fixes that and drops a from-source musl-cross-make + # build for powerpcle, which Bootlin has no toolchain for at all. + # + # TODO(kernelsmith): this belongs upstream as a kernel-specific resolver + # (`kernelToolchainFor`), NOT as a change to `toolchainFor` -- userland musl + # for powerpc64le should still be the powerpc64le triple. Kept local until + # that API exists. + toolchainArch = target: + if lib.hasPrefix "powerpc" target then "powerpc64" else target; + in { version, target, src, config }: let arch = shortArch.${target} or (throw "kernel.nix: no ARCH mapping for target ${target}"); boot = bootArtifact.${target} or null; - toolchain = kernelsmith.toolchainFor version target; + toolchain = kernelsmith.toolchainFor version (toolchainArch target); crossPrefix = "${toolchain.target}-"; # Trailing -Wno-error beats any -Werror the tree injects, at any depth. From 76b1942e43e97ccd746e3b861a185234b3c7128e Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 00:46:56 -0400 Subject: [PATCH 07/28] flake.lock: pin kernelsmith to main with riscv64 + loongarch64 rehosting/kernelsmith#2 is merged, so the branch no longer needs --override-input to resolve a toolchain for those two arches. All 20 cells evaluate from the pinned input alone. --- flake.lock | 6 +-- flake.nix | 6 +++ nix/perf.nix | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ nix/release.nix | 13 +++--- 4 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 nix/perf.nix diff --git a/flake.lock b/flake.lock index 2396fee..803c4ec 100644 --- a/flake.lock +++ b/flake.lock @@ -6,11 +6,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1783346134, - "narHash": "sha256-1izwxPuWd5+fSDbjbNjXLOGG1sGKq3UsQFbeDQYNP3Q=", + "lastModified": 1786596203, + "narHash": "sha256-ukayW5lL9ZPG6A9HHML2jVXya34k7eZpmbS1pG4zJh0=", "owner": "rehosting", "repo": "kernelsmith", - "rev": "7c5bb897c635f81b5077d32f2fb8a8ad4eb9ad6a", + "rev": "c00a01b79812dd90b5de5ebeb115871f0471313c", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 6557d4f..8b5ee28 100644 --- a/flake.nix +++ b/flake.nix @@ -87,6 +87,7 @@ # penguin to a flake input is a separate, later change. analysisLib = import ./nix/analysis.nix { inherit pkgs; }; releaseLib = import ./nix/release.nix { inherit pkgs; }; + mkPerf = import ./nix/perf.nix { inherit pkgs kernelsmith; }; # Per-cell record carrying everything the assembly needs. cellRecords = version: map @@ -95,6 +96,11 @@ inherit version target kernel; osi = analysisLib.osiConfig { inherit kernel version target; }; cosi = analysisLib.cosiJson { inherit kernel version target; }; + perf = mkPerf { + inherit version target; + src = sources.${version}; + inherit (kernel) arch; + }; }) (buildable version); diff --git a/nix/perf.nix b/nix/perf.nix new file mode 100644 index 0000000..503c2b1 --- /dev/null +++ b/nix/perf.nix @@ -0,0 +1,113 @@ +# perf. -- the statically-linked guest perf binary shipped in +# kernels-latest.tar.gz. +# +# A faithful port of _in_container_build.sh's perf step, with ONE deliberate +# behavioural change: this fails loudly. +# +# The shell runs the build with `|| echo "Warning: Failed to build perf ..."` +# and then guards the copy with `[ -f "$PERF_SRC" ]`, so an arch whose perf does +# not compile silently ships without one. The result is that +# rehosting/penguin:latest carries perf for exactly 3 of 13 targets (armel, +# loongarch64, mips64el) and nobody had to notice. Here a broken arch breaks the +# build, so "this arch has no perf" has to be a decision someone writes down +# rather than a build-day accident. +# +# perf links -static against a TARGET LIBC, which is why loongarch64 cannot use +# the kernel-only gcc that builds its kernel (see kernelsmith's +# matrix.k6LoongarchKernel -- kernel-only means no libc at all). It uses the +# nixpkgs glibc cross instead, whose triple +# (loongarch64-unknown-linux-gnu-) is byte-identical to the hand-installed +# /opt/cross toolchain the Docker image reaches for. So loongarch64 is the one +# arch where the kernel and its perf are built by different compilers -- exactly +# as in production, just written down. +{ pkgs, kernelsmith }: + +let + inherit (pkgs) lib; + + # Same family collapsing as kernel.nix: one biarch powerpc64 toolchain builds + # every powerpc variant, matching get_cc. + toolchainArch = target: + if lib.hasPrefix "powerpc" target then "powerpc64" else target; + + # mips64 needs an explicit output-format flag or ld picks the wrong ABI. + extraLdFlags = { + mips64el = " -m elf64ltsmip"; + mips64eb = " -m elf64btsmip"; + }; + + # The NO_* soup, verbatim from the shell. perf pulls in a large optional + # dependency surface; every one of these is off in the shipped build, so a + # difference here would be a silently different binary. + noFlags = [ + "NO_LIBELF" "NO_LIBUNWIND" "NO_LIBNUMA" "NO_LIBAUDIT" + "NO_LIBBIONIC" "NO_LIBPYTHON" "NO_LIBPERL" "NO_SLANG" "NO_LZMA" + "NO_ZLIB" "NO_LIBBPF" "NO_JVMTI" "NO_LIBCRYPTO" "NO_LIBZSTD" + "NO_LIBTRACEEVENT" "NO_AUXTRACE" "NO_CORESIGHT" + ]; + + extraCFlags = lib.concatStringsSep " " [ + "-Wno-error" "-fcommon" "-D__always_inline=inline" + "-Wno-redundant-decls" "-Wno-format-truncation" + "-Wno-format-overflow" "-Wno-array-bounds" + ]; + +in +{ version, target, src, arch }: + +let + isLoong = target == "loongarch64"; + + # loongarch64: nixpkgs glibc cross (has a libc). Everything else: the same + # kernelsmith toolchain that built the kernel. + loongCross = pkgs.pkgsCross.loongarch64-linux; + toolchain = if isLoong then loongCross.buildPackages.gcc else kernelsmith.toolchainFor version (toolchainArch target); + binutils = lib.optional isLoong loongCross.buildPackages.binutils; + crossPrefix = + if isLoong then loongCross.stdenv.cc.targetPrefix + else "${toolchain.target}-"; + + ldFlag = extraLdFlags.${target} or ""; + +in +pkgs.stdenv.mkDerivation { + name = "igloo-perf-${version}-${target}"; + dontUnpack = true; + enableParallelBuilding = true; + + nativeBuildInputs = [ toolchain ] ++ binutils ++ (with pkgs; [ + gnumake bison flex perl python3 pkg-config which + ]); + + buildPhase = '' + runHook preBuild + cp -r ${src} linux && chmod -R u+w linux + patchShebangs linux/scripts linux/tools 2>/dev/null || true + mkdir -p out + + make -C linux/tools/perf \ + ARCH=${arch} \ + CROSS_COMPILE=${crossPrefix} \ + CC="${crossPrefix}gcc" \ + LD="${crossPrefix}ld${ldFlag}" \ + OUTPUT=$PWD/out/ \ + LDFLAGS="-static" \ + WERROR=0 \ + EXTRA_CFLAGS="${extraCFlags}" \ + HOSTCFLAGS="-Wno-error" \ + ${lib.concatMapStringsSep " " (f: "${f}=1") noFlags} \ + -j$NIX_BUILD_CORES + + # Deliberately NOT the shell's silent `[ -f ]` guard -- see header. + test -f out/perf || { echo "FAIL: perf did not build for ${target}"; exit 1; } + runHook postBuild + ''; + + installPhase = '' + mkdir -p $out + cp out/perf $out/perf.${target} + ${crossPrefix}strip $out/perf.${target} || true + ''; + + meta.description = "static guest perf for ${version}/${target}"; +} diff --git a/nix/release.nix b/nix/release.nix index f85ba4a..6a820c1 100644 --- a/nix/release.nix +++ b/nix/release.nix @@ -12,14 +12,10 @@ # dropped rather than faked, and the provenance that matters -- the store path # each artifact came from -- is recorded instead. # -# KNOWN CONTRACT GAP: perf.. build.sh cross-builds a static perf per -# cell, but its failure is swallowed (`|| echo "Warning: Failed to build perf"`, -# then a `[ -f ]` guard), so the shipped tarball already contains whatever -# happened to compile that day -- perf coverage is unstated and unenforced. No -# consumer of perf.* was found in penguin. It is omitted here rather than -# reproduced half-working; if it turns out to matter, it needs a target libc, -# which loongarch64's kernel-only toolchain does not have (see kernelsmith's -# matrix.k6LoongarchKernel), so that cell could never ship one anyway. +# perf. is built for EVERY cell -- see nix/perf.nix. build.sh swallows +# perf build failures, so rehosting/penguin:latest ships perf for only 3 of 13 +# targets (armel, loongarch64, mips64el) without that ever being a decision. +# Here a failing arch fails the build instead. { pkgs }: let @@ -45,6 +41,7 @@ rec { done cp ${c.osi} $out/osi.${c.target}.config cp ${c.cosi} $out/cosi.${c.target}.json.xz + cp ${c.perf}/perf.${c.target} $out/perf.${c.target} '') cells} From 2566116afb5a6387010970e08f9676525f8d3cf6 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 01:27:05 -0400 Subject: [PATCH 08/28] perf: fix the four failing cells, and stop shipping one binary as four The shell build ran perf with `|| echo Warning` and copied it behind a `[ -f ]` guard, so an arch whose perf did not compile shipped without one -- rehosting/penguin:latest carries perf for 3 of 13 targets as a result. perf.nix already fails loudly instead; these are the cells that were failing, plus one that was silently wrong. 4.10/x86_64 perf resolves its tools headers with -I tools/arch/$(ARCH)/include/uapi, using ARCH verbatim rather than the SRCARCH kbuild derives from it, and tools/arch/x86_64/ does not exist. Reported as a missing uapi/asm/mman.h, which names the wrong file entirely. 4.10/mips64{eb,el} the musl ld defaults to the n32 emulation while the objects are n64. LD= on the make command line does not fix it: tools/perf/Makefile does `unexport MAKEFLAGS`, so command-line variables never reach the nested tools/lib/* builds -- which is exactly where the link fails. A PATH shim survives that. Not LDEMULATION, which the HOST ld building fixdep would also pick up. 6.13/loongarch64 the only glibc target. perf's cross-compile feature detection fails, so it defines its own gettid and pthread_attr_setaffinity_np, colliding with glibc's real ones. Also needs the WRAPPED cross cc, for the sysroot, and glibc's separate static output. Its dlfilters cannot link at all -- binutils 2.41 segfaults on a .so against a static-only glibc -- so drop dlfilters everywhere: they are dlopen plugins, dead weight in a -static perf, and never shipped. The silently-wrong one: perf.nix had inherited kernel.nix's powerpc family collapse, which routes all four variants through a single biarch powerpc64 BE toolchain. Correct for a kernel -- freestanding, and arch/powerpc/Makefile takes bitness and endianness from Kconfig -- and wrong for perf, which has no Kconfig and links -static against a target libc. It produced four byte-identical big-endian 64-bit binaries, three of which cannot run on their guest. Every cell built, so nothing complained. 20/20 cells now build, and the powerpc four are 32-bit BE, 32-bit LE, 64-bit BE and 64-bit LE respectively. --- nix/perf.nix | 120 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 110 insertions(+), 10 deletions(-) diff --git a/nix/perf.nix b/nix/perf.nix index 503c2b1..d00c2f1 100644 --- a/nix/perf.nix +++ b/nix/perf.nix @@ -25,10 +25,32 @@ let inherit (pkgs) lib; - # Same family collapsing as kernel.nix: one biarch powerpc64 toolchain builds - # every powerpc variant, matching get_cc. - toolchainArch = target: - if lib.hasPrefix "powerpc" target then "powerpc64" else target; + # NB: deliberately NO powerpc family collapsing here, unlike kernel.nix. + # + # kernel.nix routes all four powerpc variants through one biarch powerpc64 BE + # toolchain, which is correct for a kernel: it is built -nostdinc + # -ffreestanding, and arch/powerpc/Makefile derives -m32/-m64 and the + # endianness from Kconfig, so one compiler yields four different kernels. + # + # perf has no Kconfig and links -static against a TARGET LIBC, so neither of + # those holds. Collapsing the family here produced four BYTE-IDENTICAL + # big-endian 64-bit binaries for powerpc, powerpcle, powerpc64 and + # powerpc64le -- three of which cannot run on their guest at all. It fails + # silently: every cell builds, `perf` exists, and only the ELF header shows + # the damage. + # + # Using each variant's own toolchain also gets the matching 32-bit/LE musl, + # which a 64-bit BE sysroot simply does not contain. + toolchainArch = target: target; + + # perf resolves its tools headers with -I$(srctree)/tools/arch/$(ARCH)/include/uapi, + # using ARCH verbatim rather than the SRCARCH that kbuild derives from it. The + # kernel build takes ARCH=x86_64 and normalises it to x86 internally; perf does + # not, and tools/arch/x86_64/ does not exist, so 4.10 fails with + # tools/include/uapi/linux/mman.h:4: fatal error: uapi/asm/mman.h: No such file + # which names the generic header rather than the missing arch directory. + # tools/arch/x86/ is correct for every kernel version, so map it here. + perfArch = a: if a == "x86_64" then "x86" else a; # mips64 needs an explicit output-format flag or ld picks the wrong ABI. extraLdFlags = { @@ -52,6 +74,24 @@ let "-Wno-format-overflow" "-Wno-array-bounds" ]; + # perf probes for optional libc features by compiling test programs under + # tools/build/feature. Cross-compiling makes several of those tests fail for + # reasons that have nothing to do with whether the feature exists, and perf + # responds by defining its own fallback -- which then collides with the real + # declaration the target libc does provide: + # + # bench/bench.h:66 conflicting types for 'pthread_attr_setaffinity_np' + # builtin-record.c:207 static declaration of 'gettid' follows non-static + # + # Both symbols are present in glibc, so the honest fix is to tell perf the + # truth rather than silence the warning. Only the glibc target needs this; + # the musl/kernel-only toolchains really do lack them, and there perf's + # fallback is correct. + glibcFeatureFlags = lib.concatStringsSep " " [ + "-DHAVE_PTHREAD_ATTR_SETAFFINITY_NP" + "-DHAVE_GETTID" + ]; + in { version, target, src, arch }: @@ -61,8 +101,22 @@ let # loongarch64: nixpkgs glibc cross (has a libc). Everything else: the same # kernelsmith toolchain that built the kernel. loongCross = pkgs.pkgsCross.loongarch64-linux; - toolchain = if isLoong then loongCross.buildPackages.gcc else kernelsmith.toolchainFor version (toolchainArch target); - binutils = lib.optional isLoong loongCross.buildPackages.binutils; + + # Use the WRAPPED cross cc, not the bare gcc: the wrapper is what puts the + # target glibc on the include and library search paths. With the bare gcc the + # compile succeeds and the link fails on -lpthread/-lrt/-lm/-ldl, which reads + # like a missing dependency but is really a missing sysroot. + toolchain = + if isLoong then loongCross.stdenv.cc + else kernelsmith.toolchainFor version (toolchainArch target); + + # -static needs the archive halves of glibc, which nixpkgs splits into a + # separate `static` output. + loongLibs = lib.optionals isLoong [ + loongCross.buildPackages.binutils + loongCross.stdenv.cc.libc.static + ]; + crossPrefix = if isLoong then loongCross.stdenv.cc.targetPrefix else "${toolchain.target}-"; @@ -75,7 +129,7 @@ pkgs.stdenv.mkDerivation { dontUnpack = true; enableParallelBuilding = true; - nativeBuildInputs = [ toolchain ] ++ binutils ++ (with pkgs; [ + nativeBuildInputs = [ toolchain ] ++ loongLibs ++ (with pkgs; [ gnumake bison flex perl python3 pkg-config which ]); @@ -83,17 +137,63 @@ pkgs.stdenv.mkDerivation { runHook preBuild cp -r ${src} linux && chmod -R u+w linux patchShebangs linux/scripts linux/tools 2>/dev/null || true + + # Same sandbox breakage kernel.nix hits, in a different file: 4.10-era + # tools/scripts/Makefile.include validates OUTPUT with `cd $dir && /bin/pwd`, + # and there is no /bin/pwd here. It reports it as + # *** output directory "/build/out/" does not exist. Stop. + # which points at the wrong thing entirely -- the directory is right there. + # Not an IGLOO change, so it is fixed in the builder, not the patch series. + find linux/tools linux/Makefile -name 'Makefile*' -o -name '*.mk' 2>/dev/null \ + | xargs -r sed -i 's|/bin/pwd|pwd|g' + sed -i 's|/bin/pwd|pwd|g' linux/Makefile + mkdir -p out +${lib.optionalString (ldFlag != "") '' + # mips64: the musl toolchain's ld defaults to the n32 emulation + # (elf32-ntradlittlemips) while the objects are n64, so relocatable links + # inside libapi fail with "ABI is incompatible with that of the selected + # emulation". + # + # Passing LD="ld -m elf64ltsmip" on the make command line is not enough: + # tools/perf/Makefile does `unexport MAKEFLAGS`, so command-line variables + # do NOT reach the nested tools/lib/* builds, and those are exactly where + # the failure is. A PATH shim survives that, because every one of those + # builds resolves $(CROSS_COMPILE)ld through PATH. + # + # A shim rather than LDEMULATION= because the environment variable would + # also be picked up by the HOST ld that builds fixdep. + mkdir -p ldshim + cat > ldshim/${crossPrefix}ld < Date: Thu, 13 Aug 2026 01:27:45 -0400 Subject: [PATCH 09/28] nix: build igloo.ko per cell via kernelsmith buildModule; expose per-cell outputs Slice 3. Two things: 1. Per-cell perf/osi/cosi/driver outputs. Without them a broken perf could only be reached through the whole release tarball, which rebuilds every cell to show you one compiler error. 2. nix/driver.nix builds igloo.ko for each cell from THIS FLAKE's kernel derivation, through kernelsmith's new buildModule, with no tarball round trip. That is the acceptance test for the kernel `dev` output: a build tree that cannot build the one module we care about is broken, and this repo is where that should be caught. The CRC property is the point. _in_container_build.sh extracts kernel-devel-all.tar.gz to a scratch directory and builds against whatever is there, so nothing structurally prevents pairing a module with a different kernel than the one it is inserted into. Here the kernel derivation is an input, so a mismatched pair is not representable. igloo_driver is added as a source-only input for this. That is not a claim about which repo should own the driver build long-term -- under the provider/consumer split both linux_builder and igloo_driver are consumers of kernelsmith, and igloo_driver owning its own build is the better end state. --- flake.lock | 17 +++++++++++++++++ flake.nix | 31 +++++++++++++++++++++++++++++-- nix/driver.nix | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 nix/driver.nix diff --git a/flake.lock b/flake.lock index 803c4ec..9b80047 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "igloo_driver": { + "flake": false, + "locked": { + "lastModified": 1786551192, + "narHash": "sha256-zeOP0nQEb/uns46MizbcX3DpS4or4EM8XuOmRRIPbo4=", + "owner": "rehosting", + "repo": "igloo_driver", + "rev": "243c889e2b3360b16e5b12d6a20b0c5c0766dd07", + "type": "github" + }, + "original": { + "owner": "rehosting", + "repo": "igloo_driver", + "type": "github" + } + }, "kernelsmith": { "inputs": { "musl-cross-make": "musl-cross-make", @@ -53,6 +69,7 @@ }, "root": { "inputs": { + "igloo_driver": "igloo_driver", "kernelsmith": "kernelsmith", "nixpkgs": [ "kernelsmith", diff --git a/flake.nix b/flake.nix index 8b5ee28..63aa3af 100644 --- a/flake.nix +++ b/flake.nix @@ -15,10 +15,20 @@ # kernels have no recorded compiler identity. kernelsmith.url = "github:rehosting/kernelsmith"; nixpkgs.follows = "kernelsmith/nixpkgs"; + + # Source only -- igloo_driver has no flake of its own yet. This is here to + # ACCEPTANCE-TEST the kernel `dev` output (see nix/driver.nix): a build tree + # that cannot build the one module we care about is broken, and this repo is + # where that should be caught. It is not a claim about which repo should own + # the driver build long-term. + igloo_driver = { + url = "github:rehosting/igloo_driver"; + flake = false; + }; }; outputs = - { self, nixpkgs, kernelsmith }: + { self, nixpkgs, kernelsmith, igloo_driver }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; @@ -88,6 +98,7 @@ analysisLib = import ./nix/analysis.nix { inherit pkgs; }; releaseLib = import ./nix/release.nix { inherit pkgs; }; mkPerf = import ./nix/perf.nix { inherit pkgs kernelsmith; }; + mkDriver = import ./nix/driver.nix { inherit pkgs kernelsmith; }; # Per-cell record carrying everything the assembly needs. cellRecords = version: map @@ -101,14 +112,30 @@ src = sources.${version}; inherit (kernel) arch; }; + driver = mkDriver { + inherit kernel version target; + src = igloo_driver; + }; }) (buildable version); allRecords = lib.concatMap cellRecords (builtins.attrNames matrix); + # Per-cell analysis/perf outputs, individually addressable. Without these + # a broken perf can only be reached through the whole release tarball, + # which rebuilds everything to show you one compiler error. + perCellOutputs = lib.listToAttrs (lib.concatMap + (r: [ + (lib.nameValuePair "perf-${r.version}-${r.target}" r.perf) + (lib.nameValuePair "driver-${r.version}-${r.target}" r.driver) + (lib.nameValuePair "osi-${r.version}-${r.target}" r.osi) + (lib.nameValuePair "cosi-${r.version}-${r.target}" r.cosi) + ]) + allRecords); + in { - packages.${system} = cells // { + packages.${system} = cells // perCellOutputs // { default = cells."kernel-6.13-armel"; # Everything buildable today, in one derivation, for CI. diff --git a/nix/driver.nix b/nix/driver.nix new file mode 100644 index 0000000..7ebb961 --- /dev/null +++ b/nix/driver.nix @@ -0,0 +1,43 @@ +# igloo.ko per cell, built against this flake's kernel derivation. +# +# This exists here rather than in igloo_driver's own repo for one reason: it is +# the acceptance test for kernelsmith's `buildModule` and for the `dev` (build +# tree) output. If a module cannot be built from a linux_builder cell without +# unpacking a tarball, the devel output is wrong, and it is better to find that +# out in this repo's CI than in igloo_driver's. +# +# The CRC property is the point. `_in_container_build.sh` extracts +# kernel-devel-all.tar.gz to a scratch directory and builds against whatever is +# there, so nothing structurally prevents building a module against a different +# kernel than the one it will be inserted into -- the failure mode is a module +# that loads and then misbehaves, or refuses to load with a version magic +# mismatch, depending on how far the drift went. Here the kernel derivation is +# an input, so a mismatched pair is not representable. +{ pkgs, kernelsmith }: + +{ kernel, src, version, target }: + +kernelsmith.buildModule { + name = "igloo-${version}-${target}"; + inherit version src kernel; + + # igloo_driver's Makefile is not a bare `obj-m :=` file. Its default target + # generates two headers (portal_tramp_gen.h, ffi_stubs_generated.h) with + # python3 and only then re-enters kbuild. Driving kbuild directly would skip + # the codegen and fail on the missing headers. + entry = "wrapper"; + + nativeBuildInputs = [ pkgs.python3 ]; + + # The upstream Makefile lives in src/; everything it references is relative to + # it ($(src)/portal, $(src)/../scripts). + preBuild = "cd src"; + + # powerpc modules reference the out-of-line register save/restore helpers + # (_savegpr*/_restgpr*), which live in the kernel's own + # arch/powerpc/lib/crtsavres.o rather than in libgcc. Without the search path + # the module link fails on undefined _restgpr_31_x. + makeVars = pkgs.lib.optionalAttrs (pkgs.lib.hasPrefix "powerpc" target) { + EXTRA_LDFLAGS = "-L${kernel.dev}/arch/powerpc/lib"; + }; +} From adea06d5a00ac773a9b1e0dea512563b49c2e3d8 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 01:38:39 -0400 Subject: [PATCH 10/28] perf: powerpcle must follow its kernel, which is big-endian Fixing the powerpc family collapse exposed a target that is not real. arch/powerpc/platforms/Kconfig.cputype: config CPU_LITTLE_ENDIAN depends on PPC_BOOK3S_64 A 32-bit little-endian powerpc kernel cannot be expressed in mainline Linux. configs/6.13/powerpcle sets CONFIG_CPU_LITTLE_ENDIAN=y, olddefconfig silently drops it, and the built vmlinux is byte-identical to powerpc's (verified by sha256 -- same hash, both 32-bit MSB). configs/4.10/powerpcle is already retired as .unused. So powerpcle's kernel is big-endian, and building perf 'as the target name implies' would ship a little-endian userspace binary that cannot run on it. Point perf at the powerpc toolchain instead, so the pair is at least self-consistent. The larger question -- whether this cell should exist at all, given it costs a kernel, a perf, an osi/cosi extraction and a driver build per release to duplicate 'powerpc' under a name that claims otherwise -- is for draft 34, not for this commit. --- nix/driver.nix | 12 +++++------- nix/perf.nix | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/nix/driver.nix b/nix/driver.nix index 7ebb961..0afa559 100644 --- a/nix/driver.nix +++ b/nix/driver.nix @@ -33,11 +33,9 @@ kernelsmith.buildModule { # it ($(src)/portal, $(src)/../scripts). preBuild = "cd src"; - # powerpc modules reference the out-of-line register save/restore helpers - # (_savegpr*/_restgpr*), which live in the kernel's own - # arch/powerpc/lib/crtsavres.o rather than in libgcc. Without the search path - # the module link fails on undefined _restgpr_31_x. - makeVars = pkgs.lib.optionalAttrs (pkgs.lib.hasPrefix "powerpc" target) { - EXTRA_LDFLAGS = "-L${kernel.dev}/arch/powerpc/lib"; - }; + # NB: 32-bit powerpc needs arch/powerpc/lib/crtsavres.o staged into the module + # build directory. That is handled generically in kernelsmith's buildModule -- + # it is a property of ppc32 kbuild, not of this module. _in_container_build.sh + # carries the same workaround, plus an EXTRA_LDFLAGS="-L…" that does nothing: + # KBUILD_LDFLAGS_MODULE names the object positionally, and -L only affects -l. } diff --git a/nix/perf.nix b/nix/perf.nix index d00c2f1..5031726 100644 --- a/nix/perf.nix +++ b/nix/perf.nix @@ -41,7 +41,24 @@ let # # Using each variant's own toolchain also gets the matching 32-bit/LE musl, # which a 64-bit BE sysroot simply does not contain. - toolchainArch = target: target; + # + # The one exception is `powerpcle`, and it is not a toolchain problem -- it is + # that the target does not exist. arch/powerpc/platforms/Kconfig.cputype has + # + # config CPU_LITTLE_ENDIAN + # depends on PPC_BOOK3S_64 + # + # so a 32-bit little-endian powerpc kernel cannot be expressed in mainline + # Linux at all. configs/6.13/powerpcle sets CONFIG_CPU_LITTLE_ENDIAN=y, + # olddefconfig silently drops it, and the resulting vmlinux is byte-identical + # to `powerpc` (verified by sha256). configs/4.10/powerpcle is already + # retired as `.unused`. + # + # So the KERNEL for this cell is big-endian, and perf must match it or we ship + # a userspace binary that cannot run on its own kernel. Building perf "as the + # target name implies" would be the more wrong answer here. + # See draft 34 for the open question of whether this cell should exist. + toolchainArch = target: if target == "powerpcle" then "powerpc" else target; # perf resolves its tools headers with -I$(srctree)/tools/arch/$(ARCH)/include/uapi, # using ARCH verbatim rather than the SRCARCH that kbuild derives from it. The From e2670aebb7bddebb296f5f8273c3890a72346742 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 01:54:14 -0400 Subject: [PATCH 11/28] ci: make the Cachix push reachable, and cover perf + module in the gate The push step was guarded by `if: env.CACHIX_AUTH_TOKEN != ''` while the token was set in that same step's `env:` block. A step's own env is not in scope for its own `if:`, so the condition was always false and the cache was never populated -- the exact failure the workflow was written to prevent. Hoisted to job level, where the `if:` can see it. Also: - The gate now builds kernel + perf + module for its two cells, not just the kernel. perf and the module fail independently of the kernel, and both have done so recently. - A dispatch-only full-matrix job (20 cells + both release tarballs), with per-cell OK/FAIL lines so a single failure is attributable rather than buried. - Fixed the base.json path, which went through a pointless patches//../ indirection. Still unexercised on the self-hosted runners; the note at the top stands until a real run. --- .github/workflows/nix.yml | 85 ++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 2ceb81e..edd6568 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -14,11 +14,24 @@ on: push: branches: [main, nix-patchset] workflow_dispatch: + inputs: + full_matrix: + description: "Build every cell (kernel + perf + driver), not just the gate" + type: boolean + default: false concurrency: group: nix-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} +# Job-level so that step-level `if:` can actually see it. A step's own `env:` +# block is NOT in scope for that step's `if:`, so the previous +# `if: env.CACHIX_AUTH_TOKEN != ''` next to a step-level `env:` was always +# false and the cache was never pushed -- the exact failure this workflow was +# written to prevent. +env: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + jobs: series: name: series applies (${{ matrix.version }}) @@ -37,7 +50,7 @@ jobs: id: tarball run: | set -euo pipefail - TAG=$(python3 -c "import json;print(json.load(open('patches/${{ matrix.version }}/../base.json'))['${{ matrix.version }}']['tag'])") + TAG=$(python3 -c "import json;print(json.load(open('patches/base.json'))['${{ matrix.version }}']['tag'])") MAJOR="${TAG%%.*}" URL="https://cdn.kernel.org/pub/linux/kernel/v${MAJOR}.x/linux-${TAG}.tar.xz" echo "path=$(nix-prefetch-url --print-path "$URL" | tail -1)" >> "$GITHUB_OUTPUT" @@ -45,6 +58,10 @@ jobs: - name: Series applies cleanly to pristine upstream run: ./scripts/verify-series.sh "${{ matrix.version }}" "${{ steps.tarball.outputs.path }}" + # The fast gate: one cell per version, and for each of them the three + # artifacts that have historically failed independently of the kernel -- + # perf (silently skipped for 10 of 13 targets in the shell build), and the + # module (which is what proves the `dev` build tree is actually usable). build: name: build ${{ matrix.cell }} runs-on: rehosting-arc @@ -52,24 +69,72 @@ jobs: strategy: fail-fast: false matrix: - # One cell per version keeps the gate fast; `nix build .#all` covers the - # full 18-cell matrix on dispatch/release. - cell: ["kernel-4.10-armel", "kernel-6.13-armel"] + cell: ["4.10-armel", "6.13-armel"] steps: - uses: actions/checkout@v4 - uses: rehosting/nix-setup@v1 - - name: Build - run: nix build --print-out-paths ".#packages.x86_64-linux.\"${{ matrix.cell }}\"" + - name: Build kernel, perf and module + run: | + set -euo pipefail + for out in kernel perf driver; do + nix build --print-out-paths \ + ".#packages.x86_64-linux.\"$out-${{ matrix.cell }}\"" + done # Populate the cache from PRs too. Pushing only on release is why cross # toolchain closures get rebuilt from source (~68 min observed elsewhere # in this stack) instead of substituted. - name: Push to Cachix if: ${{ env.CACHIX_AUTH_TOKEN != '' }} - env: - CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + run: | + set -euo pipefail + nix profile install nixpkgs#cachix + for out in kernel perf driver; do + nix build --print-out-paths \ + ".#packages.x86_64-linux.\"$out-${{ matrix.cell }}\"" \ + | cachix push rehosting-tools + done + + # The full 20-cell matrix, on demand. Not on every PR: it is the expensive + # one, and the gate above catches the failures that are not arch-specific. + full: + name: full matrix + runs-on: rehosting-arc + needs: series + if: ${{ github.event_name == 'workflow_dispatch' && inputs.full_matrix }} + steps: + - uses: actions/checkout@v4 + - uses: rehosting/nix-setup@v1 + + - name: Every kernel + run: nix build --print-out-paths ".#all" + + # Built separately from `.#all` so a perf or module failure is + # attributable at a glance rather than buried in a 20-cell aggregate. + - name: Every perf and module + run: | + set -euo pipefail + cells=$(nix eval --json ".#packages.x86_64-linux" --apply \ + 'p: builtins.filter (n: builtins.match "(perf|driver)-.*" n != null) + (builtins.attrNames p)' | python3 -c 'import json,sys;print("\n".join(json.load(sys.stdin)))') + fail=0 + for c in $cells; do + if nix build --no-link ".#packages.x86_64-linux.\"$c\""; then + echo "OK $c" + else + echo "FAIL $c"; fail=1 + fi + done + exit $fail + + - name: Release tarballs assemble + run: | + nix build --print-out-paths .#kernels-latest + nix build --print-out-paths .#kernel-devel-all + + - name: Push to Cachix + if: ${{ env.CACHIX_AUTH_TOKEN != '' }} run: | nix profile install nixpkgs#cachix - nix build --print-out-paths ".#packages.x86_64-linux.\"${{ matrix.cell }}\"" \ - | cachix push rehosting-tools + nix build --print-out-paths .#all | cachix push rehosting-tools From 0f5639d81ff48187e94e9438cf21ce18e76f8ba9 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 01:56:57 -0400 Subject: [PATCH 12/28] shape-check: assert each artifact's ELF matches its target name Two bugs shipped on this branch that every other check passed: perf emitted four byte-identical big-endian 64-bit binaries across the powerpc family, and configs/6.13/powerpcle asked for an endianness Kconfig cannot grant so the kernel came out big-endian. Both built cleanly and produced files of the right name in the right place. They are one failure class -- an ELF whose class or byte order disagrees with what its name promises -- and reading the ELF header catches it for nothing. Checks the unstripped `vmlinux` output rather than $out: only some targets deliver a vmlinux in $out (the rest ship zImage/bzImage/Image, compressed blobs with no readable class), so checking $out would silently skip armel, arm64, loongarch64, riscv64 and x86_64 -- five of thirteen, which is the same partial coverage the check exists to prevent. Missing artifacts now fail rather than being skipped. powerpcle is excluded, with the exclusion reported as SKIP rather than passing quietly: a 32-bit little-endian powerpc kernel is not expressible in mainline Linux, so there is no honest expectation to assert -- LSB would fail a build behaving as well as it can, MSB would bless a name that lies. Draft 34 carries the recommendation to retire the target. --- .github/workflows/nix.yml | 6 +++ flake.nix | 5 +++ nix/shape.nix | 94 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 nix/shape.nix diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index edd6568..b8c22a5 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -128,6 +128,12 @@ jobs: done exit $fail + # Every artifact's ELF class and byte order must match what its target + # name claims. Cheap, and it is the only check that catches a cell which + # builds cleanly and produces the wrong machine's binary. + - name: Shapes match target names + run: nix build --print-out-paths .#shape-check + - name: Release tarballs assemble run: | nix build --print-out-paths .#kernels-latest diff --git a/flake.nix b/flake.nix index 63aa3af..5337beb 100644 --- a/flake.nix +++ b/flake.nix @@ -153,6 +153,11 @@ }; kernel-devel-all = releaseLib.develTarball { cells = allRecords; }; + # Catches the failure class where a cell builds fine and produces an + # artifact whose ELF class or endianness disagrees with its target name. + # See nix/shape.nix -- two such bugs shipped undetected on this branch. + shape-check = (import ./nix/shape.nix { inherit pkgs; }) { cells = allRecords; }; + # The analysis tools, pinned. Exposed so their provenance is inspectable # and so igloo_driver can reuse dwarf2json for its own ISF (it runs the # same fork over igloo.ko) instead of re-deriving the pin. diff --git a/nix/shape.nix b/nix/shape.nix new file mode 100644 index 0000000..a366e42 --- /dev/null +++ b/nix/shape.nix @@ -0,0 +1,94 @@ +# Assert that what a cell actually produced matches what its target name claims. +# +# Two bugs on this branch were invisible to every other check because the build +# succeeded and the artifact existed: +# +# - perf inherited kernel.nix's powerpc family collapse and emitted four +# BYTE-IDENTICAL big-endian 64-bit binaries for powerpc, powerpcle, +# powerpc64 and powerpc64le. Three cannot run on their guest. +# +# - configs/6.13/powerpcle asks for CONFIG_CPU_LITTLE_ENDIAN=y, which +# arch/powerpc/platforms/Kconfig.cputype makes conditional on PPC_BOOK3S_64. +# olddefconfig drops it without complaint and the kernel comes out +# big-endian, byte-identical to powerpc's. +# +# Both are the same shape of failure: an ELF whose class or endianness silently +# disagrees with its name. The kernel build cannot catch it (Kconfig resolved +# "correctly" by its own rules) and neither can a smoke test that only checks a +# file exists. Reading the ELF header does catch it, costs nothing, and is the +# check that would have found both. +# +# Deliberately NOT derived from the toolchain or the config -- those are the +# things being checked. The expectation comes from the target name, which is +# what every consumer downstream believes. +{ pkgs }: + +let + inherit (pkgs) lib; + + # target -> (ELF class, byte order), as the NAME promises. + expect = { + armel = { bits = 32; endian = "LSB"; }; + arm64 = { bits = 64; endian = "LSB"; }; + mipsel = { bits = 32; endian = "LSB"; }; + mipseb = { bits = 32; endian = "MSB"; }; + mips64el = { bits = 64; endian = "LSB"; }; + mips64eb = { bits = 64; endian = "MSB"; }; + powerpc = { bits = 32; endian = "MSB"; }; + powerpc64 = { bits = 64; endian = "MSB"; }; + powerpc64le = { bits = 64; endian = "LSB"; }; + loongarch64 = { bits = 64; endian = "LSB"; }; + riscv64 = { bits = 64; endian = "LSB"; }; + x86_64 = { bits = 64; endian = "LSB"; }; + + # powerpcle is deliberately absent. A 32-bit little-endian powerpc kernel is + # not expressible in mainline Linux (CPU_LITTLE_ENDIAN depends on + # PPC_BOOK3S_64), so there is no honest expectation to assert: the cell + # really does produce big-endian output, identical to `powerpc`. Asserting + # LSB would fail a build that is behaving as well as it can; asserting MSB + # would bless a target name that lies. It is excluded, and the exclusion is + # itself reported, so the anomaly stays visible rather than becoming a + # silently-passing row. See draft 34. + }; + +in +{ cells }: + +pkgs.runCommand "igloo-shape-check" +{ + nativeBuildInputs = [ pkgs.file ]; +} '' + fail=0 + report() { printf '%-24s %-9s %s\n' "$1" "$2" "$3"; } + + ${lib.concatMapStringsSep "\n" + (c: + let e = expect.${c.target} or null; in + if e == null then '' + report "${c.version}/${c.target}" "SKIP" "no honest expectation for this target name" + '' else '' + # The kernel comes from the `vmlinux` output, not `out`. Only some + # targets deliver a vmlinux in $out (the rest ship zImage/bzImage/Image, + # which are compressed blobs `file` cannot read a class or byte order + # from), so checking $out would silently skip armel, arm64, loongarch64, + # riscv64 and x86_64 -- five of thirteen, and exactly the kind of + # partial coverage this check exists to prevent. + for f in ${c.kernel.vmlinux}/vmlinux.${c.target} ${c.perf}/perf.${c.target}; do + [ -f "$f" ] || { report "${c.version}/${c.target}" "MISSING" "$f"; fail=1; continue; } + desc=$(file -b "$f") + case "$desc" in + *"${toString e.bits}-bit ${e.endian}"*) report "${c.version}/${c.target}" "ok" "$(basename $f)" ;; + *) + report "${c.version}/${c.target}" "MISMATCH" "$(basename $f): want ${toString e.bits}-bit ${e.endian}, got: $desc" + fail=1 ;; + esac + done + '') + cells} + + if [ $fail -ne 0 ]; then + echo "shape check FAILED: an artifact's ELF class/endianness disagrees with its target name" >&2 + exit 1 + fi + echo "shape check passed" > $out +'' From fc0b287ddc88ed8db2c9e2b657685aa46c46e9f2 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 09:52:31 -0400 Subject: [PATCH 13/28] Retire powerpcle: a 32-bit little-endian powerpc kernel does not exist arch/powerpc/platforms/Kconfig.cputype: config CPU_LITTLE_ENDIAN bool "Build little endian kernel" depends on PPC_BOOK3S_64 PPC_BOOK3S_64 is 64-bit only, so on a 32-bit config the symbol is not selectable. configs/6.13/powerpcle was '#include "powerpc"' plus CONFIG_CPU_LITTLE_ENDIAN=y; olddefconfig dropped the line without a word and built a big-endian kernel. vmlinux.powerpcle was verified BYTE-IDENTICAL (sha256) to vmlinux.powerpc. The cell cost a kernel, a static perf, an osi + cosi extraction and an igloo.ko per release, to ship 'powerpc' twice under a name asserting the opposite -- and had penguin ever selected it for genuinely little-endian firmware it would have been handed a big-endian kernel silently. (powerpc LE hardware starts at POWER8/ppc64le, so the likely device impact is zero, but that is luck.) 4.10 already retired this target. This brings 6.13 into line: 19 cells, not 20. The .unused file keeps the reasoning and the original two lines, so nobody rediscovers this from scratch. Drops the powerpcle special case from perf.nix (toolchainArch is now the identity for every cell in the matrix) and the exclusion from shape.nix, which was only there because no honest expectation could be written for the target. Also pins kernelsmith to the pushed buildmodule branch, so driver cells build with no --override-input. --- .gitignore | 1 + configs/6.13/powerpcle | 2 -- configs/6.13/powerpcle.unused | 33 +++++++++++++++++++++++++++++++++ flake.lock | 7 ++++--- flake.nix | 2 +- nix/matrix.nix | 12 ++++++++---- nix/perf.nix | 22 +++++----------------- nix/shape.nix | 13 +++++-------- 8 files changed, 57 insertions(+), 35 deletions(-) delete mode 100644 configs/6.13/powerpcle create mode 100644 configs/6.13/powerpcle.unused diff --git a/.gitignore b/.gitignore index 8915002..c991461 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ *.tar.gz *.log *.linted +cache cache/ kernels/ diff --git a/configs/6.13/powerpcle b/configs/6.13/powerpcle deleted file mode 100644 index d1e1d32..0000000 --- a/configs/6.13/powerpcle +++ /dev/null @@ -1,2 +0,0 @@ -#include "powerpc" -CONFIG_CPU_LITTLE_ENDIAN=y diff --git a/configs/6.13/powerpcle.unused b/configs/6.13/powerpcle.unused new file mode 100644 index 0000000..06b5d2b --- /dev/null +++ b/configs/6.13/powerpcle.unused @@ -0,0 +1,33 @@ +# RETIRED. A 32-bit little-endian powerpc kernel cannot be built from mainline +# Linux, so this config never produced what its name claims. +# +# arch/powerpc/platforms/Kconfig.cputype: +# +# config CPU_LITTLE_ENDIAN +# bool "Build little endian kernel" +# depends on PPC_BOOK3S_64 +# +# PPC_BOOK3S_64 is 64-bit only, so on a 32-bit config the symbol is not +# selectable, olddefconfig drops the line below without a word, and the build +# falls back to big endian. The resulting vmlinux.powerpcle was verified +# BYTE-IDENTICAL (sha256) to vmlinux.powerpc. +# +# The cell therefore cost a kernel build, a static perf build, an osi + cosi +# extraction and an igloo.ko build per release, to ship `powerpc` a second time +# under a name asserting the opposite. Worse than the waste: had penguin ever +# selected powerpcle for genuinely little-endian firmware, it would have been +# handed a big-endian kernel with nothing to indicate it. (In practice powerpc +# LE hardware starts at POWER8/ppc64le, so the likely device impact is zero -- +# but that is luck, not design.) +# +# 4.10 already retired this target (configs/4.10/powerpcle.unused); this brings +# 6.13 into line. If a real 32-bit LE powerpc target ever appears, it needs +# kernel support that does not exist upstream, not this file. +# +# `nix build .#shape-check` now asserts every cell's ELF class and byte order +# against its target name, so a future config asking for an endianness Kconfig +# will not grant fails loudly instead of silently. +# +# Original contents: +# #include "powerpc" +# CONFIG_CPU_LITTLE_ENDIAN=y diff --git a/flake.lock b/flake.lock index 9b80047..669c14a 100644 --- a/flake.lock +++ b/flake.lock @@ -22,15 +22,16 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1786596203, - "narHash": "sha256-ukayW5lL9ZPG6A9HHML2jVXya34k7eZpmbS1pG4zJh0=", + "lastModified": 1786626941, + "narHash": "sha256-uynOJDkUTq7V3gZxNre3CmeMwBSYYoToi1kYea52OPU=", "owner": "rehosting", "repo": "kernelsmith", - "rev": "c00a01b79812dd90b5de5ebeb115871f0471313c", + "rev": "cbea743ea5e89eb2087841f2bda1ea1e30018ea6", "type": "github" }, "original": { "owner": "rehosting", + "ref": "buildmodule", "repo": "kernelsmith", "type": "github" } diff --git a/flake.nix b/flake.nix index 5337beb..316fa34 100644 --- a/flake.nix +++ b/flake.nix @@ -13,7 +13,7 @@ # the embedded-toolchains Docker image, whose toolchains were unversioned # `wget https://musl.cc/*-cross.tgz` downloads -- i.e. today's shipped # kernels have no recorded compiler identity. - kernelsmith.url = "github:rehosting/kernelsmith"; + kernelsmith.url = "github:rehosting/kernelsmith/buildmodule"; nixpkgs.follows = "kernelsmith/nixpkgs"; # Source only -- igloo_driver has no flake of its own yet. This is here to diff --git a/nix/matrix.nix b/nix/matrix.nix index bdd0dc4..25cb347 100644 --- a/nix/matrix.nix +++ b/nix/matrix.nix @@ -4,9 +4,14 @@ # keys, deliberately -- they were already aligned). Sourced from configs//, # excluding *.inc (fragments) and *.unused (retired targets). # -# NOTE 4.10 is 7 targets, not 13: every powerpc* config is .unused, and -# loongarch64/riscv64 don't exist for that version. The full matrix is 20 cells, -# not the 26 a naive 2x13 suggests. +# NOTE 4.10 is 7 targets, not 12: every powerpc* config is .unused, and +# loongarch64/riscv64 don't exist for that version. The full matrix is 19 cells, +# not the 24 a naive 2x12 suggests. +# +# powerpcle is retired on BOTH versions. CPU_LITTLE_ENDIAN depends on +# PPC_BOOK3S_64, so a 32-bit little-endian powerpc kernel is not expressible in +# mainline Linux; the config's request was silently dropped and the cell built a +# byte-identical copy of `powerpc`. See configs/6.13/powerpcle.unused. { "4.10" = [ "armel" @@ -26,7 +31,6 @@ "mips64eb" "mips64el" "powerpc" - "powerpcle" "powerpc64" "powerpc64le" "loongarch64" diff --git a/nix/perf.nix b/nix/perf.nix index 5031726..aa18ec1 100644 --- a/nix/perf.nix +++ b/nix/perf.nix @@ -42,23 +42,11 @@ let # Using each variant's own toolchain also gets the matching 32-bit/LE musl, # which a 64-bit BE sysroot simply does not contain. # - # The one exception is `powerpcle`, and it is not a toolchain problem -- it is - # that the target does not exist. arch/powerpc/platforms/Kconfig.cputype has - # - # config CPU_LITTLE_ENDIAN - # depends on PPC_BOOK3S_64 - # - # so a 32-bit little-endian powerpc kernel cannot be expressed in mainline - # Linux at all. configs/6.13/powerpcle sets CONFIG_CPU_LITTLE_ENDIAN=y, - # olddefconfig silently drops it, and the resulting vmlinux is byte-identical - # to `powerpc` (verified by sha256). configs/4.10/powerpcle is already - # retired as `.unused`. - # - # So the KERNEL for this cell is big-endian, and perf must match it or we ship - # a userspace binary that cannot run on its own kernel. Building perf "as the - # target name implies" would be the more wrong answer here. - # See draft 34 for the open question of whether this cell should exist. - toolchainArch = target: if target == "powerpcle" then "powerpc" else target; + # (`powerpcle` used to need a special case here, because its kernel came out + # big-endian whatever its name said. The target is retired instead -- see + # configs/6.13/powerpcle.unused -- so the identity mapping is now honest for + # every cell in the matrix.) + toolchainArch = target: target; # perf resolves its tools headers with -I$(srctree)/tools/arch/$(ARCH)/include/uapi, # using ARCH verbatim rather than the SRCARCH that kbuild derives from it. The diff --git a/nix/shape.nix b/nix/shape.nix index a366e42..0cdbc2b 100644 --- a/nix/shape.nix +++ b/nix/shape.nix @@ -41,14 +41,11 @@ let riscv64 = { bits = 64; endian = "LSB"; }; x86_64 = { bits = 64; endian = "LSB"; }; - # powerpcle is deliberately absent. A 32-bit little-endian powerpc kernel is - # not expressible in mainline Linux (CPU_LITTLE_ENDIAN depends on - # PPC_BOOK3S_64), so there is no honest expectation to assert: the cell - # really does produce big-endian output, identical to `powerpc`. Asserting - # LSB would fail a build that is behaving as well as it can; asserting MSB - # would bless a target name that lies. It is excluded, and the exclusion is - # itself reported, so the anomaly stays visible rather than becoming a - # silently-passing row. See draft 34. + # No powerpcle entry, and none is needed: the target is retired (see + # configs/6.13/powerpcle.unused) precisely because no honest expectation + # could be written for it. If it ever comes back without real upstream + # ppc32-LE support, it lands in the SKIP branch below rather than passing + # quietly -- which is the point. }; in From 2715099b72beb8f1bfcc8f1e150c9abbeb8c3977 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 19:20:21 -0400 Subject: [PATCH 14/28] flake: repin kernelsmith to main now that buildModule has merged The branch pin was only ever a bridge while rehosting/kernelsmith#3 was in review. It merged rebased, so the commit hashes changed -- but the input's narHash did not, and all 19 driver cells resolve to the same store paths with no rebuild. Same content, permanent ref. --- flake.lock | 5 ++--- flake.nix | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 669c14a..232b61d 100644 --- a/flake.lock +++ b/flake.lock @@ -22,16 +22,15 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1786626941, + "lastModified": 1786663087, "narHash": "sha256-uynOJDkUTq7V3gZxNre3CmeMwBSYYoToi1kYea52OPU=", "owner": "rehosting", "repo": "kernelsmith", - "rev": "cbea743ea5e89eb2087841f2bda1ea1e30018ea6", + "rev": "f3220b9a1919076317659310d75b28f0c36fab62", "type": "github" }, "original": { "owner": "rehosting", - "ref": "buildmodule", "repo": "kernelsmith", "type": "github" } diff --git a/flake.nix b/flake.nix index 316fa34..5337beb 100644 --- a/flake.nix +++ b/flake.nix @@ -13,7 +13,7 @@ # the embedded-toolchains Docker image, whose toolchains were unversioned # `wget https://musl.cc/*-cross.tgz` downloads -- i.e. today's shipped # kernels have no recorded compiler identity. - kernelsmith.url = "github:rehosting/kernelsmith/buildmodule"; + kernelsmith.url = "github:rehosting/kernelsmith"; nixpkgs.follows = "kernelsmith/nixpkgs"; # Source only -- igloo_driver has no flake of its own yet. This is here to From 7fed7ce37494daf0c9048b07f8256331bf090d7d Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 19:23:02 -0400 Subject: [PATCH 15/28] ci: replace the phantom rehosting/nix-setup with a real local action Every job in the previous draft died at "Set up job" with Unable to resolve action rehosting/nix-setup, repository not found before running a step -- the referenced action repo does not exist. It is now a local composite action, version-locked to the workflow that uses it and unable to 404, mirroring the install-nix-action setup that already works on rehosting-arc in hyperfs. Also sets the substituters in the runner's nix.conf rather than relying on flake.nix's nixConfig, which is ignored for non-trusted users -- the failure mode there is not an error but a silent full rebuild of every cross toolchain. --- .github/actions/nix-setup/action.yml | 37 ++++++++++++++++++++++++++++ .github/workflows/nix.yml | 21 ++++++++++------ 2 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 .github/actions/nix-setup/action.yml diff --git a/.github/actions/nix-setup/action.yml b/.github/actions/nix-setup/action.yml new file mode 100644 index 0000000..390ed08 --- /dev/null +++ b/.github/actions/nix-setup/action.yml @@ -0,0 +1,37 @@ +# Shared Nix setup for this repo's workflows. +# +# Local composite action rather than a `rehosting/nix-setup` repo: an earlier +# draft of nix.yml referenced `rehosting/nix-setup@v1`, which does not exist, so +# every job failed at "Set up job" with `Unable to resolve action ..., +# repository not found` -- before running a single step. Keeping it in-repo +# means it is version-locked to the workflow that uses it and cannot 404. +# +# The setup itself mirrors what already works on `rehosting-arc` elsewhere in +# the org (rehosting/hyperfs build.yaml): cachix/install-nix-action with a +# token, plus explicit substituter config. +name: nix-setup +description: Install Nix and point it at the rehosting-tools binary cache. + +inputs: + github_token: + description: Token for install-nix-action, to avoid unauthenticated rate limits. + required: false + default: "" + +runs: + using: composite + steps: + - uses: cachix/install-nix-action@v27 + with: + github_access_token: ${{ inputs.github_token }} + # The substituters are also declared in flake.nix's nixConfig, but that + # only applies for trusted users -- on a runner where the invoking user + # is not in trusted-users the flake's request is silently ignored and + # every cross toolchain rebuilds from source. Setting them here is what + # actually takes effect. + extra_nix_config: | + max-jobs = 8 + cores = 8 + extra-substituters = https://rehosting-tools.cachix.org + extra-trusted-public-keys = rehosting-tools.cachix.org-1:iNKSaFwG7MfGn6Fk7oTmIcLHqfffQ+cQIE5gWc6MlY0= + accept-flake-config = true diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index b8c22a5..eed1883 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -5,8 +5,8 @@ # series applies cleanly to the pinned upstream tarball" is the invariant that # makes patches-as-source-of-truth safe. # -# NOTE: not yet exercised on the self-hosted runners -- treat the runner and -# cache wiring as a first draft to be confirmed on the first real run. +# Runner/cache wiring is exercised on `rehosting-arc`; see +# .github/actions/nix-setup for why that setup is a local composite action. name: nix (patch series + kernels) on: @@ -43,8 +43,9 @@ jobs: steps: - uses: actions/checkout@v4 - # install-nix-action trips over root-owned /nix on these runners. - - uses: rehosting/nix-setup@v1 + - uses: ./.github/actions/nix-setup + with: + github_token: ${{ secrets.GITHUB_TOKEN }} - name: Fetch the pinned upstream tarball id: tarball @@ -72,7 +73,9 @@ jobs: cell: ["4.10-armel", "6.13-armel"] steps: - uses: actions/checkout@v4 - - uses: rehosting/nix-setup@v1 + - uses: ./.github/actions/nix-setup + with: + github_token: ${{ secrets.GITHUB_TOKEN }} - name: Build kernel, perf and module run: | @@ -96,7 +99,7 @@ jobs: | cachix push rehosting-tools done - # The full 20-cell matrix, on demand. Not on every PR: it is the expensive + # The full 19-cell matrix, on demand. Not on every PR: it is the expensive # one, and the gate above catches the failures that are not arch-specific. full: name: full matrix @@ -105,13 +108,15 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && inputs.full_matrix }} steps: - uses: actions/checkout@v4 - - uses: rehosting/nix-setup@v1 + - uses: ./.github/actions/nix-setup + with: + github_token: ${{ secrets.GITHUB_TOKEN }} - name: Every kernel run: nix build --print-out-paths ".#all" # Built separately from `.#all` so a perf or module failure is - # attributable at a glance rather than buried in a 20-cell aggregate. + # attributable at a glance rather than buried in a 19-cell aggregate. - name: Every perf and module run: | set -euo pipefail From d9ffd8472e802a1f5bd7edec3b9acc421c7e9315 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 19:24:16 -0400 Subject: [PATCH 16/28] ci(nix-setup): install xz before the nix installer needs it install-nix-action downloads the installer fine and then fails with you do not have 'xz' installed, which I need to unpack the binary tarball The rehosting-arc image has no xz. Guarded on command -v so it costs nothing on a runner that already has it. --- .github/actions/nix-setup/action.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/actions/nix-setup/action.yml b/.github/actions/nix-setup/action.yml index 390ed08..d19df82 100644 --- a/.github/actions/nix-setup/action.yml +++ b/.github/actions/nix-setup/action.yml @@ -21,6 +21,18 @@ inputs: runs: using: composite steps: + # The nix installer unpacks an .xz tarball and the rehosting-arc image ships + # without xz, so install-nix-action dies with "you do not have 'xz' + # installed" after successfully downloading the installer. Every repo in the + # org that runs Nix on these runners apt-installs it first. + - shell: bash + run: | + set -euo pipefail + if ! command -v xz >/dev/null; then + sudo apt-get update -qq + sudo apt-get install -y -qq xz-utils curl + fi + - uses: cachix/install-nix-action@v27 with: github_access_token: ${{ inputs.github_token }} From 6db73636604530a3df38ae410aabea305b1884b9 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 19:44:48 -0400 Subject: [PATCH 17/28] patches/6.13: repair 0019, which was corruption rather than churn 2729 lines -> 163. The real content is 109 insertions and 10 deletions; the other ~2600 lines were an artifact. Every context line in the patch carried a leading space that was never stripped: it was generated by treating a unified diff's body as file content, so the " " that marks a context line became part of the line. That is not confined to the patch file -- it is in the tree we ship: pristine 6.13 IGLOO (before) # directives at column 0 120 9 # directives indented one space 0 119 struct x; forward decls indented 0 62 Indented preprocessor directives are legal C, which is why this shipped in Aug 2025 and no compiler has complained since. Repaired by reconstructing the header against pristine upstream: where a line is equal modulo whitespace, upstream's formatting wins; IGLOO's genuinely new lines are kept verbatim. The amended commit was then rebased under the remaining 18 patches of the series, all of which applied clean. Verified: - `diff -w` old vs new syscalls.h is empty, and across the whole patched tree syscalls.h is the ONLY file that differs. - The committed series re-imports from scratch: 33 commits apply cleanly to the pinned upstream tarball and yield the same header. - kernel-6.13-armel rebuilt and compared section by section: .text, .rodata, .data, .init.text and __ksymtab are byte-identical. The only differences anywhere are .debug_line (-12 bytes), .debug_info, and the 20-byte GNU build-id -- DWARF records column numbers, so de-indenting moves them, and the build-id is a hash over the linked image. The raw boot image differs in exactly those 20 contiguous build-id bytes out of 26.7 MB. So: no change to the compiled kernel's behaviour, and the worst rebase hazard in the series is gone. For comparison, 4.10's equivalent patch was already clean at 141 lines; a scan of all 71 patches finds no other instance. Note for anyone using the round-trip tooling: export-series.sh renumbers the whole series (format-patch numbers 1..33, while the committed names come from an older 37-commit export and have gaps where core/ patches sit), so running it for a one-patch fix yields 33 renames. This change regenerated only 0019's body and kept its original header. Worth making export stable against existing names. --- patches/6.13/0019-add-syscalls.h.patch | 2664 +----------------------- 1 file changed, 49 insertions(+), 2615 deletions(-) diff --git a/patches/6.13/0019-add-syscalls.h.patch b/patches/6.13/0019-add-syscalls.h.patch index 58a0ec2..2f13508 100644 --- a/patches/6.13/0019-add-syscalls.h.patch +++ b/patches/6.13/0019-add-syscalls.h.patch @@ -4,452 +4,17 @@ Date: Fri, 1 Aug 2025 11:22:08 -0400 Subject: [PATCH 19/37] add syscalls.h --- - include/linux/syscalls.h | 2701 ++++++++++++++++++++------------------ - 1 file changed, 1400 insertions(+), 1301 deletions(-) + include/linux/syscalls.h | 119 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 109 insertions(+), 10 deletions(-) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h -index c6333204d4..71394c3e30 100644 +index c6333204d..09d13ebf2 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h -@@ -6,1314 +6,1413 @@ - * Copyright (c) 2004 Open Source Development Labs - */ +@@ -213,14 +213,68 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) + } + #endif --#ifndef _LINUX_SYSCALLS_H --#define _LINUX_SYSCALLS_H -- --struct __aio_sigset; --struct epoll_event; --struct iattr; --struct inode; --struct iocb; --struct io_event; --struct iovec; --struct __kernel_old_itimerval; --struct kexec_segment; --struct linux_dirent; --struct linux_dirent64; --struct list_head; --struct mmap_arg_struct; --struct msgbuf; --struct user_msghdr; --struct mmsghdr; --struct msqid_ds; --struct new_utsname; --struct nfsctl_arg; --struct __old_kernel_stat; --struct oldold_utsname; --struct old_utsname; --struct pollfd; --struct rlimit; --struct rlimit64; --struct rusage; --struct sched_param; --struct sched_attr; --struct sel_arg_struct; --struct semaphore; --struct sembuf; --struct shmid_ds; --struct sockaddr; --struct stat; --struct stat64; --struct statfs; --struct statfs64; --struct statx; --struct sysinfo; --struct timespec; --struct __kernel_old_timeval; --struct __kernel_timex; --struct timezone; --struct tms; --struct utimbuf; --struct mq_attr; --struct compat_stat; --struct old_timeval32; --struct robust_list_head; --struct futex_waitv; --struct getcpu_cache; --struct old_linux_dirent; --struct perf_event_attr; --struct file_handle; --struct sigaltstack; --struct rseq; --union bpf_attr; --struct io_uring_params; --struct clone_args; --struct open_how; --struct mount_attr; --struct landlock_ruleset_attr; --struct lsm_ctx; --enum landlock_rule_type; --struct cachestat_range; --struct cachestat; --struct statmount; --struct mnt_id_req; --struct xattr_args; -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER --/* -- * It may be useful for an architecture to override the definitions of the -- * SYSCALL_DEFINE0() and __SYSCALL_DEFINEx() macros, in particular to use a -- * different calling convention for syscalls. To allow for that, the prototypes -- * for the sys_*() functions below will *not* be included if -- * CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled. -- */ --#include --#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ -- --/* -- * __MAP - apply a macro to syscall arguments -- * __MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to -- * m(t1, a1), m(t2, a2), ..., m(tn, an) -- * The first argument must be equal to the amount of type/name -- * pairs given. Note that this list of pairs (i.e. the arguments -- * of __MAP starting at the third one) is in the same format as -- * for SYSCALL_DEFINE/COMPAT_SYSCALL_DEFINE -- */ --#define __MAP0(m,...) --#define __MAP1(m,t,a,...) m(t,a) --#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__) --#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__) --#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__) --#define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__) --#define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__) --#define __MAP(n,...) __MAP##n(__VA_ARGS__) -- --#define __SC_DECL(t, a) t a --#define __TYPE_AS(t, v) __same_type((__force t)0, v) --#define __TYPE_IS_L(t) (__TYPE_AS(t, 0L)) --#define __TYPE_IS_UL(t) (__TYPE_AS(t, 0UL)) --#define __TYPE_IS_LL(t) (__TYPE_AS(t, 0LL) || __TYPE_AS(t, 0ULL)) --#define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a --#define __SC_CAST(t, a) (__force t) a --#define __SC_TYPE(t, a) t --#define __SC_ARGS(t, a) a --#define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long)) -- --#ifdef CONFIG_FTRACE_SYSCALLS --#define __SC_STR_ADECL(t, a) #a --#define __SC_STR_TDECL(t, a) #t -- --extern struct trace_event_class event_class_syscall_enter; --extern struct trace_event_class event_class_syscall_exit; --extern struct trace_event_functions enter_syscall_print_funcs; --extern struct trace_event_functions exit_syscall_print_funcs; -- --#define SYSCALL_TRACE_ENTER_EVENT(sname) \ -- static struct syscall_metadata __syscall_meta_##sname; \ -- static struct trace_event_call __used \ -- event_enter_##sname = { \ -- .class = &event_class_syscall_enter, \ -- { \ -- .name = "sys_enter"#sname, \ -- }, \ -- .event.funcs = &enter_syscall_print_funcs, \ -- .data = (void *)&__syscall_meta_##sname,\ -- .flags = TRACE_EVENT_FL_CAP_ANY, \ -- }; \ -- static struct trace_event_call __used \ -- __section("_ftrace_events") \ -- *__event_enter_##sname = &event_enter_##sname; -- --#define SYSCALL_TRACE_EXIT_EVENT(sname) \ -- static struct syscall_metadata __syscall_meta_##sname; \ -- static struct trace_event_call __used \ -- event_exit_##sname = { \ -- .class = &event_class_syscall_exit, \ -- { \ -- .name = "sys_exit"#sname, \ -- }, \ -- .event.funcs = &exit_syscall_print_funcs, \ -- .data = (void *)&__syscall_meta_##sname,\ -- .flags = TRACE_EVENT_FL_CAP_ANY, \ -- }; \ -- static struct trace_event_call __used \ -- __section("_ftrace_events") \ -- *__event_exit_##sname = &event_exit_##sname; -- --#define SYSCALL_METADATA(sname, nb, ...) \ -- static const char *types_##sname[] = { \ -- __MAP(nb,__SC_STR_TDECL,__VA_ARGS__) \ -- }; \ -- static const char *args_##sname[] = { \ -- __MAP(nb,__SC_STR_ADECL,__VA_ARGS__) \ -- }; \ -- SYSCALL_TRACE_ENTER_EVENT(sname); \ -- SYSCALL_TRACE_EXIT_EVENT(sname); \ -- static struct syscall_metadata __used \ -- __syscall_meta_##sname = { \ -- .name = "sys"#sname, \ -- .syscall_nr = -1, /* Filled in at boot */ \ -- .nb_args = nb, \ -- .types = nb ? types_##sname : NULL, \ -- .args = nb ? args_##sname : NULL, \ -- .enter_event = &event_enter_##sname, \ -- .exit_event = &event_exit_##sname, \ -- .enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \ -- }; \ -- static struct syscall_metadata __used \ -- __section("__syscalls_metadata") \ -- *__p_syscall_meta_##sname = &__syscall_meta_##sname; -- --static inline int is_syscall_trace_event(struct trace_event_call *tp_event) --{ -- return tp_event->class == &event_class_syscall_enter || -- tp_event->class == &event_class_syscall_exit; --} -- --#else --#define SYSCALL_METADATA(sname, nb, ...) -- --static inline int is_syscall_trace_event(struct trace_event_call *tp_event) --{ -- return 0; --} --#endif -- --#ifndef SYSCALL_DEFINE0 --#define SYSCALL_DEFINE0(sname) \ -- SYSCALL_METADATA(_##sname, 0); \ -- asmlinkage long sys_##sname(void); \ -- ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \ -- asmlinkage long sys_##sname(void) --#endif /* SYSCALL_DEFINE0 */ -- --#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) --#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) --#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) --#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__) --#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__) --#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) -- --#define SYSCALL_DEFINE_MAXARGS 6 -- --#define SYSCALL_DEFINEx(x, sname, ...) \ -- SYSCALL_METADATA(sname, x, __VA_ARGS__) \ -- __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) -- -+ #ifndef _LINUX_SYSCALLS_H -+ #define _LINUX_SYSCALLS_H -+ -+ struct __aio_sigset; -+ struct epoll_event; -+ struct iattr; -+ struct inode; -+ struct iocb; -+ struct io_event; -+ struct iovec; -+ struct __kernel_old_itimerval; -+ struct kexec_segment; -+ struct linux_dirent; -+ struct linux_dirent64; -+ struct list_head; -+ struct mmap_arg_struct; -+ struct msgbuf; -+ struct user_msghdr; -+ struct mmsghdr; -+ struct msqid_ds; -+ struct new_utsname; -+ struct nfsctl_arg; -+ struct __old_kernel_stat; -+ struct oldold_utsname; -+ struct old_utsname; -+ struct pollfd; -+ struct rlimit; -+ struct rlimit64; -+ struct rusage; -+ struct sched_param; -+ struct sched_attr; -+ struct sel_arg_struct; -+ struct semaphore; -+ struct sembuf; -+ struct shmid_ds; -+ struct sockaddr; -+ struct stat; -+ struct stat64; -+ struct statfs; -+ struct statfs64; -+ struct statx; -+ struct sysinfo; -+ struct timespec; -+ struct __kernel_old_timeval; -+ struct __kernel_timex; -+ struct timezone; -+ struct tms; -+ struct utimbuf; -+ struct mq_attr; -+ struct compat_stat; -+ struct old_timeval32; -+ struct robust_list_head; -+ struct futex_waitv; -+ struct getcpu_cache; -+ struct old_linux_dirent; -+ struct perf_event_attr; -+ struct file_handle; -+ struct sigaltstack; -+ struct rseq; -+ union bpf_attr; -+ struct io_uring_params; -+ struct clone_args; -+ struct open_how; -+ struct mount_attr; -+ struct landlock_ruleset_attr; -+ struct lsm_ctx; -+ enum landlock_rule_type; -+ struct cachestat_range; -+ struct cachestat; -+ struct statmount; -+ struct mnt_id_req; -+ struct xattr_args; -+ -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ -+ #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER -+ /* -+ * It may be useful for an architecture to override the definitions of the -+ * SYSCALL_DEFINE0() and __SYSCALL_DEFINEx() macros, in particular to use a -+ * different calling convention for syscalls. To allow for that, the prototypes -+ * for the sys_*() functions below will *not* be included if -+ * CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled. -+ */ -+ #include -+ #endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ -+ -+ /* -+ * __MAP - apply a macro to syscall arguments -+ * __MAP(n, m, t1, a1, t2, a2, ..., tn, an) will expand to -+ * m(t1, a1), m(t2, a2), ..., m(tn, an) -+ * The first argument must be equal to the amount of type/name -+ * pairs given. Note that this list of pairs (i.e. the arguments -+ * of __MAP starting at the third one) is in the same format as -+ * for SYSCALL_DEFINE/COMPAT_SYSCALL_DEFINE -+ */ -+ #define __MAP0(m,...) -+ #define __MAP1(m,t,a,...) m(t,a) -+ #define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__) -+ #define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__) -+ #define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__) -+ #define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__) -+ #define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__) -+ #define __MAP(n,...) __MAP##n(__VA_ARGS__) -+ -+ #define __SC_DECL(t, a) t a -+ #define __TYPE_AS(t, v) __same_type((__force t)0, v) -+ #define __TYPE_IS_L(t) (__TYPE_AS(t, 0L)) -+ #define __TYPE_IS_UL(t) (__TYPE_AS(t, 0UL)) -+ #define __TYPE_IS_LL(t) (__TYPE_AS(t, 0LL) || __TYPE_AS(t, 0ULL)) -+ #define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a -+ #define __SC_CAST(t, a) (__force t) a -+ #define __SC_TYPE(t, a) t -+ #define __SC_ARGS(t, a) a -+ #define __SC_TEST(t, a) (void)BUILD_BUG_ON_ZERO(!__TYPE_IS_LL(t) && sizeof(t) > sizeof(long)) -+ -+ #ifdef CONFIG_FTRACE_SYSCALLS -+ #define __SC_STR_ADECL(t, a) #a -+ #define __SC_STR_TDECL(t, a) #t -+ -+ extern struct trace_event_class event_class_syscall_enter; -+ extern struct trace_event_class event_class_syscall_exit; -+ extern struct trace_event_functions enter_syscall_print_funcs; -+ extern struct trace_event_functions exit_syscall_print_funcs; -+ -+ #define SYSCALL_TRACE_ENTER_EVENT(sname) \ -+ static struct syscall_metadata __syscall_meta_##sname; \ -+ static struct trace_event_call __used \ -+ event_enter_##sname = { \ -+ .class = &event_class_syscall_enter, \ -+ { \ -+ .name = "sys_enter"#sname, \ -+ }, \ -+ .event.funcs = &enter_syscall_print_funcs, \ -+ .data = (void *)&__syscall_meta_##sname,\ -+ .flags = TRACE_EVENT_FL_CAP_ANY, \ -+ }; \ -+ static struct trace_event_call __used \ -+ __section("_ftrace_events") \ -+ *__event_enter_##sname = &event_enter_##sname; -+ -+ #define SYSCALL_TRACE_EXIT_EVENT(sname) \ -+ static struct syscall_metadata __syscall_meta_##sname; \ -+ static struct trace_event_call __used \ -+ event_exit_##sname = { \ -+ .class = &event_class_syscall_exit, \ -+ { \ -+ .name = "sys_exit"#sname, \ -+ }, \ -+ .event.funcs = &exit_syscall_print_funcs, \ -+ .data = (void *)&__syscall_meta_##sname,\ -+ .flags = TRACE_EVENT_FL_CAP_ANY, \ -+ }; \ -+ static struct trace_event_call __used \ -+ __section("_ftrace_events") \ -+ *__event_exit_##sname = &event_exit_##sname; -+ -+ #define SYSCALL_METADATA(sname, nb, ...) \ -+ static const char *types_##sname[] = { \ -+ __MAP(nb,__SC_STR_TDECL,__VA_ARGS__) \ -+ }; \ -+ static const char *args_##sname[] = { \ -+ __MAP(nb,__SC_STR_ADECL,__VA_ARGS__) \ -+ }; \ -+ SYSCALL_TRACE_ENTER_EVENT(sname); \ -+ SYSCALL_TRACE_EXIT_EVENT(sname); \ -+ static struct syscall_metadata __used \ -+ __syscall_meta_##sname = { \ -+ .name = "sys"#sname, \ -+ .syscall_nr = -1, /* Filled in at boot */ \ -+ .nb_args = nb, \ -+ .types = nb ? types_##sname : NULL, \ -+ .args = nb ? args_##sname : NULL, \ -+ .enter_event = &event_enter_##sname, \ -+ .exit_event = &event_exit_##sname, \ -+ .enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \ -+ }; \ -+ static struct syscall_metadata __used \ -+ __section("__syscalls_metadata") \ -+ *__p_syscall_meta_##sname = &__syscall_meta_##sname; -+ -+ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) -+ { -+ return tp_event->class == &event_class_syscall_enter || -+ tp_event->class == &event_class_syscall_exit; -+ } -+ -+ #else -+ #define SYSCALL_METADATA(sname, nb, ...) -+ -+ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) -+ { -+ return 0; -+ } -+ #endif -+ +#ifdef CONFIG_IGLOO +#include +/* === Igloo Interception Hooks and Helpers === */ @@ -467,36 +32,21 @@ index c6333204d4..71394c3e30 100644 + +/* --- Definition for __PROTECT --- */ +#ifndef __PROTECT - #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) -- --/* -- * The asmlinkage stub is aliased to a function named __se_sys_*() which -- * sign-extends 32-bit ints to longs whenever needed. The actual work is -- * done within __do_sys_*(). -- */ --#ifndef __SYSCALL_DEFINEx --#define __SYSCALL_DEFINEx(x, name, ...) \ -- __diag_push(); \ -- __diag_ignore(GCC, 8, "-Wattribute-alias", \ -- "Type aliasing is used to sanitize syscall arguments");\ -- asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ -- __attribute__((alias(__stringify(__se_sys##name)))); \ -- ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ -- static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ -- asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ -- asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ ++#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) +#endif /* __PROTECT */ -+ #ifndef SYSCALL_DEFINE0 -+ #define SYSCALL_DEFINE0(name) \ + #ifndef SYSCALL_DEFINE0 +-#define SYSCALL_DEFINE0(sname) \ +- SYSCALL_METADATA(_##sname, 0); \ +- asmlinkage long sys_##sname(void); \ +- ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \ +- asmlinkage long sys_##sname(void) ++#define SYSCALL_DEFINE0(name) \ + SYSCALL_METADATA(_##name, 0); \ + asmlinkage long sys_##name(void); \ + ALLOW_ERROR_INJECTION(sys_##name, ERRNO); \ + static inline long __do_sys_##name(void); /* Declare impl */ \ + asmlinkage long sys_##name(void) \ - { \ -- long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\ -- __MAP(x,__SC_TEST,__VA_ARGS__); \ -- __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ ++ { \ + const char *syscall_basename = __stringify(name); /* Base name */ \ + long ret; \ + bool skip = false; \ @@ -523,157 +73,42 @@ index c6333204d4..71394c3e30 100644 + \ + /* Argument protection and final return */ \ + __PROTECT(0, ret); /* Protect for 0 args */ \ - return ret; \ - } \ -- __diag_pop(); \ -- static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) --#endif /* __SYSCALL_DEFINEx */ -- --/* For split 64-bit arguments on 32-bit architectures */ --#ifdef __LITTLE_ENDIAN --#define SC_ARG64(name) u32, name##_lo, u32, name##_hi --#else --#define SC_ARG64(name) u32, name##_hi, u32, name##_lo --#endif --#define SC_VAL64(type, name) ((type) name##_hi << 32 | name##_lo) -- --#ifdef CONFIG_COMPAT --#define SYSCALL32_DEFINE0 COMPAT_SYSCALL_DEFINE0 --#define SYSCALL32_DEFINE1 COMPAT_SYSCALL_DEFINE1 --#define SYSCALL32_DEFINE2 COMPAT_SYSCALL_DEFINE2 --#define SYSCALL32_DEFINE3 COMPAT_SYSCALL_DEFINE3 --#define SYSCALL32_DEFINE4 COMPAT_SYSCALL_DEFINE4 --#define SYSCALL32_DEFINE5 COMPAT_SYSCALL_DEFINE5 --#define SYSCALL32_DEFINE6 COMPAT_SYSCALL_DEFINE6 --#else --#define SYSCALL32_DEFINE0 SYSCALL_DEFINE0 --#define SYSCALL32_DEFINE1 SYSCALL_DEFINE1 --#define SYSCALL32_DEFINE2 SYSCALL_DEFINE2 --#define SYSCALL32_DEFINE3 SYSCALL_DEFINE3 --#define SYSCALL32_DEFINE4 SYSCALL_DEFINE4 --#define SYSCALL32_DEFINE5 SYSCALL_DEFINE5 --#define SYSCALL32_DEFINE6 SYSCALL_DEFINE6 --#endif -- --/* -- * These syscall function prototypes are kept in the same order as -- * include/uapi/asm-generic/unistd.h. Architecture specific entries go below, -- * followed by deprecated or obsolete system calls. -- * -- * Please note that these prototypes here are only provided for information -- * purposes, for static analysis, and for linking from the syscall table. -- * These functions should not be called elsewhere from kernel code. -- * -- * As the syscall calling convention may be different from the default -- * for architectures overriding the syscall calling convention, do not -- * include the prototypes if CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled. -- */ --#ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER --asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t __user *ctx); --asmlinkage long sys_io_destroy(aio_context_t ctx); --asmlinkage long sys_io_submit(aio_context_t, long, -- struct iocb __user * __user *); --asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, -- struct io_event __user *result); --asmlinkage long sys_io_getevents(aio_context_t ctx_id, -- long min_nr, -- long nr, -- struct io_event __user *events, -- struct __kernel_timespec __user *timeout); --asmlinkage long sys_io_getevents_time32(__u32 ctx_id, -- __s32 min_nr, -- __s32 nr, -- struct io_event __user *events, -- struct old_timespec32 __user *timeout); --asmlinkage long sys_io_pgetevents(aio_context_t ctx_id, -- long min_nr, -- long nr, -- struct io_event __user *events, -- struct __kernel_timespec __user *timeout, -- const struct __aio_sigset __user *sig); --asmlinkage long sys_io_pgetevents_time32(aio_context_t ctx_id, -- long min_nr, -- long nr, -- struct io_event __user *events, -- struct old_timespec32 __user *timeout, -- const struct __aio_sigset __user *sig); --asmlinkage long sys_io_uring_setup(u32 entries, -- struct io_uring_params __user *p); --asmlinkage long sys_io_uring_enter(unsigned int fd, u32 to_submit, -- u32 min_complete, u32 flags, -- const void __user *argp, size_t argsz); --asmlinkage long sys_io_uring_register(unsigned int fd, unsigned int op, -- void __user *arg, unsigned int nr_args); --asmlinkage long sys_setxattr(const char __user *path, const char __user *name, -- const void __user *value, size_t size, int flags); --asmlinkage long sys_setxattrat(int dfd, const char __user *path, unsigned int at_flags, -- const char __user *name, -- const struct xattr_args __user *args, size_t size); --asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name, -- const void __user *value, size_t size, int flags); --asmlinkage long sys_fsetxattr(int fd, const char __user *name, -- const void __user *value, size_t size, int flags); --asmlinkage long sys_getxattr(const char __user *path, const char __user *name, -- void __user *value, size_t size); --asmlinkage long sys_getxattrat(int dfd, const char __user *path, unsigned int at_flags, -- const char __user *name, -- struct xattr_args __user *args, size_t size); --asmlinkage long sys_lgetxattr(const char __user *path, const char __user *name, -- void __user *value, size_t size); --asmlinkage long sys_fgetxattr(int fd, const char __user *name, -- void __user *value, size_t size); --asmlinkage long sys_listxattr(const char __user *path, char __user *list, -- size_t size); --asmlinkage long sys_listxattrat(int dfd, const char __user *path, -- unsigned int at_flags, -- char __user *list, size_t size); --asmlinkage long sys_llistxattr(const char __user *path, char __user *list, -- size_t size); --asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size); --asmlinkage long sys_removexattr(const char __user *path, -- const char __user *name); --asmlinkage long sys_removexattrat(int dfd, const char __user *path, -- unsigned int at_flags, -- const char __user *name); --asmlinkage long sys_lremovexattr(const char __user *path, ++ return ret; \ ++ } \ + /* User's syscall code defines the __do_sys_##name function */ \ + static inline long __do_sys_##name(void) -+ #endif /* SYSCALL_DEFINE0 */ -+ + #endif /* SYSCALL_DEFINE0 */ + + +/* --- Modified SYSCALL_DEFINE1..6 & SYSCALL_DEFINEx --- */ +/* Pass base name AND internal (_name) to SYSCALL_DEFINEx */ -+ #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) -+ #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) -+ #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) -+ #define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__) -+ #define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__) -+ #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) -+ -+ #define SYSCALL_DEFINE_MAXARGS 6 -+ #define SYSCALL_DEFINEx(x, name, ...) \ + #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) + #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) + #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) +@@ -229,12 +283,13 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) + #define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) + + #define SYSCALL_DEFINE_MAXARGS 6 ++#define SYSCALL_DEFINEx(x, name, ...) \ + SYSCALL_METADATA(name, x, __VA_ARGS__) \ + __SYSCALL_DEFINEx(x, name, __VA_ARGS__) -+ -+ + +-#define SYSCALL_DEFINEx(x, sname, ...) \ +- SYSCALL_METADATA(sname, x, __VA_ARGS__) \ +- __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) + +-#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) +/* --- Modified __SYSCALL_DEFINEx --- */ +/* Note: Added 'name' (base name) parameter */ -+ -+ /* -+ * The asmlinkage stub is aliased to a function named __se_sys_*() which -+ * sign-extends 32-bit ints to longs whenever needed. The actual work is -+ * done within __do_sys_*(). -+ */ -+ #ifndef __SYSCALL_DEFINEx -+ #define __SYSCALL_DEFINEx(x, name, ...) \ -+ __diag_push(); \ -+ __diag_ignore(GCC, 8, "-Wattribute-alias", \ -+ "Type aliasing is used to sanitize syscall arguments");\ -+ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ -+ __attribute__((alias(__stringify(__se_sys##name)))); \ -+ ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ + + /* + * The asmlinkage stub is aliased to a function named __se_sys_*() which +@@ -249,12 +304,56 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) + asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ + __attribute__((alias(__stringify(__se_sys##name)))); \ + ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ + /* Implementation function declaration */ \ -+ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ + static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ + /* Setter function definition: Body generated using __SC_GEN_SETTER_BODY_WRAPPER */ \ + void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]); \ + void __igloo_set_args##name(const unsigned long args_ptr_array[], const __le64 new_args_le64[]) \ @@ -681,9 +116,10 @@ index c6333204d4..71394c3e30 100644 + __SC_GEN_SETTER_BODY_WRAPPER(x, __VA_ARGS__); \ + } \ + /* Sign-extended wrapper function definition */ \ -+ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ -+ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ -+ { \ + asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ +- long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\ + const char *syscall_basename = __stringify(name); /* Base name */ \ + long ret; \ + bool skip = false; \ @@ -713,7 +149,7 @@ index c6333204d4..71394c3e30 100644 + } \ + \ + /* Original type tests */ \ -+ __MAP(x,__SC_TEST,__VA_ARGS__); \ + __MAP(x,__SC_TEST,__VA_ARGS__); \ + \ + /* === Igloo Return Hook === */ \ + if (igloo_syscall_return_hook) { \ @@ -722,2008 +158,6 @@ index c6333204d4..71394c3e30 100644 + } \ + \ + /* Argument protection and final return */ \ -+ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ -+ return ret; \ -+ } \ -+ __diag_pop(); \ -+ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) -+ #endif /* __SYSCALL_DEFINEx */ -+ -+ /* For split 64-bit arguments on 32-bit architectures */ -+ #ifdef __LITTLE_ENDIAN -+ #define SC_ARG64(name) u32, name##_lo, u32, name##_hi -+ #else -+ #define SC_ARG64(name) u32, name##_hi, u32, name##_lo -+ #endif -+ #define SC_VAL64(type, name) ((type) name##_hi << 32 | name##_lo) -+ -+ #ifdef CONFIG_COMPAT -+ #define SYSCALL32_DEFINE0 COMPAT_SYSCALL_DEFINE0 -+ #define SYSCALL32_DEFINE1 COMPAT_SYSCALL_DEFINE1 -+ #define SYSCALL32_DEFINE2 COMPAT_SYSCALL_DEFINE2 -+ #define SYSCALL32_DEFINE3 COMPAT_SYSCALL_DEFINE3 -+ #define SYSCALL32_DEFINE4 COMPAT_SYSCALL_DEFINE4 -+ #define SYSCALL32_DEFINE5 COMPAT_SYSCALL_DEFINE5 -+ #define SYSCALL32_DEFINE6 COMPAT_SYSCALL_DEFINE6 -+ #else -+ #define SYSCALL32_DEFINE0 SYSCALL_DEFINE0 -+ #define SYSCALL32_DEFINE1 SYSCALL_DEFINE1 -+ #define SYSCALL32_DEFINE2 SYSCALL_DEFINE2 -+ #define SYSCALL32_DEFINE3 SYSCALL_DEFINE3 -+ #define SYSCALL32_DEFINE4 SYSCALL_DEFINE4 -+ #define SYSCALL32_DEFINE5 SYSCALL_DEFINE5 -+ #define SYSCALL32_DEFINE6 SYSCALL_DEFINE6 -+ #endif -+ -+ /* -+ * These syscall function prototypes are kept in the same order as -+ * include/uapi/asm-generic/unistd.h. Architecture specific entries go below, -+ * followed by deprecated or obsolete system calls. -+ * -+ * Please note that these prototypes here are only provided for information -+ * purposes, for static analysis, and for linking from the syscall table. -+ * These functions should not be called elsewhere from kernel code. -+ * -+ * As the syscall calling convention may be different from the default -+ * for architectures overriding the syscall calling convention, do not -+ * include the prototypes if CONFIG_ARCH_HAS_SYSCALL_WRAPPER is enabled. -+ */ -+ #ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER -+ asmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t __user *ctx); -+ asmlinkage long sys_io_destroy(aio_context_t ctx); -+ asmlinkage long sys_io_submit(aio_context_t, long, -+ struct iocb __user * __user *); -+ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, -+ struct io_event __user *result); -+ asmlinkage long sys_io_getevents(aio_context_t ctx_id, -+ long min_nr, -+ long nr, -+ struct io_event __user *events, -+ struct __kernel_timespec __user *timeout); -+ asmlinkage long sys_io_getevents_time32(__u32 ctx_id, -+ __s32 min_nr, -+ __s32 nr, -+ struct io_event __user *events, -+ struct old_timespec32 __user *timeout); -+ asmlinkage long sys_io_pgetevents(aio_context_t ctx_id, -+ long min_nr, -+ long nr, -+ struct io_event __user *events, -+ struct __kernel_timespec __user *timeout, -+ const struct __aio_sigset __user *sig); -+ asmlinkage long sys_io_pgetevents_time32(aio_context_t ctx_id, -+ long min_nr, -+ long nr, -+ struct io_event __user *events, -+ struct old_timespec32 __user *timeout, -+ const struct __aio_sigset __user *sig); -+ asmlinkage long sys_io_uring_setup(u32 entries, -+ struct io_uring_params __user *p); -+ asmlinkage long sys_io_uring_enter(unsigned int fd, u32 to_submit, -+ u32 min_complete, u32 flags, -+ const void __user *argp, size_t argsz); -+ asmlinkage long sys_io_uring_register(unsigned int fd, unsigned int op, -+ void __user *arg, unsigned int nr_args); -+ asmlinkage long sys_setxattr(const char __user *path, const char __user *name, -+ const void __user *value, size_t size, int flags); -+ asmlinkage long sys_setxattrat(int dfd, const char __user *path, unsigned int at_flags, -+ const char __user *name, -+ const struct xattr_args __user *args, size_t size); -+ asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name, -+ const void __user *value, size_t size, int flags); -+ asmlinkage long sys_fsetxattr(int fd, const char __user *name, -+ const void __user *value, size_t size, int flags); -+ asmlinkage long sys_getxattr(const char __user *path, const char __user *name, -+ void __user *value, size_t size); -+ asmlinkage long sys_getxattrat(int dfd, const char __user *path, unsigned int at_flags, -+ const char __user *name, -+ struct xattr_args __user *args, size_t size); -+ asmlinkage long sys_lgetxattr(const char __user *path, const char __user *name, -+ void __user *value, size_t size); -+ asmlinkage long sys_fgetxattr(int fd, const char __user *name, -+ void __user *value, size_t size); -+ asmlinkage long sys_listxattr(const char __user *path, char __user *list, -+ size_t size); -+ asmlinkage long sys_listxattrat(int dfd, const char __user *path, -+ unsigned int at_flags, -+ char __user *list, size_t size); -+ asmlinkage long sys_llistxattr(const char __user *path, char __user *list, -+ size_t size); -+ asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size); -+ asmlinkage long sys_removexattr(const char __user *path, - const char __user *name); --asmlinkage long sys_fremovexattr(int fd, const char __user *name); --asmlinkage long sys_getcwd(char __user *buf, unsigned long size); --asmlinkage long sys_eventfd2(unsigned int count, int flags); --asmlinkage long sys_epoll_create1(int flags); --asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, -- struct epoll_event __user *event); --asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, -- int maxevents, int timeout, -- const sigset_t __user *sigmask, -- size_t sigsetsize); --asmlinkage long sys_epoll_pwait2(int epfd, struct epoll_event __user *events, -- int maxevents, -- const struct __kernel_timespec __user *timeout, -+ asmlinkage long sys_removexattrat(int dfd, const char __user *path, -+ unsigned int at_flags, -+ const char __user *name); -+ asmlinkage long sys_lremovexattr(const char __user *path, -+ const char __user *name); -+ asmlinkage long sys_fremovexattr(int fd, const char __user *name); -+ asmlinkage long sys_getcwd(char __user *buf, unsigned long size); -+ asmlinkage long sys_eventfd2(unsigned int count, int flags); -+ asmlinkage long sys_epoll_create1(int flags); -+ asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, -+ struct epoll_event __user *event); -+ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, -+ int maxevents, int timeout, - const sigset_t __user *sigmask, - size_t sigsetsize); --asmlinkage long sys_dup(unsigned int fildes); --asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags); --asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); --#if BITS_PER_LONG == 32 --asmlinkage long sys_fcntl64(unsigned int fd, -- unsigned int cmd, unsigned long arg); --#endif --asmlinkage long sys_inotify_init1(int flags); --asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, -- u32 mask); --asmlinkage long sys_inotify_rm_watch(int fd, __s32 wd); --asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, -- unsigned long arg); --asmlinkage long sys_ioprio_set(int which, int who, int ioprio); --asmlinkage long sys_ioprio_get(int which, int who); --asmlinkage long sys_flock(unsigned int fd, unsigned int cmd); --asmlinkage long sys_mknodat(int dfd, const char __user * filename, umode_t mode, -- unsigned dev); --asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, umode_t mode); --asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag); --asmlinkage long sys_symlinkat(const char __user * oldname, -- int newdfd, const char __user * newname); --asmlinkage long sys_linkat(int olddfd, const char __user *oldname, -- int newdfd, const char __user *newname, int flags); --asmlinkage long sys_renameat(int olddfd, const char __user * oldname, -- int newdfd, const char __user * newname); --asmlinkage long sys_umount(char __user *name, int flags); --asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name, -- char __user *type, unsigned long flags, -- void __user *data); --asmlinkage long sys_pivot_root(const char __user *new_root, -- const char __user *put_old); --asmlinkage long sys_statfs(const char __user * path, -- struct statfs __user *buf); --asmlinkage long sys_statfs64(const char __user *path, size_t sz, -- struct statfs64 __user *buf); --asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf); --asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, -- struct statfs64 __user *buf); --asmlinkage long sys_statmount(const struct mnt_id_req __user *req, -- struct statmount __user *buf, size_t bufsize, -- unsigned int flags); --asmlinkage long sys_listmount(const struct mnt_id_req __user *req, -- u64 __user *mnt_ids, size_t nr_mnt_ids, -- unsigned int flags); --asmlinkage long sys_truncate(const char __user *path, long length); --asmlinkage long sys_ftruncate(unsigned int fd, off_t length); --#if BITS_PER_LONG == 32 --asmlinkage long sys_truncate64(const char __user *path, loff_t length); --asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length); --#endif --asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len); --asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode); --asmlinkage long sys_faccessat2(int dfd, const char __user *filename, int mode, -- int flags); --asmlinkage long sys_chdir(const char __user *filename); --asmlinkage long sys_fchdir(unsigned int fd); --asmlinkage long sys_chroot(const char __user *filename); --asmlinkage long sys_fchmod(unsigned int fd, umode_t mode); --asmlinkage long sys_fchmodat(int dfd, const char __user *filename, -- umode_t mode); --asmlinkage long sys_fchmodat2(int dfd, const char __user *filename, -- umode_t mode, unsigned int flags); --asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, -- gid_t group, int flag); --asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group); --asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, -- umode_t mode); --asmlinkage long sys_openat2(int dfd, const char __user *filename, -- struct open_how __user *how, size_t size); --asmlinkage long sys_close(unsigned int fd); --asmlinkage long sys_close_range(unsigned int fd, unsigned int max_fd, -- unsigned int flags); --asmlinkage long sys_vhangup(void); --asmlinkage long sys_pipe2(int __user *fildes, int flags); --asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, -- qid_t id, void __user *addr); --asmlinkage long sys_quotactl_fd(unsigned int fd, unsigned int cmd, qid_t id, -- void __user *addr); --asmlinkage long sys_getdents64(unsigned int fd, -- struct linux_dirent64 __user *dirent, -- unsigned int count); --asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, -- unsigned long offset_low, loff_t __user *result, -- unsigned int whence); --asmlinkage long sys_lseek(unsigned int fd, off_t offset, -- unsigned int whence); --asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count); --asmlinkage long sys_write(unsigned int fd, const char __user *buf, -- size_t count); --asmlinkage long sys_readv(unsigned long fd, -- const struct iovec __user *vec, -- unsigned long vlen); --asmlinkage long sys_writev(unsigned long fd, -+ asmlinkage long sys_epoll_pwait2(int epfd, struct epoll_event __user *events, -+ int maxevents, -+ const struct __kernel_timespec __user *timeout, -+ const sigset_t __user *sigmask, -+ size_t sigsetsize); -+ asmlinkage long sys_dup(unsigned int fildes); -+ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags); -+ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); -+ #if BITS_PER_LONG == 32 -+ asmlinkage long sys_fcntl64(unsigned int fd, -+ unsigned int cmd, unsigned long arg); -+ #endif -+ asmlinkage long sys_inotify_init1(int flags); -+ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, -+ u32 mask); -+ asmlinkage long sys_inotify_rm_watch(int fd, __s32 wd); -+ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, -+ unsigned long arg); -+ asmlinkage long sys_ioprio_set(int which, int who, int ioprio); -+ asmlinkage long sys_ioprio_get(int which, int who); -+ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd); -+ asmlinkage long sys_mknodat(int dfd, const char __user * filename, umode_t mode, -+ unsigned dev); -+ asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, umode_t mode); -+ asmlinkage long sys_unlinkat(int dfd, const char __user * pathname, int flag); -+ asmlinkage long sys_symlinkat(const char __user * oldname, -+ int newdfd, const char __user * newname); -+ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, -+ int newdfd, const char __user *newname, int flags); -+ asmlinkage long sys_renameat(int olddfd, const char __user * oldname, -+ int newdfd, const char __user * newname); -+ asmlinkage long sys_umount(char __user *name, int flags); -+ asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name, -+ char __user *type, unsigned long flags, -+ void __user *data); -+ asmlinkage long sys_pivot_root(const char __user *new_root, -+ const char __user *put_old); -+ asmlinkage long sys_statfs(const char __user * path, -+ struct statfs __user *buf); -+ asmlinkage long sys_statfs64(const char __user *path, size_t sz, -+ struct statfs64 __user *buf); -+ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf); -+ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, -+ struct statfs64 __user *buf); -+ asmlinkage long sys_statmount(const struct mnt_id_req __user *req, -+ struct statmount __user *buf, size_t bufsize, -+ unsigned int flags); -+ asmlinkage long sys_listmount(const struct mnt_id_req __user *req, -+ u64 __user *mnt_ids, size_t nr_mnt_ids, -+ unsigned int flags); -+ asmlinkage long sys_truncate(const char __user *path, long length); -+ asmlinkage long sys_ftruncate(unsigned int fd, off_t length); -+ #if BITS_PER_LONG == 32 -+ asmlinkage long sys_truncate64(const char __user *path, loff_t length); -+ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length); -+ #endif -+ asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len); -+ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode); -+ asmlinkage long sys_faccessat2(int dfd, const char __user *filename, int mode, -+ int flags); -+ asmlinkage long sys_chdir(const char __user *filename); -+ asmlinkage long sys_fchdir(unsigned int fd); -+ asmlinkage long sys_chroot(const char __user *filename); -+ asmlinkage long sys_fchmod(unsigned int fd, umode_t mode); -+ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, -+ umode_t mode); -+ asmlinkage long sys_fchmodat2(int dfd, const char __user *filename, -+ umode_t mode, unsigned int flags); -+ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, -+ gid_t group, int flag); -+ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group); -+ asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, -+ umode_t mode); -+ asmlinkage long sys_openat2(int dfd, const char __user *filename, -+ struct open_how __user *how, size_t size); -+ asmlinkage long sys_close(unsigned int fd); -+ asmlinkage long sys_close_range(unsigned int fd, unsigned int max_fd, -+ unsigned int flags); -+ asmlinkage long sys_vhangup(void); -+ asmlinkage long sys_pipe2(int __user *fildes, int flags); -+ asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, -+ qid_t id, void __user *addr); -+ asmlinkage long sys_quotactl_fd(unsigned int fd, unsigned int cmd, qid_t id, -+ void __user *addr); -+ asmlinkage long sys_getdents64(unsigned int fd, -+ struct linux_dirent64 __user *dirent, -+ unsigned int count); -+ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, -+ unsigned long offset_low, loff_t __user *result, -+ unsigned int whence); -+ asmlinkage long sys_lseek(unsigned int fd, off_t offset, -+ unsigned int whence); -+ asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count); -+ asmlinkage long sys_write(unsigned int fd, const char __user *buf, -+ size_t count); -+ asmlinkage long sys_readv(unsigned long fd, - const struct iovec __user *vec, - unsigned long vlen); --asmlinkage long sys_pread64(unsigned int fd, char __user *buf, -- size_t count, loff_t pos); --asmlinkage long sys_pwrite64(unsigned int fd, const char __user *buf, -- size_t count, loff_t pos); --asmlinkage long sys_preadv(unsigned long fd, const struct iovec __user *vec, -- unsigned long vlen, unsigned long pos_l, unsigned long pos_h); --asmlinkage long sys_pwritev(unsigned long fd, const struct iovec __user *vec, -- unsigned long vlen, unsigned long pos_l, unsigned long pos_h); --asmlinkage long sys_sendfile64(int out_fd, int in_fd, -- loff_t __user *offset, size_t count); --asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, -- fd_set __user *, struct __kernel_timespec __user *, -- void __user *); --asmlinkage long sys_pselect6_time32(int, fd_set __user *, fd_set __user *, -- fd_set __user *, struct old_timespec32 __user *, -- void __user *); --asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int, -- struct __kernel_timespec __user *, const sigset_t __user *, -- size_t); --asmlinkage long sys_ppoll_time32(struct pollfd __user *, unsigned int, -- struct old_timespec32 __user *, const sigset_t __user *, -- size_t); --asmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, int flags); --asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov, -- unsigned long nr_segs, unsigned int flags); --asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, -- int fd_out, loff_t __user *off_out, -- size_t len, unsigned int flags); --asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags); --asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, -- int bufsiz); --asmlinkage long sys_newfstatat(int dfd, const char __user *filename, -- struct stat __user *statbuf, int flag); --asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf); --#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) --asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf); --asmlinkage long sys_fstatat64(int dfd, const char __user *filename, -- struct stat64 __user *statbuf, int flag); --#endif --asmlinkage long sys_sync(void); --asmlinkage long sys_fsync(unsigned int fd); --asmlinkage long sys_fdatasync(unsigned int fd); --asmlinkage long sys_sync_file_range2(int fd, unsigned int flags, -- loff_t offset, loff_t nbytes); --asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, -- unsigned int flags); --asmlinkage long sys_timerfd_create(int clockid, int flags); --asmlinkage long sys_timerfd_settime(int ufd, int flags, -- const struct __kernel_itimerspec __user *utmr, -- struct __kernel_itimerspec __user *otmr); --asmlinkage long sys_timerfd_gettime(int ufd, struct __kernel_itimerspec __user *otmr); --asmlinkage long sys_timerfd_gettime32(int ufd, -- struct old_itimerspec32 __user *otmr); --asmlinkage long sys_timerfd_settime32(int ufd, int flags, -- const struct old_itimerspec32 __user *utmr, -- struct old_itimerspec32 __user *otmr); --asmlinkage long sys_utimensat(int dfd, const char __user *filename, -- struct __kernel_timespec __user *utimes, -- int flags); --asmlinkage long sys_utimensat_time32(unsigned int dfd, -- const char __user *filename, -- struct old_timespec32 __user *t, int flags); --asmlinkage long sys_acct(const char __user *name); --asmlinkage long sys_capget(cap_user_header_t header, -- cap_user_data_t dataptr); --asmlinkage long sys_capset(cap_user_header_t header, -- const cap_user_data_t data); --asmlinkage long sys_personality(unsigned int personality); --asmlinkage long sys_exit(int error_code); --asmlinkage long sys_exit_group(int error_code); --asmlinkage long sys_waitid(int which, pid_t pid, -- struct siginfo __user *infop, -- int options, struct rusage __user *ru); --asmlinkage long sys_set_tid_address(int __user *tidptr); --asmlinkage long sys_unshare(unsigned long unshare_flags); --asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, -- const struct __kernel_timespec __user *utime, -- u32 __user *uaddr2, u32 val3); --asmlinkage long sys_futex_time32(u32 __user *uaddr, int op, u32 val, -- const struct old_timespec32 __user *utime, -- u32 __user *uaddr2, u32 val3); --asmlinkage long sys_get_robust_list(int pid, -- struct robust_list_head __user * __user *head_ptr, -- size_t __user *len_ptr); --asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, -- size_t len); -- --asmlinkage long sys_futex_waitv(struct futex_waitv __user *waiters, -- unsigned int nr_futexes, unsigned int flags, -- struct __kernel_timespec __user *timeout, clockid_t clockid); -- --asmlinkage long sys_futex_wake(void __user *uaddr, unsigned long mask, int nr, unsigned int flags); -- --asmlinkage long sys_futex_wait(void __user *uaddr, unsigned long val, unsigned long mask, -- unsigned int flags, struct __kernel_timespec __user *timespec, -- clockid_t clockid); -- --asmlinkage long sys_futex_requeue(struct futex_waitv __user *waiters, -- unsigned int flags, int nr_wake, int nr_requeue); -- --asmlinkage long sys_nanosleep(struct __kernel_timespec __user *rqtp, -- struct __kernel_timespec __user *rmtp); --asmlinkage long sys_nanosleep_time32(struct old_timespec32 __user *rqtp, -- struct old_timespec32 __user *rmtp); --asmlinkage long sys_getitimer(int which, struct __kernel_old_itimerval __user *value); --asmlinkage long sys_setitimer(int which, -- struct __kernel_old_itimerval __user *value, -- struct __kernel_old_itimerval __user *ovalue); --asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, -- struct kexec_segment __user *segments, -- unsigned long flags); --asmlinkage long sys_init_module(void __user *umod, unsigned long len, -- const char __user *uargs); --asmlinkage long sys_delete_module(const char __user *name_user, -- unsigned int flags); --asmlinkage long sys_timer_create(clockid_t which_clock, -- struct sigevent __user *timer_event_spec, -- timer_t __user * created_timer_id); --asmlinkage long sys_timer_gettime(timer_t timer_id, -- struct __kernel_itimerspec __user *setting); --asmlinkage long sys_timer_getoverrun(timer_t timer_id); --asmlinkage long sys_timer_settime(timer_t timer_id, int flags, -- const struct __kernel_itimerspec __user *new_setting, -- struct __kernel_itimerspec __user *old_setting); --asmlinkage long sys_timer_delete(timer_t timer_id); --asmlinkage long sys_clock_settime(clockid_t which_clock, -- const struct __kernel_timespec __user *tp); --asmlinkage long sys_clock_gettime(clockid_t which_clock, -- struct __kernel_timespec __user *tp); --asmlinkage long sys_clock_getres(clockid_t which_clock, -- struct __kernel_timespec __user *tp); --asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags, -- const struct __kernel_timespec __user *rqtp, -- struct __kernel_timespec __user *rmtp); --asmlinkage long sys_timer_gettime32(timer_t timer_id, -- struct old_itimerspec32 __user *setting); --asmlinkage long sys_timer_settime32(timer_t timer_id, int flags, -- struct old_itimerspec32 __user *new, -- struct old_itimerspec32 __user *old); --asmlinkage long sys_clock_settime32(clockid_t which_clock, -- struct old_timespec32 __user *tp); --asmlinkage long sys_clock_gettime32(clockid_t which_clock, -- struct old_timespec32 __user *tp); --asmlinkage long sys_clock_getres_time32(clockid_t which_clock, -- struct old_timespec32 __user *tp); --asmlinkage long sys_clock_nanosleep_time32(clockid_t which_clock, int flags, -- struct old_timespec32 __user *rqtp, -- struct old_timespec32 __user *rmtp); --asmlinkage long sys_syslog(int type, char __user *buf, int len); --asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, -- unsigned long data); --asmlinkage long sys_sched_setparam(pid_t pid, -- struct sched_param __user *param); --asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, -- struct sched_param __user *param); --asmlinkage long sys_sched_getscheduler(pid_t pid); --asmlinkage long sys_sched_getparam(pid_t pid, -- struct sched_param __user *param); --asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, -- unsigned long __user *user_mask_ptr); --asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, -- unsigned long __user *user_mask_ptr); --asmlinkage long sys_sched_yield(void); --asmlinkage long sys_sched_get_priority_max(int policy); --asmlinkage long sys_sched_get_priority_min(int policy); --asmlinkage long sys_sched_rr_get_interval(pid_t pid, -- struct __kernel_timespec __user *interval); --asmlinkage long sys_sched_rr_get_interval_time32(pid_t pid, -- struct old_timespec32 __user *interval); --asmlinkage long sys_restart_syscall(void); --asmlinkage long sys_kill(pid_t pid, int sig); --asmlinkage long sys_tkill(pid_t pid, int sig); --asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig); --asmlinkage long sys_sigaltstack(const struct sigaltstack __user *uss, -- struct sigaltstack __user *uoss); --asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize); --#ifndef CONFIG_ODD_RT_SIGACTION --asmlinkage long sys_rt_sigaction(int, -- const struct sigaction __user *, -- struct sigaction __user *, -- size_t); --#endif --asmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set, -- sigset_t __user *oset, size_t sigsetsize); --asmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize); --asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese, -- siginfo_t __user *uinfo, -- const struct __kernel_timespec __user *uts, -- size_t sigsetsize); --asmlinkage long sys_rt_sigtimedwait_time32(const sigset_t __user *uthese, -- siginfo_t __user *uinfo, -- const struct old_timespec32 __user *uts, -- size_t sigsetsize); --asmlinkage long sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo); --asmlinkage long sys_setpriority(int which, int who, int niceval); --asmlinkage long sys_getpriority(int which, int who); --asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, -- void __user *arg); --asmlinkage long sys_setregid(gid_t rgid, gid_t egid); --asmlinkage long sys_setgid(gid_t gid); --asmlinkage long sys_setreuid(uid_t ruid, uid_t euid); --asmlinkage long sys_setuid(uid_t uid); --asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); --asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid); --asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); --asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid); --asmlinkage long sys_setfsuid(uid_t uid); --asmlinkage long sys_setfsgid(gid_t gid); --asmlinkage long sys_times(struct tms __user *tbuf); --asmlinkage long sys_setpgid(pid_t pid, pid_t pgid); --asmlinkage long sys_getpgid(pid_t pid); --asmlinkage long sys_getsid(pid_t pid); --asmlinkage long sys_setsid(void); --asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist); --asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist); --asmlinkage long sys_newuname(struct new_utsname __user *name); --asmlinkage long sys_sethostname(char __user *name, int len); --asmlinkage long sys_setdomainname(char __user *name, int len); --asmlinkage long sys_getrlimit(unsigned int resource, -- struct rlimit __user *rlim); --asmlinkage long sys_setrlimit(unsigned int resource, -- struct rlimit __user *rlim); --asmlinkage long sys_getrusage(int who, struct rusage __user *ru); --asmlinkage long sys_umask(int mask); --asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, -- unsigned long arg4, unsigned long arg5); --asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache); --asmlinkage long sys_gettimeofday(struct __kernel_old_timeval __user *tv, -- struct timezone __user *tz); --asmlinkage long sys_settimeofday(struct __kernel_old_timeval __user *tv, -- struct timezone __user *tz); --asmlinkage long sys_adjtimex(struct __kernel_timex __user *txc_p); --asmlinkage long sys_adjtimex_time32(struct old_timex32 __user *txc_p); --asmlinkage long sys_getpid(void); --asmlinkage long sys_getppid(void); --asmlinkage long sys_getuid(void); --asmlinkage long sys_geteuid(void); --asmlinkage long sys_getgid(void); --asmlinkage long sys_getegid(void); --asmlinkage long sys_gettid(void); --asmlinkage long sys_sysinfo(struct sysinfo __user *info); --asmlinkage long sys_mq_open(const char __user *name, int oflag, umode_t mode, struct mq_attr __user *attr); --asmlinkage long sys_mq_unlink(const char __user *name); --asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec __user *abs_timeout); --asmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct __kernel_timespec __user *abs_timeout); --asmlinkage long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *notification); --asmlinkage long sys_mq_getsetattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat); --asmlinkage long sys_mq_timedreceive_time32(mqd_t mqdes, -- char __user *u_msg_ptr, -- unsigned int msg_len, unsigned int __user *u_msg_prio, -- const struct old_timespec32 __user *u_abs_timeout); --asmlinkage long sys_mq_timedsend_time32(mqd_t mqdes, -- const char __user *u_msg_ptr, -- unsigned int msg_len, unsigned int msg_prio, -- const struct old_timespec32 __user *u_abs_timeout); --asmlinkage long sys_msgget(key_t key, int msgflg); --asmlinkage long sys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); --asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); --asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, -- size_t msgsz, long msgtyp, int msgflg); --asmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp, -- size_t msgsz, int msgflg); --asmlinkage long sys_semget(key_t key, int nsems, int semflg); --asmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg); --asmlinkage long sys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); --asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops, -- unsigned nsops, -- const struct __kernel_timespec __user *timeout); --asmlinkage long sys_semtimedop_time32(int semid, struct sembuf __user *sops, -- unsigned nsops, -- const struct old_timespec32 __user *timeout); --asmlinkage long sys_semop(int semid, struct sembuf __user *sops, -- unsigned nsops); --asmlinkage long sys_shmget(key_t key, size_t size, int flag); --asmlinkage long sys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); --asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); --asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg); --asmlinkage long sys_shmdt(char __user *shmaddr); --asmlinkage long sys_socket(int, int, int); --asmlinkage long sys_socketpair(int, int, int, int __user *); --asmlinkage long sys_bind(int, struct sockaddr __user *, int); --asmlinkage long sys_listen(int, int); --asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); --asmlinkage long sys_connect(int, struct sockaddr __user *, int); --asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); --asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); --asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, -- struct sockaddr __user *, int); --asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, -- struct sockaddr __user *, int __user *); --asmlinkage long sys_setsockopt(int fd, int level, int optname, -- char __user *optval, int optlen); --asmlinkage long sys_getsockopt(int fd, int level, int optname, -- char __user *optval, int __user *optlen); --asmlinkage long sys_shutdown(int, int); --asmlinkage long sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags); --asmlinkage long sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags); --asmlinkage long sys_readahead(int fd, loff_t offset, size_t count); --asmlinkage long sys_brk(unsigned long brk); --asmlinkage long sys_munmap(unsigned long addr, size_t len); --asmlinkage long sys_mremap(unsigned long addr, -- unsigned long old_len, unsigned long new_len, -- unsigned long flags, unsigned long new_addr); --asmlinkage long sys_add_key(const char __user *_type, -- const char __user *_description, -- const void __user *_payload, -- size_t plen, -- key_serial_t destringid); --asmlinkage long sys_request_key(const char __user *_type, -- const char __user *_description, -- const char __user *_callout_info, -- key_serial_t destringid); --asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, -- unsigned long arg4, unsigned long arg5); --#ifdef CONFIG_CLONE_BACKWARDS --asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, unsigned long, -- int __user *); --#else --#ifdef CONFIG_CLONE_BACKWARDS3 --asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *, -- int __user *, unsigned long); --#else --asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, -- int __user *, unsigned long); --#endif --#endif -- --asmlinkage long sys_clone3(struct clone_args __user *uargs, size_t size); -- --asmlinkage long sys_execve(const char __user *filename, -- const char __user *const __user *argv, -- const char __user *const __user *envp); --asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); -- --/* CONFIG_MMU only */ --asmlinkage long sys_swapon(const char __user *specialfile, int swap_flags); --asmlinkage long sys_swapoff(const char __user *specialfile); --asmlinkage long sys_mprotect(unsigned long start, size_t len, -- unsigned long prot); --asmlinkage long sys_msync(unsigned long start, size_t len, int flags); --asmlinkage long sys_mlock(unsigned long start, size_t len); --asmlinkage long sys_munlock(unsigned long start, size_t len); --asmlinkage long sys_mlockall(int flags); --asmlinkage long sys_munlockall(void); --asmlinkage long sys_mincore(unsigned long start, size_t len, -- unsigned char __user * vec); --asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); --asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec, -- size_t vlen, int behavior, unsigned int flags); --asmlinkage long sys_process_mrelease(int pidfd, unsigned int flags); --asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, -- unsigned long prot, unsigned long pgoff, -- unsigned long flags); --asmlinkage long sys_mseal(unsigned long start, size_t len, unsigned long flags); --asmlinkage long sys_mbind(unsigned long start, unsigned long len, -- unsigned long mode, -- const unsigned long __user *nmask, -- unsigned long maxnode, -- unsigned flags); --asmlinkage long sys_get_mempolicy(int __user *policy, -- unsigned long __user *nmask, -- unsigned long maxnode, -- unsigned long addr, unsigned long flags); --asmlinkage long sys_set_mempolicy(int mode, const unsigned long __user *nmask, -- unsigned long maxnode); --asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, -- const unsigned long __user *from, -- const unsigned long __user *to); --asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, -- const void __user * __user *pages, -- const int __user *nodes, -- int __user *status, -- int flags); --asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, -- siginfo_t __user *uinfo); --asmlinkage long sys_perf_event_open( -- struct perf_event_attr __user *attr_uptr, -- pid_t pid, int cpu, int group_fd, unsigned long flags); --asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int); --asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg, -- unsigned int vlen, unsigned flags, -- struct __kernel_timespec __user *timeout); --asmlinkage long sys_recvmmsg_time32(int fd, struct mmsghdr __user *msg, -- unsigned int vlen, unsigned flags, -- struct old_timespec32 __user *timeout); --asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, -+ asmlinkage long sys_writev(unsigned long fd, -+ const struct iovec __user *vec, -+ unsigned long vlen); -+ asmlinkage long sys_pread64(unsigned int fd, char __user *buf, -+ size_t count, loff_t pos); -+ asmlinkage long sys_pwrite64(unsigned int fd, const char __user *buf, -+ size_t count, loff_t pos); -+ asmlinkage long sys_preadv(unsigned long fd, const struct iovec __user *vec, -+ unsigned long vlen, unsigned long pos_l, unsigned long pos_h); -+ asmlinkage long sys_pwritev(unsigned long fd, const struct iovec __user *vec, -+ unsigned long vlen, unsigned long pos_l, unsigned long pos_h); -+ asmlinkage long sys_sendfile64(int out_fd, int in_fd, -+ loff_t __user *offset, size_t count); -+ asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, -+ fd_set __user *, struct __kernel_timespec __user *, -+ void __user *); -+ asmlinkage long sys_pselect6_time32(int, fd_set __user *, fd_set __user *, -+ fd_set __user *, struct old_timespec32 __user *, -+ void __user *); -+ asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int, -+ struct __kernel_timespec __user *, const sigset_t __user *, -+ size_t); -+ asmlinkage long sys_ppoll_time32(struct pollfd __user *, unsigned int, -+ struct old_timespec32 __user *, const sigset_t __user *, -+ size_t); -+ asmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, int flags); -+ asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov, -+ unsigned long nr_segs, unsigned int flags); -+ asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, -+ int fd_out, loff_t __user *off_out, -+ size_t len, unsigned int flags); -+ asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags); -+ asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, -+ int bufsiz); -+ asmlinkage long sys_newfstatat(int dfd, const char __user *filename, -+ struct stat __user *statbuf, int flag); -+ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf); -+ #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) -+ asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf); -+ asmlinkage long sys_fstatat64(int dfd, const char __user *filename, -+ struct stat64 __user *statbuf, int flag); -+ #endif -+ asmlinkage long sys_sync(void); -+ asmlinkage long sys_fsync(unsigned int fd); -+ asmlinkage long sys_fdatasync(unsigned int fd); -+ asmlinkage long sys_sync_file_range2(int fd, unsigned int flags, -+ loff_t offset, loff_t nbytes); -+ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, -+ unsigned int flags); -+ asmlinkage long sys_timerfd_create(int clockid, int flags); -+ asmlinkage long sys_timerfd_settime(int ufd, int flags, -+ const struct __kernel_itimerspec __user *utmr, -+ struct __kernel_itimerspec __user *otmr); -+ asmlinkage long sys_timerfd_gettime(int ufd, struct __kernel_itimerspec __user *otmr); -+ asmlinkage long sys_timerfd_gettime32(int ufd, -+ struct old_itimerspec32 __user *otmr); -+ asmlinkage long sys_timerfd_settime32(int ufd, int flags, -+ const struct old_itimerspec32 __user *utmr, -+ struct old_itimerspec32 __user *otmr); -+ asmlinkage long sys_utimensat(int dfd, const char __user *filename, -+ struct __kernel_timespec __user *utimes, -+ int flags); -+ asmlinkage long sys_utimensat_time32(unsigned int dfd, -+ const char __user *filename, -+ struct old_timespec32 __user *t, int flags); -+ asmlinkage long sys_acct(const char __user *name); -+ asmlinkage long sys_capget(cap_user_header_t header, -+ cap_user_data_t dataptr); -+ asmlinkage long sys_capset(cap_user_header_t header, -+ const cap_user_data_t data); -+ asmlinkage long sys_personality(unsigned int personality); -+ asmlinkage long sys_exit(int error_code); -+ asmlinkage long sys_exit_group(int error_code); -+ asmlinkage long sys_waitid(int which, pid_t pid, -+ struct siginfo __user *infop, - int options, struct rusage __user *ru); --asmlinkage long sys_prlimit64(pid_t pid, unsigned int resource, -- const struct rlimit64 __user *new_rlim, -- struct rlimit64 __user *old_rlim); --asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags); --#if defined(CONFIG_ARCH_SPLIT_ARG64) --asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, -- unsigned int mask_1, unsigned int mask_2, -- int dfd, const char __user * pathname); --#else --asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, -- u64 mask, int fd, -- const char __user *pathname); --#endif --asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name, -- struct file_handle __user *handle, -- void __user *mnt_id, int flag); --asmlinkage long sys_open_by_handle_at(int mountdirfd, -- struct file_handle __user *handle, -- int flags); --asmlinkage long sys_clock_adjtime(clockid_t which_clock, -- struct __kernel_timex __user *tx); --asmlinkage long sys_clock_adjtime32(clockid_t which_clock, -- struct old_timex32 __user *tx); --asmlinkage long sys_syncfs(int fd); --asmlinkage long sys_setns(int fd, int nstype); --asmlinkage long sys_pidfd_open(pid_t pid, unsigned int flags); --asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, -- unsigned int vlen, unsigned flags); --asmlinkage long sys_process_vm_readv(pid_t pid, -- const struct iovec __user *lvec, -- unsigned long liovcnt, -- const struct iovec __user *rvec, -- unsigned long riovcnt, -- unsigned long flags); --asmlinkage long sys_process_vm_writev(pid_t pid, -- const struct iovec __user *lvec, -- unsigned long liovcnt, -- const struct iovec __user *rvec, -- unsigned long riovcnt, -- unsigned long flags); --asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, -- unsigned long idx1, unsigned long idx2); --asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); --asmlinkage long sys_sched_setattr(pid_t pid, -- struct sched_attr __user *attr, -- unsigned int flags); --asmlinkage long sys_sched_getattr(pid_t pid, -- struct sched_attr __user *attr, -- unsigned int size, -- unsigned int flags); --asmlinkage long sys_renameat2(int olddfd, const char __user *oldname, -- int newdfd, const char __user *newname, -- unsigned int flags); --asmlinkage long sys_seccomp(unsigned int op, unsigned int flags, -- void __user *uargs); --asmlinkage long sys_getrandom(char __user *buf, size_t count, -- unsigned int flags); --asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags); --asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int size); --asmlinkage long sys_execveat(int dfd, const char __user *filename, -- const char __user *const __user *argv, -- const char __user *const __user *envp, int flags); --asmlinkage long sys_userfaultfd(int flags); --asmlinkage long sys_membarrier(int cmd, unsigned int flags, int cpu_id); --asmlinkage long sys_mlock2(unsigned long start, size_t len, int flags); --asmlinkage long sys_copy_file_range(int fd_in, loff_t __user *off_in, -- int fd_out, loff_t __user *off_out, -- size_t len, unsigned int flags); --asmlinkage long sys_preadv2(unsigned long fd, const struct iovec __user *vec, -- unsigned long vlen, unsigned long pos_l, unsigned long pos_h, -- rwf_t flags); --asmlinkage long sys_pwritev2(unsigned long fd, const struct iovec __user *vec, -- unsigned long vlen, unsigned long pos_l, unsigned long pos_h, -- rwf_t flags); --asmlinkage long sys_pkey_mprotect(unsigned long start, size_t len, -- unsigned long prot, int pkey); --asmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val); --asmlinkage long sys_pkey_free(int pkey); --asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, -- unsigned mask, struct statx __user *buffer); --asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len, -- int flags, uint32_t sig); --asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags); --asmlinkage long sys_move_mount(int from_dfd, const char __user *from_path, -- int to_dfd, const char __user *to_path, -- unsigned int ms_flags); --asmlinkage long sys_mount_setattr(int dfd, const char __user *path, -- unsigned int flags, -- struct mount_attr __user *uattr, size_t usize); --asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags); --asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, -- const void __user *value, int aux); --asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags); --asmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags); --asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, -- siginfo_t __user *info, -- unsigned int flags); --asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags); --asmlinkage long sys_landlock_create_ruleset(const struct landlock_ruleset_attr __user *attr, -- size_t size, __u32 flags); --asmlinkage long sys_landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type, -- const void __user *rule_attr, __u32 flags); --asmlinkage long sys_landlock_restrict_self(int ruleset_fd, __u32 flags); --asmlinkage long sys_memfd_secret(unsigned int flags); --asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long len, -- unsigned long home_node, -- unsigned long flags); --asmlinkage long sys_cachestat(unsigned int fd, -- struct cachestat_range __user *cstat_range, -- struct cachestat __user *cstat, unsigned int flags); --asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); --asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, -- u32 __user *size, u32 flags); --asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, -- u32 size, u32 flags); --asmlinkage long sys_lsm_list_modules(u64 __user *ids, u32 __user *size, u32 flags); -- --/* -- * Architecture-specific system calls -- */ -- --/* x86 */ --asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on); -- --asmlinkage long sys_uretprobe(void); -- --/* pciconfig: alpha, arm, arm64, ia64, sparc */ --asmlinkage long sys_pciconfig_read(unsigned long bus, unsigned long dfn, -- unsigned long off, unsigned long len, -- void __user *buf); --asmlinkage long sys_pciconfig_write(unsigned long bus, unsigned long dfn, -- unsigned long off, unsigned long len, -- void __user *buf); --asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn); -- --/* powerpc */ --asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, -- __u32 __user *ustatus); --asmlinkage long sys_spu_create(const char __user *name, -- unsigned int flags, umode_t mode, int fd); -- -- --/* -- * Deprecated system calls which are still defined in -- * include/uapi/asm-generic/unistd.h and wanted by >= 1 arch -- */ -- --/* __ARCH_WANT_SYSCALL_NO_AT */ --asmlinkage long sys_open(const char __user *filename, -- int flags, umode_t mode); --asmlinkage long sys_link(const char __user *oldname, -- const char __user *newname); --asmlinkage long sys_unlink(const char __user *pathname); --asmlinkage long sys_mknod(const char __user *filename, umode_t mode, -- unsigned dev); --asmlinkage long sys_chmod(const char __user *filename, umode_t mode); --asmlinkage long sys_chown(const char __user *filename, -- uid_t user, gid_t group); --asmlinkage long sys_mkdir(const char __user *pathname, umode_t mode); --asmlinkage long sys_rmdir(const char __user *pathname); --asmlinkage long sys_lchown(const char __user *filename, -- uid_t user, gid_t group); --asmlinkage long sys_access(const char __user *filename, int mode); --asmlinkage long sys_rename(const char __user *oldname, -- const char __user *newname); --asmlinkage long sys_symlink(const char __user *old, const char __user *new); --#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) --asmlinkage long sys_stat64(const char __user *filename, -- struct stat64 __user *statbuf); --asmlinkage long sys_lstat64(const char __user *filename, -- struct stat64 __user *statbuf); --#endif -- --/* __ARCH_WANT_SYSCALL_NO_FLAGS */ --asmlinkage long sys_pipe(int __user *fildes); --asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd); --asmlinkage long sys_epoll_create(int size); --asmlinkage long sys_inotify_init(void); --asmlinkage long sys_eventfd(unsigned int count); --asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask); -- --/* __ARCH_WANT_SYSCALL_OFF_T */ --asmlinkage long sys_sendfile(int out_fd, int in_fd, -- off_t __user *offset, size_t count); --asmlinkage long sys_newstat(const char __user *filename, -- struct stat __user *statbuf); --asmlinkage long sys_newlstat(const char __user *filename, -- struct stat __user *statbuf); --asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice); -- --/* __ARCH_WANT_SYSCALL_DEPRECATED */ --asmlinkage long sys_alarm(unsigned int seconds); --asmlinkage long sys_getpgrp(void); --asmlinkage long sys_pause(void); --asmlinkage long sys_time(__kernel_old_time_t __user *tloc); --asmlinkage long sys_time32(old_time32_t __user *tloc); --#ifdef __ARCH_WANT_SYS_UTIME --asmlinkage long sys_utime(char __user *filename, -- struct utimbuf __user *times); --asmlinkage long sys_utimes(char __user *filename, -- struct __kernel_old_timeval __user *utimes); --asmlinkage long sys_futimesat(int dfd, const char __user *filename, -- struct __kernel_old_timeval __user *utimes); --#endif --asmlinkage long sys_futimesat_time32(unsigned int dfd, -- const char __user *filename, -- struct old_timeval32 __user *t); --asmlinkage long sys_utime32(const char __user *filename, -- struct old_utimbuf32 __user *t); --asmlinkage long sys_utimes_time32(const char __user *filename, -- struct old_timeval32 __user *t); --asmlinkage long sys_creat(const char __user *pathname, umode_t mode); --asmlinkage long sys_getdents(unsigned int fd, -- struct linux_dirent __user *dirent, -- unsigned int count); --asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, -- fd_set __user *exp, struct __kernel_old_timeval __user *tvp); --asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, -- int timeout); --asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, -- int maxevents, int timeout); --asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf); --asmlinkage long sys_vfork(void); --asmlinkage long sys_recv(int, void __user *, size_t, unsigned); --asmlinkage long sys_send(int, void __user *, size_t, unsigned); --asmlinkage long sys_oldumount(char __user *name); --asmlinkage long sys_uselib(const char __user *library); --asmlinkage long sys_sysfs(int option, -- unsigned long arg1, unsigned long arg2); --asmlinkage long sys_fork(void); -- --/* obsolete */ --asmlinkage long sys_stime(__kernel_old_time_t __user *tptr); --asmlinkage long sys_stime32(old_time32_t __user *tptr); -- --/* obsolete */ --asmlinkage long sys_sigpending(old_sigset_t __user *uset); --asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set, -- old_sigset_t __user *oset); --#ifdef CONFIG_OLD_SIGSUSPEND --asmlinkage long sys_sigsuspend(old_sigset_t mask); --#endif -- --#ifdef CONFIG_OLD_SIGSUSPEND3 --asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask); --#endif -- --#ifdef CONFIG_OLD_SIGACTION --asmlinkage long sys_sigaction(int, const struct old_sigaction __user *, -- struct old_sigaction __user *); --#endif --asmlinkage long sys_sgetmask(void); --asmlinkage long sys_ssetmask(int newmask); --asmlinkage long sys_signal(int sig, __sighandler_t handler); -- --/* obsolete */ --asmlinkage long sys_nice(int increment); -- --/* obsolete */ --asmlinkage long sys_kexec_file_load(int kernel_fd, int initrd_fd, -- unsigned long cmdline_len, -- const char __user *cmdline_ptr, -- unsigned long flags); -- --/* obsolete */ --asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options); -- --/* obsolete */ --#ifdef CONFIG_HAVE_UID16 --asmlinkage long sys_chown16(const char __user *filename, -- old_uid_t user, old_gid_t group); --asmlinkage long sys_lchown16(const char __user *filename, -- old_uid_t user, old_gid_t group); --asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group); --asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid); --asmlinkage long sys_setgid16(old_gid_t gid); --asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid); --asmlinkage long sys_setuid16(old_uid_t uid); --asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid); --asmlinkage long sys_getresuid16(old_uid_t __user *ruid, -- old_uid_t __user *euid, old_uid_t __user *suid); --asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid); --asmlinkage long sys_getresgid16(old_gid_t __user *rgid, -- old_gid_t __user *egid, old_gid_t __user *sgid); --asmlinkage long sys_setfsuid16(old_uid_t uid); --asmlinkage long sys_setfsgid16(old_gid_t gid); --asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist); --asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist); --asmlinkage long sys_getuid16(void); --asmlinkage long sys_geteuid16(void); --asmlinkage long sys_getgid16(void); --asmlinkage long sys_getegid16(void); --#endif -- --/* obsolete */ --asmlinkage long sys_socketcall(int call, unsigned long __user *args); -- --/* obsolete */ --asmlinkage long sys_stat(const char __user *filename, -- struct __old_kernel_stat __user *statbuf); --asmlinkage long sys_lstat(const char __user *filename, -- struct __old_kernel_stat __user *statbuf); --asmlinkage long sys_fstat(unsigned int fd, -- struct __old_kernel_stat __user *statbuf); --asmlinkage long sys_readlink(const char __user *path, -- char __user *buf, int bufsiz); -- --/* obsolete */ --asmlinkage long sys_old_select(struct sel_arg_struct __user *arg); -- --/* obsolete */ --asmlinkage long sys_old_readdir(unsigned int, struct old_linux_dirent __user *, unsigned int); -- --/* obsolete */ --asmlinkage long sys_gethostname(char __user *name, int len); --asmlinkage long sys_uname(struct old_utsname __user *); --asmlinkage long sys_olduname(struct oldold_utsname __user *); --#ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT --asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim); --#endif -- --/* obsolete */ --asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, -- unsigned long third, void __user *ptr, long fifth); -- --/* obsolete */ --asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, -- unsigned long prot, unsigned long flags, -- unsigned long fd, unsigned long pgoff); --asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg); -- -- --/* -- * Not a real system call, but a placeholder for syscalls which are -- * not implemented -- see kernel/sys_ni.c -- */ --asmlinkage long sys_ni_syscall(void); -- --#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ -- --asmlinkage long sys_ni_posix_timers(void); -- --/* -- * Kernel code should not call syscalls (i.e., sys_xyzyyz()) directly. -- * Instead, use one of the functions which work equivalently, such as -- * the ksys_xyzyyz() functions prototyped below. -- */ --ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); --int ksys_fchown(unsigned int fd, uid_t user, gid_t group); --ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count); --void ksys_sync(void); --int ksys_unshare(unsigned long unshare_flags); --int ksys_setsid(void); --int ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes, -- unsigned int flags); --ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count, -- loff_t pos); --ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf, -- size_t count, loff_t pos); --int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len); --#ifdef CONFIG_ADVISE_SYSCALLS --int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); --#else --static inline int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, -- int advice) --{ -- return -EINVAL; --} --#endif --unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, -- unsigned long prot, unsigned long flags, -- unsigned long fd, unsigned long pgoff); --ssize_t ksys_readahead(int fd, loff_t offset, size_t count); --int ksys_ipc(unsigned int call, int first, unsigned long second, -- unsigned long third, void __user * ptr, long fifth); --int compat_ksys_ipc(u32 call, int first, int second, -- u32 third, u32 ptr, u32 fifth); -- --/* -- * The following kernel syscall equivalents are just wrappers to fs-internal -- * functions. Therefore, provide stubs to be inlined at the callsites. -- */ --extern int do_fchownat(int dfd, const char __user *filename, uid_t user, -- gid_t group, int flag); -- --static inline long ksys_chown(const char __user *filename, uid_t user, -- gid_t group) --{ -- return do_fchownat(AT_FDCWD, filename, user, group, 0); --} -- --static inline long ksys_lchown(const char __user *filename, uid_t user, -- gid_t group) --{ -- return do_fchownat(AT_FDCWD, filename, user, group, -- AT_SYMLINK_NOFOLLOW); --} -- --extern long do_sys_ftruncate(unsigned int fd, loff_t length, int small); -- --static inline long ksys_ftruncate(unsigned int fd, loff_t length) --{ -- return do_sys_ftruncate(fd, length, 1); --} -- --extern long do_sys_truncate(const char __user *pathname, loff_t length); -- --static inline long ksys_truncate(const char __user *pathname, loff_t length) --{ -- return do_sys_truncate(pathname, length); --} -- --static inline unsigned int ksys_personality(unsigned int personality) --{ -- unsigned int old = current->personality; -- -- if (personality != 0xffffffff) -- set_personality(personality); -- -- return old; --} -- --/* for __ARCH_WANT_SYS_IPC */ --long ksys_semtimedop(int semid, struct sembuf __user *tsops, -- unsigned int nsops, -- const struct __kernel_timespec __user *timeout); --long ksys_semget(key_t key, int nsems, int semflg); --long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); --long ksys_msgget(key_t key, int msgflg); --long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); --long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, -- long msgtyp, int msgflg); --long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, -- int msgflg); --long ksys_shmget(key_t key, size_t size, int shmflg); --long ksys_shmdt(char __user *shmaddr); --long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); --long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, -- unsigned int nsops, -- const struct old_timespec32 __user *timeout); --long __do_semtimedop(int semid, struct sembuf *tsems, unsigned int nsops, -- const struct timespec64 *timeout, -- struct ipc_namespace *ns); -- --int __sys_getsockopt(int fd, int level, int optname, char __user *optval, -- int __user *optlen); --int __sys_setsockopt(int fd, int level, int optname, char __user *optval, -- int optlen); --#endif -+ asmlinkage long sys_set_tid_address(int __user *tidptr); -+ asmlinkage long sys_unshare(unsigned long unshare_flags); -+ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, -+ const struct __kernel_timespec __user *utime, -+ u32 __user *uaddr2, u32 val3); -+ asmlinkage long sys_futex_time32(u32 __user *uaddr, int op, u32 val, -+ const struct old_timespec32 __user *utime, -+ u32 __user *uaddr2, u32 val3); -+ asmlinkage long sys_get_robust_list(int pid, -+ struct robust_list_head __user * __user *head_ptr, -+ size_t __user *len_ptr); -+ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, -+ size_t len); -+ -+ asmlinkage long sys_futex_waitv(struct futex_waitv __user *waiters, -+ unsigned int nr_futexes, unsigned int flags, -+ struct __kernel_timespec __user *timeout, clockid_t clockid); -+ -+ asmlinkage long sys_futex_wake(void __user *uaddr, unsigned long mask, int nr, unsigned int flags); -+ -+ asmlinkage long sys_futex_wait(void __user *uaddr, unsigned long val, unsigned long mask, -+ unsigned int flags, struct __kernel_timespec __user *timespec, -+ clockid_t clockid); -+ -+ asmlinkage long sys_futex_requeue(struct futex_waitv __user *waiters, -+ unsigned int flags, int nr_wake, int nr_requeue); -+ -+ asmlinkage long sys_nanosleep(struct __kernel_timespec __user *rqtp, -+ struct __kernel_timespec __user *rmtp); -+ asmlinkage long sys_nanosleep_time32(struct old_timespec32 __user *rqtp, -+ struct old_timespec32 __user *rmtp); -+ asmlinkage long sys_getitimer(int which, struct __kernel_old_itimerval __user *value); -+ asmlinkage long sys_setitimer(int which, -+ struct __kernel_old_itimerval __user *value, -+ struct __kernel_old_itimerval __user *ovalue); -+ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, -+ struct kexec_segment __user *segments, -+ unsigned long flags); -+ asmlinkage long sys_init_module(void __user *umod, unsigned long len, -+ const char __user *uargs); -+ asmlinkage long sys_delete_module(const char __user *name_user, -+ unsigned int flags); -+ asmlinkage long sys_timer_create(clockid_t which_clock, -+ struct sigevent __user *timer_event_spec, -+ timer_t __user * created_timer_id); -+ asmlinkage long sys_timer_gettime(timer_t timer_id, -+ struct __kernel_itimerspec __user *setting); -+ asmlinkage long sys_timer_getoverrun(timer_t timer_id); -+ asmlinkage long sys_timer_settime(timer_t timer_id, int flags, -+ const struct __kernel_itimerspec __user *new_setting, -+ struct __kernel_itimerspec __user *old_setting); -+ asmlinkage long sys_timer_delete(timer_t timer_id); -+ asmlinkage long sys_clock_settime(clockid_t which_clock, -+ const struct __kernel_timespec __user *tp); -+ asmlinkage long sys_clock_gettime(clockid_t which_clock, -+ struct __kernel_timespec __user *tp); -+ asmlinkage long sys_clock_getres(clockid_t which_clock, -+ struct __kernel_timespec __user *tp); -+ asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags, -+ const struct __kernel_timespec __user *rqtp, -+ struct __kernel_timespec __user *rmtp); -+ asmlinkage long sys_timer_gettime32(timer_t timer_id, -+ struct old_itimerspec32 __user *setting); -+ asmlinkage long sys_timer_settime32(timer_t timer_id, int flags, -+ struct old_itimerspec32 __user *new, -+ struct old_itimerspec32 __user *old); -+ asmlinkage long sys_clock_settime32(clockid_t which_clock, -+ struct old_timespec32 __user *tp); -+ asmlinkage long sys_clock_gettime32(clockid_t which_clock, -+ struct old_timespec32 __user *tp); -+ asmlinkage long sys_clock_getres_time32(clockid_t which_clock, -+ struct old_timespec32 __user *tp); -+ asmlinkage long sys_clock_nanosleep_time32(clockid_t which_clock, int flags, -+ struct old_timespec32 __user *rqtp, -+ struct old_timespec32 __user *rmtp); -+ asmlinkage long sys_syslog(int type, char __user *buf, int len); -+ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, -+ unsigned long data); -+ asmlinkage long sys_sched_setparam(pid_t pid, -+ struct sched_param __user *param); -+ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, -+ struct sched_param __user *param); -+ asmlinkage long sys_sched_getscheduler(pid_t pid); -+ asmlinkage long sys_sched_getparam(pid_t pid, -+ struct sched_param __user *param); -+ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, -+ unsigned long __user *user_mask_ptr); -+ asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, -+ unsigned long __user *user_mask_ptr); -+ asmlinkage long sys_sched_yield(void); -+ asmlinkage long sys_sched_get_priority_max(int policy); -+ asmlinkage long sys_sched_get_priority_min(int policy); -+ asmlinkage long sys_sched_rr_get_interval(pid_t pid, -+ struct __kernel_timespec __user *interval); -+ asmlinkage long sys_sched_rr_get_interval_time32(pid_t pid, -+ struct old_timespec32 __user *interval); -+ asmlinkage long sys_restart_syscall(void); -+ asmlinkage long sys_kill(pid_t pid, int sig); -+ asmlinkage long sys_tkill(pid_t pid, int sig); -+ asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig); -+ asmlinkage long sys_sigaltstack(const struct sigaltstack __user *uss, -+ struct sigaltstack __user *uoss); -+ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize); -+ #ifndef CONFIG_ODD_RT_SIGACTION -+ asmlinkage long sys_rt_sigaction(int, -+ const struct sigaction __user *, -+ struct sigaction __user *, -+ size_t); -+ #endif -+ asmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set, -+ sigset_t __user *oset, size_t sigsetsize); -+ asmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize); -+ asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese, -+ siginfo_t __user *uinfo, -+ const struct __kernel_timespec __user *uts, -+ size_t sigsetsize); -+ asmlinkage long sys_rt_sigtimedwait_time32(const sigset_t __user *uthese, -+ siginfo_t __user *uinfo, -+ const struct old_timespec32 __user *uts, -+ size_t sigsetsize); -+ asmlinkage long sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo); -+ asmlinkage long sys_setpriority(int which, int who, int niceval); -+ asmlinkage long sys_getpriority(int which, int who); -+ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, -+ void __user *arg); -+ asmlinkage long sys_setregid(gid_t rgid, gid_t egid); -+ asmlinkage long sys_setgid(gid_t gid); -+ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid); -+ asmlinkage long sys_setuid(uid_t uid); -+ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); -+ asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid); -+ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); -+ asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid); -+ asmlinkage long sys_setfsuid(uid_t uid); -+ asmlinkage long sys_setfsgid(gid_t gid); -+ asmlinkage long sys_times(struct tms __user *tbuf); -+ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid); -+ asmlinkage long sys_getpgid(pid_t pid); -+ asmlinkage long sys_getsid(pid_t pid); -+ asmlinkage long sys_setsid(void); -+ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist); -+ asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist); -+ asmlinkage long sys_newuname(struct new_utsname __user *name); -+ asmlinkage long sys_sethostname(char __user *name, int len); -+ asmlinkage long sys_setdomainname(char __user *name, int len); -+ asmlinkage long sys_getrlimit(unsigned int resource, -+ struct rlimit __user *rlim); -+ asmlinkage long sys_setrlimit(unsigned int resource, -+ struct rlimit __user *rlim); -+ asmlinkage long sys_getrusage(int who, struct rusage __user *ru); -+ asmlinkage long sys_umask(int mask); -+ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, -+ unsigned long arg4, unsigned long arg5); -+ asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache); -+ asmlinkage long sys_gettimeofday(struct __kernel_old_timeval __user *tv, -+ struct timezone __user *tz); -+ asmlinkage long sys_settimeofday(struct __kernel_old_timeval __user *tv, -+ struct timezone __user *tz); -+ asmlinkage long sys_adjtimex(struct __kernel_timex __user *txc_p); -+ asmlinkage long sys_adjtimex_time32(struct old_timex32 __user *txc_p); -+ asmlinkage long sys_getpid(void); -+ asmlinkage long sys_getppid(void); -+ asmlinkage long sys_getuid(void); -+ asmlinkage long sys_geteuid(void); -+ asmlinkage long sys_getgid(void); -+ asmlinkage long sys_getegid(void); -+ asmlinkage long sys_gettid(void); -+ asmlinkage long sys_sysinfo(struct sysinfo __user *info); -+ asmlinkage long sys_mq_open(const char __user *name, int oflag, umode_t mode, struct mq_attr __user *attr); -+ asmlinkage long sys_mq_unlink(const char __user *name); -+ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec __user *abs_timeout); -+ asmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct __kernel_timespec __user *abs_timeout); -+ asmlinkage long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *notification); -+ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat); -+ asmlinkage long sys_mq_timedreceive_time32(mqd_t mqdes, -+ char __user *u_msg_ptr, -+ unsigned int msg_len, unsigned int __user *u_msg_prio, -+ const struct old_timespec32 __user *u_abs_timeout); -+ asmlinkage long sys_mq_timedsend_time32(mqd_t mqdes, -+ const char __user *u_msg_ptr, -+ unsigned int msg_len, unsigned int msg_prio, -+ const struct old_timespec32 __user *u_abs_timeout); -+ asmlinkage long sys_msgget(key_t key, int msgflg); -+ asmlinkage long sys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); -+ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); -+ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, -+ size_t msgsz, long msgtyp, int msgflg); -+ asmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp, -+ size_t msgsz, int msgflg); -+ asmlinkage long sys_semget(key_t key, int nsems, int semflg); -+ asmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg); -+ asmlinkage long sys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); -+ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops, -+ unsigned nsops, -+ const struct __kernel_timespec __user *timeout); -+ asmlinkage long sys_semtimedop_time32(int semid, struct sembuf __user *sops, -+ unsigned nsops, -+ const struct old_timespec32 __user *timeout); -+ asmlinkage long sys_semop(int semid, struct sembuf __user *sops, -+ unsigned nsops); -+ asmlinkage long sys_shmget(key_t key, size_t size, int flag); -+ asmlinkage long sys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); -+ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); -+ asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg); -+ asmlinkage long sys_shmdt(char __user *shmaddr); -+ asmlinkage long sys_socket(int, int, int); -+ asmlinkage long sys_socketpair(int, int, int, int __user *); -+ asmlinkage long sys_bind(int, struct sockaddr __user *, int); -+ asmlinkage long sys_listen(int, int); -+ asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); -+ asmlinkage long sys_connect(int, struct sockaddr __user *, int); -+ asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); -+ asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); -+ asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, -+ struct sockaddr __user *, int); -+ asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, -+ struct sockaddr __user *, int __user *); -+ asmlinkage long sys_setsockopt(int fd, int level, int optname, -+ char __user *optval, int optlen); -+ asmlinkage long sys_getsockopt(int fd, int level, int optname, -+ char __user *optval, int __user *optlen); -+ asmlinkage long sys_shutdown(int, int); -+ asmlinkage long sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags); -+ asmlinkage long sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags); -+ asmlinkage long sys_readahead(int fd, loff_t offset, size_t count); -+ asmlinkage long sys_brk(unsigned long brk); -+ asmlinkage long sys_munmap(unsigned long addr, size_t len); -+ asmlinkage long sys_mremap(unsigned long addr, -+ unsigned long old_len, unsigned long new_len, -+ unsigned long flags, unsigned long new_addr); -+ asmlinkage long sys_add_key(const char __user *_type, -+ const char __user *_description, -+ const void __user *_payload, -+ size_t plen, -+ key_serial_t destringid); -+ asmlinkage long sys_request_key(const char __user *_type, -+ const char __user *_description, -+ const char __user *_callout_info, -+ key_serial_t destringid); -+ asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, -+ unsigned long arg4, unsigned long arg5); -+ #ifdef CONFIG_CLONE_BACKWARDS -+ asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, unsigned long, -+ int __user *); -+ #else -+ #ifdef CONFIG_CLONE_BACKWARDS3 -+ asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *, -+ int __user *, unsigned long); -+ #else -+ asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, -+ int __user *, unsigned long); -+ #endif -+ #endif -+ -+ asmlinkage long sys_clone3(struct clone_args __user *uargs, size_t size); -+ -+ asmlinkage long sys_execve(const char __user *filename, -+ const char __user *const __user *argv, -+ const char __user *const __user *envp); -+ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); -+ -+ /* CONFIG_MMU only */ -+ asmlinkage long sys_swapon(const char __user *specialfile, int swap_flags); -+ asmlinkage long sys_swapoff(const char __user *specialfile); -+ asmlinkage long sys_mprotect(unsigned long start, size_t len, -+ unsigned long prot); -+ asmlinkage long sys_msync(unsigned long start, size_t len, int flags); -+ asmlinkage long sys_mlock(unsigned long start, size_t len); -+ asmlinkage long sys_munlock(unsigned long start, size_t len); -+ asmlinkage long sys_mlockall(int flags); -+ asmlinkage long sys_munlockall(void); -+ asmlinkage long sys_mincore(unsigned long start, size_t len, -+ unsigned char __user * vec); -+ asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); -+ asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec, -+ size_t vlen, int behavior, unsigned int flags); -+ asmlinkage long sys_process_mrelease(int pidfd, unsigned int flags); -+ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, -+ unsigned long prot, unsigned long pgoff, -+ unsigned long flags); -+ asmlinkage long sys_mseal(unsigned long start, size_t len, unsigned long flags); -+ asmlinkage long sys_mbind(unsigned long start, unsigned long len, -+ unsigned long mode, -+ const unsigned long __user *nmask, -+ unsigned long maxnode, -+ unsigned flags); -+ asmlinkage long sys_get_mempolicy(int __user *policy, -+ unsigned long __user *nmask, -+ unsigned long maxnode, -+ unsigned long addr, unsigned long flags); -+ asmlinkage long sys_set_mempolicy(int mode, const unsigned long __user *nmask, -+ unsigned long maxnode); -+ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, -+ const unsigned long __user *from, -+ const unsigned long __user *to); -+ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, -+ const void __user * __user *pages, -+ const int __user *nodes, -+ int __user *status, -+ int flags); -+ asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, -+ siginfo_t __user *uinfo); -+ asmlinkage long sys_perf_event_open( -+ struct perf_event_attr __user *attr_uptr, -+ pid_t pid, int cpu, int group_fd, unsigned long flags); -+ asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int); -+ asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg, -+ unsigned int vlen, unsigned flags, -+ struct __kernel_timespec __user *timeout); -+ asmlinkage long sys_recvmmsg_time32(int fd, struct mmsghdr __user *msg, -+ unsigned int vlen, unsigned flags, -+ struct old_timespec32 __user *timeout); -+ asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, -+ int options, struct rusage __user *ru); -+ asmlinkage long sys_prlimit64(pid_t pid, unsigned int resource, -+ const struct rlimit64 __user *new_rlim, -+ struct rlimit64 __user *old_rlim); -+ asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags); -+ #if defined(CONFIG_ARCH_SPLIT_ARG64) -+ asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, -+ unsigned int mask_1, unsigned int mask_2, -+ int dfd, const char __user * pathname); -+ #else -+ asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, -+ u64 mask, int fd, -+ const char __user *pathname); -+ #endif -+ asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name, -+ struct file_handle __user *handle, -+ void __user *mnt_id, int flag); -+ asmlinkage long sys_open_by_handle_at(int mountdirfd, -+ struct file_handle __user *handle, -+ int flags); -+ asmlinkage long sys_clock_adjtime(clockid_t which_clock, -+ struct __kernel_timex __user *tx); -+ asmlinkage long sys_clock_adjtime32(clockid_t which_clock, -+ struct old_timex32 __user *tx); -+ asmlinkage long sys_syncfs(int fd); -+ asmlinkage long sys_setns(int fd, int nstype); -+ asmlinkage long sys_pidfd_open(pid_t pid, unsigned int flags); -+ asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, -+ unsigned int vlen, unsigned flags); -+ asmlinkage long sys_process_vm_readv(pid_t pid, -+ const struct iovec __user *lvec, -+ unsigned long liovcnt, -+ const struct iovec __user *rvec, -+ unsigned long riovcnt, -+ unsigned long flags); -+ asmlinkage long sys_process_vm_writev(pid_t pid, -+ const struct iovec __user *lvec, -+ unsigned long liovcnt, -+ const struct iovec __user *rvec, -+ unsigned long riovcnt, -+ unsigned long flags); -+ asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, -+ unsigned long idx1, unsigned long idx2); -+ asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); -+ asmlinkage long sys_sched_setattr(pid_t pid, -+ struct sched_attr __user *attr, -+ unsigned int flags); -+ asmlinkage long sys_sched_getattr(pid_t pid, -+ struct sched_attr __user *attr, -+ unsigned int size, -+ unsigned int flags); -+ asmlinkage long sys_renameat2(int olddfd, const char __user *oldname, -+ int newdfd, const char __user *newname, -+ unsigned int flags); -+ asmlinkage long sys_seccomp(unsigned int op, unsigned int flags, -+ void __user *uargs); -+ asmlinkage long sys_getrandom(char __user *buf, size_t count, -+ unsigned int flags); -+ asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags); -+ asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int size); -+ asmlinkage long sys_execveat(int dfd, const char __user *filename, -+ const char __user *const __user *argv, -+ const char __user *const __user *envp, int flags); -+ asmlinkage long sys_userfaultfd(int flags); -+ asmlinkage long sys_membarrier(int cmd, unsigned int flags, int cpu_id); -+ asmlinkage long sys_mlock2(unsigned long start, size_t len, int flags); -+ asmlinkage long sys_copy_file_range(int fd_in, loff_t __user *off_in, -+ int fd_out, loff_t __user *off_out, -+ size_t len, unsigned int flags); -+ asmlinkage long sys_preadv2(unsigned long fd, const struct iovec __user *vec, -+ unsigned long vlen, unsigned long pos_l, unsigned long pos_h, -+ rwf_t flags); -+ asmlinkage long sys_pwritev2(unsigned long fd, const struct iovec __user *vec, -+ unsigned long vlen, unsigned long pos_l, unsigned long pos_h, -+ rwf_t flags); -+ asmlinkage long sys_pkey_mprotect(unsigned long start, size_t len, -+ unsigned long prot, int pkey); -+ asmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val); -+ asmlinkage long sys_pkey_free(int pkey); -+ asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, -+ unsigned mask, struct statx __user *buffer); -+ asmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len, -+ int flags, uint32_t sig); -+ asmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags); -+ asmlinkage long sys_move_mount(int from_dfd, const char __user *from_path, -+ int to_dfd, const char __user *to_path, -+ unsigned int ms_flags); -+ asmlinkage long sys_mount_setattr(int dfd, const char __user *path, -+ unsigned int flags, -+ struct mount_attr __user *uattr, size_t usize); -+ asmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags); -+ asmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, -+ const void __user *value, int aux); -+ asmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags); -+ asmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags); -+ asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, -+ siginfo_t __user *info, -+ unsigned int flags); -+ asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags); -+ asmlinkage long sys_landlock_create_ruleset(const struct landlock_ruleset_attr __user *attr, -+ size_t size, __u32 flags); -+ asmlinkage long sys_landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type, -+ const void __user *rule_attr, __u32 flags); -+ asmlinkage long sys_landlock_restrict_self(int ruleset_fd, __u32 flags); -+ asmlinkage long sys_memfd_secret(unsigned int flags); -+ asmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long len, -+ unsigned long home_node, -+ unsigned long flags); -+ asmlinkage long sys_cachestat(unsigned int fd, -+ struct cachestat_range __user *cstat_range, -+ struct cachestat __user *cstat, unsigned int flags); -+ asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); -+ asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, -+ u32 __user *size, u32 flags); -+ asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, -+ u32 size, u32 flags); -+ asmlinkage long sys_lsm_list_modules(u64 __user *ids, u32 __user *size, u32 flags); -+ -+ /* -+ * Architecture-specific system calls -+ */ -+ -+ /* x86 */ -+ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on); -+ -+ asmlinkage long sys_uretprobe(void); -+ -+ /* pciconfig: alpha, arm, arm64, ia64, sparc */ -+ asmlinkage long sys_pciconfig_read(unsigned long bus, unsigned long dfn, -+ unsigned long off, unsigned long len, -+ void __user *buf); -+ asmlinkage long sys_pciconfig_write(unsigned long bus, unsigned long dfn, -+ unsigned long off, unsigned long len, -+ void __user *buf); -+ asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn); -+ -+ /* powerpc */ -+ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, -+ __u32 __user *ustatus); -+ asmlinkage long sys_spu_create(const char __user *name, -+ unsigned int flags, umode_t mode, int fd); -+ -+ -+ /* -+ * Deprecated system calls which are still defined in -+ * include/uapi/asm-generic/unistd.h and wanted by >= 1 arch -+ */ -+ -+ /* __ARCH_WANT_SYSCALL_NO_AT */ -+ asmlinkage long sys_open(const char __user *filename, -+ int flags, umode_t mode); -+ asmlinkage long sys_link(const char __user *oldname, -+ const char __user *newname); -+ asmlinkage long sys_unlink(const char __user *pathname); -+ asmlinkage long sys_mknod(const char __user *filename, umode_t mode, -+ unsigned dev); -+ asmlinkage long sys_chmod(const char __user *filename, umode_t mode); -+ asmlinkage long sys_chown(const char __user *filename, -+ uid_t user, gid_t group); -+ asmlinkage long sys_mkdir(const char __user *pathname, umode_t mode); -+ asmlinkage long sys_rmdir(const char __user *pathname); -+ asmlinkage long sys_lchown(const char __user *filename, -+ uid_t user, gid_t group); -+ asmlinkage long sys_access(const char __user *filename, int mode); -+ asmlinkage long sys_rename(const char __user *oldname, -+ const char __user *newname); -+ asmlinkage long sys_symlink(const char __user *old, const char __user *new); -+ #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) -+ asmlinkage long sys_stat64(const char __user *filename, -+ struct stat64 __user *statbuf); -+ asmlinkage long sys_lstat64(const char __user *filename, -+ struct stat64 __user *statbuf); -+ #endif -+ -+ /* __ARCH_WANT_SYSCALL_NO_FLAGS */ -+ asmlinkage long sys_pipe(int __user *fildes); -+ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd); -+ asmlinkage long sys_epoll_create(int size); -+ asmlinkage long sys_inotify_init(void); -+ asmlinkage long sys_eventfd(unsigned int count); -+ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask); -+ -+ /* __ARCH_WANT_SYSCALL_OFF_T */ -+ asmlinkage long sys_sendfile(int out_fd, int in_fd, -+ off_t __user *offset, size_t count); -+ asmlinkage long sys_newstat(const char __user *filename, -+ struct stat __user *statbuf); -+ asmlinkage long sys_newlstat(const char __user *filename, -+ struct stat __user *statbuf); -+ asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice); -+ -+ /* __ARCH_WANT_SYSCALL_DEPRECATED */ -+ asmlinkage long sys_alarm(unsigned int seconds); -+ asmlinkage long sys_getpgrp(void); -+ asmlinkage long sys_pause(void); -+ asmlinkage long sys_time(__kernel_old_time_t __user *tloc); -+ asmlinkage long sys_time32(old_time32_t __user *tloc); -+ #ifdef __ARCH_WANT_SYS_UTIME -+ asmlinkage long sys_utime(char __user *filename, -+ struct utimbuf __user *times); -+ asmlinkage long sys_utimes(char __user *filename, -+ struct __kernel_old_timeval __user *utimes); -+ asmlinkage long sys_futimesat(int dfd, const char __user *filename, -+ struct __kernel_old_timeval __user *utimes); -+ #endif -+ asmlinkage long sys_futimesat_time32(unsigned int dfd, -+ const char __user *filename, -+ struct old_timeval32 __user *t); -+ asmlinkage long sys_utime32(const char __user *filename, -+ struct old_utimbuf32 __user *t); -+ asmlinkage long sys_utimes_time32(const char __user *filename, -+ struct old_timeval32 __user *t); -+ asmlinkage long sys_creat(const char __user *pathname, umode_t mode); -+ asmlinkage long sys_getdents(unsigned int fd, -+ struct linux_dirent __user *dirent, -+ unsigned int count); -+ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, -+ fd_set __user *exp, struct __kernel_old_timeval __user *tvp); -+ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, -+ int timeout); -+ asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, -+ int maxevents, int timeout); -+ asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf); -+ asmlinkage long sys_vfork(void); -+ asmlinkage long sys_recv(int, void __user *, size_t, unsigned); -+ asmlinkage long sys_send(int, void __user *, size_t, unsigned); -+ asmlinkage long sys_oldumount(char __user *name); -+ asmlinkage long sys_uselib(const char __user *library); -+ asmlinkage long sys_sysfs(int option, -+ unsigned long arg1, unsigned long arg2); -+ asmlinkage long sys_fork(void); -+ -+ /* obsolete */ -+ asmlinkage long sys_stime(__kernel_old_time_t __user *tptr); -+ asmlinkage long sys_stime32(old_time32_t __user *tptr); -+ -+ /* obsolete */ -+ asmlinkage long sys_sigpending(old_sigset_t __user *uset); -+ asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set, -+ old_sigset_t __user *oset); -+ #ifdef CONFIG_OLD_SIGSUSPEND -+ asmlinkage long sys_sigsuspend(old_sigset_t mask); -+ #endif -+ -+ #ifdef CONFIG_OLD_SIGSUSPEND3 -+ asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask); -+ #endif -+ -+ #ifdef CONFIG_OLD_SIGACTION -+ asmlinkage long sys_sigaction(int, const struct old_sigaction __user *, -+ struct old_sigaction __user *); -+ #endif -+ asmlinkage long sys_sgetmask(void); -+ asmlinkage long sys_ssetmask(int newmask); -+ asmlinkage long sys_signal(int sig, __sighandler_t handler); -+ -+ /* obsolete */ -+ asmlinkage long sys_nice(int increment); -+ -+ /* obsolete */ -+ asmlinkage long sys_kexec_file_load(int kernel_fd, int initrd_fd, -+ unsigned long cmdline_len, -+ const char __user *cmdline_ptr, -+ unsigned long flags); -+ -+ /* obsolete */ -+ asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options); -+ -+ /* obsolete */ -+ #ifdef CONFIG_HAVE_UID16 -+ asmlinkage long sys_chown16(const char __user *filename, -+ old_uid_t user, old_gid_t group); -+ asmlinkage long sys_lchown16(const char __user *filename, -+ old_uid_t user, old_gid_t group); -+ asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group); -+ asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid); -+ asmlinkage long sys_setgid16(old_gid_t gid); -+ asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid); -+ asmlinkage long sys_setuid16(old_uid_t uid); -+ asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid); -+ asmlinkage long sys_getresuid16(old_uid_t __user *ruid, -+ old_uid_t __user *euid, old_uid_t __user *suid); -+ asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid); -+ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, -+ old_gid_t __user *egid, old_gid_t __user *sgid); -+ asmlinkage long sys_setfsuid16(old_uid_t uid); -+ asmlinkage long sys_setfsgid16(old_gid_t gid); -+ asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist); -+ asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist); -+ asmlinkage long sys_getuid16(void); -+ asmlinkage long sys_geteuid16(void); -+ asmlinkage long sys_getgid16(void); -+ asmlinkage long sys_getegid16(void); -+ #endif -+ -+ /* obsolete */ -+ asmlinkage long sys_socketcall(int call, unsigned long __user *args); -+ -+ /* obsolete */ -+ asmlinkage long sys_stat(const char __user *filename, -+ struct __old_kernel_stat __user *statbuf); -+ asmlinkage long sys_lstat(const char __user *filename, -+ struct __old_kernel_stat __user *statbuf); -+ asmlinkage long sys_fstat(unsigned int fd, -+ struct __old_kernel_stat __user *statbuf); -+ asmlinkage long sys_readlink(const char __user *path, -+ char __user *buf, int bufsiz); -+ -+ /* obsolete */ -+ asmlinkage long sys_old_select(struct sel_arg_struct __user *arg); -+ -+ /* obsolete */ -+ asmlinkage long sys_old_readdir(unsigned int, struct old_linux_dirent __user *, unsigned int); -+ -+ /* obsolete */ -+ asmlinkage long sys_gethostname(char __user *name, int len); -+ asmlinkage long sys_uname(struct old_utsname __user *); -+ asmlinkage long sys_olduname(struct oldold_utsname __user *); -+ #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT -+ asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim); -+ #endif -+ -+ /* obsolete */ -+ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, -+ unsigned long third, void __user *ptr, long fifth); -+ -+ /* obsolete */ -+ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long pgoff); -+ asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg); -+ -+ -+ /* -+ * Not a real system call, but a placeholder for syscalls which are -+ * not implemented -- see kernel/sys_ni.c -+ */ -+ asmlinkage long sys_ni_syscall(void); -+ -+ #endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ -+ -+ asmlinkage long sys_ni_posix_timers(void); -+ -+ /* -+ * Kernel code should not call syscalls (i.e., sys_xyzyyz()) directly. -+ * Instead, use one of the functions which work equivalently, such as -+ * the ksys_xyzyyz() functions prototyped below. -+ */ -+ ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); -+ int ksys_fchown(unsigned int fd, uid_t user, gid_t group); -+ ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count); -+ void ksys_sync(void); -+ int ksys_unshare(unsigned long unshare_flags); -+ int ksys_setsid(void); -+ int ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes, -+ unsigned int flags); -+ ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count, -+ loff_t pos); -+ ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf, -+ size_t count, loff_t pos); -+ int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len); -+ #ifdef CONFIG_ADVISE_SYSCALLS -+ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); -+ #else -+ static inline int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, -+ int advice) -+ { -+ return -EINVAL; -+ } -+ #endif -+ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long pgoff); -+ ssize_t ksys_readahead(int fd, loff_t offset, size_t count); -+ int ksys_ipc(unsigned int call, int first, unsigned long second, -+ unsigned long third, void __user * ptr, long fifth); -+ int compat_ksys_ipc(u32 call, int first, int second, -+ u32 third, u32 ptr, u32 fifth); -+ -+ /* -+ * The following kernel syscall equivalents are just wrappers to fs-internal -+ * functions. Therefore, provide stubs to be inlined at the callsites. -+ */ -+ extern int do_fchownat(int dfd, const char __user *filename, uid_t user, -+ gid_t group, int flag); -+ -+ static inline long ksys_chown(const char __user *filename, uid_t user, -+ gid_t group) -+ { -+ return do_fchownat(AT_FDCWD, filename, user, group, 0); -+ } -+ -+ static inline long ksys_lchown(const char __user *filename, uid_t user, -+ gid_t group) -+ { -+ return do_fchownat(AT_FDCWD, filename, user, group, -+ AT_SYMLINK_NOFOLLOW); -+ } -+ -+ extern long do_sys_ftruncate(unsigned int fd, loff_t length, int small); -+ -+ static inline long ksys_ftruncate(unsigned int fd, loff_t length) -+ { -+ return do_sys_ftruncate(fd, length, 1); -+ } -+ -+ extern long do_sys_truncate(const char __user *pathname, loff_t length); -+ -+ static inline long ksys_truncate(const char __user *pathname, loff_t length) -+ { -+ return do_sys_truncate(pathname, length); -+ } -+ -+ static inline unsigned int ksys_personality(unsigned int personality) -+ { -+ unsigned int old = current->personality; -+ -+ if (personality != 0xffffffff) -+ set_personality(personality); -+ -+ return old; -+ } -+ -+ /* for __ARCH_WANT_SYS_IPC */ -+ long ksys_semtimedop(int semid, struct sembuf __user *tsops, -+ unsigned int nsops, -+ const struct __kernel_timespec __user *timeout); -+ long ksys_semget(key_t key, int nsems, int semflg); -+ long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); -+ long ksys_msgget(key_t key, int msgflg); -+ long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); -+ long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, -+ long msgtyp, int msgflg); -+ long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, -+ int msgflg); -+ long ksys_shmget(key_t key, size_t size, int shmflg); -+ long ksys_shmdt(char __user *shmaddr); -+ long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); -+ long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, -+ unsigned int nsops, -+ const struct old_timespec32 __user *timeout); -+ long __do_semtimedop(int semid, struct sembuf *tsems, unsigned int nsops, -+ const struct timespec64 *timeout, -+ struct ipc_namespace *ns); -+ -+ int __sys_getsockopt(int fd, int level, int optname, char __user *optval, -+ int __user *optlen); -+ int __sys_setsockopt(int fd, int level, int optname, char __user *optval, -+ int optlen); -+ #endif -\ No newline at end of file + __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ + return ret; \ + } \ From b47dcbe7e0b1300047c5c15aec85e810ac0be900 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 19:54:05 -0400 Subject: [PATCH 18/28] ci: use rehosting/ci's shared nix-setup instead of a private copy The previous commit added a local composite action because `rehosting/nix-setup@v1` 404'd. The action does exist -- as `rehosting/ci/actions/nix-setup@v1`, alongside arc-registry-setup, pull-image and cleanup-pr-cache. Only the path was wrong, and nine workflows across penguin, fw2tar, qemu and vpnguin already consume it. The shared action is a superset of what was hand-rolled here: it installs the xz/curl the Arc pods lack (same fix, same reasoning), sets accept-flake-config, and exposes enable-kvm -- which matters on these runners, where install-nix-action's KVM/udevadm step fails on pods that expose /dev/kvm without a working udevd. Set to false; nothing here needs a VM. It also owns the Cachix wiring via cachix-action, so the manual `nix profile install nixpkgs#cachix` + `cachix push` steps are gone, and with them the job-level CACHIX_AUTH_TOKEN that only existed so a step-level `if:` could see it. One behaviour change, deliberate: nix-setup's skip-push default means PR runs PULL from rehosting-tools but do not push, with pushes to main populating it. That is the org convention (the rationale is fork PRs and pull-only tokens 403ing the post step) and it differs from what this workflow did before, which pushed from PRs too. Acceptable because the expensive closures -- the cross toolchains -- are already in the cache from the earlier run, so PRs now substitute them rather than rebuilding. Switches to secrets.CACHIX_REHOSTING, which is what the other nix workflows in the org use; CACHIX_AUTH_TOKEN also exists at org level but is not the convention. --- .github/actions/nix-setup/action.yml | 49 ------------------ .github/workflows/nix.yml | 75 +++++++++++++++------------- 2 files changed, 39 insertions(+), 85 deletions(-) delete mode 100644 .github/actions/nix-setup/action.yml diff --git a/.github/actions/nix-setup/action.yml b/.github/actions/nix-setup/action.yml deleted file mode 100644 index d19df82..0000000 --- a/.github/actions/nix-setup/action.yml +++ /dev/null @@ -1,49 +0,0 @@ -# Shared Nix setup for this repo's workflows. -# -# Local composite action rather than a `rehosting/nix-setup` repo: an earlier -# draft of nix.yml referenced `rehosting/nix-setup@v1`, which does not exist, so -# every job failed at "Set up job" with `Unable to resolve action ..., -# repository not found` -- before running a single step. Keeping it in-repo -# means it is version-locked to the workflow that uses it and cannot 404. -# -# The setup itself mirrors what already works on `rehosting-arc` elsewhere in -# the org (rehosting/hyperfs build.yaml): cachix/install-nix-action with a -# token, plus explicit substituter config. -name: nix-setup -description: Install Nix and point it at the rehosting-tools binary cache. - -inputs: - github_token: - description: Token for install-nix-action, to avoid unauthenticated rate limits. - required: false - default: "" - -runs: - using: composite - steps: - # The nix installer unpacks an .xz tarball and the rehosting-arc image ships - # without xz, so install-nix-action dies with "you do not have 'xz' - # installed" after successfully downloading the installer. Every repo in the - # org that runs Nix on these runners apt-installs it first. - - shell: bash - run: | - set -euo pipefail - if ! command -v xz >/dev/null; then - sudo apt-get update -qq - sudo apt-get install -y -qq xz-utils curl - fi - - - uses: cachix/install-nix-action@v27 - with: - github_access_token: ${{ inputs.github_token }} - # The substituters are also declared in flake.nix's nixConfig, but that - # only applies for trusted users -- on a runner where the invoking user - # is not in trusted-users the flake's request is silently ignored and - # every cross toolchain rebuilds from source. Setting them here is what - # actually takes effect. - extra_nix_config: | - max-jobs = 8 - cores = 8 - extra-substituters = https://rehosting-tools.cachix.org - extra-trusted-public-keys = rehosting-tools.cachix.org-1:iNKSaFwG7MfGn6Fk7oTmIcLHqfffQ+cQIE5gWc6MlY0= - accept-flake-config = true diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index eed1883..236e881 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -5,8 +5,9 @@ # series applies cleanly to the pinned upstream tarball" is the invariant that # makes patches-as-source-of-truth safe. # -# Runner/cache wiring is exercised on `rehosting-arc`; see -# .github/actions/nix-setup for why that setup is a local composite action. +# Nix install + Cachix wiring comes from rehosting/ci/actions/nix-setup, the +# org's shared action. Per its skip-push default, PR runs PULL from +# rehosting-tools but do not push; pushes to main populate it. name: nix (patch series + kernels) on: @@ -24,14 +25,6 @@ concurrency: group: nix-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} -# Job-level so that step-level `if:` can actually see it. A step's own `env:` -# block is NOT in scope for that step's `if:`, so the previous -# `if: env.CACHIX_AUTH_TOKEN != ''` next to a step-level `env:` was always -# false and the cache was never pushed -- the exact failure this workflow was -# written to prevent. -env: - CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} - jobs: series: name: series applies (${{ matrix.version }}) @@ -43,9 +36,19 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/nix-setup + - name: Set up Nix + uses: rehosting/ci/actions/nix-setup@v1 with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} + cache-backend: cachix + cachix-name: rehosting-tools + cachix-auth-token: ${{ secrets.CACHIX_REHOSTING }} + # No VM needed; avoids install-nix-action's KVM/udevadm step, which + # fails on Arc pods that expose /dev/kvm without a working udevd. + enable-kvm: false + extra-nix-config: | + max-jobs = 8 + cores = 8 - name: Fetch the pinned upstream tarball id: tarball @@ -73,9 +76,19 @@ jobs: cell: ["4.10-armel", "6.13-armel"] steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/nix-setup + - name: Set up Nix + uses: rehosting/ci/actions/nix-setup@v1 with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} + cache-backend: cachix + cachix-name: rehosting-tools + cachix-auth-token: ${{ secrets.CACHIX_REHOSTING }} + # No VM needed; avoids install-nix-action's KVM/udevadm step, which + # fails on Arc pods that expose /dev/kvm without a working udevd. + enable-kvm: false + extra-nix-config: | + max-jobs = 8 + cores = 8 - name: Build kernel, perf and module run: | @@ -85,20 +98,6 @@ jobs: ".#packages.x86_64-linux.\"$out-${{ matrix.cell }}\"" done - # Populate the cache from PRs too. Pushing only on release is why cross - # toolchain closures get rebuilt from source (~68 min observed elsewhere - # in this stack) instead of substituted. - - name: Push to Cachix - if: ${{ env.CACHIX_AUTH_TOKEN != '' }} - run: | - set -euo pipefail - nix profile install nixpkgs#cachix - for out in kernel perf driver; do - nix build --print-out-paths \ - ".#packages.x86_64-linux.\"$out-${{ matrix.cell }}\"" \ - | cachix push rehosting-tools - done - # The full 19-cell matrix, on demand. Not on every PR: it is the expensive # one, and the gate above catches the failures that are not arch-specific. full: @@ -108,9 +107,19 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && inputs.full_matrix }} steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/nix-setup + - name: Set up Nix + uses: rehosting/ci/actions/nix-setup@v1 with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} + cache-backend: cachix + cachix-name: rehosting-tools + cachix-auth-token: ${{ secrets.CACHIX_REHOSTING }} + # No VM needed; avoids install-nix-action's KVM/udevadm step, which + # fails on Arc pods that expose /dev/kvm without a working udevd. + enable-kvm: false + extra-nix-config: | + max-jobs = 8 + cores = 8 - name: Every kernel run: nix build --print-out-paths ".#all" @@ -143,9 +152,3 @@ jobs: run: | nix build --print-out-paths .#kernels-latest nix build --print-out-paths .#kernel-devel-all - - - name: Push to Cachix - if: ${{ env.CACHIX_AUTH_TOKEN != '' }} - run: | - nix profile install nixpkgs#cachix - nix build --print-out-paths .#all | cachix push rehosting-tools From bab4db103f754bd69edd2c4db3400ae4fac96586 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 19:55:44 -0400 Subject: [PATCH 19/28] ci: set USER/LOGNAME/TMPDIR/XDG_CACHE_HOME for the Arc pods nix-setup's Cachix step failed on both jobs with $USER must be set. If running in a container, try setting USER=root. The Arc pods run as a uid with no passwd entry, so $USER and $LOGNAME are unset and HOME-relative cache paths are not writable. `cachix use` refuses to run in that state. rehosting/qemu's nix workflow already carries exactly this block; I dropped it when adapting that workflow on the assumption it was incidental. It is a precondition for running Nix on this runner pool. TMPDIR and XDG_CACHE_HOME are created before Nix runs, since pointing at a path that does not exist fails the same way slightly later. --- .github/workflows/nix.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 236e881..e968864 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -25,6 +25,17 @@ concurrency: group: nix-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} +# The Arc pods run as a uid with no passwd entry, so $USER/$LOGNAME are unset +# and HOME-relative caches are not writable. `cachix use` fails outright with +# "$USER must be set. If running in a container, try setting USER=root." These +# four are a precondition for running Nix on this runner pool, not decoration -- +# rehosting/qemu's workflow carries the same block for the same reason. +env: + USER: runner + LOGNAME: runner + TMPDIR: /home/runner/_work/_temp + XDG_CACHE_HOME: /home/runner/_work/.cache + jobs: series: name: series applies (${{ matrix.version }}) @@ -36,6 +47,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Prepare runner directories + run: mkdir -p "$TMPDIR" "$XDG_CACHE_HOME" + - name: Set up Nix uses: rehosting/ci/actions/nix-setup@v1 with: @@ -76,6 +90,8 @@ jobs: cell: ["4.10-armel", "6.13-armel"] steps: - uses: actions/checkout@v4 + - name: Prepare runner directories + run: mkdir -p "$TMPDIR" "$XDG_CACHE_HOME" - name: Set up Nix uses: rehosting/ci/actions/nix-setup@v1 with: @@ -107,6 +123,8 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && inputs.full_matrix }} steps: - uses: actions/checkout@v4 + - name: Prepare runner directories + run: mkdir -p "$TMPDIR" "$XDG_CACHE_HOME" - name: Set up Nix uses: rehosting/ci/actions/nix-setup@v1 with: From 26abea95f1129a227e841dd4bd8aba53f8347df9 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 20:00:03 -0400 Subject: [PATCH 20/28] ci: pin buildkit v0.30.0 in the Docker build Unrelated to this branch's contents -- infrastructure drift that happens to show up as a red check on it. setup-buildx-action's default buildkit image has moved onto a version carrying the /proc/acpi masking regression, so build-image now dies with can't mask dir "/proc/acpi": mount src=tmpfs, dst=/proc/acpi, flags=MS_RDONLY, data=nr_blocks=1,nr_inodes=1: invalid argument on the kernel-5.4 Arc runners. The workflow already knew not to pin moby/buildkit:master for exactly this reason, but trusting the default is no longer sufficient. main last ran 2026-07-28 and so has not hit it yet; it will on its next run. v0.30.0 is the same pin igloo-dev applies in its source-nightly publish for this regression. --- .github/workflows/build.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bfa55af..a0340d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -114,9 +114,20 @@ jobs: with: # See the note in the (removed) per-job build step / penguin c35bedc5: # don't pin moby/buildkit:master -- it regressed on the kernel-5.4 - # runners (can't mask /proc/acpi). Default pinned-stable buildkit + the - # insecure Harbor registry config. + # runners (can't mask /proc/acpi). + # + # Relying on setup-buildx-action's *default* image is no longer enough: + # the default has since moved onto a buildkit carrying the same + # regression, and this workflow started failing with + # + # can't mask dir "/proc/acpi": mount src=tmpfs, dst=/proc/acpi, + # flags=MS_RDONLY, data=nr_blocks=1,nr_inodes=1: invalid argument + # + # main has not run since 2026-07-28 so it has not caught up with the + # drift yet. Pin the last known-good buildkit explicitly, matching the + # pin igloo-dev already applies in its source-nightly publish. driver-opts: | + image=moby/buildkit:v0.30.0 network=host buildkitd-config-inline: | [registry."${{ secrets.REHOSTING_ARC_REGISTRY }}"] From 60876adebc6fc86b4f9459fb2093d8ee4e68f288 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 20:42:32 -0400 Subject: [PATCH 21/28] nix: expose the kernels tree as a directory, not only a tarball penguin's flake pins the release TARBALL (`inputs.kernels`, flake = false) and relies on Nix unpacking it. For a Nix consumer to take these kernels from this flake instead, going through `kernels-latest` would mean packing ~335 MB of archive purely so the consumer can unpack it again. `kernelsTree` is that payload as a plain directory -- `/`, which is exactly the layout penguin lays down at /igloo_static/kernels/. It is exposed as the `kernels` package. No duplication of the assembly: kernelsTarball is now defined in terms of kernelsTree, so the two cannot drift. The README.txt and the reproducible-tar flags are unchanged, so `kernels-latest` is byte-identical to before. --- flake.nix | 13 +++++++++++++ nix/release.nix | 27 +++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/flake.nix b/flake.nix index 5337beb..5d62251 100644 --- a/flake.nix +++ b/flake.nix @@ -142,6 +142,19 @@ all = pkgs.linkFarm "igloo-kernels-all" (lib.mapAttrsToList (n: v: { name = n; path = v; }) cells); + # The same payload as kernels-latest, but as a directory. This is the + # seam for Nix consumers: penguin stages `/...` straight into + # /igloo_static/kernels/, so handing it the tree avoids packing an + # archive purely for the consumer to unpack again. + kernels = releaseLib.kernelsTree { + versions = map + (version: { + inherit version; + dir = releaseLib.kernelsDir { inherit version; cells = cellRecords version; }; + }) + (builtins.attrNames matrix); + }; + # Drop-in replacements for the Docker build's release artifacts. kernels-latest = releaseLib.kernelsTarball { versions = map diff --git a/nix/release.nix b/nix/release.nix index 6a820c1..e23c506 100644 --- a/nix/release.nix +++ b/nix/release.nix @@ -50,13 +50,22 @@ rec { for f in $(ls $out/osi.*.config | sort); do cat "$f" >> $out/osi.config; done ''; - kernelsTarball = { versions }: - pkgs.runCommand "kernels-latest.tar.gz" { nativeBuildInputs = [ pkgs.gzip ]; } '' - mkdir -p stage/kernels + # The tarball's payload as a plain directory: `/`, which is + # exactly the layout penguin lays down at /igloo_static/kernels/. + # + # Exposed separately so a Nix consumer can take the tree directly instead of + # the archive. penguin's flake currently pins the release TARBALL + # (`inputs.kernels`, flake = false) and relies on Nix unpacking it; going + # through kernelsTarball from another flake would mean tar-then-untar of + # ~335 MB to reproduce a directory this already has. Same contents either way + # -- kernelsTarball is defined in terms of this. + kernelsTree = { versions }: + pkgs.runCommand "igloo-kernels" { } '' + mkdir -p $out ${lib.concatMapStringsSep "\n" - (v: ''cp -a ${v.dir} stage/kernels/${v.version}'') + (v: ''cp -a ${v.dir} $out/${v.version}'') versions} - chmod -R u+w stage + chmod -R u+w $out # Deliberately not the Docker build's `Built by linux_builder on $(date)`: # a timestamp would make the archive non-reproducible for no benefit. @@ -68,8 +77,14 @@ rec { 'Provenance is the store path of each input, not a build date -- these' \ 'artifacts are a pure function of the pinned kernel tarball, the patch' \ 'series in patches/, the config in configs/, and the kernelsmith toolchain.' \ - > stage/kernels/README.txt + > $out/README.txt + ''; + kernelsTarball = { versions }: + pkgs.runCommand "kernels-latest.tar.gz" { nativeBuildInputs = [ pkgs.gzip ]; } '' + mkdir -p stage + cp -a ${kernelsTree { inherit versions; }} stage/kernels + chmod -R u+w stage tar ${reproTar} -cf - -C stage kernels | gzip -9n > $out ''; From f52cd827b77711487c5c8cf1bd2bed3a2005b932 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 13 Aug 2026 21:34:38 -0400 Subject: [PATCH 22/28] ci: cut a nix-built prerelease from a nixdev_* tag Lets the nix path produce a real, downloadable release before it takes over the version line, so downstream consumers can be tested against an actual artifact rather than a branch. The tag prefix is deliberately NOT `dev_*`: build.yml already triggers on that, so a shared prefix would have both pipelines cut a release for the same tag and race version-increment for the same vX.Y.Z. `nixdev_*` does not match `dev_*` (the globs are anchored), so the two release paths stay independent while both exist. The tag itself is the version -- no version-increment here -- and the release is always a prerelease. The full 19-cell matrix now runs on such a tag as well as on dispatch, which has a second effect that matters downstream: a tag is a push event, so nix-setup's skip-push default does not apply and everything built lands in rehosting-tools. A consumer pinning this flake (rehosting/penguin#932) then substitutes all 19 kernels instead of cross-building them in its own CI. Also logs the tarball manifest and per-version perf coverage, so the difference from the Docker release is visible in the run without downloading anything. --- .github/workflows/nix.yml | 72 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index e968864..aa83200 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -14,6 +14,14 @@ on: pull_request: push: branches: [main, nix-patchset] + # Cut a nix-built PRERELEASE from a tag, without touching the version line. + # + # Deliberately NOT `dev_*`: that prefix already triggers the Docker + # workflow (build.yml), so a shared prefix would have both pipelines cut a + # release for the same tag and race `version-increment` for the same vX.Y.Z. + # `nixdev_*` does not match `dev_*` -- these globs are anchored -- so the two + # stay independent while both release paths exist. + tags: ['nixdev_*'] workflow_dispatch: inputs: full_matrix: @@ -114,13 +122,24 @@ jobs: ".#packages.x86_64-linux.\"$out-${{ matrix.cell }}\"" done - # The full 19-cell matrix, on demand. Not on every PR: it is the expensive - # one, and the gate above catches the failures that are not arch-specific. + # The full 19-cell matrix: on demand, and on a `nixdev_*` tag, where it is + # also what produces the release. Not on every PR -- it is the expensive one, + # and the gate above catches the failures that are not arch-specific. + # + # Running it on the tag has a second effect that matters for downstream + # testing: this is a push event, so nix-setup's skip-push default does NOT + # apply and every path built here lands in rehosting-tools. A consumer that + # pins this flake (rehosting/penguin#932) then SUBSTITUTES all 19 kernels + # instead of cross-building them in its own CI. full: name: full matrix runs-on: rehosting-arc needs: series - if: ${{ github.event_name == 'workflow_dispatch' && inputs.full_matrix }} + permissions: + contents: write + if: >- + ${{ (github.event_name == 'workflow_dispatch' && inputs.full_matrix) + || startsWith(github.ref, 'refs/tags/nixdev_') }} steps: - uses: actions/checkout@v4 - name: Prepare runner directories @@ -168,5 +187,48 @@ jobs: - name: Release tarballs assemble run: | - nix build --print-out-paths .#kernels-latest - nix build --print-out-paths .#kernel-devel-all + set -euo pipefail + nix build --print-out-paths --out-link result-kernels .#kernels-latest + nix build --print-out-paths --out-link result-kernel-devel .#kernel-devel-all + # Copy out of the store: the outputs are read-only files whose store + # names already match, but the upload needs real files in the workdir. + cp -L result-kernels kernels-latest.tar.gz + cp -L result-kernel-devel kernel-devel-all.tar.gz + chmod u+w kernels-latest.tar.gz kernel-devel-all.tar.gz + ls -l kernels-latest.tar.gz kernel-devel-all.tar.gz + + # Manifest of what the nix path actually ships, in the log, so a reviewer + # can diff it against the Docker release without downloading anything. + - name: Manifest + run: | + tar tzf kernels-latest.tar.gz | sed 's|^\./||' | grep -v '/$' | sort + echo "--- perf coverage ---" + for v in 4.10 6.13; do + tot=$(tar tzf kernels-latest.tar.gz | grep -c "kernels/$v/osi\..*\.config" || true) + perf=$(tar tzf kernels-latest.tar.gz | grep -c "kernels/$v/perf\." || true) + echo " $v: perf for $perf of $tot targets" + done + + # Prerelease only, and only from a nixdev_* tag. The tag IS the version -- + # no version-increment here, so this cannot collide with the Docker + # pipeline's vX.Y.Z line while both exist. + - name: Publish prerelease + if: ${{ startsWith(github.ref, 'refs/tags/nixdev_') }} + uses: softprops/action-gh-release@v1 + with: + files: | + kernels-latest.tar.gz + kernel-devel-all.tar.gz + token: ${{ secrets.GITHUB_TOKEN }} + tag_name: ${{ github.ref_name }} + name: ${{ github.ref_name }} (nix, prerelease) + prerelease: true + body: | + Built by the **nix + patch series** path (linux_builder#59), not the + Docker pipeline. Prerelease, for downstream testing only -- it does + not participate in the `vX.Y.Z` version line. + + Differs from the Docker release in exactly two ways: + * `perf` for all 19 cells (the Docker path shipped 7 of 19) + * no `powerpcle` -- it was byte-identical to `powerpc` and + big-endian despite the name From 7a2b5881fefd182c2ccb96dcf68ede27cfe6435b Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Fri, 14 Aug 2026 16:59:09 -0400 Subject: [PATCH 23/28] Boot every kernel under qemu before shipping it nixdev_0.1.0 published a 4.10/x86_64 bzImage that does not boot. It prints nothing -- not one kernel line. Every gate on this branch passed it: * the build succeeded * shape-check passed (a bzImage's ELF class says nothing about whether it runs; it is also the same 8.1 MB as the Docker build's) * the series gate passed (it only proves the patches APPLY) * kernelsmith's own boot.nix passed -- but its k4 cell boots 5.10.229, and the k4 band spans 4.x AND 5.x, so 4.10 had never been booted by anything, here or upstream It was caught by a downstream consumer's integration tests (rehosting/penguin#932), which is two repos and one release too late. nix/boot.nix boots each shipped kernel headless under qemu with no rootfs and asserts two things: the kernel banner appears, and it reached the root-fs stage (a VFS/panic marker -- the whole pre-userspace path). Verified against both outcomes before committing: boot-6.13-armel ok boot-4.10-x86_64 FAIL: no kernel banner -- it never started The machine/console table is transcribed from penguin's src/penguin/arch_registry.py, so each kernel is booted on the machine penguin will actually run it on -- booting it on some other qemu model is not the claim any consumer needs. 32-bit powerpc is unbootable by declaration (arch_registry records qemu_machine=None for it); that is an explicit SKIP entry rather than a silent omission, and an unknown target is a hard error rather than a pass. Wired into both CI jobs: the per-cell gate boots its cell, and the full matrix boots all 19. This does NOT fix 4.10/x86_64 -- it makes it impossible to ship. The cause is still open; see the PR discussion. It is not the compiler (reproduced with gcc 6.5/7.5/9.5/10.5) and the .config is byte-identical to the Docker build's. --- .github/workflows/nix.yml | 14 ++++ flake.nix | 11 ++++ nix/boot.nix | 132 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 nix/boot.nix diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index aa83200..dd6fd90 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -122,6 +122,14 @@ jobs: ".#packages.x86_64-linux.\"$out-${{ matrix.cell }}\"" done + # Does the kernel actually RUN. Every other gate here passed the + # 4.10/x86_64 image that printed nothing at all -- see nix/boot.nix. + - name: Kernel boots + run: | + nix build --print-build-logs \ + ".#packages.x86_64-linux.\"boot-${{ matrix.cell }}\"" + + # The full 19-cell matrix: on demand, and on a `nixdev_*` tag, where it is # also what produces the release. Not on every PR -- it is the expensive one, # and the gate above catches the failures that are not arch-specific. @@ -185,6 +193,12 @@ jobs: - name: Shapes match target names run: nix build --print-out-paths .#shape-check + # Boot every cell. Slower than the rest of this job put together on some + # arches, and the only check that would have stopped nixdev_0.1.0's + # non-booting 4.10/x86_64 from being published. + - name: Every kernel boots + run: nix build --print-build-logs --print-out-paths .#boot-check + - name: Release tarballs assemble run: | set -euo pipefail diff --git a/flake.nix b/flake.nix index 5d62251..56b0cc9 100644 --- a/flake.nix +++ b/flake.nix @@ -99,6 +99,7 @@ releaseLib = import ./nix/release.nix { inherit pkgs; }; mkPerf = import ./nix/perf.nix { inherit pkgs kernelsmith; }; mkDriver = import ./nix/driver.nix { inherit pkgs kernelsmith; }; + bootLib = import ./nix/boot.nix { inherit pkgs; }; # Per-cell record carrying everything the assembly needs. cellRecords = version: map @@ -130,6 +131,11 @@ (lib.nameValuePair "driver-${r.version}-${r.target}" r.driver) (lib.nameValuePair "osi-${r.version}-${r.target}" r.osi) (lib.nameValuePair "cosi-${r.version}-${r.target}" r.cosi) + # The one check that asks whether the kernel RUNS. Individually + # addressable so a dead cell can be reproduced in one command: + # nix build .#packages.x86_64-linux."boot-4.10-x86_64" + (lib.nameValuePair "boot-${r.version}-${r.target}" + (bootLib.forCell { inherit (r) kernel version target; })) ]) allRecords); @@ -171,6 +177,11 @@ # See nix/shape.nix -- two such bugs shipped undetected on this branch. shape-check = (import ./nix/shape.nix { inherit pkgs; }) { cells = allRecords; }; + # Catches the strictly worse failure class shape-check cannot see: an + # artifact of exactly the right shape and size that does not run at all. + # nixdev_0.1.0's 4.10/x86_64 is one -- see nix/boot.nix. + boot-check = bootLib.all { cells = allRecords; }; + # The analysis tools, pinned. Exposed so their provenance is inspectable # and so igloo_driver can reuse dwarf2json for its own ISF (it runs the # same fork over igloo.ko) instead of re-deriving the pin. diff --git a/nix/boot.nix b/nix/boot.nix new file mode 100644 index 0000000..e619ac6 --- /dev/null +++ b/nix/boot.nix @@ -0,0 +1,132 @@ +# Boot every shipped kernel under qemu and assert it actually starts. +# +# THIS IS THE CHECK THAT WAS MISSING. nixdev_0.1.0 shipped a 4.10/x86_64 +# bzImage that compiles, links, packages, has the correct ELF class, byte order +# and machine, is the same 8.1 MB as the Docker build's -- and prints not one +# line before dying. Every existing gate passed it: +# +# * the build succeeded +# * shape-check passed (a bzImage's shape says nothing about whether it runs) +# * the series gate passed (it only proves the patches APPLY) +# * kernelsmith's own boot.nix passed -- but its k4 cell boots 5.10.229, and +# the k4 band spans 4.x AND 5.x, so 4.10 had never been booted by anything +# +# It was found by a downstream consumer's integration tests (rehosting/penguin#932), +# which is three repos and one release too late. +# +# The machine/console table is transcribed from penguin's src/penguin/arch_registry.py +# -- deliberately, so this boots each kernel on the machine penguin will actually +# run it on. A kernel that boots under some other qemu model is not the claim +# anyone downstream needs. +{ pkgs }: + +let + inherit (pkgs) lib; + + # target -> how penguin boots it. `null` means "no qemu machine exists", + # which is DECLARED here rather than silently skipped. + machines = { + armel = { system = "arm"; machine = "virt"; console = "ttyAMA0"; }; + arm64 = { system = "aarch64"; machine = "virt"; cpu = "cortex-a57"; console = "ttyAMA0"; }; + mipsel = { system = "mipsel"; machine = "malta"; console = "ttyS0"; }; + mipseb = { system = "mips"; machine = "malta"; console = "ttyS0"; }; + mips64el = { system = "mips64el"; machine = "malta"; cpu = "MIPS64R2-generic"; console = "ttyS0"; }; + mips64eb = { system = "mips64"; machine = "malta"; cpu = "MIPS64R2-generic"; console = "ttyS0"; }; + powerpc64 = { system = "ppc64"; machine = "pseries"; cpu = "power9"; console = "hvc0"; }; + powerpc64le = { system = "ppc64"; machine = "pseries"; cpu = "power9"; console = "hvc0"; }; + riscv64 = { system = "riscv64"; machine = "virt"; console = "ttyS0"; }; + loongarch64 = { system = "loongarch64"; machine = "virt"; cpu = "la464"; console = "ttyS0"; }; + x86_64 = { system = "x86_64"; machine = "pc"; console = "ttyS0"; }; + + # 32-bit powerpc: arch_registry.py records qemu_machine=None -- "no QEMU + # machine was ever configured for 32-bit ppc". Nothing to boot it on, so it + # is unbootable-by-declaration rather than an oversight. If a machine is + # ever wired up in penguin, add it here too. + powerpc = null; + }; + + # The kernel image each target ships, by extension of what kernelsDir copies. + # Globbed rather than tabulated: the artifact name varies by arch + # (zImage./bzImage./vmlinux./Image.) and duplicating that table here is one + # more thing to drift. + bootTest = { kernel, version, target, spec }: + pkgs.runCommand "igloo-boot-${version}-${target}" + { + nativeBuildInputs = [ pkgs.qemu ]; + meta.description = "boot smoke test for ${version}/${target}"; + } '' + img="" + for cand in ${kernel}/bzImage.${target} ${kernel}/zImage.${target} \ + ${kernel}/Image.${target} ${kernel}/vmlinux.${target}; do + [ -f "$cand" ] && { img="$cand"; break; } + done + if [ -z "$img" ]; then + echo "no bootable image for ${version}/${target} in ${kernel}" >&2 + ls ${kernel} >&2 + exit 1 + fi + echo "booting $(basename $img) on qemu-system-${spec.system} -M ${spec.machine}" + + # No rootfs is supplied on purpose. A kernel that starts and then cannot + # mount root is a SUCCESS for this test -- it proves early boot, console + # init and the whole pre-userspace path. Supplying a rootfs would test + # penguin's job, not this one. + # + # `timeout` rather than qemu's own exit: a kernel that hangs must fail + # here, not run until the CI job is killed. + timeout 120 qemu-system-${spec.system} \ + -M ${spec.machine} \ + ${lib.optionalString (spec ? cpu) "-cpu ${spec.cpu}"} \ + -m 256 -nographic -no-reboot \ + -kernel "$img" \ + -append "console=${spec.console} panic=1" \ + < /dev/null > boot.log 2>&1 || true + + echo "--- captured $(wc -c < boot.log) bytes ---" + cat boot.log + + # Two assertions, in increasing strength. + # + # 1. The kernel banner. This alone is what nixdev_0.1.0's 4.10/x86_64 + # failed: it decompressed, printed "Booting the kernel.", and went + # silent forever. + if ! grep -q "Linux version" boot.log; then + echo "FAIL ${version}/${target}: no kernel banner -- it never started" >&2 + exit 1 + fi + + # 2. It got as far as looking for a root filesystem. Without this a kernel + # that prints its banner and then dies in early init would still pass, + # which is most of the failure surface this test exists for. + if ! grep -Eq "VFS: Cannot open root|VFS: Unable to mount root|Kernel panic - not syncing|No filesystem could mount root|Attempted to kill init|Requested init" boot.log; then + echo "FAIL ${version}/${target}: banner printed but never reached the root-fs stage" >&2 + exit 1 + fi + + echo "ok ${version}/${target}" > $out + ''; + +in +rec { + inherit machines; + + # null spec -> a derivation that records WHY it is not boot-tested. Not a + # silent omission: `nix build .#boot-check` still names it. + forCell = { kernel, version, target }: + let spec = machines.${target} or (throw + "boot.nix: target ${target} has no entry; add it (or an explicit null)"); + in + if spec == null then + pkgs.runCommand "igloo-boot-${version}-${target}-skipped" { } '' + echo "SKIP ${version}/${target}: no qemu machine exists for this target" | tee $out + '' + else bootTest { inherit kernel version target spec; }; + + # One derivation that boots the whole matrix, for CI. + all = { cells }: + pkgs.linkFarm "igloo-boot-check" + (map (c: { + name = "${c.version}-${c.target}"; + path = forCell { inherit (c) kernel version target; }; + }) cells); +} From ff75fceda4ed98abc9491021cfc896d01d659893 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Fri, 14 Aug 2026 17:44:48 -0400 Subject: [PATCH 24/28] boot.nix: boot every target, including the three it silently could not Wiring boot.nix up against the full matrix turned up three harness bugs. All three reported a healthy kernel as dead, which is the failure mode a boot gate can least afford -- it trains you to distrust the gate. 1. The image glob was not a glob. The comment claimed it globbed "rather than tabulated" to avoid drift; the code hard-coded four names (bzImage/zImage/Image/vmlinux). 6.13/loongarch64 ships vmlinuz.efi.loongarch64 and failed as "no bootable image" while the kernel was fine. Now ranks every *. artifact, preferring the arch's wrapped image over raw vmlinux -- the wrapped one is what penguin boots -- and warns rather than fails on an unranked name. 2. loongarch64 needs two things nothing else here does, both of which penguin already supplies (penguin_run.py:659): * >1G RAM -- qemu's virt machine refuses to start below it * EFI firmware -- kernel_fmt is vmlinuz.efi, a PE image, and the built-in loader rejects it ("The image is not ELF") Booting its ELF vmlinux instead would have passed this test while testing an image penguin never runs. The pinned nixpkgs (24.05, qemu 8.2.7) predates nixpkgs shipping edk2-loongarch64-code.fd, so this adds a separate nixpkgs-qemu input for the harness alone. Worth doing on its own terms: what the kernel builds against and what we boot on should not be forced to move together, and the latter should track what penguin runs. 3. Asserting on the "Linux version" banner alone was too strict. On loongarch64 the EFI stub hands over after console setup, so the earliest printks never reach the serial log -- a kernel that booted to a root-fs panic was reported as never having started. Any timestamped printk is the portable evidence; the genuinely dead 4.10/x86_64 image emitted none, so this still catches it. Full matrix with kernelsmith#5: 18 boot, 1 declared SKIP (32-bit powerpc, which arch_registry.py records as having no qemu machine). 4.10/x86_64 -- the cell that started all of this -- now reaches the root-fs stage. flake.lock pins kernelsmith ahead of main pending kernelsmith#5. --- flake.lock | 25 ++++++++++++++++--- flake.nix | 17 +++++++++++-- nix/boot.nix | 70 +++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 91 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index 232b61d..da5a540 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1786663087, - "narHash": "sha256-uynOJDkUTq7V3gZxNre3CmeMwBSYYoToi1kYea52OPU=", + "lastModified": 1786743798, + "narHash": "sha256-M7F4Eu1ws3WKR34KxBm1CHdwARha7i5QCd0lKjxrs7w=", "owner": "rehosting", "repo": "kernelsmith", - "rev": "f3220b9a1919076317659310d75b28f0c36fab62", + "rev": "a6b66282cccfcfa610a9c8d7d9fff5bb20906dfa", "type": "github" }, "original": { @@ -67,6 +67,22 @@ "type": "github" } }, + "nixpkgs-qemu": { + "locked": { + "lastModified": 1767313136, + "narHash": "sha256-16KkgfdYqjaeRGBaYsNrhPRRENs0qzkQVUooNHtoy2w=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ac62194c3917d5f474c1a844b6fd6da2db95077d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "igloo_driver": "igloo_driver", @@ -74,7 +90,8 @@ "nixpkgs": [ "kernelsmith", "nixpkgs" - ] + ], + "nixpkgs-qemu": "nixpkgs-qemu" } } }, diff --git a/flake.nix b/flake.nix index 56b0cc9..afbb422 100644 --- a/flake.nix +++ b/flake.nix @@ -13,9 +13,21 @@ # the embedded-toolchains Docker image, whose toolchains were unversioned # `wget https://musl.cc/*-cross.tgz` downloads -- i.e. today's shipped # kernels have no recorded compiler identity. + # NB: flake.lock currently pins this AHEAD of main, to the k4-x86_64 + # binutils fix (kernelsmith#5) that 4.10/x86_64 needs to boot at all. + # Re-lock to main once that merges; the url needs no change. kernelsmith.url = "github:rehosting/kernelsmith"; nixpkgs.follows = "kernelsmith/nixpkgs"; + # qemu ONLY, for nix/boot.nix. Deliberately not `nixpkgs`: the kernel build + # pins 24.05 (qemu 8.2.7), which predates nixpkgs shipping + # edk2-loongarch64-code.fd -- and loongarch64's kernel_fmt is vmlinuz.efi, + # a PE image that needs EFI firmware to boot at all. Pinning the harness's + # qemu separately also stops "what the kernel builds against" and "what we + # boot on" from being forced to move together; the second should track what + # penguin runs, which is never a four-year-old qemu. + nixpkgs-qemu.url = "github:NixOS/nixpkgs/nixos-25.05"; + # Source only -- igloo_driver has no flake of its own yet. This is here to # ACCEPTANCE-TEST the kernel `dev` output (see nix/driver.nix): a build tree # that cannot build the one module we care about is broken, and this repo is @@ -28,10 +40,11 @@ }; outputs = - { self, nixpkgs, kernelsmith, igloo_driver }: + { self, nixpkgs, nixpkgs-qemu, kernelsmith, igloo_driver }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; + qemuPkgs = nixpkgs-qemu.legacyPackages.${system}; inherit (pkgs) lib; # Upstream bases. These are REAL RELEASE TAGS -- the point of the patchset @@ -99,7 +112,7 @@ releaseLib = import ./nix/release.nix { inherit pkgs; }; mkPerf = import ./nix/perf.nix { inherit pkgs kernelsmith; }; mkDriver = import ./nix/driver.nix { inherit pkgs kernelsmith; }; - bootLib = import ./nix/boot.nix { inherit pkgs; }; + bootLib = import ./nix/boot.nix { inherit pkgs qemuPkgs; }; # Per-cell record carrying everything the assembly needs. cellRecords = version: map diff --git a/nix/boot.nix b/nix/boot.nix index e619ac6..21df0cd 100644 --- a/nix/boot.nix +++ b/nix/boot.nix @@ -18,10 +18,14 @@ # -- deliberately, so this boots each kernel on the machine penguin will actually # run it on. A kernel that boots under some other qemu model is not the claim # anyone downstream needs. -{ pkgs }: +# `qemuPkgs` is a SEPARATE nixpkgs from `pkgs` -- see flake.nix's nixpkgs-qemu +# input. The kernel build's pin is 24.05, whose qemu is 8.2.7 and ships no +# loongarch64 EFI firmware, so that target could not be booted at all. +{ pkgs, qemuPkgs }: let inherit (pkgs) lib; + qemu = qemuPkgs.qemu; # target -> how penguin boots it. `null` means "no qemu machine exists", # which is DECLARED here rather than silently skipped. @@ -35,7 +39,18 @@ let powerpc64 = { system = "ppc64"; machine = "pseries"; cpu = "power9"; console = "hvc0"; }; powerpc64le = { system = "ppc64"; machine = "pseries"; cpu = "power9"; console = "hvc0"; }; riscv64 = { system = "riscv64"; machine = "virt"; console = "ttyS0"; }; - loongarch64 = { system = "loongarch64"; machine = "virt"; cpu = "la464"; console = "ttyS0"; }; + # loongarch64 needs two things no other target here does, and penguin + # supplies both -- see penguin_run.py's `-bios edk2-loongarch64-code.fd`. + # `mem`: qemu's virt machine refuses to start below 1G + # ("ram_size must be greater than 1G") + # `bios`: its kernel_fmt is vmlinuz.efi, a PE image, so the built-in + # loader rejects it ("The image is not ELF"). EFI firmware is + # what boots it. Booting the ELF vmlinux instead would pass this + # test while testing an image penguin never runs. + loongarch64 = { + system = "loongarch64"; machine = "virt"; cpu = "la464"; console = "ttyS0"; + mem = 2048; bios = "edk2-loongarch64-code.fd"; + }; x86_64 = { system = "x86_64"; machine = "pc"; console = "ttyS0"; }; # 32-bit powerpc: arch_registry.py records qemu_machine=None -- "no QEMU @@ -45,21 +60,37 @@ let powerpc = null; }; - # The kernel image each target ships, by extension of what kernelsDir copies. - # Globbed rather than tabulated: the artifact name varies by arch - # (zImage./bzImage./vmlinux./Image.) and duplicating that table here is one - # more thing to drift. + # The kernel image each target ships. Genuinely globbed -- an earlier version + # of this claimed to glob but actually hard-coded four names + # (bzImage/zImage/Image/vmlinux), and 6.13/loongarch64 ships + # `vmlinuz.efi.loongarch64`, so it failed as "no bootable image" while the + # kernel itself was fine. Every artifact is named `.`, so + # match on that suffix and rank the hits: prefer whatever the arch's boot + # wrapper produces, fall back to raw vmlinux. bootTest = { kernel, version, target, spec }: pkgs.runCommand "igloo-boot-${version}-${target}" { - nativeBuildInputs = [ pkgs.qemu ]; + nativeBuildInputs = [ qemu ]; meta.description = "boot smoke test for ${version}/${target}"; } '' + # Rank every *.${target} artifact; first match wins. vmlinux is last + # deliberately: where an arch ships both, the wrapped image is what + # penguin boots, so that is what this must test. img="" - for cand in ${kernel}/bzImage.${target} ${kernel}/zImage.${target} \ - ${kernel}/Image.${target} ${kernel}/vmlinux.${target}; do + for pat in bzImage zImage vmlinuz.efi vmlinuz uImage Image vmlinux; do + cand="${kernel}/$pat.${target}" [ -f "$cand" ] && { img="$cand"; break; } done + # Nothing ranked matched -- take any *.${target} regular file rather than + # failing, so a new arch's novel image name is a warning, not an outage. + if [ -z "$img" ]; then + for cand in ${kernel}/*.${target}; do + [ -f "$cand" ] || continue + case "$(basename "$cand")" in Module.symvers*|config*|*.map) continue;; esac + echo "warning: unranked image name $(basename "$cand") -- add it to the rank list" >&2 + img="$cand"; break + done + fi if [ -z "$img" ]; then echo "no bootable image for ${version}/${target} in ${kernel}" >&2 ls ${kernel} >&2 @@ -77,7 +108,8 @@ let timeout 120 qemu-system-${spec.system} \ -M ${spec.machine} \ ${lib.optionalString (spec ? cpu) "-cpu ${spec.cpu}"} \ - -m 256 -nographic -no-reboot \ + ${lib.optionalString (spec ? bios) "-bios ${qemu}/share/qemu/${spec.bios}"} \ + -m ${toString (spec.mem or 256)} -nographic -no-reboot \ -kernel "$img" \ -append "console=${spec.console} panic=1" \ < /dev/null > boot.log 2>&1 || true @@ -87,11 +119,19 @@ let # Two assertions, in increasing strength. # - # 1. The kernel banner. This alone is what nixdev_0.1.0's 4.10/x86_64 - # failed: it decompressed, printed "Booting the kernel.", and went - # silent forever. - if ! grep -q "Linux version" boot.log; then - echo "FAIL ${version}/${target}: no kernel banner -- it never started" >&2 + # 1. The kernel produced kernel log output at all. This is what + # nixdev_0.1.0's 4.10/x86_64 failed: it decompressed, printed + # "Booting the kernel.", and went silent forever. + # + # Matching the "Linux version" banner ALONE is too strict: on + # loongarch64 the EFI stub hands over after the console is set up, so + # the earliest printks -- the banner among them -- never reach the + # serial log, and a kernel that booted all the way to a root-fs panic + # was reported as never having started. A timestamped printk is the + # portable evidence of "the kernel is running"; the dead x86_64 image + # emitted none. + if ! grep -Eq "Linux version|^\[[ ]*[0-9]+\.[0-9]+\]" boot.log; then + echo "FAIL ${version}/${target}: no kernel output at all -- it never started" >&2 exit 1 fi From b69c4550938d3862fa0b9592ac0091070634cd23 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Fri, 14 Aug 2026 17:54:48 -0400 Subject: [PATCH 25/28] Re-lock kernelsmith to main, now that the k4-x86_64 binutils fix has landed Drops the temporary pin at the PR branch. Also picks up kernelsmith's $dev slimming (kernelsmith#4), which changes what an `M=` module build reads out of the kernel-devel tree -- igloo_driver is the consumer that exercises that, and its matrix is what confirms it. Boot matrix against kernelsmith main is byte-identical to the branch build (same /nix/store path): 18 ok, 1 declared SKIP. --- flake.lock | 6 +++--- flake.nix | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index da5a540..92af1ca 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1786743798, - "narHash": "sha256-M7F4Eu1ws3WKR34KxBm1CHdwARha7i5QCd0lKjxrs7w=", + "lastModified": 1786744385, + "narHash": "sha256-linrkYJ63mdakHdQStEPgUeII3Tn/NGKFBQVCs3QB0w=", "owner": "rehosting", "repo": "kernelsmith", - "rev": "a6b66282cccfcfa610a9c8d7d9fff5bb20906dfa", + "rev": "03d99e438ecab7a6ffb4d2a3072ef78269b2573c", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index afbb422..3035dc5 100644 --- a/flake.nix +++ b/flake.nix @@ -13,9 +13,6 @@ # the embedded-toolchains Docker image, whose toolchains were unversioned # `wget https://musl.cc/*-cross.tgz` downloads -- i.e. today's shipped # kernels have no recorded compiler identity. - # NB: flake.lock currently pins this AHEAD of main, to the k4-x86_64 - # binutils fix (kernelsmith#5) that 4.10/x86_64 needs to boot at all. - # Re-lock to main once that merges; the url needs no change. kernelsmith.url = "github:rehosting/kernelsmith"; nixpkgs.follows = "kernelsmith/nixpkgs"; From 0997bcca8e15e15bea24ec5a870866b88e77f395 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Fri, 14 Aug 2026 22:53:32 -0400 Subject: [PATCH 26/28] Drop the Docker build path and the submodules; rewrite the README The nix path builds every cell, boots every cell, and cuts the releases. Nothing reads the Docker path any more, so it goes: Dockerfile, .Dockerignore the embedded-toolchains image build.sh, _in_container_build.sh the in-container build .github/workflows/build.yml "Compile and release" .github/workflows/clear_cache.yml its Harbor kernel-cache janitor .gitmodules, linux/{4.10,6.13} the two fork branches patches/ replaced The submodules were already dead and already wrong: .gitmodules declared main_6.7 for linux/6.13, and the pin was a tree 89,775 commits from the branch it named (see nix/source.nix, patches/README.md). ONE capability came with build.sh rather than with Docker, so it is ported rather than dropped: `--config-only`, which cpp-assembles a config, runs savedefconfig, and diffs. nix/lint.nix does the same and is exposed as `.#config-lint--` and `.#config-lint`. It stays ADVISORY -- the Docker version discarded its own exit status, because savedefconfig prunes defaults and de-duplicates, so a readable #include- structured config never equals its savedefconfig form. Asserting on it would mean giving up the #include structure to satisfy the check. Comments across nix/ still name _in_container_build.sh where they are a faithful port of a specific step in it. Those are deliberate provenance -- they record WHY a piece of the build looks the way it does -- and the README now says so, and says where the file went. The README described the submodule workflow and pointed at panda-re/linux_builder for releases. Rewritten around the flake: quoting cell names, where source comes from, the three checks (and why boot-check is the one that matters), config linting, cutting a nixdev_* release, and who consumes this repo. It also records the two things the Docker path did silently: unversioned musl.cc toolchain downloads, so no kernel this repo ever released has a recorded compiler identity; and the hand-built x86_64-legacy toolchain pinned to binutils 2.30 whose unwritten reason was the R_X86_64_PLT32 boundary. Verified: `nix flake check` passes, and kernel-6.13-armel and boot-check resolve to the same store paths as before this commit. NOTE FOR SEQUENCING -- this removes the workflow that cuts non-prerelease v* releases, which two Docker-path consumers still pull: * penguin main pins linux_builder v3.6.5/kernels-latest.tar.gz * igloo_driver's Docker CI pulls releases/latest/kernel-devel-all.tar.gz Both keep working (existing releases stay downloadable) but neither can receive a NEW kernel release after this lands. penguin#932 and igloo_driver#100 are the nix-path replacements for those two consumers and should merge first. --- .Dockerignore | 3 - .github/workflows/build.yml | 426 ------------------------------ .github/workflows/clear_cache.yml | 30 --- .gitmodules | 8 - Dockerfile | 12 - README.md | 129 +++++++-- _in_container_build.sh | 409 ---------------------------- build.sh | 181 ------------- flake.nix | 18 ++ linux/4.10 | 1 - linux/6.13 | 1 - nix/lint.nix | 83 ++++++ 12 files changed, 208 insertions(+), 1093 deletions(-) delete mode 100644 .Dockerignore delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/clear_cache.yml delete mode 100644 .gitmodules delete mode 100644 Dockerfile delete mode 100755 _in_container_build.sh delete mode 100755 build.sh delete mode 160000 linux/4.10 delete mode 160000 linux/6.13 create mode 100644 nix/lint.nix diff --git a/.Dockerignore b/.Dockerignore deleted file mode 100644 index 76dff14..0000000 --- a/.Dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!linux/* -linux/.git diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index a0340d8..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,426 +0,0 @@ -name: Compile and release - -on: - # Releases are cut on merges into main and on dev_* tags (auto-versioned - # below, like rehosting/penguin). NOTE: we deliberately do NOT trigger on - # 'v*' tags — the release step now *creates* v* tags via version-increment, - # so a 'v*' push trigger would make every release re-trigger itself. - push: - branches: - - main - tags: - - 'dev_*' - - pull_request: - branches: - - main - - workflow_dispatch: - -# Serialize per-ref so two main merges (or a merge + dev_* tag) can't race the -# auto-version step and compute/claim the same vX.Y.Z tag. PR runs cancel their -# own superseded runs; release (push) runs are never cancelled. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - prebuild: - runs-on: rehosting-arc - outputs: - targets: ${{ steps.find_targets.outputs.targets }} - versions: ${{ steps.find_targets.outputs.versions }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - ref: ${{ github.ref }} - - - name: Log git revisions of all linux projects - run: | - echo "Main repo revision:" && git rev-parse HEAD - echo - echo "Submodule revisions:" && git submodule status - echo - echo "Full submodule SHAs:" && git submodule foreach 'echo $name: $(git rev-parse HEAD)' - - # NOTE: kernel-source preparation used to live here and wrote to the shared - # hostPath on prebuild's node, which forced every build job onto that same - # node. It now happens per-node inside each build job (see "Ensure kernel - # sources on this node" below), so prebuild only needs to discover the - # build matrix -- nothing node-specific. - - - name: Find valid targets and versions sets - id: find_targets - run: | - TARGETS_SET=() - VERSIONS_SET=() - for version_dir in configs/*/; do - version=$(basename "$version_dir") - VERSIONS_SET+=("$version") - for config_file in "$version_dir"*; do - if [[ -f "$config_file" && ! "$config_file" =~ \.inc$ && ! "$config_file" =~ \.unused$ ]]; then - target=$(basename "$config_file") - TARGETS_SET+=("$target") - fi - done - done - UNIQUE_TARGETS=$(printf "%s\n" "${TARGETS_SET[@]}" | sort -u | awk '{printf "\"%s\",",$0}' | sed 's/,$//') - UNIQUE_VERSIONS=$(printf "%s\n" "${VERSIONS_SET[@]}" | sort -u | awk '{printf "\"%s\",",$0}' | sed 's/,$//') - TARGETS_OUTPUT="[${UNIQUE_TARGETS}]" - VERSIONS_OUTPUT="[${UNIQUE_VERSIONS}]" - echo "targets=$TARGETS_OUTPUT" >> $GITHUB_OUTPUT - echo "versions=$VERSIONS_OUTPUT" >> $GITHUB_OUTPUT - echo "Found valid targets: $TARGETS_OUTPUT" - echo "Found valid versions: $VERSIONS_OUTPUT" - - # Build the kernel_builder image exactly once per run, push it to Harbor - # under an immutable per-commit tag, and let every matrix build job pull it. - # - # Why a dedicated job (instead of building inside each matrix job): - # * The image is now target-agnostic (TARGET=latest bundles every - # cross-toolchain), so all 13 build jobs would otherwise rebuild the SAME - # multi-GB image. setup-buildx-action's docker-container driver keeps its - # own cache store, separate from the shared per-node Docker daemon, so the - # daemon's warm-image reuse does NOT cover a buildx `FROM` base -- every - # job re-pulled the full all-arch base. Building once here fixes that. - # * A single writer to the `:all_cache` registry cache means the cache - # actually accumulates run-to-run instead of 13 jobs racing to overwrite - # one ref. - # * An immutable `:` tag (vs a mutable `:latest`) is safe on the shared - # daemon's single image store -- concurrent jobs/PRs can't clobber each - # other's tag (same lesson as rehosting/penguin #893). - build-image: - runs-on: rehosting-arc - if: github.event.pull_request.draft == false - steps: - - uses: actions/checkout@v4 - - - name: Trust Harbor's self-signed certificate - run: | - echo "Fetching certificate from ${{ secrets.REHOSTING_ARC_REGISTRY }}" - openssl s_client -showcerts -connect ${{ secrets.REHOSTING_ARC_REGISTRY }}:443 < /dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /usr/local/share/ca-certificates/harbor.crt > /dev/null - sudo update-ca-certificates - - - name: Log in to Rehosting Arc Registry - uses: docker/login-action@v3 - with: - registry: ${{secrets.REHOSTING_ARC_REGISTRY}} - username: ${{ secrets.REHOSTING_ARC_REGISTRY_USER }} - password: ${{ secrets.REHOSTING_ARC_REGISTRY_PASSWORD }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - # See the note in the (removed) per-job build step / penguin c35bedc5: - # don't pin moby/buildkit:master -- it regressed on the kernel-5.4 - # runners (can't mask /proc/acpi). - # - # Relying on setup-buildx-action's *default* image is no longer enough: - # the default has since moved onto a buildkit carrying the same - # regression, and this workflow started failing with - # - # can't mask dir "/proc/acpi": mount src=tmpfs, dst=/proc/acpi, - # flags=MS_RDONLY, data=nr_blocks=1,nr_inodes=1: invalid argument - # - # main has not run since 2026-07-28 so it has not caught up with the - # drift yet. Pin the last known-good buildkit explicitly, matching the - # pin igloo-dev already applies in its source-nightly publish. - driver-opts: | - image=moby/buildkit:v0.30.0 - network=host - buildkitd-config-inline: | - [registry."${{ secrets.REHOSTING_ARC_REGISTRY }}"] - insecure = true - http = true - - - name: Build and push kernel_builder image - uses: docker/build-push-action@v6 - with: - context: . - push: true - # Immutable per-commit tag -- matrix jobs pull this exact ref. - tags: | - ${{ secrets.REHOSTING_ARC_REGISTRY }}/rehosting/linux_builder:${{ github.sha }} - # TARGET=latest builds FROM the all-arch embedded-toolchains:latest so - # the single built image carries every cross-toolchain and one image - # serves every matrix target. - build-args: | - REGISTRY=${{ secrets.REHOSTING_ARC_REGISTRY }}/proxy - TARGET=latest - # Single shared build cache, written by this one job (no matrix race). - cache-from: | - type=registry,ref=${{secrets.REHOSTING_ARC_REGISTRY}}/rehosting/linux_builder:all_cache,mode=max - cache-to: | - type=registry,ref=${{secrets.REHOSTING_ARC_REGISTRY}}/rehosting/linux_builder:all_cache,mode=max - - build: - needs: [prebuild, build-image] - runs-on: rehosting-arc - if: github.event.pull_request.draft == false - - strategy: - matrix: - target_version: ${{ fromJSON(needs.prebuild.outputs.targets) }} - - env: - # The image built once by build-image; pulled (warm on the shared daemon - # after the first job lands on a node) instead of rebuilt per target. - KERNEL_BUILDER_IMAGE: ${{ secrets.REHOSTING_ARC_REGISTRY }}/rehosting/linux_builder:${{ github.sha }} - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - ref: ${{ github.ref }} - - - name: Extract target and version - id: extract - run: | - TARGET="${{ matrix.target_version }}" - echo "target=$TARGET" >> $GITHUB_OUTPUT - echo "Building target: $TARGET" - - - name: Ensure kernel sources on this node - id: sources - run: | - set -eux - SHARED="/home/runner/_shared" - BASE_REPO_DIR="$SHARED/linux" - BASE_REPO_URL="https://github.com/rehosting/linux" - SRC_PARENT="$SHARED/linux_sources" - mkdir -p "$SRC_PARENT" - - # Cache key = the pinned linux/ submodule SHAs. The kernel source - # only changes when a submodule is bumped, so a node reuses its tree - # across runs and only re-populates on a real SHA change. - KEY=$(git submodule status | awk '{gsub(/^[-+U ]+/,"",$1); print $1}' | sort | sha1sum | cut -c1-12) - SRC_ROOT="$SRC_PARENT/$KEY" - echo "kernel_src=$SRC_ROOT/linux" >> "$GITHUB_OUTPUT" - - # Per-node arbitration: whichever build job lands on a node first - # populates that node's copy; the others block on the lock, then see - # .ready and skip. flock on the shared fs is the right primitive -- - # GH 'concurrency' is cross-node and can't serialize same-node jobs. - # This also avoids the cp/rsync races the single shared dir hit. - exec 9>"$SRC_PARENT/.populate.lock" - flock 9 - - if [ ! -e "$SRC_ROOT/.ready" ]; then - echo "Populating kernel sources for key $KEY on $(hostname)" - # Node-local bare clone so submodule update pulls over fast local - # file:// instead of hitting GitHub once per submodule per job. - if [ ! -d "$BASE_REPO_DIR" ]; then - git clone --bare "$BASE_REPO_URL" "$BASE_REPO_DIR" - git -C "$BASE_REPO_DIR" config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" - fi - git -C "$BASE_REPO_DIR" fetch origin --prune --tags --force - - rm -rf "$SRC_ROOT.tmp" - mkdir -p "$SRC_ROOT.tmp" - # Copy the (submodule-less) superproject checkout, then init the - # kernel submodules into it from the local bare clone. - cp -a "$GITHUB_WORKSPACE/." "$SRC_ROOT.tmp/" - ( cd "$SRC_ROOT.tmp" - sed -i "s|url = https://github.com/rehosting/linux.git|url = file://$BASE_REPO_DIR|g" .gitmodules - git submodule sync - GIT_ALLOW_PROTOCOL=file:https git submodule update --init --depth 1 --jobs 2 ) - # Publish atomically so a partial tree is never seen as ready. - rm -rf "$SRC_ROOT" - mv "$SRC_ROOT.tmp" "$SRC_ROOT" - touch "$SRC_ROOT/.ready" - else - echo "Reusing cached kernel sources for key $KEY on $(hostname)" - fi - # Record last-use so the GC below doesn't reap an actively-reused tree. - touch "$SRC_ROOT" - - # Best-effort GC: drop keyed trees (and stale .tmp dirs) untouched for - # 14 days so the node-local cache can't grow unbounded across bumps. - find "$SRC_PARENT" -mindepth 1 -maxdepth 1 -type d ! -path "$SRC_ROOT" -mtime +14 \ - -exec rm -rf {} + 2>/dev/null || true - - flock -u 9 - - - name: Trust Harbor's self-signed certificate - run: | - echo "Fetching certificate from ${{ secrets.REHOSTING_ARC_REGISTRY }}" - openssl s_client -showcerts -connect ${{ secrets.REHOSTING_ARC_REGISTRY }}:443 < /dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /usr/local/share/ca-certificates/harbor.crt > /dev/null - sudo update-ca-certificates - - - name: Log in to Rehosting Arc Registry - uses: docker/login-action@v3 - with: - registry: ${{secrets.REHOSTING_ARC_REGISTRY}} - username: ${{ secrets.REHOSTING_ARC_REGISTRY_USER }} - password: ${{ secrets.REHOSTING_ARC_REGISTRY_PASSWORD }} - - - name: Pull kernel_builder image - run: | - set -eux - # Built once by the build-image job. On the shared per-node Docker - # daemon the first matrix job to land on a node pulls the layers; every - # later job on that node finds them already present (warm reuse). No - # per-job buildx build anymore. - docker pull "$KERNEL_BUILDER_IMAGE" - - - name: Build Kernel for ${{ matrix.target_version }} - run: | - set -eux - TARGET="${{ matrix.target_version }}" - VERSIONS_JSON='${{ needs.prebuild.outputs.versions }}' - # Per-node kernel sources prepared by the "Ensure kernel sources on - # this node" step above (node-agnostic: no dependency on prebuild's - # node). - SOURCES_DIR="${{ steps.sources.outputs.kernel_src }}" - - if [ -z "$VERSIONS_JSON" ] || [ "$VERSIONS_JSON" = "[]" ]; then - VERSIONS="" - else - VERSIONS=$(echo "$VERSIONS_JSON" | jq -r '.[]' | xargs) - fi - - # Node-shared, persistent compiler cache. Lives under the same - # /home/runner/_shared mount the kernel sources use (mirrored into the - # shared Docker daemon by kube#15), so mounting it into the build - # container needs no extra plumbing. One dir shared by every - # target/version on the node -- ccache is content-keyed and dedups, so - # a warm cache turns the ~15-20 min from-scratch compile into a mostly- - # cache-hit rebuild. _in_container_build.sh enables ccache iff CCACHE_DIR - # is set (no-op otherwise). - CCACHE_HOST_DIR="/home/runner/_shared/linux_builder_ccache" - mkdir -p "$CCACHE_HOST_DIR" - - # Use the prebuilt image (--image) and mount the stable source - # directory instead of the run-specific one, plus the shared ccache. - ./build.sh --image "$KERNEL_BUILDER_IMAGE" --targets "$TARGET" ${VERSIONS:+--versions "$VERSIONS"} \ - --extra-docker-opts "-v $SOURCES_DIR:/app/linux -v $CCACHE_HOST_DIR:/ccache -e CCACHE_DIR=/ccache -e CCACHE_MAXSIZE=15G" - - # Stage per-target outputs in the workspace; they are handed to the - # aggregate job via workflow artifacts (below) instead of a shared - # hostPath, so build and aggregate need not run on the same node. - mkdir -p build-output - mv kernels-latest.tar.gz build-output/kernels-latest-${TARGET}.tar.gz - mv kernel-devel-all.tar.gz build-output/kernel-devel-all-${TARGET}.tar.gz - - - name: Upload per-target kernel artifacts - uses: actions/upload-artifact@v4 - with: - name: kernels-${{ matrix.target_version }} - path: build-output/ - retention-days: 1 - - aggregate: - # Runs on releases (push to main / dev_* tag) AND on manual dispatch so the - # full download+combine round-trip can be exercised without cutting a - # release (the publish step below is gated to push events only). Never runs - # for pull_request. - if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' - needs: build - runs-on: rehosting-arc - env: - MATRIX_VERSIONS: ${{ toJSON(needs.build.strategy.matrix.version) }} - permissions: - actions: write - contents: write - steps: - - name: Trust Harbor's self-signed certificate - run: | - echo "Fetching certificate from ${{ secrets.REHOSTING_ARC_REGISTRY }}" - openssl s_client -showcerts -connect ${{ secrets.REHOSTING_ARC_REGISTRY }}:443 < /dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /usr/local/share/ca-certificates/harbor.crt > /dev/null - sudo update-ca-certificates - - name: Log in to Rehosting Arc Registry - uses: docker/login-action@v3 - with: - registry: ${{secrets.REHOSTING_ARC_REGISTRY}} - username: ${{ secrets.REHOSTING_ARC_REGISTRY_USER }} - password: ${{ secrets.REHOSTING_ARC_REGISTRY_PASSWORD }} - - - name: Download all per-target kernel artifacts - uses: actions/download-artifact@v4 - with: - pattern: kernels-* - path: build-output - merge-multiple: true - - - name: Combine all kernels into a single archive - run: | - set -eux - # Artifacts downloaded by the step above land here (workspace-local, - # node-agnostic) instead of the old /home/runner/_shared/runs hostPath. - BUILD_OUTPUT="$GITHUB_WORKSPACE/build-output" - - echo "[DEBUG] Listing available per-target kernel archives:" - find "$BUILD_OUTPUT" -maxdepth 1 -name "kernels-latest-*.tar.gz" -print || true - - rm -rf combined-kernels && mkdir combined-kernels - - for archive in "$BUILD_OUTPUT"/kernels-latest-*.tar.gz; do - [ -e "$archive" ] || continue - echo "[DEBUG] Extracting $archive into combined-kernels" - tar -xzf "$archive" -C combined-kernels - done - - echo "[DEBUG] Contents of combined-kernels after extraction:" - find combined-kernels || true - - # Merge osi.config for every detected version directory - if [ -d combined-kernels/kernels ]; then - for vdir in combined-kernels/kernels/*; do - [ -d "$vdir" ] || continue - version=$(basename "$vdir") - echo "[DEBUG] Merging osi.config for version $version" - { - for archive in "$BUILD_OUTPUT"/kernels-latest-*.tar.gz; do - [ -e "$archive" ] || continue - tar -O -xf "$archive" "kernels/$version/osi.config" 2>/dev/null || true - done - } > "combined-kernels/kernels/$version/osi.config" - done - fi - - tar -czvf kernels-latest.tar.gz -C combined-kernels . - - - name: Aggregate all kernel-devel artifacts - run: | - set -eux - # Artifacts downloaded by the step above land here (workspace-local, - # node-agnostic) instead of the old /home/runner/_shared/runs hostPath. - BUILD_OUTPUT="$GITHUB_WORKSPACE/build-output" - - mkdir -p kernel-devel-all - for archive in "$BUILD_OUTPUT"/kernel-devel-all-*.tar.gz; do - [ -e "$archive" ] || continue - echo "[DEBUG] Extracting $archive into kernel-devel-all/" - tar -xzf "$archive" -C kernel-devel-all - done - tar -czvf kernel-devel-all.tar.gz -C kernel-devel-all . - - # Auto-version like rehosting/penguin: query the GitHub API for the latest - # release and increment. On main this yields a clean vX.Y.Z; on a non-main - # ref (a dev_* tag) version-increment appends a -pre suffix. - - name: Get next version - id: version - uses: reecetech/version-increment@2023.10.1 - with: - use_api: true - - - name: Create and publish release - # Only publish on real release events (main merge / dev_* tag). A manual - # workflow_dispatch still runs everything above to validate the pipeline - # but does not create a release. - if: github.event_name == 'push' - uses: softprops/action-gh-release@v1 - with: - files: | - kernels-latest.tar.gz - kernel-devel-all.tar.gz - token: ${{ secrets.GITHUB_TOKEN }} - tag_name: ${{ steps.version.outputs.v-version }} - name: Release ${{ steps.version.outputs.v-version }} - generate_release_notes: true - # dev_* tags publish as prereleases; main merges as full releases. - prerelease: ${{ startsWith(github.ref, 'refs/tags/dev_') }} - # (Removed the per-run /home/runner/_shared/runs cleanup: outputs now flow - # through workflow artifacts, which expire on their own retention, and the - # workspace build-output dir is ephemeral.) diff --git a/.github/workflows/clear_cache.yml b/.github/workflows/clear_cache.yml deleted file mode 100644 index 0c16273..0000000 --- a/.github/workflows/clear_cache.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Clear kernel cache - -on: - workflow_dispatch: - -jobs: - clear-cache: - runs-on: rehosting-arc - steps: - - name: Trust Harbor's self-signed certificate - run: | - echo "Fetching certificate from ${{ secrets.REHOSTING_ARC_REGISTRY }}" - openssl s_client -showcerts -connect ${{ secrets.REHOSTING_ARC_REGISTRY }}:443 < /dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /usr/local/share/ca-certificates/harbor.crt > /dev/null - sudo update-ca-certificates - - uses: oras-project/setup-oras@v1.2.3 - - name: Log in to Rehosting Arc Registry - uses: docker/login-action@v3 - with: - registry: ${{ secrets.REHOSTING_ARC_REGISTRY }} - username: ${{ secrets.REHOSTING_ARC_REGISTRY_USER }} - password: ${{ secrets.REHOSTING_ARC_REGISTRY_PASSWORD }} - - name: Delete all kernel cache images - run: | - set -e - repo="${{ secrets.REHOSTING_ARC_REGISTRY }}/rehosting/linux_builder_cache" - tags=$(oras repo tags $repo) - for tag in $tags; do - echo "Deleting $repo:$tag" - oras repo rm $repo:$tag || echo "Failed to delete $repo:$tag" - done diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index c088407..0000000 --- a/.gitmodules +++ /dev/null @@ -1,8 +0,0 @@ -[submodule "linux_4.10"] - path = linux/4.10 - url = https://github.com/rehosting/linux.git - branch = main_4.10 -[submodule "linux_6.7"] - path = linux/6.13 - url = https://github.com/rehosting/linux.git - branch = main_6.7 diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a56fae9..0000000 --- a/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -ARG REGISTRY="docker.io" -ARG TARGET="latest" -FROM ${REGISTRY}/rehosting/embedded-toolchains:${TARGET} - -RUN apt-get update && apt-get install -y pkg-config - -# Get panda for kernelinfo_gdb. Definitely a bit overkill to pull the whole repo -RUN mkdir /extract_kernelinfo && \ - wget https://raw.githubusercontent.com/panda-re/panda-ng/refs/heads/main/plugins/osi_linux/utils/kernelinfo_gdb/extract_kernelinfo.py -O /extract_kernelinfo/extract_kernelinfo.py && \ - wget https://raw.githubusercontent.com/panda-re/panda-ng/refs/heads/main/plugins/osi_linux/utils/kernelinfo_gdb/run.sh -O /extract_kernelinfo/run.sh && \ - chmod +x /extract_kernelinfo/run.sh - diff --git a/README.md b/README.md index e1e1a0c..1c0f04d 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,130 @@ linux\_builder ==== +The IGLOO kernels: pristine upstream release tarballs plus an explicit IGLOO +patch series, cross-built by [kernelsmith][ks] for every target penguin +emulates. -Standalone repo for building a linux source tree with CI. This design keeps CI infrastructure, build scripts, and configs -out of the original tree making it easy to see the difference and port it to other kernel versions. +Two kernel versions (`4.10`, `6.13`) across up to eleven targets — 19 buildable +cells in all. Each cell ships a boot image, a `vmlinux`, a minimal kernel-devel +tree, `perf`, and the OSI/COSI analysis artifacts penguin needs. +[ks]: https://github.com/rehosting/kernelsmith -## Usage +## Quick start -### Update submodule +Everything is a Nix flake output. There is no container to build first. +```sh +nix build .#packages.x86_64-linux."kernel-6.13-armel" # one cell +nix build .#all # every buildable cell +nix build .#kernels # the payload as a tree +nix build .#kernels-latest # ...and as a tarball ``` -cd linux -# Checkout desired branch, pull, etc -git checkout master -git pull +Cell names contain a `.`, which Nix parses as an attribute-path separator, so +**the quoting above is mandatory** — `.#kernel-6.13-armel` does not resolve. -# Go back to project root -cd .. +## Where the source comes from -# Add new commit -git commit -am "Updated linux to ..." +Not from a submodule. `patches/` carries the IGLOO delta as an ordered series +applied to a pristine kernel.org tarball, pinned by hash in `patches/base.json`. +See [`patches/README.md`](patches/README.md) for the layout, how much is really +shared between versions, and how to add or refresh a patch. -git push +To prove a series still reproduces the fork branch it replaced: + +```sh +./scripts/verify-series.sh 4.10 ``` +`scripts/import-series.sh` and `scripts/export-series.sh` move patches between +this repo and a fork branch. + +## Checks + +| command | what it proves | +|---|---| +| `nix build .#boot-check` | **every kernel actually boots** under the qemu machine penguin runs it on | +| `nix build .#shape-check` | each artifact's ELF class, byte order and machine match its target name | +| `nix flake check` | the above, plus evaluation of every output | -### Make new release +`boot-check` is the one that matters most, and it is newer than the rest. +`nixdev_0.1.0` shipped a `4.10/x86_64` kernel that compiled, linked, packaged, +had the correct ELF shape and was the same size as the Docker build's — and +printed nothing before dying. Every other gate passed it; it was caught three +repos downstream in penguin's integration tests. Booting it is the only check +that would have said so. See [`nix/boot.nix`](nix/boot.nix). -To make a new release, tag the repo with a `v*.*` string and push it: +32-bit `powerpc` is boot-tested as an explicit SKIP: penguin's +`arch_registry.py` records no qemu machine for it, so it is unbootable by +declaration rather than by oversight. + +## Modifying configs +Configs live in `configs//`, with shared fragments pulled in by +`#include` (`all-common.inc`, `arm-common.inc`, ...). They are assembled with +`cpp -P -undef` and then `olddefconfig`. + +After changing one, look at its lint: + +```sh +nix build .#packages.x86_64-linux."config-lint-6.13-armel" # one cell +nix build .#config-lint # every cell ``` -git tag v3.1 -git push origin v3.1 + +Each produces `config__.linted` (the `savedefconfig` form) and +a `.diff` against the assembled config. **This is advisory, not a gate.** +`savedefconfig` prunes options that are already the arch default and +de-duplicates, so a readable config fragment and its savedefconfig form never +match — the diff tells you which of your lines were redundant, and that is all +it is for. Turning it into an assertion would mean replacing the `#include` +structure with savedefconfig output, which is a bad trade. + +This replaces `./build.sh --config-only`, which did the same thing and likewise +discarded its own exit status. + +## Releases + +Pushing a `nixdev_*` tag runs the full 19-cell matrix, boot-tests it, publishes +`kernels-latest.tar.gz` + `kernel-devel-all.tar.gz` as a **prerelease**, and +pushes every cell to the `rehosting-tools` Cachix — which is what lets +downstream repos substitute these kernels instead of cross-building them. + +```sh +git tag -a nixdev_0.1.2 -m "..." && git push origin nixdev_0.1.2 ``` -The CI jobs will then build your release and make it available at `https://github.com/panda-re/linux_builder/releases/download//kernels-latest.tar.gz` +The tag glob is anchored, so `nixdev_*` and the old `dev_*` never collide. -## Modifying configs -If you'd like to add a given option or set of options to all configs, you can add it to [configs/all-common.inc](configs/all-common.inc). +## Consumers + +- **penguin** takes this repo as a *flake input* and stages `.#kernels` + directly. The tarball is kept for other consumers, but the flake is the seam + that records **which compiler built these kernels** — a tarball pin cannot. +- **igloo_driver** builds `igloo.ko` against the kernel *derivations* here, so + a mismatched (kernel, module) pair is not expressible. Note that a nix-built + `kernel-devel-all.tar.gz` is **not** usable from a non-nix container: it ships + host tools linked against `/nix/store`. + +## History: the Docker path + +This repo used to build inside `rehosting/embedded-toolchains` via `build.sh`, +`_in_container_build.sh` and a `Dockerfile`, with the kernel source arriving as +two git submodules. All of that is removed; it lives in git history. + +Comments throughout `nix/` name `_in_container_build.sh` where the Nix code is a +faithful port of a specific step in it. Those references are deliberate +provenance — they say *why* a piece of the build looks the way it does — and +point at the file as it existed before its removal. + +Two things worth knowing about what that path did, because both were silent: -## Linting configs -Before commiting any config update you MUST lint your change by running `./build.sh --config-only`. You can specify architectures to lint with the `--targets` flag, e.g., `./build.sh --config-only --targets "armel mipel"`. If the lint fails, build.sh will exit with non-zero status and print a diff containing the problems. +- Its toolchains were unversioned `wget musl.cc/*-cross.tgz` downloads, so + **every kernel this repo has ever released has no recorded compiler + identity.** kernelsmith exists to fix that. +- It hard-coded a hand-built `x86_64-legacy` toolchain for `(x86_64, 4.10)` + alone, pinning binutils 2.30. The reason was never written down. It is that + binutils ≥ 2.31 emits `R_X86_64_PLT32`, which Linux only learned in 4.16 — + and that omission is exactly what shipped a dead kernel in `nixdev_0.1.0`. + It is now a resolver decision in kernelsmith with the reason attached. diff --git a/_in_container_build.sh b/_in_container_build.sh deleted file mode 100755 index 9e380e7..0000000 --- a/_in_container_build.sh +++ /dev/null @@ -1,409 +0,0 @@ -#!/bin/bash - -set -eu - -# Re-own bind-mounted outputs to the host caller so artifacts/cache aren't left -# root-owned on the host. Runs as root inside the container via an EXIT trap so -# it covers every exit path (including the early kernel-devel exit). Gated on a -# non-root HOST_UID, so CI (which may run as root / not set these) is unaffected. -on_exit() { - # ccache summary on every exit path (there are several early exits: - # config-only, menuconfig, diffdefconfig, kernel-devel). No-op unless ccache - # is enabled. - if [ -n "${CCACHE_DIR:-}" ]; then - echo "ccache stats after build:" - ccache -s 2>/dev/null | sed 's/^/ ccache(end): /' || true - fi - if [ -n "${HOST_UID:-}" ] && [ "${HOST_UID}" != "0" ]; then - chown -R "${HOST_UID}:${HOST_GID:-$HOST_UID}" \ - /tmp/build \ - /app/kernels-latest.tar.gz \ - /app/kernel-devel-all.tar.gz 2>/dev/null || true - fi -} -trap on_exit EXIT - -# We want to build linux for each of our targets and versions using the config files. Linux is in /app/linux/[version] -# while our configs are at configs/[version]/[arch]. We need to set the ARCH and CROSS_COMPILE variables -# and put the binaries in /app/binaries - -# Get options from build.sh -CONFIG_ONLY="$1" -VERSIONS="$2" -TARGETS="$3" -NO_STRIP="$4" -MENU_CONFIG="$5" -DIFFDEFCONFIG="$6" -KERNEL_DEVEL="${7:-false}" - -echo "Config only: $CONFIG_ONLY" -echo "Versions: $VERSIONS" -echo "Targets: $TARGETS" -echo "No strip: $NO_STRIP" -echo "menuconfig: $MENU_CONFIG" -echo "diffdefconfig: $DIFFDEFCONFIG" - -# Optional compiler cache. Enabled purely by the presence of CCACHE_DIR (set by -# the caller, e.g. CI mounts a node-shared persistent dir). When unset, CC_PREFIX -# stays empty and every `CC=` below expands to exactly the kernel default -# ($(CROSS_COMPILE)gcc), so behaviour is identical to before. ccache is content- -# keyed, so it survives `mrproper`/clean and stays correct across config and -# source bumps; concurrent build jobs sharing one CCACHE_DIR are safe (ccache -# locks internally). The container paths ($O=/tmp/build/..., src /app/linux) are -# stable across runs, which is what lets objects hit. -CC_PREFIX="" -if [ -n "${CCACHE_DIR:-}" ]; then - mkdir -p "$CCACHE_DIR" - export CCACHE_DIR - export CCACHE_MAXSIZE="${CCACHE_MAXSIZE:-15G}" - export CCACHE_COMPRESS=1 - # __DATE__/__TIME__ and header mtimes churn across a fresh checkout; treat - # them as sloppy so unchanged translation units still hit. - export CCACHE_SLOPPINESS="${CCACHE_SLOPPINESS:-time_macros,include_file_mtime,include_file_ctime,file_stat_matches}" - ccache -M "$CCACHE_MAXSIZE" >/dev/null 2>&1 || true - CC_PREFIX="ccache " - echo "ccache enabled: dir=$CCACHE_DIR maxsize=$CCACHE_MAXSIZE" - ccache -s 2>/dev/null | sed 's/^/ ccache(start): /' || true -fi - -# Array to keep track of child processes -declare -a pids - -# Function to get cross-compiler prefix -get_cc() { - local arch=$1 - local version=$2 - local abi="" - - # Clear only CFLAGS; do not clear KCFLAGS or KBUILD_CFLAGS here - unset CFLAGS - - if [[ $arch == *"arm64"* ]]; then - abi="" - arch="aarch64" - elif [[ $arch == *"arm"* ]]; then - abi="eabi" - if [[ $arch == *"eb"* ]]; then - export CFLAGS="-mbig-endian" - export KCFLAGS="${KCFLAGS:-} -mbig-endian" - fi - arch="arm" - fi - - if [[ $arch == *"loongarch"* ]]; then - echo "/opt/cross/loongarch64-linux-gcc-cross/bin/loongarch64-unknown-linux-gnu-" - elif [[ $arch == *"powerpc"* ]] && [ "$version" = "4.10" ]; then - echo "powerpc64-linux-gnu-" - elif [[ $arch == *"powerpc"* ]] && [ "$version" != "4.10" ]; then - echo "/opt/cross/powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-" - elif [ "$arch" = "x86_64" ] && [ "$version" = "4.10" ]; then - echo "/opt/cross/x86_64-legacy/bin/x86_64-linux-musl-" - elif [[ $arch == "riscv64" ]]; then - # riscv64 linux-musl seems to run out of memory on linking so we switched - # to the glibc version - echo "/usr/bin/riscv64-linux-gnu-" - else - echo "/opt/cross/${arch}-linux-musl${abi}/bin/${arch}-linux-musl${abi}-" - fi -} - -for VERSION in $VERSIONS; do -make -C /app/linux/$VERSION mrproper -for TARGET in $TARGETS; do - unset KCFLAGS KBUILD_CFLAGS HOSTCFLAGS - BUILD_TARGETS="vmlinux" - if [ $TARGET == "armel" ]; then - BUILD_TARGETS="vmlinux zImage" - elif [ $TARGET == "arm64" ]; then - BUILD_TARGETS="vmlinux Image.gz" - elif [ $TARGET == "x86_64" ]; then - BUILD_TARGETS="vmlinux bzImage" - elif [ $TARGET == "loongarch64" ]; then - BUILD_TARGETS="vmlinux vmlinuz.efi" - elif [ $TARGET == "riscv32" ]; then - BUILD_TARGETS="vmlinux Image" - elif [ $TARGET == "riscv64" ]; then - BUILD_TARGETS="vmlinux Image" - fi - - # Set short_arch based on TARGET - short_arch=$(echo $TARGET | sed -E 's/(.*)(e[lb]|eb64)$/\1/') - if [ "$short_arch" == "mips64" ]; then - short_arch="mips" - elif [ "$short_arch" == "loongarch64" ]; then - short_arch="loongarch" - elif [[ "$short_arch" == "powerpc64" || "$short_arch" == "powerpc64le" || "$short_arch" == "powerpcle" ]]; then - short_arch="powerpc" - elif [ "$short_arch" == "riscv64" ]; then - short_arch="riscv" - elif [ "$short_arch" == "riscv32" ]; then - short_arch="riscv" - fi - - # Apply extra warning suppressions only for old kernels - if [[ "$VERSION" == "4.10" && "$TARGET" == powerpc* ]]; then - echo "Applying global Wno-error for $VERSION $TARGET" - extra_wnoerr="-Wno-error -Wno-error=stringop-truncation -Wno-error=format-truncation -Wno-error=maybe-uninitialized -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=missing-attributes" - export KCFLAGS="${KCFLAGS:-} $extra_wnoerr" - export KBUILD_CFLAGS="${KBUILD_CFLAGS:-} $extra_wnoerr" - export HOSTCFLAGS="${HOSTCFLAGS:-} -Wno-error" - fi - - echo "Building $BUILD_TARGETS for $TARGET" - - if [ ! -f "/app/configs/${VERSION}/${TARGET}" ]; then - echo "No config for $TARGET" avaiable for version $VERSION. - # Only exit if there is a single version being built - if [ "$(echo $VERSIONS | wc -w)" -eq 1 ]; then - echo "Since only one version is being built, exiting." - exit 1 - fi - echo "Assuming this is fine in multi-version builds, skipping." - continue - fi - mkdir -p "/tmp/build/${VERSION}/${TARGET}" - cpp -P -undef "/app/configs/${VERSION}/${TARGET}" -o "/tmp/build/${VERSION}/${TARGET}/.config" - - - # If updating configs, lint them with kernel first! This removes default options and duplicates. - if $CONFIG_ONLY; then - echo "Linting config for $TARGET to config_${VERSION}_${TARGET}.linted" - make -C /app/linux/$VERSION ARCH=${short_arch} CROSS_COMPILE=$(get_cc $TARGET $VERSION) O=/tmp/build/${VERSION}/${TARGET}/ savedefconfig - cp "/tmp/build/${VERSION}/${TARGET}/defconfig" "/app/config_${VERSION}_${TARGET}.linted" - # Informational only: savedefconfig prunes defaults/dupes so the configs - # always differ. Don't let the non-zero exit abort the (set -e) loop, or - # only the first target ever gets linted in a multi-target --config-only run. - diff -u <(sort /tmp/build/${VERSION}/${TARGET}/.config) <(sort /tmp/build/${VERSION}/${TARGET}/defconfig | sed '/^[ #]/d') || true - else - echo "Building kernel for $TARGET" - # 2. Inject missing label for x86_64 R_X86_64_PLT32 backport bug - if [[ "$VERSION" == "4.10" && "$TARGET" == "x86_64" ]]; then - grep -q "invalid_relocation:" /app/linux/$VERSION/arch/x86/kernel/module.c || \ - sed -i 's/overflow:/invalid_relocation:\n\treturn -ENOEXEC;\noverflow:/g' /app/linux/$VERSION/arch/x86/kernel/module.c - fi - - make -C /app/linux/$VERSION ARCH=${short_arch} CROSS_COMPILE=$(get_cc $TARGET $VERSION) O=/tmp/build/${VERSION}/${TARGET}/ olddefconfig - if $MENU_CONFIG; then - make -C /app/linux/$VERSION ARCH=${short_arch} CROSS_COMPILE=$(get_cc $TARGET $VERSION) O=/tmp/build/${VERSION}/${TARGET}/ menuconfig - exit - elif $DIFFDEFCONFIG; then - cp /tmp/build/${VERSION}/${TARGET}/.config /tmp/original_config - make -C /app/linux/$VERSION ARCH=${short_arch} CROSS_COMPILE=$(get_cc $TARGET $VERSION) O=/tmp/build/${VERSION}/${TARGET}/ defconfig - /app/linux/${VERSION}/scripts/diffconfig /tmp/original_config /tmp/build/${VERSION}/${TARGET}/.config - exit - fi - make -C /app/linux/$VERSION ARCH=${short_arch} CROSS_COMPILE=$(get_cc $TARGET $VERSION) CC="${CC_PREFIX}$(get_cc $TARGET $VERSION)gcc" O=/tmp/build/${VERSION}/${TARGET}/ $BUILD_TARGETS -j$(nproc) - - # Always run modules_prepare to ensure headers and Module.symvers are generated - make -C /app/linux/$VERSION ARCH=${short_arch} CROSS_COMPILE=$(get_cc $TARGET $VERSION) CC="${CC_PREFIX}$(get_cc $TARGET $VERSION)gcc" O=/tmp/build/${VERSION}/${TARGET}/ modules_prepare - - # Build modules to ensure Module.symvers is generated - make -C /app/linux/$VERSION ARCH=${short_arch} CROSS_COMPILE=$(get_cc $TARGET $VERSION) CC="${CC_PREFIX}$(get_cc $TARGET $VERSION)gcc" O=/tmp/build/${VERSION}/${TARGET}/ modules -j$(nproc) - - # Prepare and completely clean the output directory for perf - PERF_OUTDIR="/tmp/build/${VERSION}/${TARGET}/tools/perf/" - rm -rf "$PERF_OUTDIR" - mkdir -p "$PERF_OUTDIR" - - # 3. Prepare specific Linker flags for MIPS64 ABI mismatches - PERF_LD="$(get_cc $TARGET $VERSION)ld" - if [[ "$TARGET" == *"mips64el"* ]]; then - PERF_LD="${PERF_LD} -m elf64ltsmip" - elif [[ "$TARGET" == *"mips64eb"* || "$TARGET" == "mips64" ]]; then - PERF_LD="${PERF_LD} -m elf64btsmip" - fi - - # Build perf utility statically - make -C /app/linux/$VERSION/tools/perf \ - ARCH=${short_arch} \ - CROSS_COMPILE=$(get_cc $TARGET $VERSION) \ - CC="${CC_PREFIX}$(get_cc $TARGET $VERSION)gcc" \ - LD="$PERF_LD" \ - OUTPUT="$PERF_OUTDIR" \ - LDFLAGS="-static" \ - WERROR=0 \ - EXTRA_CFLAGS="-Wno-error -fcommon -D__always_inline=inline -Wno-redundant-decls -Wno-format-truncation -Wno-format-overflow -Wno-array-bounds" \ - HOSTCFLAGS="-Wno-error" \ - NO_LIBELF=1 NO_LIBUNWIND=1 NO_LIBNUMA=1 NO_LIBAUDIT=1 \ - NO_LIBBIONIC=1 NO_LIBPYTHON=1 NO_LIBPERL=1 NO_SLANG=1 NO_LZMA=1 \ - NO_ZLIB=1 NO_LIBBPF=1 NO_JVMTI=1 NO_LIBCRYPTO=1 NO_LIBZSTD=1 \ - NO_LIBTRACEEVENT=1 NO_AUXTRACE=1 NO_CORESIGHT=1 \ - -j$(nproc) || echo "Warning: Failed to build perf for $TARGET ($VERSION)" - mkdir -p /kernels/$VERSION - - # Copy perf to delivery directory - PERF_SRC="${PERF_OUTDIR}perf" - if [ -f "$PERF_SRC" ]; then - cp "$PERF_SRC" "/kernels/$VERSION/perf.${TARGET}" - if ! $NO_STRIP; then - $(get_cc $TARGET $VERSION)strip "/kernels/$VERSION/perf.${TARGET}" || true - fi - fi - - # Copy only the required boot artifact per architecture - BOOT_SRC="" - BOOT_DST="" - case "$TARGET" in - armel) - BOOT_SRC="arch/arm/boot/zImage"; BOOT_DST="zImage.${TARGET}" ;; - arm64) - BOOT_SRC="arch/arm64/boot/Image.gz"; BOOT_DST="zImage.${TARGET}" ;; - x86_64) - BOOT_SRC="arch/x86/boot/bzImage"; BOOT_DST="bzImage.${TARGET}" ;; - loongarch64) - BOOT_SRC="arch/loongarch/boot/vmlinuz.efi"; BOOT_DST="vmlinuz.efi.${TARGET}" ;; - riscv64|riscv32) - BOOT_SRC="arch/riscv/boot/Image"; BOOT_DST="Image.${TARGET}" ;; - *) - BOOT_SRC=""; BOOT_DST="" ;; - esac - if [ -n "$BOOT_SRC" ]; then - if [ -f "/tmp/build/${VERSION}/${TARGET}/${BOOT_SRC}" ]; then - cp "/tmp/build/${VERSION}/${TARGET}/${BOOT_SRC}" "/kernels/$VERSION/${BOOT_DST}" - else - echo "Warning: Expected boot artifact not found: ${BOOT_SRC} for ${TARGET}" - fi - fi - - # vmlinux is needed for analysis, but only shipped if it is the deliverable (mips*/powerpc*) - VMLINUX_SRC="/tmp/build/${VERSION}/${TARGET}/vmlinux" - DELIVER_VMLINUX=false - case "$TARGET" in - mips*|powerpc*|powerpcle|powerpc64*|powerpc64le) - DELIVER_VMLINUX=true - ;; - esac - - # Launch kernel processing in subprocess - time ( - # Generate OSI/COSI from build-tree vmlinux - echo "[${TARGET}]" >> /kernels/$VERSION/osi.${TARGET}.config - /extract_kernelinfo/run.sh \ - "${VMLINUX_SRC}" /tmp/panda_profile.${TARGET} - cat /tmp/panda_profile.${TARGET} >> /kernels/$VERSION/osi.${TARGET}.config - dwarf2json linux --elf "${VMLINUX_SRC}" | xz -c > /kernels/$VERSION/cosi.${TARGET}.json.xz - - # If vmlinux is the boot artifact for this TARGET, copy and (optionally) strip it - if $DELIVER_VMLINUX; then - cp "${VMLINUX_SRC}" "/kernels/$VERSION/vmlinux.${TARGET}" - if ! $NO_STRIP; then - $(get_cc $TARGET $VERSION)strip "/kernels/$VERSION/vmlinux.${TARGET}" - fi - fi - - echo "Completed processing for $TARGET ($VERSION)" - ) & - # Store the PID of the background process - pids+=($!) - - # Create minimal kernel-devel archive for module builds - ( - KBUILD_DIR="/tmp/build/${VERSION}/${TARGET}" - KERNEL_SRC="/app/linux/${VERSION}" - OUTDIR="/minimal-devel/${TARGET}.${VERSION}" - mkdir -p "$OUTDIR" - # Explicitly copy .config file - if [ -f "$KBUILD_DIR/.config" ]; then - cp "$KBUILD_DIR/.config" "$OUTDIR/.config" - fi - cp "$KBUILD_DIR/Module.symvers" "$OUTDIR/" || true - cp -r "$KERNEL_SRC/include" "$OUTDIR/" || true - cp -r "$KBUILD_DIR/include" "$OUTDIR/" || true - mkdir -p "$OUTDIR/arch/${short_arch}" - cp -r "$KERNEL_SRC/arch/${short_arch}" "$OUTDIR/arch/" || true - cp -r "$KBUILD_DIR/arch/${short_arch}" "$OUTDIR/arch/" || true - # Remove arch/${ARCH}/boot from OUTDIR - rm -rf "$OUTDIR/arch/${short_arch}/boot" || true - if [ $short_arch == "x86_64" ]; then - # MIPS has a different arch directory structure - mkdir -p "$OUTDIR/arch/x86" - cp -r "$KERNEL_SRC/arch/x86" "$OUTDIR/arch/" || true - cp -r "$KBUILD_DIR/arch/x86" "$OUTDIR/arch/" || true - fi - cp -r "$KERNEL_SRC/scripts" "$OUTDIR/" || true - cp -r "$KBUILD_DIR/scripts" "$OUTDIR/" || true - cp -r "$KERNEL_SRC/tools" "$OUTDIR/" || true - cp -r "$KBUILD_DIR/tools" "$OUTDIR/" || true - cp "$KERNEL_SRC/Makefile" "$OUTDIR/" || true - cp "$KERNEL_SRC/Kconfig" "$OUTDIR/" || true - # Ensure fixdep is present for out-of-tree module builds - cp -r "$KBUILD_DIR/scripts/" "$OUTDIR/scripts/" || true - - # --- Slim the staged devel tree ------------------------------------- - # An out-of-tree module build (make -C $KDIR M=$PWD modules) only needs - # the modules_prepare result: Makefile/.config/Module.symvers, headers - # (include/, arch//include), arch Makefiles, and scripts/ host - # tools. It does not read boot images, prebuilt build objects, or most - # of tools/, so drop them -- this cuts the per-target devel archive - # ~75-85% (e.g. x86_64 ~605MB -> ~100MB uncompressed). - # - # NOTE: the `rm -rf "$OUTDIR/arch/${short_arch}/boot"` above is a no-op - # for x86_64 (real arch dir is arch/x86, but short_arch is "x86_64"), so - # the full arch/x86/boot (~120MB of bzImage/vmlinux) used to ship. The - # arch/*/boot glob here removes it properly for every arch. - rm -rf "$OUTDIR"/arch/*/boot "$OUTDIR"/arch/*/realmode || true - # Keep tools/objtool (kbuild may run it on module objects when - # CONFIG_OBJTOOL=y); drop the rest of tools/ (perf, testing, bpf = bulk). - if [ -d "$OUTDIR/tools" ]; then - find "$OUTDIR/tools" -mindepth 1 -maxdepth 1 ! -name objtool -exec rm -rf {} + || true - fi - # Drop build leftovers. Keep arch/powerpc/lib/crtsavres.o (igloo_driver - # links it for ppc targets) and everything under scripts/ and tools/ - # (host tools needed for the external-module build). - find "$OUTDIR" -name '*.cmd' -delete || true - find "$OUTDIR" -name '*.o' \ - ! -path '*/arch/powerpc/lib/crtsavres.o' \ - ! -path '*/scripts/*' \ - ! -path '*/tools/*' -delete || true - # Drop kernel .c source too: an `M=` external-module build compiles the - # module's own sources against prebuilt objects + headers, never the - # in-tree .c. Keep scripts/ and tools/ sources in case a host tool needs - # a rebuild. - find "$OUTDIR" -name '*.c' \ - ! -path '*/scripts/*' \ - ! -path '*/tools/*' -delete || true - ) & - - # Store the PID of the background process - pids+=($!) - echo "Started background process ${pids[-1]} for $TARGET ($VERSION)" - fi -done -done - -if ! $CONFIG_ONLY; then - echo "Waiting for all kernel processing to complete..." - # Wait for all background processes to complete - for pid in "${pids[@]}"; do - wait $pid - echo "Process $pid completed" - done - for VERSION in $VERSIONS; do - # Only concatenate if the version directory exists and there are any osi.*.config files - if [ -d "/kernels/$VERSION" ]; then - shopt -s nullglob - osi_configs=(/kernels/$VERSION/osi.*.config) - if [ ${#osi_configs[@]} -gt 0 ]; then - cat "${osi_configs[@]}" >> /kernels/$VERSION/osi.config - fi - shopt -u nullglob - else - echo "Skipping osi.config aggregation for $VERSION (no /kernels/$VERSION directory)" - fi - done - echo "All processes completed, creating final archive" - echo "Built by linux_builder on $(date)" > /kernels/README.txt - tar cvf - /kernels | pigz > /app/kernels-latest.tar.gz - chmod o+rw /app/kernels-latest.tar.gz -fi - -if [ "$KERNEL_DEVEL" = "true" ]; then - echo "Aggregating all kernel-devel artifacts into kernel-devel-all.tar.gz..." - - # Create the tar directly from the minimal-devel directory using pigz for parallel compression - tar cf - -C /minimal-devel . | pigz > /app/kernel-devel-all.tar.gz - exit 0 -fi - -# Ensure cache can be read/written by host -chmod -R o+rw /tmp/build diff --git a/build.sh b/build.sh deleted file mode 100755 index 3b844ac..0000000 --- a/build.sh +++ /dev/null @@ -1,181 +0,0 @@ -#!/bin/bash - -set -eux - -help() { - cat >&2 < auto-detect all version directories under ./linux -TARGETS="armel arm64 mipseb mipsel mips64eb mips64el powerpc powerpcle powerpc64 powerpc64le loongarch64 riscv64 x86_64" -NO_STRIP=false -MENU_CONFIG=false -INTERACTIVE= -DIFFDEFCONFIG=false -KERNEL_DEVEL=true -IMAGE="rehosting/linux_builder" -EXTRA_DOCKER_OPTS="" -CACHE_DIR="cache" -CLEAR_CACHE=false - -# Parse command-line arguments -while [[ $# -gt 0 ]]; do - case "$1" in - --help) - help - exit - ;; - --clear-cache) - CLEAR_CACHE=true - shift - ;; - --config-only) - CONFIG_ONLY=true - shift - ;; - --versions) - VERSIONS="$2" - shift # past flag - shift # past value - ;; - --no-strip) - NO_STRIP=true - shift # past flag - ;; - --menuconfig) - MENU_CONFIG=true - INTERACTIVE=-it - shift # past flag - ;; - --targets) - TARGETS="$2" - shift # past flag - shift # past value - ;; - --diffdefconfig) - DIFFDEFCONFIG=true - shift - ;; - --kernel-devel) - KERNEL_DEVEL=true - shift - ;; - --image) - IMAGE="$2" - shift # past flag - shift # past value - ;; - --extra-docker-opts) - EXTRA_DOCKER_OPTS="$2" - shift # past flag - shift # past value - ;; - --cache-dir) - CACHE_DIR="$2" - shift # past flag - shift # past value - ;; - *) - help - exit 1 - ;; - esac -done - -# Auto-detect versions if not provided -if [[ -z "${VERSIONS// }" ]]; then - if [[ ! -d linux ]]; then - echo "Error: linux directory not found; cannot auto-detect versions. Use --versions." >&2 - exit 1 - fi - mapfile -t _version_dirs < <(find linux -maxdepth 1 -mindepth 1 -type d -printf '%f\n' | sort -V) - if [[ ${#_version_dirs[@]} -eq 0 ]]; then - echo "Error: No version subdirectories found under linux/. Use --versions." >&2 - exit 1 - fi - VERSIONS="${_version_dirs[*]}" -fi - -# Resolve host cache directory path: -if [[ "$CACHE_DIR" == "cache" ]]; then - CACHE_HOST_DIR="$PWD/cache" -else - CACHE_HOST_DIR="$CACHE_DIR" -fi - -# Bind-mount source translation for a shared Docker daemon (opt-in, pure -# no-op otherwise). -# -# Normally dockerd shares this script's mount namespace, so a bind-mount -# source path ("$PWD", the cache dir) means the same thing to the daemon as -# to us. Under a shared per-node daemon (e.g. rehosting CI's shared-docker -# runners) it does NOT: the daemon can't see this runner's per-pod workspace -# under /home/runner/_work, so "-v $PWD:/app" would mount an empty dir and the -# build would fail with "/app/_in_container_build.sh: No such file". The runner -# exports PENGUIN_HOST_MOUNT_FROM / PENGUIN_HOST_MOUNT_TO (the same mechanism -# penguin's wrapper uses) giving the daemon-visible location of that workspace. -# -# rewrite_mount() rewrites a bind source ONLY when BOTH env vars are set and -# the path is under _FROM. When they're unset — every local build and every -# GitHub-hosted runner — it returns the path unchanged, so behaviour is -# identical to before. (Sources outside _FROM, e.g. the kernel-source cache -# under /home/runner/_shared, are left as-is; the shared daemon mirrors that -# node-shared path directly.) -rewrite_mount() { - local path="$1" - if [[ -n "${PENGUIN_HOST_MOUNT_FROM:-}" && -n "${PENGUIN_HOST_MOUNT_TO:-}" \ - && "$path" == "${PENGUIN_HOST_MOUNT_FROM}"* ]]; then - printf '%s' "${PENGUIN_HOST_MOUNT_TO}${path#"$PENGUIN_HOST_MOUNT_FROM"}" - else - printf '%s' "$path" - fi -} -CACHE_MOUNT_SRC="$(rewrite_mount "$CACHE_HOST_DIR")" -APP_MOUNT_SRC="$(rewrite_mount "$PWD")" - -if $CLEAR_CACHE; then - docker run --rm -v "$CACHE_MOUNT_SRC":/tmp/build -v "$APP_MOUNT_SRC":/app pandare/kernel_builder /bin/bash -c "rm -rf /tmp/build/*" - exit -fi - -# Check if the image exists locally, build if not -if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then - echo "Docker image $IMAGE not found, building it..." - docker build -t "$IMAGE" . -fi - -mkdir -p "$CACHE_HOST_DIR" - -docker run $INTERACTIVE \ - --rm -v "$CACHE_MOUNT_SRC":/tmp/build \ - -v "$APP_MOUNT_SRC":/app \ - -e HOST_UID="$(id -u)" -e HOST_GID="$(id -g)" \ - $EXTRA_DOCKER_OPTS \ - "$IMAGE" \ - bash /app/_in_container_build.sh \ - "$CONFIG_ONLY" "$VERSIONS" "$TARGETS" \ - "$NO_STRIP" "$MENU_CONFIG" "$DIFFDEFCONFIG" "$KERNEL_DEVEL" \ No newline at end of file diff --git a/flake.nix b/flake.nix index 3035dc5..44b083f 100644 --- a/flake.nix +++ b/flake.nix @@ -110,12 +110,20 @@ mkPerf = import ./nix/perf.nix { inherit pkgs kernelsmith; }; mkDriver = import ./nix/driver.nix { inherit pkgs kernelsmith; }; bootLib = import ./nix/boot.nix { inherit pkgs qemuPkgs; }; + lintLib = import ./nix/lint.nix { inherit pkgs; }; # Per-cell record carrying everything the assembly needs. cellRecords = version: map (target: let kernel = cells."kernel-${version}-${target}"; in { inherit version target kernel; + # Carried so nix/lint.nix can re-run savedefconfig over exactly the + # tree and fragment this cell was built from. + src = sources.${version}; + config = configLib.rawConfig { + configsSrc = ./configs; + inherit version target; + }; osi = analysisLib.osiConfig { inherit kernel version target; }; cosi = analysisLib.cosiJson { inherit kernel version target; }; perf = mkPerf { @@ -146,6 +154,10 @@ # nix build .#packages.x86_64-linux."boot-4.10-x86_64" (lib.nameValuePair "boot-${r.version}-${r.target}" (bootLib.forCell { inherit (r) kernel version target; })) + # Replaces `./build.sh --config-only`. Advisory, not a gate -- see + # nix/lint.nix for why asserting on it would be wrong. + (lib.nameValuePair "config-lint-${r.version}-${r.target}" + (lintLib.forCell { inherit (r) kernel config src version target; })) ]) allRecords); @@ -192,6 +204,10 @@ # nixdev_0.1.0's 4.10/x86_64 is one -- see nix/boot.nix. boot-check = bootLib.all { cells = allRecords; }; + # Every cell's savedefconfig lint in one build, for a config sweep. + # The nix replacement for `./build.sh --config-only` across all targets. + config-lint = lintLib.all { cells = allRecords; }; + # The analysis tools, pinned. Exposed so their provenance is inspectable # and so igloo_driver can reuse dwarf2json for its own ISF (it runs the # same fork over igloo.ko) instead of re-deriving the pin. @@ -214,6 +230,8 @@ # separator -- quote the attribute or the build fails to resolve. echo ' nix build .#packages.x86_64-linux."kernel-6.13-armel" one cell' echo " nix build .#all every buildable cell" + echo " nix build .#boot-check every kernel actually boots" + echo " nix build .#config-lint savedefconfig lint (was build.sh --config-only)" echo " ./scripts/verify-series.sh ... prove a series matches its fork branch" ''; }; diff --git a/linux/4.10 b/linux/4.10 deleted file mode 160000 index 6899687..0000000 --- a/linux/4.10 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 68996875436ed6bd835047465f364916d468d394 diff --git a/linux/6.13 b/linux/6.13 deleted file mode 160000 index 8f25e98..0000000 --- a/linux/6.13 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8f25e989e12e2fca57aec18413ad157efb452ee4 diff --git a/nix/lint.nix b/nix/lint.nix new file mode 100644 index 0000000..079f543 --- /dev/null +++ b/nix/lint.nix @@ -0,0 +1,83 @@ +# Config linting -- the nix replacement for `./build.sh --config-only`. +# +# What the Docker path did: cpp-assemble configs//, run +# `savedefconfig` against the kernel tree, drop the result at +# config__.linted, and print a diff. That diff was always +# non-empty and its exit status was discarded (`|| true`) -- savedefconfig +# prunes options that are already the default and de-duplicates, so a config +# and its savedefconfig form never match. It was an ADVISORY tool for the +# author of a config change, never a gate, and it is kept as one here. +# +# What it is good for: seeing which lines in a config fragment are redundant +# (already the arch default) or duplicated, before committing them. +# +# Deliberately NOT wired into `nix flake check`. Making it a gate would mean +# asserting that our configs equal their savedefconfig form, which is false for +# every config in this repo by construction, and "fixing" that would mean +# replacing readable fragments with savedefconfig output and losing the +# #include structure that makes configs/ maintainable. +{ pkgs }: + +let + inherit (pkgs) lib; +in +rec { + # One cell's lint. Reuses the kernel's own tree and toolchain via passthru, + # so the linted output comes from exactly the compiler and source that build + # the shipped kernel -- savedefconfig's answer depends on both. + forCell = + { kernel, config, src, version, target }: + pkgs.runCommand "igloo-config-lint-${version}-${target}" + { + nativeBuildInputs = with pkgs; [ + # stdenv.cc is the HOST compiler, and it is required: Kbuild builds + # scripts/basic/fixdep and the Kconfig binaries natively before it + # touches a single target file. `runCommand` is stdenvNoCC in current + # nixpkgs, so without this the lint dies on "gcc: command not found" + # long before reaching savedefconfig. The cross toolchain below is + # prefixed (${kernel.passthru.crossPrefix}gcc), so the two never clash. + stdenv.cc + kernel.passthru.toolchain + gnumake bc bison flex perl python3 rsync which openssl elfutils + ]; + meta.description = "savedefconfig lint for ${version}/${target}"; + } + '' + export ARCH=${kernel.passthru.arch} + export CROSS_COMPILE=${kernel.passthru.crossPrefix} + cp -r ${src} linux && chmod -R u+w linux + mkdir -p build out + + # Same two sandbox fixups the kernel build needs; see nix/kernel.nix. + sed -i 's|/bin/pwd|pwd|g' linux/Makefile + patchShebangs linux/scripts linux/tools 2>/dev/null || true + + cp ${config} build/.config + make -C linux O=$PWD/build olddefconfig >/dev/null + make -C linux O=$PWD/build savedefconfig >/dev/null + + mkdir -p $out + cp build/defconfig $out/config_${version}_${target}.linted + + # Advisory, exactly as the Docker path had it: report, never fail. + { + echo "=== ${version}/${target}: assembled .config vs savedefconfig ===" + echo "Lines only in the assembled config are redundant or defaulted." + diff -u <(sort build/.config) \ + <(sort build/defconfig | sed '/^[ #]/d') || true + } > $out/config_${version}_${target}.diff + cat $out/config_${version}_${target}.diff + ''; + + # Every cell's lint in one tree, so a config sweep is a single build. + all = { cells }: + pkgs.linkFarm "igloo-config-lint" + (map + (c: { + name = "${c.version}-${c.target}"; + path = forCell { + inherit (c) kernel config src version target; + }; + }) + cells); +} From 52be6fa1ae9ede7541e1cb280b991236a570520a Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Fri, 14 Aug 2026 23:45:36 -0400 Subject: [PATCH 27/28] Config tooling: a contract gate, provenance, and a redundancy report configs// is a cpp fragment that #includes shared pieces, so the file you edit is almost never the file an option comes from -- and the config the kernel is BUILT with is a third thing again, because olddefconfig runs afterwards and drops anything whose dependencies are unmet. Three questions follow, one tool each. .#config-required -- THE GATE. Asserts every cell ENDED UP with the options IGLOO needs, reading the post-olddefconfig .config out of the kernel's dev output rather than the fragments. That distinction is the whole point: a fragment saying CONFIG_MODVERSIONS=y proves nothing about what shipped. Seven options, each recorded with what breaks without it. MODVERSIONS is the sharpest -- without it a mismatched igloo.ko loads SILENTLY instead of being rejected, which is strictly worse than the mismatch we spent this branch chasing. Reports every violation across every cell before failing, rather than stopping at the first. .#config-explain -- provenance. Resolves the #include chain and shows where an option is set, which assignment wins, and via what path. It exists because grep does not answer the question: CONFIG_IGLOO is set in all-common.inc and no target sets it directly, so grepping a target config finds nothing at all. Builds no kernel, so it stays instant. .#config-redundant -- separates two things that look alike and are not: an option assigned twice (always a bug, only the last has effect) and an option that did not survive olddefconfig (usually an unnoticed dependency). Advisory. What they found on this tree: * 595 duplicated assignments across the matrix, including CONFIG_MODULES twice in 6.13/all-common.inc, 3 lines apart * conflicting values where 6.13/powerpc re-declares =m over all-common.inc's =y * 2-68 options per cell that do not survive olddefconfig All 19 cells DO satisfy the contract today; the gate is green. Wired into CI's full-matrix job: config-required as a gate next to boot-check (both exist for kernels that build and boot and then quietly do not do their job), the redundancy report as continue-on-error so the output lands in the log without failing the build. The gate deliberately does not pipe python into tee: a pipeline's status is its last command, so a failing check would be masked by a succeeding tee unless pipefail is set. stdenv does set it -- but a gate that silently passes when a shell option changes is the exact failure class this file exists to catch. Verified by negative test: adding a bogus required option fails all 19 cells with the per-cell reason, and removing it returns to green. --- .github/workflows/nix.yml | 17 ++ README.md | 43 ++++- flake.nix | 27 +++ nix/config-tools.nix | 349 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 435 insertions(+), 1 deletion(-) create mode 100644 nix/config-tools.nix diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index dd6fd90..2680b9f 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -199,6 +199,23 @@ jobs: - name: Every kernel boots run: nix build --print-build-logs --print-out-paths .#boot-check + # The config contract: does every cell END UP with the options IGLOO + # needs? Reads the post-olddefconfig .config, not the fragments, because + # olddefconfig silently drops options whose dependencies are unmet -- so + # a fragment saying CONFIG_MODVERSIONS=y proves nothing about what + # shipped. Sibling of the boot check: both exist for kernels that build + # and boot and then quietly do not do their job. + - name: Configs satisfy the IGLOO contract + run: nix build --print-build-logs --print-out-paths .#config-required + + # Advisory, so it must not fail the job -- but the output belongs in the + # log where a config change can be reviewed against it. + - name: Config redundancy report (advisory) + continue-on-error: true + run: | + out=$(nix build --no-link --print-out-paths .#config-redundant) + cat "$out" + - name: Release tarballs assemble run: | set -euo pipefail diff --git a/README.md b/README.md index 1c0f04d..b7f9925 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ this repo and a fork branch. |---|---| | `nix build .#boot-check` | **every kernel actually boots** under the qemu machine penguin runs it on | | `nix build .#shape-check` | each artifact's ELF class, byte order and machine match its target name | +| `nix build .#config-required` | every kernel ended up with the options IGLOO needs (see [Modifying configs](#modifying-configs)) | | `nix flake check` | the above, plus evaluation of every output | `boot-check` is the one that matters most, and it is newer than the rest. @@ -66,7 +67,47 @@ Configs live in `configs//`, with shared fragments pulled in by `#include` (`all-common.inc`, `arm-common.inc`, ...). They are assembled with `cpp -P -undef` and then `olddefconfig`. -After changing one, look at its lint: +**The file you edit is almost never the file an option comes from,** and the +config the kernel is *built* with is a third thing again — `olddefconfig` runs +last and drops anything whose dependencies are unmet. Three tools follow from +that, one per question: + +| question | command | +|---|---| +| Did every cell **end up** with what IGLOO needs? | `nix build .#config-required` | +| Where does `CONFIG_X` for this cell **come from**? | `nix run .#config-explain -- 6.13 x86_64 CONFIG_IGLOO` | +| Which lines am I writing that **do nothing**? | `nix build .#config-redundant` | + +`config-required` is a **gate**, and it reads the shipped `.config` rather than +the fragments — that distinction is the entire point. It asserts the options +whose absence is *silent*: a kernel that builds, boots, and then does not do +its job. `CONFIG_MODVERSIONS` is the sharpest of them; without it a mismatched +`igloo.ko` loads quietly instead of being rejected, which is strictly worse +than the mismatch. See `nix/config-tools.nix`, where every entry says what +breaks without it. + +`config-explain` builds no kernel, so it is instant. It exists because grep +does not answer the question: `CONFIG_IGLOO` is set in `all-common.inc` and no +target sets it directly, so grepping `configs/6.13/x86_64` finds nothing. + +``` +$ nix run .#config-explain -- 6.13 armel CONFIG_MODULES + CONFIG_MODULES=y + configs/6.13/all-common.inc:159 + via armel -> arm-common.inc -> all-common.inc +* CONFIG_MODULES=y + configs/6.13/all-common.inc:162 + via armel -> arm-common.inc -> all-common.inc + + 2 assignments; the one marked * wins (cpp: last wins). +``` + +`config-redundant` separates two things that look alike and are not: an option +assigned **twice** (always a bug — only the last has effect) and an option that +**did not survive olddefconfig** (usually a dependency you did not notice). It +currently reports 595 duplicate assignments across the matrix. + +And the raw savedefconfig lint, per cell or across the matrix: ```sh nix build .#packages.x86_64-linux."config-lint-6.13-armel" # one cell diff --git a/flake.nix b/flake.nix index 44b083f..4d62ef7 100644 --- a/flake.nix +++ b/flake.nix @@ -111,6 +111,7 @@ mkDriver = import ./nix/driver.nix { inherit pkgs kernelsmith; }; bootLib = import ./nix/boot.nix { inherit pkgs qemuPkgs; }; lintLib = import ./nix/lint.nix { inherit pkgs; }; + cfgTools = import ./nix/config-tools.nix { inherit pkgs; }; # Per-cell record carrying everything the assembly needs. cellRecords = version: map @@ -208,6 +209,21 @@ # The nix replacement for `./build.sh --config-only` across all targets. config-lint = lintLib.all { cells = allRecords; }; + # THE config gate: does every cell END UP with what IGLOO needs? + # Reads the post-olddefconfig .config, not the fragment -- see + # nix/config-tools.nix for why that distinction is the whole point. + config-required = cfgTools.requiredCheck { cells = allRecords; }; + + # Duplicated assignments, and options that did not survive + # olddefconfig. Advisory. + config-redundant = cfgTools.redundancyReport { + cells = allRecords; + configsSrc = ./configs; + }; + + # `nix run .#config-explain -- 6.13 x86_64 CONFIG_IGLOO` + config-explain = cfgTools.explainScript; + # The analysis tools, pinned. Exposed so their provenance is inspectable # and so igloo_driver can reuse dwarf2json for its own ISF (it runs the # same fork over igloo.ko) instead of re-deriving the pin. @@ -219,6 +235,14 @@ # what the series produces without a full kernel build. inherit sources; + # `nix run .#config-explain -- CONFIG_X`. An app rather + # than only a package so it is one command from a clean checkout; it reads + # configs/ and builds no kernel, so it stays instant. + apps.${system}.config-explain = { + type = "app"; + program = "${cfgTools.explainScript}/bin/config-explain"; + }; + # Cells we cannot build until kernelsmith gains these arches. missingArches = kernelsmithMissing; @@ -231,6 +255,9 @@ echo ' nix build .#packages.x86_64-linux."kernel-6.13-armel" one cell' echo " nix build .#all every buildable cell" echo " nix build .#boot-check every kernel actually boots" + echo " nix build .#config-required configs satisfy the IGLOO contract (gate)" + echo ' nix run .#config-explain -- 6.13 x86_64 CONFIG_IGLOO where does an option come from' + echo " nix build .#config-redundant duplicate / dead config lines" echo " nix build .#config-lint savedefconfig lint (was build.sh --config-only)" echo " ./scripts/verify-series.sh ... prove a series matches its fork branch" ''; diff --git a/nix/config-tools.nix b/nix/config-tools.nix new file mode 100644 index 0000000..25124e6 --- /dev/null +++ b/nix/config-tools.nix @@ -0,0 +1,349 @@ +# Tools for working on configs/. +# +# configs// is a cpp fragment that `#include`s shared pieces, +# so the file you edit is almost never the file an option comes from -- and the +# config the kernel is BUILT with is a third thing again, because `olddefconfig` +# runs afterwards and will silently drop any option whose dependencies are not +# met. Three questions follow from that, and each gets a tool here: +# +# config-required Did every cell END UP with the options IGLOO needs? +# config-explain Where does CONFIG_X for this cell come from? +# config-redundant Which lines I wrote are doing nothing? +# +# The first is a gate. The other two are answers to questions, not assertions. +{ pkgs }: + +let + inherit (pkgs) lib; + + # --------------------------------------------------------------------- + # The contract: what a kernel must have for IGLOO to work on it. + # + # Every entry is here because something downstream breaks without it, and + # each names what. This is deliberately NOT "the options we happen to set" -- + # it is the subset whose absence is a silent failure, i.e. a kernel that + # builds, boots, and then does not do its job. That failure class is the + # reason this file exists; see nix/boot.nix for the sibling case. + required = { + CONFIG_IGLOO = "the IGLOO patch series itself -- without it every igloo_* hook compiles out and the kernel is stock"; + CONFIG_MODULES = "igloo.ko is a module; nothing to load it into"; + CONFIG_MODULE_UNLOAD = "penguin unloads and reloads the driver between runs"; + CONFIG_MODVERSIONS = "the driver/kernel ABI CRCs. Without it a mismatched module loads SILENTLY instead of being rejected -- strictly worse than the mismatch"; + CONFIG_KALLSYMS_ALL = "OSI symbol resolution reads kallsyms"; + CONFIG_KPROBES = "penguin's kprobe-based instrumentation"; + CONFIG_DEBUG_INFO = "dwarf2json builds the ISF from DWARF; no debug info, no ISF"; + }; + + # --------------------------------------------------------------------- + # Shared include-resolver. cpp semantics: `#include "x.inc"` splices x.inc in + # place, and a later assignment of the same symbol overrides an earlier one. + # Both tools below need this, so it lives once. + resolverPy = '' + import os + import re + import sys + import collections + + INCLUDE = re.compile(r'\s*#include\s+"([^"]+)"') + ASSIGN = re.compile(r'\s*(CONFIG_[A-Za-z0-9_]+)\s*=\s*(.*?)\s*$') + UNSET = re.compile(r'\s*#\s*(CONFIG_[A-Za-z0-9_]+)\s+is not set\s*$') + + + def walk(path, chain=None, out=None, seen=None): + """Yield (option, value, file, line, include-chain) in cpp order.""" + chain = (chain or []) + [os.path.basename(path)] + out = out if out is not None else [] + seen = seen if seen is not None else set() + real = os.path.realpath(path) + if real in seen: # cpp would loop forever; we just stop + return out + seen.add(real) + d = os.path.dirname(path) + for n, line in enumerate(open(path, errors='replace'), 1): + m = INCLUDE.match(line) + if m: + inc = os.path.join(d, m.group(1)) + if os.path.exists(inc): + walk(inc, chain, out, seen) + else: + out.append(('!MISSING', m.group(1), path, n, list(chain))) + continue + m = ASSIGN.match(line) + if m: + out.append((m.group(1), m.group(2), path, n, list(chain))) + continue + m = UNSET.match(line) + if m: + out.append((m.group(1), 'n', path, n, list(chain))) + return out + + + def final(entries): + """Last assignment wins, exactly as cpp+Kconfig would see it.""" + v = {} + for opt, val, f, n, chain in entries: + if opt == '!MISSING': + continue + v[opt] = (val, f, n, chain) + return v + ''; + + # Parse a real .config (post-olddefconfig) -- the ground truth. + configReaderPy = '' + + + def read_config(path): + vals = {} + for line in open(path, errors='replace'): + line = line.rstrip('\n') + m = re.match(r'(CONFIG_[A-Za-z0-9_]+)=(.*)$', line) + if m: + vals[m.group(1)] = m.group(2); continue + m = re.match(r'# (CONFIG_[A-Za-z0-9_]+) is not set$', line) + if m: + vals[m.group(1)] = 'n' + return vals + ''; + +in +rec { + inherit required; + + # --------------------------------------------------------------------- + # 1. THE GATE. + # + # Reads each cell's POST-olddefconfig .config out of the kernel's dev output, + # not the fragment. That distinction is the whole point: `olddefconfig` + # silently drops an option whose dependencies are unmet, so a fragment that + # says CONFIG_MODVERSIONS=y proves nothing about the kernel that shipped. + # + # Reports EVERY violation across EVERY cell before failing. A gate that stops + # at the first problem turns one fix-and-rerun cycle into N. + requiredCheck = { cells }: + let + configs = lib.concatMapStringsSep " " (c: "${c.version}:${c.target}:${c.kernel.dev}/.config") cells; + in + pkgs.runCommand "igloo-config-required" + { + nativeBuildInputs = [ pkgs.python3 ]; + meta.description = "assert every cell ends up with the options IGLOO needs"; + } '' + cat > check.py <<'EOF' + import re, sys + ${configReaderPy} + + REQUIRED = { + ${lib.concatStringsSep "\n" (lib.mapAttrsToList + (opt: why: " ${builtins.toJSON opt}: ${builtins.toJSON why},") required)} + } + + cells = [c.split(':', 2) for c in sys.argv[1:]] + failures = [] + for version, target, path in cells: + vals = read_config(path) + for opt, why in sorted(REQUIRED.items()): + got = vals.get(opt) + if got in ('y', 'm'): + continue + failures.append((version, target, opt, got, why)) + + print("checked %d cells against %d required options" % (len(cells), len(REQUIRED))) + if not failures: + print("all cells satisfy the IGLOO config contract") + sys.exit(0) + + print("") + print("%d violation(s):" % len(failures)) + for version, target, opt, got, why in failures: + state = "unset" if got is None else ("=" + got) + print(" %s/%s %s %s" % (version, target, opt, state)) + print(" needed for: %s" % why) + print("") + print("NOTE: this reads the POST-olddefconfig .config, so an option can be") + print("set in configs/ and still fail here -- olddefconfig drops options") + print("whose dependencies are unmet. Use `nix run .#config-explain` to see") + print("where the fragment sets it, then check what its dependencies need.") + sys.exit(1) + EOF + + # NOT `python3 ... | tee $out`. A pipeline's status is its LAST command, + # so a failing check would be masked by a succeeding tee unless pipefail + # happens to be set. stdenv does set it -- but a gate that silently passes + # when a shell option changes is the exact failure class this file exists + # to catch, so don't depend on it. + python3 check.py ${configs} > report.txt; status=$? + cat report.txt + cp report.txt $out + exit $status + ''; + + # --------------------------------------------------------------------- + # 2. PROVENANCE. `nix run .#config-explain -- 6.13 x86_64 CONFIG_IGLOO` + # + # Deliberately does NOT build a kernel: this answers "where does this come + # from", which is a question about configs/, and making it cost a cross-build + # would mean nobody runs it. It reports what the fragments say and is explicit + # that olddefconfig gets the last word -- rather than quietly implying the + # fragment value is what shipped. + explainScript = pkgs.writers.writePython3Bin "config-explain" { flakeIgnore = [ "E501" "F401" ]; } '' + ${resolverPy} + + def main(): + if len(sys.argv) not in (4, 5): + print("usage: config-explain [configs-dir]", file=sys.stderr) + print(" eg: config-explain 6.13 x86_64 CONFIG_IGLOO", file=sys.stderr) + return 2 + version, target, opt = sys.argv[1], sys.argv[2], sys.argv[3] + root = sys.argv[4] if len(sys.argv) == 5 else "configs" + if not opt.startswith("CONFIG_"): + opt = "CONFIG_" + opt + + path = os.path.join(root, version, target) + if not os.path.exists(path): + print("no config for %s/%s at %s" % (version, target, path), file=sys.stderr) + return 1 + + entries = walk(path) + + missing = [e for e in entries if e[0] == '!MISSING'] + for _, inc, f, n, _ in missing: + print("warning: %s:%d includes %s, which does not exist" % (f, n, inc), file=sys.stderr) + + hits = [e for e in entries if e[0] == opt] + if not hits: + print("%s is not set anywhere in %s/%s's fragment tree." % (opt, version, target)) + print("") + print("Include chain searched:") + seen = [] + for _, _, _, _, chain in entries: + key = " -> ".join(chain) + if key not in seen: + seen.append(key) + for s in seen: + print(" %s" % s) + print("") + print("It may still be enabled in the built kernel: olddefconfig turns on") + print("options that other options select. Check the shipped .config.") + return 0 + + print("%s for %s/%s" % (opt, version, target)) + print("") + for i, (_, val, f, n, chain) in enumerate(hits): + last = (i == len(hits) - 1) + print(" %s %s=%s" % ("*" if last else " ", opt, val)) + print(" %s:%d" % (f, n)) + print(" via %s" % " -> ".join(chain)) + if len(hits) > 1: + print("") + print(" %d assignments; the one marked * wins (cpp: last wins)." % len(hits)) + print(" The earlier ones are dead weight -- see `nix build .#config-redundant`.") + print("") + print("NOTE: this is what the FRAGMENTS say. olddefconfig runs afterwards and") + print("has the last word -- it drops options whose dependencies are unmet.") + print("`nix build .#config-required` checks the shipped .config instead.") + return 0 + + + sys.exit(main()) + ''; + + # --------------------------------------------------------------------- + # 3. REDUNDANCY. Two genuinely different kinds, reported together: + # + # (a) STATIC -- an option assigned more than once in one cell's fragment + # tree. Purely a configs/ bug, needs no kernel, always actionable. + # 6.13/all-common.inc sets CONFIG_MODULES=y twice, 3 lines apart. + # + # (b) DEFAULTED -- an option whose value already matches what the arch + # gives you, so writing it changes nothing. Needs savedefconfig, hence + # the built kernel. + # + # (a) is the one worth acting on: a duplicate is always a mistake, whereas a + # defaulted option is often deliberately explicit. So they are never merged + # into one number. + redundancyReport = { cells, configsSrc }: + let + args = lib.concatMapStringsSep " " + (c: "${c.version}:${c.target}:${c.kernel.dev}/.config") cells; + in + pkgs.runCommand "igloo-config-redundant" + { + nativeBuildInputs = [ pkgs.python3 ]; + meta.description = "which config lines are duplicated or already the default"; + } '' + cp -r ${configsSrc} configs && chmod -R u+w configs + + cat > report.py <<'EOF' + import re, sys, os, collections + ${resolverPy} + ${configReaderPy} + + cells = [c.split(':', 2) for c in sys.argv[1:]] + total_dupes = 0 + + print("=" * 70) + print("DUPLICATE ASSIGNMENTS -- an option set more than once in one cell") + print("=" * 70) + print("These are always bugs: only the last one has any effect.") + print("") + for version, target, cfgpath in cells: + entries = walk(os.path.join("configs", version, target)) + byopt = collections.OrderedDict() + for opt, val, f, n, chain in entries: + if opt == '!MISSING': + continue + byopt.setdefault(opt, []).append((val, f, n)) + dupes = {o: v for o, v in byopt.items() if len(v) > 1} + if not dupes: + continue + print("%s/%s: %d option(s) assigned more than once" % (version, target, len(dupes))) + for opt, occurrences in sorted(dupes.items()): + vals = {v for v, _, _ in occurrences} + kind = "same value" if len(vals) == 1 else "CONFLICTING values" + print(" %s (%d times, %s)" % (opt, len(occurrences), kind)) + for val, f, n in occurrences: + print(" %s=%s at %s:%d" % (opt, val, f, n)) + total_dupes += 1 + print("") + if total_dupes == 0: + print("none found.") + print("") + + print("=" * 70) + print("DEFAULTED OPTIONS -- written, but already the arch default") + print("=" * 70) + print("Not necessarily bugs: being explicit about an important option is") + print("a legitimate choice. Counts only, per cell, so this stays readable.") + print("") + for version, target, cfgpath in cells: + entries = walk(os.path.join("configs", version, target)) + written = final(entries) + shipped = read_config(cfgpath) + # An option we wrote whose shipped value matches, but which we cannot + # tell apart from "we asked and got it" without savedefconfig. What we + # CAN say cheaply and truthfully: which written options did not survive. + dropped = [] + for opt, (val, f, n, chain) in sorted(written.items()): + got = shipped.get(opt) + if got is None: + dropped.append((opt, val, f, n, "not present in shipped .config")) + elif got != val: + dropped.append((opt, val, f, n, "shipped as %s" % got)) + print("%s/%s: wrote %d options; %d did not survive olddefconfig" + % (version, target, len(written), len(dropped))) + for opt, val, f, n, why in dropped: + print(" %s=%s (%s) %s:%d" % (opt, val, why, f, n)) + print("") + + print("For the full savedefconfig diff per cell, build .#config-lint.") + if total_dupes: + print("") + print("%d duplicated option(s) found -- these are worth fixing." % total_dupes) + EOF + + python3 report.py ${args} > report.txt; status=$? + cat report.txt + cp report.txt $out + exit $status + ''; +} From b96eb956bca5eb2e43867150703c202158000768 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Fri, 14 Aug 2026 23:55:01 -0400 Subject: [PATCH 28/28] Restore the vX.Y.Z release line, on the nix path Removing build.yml took the release mechanism with it. nix.yml only ever cut PRERELEASES from nixdev_* tags -- deliberately, so it could not race the Docker pipeline for a version number -- so after that removal this repo could not cut a vX.Y.Z release at all. Nothing downstream noticed because existing releases stay downloadable, which is exactly why it would have been found late. Ported from build.yml into the full-matrix job: * `full` now also runs on a push to main. With the Docker pipeline gone it is the only thing that produces a release, so a merge has to build the whole matrix, not the 2-cell gate. * `reecetech/version-increment@2023.10.1` with `use_api: true`, then a real (non-pre) release with both tarballs. Prereleases stay as they were and stay separate: a nixdev_* tag IS its own version, so a downstream repo can be handed a fixed, immutable kernel set to test against without consuming a version number. The nixdev_* prefix now outlives its original reason -- it existed to avoid colliding with build.yml's dev_* trigger. Kept anyway: nixdev_0.1.0 and nixdev_0.1.1 are published and pinned by downstream lockfiles. Comments that described build.yml as still existing are corrected rather than deleted, since they explain why the prefix is what it is. README documents both paths, and how to move the version LINE: push a bare marker tag at main's tip and let the patch increment continue from it. Explicitly NOT by setting `increment: minor`, which is not self-clearing and silently bumps the release after it too. --- .github/workflows/nix.yml | 63 +++++++++++++++++++++++++++++++-------- README.md | 32 ++++++++++++++++---- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 2680b9f..2b39bb4 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -16,11 +16,12 @@ on: branches: [main, nix-patchset] # Cut a nix-built PRERELEASE from a tag, without touching the version line. # - # Deliberately NOT `dev_*`: that prefix already triggers the Docker - # workflow (build.yml), so a shared prefix would have both pipelines cut a - # release for the same tag and race `version-increment` for the same vX.Y.Z. - # `nixdev_*` does not match `dev_*` -- these globs are anchored -- so the two - # stay independent while both release paths exist. + # The prefix is `nixdev_*` rather than `dev_*` for a reason that has now + # expired: `dev_*` triggered the Docker workflow (build.yml), and a shared + # prefix would have had both pipelines cut a release for the same tag and + # race `version-increment` for the same vX.Y.Z. build.yml is gone, so the + # collision is impossible -- but the prefix stays, because nixdev_0.1.0 and + # nixdev_0.1.1 are already published and pinned by downstream lockfiles. tags: ['nixdev_*'] workflow_dispatch: inputs: @@ -130,9 +131,10 @@ jobs: ".#packages.x86_64-linux.\"boot-${{ matrix.cell }}\"" - # The full 19-cell matrix: on demand, and on a `nixdev_*` tag, where it is - # also what produces the release. Not on every PR -- it is the expensive one, - # and the gate above catches the failures that are not arch-specific. + # The full 19-cell matrix: on demand, on a `nixdev_*` tag, and on a merge to + # main -- in the last two cases it is also what produces the release. Not on + # every PR: it is the expensive one, and the gate above catches the failures + # that are not arch-specific. # # Running it on the tag has a second effect that matters for downstream # testing: this is a push event, so nix-setup's skip-push default does NOT @@ -145,9 +147,12 @@ jobs: needs: series permissions: contents: write + # Also on a push to main: with the Docker pipeline gone, this job is the + # ONLY thing that cuts a release, so a merge has to run the whole matrix. if: >- ${{ (github.event_name == 'workflow_dispatch' && inputs.full_matrix) - || startsWith(github.ref, 'refs/tags/nixdev_') }} + || startsWith(github.ref, 'refs/tags/nixdev_') + || (github.event_name == 'push' && github.ref == 'refs/heads/main') }} steps: - uses: actions/checkout@v4 - name: Prepare runner directories @@ -240,9 +245,10 @@ jobs: echo " $v: perf for $perf of $tot targets" done - # Prerelease only, and only from a nixdev_* tag. The tag IS the version -- - # no version-increment here, so this cannot collide with the Docker - # pipeline's vX.Y.Z line while both exist. + # Prerelease from a nixdev_* tag: the tag IS the version, no increment. + # Kept distinct from the vX.Y.Z release below so a downstream repo can be + # handed a fixed, immutable kernel set to test against without that + # consuming a version number. - name: Publish prerelease if: ${{ startsWith(github.ref, 'refs/tags/nixdev_') }} uses: softprops/action-gh-release@v1 @@ -263,3 +269,36 @@ jobs: * `perf` for all 19 cells (the Docker path shipped 7 of 19) * no `powerpcle` -- it was byte-identical to `powerpc` and big-endian despite the name + + # ---- the vX.Y.Z version line ------------------------------------- + # Ported from the deleted build.yml. With the Docker pipeline gone this + # is the only thing that cuts a real release, so it lives here now; the + # collision hazard that kept the two apart no longer exists. + # + # `use_api: true` reads GIT TAGS via /git/matching-refs/tags/, takes the + # highest by `sort -V`, and applies `increment` (default: patch). So the + # way to move the version LINE is to push a bare marker tag at main's tip + # and let the patch increment continue from it -- v4.0.0 -> v4.0.1. + # + # Do NOT set `increment: minor` to force a jump. It is not self-clearing, + # so it silently bumps the release AFTER it as well, until someone + # remembers to revert. The marker tag has no such landmine. + - name: Get next version + id: version + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + uses: reecetech/version-increment@2023.10.1 + with: + use_api: true + + - name: Publish release + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + uses: softprops/action-gh-release@v1 + with: + files: | + kernels-latest.tar.gz + kernel-devel-all.tar.gz + token: ${{ secrets.GITHUB_TOKEN }} + tag_name: ${{ steps.version.outputs.v-version }} + name: Release ${{ steps.version.outputs.v-version }} + generate_release_notes: true + prerelease: false diff --git a/README.md b/README.md index b7f9925..9749e24 100644 --- a/README.md +++ b/README.md @@ -127,16 +127,38 @@ discarded its own exit status. ## Releases -Pushing a `nixdev_*` tag runs the full 19-cell matrix, boot-tests it, publishes -`kernels-latest.tar.gz` + `kernel-devel-all.tar.gz` as a **prerelease**, and -pushes every cell to the `rehosting-tools` Cachix — which is what lets -downstream repos substitute these kernels instead of cross-building them. +There are two, and they are deliberately separate. + +**`vX.Y.Z` — the real version line.** Cut automatically on every merge to +`main`. The full matrix runs, boot-tests, and publishes `kernels-latest.tar.gz` ++ `kernel-devel-all.tar.gz`. The version comes from +`reecetech/version-increment` with `use_api: true`, which reads **git tags**, +takes the highest by `sort -V`, and bumps the patch. + +To move the version *line* (say 3.6.x → 4.0.x), **push a bare marker tag at +main's tip** and let the patch increment continue from it: + +```sh +git tag v4.0.0 && git push origin v4.0.0 # marker only, no release +# the next merge to main then cuts v4.0.1 +``` + +Do **not** set `increment: minor` in the workflow to force a jump. It is not +self-clearing, so it silently bumps the release *after* it as well, until +someone remembers to revert. The marker tag has no such landmine. + +**`nixdev_*` — prereleases, off the version line.** The tag *is* the version; +no increment. For handing a downstream repo a fixed, immutable kernel set to +test against without consuming a version number. ```sh git tag -a nixdev_0.1.2 -m "..." && git push origin nixdev_0.1.2 ``` -The tag glob is anchored, so `nixdev_*` and the old `dev_*` never collide. +Both run the full matrix, and both are `push` events — so `nix-setup`'s +skip-push default does not apply and every cell lands in the `rehosting-tools` +Cachix. That is what lets downstream repos *substitute* these kernels instead +of cross-building all 19 in their own CI. ## Consumers