Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-16024

crash due to invalid cred->group_info address in cred_fscmp on 5.14.0-378.el9

    • kernel-5.14.0-410.el9
    • Normal
    • ZStream
    • sst_filesystems
    • ssg_filesystems_storage_and_HA
    • 21
    • 23
    • 5
    • QE ack, Dev ack
    • False
    • Hide

      None

      Show
      None
    • Red Hat Enterprise Linux
    • Approved Blocker

      What were you trying to do that didn't work?

      System crashed with an invalid address for a cred->group_info in cred_fscmp:

      [363434.546053] general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6b6f: 0000 [#1] PREEMPT SMP PTI
      [363434.547463] CPU: 39 PID: 564685 Comm: ifind Kdump: loaded Not tainted 5.14.0-378.el9.x86_64 #1
      [363434.548736] Hardware name: HP ProLiant DL380 Gen9/ProLiant DL380 Gen9, BIOS P89 07/18/2022
      [363434.550031] RIP: 0010:cred_fscmp+0x53/0xa0
      
      PID: 564685   TASK: ffff8a3016c2d8c0  CPU: 39   COMMAND: "ifind"
          [exception RIP: cred_fscmp+0x53]
       #6 [ffffa8548626bae0] nfs_access_get_cached at ffffffffc172f198 [nfs]
       #7 [ffffa8548626bb30] nfs_do_access at ffffffffc172fedf [nfs]
       #8 [ffffa8548626bbc8] nfs_permission at ffffffffc17301f3 [nfs]
       #9 [ffffa8548626bbf0] inode_permission at ffffffffa3e32410
      #10 [ffffa8548626bc20] link_path_walk at ffffffffa3e37426
      #11 [ffffa8548626bc80] path_lookupat at ffffffffa3e37b0e
      #12 [ffffa8548626bcb8] filename_lookup at ffffffffa3e38f2f
      #13 [ffffa8548626bdd8] vfs_statx at ffffffffa3e2ad9d
      #14 [ffffa8548626be30] vfs_fstatat at ffffffffa3e2b1b4
      #15 [ffffa8548626be58] __do_sys_newlstat at ffffffffa3e2b523 

      the crashing instruction:

      0xffffffffa3b3b4e3 <cred_fscmp+0x53>:   movslq 0x4(%rdx),%rsi
          RDX: 6b6b6b6b6b6b6b6b  RSI: ffff8ab810ba19c0  RDI: ffff8a25a2c5b940 

      more analysis below

      Please provide the package NVR for which bug is seen:

      internal kernel-5.14.0-378.el9.x86_64

      How reproducible:

      unknown, crash experienced once thus far

      Steps to reproduce

      unknown

      Expected results

      no  crash

      Actual results

      the crashing instruction:

       0xffffffffa3b3b4e3 <cred_fscmp+0x53>:   movslq 0x4(%rdx),%rsi
          RDX: 6b6b6b6b6b6b6b6b  RSI: ffff8ab810ba19c0  RDI: ffff8a25a2c5b940  

      where %rdx contains a struct group_info, and came from %rdi+0x98 (cred->group_info) slightly earlier:

      0xffffffffa3b3b4c6 <cred_fscmp+0x36>:   mov    0x98(%rdi),%rdx
      0xffffffffa3b3b4cd <cred_fscmp+0x3d>:   mov    0x98(%rsi),%rcx
      0xffffffffa3b3b4d4 <cred_fscmp+0x44>:   cmp    %rcx,%rdx
      0xffffffffa3b3b4d7 <cred_fscmp+0x47>:   je     0xffffffffa3b3b529 <cred_fscmp+0x99>
      0xffffffffa3b3b4d9 <cred_fscmp+0x49>:   test   %rdx,%rdx
      0xffffffffa3b3b4dc <cred_fscmp+0x4c>:   je     0xffffffffa3b3b515 <cred_fscmp+0x85>
      0xffffffffa3b3b4de <cred_fscmp+0x4e>:   test   %rcx,%rcx
      0xffffffffa3b3b4e1 <cred_fscmp+0x51>:   je     0xffffffffa3b3b524 <cred_fscmp+0x94>
      0xffffffffa3b3b4e3 <cred_fscmp+0x53>:   movslq 0x4(%rdx),%rsi 

      however %rdi+0x98 contains a different (and expected) value:

      crash> cred.group_info ffff8a25a2c5b940
        group_info = 0xffffffffa565ed90 <init_groups>, 

      so %rdx should not have the bogus value

      626 int cred_fscmp(const struct cred *a, const struct cred *b)
      627 {
      628         struct group_info *ga, *gb;
      629         int g;
      630 
      631         if (a == b)
      632                 return 0;
      633         if (uid_lt(a->fsuid, b->fsuid))
      634                 return -1;
      635         if (uid_gt(a->fsuid, b->fsuid))
      636                 return 1;
      637 
      638         if (gid_lt(a->fsgid, b->fsgid))
      639                 return -1;
      640         if (gid_gt(a->fsgid, b->fsgid))
      641                 return 1;
      642 
      643         ga = a->group_info;
      644         gb = b->group_info;
      645         if (ga == gb)
      646                 return 0;
      647         if (ga == NULL)
      648                 return -1;
      649         if (gb == NULL)
      650                 return 1;
      651         if (ga->ngroups < gb->ngroups) <<<< 

      called from the following:

       3054 int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
      3055                           u32 *mask, bool may_block)
      3056 {
      3057         int status;
      3058 
      3059         status = nfs_access_get_cached_rcu(inode, cred, mask);
        3022 static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, u32 *mask)
        3023 {
        3024         /* Only check the most recently returned cache entry,
        3025          * but do it without locking.
        3026          */
        3027         struct nfs_inode *nfsi = NFS_I(inode);
        3028         u64 login_time = nfs_access_login_time(current, cred);
          2956 static u64 nfs_access_login_time(const struct task_struct *task,
          2957                                  const struct cred *cred)
          2958 {
          2959         const struct task_struct *parent;
          2960         const struct cred *pcred;
          2961         u64 ret;
          2962 
          2963         rcu_read_lock();
          2964         for (;;) {
          2965                 parent = rcu_dereference(task->real_parent);
          2966                 pcred = rcu_dereference(parent->cred);
          2967                 if (parent == task || cred_fscmp(pcred, cred) != 0)
      

            rhn-support-smayhew Scott Mayhew
            rhn-support-fsorenso Frank Sorenson
            Scott Mayhew Scott Mayhew
            Zhi Li Zhi Li
            Votes:
            0 Vote for this issue
            Watchers:
            11 Start watching this issue

              Created:
              Updated:
              Resolved: