-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
gh-111178: Fix getsockaddrarg() undefined behavior #131668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Don't pass direct references to sockaddr members since their type may not match PyArg_ParseTuple() types. Instead, use temporary 'int' and 'unsigned char' variables, and update sockaddr members afterwards.
Fix the following error:
|
@picnixz: This change looks like a bugfix, do you think that it should be backported to 3.12 and 3.13 branches? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are BTPROTO_RFCOMM
and BTPROTO_HCI
for non-NetBSD below also suffering from the same issue? And yes, it is a bugfix IMO even if the function is internal.
I didn't get UBsan warning/error on this code, so I prefer to leave it unchanged.
This function is called by sock.bind(), sock.connect() and sock.sendto() for example. |
At compile time I don't think there will be but at runtime it might be because the tests are not covering the calls
By internal I meant it's not documented (but yes it's called by many other functions) |
I added abort() in BTPROTO_RFCOMM and BTPROTO_HCI code paths and ran test_socket. Sadly, test_socket pass with my change, which means that these two code paths are not tested by test_socket. If it's not tested, I don't feel comfortable to modify these code paths. |
On Linux, the struct sockaddr_l2 {
sa_family_t l2_family;
unsigned short l2_psm;
bdaddr_t l2_bdaddr;
unsigned short l2_cid;
uint8_t l2_bdaddr_type;
}; l2_psm and l2_cid members are unsigned. So I'm not sure if my change is correct. |
On common platforms I afraid that there is a similar error for BTPROTO_RFCOMM: on Linux, FreeBSD and NetBSD the https://man.archlinux.org/man/l2cap.7.en |
Fix also BTPROTO_RFCOMM and BTPROTO_HCI code path.
I updated my PR to use @serhiy-storchaka @picnixz: Please review the updated PR. |
@@ -2094,11 +2109,13 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, | |||
return 0; | |||
#else /* __NetBSD__ || __DragonFly__ */ | |||
_BT_HCI_MEMB(addr, family) = AF_BLUETOOTH; | |||
if (!PyArg_ParseTuple(args, "i", &_BT_HCI_MEMB(addr, dev))) { | |||
unsigned short dev = _BT_HCI_MEMB(addr, dev); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is it defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a bunch of define
at the top of the file:
#if (defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H)) \
&& !defined(__NetBSD__) && !defined(__DragonFly__)
#define USE_BLUETOOTH 1
#if defined(__FreeBSD__)
...
#define _BT_HCI_MEMB(sa, memb) ((sa)->hci_##memb)
...
#elif defined(__NetBSD__) || defined(__DragonFly__) // <- unreachable
...
#define _BT_HCI_MEMB(sa, memb) ((sa)->bt_##memb)
#else
...
#define _BT_HCI_MEMB(sa, memb) ((sa)->hci_##memb)
...
#endif
#endif
But AFAICT, the elif defined(__NetBSD__) || defined(__DragonFly__)
is not possible at all since we're still in the big #if
where we want !defined(__NetBSD__) && !defined(__DragonFly__)
. So indeed, it looks like the macro wouldn't be defined here.
I think we should remove !defined(__NetBSD__) && !defined(__DragonFly__)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know about _BT_HCI_MEMB
. I asked on what platform the *_dev
member is defined, what its name and the structure name. Its turned out that it is hci_node
on FreeBSD and NetBSD. hci_dev
should exist on Linux.
🤖 New build scheduled with the buildbot fleet by @serhiy-storchaka for commit 18ed09e 🤖 Results will be shown at: https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F131668%2Fmerge If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again. |
Oh no, build fails on FreeBSD:
Unrelated failures. ARM64 Windows PR and ARM64 Windows Non-Debug PR: pythoninfo steps crash with exit code s390x Fedora Stable Clang PR, s390x RHEL8 PR, s390x RHEL9 PR: test_binary_header() of test_tools.test_msgfmt.CompilationTest failed. I don't know why, but it's unrelated to this change. |
(There's an open PR fixing |
This is weird, because on FreeBSD the It is not an integer, it is a null-terminated string (size == 32 == NG_NODESIZ == HCI_DEVNAME_SIZE). |
Alright, done. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, except that I am not sure about exception types.
The socket address channel is not initialized before calling PyArg_ParseTuple().
Thanks @vstinner for the PR 🌮🎉.. I'm working now to backport this PR to: 3.12, 3.13. |
Sorry, @vstinner, I could not cleanly backport this to
|
Sorry, @vstinner, I could not cleanly backport this to
|
Don't pass direct references to sockaddr members since their type may not match PyArg_ParseTuple() types. Instead, use temporary 'int' and 'unsigned char' variables, and update sockaddr members afterwards. On FreeBSD, treat BTPROTO_HCI node name as a bytes string, not as an integer. (cherry picked from commit 8cd29c2)
GH-131977 is a backport of this pull request to the 3.13 branch. |
Merged, thanks for reviews. |
…131977) gh-111178: Fix getsockaddrarg() undefined behavior (#131668) Don't pass direct references to sockaddr members since their type may not match PyArg_ParseTuple() types. Instead, use temporary 'int' and 'unsigned char' variables, and update sockaddr members afterwards. On FreeBSD, treat BTPROTO_HCI node name as a bytes string, not as an integer. (cherry picked from commit 8cd29c2)
…onGH-131668) (pythonGH-131977) pythongh-111178: Fix getsockaddrarg() undefined behavior (pythonGH-131668) Don't pass direct references to sockaddr members since their type may not match PyArg_ParseTuple() types. Instead, use temporary 'int' and 'unsigned char' variables, and update sockaddr members afterwards. On FreeBSD, treat BTPROTO_HCI node name as a bytes string, not as an integer. (cherry picked from commit c318a03) Co-authored-by: Victor Stinner <[email protected]> (cherry picked from commit 8cd29c2)
…GH-131977) (#131979) [3.13] gh-111178: Fix getsockaddrarg() undefined behavior (GH-131668) (GH-131977) gh-111178: Fix getsockaddrarg() undefined behavior (GH-131668) Don't pass direct references to sockaddr members since their type may not match PyArg_ParseTuple() types. Instead, use temporary 'int' and 'unsigned char' variables, and update sockaddr members afterwards. On FreeBSD, treat BTPROTO_HCI node name as a bytes string, not as an integer. (cherry picked from commit c318a03) Co-authored-by: Victor Stinner <[email protected]> (cherry picked from commit 8cd29c2) Co-authored-by: Victor Stinner <[email protected]>
|
|
Don't pass direct references to sockaddr members since their type may not match PyArg_ParseTuple() types. Instead, use temporary 'int' and 'unsigned char' variables, and update sockaddr members afterwards. On FreeBSD, treat BTPROTO_HCI node name as a bytes string, not as an integer.
Don't pass direct references to sockaddr members since their type may not match PyArg_ParseTuple() types. Instead, use temporary 'int' and 'unsigned char' variables, and update sockaddr members afterwards.