maple_tree: fix allocation in mas_sparse_area()
commit 29ad6bb313487370f9dfe5441fc8982593b6384e upstream. In the case of reverse allocation, mas->index and mas->last do not point to the correct allocation range, which will cause users to get incorrect allocation results, so fix it. If the user does not use it in a specific way, this bug will not be triggered. This is a bug, but only VMA uses it now, the way VMA is used now will not trigger it. There is a possibility that a user will trigger it in the future. Also re-check whether the size is still satisfied after the lower bound was increased, which is a corner case and is incorrect in previous versions. Link: https://lkml.kernel.org/r/20230419093625.99201-1-zhangpeng.00@bytedance.com Fixes: 54a611b60590 ("Maple Tree: add new data structure") Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com> Cc: Liam R. Howlett <Liam.Howlett@Oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
cf0df43520
commit
34f3005303
@ -5277,25 +5277,28 @@ static inline void mas_fill_gap(struct ma_state *mas, void *entry,
|
||||
* @size: The size of the gap
|
||||
* @fwd: Searching forward or back
|
||||
*/
|
||||
static inline void mas_sparse_area(struct ma_state *mas, unsigned long min,
|
||||
static inline int mas_sparse_area(struct ma_state *mas, unsigned long min,
|
||||
unsigned long max, unsigned long size, bool fwd)
|
||||
{
|
||||
unsigned long start = 0;
|
||||
|
||||
if (!unlikely(mas_is_none(mas)))
|
||||
start++;
|
||||
if (!unlikely(mas_is_none(mas)) && min == 0) {
|
||||
min++;
|
||||
/*
|
||||
* At this time, min is increased, we need to recheck whether
|
||||
* the size is satisfied.
|
||||
*/
|
||||
if (min > max || max - min + 1 < size)
|
||||
return -EBUSY;
|
||||
}
|
||||
/* mas_is_ptr */
|
||||
|
||||
if (start < min)
|
||||
start = min;
|
||||
|
||||
if (fwd) {
|
||||
mas->index = start;
|
||||
mas->last = start + size - 1;
|
||||
return;
|
||||
mas->index = min;
|
||||
mas->last = min + size - 1;
|
||||
} else {
|
||||
mas->last = max;
|
||||
mas->index = max - size + 1;
|
||||
}
|
||||
|
||||
mas->index = max;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5324,10 +5327,8 @@ int mas_empty_area(struct ma_state *mas, unsigned long min,
|
||||
return -EBUSY;
|
||||
|
||||
/* Empty set */
|
||||
if (mas_is_none(mas) || mas_is_ptr(mas)) {
|
||||
mas_sparse_area(mas, min, max, size, true);
|
||||
return 0;
|
||||
}
|
||||
if (mas_is_none(mas) || mas_is_ptr(mas))
|
||||
return mas_sparse_area(mas, min, max, size, true);
|
||||
|
||||
/* The start of the window can only be within these values */
|
||||
mas->index = min;
|
||||
@ -5377,10 +5378,8 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
|
||||
}
|
||||
|
||||
/* Empty set. */
|
||||
if (mas_is_none(mas) || mas_is_ptr(mas)) {
|
||||
mas_sparse_area(mas, min, max, size, false);
|
||||
return 0;
|
||||
}
|
||||
if (mas_is_none(mas) || mas_is_ptr(mas))
|
||||
return mas_sparse_area(mas, min, max, size, false);
|
||||
|
||||
/* The start of the window can only be within these values. */
|
||||
mas->index = min;
|
||||
|
Loading…
x
Reference in New Issue
Block a user