Skip to content

Commit

Permalink
FS_comparison: do sorted comparison to get 10x speed up
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Artoria2e5 committed Mar 5, 2023
1 parent 5ec2eb7 commit 83dcc8f
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 77 deletions.
77 changes: 38 additions & 39 deletions checksec
Original file line number Diff line number Diff line change
Expand Up @@ -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 "" "" "<fortify-test name='${CHK_FORTIFY_FILE}' " "{ \"fortify-test\": { \"name\":\"${CHK_FORTIFY_FILE}\" "
FS_libc_check
FS_binary_check
Expand Down Expand Up @@ -433,8 +433,8 @@ chk_fortify_proc() {

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_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 "" "" "<fortify-test name='${name}' pid='${N}' " "{ \"fortify-test\": { \"name\":\"${name}\", \"pid\":\"${N}\" "
FS_libc_check
FS_binary_check
Expand Down Expand Up @@ -882,42 +882,41 @@ FS_comparison() {
echo_message " Fortifiable library functions | Checked function names\n" "" "" ""
echo_message " -------------------------------------------------------\n" "" "" ""

for ((FS_elem_libc = 0; FS_elem_libc < ${#FS_chk_func_libc[@]}; FS_elem_libc++)); do
for ((FS_elem_functions = 0; FS_elem_functions < ${#FS_functions[@]}; FS_elem_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
if [[ ${format} == "cli" ]]; then
printf " \033[31m%-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},yes\n" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='yes' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='yes' />\n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }"
else
echo_message "" "${FS_tmp_func},${FS_tmp_libc},yes\n" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='yes' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='no' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='no' />\n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }"
else
echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='no' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='yes' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='no' />\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
}

Expand Down
8 changes: 4 additions & 4 deletions src/functions/chk_fortify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 "" "" "<fortify-test name='${CHK_FORTIFY_FILE}' " "{ \"fortify-test\": { \"name\":\"${CHK_FORTIFY_FILE}\" "
FS_libc_check
FS_binary_check
Expand Down Expand Up @@ -76,8 +76,8 @@ chk_fortify_proc() {

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_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 "" "" "<fortify-test name='${name}' pid='${N}' " "{ \"fortify-test\": { \"name\":\"${name}\", \"pid\":\"${N}\" "
FS_libc_check
FS_binary_check
Expand Down
67 changes: 33 additions & 34 deletions src/functions/fs_funcs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,42 +34,41 @@ FS_comparison() {
echo_message " Fortifiable library functions | Checked function names\n" "" "" ""
echo_message " -------------------------------------------------------\n" "" "" ""

for ((FS_elem_libc = 0; FS_elem_libc < ${#FS_chk_func_libc[@]}; FS_elem_libc++)); do
for ((FS_elem_functions = 0; FS_elem_functions < ${#FS_functions[@]}; FS_elem_functions++)); do
FS_tmp_func=${FS_functions[$FS_elem_functions]}
FS_tmp_libc=${FS_chk_func_libc[$FS_elem_libc]}
# 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
if [[ ${format} == "cli" ]]; then
printf " \033[31m%-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},yes\n" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='yes' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='yes' />\n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"yes\" }"
else
echo_message "" "${FS_tmp_func},${FS_tmp_libc},yes\n" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='yes' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='no' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='no' />\n" ", \"function\": { \"name\":\"${FS_tmp_func}\", \"libc\":\"${FS_tmp_libc}\", \"fortifiable\":\"no\" }"
else
echo_message "" "${FS_tmp_func},${FS_tmp_libc},no\n" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='no' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='yes' />\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" " <function name='${FS_tmp_func}' libc='${FS_tmp_libc}' fortifiable='no' />\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
}

Expand Down

0 comments on commit 83dcc8f

Please sign in to comment.