]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | ||
12 | #include <linux/mm.h> | |
13 | #include <asm/uaccess.h> | |
14 | ||
15 | /*****************************************************************************/ | |
16 | /* | |
17 | * copy a null terminated string from userspace | |
18 | */ | |
19 | long strncpy_from_user(char *dst, const char *src, long count) | |
20 | { | |
21 | unsigned long max; | |
22 | char *p, ch; | |
23 | long err = -EFAULT; | |
24 | ||
25 | if (count < 0) | |
26 | BUG(); | |
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 | } /* end strncpy_from_user() */ | |
62 | ||
63 | /*****************************************************************************/ | |
64 | /* | |
65 | * Return the size of a string (including the ending 0) | |
66 | * | |
67 | * Return 0 on exception, a value greater than N if too long | |
68 | */ | |
69 | long strnlen_user(const char *src, long count) | |
70 | { | |
71 | const char *p; | |
72 | long err = 0; | |
73 | char ch; | |
74 | ||
75 | if (count < 0) | |
76 | BUG(); | |
77 | ||
78 | #ifndef CONFIG_MMU | |
79 | if ((unsigned long) src < memory_start) | |
80 | return 0; | |
81 | #endif | |
82 | ||
83 | if ((unsigned long) src >= get_addr_limit()) | |
84 | return 0; | |
85 | ||
86 | for (p = src; count > 0; count--, p++) { | |
87 | __get_user_asm(err, ch, p, "ub", "=r"); | |
88 | if (err < 0) | |
89 | return 0; | |
90 | if (!ch) | |
91 | break; | |
92 | } | |
93 | ||
94 | return p - src + 1; /* return length including NUL */ | |
95 | } /* end strnlen_user() */ |