Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 218527fe27ad ("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>

authored by

Tung Nguyen and committed by
Jakub Kicinski
3aa67762 4cfe066a

+4 -2
+4 -2
net/tipc/name_table.c
··· 348 348 349 349 /* Return if the publication already exists */ 350 350 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)) { 352 353 pr_debug("Failed to bind duplicate %u,%u,%u/%u:%u/%u\n", 353 354 p->sr.type, p->sr.lower, p->sr.upper, 354 355 node, p->sk.ref, key); ··· 389 388 u32 node = sk->node; 390 389 391 390 list_for_each_entry(p, &r->all_publ, all_publ) { 392 - if (p->key != key || (node && node != p->sk.node)) 391 + if (p->key != key || p->sk.ref != sk->ref || 392 + (node && node != p->sk.node)) 393 393 continue; 394 394 list_del(&p->all_publ); 395 395 list_del(&p->local_publ);