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:
Thomas Zimmermann 2015-01-20 10:17:45 +08:00
parent b65367839d
commit 2eed89da86
2 changed files with 72 additions and 8 deletions

View File

@ -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;

View File

@ -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;