Public bug reported:
BugLink: https://bugs.launchpad.net/bugs/1978423
[Impact]
When attempting to mount a cifs share, and it fails while the kernel is
attempting to get the root inode, typically in cifs_get_root(), a double
free can occur leading to a general protection fault which panics the
system.
For example, if we try to mount a cifs share with an out of date
kerberos ticket:
[ 479.783182] CIFS: Attempting to mount \\cifs-host\cifs-share
[ 479.791769] CIFS: VFS: Verify user has a krb5 ticket and keyutils is
installed
[ 479.791774] CIFS: VFS: \\cifs-host Send error in SessSetup = -126
[ 479.791777] CIFS: VFS: cifs_read_super: get root inode failed
We hit a general protection fault:
[ 479.826541] general protection fault, probably for non-canonical address
0x2a8e69ddd8028c0: 0000 [#1] SMP NOPTI
[ 479.826546] CPU: 9 PID: 8826 Comm: nautilus Kdump: loaded Tainted: P
OE 5.11.0-40-generic #44~20.04.2-Ubuntu
[ 479.826549] Hardware name: VMware, Inc. VMware7,1/440BX Desktop Reference
Platform, BIOS VMW71.00V.18227214.B64.2106252220 06/25/2021
[ 479.826551] RIP: 0010:kfree+0x5d/0x420
[ 479.826574] CR2: 0000559ba2c12000 CR3: 0000002160152002 CR4: 00000000007706e0
[ 479.826597] Call Trace:
[ 479.826598] <IRQ>
[ 479.826603] smb3_cleanup_fs_context_contents.part.0+0x19/0xc0 [cifs]
[ 479.826660] smb3_cleanup_fs_context+0x18/0x30 [cifs]
[ 479.826694] delayed_free+0x1f/0x30 [cifs]
[ 479.826720] rcu_core+0x32a/0x500
[ 479.826725] rcu_core_si+0xe/0x10
[ 479.826727] __do_softirq+0xe0/0x29b
[ 479.826731] asm_call_irq_on_stack+0xf/0x20
[ 479.826734] </IRQ>
[ 479.826735] do_softirq_own_stack+0x3d/0x50
[ 479.826739] irq_exit_rcu+0xa4/0xb0
[ 479.826743] sysvec_apic_timer_interrupt+0x3d/0x90
[ 479.826748] ? asm_sysvec_apic_timer_interrupt+0xa/0x20
[ 479.826750] asm_sysvec_apic_timer_interrupt+0x12/0x20
[ 479.826753] RIP: 0033:0x7f410e544e98
[Fix]
The issue happens because we fall through a goto label, and free the
same cifs_sb->ctx pointer twice. The first happens when we fall through
out_super to out:
790 struct dentry *
791 cifs_smb3_do_mount(struct file_system_type *fs_type,
792 int flags, struct smb3_fs_context *old_ctx)
793 {
...
883 out_super:
884 deactivate_locked_super(sb);
885 out:
886 if (cifs_sb) {
887 kfree(cifs_sb->prepath);
888 smb3_cleanup_fs_context(cifs_sb->ctx);
889 kfree(cifs_sb);
890 }
891 return root;
892 }
The second happens in deactivate_locked_super() when we eventually make
way to delayed_free() after many function calls inbetween:
3779 static void delayed_free(struct rcu_head *p)
3780 {
3781 struct cifs_sb_info *cifs_sb = container_of(p, struct cifs_sb_info,
rcu);
3782
3783 unload_nls(cifs_sb->local_nls);
3784 smb3_cleanup_fs_context(cifs_sb->ctx);
3785 kfree(cifs_sb);
3786 }
smb3_cleanup_fs_context() frees cifs_sb->ctx, as well as all of its
pointers in the struct.
I came across the following mailing list discussion about a double free
occurring during cifs_smb3_do_mount() when we fail to get a reference to
a root dentry [2][3].
[2] https://www.spinics.net/lists/linux-cifs/msg24485.html
[3] https://www.spinics.net/lists/linux-cifs/msg24486.html
For the mailing list discussion, there is a patch submitted [4], and it
was merged into mainline in 5.17-rc5 in the below commit:
[4] https://www.spinics.net/lists/linux-cifs/msg24487.html
commit 3d6cc9898efdfb062efb74dc18cfc700e082f5d5
Author: Ronnie Sahlberg <[email protected]>
Date: Fri Feb 11 02:59:15 2022 +1000
Subject: cifs: fix double free race when mount fails in cifs_get_root()
Link:
https://github.com/torvalds/linux/commit/3d6cc9898efdfb062efb74dc18cfc700e082f5d5
This was fixed-released in 5.13.0-48-generic and 5.15.0-23-generic.
[Testcase]
Attempt to mount a cifs share where it would fail during the initial
mount, e.g. attempting to mount a cifs share with kerberos
authentication, with an out of date or invalid kerberos ticket.
[Where problems could occur]
The fix adds a return to the out_super label, to prevent fallthrough to
out. All resources will still be cleaned up correctly through the call
to deactivate_locked_super(), which will eventually reach delayed_free()
and free the resources there, so there won't be any memory leaks of any
sort that arise due to the patch.
If a regression were to occur, it would affect users of cifs mounts,
that error out and fail during the initial mounting stage.
A workaround would be to correct the issue that prevents mount in the
first place, so it would avoid the teardown code on mount failure.
** Affects: linux (Ubuntu)
Importance: Undecided
Status: Fix Released
** Affects: linux (Ubuntu Impish)
Importance: Undecided
Status: Fix Released
** Affects: linux (Ubuntu Jammy)
Importance: Undecided
Status: Fix Released
** Tags: sts
** Changed in: linux (Ubuntu)
Status: New => Fix Released
** Also affects: linux (Ubuntu Impish)
Importance: Undecided
Status: New
** Also affects: linux (Ubuntu Jammy)
Importance: Undecided
Status: New
** Changed in: linux (Ubuntu Impish)
Status: New => Fix Released
** Changed in: linux (Ubuntu Jammy)
Status: New => Fix Released
** Description changed:
- BugLink: https://bugs.launchpad.net/bugs/
+ BugLink: https://bugs.launchpad.net/bugs/1978423
[Impact]
When attempting to mount a cifs share, and it fails while the kernel is
attempting to get the root inode, typically in cifs_get_root(), a double
free can occur leading to a general protection fault which panics the
system.
For example, if we try to mount a cifs share with an out of date
kerberos ticket:
[ 479.783182] CIFS: Attempting to mount \\cifs-host\cifs-share
[ 479.791769] CIFS: VFS: Verify user has a krb5 ticket and keyutils is
installed
[ 479.791774] CIFS: VFS: \\cifs-host Send error in SessSetup = -126
[ 479.791777] CIFS: VFS: cifs_read_super: get root inode failed
We hit a general protection fault:
[ 479.826541] general protection fault, probably for non-canonical address
0x2a8e69ddd8028c0: 0000 [#1] SMP NOPTI
[ 479.826546] CPU: 9 PID: 8826 Comm: nautilus Kdump: loaded Tainted: P
OE 5.11.0-40-generic #44~20.04.2-Ubuntu
[ 479.826549] Hardware name: VMware, Inc. VMware7,1/440BX Desktop Reference
Platform, BIOS VMW71.00V.18227214.B64.2106252220 06/25/2021
[ 479.826551] RIP: 0010:kfree+0x5d/0x420
[ 479.826574] CR2: 0000559ba2c12000 CR3: 0000002160152002 CR4:
00000000007706e0
[ 479.826597] Call Trace:
[ 479.826598] <IRQ>
[ 479.826603] smb3_cleanup_fs_context_contents.part.0+0x19/0xc0 [cifs]
[ 479.826660] smb3_cleanup_fs_context+0x18/0x30 [cifs]
[ 479.826694] delayed_free+0x1f/0x30 [cifs]
[ 479.826720] rcu_core+0x32a/0x500
[ 479.826725] rcu_core_si+0xe/0x10
[ 479.826727] __do_softirq+0xe0/0x29b
[ 479.826731] asm_call_irq_on_stack+0xf/0x20
[ 479.826734] </IRQ>
[ 479.826735] do_softirq_own_stack+0x3d/0x50
[ 479.826739] irq_exit_rcu+0xa4/0xb0
[ 479.826743] sysvec_apic_timer_interrupt+0x3d/0x90
[ 479.826748] ? asm_sysvec_apic_timer_interrupt+0xa/0x20
[ 479.826750] asm_sysvec_apic_timer_interrupt+0x12/0x20
[ 479.826753] RIP: 0033:0x7f410e544e98
[Fix]
The issue happens because we fall through a goto label, and free the
same cifs_sb->ctx pointer twice. The first happens when we fall through
out_super to out:
790 struct dentry *
- 791 cifs_smb3_do_mount(struct file_system_type *fs_type,
- 792 int flags, struct smb3_fs_context *old_ctx)
- 793 {
+ 791 cifs_smb3_do_mount(struct file_system_type *fs_type,
+ 792 int flags, struct smb3_fs_context *old_ctx)
+ 793 {
...
- 883 out_super:
- 884 deactivate_locked_super(sb);
- 885 out:
- 886 if (cifs_sb) {
- 887 kfree(cifs_sb->prepath);
- 888 smb3_cleanup_fs_context(cifs_sb->ctx);
- 889 kfree(cifs_sb);
- 890 }
- 891 return root;
- 892 }
-
- The second happens in deactivate_locked_super() when we eventually make way
to delayed_free() after many function calls inbetween:
+ 883 out_super:
+ 884 deactivate_locked_super(sb);
+ 885 out:
+ 886 if (cifs_sb) {
+ 887 kfree(cifs_sb->prepath);
+ 888 smb3_cleanup_fs_context(cifs_sb->ctx);
+ 889 kfree(cifs_sb);
+ 890 }
+ 891 return root;
+ 892 }
+
+ The second happens in deactivate_locked_super() when we eventually make
+ way to delayed_free() after many function calls inbetween:
3779 static void delayed_free(struct rcu_head *p)
3780 {
3781 struct cifs_sb_info *cifs_sb = container_of(p, struct cifs_sb_info,
rcu);
3782
3783 unload_nls(cifs_sb->local_nls);
3784 smb3_cleanup_fs_context(cifs_sb->ctx);
3785 kfree(cifs_sb);
3786 }
smb3_cleanup_fs_context() frees cifs_sb->ctx, as well as all of its
pointers in the struct.
I came across the following mailing list discussion about a double free
occurring during cifs_smb3_do_mount() when we fail to get a reference to
a root dentry [2][3].
[2] https://www.spinics.net/lists/linux-cifs/msg24485.html
[3] https://www.spinics.net/lists/linux-cifs/msg24486.html
For the mailing list discussion, there is a patch submitted [4], and it
was merged into mainline in 5.17-rc5 in the below commit:
[4] https://www.spinics.net/lists/linux-cifs/msg24487.html
commit 3d6cc9898efdfb062efb74dc18cfc700e082f5d5
Author: Ronnie Sahlberg <[email protected]>
Date: Fri Feb 11 02:59:15 2022 +1000
Subject: cifs: fix double free race when mount fails in cifs_get_root()
Link:
https://github.com/torvalds/linux/commit/3d6cc9898efdfb062efb74dc18cfc700e082f5d5
This was fixed-released in 5.13.0-48-generic and 5.15.0-23-generic.
[Testcase]
Attempt to mount a cifs share where it would fail during the initial
mount, e.g. attempting to mount a cifs share with kerberos
authentication, with an out of date or invalid kerberos ticket.
[Where problems could occur]
The fix adds a return to the out_super label, to prevent fallthrough to
out. All resources will still be cleaned up correctly through the call
to deactivate_locked_super(), which will eventually reach delayed_free()
and free the resources there, so there won't be any memory leaks of any
sort that arise due to the patch.
If a regression were to occur, it would affect users of cifs mounts,
that error out and fail during the initial mounting stage.
A workaround would be to correct the issue that prevents mount in the
first place, so it would avoid the teardown code on mount failure.
** Tags added: sts
--
You received this bug notification because you are a member of Kernel
Packages, which is subscribed to linux in Ubuntu.
https://bugs.launchpad.net/bugs/1978423
Title:
cifs: Double free in cifs_smb3_do_mount() when mount fails in
cifs_get_root()
Status in linux package in Ubuntu:
Fix Released
Status in linux source package in Impish:
Fix Released
Status in linux source package in Jammy:
Fix Released
Bug description:
BugLink: https://bugs.launchpad.net/bugs/1978423
[Impact]
When attempting to mount a cifs share, and it fails while the kernel
is attempting to get the root inode, typically in cifs_get_root(), a
double free can occur leading to a general protection fault which
panics the system.
For example, if we try to mount a cifs share with an out of date
kerberos ticket:
[ 479.783182] CIFS: Attempting to mount \\cifs-host\cifs-share
[ 479.791769] CIFS: VFS: Verify user has a krb5 ticket and keyutils is
installed
[ 479.791774] CIFS: VFS: \\cifs-host Send error in SessSetup = -126
[ 479.791777] CIFS: VFS: cifs_read_super: get root inode failed
We hit a general protection fault:
[ 479.826541] general protection fault, probably for non-canonical address
0x2a8e69ddd8028c0: 0000 [#1] SMP NOPTI
[ 479.826546] CPU: 9 PID: 8826 Comm: nautilus Kdump: loaded Tainted: P
OE 5.11.0-40-generic #44~20.04.2-Ubuntu
[ 479.826549] Hardware name: VMware, Inc. VMware7,1/440BX Desktop Reference
Platform, BIOS VMW71.00V.18227214.B64.2106252220 06/25/2021
[ 479.826551] RIP: 0010:kfree+0x5d/0x420
[ 479.826574] CR2: 0000559ba2c12000 CR3: 0000002160152002 CR4:
00000000007706e0
[ 479.826597] Call Trace:
[ 479.826598] <IRQ>
[ 479.826603] smb3_cleanup_fs_context_contents.part.0+0x19/0xc0 [cifs]
[ 479.826660] smb3_cleanup_fs_context+0x18/0x30 [cifs]
[ 479.826694] delayed_free+0x1f/0x30 [cifs]
[ 479.826720] rcu_core+0x32a/0x500
[ 479.826725] rcu_core_si+0xe/0x10
[ 479.826727] __do_softirq+0xe0/0x29b
[ 479.826731] asm_call_irq_on_stack+0xf/0x20
[ 479.826734] </IRQ>
[ 479.826735] do_softirq_own_stack+0x3d/0x50
[ 479.826739] irq_exit_rcu+0xa4/0xb0
[ 479.826743] sysvec_apic_timer_interrupt+0x3d/0x90
[ 479.826748] ? asm_sysvec_apic_timer_interrupt+0xa/0x20
[ 479.826750] asm_sysvec_apic_timer_interrupt+0x12/0x20
[ 479.826753] RIP: 0033:0x7f410e544e98
[Fix]
The issue happens because we fall through a goto label, and free the
same cifs_sb->ctx pointer twice. The first happens when we fall
through out_super to out:
790 struct dentry *
791 cifs_smb3_do_mount(struct file_system_type *fs_type,
792 int flags, struct smb3_fs_context *old_ctx)
793 {
...
883 out_super:
884 deactivate_locked_super(sb);
885 out:
886 if (cifs_sb) {
887 kfree(cifs_sb->prepath);
888 smb3_cleanup_fs_context(cifs_sb->ctx);
889 kfree(cifs_sb);
890 }
891 return root;
892 }
The second happens in deactivate_locked_super() when we eventually
make way to delayed_free() after many function calls inbetween:
3779 static void delayed_free(struct rcu_head *p)
3780 {
3781 struct cifs_sb_info *cifs_sb = container_of(p, struct cifs_sb_info,
rcu);
3782
3783 unload_nls(cifs_sb->local_nls);
3784 smb3_cleanup_fs_context(cifs_sb->ctx);
3785 kfree(cifs_sb);
3786 }
smb3_cleanup_fs_context() frees cifs_sb->ctx, as well as all of its
pointers in the struct.
I came across the following mailing list discussion about a double
free occurring during cifs_smb3_do_mount() when we fail to get a
reference to a root dentry [2][3].
[2] https://www.spinics.net/lists/linux-cifs/msg24485.html
[3] https://www.spinics.net/lists/linux-cifs/msg24486.html
For the mailing list discussion, there is a patch submitted [4], and
it was merged into mainline in 5.17-rc5 in the below commit:
[4] https://www.spinics.net/lists/linux-cifs/msg24487.html
commit 3d6cc9898efdfb062efb74dc18cfc700e082f5d5
Author: Ronnie Sahlberg <[email protected]>
Date: Fri Feb 11 02:59:15 2022 +1000
Subject: cifs: fix double free race when mount fails in cifs_get_root()
Link:
https://github.com/torvalds/linux/commit/3d6cc9898efdfb062efb74dc18cfc700e082f5d5
This was fixed-released in 5.13.0-48-generic and 5.15.0-23-generic.
[Testcase]
Attempt to mount a cifs share where it would fail during the initial
mount, e.g. attempting to mount a cifs share with kerberos
authentication, with an out of date or invalid kerberos ticket.
[Where problems could occur]
The fix adds a return to the out_super label, to prevent fallthrough
to out. All resources will still be cleaned up correctly through the
call to deactivate_locked_super(), which will eventually reach
delayed_free() and free the resources there, so there won't be any
memory leaks of any sort that arise due to the patch.
If a regression were to occur, it would affect users of cifs mounts,
that error out and fail during the initial mounting stage.
A workaround would be to correct the issue that prevents mount in the
first place, so it would avoid the teardown code on mount failure.
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1978423/+subscriptions
--
Mailing list: https://launchpad.net/~kernel-packages
Post to : [email protected]
Unsubscribe : https://launchpad.net/~kernel-packages
More help : https://help.launchpad.net/ListHelp