[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] alloca() in linux_privcmd_map_foreign_bulk causing segfault


  • To: "AP" <apxeng@xxxxxxxxx>
  • From: "Andres Lagar-Cavilla" <andres@xxxxxxxxxxxxxxxx>
  • Date: Thu, 19 Apr 2012 13:09:42 -0700
  • Cc: jbeulich@xxxxxxxx, ian.campbell@xxxxxxxxxx, santosh.jodh@xxxxxxxxxx, xen-devel@xxxxxxxxxxxxx
  • Delivery-date: Thu, 19 Apr 2012 20:10:14 +0000
  • Domainkey-signature: a=rsa-sha1; c=nofws; d=lagarcavilla.org; h=message-id :in-reply-to:references:date:subject:from:to:cc:reply-to :mime-version:content-type:content-transfer-encoding; q=dns; s= lagarcavilla.org; b=n3V6g6DaOu4KeP2s054k24JzjnkjY6WH+6AXCvagnP5t zQOKRXbJAMWKiZ0Zl/OL/NL9LcVTeqQt5JKAMjLLhBdGIbg8rCFFB9U+oK2JEviB 5H4D9P92T8eDWmHGLgIiWkrAjxOIHv0KXyiAR3NXlq6VzR/RoYn0JwCrq58mRk0=
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>

> On Tue, Apr 17, 2012 at 1:59 PM, AP <apxeng@xxxxxxxxx> wrote:
>> On Tue, Apr 17, 2012 at 8:56 AM, Andres Lagar-Cavilla
>> <andres@xxxxxxxxxxxxxxxx> wrote:
>>>>
>>>> On Tue, 2012-04-17 at 16:19 +0100, Santosh Jodh wrote:
>>>>> I only cared about linux_gnttab_grant_map for user mode blkback. You
>>>>> told me to change all others while I was in there.
>>>>
>>>> Oh, right, I remember now.
>>>>
>>>> Given that reverting it for this case will still leave the same issue
>>>> for the grant case (which I'd forgotten about) I suppose the
>>>> appropriate
>>>> workaround is to touch the alloca'd memory in the appropriate order in
>>>> all cases (perhaps with an alloca helper macro).
>>>
>>> FWIW, I am very skeptical about this whole alloca business. It's very
>>> very
>>> dangerous, no surprise on the bug report. On my code I tend to map
>>> arbitrarily-sized pfn arrays, and I've been thinking of disabling
>>> alloca.
>>>
>>> If your only safeguard is to put a loop that touches everything so the
>>> stack gets allocated .... then what's your gain?
>>>
>>> Just mmap('/dev/zero', MAP_PRIVATE|MAP_POPULATE, PROT_WRITE,
>>> round_to_page_size(what_you_need)). That's likely the fastest way to
>>> get
>>> the array in Linux. It isn't that slow either. And it's safe.
>>
>> I tried and it worked for me.
>>
>> diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
>> --- a/tools/libxc/xc_linux_osdep.c
>> +++ b/tools/libxc/xc_linux_osdep.c
>> @@ -34,16 +34,17 @@
>>  #include <xen/memory.h>
>>  #include <xen/sys/evtchn.h>
>>  #include <xen/sys/gntdev.h>
>>  #include <xen/sys/gntalloc.h>
>>
>>  #include "xenctrl.h"
>>  #include "xenctrlosdep.h"
>>
>> +#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) &
>> ~((1UL<<(_w))-1))
>>  #define ERROR(_m, _a...)
>> xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m , ## _a )
>>  #define PERROR(_m, _a...)
>> xc_osdep_log(xch,XTL_ERROR,XC_INTERNAL_ERROR,_m \
>>                   " (%d = %s)", ## _a , errno, xc_strerror(xch, errno))
>>
>>  static xc_osdep_handle linux_privcmd_open(xc_interface *xch)
>>  {
>>     int flags, saved_errno;
>>     int fd = open("/proc/xen/privcmd", O_RDWR);
>> @@ -281,17 +282,24 @@ static void *linux_privcmd_map_foreign_b
>>     /* Command was not recognized, use fall back */
>>     else if ( rc < 0 && errno == EINVAL && (int)num > 0 )
>>     {
>>         /*
>>          * IOCTL_PRIVCMD_MMAPBATCH_V2 is not supported - fall back to
>>          * IOCTL_PRIVCMD_MMAPBATCH.
>>          */
>>         privcmd_mmapbatch_t ioctlx;
>> -        xen_pfn_t *pfn = alloca(num * sizeof(*pfn));
>> +        xen_pfn_t *pfn = mmap(NULL, ROUNDUP((num * sizeof(*pfn)),
>> XC_PAGE_SHIFT),
>> +                              PROT_READ | PROT_WRITE,
>> +                              MAP_PRIVATE | MAP_ANON | MAP_POPULATE,
>> -1, 0);
>> +        if ( pfn == MAP_FAILED )
>> +        {
>> +            PERROR("xc_map_foreign_bulk: mmap of pfn array failed");
>> +            return NULL;
>> +        }
>>
>>         memcpy(pfn, arr, num * sizeof(*arr));
>>
>>         ioctlx.num = num;
>>         ioctlx.dom = dom;
>>         ioctlx.addr = (unsigned long)addr;
>>         ioctlx.arr = pfn;
>>
>> @@ -323,16 +331,18 @@ static void *linux_privcmd_map_foreign_b
>>                     break;
>>                 }
>>                 rc = -ENOENT;
>>                 continue;
>>             }
>>             break;
>>         }
>>
>> +        munmap(pfn, ROUNDUP((num * sizeof(*pfn)), XC_PAGE_SHIFT));
>> +
>>         if ( rc == -ENOENT && i == num )
>>             rc = 0;
>>         else if ( rc )
>>         {
>>             errno = -rc;
>>             rc = -1;
>>         }
>>     }
>>
>
> Just wondering what is the consensus on this? Is the mmap() method
> acceptable? Should I go ahead and submit this as a patch?

