commit c585e93020977a63bd1a203eb305bfe3cb516be6 Author: CentOS Sources Date: Tue May 17 04:48:50 2022 -0400 import kernel-srpm-macros-1.0-11.el9 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.kernel-srpm-macros.metadata b/.kernel-srpm-macros.metadata new file mode 100644 index 0000000..e69de29 diff --git a/SOURCES/brp-kmod-restore-perms b/SOURCES/brp-kmod-restore-perms new file mode 100755 index 0000000..ffabefc --- /dev/null +++ b/SOURCES/brp-kmod-restore-perms @@ -0,0 +1,28 @@ +#! /bin/bash -efu + +## A counterpart of brp-kmod-set-exec-bits that restores original kmod +## file permissions + +# If using normal root, avoid changing anything. +[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != "/" ] || exit 0 + +# Checking for required programs +which chmod >/dev/null || exit 0 + +[ -r "$RPM_BUILD_ROOT/kmod-permissions.list" ] || exit 0 + +while read perm path; do + [ -n "$perm" ] || continue + + # Account for possible kernel module compression + [ -e "$RPM_BUILD_ROOT/$path" ] || { + [ \! -e "$RPM_BUILD_ROOT/$path.gz" ] || path="$path.gz" + [ \! -e "$RPM_BUILD_ROOT/$path.bz2" ] || path="$path.bz2" + [ \! -e "$RPM_BUILD_ROOT/$path.xz" ] || path="$path.xz" + [ \! -e "$RPM_BUILD_ROOT/$path.zst" ] || path="$path.zst" + } + + chmod "$perm" "$RPM_BUILD_ROOT/$path" +done < "$RPM_BUILD_ROOT/kmod-permissions.list" + +rm -f "$RPM_BUILD_ROOT/kmod-permissions.list" diff --git a/SOURCES/brp-kmod-set-exec-bit b/SOURCES/brp-kmod-set-exec-bit new file mode 100755 index 0000000..eccd5b4 --- /dev/null +++ b/SOURCES/brp-kmod-set-exec-bit @@ -0,0 +1,14 @@ +#! /bin/bash -efux + +## A hack for making brp-strip taking into account kmod files + +# If using normal root, avoid changing anything. +[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != "/" ] || exit 0 + +# Checking for required programs +which find chmod >/dev/null || exit 0 + +find "$RPM_BUILD_ROOT" \ + -name '*.ko' \ + -printf '%#m %P\n' \ + -exec chmod u+x '{}' \; > "$RPM_BUILD_ROOT/kmod-permissions.list" diff --git a/SOURCES/find-provides.ksyms b/SOURCES/find-provides.ksyms new file mode 100755 index 0000000..92d6220 --- /dev/null +++ b/SOURCES/find-provides.ksyms @@ -0,0 +1,63 @@ +#! /bin/bash + +IFS=$'\n' + +for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do + dep_pfx="ksym" + # For built-in kmods, "kernel()" syntax is used instead of "ksym()" + printf "%s" "$module" | grep -v "^${RPM_BUILD_ROOT}/\?lib/modules/[1-9][^/]*/kernel" > /dev/null \ + || dep_pfx="kernel" + + tmpfile="" + if [ "x${module%.ko}" = "x${module}" ]; then + tmpfile=$(mktemp -t ${0##*/}.XXXXXX.ko) + proc_bin= + case "${module##*.}" in + zst) + proc_bin=zstd + ;; + xz) + proc_bin=xz + ;; + bz2) + proc_bin=bzip2 + ;; + gz) + proc_bin=gzip + ;; + esac + + [ -n "$proc_bin" ] || continue + + "$proc_bin" -d -c - < "$module" > "$tmpfile" || continue + module="$tmpfile" + fi + + if [[ -n $(nm $module | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p') ]]; then + nm $module \ + | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p' \ + | awk --non-decimal-data '{printf("'"${dep_pfx}"'(%s) = 0x%08x\n", $2, $1)}' \ + | LC_ALL=C sort -u + else + ELFRODATA=$(readelf -R .rodata $module | awk '/0x/{printf $2$3$4$5}') + if [[ -n $(readelf -h $module | grep "little endian") ]]; then + RODATA=$(echo $ELFRODATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g') + else + RODATA=$ELFRODATA + fi + # Commit binutils-2_33~1385[1] has changed (and binutils-2_35~1768[2] + # has not reverted it) the calculated type for symbols in read-write + # .rodata section from 'R' to 'D', since, apparently, many kernel + # modules have it indeed read-write. + # + # [1] https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=a288c270991d + # [2] https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=49d9fd42acef + for sym in $(nm $module | sed -r -ne 's:^0*([0-9a-f]+) [DR] __crc_(.+):0x\1 \2:p'); do + echo $sym $RODATA + done \ + | awk --non-decimal-data '{printf("'"${dep_pfx}"'(%s) = 0x%08s\n", $2, substr($3,($1*2)+1,8))}' \ + | LC_ALL=C sort -u + fi + + [ -z "$tmpfile" ] || rm -f -- "$tmpfile" +done diff --git a/SOURCES/find-requires.ksyms b/SOURCES/find-requires.ksyms new file mode 100755 index 0000000..78a2105 --- /dev/null +++ b/SOURCES/find-requires.ksyms @@ -0,0 +1,165 @@ +#! /bin/bash +# +# This script is called during external module building to create dependencies +# both upon the RHEL kernel, and on additional external modules. Symbols that +# cannot be reconciled against those provided by the kernel are assumed to be +# provided by an external module and "ksym" replaces th regular "kernel" dep. + +IFS=$'\n' + +# Extract all of the symbols provided by this module. +all_provides() { + for module in "$@"; do + tmpfile="" + if [ "x${module%.ko}" = "x${module}" ]; then + tmpfile=$(mktemp -t ${0##*/}.XXXXXX.ko) + proc_bin= + case "${module##*.}" in + zst) + proc_bin=zstd + ;; + xz) + proc_bin=xz + ;; + bz2) + proc_bin=bzip2 + ;; + gz) + proc_bin=gzip + ;; + esac + + [ -n "$proc_bin" ] || continue + + "$proc_bin" -d -c - < "$module" > "$tmpfile" || continue + module="$tmpfile" + fi + + if [[ -n $(nm "$module" | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p') ]]; then + nm "$module" \ + | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p' \ + | awk --non-decimal-data '{printf("%s:0x%08x\n", $2, $1)}' + else + ELFRODATA=$(readelf -R .rodata "$module" | awk '/0x/{printf $2$3$4$5}') + if [[ -n $(readelf -h "$module" | grep "little endian") ]]; then + RODATA=$(echo $ELFRODATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g') + else + RODATA=$ELFRODATA + fi + # Commit binutils-2_33~1385[1] has changed (and binutils-2_35~1768[2] + # has not reverted it) the calculated type for symbols in read-write + # .rodata section from 'R' to 'D', since, apparently, many kernel + # modules have it indeed read-write. + # + # [1] https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=a288c270991d + # [2] https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=49d9fd42acef + for sym in $(nm "$module" | sed -r -ne 's:^0*([0-9a-f]+) [DR] __crc_(.+):0x\1 \2:p'); do + echo $sym $RODATA + done \ + | awk --non-decimal-data '{printf("%s:0x%08s\n", $2, substr($3,($1*2)+1,8))}' + fi + + [ -z "$tmpfile" ] || rm -f -- "$tmpfile" + done \ + | LC_ALL=C sort -k1,1 -u +} + +# Extract all of the requirements of this module. +all_requires() { + for module in "$@"; do + set -- $(/sbin/modinfo -F vermagic "$module" | sed -e 's: .*::' -e q) + /sbin/modprobe --dump-modversions "$module" \ + | awk --non-decimal-data ' + BEGIN { FS = "\t" ; OFS = "\t" } + {printf("%s:0x%08x\n", $2, $1)}' \ + | sed -r -e 's:$:\t'"$1"':' + done \ + | LC_ALL=C sort -k1,1 -u +} + +# Filter out requirements fulfilled by the module itself. +mod_requires() { + LC_ALL=C join -t $'\t' -j 1 -v 1 \ + <(all_requires "$@") \ + <(all_provides "$@") \ + | LC_ALL=C sort -k1,1 -u +} + +if ! [ -e /sbin/modinfo -a -e /sbin/modprobe ]; then + cat > /dev/null + exit 0 +fi + +check_kabi() { + arch=$(uname -m) + kabi_file="/lib/modules/kabi-current/kabi_stablelist_$arch" + + # If not installed, output a warning and return (continue) + if [ ! -f "$kabi_file" ]; then + echo "" >&2 + echo "********************************************************************************" >&2 + echo "*********************** KERNEL ABI COMPATIBILITY WARNING ***********************" >&2 + echo "********************************************************************************" >&2 + echo "The kernel ABI reference files (provided by "kabi-stablelists") were not found." >&2 + echo "No compatibility check was performed. Please install the kABI reference files" >&2 + echo "and rebuild if you would like to verify compatibility with kernel ABI." >&2 + echo "" >&2 + return + fi + + unset non_kabi + for symbol in "$@"; do + if ! egrep "^[[:space:]]$symbol\$" $kabi_file >/dev/null; then + non_kabi=("${non_kabi[@]}" "$symbol") + fi + done + + if [ ${#non_kabi[@]} -gt 0 ]; then + echo "" >&2 + echo "********************************************************************************" >&2 + echo "*********************** KERNEL ABI COMPATIBILITY WARNING ***********************" >&2 + echo "********************************************************************************" >&2 + echo "The following kernel symbols are not guaranteed to remain compatible with" >&2 + echo "future kernel updates to this RHEL release:" >&2 + echo "" >&2 + for symbol in "${non_kabi[@]}"; do + printf "\t$symbol\n" >&2 + done + echo "" >&2 + echo "Red Hat recommends that you consider using only official kernel ABI symbols" >&2 + echo "where possible. Requests for additions to the kernel ABI can be filed with" >&2 + echo "your partner or customer representative (component: driver-update-program)." >&2 + echo "" >&2 + fi +} + +modules=($(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@") +if [ ${#modules[@]} -gt 0 ]; then + kernel=$(/sbin/modinfo -F vermagic "${modules[0]}" | sed -e 's: .*::' -e q) + + # get all that kernel provides + symvers=$(mktemp -t ${0##*/}.XXXXX) + + cat /usr/src/kernels/$kernel/Module.symvers | awk ' + BEGIN { FS = "\t" ; OFS = "\t" } + { print $2 ":" $1 } + ' \ + | sed -r -e 's:$:\t'"$kernel"':' \ + | LC_ALL=C sort -k1,1 -u > $symvers + + # Symbols matching with the kernel get a "kernel" dependency + mod_req=$(mktemp -t mod_req.XXXXX) + mod_requires "${modules[@]}" > "$mod_req" + LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \ + | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "kernel(" $1 ") = " $2 }' + + # Symbols from elsewhere get a "ksym" dependency + LC_ALL=C join -t $'\t' -j 1 -v 2 $symvers "$mod_req" | LC_ALL=C sort -u \ + | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "ksym(" $1 ") = " $2 }' + + # Check kABI if the kabi-stablelists package is installed + # Do this last so we can try to output this error at the end + kabi_check_symbols=($(LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \ + | awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print $1 }')) + check_kabi "${kabi_check_symbols[@]}" +fi diff --git a/SOURCES/firmware.prov b/SOURCES/firmware.prov new file mode 100644 index 0000000..8c5b7e4 --- /dev/null +++ b/SOURCES/firmware.prov @@ -0,0 +1,14 @@ +#!/bin/sh +# +# firmware.prov - Automatically extract any and all firmware dependencies from +# kernel object (.ko) files and add to RPM deps. + +IFS=$'\n' + +for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') $*; +do + for firmware in `/sbin/modinfo -F firmware $module`; + do + echo "firmware($firmware)" + done +done diff --git a/SOURCES/kabi.attr b/SOURCES/kabi.attr new file mode 100644 index 0000000..2d81387 --- /dev/null +++ b/SOURCES/kabi.attr @@ -0,0 +1,2 @@ +%__kabi_provides %{_rpmconfigdir}/kabi.sh +%__kabi_path ^(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.gz$ diff --git a/SOURCES/kabi.sh b/SOURCES/kabi.sh new file mode 100644 index 0000000..3fb749b --- /dev/null +++ b/SOURCES/kabi.sh @@ -0,0 +1,16 @@ +#!/bin/bash +x +# +# kabi.sh - Automatically extract any kernel symbol checksum from the +# symvers file and add to RPM deps. This is used to move the +# checksum checking from modprobe to rpm install for 3rd party +# modules (so they can fail during install and not at load). + +IFS=$'\n' + +for symvers in $(grep -E '(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.gz') "$@"; +do + # We generate dependencies only for symbols exported by vmlinux itself + # and not for kmods here as they are spread across subpackages, + # so Provides: generation for kmods is handled by find-provides.ksyms. + zcat $symvers | awk '/[^ ]* [^ ]* vmlinux .*/ { print "kernel(" $2 ") = " $1 }' +done diff --git a/SOURCES/kmod.attr b/SOURCES/kmod.attr new file mode 100644 index 0000000..23b1289 --- /dev/null +++ b/SOURCES/kmod.attr @@ -0,0 +1,31 @@ +%__kmod_path ^/lib/modules/.*/(modules.builtin|.*\.ko|.*\.ko\.gz|.*\.ko\.bz2|.*\.ko\.xz|.*\.ko\.zst)$ +%__kmod_provides() %{lua: + function basename(fn) + return string.gsub(fn, "(.*/)(.*)", "%2") + end + function strip_compress_sfx(fn) + return string.gsub(fn, "(.*)(\.gz|\.bz2|\.xz|\.zst)?$", "%1") + end + function printdep(mod) + print("kmod("..mod..") ") + end + local fn = rpm.expand("%{1}") + local bn = basename(fn) + if bn == "modules.builtin" then + for l in io.lines(fn) do + local builtin_mod = basename(l) + printdep(builtin_mod) + if strip_compress_sfx(builtin_mod) ~= builtin_mod then + printdep(strip_compress_sfx(builtin_mod)) + end + end + else + local mod = string.match(bn, "%g+.ko") + if mod then + printdep(mod) + if strip_compress_sfx(mod) ~= mod then + printdep(strip_compress_sfx(mod)) + end + end + end +} diff --git a/SOURCES/kmodtool b/SOURCES/kmodtool new file mode 100755 index 0000000..3066987 --- /dev/null +++ b/SOURCES/kmodtool @@ -0,0 +1,346 @@ +#!/bin/bash + +# kmodtool - Helper script for building kernel module RPMs +# An original version appeared in Fedora. This version is +# generally called only by the %kernel_module_package RPM macro +# during the process of building Driver Update Packages (which +# are also known as "kmods" in the Fedora community). +# +# Copyright (c) 2003-2010 Ville Skyttä , +# Thorsten Leemhuis +# Jon Masters +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# Changelog: +# +# 2010/07/28 - Add fixes for filelists in line with LF standard +# - Remove now defunct "framepointer" kernel variant +# - Change version to "rhel6-rh2" as a consequence. +# +# 2010/01/10 - Simplified for RHEL6. We are working on upstream +# moving to a newer format and in any case do not +# need to retain support for really old systems. + +shopt -s extglob + +myprog="kmodtool" +myver="0.10.10_rhel9" +knownvariants=@(debug|kdump|zfcpdump) +kmod_name= +kver= +verrel= +variant= + +get_verrel () +{ + verrel=${1:-$(uname -r)} + verrel=${verrel/%[.+]$knownvariants/} +} + +print_verrel () +{ + get_verrel "$@" + echo "${verrel}" +} + +get_variant () +{ + get_verrel "$@" + variant=${1:-$(uname -r)} + variant=${variant/#$verrel?(.+)/} + variant=${variant:-'""'} +} + +print_variant () +{ + get_variant $@ + echo "${variant}" +} + +# Detect flavor separator character. We have to do that due to +# a systemd-tailored patch for kernel spec[1][2] introduced in Fedora and then +# imported in RHEL 8 that broke all OOT kmod infrastructure for the flavored +# kernels. +# +# [1] https://lists.fedoraproject.org/pipermail/kernel/2013-June/004262.html +# [2] https://src.fedoraproject.org/rpms/kernel/c/faf25207dc86666a611c45ae3ffaf385c170bd2a +# +# $1 - kver +# $2 - variant +get_variant_char () +{ + variant="$2" + [ "$variant" != "default" ] || variant="" + + get_verrel "$1" + + variant_char="" + [ -n "$variant" ] || return 0 + + # We expect that the flavored kernel is already installed in the buildroot + variant_char="+" + [ -e "/usr/src/kernels/${verrel}+${variant}" ] && return 0 + + variant_char="." +} + +print_variant_char () +{ + get_variant_char "$@" + echo "${variant_char}" +} + +print_kernel_source () +{ + get_variant_char "$@" + echo "/usr/src/kernels/${verrel}${variant_char}${variant}" +} + +get_filelist() { + local IFS=$'\n' + filelist=($(cat)) + + if [ ${#filelist[@]} -gt 0 ]; + then + for ((n = 0; n < ${#filelist[@]}; n++)); + do + line="${filelist[n]}" + line=$(echo "$line" \ + | sed -e "s/%verrel/$verrel/g" \ + | sed -e "s/%variant/$variant/g" \ + | sed -e "s/%dashvariant/$dashvariant/g" \ + | sed -e "s/%dotvariant/$dotvariant/g" \ + | sed -e "s/\+%1/$dotvariant/g" \ + | sed -e "s/\.%1/$dotvariant/g" \ + | sed -e "s/\-%1/$dotvariant/g" \ + | sed -e "s/%2/$verrel/g") + echo "$line" + done + else + echo "%defattr(644,root,root,755)" + echo "/lib/modules/${verrel}${dotvariant}" + fi +} + + +get_rpmtemplate () +{ + local variant="${1}" + + get_variant_char "${verrel}" "${variant}" + + local dashvariant="${variant:+-${variant}}" + local dotvariant="${variant:+${variant_char}${variant}}" + + echo "%package -n kmod-${kmod_name}${dashvariant}" + + if [ -z "$kmod_provides_summary" ]; then + echo "Summary: ${kmod_name} kernel module(s)" + fi + + if [ -z "$kmod_provides_group" ]; then + echo "Group: System Environment/Kernel" + fi + + if [ ! -z "$kmod_version" ]; then + echo "Version: %{kmod_version}" + fi + + if [ ! -z "$kmod_release" ]; then + echo "Release: %{kmod_release}" + fi + + cat <= ${verrel}${dotvariant} +Provides: kernel${dashvariant}-modules >= ${verrel} +Provides: ${kmod_name}-kmod = %{?epoch:%{epoch}:}%{version}-%{release} +Requires(post): /usr/sbin/depmod +Requires(postun): /usr/sbin/depmod +Requires(post): /usr/sbin/weak-modules +Requires(postun): /usr/sbin/weak-modules +EOF + + if [ "yes" != "$nobuildreqs" ] + then + cat < /dev/null || : +fi + +modules=( \$(find /lib/modules/${verrel}${dotvariant}/extra/${kmod_name} | grep -E '\.ko(\.gz|\.bz2|\.xz|\.zst)?$') ) +if [ -x "/usr/sbin/weak-modules" ]; then + printf '%s\n' "\${modules[@]}" \ + | /usr/sbin/weak-modules --add-modules +fi +EOF + +cat < /var/run/rpm-kmod-${kmod_name}${dashvariant}-modules +EOF + +cat < /dev/null || : +fi + +modules=( \$(cat /var/run/rpm-kmod-${kmod_name}${dashvariant}-modules) ) +rm /var/run/rpm-kmod-${kmod_name}${dashvariant}-modules +if [ -x "/usr/sbin/weak-modules" ]; then + printf '%s\n' "\${modules[@]}" \ + | /usr/sbin/weak-modules --remove-modules +fi +EOF + +echo "%files -n kmod-${kmod_name}${dashvariant}" + +if [ "" == "$override_filelist" ]; +then + echo "%defattr(644,root,root,755)" + echo "/lib/modules/${verrel}${dotvariant}" +else + cat "$override_filelist" | get_filelist +fi +} + +print_rpmtemplate () +{ + kmod_name="${1}" + shift + kver="${1}" + get_verrel "${1}" + shift + if [ -z "${kmod_name}" ] ; then + echo "Please provide the kmodule-name as first parameter." >&2 + exit 2 + elif [ -z "${kver}" ] ; then + echo "Please provide the kver as second parameter." >&2 + exit 2 + elif [ -z "${verrel}" ] ; then + echo "Couldn't find out the verrel." >&2 + exit 2 + fi + + for variant in "$@" ; do + if [ "default" == "$variant" ]; + then + get_rpmtemplate "" + else + get_rpmtemplate "${variant}" + fi + done +} + +usage () +{ + cat <