]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
tipc: fix unique bearer names sanity check
authorHoang Le <hoang.h.le@dektech.com.au>
Thu, 1 Apr 2021 02:30:48 +0000 (09:30 +0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Jun 2021 11:24:05 +0000 (13:24 +0200)
[ Upstream commit f20a46c3044c3f75232b3d0e2d09af9b25efaf45 ]

When enabling a bearer by name, we don't sanity check its name with
higher slot in bearer list. This may have the effect that the name
of an already enabled bearer bypasses the check.

To fix the above issue, we just perform an extra checking with all
existing bearers.

Fixes: cb30a63384bc9 ("tipc: refactor function tipc_enable_bearer()")
Cc: stable@vger.kernel.org
Acked-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: Hoang Le <hoang.h.le@dektech.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/tipc/bearer.c

index 8ab17f0da0268cee160919e046e5b574d3766d77..e1006ed4d90ab93c4ae487749a05c9aa0a6a0c39 100644 (file)
@@ -243,6 +243,7 @@ static int tipc_enable_bearer(struct net *net, const char *name,
        int bearer_id = 0;
        int res = -EINVAL;
        char *errstr = "";
+       u32 i;
 
        if (!bearer_name_validate(name, &b_names)) {
                errstr = "illegal name";
@@ -267,31 +268,38 @@ static int tipc_enable_bearer(struct net *net, const char *name,
                prio = m->priority;
 
        /* Check new bearer vs existing ones and find free bearer id if any */
-       while (bearer_id < MAX_BEARERS) {
-               b = rtnl_dereference(tn->bearer_list[bearer_id]);
-               if (!b)
-                       break;
+       bearer_id = MAX_BEARERS;
+       i = MAX_BEARERS;
+       while (i-- != 0) {
+               b = rtnl_dereference(tn->bearer_list[i]);
+               if (!b) {
+                       bearer_id = i;
+                       continue;
+               }
                if (!strcmp(name, b->name)) {
                        errstr = "already enabled";
                        NL_SET_ERR_MSG(extack, "Already enabled");
                        goto rejected;
                }
-               bearer_id++;
-               if (b->priority != prio)
-                       continue;
-               if (++with_this_prio <= 2)
-                       continue;
-               pr_warn("Bearer <%s>: already 2 bearers with priority %u\n",
-                       name, prio);
-               if (prio == TIPC_MIN_LINK_PRI) {
-                       errstr = "cannot adjust to lower";
-                       NL_SET_ERR_MSG(extack, "Cannot adjust to lower");
-                       goto rejected;
+
+               if (b->priority == prio &&
+                   (++with_this_prio > 2)) {
+                       pr_warn("Bearer <%s>: already 2 bearers with priority %u\n",
+                               name, prio);
+
+                       if (prio == TIPC_MIN_LINK_PRI) {
+                               errstr = "cannot adjust to lower";
+                               NL_SET_ERR_MSG(extack, "Cannot adjust to lower");
+                               goto rejected;
+                       }
+
+                       pr_warn("Bearer <%s>: trying with adjusted priority\n",
+                               name);
+                       prio--;
+                       bearer_id = MAX_BEARERS;
+                       i = MAX_BEARERS;
+                       with_this_prio = 1;
                }
-               pr_warn("Bearer <%s>: trying with adjusted priority\n", name);
-               prio--;
-               bearer_id = 0;
-               with_this_prio = 1;
        }
 
        if (bearer_id >= MAX_BEARERS) {