linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mm/mempolicy: prevent the risk of division by 0
@ 2025-09-07 16:08 Chelsy Ratnawat
  2025-09-07 23:53 ` Joshua Hahn
  2025-09-08 18:12 ` Gregory Price
  0 siblings, 2 replies; 6+ messages in thread
From: Chelsy Ratnawat @ 2025-09-07 16:08 UTC (permalink / raw)
  To: akpm, david, joshua.hahnjy, ziy, ying.huang
  Cc: rakie.kim, byungchul, apopple, linux-mm, Chelsy Ratnawat

If no bits are set in the policy's node mask, then nodes will be 0.
This patch adds a check if nodes == 0 before dividing.

Signed-off-by: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
---
 mm/mempolicy.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index eb83cff7db8c..faacc604fc16 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2530,6 +2530,8 @@ static unsigned long alloc_pages_bulk_interleave(gfp_t gfp,
 	unsigned long total_allocated = 0;
 
 	nodes = nodes_weight(pol->nodes);
+	if (nodes == 0)
+		return 0;
 	nr_pages_per_node = nr_pages / nodes;
 	delta = nr_pages - nodes * nr_pages_per_node;
 
-- 
2.47.3



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] mm/mempolicy: prevent the risk of division by 0
  2025-09-07 16:08 [PATCH] mm/mempolicy: prevent the risk of division by 0 Chelsy Ratnawat
@ 2025-09-07 23:53 ` Joshua Hahn
  2025-09-08  3:48   ` Huang, Ying
  2025-09-08 18:12 ` Gregory Price
  1 sibling, 1 reply; 6+ messages in thread
From: Joshua Hahn @ 2025-09-07 23:53 UTC (permalink / raw)
  To: Chelsy Ratnawat
  Cc: akpm, david, joshua.hahnjy, ziy, ying.huang, rakie.kim,
	byungchul, apopple, linux-mm

On Sun,  7 Sep 2025 09:08:29 -0700 Chelsy Ratnawat <chelsyratnawat2001@gmail.com> wrote:

> If no bits are set in the policy's node mask, then nodes will be 0.
> This patch adds a check if nodes == 0 before dividing.

Hello Chelsy,

Thank you for the patch! I will start off by saying that it probably does not
hurt to add a check like this. With that said, I think it's best if we clarify:

(1) Have we seen this happen before?
(2) Should we add a Fixes tag?
(3) Do we expect to hit the nodes == 0 case, or is this just to be safe?
(4) If so, should we do more than just return 0 (i.e. WARN_ON?)

From what I can tell, I think it should not be possible for the policy to be
interleave, and the nodes to be null. If we look at mpol_new, there is an
explicit call to nodes_empty that checks if the nodes are empty, and returns
an error if that is the case (of course, excluding MPOL_DEFAULT, which actually
throws an error if the nodes are not empty).

After all, it doesn't really make semantic sense to allow interleaving across
0 nodes ; -)

But as always, it is very possible that I am missing something that you are
seeing : -) Please feel free to correct me if you believe that is the case.

With all of this said, I do agree that it's a bit scary to do a div0, even if
I am confident that the value shouldn't be zero. I don't have any strong
feelings about adding redundant checks, so I will let other mempolicy reviewers
chime in with thier opinions. One thing I do feel strongly though, is that if
we are to move forward in the patch, some explicit clarification that we
have/have not seen it happen before, and a WARN_ON would make sense. 

Thanks again for the patch. I hope you have a great rest of your weekend!
Joshua

> Signed-off-by: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
> ---
>  mm/mempolicy.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index eb83cff7db8c..faacc604fc16 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -2530,6 +2530,8 @@ static unsigned long alloc_pages_bulk_interleave(gfp_t gfp,
>  	unsigned long total_allocated = 0;
>  
>  	nodes = nodes_weight(pol->nodes);
> +	if (nodes == 0)
> +		return 0;
>  	nr_pages_per_node = nr_pages / nodes;
>  	delta = nr_pages - nodes * nr_pages_per_node;
>  
> -- 
> 2.47.3

Sent using hkml (https://github.com/sjp38/hackermail)


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] mm/mempolicy: prevent the risk of division by 0
  2025-09-07 23:53 ` Joshua Hahn
@ 2025-09-08  3:48   ` Huang, Ying
  2025-09-08  7:50     ` David Hildenbrand
  0 siblings, 1 reply; 6+ messages in thread
From: Huang, Ying @ 2025-09-08  3:48 UTC (permalink / raw)
  To: Chelsy Ratnawat, Joshua Hahn
  Cc: akpm, david, ziy, rakie.kim, byungchul, apopple, linux-mm

Joshua Hahn <joshua.hahnjy@gmail.com> writes:

> On Sun,  7 Sep 2025 09:08:29 -0700 Chelsy Ratnawat <chelsyratnawat2001@gmail.com> wrote:
>
>> If no bits are set in the policy's node mask, then nodes will be 0.
>> This patch adds a check if nodes == 0 before dividing.
>
> Hello Chelsy,
>
> Thank you for the patch! I will start off by saying that it probably does not
> hurt to add a check like this. With that said, I think it's best if we clarify:
>
> (1) Have we seen this happen before?
> (2) Should we add a Fixes tag?
> (3) Do we expect to hit the nodes == 0 case, or is this just to be safe?
> (4) If so, should we do more than just return 0 (i.e. WARN_ON?)
>
> From what I can tell, I think it should not be possible for the policy to be
> interleave, and the nodes to be null. If we look at mpol_new, there is an
> explicit call to nodes_empty that checks if the nodes are empty, and returns
> an error if that is the case (of course, excluding MPOL_DEFAULT, which actually
> throws an error if the nodes are not empty).
>
> After all, it doesn't really make semantic sense to allow interleaving across
> 0 nodes ; -)
>
> But as always, it is very possible that I am missing something that you are
> seeing : -) Please feel free to correct me if you believe that is the case.
>
> With all of this said, I do agree that it's a bit scary to do a div0, even if
> I am confident that the value shouldn't be zero. I don't have any strong
> feelings about adding redundant checks, so I will let other mempolicy reviewers
> chime in with thier opinions. One thing I do feel strongly though, is that if
> we are to move forward in the patch, some explicit clarification that we
> have/have not seen it happen before, and a WARN_ON would make sense. 

IIUC, the patch is to catch the bug during kernel development.  And, if
an exception can be generated for dividing by 0, it can be used to catch
the bug already.  If so, IMHO, the patch appears unnecessary.

[snip]

---
Best Regards,
Huang, Ying



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] mm/mempolicy: prevent the risk of division by 0
  2025-09-08  3:48   ` Huang, Ying
@ 2025-09-08  7:50     ` David Hildenbrand
  0 siblings, 0 replies; 6+ messages in thread
From: David Hildenbrand @ 2025-09-08  7:50 UTC (permalink / raw)
  To: Huang, Ying, Chelsy Ratnawat, Joshua Hahn
  Cc: akpm, ziy, rakie.kim, byungchul, apopple, linux-mm

On 08.09.25 05:48, Huang, Ying wrote:
> Joshua Hahn <joshua.hahnjy@gmail.com> writes:
> 
>> On Sun,  7 Sep 2025 09:08:29 -0700 Chelsy Ratnawat <chelsyratnawat2001@gmail.com> wrote:
>>
>>> If no bits are set in the policy's node mask, then nodes will be 0.
>>> This patch adds a check if nodes == 0 before dividing.
>>
>> Hello Chelsy,
>>
>> Thank you for the patch! I will start off by saying that it probably does not
>> hurt to add a check like this. With that said, I think it's best if we clarify:
>>
>> (1) Have we seen this happen before?
>> (2) Should we add a Fixes tag?
>> (3) Do we expect to hit the nodes == 0 case, or is this just to be safe?
>> (4) If so, should we do more than just return 0 (i.e. WARN_ON?)
>>
>>  From what I can tell, I think it should not be possible for the policy to be
>> interleave, and the nodes to be null. If we look at mpol_new, there is an
>> explicit call to nodes_empty that checks if the nodes are empty, and returns
>> an error if that is the case (of course, excluding MPOL_DEFAULT, which actually
>> throws an error if the nodes are not empty).
>>
>> After all, it doesn't really make semantic sense to allow interleaving across
>> 0 nodes ; -)
>>
>> But as always, it is very possible that I am missing something that you are
>> seeing : -) Please feel free to correct me if you believe that is the case.
>>
>> With all of this said, I do agree that it's a bit scary to do a div0, even if
>> I am confident that the value shouldn't be zero. I don't have any strong
>> feelings about adding redundant checks, so I will let other mempolicy reviewers
>> chime in with thier opinions. One thing I do feel strongly though, is that if
>> we are to move forward in the patch, some explicit clarification that we
>> have/have not seen it happen before, and a WARN_ON would make sense.
> 
> IIUC, the patch is to catch the bug during kernel development.  And, if
> an exception can be generated for dividing by 0, it can be used to catch
> the bug already.  If so, IMHO, the patch appears unnecessary.

We don't want to add runtime checks for things that are supposed to be 
caught early during testing. Usually we use VM_WARN_* for sanity 
checking such things, but the div0 would also already trigger early 
during testing, no?


-- 
Cheers

