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

usercopy exposure attempt detected in LL_IOC_LOV_GETSTRIPE ioctl

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • Critical
    • Lustre 2.14.0, Lustre 2.12.5
    • Upstream
    • None
    • CentOS 7.6.1810, starting with kernel 3.10.0-957
    • 3
    • 9223372036854775807

    Description

      Software like darshan are still using the old `ioctl` way to gather striping info for a file.

      The kernel BUG is easily triggered on a not-PFL striped file, using:

      lum->lmm_magic = LOV_USER_MAGIC;
      lum->lmm_stripe_count = LOV_MAX_STRIPE_COUNT;
      

      Any `lmm_stripe_count` greater than the actual file's stripe count will trigger the bug.

      Kernel side the issue appears to be in `lov_getstripe`: with a positive `lum_size`(line 409), `lmm_size` is set as `lum_size`(line 442) even if `lmm_magic != LOV_MAGIC_COMP_V1`(line 414), while instead the structure is just as big as `lmmk_size`:

      404         if (lum.lmm_magic == LOV_USER_MAGIC_V1 ||
      405             lum.lmm_magic == LOV_USER_MAGIC_V3)
      406                 lum_size = lov_user_md_size(lum.lmm_stripe_count,
      407                                             lum.lmm_magic);
      408 
      409         if (lum_size != 0) {
      410                 struct lov_mds_md *comp_md = lmmk;
      411 
      412                 /* Legacy app (ADIO for instance) treats the layout as V1/V3
      413                  * blindly, we'd return a reasonable V1/V3 for them. */
      414                 if (lmmk->lmm_magic == LOV_MAGIC_COMP_V1) {
      [...]
      439                 }
      440 
      441                 lmm = comp_md;
      442                 lmm_size = lum_size;
      443         } else {
      444                 lmm = lmmk;
      445                 lmm_size = lmmk_size;
      446         }
      447         /**
      448          * User specified limited buffer size, usually the buffer is
      449          * from ll_lov_setstripe(), and the buffer can only hold basic
      450          * layout template info.
      451          */
      452         if (size == 0 || size > lmm_size)
      453                 size = lmm_size;
      454         if (copy_to_user(lump, lmm, size))
      455                 GOTO(out_free, rc = -EFAULT);
      

      Please find as attachment the kernel trace and a reproducer, to be invoked as:

      $ gcc reproducer.c -o reproducer -W -Wall --pedantic
      $ ./reproducer <file_path>
      

      Attachments

        1. kernel_trace.txt
          4 kB
          Marco Grossi
        2. reproducer.c
          1 kB
          Marco Grossi

        Issue Links

          Activity

            People

              mgrossi Marco Grossi (Inactive)
              mgrossi Marco Grossi (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: