diff mbox

cifs: fix cifsConvertToUCS() for the mapchars case

Message ID 20110513201705.7fe75309@tlielax.poochiereds.net (mailing list archive)
State New, archived
Headers show

Commit Message

Jeff Layton May 14, 2011, 12:17 a.m. UTC
On Fri, 13 May 2011 05:32:35 +0200
Stefan Metzmacher <metze@samba.org> wrote:

> Commit "cifs: fix unaligned accesses in cifsConvertToUCS"
> (84cdf74e8096a10dd6acbb870dd404b92f07a756) does multiple steps
> in just one commit (moving the function and changing it without testing).
> 
> put_unaligned_le16(temp, &target[j]); is never called for any codepoint
> the goes via the 'default' switch statement. As a result we put
> just zero (or maybe uninitialized) bytes into the target buffer,
> 
> Signed-off-by: Stefan Metzmacher <metze@samba.org>
> ---
>  fs/cifs/cifs_unicode.c |   20 ++++++++++----------
>  1 files changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
> index fc0fd4f..b1ff0bd 100644
> --- a/fs/cifs/cifs_unicode.c
> +++ b/fs/cifs/cifs_unicode.c
> @@ -276,6 +276,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
>  		return cifs_strtoUCS(target, source, PATH_MAX, cp);
>  
>  	for (i = 0, j = 0; i < maxlen; j++) {
> +		charlen = 1;
>  		src_char = source[i];
>  		switch (src_char) {
>  		case 0:
> @@ -315,18 +316,17 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
>  				temp = 0x003f;
>  				charlen = 1;
>  			}
> -			len_remaining -= charlen;
> -			/*
> -			 * character may take more than one byte in the source
> -			 * string, but will take exactly two bytes in the
> -			 * target string
> -			 */
> -			i += charlen;
> -			continue;
> +			break;
>  		}
> +		/*
> +		 * character may take more than one byte in the source
> +		 * string, but will take exactly two bytes in the
> +		 * target string
> +		 */
>  		put_unaligned_le16(temp, &target[j]);
> -		i++; /* move to next char in source string */
> -		len_remaining--;
> +		/* move to next char in source string */
> +		i += charlen;
> +		len_remaining -= charlen;
>  	}
>  
>  ctoUCS_out:

Oof. Yeah, I broke it alright -- good catch...

This patch probably won't apply to the current head of the tree,
however. Rather than have a special patch for 2.6.38 and .39, what may
be best is to go ahead and push 581ade4d in Steve's master branch to
stable, and then apply something like this untested patch on top of it.

I'll plan to test it out when I get a chance, but I think that's
probably the best approach.

Thoughts?

-----------------[snip]--------------------

cifs: fix cifsConvertToUCS() for the mapchars case

As Metze pointed out, commit 84cdf74e broke mapchars case:

    Commit "cifs: fix unaligned accesses in cifsConvertToUCS"
    (84cdf74e8096a10dd6acbb870dd404b92f07a756) does multiple steps
    in just one commit (moving the function and changing it without
    testing).

    put_unaligned_le16(temp, &target[j]); is never called for any
    codepoint the goes via the 'default' switch statement. As a result
    we put just zero (or maybe uninitialized) bytes into the target
    buffer.

His proposed patch looks correct, but doesn't apply to the current head
of the tree. This patch should also fix it.

Reported-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/cifs/cifs_unicode.c |   14 ++++++--------
 1 files changed, 6 insertions(+), 8 deletions(-)

Comments

Steve French May 16, 2011, 1:38 a.m. UTC | #1
Probably too late for 2.6.39 for a patch to a non-default mount option
(but I agree that it should go to stable).  Thoughts?

Jeff's suggestion below makes sense.

