Details
-
Bug
-
Resolution: Fixed
-
Critical
-
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>