[linux-cifs-client] Re: [PATCH] cifs: fix unicode string area word
alignment in session setup
Steve French
smfrench at gmail.com
Wed Apr 15 21:46:48 GMT 2009
merged into cifs-2.6.git
On Tue, Apr 14, 2009 at 10:00 AM, Jeff Layton <jlayton at redhat.com> wrote:
> The handling of unicode string area alignment is wrong.
> decode_unicode_ssetup improperly assumes that it will always be preceded
> by a pad byte. This isn't the case if the string area is already
> word-aligned.
>
> This problem, combined with the bad buffer sizing for the serverDomain
> string can cause memory corruption. The bad alignment can make it so
> that the alignment of the characters is off. This can make them
> translate to characters that are greater than 2 bytes each. If this
> happens we can overflow the allocation.
>
> Fix this by fixing the alignment in CIFS_SessSetup instead so we can
> verify it against the head of the response. Also, clean up the
> workaround for improperly terminated strings by checking for a
> odd-length unicode buffers and then forcibly terminating them.
>
> Finally, resize the buffer for serverDomain. Now that we've fixed
> the alignment, it's probably fine, but a malicious server could
> overflow it.
>
> A better solution for handling these strings is still needed, but
> this should be a suitable bandaid.
>
> Signed-off-by: Jeff Layton <jlayton at redhat.com>
> ---
> fs/cifs/sess.c | 44 +++++++++++++++++++++++---------------------
> 1 files changed, 23 insertions(+), 21 deletions(-)
>
> diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
> index 5c68b42..70d04d0 100644
> --- a/fs/cifs/sess.c
> +++ b/fs/cifs/sess.c
> @@ -285,27 +285,26 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
> int words_left, len;
> char *data = *pbcc_area;
>
> -
> -
> cFYI(1, ("bleft %d", bleft));
>
> -
> - /* SMB header is unaligned, so cifs servers word align start of
> - Unicode strings */
> - data++;
> - bleft--; /* Windows servers do not always double null terminate
> - their final Unicode string - in which case we
> - now will not attempt to decode the byte of junk
> - which follows it */
> + /*
> + * Windows servers do not always double null terminate their final
> + * Unicode string. Check to see if there are an uneven number of bytes
> + * left. If so, then add an extra NULL pad byte to the end of the
> + * response.
> + *
> + * See section 2.7.2 in "Implementing CIFS" for details
> + */
> + if (bleft % 2) {
> + data[bleft] = 0;
> + ++bleft;
> + }
>
> words_left = bleft / 2;
>
> /* save off server operating system */
> len = UniStrnlen((wchar_t *) data, words_left);
>
> -/* We look for obvious messed up bcc or strings in response so we do not go off
> - the end since (at least) WIN2K and Windows XP have a major bug in not null
> - terminating last Unicode string in response */
> if (len >= words_left)
> return rc;
>
> @@ -343,13 +342,10 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
> return rc;
>
> kfree(ses->serverDomain);
> - ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
> - if (ses->serverDomain != NULL) {
> + ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL);
> + if (ses->serverDomain != NULL)
> cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
> nls_cp);
> - ses->serverDomain[2*len] = 0;
> - ses->serverDomain[(2*len) + 1] = 0;
> - }
> data += 2 * (len + 1);
> words_left -= len + 1;
>
> @@ -702,12 +698,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
> }
>
> /* BB check if Unicode and decode strings */
> - if (smb_buf->Flags2 & SMBFLG2_UNICODE)
> + if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
> + /* unicode string area must be word-aligned */
> + if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
> + ++bcc_ptr;
> + --bytes_remaining;
> + }
> rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
> - ses, nls_cp);
> - else
> + ses, nls_cp);
> + } else {
> rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
> ses, nls_cp);
> + }
>
> ssetup_exit:
> if (spnego_key) {
> --
> 1.6.0.6
>
>
--
Thanks,
Steve
More information about the linux-cifs-client
mailing list