Project

General

Profile

Actions

Exynos modem isolation

This article talks about a very serious freedom, privacy and security issue we found during Replicant development on several devices.

On some devices, we found that the modem wasn't isolated and was potentially able to read and write part of the RAM used by Replicant.

Note that the versions of Replicant that are still being maintained don't support any of the affected devices anymore.

However some of these devices are still supported in libsamsung-ipc as Replicant has to maintain libsamsung-ipc and that other projects are interested in supporting such devices.

There also might be a way to completely prevent the issue, by making sure that the RAM chip shared with the modem is not used for other things than communicating with the modem, but so far no one succeded yet.

Affected devices:

At least the following devices are affected:

  • Galaxy S (GT-I9000)
  • Nexus S (GT-I9020)
  • Nexus S (GT-I9020A)
  • Nexus S (GT-I9023)

Other similar devices that are not supported by Replicant are probably affected as well.

Hardware design matrix

Chip Controlled by the CPU Controlled by the modem Connected to the modem
GPS Yes No No?
Audio CODEC Yes No Yes
NAND Yes No No
RAM Yes Yes (96Mib at least) Yes
WiFi/Bluetooth Yes No No
Sensors Yes No No
NFC Yes No No
Camera Yes No No

Modem isolation

The modem (XMM 6160) is separated from the System on a chip and communicates with it over 16Mib of shared memory that comes from a 96MiB RAM chip.

The issue is that the remaining 80M of this RAM chip are also used as normal RAM by the CPU running Replicant.

Because of that, we don't have any assurance that the modem cannot read and write all the memory in that RAM chip, enabling it to either passively monitor what is going on, and/or to take control of the CPU running Replicant.

While the hardware design could ensure that only some lines of the data address are made accessible to the modem, we don't have enough documentation to verify that, and even if it was the case it couldn't be guaranteed for every single device used with Replicant.

This is bad: it means that RAM in general is potentially compromised.

Regarding audio, the modem is connected to the CODEC but cannot control it (the SoC has to enable routing from/to the modem).
There is no evidence that the GPS is connected to the modem, but since we cannot check on the hardware, there is no proof it's not connected to it either. The SoC is able to control the GPS power though, so we can keep it off.
Since the SoC has to load the modem firmware over the (fake) serial, and following the datasheets, the modem is not connected to the NAND.

The modem is potentially able to read and write (at least) 96 Mib of the main memory. So far, we cannot tell:
  • if it can only spy 80Mib or the full memory
  • if it can be fixed or not

The Linux kernel is being loaded at the beginning of the shared memory bank (0x30000000), however the kernel should be off when it loads.

Nexus S (GT-I902x) Kernel details

In kernel-crespo/arch/arm/mach-s5pv210/dev-herring-phone.c we have:

static struct resource mdmctl_res[] = {
[...]
        [2] = {
                .name = "onedram",
                .start = (S5PV210_PA_SDRAM + 0x05000000),
                .end = (S5PV210_PA_SDRAM + 0x05000000 + SZ_16M - 1),
                .flags = IORESOURCE_MEM,
        },
};

  • S5PV210_PA_SDRAM is 0x30000000
  • 0x05000000 is 80Mib
  • mdmctl_res goes in a platform device struct which is passed to the modem driver:
static struct platform_device modemctl = {
        .name = "modemctl",
        .id = -1,
        .num_resources = ARRAY_SIZE(mdmctl_res),
        .resource = mdmctl_res,
        .dev = {
                .platform_data = &mdmctl_data,
        },
};

And in the board file, in kernel-crespo/arch/arm/mach-s5pv210/mach-herring.c we have:

static void __init herring_fixup(struct machine_desc *desc,
                struct tag *tags, char **cmdline,
                struct meminfo *mi)
{
        mi->bank[0].start = 0x30000000;
        mi->bank[0].size = 80 * SZ_1M;
        mi->bank[0].node = 0;
        [...]
}

So for this RAM chip we have:

CPU physical address range Usage
0x30000000 -> 0x30000000 + 80MiB -1 System RAM
0x30000000 + 80MiB -> 0x30000000 + 80MiB + 16MiB - 1 Modem shared memory

