On Fri, 2013-10-11 at 17:16 +0100, David Howells wrote: > key_reject_and_link() marking a key as negative and setting the error with > which it was negated races with keyring searches and other things that read > that error. > > The fix is to switch the order in which the assignments are done in > key_reject_and_link() and to use memory barriers. > > Kudos to Dave Wysochanski <dwysocha@xxxxxxxxxx> and Scott Mayhew > <smayhew@xxxxxxxxxx> for tracking this down. > > This may be the cause of: > > BUG: unable to handle kernel NULL pointer dereference at 0000000000000070 > IP: [<ffffffff81219011>] wait_for_key_construction+0x31/0x80 > PGD c6b2c3067 PUD c59879067 PMD 0 > Oops: 0000 [#1] SMP > last sysfs file: /sys/devices/system/cpu/cpu3/cache/index2/shared_cpu_map > CPU 0 > Modules linked in: ... > > Pid: 13359, comm: amqzxma0 Not tainted 2.6.32-358.20.1.el6.x86_64 #1 IBM System x3650 M3 -[7945PSJ]-/00J6159 > RIP: 0010:[<ffffffff81219011>] wait_for_key_construction+0x31/0x80 > RSP: 0018:ffff880c6ab33758 EFLAGS: 00010246 > RAX: ffffffff81219080 RBX: 0000000000000000 RCX: 0000000000000002 > RDX: ffffffff81219060 RSI: 0000000000000000 RDI: 0000000000000000 > RBP: ffff880c6ab33768 R08: 0000000000000000 R09: 0000000000000000 > R10: 0000000000000001 R11: 0000000000000000 R12: ffff880adfcbce40 > R13: ffffffffa03afb84 R14: ffff880adfcbce40 R15: ffff880adfcbce43 > FS: 00007f29b8042700(0000) GS:ffff880028200000(0000) knlGS:0000000000000000 > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > CR2: 0000000000000070 CR3: 0000000c613dc000 CR4: 00000000000007f0 > DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 > DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 > Process amqzxma0 (pid: 13359, threadinfo ffff880c6ab32000, task ffff880c610deae0) > Stack: > ffff880adfcbce40 0000000000000000 ffff880c6ab337b8 ffffffff81219695 > <d> 0000000000000000 ffff880a000000d0 ffff880c6ab337a8 000000000000000f > <d> ffffffffa03afb93 000000000000000f ffff88186c7882c0 0000000000000014 > Call Trace: > [<ffffffff81219695>] request_key+0x65/0xa0 > [<ffffffffa03a0885>] nfs_idmap_request_key+0xc5/0x170 [nfs] > [<ffffffffa03a0eb4>] nfs_idmap_lookup_id+0x34/0x80 [nfs] > [<ffffffffa03a1255>] nfs_map_group_to_gid+0x75/0xa0 [nfs] > [<ffffffffa039a9ad>] decode_getfattr_attrs+0xbdd/0xfb0 [nfs] > [<ffffffff81057310>] ? __dequeue_entity+0x30/0x50 > [<ffffffff8100988e>] ? __switch_to+0x26e/0x320 > [<ffffffffa039ae03>] decode_getfattr+0x83/0xe0 [nfs] > [<ffffffffa039b610>] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs] > [<ffffffffa039b69f>] nfs4_xdr_dec_getattr+0x8f/0xa0 [nfs] > [<ffffffffa02dada4>] rpcauth_unwrap_resp+0x84/0xb0 [sunrpc] > [<ffffffffa039b610>] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs] > [<ffffffffa02cf923>] call_decode+0x1b3/0x800 [sunrpc] > [<ffffffff81096de0>] ? wake_bit_function+0x0/0x50 > [<ffffffffa02cf770>] ? call_decode+0x0/0x800 [sunrpc] > [<ffffffffa02d99a7>] __rpc_execute+0x77/0x350 [sunrpc] > [<ffffffff81096c67>] ? bit_waitqueue+0x17/0xd0 > [<ffffffffa02d9ce1>] rpc_execute+0x61/0xa0 [sunrpc] > [<ffffffffa02d03a5>] rpc_run_task+0x75/0x90 [sunrpc] > [<ffffffffa02d04c2>] rpc_call_sync+0x42/0x70 [sunrpc] > [<ffffffffa038ff80>] _nfs4_call_sync+0x30/0x40 [nfs] > [<ffffffffa038836c>] _nfs4_proc_getattr+0xac/0xc0 [nfs] > [<ffffffff810aac87>] ? futex_wait+0x227/0x380 > [<ffffffffa038b856>] nfs4_proc_getattr+0x56/0x80 [nfs] > [<ffffffffa0371403>] __nfs_revalidate_inode+0xe3/0x220 [nfs] > [<ffffffffa037158e>] nfs_revalidate_mapping+0x4e/0x170 [nfs] > [<ffffffffa036f147>] nfs_file_read+0x77/0x130 [nfs] > [<ffffffff811811aa>] do_sync_read+0xfa/0x140 > [<ffffffff81096da0>] ? autoremove_wake_function+0x0/0x40 > [<ffffffff8100bb8e>] ? apic_timer_interrupt+0xe/0x20 > [<ffffffff8100b9ce>] ? common_interrupt+0xe/0x13 > [<ffffffff81228ffb>] ? selinux_file_permission+0xfb/0x150 > [<ffffffff8121bed6>] ? security_file_permission+0x16/0x20 > [<ffffffff81181a95>] vfs_read+0xb5/0x1a0 > [<ffffffff81181bd1>] sys_read+0x51/0x90 > [<ffffffff810dc685>] ? __audit_syscall_exit+0x265/0x290 > [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b > > Signed-off-by: David Howells <dhowells@xxxxxxxxxx> > cc: Dave Wysochanski <dwysocha@xxxxxxxxxx> > cc: Scott Mayhew <smayhew@xxxxxxxxxx> > --- > > security/keys/key.c | 3 ++- > security/keys/keyring.c | 7 +++++-- > security/keys/request_key.c | 4 +++- > 3 files changed, 10 insertions(+), 4 deletions(-) > > diff --git a/security/keys/key.c b/security/keys/key.c > index 8fb7c7b..eaa9f34 100644 > --- a/security/keys/key.c > +++ b/security/keys/key.c > @@ -557,9 +557,10 @@ int key_reject_and_link(struct key *key, > if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { > /* mark the key as being negatively instantiated */ > atomic_inc(&key->user->nikeys); > + key->type_data.reject_error = -error; > + smp_wmb(); > set_bit(KEY_FLAG_NEGATIVE, &key->flags); > set_bit(KEY_FLAG_INSTANTIATED, &key->flags); > - key->type_data.reject_error = -error; > now = current_kernel_time(); > key->expiry = now.tv_sec + timeout; > key_schedule_gc(key->expiry + key_gc_delay); > diff --git a/security/keys/keyring.c b/security/keys/keyring.c > index 6ece7f2..d4cf442 100644 > --- a/security/keys/keyring.c > +++ b/security/keys/keyring.c > @@ -371,9 +371,11 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, > goto error_2; > if (key->expiry && now.tv_sec >= key->expiry) > goto error_2; > - key_ref = ERR_PTR(key->type_data.reject_error); > - if (kflags & (1 << KEY_FLAG_NEGATIVE)) > + if (kflags & (1 << KEY_FLAG_NEGATIVE)) { > + smp_rmb(); > + key_ref = ERR_PTR(key->type_data.reject_error); > goto error_2; > + } > goto found; > } > > @@ -432,6 +434,7 @@ descend: > > /* we set a different error code if we pass a negative key */ > if (kflags & (1 << KEY_FLAG_NEGATIVE)) { > + smp_rmb(); > err = key->type_data.reject_error; > continue; > } > diff --git a/security/keys/request_key.c b/security/keys/request_key.c > index c411f9b..dc6f3be 100644 > --- a/security/keys/request_key.c > +++ b/security/keys/request_key.c > @@ -592,8 +592,10 @@ int wait_for_key_construction(struct key *key, bool intr) > intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); > if (ret < 0) > return ret; > - if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) > + if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { > + smp_rmb(); > return key->type_data.reject_error; > + } > return key_validate(key); > } > EXPORT_SYMBOL(wait_for_key_construction); > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > > Definite Ack! -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html