hybrid_platforms_conductor 32.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (244) hide show
  1. checksums.yaml +7 -0
  2. data/bin/check-node +24 -0
  3. data/bin/deploy +12 -0
  4. data/bin/dump_nodes_json +12 -0
  5. data/bin/free_ips +23 -0
  6. data/bin/free_veids +17 -0
  7. data/bin/get_impacted_nodes +43 -0
  8. data/bin/last_deploys +56 -0
  9. data/bin/nodes_to_deploy +104 -0
  10. data/bin/report +10 -0
  11. data/bin/run +39 -0
  12. data/bin/setup +11 -0
  13. data/bin/ssh_config +14 -0
  14. data/bin/test +13 -0
  15. data/bin/topograph +54 -0
  16. data/lib/hybrid_platforms_conductor/action.rb +82 -0
  17. data/lib/hybrid_platforms_conductor/actions_executor.rb +307 -0
  18. data/lib/hybrid_platforms_conductor/bitbucket.rb +123 -0
  19. data/lib/hybrid_platforms_conductor/cmd_runner.rb +188 -0
  20. data/lib/hybrid_platforms_conductor/cmdb.rb +34 -0
  21. data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +78 -0
  22. data/lib/hybrid_platforms_conductor/common_config_dsl/confluence.rb +43 -0
  23. data/lib/hybrid_platforms_conductor/common_config_dsl/file_system_tests.rb +110 -0
  24. data/lib/hybrid_platforms_conductor/common_config_dsl/idempotence_tests.rb +38 -0
  25. data/lib/hybrid_platforms_conductor/config.rb +263 -0
  26. data/lib/hybrid_platforms_conductor/confluence.rb +119 -0
  27. data/lib/hybrid_platforms_conductor/connector.rb +84 -0
  28. data/lib/hybrid_platforms_conductor/credentials.rb +127 -0
  29. data/lib/hybrid_platforms_conductor/current_dir_monitor.rb +42 -0
  30. data/lib/hybrid_platforms_conductor/deployer.rb +598 -0
  31. data/lib/hybrid_platforms_conductor/executable.rb +145 -0
  32. data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +44 -0
  33. data/lib/hybrid_platforms_conductor/hpc_plugins/action/interactive.rb +44 -0
  34. data/lib/hybrid_platforms_conductor/hpc_plugins/action/my_action.rb.sample +79 -0
  35. data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +63 -0
  36. data/lib/hybrid_platforms_conductor/hpc_plugins/action/ruby.rb +69 -0
  37. data/lib/hybrid_platforms_conductor/hpc_plugins/action/scp.rb +61 -0
  38. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/config.rb +78 -0
  39. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_ip.rb +104 -0
  40. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +114 -0
  41. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/my_cmdb.rb.sample +129 -0
  42. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/platform_handlers.rb +66 -0
  43. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +156 -0
  44. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +702 -0
  45. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample +292 -0
  46. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +148 -0
  47. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/my_provisioner.rb.sample +103 -0
  48. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/podman.rb +125 -0
  49. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +522 -0
  50. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/proxmox_waiter.rb +707 -0
  51. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/reserve_proxmox_container +122 -0
  52. data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +69 -0
  53. data/lib/hybrid_platforms_conductor/hpc_plugins/report/mediawiki.rb +164 -0
  54. data/lib/hybrid_platforms_conductor/hpc_plugins/report/my_report_plugin.rb.sample +88 -0
  55. data/lib/hybrid_platforms_conductor/hpc_plugins/report/stdout.rb +61 -0
  56. data/lib/hybrid_platforms_conductor/hpc_plugins/report/templates/confluence_inventory.html.erb +33 -0
  57. data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +137 -0
  58. data/lib/hybrid_platforms_conductor/hpc_plugins/test/can_be_checked.rb +21 -0
  59. data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +112 -0
  60. data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_from_scratch.rb +35 -0
  61. data/lib/hybrid_platforms_conductor/hpc_plugins/test/connection.rb +28 -0
  62. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +44 -0
  63. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_from_scratch.rb +36 -0
  64. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +49 -0
  65. data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +25 -0
  66. data/lib/hybrid_platforms_conductor/hpc_plugins/test/executables.rb +46 -0
  67. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +45 -0
  68. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system_hdfs.rb +45 -0
  69. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +25 -0
  70. data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +77 -0
  71. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +38 -0
  72. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +56 -0
  73. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +54 -0
  74. data/lib/hybrid_platforms_conductor/hpc_plugins/test/linear_strategy.rb +47 -0
  75. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +82 -0
  76. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +120 -0
  77. data/lib/hybrid_platforms_conductor/hpc_plugins/test/my_test_plugin.rb.sample +143 -0
  78. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +74 -0
  79. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ports.rb +85 -0
  80. data/lib/hybrid_platforms_conductor/hpc_plugins/test/private_ips.rb +38 -0
  81. data/lib/hybrid_platforms_conductor/hpc_plugins/test/public_ips.rb +38 -0
  82. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre-meltdown-checker.sh +1930 -0
  83. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +56 -0
  84. data/lib/hybrid_platforms_conductor/hpc_plugins/test/veids.rb +31 -0
  85. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +159 -0
  86. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +122 -0
  87. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/my_test_report.rb.sample +48 -0
  88. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/stdout.rb +120 -0
  89. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/_confluence_errors_status.html.erb +46 -0
  90. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/_confluence_gauge.html.erb +49 -0
  91. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/confluence.html.erb +242 -0
  92. data/lib/hybrid_platforms_conductor/io_router.rb +70 -0
  93. data/lib/hybrid_platforms_conductor/json_dumper.rb +88 -0
  94. data/lib/hybrid_platforms_conductor/logger_helpers.rb +319 -0
  95. data/lib/hybrid_platforms_conductor/mutex_dir +76 -0
  96. data/lib/hybrid_platforms_conductor/nodes_handler.rb +597 -0
  97. data/lib/hybrid_platforms_conductor/parallel_threads.rb +97 -0
  98. data/lib/hybrid_platforms_conductor/platform_handler.rb +188 -0
  99. data/lib/hybrid_platforms_conductor/platforms_handler.rb +118 -0
  100. data/lib/hybrid_platforms_conductor/plugin.rb +53 -0
  101. data/lib/hybrid_platforms_conductor/plugins.rb +101 -0
  102. data/lib/hybrid_platforms_conductor/provisioner.rb +181 -0
  103. data/lib/hybrid_platforms_conductor/report.rb +31 -0
  104. data/lib/hybrid_platforms_conductor/reports_handler.rb +84 -0
  105. data/lib/hybrid_platforms_conductor/services_handler.rb +274 -0
  106. data/lib/hybrid_platforms_conductor/test.rb +141 -0
  107. data/lib/hybrid_platforms_conductor/test_by_service.rb +22 -0
  108. data/lib/hybrid_platforms_conductor/test_report.rb +282 -0
  109. data/lib/hybrid_platforms_conductor/tests_runner.rb +590 -0
  110. data/lib/hybrid_platforms_conductor/thycotic.rb +92 -0
  111. data/lib/hybrid_platforms_conductor/topographer.rb +859 -0
  112. data/lib/hybrid_platforms_conductor/topographer/plugin.rb +20 -0
  113. data/lib/hybrid_platforms_conductor/topographer/plugins/graphviz.rb +127 -0
  114. data/lib/hybrid_platforms_conductor/topographer/plugins/json.rb +72 -0
  115. data/lib/hybrid_platforms_conductor/topographer/plugins/my_topographer_output_plugin.rb.sample +37 -0
  116. data/lib/hybrid_platforms_conductor/topographer/plugins/svg.rb +30 -0
  117. data/lib/hybrid_platforms_conductor/version.rb +5 -0
  118. data/spec/hybrid_platforms_conductor_test.rb +159 -0
  119. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +43 -0
  120. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/interactive_spec.rb +18 -0
  121. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +102 -0
  122. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/ruby_spec.rb +108 -0
  123. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/scp_spec.rb +79 -0
  124. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions_spec.rb +199 -0
  125. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connection_spec.rb +212 -0
  126. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +125 -0
  127. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +50 -0
  128. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connectable_nodes_spec.rb +28 -0
  129. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +448 -0
  130. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +313 -0
  131. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb +32 -0
  132. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +134 -0
  133. data/spec/hybrid_platforms_conductor_test/api/actions_executor/logging_spec.rb +256 -0
  134. data/spec/hybrid_platforms_conductor_test/api/actions_executor/parallel_spec.rb +338 -0
  135. data/spec/hybrid_platforms_conductor_test/api/actions_executor/timeout_spec.rb +101 -0
  136. data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +165 -0
  137. data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +238 -0
  138. data/spec/hybrid_platforms_conductor_test/api/deployer/check_spec.rb +9 -0
  139. data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +243 -0
  140. data/spec/hybrid_platforms_conductor_test/api/deployer/parse_deploy_output_spec.rb +104 -0
  141. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +131 -0
  142. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/docker/Dockerfile +10 -0
  143. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/docker_spec.rb +123 -0
  144. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/podman_spec.rb +211 -0
  145. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/config_dsl_spec.rb +126 -0
  146. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/create_spec.rb +290 -0
  147. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/destroy_spec.rb +43 -0
  148. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/ip_spec.rb +60 -0
  149. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/proxmox.json +3 -0
  150. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/destroy_vm_spec.rb +82 -0
  151. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/expired_containers_spec.rb +786 -0
  152. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/ips_assignment_spec.rb +112 -0
  153. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/other_lxc_containers_resources_spec.rb +190 -0
  154. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/pve_node_resources_spec.rb +200 -0
  155. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/retries_spec.rb +35 -0
  156. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/vm_ids_assignment_spec.rb +67 -0
  157. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/start_spec.rb +79 -0
  158. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/state_spec.rb +28 -0
  159. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/stop_spec.rb +41 -0
  160. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/config_spec.rb +33 -0
  161. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_ip_spec.rb +64 -0
  162. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +133 -0
  163. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/platform_handlers_spec.rb +19 -0
  164. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +446 -0
  165. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb +127 -0
  166. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/git_diff_impacts_spec.rb +318 -0
  167. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/nodes_selectors_spec.rb +132 -0
  168. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/platform_handlers_plugins_api_spec.rb +60 -0
  169. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/several_platforms_spec.rb +58 -0
  170. data/spec/hybrid_platforms_conductor_test/api/platform_handler_spec.rb +97 -0
  171. data/spec/hybrid_platforms_conductor_test/api/platforms_handler_spec.rb +104 -0
  172. data/spec/hybrid_platforms_conductor_test/api/plugins_spec.rb +243 -0
  173. data/spec/hybrid_platforms_conductor_test/api/reports_handler_spec.rb +44 -0
  174. data/spec/hybrid_platforms_conductor_test/api/services_handler/actions_to_deploy_spec.rb +121 -0
  175. data/spec/hybrid_platforms_conductor_test/api/services_handler/deploy_allowed_spec.rb +142 -0
  176. data/spec/hybrid_platforms_conductor_test/api/services_handler/log_info_spec.rb +101 -0
  177. data/spec/hybrid_platforms_conductor_test/api/services_handler/package_spec.rb +388 -0
  178. data/spec/hybrid_platforms_conductor_test/api/services_handler/parse_deploy_output_spec.rb +274 -0
  179. data/spec/hybrid_platforms_conductor_test/api/services_handler/prepare_for_deploy_spec.rb +264 -0
  180. data/spec/hybrid_platforms_conductor_test/api/tests_runner/common_spec.rb +194 -0
  181. data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +37 -0
  182. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_check_spec.rb +194 -0
  183. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_spec.rb +137 -0
  184. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_ssh_spec.rb +257 -0
  185. data/spec/hybrid_platforms_conductor_test/api/tests_runner/platform_spec.rb +110 -0
  186. data/spec/hybrid_platforms_conductor_test/api/tests_runner/reports_spec.rb +367 -0
  187. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +111 -0
  188. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_reports_plugins/confluence_spec.rb +29 -0
  189. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb.rb +166 -0
  190. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb2.rb +93 -0
  191. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others.rb +60 -0
  192. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others2.rb +58 -0
  193. data/spec/hybrid_platforms_conductor_test/executables/check-node_spec.rb +35 -0
  194. data/spec/hybrid_platforms_conductor_test/executables/deploy_spec.rb +35 -0
  195. data/spec/hybrid_platforms_conductor_test/executables/get_impacted_nodes_spec.rb +158 -0
  196. data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +173 -0
  197. data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +283 -0
  198. data/spec/hybrid_platforms_conductor_test/executables/options/actions_executor_spec.rb +28 -0
  199. data/spec/hybrid_platforms_conductor_test/executables/options/cmd_runner_spec.rb +28 -0
  200. data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +67 -0
  201. data/spec/hybrid_platforms_conductor_test/executables/options/deployer_spec.rb +251 -0
  202. data/spec/hybrid_platforms_conductor_test/executables/options/nodes_handler_spec.rb +111 -0
  203. data/spec/hybrid_platforms_conductor_test/executables/options/nodes_selectors_spec.rb +71 -0
  204. data/spec/hybrid_platforms_conductor_test/executables/options/reports_handler_spec.rb +54 -0
  205. data/spec/hybrid_platforms_conductor_test/executables/options/tests_runner_spec.rb +139 -0
  206. data/spec/hybrid_platforms_conductor_test/executables/report_spec.rb +60 -0
  207. data/spec/hybrid_platforms_conductor_test/executables/run_spec.rb +173 -0
  208. data/spec/hybrid_platforms_conductor_test/executables/ssh_config_spec.rb +35 -0
  209. data/spec/hybrid_platforms_conductor_test/executables/test_spec.rb +41 -0
  210. data/spec/hybrid_platforms_conductor_test/helpers/actions_executor_helpers.rb +98 -0
  211. data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +92 -0
  212. data/spec/hybrid_platforms_conductor_test/helpers/cmdb_helpers.rb +37 -0
  213. data/spec/hybrid_platforms_conductor_test/helpers/config_helpers.rb +20 -0
  214. data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +130 -0
  215. data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +149 -0
  216. data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +812 -0
  217. data/spec/hybrid_platforms_conductor_test/helpers/executables_helpers.rb +96 -0
  218. data/spec/hybrid_platforms_conductor_test/helpers/nodes_handler_helpers.rb +20 -0
  219. data/spec/hybrid_platforms_conductor_test/helpers/platform_handler_helpers.rb +35 -0
  220. data/spec/hybrid_platforms_conductor_test/helpers/platforms_handler_helpers.rb +127 -0
  221. data/spec/hybrid_platforms_conductor_test/helpers/plugins_helpers.rb +48 -0
  222. data/spec/hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers.rb +789 -0
  223. data/spec/hybrid_platforms_conductor_test/helpers/reports_handler_helpers.rb +29 -0
  224. data/spec/hybrid_platforms_conductor_test/helpers/services_handler_helpers.rb +20 -0
  225. data/spec/hybrid_platforms_conductor_test/helpers/tests_runner_helpers.rb +38 -0
  226. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/test_plugin_id1.rb +22 -0
  227. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/test_plugin_id2.rb +22 -0
  228. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type/test_plugin_id3.rb +26 -0
  229. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type2/test_plugin_id4.rb +26 -0
  230. data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test.rb +225 -0
  231. data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test2.rb +11 -0
  232. data/spec/hybrid_platforms_conductor_test/report_plugin.rb +35 -0
  233. data/spec/hybrid_platforms_conductor_test/test_action.rb +66 -0
  234. data/spec/hybrid_platforms_conductor_test/test_connector.rb +151 -0
  235. data/spec/hybrid_platforms_conductor_test/test_plugins/global.rb +30 -0
  236. data/spec/hybrid_platforms_conductor_test/test_plugins/node.rb +53 -0
  237. data/spec/hybrid_platforms_conductor_test/test_plugins/node_check.rb +47 -0
  238. data/spec/hybrid_platforms_conductor_test/test_plugins/node_ssh.rb +42 -0
  239. data/spec/hybrid_platforms_conductor_test/test_plugins/platform.rb +50 -0
  240. data/spec/hybrid_platforms_conductor_test/test_plugins/several_checks.rb +50 -0
  241. data/spec/hybrid_platforms_conductor_test/test_provisioner.rb +95 -0
  242. data/spec/hybrid_platforms_conductor_test/tests_report_plugin.rb +49 -0
  243. data/spec/spec_helper.rb +111 -0
  244. metadata +566 -0
