diff mbox

9pfs: fix potential segfault during walk

Message ID 147398054143.25432.18026157491978434193.stgit@bahia (mailing list archive)
State New, archived
Headers show

Commit Message

Greg Kurz Sept. 15, 2016, 11:05 p.m. UTC
If the call to fid_to_qid() returns an error, we will call v9fs_path_free()
on uninitialized paths.

Let's fix this by initializing dpath and path before calling fid_to_qid().

Signed-off-by: Greg Kurz <groug@kaod.org>
---

Thanks Paolo (and Coverity) for spotting this.

Cc'ing stable as this is a regression introduced in 2.7. It is also present
in Michael's stable-2.6-staging branch.

 hw/9pfs/9p.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

Greg Kurz Sept. 16, 2016, 7:19 a.m. UTC | #1
On Fri, 16 Sep 2016 01:05:11 +0200
Greg Kurz <groug@kaod.org> wrote:

> If the call to fid_to_qid() returns an error, we will call v9fs_path_free()
> on uninitialized paths.
> 

I'll add this to the changelog:

It is a regression introduced by the following commit:

56f101ecce0e 9pfs: handle walk of ".." in the root directory

> Let's fix this by initializing dpath and path before calling fid_to_qid().
> 
> Signed-off-by: Greg Kurz <groug@kaod.org>
> ---
> 
> Thanks Paolo (and Coverity) for spotting this.
> 
> Cc'ing stable as this is a regression introduced in 2.7. It is also present
> in Michael's stable-2.6-staging branch.
> 
>  hw/9pfs/9p.c |    5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> index dfe293d11d1c..91a497079acb 100644
> --- a/hw/9pfs/9p.c
> +++ b/hw/9pfs/9p.c
> @@ -1320,13 +1320,14 @@ static void v9fs_walk(void *opaque)
>          goto out_nofid;
>      }
>  
> +    v9fs_path_init(&dpath);
> +    v9fs_path_init(&path);
> +
>      err = fid_to_qid(pdu, fidp, &qid);
>      if (err < 0) {
>          goto out;
>      }
>  
> -    v9fs_path_init(&dpath);
> -    v9fs_path_init(&path);
>      /*
>       * Both dpath and path initially poin to fidp.
>       * Needed to handle request with nwnames == 0
>
Cédric Le Goater Sept. 16, 2016, 7:37 a.m. UTC | #2
On 09/16/2016 09:19 AM, Greg Kurz wrote:
> On Fri, 16 Sep 2016 01:05:11 +0200
> Greg Kurz <groug@kaod.org> wrote:
> 
>> If the call to fid_to_qid() returns an error, we will call v9fs_path_free()
>> on uninitialized paths.
>>
> 
> I'll add this to the changelog:
> 
> It is a regression introduced by the following commit:
> 
> 56f101ecce0e 9pfs: handle walk of ".." in the root directory
> 
>> Let's fix this by initializing dpath and path before calling fid_to_qid().
>>
>> Signed-off-by: Greg Kurz <groug@kaod.org>
>> ---
>>
>> Thanks Paolo (and Coverity) for spotting this.
>>
>> Cc'ing stable as this is a regression introduced in 2.7. It is also present
>> in Michael's stable-2.6-staging branch.
>>
>>  hw/9pfs/9p.c |    5 +++--
>>  1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
>> index dfe293d11d1c..91a497079acb 100644
>> --- a/hw/9pfs/9p.c
>> +++ b/hw/9pfs/9p.c
>> @@ -1320,13 +1320,14 @@ static void v9fs_walk(void *opaque)
>>          goto out_nofid;
>>      }
>>  
>> +    v9fs_path_init(&dpath);
>> +    v9fs_path_init(&path);
>> +
>>      err = fid_to_qid(pdu, fidp, &qid);
>>      if (err < 0) {
>>          goto out;
>>      }
>>  
>> -    v9fs_path_init(&dpath);
>> -    v9fs_path_init(&path);
>>      /*
>>       * Both dpath and path initially poin to fidp.
>>       * Needed to handle request with nwnames == 0
>>
> 
> 


There is still a possible segv I think, in out_nofid :

    if (nwnames && nwnames <= P9_MAXWELEM) {
        for (name_idx = 0; name_idx < nwnames; name_idx++) {
            v9fs_string_free(&wnames[name_idx]);
        
&wnames[name_idx] could NULL if pdu_unmarshal() fails.



C.
Greg Kurz Sept. 16, 2016, 8:52 a.m. UTC | #3
On Fri, 16 Sep 2016 09:37:48 +0200
Cédric Le Goater <clg@kaod.org> wrote:

> On 09/16/2016 09:19 AM, Greg Kurz wrote:
> > On Fri, 16 Sep 2016 01:05:11 +0200
> > Greg Kurz <groug@kaod.org> wrote:
> >   
> >> If the call to fid_to_qid() returns an error, we will call v9fs_path_free()
> >> on uninitialized paths.
> >>  
> > 
> > I'll add this to the changelog:
> > 
> > It is a regression introduced by the following commit:
> > 
> > 56f101ecce0e 9pfs: handle walk of ".." in the root directory
> >   
> >> Let's fix this by initializing dpath and path before calling fid_to_qid().
> >>
> >> Signed-off-by: Greg Kurz <groug@kaod.org>
> >> ---
> >>
> >> Thanks Paolo (and Coverity) for spotting this.
> >>
> >> Cc'ing stable as this is a regression introduced in 2.7. It is also present
> >> in Michael's stable-2.6-staging branch.
> >>
> >>  hw/9pfs/9p.c |    5 +++--
> >>  1 file changed, 3 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> >> index dfe293d11d1c..91a497079acb 100644
> >> --- a/hw/9pfs/9p.c
> >> +++ b/hw/9pfs/9p.c
> >> @@ -1320,13 +1320,14 @@ static void v9fs_walk(void *opaque)
> >>          goto out_nofid;
> >>      }
> >>  
> >> +    v9fs_path_init(&dpath);
> >> +    v9fs_path_init(&path);
> >> +
> >>      err = fid_to_qid(pdu, fidp, &qid);
> >>      if (err < 0) {
> >>          goto out;
> >>      }
> >>  
> >> -    v9fs_path_init(&dpath);
> >> -    v9fs_path_init(&path);
> >>      /*
> >>       * Both dpath and path initially poin to fidp.
> >>       * Needed to handle request with nwnames == 0
> >>  
> > 
> >   
> 
> 
> There is still a possible segv I think, in out_nofid :
> 
>     if (nwnames && nwnames <= P9_MAXWELEM) {
>         for (name_idx = 0; name_idx < nwnames; name_idx++) {
>             v9fs_string_free(&wnames[name_idx]);
>         
> &wnames[name_idx] could NULL if pdu_unmarshal() fails.
> 

We're safe because wnames[] is fully allocated and zeroed:

    if (nwnames && nwnames <= P9_MAXWELEM) {
        wnames = g_malloc0(sizeof(wnames[0]) * nwnames); <--- here
        qids   = g_malloc0(sizeof(qids[0]) * nwnames);
        for (i = 0; i < nwnames; i++) {
            err = pdu_unmarshal(pdu, offset, "s", &wnames[i]);
            if (err < 0) {
                goto out_nofid;
            }

But I agree that the calls to v9fs_string_free() without the corresponding
calls to v9fs_string_init(), as it is done everywhere else, is disturbing
and should be addressed.

Thanks.

--
Greg

> 
> 
> C.
> 
> 
> 
>
Cédric Le Goater Sept. 16, 2016, 9:30 a.m. UTC | #4
On 09/16/2016 10:52 AM, Greg Kurz wrote:
> On Fri, 16 Sep 2016 09:37:48 +0200
> Cédric Le Goater <clg@kaod.org> wrote:
> 
>> On 09/16/2016 09:19 AM, Greg Kurz wrote:
>>> On Fri, 16 Sep 2016 01:05:11 +0200
>>> Greg Kurz <groug@kaod.org> wrote:
>>>   
>>>> If the call to fid_to_qid() returns an error, we will call v9fs_path_free()
>>>> on uninitialized paths.
>>>>  
>>>
>>> I'll add this to the changelog:
>>>
>>> It is a regression introduced by the following commit:
>>>
>>> 56f101ecce0e 9pfs: handle walk of ".." in the root directory
>>>   
>>>> Let's fix this by initializing dpath and path before calling fid_to_qid().
>>>>
>>>> Signed-off-by: Greg Kurz <groug@kaod.org>
>>>> ---
>>>>
>>>> Thanks Paolo (and Coverity) for spotting this.
>>>>
>>>> Cc'ing stable as this is a regression introduced in 2.7. It is also present
>>>> in Michael's stable-2.6-staging branch.
>>>>
>>>>  hw/9pfs/9p.c |    5 +++--
>>>>  1 file changed, 3 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
>>>> index dfe293d11d1c..91a497079acb 100644
>>>> --- a/hw/9pfs/9p.c
>>>> +++ b/hw/9pfs/9p.c
>>>> @@ -1320,13 +1320,14 @@ static void v9fs_walk(void *opaque)
>>>>          goto out_nofid;
>>>>      }
>>>>  
>>>> +    v9fs_path_init(&dpath);
>>>> +    v9fs_path_init(&path);
>>>> +
>>>>      err = fid_to_qid(pdu, fidp, &qid);
>>>>      if (err < 0) {
>>>>          goto out;
>>>>      }
>>>>  
>>>> -    v9fs_path_init(&dpath);
>>>> -    v9fs_path_init(&path);
>>>>      /*
>>>>       * Both dpath and path initially poin to fidp.
>>>>       * Needed to handle request with nwnames == 0
>>>>  
>>>
>>>   
>>
>>
>> There is still a possible segv I think, in out_nofid :
>>
>>     if (nwnames && nwnames <= P9_MAXWELEM) {
>>         for (name_idx = 0; name_idx < nwnames; name_idx++) {
>>             v9fs_string_free(&wnames[name_idx]);
>>         
>> &wnames[name_idx] could NULL if pdu_unmarshal() fails.
>>
> 
> We're safe because wnames[] is fully allocated and zeroed:

ah yes. I got confused by the structures.

Reviewed-by: Cédric Le Goater <clg@kaod.org>

C.


>     if (nwnames && nwnames <= P9_MAXWELEM) {
>         wnames = g_malloc0(sizeof(wnames[0]) * nwnames); <--- here
>         qids   = g_malloc0(sizeof(qids[0]) * nwnames);
>         for (i = 0; i < nwnames; i++) {
>             err = pdu_unmarshal(pdu, offset, "s", &wnames[i]);
>             if (err < 0) {
>                 goto out_nofid;
>             }
> 
> But I agree that the calls to v9fs_string_free() without the corresponding
> calls to v9fs_string_init(), as it is done everywhere else, is disturbing
> and should be addressed.
> 
> Thanks.
> 
> --
> Greg
> 
>>
>>
>> C.
>>
>>
>>
>>
>
diff mbox

Patch

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index dfe293d11d1c..91a497079acb 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1320,13 +1320,14 @@  static void v9fs_walk(void *opaque)
         goto out_nofid;
     }
 
+    v9fs_path_init(&dpath);
+    v9fs_path_init(&path);
+
     err = fid_to_qid(pdu, fidp, &qid);
     if (err < 0) {
         goto out;
     }
 
-    v9fs_path_init(&dpath);
-    v9fs_path_init(&path);
     /*
      * Both dpath and path initially poin to fidp.
      * Needed to handle request with nwnames == 0