Skip to content

Commit 9f867ba

Browse files
committed
Merge tag '6.15-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull more smb client updates from Steve French: - reconnect fixes: three for updating rsize/wsize and an SMB1 reconnect fix - RFC1001 fixes: fixing connections to nonstandard ports, and negprot retries - fix mfsymlinks to old servers - make mapping of open flags for SMB1 more accurate - permission fixes: adding retry on open for write, and one for stat to workaround unexpected access denied - add two new xattrs, one for retrieving SACL and one for retrieving owner (without having to retrieve the whole ACL) - fix mount parm validation for echo_interval - minor cleanup (including removing now unneeded cifs_truncate_page) * tag '6.15-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal version number cifs: Implement is_network_name_deleted for SMB1 cifs: Remove cifs_truncate_page() as it should be superfluous cifs: Do not add FILE_READ_ATTRIBUTES when using GENERIC_READ/EXECUTE/ALL cifs: Improve SMB2+ stat() to work also without FILE_READ_ATTRIBUTES cifs: Add fallback for SMB2 CREATE without FILE_READ_ATTRIBUTES cifs: Fix querying and creating MF symlinks over SMB1 cifs: Fix access_flags_to_smbopen_mode cifs: Fix negotiate retry functionality cifs: Improve handling of NetBIOS packets cifs: Allow to disable or force initialization of NetBIOS session cifs: Add a new xattr system.smb3_ntsd_owner for getting or setting owner cifs: Add a new xattr system.smb3_ntsd_sacl for getting or setting SACLs smb: client: Update IO sizes after reconnection smb: client: Store original IO parameters and prevent zero IO sizes smb:client: smb: client: Add reverse mapping from tcon to superblocks cifs: remove unreachable code in cifs_get_tcp_session() cifs: fix integer overflow in match_server()
2 parents a52a3c1 + 827a1bd commit 9f867ba

19 files changed

+438
-86
lines changed

fs/smb/client/cifs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949

