Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 797b9e5a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS updates from Steve French:
 "This patchset is the final section of the SMB2.1 support merge for
  cifs.ko.  It also includes improvements to the cifs socket handling
  from Jeff, and also fixes a few cifs bug fixes.  It adds SMB2 support
  for file and inode operations as well as moves some existing cifs code
  to use ops server struct of protocol specific callbacks.

  Most of this code is SMB2 specific.  When enabled SMB2.1 does pass
  various functional tests including most of the connectathon test
  suite, For SMB2.1, Connectathon test 4 and some related tests fail due
  to not updating mode bits remotely (cifsacl support where mode bits
  are approximated with the cifs acl is not enable for smb2), and test8
  (symlink) support is not completed for SMB2 yet (note that we will
  likely have a "Unix Extensions" eventually, at least for Samba, so in
  the long run posix locks won't have to be emulated when mounting Linux
  to Linux, but for most NAS and for Windows mounts posix lock emulation
  will still used for SMB2 in a similar fashion as we do for cifs).

  SMB2.1 dialect is supported.  Although additional fixes to enable smb2
  (the original smb2.02) dialect and to add various optional features of
  the smb3 dialect are expected to be added in the future as testing
  progresses, currently mounting with the "vers=2.1" is supported (in
  order to mount using SMB2.1 to servers like Samba 4, and Windows 7,
  Windows 2008R2)."

* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6: (82 commits)
  [CIFS] Fix indentation of fs/cifs/Kconfig entries
  [CIFS] Fix SMB2 negotiation support to select only one dialect (based on vers=)
  cifs: obtain file access during backup intent lookup (resend)
  CIFS: Fix possible freed pointer dereference in CIFS_SessSetup
  CIFS: Fix possible freed pointer dereference in SMB2_sess_setup
  CIFS: Make ops->close return void
  cifs: change DOS/NT/POSIX mapping of ERRnoresource
  cifs: remove support for deprecated "forcedirectio" and "strictcache" mount options
  cifs: remove support for CIFS_IOC_CHECKUMOUNT ioctl
  CIFS: Fix possible memory leaks in SMB2 code
  CIFS: Fix endian conversion of IndexNumber
  Trivial endian fixes
  MARK SMB2 support EXPERIMENTAL
  Update cifs version number
  cifs: add FL_CLOSE to fl_flags mask in cifs_read_flock
  cifs: Mangle string used for unc in /proc/mounts
  cifs: cleanups for cifs_mkdir_qinfo
  CIFS: Fix fast lease break after open problem
  CIFS: Add SMB2.1 lease break support
  CIFS: Fix cache coherency for read oplock case
  ...
parents 9c0ece06 1d4ab907
Loading
Loading
Loading
Loading
+20 −18
Original line number Diff line number Diff line
@@ -9,13 +9,14 @@ config CIFS
	select CRYPTO_ARC4
	select CRYPTO_ECB
	select CRYPTO_DES
	select CRYPTO_SHA256
	help
	  This is the client VFS module for the Common Internet File System
	  (CIFS) protocol which is the successor to the Server Message Block
	  (SMB) protocol, the native file sharing mechanism for most early
	  PC operating systems.  The CIFS protocol is fully supported by
	  file servers such as Windows 2000 (including Windows 2003, NT 4
	  and Windows XP) as well by Samba (which provides excellent CIFS
	  file servers such as Windows 2000 (including Windows 2003, Windows 2008,
	  NT 4 and Windows XP) as well by Samba (which provides excellent CIFS
	  server support for Linux and many other operating systems). Limited
	  support for OS/2 and Windows ME and similar servers is provided as
	  well.
@@ -114,6 +115,13 @@ config CIFS_POSIX
	  (such as Samba 3.10 and later) which can negotiate
	  CIFS POSIX ACL support.  If unsure, say N.

config CIFS_ACL
	  bool "Provide CIFS ACL support"
	  depends on CIFS_XATTR && KEYS
	  help
	    Allows fetching CIFS/NTFS ACL from the server.  The DACL blob
	    is handed over to the application/caller.

config CIFS_DEBUG2
	bool "Enable additional CIFS debugging routines"
	depends on CIFS
@@ -138,21 +146,6 @@ config CIFS_DFS_UPCALL
	    IP addresses) which is needed for implicit mounts of DFS junction
	    points. If unsure, say N.

