Skip to content

Commit

Permalink
hugetlb: remove use of list iterator variable after loop
Browse files Browse the repository at this point in the history
In preparation to limit the scope of the list iterator to the list
traversal loop, use a dedicated pointer to iterate through the list [1].

Before hugetlb_resv_map_add() was expecting a file_region struct, but in
case the list iterator in add_reservation_in_range() did not exit early,
the variable passed in, is not actually a valid structure.

In such a case 'rg' is computed on the head element of the list and
represents an out-of-bounds pointer.  This still remains safe *iff* you
only use the link member (as it is done in hugetlb_resv_map_add()).

To avoid the type-confusion altogether and limit the list iterator to the
loop, only a list_head pointer is kept to pass to hugetlb_resv_map_add().

Link: https://lore.kernel.org/all/CAHk-=wgRr_D8CB-D9Kg-c=EHreAsk5SqXPwr9Y7k9sA6cWXJ6w@mail.gmail.com/ [1]
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Jakob Koschel <[email protected]>
Cc: Mike Kravetz <[email protected]>
Cc: Mike Rapoport <[email protected]>
Cc: "Brian Johannesmeyer" <[email protected]>
Cc: Cristiano Giuffrida <[email protected]>
Cc: "Bos, H.J." <[email protected]>
Cc: Jakob Koschel <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
  • Loading branch information
Jakob-Koschel authored and akpm00 committed Apr 29, 2022
1 parent b283d98 commit 84448c8
Showing 1 changed file with 19 additions and 14 deletions.
33 changes: 19 additions & 14 deletions mm/hugetlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ static void coalesce_file_region(struct resv_map *resv, struct file_region *rg)
}

static inline long
hugetlb_resv_map_add(struct resv_map *map, struct file_region *rg, long from,
hugetlb_resv_map_add(struct resv_map *map, struct list_head *rg, long from,
long to, struct hstate *h, struct hugetlb_cgroup *cg,
long *regions_needed)
{
Expand All @@ -379,7 +379,7 @@ hugetlb_resv_map_add(struct resv_map *map, struct file_region *rg, long from,
if (!regions_needed) {
nrg = get_file_region_entry_from_cache(map, from, to);
record_hugetlb_cgroup_uncharge_info(cg, h, map, nrg);
list_add(&nrg->link, rg->link.prev);
list_add(&nrg->link, rg);
coalesce_file_region(map, nrg);
} else
*regions_needed += 1;
Expand All @@ -402,47 +402,52 @@ static long add_reservation_in_range(struct resv_map *resv, long f, long t,
long add = 0;
struct list_head *head = &resv->regions;
long last_accounted_offset = f;
struct file_region *rg = NULL, *trg = NULL;
struct file_region *iter, *trg = NULL;
struct list_head *rg = NULL;

if (regions_needed)
*regions_needed = 0;

/* In this loop, we essentially handle an entry for the range
* [last_accounted_offset, rg->from), at every iteration, with some
* [last_accounted_offset, iter->from), at every iteration, with some
* bounds checking.
*/
list_for_each_entry_safe(rg, trg, head, link) {
list_for_each_entry_safe(iter, trg, head, link) {
/* Skip irrelevant regions that start before our range. */
if (rg->from < f) {
if (iter->from < f) {
/* If this region ends after the last accounted offset,
* then we need to update last_accounted_offset.
*/
if (rg->to > last_accounted_offset)
last_accounted_offset = rg->to;
if (iter->to > last_accounted_offset)
last_accounted_offset = iter->to;
continue;
}

/* When we find a region that starts beyond our range, we've
* finished.
*/
if (rg->from >= t)
if (iter->from >= t) {
rg = iter->link.prev;
break;
}

/* Add an entry for last_accounted_offset -> rg->from, and
/* Add an entry for last_accounted_offset -> iter->from, and
* update last_accounted_offset.
*/
if (rg->from > last_accounted_offset)
add += hugetlb_resv_map_add(resv, rg,
if (iter->from > last_accounted_offset)
add += hugetlb_resv_map_add(resv, iter->link.prev,
last_accounted_offset,
rg->from, h, h_cg,
iter->from, h, h_cg,
regions_needed);

last_accounted_offset = rg->to;
last_accounted_offset = iter->to;
}

/* Handle the case where our range extends beyond
* last_accounted_offset.
*/
if (!rg)
rg = head->prev;
if (last_accounted_offset < t)
add += hugetlb_resv_map_add(resv, rg, last_accounted_offset,
t, h, h_cg, regions_needed);
Expand Down

0 comments on commit 84448c8

Please sign in to comment.