]> www.infradead.org Git - users/jedix/linux-maple.git/commit
drivers/char/mem.c: deny access in open operation when securelevel is set
authorEthan Zhao <ethan.zhao@oracle.com>
Fri, 29 Sep 2017 02:50:35 +0000 (10:50 +0800)
committerEthan Zhao <ethan.zhao@oracle.com>
Tue, 10 Oct 2017 14:06:10 +0000 (22:06 +0800)
commit8ca81822fffb2536aa1076fb17d1ea1413df3e7f
treef4ab54c74740e40c93a800e4752519cf216c965e
parent57f962434c08b3ed680920d40d8bec332775923a
drivers/char/mem.c: deny access in open operation when securelevel is set

Orabug: 26943864

There is still a secure hole left in mem.c driver -- when securelevel is set
userland application could access PCI configuration space via this driver.

--
Attempting to write via mmap() API using acc_test.

[root@ban92uut054 ~]# ./acc_test mmap 0x846000c4=0x1
Using mmap() API for access
mmap write wrote 0x1

[root@ban92uut054 ~]# setpci -s 46:00.0 0xc4.l
00000001

How, write 0x0 to offset 0xc4
[root@ban92uut054 ~]# ./acc_test mmap 0x846000c4=0x0
Using mmap() API for access
mmap write wrote 0x0
[root@ban92uut054 ~]# setpci -s 46:00.0 0xc4.l
00000000
--
source code of acc_test program:

main(int argc, char *argv[])
{

int fd;
int retval;
int val;
off_t addr;
char *tmp;
int operation = 0; //read

int access_type = -1;
off_t page_base = 0;
off_t page_offset = 0;
off_t pagesize = sysconf(_SC_PAGE_SIZE);
char *mem;
int prot;

if (argc < 3) {
printf("Insufficient args: acc_test rw|mmap <addr> [-w <val>]\n");
return -1;
}

if (strcmp("rw", argv[1]) == 0) {
access_type = 1;
printf("Using pread()/pwrite() API for access\n");
}
else if (strcmp("mmap", argv[1]) == 0) {
access_type = 2;
printf("Using mmap() API for access\n");
}
else {
printf("Illegal access type: must be rw or mmap\n");
return -1;
}

addr = strtoul(argv[2], &tmp, 16);
if ((tmp && (*tmp != '='))  &&
            ((*tmp != '\0') || (errno == EINVAL) ||
            (addr == ULONG_MAX && errno == ERANGE))) {
                fprintf(stderr, "Invalid address specified; must be hex based\n");
                if (errno) perror("error : ");
                exit(1);
}
else if (tmp && (*tmp == '=')) { // write case
tmp++;
val = strtoul(tmp, NULL, 16);
operation = 1;
}

//fd = open("/sys/bus/pci/devices/0000:46:00.0/config",O_RDWR | O_SYNC);
//retval = pread(fd, &val, 4, 0xc4);

if (operation == 1)
fd = open("/dev/mem",O_RDWR);
else
fd = open("/dev/mem",O_RDONLY);

        if (fd < 0) {
perror("open failed");
exit(1);
}

switch (access_type) {

case 1 : // pread/pwrite API
 if (!operation) {
  if (pread(fd, &val, 4, addr) < 0) {
perror("pread failed");
return -1;
}
else
printf("pread returned 0x%x from 0x%x\n",val,addr);
 }
 else {
if (pwrite(fd, &val, 4, addr) < 0) {
perror ("pwrite failed");
return -1;
}
printf("pwrite() wrote 0x%x to 0x%x\n",val,addr);
}
break;

case 2 :   // mmap API
page_base = (addr / pagesize) * pagesize;
page_offset = addr - page_base;
prot = PROT_READ;
if (operation)
prot |= PROT_WRITE;
mem = mmap(NULL, page_offset + 4, prot, MAP_SHARED,
fd, page_base);
if (mem == MAP_FAILED) {
perror("can't mmap");
return -1;
}

if (!operation)
printf("mmap read returned 0x%x\n",*(uint32_t *)&mem[page_offset]);
else {
*(uint32_t *)&mem[page_offset] = (uint32_t)val;
printf("mmap write wrote 0x%x\n",val);
}

break;

default :
printf("Illegal access mode\n");
return -1;
}

close(fd);

}
--

This patch is purposed to fix this hole when securelevel is set where one could write to
/dev/mem via the mmap() API. The fix to disallow opening /dev/mem or /dev/kmem
for access. The fix checks access at open rather than have get_securelevel() called at
the various write/read locations.

This issue is specific to UEK4 !

Signed-off-by: James Puthukattukaran <james.puthukattukaran@oracle.com>
Signed-off-by: Ethan Zhao <ethan.zhao@oracle.com>
Reviewed-by: Eric Snowberg <eric.snowberg@oracle.com>
Reviewed-by: Khalid Aziz <khalid.aziz@oracle>
drivers/char/mem.c