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 */
26
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>
36
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <arpa/inet.h>
40
41 #include <xenctrl.h>
42 #include <xen/xen.h>
43 #include <xen/domctl.h>
44 #include <xen/hvm/save.h>
45
46 int
main(int argc,char ** argv)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;
57
58 if (argc != 2 || !argv[1] || (domid = atoi(argv[1])) < 0) {
59 fprintf(stderr, "usage: %s <domid>\n", argv[0]);
60 exit(1);
61 }
62
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 }
68
69 ret = xc_domain_getinfo(xch, domid, 1, &dominfo);
70 if (ret < 0) {
71 perror("xc_domain_getinfo");
72 exit(1);
73 }
74
75 if (!dominfo.hvm) {
76 fprintf(stderr, "domain %d is not HVM\n", domid);
77 exit(1);
78 }
79
80 ret = xc_domain_pause(xch, domid);
81 if (ret < 0) {
82 perror("xc_domain_pause");
83 exit(-1);
84 }
85
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 }
95
96 len = ret;
97 buf = malloc(len);
98 if (buf == NULL) {
99 perror("malloc");
100 exit(1);
101 }
102
103 ret = xc_domain_hvm_getcontext(xch, domid, buf, len);
104 if (ret < 0) {
105 perror("xc_domain_hvm_getcontext");
106 exit(1);
107 }
108
109 off = 0;
110
111 while (off < len) {
112 descriptor = (struct hvm_save_descriptor *)(buf + off);
113
114 off += sizeof (struct hvm_save_descriptor);
115
116 if (descriptor->typecode == HVM_SAVE_CODE(CPU)) {
117 HVM_SAVE_TYPE(CPU) *cpu;
118
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 }
126
127 off += descriptor->length;
128 }
129
130 ret = xc_domain_hvm_setcontext(xch, domid, buf, len);
131 if (ret < 0) {
132 perror("xc_domain_hvm_setcontext");
133 exit(1);
134 }
135
136 ret = xc_domain_unpause(xch, domid);
137 if (ret < 0) {
138 perror("xc_domain_unpause");
139 exit(1);
140 }
141
142 return 0;
143 }
144