]>
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> | |
40234401 | 13 | #include <linux/module.h> |
7c0f6ba6 | 14 | #include <linux/uaccess.h> |
1da177e4 LT |
15 | |
16 | /*****************************************************************************/ | |
17 | /* | |
18 | * copy a null terminated string from userspace | |
19 | */ | |
a8a77573 | 20 | long strncpy_from_user(char *dst, const char __user *src, long count) |
1da177e4 LT |
21 | { |
22 | unsigned long max; | |
23 | char *p, ch; | |
24 | long err = -EFAULT; | |
25 | ||
db5c444e | 26 | BUG_ON(count < 0); |
1da177e4 LT |
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; | |
40234401 | 61 | |
1da177e4 LT |
62 | } /* end strncpy_from_user() */ |
63 | ||
40234401 DH |
64 | EXPORT_SYMBOL(strncpy_from_user); |
65 | ||
1da177e4 LT |
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 | */ | |
a8a77573 | 72 | long strnlen_user(const char __user *src, long count) |
1da177e4 | 73 | { |
a8a77573 | 74 | const char __user *p; |
1da177e4 LT |
75 | long err = 0; |
76 | char ch; | |
77 | ||
db5c444e | 78 | BUG_ON(count < 0); |
1da177e4 LT |
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 */ | |
40234401 | 97 | |
1da177e4 | 98 | } /* end strnlen_user() */ |
40234401 DH |
99 | |
100 | EXPORT_SYMBOL(strnlen_user); |