Bug 216018

Summary: Bluetooth: strlen in append_eir_data_to_buf causes calling process to freeze when short/longname does not have double NUL termination.
Product: Networking Reporter: Tom Unbehau (tomu1)
Component: OtherAssignee: Stephen Hemminger (stephen)
Status: NEW ---    
Severity: normal CC: luiz.dentz
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 5.17.6-1-MANJARO #1 Subsystem:
Regression: No Bisected commit-id:
Attachments: Program to cause strlen Kernel Bug

Description Tom Unbehau 2022-05-23 15:32:38 UTC
Created attachment 301019 [details]
Program to cause strlen Kernel Bug

The process I use to set the bluetooth short/longname via HCI freezes with a kernel bug.
I have investigated this problem and have possibly found the issue.

When writing the bluetooth localname to the kernel via HCI, the userspace is required to
write the command to the HCI socket in the following way (https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/mgmt-api.txt):


"
Command Code:		0x000F
	Controller Index:	<controller id>
	Command Parameters:	Name (249 Octets)
				Short_Name (11 Octets)
	Return Parameters:	Name (249 Octets)
				Short_Name (11 Octets))

[...]
				
The values of name and short name will be remembered when
	switching the controller off and back on again. So the name
	and short name only have to be set once when a new controller
	is found and will stay until removed.				
"

It is requested that both Name and Short_Name are zero terminated.

When this command is sent via the HCI socket eventually set_local_name is called in the kernel:

