| From 050c17f239fd53adb55aa768d4f41bc76c0fe045 Mon Sep 17 00:00:00 2001 |
| From: Ralph Campbell <rcampbell@nvidia.com> |
| Date: Wed, 20 Feb 2019 22:18:58 -0800 |
| Subject: numa: change get_mempolicy() to use nr_node_ids instead of MAX_NUMNODES |
| |
| From: Ralph Campbell <rcampbell@nvidia.com> |
| |
| commit 050c17f239fd53adb55aa768d4f41bc76c0fe045 upstream. |
| |
| The system call, get_mempolicy() [1], passes an unsigned long *nodemask |
| pointer and an unsigned long maxnode argument which specifies the length |
| of the user's nodemask array in bits (which is rounded up). The manual |
| page says that if the maxnode value is too small, get_mempolicy will |
| return EINVAL but there is no system call to return this minimum value. |
| To determine this value, some programs search /proc/<pid>/status for a |
| line starting with "Mems_allowed:" and use the number of digits in the |
| mask to determine the minimum value. A recent change to the way this line |
| is formatted [2] causes these programs to compute a value less than |
| MAX_NUMNODES so get_mempolicy() returns EINVAL. |
| |
| Change get_mempolicy(), the older compat version of get_mempolicy(), and |
| the copy_nodes_to_user() function to use nr_node_ids instead of |
| MAX_NUMNODES, thus preserving the defacto method of computing the minimum |
| size for the nodemask array and the maxnode argument. |
| |
| [1] http://man7.org/linux/man-pages/man2/get_mempolicy.2.html |
| [2] https://lore.kernel.org/lkml/1545405631-6808-1-git-send-email-longman@redhat.com |
| |
| Link: http://lkml.kernel.org/r/20190211180245.22295-1-rcampbell@nvidia.com |
| Fixes: 4fb8e5b89bcbbbb ("include/linux/nodemask.h: use nr_node_ids (not MAX_NUMNODES) in __nodemask_pr_numnodes()") |
| Signed-off-by: Ralph Campbell <rcampbell@nvidia.com> |
| Suggested-by: Alexander Duyck <alexander.duyck@gmail.com> |
| Cc: Waiman Long <longman@redhat.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| mm/mempolicy.c | 6 +++--- |
| 1 file changed, 3 insertions(+), 3 deletions(-) |
| |
| --- a/mm/mempolicy.c |
| +++ b/mm/mempolicy.c |
| @@ -1314,7 +1314,7 @@ static int copy_nodes_to_user(unsigned l |
| nodemask_t *nodes) |
| { |
| unsigned long copy = ALIGN(maxnode-1, 64) / 8; |
| - const int nbytes = BITS_TO_LONGS(MAX_NUMNODES) * sizeof(long); |
| + unsigned int nbytes = BITS_TO_LONGS(nr_node_ids) * sizeof(long); |
| |
| if (copy > nbytes) { |
| if (copy > PAGE_SIZE) |
| @@ -1491,7 +1491,7 @@ static int kernel_get_mempolicy(int __us |
| int uninitialized_var(pval); |
| nodemask_t nodes; |
| |
| - if (nmask != NULL && maxnode < MAX_NUMNODES) |
| + if (nmask != NULL && maxnode < nr_node_ids) |
| return -EINVAL; |
| |
| err = do_get_mempolicy(&pval, &nodes, addr, flags); |
| @@ -1527,7 +1527,7 @@ COMPAT_SYSCALL_DEFINE5(get_mempolicy, in |
| unsigned long nr_bits, alloc_size; |
| DECLARE_BITMAP(bm, MAX_NUMNODES); |
| |
| - nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES); |
| + nr_bits = min_t(unsigned long, maxnode-1, nr_node_ids); |
| alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8; |
| |
| if (nmask) |