aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/CHANGES6
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifssmb.c20
-rw-r--r--fs/cifs/inode.c21
-rw-r--r--fs/cifs/readdir.c2
5 files changed, 33 insertions, 18 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 9d1fb6ec8a5a..1bf818136276 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,9 @@
1Version 1.58
2------------
3Guard against buffer overruns in various UCS-2 to UTF-8 string conversions
4when the UTF-8 string is composed of unusually long (more than 4 byte) converted
5characters.
6
1Version 1.57 7Version 1.57
2------------ 8------------
3Improve support for multiple security contexts to the same server. We 9Improve support for multiple security contexts to the same server. We
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 77e190dc2883..051b71cfdea9 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
100extern const struct export_operations cifs_export_ops; 100extern const struct export_operations cifs_export_ops;
101#endif /* EXPERIMENTAL */ 101#endif /* EXPERIMENTAL */
102 102
103#define CIFS_VERSION "1.57" 103#define CIFS_VERSION "1.58"
104#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a0845dc7b8a9..a02c43b3faf5 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -88,29 +88,29 @@ static struct {
88 * on failure - errno 88 * on failure - errno
89 */ 89 */
90static int 90static int
91cifs_strncpy_to_host(char **dst, const char *src, const int maxlen, 91cifs_strlcpy_to_host(char **dst, const char *src, const int maxlen,
92 const bool is_unicode, const struct nls_table *nls_codepage) 92 const bool is_unicode, const struct nls_table *nls_codepage)
93{ 93{
94 int plen; 94 int plen;
95 95
96 if (is_unicode) { 96 if (is_unicode) {
97 plen = UniStrnlen((wchar_t *)src, maxlen); 97 plen = UniStrnlen((wchar_t *)src, maxlen);
98 *dst = kmalloc(plen + 2, GFP_KERNEL); 98 *dst = kmalloc((4 * plen) + 2, GFP_KERNEL);
99 if (!*dst) 99 if (!*dst)
100 goto cifs_strncpy_to_host_ErrExit; 100 goto cifs_strlcpy_to_host_ErrExit;
101 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage); 101 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
102 (*dst)[plen] = 0;
103 (*dst)[plen+1] = 0; /* needed for Unicode */
102 } else { 104 } else {
103 plen = strnlen(src, maxlen); 105 plen = strnlen(src, maxlen);
104 *dst = kmalloc(plen + 2, GFP_KERNEL); 106 *dst = kmalloc(plen + 2, GFP_KERNEL);
105 if (!*dst) 107 if (!*dst)
106 goto cifs_strncpy_to_host_ErrExit; 108 goto cifs_strlcpy_to_host_ErrExit;
107 strncpy(*dst, src, plen); 109 strlcpy(*dst, src, plen);
108 } 110 }
109 (*dst)[plen] = 0;
110 (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
111 return 0; 111 return 0;
112 112
113cifs_strncpy_to_host_ErrExit: 113cifs_strlcpy_to_host_ErrExit:
114 cERROR(1, ("Failed to allocate buffer for string\n")); 114 cERROR(1, ("Failed to allocate buffer for string\n"));
115 return -ENOMEM; 115 return -ENOMEM;
116} 116}
@@ -4029,7 +4029,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4029 /* copy DfsPath */ 4029 /* copy DfsPath */
4030 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); 4030 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4031 max_len = data_end - temp; 4031 max_len = data_end - temp;
4032 rc = cifs_strncpy_to_host(&(node->path_name), temp, 4032 rc = cifs_strlcpy_to_host(&(node->path_name), temp,
4033 max_len, is_unicode, nls_codepage); 4033 max_len, is_unicode, nls_codepage);
4034 if (rc) 4034 if (rc)
4035 goto parse_DFS_referrals_exit; 4035 goto parse_DFS_referrals_exit;
@@ -4037,7 +4037,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4037 /* copy link target UNC */ 4037 /* copy link target UNC */
4038 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); 4038 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4039 max_len = data_end - temp; 4039 max_len = data_end - temp;
4040 rc = cifs_strncpy_to_host(&(node->node_name), temp, 4040 rc = cifs_strlcpy_to_host(&(node->node_name), temp,
4041 max_len, is_unicode, nls_codepage); 4041 max_len, is_unicode, nls_codepage);
4042 if (rc) 4042 if (rc)
4043 goto parse_DFS_referrals_exit; 4043 goto parse_DFS_referrals_exit;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f36b4e40e443..9c869a6dcba1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -962,13 +962,21 @@ undo_setattr:
962 goto out_close; 962 goto out_close;
963} 963}
964 964
965
966/*
967 * If dentry->d_inode is null (usually meaning the cached dentry
968 * is a negative dentry) then we would attempt a standard SMB delete, but
969 * if that fails we can not attempt the fall back mechanisms on EACESS
970 * but will return the EACESS to the caller. Note that the VFS does not call
971 * unlink on negative dentries currently.
972 */
965int cifs_unlink(struct inode *dir, struct dentry *dentry) 973int cifs_unlink(struct inode *dir, struct dentry *dentry)
966{ 974{
967 int rc = 0; 975 int rc = 0;
968 int xid; 976 int xid;
969 char *full_path = NULL; 977 char *full_path = NULL;
970 struct inode *inode = dentry->d_inode; 978 struct inode *inode = dentry->d_inode;
971 struct cifsInodeInfo *cifsInode = CIFS_I(inode); 979 struct cifsInodeInfo *cifs_inode;
972 struct super_block *sb = dir->i_sb; 980 struct super_block *sb = dir->i_sb;
973 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 981 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
974 struct cifsTconInfo *tcon = cifs_sb->tcon; 982 struct cifsTconInfo *tcon = cifs_sb->tcon;
@@ -1012,7 +1020,7 @@ psx_del_no_retry:
1012 rc = cifs_rename_pending_delete(full_path, dentry, xid); 1020 rc = cifs_rename_pending_delete(full_path, dentry, xid);
1013 if (rc == 0) 1021 if (rc == 0)
1014 drop_nlink(inode); 1022 drop_nlink(inode);
1015 } else if (rc == -EACCES && dosattr == 0) { 1023 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
1016 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); 1024 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1017 if (attrs == NULL) { 1025 if (attrs == NULL) {
1018 rc = -ENOMEM; 1026 rc = -ENOMEM;
@@ -1020,7 +1028,8 @@ psx_del_no_retry:
1020 } 1028 }
1021 1029
1022 /* try to reset dos attributes */ 1030 /* try to reset dos attributes */
1023 origattr = cifsInode->cifsAttrs; 1031 cifs_inode = CIFS_I(inode);
1032 origattr = cifs_inode->cifsAttrs;
1024 if (origattr == 0) 1033 if (origattr == 0)
1025 origattr |= ATTR_NORMAL; 1034 origattr |= ATTR_NORMAL;
1026 dosattr = origattr & ~ATTR_READONLY; 1035 dosattr = origattr & ~ATTR_READONLY;
@@ -1041,13 +1050,13 @@ psx_del_no_retry:
1041 1050
1042out_reval: 1051out_reval:
1043 if (inode) { 1052 if (inode) {
1044 cifsInode = CIFS_I(inode); 1053 cifs_inode = CIFS_I(inode);
1045 cifsInode->time = 0; /* will force revalidate to get info 1054 cifs_inode->time = 0; /* will force revalidate to get info
1046 when needed */ 1055 when needed */
1047 inode->i_ctime = current_fs_time(sb); 1056 inode->i_ctime = current_fs_time(sb);
1048 } 1057 }
1049 dir->i_ctime = dir->i_mtime = current_fs_time(sb); 1058 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
1050 cifsInode = CIFS_I(dir); 1059 cifs_inode = CIFS_I(dir);
1051 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ 1060 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
1052 1061
1053 kfree(full_path); 1062 kfree(full_path);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 1a8be6228333..ebd0da7ecb3d 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -1074,7 +1074,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
1074 with the rare long characters alloc more to account for 1074 with the rare long characters alloc more to account for
1075 such multibyte target UTF-8 characters. cifs_unicode.c, 1075 such multibyte target UTF-8 characters. cifs_unicode.c,
1076 which actually does the conversion, has the same limit */ 1076 which actually does the conversion, has the same limit */
1077 tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); 1077 tmp_buf = kmalloc((4 * NAME_MAX) + 2, GFP_KERNEL);
1078 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 1078 for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
1079 if (current_entry == NULL) { 1079 if (current_entry == NULL) {
1080 /* evaluate whether this case is an error */ 1080 /* evaluate whether this case is an error */