static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
			  u16 len)
{
	struct mgmt_cp_set_local_name *cp = data;
	
The structures which are important here are hci_dev and mgmt_cp_set_local_name:

struct hci_dev (excerpt):
The relevant struct is defined as such:
	__u8		dev_name[HCI_MAX_NAME_LENGTH];
	__u8		short_name[HCI_MAX_SHORT_NAME_LENGTH];
	
The length macros are defined as such:
#define HCI_MAX_NAME_LENGTH		248
#define HCI_MAX_SHORT_NAME_LENGTH	10

struct mgmt_cp_set_local_name {
	__u8	name[MGMT_MAX_NAME_LENGTH];
	__u8	short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;

Its length macros are the following:

/* Reserve one extra byte for names in management messages so that they
 * are always guaranteed to be nul-terminated */
#define MGMT_MAX_NAME_LENGTH		(HCI_MAX_NAME_LENGTH + 1)
#define MGMT_MAX_SHORT_NAME_LENGTH	(HCI_MAX_SHORT_NAME_LENGTH + 1)

When set_local_name (net/bluetooth/mgmt.c) is called an memcpy is used to transfer
the names:

memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
if (!hdev_is_powered(hdev)) {
		memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));

This would not be a problem in of itself,
however when ext_info_changed is called in the same function (and possibly
elsewhere), it internally uses append_eir_data_to_buf, which uses 
strlen to determine the length of the device/shortname:

static u16 append_eir_data_to_buf(struct hci_dev *hdev, u8 *eir)
...
name_len = strlen(hdev->dev_name);
....
name_len = strlen(hdev->short_name);

As such, when the userspace gives a name which does not have 2 NUL bytes
at the end of long(dev)name and shortname, then the strlen will search
over the size of the buffer, as internal structure does not have a NUL
byte, which, sadly, causes my started hci process
to completely freeze (unrecoverable) due to kernel hardening
kicking in.

An easy wasy to reproduce this issue is by executing the attached program. Please note blueZ and all of these Bluetooth grabbing services need to be disabled and the controller itself must be powered off.

A temporary workaround is to terminate the sent names with two NUL
bytes.

It would be very kind of you to take a look at this issue.

Thank you for your time,
Tom Unbehau
Comment 1 Tom Unbehau 2022-05-23 15:50:34 UTC
Kernel stack trace:

[ 7444.858964] detected buffer overflow in strlen
[ 7444.858981] ------------[ cut here ]------------
[ 7444.858982] kernel BUG at lib/string_helpers.c:974!
[ 7444.858988] invalid opcode: 0000 [#1] PREEMPT SMP PTI
[ 7444.858992] CPU: 1 PID: 9583 Comm: main Not tainted 5.17.6-1-MANJARO #1 1e1d23d0a05f307a20d237ae367072b447c14fc7
[ 7444.858996] Hardware name: Dell Inc. Latitude E6530/0JC5MT, BIOS A21 02/21/2018
[ 7444.858998] RIP: 0010:fortify_panic+0xf/0x11
[ 7444.859006] Code: 18 c8 8e ac 48 89 d6 e8 70 c1 fe ff 49 8d 7c 24 e0 e8 e7 95 6b ff e9 cb a3 95 ff 48 89 fe 48 c7 c7 08 ca 8e ac e8 52 c1 fe ff <0f> 0b 48 8b 54 24 10 48 8b 74 24 08 4c 89 d1 48 c7 c7 46 ca 8e ac
[ 7444.859008] RSP: 0018:ffff9bf2c27cfa20 EFLAGS: 00010246
[ 7444.859011] RAX: 0000000000000022 RBX: ffff9bf2c27cfa62 RCX: 0000000000000000
[ 7444.859014] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[ 7444.859016] RBP: 000000000000001a R08: 0000000000000000 R09: 0000000000000000
[ 7444.859017] R10: 0000000000000000 R11: 0000000000000000 R12: 000000000000000a
[ 7444.859019] R13: 0000000000000013 R14: ffff8f6690e3e15b R15: ffff8f6690e3e063
[ 7444.859021] FS:  00007f3b871011c0(0000) GS:ffff8f6796280000(0000) knlGS:0000000000000000
[ 7444.859024] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 7444.859026] CR2: 00005585df8232b8 CR3: 0000000110eb6003 CR4: 00000000001706e0
[ 7444.859029] Call Trace:
[ 7444.859031]  <TASK>
[ 7444.859035]  append_eir_data_to_buf.cold+0x18/0x18 [bluetooth 61e060806c448e6b82ba4517e12fe79e828c6d57]
[ 7444.859082]  ext_info_changed.isra.0+0x3f/0xa0 [bluetooth 61e060806c448e6b82ba4517e12fe79e828c6d57]
[ 7444.859120]  set_local_name+0x1fa/0x280 [bluetooth 61e060806c448e6b82ba4517e12fe79e828c6d57]
[ 7444.859156]  hci_sock_sendmsg+0x923/0xa30 [bluetooth 61e060806c448e6b82ba4517e12fe79e828c6d57]
[ 7444.859193]  sock_sendmsg+0x64/0x70
[ 7444.859199]  __sys_sendto+0x128/0x1a0
[ 7444.859204]  __x64_sys_sendto+0x20/0x40
[ 7444.859207]  do_syscall_64+0x5c/0x90
[ 7444.859213]  ? vfs_write+0x203/0x2a0
[ 7444.859220]  ? syscall_exit_to_user_mode+0x23/0x50
[ 7444.859226]  ? do_syscall_64+0x69/0x90
[ 7444.859230]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 7444.859236] RIP: 0033:0x7f3b87216380
[ 7444.859239] Code: ff ff 64 89 02 eb bd 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 1d 45 31 c9 45 31 c0 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 68 c3 0f 1f 80 00 00 00 00 41 54 48 83 ec 20
[ 7444.859242] RSP: 002b:00007ffcd4b2dbd8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
[ 7444.859245] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f3b87216380
[ 7444.859248] RDX: 000000000000010a RSI: 00007ffcd4b2dc10 RDI: 0000000000000003
[ 7444.859250] RBP: 00007ffcd4b3dc20 R08: 0000000000000000 R09: 0000000000000000
[ 7444.859252] R10: 0000000000004000 R11: 0000000000000246 R12: 00007ffcd4b3dd38
[ 7444.859254] R13: 00005585dd83d396 R14: 00005585dd84fdc0 R15: 00007f3b87691000
[ 7444.859258]  </TASK>
[ 7444.859261] Modules linked in: rpcrdma rdma_cm iw_cm ib_cm ib_core pl2303 cdc_mbim cdc_ncm cdc_ether usbnet mii cdc_wdm cdc_acm uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_common videodev btusb intel_rapl_msr intel_rapl_common btrtl btbcm snd_usb_audio btintel btmtk bluetooth x86_pkg_temp_thermal snd_usbmidi_lib snd_hda_codec_hdmi snd_rawmidi intel_powerclamp dell_laptop snd_seq_device snd_hda_codec_idt mc ecdh_generic coretemp joydev mousedev kvm_intel snd_hda_codec_generic kvm snd_hda_intel snd_intel_dspcfg dell_wmi ledtrig_audio dell_smbios squashfs irqbypass loop mei_wdt iTCO_wdt snd_intel_sdw_acpi intel_pmc_bxt iwldvm mei_hdcp rapl mac80211 at24 snd_hda_codec dcdbas sparse_keymap wmi_bmof intel_cstate iTCO_vendor_support dell_smm_hwmon dell_wmi_descriptor ppdev i915 libarc4 snd_hda_core iwlwifi intel_uncore snd_hwdep vfat fat snd_pcm psmouse pcspkr cfg80211 i2c_i801 snd_timer mei_me i2c_smbus ttm snd lpc_ich e1000e tpm_tis mei intel_gtt soundcore wmi
[ 7444.859343]  tpm_tis_core parport_pc mac_hid dell_rbtn video parport dell_smo8800 rfkill nfsd auth_rpcgss nfs_acl lockd grace sunrpc uinput fuse crypto_user ip_tables x_tables ext4 crc32c_generic crc16 mbcache jbd2 dm_crypt cbc encrypted_keys dm_mod trusted asn1_encoder tee tpm rng_core usbhid serio_raw crct10dif_pclmul atkbd crc32_pclmul libps2 crc32c_intel ghash_clmulni_intel aesni_intel crypto_simd cryptd sdhci_pci sr_mod cqhci cdrom sdhci i8042 xhci_pci mmc_core xhci_pci_renesas serio
[ 7444.859413] ---[ end trace 0000000000000000 ]---
[ 7444.859414] RIP: 0010:fortify_panic+0xf/0x11
[ 7444.859419] Code: 18 c8 8e ac 48 89 d6 e8 70 c1 fe ff 49 8d 7c 24 e0 e8 e7 95 6b ff e9 cb a3 95 ff 48 89 fe 48 c7 c7 08 ca 8e ac e8 52 c1 fe ff <0f> 0b 48 8b 54 24 10 48 8b 74 24 08 4c 89 d1 48 c7 c7 46 ca 8e ac
[ 7444.859421] RSP: 0018:ffff9bf2c27cfa20 EFLAGS: 00010246
[ 7444.859423] RAX: 0000000000000022 RBX: ffff9bf2c27cfa62 RCX: 0000000000000000
[ 7444.859425] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[ 7444.859426] RBP: 000000000000001a R08: 0000000000000000 R09: 0000000000000000
[ 7444.859428] R10: 0000000000000000 R11: 0000000000000000 R12: 000000000000000a
[ 7444.859429] R13: 0000000000000013 R14: ffff8f6690e3e15b R15: ffff8f6690e3e063
[ 7444.859431] FS:  00007f3b871011c0(0000) GS:ffff8f6796280000(0000) knlGS:0000000000000000
[ 7444.859434] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 7444.859435] CR2: 00005585df8232b8 CR3: 0000000110eb6003 CR4: 00000000001706e0