5050
struct cifs_sb_info {
5151
struct rb_root tlink_tree;
52+
struct list_head tcon_sb_link;
5253
spinlock_t tlink_tree_lock;
5354
struct tcon_link *master_tlink;
5455
struct nls_table *local_nls;

fs/smb/client/cifsfs.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ extern ssize_t cifs_file_copychunk_range(unsigned int xid,
135135

136136
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
137137
extern void cifs_setsize(struct inode *inode, loff_t offset);
138-
extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
139138

140139
struct smb3_fs_context;
141140
extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type,
@@ -146,6 +145,6 @@ extern const struct export_operations cifs_export_ops;
146145
#endif /* CONFIG_CIFS_NFSD_EXPORT */
147146

148147
/* when changing internal version - update following two lines at same time */
149-
#define SMB3_PRODUCT_BUILD 53
150-
#define CIFS_VERSION "2.53"
148+
#define SMB3_PRODUCT_BUILD 54
149+
#define CIFS_VERSION "2.54"
151150
#endif /* _CIFSFS_H */

fs/smb/client/cifsglob.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,8 @@ struct TCP_Server_Info {
714714
spinlock_t srv_lock; /* protect anything here that is not protected */
715715
__u64 conn_id; /* connection identifier (useful for debugging) */
716716
int srv_count; /* reference counter */
717+
int rfc1001_sessinit; /* whether to estasblish netbios session */
718+
bool with_rfc1001; /* if netbios session is used */
717719
/* 15 character server name + 0x20 16th byte indicating type = srv */
718720
char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
719721
struct smb_version_operations *ops;
@@ -1321,7 +1323,8 @@ struct cifs_tcon {
13211323
#endif
13221324
struct list_head pending_opens; /* list of incomplete opens */
13231325
struct cached_fids *cfids;
1324-
/* BB add field for back pointer to sb struct(s)? */
1326+
struct list_head cifs_sb_list;
1327+
spinlock_t sb_list_lock;
13251328
#ifdef CONFIG_CIFS_DFS_UPCALL
13261329
struct delayed_work dfs_cache_work;
13271330
struct list_head dfs_ses_list;
@@ -1718,6 +1721,7 @@ struct mid_q_entry {
17181721
void *resp_buf; /* pointer to received SMB header */
17191722
unsigned int resp_buf_size;
17201723
int mid_state; /* wish this were enum but can not pass to wait_event */
1724+
int mid_rc; /* rc for MID_RC */
17211725
unsigned int mid_flags;
17221726
__le16 command; /* smb command code */
17231727
unsigned int optype; /* operation type */
@@ -1880,6 +1884,7 @@ static inline bool is_replayable_error(int error)
18801884
#define MID_RESPONSE_MALFORMED 0x10
18811885
#define MID_SHUTDOWN 0x20
18821886
#define MID_RESPONSE_READY 0x40 /* ready for other process handle the rsp */
1887+
#define MID_RC 0x80 /* mid_rc contains custom rc */
18831888

18841889
/* Flags */
18851890
#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */

fs/smb/client/cifssmb.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,15 +1041,31 @@ static __u16 convert_disposition(int disposition)
10411041
static int
10421042
access_flags_to_smbopen_mode(const int access_flags)
10431043
{
1044-
int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1045-
1046-
if (masked_flags == GENERIC_READ)
1047-
return SMBOPEN_READ;
1048-
else if (masked_flags == GENERIC_WRITE)
1044+
/*
1045+
* SYSTEM_SECURITY grants both read and write access to SACL, treat is as read/write.
1046+
* MAXIMUM_ALLOWED grants as many access as possible, so treat it as read/write too.
1047+
* SYNCHRONIZE as is does not grant any specific access, so do not check its mask.
1048+
* If only SYNCHRONIZE bit is specified then fallback to read access.
1049+
*/
1050+
bool with_write_flags = access_flags & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA |
1051+
FILE_DELETE_CHILD | FILE_WRITE_ATTRIBUTES | DELETE |
1052+
WRITE_DAC | WRITE_OWNER | SYSTEM_SECURITY |
1053+
MAXIMUM_ALLOWED | GENERIC_WRITE | GENERIC_ALL);
1054+
bool with_read_flags = access_flags & (FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE |
1055+
FILE_READ_ATTRIBUTES | READ_CONTROL |
1056+
SYSTEM_SECURITY | MAXIMUM_ALLOWED | GENERIC_ALL |
1057+
GENERIC_EXECUTE | GENERIC_READ);
1058+
bool with_execute_flags = access_flags & (FILE_EXECUTE | MAXIMUM_ALLOWED | GENERIC_ALL |
1059+
GENERIC_EXECUTE);
1060+
1061+
if (with_write_flags && with_read_flags)
1062+
return SMBOPEN_READWRITE;
1063+
else if (with_write_flags)
10491064
return SMBOPEN_WRITE;
1050-
1051-
/* just go for read/write */
1052-
return SMBOPEN_READWRITE;
1065+
else if (with_execute_flags)
1066+
return SMBOPEN_EXECUTE;
1067+
else
1068+
return SMBOPEN_READ;
10531069
}
10541070

10551071
int

fs/smb/client/connect.c

Lines changed: 157 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num
371371
*
372372
*/
373373
static int __cifs_reconnect(struct TCP_Server_Info *server,
374-
bool mark_smb_session)
374+
bool mark_smb_session, bool once)
375375
{
376376
int rc = 0;
377377

@@ -399,6 +399,9 @@ static int __cifs_reconnect(struct TCP_Server_Info *server,
399399
if (rc) {
400400
cifs_server_unlock(server);
401401
cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc);
402+
/* If was asked to reconnect only once, do not try it more times */
403+
if (once)
404+
break;
402405
msleep(3000);
403406
} else {
404407
atomic_inc(&tcpSesReconnectCount);
@@ -564,19 +567,33 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server)
564567
return rc;
565568
}
566569

567-
int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
570+
static int
571+
_cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session, bool once)
568572
{
569573
if (!server->leaf_fullpath)
570-
return __cifs_reconnect(server, mark_smb_session);
574+
return __cifs_reconnect(server, mark_smb_session, once);
571575
return reconnect_dfs_server(server);
572576
}
573577
#else
574-
int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
578+
static int
579+
_cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session, bool once)
575580
{
576-
return __cifs_reconnect(server, mark_smb_session);
581+
return __cifs_reconnect(server, mark_smb_session, once);
577582
}
578583
#endif
579584

585+
int
586+
cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
587+
{
588+
return _cifs_reconnect(server, mark_smb_session, false);
589+
}
590+
591+
static int
592+
cifs_reconnect_once(struct TCP_Server_Info *server)
593+
{
594+
return _cifs_reconnect(server, true, true);
595+
}
596+
580597
static void
581598
cifs_echo_request(struct work_struct *work)
582599
{
@@ -803,26 +820,110 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
803820
/* Regular SMB response */
804821
return true;
805822
case RFC1002_SESSION_KEEP_ALIVE:
823+
/*
824+
* RFC 1002 session keep alive can sent by the server only when
825+
* we established a RFC 1002 session. But Samba servers send
826+
* RFC 1002 session keep alive also over port 445 on which
827+
* RFC 1002 session is not established.
828+
*/
806829
cifs_dbg(FYI, "RFC 1002 session keep alive\n");
807830
break;
808831
case RFC1002_POSITIVE_SESSION_RESPONSE:
809-
cifs_dbg(FYI, "RFC 1002 positive session response\n");
832+
/*
833+
* RFC 1002 positive session response cannot be returned
834+
* for SMB request. RFC 1002 session response is handled
835+
* exclusively in ip_rfc1001_connect() function.
836+
*/
837+
cifs_server_dbg(VFS, "RFC 1002 positive session response (unexpected)\n");
838+
cifs_reconnect(server, true);
810839
break;
811840
case RFC1002_NEGATIVE_SESSION_RESPONSE:
812841
/*
813842
* We get this from Windows 98 instead of an error on
814-
* SMB negprot response.
843+
* SMB negprot response, when we have not established
844+
* RFC 1002 session (which means ip_rfc1001_connect()
845+
* was skipped). Note that same still happens with
846+
* Windows Server 2022 when connecting via port 139.
847+
* So for this case when mount option -o nonbsessinit
848+
* was not specified, try to reconnect with establishing
849+
* RFC 1002 session. If new socket establishment with
850+
* RFC 1002 session was successful then return to the
851+
* mid's caller -EAGAIN, so it can retry the request.
815852
*/
816-
cifs_dbg(FYI, "RFC 1002 negative session response\n");
817-
/* give server a second to clean up */
818-
msleep(1000);
819-
/*
820-
* Always try 445 first on reconnect since we get NACK
821-
* on some if we ever connected to port 139 (the NACK
822-
* is since we do not begin with RFC1001 session
823-
* initialize frame).
824-
*/
825-
cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
853+
if (!cifs_rdma_enabled(server) &&
854+
server->tcpStatus == CifsInNegotiate &&
855+
!server->with_rfc1001 &&
856+
server->rfc1001_sessinit != 0) {
857+
int rc, mid_rc;
858+
struct mid_q_entry *mid, *nmid;
859+
LIST_HEAD(dispose_list);
860+
861+
cifs_dbg(FYI, "RFC 1002 negative session response during SMB Negotiate, retrying with NetBIOS session\n");
862+
863+
/*
864+
* Before reconnect, delete all pending mids for this
865+
* server, so reconnect would not signal connection
866+
* aborted error to mid's callbacks. Note that for this
867+
* server there should be exactly one pending mid
868+
* corresponding to SMB1/SMB2 Negotiate packet.
869+
*/
870+
spin_lock(&server->mid_lock);
871+
list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) {
872+
kref_get(&mid->refcount);
873+
list_move(&mid->qhead, &dispose_list);
874+
mid->mid_flags |= MID_DELETED;
875+
}
876+
spin_unlock(&server->mid_lock);
877+
878+
/* Now try to reconnect once with NetBIOS session. */
879+
server->with_rfc1001 = true;
880+
rc = cifs_reconnect_once(server);
881+
882+
/*
883+
* If reconnect was successful then indicate -EAGAIN
884+
* to mid's caller. If reconnect failed with -EAGAIN
885+
* then mask it as -EHOSTDOWN, so mid's caller would
886+
* know that it failed.
887+
*/
888+
if (rc == 0)
889+
mid_rc = -EAGAIN;
890+
else if (rc == -EAGAIN)
891+
mid_rc = -EHOSTDOWN;
892+
else
893+
mid_rc = rc;
894+
895+
/*
896+
* After reconnect (either successful or unsuccessful)
897+
* deliver reconnect status to mid's caller via mid's
898+
* callback. Use MID_RC state which indicates that the
899+
* return code should be read from mid_rc member.
900+
*/
901+
list_for_each_entry_safe(mid, nmid, &dispose_list, qhead) {
902+
list_del_init(&mid->qhead);
903+
mid->mid_rc = mid_rc;
904+
mid->mid_state = MID_RC;
905+
mid->callback(mid);
906+
release_mid(mid);
907+
}
908+
909+
/*
910+
* If reconnect failed then wait two seconds. In most
911+
* cases we were been called from the mount context and
912+
* delivered failure to mid's callback will stop this
913+
* receiver task thread and fails the mount process.
914+
* So wait two seconds to prevent another reconnect
915+
* in this task thread, which would be useless as the
916+
* mount context will fail at all.
917+
*/
918+
if (rc != 0)
919+
msleep(2000);
920+
} else {
921+
cifs_server_dbg(VFS, "RFC 1002 negative session response (unexpected)\n");
922+
cifs_reconnect(server, true);
923+
}
924+
break;
925+
case RFC1002_RETARGET_SESSION_RESPONSE:
926+
cifs_server_dbg(VFS, "RFC 1002 retarget session response (unexpected)\n");
826927
cifs_reconnect(server, true);
827928
break;
828929
default:
@@ -1701,6 +1802,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
17011802
ctx->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
17021803
memcpy(tcp_ses->server_RFC1001_name,
17031804
ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1805+
tcp_ses->rfc1001_sessinit = ctx->rfc1001_sessinit;
1806+
tcp_ses->with_rfc1001 = false;
17041807
tcp_ses->session_estab = false;
17051808
tcp_ses->sequence_number = 0;
17061809
tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */
@@ -1731,12 +1834,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
17311834
*/
17321835
tcp_ses->tcpStatus = CifsNew;
17331836
++tcp_ses->srv_count;
1837+
tcp_ses->echo_interval = ctx->echo_interval * HZ;
17341838

1735-
if (ctx->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
1736-
ctx->echo_interval <= SMB_ECHO_INTERVAL_MAX)
1737-
tcp_ses->echo_interval = ctx->echo_interval * HZ;
1738-
else
1739-
tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
17401839
if (tcp_ses->rdma) {
17411840
#ifndef CONFIG_CIFS_SMB_DIRECT
17421841
cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
@@ -3221,6 +3320,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
32213320
return -EIO;
32223321
}
32233322

3323+
server->with_rfc1001 = true;
32243324
return 0;
32253325
}
32263326

@@ -3332,7 +3432,16 @@ generic_ip_connect(struct TCP_Server_Info *server)
33323432
return rc;
33333433
}
33343434
trace_smb3_connect_done(server->hostname, server->conn_id, &server->dstaddr);
3335-
if (sport == htons(RFC1001_PORT))
3435+
3436+
/*
3437+
* Establish RFC1001 NetBIOS session when it was explicitly requested
3438+
* by mount option -o nbsessinit, or when connecting to default RFC1001
3439+
* server port (139) and it was not explicitly disabled by mount option
3440+
* -o nonbsessinit.
3441+
*/
3442+
if (server->with_rfc1001 ||
3443+
server->rfc1001_sessinit == 1 ||
3444+
(server->rfc1001_sessinit == -1 && sport == htons(RFC1001_PORT)))
33363445
rc = ip_rfc1001_connect(server);
33373446

