2015-12-02 20:28:42

by Kees Cook

[permalink] [raw]
Subject: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of
kernel self-protection:
http://www.openwall.com/lists/kernel-hardening/2015/11/30/13
Additionally, its name has grown to mean things beyond just rodata. To
get ARM closer to this, we ought to rearrange the names of the configs
that control how the kernel protects its memory. What was called
CONFIG_ARM_KERNMEM_PERMS is really doing the work that other architectures
call CONFIG_DEBUG_RODATA.

This redefines CONFIG_DEBUG_RODATA to actually do the bulk of the
ROing (and NXing). In the place of the old CONFIG_DEBUG_RODATA, use
CONFIG_DEBUG_ALIGN_RODATA, since that's what the option does: adds
section alignment for making rodata explicitly NX, as arm does not split
the page tables like arm64 does without _ALIGN_RODATA.

Also adds human readable names to the sections so I could more easily
debug my typos, and makes CONFIG_DEBUG_RODATA default "y" for CPU_V7.

Results in /sys/kernel/debug/kernel_page_tables for each config state:

# CONFIG_DEBUG_RODATA is not set
# CONFIG_DEBUG_ALIGN_RODATA is not set

---[ Kernel Mapping ]---
0x80000000-0x80900000 9M RW x SHD
0x80900000-0xa0000000 503M RW NX SHD

CONFIG_DEBUG_RODATA=y
CONFIG_DEBUG_ALIGN_RODATA=y

---[ Kernel Mapping ]---
0x80000000-0x80100000 1M RW NX SHD
0x80100000-0x80700000 6M ro x SHD
0x80700000-0x80a00000 3M ro NX SHD
0x80a00000-0xa0000000 502M RW NX SHD

CONFIG_DEBUG_RODATA=y
# CONFIG_DEBUG_ALIGN_RODATA is not set

---[ Kernel Mapping ]---
0x80000000-0x80100000 1M RW NX SHD
0x80100000-0x80a00000 9M ro x SHD
0x80a00000-0xa0000000 502M RW NX SHD

Signed-off-by: Kees Cook <[email protected]>
---
Depends on 8464/1 "Update all mm structures with section adjustments"
---
arch/arm/kernel/vmlinux.lds.S | 10 +++++-----
arch/arm/mm/Kconfig | 34 ++++++++++++++++++----------------
arch/arm/mm/init.c | 19 ++++++++++---------
3 files changed, 33 insertions(+), 30 deletions(-)

diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 8b60fde5ce48..a6e395c53a48 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -8,7 +8,7 @@
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/page.h>
-#ifdef CONFIG_ARM_KERNMEM_PERMS
+#ifdef CONFIG_DEBUG_RODATA
#include <asm/pgtable.h>
#endif

@@ -94,7 +94,7 @@ SECTIONS
HEAD_TEXT
}

-#ifdef CONFIG_ARM_KERNMEM_PERMS
+#ifdef CONFIG_DEBUG_RODATA
. = ALIGN(1<<SECTION_SHIFT);
#endif

@@ -117,7 +117,7 @@ SECTIONS
ARM_CPU_KEEP(PROC_INFO)
}

-#ifdef CONFIG_DEBUG_RODATA
+#ifdef CONFIG_DEBUG_ALIGN_RODATA
. = ALIGN(1<<SECTION_SHIFT);
#endif
RO_DATA(PAGE_SIZE)
@@ -153,7 +153,7 @@ SECTIONS
_etext = .; /* End of text and rodata section */

#ifndef CONFIG_XIP_KERNEL
-# ifdef CONFIG_ARM_KERNMEM_PERMS
+# ifdef CONFIG_DEBUG_RODATA
. = ALIGN(1<<SECTION_SHIFT);
# else
. = ALIGN(PAGE_SIZE);
@@ -231,7 +231,7 @@ SECTIONS
__data_loc = ALIGN(4); /* location in binary */
. = PAGE_OFFSET + TEXT_OFFSET;
#else
-#ifdef CONFIG_ARM_KERNMEM_PERMS
+#ifdef CONFIG_DEBUG_RODATA
. = ALIGN(1<<SECTION_SHIFT);
#else
. = ALIGN(THREAD_SIZE);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 41218867a9a6..68331f91c90f 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -1039,24 +1039,26 @@ config ARCH_SUPPORTS_BIG_ENDIAN
This option specifies the architecture can support big endian
operation.

-config ARM_KERNMEM_PERMS
- bool "Restrict kernel memory permissions"
+config DEBUG_RODATA
+ bool "Make kernel text and rodata read-only"
depends on MMU
+ default y if CPU_V7
help
- If this is set, kernel memory other than kernel text (and rodata)
- will be made non-executable. The tradeoff is that each region is
- padded to section-size (1MiB) boundaries (because their permissions
- are different and splitting the 1M pages into 4K ones causes TLB
- performance problems), wasting memory.
+ If this is set, kernel text and rodata memory will be made
+ read-only, and non-text kernel memory will be made non-executable.
+ The tradeoff is that each region is padded to section-size (1MiB)
+ boundaries (because their permissions are different and splitting
+ the 1M pages into 4K ones causes TLB performance problems), which
+ can waste memory.

-config DEBUG_RODATA
- bool "Make kernel text and rodata read-only"
- depends on ARM_KERNMEM_PERMS
+config DEBUG_ALIGN_RODATA
+ bool "Make rodata strictly non-executable"
+ depends on DEBUG_RODATA
default y
help
- If this is set, kernel text and rodata will be made read-only. This
- is to help catch accidental or malicious attempts to change the
- kernel's executable code. Additionally splits rodata from kernel
- text so it can be made explicitly non-executable. This creates
- another section-size padded region, so it can waste more memory
- space while gaining the read-only protections.
+ If this is set, rodata will be made explicitly non-executable. This
+ provides protection on the rare chance that attackers might find and
+ use ROP gadgets that exist in the rodata section. This adds an
+ additional section-aligned split of rodata from kernel text so it
+ can be made explicitly non-executable. This padding may waste memory
+ space to gain the additional protection.
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 7f8cd1b3557f..321d3683dc7c 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -569,8 +569,9 @@ void __init mem_init(void)
}
}

