From 83dcc8f1441a2a71179ee6ab7a45afdfa1574ff8 Mon Sep 17 00:00:00 2001 From: Mingye Wang Date: Sun, 5 Mar 2023 14:29:42 +0800 Subject: [PATCH] FS_comparison: do sorted comparison to get 10x speed up * New linear time O(n+m) comparison to replace O(nm) thing Gives 10x speed up on /bin/bash * Modify chk_fortify to sastify the new precondition --- checksec | 77 ++++++++++++++++++------------------ src/functions/chk_fortify.sh | 8 ++-- src/functions/fs_funcs.sh | 67 ++++++++++++++++--------------- 3 files changed, 75 insertions(+), 77 deletions(-) diff --git a/checksec b/checksec index b97e3e8..55a22fe 100755 --- a/checksec +++ b/checksec @@ -392,8 +392,8 @@ chk_fortify_file() { FS_chk_func_libc=() FS_functions=() - while IFS='' read -r line; do FS_chk_func_libc+=("$line"); done < <(${readelf} -s "${FS_libc}" 2> /dev/null | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') - while IFS='' read -r line; do FS_functions+=("$line"); done < <(${readelf} -s "${CHK_FORTIFY_FILE}" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') + while IFS='' read -r line; do FS_chk_func_libc+=("$line"); done < <(${readelf} -s "${FS_libc}" 2> /dev/null | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//' | sort -u) + while IFS='' read -r line; do FS_functions+=("$line"); done < <(${readelf} -s "${CHK_FORTIFY_FILE}" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//' | sort -u) echo_message "" "" " /dev/null | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') - while IFS='' read -r line; do FS_functions+=("$line"); done < <(${readelf} -s "${CHK_FORTIFY_PROC}/exe" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') + while IFS='' read -r line; do FS_chk_func_libc+=("$line"); done < <(${readelf} -s "${FS_libc}" 2> /dev/null | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//' | sort -u) + while IFS='' read -r line; do FS_functions+=("$line"); done < <(${readelf} -s "${CHK_FORTIFY_PROC}/exe" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//' | sort -u) echo_message "" "" "\n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }" - elif [[ $FS_elem_functions == $((${#FS_functions[@]} - 1)) ]]; then - echo_message "" "${FS_tmp_func},${FS_tmp_libc},yes\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }" - else - echo_message "" "${FS_tmp_func},${FS_tmp_libc},yes\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }" - fi - fi - ((FS_cnt_total++)) - ((FS_cnt_unchecked++)) - elif [[ ${FS_tmp_func} =~ ^${FS_tmp_libc}(_chk)$ ]]; then - if [[ ${format} == "cli" ]]; then - printf " \033[32m%-30s\033[m | __%s%s\n" "${FS_tmp_func}" "${FS_tmp_libc}" "${FS_end}" - else - if [[ $FS_elem_functions == 0 ]]; then - echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }" - elif [[ $FS_elem_functions == $((${#FS_functions[@]} - 1)) ]]; then - echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }" - else - echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }" - fi - fi - ((FS_cnt_total++)) - ((FS_cnt_checked++)) + # PRECONDITION. FS_chk_func_libc[] and FS_functions[] are both sorted to current locale and unique (sort -u). + for ((FS_elem_libc = 0, FS_elem_functions = 0; \ + FS_elem_libc < ${#FS_chk_func_libc[@]} && \ + FS_elem_functions < ${#FS_functions[@]}; )); do + FS_tmp_func=${FS_functions[$FS_elem_functions]} + FS_tmp_libc=${FS_chk_func_libc[$FS_elem_libc]} + + if [[ ${FS_tmp_func} < ${FS_tmp_libc} ]]; then + ((FS_elem_functions++)) + elif [[ ${FS_tmp_func} == "${FS_tmp_libc}" ]]; then + if [[ ${format} == "cli" ]]; then + printf " \033[31m%-30s\033[m | __%s%s\n" "${FS_tmp_func}" "${FS_tmp_libc}" "${FS_end}" + else + echo_message "" "${FS_tmp_func},${FS_tmp_libc},yes\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }" fi - - done + ((FS_cnt_total++)) + ((FS_cnt_unchecked++)) + ((FS_elem_functions++)) + # HERE LIES DRAGONS. If you advance the libc pointer now, you will miss the _chk! + elif [[ ${FS_tmp_func} < ${FS_tmp_libc}_chk ]]; then + ((FS_elem_functions++)) + elif [[ ${FS_tmp_func} == "${FS_tmp_libc}_chk" ]]; then + if [[ ${format} == "cli" ]]; then + printf " \033[32m%-30s\033[m | __%s%s\n" "${FS_tmp_func}" "${FS_tmp_libc}" "${FS_end}" + else + echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }" + fi + ((FS_cnt_total++)) + ((FS_cnt_checked++)) + ((FS_elem_functions++)) + ((FS_elem_libc++)) + else + # [[ ${FS_tmp_func} > ${FS_tmp_libc}_chk ]] + ((FS_elem_libc++)) + fi done } diff --git a/src/functions/chk_fortify.sh b/src/functions/chk_fortify.sh index 91ce2c6..8a48f90 100644 --- a/src/functions/chk_fortify.sh +++ b/src/functions/chk_fortify.sh @@ -35,8 +35,8 @@ chk_fortify_file() { FS_chk_func_libc=() FS_functions=() - while IFS='' read -r line; do FS_chk_func_libc+=("$line"); done < <(${readelf} -s "${FS_libc}" 2> /dev/null | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') - while IFS='' read -r line; do FS_functions+=("$line"); done < <(${readelf} -s "${CHK_FORTIFY_FILE}" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') + while IFS='' read -r line; do FS_chk_func_libc+=("$line"); done < <(${readelf} -s "${FS_libc}" 2> /dev/null | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//' | sort -u) + while IFS='' read -r line; do FS_functions+=("$line"); done < <(${readelf} -s "${CHK_FORTIFY_FILE}" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//' | sort -u) echo_message "" "" " /dev/null | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') - while IFS='' read -r line; do FS_functions+=("$line"); done < <(${readelf} -s "${CHK_FORTIFY_PROC}/exe" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') + while IFS='' read -r line; do FS_chk_func_libc+=("$line"); done < <(${readelf} -s "${FS_libc}" 2> /dev/null | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//' | sort -u) + while IFS='' read -r line; do FS_functions+=("$line"); done < <(${readelf} -s "${CHK_FORTIFY_PROC}/exe" 2> /dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//' | sort -u) echo_message "" "" "\n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }" - elif [[ $FS_elem_functions == $((${#FS_functions[@]} - 1)) ]]; then - echo_message "" "${FS_tmp_func},${FS_tmp_libc},yes\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }" - else - echo_message "" "${FS_tmp_func},${FS_tmp_libc},yes\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }" - fi - fi - ((FS_cnt_total++)) - ((FS_cnt_unchecked++)) - elif [[ ${FS_tmp_func} =~ ^${FS_tmp_libc}(_chk)$ ]]; then - if [[ ${format} == "cli" ]]; then - printf " \033[32m%-30s\033[m | __%s%s\n" "${FS_tmp_func}" "${FS_tmp_libc}" "${FS_end}" - else - if [[ $FS_elem_functions == 0 ]]; then - echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }" - elif [[ $FS_elem_functions == $((${#FS_functions[@]} - 1)) ]]; then - echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }" - else - echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }" - fi - fi - ((FS_cnt_total++)) - ((FS_cnt_checked++)) + if [[ ${FS_tmp_func} < ${FS_tmp_libc} ]]; then + ((FS_elem_functions++)) + elif [[ ${FS_tmp_func} == "${FS_tmp_libc}" ]]; then + if [[ ${format} == "cli" ]]; then + printf " \033[31m%-30s\033[m | __%s%s\n" "${FS_tmp_func}" "${FS_tmp_libc}" "${FS_end}" + else + echo_message "" "${FS_tmp_func},${FS_tmp_libc},yes\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }" fi - - done + ((FS_cnt_total++)) + ((FS_cnt_unchecked++)) + ((FS_elem_functions++)) + # HERE LIES DRAGONS. If you advance the libc pointer now, you will miss the _chk! + elif [[ ${FS_tmp_func} < ${FS_tmp_libc}_chk ]]; then + ((FS_elem_functions++)) + elif [[ ${FS_tmp_func} == "${FS_tmp_libc}_chk" ]]; then + if [[ ${format} == "cli" ]]; then + printf " \033[32m%-30s\033[m | __%s%s\n" "${FS_tmp_func}" "${FS_tmp_libc}" "${FS_end}" + else + echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " \n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }" + fi + ((FS_cnt_total++)) + ((FS_cnt_checked++)) + ((FS_elem_functions++)) + ((FS_elem_libc++)) + else + # [[ ${FS_tmp_func} > ${FS_tmp_libc}_chk ]] + ((FS_elem_libc++)) + fi done }