Skip to content

Commit 7c9e41e

Browse files
committed
Merge tag '5.13-rc-smb3-part2' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs updates from Steve French: "Ten CIFS/SMB3 changes - including two marked for stable - including some important multichannel fixes, as well as support for handle leases (deferred close) and shutdown support: - some important multichannel fixes - support for handle leases (deferred close) - shutdown support (which is also helpful since it enables multiple xfstests) - enable negotiating stronger encryption by default (GCM256) - improve wireshark debugging by allowing more options for root to dump decryption keys SambaXP and the SMB3 Plugfest test event are going on now so I am expecting more patches over the next few days due to extra testing (including more multichannel fixes)" * tag '5.13-rc-smb3-part2' of git://git.samba.org/sfrench/cifs-2.6: fs/cifs: Fix resource leak Cifs: Fix kernel oops caused by deferred close for files. cifs: fix regression when mounting shares with prefix paths cifs: use echo_interval even when connection not ready. cifs: detect dead connections only when echoes are enabled. smb3.1.1: allow dumping keys for multiuser mounts smb3.1.1: allow dumping GCM256 keys to improve debugging of encrypted shares cifs: add shutdown support cifs: Deferred close for files smb3.1.1: enable negotiating stronger encryption by default
2 parents 16bb86b + bae4c0c commit 7c9e41e

File tree

14 files changed

+447
-33
lines changed

14 files changed

+447
-33
lines changed

fs/cifs/cifs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */
5656
#define CIFS_MOUNT_RO_CACHE 0x20000000 /* assumes share will not change */
5757
#define CIFS_MOUNT_RW_CACHE 0x40000000 /* assumes only client accessing */
58+
#define CIFS_MOUNT_SHUTDOWN 0x80000000
5859

5960
struct cifs_sb_info {
6061
struct rb_root tlink_tree;

fs/cifs/cifs_ioctl.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ struct smb_query_info {
5757
/* char buffer[]; */
5858
} __packed;
5959

60+
/*
61+
* Dumping the commonly used 16 byte (e.g. CCM and GCM128) keys still supported
62+
* for backlevel compatibility, but is not sufficient for dumping the less
63+
* frequently used GCM256 (32 byte) keys (see the newer "CIFS_DUMP_FULL_KEY"
64+
* ioctl for dumping decryption info for GCM256 mounts)
65+
*/
6066
struct smb3_key_debug_info {
6167
__u64 Suid;
6268
__u16 cipher_type;
@@ -65,6 +71,18 @@ struct smb3_key_debug_info {
6571
__u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
6672
} __packed;
6773

74+
/*
75+
* Dump full key (32 byte encrypt/decrypt keys instead of 16 bytes)
76+
* is needed if GCM256 (stronger encryption) negotiated
77+
*/
78+
struct smb3_full_key_debug_info {
79+
__u64 Suid;
80+
__u16 cipher_type;
81+
__u8 auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */
82+
__u8 smb3encryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
83+
__u8 smb3decryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
84+
} __packed;
85+
6886
struct smb3_notify {
6987
__u32 completion_filter;
7088
bool watch_tree;
@@ -78,3 +96,20 @@ struct smb3_notify {
7896
#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
7997
#define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info)
8098
#define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify)
99+
#define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info)
100+
#define CIFS_IOC_SHUTDOWN _IOR ('X', 125, __u32)
101+
102+
/*
103+
* Flags for going down operation
104+
*/
105+
#define CIFS_GOING_FLAGS_DEFAULT 0x0 /* going down */
106+
#define CIFS_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
107+
#define CIFS_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
108+
109+
static inline bool cifs_forced_shutdown(struct cifs_sb_info *sbi)
110+
{
111+
if (CIFS_MOUNT_SHUTDOWN & sbi->mnt_cifs_flags)
112+
return true;
113+
else
114+
return false;
115+
}

fs/cifs/cifsfs.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ bool enable_oplocks = true;
7575
bool linuxExtEnabled = true;
7676
bool lookupCacheEnabled = true;
7777
bool disable_legacy_dialects; /* false by default */
78-
bool enable_gcm_256; /* false by default, change when more servers support it */
78+
bool enable_gcm_256 = true;
7979
bool require_gcm_256; /* false by default */
8080
unsigned int global_secflags = CIFSSEC_DEF;
8181
/* unsigned int ntlmv2_support = 0; */
@@ -133,6 +133,7 @@ struct workqueue_struct *cifsiod_wq;
133133
struct workqueue_struct *decrypt_wq;
134134
struct workqueue_struct *fileinfo_put_wq;
135135
struct workqueue_struct *cifsoplockd_wq;
136+
struct workqueue_struct *deferredclose_wq;
136137
__u32 cifs_lock_secret;
137138

138139
/*
@@ -390,6 +391,8 @@ cifs_alloc_inode(struct super_block *sb)
390391
/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; */
391392
INIT_LIST_HEAD(&cifs_inode->openFileList);
392393
INIT_LIST_HEAD(&cifs_inode->llist);
394+
INIT_LIST_HEAD(&cifs_inode->deferred_closes);
395+
spin_lock_init(&cifs_inode->deferred_lock);
393396
return &cifs_inode->vfs_inode;
394397
}
395398

@@ -860,13 +863,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
860863
goto out;
861864
}
862865

863-
/* cifs_setup_volume_info->smb3_parse_devname() redups UNC & prepath */
864-
kfree(cifs_sb->ctx->UNC);
865-
cifs_sb->ctx->UNC = NULL;
866-
kfree(cifs_sb->ctx->prepath);
867-
cifs_sb->ctx->prepath = NULL;
868-
869-
rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, old_ctx->UNC);
866+
rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, NULL);
870867
if (rc) {
871868
root = ERR_PTR(rc);
872869
goto out;
@@ -1637,9 +1634,16 @@ init_cifs(void)
16371634
goto out_destroy_fileinfo_put_wq;
16381635
}
16391636

