]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: add debuging code around sock_hold and sock_put.
authorChris Mason <chris.mason@oracle.com>
Fri, 3 Feb 2012 16:09:07 +0000 (11:09 -0500)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 7 Jul 2015 23:41:32 +0000 (16:41 -0700)
RDS had a recent series of memory corruptions because of
a use-after-free and double-free of rds sockets.  This adds
some debugging code around sock_put and sock_hold to
catch any similar bugs and spit out useful debugging info.

This is a temporary commit while customers try out our fix.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
Signed-off-by: Bang Nguyen <bang.nguyen@oracle.com>
net/rds/af_rds.c
net/rds/rds.h
net/rds/send.c

index f7620f07fc446f6ef135eed03448b39930dd2ec5..63afc6354bab48e01dbd0554a901e23b1492412a 100644 (file)
@@ -98,7 +98,19 @@ static int rds_release(struct socket *sock)
        rds_trans_put(rs->rs_transport);
 
        sock->sk = NULL;
-       sock_put(sk);
+       if ((atomic_read(&sk->sk_refcnt) == 0)) {
+               printk(KERN_CRIT "zero refcnt on sock put release\n");
+               WARN_ON(1);
+       }
+
+       if (atomic_dec_and_test(&sk->sk_refcnt)) {
+               if (rs->poison != 0xABABABAB) {
+                       printk(KERN_CRIT "bad poison on put release %x\n", rs->poison);
+                       WARN_ON(1);
+               }
+               rs->poison = 0xDEADBEEF;
+               sk_free(sk);
+       }
 out:
        return 0;
 }
@@ -430,6 +442,11 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
        INIT_LIST_HEAD(&rs->rs_cong_list);
        spin_lock_init(&rs->rs_rdma_lock);
        rs->rs_rdma_keys = RB_ROOT;
+       rs->poison = 0xABABABAB;
+
+       if (rs->rs_bound_addr) {
+printk(KERN_CRIT "bound addr %x at create\n", rs->rs_bound_addr);
+       }
 
        spin_lock_irqsave(&rds_sock_lock, flags);
        list_add_tail(&rs->rs_item, &rds_sock_list);
@@ -453,14 +470,47 @@ static int rds_create(struct net *net, struct socket *sock, int protocol)
        return __rds_create(sock, sk, protocol);
 }
 
+void debug_sock_hold(struct sock *sk)
+{
+       struct rds_sock *rs = rds_sk_to_rs(sk);
+       if ((atomic_read(&sk->sk_refcnt) == 0)) {
+               printk(KERN_CRIT "zero refcnt on sock hold\n");
+               WARN_ON(1);
+       }
+       if (rs->poison != 0xABABABAB) {
+               printk(KERN_CRIT "bad poison on hold %x\n", rs->poison);
+               WARN_ON(1);
+       }
+       sock_hold(sk);
+}
+
+
 void rds_sock_addref(struct rds_sock *rs)
 {
-       sock_hold(rds_rs_to_sk(rs));
+       debug_sock_hold(rds_rs_to_sk(rs));
+}
+
+void debug_sock_put(struct sock *sk)
+{
+       if ((atomic_read(&sk->sk_refcnt) == 0)) {
+               printk(KERN_CRIT "zero refcnt on sock put\n");
+               WARN_ON(1);
+       }
+       if (atomic_dec_and_test(&sk->sk_refcnt)) {
+               struct rds_sock *rs = rds_sk_to_rs(sk);
+               if (rs->poison != 0xABABABAB) {
+                       printk(KERN_CRIT "bad poison on put %x\n", rs->poison);
+                       WARN_ON(1);
+               }
+               rs->poison = 0xDEADBEEF;
+               sk_free(sk);
+       }
 }
 
+
 void rds_sock_put(struct rds_sock *rs)
 {
-       sock_put(rds_rs_to_sk(rs));
+       debug_sock_put(rds_rs_to_sk(rs));
 }
 
 static struct net_proto_family rds_family_ops = {
index 5590164fbceac1b3ffdefda0e048ae7593c2bbbd..bdf9a8ed1b2a5e008907aa3d69795cdd1bf4764d 100644 (file)
@@ -507,6 +507,7 @@ struct rds_sock {
        /* Socket options - in case there will be more */
        unsigned char           rs_recverr,
                                rs_cong_monitor;
+       int poison;
 };
 
 static inline struct rds_sock *rds_sk_to_rs(const struct sock *sk)
@@ -581,6 +582,8 @@ static inline void __rds_wake_sk_sleep(struct sock *sk)
 }
 extern wait_queue_head_t rds_poll_waitq;
 
+void debug_sock_hold(struct sock *sock);
+void debug_sock_put(struct sock *sock);
 
 /* bind.c */
 int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
index 9967e9f5a65a2b9f8f84bf3446c45ab152923d00..567f4b292a9cc321a6d3b0bdb788e37f08d8a6a8 100644 (file)
@@ -477,7 +477,7 @@ void rds_rdma_send_complete(struct rds_message *rm, int status)
         && ro->op_active && ro->op_notify && ro->op_notifier) {
                notifier = ro->op_notifier;
                rs = rm->m_rs;
-               sock_hold(rds_rs_to_sk(rs));
+               debug_sock_hold(rds_rs_to_sk(rs));
 
                notifier->n_status = status;
                spin_lock(&rs->rs_lock);
@@ -491,7 +491,7 @@ void rds_rdma_send_complete(struct rds_message *rm, int status)
 
        if (rs) {
                rds_wake_sk_sleep(rs);
-               sock_put(rds_rs_to_sk(rs));
+               debug_sock_put(rds_rs_to_sk(rs));
        }
 }
 EXPORT_SYMBOL_GPL(rds_rdma_send_complete);
@@ -513,7 +513,7 @@ void rds_atomic_send_complete(struct rds_message *rm, int status)
            && ao->op_active && ao->op_notify && ao->op_notifier) {
                notifier = ao->op_notifier;
                rs = rm->m_rs;
-               sock_hold(rds_rs_to_sk(rs));
+               debug_sock_hold(rds_rs_to_sk(rs));
 
                notifier->n_status = status;
                spin_lock(&rs->rs_lock);
@@ -527,7 +527,7 @@ void rds_atomic_send_complete(struct rds_message *rm, int status)
 
        if (rs) {
                rds_wake_sk_sleep(rs);
-               sock_put(rds_rs_to_sk(rs));
+               debug_sock_put(rds_rs_to_sk(rs));
        }
 }
 EXPORT_SYMBOL_GPL(rds_atomic_send_complete);
@@ -634,10 +634,10 @@ void rds_send_remove_from_sock(struct list_head *messages, int status)
                if (rs != rm->m_rs) {
                        if (rs) {
                                rds_wake_sk_sleep(rs);
-                               sock_put(rds_rs_to_sk(rs));
+                               debug_sock_put(rds_rs_to_sk(rs));
                        }
                        rs = rm->m_rs;
-                       sock_hold(rds_rs_to_sk(rs));
+                       debug_sock_hold(rds_rs_to_sk(rs));
                }
                spin_lock(&rs->rs_lock);
 
@@ -671,7 +671,7 @@ unlock_and_drop:
 
        if (rs) {
                rds_wake_sk_sleep(rs);
-               sock_put(rds_rs_to_sk(rs));
+               debug_sock_put(rds_rs_to_sk(rs));
        }
 }