cifs: fix unaligned accesses in cifsConvertToUCS
Move cifsConvertToUCS to cifs_unicode.c where all of the other unicode related functions live. Have it store mapped characters in 'temp' and then use put_unaligned_le16 to copy it to the target buffer. Also fix the comments to match kernel coding style. 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>
This commit is contained in:
		
					parent
					
						
							
								ba2dbf30df
							
						
					
				
			
			
				commit
				
					
						84cdf74e80
					
				
			
		
					 2 changed files with 76 additions and 71 deletions
				
			
		| 
						 | 
					@ -257,3 +257,79 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
 | 
				
			||||||
	return dst;
 | 
						return dst;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Convert 16 bit Unicode pathname to wire format from string in current code
 | 
				
			||||||
 | 
					 * page. Conversion may involve remapping up the six characters that are
 | 
				
			||||||
 | 
					 * only legal in POSIX-like OS (if they are present in the string). Path
 | 
				
			||||||
 | 
					 * names are little endian 16 bit Unicode on the wire
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
 | 
				
			||||||
 | 
							 const struct nls_table *cp, int mapChars)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, j, charlen;
 | 
				
			||||||
 | 
						int len_remaining = maxlen;
 | 
				
			||||||
 | 
						char src_char;
 | 
				
			||||||
 | 
						__u16 temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mapChars)
 | 
				
			||||||
 | 
							return cifs_strtoUCS(target, source, PATH_MAX, cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0, j = 0; i < maxlen; j++) {
 | 
				
			||||||
 | 
							src_char = source[i];
 | 
				
			||||||
 | 
							switch (src_char) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								put_unaligned_le16(0, &target[j]);
 | 
				
			||||||
 | 
								goto ctoUCS_out;
 | 
				
			||||||
 | 
							case ':':
 | 
				
			||||||
 | 
								temp = UNI_COLON;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '*':
 | 
				
			||||||
 | 
								temp = UNI_ASTERIK;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '?':
 | 
				
			||||||
 | 
								temp = UNI_QUESTION;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '<':
 | 
				
			||||||
 | 
								temp = UNI_LESSTHAN;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '>':
 | 
				
			||||||
 | 
								temp = UNI_GRTRTHAN;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '|':
 | 
				
			||||||
 | 
								temp = UNI_PIPE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * FIXME: We can not handle remapping backslash (UNI_SLASH)
 | 
				
			||||||
 | 
							 * until all the calls to build_path_from_dentry are modified,
 | 
				
			||||||
 | 
							 * as they use backslash as separator.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								charlen = cp->char2uni(source+i, len_remaining,
 | 
				
			||||||
 | 
											&temp);
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * if no match, use question mark, which at least in
 | 
				
			||||||
 | 
								 * some cases serves as wild card
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (charlen < 1) {
 | 
				
			||||||
 | 
									temp = 0x003f;
 | 
				
			||||||
 | 
									charlen = 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								len_remaining -= charlen;
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * character may take more than one byte in the source
 | 
				
			||||||
 | 
								 * string, but will take exactly two bytes in the
 | 
				
			||||||
 | 
								 * target string
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								i += charlen;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							put_unaligned_le16(temp, &target[j]);
 | 
				
			||||||
 | 
							i++; /* move to next char in source string */
 | 
				
			||||||
 | 
							len_remaining--;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ctoUCS_out:
 | 
				
			||||||
 | 
						return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -637,77 +637,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Convert 16 bit Unicode pathname to wire format from string in current code
 | 
					 | 
				
			||||||
   page.  Conversion may involve remapping up the seven characters that are
 | 
					 | 
				
			||||||
   only legal in POSIX-like OS (if they are present in the string). Path
 | 
					 | 
				
			||||||
   names are little endian 16 bit Unicode on the wire */
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
 | 
					 | 
				
			||||||
		 const struct nls_table *cp, int mapChars)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int i, j, charlen;
 | 
					 | 
				
			||||||
	int len_remaining = maxlen;
 | 
					 | 
				
			||||||
	char src_char;
 | 
					 | 
				
			||||||
	__u16 temp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!mapChars)
 | 
					 | 
				
			||||||
		return cifs_strtoUCS(target, source, PATH_MAX, cp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0, j = 0; i < maxlen; j++) {
 | 
					 | 
				
			||||||
		src_char = source[i];
 | 
					 | 
				
			||||||
		switch (src_char) {
 | 
					 | 
				
			||||||
			case 0:
 | 
					 | 
				
			||||||
				target[j] = 0;
 | 
					 | 
				
			||||||
				goto ctoUCS_out;
 | 
					 | 
				
			||||||
			case ':':
 | 
					 | 
				
			||||||
				target[j] = cpu_to_le16(UNI_COLON);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case '*':
 | 
					 | 
				
			||||||
				target[j] = cpu_to_le16(UNI_ASTERIK);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case '?':
 | 
					 | 
				
			||||||
				target[j] = cpu_to_le16(UNI_QUESTION);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case '<':
 | 
					 | 
				
			||||||
				target[j] = cpu_to_le16(UNI_LESSTHAN);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case '>':
 | 
					 | 
				
			||||||
				target[j] = cpu_to_le16(UNI_GRTRTHAN);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case '|':
 | 
					 | 
				
			||||||
				target[j] = cpu_to_le16(UNI_PIPE);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			/* BB We can not handle remapping slash until
 | 
					 | 
				
			||||||
			   all the calls to build_path_from_dentry
 | 
					 | 
				
			||||||
			   are modified, as they use slash as separator BB */
 | 
					 | 
				
			||||||
			/* case '\\':
 | 
					 | 
				
			||||||
				target[j] = cpu_to_le16(UNI_SLASH);
 | 
					 | 
				
			||||||
				break;*/
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				charlen = cp->char2uni(source+i,
 | 
					 | 
				
			||||||
					len_remaining, &temp);
 | 
					 | 
				
			||||||
				/* if no match, use question mark, which
 | 
					 | 
				
			||||||
				at least in some cases servers as wild card */
 | 
					 | 
				
			||||||
				if (charlen < 1) {
 | 
					 | 
				
			||||||
					target[j] = cpu_to_le16(0x003f);
 | 
					 | 
				
			||||||
					charlen = 1;
 | 
					 | 
				
			||||||
				} else
 | 
					 | 
				
			||||||
					target[j] = cpu_to_le16(temp);
 | 
					 | 
				
			||||||
				len_remaining -= charlen;
 | 
					 | 
				
			||||||
				/* character may take more than one byte in the
 | 
					 | 
				
			||||||
				   the source string, but will take exactly two
 | 
					 | 
				
			||||||
				   bytes in the target string */
 | 
					 | 
				
			||||||
				i += charlen;
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		i++; /* move to next char in source string */
 | 
					 | 
				
			||||||
		len_remaining--;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ctoUCS_out:
 | 
					 | 
				
			||||||
	return i;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
 | 
					cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue