Hi Ajay,

> On Jun 5, 2020 at 02:23,Ajay Kaher <aka...@vmware.com> wrote:
> 
> So, v4.9.y should be vulnerable, however not able to reproduce on v4.9.y.
> Does any specific scenerio need to test for v4.9.y?
> 
> For v4.9, modified test program as MAP_SHARED_VALIDATE is not available:
> - return mmap(NULL, REGION_PM_SIZE, PROT, MAP_SHARED_VALIDATE|MAP_SYNC,
> + return mmap(NULL, REGION_PM_SIZE, PROT, MAP_SHARED|MAP_SYNC,
> 
> Let me know if I need to test some other way for v4.9.y.
> 

I further looked into this.  In v4.9, fsdax (mount a dax file
system, then open, mmap, mremap) does not suffer this issue
because fsdax does not use huge page (FS_DAX_PMD is marked
BROKEN).

fs/dax.c:dax_pmd_fault:

        if (!IS_ENABLED(CONFIG_FS_DAX_PMD))
                return VM_FAULT_FALLBACK;

fs/Kconfig:

config FS_DAX_PMD
        bool
        default FS_DAX
        depends on FS_DAX
        depends on ZONE_DEVICE
        depends on TRANSPARENT_HUGEPAGE
        depends on BROKEN


However, I can re-produce the issue for the devdax mode.  Here is how
I re-produce it:

1. It seems some interface changed for ndctl.  So I use an old
   commit (4295f1ea614a26e1304ed590fb7209c8c78270ab) in the repo
   https://github.com/pmem/ndctl.
2. sudo ./ndctl/ndctl create-namespace -f -t pmem -m dax -e 'namespace0.0'
3. then use the following program:

#define _GNU_SOURCE
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>

#define PROT                    PROT_READ|PROT_WRITE

#define REGION_PM_TMP_PATH      "/dev/dax0.0"

#define REGION_MEM_SIZE 1024ULL*1024*1024*2
#define REGION_PM_SIZE  1024ULL*1024*1024*4
#define REMAP_MEM_OFF   1024ULL*1024*1024*1
#define REMAP_PM_OFF    1024ULL*1024*1024*3
#define REMAP_SIZE      1024ULL*1024*1024*1

#define REGION_MEM_PTR  ((void *)0x7fd400000000ULL)
#define REGION_PM_PTR   ((void *)0x4fd300000000ULL)

char * map_tmp_pm_region(void)
{
        int fd;

        fd = open(REGION_PM_TMP_PATH, O_RDWR, 0644);
        if (fd < 0) {
                perror(REGION_PM_TMP_PATH);
                exit(-1);
        }

        return mmap(REGION_PM_PTR, REGION_PM_SIZE, PROT, MAP_SHARED|MAP_SYNC,
                   fd, 0);
}

int main(int argc, char **argv)
{
        char *regm, *regp, *remap;
        int ret;

        regm = mmap(REGION_MEM_PTR, REGION_MEM_SIZE, PROT, 
MAP_PRIVATE|MAP_ANONYMOUS,
                    -1, 0);
        if (regm == MAP_FAILED) {
                perror("regm");
                return -1;
        }

        regp = map_tmp_pm_region();
        if (regp == MAP_FAILED) {
                perror("regp");
                return -1;
        }

        memset(regm, 'a', REGION_MEM_SIZE);
        memset(regp, 'i', REGION_PM_SIZE);

        remap = mremap(regp + REMAP_PM_OFF, REMAP_SIZE, REMAP_SIZE,
                       MREMAP_MAYMOVE|MREMAP_FIXED, regm + REMAP_MEM_OFF);
        if (remap != regm + REMAP_MEM_OFF) {
                perror("mremap");
                return -1;
        }

        *(regm + REMAP_MEM_OFF) = 0x00;
        return 0;
}

4. Then I was able to see the "Corrupted page table" message in dmesg.

Best regards,
Fan

Reply via email to