config CIFS_FSCACHE
	  bool "Provide CIFS client caching support"
	  depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
	  help
	    Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
	    to be cached locally on disk through the general filesystem cache
	    manager. If unsure, say N.

config CIFS_ACL
	  bool "Provide CIFS ACL support"
	  depends on CIFS_XATTR && KEYS
	  help
	    Allows to fetch CIFS/NTFS ACL from the server.  The DACL blob
	    is handed over to the application/caller.

config CIFS_NFSD_EXPORT
	  bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)"
	  depends on CIFS && EXPERIMENTAL && BROKEN
@@ -161,7 +154,7 @@ config CIFS_NFSD_EXPORT

config CIFS_SMB2
	bool "SMB2 network file system support (EXPERIMENTAL)"
	depends on EXPERIMENTAL && INET && BROKEN
	depends on CIFS && EXPERIMENTAL && INET
	select NLS
	select KEYS
	select FSCACHE
@@ -178,3 +171,12 @@ config CIFS_SMB2
	  (compared to cifs) due to protocol improvements.

	  Unless you are a developer or tester, say N.

config CIFS_FSCACHE
	  bool "Provide CIFS client caching support"
	  depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
	  help
	    Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
	    to be cached locally on disk through the general filesystem cache
	    manager. If unsure, say N.
+1 −1
Original line number Diff line number Diff line
@@ -17,4 +17,4 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o

cifs-$(CONFIG_CIFS_SMB2) += smb2ops.o smb2maperror.o smb2transport.o \
			    smb2misc.o smb2pdu.o smb2inode.o
			    smb2misc.o smb2pdu.o smb2inode.o smb2file.o
+1 −1
Original line number Diff line number Diff line
@@ -1222,7 +1222,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
	if (!open_file)
		return get_cifs_acl_by_path(cifs_sb, path, pacllen);

	pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
	pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
	cifsFileInfo_put(open_file);
	return pntsd;
}
+58 −9
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "ntlmssp.h"
#include <linux/ctype.h>
#include <linux/random.h>
#include <linux/highmem.h>

/*
 * Calculate and return the CIFS signature based on the mac key and SMB PDU.
@@ -37,11 +38,13 @@
 * the sequence number before this function is called. Also, this function
 * should be called with the server->srv_mutex held.
 */
static int cifs_calc_signature(const struct kvec *iov, int n_vec,
static int cifs_calc_signature(struct smb_rqst *rqst,
			struct TCP_Server_Info *server, char *signature)
{
	int i;
	int rc;
	struct kvec *iov = rqst->rq_iov;
	int n_vec = rqst->rq_nvec;

	if (iov == NULL || signature == NULL || server == NULL)
		return -EINVAL;
@@ -91,6 +94,16 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
		}
	}

	/* now hash over the rq_pages array */
	for (i = 0; i < rqst->rq_npages; i++) {
		struct kvec p_iov;

		cifs_rqst_page_to_kvec(rqst, i, &p_iov);
		crypto_shash_update(&server->secmech.sdescmd5->shash,
					p_iov.iov_base, p_iov.iov_len);
		kunmap(rqst->rq_pages[i]);
	}

	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
	if (rc)
		cERROR(1, "%s: Could not generate md5 hash", __func__);
@@ -99,12 +112,12 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec,
}

/* must be called with server->srv_mutex held */
int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
		   __u32 *pexpected_response_sequence_number)
{
	int rc = 0;
	char smb_signature[20];
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;

	if ((cifs_pdu == NULL) || (server == NULL))
		return -EINVAL;
@@ -125,7 +138,7 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
	*pexpected_response_sequence_number = server->sequence_number++;
	server->sequence_number++;

	rc = cifs_calc_signature(iov, n_vec, server, smb_signature);
	rc = cifs_calc_signature(rqst, server, smb_signature);
	if (rc)
		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
	else
@@ -134,6 +147,15 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
	return rc;
}

