[linux-cifs-client] [PATCH 2/2] cifs: Increase size of tmp_buf
in cifs_readdir to avoid potential overflows
Jeff Layton
jlayton at redhat.com
Tue Apr 21 08:17:51 GMT 2009
On Tue, 21 Apr 2009 04:24:43 +0200
Günter Kukkukk <linux at kukkukk.com> wrote:
> 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
Ugh. Good catch...
I probably shouldn't have tried to review that patch while heavily
jet-lagged.
Suresh, I think you need to reintroduce that UniStrnLenbytes function
here and then make cifs_strlcpy_to_host use it.
As far as the buffer size using 4 times number of wide chars:
That buffer should be sufficient for UTF-8. Are there character sets
where UCS2 chars will translate to being more than 4 bytes? If so, then
yes...we need to change it. If not, then it sounds like
NLS_MAX_CHARSET_SIZE is too big and needs to be fixed.
--
Jeff Layton <jlayton at redhat.com>
More information about the linux-cifs-client
mailing list