#!/bin/bash
#
#
# NAME: compile_kernel.sh
#
# COPY: Copyright 2012 d2@tdhack.com
#
# LEGAL NOTICE: This software is for internal use ONLY. Copying, modifying
# or distributing it without knowledge and/or permission of
# its author is strictly forbidden!
#
# Author of this script can not be held responsible for any
# damage or problems this software may cause (especially
# version modified by third parties).
#
# Any changes should be discussed with author of this script
# or sent to him as diff-patch to let him quickly verify or
# introduce changes made by others.
#
# Remember: You are using this software at your own risk and
# by using it you agree with all above terms of use.
#
#
#
# chpax -ps /usr/sbin/grub-probe
# paxctl -ps /usr/sbin/grub-probe
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
DEBUG=0
HOMEDIR=/home/kernel
MAILRCPT="d2@tdhack.com"
INSTALLLOG=/tmp/installlog.txt
LOCALDATA=${HOMEDIR}/localdata
CURGR=${LOCALDATA}/gr.txt
KRFILE=/tmp/kernel.txt
GRFILE=/tmp/grsec.txt
VSFILE=/tmp/vserver.txt
YESALL=1
if [[ ${DEBUG} == 1 ]]; then
ECHO="echo "
fi
trap sk_handle ERR
function sk_handle() {
LINE=${1}
echo -e "${FERR} *** Fatal Error. Read more recent log from console ***${NC}"
echo -en "${FERR} Continue anyway? (y/n)${NC} "
if [[ ${YESALL} == 1 ]]; then
echo -e "${GREEN}Aborting.${NC}"
exit 1
else
if [[ $(sk_yesno) == 1 ]]; then
echo -e "${GREEN}Aborting.${NC}"
exit 1
else
echo -e "${LRED}Continuing regardless previous errors.${NC}"
fi
fi
}
function sk_checkstatus(){
if [[ $? != 0 ]]; then
sk_mailadmin "An error occured during build, please fix it manually!"
echo -e "Aborting operation."
exit 1
fi
}
function sk_setcolors(){
LRED="\033[1;31m"
RED="\033[0;31m"
FERR="\033[37;41m"
LGREEN="\033[1;32m"
GREEN="\033[0;32m"
LYELLOW="\033[1;33m"
YELLOW="\033[0;33m"
LCYAN="\033[1;36m"
CYAN="\033[0;36m"
LGRAY="\033[0;37m"
GRAY="\033[1;30m"
WHITE="\033[1;37m"
NC="\033[0m"
}
function sk_probe_kernel(){
NEWKERNEL_LINK=`wget -q http://kernel.org -O ${KRFILE};cat ${KRFILE}|sed -n "/
/,/<\/h3>/p"|grep href|cut -d\" -f2`
NEWKERNEL_NAME=`basename ${NEWKERNEL_LINK} 2>/dev/null`
NEWKERNEL_VERS=`echo ${NEWKERNEL_NAME}|sed -r "s,(linux-)|(.tar.bz2),,g"`
#NEWGRSEC_NAME=`wget -q http://grsecurity.net/test.php -O ${GRFILE};cat ${GRFILE}|grep "${NEWKERNEL_VERS}"|grep ".patch"|grep -v pax|sed -r 's,(<[^>]*>)|(\[sig\])|([0-9]{2}(:?/| ))|([0-9]{2}:[0-9]{2}), ,g'|awk '{print $2}'`
NEWGRSEC_NAME=`wget -q http://grsecurity.net/test.php -O ${GRFILE};cat ${GRFILE}|grep "\-${NEWKERNEL_VERS}"|grep ".patch"|grep -v pax|sed -r 's,<[^>]*>|\[sig\]|../../.. ..:.., ,g'|tr " " "\n"|grep "\-${NEWKERNEL_VERS}"|grep ".patch"`
NEWGRSEC_LINK="http://grsecurity.net/test/${NEWGRSEC_NAME}"
#NEWVSERVER=`wget http://linux-vserver.org/Welcome_to_Linux-VServer.org -O /tmp/vserver.txt;cat /tmp/vserver.txt|grep 2.6.31.6|grep diff|grep grsec|awk '{print $6}'|cut -d\" -f2`
echo -e "[+] new kernel link: ${NEWKERNEL_LINK}"
echo -e "[+] new kernel: ${NEWKERNEL_NAME}"
echo -e "[+] new kernel version: ${NEWKERNEL_VERS}"
echo -e "[+] new grsec name: ${NEWGRSEC_NAME}"
echo -e "[+] newgrsec link: ${NEWGRSEC_LINK}"
if [[ ${NEWGRSEC_NAME} ]]; then
echo -e "[+] Matching grsec patch for kernel ${NEWKERNEL_VERS} has been found" | tee -a ${INSTALLLOG}
if [[ -e ${CURGR} ]]; then
OLDGR=`cat ${CURGR}`
if [[ "${OLDGR}" != "${NEWGRSEC_NAME}" ]]; then
echo -e "[+] build new kernel" | tee -a ${INSTALLLOG}
sk_mailadmin "Matching grsec patch for kernel ${NEWKERNEL_VERS} has been found"
cd ${HOMEDIR}/update | tee -a ${INSTALLLOG}
echo -e "[+] fetching new kernel sources ... this will take a while, be patient!" | tee -a ${INSTALLLOG}
${ECHO} wget -q ${NEWKERNEL_LINK} -O ${HOMEDIR}/update/${NEWKERNEL_NAME} | tee -a ${INSTALLLOG}
echo -e "[+] fetching new grsec patch" | tee -a ${INSTALLLOG}
${ECHO} wget -q ${NEWGRSEC_LINK} -O ${HOMEDIR}/update/${NEWGRSEC_NAME} | tee -a ${INSTALLLOG}
echo "${NEWGRSEC_NAME}" > ${CURGR}
sk_buildkernel
else
echo -e "[-] Last compiled kernel is most recent one." | tee -a ${INSTALLLOG}
sk_mailadmin "Last compiled kernel is most recent one."
exit 1
fi
else
echo ${NEWGRSEC_NAME} > ${CURGR}
echo -e "[+] No previous verion found. Build new kernel" | tee -a ${INSTALLLOG}
sk_mailadmin "No previous verion found. Build new kernel"
${ECHO} wget -q ${NEWKERNEL_LINK} -O ${HOMEDIR}/update/${NEWKERNEL_NAME} | tee -a ${INSTALLLOG}
${ECHO} wget -q ${NEWGRSEC_LINK} -O ${HOMEDIR}/update/${NEWGRSEC_NAME} | tee -a ${INSTALLLOG}
sk_buildkernel
fi
else
echo -e "[-] No matching grsec patch for kernel ${NEWKERNEL_VERS} has been found" | tee -a ${INSTALLLOG}
sk_mailadmin "No matching grsec patch for kernel ${NEWKERNEL_VERS} has been found"
fi
}
function sk_buildkernel(){
if [[ `ls ${HOMEDIR}/update` != '' ]]; then
${ECHO} cd ${HOMEDIR}/update
NEWKERNEL=`ls linux-*.tar.bz2|sed -e 's,.tar.bz2,,g'`
NEWGRSEC=`ls *.patch`
if [[ ${NEWKERNEL} == '' ]]; then
echo -e "${RED}[-] No new kernel available. Abort.${NC}" | tee -a ${INSTALLLOG}
exit 1
else
echo -e "${GREEN}[+] Found new kernel:${NC} ${LCYAN} ${NEWKERNEL}${NC}" | tee -a ${INSTALLLOG}
fi
if [[ ${NEWGRSEC} == '' ]]; then
echo -e "${RED}[-] No new grsecs available. Abort.${NC}" | tee -a ${INSTALLLOG}
exit 1
elif [[ ${NEWGRSEC} =~ `echo ${NEWKERNEL}|sed -e 's,linux-,,g'` ]]; then
echo -e "${GREEN}[+] Found new grsec:${NC} ${LCYAN} ${NEWGRSEC}${NC}" | tee -a ${INSTALLLOG}
else
echo -e "${RED}[-] grsec patch is not for this kernel.${NC}" | tee -a ${INSTALLLOG}
exit 1
fi
if [[ -e ../linux/.config ]]; then
${ECHO} cp -pr ../linux/.config . | tee -a ${INSTALLLOG}
elif [[ -e /boot/config-`uname -r` ]]; then
echo -e "[+] using /boot/config-`uname -r` as a config file." | tee -a ${INSTALLLOG}
${ECHO} cp -pr /boot/config-`uname -r` .config
DOBRK=1
else
echo -e "[-] config file not found, using default one" | tee -a ${INSTALLLOG}
fi
${ECHO} tar -jxf *.tar.bz2 | tee -a ${INSTALLLOG}
#NEWKERNEL=`ls -d linux-|grep -v *.tar.bz2`
WORKINGGRSEC=`ls ${NEWKERNEL}/|grep grsecurity`
if [[ (`ls -d ${HOMEDIR}/linux-*|grep ${NEWKERNEL}` != '') && (${WORKINGGRSEC} == ${NEWGRSEC}) ]]; then
echo -e "${RED}[-] Sources${NC} ${LCYAN}${NEWKERNEL}${NC} ${GREEN}exists and is using the same grsec patch Upgrade aborted.${NC}" | tee -a ${INSTALLLOG}
exit 1
fi
if [[ -e ../${NEWKERNEL} ]]; then
HOWMANY=`ls ../|grep ${NEWKERNEL}|wc -l|awk '{print $1}'`
if [[ ${HOWMANY} == '' ]]
then
HOWMANY="0"
fi
${ECHO} mv ../${NEWKERNEL} ../${NEWKERNEL}-bak_${HOWMANY}
fi
${ECHO} mv ${NEWKERNEL} ../
sk_checkstatus
cd ../
${ECHO} sk_delete linux | tee -a ${INSTALLLOG}
${ECHO} ln -s ${NEWKERNEL} linux | tee -a ${INSTALLLOG}
${ECHO} cp -pr ${HOMEDIR}/update/.config linux/ | tee -a ${INSTALLLOG}
${ECHO} cd linux
echo -e "${GREEN}[+] Patching sources${NC}" | tee -a ${INSTALLLOG}
${ECHO} patch -p1 < ${HOMEDIR}/update/${NEWGRSEC} | tee -a ${INSTALLLOG}
${ECHO} cp -pr ${HOMEDIR}/update/${NEWGRSEC} ${HOMEDIR}/linux/ ; checkstatus | tee -a ${INSTALLLOG}
${ECHO} sk_delete localversion-grsec
${ECHO} touch localversion-grsec
if [[ ${DOBRK} == 1 ]]; then
echo -e "[-] you need to do make menuconfig in ${HOMEDIR}/linux/. This is because I have create kernel config from scratch.\n Enable what you want and place it in ${HOMEDIR}/linux/.config, then issue manually:\n export CONCURRENCY_LEVEL=$[`cat /proc/cpuinfo|grep ^processor|wc -l|awk '{print $1}'`] && make-kpkg clean && make-kpkg --rootcmd fakeroot --initrd kernel_image kernel_headers\n Exiting now." | tee -a ${INSTALLLOG}
sk_mailadmin "you need to do make menuconfig in ${HOMEDIR}/linux/"
exit 1
fi
echo -e "${GREEN}[+] Done${NC}" | tee -a ${INSTALLLOG}
${ECHO} cd ${HOMEDIR}/linux
sk_checkstatus
echo -e "${GREEN}[+] Compiling kernel${NC}" | tee -a ${INSTALLLOG}
${ECHO} make-kpkg clean ; checkstatus| tee -a ${INSTALLLOG}
${ECHO} export CONCURRENCY_LEVEL=$[`cat /proc/cpuinfo|grep ^processor|wc -l|awk '{print $1}'`]
${ECHO} make-kpkg --rootcmd fakeroot --initrd kernel_image kernel_headers ; checkstatus | tee -a ${INSTALLLOG}
sk_mailadmin "New kernel ready for installation (run chpax -ps /usr/sbin/grub-probe first)"
else
echo -e "${RED}[-] No new updates available. Abort.${NC}" | tee -a ${INSTALLLOG}
exit 1
fi
}
function sk_mailadmin(){
MAILSUBJECTPREFIX="[kernel] "
MAILSUBJECT="${MAILSUBJECTPREFIX} ${1}"
MAILFILE=/tmp/mailfile.txt
MAILBODY=/tmp/mailbody.txt
echo -e "Details,\n
kernel link: ${NEWKERNEL_LINK}
kernel name: ${NEWKERNEL_NAME}
kernel version: ${NEWKERNEL_VERS}
grsec name: ${NEWGRSEC_NAME}
grsec link: ${NEWGRSEC_LINK}\n\n\n === INSTALLATION LOG === \n\n\n" > ${MAILFILE}
cat ${MAILFILE} ${INSTALLLOG} > ${MAILBODY}
for addr in ${MAILRCPT}; do
mailx -a "FROM: `whoami`@`uname -n`" -s "${MAILSUBJECT}" ${addr} < ${MAILBODY}
done
}
function sk_cleanup(){
for clean in ${INSTALLLOG} ${MAILFILE} ${KRFILE} ${GRFILE} ${MAILBODY} ${HOMEDIR}/update; do
if [[ -e ${clean} ]]; then
${ECHO} sk_delete ${clean} silent
fi
done
if [[ ! -e ${HOMEDIR}/update ]]; then
${ECHO} mkdir -p ${HOMEDIR}/update
fi
if [[ ! -e ${LOCALDATA} ]]; then
${ECHO} mkdir -p ${LOCALDATA}
fi
${ECHO} touch ${CURGR}
${ECHO} cd ${HOMEDIR}
}
function sk_delete(){
# sk_delete file [silent]
if [[ ${DEBUG} == 1 ]]; then
echo -e "*** fname: ${FUNCNAME} ***"
caller 0
fi
if [[ ${#*} == 0 ]]; then
echo -e "usage: ${FUNCNAME} {file} [silent]"
echo -e "example: ${FUNCNAME} /tmp/test.txt silent"
return 0
fi
local sk_deleteWHAT=${1}
local sk_deleteISSILENT=${2}
for removeme in ${sk_deleteWHAT}; do
if [[ (${removeme} != "") && ($(sk_checkvar ${removeme}) == 0) ]]; then
if [[ ${sk_deleteISSILENT} != silent ]]; then
echo -e "${GREEN}Removing${NC} ${LCYAN}${removeme}${NC}"
fi
${ECHO}rm -rf ${removeme} 2>/dev/null
sk_checkstatus $[LINENO-1] ${FUNCNAME}
else
echo -en "${LRED}Can't delete${NC} ${LCYAN}${removeme}${NC} ${LRED}Continue?${NC} (yes/[no]) "
if [[ $(sk_yesno) == 1 ]]; then
echo -e "${RED}Aborting.${NC}"
exit 1
else
echo -e "${LRED}Continuing regardless previous errors.${NC}"
fi
fi
done
}
function sk_checkvar(){
# VAR=$(sk_checkvar ${NAME})
if [[ ${DEBUG} == 1 ]]; then
echo -e "*** fname: ${FUNCNAME} ***"
caller 0
fi
if [[ ${#*} == 0 ]]; then
echo -e "usage: ${FUNCNAME} {var}"
echo -e "example: ${FUNCNAME} /tmp"
return 0
fi
local sk_checkvarVARIABLE="$(sk_removeslashes ${1})"
local sk_checkvarFORBIDDENLIST="/ /usr /root /home /etc /var /tmp /srv /sys /selinux /scripts /sbin /proc /opt /mnt /media /lib32 /lib /export /dev /boot /bin /vol /tftpboot /system /storage /storage2 /platform /net /kernel /home/kernel /devices /data /data1 /data2 /data01 /data01 /cdrom $HOME $HOME/bin"
for forbidden in ${sk_checkvarFORBIDDENLIST}; do
if [[ (${sk_checkvarVARIABLE} == ${forbidden}) || (${sk_checkvarVARIABLE} == ${forbidden}/) ]]; then
#echo -e "${checkvarVARIABLE} contains forbiden string"
local sk_checkvarFORBIDDEN=1
break
else
local sk_checkvarFORBIDDEN=0
fi
done
if [[ ${sk_checkvarFORBIDDEN} == 0 ]]; then
echo 0
else
echo 1
fi
}
function sk_cwhoami(){
# sk_cwhoami root
if [[ ${DEBUG} == 1 ]]
then
echo -e "*** fname: ${FUNCNAME} ***"
caller 0
fi
if [[ ${#*} == 0 ]]
then
echo -e "usage: ${FUNCNAME} {var}"
echo -e "example: ${FUNCNAME} root"
return 0
fi
local sk_cwhoamiREQUIRED_USER=${1}
if [[ `whoami` != ${sk_cwhoamiREQUIRED_USER} ]]
then
echo -e "${RED}[-] You are not${NC} ${LCYAN}${sk_cwhoamiREQUIRED_USER}${NC}${RED}. Aborting.${NC}"
exit 1
fi
}
function sk_removeslashes(){
if [[ ${DEBUG} == 1 ]]
then
echo -e "*** fname: ${FUNCNAME} ***"
caller 0
fi
echo ${1}|sed -e 's,//*,/,g'
}
if [[ ${SSH_CLIENT} != "" ]]; then
sk_setcolors
YESALL=0
fi
sk_cwhoami root
sk_cleanup
sk_probe_kernel
sk_cleanup