Skip to content
  • Alexey Dobriyan's avatar
    proc: fix NULL ->i_fop oops · c2319540
    Alexey Dobriyan authored
    proc_kill_inodes() can clear ->i_fop in the middle of vfs_readdir resulting in
    NULL dereference during "file->f_op->readdir(file, buf, filler)".
    
    The solution is to remove proc_kill_inodes() completely:
    
    a) we don't have tricky modules implementing their tricky readdir hooks which
       could keeping this revoke from hell.
    
    b) In a situation when module is gone but PDE still alive, standard
       readdir will return only "." and "..", because pde->next was cleared by
       remove_proc_entry().
    
    c) the race proc_kill_inode() destined to prevent is not completely
       fixed, just race window made smaller, because vfs_readdir() is run
       without sb_lock held and without file_list_lock held.  Effectively,
       ->i_fop is cleared at random moment, which can't fix properly anything.
    
    BUG: unable to handle kernel NULL pointer dereference at virtual address 00000018
    printing eip: c1061205 *pdpt = 0000000005b22001 *pde = 0000000000000000
    Oops: 0000 [#1] PREEMPT SMP
    Modules linked in: foo af_packet ipv6 cpufreq_ondemand loop serio_raw sr_mod k8temp cdrom hwmon amd_rng
    Pid: 2033, comm: find Not tainted (2.6.24-rc1-b1d08ac0
    
     #2)
    EIP: 0060:[<c1061205>] EFLAGS: 00010246 CPU: 0
    EIP is at vfs_readdir+0x47/0x74
    EAX: c6b6a780 EBX: 00000000 ECX: c1061040 EDX: c5decf94
    ESI: c6b6a780 EDI: fffffffe EBP: c9797c54 ESP: c5decf78
     DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
    Process find (pid: 2033, ti=c5dec000 task=c64bba90 task.ti=c5dec000)
    Stack: c5decf94 c1061040 fffffff7 0805ffbc 00000000 c6b6a780 c1061295 0805ffbc
           00000000 00000400 00000000 00000004 0805ffbc 4588eff4 c5dec000 c10026ba
           00000004 0805ffbc 00000400 0805ffbc 4588eff4 bfdc6c70 000000dc 0000007b
    Call Trace:
     [<c1061040>] filldir64+0x0/0xc5
     [<c1061295>] sys_getdents64+0x63/0xa5
     [<c10026ba>] sysenter_past_esp+0x5f/0x85
     =======================
    Code: 49 83 78 18 00 74 43 8d 6b 74 bf fe ff ff ff 89 e8 e8 b8 c0 12 00 f6 83 2c 01 00 00 10 75 22 8b 5e 10 8b 4c 24 04 89 f0 8b 14 24 <ff> 53 18 f6 46 1a 04 89 c7 75 0b 8b 56 0c 8b 46 08 e8 c8 66 00
    EIP: [<c1061205>] vfs_readdir+0x47/0x74 SS:ESP 0068:c5decf78
    
    hch: "Nice, getting rid of this is a very good step formwards.
          Unfortunately we have another copy of this junk in
          security/selinux/selinuxfs.c:sel_remove_entries() which would need the
          same treatment."
    
    Signed-off-by: default avatarAlexey Dobriyan <adobriyan@sw.ru>
    Acked-by: default avatarChristoph Hellwig <hch@infradead.org>
    Cc: Al Viro <viro@zeniv.linux.org.uk>
    Cc: Stephen Smalley <sds@tycho.nsa.gov>
    Cc: James Morris <jmorris@namei.org>
    Cc: "Eric W. Biederman" <ebiederm@xmission.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    c2319540