Browse Source

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

Pull cifs/smb3 fixes from Steve French:
 "This includes various cifs and smb3 bug fixes including those for bugs
  found with the recently updated xfstests.

  Also I am working fixes for two additional cifs problems found by
  xfstests which I plan to send later (when reviewed and run additional
  tests)"

* 'for-next-3.17' of git://git.samba.org/sfrench/cifs-2.6:
  Clarify Kconfig help text for CIFS and SMB2/SMB3
  CIFS: Fix wrong filename length for SMB2
  CIFS: Fix wrong restart readdir for SMB1
  CIFS: Fix directory rename error
  cifs: No need to send SIGKILL to demux_thread during umount
  cifs: Allow directIO read/write during cache=strict
  cifs: remove unneeded check of null checking in if condition
  cifs: fix a possible use of uninit variable in SMB2_sess_setup
  cifs: fix memory leak when password is supplied multiple times
  cifs: fix a possible null pointer deref in decode_ascii_ssetup
  Trivial whitespace fix
Linus Torvalds 11 years ago
parent
commit
e874a5fe3e
12 changed files with 58 additions and 50 deletions
  1. 23 12
      fs/cifs/Kconfig
  2. 0 5
      fs/cifs/cifsglob.h
  3. 2 19
      fs/cifs/connect.c
  4. 8 0
      fs/cifs/dir.c
  5. 8 0
      fs/cifs/file.c
  6. 4 1
      fs/cifs/inode.c
  7. 2 2
      fs/cifs/readdir.c
  8. 4 3
      fs/cifs/sess.c
  9. 1 1
      fs/cifs/smb2file.c
  10. 1 1
      fs/cifs/smb2inode.c
  11. 2 2
      fs/cifs/smb2ops.c
  12. 3 4
      fs/cifs/smb2pdu.c

+ 23 - 12
fs/cifs/Kconfig

@@ -22,6 +22,11 @@ config CIFS
 	  support for OS/2 and Windows ME and similar servers is provided as
 	  support for OS/2 and Windows ME and similar servers is provided as
 	  well.
 	  well.
 
 
+	  The module also provides optional support for the followon
+	  protocols for CIFS including SMB3, which enables
+	  useful performance and security features (see the description
+	  of CONFIG_CIFS_SMB2).
+
 	  The cifs module provides an advanced network file system
 	  The cifs module provides an advanced network file system
 	  client for mounting to CIFS compliant servers.  It includes
 	  client for mounting to CIFS compliant servers.  It includes
 	  support for DFS (hierarchical name space), secure per-user
 	  support for DFS (hierarchical name space), secure per-user
@@ -121,7 +126,8 @@ config CIFS_ACL
 	  depends on CIFS_XATTR && KEYS
 	  depends on CIFS_XATTR && KEYS
 	  help
 	  help
 	    Allows fetching CIFS/NTFS ACL from the server.  The DACL blob
 	    Allows fetching CIFS/NTFS ACL from the server.  The DACL blob
-	    is handed over to the application/caller.
+	    is handed over to the application/caller.  See the man
+	    page for getcifsacl for more information.
 
 
 config CIFS_DEBUG
 config CIFS_DEBUG
 	bool "Enable CIFS debugging routines"
 	bool "Enable CIFS debugging routines"
@@ -162,7 +168,7 @@ config CIFS_NFSD_EXPORT
 	   Allows NFS server to export a CIFS mounted share (nfsd over cifs)
 	   Allows NFS server to export a CIFS mounted share (nfsd over cifs)
 
 
 config CIFS_SMB2
 config CIFS_SMB2
-	bool "SMB2 network file system support"
+	bool "SMB2 and SMB3 network file system support"
 	depends on CIFS && INET
 	depends on CIFS && INET
 	select NLS
 	select NLS
 	select KEYS
 	select KEYS
@@ -170,16 +176,21 @@ config CIFS_SMB2
 	select DNS_RESOLVER
 	select DNS_RESOLVER
 
 
 	help
 	help
