mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
15 cifs client fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmVFoW8ACgkQiiy9cAdy T1HFtQwAvvJH7wsCuN/QYCMPbXJ150fgmgMs+FJeq/gMRJaRjeFLpR9NfO6DAYbA NraRyfoinxvBkftXVQkDUKn0xSdxz1JEZodq08+kvEZyIQp5z9Q5NTsSF4loyMlg jtRM6UtkiFmsaRrbLL+EguZiQkhV8/SyGtojxn5jozubXUZS1+llMZk56MbOxIdY RRGjndlxRxtJWP/xCHLwnGF7wRWqeiQhNPml1DoEVo2LOZK7OTqZP5cckwusj0YR nAaSffn3U2v5tVPOpHMZIZbAcRIawRTjv6CT+hMH5/9k1JOy4vc8Y92uiO7DLx2O uoI4fOs9hX3yWvJCe9QExvOjvmtWaAY8uhI8dGEo2mWvRQqdPBGcrVXpUqbVY1r0 ffb6N+CJ5VZmbgIi57+3FUU2YuJnIxyWj0uQCJr7Q6E9sZiHx2IZ2Y3Yck5yy6Bk ZsZLQcB5xQiosCjt2xR9UmXv/bUCH3TwCY/TUPARkf+QQCo58DQokczy0UtEffzB rLxedNQz =zu9T -----END PGP SIGNATURE----- Merge tag '6.7-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6 Pull smb client updates from Steve French: - use after free fixes and deadlock fix - symlink timestamp fix - hashing perf improvement - multichannel fixes - minor debugging improvements - fix creating fifos when using "sfu" mounts - NTLMSSP authentication improvement - minor fixes to include some missing create flags and structures from recently updated protocol documentation * tag '6.7-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: cifs: force interface update before a fresh session setup cifs: do not reset chan_max if multichannel is not supported at mount cifs: reconnect helper should set reconnect for the right channel smb: client: fix use-after-free in smb2_query_info_compound() smb: client: remove extra @chan_count check in __cifs_put_smb_ses() cifs: add xid to query server interface call cifs: print server capabilities in DebugData smb: use crypto_shash_digest() in symlink_hash() smb: client: fix use-after-free bug in cifs_debug_data_proc_show() smb: client: fix potential deadlock when releasing mids smb3: fix creating FIFOs when mounting with "sfu" mount option Add definition for new smb3.1.1 command type SMB3: clarify some of the unused CreateOption flags cifs: Add client version details to NTLM authenticate message smb3: fix touch -h of symlink
This commit is contained in:
commit
766e9cf3bd
@ -32,7 +32,7 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
|
|||||||
* fully cached or it may be in the process of
|
* fully cached or it may be in the process of
|
||||||
* being deleted due to a lease break.
|
* being deleted due to a lease break.
|
||||||
*/
|
*/
|
||||||
if (!cfid->has_lease) {
|
if (!cfid->time || !cfid->has_lease) {
|
||||||
spin_unlock(&cfids->cfid_list_lock);
|
spin_unlock(&cfids->cfid_list_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -193,10 +193,20 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
npath = path_no_prefix(cifs_sb, path);
|
npath = path_no_prefix(cifs_sb, path);
|
||||||
if (IS_ERR(npath)) {
|
if (IS_ERR(npath)) {
|
||||||
rc = PTR_ERR(npath);
|
rc = PTR_ERR(npath);
|
||||||
kfree(utf16_path);
|
goto out;
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!npath[0]) {
|
||||||
|
dentry = dget(cifs_sb->root);
|
||||||
|
} else {
|
||||||
|
dentry = path_to_dentry(cifs_sb, npath);
|
||||||
|
if (IS_ERR(dentry)) {
|
||||||
|
rc = -ENOENT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cfid->dentry = dentry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We do not hold the lock for the open because in case
|
* We do not hold the lock for the open because in case
|
||||||
* SMB2_open needs to reconnect.
|
* SMB2_open needs to reconnect.
|
||||||
@ -249,6 +259,15 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
|
|
||||||
smb2_set_related(&rqst[1]);
|
smb2_set_related(&rqst[1]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set @cfid->has_lease to true before sending out compounded request so
|
||||||
|
* its lease reference can be put in cached_dir_lease_break() due to a
|
||||||
|
* potential lease break right after the request is sent or while @cfid
|
||||||
|
* is still being cached. Concurrent processes won't be to use it yet
|
||||||
|
* due to @cfid->time being zero.
|
||||||
|
*/
|
||||||
|
cfid->has_lease = true;
|
||||||
|
|
||||||
rc = compound_send_recv(xid, ses, server,
|
rc = compound_send_recv(xid, ses, server,
|
||||||
flags, 2, rqst,
|
flags, 2, rqst,
|
||||||
resp_buftype, rsp_iov);
|
resp_buftype, rsp_iov);
|
||||||
@ -263,6 +282,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
cfid->tcon = tcon;
|
cfid->tcon = tcon;
|
||||||
cfid->is_open = true;
|
cfid->is_open = true;
|
||||||
|
|
||||||
|
spin_lock(&cfids->cfid_list_lock);
|
||||||
|
|
||||||
o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
|
o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
|
||||||
oparms.fid->persistent_fid = o_rsp->PersistentFileId;
|
oparms.fid->persistent_fid = o_rsp->PersistentFileId;
|
||||||
oparms.fid->volatile_fid = o_rsp->VolatileFileId;
|
oparms.fid->volatile_fid = o_rsp->VolatileFileId;
|
||||||
@ -270,18 +291,25 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId);
|
oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId);
|
||||||
#endif /* CIFS_DEBUG2 */
|
#endif /* CIFS_DEBUG2 */
|
||||||
|
|
||||||
if (o_rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
|
rc = -EINVAL;
|
||||||
|
if (o_rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) {
|
||||||
|
spin_unlock(&cfids->cfid_list_lock);
|
||||||
goto oshr_free;
|
goto oshr_free;
|
||||||
|
}
|
||||||
|
|
||||||
smb2_parse_contexts(server, o_rsp,
|
smb2_parse_contexts(server, o_rsp,
|
||||||
&oparms.fid->epoch,
|
&oparms.fid->epoch,
|
||||||
oparms.fid->lease_key, &oplock,
|
oparms.fid->lease_key, &oplock,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
if (!(oplock & SMB2_LEASE_READ_CACHING_HE))
|
if (!(oplock & SMB2_LEASE_READ_CACHING_HE)) {
|
||||||
|
spin_unlock(&cfids->cfid_list_lock);
|
||||||
goto oshr_free;
|
goto oshr_free;
|
||||||
|
}
|
||||||
qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
|
qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
|
||||||
if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info))
|
if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info)) {
|
||||||
|
spin_unlock(&cfids->cfid_list_lock);
|
||||||
goto oshr_free;
|
goto oshr_free;
|
||||||
|
}
|
||||||
if (!smb2_validate_and_copy_iov(
|
if (!smb2_validate_and_copy_iov(
|
||||||
le16_to_cpu(qi_rsp->OutputBufferOffset),
|
le16_to_cpu(qi_rsp->OutputBufferOffset),
|
||||||
sizeof(struct smb2_file_all_info),
|
sizeof(struct smb2_file_all_info),
|
||||||
@ -289,37 +317,24 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
(char *)&cfid->file_all_info))
|
(char *)&cfid->file_all_info))
|
||||||
cfid->file_all_info_is_valid = true;
|
cfid->file_all_info_is_valid = true;
|
||||||
|
|
||||||
if (!npath[0])
|
|
||||||
dentry = dget(cifs_sb->root);
|
|
||||||
else {
|
|
||||||
dentry = path_to_dentry(cifs_sb, npath);
|
|
||||||
if (IS_ERR(dentry)) {
|
|
||||||
rc = -ENOENT;
|
|
||||||
goto oshr_free;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_lock(&cfids->cfid_list_lock);
|
|
||||||
cfid->dentry = dentry;
|
|
||||||
cfid->time = jiffies;
|
cfid->time = jiffies;
|
||||||
cfid->has_lease = true;
|
|
||||||
spin_unlock(&cfids->cfid_list_lock);
|
spin_unlock(&cfids->cfid_list_lock);
|
||||||
|
/* At this point the directory handle is fully cached */
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
oshr_free:
|
oshr_free:
|
||||||
kfree(utf16_path);
|
|
||||||
SMB2_open_free(&rqst[0]);
|
SMB2_open_free(&rqst[0]);
|
||||||
SMB2_query_info_free(&rqst[1]);
|
SMB2_query_info_free(&rqst[1]);
|
||||||
free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
|
free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
|
||||||
free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
|
free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
|
||||||
spin_lock(&cfids->cfid_list_lock);
|
|
||||||
if (!cfid->has_lease) {
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
spin_lock(&cfids->cfid_list_lock);
|
||||||
if (cfid->on_list) {
|
if (cfid->on_list) {
|
||||||
list_del(&cfid->entry);
|
list_del(&cfid->entry);
|
||||||
cfid->on_list = false;
|
cfid->on_list = false;
|
||||||
cfids->num_entries--;
|
cfids->num_entries--;
|
||||||
}
|
}
|
||||||
rc = -ENOENT;
|
if (cfid->has_lease) {
|
||||||
} else {
|
|
||||||
/*
|
/*
|
||||||
* We are guaranteed to have two references at this
|
* We are guaranteed to have two references at this
|
||||||
* point. One for the caller and one for a potential
|
* point. One for the caller and one for a potential
|
||||||
@ -327,25 +342,24 @@ oshr_free:
|
|||||||
* will be closed when the caller closes the cached
|
* will be closed when the caller closes the cached
|
||||||
* handle.
|
* handle.
|
||||||
*/
|
*/
|
||||||
|
cfid->has_lease = false;
|
||||||
spin_unlock(&cfids->cfid_list_lock);
|
spin_unlock(&cfids->cfid_list_lock);
|
||||||
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
spin_unlock(&cfids->cfid_list_lock);
|
spin_unlock(&cfids->cfid_list_lock);
|
||||||
|
}
|
||||||
|
out:
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (cfid->is_open)
|
if (cfid->is_open)
|
||||||
SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
|
SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
|
||||||
cfid->fid.volatile_fid);
|
cfid->fid.volatile_fid);
|
||||||
free_cached_dir(cfid);
|
free_cached_dir(cfid);
|
||||||
cfid = NULL;
|
} else {
|
||||||
}
|
|
||||||
out:
|
|
||||||
if (rc == 0) {
|
|
||||||
*ret_cfid = cfid;
|
*ret_cfid = cfid;
|
||||||
atomic_inc(&tcon->num_remote_opens);
|
atomic_inc(&tcon->num_remote_opens);
|
||||||
}
|
}
|
||||||
|
kfree(utf16_path);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,6 +427,8 @@ skip_rdma:
|
|||||||
if (server->nosharesock)
|
if (server->nosharesock)
|
||||||
seq_printf(m, " nosharesock");
|
seq_printf(m, " nosharesock");
|
||||||
|
|
||||||
|
seq_printf(m, "\nServer capabilities: 0x%x", server->capabilities);
|
||||||
|
|
||||||
if (server->rdma)
|
if (server->rdma)
|
||||||
seq_printf(m, "\nRDMA ");
|
seq_printf(m, "\nRDMA ");
|
||||||
seq_printf(m, "\nTCP status: %d Instance: %d"
|
seq_printf(m, "\nTCP status: %d Instance: %d"
|
||||||
@ -452,6 +454,11 @@ skip_rdma:
|
|||||||
seq_printf(m, "\n\n\tSessions: ");
|
seq_printf(m, "\n\n\tSessions: ");
|
||||||
i = 0;
|
i = 0;
|
||||||
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
|
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
|
||||||
|
spin_lock(&ses->ses_lock);
|
||||||
|
if (ses->ses_status == SES_EXITING) {
|
||||||
|
spin_unlock(&ses->ses_lock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
if ((ses->serverDomain == NULL) ||
|
if ((ses->serverDomain == NULL) ||
|
||||||
(ses->serverOS == NULL) ||
|
(ses->serverOS == NULL) ||
|
||||||
@ -472,6 +479,7 @@ skip_rdma:
|
|||||||
ses->ses_count, ses->serverOS, ses->serverNOS,
|
ses->ses_count, ses->serverOS, ses->serverNOS,
|
||||||
ses->capabilities, ses->ses_status);
|
ses->capabilities, ses->ses_status);
|
||||||
}
|
}
|
||||||
|
spin_unlock(&ses->ses_lock);
|
||||||
|
|
||||||
seq_printf(m, "\n\tSecurity type: %s ",
|
seq_printf(m, "\n\tSecurity type: %s ",
|
||||||
get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
|
get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
|
||||||
|
@ -1191,6 +1191,7 @@ const char *cifs_get_link(struct dentry *dentry, struct inode *inode,
|
|||||||
|
|
||||||
const struct inode_operations cifs_symlink_inode_ops = {
|
const struct inode_operations cifs_symlink_inode_ops = {
|
||||||
.get_link = cifs_get_link,
|
.get_link = cifs_get_link,
|
||||||
|
.setattr = cifs_setattr,
|
||||||
.permission = cifs_permission,
|
.permission = cifs_permission,
|
||||||
.listxattr = cifs_listxattr,
|
.listxattr = cifs_listxattr,
|
||||||
};
|
};
|
||||||
|
@ -2570,7 +2570,7 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
struct win_dev {
|
struct win_dev {
|
||||||
unsigned char type[8]; /* IntxCHR or IntxBLK */
|
unsigned char type[8]; /* IntxCHR or IntxBLK or LnxFIFO*/
|
||||||
__le64 major;
|
__le64 major;
|
||||||
__le64 minor;
|
__le64 minor;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
@ -81,7 +81,7 @@ extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
|
|||||||
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
|
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
|
||||||
char *cifs_build_devname(char *nodename, const char *prepath);
|
char *cifs_build_devname(char *nodename, const char *prepath);
|
||||||
extern void delete_mid(struct mid_q_entry *mid);
|
extern void delete_mid(struct mid_q_entry *mid);
|
||||||
extern void release_mid(struct mid_q_entry *mid);
|
void __release_mid(struct kref *refcount);
|
||||||
extern void cifs_wake_up_task(struct mid_q_entry *mid);
|
extern void cifs_wake_up_task(struct mid_q_entry *mid);
|
||||||
extern int cifs_handle_standard(struct TCP_Server_Info *server,
|
extern int cifs_handle_standard(struct TCP_Server_Info *server,
|
||||||
struct mid_q_entry *mid);
|
struct mid_q_entry *mid);
|
||||||
@ -740,4 +740,9 @@ static inline bool dfs_src_pathname_equal(const char *s1, const char *s2)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void release_mid(struct mid_q_entry *mid)
|
||||||
|
{
|
||||||
|
kref_put(&mid->refcount, __release_mid);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _CIFSPROTO_H */
|
#endif /* _CIFSPROTO_H */
|
||||||
|
@ -119,6 +119,7 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
|
|||||||
static void smb2_query_server_interfaces(struct work_struct *work)
|
static void smb2_query_server_interfaces(struct work_struct *work)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
int xid;
|
||||||
struct cifs_tcon *tcon = container_of(work,
|
struct cifs_tcon *tcon = container_of(work,
|
||||||
struct cifs_tcon,
|
struct cifs_tcon,
|
||||||
query_interfaces.work);
|
query_interfaces.work);
|
||||||
@ -126,7 +127,10 @@ static void smb2_query_server_interfaces(struct work_struct *work)
|
|||||||
/*
|
/*
|
||||||
* query server network interfaces, in case they change
|
* query server network interfaces, in case they change
|
||||||
*/
|
*/
|
||||||
rc = SMB3_request_interfaces(0, tcon, false);
|
xid = get_xid();
|
||||||
|
rc = SMB3_request_interfaces(xid, tcon, false);
|
||||||
|
free_xid(xid);
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
|
cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
@ -156,13 +160,14 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
|
|||||||
/* If server is a channel, select the primary channel */
|
/* If server is a channel, select the primary channel */
|
||||||
pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
|
pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
|
||||||
|
|
||||||
spin_lock(&pserver->srv_lock);
|
/* if we need to signal just this channel */
|
||||||
if (!all_channels) {
|
if (!all_channels) {
|
||||||
pserver->tcpStatus = CifsNeedReconnect;
|
spin_lock(&server->srv_lock);
|
||||||
spin_unlock(&pserver->srv_lock);
|
if (server->tcpStatus != CifsExiting)
|
||||||
|
server->tcpStatus = CifsNeedReconnect;
|
||||||
|
spin_unlock(&server->srv_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
spin_unlock(&pserver->srv_lock);
|
|
||||||
|
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
|
list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
|
||||||
@ -1969,9 +1974,10 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|||||||
|
|
||||||
void __cifs_put_smb_ses(struct cifs_ses *ses)
|
void __cifs_put_smb_ses(struct cifs_ses *ses)
|
||||||
{
|
{
|
||||||
unsigned int rc, xid;
|
|
||||||
unsigned int chan_count;
|
|
||||||
struct TCP_Server_Info *server = ses->server;
|
struct TCP_Server_Info *server = ses->server;
|
||||||
|
unsigned int xid;
|
||||||
|
size_t i;
|
||||||
|
int rc;
|
||||||
|
|
||||||
spin_lock(&ses->ses_lock);
|
spin_lock(&ses->ses_lock);
|
||||||
if (ses->ses_status == SES_EXITING) {
|
if (ses->ses_status == SES_EXITING) {
|
||||||
@ -2017,13 +2023,8 @@ void __cifs_put_smb_ses(struct cifs_ses *ses)
|
|||||||
list_del_init(&ses->smb_ses_list);
|
list_del_init(&ses->smb_ses_list);
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
chan_count = ses->chan_count;
|
|
||||||
|
|
||||||
/* close any extra channels */
|
/* close any extra channels */
|
||||||
if (chan_count > 1) {
|
for (i = 1; i < ses->chan_count; i++) {
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 1; i < chan_count; i++) {
|
|
||||||
if (ses->chans[i].iface) {
|
if (ses->chans[i].iface) {
|
||||||
kref_put(&ses->chans[i].iface->refcount, release_iface);
|
kref_put(&ses->chans[i].iface->refcount, release_iface);
|
||||||
ses->chans[i].iface = NULL;
|
ses->chans[i].iface = NULL;
|
||||||
@ -2031,7 +2032,6 @@ void __cifs_put_smb_ses(struct cifs_ses *ses)
|
|||||||
cifs_put_tcp_session(ses->chans[i].server, 0);
|
cifs_put_tcp_session(ses->chans[i].server, 0);
|
||||||
ses->chans[i].server = NULL;
|
ses->chans[i].server = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sesInfoFree(ses);
|
sesInfoFree(ses);
|
||||||
cifs_put_tcp_session(server, 0);
|
cifs_put_tcp_session(server, 0);
|
||||||
@ -3849,8 +3849,12 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
|||||||
is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
||||||
spin_unlock(&ses->chan_lock);
|
spin_unlock(&ses->chan_lock);
|
||||||
|
|
||||||
if (!is_binding)
|
if (!is_binding) {
|
||||||
ses->ses_status = SES_IN_SETUP;
|
ses->ses_status = SES_IN_SETUP;
|
||||||
|
|
||||||
|
/* force iface_list refresh */
|
||||||
|
ses->iface_last_update = 0;
|
||||||
|
}
|
||||||
spin_unlock(&ses->ses_lock);
|
spin_unlock(&ses->ses_lock);
|
||||||
|
|
||||||
/* update ses ip_addr only for primary chan */
|
/* update ses ip_addr only for primary chan */
|
||||||
|
@ -594,6 +594,10 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
|
|||||||
cifs_dbg(FYI, "Symlink\n");
|
cifs_dbg(FYI, "Symlink\n");
|
||||||
fattr->cf_mode |= S_IFLNK;
|
fattr->cf_mode |= S_IFLNK;
|
||||||
fattr->cf_dtype = DT_LNK;
|
fattr->cf_dtype = DT_LNK;
|
||||||
|
} else if (memcmp("LnxFIFO", pbuf, 8) == 0) {
|
||||||
|
cifs_dbg(FYI, "FIFO\n");
|
||||||
|
fattr->cf_mode |= S_IFIFO;
|
||||||
|
fattr->cf_dtype = DT_FIFO;
|
||||||
} else {
|
} else {
|
||||||
fattr->cf_mode |= S_IFREG; /* file? */
|
fattr->cf_mode |= S_IFREG; /* file? */
|
||||||
fattr->cf_dtype = DT_REG;
|
fattr->cf_dtype = DT_REG;
|
||||||
|
@ -42,23 +42,11 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
|
|||||||
|
|
||||||
rc = cifs_alloc_hash("md5", &md5);
|
rc = cifs_alloc_hash("md5", &md5);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto symlink_hash_err;
|
return rc;
|
||||||
|
|
||||||
rc = crypto_shash_init(md5);
|
rc = crypto_shash_digest(md5, link_str, link_len, md5_hash);
|
||||||
if (rc) {
|
|
||||||
cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__);
|
|
||||||
goto symlink_hash_err;
|
|
||||||
}
|
|
||||||
rc = crypto_shash_update(md5, link_str, link_len);
|
|
||||||
if (rc) {
|
|
||||||
cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
|
|
||||||
goto symlink_hash_err;
|
|
||||||
}
|
|
||||||
rc = crypto_shash_final(md5, md5_hash);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
|
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
|
||||||
|
|
||||||
symlink_hash_err:
|
|
||||||
cifs_free_hash(&md5);
|
cifs_free_hash(&md5);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -133,8 +133,8 @@ typedef struct _AUTHENTICATE_MESSAGE {
|
|||||||
SECURITY_BUFFER WorkstationName;
|
SECURITY_BUFFER WorkstationName;
|
||||||
SECURITY_BUFFER SessionKey;
|
SECURITY_BUFFER SessionKey;
|
||||||
__le32 NegotiateFlags;
|
__le32 NegotiateFlags;
|
||||||
/* SECURITY_BUFFER for version info not present since we
|
struct ntlmssp_version Version;
|
||||||
do not set the version is present flag */
|
/* SECURITY_BUFFER */
|
||||||
char UserString[];
|
char UserString[];
|
||||||
} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
|
} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
|
||||||
|
|
||||||
|
@ -186,7 +186,6 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
|
if (!(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
|
||||||
ses->chan_max = 1;
|
|
||||||
spin_unlock(&ses->chan_lock);
|
spin_unlock(&ses->chan_lock);
|
||||||
cifs_server_dbg(VFS, "no multichannel support\n");
|
cifs_server_dbg(VFS, "no multichannel support\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -1060,10 +1059,16 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer,
|
|||||||
memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
|
memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
|
||||||
sec_blob->MessageType = NtLmAuthenticate;
|
sec_blob->MessageType = NtLmAuthenticate;
|
||||||
|
|
||||||
|
/* send version information in ntlmssp authenticate also */
|
||||||
flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
|
flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
|
||||||
NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
|
NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_VERSION |
|
||||||
/* we only send version information in ntlmssp negotiate, so do not set this flag */
|
NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
|
||||||
flags = flags & ~NTLMSSP_NEGOTIATE_VERSION;
|
|
||||||
|
sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR;
|
||||||
|
sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL;
|
||||||
|
sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD);
|
||||||
|
sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
|
||||||
|
|
||||||
tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
|
tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
|
||||||
sec_blob->NegotiateFlags = cpu_to_le32(flags);
|
sec_blob->NegotiateFlags = cpu_to_le32(flags);
|
||||||
|
|
||||||
|
@ -787,7 +787,7 @@ __smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid,
|
|||||||
{
|
{
|
||||||
struct close_cancelled_open *cancelled;
|
struct close_cancelled_open *cancelled;
|
||||||
|
|
||||||
cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC);
|
cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
|
||||||
if (!cancelled)
|
if (!cancelled)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -5089,7 +5089,7 @@ smb2_make_node(unsigned int xid, struct inode *inode,
|
|||||||
* over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
|
* over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!S_ISCHR(mode) && !S_ISBLK(mode))
|
if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
cifs_dbg(FYI, "sfu compat create special file\n");
|
cifs_dbg(FYI, "sfu compat create special file\n");
|
||||||
@ -5137,6 +5137,12 @@ smb2_make_node(unsigned int xid, struct inode *inode,
|
|||||||
pdev->minor = cpu_to_le64(MINOR(dev));
|
pdev->minor = cpu_to_le64(MINOR(dev));
|
||||||
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
|
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
|
||||||
&bytes_written, iov, 1);
|
&bytes_written, iov, 1);
|
||||||
|
} else if (S_ISFIFO(mode)) {
|
||||||
|
memcpy(pdev->type, "LnxFIFO", 8);
|
||||||
|
pdev->major = 0;
|
||||||
|
pdev->minor = 0;
|
||||||
|
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
|
||||||
|
&bytes_written, iov, 1);
|
||||||
}
|
}
|
||||||
tcon->ses->server->ops->close(xid, tcon, &fid);
|
tcon->ses->server->ops->close(xid, tcon, &fid);
|
||||||
d_drop(dentry);
|
d_drop(dentry);
|
||||||
|
@ -76,7 +76,7 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
|
|||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __release_mid(struct kref *refcount)
|
void __release_mid(struct kref *refcount)
|
||||||
{
|
{
|
||||||
struct mid_q_entry *midEntry =
|
struct mid_q_entry *midEntry =
|
||||||
container_of(refcount, struct mid_q_entry, refcount);
|
container_of(refcount, struct mid_q_entry, refcount);
|
||||||
@ -156,15 +156,6 @@ static void __release_mid(struct kref *refcount)
|
|||||||
mempool_free(midEntry, cifs_mid_poolp);
|
mempool_free(midEntry, cifs_mid_poolp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_mid(struct mid_q_entry *mid)
|
|
||||||
{
|
|
||||||
struct TCP_Server_Info *server = mid->server;
|
|
||||||
|
|
||||||
spin_lock(&server->mid_lock);
|
|
||||||
kref_put(&mid->refcount, __release_mid);
|
|
||||||
spin_unlock(&server->mid_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_mid(struct mid_q_entry *mid)
|
delete_mid(struct mid_q_entry *mid)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#define SMB2_QUERY_INFO_HE 0x0010
|
#define SMB2_QUERY_INFO_HE 0x0010
|
||||||
#define SMB2_SET_INFO_HE 0x0011
|
#define SMB2_SET_INFO_HE 0x0011
|
||||||
#define SMB2_OPLOCK_BREAK_HE 0x0012
|
#define SMB2_OPLOCK_BREAK_HE 0x0012
|
||||||
|
#define SMB2_SERVER_TO_CLIENT_NOTIFICATION 0x0013
|
||||||
|
|
||||||
/* The same list in little endian */
|
/* The same list in little endian */
|
||||||
#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE)
|
#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE)
|
||||||
@ -411,6 +412,7 @@ struct smb2_tree_disconnect_rsp {
|
|||||||
#define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */
|
#define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */
|
||||||
#define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */
|
#define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */
|
||||||
#define SMB2_GLOBAL_CAP_ENCRYPTION 0x00000040 /* New to SMB3 */
|
#define SMB2_GLOBAL_CAP_ENCRYPTION 0x00000040 /* New to SMB3 */
|
||||||
|
#define SMB2_GLOBAL_CAP_NOTIFICATIONS 0x00000080 /* New to SMB3.1.1 */
|
||||||
/* Internal types */
|
/* Internal types */
|
||||||
#define SMB2_NT_FIND 0x00100000
|
#define SMB2_NT_FIND 0x00100000
|
||||||
#define SMB2_LARGE_FILES 0x00200000
|
#define SMB2_LARGE_FILES 0x00200000
|
||||||
@ -981,6 +983,19 @@ struct smb2_change_notify_rsp {
|
|||||||
__u8 Buffer[]; /* array of file notify structs */
|
__u8 Buffer[]; /* array of file notify structs */
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SMB2_SERVER_TO_CLIENT_NOTIFICATION: See MS-SMB2 section 2.2.44
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SMB2_NOTIFY_SESSION_CLOSED 0x0000
|
||||||
|
|
||||||
|
struct smb2_server_client_notification {
|
||||||
|
struct smb2_hdr hdr;
|
||||||
|
__le16 StructureSize;
|
||||||
|
__u16 Reserved; /* MBZ */
|
||||||
|
__le32 NotificationType;
|
||||||
|
__u8 NotificationBuffer[4]; /* MBZ */
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SMB2_CREATE See MS-SMB2 section 2.2.13
|
* SMB2_CREATE See MS-SMB2 section 2.2.13
|
||||||
@ -1097,16 +1112,23 @@ struct smb2_change_notify_rsp {
|
|||||||
#define FILE_WRITE_THROUGH_LE cpu_to_le32(0x00000002)
|
#define FILE_WRITE_THROUGH_LE cpu_to_le32(0x00000002)
|
||||||
#define FILE_SEQUENTIAL_ONLY_LE cpu_to_le32(0x00000004)
|
#define FILE_SEQUENTIAL_ONLY_LE cpu_to_le32(0x00000004)
|
||||||
#define FILE_NO_INTERMEDIATE_BUFFERING_LE cpu_to_le32(0x00000008)
|
#define FILE_NO_INTERMEDIATE_BUFFERING_LE cpu_to_le32(0x00000008)
|
||||||
|
/* FILE_SYNCHRONOUS_IO_ALERT_LE cpu_to_le32(0x00000010) should be zero, ignored */
|
||||||
|
/* FILE_SYNCHRONOUS_IO_NONALERT cpu_to_le32(0x00000020) should be zero, ignored */
|
||||||
#define FILE_NON_DIRECTORY_FILE_LE cpu_to_le32(0x00000040)
|
#define FILE_NON_DIRECTORY_FILE_LE cpu_to_le32(0x00000040)
|
||||||
#define FILE_COMPLETE_IF_OPLOCKED_LE cpu_to_le32(0x00000100)
|
#define FILE_COMPLETE_IF_OPLOCKED_LE cpu_to_le32(0x00000100)
|
||||||
#define FILE_NO_EA_KNOWLEDGE_LE cpu_to_le32(0x00000200)
|
#define FILE_NO_EA_KNOWLEDGE_LE cpu_to_le32(0x00000200)
|
||||||
|
/* FILE_OPEN_REMOTE_INSTANCE cpu_to_le32(0x00000400) should be zero, ignored */
|
||||||
#define FILE_RANDOM_ACCESS_LE cpu_to_le32(0x00000800)
|
#define FILE_RANDOM_ACCESS_LE cpu_to_le32(0x00000800)
|
||||||
#define FILE_DELETE_ON_CLOSE_LE cpu_to_le32(0x00001000)
|
#define FILE_DELETE_ON_CLOSE_LE cpu_to_le32(0x00001000) /* MBZ */
|
||||||
#define FILE_OPEN_BY_FILE_ID_LE cpu_to_le32(0x00002000)
|
#define FILE_OPEN_BY_FILE_ID_LE cpu_to_le32(0x00002000)
|
||||||
#define FILE_OPEN_FOR_BACKUP_INTENT_LE cpu_to_le32(0x00004000)
|
#define FILE_OPEN_FOR_BACKUP_INTENT_LE cpu_to_le32(0x00004000)
|
||||||
#define FILE_NO_COMPRESSION_LE cpu_to_le32(0x00008000)
|
#define FILE_NO_COMPRESSION_LE cpu_to_le32(0x00008000)
|
||||||
|
/* FILE_OPEN_REQUIRING_OPLOCK cpu_to_le32(0x00010000) should be zero, ignored */
|
||||||
|
/* FILE_DISALLOW_EXCLUSIVE cpu_to_le32(0x00020000) should be zero, ignored */
|
||||||
|
/* FILE_RESERVE_OPFILTER cpu_to_le32(0x00100000) MBZ */
|
||||||
#define FILE_OPEN_REPARSE_POINT_LE cpu_to_le32(0x00200000)
|
#define FILE_OPEN_REPARSE_POINT_LE cpu_to_le32(0x00200000)
|
||||||
#define FILE_OPEN_NO_RECALL_LE cpu_to_le32(0x00400000)
|
#define FILE_OPEN_NO_RECALL_LE cpu_to_le32(0x00400000)
|
||||||
|
/* #define FILE_OPEN_FOR_FREE_SPACE_QUERY cpu_to_le32(0x00800000) should be zero, ignored */
|
||||||
#define CREATE_OPTIONS_MASK_LE cpu_to_le32(0x00FFFFFF)
|
#define CREATE_OPTIONS_MASK_LE cpu_to_le32(0x00FFFFFF)
|
||||||
|
|
||||||
#define FILE_READ_RIGHTS_LE (FILE_READ_DATA_LE | FILE_READ_EA_LE \
|
#define FILE_READ_RIGHTS_LE (FILE_READ_DATA_LE | FILE_READ_EA_LE \
|
||||||
|
Loading…
Reference in New Issue
Block a user