On Fri, May 13, 2011 at 7:17 PM, Jeff Layton <jlayton@redhat.com> wrote:
> On Fri, 13 May 2011 05:32:35 +0200
> Stefan Metzmacher <metze@samba.org> wrote:
>
>> Commit "cifs: fix unaligned accesses in cifsConvertToUCS"
>> (84cdf74e8096a10dd6acbb870dd404b92f07a756) does multiple steps
>> in just one commit (moving the function and changing it without testing).
>>
>> put_unaligned_le16(temp, &target[j]); is never called for any codepoint
>> the goes via the 'default' switch statement. As a result we put
>> just zero (or maybe uninitialized) bytes into the target buffer,
>>
>> Signed-off-by: Stefan Metzmacher <metze@samba.org>
>> ---
>>  fs/cifs/cifs_unicode.c |   20 ++++++++++----------
>>  1 files changed, 10 insertions(+), 10 deletions(-)
>>
>> diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
>> index fc0fd4f..b1ff0bd 100644
>> --- a/fs/cifs/cifs_unicode.c
>> +++ b/fs/cifs/cifs_unicode.c
>> @@ -276,6 +276,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
>>               return cifs_strtoUCS(target, source, PATH_MAX, cp);
>>
>>       for (i = 0, j = 0; i < maxlen; j++) {
>> +             charlen = 1;
>>               src_char = source[i];
>>               switch (src_char) {
>>               case 0:
>> @@ -315,18 +316,17 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
>>                               temp = 0x003f;
>>                               charlen = 1;
>>                       }
>> -                     len_remaining -= charlen;
>> -                     /*
>> -                      * character may take more than one byte in the source
>> -                      * string, but will take exactly two bytes in the
>> -                      * target string
>> -                      */
>> -                     i += charlen;
>> -                     continue;
>> +                     break;
>>               }
>> +             /*
>> +              * character may take more than one byte in the source
>> +              * string, but will take exactly two bytes in the
>> +              * target string
>> +              */
>>               put_unaligned_le16(temp, &target[j]);
>> -             i++; /* move to next char in source string */
>> -             len_remaining--;
>> +             /* move to next char in source string */
>> +             i += charlen;
>> +             len_remaining -= charlen;
>>       }
>>
>>  ctoUCS_out:
>
> Oof. Yeah, I broke it alright -- good catch...
>
> This patch probably won't apply to the current head of the tree,
> however. Rather than have a special patch for 2.6.38 and .39, what may
> be best is to go ahead and push 581ade4d in Steve's master branch to
> stable, and then apply something like this untested patch on top of it.
>
> I'll plan to test it out when I get a chance, but I think that's
> probably the best approach.
>
> Thoughts?
>
> -----------------[snip]--------------------
>
> cifs: fix cifsConvertToUCS() for the mapchars case
>
> As Metze pointed out, commit 84cdf74e broke mapchars case:
>
>    Commit "cifs: fix unaligned accesses in cifsConvertToUCS"
>    (84cdf74e8096a10dd6acbb870dd404b92f07a756) does multiple steps
>    in just one commit (moving the function and changing it without
>    testing).
>
>    put_unaligned_le16(temp, &target[j]); is never called for any
>    codepoint the goes via the 'default' switch statement. As a result
>    we put just zero (or maybe uninitialized) bytes into the target
>    buffer.
>
> His proposed patch looks correct, but doesn't apply to the current head
> of the tree. This patch should also fix it.
>
> Reported-by: Stefan Metzmacher <metze@samba.org>
> Signed-off-by: Jeff Layton <jlayton@redhat.com>
> ---
>  fs/cifs/cifs_unicode.c |   14 ++++++--------
>  1 files changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
> index 23d43cd..1b2e180 100644
> --- a/fs/cifs/cifs_unicode.c
> +++ b/fs/cifs/cifs_unicode.c
> @@ -277,6 +277,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
>
>        for (i = 0, j = 0; i < srclen; j++) {
>                src_char = source[i];
> +               charlen = 1;
>                switch (src_char) {
>                case 0:
>                        put_unaligned(0, &target[j]);
> @@ -316,16 +317,13 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
>                                dst_char = cpu_to_le16(0x003f);
>                                charlen = 1;
>                        }
> -                       /*
> -                        * character may take more than one byte in the source
> -                        * string, but will take exactly two bytes in the
> -                        * target string
> -                        */
> -                       i += charlen;
> -                       continue;
>                }
> +               /*
> +                * character may take more than one byte in the source string,
> +                * but will take exactly two bytes in the target string
> +                */
> +               i += charlen;
>                put_unaligned(dst_char, &target[j]);
> -               i++; /* move to next char in source string */
>        }
>
>  ctoUCS_out:
> --
> 1.7.4.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
Jeff Layton May 16, 2011, 10:49 a.m. UTC | #2
On Sun, 15 May 2011 20:38:24 -0500
Steve French <smfrench@gmail.com> wrote:

> Probably too late for 2.6.39 for a patch to a non-default mount option
> (but I agree that it should go to stable).  Thoughts?
> 

You're proposing to fix it in 2.6.38-stable, but leave it broken in
2.6.39? That doesn't make much sense to me...

