Skip to content

Commit fd6edc5

Browse files
raven-aualoktiwa
authored andcommitted
vfs: check dentry is still valid in get_link()
When following a trailing symlink in rcu-walk mode it's possible for the dentry to become invalid between the last dentry seq lock check and getting the link (eg. an unlink) leading to a backtrace similar to this: crash> bt PID: 10964 TASK: ffff951c8aa92f80 CPU: 3 COMMAND: "TaniumCX" … #7 [ffffae44d0a6fbe0] page_fault at ffffffff8d6010fe [exception RIP: unknown or invalid address] RIP: 0000000000000000 RSP: ffffae44d0a6fc90 RFLAGS: 00010246 RAX: ffffffff8da3cc80 RBX: ffffae44d0a6fd30 RCX: 0000000000000000 RDX: ffffae44d0a6fd98 RSI: ffff951aa9af3008 RDI: 0000000000000000 RBP: 0000000000000000 R8: ffffae44d0a6fb94 R9: 0000000000000000 R10: ffff951c95d8c318 R11: 0000000000080000 R12: ffffae44d0a6fd98 R13: ffff951aa9af3008 R14: ffff951c8c9eb840 R15: 0000000000000000 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #8 [ffffae44d0a6fc90] trailing_symlink at ffffffff8cf24e61 #9 [ffffae44d0a6fcc8] path_lookupat at ffffffff8cf261d1 Most of the time this is not a problem because the inode is unchanged while the rcu read lock is held. But xfs can re-use inodes which can result in the inode ->get_link() method becoming invalid (or NULL). This case needs to be checked for in fs/namei.c:get_link() and if detected the walk re-started. Signed-off-by: Ian Kent <[email protected]> Orabug: 37536393 This is the backport of an upstream patch, yet to be merged: https://lore.kernel.org/lkml/[email protected] One of our customers found a similar issue on uek5 in bug 37322383. Investigation of vmcore revealed that the dentry became invalid between the last dentry seq lock check and getting the link. The customer has tested this patch and verified that this patch avoids the crash. We want to merge this patch to uek6 only for now as this is not yet in upstream. Signed-off-by: Srikanth C S <[email protected]> Signed-off-by: Gautham Ananthakrishna <[email protected]> Reviewed-by: Mark Tinguely <[email protected]> Signed-off-by: Alok Tiwari <[email protected]>
1 parent dfcbc82 commit fd6edc5

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

fs/namei.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,8 +1150,11 @@ const char *get_link(struct nameidata *nd)
11501150
if (!res) {
11511151
const char * (*get)(struct dentry *, struct inode *,
11521152
struct delayed_call *);
1153-
get = inode->i_op->get_link;
1153+
get = READ_ONCE(inode->i_op->get_link);
11541154
if (nd->flags & LOOKUP_RCU) {
1155+
/* Does the inode still match the associated dentry? */
1156+
if (unlikely(read_seqcount_retry(&dentry->d_seq, last->seq)))
1157+
return ERR_PTR(-ECHILD);
11551158
res = get(NULL, inode, &last->done);
11561159
if (res == ERR_PTR(-ECHILD)) {
11571160
if (unlikely(unlazy_walk(nd)))

0 commit comments

Comments
 (0)