Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uaccess.c
Go to the documentation of this file.
1 /* uaccess.c: userspace access functions
2  *
3  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells ([email protected])
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 
12 #include <linux/mm.h>
13 #include <linux/module.h>
14 #include <asm/uaccess.h>
15 
16 /*****************************************************************************/
17 /*
18  * copy a null terminated string from userspace
19  */
20 long strncpy_from_user(char *dst, const char __user *src, long count)
21 {
22  unsigned long max;
23  char *p, ch;
24  long err = -EFAULT;
25 
26  BUG_ON(count < 0);
27 
28  p = dst;
29 
30 #ifndef CONFIG_MMU
31  if ((unsigned long) src < memory_start)
32  goto error;
33 #endif
34 
35  if ((unsigned long) src >= get_addr_limit())
36  goto error;
37 
38  max = get_addr_limit() - (unsigned long) src;
39  if ((unsigned long) count > max) {
40  memset(dst + max, 0, count - max);
41  count = max;
42  }
43 
44  err = 0;
45  for (; count > 0; count--, p++, src++) {
46  __get_user_asm(err, ch, src, "ub", "=r");
47  if (err < 0)
48  goto error;
49  if (!ch)
50  break;
51  *p = ch;
52  }
53 
54  err = p - dst; /* return length excluding NUL */
55 
56  error:
57  if (count > 0)
58  memset(p, 0, count); /* clear remainder of buffer [security] */
59 
60  return err;
61 
62 } /* end strncpy_from_user() */
63 
65 
66 /*****************************************************************************/
67 /*
68  * Return the size of a string (including the ending 0)
69  *
70  * Return 0 on exception, a value greater than N if too long
71  */
72 long strnlen_user(const char __user *src, long count)
73 {
74  const char __user *p;
75  long err = 0;
76  char ch;
77 
78  BUG_ON(count < 0);
79 
80 #ifndef CONFIG_MMU
81  if ((unsigned long) src < memory_start)
82  return 0;
83 #endif
84 
85  if ((unsigned long) src >= get_addr_limit())
86  return 0;
87 
88  for (p = src; count > 0; count--, p++) {
89  __get_user_asm(err, ch, p, "ub", "=r");
90  if (err < 0)
91  return 0;
92  if (!ch)
93  break;
94  }
95 
96  return p - src + 1; /* return length including NUL */
97 
98 } /* end strnlen_user() */
99