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>

authored by Jeff Layton and committed by Steve French ba2dbf30 26ec2548

+28 -23
+28 -23
fs/cifs/cifs_unicode.c
··· 44 int charlen, outlen = 0; 45 int maxwords = maxbytes / 2; 46 char tmp[NLS_MAX_CHARSET_SIZE]; 47 48 - for (i = 0; i < maxwords && from[i]; i++) { 49 - charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, 50 - NLS_MAX_CHARSET_SIZE); 51 if (charlen > 0) 52 outlen += charlen; 53 else ··· 62 } 63 64 /* 65 - * cifs_mapchar - convert a little-endian char to proper char in codepage 66 * @target - where converted character should be copied 67 - * @src_char - 2 byte little-endian source character 68 * @cp - codepage to which character should be converted 69 * @mapchar - should character be mapped according to mapchars mount option? 70 * ··· 73 * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). 74 */ 75 static int 76 - cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, 77 bool mapchar) 78 { 79 int len = 1; ··· 86 * build_path_from_dentry are modified, as they use slash as 87 * separator. 88 */ 89 - switch (le16_to_cpu(src_char)) { 90 case UNI_COLON: 91 *target = ':'; 92 break; ··· 113 return len; 114 115 cp_convert: 116 - len = cp->uni2char(le16_to_cpu(src_char), target, 117 - NLS_MAX_CHARSET_SIZE); 118 if (len <= 0) { 119 *target = '?'; 120 len = 1; ··· 152 int nullsize = nls_nullsize(codepage); 153 int fromwords = fromlen / 2; 154 char tmp[NLS_MAX_CHARSET_SIZE]; 155 156 /* 157 * because the chars can be of varying widths, we need to take care ··· 162 */ 163 safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); 164 165 - for (i = 0; i < fromwords && from[i]; i++) { 166 /* 167 * check to see if converting this character might make the 168 * conversion bleed into the null terminator 169 */ 170 if (outlen >= safelen) { 171 - charlen = cifs_mapchar(tmp, from[i], codepage, mapchar); 172 if ((outlen + charlen) > (tolen - nullsize)) 173 break; 174 } 175 176 /* put converted char into 'to' buffer */ 177 - charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar); 178 outlen += charlen; 179 } 180 ··· 201 { 202 int charlen; 203 int i; 204 - wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */ 205 206 for (i = 0; len && *from; i++, from += charlen, len -= charlen) { 207 - 208 - /* works for 2.4.0 kernel or later */ 209 - charlen = codepage->char2uni(from, len, &wchar_to[i]); 210 if (charlen < 1) { 211 - cERROR(1, "strtoUCS: char2uni of %d returned %d", 212 - (int)*from, charlen); 213 /* A question mark */ 214 - to[i] = cpu_to_le16(0x003f); 215 charlen = 1; 216 - } else 217 - to[i] = cpu_to_le16(wchar_to[i]); 218 - 219 } 220 221 - to[i] = 0; 222 return i; 223 } 224
··· 44 int charlen, outlen = 0; 45 int maxwords = maxbytes / 2; 46 char tmp[NLS_MAX_CHARSET_SIZE]; 47 + __u16 ftmp; 48 49 + for (i = 0; i < maxwords; i++) { 50 + ftmp = get_unaligned_le16(&from[i]); 51 + if (ftmp == 0) 52 + break; 53 + 54 + charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE); 55 if (charlen > 0) 56 outlen += charlen; 57 else ··· 58 } 59 60 /* 61 + * cifs_mapchar - convert a host-endian char to proper char in codepage 62 * @target - where converted character should be copied 63 + * @src_char - 2 byte host-endian source character 64 * @cp - codepage to which character should be converted 65 * @mapchar - should character be mapped according to mapchars mount option? 66 * ··· 69 * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). 70 */ 71 static int 72 + cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, 73 bool mapchar) 74 { 75 int len = 1; ··· 82 * build_path_from_dentry are modified, as they use slash as 83 * separator. 84 */ 85 + switch (src_char) { 86 case UNI_COLON: 87 *target = ':'; 88 break; ··· 109 return len; 110 111 cp_convert: 112 + len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); 113 if (len <= 0) { 114 *target = '?'; 115 len = 1; ··· 149 int nullsize = nls_nullsize(codepage); 150 int fromwords = fromlen / 2; 151 char tmp[NLS_MAX_CHARSET_SIZE]; 152 + __u16 ftmp; 153 154 /* 155 * because the chars can be of varying widths, we need to take care ··· 158 */ 159 safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); 160 161 + for (i = 0; i < fromwords; i++) { 162 + ftmp = get_unaligned_le16(&from[i]); 163 + if (ftmp == 0) 164 + break; 165 + 166 /* 167 * check to see if converting this character might make the 168 * conversion bleed into the null terminator 169 */ 170 if (outlen >= safelen) { 171 + charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar); 172 if ((outlen + charlen) > (tolen - nullsize)) 173 break; 174 } 175 176 /* put converted char into 'to' buffer */ 177 + charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar); 178 outlen += charlen; 179 } 180 ··· 193 { 194 int charlen; 195 int i; 196 + wchar_t wchar_to; /* needed to quiet sparse */ 197 198 for (i = 0; len && *from; i++, from += charlen, len -= charlen) { 199 + charlen = codepage->char2uni(from, len, &wchar_to); 200 if (charlen < 1) { 201 + cERROR(1, "strtoUCS: char2uni of 0x%x returned %d", 202 + *from, charlen); 203 /* A question mark */ 204 + wchar_to = 0x003f; 205 charlen = 1; 206 + } 207 + put_unaligned_le16(wchar_to, &to[i]); 208 } 209 210 + put_unaligned_le16(0, &to[i]); 211 return i; 212 } 213