diff options
-rw-r--r-- | include/linux/kernel.h | 4 | ||||
-rw-r--r-- | kernel/params.c | 20 | ||||
-rw-r--r-- | lib/vsprintf.c | 123 |
3 files changed, 137 insertions, 10 deletions
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 8f28d35867f8..2df44e773270 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -141,6 +141,10 @@ extern unsigned long simple_strtoul(const char *,char **,unsigned int); | |||
141 | extern long simple_strtol(const char *,char **,unsigned int); | 141 | extern long simple_strtol(const char *,char **,unsigned int); |
142 | extern unsigned long long simple_strtoull(const char *,char **,unsigned int); | 142 | extern unsigned long long simple_strtoull(const char *,char **,unsigned int); |
143 | extern long long simple_strtoll(const char *,char **,unsigned int); | 143 | extern long long simple_strtoll(const char *,char **,unsigned int); |
144 | extern int strict_strtoul(const char *, unsigned int, unsigned long *); | ||
145 | extern int strict_strtol(const char *, unsigned int, long *); | ||
146 | extern int strict_strtoull(const char *, unsigned int, unsigned long long *); | ||
147 | extern int strict_strtoll(const char *, unsigned int, long long *); | ||
144 | extern int sprintf(char * buf, const char * fmt, ...) | 148 | extern int sprintf(char * buf, const char * fmt, ...) |
145 | __attribute__ ((format (printf, 2, 3))); | 149 | __attribute__ ((format (printf, 2, 3))); |
146 | extern int vsprintf(char *buf, const char *, va_list) | 150 | extern int vsprintf(char *buf, const char *, va_list) |
diff --git a/kernel/params.c b/kernel/params.c index e28c70628bb7..afc46a23eb6d 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -180,12 +180,12 @@ int parse_args(const char *name, | |||
180 | #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ | 180 | #define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ |
181 | int param_set_##name(const char *val, struct kernel_param *kp) \ | 181 | int param_set_##name(const char *val, struct kernel_param *kp) \ |
182 | { \ | 182 | { \ |
183 | char *endp; \ | ||
184 | tmptype l; \ | 183 | tmptype l; \ |
184 | int ret; \ | ||
185 | \ | 185 | \ |
186 | if (!val) return -EINVAL; \ | 186 | if (!val) return -EINVAL; \ |
187 | l = strtolfn(val, &endp, 0); \ | 187 | ret = strtolfn(val, 0, &l); \ |
188 | if (endp == val || ((type)l != l)) \ | 188 | if (ret == -EINVAL || ((type)l != l)) \ |
189 | return -EINVAL; \ | 189 | return -EINVAL; \ |
190 | *((type *)kp->arg) = l; \ | 190 | *((type *)kp->arg) = l; \ |
191 | return 0; \ | 191 | return 0; \ |
@@ -195,13 +195,13 @@ int parse_args(const char *name, | |||
195 | return sprintf(buffer, format, *((type *)kp->arg)); \ | 195 | return sprintf(buffer, format, *((type *)kp->arg)); \ |
196 | } | 196 | } |
197 | 197 | ||
198 | STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, simple_strtoul); | 198 | STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, strict_strtoul); |
199 | STANDARD_PARAM_DEF(short, short, "%hi", long, simple_strtol); | 199 | STANDARD_PARAM_DEF(short, short, "%hi", long, strict_strtol); |
200 | STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, simple_strtoul); | 200 | STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, strict_strtoul); |
201 | STANDARD_PARAM_DEF(int, int, "%i", long, simple_strtol); | 201 | STANDARD_PARAM_DEF(int, int, "%i", long, strict_strtol); |
202 | STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, simple_strtoul); | 202 | STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, strict_strtoul); |
203 | STANDARD_PARAM_DEF(long, long, "%li", long, simple_strtol); | 203 | STANDARD_PARAM_DEF(long, long, "%li", long, strict_strtol); |
204 | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, simple_strtoul); | 204 | STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, strict_strtoul); |
205 | 205 | ||
206 | int param_set_charp(const char *val, struct kernel_param *kp) | 206 | int param_set_charp(const char *val, struct kernel_param *kp) |
207 | { | 207 | { |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7b481cea54ae..419993f58c6b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -126,6 +126,129 @@ long long simple_strtoll(const char *cp,char **endp,unsigned int base) | |||
126 | return simple_strtoull(cp,endp,base); | 126 | return simple_strtoull(cp,endp,base); |
127 | } | 127 | } |
128 | 128 | ||
129 | |||
130 | /** | ||
131 | * strict_strtoul - convert a string to an unsigned long strictly | ||
132 | * @cp: The string to be converted | ||
133 | * @base: The number base to use | ||
134 | * @res: The converted result value | ||
135 | * | ||
136 | * strict_strtoul converts a string to an unsigned long only if the | ||
137 | * string is really an unsigned long string, any string containing | ||
138 | * any invalid char at the tail will be rejected and -EINVAL is returned, | ||
139 | * only a newline char at the tail is acceptible because people generally | ||
140 | * change a module parameter in the following way: | ||
141 | * | ||
142 | * echo 1024 > /sys/module/e1000/parameters/copybreak | ||
143 | * | ||
144 | * echo will append a newline to the tail. | ||
145 | * | ||
146 | * It returns 0 if conversion is successful and *res is set to the converted | ||
147 | * value, otherwise it returns -EINVAL and *res is set to 0. | ||
148 | * | ||
149 | * simple_strtoul just ignores the successive invalid characters and | ||
150 | * return the converted value of prefix part of the string. | ||
151 | */ | ||
152 | int strict_strtoul(const char *cp, unsigned int base, unsigned long *res); | ||
153 | |||
154 | /** | ||
155 | * strict_strtol - convert a string to a long strictly | ||
156 | * @cp: The string to be converted | ||
157 | * @base: The number base to use | ||
158 | * @res: The converted result value | ||
159 | * | ||
160 | * strict_strtol is similiar to strict_strtoul, but it allows the first | ||
161 | * character of a string is '-'. | ||
162 | * | ||
163 | * It returns 0 if conversion is successful and *res is set to the converted | ||
164 | * value, otherwise it returns -EINVAL and *res is set to 0. | ||
165 | */ | ||
166 | int strict_strtol(const char *cp, unsigned int base, long *res); | ||
167 | |||
168 | /** | ||
169 | * strict_strtoull - convert a string to an unsigned long long strictly | ||
170 | * @cp: The string to be converted | ||
171 | * @base: The number base to use | ||
172 | * @res: The converted result value | ||
173 | * | ||
174 | * strict_strtoull converts a string to an unsigned long long only if the | ||
175 | * string is really an unsigned long long string, any string containing | ||
176 | * any invalid char at the tail will be rejected and -EINVAL is returned, | ||
177 | * only a newline char at the tail is acceptible because people generally | ||
178 | * change a module parameter in the following way: | ||
179 | * | ||
180 | * echo 1024 > /sys/module/e1000/parameters/copybreak | ||
181 | * | ||
182 | * echo will append a newline to the tail of the string. | ||
183 | * | ||
184 | * It returns 0 if conversion is successful and *res is set to the converted | ||
185 | * value, otherwise it returns -EINVAL and *res is set to 0. | ||
186 | * | ||
187 | * simple_strtoull just ignores the successive invalid characters and | ||
188 | * return the converted value of prefix part of the string. | ||
189 | */ | ||
190 | int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res); | ||
191 | |||
192 | /** | ||
193 | * strict_strtoll - convert a string to a long long strictly | ||
194 | * @cp: The string to be converted | ||
195 | * @base: The number base to use | ||
196 | * @res: The converted result value | ||
197 | * | ||
198 | * strict_strtoll is similiar to strict_strtoull, but it allows the first | ||
199 | * character of a string is '-'. | ||
200 | * | ||
201 | * It returns 0 if conversion is successful and *res is set to the converted | ||
202 | * value, otherwise it returns -EINVAL and *res is set to 0. | ||
203 | */ | ||
204 | int strict_strtoll(const char *cp, unsigned int base, long long *res); | ||
205 | |||
206 | #define define_strict_strtoux(type, valtype) \ | ||
207 | int strict_strtou##type(const char *cp, unsigned int base, valtype *res)\ | ||
208 | { \ | ||
209 | char *tail; \ | ||
210 | valtype val; \ | ||
211 | size_t len; \ | ||
212 | \ | ||
213 | *res = 0; \ | ||
214 | len = strlen(cp); \ | ||
215 | if (len == 0) \ | ||
216 | return -EINVAL; \ | ||
217 | \ | ||
218 | val = simple_strtoul(cp, &tail, base); \ | ||
219 | if ((*tail == '\0') || \ | ||
220 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {\ | ||
221 | *res = val; \ | ||
222 | return 0; \ | ||
223 | } \ | ||
224 | \ | ||
225 | return -EINVAL; \ | ||
226 | } \ | ||
227 | |||
228 | #define define_strict_strtox(type, valtype) \ | ||
229 | int strict_strto##type(const char *cp, unsigned int base, valtype *res) \ | ||
230 | { \ | ||
231 | int ret; \ | ||
232 | if (*cp == '-') { \ | ||
233 | ret = strict_strtou##type(cp+1, base, res); \ | ||
234 | if (ret != 0) \ | ||
235 | *res = -(*res); \ | ||
236 | } else \ | ||
237 | ret = strict_strtou##type(cp, base, res); \ | ||
238 | \ | ||
239 | return ret; \ | ||
240 | } \ | ||
241 | |||
242 | define_strict_strtoux(l, unsigned long) | ||
243 | define_strict_strtox(l, long) | ||
244 | define_strict_strtoux(ll, unsigned long long) | ||
245 | define_strict_strtox(ll, long long) | ||
246 | |||
247 | EXPORT_SYMBOL(strict_strtoul); | ||
248 | EXPORT_SYMBOL(strict_strtol); | ||
249 | EXPORT_SYMBOL(strict_strtoll); | ||
250 | EXPORT_SYMBOL(strict_strtoull); | ||
251 | |||
129 | static int skip_atoi(const char **s) | 252 | static int skip_atoi(const char **s) |
130 | { | 253 | { |
131 | int i=0; | 254 | int i=0; |