diff mbox series

[v3,3/8] sunrpc: introduce per-netns sunrpc_net->bc_prep_reply_hdr()

Message ID 457b3440-bcbb-2af4-65e7-8af75ef7be32@virtuozzo.com (mailing list archive)
State New, archived
Headers show
Series use-after-free in svc_process_common() | expand

Commit Message

Vasily Averin Dec. 21, 2018, 5:35 p.m. UTC
Currently svc_process_common() uses quite complex schema to adjust reply
header, only required for tcp transports.
This patch adds an alternative way to access required function:
function pointer is added into per-netns sunrpc_net structure during
creation of back channel svc_xprt.

Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
---
 net/sunrpc/netns.h    | 2 ++
 net/sunrpc/svc_xprt.c | 5 +++++
 net/sunrpc/svcsock.c  | 3 +++
 3 files changed, 10 insertions(+)
diff mbox series

Patch

diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index 7ec10b92bea1..ff067107e4f7 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -6,6 +6,7 @@ 
 #include <net/netns/generic.h>
 
 struct cache_detail;
+struct svc_rqst;
 
 struct sunrpc_net {
 	struct proc_dir_entry *proc_net_rpc;
@@ -33,6 +34,7 @@  struct sunrpc_net {
 	int pipe_version;
 	atomic_t pipe_users;
 	struct proc_dir_entry *use_gssp_proc;
+	void (*bc_prep_reply_hdr)(struct svc_rqst *);
 };
 
 extern unsigned int sunrpc_net_id;
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 51d36230b6e3..2ffeecfa0978 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -19,6 +19,8 @@ 
 #include <linux/netdevice.h>
 #include <trace/events/sunrpc.h>
 
+#include "netns.h"
+
 #define RPCDBG_FACILITY	RPCDBG_SVCXPRT
 
 static unsigned int svc_rpc_per_connection_limit __read_mostly;
@@ -134,8 +136,11 @@  static void svc_xprt_free(struct kref *kref)
 	struct svc_xprt *xprt =
 		container_of(kref, struct svc_xprt, xpt_ref);
 	struct module *owner = xprt->xpt_class->xcl_owner;
+	struct sunrpc_net *sn = net_generic(xprt->xpt_net, sunrpc_net_id);
+
 	if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags))
 		svcauth_unix_info_release(xprt);
+	sn->bc_prep_reply_hdr = NULL;
 	put_net(xprt->xpt_net);
 	/* See comment on corresponding get in xs_setup_bc_tcp(): */
 	if (xprt->xpt_bc_xprt)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 986f3ed7d1a2..7c0f9439f94c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -55,6 +55,7 @@ 
 #include <linux/sunrpc/xprt.h>
 
 #include "sunrpc.h"
+#include "netns.h"
 
 #define RPCDBG_FACILITY	RPCDBG_SVCXPRT
 
@@ -1608,6 +1609,7 @@  static struct svc_xprt *svc_bc_create_socket(struct svc_serv *serv,
 {
 	struct svc_sock *svsk;
 	struct svc_xprt *xprt;
+	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
 	if (protocol != IPPROTO_TCP) {
 		printk(KERN_WARNING "svc: only TCP sockets"
@@ -1623,6 +1625,7 @@  static struct svc_xprt *svc_bc_create_socket(struct svc_serv *serv,
 	svc_xprt_init(net, &svc_tcp_bc_class, xprt, serv);
 	set_bit(XPT_CONG_CTRL, &svsk->sk_xprt.xpt_flags);
 
+	sn->bc_prep_reply_hdr = svc_tcp_prep_reply_hdr;
 	serv->sv_bc_xprt = xprt;
 
 	return xprt;