diff options
| -rw-r--r-- | include/linux/rbtree.h | 2 | ||||
| -rw-r--r-- | include/linux/rbtree_augmented.h | 13 | ||||
| -rw-r--r-- | include/linux/rcupdate.h | 8 | ||||
| -rw-r--r-- | lib/rbtree.c | 26 | ||||
| -rw-r--r-- | net/rxrpc/Makefile | 1 | ||||
| -rw-r--r-- | net/rxrpc/af_rxrpc.c | 20 | ||||
| -rw-r--r-- | net/rxrpc/ar-internal.h | 156 | ||||
| -rw-r--r-- | net/rxrpc/call_accept.c | 38 | ||||
| -rw-r--r-- | net/rxrpc/call_event.c | 14 | ||||
| -rw-r--r-- | net/rxrpc/call_object.c | 273 | ||||
| -rw-r--r-- | net/rxrpc/conn_client.c | 282 | ||||
| -rw-r--r-- | net/rxrpc/conn_event.c | 44 | ||||
| -rw-r--r-- | net/rxrpc/conn_object.c | 636 | ||||
| -rw-r--r-- | net/rxrpc/conn_service.c | 230 | ||||
| -rw-r--r-- | net/rxrpc/input.c | 71 | ||||
| -rw-r--r-- | net/rxrpc/insecure.c | 7 | ||||
| -rw-r--r-- | net/rxrpc/local_object.c | 19 | ||||
| -rw-r--r-- | net/rxrpc/peer_object.c | 2 | ||||
| -rw-r--r-- | net/rxrpc/proc.c | 23 | ||||
| -rw-r--r-- | net/rxrpc/rxkad.c | 191 | ||||
| -rw-r--r-- | net/rxrpc/utils.c | 37 |
21 files changed, 1031 insertions, 1062 deletions
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index b6900099ea81..e585018498d5 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h | |||
| @@ -76,6 +76,8 @@ extern struct rb_node *rb_next_postorder(const struct rb_node *); | |||
| 76 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ | 76 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ |
| 77 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, | 77 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, |
| 78 | struct rb_root *root); | 78 | struct rb_root *root); |
| 79 | extern void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, | ||
| 80 | struct rb_root *root); | ||
| 79 | 81 | ||
| 80 | static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, | 82 | static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, |
| 81 | struct rb_node **rb_link) | 83 | struct rb_node **rb_link) |
diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h index 14d7b831b63a..d076183e49be 100644 --- a/include/linux/rbtree_augmented.h +++ b/include/linux/rbtree_augmented.h | |||
| @@ -130,6 +130,19 @@ __rb_change_child(struct rb_node *old, struct rb_node *new, | |||
| 130 | WRITE_ONCE(root->rb_node, new); | 130 | WRITE_ONCE(root->rb_node, new); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | static inline void | ||
| 134 | __rb_change_child_rcu(struct rb_node *old, struct rb_node *new, | ||
| 135 | struct rb_node *parent, struct rb_root *root) | ||
| 136 | { | ||
| 137 | if (parent) { | ||
| 138 | if (parent->rb_left == old) | ||
| 139 | rcu_assign_pointer(parent->rb_left, new); | ||
| 140 | else | ||
| 141 | rcu_assign_pointer(parent->rb_right, new); | ||
| 142 | } else | ||
| 143 | rcu_assign_pointer(root->rb_node, new); | ||
| 144 | } | ||
| 145 | |||
| 133 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, | 146 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, |
| 134 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); | 147 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); |
| 135 | 148 | ||
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 5f1533e3d032..85830e6c797b 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
| @@ -611,6 +611,12 @@ static inline void rcu_preempt_sleep_check(void) | |||
| 611 | rcu_dereference_sparse(p, space); \ | 611 | rcu_dereference_sparse(p, space); \ |
| 612 | ((typeof(*p) __force __kernel *)(p)); \ | 612 | ((typeof(*p) __force __kernel *)(p)); \ |
| 613 | }) | 613 | }) |
| 614 | #define rcu_dereference_raw(p) \ | ||
| 615 | ({ \ | ||
| 616 | /* Dependency order vs. p above. */ \ | ||
| 617 | typeof(p) ________p1 = lockless_dereference(p); \ | ||
| 618 | ((typeof(*p) __force __kernel *)(________p1)); \ | ||
| 619 | }) | ||
| 614 | 620 | ||
| 615 | /** | 621 | /** |
| 616 | * RCU_INITIALIZER() - statically initialize an RCU-protected global variable | 622 | * RCU_INITIALIZER() - statically initialize an RCU-protected global variable |
| @@ -729,8 +735,6 @@ static inline void rcu_preempt_sleep_check(void) | |||
| 729 | __rcu_dereference_check((p), (c) || rcu_read_lock_sched_held(), \ | 735 | __rcu_dereference_check((p), (c) || rcu_read_lock_sched_held(), \ |
| 730 | __rcu) | 736 | __rcu) |
| 731 | 737 | ||
| 732 | #define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/ | ||
| 733 | |||
| 734 | /* | 738 | /* |
| 735 | * The tracing infrastructure traces RCU (we want that), but unfortunately | 739 | * The tracing infrastructure traces RCU (we want that), but unfortunately |
| 736 | * some of the RCU checks causes tracing to lock up the system. | 740 | * some of the RCU checks causes tracing to lock up the system. |
diff --git a/lib/rbtree.c b/lib/rbtree.c index 1356454e36de..eb8a19fee110 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c | |||
| @@ -539,17 +539,39 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new, | |||
| 539 | { | 539 | { |
| 540 | struct rb_node *parent = rb_parent(victim); | 540 | struct rb_node *parent = rb_parent(victim); |
| 541 | 541 | ||
| 542 | /* Copy the pointers/colour from the victim to the replacement */ | ||
| 543 | *new = *victim; | ||
| 544 | |||
| 542 | /* Set the surrounding nodes to point to the replacement */ | 545 | /* Set the surrounding nodes to point to the replacement */ |
| 543 | __rb_change_child(victim, new, parent, root); | ||
| 544 | if (victim->rb_left) | 546 | if (victim->rb_left) |
| 545 | rb_set_parent(victim->rb_left, new); | 547 | rb_set_parent(victim->rb_left, new); |
| 546 | if (victim->rb_right) | 548 | if (victim->rb_right) |
| 547 | rb_set_parent(victim->rb_right, new); | 549 | rb_set_parent(victim->rb_right, new); |
| 550 | __rb_change_child(victim, new, parent, root); | ||
| 551 | } | ||
| 552 | EXPORT_SYMBOL(rb_replace_node); | ||
| 553 | |||
| 554 | void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, | ||
| 555 | struct rb_root *root) | ||
| 556 | { | ||
| 557 | struct rb_node *parent = rb_parent(victim); | ||
| 548 | 558 | ||
| 549 | /* Copy the pointers/colour from the victim to the replacement */ | 559 | /* Copy the pointers/colour from the victim to the replacement */ |
| 550 | *new = *victim; | 560 | *new = *victim; |
| 561 | |||
| 562 | /* Set the surrounding nodes to point to the replacement */ | ||
| 563 | if (victim->rb_left) | ||
| 564 | rb_set_parent(victim->rb_left, new); | ||
| 565 | if (victim->rb_right) | ||
| 566 | rb_set_parent(victim->rb_right, new); | ||
| 567 | |||
| 568 | /* Set the parent's pointer to the new node last after an RCU barrier | ||
| 569 | * so that the pointers onwards are seen to be set correctly when doing | ||
| 570 | * an RCU walk over the tree. | ||
| 571 | */ | ||
| 572 | __rb_change_child_rcu(victim, new, parent, root); | ||
| 551 | } | 573 | } |
| 552 | EXPORT_SYMBOL(rb_replace_node); | 574 | EXPORT_SYMBOL(rb_replace_node_rcu); |
| 553 | 575 | ||
| 554 | static struct rb_node *rb_left_deepest_node(const struct rb_node *node) | 576 | static struct rb_node *rb_left_deepest_node(const struct rb_node *node) |
| 555 | { | 577 | { |
diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile index 6522e50fb750..10f3f48a16a8 100644 --- a/net/rxrpc/Makefile +++ b/net/rxrpc/Makefile | |||
| @@ -10,6 +10,7 @@ af-rxrpc-y := \ | |||
| 10 | conn_client.o \ | 10 | conn_client.o \ |
| 11 | conn_event.o \ | 11 | conn_event.o \ |
| 12 | conn_object.o \ | 12 | conn_object.o \ |
| 13 | conn_service.o \ | ||
| 13 | input.o \ | 14 | input.o \ |
| 14 | insecure.o \ | 15 | insecure.o \ |
| 15 | key.o \ | 16 | key.o \ |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 5d3e795a7c48..d6e4e3b69dc3 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
| @@ -788,27 +788,7 @@ static void __exit af_rxrpc_exit(void) | |||
| 788 | proto_unregister(&rxrpc_proto); | 788 | proto_unregister(&rxrpc_proto); |
| 789 | rxrpc_destroy_all_calls(); | 789 | rxrpc_destroy_all_calls(); |
| 790 | rxrpc_destroy_all_connections(); | 790 | rxrpc_destroy_all_connections(); |
| 791 | |||
| 792 | ASSERTCMP(atomic_read(&rxrpc_n_skbs), ==, 0); | 791 | ASSERTCMP(atomic_read(&rxrpc_n_skbs), ==, 0); |
| 793 | |||
| 794 | /* We need to flush the scheduled work twice because the local endpoint | ||
| 795 | * records involve a work item in their destruction as they can only be | ||
| 796 | * destroyed from process context. However, a connection may have a | ||
| 797 | * work item outstanding - and this will pin the local endpoint record | ||
| 798 | * until the connection goes away. | ||
| 799 | * | ||
| 800 | * Peers don't pin locals and calls pin sockets - which prevents the | ||
| 801 | * module from being unloaded - so we should only need two flushes. | ||
| 802 | */ | ||
| 803 | _debug("flush scheduled work"); | ||
| 804 | flush_workqueue(rxrpc_workqueue); | ||
| 805 | _debug("flush scheduled work 2"); | ||
| 806 | flush_workqueue(rxrpc_workqueue); | ||
| 807 | _debug("synchronise RCU"); | ||
| 808 | rcu_barrier(); | ||
| 809 | _debug("destroy locals"); | ||
| 810 | ASSERT(idr_is_empty(&rxrpc_client_conn_ids)); | ||
| 811 | idr_destroy(&rxrpc_client_conn_ids); | ||
| 812 | rxrpc_destroy_all_locals(); | 792 | rxrpc_destroy_all_locals(); |
| 813 | 793 | ||
| 814 | remove_proc_entry("rxrpc_conns", init_net.proc_net); | 794 | remove_proc_entry("rxrpc_conns", init_net.proc_net); |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 702db72196fb..1bb9e7ac9e14 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/atomic.h> | 12 | #include <linux/atomic.h> |
| 13 | #include <linux/seqlock.h> | ||
| 13 | #include <net/sock.h> | 14 | #include <net/sock.h> |
| 14 | #include <net/af_rxrpc.h> | 15 | #include <net/af_rxrpc.h> |
| 15 | #include <rxrpc/packet.h> | 16 | #include <rxrpc/packet.h> |
| @@ -35,7 +36,6 @@ struct rxrpc_crypt { | |||
| 35 | queue_delayed_work(rxrpc_workqueue, (WS), (D)) | 36 | queue_delayed_work(rxrpc_workqueue, (WS), (D)) |
| 36 | 37 | ||
| 37 | #define rxrpc_queue_call(CALL) rxrpc_queue_work(&(CALL)->processor) | 38 | #define rxrpc_queue_call(CALL) rxrpc_queue_work(&(CALL)->processor) |
| 38 | #define rxrpc_queue_conn(CONN) rxrpc_queue_work(&(CONN)->processor) | ||
| 39 | 39 | ||
| 40 | struct rxrpc_connection; | 40 | struct rxrpc_connection; |
| 41 | 41 | ||
| @@ -141,17 +141,16 @@ struct rxrpc_security { | |||
| 141 | int (*init_connection_security)(struct rxrpc_connection *); | 141 | int (*init_connection_security)(struct rxrpc_connection *); |
| 142 | 142 | ||
| 143 | /* prime a connection's packet security */ | 143 | /* prime a connection's packet security */ |
| 144 | void (*prime_packet_security)(struct rxrpc_connection *); | 144 | int (*prime_packet_security)(struct rxrpc_connection *); |
| 145 | 145 | ||
| 146 | /* impose security on a packet */ | 146 | /* impose security on a packet */ |
| 147 | int (*secure_packet)(const struct rxrpc_call *, | 147 | int (*secure_packet)(struct rxrpc_call *, |
| 148 | struct sk_buff *, | 148 | struct sk_buff *, |
| 149 | size_t, | 149 | size_t, |
| 150 | void *); | 150 | void *); |
| 151 | 151 | ||
| 152 | /* verify the security on a received packet */ | 152 | /* verify the security on a received packet */ |
| 153 | int (*verify_packet)(const struct rxrpc_call *, struct sk_buff *, | 153 | int (*verify_packet)(struct rxrpc_call *, struct sk_buff *, u32 *); |
| 154 | u32 *); | ||
| 155 | 154 | ||
| 156 | /* issue a challenge */ | 155 | /* issue a challenge */ |
| 157 | int (*issue_challenge)(struct rxrpc_connection *); | 156 | int (*issue_challenge)(struct rxrpc_connection *); |
| @@ -208,7 +207,7 @@ struct rxrpc_peer { | |||
| 208 | struct hlist_head error_targets; /* targets for net error distribution */ | 207 | struct hlist_head error_targets; /* targets for net error distribution */ |
| 209 | struct work_struct error_distributor; | 208 | struct work_struct error_distributor; |
| 210 | struct rb_root service_conns; /* Service connections */ | 209 | struct rb_root service_conns; /* Service connections */ |
| 211 | rwlock_t conn_lock; | 210 | seqlock_t service_conn_lock; |
| 212 | spinlock_t lock; /* access lock */ | 211 | spinlock_t lock; /* access lock */ |
| 213 | unsigned int if_mtu; /* interface MTU for this peer */ | 212 | unsigned int if_mtu; /* interface MTU for this peer */ |
| 214 | unsigned int mtu; /* network MTU for this peer */ | 213 | unsigned int mtu; /* network MTU for this peer */ |
| @@ -231,18 +230,12 @@ struct rxrpc_peer { | |||
| 231 | * Keys for matching a connection. | 230 | * Keys for matching a connection. |
| 232 | */ | 231 | */ |
| 233 | struct rxrpc_conn_proto { | 232 | struct rxrpc_conn_proto { |
| 234 | unsigned long hash_key; | 233 | union { |
| 235 | struct rxrpc_local *local; /* Representation of local endpoint */ | 234 | struct { |
| 236 | u32 epoch; /* epoch of this connection */ | 235 | u32 epoch; /* epoch of this connection */ |
| 237 | u32 cid; /* connection ID */ | 236 | u32 cid; /* connection ID */ |
| 238 | u8 in_clientflag; /* RXRPC_CLIENT_INITIATED if we are server */ | 237 | }; |
| 239 | u8 addr_size; /* Size of the address */ | 238 | u64 index_key; |
| 240 | sa_family_t family; /* Transport protocol */ | ||
| 241 | __be16 port; /* Peer UDP/UDP6 port */ | ||
| 242 | union { /* Peer address */ | ||
| 243 | struct in_addr ipv4_addr; | ||
| 244 | struct in6_addr ipv6_addr; | ||
| 245 | u32 raw_addr[0]; | ||
| 246 | }; | 239 | }; |
| 247 | }; | 240 | }; |
| 248 | 241 | ||
| @@ -256,6 +249,37 @@ struct rxrpc_conn_parameters { | |||
| 256 | }; | 249 | }; |
| 257 | 250 | ||
| 258 | /* | 251 | /* |
| 252 | * Bits in the connection flags. | ||
| 253 | */ | ||
| 254 | enum rxrpc_conn_flag { | ||
| 255 | RXRPC_CONN_HAS_IDR, /* Has a client conn ID assigned */ | ||
| 256 | RXRPC_CONN_IN_SERVICE_CONNS, /* Conn is in peer->service_conns */ | ||
| 257 | RXRPC_CONN_IN_CLIENT_CONNS, /* Conn is in local->client_conns */ | ||
| 258 | }; | ||
| 259 | |||
| 260 | /* | ||
| 261 | * Events that can be raised upon a connection. | ||
| 262 | */ | ||
| 263 | enum rxrpc_conn_event { | ||
| 264 | RXRPC_CONN_EV_CHALLENGE, /* Send challenge packet */ | ||
| 265 | }; | ||
| 266 | |||
| 267 | /* | ||
| 268 | * The connection protocol state. | ||
| 269 | */ | ||
| 270 | enum rxrpc_conn_proto_state { | ||
| 271 | RXRPC_CONN_UNUSED, /* Connection not yet attempted */ | ||
| 272 | RXRPC_CONN_CLIENT, /* Client connection */ | ||
| 273 | RXRPC_CONN_SERVICE_UNSECURED, /* Service unsecured connection */ | ||
| 274 | RXRPC_CONN_SERVICE_CHALLENGING, /* Service challenging for security */ | ||
| 275 | RXRPC_CONN_SERVICE, /* Service secured connection */ | ||
| 276 | RXRPC_CONN_REMOTELY_ABORTED, /* Conn aborted by peer */ | ||
| 277 | RXRPC_CONN_LOCALLY_ABORTED, /* Conn aborted locally */ | ||
| 278 | RXRPC_CONN_NETWORK_ERROR, /* Conn terminated by network error */ | ||
| 279 | RXRPC_CONN__NR_STATES | ||
| 280 | }; | ||
| 281 | |||
| 282 | /* | ||
| 259 | * RxRPC connection definition | 283 | * RxRPC connection definition |
| 260 | * - matched by { local, peer, epoch, conn_id, direction } | 284 | * - matched by { local, peer, epoch, conn_id, direction } |
| 261 | * - each connection can only handle four simultaneous calls | 285 | * - each connection can only handle four simultaneous calls |
| @@ -265,44 +289,38 @@ struct rxrpc_connection { | |||
| 265 | struct rxrpc_conn_parameters params; | 289 | struct rxrpc_conn_parameters params; |
| 266 | 290 | ||
| 267 | spinlock_t channel_lock; | 291 | spinlock_t channel_lock; |
| 268 | struct rxrpc_call *channels[RXRPC_MAXCALLS]; /* active calls */ | 292 | |
| 293 | struct rxrpc_channel { | ||
| 294 | struct rxrpc_call __rcu *call; /* Active call */ | ||
| 295 | u32 call_id; /* ID of current call */ | ||
| 296 | u32 call_counter; /* Call ID counter */ | ||
| 297 | u32 last_call; /* ID of last call */ | ||
| 298 | u32 last_result; /* Result of last call (0/abort) */ | ||
| 299 | } channels[RXRPC_MAXCALLS]; | ||
| 269 | wait_queue_head_t channel_wq; /* queue to wait for channel to become available */ | 300 | wait_queue_head_t channel_wq; /* queue to wait for channel to become available */ |
| 270 | 301 | ||
| 302 | struct rcu_head rcu; | ||
| 271 | struct work_struct processor; /* connection event processor */ | 303 | struct work_struct processor; /* connection event processor */ |
| 272 | union { | 304 | union { |
| 273 | struct rb_node client_node; /* Node in local->client_conns */ | 305 | struct rb_node client_node; /* Node in local->client_conns */ |
| 274 | struct rb_node service_node; /* Node in peer->service_conns */ | 306 | struct rb_node service_node; /* Node in peer->service_conns */ |
| 275 | }; | 307 | }; |
| 276 | struct list_head link; /* link in master connection list */ | 308 | struct list_head link; /* link in master connection list */ |
| 277 | struct rb_root calls; /* calls on this connection */ | ||
| 278 | struct sk_buff_head rx_queue; /* received conn-level packets */ | 309 | struct sk_buff_head rx_queue; /* received conn-level packets */ |
| 279 | const struct rxrpc_security *security; /* applied security module */ | 310 | const struct rxrpc_security *security; /* applied security module */ |
| 280 | struct key *server_key; /* security for this service */ | 311 | struct key *server_key; /* security for this service */ |
| 281 | struct crypto_skcipher *cipher; /* encryption handle */ | 312 | struct crypto_skcipher *cipher; /* encryption handle */ |
| 282 | struct rxrpc_crypt csum_iv; /* packet checksum base */ | 313 | struct rxrpc_crypt csum_iv; /* packet checksum base */ |
| 283 | unsigned long flags; | 314 | unsigned long flags; |
| 284 | #define RXRPC_CONN_HAS_IDR 0 /* - Has a client conn ID assigned */ | ||
| 285 | unsigned long events; | 315 | unsigned long events; |
| 286 | #define RXRPC_CONN_CHALLENGE 0 /* send challenge packet */ | ||
| 287 | unsigned long put_time; /* Time at which last put */ | 316 | unsigned long put_time; /* Time at which last put */ |
| 288 | rwlock_t lock; /* access lock */ | ||
| 289 | spinlock_t state_lock; /* state-change lock */ | 317 | spinlock_t state_lock; /* state-change lock */ |
| 290 | atomic_t usage; | 318 | atomic_t usage; |
| 291 | enum { /* current state of connection */ | 319 | enum rxrpc_conn_proto_state state : 8; /* current state of connection */ |
| 292 | RXRPC_CONN_UNUSED, /* - connection not yet attempted */ | ||
| 293 | RXRPC_CONN_CLIENT, /* - client connection */ | ||
| 294 | RXRPC_CONN_SERVER_UNSECURED, /* - server unsecured connection */ | ||
| 295 | RXRPC_CONN_SERVER_CHALLENGING, /* - server challenging for security */ | ||
| 296 | RXRPC_CONN_SERVER, /* - server secured connection */ | ||
| 297 | RXRPC_CONN_REMOTELY_ABORTED, /* - conn aborted by peer */ | ||
| 298 | RXRPC_CONN_LOCALLY_ABORTED, /* - conn aborted locally */ | ||
| 299 | RXRPC_CONN_NETWORK_ERROR, /* - conn terminated by network error */ | ||
| 300 | } state; | ||
| 301 | u32 local_abort; /* local abort code */ | 320 | u32 local_abort; /* local abort code */ |
| 302 | u32 remote_abort; /* remote abort code */ | 321 | u32 remote_abort; /* remote abort code */ |
| 303 | int error; /* local error incurred */ | 322 | int error; /* local error incurred */ |
| 304 | int debug_id; /* debug ID for printks */ | 323 | int debug_id; /* debug ID for printks */ |
| 305 | unsigned int call_counter; /* call ID counter */ | ||
| 306 | atomic_t serial; /* packet serial number counter */ | 324 | atomic_t serial; /* packet serial number counter */ |
| 307 | atomic_t hi_serial; /* highest serial number received */ | 325 | atomic_t hi_serial; /* highest serial number received */ |
| 308 | atomic_t avail_chans; /* number of channels available */ | 326 | atomic_t avail_chans; /* number of channels available */ |
| @@ -382,6 +400,7 @@ enum rxrpc_call_state { | |||
| 382 | * - matched by { connection, call_id } | 400 | * - matched by { connection, call_id } |
| 383 | */ | 401 | */ |
| 384 | struct rxrpc_call { | 402 | struct rxrpc_call { |
| 403 | struct rcu_head rcu; | ||
| 385 | struct rxrpc_connection *conn; /* connection carrying call */ | 404 | struct rxrpc_connection *conn; /* connection carrying call */ |
| 386 | struct rxrpc_sock *socket; /* socket responsible */ | 405 | struct rxrpc_sock *socket; /* socket responsible */ |
| 387 | struct timer_list lifetimer; /* lifetime remaining on call */ | 406 | struct timer_list lifetimer; /* lifetime remaining on call */ |
| @@ -394,11 +413,11 @@ struct rxrpc_call { | |||
| 394 | struct hlist_node error_link; /* link in error distribution list */ | 413 | struct hlist_node error_link; /* link in error distribution list */ |
| 395 | struct list_head accept_link; /* calls awaiting acceptance */ | 414 | struct list_head accept_link; /* calls awaiting acceptance */ |
| 396 | struct rb_node sock_node; /* node in socket call tree */ | 415 | struct rb_node sock_node; /* node in socket call tree */ |
| 397 | struct rb_node conn_node; /* node in connection call tree */ | ||
| 398 | struct sk_buff_head rx_queue; /* received packets */ | 416 | struct sk_buff_head rx_queue; /* received packets */ |
| 399 | struct sk_buff_head rx_oos_queue; /* packets received out of sequence */ | 417 | struct sk_buff_head rx_oos_queue; /* packets received out of sequence */ |
| 400 | struct sk_buff *tx_pending; /* Tx socket buffer being filled */ | 418 | struct sk_buff *tx_pending; /* Tx socket buffer being filled */ |
| 401 | wait_queue_head_t tx_waitq; /* wait for Tx window space to become available */ | 419 | wait_queue_head_t tx_waitq; /* wait for Tx window space to become available */ |
| 420 | __be32 crypto_buf[2]; /* Temporary packet crypto buffer */ | ||
| 402 | unsigned long user_call_ID; /* user-defined call ID */ | 421 | unsigned long user_call_ID; /* user-defined call ID */ |
| 403 | unsigned long creation_jif; /* time of call creation */ | 422 | unsigned long creation_jif; /* time of call creation */ |
| 404 | unsigned long flags; | 423 | unsigned long flags; |
| @@ -442,19 +461,12 @@ struct rxrpc_call { | |||
| 442 | #define RXRPC_ACKR_WINDOW_ASZ DIV_ROUND_UP(RXRPC_MAXACKS, BITS_PER_LONG) | 461 | #define RXRPC_ACKR_WINDOW_ASZ DIV_ROUND_UP(RXRPC_MAXACKS, BITS_PER_LONG) |
| 443 | unsigned long ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1]; | 462 | unsigned long ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1]; |
| 444 | 463 | ||
| 445 | struct hlist_node hash_node; | 464 | u8 in_clientflag; /* Copy of conn->in_clientflag */ |
| 446 | unsigned long hash_key; /* Full hash key */ | 465 | struct rxrpc_local *local; /* Local endpoint. */ |
| 447 | u8 in_clientflag; /* Copy of conn->in_clientflag for hashing */ | ||
| 448 | struct rxrpc_local *local; /* Local endpoint. Used for hashing. */ | ||
| 449 | sa_family_t family; /* Frame protocol */ | ||
| 450 | u32 call_id; /* call ID on connection */ | 466 | u32 call_id; /* call ID on connection */ |
| 451 | u32 cid; /* connection ID plus channel index */ | 467 | u32 cid; /* connection ID plus channel index */ |
| 452 | u32 epoch; /* epoch of this connection */ | 468 | u32 epoch; /* epoch of this connection */ |
| 453 | u16 service_id; /* service ID */ | 469 | u16 service_id; /* service ID */ |
| 454 | union { /* Peer IP address for hashing */ | ||
| 455 | __be32 ipv4_addr; | ||
| 456 | __u8 ipv6_addr[16]; /* Anticipates eventual IPv6 support */ | ||
| 457 | } peer_ip; | ||
| 458 | }; | 470 | }; |
| 459 | 471 | ||
| 460 | /* | 472 | /* |
| @@ -502,8 +514,6 @@ extern struct kmem_cache *rxrpc_call_jar; | |||
| 502 | extern struct list_head rxrpc_calls; | 514 | extern struct list_head rxrpc_calls; |
| 503 | extern rwlock_t rxrpc_call_lock; | 515 | extern rwlock_t rxrpc_call_lock; |
| 504 | 516 | ||
| 505 | struct rxrpc_call *rxrpc_find_call_hash(struct rxrpc_host_header *, | ||
| 506 | void *, sa_family_t, const void *); | ||
| 507 | struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *, unsigned long); | 517 | struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *, unsigned long); |
| 508 | struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *, | 518 | struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *, |
| 509 | struct rxrpc_conn_parameters *, | 519 | struct rxrpc_conn_parameters *, |
| @@ -522,8 +532,10 @@ void __exit rxrpc_destroy_all_calls(void); | |||
| 522 | */ | 532 | */ |
| 523 | extern struct idr rxrpc_client_conn_ids; | 533 | extern struct idr rxrpc_client_conn_ids; |
| 524 | 534 | ||
| 525 | int rxrpc_get_client_connection_id(struct rxrpc_connection *, gfp_t); | 535 | void rxrpc_destroy_client_conn_ids(void); |
| 526 | void rxrpc_put_client_connection_id(struct rxrpc_connection *); | 536 | int rxrpc_connect_call(struct rxrpc_call *, struct rxrpc_conn_parameters *, |
| 537 | struct sockaddr_rxrpc *, gfp_t); | ||
| 538 | void rxrpc_unpublish_client_conn(struct rxrpc_connection *); | ||
| 527 | 539 | ||
| 528 | /* | 540 | /* |
| 529 | * conn_event.c | 541 | * conn_event.c |
| @@ -539,17 +551,14 @@ extern unsigned int rxrpc_connection_expiry; | |||
| 539 | extern struct list_head rxrpc_connections; | 551 | extern struct list_head rxrpc_connections; |
| 540 | extern rwlock_t rxrpc_connection_lock; | 552 | extern rwlock_t rxrpc_connection_lock; |
| 541 | 553 | ||
| 542 | int rxrpc_connect_call(struct rxrpc_call *, struct rxrpc_conn_parameters *, | 554 | int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *); |
| 543 | struct sockaddr_rxrpc *, gfp_t); | 555 | struct rxrpc_connection *rxrpc_alloc_connection(gfp_t); |
| 544 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *, | 556 | struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *, |
| 545 | struct rxrpc_peer *, | 557 | struct sk_buff *); |
| 546 | struct sk_buff *); | 558 | void __rxrpc_disconnect_call(struct rxrpc_call *); |
| 547 | void rxrpc_disconnect_call(struct rxrpc_call *); | 559 | void rxrpc_disconnect_call(struct rxrpc_call *); |
| 548 | void rxrpc_put_connection(struct rxrpc_connection *); | 560 | void rxrpc_put_connection(struct rxrpc_connection *); |
| 549 | void __exit rxrpc_destroy_all_connections(void); | 561 | void __exit rxrpc_destroy_all_connections(void); |
| 550 | struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *, | ||
| 551 | struct rxrpc_peer *, | ||
| 552 | struct sk_buff *); | ||
| 553 | 562 | ||
| 554 | static inline bool rxrpc_conn_is_client(const struct rxrpc_connection *conn) | 563 | static inline bool rxrpc_conn_is_client(const struct rxrpc_connection *conn) |
| 555 | { | 564 | { |
| @@ -558,7 +567,7 @@ static inline bool rxrpc_conn_is_client(const struct rxrpc_connection *conn) | |||
| 558 | 567 | ||
| 559 | static inline bool rxrpc_conn_is_service(const struct rxrpc_connection *conn) | 568 | static inline bool rxrpc_conn_is_service(const struct rxrpc_connection *conn) |
| 560 | { | 569 | { |
| 561 | return conn->proto.in_clientflag; | 570 | return !rxrpc_conn_is_client(conn); |
| 562 | } | 571 | } |
| 563 | 572 | ||
| 564 | static inline void rxrpc_get_connection(struct rxrpc_connection *conn) | 573 | static inline void rxrpc_get_connection(struct rxrpc_connection *conn) |
| @@ -566,6 +575,31 @@ static inline void rxrpc_get_connection(struct rxrpc_connection *conn) | |||
| 566 | atomic_inc(&conn->usage); | 575 | atomic_inc(&conn->usage); |
| 567 | } | 576 | } |
| 568 | 577 | ||
| 578 | static inline | ||
| 579 | struct rxrpc_connection *rxrpc_get_connection_maybe(struct rxrpc_connection *conn) | ||
| 580 | { | ||
| 581 | return atomic_inc_not_zero(&conn->usage) ? conn : NULL; | ||
| 582 | } | ||
| 583 | |||
| 584 | static inline bool rxrpc_queue_conn(struct rxrpc_connection *conn) | ||
| 585 | { | ||
| 586 | if (!rxrpc_get_connection_maybe(conn)) | ||
| 587 | return false; | ||
| 588 | if (!rxrpc_queue_work(&conn->processor)) | ||
| 589 | rxrpc_put_connection(conn); | ||
| 590 | return true; | ||
| 591 | } | ||
| 592 | |||
| 593 | /* | ||
| 594 | * conn_service.c | ||
| 595 | */ | ||
| 596 | struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *, | ||
| 597 | struct sk_buff *); | ||
| 598 | struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *, | ||
| 599 | struct sockaddr_rxrpc *, | ||
| 600 | struct sk_buff *); | ||
| 601 | void rxrpc_unpublish_service_conn(struct rxrpc_connection *); | ||
| 602 | |||
| 569 | /* | 603 | /* |
| 570 | * input.c | 604 | * input.c |
| 571 | */ | 605 | */ |
| @@ -618,6 +652,11 @@ static inline void rxrpc_put_local(struct rxrpc_local *local) | |||
| 618 | __rxrpc_put_local(local); | 652 | __rxrpc_put_local(local); |
| 619 | } | 653 | } |
| 620 | 654 | ||
| 655 | static inline void rxrpc_queue_local(struct rxrpc_local *local) | ||
| 656 | { | ||
| 657 | rxrpc_queue_work(&local->processor); | ||
| 658 | } | ||
| 659 | |||
| 621 | /* | 660 | /* |
| 622 | * misc.c | 661 | * misc.c |
| 623 | */ | 662 | */ |
| @@ -722,8 +761,7 @@ static inline void rxrpc_sysctl_exit(void) {} | |||
| 722 | /* | 761 | /* |
| 723 | * utils.c | 762 | * utils.c |
| 724 | */ | 763 | */ |
| 725 | void rxrpc_get_addr_from_skb(struct rxrpc_local *, const struct sk_buff *, | 764 | int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *); |
| 726 | struct sockaddr_rxrpc *); | ||
| 727 | 765 | ||
| 728 | /* | 766 | /* |
| 729 | * debug tracing | 767 | * debug tracing |
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c index 202e053a3c6d..0b2832141bd0 100644 --- a/net/rxrpc/call_accept.c +++ b/net/rxrpc/call_accept.c | |||
| @@ -75,7 +75,6 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, | |||
| 75 | { | 75 | { |
| 76 | struct rxrpc_connection *conn; | 76 | struct rxrpc_connection *conn; |
| 77 | struct rxrpc_skb_priv *sp, *nsp; | 77 | struct rxrpc_skb_priv *sp, *nsp; |
| 78 | struct rxrpc_peer *peer; | ||
| 79 | struct rxrpc_call *call; | 78 | struct rxrpc_call *call; |
| 80 | struct sk_buff *notification; | 79 | struct sk_buff *notification; |
| 81 | int ret; | 80 | int ret; |
| @@ -94,15 +93,7 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, | |||
| 94 | rxrpc_new_skb(notification); | 93 | rxrpc_new_skb(notification); |
| 95 | notification->mark = RXRPC_SKB_MARK_NEW_CALL; | 94 | notification->mark = RXRPC_SKB_MARK_NEW_CALL; |
| 96 | 95 | ||
| 97 | peer = rxrpc_lookup_peer(local, srx, GFP_NOIO); | 96 | conn = rxrpc_incoming_connection(local, srx, skb); |
| 98 | if (!peer) { | ||
| 99 | _debug("no peer"); | ||
| 100 | ret = -EBUSY; | ||
| 101 | goto error; | ||
| 102 | } | ||
| 103 | |||
| 104 | conn = rxrpc_incoming_connection(local, peer, skb); | ||
| 105 | rxrpc_put_peer(peer); | ||
| 106 | if (IS_ERR(conn)) { | 97 | if (IS_ERR(conn)) { |
| 107 | _debug("no conn"); | 98 | _debug("no conn"); |
| 108 | ret = PTR_ERR(conn); | 99 | ret = PTR_ERR(conn); |
| @@ -128,12 +119,11 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, | |||
| 128 | 119 | ||
| 129 | spin_lock(&call->conn->state_lock); | 120 | spin_lock(&call->conn->state_lock); |
| 130 | if (sp->hdr.securityIndex > 0 && | 121 | if (sp->hdr.securityIndex > 0 && |
| 131 | call->conn->state == RXRPC_CONN_SERVER_UNSECURED) { | 122 | call->conn->state == RXRPC_CONN_SERVICE_UNSECURED) { |
| 132 | _debug("await conn sec"); | 123 | _debug("await conn sec"); |
| 133 | list_add_tail(&call->accept_link, &rx->secureq); | 124 | list_add_tail(&call->accept_link, &rx->secureq); |
| 134 | call->conn->state = RXRPC_CONN_SERVER_CHALLENGING; | 125 | call->conn->state = RXRPC_CONN_SERVICE_CHALLENGING; |
| 135 | rxrpc_get_connection(call->conn); | 126 | set_bit(RXRPC_CONN_EV_CHALLENGE, &call->conn->events); |
| 136 | set_bit(RXRPC_CONN_CHALLENGE, &call->conn->events); | ||
| 137 | rxrpc_queue_conn(call->conn); | 127 | rxrpc_queue_conn(call->conn); |
| 138 | } else { | 128 | } else { |
| 139 | _debug("conn ready"); | 129 | _debug("conn ready"); |
| @@ -227,20 +217,8 @@ void rxrpc_accept_incoming_calls(struct rxrpc_local *local) | |||
| 227 | whdr._rsvd = 0; | 217 | whdr._rsvd = 0; |
| 228 | whdr.serviceId = htons(sp->hdr.serviceId); | 218 | whdr.serviceId = htons(sp->hdr.serviceId); |
| 229 | 219 | ||
| 230 | /* determine the remote address */ | 220 | if (rxrpc_extract_addr_from_skb(&srx, skb) < 0) |
| 231 | memset(&srx, 0, sizeof(srx)); | 221 | goto drop; |
| 232 | srx.srx_family = AF_RXRPC; | ||
| 233 | srx.transport.family = local->srx.transport.family; | ||
| 234 | srx.transport_type = local->srx.transport_type; | ||
| 235 | switch (srx.transport.family) { | ||
| 236 | case AF_INET: | ||
| 237 | srx.transport_len = sizeof(struct sockaddr_in); | ||
| 238 | srx.transport.sin.sin_port = udp_hdr(skb)->source; | ||
| 239 | srx.transport.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; | ||
| 240 | break; | ||
| 241 | default: | ||
| 242 | goto busy; | ||
| 243 | } | ||
| 244 | 222 | ||
| 245 | /* get the socket providing the service */ | 223 | /* get the socket providing the service */ |
| 246 | read_lock_bh(&local->services_lock); | 224 | read_lock_bh(&local->services_lock); |
| @@ -286,6 +264,10 @@ busy: | |||
| 286 | rxrpc_free_skb(skb); | 264 | rxrpc_free_skb(skb); |
| 287 | return; | 265 | return; |
| 288 | 266 | ||
| 267 | drop: | ||
| 268 | rxrpc_free_skb(skb); | ||
| 269 | return; | ||
| 270 | |||
| 289 | invalid_service: | 271 | invalid_service: |
| 290 | skb->priority = RX_INVALID_OPERATION; | 272 | skb->priority = RX_INVALID_OPERATION; |
| 291 | rxrpc_reject_packet(local, skb); | 273 | rxrpc_reject_packet(local, skb); |
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c index 0ba84295f913..fc32aa5764a2 100644 --- a/net/rxrpc/call_event.c +++ b/net/rxrpc/call_event.c | |||
| @@ -858,11 +858,6 @@ void rxrpc_process_call(struct work_struct *work) | |||
| 858 | iov[0].iov_len = sizeof(whdr); | 858 | iov[0].iov_len = sizeof(whdr); |
| 859 | 859 | ||
| 860 | /* deal with events of a final nature */ | 860 | /* deal with events of a final nature */ |
| 861 | if (test_bit(RXRPC_CALL_EV_RELEASE, &call->events)) { | ||
| 862 | rxrpc_release_call(call); | ||
| 863 | clear_bit(RXRPC_CALL_EV_RELEASE, &call->events); | ||
| 864 | } | ||
| 865 | |||
| 866 | if (test_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events)) { | 861 | if (test_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events)) { |
| 867 | enum rxrpc_skb_mark mark; | 862 | enum rxrpc_skb_mark mark; |
| 868 | int error; | 863 | int error; |
| @@ -1094,7 +1089,7 @@ void rxrpc_process_call(struct work_struct *work) | |||
| 1094 | 1089 | ||
| 1095 | if (call->state == RXRPC_CALL_SERVER_SECURING) { | 1090 | if (call->state == RXRPC_CALL_SERVER_SECURING) { |
| 1096 | _debug("securing"); | 1091 | _debug("securing"); |
| 1097 | write_lock(&call->conn->lock); | 1092 | write_lock(&call->socket->call_lock); |
| 1098 | if (!test_bit(RXRPC_CALL_RELEASED, &call->flags) && | 1093 | if (!test_bit(RXRPC_CALL_RELEASED, &call->flags) && |
| 1099 | !test_bit(RXRPC_CALL_EV_RELEASE, &call->events)) { | 1094 | !test_bit(RXRPC_CALL_EV_RELEASE, &call->events)) { |
| 1100 | _debug("not released"); | 1095 | _debug("not released"); |
| @@ -1102,7 +1097,7 @@ void rxrpc_process_call(struct work_struct *work) | |||
| 1102 | list_move_tail(&call->accept_link, | 1097 | list_move_tail(&call->accept_link, |
| 1103 | &call->socket->acceptq); | 1098 | &call->socket->acceptq); |
| 1104 | } | 1099 | } |
| 1105 | write_unlock(&call->conn->lock); | 1100 | write_unlock(&call->socket->call_lock); |
| 1106 | read_lock(&call->state_lock); | 1101 | read_lock(&call->state_lock); |
| 1107 | if (call->state < RXRPC_CALL_COMPLETE) | 1102 | if (call->state < RXRPC_CALL_COMPLETE) |
| 1108 | set_bit(RXRPC_CALL_EV_POST_ACCEPT, &call->events); | 1103 | set_bit(RXRPC_CALL_EV_POST_ACCEPT, &call->events); |
| @@ -1144,6 +1139,11 @@ void rxrpc_process_call(struct work_struct *work) | |||
| 1144 | goto maybe_reschedule; | 1139 | goto maybe_reschedule; |
| 1145 | } | 1140 | } |
| 1146 | 1141 | ||
| 1142 | if (test_bit(RXRPC_CALL_EV_RELEASE, &call->events)) { | ||
| 1143 | rxrpc_release_call(call); | ||
| 1144 | clear_bit(RXRPC_CALL_EV_RELEASE, &call->events); | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | /* other events may have been raised since we started checking */ | 1147 | /* other events may have been raised since we started checking */ |
| 1148 | goto maybe_reschedule; | 1148 | goto maybe_reschedule; |
| 1149 | 1149 | ||
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index ad933daae13b..91287c9d01bb 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/circ_buf.h> | 16 | #include <linux/circ_buf.h> |
| 17 | #include <linux/hashtable.h> | ||
| 18 | #include <linux/spinlock_types.h> | 17 | #include <linux/spinlock_types.h> |
| 19 | #include <net/sock.h> | 18 | #include <net/sock.h> |
| 20 | #include <net/af_rxrpc.h> | 19 | #include <net/af_rxrpc.h> |
| @@ -61,142 +60,6 @@ static void rxrpc_dead_call_expired(unsigned long _call); | |||
| 61 | static void rxrpc_ack_time_expired(unsigned long _call); | 60 | static void rxrpc_ack_time_expired(unsigned long _call); |
| 62 | static void rxrpc_resend_time_expired(unsigned long _call); | 61 | static void rxrpc_resend_time_expired(unsigned long _call); |
| 63 | 62 | ||
| 64 | static DEFINE_SPINLOCK(rxrpc_call_hash_lock); | ||
| 65 | static DEFINE_HASHTABLE(rxrpc_call_hash, 10); | ||
| 66 | |||
| 67 | /* | ||
| 68 | * Hash function for rxrpc_call_hash | ||
| 69 | */ | ||
| 70 | static unsigned long rxrpc_call_hashfunc( | ||
| 71 | u8 in_clientflag, | ||
| 72 | u32 cid, | ||
| 73 | u32 call_id, | ||
| 74 | u32 epoch, | ||
| 75 | u16 service_id, | ||
| 76 | sa_family_t family, | ||
| 77 | void *localptr, | ||
| 78 | unsigned int addr_size, | ||
| 79 | const u8 *peer_addr) | ||
| 80 | { | ||
| 81 | const u16 *p; | ||
| 82 | unsigned int i; | ||
| 83 | unsigned long key; | ||
| 84 | |||
| 85 | _enter(""); | ||
| 86 | |||
| 87 | key = (unsigned long)localptr; | ||
| 88 | /* We just want to add up the __be32 values, so forcing the | ||
| 89 | * cast should be okay. | ||
| 90 | */ | ||
| 91 | key += epoch; | ||
| 92 | key += service_id; | ||
| 93 | key += call_id; | ||
| 94 | key += (cid & RXRPC_CIDMASK) >> RXRPC_CIDSHIFT; | ||
| 95 | key += cid & RXRPC_CHANNELMASK; | ||
| 96 | key += in_clientflag; | ||
| 97 | key += family; | ||
| 98 | /* Step through the peer address in 16-bit portions for speed */ | ||
| 99 | for (i = 0, p = (const u16 *)peer_addr; i < addr_size >> 1; i++, p++) | ||
| 100 | key += *p; | ||
| 101 | _leave(" key = 0x%lx", key); | ||
| 102 | return key; | ||
| 103 | } | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Add a call to the hashtable | ||
| 107 | */ | ||
| 108 | static void rxrpc_call_hash_add(struct rxrpc_call *call) | ||
| 109 | { | ||
| 110 | unsigned long key; | ||
| 111 | unsigned int addr_size = 0; | ||
| 112 | |||
| 113 | _enter(""); | ||
| 114 | switch (call->family) { | ||
| 115 | case AF_INET: | ||
| 116 | addr_size = sizeof(call->peer_ip.ipv4_addr); | ||
| 117 | break; | ||
| 118 | case AF_INET6: | ||
| 119 | addr_size = sizeof(call->peer_ip.ipv6_addr); | ||
| 120 | break; | ||
| 121 | default: | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | key = rxrpc_call_hashfunc(call->in_clientflag, call->cid, | ||
| 125 | call->call_id, call->epoch, | ||
| 126 | call->service_id, call->family, | ||
| 127 | call->conn->params.local, addr_size, | ||
| 128 | call->peer_ip.ipv6_addr); | ||
| 129 | /* Store the full key in the call */ | ||
| 130 | call->hash_key = key; | ||
| 131 | spin_lock(&rxrpc_call_hash_lock); | ||
| 132 | hash_add_rcu(rxrpc_call_hash, &call->hash_node, key); | ||
| 133 | spin_unlock(&rxrpc_call_hash_lock); | ||
| 134 | _leave(""); | ||
| 135 | } | ||
| 136 | |||
| 137 | /* | ||
| 138 | * Remove a call from the hashtable | ||
| 139 | */ | ||
| 140 | static void rxrpc_call_hash_del(struct rxrpc_call *call) | ||
| 141 | { | ||
| 142 | _enter(""); | ||
| 143 | spin_lock(&rxrpc_call_hash_lock); | ||
| 144 | hash_del_rcu(&call->hash_node); | ||
| 145 | spin_unlock(&rxrpc_call_hash_lock); | ||
| 146 | _leave(""); | ||
| 147 | } | ||
| 148 | |||
| 149 | /* | ||
| 150 | * Find a call in the hashtable and return it, or NULL if it | ||
| 151 | * isn't there. | ||
| 152 | */ | ||
| 153 | struct rxrpc_call *rxrpc_find_call_hash( | ||
| 154 | struct rxrpc_host_header *hdr, | ||
| 155 | void *localptr, | ||
| 156 | sa_family_t family, | ||
| 157 | const void *peer_addr) | ||
| 158 | { | ||
| 159 | unsigned long key; | ||
| 160 | unsigned int addr_size = 0; | ||
| 161 | struct rxrpc_call *call = NULL; | ||
| 162 | struct rxrpc_call *ret = NULL; | ||
| 163 | u8 in_clientflag = hdr->flags & RXRPC_CLIENT_INITIATED; | ||
| 164 | |||
| 165 | _enter(""); | ||
| 166 | switch (family) { | ||
| 167 | case AF_INET: | ||
| 168 | addr_size = sizeof(call->peer_ip.ipv4_addr); | ||
| 169 | break; | ||
| 170 | case AF_INET6: | ||
| 171 | addr_size = sizeof(call->peer_ip.ipv6_addr); | ||
| 172 | break; | ||
| 173 | default: | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | |||
| 177 | key = rxrpc_call_hashfunc(in_clientflag, hdr->cid, hdr->callNumber, | ||
| 178 | hdr->epoch, hdr->serviceId, | ||
| 179 | family, localptr, addr_size, | ||
| 180 | peer_addr); | ||
| 181 | hash_for_each_possible_rcu(rxrpc_call_hash, call, hash_node, key) { | ||
| 182 | if (call->hash_key == key && | ||
| 183 | call->call_id == hdr->callNumber && | ||
| 184 | call->cid == hdr->cid && | ||
| 185 | call->in_clientflag == in_clientflag && | ||
| 186 | call->service_id == hdr->serviceId && | ||
| 187 | call->family == family && | ||
| 188 | call->local == localptr && | ||
| 189 | memcmp(call->peer_ip.ipv6_addr, peer_addr, | ||
| 190 | addr_size) == 0 && | ||
| 191 | call->epoch == hdr->epoch) { | ||
| 192 | ret = call; | ||
| 193 | break; | ||
| 194 | } | ||
| 195 | } | ||
| 196 | _leave(" = %p", ret); | ||
| 197 | return ret; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* | 63 | /* |
| 201 | * find an extant server call | 64 | * find an extant server call |
| 202 | * - called in process context with IRQs enabled | 65 | * - called in process context with IRQs enabled |
| @@ -305,20 +168,7 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx, | |||
| 305 | call->socket = rx; | 168 | call->socket = rx; |
| 306 | call->rx_data_post = 1; | 169 | call->rx_data_post = 1; |
| 307 | 170 | ||
| 308 | /* Record copies of information for hashtable lookup */ | ||
| 309 | call->family = rx->family; | ||
| 310 | call->local = rx->local; | 171 | call->local = rx->local; |
| 311 | switch (call->family) { | ||
| 312 | case AF_INET: | ||
| 313 | call->peer_ip.ipv4_addr = srx->transport.sin.sin_addr.s_addr; | ||
| 314 | break; | ||
| 315 | case AF_INET6: | ||
| 316 | memcpy(call->peer_ip.ipv6_addr, | ||
| 317 | srx->transport.sin6.sin6_addr.in6_u.u6_addr8, | ||
| 318 | sizeof(call->peer_ip.ipv6_addr)); | ||
| 319 | break; | ||
| 320 | } | ||
| 321 | |||
| 322 | call->service_id = srx->srx_service; | 172 | call->service_id = srx->srx_service; |
| 323 | call->in_clientflag = 0; | 173 | call->in_clientflag = 0; |
| 324 | 174 | ||
| @@ -345,9 +195,6 @@ static int rxrpc_begin_client_call(struct rxrpc_call *call, | |||
| 345 | 195 | ||
| 346 | call->state = RXRPC_CALL_CLIENT_SEND_REQUEST; | 196 | call->state = RXRPC_CALL_CLIENT_SEND_REQUEST; |
| 347 | 197 | ||
| 348 | /* Add the new call to the hashtable */ | ||
| 349 | rxrpc_call_hash_add(call); | ||
| 350 | |||
| 351 | spin_lock(&call->conn->params.peer->lock); | 198 | spin_lock(&call->conn->params.peer->lock); |
| 352 | hlist_add_head(&call->error_link, &call->conn->params.peer->error_targets); | 199 | hlist_add_head(&call->error_link, &call->conn->params.peer->error_targets); |
| 353 | spin_unlock(&call->conn->params.peer->lock); | 200 | spin_unlock(&call->conn->params.peer->lock); |
| @@ -425,9 +272,10 @@ error: | |||
| 425 | rxrpc_put_call(call); | 272 | rxrpc_put_call(call); |
| 426 | 273 | ||
| 427 | write_lock_bh(&rxrpc_call_lock); | 274 | write_lock_bh(&rxrpc_call_lock); |
| 428 | list_del(&call->link); | 275 | list_del_init(&call->link); |
| 429 | write_unlock_bh(&rxrpc_call_lock); | 276 | write_unlock_bh(&rxrpc_call_lock); |
| 430 | 277 | ||
| 278 | call->state = RXRPC_CALL_DEAD; | ||
| 431 | rxrpc_put_call(call); | 279 | rxrpc_put_call(call); |
| 432 | _leave(" = %d", ret); | 280 | _leave(" = %d", ret); |
| 433 | return ERR_PTR(ret); | 281 | return ERR_PTR(ret); |
| @@ -439,6 +287,7 @@ error: | |||
| 439 | */ | 287 | */ |
| 440 | found_user_ID_now_present: | 288 | found_user_ID_now_present: |
| 441 | write_unlock(&rx->call_lock); | 289 | write_unlock(&rx->call_lock); |
| 290 | call->state = RXRPC_CALL_DEAD; | ||
| 442 | rxrpc_put_call(call); | 291 | rxrpc_put_call(call); |
| 443 | _leave(" = -EEXIST [%p]", call); | 292 | _leave(" = -EEXIST [%p]", call); |
| 444 | return ERR_PTR(-EEXIST); | 293 | return ERR_PTR(-EEXIST); |
| @@ -454,8 +303,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, | |||
| 454 | { | 303 | { |
| 455 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 304 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 456 | struct rxrpc_call *call, *candidate; | 305 | struct rxrpc_call *call, *candidate; |
| 457 | struct rb_node **p, *parent; | 306 | u32 call_id, chan; |
| 458 | u32 call_id; | ||
| 459 | 307 | ||
| 460 | _enter(",%d", conn->debug_id); | 308 | _enter(",%d", conn->debug_id); |
| 461 | 309 | ||
| @@ -465,20 +313,23 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, | |||
| 465 | if (!candidate) | 313 | if (!candidate) |
| 466 | return ERR_PTR(-EBUSY); | 314 | return ERR_PTR(-EBUSY); |
| 467 | 315 | ||
| 316 | chan = sp->hdr.cid & RXRPC_CHANNELMASK; | ||
| 468 | candidate->socket = rx; | 317 | candidate->socket = rx; |
| 469 | candidate->conn = conn; | 318 | candidate->conn = conn; |
| 470 | candidate->cid = sp->hdr.cid; | 319 | candidate->cid = sp->hdr.cid; |
| 471 | candidate->call_id = sp->hdr.callNumber; | 320 | candidate->call_id = sp->hdr.callNumber; |
| 472 | candidate->channel = sp->hdr.cid & RXRPC_CHANNELMASK; | 321 | candidate->channel = chan; |
| 473 | candidate->rx_data_post = 0; | 322 | candidate->rx_data_post = 0; |
| 474 | candidate->state = RXRPC_CALL_SERVER_ACCEPTING; | 323 | candidate->state = RXRPC_CALL_SERVER_ACCEPTING; |
| 475 | if (conn->security_ix > 0) | 324 | if (conn->security_ix > 0) |
| 476 | candidate->state = RXRPC_CALL_SERVER_SECURING; | 325 | candidate->state = RXRPC_CALL_SERVER_SECURING; |
| 477 | 326 | ||
| 478 | write_lock_bh(&conn->lock); | 327 | spin_lock(&conn->channel_lock); |
| 479 | 328 | ||
| 480 | /* set the channel for this call */ | 329 | /* set the channel for this call */ |
| 481 | call = conn->channels[candidate->channel]; | 330 | call = rcu_dereference_protected(conn->channels[chan].call, |
| 331 | lockdep_is_held(&conn->channel_lock)); | ||
| 332 | |||
| 482 | _debug("channel[%u] is %p", candidate->channel, call); | 333 | _debug("channel[%u] is %p", candidate->channel, call); |
| 483 | if (call && call->call_id == sp->hdr.callNumber) { | 334 | if (call && call->call_id == sp->hdr.callNumber) { |
| 484 | /* already set; must've been a duplicate packet */ | 335 | /* already set; must've been a duplicate packet */ |
| @@ -507,9 +358,9 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, | |||
| 507 | call->debug_id, rxrpc_call_states[call->state]); | 358 | call->debug_id, rxrpc_call_states[call->state]); |
| 508 | 359 | ||
| 509 | if (call->state >= RXRPC_CALL_COMPLETE) { | 360 | if (call->state >= RXRPC_CALL_COMPLETE) { |
| 510 | conn->channels[call->channel] = NULL; | 361 | __rxrpc_disconnect_call(call); |
| 511 | } else { | 362 | } else { |
| 512 | write_unlock_bh(&conn->lock); | 363 | spin_unlock(&conn->channel_lock); |
| 513 | kmem_cache_free(rxrpc_call_jar, candidate); | 364 | kmem_cache_free(rxrpc_call_jar, candidate); |
| 514 | _leave(" = -EBUSY"); | 365 | _leave(" = -EBUSY"); |
| 515 | return ERR_PTR(-EBUSY); | 366 | return ERR_PTR(-EBUSY); |
| @@ -519,33 +370,22 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, | |||
| 519 | /* check the call number isn't duplicate */ | 370 | /* check the call number isn't duplicate */ |
| 520 | _debug("check dup"); | 371 | _debug("check dup"); |
| 521 | call_id = sp->hdr.callNumber; | 372 | call_id = sp->hdr.callNumber; |
| 522 | p = &conn->calls.rb_node; | 373 | |
| 523 | parent = NULL; | 374 | /* We just ignore calls prior to the current call ID. Terminated calls |
| 524 | while (*p) { | 375 | * are handled via the connection. |
| 525 | parent = *p; | 376 | */ |
| 526 | call = rb_entry(parent, struct rxrpc_call, conn_node); | 377 | if (call_id <= conn->channels[chan].call_counter) |
| 527 | 378 | goto old_call; /* TODO: Just drop packet */ | |
| 528 | /* The tree is sorted in order of the __be32 value without | ||
| 529 | * turning it into host order. | ||
| 530 | */ | ||
| 531 | if (call_id < call->call_id) | ||
| 532 | p = &(*p)->rb_left; | ||
| 533 | else if (call_id > call->call_id) | ||
| 534 | p = &(*p)->rb_right; | ||
| 535 | else | ||
| 536 | goto old_call; | ||
| 537 | } | ||
| 538 | 379 | ||
| 539 | /* make the call available */ | 380 | /* make the call available */ |
| 540 | _debug("new call"); | 381 | _debug("new call"); |
| 541 | call = candidate; | 382 | call = candidate; |
| 542 | candidate = NULL; | 383 | candidate = NULL; |
| 543 | rb_link_node(&call->conn_node, parent, p); | 384 | conn->channels[chan].call_counter = call_id; |
| 544 | rb_insert_color(&call->conn_node, &conn->calls); | 385 | rcu_assign_pointer(conn->channels[chan].call, call); |
| 545 | conn->channels[call->channel] = call; | ||
| 546 | sock_hold(&rx->sk); | 386 | sock_hold(&rx->sk); |
| 547 | rxrpc_get_connection(conn); | 387 | rxrpc_get_connection(conn); |
| 548 | write_unlock_bh(&conn->lock); | 388 | spin_unlock(&conn->channel_lock); |
| 549 | 389 | ||
| 550 | spin_lock(&conn->params.peer->lock); | 390 | spin_lock(&conn->params.peer->lock); |
| 551 | hlist_add_head(&call->error_link, &conn->params.peer->error_targets); | 391 | hlist_add_head(&call->error_link, &conn->params.peer->error_targets); |
| @@ -555,27 +395,10 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, | |||
| 555 | list_add_tail(&call->link, &rxrpc_calls); | 395 | list_add_tail(&call->link, &rxrpc_calls); |
| 556 | write_unlock_bh(&rxrpc_call_lock); | 396 | write_unlock_bh(&rxrpc_call_lock); |
| 557 | 397 | ||
| 558 | /* Record copies of information for hashtable lookup */ | ||
| 559 | call->family = rx->family; | ||
| 560 | call->local = conn->params.local; | 398 | call->local = conn->params.local; |
| 561 | switch (call->family) { | ||
| 562 | case AF_INET: | ||
| 563 | call->peer_ip.ipv4_addr = | ||
| 564 | conn->params.peer->srx.transport.sin.sin_addr.s_addr; | ||
| 565 | break; | ||
| 566 | case AF_INET6: | ||
| 567 | memcpy(call->peer_ip.ipv6_addr, | ||
| 568 | conn->params.peer->srx.transport.sin6.sin6_addr.in6_u.u6_addr8, | ||
| 569 | sizeof(call->peer_ip.ipv6_addr)); | ||
| 570 | break; | ||
| 571 | default: | ||
| 572 | break; | ||
| 573 | } | ||
| 574 | call->epoch = conn->proto.epoch; | 399 | call->epoch = conn->proto.epoch; |
| 575 | call->service_id = conn->params.service_id; | 400 | call->service_id = conn->params.service_id; |
| 576 | call->in_clientflag = conn->proto.in_clientflag; | 401 | call->in_clientflag = RXRPC_CLIENT_INITIATED; |
| 577 | /* Add the new call to the hashtable */ | ||
| 578 | rxrpc_call_hash_add(call); | ||
| 579 | 402 | ||
| 580 | _net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id); | 403 | _net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id); |
| 581 | 404 | ||
| @@ -585,19 +408,19 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, | |||
| 585 | return call; | 408 | return call; |
| 586 | 409 | ||
| 587 | extant_call: | 410 | extant_call: |
| 588 | write_unlock_bh(&conn->lock); | 411 | spin_unlock(&conn->channel_lock); |
| 589 | kmem_cache_free(rxrpc_call_jar, candidate); | 412 | kmem_cache_free(rxrpc_call_jar, candidate); |
| 590 | _leave(" = %p {%d} [extant]", call, call ? call->debug_id : -1); | 413 | _leave(" = %p {%d} [extant]", call, call ? call->debug_id : -1); |
| 591 | return call; | 414 | return call; |
| 592 | 415 | ||
| 593 | aborted_call: | 416 | aborted_call: |
| 594 | write_unlock_bh(&conn->lock); | 417 | spin_unlock(&conn->channel_lock); |
| 595 | kmem_cache_free(rxrpc_call_jar, candidate); | 418 | kmem_cache_free(rxrpc_call_jar, candidate); |
| 596 | _leave(" = -ECONNABORTED"); | 419 | _leave(" = -ECONNABORTED"); |
| 597 | return ERR_PTR(-ECONNABORTED); | 420 | return ERR_PTR(-ECONNABORTED); |
| 598 | 421 | ||
| 599 | old_call: | 422 | old_call: |
| 600 | write_unlock_bh(&conn->lock); | 423 | spin_unlock(&conn->channel_lock); |
| 601 | kmem_cache_free(rxrpc_call_jar, candidate); | 424 | kmem_cache_free(rxrpc_call_jar, candidate); |
| 602 | _leave(" = -ECONNRESET [old]"); | 425 | _leave(" = -ECONNRESET [old]"); |
| 603 | return ERR_PTR(-ECONNRESET); | 426 | return ERR_PTR(-ECONNRESET); |
| @@ -626,6 +449,10 @@ void rxrpc_release_call(struct rxrpc_call *call) | |||
| 626 | */ | 449 | */ |
| 627 | _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn); | 450 | _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn); |
| 628 | 451 | ||
| 452 | spin_lock(&conn->params.peer->lock); | ||
| 453 | hlist_del_init(&call->error_link); | ||
| 454 | spin_unlock(&conn->params.peer->lock); | ||
| 455 | |||
| 629 | write_lock_bh(&rx->call_lock); | 456 | write_lock_bh(&rx->call_lock); |
| 630 | if (!list_empty(&call->accept_link)) { | 457 | if (!list_empty(&call->accept_link)) { |
| 631 | _debug("unlinking once-pending call %p { e=%lx f=%lx }", | 458 | _debug("unlinking once-pending call %p { e=%lx f=%lx }", |
| @@ -641,24 +468,17 @@ void rxrpc_release_call(struct rxrpc_call *call) | |||
| 641 | write_unlock_bh(&rx->call_lock); | 468 | write_unlock_bh(&rx->call_lock); |
| 642 | 469 | ||
| 643 | /* free up the channel for reuse */ | 470 | /* free up the channel for reuse */ |
| 644 | spin_lock(&conn->channel_lock); | 471 | write_lock_bh(&call->state_lock); |
| 645 | write_lock_bh(&conn->lock); | ||
| 646 | write_lock(&call->state_lock); | ||
| 647 | |||
| 648 | rxrpc_disconnect_call(call); | ||
| 649 | |||
| 650 | spin_unlock(&conn->channel_lock); | ||
| 651 | 472 | ||
| 652 | if (call->state < RXRPC_CALL_COMPLETE && | 473 | if (call->state < RXRPC_CALL_COMPLETE && |
| 653 | call->state != RXRPC_CALL_CLIENT_FINAL_ACK) { | 474 | call->state != RXRPC_CALL_CLIENT_FINAL_ACK) { |
| 654 | _debug("+++ ABORTING STATE %d +++\n", call->state); | 475 | _debug("+++ ABORTING STATE %d +++\n", call->state); |
| 655 | call->state = RXRPC_CALL_LOCALLY_ABORTED; | 476 | call->state = RXRPC_CALL_LOCALLY_ABORTED; |
| 656 | call->local_abort = RX_CALL_DEAD; | 477 | call->local_abort = RX_CALL_DEAD; |
| 657 | set_bit(RXRPC_CALL_EV_ABORT, &call->events); | ||
| 658 | rxrpc_queue_call(call); | ||
| 659 | } | 478 | } |
| 660 | write_unlock(&call->state_lock); | 479 | write_unlock_bh(&call->state_lock); |
| 661 | write_unlock_bh(&conn->lock); | 480 | |
| 481 | rxrpc_disconnect_call(call); | ||
| 662 | 482 | ||
| 663 | /* clean up the Rx queue */ | 483 | /* clean up the Rx queue */ |
| 664 | if (!skb_queue_empty(&call->rx_queue) || | 484 | if (!skb_queue_empty(&call->rx_queue) || |
| @@ -792,6 +612,17 @@ void __rxrpc_put_call(struct rxrpc_call *call) | |||
| 792 | } | 612 | } |
| 793 | 613 | ||
| 794 | /* | 614 | /* |
| 615 | * Final call destruction under RCU. | ||
| 616 | */ | ||
| 617 | static void rxrpc_rcu_destroy_call(struct rcu_head *rcu) | ||
| 618 | { | ||
| 619 | struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu); | ||
| 620 | |||
| 621 | rxrpc_purge_queue(&call->rx_queue); | ||
| 622 | kmem_cache_free(rxrpc_call_jar, call); | ||
| 623 | } | ||
| 624 | |||
| 625 | /* | ||
| 795 | * clean up a call | 626 | * clean up a call |
| 796 | */ | 627 | */ |
| 797 | static void rxrpc_cleanup_call(struct rxrpc_call *call) | 628 | static void rxrpc_cleanup_call(struct rxrpc_call *call) |
| @@ -815,19 +646,7 @@ static void rxrpc_cleanup_call(struct rxrpc_call *call) | |||
| 815 | return; | 646 | return; |
| 816 | } | 647 | } |
| 817 | 648 | ||
| 818 | if (call->conn) { | 649 | ASSERTCMP(call->conn, ==, NULL); |
| 819 | spin_lock(&call->conn->params.peer->lock); | ||
| 820 | hlist_del_init(&call->error_link); | ||
| 821 | spin_unlock(&call->conn->params.peer->lock); | ||
| 822 | |||
| 823 | write_lock_bh(&call->conn->lock); | ||
| 824 | rb_erase(&call->conn_node, &call->conn->calls); | ||
| 825 | write_unlock_bh(&call->conn->lock); | ||
| 826 | rxrpc_put_connection(call->conn); | ||
| 827 | } | ||
| 828 | |||
| 829 | /* Remove the call from the hash */ | ||
| 830 | rxrpc_call_hash_del(call); | ||
| 831 | 650 | ||
| 832 | if (call->acks_window) { | 651 | if (call->acks_window) { |
| 833 | _debug("kill Tx window %d", | 652 | _debug("kill Tx window %d", |
| @@ -855,7 +674,7 @@ static void rxrpc_cleanup_call(struct rxrpc_call *call) | |||
| 855 | rxrpc_purge_queue(&call->rx_queue); | 674 | rxrpc_purge_queue(&call->rx_queue); |
| 856 | ASSERT(skb_queue_empty(&call->rx_oos_queue)); | 675 | ASSERT(skb_queue_empty(&call->rx_oos_queue)); |
| 857 | sock_put(&call->socket->sk); | 676 | sock_put(&call->socket->sk); |
| 858 | kmem_cache_free(rxrpc_call_jar, call); | 677 | call_rcu(&call->rcu, rxrpc_rcu_destroy_call); |
| 859 | } | 678 | } |
| 860 | 679 | ||
| 861 | /* | 680 | /* |
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index 82488d6adb83..9e91f27b0d0f 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c | |||
| @@ -33,7 +33,8 @@ static DEFINE_SPINLOCK(rxrpc_conn_id_lock); | |||
| 33 | * client conns away from the current allocation point to try and keep the IDs | 33 | * client conns away from the current allocation point to try and keep the IDs |
| 34 | * concentrated. We will also need to retire connections from an old epoch. | 34 | * concentrated. We will also need to retire connections from an old epoch. |
| 35 | */ | 35 | */ |
| 36 | int rxrpc_get_client_connection_id(struct rxrpc_connection *conn, gfp_t gfp) | 36 | static int rxrpc_get_client_connection_id(struct rxrpc_connection *conn, |
| 37 | gfp_t gfp) | ||
| 37 | { | 38 | { |
| 38 | u32 epoch; | 39 | u32 epoch; |
| 39 | int id; | 40 | int id; |
| @@ -83,7 +84,7 @@ error: | |||
| 83 | /* | 84 | /* |
| 84 | * Release a connection ID for a client connection from the global pool. | 85 | * Release a connection ID for a client connection from the global pool. |
| 85 | */ | 86 | */ |
| 86 | void rxrpc_put_client_connection_id(struct rxrpc_connection *conn) | 87 | static void rxrpc_put_client_connection_id(struct rxrpc_connection *conn) |
| 87 | { | 88 | { |
| 88 | if (test_bit(RXRPC_CONN_HAS_IDR, &conn->flags)) { | 89 | if (test_bit(RXRPC_CONN_HAS_IDR, &conn->flags)) { |
| 89 | spin_lock(&rxrpc_conn_id_lock); | 90 | spin_lock(&rxrpc_conn_id_lock); |
| @@ -92,3 +93,280 @@ void rxrpc_put_client_connection_id(struct rxrpc_connection *conn) | |||
| 92 | spin_unlock(&rxrpc_conn_id_lock); | 93 | spin_unlock(&rxrpc_conn_id_lock); |
| 93 | } | 94 | } |
| 94 | } | 95 | } |
| 96 | |||
| 97 | /* | ||
| 98 | * Destroy the client connection ID tree. | ||
| 99 | */ | ||
| 100 | void rxrpc_destroy_client_conn_ids(void) | ||
| 101 | { | ||
| 102 | struct rxrpc_connection *conn; | ||
| 103 | int id; | ||
| 104 | |||
| 105 | if (!idr_is_empty(&rxrpc_client_conn_ids)) { | ||
| 106 | idr_for_each_entry(&rxrpc_client_conn_ids, conn, id) { | ||
| 107 | pr_err("AF_RXRPC: Leaked client conn %p {%d}\n", | ||
| 108 | conn, atomic_read(&conn->usage)); | ||
| 109 | } | ||
| 110 | BUG(); | ||
| 111 | } | ||
| 112 | |||
| 113 | idr_destroy(&rxrpc_client_conn_ids); | ||
| 114 | } | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Allocate a client connection. The caller must take care to clear any | ||
| 118 | * padding bytes in *cp. | ||
| 119 | */ | ||
| 120 | static struct rxrpc_connection * | ||
| 121 | rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp) | ||
| 122 | { | ||
| 123 | struct rxrpc_connection *conn; | ||
| 124 | int ret; | ||
| 125 | |||
| 126 | _enter(""); | ||
| 127 | |||
| 128 | conn = rxrpc_alloc_connection(gfp); | ||
| 129 | if (!conn) { | ||
| 130 | _leave(" = -ENOMEM"); | ||
| 131 | return ERR_PTR(-ENOMEM); | ||
| 132 | } | ||
| 133 | |||
| 134 | conn->params = *cp; | ||
| 135 | conn->out_clientflag = RXRPC_CLIENT_INITIATED; | ||
| 136 | conn->state = RXRPC_CONN_CLIENT; | ||
| 137 | |||
| 138 | ret = rxrpc_get_client_connection_id(conn, gfp); | ||
| 139 | if (ret < 0) | ||
| 140 | goto error_0; | ||
| 141 | |||
| 142 | ret = rxrpc_init_client_conn_security(conn); | ||
| 143 | if (ret < 0) | ||
| 144 | goto error_1; | ||
| 145 | |||
| 146 | ret = conn->security->prime_packet_security(conn); | ||
| 147 | if (ret < 0) | ||
| 148 | goto error_2; | ||
| 149 | |||
| 150 | write_lock(&rxrpc_connection_lock); | ||
| 151 | list_add_tail(&conn->link, &rxrpc_connections); | ||
| 152 | write_unlock(&rxrpc_connection_lock); | ||
| 153 | |||
| 154 | /* We steal the caller's peer ref. */ | ||
| 155 | cp->peer = NULL; | ||
| 156 | rxrpc_get_local(conn->params.local); | ||
| 157 | key_get(conn->params.key); | ||
| 158 | |||
| 159 | _leave(" = %p", conn); | ||
| 160 | return conn; | ||
| 161 | |||
| 162 | error_2: | ||
| 163 | conn->security->clear(conn); | ||
| 164 | error_1: | ||
| 165 | rxrpc_put_client_connection_id(conn); | ||
| 166 | error_0: | ||
| 167 | kfree(conn); | ||
| 168 | _leave(" = %d", ret); | ||
| 169 | return ERR_PTR(ret); | ||
| 170 | } | ||
| 171 | |||
| 172 | /* | ||
| 173 | * find a connection for a call | ||
| 174 | * - called in process context with IRQs enabled | ||
| 175 | */ | ||
| 176 | int rxrpc_connect_call(struct rxrpc_call *call, | ||
| 177 | struct rxrpc_conn_parameters *cp, | ||
| 178 | struct sockaddr_rxrpc *srx, | ||
| 179 | gfp_t gfp) | ||
| 180 | { | ||
| 181 | struct rxrpc_connection *conn, *candidate = NULL; | ||
| 182 | struct rxrpc_local *local = cp->local; | ||
| 183 | struct rb_node *p, **pp, *parent; | ||
| 184 | long diff; | ||
| 185 | int chan; | ||
| 186 | |||
| 187 | DECLARE_WAITQUEUE(myself, current); | ||
| 188 | |||
| 189 | _enter("{%d,%lx},", call->debug_id, call->user_call_ID); | ||
| 190 | |||
| 191 | cp->peer = rxrpc_lookup_peer(cp->local, srx, gfp); | ||
| 192 | if (!cp->peer) | ||
| 193 | return -ENOMEM; | ||
| 194 | |||
| 195 | if (!cp->exclusive) { | ||
| 196 | /* Search for a existing client connection unless this is going | ||
| 197 | * to be a connection that's used exclusively for a single call. | ||
| 198 | */ | ||
| 199 | _debug("search 1"); | ||
| 200 | spin_lock(&local->client_conns_lock); | ||
| 201 | p = local->client_conns.rb_node; | ||
| 202 | while (p) { | ||
| 203 | conn = rb_entry(p, struct rxrpc_connection, client_node); | ||
| 204 | |||
| 205 | #define cmp(X) ((long)conn->params.X - (long)cp->X) | ||
| 206 | diff = (cmp(peer) ?: | ||
| 207 | cmp(key) ?: | ||
| 208 | cmp(security_level)); | ||
| 209 | if (diff < 0) | ||
| 210 | p = p->rb_left; | ||
| 211 | else if (diff > 0) | ||
| 212 | p = p->rb_right; | ||
| 213 | else | ||
| 214 | goto found_extant_conn; | ||
| 215 | } | ||
| 216 | spin_unlock(&local->client_conns_lock); | ||
| 217 | } | ||
| 218 | |||
| 219 | /* We didn't find a connection or we want an exclusive one. */ | ||
| 220 | _debug("get new conn"); | ||
| 221 | candidate = rxrpc_alloc_client_connection(cp, gfp); | ||
| 222 | if (!candidate) { | ||
| 223 | _leave(" = -ENOMEM"); | ||
| 224 | return -ENOMEM; | ||
| 225 | } | ||
| 226 | |||
| 227 | if (cp->exclusive) { | ||
| 228 | /* Assign the call on an exclusive connection to channel 0 and | ||
| 229 | * don't add the connection to the endpoint's shareable conn | ||
| 230 | * lookup tree. | ||
| 231 | */ | ||
| 232 | _debug("exclusive chan 0"); | ||
| 233 | conn = candidate; | ||
| 234 | atomic_set(&conn->avail_chans, RXRPC_MAXCALLS - 1); | ||
| 235 | spin_lock(&conn->channel_lock); | ||
| 236 | chan = 0; | ||
| 237 | goto found_channel; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* We need to redo the search before attempting to add a new connection | ||
| 241 | * lest we race with someone else adding a conflicting instance. | ||
| 242 | */ | ||
| 243 | _debug("search 2"); | ||
| 244 | spin_lock(&local->client_conns_lock); | ||
| 245 | |||
| 246 | pp = &local->client_conns.rb_node; | ||
| 247 | parent = NULL; | ||
| 248 | while (*pp) { | ||
| 249 | parent = *pp; | ||
| 250 | conn = rb_entry(parent, struct rxrpc_connection, client_node); | ||
| 251 | |||
| 252 | diff = (cmp(peer) ?: | ||
| 253 | cmp(key) ?: | ||
| 254 | cmp(security_level)); | ||
| 255 | if (diff < 0) | ||
| 256 | pp = &(*pp)->rb_left; | ||
| 257 | else if (diff > 0) | ||
| 258 | pp = &(*pp)->rb_right; | ||
| 259 | else | ||
| 260 | goto found_extant_conn; | ||
| 261 | } | ||
| 262 | |||
| 263 | /* The second search also failed; simply add the new connection with | ||
| 264 | * the new call in channel 0. Note that we need to take the channel | ||
| 265 | * lock before dropping the client conn lock. | ||
| 266 | */ | ||
| 267 | _debug("new conn"); | ||
| 268 | set_bit(RXRPC_CONN_IN_CLIENT_CONNS, &candidate->flags); | ||
| 269 | rb_link_node(&candidate->client_node, parent, pp); | ||
| 270 | rb_insert_color(&candidate->client_node, &local->client_conns); | ||
| 271 | attached: | ||
| 272 | conn = candidate; | ||
| 273 | candidate = NULL; | ||
| 274 | |||
| 275 | atomic_set(&conn->avail_chans, RXRPC_MAXCALLS - 1); | ||
| 276 | spin_lock(&conn->channel_lock); | ||
| 277 | spin_unlock(&local->client_conns_lock); | ||
| 278 | chan = 0; | ||
| 279 | |||
| 280 | found_channel: | ||
| 281 | _debug("found chan"); | ||
| 282 | call->conn = conn; | ||
| 283 | call->channel = chan; | ||
| 284 | call->epoch = conn->proto.epoch; | ||
| 285 | call->cid = conn->proto.cid | chan; | ||
| 286 | call->call_id = ++conn->channels[chan].call_counter; | ||
| 287 | conn->channels[chan].call_id = call->call_id; | ||
| 288 | rcu_assign_pointer(conn->channels[chan].call, call); | ||
| 289 | |||
| 290 | _net("CONNECT call %d on conn %d", call->debug_id, conn->debug_id); | ||
| 291 | |||
| 292 | spin_unlock(&conn->channel_lock); | ||
| 293 | rxrpc_put_peer(cp->peer); | ||
| 294 | cp->peer = NULL; | ||
| 295 | _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage)); | ||
| 296 | return 0; | ||
| 297 | |||
| 298 | /* We found a potentially suitable connection already in existence. If | ||
| 299 | * we can reuse it (ie. its usage count hasn't been reduced to 0 by the | ||
| 300 | * reaper), discard any candidate we may have allocated, and try to get | ||
| 301 | * a channel on this one, otherwise we have to replace it. | ||
| 302 | */ | ||
| 303 | found_extant_conn: | ||
| 304 | _debug("found conn"); | ||
| 305 | if (!rxrpc_get_connection_maybe(conn)) { | ||
| 306 | set_bit(RXRPC_CONN_IN_CLIENT_CONNS, &candidate->flags); | ||
| 307 | rb_replace_node(&conn->client_node, | ||
| 308 | &candidate->client_node, | ||
| 309 | &local->client_conns); | ||
| 310 | clear_bit(RXRPC_CONN_IN_CLIENT_CONNS, &conn->flags); | ||
| 311 | goto attached; | ||
| 312 | } | ||
| 313 | |||
| 314 | spin_unlock(&local->client_conns_lock); | ||
| 315 | |||
| 316 | rxrpc_put_connection(candidate); | ||
| 317 | |||
| 318 | if (!atomic_add_unless(&conn->avail_chans, -1, 0)) { | ||
| 319 | if (!gfpflags_allow_blocking(gfp)) { | ||
| 320 | rxrpc_put_connection(conn); | ||
| 321 | _leave(" = -EAGAIN"); | ||
| 322 | return -EAGAIN; | ||
| 323 | } | ||
| 324 | |||
| 325 | add_wait_queue(&conn->channel_wq, &myself); | ||
| 326 | for (;;) { | ||
| 327 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 328 | if (atomic_add_unless(&conn->avail_chans, -1, 0)) | ||
| 329 | break; | ||
| 330 | if (signal_pending(current)) | ||
| 331 | goto interrupted; | ||
| 332 | schedule(); | ||
| 333 | } | ||
| 334 | remove_wait_queue(&conn->channel_wq, &myself); | ||
| 335 | __set_current_state(TASK_RUNNING); | ||
| 336 | } | ||
| 337 | |||
| 338 | /* The connection allegedly now has a free channel and we can now | ||
| 339 | * attach the call to it. | ||
| 340 | */ | ||
| 341 | spin_lock(&conn->channel_lock); | ||
| 342 | |||
| 343 | for (chan = 0; chan < RXRPC_MAXCALLS; chan++) | ||
| 344 | if (!conn->channels[chan].call) | ||
| 345 | goto found_channel; | ||
| 346 | BUG(); | ||
| 347 | |||
| 348 | interrupted: | ||
| 349 | remove_wait_queue(&conn->channel_wq, &myself); | ||
| 350 | __set_current_state(TASK_RUNNING); | ||
| 351 | rxrpc_put_connection(conn); | ||
| 352 | rxrpc_put_peer(cp->peer); | ||
| 353 | cp->peer = NULL; | ||
| 354 | _leave(" = -ERESTARTSYS"); | ||
| 355 | return -ERESTARTSYS; | ||
| 356 | } | ||
| 357 | |||
| 358 | /* | ||
| 359 | * Remove a client connection from the local endpoint's tree, thereby removing | ||
| 360 | * it as a target for reuse for new client calls. | ||
| 361 | */ | ||
| 362 | void rxrpc_unpublish_client_conn(struct rxrpc_connection *conn) | ||
| 363 | { | ||
| 364 | struct rxrpc_local *local = conn->params.local; | ||
| 365 | |||
| 366 | spin_lock(&local->client_conns_lock); | ||
| 367 | if (test_and_clear_bit(RXRPC_CONN_IN_CLIENT_CONNS, &conn->flags)) | ||
| 368 | rb_erase(&conn->client_node, &local->client_conns); | ||
| 369 | spin_unlock(&local->client_conns_lock); | ||
| 370 | |||
| 371 | rxrpc_put_client_connection_id(conn); | ||
| 372 | } | ||
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c index bf6971555eac..cee0f35bc1cf 100644 --- a/net/rxrpc/conn_event.c +++ b/net/rxrpc/conn_event.c | |||
| @@ -31,15 +31,17 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn, int state, | |||
| 31 | u32 abort_code) | 31 | u32 abort_code) |
| 32 | { | 32 | { |
| 33 | struct rxrpc_call *call; | 33 | struct rxrpc_call *call; |
| 34 | struct rb_node *p; | 34 | int i; |
| 35 | 35 | ||
| 36 | _enter("{%d},%x", conn->debug_id, abort_code); | 36 | _enter("{%d},%x", conn->debug_id, abort_code); |
| 37 | 37 | ||
| 38 | read_lock_bh(&conn->lock); | 38 | spin_lock(&conn->channel_lock); |
| 39 | 39 | ||
| 40 | for (p = rb_first(&conn->calls); p; p = rb_next(p)) { | 40 | for (i = 0; i < RXRPC_MAXCALLS; i++) { |
| 41 | call = rb_entry(p, struct rxrpc_call, conn_node); | 41 | call = rcu_dereference_protected( |
| 42 | write_lock(&call->state_lock); | 42 | conn->channels[i].call, |
| 43 | lockdep_is_held(&conn->channel_lock)); | ||
| 44 | write_lock_bh(&call->state_lock); | ||
| 43 | if (call->state <= RXRPC_CALL_COMPLETE) { | 45 | if (call->state <= RXRPC_CALL_COMPLETE) { |
| 44 | call->state = state; | 46 | call->state = state; |
| 45 | if (state == RXRPC_CALL_LOCALLY_ABORTED) { | 47 | if (state == RXRPC_CALL_LOCALLY_ABORTED) { |
| @@ -51,10 +53,10 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn, int state, | |||
| 51 | } | 53 | } |
| 52 | rxrpc_queue_call(call); | 54 | rxrpc_queue_call(call); |
| 53 | } | 55 | } |
| 54 | write_unlock(&call->state_lock); | 56 | write_unlock_bh(&call->state_lock); |
| 55 | } | 57 | } |
| 56 | 58 | ||
| 57 | read_unlock_bh(&conn->lock); | 59 | spin_unlock(&conn->channel_lock); |
| 58 | _leave(""); | 60 | _leave(""); |
| 59 | } | 61 | } |
| 60 | 62 | ||
| @@ -188,18 +190,24 @@ static int rxrpc_process_event(struct rxrpc_connection *conn, | |||
| 188 | if (ret < 0) | 190 | if (ret < 0) |
| 189 | return ret; | 191 | return ret; |
| 190 | 192 | ||
| 191 | conn->security->prime_packet_security(conn); | 193 | ret = conn->security->prime_packet_security(conn); |
| 192 | read_lock_bh(&conn->lock); | 194 | if (ret < 0) |
| 195 | return ret; | ||
| 196 | |||
| 197 | spin_lock(&conn->channel_lock); | ||
| 193 | spin_lock(&conn->state_lock); | 198 | spin_lock(&conn->state_lock); |
| 194 | 199 | ||
| 195 | if (conn->state == RXRPC_CONN_SERVER_CHALLENGING) { | 200 | if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) { |
| 196 | conn->state = RXRPC_CONN_SERVER; | 201 | conn->state = RXRPC_CONN_SERVICE; |
| 197 | for (loop = 0; loop < RXRPC_MAXCALLS; loop++) | 202 | for (loop = 0; loop < RXRPC_MAXCALLS; loop++) |
| 198 | rxrpc_call_is_secure(conn->channels[loop]); | 203 | rxrpc_call_is_secure( |
| 204 | rcu_dereference_protected( | ||
| 205 | conn->channels[loop].call, | ||
| 206 | lockdep_is_held(&conn->channel_lock))); | ||
| 199 | } | 207 | } |
| 200 | 208 | ||
| 201 | spin_unlock(&conn->state_lock); | 209 | spin_unlock(&conn->state_lock); |
| 202 | read_unlock_bh(&conn->lock); | 210 | spin_unlock(&conn->channel_lock); |
| 203 | return 0; | 211 | return 0; |
| 204 | 212 | ||
| 205 | default: | 213 | default: |
| @@ -263,12 +271,8 @@ void rxrpc_process_connection(struct work_struct *work) | |||
| 263 | 271 | ||
| 264 | _enter("{%d}", conn->debug_id); | 272 | _enter("{%d}", conn->debug_id); |
| 265 | 273 | ||
| 266 | rxrpc_get_connection(conn); | 274 | if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events)) |
| 267 | |||
| 268 | if (test_and_clear_bit(RXRPC_CONN_CHALLENGE, &conn->events)) { | ||
| 269 | rxrpc_secure_connection(conn); | 275 | rxrpc_secure_connection(conn); |
| 270 | rxrpc_put_connection(conn); | ||
| 271 | } | ||
| 272 | 276 | ||
| 273 | /* go through the conn-level event packets, releasing the ref on this | 277 | /* go through the conn-level event packets, releasing the ref on this |
| 274 | * connection that each one has when we've finished with it */ | 278 | * connection that each one has when we've finished with it */ |
| @@ -283,7 +287,6 @@ void rxrpc_process_connection(struct work_struct *work) | |||
| 283 | goto requeue_and_leave; | 287 | goto requeue_and_leave; |
| 284 | case -ECONNABORTED: | 288 | case -ECONNABORTED: |
| 285 | default: | 289 | default: |
| 286 | rxrpc_put_connection(conn); | ||
| 287 | rxrpc_free_skb(skb); | 290 | rxrpc_free_skb(skb); |
| 288 | break; | 291 | break; |
| 289 | } | 292 | } |
| @@ -301,7 +304,6 @@ requeue_and_leave: | |||
| 301 | protocol_error: | 304 | protocol_error: |
| 302 | if (rxrpc_abort_connection(conn, -ret, abort_code) < 0) | 305 | if (rxrpc_abort_connection(conn, -ret, abort_code) < 0) |
| 303 | goto requeue_and_leave; | 306 | goto requeue_and_leave; |
| 304 | rxrpc_put_connection(conn); | ||
| 305 | rxrpc_free_skb(skb); | 307 | rxrpc_free_skb(skb); |
| 306 | _leave(" [EPROTO]"); | 308 | _leave(" [EPROTO]"); |
| 307 | goto out; | 309 | goto out; |
| @@ -315,7 +317,7 @@ void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb) | |||
| 315 | CHECK_SLAB_OKAY(&local->usage); | 317 | CHECK_SLAB_OKAY(&local->usage); |
| 316 | 318 | ||
| 317 | skb_queue_tail(&local->reject_queue, skb); | 319 | skb_queue_tail(&local->reject_queue, skb); |
| 318 | rxrpc_queue_work(&local->processor); | 320 | rxrpc_queue_local(local); |
| 319 | } | 321 | } |
| 320 | 322 | ||
| 321 | /* | 323 | /* |
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index 4bfad7cf96cb..896d84493a05 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/net.h> | 16 | #include <linux/net.h> |
| 17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
| 18 | #include <linux/crypto.h> | ||
| 19 | #include <net/sock.h> | 18 | #include <net/sock.h> |
| 20 | #include <net/af_rxrpc.h> | 19 | #include <net/af_rxrpc.h> |
| 21 | #include "ar-internal.h" | 20 | #include "ar-internal.h" |
| @@ -34,7 +33,7 @@ static DECLARE_DELAYED_WORK(rxrpc_connection_reap, rxrpc_connection_reaper); | |||
| 34 | /* | 33 | /* |
| 35 | * allocate a new connection | 34 | * allocate a new connection |
| 36 | */ | 35 | */ |
| 37 | static struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp) | 36 | struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp) |
| 38 | { | 37 | { |
| 39 | struct rxrpc_connection *conn; | 38 | struct rxrpc_connection *conn; |
| 40 | 39 | ||
| @@ -46,12 +45,13 @@ static struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp) | |||
| 46 | init_waitqueue_head(&conn->channel_wq); | 45 | init_waitqueue_head(&conn->channel_wq); |
| 47 | INIT_WORK(&conn->processor, &rxrpc_process_connection); | 46 | INIT_WORK(&conn->processor, &rxrpc_process_connection); |
| 48 | INIT_LIST_HEAD(&conn->link); | 47 | INIT_LIST_HEAD(&conn->link); |
| 49 | conn->calls = RB_ROOT; | ||
| 50 | skb_queue_head_init(&conn->rx_queue); | 48 | skb_queue_head_init(&conn->rx_queue); |
| 51 | conn->security = &rxrpc_no_security; | 49 | conn->security = &rxrpc_no_security; |
| 52 | rwlock_init(&conn->lock); | ||
| 53 | spin_lock_init(&conn->state_lock); | 50 | spin_lock_init(&conn->state_lock); |
| 54 | atomic_set(&conn->usage, 1); | 51 | /* We maintain an extra ref on the connection whilst it is |
| 52 | * on the rxrpc_connections list. | ||
| 53 | */ | ||
| 54 | atomic_set(&conn->usage, 2); | ||
| 55 | conn->debug_id = atomic_inc_return(&rxrpc_debug_id); | 55 | conn->debug_id = atomic_inc_return(&rxrpc_debug_id); |
| 56 | atomic_set(&conn->avail_chans, RXRPC_MAXCALLS); | 56 | atomic_set(&conn->avail_chans, RXRPC_MAXCALLS); |
| 57 | conn->size_align = 4; | 57 | conn->size_align = 4; |
| @@ -63,465 +63,118 @@ static struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp) | |||
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | /* | 65 | /* |
| 66 | * add a call to a connection's call-by-ID tree | 66 | * Look up a connection in the cache by protocol parameters. |
| 67 | */ | 67 | * |
| 68 | static void rxrpc_add_call_ID_to_conn(struct rxrpc_connection *conn, | 68 | * If successful, a pointer to the connection is returned, but no ref is taken. |
| 69 | struct rxrpc_call *call) | 69 | * NULL is returned if there is no match. |
| 70 | { | 70 | * |
| 71 | struct rxrpc_call *xcall; | 71 | * The caller must be holding the RCU read lock. |
| 72 | struct rb_node *parent, **p; | ||
| 73 | __be32 call_id; | ||
| 74 | |||
| 75 | write_lock_bh(&conn->lock); | ||
| 76 | |||
| 77 | call_id = call->call_id; | ||
| 78 | p = &conn->calls.rb_node; | ||
| 79 | parent = NULL; | ||
| 80 | while (*p) { | ||
| 81 | parent = *p; | ||
| 82 | xcall = rb_entry(parent, struct rxrpc_call, conn_node); | ||
| 83 | |||
| 84 | if (call_id < xcall->call_id) | ||
| 85 | p = &(*p)->rb_left; | ||
| 86 | else if (call_id > xcall->call_id) | ||
| 87 | p = &(*p)->rb_right; | ||
| 88 | else | ||
| 89 | BUG(); | ||
| 90 | } | ||
| 91 | |||
| 92 | rb_link_node(&call->conn_node, parent, p); | ||
| 93 | rb_insert_color(&call->conn_node, &conn->calls); | ||
| 94 | |||
| 95 | write_unlock_bh(&conn->lock); | ||
| 96 | } | ||
| 97 | |||
| 98 | /* | ||
| 99 | * Allocate a client connection. The caller must take care to clear any | ||
| 100 | * padding bytes in *cp. | ||
| 101 | */ | 72 | */ |
| 102 | static struct rxrpc_connection * | 73 | struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *local, |
| 103 | rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp) | 74 | struct sk_buff *skb) |
| 104 | { | 75 | { |
| 105 | struct rxrpc_connection *conn; | 76 | struct rxrpc_connection *conn; |
| 106 | int ret; | 77 | struct rxrpc_conn_proto k; |
| 107 | 78 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | |
| 108 | _enter(""); | 79 | struct sockaddr_rxrpc srx; |
| 109 | 80 | struct rxrpc_peer *peer; | |
| 110 | conn = rxrpc_alloc_connection(gfp); | ||
| 111 | if (!conn) { | ||
| 112 | _leave(" = -ENOMEM"); | ||
| 113 | return ERR_PTR(-ENOMEM); | ||
| 114 | } | ||
| 115 | |||
| 116 | conn->params = *cp; | ||
| 117 | conn->proto.local = cp->local; | ||
| 118 | conn->proto.epoch = rxrpc_epoch; | ||
| 119 | conn->proto.cid = 0; | ||
| 120 | conn->proto.in_clientflag = 0; | ||
| 121 | conn->proto.family = cp->peer->srx.transport.family; | ||
| 122 | conn->out_clientflag = RXRPC_CLIENT_INITIATED; | ||
| 123 | conn->state = RXRPC_CONN_CLIENT; | ||
| 124 | |||
| 125 | switch (conn->proto.family) { | ||
| 126 | case AF_INET: | ||
| 127 | conn->proto.addr_size = sizeof(conn->proto.ipv4_addr); | ||
| 128 | conn->proto.ipv4_addr = cp->peer->srx.transport.sin.sin_addr; | ||
| 129 | conn->proto.port = cp->peer->srx.transport.sin.sin_port; | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | |||
| 133 | ret = rxrpc_get_client_connection_id(conn, gfp); | ||
| 134 | if (ret < 0) | ||
| 135 | goto error_0; | ||
| 136 | |||
| 137 | ret = rxrpc_init_client_conn_security(conn); | ||
| 138 | if (ret < 0) | ||
| 139 | goto error_1; | ||
| 140 | |||
| 141 | conn->security->prime_packet_security(conn); | ||
| 142 | |||
| 143 | write_lock(&rxrpc_connection_lock); | ||
| 144 | list_add_tail(&conn->link, &rxrpc_connections); | ||
| 145 | write_unlock(&rxrpc_connection_lock); | ||
| 146 | |||
| 147 | /* We steal the caller's peer ref. */ | ||
| 148 | cp->peer = NULL; | ||
| 149 | rxrpc_get_local(conn->params.local); | ||
| 150 | key_get(conn->params.key); | ||
| 151 | |||
| 152 | _leave(" = %p", conn); | ||
| 153 | return conn; | ||
| 154 | |||
| 155 | error_1: | ||
| 156 | rxrpc_put_client_connection_id(conn); | ||
| 157 | error_0: | ||
| 158 | kfree(conn); | ||
| 159 | _leave(" = %d", ret); | ||
| 160 | return ERR_PTR(ret); | ||
| 161 | } | ||
| 162 | |||
| 163 | /* | ||
| 164 | * find a connection for a call | ||
| 165 | * - called in process context with IRQs enabled | ||
| 166 | */ | ||
| 167 | int rxrpc_connect_call(struct rxrpc_call *call, | ||
| 168 | struct rxrpc_conn_parameters *cp, | ||
| 169 | struct sockaddr_rxrpc *srx, | ||
| 170 | gfp_t gfp) | ||
| 171 | { | ||
| 172 | struct rxrpc_connection *conn, *candidate = NULL; | ||
| 173 | struct rxrpc_local *local = cp->local; | ||
| 174 | struct rb_node *p, **pp, *parent; | ||
| 175 | long diff; | ||
| 176 | int chan; | ||
| 177 | 81 | ||
| 178 | DECLARE_WAITQUEUE(myself, current); | 82 | _enter(",%x", sp->hdr.cid & RXRPC_CIDMASK); |
| 179 | 83 | ||
| 180 | _enter("{%d,%lx},", call->debug_id, call->user_call_ID); | 84 | if (rxrpc_extract_addr_from_skb(&srx, skb) < 0) |
| 85 | goto not_found; | ||
| 181 | 86 | ||
| 182 | cp->peer = rxrpc_lookup_peer(cp->local, srx, gfp); | 87 | k.epoch = sp->hdr.epoch; |
| 183 | if (!cp->peer) | 88 | k.cid = sp->hdr.cid & RXRPC_CIDMASK; |
| 184 | return -ENOMEM; | ||
| 185 | 89 | ||
| 186 | if (!cp->exclusive) { | 90 | /* We may have to handle mixing IPv4 and IPv6 */ |
| 187 | /* Search for a existing client connection unless this is going | 91 | if (srx.transport.family != local->srx.transport.family) { |
| 188 | * to be a connection that's used exclusively for a single call. | 92 | pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n", |
| 189 | */ | 93 | srx.transport.family, |
| 190 | _debug("search 1"); | 94 | local->srx.transport.family); |
| 191 | spin_lock(&local->client_conns_lock); | 95 | goto not_found; |
| 192 | p = local->client_conns.rb_node; | ||
| 193 | while (p) { | ||
| 194 | conn = rb_entry(p, struct rxrpc_connection, client_node); | ||
| 195 | |||
| 196 | #define cmp(X) ((long)conn->params.X - (long)cp->X) | ||
| 197 | diff = (cmp(peer) ?: | ||
| 198 | cmp(key) ?: | ||
| 199 | cmp(security_level)); | ||
| 200 | if (diff < 0) | ||
| 201 | p = p->rb_left; | ||
| 202 | else if (diff > 0) | ||
| 203 | p = p->rb_right; | ||
| 204 | else | ||
| 205 | goto found_extant_conn; | ||
| 206 | } | ||
| 207 | spin_unlock(&local->client_conns_lock); | ||
| 208 | } | 96 | } |
| 209 | 97 | ||
| 210 | /* We didn't find a connection or we want an exclusive one. */ | 98 | k.epoch = sp->hdr.epoch; |
| 211 | _debug("get new conn"); | 99 | k.cid = sp->hdr.cid & RXRPC_CIDMASK; |
| 212 | candidate = rxrpc_alloc_client_connection(cp, gfp); | ||
| 213 | if (!candidate) { | ||
| 214 | _leave(" = -ENOMEM"); | ||
| 215 | return -ENOMEM; | ||
| 216 | } | ||
| 217 | 100 | ||
| 218 | if (cp->exclusive) { | 101 | if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) { |
| 219 | /* Assign the call on an exclusive connection to channel 0 and | 102 | /* We need to look up service connections by the full protocol |
| 220 | * don't add the connection to the endpoint's shareable conn | 103 | * parameter set. We look up the peer first as an intermediate |
| 221 | * lookup tree. | 104 | * step and then the connection from the peer's tree. |
| 222 | */ | 105 | */ |
| 223 | _debug("exclusive chan 0"); | 106 | peer = rxrpc_lookup_peer_rcu(local, &srx); |
| 224 | conn = candidate; | 107 | if (!peer) |
| 225 | atomic_set(&conn->avail_chans, RXRPC_MAXCALLS - 1); | 108 | goto not_found; |
| 226 | spin_lock(&conn->channel_lock); | 109 | conn = rxrpc_find_service_conn_rcu(peer, skb); |
| 227 | chan = 0; | 110 | if (!conn || atomic_read(&conn->usage) == 0) |
| 228 | goto found_channel; | 111 | goto not_found; |
| 229 | } | 112 | _leave(" = %p", conn); |
| 230 | 113 | return conn; | |
| 231 | /* We need to redo the search before attempting to add a new connection | 114 | } else { |
| 232 | * lest we race with someone else adding a conflicting instance. | 115 | /* Look up client connections by connection ID alone as their |
| 233 | */ | 116 | * IDs are unique for this machine. |
| 234 | _debug("search 2"); | 117 | */ |
| 235 | spin_lock(&local->client_conns_lock); | 118 | conn = idr_find(&rxrpc_client_conn_ids, |
| 236 | 119 | sp->hdr.cid >> RXRPC_CIDSHIFT); | |
| 237 | pp = &local->client_conns.rb_node; | 120 | if (!conn || atomic_read(&conn->usage) == 0) { |
| 238 | parent = NULL; | 121 | _debug("no conn"); |
| 239 | while (*pp) { | 122 | goto not_found; |
| 240 | parent = *pp; | ||
| 241 | conn = rb_entry(parent, struct rxrpc_connection, client_node); | ||
| 242 | |||
| 243 | diff = (cmp(peer) ?: | ||
| 244 | cmp(key) ?: | ||
| 245 | cmp(security_level)); | ||
| 246 | if (diff < 0) | ||
| 247 | pp = &(*pp)->rb_left; | ||
| 248 | else if (diff > 0) | ||
| 249 | pp = &(*pp)->rb_right; | ||
| 250 | else | ||
| 251 | goto found_extant_conn; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* The second search also failed; simply add the new connection with | ||
| 255 | * the new call in channel 0. Note that we need to take the channel | ||
| 256 | * lock before dropping the client conn lock. | ||
| 257 | */ | ||
| 258 | _debug("new conn"); | ||
| 259 | conn = candidate; | ||
| 260 | candidate = NULL; | ||
| 261 | |||
| 262 | rb_link_node(&conn->client_node, parent, pp); | ||
| 263 | rb_insert_color(&conn->client_node, &local->client_conns); | ||
| 264 | |||
| 265 | atomic_set(&conn->avail_chans, RXRPC_MAXCALLS - 1); | ||
| 266 | spin_lock(&conn->channel_lock); | ||
| 267 | spin_unlock(&local->client_conns_lock); | ||
| 268 | chan = 0; | ||
| 269 | |||
| 270 | found_channel: | ||
| 271 | _debug("found chan"); | ||
| 272 | call->conn = conn; | ||
| 273 | call->channel = chan; | ||
| 274 | call->epoch = conn->proto.epoch; | ||
| 275 | call->cid = conn->proto.cid | chan; | ||
| 276 | call->call_id = ++conn->call_counter; | ||
| 277 | rcu_assign_pointer(conn->channels[chan], call); | ||
| 278 | |||
| 279 | _net("CONNECT call %d on conn %d", call->debug_id, conn->debug_id); | ||
| 280 | |||
| 281 | rxrpc_add_call_ID_to_conn(conn, call); | ||
| 282 | spin_unlock(&conn->channel_lock); | ||
| 283 | rxrpc_put_peer(cp->peer); | ||
| 284 | cp->peer = NULL; | ||
| 285 | _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage)); | ||
| 286 | return 0; | ||
| 287 | |||
| 288 | /* We found a suitable connection already in existence. Discard any | ||
| 289 | * candidate we may have allocated, and try to get a channel on this | ||
| 290 | * one. | ||
| 291 | */ | ||
| 292 | found_extant_conn: | ||
| 293 | _debug("found conn"); | ||
| 294 | rxrpc_get_connection(conn); | ||
| 295 | spin_unlock(&local->client_conns_lock); | ||
| 296 | |||
| 297 | rxrpc_put_connection(candidate); | ||
| 298 | |||
| 299 | if (!atomic_add_unless(&conn->avail_chans, -1, 0)) { | ||
| 300 | if (!gfpflags_allow_blocking(gfp)) { | ||
| 301 | rxrpc_put_connection(conn); | ||
| 302 | _leave(" = -EAGAIN"); | ||
| 303 | return -EAGAIN; | ||
| 304 | } | 123 | } |
| 305 | 124 | ||
| 306 | add_wait_queue(&conn->channel_wq, &myself); | 125 | if (conn->proto.epoch != k.epoch || |
| 307 | for (;;) { | 126 | conn->params.local != local) |
| 308 | set_current_state(TASK_INTERRUPTIBLE); | 127 | goto not_found; |
| 309 | if (atomic_add_unless(&conn->avail_chans, -1, 0)) | 128 | |
| 310 | break; | 129 | peer = conn->params.peer; |
| 311 | if (signal_pending(current)) | 130 | switch (srx.transport.family) { |
| 312 | goto interrupted; | 131 | case AF_INET: |
| 313 | schedule(); | 132 | if (peer->srx.transport.sin.sin_port != |
| 133 | srx.transport.sin.sin_port || | ||
| 134 | peer->srx.transport.sin.sin_addr.s_addr != | ||
| 135 | srx.transport.sin.sin_addr.s_addr) | ||
| 136 | goto not_found; | ||
| 137 | break; | ||
| 138 | default: | ||
| 139 | BUG(); | ||
| 314 | } | 140 | } |
| 315 | remove_wait_queue(&conn->channel_wq, &myself); | ||
| 316 | __set_current_state(TASK_RUNNING); | ||
| 317 | } | ||
| 318 | |||
| 319 | /* The connection allegedly now has a free channel and we can now | ||
| 320 | * attach the call to it. | ||
| 321 | */ | ||
| 322 | spin_lock(&conn->channel_lock); | ||
| 323 | |||
| 324 | for (chan = 0; chan < RXRPC_MAXCALLS; chan++) | ||
| 325 | if (!conn->channels[chan]) | ||
| 326 | goto found_channel; | ||
| 327 | BUG(); | ||
| 328 | |||
| 329 | interrupted: | ||
| 330 | remove_wait_queue(&conn->channel_wq, &myself); | ||
| 331 | __set_current_state(TASK_RUNNING); | ||
| 332 | rxrpc_put_connection(conn); | ||
| 333 | rxrpc_put_peer(cp->peer); | ||
| 334 | cp->peer = NULL; | ||
| 335 | _leave(" = -ERESTARTSYS"); | ||
| 336 | return -ERESTARTSYS; | ||
| 337 | } | ||
| 338 | |||
| 339 | /* | ||
| 340 | * get a record of an incoming connection | ||
| 341 | */ | ||
| 342 | struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *local, | ||
| 343 | struct rxrpc_peer *peer, | ||
| 344 | struct sk_buff *skb) | ||
| 345 | { | ||
| 346 | struct rxrpc_connection *conn, *candidate = NULL; | ||
| 347 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | ||
| 348 | struct rb_node *p, **pp; | ||
| 349 | const char *new = "old"; | ||
| 350 | __be32 epoch; | ||
| 351 | u32 cid; | ||
| 352 | |||
| 353 | _enter(""); | ||
| 354 | |||
| 355 | ASSERT(sp->hdr.flags & RXRPC_CLIENT_INITIATED); | ||
| 356 | |||
| 357 | epoch = sp->hdr.epoch; | ||
| 358 | cid = sp->hdr.cid & RXRPC_CIDMASK; | ||
| 359 | |||
| 360 | /* search the connection list first */ | ||
| 361 | read_lock_bh(&peer->conn_lock); | ||
| 362 | |||
| 363 | p = peer->service_conns.rb_node; | ||
| 364 | while (p) { | ||
| 365 | conn = rb_entry(p, struct rxrpc_connection, service_node); | ||
| 366 | 141 | ||
| 367 | _debug("maybe %x", conn->proto.cid); | 142 | _leave(" = %p", conn); |
| 368 | 143 | return conn; | |
| 369 | if (epoch < conn->proto.epoch) | ||
| 370 | p = p->rb_left; | ||
| 371 | else if (epoch > conn->proto.epoch) | ||
| 372 | p = p->rb_right; | ||
| 373 | else if (cid < conn->proto.cid) | ||
| 374 | p = p->rb_left; | ||
| 375 | else if (cid > conn->proto.cid) | ||
| 376 | p = p->rb_right; | ||
| 377 | else | ||
| 378 | goto found_extant_connection; | ||
| 379 | } | ||
| 380 | read_unlock_bh(&peer->conn_lock); | ||
| 381 | |||
| 382 | /* not yet present - create a candidate for a new record and then | ||
| 383 | * redo the search */ | ||
| 384 | candidate = rxrpc_alloc_connection(GFP_NOIO); | ||
| 385 | if (!candidate) { | ||
| 386 | _leave(" = -ENOMEM"); | ||
| 387 | return ERR_PTR(-ENOMEM); | ||
| 388 | } | 144 | } |
| 389 | 145 | ||
| 390 | candidate->proto.local = local; | 146 | not_found: |
| 391 | candidate->proto.epoch = sp->hdr.epoch; | 147 | _leave(" = NULL"); |
| 392 | candidate->proto.cid = sp->hdr.cid & RXRPC_CIDMASK; | 148 | return NULL; |
| 393 | candidate->proto.in_clientflag = RXRPC_CLIENT_INITIATED; | ||
| 394 | candidate->params.local = local; | ||
| 395 | candidate->params.peer = peer; | ||
| 396 | candidate->params.service_id = sp->hdr.serviceId; | ||
| 397 | candidate->security_ix = sp->hdr.securityIndex; | ||
| 398 | candidate->out_clientflag = 0; | ||
| 399 | candidate->state = RXRPC_CONN_SERVER; | ||
| 400 | if (candidate->params.service_id) | ||
| 401 | candidate->state = RXRPC_CONN_SERVER_UNSECURED; | ||
| 402 | |||
| 403 | write_lock_bh(&peer->conn_lock); | ||
| 404 | |||
| 405 | pp = &peer->service_conns.rb_node; | ||
| 406 | p = NULL; | ||
| 407 | while (*pp) { | ||
| 408 | p = *pp; | ||
| 409 | conn = rb_entry(p, struct rxrpc_connection, service_node); | ||
| 410 | |||
| 411 | if (epoch < conn->proto.epoch) | ||
| 412 | pp = &(*pp)->rb_left; | ||
| 413 | else if (epoch > conn->proto.epoch) | ||
| 414 | pp = &(*pp)->rb_right; | ||
| 415 | else if (cid < conn->proto.cid) | ||
| 416 | pp = &(*pp)->rb_left; | ||
| 417 | else if (cid > conn->proto.cid) | ||
| 418 | pp = &(*pp)->rb_right; | ||
| 419 | else | ||
| 420 | goto found_extant_second; | ||
| 421 | } | ||
| 422 | |||
| 423 | /* we can now add the new candidate to the list */ | ||
| 424 | conn = candidate; | ||
| 425 | candidate = NULL; | ||
| 426 | rb_link_node(&conn->service_node, p, pp); | ||
| 427 | rb_insert_color(&conn->service_node, &peer->service_conns); | ||
| 428 | rxrpc_get_peer(peer); | ||
| 429 | rxrpc_get_local(local); | ||
| 430 | |||
| 431 | write_unlock_bh(&peer->conn_lock); | ||
| 432 | |||
| 433 | write_lock(&rxrpc_connection_lock); | ||
| 434 | list_add_tail(&conn->link, &rxrpc_connections); | ||
| 435 | write_unlock(&rxrpc_connection_lock); | ||
| 436 | |||
| 437 | new = "new"; | ||
| 438 | |||
| 439 | success: | ||
| 440 | _net("CONNECTION %s %d {%x}", new, conn->debug_id, conn->proto.cid); | ||
| 441 | |||
| 442 | _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage)); | ||
| 443 | return conn; | ||
| 444 | |||
| 445 | /* we found the connection in the list immediately */ | ||
| 446 | found_extant_connection: | ||
| 447 | if (sp->hdr.securityIndex != conn->security_ix) { | ||
| 448 | read_unlock_bh(&peer->conn_lock); | ||
| 449 | goto security_mismatch; | ||
| 450 | } | ||
| 451 | rxrpc_get_connection(conn); | ||
| 452 | read_unlock_bh(&peer->conn_lock); | ||
| 453 | goto success; | ||
| 454 | |||
| 455 | /* we found the connection on the second time through the list */ | ||
| 456 | found_extant_second: | ||
| 457 | if (sp->hdr.securityIndex != conn->security_ix) { | ||
| 458 | write_unlock_bh(&peer->conn_lock); | ||
| 459 | goto security_mismatch; | ||
| 460 | } | ||
| 461 | rxrpc_get_connection(conn); | ||
| 462 | write_unlock_bh(&peer->conn_lock); | ||
| 463 | kfree(candidate); | ||
| 464 | goto success; | ||
| 465 | |||
| 466 | security_mismatch: | ||
| 467 | kfree(candidate); | ||
| 468 | _leave(" = -EKEYREJECTED"); | ||
| 469 | return ERR_PTR(-EKEYREJECTED); | ||
| 470 | } | 149 | } |
| 471 | 150 | ||
| 472 | /* | 151 | /* |
| 473 | * find a connection based on transport and RxRPC connection ID for an incoming | 152 | * Disconnect a call and clear any channel it occupies when that call |
| 474 | * packet | 153 | * terminates. The caller must hold the channel_lock and must release the |
| 154 | * call's ref on the connection. | ||
| 475 | */ | 155 | */ |
| 476 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local, | 156 | void __rxrpc_disconnect_call(struct rxrpc_call *call) |
| 477 | struct rxrpc_peer *peer, | ||
| 478 | struct sk_buff *skb) | ||
| 479 | { | 157 | { |
| 480 | struct rxrpc_connection *conn; | 158 | struct rxrpc_connection *conn = call->conn; |
| 481 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 159 | struct rxrpc_channel *chan = &conn->channels[call->channel]; |
| 482 | struct rb_node *p; | ||
| 483 | u32 epoch, cid; | ||
| 484 | |||
| 485 | _enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags); | ||
| 486 | 160 | ||
| 487 | read_lock_bh(&peer->conn_lock); | 161 | _enter("%d,%d", conn->debug_id, call->channel); |
| 488 | 162 | ||
| 489 | cid = sp->hdr.cid & RXRPC_CIDMASK; | 163 | if (rcu_access_pointer(chan->call) == call) { |
| 490 | epoch = sp->hdr.epoch; | 164 | /* Save the result of the call so that we can repeat it if necessary |
| 165 | * through the channel, whilst disposing of the actual call record. | ||
| 166 | */ | ||
| 167 | chan->last_result = call->local_abort; | ||
| 168 | smp_wmb(); | ||
| 169 | chan->last_call = chan->call_id; | ||
| 170 | chan->call_id = chan->call_counter; | ||
| 491 | 171 | ||
| 492 | if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) { | 172 | rcu_assign_pointer(chan->call, NULL); |
| 493 | p = peer->service_conns.rb_node; | 173 | atomic_inc(&conn->avail_chans); |
| 494 | while (p) { | 174 | wake_up(&conn->channel_wq); |
| 495 | conn = rb_entry(p, struct rxrpc_connection, service_node); | ||
| 496 | |||
| 497 | _debug("maybe %x", conn->proto.cid); | ||
| 498 | |||
| 499 | if (epoch < conn->proto.epoch) | ||
| 500 | p = p->rb_left; | ||
| 501 | else if (epoch > conn->proto.epoch) | ||
| 502 | p = p->rb_right; | ||
| 503 | else if (cid < conn->proto.cid) | ||
| 504 | p = p->rb_left; | ||
| 505 | else if (cid > conn->proto.cid) | ||
| 506 | p = p->rb_right; | ||
| 507 | else | ||
| 508 | goto found; | ||
| 509 | } | ||
| 510 | } else { | ||
| 511 | conn = idr_find(&rxrpc_client_conn_ids, cid >> RXRPC_CIDSHIFT); | ||
| 512 | if (conn && conn->proto.epoch == epoch) | ||
| 513 | goto found; | ||
| 514 | } | 175 | } |
| 515 | 176 | ||
| 516 | read_unlock_bh(&peer->conn_lock); | 177 | _leave(""); |
| 517 | _leave(" = NULL"); | ||
| 518 | return NULL; | ||
| 519 | |||
| 520 | found: | ||
| 521 | rxrpc_get_connection(conn); | ||
| 522 | read_unlock_bh(&peer->conn_lock); | ||
| 523 | _leave(" = %p", conn); | ||
| 524 | return conn; | ||
| 525 | } | 178 | } |
| 526 | 179 | ||
| 527 | /* | 180 | /* |
| @@ -531,15 +184,13 @@ found: | |||
| 531 | void rxrpc_disconnect_call(struct rxrpc_call *call) | 184 | void rxrpc_disconnect_call(struct rxrpc_call *call) |
| 532 | { | 185 | { |
| 533 | struct rxrpc_connection *conn = call->conn; | 186 | struct rxrpc_connection *conn = call->conn; |
| 534 | unsigned chan = call->channel; | ||
| 535 | 187 | ||
| 536 | _enter("%d,%d", conn->debug_id, call->channel); | 188 | spin_lock(&conn->channel_lock); |
| 189 | __rxrpc_disconnect_call(call); | ||
| 190 | spin_unlock(&conn->channel_lock); | ||
| 537 | 191 | ||
| 538 | if (conn->channels[chan] == call) { | 192 | call->conn = NULL; |
| 539 | rcu_assign_pointer(conn->channels[chan], NULL); | 193 | rxrpc_put_connection(conn); |
| 540 | atomic_inc(&conn->avail_chans); | ||
| 541 | wake_up(&conn->channel_wq); | ||
| 542 | } | ||
| 543 | } | 194 | } |
| 544 | 195 | ||
| 545 | /* | 196 | /* |
| @@ -553,10 +204,10 @@ void rxrpc_put_connection(struct rxrpc_connection *conn) | |||
| 553 | _enter("%p{u=%d,d=%d}", | 204 | _enter("%p{u=%d,d=%d}", |
| 554 | conn, atomic_read(&conn->usage), conn->debug_id); | 205 | conn, atomic_read(&conn->usage), conn->debug_id); |
| 555 | 206 | ||
| 556 | ASSERTCMP(atomic_read(&conn->usage), >, 0); | 207 | ASSERTCMP(atomic_read(&conn->usage), >, 1); |
| 557 | 208 | ||
| 558 | conn->put_time = ktime_get_seconds(); | 209 | conn->put_time = ktime_get_seconds(); |
| 559 | if (atomic_dec_and_test(&conn->usage)) { | 210 | if (atomic_dec_return(&conn->usage) == 1) { |
| 560 | _debug("zombie"); | 211 | _debug("zombie"); |
| 561 | rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0); | 212 | rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0); |
| 562 | } | 213 | } |
| @@ -567,15 +218,17 @@ void rxrpc_put_connection(struct rxrpc_connection *conn) | |||
| 567 | /* | 218 | /* |
| 568 | * destroy a virtual connection | 219 | * destroy a virtual connection |
| 569 | */ | 220 | */ |
| 570 | static void rxrpc_destroy_connection(struct rxrpc_connection *conn) | 221 | static void rxrpc_destroy_connection(struct rcu_head *rcu) |
| 571 | { | 222 | { |
| 572 | _enter("%p{%d}", conn, atomic_read(&conn->usage)); | 223 | struct rxrpc_connection *conn = |
| 224 | container_of(rcu, struct rxrpc_connection, rcu); | ||
| 225 | |||
| 226 | _enter("{%d,u=%d}", conn->debug_id, atomic_read(&conn->usage)); | ||
| 573 | 227 | ||
| 574 | ASSERTCMP(atomic_read(&conn->usage), ==, 0); | 228 | ASSERTCMP(atomic_read(&conn->usage), ==, 0); |
| 575 | 229 | ||
| 576 | _net("DESTROY CONN %d", conn->debug_id); | 230 | _net("DESTROY CONN %d", conn->debug_id); |
| 577 | 231 | ||
| 578 | ASSERT(RB_EMPTY_ROOT(&conn->calls)); | ||
| 579 | rxrpc_purge_queue(&conn->rx_queue); | 232 | rxrpc_purge_queue(&conn->rx_queue); |
| 580 | 233 | ||
| 581 | conn->security->clear(conn); | 234 | conn->security->clear(conn); |
| @@ -594,59 +247,41 @@ static void rxrpc_destroy_connection(struct rxrpc_connection *conn) | |||
| 594 | static void rxrpc_connection_reaper(struct work_struct *work) | 247 | static void rxrpc_connection_reaper(struct work_struct *work) |
| 595 | { | 248 | { |
| 596 | struct rxrpc_connection *conn, *_p; | 249 | struct rxrpc_connection *conn, *_p; |
| 597 | struct rxrpc_peer *peer; | 250 | unsigned long reap_older_than, earliest, put_time, now; |
| 598 | unsigned long now, earliest, reap_time; | ||
| 599 | 251 | ||
| 600 | LIST_HEAD(graveyard); | 252 | LIST_HEAD(graveyard); |
| 601 | 253 | ||
| 602 | _enter(""); | 254 | _enter(""); |
| 603 | 255 | ||
| 604 | now = ktime_get_seconds(); | 256 | now = ktime_get_seconds(); |
| 257 | reap_older_than = now - rxrpc_connection_expiry; | ||
| 605 | earliest = ULONG_MAX; | 258 | earliest = ULONG_MAX; |
| 606 | 259 | ||
| 607 | write_lock(&rxrpc_connection_lock); | 260 | write_lock(&rxrpc_connection_lock); |
| 608 | list_for_each_entry_safe(conn, _p, &rxrpc_connections, link) { | 261 | list_for_each_entry_safe(conn, _p, &rxrpc_connections, link) { |
| 609 | _debug("reap CONN %d { u=%d,t=%ld }", | 262 | ASSERTCMP(atomic_read(&conn->usage), >, 0); |
| 610 | conn->debug_id, atomic_read(&conn->usage), | 263 | if (likely(atomic_read(&conn->usage) > 1)) |
| 611 | (long) now - (long) conn->put_time); | ||
| 612 | |||
| 613 | if (likely(atomic_read(&conn->usage) > 0)) | ||
| 614 | continue; | 264 | continue; |
| 615 | 265 | ||
| 616 | if (rxrpc_conn_is_client(conn)) { | 266 | put_time = READ_ONCE(conn->put_time); |
| 617 | struct rxrpc_local *local = conn->params.local; | 267 | if (time_after(put_time, reap_older_than)) { |
| 618 | spin_lock(&local->client_conns_lock); | 268 | if (time_before(put_time, earliest)) |
| 619 | reap_time = conn->put_time + rxrpc_connection_expiry; | 269 | earliest = put_time; |
| 620 | 270 | continue; | |
| 621 | if (atomic_read(&conn->usage) > 0) { | ||
| 622 | ; | ||
| 623 | } else if (reap_time <= now) { | ||
| 624 | list_move_tail(&conn->link, &graveyard); | ||
| 625 | rxrpc_put_client_connection_id(conn); | ||
| 626 | rb_erase(&conn->client_node, | ||
| 627 | &local->client_conns); | ||
| 628 | } else if (reap_time < earliest) { | ||
| 629 | earliest = reap_time; | ||
| 630 | } | ||
| 631 | |||
| 632 | spin_unlock(&local->client_conns_lock); | ||
| 633 | } else { | ||
| 634 | peer = conn->params.peer; | ||
| 635 | write_lock_bh(&peer->conn_lock); | ||
| 636 | reap_time = conn->put_time + rxrpc_connection_expiry; | ||
| 637 | |||
| 638 | if (atomic_read(&conn->usage) > 0) { | ||
| 639 | ; | ||
| 640 | } else if (reap_time <= now) { | ||
| 641 | list_move_tail(&conn->link, &graveyard); | ||
| 642 | rb_erase(&conn->service_node, | ||
| 643 | &peer->service_conns); | ||
| 644 | } else if (reap_time < earliest) { | ||
| 645 | earliest = reap_time; | ||
| 646 | } | ||
| 647 | |||
| 648 | write_unlock_bh(&peer->conn_lock); | ||
| 649 | } | 271 | } |
| 272 | |||
| 273 | /* The usage count sits at 1 whilst the object is unused on the | ||
| 274 | * list; we reduce that to 0 to make the object unavailable. | ||
| 275 | */ | ||
| 276 | if (atomic_cmpxchg(&conn->usage, 1, 0) != 1) | ||
| 277 | continue; | ||
| 278 | |||
| 279 | if (rxrpc_conn_is_client(conn)) | ||
| 280 | rxrpc_unpublish_client_conn(conn); | ||
| 281 | else | ||
| 282 | rxrpc_unpublish_service_conn(conn); | ||
| 283 | |||
| 284 | list_move_tail(&conn->link, &graveyard); | ||
| 650 | } | 285 | } |
| 651 | write_unlock(&rxrpc_connection_lock); | 286 | write_unlock(&rxrpc_connection_lock); |
| 652 | 287 | ||
| @@ -657,14 +292,14 @@ static void rxrpc_connection_reaper(struct work_struct *work) | |||
| 657 | (earliest - now) * HZ); | 292 | (earliest - now) * HZ); |
| 658 | } | 293 | } |
| 659 | 294 | ||
| 660 | /* then destroy all those pulled out */ | ||
| 661 | while (!list_empty(&graveyard)) { | 295 | while (!list_empty(&graveyard)) { |
| 662 | conn = list_entry(graveyard.next, struct rxrpc_connection, | 296 | conn = list_entry(graveyard.next, struct rxrpc_connection, |
| 663 | link); | 297 | link); |
| 664 | list_del_init(&conn->link); | 298 | list_del_init(&conn->link); |
| 665 | 299 | ||
| 666 | ASSERTCMP(atomic_read(&conn->usage), ==, 0); | 300 | ASSERTCMP(atomic_read(&conn->usage), ==, 0); |
| 667 | rxrpc_destroy_connection(conn); | 301 | skb_queue_purge(&conn->rx_queue); |
| 302 | call_rcu(&conn->rcu, rxrpc_destroy_connection); | ||
| 668 | } | 303 | } |
| 669 | 304 | ||
| 670 | _leave(""); | 305 | _leave(""); |
| @@ -676,11 +311,30 @@ static void rxrpc_connection_reaper(struct work_struct *work) | |||
| 676 | */ | 311 | */ |
| 677 | void __exit rxrpc_destroy_all_connections(void) | 312 | void __exit rxrpc_destroy_all_connections(void) |
| 678 | { | 313 | { |
| 314 | struct rxrpc_connection *conn, *_p; | ||
| 315 | bool leak = false; | ||
| 316 | |||
| 679 | _enter(""); | 317 | _enter(""); |
| 680 | 318 | ||
| 681 | rxrpc_connection_expiry = 0; | 319 | rxrpc_connection_expiry = 0; |
| 682 | cancel_delayed_work(&rxrpc_connection_reap); | 320 | cancel_delayed_work(&rxrpc_connection_reap); |
| 683 | rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0); | 321 | rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0); |
| 322 | flush_workqueue(rxrpc_workqueue); | ||
| 323 | |||
| 324 | write_lock(&rxrpc_connection_lock); | ||
| 325 | list_for_each_entry_safe(conn, _p, &rxrpc_connections, link) { | ||
| 326 | pr_err("AF_RXRPC: Leaked conn %p {%d}\n", | ||
| 327 | conn, atomic_read(&conn->usage)); | ||
| 328 | leak = true; | ||
| 329 | } | ||
| 330 | write_unlock(&rxrpc_connection_lock); | ||
| 331 | BUG_ON(leak); | ||
| 332 | |||
| 333 | /* Make sure the local and peer records pinned by any dying connections | ||
| 334 | * are released. | ||
| 335 | */ | ||
| 336 | rcu_barrier(); | ||
| 337 | rxrpc_destroy_client_conn_ids(); | ||
| 684 | 338 | ||
| 685 | _leave(""); | 339 | _leave(""); |
| 686 | } | 340 | } |
diff --git a/net/rxrpc/conn_service.c b/net/rxrpc/conn_service.c new file mode 100644 index 000000000000..7cbd612be0d7 --- /dev/null +++ b/net/rxrpc/conn_service.c | |||
| @@ -0,0 +1,230 @@ | |||
| 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 | |||
| 12 | #include <linux/slab.h> | ||
| 13 | #include "ar-internal.h" | ||
| 14 | |||
| 15 | /* | ||
| 16 | * Find a service connection under RCU conditions. | ||
| 17 | * | ||
| 18 | * We could use a hash table, but that is subject to bucket stuffing by an | ||
| 19 | * attacker as the client gets to pick the epoch and cid values and would know | ||
| 20 | * the hash function. So, instead, we use a hash table for the peer and from | ||
| 21 | * that an rbtree to find the service connection. Under ordinary circumstances | ||
| 22 | * it might be slower than a large hash table, but it is at least limited in | ||
| 23 | * depth. | ||
| 24 | */ | ||
| 25 | struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *peer, | ||
| 26 | struct sk_buff *skb) | ||
| 27 | { | ||
| 28 | struct rxrpc_connection *conn = NULL; | ||
| 29 | struct rxrpc_conn_proto k; | ||
| 30 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | ||
| 31 | struct rb_node *p; | ||
| 32 | unsigned int seq = 0; | ||
| 33 | |||
| 34 | k.epoch = sp->hdr.epoch; | ||
| 35 | k.cid = sp->hdr.cid & RXRPC_CIDMASK; | ||
| 36 | |||
| 37 | do { | ||
| 38 | /* Unfortunately, rbtree walking doesn't give reliable results | ||
| 39 | * under just the RCU read lock, so we have to check for | ||
| 40 | * changes. | ||
| 41 | */ | ||
| 42 | read_seqbegin_or_lock(&peer->service_conn_lock, &seq); | ||
| 43 | |||
| 44 | p = rcu_dereference_raw(peer->service_conns.rb_node); | ||
| 45 | while (p) { | ||
| 46 | conn = rb_entry(p, struct rxrpc_connection, service_node); | ||
| 47 | |||
| 48 | if (conn->proto.index_key < k.index_key) | ||
| 49 | p = rcu_dereference_raw(p->rb_left); | ||
| 50 | else if (conn->proto.index_key > k.index_key) | ||
| 51 | p = rcu_dereference_raw(p->rb_right); | ||
| 52 | else | ||
| 53 | goto done; | ||
| 54 | conn = NULL; | ||
| 55 | } | ||
| 56 | } while (need_seqretry(&peer->service_conn_lock, seq)); | ||
| 57 | |||
| 58 | done: | ||
| 59 | done_seqretry(&peer->service_conn_lock, seq); | ||
| 60 | _leave(" = %d", conn ? conn->debug_id : -1); | ||
| 61 | return conn; | ||
| 62 | } | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Insert a service connection into a peer's tree, thereby making it a target | ||
| 66 | * for incoming packets. | ||
| 67 | */ | ||
| 68 | static struct rxrpc_connection * | ||
| 69 | rxrpc_publish_service_conn(struct rxrpc_peer *peer, | ||
| 70 | struct rxrpc_connection *conn) | ||
| 71 | { | ||
| 72 | struct rxrpc_connection *cursor = NULL; | ||
| 73 | struct rxrpc_conn_proto k = conn->proto; | ||
| 74 | struct rb_node **pp, *parent; | ||
| 75 | |||
| 76 | write_seqlock_bh(&peer->service_conn_lock); | ||
| 77 | |||
| 78 | pp = &peer->service_conns.rb_node; | ||
| 79 | parent = NULL; | ||
| 80 | while (*pp) { | ||
| 81 | parent = *pp; | ||
| 82 | cursor = rb_entry(parent, | ||
| 83 | struct rxrpc_connection, service_node); | ||
| 84 | |||
| 85 | if (cursor->proto.index_key < k.index_key) | ||
| 86 | pp = &(*pp)->rb_left; | ||
| 87 | else if (cursor->proto.index_key > k.index_key) | ||
| 88 | pp = &(*pp)->rb_right; | ||
| 89 | else | ||
| 90 | goto found_extant_conn; | ||
| 91 | } | ||
| 92 | |||
| 93 | rb_link_node_rcu(&conn->service_node, parent, pp); | ||
| 94 | rb_insert_color(&conn->service_node, &peer->service_conns); | ||
| 95 | conn_published: | ||
| 96 | set_bit(RXRPC_CONN_IN_SERVICE_CONNS, &conn->flags); | ||
| 97 | write_sequnlock_bh(&peer->service_conn_lock); | ||
| 98 | _leave(" = %d [new]", conn->debug_id); | ||
| 99 | return conn; | ||
| 100 | |||
| 101 | found_extant_conn: | ||
| 102 | if (atomic_read(&cursor->usage) == 0) | ||
| 103 | goto replace_old_connection; | ||
| 104 | write_sequnlock_bh(&peer->service_conn_lock); | ||
| 105 | /* We should not be able to get here. rxrpc_incoming_connection() is | ||
| 106 | * called in a non-reentrant context, so there can't be a race to | ||
| 107 | * insert a new connection. | ||
| 108 | */ | ||
| 109 | BUG(); | ||
| 110 | |||
| 111 | replace_old_connection: | ||
| 112 | /* The old connection is from an outdated epoch. */ | ||
| 113 | _debug("replace conn"); | ||
| 114 | rb_replace_node_rcu(&cursor->service_node, | ||
| 115 | &conn->service_node, | ||
| 116 | &peer->service_conns); | ||
| 117 | clear_bit(RXRPC_CONN_IN_SERVICE_CONNS, &cursor->flags); | ||
| 118 | goto conn_published; | ||
| 119 | } | ||
| 120 | |||
| 121 | /* | ||
| 122 | * get a record of an incoming connection | ||
| 123 | */ | ||
| 124 | struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *local, | ||
| 125 | struct sockaddr_rxrpc *srx, | ||
| 126 | struct sk_buff *skb) | ||
| 127 | { | ||
| 128 | struct rxrpc_connection *conn; | ||
| 129 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | ||
| 130 | struct rxrpc_peer *peer; | ||
| 131 | const char *new = "old"; | ||
| 132 | |||
| 133 | _enter(""); | ||
| 134 | |||
| 135 | peer = rxrpc_lookup_peer(local, srx, GFP_NOIO); | ||
| 136 | if (!peer) { | ||
| 137 | _debug("no peer"); | ||
| 138 | return ERR_PTR(-EBUSY); | ||
| 139 | } | ||
| 140 | |||
| 141 | ASSERT(sp->hdr.flags & RXRPC_CLIENT_INITIATED); | ||
| 142 | |||
| 143 | rcu_read_lock(); | ||
| 144 | peer = rxrpc_lookup_peer_rcu(local, srx); | ||
| 145 | if (peer) { | ||
| 146 | conn = rxrpc_find_service_conn_rcu(peer, skb); | ||
| 147 | if (conn) { | ||
| 148 | if (sp->hdr.securityIndex != conn->security_ix) | ||
| 149 | goto security_mismatch_rcu; | ||
| 150 | if (rxrpc_get_connection_maybe(conn)) | ||
| 151 | goto found_extant_connection_rcu; | ||
| 152 | |||
| 153 | /* The conn has expired but we can't remove it without | ||
| 154 | * the appropriate lock, so we attempt to replace it | ||
| 155 | * when we have a new candidate. | ||
| 156 | */ | ||
| 157 | } | ||
| 158 | |||
| 159 | if (!rxrpc_get_peer_maybe(peer)) | ||
| 160 | peer = NULL; | ||
| 161 | } | ||
| 162 | rcu_read_unlock(); | ||
| 163 | |||
| 164 | if (!peer) { | ||
| 165 | peer = rxrpc_lookup_peer(local, srx, GFP_NOIO); | ||
| 166 | if (IS_ERR(peer)) | ||
| 167 | goto enomem; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* We don't have a matching record yet. */ | ||
| 171 | conn = rxrpc_alloc_connection(GFP_NOIO); | ||
| 172 | if (!conn) | ||
| 173 | goto enomem_peer; | ||
| 174 | |||
| 175 | conn->proto.epoch = sp->hdr.epoch; | ||
| 176 | conn->proto.cid = sp->hdr.cid & RXRPC_CIDMASK; | ||
| 177 | conn->params.local = local; | ||
| 178 | conn->params.peer = peer; | ||
| 179 | conn->params.service_id = sp->hdr.serviceId; | ||
| 180 | conn->security_ix = sp->hdr.securityIndex; | ||
| 181 | conn->out_clientflag = 0; | ||
| 182 | conn->state = RXRPC_CONN_SERVICE; | ||
| 183 | if (conn->params.service_id) | ||
| 184 | conn->state = RXRPC_CONN_SERVICE_UNSECURED; | ||
| 185 | |||
| 186 | rxrpc_get_local(local); | ||
| 187 | |||
| 188 | write_lock(&rxrpc_connection_lock); | ||
| 189 | list_add_tail(&conn->link, &rxrpc_connections); | ||
| 190 | write_unlock(&rxrpc_connection_lock); | ||
| 191 | |||
| 192 | /* Make the connection a target for incoming packets. */ | ||
| 193 | rxrpc_publish_service_conn(peer, conn); | ||
| 194 | |||
| 195 | new = "new"; | ||
| 196 | |||
| 197 | success: | ||
| 198 | _net("CONNECTION %s %d {%x}", new, conn->debug_id, conn->proto.cid); | ||
| 199 | _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage)); | ||
| 200 | return conn; | ||
| 201 | |||
| 202 | found_extant_connection_rcu: | ||
| 203 | rcu_read_unlock(); | ||
| 204 | goto success; | ||
| 205 | |||
| 206 | security_mismatch_rcu: | ||
| 207 | rcu_read_unlock(); | ||
| 208 | _leave(" = -EKEYREJECTED"); | ||
| 209 | return ERR_PTR(-EKEYREJECTED); | ||
| 210 | |||
| 211 | enomem_peer: | ||
| 212 | rxrpc_put_peer(peer); | ||
| 213 | enomem: | ||
| 214 | _leave(" = -ENOMEM"); | ||
| 215 | return ERR_PTR(-ENOMEM); | ||
| 216 | } | ||
| 217 | |||
| 218 | /* | ||
| 219 | * Remove the service connection from the peer's tree, thereby removing it as a | ||
| 220 | * target for incoming packets. | ||
| 221 | */ | ||
| 222 | void rxrpc_unpublish_service_conn(struct rxrpc_connection *conn) | ||
| 223 | { | ||
| 224 | struct rxrpc_peer *peer = conn->params.peer; | ||
| 225 | |||
| 226 | write_seqlock_bh(&peer->service_conn_lock); | ||
| 227 | if (test_and_clear_bit(RXRPC_CONN_IN_SERVICE_CONNS, &conn->flags)) | ||
| 228 | rb_erase(&conn->service_node, &peer->service_conns); | ||
| 229 | write_sequnlock_bh(&peer->service_conn_lock); | ||
| 230 | } | ||
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index f4bd57b77b93..991a20d25093 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c | |||
| @@ -476,7 +476,7 @@ static void rxrpc_process_jumbo_packet(struct rxrpc_call *call, | |||
| 476 | sp->hdr.seq += 1; | 476 | sp->hdr.seq += 1; |
| 477 | sp->hdr.serial += 1; | 477 | sp->hdr.serial += 1; |
| 478 | sp->hdr.flags = jhdr.flags; | 478 | sp->hdr.flags = jhdr.flags; |
| 479 | sp->hdr._rsvd = jhdr._rsvd; | 479 | sp->hdr._rsvd = ntohs(jhdr._rsvd); |
| 480 | 480 | ||
| 481 | _proto("Rx DATA Jumbo %%%u", sp->hdr.serial - 1); | 481 | _proto("Rx DATA Jumbo %%%u", sp->hdr.serial - 1); |
| 482 | 482 | ||
| @@ -575,14 +575,13 @@ done: | |||
| 575 | * post connection-level events to the connection | 575 | * post connection-level events to the connection |
| 576 | * - this includes challenges, responses and some aborts | 576 | * - this includes challenges, responses and some aborts |
| 577 | */ | 577 | */ |
| 578 | static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn, | 578 | static bool rxrpc_post_packet_to_conn(struct rxrpc_connection *conn, |
| 579 | struct sk_buff *skb) | 579 | struct sk_buff *skb) |
| 580 | { | 580 | { |
| 581 | _enter("%p,%p", conn, skb); | 581 | _enter("%p,%p", conn, skb); |
| 582 | 582 | ||
| 583 | rxrpc_get_connection(conn); | ||
| 584 | skb_queue_tail(&conn->rx_queue, skb); | 583 | skb_queue_tail(&conn->rx_queue, skb); |
| 585 | rxrpc_queue_conn(conn); | 584 | return rxrpc_queue_conn(conn); |
| 586 | } | 585 | } |
| 587 | 586 | ||
| 588 | /* | 587 | /* |
| @@ -595,7 +594,7 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local, | |||
| 595 | _enter("%p,%p", local, skb); | 594 | _enter("%p,%p", local, skb); |
| 596 | 595 | ||
| 597 | skb_queue_tail(&local->event_queue, skb); | 596 | skb_queue_tail(&local->event_queue, skb); |
| 598 | rxrpc_queue_work(&local->processor); | 597 | rxrpc_queue_local(local); |
| 599 | } | 598 | } |
| 600 | 599 | ||
| 601 | /* | 600 | /* |
| @@ -627,32 +626,6 @@ int rxrpc_extract_header(struct rxrpc_skb_priv *sp, struct sk_buff *skb) | |||
| 627 | return 0; | 626 | return 0; |
| 628 | } | 627 | } |
| 629 | 628 | ||
| 630 | static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local, | ||
| 631 | struct sk_buff *skb) | ||
| 632 | { | ||
| 633 | struct rxrpc_peer *peer; | ||
| 634 | struct rxrpc_connection *conn; | ||
| 635 | struct sockaddr_rxrpc srx; | ||
| 636 | |||
| 637 | rxrpc_get_addr_from_skb(local, skb, &srx); | ||
| 638 | rcu_read_lock(); | ||
| 639 | peer = rxrpc_lookup_peer_rcu(local, &srx); | ||
| 640 | if (!peer) | ||
| 641 | goto cant_find_peer; | ||
| 642 | |||
| 643 | conn = rxrpc_find_connection(local, peer, skb); | ||
| 644 | rcu_read_unlock(); | ||
| 645 | if (!conn) | ||
| 646 | goto cant_find_conn; | ||
| 647 | |||
| 648 | return conn; | ||
| 649 | |||
| 650 | cant_find_peer: | ||
| 651 | rcu_read_unlock(); | ||
| 652 | cant_find_conn: | ||
| 653 | return NULL; | ||
| 654 | } | ||
| 655 | |||
| 656 | /* | 629 | /* |
| 657 | * handle data received on the local endpoint | 630 | * handle data received on the local endpoint |
| 658 | * - may be called in interrupt context | 631 | * - may be called in interrupt context |
| @@ -663,6 +636,7 @@ cant_find_conn: | |||
| 663 | */ | 636 | */ |
| 664 | void rxrpc_data_ready(struct sock *sk) | 637 | void rxrpc_data_ready(struct sock *sk) |
| 665 | { | 638 | { |
| 639 | struct rxrpc_connection *conn; | ||
| 666 | struct rxrpc_skb_priv *sp; | 640 | struct rxrpc_skb_priv *sp; |
| 667 | struct rxrpc_local *local = sk->sk_user_data; | 641 | struct rxrpc_local *local = sk->sk_user_data; |
| 668 | struct sk_buff *skb; | 642 | struct sk_buff *skb; |
| @@ -726,34 +700,37 @@ void rxrpc_data_ready(struct sock *sk) | |||
| 726 | (sp->hdr.callNumber == 0 || sp->hdr.seq == 0)) | 700 | (sp->hdr.callNumber == 0 || sp->hdr.seq == 0)) |
| 727 | goto bad_message; | 701 | goto bad_message; |
| 728 | 702 | ||
| 729 | if (sp->hdr.callNumber == 0) { | 703 | rcu_read_lock(); |
| 730 | /* This is a connection-level packet. These should be | ||
| 731 | * fairly rare, so the extra overhead of looking them up the | ||
| 732 | * old-fashioned way doesn't really hurt */ | ||
| 733 | struct rxrpc_connection *conn; | ||
| 734 | 704 | ||
| 735 | conn = rxrpc_conn_from_local(local, skb); | 705 | retry_find_conn: |
| 736 | if (!conn) | 706 | conn = rxrpc_find_connection_rcu(local, skb); |
| 737 | goto cant_route_call; | 707 | if (!conn) |
| 708 | goto cant_route_call; | ||
| 738 | 709 | ||
| 710 | if (sp->hdr.callNumber == 0) { | ||
| 711 | /* Connection-level packet */ | ||
| 739 | _debug("CONN %p {%d}", conn, conn->debug_id); | 712 | _debug("CONN %p {%d}", conn, conn->debug_id); |
| 740 | rxrpc_post_packet_to_conn(conn, skb); | 713 | if (!rxrpc_post_packet_to_conn(conn, skb)) |
| 741 | rxrpc_put_connection(conn); | 714 | goto retry_find_conn; |
| 742 | } else { | 715 | } else { |
| 743 | struct rxrpc_call *call; | 716 | /* Call-bound packets are routed by connection channel. */ |
| 717 | unsigned int channel = sp->hdr.cid & RXRPC_CHANNELMASK; | ||
| 718 | struct rxrpc_channel *chan = &conn->channels[channel]; | ||
| 719 | struct rxrpc_call *call = rcu_dereference(chan->call); | ||
| 744 | 720 | ||
| 745 | call = rxrpc_find_call_hash(&sp->hdr, local, | 721 | if (!call || atomic_read(&call->usage) == 0) |
| 746 | AF_INET, &ip_hdr(skb)->saddr); | ||
| 747 | if (call) | ||
| 748 | rxrpc_post_packet_to_call(call, skb); | ||
| 749 | else | ||
| 750 | goto cant_route_call; | 722 | goto cant_route_call; |
| 723 | |||
| 724 | rxrpc_post_packet_to_call(call, skb); | ||
| 751 | } | 725 | } |
| 752 | 726 | ||
| 727 | rcu_read_unlock(); | ||
| 753 | out: | 728 | out: |
| 754 | return; | 729 | return; |
| 755 | 730 | ||
| 756 | cant_route_call: | 731 | cant_route_call: |
| 732 | rcu_read_unlock(); | ||
| 733 | |||
| 757 | _debug("can't route call"); | 734 | _debug("can't route call"); |
| 758 | if (sp->hdr.flags & RXRPC_CLIENT_INITIATED && | 735 | if (sp->hdr.flags & RXRPC_CLIENT_INITIATED && |
| 759 | sp->hdr.type == RXRPC_PACKET_TYPE_DATA) { | 736 | sp->hdr.type == RXRPC_PACKET_TYPE_DATA) { |
diff --git a/net/rxrpc/insecure.c b/net/rxrpc/insecure.c index e571403613c1..c21ad213b337 100644 --- a/net/rxrpc/insecure.c +++ b/net/rxrpc/insecure.c | |||
| @@ -17,11 +17,12 @@ static int none_init_connection_security(struct rxrpc_connection *conn) | |||
| 17 | return 0; | 17 | return 0; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | static void none_prime_packet_security(struct rxrpc_connection *conn) | 20 | static int none_prime_packet_security(struct rxrpc_connection *conn) |
| 21 | { | 21 | { |
| 22 | return 0; | ||
| 22 | } | 23 | } |
| 23 | 24 | ||
| 24 | static int none_secure_packet(const struct rxrpc_call *call, | 25 | static int none_secure_packet(struct rxrpc_call *call, |
| 25 | struct sk_buff *skb, | 26 | struct sk_buff *skb, |
| 26 | size_t data_size, | 27 | size_t data_size, |
| 27 | void *sechdr) | 28 | void *sechdr) |
| @@ -29,7 +30,7 @@ static int none_secure_packet(const struct rxrpc_call *call, | |||
| 29 | return 0; | 30 | return 0; |
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | static int none_verify_packet(const struct rxrpc_call *call, | 33 | static int none_verify_packet(struct rxrpc_call *call, |
| 33 | struct sk_buff *skb, | 34 | struct sk_buff *skb, |
| 34 | u32 *_abort_code) | 35 | u32 *_abort_code) |
| 35 | { | 36 | { |
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c index 3ab7764f7cd8..a753796fbe8f 100644 --- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c | |||
| @@ -374,14 +374,17 @@ void __exit rxrpc_destroy_all_locals(void) | |||
| 374 | 374 | ||
| 375 | _enter(""); | 375 | _enter(""); |
| 376 | 376 | ||
| 377 | if (list_empty(&rxrpc_local_endpoints)) | 377 | flush_workqueue(rxrpc_workqueue); |
| 378 | return; | ||
| 379 | 378 | ||
| 380 | mutex_lock(&rxrpc_local_mutex); | 379 | if (!list_empty(&rxrpc_local_endpoints)) { |
| 381 | list_for_each_entry(local, &rxrpc_local_endpoints, link) { | 380 | mutex_lock(&rxrpc_local_mutex); |
| 382 | pr_err("AF_RXRPC: Leaked local %p {%d}\n", | 381 | list_for_each_entry(local, &rxrpc_local_endpoints, link) { |
| 383 | local, atomic_read(&local->usage)); | 382 | pr_err("AF_RXRPC: Leaked local %p {%d}\n", |
| 383 | local, atomic_read(&local->usage)); | ||
| 384 | } | ||
| 385 | mutex_unlock(&rxrpc_local_mutex); | ||
| 386 | BUG(); | ||
| 384 | } | 387 | } |
| 385 | mutex_unlock(&rxrpc_local_mutex); | 388 | |
| 386 | BUG(); | 389 | rcu_barrier(); |
| 387 | } | 390 | } |
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c index 01d4930a11f7..538e9831c699 100644 --- a/net/rxrpc/peer_object.c +++ b/net/rxrpc/peer_object.c | |||
| @@ -189,7 +189,7 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp) | |||
| 189 | INIT_WORK(&peer->error_distributor, | 189 | INIT_WORK(&peer->error_distributor, |
| 190 | &rxrpc_peer_error_distributor); | 190 | &rxrpc_peer_error_distributor); |
| 191 | peer->service_conns = RB_ROOT; | 191 | peer->service_conns = RB_ROOT; |
| 192 | rwlock_init(&peer->conn_lock); | 192 | seqlock_init(&peer->service_conn_lock); |
| 193 | spin_lock_init(&peer->lock); | 193 | spin_lock_init(&peer->lock); |
| 194 | peer->debug_id = atomic_inc_return(&rxrpc_debug_id); | 194 | peer->debug_id = atomic_inc_return(&rxrpc_debug_id); |
| 195 | } | 195 | } |
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c index 500cdcdc843c..ced5f07444e5 100644 --- a/net/rxrpc/proc.c +++ b/net/rxrpc/proc.c | |||
| @@ -14,15 +14,15 @@ | |||
| 14 | #include <net/af_rxrpc.h> | 14 | #include <net/af_rxrpc.h> |
| 15 | #include "ar-internal.h" | 15 | #include "ar-internal.h" |
| 16 | 16 | ||
| 17 | static const char *const rxrpc_conn_states[] = { | 17 | static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = { |
| 18 | [RXRPC_CONN_UNUSED] = "Unused ", | 18 | [RXRPC_CONN_UNUSED] = "Unused ", |
| 19 | [RXRPC_CONN_CLIENT] = "Client ", | 19 | [RXRPC_CONN_CLIENT] = "Client ", |
| 20 | [RXRPC_CONN_SERVER_UNSECURED] = "SvUnsec ", | 20 | [RXRPC_CONN_SERVICE_UNSECURED] = "SvUnsec ", |
| 21 | [RXRPC_CONN_SERVER_CHALLENGING] = "SvChall ", | 21 | [RXRPC_CONN_SERVICE_CHALLENGING] = "SvChall ", |
| 22 | [RXRPC_CONN_SERVER] = "SvSecure", | 22 | [RXRPC_CONN_SERVICE] = "SvSecure", |
| 23 | [RXRPC_CONN_REMOTELY_ABORTED] = "RmtAbort", | 23 | [RXRPC_CONN_REMOTELY_ABORTED] = "RmtAbort", |
| 24 | [RXRPC_CONN_LOCALLY_ABORTED] = "LocAbort", | 24 | [RXRPC_CONN_LOCALLY_ABORTED] = "LocAbort", |
| 25 | [RXRPC_CONN_NETWORK_ERROR] = "NetError", | 25 | [RXRPC_CONN_NETWORK_ERROR] = "NetError", |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | /* | 28 | /* |
| @@ -137,7 +137,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) | |||
| 137 | if (v == &rxrpc_connections) { | 137 | if (v == &rxrpc_connections) { |
| 138 | seq_puts(seq, | 138 | seq_puts(seq, |
| 139 | "Proto Local Remote " | 139 | "Proto Local Remote " |
| 140 | " SvID ConnID Calls End Use State Key " | 140 | " SvID ConnID End Use State Key " |
| 141 | " Serial ISerial\n" | 141 | " Serial ISerial\n" |
| 142 | ); | 142 | ); |
| 143 | return 0; | 143 | return 0; |
| @@ -154,13 +154,12 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) | |||
| 154 | ntohs(conn->params.peer->srx.transport.sin.sin_port)); | 154 | ntohs(conn->params.peer->srx.transport.sin.sin_port)); |
| 155 | 155 | ||
| 156 | seq_printf(seq, | 156 | seq_printf(seq, |
| 157 | "UDP %-22.22s %-22.22s %4x %08x %08x %s %3u" | 157 | "UDP %-22.22s %-22.22s %4x %08x %s %3u" |
| 158 | " %s %08x %08x %08x\n", | 158 | " %s %08x %08x %08x\n", |
| 159 | lbuff, | 159 | lbuff, |
| 160 | rbuff, | 160 | rbuff, |
| 161 | conn->params.service_id, | 161 | conn->params.service_id, |
| 162 | conn->proto.cid, | 162 | conn->proto.cid, |
| 163 | conn->call_counter, | ||
| 164 | rxrpc_conn_is_service(conn) ? "Svc" : "Clt", | 163 | rxrpc_conn_is_service(conn) ? "Svc" : "Clt", |
| 165 | atomic_read(&conn->usage), | 164 | atomic_read(&conn->usage), |
| 166 | rxrpc_conn_states[conn->state], | 165 | rxrpc_conn_states[conn->state], |
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index 23c05ec6fa28..63afa9e9cc08 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c | |||
| @@ -103,43 +103,43 @@ error: | |||
| 103 | * prime the encryption state with the invariant parts of a connection's | 103 | * prime the encryption state with the invariant parts of a connection's |
| 104 | * description | 104 | * description |
| 105 | */ | 105 | */ |
| 106 | static void rxkad_prime_packet_security(struct rxrpc_connection *conn) | 106 | static int rxkad_prime_packet_security(struct rxrpc_connection *conn) |
| 107 | { | 107 | { |
| 108 | struct rxrpc_key_token *token; | 108 | struct rxrpc_key_token *token; |
| 109 | SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); | 109 | SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); |
| 110 | struct scatterlist sg[2]; | 110 | struct scatterlist sg; |
| 111 | struct rxrpc_crypt iv; | 111 | struct rxrpc_crypt iv; |
| 112 | struct { | 112 | __be32 *tmpbuf; |
| 113 | __be32 x[4]; | 113 | size_t tmpsize = 4 * sizeof(__be32); |
| 114 | } tmpbuf __attribute__((aligned(16))); /* must all be in same page */ | ||
| 115 | 114 | ||
| 116 | _enter(""); | 115 | _enter(""); |
| 117 | 116 | ||
| 118 | if (!conn->params.key) | 117 | if (!conn->params.key) |
| 119 | return; | 118 | return 0; |
| 119 | |||
| 120 | tmpbuf = kmalloc(tmpsize, GFP_KERNEL); | ||
| 121 | if (!tmpbuf) | ||
| 122 | return -ENOMEM; | ||
| 120 | 123 | ||
| 121 | token = conn->params.key->payload.data[0]; | 124 | token = conn->params.key->payload.data[0]; |
| 122 | memcpy(&iv, token->kad->session_key, sizeof(iv)); | 125 | memcpy(&iv, token->kad->session_key, sizeof(iv)); |
| 123 | 126 | ||
| 124 | tmpbuf.x[0] = htonl(conn->proto.epoch); | 127 | tmpbuf[0] = htonl(conn->proto.epoch); |
| 125 | tmpbuf.x[1] = htonl(conn->proto.cid); | 128 | tmpbuf[1] = htonl(conn->proto.cid); |
| 126 | tmpbuf.x[2] = 0; | 129 | tmpbuf[2] = 0; |
| 127 | tmpbuf.x[3] = htonl(conn->security_ix); | 130 | tmpbuf[3] = htonl(conn->security_ix); |
| 128 | |||
| 129 | sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); | ||
| 130 | sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); | ||
| 131 | 131 | ||
| 132 | sg_init_one(&sg, tmpbuf, tmpsize); | ||
| 132 | skcipher_request_set_tfm(req, conn->cipher); | 133 | skcipher_request_set_tfm(req, conn->cipher); |
| 133 | skcipher_request_set_callback(req, 0, NULL, NULL); | 134 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 134 | skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); | 135 | skcipher_request_set_crypt(req, &sg, &sg, tmpsize, iv.x); |
| 135 | |||
| 136 | crypto_skcipher_encrypt(req); | 136 | crypto_skcipher_encrypt(req); |
| 137 | skcipher_request_zero(req); | 137 | skcipher_request_zero(req); |
| 138 | 138 | ||
| 139 | memcpy(&conn->csum_iv, &tmpbuf.x[2], sizeof(conn->csum_iv)); | 139 | memcpy(&conn->csum_iv, tmpbuf + 2, sizeof(conn->csum_iv)); |
| 140 | ASSERTCMP((u32 __force)conn->csum_iv.n[0], ==, (u32 __force)tmpbuf.x[2]); | 140 | kfree(tmpbuf); |
| 141 | 141 | _leave(" = 0"); | |
| 142 | _leave(""); | 142 | return 0; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | /* | 145 | /* |
| @@ -152,12 +152,9 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, | |||
| 152 | { | 152 | { |
| 153 | struct rxrpc_skb_priv *sp; | 153 | struct rxrpc_skb_priv *sp; |
| 154 | SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); | 154 | SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); |
| 155 | struct rxkad_level1_hdr hdr; | ||
| 155 | struct rxrpc_crypt iv; | 156 | struct rxrpc_crypt iv; |
| 156 | struct scatterlist sg[2]; | 157 | struct scatterlist sg; |
| 157 | struct { | ||
| 158 | struct rxkad_level1_hdr hdr; | ||
| 159 | __be32 first; /* first four bytes of data and padding */ | ||
| 160 | } tmpbuf __attribute__((aligned(8))); /* must all be in same page */ | ||
| 161 | u16 check; | 158 | u16 check; |
| 162 | 159 | ||
| 163 | sp = rxrpc_skb(skb); | 160 | sp = rxrpc_skb(skb); |
| @@ -167,24 +164,19 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, | |||
| 167 | check = sp->hdr.seq ^ sp->hdr.callNumber; | 164 | check = sp->hdr.seq ^ sp->hdr.callNumber; |
| 168 | data_size |= (u32)check << 16; | 165 | data_size |= (u32)check << 16; |
| 169 | 166 | ||
| 170 | tmpbuf.hdr.data_size = htonl(data_size); | 167 | hdr.data_size = htonl(data_size); |
| 171 | memcpy(&tmpbuf.first, sechdr + 4, sizeof(tmpbuf.first)); | 168 | memcpy(sechdr, &hdr, sizeof(hdr)); |
| 172 | 169 | ||
| 173 | /* start the encryption afresh */ | 170 | /* start the encryption afresh */ |
| 174 | memset(&iv, 0, sizeof(iv)); | 171 | memset(&iv, 0, sizeof(iv)); |
| 175 | 172 | ||
| 176 | sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); | 173 | sg_init_one(&sg, sechdr, 8); |
| 177 | sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); | ||
| 178 | |||
| 179 | skcipher_request_set_tfm(req, call->conn->cipher); | 174 | skcipher_request_set_tfm(req, call->conn->cipher); |
| 180 | skcipher_request_set_callback(req, 0, NULL, NULL); | 175 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 181 | skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); | 176 | skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x); |
| 182 | |||
| 183 | crypto_skcipher_encrypt(req); | 177 | crypto_skcipher_encrypt(req); |
| 184 | skcipher_request_zero(req); | 178 | skcipher_request_zero(req); |
| 185 | 179 | ||
| 186 | memcpy(sechdr, &tmpbuf, sizeof(tmpbuf)); | ||
| 187 | |||
| 188 | _leave(" = 0"); | 180 | _leave(" = 0"); |
| 189 | return 0; | 181 | return 0; |
| 190 | } | 182 | } |
| @@ -198,8 +190,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, | |||
| 198 | void *sechdr) | 190 | void *sechdr) |
| 199 | { | 191 | { |
| 200 | const struct rxrpc_key_token *token; | 192 | const struct rxrpc_key_token *token; |
| 201 | struct rxkad_level2_hdr rxkhdr | 193 | struct rxkad_level2_hdr rxkhdr; |
| 202 | __attribute__((aligned(8))); /* must be all on one page */ | ||
| 203 | struct rxrpc_skb_priv *sp; | 194 | struct rxrpc_skb_priv *sp; |
| 204 | SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); | 195 | SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); |
| 205 | struct rxrpc_crypt iv; | 196 | struct rxrpc_crypt iv; |
| @@ -218,18 +209,16 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, | |||
| 218 | 209 | ||
| 219 | rxkhdr.data_size = htonl(data_size | (u32)check << 16); | 210 | rxkhdr.data_size = htonl(data_size | (u32)check << 16); |
| 220 | rxkhdr.checksum = 0; | 211 | rxkhdr.checksum = 0; |
| 212 | memcpy(sechdr, &rxkhdr, sizeof(rxkhdr)); | ||
| 221 | 213 | ||
| 222 | /* encrypt from the session key */ | 214 | /* encrypt from the session key */ |
| 223 | token = call->conn->params.key->payload.data[0]; | 215 | token = call->conn->params.key->payload.data[0]; |
| 224 | memcpy(&iv, token->kad->session_key, sizeof(iv)); | 216 | memcpy(&iv, token->kad->session_key, sizeof(iv)); |
| 225 | 217 | ||
| 226 | sg_init_one(&sg[0], sechdr, sizeof(rxkhdr)); | 218 | sg_init_one(&sg[0], sechdr, sizeof(rxkhdr)); |
| 227 | sg_init_one(&sg[1], &rxkhdr, sizeof(rxkhdr)); | ||
| 228 | |||
| 229 | skcipher_request_set_tfm(req, call->conn->cipher); | 219 | skcipher_request_set_tfm(req, call->conn->cipher); |
| 230 | skcipher_request_set_callback(req, 0, NULL, NULL); | 220 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 231 | skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(rxkhdr), iv.x); | 221 | skcipher_request_set_crypt(req, &sg[0], &sg[0], sizeof(rxkhdr), iv.x); |
| 232 | |||
| 233 | crypto_skcipher_encrypt(req); | 222 | crypto_skcipher_encrypt(req); |
| 234 | 223 | ||
| 235 | /* we want to encrypt the skbuff in-place */ | 224 | /* we want to encrypt the skbuff in-place */ |
| @@ -243,9 +232,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, | |||
| 243 | 232 | ||
| 244 | sg_init_table(sg, nsg); | 233 | sg_init_table(sg, nsg); |
| 245 | skb_to_sgvec(skb, sg, 0, len); | 234 | skb_to_sgvec(skb, sg, 0, len); |
| 246 | |||
| 247 | skcipher_request_set_crypt(req, sg, sg, len, iv.x); | 235 | skcipher_request_set_crypt(req, sg, sg, len, iv.x); |
| 248 | |||
| 249 | crypto_skcipher_encrypt(req); | 236 | crypto_skcipher_encrypt(req); |
| 250 | 237 | ||
| 251 | _leave(" = 0"); | 238 | _leave(" = 0"); |
| @@ -259,7 +246,7 @@ out: | |||
| 259 | /* | 246 | /* |
| 260 | * checksum an RxRPC packet header | 247 | * checksum an RxRPC packet header |
| 261 | */ | 248 | */ |
| 262 | static int rxkad_secure_packet(const struct rxrpc_call *call, | 249 | static int rxkad_secure_packet(struct rxrpc_call *call, |
| 263 | struct sk_buff *skb, | 250 | struct sk_buff *skb, |
| 264 | size_t data_size, | 251 | size_t data_size, |
| 265 | void *sechdr) | 252 | void *sechdr) |
| @@ -267,10 +254,7 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, | |||
| 267 | struct rxrpc_skb_priv *sp; | 254 | struct rxrpc_skb_priv *sp; |
| 268 | SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); | 255 | SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); |
| 269 | struct rxrpc_crypt iv; | 256 | struct rxrpc_crypt iv; |
| 270 | struct scatterlist sg[2]; | 257 | struct scatterlist sg; |
| 271 | struct { | ||
| 272 | __be32 x[2]; | ||
| 273 | } tmpbuf __attribute__((aligned(8))); /* must all be in same page */ | ||
| 274 | u32 x, y; | 258 | u32 x, y; |
| 275 | int ret; | 259 | int ret; |
| 276 | 260 | ||
| @@ -293,20 +277,17 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, | |||
| 293 | /* calculate the security checksum */ | 277 | /* calculate the security checksum */ |
| 294 | x = call->channel << (32 - RXRPC_CIDSHIFT); | 278 | x = call->channel << (32 - RXRPC_CIDSHIFT); |
| 295 | x |= sp->hdr.seq & 0x3fffffff; | 279 | x |= sp->hdr.seq & 0x3fffffff; |
| 296 | tmpbuf.x[0] = htonl(sp->hdr.callNumber); | 280 | call->crypto_buf[0] = htonl(sp->hdr.callNumber); |
| 297 | tmpbuf.x[1] = htonl(x); | 281 | call->crypto_buf[1] = htonl(x); |
| 298 | |||
| 299 | sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); | ||
| 300 | sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); | ||
| 301 | 282 | ||
| 283 | sg_init_one(&sg, call->crypto_buf, 8); | ||
| 302 | skcipher_request_set_tfm(req, call->conn->cipher); | 284 | skcipher_request_set_tfm(req, call->conn->cipher); |
| 303 | skcipher_request_set_callback(req, 0, NULL, NULL); | 285 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 304 | skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); | 286 | skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x); |
| 305 | |||
| 306 | crypto_skcipher_encrypt(req); | 287 | crypto_skcipher_encrypt(req); |
| 307 | skcipher_request_zero(req); | 288 | skcipher_request_zero(req); |
| 308 | 289 | ||
| 309 | y = ntohl(tmpbuf.x[1]); | 290 | y = ntohl(call->crypto_buf[1]); |
| 310 | y = (y >> 16) & 0xffff; | 291 | y = (y >> 16) & 0xffff; |
| 311 | if (y == 0) | 292 | if (y == 0) |
| 312 | y = 1; /* zero checksums are not permitted */ | 293 | y = 1; /* zero checksums are not permitted */ |
| @@ -367,7 +348,6 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, | |||
| 367 | skcipher_request_set_tfm(req, call->conn->cipher); | 348 | skcipher_request_set_tfm(req, call->conn->cipher); |
| 368 | skcipher_request_set_callback(req, 0, NULL, NULL); | 349 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 369 | skcipher_request_set_crypt(req, sg, sg, 8, iv.x); | 350 | skcipher_request_set_crypt(req, sg, sg, 8, iv.x); |
| 370 | |||
| 371 | crypto_skcipher_decrypt(req); | 351 | crypto_skcipher_decrypt(req); |
| 372 | skcipher_request_zero(req); | 352 | skcipher_request_zero(req); |
| 373 | 353 | ||
| @@ -452,7 +432,6 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, | |||
| 452 | skcipher_request_set_tfm(req, call->conn->cipher); | 432 | skcipher_request_set_tfm(req, call->conn->cipher); |
| 453 | skcipher_request_set_callback(req, 0, NULL, NULL); | 433 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 454 | skcipher_request_set_crypt(req, sg, sg, skb->len, iv.x); | 434 | skcipher_request_set_crypt(req, sg, sg, skb->len, iv.x); |
| 455 | |||
| 456 | crypto_skcipher_decrypt(req); | 435 | crypto_skcipher_decrypt(req); |
| 457 | skcipher_request_zero(req); | 436 | skcipher_request_zero(req); |
| 458 | if (sg != _sg) | 437 | if (sg != _sg) |
| @@ -498,17 +477,14 @@ nomem: | |||
| 498 | /* | 477 | /* |
| 499 | * verify the security on a received packet | 478 | * verify the security on a received packet |
| 500 | */ | 479 | */ |
| 501 | static int rxkad_verify_packet(const struct rxrpc_call *call, | 480 | static int rxkad_verify_packet(struct rxrpc_call *call, |
| 502 | struct sk_buff *skb, | 481 | struct sk_buff *skb, |
| 503 | u32 *_abort_code) | 482 | u32 *_abort_code) |
| 504 | { | 483 | { |
| 505 | SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); | 484 | SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); |
| 506 | struct rxrpc_skb_priv *sp; | 485 | struct rxrpc_skb_priv *sp; |
| 507 | struct rxrpc_crypt iv; | 486 | struct rxrpc_crypt iv; |
| 508 | struct scatterlist sg[2]; | 487 | struct scatterlist sg; |
| 509 | struct { | ||
| 510 | __be32 x[2]; | ||
| 511 | } tmpbuf __attribute__((aligned(8))); /* must all be in same page */ | ||
| 512 | u16 cksum; | 488 | u16 cksum; |
| 513 | u32 x, y; | 489 | u32 x, y; |
| 514 | int ret; | 490 | int ret; |
| @@ -533,20 +509,17 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, | |||
| 533 | /* validate the security checksum */ | 509 | /* validate the security checksum */ |
| 534 | x = call->channel << (32 - RXRPC_CIDSHIFT); | 510 | x = call->channel << (32 - RXRPC_CIDSHIFT); |
| 535 | x |= sp->hdr.seq & 0x3fffffff; | 511 | x |= sp->hdr.seq & 0x3fffffff; |
| 536 | tmpbuf.x[0] = htonl(call->call_id); | 512 | call->crypto_buf[0] = htonl(call->call_id); |
| 537 | tmpbuf.x[1] = htonl(x); | 513 | call->crypto_buf[1] = htonl(x); |
| 538 | |||
| 539 | sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); | ||
| 540 | sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); | ||
| 541 | 514 | ||
| 515 | sg_init_one(&sg, call->crypto_buf, 8); | ||
| 542 | skcipher_request_set_tfm(req, call->conn->cipher); | 516 | skcipher_request_set_tfm(req, call->conn->cipher); |
| 543 | skcipher_request_set_callback(req, 0, NULL, NULL); | 517 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 544 | skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); | 518 | skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x); |
| 545 | |||
| 546 | crypto_skcipher_encrypt(req); | 519 | crypto_skcipher_encrypt(req); |
| 547 | skcipher_request_zero(req); | 520 | skcipher_request_zero(req); |
| 548 | 521 | ||
| 549 | y = ntohl(tmpbuf.x[1]); | 522 | y = ntohl(call->crypto_buf[1]); |
| 550 | cksum = (y >> 16) & 0xffff; | 523 | cksum = (y >> 16) & 0xffff; |
| 551 | if (cksum == 0) | 524 | if (cksum == 0) |
| 552 | cksum = 1; /* zero checksums are not permitted */ | 525 | cksum = 1; /* zero checksums are not permitted */ |
| @@ -710,29 +683,6 @@ static void rxkad_calc_response_checksum(struct rxkad_response *response) | |||
| 710 | } | 683 | } |
| 711 | 684 | ||
| 712 | /* | 685 | /* |
| 713 | * load a scatterlist with a potentially split-page buffer | ||
| 714 | */ | ||
| 715 | static void rxkad_sg_set_buf2(struct scatterlist sg[2], | ||
| 716 | void *buf, size_t buflen) | ||
| 717 | { | ||
| 718 | int nsg = 1; | ||
| 719 | |||
| 720 | sg_init_table(sg, 2); | ||
| 721 | |||
| 722 | sg_set_buf(&sg[0], buf, buflen); | ||
| 723 | if (sg[0].offset + buflen > PAGE_SIZE) { | ||
| 724 | /* the buffer was split over two pages */ | ||
| 725 | sg[0].length = PAGE_SIZE - sg[0].offset; | ||
| 726 | sg_set_buf(&sg[1], buf + sg[0].length, buflen - sg[0].length); | ||
| 727 | nsg++; | ||
| 728 | } | ||
| 729 | |||
| 730 | sg_mark_end(&sg[nsg - 1]); | ||
| 731 | |||
| 732 | ASSERTCMP(sg[0].length + sg[1].length, ==, buflen); | ||
| 733 | } | ||
| 734 | |||
| 735 | /* | ||
| 736 | * encrypt the response packet | 686 | * encrypt the response packet |
| 737 | */ | 687 | */ |
| 738 | static void rxkad_encrypt_response(struct rxrpc_connection *conn, | 688 | static void rxkad_encrypt_response(struct rxrpc_connection *conn, |
| @@ -741,17 +691,16 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn, | |||
| 741 | { | 691 | { |
| 742 | SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); | 692 | SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); |
| 743 | struct rxrpc_crypt iv; | 693 | struct rxrpc_crypt iv; |
| 744 | struct scatterlist sg[2]; | 694 | struct scatterlist sg[1]; |
| 745 | 695 | ||
| 746 | /* continue encrypting from where we left off */ | 696 | /* continue encrypting from where we left off */ |
| 747 | memcpy(&iv, s2->session_key, sizeof(iv)); | 697 | memcpy(&iv, s2->session_key, sizeof(iv)); |
| 748 | 698 | ||
| 749 | rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted)); | 699 | sg_init_table(sg, 1); |
| 750 | 700 | sg_set_buf(sg, &resp->encrypted, sizeof(resp->encrypted)); | |
| 751 | skcipher_request_set_tfm(req, conn->cipher); | 701 | skcipher_request_set_tfm(req, conn->cipher); |
| 752 | skcipher_request_set_callback(req, 0, NULL, NULL); | 702 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 753 | skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); | 703 | skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); |
| 754 | |||
| 755 | crypto_skcipher_encrypt(req); | 704 | crypto_skcipher_encrypt(req); |
| 756 | skcipher_request_zero(req); | 705 | skcipher_request_zero(req); |
| 757 | } | 706 | } |
| @@ -818,14 +767,10 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, | |||
| 818 | resp.kvno = htonl(token->kad->kvno); | 767 | resp.kvno = htonl(token->kad->kvno); |
| 819 | resp.ticket_len = htonl(token->kad->ticket_len); | 768 | resp.ticket_len = htonl(token->kad->ticket_len); |
| 820 | 769 | ||
| 821 | resp.encrypted.call_id[0] = | 770 | resp.encrypted.call_id[0] = htonl(conn->channels[0].call_counter); |
| 822 | htonl(conn->channels[0] ? conn->channels[0]->call_id : 0); | 771 | resp.encrypted.call_id[1] = htonl(conn->channels[1].call_counter); |
| 823 | resp.encrypted.call_id[1] = | 772 | resp.encrypted.call_id[2] = htonl(conn->channels[2].call_counter); |
| 824 | htonl(conn->channels[1] ? conn->channels[1]->call_id : 0); | 773 | resp.encrypted.call_id[3] = htonl(conn->channels[3].call_counter); |
| 825 | resp.encrypted.call_id[2] = | ||
| 826 | htonl(conn->channels[2] ? conn->channels[2]->call_id : 0); | ||
| 827 | resp.encrypted.call_id[3] = | ||
| 828 | htonl(conn->channels[3] ? conn->channels[3]->call_id : 0); | ||
| 829 | 774 | ||
| 830 | /* calculate the response checksum and then do the encryption */ | 775 | /* calculate the response checksum and then do the encryption */ |
| 831 | rxkad_calc_response_checksum(&resp); | 776 | rxkad_calc_response_checksum(&resp); |
| @@ -887,10 +832,8 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, | |||
| 887 | } | 832 | } |
| 888 | 833 | ||
| 889 | sg_init_one(&sg[0], ticket, ticket_len); | 834 | sg_init_one(&sg[0], ticket, ticket_len); |
| 890 | |||
| 891 | skcipher_request_set_callback(req, 0, NULL, NULL); | 835 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 892 | skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x); | 836 | skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x); |
| 893 | |||
| 894 | crypto_skcipher_decrypt(req); | 837 | crypto_skcipher_decrypt(req); |
| 895 | skcipher_request_free(req); | 838 | skcipher_request_free(req); |
| 896 | 839 | ||
| @@ -1001,7 +944,7 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, | |||
| 1001 | const struct rxrpc_crypt *session_key) | 944 | const struct rxrpc_crypt *session_key) |
| 1002 | { | 945 | { |
| 1003 | SKCIPHER_REQUEST_ON_STACK(req, rxkad_ci); | 946 | SKCIPHER_REQUEST_ON_STACK(req, rxkad_ci); |
| 1004 | struct scatterlist sg[2]; | 947 | struct scatterlist sg[1]; |
| 1005 | struct rxrpc_crypt iv; | 948 | struct rxrpc_crypt iv; |
| 1006 | 949 | ||
| 1007 | _enter(",,%08x%08x", | 950 | _enter(",,%08x%08x", |
| @@ -1016,12 +959,11 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, | |||
| 1016 | 959 | ||
| 1017 | memcpy(&iv, session_key, sizeof(iv)); | 960 | memcpy(&iv, session_key, sizeof(iv)); |
| 1018 | 961 | ||
| 1019 | rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted)); | 962 | sg_init_table(sg, 1); |
| 1020 | 963 | sg_set_buf(sg, &resp->encrypted, sizeof(resp->encrypted)); | |
| 1021 | skcipher_request_set_tfm(req, rxkad_ci); | 964 | skcipher_request_set_tfm(req, rxkad_ci); |
| 1022 | skcipher_request_set_callback(req, 0, NULL, NULL); | 965 | skcipher_request_set_callback(req, 0, NULL, NULL); |
| 1023 | skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); | 966 | skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); |
| 1024 | |||
| 1025 | crypto_skcipher_decrypt(req); | 967 | crypto_skcipher_decrypt(req); |
| 1026 | skcipher_request_zero(req); | 968 | skcipher_request_zero(req); |
| 1027 | 969 | ||
| @@ -1045,7 +987,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn, | |||
| 1045 | void *ticket; | 987 | void *ticket; |
| 1046 | u32 abort_code, version, kvno, ticket_len, level; | 988 | u32 abort_code, version, kvno, ticket_len, level; |
| 1047 | __be32 csum; | 989 | __be32 csum; |
| 1048 | int ret; | 990 | int ret, i; |
| 1049 | 991 | ||
| 1050 | _enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key)); | 992 | _enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key)); |
| 1051 | 993 | ||
| @@ -1108,11 +1050,26 @@ static int rxkad_verify_response(struct rxrpc_connection *conn, | |||
| 1108 | if (response.encrypted.checksum != csum) | 1050 | if (response.encrypted.checksum != csum) |
| 1109 | goto protocol_error_free; | 1051 | goto protocol_error_free; |
| 1110 | 1052 | ||
| 1111 | if (ntohl(response.encrypted.call_id[0]) > INT_MAX || | 1053 | spin_lock(&conn->channel_lock); |
| 1112 | ntohl(response.encrypted.call_id[1]) > INT_MAX || | 1054 | for (i = 0; i < RXRPC_MAXCALLS; i++) { |
| 1113 | ntohl(response.encrypted.call_id[2]) > INT_MAX || | 1055 | struct rxrpc_call *call; |
| 1114 | ntohl(response.encrypted.call_id[3]) > INT_MAX) | 1056 | u32 call_id = ntohl(response.encrypted.call_id[i]); |
| 1115 | goto protocol_error_free; | 1057 | |
| 1058 | if (call_id > INT_MAX) | ||
| 1059 | goto protocol_error_unlock; | ||
| 1060 | |||
| 1061 | if (call_id < conn->channels[i].call_counter) | ||
| 1062 | goto protocol_error_unlock; | ||
| 1063 | if (call_id > conn->channels[i].call_counter) { | ||
| 1064 | call = rcu_dereference_protected( | ||
| 1065 | conn->channels[i].call, | ||
| 1066 | lockdep_is_held(&conn->channel_lock)); | ||
| 1067 | if (call && call->state < RXRPC_CALL_COMPLETE) | ||
| 1068 | goto protocol_error_unlock; | ||
| 1069 | conn->channels[i].call_counter = call_id; | ||
| 1070 | } | ||
| 1071 | } | ||
| 1072 | spin_unlock(&conn->channel_lock); | ||
| 1116 | 1073 | ||
| 1117 | abort_code = RXKADOUTOFSEQUENCE; | 1074 | abort_code = RXKADOUTOFSEQUENCE; |
| 1118 | if (ntohl(response.encrypted.inc_nonce) != conn->security_nonce + 1) | 1075 | if (ntohl(response.encrypted.inc_nonce) != conn->security_nonce + 1) |
| @@ -1137,6 +1094,8 @@ static int rxkad_verify_response(struct rxrpc_connection *conn, | |||
| 1137 | _leave(" = 0"); | 1094 | _leave(" = 0"); |
| 1138 | return 0; | 1095 | return 0; |
| 1139 | 1096 | ||
| 1097 | protocol_error_unlock: | ||
| 1098 | spin_unlock(&conn->channel_lock); | ||
| 1140 | protocol_error_free: | 1099 | protocol_error_free: |
| 1141 | kfree(ticket); | 1100 | kfree(ticket); |
| 1142 | protocol_error: | 1101 | protocol_error: |
diff --git a/net/rxrpc/utils.c b/net/rxrpc/utils.c index f28122a15a24..b88914d53ca5 100644 --- a/net/rxrpc/utils.c +++ b/net/rxrpc/utils.c | |||
| @@ -10,32 +10,37 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
| 13 | #include <linux/ipv6.h> | ||
| 13 | #include <linux/udp.h> | 14 | #include <linux/udp.h> |
| 14 | #include "ar-internal.h" | 15 | #include "ar-internal.h" |
| 15 | 16 | ||
| 16 | /* | 17 | /* |
| 17 | * Set up an RxRPC address from a socket buffer. | 18 | * Fill out a peer address from a socket buffer containing a packet. |
| 18 | */ | 19 | */ |
| 19 | void rxrpc_get_addr_from_skb(struct rxrpc_local *local, | 20 | int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *srx, struct sk_buff *skb) |
| 20 | const struct sk_buff *skb, | ||
| 21 | struct sockaddr_rxrpc *srx) | ||
| 22 | { | 21 | { |
| 23 | memset(srx, 0, sizeof(*srx)); | 22 | memset(srx, 0, sizeof(*srx)); |
| 24 | srx->transport_type = local->srx.transport_type; | ||
| 25 | srx->transport.family = local->srx.transport.family; | ||
| 26 | 23 | ||
| 27 | /* Can we see an ipv4 UDP packet on an ipv6 UDP socket? and vice | 24 | switch (ntohs(skb->protocol)) { |
| 28 | * versa? | 25 | case ETH_P_IP: |
| 29 | */ | 26 | srx->transport_type = SOCK_DGRAM; |
| 30 | switch (srx->transport.family) { | 27 | srx->transport_len = sizeof(srx->transport.sin); |
| 31 | case AF_INET: | 28 | srx->transport.sin.sin_family = AF_INET; |
| 32 | srx->transport.sin.sin_port = udp_hdr(skb)->source; | 29 | srx->transport.sin.sin_port = udp_hdr(skb)->source; |
| 33 | srx->transport_len = sizeof(struct sockaddr_in); | 30 | srx->transport.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; |
| 34 | memcpy(&srx->transport.sin.sin_addr, &ip_hdr(skb)->saddr, | 31 | return 0; |
| 35 | sizeof(struct in_addr)); | 32 | |
| 36 | break; | 33 | case ETH_P_IPV6: |
| 34 | srx->transport_type = SOCK_DGRAM; | ||
| 35 | srx->transport_len = sizeof(srx->transport.sin6); | ||
| 36 | srx->transport.sin6.sin6_family = AF_INET6; | ||
| 37 | srx->transport.sin6.sin6_port = udp_hdr(skb)->source; | ||
| 38 | srx->transport.sin6.sin6_addr = ipv6_hdr(skb)->saddr; | ||
| 39 | return 0; | ||
| 37 | 40 | ||
| 38 | default: | 41 | default: |
| 39 | BUG(); | 42 | pr_warn_ratelimited("AF_RXRPC: Unknown eth protocol %u\n", |
| 43 | ntohs(skb->protocol)); | ||
| 44 | return -EAFNOSUPPORT; | ||
| 40 | } | 45 | } |
| 41 | } | 46 | } |
