[linux-cifs-client] [PATCH 2/2] cifs: Increase size of tmp_buf in cifs_readdir to avoid potential overflows

Günter Kukkukk linux at kukkukk.com
Tue Apr 21 02:24:43 GMT 2009


Am Montag, 20. April 2009 schrieb Steve French:
> Merged this and also patch 1 of 2
> 
> thx
> 
> On Mon, Apr 20, 2009 at 10:30 AM, Jeff Layton <jlayton at redhat.com> wrote:
> > On Mon, 20 Apr 2009 18:54:36 +0530
> > Suresh Jayaraman <sjayaraman at suse.de> wrote:
> >
> >> Increase size of tmp_buf to possible maximum to avoid potential
> >> overflows.
> >>
> >>
> >> Pointed-out-by: Jeff Layton <jlayton at redhat.com>
> >> Signed-off-by: Suresh Jayaraman <sjayaraman at suse.de>
> >> ---
> >>  fs/cifs/readdir.c |    2 +-
> >>  1 files changed, 1 insertions(+), 1 deletions(-)
> >>
> >> diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
> >> index 1a8be62..ebd0da7 100644
> >> --- a/fs/cifs/readdir.c
> >> +++ b/fs/cifs/readdir.c
> >> @@ -1074,7 +1074,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
> >>               with the rare long characters alloc more to account for
> >>               such multibyte target UTF-8 characters. cifs_unicode.c,
> >>               which actually does the conversion, has the same limit */
> >> -             tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
> >> +             tmp_buf = kmalloc((4 * NAME_MAX) + 2, GFP_KERNEL);
> >>               for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
> >>                       if (current_entry == NULL) {
> >>                               /* evaluate whether this case is an error */
> >
> > Acked-by: Jeff Layton <jlayton at redhat.com>
> >
> 
> 
> 

I think patch 1 
  - cifs: Rename cifs_strncpy_to_host and fix buffer size
is wrong (which also results from using weak variables names).

               (*dst)[plen] = 0;
               (*dst)[plen+1] = 0; /* needed for Unicode */

is using _source_ "plen" length when applied to dest. string.
In addition, hardcoded (numbered) stuff like this
   *dst = kmalloc((4 * plen) + 2, GFP_KERNEL);
is also wrong.
It's based on todays (right) assumption, that an UTF-8 string
can only consume max. 4 bytes per char.

But - the maximum length is defined in:
./include/linux/nls.h:#define NLS_MAX_CHARSET_SIZE 6 /* for UTF-8 */

At least that hardcoded "4" should be carefully defined somewhere - if
ever used!

my current diff (not tested) - temporary:
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a02c43b..c9dcc1b 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -91,22 +91,25 @@ static int
 cifs_strlcpy_to_host(char **dst, const char *src, const int maxlen,
                 const bool is_unicode, const struct nls_table *nls_codepage)
 {
-       int plen;
+       int src_len, dst_len;

        if (is_unicode) {
-               plen = UniStrnlen((wchar_t *)src, maxlen);
-               *dst = kmalloc((4 * plen) + 2, GFP_KERNEL);
+               src_len = UniStrnlen((wchar_t *)src, maxlen);
+               *dst = kmalloc((NLS_MAX_CHARSET_SIZE * src_len) + 2, GFP_KERNEL);
                if (!*dst)
                        goto cifs_strlcpy_to_host_ErrExit;
-               cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
-               (*dst)[plen] = 0;
-               (*dst)[plen+1] = 0; /* needed for Unicode */
+               dst_len = cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
+               /* Note:
+                * cifs_strfromUCS_le already zero terminates the string
+                * using 1 null byte
+                */
+               (*dst)[dst_len+1] = 0; /* needed for Unicode (really?)*/
        } else {
-               plen = strnlen(src, maxlen);
-               *dst = kmalloc(plen + 2, GFP_KERNEL);
+               src_len = strnlen(src, maxlen);
+               *dst = kmalloc(src_len + 1, GFP_KERNEL);
                if (!*dst)

cheers - Günter


More information about the linux-cifs-client mailing list