#!/bin/bash
# This script is designed to create a livepatch module for the specified Photon OS kernel version.
# Args:
# -k: Specifies the kernel version. If not set, builds native livepatch
# -p: Patch file list. Need at least one patch file listed here
# -n: Output file name. Will be default if not specified.
# -o: Output folder for livepatch modules.
# -R: Don't set replace flag for the livepatch module. Default is to set the flag.
# --export-debuginfo: Save debug files such as patched vmlinux, changed objs, etc.
# -h/--help: Prints help message
# -d: Use file contents as description field for livepatch module.
# --rpm: Package the kernel module as an rpm
# --rpm-version: Specify the version number of the rpm
# --rpm-release: Specify the release number of the rpm
# --rpm-desc: Specify the description file for the rpm. If not set, it will be the same as the module.
#
# ex)
# With all options enabled, and multiple patches:
# gen_livepatch -k 4.19.247-2.ph3 -o my_dir -n my_livepatch.ko -p my_patch1.patch my_patch2.patch -D description.txt -R --export-debuginfo
# ex)
# All default settings. Must supply at least one patch file though. Builds a livepatch for the current kernel version
# gen_livepatch -p my_patch.patch
#
# If GEN_LIVEPATCH_DEBUG is set to 1, the tmp directory will not be deleted at the end of the script. Useful for debugging purposes.
set -o pipefail
GCC=/usr/bin/gcc
BUILD_DIR="/var/opt/gen_livepatch"
DEFAULT_OUTPUT_FOLDER="$BUILD_DIR/livepatches"
TEMP_DIR="$BUILD_DIR/tmp"
SRC_DIR="$TEMP_DIR/rpmbuild/BUILD"
VERSION_RELEASE_FLAVOR=""
OUTPUT_FOLDER=""
LIVEPATCH_NAME=""
LIVEPATCH_EXT="_klp"
DEBUG_PKGNAME=""
SRC_PKGNAME=""
SPEC_FILENAME=""
VMLINUX_PATH=""
STARTING_DIR="$PWD"
PH_TAG=""
KERNEL_RELEASE=""
KERNEL_FLAVOR=""
KERNEL_VERSION=""
KERNEL_VERSION_RELEASE_TAG=""
KERNEL_RELEASE_TAG=""
IS_RT=0
NON_REPLACE_FLAG=""
EXPORT_DEBUGINFO=0
DEBUGINFO_DIR="$BUILD_DIR/debuginfo"
KPATCH_BUILDDIR="$HOME/.kpatch"
DESC_FILE=""
RPM_DESCFILE=""
PACKAGE_AS_RPM=0
RPM_VERSION=""
RPM_RELEASE=""
BUILD_RPM_SPECFILE="/etc/gen_livepatch/build-rpm.spec"
DEBUGINFO_LOCAL_PATH=""
RPM_MACRO_FILE=""
HAS_DIST_TAG=1
patches=()
# args
# 1. string to match
# 2. array values
match_string_in_array() {
local string_to_match=$1
shift
while (( $# )); do
if [[ "$string_to_match" == "$1" ]]; then
return 0
fi
shift
done
return 1
}
# parse the command line arguments and fill in variables
parse_args() {
# just print help message if no arguments
if [ $# -eq 0 ]; then
print_help 0
elif [[ $1 != -* ]]; then
echo "A flag must be set before any other parameters"
print_help 1
fi
local flag=""
flags=( "-s" "-p" "-v" "-o" "-h" "--help" "-k" "-n" "-R" "--export-debuginfo" "-d" "--rpm" "--rpm-version" "--rpm-release" "--rpm-desc" )
while (( "$#" )); do
if [[ $1 = -* ]]; then
flag=$1
# check to make sure number of args are correct
if ! match_string_in_array $flag ${flags[@]} ; then
error "Unknown option $flag"
elif [[ $1 == -h || $1 == --help ]]; then
print_help 0
elif [[ $1 == -R ]]; then
NON_REPLACE_FLAG="-R"
elif [[ $1 == --export-debuginfo ]]; then
EXPORT_DEBUGINFO=1
elif [[ $1 == --rpm ]]; then
PACKAGE_AS_RPM=1
elif [[ $2 == -* || -z $2 ]]; then
error "$1 needs at least one argument"
elif [[ $3 != -* && $flag != -p && -n $3 ]]; then
error "$1 only takes one argument"
fi
else
case "$flag" in
-p)
patches+=("$1")
;;
-k)
VERSION_RELEASE_FLAVOR=$1
;;
-o)
OUTPUT_FOLDER=$1
;;
-n)
LIVEPATCH_NAME=$1
;;
-d)
DESC_FILE=$1
[ -f "$DESC_FILE" ] || error "Module description file does not exist"
;;
-s)
SRC_RPM_LOCAL_PATH=$1
[ -f "$SRC_RPM_LOCAL_PATH" ] || error "Unable to locate local src rpm at $SRC_RPM_LOCAL_PATH"
;;
-v)
DEBUGINFO_LOCAL_PATH=$1
[ -f "$DEBUGINFO_LOCAL_PATH" ] || error "Unable to locate local debuginfo rpm at $DEBUGINFO_LOCAL_PATH"
;;
--rpm-version)
RPM_VERSION=$1
;;
--rpm-release)
RPM_RELEASE=$1
;;
--rpm-desc)
RPM_DESCFILE=$1
[ -f "$RPM_DESCFILE" ] || error "RPM description file does not exist"
;;
esac
fi
# shift to the next argument
shift
done
if [ -z "$patches" ]; then
error "Please input at least one patch file"
fi
if [ -z "$VERSION_RELEASE_FLAVOR" ]; then
echo "No kernel version specified, building native patch"
VERSION_RELEASE_FLAVOR=$(uname -r)
fi
if [ -z "$LIVEPATCH_NAME" ]; then
echo "No output name specified, using default"
# just use the first 20 characters of the patch file name
local first_patch_name=$(cut -d '.' -f 1 <<< "$(basename "${patches[0]}")")
local cur_datetime=$(date +%d%b%Y-%H_%M_%S)
LIVEPATCH_NAME=${first_patch_name}-${cur_datetime}${LIVEPATCH_EXT}
fi
if [ -z "$OUTPUT_FOLDER" ]; then
echo "Output folder not specified, using default."
echo "Outputting livepatches to: $DEFAULT_OUTPUT_FOLDER"
OUTPUT_FOLDER="$DEFAULT_OUTPUT_FOLDER"
fi
if [[ -z "$RPM_VERSION" && "$PACKAGE_AS_RPM" == 1 ]]; then
echo "RPM version number not specified, setting to 1"
RPM_VERSION=1
fi
if [[ -z "$RPM_RELEASE" && "$PACKAGE_AS_RPM" == 1 ]]; then
echo "RPM release not specified, setting to 1"
RPM_RELEASE=1
fi
# if building an rpm, and rpm description is not specified, use the kernel module desc file if it is set
if [[ ! -z "$DESC_FILE" && "$PACKAGE_AS_RPM" == 1 && -z "$RPM_DESCFILE" ]]; then
echo "Separate RPM description not specified, using module description"
RPM_DESCFILE=$DESC_FILE
fi
# make sure output folder exists
mkdir -p "$OUTPUT_FOLDER"
# remove .ko if it's added, otherwise resulting kernel module will have wrong name
if [[ "${LIVEPATCH_NAME##*.}" == "ko" ]]; then
LIVEPATCH_NAME="${LIVEPATCH_NAME%.*}"
fi
is_rt "$VERSION_RELEASE_FLAVOR"
get_kernel_flavor "$VERSION_RELEASE_FLAVOR"
get_kernel_version "$VERSION_RELEASE_FLAVOR"
get_kernel_release "$VERSION_RELEASE_FLAVOR"
get_photon_tag "$VERSION_RELEASE_FLAVOR"
KERNEL_VERSION_RELEASE_TAG=${KERNEL_VERSION}-${KERNEL_RELEASE}.${PH_TAG}
KERNEL_RELEASE_TAG=${KERNEL_RELEASE}.${PH_TAG}
# Add dist tag to rpm macros file to better handle rpmbuild of linux src rpm
if [ "$(rpm -E %dist)" == "%dist" ]; then
echo "%dist .$PH_TAG" >> "$HOME"/.rpmmacros || error "Failed to define %dist tag in $HOME/.rpmmacros"
# record RPM macro file as whatever file we edited here, so we can reverse
# this change at the end of the build
RPM_MACRO_FILE="$HOME/.rpmmacros"
HAS_DIST_TAG=0
fi
}
# takes in uname -r formatted string
# ex) 4.19.247-2.ph3-aws
get_kernel_flavor() {
# check for rt kernel extension
if [[ $IS_RT != 1 ]]; then
KERNEL_FLAVOR=$(cut -d '-' -f 3 <<< "$1")
if [ -z "$KERNEL_FLAVOR" ]; then
KERNEL_FLAVOR="generic"
fi
else
KERNEL_FLAVOR=rt
fi
}
is_rt() {
local rt_ext="$(cut -d '-' -f 4 <<< "$1")"
if [[ -n $rt_ext ]]; then
IS_RT=1
fi
}
# takes in uname -r formatted string
# returns the release number
get_kernel_release() {
local field_num=2
if [[ $IS_RT == 1 ]]; then
# rt kernel
field_num=3
fi
local release_tag=$(cut -d '-' -f $field_num <<< "$1")
local release=$(cut -d '.' -f 1 <<< "$release_tag")
KERNEL_RELEASE=$release
}
# takes in uname -r formatted string
# gets kernel version only
# ex) 5.10.118
get_kernel_version() {
KERNEL_VERSION=$(cut -d '-' -f 1 <<< "$1")
}
# extracts .phX tag from
# uname -r formatted string
get_photon_tag() {
local field_num=2
if [[ $IS_RT == 1 ]]; then
# rt kernel
field_num=3
fi
local release_tag=$(cut -d '-' -f $field_num <<< "$1")
local kernel_tag=$(cut -d '.' -f 2 <<< "$release_tag")
PH_TAG=$kernel_tag
}
print_config() {
echo -e "\nBuilding livepatch"
echo -e "Linux Version: $KERNEL_VERSION_RELEASE_TAG"
echo -e "Photon OS Version: $PHOTON_VERSION"
echo -e "Photon OS Flavor: $KERNEL_FLAVOR"
echo -e "Patch files: "
for patch in "${patches[@]}"; do
echo -e "\t $(basename "$patch")"
done
}
# Copied from kpatch-build. Used to find gcc version that was used to compile an executable
gcc_version_from_file() {
readelf -p .comment "$1" | grep -m 1 -o 'GCC:.*' || error "Error with readelf"
}
# Copied from kpatch-build. Used to check if GCC versions match
gcc_version_check() {
local target="$1"
local c="$BUILD_DIR/gcc_version_check.c"
local o="$BUILD_DIR/gcc_version_check.o"
local out gccver kgccver
# gcc --version varies between distributions therefore extract version
# by compiling a test file and compare it to vmlinux's version.
echo 'int main(void) {return 0;}' > "$c"
out="$("$GCC" -c -pg -ffunction-sections -o "$o" "$c" 2>&1)"
if [[ $? != 0 ]]; then
error "GCC compilation error"
fi
if [[ -n "$out" ]]; then
echo "gcc >= 4.8 required for -pg -ffunction-settings"
echo "gcc output: $out"
error
fi
gccver="$(gcc_version_from_file "$o")"
kgccver="$(gcc_version_from_file "$target")"
rm -f "$c" "$o"
# ensure gcc version matches that used to build the kernel
if [[ "$gccver" != "$kgccver" ]]; then
echo "gcc/kernel version mismatch"
echo "gcc version: $gccver"
echo "kernel version: $kgccver"
echo "kpatch may have problems when building with the wrong gcc, exiting to be safe..."
error
fi
}
# prints error message and then exits
error() {
if [[ -z "$1" ]]; then
echo "Error! Exiting." 1>&2
else
echo "ERROR: $1" 1>&2
fi
#clean up before exiting
if [[ $GEN_LIVEPATCH_DEBUG != 1 ]]; then
rm -rf $TEMP_DIR
fi
exit 1
}
print_help() {
echo -e "This script is designed to create a livepatch module for the specified Photon OS kernel version and flavor."
echo -e "Arguments:"
echo -e "\t -k: Specifies the kernel version. If not set, builds native livepatch"
echo -e "\t -p: Patch file list. Need at least one patch file listed here"
echo -e "\t -n: Output file name. Will be default if not specified."
echo -e "\t -o: Output directory. Will be default if not specified."
echo -e "\t -R: Don't set the replace flag in the livepatch module. Replace flag is set by default."
echo -e "\t --export-debuginfo: Save debug files such as patched vmlinux, changed objs, etc."
echo -e "\t -h/--help: Print help message"
echo -e "\t -d: Use file contents as description field for livepatch module."
echo -e "\t -s: Specify the location of a local copy of the Linux src rpm to use"
echo -e "\t -v: Specify the location of a local copy of the Linux debuginfo rpm to use"
echo -e "\t --rpm: Package the kernel module as an rpm"
echo -e "\t --rpm-version: Specify the version number of the rpm"
echo -e "\t --rpm-release: Specify the release number of the rpm"
echo -e "\t --rpm-desc: Specify the description file for the rpm. If not set, it will be the same as the module."
exit "$1"
}
install_kernel_dependencies() {
local to_be_installed_pkgs=($(rpm -qpR "$1" | grep -vw rpmlib))
echo -e "The following packages must be installed:\n${to_be_installed_pkgs[*]}\n"
tdnf install -qy "${to_be_installed_pkgs[@]}" || error "Error installing required packages"
}
parse_source_rpm() {
echo -e "\nDownloading and/or processing source rpm"
local src_rpm_url="https://packages.vmware.com/photon/${PHOTON_VERSION}/photon_srpms_${PHOTON_VERSION}_x86_64/$SRC_PKGNAME"
# allow downloading/copying of source rpm from either local or custom urls. Just need these variables to be exported before
# running to enable these options.
if [ -n "${SRC_RPM_LOCAL_PATH}" ]; then
cp "$SRC_RPM_LOCAL_PATH" "$SRC_PKGNAME" || error "Couldn't find local src rpm"
elif [ -n "${SRC_RPM_REMOTE_URL}" ]; then
curl "$SRC_RPM_REMOTE_URL" --output "$SRC_PKGNAME" &> /dev/null || error "Couldn't download remote src rpm"
else
curl "$src_rpm_url" --output "$SRC_PKGNAME" &> /dev/null || error "Couldn't download photon kernel source rpm"
fi
# set up temporary rpm build environment
local rpmdir="%_topdir %(echo $PWD)/rpmbuild"
mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} || error
rpm -i "$SRC_PKGNAME" --define "$rpmdir" || error "Failed to extract spec file"
local config_filename=$(awk '/^Source1:/{print $NF}' rpmbuild/SPECS/linux*.spec)
if [[ "$config_filename" = "config_%{_arch}" ]]; then
config_filename="config_x86_64"
fi
install_kernel_dependencies "$SRC_PKGNAME"
rpmbuild -bp "rpmbuild/SPECS/$SPEC_FILENAME" --define "$rpmdir" &> /dev/null || error "Failed to extract kernel source and create linux source directory"
echo "Copying source files to correct locations, if they exist"
ls rpmbuild/BUILD/fips*canister* &> /dev/null && cp -rT rpmbuild/BUILD/fips*canister* "rpmbuild/BUILD/linux-$KERNEL_VERSION/crypto"
cp rpmbuild/SOURCES/"$config_filename" rpmbuild/BUILD/linux-"$LINUX_VERSION"/.config || error "Failed to locate kernel config file"
[[ -f rpmbuild/SOURCES/fips_canister-kallsyms ]] && cp rpmbuild/SOURCES/fips_canister-kallsyms "rpmbuild/BUILD/linux-$LINUX_VERSION/crypto"
if [[ "$KERNEL_FLAVOR" == "esx" ]] || [[ "$KERNEL_FLAVOR" == "rt" ]]; then
# change m to y for fips canister
cp "rpmbuild/SOURCES/modify_kernel_configs.inc" "rpmbuild/BUILD/linux-$LINUX_VERSION"
pushd "rpmbuild/BUILD/linux-$LINUX_VERSION" &> /dev/null || error
source "modify_kernel_configs.inc"
popd &> /dev/null || error
fi
# make sure vermagic gets the right tag, otherwise kpatch load may fail
# basically just make sure vermagic in modinfo is the same as uname -r
if [[ $KERNEL_FLAVOR == "generic" ]]; then
sed -i s/^CONFIG_LOCALVERSION=\".*\"/CONFIG_LOCALVERSION=\"-$KERNEL_RELEASE_TAG\"/g rpmbuild/BUILD/linux-"$LINUX_VERSION"/.config
else
sed -i s/^CONFIG_LOCALVERSION=\".*\"/CONFIG_LOCALVERSION=\"-$KERNEL_RELEASE_TAG-$KERNEL_FLAVOR\"/g rpmbuild/BUILD/linux-"$LINUX_VERSION"/.config
fi
}
parse_debuginfo_rpm() {
echo -e "\nDownloading debug package and extracting vmlinux"
if [[ -n "$DEBUGINFO_LOCAL_PATH" ]]; then
cp "$DEBUGINFO_LOCAL_PATH" "$DEBUG_PKGNAME"
else
curl "https://packages.vmware.com/photon/$PHOTON_VERSION/photon_debuginfo_${PHOTON_VERSION}_x86_64/x86_64/$DEBUG_PKGNAME" --output "$DEBUG_PKGNAME" &> /dev/null || error
fi
local absolute_path=$(rpm -qlp "$DEBUG_PKGNAME" | grep "vmlinux-$LINUX_VERSION")
# remove the first slash from the path
VMLINUX_PATH=${absolute_path:1}
# extract vmlinux
rpm2cpio "$DEBUG_PKGNAME" | cpio -ivd "./$VMLINUX_PATH" &> /dev/null || error "Couldn't extract vmlinux from $DEBUG_PKGNAME"
}
# sets all the variables for file names
# vmlinux path is set when we parse the debuginfo package
set_filenames_and_paths() {
#determine which photon version this is
PHOTON_VERSION="${PH_TAG//[^0-9]/}".0
#determine which linux version this is
LINUX_VERSION=$(cut -d '-' -f 1 <<< $KERNEL_VERSION_RELEASE_TAG)
#set file paths based on kernel flavor
if [[ "$KERNEL_FLAVOR" == "generic" ]]; then
DEBUG_PKGNAME="linux-debuginfo-$KERNEL_VERSION_RELEASE_TAG.x86_64.rpm"
SRC_PKGNAME="linux-$KERNEL_VERSION_RELEASE_TAG.src.rpm"
SPEC_FILENAME="linux.spec"
else
DEBUG_PKGNAME="linux-$KERNEL_FLAVOR-debuginfo-$KERNEL_VERSION_RELEASE_TAG.x86_64.rpm"
SRC_PKGNAME="linux-$KERNEL_FLAVOR-$KERNEL_VERSION_RELEASE_TAG.src.rpm"
SPEC_FILENAME="linux-$KERNEL_FLAVOR.spec"
fi
}
#executes the kpatch-build command to build the livepatch
kpatch_build() {
#only need -R flag for 3.0, since 3.0 doesn't support klp_replace
#otherwise leave it as set by the user
if [[ $PHOTON_VERSION == "3.0" ]]; then
NON_REPLACE_FLAG="-R"
fi
local skip_cleanup=""
if [[ $EXPORT_DEBUGINFO == 1 ]]; then
skip_cleanup="--skip-cleanup"
fi
local description_file=""
if [ -f "$DESC_FILE" ]; then
description_file="-D $DESC_FILE"
fi
kpatch-build -v "$TEMP_DIR/$VMLINUX_PATH" \
-s "$TEMP_DIR/rpmbuild/BUILD/linux-$LINUX_VERSION" \
-c "$TEMP_DIR/rpmbuild/BUILD/linux-$LINUX_VERSION/.config" \
-j "$(nproc)" \
-n "$LIVEPATCH_NAME" \
-o "$OUTPUT_FOLDER" \
"${patches[@]}" \
$NON_REPLACE_FLAG \
$skip_cleanup \
$description_file \
|| error "Building livepatch module failed."
echo "Livepatch module successfully built"
# save all of the debug info like vmlinux, changed objects, etc if asked to
# vmlinux is the patched vmlinux, not original
if [[ $EXPORT_DEBUGINFO == 1 ]]; then
echo "Saving kpatch-build debug files to $DEBUGINFO_DIR"
# clean out any old files
if [[ -n "$DEBUFINFO_DIR" ]]; then
rm -r "${DEBUGINFO_DIR:?}"/* &> /dev/null
fi
mkdir -p $DEBUGINFO_DIR/patched-debuginfo
cp $SRC_DIR/linux-"$KERNEL_VERSION"/vmlinux* \
$SRC_DIR/linux-"$KERNEL_VERSION"/modules* \
$SRC_DIR/linux-"$KERNEL_VERSION"/Module.symvers \
$DEBUGINFO_DIR/patched-debuginfo
cp -r "$KPATCH_BUILDDIR"/tmp "$DEBUGINFO_DIR"/kpatch-tmp
fi
}
# function to package the required module inside of an rpm
package_module_in_rpm() {
echo -e "\nPreparing to build rpm"
local linux_version
[[ "$KERNEL_FLAVOR" == "generic" ]] && linux_version="$KERNEL_VERSION_RELEASE_TAG" || linux_version="${KERNEL_VERSION_RELEASE_TAG}-${KERNEL_FLAVOR}"
pushd "$TEMP_DIR" > /dev/null 2>&1 || error
# set up temporary rpm build environment
local rpmdir="%_topdir %(echo $PWD)/rpmbuild"
mkdir -p rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} || error
popd > /dev/null 2>&1 || error
cd "$STARTING_DIR" > /dev/null 2>&1 || error
mv "$OUTPUT_FOLDER"/"$LIVEPATCH_NAME".ko "$TEMP_DIR"/rpmbuild/SOURCES || error
# fill in needed info in spec file skeleton
local spec_file="$TEMP_DIR/rpmbuild/SPECS/build-rpm.spec"
cp "$BUILD_RPM_SPECFILE" "$spec_file" || error
sed -i "s/@@VERSION@@/$RPM_VERSION/g" "$spec_file" || error "Filling in RPM vesion for spec file skeleton failed"
sed -i "s/@@RELEASE@@/$RPM_RELEASE/g" "$spec_file" || error "Filling in RPM release for spec file skeleton failed"
sed -i "s/@@LIVEPATCH_NAME@@/$LIVEPATCH_NAME/g" "$spec_file" || error "Filling in livepatch name for spec file skeleton failed"
sed -i "s/@@LINUX_VERSION@@/$linux_version/g" "$spec_file" || error "Filling in linux version for spec file skeleton failed"
if [ -f "$RPM_DESCFILE" ]; then
sed -i "s/@@DESCRIPTION@@/$(cat "$RPM_DESCFILE")/g" "$spec_file" || error "Filling in description for spec file skeleton failed"
else
sed -i "s/@@DESCRIPTION@@/Livepatch module for Linux $linux_version\n/g" "$spec_file" || error "Filling in description for spec file skeleton failed"
fi
echo "Building rpm"
rpmbuild -bb $spec_file --define "$rpmdir" > /dev/null 2>&1 || error "Packaging kernel module as rpm failed"
# should only build for x86_64 arch but put a * there just in case
cp "$TEMP_DIR"/rpmbuild/RPMS/*/"$LIVEPATCH_NAME"*.rpm "$OUTPUT_FOLDER" || error "Current dir: $STARTING_DIR. Failed to save RPM to $OUTPUT_FOLDER"
echo "SUCCESS: Building rpm finished"
}
cleanup() {
if [[ $GEN_LIVEPATCH_DEBUG != 1 ]]; then
rm -rf $TEMP_DIR || error "Failed to delete temp dir: $TEMP_DIR"
fi
[[ "$HAS_DIST_TAG" -eq 0 ]] && sed -i "/%dist .$PH_TAG/d" "$RPM_MACRO_FILE"
}
#cleanup on exit
trap cleanup EXIT SIGINT SIGTERM
#make sure our working directory is clean before we start
rm -rf $TEMP_DIR
#parse command line arguments
parse_args "$@"
#set variables for all filenames/paths
set_filenames_and_paths
print_config
mkdir -p $TEMP_DIR
cd $TEMP_DIR || error
#download, prep, kernel source
parse_source_rpm
#download and extract vmlinux
parse_debuginfo_rpm
#execute kpatch-build with all of the required args
gcc_version_check "$VMLINUX_PATH"
echo -e "\nAll sources ready, building livepatch module..."
# cd back to starting directory so that patch file paths are correct
cd "$STARTING_DIR" || error
kpatch_build
if [[ $PACKAGE_AS_RPM == 1 ]]; then
package_module_in_rpm
fi