[Bug 206626] Integer overflow in nfssvc system call

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Mon Jan 25 23:58:10 UTC 2016


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=206626

            Bug ID: 206626
           Summary: Integer overflow in nfssvc system call
           Product: Base System
           Version: 11.0-CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: kern
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: ecturt at gmail.com

The system call `sys_nfssvc` calls `nfssvc_call`, which copies in some user
data, and calls `nfssvc_idname`:

        if (uap->flag & NFSSVC_IDNAME) {
                if ((uap->flag & NFSSVC_NEWSTRUCT) != 0)
                        error = copyin(uap->argp, &nid, sizeof(nid));
                else {
                        error = copyin(uap->argp, &onid, sizeof(onid));
                        if (error == 0) {
                                nid.nid_flag = onid.nid_flag;
                                nid.nid_uid = onid.nid_uid;
                                nid.nid_gid = onid.nid_gid;
                                nid.nid_usermax = onid.nid_usermax;
                                nid.nid_usertimeout = onid.nid_usertimeout;
                                nid.nid_name = onid.nid_name;
                                nid.nid_namelen = onid.nid_namelen;
                                nid.nid_ngroup = 0;
                                nid.nid_grps = NULL;
                        }
                }
                if (error)
                        goto out;
                error = nfssvc_idname(&nid);
                goto out;

In `nfssvc_idname`, `nidp->nid_namelen` is user controllable, and is used
without any bound checks:

/*
 * This function is called from the nfssvc(2) system call, to update the
 * kernel user/group name list(s) for the V4 owner and ownergroup attributes.
 */
APPLESTATIC int
nfssvc_idname(struct nfsd_idargs *nidp)
{
        ...

        if (nidp->nid_flag & NFSID_INITIALIZE) {
                cp = malloc(nidp->nid_namelen + 1, M_NFSSTRING, M_WAITOK);
                error = copyin(CAST_USER_ADDR_T(nidp->nid_name), cp,
                    nidp->nid_namelen);
                if (error != 0) {
                        free(cp, M_NFSSTRING);
                        goto out;
                }

        ...
}

Let's look at the disassembly of how `malloc` is called:

.text:FFFFFFFF807651AD                 mov     edi, [rdi+20h]
.text:FFFFFFFF807651B0                 mov     edx, 2
.text:FFFFFFFF807651B5                 mov     rsi, offset M_NEWNFSSTRING
.text:FFFFFFFF807651BC                 add     edi, 1
.text:FFFFFFFF807651BF                 movsxd  rdi, edi
.text:FFFFFFFF807651C2                 call    malloc

If a `nid_namelen` of `0xffffffff` is supplied, an allocation size of `0` bytes
will be passed to `malloc`.

We then have `copyin` of `0xffffffff` bytes on this allocation of size `0`.

The bug is only triggerable as `root`, and I couldn't get any way to panic from
writing to allocation of 0 bytes.

Code to play with if anyone is interested in exploring its potential further:
https://gist.github.com/CTurt/957360482a4dc453f6a4

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list