-#ifdef CONFIG_ARM_KERNMEM_PERMS
+#ifdef CONFIG_DEBUG_RODATA
struct section_perm {
+ const char *name;
unsigned long start;
unsigned long end;
pmdval_t mask;
@@ -581,6 +582,7 @@ struct section_perm {
static struct section_perm nx_perms[] = {
/* Make pages tables, etc before _stext RW (set NX). */
{
+ .name = "pre-text NX",
.start = PAGE_OFFSET,
.end = (unsigned long)_stext,
.mask = ~PMD_SECT_XN,
@@ -588,14 +590,16 @@ static struct section_perm nx_perms[] = {
},
/* Make init RW (set NX). */
{
+ .name = "init NX",
.start = (unsigned long)__init_begin,
.end = (unsigned long)_sdata,
.mask = ~PMD_SECT_XN,
.prot = PMD_SECT_XN,
},
-#ifdef CONFIG_DEBUG_RODATA
+#ifdef CONFIG_DEBUG_ALIGN_RODATA
/* Make rodata NX (set RO in ro_perms below). */
{
+ .name = "rodata NX",
.start = (unsigned long)__start_rodata,
.end = (unsigned long)__init_begin,
.mask = ~PMD_SECT_XN,
@@ -604,10 +608,10 @@ static struct section_perm nx_perms[] = {
#endif
};

-#ifdef CONFIG_DEBUG_RODATA
static struct section_perm ro_perms[] = {
/* Make kernel code and rodata RX (set RO). */
{
+ .name = "text/rodata RO",
.start = (unsigned long)_stext,
.end = (unsigned long)__init_begin,
#ifdef CONFIG_ARM_LPAE
@@ -620,7 +624,6 @@ static struct section_perm ro_perms[] = {
#endif
},
};
-#endif

/*
* Updates section permissions only for the current mm (sections are
@@ -667,8 +670,8 @@ void set_section_perms(struct section_perm *perms, int n, bool set,
for (i = 0; i < n; i++) {
if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) ||
!IS_ALIGNED(perms[i].end, SECTION_SIZE)) {
- pr_err("BUG: section %lx-%lx not aligned to %lx\n",
- perms[i].start, perms[i].end,
+ pr_err("BUG: %s section %lx-%lx not aligned to %lx\n",
+ perms[i].name, perms[i].start, perms[i].end,
SECTION_SIZE);
continue;
}
@@ -709,7 +712,6 @@ void fix_kernmem_perms(void)
stop_machine(__fix_kernmem_perms, NULL, NULL);
}

-#ifdef CONFIG_DEBUG_RODATA
int __mark_rodata_ro(void *unused)
{
update_sections_early(ro_perms, ARRAY_SIZE(ro_perms));
@@ -732,11 +734,10 @@ void set_kernel_text_ro(void)
set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
current->active_mm);
}
-#endif /* CONFIG_DEBUG_RODATA */

#else
static inline void fix_kernmem_perms(void) { }
-#endif /* CONFIG_ARM_KERNMEM_PERMS */
+#endif /* CONFIG_DEBUG_RODATA */

void free_tcmmem(void)
{
--
1.9.1


--
Kees Cook
Chrome OS & Brillo Security


2015-12-03 00:05:12

by Laura Abbott

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

On 12/02/2015 12:27 PM, Kees Cook wrote:
> The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of
> kernel self-protection:
> http://www.openwall.com/lists/kernel-hardening/2015/11/30/13
> Additionally, its name has grown to mean things beyond just rodata. To
> get ARM closer to this, we ought to rearrange the names of the configs
> that control how the kernel protects its memory. What was called
> CONFIG_ARM_KERNMEM_PERMS is really doing the work that other architectures
> call CONFIG_DEBUG_RODATA.
>
> This redefines CONFIG_DEBUG_RODATA to actually do the bulk of the
> ROing (and NXing). In the place of the old CONFIG_DEBUG_RODATA, use
> CONFIG_DEBUG_ALIGN_RODATA, since that's what the option does: adds
> section alignment for making rodata explicitly NX, as arm does not split
> the page tables like arm64 does without _ALIGN_RODATA.
>
> Also adds human readable names to the sections so I could more easily
> debug my typos, and makes CONFIG_DEBUG_RODATA default "y" for CPU_V7.
>
> Results in /sys/kernel/debug/kernel_page_tables for each config state:
>
> # CONFIG_DEBUG_RODATA is not set
> # CONFIG_DEBUG_ALIGN_RODATA is not set
>
> ---[ Kernel Mapping ]---
> 0x80000000-0x80900000 9M RW x SHD
> 0x80900000-0xa0000000 503M RW NX SHD
>
> CONFIG_DEBUG_RODATA=y
> CONFIG_DEBUG_ALIGN_RODATA=y
>
> ---[ Kernel Mapping ]---
> 0x80000000-0x80100000 1M RW NX SHD
> 0x80100000-0x80700000 6M ro x SHD
> 0x80700000-0x80a00000 3M ro NX SHD
> 0x80a00000-0xa0000000 502M RW NX SHD
>
> CONFIG_DEBUG_RODATA=y
> # CONFIG_DEBUG_ALIGN_RODATA is not set
>
> ---[ Kernel Mapping ]---
> 0x80000000-0x80100000 1M RW NX SHD
> 0x80100000-0x80a00000 9M ro x SHD
> 0x80a00000-0xa0000000 502M RW NX SHD
>
> Signed-off-by: Kees Cook <[email protected]>
> ---

Reviewed-by: Laura Abbott <[email protected]>

2015-12-22 10:37:15

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

Hi Kees, Russell,

On Wed, Dec 2, 2015 at 9:27 PM, Kees Cook <[email protected]> wrote:
> The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of
> kernel self-protection:
> http://www.openwall.com/lists/kernel-hardening/2015/11/30/13
> Additionally, its name has grown to mean things beyond just rodata. To
> get ARM closer to this, we ought to rearrange the names of the configs
> that control how the kernel protects its memory. What was called
> CONFIG_ARM_KERNMEM_PERMS is really doing the work that other architectures
> call CONFIG_DEBUG_RODATA.

[...]

This broke s2ram with shmobile_defconfig on r8a7791/koelsch:

Freezing user space processes ... (elapsed 0.002 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.003 seconds) done.
PM: suspend of devices complete after 112.157 msecs
PM: late suspend of devices complete after 1.605 msecs
PM: noirq suspend of devices complete after 13.098 msecs
Disabling non-boot CPUs ...
s---[ end Kernel panic - not syncing: Attempted to kill the idle task!
CPU0: stopping
CPU: 0 PID: 2412 Comm: s2ram Tainted: G D
4.4.0-rc6-00003-g1bb20571dcf0edfc #470
Hardware name: Generic R8A7791 (Flattened Device Tree)
Backtrace:
[<c010a92c>] (dump_backtrace) from [<c010aad4>] (show_stack+0x18/0x1c)
r6:00000000 r5:00000000 r4:00000000 r3:80404000
[<c010aabc>] (show_stack) from [<c02b9ff4>] (dump_stack+0x78/0x94)
[<c02b9f7c>] (dump_stack) from [<c010d4b4>] (handle_IPI+0xf4/0x19c)
r4:c09313f0 r3:c09091ec
[<c010d3c0>] (handle_IPI) from [<c0101430>] (gic_handle_irq+0x7c/0x98)
r7:c0910b80 r6:ee1d5c30 r5:c0902754 r4:f0802000
[<c01013b4>] (gic_handle_irq) from [<c010b654>] (__irq_svc+0x54/0x70)
Exception stack(0xee1d5c30 to 0xee1d5c78)
5c20: c0955484 00000002
00000000 60070013
5c40: c0942718 c093916c 00000005 0000000f 00000000 00000000
c0943088 ee1d5cd4
5c60: ee1d5c08 ee1d5c80 c033fc20 c0158120 60070013 ffffffff
r8:00000000 r7:ee1d5c64 r6:ffffffff r5:60070013 r4:c0158120 r3:c033fc20
[<c0157ecc>] (console_unlock) from [<c0158724>] (vprintk_emit+0x448/0x4a4)
r10:c09450a6 r9:00000000 r8:0000000e r7:00000005 r6:00000006 r5:c0932758
r4:00000001
[<c01582dc>] (vprintk_emit) from [<c01588e0>] (vprintk_default+0x28/0x30)
r10:c09055e0 r9:00000001 r8:c09055e0 r7:00000010 r6:00000000 r5:00000000
r4:00000001
[<c01588b8>] (vprintk_default) from [<c018e538>] (printk+0x34/0x40)
[<c018e508>] (printk) from [<c010cfb8>] (__cpu_die+0x34/0x78)
r3:00000003 r2:c0906808 r1:00000001 r0:c0710af6
[<c010cf84>] (__cpu_die) from [<c011d7d0>] (_cpu_down+0x168/0x290)
r4:00000001 r3:00000005
[<c011d668>] (_cpu_down) from [<c011dd90>] (disable_nonboot_cpus+0x70/0xf0)
r10:00000051 r9:c0932734 r8:c0902528 r7:00000000 r6:c090245c r5:c0931b40
r4:00000001
[<c011dd20>] (disable_nonboot_cpus) from [<c0155fd8>]
(suspend_devices_and_enter+0x290/0x3f8)
r8:c0714bb5 r7:eebac300 r6:00000003 r5:c0932734 r4:00000000 r3:00000000
[<c0155d48>] (suspend_devices_and_enter) from [<c01561f4>]
(pm_suspend+0xb4/0x1c8)
r9:c093273c r8:c0714bb5 r7:eebac300 r6:00000003 r5:c09576fc r4:00000000
[<c0156140>] (pm_suspend) from [<c0155148>] (state_store+0xb0/0xc4)
r6:00000004 r5:00000003 r4:00000003 r3:0000006d
[<c0155098>] (state_store) from [<c02bbce8>] (kobj_attr_store+0x1c/0x28)
r9:000cdc08 r8:ee1d5f80 r7:eebacb0c r6:eebacb00 r5:eebac300 r4:eebac300
[<c02bbccc>] (kobj_attr_store) from [<c0222438>] (sysfs_kf_write+0x44/0x50)
[<c02223f4>] (sysfs_kf_write) from [<c0221ae0>]
(kernfs_fop_write+0x13c/0x1a0)
r4:00000004 r3:c02223f4
[<c02219a4>] (kernfs_fop_write) from [<c01ca1b4>] (__vfs_write+0x34/0xdc)
r10:00000000 r9:ee1d4000 r8:c0106fa4 r7:00000004 r6:ee1d5f80 r5:c02219a4
r4:edf85d00
[<c01ca180>] (__vfs_write) from [<c01ca3dc>] (vfs_write+0xb8/0x140)
r7:ee1d5f80 r6:000cdc08 r5:edf85d00 r4:00000004
[<c01ca324>] (vfs_write) from [<c01ca544>] (SyS_write+0x50/0x90)
r9:ee1d4000 r8:c0106fa4 r7:000cdc08 r6:00000004 r5:edf85d00 r4:edf85d00
[<c01ca4f4>] (SyS_write) from [<c0106de0>] (ret_fast_syscall+0x0/0x3c)

Before commit 1bb20571dcf0edfc ("ARM: 8470/1: mm: flip priority of
CONFIG_DEBUG_RODATA"):

# CONFIG_ARM_KERNMEM_PERMS is not set

Freezing user space processes ... (elapsed 0.001 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.003 seconds) done.
PM: suspend of devices complete after 112.163 msecs
PM: late suspend of devices complete after 1.610 msecs
PM: noirq suspend of devices complete after 13.109 msecs
Disabling non-boot CPUs ...
CPU1: shutdown

After the offending commit:

CONFIG_DEBUG_RODATA=y
CONFIG_DEBUG_ALIGN_RODATA=y

The "problem" is that DEBUG_RODATA now defaults to y on CPU_V7, so it gets
enabled for shmobile_defconfig. If I manually disable DEBUG_RODATA again,
s2ram does work.

The real problem is something else, though. I can trigger the same panic
without the offending commit by enabling:

CONFIG_ARM_KERNMEM_PERMS=y
CONFIG_DEBUG_RODATA=y

I never enabled those options before, so I have no idea if this is a recent
regression. I've just tried a few older versions: on v4.4-rc1 I see the same
panic, on v4.3 (and v4.3.3) I don't see the panic, and the "CPU1: shutdown"
line, but the system doesn't wake up.

Thanks for your suggestions!

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2015-12-23 00:36:15

by Laura Abbott

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

On 12/22/2015 02:37 AM, Geert Uytterhoeven wrote:
> Hi Kees, Russell,
>
> On Wed, Dec 2, 2015 at 9:27 PM, Kees Cook <[email protected]> wrote:
>> The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of
>> kernel self-protection:
>> http://www.openwall.com/lists/kernel-hardening/2015/11/30/13
>> Additionally, its name has grown to mean things beyond just rodata. To
>> get ARM closer to this, we ought to rearrange the names of the configs
>> that control how the kernel protects its memory. What was called
>> CONFIG_ARM_KERNMEM_PERMS is really doing the work that other architectures
>> call CONFIG_DEBUG_RODATA.
>
> [...]
>
> This broke s2ram with shmobile_defconfig on r8a7791/koelsch:
>
> Freezing user space processes ... (elapsed 0.002 seconds) done.
> Freezing remaining freezable tasks ... (elapsed 0.003 seconds) done.
> PM: suspend of devices complete after 112.157 msecs
> PM: late suspend of devices complete after 1.605 msecs
> PM: noirq suspend of devices complete after 13.098 msecs
> Disabling non-boot CPUs ...
> s---[ end Kernel panic - not syncing: Attempted to kill the idle task!
> CPU0: stopping
> CPU: 0 PID: 2412 Comm: s2ram Tainted: G D
> 4.4.0-rc6-00003-g1bb20571dcf0edfc #470
> Hardware name: Generic R8A7791 (Flattened Device Tree)
> Backtrace:
> [<c010a92c>] (dump_backtrace) from [<c010aad4>] (show_stack+0x18/0x1c)
> r6:00000000 r5:00000000 r4:00000000 r3:80404000
> [<c010aabc>] (show_stack) from [<c02b9ff4>] (dump_stack+0x78/0x94)
> [<c02b9f7c>] (dump_stack) from [<c010d4b4>] (handle_IPI+0xf4/0x19c)
> r4:c09313f0 r3:c09091ec
> [<c010d3c0>] (handle_IPI) from [<c0101430>] (gic_handle_irq+0x7c/0x98)
> r7:c0910b80 r6:ee1d5c30 r5:c0902754 r4:f0802000
> [<c01013b4>] (gic_handle_irq) from [<c010b654>] (__irq_svc+0x54/0x70)
> Exception stack(0xee1d5c30 to 0xee1d5c78)
> 5c20: c0955484 00000002
> 00000000 60070013
> 5c40: c0942718 c093916c 00000005 0000000f 00000000 00000000
> c0943088 ee1d5cd4
> 5c60: ee1d5c08 ee1d5c80 c033fc20 c0158120 60070013 ffffffff
> r8:00000000 r7:ee1d5c64 r6:ffffffff r5:60070013 r4:c0158120 r3:c033fc20
> [<c0157ecc>] (console_unlock) from [<c0158724>] (vprintk_emit+0x448/0x4a4)
> r10:c09450a6 r9:00000000 r8:0000000e r7:00000005 r6:00000006 r5:c0932758
> r4:00000001
> [<c01582dc>] (vprintk_emit) from [<c01588e0>] (vprintk_default+0x28/0x30)
> r10:c09055e0 r9:00000001 r8:c09055e0 r7:00000010 r6:00000000 r5:00000000
> r4:00000001
> [<c01588b8>] (vprintk_default) from [<c018e538>] (printk+0x34/0x40)
> [<c018e508>] (printk) from [<c010cfb8>] (__cpu_die+0x34/0x78)
> r3:00000003 r2:c0906808 r1:00000001 r0:c0710af6
> [<c010cf84>] (__cpu_die) from [<c011d7d0>] (_cpu_down+0x168/0x290)
> r4:00000001 r3:00000005
> [<c011d668>] (_cpu_down) from [<c011dd90>] (disable_nonboot_cpus+0x70/0xf0)
> r10:00000051 r9:c0932734 r8:c0902528 r7:00000000 r6:c090245c r5:c0931b40
> r4:00000001
> [<c011dd20>] (disable_nonboot_cpus) from [<c0155fd8>]
> (suspend_devices_and_enter+0x290/0x3f8)
> r8:c0714bb5 r7:eebac300 r6:00000003 r5:c0932734 r4:00000000 r3:00000000
> [<c0155d48>] (suspend_devices_and_enter) from [<c01561f4>]
> (pm_suspend+0xb4/0x1c8)
> r9:c093273c r8:c0714bb5 r7:eebac300 r6:00000003 r5:c09576fc r4:00000000
> [<c0156140>] (pm_suspend) from [<c0155148>] (state_store+0xb0/0xc4)
> r6:00000004 r5:00000003 r4:00000003 r3:0000006d
> [<c0155098>] (state_store) from [<c02bbce8>] (kobj_attr_store+0x1c/0x28)
> r9:000cdc08 r8:ee1d5f80 r7:eebacb0c r6:eebacb00 r5:eebac300 r4:eebac300
> [<c02bbccc>] (kobj_attr_store) from [<c0222438>] (sysfs_kf_write+0x44/0x50)
> [<c02223f4>] (sysfs_kf_write) from [<c0221ae0>]
> (kernfs_fop_write+0x13c/0x1a0)
> r4:00000004 r3:c02223f4
> [<c02219a4>] (kernfs_fop_write) from [<c01ca1b4>] (__vfs_write+0x34/0xdc)
> r10:00000000 r9:ee1d4000 r8:c0106fa4 r7:00000004 r6:ee1d5f80 r5:c02219a4
> r4:edf85d00
> [<c01ca180>] (__vfs_write) from [<c01ca3dc>] (vfs_write+0xb8/0x140)
> r7:ee1d5f80 r6:000cdc08 r5:edf85d00 r4:00000004
> [<c01ca324>] (vfs_write) from [<c01ca544>] (SyS_write+0x50/0x90)
> r9:ee1d4000 r8:c0106fa4 r7:000cdc08 r6:00000004 r5:edf85d00 r4:edf85d00
> [<c01ca4f4>] (SyS_write) from [<c0106de0>] (ret_fast_syscall+0x0/0x3c)
>
> Before commit 1bb20571dcf0edfc ("ARM: 8470/1: mm: flip priority of
> CONFIG_DEBUG_RODATA"):
>
> # CONFIG_ARM_KERNMEM_PERMS is not set
>
> Freezing user space processes ... (elapsed 0.001 seconds) done.
> Freezing remaining freezable tasks ... (elapsed 0.003 seconds) done.
> PM: suspend of devices complete after 112.163 msecs
> PM: late suspend of devices complete after 1.610 msecs
> PM: noirq suspend of devices complete after 13.109 msecs
> Disabling non-boot CPUs ...
> CPU1: shutdown
>
> After the offending commit:
>
> CONFIG_DEBUG_RODATA=y
> CONFIG_DEBUG_ALIGN_RODATA=y
>
> The "problem" is that DEBUG_RODATA now defaults to y on CPU_V7, so it gets
> enabled for shmobile_defconfig. If I manually disable DEBUG_RODATA again,
> s2ram does work.
>
> The real problem is something else, though. I can trigger the same panic
> without the offending commit by enabling:
>
> CONFIG_ARM_KERNMEM_PERMS=y
> CONFIG_DEBUG_RODATA=y
>
> I never enabled those options before, so I have no idea if this is a recent
> regression. I've just tried a few older versions: on v4.4-rc1 I see the same
> panic, on v4.3 (and v4.3.3) I don't see the panic, and the "CPU1: shutdown"
> line, but the system doesn't wake up.
>
> Thanks for your suggestions!
>
> Gr{oetje,eeting}s,
>
> Geert
>

At a thought I think the RO/NX persmission are working as expected and
something in the suspend code is writing or executing from where it
shouldn't. I hit similar problems when working on RO/NX support for
arm64.

Looking in arch/arm/mach-shmobile/headsmp.S, it looks like
shmobile_boot_fn, shmobile_boot_arg, shmobile_smp_mpdir, shmobile_smp_fn,
and shmobile_smp_arg are ending up in the the text section which is going
to be read_only. Assuming I understand the code flow, it looks like those
are modified at suspend time which isn't going to work. I would say just
throw those objects in the .data section but I notice shmobile_boot_size
is there as well which seems to be calculated based off of the boot
vector so you might need to do some re-working there.

Thanks,
Laura

2015-12-23 19:51:38

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

* Kees Cook <[email protected]> [151202 12:31]:
> The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of
> kernel self-protection:
> http://www.openwall.com/lists/kernel-hardening/2015/11/30/13
> Additionally, its name has grown to mean things beyond just rodata. To
> get ARM closer to this, we ought to rearrange the names of the configs
> that control how the kernel protects its memory. What was called
> CONFIG_ARM_KERNMEM_PERMS is really doing the work that other architectures
> call CONFIG_DEBUG_RODATA.
>
> This redefines CONFIG_DEBUG_RODATA to actually do the bulk of the
> ROing (and NXing). In the place of the old CONFIG_DEBUG_RODATA, use
> CONFIG_DEBUG_ALIGN_RODATA, since that's what the option does: adds
> section alignment for making rodata explicitly NX, as arm does not split
> the page tables like arm64 does without _ALIGN_RODATA.

Also all omap3 boards are now oopsing in Linux next if PM is enabled:

[ 18.549865] Unable to handle kernel paging request at virtual address c01237dc
[ 18.557830] pgd = cf704000
[ 18.560974] [c01237dc] *pgd=8000041e(bad)
[ 18.565765] Internal error: Oops: 80d [#1] SMP ARM
[ 18.571105] Modules linked in: ledtrig_default_on leds_gpio led_class rtc_twl twl4030_wdt
[ 18.581024] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.0-rc6-00003-g1bb2057 #2973
[ 18.589508] Hardware name: Generic OMAP36xx (Flattened Device Tree)
[ 18.596466] task: c0c06638 ti: c0c00000 task.ti: c0c00000
[ 18.602539] PC is at wait_dll_lock_timed+0x8/0x14
[ 18.607849] LR is at save_context_wfi+0x24/0x28
[ 18.612976] pc : [<c0123750>] lr : [<c01236b0>] psr: 600e0093
[ 18.612976] sp : c0c01ea0 ip : c0c028d4 fp : 00000002
[ 18.625549] r10: 00000000 r9 : ffffffff r8 : 00000000
[ 18.631378] r7 : c01237d8 r6 : 00000003 r5 : 0000000a r4 : 00000001
[ 18.638610] r3 : 00000004 r2 : 00000006 r1 : f03fe03a r0 : 0a000023
[ 18.645843] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment none
[ 18.653839] Control: 10c53879 Table: 8f704019 DAC: 00000051
[ 18.660217] Process swapper/0 (pid: 0, stack limit = 0xc0c00218)
[ 18.666900] Stack: (0xc0c01ea0 to 0xc0c02000)
[ 18.671936] 1ea0: 00000030 c0c01efc 00000003 00000001 00000000 c0c0a0a0 c0c028d4 00000000
[ 18.681060] 1ec0: c0122ef8 00000000 c010d210 8f0b0000 c0c01efc 80119dc0 00000000 00000000
[ 18.690185] 1ee0: 00000000 00000051 80004019 10c5387d 000000e2 00f00000 00000000 c0c06638
[ 18.699279] 1f00: cf6a4e00 00000003 00000001 00000000 c0c0a0a0 00000000 00000000 c010d3bc
[ 18.708404] 1f20: c0cbd460 c0cbdd14 00000003 c012308c 00000003 c0c09f90 c0cbdd54 00000000
[ 18.717529] 1f40: 00000001 c0124584 51b8dc60 00000004 c0cb8a9c c0c09fa0 cfb3ba58 c05a8e14
[ 18.726654] 1f60: 008a43a0 00000000 51b8dc60 00000004 51b8dc60 00000004 c0c029ec c0c00000
[ 18.735778] 1f80: c0c029ec 00000000 c0cb8a9c cfb3ba58 c0c09fa0 c0c0298c c0b6ea50 c017bbb4
[ 18.744934] 1fa0: c0740760 c0b6a4e4 c0cbd000 ffffffff cfb473c0 c0b00c34 ffffffff ffffffff
[ 18.754058] 1fc0: 00000000 c0b0066c 00000000 c0b4fa48 00000000 c0cbd214 c0c0296c c0b4fa44
[ 18.763183] 1fe0: c0c08208 80004059 413fc082 00000000 00000000 8000807c 00000000 00000000
[ 18.772308] [<c0123750>] (wait_dll_lock_timed) from [<c0c0a0a0>] (omap3_idle_driver+0x100/0x33c)
[ 18.782043] Code: 1a000019 e28f708c e59f408c e2844001 (e5874004)

Reverting the $subject patch fixes the issue.

Regards,

Tony

2015-12-23 20:01:53

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

On Wed, Dec 23, 2015 at 11:51:29AM -0800, Tony Lindgren wrote:
> Also all omap3 boards are now oopsing in Linux next if PM is enabled:

I'm not sure that's entirely true. My LDP3430 works fine with this
change in place, and that has CONFIG_PM=y. See my nightly build/boot
results, which includes an attempt to enter hibernation. Remember
that last night's results are from my tree plus arm-soc's for-next.

Maybe there's some other change in linux-next which, when combined
with this change, is provoking it?

--
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

2015-12-23 20:15:44

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

On Wed, Dec 02, 2015 at 12:27:25PM -0800, Kees Cook wrote:
> The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of
> kernel self-protection:
> http://www.openwall.com/lists/kernel-hardening/2015/11/30/13
> Additionally, its name has grown to mean things beyond just rodata. To
> get ARM closer to this, we ought to rearrange the names of the configs
> that control how the kernel protects its memory. What was called
> CONFIG_ARM_KERNMEM_PERMS is really doing the work that other architectures
> call CONFIG_DEBUG_RODATA.

Kees,

There is a subtle problem with the kernel memory permissions and the
DMA debugging.

DMA debugging checks whether we're trying to do DMA from the kernel
mappings (text, rodata, data etc). It checks _text.._etext. However,
when RODATA is enabled, we have about one section between _text and
_stext which are freed into the kernel's page pool, and then become
available for allocation and use for DMA.

This then causes the DMA debugging sanity check to fire.

So, I think I'll revert this change for the time being as it seems to
be causing many people problems, and having this enabled is creating
extra warnings when kernel debug options are enabled along with it.

Sorry.

--
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

2015-12-23 20:18:49

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

* Russell King - ARM Linux <[email protected]> [151223 12:01]:
> On Wed, Dec 23, 2015 at 11:51:29AM -0800, Tony Lindgren wrote:
> > Also all omap3 boards are now oopsing in Linux next if PM is enabled:
>
> I'm not sure that's entirely true. My LDP3430 works fine with this
> change in place, and that has CONFIG_PM=y. See my nightly build/boot
> results, which includes an attempt to enter hibernation. Remember
> that last night's results are from my tree plus arm-soc's for-next.

Right but you don't have any deeper idle states enabled for your
old ldp, see the script below. It may not work properly on your ldp
because of the old silicon revision of the SoC..

> Maybe there's some other change in linux-next which, when combined
> with this change, is provoking it?

Well it seems to be the new default Kconfig options selected by
default as Geert is saying?

And it seems to require off mode enabled for idle to hit it, retention
idle does not seem to trigger it.

Regards,

Tony


8< -------------------------
#!/bin/bash

uarts=$(find /sys/class/tty/tty[SO]*/device/power/ -type d)
for uart in $uarts; do
echo 3000 > $uart/autosuspend_delay_ms 2>&1
done

uarts=$(find /sys/class/tty/tty[SO]*/power/ -type d 2>/dev/null)
for uart in $uarts; do
echo enabled > $uart/wakeup 2>&1
echo auto > $uart/control 2>&1
done

echo 1 > /sys/kernel/debug/pm_debug/enable_off_mode

2015-12-23 20:31:48

by Laura Abbott

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

On 12/23/2015 11:51 AM, Tony Lindgren wrote:
> * Kees Cook <[email protected]> [151202 12:31]:
>> The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of
>> kernel self-protection:
>> http://www.openwall.com/lists/kernel-hardening/2015/11/30/13
>> Additionally, its name has grown to mean things beyond just rodata. To
>> get ARM closer to this, we ought to rearrange the names of the configs
>> that control how the kernel protects its memory. What was called
>> CONFIG_ARM_KERNMEM_PERMS is really doing the work that other architectures
>> call CONFIG_DEBUG_RODATA.
>>
>> This redefines CONFIG_DEBUG_RODATA to actually do the bulk of the
>> ROing (and NXing). In the place of the old CONFIG_DEBUG_RODATA, use
>> CONFIG_DEBUG_ALIGN_RODATA, since that's what the option does: adds
>> section alignment for making rodata explicitly NX, as arm does not split
>> the page tables like arm64 does without _ALIGN_RODATA.
>
> Also all omap3 boards are now oopsing in Linux next if PM is enabled:
>
> [ 18.549865] Unable to handle kernel paging request at virtual address c01237dc
> [ 18.557830] pgd = cf704000
> [ 18.560974] [c01237dc] *pgd=8000041e(bad)
> [ 18.565765] Internal error: Oops: 80d [#1] SMP ARM
> [ 18.571105] Modules linked in: ledtrig_default_on leds_gpio led_class rtc_twl twl4030_wdt
> [ 18.581024] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.0-rc6-00003-g1bb2057 #2973
> [ 18.589508] Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [ 18.596466] task: c0c06638 ti: c0c00000 task.ti: c0c00000
> [ 18.602539] PC is at wait_dll_lock_timed+0x8/0x14
> [ 18.607849] LR is at save_context_wfi+0x24/0x28
> [ 18.612976] pc : [<c0123750>] lr : [<c01236b0>] psr: 600e0093
> [ 18.612976] sp : c0c01ea0 ip : c0c028d4 fp : 00000002
> [ 18.625549] r10: 00000000 r9 : ffffffff r8 : 00000000
> [ 18.631378] r7 : c01237d8 r6 : 00000003 r5 : 0000000a r4 : 00000001
> [ 18.638610] r3 : 00000004 r2 : 00000006 r1 : f03fe03a r0 : 0a000023
> [ 18.645843] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment none
> [ 18.653839] Control: 10c53879 Table: 8f704019 DAC: 00000051
> [ 18.660217] Process swapper/0 (pid: 0, stack limit = 0xc0c00218)
> [ 18.666900] Stack: (0xc0c01ea0 to 0xc0c02000)
> [ 18.671936] 1ea0: 00000030 c0c01efc 00000003 00000001 00000000 c0c0a0a0 c0c028d4 00000000
> [ 18.681060] 1ec0: c0122ef8 00000000 c010d210 8f0b0000 c0c01efc 80119dc0 00000000 00000000
> [ 18.690185] 1ee0: 00000000 00000051 80004019 10c5387d 000000e2 00f00000 00000000 c0c06638
> [ 18.699279] 1f00: cf6a4e00 00000003 00000001 00000000 c0c0a0a0 00000000 00000000 c010d3bc
> [ 18.708404] 1f20: c0cbd460 c0cbdd14 00000003 c012308c 00000003 c0c09f90 c0cbdd54 00000000
> [ 18.717529] 1f40: 00000001 c0124584 51b8dc60 00000004 c0cb8a9c c0c09fa0 cfb3ba58 c05a8e14
> [ 18.726654] 1f60: 008a43a0 00000000 51b8dc60 00000004 51b8dc60 00000004 c0c029ec c0c00000
> [ 18.735778] 1f80: c0c029ec 00000000 c0cb8a9c cfb3ba58 c0c09fa0 c0c0298c c0b6ea50 c017bbb4
> [ 18.744934] 1fa0: c0740760 c0b6a4e4 c0cbd000 ffffffff cfb473c0 c0b00c34 ffffffff ffffffff
> [ 18.754058] 1fc0: 00000000 c0b0066c 00000000 c0b4fa48 00000000 c0cbd214 c0c0296c c0b4fa44
> [ 18.763183] 1fe0: c0c08208 80004059 413fc082 00000000 00000000 8000807c 00000000 00000000
> [ 18.772308] [<c0123750>] (wait_dll_lock_timed) from [<c0c0a0a0>] (omap3_idle_driver+0x100/0x33c)
> [ 18.782043] Code: 1a000019 e28f708c e59f408c e2844001 (e5874004)
>
> Reverting the $subject patch fixes the issue.
>
> Regards,
>
> Tony
>

Looks like a case similar to Geert's

adr r7, kick_counter
wait_dll_lock_timed:
ldr r4, wait_dll_lock_counter
add r4, r4, #1
str r4, [r7, #wait_dll_lock_counter - kick_counter]
ldr r4, sdrc_dlla_status
/* Wait 20uS for lock */
mov r6, #8


kick_counter and wait_dll_lock_counter are in the text section which is marked read only.
They need to be moved to the data section along with a few other variables from what I
can tell (maybe those are read only?).

I suspect this is going to be a common issue with suspend/resume code paths since those
are hand written assembly.

Thanks,
Laura

2015-12-23 21:26:23

by Laura Abbott

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

On 12/23/2015 12:15 PM, Russell King - ARM Linux wrote:
> On Wed, Dec 02, 2015 at 12:27:25PM -0800, Kees Cook wrote:
>> The use of CONFIG_DEBUG_RODATA is generally seen as an essential part of
>> kernel self-protection:
>> http://www.openwall.com/lists/kernel-hardening/2015/11/30/13
>> Additionally, its name has grown to mean things beyond just rodata. To
>> get ARM closer to this, we ought to rearrange the names of the configs
>> that control how the kernel protects its memory. What was called
>> CONFIG_ARM_KERNMEM_PERMS is really doing the work that other architectures
>> call CONFIG_DEBUG_RODATA.
>
> Kees,
>
> There is a subtle problem with the kernel memory permissions and the
> DMA debugging.
>
> DMA debugging checks whether we're trying to do DMA from the kernel
> mappings (text, rodata, data etc). It checks _text.._etext. However,
> when RODATA is enabled, we have about one section between _text and
> _stext which are freed into the kernel's page pool, and then become
> available for allocation and use for DMA.
>
> This then causes the DMA debugging sanity check to fire.
>
> So, I think I'll revert this change for the time being as it seems to
> be causing many people problems, and having this enabled is creating
> extra warnings when kernel debug options are enabled along with it.
>
> Sorry.
>

in include/asm-generic/sections.h:

/*
* Usage guidelines:
* _text, _data: architecture specific, don't use them in arch-independent code
* [_stext, _etext]: contains .text.* sections, may also contain .rodata.*
* and/or .init.* sections


So based on that comment it seems like the dma-debug should be checking for
_stext not _text since only _stext is guaranteed across all architectures.
I'll submit a patch to dma-debug.c if this seems appropriate or if you
haven't done so already.

Thanks,
Laura

2015-12-23 21:29:18

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

Hi,

* Laura Abbott <[email protected]> [151223 12:31]:
>
> Looks like a case similar to Geert's
>
> adr r7, kick_counter
> wait_dll_lock_timed:
> ldr r4, wait_dll_lock_counter
> add r4, r4, #1
> str r4, [r7, #wait_dll_lock_counter - kick_counter]
> ldr r4, sdrc_dlla_status
> /* Wait 20uS for lock */
> mov r6, #8
>
>
> kick_counter and wait_dll_lock_counter are in the text section which is marked read only.
> They need to be moved to the data section along with a few other variables from what I
> can tell (maybe those are read only?).

Thanks for looking, yeah so it seem.

> I suspect this is going to be a common issue with suspend/resume code paths since those
> are hand written assembly.

Yes I suspect we have quite a few cases like this.

Regards,

Tony

2015-12-23 21:45:21

by Nicolas Pitre

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

On Wed, 23 Dec 2015, Tony Lindgren wrote:

> Hi,
>
> * Laura Abbott <[email protected]> [151223 12:31]:
> >
> > Looks like a case similar to Geert's
> >
> > adr r7, kick_counter
> > wait_dll_lock_timed:
> > ldr r4, wait_dll_lock_counter
> > add r4, r4, #1
> > str r4, [r7, #wait_dll_lock_counter - kick_counter]
> > ldr r4, sdrc_dlla_status
> > /* Wait 20uS for lock */
> > mov r6, #8
> >
> >
> > kick_counter and wait_dll_lock_counter are in the text section which is marked read only.
> > They need to be moved to the data section along with a few other variables from what I
> > can tell (maybe those are read only?).
>
> Thanks for looking, yeah so it seem.
>
> > I suspect this is going to be a common issue with suspend/resume code paths since those
> > are hand written assembly.
>
> Yes I suspect we have quite a few cases like this.

We fixed a bunch of similar issues where code was located in the .data
section for ease of use from assembly code. See commit b4e61537 and
d0776aff for example.


Nicolas

2015-12-24 00:11:27

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

* Nicolas Pitre <[email protected]> [151223 13:45]:
> On Wed, 23 Dec 2015, Tony Lindgren wrote:
>
> > Hi,
> >
> > * Laura Abbott <[email protected]> [151223 12:31]:
> > >
> > > Looks like a case similar to Geert's
> > >
> > > adr r7, kick_counter
> > > wait_dll_lock_timed:
> > > ldr r4, wait_dll_lock_counter
> > > add r4, r4, #1
> > > str r4, [r7, #wait_dll_lock_counter - kick_counter]
> > > ldr r4, sdrc_dlla_status
> > > /* Wait 20uS for lock */
> > > mov r6, #8
> > >
> > >
> > > kick_counter and wait_dll_lock_counter are in the text section which is marked read only.
> > > They need to be moved to the data section along with a few other variables from what I
> > > can tell (maybe those are read only?).
> >
> > Thanks for looking, yeah so it seem.
> >
> > > I suspect this is going to be a common issue with suspend/resume code paths since those
> > > are hand written assembly.
> >
> > Yes I suspect we have quite a few cases like this.
>
> We fixed a bunch of similar issues where code was located in the .data
> section for ease of use from assembly code. See commit b4e61537 and
> d0776aff for example.

Thanks hey some assembly fun for the holidays :) I also need to check what
all gets relocated to SRAM here.

In any case, seems like the $subject patch is too intrusive for v4.5 at
this point.

Regards,

Tony

2015-12-24 00:34:54

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: mm: flip priority of CONFIG_DEBUG_RODATA

On Wed, Dec 23, 2015 at 04:11:22PM -0800, Tony Lindgren wrote:
> * Nicolas Pitre <[email protected]> [151223 13:45]:
> > We fixed a bunch of similar issues where code was located in the .data
> > section for ease of use from assembly code. See commit b4e61537 and
> > d0776aff for example.
>
> Thanks hey some assembly fun for the holidays :) I also need to check what
> all gets relocated to SRAM here.
>
> In any case, seems like the $subject patch is too intrusive for v4.5 at
> this point.

Given Christmas and an unknown time between that and the merge window
actually opening, I decided Tuesday would be the last day I take any
patches into my tree - and today would be the day that I drop anything
that causes problems.

So, I've already dropped this, so tomorrow's linux-next should not have
this change.

You'll still see breakage if people enable RODATA though, but that's no
different from previous kernels.

--
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.