conn_service.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* Service connection management
  2. *
  3. * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public Licence
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the Licence, or (at your option) any later version.
  10. */
  11. #include <linux/slab.h>
  12. #include "ar-internal.h"
  13. /*
  14. * Find a service connection under RCU conditions.
  15. *
  16. * We could use a hash table, but that is subject to bucket stuffing by an
  17. * attacker as the client gets to pick the epoch and cid values and would know
  18. * the hash function. So, instead, we use a hash table for the peer and from
  19. * that an rbtree to find the service connection. Under ordinary circumstances
  20. * it might be slower than a large hash table, but it is at least limited in
  21. * depth.
  22. */
  23. struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *peer,
  24. struct sk_buff *skb)
  25. {
  26. struct rxrpc_connection *conn = NULL;
  27. struct rxrpc_conn_proto k;
  28. struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
  29. struct rb_node *p;
  30. unsigned int seq = 0;
  31. k.epoch = sp->hdr.epoch;
  32. k.cid = sp->hdr.cid & RXRPC_CIDMASK;
  33. do {
  34. /* Unfortunately, rbtree walking doesn't give reliable results
  35. * under just the RCU read lock, so we have to check for
  36. * changes.
  37. */
  38. read_seqbegin_or_lock(&peer->service_conn_lock, &seq);
  39. p = rcu_dereference_raw(peer->service_conns.rb_node);
  40. while (p) {
  41. conn = rb_entry(p, struct rxrpc_connection, service_node);
  42. if (conn->proto.index_key < k.index_key)
  43. p = rcu_dereference_raw(p->rb_left);
  44. else if (conn->proto.index_key > k.index_key)
  45. p = rcu_dereference_raw(p->rb_right);
  46. else
  47. goto done;
  48. conn = NULL;
  49. }
  50. } while (need_seqretry(&peer->service_conn_lock, seq));
  51. done:
  52. done_seqretry(&peer->service_conn_lock, seq);
  53. _leave(" = %d", conn ? conn->debug_id : -1);
  54. return conn;
  55. }
  56. /*
  57. * Insert a service connection into a peer's tree, thereby making it a target
  58. * for incoming packets.
  59. */
  60. static void rxrpc_publish_service_conn(struct rxrpc_peer *peer,
  61. struct rxrpc_connection *conn)
  62. {
  63. struct rxrpc_connection *cursor = NULL;
  64. struct rxrpc_conn_proto k = conn->proto;
  65. struct rb_node **pp, *parent;
  66. write_seqlock_bh(&peer->service_conn_lock);
  67. pp = &peer->service_conns.rb_node;
  68. parent = NULL;
  69. while (*pp) {
  70. parent = *pp;
  71. cursor = rb_entry(parent,
  72. struct rxrpc_connection, service_node);
  73. if (cursor->proto.index_key < k.index_key)
  74. pp = &(*pp)->rb_left;
  75. else if (cursor->proto.index_key > k.index_key)
  76. pp = &(*pp)->rb_right;
  77. else
  78. goto found_extant_conn;
  79. }
  80. rb_link_node_rcu(&conn->service_node, parent, pp);
  81. rb_insert_color(&conn->service_node, &peer->service_conns);
  82. conn_published:
  83. set_bit(RXRPC_CONN_IN_SERVICE_CONNS, &conn->flags);
  84. write_sequnlock_bh(&peer->service_conn_lock);
  85. _leave(" = %d [new]", conn->debug_id);
  86. return;
  87. found_extant_conn:
  88. if (atomic_read(&cursor->usage) == 0)
  89. goto replace_old_connection;
  90. write_sequnlock_bh(&peer->service_conn_lock);
  91. /* We should not be able to get here. rxrpc_incoming_connection() is
  92. * called in a non-reentrant context, so there can't be a race to
  93. * insert a new connection.
  94. */
  95. BUG();
  96. replace_old_connection:
  97. /* The old connection is from an outdated epoch. */
  98. _debug("replace conn");
  99. rb_replace_node_rcu(&cursor->service_node,
  100. &conn->service_node,
  101. &peer->service_conns);
  102. clear_bit(RXRPC_CONN_IN_SERVICE_CONNS, &cursor->flags);
  103. goto conn_published;
  104. }
  105. /*
  106. * Preallocate a service connection. The connection is placed on the proc and
  107. * reap lists so that we don't have to get the lock from BH context.
  108. */
  109. struct rxrpc_connection *rxrpc_prealloc_service_connection(gfp_t gfp)
  110. {
  111. struct rxrpc_connection *conn = rxrpc_alloc_connection(gfp);
  112. if (conn) {
  113. /* We maintain an extra ref on the connection whilst it is on
  114. * the rxrpc_connections list.
  115. */
  116. conn->state = RXRPC_CONN_SERVICE_PREALLOC;
  117. atomic_set(&conn->usage, 2);
  118. write_lock(&rxrpc_connection_lock);
  119. list_add_tail(&conn->link, &rxrpc_connections);
  120. list_add_tail(&conn->proc_link, &rxrpc_connection_proc_list);
  121. write_unlock(&rxrpc_connection_lock);
  122. trace_rxrpc_conn(conn, rxrpc_conn_new_service,
  123. atomic_read(&conn->usage),
  124. __builtin_return_address(0));
  125. }
  126. return conn;
  127. }
  128. /*
  129. * Set up an incoming connection. This is called in BH context with the RCU
  130. * read lock held.
  131. */
  132. void rxrpc_new_incoming_connection(struct rxrpc_connection *conn,
  133. struct sk_buff *skb)
  134. {
  135. struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
  136. _enter("");
  137. conn->proto.epoch = sp->hdr.epoch;
  138. conn->proto.cid = sp->hdr.cid & RXRPC_CIDMASK;
  139. conn->params.service_id = sp->hdr.serviceId;
  140. conn->security_ix = sp->hdr.securityIndex;
  141. conn->out_clientflag = 0;
  142. if (conn->security_ix)
  143. conn->state = RXRPC_CONN_SERVICE_UNSECURED;
  144. else
  145. conn->state = RXRPC_CONN_SERVICE;
  146. /* Make the connection a target for incoming packets. */
  147. rxrpc_publish_service_conn(conn->params.peer, conn);
  148. _net("CONNECTION new %d {%x}", conn->debug_id, conn->proto.cid);
  149. }
  150. /*
  151. * Remove the service connection from the peer's tree, thereby removing it as a
  152. * target for incoming packets.
  153. */
  154. void rxrpc_unpublish_service_conn(struct rxrpc_connection *conn)
  155. {
  156. struct rxrpc_peer *peer = conn->params.peer;
  157. write_seqlock_bh(&peer->service_conn_lock);
  158. if (test_and_clear_bit(RXRPC_CONN_IN_SERVICE_CONNS, &conn->flags))
  159. rb_erase(&conn->service_node, &peer->service_conns);
  160. write_sequnlock_bh(&peer->service_conn_lock);
  161. }