Commit 8560697b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '6.15-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - Fix hard link lease key problem when close is deferred

 - Revert the socket lockdep/refcount workarounds done in cifs.ko now
   that it is fixed at the socket layer

* tag '6.15-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  Revert "smb: client: fix TCP timers deadlock after rmmod"
  Revert "smb: client: Fix netns refcount imbalance causing leaks and use-after-free"
  smb3 client: fix open hardlink on deferred close file error
parents 3088d269 95d2b9f6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -163,6 +163,8 @@ extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
				  struct cifsFileInfo **ret_file);
extern int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode,
				  struct file *file);
extern unsigned int smbCalcSize(void *buf);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
			struct TCP_Server_Info *server);
+9 −25
Original line number Diff line number Diff line
@@ -300,7 +300,6 @@ cifs_abort_connection(struct TCP_Server_Info *server)
			 server->ssocket->flags);
		sock_release(server->ssocket);
		server->ssocket = NULL;
		put_net(cifs_net_ns(server));
	}
	server->sequence_number = 0;
	server->session_estab = false;
@@ -1074,13 +1073,9 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
	msleep(125);
	if (cifs_rdma_enabled(server))
		smbd_destroy(server);

	if (server->ssocket) {
		sock_release(server->ssocket);
		server->ssocket = NULL;

		/* Release netns reference for the socket. */
		put_net(cifs_net_ns(server));
	}

	if (!list_empty(&server->pending_mid_q)) {
@@ -1128,7 +1123,6 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
		 */
	}

	/* Release netns reference for this server. */
	put_net(cifs_net_ns(server));
	kfree(server->leaf_fullpath);
	kfree(server->hostname);
@@ -1774,8 +1768,6 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,

	tcp_ses->ops = ctx->ops;
	tcp_ses->vals = ctx->vals;

	/* Grab netns reference for this server. */
	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));

	tcp_ses->sign = ctx->sign;
@@ -1903,7 +1895,6 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
out_err_crypto_release:
	cifs_crypto_secmech_release(tcp_ses);

	/* Release netns reference for this server. */
	put_net(cifs_net_ns(tcp_ses));

out_err:
@@ -1912,10 +1903,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
			cifs_put_tcp_session(tcp_ses->primary_server, false);
		kfree(tcp_ses->hostname);
		kfree(tcp_ses->leaf_fullpath);
		if (tcp_ses->ssocket) {
		if (tcp_ses->ssocket)
			sock_release(tcp_ses->ssocket);
			put_net(cifs_net_ns(tcp_ses));
		}
		kfree(tcp_ses);
	}
	return ERR_PTR(rc);
@@ -3359,24 +3348,20 @@ generic_ip_connect(struct TCP_Server_Info *server)
		socket = server->ssocket;
	} else {
		struct net *net = cifs_net_ns(server);
		struct sock *sk;

		rc = sock_create_kern(net, sfamily, SOCK_STREAM, IPPROTO_TCP, &server->ssocket);
		rc = __sock_create(net, sfamily, SOCK_STREAM,
				   IPPROTO_TCP, &server->ssocket, 1);
		if (rc < 0) {
			cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
			return rc;
		}

		/*
		 * Grab netns reference for the socket.
		 *
		 * This reference will be released in several situations:
		 * - In the failure path before the cifsd thread is started.
		 * - In the all place where server->socket is released, it is
		 *   also set to NULL.
		 * - Ultimately in clean_demultiplex_info(), during the final
		 *   teardown.
		 */
		get_net(net);
		sk = server->ssocket->sk;
		__netns_tracker_free(net, &sk->ns_tracker, false);
		sk->sk_net_refcnt = 1;
		get_net_track(net, &sk->ns_tracker, GFP_KERNEL);
		sock_inuse_add(net, 1);

		/* BB other socket options to set KEEPALIVE, NODELAY? */
		cifs_dbg(FYI, "Socket created\n");
@@ -3428,7 +3413,6 @@ generic_ip_connect(struct TCP_Server_Info *server)
	if (rc < 0) {
		cifs_dbg(FYI, "Error %d connecting to server\n", rc);
		trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc);
		put_net(cifs_net_ns(server));
		sock_release(socket);
		server->ssocket = NULL;
		return rc;
+28 −0
Original line number Diff line number Diff line
@@ -1007,6 +1007,11 @@ int cifs_open(struct inode *inode, struct file *file)
		} else {
			_cifsFileInfo_put(cfile, true, false);
		}
	} else {
		/* hard link on the defeered close file */
		rc = cifs_get_hardlink_path(tcon, inode, file);
		if (rc)
			cifs_close_deferred_file(CIFS_I(inode));
	}

	if (server->oplocks)
@@ -2071,6 +2076,29 @@ cifs_move_llist(struct list_head *source, struct list_head *dest)
		list_move(li, dest);
}

int
cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode,
				struct file *file)
{
	struct cifsFileInfo *open_file = NULL;
	struct cifsInodeInfo *cinode = CIFS_I(inode);
	int rc = 0;

	spin_lock(&tcon->open_file_lock);
	spin_lock(&cinode->open_file_lock);

	list_for_each_entry(open_file, &cinode->openFileList, flist) {
		if (file->f_flags == open_file->f_flags) {
			rc = -EINVAL;
			break;
		}
	}

	spin_unlock(&cinode->open_file_lock);
	spin_unlock(&tcon->open_file_lock);
	return rc;
}

void
cifs_free_llist(struct list_head *llist)
{