Uname: Linux server.saraya-global.com 4.18.0-553.77.1.el8_10.x86_64 #1 SMP Tue Sep 30 05:56:43 EDT 2025 x86_64
User: 1003 (sarayaglobal)
Group: 1004 (sarayaglobal)
Disabled functions: NONE
Safe mode: On[ PHPinfo ]
//usr/sbin      ( Reset | Go to )
File Name: kpatch
#!/bin/bash
#
# kpatch hot patch module management script
#
# Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
# Copyright (C) 2014 Josh Poimboeuf <jpoimboe@redhat.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA,
# 02110-1301, USA.

# This is the kpatch user script that manages installing, loading, and
# displaying information about kernel patch modules installed on the system.

INSTALLDIR=/var/lib/kpatch
SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
VERSION="0.9.7"
POST_ENABLE_WAIT=15    # seconds
POST_SIGNAL_WAIT=60    # seconds
MODULE_REF_WAIT=15    # seconds

# How many times to try loading the patch if activeness safety check fails.
MAX_LOAD_ATTEMPTS=5
# How long to wait before retry, in seconds.
RETRY_INTERVAL=2

usage_cmd() {
    printf '   %-20s\n%s\n' "$1" "$(fmt -w 80 <(echo "      $2"))" >&2
}

usage () {
    # ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION
    # When changing this, please also update the man page.  Thanks!
    echo "usage: kpatch <command> [<args>]" >&2
    echo >&2
    echo "Valid commands:" >&2
    usage_cmd "install [-k|--kernel-version=<kernel version>] <module>" "install patch module to be loaded at boot"
    usage_cmd "uninstall [-k|--kernel-version=<kernel version>] <module>" "uninstall patch module"
    echo >&2
    usage_cmd "load --all" "load all installed patch modules into the running kernel"
    usage_cmd "load <module>" "load patch module into the running kernel"
    usage_cmd "unload --all (UNSUPPORTED)" "unload all patch modules from the running kernel"
    usage_cmd "unload <module> (UNSUPPORTED)" "unload patch module from the running kernel"
    echo >&2
    usage_cmd "info <module>" "show information about a patch module"
    echo >&2
    usage_cmd "list" "list installed patch modules"
    echo >&2
    usage_cmd "signal" "signal/poke any process stalling the current patch transition. This is only useful on systems that have the sysfs livepatch signal interface. On other systems, the signaling should be done automatically by the OS and this subcommand is a no-op."
    echo >&2
    usage_cmd "version" "display the kpatch version"
    exit 1
}

warn() {
    echo "kpatch: $*" >&2
}

die() {
    warn "$@"
    exit 1
}

confirm_prompt() {
    local prompt="$1"
    local answer
    while true; do
        read -rp "$prompt [Y/N] " answer
        [[ $answer == 'Y' || $answer == 'y' ]] && return 0
        [[ $answer == 'N' || $answer == 'n' ]] && return 1
    done
}

__find_module () {
    MODULE="$1"
    [[ -f "$MODULE" ]] && return

    MODULE="$INSTALLDIR/$(uname -r)/$1"
    [[ -f "$MODULE" ]] && return

    return 1
}

mod_name () {
    MODNAME="$(basename "$1")"
    MODNAME="${MODNAME%.ko}"
    MODNAME="${MODNAME//-/_}"
}

