Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '6.4-rc4-smb3-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:
"Eight server fixes (most also for stable):

- Two fixes for uninitialized pointer reads (rename and link)

- Fix potential UAF in oplock break

- Two fixes for potential out of bound reads in negotiate

- Fix crediting bug

- Two fixes for xfstests (allocation size fix for test 694 and lookup
issue shown by test 464)"

* tag '6.4-rc4-smb3-server-fixes' of git://git.samba.org/ksmbd:
ksmbd: call putname after using the last component
ksmbd: fix incorrect AllocationSize set in smb2_get_info
ksmbd: fix UAF issue from opinfo->conn
ksmbd: fix multiple out-of-bounds read during context decoding
ksmbd: fix slab-out-of-bounds read in smb2_handle_negotiate
ksmbd: fix credit count leakage
ksmbd: fix uninitialized pointer read in smb2_create_link()
ksmbd: fix uninitialized pointer read in ksmbd_vfs_rename()

+100 -77
+47 -25
fs/smb/server/oplock.c
··· 157 157 rcu_read_lock(); 158 158 opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info, 159 159 op_entry); 160 - if (opinfo && !atomic_inc_not_zero(&opinfo->refcount)) 161 - opinfo = NULL; 160 + if (opinfo) { 161 + if (!atomic_inc_not_zero(&opinfo->refcount)) 162 + opinfo = NULL; 163 + else { 164 + atomic_inc(&opinfo->conn->r_count); 165 + if (ksmbd_conn_releasing(opinfo->conn)) { 166 + atomic_dec(&opinfo->conn->r_count); 167 + atomic_dec(&opinfo->refcount); 168 + opinfo = NULL; 169 + } 170 + } 171 + } 172 + 162 173 rcu_read_unlock(); 163 174 164 175 return opinfo; 176 + } 177 + 178 + static void opinfo_conn_put(struct oplock_info *opinfo) 179 + { 180 + struct ksmbd_conn *conn; 181 + 182 + if (!opinfo) 183 + return; 184 + 185 + conn = opinfo->conn; 186 + /* 187 + * Checking waitqueue to dropping pending requests on 188 + * disconnection. waitqueue_active is safe because it 189 + * uses atomic operation for condition. 190 + */ 191 + if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q)) 192 + wake_up(&conn->r_count_q); 193 + opinfo_put(opinfo); 165 194 } 166 195 167 196 void opinfo_put(struct oplock_info *opinfo) ··· 695 666 696 667 out: 697 668 ksmbd_free_work_struct(work); 698 - /* 699 - * Checking waitqueue to dropping pending requests on 700 - * disconnection. waitqueue_active is safe because it 701 - * uses atomic operation for condition. 702 - */ 703 - if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q)) 704 - wake_up(&conn->r_count_q); 705 669 } 706 670 707 671 /** ··· 728 706 work->conn = conn; 729 707 work->sess = opinfo->sess; 730 708 731 - atomic_inc(&conn->r_count); 732 709 if (opinfo->op_state == OPLOCK_ACK_WAIT) { 733 710 INIT_WORK(&work->work, __smb2_oplock_break_noti); 734 711 ksmbd_queue_work(work); ··· 797 776 798 777 out: 799 778 ksmbd_free_work_struct(work); 800 - /* 801 - * Checking waitqueue to dropping pending requests on 802 - * disconnection. waitqueue_active is safe because it 803 - * uses atomic operation for condition. 804 - */ 805 - if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q)) 806 - wake_up(&conn->r_count_q); 807 779 } 808 780 809 781 /** ··· 836 822 work->conn = conn; 837 823 work->sess = opinfo->sess; 838 824 839 - atomic_inc(&conn->r_count); 840 825 if (opinfo->op_state == OPLOCK_ACK_WAIT) { 841 826 list_for_each_safe(tmp, t, &opinfo->interim_list) { 842 827 struct ksmbd_work *in_work; ··· 1157 1144 } 1158 1145 prev_opinfo = opinfo_get_list(ci); 1159 1146 if (!prev_opinfo || 1160 - (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) 1147 + (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) { 1148 + opinfo_conn_put(prev_opinfo); 1161 1149 goto set_lev; 1150 + } 1162 1151 prev_op_has_lease = prev_opinfo->is_lease; 1163 1152 if (prev_op_has_lease) 1164 1153 prev_op_state = prev_opinfo->o_lease->state; ··· 1168 1153 if (share_ret < 0 && 1169 1154 prev_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE) { 1170 1155 err = share_ret; 1171 - opinfo_put(prev_opinfo); 1156 + opinfo_conn_put(prev_opinfo); 1172 1157 goto err_out; 1173 1158 } 1174 1159 1175 1160 if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH && 1176 1161 prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) { 1177 - opinfo_put(prev_opinfo); 1162 + opinfo_conn_put(prev_opinfo); 1178 1163 goto op_break_not_needed; 1179 1164 } 1180 1165 1181 1166 list_add(&work->interim_entry, &prev_opinfo->interim_list); 1182 1167 err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II); 1183 - opinfo_put(prev_opinfo); 1168 + opinfo_conn_put(prev_opinfo); 1184 1169 if (err == -ENOENT) 1185 1170 goto set_lev; 1186 1171 /* Check all oplock was freed by close */ ··· 1243 1228 return; 1244 1229 if (brk_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH && 1245 1230 brk_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) { 1246 - opinfo_put(brk_opinfo); 1231 + opinfo_conn_put(brk_opinfo); 1247 1232 return; 1248 1233 } 1249 1234 1250 1235 brk_opinfo->open_trunc = is_trunc; 1251 1236 list_add(&work->interim_entry, &brk_opinfo->interim_list); 1252 1237 oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II); 1253 - opinfo_put(brk_opinfo); 1238 + opinfo_conn_put(brk_opinfo); 1254 1239 } 1255 1240 1256 1241 /** ··· 1278 1263 list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) { 1279 1264 if (!atomic_inc_not_zero(&brk_op->refcount)) 1280 1265 continue; 1266 + 1267 + atomic_inc(&brk_op->conn->r_count); 1268 + if (ksmbd_conn_releasing(brk_op->conn)) { 1269 + atomic_dec(&brk_op->conn->r_count); 1270 + continue; 1271 + } 1272 + 1281 1273 rcu_read_unlock(); 1282 1274 if (brk_op->is_lease && (brk_op->o_lease->state & 1283 1275 (~(SMB2_LEASE_READ_CACHING_LE | ··· 1314 1292 brk_op->open_trunc = is_trunc; 1315 1293 oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE); 1316 1294 next: 1317 - opinfo_put(brk_op); 1295 + opinfo_conn_put(brk_op); 1318 1296 rcu_read_lock(); 1319 1297 } 1320 1298 rcu_read_unlock();
+46 -50
fs/smb/server/smb2pdu.c
··· 326 326 if (hdr->Command == SMB2_NEGOTIATE) 327 327 aux_max = 1; 328 328 else 329 - aux_max = conn->vals->max_credits - credit_charge; 329 + aux_max = conn->vals->max_credits - conn->total_credits; 330 330 credits_granted = min_t(unsigned short, credits_requested, aux_max); 331 - 332 - if (conn->vals->max_credits - conn->total_credits < credits_granted) 333 - credits_granted = conn->vals->max_credits - 334 - conn->total_credits; 335 331 336 332 conn->total_credits += credits_granted; 337 333 work->credits_granted += credits_granted; ··· 845 849 846 850 static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn, 847 851 struct smb2_preauth_neg_context *pneg_ctxt, 848 - int len_of_ctxts) 852 + int ctxt_len) 849 853 { 850 854 /* 851 855 * sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt, 852 856 * which may not be present. Only check for used HashAlgorithms[1]. 853 857 */ 854 - if (len_of_ctxts < MIN_PREAUTH_CTXT_DATA_LEN) 858 + if (ctxt_len < 859 + sizeof(struct smb2_neg_context) + MIN_PREAUTH_CTXT_DATA_LEN) 855 860 return STATUS_INVALID_PARAMETER; 856 861 857 862 if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512) ··· 864 867 865 868 static void decode_encrypt_ctxt(struct ksmbd_conn *conn, 866 869 struct smb2_encryption_neg_context *pneg_ctxt, 867 - int len_of_ctxts) 870 + int ctxt_len) 868 871 { 869 - int cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount); 870 - int i, cphs_size = cph_cnt * sizeof(__le16); 872 + int cph_cnt; 873 + int i, cphs_size; 874 + 875 + if (sizeof(struct smb2_encryption_neg_context) > ctxt_len) { 876 + pr_err("Invalid SMB2_ENCRYPTION_CAPABILITIES context size\n"); 877 + return; 878 + } 871 879 872 880 conn->cipher_type = 0; 873 881 882 + cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount); 883 + cphs_size = cph_cnt * sizeof(__le16); 884 + 874 885 if (sizeof(struct smb2_encryption_neg_context) + cphs_size > 875 - len_of_ctxts) { 886 + ctxt_len) { 876 887 pr_err("Invalid cipher count(%d)\n", cph_cnt); 877 888 return; 878 889 } ··· 928 923 929 924 static void decode_sign_cap_ctxt(struct ksmbd_conn *conn, 930 925 struct smb2_signing_capabilities *pneg_ctxt, 931 - int len_of_ctxts) 926 + int ctxt_len) 932 927 { 933 - int sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount); 934 - int i, sign_alos_size = sign_algo_cnt * sizeof(__le16); 928 + int sign_algo_cnt; 929 + int i, sign_alos_size; 930 + 931 + if (sizeof(struct smb2_signing_capabilities) > ctxt_len) { 932 + pr_err("Invalid SMB2_SIGNING_CAPABILITIES context length\n"); 933 + return; 934 + } 935 935 936 936 conn->signing_negotiated = false; 937 + sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount); 938 + sign_alos_size = sign_algo_cnt * sizeof(__le16); 937 939 938 940 if (sizeof(struct smb2_signing_capabilities) + sign_alos_size > 939 - len_of_ctxts) { 941 + ctxt_len) { 940 942 pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt); 941 943 return; 942 944 } ··· 981 969 len_of_ctxts = len_of_smb - offset; 982 970 983 971 while (i++ < neg_ctxt_cnt) { 984 - int clen; 985 - 986 - /* check that offset is not beyond end of SMB */ 987 - if (len_of_ctxts == 0) 988 - break; 972 + int clen, ctxt_len; 989 973 990 974 if (len_of_ctxts < sizeof(struct smb2_neg_context)) 991 975 break; 992 976 993 977 pctx = (struct smb2_neg_context *)((char *)pctx + offset); 994 978 clen = le16_to_cpu(pctx->DataLength); 995 - if (clen + sizeof(struct smb2_neg_context) > len_of_ctxts) 979 + ctxt_len = clen + sizeof(struct smb2_neg_context); 980 + 981 + if (ctxt_len > len_of_ctxts) 996 982 break; 997 983 998 984 if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) { ··· 1001 991 1002 992 status = decode_preauth_ctxt(conn, 1003 993 (struct smb2_preauth_neg_context *)pctx, 1004 - len_of_ctxts); 994 + ctxt_len); 1005 995 if (status != STATUS_SUCCESS) 1006 996 break; 1007 997 } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) { ··· 1012 1002 1013 1003 decode_encrypt_ctxt(conn, 1014 1004 (struct smb2_encryption_neg_context *)pctx, 1015 - len_of_ctxts); 1005 + ctxt_len); 1016 1006 } else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) { 1017 1007 ksmbd_debug(SMB, 1018 1008 "deassemble SMB2_COMPRESSION_CAPABILITIES context\n"); ··· 1031 1021 } else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) { 1032 1022 ksmbd_debug(SMB, 1033 1023 "deassemble SMB2_SIGNING_CAPABILITIES context\n"); 1024 + 1034 1025 decode_sign_cap_ctxt(conn, 1035 1026 (struct smb2_signing_capabilities *)pctx, 1036 - len_of_ctxts); 1027 + ctxt_len); 1037 1028 } 1038 1029 1039 1030 /* offsets must be 8 byte aligned */ ··· 1068 1057 return rc; 1069 1058 } 1070 1059 1071 - if (req->DialectCount == 0) { 1072 - pr_err("malformed packet\n"); 1060 + smb2_buf_len = get_rfc1002_len(work->request_buf); 1061 + smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects); 1062 + if (smb2_neg_size > smb2_buf_len) { 1073 1063 rsp->hdr.Status = STATUS_INVALID_PARAMETER; 1074 1064 rc = -EINVAL; 1075 1065 goto err_out; 1076 1066 } 1077 1067 1078 - smb2_buf_len = get_rfc1002_len(work->request_buf); 1079 - smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects); 1080 - if (smb2_neg_size > smb2_buf_len) { 1068 + if (req->DialectCount == 0) { 1069 + pr_err("malformed packet\n"); 1081 1070 rsp->hdr.Status = STATUS_INVALID_PARAMETER; 1082 1071 rc = -EINVAL; 1083 1072 goto err_out; ··· 4369 4358 return 0; 4370 4359 } 4371 4360 4372 - static unsigned long long get_allocation_size(struct inode *inode, 4373 - struct kstat *stat) 4374 - { 4375 - unsigned long long alloc_size = 0; 4376 - 4377 - if (!S_ISDIR(stat->mode)) { 4378 - if ((inode->i_blocks << 9) <= stat->size) 4379 - alloc_size = stat->size; 4380 - else 4381 - alloc_size = inode->i_blocks << 9; 4382 - } 4383 - 4384 - return alloc_size; 4385 - } 4386 - 4387 4361 static void get_file_standard_info(struct smb2_query_info_rsp *rsp, 4388 4362 struct ksmbd_file *fp, void *rsp_org) 4389 4363 { ··· 4383 4387 sinfo = (struct smb2_file_standard_info *)rsp->Buffer; 4384 4388 delete_pending = ksmbd_inode_pending_delete(fp); 4385 4389 4386 - sinfo->AllocationSize = cpu_to_le64(get_allocation_size(inode, &stat)); 4390 + sinfo->AllocationSize = cpu_to_le64(inode->i_blocks << 9); 4387 4391 sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); 4388 4392 sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending); 4389 4393 sinfo->DeletePending = delete_pending; ··· 4448 4452 file_info->Attributes = fp->f_ci->m_fattr; 4449 4453 file_info->Pad1 = 0; 4450 4454 file_info->AllocationSize = 4451 - cpu_to_le64(get_allocation_size(inode, &stat)); 4455 + cpu_to_le64(inode->i_blocks << 9); 4452 4456 file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); 4453 4457 file_info->NumberOfLinks = 4454 4458 cpu_to_le32(get_nlink(&stat) - delete_pending); ··· 4637 4641 file_info->ChangeTime = cpu_to_le64(time); 4638 4642 file_info->Attributes = fp->f_ci->m_fattr; 4639 4643 file_info->AllocationSize = 4640 - cpu_to_le64(get_allocation_size(inode, &stat)); 4644 + cpu_to_le64(inode->i_blocks << 9); 4641 4645 file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); 4642 4646 file_info->Reserved = cpu_to_le32(0); 4643 4647 rsp->OutputBufferLength = ··· 5502 5506 { 5503 5507 char *link_name = NULL, *target_name = NULL, *pathname = NULL; 5504 5508 struct path path; 5505 - bool file_present = true; 5509 + bool file_present = false; 5506 5510 int rc; 5507 5511 5508 5512 if (buf_len < (u64)sizeof(struct smb2_file_link_info) + ··· 5535 5539 if (rc) { 5536 5540 if (rc != -ENOENT) 5537 5541 goto out; 5538 - file_present = false; 5539 - } 5542 + } else 5543 + file_present = true; 5540 5544 5541 5545 if (file_info->ReplaceIfExists) { 5542 5546 if (file_present) {
+7 -2
fs/smb/server/vfs.c
··· 86 86 err = vfs_path_parent_lookup(filename, flags, 87 87 &parent_path, &last, &type, 88 88 root_share_path); 89 - putname(filename); 90 - if (err) 89 + if (err) { 90 + putname(filename); 91 91 return err; 92 + } 92 93 93 94 if (unlikely(type != LAST_NORM)) { 94 95 path_put(&parent_path); 96 + putname(filename); 95 97 return -ENOENT; 96 98 } 97 99 ··· 110 108 path->dentry = d; 111 109 path->mnt = share_conf->vfs_path.mnt; 112 110 path_put(&parent_path); 111 + putname(filename); 113 112 114 113 return 0; 115 114 116 115 err_out: 117 116 inode_unlock(parent_path.dentry->d_inode); 118 117 path_put(&parent_path); 118 + putname(filename); 119 119 return -ENOENT; 120 120 } 121 121 ··· 747 743 rd.new_dir = new_path.dentry->d_inode, 748 744 rd.new_dentry = new_dentry, 749 745 rd.flags = flags, 746 + rd.delegated_inode = NULL, 750 747 err = vfs_rename(&rd); 751 748 if (err) 752 749 ksmbd_debug(VFS, "vfs_rename failed err %d\n", err);