I think you should, and you should include my
Acked-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx>

Thanks,
Andres
>
> Thanks,
> AP
>
>>> Andres
>>>
>>>>
>>>> Ian.
>>>>
>>>>>
>>>>> -----Original Message-----
>>>>> From: Jan Beulich [mailto:JBeulich@xxxxxxxx]
>>>>> Sent: Tuesday, April 17, 2012 12:56 AM
>>>>> To: Ian Campbell; AP
>>>>> Cc: Santosh Jodh; xen-devel@xxxxxxxxxxxxxxxxxxx
>>>>> Subject: Re: [Xen-devel] alloca() in linux_privcmd_map_foreign_bulk
>>>>> causing segfault
>>>>>
>>>>> >>> On 17.04.12 at 09:27, Ian Campbell <Ian.Campbell@xxxxxxxxxx>
>>>>> wrote:
>>>>> > On Tue, 2012-04-17 at 05:57 +0100, AP wrote:
>>>>> >> On xen-unstable 25164:5bbda657a016, when I try to map in large
>>>>> >> amounts of pages (in the GB range) from a guest in to Dom0
>>>>> >
>>>>> > Out of interest -- what are you doing this for?
>>>>> >
>>>>> >>  using
>>>>> >> xc_map_foreign_bulk() I am hitting a segfault.
>>>>> >>
>>>>> >> Program received signal SIGSEGV, Segmentation fault.
>>>>> >> 0x00007ffff7bd38d5 in linux_privcmd_map_foreign_bulk
>>>>> (xch=0x605050,
>>>>> >>     h=<optimized out>, dom=2, prot=<optimized out>,
>>>>> arr=0x7ffff6bf5010,
>>>>> >>     err=0x7ffff67f4010, num=<optimized out>)
>>>>> >>     at /usr/include/x86_64-linux-gnu/bits/string3.h:52
>>>>> >> 52          return __builtin___memcpy_chk (__dest, __src, __len,
>>>>> __bos0
>>>>> (__dest));
>>>>> >> (gdb) bt
>>>>> >> #0  0x00007ffff7bd38d5 in linux_privcmd_map_foreign_bulk
>>>>> (xch=0x605050,
>>>>> >>     h=<optimized out>, dom=2, prot=<optimized out>,
>>>>> arr=0x7ffff6bf5010,
>>>>> >>     err=0x7ffff67f4010, num=<optimized out>)
>>>>> >>     at /usr/include/x86_64-linux-gnu/bits/string3.h:52
>>>>> >> #1  0x00007ffff7bd1ffc in xc_map_foreign_bulk (xch=<optimized
>>>>> out>,
>>>>> >>     dom=<optimized out>, prot=<optimized out>, arr=<optimized
>>>>> out>,
>>>>> >>     err=<optimized out>, num=<optimized out>) at
>>>>> >> xc_foreign_memory.c:79
>>>>> >>
>>>>> >> This was working for me with Xen 4.1.2. On comparing
>>>>> >> linux_privcmd_map_foreign_bulk() between 4.1.2 and unstable I see
>>>>> >> that the pfn array in linux_privcmd_map_foreign_bulk() is being
>>>>> >> allocated using alloca() in unstable vs malloc() in 4.1.2. So I am
>>>>> >> blowing the stack with the call.
>>>>> >
>>>>> > I bet this is due to Linux's stack guard page. This means that if
>>>>> you
>>>>> > try and increase the stack by more than ~1 page you skip entirely
>>>>> over
>>>>> > the "next" stack page and into the guard.
>>>>> >
>>>>> > Does it help if after the alloca you add a loop which touches the
>>>>> > first word of each page of the new buffer? Since the stack grows
>>>>> down
>>>>> > you might actually need to do it backwards from the end of the
>>>>> array
>>>>> > in order to start at the end which is nearest the existing stack?
>>>>> > (it's before coffee o'clock so thinking about stack direction isn't
>>>>> my
>>>>> > strong point yet...)
>>>>>
>>>>> This should really be done by the alloca() implementation itself -
>>>>> anything else is a bug.
>>>>>
>>>>> > The switch to alloca was made recently in order to optimise the
>>>>> > hotpath for a userspace I/O backend.
>>>>>
>>>>> Probably this should be made size-dependent ...
>>>>>
>>>>> > BTW, Santosh, it didn't occur to me at the time but what is privcmd
>>>>> > mmap doing on the hot path for the userspace I/O anyway? Most
>>>>> hotpath
>>>>> > operations should really be grant table ops, a backend shouldn't be
>>>>> > relying on the privileges accorded to dom0 -- for one thing it
>>>>> should
>>>>> > be expected to work in a driver domain.
>>>>>
>>>>> ... if this indeed turns out to be a hot path for something at all?
>>>>>
>>>>> Jan
>>>>>
>>>>> >>  If I replace the alloca() with malloc() the call goes through.
>>>>> What
>>>>> >> is the way around this? Should I be using
>>>>> >> xc_map_foreign_batch() instead, which I think is deprecated?
>>>>> Please
>>>>> >> advice...
>>>>> >>
>>>>> >> Thanks,
>>>>> >> AP
>>>>> >>
>>>
>>>
>



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.