33383447
return rc;
@@ -3481,6 +3590,7 @@ int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
34813590
struct smb3_fs_context *ctx = cifs_sb->ctx;
34823591

34833592
INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3593+
INIT_LIST_HEAD(&cifs_sb->tcon_sb_link);
34843594

34853595
spin_lock_init(&cifs_sb->tlink_tree_lock);
34863596
cifs_sb->tlink_tree = RB_ROOT;
@@ -3713,6 +3823,10 @@ static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
37133823
tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
37143824
spin_unlock(&cifs_sb->tlink_tree_lock);
37153825

3826+
spin_lock(&tcon->sb_list_lock);
3827+
list_add(&cifs_sb->tcon_sb_link, &tcon->cifs_sb_list);
3828+
spin_unlock(&tcon->sb_list_lock);
3829+
37163830
queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
37173831
TLINK_IDLE_EXPIRE);
37183832
return 0;
@@ -4054,9 +4168,19 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
40544168
struct rb_root *root = &cifs_sb->tlink_tree;
40554169
struct rb_node *node;
40564170
struct tcon_link *tlink;
4171+
struct cifs_tcon *tcon = NULL;
40574172

40584173
cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
40594174

4175+
if (cifs_sb->master_tlink) {
4176+
tcon = cifs_sb->master_tlink->tl_tcon;
4177+
if (tcon) {
4178+
spin_lock(&tcon->sb_list_lock);
4179+
list_del_init(&cifs_sb->tcon_sb_link);
4180+
spin_unlock(&tcon->sb_list_lock);
4181+
}
4182+
}
4183+
40604184
spin_lock(&cifs_sb->tlink_tree_lock);
40614185
while ((node = rb_first(root))) {
40624186
tlink = rb_entry(node, struct tcon_link, tl_rbnode);
@@ -4078,11 +4202,13 @@ int
40784202
cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
40794203
struct TCP_Server_Info *server)
40804204
{
4205+
bool in_retry = false;
40814206
int rc = 0;
40824207

40834208
if (!server->ops->need_neg || !server->ops->negotiate)
40844209
return -ENOSYS;
40854210

4211+
retry:
40864212
/* only send once per connect */
40874213
spin_lock(&server->srv_lock);
40884214
if (server->tcpStatus != CifsGood &&
@@ -4102,6 +4228,14 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
41024228
spin_unlock(&server->srv_lock);
41034229

41044230
rc = server->ops->negotiate(xid, ses, server);
4231+
if (rc == -EAGAIN) {
4232+
/* Allow one retry attempt */
4233+
if (!in_retry) {
4234+
in_retry = true;
4235+
goto retry;
4236+
}
4237+
rc = -EHOSTDOWN;
4238+
}
41054239
if (rc == 0) {
41064240
spin_lock(&server->srv_lock);
41074241
if (server->tcpStatus == CifsInNegotiate)

0 commit comments

Comments
 (0)