> Jeff's suggestion below makes sense.
> 
> On Fri, May 13, 2011 at 7:17 PM, Jeff Layton <jlayton@redhat.com> wrote:
> > On Fri, 13 May 2011 05:32:35 +0200
> > Stefan Metzmacher <metze@samba.org> wrote:
> >
> >> Commit "cifs: fix unaligned accesses in cifsConvertToUCS"
> >> (84cdf74e8096a10dd6acbb870dd404b92f07a756) does multiple steps
> >> in just one commit (moving the function and changing it without testing).
> >>
> >> put_unaligned_le16(temp, &target[j]); is never called for any codepoint
> >> the goes via the 'default' switch statement. As a result we put
> >> just zero (or maybe uninitialized) bytes into the target buffer,
> >>
> >> Signed-off-by: Stefan Metzmacher <metze@samba.org>
> >> ---
> >>  fs/cifs/cifs_unicode.c |   20 ++++++++++----------
> >>  1 files changed, 10 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
> >> index fc0fd4f..b1ff0bd 100644
> >> --- a/fs/cifs/cifs_unicode.c
> >> +++ b/fs/cifs/cifs_unicode.c
> >> @@ -276,6 +276,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
> >>               return cifs_strtoUCS(target, source, PATH_MAX, cp);
> >>
> >>       for (i = 0, j = 0; i < maxlen; j++) {
> >> +             charlen = 1;
> >>               src_char = source[i];
> >>               switch (src_char) {
> >>               case 0:
> >> @@ -315,18 +316,17 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
> >>                               temp = 0x003f;
> >>                               charlen = 1;
> >>                       }
> >> -                     len_remaining -= charlen;
> >> -                     /*
> >> -                      * character may take more than one byte in the source
> >> -                      * string, but will take exactly two bytes in the
> >> -                      * target string
> >> -                      */
> >> -                     i += charlen;
> >> -                     continue;
> >> +                     break;
> >>               }
> >> +             /*
> >> +              * character may take more than one byte in the source
> >> +              * string, but will take exactly two bytes in the
> >> +              * target string
> >> +              */
> >>               put_unaligned_le16(temp, &target[j]);
> >> -             i++; /* move to next char in source string */
> >> -             len_remaining--;
> >> +             /* move to next char in source string */
> >> +             i += charlen;
> >> +             len_remaining -= charlen;
> >>       }
> >>
> >>  ctoUCS_out:
> >
> > Oof. Yeah, I broke it alright -- good catch...
> >
> > This patch probably won't apply to the current head of the tree,
> > however. Rather than have a special patch for 2.6.38 and .39, what may
> > be best is to go ahead and push 581ade4d in Steve's master branch to
> > stable, and then apply something like this untested patch on top of it.
> >
> > I'll plan to test it out when I get a chance, but I think that's
> > probably the best approach.
> >
> > Thoughts?
> >
> > -----------------[snip]--------------------
> >
> > cifs: fix cifsConvertToUCS() for the mapchars case
> >
> > As Metze pointed out, commit 84cdf74e broke mapchars case:
> >
> >    Commit "cifs: fix unaligned accesses in cifsConvertToUCS"
> >    (84cdf74e8096a10dd6acbb870dd404b92f07a756) does multiple steps
> >    in just one commit (moving the function and changing it without
> >    testing).
> >
> >    put_unaligned_le16(temp, &target[j]); is never called for any
> >    codepoint the goes via the 'default' switch statement. As a result
> >    we put just zero (or maybe uninitialized) bytes into the target
> >    buffer.
> >
> > His proposed patch looks correct, but doesn't apply to the current head
> > of the tree. This patch should also fix it.
> >
> > Reported-by: Stefan Metzmacher <metze@samba.org>
> > Signed-off-by: Jeff Layton <jlayton@redhat.com>
> > ---
> >  fs/cifs/cifs_unicode.c |   14 ++++++--------
> >  1 files changed, 6 insertions(+), 8 deletions(-)
> >
> > diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
> > index 23d43cd..1b2e180 100644
> > --- a/fs/cifs/cifs_unicode.c
> > +++ b/fs/cifs/cifs_unicode.c
> > @@ -277,6 +277,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
> >
> >        for (i = 0, j = 0; i < srclen; j++) {
> >                src_char = source[i];
> > +               charlen = 1;
> >                switch (src_char) {
> >                case 0:
> >                        put_unaligned(0, &target[j]);
> > @@ -316,16 +317,13 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
> >                                dst_char = cpu_to_le16(0x003f);
> >                                charlen = 1;
> >                        }
> > -                       /*
> > -                        * character may take more than one byte in the source
> > -                        * string, but will take exactly two bytes in the
> > -                        * target string
> > -                        */
> > -                       i += charlen;
> > -                       continue;
> >                }
> > +               /*
> > +                * character may take more than one byte in the source string,
> > +                * but will take exactly two bytes in the target string
> > +                */
> > +               i += charlen;
> >                put_unaligned(dst_char, &target[j]);
> > -               i++; /* move to next char in source string */
> >        }
> >
> >  ctoUCS_out:
> > --
> > 1.7.4.4
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
> 
> 
>
diff mbox

Patch

diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 23d43cd..1b2e180 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -277,6 +277,7 @@  cifsConvertToUCS(__le16 *target, const char *source, int srclen,
 
 	for (i = 0, j = 0; i < srclen; j++) {
 		src_char = source[i];
+		charlen = 1;
 		switch (src_char) {
 		case 0:
 			put_unaligned(0, &target[j]);
@@ -316,16 +317,13 @@  cifsConvertToUCS(__le16 *target, const char *source, int srclen,
 				dst_char = cpu_to_le16(0x003f);
 				charlen = 1;
 			}
-			/*
-			 * character may take more than one byte in the source
-			 * string, but will take exactly two bytes in the
-			 * target string
-			 */
-			i += charlen;
-			continue;
 		}
+		/*
+		 * character may take more than one byte in the source string,
+		 * but will take exactly two bytes in the target string
+		 */
+		i += charlen;
 		put_unaligned(dst_char, &target[j]);
-		i++; /* move to next char in source string */
 	}
 
 ctoUCS_out: