smack: Possible NULL pointer deref in cred_free hook.
Tetsuo Handa
penguin-kernel at I-love.SAKURA.ne.jp
Tue Feb 6 14:31:28 UTC 2024
Hello, Casey.
I confirmed using fault injection shown below that smack_cred_free() is not
prepared for being called without successful smack_cred_prepare().
diff --git a/security/security.c b/security/security.c
index 10adc4d3c5e0..690136b60d28 100644
--- a/security/security.c
+++ b/security/security.c
@@ -3059,7 +3059,7 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
if (rc)
return rc;
- rc = call_int_hook(cred_prepare, 0, new, old, gfp);
+ rc = -EPERM; //call_int_hook(cred_prepare, 0, new, old, gfp);
if (unlikely(rc))
security_cred_free(new);
return rc;
[ 11.366204] LSM: initializing lsm=capability,yama,smack,integrity
[ 11.368005] Yama: becoming mindful.
[ 11.371997] Smack: Initializing.
[ 11.373957] Smack: IPv6 port labeling enabled.
[ 11.379072] Mount-cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
[ 11.383676] Mountpoint-cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
[ 11.400071] Running RCU synchronous self tests
[ 11.450967] Running RCU synchronous self tests
[ 11.453956] BUG: kernel NULL pointer dereference, address: 0000000000000000
[ 11.454948] #PF: supervisor read access in kernel mode
[ 11.454948] #PF: error_code(0x0000) - not-present page
[ 11.454948] PGD 0 P4D 0
[ 11.454948] Oops: 0000 [#1] PREEMPT SMP PTI
[ 11.454948] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.8.0-rc3+ #47
[ 11.454948] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020
[ 11.454948] RIP: 0010:smk_destroy_label_list+0x11/0x40
[ 11.454948] Code: 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 66 0f 1f 00 0f 1f 44 00 00 55 48 89 fd 53 48 8b 3f <48> 8b 1f 48 39 fd 74 13 e8 c2 bd e2 ff 48 89 d8 48 89 df 48 8b 1b
[ 11.454948] RSP: 0000:ffffffffa3003c50 EFLAGS: 00010286
[ 11.454948] RAX: ffffffffa1f763e0 RBX: ffffffffa2f19b00 RCX: 0000000000000100
[ 11.454948] RDX: 00000000000000d8 RSI: 0000000000000000 RDI: 0000000000000000
[ 11.454948] RBP: ffff8d71c03300c8 R08: 0000000000400dc0 R09: 00000000ffffffff
[ 11.454948] R10: ffffffffa3003c48 R11: ffff8d7259ffc220 R12: ffff8d71c0330018
[ 11.454948] R13: ffffffffa3003e48 R14: ffff8d71c03c8000 R15: 0000000000000001
[ 11.454948] FS: 0000000000000000(0000) GS:ffff8d7259e00000(0000) knlGS:0000000000000000
[ 11.454948] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 11.454948] CR2: 0000000000000000 CR3: 000000014e03c000 CR4: 0000000000350ef0
[ 11.454948] Call Trace:
[ 11.454948] <TASK>
[ 11.454948] ? __die_body+0x1e/0x60
[ 11.454948] ? page_fault_oops+0x15b/0x470
[ 11.454948] ? local_clock+0x15/0x30
[ 11.454948] ? lock_release+0x275/0x350
[ 11.454948] ? exc_page_fault+0x74/0x1e0
[ 11.454948] ? asm_exc_page_fault+0x26/0x30
[ 11.454948] ? __pfx_smack_cred_free+0x10/0x10
[ 11.454948] ? smk_destroy_label_list+0x11/0x40
[ 11.454948] smack_cred_free+0x30/0xa0
[ 11.454948] security_cred_free+0x2f/0x60
[ 11.454948] security_prepare_creds+0x2b/0x60
[ 11.454948] prepare_creds+0x1b3/0x2c0
[ 11.454948] copy_creds+0x2e/0x380
[ 11.454948] copy_process+0x47e/0x2080
[ 11.454948] ? find_held_lock+0x34/0xa0
[ 11.454948] kernel_clone+0x9f/0x6c0
[ 11.454948] ? __mutex_unlock_slowpath+0x43/0x2c0
[ 11.454948] ? synchronize_rcu_expedited+0x3fa/0x4e0
[ 11.454948] user_mode_thread+0x5f/0x90
[ 11.454948] ? __pfx_kernel_init+0x10/0x10
[ 11.454948] rest_init+0x22/0x1d0
[ 11.454948] arch_call_rest_init+0xe/0x30
[ 11.454948] start_kernel+0x63e/0x720
[ 11.454948] x86_64_start_reservations+0x18/0x30
[ 11.454948] x86_64_start_kernel+0x91/0xa0
[ 11.454948] secondary_startup_64_no_verify+0x184/0x18b
[ 11.454948] </TASK>
[ 11.454948] Modules linked in:
[ 11.454948] CR2: 0000000000000000
[ 11.454948] ---[ end trace 0000000000000000 ]---
[ 11.454948] RIP: 0010:smk_destroy_label_list+0x11/0x40
[ 11.454948] Code: 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 66 0f 1f 00 0f 1f 44 00 00 55 48 89 fd 53 48 8b 3f <48> 8b 1f 48 39 fd 74 13 e8 c2 bd e2 ff 48 89 d8 48 89 df 48 8b 1b
[ 11.454948] RSP: 0000:ffffffffa3003c50 EFLAGS: 00010286
[ 11.454948] RAX: ffffffffa1f763e0 RBX: ffffffffa2f19b00 RCX: 0000000000000100
[ 11.454948] RDX: 00000000000000d8 RSI: 0000000000000000 RDI: 0000000000000000
[ 11.454948] RBP: ffff8d71c03300c8 R08: 0000000000400dc0 R09: 00000000ffffffff
[ 11.454948] R10: ffffffffa3003c48 R11: ffff8d7259ffc220 R12: ffff8d71c0330018
[ 11.454948] R13: ffffffffa3003e48 R14: ffff8d71c03c8000 R15: 0000000000000001
[ 11.454948] FS: 0000000000000000(0000) GS:ffff8d7259e00000(0000) knlGS:0000000000000000
[ 11.454948] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 11.454948] CR2: 0000000000000000 CR3: 000000014e03c000 CR4: 0000000000350ef0
[ 11.454948] Kernel panic - not syncing: Fatal exception
[ 11.454948] ---[ end Kernel panic - not syncing: Fatal exception ]---
On 2024/01/27 23:36, Tetsuo Handa wrote:
> The cred_free hook might be called without successful cred_prepare
> as long as cred->security != NULL. It seems to me that smack_cred_free()
> is not prepared for that case. Please check.
>
> prepare_creds() {
> new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
> if (!new)
> return NULL;
> new->security = NULL;
> security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) {
> int rc = lsm_cred_alloc(new, gfp);
> if (rc)
> return rc;
> rc = call_int_hook(cred_prepare, 0, new, old, gfp) {
> // cred->security != NULL and one of callbacks returned an error
> }
> if (unlikely(rc)) {
> security_cred_free(new) {
> call_void_hook(cred_free, cred) {
> // at least one callback is called without successful cred_prepare
> }
> kfree(cred->security);
> cred->security = NULL;
> }
> }
> }
> goto error;
> error:
> abort_creds(new)
> return NULL;
> }
More information about the Linux-security-module-archive
mailing list