Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
psaction.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, 2012, 2013, 2014 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (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, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <string.h>
23 
24 #include <sys/user.h>
25 #include <sys/ptrace.h>
26 #include <inttypes.h>
27 
28 #include <signal.h>
29 
30 #include <argp.h>
31 
32 #include "log.h"
33 #include "dwdebug.h"
34 #include "target_api.h"
35 #include "target.h"
37 
38 #include "probe_api.h"
39 #include "probe.h"
40 #include "alist.h"
41 #include "list.h"
42 
43 struct target *t = NULL;
44 
45 GHashTable *probes = NULL;
46 
48  GHashTableIter iter;
49  gpointer key;
50  struct probe *probe;
51  target_status_t retval;
52 
53  if (probes) {
54  g_hash_table_iter_init(&iter,probes);
55  while (g_hash_table_iter_next(&iter,
56  (gpointer)&key,
57  (gpointer)&probe)) {
58  probe_unregister(probe,1);
59  probe_free(probe,1);
60  }
61  }
62  retval = target_close(t);
63  target_finalize(t);
64 
65  if (probes)
66  g_hash_table_destroy(probes);
67 
68  return retval;
69 }
70 
71 void sigh(int signo) {
72  if (t) {
73  target_pause(t);
74  cleanup();
75  }
76  exit(0);
77 }
78 
79 int pslist_list(struct target *target,struct value *value,void *data) {
80  struct value *pid_v;
81  struct value *uid_v;
82  struct value *name_v;
83 
84  pid_v = target_load_value_member(target,NULL,value,"pid",NULL,LOAD_FLAG_NONE);
85  name_v = target_load_value_member(target,NULL,value,"comm",NULL,LOAD_FLAG_NONE);
86  uid_v = target_load_value_member(target,NULL,value,"uid",NULL,LOAD_FLAG_NONE);
87  if (!uid_v)
88  uid_v = target_load_value_member(target,NULL,value,"cred.uid",NULL,
90 
91  printf("%d\t%d\t%s\n",v_u32(pid_v),v_u32(uid_v),name_v->buf);
92 
93  value_free(pid_v);
94  value_free(uid_v);
95  value_free(name_v);
96 
97  return 0;
98 }
99 
100 int pslist_check(struct target *target,struct value *value,void *data) {
101  struct value *pid_v;
102  struct value *uid_v;
103  struct value *name_v;
104  struct rfilter *rf = (struct rfilter *)data;
105  int accept;
106 
107  name_v = target_load_value_member(target,NULL,value,"comm",NULL,LOAD_FLAG_NONE);
108  rfilter_check(rf,name_v->buf,&accept,NULL);
109  if (accept == RF_ACCEPT) {
110  value_free(name_v);
111  return 0;
112  }
113 
114  pid_v = target_load_value_member(target,NULL,value,"pid",NULL,LOAD_FLAG_NONE);
115  uid_v = target_load_value_member(target,NULL,value,"uid",NULL,LOAD_FLAG_NONE);
116  if (!uid_v)
117  uid_v = target_load_value_member(target,NULL,value,"cred.uid",NULL,
119 
120  printf("Check found bad %d\t%d\t%s\n",v_u32(pid_v),v_u32(uid_v),name_v->buf);
121 
122  value_free(pid_v);
123  value_free(uid_v);
124  value_free(name_v);
125 
126  return 0;
127 }
128 
129 int pslist_zombie(struct target *target,struct value *value,void *data) {
130  struct value *pid_v;
131  struct value *uid_v;
132  struct value *name_v;
133  struct rfilter *rf = (struct rfilter *)data;
134  int accept;
135  struct value *v;
136 
137  name_v = target_load_value_member(target,NULL,value,"comm",NULL,LOAD_FLAG_NONE);
138  rfilter_check(rf,name_v->buf,&accept,NULL);
139  if (accept == RF_REJECT) {
140  value_free(name_v);
141  return 0;
142  }
143 
144  pid_v = target_load_value_member(target,NULL,value,"pid",NULL,LOAD_FLAG_NONE);
145  uid_v = target_load_value_member(target,NULL,value,"uid",NULL,LOAD_FLAG_NONE);
146  if (!uid_v)
147  uid_v = target_load_value_member(target,NULL,value,"cred.uid",NULL,
149 
150  printf("Zombifying %d\t%d\t%s\n",v_u32(pid_v),v_u32(uid_v),name_v->buf);
151 
152  value_free(pid_v);
153  value_free(uid_v);
154  value_free(name_v);
155 
156  /* Set task_struct->state = -1 */
157  v = target_load_value_member(target,NULL,value,"state",NULL,LOAD_FLAG_NONE);
158  value_update_num(v,-1);
159  target_store_value(target,v);
160  value_free(v);
161 
162  return 0;
163 }
164 
165 #define LOCAL_NSIG 64
166 #define LOCAL_NSIG_BPW 32
167 #define LOCAL_NSIG_WORDS (LOCAL_NSIG / LOCAL_NSIG_BPW)
168 typedef struct {
169  unsigned long sig[LOCAL_NSIG_WORDS];
171 
172 struct signame {
173  char *name;
174  int signo;
175 };
176 
177 static struct signame sigmap[] = {
178  { "SIGHUP",SIGHUP },
179  { "SIGINT",SIGINT },
180  { "SIGQUIT",SIGQUIT },
181  { "SIGILL",SIGILL },
182  { "SIGTRAP",SIGTRAP },
183  { "SIGABRT",SIGABRT },
184  { "SIGIOT",SIGIOT },
185  { "SIGBUS",SIGBUS },
186  { "SIGFPE",SIGFPE },
187  { "SIGKILL",SIGKILL },
188  { "SIGUSR1",SIGUSR1 },
189  { "SIGSEGV",SIGSEGV },
190  { "SIGUSR2",SIGUSR2 },
191  { "SIGPIPE",SIGPIPE },
192  { "SIGALRM",SIGALRM },
193  { "SIGTERM",SIGTERM },
194  { "SIGSTKFLT",SIGSTKFLT },
195  { "SIGCLD",SIGCLD },
196  { "SIGCHLD",SIGCHLD },
197  { "SIGCONT",SIGCONT },
198  { "SIGSTOP",SIGSTOP },
199  { "SIGTSTP",SIGTSTP },
200  { "SIGTTIN",SIGTTIN },
201  { "SIGTTOU",SIGTTOU },
202  { "SIGURG",SIGURG },
203  { "SIGXCPU",SIGXCPU },
204  { "SIGXFSZ",SIGXFSZ },
205  { "SIGVTALRM",SIGVTALRM },
206  { "SIGPROF",SIGPROF },
207  { "SIGWINCH",SIGWINCH },
208  { "SIGPOLL",SIGPOLL },
209  { "SIGIO",SIGIO },
210  { "SIGPWR",SIGPWR },
211  { "SIGSYS",SIGSYS },
212  { NULL,-1 },
213 };
214 
215 static int convert_arg_to_sig(char *arg) {
216  unsigned int i;
217  unsigned int len;
218  char *argcopy = NULL;
219 
220  if (isdigit(*arg))
221  return atoi(arg);
222 
223  argcopy = strdup(arg);
224  len = strlen(argcopy);
225  for (i = 0; i < len; ++i)
226  argcopy[i] = toupper(argcopy[i]);
227 
228  for (i = 0; i < sizeof(sigmap) / sizeof(struct signame); ++i) {
229  if (!sigmap[i].name)
230  continue;
231  if (strcmp(sigmap[i].name,argcopy) == 0) {
232  free(argcopy);
233  return sigmap[i].signo;
234  }
235  }
236 
237  free(argcopy);
238 
239  /* Prepend SIG and try again. */
240  len = strlen(arg) + 3 + 1;
241  argcopy = (char *)malloc(len);
242  snprintf(argcopy,len,"SIG%s",arg);
243  for (i = 0; i < len; ++i)
244  argcopy[i] = toupper(argcopy[i]);
245  for (i = 0; i < sizeof(sigmap) / sizeof(struct signame); ++i) {
246  if (!sigmap[i].name)
247  continue;
248  if (strcmp(sigmap[i].name,argcopy) == 0) {
249  free(argcopy);
250  return sigmap[i].signo;
251  }
252  }
253 
254  free(argcopy);
255  return -1;
256 }
257 
258 static char *convert_sig_to_name(int signo) {
259  unsigned int i;
260 
261  for (i = 0; i < sizeof(sigmap) / sizeof(struct signame); ++i) {
262  if (!sigmap[i].name)
263  continue;
264  if (sigmap[i].signo == signo)
265  return sigmap[i].name;
266  }
267  return NULL;
268 }
269 
270 struct psa_siginfo {
271  struct rfilter *rf;
272  int sig;
273 };
274 
275 int pslist_sig(struct target *target,struct value *value,void *data) {
276  struct value *pid_v;
277  struct value *uid_v;
278  struct value *name_v;
279  struct psa_siginfo *psa_siginfo = (struct psa_siginfo *)data;
280  struct rfilter *rf = psa_siginfo->rf;
281  int accept;
282  struct value *signal_v;
283  struct value *signal_pending_v;
284  struct value *signal_pending_signal_v;
285  struct value *v;
286  int sig = psa_siginfo->sig;
287  uint32_t sigmask = 1UL << (sig - 1);
288  struct value *thread_info_v;
289 
290  name_v = target_load_value_member(target,NULL,value,"comm",NULL,LOAD_FLAG_NONE);
291  rfilter_check(rf,name_v->buf,&accept,NULL);
292  if (accept == RF_REJECT) {
293  value_free(name_v);
294  return 0;
295  }
296 
297  pid_v = target_load_value_member(target,NULL,value,"pid",NULL,LOAD_FLAG_NONE);
298  uid_v = target_load_value_member(target,NULL,value,"uid",NULL,LOAD_FLAG_NONE);
299  if (!uid_v)
300  uid_v = target_load_value_member(target,NULL,value,"cred.uid",NULL,
302 
303  printf("Sending %s (%d) to %d\t%d\t%s\n",
304  convert_sig_to_name(sig),sig,v_u32(pid_v),v_u32(uid_v),name_v->buf);
305 
306  value_free(pid_v);
307  value_free(uid_v);
308  value_free(name_v);
309 
310  /* Load task_struct.signal (which is a struct signal_struct *) */
311  signal_v = target_load_value_member(target,NULL,value,"signal",NULL,
313  /* Load task_struct.signal->shared_pending */
314  signal_pending_v = target_load_value_member(target,NULL,signal_v,"shared_pending",
315  NULL,LOAD_FLAG_NONE);
316  /* Load task-struct.signal->shared_pending.signal, which is
317  * technically a struct containing an array, but we know what parts
318  * of it to update, so we do it "raw".
319  */
320  signal_pending_signal_v = target_load_value_member(target,NULL,signal_pending_v,
321  "signal",
322  NULL,LOAD_FLAG_NONE);
323  /* Set a pending SIGSTOP in the pending sigset. */
324  if (value_update_zero(signal_pending_signal_v,(char *)&sigmask,
325  sizeof(uint32_t))) {
326  printf(" ERROR: could not setup pending signal %d!\n",sig);
327  return 0;
328  }
329  target_store_value(target,signal_pending_signal_v);
330  value_free(signal_pending_signal_v);
331  value_free(signal_pending_v);
332 
333  /* Now, set some junk in the signal struct. We really should do
334  * these three things for each thread in the process, but for now,
335  * assume single-threaded processes!
336  */
337  /*
338  * NB: don't set SIGNAL_GROUP_EXIT, after all. It interferes with
339  * SIGSTOP delivery, and does not seem necessary for KILL. Although
340  * maybe that's because I haven't tried to kill a multithreaded
341  * program...
342  */
343  /*
344 #define LOCAL_SIGNAL_GROUP_EXIT 0x00000008
345  v = target_load_value_member(target,NULL,signal_v,"flags",NULL,LOAD_FLAG_NONE);
346  value_update_u32(v,LOCAL_SIGNAL_GROUP_EXIT);
347  target_store_value(target,v);
348  value_free(v);
349 
350  v = target_load_value_member(target,NULL,signal_v,"group_exit_code",
351  NULL,LOAD_FLAG_NONE);
352  value_update_i32(v,sig);
353  target_store_value(target,v);
354  value_free(v);
355  */
356  v = target_load_value_member(target,NULL,signal_v,"group_stop_count",
357  NULL,LOAD_FLAG_NONE);
358  value_update_i32(v,0);
359  target_store_value(target,v);
360  value_free(v);
361 
362  value_free(signal_v);
363 
364  /*
365  else {
366  signal_pending_signal_v =
367  target_load_value_member(target,NULL,value,"pending.signal",NULL,
368  LOAD_FLAG_AUTO_DEREF);
369  if (value_update_zero(signal_pending_signal_v,(char *)&sigmask,
370  sizeof(uint32_t))) {
371  printf(" ERROR: could not setup pending signal %d!\n",sig);
372  return 0;
373  }
374  target_store_value(target,signal_pending_signal_v);
375  value_free(signal_pending_signal_v);
376  }
377  */
378 
379 #define LOCAL_TIF_SIGPENDING (1UL << 2)
380 
381  /* Finally, set SIGPENDING in the task_struct's thread_info struct. */
382  thread_info_v = target_load_value_member(target,NULL,value,"thread_info",NULL,
384  if (!thread_info_v) {
385  struct target_location_ctxt *tlctxt = target_global_tlctxt(target);
386  v = target_load_value_member(target,tlctxt,
387  value,"stack",NULL,LOAD_FLAG_NONE);
389  tlctxt = NULL;
390  if (!v) {
391  printf(" ERROR: could not load stack (thread_info) in"
392  " task %d\t%d\t%s!\n",
393  v_u32(pid_v),v_u32(uid_v),name_v->buf);
394  return 0;
395  }
396  ADDR stack_member_addr = v_addr(v);
397  value_free(v);
398  v = NULL;
399 
400  thread_info_v = target_load_type(target,value->type,
401  stack_member_addr,LOAD_FLAG_NONE);
402  if (!thread_info_v) {
403  printf(" ERROR: could not load stack (thread_info)"
404  " in task %d\t%d\t%s!\n",
405  v_u32(pid_v),v_u32(uid_v),name_v->buf);
406  return 0;
407  }
408  }
409  v = target_load_value_member(target,NULL,thread_info_v,"flags",NULL,
412  target_store_value(target,v);
413  value_free(v);
414 
415  value_free(thread_info_v);
416 
417  return 0;
418 }
419 
420 int __ps_kill(struct target *target,struct value *value) {
421  struct value *pid_v;
422  struct value *uid_v;
423  struct value *name_v;
424  struct value *signal_v;
425  struct value *signal_pending_v;
426  struct value *signal_pending_signal_v;
427  struct value *v;
428  uint32_t sigkillmask = 1 << 9;
429  struct value *thread_info_v;
430 
431  name_v = target_load_value_member(target,NULL,value,"comm",NULL,LOAD_FLAG_NONE);
432  pid_v = target_load_value_member(target,NULL,value,"pid",NULL,LOAD_FLAG_NONE);
433  uid_v = target_load_value_member(target,NULL,value,"uid",NULL,LOAD_FLAG_NONE);
434  if (!uid_v)
435  uid_v = target_load_value_member(target,NULL,value,"cred.uid",NULL,
437 
438  printf("Killing %d\t%d\t%s\n",v_u32(pid_v),v_u32(uid_v),name_v->buf);
439 
440  value_free(pid_v);
441  value_free(uid_v);
442  value_free(name_v);
443 
444  /* Load task_struct.signal (which is a struct signal_struct *) */
445  signal_v = target_load_value_member(target,NULL,value,"signal",NULL,
447  /* Load task_struct.signal->shared_pending */
448  signal_pending_v = target_load_value_member(target,NULL,signal_v,"shared_pending",
449  NULL,LOAD_FLAG_NONE);
450  /* Load task-struct.signal->shared_pending.signal, which is
451  * technically a struct containing an array, but we know what parts
452  * of it to update, so we do it "raw".
453  */
454  signal_pending_signal_v = target_load_value_member(target,NULL,signal_pending_v,
455  "signal",
456  NULL,LOAD_FLAG_NONE);
457  /* Set a pending SIGKILL in the pending sigset. */
458  if (value_update_zero(signal_pending_signal_v,(char *)&sigkillmask,
459  sizeof(uint32_t))) {
460  printf(" ERROR: could not kill!\n");
461  return 0;
462  }
463  target_store_value(target,signal_pending_signal_v);
464  value_free(signal_pending_signal_v);
465  value_free(signal_pending_v);
466 
467  /* Now, set some junk in the signal struct. We really should do
468  * these three things for each thread in the process, but for now,
469  * assume single-threaded processes!
470  */
471 #define LOCAL_SIGNAL_GROUP_EXIT 0x00000008
472  v = target_load_value_member(target,NULL,signal_v,"flags",NULL,LOAD_FLAG_NONE);
474  target_store_value(target,v);
475  value_free(v);
476 
477  v = target_load_value_member(target,NULL,signal_v,"group_exit_code",
478  NULL,LOAD_FLAG_NONE);
479  value_update_i32(v,9);
480  target_store_value(target,v);
481  value_free(v);
482 
483  v = target_load_value_member(target,NULL,signal_v,"group_stop_count",
484  NULL,LOAD_FLAG_NONE);
485  value_update_i32(v,0);
486  target_store_value(target,v);
487  value_free(v);
488 
489  value_free(signal_v);
490 
491 #define LOCAL_TIF_SIGPENDING (1UL << 2)
492 
493  /* Finally, set SIGPENDING in the task_struct's thread_info struct. */
494  thread_info_v = target_load_value_member(target,NULL,value,"thread_info",NULL,
496  if (!thread_info_v) {
497  struct target_location_ctxt *tlctxt = target_global_tlctxt(target);
498  v = target_load_value_member(target,tlctxt,
499  value,"stack",NULL,LOAD_FLAG_NONE);
501  tlctxt = NULL;
502  if (!v) {
503  printf(" ERROR: could not load stack (thread_info) in"
504  " task %d\t%d\t%s!\n",
505  v_u32(pid_v),v_u32(uid_v),name_v->buf);
506  return 0;
507  }
508  ADDR stack_member_addr = v_addr(v);
509  value_free(v);
510  v = NULL;
511 
512  thread_info_v = target_load_type(target,value->type,
513  stack_member_addr,LOAD_FLAG_NONE);
514  if (!thread_info_v) {
515  printf(" ERROR: could not load stack (thread_info)"
516  " in task %d\t%d\t%s!\n",
517  v_u32(pid_v),v_u32(uid_v),name_v->buf);
518  return 0;
519  }
520  }
521  v = target_load_value_member(target,NULL,thread_info_v,"flags",NULL,
524  target_store_value(target,v);
525  value_free(v);
526 
527  value_free(thread_info_v);
528 
529  return 0;
530 }
531 
532 int pslist_kill(struct target *target,struct value *value,void *data) {
533  struct value *name_v;
534  struct rfilter *rf = (struct rfilter *)data;
535  int accept;
536 
537  name_v = target_load_value_member(target,NULL,value,"comm",NULL,LOAD_FLAG_NONE);
538  rfilter_check(rf,name_v->buf,&accept,NULL);
539  if (accept == RF_REJECT) {
540  value_free(name_v);
541  return 0;
542  }
543  value_free(name_v);
544 
545  return __ps_kill(target,value);
546 }
547 
549  long state;
550  unsigned long flags;
551  int pid;
552  int tgid;
555  int uid;
556  int euid;
557  int suid;
558  int fsuid;
559  int gid;
560  int egid;
561  int sgid;
562  int fsgid;
563 
564  char *comm;
565 
566  ADDR self;
567 
568  struct list_head tasks;
569 
570  struct value *value;
571 
574 
575  char *comm_hier;
576 };
577 
578 int pslist_load(struct target *target,struct value *value,void *data) {
579  struct value *v;
580 
581  struct linux_task_struct **head = ((struct linux_task_struct **)data);
582  struct linux_task_struct *current = \
583  (struct linux_task_struct *)malloc(sizeof(struct linux_task_struct));
584  memset(current,0,sizeof(struct linux_task_struct));
585  INIT_LIST_HEAD(&current->tasks);
586 
587  if (!*head) {
588  *head = current;
589  }
590  else
591  list_add_tail(&current->tasks,&((*head)->tasks));
592 
593  current->self = value_addr(value);
594 
595  v = target_load_value_member(target,NULL,value,"comm",NULL,LOAD_FLAG_NONE);
596  current->comm = strdup(v->buf);
597  value_free(v);
598 
599  v = target_load_value_member(target,NULL,value,"state",NULL,LOAD_FLAG_NONE);
600  current->state = v_i32(v);
601  value_free(v);
602 
603  v = target_load_value_member(target,NULL,value,"flags",NULL,LOAD_FLAG_NONE);
604  current->flags = v_u32(v);
605  value_free(v);
606 
607  v = target_load_value_member(target,NULL,value,"pid",NULL,LOAD_FLAG_NONE);
608  current->pid = v_i32(v);
609  value_free(v);
610 
611  v = target_load_value_member(target,NULL,value,"parent",NULL,LOAD_FLAG_NONE);
612  current->parent_addr = v_addr(v);
613  value_free(v);
614 
615  v = target_load_value_member(target,NULL,value,"real_parent",NULL,
617  current->real_parent_addr = v_addr(v);
618  value_free(v);
619 
620  v = target_load_value_member(target,NULL,value,"tgid",NULL,LOAD_FLAG_NONE);
621  current->tgid = v_i32(v);
622  value_free(v);
623 
624  v = target_load_value_member(target,NULL,value,"uid",NULL,LOAD_FLAG_NONE);
625  current->uid = v_i32(v);
626  value_free(v);
627 
628  v = target_load_value_member(target,NULL,value,"euid",NULL,LOAD_FLAG_NONE);
629  current->euid = v_i32(v);
630  value_free(v);
631 
632  v = target_load_value_member(target,NULL,value,"suid",NULL,LOAD_FLAG_NONE);
633  current->suid = v_i32(v);
634  value_free(v);
635 
636  v = target_load_value_member(target,NULL,value,"fsuid",NULL,LOAD_FLAG_NONE);
637  current->fsuid = v_i32(v);
638  value_free(v);
639 
640  v = target_load_value_member(target,NULL,value,"gid",NULL,LOAD_FLAG_NONE);
641  current->gid = v_i32(v);
642  value_free(v);
643 
644  v = target_load_value_member(target,NULL,value,"egid",NULL,LOAD_FLAG_NONE);
645  current->egid = v_i32(v);
646  value_free(v);
647 
648  v = target_load_value_member(target,NULL,value,"sgid",NULL,LOAD_FLAG_NONE);
649  current->sgid = v_i32(v);
650  value_free(v);
651 
652  v = target_load_value_member(target,NULL,value,"fsgid",NULL,LOAD_FLAG_NONE);
653  current->fsgid = v_i32(v);
654  value_free(v);
655 
656  current->value = value;
657 
658  return 0;
659 }
660 
662  int argc;
663  char **argv;
664  /* Grab this from the child parser. */
666 };
667 
669 
670 struct argp_option psa_argp_opts[] = {
671  { 0,0,0,0,0,0 },
672 };
673 
674 error_t psa_argp_parse_opt(int key,char *arg,struct argp_state *state) {
675  struct psa_argp_state *opts = \
676  (struct psa_argp_state *)target_argp_driver_state(state);
677 
678  switch (key) {
679  case ARGP_KEY_ARG:
680  return ARGP_ERR_UNKNOWN;
681  case ARGP_KEY_ARGS:
682  /* Eat all the remaining args. */
683  if (state->quoted > 0)
684  opts->argc = state->quoted - state->next;
685  else
686  opts->argc = state->argc - state->next;
687  if (opts->argc > 0) {
688  opts->argv = calloc(opts->argc,sizeof(char *));
689  memcpy(opts->argv,&state->argv[state->next],opts->argc*sizeof(char *));
690  state->next += opts->argc;
691  }
692  return 0;
693  case ARGP_KEY_INIT:
695  return 0;
696  case ARGP_KEY_END:
697  case ARGP_KEY_NO_ARGS:
698  case ARGP_KEY_SUCCESS:
699  opts->tspec = target_argp_target_spec(state);
700  return 0;
701  case ARGP_KEY_ERROR:
702  case ARGP_KEY_FINI:
703  return 0;
704 
705  default:
706  return ARGP_ERR_UNKNOWN;
707  }
708 
709  return 0;
710 }
711 
712 struct argp psa_argp = {
713  psa_argp_opts,psa_argp_parse_opt,NULL,NULL,NULL,NULL,NULL,
714 };
715 
716 int main(int argc,char **argv) {
717  char *command;
718  target_status_t tstat;
719  struct rfilter *rf = NULL;
720  struct psa_siginfo *psa_siginfo = NULL;
721 
722  struct bsymbol *init_task_bsymbol;
723 
724  struct bsymbol *bs;
725  struct value *v;
726  int i;
727 
728  regex_t *preg;
729  int rc;
730  char errbuf[64];
731  struct array_list *regexp_list;
732 
733  struct dump_info udn = {
734  .stream = stderr,
735  .prefix = "",
736  .detail = 1,
737  .meta = 1,
738  };
739 
740  struct linux_task_struct *init_task = NULL;
741  struct linux_task_struct *ti;
742  struct linux_task_struct *tj;
743  unsigned int csize;
744  unsigned int clen;
745 
746  struct target_spec *tspec;
747  char targetstr[128];
748 
749  struct target_location_ctxt *tlctxt;
750 
751  target_init();
752  atexit(target_fini);
753 
754  memset(&opts,0,sizeof(opts));
755 
756  tspec = target_argp_driver_parse_one(&psa_argp,&opts,argc,argv,
758 
759  if (!tspec) {
760  verror("could not parse target arguments!\n");
761  exit(-1);
762  }
763 
764  if (!opts.argc) {
765  fprintf(stderr,"ERROR: must supply a command!\n");
766  exit(-5);
767  }
768 
769  command = opts.argv[0];
770 
771  if (strcmp(command,"list") == 0
772  || strcmp(command,"watch") == 0)
773  ;
774  else if (strcmp(command,"check") == 0
775  || strcmp(command,"zombie") == 0
776  || strcmp(command,"kill") == 0) {
777  if (opts.argc < 2) {
778  fprintf(stderr,"ERROR: check|zombie|kill commands must"
779  " be followed by an rfilter!\n");
780  exit(-5);
781  }
782  rf = rfilter_create_parse(opts.argv[1]);
783  if (!rf) {
784  fprintf(stderr,"ERROR: bad rfilter '%s'!\n",opts.argv[1]);
785  exit(-7);
786  }
787  }
788  else if (strcmp(command,"sig") == 0) {
789  if (opts.argc < 3) {
790  fprintf(stderr,"ERROR: sig command must"
791  " be followed by a signal name/number and an rfilter!\n");
792  exit(-5);
793  }
794  psa_siginfo = (struct psa_siginfo *)calloc(1,sizeof(*psa_siginfo));
795  psa_siginfo->sig = convert_arg_to_sig(opts.argv[1]);
796  if (psa_siginfo->sig < 1) {
797  fprintf(stderr,"ERROR: bad signal string '%s'!\n",opts.argv[1]);
798  exit(-7);
799  }
800  psa_siginfo->rf = rfilter_create_parse(opts.argv[2]);
801  if (!psa_siginfo->rf) {
802  fprintf(stderr,"ERROR: bad rfilter '%s'!\n",opts.argv[2]);
803  exit(-7);
804  }
805  }
806  else if (strcmp(command,"hiercheck") == 0
807  || strcmp(command,"hierkill") == 0) {
808  if (opts.argc < 2) {
809  fprintf(stderr,"ERROR: hiercheck|hierkill commands must"
810  " be followed by one or more process hierarchy regexps!\n");
811  exit(-5);
812  }
813  regexp_list = array_list_create(opts.argc - 1);
814  i = 1;
815  while (i < opts.argc) {
816  preg = (regex_t *)malloc(sizeof(regex_t));
817  if ((rc = regcomp(preg,opts.argv[i],REG_EXTENDED | REG_NOSUB))) {
818  regerror(rc,preg,errbuf,64);
819  fprintf(stderr,"ERROR: bad regexp '%s': %s\n",opts.argv[i],errbuf);
820  exit(-12);
821  }
822  array_list_append(regexp_list,preg);
823  ++i;
824  }
825  }
826  else if (strcmp(command,"dump") == 0) {
827  if (opts.argc < 2) {
828  fprintf(stderr,"ERROR: dump command must"
829  " be followed by a list of variables to dump!\n");
830  exit(-5);
831  }
832  }
833  else {
834  fprintf(stderr,"ERROR: command must be one of"
835  " list|dump|check|zombie|sig|kill!\n");
836  exit(-6);
837  }
838 
839  t = target_instantiate(tspec,NULL);
840  if (!t) {
841  verror("could not instantiate target!\n");
842  exit(-1);
843  }
844  target_snprintf(t,targetstr,sizeof(targetstr));
845 
846  if (target_open(t)) {
847  fprintf(stderr,"could not open %s!\n",targetstr);
848  exit(-4);
849  }
850 
851  if (strcmp(command,"dump") == 0) {
852  for (i = 1 ; i < opts.argc; ++i) {
853  bs = target_lookup_sym(t,opts.argv[i],NULL,NULL,SYMBOL_TYPE_FLAG_VAR);
854  if (!bs) {
855  fprintf(stderr,"ERROR: could not lookup %s!\n",opts.argv[i]);
856  }
857  else {
859  v = target_load_symbol(t,tlctxt,bs,
863  tlctxt = NULL;
864  if (!v) {
865  fprintf(stderr,"ERROR: could not load value for %s!\n",
866  opts.argv[i]);
867  }
868  else {
869  value_dump(v,&udn);
870  fprintf(udn.stream,"\n");
871  value_free(v);
872  }
873  bsymbol_release(bs);
874  }
875  }
876 
877  goto exit;
878  }
879 
880  init_task_bsymbol = target_lookup_sym(t,"init_task",NULL,NULL,
882  if (!init_task_bsymbol) {
883  fprintf(stderr,"ERROR: could not find init_task symbol!\n");
884  goto exit;
885  }
886 
887  /*
888  * If we are just doing list|check|filter, we don't need to install probes.
889  */
890  if (strcmp(command,"list") == 0) {
891  printf("PID\tUID\tProcess Name\n");
892  os_linux_list_for_each_struct(t,init_task_bsymbol,"tasks",0,
893  pslist_list,NULL);
894  goto exit;
895  }
896  else if (strcmp(command,"check") == 0) {
897  os_linux_list_for_each_struct(t,init_task_bsymbol,"tasks",0,
898  pslist_check,rf);
899  goto exit;
900  }
901  else if (strcmp(command,"zombie") == 0) {
902  os_linux_list_for_each_struct(t,init_task_bsymbol,"tasks",0,
903  pslist_zombie,rf);
904  goto exit;
905  }
906  else if (strcmp(command,"sig") == 0) {
907  os_linux_list_for_each_struct(t,init_task_bsymbol,"tasks",0,
908  pslist_sig,psa_siginfo);
909  goto exit;
910  }
911  else if (strcmp(command,"kill") == 0) {
912  os_linux_list_for_each_struct(t,init_task_bsymbol,"tasks",0,
913  pslist_kill,rf);
914  goto exit;
915  }
916  else if (strcmp(command,"hiercheck") == 0
917  || strcmp(command,"hierkill") == 0) {
918  /* Load the process list into our structs. */
919  os_linux_list_for_each_struct(t,init_task_bsymbol,"tasks",1,
920  pslist_load,&init_task);
921 
922  /* Setup the parent pointers in our structs. */
923  list_for_each_entry(ti,&init_task->tasks,tasks) {
924  list_for_each_entry(tj,&init_task->tasks,tasks) {
925  if (ti->parent_addr == tj->self) {
926  //printf("parent of %s is %s\n",ti->comm,tj->comm);
927  ti->parent = tj;
928  break;
929  }
930  }
931  if (ti->parent_addr == ti->real_parent_addr)
932  ti->real_parent = ti->parent;
933  else {
934  list_for_each_entry(tj,&init_task->tasks,tasks) {
935  if (ti->real_parent_addr == tj->self) {
936  //printf("real parent of %s is %s\n",ti->comm,tj->comm);
937  ti->real_parent = tj;
938  break;
939  }
940  }
941  }
942  }
943 
944  /* Build the comm_hier values for each pid. */
945  list_for_each_entry(ti,&init_task->tasks,tasks) {
946  csize = 32;
947  clen = 0;
948  ti->comm_hier = malloc(csize);
949  ti->comm_hier[0] = '\0';
950 
951  tj = ti;
952  while (tj) {
953  if ((csize - clen) < (strlen(tj->comm) + 2)) {
954  csize += 32;
955  realloc(ti->comm_hier,csize);
956  }
957  if (ti != tj)
958  rc = snprintf(ti->comm_hier + clen,csize - clen,":%s",
959  tj->comm);
960  else
961  rc = snprintf(ti->comm_hier + clen,csize - clen,"%s",
962  tj->comm);
963  clen += rc;
964  tj = tj->parent;
965  }
966 
967  printf("hier: %s\n",ti->comm_hier);
968  }
969 
970  /* Check each pid's comm_hier against our regexps; if we don't find
971  * a match, either print (hiercheck) the process, or kill
972  * (hierkill).
973  */
974  list_for_each_entry(ti,&init_task->tasks,tasks) {
975  for (i = 0; i < array_list_len(regexp_list); ++i) {
976  preg = (regex_t *)array_list_item(regexp_list,i);
977  if (regexec(preg,ti->comm_hier,0,NULL,0) == 0)
978  break;
979  }
980  if (i == array_list_len(regexp_list)) {
981  if (strcmp(command,"hiercheck") == 0) {
982  printf("Disallowed process: %d\t%d\t%s (not killing)\n",
983  ti->pid,ti->uid,ti->comm);
984  }
985  else {
986  __ps_kill(t,ti->value);
987  }
988  }
989  }
990 
991  goto exit;
992  }
993 
994  /*
995  * If we are going to watch for processes, set up monitoring.
996  */
997  signal(SIGHUP,sigh);
998  signal(SIGINT,sigh);
999  signal(SIGQUIT,sigh);
1000  signal(SIGABRT,sigh);
1001  signal(SIGKILL,sigh);
1002  signal(SIGSEGV,sigh);
1003  signal(SIGPIPE,sigh);
1004  signal(SIGALRM,sigh);
1005  signal(SIGTERM,sigh);
1006  signal(SIGUSR1,sigh);
1007  signal(SIGUSR2,sigh);
1008 
1009  /* Install probes... */
1010 
1011  // XXX fill in...
1012 
1013  /* The target is paused after the attach; we have to resume it now
1014  * that we've registered probes.
1015  */
1016  target_resume(t);
1017 
1018  fprintf(stdout,"Starting watch loop!\n");
1019  fflush(stdout);
1020 
1021  while (1) {
1022  tstat = target_monitor(t);
1023  if (tstat == TSTATUS_PAUSED) {
1024  fflush(stderr);
1025  fflush(stdout);
1026  printf("%s interrupted at 0x%" PRIxREGVAL "\n",targetstr,
1028  goto resume;
1029 
1030 
1031  resume:
1032  if (target_resume(t)) {
1033  fprintf(stderr,"could not resume target domain %s\n",targetstr);
1034  cleanup();
1035  exit(-16);
1036  }
1037  }
1038  else {
1039  goto exit;
1040  }
1041  }
1042 
1043  exit:
1044  fflush(stderr);
1045  fflush(stdout);
1046  tstat = cleanup();
1047  if (tstat == TSTATUS_DONE) {
1048  printf("%s finished.\n",targetstr);
1049  exit(0);
1050  }
1051  else if (tstat == TSTATUS_ERROR) {
1052  printf("%s monitoring failed!\n",targetstr);
1053  exit(-9);
1054  }
1055  else {
1056  printf("%s monitoring failed with %d!\n",targetstr,tstat);
1057  exit(-10);
1058  }
1059 }
struct value * target_load_symbol(struct target *target, struct target_location_ctxt *tlctxt, struct bsymbol *bsymbol, load_flags_t flags)
Definition: target.c:3270
#define RF_ACCEPT
Definition: rfilter.h:29
struct value * target_load_type(struct target *target, struct symbol *type, ADDR addr, load_flags_t flags)
Definition: target.c:2653
struct argp_option psa_argp_opts[]
Definition: psaction.c:670
int probe_unregister(struct probe *probe, int force)
Definition: probe.c:1137
int value_update_i32(struct value *value, int32_t v)
Definition: value.c:537
void * target_argp_driver_state(struct argp_state *state)
Definition: target.c:716
target_status_t
Definition: target_api.h:197
int __ps_kill(struct target *target, struct value *value)
Definition: psaction.c:420
struct target_spec * tspec
Definition: dumptarget.c:113
GHashTable * probes
Definition: psaction.c:45
unsigned long flags
Definition: psaction.c:550
static uint64_t unsigned int i
struct bsymbol * target_lookup_sym(struct target *target, const char *name, const char *delim, char *srcfile, symbol_type_flag_t ftype)
Definition: target.c:2199
target_status_t cleanup()
Definition: psaction.c:47
void target_init(void)
Definition: target.c:69
int target_resume(struct target *target)
Definition: target_api.c:1012
struct target_location_ctxt * target_location_ctxt_create_from_bsymbol(struct target *target, tid_t tid, struct bsymbol *bsymbol)
Definition: target.c:5325
struct linux_task_struct * real_parent
Definition: psaction.c:572
struct value * value
Definition: psaction.c:570
int target_pause(struct target *target)
Definition: target_api.c:1027
void value_dump(struct value *value, struct dump_info *ud)
Definition: value.c:1294
struct list_head tasks
Definition: psaction.c:568
int value_update_num(struct value *value, num_t v)
Definition: value.c:586
int target_close(struct target *target)
Definition: target_api.c:1511
struct list_head probe
Definition: probe.h:379
#define verror(format,...)
Definition: log.h:30
int os_linux_list_for_each_struct(struct target *t, struct bsymbol *bsymbol, char *list_head_member_name, int nofree, os_linux_list_iterator_t iterator, void *data)
struct argp psa_argp
Definition: psaction.c:712
Definition: list.h:51
#define LOCAL_TIF_SIGPENDING
void target_fini(void)
Definition: target.c:91
int target_snprintf(struct target *target, char *buf, int bufsiz)
Definition: target_api.c:829
void free(void *ptr)
Definition: debugserver.c:207
REGVAL target_read_reg(struct target *target, tid_t tid, REG reg)
Definition: target_api.c:1132
char * comm_hier
Definition: psaction.c:575
#define list_for_each_entry(pos, head, member)
Definition: list.h:335
int main(int argc, char **argv)
Definition: psaction.c:716
REFCNT bsymbol_release(struct bsymbol *bsymbol)
Definition: symbol.c:90
int probe_free(struct probe *probe, int force)
Definition: probe.c:777
char * buf
Definition: target_api.h:3298
#define LOCAL_SIGNAL_GROUP_EXIT
int pslist_load(struct target *target, struct value *value, void *data)
Definition: psaction.c:578
int pslist_check(struct target *target, struct value *value, void *data)
Definition: psaction.c:100
void value_free(struct value *value)
Definition: value.c:282
struct target_location_ctxt * target_global_tlctxt(struct target *target)
Definition: target.c:5299
struct value * target_load_value_member(struct target *target, struct target_location_ctxt *tlctxt, struct value *old_value, const char *member, const char *delim, load_flags_t flags)
Definition: target.c:2942
int len
Definition: dumptarget.c:52
#define RF_REJECT
Definition: rfilter.h:30
int signo
Definition: psaction.c:174
Definition: probe.h:308
ADDR real_parent_addr
Definition: psaction.c:554
int target_store_value(struct target *target, struct value *value)
Definition: target.c:3548
ADDR v_addr(struct value *v)
Definition: value.c:429
void * realloc(void *ptr, size_t size)
Definition: debugserver.c:221
FILE * stream
Definition: output.h:26
char * name
Definition: psaction.c:173
struct psa_argp_state opts
Definition: psaction.c:668
int pslist_list(struct target *target, struct value *value, void *data)
Definition: psaction.c:79
void sigh(int signo)
Definition: psaction.c:71
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
struct target_spec * tspec
Definition: psaction.c:665
struct linux_task_struct * parent
Definition: psaction.c:573
error_t psa_argp_parse_opt(int key, char *arg, struct argp_state *state)
Definition: psaction.c:674
char ** argv
Definition: psaction.c:663
int pslist_sig(struct target *target, struct value *value, void *data)
Definition: psaction.c:275
int target_finalize(struct target *target)
Definition: target.c:1955
uint32_t ADDR
Definition: common.h:64
struct symbol * type
Definition: target_api.h:3287
struct target * t
Definition: psaction.c:43
struct rfilter * rf
Definition: psaction.c:271
int target_open(struct target *target)
Definition: target_api.c:513
int32_t v_i32(struct value *v)
Definition: value.c:394
target_status_t target_monitor(struct target *target)
Definition: target_api.c:869
struct target_spec * target_argp_target_spec(struct argp_state *state)
Definition: target.c:709
void target_location_ctxt_free(struct target_location_ctxt *tlctxt)
Definition: target.c:5348
struct target_spec * target_argp_driver_parse_one(struct argp *driver_parser, void *driver_state, int argc, char **argv, target_type_t target_types, int filter_quoted)
Definition: target.c:802
int value_update_u32(struct value *value, uint32_t v)
Definition: value.c:505
struct target * target_instantiate(struct target_spec *spec, struct evloop *evloop)
Definition: target_api.c:55
void * malloc(size_t size)
Definition: debugserver.c:214
int value_update_zero(struct value *value, const char *buf, int bufsiz)
Definition: value.c:447
uint32_t v_u32(struct value *v)
Definition: value.c:390
#define LOCAL_NSIG_WORDS
Definition: psaction.c:167
#define INIT_LIST_HEAD(ptr)
Definition: list.h:60
ADDR value_addr(struct value *value)
Definition: value.c:302
REG ipregno
Definition: target_api.h:2508
#define TID_GLOBAL
Definition: target_api.h:145
void target_driver_argp_init_children(struct argp_state *state)
Definition: target.c:1057
int pslist_kill(struct target *target, struct value *value, void *data)
Definition: psaction.c:532
int pslist_zombie(struct target *target, struct value *value, void *data)
Definition: psaction.c:129
#define PRIxREGVAL
Definition: common.h:72