diff options
Diffstat (limited to 'kernel/sysctl_binary.c')
| -rw-r--r-- | kernel/sysctl_binary.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index 112533d5fc0..8cd50d8f9bd 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c | |||
| @@ -1331,7 +1331,7 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
| 1331 | ssize_t result; | 1331 | ssize_t result; |
| 1332 | char *pathname; | 1332 | char *pathname; |
| 1333 | int flags; | 1333 | int flags; |
| 1334 | int acc_mode, fmode; | 1334 | int acc_mode; |
| 1335 | 1335 | ||
| 1336 | pathname = sysctl_getname(name, nlen, &table); | 1336 | pathname = sysctl_getname(name, nlen, &table); |
| 1337 | result = PTR_ERR(pathname); | 1337 | result = PTR_ERR(pathname); |
| @@ -1342,15 +1342,12 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
| 1342 | if (oldval && oldlen && newval && newlen) { | 1342 | if (oldval && oldlen && newval && newlen) { |
| 1343 | flags = O_RDWR; | 1343 | flags = O_RDWR; |
| 1344 | acc_mode = MAY_READ | MAY_WRITE; | 1344 | acc_mode = MAY_READ | MAY_WRITE; |
| 1345 | fmode = FMODE_READ | FMODE_WRITE; | ||
| 1346 | } else if (newval && newlen) { | 1345 | } else if (newval && newlen) { |
| 1347 | flags = O_WRONLY; | 1346 | flags = O_WRONLY; |
| 1348 | acc_mode = MAY_WRITE; | 1347 | acc_mode = MAY_WRITE; |
| 1349 | fmode = FMODE_WRITE; | ||
| 1350 | } else if (oldval && oldlen) { | 1348 | } else if (oldval && oldlen) { |
| 1351 | flags = O_RDONLY; | 1349 | flags = O_RDONLY; |
| 1352 | acc_mode = MAY_READ; | 1350 | acc_mode = MAY_READ; |
| 1353 | fmode = FMODE_READ; | ||
| 1354 | } else { | 1351 | } else { |
| 1355 | result = 0; | 1352 | result = 0; |
| 1356 | goto out_putname; | 1353 | goto out_putname; |
| @@ -1361,7 +1358,7 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
| 1361 | if (result) | 1358 | if (result) |
| 1362 | goto out_putname; | 1359 | goto out_putname; |
| 1363 | 1360 | ||
| 1364 | result = may_open(&nd.path, acc_mode, fmode); | 1361 | result = may_open(&nd.path, acc_mode, flags); |
| 1365 | if (result) | 1362 | if (result) |
| 1366 | goto out_putpath; | 1363 | goto out_putpath; |
| 1367 | 1364 | ||
| @@ -1417,6 +1414,35 @@ static void deprecated_sysctl_warning(const int *name, int nlen) | |||
| 1417 | return; | 1414 | return; |
| 1418 | } | 1415 | } |
| 1419 | 1416 | ||
| 1417 | #define WARN_ONCE_HASH_BITS 8 | ||
| 1418 | #define WARN_ONCE_HASH_SIZE (1<<WARN_ONCE_HASH_BITS) | ||
| 1419 | |||
| 1420 | static DECLARE_BITMAP(warn_once_bitmap, WARN_ONCE_HASH_SIZE); | ||
| 1421 | |||
| 1422 | #define FNV32_OFFSET 2166136261U | ||
| 1423 | #define FNV32_PRIME 0x01000193 | ||
| 1424 | |||
| 1425 | /* | ||
| 1426 | * Print each legacy sysctl (approximately) only once. | ||
| 1427 | * To avoid making the tables non-const use a external | ||
| 1428 | * hash-table instead. | ||
| 1429 | * Worst case hash collision: 6, but very rarely. | ||
| 1430 | * NOTE! We don't use the SMP-safe bit tests. We simply | ||
| 1431 | * don't care enough. | ||
| 1432 | */ | ||
| 1433 | static void warn_on_bintable(const int *name, int nlen) | ||
| 1434 | { | ||
| 1435 | int i; | ||
| 1436 | u32 hash = FNV32_OFFSET; | ||
| 1437 | |||
| 1438 | for (i = 0; i < nlen; i++) | ||
| 1439 | hash = (hash ^ name[i]) * FNV32_PRIME; | ||
| 1440 | hash %= WARN_ONCE_HASH_SIZE; | ||
| 1441 | if (__test_and_set_bit(hash, warn_once_bitmap)) | ||
| 1442 | return; | ||
| 1443 | deprecated_sysctl_warning(name, nlen); | ||
| 1444 | } | ||
| 1445 | |||
| 1420 | static ssize_t do_sysctl(int __user *args_name, int nlen, | 1446 | static ssize_t do_sysctl(int __user *args_name, int nlen, |
| 1421 | void __user *oldval, size_t oldlen, void __user *newval, size_t newlen) | 1447 | void __user *oldval, size_t oldlen, void __user *newval, size_t newlen) |
| 1422 | { | 1448 | { |
| @@ -1431,7 +1457,7 @@ static ssize_t do_sysctl(int __user *args_name, int nlen, | |||
| 1431 | if (get_user(name[i], args_name + i)) | 1457 | if (get_user(name[i], args_name + i)) |
| 1432 | return -EFAULT; | 1458 | return -EFAULT; |
| 1433 | 1459 | ||
| 1434 | deprecated_sysctl_warning(name, nlen); | 1460 | warn_on_bintable(name, nlen); |
| 1435 | 1461 | ||
| 1436 | return binary_sysctl(name, nlen, oldval, oldlen, newval, newlen); | 1462 | return binary_sysctl(name, nlen, oldval, oldlen, newval, newlen); |
| 1437 | } | 1463 | } |