int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
		   __u32 *pexpected_response_sequence)
{
	struct smb_rqst rqst = { .rq_iov = iov,
				 .rq_nvec = n_vec };

	return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
}

/* must be called with server->srv_mutex held */
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
		  __u32 *pexpected_response_sequence_number)
@@ -147,14 +169,14 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
			      pexpected_response_sequence_number);
}

int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
int cifs_verify_signature(struct smb_rqst *rqst,
			  struct TCP_Server_Info *server,
			  __u32 expected_sequence_number)
{
	unsigned int rc;
	char server_response_sig[8];
	char what_we_think_sig_should_be[20];
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;

	if (cifs_pdu == NULL || server == NULL)
		return -EINVAL;
@@ -186,8 +208,7 @@ int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
	cifs_pdu->Signature.Sequence.Reserved = 0;

	mutex_lock(&server->srv_mutex);
	rc = cifs_calc_signature(iov, nr_iov, server,
				 what_we_think_sig_should_be);
	rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
	mutex_unlock(&server->srv_mutex);

	if (rc)
@@ -686,12 +707,17 @@ calc_seckey(struct cifs_ses *ses)
void
cifs_crypto_shash_release(struct TCP_Server_Info *server)
{
	if (server->secmech.hmacsha256)
		crypto_free_shash(server->secmech.hmacsha256);

	if (server->secmech.md5)
		crypto_free_shash(server->secmech.md5);

	if (server->secmech.hmacmd5)
		crypto_free_shash(server->secmech.hmacmd5);

	kfree(server->secmech.sdeschmacsha256);

	kfree(server->secmech.sdeschmacmd5);

	kfree(server->secmech.sdescmd5);
@@ -716,6 +742,13 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
		goto crypto_allocate_md5_fail;
	}

	server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
	if (IS_ERR(server->secmech.hmacsha256)) {
		cERROR(1, "could not allocate crypto hmacsha256\n");
		rc = PTR_ERR(server->secmech.hmacsha256);
		goto crypto_allocate_hmacsha256_fail;
	}

	size = sizeof(struct shash_desc) +
			crypto_shash_descsize(server->secmech.hmacmd5);
	server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
@@ -727,7 +760,6 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
	server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
	server->secmech.sdeschmacmd5->shash.flags = 0x0;


	size = sizeof(struct shash_desc) +
			crypto_shash_descsize(server->secmech.md5);
	server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
@@ -739,12 +771,29 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server)
	server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
	server->secmech.sdescmd5->shash.flags = 0x0;

	size = sizeof(struct shash_desc) +
			crypto_shash_descsize(server->secmech.hmacsha256);
	server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
	if (!server->secmech.sdeschmacsha256) {
		cERROR(1, "%s: Can't alloc hmacsha256\n", __func__);
		rc = -ENOMEM;
		goto crypto_allocate_hmacsha256_sdesc_fail;
	}
	server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
	server->secmech.sdeschmacsha256->shash.flags = 0x0;

	return 0;

crypto_allocate_hmacsha256_sdesc_fail:
	kfree(server->secmech.sdescmd5);

crypto_allocate_md5_sdesc_fail:
	kfree(server->secmech.sdeschmacmd5);

crypto_allocate_hmacmd5_sdesc_fail:
	crypto_free_shash(server->secmech.hmacsha256);

crypto_allocate_hmacsha256_fail:
	crypto_free_shash(server->secmech.md5);

crypto_allocate_md5_fail:
+29 −34
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/namei.h>
#include <linux/random.h>
#include <net/ipv6.h>
#include "cifsfs.h"
#include "cifspdu.h"
@@ -51,7 +52,6 @@
#ifdef CONFIG_CIFS_SMB2
#include "smb2pdu.h"
#endif
#define CIFS_MAGIC_NUMBER 0xFF534D42	/* the first four bytes of SMB PDUs */

int cifsFYI = 0;
int cifsERROR = 1;
@@ -89,6 +89,10 @@ extern mempool_t *cifs_mid_poolp;

struct workqueue_struct	*cifsiod_wq;

#ifdef CONFIG_CIFS_SMB2
__u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
#endif

