mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 1119746: Support random postfix for Bluetooth daemon socket name, r=btian
This patch adds support for a random postfix for bluetoothd's socket name. The postfix is re-generated for every instance of the daemon. This prevents name collisions between mutliple sessions and malicious programs from taking over the connection easily.
This commit is contained in:
parent
b65367839d
commit
2eed89da86
@ -7,6 +7,7 @@
|
||||
#include "BluetoothDaemonInterface.h"
|
||||
#include <cutils/properties.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include "BluetoothDaemonA2dpInterface.h"
|
||||
#include "BluetoothDaemonAvrcpInterface.h"
|
||||
#include "BluetoothDaemonHandsfreeInterface.h"
|
||||
@ -17,6 +18,7 @@
|
||||
#include "mozilla/ipc/ListenSocket.h"
|
||||
#include "mozilla/ipc/UnixSocketConnector.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "prrng.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
@ -1822,10 +1824,13 @@ BluetoothDaemonInterface::OnConnectSuccess(enum Channel aChannel)
|
||||
MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
|
||||
|
||||
switch (aChannel) {
|
||||
case LISTEN_SOCKET:
|
||||
// Init, step 2: Start Bluetooth daemon */
|
||||
if (NS_WARN_IF(property_set("ctl.start", "bluetoothd") < 0)) {
|
||||
OnConnectError(CMD_CHANNEL);
|
||||
case LISTEN_SOCKET: {
|
||||
// Init, step 2: Start Bluetooth daemon */
|
||||
nsCString value("bluetoothd:-a ");
|
||||
value.Append(mListenSocketName);
|
||||
if (NS_WARN_IF(property_set("ctl.start", value.get()) < 0)) {
|
||||
OnConnectError(CMD_CHANNEL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMD_CHANNEL:
|
||||
@ -1984,6 +1989,46 @@ private:
|
||||
nsCString mSocketName;
|
||||
};
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonInterface::CreateRandomAddressString(
|
||||
const nsACString& aPrefix, unsigned long aPostfixLength,
|
||||
nsACString& aAddress)
|
||||
{
|
||||
static const char sHexChar[16] = {
|
||||
[0x0] = '0', [0x1] = '1', [0x2] = '2', [0x3] = '3',
|
||||
[0x4] = '4', [0x5] = '5', [0x6] = '6', [0x7] = '7',
|
||||
[0x8] = '8', [0x9] = '9', [0xa] = 'a', [0xb] = 'b',
|
||||
[0xc] = 'c', [0xd] = 'd', [0xe] = 'e', [0xf] = 'f'
|
||||
};
|
||||
|
||||
unsigned short seed[3];
|
||||
|
||||
if (NS_WARN_IF(!PR_GetRandomNoise(seed, sizeof(seed)))) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
aAddress = aPrefix;
|
||||
aAddress.Append('-');
|
||||
|
||||
while (aPostfixLength) {
|
||||
|
||||
// Android doesn't provide rand_r, so we use nrand48 here,
|
||||
// even though it's deprecated.
|
||||
long value = nrand48(seed);
|
||||
|
||||
size_t bits = sizeof(value) * CHAR_BIT;
|
||||
|
||||
while ((bits > 4) && aPostfixLength) {
|
||||
aAddress.Append(sHexChar[value&0xf]);
|
||||
bits -= 4;
|
||||
value >>= 4;
|
||||
--aPostfixLength;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* The init procedure consists of several steps.
|
||||
*
|
||||
@ -2020,9 +2065,11 @@ BluetoothDaemonInterface::Init(
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
static const char BASE_SOCKET_NAME[] = "bluetoothd";
|
||||
static unsigned long POSTFIX_LENGTH = 16;
|
||||
|
||||
// If we could not cleanup before and an old instance of the
|
||||
// daemon is still running, we kill it here.
|
||||
// If we could not cleanup properly before and an old
|
||||
// instance of the daemon is still running, we kill it
|
||||
// here.
|
||||
unused << NS_WARN_IF(property_set("ctl.stop", "bluetoothd"));
|
||||
|
||||
sNotificationHandler = aNotificationHandler;
|
||||
@ -2047,9 +2094,21 @@ BluetoothDaemonInterface::Init(
|
||||
mCmdChannel->CloseSocket();
|
||||
}
|
||||
|
||||
// The listen socket's name is generated with a random postfix. This
|
||||
// avoids naming collisions if we still have a listen socket from a
|
||||
// previously failed cleanup. It also makes it hard for malicious
|
||||
// external programs to capture the socket name or connect before
|
||||
// the daemon can do so. If no random postfix can be generated, we
|
||||
// simply use the base name as-is.
|
||||
nsresult rv = CreateRandomAddressString(NS_LITERAL_CSTRING(BASE_SOCKET_NAME),
|
||||
POSTFIX_LENGTH,
|
||||
mListenSocketName);
|
||||
if (NS_FAILED(rv)) {
|
||||
mListenSocketName = BASE_SOCKET_NAME;
|
||||
}
|
||||
|
||||
bool success = mListenSocket->Listen(
|
||||
new BluetoothDaemonSocketConnector(NS_LITERAL_CSTRING(BASE_SOCKET_NAME)),
|
||||
mCmdChannel);
|
||||
new BluetoothDaemonSocketConnector(mListenSocketName), mCmdChannel);
|
||||
if (!success) {
|
||||
OnConnectError(CMD_CHANNEL);
|
||||
return;
|
||||
|
@ -129,9 +129,14 @@ protected:
|
||||
void OnConnectError(enum Channel aChannel);
|
||||
void OnDisconnect(enum Channel aChannel);
|
||||
|
||||
nsresult CreateRandomAddressString(const nsACString& aPrefix,
|
||||
unsigned long aPostfixLength,
|
||||
nsACString& aAddress);
|
||||
|
||||
private:
|
||||
void DispatchError(BluetoothResultHandler* aRes, BluetoothStatus aStatus);
|
||||
|
||||
nsCString mListenSocketName;
|
||||
nsRefPtr<BluetoothDaemonListenSocket> mListenSocket;
|
||||
nsRefPtr<BluetoothDaemonChannel> mCmdChannel;
|
||||
nsRefPtr<BluetoothDaemonChannel> mNtfChannel;
|
||||
|
Loading…
Reference in New Issue
Block a user