net: Fix use after free by removing length arg from sk_data_ready callbacks.
[linux.git] / net / sunrpc / xprtsock.c
index 0addefca8e7757d78571928580d6f7473a1354ae..96458d43432409e25bfc71e0cb4031d7c7252c97 100644 (file)
@@ -254,7 +254,7 @@ struct sock_xprt {
        /*
         * Saved socket callback addresses
         */
-       void                    (*old_data_ready)(struct sock *, int);
+       void                    (*old_data_ready)(struct sock *);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
        void                    (*old_error_report)(struct sock *);
@@ -946,7 +946,7 @@ static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
  *
  * Currently this assumes we can read the whole reply in a single gulp.
  */
-static void xs_local_data_ready(struct sock *sk, int len)
+static void xs_local_data_ready(struct sock *sk)
 {
        struct rpc_task *task;
        struct rpc_xprt *xprt;
@@ -1009,7 +1009,7 @@ static void xs_local_data_ready(struct sock *sk, int len)
  * @len: how much data to read
  *
  */
-static void xs_udp_data_ready(struct sock *sk, int len)
+static void xs_udp_data_ready(struct sock *sk)
 {
        struct rpc_task *task;
        struct rpc_xprt *xprt;
@@ -1306,41 +1306,29 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
  * If we're unable to obtain the rpc_rqst we schedule the closing of the
  * connection and return -1.
  */
-static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
+static int xs_tcp_read_callback(struct rpc_xprt *xprt,
                                       struct xdr_skb_reader *desc)
 {
        struct sock_xprt *transport =
                                container_of(xprt, struct sock_xprt, xprt);
        struct rpc_rqst *req;
 
-       req = xprt_alloc_bc_request(xprt);
+       /* Look up and lock the request corresponding to the given XID */
+       spin_lock(&xprt->transport_lock);
+       req = xprt_lookup_bc_request(xprt, transport->tcp_xid);
        if (req == NULL) {
+               spin_unlock(&xprt->transport_lock);
                printk(KERN_WARNING "Callback slot table overflowed\n");
                xprt_force_disconnect(xprt);
                return -1;
        }
 
-       req->rq_xid = transport->tcp_xid;
        dprintk("RPC:       read callback  XID %08x\n", ntohl(req->rq_xid));
        xs_tcp_read_common(xprt, desc, req);
 
-       if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
-               struct svc_serv *bc_serv = xprt->bc_serv;
-
-               /*
-                * Add callback request to callback list.  The callback
-                * service sleeps on the sv_cb_waitq waiting for new
-                * requests.  Wake it up after adding enqueing the
-                * request.
-                */
-               dprintk("RPC:       add callback request to list\n");
-               spin_lock(&bc_serv->sv_cb_lock);
-               list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
-               spin_unlock(&bc_serv->sv_cb_lock);
-               wake_up(&bc_serv->sv_cb_waitq);
-       }
-
-       req->rq_private_buf.len = transport->tcp_copied;
+       if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
+               xprt_complete_bc_request(req, transport->tcp_copied);
+       spin_unlock(&xprt->transport_lock);
 
        return 0;
 }
@@ -1444,7 +1432,7 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
  * @bytes: how much data to read
  *
  */
-static void xs_tcp_data_ready(struct sock *sk, int bytes)
+static void xs_tcp_data_ready(struct sock *sk)
 {
        struct rpc_xprt *xprt;
        read_descriptor_t rd_desc;