linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] hugetlbfs: initialize shared policy as part of inode allocation
@ 2017-03-24 23:11 Mike Kravetz
  2017-03-25  0:54 ` Tetsuo Handa
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Kravetz @ 2017-03-24 23:11 UTC (permalink / raw)
  To: linux-mm, linux-kernel
  Cc: Dmitry Vyukov, Tetsuo Handa, Michal Hocko, Hillf Danton,
	Dave Hansen, Andrew Morton, Mike Kravetz

Any time after inode allocation, destroy_inode can be called.  The
hugetlbfs inode contains a shared_policy structure, and
mpol_free_shared_policy is unconditionally called as part of
hugetlbfs_destroy_inode.  Initialize the policy as part of inode
allocation so that any quick (error path) calls to destroy_inode
will be handed an initialized policy.

syzkaller fuzzer found this bug, that resulted in the following:

BUG: KASAN: user-memory-access in atomic_inc
include/asm-generic/atomic-instrumented.h:87 [inline] at addr
000000131730bd7a
BUG: KASAN: user-memory-access in __lock_acquire+0x21a/0x3a80
kernel/locking/lockdep.c:3239 at addr 000000131730bd7a
Write of size 4 by task syz-executor6/14086
CPU: 3 PID: 14086 Comm: syz-executor6 Not tainted 4.11.0-rc3+ #364
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:16 [inline]
 dump_stack+0x1b8/0x28d lib/dump_stack.c:52
 kasan_report_error mm/kasan/report.c:291 [inline]
 kasan_report.part.2+0x34a/0x480 mm/kasan/report.c:316
 kasan_report+0x21/0x30 mm/kasan/report.c:303
 check_memory_region_inline mm/kasan/kasan.c:326 [inline]
 check_memory_region+0x137/0x190 mm/kasan/kasan.c:333
 kasan_check_write+0x14/0x20 mm/kasan/kasan.c:344
 atomic_inc include/asm-generic/atomic-instrumented.h:87 [inline]
 __lock_acquire+0x21a/0x3a80 kernel/locking/lockdep.c:3239
 lock_acquire+0x1ee/0x590 kernel/locking/lockdep.c:3762
 __raw_write_lock include/linux/rwlock_api_smp.h:210 [inline]
 _raw_write_lock+0x33/0x50 kernel/locking/spinlock.c:295
 mpol_free_shared_policy+0x43/0xb0 mm/mempolicy.c:2536
 hugetlbfs_destroy_inode+0xca/0x120 fs/hugetlbfs/inode.c:952
 alloc_inode+0x10d/0x180 fs/inode.c:216
 new_inode_pseudo+0x69/0x190 fs/inode.c:889
 new_inode+0x1c/0x40 fs/inode.c:918
 hugetlbfs_get_inode+0x40/0x420 fs/hugetlbfs/inode.c:734
 hugetlb_file_setup+0x329/0x9f0 fs/hugetlbfs/inode.c:1282
 newseg+0x422/0xd30 ipc/shm.c:575
 ipcget_new ipc/util.c:285 [inline]
 ipcget+0x21e/0x580 ipc/util.c:639
 SYSC_shmget ipc/shm.c:673 [inline]
 SyS_shmget+0x158/0x230 ipc/shm.c:657
 entry_SYSCALL_64_fastpath+0x1f/0xc2

Analysis provided by Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
---
 fs/hugetlbfs/inode.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 54de77e..8e28e16 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -733,7 +733,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
 
 	inode = new_inode(sb);
 	if (inode) {
-		struct hugetlbfs_inode_info *info;
 		inode->i_ino = get_next_ino();
 		inode_init_owner(inode, dir, mode);
 		lockdep_set_class(&inode->i_mapping->i_mmap_rwsem,
@@ -741,15 +740,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
 		inode->i_mapping->a_ops = &hugetlbfs_aops;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
 		inode->i_mapping->private_data = resv_map;
-		info = HUGETLBFS_I(inode);
-		/*
-		 * The policy is initialized here even if we are creating a
-		 * private inode because initialization simply creates an
-		 * an empty rb tree and calls rwlock_init(), later when we
-		 * call mpol_free_shared_policy() it will just return because
-		 * the rb tree will still be empty.
-		 */
-		mpol_shared_policy_init(&info->policy, NULL);
 		switch (mode & S_IFMT) {
 		default:
 			init_special_inode(inode, mode, dev);
@@ -937,6 +927,18 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb)
 		hugetlbfs_inc_free_inodes(sbinfo);
 		return NULL;
 	}
+
+	/*
+	 * Any time after allocation, hugetlbfs_destroy_inode can be called
+	 * for the inode.  mpol_free_shared_policy is unconditionally called
+	 * as part of hugetlbfs_destroy_inode.  So, initialize policy here
+	 * in case of a quick call to destroy.
+	 *
+	 * Note that the policy is initialized even if we are creating a
+	 * private inode.  This simplifies hugetlbfs_destroy_inode.
+	 */
+	mpol_shared_policy_init(&p->policy, NULL);
+
 	return &p->vfs_inode;
 }
 
-- 
2.7.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] hugetlbfs: initialize shared policy as part of inode allocation
  2017-03-24 23:11 [PATCH] hugetlbfs: initialize shared policy as part of inode allocation Mike Kravetz
@ 2017-03-25  0:54 ` Tetsuo Handa
  2017-03-25 21:35   ` Mike Kravetz
  0 siblings, 1 reply; 3+ messages in thread
From: Tetsuo Handa @ 2017-03-25  0:54 UTC (permalink / raw)
  To: mike.kravetz, linux-mm, linux-kernel
  Cc: dvyukov, mhocko, hillf.zj, dave.hansen, akpm

Mike Kravetz wrote:
> Any time after inode allocation, destroy_inode can be called.  The
> hugetlbfs inode contains a shared_policy structure, and
> mpol_free_shared_policy is unconditionally called as part of
> hugetlbfs_destroy_inode.  Initialize the policy as part of inode
> allocation so that any quick (error path) calls to destroy_inode
> will be handed an initialized policy.

I think you can as well do

-		struct hugetlbfs_inode_info *info;
-		info = HUGETLBFS_I(inode);
-		mpol_shared_policy_init(&info->policy, NULL);

in hugetlbfs_get_root().

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] hugetlbfs: initialize shared policy as part of inode allocation
  2017-03-25  0:54 ` Tetsuo Handa
@ 2017-03-25 21:35   ` Mike Kravetz
  0 siblings, 0 replies; 3+ messages in thread
From: Mike Kravetz @ 2017-03-25 21:35 UTC (permalink / raw)
  To: Tetsuo Handa, linux-mm, linux-kernel
  Cc: dvyukov, mhocko, hillf.zj, dave.hansen, akpm

On 03/24/2017 05:54 PM, Tetsuo Handa wrote:
> Mike Kravetz wrote:
>> Any time after inode allocation, destroy_inode can be called.  The
>> hugetlbfs inode contains a shared_policy structure, and
>> mpol_free_shared_policy is unconditionally called as part of
>> hugetlbfs_destroy_inode.  Initialize the policy as part of inode
>> allocation so that any quick (error path) calls to destroy_inode
>> will be handed an initialized policy.
> 
> I think you can as well do
> 
> -		struct hugetlbfs_inode_info *info;
> -		info = HUGETLBFS_I(inode);
> -		mpol_shared_policy_init(&info->policy, NULL);
> 
> in hugetlbfs_get_root().

Thank you.  You are correct.
After doing shared policy initialization at inode allocation time,
it is redundant here.

I will send v2 patch with this modification.

-- 
Mike Kravetz

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-03-25 21:36 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-24 23:11 [PATCH] hugetlbfs: initialize shared policy as part of inode allocation Mike Kravetz
2017-03-25  0:54 ` Tetsuo Handa
2017-03-25 21:35   ` Mike Kravetz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox