uaccess_user.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
  3. * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
  4. * Licensed under the GPL
  5. */
  6. #include <string.h>
  7. #include "uml_uaccess.h"
  8. #include "task.h"
  9. #include "kern_util.h"
  10. #include "os.h"
  11. #include "longjmp.h"
  12. int __do_copy_from_user(void *to, const void *from, int n,
  13. void **fault_addr, void **fault_catcher)
  14. {
  15. struct tt_regs save = TASK_REGS(get_current())->tt;
  16. unsigned long fault;
  17. int faulted;
  18. fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
  19. __do_copy, &faulted);
  20. TASK_REGS(get_current())->tt = save;
  21. if(!faulted)
  22. return 0;
  23. else if (fault)
  24. return n - (fault - (unsigned long) from);
  25. else
  26. /* In case of a general protection fault, we don't have the
  27. * fault address, so NULL is used instead. Pretend we didn't
  28. * copy anything. */
  29. return n;
  30. }
  31. static void __do_strncpy(void *dst, const void *src, int count)
  32. {
  33. strncpy(dst, src, count);
  34. }
  35. int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
  36. void **fault_addr, void **fault_catcher)
  37. {
  38. struct tt_regs save = TASK_REGS(get_current())->tt;
  39. unsigned long fault;
  40. int faulted;
  41. fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
  42. __do_strncpy, &faulted);
  43. TASK_REGS(get_current())->tt = save;
  44. if(!faulted) return(strlen(dst));
  45. else return(-1);
  46. }
  47. static void __do_clear(void *to, const void *from, int n)
  48. {
  49. memset(to, 0, n);
  50. }
  51. int __do_clear_user(void *mem, unsigned long len,
  52. void **fault_addr, void **fault_catcher)
  53. {
  54. struct tt_regs save = TASK_REGS(get_current())->tt;
  55. unsigned long fault;
  56. int faulted;
  57. fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
  58. __do_clear, &faulted);
  59. TASK_REGS(get_current())->tt = save;
  60. if(!faulted) return(0);
  61. else return(len - (fault - (unsigned long) mem));
  62. }
  63. int __do_strnlen_user(const char *str, unsigned long n,
  64. void **fault_addr, void **fault_catcher)
  65. {
  66. struct tt_regs save = TASK_REGS(get_current())->tt;
  67. int ret;
  68. unsigned long *faddrp = (unsigned long *)fault_addr;
  69. jmp_buf jbuf;
  70. *fault_catcher = &jbuf;
  71. if(UML_SETJMP(&jbuf) == 0)
  72. ret = strlen(str) + 1;
  73. else ret = *faddrp - (unsigned long) str;
  74. *fault_addr = NULL;
  75. *fault_catcher = NULL;
  76. TASK_REGS(get_current())->tt = save;
  77. return ret;
  78. }
  79. /*
  80. * Overrides for Emacs so that we follow Linus's tabbing style.
  81. * Emacs will notice this stuff at the end of the file and automatically
  82. * adjust the settings for this buffer only. This must remain at the end
  83. * of the file.
  84. * ---------------------------------------------------------------------------
  85. * Local variables:
  86. * c-file-style: "linux"
  87. * End:
  88. */