gsgx_ioctl_1_6.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * (C) Copyright 2013 Intel Corporation
  3. * Author: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; version 2
  8. * of the License.
  9. */
  10. #include <linux/module.h>
  11. #include <linux/kernel.h>
  12. #include <linux/version.h>
  13. #include <linux/highmem.h>
  14. #include <linux/miscdevice.h>
  15. #include <linux/vmalloc.h>
  16. #include <linux/security.h>
  17. #include <asm/tlbflush.h>
  18. #include "gsgx.h"
  19. #if SDK_DRIVER_VERSION == KERNEL_VERSION(1, 6, 0)
  20. #include "isgx.h"
  21. #include "isgx_arch.h"
  22. #include "isgx_user.h"
  23. struct file *isgx_dev;
  24. static long enclave_create(struct file *filep, void * arg)
  25. {
  26. struct gsgx_enclave_create *createp = arg;
  27. struct isgx_create_param isgx_create;
  28. isgx_create.addr = createp->src;
  29. filep->private_data = (void *) createp->src;
  30. return KSYM(isgx_ioctl_enclave_create)(filep, ISGX_IOCTL_ENCLAVE_CREATE,
  31. (unsigned long) &isgx_create);
  32. }
  33. static long enclave_add_pages(struct file *filep, void * arg)
  34. {
  35. struct gsgx_enclave_add_pages *addp = arg;
  36. struct isgx_add_param isgx_add;
  37. uint64_t off;
  38. int ret = 0;
  39. if (!addp->addr || (addp->addr & (PAGE_SIZE - 1)))
  40. return -EINVAL;
  41. if (!addp->size || (addp->size & (PAGE_SIZE - 1)))
  42. return -EINVAL;
  43. if (!addp->secinfo)
  44. return -EINVAL;
  45. isgx_add.secinfo = (struct isgx_secinfo *) addp->secinfo;
  46. for (off = 0 ; off < addp->size ; off += PAGE_SIZE) {
  47. isgx_add.addr = addp->addr + off;
  48. isgx_add.user_addr =
  49. addp->flags & GSGX_ENCLAVE_ADD_PAGES_REPEAT_SRC ?
  50. addp->user_addr : addp->user_addr + off;
  51. isgx_add.flags =
  52. addp->flags & GSGX_ENCLAVE_ADD_PAGES_SKIP_EEXTEND ?
  53. ISGX_ADD_SKIP_EEXTEND : 0;
  54. ret = KSYM(isgx_ioctl_enclave_add_page)(filep,
  55. ISGX_IOCTL_ENCLAVE_ADD_PAGE, (unsigned long) &isgx_add);
  56. if (ret < 0)
  57. break;
  58. }
  59. return ret;
  60. }
  61. static long enclave_init(struct file *filep, void * arg)
  62. {
  63. struct gsgx_enclave_init *initp = arg;
  64. struct isgx_init_param isgx_init;
  65. isgx_init.addr = initp->addr;
  66. isgx_init.sigstruct = (void *) initp->sigstruct;
  67. isgx_init.einittoken = (struct isgx_einittoken *) initp->einittoken;
  68. return KSYM(isgx_ioctl_enclave_init)(filep, ISGX_IOCTL_ENCLAVE_INIT,
  69. (unsigned long) &isgx_init);
  70. }
  71. long gsgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  72. {
  73. char data[256];
  74. long (*handler) (struct file *filp, void *arg) = NULL;
  75. long ret;
  76. switch (cmd) {
  77. case GSGX_IOCTL_ENCLAVE_CREATE:
  78. handler = enclave_create;
  79. break;
  80. case GSGX_IOCTL_ENCLAVE_ADD_PAGES:
  81. handler = enclave_add_pages;
  82. break;
  83. case GSGX_IOCTL_ENCLAVE_INIT:
  84. handler = enclave_init;
  85. break;
  86. default:
  87. return -EINVAL;
  88. }
  89. if (copy_from_user(data, (void __user *) arg, _IOC_SIZE(cmd)))
  90. return -EFAULT;
  91. ret = handler(filep, (void *) data);
  92. if (!ret && (cmd & IOC_OUT)) {
  93. if (copy_to_user((void __user *) arg, data, _IOC_SIZE(cmd)))
  94. return -EFAULT;
  95. }
  96. return ret;
  97. }
  98. int gsgx_mmap(struct file *file, struct vm_area_struct *vma)
  99. {
  100. return KSYM(isgx_mmap)(file, vma);
  101. }
  102. unsigned long gsgx_get_unmapped_area(struct file *file, unsigned long addr,
  103. unsigned long len, unsigned long pgoff,
  104. unsigned long flags)
  105. {
  106. if (file->private_data == (void *) GSGX_ENCLAVE_CREATE_NO_ADDR) {
  107. unsigned long unmapped_addr =
  108. KSYM(isgx_get_unmapped_area)(file, addr, len,
  109. pgoff, flags);
  110. file->private_data = (void *) unmapped_addr;
  111. return unmapped_addr;
  112. } else {
  113. unsigned long unmapped_addr = (unsigned long) file->private_data;
  114. struct mm_struct *mm = current->mm;
  115. struct vm_area_struct *vma = find_vma(mm, unmapped_addr);
  116. if (vma && vma->vm_start <= len)
  117. return -EINVAL;
  118. return unmapped_addr;
  119. }
  120. }
  121. IMPORT_KSYM_PROTO(isgx_ioctl_enclave_create, long,
  122. struct file *filep, unsigned int cmd, unsigned long arg);
  123. IMPORT_KSYM_PROTO(isgx_ioctl_enclave_init, long,
  124. struct file *filep, unsigned int cmd, unsigned long arg);
  125. IMPORT_KSYM_PROTO(isgx_ioctl_enclave_add_page, long,
  126. struct file *filep, unsigned int cmd, unsigned long arg);
  127. IMPORT_KSYM(isgx_enclave_release);
  128. IMPORT_KSYM_PROTO(isgx_mmap, int, struct file *, struct vm_area_struct *);
  129. IMPORT_KSYM_PROTO(isgx_get_unmapped_area, unsigned long,
  130. struct file *, unsigned long, unsigned long,
  131. unsigned long, unsigned long);
  132. int gsgx_lookup_ksyms(void)
  133. {
  134. int ret;
  135. if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_create)))
  136. return ret;
  137. if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_init)))
  138. return ret;
  139. if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_add_page)))
  140. return ret;
  141. if ((ret = LOOKUP_KSYM(isgx_enclave_release)))
  142. return ret;
  143. if ((ret = LOOKUP_KSYM(isgx_mmap)))
  144. return ret;
  145. if ((ret = LOOKUP_KSYM(isgx_get_unmapped_area)))
  146. return ret;
  147. return 0;
  148. }
  149. #endif /* SGX_DRIVER_VERSION == 1.7 */