Whamcloud - gitweb
LU-17651 lnet: Fix KASAN use-after-free in lnet_net_remove_cpts 61/57861/7
authorJames Simmons <jsimmons@infradead.org>
Fri, 31 Jan 2025 04:42:32 +0000 (23:42 -0500)
committerOleg Drokin <green@whamcloud.com>
Fri, 7 Feb 2025 03:35:57 +0000 (03:35 +0000)
Allocation of net (struct lnet_net) is done under lnet_dyn_add_ni().
When adding and starting net there is a check if the net is unique
or not. If it is not unique (it is a duplicate or already added before)
the net cleanup is done under lnet_startup_lndnet() and -EEXISTS is
return. This breaks the order of allocation. The allocation order
is struct lnet_ni is part of struct lnet_net. Therefore lnet_net
cannot be deallocated before lnet_ni.

This patch removes lnet_net_free() call only when the net is found
to be duplicate. The cleanup of net (lnet_net_free()) is called
from lnet_dyn_add_ni() where it is actually allocated. This is
locally tested and no KASAN error was reported.

Lustre: DEBUG MARKER: lnetctl net add --net tcp --if ens2
LNet: Added LNI 192.168.205.1@tcp [8/256/0/180]
LNet: Accept secure, port 988
Lustre: DEBUG MARKER: lnetctl net add --net tcp --if ens2
==================================================================
BUG: KASAN: use-after-free in lnet_net_remove_cpts.constprop.0+0x774/0x7f0 [lnet]
Read of size 8 at addr ffff888005be7a50 by task lnetctl/79304

CPU: 1 PID: 79304 Comm: lnetctl Kdump: loaded Tainted: G        W  OE     -------  ---  5.14.0rocky93-debug #4
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-1.fc39 04/01/2014
 Call Trace:
 <TASK>
  ? lnet_net_remove_cpts.constprop.0+0x774/0x7f0 [lnet]
  dump_stack_lvl+0x57/0x7d
  print_address_description.constprop.0+0x1f/0x1e0
  ? lnet_net_remove_cpts.constprop.0+0x774/0x7f0 [lnet]
  print_report.cold+0x55/0x240
  kasan_report+0xc8/0x200
  ? lnet_net_remove_cpts.constprop.0+0x774/0x7f0 [lnet]
  lnet_net_remove_cpts.constprop.0+0x774/0x7f0 [lnet]
  lnet_ni_free+0x6a/0x620 [lnet]
  lnet_dyn_add_ni+0x29d/0x370 [lnet]

Test-Parameters: trivial testlist=sanity-lnet
Change-Id: I2c751a1bfeb583b86d9b68241607cf90c69f4277
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/57861
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Arshad Hussain <arshad.hussain@aeoncomputing.com>
Reviewed-by: Frank Sehr <fsehr@whamcloud.com>
Reviewed-by: Chris Horn <chris.horn@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lnet/lnet/api-ni.c

index 0335632..19f191b 100644 (file)
@@ -2700,7 +2700,11 @@ lnet_startup_lndnet(struct lnet_net *net, struct lnet_lnd_tunables *tun)
                    !lnet_ni_unique_net(&net_l->net_ni_list,
                                        ni->ni_interface)) {
                        rc = -EEXIST;
-                       goto failed1;
+                       /* In case of not unique net. Simply return with
+                        * errno code and the cleanup will happen under
+                        * lnet_dyn_add_ni()
+                        */
+                       return rc;
                }
 
                /* adjust the pointer the parent network, just in case it
@@ -3777,8 +3781,10 @@ int lnet_dyn_add_ni(struct lnet_ioctl_config_ni *conf, u32 net_id,
        mutex_unlock(&the_lnet.ln_api_mutex);
 
        /* If NI already exist delete this new unused copy */
-       if (rc == -EEXIST)
+       if (rc == -EEXIST) {
                lnet_ni_free(ni);
+               lnet_net_free(net);
+       }
 
        return rc;
 }