Re: BISECT result: 6.0.0-RC kernels trigger Firefox snap bug with 6.0.0-rc3 through 6.0.0-rc7
From: Slade Watkins
Date: Wed Oct 19 2022 - 01:17:27 EST
Hi Phillip,
On Tue, Oct 18, 2022 at 1:42 PM Phillip Lougher <phillip@xxxxxxxxxxxxxxx> wrote:
>
> This diff has fixed the problem with my repoducer.
> Please test and report your results.
>
> Phillip
Tested-by me just a few moments ago and can report this fixed the
problem. (I believe Mirsad also reported that this fixed it.)
Yours,
-srw
>
> diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
> index e56510964b22..e526eb7a1658 100644
> --- a/fs/squashfs/file.c
> +++ b/fs/squashfs/file.c
> @@ -557,6 +557,7 @@ static void squashfs_readahead(struct readahead_control *ractl)
> int res, bsize;
> u64 block = 0;
> unsigned int expected;
> + struct page *last_page;
>
> nr_pages = __readahead_batch(ractl, pages, max_pages);
> if (!nr_pages)
> @@ -593,15 +594,15 @@ static void squashfs_readahead(struct readahead_control *ractl)
>
> res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
>
> - squashfs_page_actor_free(actor);
> + last_page = squashfs_page_actor_free(actor);
>
> if (res == expected) {
> int bytes;
>
> /* Last page (if present) may have trailing bytes not filled */
> bytes = res % PAGE_SIZE;
> - if (pages[nr_pages - 1]->index == file_end && bytes)
> - memzero_page(pages[nr_pages - 1], bytes,
> + if (index == file_end && bytes && last_page)
> + memzero_page(last_page, bytes,
> PAGE_SIZE - bytes);
>
> for (i = 0; i < nr_pages; i++) {
> diff --git a/fs/squashfs/page_actor.c b/fs/squashfs/page_actor.c
> index 54b93bf4a25c..6aa38f88e31c 100644
> --- a/fs/squashfs/page_actor.c
> +++ b/fs/squashfs/page_actor.c
> @@ -53,6 +53,7 @@ struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
> actor->pages = pages;
> actor->next_page = 0;
> actor->tmp_buffer = NULL;
> + actor->last_page = NULL;
> actor->squashfs_first_page = cache_first_page;
> actor->squashfs_next_page = cache_next_page;
> actor->squashfs_finish_page = cache_finish_page;
> @@ -71,11 +72,13 @@ static void *handle_next_page(struct squashfs_page_actor *actor)
> (actor->next_index != actor->page[actor->next_page]->index)) {
> actor->next_index++;
> actor->returned_pages++;
> + actor->last_page = NULL;
> return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM);
> }
>
> actor->next_index++;
> actor->returned_pages++;
> + actor->last_page = actor->page[actor->next_page];
> return actor->pageaddr = kmap_local_page(actor->page[actor->next_page++]);
> }
>
> diff --git a/fs/squashfs/page_actor.h b/fs/squashfs/page_actor.h
> index 95ffbb543d91..97d4983559b1 100644
> --- a/fs/squashfs/page_actor.h
> +++ b/fs/squashfs/page_actor.h
> @@ -16,6 +16,7 @@ struct squashfs_page_actor {
> void *(*squashfs_first_page)(struct squashfs_page_actor *);
> void *(*squashfs_next_page)(struct squashfs_page_actor *);
> void (*squashfs_finish_page)(struct squashfs_page_actor *);
> + struct page *last_page;
> int pages;
> int length;
> int next_page;
> @@ -29,10 +30,13 @@ extern struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
> extern struct squashfs_page_actor *squashfs_page_actor_init_special(
> struct squashfs_sb_info *msblk,
> struct page **page, int pages, int length);
> -static inline void squashfs_page_actor_free(struct squashfs_page_actor *actor)
> +static inline struct page *squashfs_page_actor_free(struct squashfs_page_actor *actor)
> {
> + struct page *last_page = actor->last_page;
> +
> kfree(actor->tmp_buffer);
> kfree(actor);
> + return last_page;
> }
> static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
> {