runtime/ktap.c - ktap

Global variables defined

Functions defined

Source code

  1. /*
  2. * ktap.c - ktapvm kernel module main entry
  3. *
  4. * This file is part of ktap by Jovi Zhangwei.
  5. *
  6. * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
  7. *
  8. * ktap is free software; you can redistribute it and/or modify it
  9. * under the terms and conditions of the GNU General Public License,
  10. * version 2, as published by the Free Software Foundation.
  11. *
  12. * ktap is distributed in the hope it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15. * more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along with
  18. * this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  20. */

  21. /*
  22. * this file is the first file to be compile, add CONFIG_ checking in here.
  23. * See Requirements in doc/tutorial.md
  24. */

  25. #include <linux/version.h>
  26. #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
  27. #error "Currently ktap don't support kernel older than 3.1"
  28. #endif

  29. #if !CONFIG_EVENT_TRACING
  30. #error "Please enable CONFIG_EVENT_TRACING before compile ktap"
  31. #endif

  32. #if !CONFIG_PERF_EVENTS
  33. #error "Please enable CONFIG_PERF_EVENTS before compile ktap"
  34. #endif

  35. #include <linux/module.h>
  36. #include <linux/errno.h>
  37. #include <linux/file.h>
  38. #include <linux/slab.h>
  39. #include <linux/fcntl.h>
  40. #include <linux/sched.h>
  41. #include <linux/poll.h>
  42. #include <linux/anon_inodes.h>
  43. #include <linux/debugfs.h>
  44. #include <linux/vmalloc.h>
  45. #include "../include/ktap_types.h"
  46. #include "ktap.h"
  47. #include "kp_bcread.h"
  48. #include "kp_vm.h"

  49. /* common helper function */
  50. long gettimeofday_ns(void)
  51. {
  52.     struct timespec now;

  53.     getnstimeofday(&now);
  54.     return now.tv_sec * NSEC_PER_SEC + now.tv_nsec;
  55. }

  56. static int load_trunk(ktap_option_t *parm, unsigned long **buff)
  57. {
  58.     int ret;
  59.     unsigned long *vmstart;

  60.     vmstart = vmalloc(parm->trunk_len);
  61.     if (!vmstart)
  62.         return -ENOMEM;

  63.     ret = copy_from_user(vmstart, (void __user *)parm->trunk,
  64.                  parm->trunk_len);
  65.     if (ret < 0) {
  66.         vfree(vmstart);
  67.         return -EFAULT;
  68.     }

  69.     *buff = vmstart;
  70.     return 0;
  71. }

  72. static struct dentry *kp_dir_dentry;

  73. /* Ktap Main Entry */
  74. static int ktap_main(struct file *file, ktap_option_t *parm)
  75. {
  76.     unsigned long *buff = NULL;
  77.     ktap_state_t *ks;
  78.     ktap_proto_t *pt;
  79.     long start_time, delta_time;
  80.     int ret;

  81.     start_time = gettimeofday_ns();

  82.     ks = kp_vm_new_state(parm, kp_dir_dentry);
  83.     if (unlikely(!ks))
  84.         return -ENOEXEC;

  85.     file->private_data = ks;

  86.     ret = load_trunk(parm, &buff);
  87.     if (ret) {
  88.         kp_error(ks, "cannot load file\n");
  89.         goto out;
  90.     }

  91.     pt = kp_bcread(ks, (unsigned char *)buff, parm->trunk_len);

  92.     vfree(buff);

  93.     if (pt) {
  94.         /* validate byte code */
  95.         if (kp_vm_validate_code(ks, pt, ks->stack))
  96.             goto out;

  97.         delta_time = (gettimeofday_ns() - start_time) / NSEC_PER_USEC;
  98.         kp_verbose_printf(ks, "booting time: %d (us)\n", delta_time);

  99.         /* enter vm */
  100.         kp_vm_call_proto(ks, pt);
  101.     }

  102. out:
  103.     kp_vm_exit(ks);
  104.     return ret;
  105. }


  106. static void print_version(void)
  107. {
  108. }

  109. static long ktap_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  110. {
  111.     ktap_option_t parm;
  112.     int ret;

  113.     switch (cmd) {
  114.     case KTAP_CMD_IOC_VERSION:
  115.         print_version();
  116.         return 0;
  117.     case KTAP_CMD_IOC_RUN:
  118.         /*
  119.          * must be root to run ktap script (at least for now)
  120.          *
  121.          * TODO: check perf_paranoid sysctl and allow non-root user
  122.          * to use ktap for tracing process(like uprobe) ?
  123.          */
  124.         if (!capable(CAP_SYS_ADMIN))
  125.             return -EACCES;

  126.         ret = copy_from_user(&parm, (void __user *)arg,
  127.                      sizeof(ktap_option_t));
  128.         if (ret < 0)
  129.             return -EFAULT;

  130.         return ktap_main(file, &parm);
  131.     default:
  132.         return -EINVAL;
  133.     };

  134.         return 0;
  135. }

  136. static const struct file_operations ktap_fops = {
  137.     .llseek                 = no_llseek,
  138.     .unlocked_ioctl         = ktap_ioctl,
  139. };

  140. static long ktapvm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  141. {
  142.     int new_fd, err;
  143.     struct file *new_file;

  144.     new_fd = get_unused_fd();
  145.     if (new_fd < 0)
  146.         return new_fd;

  147.     new_file = anon_inode_getfile("[ktap]", &ktap_fops, NULL, O_RDWR);
  148.     if (IS_ERR(new_file)) {
  149.         err = PTR_ERR(new_file);
  150.         put_unused_fd(new_fd);
  151.         return err;
  152.     }

  153.     file->private_data = NULL;
  154.     fd_install(new_fd, new_file);
  155.     return new_fd;
  156. }

  157. static const struct file_operations ktapvm_fops = {
  158.     .owner  = THIS_MODULE,
  159.     .unlocked_ioctl         = ktapvm_ioctl,
  160. };

  161. int (*kp_ftrace_profile_set_filter)(struct perf_event *event, int event_id,
  162.                     const char *filter_str);

  163. struct syscall_metadata **syscalls_metadata;

  164. /*TODO: kill this function in future */
  165. static int __init init_dummy_kernel_functions(void)
  166. {
  167.     unsigned long *addr;

  168.     /*
  169.      * ktap need symbol ftrace_profile_set_filter to set event filter,
  170.      * export it in future.
  171.      */
  172. #ifdef CONFIG_PPC64
  173.     kp_ftrace_profile_set_filter =
  174.         (void *)kallsyms_lookup_name(".ftrace_profile_set_filter");
  175. #else
  176.     kp_ftrace_profile_set_filter =
  177.         (void *)kallsyms_lookup_name("ftrace_profile_set_filter");
  178. #endif
  179.     if (!kp_ftrace_profile_set_filter) {
  180.         pr_err("ktap: cannot lookup ftrace_profile_set_filter "
  181.             "in kallsyms\n");
  182.         return -1;
  183.     }

  184.     /* use syscalls_metadata for syscall event handling */
  185.     addr = (void *)kallsyms_lookup_name("syscalls_metadata");
  186.     if (!addr) {
  187.         pr_err("ktap: cannot lookup syscalls_metadata in kallsyms\n");
  188.         return -1;
  189.     }

  190.     syscalls_metadata = (struct syscall_metadata **)*addr;
  191.     return 0;
  192. }

  193. static int __init init_ktap(void)
  194. {
  195.     struct dentry *ktapvm_dentry;

  196.     if (init_dummy_kernel_functions())
  197.         return -1;

  198.     kp_dir_dentry = debugfs_create_dir("ktap", NULL);
  199.     if (!kp_dir_dentry) {
  200.         pr_err("ktap: debugfs_create_dir failed\n");
  201.         return -1;
  202.     }

  203.     ktapvm_dentry = debugfs_create_file("ktapvm", 0444, kp_dir_dentry, NULL,
  204.                         &ktapvm_fops);

  205.     if (!ktapvm_dentry) {
  206.         pr_err("ktapvm: cannot create ktapvm file\n");
  207.         debugfs_remove_recursive(kp_dir_dentry);
  208.         return -1;
  209.     }

  210.     return 0;
  211. }

  212. static void __exit exit_ktap(void)
  213. {
  214.     debugfs_remove_recursive(kp_dir_dentry);
  215. }

  216. module_init(init_ktap);
  217. module_exit(exit_ktap);

  218. MODULE_AUTHOR("Jovi Zhangwei <jovi.zhangwei@gmail.com>");
  219. MODULE_DESCRIPTION("ktap");
  220. MODULE_LICENSE("GPL");

  221. int kp_max_loop_count = 100000;
  222. module_param_named(max_loop_count, kp_max_loop_count, int, S_IRUGO | S_IWUSR);
  223. MODULE_PARM_DESC(max_loop_count, "max loop execution count");