Merge pull request #186 from fbelavenuto/patch-cmos-write

Add patch rtc_cmos_write (issue #174)
This commit is contained in:
Fabio Belavenuto 2022-09-22 11:37:56 -03:00 committed by GitHub
commit e3594d5bdc
46 changed files with 94 additions and 42 deletions

View File

@ -1 +1 @@
0.4-alpha9
0.4-alpha10

View File

@ -1,5 +1,5 @@
ARPL_VERSION="0.4-alpha9"
ARPL_VERSION="0.4-alpha10"
# Define paths
TMP_PATH="/tmp"

View File

@ -683,14 +683,14 @@ function make() {
[ ! -f "${ORI_ZIMAGE_FILE}" -o ! -f "${ORI_RDGZ_FILE}" ] && extractDsmFiles
/opt/arpl/zimage-patch.sh | tee -a "${LOG_FILE}"
/opt/arpl/zimage-patch.sh
if [ $? -ne 0 ]; then
dialog --backtitle "`backtitle`" --title "Error" --aspect 18 \
--msgbox "zImage not patched:\n`<"${LOG_FILE}"`" 0 0
return 1
fi
/opt/arpl/ramdisk-patch.sh | tee -a "${LOG_FILE}"
/opt/arpl/ramdisk-patch.sh
if [ $? -ne 0 ]; then
dialog --backtitle "`backtitle`" --title "Error" --aspect 18 \
--msgbox "Ramdisk not patched:\n`<"${LOG_FILE}"`" 0 0

View File

@ -3,8 +3,10 @@
. /opt/arpl/include/functions.sh
. /opt/arpl/include/addons.sh
set -o pipefail # Get exit code from process piped
# Sanity check
[ -f "${ORI_RDGZ_FILE}" ] || die "${ORI_RDGZ_FILE} not found!"
[ -f "${ORI_RDGZ_FILE}" ] || (die "${ORI_RDGZ_FILE} not found!" | tee -a "${LOG_FILE}")
echo -n "Patching Ramdisk"
@ -39,7 +41,7 @@ KVER="`readModelKey "${MODEL}" "builds.${BUILD}.kver"`"
RD_COMPRESSED="`readModelKey "${MODEL}" "builds.${BUILD}.rd-compressed"`"
# Sanity check
[ -z "${PLATFORM}" -o -z "${KVER}" ] && die "ERROR: Configuration for model ${MODEL} and buildnumber ${BUILD} not found."
[ -z "${PLATFORM}" -o -z "${KVER}" ] && (die "ERROR: Configuration for model ${MODEL} and buildnumber ${BUILD} not found." | tee -a "${LOG_FILE}")
declare -A SYNOINFO
declare -A ADDONS
@ -125,7 +127,7 @@ fi
for ADDON in ${!ADDONS[@]}; do
PARAMS=${ADDONS[${ADDON}]}
if ! installAddon ${ADDON}; then
echo "ADDON ${ADDON} not found!" | tee "${LOG_FILE}"
echo "ADDON ${ADDON} not found!" | tee -a "${LOG_FILE}"
exit 1
fi
echo "/addons/${ADDON}.sh \${1} ${PARAMS}" >> "${RAMDISK_PATH}/addons/addons.sh" 2>"${LOG_FILE}" || dieLog

View File

@ -2,8 +2,10 @@
. /opt/arpl/include/functions.sh
set -o pipefail # Get exit code from process piped
# Sanity check
[ -f "${ORI_ZIMAGE_FILE}" ] || die "${ORI_ZIMAGE_FILE} not found!"
[ -f "${ORI_ZIMAGE_FILE}" ] || (die "${ORI_ZIMAGE_FILE} not found!" | tee -a "${LOG_FILE}")
echo -n "Patching zImage"
@ -17,7 +19,6 @@ echo -n "."
echo -n "."
# rebuild zImage
/opt/arpl/vmlinux-to-bzImage.sh "${TMP_PATH}/vmlinux-mod" "${MOD_ZIMAGE_FILE}" >"${LOG_FILE}" 2>&1 || dieLog
echo -n "."
# Update HASH of new DSM zImage
HASH="`sha256sum ${ORI_ZIMAGE_FILE} | awk '{print$1}'`"

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Fabio Belavenuto <belavenuto@gmail.com>
* Copyright (c) 2022 Fabio Belavenuto <belavenuto@gmail.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
@ -28,11 +28,8 @@
* - values of ORs are 1/2/4/8 respectively
* - [const-ptr] is always the same
*
*/
/**
* A quick tool for patching the ramdisk check in the DSM kernel image
* This lets you tinker with the initial ramdisk contents without disabling mount() features and modules loading
*
* Added patch for CMOS_WRITE by Fabio Belavenuto
*
*/
#include <stdio.h>
@ -44,22 +41,25 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <gelf.h>
const int DIR_FWD = 1;
const int DIR_RWD = -1;
/* Variables */
int fd;
int verbose = 1, read_only = 0;
Elf *elfHandle;
GElf_Ehdr elfExecHeader;
uint64_t orPos[4], fileSize, rodataAddr, rodataOffs, initTextOffs;
int fd, verbose = 1, read_only = 0;
Elf *elfHandle;
GElf_Ehdr elfExecHeader;
uint64_t orPos[4], fileSize, rodataAddr, rodataOffs, initTextOffs;
unsigned char *fileData;
/*****************************************************************************/
void errorMsg(char *message) {
fprintf(stderr, "%s\n", message);
void errorMsg(char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(1);
}
@ -125,8 +125,8 @@ void patchBootParams() {
uint64_t newPtrOffset, ptrOffset;
int n;
printf("Patching boot params.\n");
//The function will reside in init code part. We don't care we may potentially search beyond as we expect it to be found
printf("Found .init.text at %lX\n", initTextOffs);
while (initTextOffs < fileSize) {
addr = findPUSH_R12_R15_SEQ(initTextOffs);
if (addr == -1)
@ -160,8 +160,8 @@ void patchBootParams() {
} else if (ptrOffset == newPtrOffset) {
++ec;
}
printf("\t[+] Found LOCK-OR#$idx sequence @ %lX => %02X %02X %02X %02X %02X %02X %02X %02X [RIP+%lX]\n",
pos, fileData[pos], fileData[pos+1], fileData[pos+2], fileData[pos+3], fileData[pos+4],
printf("\t[+] Found LOCK-OR#%d sequence @ %lX => %02X %02X %02X %02X %02X %02X %02X %02X [RIP+%lX]\n",
n, pos, fileData[pos], fileData[pos+1], fileData[pos+2], fileData[pos+3], fileData[pos+4],
fileData[pos+5], fileData[pos+6], fileData[pos+7], newPtrOffset);
}
if (ec != 4) {
@ -175,7 +175,7 @@ void patchBootParams() {
break;
}
if (addr == -1) {
errorMsg("\nFailed to find matching sequences");
errorMsg("\nFailed to find matching sequences\n");
} else {
//Patch offsets
for (n = 0; n < 4; n++) {
@ -197,11 +197,10 @@ uint32_t changeEndian(uint32_t num) {
/*****************************************************************************/
uint64_t findSeq(const char* seq, int len, uint32_t pos, int dir, uint64_t max) {
uint64_t i;
uint64_t i = pos;
i = pos;
do {
if (strncmp((const char*)fileData+i, seq, len) == 0) {
if (memcmp((const char*)fileData+i, seq, len) == 0) {
return i;
}
i += dir;
@ -216,9 +215,9 @@ void patchRamdiskCheck() {
uint64_t printkPos, testPos, jzPos;
const char str[] = "3ramdisk corrupt";
printf("Patching ramdisk check\n");
printf("Patching ramdisk check.\n");
for (pos = rodataOffs; pos < fileSize; pos++) {
if (strncmp(str, (const char*)(fileData + pos), 16) == 0) {
if (memcmp(str, (const char*)(fileData + pos), 16) == 0) {
pos -= rodataOffs;
break;
}
@ -227,17 +226,15 @@ void patchRamdiskCheck() {
printf("LE arg addr: %08lX\n", errPrintAddr);
printkPos = findSeq((const char*)&errPrintAddr, 4, 0, DIR_FWD, -1);
if (printkPos == -1) {
errorMsg("printk pos not found!");
errorMsg("printk pos not found!\n");
}
//double check if it's a MOV reg,VAL (where reg is EAX/ECX/EDX/EBX/ESP/EBP/ESI/EDI)
printkPos -= 3;
if (strncmp((const char*)fileData+printkPos, "\x48\xc7", 2) != 0) {
printf("Expected MOV=>reg before printk error, got %02X %02X\n", fileData[printkPos], fileData[printkPos+1]);
errorMsg("");
if (memcmp((const char*)fileData+printkPos, "\x48\xc7", 2) != 0) {
errorMsg("Expected MOV=>reg before printk error, got %02X %02X\n", fileData[printkPos], fileData[printkPos+1]);
}
if (fileData[printkPos+2] < 0xC0 || fileData[printkPos+2] > 0xC7) {
printf("Expected MOV w/reg operand [C0-C7], got %02X\n", fileData[printkPos+2]);
errorMsg("");
errorMsg("Expected MOV w/reg operand [C0-C7], got %02X\n", fileData[printkPos+2]);
}
printf("Found printk MOV @ %08lX\n", printkPos);
@ -256,6 +253,54 @@ void patchRamdiskCheck() {
fileData[jzPos] = 0xEB;
}
/*****************************************************************************/
void patchCmosWrite() {
uint64_t pos, errPrintAddr;
uint64_t pr_errPos, testPos, callPos;
const char str[] = "3smpboot: %s: this boot have memory training";
printf("Patching call to rtc_cmos_write.\n");
for (pos = rodataOffs; pos < fileSize; pos++) {
if (memcmp(str, (const char*)(fileData + pos), 16) == 0) {
pos -= rodataOffs;
break;
}
}
errPrintAddr = rodataAddr + pos - 1;
printf("LE arg addr: %08lX\n", errPrintAddr);
pr_errPos = findSeq((const char*)&errPrintAddr, 4, 0, DIR_FWD, -1);
if (pr_errPos == -1) {
printf("pr_err pos not found - ignoring.\n"); // Some kernels do not have the call, exit without error
return;
}
//double check if it's a MOV reg,VAL (where reg is EAX/ECX/EDX/EBX/ESP/EBP/ESI/EDI)
pr_errPos -= 3;
if (memcmp((const char*)fileData+pr_errPos, "\x48\xc7", 2) != 0) {
errorMsg("Expected MOV=>reg before pr_err error, got %02X %02X\n", fileData[pr_errPos], fileData[pr_errPos+1]);
}
if (fileData[pr_errPos+2] < 0xC0 || fileData[pr_errPos+2] > 0xC7) {
errorMsg("Expected MOV w/reg operand [C0-C7], got %02X\n", fileData[pr_errPos+2]);
}
printf("Found pr_err MOV @ %08lX\n", pr_errPos);
// now we should seek a reasonable amount (say, up to 64 bytes) for a sequence of
// MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX
testPos = findSeq("\xBE\x48\x00\x00\x00\xBF\xFF\x00\x00\x00\x89\xC3", 12, pr_errPos, DIR_RWD, 64);
if (testPos == -1) {
printf("Failed to find MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX\n");
return;
}
printf("Found MOV ESI, 0x48 => MOV EDI, 0xFF => MOV EBX, EAX @ %08lX\n", testPos);
callPos = testPos + 12;
if (fileData[callPos] != 0xE8) {
errorMsg("Failed to find CALL\n");
}
printf("OK - patching %02X (CALL) to 0x90.. (NOPs) @ %08lX\n",
fileData[callPos], callPos);
for(uint64_t i = 0; i < 5; i++)
fileData[callPos+i] = 0x90;
}
/*****************************************************************************/
int main(int argc, char *argv[]) {
struct stat fileInf;
@ -264,7 +309,7 @@ int main(int argc, char *argv[]) {
char *sectionName;
if (argc != 3) {
errorMsg("Use: kpatch <vmlinux> <output>");
errorMsg("Use: kpatch <vmlinux> <output>\n");
}
if (elf_version(EV_CURRENT) == EV_NONE)
@ -281,13 +326,13 @@ int main(int argc, char *argv[]) {
switch(elf_kind(elfHandle)) {
case ELF_K_NUM:
case ELF_K_NONE:
errorMsg("file type unknown");
errorMsg("file type unknown\n");
break;
case ELF_K_COFF:
errorMsg("COFF binaries not supported");
errorMsg("COFF binaries not supported\n");
break;
case ELF_K_AR:
errorMsg("AR archives not supported");
errorMsg("AR archives not supported\n");
break;
case ELF_K_ELF:
break;
@ -319,8 +364,12 @@ int main(int argc, char *argv[]) {
}
close(fd);
printf("Found .init.text offset @ %lX\n", initTextOffs);
printf("Found .rodata address @ %lX\n", rodataAddr);
printf("Found .rodata offset @ %lX\n", rodataOffs);
patchBootParams();
patchRamdiskCheck();
patchCmosWrite();
if ((fd = open(argv[2], O_WRONLY | O_CREAT, 0644)) == -1) {
errorNum();
}
@ -328,6 +377,6 @@ int main(int argc, char *argv[]) {
errorNum();
}
close(fd);
printf("\n");
printf("Finish!\n");
return 0;
}