-	  This enables experimental support for the SMB2 (Server Message Block
-	  version 2) protocol. The SMB2 protocol is the successor to the
-	  popular CIFS and SMB network file sharing protocols. SMB2 is the
-	  native file sharing mechanism for recent versions of Windows
-	  operating systems (since Vista).  SMB2 enablement will eventually
-	  allow users better performance, security and features, than would be
-	  possible with cifs. Note that smb2 mount options also are simpler
-	  (compared to cifs) due to protocol improvements.
-
-	  Unless you are a developer or tester, say N.
+	  This enables support for the Server Message Block version 2
+	  family of protocols, including SMB3.  SMB3 support is
+	  enabled on mount by specifying "vers=3.0" in the mount
+	  options. These protocols are the successors to the popular
+	  CIFS and SMB network file sharing protocols. SMB3 is the
+	  native file sharing mechanism for the more recent
+	  versions of Windows (Windows 8 and Windows 2012 and
+	  later) and Samba server and many others support SMB3 well.
+	  In general SMB3 enables better performance, security
+	  and features, than would be possible with CIFS (Note that
+	  when mounting to Samba, due to the CIFS POSIX extensions,
+	  CIFS mounts can provide slightly better POSIX compatibility
+	  than SMB3 mounts do though). Note that SMB2/SMB3 mount
+	  options are also slightly simpler (compared to CIFS) due
+	  to protocol improvements.
 
 
 config CIFS_FSCACHE
 config CIFS_FSCACHE
 	  bool "Provide CIFS client caching support"
 	  bool "Provide CIFS client caching support"

+ 0 - 5
fs/cifs/cifsglob.h

@@ -70,11 +70,6 @@
 #define SERVER_NAME_LENGTH 40
 #define SERVER_NAME_LENGTH 40
 #define SERVER_NAME_LEN_WITH_NULL     (SERVER_NAME_LENGTH + 1)
 #define SERVER_NAME_LEN_WITH_NULL     (SERVER_NAME_LENGTH + 1)
 
 
-/* used to define string lengths for reversing unicode strings */
-/*         (256+1)*2 = 514                                     */
-/*           (max path length + 1 for null) * 2 for unicode    */
-#define MAX_NAME 514
-
 /* SMB echo "timeout" -- FIXME: tunable? */
 /* SMB echo "timeout" -- FIXME: tunable? */
 #define SMB_ECHO_INTERVAL (60 * HZ)
 #define SMB_ECHO_INTERVAL (60 * HZ)
 
 

+ 2 - 19
fs/cifs/connect.c

@@ -837,7 +837,6 @@ cifs_demultiplex_thread(void *p)
 	struct TCP_Server_Info *server = p;
 	struct TCP_Server_Info *server = p;
 	unsigned int pdu_length;
 	unsigned int pdu_length;
 	char *buf = NULL;
 	char *buf = NULL;
-	struct task_struct *task_to_wake = NULL;
 	struct mid_q_entry *mid_entry;
 	struct mid_q_entry *mid_entry;
 
 
 	current->flags |= PF_MEMALLOC;
 	current->flags |= PF_MEMALLOC;
@@ -928,19 +927,7 @@ cifs_demultiplex_thread(void *p)
 	if (server->smallbuf) /* no sense logging a debug message if NULL */
 	if (server->smallbuf) /* no sense logging a debug message if NULL */
 		cifs_small_buf_release(server->smallbuf);
 		cifs_small_buf_release(server->smallbuf);
 
 
-	task_to_wake = xchg(&server->tsk, NULL);
 	clean_demultiplex_info(server);
 	clean_demultiplex_info(server);
-
-	/* if server->tsk was NULL then wait for a signal before exiting */
-	if (!task_to_wake) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		while (!signal_pending(current)) {
-			schedule();
-			set_current_state(TASK_INTERRUPTIBLE);
-		}
-		set_current_state(TASK_RUNNING);
-	}
-
 	module_put_and_exit(0);
 	module_put_and_exit(0);
 }
 }
 
 
@@ -1600,6 +1587,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 			tmp_end++;
 			tmp_end++;
 			if (!(tmp_end < end && tmp_end[1] == delim)) {
 			if (!(tmp_end < end && tmp_end[1] == delim)) {
 				/* No it is not. Set the password to NULL */
 				/* No it is not. Set the password to NULL */
+				kfree(vol->password);
 				vol->password = NULL;
 				vol->password = NULL;
 				break;
 				break;
 			}
 			}
@@ -1637,6 +1625,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 					options = end;
 					options = end;
 			}
 			}
 
 
