diff options
Diffstat (limited to 'lib/bitmap.c')
| -rw-r--r-- | lib/bitmap.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index d71e38c54ea5..037fa9aa2ed7 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
| @@ -316,10 +316,11 @@ int bitmap_scnprintf(char *buf, unsigned int buflen, | |||
| 316 | EXPORT_SYMBOL(bitmap_scnprintf); | 316 | EXPORT_SYMBOL(bitmap_scnprintf); |
| 317 | 317 | ||
| 318 | /** | 318 | /** |
| 319 | * bitmap_parse - convert an ASCII hex string into a bitmap. | 319 | * __bitmap_parse - convert an ASCII hex string into a bitmap. |
| 320 | * @ubuf: pointer to buffer in user space containing string. | 320 | * @buf: pointer to buffer containing string. |
| 321 | * @ubuflen: buffer size in bytes. If string is smaller than this | 321 | * @buflen: buffer size in bytes. If string is smaller than this |
| 322 | * then it must be terminated with a \0. | 322 | * then it must be terminated with a \0. |
| 323 | * @is_user: location of buffer, 0 indicates kernel space | ||
| 323 | * @maskp: pointer to bitmap array that will contain result. | 324 | * @maskp: pointer to bitmap array that will contain result. |
| 324 | * @nmaskbits: size of bitmap, in bits. | 325 | * @nmaskbits: size of bitmap, in bits. |
| 325 | * | 326 | * |
| @@ -330,11 +331,13 @@ EXPORT_SYMBOL(bitmap_scnprintf); | |||
| 330 | * characters and for grouping errors such as "1,,5", ",44", "," and "". | 331 | * characters and for grouping errors such as "1,,5", ",44", "," and "". |
| 331 | * Leading and trailing whitespace accepted, but not embedded whitespace. | 332 | * Leading and trailing whitespace accepted, but not embedded whitespace. |
| 332 | */ | 333 | */ |
| 333 | int bitmap_parse(const char __user *ubuf, unsigned int ubuflen, | 334 | int __bitmap_parse(const char *buf, unsigned int buflen, |
| 334 | unsigned long *maskp, int nmaskbits) | 335 | int is_user, unsigned long *maskp, |
| 336 | int nmaskbits) | ||
| 335 | { | 337 | { |
| 336 | int c, old_c, totaldigits, ndigits, nchunks, nbits; | 338 | int c, old_c, totaldigits, ndigits, nchunks, nbits; |
| 337 | u32 chunk; | 339 | u32 chunk; |
| 340 | const char __user *ubuf = buf; | ||
| 338 | 341 | ||
| 339 | bitmap_zero(maskp, nmaskbits); | 342 | bitmap_zero(maskp, nmaskbits); |
| 340 | 343 | ||
| @@ -343,11 +346,15 @@ int bitmap_parse(const char __user *ubuf, unsigned int ubuflen, | |||
| 343 | chunk = ndigits = 0; | 346 | chunk = ndigits = 0; |
| 344 | 347 | ||
| 345 | /* Get the next chunk of the bitmap */ | 348 | /* Get the next chunk of the bitmap */ |
| 346 | while (ubuflen) { | 349 | while (buflen) { |
| 347 | old_c = c; | 350 | old_c = c; |
| 348 | if (get_user(c, ubuf++)) | 351 | if (is_user) { |
| 349 | return -EFAULT; | 352 | if (__get_user(c, ubuf++)) |
| 350 | ubuflen--; | 353 | return -EFAULT; |
| 354 | } | ||
| 355 | else | ||
| 356 | c = *buf++; | ||
| 357 | buflen--; | ||
| 351 | if (isspace(c)) | 358 | if (isspace(c)) |
| 352 | continue; | 359 | continue; |
| 353 | 360 | ||
| @@ -388,11 +395,36 @@ int bitmap_parse(const char __user *ubuf, unsigned int ubuflen, | |||
| 388 | nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ; | 395 | nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ; |
| 389 | if (nbits > nmaskbits) | 396 | if (nbits > nmaskbits) |
| 390 | return -EOVERFLOW; | 397 | return -EOVERFLOW; |
| 391 | } while (ubuflen && c == ','); | 398 | } while (buflen && c == ','); |
| 392 | 399 | ||
| 393 | return 0; | 400 | return 0; |
| 394 | } | 401 | } |
| 395 | EXPORT_SYMBOL(bitmap_parse); | 402 | EXPORT_SYMBOL(__bitmap_parse); |
| 403 | |||
| 404 | /** | ||
| 405 | * bitmap_parse_user() | ||
| 406 | * | ||
| 407 | * @ubuf: pointer to user buffer containing string. | ||
| 408 | * @ulen: buffer size in bytes. If string is smaller than this | ||
| 409 | * then it must be terminated with a \0. | ||
| 410 | * @maskp: pointer to bitmap array that will contain result. | ||
| 411 | * @nmaskbits: size of bitmap, in bits. | ||
| 412 | * | ||
| 413 | * Wrapper for __bitmap_parse(), providing it with user buffer. | ||
| 414 | * | ||
| 415 | * We cannot have this as an inline function in bitmap.h because it needs | ||
| 416 | * linux/uaccess.h to get the access_ok() declaration and this causes | ||
| 417 | * cyclic dependencies. | ||
| 418 | */ | ||
| 419 | int bitmap_parse_user(const char __user *ubuf, | ||
| 420 | unsigned int ulen, unsigned long *maskp, | ||
| 421 | int nmaskbits) | ||
| 422 | { | ||
| 423 | if (!access_ok(VERIFY_READ, ubuf, ulen)) | ||
| 424 | return -EFAULT; | ||
| 425 | return __bitmap_parse((const char *)ubuf, ulen, 1, maskp, nmaskbits); | ||
| 426 | } | ||
| 427 | EXPORT_SYMBOL(bitmap_parse_user); | ||
| 396 | 428 | ||
| 397 | /* | 429 | /* |
| 398 | * bscnl_emit(buf, buflen, rbot, rtop, bp) | 430 | * bscnl_emit(buf, buflen, rbot, rtop, bp) |
