Fix kernel NULL pointer dereference by dlm_astd
PATCH 1/1 Fix kernel NULL pointer dereference by dlm_astd
Hi,
This patch replaces the one I previously posted here.
Regards,
Bob Peterson
Red Hat File Systems
--
commit 77ac19b0f0061396d0dc15f705ac4e0a574bd614
Author: Bob Peterson <[email protected]> Date: Thu Jun 17 15:38:32 2010 -0500
GFS2: Fix kernel NULL pointer dereference by dlm_astd
This patch fixes a problem in an error path when looking up dinodes. There are two sister-functions, gfs2_inode_lookup and gfs2_process_unlinked_inode. Both functions acquire and hold the i_iopen glock for the dinode being looked up. The last thing they try to do is hold the i_gl glock for the dinode. If that glock fails for some reason, the error path was incorrectly calling gfs2_glock_put for the i_iopen glock twice. This resulted in the glock being prematurely freed. The "minimum hold time" usually kept the glock in memory, but the lock interface to dlm (aka lock_dlm) freed its memory for the glock. In some circumstances, it would cause dlm's dlm_astd daemon to try to call the bast function for the freed lock_dlm memory, which resulted in a NULL pointer dereference.
rhbz#604244
fs/gfs2/inode.c +8 -4
@@ -171,7 +171,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, {struct inode *inode;struct gfs2_inode *ip; -struct gfs2_glock *io_gl; +struct gfs2_glock *io_gl =NULL ;int error; inode =gfs2_iget (sb, no_addr);
@@ -200,6 +200,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, ip->i_iopen_gh.gh_gl->gl_object = ip;gfs2_glock_put (io_gl); + io_gl =NULL ;if ((type ==DT_UNKNOWN ) && (no_formal_ino ==0 )) goto gfs2_nfsbypass;
@@ -230,7 +231,8 @@ gfs2_nfsbypass: fail_glock:gfs2_glock_dq (&ip->i_iopen_gh); fail_iopen: -gfs2_glock_put (io_gl); +if (io_gl) +gfs2_glock_put (io_gl); fail_put:if (inode->i_state &I_NEW ) ip->i_gl->gl_object =NULL ;
@@ -258,7 +260,7 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) {struct gfs2_sbd *sdp;struct gfs2_inode *ip; -struct gfs2_glock *io_gl; +struct gfs2_glock *io_gl =NULL ;int error;struct gfs2_holder gh;struct inode *inode;
@@ -295,6 +297,7 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) ip->i_iopen_gh.gh_gl->gl_object = ip;gfs2_glock_put (io_gl); + io_gl =NULL ; inode->i_mode =DT2IF (DT_UNKNOWN );
@@ -321,7 +324,8 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) fail_glock:gfs2_glock_dq (&ip->i_iopen_gh); fail_iopen: -gfs2_glock_put (io_gl); +if (io_gl) +gfs2_glock_put (io_gl); fail_put: ip->i_gl->gl_object =NULL ;gfs2_glock_put (ip->i_gl);
PATCH 1/1 Fix kernel NULL pointer dereference by dlm_astd
Hi,
This really is in the -nmw tree this time. Sorry for the earlier confusion. Thanks,
Steve.
Quoted 90 lines · Bob Peterson
Hi,
This patch replaces the one I previously posted here.
Regards,
Bob Peterson
Red Hat File Systems
--
commit77ac19b0f0061396d0dc15f705ac4e0a574bd614Author: Bob Peterson <[email protected]> Date: Thu Jun 17 15:38:32 2010 -0500GFS2: Fix kernel NULL pointer dereference by
dlm_astdThis patch fixes a problem in an error path when looking up dinodes. There are two sister-functions,
gfs2_inode_lookupandgfs2_process_unlinked_inode. Both functions acquire and hold thei_iopenglock for the dinode being looked up. The last thing they try to do is hold thei_glglock for the dinode. If that glock fails for some reason, the error path was incorrectly callinggfs2_glock_putfor thei_iopenglock twice. This resulted in the glock being prematurely freed. The "minimum hold time" usually kept the glock in memory, but the lock interface to dlm (akalock_dlm) freed its memory for the glock. In some circumstances, it would cause dlm'sdlm_astddaemon to try to call the bast function for the freedlock_dlmmemory, which resulted in a NULL pointer dereference.rhbz#604244
fs/gfs2/inode.c +8
-4@@ -171,7 +171,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, {struct inode *inode;struct gfs2_inode *ip; -struct gfs2_glock *io_gl; +struct gfs2_glock *io_gl =NULL ;int error; inode =gfs2_iget (sb, no_addr);@@ -200,6 +200,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, ip->i_iopen_gh.gh_gl->gl_object = ip;gfs2_glock_put (io_gl); + io_gl =NULL ;if ((type ==DT_UNKNOWN ) && (no_formal_ino ==0 )) goto gfs2_nfsbypass;@@ -230,7 +231,8 @@ gfs2_nfsbypass: fail_glock:gfs2_glock_dq (&ip->i_iopen_gh); fail_iopen: -gfs2_glock_put (io_gl); +if (io_gl) +gfs2_glock_put (io_gl); fail_put:if (inode->i_state &I_NEW ) ip->i_gl->gl_object =NULL ;@@ -258,7 +260,7 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) {struct gfs2_sbd *sdp;struct gfs2_inode *ip; -struct gfs2_glock *io_gl; +struct gfs2_glock *io_gl =NULL ;int error;struct gfs2_holder gh;struct inode *inode;@@ -295,6 +297,7 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) ip->i_iopen_gh.gh_gl->gl_object = ip;gfs2_glock_put (io_gl); + io_gl =NULL ; inode->i_mode =DT2IF (DT_UNKNOWN );@@ -321,7 +324,8 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) fail_glock:gfs2_glock_dq (&ip->i_iopen_gh); fail_iopen: -gfs2_glock_put (io_gl); +if (io_gl) +gfs2_glock_put (io_gl); fail_put: ip->i_gl->gl_object =NULL ;gfs2_glock_put (ip->i_gl);