9df4dc21ff6a2b6f2fe66e8c4bee8f2e74609cdd
[libguestfs.git] / daemon / debug.c
1 /* libguestfs - the guestfsd daemon
2  * Copyright (C) 2009 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <dirent.h>
29 #include <sys/resource.h>
30
31 #include "../src/guestfs_protocol.h"
32 #include "daemon.h"
33 #include "actions.h"
34
35 /* This command exposes debugging information, internals and
36  * status.  There is no comprehensive documentation for this
37  * command.  You have to look at the source code in this file
38  * to find out what you can do.
39  *
40  * Commands always output a freeform string.
41  *
42  * Since libguestfs 1.5.7, the debug command has been enabled
43  * by default for all builds (previously you had to enable it
44  * in configure).  This command is not part of the stable ABI
45  * and may change at any time.
46  */
47
48 struct cmd {
49   const char *cmd;
50   char * (*f) (const char *subcmd, int argc, char *const *const argv);
51 };
52
53 static char *debug_help (const char *subcmd, int argc, char *const *const argv);
54 static char *debug_core_pattern (const char *subcmd, int argc, char *const *const argv);
55 static char *debug_env (const char *subcmd, int argc, char *const *const argv);
56 static char *debug_fds (const char *subcmd, int argc, char *const *const argv);
57 static char *debug_ls (const char *subcmd, int argc, char *const *const argv);
58 static char *debug_ll (const char *subcmd, int argc, char *const *const argv);
59 static char *debug_segv (const char *subcmd, int argc, char *const *const argv);
60 static char *debug_sh (const char *subcmd, int argc, char *const *const argv);
61
62 static struct cmd cmds[] = {
63   { "help", debug_help },
64   { "core_pattern", debug_core_pattern },
65   { "env", debug_env },
66   { "fds", debug_fds },
67   { "ls", debug_ls },
68   { "ll", debug_ll },
69   { "segv", debug_segv },
70   { "sh", debug_sh },
71   { NULL, NULL }
72 };
73
74 char *
75 do_debug (const char *subcmd, char *const *argv)
76 {
77   int argc, i;
78
79   for (i = argc = 0; argv[i] != NULL; ++i)
80     argc++;
81
82   for (i = 0; cmds[i].cmd != NULL; ++i) {
83     if (STRCASEEQ (subcmd, cmds[i].cmd))
84       return cmds[i].f (subcmd, argc, argv);
85   }
86
87   reply_with_error ("use 'debug help' to list the supported commands");
88   return NULL;
89 }
90
91 static char *
92 debug_help (const char *subcmd, int argc, char *const *const argv)
93 {
94   int len, i;
95   char *r, *p;
96
97   r = strdup ("Commands supported:");
98   if (!r) {
99     reply_with_perror ("strdup");
100     return NULL;
101   }
102
103   len = strlen (r);
104   for (i = 0; cmds[i].cmd != NULL; ++i) {
105     len += strlen (cmds[i].cmd) + 1; /* space + new command */
106     p = realloc (r, len + 1);        /* +1 for the final NUL */
107     if (p == NULL) {
108       reply_with_perror ("realloc");
109       free (r);
110       return NULL;
111     }
112     r = p;
113
114     strcat (r, " ");
115     strcat (r, cmds[i].cmd);
116   }
117
118   return r;
119 }
120
121 /* Show open FDs. */
122 static char *
123 debug_fds (const char *subcmd, int argc, char *const *const argv)
124 {
125   int r;
126   char *out;
127   size_t size;
128   FILE *fp;
129   DIR *dir;
130   struct dirent *d;
131   char fname[256], link[256];
132   struct stat statbuf;
133
134   fp = open_memstream (&out, &size);
135   if (!fp) {
136     reply_with_perror ("open_memstream");
137     return NULL;
138   }
139
140   dir = opendir ("/proc/self/fd");
141   if (!dir) {
142     reply_with_perror ("opendir: /proc/self/fd");
143     fclose (fp);
144     return NULL;
145   }
146
147   while ((d = readdir (dir)) != NULL) {
148     if (STREQ (d->d_name, ".") || STREQ (d->d_name, ".."))
149       continue;
150
151     snprintf (fname, sizeof fname, "/proc/self/fd/%s", d->d_name);
152
153     r = lstat (fname, &statbuf);
154     if (r == -1) {
155       reply_with_perror ("stat: %s", fname);
156       fclose (fp);
157       free (out);
158       closedir (dir);
159       return NULL;
160     }
161
162     if (S_ISLNK (statbuf.st_mode)) {
163       r = readlink (fname, link, sizeof link - 1);
164       if (r == -1) {
165         reply_with_perror ("readline: %s", fname);
166         fclose (fp);
167         free (out);
168         closedir (dir);
169         return NULL;
170       }
171       link[r] = '\0';
172
173       fprintf (fp, "%2s %s\n", d->d_name, link);
174     } else
175       fprintf (fp, "%2s 0%o\n", d->d_name, statbuf.st_mode);
176   }
177
178   fclose (fp);
179
180   if (closedir (dir) == -1) {
181     reply_with_perror ("closedir");
182     free (out);
183     return NULL;
184   }
185
186   return out;
187 }
188
189 /* Force a segfault in the daemon. */
190 static char *
191 debug_segv (const char *subcmd, int argc, char *const *const argv)
192 {
193   *(int*)0 = 0;
194   return NULL;
195 }
196
197 /* Run an arbitrary shell command using /bin/sh from the appliance.
198  *
199  * Note this is somewhat different from the ordinary guestfs_sh command
200  * because it's not using the guest shell, and is not chrooted.
201  */
202 static char *
203 debug_sh (const char *subcmd, int argc, char *const *const argv)
204 {
205   if (argc < 1) {
206     reply_with_error ("sh: expecting a command to run");
207     return NULL;
208   }
209
210   char *cmd;
211   int len, i, j;
212
213   /* guestfish splits the parameter(s) into a list of strings,
214    * and we have to reassemble them here.  Not ideal. XXX
215    */
216   for (i = len = 0; i < argc; ++i)
217     len += strlen (argv[i]) + 1;
218   cmd = malloc (len);
219   if (!cmd) {
220     reply_with_perror ("malloc");
221     return NULL;
222   }
223   for (i = j = 0; i < argc; ++i) {
224     len = strlen (argv[i]);
225     memcpy (&cmd[j], argv[i], len);
226     j += len;
227     cmd[j] = ' ';
228     j++;
229   }
230   cmd[j-1] = '\0';
231
232   /* Set up some environment variables. */
233   setenv ("root", sysroot, 1);
234   if (access ("/sys/block/sda", F_OK) == 0)
235     setenv ("sd", "sd", 1);
236   else if (access ("/sys/block/hda", F_OK) == 0)
237     setenv ("sd", "hd", 1);
238   else if (access ("/sys/block/vda", F_OK) == 0)
239     setenv ("sd", "vd", 1);
240
241   char *err;
242   int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
243                     "/bin/sh", "-c", cmd, NULL);
244   free (cmd);
245
246   if (r == -1) {
247     reply_with_error ("%s", err);
248     free (err);
249     return NULL;
250   }
251
252   return err;
253 }
254
255 /* Print the environment that commands get (by running external printenv). */
256 static char *
257 debug_env (const char *subcmd, int argc, char *const *const argv)
258 {
259   int r;
260   char *out, *err;
261
262   r = command (&out, &err, "printenv", NULL);
263   if (r == -1) {
264     reply_with_error ("printenv: %s", err);
265     free (out);
266     free (err);
267     return NULL;
268   }
269
270   free (err);
271
272   return out;
273 }
274
275 /* List files in the appliance. */
276 static char *
277 debug_ls (const char *subcmd, int argc, char *const *const argv)
278 {
279   int len = count_strings (argv);
280   const char *cargv[len+3];
281   int i;
282
283   cargv[0] = "ls";
284   cargv[1] = "-a";
285   for (i = 0; i < len; ++i)
286     cargv[2+i] = argv[i];
287   cargv[2+len] = NULL;
288
289   int r;
290   char *out, *err;
291
292   r = commandv (&out, &err, (void *) cargv);
293   if (r == -1) {
294     reply_with_error ("ls: %s", err);
295     free (out);
296     free (err);
297     return NULL;
298   }
299
300   free (err);
301
302   return out;
303 }
304
305 /* List files in the appliance. */
306 static char *
307 debug_ll (const char *subcmd, int argc, char *const *const argv)
308 {
309   int len = count_strings (argv);
310   const char *cargv[len+3];
311   int i;
312
313   cargv[0] = "ls";
314   cargv[1] = "-la";
315   for (i = 0; i < len; ++i)
316     cargv[2+i] = argv[i];
317   cargv[2+len] = NULL;
318
319   int r;
320   char *out, *err;
321
322   r = commandv (&out, &err, (void *) cargv);
323   if (r == -1) {
324     reply_with_error ("ll: %s", err);
325     free (out);
326     free (err);
327     return NULL;
328   }
329
330   free (err);
331
332   return out;
333 }
334
335 /* Enable core dumping to the given core pattern.
336  * Note that this pattern is relative to any chroot of the process which
337  * crashes. This means that if you want to write the core file to the guest's
338  * storage the pattern must start with /sysroot only if the command which
339  * crashes doesn't chroot.
340  */
341 static char *
342 debug_core_pattern (const char *subcmd, int argc, char *const *const argv)
343 {
344   if (argc < 1) {
345     reply_with_error ("core_pattern: expecting a core pattern");
346     return NULL;
347   }
348
349   const char *pattern = argv[0];
350   const size_t pattern_len = strlen(pattern);
351
352 #define CORE_PATTERN "/proc/sys/kernel/core_pattern"
353   int fd = open (CORE_PATTERN, O_WRONLY);
354   if (fd == -1) {
355     reply_with_perror ("open: " CORE_PATTERN);
356     return NULL;
357   }
358   if (write (fd, pattern, pattern_len) < (ssize_t) pattern_len) {
359     reply_with_perror ("write: " CORE_PATTERN);
360     return NULL;
361   }
362   if (close (fd) == -1) {
363     reply_with_perror ("close: " CORE_PATTERN);
364     return NULL;
365   }
366
367   struct rlimit limit = {
368     .rlim_cur = RLIM_INFINITY,
369     .rlim_max = RLIM_INFINITY
370   };
371   if (setrlimit (RLIMIT_CORE, &limit) == -1) {
372     reply_with_perror ("setrlimit (RLIMIT_CORE)");
373     return NULL;
374   }
375
376   char *ret = strdup ("ok");
377   if (NULL == ret) {
378     reply_with_perror ("strdup");
379     return NULL;
380   }
381
382   return ret;
383 }
384
385 static int
386 write_cb (void *fd_ptr, const void *buf, size_t len)
387 {
388   int fd = *(int *)fd_ptr;
389   return xwrite (fd, buf, len);
390 }
391
392 /* Has one FileIn parameter. */
393 int
394 do_debug_upload (const char *filename, int mode)
395 {
396   /* Not chrooted - this command lets you upload a file to anywhere
397    * in the appliance.
398    */
399   int fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, mode);
400
401   if (fd == -1) {
402     int err = errno;
403     cancel_receive ();
404     errno = err;
405     reply_with_perror ("%s", filename);
406     return -1;
407   }
408
409   int r = receive_file (write_cb, &fd);
410   if (r == -1) {                /* write error */
411     int err = errno;
412     cancel_receive ();
413     errno = err;
414     reply_with_error ("write error: %s", filename);
415     close (fd);
416     return -1;
417   }
418   if (r == -2) {                /* cancellation from library */
419     close (fd);
420     /* Do NOT send any error. */
421     return -1;
422   }
423
424   if (close (fd) == -1) {
425     int err = errno;
426     if (r == -1)                /* if r == 0, file transfer ended already */
427       cancel_receive ();
428     errno = err;
429     reply_with_perror ("close: %s", filename);
430     return -1;
431   }
432
433   return 0;
434 }