static int
cifs_read_super(struct super_block *sb)
{
@@ -160,13 +164,12 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
	struct super_block *sb = dentry->d_sb;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
	int rc = -EOPNOTSUPP;
	struct TCP_Server_Info *server = tcon->ses->server;
	unsigned int xid;
	int rc = 0;

	xid = get_xid();

	buf->f_type = CIFS_MAGIC_NUMBER;

	/*
	 * PATH_MAX may be too long - it would presumably be total path,
	 * but note that some servers (includinng Samba 3) have a shorter
@@ -178,27 +181,8 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
	buf->f_files = 0;	/* undefined */
	buf->f_ffree = 0;	/* unlimited */

	/*
	 * We could add a second check for a QFS Unix capability bit
	 */
	if ((tcon->ses->capabilities & CAP_UNIX) &&
	    (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability)))
		rc = CIFSSMBQFSPosixInfo(xid, tcon, buf);

	/*
	 * Only need to call the old QFSInfo if failed on newer one,
	 * e.g. by OS/2.
	 **/
	if (rc && (tcon->ses->capabilities & CAP_NT_SMBS))
		rc = CIFSSMBQFSInfo(xid, tcon, buf);

	/*
	 * Some old Windows servers also do not support level 103, retry with
	 * older level one if old server failed the previous call or we
	 * bypassed it because we detected that this was an older LANMAN sess
	 */
	if (rc)
		rc = SMBOldQFSInfo(xid, tcon, buf);
	if (server->ops->queryfs)
		rc = server->ops->queryfs(xid, tcon, buf);

	free_xid(xid);
	return 0;
@@ -239,9 +223,10 @@ cifs_alloc_inode(struct super_block *sb)
		return NULL;
	cifs_inode->cifsAttrs = 0x20;	/* default */
	cifs_inode->time = 0;
	/* Until the file is open and we have gotten oplock
	info back from the server, can not assume caching of
	file data or metadata */
	/*
	 * Until the file is open and we have gotten oplock info back from the
	 * server, can not assume caching of file data or metadata.
	 */
	cifs_set_oplock_level(cifs_inode, 0);
	cifs_inode->delete_pending = false;
	cifs_inode->invalid_mapping = false;
@@ -249,11 +234,16 @@ cifs_alloc_inode(struct super_block *sb)
	cifs_inode->server_eof = 0;
	cifs_inode->uniqueid = 0;
	cifs_inode->createtime = 0;

	/* Can not set i_flags here - they get immediately overwritten
	   to zero by the VFS */
#ifdef CONFIG_CIFS_SMB2
	get_random_bytes(cifs_inode->lease_key, SMB2_LEASE_KEY_SIZE);
#endif
	/*
	 * Can not set i_flags here - they get immediately overwritten to zero
	 * by the VFS.
	 */
	/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; */
	INIT_LIST_HEAD(&cifs_inode->openFileList);
	INIT_LIST_HEAD(&cifs_inode->llist);
	return &cifs_inode->vfs_inode;
}

@@ -360,7 +350,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
	cifs_show_security(s, tcon->ses->server);
	cifs_show_cache_flavor(s, cifs_sb);

	seq_printf(s, ",unc=%s", tcon->treeName);
	seq_printf(s, ",unc=");
	seq_escape(s, tcon->treeName, " \t\n\\");

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
		seq_printf(s, ",multiuser");
@@ -957,7 +948,7 @@ cifs_init_once(void *inode)
	struct cifsInodeInfo *cifsi = inode;

	inode_init_once(&cifsi->vfs_inode);
	mutex_init(&cifsi->lock_mutex);
	init_rwsem(&cifsi->lock_sem);
}

static int
@@ -1127,6 +1118,10 @@ init_cifs(void)
	spin_lock_init(&cifs_file_list_lock);
	spin_lock_init(&GlobalMid_Lock);

#ifdef CONFIG_CIFS_SMB2
	get_random_bytes(cifs_client_guid, SMB2_CLIENT_GUID_SIZE);
#endif

	if (cifs_max_pending < 2) {
		cifs_max_pending = 2;
		cFYI(1, "cifs_max_pending set to min of 2");
Loading