From mboxrd@z Thu Jan 1 00:00:00 1970 From: Robin Dong Subject: [PATCH] vfs: check value of varaiable 'nd' before using its member Date: Wed, 4 Jul 2012 17:32:44 +0800 Message-ID: <1341394364-32289-1-git-send-email-robin.k.dong@gmail.com> Cc: Robin Dong To: linux-fsdevel@vger.kernel.org Return-path: Received: from mail-yw0-f46.google.com ([209.85.213.46]:63330 "EHLO mail-yw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753073Ab2GDJcz (ORCPT ); Wed, 4 Jul 2012 05:32:55 -0400 Received: by yhmm54 with SMTP id m54so7023816yhm.19 for ; Wed, 04 Jul 2012 02:32:54 -0700 (PDT) Sender: linux-fsdevel-owner@vger.kernel.org List-ID: From: Robin Dong When we using lookup_one_len() to search pathname component, it will call __lookup_hash() with variable 'nd' as NULL : --> __lookup_hash ( nd = NULL ) --> lookup_dcache --> d_invalidate --> proc_sys_revalidate the proc_sys_revalidate will use 'nd->flags' before check whether its value is NULL. This will cause kernel panic. Therefore, we should adding check-code for filesystems which directly use nd->flags. Signed-off-by: Robin Dong --- fs/9p/vfs_dentry.c | 2 +- fs/afs/dir.c | 2 +- fs/coda/dir.c | 2 +- fs/hfs/sysdep.c | 2 +- fs/ncpfs/dir.c | 2 +- fs/nfs/dir.c | 2 +- fs/proc/proc_sysctl.c | 2 +- fs/sysfs/dir.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index d529437..2785900 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -106,7 +106,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) struct inode *inode; struct v9fs_inode *v9inode; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; inode = dentry->d_inode; diff --git a/fs/afs/dir.c b/fs/afs/dir.c index e22dc4b..93c1bbb 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -607,7 +607,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) void *dir_version; int ret; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; vnode = AFS_FS_I(dentry->d_inode); diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 1775158..804344d 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -541,7 +541,7 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) struct inode *inode; struct coda_inode_info *cii; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; inode = de->d_inode; diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c index 19cf291..1127ea3 100644 --- a/fs/hfs/sysdep.c +++ b/fs/hfs/sysdep.c @@ -18,7 +18,7 @@ static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) struct inode *inode; int diff; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; inode = dentry->d_inode; diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index aeed93a..69d6b55 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -302,7 +302,7 @@ ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd) if (dentry == dentry->d_sb->s_root) return 1; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; parent = dget_parent(dentry); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index f430057..badda4e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1123,7 +1123,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) struct nfs_fattr *fattr = NULL; int error; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; parent = dget_parent(dentry); diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 3476bca..7df97f5 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -796,7 +796,7 @@ static const struct inode_operations proc_sys_dir_operations = { static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd) { - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; return !PROC_I(dentry->d_inode)->sysctl->unregistering; } diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e6bb9b2..9f02776 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -308,7 +308,7 @@ static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd) struct sysfs_dirent *sd; int is_dir; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; sd = dentry->d_fsdata; -- 1.7.3.2