diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 8ce6e4458cc25..7b80c34e841db 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -2961,8 +2961,15 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) } /* copy the name of head/only segment */ - outlen = jfs_strfromUCS_le(name_ptr, d->name, len, - codepage); + outlen = jfs_strfromUCS_le(name_ptr, + (char *)dirent_buf + + PAGE_SIZE - name_ptr, + d->name, len, codepage); + if (outlen < 0) { + index = i; + overflow = 1; + break; + } jfs_dirent->name_len = outlen; /* copy name in the additional segment(s) */ @@ -2981,12 +2988,21 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) goto skip_one; } len = min(d_namleft, DTSLOTDATALEN); - outlen = jfs_strfromUCS_le(name_ptr, t->name, - len, codepage); + outlen = jfs_strfromUCS_le(name_ptr, + (char *)dirent_buf + + PAGE_SIZE - name_ptr, + t->name, len, codepage); + if (outlen < 0) { + index = i; + overflow = 1; + break; + } jfs_dirent->name_len += outlen; next = t->next; } + if (overflow == 1) + break; jfs_dirents++; jfs_dirent = next_jfs_dirent(jfs_dirent); diff --git a/fs/jfs/jfs_unicode.c b/fs/jfs/jfs_unicode.c index 0c1e9027245a6..f73c718c5dd03 100644 --- a/fs/jfs/jfs_unicode.c +++ b/fs/jfs/jfs_unicode.c @@ -16,17 +16,25 @@ * FUNCTION: Convert little-endian unicode string to character string * */ -int jfs_strfromUCS_le(char *to, const __le16 * from, +int jfs_strfromUCS_le(char *to, int to_size, const __le16 *from, int len, struct nls_table *codepage) { - int i; + int i, remaining_size; int outlen = 0; static int warn_again = 5; /* Only warn up to 5 times total */ int warn = !!warn_again; /* once per string */ + if (to_size <= 0) + return -ENAMETOOLONG; + if (codepage) { for (i = 0; (i < len) && from[i]; i++) { int charlen; + + remaining_size = to_size - outlen - 1; + if (remaining_size < NLS_MAX_CHARSET_SIZE) + return -ENAMETOOLONG; + charlen = codepage->uni2char(le16_to_cpu(from[i]), &to[outlen], @@ -38,6 +46,8 @@ int jfs_strfromUCS_le(char *to, const __le16 * from, } } else { for (i = 0; (i < len) && from[i]; i++) { + if (i >= to_size - 1) + return -ENAMETOOLONG; if (unlikely(le16_to_cpu(from[i]) & 0xff00)) { to[i] = '?'; if (unlikely(warn)) { diff --git a/fs/jfs/jfs_unicode.h b/fs/jfs/jfs_unicode.h index b6a78d4aef1b0..ea03dd5a0e0cb 100644 --- a/fs/jfs/jfs_unicode.h +++ b/fs/jfs/jfs_unicode.h @@ -12,7 +12,7 @@ #include "jfs_types.h" extern int get_UCSname(struct component_name *, struct dentry *); -extern int jfs_strfromUCS_le(char *, const __le16 *, int, struct nls_table *); +extern int jfs_strfromUCS_le(char *, int, const __le16 *, int, struct nls_table *); #define free_UCSname(COMP) kfree((COMP)->name)