+			kfree(vol->password);
 			/* Now build new password string */
 			/* Now build new password string */
 			temp_len = strlen(value);
 			temp_len = strlen(value);
 			vol->password = kzalloc(temp_len+1, GFP_KERNEL);
 			vol->password = kzalloc(temp_len+1, GFP_KERNEL);
@@ -2061,8 +2050,6 @@ cifs_find_tcp_session(struct smb_vol *vol)
 static void
 static void
 cifs_put_tcp_session(struct TCP_Server_Info *server)
 cifs_put_tcp_session(struct TCP_Server_Info *server)
 {
 {
-	struct task_struct *task;
-
 	spin_lock(&cifs_tcp_ses_lock);
 	spin_lock(&cifs_tcp_ses_lock);
 	if (--server->srv_count > 0) {
 	if (--server->srv_count > 0) {
 		spin_unlock(&cifs_tcp_ses_lock);
 		spin_unlock(&cifs_tcp_ses_lock);
@@ -2086,10 +2073,6 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
 	kfree(server->session_key.response);
 	kfree(server->session_key.response);
 	server->session_key.response = NULL;
 	server->session_key.response = NULL;
 	server->session_key.len = 0;
 	server->session_key.len = 0;
-
-	task = xchg(&server->tsk, NULL);
-	if (task)
-		force_sig(SIGKILL, task);
 }
 }
 
 
 static struct TCP_Server_Info *
 static struct TCP_Server_Info *

+ 8 - 0
fs/cifs/dir.c

@@ -497,6 +497,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
 		goto out;
 		goto out;
 	}
 	}
 
 
+	if (file->f_flags & O_DIRECT &&
+	    CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
+		if (CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+			file->f_op = &cifs_file_direct_nobrl_ops;
+		else
+			file->f_op = &cifs_file_direct_ops;
+		}
+
 	file_info = cifs_new_fileinfo(&fid, file, tlink, oplock);
 	file_info = cifs_new_fileinfo(&fid, file, tlink, oplock);
 	if (file_info == NULL) {
 	if (file_info == NULL) {
 		if (server->ops->close)
 		if (server->ops->close)

+ 8 - 0
fs/cifs/file.c

@@ -467,6 +467,14 @@ int cifs_open(struct inode *inode, struct file *file)
 	cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
 	cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
 		 inode, file->f_flags, full_path);
 		 inode, file->f_flags, full_path);
 
 
+	if (file->f_flags & O_DIRECT &&
+	    cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
+		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+			file->f_op = &cifs_file_direct_nobrl_ops;
+		else
+			file->f_op = &cifs_file_direct_ops;
+	}
+
 	if (server->oplocks)
 	if (server->oplocks)
 		oplock = REQ_OPLOCK;
 		oplock = REQ_OPLOCK;
 	else
 	else

+ 4 - 1
fs/cifs/inode.c

@@ -1720,7 +1720,10 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
 unlink_target:
 unlink_target:
 	/* Try unlinking the target dentry if it's not negative */
 	/* Try unlinking the target dentry if it's not negative */
 	if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
 	if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
-		tmprc = cifs_unlink(target_dir, target_dentry);
+		if (d_is_dir(target_dentry))
+			tmprc = cifs_rmdir(target_dir, target_dentry);
+		else
+			tmprc = cifs_unlink(target_dir, target_dentry);
 		if (tmprc)
 		if (tmprc)
 			goto cifs_rename_exit;
 			goto cifs_rename_exit;
 		rc = cifs_do_rename(xid, source_dentry, from_name,
 		rc = cifs_do_rename(xid, source_dentry, from_name,

+ 2 - 2
fs/cifs/readdir.c

@@ -596,8 +596,8 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
 		if (server->ops->dir_needs_close(cfile)) {
 		if (server->ops->dir_needs_close(cfile)) {
 			cfile->invalidHandle = true;
 			cfile->invalidHandle = true;
 			spin_unlock(&cifs_file_list_lock);
 			spin_unlock(&cifs_file_list_lock);
-			if (server->ops->close)
-				server->ops->close(xid, tcon, &cfile->fid);
+			if (server->ops->close_dir)
+				server->ops->close_dir(xid, tcon, &cfile->fid);
 		} else
 		} else
 			spin_unlock(&cifs_file_list_lock);
 			spin_unlock(&cifs_file_list_lock);
 		if (cfile->srch_inf.ntwrk_buf_start) {
 		if (cfile->srch_inf.ntwrk_buf_start) {

+ 4 - 3
fs/cifs/sess.c

@@ -243,10 +243,11 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
 	kfree(ses->serverOS);
 	kfree(ses->serverOS);
 
 
 	ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
 	ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
-	if (ses->serverOS)
+	if (ses->serverOS) {
 		strncpy(ses->serverOS, bcc_ptr, len);
 		strncpy(ses->serverOS, bcc_ptr, len);
-	if (strncmp(ses->serverOS, "OS/2", 4) == 0)
-		cifs_dbg(FYI, "OS/2 server\n");
+		if (strncmp(ses->serverOS, "OS/2", 4) == 0)
+			cifs_dbg(FYI, "OS/2 server\n");
+	}
 
 
 	bcc_ptr += len + 1;
 	bcc_ptr += len + 1;
 	bleft -= len + 1;
 	bleft -= len + 1;

+ 1 - 1
fs/cifs/smb2file.c

@@ -50,7 +50,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
 		goto out;
 		goto out;
 	}
 	}
 
 
-	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
 			    GFP_KERNEL);
 			    GFP_KERNEL);
 	if (smb2_data == NULL) {
 	if (smb2_data == NULL) {
 		rc = -ENOMEM;
 		rc = -ENOMEM;

+ 1 - 1
fs/cifs/smb2inode.c

@@ -131,7 +131,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
 	*adjust_tz = false;
 	*adjust_tz = false;
 	*symlink = false;
 	*symlink = false;
 
 
-	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
 			    GFP_KERNEL);
 			    GFP_KERNEL);
 	if (smb2_data == NULL)
 	if (smb2_data == NULL)
 		return -ENOMEM;
 		return -ENOMEM;

+ 2 - 2
fs/cifs/smb2ops.c

@@ -389,7 +389,7 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
 	int rc;
 	int rc;
 	struct smb2_file_all_info *smb2_data;
 	struct smb2_file_all_info *smb2_data;
 
 
-	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
 			    GFP_KERNEL);
 			    GFP_KERNEL);
 	if (smb2_data == NULL)
 	if (smb2_data == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
@@ -1035,7 +1035,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 		if (keep_size == false)
 		if (keep_size == false)
 			return -EOPNOTSUPP;
 			return -EOPNOTSUPP;
 
 
-	/* 
+	/*
 	 * Must check if file sparse since fallocate -z (zero range) assumes
 	 * Must check if file sparse since fallocate -z (zero range) assumes
 	 * non-sparse allocation
 	 * non-sparse allocation
 	 */
 	 */

+ 3 - 4
fs/cifs/smb2pdu.c

@@ -530,7 +530,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
 	struct smb2_sess_setup_rsp *rsp = NULL;
 	struct smb2_sess_setup_rsp *rsp = NULL;
 	struct kvec iov[2];
 	struct kvec iov[2];
 	int rc = 0;
 	int rc = 0;
-	int resp_buftype;
+	int resp_buftype = CIFS_NO_BUFFER;
 	__le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
 	__le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
 	struct TCP_Server_Info *server = ses->server;
 	struct TCP_Server_Info *server = ses->server;
 	u16 blob_length = 0;
 	u16 blob_length = 0;
@@ -1403,8 +1403,7 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
 	rsp = (struct smb2_close_rsp *)iov[0].iov_base;
 	rsp = (struct smb2_close_rsp *)iov[0].iov_base;
 
 
 	if (rc != 0) {
 	if (rc != 0) {
-		if (tcon)
-			cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
+		cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
 		goto close_exit;
 		goto close_exit;
 	}
 	}
 
 
@@ -1533,7 +1532,7 @@ SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
 {
 {
 	return query_info(xid, tcon, persistent_fid, volatile_fid,
 	return query_info(xid, tcon, persistent_fid, volatile_fid,
 			  FILE_ALL_INFORMATION,
 			  FILE_ALL_INFORMATION,
-			  sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+			  sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
 			  sizeof(struct smb2_file_all_info), data);
 			  sizeof(struct smb2_file_all_info), data);
 }
 }