So we can suppose that there is at least one ram chip that is shared between the modem and the main CPU. Avoiding the use of this memory bank would result in loosing at least 80Mib of memory.

Galaxy S (GT-I9000) Kernel details

In arch/arm/mach-s5pv210/dev-s1-phone.c we have:

static struct resource onedram_res[] = {
[...]
    [0] = {
        .start = (S5PV210_PA_SDRAM + 0x05000000),
        .end = (S5PV210_PA_SDRAM + 0x05000000 + SZ_16M - 1),
        .flags = IORESOURCE_MEM,
        },
};

  • S5PV210_PA_SDRAM is 0x30000000
  • 0x05000000 is 80Mib
  • mdmctl_res goes in a platform device struct which is passed to the modem driver:
static struct platform_device onedram = {
        .name = "onedram",
        .id = -1,
        .num_resources = ARRAY_SIZE(onedram_res),
        .resource = onedram_res,
        .dev = {
            .platform_data = &onedram_data,
            },
        };

And in the board file, in arch/arm/mach-s5pv210/mach-aries.c we have:

static void __init aries_fixup(struct machine_desc *desc,
        struct tag *tags, char **cmdline,
        struct meminfo *mi)
{
    mi->bank[0].start = 0x30000000;
    mi->bank[0].size = 80 * SZ_1M;
        [...]
}

So for this RAM chip we have:

CPU physical address range Usage
0x30000000 -> 0x30000000 + 80MiB -1 System RAM
0x30000000 + 80MiB -> 0x30000000 + 80MiB + 16MiB - 1 Modem shared memory

So we can suppose that there is at least one ram chip that is shared between the modem and the main CPU. Avoiding the use of this memory bank would result in loosing at least 80Mib of memory.

Workaround attempt

It might be possible to limit the amount of damage by relying on the fact that the modem has to be booted by Replicant, and make sure that the RAM chip that is shared with the modem isn't used for other things than this memory sharing.

This would make us lose about 80Mib of RAM, and the shared memory would still be used for SoC/Modem communication but as the RAM chip would be used only for that, so the modem would not be able read and write problematic data on it.

We would also need to make sure that the booloader doesn't load the kernel in that region or that the kernel is relocated to some other region before intializing the modem.

The current diff with the Nexus S kernel is here, but it doesn't boot at all with the following changes (and mkbootimg changes):

diff --git a/arch/arm/configs/herring_defconfig b/arch/arm/configs/herring_defconfig
old mode 100755
new mode 100644
index 11abbf0..99bf3f5
--- a/arch/arm/configs/herring_defconfig
+++ b/arch/arm/configs/herring_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.35.7
-# Fri Jun  3 07:07:08 2011
+# Sun Apr  8 14:40:16 2012
 #
 CONFIG_ARM=y
 CONFIG_HAVE_PWM=y
@@ -418,8 +418,8 @@ CONFIG_ALIGNMENT_TRAP=y
 #
 CONFIG_ZBOOT_ROM_TEXT=0
 CONFIG_ZBOOT_ROM_BSS=0
-CONFIG_CMDLINE="console=ttyFIQ0" 
-# CONFIG_CMDLINE_FORCE is not set
+CONFIG_CMDLINE="console=ttyFIQ0 no_console_suspend earlyprintk=serial,ttySAC2,115200 androidboot.serialno=3733BAB66DE200EC androidboot.bootloader=I9020XXKA3 androidboot.baseband=I9020XXKB3 androidboot.info=0x4,0x0,1 androidboot.carrier=EUR gain_code=3 s3cfb.bootloaderfb=0x34a00000 mach-herring.lcd_type=0x00000000 oem_state=unlocked" 
+CONFIG_CMDLINE_FORCE=y
 # CONFIG_XIP_KERNEL is not set
 # CONFIG_KEXEC is not set

@@ -823,8 +823,6 @@ CONFIG_UEVENT_HELPER_PATH="" 
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_EXTRA_FIRMWARE="" 
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -835,7 +833,7 @@ CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
 # CONFIG_MTD_AR7_PARTS is not set