David / dhildenb



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] mm/mempolicy: prevent the risk of division by 0
  2025-09-07 16:08 [PATCH] mm/mempolicy: prevent the risk of division by 0 Chelsy Ratnawat
  2025-09-07 23:53 ` Joshua Hahn
@ 2025-09-08 18:12 ` Gregory Price
  2025-09-08 21:25   ` Gregory Price
  1 sibling, 1 reply; 6+ messages in thread
From: Gregory Price @ 2025-09-08 18:12 UTC (permalink / raw)
  To: Chelsy Ratnawat
  Cc: akpm, david, joshua.hahnjy, ziy, ying.huang, rakie.kim,
	byungchul, apopple, linux-mm

On Sun, Sep 07, 2025 at 09:08:29AM -0700, Chelsy Ratnawat wrote:
> If no bits are set in the policy's node mask, then nodes will be 0.
> This patch adds a check if nodes == 0 before dividing.
> 
> Signed-off-by: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
> ---
>  mm/mempolicy.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index eb83cff7db8c..faacc604fc16 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -2530,6 +2530,8 @@ static unsigned long alloc_pages_bulk_interleave(gfp_t gfp,
>  	unsigned long total_allocated = 0;
>  
>  	nodes = nodes_weight(pol->nodes);
> +	if (nodes == 0)
> +		return 0;

3 second look at this code would tell you the only way this can happen
is a mempolicy where MPOL_INTERLEAVE is set and the nodemask is empty

The only way this can occur is

1) someone setting that explicitly, which is invalid and protected by
   a line in mpol_new:

   else if (nodes_empty(*nodes))
	return ERR_PTR(-EINVAL);

2) or a rebind event occurring due to a cgroup task migration or
   cpuset change - which is protected by a check in the rebind:

   if (nodes_empty(tmp))
	tmp = *nodes;


I doubt this bug was observed in action.

>  	nr_pages_per_node = nr_pages / nodes;
>  	delta = nr_pages - nodes * nr_pages_per_node;
>  
> -- 
> 2.47.3
> 
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] mm/mempolicy: prevent the risk of division by 0
  2025-09-08 18:12 ` Gregory Price
@ 2025-09-08 21:25   ` Gregory Price
  0 siblings, 0 replies; 6+ messages in thread
From: Gregory Price @ 2025-09-08 21:25 UTC (permalink / raw)
  To: Chelsy Ratnawat
  Cc: akpm, david, joshua.hahnjy, ziy, ying.huang, rakie.kim,
	byungchul, apopple, linux-mm

On Mon, Sep 08, 2025 at 02:12:29PM -0400, Gregory Price wrote:
> On Sun, Sep 07, 2025 at 09:08:29AM -0700, Chelsy Ratnawat wrote:
> > If no bits are set in the policy's node mask, then nodes will be 0.
> > This patch adds a check if nodes == 0 before dividing.
> > 
> > Signed-off-by: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
> > ---
> >  mm/mempolicy.c | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> > index eb83cff7db8c..faacc604fc16 100644
> > --- a/mm/mempolicy.c
> > +++ b/mm/mempolicy.c
> > @@ -2530,6 +2530,8 @@ static unsigned long alloc_pages_bulk_interleave(gfp_t gfp,
> >  	unsigned long total_allocated = 0;
> >  
> >  	nodes = nodes_weight(pol->nodes);
> > +	if (nodes == 0)
> > +		return 0;
> 
> 3 second look at this code would tell you the only way this can happen
> is a mempolicy where MPOL_INTERLEAVE is set and the nodemask is empty
>

after some more thought... there is actually a race condition here that
is non-obvious

in some places we take a cpusets cookie to prevent pol->nodes from ever
showing up empty while iterating over the policy nodes.

Excerpt from: alloc_pages_bulk_weighted_interleave

```
        /* read the nodes onto the stack, retry if done during rebind */
        do {
                cpuset_mems_cookie = read_mems_allowed_begin();
                nnodes = read_once_policy_nodemask(pol, &nodes);
        } while (read_mems_allowed_retry(cpuset_mems_cookie));

        /* if the nodemask has become invalid, we cannot do anything */
        if (!nnodes)
                return 0;
```

So this actually can happen - otherwise I wouldn't have bothered with
the stack read in this code chunk anyway.

So now i've argued with and against myself, i think this patch
as-written is not sufficient - and in fact there's a very subtle bug in
the normal interleave that isn't present in the weighted interleave
because we take a copy of the nodes.

So mea culpa for the snap read and response.  But could you please
take a look at the weighted interleave code and model the fix off
of that?

~Gregory


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-09-08 21:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-07 16:08 [PATCH] mm/mempolicy: prevent the risk of division by 0 Chelsy Ratnawat
2025-09-07 23:53 ` Joshua Hahn
2025-09-08  3:48   ` Huang, Ying
2025-09-08  7:50     ` David Hildenbrand
2025-09-08 18:12 ` Gregory Price
2025-09-08 21:25   ` Gregory Price

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox