Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kernfs: fix ino wrap-around detection

When the 32bit ino wraps around, kernfs increments the generation
number to distinguish reused ino instances. The wrap-around detection
tests whether the allocated ino is lower than what the cursor but the
cursor is pointing to the next ino to allocate so the condition never
triggers.

Fix it by remembering the last ino and comparing against that.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: 4a3ef68acacf ("kernfs: implement i_generation")
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: stable@vger.kernel.org # v4.14+

+3 -3
+2 -3
fs/kernfs/dir.c
··· 622 622 { 623 623 struct kernfs_node *kn; 624 624 u32 gen; 625 - int cursor; 626 625 int ret; 627 626 628 627 name = kstrdup_const(name, GFP_KERNEL); ··· 634 635 635 636 idr_preload(GFP_KERNEL); 636 637 spin_lock(&kernfs_idr_lock); 637 - cursor = idr_get_cursor(&root->ino_idr); 638 638 ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC); 639 - if (ret >= 0 && ret < cursor) 639 + if (ret >= 0 && ret < root->last_ino) 640 640 root->next_generation++; 641 641 gen = root->next_generation; 642 + root->last_ino = ret; 642 643 spin_unlock(&kernfs_idr_lock); 643 644 idr_preload_end(); 644 645 if (ret < 0)
+1
include/linux/kernfs.h
··· 187 187 188 188 /* private fields, do not use outside kernfs proper */ 189 189 struct idr ino_idr; 190 + u32 last_ino; 190 191 u32 next_generation; 191 192 struct kernfs_syscall_ops *syscall_ops; 192 193