uaccess.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* uaccess.c: userspace access functions
  2. *
  3. * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/mm.h>
  12. #include <linux/module.h>
  13. #include <asm/uaccess.h>
  14. /*****************************************************************************/
  15. /*
  16. * copy a null terminated string from userspace
  17. */
  18. long strncpy_from_user(char *dst, const char *src, long count)
  19. {
  20. unsigned long max;
  21. char *p, ch;
  22. long err = -EFAULT;
  23. if (count < 0)
  24. BUG();
  25. p = dst;
  26. #ifndef CONFIG_MMU
  27. if ((unsigned long) src < memory_start)
  28. goto error;
  29. #endif
  30. if ((unsigned long) src >= get_addr_limit())
  31. goto error;
  32. max = get_addr_limit() - (unsigned long) src;
  33. if ((unsigned long) count > max) {
  34. memset(dst + max, 0, count - max);
  35. count = max;
  36. }
  37. err = 0;
  38. for (; count > 0; count--, p++, src++) {
  39. __get_user_asm(err, ch, src, "ub", "=r");
  40. if (err < 0)
  41. goto error;
  42. if (!ch)
  43. break;
  44. *p = ch;
  45. }
  46. err = p - dst; /* return length excluding NUL */
  47. error:
  48. if (count > 0)
  49. memset(p, 0, count); /* clear remainder of buffer [security] */
  50. return err;
  51. } /* end strncpy_from_user() */
  52. EXPORT_SYMBOL(strncpy_from_user);
  53. /*****************************************************************************/
  54. /*
  55. * Return the size of a string (including the ending 0)
  56. *
  57. * Return 0 on exception, a value greater than N if too long
  58. */
  59. long strnlen_user(const char *src, long count)
  60. {
  61. const char *p;
  62. long err = 0;
  63. char ch;
  64. if (count < 0)
  65. BUG();
  66. #ifndef CONFIG_MMU
  67. if ((unsigned long) src < memory_start)
  68. return 0;
  69. #endif
  70. if ((unsigned long) src >= get_addr_limit())
  71. return 0;
  72. for (p = src; count > 0; count--, p++) {
  73. __get_user_asm(err, ch, p, "ub", "=r");
  74. if (err < 0)
  75. return 0;
  76. if (!ch)
  77. break;
  78. }
  79. return p - src + 1; /* return length including NUL */
  80. } /* end strnlen_user() */
  81. EXPORT_SYMBOL(strnlen_user);