1637+
deferredclose_wq = alloc_workqueue("deferredclose",
1638+
WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
1639+
if (!deferredclose_wq) {
1640+
rc = -ENOMEM;
1641+
goto out_destroy_cifsoplockd_wq;
1642+
}
1643+
16401644
rc = cifs_fscache_register();
16411645
if (rc)
1642-
goto out_destroy_cifsoplockd_wq;
1646+
goto out_destroy_deferredclose_wq;
16431647

16441648
rc = cifs_init_inodecache();
16451649
if (rc)
@@ -1707,6 +1711,8 @@ init_cifs(void)
17071711
cifs_destroy_inodecache();
17081712
out_unreg_fscache:
17091713
cifs_fscache_unregister();
1714+
out_destroy_deferredclose_wq:
1715+
destroy_workqueue(deferredclose_wq);
17101716
out_destroy_cifsoplockd_wq:
17111717
destroy_workqueue(cifsoplockd_wq);
17121718
out_destroy_fileinfo_put_wq:
@@ -1741,6 +1747,7 @@ exit_cifs(void)
17411747
cifs_destroy_mids();
17421748
cifs_destroy_inodecache();
17431749
cifs_fscache_unregister();
1750+
destroy_workqueue(deferredclose_wq);
17441751
destroy_workqueue(cifsoplockd_wq);
17451752
destroy_workqueue(decrypt_wq);
17461753
destroy_workqueue(fileinfo_put_wq);

fs/cifs/cifsglob.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,14 @@ struct cifs_pending_open {
11541154
__u32 oplock;
11551155
};
11561156

1157+
struct cifs_deferred_close {
1158+
struct list_head dlist;
1159+
struct tcon_link *tlink;
1160+
__u16 netfid;
1161+
__u64 persistent_fid;
1162+
__u64 volatile_fid;
1163+
};
1164+
11571165
/*
11581166
* This info hangs off the cifsFileInfo structure, pointed to by llist.
11591167
* This is used to track byte stream locks on the file
@@ -1248,6 +1256,9 @@ struct cifsFileInfo {
12481256
struct cifs_search_info srch_inf;
12491257
struct work_struct oplock_break; /* work for oplock breaks */
12501258
struct work_struct put; /* work for the final part of _put */
1259+
struct delayed_work deferred;
1260+
bool oplock_break_received; /* Flag to indicate oplock break */
1261+
bool deferred_scheduled;
12511262
};
12521263

12531264
struct cifs_io_parms {
@@ -1392,6 +1403,7 @@ struct cifsInodeInfo {
13921403
#define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */
13931404
#define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */
13941405
#define CIFS_INO_LOCK (5) /* lock bit for synchronization */
1406+
#define CIFS_INO_MODIFIED_ATTR (6) /* Indicate change in mtime/ctime */
13951407
unsigned long flags;
13961408
spinlock_t writers_lock;
13971409
unsigned int writers; /* Number of writers on this inode */
@@ -1404,6 +1416,8 @@ struct cifsInodeInfo {
14041416
struct fscache_cookie *fscache;
14051417
#endif
14061418
struct inode vfs_inode;
1419+
struct list_head deferred_closes; /* list of deferred closes */
1420+
spinlock_t deferred_lock; /* protection on deferred list */
14071421
};
14081422

14091423
static inline struct cifsInodeInfo *
@@ -1871,11 +1885,14 @@ extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */
18711885

18721886
void cifs_oplock_break(struct work_struct *work);
18731887
void cifs_queue_oplock_break(struct cifsFileInfo *cfile);
1888+
void smb2_deferred_work_close(struct work_struct *work);
18741889

1890+
extern const struct slow_work_ops cifs_oplock_break_ops;
18751891
extern struct workqueue_struct *cifsiod_wq;
18761892
extern struct workqueue_struct *decrypt_wq;
18771893
extern struct workqueue_struct *fileinfo_put_wq;
18781894
extern struct workqueue_struct *cifsoplockd_wq;
1895+
extern struct workqueue_struct *deferredclose_wq;
18791896
extern __u32 cifs_lock_secret;
18801897

18811898
extern mempool_t *cifs_mid_poolp;

fs/cifs/cifsproto.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,19 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
267267
struct tcon_link *tlink,
268268
struct cifs_pending_open *open);
269269
extern void cifs_del_pending_open(struct cifs_pending_open *open);
270+
271+
extern bool cifs_is_deferred_close(struct cifsFileInfo *cfile,
272+
struct cifs_deferred_close **dclose);
273+
274+
extern void cifs_add_deferred_close(struct cifsFileInfo *cfile,
275+
struct cifs_deferred_close *dclose);
276+
277+
extern void cifs_del_deferred_close(struct cifsFileInfo *cfile);
278+
279+
extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
280+
281+
extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
282+
270283
extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx);
271284
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
272285
int from_reconnect);

