Uploaded image for project: 'Lustre'
  1. Lustre
  2. LU-21118

osd-ldiskfs: MDS LBUG in osd_olc_save() for names longer than NAME_MAX

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • Lustre 2.18.0
    • None
    • ldiskfs MDT; clients without LU-18783 on RHEL 10 kernels (e.g. 6.12.0-124.27.1.el10_1)
    • 3
    • 9223372036854775807

      An ldiskfs MDT LBUGs when a client sends a directory entry name longer than 256 bytes in a request that looks the name up before mdd_name_check() runs, e.g. rename or open-by-name:

      LustreError: 4212:0:(osd_handler.c:8127:osd_olc_save()) ASSERTION( ln->ln_namelen <= 255 + 1 ) failed:
      LustreError: 4212:0:(osd_handler.c:8127:osd_olc_save()) LBUG
      CPU: 17 PID: 4212 Comm: mdt_io02_002 Kdump: loaded Tainted: G           OE     -------- -  - 4.18.0-553.117.1+2.1.el8_10_ciq.x86_64 #1
      Call Trace:
       dump_stack+0x41/0x60
       lbug_with_loc.cold.8+0x5/0x43 [libcfs]
       osd_index_ea_lookup+0x6f8/0x770 [osd_ldiskfs]
       __mdd_lookup.isra.21+0x286/0x370 [mdd]
       mdd_lookup+0x10d/0x150 [mdd]
       mdt_lookup_version_check+0x59/0x2e0 [mdt]
       mdt_reint_rename+0x99b/0x1e30 [mdt]
       mdt_reint_rec+0x127/0x260 [mdt]
       mdt_reint_internal+0x4ac/0x7a0 [mdt]
       mdt_reint+0x5e/0x100 [mdt]
       tgt_request_handle+0xc0a/0x1b50 [ptlrpc]
       ptlrpc_server_handle_request+0x25a/0xca0 [ptlrpc]
       ptlrpc_main+0xb45/0x13a0 [ptlrpc]
       kthread+0x134/0x150
       ret_from_fork+0x1f/0x40
      

      The MDT never limits the name length before the OSD lookup:

      • mdt_name_unpack() / lu_name_is_valid() only check that the name is non-empty, NUL terminated and contains no '/'; there is no upper bound.
      • mdt_reint_rename() looks up rr_name and rr_tgt_name via mdt_lookup_version_check() straight away, and mdt_reint_open() calls mdo_lookup() before creating. The ENAMETOOLONG check in mdd_name_check() only runs later (and is skipped for encrypted parents).
      • osd_index_ea_lookup() always calls osd_olc_save(), even when the lookup itself fails, and osd_olc_save() asserts ln_namelen <= LDISKFS_NAME_LEN + 1 before copying into the fixed-size lce_name[] cache slot.

      So any client that does not check the length itself can LBUG the MDS with a single rename(2). This is the ldiskfs counterpart of LU-21031 (osd-zfs accepting such names on insert).

      How such names reach the MDS in practice: clients without LU-18783 (e.g. 2.14/2.15/2.16-based) only check d_name.len > ll_namelen in ll_lookup_it(). ll_lookup_nd() skips ll_lookup_it() for (LOOKUP_CREATE && !LOOKUP_OPEN) (LU-4185). Since Linux commit 204a575e91f3 ("VFS: add common error checks to lookup_one_qstr_excl()"), backported to RHEL 10 (kernel-6.12.0-91.el10 and later, so all EL10.1 6.12.0-124.*.el10_1 kernels), do_renameat2() looks up the rename target with LOOKUP_RENAME_TARGET | LOOKUP_CREATE. So on EL10 clients the rename target length is never checked and the name is sent to the MDT. EL8/EL9 and upstream v6.12 pass only LOOKUP_RENAME_TARGET and are not affected. In our case the clients were 6.12.0-124.27.1.el10_1 with a 2.14.0-based client that lacks LU-18783.

      LU-18783 closes the hole on the client side, but the MDS must not depend on every client checking the length. LU-15928 (passing keylen through dt_lookup()) does not cover this case, since rename names are already NUL terminated and strlen() == ln_namelen.

      Proposed fix: osd_index_ea_lookup() refuses names longer than LDISKFS_NAME_LEN with -ENAMETOOLONG, after any critical-decoding of an encrypted name and before the lookup cache is touched.

      Reproducer (expected, not yet run on master): ldiskfs MDT on master, a client without LU-18783 on a RHEL 10 kernel, then

      touch /mnt/lustre/f
      mv /mnt/lustre/f /mnt/lustre/$(printf 'z%.0s' {1..256})
      

            wc-triage WC Triage
            jinshanx Jinshan Xiong
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: