├── .github ├── FUNDING.yml └── workflows │ ├── build.yml │ ├── release.yml │ ├── update.yml │ └── watch.yml ├── .gitignore ├── .gitmodules ├── README.md ├── crack.bundle ├── debian ├── changelog ├── compat ├── config │ └── config.pve ├── copyright ├── patches │ ├── pve │ │ ├── 0001-Make-mkcompile_h-accept-an-alternate-timestamp-strin.patch │ │ ├── 0002-bridge-keep-MAC-of-first-assigned-port.patch │ │ ├── 0003-pci-Enable-overrides-for-missing-ACS-capabilities-4..patch │ │ ├── 0004-kvm-disable-default-dynamic-halt-polling-growth.patch │ │ ├── 0005-net-core-downgrade-unregister_netdevice-refcount-lea.patch │ │ ├── 0006-do-not-generate-split-BTF-type-info-per-default.patch │ │ ├── 0007-Ubuntu-remove-leftover-reference-to-ubuntu-hio-drive.patch │ │ ├── 0008-bug-introduce-ASSERT_STRUCT_OFFSET.patch │ │ ├── 0009-KVM-x86-emulator-update-the-emulation-mode-after-rsm.patch │ │ ├── 0010-KVM-x86-emulator-smm-add-structs-for-KVM-s-smram-lay.patch │ │ ├── 0011-KVM-x86-emulator-smm-use-smram-structs-in-the-common.patch │ │ ├── 0012-KVM-x86-emulator-smm-use-smram-struct-for-32-bit-smr.patch │ │ ├── 0013-KVM-x86-emulator-smm-use-smram-struct-for-64-bit-smr.patch │ │ ├── 0014-KVM-x86-SVM-use-smram-structs.patch │ │ ├── 0015-KVM-x86-SVM-don-t-save-SVM-state-to-SMRAM-when-VM-is.patch │ │ └── 0016-KVM-x86-emulator-smm-preserve-interrupt-shadow-in-SM.patch │ ├── series.linux │ ├── series.zfs │ ├── ubuntu │ │ ├── 0001-apparmor-compatibility-v2.x-net-rules.patch │ │ ├── 0002-apparmor-af_unix-mediation.patch │ │ ├── 0003-apparmor-fix-apparmor-mediating-locking-non-fs-unix-sockets.patch │ │ └── 0004-apparmor-fix-use-after-free-in-sk_peer_label.patch │ └── zfs │ │ ├── 0001-Check-for-META-and-DCH-consistency-in-autoconf.patch │ │ ├── 0002-always-load-ZFS-module-on-boot.patch │ │ ├── 0003-Fix-the-path-to-the-zed-binary-on-the-systemd-unit.patch │ │ ├── 0004-import-with-d-dev-disk-by-id-in-scan-service.patch │ │ ├── 0005-Enable-zed-emails.patch │ │ ├── 0006-dont-symlink-zed-scripts.patch │ │ ├── 0007-Use-installed-python3.patch │ │ ├── 0008-Add-systemd-unit-for-importing-specific-pools.patch │ │ ├── 0009-Patch-move-manpage-arcstat-1-to-arcstat-8.patch │ │ ├── 0010-arcstat-Fix-integer-division-with-python3.patch │ │ └── 0011-arc-stat-summary-guard-access-to-l2arc-MFU-MRU-stats.patch ├── rules ├── rules.d │ ├── arch │ │ ├── amd64.mk │ │ └── arm64.mk │ └── common.mk ├── source │ └── format └── templates │ ├── control.in │ ├── pve-headers.postinst.in │ ├── pve-kernel.postinst.in │ ├── pve-kernel.postrm.in │ └── pve-kernel.prerm.in ├── runner ├── Dockerfile └── entrypoint.sh └── scripts ├── check.sh ├── update.sh └── version.sh /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://www.buymeacoffee.com/fabianishere 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Kernel Build 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | build: 7 | name: Build 8 | runs-on: [self-hosted] 9 | if: ${{ !contains(github.event.head_commit.message, 'skip ci') }} 10 | steps: 11 | - name: Clean Workspace 12 | run: rm -rf *.deb *.ddeb *.build *.buildinfo *.changes 13 | - name: Checkout Sources 14 | uses: actions/checkout@v3 15 | with: 16 | submodules: recursive 17 | path: pve-edge-kernel 18 | - name: Clean Repository 19 | run: git -C pve-edge-kernel submodule foreach git clean -ffdx 20 | - name: Build Kernel 21 | run: | 22 | rm -rf *.deb *.ddeb *.build *.buildinfo *.changes 23 | cd pve-edge-kernel 24 | debian/rules debian/control 25 | debuild -e CCACHE_DIR=/var/cache/ccache --prepend-path=/usr/lib/ccache --jobs=auto -b -uc -us 26 | - name: Upload Artifacts 27 | uses: actions/upload-artifact@v3 28 | with: 29 | name: debs 30 | path: "*.deb" 31 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Kernel Release 2 | 3 | on: 4 | pull_request: 5 | types: [closed] 6 | branches: 7 | - v* 8 | - flavor/*/v* 9 | workflow_dispatch: 10 | 11 | jobs: 12 | build: 13 | name: Build (${{ matrix.debian }}) 14 | runs-on: [self-hosted, '${{ matrix.debian }}'] 15 | if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} 16 | strategy: 17 | matrix: 18 | debian: [bullseye] 19 | include: 20 | - build_profile: 'generic' 21 | build_cc: gcc 22 | build_cflags: '' 23 | steps: 24 | - name: Clean Workspace 25 | run: rm -rf *.deb *.ddeb *.build *.buildinfo *.changes 26 | - name: Checkout Sources 27 | uses: actions/checkout@v3 28 | with: 29 | submodules: recursive 30 | path: pve-edge-kernel 31 | - name: Clean Repository 32 | run: git -C pve-edge-kernel submodule foreach git clean -ffdx 33 | - name: Build Kernel 34 | run: | 35 | cd pve-edge-kernel 36 | debian/rules debian/control 37 | if [ "$PVE_BUILD_PROFILE" != "generic" ]; then 38 | debchange -l +$PVE_BUILD_PROFILE -D edge --force-distribution -U -M "Specialization for $PVE_BUILD_PROFILE" 39 | fi 40 | debuild --no-lintian -e PVE* -e CCACHE_DIR=/var/cache/ccache --prepend-path=/usr/lib/ccache --jobs=auto -b -uc -us 41 | env: 42 | PVE_BUILD_PROFILE: ${{ matrix.build_profile }} 43 | PVE_KERNEL_CC: ${{ matrix.build_cc }} 44 | PVE_KERNEL_CFLAGS: ${{ matrix.build_cflags }} 45 | PVE_ZFS_CC: ${{ matrix.build_cc }} 46 | - name: Upload Artifacts 47 | uses: actions/upload-artifact@v3 48 | with: 49 | name: ${{ matrix.debian }}-${{ matrix.build_profile }} 50 | path: "*.deb" 51 | publish: 52 | name: Publish 53 | runs-on: ubuntu-latest 54 | if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true }} 55 | needs: build 56 | steps: 57 | - name: Checkout Sources 58 | uses: actions/checkout@v3 59 | - name: Download Artifacts 60 | uses: actions/download-artifact@v3 61 | with: 62 | path: artifacts 63 | - name: Delete Debug Symbols 64 | run: rm -f artifacts/*/*dbgsym*.deb 65 | - name: Format Release Name 66 | id: format_release 67 | run: | 68 | echo "release=$(scripts/version.sh)" >> $GITHUB_OUTPUT 69 | changelog=$(dpkg-parsechangelog -c 1 -l debian/changelog) 70 | echo "changelog<> $GITHUB_OUTPUT 71 | - name: Create Release 72 | uses: ncipollo/release-action@v1 73 | with: 74 | commit: ${{ github.sha }} 75 | tag: v${{ steps.format_release.outputs.release }} 76 | body: ${{ steps.format_release.outputs.changelog }} 77 | token: ${{ secrets.PAT }} 78 | artifacts: "artifacts/bullseye-generic/pve-headers-*.deb,artifacts/bullseye-generic/pve-kernel-*.deb,artifacts/bullseye-generic/linux-tools-*.deb" 79 | - name: Release to CloudSmith 80 | run: | 81 | pip install --upgrade cloudsmith-cli 82 | find artifacts/bullseye-generic \ 83 | -name '*.deb' \ 84 | -not -name "*dbgsym*" \ 85 | -exec cloudsmith push deb pve-edge/kernel/debian/bullseye {} --republish \; 86 | env: 87 | CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} 88 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: Kernel Update 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | tag: 7 | description: 'Tag of the Linux Kernel to update to' 8 | required: true 9 | version: 10 | description: 'Custom version number' 11 | required: false 12 | release: 13 | description: 'Custom release number' 14 | required: false 15 | 16 | jobs: 17 | update: 18 | name: Update 19 | runs-on: [ubuntu-latest] 20 | steps: 21 | - name: Checkout Sources 22 | uses: actions/checkout@v3 23 | with: 24 | submodules: recursive 25 | - name: Setup System Dependencies 26 | run: sudo apt update && sudo apt install devscripts 27 | - name: Update Kernel 28 | id: update 29 | run: | 30 | TAG=${{ github.event.inputs.tag }} 31 | VERSION=${{ github.event.inputs.version }} 32 | RELEASE=${{ github.event.inputs.release }} 33 | VERSION_OPT=${VERSION:+-v ${VERSION}} 34 | RELEASE_OPT=${RELEASE:+-r ${RELEASE}} 35 | ./scripts/update.sh -t ${{ github.event.inputs.tag }} $VERSION_OPT $RELEASE_OPT 36 | echo "version=$(scripts/version.sh -L)" >> $GITHUB_OUTPUT 37 | echo "full=$(scripts/version.sh)" >> $GITHUB_OUTPUT 38 | changelog=$(dpkg-parsechangelog -c 1 -l debian/changelog) 39 | echo "changelog<> $GITHUB_OUTPUT 40 | echo "branch=${GITHUB_REF##*/}" >> $GITHUB_OUTPUT 41 | - name: Create Pull Request 42 | uses: peter-evans/create-pull-request@v4 43 | with: 44 | token: ${{ secrets.PAT }} # Custom token needed to recursively trigger workflows 45 | author: Fabian Mastenbroek 46 | commit-message: | 47 | Add Linux ${{ steps.update.outputs.version }} 48 | 49 | This change updates the kernel to Linux ${{ steps.update.outputs.version }}. 50 | branch: staging/v${{ steps.update.outputs.full }} 51 | branch-suffix: short-commit-hash 52 | delete-branch: true 53 | title: "Add Linux ${{ steps.update.outputs.version }}" 54 | body: | 55 | Automated pull request to update the kernel to Linux ${{ steps.update.outputs.version }}. 56 | 57 | **Changelog:** 58 | ``` 59 | ${{ steps.update.outputs.changelog }} 60 | ``` 61 | labels: | 62 | release 63 | -------------------------------------------------------------------------------- /.github/workflows/watch.yml: -------------------------------------------------------------------------------- 1 | name: Kernel Watch 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '0 12 * * *' # Every day 7 | 8 | jobs: 9 | check: 10 | name: Check for new Release 11 | runs-on: [ubuntu-latest] 12 | strategy: 13 | matrix: 14 | branch: [] 15 | steps: 16 | - name: Checkout Sources 17 | uses: actions/checkout@v3 18 | with: 19 | ref: ${{ matrix.branch }} 20 | submodules: recursive 21 | - name: Setup System Dependencies 22 | run: sudo apt install jq curl 23 | - name: Check for Release 24 | id: check 25 | run: | 26 | NEW=$(scripts/check.sh ${{ matrix.branch }}) 27 | if [[ -z $NEW ]]; then 28 | echo "No new release found" 29 | exit 0 30 | fi 31 | echo "Found new Linux kernel version $NEW" 32 | STAGING=$(git ls-remote --heads origin "staging/v$NEW*") 33 | if [[ $STAGING ]]; then 34 | echo "Existing staging update found" 35 | exit 0 36 | fi 37 | echo "No staging update found: triggering update" 38 | echo "version=$NEW" >> $GITHUB_OUTPUT 39 | - name: Trigger Update 40 | if: ${{ steps.check.outputs.version }} 41 | uses: benc-uk/workflow-dispatch@v1 42 | with: 43 | workflow: Kernel Update 44 | token: ${{ secrets.PAT }} # Custom token needed to recursively trigger workflows 45 | inputs: '{ "tag": "v${{ steps.check.outputs.version }}" }' 46 | ref: ${{ matrix.branch }} 47 | 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build artifacts 2 | build 3 | *.prepared 4 | config*.org 5 | *.deb 6 | *.ddeb 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "zfs"] 2 | path = zfs 3 | url = https://github.com/openzfs/zfs.git 4 | 5 | [submodule "linux"] 6 | path = linux 7 | url = git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Proxmox Edge kernels 2 | Custom Linux kernels for Proxmox VE 7. 3 | 4 | #### Available Versions 5 | 1. Linux 6.0 6 | 7 | Older builds are still available at the [Releases](https://github.com/fabianishere/pve-edge-kernel/releases) page. 8 | 9 | ## Installation 10 | [![Hosted By: Cloudsmith](https://img.shields.io/badge/OSS%20hosting%20by-cloudsmith-blue?logo=cloudsmith&style=flat-square)](https://cloudsmith.com) 11 | 12 | First, set up our Debian repository on your Proxmox installation: 13 | 1. **Add the repository's GPG key:** 14 | ```bash 15 | curl -1sLf 'https://dl.cloudsmith.io/public/pve-edge/kernel/gpg.8EC01CCF309B98E7.key' | gpg --dearmor -o /usr/share/keyrings/pve-edge-kernel.gpg 16 | ``` 17 | 2. **Set up the `pve-edge-kernel` repository:** 18 | ```bash 19 | echo "deb [signed-by=/usr/share/keyrings/pve-edge-kernel.gpg] https://dl.cloudsmith.io/public/pve-edge/kernel/deb/debian bullseye main" > /etc/apt/sources.list.d/pve-edge-kernel.list 20 | ``` 21 | 3. **Install a kernel package:** 22 | ```bash 23 | apt update 24 | apt install pve-kernel-6.0-edge 25 | ``` 26 | 27 | Package repository hosting is graciously provided by [Cloudsmith](https://cloudsmith.com). 28 | Cloudsmith is the only fully hosted, cloud-native, universal package management solution, that 29 | enables your organization to create, store and share packages in any format, to any place, with total 30 | confidence. 31 | 32 | ### Manual 33 | Alternatively, you may manually install the kernels. Select from the [Releases](https://github.com/fabianishere/pve-edge-kernel/releases) 34 | page the kernel version you want to install and download the appropriate Debian package. 35 | Then, you can install the package as follows: 36 | 37 | ```sh 38 | apt install ./pve-kernel-VERSION_amd64.deb 39 | ``` 40 | 41 | ## Building manually 42 | You may also choose to manually build one of these kernels yourself. 43 | 44 | #### Prerequisites 45 | Make sure you have at least 10 GB of free space available and have the following 46 | packages installed: 47 | 48 | ```bash 49 | apt install devscripts debhelper equivs git 50 | ``` 51 | 52 | #### Obtaining the source 53 | Obtain the source code as follows: 54 | ```bash 55 | git clone https://github.com/fabianishere/pve-edge-kernel 56 | cd pve-edge-kernel 57 | ``` 58 | Then, select the branch of your likings (e.g. `v6.0.x`) and update the submodules: 59 | ```bash 60 | git checkout v6.0.x 61 | git submodule update --init --depth=1 --recursive linux 62 | git submodule update --init --recursive 63 | ``` 64 | 65 | #### Building 66 | First, generate the Debian control file for your kernel by running the following 67 | in your command prompt: 68 | ```bash 69 | debian/rules debian/control 70 | ``` 71 | Before we build, make sure you have installed the build dependencies: 72 | ```bash 73 | sudo mk-build-deps -i 74 | ``` 75 | Invoking the following command will build the kernel and its associated packages: 76 | ```bash 77 | debuild -ePVE* --jobs=auto -b -uc -us 78 | ``` 79 | The Makefile provides several environmental variables to control: 80 | 81 | 1. `PVE_KERNEL_CC` 82 | The compiler to use for the kernel build. 83 | 2. `PVE_KERNEL_CFLAGS` 84 | The compilation options to use for the kernel build. Use this variable to specify 85 | the optimization level or micro architecture to build for. 86 | 87 | Kernel options may be controlled from [debian/config/config.pve](debian/config/config.pve). To build with 88 | additional patches, you may add them to the [debian/patches/pve](debian/patches/pve) directory 89 | and update the [series](debian/patches/series.linux) file accordingly. 90 | 91 | ## Removal 92 | Use `apt` to remove individual kernel packages from your system. If you want 93 | to remove all packages from a particular kernel release, use the following 94 | command: 95 | 96 | ```bash 97 | apt remove pve-kernel-6.0*edge pve-headers-6.0*edge 98 | ``` 99 | 100 | ## Contributing 101 | Questions, suggestions and contributions are welcome and appreciated! 102 | You can contribute in various meaningful ways: 103 | 104 | * Report a bug through [Github issues](https://github.com/fabianishere/pve-edge-kernel/issues). 105 | * Propose new patches and flavors for the project. 106 | * Contribute improvements to the documentation. 107 | * Provide feedback about how we can improve the project. 108 | -------------------------------------------------------------------------------- /crack.bundle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fabianishere/pve-edge-kernel/c0cf4f9dcd1c9a94be0d87596d0cda26e81954f1/crack.bundle -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | pve-kernel (6.1.0-1) edge; urgency=medium 2 | 3 | * Update to Linux 6.1 4 | * Update to ZFS 2.1.7 5 | 6 | -- Fabian Mastenbroek Sat, 17 Dec 2022 17:00:00 +0000 7 | 8 | pve-kernel (6.0.0-1) edge; urgency=medium 9 | 10 | * Update to Linux 6.0 11 | * Update to ZFS 2.1.6 12 | 13 | -- Fabian Mastenbroek Mon, 03 Oct 2022 16:00:00 +0000 14 | 15 | pve-kernel (5.19.0-1) edge; urgency=medium 16 | 17 | * Update to Linux 5.19 18 | 19 | -- Fabian Mastenbroek Wed, 03 Aug 2022 16:00:00 +0000 20 | 21 | pve-kernel (5.18.0-1) edge; urgency=medium 22 | 23 | * Update to Linux 5.18 24 | * Update to ZFS 2.1.5 25 | 26 | -- Fabian Mastenbroek Mon, 26 Mar 2022 20:00:00 +0000 27 | 28 | pve-kernel (5.17.0-1) edge; urgency=medium 29 | 30 | * Update to Linux 5.17 31 | * Update to ZFS 2.1.3 32 | 33 | -- Fabian Mastenbroek Mon, 21 Mar 2022 13:00:00 +0000 34 | 35 | pve-kernel (5.16.0-1) edge; urgency=medium 36 | 37 | * Disable UBNSAN (see issue #164 and #200). 38 | * Update to ZFS 2.1.2 39 | * Fix AppArmor incompatibilities 40 | 41 | -- Fabian Mastenbroek Mon, 10 Jan 2022 11:00:00 +0000 42 | 43 | pve-kernel (5.15.0-1) edge; urgency=medium 44 | 45 | * Update to Linux 5.15. 46 | * Update to OpenZFS 2.1.1 47 | * Drop kernel release from version 48 | 49 | -- Fabian Mastenbroek Tue, 2 Nov 2021 10:00:00 +0000 50 | 51 | pve-kernel (5.14.0-1) edge; urgency=medium 52 | 53 | * Update to Linux 5.14. 54 | * Update to OpenZFS 2.1.0. 55 | 56 | -- Fabian Mastenbroek Mon, 30 Aug 2021 11:00:00 +0000 57 | 58 | pve-kernel (5.13.0-1) edge; urgency=medium 59 | 60 | * Update to Linux 5.13. 61 | * Update to OpenZFS 2.1.0-rc7. 62 | 63 | -- Fabian Mastenbroek Mon, 28 Jun 2021 17:00:00 +0000 64 | 65 | pve-kernel (5.12.0-1) edge; urgency=medium 66 | 67 | * Update to Linux 5.12. 68 | * Update to OpenZFS 2.1.0-rc5. 69 | 70 | -- Fabian Mastenbroek Thu, 18 Feb 2021 10:49:30 +0000 71 | 72 | pve-kernel (5.11.0-1) edge; urgency=medium 73 | 74 | * Update to Linux 5.11. 75 | * Properly add module.lds to headers package. 76 | 77 | -- Fabian Mastenbroek Thu, 18 Feb 2021 10:49:30 +0000 78 | 79 | pve-kernel (5.10.0-1) edge; urgency=medium 80 | 81 | * Update to Linux 5.10. 82 | 83 | -- Fabian Mastenbroek Sun, 24 Jan 2021 12:53:48 +0000 84 | 85 | pve-kernel (5.9.0-1) edge; urgency=medium 86 | 87 | * Update to Linux 5.9. 88 | 89 | -- Fabian Mastenbroek Thu, 12 Nov 2020 16:49:51 +0000 90 | 91 | pve-kernel (5.8.0-1) edge; urgency=medium 92 | 93 | * update to Linux 5.8 based on Ubuntu 5.8.0-12.13 94 | 95 | -- Fabian Mastenbroek Sun, 9 Aug 2020 14:58:00 +0200 96 | 97 | pve-kernel (5.7.0-1) edge; urgency=medium 98 | 99 | * update to Linux 5.7 based on Ubuntu 5.7.0-5.6 100 | 101 | -- Fabian Mastenbroek Mon, 1 Jun 2020 19:57:12 +0200 102 | 103 | pve-kernel (5.6.0-1) edge; urgency=medium 104 | 105 | * update to Linux 5.6. 106 | 107 | -- Fabian Mastenbroek Sat, 2 May 2020 21:07:10 +0200 108 | 109 | pve-kernel (5.5.0-1) edge; urgency=medium 110 | 111 | * update to Linux 5.5. 112 | 113 | -- Fabian Mastenbroek Thu, 30 Apr 2020 18:30:30 +0200 114 | 115 | pve-kernel (5.4.30-1) edge; urgency=medium 116 | 117 | * update to Ubuntu-5.4.0-24.28 118 | 119 | * bump ABI to 5.4.30-1 120 | 121 | -- Fabian Mastenbroek Tue, 28 Apr 2020 14:11:30 +0200 122 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 11 2 | -------------------------------------------------------------------------------- /debian/config/config.pve: -------------------------------------------------------------------------------- 1 | CONFIG_DEBUG_INFO_NONE=y # PVE strips debug info afterwards 2 | CONFIG_INTEL_MEI_WDT=m 3 | CONFIG_SND_PCM_OSS=n 4 | CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y 5 | CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=n 6 | CONFIG_CEPH_FS=m 7 | CONFIG_BLK_DEV_NBD=m 8 | CONFIG_BLK_DEV_RBD=m 9 | CONFIG_SND_PCSP=n 10 | CONFIG_BCACHE=m 11 | CONFIG_JFS_FS=m 12 | CONFIG_HFS_FS=m 13 | CONFIG_HFSPLUS_FS=m 14 | CONFIG_CIFS_SMB_DIRECT=y 15 | CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y 16 | CONFIG_BRIDGE=y 17 | CONFIG_BRIDGE_NETFILTER=y 18 | CONFIG_BLK_DEV_SD=y 19 | CONFIG_BLK_DEV_SR=y 20 | CONFIG_BLK_DEV_DM=y 21 | CONFIG_BLK_DEV_NVME=y 22 | CONFIG_NLS_ISO8859_1=y 23 | CONFIG_INPUT_EVBUG=n 24 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=n 25 | CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=n 26 | CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y 27 | CONFIG_SYSFB_SIMPLEFB=y 28 | CONFIG_DRM_SIMPLEDRM=y 29 | CONFIG_MODULE_SIG=n 30 | CONFIG_MODULE_SIG_KEY="" 31 | CONFIG_MODULE_SIG_ALL=n 32 | CONFIG_MEMCG_DISABLED=n 33 | CONFIG_MEMCG_SWAP_ENABLED=y 34 | CONFIG_HYPERV=y 35 | CONFIG_VFIO_IOMMU_TYPE1=m 36 | CONFIG_VFIO_VIRQFD=m 37 | CONFIG_VFIO=m 38 | CONFIG_VFIO_PCI=m 39 | CONFIG_USB_XHCI_HCD=m 40 | CONFIG_USB_XHCI_PCI=m 41 | CONFIG_USB_EHCI_HCD=m 42 | CONFIG_USB_EHCI_PCI=m 43 | CONFIG_USB_EHCI_HCD_PLATFORM=m 44 | CONFIG_USB_OHCI_HCD=m 45 | CONFIG_USB_OHCI_HCD_PCI=m 46 | CONFIG_USB_OHCI_HCD_PLATFORM=m 47 | CONFIG_USB_OHCI_HCD_SSB=n 48 | CONFIG_USB_UHCI_HCD=m 49 | CONFIG_USB_SL811_HCD_ISO=n 50 | CONFIG_MEMCG_KMEM=y 51 | CONFIG_DEFAULT_CFQ=n 52 | CONFIG_DEFAULT_DEADLINE=y 53 | CONFIG_MODVERSIONS=y 54 | CONFIG_DEFAULT_SECURITY_DAC=n 55 | CONFIG_DEFAULT_SECURITY_APPARMOR=y 56 | CONFIG_DEFAULT_SECURITY=apparmor 57 | CONFIG_UNWINDER_ORC=n 58 | CONFIG_UNWINDER_GUESS=n 59 | CONFIG_UNWINDER_FRAME_POINTER=y 60 | CONFIG_SYSTEM_TRUSTED_KEYS="" 61 | CONFIG_SYSTEM_REVOCATION_KEYS="" 62 | CONFIG_SECURITY_LOCKDOWN_LSM=n 63 | CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=n 64 | CONFIG_LSM="yama,integrity,apparmor" 65 | CONFIG_PAGE_TABLE_ISOLATION=y 66 | CONFIG_UBSAN=n 67 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: Linux kernel 3 | Source: https://www.kernel.org/pub/linux/kernel/ 4 | Files-Excluded: linux/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt 5 | linux/arch/powerpc/platforms/8xx/micropatch.c 6 | linux/drivers/media/usb/dvb-usb/af9005-script.h 7 | linux/drivers/media/i2c/vs6624.c 8 | linux/drivers/net/appletalk/cops* 9 | linux/drivers/video/fbdev/nvidia 10 | linux/drivers/video/fbdev/riva 11 | Comment: 12 | The 'perf' tool is dynamically linked with the Python interpreter, 13 | which is itself dynamically linked with OpenSSL, which is not 14 | GPL-compatible. However, since perf itself does not link with or use 15 | OpenSSL, we believe that this indirect linking does not require 16 | additional permissions beyond the GPL. 17 | 18 | Files: linux/* 19 | Copyright: 1991-2012 Linus Torvalds and many others 20 | License: GPL-2 21 | 22 | Files: zfs/* 23 | Copyright: ZFS authors 24 | License: CDDL 25 | 26 | Files: debian/* 27 | Copyright: 2021 Fabian Mastenbroek 28 | License: GPL-2 29 | 30 | Files: linux/drivers/crypto/vmx/*.pl 31 | Copyright: 2006,2014 Andy Polyakov 32 | License: CRYPTOGAMS 33 | All rights reserved. 34 | . 35 | Redistribution and use in source and binary forms, with or without 36 | modification, are permitted provided that the following conditions 37 | are met: 38 | . 39 | * Redistributions of source code must retain copyright notices, this 40 | list of conditions and the following disclaimer. 41 | * Redistributions in binary form must reproduce the above copyright 42 | notice, this list of conditions and the following disclaimer in the 43 | documentation and/or other materials provided with the 44 | distribution. 45 | * Neither the name of the CRYPTOGAMS nor the names of its copyright 46 | holder and contributors may be used to endorse or promote products 47 | derived from this software without specific prior written 48 | permission. 49 | . 50 | ALTERNATIVELY, provided that this notice is retained in full, this 51 | product may be distributed under the terms of the GNU General Public 52 | License (GPL), in which case the provisions of the GPL apply INSTEAD 53 | OF those given above. 54 | . 55 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 56 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 57 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 58 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 59 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 60 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 61 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 62 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 63 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 64 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 65 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 66 | 67 | Files: linux/fs/nls/mac-* 68 | Copyright: 1991-2012 Unicode, Inc. 69 | License: Unicode-data 70 | All rights reserved. Distributed under the Terms of Use in 71 | http://www.unicode.org/copyright.html. 72 | . 73 | Permission is hereby granted, free of charge, to any person obtaining a 74 | copy of the Unicode data files and any associated documentation (the "Data 75 | Files") or Unicode software and any associated documentation (the 76 | "Software") to deal in the Data Files or Software without restriction, 77 | including without limitation the rights to use, copy, modify, merge, 78 | publish, distribute, and/or sell copies of the Data Files or Software, and 79 | to permit persons to whom the Data Files or Software are furnished to do 80 | so, provided that (a) the above copyright notice(s) and this permission 81 | notice appear with all copies of the Data Files or Software, (b) both the 82 | above copyright notice(s) and this permission notice appear in associated 83 | documentation, and (c) there is clear notice in each modified Data File or 84 | in the Software as well as in the documentation associated with the Data 85 | File(s) or Software that the data or software has been modified. 86 | . 87 | THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 88 | KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 89 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF 90 | THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS 91 | INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT 92 | OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 93 | USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 94 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 95 | PERFORMANCE OF THE DATA FILES OR SOFTWARE. 96 | . 97 | Except as contained in this notice, the name of a copyright holder shall 98 | not be used in advertising or otherwise to promote the sale, use or other 99 | dealings in these Data Files or Software without prior written 100 | authorization of the copyright holder. 101 | 102 | Files: linux/include/xen/interface/* 103 | Copyright: 2002-2006 Keir Fraser 104 | 2004 Tim Deegan 105 | 2004 Andrew Warfield 106 | 2005 Nguyen Anh Quynh 107 | 2005-2006 IBM Corporation 108 | 2005 Anthony Liguori 109 | 2005 Rusty Russell 110 | 2005-2006 XenSource Ltd. 111 | 2006 Ian Campbell 112 | 2006 Red Hat, Inc. 113 | 2010 Ryan Wilson 114 | License: Xen-interface 115 | Permission is hereby granted, free of charge, to any person obtaining a copy 116 | of this software and associated documentation files (the "Software"), to 117 | deal in the Software without restriction, including without limitation the 118 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 119 | sell copies of the Software, and to permit persons to whom the Software is 120 | furnished to do so, subject to the following conditions: 121 | . 122 | The above copyright notice and this permission notice shall be included in 123 | all copies or substantial portions of the Software. 124 | . 125 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 126 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 127 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 128 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 129 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 130 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 131 | DEALINGS IN THE SOFTWARE. 132 | 133 | Files: linux/scripts/extract-cert.c scripts/sign-file.c 134 | Copyright: 2014-2015 Red Hat, Inc. 135 | 2015 Intel Corporation 136 | License: LGPL-2.1 137 | 138 | Files: linux/tools/lib/bpf/* 139 | Copyright: 2015-2020 Linus Torvalds and many others 140 | License: LGPL-2.1 or BSD-2-clause 141 | 142 | Files: linux/tools/bpf/bpftool/* 143 | Copyright: 2017-2020 Linus Torvalds and many others 144 | License: GPL-2 or BSD-2-clause 145 | 146 | License: BSD-2-clause 147 | Redistribution and use in source and binary forms, with or without 148 | modification, are permitted provided that the following conditions are met: 149 | . 150 | 1. Redistributions of source code must retain the above copyright notice, 151 | this list of conditions and the following disclaimer. 152 | . 153 | 2. Redistributions in binary form must reproduce the above copyright 154 | notice, this list of conditions and the following disclaimer in the 155 | documentation and/or other materials provided with the distribution. 156 | . 157 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 158 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 159 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 160 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 161 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 162 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 163 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 164 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 165 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 166 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 167 | POSSIBILITY OF SUCH DAMAGE. 168 | 169 | License: GPL-2 170 | This package is free software; you can redistribute it and/or modify 171 | it under the terms of the GNU General Public License version 2 as 172 | published by the Free Software Foundation. 173 | . 174 | This package is distributed in the hope that it will be useful, 175 | but WITHOUT ANY WARRANTY; without even the implied warranty of 176 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 177 | GNU General Public License for more details. 178 | . 179 | You should have received a copy of the GNU General Public License 180 | along with this package; if not, write to the Free Software 181 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 182 | . 183 | On Debian systems, the complete text of the GNU General Public License version 184 | 2 can be found in `/usr/share/common-licenses/GPL-2'. 185 | 186 | License: LGPL-2.1 187 | This program is free software; you can redistribute it and/or modify it 188 | under the terms of the GNU Lesser General Public License as published by 189 | the Free Software Foundation; either version 2.1 of the License, or 190 | (at your option) any later version. 191 | . 192 | This program is distributed in the hope that it will be useful, but 193 | WITHOUT ANY WARRANTY; without even the implied warranty of 194 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 195 | Lesser General Public License for more details. 196 | . 197 | You should have received a copy of the GNU Lesser General Public License 198 | along with this program; If not, see . 199 | . 200 | On Debian systems, the complete text of the GNU Lesser General Public 201 | License version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. 202 | 203 | License: GPL-2+ or X11 204 | This file is dual-licensed: you can use it either under the terms 205 | of the GPL or the X11 license, at your option. Note that this dual 206 | licensing only applies to this file, and not this project as a 207 | whole. 208 | . 209 | a) This file is free software; you can redistribute it and/or 210 | modify it under the terms of the GNU General Public License as 211 | published by the Free Software Foundation; either version 2 of the 212 | License, or (at your option) any later version. 213 | . 214 | This file is distributed in the hope that it will be useful, 215 | but WITHOUT ANY WARRANTY; without even the implied warranty of 216 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 217 | GNU General Public License for more details. 218 | . 219 | Or, alternatively, 220 | . 221 | b) Permission is hereby granted, free of charge, to any person 222 | obtaining a copy of this software and associated documentation 223 | files (the "Software"), to deal in the Software without 224 | restriction, including without limitation the rights to use, 225 | copy, modify, merge, publish, distribute, sublicense, and/or 226 | sell copies of the Software, and to permit persons to whom the 227 | Software is furnished to do so, subject to the following 228 | conditions: 229 | . 230 | The above copyright notice and this permission notice shall be 231 | included in all copies or substantial portions of the Software. 232 | . 233 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 234 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 235 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 236 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 237 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 238 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 239 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 240 | OTHER DEALINGS IN THE SOFTWARE. 241 | 242 | License: CDDL 243 | The contents of this file are subject to the terms of the 244 | Common Development and Distribution License (the "License"). 245 | You may not use this file except in compliance with the License. 246 | 247 | You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 248 | or http://www.opensolaris.org/os/licensing. 249 | See the License for the specific language governing permissions 250 | and limitations under the License. 251 | 252 | When distributing Covered Code, include this CDDL HEADER in each 253 | file and include the License file at usr/src/OPENSOLARIS.LICENSE. 254 | If applicable, add the following below this CDDL HEADER, with the 255 | fields enclosed by brackets "[]" replaced with your own identifying 256 | information: Portions Copyright [yyyy] [name of copyright owner] 257 | -------------------------------------------------------------------------------- /debian/patches/pve/0001-Make-mkcompile_h-accept-an-alternate-timestamp-strin.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Ben Hutchings 3 | Date: Tue, 12 May 2015 19:29:22 +0100 4 | Subject: [PATCH] Make mkcompile_h accept an alternate timestamp string 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=UTF-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | We want to include the Debian version in the utsname::version string 10 | instead of a full timestamp string. However, we still need to provide 11 | a standard timestamp string for gen_initramfs_list.sh to make the 12 | kernel image reproducible. 13 | 14 | Make mkcompile_h use $KBUILD_BUILD_VERSION_TIMESTAMP in preference to 15 | $KBUILD_BUILD_TIMESTAMP. 16 | 17 | Signed-off-by: Fabian Grünbichler 18 | Signed-off-by: Thomas Lamprecht 19 | --- 20 | init/Makefile | 2 +- 21 | 1 file changed, 1 insertion(+), 1 deletion(-) 22 | 23 | diff --git a/init/Makefile b/init/Makefile 24 | index 8316c23bead2..e99b8de4a93a 100644 25 | --- a/init/Makefile 26 | +++ b/init/Makefile 27 | @@ -29,7 +29,7 @@ preempt-flag-$(CONFIG_PREEMPT_DYNAMIC) := PREEMPT_DYNAMIC 28 | preempt-flag-$(CONFIG_PREEMPT_RT) := PREEMPT_RT 29 | 30 | build-version = $(or $(KBUILD_BUILD_VERSION), $(build-version-auto)) 31 | -build-timestamp = $(or $(KBUILD_BUILD_TIMESTAMP), $(build-timestamp-auto)) 32 | +build-timestamp = $(or $(KBUILD_BUILD_VERSION_TIMESTAMP), $(KBUILD_BUILD_TIMESTAMP), $(build-timestamp-auto)) 33 | 34 | # Maximum length of UTS_VERSION is 64 chars 35 | filechk_uts_version = \ 36 | -------------------------------------------------------------------------------- /debian/patches/pve/0002-bridge-keep-MAC-of-first-assigned-port.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= 3 | Date: Thu, 14 Sep 2017 11:02:18 +0200 4 | Subject: [PATCH] bridge: keep MAC of first assigned port 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=UTF-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | original commit message: 10 | 11 | Default bridge changes MAC dynamically using smallest MAC of all 12 | connected ports (for no real reason). To avoid problems with ARP 13 | we simply use the MAC of the first connected port. 14 | 15 | Signed-off-by: Fabian Grünbichler 16 | Signed-off-by: Thomas Lamprecht 17 | --- 18 | net/bridge/br_stp_if.c | 5 +---- 19 | 1 file changed, 1 insertion(+), 4 deletions(-) 20 | 21 | diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c 22 | index 75204d36d7f9..1fb5ff73ec1e 100644 23 | --- a/net/bridge/br_stp_if.c 24 | +++ b/net/bridge/br_stp_if.c 25 | @@ -265,10 +265,7 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br) 26 | return false; 27 | 28 | list_for_each_entry(p, &br->port_list, list) { 29 | - if (addr == br_mac_zero || 30 | - memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0) 31 | - addr = p->dev->dev_addr; 32 | - 33 | + addr = p->dev->dev_addr; 34 | } 35 | 36 | if (ether_addr_equal(br->bridge_id.addr, addr)) 37 | -------------------------------------------------------------------------------- /debian/patches/pve/0003-pci-Enable-overrides-for-missing-ACS-capabilities-4..patch: -------------------------------------------------------------------------------- 1 | From 1e30ab2525d8a9ad1fe9a76bef64ff54c2d95e0d Mon Sep 17 00:00:00 2001 2 | From: Mark Weiman 3 | Date: Sun, 12 Aug 2018 11:36:21 -0400 4 | Subject: [PATCH 09/14] pci: Enable overrides for missing ACS capabilities 5 | 6 | This an updated version of Alex Williamson's patch from: 7 | https://lkml.org/lkml/2013/5/30/513 8 | 9 | Original commit message follows: 10 | 11 | PCIe ACS (Access Control Services) is the PCIe 2.0+ feature that 12 | allows us to control whether transactions are allowed to be redirected 13 | in various subnodes of a PCIe topology. For instance, if two 14 | endpoints are below a root port or downsteam switch port, the 15 | downstream port may optionally redirect transactions between the 16 | devices, bypassing upstream devices. The same can happen internally 17 | on multifunction devices. The transaction may never be visible to the 18 | upstream devices. 19 | 20 | One upstream device that we particularly care about is the IOMMU. If 21 | a redirection occurs in the topology below the IOMMU, then the IOMMU 22 | cannot provide isolation between devices. This is why the PCIe spec 23 | encourages topologies to include ACS support. Without it, we have to 24 | assume peer-to-peer DMA within a hierarchy can bypass IOMMU isolation. 25 | 26 | Unfortunately, far too many topologies do not support ACS to make this 27 | a steadfast requirement. Even the latest chipsets from Intel are only 28 | sporadically supporting ACS. We have trouble getting interconnect 29 | vendors to include the PCIe spec required PCIe capability, let alone 30 | suggested features. 31 | 32 | Therefore, we need to add some flexibility. The pcie_acs_override= 33 | boot option lets users opt-in specific devices or sets of devices to 34 | assume ACS support. The "downstream" option assumes full ACS support 35 | on root ports and downstream switch ports. The "multifunction" 36 | option assumes the subset of ACS features available on multifunction 37 | endpoints and upstream switch ports are supported. The "id:nnnn:nnnn" 38 | option enables ACS support on devices matching the provided vendor 39 | and device IDs, allowing more strategic ACS overrides. These options 40 | may be combined in any order. A maximum of 16 id specific overrides 41 | are available. It's suggested to use the most limited set of options 42 | necessary to avoid completely disabling ACS across the topology. 43 | Note to hardware vendors, we have facilities to permanently quirk 44 | specific devices which enforce isolation but not provide an ACS 45 | capability. Please contact me to have your devices added and save 46 | your customers the hassle of this boot option. 47 | 48 | Signed-off-by: Mark Weiman 49 | Signed-off-by: Alexandre Frade 50 | --- 51 | .../admin-guide/kernel-parameters.txt | 9 ++ 52 | drivers/pci/quirks.c | 101 ++++++++++++++++++ 53 | 2 files changed, 110 insertions(+) 54 | 55 | diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt 56 | index 8dee8f68fe15..8aa1f5c6c042 100644 57 | --- a/Documentation/admin-guide/kernel-parameters.txt 58 | +++ b/Documentation/admin-guide/kernel-parameters.txt 59 | @@ -3402,6 +3402,15 @@ 60 | nomsi [MSI] If the PCI_MSI kernel config parameter is 61 | enabled, this kernel boot option can be used to 62 | disable the use of MSI interrupts system-wide. 63 | + pcie_acs_override = 64 | + [PCIE] Override missing PCIe ACS support for: 65 | + downstream 66 | + All downstream ports - full ACS capabilities 67 | + multifunction 68 | + All multifunction devices - multifunction ACS subset 69 | + id:nnnn:nnnn 70 | + Specific device - full ACS capabilities 71 | + Specified as vid:did (vendor/device ID) in hex 72 | noioapicquirk [APIC] Disable all boot interrupt quirks. 73 | Safety option to keep boot IRQs enabled. This 74 | should never be necessary. 75 | diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c 76 | index 320255e5e8f8..8d5808de9071 100644 77 | --- a/drivers/pci/quirks.c 78 | +++ b/drivers/pci/quirks.c 79 | @@ -3483,6 +3483,106 @@ static void quirk_no_bus_reset(struct pci_dev *dev) 80 | dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET; 81 | } 82 | 83 | +static bool acs_on_downstream; 84 | +static bool acs_on_multifunction; 85 | + 86 | +#define NUM_ACS_IDS 16 87 | +struct acs_on_id { 88 | + unsigned short vendor; 89 | + unsigned short device; 90 | +}; 91 | +static struct acs_on_id acs_on_ids[NUM_ACS_IDS]; 92 | +static u8 max_acs_id; 93 | + 94 | +static __init int pcie_acs_override_setup(char *p) 95 | +{ 96 | + if (!p) 97 | + return -EINVAL; 98 | + 99 | + while (*p) { 100 | + if (!strncmp(p, "downstream", 10)) 101 | + acs_on_downstream = true; 102 | + if (!strncmp(p, "multifunction", 13)) 103 | + acs_on_multifunction = true; 104 | + if (!strncmp(p, "id:", 3)) { 105 | + char opt[5]; 106 | + int ret; 107 | + long val; 108 | + 109 | + if (max_acs_id >= NUM_ACS_IDS - 1) { 110 | + pr_warn("Out of PCIe ACS override slots (%d)\n", 111 | + NUM_ACS_IDS); 112 | + goto next; 113 | + } 114 | + 115 | + p += 3; 116 | + snprintf(opt, 5, "%s", p); 117 | + ret = kstrtol(opt, 16, &val); 118 | + if (ret) { 119 | + pr_warn("PCIe ACS ID parse error %d\n", ret); 120 | + goto next; 121 | + } 122 | + acs_on_ids[max_acs_id].vendor = val; 123 | + 124 | + p += strcspn(p, ":"); 125 | + if (*p != ':') { 126 | + pr_warn("PCIe ACS invalid ID\n"); 127 | + goto next; 128 | + } 129 | + 130 | + p++; 131 | + snprintf(opt, 5, "%s", p); 132 | + ret = kstrtol(opt, 16, &val); 133 | + if (ret) { 134 | + pr_warn("PCIe ACS ID parse error %d\n", ret); 135 | + goto next; 136 | + } 137 | + acs_on_ids[max_acs_id].device = val; 138 | + max_acs_id++; 139 | + } 140 | +next: 141 | + p += strcspn(p, ","); 142 | + if (*p == ',') 143 | + p++; 144 | + } 145 | + 146 | + if (acs_on_downstream || acs_on_multifunction || max_acs_id) 147 | + pr_warn("Warning: PCIe ACS overrides enabled; This may allow non-IOMMU protected peer-to-peer DMA\n"); 148 | + 149 | + return 0; 150 | +} 151 | +early_param("pcie_acs_override", pcie_acs_override_setup); 152 | + 153 | +static int pcie_acs_overrides(struct pci_dev *dev, u16 acs_flags) 154 | +{ 155 | + int i; 156 | + 157 | + /* Never override ACS for legacy devices or devices with ACS caps */ 158 | + if (!pci_is_pcie(dev) || 159 | + pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS)) 160 | + return -ENOTTY; 161 | + 162 | + for (i = 0; i < max_acs_id; i++) 163 | + if (acs_on_ids[i].vendor == dev->vendor && 164 | + acs_on_ids[i].device == dev->device) 165 | + return 1; 166 | + 167 | + switch (pci_pcie_type(dev)) { 168 | + case PCI_EXP_TYPE_DOWNSTREAM: 169 | + case PCI_EXP_TYPE_ROOT_PORT: 170 | + if (acs_on_downstream) 171 | + return 1; 172 | + break; 173 | + case PCI_EXP_TYPE_ENDPOINT: 174 | + case PCI_EXP_TYPE_UPSTREAM: 175 | + case PCI_EXP_TYPE_LEG_END: 176 | + case PCI_EXP_TYPE_RC_END: 177 | + if (acs_on_multifunction && dev->multifunction) 178 | + return 1; 179 | + } 180 | + 181 | + return -ENOTTY; 182 | +} 183 | /* 184 | * Some Atheros AR9xxx and QCA988x chips do not behave after a bus reset. 185 | * The device will throw a Link Down error on AER-capable systems and 186 | @@ -4796,6 +4896,8 @@ static const struct pci_dev_acs_enabled { 187 | { PCI_VENDOR_ID_ZHAOXIN, 0x9083, pci_quirk_mf_endpoint_acs }, 188 | /* Zhaoxin Root/Downstream Ports */ 189 | { PCI_VENDOR_ID_ZHAOXIN, PCI_ANY_ID, pci_quirk_zhaoxin_pcie_ports_acs }, 190 | + /* PCIe ACS overrides */ 191 | + { PCI_ANY_ID, PCI_ANY_ID, pcie_acs_overrides }, 192 | { 0 } 193 | }; 194 | 195 | -- 196 | 2.17.1 197 | -------------------------------------------------------------------------------- /debian/patches/pve/0004-kvm-disable-default-dynamic-halt-polling-growth.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= 3 | Date: Thu, 14 Sep 2017 11:09:58 +0200 4 | Subject: [PATCH] kvm: disable default dynamic halt polling growth 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=UTF-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | Signed-off-by: Fabian Grünbichler 10 | Signed-off-by: Thomas Lamprecht 11 | --- 12 | virt/kvm/kvm_main.c | 2 +- 13 | 1 file changed, 1 insertion(+), 1 deletion(-) 14 | 15 | diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c 16 | index fab4d3790578..adae153354c2 100644 17 | --- a/virt/kvm/kvm_main.c 18 | +++ b/virt/kvm/kvm_main.c 19 | @@ -79,7 +79,7 @@ module_param(halt_poll_ns, uint, 0644); 20 | EXPORT_SYMBOL_GPL(halt_poll_ns); 21 | 22 | /* Default doubles per-vcpu halt_poll_ns. */ 23 | -unsigned int halt_poll_ns_grow = 2; 24 | +unsigned int halt_poll_ns_grow = 0; 25 | module_param(halt_poll_ns_grow, uint, 0644); 26 | EXPORT_SYMBOL_GPL(halt_poll_ns_grow); 27 | 28 | -------------------------------------------------------------------------------- /debian/patches/pve/0005-net-core-downgrade-unregister_netdevice-refcount-lea.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Thomas Lamprecht 3 | Date: Wed, 7 Oct 2020 17:18:28 +0200 4 | Subject: [PATCH] net: core: downgrade unregister_netdevice refcount leak from 5 | emergency to error 6 | 7 | Signed-off-by: Thomas Lamprecht 8 | --- 9 | net/core/dev.c | 2 +- 10 | 1 file changed, 1 insertion(+), 1 deletion(-) 11 | 12 | diff --git a/net/core/dev.c b/net/core/dev.c 13 | index 3be256051e99..e79b1695a4cb 100644 14 | --- a/net/core/dev.c 15 | +++ b/net/core/dev.c 16 | @@ -10273,7 +10273,7 @@ static struct net_device *netdev_wait_allrefs_any(struct list_head *list) 17 | if (time_after(jiffies, warning_time + 18 | READ_ONCE(netdev_unregister_timeout_secs) * HZ)) { 19 | list_for_each_entry(dev, list, todo_list) { 20 | - pr_emerg("unregister_netdevice: waiting for %s to become free. Usage count = %d\n", 21 | + pr_err("unregister_netdevice: waiting for %s to become free. Usage count = %d\n", 22 | dev->name, netdev_refcnt_read(dev)); 23 | ref_tracker_dir_print(&dev->refcnt_tracker, 10); 24 | } 25 | -------------------------------------------------------------------------------- /debian/patches/pve/0006-do-not-generate-split-BTF-type-info-per-default.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= 3 | Date: Thu, 14 Sep 2017 11:09:58 +0200 4 | Subject: [PATCH] do not generate split BTF type info per default 5 | 6 | This reverts commit a8ed1a0607cfa5478ff6009539f44790c4d0956d. 7 | 8 | It breaks ZFS sometimes: 9 | https://github.com/openzfs/zfs/issues/12301#issuecomment-873303739 10 | 11 | Signed-off-by: Thomas Lamprecht 12 | --- 13 | lib/Kconfig.debug | 2 +- 14 | 1 file changed, 1 insertion(+), 1 deletion(-) 15 | 16 | diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug 17 | index 3638b3424be5..43172078db03 100644 18 | --- a/lib/Kconfig.debug 19 | +++ b/lib/Kconfig.debug 20 | @@ -365,7 +365,7 @@ config PAHOLE_HAS_BTF_TAG 21 | these attributes, so make the config depend on CC_IS_CLANG. 22 | 23 | config DEBUG_INFO_BTF_MODULES 24 | - def_bool y 25 | + def_bool n 26 | depends on DEBUG_INFO_BTF && MODULES && PAHOLE_HAS_SPLIT_BTF 27 | help 28 | Generate compact split BTF type information for kernel modules. 29 | -------------------------------------------------------------------------------- /debian/patches/pve/0007-Ubuntu-remove-leftover-reference-to-ubuntu-hio-drive.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Thomas Lamprecht 3 | Date: Sat, 12 Mar 2022 16:19:10 +0100 4 | Subject: [PATCH] Ubuntu: remove leftover reference to ubuntu/hio driver 5 | 6 | A single reference to the hio driver was forgotten when it was removed 7 | recently. While this reference is not a problem for the build itself, it 8 | breaks the __clean target from 'scripts/Makefile.clean' here, as make 9 | cannot enter the "ubuntu/hio" folder for cleaning due to ENOENT. 10 | 11 | Fixes: 4ea6dd9afa0a0d ("UBUNTU: Remove ubuntu/hio driver") 12 | Signed-off-by: Thomas Lamprecht 13 | --- 14 | ubuntu/Makefile | 4 ---- 15 | 1 file changed, 4 deletions(-) 16 | 17 | diff --git a/ubuntu/Makefile b/ubuntu/Makefile 18 | index 27fa95ba242a..3bfc4494c069 100644 19 | --- a/ubuntu/Makefile 20 | +++ b/ubuntu/Makefile 21 | @@ -15,10 +15,6 @@ 22 | ## 23 | ## 24 | ## 25 | -obj-$(CONFIG_HIO) += hio/ 26 | -## 27 | -## 28 | -## 29 | obj-$(CONFIG_UBUNTU_HOST) += ubuntu-host/ 30 | ## 31 | ## 32 | -------------------------------------------------------------------------------- /debian/patches/pve/0008-bug-introduce-ASSERT_STRUCT_OFFSET.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:49:59 +0300 4 | Subject: [PATCH] bug: introduce ASSERT_STRUCT_OFFSET 5 | 6 | ASSERT_STRUCT_OFFSET allows to assert during the build of 7 | the kernel that a field in a struct have an expected offset. 8 | 9 | KVM used to have such macro, but there is almost nothing KVM specific 10 | in it so move it to build_bug.h, so that it can be used in other 11 | places in KVM. 12 | 13 | Signed-off-by: Maxim Levitsky 14 | Signed-off-by: Thomas Lamprecht 15 | --- 16 | arch/x86/kvm/vmx/vmcs12.h | 5 ++--- 17 | include/linux/build_bug.h | 9 +++++++++ 18 | 2 files changed, 11 insertions(+), 3 deletions(-) 19 | 20 | diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h 21 | index 746129ddd5ae..01936013428b 100644 22 | --- a/arch/x86/kvm/vmx/vmcs12.h 23 | +++ b/arch/x86/kvm/vmx/vmcs12.h 24 | @@ -208,9 +208,8 @@ struct __packed vmcs12 { 25 | /* 26 | * For save/restore compatibility, the vmcs12 field offsets must not change. 27 | */ 28 | -#define CHECK_OFFSET(field, loc) \ 29 | - BUILD_BUG_ON_MSG(offsetof(struct vmcs12, field) != (loc), \ 30 | - "Offset of " #field " in struct vmcs12 has changed.") 31 | +#define CHECK_OFFSET(field, loc) \ 32 | + ASSERT_STRUCT_OFFSET(struct vmcs12, field, loc) 33 | 34 | static inline void vmx_check_vmcs12_offsets(void) 35 | { 36 | diff --git a/include/linux/build_bug.h b/include/linux/build_bug.h 37 | index e3a0be2c90ad..3aa3640f8c18 100644 38 | --- a/include/linux/build_bug.h 39 | +++ b/include/linux/build_bug.h 40 | @@ -77,4 +77,13 @@ 41 | #define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr) 42 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg) 43 | 44 | + 45 | +/* 46 | + * Compile time check that field has an expected offset 47 | + */ 48 | +#define ASSERT_STRUCT_OFFSET(type, field, expected_offset) \ 49 | + BUILD_BUG_ON_MSG(offsetof(type, field) != (expected_offset), \ 50 | + "Offset of " #field " in " #type " has changed.") 51 | + 52 | + 53 | #endif /* _LINUX_BUILD_BUG_H */ 54 | -------------------------------------------------------------------------------- /debian/patches/pve/0009-KVM-x86-emulator-update-the-emulation-mode-after-rsm.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:50:02 +0300 4 | Subject: [PATCH] KVM: x86: emulator: update the emulation mode after rsm 5 | 6 | This ensures that RIP will be correctly written back, 7 | because the RSM instruction can switch the CPU mode from 8 | 32 bit (or less) to 64 bit. 9 | 10 | This fixes a guest crash in case the #SMI is received 11 | while the guest runs a code from an address > 32 bit. 12 | 13 | Signed-off-by: Maxim Levitsky 14 | Signed-off-by: Thomas Lamprecht 15 | --- 16 | arch/x86/kvm/emulate.c | 5 +++++ 17 | 1 file changed, 5 insertions(+) 18 | 19 | diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c 20 | index 4a43261d25a2..4f7f5117ec7a 100644 21 | --- a/arch/x86/kvm/emulate.c 22 | +++ b/arch/x86/kvm/emulate.c 23 | @@ -2654,6 +2654,11 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) 24 | if (ret != X86EMUL_CONTINUE) 25 | goto emulate_shutdown; 26 | 27 | + 28 | + ret = emulator_recalc_and_set_mode(ctxt); 29 | + if (ret != X86EMUL_CONTINUE) 30 | + goto emulate_shutdown; 31 | + 32 | /* 33 | * Note, the ctxt->ops callbacks are responsible for handling side 34 | * effects when writing MSRs and CRs, e.g. MMU context resets, CPUID 35 | -------------------------------------------------------------------------------- /debian/patches/pve/0010-KVM-x86-emulator-smm-add-structs-for-KVM-s-smram-lay.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:50:05 +0300 4 | Subject: [PATCH] KVM: x86: emulator/smm: add structs for KVM's smram layout 5 | 6 | Those structs will be used to read/write the smram state image. 7 | 8 | Also document the differences between KVM's SMRAM layout and SMRAM 9 | layout that is used by real Intel/AMD cpus. 10 | 11 | Signed-off-by: Maxim Levitsky 12 | Signed-off-by: Thomas Lamprecht 13 | --- 14 | arch/x86/kvm/emulate.c | 6 + 15 | arch/x86/kvm/kvm_emulate.h | 218 +++++++++++++++++++++++++++++++++++++ 16 | arch/x86/kvm/x86.c | 1 + 17 | 3 files changed, 225 insertions(+) 18 | 19 | diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c 20 | index 4f7f5117ec7a..470dd4453b01 100644 21 | --- a/arch/x86/kvm/emulate.c 22 | +++ b/arch/x86/kvm/emulate.c 23 | @@ -5856,3 +5856,9 @@ bool emulator_can_use_gpa(struct x86_emulate_ctxt *ctxt) 24 | 25 | return true; 26 | } 27 | + 28 | +void __init kvm_emulator_init(void) 29 | +{ 30 | + __check_smram32_offsets(); 31 | + __check_smram64_offsets(); 32 | +} 33 | diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h 34 | index 89246446d6aa..dd0ae61e44a1 100644 35 | --- a/arch/x86/kvm/kvm_emulate.h 36 | +++ b/arch/x86/kvm/kvm_emulate.h 37 | @@ -13,6 +13,7 @@ 38 | #define _ASM_X86_KVM_X86_EMULATE_H 39 | 40 | #include 41 | +#include 42 | #include "fpu.h" 43 | 44 | struct x86_emulate_ctxt; 45 | @@ -503,6 +504,223 @@ enum x86_intercept { 46 | nr_x86_intercepts 47 | }; 48 | 49 | + 50 | +/* 32 bit KVM's emulated SMM layout. Loosely based on Intel's layout */ 51 | + 52 | +struct kvm_smm_seg_state_32 { 53 | + u32 flags; 54 | + u32 limit; 55 | + u32 base; 56 | +} __packed; 57 | + 58 | +struct kvm_smram_state_32 { 59 | + u32 reserved1[62]; 60 | + u32 smbase; 61 | + u32 smm_revision; 62 | + u32 reserved2[5]; 63 | + u32 cr4; /* CR4 is not present in Intel/AMD SMRAM image */ 64 | + u32 reserved3[5]; 65 | + 66 | + /* 67 | + * Segment state is not present/documented in the Intel/AMD SMRAM image 68 | + * Instead this area on Intel/AMD contains IO/HLT restart flags. 69 | + */ 70 | + struct kvm_smm_seg_state_32 ds; 71 | + struct kvm_smm_seg_state_32 fs; 72 | + struct kvm_smm_seg_state_32 gs; 73 | + struct kvm_smm_seg_state_32 idtr; /* IDTR has only base and limit */ 74 | + struct kvm_smm_seg_state_32 tr; 75 | + u32 reserved; 76 | + struct kvm_smm_seg_state_32 gdtr; /* GDTR has only base and limit */ 77 | + struct kvm_smm_seg_state_32 ldtr; 78 | + struct kvm_smm_seg_state_32 es; 79 | + struct kvm_smm_seg_state_32 cs; 80 | + struct kvm_smm_seg_state_32 ss; 81 | + 82 | + u32 es_sel; 83 | + u32 cs_sel; 84 | + u32 ss_sel; 85 | + u32 ds_sel; 86 | + u32 fs_sel; 87 | + u32 gs_sel; 88 | + u32 ldtr_sel; 89 | + u32 tr_sel; 90 | + 91 | + u32 dr7; 92 | + u32 dr6; 93 | + u32 gprs[8]; /* GPRS in the "natural" X86 order (EAX/ECX/EDX.../EDI) */ 94 | + u32 eip; 95 | + u32 eflags; 96 | + u32 cr3; 97 | + u32 cr0; 98 | +} __packed; 99 | + 100 | + 101 | +static inline void __check_smram32_offsets(void) 102 | +{ 103 | +#define __CHECK_SMRAM32_OFFSET(field, offset) \ 104 | + ASSERT_STRUCT_OFFSET(struct kvm_smram_state_32, field, offset - 0xFE00) 105 | + 106 | + __CHECK_SMRAM32_OFFSET(reserved1, 0xFE00); 107 | + __CHECK_SMRAM32_OFFSET(smbase, 0xFEF8); 108 | + __CHECK_SMRAM32_OFFSET(smm_revision, 0xFEFC); 109 | + __CHECK_SMRAM32_OFFSET(reserved2, 0xFF00); 110 | + __CHECK_SMRAM32_OFFSET(cr4, 0xFF14); 111 | + __CHECK_SMRAM32_OFFSET(reserved3, 0xFF18); 112 | + __CHECK_SMRAM32_OFFSET(ds, 0xFF2C); 113 | + __CHECK_SMRAM32_OFFSET(fs, 0xFF38); 114 | + __CHECK_SMRAM32_OFFSET(gs, 0xFF44); 115 | + __CHECK_SMRAM32_OFFSET(idtr, 0xFF50); 116 | + __CHECK_SMRAM32_OFFSET(tr, 0xFF5C); 117 | + __CHECK_SMRAM32_OFFSET(gdtr, 0xFF6C); 118 | + __CHECK_SMRAM32_OFFSET(ldtr, 0xFF78); 119 | + __CHECK_SMRAM32_OFFSET(es, 0xFF84); 120 | + __CHECK_SMRAM32_OFFSET(cs, 0xFF90); 121 | + __CHECK_SMRAM32_OFFSET(ss, 0xFF9C); 122 | + __CHECK_SMRAM32_OFFSET(es_sel, 0xFFA8); 123 | + __CHECK_SMRAM32_OFFSET(cs_sel, 0xFFAC); 124 | + __CHECK_SMRAM32_OFFSET(ss_sel, 0xFFB0); 125 | + __CHECK_SMRAM32_OFFSET(ds_sel, 0xFFB4); 126 | + __CHECK_SMRAM32_OFFSET(fs_sel, 0xFFB8); 127 | + __CHECK_SMRAM32_OFFSET(gs_sel, 0xFFBC); 128 | + __CHECK_SMRAM32_OFFSET(ldtr_sel, 0xFFC0); 129 | + __CHECK_SMRAM32_OFFSET(tr_sel, 0xFFC4); 130 | + __CHECK_SMRAM32_OFFSET(dr7, 0xFFC8); 131 | + __CHECK_SMRAM32_OFFSET(dr6, 0xFFCC); 132 | + __CHECK_SMRAM32_OFFSET(gprs, 0xFFD0); 133 | + __CHECK_SMRAM32_OFFSET(eip, 0xFFF0); 134 | + __CHECK_SMRAM32_OFFSET(eflags, 0xFFF4); 135 | + __CHECK_SMRAM32_OFFSET(cr3, 0xFFF8); 136 | + __CHECK_SMRAM32_OFFSET(cr0, 0xFFFC); 137 | +#undef __CHECK_SMRAM32_OFFSET 138 | +} 139 | + 140 | + 141 | +/* 64 bit KVM's emulated SMM layout. Based on AMD64 layout */ 142 | + 143 | +struct kvm_smm_seg_state_64 { 144 | + u16 selector; 145 | + u16 attributes; 146 | + u32 limit; 147 | + u64 base; 148 | +}; 149 | + 150 | +struct kvm_smram_state_64 { 151 | + 152 | + struct kvm_smm_seg_state_64 es; 153 | + struct kvm_smm_seg_state_64 cs; 154 | + struct kvm_smm_seg_state_64 ss; 155 | + struct kvm_smm_seg_state_64 ds; 156 | + struct kvm_smm_seg_state_64 fs; 157 | + struct kvm_smm_seg_state_64 gs; 158 | + struct kvm_smm_seg_state_64 gdtr; /* GDTR has only base and limit*/ 159 | + struct kvm_smm_seg_state_64 ldtr; 160 | + struct kvm_smm_seg_state_64 idtr; /* IDTR has only base and limit*/ 161 | + struct kvm_smm_seg_state_64 tr; 162 | + 163 | + /* I/O restart and auto halt restart are not implemented by KVM */ 164 | + u64 io_restart_rip; 165 | + u64 io_restart_rcx; 166 | + u64 io_restart_rsi; 167 | + u64 io_restart_rdi; 168 | + u32 io_restart_dword; 169 | + u32 reserved1; 170 | + u8 io_inst_restart; 171 | + u8 auto_hlt_restart; 172 | + u8 reserved2[6]; 173 | + 174 | + u64 efer; 175 | + 176 | + /* 177 | + * Two fields below are implemented on AMD only, to store 178 | + * SVM guest vmcb address if the #SMI was received while in the guest mode. 179 | + */ 180 | + u64 svm_guest_flag; 181 | + u64 svm_guest_vmcb_gpa; 182 | + u64 svm_guest_virtual_int; /* unknown purpose, not implemented */ 183 | + 184 | + u32 reserved3[3]; 185 | + u32 smm_revison; 186 | + u32 smbase; 187 | + u32 reserved4[5]; 188 | + 189 | + /* ssp and svm_* fields below are not implemented by KVM */ 190 | + u64 ssp; 191 | + u64 svm_guest_pat; 192 | + u64 svm_host_efer; 193 | + u64 svm_host_cr4; 194 | + u64 svm_host_cr3; 195 | + u64 svm_host_cr0; 196 | + 197 | + u64 cr4; 198 | + u64 cr3; 199 | + u64 cr0; 200 | + u64 dr7; 201 | + u64 dr6; 202 | + u64 rflags; 203 | + u64 rip; 204 | + u64 gprs[16]; /* GPRS in a reversed "natural" X86 order (R15/R14/../RCX/RAX.) */ 205 | +}; 206 | + 207 | + 208 | +static inline void __check_smram64_offsets(void) 209 | +{ 210 | +#define __CHECK_SMRAM64_OFFSET(field, offset) \ 211 | + ASSERT_STRUCT_OFFSET(struct kvm_smram_state_64, field, offset - 0xFE00) 212 | + 213 | + __CHECK_SMRAM64_OFFSET(es, 0xFE00); 214 | + __CHECK_SMRAM64_OFFSET(cs, 0xFE10); 215 | + __CHECK_SMRAM64_OFFSET(ss, 0xFE20); 216 | + __CHECK_SMRAM64_OFFSET(ds, 0xFE30); 217 | + __CHECK_SMRAM64_OFFSET(fs, 0xFE40); 218 | + __CHECK_SMRAM64_OFFSET(gs, 0xFE50); 219 | + __CHECK_SMRAM64_OFFSET(gdtr, 0xFE60); 220 | + __CHECK_SMRAM64_OFFSET(ldtr, 0xFE70); 221 | + __CHECK_SMRAM64_OFFSET(idtr, 0xFE80); 222 | + __CHECK_SMRAM64_OFFSET(tr, 0xFE90); 223 | + __CHECK_SMRAM64_OFFSET(io_restart_rip, 0xFEA0); 224 | + __CHECK_SMRAM64_OFFSET(io_restart_rcx, 0xFEA8); 225 | + __CHECK_SMRAM64_OFFSET(io_restart_rsi, 0xFEB0); 226 | + __CHECK_SMRAM64_OFFSET(io_restart_rdi, 0xFEB8); 227 | + __CHECK_SMRAM64_OFFSET(io_restart_dword, 0xFEC0); 228 | + __CHECK_SMRAM64_OFFSET(reserved1, 0xFEC4); 229 | + __CHECK_SMRAM64_OFFSET(io_inst_restart, 0xFEC8); 230 | + __CHECK_SMRAM64_OFFSET(auto_hlt_restart, 0xFEC9); 231 | + __CHECK_SMRAM64_OFFSET(reserved2, 0xFECA); 232 | + __CHECK_SMRAM64_OFFSET(efer, 0xFED0); 233 | + __CHECK_SMRAM64_OFFSET(svm_guest_flag, 0xFED8); 234 | + __CHECK_SMRAM64_OFFSET(svm_guest_vmcb_gpa, 0xFEE0); 235 | + __CHECK_SMRAM64_OFFSET(svm_guest_virtual_int, 0xFEE8); 236 | + __CHECK_SMRAM64_OFFSET(reserved3, 0xFEF0); 237 | + __CHECK_SMRAM64_OFFSET(smm_revison, 0xFEFC); 238 | + __CHECK_SMRAM64_OFFSET(smbase, 0xFF00); 239 | + __CHECK_SMRAM64_OFFSET(reserved4, 0xFF04); 240 | + __CHECK_SMRAM64_OFFSET(ssp, 0xFF18); 241 | + __CHECK_SMRAM64_OFFSET(svm_guest_pat, 0xFF20); 242 | + __CHECK_SMRAM64_OFFSET(svm_host_efer, 0xFF28); 243 | + __CHECK_SMRAM64_OFFSET(svm_host_cr4, 0xFF30); 244 | + __CHECK_SMRAM64_OFFSET(svm_host_cr3, 0xFF38); 245 | + __CHECK_SMRAM64_OFFSET(svm_host_cr0, 0xFF40); 246 | + __CHECK_SMRAM64_OFFSET(cr4, 0xFF48); 247 | + __CHECK_SMRAM64_OFFSET(cr3, 0xFF50); 248 | + __CHECK_SMRAM64_OFFSET(cr0, 0xFF58); 249 | + __CHECK_SMRAM64_OFFSET(dr7, 0xFF60); 250 | + __CHECK_SMRAM64_OFFSET(dr6, 0xFF68); 251 | + __CHECK_SMRAM64_OFFSET(rflags, 0xFF70); 252 | + __CHECK_SMRAM64_OFFSET(rip, 0xFF78); 253 | + __CHECK_SMRAM64_OFFSET(gprs, 0xFF80); 254 | +#undef __CHECK_SMRAM64_OFFSET 255 | +} 256 | + 257 | +union kvm_smram { 258 | + struct kvm_smram_state_64 smram64; 259 | + struct kvm_smram_state_32 smram32; 260 | + u8 bytes[512]; 261 | +}; 262 | + 263 | +void __init kvm_emulator_init(void); 264 | + 265 | + 266 | /* Host execution mode. */ 267 | #if defined(CONFIG_X86_32) 268 | #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32 269 | diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c 270 | index acca85b10545..20aec64e3521 100644 271 | --- a/arch/x86/kvm/x86.c 272 | +++ b/arch/x86/kvm/x86.c 273 | @@ -13730,6 +13730,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_msr_protocol_exit); 274 | static int __init kvm_x86_init(void) 275 | { 276 | kvm_mmu_x86_module_init(); 277 | + kvm_emulator_init(); 278 | return 0; 279 | } 280 | module_init(kvm_x86_init); 281 | -------------------------------------------------------------------------------- /debian/patches/pve/0011-KVM-x86-emulator-smm-use-smram-structs-in-the-common.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:50:06 +0300 4 | Subject: [PATCH] KVM: x86: emulator/smm: use smram structs in the common code 5 | 6 | Switch from using a raw array to 'union kvm_smram'. 7 | 8 | Signed-off-by: Maxim Levitsky 9 | Signed-off-by: Thomas Lamprecht 10 | --- 11 | arch/x86/include/asm/kvm_host.h | 5 +++-- 12 | arch/x86/kvm/emulate.c | 12 +++++++----- 13 | arch/x86/kvm/kvm_emulate.h | 3 ++- 14 | arch/x86/kvm/svm/svm.c | 8 ++++++-- 15 | arch/x86/kvm/vmx/vmx.c | 4 ++-- 16 | arch/x86/kvm/x86.c | 16 ++++++++-------- 17 | 6 files changed, 28 insertions(+), 20 deletions(-) 18 | 19 | diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h 20 | index f05ebaa26f0f..6885f3839e25 100644 21 | --- a/arch/x86/include/asm/kvm_host.h 22 | +++ b/arch/x86/include/asm/kvm_host.h 23 | @@ -204,6 +204,7 @@ typedef enum exit_fastpath_completion fastpath_t; 24 | 25 | struct x86_emulate_ctxt; 26 | struct x86_exception; 27 | +union kvm_smram; 28 | enum x86_intercept; 29 | enum x86_intercept_stage; 30 | 31 | @@ -1613,8 +1614,8 @@ struct kvm_x86_ops { 32 | void (*setup_mce)(struct kvm_vcpu *vcpu); 33 | 34 | int (*smi_allowed)(struct kvm_vcpu *vcpu, bool for_injection); 35 | - int (*enter_smm)(struct kvm_vcpu *vcpu, char *smstate); 36 | - int (*leave_smm)(struct kvm_vcpu *vcpu, const char *smstate); 37 | + int (*enter_smm)(struct kvm_vcpu *vcpu, union kvm_smram *smram); 38 | + int (*leave_smm)(struct kvm_vcpu *vcpu, const union kvm_smram *smram); 39 | void (*enable_smi_window)(struct kvm_vcpu *vcpu); 40 | 41 | int (*mem_enc_ioctl)(struct kvm *kvm, void __user *argp); 42 | diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c 43 | index 470dd4453b01..7294dffa794a 100644 44 | --- a/arch/x86/kvm/emulate.c 45 | +++ b/arch/x86/kvm/emulate.c 46 | @@ -2582,16 +2582,18 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, 47 | static int em_rsm(struct x86_emulate_ctxt *ctxt) 48 | { 49 | unsigned long cr0, cr4, efer; 50 | - char buf[512]; 51 | + const union kvm_smram smram; 52 | u64 smbase; 53 | int ret; 54 | 55 | + BUILD_BUG_ON(sizeof(smram) != 512); 56 | + 57 | if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_MASK) == 0) 58 | return emulate_ud(ctxt); 59 | 60 | smbase = ctxt->ops->get_smbase(ctxt); 61 | 62 | - ret = ctxt->ops->read_phys(ctxt, smbase + 0xfe00, buf, sizeof(buf)); 63 | + ret = ctxt->ops->read_phys(ctxt, smbase + 0xfe00, (void *)&smram, sizeof(smram)); 64 | if (ret != X86EMUL_CONTINUE) 65 | return X86EMUL_UNHANDLEABLE; 66 | 67 | @@ -2641,15 +2643,15 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) 68 | * state (e.g. enter guest mode) before loading state from the SMM 69 | * state-save area. 70 | */ 71 | - if (ctxt->ops->leave_smm(ctxt, buf)) 72 | + if (ctxt->ops->leave_smm(ctxt, &smram)) 73 | goto emulate_shutdown; 74 | 75 | #ifdef CONFIG_X86_64 76 | if (emulator_has_longmode(ctxt)) 77 | - ret = rsm_load_state_64(ctxt, buf); 78 | + ret = rsm_load_state_64(ctxt, (const char *)&smram); 79 | else 80 | #endif 81 | - ret = rsm_load_state_32(ctxt, buf); 82 | + ret = rsm_load_state_32(ctxt, (const char *)&smram); 83 | 84 | if (ret != X86EMUL_CONTINUE) 85 | goto emulate_shutdown; 86 | diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h 87 | index dd0ae61e44a1..76c0b8e7890b 100644 88 | --- a/arch/x86/kvm/kvm_emulate.h 89 | +++ b/arch/x86/kvm/kvm_emulate.h 90 | @@ -19,6 +19,7 @@ 91 | struct x86_emulate_ctxt; 92 | enum x86_intercept; 93 | enum x86_intercept_stage; 94 | +union kvm_smram; 95 | 96 | struct x86_exception { 97 | u8 vector; 98 | @@ -236,7 +237,7 @@ struct x86_emulate_ops { 99 | 100 | unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt); 101 | void (*exiting_smm)(struct x86_emulate_ctxt *ctxt); 102 | - int (*leave_smm)(struct x86_emulate_ctxt *ctxt, const char *smstate); 103 | + int (*leave_smm)(struct x86_emulate_ctxt *ctxt, const union kvm_smram *smram); 104 | void (*triple_fault)(struct x86_emulate_ctxt *ctxt); 105 | int (*set_xcr)(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr); 106 | }; 107 | diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c 108 | index ce362e88a567..45c4def86cd3 100644 109 | --- a/arch/x86/kvm/svm/svm.c 110 | +++ b/arch/x86/kvm/svm/svm.c 111 | @@ -4385,12 +4385,14 @@ static int svm_smi_allowed(struct kvm_vcpu *vcpu, bool for_injection) 112 | return 1; 113 | } 114 | 115 | -static int svm_enter_smm(struct kvm_vcpu *vcpu, char *smstate) 116 | +static int svm_enter_smm(struct kvm_vcpu *vcpu, union kvm_smram *smram) 117 | { 118 | struct vcpu_svm *svm = to_svm(vcpu); 119 | struct kvm_host_map map_save; 120 | int ret; 121 | 122 | + char *smstate = (char *)smram; 123 | + 124 | if (!is_guest_mode(vcpu)) 125 | return 0; 126 | 127 | @@ -4432,7 +4434,7 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, char *smstate) 128 | return 0; 129 | } 130 | 131 | -static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate) 132 | +static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) 133 | { 134 | struct vcpu_svm *svm = to_svm(vcpu); 135 | struct kvm_host_map map, map_save; 136 | @@ -4440,6 +4442,8 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate) 137 | struct vmcb *vmcb12; 138 | int ret; 139 | 140 | + const char *smstate = (const char *)smram; 141 | + 142 | if (!guest_cpuid_has(vcpu, X86_FEATURE_LM)) 143 | return 0; 144 | 145 | diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c 146 | index 63247c57c72c..4319f65181f7 100644 147 | --- a/arch/x86/kvm/vmx/vmx.c 148 | +++ b/arch/x86/kvm/vmx/vmx.c 149 | @@ -7914,7 +7914,7 @@ static int vmx_smi_allowed(struct kvm_vcpu *vcpu, bool for_injection) 150 | return !is_smm(vcpu); 151 | } 152 | 153 | -static int vmx_enter_smm(struct kvm_vcpu *vcpu, char *smstate) 154 | +static int vmx_enter_smm(struct kvm_vcpu *vcpu, union kvm_smram *smram) 155 | { 156 | struct vcpu_vmx *vmx = to_vmx(vcpu); 157 | 158 | @@ -7935,7 +7935,7 @@ static int vmx_enter_smm(struct kvm_vcpu *vcpu, char *smstate) 159 | return 0; 160 | } 161 | 162 | -static int vmx_leave_smm(struct kvm_vcpu *vcpu, const char *smstate) 163 | +static int vmx_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) 164 | { 165 | struct vcpu_vmx *vmx = to_vmx(vcpu); 166 | int ret; 167 | diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c 168 | index 20aec64e3521..94c29391b065 100644 169 | --- a/arch/x86/kvm/x86.c 170 | +++ b/arch/x86/kvm/x86.c 171 | @@ -8186,9 +8186,9 @@ static void emulator_exiting_smm(struct x86_emulate_ctxt *ctxt) 172 | } 173 | 174 | static int emulator_leave_smm(struct x86_emulate_ctxt *ctxt, 175 | - const char *smstate) 176 | + const union kvm_smram *smram) 177 | { 178 | - return static_call(kvm_x86_leave_smm)(emul_to_vcpu(ctxt), smstate); 179 | + return static_call(kvm_x86_leave_smm)(emul_to_vcpu(ctxt), smram); 180 | } 181 | 182 | static void emulator_triple_fault(struct x86_emulate_ctxt *ctxt) 183 | @@ -10246,25 +10246,25 @@ static void enter_smm(struct kvm_vcpu *vcpu) 184 | struct kvm_segment cs, ds; 185 | struct desc_ptr dt; 186 | unsigned long cr0; 187 | - char buf[512]; 188 | + union kvm_smram smram; 189 | 190 | - memset(buf, 0, 512); 191 | + memset(smram.bytes, 0, sizeof(smram.bytes)); 192 | #ifdef CONFIG_X86_64 193 | if (guest_cpuid_has(vcpu, X86_FEATURE_LM)) 194 | - enter_smm_save_state_64(vcpu, buf); 195 | + enter_smm_save_state_64(vcpu, (char *)&smram); 196 | else 197 | #endif 198 | - enter_smm_save_state_32(vcpu, buf); 199 | + enter_smm_save_state_32(vcpu, (char *)&smram); 200 | 201 | /* 202 | * Give enter_smm() a chance to make ISA-specific changes to the vCPU 203 | * state (e.g. leave guest mode) after we've saved the state into the 204 | * SMM state-save area. 205 | */ 206 | - static_call(kvm_x86_enter_smm)(vcpu, buf); 207 | + static_call(kvm_x86_enter_smm)(vcpu, &smram); 208 | 209 | kvm_smm_changed(vcpu, true); 210 | - kvm_vcpu_write_guest(vcpu, vcpu->arch.smbase + 0xfe00, buf, sizeof(buf)); 211 | + kvm_vcpu_write_guest(vcpu, vcpu->arch.smbase + 0xfe00, &smram, sizeof(smram)); 212 | 213 | if (static_call(kvm_x86_get_nmi_mask)(vcpu)) 214 | vcpu->arch.hflags |= HF_SMM_INSIDE_NMI_MASK; 215 | -------------------------------------------------------------------------------- /debian/patches/pve/0012-KVM-x86-emulator-smm-use-smram-struct-for-32-bit-smr.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:50:07 +0300 4 | Subject: [PATCH] KVM: x86: emulator/smm: use smram struct for 32 bit smram 5 | load/restore 6 | 7 | Use kvm_smram_state_32 struct to save/restore 32 bit SMM state 8 | (used when X86_FEATURE_LM is not present in the guest CPUID). 9 | 10 | Signed-off-by: Maxim Levitsky 11 | Signed-off-by: Thomas Lamprecht 12 | --- 13 | arch/x86/kvm/emulate.c | 81 +++++++++++++++--------------------------- 14 | arch/x86/kvm/x86.c | 75 +++++++++++++++++--------------------- 15 | 2 files changed, 60 insertions(+), 96 deletions(-) 16 | 17 | diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c 18 | index 7294dffa794a..65d82292ccec 100644 19 | --- a/arch/x86/kvm/emulate.c 20 | +++ b/arch/x86/kvm/emulate.c 21 | @@ -2359,25 +2359,17 @@ static void rsm_set_desc_flags(struct desc_struct *desc, u32 flags) 22 | desc->type = (flags >> 8) & 15; 23 | } 24 | 25 | -static int rsm_load_seg_32(struct x86_emulate_ctxt *ctxt, const char *smstate, 26 | +static void rsm_load_seg_32(struct x86_emulate_ctxt *ctxt, 27 | + const struct kvm_smm_seg_state_32 *state, 28 | + u16 selector, 29 | int n) 30 | { 31 | struct desc_struct desc; 32 | - int offset; 33 | - u16 selector; 34 | - 35 | - selector = GET_SMSTATE(u32, smstate, 0x7fa8 + n * 4); 36 | - 37 | - if (n < 3) 38 | - offset = 0x7f84 + n * 12; 39 | - else 40 | - offset = 0x7f2c + (n - 3) * 12; 41 | 42 | - set_desc_base(&desc, GET_SMSTATE(u32, smstate, offset + 8)); 43 | - set_desc_limit(&desc, GET_SMSTATE(u32, smstate, offset + 4)); 44 | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, offset)); 45 | + set_desc_base(&desc, state->base); 46 | + set_desc_limit(&desc, state->limit); 47 | + rsm_set_desc_flags(&desc, state->flags); 48 | ctxt->ops->set_segment(ctxt, selector, &desc, 0, n); 49 | - return X86EMUL_CONTINUE; 50 | } 51 | 52 | #ifdef CONFIG_X86_64 53 | @@ -2448,63 +2440,46 @@ static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt, 54 | } 55 | 56 | static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, 57 | - const char *smstate) 58 | + const struct kvm_smram_state_32 *smstate) 59 | { 60 | - struct desc_struct desc; 61 | struct desc_ptr dt; 62 | - u16 selector; 63 | - u32 val, cr0, cr3, cr4; 64 | int i; 65 | 66 | - cr0 = GET_SMSTATE(u32, smstate, 0x7ffc); 67 | - cr3 = GET_SMSTATE(u32, smstate, 0x7ff8); 68 | - ctxt->eflags = GET_SMSTATE(u32, smstate, 0x7ff4) | X86_EFLAGS_FIXED; 69 | - ctxt->_eip = GET_SMSTATE(u32, smstate, 0x7ff0); 70 | + ctxt->eflags = smstate->eflags | X86_EFLAGS_FIXED; 71 | + ctxt->_eip = smstate->eip; 72 | 73 | for (i = 0; i < 8; i++) 74 | - *reg_write(ctxt, i) = GET_SMSTATE(u32, smstate, 0x7fd0 + i * 4); 75 | - 76 | - val = GET_SMSTATE(u32, smstate, 0x7fcc); 77 | + *reg_write(ctxt, i) = smstate->gprs[i]; 78 | 79 | - if (ctxt->ops->set_dr(ctxt, 6, val)) 80 | + if (ctxt->ops->set_dr(ctxt, 6, smstate->dr6)) 81 | return X86EMUL_UNHANDLEABLE; 82 | - 83 | - val = GET_SMSTATE(u32, smstate, 0x7fc8); 84 | - 85 | - if (ctxt->ops->set_dr(ctxt, 7, val)) 86 | + if (ctxt->ops->set_dr(ctxt, 7, smstate->dr7)) 87 | return X86EMUL_UNHANDLEABLE; 88 | 89 | - selector = GET_SMSTATE(u32, smstate, 0x7fc4); 90 | - set_desc_base(&desc, GET_SMSTATE(u32, smstate, 0x7f64)); 91 | - set_desc_limit(&desc, GET_SMSTATE(u32, smstate, 0x7f60)); 92 | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, 0x7f5c)); 93 | - ctxt->ops->set_segment(ctxt, selector, &desc, 0, VCPU_SREG_TR); 94 | + rsm_load_seg_32(ctxt, &smstate->tr, smstate->tr_sel, VCPU_SREG_TR); 95 | + rsm_load_seg_32(ctxt, &smstate->ldtr, smstate->ldtr_sel, VCPU_SREG_LDTR); 96 | 97 | - selector = GET_SMSTATE(u32, smstate, 0x7fc0); 98 | - set_desc_base(&desc, GET_SMSTATE(u32, smstate, 0x7f80)); 99 | - set_desc_limit(&desc, GET_SMSTATE(u32, smstate, 0x7f7c)); 100 | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, 0x7f78)); 101 | - ctxt->ops->set_segment(ctxt, selector, &desc, 0, VCPU_SREG_LDTR); 102 | 103 | - dt.address = GET_SMSTATE(u32, smstate, 0x7f74); 104 | - dt.size = GET_SMSTATE(u32, smstate, 0x7f70); 105 | + dt.address = smstate->gdtr.base; 106 | + dt.size = smstate->gdtr.limit; 107 | ctxt->ops->set_gdt(ctxt, &dt); 108 | 109 | - dt.address = GET_SMSTATE(u32, smstate, 0x7f58); 110 | - dt.size = GET_SMSTATE(u32, smstate, 0x7f54); 111 | + dt.address = smstate->idtr.base; 112 | + dt.size = smstate->idtr.limit; 113 | ctxt->ops->set_idt(ctxt, &dt); 114 | 115 | - for (i = 0; i < 6; i++) { 116 | - int r = rsm_load_seg_32(ctxt, smstate, i); 117 | - if (r != X86EMUL_CONTINUE) 118 | - return r; 119 | - } 120 | + rsm_load_seg_32(ctxt, &smstate->es, smstate->es_sel, VCPU_SREG_ES); 121 | + rsm_load_seg_32(ctxt, &smstate->cs, smstate->cs_sel, VCPU_SREG_CS); 122 | + rsm_load_seg_32(ctxt, &smstate->ss, smstate->ss_sel, VCPU_SREG_SS); 123 | 124 | - cr4 = GET_SMSTATE(u32, smstate, 0x7f14); 125 | + rsm_load_seg_32(ctxt, &smstate->ds, smstate->ds_sel, VCPU_SREG_DS); 126 | + rsm_load_seg_32(ctxt, &smstate->fs, smstate->fs_sel, VCPU_SREG_FS); 127 | + rsm_load_seg_32(ctxt, &smstate->gs, smstate->gs_sel, VCPU_SREG_GS); 128 | 129 | - ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smstate, 0x7ef8)); 130 | + ctxt->ops->set_smbase(ctxt, smstate->smbase); 131 | 132 | - return rsm_enter_protected_mode(ctxt, cr0, cr3, cr4); 133 | + return rsm_enter_protected_mode(ctxt, smstate->cr0, 134 | + smstate->cr3, smstate->cr4); 135 | } 136 | 137 | #ifdef CONFIG_X86_64 138 | @@ -2651,7 +2626,7 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) 139 | ret = rsm_load_state_64(ctxt, (const char *)&smram); 140 | else 141 | #endif 142 | - ret = rsm_load_state_32(ctxt, (const char *)&smram); 143 | + ret = rsm_load_state_32(ctxt, &smram.smram32); 144 | 145 | if (ret != X86EMUL_CONTINUE) 146 | goto emulate_shutdown; 147 | diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c 148 | index 94c29391b065..579a1cb6a7c8 100644 149 | --- a/arch/x86/kvm/x86.c 150 | +++ b/arch/x86/kvm/x86.c 151 | @@ -10100,22 +10100,18 @@ static u32 enter_smm_get_segment_flags(struct kvm_segment *seg) 152 | return flags; 153 | } 154 | 155 | -static void enter_smm_save_seg_32(struct kvm_vcpu *vcpu, char *buf, int n) 156 | +static void enter_smm_save_seg_32(struct kvm_vcpu *vcpu, 157 | + struct kvm_smm_seg_state_32 *state, 158 | + u32 *selector, 159 | + int n) 160 | { 161 | struct kvm_segment seg; 162 | - int offset; 163 | 164 | kvm_get_segment(vcpu, &seg, n); 165 | - put_smstate(u32, buf, 0x7fa8 + n * 4, seg.selector); 166 | - 167 | - if (n < 3) 168 | - offset = 0x7f84 + n * 12; 169 | - else 170 | - offset = 0x7f2c + (n - 3) * 12; 171 | - 172 | - put_smstate(u32, buf, offset + 8, seg.base); 173 | - put_smstate(u32, buf, offset + 4, seg.limit); 174 | - put_smstate(u32, buf, offset, enter_smm_get_segment_flags(&seg)); 175 | + *selector = seg.selector; 176 | + state->base = seg.base; 177 | + state->limit = seg.limit; 178 | + state->flags = enter_smm_get_segment_flags(&seg); 179 | } 180 | 181 | #ifdef CONFIG_X86_64 182 | @@ -10136,54 +10132,47 @@ static void enter_smm_save_seg_64(struct kvm_vcpu *vcpu, char *buf, int n) 183 | } 184 | #endif 185 | 186 | -static void enter_smm_save_state_32(struct kvm_vcpu *vcpu, char *buf) 187 | +static void enter_smm_save_state_32(struct kvm_vcpu *vcpu, struct kvm_smram_state_32 *smram) 188 | { 189 | struct desc_ptr dt; 190 | - struct kvm_segment seg; 191 | unsigned long val; 192 | int i; 193 | 194 | - put_smstate(u32, buf, 0x7ffc, kvm_read_cr0(vcpu)); 195 | - put_smstate(u32, buf, 0x7ff8, kvm_read_cr3(vcpu)); 196 | - put_smstate(u32, buf, 0x7ff4, kvm_get_rflags(vcpu)); 197 | - put_smstate(u32, buf, 0x7ff0, kvm_rip_read(vcpu)); 198 | + smram->cr0 = kvm_read_cr0(vcpu); 199 | + smram->cr3 = kvm_read_cr3(vcpu); 200 | + smram->eflags = kvm_get_rflags(vcpu); 201 | + smram->eip = kvm_rip_read(vcpu); 202 | 203 | for (i = 0; i < 8; i++) 204 | - put_smstate(u32, buf, 0x7fd0 + i * 4, kvm_register_read_raw(vcpu, i)); 205 | + smram->gprs[i] = kvm_register_read_raw(vcpu, i); 206 | 207 | kvm_get_dr(vcpu, 6, &val); 208 | - put_smstate(u32, buf, 0x7fcc, (u32)val); 209 | + smram->dr6 = (u32)val; 210 | kvm_get_dr(vcpu, 7, &val); 211 | - put_smstate(u32, buf, 0x7fc8, (u32)val); 212 | + smram->dr7 = (u32)val; 213 | 214 | - kvm_get_segment(vcpu, &seg, VCPU_SREG_TR); 215 | - put_smstate(u32, buf, 0x7fc4, seg.selector); 216 | - put_smstate(u32, buf, 0x7f64, seg.base); 217 | - put_smstate(u32, buf, 0x7f60, seg.limit); 218 | - put_smstate(u32, buf, 0x7f5c, enter_smm_get_segment_flags(&seg)); 219 | - 220 | - kvm_get_segment(vcpu, &seg, VCPU_SREG_LDTR); 221 | - put_smstate(u32, buf, 0x7fc0, seg.selector); 222 | - put_smstate(u32, buf, 0x7f80, seg.base); 223 | - put_smstate(u32, buf, 0x7f7c, seg.limit); 224 | - put_smstate(u32, buf, 0x7f78, enter_smm_get_segment_flags(&seg)); 225 | + enter_smm_save_seg_32(vcpu, &smram->tr, &smram->tr_sel, VCPU_SREG_TR); 226 | + enter_smm_save_seg_32(vcpu, &smram->ldtr, &smram->ldtr_sel, VCPU_SREG_LDTR); 227 | 228 | static_call(kvm_x86_get_gdt)(vcpu, &dt); 229 | - put_smstate(u32, buf, 0x7f74, dt.address); 230 | - put_smstate(u32, buf, 0x7f70, dt.size); 231 | + smram->gdtr.base = dt.address; 232 | + smram->gdtr.limit = dt.size; 233 | 234 | static_call(kvm_x86_get_idt)(vcpu, &dt); 235 | - put_smstate(u32, buf, 0x7f58, dt.address); 236 | - put_smstate(u32, buf, 0x7f54, dt.size); 237 | + smram->idtr.base = dt.address; 238 | + smram->idtr.limit = dt.size; 239 | 240 | - for (i = 0; i < 6; i++) 241 | - enter_smm_save_seg_32(vcpu, buf, i); 242 | + enter_smm_save_seg_32(vcpu, &smram->es, &smram->es_sel, VCPU_SREG_ES); 243 | + enter_smm_save_seg_32(vcpu, &smram->cs, &smram->cs_sel, VCPU_SREG_CS); 244 | + enter_smm_save_seg_32(vcpu, &smram->ss, &smram->ss_sel, VCPU_SREG_SS); 245 | 246 | - put_smstate(u32, buf, 0x7f14, kvm_read_cr4(vcpu)); 247 | + enter_smm_save_seg_32(vcpu, &smram->ds, &smram->ds_sel, VCPU_SREG_DS); 248 | + enter_smm_save_seg_32(vcpu, &smram->fs, &smram->fs_sel, VCPU_SREG_FS); 249 | + enter_smm_save_seg_32(vcpu, &smram->gs, &smram->gs_sel, VCPU_SREG_GS); 250 | 251 | - /* revision id */ 252 | - put_smstate(u32, buf, 0x7efc, 0x00020000); 253 | - put_smstate(u32, buf, 0x7ef8, vcpu->arch.smbase); 254 | + smram->cr4 = kvm_read_cr4(vcpu); 255 | + smram->smm_revision = 0x00020000; 256 | + smram->smbase = vcpu->arch.smbase; 257 | } 258 | 259 | #ifdef CONFIG_X86_64 260 | @@ -10254,7 +10243,7 @@ static void enter_smm(struct kvm_vcpu *vcpu) 261 | enter_smm_save_state_64(vcpu, (char *)&smram); 262 | else 263 | #endif 264 | - enter_smm_save_state_32(vcpu, (char *)&smram); 265 | + enter_smm_save_state_32(vcpu, &smram.smram32); 266 | 267 | /* 268 | * Give enter_smm() a chance to make ISA-specific changes to the vCPU 269 | -------------------------------------------------------------------------------- /debian/patches/pve/0013-KVM-x86-emulator-smm-use-smram-struct-for-64-bit-smr.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:50:08 +0300 4 | Subject: [PATCH] KVM: x86: emulator/smm: use smram struct for 64 bit smram 5 | load/restore 6 | 7 | Use kvm_smram_state_64 struct to save/restore the 64 bit SMM state 8 | (used when X86_FEATURE_LM is present in the guest CPUID, 9 | regardless of 32-bitness of the guest). 10 | 11 | Signed-off-by: Maxim Levitsky 12 | Signed-off-by: Thomas Lamprecht 13 | --- 14 | arch/x86/kvm/emulate.c | 88 ++++++++++++++---------------------------- 15 | arch/x86/kvm/x86.c | 75 ++++++++++++++++------------------- 16 | 2 files changed, 62 insertions(+), 101 deletions(-) 17 | 18 | diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c 19 | index 65d82292ccec..03f9e5aa036e 100644 20 | --- a/arch/x86/kvm/emulate.c 21 | +++ b/arch/x86/kvm/emulate.c 22 | @@ -2373,24 +2373,16 @@ static void rsm_load_seg_32(struct x86_emulate_ctxt *ctxt, 23 | } 24 | 25 | #ifdef CONFIG_X86_64 26 | -static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, const char *smstate, 27 | - int n) 28 | +static void rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, 29 | + const struct kvm_smm_seg_state_64 *state, 30 | + int n) 31 | { 32 | struct desc_struct desc; 33 | - int offset; 34 | - u16 selector; 35 | - u32 base3; 36 | - 37 | - offset = 0x7e00 + n * 16; 38 | - 39 | - selector = GET_SMSTATE(u16, smstate, offset); 40 | - rsm_set_desc_flags(&desc, GET_SMSTATE(u16, smstate, offset + 2) << 8); 41 | - set_desc_limit(&desc, GET_SMSTATE(u32, smstate, offset + 4)); 42 | - set_desc_base(&desc, GET_SMSTATE(u32, smstate, offset + 8)); 43 | - base3 = GET_SMSTATE(u32, smstate, offset + 12); 44 | 45 | - ctxt->ops->set_segment(ctxt, selector, &desc, base3, n); 46 | - return X86EMUL_CONTINUE; 47 | + rsm_set_desc_flags(&desc, state->attributes << 8); 48 | + set_desc_limit(&desc, state->limit); 49 | + set_desc_base(&desc, (u32)state->base); 50 | + ctxt->ops->set_segment(ctxt, state->selector, &desc, state->base >> 32, n); 51 | } 52 | #endif 53 | 54 | @@ -2484,71 +2476,49 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, 55 | 56 | #ifdef CONFIG_X86_64 57 | static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, 58 | - const char *smstate) 59 | + const struct kvm_smram_state_64 *smstate) 60 | { 61 | - struct desc_struct desc; 62 | struct desc_ptr dt; 63 | - u64 val, cr0, cr3, cr4; 64 | - u32 base3; 65 | - u16 selector; 66 | int i, r; 67 | 68 | for (i = 0; i < 16; i++) 69 | - *reg_write(ctxt, i) = GET_SMSTATE(u64, smstate, 0x7ff8 - i * 8); 70 | + *reg_write(ctxt, i) = smstate->gprs[15 - i]; 71 | 72 | - ctxt->_eip = GET_SMSTATE(u64, smstate, 0x7f78); 73 | - ctxt->eflags = GET_SMSTATE(u32, smstate, 0x7f70) | X86_EFLAGS_FIXED; 74 | + ctxt->_eip = smstate->rip; 75 | + ctxt->eflags = smstate->rflags | X86_EFLAGS_FIXED; 76 | 77 | - val = GET_SMSTATE(u64, smstate, 0x7f68); 78 | - 79 | - if (ctxt->ops->set_dr(ctxt, 6, val)) 80 | + if (ctxt->ops->set_dr(ctxt, 6, smstate->dr6)) 81 | return X86EMUL_UNHANDLEABLE; 82 | - 83 | - val = GET_SMSTATE(u64, smstate, 0x7f60); 84 | - 85 | - if (ctxt->ops->set_dr(ctxt, 7, val)) 86 | + if (ctxt->ops->set_dr(ctxt, 7, smstate->dr7)) 87 | return X86EMUL_UNHANDLEABLE; 88 | 89 | - cr0 = GET_SMSTATE(u64, smstate, 0x7f58); 90 | - cr3 = GET_SMSTATE(u64, smstate, 0x7f50); 91 | - cr4 = GET_SMSTATE(u64, smstate, 0x7f48); 92 | - ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smstate, 0x7f00)); 93 | - val = GET_SMSTATE(u64, smstate, 0x7ed0); 94 | + ctxt->ops->set_smbase(ctxt, smstate->smbase); 95 | 96 | - if (ctxt->ops->set_msr(ctxt, MSR_EFER, val & ~EFER_LMA)) 97 | + if (ctxt->ops->set_msr(ctxt, MSR_EFER, smstate->efer & ~EFER_LMA)) 98 | return X86EMUL_UNHANDLEABLE; 99 | 100 | - selector = GET_SMSTATE(u32, smstate, 0x7e90); 101 | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, 0x7e92) << 8); 102 | - set_desc_limit(&desc, GET_SMSTATE(u32, smstate, 0x7e94)); 103 | - set_desc_base(&desc, GET_SMSTATE(u32, smstate, 0x7e98)); 104 | - base3 = GET_SMSTATE(u32, smstate, 0x7e9c); 105 | - ctxt->ops->set_segment(ctxt, selector, &desc, base3, VCPU_SREG_TR); 106 | + rsm_load_seg_64(ctxt, &smstate->tr, VCPU_SREG_TR); 107 | 108 | - dt.size = GET_SMSTATE(u32, smstate, 0x7e84); 109 | - dt.address = GET_SMSTATE(u64, smstate, 0x7e88); 110 | + dt.size = smstate->idtr.limit; 111 | + dt.address = smstate->idtr.base; 112 | ctxt->ops->set_idt(ctxt, &dt); 113 | 114 | - selector = GET_SMSTATE(u32, smstate, 0x7e70); 115 | - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smstate, 0x7e72) << 8); 116 | - set_desc_limit(&desc, GET_SMSTATE(u32, smstate, 0x7e74)); 117 | - set_desc_base(&desc, GET_SMSTATE(u32, smstate, 0x7e78)); 118 | - base3 = GET_SMSTATE(u32, smstate, 0x7e7c); 119 | - ctxt->ops->set_segment(ctxt, selector, &desc, base3, VCPU_SREG_LDTR); 120 | + rsm_load_seg_64(ctxt, &smstate->ldtr, VCPU_SREG_LDTR); 121 | 122 | - dt.size = GET_SMSTATE(u32, smstate, 0x7e64); 123 | - dt.address = GET_SMSTATE(u64, smstate, 0x7e68); 124 | + dt.size = smstate->gdtr.limit; 125 | + dt.address = smstate->gdtr.base; 126 | ctxt->ops->set_gdt(ctxt, &dt); 127 | 128 | - r = rsm_enter_protected_mode(ctxt, cr0, cr3, cr4); 129 | + r = rsm_enter_protected_mode(ctxt, smstate->cr0, smstate->cr3, smstate->cr4); 130 | if (r != X86EMUL_CONTINUE) 131 | return r; 132 | 133 | - for (i = 0; i < 6; i++) { 134 | - r = rsm_load_seg_64(ctxt, smstate, i); 135 | - if (r != X86EMUL_CONTINUE) 136 | - return r; 137 | - } 138 | + rsm_load_seg_64(ctxt, &smstate->es, VCPU_SREG_ES); 139 | + rsm_load_seg_64(ctxt, &smstate->cs, VCPU_SREG_CS); 140 | + rsm_load_seg_64(ctxt, &smstate->ss, VCPU_SREG_SS); 141 | + rsm_load_seg_64(ctxt, &smstate->ds, VCPU_SREG_DS); 142 | + rsm_load_seg_64(ctxt, &smstate->fs, VCPU_SREG_FS); 143 | + rsm_load_seg_64(ctxt, &smstate->gs, VCPU_SREG_GS); 144 | 145 | return X86EMUL_CONTINUE; 146 | } 147 | @@ -2623,7 +2593,7 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) 148 | 149 | #ifdef CONFIG_X86_64 150 | if (emulator_has_longmode(ctxt)) 151 | - ret = rsm_load_state_64(ctxt, (const char *)&smram); 152 | + ret = rsm_load_state_64(ctxt, &smram.smram64); 153 | else 154 | #endif 155 | ret = rsm_load_state_32(ctxt, &smram.smram32); 156 | diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c 157 | index 579a1cb6a7c8..7a4d86f9bdcd 100644 158 | --- a/arch/x86/kvm/x86.c 159 | +++ b/arch/x86/kvm/x86.c 160 | @@ -10115,20 +10115,17 @@ static void enter_smm_save_seg_32(struct kvm_vcpu *vcpu, 161 | } 162 | 163 | #ifdef CONFIG_X86_64 164 | -static void enter_smm_save_seg_64(struct kvm_vcpu *vcpu, char *buf, int n) 165 | +static void enter_smm_save_seg_64(struct kvm_vcpu *vcpu, 166 | + struct kvm_smm_seg_state_64 *state, 167 | + int n) 168 | { 169 | struct kvm_segment seg; 170 | - int offset; 171 | - u16 flags; 172 | 173 | kvm_get_segment(vcpu, &seg, n); 174 | - offset = 0x7e00 + n * 16; 175 | - 176 | - flags = enter_smm_get_segment_flags(&seg) >> 8; 177 | - put_smstate(u16, buf, offset, seg.selector); 178 | - put_smstate(u16, buf, offset + 2, flags); 179 | - put_smstate(u32, buf, offset + 4, seg.limit); 180 | - put_smstate(u64, buf, offset + 8, seg.base); 181 | + state->selector = seg.selector; 182 | + state->attributes = enter_smm_get_segment_flags(&seg) >> 8; 183 | + state->limit = seg.limit; 184 | + state->base = seg.base; 185 | } 186 | #endif 187 | 188 | @@ -10176,57 +10173,51 @@ static void enter_smm_save_state_32(struct kvm_vcpu *vcpu, struct kvm_smram_stat 189 | } 190 | 191 | #ifdef CONFIG_X86_64 192 | -static void enter_smm_save_state_64(struct kvm_vcpu *vcpu, char *buf) 193 | +static void enter_smm_save_state_64(struct kvm_vcpu *vcpu, struct kvm_smram_state_64 *smram) 194 | { 195 | struct desc_ptr dt; 196 | - struct kvm_segment seg; 197 | unsigned long val; 198 | int i; 199 | 200 | for (i = 0; i < 16; i++) 201 | - put_smstate(u64, buf, 0x7ff8 - i * 8, kvm_register_read_raw(vcpu, i)); 202 | + smram->gprs[15 - i] = kvm_register_read_raw(vcpu, i); 203 | + 204 | + smram->rip = kvm_rip_read(vcpu); 205 | + smram->rflags = kvm_get_rflags(vcpu); 206 | 207 | - put_smstate(u64, buf, 0x7f78, kvm_rip_read(vcpu)); 208 | - put_smstate(u32, buf, 0x7f70, kvm_get_rflags(vcpu)); 209 | 210 | kvm_get_dr(vcpu, 6, &val); 211 | - put_smstate(u64, buf, 0x7f68, val); 212 | + smram->dr6 = val; 213 | kvm_get_dr(vcpu, 7, &val); 214 | - put_smstate(u64, buf, 0x7f60, val); 215 | - 216 | - put_smstate(u64, buf, 0x7f58, kvm_read_cr0(vcpu)); 217 | - put_smstate(u64, buf, 0x7f50, kvm_read_cr3(vcpu)); 218 | - put_smstate(u64, buf, 0x7f48, kvm_read_cr4(vcpu)); 219 | + smram->dr7 = val; 220 | 221 | - put_smstate(u32, buf, 0x7f00, vcpu->arch.smbase); 222 | + smram->cr0 = kvm_read_cr0(vcpu); 223 | + smram->cr3 = kvm_read_cr3(vcpu); 224 | + smram->cr4 = kvm_read_cr4(vcpu); 225 | 226 | - /* revision id */ 227 | - put_smstate(u32, buf, 0x7efc, 0x00020064); 228 | + smram->smbase = vcpu->arch.smbase; 229 | + smram->smm_revison = 0x00020064; 230 | 231 | - put_smstate(u64, buf, 0x7ed0, vcpu->arch.efer); 232 | + smram->efer = vcpu->arch.efer; 233 | 234 | - kvm_get_segment(vcpu, &seg, VCPU_SREG_TR); 235 | - put_smstate(u16, buf, 0x7e90, seg.selector); 236 | - put_smstate(u16, buf, 0x7e92, enter_smm_get_segment_flags(&seg) >> 8); 237 | - put_smstate(u32, buf, 0x7e94, seg.limit); 238 | - put_smstate(u64, buf, 0x7e98, seg.base); 239 | + enter_smm_save_seg_64(vcpu, &smram->tr, VCPU_SREG_TR); 240 | 241 | static_call(kvm_x86_get_idt)(vcpu, &dt); 242 | - put_smstate(u32, buf, 0x7e84, dt.size); 243 | - put_smstate(u64, buf, 0x7e88, dt.address); 244 | + smram->idtr.limit = dt.size; 245 | + smram->idtr.base = dt.address; 246 | 247 | - kvm_get_segment(vcpu, &seg, VCPU_SREG_LDTR); 248 | - put_smstate(u16, buf, 0x7e70, seg.selector); 249 | - put_smstate(u16, buf, 0x7e72, enter_smm_get_segment_flags(&seg) >> 8); 250 | - put_smstate(u32, buf, 0x7e74, seg.limit); 251 | - put_smstate(u64, buf, 0x7e78, seg.base); 252 | + enter_smm_save_seg_64(vcpu, &smram->ldtr, VCPU_SREG_LDTR); 253 | 254 | static_call(kvm_x86_get_gdt)(vcpu, &dt); 255 | - put_smstate(u32, buf, 0x7e64, dt.size); 256 | - put_smstate(u64, buf, 0x7e68, dt.address); 257 | + smram->gdtr.limit = dt.size; 258 | + smram->gdtr.base = dt.address; 259 | 260 | - for (i = 0; i < 6; i++) 261 | - enter_smm_save_seg_64(vcpu, buf, i); 262 | + enter_smm_save_seg_64(vcpu, &smram->es, VCPU_SREG_ES); 263 | + enter_smm_save_seg_64(vcpu, &smram->cs, VCPU_SREG_CS); 264 | + enter_smm_save_seg_64(vcpu, &smram->ss, VCPU_SREG_SS); 265 | + enter_smm_save_seg_64(vcpu, &smram->ds, VCPU_SREG_DS); 266 | + enter_smm_save_seg_64(vcpu, &smram->fs, VCPU_SREG_FS); 267 | + enter_smm_save_seg_64(vcpu, &smram->gs, VCPU_SREG_GS); 268 | } 269 | #endif 270 | 271 | @@ -10240,7 +10231,7 @@ static void enter_smm(struct kvm_vcpu *vcpu) 272 | memset(smram.bytes, 0, sizeof(smram.bytes)); 273 | #ifdef CONFIG_X86_64 274 | if (guest_cpuid_has(vcpu, X86_FEATURE_LM)) 275 | - enter_smm_save_state_64(vcpu, (char *)&smram); 276 | + enter_smm_save_state_64(vcpu, &smram.smram64); 277 | else 278 | #endif 279 | enter_smm_save_state_32(vcpu, &smram.smram32); 280 | -------------------------------------------------------------------------------- /debian/patches/pve/0014-KVM-x86-SVM-use-smram-structs.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:50:09 +0300 4 | Subject: [PATCH] KVM: x86: SVM: use smram structs 5 | 6 | This removes the last user of put_smstate/GET_SMSTATE so 7 | remove these functions as well. 8 | 9 | Also add a sanity check that we don't attempt to enter the SMM 10 | on non long mode capable guest CPU with a running nested guest. 11 | 12 | Signed-off-by: Maxim Levitsky 13 | Signed-off-by: Thomas Lamprecht 14 | --- 15 | arch/x86/include/asm/kvm_host.h | 6 ------ 16 | arch/x86/kvm/svm/svm.c | 21 ++++++--------------- 17 | 2 files changed, 6 insertions(+), 21 deletions(-) 18 | 19 | diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h 20 | index 6885f3839e25..f5b82b6f4f84 100644 21 | --- a/arch/x86/include/asm/kvm_host.h 22 | +++ b/arch/x86/include/asm/kvm_host.h 23 | @@ -2090,12 +2090,6 @@ static inline int kvm_cpu_get_apicid(int mps_cpu) 24 | #endif 25 | } 26 | 27 | -#define put_smstate(type, buf, offset, val) \ 28 | - *(type *)((buf) + (offset) - 0x7e00) = val 29 | - 30 | -#define GET_SMSTATE(type, buf, offset) \ 31 | - (*(type *)((buf) + (offset) - 0x7e00)) 32 | - 33 | int kvm_cpu_dirty_log_size(void); 34 | 35 | int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages); 36 | diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c 37 | index 45c4def86cd3..bfacbef667d7 100644 38 | --- a/arch/x86/kvm/svm/svm.c 39 | +++ b/arch/x86/kvm/svm/svm.c 40 | @@ -4391,15 +4391,11 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, union kvm_smram *smram) 41 | struct kvm_host_map map_save; 42 | int ret; 43 | 44 | - char *smstate = (char *)smram; 45 | - 46 | if (!is_guest_mode(vcpu)) 47 | return 0; 48 | 49 | - /* FED8h - SVM Guest */ 50 | - put_smstate(u64, smstate, 0x7ed8, 1); 51 | - /* FEE0h - SVM Guest VMCB Physical Address */ 52 | - put_smstate(u64, smstate, 0x7ee0, svm->nested.vmcb12_gpa); 53 | + smram->smram64.svm_guest_flag = 1; 54 | + smram->smram64.svm_guest_vmcb_gpa = svm->nested.vmcb12_gpa; 55 | 56 | svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX]; 57 | svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP]; 58 | @@ -4438,28 +4434,23 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) 59 | { 60 | struct vcpu_svm *svm = to_svm(vcpu); 61 | struct kvm_host_map map, map_save; 62 | - u64 saved_efer, vmcb12_gpa; 63 | struct vmcb *vmcb12; 64 | int ret; 65 | 66 | - const char *smstate = (const char *)smram; 67 | - 68 | if (!guest_cpuid_has(vcpu, X86_FEATURE_LM)) 69 | return 0; 70 | 71 | /* Non-zero if SMI arrived while vCPU was in guest mode. */ 72 | - if (!GET_SMSTATE(u64, smstate, 0x7ed8)) 73 | + if (!smram->smram64.svm_guest_flag) 74 | return 0; 75 | 76 | if (!guest_cpuid_has(vcpu, X86_FEATURE_SVM)) 77 | return 1; 78 | 79 | - saved_efer = GET_SMSTATE(u64, smstate, 0x7ed0); 80 | - if (!(saved_efer & EFER_SVME)) 81 | + if (!(smram->smram64.efer & EFER_SVME)) 82 | return 1; 83 | 84 | - vmcb12_gpa = GET_SMSTATE(u64, smstate, 0x7ee0); 85 | - if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map) == -EINVAL) 86 | + if (kvm_vcpu_map(vcpu, gpa_to_gfn(smram->smram64.svm_guest_vmcb_gpa), &map) == -EINVAL) 87 | return 1; 88 | 89 | ret = 1; 90 | @@ -4485,7 +4476,7 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) 91 | vmcb12 = map.hva; 92 | nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); 93 | nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); 94 | - ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, false); 95 | + ret = enter_svm_guest_mode(vcpu, smram->smram64.svm_guest_vmcb_gpa, vmcb12, false); 96 | 97 | if (ret) 98 | goto unmap_save; 99 | -------------------------------------------------------------------------------- /debian/patches/pve/0015-KVM-x86-SVM-don-t-save-SVM-state-to-SMRAM-when-VM-is.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:50:10 +0300 4 | Subject: [PATCH] KVM: x86: SVM: don't save SVM state to SMRAM when VM is not 5 | long mode capable 6 | 7 | When the guest CPUID doesn't have support for long mode, 32 bit SMRAM 8 | layout is used and it has no support for preserving EFER and/or SVM 9 | state. 10 | 11 | Note that this isn't relevant to running 32 bit guests on VM which is 12 | long mode capable - such VM can still run 32 bit guests in compatibility 13 | mode. 14 | 15 | Signed-off-by: Maxim Levitsky 16 | Signed-off-by: Thomas Lamprecht 17 | --- 18 | arch/x86/kvm/svm/svm.c | 9 +++++++++ 19 | 1 file changed, 9 insertions(+) 20 | 21 | diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c 22 | index bfacbef667d7..6b02f99fe70c 100644 23 | --- a/arch/x86/kvm/svm/svm.c 24 | +++ b/arch/x86/kvm/svm/svm.c 25 | @@ -4394,6 +4394,15 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, union kvm_smram *smram) 26 | if (!is_guest_mode(vcpu)) 27 | return 0; 28 | 29 | + /* 30 | + * 32 bit SMRAM format doesn't preserve EFER and SVM state. 31 | + * SVM should not be enabled by the userspace without marking 32 | + * the CPU as at least long mode capable. 33 | + */ 34 | + 35 | + if (!guest_cpuid_has(vcpu, X86_FEATURE_LM)) 36 | + return 1; 37 | + 38 | smram->smram64.svm_guest_flag = 1; 39 | smram->smram64.svm_guest_vmcb_gpa = svm->nested.vmcb12_gpa; 40 | 41 | -------------------------------------------------------------------------------- /debian/patches/pve/0016-KVM-x86-emulator-smm-preserve-interrupt-shadow-in-SM.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Maxim Levitsky 3 | Date: Wed, 3 Aug 2022 18:50:11 +0300 4 | Subject: [PATCH] KVM: x86: emulator/smm: preserve interrupt shadow in SMRAM 5 | 6 | When #SMI is asserted, the CPU can be in interrupt shadow 7 | due to sti or mov ss. 8 | 9 | It is not mandatory in Intel/AMD prm to have the #SMI 10 | blocked during the shadow, and on top of 11 | that, since neither SVM nor VMX has true support for SMI 12 | window, waiting for one instruction would mean single stepping 13 | the guest. 14 | 15 | Instead, allow #SMI in this case, but both reset the interrupt 16 | window and stash its value in SMRAM to restore it on exit 17 | from SMM. 18 | 19 | This fixes rare failures seen mostly on windows guests on VMX, 20 | when #SMI falls on the sti instruction which mainfest in 21 | VM entry failure due to EFLAGS.IF not being set, but STI interrupt 22 | window still being set in the VMCS. 23 | 24 | Signed-off-by: Maxim Levitsky 25 | Signed-off-by: Thomas Lamprecht 26 | --- 27 | arch/x86/kvm/emulate.c | 17 ++++++++++++++--- 28 | arch/x86/kvm/kvm_emulate.h | 10 ++++++---- 29 | arch/x86/kvm/x86.c | 12 ++++++++++++ 30 | 3 files changed, 32 insertions(+), 7 deletions(-) 31 | 32 | diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c 33 | index 03f9e5aa036e..bb008a5be539 100644 34 | --- a/arch/x86/kvm/emulate.c 35 | +++ b/arch/x86/kvm/emulate.c 36 | @@ -2435,7 +2435,7 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, 37 | const struct kvm_smram_state_32 *smstate) 38 | { 39 | struct desc_ptr dt; 40 | - int i; 41 | + int i, r; 42 | 43 | ctxt->eflags = smstate->eflags | X86_EFLAGS_FIXED; 44 | ctxt->_eip = smstate->eip; 45 | @@ -2470,8 +2470,16 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, 46 | 47 | ctxt->ops->set_smbase(ctxt, smstate->smbase); 48 | 49 | - return rsm_enter_protected_mode(ctxt, smstate->cr0, 50 | - smstate->cr3, smstate->cr4); 51 | + r = rsm_enter_protected_mode(ctxt, smstate->cr0, 52 | + smstate->cr3, smstate->cr4); 53 | + 54 | + if (r != X86EMUL_CONTINUE) 55 | + return r; 56 | + 57 | + ctxt->ops->set_int_shadow(ctxt, 0); 58 | + ctxt->interruptibility = (u8)smstate->int_shadow; 59 | + 60 | + return X86EMUL_CONTINUE; 61 | } 62 | 63 | #ifdef CONFIG_X86_64 64 | @@ -2520,6 +2528,9 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, 65 | rsm_load_seg_64(ctxt, &smstate->fs, VCPU_SREG_FS); 66 | rsm_load_seg_64(ctxt, &smstate->gs, VCPU_SREG_GS); 67 | 68 | + ctxt->ops->set_int_shadow(ctxt, 0); 69 | + ctxt->interruptibility = (u8)smstate->int_shadow; 70 | + 71 | return X86EMUL_CONTINUE; 72 | } 73 | #endif 74 | diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h 75 | index 76c0b8e7890b..a7313add0f2a 100644 76 | --- a/arch/x86/kvm/kvm_emulate.h 77 | +++ b/arch/x86/kvm/kvm_emulate.h 78 | @@ -234,6 +234,7 @@ struct x86_emulate_ops { 79 | bool (*guest_has_rdpid)(struct x86_emulate_ctxt *ctxt); 80 | 81 | void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked); 82 | + void (*set_int_shadow)(struct x86_emulate_ctxt *ctxt, u8 shadow); 83 | 84 | unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt); 85 | void (*exiting_smm)(struct x86_emulate_ctxt *ctxt); 86 | @@ -518,7 +519,8 @@ struct kvm_smram_state_32 { 87 | u32 reserved1[62]; 88 | u32 smbase; 89 | u32 smm_revision; 90 | - u32 reserved2[5]; 91 | + u32 reserved2[4]; 92 | + u32 int_shadow; /* KVM extension */ 93 | u32 cr4; /* CR4 is not present in Intel/AMD SMRAM image */ 94 | u32 reserved3[5]; 95 | 96 | @@ -566,6 +568,7 @@ static inline void __check_smram32_offsets(void) 97 | __CHECK_SMRAM32_OFFSET(smbase, 0xFEF8); 98 | __CHECK_SMRAM32_OFFSET(smm_revision, 0xFEFC); 99 | __CHECK_SMRAM32_OFFSET(reserved2, 0xFF00); 100 | + __CHECK_SMRAM32_OFFSET(int_shadow, 0xFF10); 101 | __CHECK_SMRAM32_OFFSET(cr4, 0xFF14); 102 | __CHECK_SMRAM32_OFFSET(reserved3, 0xFF18); 103 | __CHECK_SMRAM32_OFFSET(ds, 0xFF2C); 104 | @@ -625,7 +628,7 @@ struct kvm_smram_state_64 { 105 | u64 io_restart_rsi; 106 | u64 io_restart_rdi; 107 | u32 io_restart_dword; 108 | - u32 reserved1; 109 | + u32 int_shadow; 110 | u8 io_inst_restart; 111 | u8 auto_hlt_restart; 112 | u8 reserved2[6]; 113 | @@ -663,7 +666,6 @@ struct kvm_smram_state_64 { 114 | u64 gprs[16]; /* GPRS in a reversed "natural" X86 order (R15/R14/../RCX/RAX.) */ 115 | }; 116 | 117 | - 118 | static inline void __check_smram64_offsets(void) 119 | { 120 | #define __CHECK_SMRAM64_OFFSET(field, offset) \ 121 | @@ -684,7 +686,7 @@ static inline void __check_smram64_offsets(void) 122 | __CHECK_SMRAM64_OFFSET(io_restart_rsi, 0xFEB0); 123 | __CHECK_SMRAM64_OFFSET(io_restart_rdi, 0xFEB8); 124 | __CHECK_SMRAM64_OFFSET(io_restart_dword, 0xFEC0); 125 | - __CHECK_SMRAM64_OFFSET(reserved1, 0xFEC4); 126 | + __CHECK_SMRAM64_OFFSET(int_shadow, 0xFEC4); 127 | __CHECK_SMRAM64_OFFSET(io_inst_restart, 0xFEC8); 128 | __CHECK_SMRAM64_OFFSET(auto_hlt_restart, 0xFEC9); 129 | __CHECK_SMRAM64_OFFSET(reserved2, 0xFECA); 130 | diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c 131 | index 7a4d86f9bdcd..609829ec1d13 100644 132 | --- a/arch/x86/kvm/x86.c 133 | +++ b/arch/x86/kvm/x86.c 134 | @@ -8173,6 +8173,11 @@ static void emulator_set_nmi_mask(struct x86_emulate_ctxt *ctxt, bool masked) 135 | static_call(kvm_x86_set_nmi_mask)(emul_to_vcpu(ctxt), masked); 136 | } 137 | 138 | +static void emulator_set_int_shadow(struct x86_emulate_ctxt *ctxt, u8 shadow) 139 | +{ 140 | + static_call(kvm_x86_set_interrupt_shadow)(emul_to_vcpu(ctxt), shadow); 141 | +} 142 | + 143 | static unsigned emulator_get_hflags(struct x86_emulate_ctxt *ctxt) 144 | { 145 | return emul_to_vcpu(ctxt)->arch.hflags; 146 | @@ -8253,6 +8258,7 @@ static const struct x86_emulate_ops emulate_ops = { 147 | .guest_has_fxsr = emulator_guest_has_fxsr, 148 | .guest_has_rdpid = emulator_guest_has_rdpid, 149 | .set_nmi_mask = emulator_set_nmi_mask, 150 | + .set_int_shadow = emulator_set_int_shadow, 151 | .get_hflags = emulator_get_hflags, 152 | .exiting_smm = emulator_exiting_smm, 153 | .leave_smm = emulator_leave_smm, 154 | @@ -10170,6 +10176,8 @@ static void enter_smm_save_state_32(struct kvm_vcpu *vcpu, struct kvm_smram_stat 155 | smram->cr4 = kvm_read_cr4(vcpu); 156 | smram->smm_revision = 0x00020000; 157 | smram->smbase = vcpu->arch.smbase; 158 | + 159 | + smram->int_shadow = static_call(kvm_x86_get_interrupt_shadow)(vcpu); 160 | } 161 | 162 | #ifdef CONFIG_X86_64 163 | @@ -10218,6 +10226,8 @@ static void enter_smm_save_state_64(struct kvm_vcpu *vcpu, struct kvm_smram_stat 164 | enter_smm_save_seg_64(vcpu, &smram->ds, VCPU_SREG_DS); 165 | enter_smm_save_seg_64(vcpu, &smram->fs, VCPU_SREG_FS); 166 | enter_smm_save_seg_64(vcpu, &smram->gs, VCPU_SREG_GS); 167 | + 168 | + smram->int_shadow = static_call(kvm_x86_get_interrupt_shadow)(vcpu); 169 | } 170 | #endif 171 | 172 | @@ -10254,6 +10264,8 @@ static void enter_smm(struct kvm_vcpu *vcpu) 173 | kvm_set_rflags(vcpu, X86_EFLAGS_FIXED); 174 | kvm_rip_write(vcpu, 0x8000); 175 | 176 | + static_call(kvm_x86_set_interrupt_shadow)(vcpu, 0); 177 | + 178 | cr0 = vcpu->arch.cr0 & ~(X86_CR0_PE | X86_CR0_EM | X86_CR0_TS | X86_CR0_PG); 179 | static_call(kvm_x86_set_cr0)(vcpu, cr0); 180 | vcpu->arch.cr0 = cr0; 181 | -------------------------------------------------------------------------------- /debian/patches/series.linux: -------------------------------------------------------------------------------- 1 | ubuntu/0001-apparmor-compatibility-v2.x-net-rules.patch 2 | ubuntu/0002-apparmor-af_unix-mediation.patch 3 | ubuntu/0003-apparmor-fix-apparmor-mediating-locking-non-fs-unix-sockets.patch 4 | ubuntu/0004-apparmor-fix-use-after-free-in-sk_peer_label.patch 5 | 6 | pve/0001-Make-mkcompile_h-accept-an-alternate-timestamp-strin.patch 7 | pve/0002-bridge-keep-MAC-of-first-assigned-port.patch 8 | pve/0003-pci-Enable-overrides-for-missing-ACS-capabilities-4..patch 9 | pve/0004-kvm-disable-default-dynamic-halt-polling-growth.patch 10 | pve/0005-net-core-downgrade-unregister_netdevice-refcount-lea.patch 11 | # pve/0007-Ubuntu-remove-leftover-reference-to-ubuntu-hio-drive.patch # Not in Ubuntu Mainline 12 | pve/0008-bug-introduce-ASSERT_STRUCT_OFFSET.patch 13 | pve/0009-KVM-x86-emulator-update-the-emulation-mode-after-rsm.patch 14 | pve/0010-KVM-x86-emulator-smm-add-structs-for-KVM-s-smram-lay.patch 15 | pve/0011-KVM-x86-emulator-smm-use-smram-structs-in-the-common.patch 16 | pve/0012-KVM-x86-emulator-smm-use-smram-struct-for-32-bit-smr.patch 17 | pve/0013-KVM-x86-emulator-smm-use-smram-struct-for-64-bit-smr.patch 18 | pve/0014-KVM-x86-SVM-use-smram-structs.patch 19 | pve/0015-KVM-x86-SVM-don-t-save-SVM-state-to-SMRAM-when-VM-is.patch 20 | pve/0016-KVM-x86-emulator-smm-preserve-interrupt-shadow-in-SM.patch 21 | -------------------------------------------------------------------------------- /debian/patches/series.zfs: -------------------------------------------------------------------------------- 1 | zfs/0001-Check-for-META-and-DCH-consistency-in-autoconf.patch 2 | zfs/0002-always-load-ZFS-module-on-boot.patch 3 | zfs/0003-Fix-the-path-to-the-zed-binary-on-the-systemd-unit.patch 4 | zfs/0004-import-with-d-dev-disk-by-id-in-scan-service.patch 5 | zfs/0005-Enable-zed-emails.patch 6 | zfs/0006-dont-symlink-zed-scripts.patch 7 | zfs/0007-Use-installed-python3.patch 8 | zfs/0008-Add-systemd-unit-for-importing-specific-pools.patch 9 | zfs/0009-Patch-move-manpage-arcstat-1-to-arcstat-8.patch 10 | zfs/0010-arcstat-Fix-integer-division-with-python3.patch 11 | zfs/0011-arc-stat-summary-guard-access-to-l2arc-MFU-MRU-stats.patch 12 | -------------------------------------------------------------------------------- /debian/patches/ubuntu/0001-apparmor-compatibility-v2.x-net-rules.patch: -------------------------------------------------------------------------------- 1 | From f153f512ed7a81e9b92a04d49869cffebf714f52 Mon Sep 17 00:00:00 2001 2 | From: John Johansen 3 | Date: Sun, 17 Jun 2018 03:56:25 -0700 4 | Subject: UBUNTU: SAUCE: apparmor: patch to provide compatibility with v2.x net 5 | rules 6 | 7 | The networking rules upstreamed in 4.17 have a deliberate abi break 8 | with the older 2.x network rules. 9 | 10 | This patch provides compatibility with the older rules for those 11 | still using an apparmor 2.x userspace and still want network rules 12 | to work on a newer kernel. 13 | 14 | Signed-off-by: John Johansen 15 | [ saf: resolve conflicts when rebasing to 4.20 ] 16 | Signed-off-by: Seth Forshee 17 | --- 18 | security/apparmor/apparmorfs.c | 1 + 19 | security/apparmor/include/apparmor.h | 2 +- 20 | security/apparmor/include/net.h | 11 ++++++++ 21 | security/apparmor/include/policy.h | 2 ++ 22 | security/apparmor/net.c | 31 ++++++++++++++++----- 23 | security/apparmor/policy.c | 1 + 24 | security/apparmor/policy_unpack.c | 54 ++++++++++++++++++++++++++++++++++-- 25 | 7 files changed, 92 insertions(+), 10 deletions(-) 26 | 27 | (limited to 'security/apparmor') 28 | 29 | diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c 30 | index 2ee3b3d..0aef8e3 100644 31 | --- a/security/apparmor/apparmorfs.c 32 | +++ b/security/apparmor/apparmorfs.c 33 | @@ -2362,6 +2362,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { 34 | AA_SFS_DIR("domain", aa_sfs_entry_domain), 35 | AA_SFS_DIR("file", aa_sfs_entry_file), 36 | AA_SFS_DIR("network_v8", aa_sfs_entry_network), 37 | + AA_SFS_DIR("network", aa_sfs_entry_network_compat), 38 | AA_SFS_DIR("mount", aa_sfs_entry_mount), 39 | AA_SFS_DIR("namespaces", aa_sfs_entry_ns), 40 | AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), 41 | diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h 42 | index 1fbabdb..5870de2 100644 43 | --- a/security/apparmor/include/apparmor.h 44 | +++ b/security/apparmor/include/apparmor.h 45 | @@ -20,7 +20,7 @@ 46 | #define AA_CLASS_UNKNOWN 1 47 | #define AA_CLASS_FILE 2 48 | #define AA_CLASS_CAP 3 49 | -#define AA_CLASS_DEPRECATED 4 50 | +#define AA_CLASS_NET_COMPAT 4 51 | #define AA_CLASS_RLIMITS 5 52 | #define AA_CLASS_DOMAIN 6 53 | #define AA_CLASS_MOUNT 7 54 | diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h 55 | index aadb4b2..98a42ef 100644 56 | --- a/security/apparmor/include/net.h 57 | +++ b/security/apparmor/include/net.h 58 | @@ -68,6 +68,16 @@ struct aa_sk_ctx { 59 | DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \ 60 | (SK)->sk_protocol) 61 | 62 | +/* struct aa_net - network confinement data 63 | + * @allow: basic network families permissions 64 | + * @audit: which network permissions to force audit 65 | + * @quiet: which network permissions to quiet rejects 66 | + */ 67 | +struct aa_net_compat { 68 | + u16 allow[AF_MAX]; 69 | + u16 audit[AF_MAX]; 70 | + u16 quiet[AF_MAX]; 71 | +}; 72 | 73 | #define af_select(FAMILY, FN, DEF_FN) \ 74 | ({ \ 75 | @@ -87,6 +97,7 @@ struct aa_secmark { 76 | }; 77 | 78 | extern struct aa_sfs_entry aa_sfs_entry_network[]; 79 | +extern struct aa_sfs_entry aa_sfs_entry_network_compat[]; 80 | 81 | void audit_net_cb(struct audit_buffer *ab, void *va); 82 | int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 83 | diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h 84 | index b5b4b81..f904105 100644 85 | --- a/security/apparmor/include/policy.h 86 | +++ b/security/apparmor/include/policy.h 87 | @@ -108,6 +108,7 @@ struct aa_data { 88 | * @policy: general match rules governing policy 89 | * @file: The set of rules governing basic file access and domain transitions 90 | * @caps: capabilities for the profile 91 | + * @net_compat: v2 compat network controls for the profile 92 | * @rlimits: rlimits for the profile 93 | * 94 | * @dents: dentries for the profiles file entries in apparmorfs 95 | @@ -145,6 +146,7 @@ struct aa_profile { 96 | struct aa_policydb policy; 97 | struct aa_file_rules file; 98 | struct aa_caps caps; 99 | + struct aa_net_compat *net_compat; 100 | 101 | int xattr_count; 102 | char **xattrs; 103 | diff --git a/security/apparmor/net.c b/security/apparmor/net.c 104 | index e0c1b50..e693df8 100644 105 | --- a/security/apparmor/net.c 106 | +++ b/security/apparmor/net.c 107 | @@ -24,6 +24,11 @@ struct aa_sfs_entry aa_sfs_entry_network[] = { 108 | { } 109 | }; 110 | 111 | +struct aa_sfs_entry aa_sfs_entry_network_compat[] = { 112 | + AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK), 113 | + { } 114 | +}; 115 | + 116 | static const char * const net_mask_names[] = { 117 | "unknown", 118 | "send", 119 | @@ -118,14 +123,26 @@ int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 120 | if (profile_unconfined(profile)) 121 | return 0; 122 | state = PROFILE_MEDIATES(profile, AA_CLASS_NET); 123 | - if (!state) 124 | + if (state) { 125 | + if (!state) 126 | + return 0; 127 | + buffer[0] = cpu_to_be16(family); 128 | + buffer[1] = cpu_to_be16((u16) type); 129 | + state = aa_dfa_match_len(profile->policy.dfa, state, 130 | + (char *) &buffer, 4); 131 | + aa_compute_perms(profile->policy.dfa, state, &perms); 132 | + } else if (profile->net_compat) { 133 | + /* 2.x socket mediation compat */ 134 | + perms.allow = (profile->net_compat->allow[family] & (1 << type)) ? 135 | + ALL_PERMS_MASK : 0; 136 | + perms.audit = (profile->net_compat->audit[family] & (1 << type)) ? 137 | + ALL_PERMS_MASK : 0; 138 | + perms.quiet = (profile->net_compat->quiet[family] & (1 << type)) ? 139 | + ALL_PERMS_MASK : 0; 140 | + 141 | + } else { 142 | return 0; 143 | - 144 | - buffer[0] = cpu_to_be16(family); 145 | - buffer[1] = cpu_to_be16((u16) type); 146 | - state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer, 147 | - 4); 148 | - aa_compute_perms(profile->policy.dfa, state, &perms); 149 | + } 150 | aa_apply_modes_to_perms(profile, &perms); 151 | 152 | return aa_check_perms(profile, &perms, request, sa, audit_net_cb); 153 | diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c 154 | index 4c010c9..a00e39b 100644 155 | --- a/security/apparmor/policy.c 156 | +++ b/security/apparmor/policy.c 157 | @@ -222,6 +222,7 @@ void aa_free_profile(struct aa_profile *profile) 158 | aa_free_file_rules(&profile->file); 159 | aa_free_cap_rules(&profile->caps); 160 | aa_free_rlimit_rules(&profile->rlimits); 161 | + kfree_sensitive(profile->net_compat); 162 | 163 | for (i = 0; i < profile->xattr_count; i++) 164 | kfree_sensitive(profile->xattrs[i]); 165 | diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c 166 | index 4e1f96b..aedfecc 100644 167 | --- a/security/apparmor/policy_unpack.c 168 | +++ b/security/apparmor/policy_unpack.c 169 | @@ -34,7 +34,7 @@ 170 | 171 | #define v5 5 /* base version */ 172 | #define v6 6 /* per entry policydb mediation check */ 173 | -#define v7 7 174 | +#define v7 7 /* v2 compat networking */ 175 | #define v8 8 /* full network masking */ 176 | 177 | /* 178 | @@ -314,6 +314,19 @@ fail: 179 | return false; 180 | } 181 | 182 | +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name) 183 | +{ 184 | + if (unpack_nameX(e, AA_U16, name)) { 185 | + if (!inbounds(e, sizeof(u16))) 186 | + return 0; 187 | + if (data) 188 | + *data = le16_to_cpu(get_unaligned((__le16 *) e->pos)); 189 | + e->pos += sizeof(u16); 190 | + return 1; 191 | + } 192 | + return 0; 193 | +} 194 | + 195 | static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) 196 | { 197 | void *pos = e->pos; 198 | @@ -676,7 +689,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) 199 | struct aa_profile *profile = NULL; 200 | const char *tmpname, *tmpns = NULL, *name = NULL; 201 | const char *info = "failed to unpack profile"; 202 | - size_t ns_len; 203 | + size_t size = 0, ns_len; 204 | struct rhashtable_params params = { 0 }; 205 | char *key = NULL; 206 | struct aa_data *data; 207 | @@ -823,6 +836,43 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) 208 | goto fail; 209 | } 210 | 211 | + size = unpack_array(e, "net_allowed_af"); 212 | + if (size || VERSION_LT(e->version, v8)) { 213 | + profile->net_compat = kzalloc(sizeof(struct aa_net_compat), GFP_KERNEL); 214 | + if (!profile->net_compat) { 215 | + info = "out of memory"; 216 | + goto fail; 217 | + } 218 | + for (i = 0; i < size; i++) { 219 | + /* discard extraneous rules that this kernel will 220 | + * never request 221 | + */ 222 | + if (i >= AF_MAX) { 223 | + u16 tmp; 224 | + 225 | + if (!unpack_u16(e, &tmp, NULL) || 226 | + !unpack_u16(e, &tmp, NULL) || 227 | + !unpack_u16(e, &tmp, NULL)) 228 | + goto fail; 229 | + continue; 230 | + } 231 | + if (!unpack_u16(e, &profile->net_compat->allow[i], NULL)) 232 | + goto fail; 233 | + if (!unpack_u16(e, &profile->net_compat->audit[i], NULL)) 234 | + goto fail; 235 | + if (!unpack_u16(e, &profile->net_compat->quiet[i], NULL)) 236 | + goto fail; 237 | + } 238 | + if (size && !unpack_nameX(e, AA_ARRAYEND, NULL)) 239 | + goto fail; 240 | + if (VERSION_LT(e->version, v7)) { 241 | + /* pre v7 policy always allowed these */ 242 | + profile->net_compat->allow[AF_UNIX] = 0xffff; 243 | + profile->net_compat->allow[AF_NETLINK] = 0xffff; 244 | + } 245 | + } 246 | + 247 | + 248 | if (unpack_nameX(e, AA_STRUCT, "policydb")) { 249 | /* generic policy dfa - optional and may be NULL */ 250 | info = "failed to unpack policydb"; 251 | -------------------------------------------------------------------------------- /debian/patches/ubuntu/0002-apparmor-af_unix-mediation.patch: -------------------------------------------------------------------------------- 1 | From c59a2789cc146827c225f9f9035b9fc23a82fc45 Mon Sep 17 00:00:00 2001 2 | From: John Johansen 3 | Date: Tue, 18 Jul 2017 23:27:23 -0700 4 | Subject: UBUNTU: SAUCE: apparmor: af_unix mediation 5 | 6 | af_socket mediation did not make it into 4.17 so add remaining out 7 | of tree patch 8 | 9 | Signed-off-by: John Johansen 10 | Signed-off-by: Seth Forshee 11 | --- 12 | security/apparmor/Makefile | 3 +- 13 | security/apparmor/af_unix.c | 652 ++++++++++++++++++++++++++++++++++++ 14 | security/apparmor/apparmorfs.c | 6 + 15 | security/apparmor/file.c | 4 +- 16 | security/apparmor/include/af_unix.h | 114 +++++++ 17 | security/apparmor/include/net.h | 4 + 18 | security/apparmor/include/path.h | 1 + 19 | security/apparmor/include/policy.h | 10 +- 20 | security/apparmor/lsm.c | 112 +++++++ 21 | security/apparmor/net.c | 53 ++- 22 | 10 files changed, 953 insertions(+), 6 deletions(-) 23 | create mode 100644 security/apparmor/af_unix.c 24 | create mode 100644 security/apparmor/include/af_unix.h 25 | 26 | (limited to 'security/apparmor') 27 | 28 | diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile 29 | index ff23fcf..fad407f 100644 30 | --- a/security/apparmor/Makefile 31 | +++ b/security/apparmor/Makefile 32 | @@ -5,7 +5,8 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o 33 | 34 | apparmor-y := apparmorfs.o audit.o capability.o task.o ipc.o lib.o match.o \ 35 | path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 36 | - resource.o secid.o file.o policy_ns.o label.o mount.o net.o 37 | + resource.o secid.o file.o policy_ns.o label.o mount.o net.o \ 38 | + af_unix.o 39 | apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 40 | 41 | clean-files := capability_names.h rlim_names.h net_names.h 42 | diff --git a/security/apparmor/af_unix.c b/security/apparmor/af_unix.c 43 | new file mode 100644 44 | index 0000000..54b3796 45 | --- /dev/null 46 | +++ b/security/apparmor/af_unix.c 47 | @@ -0,0 +1,652 @@ 48 | +/* 49 | + * AppArmor security module 50 | + * 51 | + * This file contains AppArmor af_unix fine grained mediation 52 | + * 53 | + * Copyright 2018 Canonical Ltd. 54 | + * 55 | + * This program is free software; you can redistribute it and/or 56 | + * modify it under the terms of the GNU General Public License as 57 | + * published by the Free Software Foundation, version 2 of the 58 | + * License. 59 | + */ 60 | + 61 | +#include 62 | + 63 | +#include "include/audit.h" 64 | +#include "include/af_unix.h" 65 | +#include "include/apparmor.h" 66 | +#include "include/file.h" 67 | +#include "include/label.h" 68 | +#include "include/path.h" 69 | +#include "include/policy.h" 70 | +#include "include/cred.h" 71 | + 72 | +static inline struct sock *aa_sock(struct unix_sock *u) 73 | +{ 74 | + return &u->sk; 75 | +} 76 | + 77 | +static inline int unix_fs_perm(const char *op, u32 mask, struct aa_label *label, 78 | + struct unix_sock *u, int flags) 79 | +{ 80 | + AA_BUG(!label); 81 | + AA_BUG(!u); 82 | + AA_BUG(!UNIX_FS(aa_sock(u))); 83 | + 84 | + if (unconfined(label) || !LABEL_MEDIATES(label, AA_CLASS_FILE)) 85 | + return 0; 86 | + 87 | + mask &= NET_FS_PERMS; 88 | + if (!u->path.dentry) { 89 | + struct path_cond cond = { }; 90 | + struct aa_perms perms = { }; 91 | + struct aa_profile *profile; 92 | + 93 | + /* socket path has been cleared because it is being shutdown 94 | + * can only fall back to original sun_path request 95 | + */ 96 | + struct aa_sk_ctx *ctx = SK_CTX(&u->sk); 97 | + if (ctx->path.dentry) 98 | + return aa_path_perm(op, label, &ctx->path, flags, mask, 99 | + &cond); 100 | + return fn_for_each_confined(label, profile, 101 | + ((flags | profile->path_flags) & PATH_MEDIATE_DELETED) ? 102 | + __aa_path_perm(op, profile, 103 | + u->addr->name->sun_path, mask, 104 | + &cond, flags, &perms) : 105 | + aa_audit_file(profile, &nullperms, op, mask, 106 | + u->addr->name->sun_path, NULL, 107 | + NULL, cond.uid, 108 | + "Failed name lookup - " 109 | + "deleted entry", -EACCES)); 110 | + } else { 111 | + /* the sunpath may not be valid for this ns so use the path */ 112 | + struct path_cond cond = { u->path.dentry->d_inode->i_uid, 113 | + u->path.dentry->d_inode->i_mode 114 | + }; 115 | + 116 | + return aa_path_perm(op, label, &u->path, flags, mask, &cond); 117 | + } 118 | + 119 | + return 0; 120 | +} 121 | + 122 | +/* passing in state returned by PROFILE_MEDIATES_AF */ 123 | +static unsigned int match_to_prot(struct aa_profile *profile, 124 | + unsigned int state, int type, int protocol, 125 | + const char **info) 126 | +{ 127 | + __be16 buffer[2]; 128 | + buffer[0] = cpu_to_be16(type); 129 | + buffer[1] = cpu_to_be16(protocol); 130 | + state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer, 131 | + 4); 132 | + if (!state) 133 | + *info = "failed type and protocol match"; 134 | + return state; 135 | +} 136 | + 137 | +static unsigned int match_addr(struct aa_profile *profile, unsigned int state, 138 | + struct sockaddr_un *addr, int addrlen) 139 | +{ 140 | + if (addr) 141 | + /* include leading \0 */ 142 | + state = aa_dfa_match_len(profile->policy.dfa, state, 143 | + addr->sun_path, 144 | + unix_addr_len(addrlen)); 145 | + else 146 | + /* anonymous end point */ 147 | + state = aa_dfa_match_len(profile->policy.dfa, state, "\x01", 148 | + 1); 149 | + /* todo change to out of band */ 150 | + state = aa_dfa_null_transition(profile->policy.dfa, state); 151 | + return state; 152 | +} 153 | + 154 | +static unsigned int match_to_local(struct aa_profile *profile, 155 | + unsigned int state, int type, int protocol, 156 | + struct sockaddr_un *addr, int addrlen, 157 | + const char **info) 158 | +{ 159 | + state = match_to_prot(profile, state, type, protocol, info); 160 | + if (state) { 161 | + state = match_addr(profile, state, addr, addrlen); 162 | + if (state) { 163 | + /* todo: local label matching */ 164 | + state = aa_dfa_null_transition(profile->policy.dfa, 165 | + state); 166 | + if (!state) 167 | + *info = "failed local label match"; 168 | + } else 169 | + *info = "failed local address match"; 170 | + } 171 | + 172 | + return state; 173 | +} 174 | + 175 | +static unsigned int match_to_sk(struct aa_profile *profile, 176 | + unsigned int state, struct unix_sock *u, 177 | + const char **info) 178 | +{ 179 | + struct sockaddr_un *addr = NULL; 180 | + int addrlen = 0; 181 | + 182 | + if (u->addr) { 183 | + addr = u->addr->name; 184 | + addrlen = u->addr->len; 185 | + } 186 | + 187 | + return match_to_local(profile, state, u->sk.sk_type, u->sk.sk_protocol, 188 | + addr, addrlen, info); 189 | +} 190 | + 191 | +#define CMD_ADDR 1 192 | +#define CMD_LISTEN 2 193 | +#define CMD_OPT 4 194 | + 195 | +static inline unsigned int match_to_cmd(struct aa_profile *profile, 196 | + unsigned int state, struct unix_sock *u, 197 | + char cmd, const char **info) 198 | +{ 199 | + state = match_to_sk(profile, state, u, info); 200 | + if (state) { 201 | + state = aa_dfa_match_len(profile->policy.dfa, state, &cmd, 1); 202 | + if (!state) 203 | + *info = "failed cmd selection match"; 204 | + } 205 | + 206 | + return state; 207 | +} 208 | + 209 | +static inline unsigned int match_to_peer(struct aa_profile *profile, 210 | + unsigned int state, 211 | + struct unix_sock *u, 212 | + struct sockaddr_un *peer_addr, 213 | + int peer_addrlen, 214 | + const char **info) 215 | +{ 216 | + state = match_to_cmd(profile, state, u, CMD_ADDR, info); 217 | + if (state) { 218 | + state = match_addr(profile, state, peer_addr, peer_addrlen); 219 | + if (!state) 220 | + *info = "failed peer address match"; 221 | + } 222 | + return state; 223 | +} 224 | + 225 | +static int do_perms(struct aa_profile *profile, unsigned int state, u32 request, 226 | + struct common_audit_data *sa) 227 | +{ 228 | + struct aa_perms perms; 229 | + 230 | + AA_BUG(!profile); 231 | + 232 | + aa_compute_perms(profile->policy.dfa, state, &perms); 233 | + aa_apply_modes_to_perms(profile, &perms); 234 | + return aa_check_perms(profile, &perms, request, sa, 235 | + audit_net_cb); 236 | +} 237 | + 238 | +static int match_label(struct aa_profile *profile, struct aa_profile *peer, 239 | + unsigned int state, u32 request, 240 | + struct common_audit_data *sa) 241 | +{ 242 | + AA_BUG(!profile); 243 | + AA_BUG(!peer); 244 | + 245 | + aad(sa)->peer = &peer->label; 246 | + 247 | + if (state) { 248 | + state = aa_dfa_match(profile->policy.dfa, state, 249 | + peer->base.hname); 250 | + if (!state) 251 | + aad(sa)->info = "failed peer label match"; 252 | + } 253 | + return do_perms(profile, state, request, sa); 254 | +} 255 | + 256 | + 257 | +/* unix sock creation comes before we know if the socket will be an fs 258 | + * socket 259 | + * v6 - semantics are handled by mapping in profile load 260 | + * v7 - semantics require sock create for tasks creating an fs socket. 261 | + */ 262 | +static int profile_create_perm(struct aa_profile *profile, int family, 263 | + int type, int protocol) 264 | +{ 265 | + unsigned int state; 266 | + DEFINE_AUDIT_NET(sa, OP_CREATE, NULL, family, type, protocol); 267 | + 268 | + AA_BUG(!profile); 269 | + AA_BUG(profile_unconfined(profile)); 270 | + 271 | + if ((state = PROFILE_MEDIATES_AF(profile, AF_UNIX))) { 272 | + state = match_to_prot(profile, state, type, protocol, 273 | + &aad(&sa)->info); 274 | + return do_perms(profile, state, AA_MAY_CREATE, &sa); 275 | + } 276 | + 277 | + return aa_profile_af_perm(profile, &sa, AA_MAY_CREATE, family, type); 278 | +} 279 | + 280 | +int aa_unix_create_perm(struct aa_label *label, int family, int type, 281 | + int protocol) 282 | +{ 283 | + struct aa_profile *profile; 284 | + 285 | + if (unconfined(label)) 286 | + return 0; 287 | + 288 | + return fn_for_each_confined(label, profile, 289 | + profile_create_perm(profile, family, type, protocol)); 290 | +} 291 | + 292 | + 293 | +static inline int profile_sk_perm(struct aa_profile *profile, const char *op, 294 | + u32 request, struct sock *sk) 295 | +{ 296 | + unsigned int state; 297 | + DEFINE_AUDIT_SK(sa, op, sk); 298 | + 299 | + AA_BUG(!profile); 300 | + AA_BUG(!sk); 301 | + AA_BUG(UNIX_FS(sk)); 302 | + AA_BUG(profile_unconfined(profile)); 303 | + 304 | + state = PROFILE_MEDIATES_AF(profile, AF_UNIX); 305 | + if (state) { 306 | + state = match_to_sk(profile, state, unix_sk(sk), 307 | + &aad(&sa)->info); 308 | + return do_perms(profile, state, request, &sa); 309 | + } 310 | + 311 | + return aa_profile_af_sk_perm(profile, &sa, request, sk); 312 | +} 313 | + 314 | +int aa_unix_label_sk_perm(struct aa_label *label, const char *op, u32 request, 315 | + struct sock *sk) 316 | +{ 317 | + struct aa_profile *profile; 318 | + 319 | + return fn_for_each_confined(label, profile, 320 | + profile_sk_perm(profile, op, request, sk)); 321 | +} 322 | + 323 | +static int unix_label_sock_perm(struct aa_label *label, const char *op, u32 request, 324 | + struct socket *sock) 325 | +{ 326 | + if (unconfined(label)) 327 | + return 0; 328 | + if (UNIX_FS(sock->sk)) 329 | + return unix_fs_perm(op, request, label, unix_sk(sock->sk), 0); 330 | + 331 | + return aa_unix_label_sk_perm(label, op, request, sock->sk); 332 | +} 333 | + 334 | +/* revaliation, get/set attr */ 335 | +int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock) 336 | +{ 337 | + struct aa_label *label; 338 | + int error; 339 | + 340 | + label = begin_current_label_crit_section(); 341 | + error = unix_label_sock_perm(label, op, request, sock); 342 | + end_current_label_crit_section(label); 343 | + 344 | + return error; 345 | +} 346 | + 347 | +static int profile_bind_perm(struct aa_profile *profile, struct sock *sk, 348 | + struct sockaddr *addr, int addrlen) 349 | +{ 350 | + unsigned int state; 351 | + DEFINE_AUDIT_SK(sa, OP_BIND, sk); 352 | + 353 | + AA_BUG(!profile); 354 | + AA_BUG(!sk); 355 | + AA_BUG(addr->sa_family != AF_UNIX); 356 | + AA_BUG(profile_unconfined(profile)); 357 | + AA_BUG(unix_addr_fs(addr, addrlen)); 358 | + 359 | + state = PROFILE_MEDIATES_AF(profile, AF_UNIX); 360 | + if (state) { 361 | + /* bind for abstract socket */ 362 | + aad(&sa)->net.addr = unix_addr(addr); 363 | + aad(&sa)->net.addrlen = addrlen; 364 | + 365 | + state = match_to_local(profile, state, 366 | + sk->sk_type, sk->sk_protocol, 367 | + unix_addr(addr), addrlen, 368 | + &aad(&sa)->info); 369 | + return do_perms(profile, state, AA_MAY_BIND, &sa); 370 | + } 371 | + 372 | + return aa_profile_af_sk_perm(profile, &sa, AA_MAY_BIND, sk); 373 | +} 374 | + 375 | +int aa_unix_bind_perm(struct socket *sock, struct sockaddr *address, 376 | + int addrlen) 377 | +{ 378 | + struct aa_profile *profile; 379 | + struct aa_label *label; 380 | + int error = 0; 381 | + 382 | + label = begin_current_label_crit_section(); 383 | + /* fs bind is handled by mknod */ 384 | + if (!(unconfined(label) || unix_addr_fs(address, addrlen))) 385 | + error = fn_for_each_confined(label, profile, 386 | + profile_bind_perm(profile, sock->sk, address, 387 | + addrlen)); 388 | + end_current_label_crit_section(label); 389 | + 390 | + return error; 391 | +} 392 | + 393 | +int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address, 394 | + int addrlen) 395 | +{ 396 | + /* unix connections are covered by the 397 | + * - unix_stream_connect (stream) and unix_may_send hooks (dgram) 398 | + * - fs connect is handled by open 399 | + */ 400 | + return 0; 401 | +} 402 | + 403 | +static int profile_listen_perm(struct aa_profile *profile, struct sock *sk, 404 | + int backlog) 405 | +{ 406 | + unsigned int state; 407 | + DEFINE_AUDIT_SK(sa, OP_LISTEN, sk); 408 | + 409 | + AA_BUG(!profile); 410 | + AA_BUG(!sk); 411 | + AA_BUG(UNIX_FS(sk)); 412 | + AA_BUG(profile_unconfined(profile)); 413 | + 414 | + state = PROFILE_MEDIATES_AF(profile, AF_UNIX); 415 | + if (state) { 416 | + __be16 b = cpu_to_be16(backlog); 417 | + 418 | + state = match_to_cmd(profile, state, unix_sk(sk), CMD_LISTEN, 419 | + &aad(&sa)->info); 420 | + if (state) { 421 | + state = aa_dfa_match_len(profile->policy.dfa, state, 422 | + (char *) &b, 2); 423 | + if (!state) 424 | + aad(&sa)->info = "failed listen backlog match"; 425 | + } 426 | + return do_perms(profile, state, AA_MAY_LISTEN, &sa); 427 | + } 428 | + 429 | + return aa_profile_af_sk_perm(profile, &sa, AA_MAY_LISTEN, sk); 430 | +} 431 | + 432 | +int aa_unix_listen_perm(struct socket *sock, int backlog) 433 | +{ 434 | + struct aa_profile *profile; 435 | + struct aa_label *label; 436 | + int error = 0; 437 | + 438 | + label = begin_current_label_crit_section(); 439 | + if (!(unconfined(label) || UNIX_FS(sock->sk))) 440 | + error = fn_for_each_confined(label, profile, 441 | + profile_listen_perm(profile, sock->sk, 442 | + backlog)); 443 | + end_current_label_crit_section(label); 444 | + 445 | + return error; 446 | +} 447 | + 448 | + 449 | +static inline int profile_accept_perm(struct aa_profile *profile, 450 | + struct sock *sk, 451 | + struct sock *newsk) 452 | +{ 453 | + unsigned int state; 454 | + DEFINE_AUDIT_SK(sa, OP_ACCEPT, sk); 455 | + 456 | + AA_BUG(!profile); 457 | + AA_BUG(!sk); 458 | + AA_BUG(UNIX_FS(sk)); 459 | + AA_BUG(profile_unconfined(profile)); 460 | + 461 | + state = PROFILE_MEDIATES_AF(profile, AF_UNIX); 462 | + if (state) { 463 | + state = match_to_sk(profile, state, unix_sk(sk), 464 | + &aad(&sa)->info); 465 | + return do_perms(profile, state, AA_MAY_ACCEPT, &sa); 466 | + } 467 | + 468 | + return aa_profile_af_sk_perm(profile, &sa, AA_MAY_ACCEPT, sk); 469 | +} 470 | + 471 | +/* ability of sock to connect, not peer address binding */ 472 | +int aa_unix_accept_perm(struct socket *sock, struct socket *newsock) 473 | +{ 474 | + struct aa_profile *profile; 475 | + struct aa_label *label; 476 | + int error = 0; 477 | + 478 | + label = begin_current_label_crit_section(); 479 | + if (!(unconfined(label) || UNIX_FS(sock->sk))) 480 | + error = fn_for_each_confined(label, profile, 481 | + profile_accept_perm(profile, sock->sk, 482 | + newsock->sk)); 483 | + end_current_label_crit_section(label); 484 | + 485 | + return error; 486 | +} 487 | + 488 | + 489 | +/* dgram handled by unix_may_sendmsg, right to send on stream done at connect 490 | + * could do per msg unix_stream here 491 | + */ 492 | +/* sendmsg, recvmsg */ 493 | +int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock, 494 | + struct msghdr *msg, int size) 495 | +{ 496 | + return 0; 497 | +} 498 | + 499 | + 500 | +static int profile_opt_perm(struct aa_profile *profile, const char *op, u32 request, 501 | + struct sock *sk, int level, int optname) 502 | +{ 503 | + unsigned int state; 504 | + DEFINE_AUDIT_SK(sa, op, sk); 505 | + 506 | + AA_BUG(!profile); 507 | + AA_BUG(!sk); 508 | + AA_BUG(UNIX_FS(sk)); 509 | + AA_BUG(profile_unconfined(profile)); 510 | + 511 | + state = PROFILE_MEDIATES_AF(profile, AF_UNIX); 512 | + if (state) { 513 | + __be16 b = cpu_to_be16(optname); 514 | + 515 | + state = match_to_cmd(profile, state, unix_sk(sk), CMD_OPT, 516 | + &aad(&sa)->info); 517 | + if (state) { 518 | + state = aa_dfa_match_len(profile->policy.dfa, state, 519 | + (char *) &b, 2); 520 | + if (!state) 521 | + aad(&sa)->info = "failed sockopt match"; 522 | + } 523 | + return do_perms(profile, state, request, &sa); 524 | + } 525 | + 526 | + return aa_profile_af_sk_perm(profile, &sa, request, sk); 527 | +} 528 | + 529 | +int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock, int level, 530 | + int optname) 531 | +{ 532 | + struct aa_profile *profile; 533 | + struct aa_label *label; 534 | + int error = 0; 535 | + 536 | + label = begin_current_label_crit_section(); 537 | + if (!(unconfined(label) || UNIX_FS(sock->sk))) 538 | + error = fn_for_each_confined(label, profile, 539 | + profile_opt_perm(profile, op, request, 540 | + sock->sk, level, optname)); 541 | + end_current_label_crit_section(label); 542 | + 543 | + return error; 544 | +} 545 | + 546 | +/* null peer_label is allowed, in which case the peer_sk label is used */ 547 | +static int profile_peer_perm(struct aa_profile *profile, const char *op, u32 request, 548 | + struct sock *sk, struct sock *peer_sk, 549 | + struct aa_label *peer_label, 550 | + struct common_audit_data *sa) 551 | +{ 552 | + unsigned int state; 553 | + 554 | + AA_BUG(!profile); 555 | + AA_BUG(profile_unconfined(profile)); 556 | + AA_BUG(!sk); 557 | + AA_BUG(!peer_sk); 558 | + AA_BUG(UNIX_FS(peer_sk)); 559 | + 560 | + state = PROFILE_MEDIATES_AF(profile, AF_UNIX); 561 | + if (state) { 562 | + struct aa_sk_ctx *peer_ctx = SK_CTX(peer_sk); 563 | + struct aa_profile *peerp; 564 | + struct sockaddr_un *addr = NULL; 565 | + int len = 0; 566 | + if (unix_sk(peer_sk)->addr) { 567 | + addr = unix_sk(peer_sk)->addr->name; 568 | + len = unix_sk(peer_sk)->addr->len; 569 | + } 570 | + state = match_to_peer(profile, state, unix_sk(sk), 571 | + addr, len, &aad(sa)->info); 572 | + if (!peer_label) 573 | + peer_label = peer_ctx->label; 574 | + return fn_for_each_in_ns(peer_label, peerp, 575 | + match_label(profile, peerp, state, request, 576 | + sa)); 577 | + } 578 | + 579 | + return aa_profile_af_sk_perm(profile, sa, request, sk); 580 | +} 581 | + 582 | +/** 583 | + * 584 | + * Requires: lock held on both @sk and @peer_sk 585 | + */ 586 | +int aa_unix_peer_perm(struct aa_label *label, const char *op, u32 request, 587 | + struct sock *sk, struct sock *peer_sk, 588 | + struct aa_label *peer_label) 589 | +{ 590 | + struct unix_sock *peeru = unix_sk(peer_sk); 591 | + struct unix_sock *u = unix_sk(sk); 592 | + 593 | + AA_BUG(!label); 594 | + AA_BUG(!sk); 595 | + AA_BUG(!peer_sk); 596 | + 597 | + if (UNIX_FS(aa_sock(peeru))) 598 | + return unix_fs_perm(op, request, label, peeru, 0); 599 | + else if (UNIX_FS(aa_sock(u))) 600 | + return unix_fs_perm(op, request, label, u, 0); 601 | + else { 602 | + struct aa_profile *profile; 603 | + DEFINE_AUDIT_SK(sa, op, sk); 604 | + aad(&sa)->net.peer_sk = peer_sk; 605 | + 606 | + /* TODO: ns!!! */ 607 | + if (!net_eq(sock_net(sk), sock_net(peer_sk))) { 608 | + ; 609 | + } 610 | + 611 | + if (unconfined(label)) 612 | + return 0; 613 | + 614 | + return fn_for_each_confined(label, profile, 615 | + profile_peer_perm(profile, op, request, sk, 616 | + peer_sk, peer_label, &sa)); 617 | + } 618 | +} 619 | + 620 | + 621 | +/* from net/unix/af_unix.c */ 622 | +static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) 623 | +{ 624 | + if (unlikely(sk1 == sk2) || !sk2) { 625 | + unix_state_lock(sk1); 626 | + return; 627 | + } 628 | + if (sk1 < sk2) { 629 | + unix_state_lock(sk1); 630 | + unix_state_lock_nested(sk2); 631 | + } else { 632 | + unix_state_lock(sk2); 633 | + unix_state_lock_nested(sk1); 634 | + } 635 | +} 636 | + 637 | +static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2) 638 | +{ 639 | + if (unlikely(sk1 == sk2) || !sk2) { 640 | + unix_state_unlock(sk1); 641 | + return; 642 | + } 643 | + unix_state_unlock(sk1); 644 | + unix_state_unlock(sk2); 645 | +} 646 | + 647 | +int aa_unix_file_perm(struct aa_label *label, const char *op, u32 request, 648 | + struct socket *sock) 649 | +{ 650 | + struct sock *peer_sk = NULL; 651 | + u32 sk_req = request & ~NET_PEER_MASK; 652 | + int error = 0; 653 | + 654 | + AA_BUG(!label); 655 | + AA_BUG(!sock); 656 | + AA_BUG(!sock->sk); 657 | + AA_BUG(sock->sk->sk_family != AF_UNIX); 658 | + 659 | + /* TODO: update sock label with new task label */ 660 | + unix_state_lock(sock->sk); 661 | + peer_sk = unix_peer(sock->sk); 662 | + if (peer_sk) 663 | + sock_hold(peer_sk); 664 | + if (!unix_connected(sock) && sk_req) { 665 | + error = unix_label_sock_perm(label, op, sk_req, sock); 666 | + if (!error) { 667 | + // update label 668 | + } 669 | + } 670 | + unix_state_unlock(sock->sk); 671 | + if (!peer_sk) 672 | + return error; 673 | + 674 | + unix_state_double_lock(sock->sk, peer_sk); 675 | + if (UNIX_FS(sock->sk)) { 676 | + error = unix_fs_perm(op, request, label, unix_sk(sock->sk), 677 | + PATH_SOCK_COND); 678 | + } else if (UNIX_FS(peer_sk)) { 679 | + error = unix_fs_perm(op, request, label, unix_sk(peer_sk), 680 | + PATH_SOCK_COND); 681 | + } else { 682 | + struct aa_sk_ctx *pctx = SK_CTX(peer_sk); 683 | + if (sk_req) 684 | + error = aa_unix_label_sk_perm(label, op, sk_req, 685 | + sock->sk); 686 | + last_error(error, 687 | + xcheck(aa_unix_peer_perm(label, op, 688 | + MAY_READ | MAY_WRITE, 689 | + sock->sk, peer_sk, NULL), 690 | + aa_unix_peer_perm(pctx->label, op, 691 | + MAY_READ | MAY_WRITE, 692 | + peer_sk, sock->sk, label))); 693 | + } 694 | + 695 | + unix_state_double_unlock(sock->sk, peer_sk); 696 | + sock_put(peer_sk); 697 | + 698 | + return error; 699 | +} 700 | diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c 701 | index 0aef8e3..d581800 100644 702 | --- a/security/apparmor/apparmorfs.c 703 | +++ b/security/apparmor/apparmorfs.c 704 | @@ -2346,6 +2346,11 @@ static struct aa_sfs_entry aa_sfs_entry_ns[] = { 705 | { } 706 | }; 707 | 708 | +static struct aa_sfs_entry aa_sfs_entry_dbus[] = { 709 | + AA_SFS_FILE_STRING("mask", "acquire send receive"), 710 | + { } 711 | +}; 712 | + 713 | static struct aa_sfs_entry aa_sfs_entry_query_label[] = { 714 | AA_SFS_FILE_STRING("perms", "allow deny audit quiet"), 715 | AA_SFS_FILE_BOOLEAN("data", 1), 716 | @@ -2370,6 +2375,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { 717 | AA_SFS_DIR("caps", aa_sfs_entry_caps), 718 | AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), 719 | AA_SFS_DIR("signal", aa_sfs_entry_signal), 720 | + AA_SFS_DIR("dbus", aa_sfs_entry_dbus), 721 | AA_SFS_DIR("query", aa_sfs_entry_query), 722 | { } 723 | }; 724 | diff --git a/security/apparmor/file.c b/security/apparmor/file.c 725 | index e1b7e936..866272c 100644 726 | --- a/security/apparmor/file.c 727 | +++ b/security/apparmor/file.c 728 | @@ -14,6 +14,7 @@ 729 | #include 730 | #include 731 | 732 | +#include "include/af_unix.h" 733 | #include "include/apparmor.h" 734 | #include "include/audit.h" 735 | #include "include/cred.h" 736 | @@ -271,7 +272,8 @@ int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, 737 | { 738 | int e = 0; 739 | 740 | - if (profile_unconfined(profile)) 741 | + if (profile_unconfined(profile) || 742 | + ((flags & PATH_SOCK_COND) && !PROFILE_MEDIATES_AF(profile, AF_UNIX))) 743 | return 0; 744 | aa_str_perms(profile->file.dfa, profile->file.start, name, cond, perms); 745 | if (request & ~perms->allow) 746 | diff --git a/security/apparmor/include/af_unix.h b/security/apparmor/include/af_unix.h 747 | new file mode 100644 748 | index 0000000..d1b7f23 749 | --- /dev/null 750 | +++ b/security/apparmor/include/af_unix.h 751 | @@ -0,0 +1,114 @@ 752 | +/* 753 | + * AppArmor security module 754 | + * 755 | + * This file contains AppArmor af_unix fine grained mediation 756 | + * 757 | + * Copyright 2014 Canonical Ltd. 758 | + * 759 | + * This program is free software; you can redistribute it and/or 760 | + * modify it under the terms of the GNU General Public License as 761 | + * published by the Free Software Foundation, version 2 of the 762 | + * License. 763 | + */ 764 | +#ifndef __AA_AF_UNIX_H 765 | + 766 | +#include 767 | + 768 | +#include "label.h" 769 | +//#include "include/net.h" 770 | + 771 | +#define unix_addr_len(L) ((L) - sizeof(sa_family_t)) 772 | +#define unix_abstract_name_len(L) (unix_addr_len(L) - 1) 773 | +#define unix_abstract_len(U) (unix_abstract_name_len((U)->addr->len)) 774 | +#define addr_unix_abstract_name(B) ((B)[0] == 0) 775 | +#define addr_unix_anonymous(U) (addr_unix_len(U) <= 0) 776 | +#define addr_unix_abstract(U) (!addr_unix_anonymous(U) && addr_unix_abstract_name((U)->addr)) 777 | +//#define unix_addr_fs(U) (!unix_addr_anonymous(U) && !unix_addr_abstract_name((U)->addr)) 778 | + 779 | +#define unix_addr(A) ((struct sockaddr_un *)(A)) 780 | +#define unix_addr_anon(A, L) ((A) && unix_addr_len(L) <= 0) 781 | +#define unix_addr_fs(A, L) (!unix_addr_anon(A, L) && !addr_unix_abstract_name(unix_addr(A)->sun_path)) 782 | + 783 | +#define UNIX_ANONYMOUS(U) (!unix_sk(U)->addr) 784 | +/* from net/unix/af_unix.c */ 785 | +#define UNIX_ABSTRACT(U) (!UNIX_ANONYMOUS(U) && \ 786 | + unix_sk(U)->addr->hash < UNIX_HASH_SIZE) 787 | +#define UNIX_FS(U) (!UNIX_ANONYMOUS(U) && unix_sk(U)->addr->name->sun_path[0]) 788 | +#define unix_peer(sk) (unix_sk(sk)->peer) 789 | +#define unix_connected(S) ((S)->state == SS_CONNECTED) 790 | + 791 | +static inline void print_unix_addr(struct sockaddr_un *A, int L) 792 | +{ 793 | + char *buf = (A) ? (char *) &(A)->sun_path : NULL; 794 | + int len = unix_addr_len(L); 795 | + if (!buf || len <= 0) 796 | + printk(" "); 797 | + else if (buf[0]) 798 | + printk(" %s", buf); 799 | + else 800 | + /* abstract name len includes leading \0 */ 801 | + printk(" %d @%.*s", len - 1, len - 1, buf+1); 802 | +}; 803 | + 804 | +/* 805 | + printk("%s: %s: f %d, t %d, p %d", __FUNCTION__, \ 806 | + #SK , \ 807 | +*/ 808 | +#define print_unix_sk(SK) \ 809 | +do { \ 810 | + struct unix_sock *u = unix_sk(SK); \ 811 | + printk("%s: f %d, t %d, p %d", #SK , \ 812 | + (SK)->sk_family, (SK)->sk_type, (SK)->sk_protocol); \ 813 | + if (u->addr) \ 814 | + print_unix_addr(u->addr->name, u->addr->len); \ 815 | + else \ 816 | + print_unix_addr(NULL, sizeof(sa_family_t)); \ 817 | + /* printk("\n");*/ \ 818 | +} while (0) 819 | + 820 | +#define print_sk(SK) \ 821 | +do { \ 822 | + if (!(SK)) { \ 823 | + printk("%s: %s is null\n", __FUNCTION__, #SK); \ 824 | + } else if ((SK)->sk_family == PF_UNIX) { \ 825 | + print_unix_sk(SK); \ 826 | + printk("\n"); \ 827 | + } else { \ 828 | + printk("%s: %s: family %d\n", __FUNCTION__, #SK , \ 829 | + (SK)->sk_family); \ 830 | + } \ 831 | +} while (0) 832 | + 833 | +#define print_sock_addr(U) \ 834 | +do { \ 835 | + printk("%s:\n", __FUNCTION__); \ 836 | + printk(" sock %s:", sock_ctx && sock_ctx->label ? aa_label_printk(sock_ctx->label, GFP_ATOMIC); : ""); print_sk(sock); \ 837 | + printk(" other %s:", other_ctx && other_ctx->label ? aa_label_printk(other_ctx->label, GFP_ATOMIC); : ""); print_sk(other); \ 838 | + printk(" new %s", new_ctx && new_ctx->label ? aa_label_printk(new_ctx->label, GFP_ATOMIC); : ""); print_sk(newsk); \ 839 | +} while (0) 840 | + 841 | + 842 | + 843 | + 844 | +int aa_unix_peer_perm(struct aa_label *label, const char *op, u32 request, 845 | + struct sock *sk, struct sock *peer_sk, 846 | + struct aa_label *peer_label); 847 | +int aa_unix_label_sk_perm(struct aa_label *label, const char *op, u32 request, 848 | + struct sock *sk); 849 | +int aa_unix_sock_perm(const char *op, u32 request, struct socket *sock); 850 | +int aa_unix_create_perm(struct aa_label *label, int family, int type, 851 | + int protocol); 852 | +int aa_unix_bind_perm(struct socket *sock, struct sockaddr *address, 853 | + int addrlen); 854 | +int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address, 855 | + int addrlen); 856 | +int aa_unix_listen_perm(struct socket *sock, int backlog); 857 | +int aa_unix_accept_perm(struct socket *sock, struct socket *newsock); 858 | +int aa_unix_msg_perm(const char *op, u32 request, struct socket *sock, 859 | + struct msghdr *msg, int size); 860 | +int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock, int level, 861 | + int optname); 862 | +int aa_unix_file_perm(struct aa_label *label, const char *op, u32 request, 863 | + struct socket *sock); 864 | + 865 | +#endif /* __AA_AF_UNIX_H */ 866 | diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h 867 | index 98a42ef..b4044fa 100644 868 | --- a/security/apparmor/include/net.h 869 | +++ b/security/apparmor/include/net.h 870 | @@ -49,6 +49,7 @@ 871 | struct aa_sk_ctx { 872 | struct aa_label *label; 873 | struct aa_label *peer; 874 | + struct path path; 875 | }; 876 | 877 | #define SK_CTX(X) ((X)->sk_security) 878 | @@ -83,6 +84,9 @@ struct aa_net_compat { 879 | ({ \ 880 | int __e; \ 881 | switch ((FAMILY)) { \ 882 | + case AF_UNIX: \ 883 | + __e = aa_unix_ ## FN; \ 884 | + break; \ 885 | default: \ 886 | __e = DEF_FN; \ 887 | } \ 888 | diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h 889 | index 44a7945..44592cd 100644 890 | --- a/security/apparmor/include/path.h 891 | +++ b/security/apparmor/include/path.h 892 | @@ -13,6 +13,7 @@ 893 | 894 | enum path_flags { 895 | PATH_IS_DIR = 0x1, /* path is a directory */ 896 | + PATH_SOCK_COND = 0x2, 897 | PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */ 898 | PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */ 899 | PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */ 900 | diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h 901 | index f904105..f1c9cdc 100644 902 | --- a/security/apparmor/include/policy.h 903 | +++ b/security/apparmor/include/policy.h 904 | @@ -230,9 +230,13 @@ static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile, 905 | unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET); 906 | __be16 be_af = cpu_to_be16(AF); 907 | 908 | - if (!state) 909 | - return 0; 910 | - return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2); 911 | + if (!state) { 912 | + state = PROFILE_MEDIATES(profile, AA_CLASS_NET_COMPAT); 913 | + if (!state) 914 | + return 0; 915 | + } 916 | + state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2); 917 | + return state; 918 | } 919 | 920 | /** 921 | diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c 922 | index f72406f..59a8ddd 100644 923 | --- a/security/apparmor/lsm.c 924 | +++ b/security/apparmor/lsm.c 925 | @@ -25,6 +25,7 @@ 926 | #include 927 | #include 928 | 929 | +#include "include/af_unix.h" 930 | #include "include/apparmor.h" 931 | #include "include/apparmorfs.h" 932 | #include "include/audit.h" 933 | @@ -801,6 +802,7 @@ static void apparmor_sk_free_security(struct sock *sk) 934 | SK_CTX(sk) = NULL; 935 | aa_put_label(ctx->label); 936 | aa_put_label(ctx->peer); 937 | + path_put(&ctx->path); 938 | kfree(ctx); 939 | } 940 | 941 | @@ -820,6 +822,99 @@ static void apparmor_sk_clone_security(const struct sock *sk, 942 | if (new->peer) 943 | aa_put_label(new->peer); 944 | new->peer = aa_get_label(ctx->peer); 945 | + new->path = ctx->path; 946 | + path_get(&new->path); 947 | +} 948 | + 949 | +static struct path *UNIX_FS_CONN_PATH(struct sock *sk, struct sock *newsk) 950 | +{ 951 | + if (sk->sk_family == PF_UNIX && UNIX_FS(sk)) 952 | + return &unix_sk(sk)->path; 953 | + else if (newsk->sk_family == PF_UNIX && UNIX_FS(newsk)) 954 | + return &unix_sk(newsk)->path; 955 | + return NULL; 956 | +} 957 | + 958 | +/** 959 | + * apparmor_unix_stream_connect - check perms before making unix domain conn 960 | + * 961 | + * peer is locked when this hook is called 962 | + */ 963 | +static int apparmor_unix_stream_connect(struct sock *sk, struct sock *peer_sk, 964 | + struct sock *newsk) 965 | +{ 966 | + struct aa_sk_ctx *sk_ctx = SK_CTX(sk); 967 | + struct aa_sk_ctx *peer_ctx = SK_CTX(peer_sk); 968 | + struct aa_sk_ctx *new_ctx = SK_CTX(newsk); 969 | + struct aa_label *label; 970 | + struct path *path; 971 | + int error; 972 | + 973 | + label = __begin_current_label_crit_section(); 974 | + error = aa_unix_peer_perm(label, OP_CONNECT, 975 | + (AA_MAY_CONNECT | AA_MAY_SEND | AA_MAY_RECEIVE), 976 | + sk, peer_sk, NULL); 977 | + if (!UNIX_FS(peer_sk)) { 978 | + last_error(error, 979 | + aa_unix_peer_perm(peer_ctx->label, OP_CONNECT, 980 | + (AA_MAY_ACCEPT | AA_MAY_SEND | AA_MAY_RECEIVE), 981 | + peer_sk, sk, label)); 982 | + } 983 | + __end_current_label_crit_section(label); 984 | + 985 | + if (error) 986 | + return error; 987 | + 988 | + /* label newsk if it wasn't labeled in post_create. Normally this 989 | + * would be done in sock_graft, but because we are directly looking 990 | + * at the peer_sk to obtain peer_labeling for unix socks this 991 | + * does not work 992 | + */ 993 | + if (!new_ctx->label) 994 | + new_ctx->label = aa_get_label(peer_ctx->label); 995 | + 996 | + /* Cross reference the peer labels for SO_PEERSEC */ 997 | + if (new_ctx->peer) 998 | + aa_put_label(new_ctx->peer); 999 | + 1000 | + if (sk_ctx->peer) 1001 | + aa_put_label(sk_ctx->peer); 1002 | + 1003 | + new_ctx->peer = aa_get_label(sk_ctx->label); 1004 | + sk_ctx->peer = aa_get_label(peer_ctx->label); 1005 | + 1006 | + path = UNIX_FS_CONN_PATH(sk, peer_sk); 1007 | + if (path) { 1008 | + new_ctx->path = *path; 1009 | + sk_ctx->path = *path; 1010 | + path_get(path); 1011 | + path_get(path); 1012 | + } 1013 | + return 0; 1014 | +} 1015 | + 1016 | +/** 1017 | + * apparmor_unix_may_send - check perms before conn or sending unix dgrams 1018 | + * 1019 | + * other is locked when this hook is called 1020 | + * 1021 | + * dgram connect calls may_send, peer setup but path not copied????? 1022 | + */ 1023 | +static int apparmor_unix_may_send(struct socket *sock, struct socket *peer) 1024 | +{ 1025 | + struct aa_sk_ctx *peer_ctx = SK_CTX(peer->sk); 1026 | + struct aa_label *label; 1027 | + int error; 1028 | + 1029 | + label = __begin_current_label_crit_section(); 1030 | + error = xcheck(aa_unix_peer_perm(label, OP_SENDMSG, AA_MAY_SEND, 1031 | + sock->sk, peer->sk, NULL), 1032 | + aa_unix_peer_perm(peer_ctx->label, OP_SENDMSG, 1033 | + AA_MAY_RECEIVE, 1034 | + peer->sk, sock->sk, label)); 1035 | + __end_current_label_crit_section(label); 1036 | + 1037 | + return error; 1038 | } 1039 | 1040 | /** 1041 | @@ -1065,11 +1160,25 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 1042 | 1043 | static struct aa_label *sk_peer_label(struct sock *sk) 1044 | { 1045 | + struct sock *peer_sk; 1046 | struct aa_sk_ctx *ctx = SK_CTX(sk); 1047 | 1048 | if (ctx->peer) 1049 | return ctx->peer; 1050 | 1051 | + if (sk->sk_family != PF_UNIX) 1052 | + return ERR_PTR(-ENOPROTOOPT); 1053 | + 1054 | + /* check for sockpair peering which does not go through 1055 | + * security_unix_stream_connect 1056 | + */ 1057 | + peer_sk = unix_peer(sk); 1058 | + if (peer_sk) { 1059 | + ctx = SK_CTX(peer_sk); 1060 | + if (ctx->label) 1061 | + return ctx->label; 1062 | + } 1063 | + 1064 | return ERR_PTR(-ENOPROTOOPT); 1065 | } 1066 | 1067 | @@ -1216,6 +1325,9 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { 1068 | LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), 1069 | LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), 1070 | 1071 | + LSM_HOOK_INIT(unix_stream_connect, apparmor_unix_stream_connect), 1072 | + LSM_HOOK_INIT(unix_may_send, apparmor_unix_may_send), 1073 | + 1074 | LSM_HOOK_INIT(socket_create, apparmor_socket_create), 1075 | LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create), 1076 | LSM_HOOK_INIT(socket_bind, apparmor_socket_bind), 1077 | diff --git a/security/apparmor/net.c b/security/apparmor/net.c 1078 | index e693df8..e2e759b 100644 1079 | --- a/security/apparmor/net.c 1080 | +++ b/security/apparmor/net.c 1081 | @@ -8,6 +8,7 @@ 1082 | * Copyright 2009-2017 Canonical Ltd. 1083 | */ 1084 | 1085 | +#include "include/af_unix.h" 1086 | #include "include/apparmor.h" 1087 | #include "include/audit.h" 1088 | #include "include/cred.h" 1089 | @@ -26,6 +27,7 @@ struct aa_sfs_entry aa_sfs_entry_network[] = { 1090 | 1091 | struct aa_sfs_entry aa_sfs_entry_network_compat[] = { 1092 | AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK), 1093 | + AA_SFS_FILE_BOOLEAN("af_unix", 1), 1094 | { } 1095 | }; 1096 | 1097 | @@ -71,6 +73,36 @@ static const char * const net_mask_names[] = { 1098 | "unknown", 1099 | }; 1100 | 1101 | +static void audit_unix_addr(struct audit_buffer *ab, const char *str, 1102 | + struct sockaddr_un *addr, int addrlen) 1103 | +{ 1104 | + int len = unix_addr_len(addrlen); 1105 | + 1106 | + if (!addr || len <= 0) { 1107 | + audit_log_format(ab, " %s=none", str); 1108 | + } else if (addr->sun_path[0]) { 1109 | + audit_log_format(ab, " %s=", str); 1110 | + audit_log_untrustedstring(ab, addr->sun_path); 1111 | + } else { 1112 | + audit_log_format(ab, " %s=\"@", str); 1113 | + if (audit_string_contains_control(&addr->sun_path[1], len - 1)) 1114 | + audit_log_n_hex(ab, &addr->sun_path[1], len - 1); 1115 | + else 1116 | + audit_log_format(ab, "%.*s", len - 1, 1117 | + &addr->sun_path[1]); 1118 | + audit_log_format(ab, "\""); 1119 | + } 1120 | +} 1121 | + 1122 | +static void audit_unix_sk_addr(struct audit_buffer *ab, const char *str, 1123 | + struct sock *sk) 1124 | +{ 1125 | + struct unix_sock *u = unix_sk(sk); 1126 | + if (u && u->addr) 1127 | + audit_unix_addr(ab, str, u->addr->name, u->addr->len); 1128 | + else 1129 | + audit_unix_addr(ab, str, NULL, 0); 1130 | +} 1131 | 1132 | /* audit callback for net specific fields */ 1133 | void audit_net_cb(struct audit_buffer *ab, void *va) 1134 | @@ -102,6 +134,23 @@ void audit_net_cb(struct audit_buffer *ab, void *va) 1135 | net_mask_names, NET_PERMS_MASK); 1136 | } 1137 | } 1138 | + if (sa->u.net->family == AF_UNIX) { 1139 | + if ((aad(sa)->request & ~NET_PEER_MASK) && aad(sa)->net.addr) 1140 | + audit_unix_addr(ab, "addr", 1141 | + unix_addr(aad(sa)->net.addr), 1142 | + aad(sa)->net.addrlen); 1143 | + else 1144 | + audit_unix_sk_addr(ab, "addr", sa->u.net->sk); 1145 | + if (aad(sa)->request & NET_PEER_MASK) { 1146 | + if (aad(sa)->net.addr) 1147 | + audit_unix_addr(ab, "peer_addr", 1148 | + unix_addr(aad(sa)->net.addr), 1149 | + aad(sa)->net.addrlen); 1150 | + else 1151 | + audit_unix_sk_addr(ab, "peer_addr", 1152 | + aad(sa)->net.peer_sk); 1153 | + } 1154 | + } 1155 | if (aad(sa)->peer) { 1156 | audit_log_format(ab, " peer="); 1157 | aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 1158 | @@ -202,7 +251,9 @@ int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, 1159 | AA_BUG(!sock); 1160 | AA_BUG(!sock->sk); 1161 | 1162 | - return aa_label_sk_perm(label, op, request, sock->sk); 1163 | + return af_select(sock->sk->sk_family, 1164 | + file_perm(label, op, request, sock), 1165 | + aa_label_sk_perm(label, op, request, sock->sk)); 1166 | } 1167 | 1168 | #ifdef CONFIG_NETWORK_SECMARK 1169 | -------------------------------------------------------------------------------- /debian/patches/ubuntu/0003-apparmor-fix-apparmor-mediating-locking-non-fs-unix-sockets.patch: -------------------------------------------------------------------------------- 1 | From d7410054784d8aa0e313f9eeb6110a791420f3d3 Mon Sep 17 00:00:00 2001 2 | From: John Johansen 3 | Date: Mon, 30 Jul 2018 13:55:30 -0700 4 | Subject: UBUNTU SAUCE: apparmor: fix apparmor mediating locking non-fs, unix 5 | sockets 6 | 7 | The apparmor policy language current does not allow expressing of the 8 | locking permission for no-fs unix sockets. However the kernel is 9 | enforcing mediation. 10 | 11 | Add the AA_MAY_LOCK perm to the computed perm mask which will grant 12 | permission for all current abi profiles, but still allow specifying 13 | auditing of the operation if needed. 14 | 15 | BugLink: http://bugs.launchpad.net/bugs/1780227 16 | Signed-off-by: John Johansen 17 | Acked-by: Acked-by: Stefan Bader 18 | Acked-by: Acked-by: Kleber Sacilotto de Souza 19 | Signed-off-by: Seth Forshee 20 | --- 21 | security/apparmor/lib.c | 2 +- 22 | 1 file changed, 1 insertion(+), 1 deletion(-) 23 | 24 | (limited to 'security/apparmor') 25 | 26 | diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c 27 | index fa49b81..bf72843 100644 28 | --- a/security/apparmor/lib.c 29 | +++ b/security/apparmor/lib.c 30 | @@ -334,7 +334,7 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, 31 | /* for v5 perm mapping in the policydb, the other set is used 32 | * to extend the general perm set 33 | */ 34 | - perms->allow |= map_other(dfa_other_allow(dfa, state)); 35 | + perms->allow |= map_other(dfa_other_allow(dfa, state)) | AA_MAY_LOCK; 36 | perms->audit |= map_other(dfa_other_audit(dfa, state)); 37 | perms->quiet |= map_other(dfa_other_quiet(dfa, state)); 38 | // perms->xindex = dfa_user_xindex(dfa, state); 39 | -------------------------------------------------------------------------------- /debian/patches/ubuntu/0004-apparmor-fix-use-after-free-in-sk_peer_label.patch: -------------------------------------------------------------------------------- 1 | From e9243f6a285589f49161faf0f96f4cf15c1dafae Mon Sep 17 00:00:00 2001 2 | From: John Johansen 3 | Date: Tue, 26 Jun 2018 20:19:19 -0700 4 | Subject: UBUNTU: SAUCE: apparmor: fix use after free in sk_peer_label 5 | 6 | BugLink: http://bugs.launchpad.net/bugs/1778646 7 | Signed-off-by: John Johansen 8 | Signed-off-by: Seth Forshee 9 | --- 10 | security/apparmor/lsm.c | 11 +++++++---- 11 | 1 file changed, 7 insertions(+), 4 deletions(-) 12 | 13 | (limited to 'security/apparmor') 14 | 15 | diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c 16 | index 59a8ddd..b1216ee 100644 17 | --- a/security/apparmor/lsm.c 18 | +++ b/security/apparmor/lsm.c 19 | @@ -1162,9 +1162,10 @@ static struct aa_label *sk_peer_label(struct sock *sk) 20 | { 21 | struct sock *peer_sk; 22 | struct aa_sk_ctx *ctx = SK_CTX(sk); 23 | + struct aa_label *label = ERR_PTR(-ENOPROTOOPT); 24 | 25 | if (ctx->peer) 26 | - return ctx->peer; 27 | + return aa_get_label(ctx->peer); 28 | 29 | if (sk->sk_family != PF_UNIX) 30 | return ERR_PTR(-ENOPROTOOPT); 31 | @@ -1172,14 +1173,15 @@ static struct aa_label *sk_peer_label(struct sock *sk) 32 | /* check for sockpair peering which does not go through 33 | * security_unix_stream_connect 34 | */ 35 | - peer_sk = unix_peer(sk); 36 | + peer_sk = unix_peer_get(sk); 37 | if (peer_sk) { 38 | ctx = SK_CTX(peer_sk); 39 | if (ctx->label) 40 | - return ctx->label; 41 | + label = aa_get_label(ctx->label); 42 | + sock_put(peer_sk); 43 | } 44 | 45 | - return ERR_PTR(-ENOPROTOOPT); 46 | + return label; 47 | } 48 | 49 | /** 50 | @@ -1223,6 +1225,7 @@ out: 51 | 52 | } 53 | 54 | + aa_put_label(peer); 55 | done: 56 | end_current_label_crit_section(label); 57 | -------------------------------------------------------------------------------- /debian/patches/zfs/0001-Check-for-META-and-DCH-consistency-in-autoconf.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Debian ZFS on Linux maintainers 3 | 4 | Date: Wed, 30 Jan 2019 15:12:04 +0100 5 | Subject: [PATCH] Check-for-META-and-DCH-consistency-in-autoconf 6 | 7 | Signed-off-by: Thomas Lamprecht 8 | --- 9 | config/zfs-meta.m4 | 34 +++++++++++++++++++++++++++++----- 10 | 1 file changed, 29 insertions(+), 5 deletions(-) 11 | 12 | diff --git a/config/zfs-meta.m4 b/config/zfs-meta.m4 13 | index 20064a0fb..4d5f545ad 100644 14 | --- a/config/zfs-meta.m4 15 | +++ b/config/zfs-meta.m4 16 | @@ -1,9 +1,10 @@ 17 | dnl # 18 | dnl # DESCRIPTION: 19 | -dnl # Read meta data from the META file. When building from a git repository 20 | -dnl # the ZFS_META_RELEASE field will be overwritten if there is an annotated 21 | -dnl # tag matching the form ZFS_META_NAME-ZFS_META_VERSION-*. This allows 22 | -dnl # for working builds to be uniquely identified using the git commit hash. 23 | +dnl # Read meta data from the META file or the debian/changelog file if it 24 | +dnl # exists. When building from a git repository the ZFS_META_RELEASE field 25 | +dnl # will be overwritten if there is an annotated tag matching the form 26 | +dnl # ZFS_META_NAME-ZFS_META_VERSION-*. This allows for working builds to be 27 | +dnl # uniquely identified using the git commit hash. 28 | dnl # 29 | dnl # The META file format is as follows: 30 | dnl # ^[ ]*KEY:[ \t]+VALUE$ 31 | @@ -49,6 +50,7 @@ AC_DEFUN([ZFS_AC_META], [ 32 | _zfs_ac_meta_type="none" 33 | if test -f "$META"; then 34 | _zfs_ac_meta_type="META file" 35 | + _dpkg_parsechangelog=$(dpkg-parsechangelog 2>/dev/null) 36 | 37 | ZFS_META_NAME=_ZFS_AC_META_GETVAL([(Name|Project|Package)]); 38 | if test -n "$ZFS_META_NAME"; then 39 | @@ -69,8 +71,30 @@ AC_DEFUN([ZFS_AC_META], [ 40 | AC_SUBST([ZFS_META_VERSION]) 41 | fi 42 | 43 | + if test -n "${_dpkg_parsechangelog}"; then 44 | + _dpkg_version=$(echo "${_dpkg_parsechangelog}" \ 45 | + | $AWK '$[]1 == "Version:" { print $[]2; }' \ 46 | + | cut -d- -f1) 47 | + if test "${_dpkg_version}" != "$ZFS_META_VERSION"; then 48 | + AC_MSG_ERROR([ 49 | + *** Version $ZFS_META_VERSION in the META file is different than 50 | + *** version $_dpkg_version in the debian/changelog file. DKMS and DEB 51 | + *** packaging require that these files have the same version. 52 | + ]) 53 | + fi 54 | + fi 55 | + 56 | ZFS_META_RELEASE=_ZFS_AC_META_GETVAL([Release]); 57 | - if test ! -f ".nogitrelease" && git rev-parse --git-dir > /dev/null 2>&1; then 58 | + 59 | + if test -n "${_dpkg_parsechangelog}"; then 60 | + _dpkg_release=$(echo "${_dpkg_parsechangelog}" \ 61 | + | $AWK '$[]1 == "Version:" { print $[]2; }' \ 62 | + | cut -d- -f2-) 63 | + if test -n "${_dpkg_release}"; then 64 | + ZFS_META_RELEASE=${_dpkg_release} 65 | + _zfs_ac_meta_type="dpkg-parsechangelog" 66 | + fi 67 | + elif test ! -f ".nogitrelease" && git rev-parse --git-dir > /dev/null 2>&1; then 68 | _match="${ZFS_META_NAME}-${ZFS_META_VERSION}" 69 | _alias=$(git describe --match=${_match} 2>/dev/null) 70 | _release=$(echo ${_alias}|sed "s/${ZFS_META_NAME}//"|cut -f3- -d'-'|tr - _) -------------------------------------------------------------------------------- /debian/patches/zfs/0002-always-load-ZFS-module-on-boot.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= 3 | Date: Fri, 19 Jan 2018 12:13:46 +0100 4 | Subject: [PATCH] always load ZFS module on boot 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=UTF-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | since zfs-import-scan.service is disabled by default, and 10 | zfs-import-cache.service only gets started if a cache file exists, this 11 | is needed for zfs-mount, zfs-share and zfs-zed services in case ZFS is 12 | not actually used. 13 | 14 | Signed-off-by: Fabian Grünbichler 15 | Signed-off-by: Stoiko Ivanov 16 | Signed-off-by: Thomas Lamprecht 17 | --- 18 | etc/modules-load.d/zfs.conf | 2 +- 19 | 1 file changed, 1 insertion(+), 1 deletion(-) 20 | 21 | diff --git a/etc/modules-load.d/zfs.conf b/etc/modules-load.d/zfs.conf 22 | index 44e1bb3ed..7509b03cb 100644 23 | --- a/etc/modules-load.d/zfs.conf 24 | +++ b/etc/modules-load.d/zfs.conf 25 | @@ -1,3 +1,3 @@ 26 | # The default behavior is to allow udev to load the kernel modules on demand. 27 | # Uncomment the following line to unconditionally load them at boot. 28 | -#zfs 29 | +zfs 30 | -------------------------------------------------------------------------------- /debian/patches/zfs/0003-Fix-the-path-to-the-zed-binary-on-the-systemd-unit.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= 3 | Date: Mon, 6 Feb 2017 12:04:35 +0100 4 | Subject: [PATCH] Fix the path to the zed binary on the systemd unit. 5 | 6 | We install zed into /usr/sbin manually meanwhile the upstream default is 7 | installing it into /sbin. Ubuntu packages also install zed to /usr/sbin, but 8 | they ship their own zfs-zed unit. 9 | 10 | Signed-off-by: Thomas Lamprecht 11 | --- 12 | etc/systemd/system/zfs-zed.service.in | 2 +- 13 | 1 file changed, 1 insertion(+), 1 deletion(-) 14 | 15 | diff --git a/etc/systemd/system/zfs-zed.service.in b/etc/systemd/system/zfs-zed.service.in 16 | index 008075138..570e27707 100644 17 | --- a/etc/systemd/system/zfs-zed.service.in 18 | +++ b/etc/systemd/system/zfs-zed.service.in 19 | @@ -4,7 +4,7 @@ Documentation=man:zed(8) 20 | ConditionPathIsDirectory=/sys/module/zfs 21 | 22 | [Service] 23 | -ExecStart=@sbindir@/zed -F 24 | +ExecStart=/usr/sbin/zed -F 25 | Restart=on-abort 26 | 27 | [Install] 28 | -------------------------------------------------------------------------------- /debian/patches/zfs/0004-import-with-d-dev-disk-by-id-in-scan-service.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= 3 | Date: Mon, 24 Oct 2016 13:47:06 +0200 4 | Subject: [PATCH] import with -d /dev/disk/by-id in scan service 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=UTF-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | Signed-off-by: Fabian Grünbichler 10 | Signed-off-by: Stoiko Ivanov 11 | Signed-off-by: Thomas Lamprecht 12 | --- 13 | etc/systemd/system/zfs-import-scan.service.in | 2 +- 14 | 1 file changed, 1 insertion(+), 1 deletion(-) 15 | 16 | diff --git a/etc/systemd/system/zfs-import-scan.service.in b/etc/systemd/system/zfs-import-scan.service.in 17 | index c1111c73a..c5e12c2c6 100644 18 | --- a/etc/systemd/system/zfs-import-scan.service.in 19 | +++ b/etc/systemd/system/zfs-import-scan.service.in 20 | @@ -13,7 +13,7 @@ ConditionPathIsDirectory=/sys/module/zfs 21 | [Service] 22 | Type=oneshot 23 | RemainAfterExit=yes 24 | -ExecStart=@sbindir@/zpool import -aN -o cachefile=none $ZPOOL_IMPORT_OPTS 25 | +ExecStart=@sbindir@/zpool import -aN -d /dev/disk/by-id -o cachefile=none $ZPOOL_IMPORT_OPTS 26 | 27 | [Install] 28 | WantedBy=zfs-import.target 29 | -------------------------------------------------------------------------------- /debian/patches/zfs/0005-Enable-zed-emails.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Richard Laager 3 | Date: Wed, 30 Jan 2019 15:12:04 +0100 4 | Subject: [PATCH] Enable zed emails 5 | 6 | The OpenZFS event daemon monitors pools. This patch enables the email sending 7 | function by default (if zed is installed). This is consistent with the default 8 | behavior of mdadm. 9 | 10 | Signed-off-by: Thomas Lamprecht 11 | --- 12 | cmd/zed/zed.d/zed.rc | 2 +- 13 | 1 file changed, 1 insertion(+), 1 deletion(-) 14 | 15 | diff --git a/cmd/zed/zed.d/zed.rc b/cmd/zed/zed.d/zed.rc 16 | index 9ac77f929..672617f54 100644 17 | --- a/cmd/zed/zed.d/zed.rc 18 | +++ b/cmd/zed/zed.d/zed.rc 19 | @@ -41,7 +41,7 @@ ZED_EMAIL_ADDR="root" 20 | ## 21 | # Minimum number of seconds between notifications for a similar event. 22 | # 23 | -#ZED_NOTIFY_INTERVAL_SECS=3600 24 | +ZED_NOTIFY_INTERVAL_SECS=3600 25 | 26 | ## 27 | # Notification verbosity. -------------------------------------------------------------------------------- /debian/patches/zfs/0006-dont-symlink-zed-scripts.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Antonio Russo 3 | Date: Fri, 20 Mar 2020 17:28:43 +0100 4 | Subject: [PATCH] dont symlink zed scripts 5 | 6 | (cherry picked and adapted from 5cee380324d74e640d5dd7a360faba3994c8007f [0]) 7 | 8 | [0] https://salsa.debian.org/zfsonlinux-team/zfs.git 9 | 10 | Signed-off-by: Stoiko Ivanov 11 | 12 | Description: track default symlinks, instead of symlinking 13 | Forwarded: no need 14 | --- 15 | cmd/zed/zed.d/Makefile.am | 2 +- 16 | 1 file changed, 1 insertion(+), 1 deletion(-) 17 | 18 | diff --git a/cmd/zed/zed.d/Makefile.am b/cmd/zed/zed.d/Makefile.am 19 | index 8b2d0c200..118c96547 100644 20 | --- a/cmd/zed/zed.d/Makefile.am 21 | +++ b/cmd/zed/zed.d/Makefile.am 22 | @@ -48,6 +48,6 @@ install-data-hook: 23 | for f in $(zedconfdefaults); do \ 24 | test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \ 25 | -L "$(DESTDIR)$(zedconfdir)/$${f}" || \ 26 | - ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \ 27 | + echo "$${f}" >> "$(DESTDIR)$(zedexecdir)/DEFAULT-ENABLED" ; \ 28 | done 29 | chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc" 30 | -------------------------------------------------------------------------------- /debian/patches/zfs/0007-Use-installed-python3.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Antonio Russo 3 | Date: Tue, 5 May 2020 22:15:16 -0600 4 | Subject: [PATCH] Use installed python3 5 | 6 | --- 7 | .../functional/cli_root/zfs_program/zfs_program_json.ksh | 6 +++--- 8 | .../tests/functional/rsend/send_encrypted_files.ksh | 2 +- 9 | .../tests/functional/rsend/send_realloc_dnode_size.ksh | 2 +- 10 | 3 files changed, 5 insertions(+), 5 deletions(-) 11 | 12 | diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh 13 | index 3788543b0..c7ee4ae9a 100755 14 | --- a/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh 15 | +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh 16 | @@ -100,10 +100,10 @@ typeset -a pos_cmds_out=( 17 | # the same as the input and the --sort-keys option was added. Detect when 18 | # --sort-keys is supported and apply the option to ensure the expected order. 19 | # 20 | -if python -m json.tool --sort-keys <<< "{}"; then 21 | - JSON_TOOL_CMD="python -m json.tool --sort-keys" 22 | +if python3 -m json.tool --sort-keys <<< "{}"; then 23 | + JSON_TOOL_CMD="python3 -m json.tool --sort-keys" 24 | else 25 | - JSON_TOOL_CMD="python -m json.tool" 26 | + JSON_TOOL_CMD="python3 -m json.tool" 27 | fi 28 | 29 | typeset -i cnt=0 30 | diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_files.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_files.ksh 31 | index f89cb3b31..375d483f7 100755 32 | --- a/tests/zfs-tests/tests/functional/rsend/send_encrypted_files.ksh 33 | +++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_files.ksh 34 | @@ -87,7 +87,7 @@ log_must xattrtest -f 10 -x 3 -s 32768 -r -k -p /$TESTPOOL/$TESTFS2/xattrsadir 35 | # ZoL issue #7432 36 | log_must zfs set compression=on xattr=sa $TESTPOOL/$TESTFS2 37 | log_must touch /$TESTPOOL/$TESTFS2/attrs 38 | -log_must eval "python -c 'print \"a\" * 4096' | \ 39 | +log_must eval "python3 -c 'print \"a\" * 4096' | \ 40 | set_xattr_stdin bigval /$TESTPOOL/$TESTFS2/attrs" 41 | log_must zfs set compression=off xattr=on $TESTPOOL/$TESTFS2 42 | 43 | diff --git a/tests/zfs-tests/tests/functional/rsend/send_realloc_dnode_size.ksh b/tests/zfs-tests/tests/functional/rsend/send_realloc_dnode_size.ksh 44 | index 394fe95bb..43560aac5 100755 45 | --- a/tests/zfs-tests/tests/functional/rsend/send_realloc_dnode_size.ksh 46 | +++ b/tests/zfs-tests/tests/functional/rsend/send_realloc_dnode_size.ksh 47 | @@ -93,7 +93,7 @@ log_must zfs snapshot $POOL/fs@c 48 | # 4. Create an empty file and add xattrs to it to exercise reclaiming a 49 | # dnode that requires more than 1 slot for its bonus buffer (Zol #7433) 50 | log_must zfs set compression=on xattr=sa $POOL/fs 51 | -log_must eval "python -c 'print \"a\" * 512' | 52 | +log_must eval "python3 -c 'print \"a\" * 512' | 53 | set_xattr_stdin bigval /$POOL/fs/attrs" 54 | log_must zfs snapshot $POOL/fs@d 55 | 56 | -------------------------------------------------------------------------------- /debian/patches/zfs/0008-Add-systemd-unit-for-importing-specific-pools.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Stoiko Ivanov 3 | Date: Tue, 15 Sep 2020 19:07:24 +0200 4 | Subject: [PATCH] Add systemd-unit for importing specific pools 5 | 6 | The unit can be instantiated with a specific poolname, which will get imported 7 | by scanning /dev/disk/by-id, irrespective of the existence and content of 8 | /etc/zfs/zpool.cache. 9 | 10 | the instance name is used unescaped (see systemd.unit(5)), since zpool names 11 | can contain characters which will be escaped by systemd. 12 | 13 | Signed-off-by: Stoiko Ivanov 14 | --- 15 | etc/systemd/system/50-zfs.preset.in | 1 + 16 | etc/systemd/system/Makefile.am | 1 + 17 | etc/systemd/system/zfs-import@.service.in | 16 ++++++++++++++++ 18 | 3 files changed, 18 insertions(+) 19 | create mode 100644 etc/systemd/system/zfs-import@.service.in 20 | 21 | diff --git a/etc/systemd/system/50-zfs.preset.in b/etc/systemd/system/50-zfs.preset.in 22 | index e4056a92c..030611419 100644 23 | --- a/etc/systemd/system/50-zfs.preset.in 24 | +++ b/etc/systemd/system/50-zfs.preset.in 25 | @@ -1,6 +1,7 @@ 26 | # ZFS is enabled by default 27 | enable zfs-import-cache.service 28 | disable zfs-import-scan.service 29 | +enable zfs-import@.service 30 | enable zfs-import.target 31 | enable zfs-mount.service 32 | enable zfs-share.service 33 | diff --git a/etc/systemd/system/Makefile.am b/etc/systemd/system/Makefile.am 34 | index 5e65e1db4..8e6baeb68 100644 35 | --- a/etc/systemd/system/Makefile.am 36 | +++ b/etc/systemd/system/Makefile.am 37 | @@ -7,6 +7,7 @@ systemdunit_DATA = \ 38 | zfs-zed.service \ 39 | zfs-import-cache.service \ 40 | zfs-import-scan.service \ 41 | + zfs-import@.service \ 42 | zfs-mount.service \ 43 | zfs-share.service \ 44 | zfs-volume-wait.service \ 45 | diff --git a/etc/systemd/system/zfs-import@.service.in b/etc/systemd/system/zfs-import@.service.in 46 | new file mode 100644 47 | index 000000000..9b4ee9371 48 | --- /dev/null 49 | +++ b/etc/systemd/system/zfs-import@.service.in 50 | @@ -0,0 +1,16 @@ 51 | +[Unit] 52 | +Description=Import ZFS pool %i 53 | +Documentation=man:zpool(8) 54 | +DefaultDependencies=no 55 | +After=systemd-udev-settle.service 56 | +After=cryptsetup.target 57 | +After=multipathd.target 58 | +Before=zfs-import.target 59 | + 60 | +[Service] 61 | +Type=oneshot 62 | +RemainAfterExit=yes 63 | +ExecStart=@sbindir@/zpool import -N -d /dev/disk/by-id -o cachefile=none %I 64 | + 65 | +[Install] 66 | +WantedBy=zfs-import.target 67 | -------------------------------------------------------------------------------- /debian/patches/zfs/0009-Patch-move-manpage-arcstat-1-to-arcstat-8.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Stoiko Ivanov 3 | Date: Thu, 4 Feb 2021 19:01:12 +0100 4 | Subject: [PATCH] Patch: move manpage arcstat(1) to arcstat(8). 5 | 6 | Originally-By: Mo Zhou 7 | Originally-By: Antonio Russo 8 | 9 | Signed-off-by: Stoiko Ivanov 10 | --- 11 | diff --git a/man/Makefile.am b/man/Makefile.am 12 | index 8ab1b7572..5485076f9 100644 13 | --- a/man/Makefile.am 14 | +++ b/man/Makefile.am 15 | @@ -8,7 +8,7 @@ dist_man_MANS = \ 16 | man1/ztest.1 \ 17 | man1/raidz_test.1 \ 18 | man1/zvol_wait.1 \ 19 | - man1/arcstat.1 \ 20 | + man8/arcstat.8 \ 21 | \ 22 | man5/vdev_id.conf.5 \ 23 | \ 24 | diff --git a/man/man1/arcstat.1 b/man/man1/arcstat.1 25 | index a69cd8937..dfe9c971b 100644 26 | --- a/man/man1/arcstat.1 27 | +++ b/man/man1/arcstat.1 28 | @@ -13,7 +13,7 @@ 29 | .\" Copyright (c) 2020 by AJ Jordan. All rights reserved. 30 | .\" 31 | .Dd May 26, 2021 32 | -.Dt ARCSTAT 1 33 | +.Dt ARCSTAT 8 34 | .Os 35 | . 36 | .Sh NAME 37 | -------------------------------------------------------------------------------- /debian/patches/zfs/0010-arcstat-Fix-integer-division-with-python3.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Valmiky Arquissandas 3 | Date: Fri, 8 Oct 2021 16:32:27 +0100 4 | Subject: [PATCH] arcstat: Fix integer division with python3 5 | 6 | The arcstat script requests compatibility with python2 and python3, but 7 | PEP 238 modified the / operator and results in erroneous output when 8 | run under python3. 9 | 10 | This commit replaces instances of / with //, yielding the expected 11 | result in both versions of Python. 12 | 13 | Reviewed-by: Brian Behlendorf 14 | Reviewed-by: John Kennedy 15 | Reviewed-by: Ryan Moeller 16 | Signed-off-by: Valmiky Arquissandas 17 | Closes #12603 18 | (cherry picked from commit 2d02bba23d83ae8fede8d281edc255f01ccd28e9) 19 | Signed-off-by: Thomas Lamprecht 20 | --- 21 | cmd/arcstat/arcstat.in | 66 +++++++++++++++++++++--------------------- 22 | 1 file changed, 33 insertions(+), 33 deletions(-) 23 | 24 | diff --git a/cmd/arcstat/arcstat.in b/cmd/arcstat/arcstat.in 25 | index 9e7c52a6c..cd9a803a2 100755 26 | --- a/cmd/arcstat/arcstat.in 27 | +++ b/cmd/arcstat/arcstat.in 28 | @@ -441,73 +441,73 @@ def calculate(): 29 | 30 | v = dict() 31 | v["time"] = time.strftime("%H:%M:%S", time.localtime()) 32 | - v["hits"] = d["hits"] / sint 33 | - v["miss"] = d["misses"] / sint 34 | + v["hits"] = d["hits"] // sint 35 | + v["miss"] = d["misses"] // sint 36 | v["read"] = v["hits"] + v["miss"] 37 | - v["hit%"] = 100 * v["hits"] / v["read"] if v["read"] > 0 else 0 38 | + v["hit%"] = 100 * v["hits"] // v["read"] if v["read"] > 0 else 0 39 | v["miss%"] = 100 - v["hit%"] if v["read"] > 0 else 0 40 | 41 | - v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) / sint 42 | - v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) / sint 43 | + v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) // sint 44 | + v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) // sint 45 | 46 | v["dread"] = v["dhit"] + v["dmis"] 47 | - v["dh%"] = 100 * v["dhit"] / v["dread"] if v["dread"] > 0 else 0 48 | + v["dh%"] = 100 * v["dhit"] // v["dread"] if v["dread"] > 0 else 0 49 | v["dm%"] = 100 - v["dh%"] if v["dread"] > 0 else 0 50 | 51 | - v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) / sint 52 | + v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) // sint 53 | v["pmis"] = (d["prefetch_data_misses"] + 54 | - d["prefetch_metadata_misses"]) / sint 55 | + d["prefetch_metadata_misses"]) // sint 56 | 57 | v["pread"] = v["phit"] + v["pmis"] 58 | - v["ph%"] = 100 * v["phit"] / v["pread"] if v["pread"] > 0 else 0 59 | + v["ph%"] = 100 * v["phit"] // v["pread"] if v["pread"] > 0 else 0 60 | v["pm%"] = 100 - v["ph%"] if v["pread"] > 0 else 0 61 | 62 | v["mhit"] = (d["prefetch_metadata_hits"] + 63 | - d["demand_metadata_hits"]) / sint 64 | + d["demand_metadata_hits"]) // sint 65 | v["mmis"] = (d["prefetch_metadata_misses"] + 66 | - d["demand_metadata_misses"]) / sint 67 | + d["demand_metadata_misses"]) // sint 68 | 69 | v["mread"] = v["mhit"] + v["mmis"] 70 | - v["mh%"] = 100 * v["mhit"] / v["mread"] if v["mread"] > 0 else 0 71 | + v["mh%"] = 100 * v["mhit"] // v["mread"] if v["mread"] > 0 else 0 72 | v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0 73 | 74 | v["arcsz"] = cur["size"] 75 | v["size"] = cur["size"] 76 | v["c"] = cur["c"] 77 | - v["mfu"] = d["mfu_hits"] / sint 78 | - v["mru"] = d["mru_hits"] / sint 79 | - v["mrug"] = d["mru_ghost_hits"] / sint 80 | - v["mfug"] = d["mfu_ghost_hits"] / sint 81 | - v["eskip"] = d["evict_skip"] / sint 82 | - v["el2skip"] = d["evict_l2_skip"] / sint 83 | - v["el2cach"] = d["evict_l2_cached"] / sint 84 | - v["el2el"] = d["evict_l2_eligible"] / sint 85 | - v["el2mfu"] = d["evict_l2_eligible_mfu"] / sint 86 | - v["el2mru"] = d["evict_l2_eligible_mru"] / sint 87 | - v["el2inel"] = d["evict_l2_ineligible"] / sint 88 | - v["mtxmis"] = d["mutex_miss"] / sint 89 | + v["mfu"] = d["mfu_hits"] // sint 90 | + v["mru"] = d["mru_hits"] // sint 91 | + v["mrug"] = d["mru_ghost_hits"] // sint 92 | + v["mfug"] = d["mfu_ghost_hits"] // sint 93 | + v["eskip"] = d["evict_skip"] // sint 94 | + v["el2skip"] = d["evict_l2_skip"] // sint 95 | + v["el2cach"] = d["evict_l2_cached"] // sint 96 | + v["el2el"] = d["evict_l2_eligible"] // sint 97 | + v["el2mfu"] = d["evict_l2_eligible_mfu"] // sint 98 | + v["el2mru"] = d["evict_l2_eligible_mru"] // sint 99 | + v["el2inel"] = d["evict_l2_ineligible"] // sint 100 | + v["mtxmis"] = d["mutex_miss"] // sint 101 | 102 | if l2exist: 103 | - v["l2hits"] = d["l2_hits"] / sint 104 | - v["l2miss"] = d["l2_misses"] / sint 105 | + v["l2hits"] = d["l2_hits"] // sint 106 | + v["l2miss"] = d["l2_misses"] // sint 107 | v["l2read"] = v["l2hits"] + v["l2miss"] 108 | - v["l2hit%"] = 100 * v["l2hits"] / v["l2read"] if v["l2read"] > 0 else 0 109 | + v["l2hit%"] = 100 * v["l2hits"] // v["l2read"] if v["l2read"] > 0 else 0 110 | 111 | v["l2miss%"] = 100 - v["l2hit%"] if v["l2read"] > 0 else 0 112 | v["l2asize"] = cur["l2_asize"] 113 | v["l2size"] = cur["l2_size"] 114 | - v["l2bytes"] = d["l2_read_bytes"] / sint 115 | + v["l2bytes"] = d["l2_read_bytes"] // sint 116 | 117 | v["l2pref"] = cur["l2_prefetch_asize"] 118 | v["l2mfu"] = cur["l2_mfu_asize"] 119 | v["l2mru"] = cur["l2_mru_asize"] 120 | v["l2data"] = cur["l2_bufc_data_asize"] 121 | v["l2meta"] = cur["l2_bufc_metadata_asize"] 122 | - v["l2pref%"] = 100 * v["l2pref"] / v["l2asize"] 123 | - v["l2mfu%"] = 100 * v["l2mfu"] / v["l2asize"] 124 | - v["l2mru%"] = 100 * v["l2mru"] / v["l2asize"] 125 | - v["l2data%"] = 100 * v["l2data"] / v["l2asize"] 126 | - v["l2meta%"] = 100 * v["l2meta"] / v["l2asize"] 127 | + v["l2pref%"] = 100 * v["l2pref"] // v["l2asize"] 128 | + v["l2mfu%"] = 100 * v["l2mfu"] // v["l2asize"] 129 | + v["l2mru%"] = 100 * v["l2mru"] // v["l2asize"] 130 | + v["l2data%"] = 100 * v["l2data"] // v["l2asize"] 131 | + v["l2meta%"] = 100 * v["l2meta"] // v["l2asize"] 132 | 133 | v["grow"] = 0 if cur["arc_no_grow"] else 1 134 | v["need"] = cur["arc_need_free"] 135 | -------------------------------------------------------------------------------- /debian/patches/zfs/0011-arc-stat-summary-guard-access-to-l2arc-MFU-MRU-stats.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Thomas Lamprecht 3 | Date: Wed, 10 Nov 2021 09:29:47 +0100 4 | Subject: [PATCH] arc stat/summary: guard access to l2arc MFU/MRU stats 5 | 6 | commit 085321621e79a75bea41c2b6511da6ebfbf2ba0a added printing MFU 7 | and MRU stats for 2.1 user space tools, but those keys are not 8 | available in the 2.0 module. That means it may break the arcstat and 9 | arc_summary tools after upgrade to 2.1 (user space), before a reboot 10 | to the new 2.1 ZFS kernel-module happened, due to python raising a 11 | KeyError on the dict access then. 12 | 13 | Move those two keys to a .get accessor with `0` as fallback, as it 14 | should be better to show some possible wrong data for new stat-keys 15 | than throwing an exception. 16 | 17 | Signed-off-by: Thomas Lamprecht 18 | 19 | also move l2_mfu_asize l2_mru_asize l2_prefetch_asize 20 | l2_bufc_data_asize l2_bufc_metadata_asize to .get accessor 21 | (these are only present with a cache device in the pool) 22 | Signed-off-by: Stoiko Ivanov 23 | --- 24 | cmd/arc_summary/arc_summary3 | 28 ++++++++++++++-------------- 25 | cmd/arcstat/arcstat.in | 14 +++++++------- 26 | 2 files changed, 21 insertions(+), 21 deletions(-) 27 | 28 | diff --git a/cmd/arc_summary/arc_summary3 b/cmd/arc_summary/arc_summary3 29 | index 7b28012ed..fe6a6d9e2 100755 30 | --- a/cmd/arc_summary/arc_summary3 31 | +++ b/cmd/arc_summary/arc_summary3 32 | @@ -617,13 +617,13 @@ def section_arc(kstats_dict): 33 | prt_i1('L2 cached evictions:', f_bytes(arc_stats['evict_l2_cached'])) 34 | prt_i1('L2 eligible evictions:', f_bytes(arc_stats['evict_l2_eligible'])) 35 | prt_i2('L2 eligible MFU evictions:', 36 | - f_perc(arc_stats['evict_l2_eligible_mfu'], 37 | + f_perc(arc_stats.get('evict_l2_eligible_mfu', 0), # 2.0 module compat 38 | arc_stats['evict_l2_eligible']), 39 | - f_bytes(arc_stats['evict_l2_eligible_mfu'])) 40 | + f_bytes(arc_stats.get('evict_l2_eligible_mfu', 0))) 41 | prt_i2('L2 eligible MRU evictions:', 42 | - f_perc(arc_stats['evict_l2_eligible_mru'], 43 | + f_perc(arc_stats.get('evict_l2_eligible_mru', 0), # 2.0 module compat 44 | arc_stats['evict_l2_eligible']), 45 | - f_bytes(arc_stats['evict_l2_eligible_mru'])) 46 | + f_bytes(arc_stats.get('evict_l2_eligible_mru', 0))) 47 | prt_i1('L2 ineligible evictions:', 48 | f_bytes(arc_stats['evict_l2_ineligible'])) 49 | print() 50 | @@ -765,20 +765,20 @@ def section_l2arc(kstats_dict): 51 | f_perc(arc_stats['l2_hdr_size'], arc_stats['l2_size']), 52 | f_bytes(arc_stats['l2_hdr_size'])) 53 | prt_i2('MFU allocated size:', 54 | - f_perc(arc_stats['l2_mfu_asize'], arc_stats['l2_asize']), 55 | - f_bytes(arc_stats['l2_mfu_asize'])) 56 | + f_perc(arc_stats.get('l2_mfu_asize', 0), arc_stats['l2_asize']), 57 | + f_bytes(arc_stats.get('l2_mfu_asize', 0))) # 2.0 module compat 58 | prt_i2('MRU allocated size:', 59 | - f_perc(arc_stats['l2_mru_asize'], arc_stats['l2_asize']), 60 | - f_bytes(arc_stats['l2_mru_asize'])) 61 | + f_perc(arc_stats.get('l2_mru_asize', 0), arc_stats['l2_asize']), 62 | + f_bytes(arc_stats.get('l2_mru_asize', 0))) # 2.0 module compat 63 | prt_i2('Prefetch allocated size:', 64 | - f_perc(arc_stats['l2_prefetch_asize'], arc_stats['l2_asize']), 65 | - f_bytes(arc_stats['l2_prefetch_asize'])) 66 | + f_perc(arc_stats.get('l2_prefetch_asize', 0), arc_stats['l2_asize']), 67 | + f_bytes(arc_stats.get('l2_prefetch_asize',0))) # 2.0 module compat 68 | prt_i2('Data (buffer content) allocated size:', 69 | - f_perc(arc_stats['l2_bufc_data_asize'], arc_stats['l2_asize']), 70 | - f_bytes(arc_stats['l2_bufc_data_asize'])) 71 | + f_perc(arc_stats.get('l2_bufc_data_asize', 0), arc_stats['l2_asize']), 72 | + f_bytes(arc_stats.get('l2_bufc_data_asize', 0))) # 2.0 module compat 73 | prt_i2('Metadata (buffer content) allocated size:', 74 | - f_perc(arc_stats['l2_bufc_metadata_asize'], arc_stats['l2_asize']), 75 | - f_bytes(arc_stats['l2_bufc_metadata_asize'])) 76 | + f_perc(arc_stats.get('l2_bufc_metadata_asize', 0), arc_stats['l2_asize']), 77 | + f_bytes(arc_stats.get('l2_bufc_metadata_asize', 0))) # 2.0 module compat 78 | 79 | print() 80 | prt_1('L2ARC breakdown:', f_hits(l2_access_total)) 81 | diff --git a/cmd/arcstat/arcstat.in b/cmd/arcstat/arcstat.in 82 | index cd9a803a2..ea45dc602 100755 83 | --- a/cmd/arcstat/arcstat.in 84 | +++ b/cmd/arcstat/arcstat.in 85 | @@ -482,8 +482,8 @@ def calculate(): 86 | v["el2skip"] = d["evict_l2_skip"] // sint 87 | v["el2cach"] = d["evict_l2_cached"] // sint 88 | v["el2el"] = d["evict_l2_eligible"] // sint 89 | - v["el2mfu"] = d["evict_l2_eligible_mfu"] // sint 90 | - v["el2mru"] = d["evict_l2_eligible_mru"] // sint 91 | + v["el2mfu"] = d.get("evict_l2_eligible_mfu", 0) // sint 92 | + v["el2mru"] = d.get("evict_l2_eligible_mru", 0) // sint 93 | v["el2inel"] = d["evict_l2_ineligible"] // sint 94 | v["mtxmis"] = d["mutex_miss"] // sint 95 | 96 | @@ -498,11 +498,11 @@ def calculate(): 97 | v["l2size"] = cur["l2_size"] 98 | v["l2bytes"] = d["l2_read_bytes"] // sint 99 | 100 | - v["l2pref"] = cur["l2_prefetch_asize"] 101 | - v["l2mfu"] = cur["l2_mfu_asize"] 102 | - v["l2mru"] = cur["l2_mru_asize"] 103 | - v["l2data"] = cur["l2_bufc_data_asize"] 104 | - v["l2meta"] = cur["l2_bufc_metadata_asize"] 105 | + v["l2pref"] = cur.get("l2_prefetch_asize", 0) 106 | + v["l2mfu"] = cur.get("l2_mfu_asize", 0) 107 | + v["l2mru"] = cur.get("l2_mru_asize", 0) 108 | + v["l2data"] = cur.get("l2_bufc_data_asize", 0) 109 | + v["l2meta"] = cur.get("l2_bufc_metadata_asize", 0) 110 | v["l2pref%"] = 100 * v["l2pref"] // v["l2asize"] 111 | v["l2mfu%"] = 100 * v["l2mfu"] // v["l2asize"] 112 | v["l2mru%"] = 100 * v["l2mru"] // v["l2asize"] -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | include /usr/share/dpkg/default.mk 4 | 5 | # Common variables for all architectures 6 | include debian/rules.d/common.mk 7 | 8 | # Pull in some arch specific stuff 9 | include debian/rules.d/arch/${DEB_BUILD_ARCH}.mk 10 | 11 | BUILD_DIR ?= ${CURDIR} 12 | KERNEL_SRC := linux 13 | ZFS_SRC := zfs 14 | 15 | %: 16 | dh $@ --with quilt 17 | 18 | ## Debian package metadata 19 | debian/control: debian/templates/control.in 20 | sed -e 's/@KVNAME@/${KVNAME}/g' -e 's/@KVMAJMIN@/${KERNEL_MAJMIN}/g' < debian/templates/control.in > debian/control 21 | 22 | debian/SOURCE: 23 | echo "git clone git@github.com:fabianishere/pve-edge-kernel.git \ 24 | git checkout ${PKG_GIT_VERSION} \ 25 | git submodule update --init --depth=1" > $@ 26 | 27 | ## Debhelper phases 28 | override_dh_quilt_patch: 29 | # Apply crack bundle 30 | git -C ${KERNEL_SRC} fetch ../crack.bundle $$(git -C ${KERNEL_SRC} ls-remote ../crack.bundle | cut -f1) 31 | git -C ${KERNEL_SRC} checkout -f FETCH_HEAD 32 | # Apply patches 33 | cd ${KERNEL_SRC}; \ 34 | QUILT_PATCHES=../debian/patches \ 35 | QUILT_SERIES=series.linux \ 36 | quilt --quiltrc /dev/null --color=always push -a || test $$? = 2 37 | cd ${ZFS_SRC}; \ 38 | QUILT_PATCHES=../debian/patches \ 39 | QUILT_SERIES=series.zfs \ 40 | quilt --quiltrc /dev/null --color=always push -a || test $$? = 2 41 | 42 | override_dh_quilt_unpatch: 43 | cd ${KERNEL_SRC}; \ 44 | QUILT_PATCHES=../debian/patches \ 45 | QUILT_SERIES=series.linux \ 46 | quilt --quiltrc /dev/null pop -a || test $$? = 2 47 | cd ${ZFS_SRC}; \ 48 | QUILT_PATCHES=../debian/patches \ 49 | QUILT_SERIES=series.zfs \ 50 | quilt --quiltrc /dev/null pop -a || test $$? = 2 51 | rm -rf ${KERNEL_SRC}/.pc ${ZFS_SRC}/.pc 52 | 53 | override_dh_autoreconf: 54 | dh_autoreconf -D ${ZFS_SRC} 55 | 56 | override_dh_auto_configure: ${KERNEL_SRC}/.config 57 | 58 | override_dh_auto_build: 59 | # Kernel 60 | dh_auto_build -D ${KERNEL_SRC} -- \ 61 | CC="${PVE_KERNEL_CC}" \ 62 | KCFLAGS="${PVE_KERNEL_CFLAGS}" \ 63 | EXTRAVERSION="${EXTRAVERSION}" \ 64 | LOCALVERSION="${LOCALVERSION}" \ 65 | KBUILD_BUILD_VERSION_TIMESTAMP="${PKG_DISTRIBUTOR} ${DEB_VERSION} (${PKG_DATE_UTC_ISO})" 66 | # ZFS 67 | dh_auto_configure -D ${ZFS_SRC} -- CC="${PVE_ZFS_CC}" --with-config=kernel --with-linux=$(realpath ${KERNEL_SRC}) --with-linux-obj=$(realpath ${KERNEL_SRC}) 68 | dh_auto_build -D ${ZFS_SRC} 69 | 70 | override_dh_auto_install: debian/SOURCE .install_mark .tools_install_mark .headers_install_mark .usr_headers_install_mark 71 | dh_installdocs -A debian/copyright debian/SOURCE 72 | dh_installchangelogs 73 | dh_installman 74 | dh_strip_nondeterminism 75 | dh_compress 76 | dh_fixperms 77 | 78 | override_dh_auto_clean: debian/control 79 | dh_clean 80 | dh_auto_clean -D ${KERNEL_SRC} 81 | dh_auto_clean -D ${ZFS_SRC} 82 | rm -f ${PVE_KERNEL_TEMPLATES} ${PVE_HEADER_TEMPLATES} 83 | rm -f debian/SOURCE debian/*.tmp .*_mark 84 | 85 | ## Kernel 86 | PVE_KERNEL_TEMPLATES := $(patsubst debian/templates/pve-kernel.%.in, debian/${PVE_KERNEL_PKG}.%, $(wildcard debian/templates/pve-kernel.*.in)) 87 | 88 | ${KERNEL_SRC}/.config: 89 | python3 ${KERNEL_SRC}/debian/scripts/misc/annotations -f ${KERNEL_SRC}/debian.master/config/annotations -a ${DEB_BUILD_ARCH} --export > ${KERNEL_SRC}/debian.master/config/config.ubuntu 90 | ${KERNEL_SRC}/scripts/kconfig/merge_config.sh -m \ 91 | -O ${KERNEL_SRC} \ 92 | ${KERNEL_SRC}/debian.master/config/config.ubuntu \ 93 | debian/config/config.pve 94 | ${MAKE} -C ${KERNEL_SRC} CC=${PVE_KERNEL_CC} olddefconfig 95 | 96 | debian/${PVE_KERNEL_PKG}.%: debian/templates/pve-kernel.%.in 97 | sed -e 's/@@KVNAME@@/${KVNAME}/g' < debian/templates/pve-kernel.$*.in > debian/${PVE_KERNEL_PKG}.$* 98 | chmod +x debian/${PVE_KERNEL_PKG}.$* 99 | 100 | .install_mark: ${PVE_KERNEL_TEMPLATES} 101 | rm -rf debian/${PVE_KERNEL_PKG} 102 | mkdir -p debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME} 103 | mkdir debian/${PVE_KERNEL_PKG}/boot 104 | install -m 644 ${KERNEL_SRC}/.config debian/${PVE_KERNEL_PKG}/boot/config-${KVNAME} 105 | install -m 644 ${KERNEL_SRC}/System.map debian/${PVE_KERNEL_PKG}/boot/System.map-${KVNAME} 106 | install -m 644 ${KERNEL_SRC}/${KERNEL_IMAGE_PATH} debian/${PVE_KERNEL_PKG}/boot/${KERNEL_INSTALL_FILE}-${KVNAME} 107 | ${MAKE} -C ${KERNEL_SRC} INSTALL_MOD_PATH=${BUILD_DIR}/debian/${PVE_KERNEL_PKG}/ modules_install 108 | # install zfs drivers 109 | install -d -m 0755 debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 110 | install -m 644 ${ZFS_SRC}/module/avl/zavl.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 111 | install -m 644 ${ZFS_SRC}/module/nvpair/znvpair.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 112 | install -m 644 ${ZFS_SRC}/module/unicode/zunicode.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 113 | install -m 644 ${ZFS_SRC}/module/zcommon/zcommon.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 114 | install -m 644 ${ZFS_SRC}/module/icp/icp.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 115 | install -m 644 ${ZFS_SRC}/module/zfs/zfs.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 116 | install -m 644 ${ZFS_SRC}/module/lua/zlua.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 117 | install -m 644 ${ZFS_SRC}/module/spl/spl.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 118 | install -m 644 ${ZFS_SRC}/module/zstd/zzstd.ko debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/zfs 119 | # remove firmware 120 | rm -rf debian/${PVE_KERNEL_PKG}/lib/firmware 121 | # strip debug info 122 | find debian/${PVE_KERNEL_PKG}/lib/modules -name \*.ko -print | while read f ; do strip --strip-debug "$$f"; done 123 | # finalize 124 | /sbin/depmod -b debian/${PVE_KERNEL_PKG}/ ${KVNAME} 125 | # Autogenerate blacklist for watchdog devices (see README) 126 | install -m 0755 -d debian/${PVE_KERNEL_PKG}/lib/modprobe.d 127 | ls debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/kernel/drivers/watchdog/ > debian/watchdog-blacklist.tmp 128 | echo ipmi_watchdog.ko >> debian/watchdog-blacklist.tmp 129 | cat debian/watchdog-blacklist.tmp | sed -e 's/^/blacklist /' -e 's/.ko$$//' | sort -u > debian/${PVE_KERNEL_PKG}/lib/modprobe.d/blacklist_${PVE_KERNEL_PKG}.conf 130 | rm -f debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/source 131 | rm -f debian/${PVE_KERNEL_PKG}/lib/modules/${KVNAME}/build 132 | touch $@ 133 | 134 | ## Kernel tools 135 | .tools_compile_mark: 136 | dh_auto_build -D ${KERNEL_SRC}/tools/perf -- prefix=/usr \ 137 | HAVE_NO_LIBBFD=1 \ 138 | HAVE_CPLUS_DEMANGLE_SUPPORT=1 \ 139 | NO_LIBPYTHON=1 \ 140 | NO_LIBPERL=1 \ 141 | NO_LIBCRYPTO=1 \ 142 | PYTHON=python3 143 | echo "checking GPL-2 only perf binary for library linkage with incompatible licenses.." 144 | ! ldd ${KERNEL_SRC}/tools/perf/perf | grep -q -E '\blibbfd' 145 | ! ldd ${KERNEL_SRC}/tools/perf/perf | grep -q -E '\blibcrypto' 146 | ${MAKE} -C ${KERNEL_SRC}/tools/perf man 147 | touch $@ 148 | 149 | .tools_install_mark: .tools_compile_mark 150 | rm -rf debian/${LINUX_TOOLS_PKG} 151 | mkdir -p debian/${LINUX_TOOLS_PKG}/usr/bin 152 | mkdir -p debian/${LINUX_TOOLS_PKG}/usr/share/man/man1 153 | install -m 755 ${BUILD_DIR}/${KERNEL_SRC}/tools/perf/perf debian/${LINUX_TOOLS_PKG}/usr/bin/perf_$(KERNEL_MAJMIN) 154 | for i in ${BUILD_DIR}/${KERNEL_SRC}/tools/perf/Documentation/*.1; do \ 155 | fname="$${i##*/}"; manname="$${fname%.1}"; \ 156 | install -m644 "$$i" "debian/${LINUX_TOOLS_PKG}/usr/share/man/man1/$${manname}_$(KERNEL_MAJMIN).1"; \ 157 | done 158 | touch $@ 159 | 160 | ## Headers 161 | PVE_HEADER_TEMPLATES := $(patsubst debian/templates/pve-headers.%.in, debian/${PVE_HEADER_PKG}.%, $(wildcard debian/templates/pve-headers.*.in)) 162 | 163 | debian/${PVE_HEADER_PKG}.%: debian/templates/pve-headers.%.in 164 | sed -e 's/@@KVNAME@@/${KVNAME}/g' < debian/templates/pve-headers.$*.in > debian/${PVE_HEADER_PKG}.$* 165 | chmod +x debian/${PVE_HEADER_PKG}.$* 166 | 167 | .headers_install_mark: ${PVE_HEADER_TEMPLATES} 168 | rm -rf debian/${PVE_HEADER_PKG} 169 | mkdir -p debian/${PVE_HEADER_PKG}/usr/src/linux-headers-${KVNAME} 170 | install -m 0644 ${KERNEL_SRC}/.config debian/${PVE_HEADER_PKG}/usr/src/linux-headers-${KVNAME} 171 | ( \ 172 | cd ${KERNEL_SRC}; \ 173 | find . -path './debian/*' -prune \ 174 | -o -path './include/*' -prune \ 175 | -o -path './scripts' -prune \ 176 | -o -type f \ 177 | \( \ 178 | -name 'Makefile*' \ 179 | -o -name 'Kconfig*' \ 180 | -o -name 'Kbuild*' \ 181 | -o -name '*.sh' \ 182 | -o -name '*.pl' \ 183 | \) \ 184 | -print; \ 185 | find include scripts -type f -o -type l; \ 186 | find arch/${KERNEL_BUILD_ARCH} -maxdepth 1 -name Makefile\*; \ 187 | find arch/${KERNEL_BUILD_ARCH} -name module.lds -o -name Kbuild.platforms -o -name Platform; \ 188 | find $$(find arch/${KERNEL_BUILD_ARCH} -name include -o -name scripts -type d) -type f; \ 189 | find arch/${KERNEL_BUILD_ARCH}/include Module.symvers include scripts -type f; \ 190 | find tools/ -name 'objtool' -type f \ 191 | ) | rsync -avq --files-from=- ${KERNEL_SRC} debian/${PVE_HEADER_PKG}/usr/src/linux-headers-${KVNAME} 192 | mkdir -p debian/${PVE_HEADER_PKG}/lib/modules/${KVNAME} 193 | ln -sf /usr/src/linux-headers-${KVNAME} debian/${PVE_HEADER_PKG}/lib/modules/${KVNAME}/build 194 | touch $@ 195 | 196 | ## User-space headers 197 | .usr_headers_install_mark: PKG_DIR = debian/${PVE_USR_HEADER_PKG} 198 | .usr_headers_install_mark: OUT_DIR = ${PKG_DIR}/usr 199 | .usr_headers_install_mark: 200 | rm -rf '${PKG_DIR}' 201 | mkdir -p '${PKG_DIR}' 202 | $(MAKE) -C ${KERNEL_SRC} headers_install ARCH=$(KERNEL_HEADER_ARCH) INSTALL_HDR_PATH='$(CURDIR)'/$(OUT_DIR) 203 | rm -rf $(OUT_DIR)/include/drm $(OUT_DIR)/include/scsi 204 | find $(OUT_DIR)/include \( -name .install -o -name ..install.cmd \) -execdir rm {} + 205 | # Move include/asm to arch-specific directory 206 | mkdir -p $(OUT_DIR)/include/$(DEB_HOST_MULTIARCH) 207 | mv $(OUT_DIR)/include/asm $(OUT_DIR)/include/$(DEB_HOST_MULTIARCH)/ 208 | test ! -d $(OUT_DIR)/include/arch || \ 209 | mv $(OUT_DIR)/include/arch $(OUT_DIR)/include/$(DEB_HOST_MULTIARCH)/ 210 | touch $@ 211 | -------------------------------------------------------------------------------- /debian/rules.d/arch/amd64.mk: -------------------------------------------------------------------------------- 1 | KERNEL_BUILD_ARCH = x86 2 | KERNEL_HEADER_ARCH = $(KERNEL_BUILD_ARCH) 3 | KERNEL_BUILD_IMAGE = bzImage 4 | KERNEL_IMAGE_PATH = arch/$(KERNEL_BUILD_ARCH)/boot/${KERNEL_BUILD_IMAGE} 5 | KERNEL_INSTALL_FILE = vmlinuz 6 | -------------------------------------------------------------------------------- /debian/rules.d/arch/arm64.mk: -------------------------------------------------------------------------------- 1 | KERNEL_BUILD_ARCH = arm64 2 | KERNEL_HEADER_ARCH = $(KERNEL_BUILD_ARCH) 3 | KERNEL_BUILD_IMAGE = Image 4 | KERNEL_IMAGE_PATH = arch/$(KERNEL_BUILD_ARCH)/boot/${KERNEL_BUILD_IMAGE} 5 | KERNEL_INSTALL_FILE = vmlinuz 6 | -------------------------------------------------------------------------------- /debian/rules.d/common.mk: -------------------------------------------------------------------------------- 1 | ## Kernel information 2 | KERNEL_MAJMIN=$(shell ./scripts/version.sh -n) 3 | KERNEL_VER=$(shell ./scripts/version.sh -L) 4 | 5 | ## Debian package information 6 | PKG_DISTRIBUTOR ?= PVE Edge 7 | PKG_RELEASE = $(shell ./scripts/version.sh -r) 8 | PKG_DATE := $(shell dpkg-parsechangelog -SDate) 9 | PKG_DATE_UTC_ISO := $(shell date -u -d '$(PKG_DATE)' +%Y-%m-%d) 10 | PKG_GIT_VERSION := $(shell git rev-parse HEAD) 11 | 12 | # Build settings 13 | PVE_KERNEL_CC ?= ${CC} 14 | PVE_ZFS_CC ?= ${CC} 15 | 16 | ### Debian package names 17 | EXTRAVERSION=-edge 18 | KVNAME=${KERNEL_VER}${EXTRAVERSION} 19 | 20 | PVE_KERNEL_PKG=pve-kernel-${KVNAME} 21 | PVE_HEADER_PKG=pve-headers-${KVNAME} 22 | PVE_USR_HEADER_PKG=pve-kernel-libc-dev 23 | LINUX_TOOLS_PKG=linux-tools-${KERNEL_MAJMIN} 24 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /debian/templates/control.in: -------------------------------------------------------------------------------- 1 | Source: pve-kernel 2 | Section: devel 3 | Priority: optional 4 | Maintainer: Fabian Mastenbroek 5 | Build-Depends: asciidoc, 6 | automake, 7 | bc, 8 | bison, 9 | cpio, 10 | debhelper (>= 10~), 11 | dwarves (>= 1.16), 12 | flex, 13 | gcc (>= 8.3.0-6), 14 | git, 15 | kmod, 16 | libdw-dev, 17 | libelf-dev, 18 | libiberty-dev, 19 | libnuma-dev, 20 | libslang2-dev, 21 | libssl-dev, 22 | lz4, 23 | python3-minimal, 24 | python3-dev, 25 | quilt, 26 | rsync, 27 | xmlto, 28 | zlib1g-dev, 29 | zstd 30 | Build-Conflicts: pve-headers-@KVNAME@, 31 | Vcs-Git: git://github.com/fabianishere/pve-edge-kernel.git 32 | Vcs-Browser: https://github.com/fabianishere/pve-edge-kernel 33 | 34 | Package: linux-tools-@KVMAJMIN@ 35 | Architecture: any 36 | Section: devel 37 | Priority: optional 38 | Depends: linux-base, 39 | ${misc:Depends}, 40 | ${shlibs:Depends}, 41 | Description: Linux kernel version specific tools for version @KVMAJMIN@ 42 | This package provides the architecture dependent parts for kernel 43 | version locked tools (such as perf and x86_energy_perf_policy) 44 | 45 | Package: pve-headers-@KVMAJMIN@-edge 46 | Architecture: all 47 | Section: admin 48 | Priority: optional 49 | Depends: pve-headers-@KVNAME@, 50 | Description: Latest Proxmox Edge Kernel Headers 51 | This is a metapackage which will install the kernel headers 52 | for the latest available Proxmox Edge kernel from the @KVMAJMIN@ 53 | series. 54 | 55 | Package: pve-kernel-@KVMAJMIN@-edge 56 | Architecture: all 57 | Section: admin 58 | Priority: optional 59 | Depends: pve-firmware, 60 | pve-kernel-@KVNAME@, 61 | Description: Latest Proxmox Edge Kernel Image 62 | This is a metapackage which will install the latest available 63 | Proxmox Edge kernel from the @KVMAJMIN@ series. 64 | 65 | Package: pve-headers-@KVNAME@ 66 | Section: devel 67 | Priority: optional 68 | Architecture: any 69 | Provides: linux-headers, 70 | linux-headers-2.6, 71 | Depends: 72 | Description: The Proxmox Edge Kernel Headers 73 | This package contains the Proxmox Edge Linux kernel headers 74 | 75 | Package: pve-kernel-@KVNAME@ 76 | Section: admin 77 | Priority: optional 78 | Architecture: any 79 | Provides: linux-image, 80 | linux-image-2.6, 81 | Suggests: pve-firmware, 82 | Depends: busybox, 83 | initramfs-tools, 84 | Recommends: grub-pc | grub-efi-amd64 | grub-efi-ia32 | grub-efi-arm64, 85 | Description: The Proxmox PVE Kernel Image 86 | This package contains the Linux kernel and initial ramdisk used for booting 87 | 88 | Package: pve-kernel-libc-dev 89 | Section: devel 90 | Priority: optional 91 | Architecture: any 92 | Provides: linux-libc-dev, 93 | Conflicts: linux-libc-dev, 94 | Replaces: linux-libc-dev, 95 | Depends: ${misc:Depends} 96 | Description: Linux support headers for userspace development 97 | This package provides userspaces headers from the Linux kernel. These headers 98 | are used by the installed headers for GNU libc and other system libraries. 99 | -------------------------------------------------------------------------------- /debian/templates/pve-headers.postinst.in: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Abort if any command returns an error value 4 | set -e 5 | 6 | case "$1" in 7 | configure) 8 | 9 | # There are three sub-cases: 10 | if test "${2+set}" != set; then 11 | # We're being installed by an ancient dpkg which doesn't remember 12 | # which version was most recently configured, or even whether 13 | # there is a most recently configured version. 14 | : 15 | 16 | elif test -z "$2" -o "$2" = ""; then 17 | # The package has not ever been configured on this system, or was 18 | # purged since it was last configured. 19 | : 20 | 21 | else 22 | # Version $2 is the most recently configured version of this 23 | # package. 24 | : 25 | 26 | fi ;; 27 | abort-upgrade) 28 | # Back out of an attempt to upgrade this package FROM THIS VERSION 29 | # to version $2. Undo the effects of "prerm upgrade $2". 30 | : 31 | 32 | ;; 33 | abort-remove) 34 | if test "$2" != in-favour; then 35 | echo "$0: undocumented call to \`postinst $*'" 1>&2 36 | exit 0 37 | fi 38 | # Back out of an attempt to remove this package, which was due to 39 | # a conflict with package $3 (version $4). Undo the effects of 40 | # "prerm remove in-favour $3 $4". 41 | : 42 | 43 | ;; 44 | abort-deconfigure) 45 | if test "$2" != in-favour -o "$5" != removing; then 46 | echo "$0: undocumented call to \`postinst $*'" 1>&2 47 | exit 0 48 | fi 49 | # Back out of an attempt to deconfigure this package, which was 50 | # due to package $6 (version $7) which we depend on being removed 51 | # to make way for package $3 (version $4). Undo the effects of 52 | # "prerm deconfigure in-favour $3 $4 removing $6 $7". 53 | : 54 | 55 | ;; 56 | *) echo "$0: didn't understand being called with \`$1'" 1>&2 57 | exit 0;; 58 | esac 59 | 60 | exit 0 61 | -------------------------------------------------------------------------------- /debian/templates/pve-kernel.postinst.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | 5 | # Ignore all invocations except when called on to configure. 6 | exit 0 unless $ARGV[0] =~ /configure/; 7 | 8 | # do nothing if run from proxmox installer 9 | exit 0 if -e "/proxmox_install_mode"; 10 | 11 | my $imagedir = "/boot"; 12 | 13 | my $version = "@@KVNAME@@"; 14 | 15 | system("depmod $version"); 16 | 17 | if (-d "/etc/kernel/postinst.d") { 18 | print STDERR "Examining /etc/kernel/postinst.d.\n"; 19 | system ("run-parts --verbose --exit-on-error --arg=$version " . 20 | "--arg=$imagedir/vmlinuz-$version " . 21 | "/etc/kernel/postinst.d") && 22 | die "Failed to process /etc/kernel/postinst.d"; 23 | } 24 | 25 | exit 0 26 | -------------------------------------------------------------------------------- /debian/templates/pve-kernel.postrm.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | 5 | # Ignore all 'upgrade' invocations . 6 | exit 0 if $ARGV[0] =~ /upgrade/; 7 | 8 | my $imagedir = "/boot"; 9 | 10 | my $version = "@@KVNAME@@"; 11 | 12 | if (-d "/etc/kernel/postrm.d") { 13 | print STDERR "Examining /etc/kernel/postrm.d.\n"; 14 | system ("run-parts --verbose --exit-on-error --arg=$version " . 15 | "--arg=$imagedir/vmlinuz-$version " . 16 | "/etc/kernel/postrm.d") && 17 | die "Failed to process /etc/kernel/postrm.d"; 18 | } 19 | 20 | unlink "$imagedir/initrd.img-$version"; 21 | unlink "$imagedir/initrd.img-$version.bak"; 22 | unlink "/var/lib/initramfs-tools/$version"; 23 | 24 | # Ignore all invocations except when called on to purge. 25 | exit 0 unless $ARGV[0] =~ /purge/; 26 | 27 | my @files_to_remove = qw{ 28 | modules.dep modules.isapnpmap modules.pcimap 29 | modules.usbmap modules.parportmap 30 | modules.generic_string modules.ieee1394map 31 | modules.ieee1394map modules.pnpbiosmap 32 | modules.alias modules.ccwmap modules.inputmap 33 | modules.symbols modules.ofmap 34 | modules.seriomap modules.*.bin 35 | modules.softdep modules.devname 36 | }; 37 | 38 | foreach my $extra_file (@files_to_remove) { 39 | for (glob("/lib/modules/$version/$extra_file")) { 40 | unlink; 41 | } 42 | } 43 | 44 | system ("rmdir", "/lib/modules/$version") if -d "/lib/modules/$version"; 45 | 46 | exit 0 47 | -------------------------------------------------------------------------------- /debian/templates/pve-kernel.prerm.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | 5 | # Ignore all invocations uxcept when called on to remove 6 | exit 0 unless ($ARGV[0] && $ARGV[0] =~ /remove/) ; 7 | 8 | # do nothing if run from proxmox installer 9 | exit 0 if -e "/proxmox_install_mode"; 10 | 11 | my $imagedir = "/boot"; 12 | 13 | my $version = "@@KVNAME@@"; 14 | 15 | if (-d "/etc/kernel/prerm.d") { 16 | print STDERR "Examining /etc/kernel/prerm.d.\n"; 17 | system ("run-parts --verbose --exit-on-error --arg=$version " . 18 | "--arg=$imagedir/vmlinuz-$version " . 19 | "/etc/kernel/prerm.d") && 20 | die "Failed to process /etc/kernel/prerm.d"; 21 | } 22 | 23 | exit 0 24 | -------------------------------------------------------------------------------- /runner/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:bullseye 2 | 3 | ARG GITHUB_RUNNER_VERSION="2.301.1" 4 | 5 | ENV GITHUB_PAT "" 6 | ENV GITHUB_OWNER "fabianishere" 7 | ENV GITHUB_REPOSITORY "pve-edge-kernel" 8 | ENV RUNNER_WORKDIR "_work" 9 | 10 | RUN apt-get update \ 11 | && apt-get install -y \ 12 | curl \ 13 | sudo \ 14 | git \ 15 | jq \ 16 | devscripts \ 17 | debhelper \ 18 | equivs \ 19 | asciidoc \ 20 | bc \ 21 | bison \ 22 | cpio \ 23 | dwarves \ 24 | flex \ 25 | kmod \ 26 | libdw-dev \ 27 | libelf-dev \ 28 | libiberty-dev \ 29 | libnuma-dev \ 30 | libslang2-dev \ 31 | libssl-dev \ 32 | lz4 \ 33 | quilt \ 34 | rsync \ 35 | xmlto \ 36 | zlib1g-dev \ 37 | zstd \ 38 | python3-dev \ 39 | && apt-get clean \ 40 | && rm -rf /var/lib/apt/lists/* \ 41 | && useradd -m github \ 42 | && usermod -aG sudo github \ 43 | && echo "%sudo ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers 44 | 45 | USER github 46 | WORKDIR /home/github 47 | 48 | RUN curl -Ls https://github.com/actions/runner/releases/download/v${GITHUB_RUNNER_VERSION}/actions-runner-linux-x64-${GITHUB_RUNNER_VERSION}.tar.gz | tar xz 49 | 50 | COPY --chown=github:github entrypoint.sh ./entrypoint.sh 51 | RUN sudo chmod u+x ./entrypoint.sh 52 | 53 | ENTRYPOINT ["/home/github/entrypoint.sh"] 54 | -------------------------------------------------------------------------------- /runner/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | registration_url="https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners/registration-token" 3 | echo "Requesting registration URL at '${registration_url}'" 4 | 5 | payload=$(curl -sX POST -H "Authorization: token ${GITHUB_PAT}" ${registration_url}) 6 | export RUNNER_TOKEN=$(echo $payload | jq .token --raw-output) 7 | 8 | ./config.sh \ 9 | --name $(hostname) \ 10 | --token ${RUNNER_TOKEN} \ 11 | --url https://github.com/${GITHUB_OWNER}/${GITHUB_REPOSITORY} \ 12 | --work ${RUNNER_WORKDIR} \ 13 | --unattended \ 14 | --replace \ 15 | --label bullseye 16 | 17 | remove() { 18 | ./config.sh remove --token "${RUNNER_TOKEN}" 19 | } 20 | 21 | trap 'remove; exit 130' INT 22 | trap 'remove; exit 143' TERM 23 | 24 | ./run.sh "$*" & 25 | 26 | wait $! 27 | -------------------------------------------------------------------------------- /scripts/check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to check for new kernel release 3 | set -e 4 | set -o pipefail 5 | 6 | MAJOR=$(echo $1 | sed -e "s/^v//" -e "s/\.[^.]*$//") 7 | CURRENT=$(scripts/version.sh -L) 8 | NEW=$(curl -s https://www.kernel.org/releases.json | jq -r ".releases|sort_by(-.released.timestamp)|map(select(.version | startswith(\"$MAJOR\")))|first|.version") 9 | 10 | if [[ "$(scripts/version.sh -p)" = "0" ]]; then 11 | [[ "$(scripts/version.sh -n)" = "$NEW" ]] || echo $NEW 12 | else 13 | [[ "$CURRENT" = "$NEW" ]] || echo $NEW 14 | fi 15 | -------------------------------------------------------------------------------- /scripts/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to prepare update for new kernel release 3 | set -e 4 | set -o pipefail 5 | 6 | LINUX_REPOSITORY=linux 7 | LINUX_VERSION_PREVIOUS=$(scripts/version.sh -L) 8 | 9 | while getopts "R:t:v:r:h" OPTION; do 10 | case $OPTION in 11 | R) 12 | LINUX_REPOSITORY=$OPTARG 13 | ;; 14 | t) 15 | LINUX_TAG=$OPTARG 16 | ;; 17 | v) 18 | LINUX_VERSION=$OPTARG 19 | ;; 20 | r) 21 | LINUX_PACKAGE_RELEASE=$OPTARG 22 | ;; 23 | h) 24 | echo "update.sh -Rrtvh" 25 | echo " -R path to Linux Git repository" 26 | echo " -t tag in Linux Git repository to pick" 27 | echo " -v manual version for this kernel" 28 | echo " -r manual release version for this kernel" 29 | echo " -h this help message" 30 | exit 1 31 | ;; 32 | *) 33 | echo "Incorrect options provided" 34 | exit 1 35 | ;; 36 | esac 37 | done 38 | 39 | # Fetch from Git repository 40 | echo "Fetching $LINUX_TAG from Linux Git repository..." 41 | 42 | git --git-dir $LINUX_REPOSITORY/.git fetch origin --depth 1 $LINUX_TAG 43 | git --git-dir $LINUX_REPOSITORY/.git checkout FETCH_HEAD 44 | 45 | if [[ -z "$LINUX_VERSION" ]]; then 46 | # Parse the Linux version from the Linux repository if it not provided by the user 47 | LINUX_VERSION=$(scripts/version.sh -L) 48 | fi 49 | 50 | echo "Using Linux $LINUX_VERSION." 51 | 52 | # Prepare Debian changelog 53 | sed -e "s/@KVNAME@/$LINUX_VERSION/g" -e "s/@KVMAJMIN@/$LINUX_VERSION_MAJOR.$LINUX_VERSION_MINOR/g" < debian/templates/control.in > debian/control 54 | 55 | LINUX_VERSION_MAJOR=$(echo $LINUX_VERSION | cut -d. -f1) 56 | LINUX_VERSION_MINOR=$(echo $LINUX_VERSION | cut -d. -f2) 57 | LINUX_VERSION_PATCH=$(echo $LINUX_VERSION | cut -d. -f3) 58 | LINUX_VERSION_PATCH=${LINUX_VERSION_PATCH:-0} # Default to 0 59 | 60 | LINUX_PACKAGE_RELEASE_PREVIOUS=$(scripts/version.sh -r) 61 | 62 | # Check whether we need to increment the package release 63 | if [[ -n $LINUX_PACKAGE_RELEASE ]]; then 64 | echo "Using custom package release $LINUX_PACKAGE_RELEASE" 65 | elif [[ $LINUX_VERSION == "$LINUX_VERSION_PREVIOUS" ]]; then 66 | LINUX_PACKAGE_RELEASE=$((LINUX_PACKAGE_RELEASE_PREVIOUS + 1)) 67 | echo "Incrementing package release to $LINUX_PACKAGE_RELEASE" 68 | else 69 | LINUX_PACKAGE_RELEASE=1 70 | echo "New package release" 71 | fi 72 | 73 | echo "Updating crack.bundle..." 74 | wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v$LINUX_VERSION/crack.bundle -O crack.bundle 75 | 76 | echo "Generating entry for change log..." 77 | # Generate a changelog entry 78 | debchange -v $LINUX_VERSION-$LINUX_PACKAGE_RELEASE -D edge --force-distribution -U -M "Update to Linux $LINUX_VERSION." 79 | 80 | echo "Cleaning up" 81 | rm -f debian/control 82 | 83 | -------------------------------------------------------------------------------- /scripts/version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script for parsing version information in the repository 3 | set -e 4 | set -o pipefail 5 | 6 | LINUX_REPOSITORY=linux 7 | LINUX_VERSION=$(sed -n "s/^VERSION = \([0-9]*$\)/\1/p" < linux/Makefile | xargs) 8 | LINUX_PATCHLEVEL=$(sed -n "s/^PATCHLEVEL = \([0-9]*$\)/\1/p" < linux/Makefile | xargs) 9 | LINUX_SUBLEVEL=$(sed -n "s/^SUBLEVEL = \([0-9]*$\)/\1/p" < linux/Makefile | xargs) 10 | LINUX_VERSION_FULL=$LINUX_VERSION.$LINUX_PATCHLEVEL.$LINUX_SUBLEVEL 11 | PACKAGE_VERSION=$(dpkg-parsechangelog -SVersion) 12 | PACKAGE_RELEASE=$(echo $PACKAGE_VERSION | sed -n 's/^.*-\([0-9]*\).*$/\1/p' | xargs) 13 | 14 | while getopts "MmnprdLh" OPTION; do 15 | case $OPTION in 16 | M) 17 | echo $LINUX_VERSION 18 | exit 0 19 | ;; 20 | m) 21 | echo $LINUX_PATCHLEVEL 22 | exit 0 23 | ;; 24 | n) 25 | echo $LINUX_VERSION.$LINUX_PATCHLEVEL 26 | exit 0 27 | ;; 28 | p) 29 | echo $LINUX_SUBLEVEL 30 | exit 0 31 | ;; 32 | r) 33 | echo $PACKAGE_RELEASE 34 | exit 0 35 | ;; 36 | L) 37 | echo $LINUX_VERSION_FULL 38 | exit 0 39 | ;; 40 | h) 41 | echo "version.sh [-Mmnprfh]" 42 | echo " -M major version" 43 | echo " -m minor version" 44 | echo " -n major minor version" 45 | echo " -p patch version" 46 | echo " -r package release" 47 | echo " -L Linux version" 48 | echo " -h this help message" 49 | exit 1 50 | ;; 51 | *) 52 | echo "Incorrect options provided" 53 | exit 1 54 | ;; 55 | esac 56 | done 57 | 58 | echo "$PACKAGE_VERSION" 59 | --------------------------------------------------------------------------------