fs/cifs/connect.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -392,16 +392,6 @@ cifs_echo_request(struct work_struct *work)
392392
int rc;
393393
struct TCP_Server_Info *server = container_of(work,
394394
struct TCP_Server_Info, echo.work);
395-
unsigned long echo_interval;
396-
397-
/*
398-
* If we need to renegotiate, set echo interval to zero to
399-
* immediately call echo service where we can renegotiate.
400-
*/
401-
if (server->tcpStatus == CifsNeedNegotiate)
402-
echo_interval = 0;
403-
else
404-
echo_interval = server->echo_interval;
405395

406396
/*
407397
* We cannot send an echo if it is disabled.
@@ -412,7 +402,7 @@ cifs_echo_request(struct work_struct *work)
412402
server->tcpStatus == CifsExiting ||
413403
server->tcpStatus == CifsNew ||
414404
(server->ops->can_echo && !server->ops->can_echo(server)) ||
415-
time_before(jiffies, server->lstrp + echo_interval - HZ))
405+
time_before(jiffies, server->lstrp + server->echo_interval - HZ))
416406
goto requeue_echo;
417407

418408
rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
@@ -476,6 +466,7 @@ server_unresponsive(struct TCP_Server_Info *server)
476466
*/
477467
if ((server->tcpStatus == CifsGood ||
478468
server->tcpStatus == CifsNeedNegotiate) &&
469+
(!server->ops->can_echo || server->ops->can_echo(server)) &&
479470
time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
480471
cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
481472
(3 * server->echo_interval) / HZ);
@@ -3158,17 +3149,29 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_
31583149
int
31593150
cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname)
31603151
{
3161-
int rc = 0;
3152+
int rc;
31623153

3163-
smb3_parse_devname(devname, ctx);
3154+
if (devname) {
3155+
cifs_dbg(FYI, "%s: devname=%s\n", __func__, devname);
3156+
rc = smb3_parse_devname(devname, ctx);
3157+
if (rc) {
3158+
cifs_dbg(VFS, "%s: failed to parse %s: %d\n", __func__, devname, rc);
3159+
return rc;
3160+
}
3161+
}
31643162

31653163
if (mntopts) {
31663164
char *ip;
31673165

3168-
cifs_dbg(FYI, "%s: mntopts=%s\n", __func__, mntopts);
31693166
rc = smb3_parse_opt(mntopts, "ip", &ip);
3170-
if (!rc && !cifs_convert_address((struct sockaddr *)&ctx->dstaddr, ip,
3171-
strlen(ip))) {
3167+
if (rc) {
3168+
cifs_dbg(VFS, "%s: failed to parse ip options: %d\n", __func__, rc);
3169+
return rc;
3170+
}
3171+
3172+
rc = cifs_convert_address((struct sockaddr *)&ctx->dstaddr, ip, strlen(ip));
3173+
kfree(ip);
3174+
if (!rc) {
31723175
cifs_dbg(VFS, "%s: failed to convert ip address\n", __func__);
31733176
return -EINVAL;
31743177
}
@@ -3188,7 +3191,7 @@ cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const c
31883191
return -EINVAL;
31893192
}
31903193

3191-
return rc;
3194+
return 0;
31923195
}
31933196

31943197
static int

fs/cifs/dir.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "cifs_fs_sb.h"
3535
#include "cifs_unicode.h"
3636
#include "fs_context.h"
37+
#include "cifs_ioctl.h"
3738

3839
static void
3940
renew_parental_timestamps(struct dentry *direntry)
@@ -430,6 +431,9 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
430431
__u32 oplock;
431432
struct cifsFileInfo *file_info;
432433

434+
if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
435+
return -EIO;
436+
433437
/*
434438
* Posix open is only called (at lookup time) for file create now. For
435439
* opens (rather than creates), because we do not know if it is a file
@@ -546,6 +550,9 @@ int cifs_create(struct user_namespace *mnt_userns, struct inode *inode,
546550
cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
547551
inode, direntry, direntry);
548552

553+
if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
554+
return -EIO;
555+
549556
tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
550557
rc = PTR_ERR(tlink);
551558
if (IS_ERR(tlink))
@@ -583,6 +590,9 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
583590
return -EINVAL;
584591

585592
cifs_sb = CIFS_SB(inode->i_sb);
593+
if (unlikely(cifs_forced_shutdown(cifs_sb)))
594+
return -EIO;
595+
586596
tlink = cifs_sb_tlink(cifs_sb);
587597
if (IS_ERR(tlink))
588598
return PTR_ERR(tlink);

0 commit comments

Comments
 (0)