|
| 1 | +#!/usr/bin/python3 |
| 2 | + |
| 3 | +# SPDX-License-Identifier: GPL-2.0-only |
| 4 | +# Copyright (c) 2026 Intel Corporation |
| 5 | + |
| 6 | +# Author: Kai Zhang <kai.zhang@intel.com> |
| 7 | +# |
| 8 | +# History: Apr. 2026 - Kai Zhang - creation |
| 9 | + |
| 10 | + |
| 11 | +from provider import dmesg_router # pylint: disable=unused-import |
| 12 | +from avocado.utils import process |
| 13 | +from virttest import error_context, env_process |
| 14 | +from provider.cpu_utils import check_cpu_flags |
| 15 | + |
| 16 | + |
| 17 | +def check_confident(vm, session, dump_memory_path): |
| 18 | + session.cmd("mkdir -pv /tmp/mnt/") |
| 19 | + session.cmd("mount tmpfs /tmp/mnt/ -t tmpfs -o size=32M") |
| 20 | + vm.copy_files_to("/tmp/secret", "/tmp/mnt/") |
| 21 | + |
| 22 | + # paging = "off" |
| 23 | + process.system("rm -f %s && touch %s" % (dump_memory_path, dump_memory_path), ignore_status=True) |
| 24 | + vm.monitor.human_monitor_cmd("dump-guest-memory %s" % dump_memory_path) |
| 25 | + with open(dump_memory_path, '+rb') as f: |
| 26 | + content = f.read().decode('utf-8', errors='ignore') |
| 27 | + if "TDX Test" not in content: |
| 28 | + return False |
| 29 | + return True |
| 30 | + |
| 31 | + |
| 32 | +@error_context.context_aware |
| 33 | +def run(test, params, env): |
| 34 | + """ |
| 35 | + TDX memory confidentiality test: |
| 36 | + 1. Boot VM |
| 37 | + 2. Write something in a file on host and copy it to tmpfs on VM |
| 38 | + 3. Dump memory from VM, expect the secret could be found |
| 39 | + 4. Boot TDVM |
| 40 | + 5. Write something in a file on host and copy it to tmpfs on TDVM |
| 41 | + 6. Dump memory from TDVM, expect the secret could not be found |
| 42 | +
|
| 43 | + :param test: QEMU test object |
| 44 | + :param params: Dictionary with the test parameters |
| 45 | + :param env: Dictionary with test environment. |
| 46 | +
|
| 47 | + This test will create both legacy VM and tdx-enabled VM. |
| 48 | + """ |
| 49 | + with open("/tmp/secret", "w") as secret_file: |
| 50 | + secret_file.write("TDX Test: This is a test\n") |
| 51 | + dump_memory_path = params.get("dump_memory_path") |
| 52 | + params["start_vm"] = "yes" |
| 53 | + env_process.preprocess_vm(test, params, env, params["main_vm"]) |
| 54 | + vm = env.get_vm(params["main_vm"]) |
| 55 | + vm.verify_alive() |
| 56 | + timeout = params.get_numeric("login_timeout", 240) |
| 57 | + session = vm.wait_for_login(timeout=timeout) |
| 58 | + copy_result = check_confident(vm, session, dump_memory_path) |
| 59 | + if not copy_result: |
| 60 | + test.fail("Secret is not found in memory dump of legacy VM") |
| 61 | + session.close() |
| 62 | + vm.destroy() |
| 63 | + |
| 64 | + params["vm_secure_guest_type"] = "tdx" |
| 65 | + params["guest_flags"] = "tdx_guest" |
| 66 | + env_process.preprocess_vm(test, params, env, params["main_vm"]) |
| 67 | + vm = env.get_vm(params["main_vm"]) |
| 68 | + vm.verify_alive() |
| 69 | + timeout = params.get_numeric("login_timeout", 240) |
| 70 | + session = vm.wait_for_login(timeout=timeout) |
| 71 | + flags = params["guest_flags"] |
| 72 | + check_cpu_flags(params, flags, test, session) |
| 73 | + copy_result = check_confident(vm, session, dump_memory_path) |
| 74 | + if copy_result: |
| 75 | + test.fail("Secret is found in memory dump of TDVM") |
| 76 | + process.system("rm -f /tmp/secret %s" % params["dump_memory_path"], ignore_status=True) |
| 77 | + # TDVM will be destroyed as `kill_vm = yes` is set in cfg, no need to destroy it here. |
| 78 | + session.close() |
0 commit comments