Skip to content

Commit 3aa6776

Browse files
Tung Nguyenkuba-moo
authored andcommitted
tipc: fix duplicate publication key in tipc_service_insert_publ()
TIPC uses named table to store TIPC services represented by type and instance. Each time an application calls TIPC API bind() to bind a type/instance to a socket, an entry is created and inserted into the named table. It looks like this: named table: key1, entry1 (type, instance ...) key2, entry2 (type, instance ...) In the above table, each entry represents a route for sending data from one socket to the other. For all publications originated from the same node, the key is UNIQUE to identify each entry. It is calculated by this formula: key = socket portid + number of bindings + 1 (1) where: - socket portid: unique and calculated by using linux kernel function get_random_u32_below(). So, the value is randomized. - number of bindings: the number of times a type/instance pair is bound to a socket. This number is linearly increased, starting from 0. While the socket portid is unique and randomized by linux kernel, the linear increment of "number of bindings" in formula (1) makes "key" not unique anymore. For example: - Socket 1 is created with its associated port number 20062001. Type 1000, instance 1 is bound to socket 1: key1: 20062001 + 0 + 1 = 20062002 Then, bind() is called a second time on Socket 1 to by the same type 1000, instance 1: key2: 20062001 + 1 + 1 = 20062003 Named table: key1 (20062002), entry1 (1000, 1 ...) key2 (20062003), entry2 (1000, 1 ...) - Socket 2 is created with its associated port number 20062002. Type 1000, instance 1 is bound to socket 2: key3: 20062002 + 0 + 1 = 20062003 TIPC looks up the named table and finds out that key2 with the same value already exists and rejects the insertion into the named table. This leads to failure of bind() call from application on Socket 2 with error message EINVAL "Invalid argument". This commit fixes this issue by adding more port id checking to make sure that the key is unique to publications originated from the same port id and node. Fixes: 218527f ("tipc: replace name table service range array with rb tree") Signed-off-by: Tung Nguyen <tung.quang.nguyen@est.tech> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260220050541.237962-1-tung.quang.nguyen@est.tech Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 4cfe066 commit 3aa6776

1 file changed

Lines changed: 4 additions & 2 deletions

File tree

net/tipc/name_table.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ static bool tipc_service_insert_publ(struct net *net,
348348

349349
/* Return if the publication already exists */
350350
list_for_each_entry(_p, &sr->all_publ, all_publ) {
351-
if (_p->key == key && (!_p->sk.node || _p->sk.node == node)) {
351+
if (_p->key == key && _p->sk.ref == p->sk.ref &&
352+
(!_p->sk.node || _p->sk.node == node)) {
352353
pr_debug("Failed to bind duplicate %u,%u,%u/%u:%u/%u\n",
353354
p->sr.type, p->sr.lower, p->sr.upper,
354355
node, p->sk.ref, key);
@@ -388,7 +389,8 @@ static struct publication *tipc_service_remove_publ(struct service_range *r,
388389
u32 node = sk->node;
389390

390391
list_for_each_entry(p, &r->all_publ, all_publ) {
391-
if (p->key != key || (node && node != p->sk.node))
392+
if (p->key != key || p->sk.ref != sk->ref ||
393+
(node && node != p->sk.node))
392394
continue;
393395
list_del(&p->all_publ);
394396
list_del(&p->local_publ);

0 commit comments

Comments
 (0)