general protection fault in strncasecmp

Hillf Danton hdanton at sina.com
Thu Sep 24 09:40:52 EDT 2020


On Thu, 24 Sep 2020 02:26:27 -0700
> syzbot found the following issue on:
> 
> HEAD commit:    98477740 Merge branch 'rcu/urgent' of git://git.kernel.org..
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=15b4d887900000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=5f4c828c9e3cef97
> dashboard link: https://syzkaller.appspot.com/bug?extid=459a5dce0b4cb70fd076
> compiler:       gcc (GCC) 10.1.0-syz 20200507
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=125d46c5900000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=16c58f8b900000
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+459a5dce0b4cb70fd076 at syzkaller.appspotmail.com
> 
> general protection fault, probably for non-canonical address 0xf27d208691691fdb: 0000 [#1] PREEMPT SMP KASAN
> KASAN: maybe wild-memory-access in range [0x93e924348b48fed8-0x93e924348b48fedf]
> CPU: 1 PID: 10071 Comm: syz-executor152 Not tainted 5.9.0-rc6-syzkaller #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> RIP: 0010:strncasecmp lib/string.c:52 [inline]
> RIP: 0010:strncasecmp+0x5f/0x240 lib/string.c:43
> Code: 00 40 38 ce 0f 85 ec 01 00 00 4c 39 e2 0f 84 11 01 00 00 4c 89 fe 4c 89 e7 49 83 c4 01 48 89 f8 48 89 f9 48 c1 e8 03 83 e1 07 <42> 0f b6 04 28 38 c8 7f 08 84 c0 0f 85 0f 01 00 00 41 0f b6 6c 24
> RSP: 0018:ffffc9000ba7f958 EFLAGS: 00010202
> RAX: 127d248691691fdb RBX: dffffc0000000000 RCX: 0000000000000001
> RDX: 93e924348b48fee3 RSI: ffff8880a1a65401 RDI: 93e924348b48fed9
> RBP: 0000000000000009 R08: 000000000000002e R09: 0000000000000025
> R10: 0000000000000000 R11: 0000000000000005 R12: 93e924348b48feda
> R13: dffffc0000000000 R14: 00000000000000e7 R15: ffffffff82ddbcd0
> FS:  00007fd01e732700(0000) GS:ffff8880ae500000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00000000004cdb30 CR3: 00000000929cd000 CR4: 00000000001506e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> Call Trace:
>  afs_lookup_cell_rcu+0x313/0x720 fs/afs/cell.c:88
>  afs_lookup_cell+0x2ee/0x1440 fs/afs/cell.c:249
>  afs_parse_source fs/afs/super.c:290 [inline]
>  afs_parse_param+0x404/0x8c0 fs/afs/super.c:326
>  vfs_parse_fs_param fs/fs_context.c:117 [inline]
>  vfs_parse_fs_param+0x203/0x550 fs/fs_context.c:98
>  vfs_parse_fs_string+0xe6/0x150 fs/fs_context.c:161
>  generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:201
>  do_new_mount fs/namespace.c:2871 [inline]
>  path_mount+0x133f/0x20a0 fs/namespace.c:3192
>  do_mount fs/namespace.c:3205 [inline]
>  __do_sys_mount fs/namespace.c:3413 [inline]
>  __se_sys_mount fs/namespace.c:3390 [inline]
>  __x64_sys_mount+0x27f/0x300 fs/namespace.c:3390
>  do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
>  entry_SYSCALL_64_after_hwframe+0x44/0xa9


Bump up cell's usage count before anything important and skip it in
case of failure to do so.

--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -85,6 +85,20 @@ struct afs_cell *afs_lookup_cell_rcu(str
 		while (p) {
 			cell = rb_entry(p, struct afs_cell, net_node);
 
+			/*
+			 * care to detect writers because
+			 *
+			 * read_seqbegin_or_lock(&net->cells_lock, &seq);
+			 *
+			 * is unable to block 
+			 *
+			 * write_seqlock(&net->cells_lock);
+			 *
+			 */
+			if (!atomic_inc_not_zero(&cell->usage)) {
+				cell = NULL;
+				break;
+			}
 			n = strncasecmp(cell->name, name,
 					min_t(size_t, cell->name_len, namesz));
 			if (n == 0)
@@ -94,17 +108,11 @@ struct afs_cell *afs_lookup_cell_rcu(str
 			} else if (n > 0) {
 				p = rcu_dereference_raw(p->rb_right);
 			} else {
-				if (atomic_inc_not_zero(&cell->usage)) {
-					ret = 0;
-					break;
-				}
-				/* We want to repeat the search, this time with
-				 * the lock properly locked.
-				 */
+				ret = 0;
+				break;
 			}
 			cell = NULL;
 		}
-
 	} while (need_seqretry(&net->cells_lock, seq));
 
 	done_seqretry(&net->cells_lock, seq);




More information about the linux-afs mailing list