From f73c17ed402a22bf94cba5fc1db31cd71f2b7e70 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Apr 2025 11:45:47 +0200 Subject: [PATCH] 5.15-stable patches added patches: ksmbd-fix-potencial-out-of-bounds-when-buffer-offset-is-invalid.patch net-make-sock_inuse_add-available.patch smb-client-fix-potential-uaf-in-cifs_dump_full_key.patch smb-client-fix-use-after-free-of-network-namespace.patch --- ...bounds-when-buffer-offset-is-invalid.patch | 302 ++++++++++++++++++ .../net-make-sock_inuse_add-available.patch | 97 ++++++ queue-5.15/series | 4 + ...-potential-uaf-in-cifs_dump_full_key.patch | 37 +++ ...-use-after-free-of-network-namespace.patch | 204 ++++++++++++ 5 files changed, 644 insertions(+) create mode 100644 queue-5.15/ksmbd-fix-potencial-out-of-bounds-when-buffer-offset-is-invalid.patch create mode 100644 queue-5.15/net-make-sock_inuse_add-available.patch create mode 100644 queue-5.15/smb-client-fix-potential-uaf-in-cifs_dump_full_key.patch create mode 100644 queue-5.15/smb-client-fix-use-after-free-of-network-namespace.patch diff --git a/queue-5.15/ksmbd-fix-potencial-out-of-bounds-when-buffer-offset-is-invalid.patch b/queue-5.15/ksmbd-fix-potencial-out-of-bounds-when-buffer-offset-is-invalid.patch new file mode 100644 index 0000000000..86ae4fd212 --- /dev/null +++ b/queue-5.15/ksmbd-fix-potencial-out-of-bounds-when-buffer-offset-is-invalid.patch @@ -0,0 +1,302 @@ +From c6cd2e8d2d9aa7ee35b1fa6a668e32a22a9753da Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Tue, 19 Mar 2024 08:40:48 +0900 +Subject: ksmbd: fix potencial out-of-bounds when buffer offset is invalid + +From: Namjae Jeon + +commit c6cd2e8d2d9aa7ee35b1fa6a668e32a22a9753da upstream. + +I found potencial out-of-bounds when buffer offset fields of a few requests +is invalid. This patch set the minimum value of buffer offset field to +->Buffer offset to validate buffer length. + +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Bin Lan +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + fs/ksmbd/smb2misc.c | 22 ++++++++++++++++------ + fs/ksmbd/smb2pdu.c | 47 +++++++++++++++++++++++++---------------------- + 2 files changed, 41 insertions(+), 28 deletions(-) + +--- a/fs/ksmbd/smb2misc.c ++++ b/fs/ksmbd/smb2misc.c +@@ -102,7 +102,9 @@ static int smb2_get_data_area_len(unsign + *len = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferLength); + break; + case SMB2_TREE_CONNECT: +- *off = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset); ++ *off = max_t(unsigned short int, ++ le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset), ++ offsetof(struct smb2_tree_connect_req, Buffer)); + *len = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength); + break; + case SMB2_CREATE: +@@ -129,11 +131,15 @@ static int smb2_get_data_area_len(unsign + break; + } + case SMB2_QUERY_INFO: +- *off = le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset); ++ *off = max_t(unsigned int, ++ le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset), ++ offsetof(struct smb2_query_info_req, Buffer)); + *len = le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLength); + break; + case SMB2_SET_INFO: +- *off = le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset); ++ *off = max_t(unsigned int, ++ le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset), ++ offsetof(struct smb2_set_info_req, Buffer)); + *len = le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength); + break; + case SMB2_READ: +@@ -143,7 +149,7 @@ static int smb2_get_data_area_len(unsign + case SMB2_WRITE: + if (((struct smb2_write_req *)hdr)->DataOffset || + ((struct smb2_write_req *)hdr)->Length) { +- *off = max_t(unsigned int, ++ *off = max_t(unsigned short int, + le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset), + offsetof(struct smb2_write_req, Buffer) - 4); + *len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length); +@@ -154,7 +160,9 @@ static int smb2_get_data_area_len(unsign + *len = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLength); + break; + case SMB2_QUERY_DIRECTORY: +- *off = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset); ++ *off = max_t(unsigned short int, ++ le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset), ++ offsetof(struct smb2_query_directory_req, Buffer)); + *len = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameLength); + break; + case SMB2_LOCK: +@@ -169,7 +177,9 @@ static int smb2_get_data_area_len(unsign + break; + } + case SMB2_IOCTL: +- *off = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset); ++ *off = max_t(unsigned int, ++ le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset), ++ offsetof(struct smb2_ioctl_req, Buffer)); + *len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount); + break; + default: +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1967,7 +1967,7 @@ int smb2_tree_connect(struct ksmbd_work + + WORK_BUFFERS(work, req, rsp); + +- treename = smb_strndup_from_utf16(req->Buffer, ++ treename = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->PathOffset), + le16_to_cpu(req->PathLength), true, + conn->local_nls); + if (IS_ERR(treename)) { +@@ -2714,7 +2714,7 @@ int smb2_open(struct ksmbd_work *work) + goto err_out2; + } + +- name = smb2_get_name(req->Buffer, ++ name = smb2_get_name((char *)req + le16_to_cpu(req->NameOffset), + le16_to_cpu(req->NameLength), + work->conn->local_nls); + if (IS_ERR(name)) { +@@ -4086,7 +4086,7 @@ int smb2_query_dir(struct ksmbd_work *wo + } + + srch_flag = req->Flags; +- srch_ptr = smb_strndup_from_utf16(req->Buffer, ++ srch_ptr = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->FileNameOffset), + le16_to_cpu(req->FileNameLength), 1, + conn->local_nls); + if (IS_ERR(srch_ptr)) { +@@ -4346,7 +4346,8 @@ static int smb2_get_ea(struct ksmbd_work + sizeof(struct smb2_ea_info_req)) + return -EINVAL; + +- ea_req = (struct smb2_ea_info_req *)req->Buffer; ++ ea_req = (struct smb2_ea_info_req *)((char *)req + ++ le16_to_cpu(req->InputBufferOffset)); + } else { + /* need to send all EAs, if no specific EA is requested*/ + if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY) +@@ -5952,6 +5953,7 @@ static int smb2_set_info_file(struct ksm + struct ksmbd_share_config *share) + { + unsigned int buf_len = le32_to_cpu(req->BufferLength); ++ char *buffer = (char *)req + le16_to_cpu(req->BufferOffset); + + switch (req->FileInfoClass) { + case FILE_BASIC_INFORMATION: +@@ -5959,7 +5961,7 @@ static int smb2_set_info_file(struct ksm + if (buf_len < sizeof(struct smb2_file_basic_info)) + return -EINVAL; + +- return set_file_basic_info(fp, (struct smb2_file_basic_info *)req->Buffer, share); ++ return set_file_basic_info(fp, (struct smb2_file_basic_info *)buffer, share); + } + case FILE_ALLOCATION_INFORMATION: + { +@@ -5967,7 +5969,7 @@ static int smb2_set_info_file(struct ksm + return -EINVAL; + + return set_file_allocation_info(work, fp, +- (struct smb2_file_alloc_info *)req->Buffer); ++ (struct smb2_file_alloc_info *)buffer); + } + case FILE_END_OF_FILE_INFORMATION: + { +@@ -5975,7 +5977,7 @@ static int smb2_set_info_file(struct ksm + return -EINVAL; + + return set_end_of_file_info(work, fp, +- (struct smb2_file_eof_info *)req->Buffer); ++ (struct smb2_file_eof_info *)buffer); + } + case FILE_RENAME_INFORMATION: + { +@@ -5983,7 +5985,7 @@ static int smb2_set_info_file(struct ksm + return -EINVAL; + + return set_rename_info(work, fp, +- (struct smb2_file_rename_info *)req->Buffer, ++ (struct smb2_file_rename_info *)buffer, + buf_len); + } + case FILE_LINK_INFORMATION: +@@ -5992,7 +5994,7 @@ static int smb2_set_info_file(struct ksm + return -EINVAL; + + return smb2_create_link(work, work->tcon->share_conf, +- (struct smb2_file_link_info *)req->Buffer, ++ (struct smb2_file_link_info *)buffer, + buf_len, fp->filp, + work->conn->local_nls); + } +@@ -6002,7 +6004,7 @@ static int smb2_set_info_file(struct ksm + return -EINVAL; + + return set_file_disposition_info(fp, +- (struct smb2_file_disposition_info *)req->Buffer); ++ (struct smb2_file_disposition_info *)buffer); + } + case FILE_FULL_EA_INFORMATION: + { +@@ -6015,7 +6017,7 @@ static int smb2_set_info_file(struct ksm + if (buf_len < sizeof(struct smb2_ea_info)) + return -EINVAL; + +- return smb2_set_ea((struct smb2_ea_info *)req->Buffer, ++ return smb2_set_ea((struct smb2_ea_info *)buffer, + buf_len, &fp->filp->f_path, true); + } + case FILE_POSITION_INFORMATION: +@@ -6023,14 +6025,14 @@ static int smb2_set_info_file(struct ksm + if (buf_len < sizeof(struct smb2_file_pos_info)) + return -EINVAL; + +- return set_file_position_info(fp, (struct smb2_file_pos_info *)req->Buffer); ++ return set_file_position_info(fp, (struct smb2_file_pos_info *)buffer); + } + case FILE_MODE_INFORMATION: + { + if (buf_len < sizeof(struct smb2_file_mode_info)) + return -EINVAL; + +- return set_file_mode_info(fp, (struct smb2_file_mode_info *)req->Buffer); ++ return set_file_mode_info(fp, (struct smb2_file_mode_info *)buffer); + } + } + +@@ -6111,7 +6113,7 @@ int smb2_set_info(struct ksmbd_work *wor + } + rc = smb2_set_info_sec(fp, + le32_to_cpu(req->AdditionalInformation), +- req->Buffer, ++ (char *)req + le16_to_cpu(req->BufferOffset), + le32_to_cpu(req->BufferLength)); + ksmbd_revert_fsids(work); + break; +@@ -7563,7 +7565,7 @@ static int fsctl_pipe_transceive(struct + struct smb2_ioctl_rsp *rsp) + { + struct ksmbd_rpc_command *rpc_resp; +- char *data_buf = (char *)&req->Buffer[0]; ++ char *data_buf = (char *)req + le32_to_cpu(req->InputOffset); + int nbytes = 0; + + rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf, +@@ -7676,6 +7678,7 @@ int smb2_ioctl(struct ksmbd_work *work) + u64 id = KSMBD_NO_FID; + struct ksmbd_conn *conn = work->conn; + int ret = 0; ++ char *buffer; + + if (work->next_smb2_rcv_hdr_off) { + req = ksmbd_req_buf_next(work); +@@ -7698,6 +7701,7 @@ int smb2_ioctl(struct ksmbd_work *work) + goto out; + } + ++ buffer = (char *)req + le32_to_cpu(req->InputOffset); + cnt_code = le32_to_cpu(req->CntCode); + ret = smb2_calc_max_out_buf_len(work, 48, + le32_to_cpu(req->MaxOutputResponse)); +@@ -7755,7 +7759,7 @@ int smb2_ioctl(struct ksmbd_work *work) + } + + ret = fsctl_validate_negotiate_info(conn, +- (struct validate_negotiate_info_req *)&req->Buffer[0], ++ (struct validate_negotiate_info_req *)buffer, + (struct validate_negotiate_info_rsp *)&rsp->Buffer[0], + in_buf_len); + if (ret < 0) +@@ -7808,7 +7812,7 @@ int smb2_ioctl(struct ksmbd_work *work) + rsp->VolatileFileId = req->VolatileFileId; + rsp->PersistentFileId = req->PersistentFileId; + fsctl_copychunk(work, +- (struct copychunk_ioctl_req *)&req->Buffer[0], ++ (struct copychunk_ioctl_req *)buffer, + le32_to_cpu(req->CntCode), + le32_to_cpu(req->InputCount), + req->VolatileFileId, +@@ -7821,8 +7825,7 @@ int smb2_ioctl(struct ksmbd_work *work) + goto out; + } + +- ret = fsctl_set_sparse(work, id, +- (struct file_sparse *)&req->Buffer[0]); ++ ret = fsctl_set_sparse(work, id, (struct file_sparse *)buffer); + if (ret < 0) + goto out; + break; +@@ -7845,7 +7848,7 @@ int smb2_ioctl(struct ksmbd_work *work) + } + + zero_data = +- (struct file_zero_data_information *)&req->Buffer[0]; ++ (struct file_zero_data_information *)buffer; + + off = le64_to_cpu(zero_data->FileOffset); + bfz = le64_to_cpu(zero_data->BeyondFinalZero); +@@ -7876,7 +7879,7 @@ int smb2_ioctl(struct ksmbd_work *work) + } + + ret = fsctl_query_allocated_ranges(work, id, +- (struct file_allocated_range_buffer *)&req->Buffer[0], ++ (struct file_allocated_range_buffer *)buffer, + (struct file_allocated_range_buffer *)&rsp->Buffer[0], + out_buf_len / + sizeof(struct file_allocated_range_buffer), &nbytes); +@@ -7920,7 +7923,7 @@ int smb2_ioctl(struct ksmbd_work *work) + goto out; + } + +- dup_ext = (struct duplicate_extents_to_file *)&req->Buffer[0]; ++ dup_ext = (struct duplicate_extents_to_file *)buffer; + + fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle, + dup_ext->PersistentFileHandle); diff --git a/queue-5.15/net-make-sock_inuse_add-available.patch b/queue-5.15/net-make-sock_inuse_add-available.patch new file mode 100644 index 0000000000..93aa07a6e7 --- /dev/null +++ b/queue-5.15/net-make-sock_inuse_add-available.patch @@ -0,0 +1,97 @@ +From d477eb9004845cb2dc92ad5eed79a437738a868a Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 15 Nov 2021 09:11:48 -0800 +Subject: net: make sock_inuse_add() available + +From: Eric Dumazet + +commit d477eb9004845cb2dc92ad5eed79a437738a868a upstream. + +MPTCP hard codes it, let us instead provide this helper. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Kuniyuki Iwashima +[ cherry-pick from amazon-linux amazon-5.15.y/mainline ] +Link: https://github.com/amazonlinux/linux/commit/7154d8eaac16 +Signed-off-by: Xiangyu Chen +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + include/net/sock.h | 10 ++++++++++ + net/core/sock.c | 10 ---------- + net/mptcp/subflow.c | 4 +--- + 3 files changed, 11 insertions(+), 13 deletions(-) + +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1472,6 +1472,12 @@ static inline void sock_prot_inuse_add(c + { + this_cpu_add(net->core.prot_inuse->val[prot->inuse_idx], val); + } ++ ++static inline void sock_inuse_add(const struct net *net, int val) ++{ ++ this_cpu_add(*net->core.sock_inuse, val); ++} ++ + int sock_prot_inuse_get(struct net *net, struct proto *proto); + int sock_inuse_get(struct net *net); + #else +@@ -1479,6 +1485,10 @@ static inline void sock_prot_inuse_add(c + const struct proto *prot, int val) + { + } ++ ++static inline void sock_inuse_add(const struct net *net, int val) ++{ ++} + #endif + + +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -144,8 +144,6 @@ + static DEFINE_MUTEX(proto_list_mutex); + static LIST_HEAD(proto_list); + +-static void sock_inuse_add(struct net *net, int val); +- + /** + * sk_ns_capable - General socket capability test + * @sk: Socket to use a capability on or through +@@ -3519,11 +3517,6 @@ int sock_prot_inuse_get(struct net *net, + } + EXPORT_SYMBOL_GPL(sock_prot_inuse_get); + +-static void sock_inuse_add(struct net *net, int val) +-{ +- this_cpu_add(*net->core.sock_inuse, val); +-} +- + int sock_inuse_get(struct net *net) + { + int cpu, res = 0; +@@ -3602,9 +3595,6 @@ static inline void release_proto_idx(str + { + } + +-static void sock_inuse_add(struct net *net, int val) +-{ +-} + #endif + + static void tw_prot_cleanup(struct timewait_sock_ops *twsk_prot) +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -1584,9 +1584,7 @@ int mptcp_subflow_create_socket(struct s + */ + sf->sk->sk_net_refcnt = 1; + get_net(net); +-#ifdef CONFIG_PROC_FS +- this_cpu_add(*net->core.sock_inuse, 1); +-#endif ++ sock_inuse_add(net, 1); + err = tcp_set_ulp(sf->sk, "mptcp"); + release_sock(sf->sk); + diff --git a/queue-5.15/series b/queue-5.15/series index 7965f7dcbc..94d8c3edfc 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -217,3 +217,7 @@ drm-amd-display-add-null-checks-for-stream-and-plane-before-dereferencing.patch drm-amdgpu-fix-usage-slab-after-free.patch landlock-add-the-errata-interface.patch nvmet-fc-remove-unused-functions.patch +smb-client-fix-potential-uaf-in-cifs_dump_full_key.patch +ksmbd-fix-potencial-out-of-bounds-when-buffer-offset-is-invalid.patch +net-make-sock_inuse_add-available.patch +smb-client-fix-use-after-free-of-network-namespace.patch diff --git a/queue-5.15/smb-client-fix-potential-uaf-in-cifs_dump_full_key.patch b/queue-5.15/smb-client-fix-potential-uaf-in-cifs_dump_full_key.patch new file mode 100644 index 0000000000..916b101594 --- /dev/null +++ b/queue-5.15/smb-client-fix-potential-uaf-in-cifs_dump_full_key.patch @@ -0,0 +1,37 @@ +From 58acd1f497162e7d282077f816faa519487be045 Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Tue, 2 Apr 2024 16:33:54 -0300 +Subject: smb: client: fix potential UAF in cifs_dump_full_key() + +From: Paulo Alcantara + +commit 58acd1f497162e7d282077f816faa519487be045 upstream. + +Skip sessions that are being teared down (status == SES_EXITING) to +avoid UAF. + +Cc: stable@vger.kernel.org +Signed-off-by: Paulo Alcantara (Red Hat) +Signed-off-by: Steve French +[ This patch removes lock/unlock operation in routine cifs_dump_full_key() + for ses_lock is not present in v5.15 and not ported yet. ses->status + is protected by a global lock, cifs_tcp_ses_lock, in v5.15. ] +Signed-off-by: Jianqi Ren +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/ioctl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/cifs/ioctl.c ++++ b/fs/cifs/ioctl.c +@@ -232,7 +232,8 @@ static int cifs_dump_full_key(struct cif + spin_lock(&cifs_tcp_ses_lock); + list_for_each_entry(server_it, &cifs_tcp_ses_list, tcp_ses_list) { + list_for_each_entry(ses_it, &server_it->smb_ses_list, smb_ses_list) { +- if (ses_it->Suid == out.session_id) { ++ if (ses_it->status != CifsExiting && ++ ses_it->Suid == out.session_id) { + ses = ses_it; + /* + * since we are using the session outside the crit diff --git a/queue-5.15/smb-client-fix-use-after-free-of-network-namespace.patch b/queue-5.15/smb-client-fix-use-after-free-of-network-namespace.patch new file mode 100644 index 0000000000..9baf3e6291 --- /dev/null +++ b/queue-5.15/smb-client-fix-use-after-free-of-network-namespace.patch @@ -0,0 +1,204 @@ +From ef7134c7fc48e1441b398e55a862232868a6f0a7 Mon Sep 17 00:00:00 2001 +From: Kuniyuki Iwashima +Date: Sat, 2 Nov 2024 14:24:38 -0700 +Subject: smb: client: Fix use-after-free of network namespace. + +From: Kuniyuki Iwashima + +commit ef7134c7fc48e1441b398e55a862232868a6f0a7 upstream. + +Recently, we got a customer report that CIFS triggers oops while +reconnecting to a server. [0] + +The workload runs on Kubernetes, and some pods mount CIFS servers +in non-root network namespaces. The problem rarely happened, but +it was always while the pod was dying. + +The root cause is wrong reference counting for network namespace. + +CIFS uses kernel sockets, which do not hold refcnt of the netns that +the socket belongs to. That means CIFS must ensure the socket is +always freed before its netns; otherwise, use-after-free happens. + +The repro steps are roughly: + + 1. mount CIFS in a non-root netns + 2. drop packets from the netns + 3. destroy the netns + 4. unmount CIFS + +We can reproduce the issue quickly with the script [1] below and see +the splat [2] if CONFIG_NET_NS_REFCNT_TRACKER is enabled. + +When the socket is TCP, it is hard to guarantee the netns lifetime +without holding refcnt due to async timers. + +Let's hold netns refcnt for each socket as done for SMC in commit +9744d2bf1976 ("smc: Fix use-after-free in tcp_write_timer_handler()."). + +Note that we need to move put_net() from cifs_put_tcp_session() to +clean_demultiplex_info(); otherwise, __sock_create() still could touch a +freed netns while cifsd tries to reconnect from cifs_demultiplex_thread(). + +Also, maybe_get_net() cannot be put just before __sock_create() because +the code is not under RCU and there is a small chance that the same +address happened to be reallocated to another netns. + +[0]: +CIFS: VFS: \\XXXXXXXXXXX has not responded in 15 seconds. Reconnecting... +CIFS: Serverclose failed 4 times, giving up +Unable to handle kernel paging request at virtual address 14de99e461f84a07 +Mem abort info: + ESR = 0x0000000096000004 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x04: level 0 translation fault +Data abort info: + ISV = 0, ISS = 0x00000004 + CM = 0, WnR = 0 +[14de99e461f84a07] address between user and kernel address ranges +Internal error: Oops: 0000000096000004 [#1] SMP +Modules linked in: cls_bpf sch_ingress nls_utf8 cifs cifs_arc4 cifs_md4 dns_resolver tcp_diag inet_diag veth xt_state xt_connmark nf_conntrack_netlink xt_nat xt_statistic xt_MASQUERADE xt_mark xt_addrtype ipt_REJECT nf_reject_ipv4 nft_chain_nat nf_nat xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 xt_comment nft_compat nf_tables nfnetlink overlay nls_ascii nls_cp437 sunrpc vfat fat aes_ce_blk aes_ce_cipher ghash_ce sm4_ce_cipher sm4 sm3_ce sm3 sha3_ce sha512_ce sha512_arm64 sha1_ce ena button sch_fq_codel loop fuse configfs dmi_sysfs sha2_ce sha256_arm64 dm_mirror dm_region_hash dm_log dm_mod dax efivarfs +CPU: 5 PID: 2690970 Comm: cifsd Not tainted 6.1.103-109.184.amzn2023.aarch64 #1 +Hardware name: Amazon EC2 r7g.4xlarge/, BIOS 1.0 11/1/2018 +pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : fib_rules_lookup+0x44/0x238 +lr : __fib_lookup+0x64/0xbc +sp : ffff8000265db790 +x29: ffff8000265db790 x28: 0000000000000000 x27: 000000000000bd01 +x26: 0000000000000000 x25: ffff000b4baf8000 x24: ffff00047b5e4580 +x23: ffff8000265db7e0 x22: 0000000000000000 x21: ffff00047b5e4500 +x20: ffff0010e3f694f8 x19: 14de99e461f849f7 x18: 0000000000000000 +x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 +x14: 0000000000000000 x13: 0000000000000000 x12: 3f92800abd010002 +x11: 0000000000000001 x10: ffff0010e3f69420 x9 : ffff800008a6f294 +x8 : 0000000000000000 x7 : 0000000000000006 x6 : 0000000000000000 +x5 : 0000000000000001 x4 : ffff001924354280 x3 : ffff8000265db7e0 +x2 : 0000000000000000 x1 : ffff0010e3f694f8 x0 : ffff00047b5e4500 +Call trace: + fib_rules_lookup+0x44/0x238 + __fib_lookup+0x64/0xbc + ip_route_output_key_hash_rcu+0x2c4/0x398 + ip_route_output_key_hash+0x60/0x8c + tcp_v4_connect+0x290/0x488 + __inet_stream_connect+0x108/0x3d0 + inet_stream_connect+0x50/0x78 + kernel_connect+0x6c/0xac + generic_ip_connect+0x10c/0x6c8 [cifs] + __reconnect_target_unlocked+0xa0/0x214 [cifs] + reconnect_dfs_server+0x144/0x460 [cifs] + cifs_reconnect+0x88/0x148 [cifs] + cifs_readv_from_socket+0x230/0x430 [cifs] + cifs_read_from_socket+0x74/0xa8 [cifs] + cifs_demultiplex_thread+0xf8/0x704 [cifs] + kthread+0xd0/0xd4 +Code: aa0003f8 f8480f13 eb18027f 540006c0 (b9401264) + +[1]: +CIFS_CRED="/root/cred.cifs" +CIFS_USER="Administrator" +CIFS_PASS="Password" +CIFS_IP="X.X.X.X" +CIFS_PATH="//${CIFS_IP}/Users/Administrator/Desktop/CIFS_TEST" +CIFS_MNT="/mnt/smb" +DEV="enp0s3" + +cat < ${CIFS_CRED} +username=${CIFS_USER} +password=${CIFS_PASS} +domain=EXAMPLE.COM +EOF + +unshare -n bash -c " +mkdir -p ${CIFS_MNT} +ip netns attach root 1 +ip link add eth0 type veth peer veth0 netns root +ip link set eth0 up +ip -n root link set veth0 up +ip addr add 192.168.0.2/24 dev eth0 +ip -n root addr add 192.168.0.1/24 dev veth0 +ip route add default via 192.168.0.1 dev eth0 +ip netns exec root sysctl net.ipv4.ip_forward=1 +ip netns exec root iptables -t nat -A POSTROUTING -s 192.168.0.2 -o ${DEV} -j MASQUERADE +mount -t cifs ${CIFS_PATH} ${CIFS_MNT} -o vers=3.0,sec=ntlmssp,credentials=${CIFS_CRED},rsize=65536,wsize=65536,cache=none,echo_interval=1 +touch ${CIFS_MNT}/a.txt +ip netns exec root iptables -t nat -D POSTROUTING -s 192.168.0.2 -o ${DEV} -j MASQUERADE +" + +umount ${CIFS_MNT} + +[2]: +ref_tracker: net notrefcnt@000000004bbc008d has 1/1 users at + sk_alloc (./include/net/net_namespace.h:339 net/core/sock.c:2227) + inet_create (net/ipv4/af_inet.c:326 net/ipv4/af_inet.c:252) + __sock_create (net/socket.c:1576) + generic_ip_connect (fs/smb/client/connect.c:3075) + cifs_get_tcp_session.part.0 (fs/smb/client/connect.c:3160 fs/smb/client/connect.c:1798) + cifs_mount_get_session (fs/smb/client/trace.h:959 fs/smb/client/connect.c:3366) + dfs_mount_share (fs/smb/client/dfs.c:63 fs/smb/client/dfs.c:285) + cifs_mount (fs/smb/client/connect.c:3622) + cifs_smb3_do_mount (fs/smb/client/cifsfs.c:949) + smb3_get_tree (fs/smb/client/fs_context.c:784 fs/smb/client/fs_context.c:802 fs/smb/client/fs_context.c:794) + vfs_get_tree (fs/super.c:1800) + path_mount (fs/namespace.c:3508 fs/namespace.c:3834) + __x64_sys_mount (fs/namespace.c:3848 fs/namespace.c:4057 fs/namespace.c:4034 fs/namespace.c:4034) + do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) + +Fixes: 26abe14379f8 ("net: Modify sk_alloc to not reference count the netns of kernel sockets.") +Signed-off-by: Kuniyuki Iwashima +Acked-by: Tom Talpey +Signed-off-by: Steve French +[ cherry-pick from amazon-linux amazon-5.15.y/mainline ] +Link: https://github.com/amazonlinux/linux/commit/ee70e0a05686 +Signed-off-by: Xiangyu Chen +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/connect.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -839,6 +839,7 @@ static void clean_demultiplex_info(struc + */ + } + ++ put_net(cifs_net_ns(server)); + #ifdef CONFIG_CIFS_DFS_UPCALL + kfree(server->origin_fullpath); + kfree(server->leaf_fullpath); +@@ -1373,8 +1374,6 @@ cifs_put_tcp_session(struct TCP_Server_I + /* srv_count can never go negative */ + WARN_ON(server->srv_count < 0); + +- put_net(cifs_net_ns(server)); +- + list_del_init(&server->tcp_ses_list); + spin_unlock(&cifs_tcp_ses_lock); + +@@ -2701,7 +2700,10 @@ generic_ip_connect(struct TCP_Server_Inf + } + + if (socket == NULL) { +- rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM, ++ struct net *net = cifs_net_ns(server); ++ struct sock *sk; ++ ++ rc = __sock_create(net, sfamily, SOCK_STREAM, + IPPROTO_TCP, &socket, 1); + if (rc < 0) { + cifs_server_dbg(VFS, "Error %d creating socket\n", rc); +@@ -2709,6 +2711,11 @@ generic_ip_connect(struct TCP_Server_Inf + return rc; + } + ++ sk = socket->sk; ++ sk->sk_net_refcnt = 1; ++ get_net(net); ++ sock_inuse_add(net, 1); ++ + /* BB other socket options to set KEEPALIVE, NODELAY? */ + cifs_dbg(FYI, "Socket created\n"); + server->ssocket = socket; -- 2.47.3