Commit 7c9e41e0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 16bb86b5 bae4c0c1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@
#define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */
#define CIFS_MOUNT_RO_CACHE	0x20000000  /* assumes share will not change */
#define CIFS_MOUNT_RW_CACHE	0x40000000  /* assumes only client accessing */
#define CIFS_MOUNT_SHUTDOWN	0x80000000

struct cifs_sb_info {
	struct rb_root tlink_tree;
+35 −0
Original line number Diff line number Diff line
@@ -57,6 +57,12 @@ struct smb_query_info {
	/* char buffer[]; */
} __packed;

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

/*
 * Dump full key (32 byte encrypt/decrypt keys instead of 16 bytes)
 * is needed if GCM256 (stronger encryption) negotiated
 */
struct smb3_full_key_debug_info {
	__u64	Suid;
	__u16	cipher_type;
	__u8	auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */
	__u8	smb3encryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
	__u8	smb3decryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
} __packed;

struct smb3_notify {
	__u32	completion_filter;
	bool	watch_tree;
@@ -78,3 +96,20 @@ struct smb3_notify {
#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
#define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info)
#define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify)
#define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info)
#define CIFS_IOC_SHUTDOWN _IOR ('X', 125, __u32)

/*
 * Flags for going down operation
 */
#define CIFS_GOING_FLAGS_DEFAULT                0x0     /* going down */
#define CIFS_GOING_FLAGS_LOGFLUSH               0x1     /* flush log but not data */
#define CIFS_GOING_FLAGS_NOLOGFLUSH             0x2     /* don't flush log nor data */

static inline bool cifs_forced_shutdown(struct cifs_sb_info *sbi)
{
	if (CIFS_MOUNT_SHUTDOWN & sbi->mnt_cifs_flags)
		return true;
	else
		return false;
}
+16 −9
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ bool enable_oplocks = true;
bool linuxExtEnabled = true;
bool lookupCacheEnabled = true;
bool disable_legacy_dialects; /* false by default */
bool enable_gcm_256;  /* false by default, change when more servers support it */
bool enable_gcm_256 = true;
bool require_gcm_256; /* false by default */
unsigned int global_secflags = CIFSSEC_DEF;
/* unsigned int ntlmv2_support = 0; */
@@ -133,6 +133,7 @@ struct workqueue_struct *cifsiod_wq;
struct workqueue_struct	*decrypt_wq;
struct workqueue_struct	*fileinfo_put_wq;
struct workqueue_struct	*cifsoplockd_wq;
struct workqueue_struct *deferredclose_wq;
__u32 cifs_lock_secret;

/*
@@ -390,6 +391,8 @@ cifs_alloc_inode(struct super_block *sb)
	/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; */
	INIT_LIST_HEAD(&cifs_inode->openFileList);
	INIT_LIST_HEAD(&cifs_inode->llist);
	INIT_LIST_HEAD(&cifs_inode->deferred_closes);
	spin_lock_init(&cifs_inode->deferred_lock);
	return &cifs_inode->vfs_inode;
}

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

	/* cifs_setup_volume_info->smb3_parse_devname() redups UNC & prepath */
	kfree(cifs_sb->ctx->UNC);
	cifs_sb->ctx->UNC = NULL;
	kfree(cifs_sb->ctx->prepath);
	cifs_sb->ctx->prepath = NULL;

	rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, old_ctx->UNC);
	rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, NULL);
	if (rc) {
		root = ERR_PTR(rc);
		goto out;
@@ -1637,9 +1634,16 @@ init_cifs(void)
		goto out_destroy_fileinfo_put_wq;
	}

	deferredclose_wq = alloc_workqueue("deferredclose",
					   WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
	if (!deferredclose_wq) {
		rc = -ENOMEM;
		goto out_destroy_cifsoplockd_wq;
	}

	rc = cifs_fscache_register();
	if (rc)
		goto out_destroy_cifsoplockd_wq;
		goto out_destroy_deferredclose_wq;

	rc = cifs_init_inodecache();
	if (rc)
@@ -1707,6 +1711,8 @@ init_cifs(void)
	cifs_destroy_inodecache();
out_unreg_fscache:
	cifs_fscache_unregister();
out_destroy_deferredclose_wq:
	destroy_workqueue(deferredclose_wq);
out_destroy_cifsoplockd_wq:
	destroy_workqueue(cifsoplockd_wq);
out_destroy_fileinfo_put_wq:
@@ -1741,6 +1747,7 @@ exit_cifs(void)
	cifs_destroy_mids();
	cifs_destroy_inodecache();
	cifs_fscache_unregister();
	destroy_workqueue(deferredclose_wq);
	destroy_workqueue(cifsoplockd_wq);
	destroy_workqueue(decrypt_wq);
	destroy_workqueue(fileinfo_put_wq);
+17 −0
Original line number Diff line number Diff line
@@ -1154,6 +1154,14 @@ struct cifs_pending_open {
	__u32 oplock;
};

struct cifs_deferred_close {
	struct list_head dlist;
	struct tcon_link *tlink;
	__u16  netfid;
	__u64  persistent_fid;
	__u64  volatile_fid;
};

/*
 * This info hangs off the cifsFileInfo structure, pointed to by llist.
 * This is used to track byte stream locks on the file
@@ -1248,6 +1256,9 @@ struct cifsFileInfo {
	struct cifs_search_info srch_inf;
	struct work_struct oplock_break; /* work for oplock breaks */
	struct work_struct put; /* work for the final part of _put */
	struct delayed_work deferred;
	bool oplock_break_received; /* Flag to indicate oplock break */
	bool deferred_scheduled;
};

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

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

void cifs_oplock_break(struct work_struct *work);
void cifs_queue_oplock_break(struct cifsFileInfo *cfile);
void smb2_deferred_work_close(struct work_struct *work);

extern const struct slow_work_ops cifs_oplock_break_ops;
extern struct workqueue_struct *cifsiod_wq;
extern struct workqueue_struct *decrypt_wq;
extern struct workqueue_struct *fileinfo_put_wq;
extern struct workqueue_struct *cifsoplockd_wq;
extern struct workqueue_struct *deferredclose_wq;
extern __u32 cifs_lock_secret;

extern mempool_t *cifs_mid_poolp;
+13 −0
Original line number Diff line number Diff line
@@ -267,6 +267,19 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
					 struct tcon_link *tlink,
					 struct cifs_pending_open *open);
extern void cifs_del_pending_open(struct cifs_pending_open *open);

extern bool cifs_is_deferred_close(struct cifsFileInfo *cfile,
				struct cifs_deferred_close **dclose);

extern void cifs_add_deferred_close(struct cifsFileInfo *cfile,
				struct cifs_deferred_close *dclose);

extern void cifs_del_deferred_close(struct cifsFileInfo *cfile);

extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);

extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);

extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx);
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
				 int from_reconnect);
Loading