@@ -1191,6 +1189,7 @@ CONFIG_DEVKMEM=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_UARTS_4=y
 CONFIG_SERIAL_SAMSUNG_UARTS=4
+# CONFIG_SERIAL_SAMSUNG_DEBUG is not set
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
 CONFIG_SERIAL_S5PV210=y
 # CONFIG_SERIAL_MAX3100 is not set
@@ -2046,7 +2045,9 @@ CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_ICEDCC is not set
 CONFIG_OC_ETM=y
 CONFIG_DEBUG_S3C_UART=2

diff --git a/arch/arm/mach-s5pv210/dev-herring-phone.c b/arch/arm/mach-s5pv210/dev-herring-phone.c
index f8798b3..ecef636 100755
--- a/arch/arm/mach-s5pv210/dev-herring-phone.c
+++ b/arch/arm/mach-s5pv210/dev-herring-phone.c
@@ -48,8 +48,8 @@ static struct resource mdmctl_res[] = {
     },
     [2] = {
         .name = "onedram",
-        .start = (S5PV210_PA_SDRAM + 0x05000000),
-        .end = (S5PV210_PA_SDRAM + 0x05000000 + SZ_16M - 1),
+        .start = (0x30000000  + 0x05000000),
+        .end = (0x30000000  + 0x05000000 + SZ_16M - 1),
         .flags = IORESOURCE_MEM,
     },
 };
diff --git a/arch/arm/mach-s5pv210/mach-herring.c b/arch/arm/mach-s5pv210/mach-herring.c
index c3a0182..67fa1cf 100755
--- a/arch/arm/mach-s5pv210/mach-herring.c
+++ b/arch/arm/mach-s5pv210/mach-herring.c
@@ -5494,21 +5494,17 @@ static void __init herring_fixup(struct machine_desc *desc,
         struct tag *tags, char **cmdline,
         struct meminfo *mi)
 {
-    mi->bank[0].start = 0x30000000;
-    mi->bank[0].size = 80 * SZ_1M;
+    mi->bank[0].start = 0x40000000;
+    mi->bank[0].size = 256 * SZ_1M;
     mi->bank[0].node = 0;

-    mi->bank[1].start = 0x40000000;
-    mi->bank[1].size = 256 * SZ_1M;
-    mi->bank[1].node = 1;
-
-    mi->bank[2].start = 0x50000000;
+    mi->bank[1].start = 0x50000000;
     /* 1M for ram_console buffer */
-    mi->bank[2].size = 127 * SZ_1M;
-    mi->bank[2].node = 2;
-    mi->nr_banks = 3;
+    mi->bank[1].size = 127 * SZ_1M;
+    mi->bank[1].node = 1;
+    mi->nr_banks = 2;

-    ram_console_start = mi->bank[2].start + mi->bank[2].size;
+    ram_console_start = mi->bank[1].start + mi->bank[1].size;
     ram_console_size = SZ_1M - SZ_4K;

     pm_debug_scratchpad = ram_console_start + ram_console_size;
diff --git a/BoardConfigCommon.mk b/BoardConfigCommon.mk
index fff6d1b..c09d935 100755
--- a/BoardConfigCommon.mk
+++ b/BoardConfigCommon.mk
@@ -51,10 +51,10 @@ DEFAULT_FB_NUM := 2

 BOARD_NAND_PAGE_SIZE := 4096 -s 128

-BOARD_KERNEL_BASE := 0x30000000
+BOARD_KERNEL_BASE := 0x40000000
 BOARD_KERNEL_PAGESIZE := 4096
-BOARD_KERNEL_CMDLINE := console=ttyFIQ0 no_console_suspend
-
+BOARD_KERNEL_CMDLINE := console=ttyFIQ0 no_console_suspend earlyprintk=serial,ttySAC2,115200 bootmem_debug
+BOARD_FORCE_RAMDISK_ADDRESS := 0x41000000
 #TARGET_RECOVERY_UI_LIB := librecovery_ui_crespo
 TARGET_RELEASETOOLS_EXTENSIONS := device/samsung/crespo

Updated by Denis 'GNUtoo' Carikli 4 months ago · 23 revisions