From: Oleg Nesterov <oleg@redhat.com>
To: Andy Lutomirski <luto@amacapital.net>,
Hugh Dickins <hughd@google.com>,
Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jan Kratochvil <jan.kratochvil@redhat.com>,
Sergio Durigan Junior <sergiodj@redhat.com>,
GDB Patches <gdb-patches@sourceware.org>,
Pedro Alves <palves@redhat.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: install_special_mapping && vm_pgoff (Was: vvar, gup && coredump)
Date: Mon, 16 Mar 2015 20:01:54 +0100 [thread overview]
Message-ID: <20150316190154.GA18472@redhat.com> (raw)
In-Reply-To: <20150312174653.GA13086@redhat.com>
On 03/12, Oleg Nesterov wrote:
>
> OTOH. We can probably add ->access() into special_mapping_vmops, this
> way __access_remote_vm() could work even if gup() fails ?
So I tried to think how special_mapping_vmops->access() can work, it
needs to rely on ->vm_pgoff.
But afaics this logic is just broken. Lets even forget about vvar vma
which uses remap_file_pages(). Lets look at "[vdso]" which uses the
"normal" pages.
The comment in special_mapping_fault() says
* special mappings have no vm_file, and in that case, the mm
* uses vm_pgoff internally.
Yes. But afaics mm/ doesn't do this correctly. So
* do not copy this code into drivers!
looks like a good recommendation ;)
I think that this logic is wrong even if ARRAY_SIZE(pages) == 1, but I am
not sure. But since vdso use 2 pages, it is trivial to show that this logic
is wrong. To verify, I changed show_map_vma() to expose pgoff even if !file,
but this test-case can show the problem too:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <assert.h>
void *find_vdso_vaddr(void)
{
FILE *perl;
char buf[32] = {};
perl = popen("perl -e 'open STDIN,qq|/proc/@{[getppid]}/maps|;"
"/^(.*?)-.*vdso/ && print hex $1 while <>'", "r");
fread(buf, sizeof(buf), 1, perl);
fclose(perl);
return (void *)atol(buf);
}
#define PAGE_SIZE 4096
int main(void)
{
void *vdso = find_vdso_vaddr();
assert(vdso);
// of course they should differ, and they do so far
printf("vdso pages differ: %d\n",
!!memcmp(vdso, vdso + PAGE_SIZE, PAGE_SIZE));
// split into 2 vma's
assert(mprotect(vdso, PAGE_SIZE, PROT_READ) == 0);
// force another fault on the next check
assert(madvise(vdso, 2 * PAGE_SIZE, MADV_DONTNEED) == 0);
// now they no longer differ, the 2nd vm_pgoff is wrong
printf("vdso pages differ: %d\n",
!!memcmp(vdso, vdso + PAGE_SIZE, PAGE_SIZE));
return 0;
}
output:
vdso pages differ: 1
vdso pages differ: 0
And not only "split_vma" is wrong, I think that "move_vma" is not right too.
Note this check in copy_vma(),
/*
* If anonymous vma has not yet been faulted, update new pgoff
* to match new location, to increase its chance of merging.
*/
if (unlikely(!vma->vm_file && !vma->anon_vma)) {
pgoff = addr >> PAGE_SHIFT;
faulted_in_anon_vma = false;
}
I can easily misread this code. But it doesn't look right too. If vdso was cow'ed
(breakpoint installed by gdb) and sys_nremap()'ed, then the new pgoff will be wrong
too after, say, MADV_DONTNEED.
Or I am totally confused?
Oleg.
next prev parent reply other threads:[~2015-03-16 19:03 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <878ufc9kau.fsf@redhat.com>
[not found] ` <20150305154827.GA9441@host1.jankratochvil.net>
[not found] ` <87zj7r5fpz.fsf@redhat.com>
[not found] ` <20150305205744.GA13165@host1.jankratochvil.net>
[not found] ` <20150311200052.GA22654@redhat.com>
2015-03-12 14:34 ` vvar, gup && coredump Oleg Nesterov
2015-03-12 16:29 ` Andy Lutomirski
2015-03-12 16:54 ` Oleg Nesterov
2015-03-12 17:17 ` Andy Lutomirski
2015-03-12 17:39 ` Oleg Nesterov
2015-03-12 17:45 ` Sergio Durigan Junior
2015-03-12 18:02 ` Oleg Nesterov
2015-03-13 4:50 ` Sergio Durigan Junior
2015-03-13 15:04 ` Oleg Nesterov
2015-03-12 17:55 ` Andy Lutomirski
2015-03-12 18:08 ` Oleg Nesterov
2015-03-12 18:33 ` Andy Lutomirski
2015-03-13 15:22 ` Oleg Nesterov
2015-03-12 17:46 ` Oleg Nesterov
2015-03-12 17:54 ` Andy Lutomirski
2015-03-12 18:05 ` Oleg Nesterov
2015-03-12 18:23 ` Sergio Durigan Junior
2015-03-12 18:19 ` Pedro Alves
2015-03-12 18:25 ` Andy Lutomirski
2015-03-16 19:01 ` Oleg Nesterov [this message]
2015-03-16 19:20 ` install_special_mapping && vm_pgoff (Was: vvar, gup && coredump) Andy Lutomirski
2015-03-16 19:20 ` Andy Lutomirski
2015-03-16 19:44 ` Oleg Nesterov
2015-03-16 19:44 ` Oleg Nesterov
2015-03-17 13:43 ` Oleg Nesterov
2015-03-17 13:43 ` Oleg Nesterov
2015-03-18 1:44 ` Andy Lutomirski
2015-03-18 1:44 ` Andy Lutomirski
2015-03-18 18:06 ` Oleg Nesterov
2015-03-18 18:06 ` Oleg Nesterov
2015-03-16 19:40 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150316190154.GA18472@redhat.com \
--to=oleg@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=hughd@google.com \
--cc=jan.kratochvil@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=palves@redhat.com \
--cc=sergiodj@redhat.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.