diff options
| author | Jeff Layton <jlayton@redhat.com> | 2011-01-20 13:36:51 -0500 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2011-01-20 16:47:57 -0500 |
| commit | ba2dbf30df210b519bdd8d34ac2ecaaeeef34c44 (patch) | |
| tree | 6272ffcad087a8bcda2a00a061094f32a175aab4 | |
| parent | 26ec254869c0158ea8db6de83b7644e2d93cac2a (diff) | |
cifs: clean up unaligned accesses in cifs_unicode.c
Make sure we use get/put_unaligned routines when accessing wide
character strings.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: Pavel Shilovsky <piastryyy@gmail.com>
Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
| -rw-r--r-- | fs/cifs/cifs_unicode.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 430f510a1720..5f6e71857be6 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
| @@ -44,10 +44,14 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
| 44 | int charlen, outlen = 0; | 44 | int charlen, outlen = 0; |
| 45 | int maxwords = maxbytes / 2; | 45 | int maxwords = maxbytes / 2; |
| 46 | char tmp[NLS_MAX_CHARSET_SIZE]; | 46 | char tmp[NLS_MAX_CHARSET_SIZE]; |
| 47 | __u16 ftmp; | ||
| 47 | 48 | ||
| 48 | for (i = 0; i < maxwords && from[i]; i++) { | 49 | for (i = 0; i < maxwords; i++) { |
| 49 | charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, | 50 | ftmp = get_unaligned_le16(&from[i]); |
| 50 | NLS_MAX_CHARSET_SIZE); | 51 | if (ftmp == 0) |
| 52 | break; | ||
| 53 | |||
| 54 | charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE); | ||
| 51 | if (charlen > 0) | 55 | if (charlen > 0) |
| 52 | outlen += charlen; | 56 | outlen += charlen; |
| 53 | else | 57 | else |
| @@ -58,9 +62,9 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | /* | 64 | /* |
| 61 | * cifs_mapchar - convert a little-endian char to proper char in codepage | 65 | * cifs_mapchar - convert a host-endian char to proper char in codepage |
| 62 | * @target - where converted character should be copied | 66 | * @target - where converted character should be copied |
| 63 | * @src_char - 2 byte little-endian source character | 67 | * @src_char - 2 byte host-endian source character |
| 64 | * @cp - codepage to which character should be converted | 68 | * @cp - codepage to which character should be converted |
| 65 | * @mapchar - should character be mapped according to mapchars mount option? | 69 | * @mapchar - should character be mapped according to mapchars mount option? |
| 66 | * | 70 | * |
| @@ -69,7 +73,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
| 69 | * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). | 73 | * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). |
| 70 | */ | 74 | */ |
| 71 | static int | 75 | static int |
| 72 | cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, | 76 | cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, |
| 73 | bool mapchar) | 77 | bool mapchar) |
| 74 | { | 78 | { |
| 75 | int len = 1; | 79 | int len = 1; |
| @@ -82,7 +86,7 @@ cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, | |||
| 82 | * build_path_from_dentry are modified, as they use slash as | 86 | * build_path_from_dentry are modified, as they use slash as |
| 83 | * separator. | 87 | * separator. |
| 84 | */ | 88 | */ |
| 85 | switch (le16_to_cpu(src_char)) { | 89 | switch (src_char) { |
| 86 | case UNI_COLON: | 90 | case UNI_COLON: |
| 87 | *target = ':'; | 91 | *target = ':'; |
| 88 | break; | 92 | break; |
| @@ -109,8 +113,7 @@ out: | |||
| 109 | return len; | 113 | return len; |
| 110 | 114 | ||
| 111 | cp_convert: | 115 | cp_convert: |
| 112 | len = cp->uni2char(le16_to_cpu(src_char), target, | 116 | len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); |
| 113 | NLS_MAX_CHARSET_SIZE); | ||
| 114 | if (len <= 0) { | 117 | if (len <= 0) { |
| 115 | *target = '?'; | 118 | *target = '?'; |
| 116 | len = 1; | 119 | len = 1; |
| @@ -149,6 +152,7 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, | |||
| 149 | int nullsize = nls_nullsize(codepage); | 152 | int nullsize = nls_nullsize(codepage); |
| 150 | int fromwords = fromlen / 2; | 153 | int fromwords = fromlen / 2; |
| 151 | char tmp[NLS_MAX_CHARSET_SIZE]; | 154 | char tmp[NLS_MAX_CHARSET_SIZE]; |
| 155 | __u16 ftmp; | ||
| 152 | 156 | ||
| 153 | /* | 157 | /* |
| 154 | * because the chars can be of varying widths, we need to take care | 158 | * because the chars can be of varying widths, we need to take care |
| @@ -158,19 +162,23 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, | |||
| 158 | */ | 162 | */ |
| 159 | safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); | 163 | safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); |
| 160 | 164 | ||
| 161 | for (i = 0; i < fromwords && from[i]; i++) { | 165 | for (i = 0; i < fromwords; i++) { |
| 166 | ftmp = get_unaligned_le16(&from[i]); | ||
| 167 | if (ftmp == 0) | ||
| 168 | break; | ||
| 169 | |||
| 162 | /* | 170 | /* |
| 163 | * check to see if converting this character might make the | 171 | * check to see if converting this character might make the |
| 164 | * conversion bleed into the null terminator | 172 | * conversion bleed into the null terminator |
| 165 | */ | 173 | */ |
| 166 | if (outlen >= safelen) { | 174 | if (outlen >= safelen) { |
| 167 | charlen = cifs_mapchar(tmp, from[i], codepage, mapchar); | 175 | charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar); |
| 168 | if ((outlen + charlen) > (tolen - nullsize)) | 176 | if ((outlen + charlen) > (tolen - nullsize)) |
| 169 | break; | 177 | break; |
| 170 | } | 178 | } |
| 171 | 179 | ||
| 172 | /* put converted char into 'to' buffer */ | 180 | /* put converted char into 'to' buffer */ |
| 173 | charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar); | 181 | charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar); |
| 174 | outlen += charlen; | 182 | outlen += charlen; |
| 175 | } | 183 | } |
| 176 | 184 | ||
| @@ -193,24 +201,21 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, | |||
| 193 | { | 201 | { |
| 194 | int charlen; | 202 | int charlen; |
| 195 | int i; | 203 | int i; |
| 196 | wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */ | 204 | wchar_t wchar_to; /* needed to quiet sparse */ |
| 197 | 205 | ||
| 198 | for (i = 0; len && *from; i++, from += charlen, len -= charlen) { | 206 | for (i = 0; len && *from; i++, from += charlen, len -= charlen) { |
| 199 | 207 | charlen = codepage->char2uni(from, len, &wchar_to); | |
| 200 | /* works for 2.4.0 kernel or later */ | ||
| 201 | charlen = codepage->char2uni(from, len, &wchar_to[i]); | ||
| 202 | if (charlen < 1) { | 208 | if (charlen < 1) { |
| 203 | cERROR(1, "strtoUCS: char2uni of %d returned %d", | 209 | cERROR(1, "strtoUCS: char2uni of 0x%x returned %d", |
| 204 | (int)*from, charlen); | 210 | *from, charlen); |
| 205 | /* A question mark */ | 211 | /* A question mark */ |
| 206 | to[i] = cpu_to_le16(0x003f); | 212 | wchar_to = 0x003f; |
| 207 | charlen = 1; | 213 | charlen = 1; |
| 208 | } else | 214 | } |
| 209 | to[i] = cpu_to_le16(wchar_to[i]); | 215 | put_unaligned_le16(wchar_to, &to[i]); |
| 210 | |||
| 211 | } | 216 | } |
| 212 | 217 | ||
| 213 | to[i] = 0; | 218 | put_unaligned_le16(0, &to[i]); |
| 214 | return i; | 219 | return i; |
| 215 | } | 220 | } |
| 216 | 221 | ||
