mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 12:35:52 +02:00
14 smb3/cifs client fixes and minor update to maintainers file
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmfpzSUACgkQiiy9cAdy T1GTHQwAhjeBIlGw2kaJDHBn32BDSpmw7r4D6gGUU+cv4sL4O2flRaDmshpGvO3r vgUxI8VFwLRvPem7QHr9aseFBIu6jQwWzI2tgkq+XW4LeyRtcgWff8dT8bQPc3b9 t/z1wAqZhlr8MY5mma+aHjWsdRZNYzMWNFSWURpDylqhhNFxUbl/u24RF08VG+It bqBi+RyNIX2u0jHAuSUKUW0xFImp+YSEqg/TqYw10vZ4ChtfYtCX5YcbQNHls2XE IA7p0uOfFLrLmTmmw95A8rLtDlREb9rLcD2bLeBR2qFGnbrZFvCg917S0WchTU58 P2UnKAZJqEhnMBefuXZ/LGKju5bnLAV6YGl/lKPf53UE71C9r5zBID3YgeweKiYS aWEjlY/FeC/Gb7iniRDBWE2BCaI6Sp7y/CmLucy58xrGhpPoXlliDj2FRCWWAFi4 zk2rCempLa+uiIbIQReLclWbxA/ysqMJLwbtEKGa/le45LdtxAKkiTNLJ3MQciwd s6+i344q =Mjh/ -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
8b175e2e18
|
|
@ -12905,8 +12905,8 @@ F: tools/testing/selftests/
|
|||
KERNEL SMB3 SERVER (KSMBD)
|
||||
M: Namjae Jeon <linkinjeon@kernel.org>
|
||||
M: Namjae Jeon <linkinjeon@samba.org>
|
||||
M: Steve French <sfrench@samba.org>
|
||||
M: Steve French <smfrench@gmail.com>
|
||||
M: Steve French <sfrench@samba.org>
|
||||
R: Sergey Senozhatsky <senozhatsky@chromium.org>
|
||||
R: Tom Talpey <tom@talpey.com>
|
||||
L: linux-cifs@vger.kernel.org
|
||||
|
|
|
|||
|
|
@ -811,7 +811,23 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
|||
return;
|
||||
|
||||
for (i = 0; i < num_aces; ++i) {
|
||||
if (end_of_acl - acl_base < acl_size)
|
||||
break;
|
||||
|
||||
ppace[i] = (struct smb_ace *) (acl_base + acl_size);
|
||||
acl_base = (char *)ppace[i];
|
||||
acl_size = offsetof(struct smb_ace, sid) +
|
||||
offsetof(struct smb_sid, sub_auth);
|
||||
|
||||
if (end_of_acl - acl_base < acl_size ||
|
||||
ppace[i]->sid.num_subauth == 0 ||
|
||||
ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
|
||||
(end_of_acl - acl_base <
|
||||
acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
|
||||
(le16_to_cpu(ppace[i]->size) <
|
||||
acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth))
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
dump_ace(ppace[i], end_of_acl);
|
||||
#endif
|
||||
|
|
@ -855,7 +871,6 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
|||
(void *)ppace[i],
|
||||
sizeof(struct smb_ace)); */
|
||||
|
||||
acl_base = (char *)ppace[i];
|
||||
acl_size = le16_to_cpu(ppace[i]->size);
|
||||
}
|
||||
|
||||
|
|
@ -1550,7 +1565,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
|||
int rc = 0;
|
||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||
struct smb_version_operations *ops;
|
||||
const u32 info = 0;
|
||||
const u32 info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO;
|
||||
|
||||
cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
|
||||
|
||||
|
|
@ -1604,7 +1619,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
|||
struct tcon_link *tlink;
|
||||
struct smb_version_operations *ops;
|
||||
bool mode_from_sid, id_from_sid;
|
||||
const u32 info = 0;
|
||||
const u32 info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO;
|
||||
bool posix;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
|
|
|
|||
|
|
@ -637,6 +637,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
|||
cifs_sb->ctx->dir_mode);
|
||||
if (cifs_sb->ctx->iocharset)
|
||||
seq_printf(s, ",iocharset=%s", cifs_sb->ctx->iocharset);
|
||||
if (tcon->ses->unicode == 0)
|
||||
seq_puts(s, ",nounicode");
|
||||
else if (tcon->ses->unicode == 1)
|
||||
seq_puts(s, ",unicode");
|
||||
if (tcon->seal)
|
||||
seq_puts(s, ",seal");
|
||||
else if (tcon->ses->server->ignore_signature)
|
||||
|
|
|
|||
|
|
@ -653,6 +653,7 @@ struct smb_version_values {
|
|||
unsigned int cap_unix;
|
||||
unsigned int cap_nt_find;
|
||||
unsigned int cap_large_files;
|
||||
unsigned int cap_unicode;
|
||||
__u16 signing_enabled;
|
||||
__u16 signing_required;
|
||||
size_t create_lease_size;
|
||||
|
|
@ -1120,6 +1121,7 @@ struct cifs_ses {
|
|||
bool sign; /* is signing required? */
|
||||
bool domainAuto:1;
|
||||
bool expired_pwd; /* track if access denied or expired pwd so can know if need to update */
|
||||
int unicode;
|
||||
unsigned int flags;
|
||||
__u16 session_flags;
|
||||
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ extern void cifs_small_buf_release(void *);
|
|||
extern void free_rsp_buf(int, void *);
|
||||
extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
|
||||
unsigned int /* length */);
|
||||
extern int smb_send_kvec(struct TCP_Server_Info *server,
|
||||
struct msghdr *msg,
|
||||
size_t *sent);
|
||||
extern unsigned int _get_xid(void);
|
||||
extern void _free_xid(unsigned int);
|
||||
#define get_xid() \
|
||||
|
|
@ -592,7 +595,6 @@ int cifs_async_readv(struct cifs_io_subrequest *rdata);
|
|||
int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid);
|
||||
|
||||
void cifs_async_writev(struct cifs_io_subrequest *wdata);
|
||||
void cifs_writev_complete(struct work_struct *work);
|
||||
int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
const unsigned char *path, char *pbuf,
|
||||
|
|
|
|||
|
|
@ -437,7 +437,10 @@ CIFSSMBNegotiate(const unsigned int xid,
|
|||
return rc;
|
||||
|
||||
pSMB->hdr.Mid = get_next_mid(server);
|
||||
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
|
||||
pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
|
||||
|
||||
if (ses->unicode != 0)
|
||||
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
||||
|
||||
if (should_set_ext_sec_flag(ses->sectype)) {
|
||||
cifs_dbg(FYI, "Requesting extended security\n");
|
||||
|
|
@ -2709,6 +2712,9 @@ int cifs_query_reparse_point(const unsigned int xid,
|
|||
if (cap_unix(tcon->ses))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
oparms = (struct cifs_open_parms) {
|
||||
.tcon = tcon,
|
||||
.cifs_sb = cifs_sb,
|
||||
|
|
@ -3400,8 +3406,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
|
|||
/* BB TEST with big acls that might need to be e.g. larger than 16K */
|
||||
pSMB->MaxSetupCount = 0;
|
||||
pSMB->Fid = fid; /* file handle always le */
|
||||
pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
|
||||
CIFS_ACL_DACL | info);
|
||||
pSMB->AclFlags = cpu_to_le32(info);
|
||||
pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
|
||||
inc_rfc1001_len(pSMB, 11);
|
||||
iov[0].iov_base = (char *)pSMB;
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ cifs_abort_connection(struct TCP_Server_Info *server)
|
|||
server->ssocket->flags);
|
||||
sock_release(server->ssocket);
|
||||
server->ssocket = NULL;
|
||||
put_net(cifs_net_ns(server));
|
||||
}
|
||||
server->sequence_number = 0;
|
||||
server->session_estab = false;
|
||||
|
|
@ -1676,6 +1677,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
|
|||
/* Grab netns reference for this server. */
|
||||
cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
|
||||
|
||||
tcp_ses->sign = ctx->sign;
|
||||
tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId);
|
||||
tcp_ses->noblockcnt = ctx->rootfs;
|
||||
tcp_ses->noblocksnd = ctx->noblocksnd || ctx->rootfs;
|
||||
|
|
@ -2349,6 +2351,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|||
ses->cred_uid = ctx->cred_uid;
|
||||
ses->linux_uid = ctx->linux_uid;
|
||||
|
||||
ses->unicode = ctx->unicode;
|
||||
ses->sectype = ctx->sectype;
|
||||
ses->sign = ctx->sign;
|
||||
|
||||
|
|
@ -3025,6 +3028,44 @@ bind_socket(struct TCP_Server_Info *server)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
smb_recv_kvec(struct TCP_Server_Info *server, struct msghdr *msg, size_t *recv)
|
||||
{
|
||||
int rc = 0;
|
||||
int retries = 0;
|
||||
int msg_flags = server->noblocksnd ? MSG_DONTWAIT : 0;
|
||||
|
||||
*recv = 0;
|
||||
|
||||
while (msg_data_left(msg)) {
|
||||
rc = sock_recvmsg(server->ssocket, msg, msg_flags);
|
||||
if (rc == -EAGAIN) {
|
||||
retries++;
|
||||
if (retries >= 14 ||
|
||||
(!server->noblocksnd && (retries > 2))) {
|
||||
cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
|
||||
server->ssocket);
|
||||
return -EAGAIN;
|
||||
}
|
||||
msleep(1 << retries);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (rc == 0) {
|
||||
cifs_dbg(FYI, "Received no data (TCP RST)\n");
|
||||
return -ECONNABORTED;
|
||||
}
|
||||
|
||||
/* recv was at least partially successful */
|
||||
*recv += rc;
|
||||
retries = 0; /* in case we get ENOSPC on the next send */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ip_rfc1001_connect(struct TCP_Server_Info *server)
|
||||
{
|
||||
|
|
@ -3035,8 +3076,12 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
|
|||
* sessinit is sent but no second negprot
|
||||
*/
|
||||
struct rfc1002_session_packet req = {};
|
||||
struct smb_hdr *smb_buf = (struct smb_hdr *)&req;
|
||||
struct rfc1002_session_packet resp = {};
|
||||
struct msghdr msg = {};
|
||||
struct kvec iov = {};
|
||||
unsigned int len;
|
||||
size_t sent;
|
||||
size_t recv;
|
||||
|
||||
req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name);
|
||||
|
||||
|
|
@ -3065,19 +3110,118 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
|
|||
* As per rfc1002, @len must be the number of bytes that follows the
|
||||
* length field of a rfc1002 session request payload.
|
||||
*/
|
||||
len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req);
|
||||
len = sizeof(req.trailer.session_req);
|
||||
req.type = RFC1002_SESSION_REQUEST;
|
||||
req.flags = 0;
|
||||
req.length = cpu_to_be16(len);
|
||||
len += offsetof(typeof(req), trailer.session_req);
|
||||
iov.iov_base = &req;
|
||||
iov.iov_len = len;
|
||||
iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, len);
|
||||
rc = smb_send_kvec(server, &msg, &sent);
|
||||
if (rc < 0 || len != sent)
|
||||
return (rc == -EINTR || rc == -EAGAIN) ? rc : -ECONNABORTED;
|
||||
|
||||
smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len);
|
||||
rc = smb_send(server, smb_buf, len);
|
||||
/*
|
||||
* RFC1001 layer in at least one server requires very short break before
|
||||
* negprot presumably because not expecting negprot to follow so fast.
|
||||
* This is a simple solution that works without complicating the code
|
||||
* and causes no significant slowing down on mount for everyone else
|
||||
* For example DOS SMB servers cannot process negprot if it was received
|
||||
* before the server sent response for SESSION_REQUEST packet. So, wait
|
||||
* for the response, read it and parse it as it can contain useful error
|
||||
* information (e.g. specified server name was incorrect). For example
|
||||
* even the latest Windows Server 2022 SMB1 server over port 139 send
|
||||
* error if its server name was in SESSION_REQUEST packet incorrect.
|
||||
* Nowadays usage of port 139 is not common, so waiting for reply here
|
||||
* does not slowing down mounting of common case (over port 445).
|
||||
*/
|
||||
usleep_range(1000, 2000);
|
||||
len = offsetof(typeof(resp), trailer);
|
||||
iov.iov_base = &resp;
|
||||
iov.iov_len = len;
|
||||
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, len);
|
||||
rc = smb_recv_kvec(server, &msg, &recv);
|
||||
if (rc < 0 || recv != len)
|
||||
return (rc == -EINTR || rc == -EAGAIN) ? rc : -ECONNABORTED;
|
||||
|
||||
return rc;
|
||||
switch (resp.type) {
|
||||
case RFC1002_POSITIVE_SESSION_RESPONSE:
|
||||
if (be16_to_cpu(resp.length) != 0) {
|
||||
cifs_dbg(VFS, "RFC 1002 positive session response but with invalid non-zero length %u\n",
|
||||
be16_to_cpu(resp.length));
|
||||
return -EIO;
|
||||
}
|
||||
cifs_dbg(FYI, "RFC 1002 positive session response");
|
||||
break;
|
||||
case RFC1002_NEGATIVE_SESSION_RESPONSE:
|
||||
/* Read RFC1002 response error code and convert it to errno in rc */
|
||||
len = sizeof(resp.trailer.neg_ses_resp_error_code);
|
||||
iov.iov_base = &resp.trailer.neg_ses_resp_error_code;
|
||||
iov.iov_len = len;
|
||||
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, len);
|
||||
if (be16_to_cpu(resp.length) == len &&
|
||||
smb_recv_kvec(server, &msg, &recv) == 0 &&
|
||||
recv == len) {
|
||||
cifs_dbg(VFS, "RFC 1002 negative session response with error 0x%x\n",
|
||||
resp.trailer.neg_ses_resp_error_code);
|
||||
switch (resp.trailer.neg_ses_resp_error_code) {
|
||||
case RFC1002_NOT_LISTENING_CALLED:
|
||||
/* server does not listen for specified server name */
|
||||
fallthrough;
|
||||
case RFC1002_NOT_PRESENT:
|
||||
/* server name is incorrect */
|
||||
rc = -ENOENT;
|
||||
cifs_dbg(VFS, "Server rejected NetBIOS servername %.15s\n",
|
||||
server->server_RFC1001_name[0] ?
|
||||
server->server_RFC1001_name :
|
||||
DEFAULT_CIFS_CALLED_NAME);
|
||||
cifs_dbg(VFS, "Specify correct NetBIOS servername in source path or with -o servern= option\n");
|
||||
break;
|
||||
case RFC1002_NOT_LISTENING_CALLING:
|
||||
/* client name was not accepted by server */
|
||||
rc = -EACCES;
|
||||
cifs_dbg(VFS, "Server rejected NetBIOS clientname %.15s\n",
|
||||
server->workstation_RFC1001_name[0] ?
|
||||
server->workstation_RFC1001_name :
|
||||
"LINUX_CIFS_CLNT");
|
||||
cifs_dbg(VFS, "Specify correct NetBIOS clientname with -o netbiosname= option\n");
|
||||
break;
|
||||
case RFC1002_INSUFFICIENT_RESOURCE:
|
||||
/* remote server resource error */
|
||||
rc = -EREMOTEIO;
|
||||
break;
|
||||
case RFC1002_UNSPECIFIED_ERROR:
|
||||
default:
|
||||
/* other/unknown error */
|
||||
rc = -EIO;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cifs_dbg(VFS, "RFC 1002 negative session response\n");
|
||||
rc = -EIO;
|
||||
}
|
||||
return rc;
|
||||
case RFC1002_RETARGET_SESSION_RESPONSE:
|
||||
cifs_dbg(VFS, "RFC 1002 retarget session response\n");
|
||||
if (be16_to_cpu(resp.length) == sizeof(resp.trailer.retarget_resp)) {
|
||||
len = sizeof(resp.trailer.retarget_resp);
|
||||
iov.iov_base = &resp.trailer.retarget_resp;
|
||||
iov.iov_len = len;
|
||||
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, len);
|
||||
if (smb_recv_kvec(server, &msg, &recv) == 0 && recv == len) {
|
||||
cifs_dbg(VFS, "Server wants to redirect connection\n");
|
||||
cifs_dbg(VFS, "Remount with options -o ip=%pI4,port=%u\n",
|
||||
&resp.trailer.retarget_resp.retarget_ip_addr,
|
||||
be16_to_cpu(resp.trailer.retarget_resp.port));
|
||||
}
|
||||
}
|
||||
cifs_dbg(VFS, "Closing connection\n");
|
||||
/* FIXME: Should we automatically redirect to new retarget_resp server? */
|
||||
return -EMULTIHOP;
|
||||
default:
|
||||
cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", resp.type);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -3123,8 +3267,12 @@ generic_ip_connect(struct TCP_Server_Info *server)
|
|||
/*
|
||||
* Grab netns reference for the socket.
|
||||
*
|
||||
* It'll be released here, on error, or in clean_demultiplex_info() upon server
|
||||
* teardown.
|
||||
* This reference will be released in several situations:
|
||||
* - In the failure path before the cifsd thread is started.
|
||||
* - In the all place where server->socket is released, it is
|
||||
* also set to NULL.
|
||||
* - Ultimately in clean_demultiplex_info(), during the final
|
||||
* teardown.
|
||||
*/
|
||||
get_net(net);
|
||||
|
||||
|
|
@ -3140,10 +3288,8 @@ generic_ip_connect(struct TCP_Server_Info *server)
|
|||
}
|
||||
|
||||
rc = bind_socket(server);
|
||||
if (rc < 0) {
|
||||
put_net(cifs_net_ns(server));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Eventually check for other socket options to change from
|
||||
|
|
@ -3189,9 +3335,6 @@ generic_ip_connect(struct TCP_Server_Info *server)
|
|||
if (sport == htons(RFC1001_PORT))
|
||||
rc = ip_rfc1001_connect(server);
|
||||
|
||||
if (rc < 0)
|
||||
put_net(cifs_net_ns(server));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -3981,7 +4124,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
|||
struct TCP_Server_Info *server,
|
||||
struct nls_table *nls_info)
|
||||
{
|
||||
int rc = -ENOSYS;
|
||||
int rc = 0;
|
||||
struct TCP_Server_Info *pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr;
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr;
|
||||
|
|
@ -4033,6 +4176,26 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
|||
if (!linuxExtEnabled)
|
||||
ses->capabilities &= (~server->vals->cap_unix);
|
||||
|
||||
/*
|
||||
* Check if the server supports specified encoding mode.
|
||||
* Zero value in vals->cap_unicode indidcates that chosen
|
||||
* protocol dialect does not support non-UNICODE mode.
|
||||
*/
|
||||
if (ses->unicode == 1 && server->vals->cap_unicode != 0 &&
|
||||
!(server->capabilities & server->vals->cap_unicode)) {
|
||||
cifs_dbg(VFS, "Server does not support mounting in UNICODE mode\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
} else if (ses->unicode == 0 && server->vals->cap_unicode == 0) {
|
||||
cifs_dbg(VFS, "Server does not support mounting in non-UNICODE mode\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
} else if (ses->unicode == 0) {
|
||||
/*
|
||||
* When UNICODE mode was explicitly disabled then
|
||||
* do not announce client UNICODE capability.
|
||||
*/
|
||||
ses->capabilities &= (~server->vals->cap_unicode);
|
||||
}
|
||||
|
||||
if (ses->auth_key.response) {
|
||||
cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
|
||||
ses->auth_key.response);
|
||||
|
|
@ -4045,8 +4208,12 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
|||
cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
|
||||
server->sec_mode, server->capabilities, server->timeAdj);
|
||||
|
||||
if (server->ops->sess_setup)
|
||||
rc = server->ops->sess_setup(xid, ses, server, nls_info);
|
||||
if (!rc) {
|
||||
if (server->ops->sess_setup)
|
||||
rc = server->ops->sess_setup(xid, ses, server, nls_info);
|
||||
else
|
||||
rc = -ENOSYS;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
|
||||
|
|
@ -4116,6 +4283,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
|
|||
ctx->seal = master_tcon->seal;
|
||||
ctx->witness = master_tcon->use_witness;
|
||||
ctx->dfs_root_ses = master_tcon->ses->dfs_root_ses;
|
||||
ctx->unicode = master_tcon->ses->unicode;
|
||||
|
||||
rc = cifs_set_vol_auth(ctx, master_tcon->ses);
|
||||
if (rc) {
|
||||
|
|
|
|||
|
|
@ -3082,7 +3082,7 @@ void cifs_oplock_break(struct work_struct *work)
|
|||
cinode->oplock = 0;
|
||||
}
|
||||
|
||||
if (inode && S_ISREG(inode->i_mode)) {
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
if (CIFS_CACHE_READ(cinode))
|
||||
break_lease(inode, O_RDONLY);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
|
|||
fsparam_flag("compress", Opt_compress),
|
||||
fsparam_flag("witness", Opt_witness),
|
||||
fsparam_flag_no("nativesocket", Opt_nativesocket),
|
||||
fsparam_flag_no("unicode", Opt_unicode),
|
||||
|
||||
/* Mount options which take uid or gid */
|
||||
fsparam_uid("backupuid", Opt_backupuid),
|
||||
|
|
@ -963,6 +964,10 @@ static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
|
|||
cifs_errorf(fc, "can not change iocharset during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->unicode != old_ctx->unicode) {
|
||||
cifs_errorf(fc, "can not change unicode during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1118,6 +1123,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
|||
int i, opt;
|
||||
bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
|
||||
bool skip_parsing = false;
|
||||
char *hostname;
|
||||
|
||||
cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
|
||||
|
||||
|
|
@ -1443,6 +1449,16 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
|||
cifs_errorf(fc, "OOM when copying UNC string\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
hostname = extract_hostname(ctx->UNC);
|
||||
if (IS_ERR(hostname)) {
|
||||
cifs_errorf(fc, "Cannot extract hostname from UNC string\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
/* last byte, type, is 0x20 for servr type */
|
||||
memset(ctx->target_rfc1001_name, 0x20, RFC1001_NAME_LEN_WITH_NULL);
|
||||
for (i = 0; i < RFC1001_NAME_LEN && hostname[i] != 0; i++)
|
||||
ctx->target_rfc1001_name[i] = toupper(hostname[i]);
|
||||
kfree(hostname);
|
||||
break;
|
||||
case Opt_user:
|
||||
kfree(ctx->username);
|
||||
|
|
@ -1627,6 +1643,10 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
|||
ctx->witness = true;
|
||||
pr_warn_once("Witness protocol support is experimental\n");
|
||||
break;
|
||||
case Opt_unicode:
|
||||
ctx->unicode = !result.negated;
|
||||
cifs_dbg(FYI, "unicode set to %d\n", ctx->unicode);
|
||||
break;
|
||||
case Opt_rootfs:
|
||||
#ifndef CONFIG_CIFS_ROOT
|
||||
cifs_dbg(VFS, "rootfs support requires CONFIG_CIFS_ROOT config option\n");
|
||||
|
|
@ -1928,6 +1948,8 @@ int smb3_init_fs_context(struct fs_context *fc)
|
|||
ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT;
|
||||
ctx->nonativesocket = 0;
|
||||
|
||||
ctx->unicode = -1; /* autodetect, but prefer UNICODE mode */
|
||||
|
||||
/*
|
||||
* short int override_uid = -1;
|
||||
* short int override_gid = -1;
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ enum cifs_param {
|
|||
Opt_witness,
|
||||
Opt_is_upcall_target_mount,
|
||||
Opt_is_upcall_target_application,
|
||||
Opt_unicode,
|
||||
|
||||
/* Mount options which take numeric value */
|
||||
Opt_backupuid,
|
||||
|
|
@ -306,6 +307,7 @@ struct smb3_fs_context {
|
|||
bool compress; /* enable SMB2 messages (READ/WRITE) de/compression */
|
||||
bool rootfs:1; /* if it's a SMB root file system */
|
||||
bool witness:1; /* use witness protocol */
|
||||
int unicode;
|
||||
char *leaf_fullpath;
|
||||
struct cifs_ses *dfs_root_ses;
|
||||
bool dfs_automount:1; /* set for dfs automount only */
|
||||
|
|
|
|||
|
|
@ -643,7 +643,8 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
|
|||
case CIFS_SYMLINK_TYPE_NATIVE:
|
||||
case CIFS_SYMLINK_TYPE_NFS:
|
||||
case CIFS_SYMLINK_TYPE_WSL:
|
||||
if (server->ops->create_reparse_symlink) {
|
||||
if (server->ops->create_reparse_symlink &&
|
||||
(le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) {
|
||||
rc = server->ops->create_reparse_symlink(xid, inode,
|
||||
direntry,
|
||||
pTcon,
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
|
|||
|
||||
iface->num_channels++;
|
||||
iface->weight_fulfilled++;
|
||||
cifs_dbg(VFS, "successfully opened new channel on iface:%pIS\n",
|
||||
cifs_info("successfully opened new channel on iface:%pIS\n",
|
||||
&iface->sockaddr);
|
||||
break;
|
||||
}
|
||||
|
|
@ -501,6 +501,7 @@ cifs_ses_add_channel(struct cifs_ses *ses,
|
|||
ctx->password = ses->password;
|
||||
ctx->sectype = ses->sectype;
|
||||
ctx->sign = ses->sign;
|
||||
ctx->unicode = ses->unicode;
|
||||
|
||||
/* UNC and paths */
|
||||
/* XXX: Use ses->server->hostname? */
|
||||
|
|
@ -522,6 +523,13 @@ cifs_ses_add_channel(struct cifs_ses *ses,
|
|||
ctx->sockopt_tcp_nodelay = ses->server->tcp_nodelay;
|
||||
ctx->echo_interval = ses->server->echo_interval / HZ;
|
||||
ctx->max_credits = ses->server->max_credits;
|
||||
ctx->min_offload = ses->server->min_offload;
|
||||
ctx->compress = ses->server->compression.requested;
|
||||
ctx->dfs_conn = ses->server->dfs_conn;
|
||||
ctx->ignore_signature = ses->server->ignore_signature;
|
||||
ctx->leaf_fullpath = ses->server->leaf_fullpath;
|
||||
ctx->rootfs = ses->server->noblockcnt;
|
||||
ctx->retrans = ses->server->retrans;
|
||||
|
||||
/*
|
||||
* This will be used for encoding/decoding user/domain/pw
|
||||
|
|
|
|||
|
|
@ -1170,6 +1170,7 @@ struct smb_version_values smb1_values = {
|
|||
.cap_unix = CAP_UNIX,
|
||||
.cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
|
||||
.cap_large_files = CAP_LARGE_FILES,
|
||||
.cap_unicode = CAP_UNICODE,
|
||||
.signing_enabled = SECMODE_SIGN_ENABLED,
|
||||
.signing_required = SECMODE_SIGN_REQUIRED,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1273,6 +1273,14 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
|
|||
int rc;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* If server filesystem does not support reparse points then do not
|
||||
* attempt to create reparse point. This will prevent creating unusable
|
||||
* empty object on the server.
|
||||
*/
|
||||
if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
|
||||
SYNCHRONIZE | DELETE |
|
||||
FILE_READ_ATTRIBUTES |
|
||||
|
|
|
|||
|
|
@ -816,11 +816,12 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
|
|||
WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
if (tcon->ses)
|
||||
if (tcon->ses) {
|
||||
server = tcon->ses->server;
|
||||
|
||||
cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n",
|
||||
tcon->tid, persistent_fid, volatile_fid);
|
||||
cifs_server_dbg(FYI,
|
||||
"tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n",
|
||||
tcon->tid, persistent_fid, volatile_fid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -969,7 +969,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
if (islink)
|
||||
rc = -EREMOTE;
|
||||
}
|
||||
if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb &&
|
||||
if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) &&
|
||||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS))
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
|
|
@ -5229,7 +5229,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
|
|||
const char *full_path, umode_t mode, dev_t dev)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
int rc;
|
||||
int rc = -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* Check if mounted with mount parm 'sfu' mount parm.
|
||||
|
|
@ -5240,7 +5240,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
|
|||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
rc = cifs_sfu_make_node(xid, inode, dentry, tcon,
|
||||
full_path, mode, dev);
|
||||
} else {
|
||||
} else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
|
||||
rc = smb2_mknod_reparse(xid, inode, dentry, tcon,
|
||||
full_path, mode, dev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3916,12 +3916,10 @@ SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
u64 persistent_fid, u64 volatile_fid,
|
||||
void **data, u32 *plen, u32 extra_info)
|
||||
{
|
||||
__u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
|
||||
extra_info;
|
||||
*plen = 0;
|
||||
|
||||
return query_info(xid, tcon, persistent_fid, volatile_fid,
|
||||
0, SMB2_O_INFO_SECURITY, additional_info,
|
||||
0, SMB2_O_INFO_SECURITY, extra_info,
|
||||
SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ delete_mid(struct mid_q_entry *mid)
|
|||
* Our basic "send data to server" function. Should be called with srv_mutex
|
||||
* held. The caller is responsible for handling the results.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
|
||||
size_t *sent)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -320,10 +320,17 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
|
|||
if (pTcon->ses->server->ops->get_acl == NULL)
|
||||
goto out; /* rc already EOPNOTSUPP */
|
||||
|
||||
if (handler->flags == XATTR_CIFS_NTSD_FULL) {
|
||||
extra_info = SACL_SECINFO;
|
||||
} else {
|
||||
extra_info = 0;
|
||||
switch (handler->flags) {
|
||||
case XATTR_CIFS_NTSD_FULL:
|
||||
extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | SACL_SECINFO;
|
||||
break;
|
||||
case XATTR_CIFS_NTSD:
|
||||
extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO;
|
||||
break;
|
||||
case XATTR_CIFS_ACL:
|
||||
default:
|
||||
extra_info = DACL_SECINFO;
|
||||
break;
|
||||
}
|
||||
pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
|
||||
inode, full_path, &acllen, extra_info);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user