find_module () {
    arg="$1"
    if [[ "$arg" =~ \.ko ]]; then
        __find_module "$arg" || return 1
        mod_name "$MODULE"
        return
    else
        for i in "$INSTALLDIR/$(uname -r)"/*; do
            mod_name "$i"
            if [[ "$MODNAME" == "$arg" ]]; then
                MODULE="$i"
                return
            fi
        done
    fi

    return 1
}

find_core_module() {
    COREMOD="$SCRIPTDIR"/../kmod/core/kpatch.ko
    [[ -f "$COREMOD" ]] && return

    COREMOD="/usr/local/lib/kpatch/$(uname -r)/kpatch.ko"
    [[ -f "$COREMOD" ]] && return

    COREMOD="/usr/lib/kpatch/$(uname -r)/kpatch.ko"
    [[ -f "$COREMOD" ]] && return

    COREMOD="/usr/local/lib/modules/$(uname -r)/extra/kpatch/kpatch.ko"
    [[ -f "$COREMOD" ]] && return

    COREMOD="/usr/lib/modules/$(uname -r)/extra/kpatch/kpatch.ko"
    [[ -f "$COREMOD" ]] && return

    return 1
}

kpatch_core_loaded() {
    [[ -d "/sys/kernel/kpatch" ]]
}

core_loaded () {
    [[ -d "/sys/kernel/kpatch" ]] || [[ -d "/sys/kernel/livepatch" ]]
}

get_module_name () {
    readelf -p .gnu.linkonce.this_module "$1" | grep '\[.*\]' | awk '{print $3}'
}

init_sysfs_var() {
    # If the kernel is configured with CONFIG_LIVEPATCH, use that.
    # Otherwise, use the kpatch core module (kpatch.ko).
    if [[ -e /sys/kernel/livepatch ]] ; then
        # livepatch ABI
        SYSFS="/sys/kernel/livepatch"

    elif [[ -e /sys/kernel/kpatch/patches ]] ; then
        # kpatch pre-0.4 ABI
        SYSFS="/sys/kernel/kpatch/patches"

    else
        # kpatch 0.4 ABI
        SYSFS="/sys/kernel/kpatch"
    fi
}

verify_module_checksum () {
    modname="$(get_module_name "$1")"
    [[ -z "$modname" ]] && return 1

    checksum="$(readelf -p .kpatch.checksum "$1" 2>&1 | grep '\[.*\]' | awk '{print $3}')"

    # Fail checksum match only if both exist and diverge
    if [[ -n "$checksum" ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then
        sysfs_checksum="$(cat "$SYSFS/${modname}/checksum")"
        [[ "$checksum" == "$sysfs_checksum" ]] || return 1
    fi

    return 0
}

in_transition() {
    local moddir="$SYSFS/$1"
    [[ $(cat "$moddir/transition" 2>/dev/null) == "1" ]] && return 0
    return 1
}

is_stalled() {
    local module="$1"
    local pid="$2"
    local patch_enabled
    local patch_state

    patch_enabled="$(cat "$SYSFS/$module/enabled" 2>/dev/null)"
    patch_state="$(cat "/proc/$pid/patch_state" 2>/dev/null)"

    # No patch transition in progress
    [[ "$patch_state" == "-1" ]] && return 1

    [[ -z "$patch_enabled" ]] || [[ -z "$patch_state" ]] && return 1

    # Stalls can be determined if the process state does not match
    # the transition target (ie, "enabled" and "patched", "disabled"
    # and "unpatched").  The state value enumerations match, so we
    # can just compare them directly:
    [[ "$patch_enabled" != "$patch_state" ]] && return 0
    return 1
}

get_transition_patch() {
    local module
    local modname
    for module in "$SYSFS"/*; do
        modname=$(basename "$module")
        if in_transition "$modname" ; then
            echo "$modname"
            return
        fi
    done
}

show_stalled_processes() {
    local module
    local proc_task
    local tid

    module=$(get_transition_patch)
    [[ -z "$module" ]] && return

    echo ""
    echo "Stalled processes:"
    for proc_task in /proc/[0-9]*/task/[0-9]*; do
        tid=${proc_task#*/task/}
        is_stalled "$module" "$tid" && echo -e "$tid $(cat "$proc_task"/comm 2>/dev/null)\nstack:\n$(cat "$proc_task"/stack 2>/dev/null)"
    done
}

signal_stalled_processes() {
    local module
    local proc_task
    local tid

    module=$(get_transition_patch)
    [[ -z "$module" ]] && return

    if [[ -e "/sys/kernel/livepatch/$module/signal" ]] ; then
        echo "signaling stalled process(es):"
        echo 1 > "/sys/kernel/livepatch/$module/signal"
        else
            warn "Livepatch process signaling is performed automatically on your system."
            warn "Skipping manual process signaling."
    fi
}

wait_for_patch_transition() {
    local module="$1"
    local i

    in_transition "$module" || return 0

    echo "waiting (up to $POST_ENABLE_WAIT seconds) for patch transition to complete..."
    for (( i=0; i<POST_ENABLE_WAIT; i++ )); do
        if ! in_transition "$module" ; then
            echo "transition complete ($i seconds)"
            return 0
        fi
        sleep 1s
    done

    echo "patch transition has stalled!"
    signal_stalled_processes

    echo "waiting (up to $POST_SIGNAL_WAIT seconds) for patch transition to complete..."
    for (( i=0; i<POST_SIGNAL_WAIT; i++ )); do
        if ! in_transition "$module" ; then
            echo "transition complete ($i seconds)"
            return 0
        fi
        sleep 1s
    done

    return 1
}

module_ref_count() {
    local modname="$1"
    [[ $(cat "/sys/module/$modname/refcnt" 2>/dev/null) -gt "0" ]]
}

wait_for_zero_module_ref_count() {
    local modname="$1"
    local i=0

    # We can't rely on a zero refcount with kpatch.ko as it
    # implements KPATCH_FORCE_UNSAFE with an additional reference on
    # kpatch-patch modules to avoid potential crashes.
    kpatch_core_loaded && return 0

    module_ref_count "$modname" || return 0

    echo "waiting (up to $MODULE_REF_WAIT seconds) for module refcount..."
    for (( i=0; i<MODULE_REF_WAIT; i++ )); do
        module_ref_count "$modname" || return 0
        sleep 1s
    done

    return 1
}

load_module () {
    local module="$1"

    if ! core_loaded; then
        if modprobe -q kpatch; then
            echo "loaded core module"
        else
            find_core_module || die "can't find core module"
            echo "loading core module: $COREMOD"
            insmod "$COREMOD" || die "failed to load core module"
        fi

        # Now that the core module has been loaded, set $SYSFS to the
        # correct value based on the loaded core module's ABI.
        init_sysfs_var
    fi

    local modname
    modname="$(get_module_name "$module")"
    local moddir="$SYSFS/$modname"
    if [[ -d "$moddir" ]] ; then
        if [[ "$(cat "${moddir}/enabled")" -eq 0 ]]; then
            if verify_module_checksum "$module"; then # same checksum
                echo "module already loaded, re-enabling"
                echo 1 > "${moddir}/enabled" || die "failed to re-enable module $modname"
                if ! wait_for_patch_transition "$modname" ; then
                    show_stalled_processes
                    echo "module $modname did not complete its transition, disabling..."
                    echo 0 > "${moddir}/enabled" || die "failed to disable module $modname"
                    wait_for_patch_transition "$modname"
                    die "error: failed to re-enable module $modname (transition stalled), patch disabled"
                fi
                return
            else
                die "error: cannot re-enable patch module $modname, cannot verify checksum match"
            fi
        else
            echo "module named $modname already loaded and enabled"
        fi
    else
        # Cleanup possibly loaded, but disabled patch.
        remove_module "$modname" "quiet"

        echo "loading patch module: $module"
        local i=0
        while true; do
            out="$(LC_ALL=C insmod "$module" 2>&1)"
            [[ -z "$out" ]] && break
            echo "$out" 1>&2
            [[ ! "$out" =~ "Device or resource busy" ]] &&
                die "failed to load module $module"

            # "Device or resource busy" means the activeness safety check
            # failed.  Retry in a few seconds.
            i=$((i+1))
            if [[ $i -eq $MAX_LOAD_ATTEMPTS ]]; then
                die "failed to load module $module"
                break
            else
                warn "retrying..."
                sleep $RETRY_INTERVAL
            fi
        done
    fi

    if ! wait_for_patch_transition "$modname" ; then
        show_stalled_processes
        echo "module $modname did not complete its transition, unloading..."
        unload_module "$modname"
        die "error: failed to load module $modname (transition stalled)"
    fi

    return 0
}

disable_patch () {
    local modname="$1"

    local enabled="$SYSFS/$modname/enabled"
    if ! [[ -e "$enabled" ]]; then
        if [[ -d "/sys/module/$modname" ]] ; then
            # Module is loaded, but already disabled
            return 0
        fi
        warn "patch module $modname is not loaded"
        return 1
    fi

    if [[ "$(cat "$enabled")" -eq 1 ]]; then
        echo "disabling patch module: $modname"
        local i=0
        while true; do
            out="$(export LC_ALL=C; sh -c "echo 0 > $enabled" 2>&1)"
            [[ -z "$out" ]] && break
            echo "$out" 1>&2
            if [[ ! "$out" =~ "Device or resource busy" ]]; then
                return 1
            fi

            # "Device or resource busy" means the activeness safety check
            # failed.  Retry in a few seconds.
            i=$((i+1))
            if [[ $i -eq $MAX_LOAD_ATTEMPTS ]]; then
                return 1
            else
                warn "retrying..."
                sleep $RETRY_INTERVAL
            fi
        done
    fi
}

disable_patch_strict () {
    local modname="$1"

    disable_patch "$modname" || die "failed to disable module $modname"

    if ! wait_for_patch_transition "$modname" ; then
        die "transition stalled for $modname"
    fi
}

remove_module () {
    local modname="$1"

    if ! wait_for_zero_module_ref_count "$modname"; then
        die "failed to unload module $modname (refcnt)"
    fi

    if [[ "$#" -lt 2 || "$2" != "quiet" ]] ; then
        echo "unloading patch module: $modname"
    fi
    # ignore any error here because rmmod can fail if the module used
    # KPATCH_FORCE_UNSAFE.
    rmmod "$modname" 2> /dev/null || return 0
}

unload_module () {
    PATCH="${1//-/_}"
    PATCH="${PATCH%.ko}"
    disable_patch_strict "$PATCH"
    remove_module "$PATCH"
}

get_module_version() {
    MODVER="$(modinfo -F vermagic "$1")" || return 1
    MODVER="${MODVER/ */}"
}

unset MODULE

# Initialize the $SYSFS var.  This only works if the core module has been
# loaded.  Otherwise, the value of $SYSFS doesn't matter at this point anyway,
# and we'll have to call this function again after loading it.
init_sysfs_var

[[ "$#" -lt 1 ]] && usage

# RHEL-specific support options
case "$1" in
"force")
    # For scripting purposes, support "kpatch force unload".
    # Shift out the "force" to avoid the user-prompt check below.
    shift
    ;;
