Re: Linux 1.3.36: 'bforget' is flawed

Linus Torvalds (Linus.Torvalds@cs.Helsinki.FI)
Mon, 6 Nov 1995 14:15:03 +0200


Michael Elizabeth Chastain: "Linux 1.3.36: 'bforget' is flawed" (Nov 5, 18:52):
> Hello,
>
> The attached test program demonstrates a problem in the new 'bforget'
> function in 'fd/buffer.c'. This program runs without problems on
> 1.3.35, but causes problems on 1.3.36.

Actually, as far as I can tell "bforget" itself is ok, but there is a
bug in the mmap exit code..

> From reading the code, it appears that 'bforget' is an optimized form
> of 'brelse' for cases where a buffer has 'b_count == 1'. But buffers
> can be shared with non-buffer objects, specifically with memory maps,
> and this causes the problem.

Actually, "bforget()" assumes that the buffers _can't_ be shared with
memory maps, and that is enforced by "truncate()" etc with the
"vmtruncate()" code. Similarly, when removing the file with "unlink()",
the file is actually removed only after it is no longer used, so there
cannot in theory be any shared pages.

_However_, the mmap exit code actually does things the wrong way. It
_first_ releases the inode, and only _then_ it unmaps the (potentially
shared) pages.

Fixes go something like this:

- in mm/mmap.c, function exit_mmap()

move the "if (mpnt->vm_inode) iput(mpnt->vm_inode)"
to _after_ the "zap_page_range(....)" line.

- in mm/mmap.c, function "unmap_fixup()"

after calling the "mpnt->vm_ops->close()" function,
call "zap_page_range()" for the area before doing the
iput()..

I'll have to take a closer look, but something like the above should fix
it. Sorry for not having real diffs yet,

Linus