rfkill: Fix reading from rfkill socket
PATCH 1/1 rfkill: Fix reading from rfkill socket
From: Benjamin Berg <[email protected]>
The kernel will always send exactly one event, but the size of the passed struct will depend on the length of the submitted read() and the kernel version. i.e. the interface can be extended and we need to expect for a read to be longer than expected if we ask for it.
Fix this by only requesting the needed length and explicitly check the length against the V1 version of the structure to make the code a bit more future proof in case the internal copy of the struct is updated to contain new fields.
--- src/rfkill.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-)
src/rfkill.c +11 -13
@@ -53,12 +53,12 @@ struct rfkill_event {uint8_t soft;uint8_t hard; }; +#define RFKILL_EVENT_SIZE_V1 8static gboolean rfkill_event (GIOChannel *chan,GIOCondition cond,gpointer data) { -unsigned char buf[32 ]; -struct rfkill_event *event = (void *) buf; +struct rfkill_event event = {0 };struct btd_adapter *adapter;char sysname[PATH_MAX ];ssize_t len;
@@ -69,34 +69,32 @@ static gboolean rfkill_event(GIOChannel *chan, fd =g_io_channel_unix_get_fd (chan); -memset (buf,0 ,sizeof (buf)); - - len =read (fd, buf,sizeof (buf)); + len =read (fd, &event,sizeof (event));if (len <0 ) {if (errno ==EAGAIN )return TRUE;return FALSE; } -if (len !=sizeof (struct rfkill_event )) +if (len <RFKILL_EVENT_SIZE_V1 )return TRUE;DBG ("RFKILL event idx %u type %u op %u soft %u hard %u" , - event->idx, event->type, event->op, - event->soft, event->hard); + event.idx, event.type, event.op, + event.soft, event.hard); -if (event->soft || event->hard) +if (event.soft || event.hard)return TRUE; -if (event->op !=RFKILL_OP_CHANGE ) +if (event.op !=RFKILL_OP_CHANGE )return TRUE; -if (event->type !=RFKILL_TYPE_BLUETOOTH && - event->type !=RFKILL_TYPE_ALL ) +if (event.type !=RFKILL_TYPE_BLUETOOTH && + event.type !=RFKILL_TYPE_ALL )return TRUE;snprintf (sysname,sizeof (sysname) -1 , -"/sys/class/rfkill/rfkill%u/name" , event->idx); +"/sys/class/rfkill/rfkill%u/name" , event.idx); fd =open (sysname,O_RDONLY );if (fd <0 )
Signature · 1 line
2.31.1
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=476383
---Test result---
Test Summary:
CheckPatch PASS 0.56 seconds GitLint PASS 0.12 seconds Prep - Setup ELL PASS 45.13 seconds Build - Prep PASS 0.15 seconds Build - Configure PASS 7.93 seconds Build - Make PASS 191.25 seconds Make Check PASS 8.55 seconds Make Dist PASS 11.38 seconds Make Dist - Configure PASS 4.79 seconds Make Dist - Make PASS 77.65 seconds Build w/ext ELL - Configure PASS 7.91 seconds Build w/ext ELL - Make PASS 179.36 seconds
Details
##############################
Test: CheckPatch - PASS
Desc: Run checkpatch.pl script with rule in .checkpatch.conf
##############################
Test: GitLint - PASS
Desc: Run gitlint with rule in .gitlint
##############################
Test: Prep - Setup ELL - PASS
Desc: Clone, build, and install ELL
##############################
Test: Build - Prep - PASS
Desc: Prepare environment for build
##############################
Test: Build - Configure - PASS
Desc: Configure the BlueZ source tree
##############################
Test: Build - Make - PASS
Desc: Build the BlueZ source tree
##############################
Test: Make Check - PASS
Desc: Run 'make check'
##############################
Test: Make Dist - PASS
Desc: Run 'make dist' and build the distribution tarball
##############################
Test: Make Dist - Configure - PASS
Desc: Configure the source from distribution tarball
##############################
Test: Make Dist - Make - PASS
Desc: Build the source from distribution tarball
##############################
Test: Build w/ext ELL - Configure - PASS
Desc: Configure BlueZ source with '--enable-external-ell' configuration
##############################
Test: Build w/ext ELL - Make - PASS
Desc: Build BlueZ source with '--enable-external-ell' configuration
---
Regards,
Linux Bluetooth
Quoted 8 lines · Benjamin Berg
From: Benjamin Berg <[email protected]>
The kernel will always send exactly one event, but the size of the passed struct will depend on the length of the submitted
read()and the kernel version. i.e. the interface can be extended and we need to expect
for a read to be longer than expected if we ask for it.
Quoted 4 lines
Fix this by only requesting the needed length and explicitly check the length against the V1 version of the structure to make the code a bit more future proof in case the internal copy of the struct is updated to contain new fields.
This fixes a bug in GNOME where to enable Bluetooth, we removed a soft rfkill block on the Bluetooth interface.
Without this, the bluetooth rfkill gets unblocked, but bluetoothd doesn't see it as unblocked so never powers it on, causing the UI to appear broken, as we expect Bluetooth devices to be either blocked through rfkill, or powered on.
The equivalent gnome-settings-daemon fix (which deals with rfkill) was reviewed by Hans de Goede:
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/merge_requests/234
Benjamin, it might be worth resending this with a better commit message explaining exactly what it fixes and referencing the gnome-bluetooth bug:
https://gitlab.gnome.org/GNOME/gnome-bluetooth/-/issues/38
Cheers
Quoted 71 lines
---
src/rfkill.c | 24 +++++++++++-------------1 file changed, 11 insertions(+), 13 deletions(-)src/rfkill.c +1
-0@@ -53,12 +53,12 @@ struct rfkill_event { uint8_t soft; uint8_t hard; }; +#define RFKILL_EVENT_SIZE_V1 8
static gbooleanrfkill_event(GIOChannel *chan, GIOCondition cond, gpointer data){
- unsigned char buf[32];
- structrfkill_event*event = (void *) buf;
+ structrfkill_eventevent = { 0 };
structbtd_adapter*adapter;
char sysname[PATH_MAX];
ssize_t len;src/rfkill.c +0
-0@@ -69,34 +69,32 @@ static gboolean rfkill_event(GIOChannel *chan,
fd =g_io_channel_unix_get_fd(chan);
- memset(buf, 0, sizeof(buf));
-
- len =read(fd, buf, sizeof(buf));
+ len =read(fd, &event, sizeof(event));
if (len < 0) {
if (errno == EAGAIN)
return TRUE;
return FALSE;
}
- if (len !=sizeof(struct rfkill_event))
+ if (len <RFKILL_EVENT_SIZE_V1)
return TRUE;
DBG("RFKILL event idx %u type %u op %u soft %u hard %u", - event->idx,event->type, event-Quoted 1 line
op,
- event->soft, event-
Quoted 1 line
hard);
+ event.idx, event.type, event.op,
+ event.soft, event.hard);
- if (event->soft||event->hard)
+ if (event.soft || event.hard)
return TRUE;
- if (event->op!=RFKILL_OP_CHANGE)
+ if (event.op !=RFKILL_OP_CHANGE)
return TRUE;
- if (event->type!=RFKILL_TYPE_BLUETOOTH&&
- event->type !=RFKILL_TYPE_ALL) + if (event.type !=RFKILL_TYPE_BLUETOOTH&&
+ event.type !=RFKILL_TYPE_ALL) return TRUE;
snprintf(sysname, sizeof(sysname) - 1,
- "/sys/class/rfkill/rfkill%u/name",event->idx); + "/sys/class/rfkill/rfkill%u/name", event.idx);
fd =open(sysname, O_RDONLY);
if (fd < 0)
Quoted 25 lines · Bastien Nocera
Quoted 9 lines · Benjamin Berg
From: Benjamin Berg <[email protected]>
The kernel will always send exactly one event, but the size of the passed struct will depend on the length of the submitted
read()and the
kernel version. i.e. the interface can be extended and we need to expect
for a read to be longer than expected if we ask for it.Quoted 6 lines
Fix this by only requesting the needed length and explicitly check the
length against the V1 version of the structure to make the code a bit more future proof in case the internal copy of the struct is updated to
contain new fields.This fixes a bug in GNOME where to enable Bluetooth, we removed a soft rfkill block on the Bluetooth interface.
Without this, the bluetooth rfkill gets unblocked, but bluetoothd doesn't see it as unblocked so never powers it on, causing the UI to appear broken, as we expect Bluetooth devices to be either blocked through rfkill, or powered on.
Quoted 10 lines
The equivalent gnome-settings-daemon fix (which deals with rfkill) was reviewed by Hans de Goede:
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/merge_requests/234Benjamin, it might be worth resending this with a better commit message explaining exactly what it fixes and referencing the gnome-bluetooth bug:
https://gitlab.gnome.org/GNOME/gnome-bluetooth/-/issues/38
It's also been pushed to Fedora rawhide and Fedora 34:
https://bodhi.fedoraproject.org/updates/FEDORA-2021-2cd83da751
Luiz Augusto von Dentz
maintainerHi,
Quoted 31 lines · Bastien Nocera
Quoted 29 lines · Bastien Nocera
Quoted 9 lines · Benjamin Berg
From: Benjamin Berg <[email protected]>
The kernel will always send exactly one event, but the size of the passed struct will depend on the length of the submitted
read()and the
kernel version. i.e. the interface can be extended and we need to expect
for a read to be longer than expected if we ask for it.Quoted 6 lines
Fix this by only requesting the needed length and explicitly check the
length against the V1 version of the structure to make the code a bit more future proof in case the internal copy of the struct is updated to
contain new fields.This fixes a bug in GNOME where to enable Bluetooth, we removed a soft rfkill block on the Bluetooth interface.
Without this, the bluetooth rfkill gets unblocked, but bluetoothd doesn't see it as unblocked so never powers it on, causing the UI to appear broken, as we expect Bluetooth devices to be either blocked through rfkill, or powered on.
The equivalent gnome-settings-daemon fix (which deals with rfkill) was reviewed by Hans de Goede:
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/merge_requests/234
Quoted 8 lines
Quoted 6 lines
Benjamin, it might be worth resending this with a better commit message explaining exactly what it fixes and referencing the gnome-bluetooth bug:
https://gitlab.gnome.org/GNOME/gnome-bluetooth/-/issues/38It's also been pushed to Fedora rawhide and Fedora 34:
https://bodhi.fedoraproject.org/updates/FEDORA-2021-2cd83da751
I missed this one for some reason, it has been applied now.
Signature · 1 line
Luiz Augusto von Dentz