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

Merge tag '6.15-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client updates from Steve French:

- Fix for network namespace refcount leak

- Multichannel fix and minor multichannel debug message cleanup

- Fix potential null ptr reference in SMB3 close

- Fix for special file handling when reparse points not supported by
server

- Two ACL fixes one for stricter ACE validation, one for incorrect
perms requested

- Three RFC1001 fixes: one for SMB3 mounts on port 139, one for better
default hostname, and one for better session response processing

- Minor update to email address for MAINTAINERS file

- Allow disabling Unicode for access to old SMB1 servers

- Three minor cleanups

* tag '6.15-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: Add new mount option -o nounicode to disable SMB1 UNICODE mode
cifs: Set default Netbios RFC1001 server name to hostname in UNC
smb: client: Fix netns refcount imbalance causing leaks and use-after-free
cifs: add validation check for the fields in smb_aces
CIFS: Propagate min offload along with other parameters from primary to secondary channels.
cifs: Improve establishing SMB connection with NetBIOS session
cifs: Fix establishing NetBIOS session for SMB2+ connection
cifs: Fix getting DACL-only xattr system.cifs_acl and system.smb3_acl
cifs: Check if server supports reparse points before using them
MAINTAINERS: reorder preferred email for Steve French
cifs: avoid NULL pointer dereference in dbg call
smb: client: Remove redundant check in smb2_is_path_accessible()
smb: client: Remove redundant check in cifs_oplock_break()
smb: mark the new channel addition log as informational log with cifs_info
smb: minor cleanup to remove unused function declaration

