debuggers.hg

view tools/misc/xen-hvmcrash.c @ 21939:754877be695b

tools/misc: xen-hvmcrash: New tool to attempt to crash HVM guests

This tool reads the CPU save records, overwrites RIP with a bogus
value, and then restores them. This is, of course, not guaranteed
to crash the guest (since the CPUs may not be executing in kernel
at the time) but it's good for breaking into some tight loops that
would be hard to debug otherwise.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Paul Durrant <paul.durrant@citrix.com>
date Thu Jul 29 18:58:19 2010 +0100 (2010-07-29)
parents
children
line source
1 /*
2 * xen-hvmcrash.c
3 *
4 * Attempt to crash an HVM guest by overwriting RIP/EIP with a bogus value
5 *
6 * Copyright (c) 2010 Citrix Systems, Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to
10 * deal in the Software without restriction, including without limitation the
11 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 * sell copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
27 #include <inttypes.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stddef.h>
31 #include <stdint.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <limits.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <arpa/inet.h>
41 #include <xenctrl.h>
42 #include <xen/xen.h>
43 #include <xen/domctl.h>
44 #include <xen/hvm/save.h>
46 int
47 main(int argc, char **argv)
48 {
49 int domid;
50 xc_interface *xch;
51 xc_dominfo_t dominfo;
52 int ret;
53 uint32_t len;
54 uint8_t *buf;
55 uint32_t off;
56 struct hvm_save_descriptor *descriptor;
58 if (argc != 2 || !argv[1] || (domid = atoi(argv[1])) < 0) {
59 fprintf(stderr, "usage: %s <domid>\n", argv[0]);
60 exit(1);
61 }
63 xch = xc_interface_open(0, 0, 0);
64 if (!xch) {
65 fprintf(stderr, "error: can't open libxc handle\n");
66 exit(1);
67 }
69 ret = xc_domain_getinfo(xch, domid, 1, &dominfo);
70 if (ret < 0) {
71 perror("xc_domain_getinfo");
72 exit(1);
73 }
75 if (!dominfo.hvm) {
76 fprintf(stderr, "domain %d is not HVM\n", domid);
77 exit(1);
78 }
80 ret = xc_domain_pause(xch, domid);
81 if (ret < 0) {
82 perror("xc_domain_pause");
83 exit(-1);
84 }
86 /*
87 * Calling with zero buffer length should return the buffer length
88 * required.
89 */
90 ret = xc_domain_hvm_getcontext(xch, domid, 0, 0);
91 if (ret < 0) {
92 perror("xc_domain_hvm_getcontext");
93 exit(1);
94 }
96 len = ret;
97 buf = malloc(len);
98 if (buf == NULL) {
99 perror("malloc");
100 exit(1);
101 }
103 ret = xc_domain_hvm_getcontext(xch, domid, buf, len);
104 if (ret < 0) {
105 perror("xc_domain_hvm_getcontext");
106 exit(1);
107 }
109 off = 0;
111 while (off < len) {
112 descriptor = (struct hvm_save_descriptor *)(buf + off);
114 off += sizeof (struct hvm_save_descriptor);
116 if (descriptor->typecode == HVM_SAVE_CODE(CPU)) {
117 HVM_SAVE_TYPE(CPU) *cpu;
119 /* Overwrite EIP/RIP with some recognisable but bogus value */
120 cpu = (HVM_SAVE_TYPE(CPU) *)(buf + off);
121 printf("CPU[%d]: RIP = %" PRIx64 "\n", descriptor->instance, cpu->rip);
122 cpu->rip = 0xf001;
123 } else if (descriptor->typecode == HVM_SAVE_CODE(END)) {
124 break;
125 }
127 off += descriptor->length;
128 }
130 ret = xc_domain_hvm_setcontext(xch, domid, buf, len);
131 if (ret < 0) {
132 perror("xc_domain_hvm_setcontext");
133 exit(1);
134 }
136 ret = xc_domain_unpause(xch, domid);
137 if (ret < 0) {
138 perror("xc_domain_unpause");
139 exit(1);
140 }
142 return 0;
143 }