"unload")
    confirm_prompt "WARNING: Red Hat doesn't support unloading of kpatches, continue anyway?" || exit 1
    ;;
esac

case "$1" in
"load")
    [[ "$#" -ne 2 ]] && usage
    case "$2" in
    "--all")
        for i in "$INSTALLDIR/$(uname -r)"/*.ko; do
            [[ -e "$i" ]] || continue
            load_module "$i" || die "failed to load module $i"
        done
        ;;
    *)
        PATCH="$2"
        find_module "$PATCH" || die "can't find $PATCH"
        load_module "$MODULE" || die "failed to load module $PATCH"
        ;;
    esac
    ;;

"unload")
    [[ "$#" -ne 2 ]] && usage
    case "$2" in
    "--all")
        # Versions of linux < 5.1 livepatching require patches to be
        # disabled in the inverse order in which they were enabled.
        while true; do
            nr_disabled=0
            for module in "$SYSFS"/*; do
                modname="$(basename "$module")"

                [[ -e "$module" ]] || continue
                disable_patch "$modname" || continue
                if ! wait_for_patch_transition "$modname" ; then
                    warn "transition stalled for $modname"
                    continue
                fi
                remove_module "$modname"
                nr_disabled=$((nr_disabled + 1))
            done
            if [ $nr_disabled -eq 0 ]; then
                break
            fi
        done

        nr_remaining=0
        for module in "$SYSFS"/*; do
            modname="$(basename "$module")"

            [[ -e "$module" ]] || continue
            nr_remaining=$((nr_remaining + 1))
            warn "failed to unload module $modname"
        done

        if [ $nr_remaining -gt 0 ]; then
            exit 1
        fi
        ;;
    *)
        unload_module "$(basename "$2")" || die "failed to unload module $2"
        ;;
    esac
    ;;

"install")
    KVER="$(uname -r)"
    shift
    options="$(getopt -o k: -l "kernel-version:" -- "$@")" || die "getopt failed"
    eval set -- "$options"
    while [[ $# -gt 0 ]]; do
        case "$1" in
        -k|--kernel-version)
            KVER="$2"
            shift
            ;;
        --)
            [[ -z "$2" ]] && die "no module file specified"
            PATCH="$2"
            ;;
        esac
        shift
    done

    [[ ! -e "$PATCH" ]] && die "$PATCH doesn't exist"
    [[ "${PATCH: -3}" == ".ko" ]] || die "$PATCH isn't a .ko file"

    get_module_version "$PATCH" || die "modinfo failed"
    [[ "$KVER" != "$MODVER" ]] && die "invalid module version $MODVER for kernel $KVER"

    [[ -e "$INSTALLDIR/$KVER/$(basename "$PATCH")" ]] && die "$PATCH is already installed"

    echo "installing $PATCH ($KVER)"
    mkdir -p "$INSTALLDIR/$KVER" || die "failed to create install directory"
    cp -f "$PATCH" "$INSTALLDIR/$KVER" || die "failed to install module $PATCH"
    command -v systemctl > /dev/null 2>&1 && systemctl enable kpatch.service
    ;;

"uninstall")
    KVER="$(uname -r)"
    shift
    options="$(getopt -o k: -l "kernel-version:" -- "$@")" || die "getopt failed"
    eval set -- "$options"
    while [[ $# -gt 0 ]]; do
        case "$1" in
        -k|--kernel-version)
            KVER="$2"
            shift
            ;;
        --)
            [[ -z "$2" ]] && die "no module file specified"
            PATCH="$2"
            [[ "$PATCH" != "$(basename "$PATCH")" ]] && die "please supply patch module name without path"
            ;;
        esac
        shift
    done

    MODULE="$INSTALLDIR/$KVER/$PATCH"
    if [[ ! -f "$MODULE" ]]; then
        mod_name "$PATCH"
        PATCHNAME="$MODNAME"
        for i in "$INSTALLDIR/$KVER"/*; do
            mod_name "$i"
            if [[ "$MODNAME" == "$PATCHNAME" ]]; then
                MODULE="$i"
                break
            fi
        done
    fi

    [[ ! -e "$MODULE" ]] && die "$PATCH is not installed for kernel $KVER"

    echo "uninstalling $PATCH ($KVER)"
    rm -f "$MODULE" || die "failed to uninstall module $PATCH"
    rmdir --ignore-fail-on-non-empty "$INSTALLDIR/$KVER" || die "failed to remove directory $INSTALLDIR/$KVER"

    ;;

"list")
    [[ "$#" -ne 1 ]] && usage
    echo "Loaded patch modules:"
    for module in "$SYSFS"/*; do
        if [[ -e "$module" ]]; then
            modname=$(basename "$module")
            if [[ "$(cat "$module/enabled" 2>/dev/null)" -eq 1 ]]; then
                in_transition "$modname" && state="enabling..." \
                             || state="enabled"
            else
                in_transition "$modname" && state="disabling..." \
                             || state="disabled"
            fi
            echo "$modname [$state]"
        fi
    done
    show_stalled_processes
    echo ""
    echo "Installed patch modules:"
    for kdir in "$INSTALLDIR"/*; do
        [[ -e "$kdir" ]] || continue
        for module in "$kdir"/*.ko; do
            [[ -e "$module" ]] || continue
            mod_name "$module"
            echo "$MODNAME ($(basename "$kdir"))"
        done
    done
    ;;

"info")
    [[ "$#" -ne 2 ]] && usage
    PATCH="$2"
    find_module "$PATCH" || die "can't find $PATCH"
    echo "Patch information for $PATCH:"
    modinfo "$MODULE" || die "failed to get info for module $PATCH"
    ;;

"signal")
    [[ "$#" -ne 1 ]] && usage
    signal_stalled_processes
    ;;

"help"|"-h"|"--help")
    usage
    ;;

"version"|"-v"|"--version")
    echo "$VERSION"
    ;;

*)
    echo "subcommand $1 not recognized"
    usage
    ;;
esac

All system for education purposes only. For more tools: Telegram @jackleet

Mr.X Private Shell

Logo
-
New File | New Folder
Command
SQL