+289 -45
+1 -1
MAINTAINERS
··· 12905 12905 KERNEL SMB3 SERVER (KSMBD) 12906 12906 M: Namjae Jeon <linkinjeon@kernel.org> 12907 12907 M: Namjae Jeon <linkinjeon@samba.org> 12908 - M: Steve French <sfrench@samba.org> 12909 12908 M: Steve French <smfrench@gmail.com> 12909 + M: Steve French <sfrench@samba.org> 12910 12910 R: Sergey Senozhatsky <senozhatsky@chromium.org> 12911 12911 R: Tom Talpey <tom@talpey.com> 12912 12912 L: linux-cifs@vger.kernel.org
+18 -3
fs/smb/client/cifsacl.c
··· 811 811 return; 812 812 813 813 for (i = 0; i < num_aces; ++i) { 814 + if (end_of_acl - acl_base < acl_size) 815 + break; 816 + 814 817 ppace[i] = (struct smb_ace *) (acl_base + acl_size); 818 + acl_base = (char *)ppace[i]; 819 + acl_size = offsetof(struct smb_ace, sid) + 820 + offsetof(struct smb_sid, sub_auth); 821 + 822 + if (end_of_acl - acl_base < acl_size || 823 + ppace[i]->sid.num_subauth == 0 || 824 + ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || 825 + (end_of_acl - acl_base < 826 + acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) || 827 + (le16_to_cpu(ppace[i]->size) < 828 + acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth)) 829 + break; 830 + 815 831 #ifdef CONFIG_CIFS_DEBUG2 816 832 dump_ace(ppace[i], end_of_acl); 817 833 #endif ··· 871 855 (void *)ppace[i], 872 856 sizeof(struct smb_ace)); */ 873 857 874 - acl_base = (char *)ppace[i]; 875 858 acl_size = le16_to_cpu(ppace[i]->size); 876 859 } 877 860 ··· 1565 1550 int rc = 0; 1566 1551 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); 1567 1552 struct smb_version_operations *ops; 1568 - const u32 info = 0; 1553 + const u32 info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO; 1569 1554 1570 1555 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path); 1571 1556 ··· 1619 1604 struct tcon_link *tlink; 1620 1605 struct smb_version_operations *ops; 1621 1606 bool mode_from_sid, id_from_sid; 1622 - const u32 info = 0; 1607 + const u32 info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO; 1623 1608 bool posix; 1624 1609 1625 1610 tlink = cifs_sb_tlink(cifs_sb);
+4
fs/smb/client/cifsfs.c
··· 637 637 cifs_sb->ctx->dir_mode); 638 638 if (cifs_sb->ctx->iocharset) 639 639 seq_printf(s, ",iocharset=%s", cifs_sb->ctx->iocharset); 640 + if (tcon->ses->unicode == 0) 641 + seq_puts(s, ",nounicode"); 642 + else if (tcon->ses->unicode == 1) 643 + seq_puts(s, ",unicode"); 640 644 if (tcon->seal) 641 645 seq_puts(s, ",seal"); 642 646 else if (tcon->ses->server->ignore_signature)
+2
fs/smb/client/cifsglob.h
··· 653 653 unsigned int cap_unix; 654 654 unsigned int cap_nt_find; 655 655 unsigned int cap_large_files; 656 + unsigned int cap_unicode; 656 657 __u16 signing_enabled; 657 658 __u16 signing_required; 658 659 size_t create_lease_size; ··· 1121 1120 bool sign; /* is signing required? */ 1122 1121 bool domainAuto:1; 1123 1122 bool expired_pwd; /* track if access denied or expired pwd so can know if need to update */ 1123 + int unicode; 1124 1124 unsigned int flags; 1125 1125 __u16 session_flags; 1126 1126 __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
+3 -1
fs/smb/client/cifsproto.h
··· 31 31 extern void free_rsp_buf(int, void *); 32 32 extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, 33 33 unsigned int /* length */); 34 + extern int smb_send_kvec(struct TCP_Server_Info *server, 35 + struct msghdr *msg, 36 + size_t *sent); 34 37 extern unsigned int _get_xid(void); 35 38 extern void _free_xid(unsigned int); 36 39 #define get_xid() \ ··· 595 592 int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); 596 593 597 594 void cifs_async_writev(struct cifs_io_subrequest *wdata); 598 - void cifs_writev_complete(struct work_struct *work); 599 595 int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, 600 596 struct cifs_sb_info *cifs_sb, 601 597 const unsigned char *path, char *pbuf,
+8 -3
fs/smb/client/cifssmb.c
··· 437 437 return rc; 438 438 439 439 pSMB->hdr.Mid = get_next_mid(server); 440 - pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); 440 + pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; 441 + 442 + if (ses->unicode != 0) 443 + pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 441 444 442 445 if (should_set_ext_sec_flag(ses->sectype)) { 443 446 cifs_dbg(FYI, "Requesting extended security\n"); ··· 2712 2709 if (cap_unix(tcon->ses)) 2713 2710 return -EOPNOTSUPP; 2714 2711 2712 + if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) 2713 + return -EOPNOTSUPP; 2714 + 2715 2715 oparms = (struct cifs_open_parms) { 2716 2716 .tcon = tcon, 2717 2717 .cifs_sb = cifs_sb, ··· 3406 3400 /* BB TEST with big acls that might need to be e.g. larger than 16K */ 3407 3401 pSMB->MaxSetupCount = 0; 3408 3402 pSMB->Fid = fid; /* file handle always le */ 3409 - pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | 3410 - CIFS_ACL_DACL | info); 3403 + pSMB->AclFlags = cpu_to_le32(info); 3411 3404 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ 3412 3405 inc_rfc1001_len(pSMB, 11); 3413 3406 iov[0].iov_base = (char *)pSMB;
+187 -19
fs/smb/client/connect.c
··· 300 300 server->ssocket->flags); 301 301 sock_release(server->ssocket); 302 302 server->ssocket = NULL; 303 + put_net(cifs_net_ns(server)); 303 304 } 304 305 server->sequence_number = 0; 305 306 server->session_estab = false; ··· 1677 1676 /* Grab netns reference for this server. */ 1678 1677 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); 1679 1678 1679 + tcp_ses->sign = ctx->sign; 1680 1680 tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId); 1681 1681 tcp_ses->noblockcnt = ctx->rootfs; 1682 1682 tcp_ses->noblocksnd = ctx->noblocksnd || ctx->rootfs; ··· 2351 2349 ses->cred_uid = ctx->cred_uid; 2352 2350 ses->linux_uid = ctx->linux_uid; 2353 2351 2352 + ses->unicode = ctx->unicode; 2354 2353 ses->sectype = ctx->sectype; 2355 2354 ses->sign = ctx->sign; 2356 2355 ··· 3029 3026 } 3030 3027 3031 3028 static int 3029 + smb_recv_kvec(struct TCP_Server_Info *server, struct msghdr *msg, size_t *recv) 3030 + { 3031 + int rc = 0; 3032 + int retries = 0; 3033 + int msg_flags = server->noblocksnd ? MSG_DONTWAIT : 0; 3034 + 3035 + *recv = 0; 3036 + 3037 + while (msg_data_left(msg)) { 3038 + rc = sock_recvmsg(server->ssocket, msg, msg_flags); 3039 + if (rc == -EAGAIN) { 3040 + retries++; 3041 + if (retries >= 14 || 3042 + (!server->noblocksnd && (retries > 2))) { 3043 + cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", 3044 + server->ssocket); 3045 + return -EAGAIN; 3046 + } 3047 + msleep(1 << retries); 3048 + continue; 3049 + } 3050 + 3051 + if (rc < 0) 3052 + return rc; 3053 + 3054 + if (rc == 0) { 3055 + cifs_dbg(FYI, "Received no data (TCP RST)\n"); 3056 + return -ECONNABORTED; 3057 + } 3058 + 3059 + /* recv was at least partially successful */ 3060 + *recv += rc; 3061 + retries = 0; /* in case we get ENOSPC on the next send */ 3062 + } 3063 + return 0; 3064 + } 3065 + 3066 + static int 3032 3067 ip_rfc1001_connect(struct TCP_Server_Info *server) 3033 3068 { 3034 3069 int rc = 0; ··· 3076 3035 * sessinit is sent but no second negprot 3077 3036 */ 3078 3037 struct rfc1002_session_packet req = {}; 3079 - struct smb_hdr *smb_buf = (struct smb_hdr *)&req; 3038 + struct rfc1002_session_packet resp = {}; 3039 + struct msghdr msg = {}; 3040 + struct kvec iov = {}; 3080 3041 unsigned int len; 3042 + size_t sent; 3043 + size_t recv; 3081 3044 3082 3045 req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name); 3083 3046 ··· 3110 3065 * As per rfc1002, @len must be the number of bytes that follows the 3111 3066 * length field of a rfc1002 session request payload. 3112 3067 */ 3113 - len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req); 3068 + len = sizeof(req.trailer.session_req); 3069 + req.type = RFC1002_SESSION_REQUEST; 3070 + req.flags = 0; 3071 + req.length = cpu_to_be16(len); 3072 + len += offsetof(typeof(req), trailer.session_req); 3073 + iov.iov_base = &req; 3074 + iov.iov_len = len; 3075 + iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, len); 3076 + rc = smb_send_kvec(server, &msg, &sent); 3077 + if (rc < 0 || len != sent) 3078 + return (rc == -EINTR || rc == -EAGAIN) ? rc : -ECONNABORTED; 3114 3079 3115 - smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len); 3116 - rc = smb_send(server, smb_buf, len); 3117 3080 /* 3118 3081 * RFC1001 layer in at least one server requires very short break before 3119 3082 * negprot presumably because not expecting negprot to follow so fast. 3120 - * This is a simple solution that works without complicating the code 3121 - * and causes no significant slowing down on mount for everyone else 3083 + * For example DOS SMB servers cannot process negprot if it was received 3084 + * before the server sent response for SESSION_REQUEST packet. So, wait 3085 + * for the response, read it and parse it as it can contain useful error 3086 + * information (e.g. specified server name was incorrect). For example 3087 + * even the latest Windows Server 2022 SMB1 server over port 139 send 3088 + * error if its server name was in SESSION_REQUEST packet incorrect. 3089 + * Nowadays usage of port 139 is not common, so waiting for reply here 3090 + * does not slowing down mounting of common case (over port 445). 3122 3091 */ 3123 - usleep_range(1000, 2000); 3092 + len = offsetof(typeof(resp), trailer); 3093 + iov.iov_base = &resp; 3094 + iov.iov_len = len; 3095 + iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, len); 3096 + rc = smb_recv_kvec(server, &msg, &recv); 3097 + if (rc < 0 || recv != len) 3098 + return (rc == -EINTR || rc == -EAGAIN) ? rc : -ECONNABORTED; 3124 3099 3125 - return rc; 3100 + switch (resp.type) { 3101 + case RFC1002_POSITIVE_SESSION_RESPONSE: 3102 + if (be16_to_cpu(resp.length) != 0) { 3103 + cifs_dbg(VFS, "RFC 1002 positive session response but with invalid non-zero length %u\n", 3104 + be16_to_cpu(resp.length)); 3105 + return -EIO; 3106 + } 3107 + cifs_dbg(FYI, "RFC 1002 positive session response"); 3108 + break; 3109 + case RFC1002_NEGATIVE_SESSION_RESPONSE: 3110 + /* Read RFC1002 response error code and convert it to errno in rc */ 3111 + len = sizeof(resp.trailer.neg_ses_resp_error_code); 3112 + iov.iov_base = &resp.trailer.neg_ses_resp_error_code; 3113 + iov.iov_len = len; 3114 + iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, len); 3115 + if (be16_to_cpu(resp.length) == len && 3116 + smb_recv_kvec(server, &msg, &recv) == 0 && 3117 + recv == len) { 3118 + cifs_dbg(VFS, "RFC 1002 negative session response with error 0x%x\n", 3119 + resp.trailer.neg_ses_resp_error_code); 3120 + switch (resp.trailer.neg_ses_resp_error_code) { 3121 + case RFC1002_NOT_LISTENING_CALLED: 3122 + /* server does not listen for specified server name */ 3123 + fallthrough; 3124 + case RFC1002_NOT_PRESENT: 3125 + /* server name is incorrect */ 3126 + rc = -ENOENT; 3127 + cifs_dbg(VFS, "Server rejected NetBIOS servername %.15s\n", 3128 + server->server_RFC1001_name[0] ? 3129 + server->server_RFC1001_name : 3130 + DEFAULT_CIFS_CALLED_NAME); 3131 + cifs_dbg(VFS, "Specify correct NetBIOS servername in source path or with -o servern= option\n"); 3132 + break; 3133 + case RFC1002_NOT_LISTENING_CALLING: 3134 + /* client name was not accepted by server */ 3135 + rc = -EACCES; 3136 + cifs_dbg(VFS, "Server rejected NetBIOS clientname %.15s\n", 3137 + server->workstation_RFC1001_name[0] ? 3138 + server->workstation_RFC1001_name : 3139 + "LINUX_CIFS_CLNT"); 3140 + cifs_dbg(VFS, "Specify correct NetBIOS clientname with -o netbiosname= option\n"); 3141 + break; 3142 + case RFC1002_INSUFFICIENT_RESOURCE: 3143 + /* remote server resource error */ 3144 + rc = -EREMOTEIO; 3145 + break; 3146 + case RFC1002_UNSPECIFIED_ERROR: 3147 + default: 3148 + /* other/unknown error */ 3149 + rc = -EIO; 3150 + break; 3151 + } 3152 + } else { 3153 + cifs_dbg(VFS, "RFC 1002 negative session response\n"); 3154 + rc = -EIO; 3155 + } 3156 + return rc; 3157 + case RFC1002_RETARGET_SESSION_RESPONSE: 3158 + cifs_dbg(VFS, "RFC 1002 retarget session response\n"); 3159 + if (be16_to_cpu(resp.length) == sizeof(resp.trailer.retarget_resp)) { 3160 + len = sizeof(resp.trailer.retarget_resp); 3161 + iov.iov_base = &resp.trailer.retarget_resp; 3162 + iov.iov_len = len; 3163 + iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, len); 3164 + if (smb_recv_kvec(server, &msg, &recv) == 0 && recv == len) { 3165 + cifs_dbg(VFS, "Server wants to redirect connection\n"); 3166 + cifs_dbg(VFS, "Remount with options -o ip=%pI4,port=%u\n", 3167 + &resp.trailer.retarget_resp.retarget_ip_addr, 3168 + be16_to_cpu(resp.trailer.retarget_resp.port)); 3169 + } 3170 + } 3171 + cifs_dbg(VFS, "Closing connection\n"); 3172 + /* FIXME: Should we automatically redirect to new retarget_resp server? */ 3173 + return -EMULTIHOP; 3174 + default: 3175 + cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", resp.type); 3176 + return -EIO; 3177 + } 3178 + 3179 + return 0; 3126 3180 } 3127 3181 3128 3182 static int ··· 3267 3123 /* 3268 3124 * Grab netns reference for the socket. 3269 3125 * 3270 - * It'll be released here, on error, or in clean_demultiplex_info() upon server 3271 - * teardown. 3126 + * This reference will be released in several situations: 3127 + * - In the failure path before the cifsd thread is started. 3128 + * - In the all place where server->socket is released, it is 3129 + * also set to NULL. 3130 + * - Ultimately in clean_demultiplex_info(), during the final 3131 + * teardown. 3272 3132 */ 3273 3133 get_net(net); 3274 3134 ··· 3288 3140 } 3289 3141 3290 3142 rc = bind_socket(server); 3291 - if (rc < 0) { 3292 - put_net(cifs_net_ns(server)); 3143 + if (rc < 0) 3293 3144 return rc; 3294 - } 3295 3145 3296 3146 /* 3297 3147 * Eventually check for other socket options to change from ··· 3334 3188 trace_smb3_connect_done(server->hostname, server->conn_id, &server->dstaddr); 3335 3189 if (sport == htons(RFC1001_PORT)) 3336 3190 rc = ip_rfc1001_connect(server); 3337 - 3338 - if (rc < 0) 3339 - put_net(cifs_net_ns(server)); 3340 3191 3341 3192 return rc; 3342 3193 } ··· 4124 3981 struct TCP_Server_Info *server, 4125 3982 struct nls_table *nls_info) 4126 3983 { 4127 - int rc = -ENOSYS; 3984 + int rc = 0; 4128 3985 struct TCP_Server_Info *pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; 4129 3986 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr; 4130 3987 struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr; ··· 4176 4033 if (!linuxExtEnabled) 4177 4034 ses->capabilities &= (~server->vals->cap_unix); 4178 4035 4036 + /* 4037 + * Check if the server supports specified encoding mode. 4038 + * Zero value in vals->cap_unicode indidcates that chosen 4039 + * protocol dialect does not support non-UNICODE mode. 4040 + */ 4041 + if (ses->unicode == 1 && server->vals->cap_unicode != 0 && 4042 + !(server->capabilities & server->vals->cap_unicode)) { 4043 + cifs_dbg(VFS, "Server does not support mounting in UNICODE mode\n"); 4044 + rc = -EOPNOTSUPP; 4045 + } else if (ses->unicode == 0 && server->vals->cap_unicode == 0) { 4046 + cifs_dbg(VFS, "Server does not support mounting in non-UNICODE mode\n"); 4047 + rc = -EOPNOTSUPP; 4048 + } else if (ses->unicode == 0) { 4049 + /* 4050 + * When UNICODE mode was explicitly disabled then 4051 + * do not announce client UNICODE capability. 4052 + */ 4053 + ses->capabilities &= (~server->vals->cap_unicode); 4054 + } 4055 + 4179 4056 if (ses->auth_key.response) { 4180 4057 cifs_dbg(FYI, "Free previous auth_key.response = %p\n", 4181 4058 ses->auth_key.response); ··· 4208 4045 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n", 4209 4046 server->sec_mode, server->capabilities, server->timeAdj); 4210 4047 4211 - if (server->ops->sess_setup) 4212 - rc = server->ops->sess_setup(xid, ses, server, nls_info); 4048 + if (!rc) { 4049 + if (server->ops->sess_setup) 4050 + rc = server->ops->sess_setup(xid, ses, server, nls_info); 4051 + else 4052 + rc = -ENOSYS; 4053 + } 4213 4054 4214 4055 if (rc) { 4215 4056 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); ··· 4283 4116 ctx->seal = master_tcon->seal; 4284 4117 ctx->witness = master_tcon->use_witness; 4285 4118 ctx->dfs_root_ses = master_tcon->ses->dfs_root_ses; 4119 + ctx->unicode = master_tcon->ses->unicode; 4286 4120 4287 4121 rc = cifs_set_vol_auth(ctx, master_tcon->ses); 4288 4122 if (rc) {
+1 -1
fs/smb/client/file.c
··· 3082 3082 cinode->oplock = 0; 3083 3083 } 3084 3084 3085 - if (inode && S_ISREG(inode->i_mode)) { 3085 + if (S_ISREG(inode->i_mode)) { 3086 3086 if (CIFS_CACHE_READ(cinode)) 3087 3087 break_lease(inode, O_RDONLY); 3088 3088 else
+22
fs/smb/client/fs_context.c
··· 134 134 fsparam_flag("compress", Opt_compress), 135 135 fsparam_flag("witness", Opt_witness), 136 136 fsparam_flag_no("nativesocket", Opt_nativesocket), 137 + fsparam_flag_no("unicode", Opt_unicode), 137 138 138 139 /* Mount options which take uid or gid */ 139 140 fsparam_uid("backupuid", Opt_backupuid), ··· 964 963 cifs_errorf(fc, "can not change iocharset during remount\n"); 965 964 return -EINVAL; 966 965 } 966 + if (new_ctx->unicode != old_ctx->unicode) { 967 + cifs_errorf(fc, "can not change unicode during remount\n"); 968 + return -EINVAL; 969 + } 967 970 968 971 return 0; 969 972 } ··· 1123 1118 int i, opt; 1124 1119 bool is_smb3 = !strcmp(fc->fs_type->name, "smb3"); 1125 1120 bool skip_parsing = false; 1121 + char *hostname; 1126 1122 1127 1123 cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key); 1128 1124 ··· 1449 1443 cifs_errorf(fc, "OOM when copying UNC string\n"); 1450 1444 goto cifs_parse_mount_err; 1451 1445 } 1446 + hostname = extract_hostname(ctx->UNC); 1447 + if (IS_ERR(hostname)) { 1448 + cifs_errorf(fc, "Cannot extract hostname from UNC string\n"); 1449 + goto cifs_parse_mount_err; 1450 + } 1451 + /* last byte, type, is 0x20 for servr type */ 1452 + memset(ctx->target_rfc1001_name, 0x20, RFC1001_NAME_LEN_WITH_NULL); 1453 + for (i = 0; i < RFC1001_NAME_LEN && hostname[i] != 0; i++) 1454 + ctx->target_rfc1001_name[i] = toupper(hostname[i]); 1455 + kfree(hostname); 1452 1456 break; 1453 1457 case Opt_user: 1454 1458 kfree(ctx->username); ··· 1642 1626 #endif 1643 1627 ctx->witness = true; 1644 1628 pr_warn_once("Witness protocol support is experimental\n"); 1629 + break; 1630 + case Opt_unicode: 1631 + ctx->unicode = !result.negated; 1632 + cifs_dbg(FYI, "unicode set to %d\n", ctx->unicode); 1645 1633 break; 1646 1634 case Opt_rootfs: 1647 1635 #ifndef CONFIG_CIFS_ROOT ··· 1947 1927 ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT; 1948 1928 ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT; 1949 1929 ctx->nonativesocket = 0; 1930 + 1931 + ctx->unicode = -1; /* autodetect, but prefer UNICODE mode */ 1950 1932 1951 1933 /* 1952 1934 * short int override_uid = -1;
+2
fs/smb/client/fs_context.h
··· 135 135 Opt_witness, 136 136 Opt_is_upcall_target_mount, 137 137 Opt_is_upcall_target_application, 138 + Opt_unicode, 138 139 139 140 /* Mount options which take numeric value */ 140 141 Opt_backupuid, ··· 307 306 bool compress; /* enable SMB2 messages (READ/WRITE) de/compression */ 308 307 bool rootfs:1; /* if it's a SMB root file system */ 309 308 bool witness:1; /* use witness protocol */ 309 + int unicode; 310 310 char *leaf_fullpath; 311 311 struct cifs_ses *dfs_root_ses; 312 312 bool dfs_automount:1; /* set for dfs automount only */
+2 -1
fs/smb/client/link.c
··· 643 643 case CIFS_SYMLINK_TYPE_NATIVE: 644 644 case CIFS_SYMLINK_TYPE_NFS: 645 645 case CIFS_SYMLINK_TYPE_WSL: 646 - if (server->ops->create_reparse_symlink) { 646 + if (server->ops->create_reparse_symlink && 647 + (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) { 647 648 rc = server->ops->create_reparse_symlink(xid, inode, 648 649 direntry, 649 650 pTcon,
+9 -1
fs/smb/client/sess.c
··· 242 242 243 243 iface->num_channels++; 244 244 iface->weight_fulfilled++; 245 - cifs_dbg(VFS, "successfully opened new channel on iface:%pIS\n", 245 + cifs_info("successfully opened new channel on iface:%pIS\n", 246 246 &iface->sockaddr); 247 247 break; 248 248 } ··· 501 501 ctx->password = ses->password; 502 502 ctx->sectype = ses->sectype; 503 503 ctx->sign = ses->sign; 504 + ctx->unicode = ses->unicode; 504 505 505 506 /* UNC and paths */ 506 507 /* XXX: Use ses->server->hostname? */ ··· 523 522 ctx->sockopt_tcp_nodelay = ses->server->tcp_nodelay; 524 523 ctx->echo_interval = ses->server->echo_interval / HZ; 525 524 ctx->max_credits = ses->server->max_credits; 525 + ctx->min_offload = ses->server->min_offload; 526 + ctx->compress = ses->server->compression.requested; 527 + ctx->dfs_conn = ses->server->dfs_conn; 528 + ctx->ignore_signature = ses->server->ignore_signature; 529 + ctx->leaf_fullpath = ses->server->leaf_fullpath; 530 + ctx->rootfs = ses->server->noblockcnt; 531 + ctx->retrans = ses->server->retrans; 526 532 527 533 /* 528 534 * This will be used for encoding/decoding user/domain/pw
+1
fs/smb/client/smb1ops.c
··· 1170 1170 .cap_unix = CAP_UNIX, 1171 1171 .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND, 1172 1172 .cap_large_files = CAP_LARGE_FILES, 1173 + .cap_unicode = CAP_UNICODE, 1173 1174 .signing_enabled = SECMODE_SIGN_ENABLED, 1174 1175 .signing_required = SECMODE_SIGN_REQUIRED, 1175 1176 };
+8
fs/smb/client/smb2inode.c
··· 1273 1273 int rc; 1274 1274 int i; 1275 1275 1276 + /* 1277 + * If server filesystem does not support reparse points then do not 1278 + * attempt to create reparse point. This will prevent creating unusable 1279 + * empty object on the server. 1280 + */ 1281 + if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) 1282 + return ERR_PTR(-EOPNOTSUPP); 1283 + 1276 1284 oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, 1277 1285 SYNCHRONIZE | DELETE | 1278 1286 FILE_READ_ATTRIBUTES |
+5 -4
fs/smb/client/smb2misc.c
··· 816 816 WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); 817 817 spin_unlock(&cifs_tcp_ses_lock); 818 818 819 - if (tcon->ses) 819 + if (tcon->ses) { 820 820 server = tcon->ses->server; 821 - 822 - cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n", 823 - tcon->tid, persistent_fid, volatile_fid); 821 + cifs_server_dbg(FYI, 822 + "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n", 823 + tcon->tid, persistent_fid, volatile_fid); 824 + } 824 825 825 826 return 0; 826 827 }
+3 -3
fs/smb/client/smb2ops.c
··· 969 969 if (islink) 970 970 rc = -EREMOTE; 971 971 } 972 - if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb && 972 + if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && 973 973 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)) 974 974 rc = -EOPNOTSUPP; 975 975 goto out; ··· 5229 5229 const char *full_path, umode_t mode, dev_t dev) 5230 5230 { 5231 5231 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 5232 - int rc; 5232 + int rc = -EOPNOTSUPP; 5233 5233 5234 5234 /* 5235 5235 * Check if mounted with mount parm 'sfu' mount parm. ··· 5240 5240 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { 5241 5241 rc = cifs_sfu_make_node(xid, inode, dentry, tcon, 5242 5242 full_path, mode, dev); 5243 - } else { 5243 + } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) { 5244 5244 rc = smb2_mknod_reparse(xid, inode, dentry, tcon, 5245 5245 full_path, mode, dev); 5246 5246 }
+1 -3
fs/smb/client/smb2pdu.c
··· 3916 3916 u64 persistent_fid, u64 volatile_fid, 3917 3917 void **data, u32 *plen, u32 extra_info) 3918 3918 { 3919 - __u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | 3920 - extra_info; 3921 3919 *plen = 0; 3922 3920 3923 3921 return query_info(xid, tcon, persistent_fid, volatile_fid, 3924 - 0, SMB2_O_INFO_SECURITY, additional_info, 3922 + 0, SMB2_O_INFO_SECURITY, extra_info, 3925 3923 SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen); 3926 3924 } 3927 3925
+1 -1
fs/smb/client/transport.c
··· 179 179 * Our basic "send data to server" function. Should be called with srv_mutex 180 180 * held. The caller is responsible for handling the results. 181 181 */ 182 - static int 182 + int 183 183 smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, 184 184 size_t *sent) 185 185 {
+11 -4
fs/smb/client/xattr.c
··· 320 320 if (pTcon->ses->server->ops->get_acl == NULL) 321 321 goto out; /* rc already EOPNOTSUPP */ 322 322 323 - if (handler->flags == XATTR_CIFS_NTSD_FULL) { 324 - extra_info = SACL_SECINFO; 325 - } else { 326 - extra_info = 0; 323 + switch (handler->flags) { 324 + case XATTR_CIFS_NTSD_FULL: 325 + extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | SACL_SECINFO; 326 + break; 327 + case XATTR_CIFS_NTSD: 328 + extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO; 329 + break; 330 + case XATTR_CIFS_ACL: 331 + default: 332 + extra_info = DACL_SECINFO; 333 + break; 327 334 } 328 335 pacl = pTcon->ses->server->ops->get_acl(cifs_sb, 329 336 inode, full_path, &acllen, extra_info);