@@ -0,0 +1,85 @@
1
+ module HybridPlatformsConductor
2
+
3
+ module HpcPlugins
4
+
5
+ module Test
6
+
7
+ # Various tests on ports
8
+ class Ports < HybridPlatformsConductor::Test
9
+
10
+ # Config DSL extension for this test plugin
11
+ module ConfigDslExtension
12
+
13
+ # List of rules on ports. Each info has the following properties:
14
+ # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule.
15
+ # * *ports* (Array<Integer>): List of ports concerned by this rule.
16
+ # * *state* (Symbol): State those ports should be in. Possible states are:
17
+ # * *opened*: The port should be opened
18
+ # * *closed*: The port should be closed
19
+ # Array< Hash<Symbol, Object> >
20
+ attr_reader :ports_rules
21
+
22
+ # Initialize the DSL
23
+ def init_ports_test
24
+ @ports_rules = []
25
+ end
26
+
27
+ # Give a list of ports that should be opened
28
+ #
29
+ # Parameters::
30
+ # * *ports* (Integer or Array<Integer>): List of ports
31
+ def check_opened_ports(*ports)
32
+ @ports_rules << {
33
+ ports: ports.flatten,
34
+ state: :opened,
35
+ nodes_selectors_stack: current_nodes_selectors_stack
36
+ }
37
+ end
38
+
39
+ # Give a list of ports that should be closed
40
+ #
41
+ # Parameters::
42
+ # * *ports* (Integer or Array<Integer>): List of ports
43
+ def check_closed_ports(*ports)
44
+ @ports_rules << {
45
+ ports: ports.flatten,
46
+ state: :closed,
47
+ nodes_selectors_stack: current_nodes_selectors_stack
48
+ }
49
+ end
50
+
51
+ end
52
+
53
+ self.extend_config_dsl_with ConfigDslExtension, :init_ports_test
54
+
55
+ # Check my_test_plugin.rb.sample documentation for signature details.
56
+ def test_for_node
57
+ @nodes_handler.select_confs_for_node(@node, @config.ports_rules).each do |ports_rule_info|
58
+ node_ip = @nodes_handler.get_host_ip_of(@node)
59
+ ports_rule_info[:ports].each do |port|
60
+ log_debug "Test port #{node_ip}:#{port}"
61
+ port_opened =
62
+ begin
63
+ Socket.tcp(node_ip, port, connect_timeout: 5) { true }
64
+ rescue
65
+ false
66
+ end
67
+ case ports_rule_info[:state]
68
+ when :opened
69
+ error "Port #{port} should be opened but it's not" unless port_opened
70
+ when :closed
71
+ error "Port #{port} should be closed but it's not" if port_opened
72
+ else
73
+ raise "Unknown desired state for port: #{ports_rule_info[:state]}. Please correct this test plugin."
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ end
@@ -0,0 +1,38 @@
1
+ module HybridPlatformsConductor
2
+
3
+ module HpcPlugins
4
+
5
+ module Test
6
+
7
+ # Test that Private IPs are assigned correctly
8
+ class PrivateIps < HybridPlatformsConductor::Test
9
+
10
+ # Check my_test_plugin.rb.sample documentation for signature details.
11
+ def test
12
+ # Get a map of private IPs per node
13
+ @nodes_handler.prefetch_metadata_of @nodes_handler.known_nodes, :private_ips
14
+ private_ips = Hash[@nodes_handler.
15
+ known_nodes.
16
+ map { |node| [node, @nodes_handler.get_private_ips_of(node) || []] }
17
+ ]
18
+
19
+ # Check there are no duplicates
20
+ nodes_per_private_ip = {}
21
+ private_ips.each do |node, private_ips|
22
+ private_ips.each do |private_ip|
23
+ nodes_per_private_ip[private_ip] = [] unless nodes_per_private_ip.key?(private_ip)
24
+ nodes_per_private_ip[private_ip] << node
25
+ end
26
+ end
27
+ nodes_per_private_ip.each do |private_ip, nodes|
28
+ error "Private IP #{private_ip} is used by the following nodes: #{nodes.join(', ')}" if nodes.size > 1
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,38 @@
1
+ module HybridPlatformsConductor
2
+
3
+ module HpcPlugins
4
+
5
+ module Test
6
+
7
+ # Test that Public IPs are assigned correctly
8
+ class PublicIps < HybridPlatformsConductor::Test
9
+
10
+ # Check my_test_plugin.rb.sample documentation for signature details.
11
+ def test
12
+ # Get a map of public IPs per node
13
+ @nodes_handler.prefetch_metadata_of @nodes_handler.known_nodes, :public_ips
14
+ public_ips = Hash[@nodes_handler.
15
+ known_nodes.
16
+ map { |node| [node, @nodes_handler.get_public_ips_of(node) || []] }
17
+ ]
18
+
19
+ # Check there are no duplicates
20
+ nodes_per_public_ip = {}
21
+ public_ips.each do |node, public_ips|
22
+ public_ips.each do |public_ip|
23
+ nodes_per_public_ip[public_ip] = [] unless nodes_per_public_ip.key?(public_ip)
24
+ nodes_per_public_ip[public_ip] << node
25
+ end
26
+ end
27
+ nodes_per_public_ip.each do |public_ip, nodes|
28
+ error "Public IP #{public_ip} is used by the following nodes: #{nodes.join(', ')}" if nodes.size > 1
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,1930 @@
1
+ #! /bin/sh
2
+ # Spectre & Meltdown checker
3
+ #
4
+ # Check for the latest version at:
5
+ # https://github.com/speed47/spectre-meltdown-checker
6
+ # git clone https://github.com/speed47/spectre-meltdown-checker.git
7
+ # or wget meltdown.xae -O spectre-meltdown-checker.sh
8
+ # or curl -L meltdown.xae -o spectre-meltdown-checker.sh
9
+ #
10
+ # Stephane Lesimple
11
+ #
12
+ VERSION='0.35'
13
+
14
+ trap 'exit_cleanup' EXIT
15
+ trap '_warn "interrupted, cleaning up..."; exit_cleanup; exit 1' INT
16
+ exit_cleanup()
17
+ {
18
+ # cleanup the temp decompressed config & kernel image
19
+ [ -n "$dumped_config" ] && [ -f "$dumped_config" ] && rm -f "$dumped_config"
20
+ [ -n "$vmlinuxtmp" ] && [ -f "$vmlinuxtmp" ] && rm -f "$vmlinuxtmp"
21
+ [ "$mounted_debugfs" = 1 ] && umount /sys/kernel/debug 2>/dev/null
22
+ [ "$insmod_cpuid" = 1 ] && rmmod cpuid 2>/dev/null
23
+ [ "$insmod_msr" = 1 ] && rmmod msr 2>/dev/null
24
+ }
25
+
26
+ show_usage()
27
+ {
28
+ # shellcheck disable=SC2086
29
+ cat <<EOFSPECTRE
30
+ Usage:
31
+ Live mode: $(basename $0) [options] [--live]
32
+ Offline mode: $(basename $0) [options] [--kernel <vmlinux_file>] [--config <kernel_config>] [--map <kernel_map_file>]
33
+
34
+ Modes:
35
+ Two modes are available.
36
+
37
+ First mode is the "live" mode (default), it does its best to find information about the currently running kernel.
38
+ To run under this mode, just start the script without any option (you can also use --live explicitly)
39
+
40
+ Second mode is the "offline" mode, where you can inspect a non-running kernel.
41
+ You'll need to specify the location of the vmlinux file, config and System.map files:
42
+
43
+ --kernel vmlinux_file Specify a (possibly compressed) vmlinux file
44
+ --config kernel_config Specify a kernel config file
45
+ --map kernel_map_file Specify a kernel System.map file
46
+
47
+ Options:
48
+ --no-color Don't use color codes
49
+ --verbose, -v Increase verbosity level
50
+ --no-sysfs Don't use the /sys interface even if present
51
+ --sysfs-only Only use the /sys interface, don't run our own checks
52
+ --coreos Special mode for CoreOS (use an ephemeral toolbox to inspect kernel)
53
+ --batch text Produce machine readable output, this is the default if --batch is specified alone
54
+ --batch json Produce JSON output formatted for Puppet, Ansible, Chef...
55
+ --batch nrpe Produce machine readable output formatted for NRPE
56
+ --batch prometheus Produce output for consumption by prometheus-node-exporter
57
+ --variant [1,2,3] Specify which variant you'd like to check, by default all variants are checked
58
+ Can be specified multiple times (e.g. --variant 2 --variant 3)
59
+
60
+ Return codes:
61
+ 0 (not vulnerable), 2 (vulnerable), 3 (unknown), 255 (error)
62
+
63
+ IMPORTANT:
64
+ A false sense of security is worse than no security at all.
65
+ Please use the --disclaimer option to understand exactly what this script does.
66
+
67
+ EOFSPECTRE
68
+ }
69
+
70
+ show_disclaimer()
71
+ {
72
+ cat <<EOFSPECTRE
73
+ Disclaimer:
74
+
75
+ This tool does its best to determine whether your system is immune (or has proper mitigations in place) for the
76
+ collectively named "speculative execution" vulnerabilities. It doesn't attempt to run any kind of exploit, and can't guarantee
77
+ that your system is secure, but rather helps you verifying whether your system has the known correct mitigations in place.
78
+ However, some mitigations could also exist in your kernel that this script doesn't know (yet) how to detect, or it might
79
+ falsely detect mitigations that in the end don't work as expected (for example, on backported or modified kernels).
80
+
81
+ Your system exposure also depends on your CPU. As of now, AMD and ARM processors are marked as immune to some or all of these
82
+ vulnerabilities (except some specific ARM models). All Intel processors manufactured since circa 1995 are thought to be vulnerable,
83
+ except some specific/old models, such as some early Atoms. Whatever processor one uses, one might seek more information
84
+ from the manufacturer of that processor and/or of the device in which it runs.
85
+
86
+ The nature of the discovered vulnerabilities being quite new, the lanprdape of vulnerable processors can be expected
87
+ to change over time, which is why this script makes the assumption that all CPUs are vulnerable, except if the manufacturer
88
+ explicitly stated otherwise in a verifiable public announcement.
89
+
90
+ Please also note that for Spectre vulnerabilities, all software can possibly be exploited, this tool only verifies that the
91
+ kernel (which is the core of the system) you're using has the proper protections in place. Verifying all the other software
92
+ is out of the scope of this tool. As a general measure, ensure you always have the most up to date stable versions of all
93
+ the softwares you use, especially for those who are exposed to the world, such as network daemons and browsers.
94
+
95
+ This tool has been released in the hope that it'll be useful, but don't use it to jump to conclusions about your security.
96
+
97
+ EOFSPECTRE
98
+ }
99
+
100
+ # parse options
101
+ opt_kernel=''
102
+ opt_config=''
103
+ opt_map=''
104
+ opt_live_explicit=0
105
+ opt_live=1
106
+ opt_no_color=0
107
+ opt_batch=0
108
+ opt_batch_format="text"
109
+ opt_verbose=1
110
+ opt_variant1=0
111
+ opt_variant2=0
112
+ opt_variant3=0
113
+ opt_allvariants=1
114
+ opt_no_sysfs=0
115
+ opt_sysfs_only=0
116
+ opt_coreos=0
117
+
118
+ global_critical=0
119
+ global_unknown=0
120
+ nrpe_vuln=""
121
+
122
+ # find a sane `echo` command
123
+ # we'll try to avoid using shell builtins that might not take options
124
+ if which echo >/dev/null 2>&1; then
125
+ echo_cmd=$(which echo)
126
+ else
127
+ [ -x /bin/echo ] && echo_cmd=/bin/echo
128
+ [ -x /system/bin/echo ] && echo_cmd=/system/bin/echo
129
+ fi
130
+ # still empty ? fallback to builtin
131
+ [ -z "$echo_cmd" ] && echo_cmd=echo
132
+ __echo()
133
+ {
134
+ opt="$1"
135
+ shift
136
+ _msg="$*"
137
+
138
+ if [ "$opt_no_color" = 1 ] ; then
139
+ # strip ANSI color codes
140
+ # some sed versions (i.e. toybox) can't seem to handle
141
+ # \033 aka \x1B correctly, so do it for them.
142
+ _ctrlchar=$($echo_cmd -e "\033")
143
+ _msg=$($echo_cmd -e "$_msg" | sed -r "s/$_ctrlchar\[([0-9][0-9]?(;[0-9][0-9]?)?)?m//g")
144
+ fi
145
+ # shellcheck disable=SC2086
146
+ $echo_cmd $opt -e "$_msg"
147
+ }
148
+
149
+ _echo()
150
+ {
151
+ if [ "$opt_verbose" -ge "$1" ]; then
152
+ shift
153
+ __echo '' "$*"
154
+ fi
155
+ }
156
+
157
+ _echo_nol()
158
+ {
159
+ if [ "$opt_verbose" -ge "$1" ]; then
160
+ shift
161
+ __echo -n "$*"
162
+ fi
163
+ }
164
+
165
+ _warn()
166
+ {
167
+ _echo 0 "\033[31m$*\033[0m" >&2
168
+ }
169
+
170
+ _info()
171
+ {
172
+ _echo 1 "$*"
173
+ }
174
+
175
+ _info_nol()
176
+ {
177
+ _echo_nol 1 "$*"
178
+ }
179
+
180
+ _verbose()
181
+ {
182
+ _echo 2 "$*"
183
+ }
184
+
185
+ _verbose_nol()
186
+ {
187
+ _echo_nol 2 "$*"
188
+ }
189
+
190
+ _debug()
191
+ {
192
+ _echo 3 "\033[34m(debug) $*\033[0m"
193
+ }
194
+
195
+ is_cpu_vulnerable_cached=0
196
+ _is_cpu_vulnerable_cached()
197
+ {
198
+ # shellcheck disable=SC2086
199
+ [ "$1" = 1 ] && return $variant1
200
+ # shellcheck disable=SC2086
201
+ [ "$1" = 2 ] && return $variant2
202
+ # shellcheck disable=SC2086
203
+ [ "$1" = 3 ] && return $variant3
204
+ echo "$0: error: invalid variant '$1' passed to is_cpu_vulnerable()" >&2
205
+ exit 255
206
+ }
207
+
208
+ is_cpu_vulnerable()
209
+ {
210
+ # param: 1, 2 or 3 (variant)
211
+ # returns 0 if vulnerable, 1 if not vulnerable
212
+ # (note that in shell, a return of 0 is success)
213
+ # by default, everything is vulnerable, we work in a "whitelist" logic here.
214
+ # usage: is_cpu_vulnerable 2 && do something if vulnerable
215
+ if [ "$is_cpu_vulnerable_cached" = 1 ]; then
216
+ _is_cpu_vulnerable_cached "$1"
217
+ return $?
218
+ fi
219
+
220
+ variant1=''
221
+ variant2=''
222
+ variant3=''
223
+
224
+ if is_cpu_specex_free; then
225
+ variant1=immune
226
+ variant2=immune
227
+ variant3=immune
228
+ elif [ "$cpu_vendor" = GenuineIntel ]; then
229
+ # Intel
230
+ # https://github.com/crozone/SpectrePoC/issues/1 ^F E5200 => spectre 2 not vulnerable
231
+ # https://github.com/paboldin/meltdown-exploit/issues/19 ^F E5200 => meltdown vulnerable
232
+ # model name : Pentium(R) Dual-Core CPU E5200 @ 2.50GHz
233
+ if grep -qE '^model name.+ Pentium\(R\) Dual-Core[[:space:]]+CPU[[:space:]]+E[0-9]{4}K? ' /proc/cpuinfo; then
234
+ variant1=vuln
235
+ [ -z "$variant2" ] && variant2=immune
236
+ variant3=vuln
237
+ fi
238
+ if [ "$capabilities_rdcl_no" = 1 ]; then
239
+ # capability bit for future Intel processor that will explicitly state
240
+ # that they're not vulnerable to Meltdown
241
+ # this var is set in check_cpu()
242
+ variant3=immune
243
+ _debug "is_cpu_vulnerable: RDCL_NO is set so not vuln to meltdown"
244
+ fi
245
+ elif [ "$cpu_vendor" = AuthenticAMD ]; then
246
+ # AMD revised their statement about variant2 => vulnerable
247
+ # https://www.amd.com/en/corporate/speculative-execution
248
+ variant1=vuln
249
+ variant2=vuln
250
+ [ -z "$variant3" ] && variant3=immune
251
+ elif [ "$cpu_vendor" = ARM ]; then
252
+ # ARM
253
+ # reference: https://developer.arm.com/support/security-update
254
+ # some devices (phones or other) have several ARMs and as such different part numbers,
255
+ # an example is "bigLITTLE". we shouldn't rely on the first CPU only, so we check the whole list
256
+ i=0
257
+ for cpupart in $cpu_part_list
258
+ do
259
+ i=$(( i + 1 ))
260
+ # do NOT quote $cpu_arch_list below
261
+ # shellcheck disable=SC2086
262
+ cpuarch=$(echo $cpu_arch_list | awk '{ print $'$i' }')
263
+ _debug "checking cpu$i: <$cpupart> <$cpuarch>"
264
+ # some kernels report AArch64 instead of 8
265
+ [ "$cpuarch" = "AArch64" ] && cpuarch=8
266
+ if [ -n "$cpupart" ] && [ -n "$cpuarch" ]; then
267
+ # Cortex-R7 and Cortex-R8 are real-time and only used in medical devices or such
268
+ # I can't find their CPU part number, but it's probably not that useful anyway
269
+ # model R7 R8 A9 A15 A17 A57 A72 A73 A75
270
+ # part ? ? 0xc09 0xc0f 0xc0e 0xd07 0xd08 0xd09 0xd0a
271
+ # arch 7? 7? 7 7 7 8 8 8 8
272
+ #
273
+ # variant 1 & variant 2
274
+ if [ "$cpuarch" = 7 ] && echo "$cpupart" | grep -Eq '^0x(c09|c0f|c0e)$'; then
275
+ # armv7 vulnerable chips
276
+ _debug "checking cpu$i: this armv7 vulnerable to spectre 1 & 2"
277
+ variant1=vuln
278
+ variant2=vuln
279
+ elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -Eq '^0x(d07|d08|d09|d0a)$'; then
280
+ # armv8 vulnerable chips
281
+ _debug "checking cpu$i: this armv8 vulnerable to spectre 1 & 2"
282
+ variant1=vuln
283
+ variant2=vuln
284
+ else
285
+ _debug "checking cpu$i: this arm non vulnerable to 1 & 2"
286
+ # others are not vulnerable
287
+ [ -z "$variant1" ] && variant1=immune
288
+ [ -z "$variant2" ] && variant2=immune
289
+ fi
290
+
291
+ # for variant3, only A75 is vulnerable
292
+ if [ "$cpuarch" = 8 ] && [ "$cpupart" = 0xd0a ]; then
293
+ _debug "checking cpu$i: arm A75 vulnerable to meltdown"
294
+ variant3=vuln
295
+ else
296
+ _debug "checking cpu$i: this arm non vulnerable to meltdown"
297
+ [ -z "$variant3" ] && variant3=immune
298
+ fi
299
+ fi
300
+ _debug "is_cpu_vulnerable: for cpu$i and so far, we have <$variant1> <$variant2> <$variant3>"
301
+ done
302
+ fi
303
+ _debug "is_cpu_vulnerable: temp results are <$variant1> <$variant2> <$variant3>"
304
+ # if at least one of the cpu is vulnerable, then the system is vulnerable
305
+ [ "$variant1" = "immune" ] && variant1=1 || variant1=0
306
+ [ "$variant2" = "immune" ] && variant2=1 || variant2=0
307
+ [ "$variant3" = "immune" ] && variant3=1 || variant3=0
308
+ _debug "is_cpu_vulnerable: final results are <$variant1> <$variant2> <$variant3>"
309
+ is_cpu_vulnerable_cached=1
310
+ _is_cpu_vulnerable_cached "$1"
311
+ return $?
312
+ }
313
+
314
+ is_cpu_specex_free()
315
+ {
316
+ # return true (0) if the CPU doesn't do speculative execution, false (1) if it does.
317
+ # if it's not in the list we know, return false (1).
318
+ # source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n882
319
+ # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CEDARVIEW, X86_FEATURE_ANY },
320
+ # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CLOVERVIEW, X86_FEATURE_ANY },
321
+ # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_LINCROFT, X86_FEATURE_ANY },
322
+ # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PENWELL, X86_FEATURE_ANY },
323
+ # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PINEVIEW, X86_FEATURE_ANY },
324
+ # { X86_VENDOR_CENTAUR, 5 },
325
+ # { X86_VENDOR_INTEL, 5 },
326
+ # { X86_VENDOR_NSC, 5 },
327
+ # { X86_VENDOR_ANY, 4 },
328
+ parse_cpu_details
329
+ if [ "$cpu_vendor" = GenuineIntel ]; then
330
+ if [ "$cpu_family" = 6 ]; then
331
+ if [ "$cpu_model" = "$INTEL_FAM6_ATOM_CEDARVIEW" ] || \
332
+ [ "$cpu_model" = "$INTEL_FAM6_ATOM_CLOVERVIEW" ] || \
333
+ [ "$cpu_model" = "$INTEL_FAM6_ATOM_LINCROFT" ] || \
334
+ [ "$cpu_model" = "$INTEL_FAM6_ATOM_PENWELL" ] || \
335
+ [ "$cpu_model" = "$INTEL_FAM6_ATOM_PINEVIEW" ]; then
336
+ return 0
337
+ fi
338
+ elif [ "$cpu_family" = 5 ]; then
339
+ return 0
340
+ fi
341
+ fi
342
+ [ "$cpu_family" = 4 ] && return 0
343
+ return 1
344
+ }
345
+
346
+ show_header()
347
+ {
348
+ _info "Spectre and Meltdown mitigation detection tool v$VERSION"
349
+ _info
350
+ }
351
+
352
+ parse_opt_file()
353
+ {
354
+ # parse_opt_file option_name option_value
355
+ option_name="$1"
356
+ option_value="$2"
357
+ if [ -z "$option_value" ]; then
358
+ show_header
359
+ show_usage
360
+ echo "$0: error: --$option_name expects one parameter (a file)" >&2
361
+ exit 1
362
+ elif [ ! -e "$option_value" ]; then
363
+ show_header
364
+ echo "$0: error: couldn't find file $option_value" >&2
365
+ exit 1
366
+ elif [ ! -f "$option_value" ]; then
367
+ show_header
368
+ echo "$0: error: $option_value is not a file" >&2
369
+ exit 1
370
+ elif [ ! -r "$option_value" ]; then
371
+ show_header
372
+ echo "$0: error: couldn't read $option_value (are you root?)" >&2
373
+ exit 1
374
+ fi
375
+ echo "$option_value"
376
+ exit 0
377
+ }
378
+
379
+ while [ -n "$1" ]; do
380
+ if [ "$1" = "--kernel" ]; then
381
+ opt_kernel=$(parse_opt_file kernel "$2"); ret=$?
382
+ [ $ret -ne 0 ] && exit 255
383
+ shift 2
384
+ opt_live=0
385
+ elif [ "$1" = "--config" ]; then
386
+ opt_config=$(parse_opt_file config "$2"); ret=$?
387
+ [ $ret -ne 0 ] && exit 255
388
+ shift 2
389
+ opt_live=0
390
+ elif [ "$1" = "--map" ]; then
391
+ opt_map=$(parse_opt_file map "$2"); ret=$?
392
+ [ $ret -ne 0 ] && exit 255
393
+ shift 2
394
+ opt_live=0
395
+ elif [ "$1" = "--live" ]; then
396
+ opt_live_explicit=1
397
+ shift
398
+ elif [ "$1" = "--no-color" ]; then
399
+ opt_no_color=1
400
+ shift
401
+ elif [ "$1" = "--no-sysfs" ]; then
402
+ opt_no_sysfs=1
403
+ shift
404
+ elif [ "$1" = "--sysfs-only" ]; then
405
+ opt_sysfs_only=1
406
+ shift
407
+ elif [ "$1" = "--coreos" ]; then
408
+ opt_coreos=1
409
+ shift
410
+ elif [ "$1" = "--coreos-within-toolbox" ]; then
411
+ # don't use directly: used internally by --coreos
412
+ opt_coreos=0
413
+ shift
414
+ elif [ "$1" = "--batch" ]; then
415
+ opt_batch=1
416
+ opt_verbose=0
417
+ shift
418
+ case "$1" in
419
+ text|nrpe|json|prometheus) opt_batch_format="$1"; shift;;
420
+ --*) ;; # allow subsequent flags
421
+ '') ;; # allow nothing at all
422
+ *)
423
+ echo "$0: error: unknown batch format '$1'" >&2
424
+ echo "$0: error: --batch expects a format from: text, nrpe, json" >&2
425
+ exit 255
426
+ ;;
427
+ esac
428
+ elif [ "$1" = "-v" ] || [ "$1" = "--verbose" ]; then
429
+ opt_verbose=$(( opt_verbose + 1 ))
430
+ shift
431
+ elif [ "$1" = "--variant" ]; then
432
+ if [ -z "$2" ]; then
433
+ echo "$0: error: option --variant expects a parameter (1, 2 or 3)" >&2
434
+ exit 255
435
+ fi
436
+ case "$2" in
437
+ 1) opt_variant1=1; opt_allvariants=0;;
438
+ 2) opt_variant2=1; opt_allvariants=0;;
439
+ 3) opt_variant3=1; opt_allvariants=0;;
440
+ *)
441
+ echo "$0: error: invalid parameter '$2' for --variant, expected either 1, 2 or 3" >&2;
442
+ exit 255
443
+ ;;
444
+ esac
445
+ shift 2
446
+ elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
447
+ show_header
448
+ show_usage
449
+ exit 0
450
+ elif [ "$1" = "--version" ]; then
451
+ opt_no_color=1
452
+ show_header
453
+ exit 0
454
+ elif [ "$1" = "--disclaimer" ]; then
455
+ show_header
456
+ show_disclaimer
457
+ exit 0
458
+ else
459
+ show_header
460
+ show_usage
461
+ echo "$0: error: unknown option '$1'"
462
+ exit 255
463
+ fi
464
+ done
465
+
466
+ show_header
467
+
468
+ if [ "$opt_no_sysfs" = 1 ] && [ "$opt_sysfs_only" = 1 ]; then
469
+ _warn "Incompatible options specified (--no-sysfs and --sysfs-only), aborting"
470
+ exit 255
471
+ fi
472
+
473
+ # print status function
474
+ pstatus()
475
+ {
476
+ if [ "$opt_no_color" = 1 ]; then
477
+ _info_nol "$2"
478
+ else
479
+ case "$1" in
480
+ red) col="\033[41m\033[30m";;
481
+ green) col="\033[42m\033[30m";;
482
+ yellow) col="\033[43m\033[30m";;
483
+ blue) col="\033[44m\033[30m";;
484
+ *) col="";;
485
+ esac
486
+ _info_nol "$col $2 \033[0m"
487
+ fi
488
+ [ -n "$3" ] && _info_nol " ($3)"
489
+ _info
490
+ }
491
+
492
+ # Print the final status of a vulnerability (incl. batch mode)
493
+ # Arguments are: CVE UNK/OK/VULN description
494
+ pvulnstatus()
495
+ {
496
+ if [ "$opt_batch" = 1 ]; then
497
+ case "$1" in
498
+ CVE-2017-5753) aka="SPECTRE VARIANT 1";;
499
+ CVE-2017-5715) aka="SPECTRE VARIANT 2";;
500
+ CVE-2017-5754) aka="MELTDOWN";;
501
+ esac
502
+
503
+ case "$opt_batch_format" in
504
+ text) _echo 0 "$1: $2 ($3)";;
505
+ json)
506
+ case "$2" in
507
+ UNK) is_vuln="null";;
508
+ VULN) is_vuln="true";;
509
+ OK) is_vuln="false";;
510
+ esac
511
+ json_output="${json_output:-[}{\"NAME\":\"$aka\",\"CVE\":\"$1\",\"VULNERABLE\":$is_vuln,\"INFOS\":\"$3\"},"
512
+ ;;
513
+
514
+ nrpe) [ "$2" = VULN ] && nrpe_vuln="$nrpe_vuln $1";;
515
+ prometheus)
516
+ prometheus_output="${prometheus_output:+$prometheus_output\n}specex_vuln_status{name=\"$aka\",cve=\"$1\",status=\"$2\",info=\"$3\"} 1"
517
+ ;;
518
+ esac
519
+ fi
520
+
521
+ # always fill global_* vars because we use that do decide the program exit code
522
+ case "$2" in
523
+ UNK) global_unknown="1";;
524
+ VULN) global_critical="1";;
525
+ esac
526
+
527
+ # display info if we're not in quiet/batch mode
528
+ vulnstatus="$2"
529
+ shift 2
530
+ _info_nol "> \033[46m\033[30mSTATUS:\033[0m "
531
+ case "$vulnstatus" in
532
+ UNK) pstatus yellow 'UNKNOWN' "$@";;
533
+ VULN) pstatus red 'VULNERABLE' "$@";;
534
+ OK) pstatus green 'NOT VULNERABLE' "$@";;
535
+ esac
536
+ }
537
+
538
+
539
+ # The 3 below functions are taken from the extract-linux script, available here:
540
+ # https://github.com/torvalds/linux/blob/master/scripts/extract-vmlinux
541
+ # The functions have been modified for better integration to this script
542
+ # The original header of the file has been retained below
543
+
544
+ # ----------------------------------------------------------------------
545
+ # extract-vmlinux - Extract uncompressed vmlinux from a kernel image
546
+ #
547
+ # Inspired from extract-ikconfig
548
+ # (c) 2009,2010 Dick Streefland <dick@streefland.net>
549
+ #
550
+ # (c) 2011 Corentin Chary <corentin.chary@gmail.com>
551
+ #
552
+ # Licensed under the GNU General Public License, version 2 (GPLv2).
553
+ # ----------------------------------------------------------------------
554
+
555
+ vmlinux=''
556
+ vmlinux_err=''
557
+ check_vmlinux()
558
+ {
559
+ readelf -h "$1" >/dev/null 2>&1 && return 0
560
+ return 1
561
+ }
562
+
563
+ try_decompress()
564
+ {
565
+ # The obscure use of the "tr" filter is to work around older versions of
566
+ # "grep" that report the byte offset of the line instead of the pattern.
567
+
568
+ # Try to find the header ($1) and decompress from here
569
+ for pos in $(tr "$1\n$2" "\n$2=" < "$6" | grep -abo "^$2")
570
+ do
571
+ _debug "try_decompress: magic for $3 found at offset $pos"
572
+ if ! which "$3" >/dev/null 2>&1; then
573
+ vmlinux_err="missing '$3' tool, please install it, usually it's in the '$5' package"
574
+ return 0
575
+ fi
576
+ pos=${pos%%:*}
577
+ # shellcheck disable=SC2086
578
+ tail -c+$pos "$6" 2>/dev/null | $3 $4 > "$vmlinuxtmp" 2>/dev/null
579
+ if check_vmlinux "$vmlinuxtmp"; then
580
+ vmlinux="$vmlinuxtmp"
581
+ _debug "try_decompress: decompressed with $3 successfully!"
582
+ return 0
583
+ else
584
+ _debug "try_decompress: decompression with $3 did not work"
585
+ fi
586
+ done
587
+ return 1
588
+ }
589
+
590
+ extract_vmlinux()
591
+ {
592
+ [ -n "$1" ] || return 1
593
+ # Prepare temp files:
594
+ vmlinuxtmp="$(mktemp /tmp/vmlinux-XXXXXX)"
595
+
596
+ # Initial attempt for uncompressed images or objects:
597
+ if check_vmlinux "$1"; then
598
+ cat "$1" > "$vmlinuxtmp"
599
+ vmlinux=$vmlinuxtmp
600
+ return 0
601
+ fi
602
+
603
+ # That didn't work, so retry after decompression.
604
+ try_decompress '\037\213\010' xy gunzip '' gunzip "$1" && return 0
605
+ try_decompress '\3757zXZ\000' abcde unxz '' xz-utils "$1" && return 0
606
+ try_decompress 'BZh' xy bunzip2 '' bzip2 "$1" && return 0
607
+ try_decompress '\135\0\0\0' xxx unlzma '' xz-utils "$1" && return 0
608
+ try_decompress '\211\114\132' xy 'lzop' '-d' lzop "$1" && return 0
609
+ try_decompress '\002\041\114\030' xyy 'lz4' '-d -l' liblz4-tool "$1" && return 0
610
+ try_decompress '\177ELF' xxy 'cat' '' cat "$1" && return 0
611
+ return 1
612
+ }
613
+
614
+ # end of extract-vmlinux functions
615
+
616
+ mount_debugfs()
617
+ {
618
+ if [ ! -e /sys/kernel/debug/sched_features ]; then
619
+ # try to mount the debugfs hierarchy ourselves and remember it to umount afterwards
620
+ mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null && mounted_debugfs=1
621
+ fi
622
+ }
623
+
624
+ load_msr()
625
+ {
626
+ modprobe msr 2>/dev/null && insmod_msr=1
627
+ _debug "attempted to load module msr, insmod_msr=$insmod_msr"
628
+ }
629
+
630
+ load_cpuid()
631
+ {
632
+ modprobe cpuid 2>/dev/null && insmod_cpuid=1
633
+ _debug "attempted to load module cpuid, insmod_cpuid=$insmod_cpuid"
634
+ }
635
+
636
+ read_cpuid()
637
+ {
638
+ _leaf="$1"
639
+ _bytenum="$2"
640
+ _and_operand="$3"
641
+
642
+ if [ ! -e /dev/cpu/0/cpuid ]; then
643
+ # try to load the module ourselves (and remember it so we can rmmod it afterwards)
644
+ load_cpuid
645
+ fi
646
+ if [ ! -e /dev/cpu/0/cpuid ]; then
647
+ return 2
648
+ fi
649
+
650
+ if [ "$opt_verbose" -ge 3 ]; then
651
+ dd if=/dev/cpu/0/cpuid bs=16 skip="$_leaf" iflag=skip_bytes count=1 >/dev/null 2>/dev/null
652
+ _debug "cpuid: reading leaf$_leaf of cpuid on cpu0, ret=$?"
653
+ _debug "cpuid: leaf$_leaf eax-ebx-ecx-edx: $( dd if=/dev/cpu/0/cpuid bs=16 skip="$_leaf" iflag=skip_bytes count=1 2>/dev/null | od -x -A n)"
654
+ _debug "cpuid: leaf$_leaf edx higher byte is: $(dd if=/dev/cpu/0/cpuid bs=16 skip="$_leaf" iflag=skip_bytes count=1 2>/dev/null | dd bs=1 skip="$_bytenum" count=1 2>/dev/null | od -x -A n)"
655
+ fi
656
+ # getting proper byte of edx on leaf$_leaf of cpuinfo in decimal
657
+ _reg_byte=$(dd if=/dev/cpu/0/cpuid bs=16 skip="$_leaf" iflag=skip_bytes count=1 2>/dev/null | dd bs=1 skip="$_bytenum" count=1 2>/dev/null | od -t u1 -A n | awk '{print $1}')
658
+ _debug "cpuid: leaf$_leaf byte $_bytenum: $_reg_byte (decimal)"
659
+ _reg_bit=$(( _reg_byte & _and_operand ))
660
+ _debug "cpuid: leaf$_leaf byte $_bytenum & $_and_operand = $_reg_bit"
661
+ [ "$_reg_bit" -eq 0 ] && return 1
662
+ # $_reg_bit is > 0, so the bit was found: return true (aka 0)
663
+ return 0
664
+ }
665
+
666
+ dmesg_grep()
667
+ {
668
+ # grep for something in dmesg, ensuring that the dmesg buffer
669
+ # has not been truncated
670
+ dmesg_grepped=''
671
+ if ! dmesg | grep -qE '(^|\] )Linux version [0-9]'; then
672
+ # dmesg truncated
673
+ return 2
674
+ fi
675
+ dmesg_grepped=$(dmesg | grep -E "$1" | head -1)
676
+ # not found:
677
+ [ -z "$dmesg_grepped" ] && return 1
678
+ # found, output is in $dmesg_grepped
679
+ return 0
680
+ }
681
+
682
+ is_coreos()
683
+ {
684
+ which coreos-install >/dev/null 2>&1 && which toolbox >/dev/null 2>&1 && return 0
685
+ return 1
686
+ }
687
+
688
+ parse_cpu_details()
689
+ {
690
+ [ "$parse_cpu_details_done" = 1 ] && return 0
691
+ cpu_vendor=$( grep '^vendor_id' /proc/cpuinfo | awk '{print $3}' | head -1)
692
+ cpu_friendly_name=$(grep '^model name' /proc/cpuinfo | cut -d: -f2- | head -1 | sed -e 's/^ *//')
693
+ # special case for ARM follows
694
+ if grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x41' /proc/cpuinfo; then
695
+ cpu_vendor='ARM'
696
+ # some devices (phones or other) have several ARMs and as such different part numbers,
697
+ # an example is "bigLITTLE", so we need to store the whole list, this is needed for is_cpu_vulnerable
698
+ cpu_part_list=$(awk '/CPU part/ {print $4}' /proc/cpuinfo)
699
+ cpu_arch_list=$(awk '/CPU architecture/ {print $3}' /proc/cpuinfo)
700
+ # take the first one to fill the friendly name, do NOT quote the vars below
701
+ # shellcheck disable=SC2086
702
+ cpu_arch=$(echo $cpu_arch_list | awk '{ print $1 }')
703
+ # shellcheck disable=SC2086
704
+ cpu_part=$(echo $cpu_part_list | awk '{ print $1 }')
705
+ [ "$cpu_arch" = "AArch64" ] && cpu_arch=8
706
+ cpu_friendly_name="ARM"
707
+ [ -n "$cpu_arch" ] && cpu_friendly_name="$cpu_friendly_name v$cpu_arch"
708
+ [ -n "$cpu_part" ] && cpu_friendly_name="$cpu_friendly_name model $cpu_part"
709
+ fi
710
+
711
+ cpu_family=$( grep '^cpu family' /proc/cpuinfo | awk '{print $4}' | grep -E '^[0-9]+$' | head -1)
712
+ cpu_model=$( grep '^model' /proc/cpuinfo | awk '{print $3}' | grep -E '^[0-9]+$' | head -1)
713
+ cpu_stepping=$(grep '^stepping' /proc/cpuinfo | awk '{print $3}' | grep -E '^[0-9]+$' | head -1)
714
+ cpu_ucode=$( grep '^microcode' /proc/cpuinfo | awk '{print $3}' | head -1)
715
+
716
+ # also define those that we will need in other funcs
717
+ # taken from ttps://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/include/asm/intel-family.h
718
+ # shellcheck disable=SC2034
719
+ {
720
+ INTEL_FAM6_CORE_YONAH=$(( 0x0E ))
721
+
722
+ INTEL_FAM6_CORE2_MEROM=$(( 0x0F ))
723
+ INTEL_FAM6_CORE2_MEROM_L=$(( 0x16 ))
724
+ INTEL_FAM6_CORE2_PENRYN=$(( 0x17 ))
725
+ INTEL_FAM6_CORE2_DUNNINGTON=$(( 0x1D ))
726
+
727
+ INTEL_FAM6_NEHALEM=$(( 0x1E ))
728
+ INTEL_FAM6_NEHALEM_G=$(( 0x1F ))
729
+ INTEL_FAM6_NEHALEM_EP=$(( 0x1A ))
730
+ INTEL_FAM6_NEHALEM_EX=$(( 0x2E ))
731
+
732
+ INTEL_FAM6_WESTMERE=$(( 0x25 ))
733
+ INTEL_FAM6_WESTMERE_EP=$(( 0x2C ))
734
+ INTEL_FAM6_WESTMERE_EX=$(( 0x2F ))
735
+
736
+ INTEL_FAM6_SANDYBRIDGE=$(( 0x2A ))
737
+ INTEL_FAM6_SANDYBRIDGE_X=$(( 0x2D ))
738
+ INTEL_FAM6_IVYBRIDGE=$(( 0x3A ))
739
+ INTEL_FAM6_IVYBRIDGE_X=$(( 0x3E ))
740
+
741
+ INTEL_FAM6_HASWELL_CORE=$(( 0x3C ))
742
+ INTEL_FAM6_HASWELL_X=$(( 0x3F ))
743
+ INTEL_FAM6_HASWELL_ULT=$(( 0x45 ))
744
+ INTEL_FAM6_HASWELL_GT3E=$(( 0x46 ))
745
+
746
+ INTEL_FAM6_BROADWELL_CORE=$(( 0x3D ))
747
+ INTEL_FAM6_BROADWELL_GT3E=$(( 0x47 ))
748
+ INTEL_FAM6_BROADWELL_X=$(( 0x4F ))
749
+ INTEL_FAM6_BROADWELL_XEON_D=$(( 0x56 ))
750
+
751
+ INTEL_FAM6_SKYLAKE_MOBILE=$(( 0x4E ))
752
+ INTEL_FAM6_SKYLAKE_DESKTOP=$(( 0x5E ))
753
+ INTEL_FAM6_SKYLAKE_X=$(( 0x55 ))
754
+ INTEL_FAM6_KABYLAKE_MOBILE=$(( 0x8E ))
755
+ INTEL_FAM6_KABYLAKE_DESKTOP=$(( 0x9E ))
756
+
757
+ # /* "Small Core" Processors (Atom) */
758
+
759
+ INTEL_FAM6_ATOM_PINEVIEW=$(( 0x1C ))
760
+ INTEL_FAM6_ATOM_LINCROFT=$(( 0x26 ))
761
+ INTEL_FAM6_ATOM_PENWELL=$(( 0x27 ))
762
+ INTEL_FAM6_ATOM_CLOVERVIEW=$(( 0x35 ))
763
+ INTEL_FAM6_ATOM_CEDARVIEW=$(( 0x36 ))
764
+ INTEL_FAM6_ATOM_SILVERMONT1=$(( 0x37 ))
765
+ INTEL_FAM6_ATOM_SILVERMONT2=$(( 0x4D ))
766
+ INTEL_FAM6_ATOM_AIRMONT=$(( 0x4C ))
767
+ INTEL_FAM6_ATOM_MERRIFIELD=$(( 0x4A ))
768
+ INTEL_FAM6_ATOM_MOOREFIELD=$(( 0x5A ))
769
+ INTEL_FAM6_ATOM_GOLDMONT=$(( 0x5C ))
770
+ INTEL_FAM6_ATOM_DENVERTON=$(( 0x5F ))
771
+ INTEL_FAM6_ATOM_GEMINI_LAKE=$(( 0x7A ))
772
+
773
+ # /* Xeon Phi */
774
+
775
+ INTEL_FAM6_XEON_PHI_KNL=$(( 0x57 ))
776
+ INTEL_FAM6_XEON_PHI_KNM=$(( 0x85 ))
777
+ }
778
+ parse_cpu_details_done=1
779
+ }
780
+
781
+ is_ucode_blacklisted()
782
+ {
783
+ parse_cpu_details
784
+ # if it's not an Intel, don't bother: it's not blacklisted
785
+ [ "$cpu_vendor" = GenuineIntel ] || return 1
786
+ # it also needs to be family=6
787
+ [ "$cpu_family" = 6 ] || return 1
788
+ # now, check each known bad microcode
789
+ # source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/intel.c#n105
790
+ # 2018-02-08 update: https://newsroom.intel.com/wp-content/uploads/sites/11/2018/02/microcode-update-guidance.pdf
791
+ # model,stepping,microcode
792
+ ucode_found="model $cpu_model stepping $cpu_stepping ucode $cpu_ucode"
793
+ for tuple in \
794
+ $INTEL_FAM6_KABYLAKE_DESKTOP,0x0B,0x80 \
795
+ $INTEL_FAM6_KABYLAKE_DESKTOP,0x0A,0x80 \
796
+ $INTEL_FAM6_KABYLAKE_DESKTOP,0x09,0x80 \
797
+ $INTEL_FAM6_KABYLAKE_MOBILE,0x0A,0x80 \
798
+ $INTEL_FAM6_KABYLAKE_MOBILE,0x09,0x80 \
799
+ $INTEL_FAM6_SKYLAKE_X,0x03,0x0100013e \
800
+ $INTEL_FAM6_SKYLAKE_X,0x04,0x02000036 \
801
+ $INTEL_FAM6_SKYLAKE_X,0x04,0x0200003a \
802
+ $INTEL_FAM6_SKYLAKE_X,0x04,0x0200003c \
803
+ $INTEL_FAM6_BROADWELL_CORE,0x04,0x28 \
804
+ $INTEL_FAM6_BROADWELL_GT3E,0x01,0x1b \
805
+ $INTEL_FAM6_BROADWELL_XEON_D,0x02,0x14 \
806
+ $INTEL_FAM6_BROADWELL_XEON_D,0x03,0x07000011 \
807
+ $INTEL_FAM6_BROADWELL_X,0x01,0x0b000023 \
808
+ $INTEL_FAM6_BROADWELL_X,0x01,0x0b000025 \
809
+ $INTEL_FAM6_HASWELL_ULT,0x01,0x21 \
810
+ $INTEL_FAM6_HASWELL_GT3E,0x01,0x18 \
811
+ $INTEL_FAM6_HASWELL_CORE,0x03,0x23 \
812
+ $INTEL_FAM6_HASWELL_X,0x02,0x3b \
813
+ $INTEL_FAM6_HASWELL_X,0x04,0x10 \
814
+ $INTEL_FAM6_IVYBRIDGE_X,0x04,0x42a \
815
+ $INTEL_FAM6_SANDYBRIDGE_X,0x06,0x61b \
816
+ $INTEL_FAM6_SANDYBRIDGE_X,0x07,0x712
817
+ do
818
+ model=$(echo $tuple | cut -d, -f1)
819
+ stepping=$(( $(echo $tuple | cut -d, -f2) ))
820
+ ucode=$(echo $tuple | cut -d, -f3)
821
+ if [ "$cpu_model" = "$model" ] && [ "$cpu_stepping" = "$stepping" ] && echo "$cpu_ucode" | grep -qi "^$ucode$"; then
822
+ _debug "is_ucode_blacklisted: we have a match! ($cpu_model/$cpu_stepping/$cpu_ucode)"
823
+ return 0
824
+ fi
825
+ done
826
+ _debug "is_ucode_blacklisted: no ($cpu_model/$cpu_stepping/$cpu_ucode)"
827
+ return 1
828
+ }
829
+
830
+ is_skylake_cpu()
831
+ {
832
+ # is this a skylake cpu?
833
+ # return 0 if yes, 1 otherwise
834
+ #if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
835
+ # boot_cpu_data.x86 == 6) {
836
+ # switch (boot_cpu_data.x86_model) {
837
+ # case INTEL_FAM6_SKYLAKE_MOBILE:
838
+ # case INTEL_FAM6_SKYLAKE_DESKTOP:
839
+ # case INTEL_FAM6_SKYLAKE_X:
840
+ # case INTEL_FAM6_KABYLAKE_MOBILE:
841
+ # case INTEL_FAM6_KABYLAKE_DESKTOP:
842
+ # return true;
843
+ parse_cpu_details
844
+ [ "$cpu_vendor" = GenuineIntel ] || return 1
845
+ [ "$cpu_family" = 6 ] || return 1
846
+ if [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_MOBILE ] || \
847
+ [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_DESKTOP ] || \
848
+ [ "$cpu_model" = $INTEL_FAM6_SKYLAKE_X ] || \
849
+ [ "$cpu_model" = $INTEL_FAM6_KABYLAKE_MOBILE ] || \
850
+ [ "$cpu_model" = $INTEL_FAM6_KABYLAKE_DESKTOP ]; then
851
+ return 0
852
+ fi
853
+ return 1
854
+ }
855
+
856
+ # check for mode selection inconsistency
857
+ if [ "$opt_live_explicit" = 1 ]; then
858
+ if [ -n "$opt_kernel" ] || [ -n "$opt_config" ] || [ -n "$opt_map" ]; then
859
+ show_usage
860
+ echo "$0: error: incompatible modes specified, use either --live or --kernel/--config/--map" >&2
861
+ exit 255
862
+ fi
863
+ fi
864
+
865
+ # coreos mode
866
+ if [ "$opt_coreos" = 1 ]; then
867
+ if ! is_coreos; then
868
+ _warn "CoreOS mode asked, but we're not under CoreOS!"
869
+ exit 255
870
+ fi
871
+ _warn "CoreOS mode, starting an ephemeral toolbox to launch the script"
872
+ load_msr
873
+ load_cpuid
874
+ mount_debugfs
875
+ toolbox --ephemeral --bind-ro /dev/cpu:/dev/cpu -- sh -c "dnf install -y binutils which && /media/root$PWD/$0 $* --coreos-within-toolbox"
876
+ exitcode=$?
877
+ exit $exitcode
878
+ else
879
+ if is_coreos; then
880
+ _warn "You seem to be running CoreOS, you might want to use the --coreos option for better results"
881
+ _warn
882
+ fi
883
+ fi
884
+
885
+ parse_cpu_details
886
+ if [ "$opt_live" = 1 ]; then
887
+ # root check (only for live mode, for offline mode, we already checked if we could read the files)
888
+ if [ "$(id -u)" -ne 0 ]; then
889
+ _warn "Note that you should launch this script with root privileges to get accurate information."
890
+ _warn "We'll proceed but you might see permission denied errors."
891
+ _warn "To run it as root, you can try the following command: sudo $0"
892
+ _warn
893
+ fi
894
+ _info "Checking for vulnerabilities on current system"
895
+ _info "Kernel is \033[35m$(uname -s) $(uname -r) $(uname -v) $(uname -m)\033[0m"
896
+ _info "CPU is \033[35m$cpu_friendly_name\033[0m"
897
+
898
+ # try to find the image of the current running kernel
899
+ # first, look for the BOOT_IMAGE hint in the kernel cmdline
900
+ if [ -r /proc/cmdline ] && grep -q 'BOOT_IMAGE=' /proc/cmdline; then
901
+ opt_kernel=$(grep -Eo 'BOOT_IMAGE=[^ ]+' /proc/cmdline | cut -d= -f2)
902
+ _debug "found opt_kernel=$opt_kernel in /proc/cmdline"
903
+ # if we have a dedicated /boot partition, our bootloader might have just called it /
904
+ # so try to prepend /boot and see if we find anything
905
+ [ -e "/boot/$opt_kernel" ] && opt_kernel="/boot/$opt_kernel"
906
+ # special case for CoreOS if we're inside the toolbox
907
+ [ -e "/media/root/boot/$opt_kernel" ] && opt_kernel="/media/root/boot/$opt_kernel"
908
+ _debug "opt_kernel is now $opt_kernel"
909
+ # else, the full path is already there (most probably /boot/something)
910
+ fi
911
+ # if we didn't find a kernel, default to guessing
912
+ if [ ! -e "$opt_kernel" ]; then
913
+ # Fedora:
914
+ [ -e "/lib/modules/$(uname -r)/vmlinuz" ] && opt_kernel="/lib/modules/$(uname -r)/vmlinuz"
915
+ # Slackare:
916
+ [ -e "/boot/vmlinuz" ] && opt_kernel="/boot/vmlinuz"
917
+ # Arch:
918
+ [ -e "/boot/vmlinuz-linux" ] && opt_kernel="/boot/vmlinuz-linux"
919
+ # Linux-Libre:
920
+ [ -e "/boot/vmlinuz-linux-libre" ] && opt_kernel="/boot/vmlinuz-linux-libre"
921
+ # pine64
922
+ [ -e "/boot/pine64/Image" ] && opt_kernel="/boot/pine64/Image"
923
+ # generic:
924
+ [ -e "/boot/vmlinuz-$(uname -r)" ] && opt_kernel="/boot/vmlinuz-$(uname -r)"
925
+ [ -e "/boot/kernel-$( uname -r)" ] && opt_kernel="/boot/kernel-$( uname -r)"
926
+ [ -e "/boot/bzImage-$(uname -r)" ] && opt_kernel="/boot/bzImage-$(uname -r)"
927
+ # Gentoo:
928
+ [ -e "/boot/kernel-genkernel-$(uname -m)-$(uname -r)" ] && opt_kernel="/boot/kernel-genkernel-$(uname -m)-$(uname -r)"
929
+ # NixOS:
930
+ [ -e "/run/booted-system/kernel" ] && opt_kernel="/run/booted-system/kernel"
931
+ # systemd kernel-install:
932
+ [ -e "/etc/machine-id" ] && [ -e "/boot/$(cat /etc/machine-id)/$(uname -r)/linux" ] && opt_kernel="/boot/$(cat /etc/machine-id)/$(uname -r)/linux"
933
+ fi
934
+
935
+ # system.map
936
+ if [ -e /proc/kallsyms ] ; then
937
+ opt_map=/proc/kallsyms
938
+ elif [ -e "/lib/modules/$(uname -r)/System.map" ] ; then
939
+ opt_map="/lib/modules/$(uname -r)/System.map"
940
+ elif [ -e "/boot/System.map-$(uname -r)" ] ; then
941
+ opt_map="/boot/System.map-$(uname -r)"
942
+ fi
943
+
944
+ # config
945
+ if [ -e /proc/config.gz ] ; then
946
+ dumped_config="$(mktemp /tmp/config-XXXXXX)"
947
+ gunzip -c /proc/config.gz > "$dumped_config"
948
+ # dumped_config will be deleted at the end of the script
949
+ opt_config="$dumped_config"
950
+ elif [ -e "/lib/modules/$(uname -r)/config" ]; then
951
+ opt_config="/lib/modules/$(uname -r)/config"
952
+ elif [ -e "/boot/config-$(uname -r)" ]; then
953
+ opt_config="/boot/config-$(uname -r)"
954
+ fi
955
+ else
956
+ _info "Checking for vulnerabilities against specified kernel"
957
+ _info "CPU is \033[35m$cpu_friendly_name\033[0m"
958
+ fi
959
+
960
+ if [ -n "$opt_kernel" ]; then
961
+ _verbose "Will use vmlinux image \033[35m$opt_kernel\033[0m"
962
+ else
963
+ _verbose "Will use no vmlinux image (accuracy might be reduced)"
964
+ bad_accuracy=1
965
+ fi
966
+
967
+ if [ -n "$opt_config" ] && ! grep -q '^CONFIG_' "$opt_config"; then
968
+ # given file is invalid!
969
+ _warn "The kernel config file seems invalid, was expecting a plain-text file, ignoring it!"
970
+ opt_config=''
971
+ fi
972
+
973
+ if [ -n "$dumped_config" ] && [ -n "$opt_config" ]; then
974
+ _verbose "Will use kconfig \033[35m/proc/config.gz (decompressed)\033[0m"
975
+ elif [ -n "$opt_config" ]; then
976
+ _verbose "Will use kconfig \033[35m$opt_config\033[0m"
977
+ else
978
+ _verbose "Will use no kconfig (accuracy might be reduced)"
979
+ bad_accuracy=1
980
+ fi
981
+
982
+ if [ -n "$opt_map" ]; then
983
+ _verbose "Will use System.map file \033[35m$opt_map\033[0m"
984
+ else
985
+ _verbose "Will use no System.map file (accuracy might be reduced)"
986
+ bad_accuracy=1
987
+ fi
988
+
989
+ if [ "$bad_accuracy" = 1 ]; then
990
+ _info "We're missing some kernel info (see -v), accuracy might be reduced"
991
+ fi
992
+
993
+ if [ -e "$opt_kernel" ]; then
994
+ if ! which readelf >/dev/null 2>&1; then
995
+ _debug "readelf not found"
996
+ vmlinux_err="missing 'readelf' tool, please install it, usually it's in the 'binutils' package"
997
+ elif [ "$opt_sysfs_only" = 1 ]; then
998
+ vmlinux_err='kernel image decompression skipped'
999
+ else
1000
+ extract_vmlinux "$opt_kernel"
1001
+ fi
1002
+ else
1003
+ _debug "no opt_kernel defined"
1004
+ vmlinux_err="couldn't find your kernel image in /boot, if you used netboot, this is normal"
1005
+ fi
1006
+ if [ -z "$vmlinux" ] || [ ! -r "$vmlinux" ]; then
1007
+ [ -z "$vmlinux_err" ] && vmlinux_err="couldn't extract your kernel from $opt_kernel"
1008
+ else
1009
+ vmlinux_version=$(strings "$vmlinux" 2>/dev/null | grep '^Linux version ' | head -1)
1010
+ if [ -z "$vmlinux_version" ]; then
1011
+ # try harder with some kernels (such as Red Hat) that don't have ^Linux version before their version string
1012
+ vmlinux_version=$(strings "$vmlinux" 2>/dev/null | grep -E '^[[:alnum:]][^[:space:]]+ \([^[:space:]]+\) #[0-9]+ .+ (19|20)[0-9][0-9]$' | head -1)
1013
+ fi
1014
+ if [ -n "$vmlinux_version" ]; then
1015
+ # in live mode, check if the img we found is the correct one
1016
+ if [ "$opt_live" = 1 ]; then
1017
+ _verbose "Kernel image is \033[35m$vmlinux_version"
1018
+ if ! echo "$vmlinux_version" | grep -qF "$(uname -r)" || \
1019
+ ! echo "$vmlinux_version" | grep -qF "$(uname -v)"; then
1020
+ _warn "Possible disrepancy between your running kernel and the image we found ($opt_kernel), results might be incorrect"
1021
+ fi
1022
+ else
1023
+ _info "Kernel image is \033[35m$vmlinux_version"
1024
+ fi
1025
+ else
1026
+ _verbose "Kernel image version is unknown"
1027
+ fi
1028
+ fi
1029
+
1030
+ _info
1031
+
1032
+ # end of header stuff
1033
+
1034
+ # now we define some util functions and the check_*() funcs, as
1035
+ # the user can choose to execute only some of those
1036
+
1037
+ sys_interface_check()
1038
+ {
1039
+ [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$1" ] || return 1
1040
+ _info_nol "* Mitigated according to the /sys interface: "
1041
+ if grep -qi '^not affected' "$1"; then
1042
+ # Not affected
1043
+ status=OK
1044
+ pstatus green YES "kernel confirms that your CPU is unaffected"
1045
+ elif grep -qi '^mitigation' "$1"; then
1046
+ # Mitigation: PTI
1047
+ status=OK
1048
+ pstatus green YES "kernel confirms that the mitigation is active"
1049
+ elif grep -qi '^vulnerable' "$1"; then
1050
+ # Vulnerable
1051
+ status=VULN
1052
+ pstatus red NO "kernel confirms your system is vulnerable"
1053
+ else
1054
+ status=UNK
1055
+ pstatus yellow UNKNOWN "unknown value reported by kernel"
1056
+ fi
1057
+ msg=$(cat "$1")
1058
+ _debug "sys_interface_check: $1=$msg"
1059
+ return 0
1060
+ }
1061
+
1062
+ check_cpu()
1063
+ {
1064
+ _info "\033[1;34mHardware check\033[0m"
1065
+
1066
+ _info "* Hardware support (CPU microcode) for mitigation techniques"
1067
+ _info " * Indirect Branch Restricted Speculation (IBRS)"
1068
+ _info_nol " * SPEC_CTRL MSR is available: "
1069
+ if [ ! -e /dev/cpu/0/msr ]; then
1070
+ # try to load the module ourselves (and remember it so we can rmmod it afterwards)
1071
+ load_msr
1072
+ fi
1073
+ if [ ! -e /dev/cpu/0/msr ]; then
1074
+ spec_ctrl_msr=-1
1075
+ pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/msr, is msr support enabled in your kernel?"
1076
+ else
1077
+ # the new MSR 'SPEC_CTRL' is at offset 0x48
1078
+ # here we use dd, it's the same as using 'rdmsr 0x48' but without needing the rdmsr tool
1079
+ # if we get a read error, the MSR is not there. bs has to be 8 for msr
1080
+ # skip=9 because 8*9=72=0x48
1081
+ dd if=/dev/cpu/0/msr of=/dev/null bs=8 count=1 skip=9 2>/dev/null; ret=$?
1082
+ if [ $ret -eq 0 ]; then
1083
+ spec_ctrl_msr=1
1084
+ pstatus green YES
1085
+ else
1086
+ spec_ctrl_msr=0
1087
+ pstatus red NO
1088
+ fi
1089
+ fi
1090
+
1091
+ _info_nol " * CPU indicates IBRS capability: "
1092
+ # from kernel src: { X86_FEATURE_SPEC_CTRL, CPUID_EDX,26, 0x00000007, 0 },
1093
+ read_cpuid 7 15 4; ret=$?
1094
+ if [ $ret -eq 0 ]; then
1095
+ pstatus green YES "SPEC_CTRL feature bit"
1096
+ cpuid_spec_ctrl=1
1097
+ elif [ $ret -eq 2 ]; then
1098
+ pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/cpuid, is cpuid support enabled in your kernel?"
1099
+ else
1100
+ pstatus red NO
1101
+ fi
1102
+
1103
+ # hardware support according to kernel
1104
+ if [ "$opt_verbose" -ge 2 ]; then
1105
+ # the spec_ctrl flag in cpuinfo is set if and only if the kernel sees
1106
+ # that the spec_ctrl cpuinfo bit set. we already check that ourselves above
1107
+ # but let's check it anyway (in verbose mode only)
1108
+ _verbose_nol " * Kernel has set the spec_ctrl flag in cpuinfo: "
1109
+ if [ "$opt_live" = 1 ]; then
1110
+ if grep ^flags /proc/cpuinfo | grep -qw spec_ctrl; then
1111
+ pstatus green YES
1112
+ else
1113
+ pstatus blue NO
1114
+ fi
1115
+ else
1116
+ pstatus blue N/A "not testable in offline mode"
1117
+ fi
1118
+ fi
1119
+
1120
+ # IBPB
1121
+ _info " * Indirect Branch Prediction Barrier (IBPB)"
1122
+ _info_nol " * PRED_CMD MSR is available: "
1123
+ if [ ! -e /dev/cpu/0/msr ]; then
1124
+ pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/msr, is msr support enabled in your kernel?"
1125
+ else
1126
+ # the new MSR 'PRED_CTRL' is at offset 0x49, write-only
1127
+ # here we use dd, it's the same as using 'wrmsr 0x49 0' but without needing the wrmsr tool
1128
+ # if we get a write error, the MSR is not there
1129
+ $echo_cmd -ne "\0\0\0\0\0\0\0\0" | dd of=/dev/cpu/0/msr bs=8 count=1 seek=73 oflag=seek_bytes 2>/dev/null; ret=$?
1130
+ if [ $ret -eq 0 ]; then
1131
+ pstatus green YES
1132
+ else
1133
+ pstatus red NO
1134
+ fi
1135
+ fi
1136
+
1137
+
1138
+ _info_nol " * CPU indicates IBPB capability: "
1139
+ # CPUID EAX=0x80000008, ECX=0x00 return EBX[12] indicates support for just IBPB.
1140
+ read_cpuid 2147483656 5 16; ret=$?
1141
+ if [ $ret -eq 0 ]; then
1142
+ pstatus green YES "IBPB_SUPPORT feature bit"
1143
+ elif [ "$cpuid_spec_ctrl" = 1 ]; then
1144
+ pstatus green YES "SPEC_CTRL feature bit"
1145
+ elif [ $ret -eq 2 ]; then
1146
+ pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/cpuid, is cpuid support enabled in your kernel?"
1147
+ else
1148
+ pstatus red NO
1149
+ fi
1150
+
1151
+ # STIBP
1152
+ _info " * Single Thread Indirect Branch Predictors (STIBP)"
1153
+ _info_nol " * SPEC_CTRL MSR is available: "
1154
+ if [ "$spec_ctrl_msr" = 1 ]; then
1155
+ pstatus green YES
1156
+ elif [ "$spec_ctrl_msr" = 0 ]; then
1157
+ pstatus red NO
1158
+ else
1159
+ pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/msr, is msr support enabled in your kernel?"
1160
+ fi
1161
+
1162
+ _info_nol " * CPU indicates STIBP capability: "
1163
+ # A processor supports STIBP if it enumerates CPUID (EAX=7H,ECX=0):EDX[27] as 1
1164
+ read_cpuid 7 15 8; ret=$?
1165
+ if [ $ret -eq 0 ]; then
1166
+ pstatus green YES
1167
+ elif [ $ret -eq 2 ]; then
1168
+ pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/cpuid, is cpuid support enabled in your kernel?"
1169
+ else
1170
+ pstatus red NO
1171
+ fi
1172
+
1173
+ _info " * Enhanced IBRS (IBRS_ALL)"
1174
+ _info_nol " * CPU indicates ARCH_CAPABILITIES MSR availability: "
1175
+ cpuid_arch_capabilities=-1
1176
+ # A processor supports STIBP if it enumerates CPUID (EAX=7H,ECX=0):EDX[27] as 1
1177
+ read_cpuid 7 15 32; ret=$?
1178
+ if [ $ret -eq 0 ]; then
1179
+ pstatus green YES
1180
+ cpuid_arch_capabilities=1
1181
+ elif [ $ret -eq 2 ]; then
1182
+ pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/cpuid, is cpuid support enabled in your kernel?"
1183
+ else
1184
+ pstatus red NO
1185
+ cpuid_arch_capabilities=0
1186
+ fi
1187
+
1188
+ _info_nol " * ARCH_CAPABILITIES MSR advertises IBRS_ALL capability: "
1189
+ capabilities_rdcl_no=-1
1190
+ capabilities_ibrs_all=-1
1191
+ if [ "$cpuid_arch_capabilities" = -1 ]; then
1192
+ pstatus yellow UNKNOWN
1193
+ elif [ "$cpuid_arch_capabilities" != 1 ]; then
1194
+ capabilities_rdcl_no=0
1195
+ capabilities_ibrs_all=0
1196
+ pstatus red NO
1197
+ elif [ ! -e /dev/cpu/0/msr ]; then
1198
+ spec_ctrl_msr=-1
1199
+ pstatus yellow UNKNOWN "couldn't read /dev/cpu/0/msr, is msr support enabled in your kernel?"
1200
+ else
1201
+ # the new MSR 'ARCH_CAPABILITIES' is at offset 0x10a
1202
+ # here we use dd, it's the same as using 'rdmsr 0x10a' but without needing the rdmsr tool
1203
+ # if we get a read error, the MSR is not there. bs has to be 8 for msr
1204
+ capabilities=$(dd if=/dev/cpu/0/msr bs=8 count=1 skip=266 iflag=skip_bytes 2>/dev/null | od -t u1 -A n | awk '{print $8}'); ret=$?
1205
+ capabilities_rdcl_no=0
1206
+ capabilities_ibrs_all=0
1207
+ if [ $ret -eq 0 ]; then
1208
+ _debug "capabilities MSR lower byte is $capabilities (decimal)"
1209
+ [ $(( capabilities & 1 )) -eq 1 ] && capabilities_rdcl_no=1
1210
+ [ $(( capabilities & 2 )) -eq 2 ] && capabilities_ibrs_all=1
1211
+ _debug "capabilities says rdcl_no=$capabilities_rdcl_no ibrs_all=$capabilities_ibrs_all"
1212
+ if [ "$capabilities_ibrs_all" = 1 ]; then
1213
+ pstatus green YES
1214
+ else
1215
+ pstatus red NO
1216
+ fi
1217
+ else
1218
+ pstatus yellow UNKNOWN
1219
+ fi
1220
+ fi
1221
+
1222
+ _info_nol " * CPU explicitly indicates not being vulnerable to Meltdown (RDCL_NO): "
1223
+ if [ "$capabilities_rdcl_no" = -1 ]; then
1224
+ pstatus yellow UNKNOWN
1225
+ elif [ "$capabilities_rdcl_no" = 1 ]; then
1226
+ pstatus green YES
1227
+ else
1228
+ pstatus blue NO
1229
+ fi
1230
+
1231
+ _info_nol " * CPU microcode is known to cause stability problems: "
1232
+ if is_ucode_blacklisted; then
1233
+ pstatus red YES "$ucode_found"
1234
+ _warn
1235
+ _warn "The microcode your CPU is running on is known to cause instability problems,"
1236
+ _warn "such as intempestive reboots or random crashes."
1237
+ _warn "You are advised to either revert to a previous microcode version (that might not have"
1238
+ _warn "the mitigations for Spectre), or upgrade to a newer one if available."
1239
+ _warn
1240
+ else
1241
+ pstatus blue NO "$ucode_found"
1242
+ fi
1243
+
1244
+ _info "* CPU vulnerability to the three speculative execution attacks variants"
1245
+ for v in 1 2 3; do
1246
+ _info_nol " * Vulnerable to Variant $v: "
1247
+ if is_cpu_vulnerable $v; then
1248
+ pstatus red YES
1249
+ else
1250
+ pstatus green NO
1251
+ fi
1252
+ done
1253
+
1254
+ _info
1255
+ }
1256
+
1257
+ check_redhat_canonical_spectre()
1258
+ {
1259
+ # if we were already called, don't do it again
1260
+ [ -n "$redhat_canonical_spectre" ] && return
1261
+
1262
+ if ! which strings >/dev/null 2>&1; then
1263
+ redhat_canonical_spectre=-1
1264
+ elif [ -n "$vmlinux_err" ]; then
1265
+ redhat_canonical_spectre=-2
1266
+ else
1267
+ # Red Hat / Ubuntu specific variant1 patch is difficult to detect,
1268
+ # let's use the same way than the official Red Hat detection script,
1269
+ # and detect their specific variant2 patch. If it's present, it means
1270
+ # that the variant1 patch is also present (both were merged at the same time)
1271
+ if strings "$vmlinux" | grep -qw noibrs && strings "$vmlinux" | grep -qw noibpb; then
1272
+ _debug "found redhat/canonical version of the variant2 patch (implies variant1)"
1273
+ redhat_canonical_spectre=1
1274
+ else
1275
+ redhat_canonical_spectre=0
1276
+ fi
1277
+ fi
1278
+ }
1279
+
1280
+
1281
+ ###################
1282
+ # SPECTRE VARIANT 1
1283
+ check_variant1()
1284
+ {
1285
+ _info "\033[1;34mCVE-2017-5753 [bounds check bypass] aka 'Spectre Variant 1'\033[0m"
1286
+
1287
+ status=UNK
1288
+ sys_interface_available=0
1289
+ msg=''
1290
+ if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/spectre_v1"; then
1291
+ # this kernel has the /sys interface, trust it over everything
1292
+ # v0.33+: don't. some kernels have backported the array_index_mask_nospec() workaround without
1293
+ # modifying the vulnerabilities/spectre_v1 file. that's bad. we can't trust it when it says Vulnerable :(
1294
+ # see "silent backport" detection at the bottom of this func
1295
+ sys_interface_available=1
1296
+ fi
1297
+ if [ "$opt_sysfs_only" != 1 ]; then
1298
+ # no /sys interface (or offline mode), fallback to our own ways
1299
+ _info_nol "* Kernel has array_index_mask_nospec: "
1300
+ # vanilla: look for the Linus' mask aka array_index_mask_nospec()
1301
+ # that is inlined at least in raw_copy_from_user (__get_user_X symbols)
1302
+ #mov PER_CPU_VAR(current_task), %_ASM_DX
1303
+ #cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
1304
+ #jae bad_get_user
1305
+ # /* array_index_mask_nospec() are the 2 opcodes that follow */
1306
+ #+sbb %_ASM_DX, %_ASM_DX
1307
+ #+and %_ASM_DX, %_ASM_AX
1308
+ #ASM_STAC
1309
+ # x86 64bits: jae(0x0f 0x83 0x?? 0x?? 0x?? 0x??) sbb(0x48 0x19 0xd2) and(0x48 0x21 0xd0)
1310
+ # x86 32bits: cmp(0x3b 0x82 0x?? 0x?? 0x00 0x00) jae(0x73 0x??) sbb(0x19 0xd2) and(0x21 0xd0)
1311
+ if [ -n "$vmlinux_err" ]; then
1312
+ pstatus yellow UNKNOWN "couldn't check ($vmlinux_err)"
1313
+ elif ! which perl >/dev/null 2>&1; then
1314
+ pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
1315
+ else
1316
+ perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found) }' "$vmlinux"; ret=$?
1317
+ if [ $ret -gt 0 ]; then
1318
+ pstatus green YES "$ret occurence(s) found of 64 bits array_index_mask_nospec()"
1319
+ v1_mask_nospec=1
1320
+ else
1321
+ perl -ne '/\x3b\x82..\x00\x00\x73.\x19\xd2\x21\xd0/ and $found++; END { exit($found) }' "$vmlinux"; ret=$?
1322
+ if [ $ret -gt 0 ]; then
1323
+ pstatus green YES "$ret occurence(s) found of 32 bits array_index_mask_nospec()"
1324
+ v1_mask_nospec=1
1325
+ else
1326
+ pstatus red NO
1327
+ fi
1328
+ fi
1329
+ fi
1330
+
1331
+ _info_nol "* Kernel has the Red Hat/Ubuntu patch: "
1332
+ check_redhat_canonical_spectre
1333
+ if [ "$redhat_canonical_spectre" = -1 ]; then
1334
+ pstatus yellow UNKNOWN "missing 'strings' tool, please install it, usually it's in the binutils package"
1335
+ elif [ "$redhat_canonical_spectre" = -2 ]; then
1336
+ pstatus yellow UNKNOWN "couldn't check ($vmlinux_err)"
1337
+ elif [ "$redhat_canonical_spectre" = 1 ]; then
1338
+ pstatus green YES
1339
+ else
1340
+ pstatus red NO
1341
+ fi
1342
+
1343
+ if [ "$opt_verbose" -ge 2 ] || ( [ "$v1_mask_nospec" != 1 ] && [ "$redhat_canonical_spectre" != 1 ] ); then
1344
+ # this is a slow heuristic and we don't need it if we already know the kernel is patched
1345
+ # but still show it in verbose mode
1346
+ _info_nol "* Checking count of LFENCE instructions following a jump in kernel... "
1347
+ if [ -n "$vmlinux_err" ]; then
1348
+ pstatus yellow UNKNOWN "couldn't check ($vmlinux_err)"
1349
+ else
1350
+ if ! which objdump >/dev/null 2>&1; then
1351
+ pstatus yellow UNKNOWN "missing 'objdump' tool, please install it, usually it's in the binutils package"
1352
+ else
1353
+ # here we disassemble the kernel and count the number of occurrences of the LFENCE opcode
1354
+ # in non-patched kernels, this has been empirically determined as being around 40-50
1355
+ # in patched kernels, this is more around 70-80, sometimes way higher (100+)
1356
+ # v0.13: 68 found in a 3.10.23-xxxx-std-ipv6-64 (with lots of modules compiled-in directly), which doesn't have the LFENCE patches,
1357
+ # so let's push the threshold to 70.
1358
+ # v0.33+: now only count lfence opcodes after a jump, way less error-prone
1359
+ # non patched kernel have between 0 and 20 matches, patched ones have at least 40-45
1360
+ nb_lfence=$(objdump -d "$vmlinux" | grep -w -B1 lfence | grep -Ewc 'jmp|jne|je')
1361
+ if [ "$nb_lfence" -lt 30 ]; then
1362
+ pstatus red NO "only $nb_lfence jump-then-lfence instructions found, should be >= 30 (heuristic)"
1363
+ else
1364
+ v1_lfence=1
1365
+ pstatus green YES "$nb_lfence jump-then-lfence instructions found, which is >= 30 (heuristic)"
1366
+ fi
1367
+ fi
1368
+ fi
1369
+ fi
1370
+
1371
+ else
1372
+ # we have no sysfs but were asked to use it only!
1373
+ msg="/sys vulnerability interface use forced, but it's not available!"
1374
+ status=UNK
1375
+ fi
1376
+
1377
+ # report status
1378
+ cve='CVE-2017-5753'
1379
+ if ! is_cpu_vulnerable 1; then
1380
+ # override status & msg in case CPU is not vulnerable after all
1381
+ pvulnstatus $cve OK "your CPU vendor reported your CPU model as not vulnerable"
1382
+ elif [ -z "$msg" ]; then
1383
+ # if msg is empty, sysfs check didn't fill it, rely on our own test
1384
+ if [ "$v1_mask_nospec" = 1 ]; then
1385
+ pvulnstatus $cve OK "Kernel source has been patched to mitigate the vulnerability (array_index_mask_nospec)"
1386
+ elif [ "$redhat_canonical_spectre" = 1 ]; then
1387
+ pvulnstatus $cve OK "Kernel source has been patched to mitigate the vulnerability (Red Hat/Ubuntu patch)"
1388
+ elif [ "$v1_lfence" = 1 ]; then
1389
+ pvulnstatus $cve OK "Kernel source has PROBABLY been patched to mitigate the vulnerability (jump-then-lfence instructions heuristic)"
1390
+ elif [ "$vmlinux_err" ]; then
1391
+ pvulnstatus $cve UNK "Couldn't find kernel image or tools missing to execute the checks"
1392
+ else
1393
+ pvulnstatus $cve VULN "Kernel source needs to be patched to mitigate the vulnerability"
1394
+ fi
1395
+ else
1396
+ if [ "$msg" = "Vulnerable" ] && [ "$v1_mask_nospec" = 1 ]; then
1397
+ pvulnstatus $cve OK "Kernel source has been patched to mitigate the vulnerability (silent backport of array_index_mask_nospec)"
1398
+ else
1399
+ [ "$msg" = "Vulnerable" ] && msg="Kernel source needs to be patched to mitigate the vulnerability"
1400
+ pvulnstatus $cve "$status" "$msg"
1401
+ fi
1402
+ fi
1403
+ }
1404
+
1405
+ ###################
1406
+ # SPECTRE VARIANT 2
1407
+ check_variant2()
1408
+ {
1409
+ _info "\033[1;34mCVE-2017-5715 [branch target injection] aka 'Spectre Variant 2'\033[0m"
1410
+
1411
+ status=UNK
1412
+ sys_interface_available=0
1413
+ msg=''
1414
+ if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/spectre_v2"; then
1415
+ # this kernel has the /sys interface, trust it over everything
1416
+ sys_interface_available=1
1417
+ fi
1418
+ if [ "$opt_sysfs_only" != 1 ]; then
1419
+ _info "* Mitigation 1"
1420
+ _info_nol " * Kernel is compiled with IBRS/IBPB support: "
1421
+ ibrs_can_tell=0
1422
+
1423
+ if [ "$opt_live" = 1 ]; then
1424
+ ibrs_can_tell=1
1425
+ mount_debugfs
1426
+ for dir in \
1427
+ /sys/kernel/debug \
1428
+ /sys/kernel/debug/x86 \
1429
+ /proc/sys/kernel; do
1430
+ if [ -e "$dir/ibrs_enabled" ]; then
1431
+ # if the file is there, we have IBRS compiled-in
1432
+ # /sys/kernel/debug/ibrs_enabled: vanilla
1433
+ # /sys/kernel/debug/x86/ibrs_enabled: Red Hat (see https://access.redhat.com/articles/3311301)
1434
+ # /proc/sys/kernel/ibrs_enabled: OpenSUSE tumbleweed
1435
+ pstatus green YES
1436
+ ibrs_knob_dir=$dir
1437
+ ibrs_supported=1
1438
+ ibrs_enabled=$(cat "$dir/ibrs_enabled" 2>/dev/null)
1439
+ _debug "ibrs: found $dir/ibrs_enabled=$ibrs_enabled"
1440
+ if [ -e "$dir/ibpb_enabled" ]; then
1441
+ ibpb_enabled=$(cat "$dir/ibpb_enabled" 2>/dev/null)
1442
+ _debug "ibpb: found $dir/ibpb_enabled=$ibpb_enabled"
1443
+ else
1444
+ ibpb_enabled=-1
1445
+ _debug "ibpb: no ibpb_enabled file in $dir"
1446
+ fi
1447
+ break
1448
+ else
1449
+ _debug "ibrs: $dir/ibrs_enabled file doesn't exist"
1450
+ fi
1451
+ done
1452
+ # on some newer kernels, the spec_ctrl_ibrs flag in /proc/cpuinfo
1453
+ # is set when ibrs has been administratively enabled (usually from cmdline)
1454
+ # which in that case means ibrs is supported *and* enabled for kernel & user
1455
+ # as per the ibrs patch series v3
1456
+ if [ "$ibrs_supported" = 0 ]; then
1457
+ if grep ^flags /proc/cpuinfo | grep -qw spec_ctrl_ibrs; then
1458
+ _debug "ibrs: found spec_ctrl_ibrs flag in /proc/cpuinfo"
1459
+ ibrs_supported=1
1460
+ # enabled=2 -> kernel & user
1461
+ ibrs_enabled=2
1462
+ # XXX and what about ibpb ?
1463
+ fi
1464
+ fi
1465
+ fi
1466
+ if [ "$ibrs_supported" != 1 ] && [ -n "$opt_map" ]; then
1467
+ ibrs_can_tell=1
1468
+ if grep -q spec_ctrl "$opt_map"; then
1469
+ pstatus green YES
1470
+ ibrs_supported=1
1471
+ _debug "ibrs: found '*spec_ctrl*' symbol in $opt_map"
1472
+ fi
1473
+ fi
1474
+ if [ "$ibrs_supported" != 1 ]; then
1475
+ check_redhat_canonical_spectre
1476
+ if [ "$redhat_canonical_spectre" = 1 ]; then
1477
+ pstatus green YES "Red Hat/Ubuntu patch"
1478
+ ibrs_supported=1
1479
+ fi
1480
+ fi
1481
+ if [ "$ibrs_supported" != 1 ]; then
1482
+ if [ "$ibrs_can_tell" = 1 ]; then
1483
+ pstatus red NO
1484
+ else
1485
+ # if we're in offline mode without System.map, we can't really know
1486
+ pstatus yellow UNKNOWN "in offline mode, we need System.map to be able to tell"
1487
+ fi
1488
+ fi
1489
+
1490
+ _info " * Currently enabled features"
1491
+ _info_nol " * IBRS enabled for Kernel space: "
1492
+ if [ "$opt_live" = 1 ]; then
1493
+ if [ "$ibpb_enabled" = 2 ]; then
1494
+ # if ibpb=2, ibrs is forcefully=0
1495
+ pstatus blue NO "IBPB used instead of IBRS in all kernel entrypoints"
1496
+ else
1497
+ # 0 means disabled
1498
+ # 1 is enabled only for kernel space
1499
+ # 2 is enabled for kernel and user space
1500
+ case "$ibrs_enabled" in
1501
+ "")
1502
+ if [ "$ibrs_supported" = 1 ]; then
1503
+ pstatus yellow UNKNOWN
1504
+ else
1505
+ pstatus red NO
1506
+ fi
1507
+ ;;
1508
+ 0)
1509
+ pstatus red NO
1510
+ _verbose " - To enable, \`echo 1 > $ibrs_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error."
1511
+ ;;
1512
+ 1 | 2) pstatus green YES;;
1513
+ *) pstatus yellow UNKNOWN;;
1514
+ esac
1515
+ fi
1516
+ else
1517
+ pstatus blue N/A "not testable in offline mode"
1518
+ fi
1519
+
1520
+ _info_nol " * IBRS enabled for User space: "
1521
+ if [ "$opt_live" = 1 ]; then
1522
+ if [ "$ibpb_enabled" = 2 ]; then
1523
+ # if ibpb=2, ibrs is forcefully=0
1524
+ pstatus blue NO "IBPB used instead of IBRS in all kernel entrypoints"
1525
+ else
1526
+ case "$ibrs_enabled" in
1527
+ "")
1528
+ if [ "$ibrs_supported" = 1 ]; then
1529
+ pstatus yellow UNKNOWN
1530
+ else
1531
+ pstatus red NO
1532
+ fi
1533
+ ;;
1534
+ 0 | 1)
1535
+ pstatus red NO
1536
+ _verbose " - To enable, \`echo 2 > $ibrs_knob_dir/ibrs_enabled' as root. If you don't have hardware support, you'll get an error."
1537
+ ;;
1538
+ 2) pstatus green YES;;
1539
+ *) pstatus yellow UNKNOWN;;
1540
+ esac
1541
+ fi
1542
+ else
1543
+ pstatus blue N/A "not testable in offline mode"
1544
+ fi
1545
+
1546
+ _info_nol " * IBPB enabled: "
1547
+ if [ "$opt_live" = 1 ]; then
1548
+ case "$ibpb_enabled" in
1549
+ "")
1550
+ if [ "$ibrs_supported" = 1 ]; then
1551
+ pstatus yellow UNKNOWN
1552
+ else
1553
+ pstatus red NO
1554
+ fi
1555
+ ;;
1556
+ 0)
1557
+ pstatus red NO
1558
+ _verbose " - To enable, \`echo 1 > $ibrs_knob_dir/ibpb_enabled' as root. If you don't have hardware support, you'll get an error."
1559
+ ;;
1560
+ 1) pstatus green YES;;
1561
+ 2) pstatus green YES "IBPB used instead of IBRS in all kernel entrypoints";;
1562
+ *) pstatus yellow UNKNOWN;;
1563
+ esac
1564
+ else
1565
+ pstatus blue N/A "not testable in offline mode"
1566
+ fi
1567
+
1568
+ _info "* Mitigation 2"
1569
+ _info_nol " * Kernel compiled with retpoline option: "
1570
+ # We check the RETPOLINE kernel options
1571
+ if [ -r "$opt_config" ]; then
1572
+ if grep -q '^CONFIG_RETPOLINE=y' "$opt_config"; then
1573
+ pstatus green YES
1574
+ retpoline=1
1575
+ # shellcheck disable=SC2046
1576
+ _debug 'retpoline: found '$(grep '^CONFIG_RETPOLINE' "$opt_config")" in $opt_config"
1577
+ else
1578
+ pstatus red NO
1579
+ fi
1580
+ else
1581
+ pstatus yellow UNKNOWN "couldn't read your kernel configuration"
1582
+ fi
1583
+
1584
+ _info_nol " * Kernel compiled with a retpoline-aware compiler: "
1585
+ # Now check if the compiler used to compile the kernel knows how to insert retpolines in generated asm
1586
+ # For gcc, this is -mindirect-branch=thunk-extern (detected by the kernel makefiles)
1587
+ # See gcc commit https://github.com/hjl-tools/gcc/commit/23b517d4a67c02d3ef80b6109218f2aadad7bd79
1588
+ # In latest retpoline LKML patches, the noretpoline_setup symbol exists only if CONFIG_RETPOLINE is set
1589
+ # *AND* if the compiler is retpoline-compliant, so look for that symbol
1590
+ if [ -e "/sys/devices/system/cpu/vulnerabilities/spectre_v2" ]; then
1591
+ if grep -qw Minimal /sys/devices/system/cpu/vulnerabilities/spectre_v2; then
1592
+ pstatus red NO "kernel reports minimal retpoline compilation"
1593
+ elif grep -qw Full /sys/devices/system/cpu/vulnerabilities/spectre_v2; then
1594
+ retpoline_compiler=1
1595
+ pstatus green YES "kernel reports full retpoline compilation"
1596
+ else
1597
+ if [ "$retpoline" = 1 ]; then
1598
+ pstatus yellow UNKNOWN
1599
+ else
1600
+ pstatus red NO
1601
+ fi
1602
+ fi
1603
+ elif [ -n "$opt_map" ]; then
1604
+ # look for the symbol
1605
+ if grep -qw noretpoline_setup "$opt_map"; then
1606
+ retpoline_compiler=1
1607
+ pstatus green YES "noretpoline_setup symbol found in System.map"
1608
+ else
1609
+ if [ "$retpoline" = 1 ]; then
1610
+ pstatus yellow UNKNOWN
1611
+ else
1612
+ pstatus red NO
1613
+ fi
1614
+ fi
1615
+ elif [ -n "$vmlinux" ]; then
1616
+ # look for the symbol
1617
+ if which nm >/dev/null 2>&1; then
1618
+ # the proper way: use nm and look for the symbol
1619
+ if nm "$vmlinux" 2>/dev/null | grep -qw 'noretpoline_setup'; then
1620
+ retpoline_compiler=1
1621
+ pstatus green YES "noretpoline_setup found in vmlinux symbols"
1622
+ else
1623
+ if [ "$retpoline" = 1 ]; then
1624
+ pstatus yellow UNKNOWN
1625
+ else
1626
+ pstatus red NO
1627
+ fi
1628
+ fi
1629
+ elif grep -q noretpoline_setup "$vmlinux"; then
1630
+ # if we don't have nm, nevermind, the symbol name is long enough to not have
1631
+ # any false positive using good old grep directly on the binary
1632
+ retpoline_compiler=1
1633
+ pstatus green YES "noretpoline_setup found in vmlinux"
1634
+ else
1635
+ if [ "$retpoline" = 1 ]; then
1636
+ pstatus yellow UNKNOWN
1637
+ else
1638
+ pstatus red NO
1639
+ fi
1640
+ fi
1641
+ else
1642
+ if [ "$retpoline" = 1 ]; then
1643
+ pstatus yellow UNKNOWN "couldn't find your kernel image or System.map"
1644
+ else
1645
+ pstatus red NO
1646
+ fi
1647
+ fi
1648
+ elif [ "$sys_interface_available" = 0 ]; then
1649
+ # we have no sysfs but were asked to use it only!
1650
+ msg="/sys vulnerability interface use forced, but it's not available!"
1651
+ status=UNK
1652
+ fi
1653
+
1654
+ cve='CVE-2017-5715'
1655
+ if ! is_cpu_vulnerable 2; then
1656
+ # override status & msg in case CPU is not vulnerable after all
1657
+ pvulnstatus $cve OK "your CPU vendor reported your CPU model as not vulnerable"
1658
+ elif [ -z "$msg" ]; then
1659
+ # if msg is empty, sysfs check didn't fill it, rely on our own test
1660
+ if [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ]; then
1661
+ pvulnstatus $cve OK "retpoline mitigates the vulnerability"
1662
+ elif [ "$opt_live" = 1 ]; then
1663
+ if ( [ "$ibrs_enabled" = 1 ] || [ "$ibrs_enabled" = 2 ] ) && [ "$ibpb_enabled" = 1 ]; then
1664
+ pvulnstatus $cve OK "IBRS/IBPB are mitigating the vulnerability"
1665
+ elif ( [ "$ibrs_enabled" = 1 ] || [ "$ibrs_enabled" = 2 ] ) && [ "$ibpb_enabled" = -1 ]; then
1666
+ # IBPB doesn't seem here on this kernel
1667
+ pvulnstatus $cve OK "IBRS is mitigating the vulnerability"
1668
+ elif [ "$ibpb_enabled" = 2 ]; then
1669
+ pvulnstatus $cve OK "Full IBPB is mitigating the vulnerability"
1670
+ elif [ "$ibrs_supported" = 1 ] && [ "$cpuid_spec_ctrl" != 1 ]; then
1671
+ pvulnstatus $cve VULN "Your kernel is compiled with IBRS but your CPU microcode is lacking support to successfully mitigate the vulnerability"
1672
+ else
1673
+ pvulnstatus $cve VULN "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
1674
+ fi
1675
+ else
1676
+ if [ "$ibrs_supported" = 1 ]; then
1677
+ pvulnstatus $cve OK "offline mode: IBRS/IBPB will mitigate the vulnerability if enabled at runtime"
1678
+ elif [ "$ibrs_can_tell" = 1 ]; then
1679
+ pvulnstatus $cve VULN "IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
1680
+ else
1681
+ pvulnstatus $cve UNK "offline mode: not enough information"
1682
+ fi
1683
+ fi
1684
+ else
1685
+ [ "$msg" = "Vulnerable" ] && msg="IBRS hardware + kernel support OR kernel with retpoline are needed to mitigate the vulnerability"
1686
+ pvulnstatus $cve "$status" "$msg"
1687
+ fi
1688
+ }
1689
+
1690
+ ########################
1691
+ # MELTDOWN aka VARIANT 3
1692
+ check_variant3()
1693
+ {
1694
+ _info "\033[1;34mCVE-2017-5754 [rogue data cache load] aka 'Meltdown' aka 'Variant 3'\033[0m"
1695
+
1696
+ status=UNK
1697
+ sys_interface_available=0
1698
+ msg=''
1699
+ if sys_interface_check "/sys/devices/system/cpu/vulnerabilities/meltdown"; then
1700
+ # this kernel has the /sys interface, trust it over everything
1701
+ sys_interface_available=1
1702
+ fi
1703
+ if [ "$opt_sysfs_only" != 1 ]; then
1704
+ _info_nol "* Kernel supports Page Table Isolation (PTI): "
1705
+ kpti_support=0
1706
+ kpti_can_tell=0
1707
+ if [ -n "$opt_config" ]; then
1708
+ kpti_can_tell=1
1709
+ if grep -Eq '^(CONFIG_PAGE_TABLE_ISOLATION|CONFIG_KAISER)=y' "$opt_config"; then
1710
+ # shellcheck disable=SC2046
1711
+ _debug 'kpti_support: found option '$(grep -E '^(CONFIG_PAGE_TABLE_ISOLATION|CONFIG_KAISER)=y' "$opt_config")" in $opt_config"
1712
+ kpti_support=1
1713
+ fi
1714
+ fi
1715
+ if [ "$kpti_support" = 0 ] && [ -n "$opt_map" ]; then
1716
+ # it's not an elif: some backports don't have the PTI config but still include the patch
1717
+ # so we try to find an exported symbol that is part of the PTI patch in System.map
1718
+ kpti_can_tell=1
1719
+ if grep -qw kpti_force_enabled "$opt_map"; then
1720
+ _debug "kpti_support: found kpti_force_enabled in $opt_map"
1721
+ kpti_support=1
1722
+ fi
1723
+ fi
1724
+ if [ "$kpti_support" = 0 ] && [ -n "$vmlinux" ]; then
1725
+ # same as above but in case we don't have System.map and only vmlinux, look for the
1726
+ # nopti option that is part of the patch (kernel command line option)
1727
+ kpti_can_tell=1
1728
+ if ! which strings >/dev/null 2>&1; then
1729
+ pstatus yellow UNKNOWN "missing 'strings' tool, please install it, usually it's in the binutils package"
1730
+ else
1731
+ if strings "$vmlinux" | grep -qw nopti; then
1732
+ _debug "kpti_support: found nopti string in $vmlinux"
1733
+ kpti_support=1
1734
+ fi
1735
+ fi
1736
+ fi
1737
+
1738
+ if [ "$kpti_support" = 1 ]; then
1739
+ pstatus green YES
1740
+ elif [ "$kpti_can_tell" = 1 ]; then
1741
+ pstatus red NO
1742
+ else
1743
+ pstatus yellow UNKNOWN "couldn't read your kernel configuration nor System.map file"
1744
+ fi
1745
+
1746
+ mount_debugfs
1747
+ _info_nol "* PTI enabled and active: "
1748
+ if [ "$opt_live" = 1 ]; then
1749
+ dmesg_grep="Kernel/User page tables isolation: enabled"
1750
+ dmesg_grep="$dmesg_grep|Kernel page table isolation enabled"
1751
+ dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace"
1752
+ if grep ^flags /proc/cpuinfo | grep -qw pti; then
1753
+ # vanilla PTI patch sets the 'pti' flag in cpuinfo
1754
+ _debug "kpti_enabled: found 'pti' flag in /proc/cpuinfo"
1755
+ kpti_enabled=1
1756
+ elif grep ^flags /proc/cpuinfo | grep -qw kaiser; then
1757
+ # kernel line 4.9 sets the 'kaiser' flag in cpuinfo
1758
+ _debug "kpti_enabled: found 'kaiser' flag in /proc/cpuinfo"
1759
+ kpti_enabled=1
1760
+ elif [ -e /sys/kernel/debug/x86/pti_enabled ]; then
1761
+ # Red Hat Backport creates a dedicated file, see https://access.redhat.com/articles/3311301
1762
+ kpti_enabled=$(cat /sys/kernel/debug/x86/pti_enabled 2>/dev/null)
1763
+ _debug "kpti_enabled: file /sys/kernel/debug/x86/pti_enabled exists and says: $kpti_enabled"
1764
+ fi
1765
+ if [ -z "$kpti_enabled" ]; then
1766
+ dmesg_grep "$dmesg_grep"; ret=$?
1767
+ if [ $ret -eq 0 ]; then
1768
+ _debug "kpti_enabled: found hint in dmesg: $dmesg_grepped"
1769
+ kpti_enabled=1
1770
+ elif [ $ret -eq 2 ]; then
1771
+ _debug "kpti_enabled: dmesg truncated"
1772
+ kpti_enabled=-1
1773
+ fi
1774
+ fi
1775
+ if [ -z "$kpti_enabled" ]; then
1776
+ _debug "kpti_enabled: couldn't find any hint that PTI is enabled"
1777
+ kpti_enabled=0
1778
+ fi
1779
+ if [ "$kpti_enabled" = 1 ]; then
1780
+ pstatus green YES
1781
+ elif [ "$kpti_enabled" = -1 ]; then
1782
+ pstatus yellow UNKNOWN "dmesg truncated, please reboot and relaunch this script"
1783
+ else
1784
+ pstatus red NO
1785
+ fi
1786
+ else
1787
+ pstatus blue N/A "can't verify if PTI is enabled in offline mode"
1788
+ fi
1789
+
1790
+ # no security impact but give a hint to the user in verbose mode
1791
+ # about PCID/INVPCID cpuid features that must be present to avoid
1792
+ # too big a performance impact with PTI
1793
+ # refs:
1794
+ # https://marc.info/?t=151532047900001&r=1&w=2
1795
+ # https://groups.google.com/forum/m/#!topic/mechanical-sympathy/L9mHTbeQLNU
1796
+ if [ "$opt_verbose" -ge 2 ]; then
1797
+ _info "* Performance impact if PTI is enabled"
1798
+ _info_nol " * CPU supports PCID: "
1799
+ if grep ^flags /proc/cpuinfo | grep -qw pcid; then
1800
+ pstatus green YES 'performance degradation with PTI will be limited'
1801
+ else
1802
+ pstatus blue NO 'no security impact but performance will be degraded with PTI'
1803
+ fi
1804
+ _info_nol " * CPU supports INVPCID: "
1805
+ if grep ^flags /proc/cpuinfo | grep -qw invpcid; then
1806
+ pstatus green YES 'performance degradation with PTI will be limited'
1807
+ else
1808
+ pstatus blue NO 'no security impact but performance will be degraded with PTI'
1809
+ fi
1810
+ fi
1811
+ elif [ "$sys_interface_available" = 0 ]; then
1812
+ # we have no sysfs but were asked to use it only!
1813
+ msg="/sys vulnerability interface use forced, but it's not available!"
1814
+ status=UNK
1815
+ fi
1816
+
1817
+
1818
+ # Test if the current host is a Xen PV Dom0 / DomU
1819
+ if [ -d "/proc/xen" ]; then
1820
+ # XXX do we have a better way that relying on dmesg?
1821
+ dmesg_grep 'Booting paravirtualized kernel on Xen$'; ret=$?
1822
+ if [ $ret -eq 2 ]; then
1823
+ _warn "dmesg truncated, Xen detection will be unreliable. Please reboot and relaunch this script"
1824
+ elif [ $ret -eq 0 ]; then
1825
+ if [ -e /proc/xen/capabilities ] && grep -q "control_d" /proc/xen/capabilities; then
1826
+ xen_pv_domo=1
1827
+ else
1828
+ xen_pv_domu=1
1829
+ fi
1830
+ fi
1831
+ fi
1832
+
1833
+ if [ "$opt_live" = 1 ]; then
1834
+ # checking whether we're running under Xen PV 64 bits. If yes, we are affected by variant3
1835
+ # (unless we are a Dom0)
1836
+ _info_nol "* Running as a Xen PV DomU: "
1837
+ if [ "$xen_pv_domu" = 1 ]; then
1838
+ pstatus red YES
1839
+ else
1840
+ pstatus green NO
1841
+ fi
1842
+ fi
1843
+
1844
+ cve='CVE-2017-5754'
1845
+ if ! is_cpu_vulnerable 3; then
1846
+ # override status & msg in case CPU is not vulnerable after all
1847
+ pvulnstatus $cve OK "your CPU vendor reported your CPU model as not vulnerable"
1848
+ elif [ -z "$msg" ]; then
1849
+ # if msg is empty, sysfs check didn't fill it, rely on our own test
1850
+ if [ "$opt_live" = 1 ]; then
1851
+ if [ "$kpti_enabled" = 1 ]; then
1852
+ pvulnstatus $cve OK "PTI mitigates the vulnerability"
1853
+ elif [ "$xen_pv_domo" = 1 ]; then
1854
+ pvulnstatus $cve OK "Xen Dom0s are safe and do not require PTI"
1855
+ elif [ "$xen_pv_domu" = 1 ]; then
1856
+ pvulnstatus $cve VULN "Xen PV DomUs are vulnerable and need to be run in HVM, PVHVM, PVH mode, or the Xen hypervisor must have the Xen's own PTI patch"
1857
+ else
1858
+ pvulnstatus $cve VULN "PTI is needed to mitigate the vulnerability"
1859
+ fi
1860
+ else
1861
+ if [ "$kpti_support" = 1 ]; then
1862
+ pvulnstatus $cve OK "offline mode: PTI will mitigate the vulnerability if enabled at runtime"
1863
+ elif [ "$kpti_can_tell" = 1 ]; then
1864
+ pvulnstatus $cve VULN "PTI is needed to mitigate the vulnerability"
1865
+ else
1866
+ pvulnstatus $cve UNK "offline mode: not enough information"
1867
+ fi
1868
+ fi
1869
+ else
1870
+ if [ "$xen_pv_domo" = 1 ]; then
1871
+ msg="Xen Dom0s are safe and do not require PTI"
1872
+ status="OK"
1873
+ elif [ "$xen_pv_domu" = 1 ]; then
1874
+ msg="Xen PV DomUs are vulnerable and need to be run in HVM, PVHVM or PVH mode"
1875
+ status="VULN"
1876
+ elif [ "$msg" = "Vulnerable" ]; then
1877
+ msg="PTI is needed to mitigate the vulnerability"
1878
+ fi
1879
+ pvulnstatus $cve "$status" "$msg"
1880
+ fi
1881
+
1882
+ # Warn the user about XSA-254 recommended mitigations
1883
+ if [ "$xen_pv_domo" = 1 ]; then
1884
+ _warn
1885
+ _warn "This host is a Xen Dom0. Please make sure that you are running your DomUs"
1886
+ _warn "in HVM, PVHVM or PVH mode to prevent any guest-to-host / host-to-guest attacks."
1887
+ _warn
1888
+ _warn "See https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ and XSA-254 for details."
1889
+ fi
1890
+ }
1891
+
1892
+ check_cpu
1893
+ # now run the checks the user asked for
1894
+ if [ "$opt_variant1" = 1 ] || [ "$opt_allvariants" = 1 ]; then
1895
+ check_variant1
1896
+ _info
1897
+ fi
1898
+ if [ "$opt_variant2" = 1 ] || [ "$opt_allvariants" = 1 ]; then
1899
+ check_variant2
1900
+ _info
1901
+ fi
1902
+ if [ "$opt_variant3" = 1 ] || [ "$opt_allvariants" = 1 ]; then
1903
+ check_variant3
1904
+ _info
1905
+ fi
1906
+
1907
+ _info "A false sense of security is worse than no security at all, see --disclaimer"
1908
+
1909
+ if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "nrpe" ]; then
1910
+ if [ ! -z "$nrpe_vuln" ]; then
1911
+ echo "Vulnerable:$nrpe_vuln"
1912
+ else
1913
+ echo "OK"
1914
+ fi
1915
+ fi
1916
+
1917
+ if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
1918
+ _echo 0 "${json_output%?}]"
1919
+ fi
1920
+
1921
+ if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then
1922
+ echo "# TYPE specex_vuln_status untyped"
1923
+ echo "# HELP specex_vuln_status Exposure of system to speculative execution vulnerabilities"
1924
+ echo "$prometheus_output"
1925
+ fi
1926
+
1927
+ # exit with the proper exit code
1928
+ # [ "$global_critical" = 1 ] && exit 2 # critical
1929
+ # [ "$global_unknown" = 1 ] && exit 3 # unknown
1930
+ # exit 0 # ok