Commit adbe8726dc2a3805630d517270db17e3af86e526

Authored by Eric B Munson
Committed by Linus Torvalds
1 parent 08d4a24659

hugetlb: do not allow pagesize >= MAX_ORDER pool adjustment

Huge pages with order >= MAX_ORDER must be allocated at boot via the
kernel command line, they cannot be allocated or freed once the kernel is
up and running.  Currently we allow values to be written to the sysfs and
sysctl files controling pool size for these huge page sizes.  This patch
makes the store functions for nr_hugepages and nr_overcommit_hugepages
return -EINVAL when the pool for a page size >= MAX_ORDER is changed.

[akpm@linux-foundation.org: avoid multiple return paths in nr_hugepages_store_common()]
[caiqian@redhat.com: add checking in hugetlb_overcommit_handler()]
Signed-off-by: Eric B Munson <emunson@mgebm.net>
Reported-by: CAI Qian <caiqian@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Nishanth Aravamudan <nacc@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 21 additions and 2 deletions Side-by-side Diff

... ... @@ -1363,6 +1363,7 @@
1363 1363  
1364 1364 return sprintf(buf, "%lu\n", nr_huge_pages);
1365 1365 }
  1366 +
1366 1367 static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
1367 1368 struct kobject *kobj, struct kobj_attribute *attr,
1368 1369 const char *buf, size_t len)
1369 1370  
... ... @@ -1375,11 +1376,16 @@
1375 1376  
1376 1377 err = strict_strtoul(buf, 10, &count);
1377 1378 if (err) {
1378   - NODEMASK_FREE(nodes_allowed);
1379   - return 0;
  1379 + err = 0; /* This seems wrong */
  1380 + goto out;
1380 1381 }
1381 1382  
1382 1383 h = kobj_to_hstate(kobj, &nid);
  1384 + if (h->order >= MAX_ORDER) {
  1385 + err = -EINVAL;
  1386 + goto out;
  1387 + }
  1388 +
1383 1389 if (nid == NUMA_NO_NODE) {
1384 1390 /*
1385 1391 * global hstate attribute
... ... @@ -1405,6 +1411,9 @@
1405 1411 NODEMASK_FREE(nodes_allowed);
1406 1412  
1407 1413 return len;
  1414 +out:
  1415 + NODEMASK_FREE(nodes_allowed);
  1416 + return err;
1408 1417 }
1409 1418  
1410 1419 static ssize_t nr_hugepages_show(struct kobject *kobj,
... ... @@ -1447,6 +1456,7 @@
1447 1456 struct hstate *h = kobj_to_hstate(kobj, NULL);
1448 1457 return sprintf(buf, "%lu\n", h->nr_overcommit_huge_pages);
1449 1458 }
  1459 +
1450 1460 static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj,
1451 1461 struct kobj_attribute *attr, const char *buf, size_t count)
1452 1462 {
... ... @@ -1454,6 +1464,9 @@
1454 1464 unsigned long input;
1455 1465 struct hstate *h = kobj_to_hstate(kobj, NULL);
1456 1466  
  1467 + if (h->order >= MAX_ORDER)
  1468 + return -EINVAL;
  1469 +
1457 1470 err = strict_strtoul(buf, 10, &input);
1458 1471 if (err)
1459 1472 return 0;
... ... @@ -1864,6 +1877,9 @@
1864 1877 if (!write)
1865 1878 tmp = h->max_huge_pages;
1866 1879  
  1880 + if (write && h->order >= MAX_ORDER)
  1881 + return -EINVAL;
  1882 +
1867 1883 table->data = &tmp;
1868 1884 table->maxlen = sizeof(unsigned long);
1869 1885 ret = proc_doulongvec_minmax(table, write, buffer, length, ppos);
... ... @@ -1926,6 +1942,9 @@
1926 1942  
1927 1943 if (!write)
1928 1944 tmp = h->nr_overcommit_huge_pages;
  1945 +
  1946 + if (write && h->order >= MAX_ORDER)
  1947 + return -EINVAL;
1929 1948  
1930 1949 table->data = &tmp;
1931 1950 table->maxlen = sizeof(unsigned long);