int-log-compiler-common.sh 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #!/bin/false This script should be sourced by the other log-compilers
  2. #;**********************************************************************;
  3. # SPDX-License-Identifier: BSD-2-Clause
  4. #
  5. # Copyright (c) 2017 - 2020, Intel Corporation
  6. # Copyright (c) 2018 - 2020, Fraunhofer SIT sponsored by Infineon Technologies AG
  7. #
  8. # All rights reserved.
  9. #;**********************************************************************;
  10. set -u
  11. usage_error ()
  12. {
  13. echo "$0: $*" >&2
  14. print_usage >&2
  15. exit 2
  16. }
  17. print_usage ()
  18. {
  19. cat <<END
  20. Usage:
  21. `basename "$0"` TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
  22. END
  23. }
  24. while test $# -gt 0; do
  25. case $1 in
  26. --help) print_usage; exit $?;;
  27. --) shift; break;;
  28. -*) usage_error "invalid option: '$1'";;
  29. *) break;;
  30. esac
  31. shift
  32. done
  33. OS=$(uname)
  34. sock_tool="unknown"
  35. sock_tool_params=""
  36. if [ "$OS" == "Linux" ]; then
  37. sock_tool="ss"
  38. sock_tool_params="-lntp4"
  39. elif [ "$OS" == "FreeBSD" ]; then
  40. sock_tool="sockstat"
  41. sock_tool_params="-l4"
  42. fi
  43. simulator_bin=""
  44. INTEGRATION_TCTI=$1
  45. TPM20TEST_DEVICE_FILE=""
  46. TPM20TEST_TCTI_NAME=""
  47. TPM20TEST_TCTI=""
  48. TPM20TEST_SOCKET_PORT=""
  49. TPM20TEST_SOCKET_ADDRESS=""
  50. SIM_PORT_DATA=""
  51. case ${INTEGRATION_TCTI} in
  52. "swtpm")
  53. simulator_bin="swtpm"
  54. TPM20TEST_TCTI_NAME="swtpm"
  55. TPM20TEST_SOCKET_ADDRESS="127.0.0.1"
  56. ;;
  57. "mssim")
  58. simulator_bin="tpm_server"
  59. TPM20TEST_TCTI_NAME="socket"
  60. TPM20TEST_SOCKET_ADDRESS="127.0.0.1"
  61. ;;
  62. "device")
  63. simulator_bin=""
  64. TPM20TEST_TCTI_NAME="device"
  65. DEVICE_FILE=$2
  66. TPM20TEST_DEVICE_FILE=${DEVICE_FILE:9}
  67. TPM20TEST_TCTI="${TPM20TEST_TCTI_NAME}:${TPM20TEST_DEVICE_FILE}"
  68. ;;
  69. *)
  70. echo "Wrong INTEGRATION_TCTI exiting.."
  71. exit 1;
  72. ;;
  73. esac
  74. # Verify the running shell and OS environment is sufficient to run these tests.
  75. sanity_test ()
  76. {
  77. # Check special file
  78. if [ ! -e /dev/urandom ]; then
  79. echo "Missing file /dev/urandom; exiting"
  80. exit 1
  81. fi
  82. if [ -z "$(which ${sock_tool})" ]; then
  83. echo "ss not on PATH; exiting"
  84. exit 1
  85. fi
  86. if [[ ! -z ${simulator_bin} && -z "$(which ${simulator_bin})" ]]; then
  87. echo "${simulator_bin} not on PATH; exiting"
  88. exit 1
  89. fi
  90. }
  91. # This function takes a PID as a parameter and determines whether or not the
  92. # process is currently running. If the daemon is running 0 is returned. Any
  93. # other value indicates that the daemon isn't running.
  94. daemon_status ()
  95. {
  96. local pid=$1
  97. if [ $(kill -0 "${pid}" 2> /dev/null) ]; then
  98. echo "failed to detect running daemon with PID: ${pid}";
  99. return 1
  100. fi
  101. return 0
  102. }
  103. # This is a generic function to start a daemon, setup the environment
  104. # variables, redirect output to a log file, store the PID of the daemon
  105. # in a file and disconnect the daemon from the parent shell.
  106. daemon_start ()
  107. {
  108. local daemon_bin="$1"
  109. local daemon_opts="$2"
  110. local daemon_log_file="$3"
  111. local daemon_pid_file="$4"
  112. local daemon_env="$5"
  113. env ${daemon_env} stdbuf -o0 -e0 ${daemon_bin} ${daemon_opts} > ${daemon_log_file} 2>&1 &
  114. local ret=$?
  115. local pid=$!
  116. if [ ${ret} -ne 0 ]; then
  117. echo "failed to start daemon: \"${daemon_bin}\" with env: \"${daemon_env}\""
  118. exit ${ret}
  119. fi
  120. sleep 1
  121. daemon_status "${pid}"
  122. if [ $? -ne 0 ]; then
  123. echo "daemon died after successfully starting in background, check " \
  124. "log file: ${daemon_log_file}"
  125. return 1
  126. fi
  127. echo ${pid} > ${daemon_pid_file}
  128. disown ${pid}
  129. echo "successfully started daemon: ${daemon_bin} with PID: ${pid}"
  130. return 0
  131. }
  132. # function to start the simulator
  133. # This also that we have a private place to store the NVChip file. Since we
  134. # can't tell the simulator what to name this file we must generate a random
  135. # directory under /tmp, move to this directory, start the simulator, then
  136. # return to the old pwd.
  137. simulator_start ()
  138. {
  139. local sim_bin="$1"
  140. local sim_port="$2"
  141. local sim_log_file="$3"
  142. local sim_pid_file="$4"
  143. local sim_tmp_dir="$5"
  144. # simulator port is a random port between 1024 and 65535
  145. cd ${sim_tmp_dir}
  146. if [ "${INTEGRATION_TCTI}" == "mssim" ]; then
  147. daemon_start "${sim_bin}" "-port ${sim_port}" "${sim_log_file}" \
  148. "${sim_pid_file}" ""
  149. elif [ "${INTEGRATION_TCTI}" == "swtpm" ]; then
  150. daemon_start "${sim_bin}" "socket --tpm2 -p ${sim_port} --ctrl type=tcp,port=$((${sim_port}+1)) --log fd=1,level=5 --flags not-need-init --tpmstate dir=${sim_tmp_dir} --locality allow-set-locality" \
  151. "${sim_log_file}" "${sim_pid_file}" ""
  152. else
  153. cd -
  154. return -1
  155. fi
  156. local ret=$?
  157. cd -
  158. return $ret
  159. }
  160. # function to stop a running daemon
  161. # This function takes a single parameter: a file containing the PID of the
  162. # process to be killed. The PID is extracted and the daemon killed.
  163. daemon_stop ()
  164. {
  165. local pid_file=$1
  166. local pid=0
  167. local ret=0
  168. if [ ! -f ${pid_file} ]; then
  169. echo "failed to stop daemon, no pid file: ${pid_file}"
  170. return 1
  171. fi
  172. pid=$(cat ${pid_file})
  173. daemon_status "${pid}"
  174. ret=$?
  175. if [ ${ret} -ne 0 ]; then
  176. echo "failed to detect running daemon with PID: ${pid}";
  177. return ${ret}
  178. fi
  179. kill ${pid}
  180. ret=$?
  181. if [ ${ret} -ne 0 ]; then
  182. echo "failed to kill daemon process with PID: ${pid}"
  183. fi
  184. return ${ret}
  185. }
  186. # Once option processing is done, $@ should be the name of the test executable
  187. # followed by all of the options passed to the test executable.
  188. TEST_BIN=$(realpath "${@: -1}")
  189. TEST_DIR=$(dirname "${@: -1}")
  190. TEST_NAME=$(basename "${TEST_BIN}")
  191. # start an instance of the simulator for the test, have it use a random port
  192. SIM_LOG_FILE=${TEST_BIN}_simulator.log
  193. SIM_PID_FILE=${TEST_BIN}_simulator.pid
  194. SIM_TMP_DIR=$(mktemp -d /tmp/tpm_simulator_XXXXXX)
  195. PORT_MIN=1024
  196. PORT_MAX=65534
  197. BACKOFF_FACTOR=2
  198. BACKOFF_MAX=6
  199. BACKOFF=1
  200. try_simulator_start ()
  201. {
  202. for i in $(seq ${BACKOFF_MAX}); do
  203. SIM_PORT_DATA=$(od -A n -N 2 -t u2 /dev/urandom | awk -v min=${PORT_MIN} -v max=${PORT_MAX} '{print ($1 % (max - min)) + min}')
  204. if [ $(expr ${SIM_PORT_DATA} % 2) -eq 1 ]; then
  205. SIM_PORT_DATA=$((${SIM_PORT_DATA}-1))
  206. fi
  207. SIM_PORT_CMD=$((${SIM_PORT_DATA}+1))
  208. echo "Starting simulator on port ${SIM_PORT_DATA}"
  209. simulator_start ${simulator_bin} ${SIM_PORT_DATA} ${SIM_LOG_FILE} ${SIM_PID_FILE} ${SIM_TMP_DIR}
  210. sleep 1 # give daemon time to bind to ports
  211. if [ ! -s ${SIM_PID_FILE} ] ; then
  212. echo "Simulator PID file is empty or missing. Giving up."
  213. exit 1
  214. fi
  215. PID=$(cat ${SIM_PID_FILE})
  216. echo "simulator PID: ${PID}";
  217. ${sock_tool} ${sock_tool_params} 2> /dev/null | grep "${PID}" | grep "${SIM_PORT_DATA}"
  218. ret_data=$?
  219. ${sock_tool} ${sock_tool_params} 2> /dev/null | grep "${PID}" | grep "${SIM_PORT_CMD}"
  220. ret_cmd=$?
  221. if test $ret_data -eq 0 && test $ret_cmd -eq 0; then
  222. echo "Simulator with PID ${PID} bound to port ${SIM_PORT_DATA} and " \
  223. "${SIM_PORT_CMD} successfully.";
  224. break
  225. fi
  226. echo "Port conflict? Cleaning up PID: ${PID}"
  227. kill "${PID}"
  228. BACKOFF=$((${BACKOFF}*${BACKOFF_FACTOR}))
  229. echo "Failed to start simulator: port ${SIM_PORT_DATA} or " \
  230. "${SIM_PORT_CMD} probably in use. Retrying in ${BACKOFF}."
  231. sleep ${BACKOFF}
  232. if [ $i -eq 10 ]; then
  233. echo "Failed to start simulator after $i tries. Giving up.";
  234. exit 1
  235. fi
  236. done
  237. }