* Re: [PATCH v2 1/4] siphash: add cryptographically secure hashtable function
From: Jason A. Donenfeld @ 2016-12-14 23:29 UTC (permalink / raw)
To: Hannes Frederic Sowa
Cc: David Laight, Netdev, kernel-hardening, Jean-Philippe Aumasson,
LKML, Linux Crypto Mailing List, Daniel J . Bernstein,
Linus Torvalds, Eric Biggers
In-Reply-To: <8ea3fdff-23c4-b81d-2588-44549bd2d8c1@stressinduktion.org>
Hi Hannes,
On Wed, Dec 14, 2016 at 11:03 PM, Hannes Frederic Sowa
<hannes@stressinduktion.org> wrote:
> I fear that the alignment requirement will be a source of bugs on 32 bit
> machines, where you cannot even simply take a well aligned struct on a
> stack and put it into the normal siphash(aligned) function without
> adding alignment annotations everywhere. Even blocks returned from
> kmalloc on 32 bit are not aligned to 64 bit.
That's what the "__aligned(SIPHASH24_ALIGNMENT)" attribute is for. The
aligned siphash function will be for structs explicitly made for
siphash consumption. For everything else there's siphash_unaligned.
> Can we do this a runtime check and just have one function (siphash)
> dealing with that?
Seems like the runtime branching on the aligned function would be bad
for performance, when we likely know at compile time if it's going to
be aligned or not. I suppose we could add that check just to the
unaligned version, and rename it to "maybe_unaligned"? Is this what
you have in mind?
Jason
^ permalink raw reply
* Re: [PATCH v3 1/3] siphash: add cryptographically secure hashtable function
From: Linus Torvalds @ 2016-12-14 23:30 UTC (permalink / raw)
To: Jason A. Donenfeld
Cc: Tom Herbert, Netdev, kernel-hardening@lists.openwall.com, LKML,
Linux Crypto Mailing List, Jean-Philippe Aumasson,
Daniel J . Bernstein, Eric Biggers, David Laight
In-Reply-To: <CAHmME9rpvf4tyDjZcJAJxMAW1LcqNm7DiquiYX0uQhRzDLbwqw@mail.gmail.com>
On Wed, Dec 14, 2016 at 2:56 PM, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
> So actually jhash_Nwords makes no sense, since it takes dwords
> (32-bits) not words (16-bits). The siphash analog should be called
> siphash24_Nqwords.
No. The bug is talking about "words" in the first place.
Depending on your background, a "word" can be generally be either 16
bits or 32 bits (or, in some cases, 18 bits).
In theory, a 64-bit entity can be a "word" too, but pretty much nobody
uses that. Even architectures that started out with a 64-bit register
size and never had any smaller historical baggage (eg alpha) tend to
call 32-bit entities "words".
So 16 bits can be a word, but some people/architectures will call it a
"half-word".
To make matters even more confusing, a "quadword" is generally always
64 bits, regardless of the size of "word".
So please try to avoid the use of "word" entirely. It's too ambiguous,
and it's not even helpful as a "size of the native register". It's
almost purely random.
For the kernel, we tend use
- uX for types that have specific sizes (X being the number of bits)
- "[unsigned] long" for native register size
But never "word".
Linus
^ permalink raw reply
* Re: [PATCH v3 1/3] siphash: add cryptographically secure hashtable function
From: Jason A. Donenfeld @ 2016-12-14 23:34 UTC (permalink / raw)
To: Linus Torvalds
Cc: Tom Herbert, Netdev, kernel-hardening@lists.openwall.com, LKML,
Linux Crypto Mailing List, Jean-Philippe Aumasson,
Daniel J . Bernstein, Eric Biggers, David Laight
In-Reply-To: <CA+55aFyBGQpEKiAcs0w58ZEie+L8OrWvf_2hvGx4E=L56p5hMg@mail.gmail.com>
Hey Linus,
On Thu, Dec 15, 2016 at 12:30 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> No. The bug is talking about "words" in the first place.
>
> Depending on your background, a "word" can be generally be either 16
> bits or 32 bits (or, in some cases, 18 bits).
>
> In theory, a 64-bit entity can be a "word" too, but pretty much nobody
> uses that. Even architectures that started out with a 64-bit register
> size and never had any smaller historical baggage (eg alpha) tend to
> call 32-bit entities "words".
>
> So 16 bits can be a word, but some people/architectures will call it a
> "half-word".
>
> To make matters even more confusing, a "quadword" is generally always
> 64 bits, regardless of the size of "word".
>
> So please try to avoid the use of "word" entirely. It's too ambiguous,
> and it's not even helpful as a "size of the native register". It's
> almost purely random.
>
> For the kernel, we tend use
>
> - uX for types that have specific sizes (X being the number of bits)
>
> - "[unsigned] long" for native register size
>
> But never "word".
The voice of reason. Have a desired name for this function family?
siphash_3u64s
siphash_3u64
siphash_three_u64
siphash_3sixityfourbitintegers
Or does your reasonable dislike of "word" still allow for the use of
dword and qword, so that the current function names of:
siphash_3qwords
siphash_6dwords
are okay?
Jason
^ permalink raw reply
* Re: [PATCH v3 1/3] siphash: add cryptographically secure hashtable function
From: Linus Torvalds @ 2016-12-15 0:10 UTC (permalink / raw)
To: Jason A. Donenfeld
Cc: Tom Herbert, Netdev, kernel-hardening@lists.openwall.com, LKML,
Linux Crypto Mailing List, Jean-Philippe Aumasson,
Daniel J . Bernstein, Eric Biggers, David Laight
In-Reply-To: <CAHmME9pu6No0wqPzPpaBwQR_b+5CXvh0kke7J8ouN=rx4pxMGg@mail.gmail.com>
On Wed, Dec 14, 2016 at 3:34 PM, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
> Or does your reasonable dislike of "word" still allow for the use of
> dword and qword, so that the current function names of:
dword really is confusing to people.
If you have a MIPS background, it means 64 bits. While to people with
Windows programming backgrounds it means 32 bits.
Please try to avoid using it.
As mentioned, I think almost everybody agrees on the "q" part being 64
bits, but that may just be me not having seen it in any other context.
And before anybody points it out - yes, we already have lots of uses
of "dword" in various places. But they tend to be mostly
hardware-specific - either architectures or drivers.
So I'd _prefer_ to try to keep "word" and "dword" away from generic
helper routines. But it's not like anything is really black and white.
Linus
^ permalink raw reply
* [PATCH net] bpf: fix regression on verifier pruning wrt map lookups
From: Daniel Borkmann @ 2016-12-15 0:30 UTC (permalink / raw)
To: davem; +Cc: ast, jbacik, tgraf, netdev, Daniel Borkmann
Commit 57a09bf0a416 ("bpf: Detect identical PTR_TO_MAP_VALUE_OR_NULL
registers") introduced a regression where existing programs stopped
loading due to reaching the verifier's maximum complexity limit,
whereas prior to this commit they were loading just fine; the affected
program has roughly 2k instructions.
What was found is that state pruning couldn't be performed effectively
anymore due to mismatches of the verifier's register state, in particular
in the id tracking. It doesn't mean that 57a09bf0a416 is incorrect per
se, but rather that verifier needs to perform a lot more work for the
same program with regards to involved map lookups.
Since commit 57a09bf0a416 is only about tracking registers with type
PTR_TO_MAP_VALUE_OR_NULL, the id is only needed to follow registers
until they are promoted through pattern matching with a NULL check to
either PTR_TO_MAP_VALUE or UNKNOWN_VALUE type. After that point, the
id becomes irrelevant for the transitioned types.
For UNKNOWN_VALUE, id is already reset to 0 via mark_reg_unknown_value(),
but not so for PTR_TO_MAP_VALUE where id is becoming stale. It's even
transferred further into other types that don't make use of it. Among
others, one example is where UNKNOWN_VALUE is set on function call
return with RET_INTEGER return type.
states_equal() will then fall through the memcmp() on register state;
note that the second memcmp() uses offsetofend(), so the id is part of
that since d2a4dd37f6b4 ("bpf: fix state equivalence"). But the bisect
pointed already to 57a09bf0a416, where we really reach beyond complexity
limit. What I found was that states_equal() often failed in this
case due to id mismatches in spilled regs with registers in type
PTR_TO_MAP_VALUE. Unlike non-spilled regs, spilled regs just perform
a memcmp() on their reg state and don't have any other optimizations
in place, therefore also id was relevant in this case for making a
pruning decision.
We can safely reset id to 0 as well when converting to PTR_TO_MAP_VALUE.
For the affected program, it resulted in a ~17 fold reduction of
complexity and let the program load fine again. Selftest suite also
runs fine. The only other place where env->id_gen is used currently is
through direct packet access, but for these cases id is long living, thus
a different scenario.
Also, the current logic in mark_map_regs() is not fully correct when
marking NULL branch with UNKNOWN_VALUE. We need to cache the destination
reg's id in any case. Otherwise, once we marked that reg as UNKNOWN_VALUE,
it's id is reset and any subsequent registers that hold the original id
and are of type PTR_TO_MAP_VALUE_OR_NULL won't be marked UNKNOWN_VALUE
anymore, since mark_map_reg() reuses the uncached regs[regno].id that
was just overridden. Note, we don't need to cache it outside of
mark_map_regs(), since it's called once on this_branch and the other
time on other_branch, which are both two independent verifier states.
A test case for this is added here, too.
Fixes: 57a09bf0a416 ("bpf: Detect identical PTR_TO_MAP_VALUE_OR_NULL registers")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Thomas Graf <tgraf@suug.ch>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
kernel/bpf/verifier.c | 11 ++++++++---
tools/testing/selftests/bpf/test_verifier.c | 28 ++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index d28f9a3..81e267b 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1970,6 +1970,11 @@ static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
if (reg->type == PTR_TO_MAP_VALUE_OR_NULL && reg->id == id) {
reg->type = type;
+ /* We don't need id from this point onwards anymore, thus we
+ * should better reset it, so that state pruning has chances
+ * to take effect.
+ */
+ reg->id = 0;
if (type == UNKNOWN_VALUE)
mark_reg_unknown_value(regs, regno);
}
@@ -1982,16 +1987,16 @@ static void mark_map_regs(struct bpf_verifier_state *state, u32 regno,
enum bpf_reg_type type)
{
struct bpf_reg_state *regs = state->regs;
+ u32 id = regs[regno].id;
int i;
for (i = 0; i < MAX_BPF_REG; i++)
- mark_map_reg(regs, i, regs[regno].id, type);
+ mark_map_reg(regs, i, id, type);
for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
if (state->stack_slot_type[i] != STACK_SPILL)
continue;
- mark_map_reg(state->spilled_regs, i / BPF_REG_SIZE,
- regs[regno].id, type);
+ mark_map_reg(state->spilled_regs, i / BPF_REG_SIZE, id, type);
}
}
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 0103bf2..072dc63 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -2661,6 +2661,34 @@ struct test_val {
.prog_type = BPF_PROG_TYPE_SCHED_CLS
},
{
+ "multiple registers share map_lookup_elem bad reg type",
+ .insns = {
+ BPF_MOV64_IMM(BPF_REG_1, 10),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+ BPF_LD_MAP_FD(BPF_REG_1, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_map_lookup_elem),
+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+ BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+ BPF_MOV64_REG(BPF_REG_5, BPF_REG_0),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+ BPF_MOV64_IMM(BPF_REG_1, 1),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+ BPF_MOV64_IMM(BPF_REG_1, 2),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_3, 0, 1),
+ BPF_ST_MEM(BPF_DW, BPF_REG_3, 0, 0),
+ BPF_MOV64_IMM(BPF_REG_1, 3),
+ BPF_EXIT_INSN(),
+ },
+ .fixup_map1 = { 4 },
+ .result = REJECT,
+ .errstr = "R3 invalid mem access 'inv'",
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS
+ },
+ {
"invalid map access from else condition",
.insns = {
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
--
1.9.3
^ permalink raw reply related
* [BISECTED] v4.9: OCTEON ethernet crash
From: Aaro Koskinen @ 2016-12-15 0:32 UTC (permalink / raw)
To: Florian Fainelli, David S. Miller, David Daney, netdev
Hi,
I'm getting the following crash on every boot on OCTEON (EdgeRouter Lite)
with v4.9 (right after setting up ethernet bridging):
[ 16.814902] CPU 0 Unable to handle kernel paging request at virtual address 0000000000000080, epc == ffffffff81458570, ra == ffffffff81458804
[ 16.827805] Oops[#1]:
[ 16.830100] CPU: 0 PID: 706 Comm: ifconfig Not tainted 4.9.0-octeon-los_be07e6-00002-g29a0b7e #1
[ 16.838884] task: 800000041f9dec00 task.stack: 800000041f0d8000
[ 16.844801] $ 0 : 0000000000000000 0000000010108ce1 0000000000000000 0000000000000001
[ 16.852867] $ 4 : 800000041f98a000 800000041fb67800 0000000000000000 0000000000000002
[ 16.860932] $ 8 : 800000041fb67810 800000041f0dbb40 10434794771be290 771bf16800000001
[ 16.868997] $12 : 0000000000000000 ffffffff81383edc ffffffff81296950 0000000000000000
[ 16.877060] $16 : 800000041fb67800 800000041f98a000 ffffffff81508c48 800000041f817800
[ 16.885125] $20 : 0000000000000000 0000000000000002 0000000000000000 800000041f98a000
[ 16.893190] $24 : 0000000000000000 0000000000000000
[ 16.901256] $28 : 800000041f0d8000 800000041f0dbb10 800000041e109410 ffffffff81458804
[ 16.909321] Hi : 00000000000002c9
[ 16.912896] Lo : 0000000000001c1d
[ 16.916484] epc : ffffffff81458570 phy_attach_direct+0x38/0x1b0
[ 16.922580] ra : ffffffff81458804 phy_connect_direct+0x24/0x88
[ 16.928671] Status: 10108ce3 KX SX UX KERNEL EXL IE
[ 16.933723] Cause : 00800008 (ExcCode 02)
[ 16.937730] BadVA : 0000000000000080
[ 16.941306] PrId : 000d0601 (Cavium Octeon+)
[ 16.945660] Modules linked in: at803x
[ 16.949353] Process ifconfig (pid: 706, threadinfo=800000041f0d8000, task=800000041f9dec00, tls=00000000771c3490)
[ 16.959605] Stack : 800000041fb67800 800000041f98a000 ffffffff81508c48 0000000000000002
[ 16.967671] 0000000000000000 0000000000000000 800000041e109400 ffffffff81458804
[ 16.975734] 800000041fb67800 800000041f98a000 ffffffff81508c48 ffffffff81504cd4
[ 16.983799] 800000041f98a000 800000041f98a000 ffffffff81509830 0000000000000000
[ 16.991864] 0000000000000000 ffffffff81508f58 0000000000000000 ffffffff815087e0
[ 16.999928] 800000041f98a000 800000041f98a048 ffffffff816fcc88 0000000000001302
[ 17.007993] 0000000000008914 ffffffff8150993c ffffffff816fcc88 0000000000001302
[ 17.016057] 800000041f98a000 ffffffff8153bc6c 800000041f98a000 0000000000000008
[ 17.024122] 8000000003c500d8 0000000000000000 800000041f98a000 0000000000000341
[ 17.032187] 0000000000001043 ffffffff8153bf94 00000000000000fe 800000041f98a000
[ 17.040251] ...
[ 17.042722] Call Trace:
[ 17.045175] [<ffffffff81458570>] phy_attach_direct+0x38/0x1b0
[ 17.050927] [<ffffffff81458804>] phy_connect_direct+0x24/0x88
[ 17.056682] [<ffffffff81504cd4>] of_phy_connect+0x54/0xb0
[ 17.062089] [<ffffffff81508f58>] cvm_oct_phy_setup_device+0x48/0xc0
[ 17.068361] [<ffffffff815087e0>] cvm_oct_common_open+0x58/0x2a8
[ 17.074285] [<ffffffff8150993c>] cvm_oct_rgmii_open+0x1c/0x90
[ 17.080040] [<ffffffff8153bc6c>] __dev_open+0x104/0x198
[ 17.085270] [<ffffffff8153bf94>] __dev_change_flags+0x94/0x180
[ 17.091107] [<ffffffff8153c0a4>] dev_change_flags+0x24/0x68
[ 17.096687] [<ffffffff815c6e30>] devinet_ioctl+0x6a8/0x8b0
[ 17.102181] [<ffffffff81516e0c>] sock_do_ioctl.constprop.14+0x24/0x68
[ 17.108626] [<ffffffff81518338>] compat_sock_ioctl+0xd18/0xfc8
[ 17.114471] [<ffffffff81296a10>] compat_SyS_ioctl+0xc0/0x1980
[ 17.120222] [<ffffffff8113109c>] syscall_common+0x18/0x3c
[ 17.125621] Code: ffb20010 dc8204b8 dcb30298 <dc420080> de640000 dc520010 12440005 00a08025 0c46e4a6
[ 17.135490]
[ 17.137147] ---[ end trace f1d7b064cedee4e4 ]---
[ 17.141882] Kernel panic - not syncing: Fatal exception
[ 17.147140] ---[ end Kernel panic - not syncing: Fatal exception
Git bisect points to:
commit ec988ad78ed6d184a7f4ca6b8e962b0e8f1de461
Author: Florian Fainelli <f.fainelli@gmail.com>
Date: Tue Dec 6 20:54:43 2016 -0800
phy: Don't increment MDIO bus refcount unless it's a different owner
Reverting this patch from v4.9 fixes the issue...
A.
^ permalink raw reply
* [PATCH net] bpf, test_verifier: fix a test case error result on unprivileged
From: Daniel Borkmann @ 2016-12-15 0:39 UTC (permalink / raw)
To: davem; +Cc: ast, netdev, Daniel Borkmann
Running ./test_verifier as unprivileged lets 1 out of 98 tests fail:
[...]
#71 unpriv: check that printk is disallowed FAIL
Unexpected error message!
0: (7a) *(u64 *)(r10 -8) = 0
1: (bf) r1 = r10
2: (07) r1 += -8
3: (b7) r2 = 8
4: (bf) r3 = r1
5: (85) call bpf_trace_printk#6
unknown func bpf_trace_printk#6
[...]
The test case is correct, just that the error outcome changed with
ebb676daa1a3 ("bpf: Print function name in addition to function id").
Same as with e00c7b216f34 ("bpf: fix multiple issues in selftest suite
and samples") issue 2), so just fix up the function name.
Fixes: ebb676daa1a3 ("bpf: Print function name in addition to function id")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
tools/testing/selftests/bpf/test_verifier.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 072dc63..853d7e4 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -1059,7 +1059,7 @@ struct test_val {
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .errstr_unpriv = "unknown func 6",
+ .errstr_unpriv = "unknown func bpf_trace_printk#6",
.result_unpriv = REJECT,
.result = ACCEPT,
},
--
1.9.3
^ permalink raw reply related
* Re: [BISECTED] v4.9: OCTEON ethernet crash
From: Florian Fainelli @ 2016-12-15 0:41 UTC (permalink / raw)
To: Aaro Koskinen, David S. Miller, David Daney, netdev
In-Reply-To: <20161215003253.un6hk2ytl3auiztn@raspberrypi-2.musicnaut.iki.fi>
On 12/14/2016 04:32 PM, Aaro Koskinen wrote:
> Hi,
>
> I'm getting the following crash on every boot on OCTEON (EdgeRouter Lite)
> with v4.9 (right after setting up ethernet bridging):
>
> [ 16.814902] CPU 0 Unable to handle kernel paging request at virtual address 0000000000000080, epc == ffffffff81458570, ra == ffffffff81458804
> [ 16.827805] Oops[#1]:
> [ 16.830100] CPU: 0 PID: 706 Comm: ifconfig Not tainted 4.9.0-octeon-los_be07e6-00002-g29a0b7e #1
> [ 16.838884] task: 800000041f9dec00 task.stack: 800000041f0d8000
> [ 16.844801] $ 0 : 0000000000000000 0000000010108ce1 0000000000000000 0000000000000001
> [ 16.852867] $ 4 : 800000041f98a000 800000041fb67800 0000000000000000 0000000000000002
> [ 16.860932] $ 8 : 800000041fb67810 800000041f0dbb40 10434794771be290 771bf16800000001
> [ 16.868997] $12 : 0000000000000000 ffffffff81383edc ffffffff81296950 0000000000000000
> [ 16.877060] $16 : 800000041fb67800 800000041f98a000 ffffffff81508c48 800000041f817800
> [ 16.885125] $20 : 0000000000000000 0000000000000002 0000000000000000 800000041f98a000
> [ 16.893190] $24 : 0000000000000000 0000000000000000
> [ 16.901256] $28 : 800000041f0d8000 800000041f0dbb10 800000041e109410 ffffffff81458804
> [ 16.909321] Hi : 00000000000002c9
> [ 16.912896] Lo : 0000000000001c1d
> [ 16.916484] epc : ffffffff81458570 phy_attach_direct+0x38/0x1b0
> [ 16.922580] ra : ffffffff81458804 phy_connect_direct+0x24/0x88
> [ 16.928671] Status: 10108ce3 KX SX UX KERNEL EXL IE
> [ 16.933723] Cause : 00800008 (ExcCode 02)
> [ 16.937730] BadVA : 0000000000000080
> [ 16.941306] PrId : 000d0601 (Cavium Octeon+)
> [ 16.945660] Modules linked in: at803x
> [ 16.949353] Process ifconfig (pid: 706, threadinfo=800000041f0d8000, task=800000041f9dec00, tls=00000000771c3490)
> [ 16.959605] Stack : 800000041fb67800 800000041f98a000 ffffffff81508c48 0000000000000002
> [ 16.967671] 0000000000000000 0000000000000000 800000041e109400 ffffffff81458804
> [ 16.975734] 800000041fb67800 800000041f98a000 ffffffff81508c48 ffffffff81504cd4
> [ 16.983799] 800000041f98a000 800000041f98a000 ffffffff81509830 0000000000000000
> [ 16.991864] 0000000000000000 ffffffff81508f58 0000000000000000 ffffffff815087e0
> [ 16.999928] 800000041f98a000 800000041f98a048 ffffffff816fcc88 0000000000001302
> [ 17.007993] 0000000000008914 ffffffff8150993c ffffffff816fcc88 0000000000001302
> [ 17.016057] 800000041f98a000 ffffffff8153bc6c 800000041f98a000 0000000000000008
> [ 17.024122] 8000000003c500d8 0000000000000000 800000041f98a000 0000000000000341
> [ 17.032187] 0000000000001043 ffffffff8153bf94 00000000000000fe 800000041f98a000
> [ 17.040251] ...
> [ 17.042722] Call Trace:
> [ 17.045175] [<ffffffff81458570>] phy_attach_direct+0x38/0x1b0
> [ 17.050927] [<ffffffff81458804>] phy_connect_direct+0x24/0x88
> [ 17.056682] [<ffffffff81504cd4>] of_phy_connect+0x54/0xb0
> [ 17.062089] [<ffffffff81508f58>] cvm_oct_phy_setup_device+0x48/0xc0
> [ 17.068361] [<ffffffff815087e0>] cvm_oct_common_open+0x58/0x2a8
> [ 17.074285] [<ffffffff8150993c>] cvm_oct_rgmii_open+0x1c/0x90
> [ 17.080040] [<ffffffff8153bc6c>] __dev_open+0x104/0x198
> [ 17.085270] [<ffffffff8153bf94>] __dev_change_flags+0x94/0x180
> [ 17.091107] [<ffffffff8153c0a4>] dev_change_flags+0x24/0x68
> [ 17.096687] [<ffffffff815c6e30>] devinet_ioctl+0x6a8/0x8b0
> [ 17.102181] [<ffffffff81516e0c>] sock_do_ioctl.constprop.14+0x24/0x68
> [ 17.108626] [<ffffffff81518338>] compat_sock_ioctl+0xd18/0xfc8
> [ 17.114471] [<ffffffff81296a10>] compat_SyS_ioctl+0xc0/0x1980
> [ 17.120222] [<ffffffff8113109c>] syscall_common+0x18/0x3c
> [ 17.125621] Code: ffb20010 dc8204b8 dcb30298 <dc420080> de640000 dc520010 12440005 00a08025 0c46e4a6
> [ 17.135490]
> [ 17.137147] ---[ end trace f1d7b064cedee4e4 ]---
> [ 17.141882] Kernel panic - not syncing: Fatal exception
> [ 17.147140] ---[ end Kernel panic - not syncing: Fatal exception
>
> Git bisect points to:
>
> commit ec988ad78ed6d184a7f4ca6b8e962b0e8f1de461
> Author: Florian Fainelli <f.fainelli@gmail.com>
> Date: Tue Dec 6 20:54:43 2016 -0800
>
> phy: Don't increment MDIO bus refcount unless it's a different owner
>
> Reverting this patch from v4.9 fixes the issue...
This should help:
diff --git a/drivers/staging/octeon/ethernet.c
b/drivers/staging/octeon/ethernet.c
index 8130dfe89745..12ebc4d800c3 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -770,6 +770,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
/* Initialize the device private structure. */
struct octeon_ethernet *priv = netdev_priv(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
dev->netdev_ops = &cvm_oct_pow_netdev_ops;
priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
priv->port = CVMX_PIP_NUM_INPUT_PORTS;
--
Florian
^ permalink raw reply related
* Re: [PATCH net] bpf, test_verifier: fix a test case error result on unprivileged
From: Alexei Starovoitov @ 2016-12-15 0:43 UTC (permalink / raw)
To: Daniel Borkmann, davem; +Cc: netdev
In-Reply-To: <639d61f73c907b704001ed2b115208998990eb38.1481762158.git.daniel@iogearbox.net>
On 12/14/16 4:39 PM, Daniel Borkmann wrote:
> Running ./test_verifier as unprivileged lets 1 out of 98 tests fail:
>
> [...]
> #71 unpriv: check that printk is disallowed FAIL
> Unexpected error message!
> 0: (7a) *(u64 *)(r10 -8) = 0
> 1: (bf) r1 = r10
> 2: (07) r1 += -8
> 3: (b7) r2 = 8
> 4: (bf) r3 = r1
> 5: (85) call bpf_trace_printk#6
> unknown func bpf_trace_printk#6
> [...]
>
> The test case is correct, just that the error outcome changed with
> ebb676daa1a3 ("bpf: Print function name in addition to function id").
> Same as with e00c7b216f34 ("bpf: fix multiple issues in selftest suite
> and samples") issue 2), so just fix up the function name.
>
> Fixes: ebb676daa1a3 ("bpf: Print function name in addition to function id")
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
was thinking to send the same fix. Thanks you for beating me :)
Acked-by: Alexei Starovoitov <ast@kernel.org>
^ permalink raw reply
* Re: [PATCH net-next 1/1] driver: ipvlan: Define common functions to decrease duplicated codes used to add or del IP address
From: Feng Gao @ 2016-12-15 0:50 UTC (permalink / raw)
To: David S. Miller, Mahesh Bandewar, Eric Dumazet,
Linux Kernel Network Developers, Feng Gao
In-Reply-To: <1481727165-18824-1-git-send-email-fgao@ikuai8.com>
On Wed, Dec 14, 2016 at 10:52 PM, <fgao@ikuai8.com> wrote:
> From: Gao Feng <gfree.wind@gmail.com>
>
> There are some duplicated codes in ipvlan_add_addr6/4 and
> ipvlan_del_addr6/4. Now define two common functions ipvlan_add_addr
> and ipvlan_del_addr to decrease the duplicated codes.
> It could be helful to maintain the codes.
>
> Signed-off-by: Gao Feng <gfree.wind@gmail.com>
> ---
> drivers/net/ipvlan/ipvlan_main.c | 68 +++++++++++++++++-----------------------
> 1 file changed, 29 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
> index 693ec5b..5874d30 100644
> --- a/drivers/net/ipvlan/ipvlan_main.c
> +++ b/drivers/net/ipvlan/ipvlan_main.c
> @@ -669,23 +669,22 @@ static int ipvlan_device_event(struct notifier_block *unused,
> return NOTIFY_DONE;
> }
>
> -static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
> +static int ipvlan_add_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
> {
> struct ipvl_addr *addr;
>
> - if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) {
> - netif_err(ipvlan, ifup, ipvlan->dev,
> - "Failed to add IPv6=%pI6c addr for %s intf\n",
> - ip6_addr, ipvlan->dev->name);
> - return -EINVAL;
> - }
> addr = kzalloc(sizeof(struct ipvl_addr), GFP_ATOMIC);
> if (!addr)
> return -ENOMEM;
>
> addr->master = ipvlan;
> - memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr));
> - addr->atype = IPVL_IPV6;
> + if (is_v6) {
> + memcpy(&addr->ip6addr, iaddr, sizeof(struct in6_addr));
> + addr->atype = IPVL_IPV6;
> + } else {
> + memcpy(&addr->ip4addr, iaddr, sizeof(struct in_addr));
> + addr->atype = IPVL_IPV4;
> + }
> list_add_tail(&addr->anode, &ipvlan->addrs);
>
> /* If the interface is not up, the address will be added to the hash
> @@ -697,11 +696,11 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
> return 0;
> }
>
> -static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
> +static void ipvlan_del_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
> {
> struct ipvl_addr *addr;
>
> - addr = ipvlan_find_addr(ipvlan, ip6_addr, true);
> + addr = ipvlan_find_addr(ipvlan, iaddr, is_v6);
> if (!addr)
> return;
>
> @@ -712,6 +711,23 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
> return;
> }
>
> +static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
> +{
> + if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) {
> + netif_err(ipvlan, ifup, ipvlan->dev,
> + "Failed to add IPv6=%pI6c addr for %s intf\n",
> + ip6_addr, ipvlan->dev->name);
> + return -EINVAL;
> + }
> +
> + return ipvlan_add_addr(ipvlan, ip6_addr, true);
> +}
> +
> +static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
> +{
> + return ipvlan_del_addr(ipvlan, ip6_addr, true);
> +}
> +
> static int ipvlan_addr6_event(struct notifier_block *unused,
> unsigned long event, void *ptr)
> {
> @@ -745,45 +761,19 @@ static int ipvlan_addr6_event(struct notifier_block *unused,
>
> static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
> {
> - struct ipvl_addr *addr;
> -
> if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) {
> netif_err(ipvlan, ifup, ipvlan->dev,
> "Failed to add IPv4=%pI4 on %s intf.\n",
> ip4_addr, ipvlan->dev->name);
> return -EINVAL;
> }
> - addr = kzalloc(sizeof(struct ipvl_addr), GFP_KERNEL);
> - if (!addr)
> - return -ENOMEM;
> -
> - addr->master = ipvlan;
> - memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr));
> - addr->atype = IPVL_IPV4;
> - list_add_tail(&addr->anode, &ipvlan->addrs);
> -
> - /* If the interface is not up, the address will be added to the hash
> - * list by ipvlan_open.
> - */
> - if (netif_running(ipvlan->dev))
> - ipvlan_ht_addr_add(ipvlan, addr);
>
> - return 0;
> + return ipvlan_add_addr(ipvlan, ip4_addr, false);
> }
>
> static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
> {
> - struct ipvl_addr *addr;
> -
> - addr = ipvlan_find_addr(ipvlan, ip4_addr, false);
> - if (!addr)
> - return;
> -
> - ipvlan_ht_addr_del(addr);
> - list_del(&addr->anode);
> - kfree_rcu(addr, rcu);
> -
> - return;
> + return ipvlan_del_addr(ipvlan, ip4_addr, false);
> }
>
> static int ipvlan_addr4_event(struct notifier_block *unused,
> --
> 1.9.1
>
>
Sorry, I just remember the "net-next" cleanup is closing.
Ignore this commit please, I would send a new after "net-next" is opened.
Regards
Feng
^ permalink raw reply
* [PATCH net-next 0/2] inet: Fixes for inet_csk_get_port and soreusport
From: Tom Herbert @ 2016-12-15 0:54 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team, jbacik, eric.dumazet, raigatgoog
This patch set fixes a couple of issues I noticed while debugging our
softlockup issue in inet_csk_get_port.
- Don't allow jump into port scan in inet_csk_get_port if function
was called with non-zero port number (looking up explicit port
number).
- When inet_csk_get_port is called with zero port number (ie. perform
scan) an reuseport is set on the socket, don't match sockets that
also have reuseport set. The intent from the user should be
to get a new port number and then explictly bind other
sockets to that number using soreuseport.
Tested:
Ran first patch on production workload with no ill effect.
For second patch, ran a little listener application and first
demonstrated that unbound sockets with soreuseport can indeed
be bound to unrelated soreuseport sockets.
Tom Herbert (2):
inet: Don't go into port scan when looking for specific bind port
inet: Fix get port to handle zero port number with soreuseport set
include/net/inet6_connection_sock.h | 3 ++-
include/net/inet_connection_sock.h | 6 ++++--
net/ipv4/inet_connection_sock.c | 16 ++++++++++------
net/ipv6/inet6_connection_sock.c | 7 ++++---
4 files changed, 20 insertions(+), 12 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH net-next 2/2] inet: Fix get port to handle zero port number with soreuseport set
From: Tom Herbert @ 2016-12-15 0:54 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team, jbacik, eric.dumazet, raigatgoog
In-Reply-To: <20161215005416.1561632-1-tom@herbertland.com>
A user may call listen with binding an explicit port with the intent
that the kernel will assign an available port to the socket. In this
case inet_csk_get_port does a port scan. For such sockets, the user may
also set soreuseport with the intent a creating more sockets for the
port that is selected. The problem is that the initial socket being
opened could inadvertently choose an existing and unreleated port
number that was already created with soreuseport.
This patch adds a boolean parameter to inet_bind_conflict that indicates
rather soreuseport is allowed for the check (in addition to
sk->sk_reuseport). In calls to inet_bind_conflict from inet_csk_get_port
the argument is set to true if an explicit port is being looked up (snum
argument is nonzero), and is false if port scan is done.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/inet6_connection_sock.h | 3 ++-
include/net/inet_connection_sock.h | 6 ++++--
net/ipv4/inet_connection_sock.c | 14 +++++++++-----
net/ipv6/inet6_connection_sock.c | 7 ++++---
4 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index 954ad6b..3212b39 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -22,7 +22,8 @@ struct sock;
struct sockaddr;
int inet6_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax);
+ const struct inet_bind_bucket *tb, bool relax,
+ bool soreuseport_ok);
struct dst_entry *inet6_csk_route_req(const struct sock *sk, struct flowi6 *fl6,
const struct request_sock *req, u8 proto);
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 146054c..85ee387 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -63,7 +63,8 @@ struct inet_connection_sock_af_ops {
#endif
void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
int (*bind_conflict)(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax);
+ const struct inet_bind_bucket *tb,
+ bool relax, bool soreuseport_ok);
void (*mtu_reduced)(struct sock *sk);
};
@@ -261,7 +262,8 @@ inet_csk_rto_backoff(const struct inet_connection_sock *icsk,
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
int inet_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax);
+ const struct inet_bind_bucket *tb, bool relax,
+ bool soreuseport_ok);
int inet_csk_get_port(struct sock *sk, unsigned short snum);
struct dst_entry *inet_csk_route_req(const struct sock *sk, struct flowi4 *fl4,
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index f59838a6..19ea045 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -45,11 +45,12 @@ void inet_get_local_port_range(struct net *net, int *low, int *high)
EXPORT_SYMBOL(inet_get_local_port_range);
int inet_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax)
+ const struct inet_bind_bucket *tb, bool relax,
+ bool reuseport_ok)
{
struct sock *sk2;
- int reuse = sk->sk_reuse;
- int reuseport = sk->sk_reuseport;
+ bool reuse = sk->sk_reuse;
+ bool reuseport = !!sk->sk_reuseport && reuseport_ok;
kuid_t uid = sock_i_uid((struct sock *)sk);
/*
@@ -105,6 +106,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
struct inet_bind_bucket *tb;
kuid_t uid = sock_i_uid(sk);
u32 remaining, offset;
+ bool reuseport_ok = !!snum;
if (port) {
have_port:
@@ -165,7 +167,8 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
smallest_size = tb->num_owners;
smallest_port = port;
}
- if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false))
+ if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false,
+ reuseport_ok))
goto tb_found;
goto next_port;
}
@@ -206,7 +209,8 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
sk->sk_reuseport && uid_eq(tb->fastuid, uid))) &&
smallest_size == -1)
goto success;
- if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true)) {
+ if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true,
+ reuseport_ok)) {
if ((reuse ||
(tb->fastreuseport > 0 &&
sk->sk_reuseport &&
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 1c86c47..7396e75 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -29,11 +29,12 @@
#include <net/sock_reuseport.h>
int inet6_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax)
+ const struct inet_bind_bucket *tb, bool relax,
+ bool reuseport_ok)
{
const struct sock *sk2;
- int reuse = sk->sk_reuse;
- int reuseport = sk->sk_reuseport;
+ bool reuse = !!sk->sk_reuse;
+ bool reuseport = !!sk->sk_reuseport && reuseport_ok;
kuid_t uid = sock_i_uid((struct sock *)sk);
/* We must walk the whole port owner list in this case. -DaveM */
--
2.9.3
^ permalink raw reply related
* [PATCH net-next 1/2] inet: Don't go into port scan when looking for specific bind port
From: Tom Herbert @ 2016-12-15 0:54 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team, jbacik, eric.dumazet, raigatgoog
In-Reply-To: <20161215005416.1561632-1-tom@herbertland.com>
inet_csk_get_port is called with port number (snum argument) that may be
zero or nonzero. If it is zero, then the intent is to find an available
ephemeral port number to bind to. If snum is non-zero then the caller
is asking to allocate a specific port number. In the latter case we
never want to perform the scan in ephemeral port range. It is
conceivable that this can happen if the "goto again" in "tb_found:"
is done. This patch adds a check that snum is zero before doing
the "goto again".
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/ipv4/inet_connection_sock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index d5d3ead..f59838a6 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -212,7 +212,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
sk->sk_reuseport &&
!rcu_access_pointer(sk->sk_reuseport_cb) &&
uid_eq(tb->fastuid, uid))) &&
- smallest_size != -1 && --attempts >= 0) {
+ !snum && smallest_size != -1 && --attempts >= 0) {
spin_unlock_bh(&head->lock);
goto again;
}
--
2.9.3
^ permalink raw reply related
* Re: [BISECTED] v4.9: OCTEON ethernet crash
From: Aaro Koskinen @ 2016-12-15 0:57 UTC (permalink / raw)
To: Florian Fainelli; +Cc: David S. Miller, David Daney, netdev
In-Reply-To: <f70acf45-191d-215a-0019-420627a35d98@gmail.com>
Hi,
On Wed, Dec 14, 2016 at 04:41:13PM -0800, Florian Fainelli wrote:
> On 12/14/2016 04:32 PM, Aaro Koskinen wrote:
> > Git bisect points to:
> >
> > commit ec988ad78ed6d184a7f4ca6b8e962b0e8f1de461
> > Author: Florian Fainelli <f.fainelli@gmail.com>
> > Date: Tue Dec 6 20:54:43 2016 -0800
> >
> > phy: Don't increment MDIO bus refcount unless it's a different owner
> >
> > Reverting this patch from v4.9 fixes the issue...
>
> This should help:
>
> diff --git a/drivers/staging/octeon/ethernet.c
> b/drivers/staging/octeon/ethernet.c
> index 8130dfe89745..12ebc4d800c3 100644
> --- a/drivers/staging/octeon/ethernet.c
> +++ b/drivers/staging/octeon/ethernet.c
> @@ -770,6 +770,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
> /* Initialize the device private structure. */
> struct octeon_ethernet *priv = netdev_priv(dev);
>
> + SET_NETDEV_DEV(dev, &pdev->dev);
> dev->netdev_ops = &cvm_oct_pow_netdev_ops;
> priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
> priv->port = CVMX_PIP_NUM_INPUT_PORTS;
No, it's still crashing.
A.
^ permalink raw reply
* Re: [BISECTED] v4.9: OCTEON ethernet crash
From: Florian Fainelli @ 2016-12-15 1:00 UTC (permalink / raw)
To: Aaro Koskinen; +Cc: David S. Miller, David Daney, netdev
In-Reply-To: <20161215005751.457nm46shyjdt63q@raspberrypi-2.musicnaut.iki.fi>
On 12/14/2016 04:57 PM, Aaro Koskinen wrote:
> Hi,
>
> On Wed, Dec 14, 2016 at 04:41:13PM -0800, Florian Fainelli wrote:
>> On 12/14/2016 04:32 PM, Aaro Koskinen wrote:
>>> Git bisect points to:
>>>
>>> commit ec988ad78ed6d184a7f4ca6b8e962b0e8f1de461
>>> Author: Florian Fainelli <f.fainelli@gmail.com>
>>> Date: Tue Dec 6 20:54:43 2016 -0800
>>>
>>> phy: Don't increment MDIO bus refcount unless it's a different owner
>>>
>>> Reverting this patch from v4.9 fixes the issue...
>>
>> This should help:
>>
>> diff --git a/drivers/staging/octeon/ethernet.c
>> b/drivers/staging/octeon/ethernet.c
>> index 8130dfe89745..12ebc4d800c3 100644
>> --- a/drivers/staging/octeon/ethernet.c
>> +++ b/drivers/staging/octeon/ethernet.c
>> @@ -770,6 +770,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
>> /* Initialize the device private structure. */
>> struct octeon_ethernet *priv = netdev_priv(dev);
>>
>> + SET_NETDEV_DEV(dev, &pdev->dev);
>> dev->netdev_ops = &cvm_oct_pow_netdev_ops;
>> priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
>> priv->port = CVMX_PIP_NUM_INPUT_PORTS;
>
> No, it's still crashing.
How about this:
diff --git a/drivers/staging/octeon/ethernet.c
b/drivers/staging/octeon/ethernet.c
index 12ebc4d800c3..4971aa54756a 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -817,6 +817,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
}
/* Initialize the device private structure. */
+ SET_NETDEV_DEV(dev, &pdev->dev);
priv = netdev_priv(dev);
priv->netdev = dev;
priv->of_node = cvm_oct_node_for_port(pip,
interface,
--
Florian
^ permalink raw reply related
* Re: [BISECTED] v4.9: OCTEON ethernet crash
From: Aaro Koskinen @ 2016-12-15 1:12 UTC (permalink / raw)
To: Florian Fainelli; +Cc: David S. Miller, David Daney, netdev
In-Reply-To: <4ca48a84-c041-d698-e55b-0c8da0fc4140@gmail.com>
Hi,
On Wed, Dec 14, 2016 at 05:00:59PM -0800, Florian Fainelli wrote:
> On 12/14/2016 04:57 PM, Aaro Koskinen wrote:
> > On Wed, Dec 14, 2016 at 04:41:13PM -0800, Florian Fainelli wrote:
> >> On 12/14/2016 04:32 PM, Aaro Koskinen wrote:
> >>> Git bisect points to:
> >>>
> >>> commit ec988ad78ed6d184a7f4ca6b8e962b0e8f1de461
> >>> Author: Florian Fainelli <f.fainelli@gmail.com>
> >>> Date: Tue Dec 6 20:54:43 2016 -0800
> >>>
> >>> phy: Don't increment MDIO bus refcount unless it's a different owner
> >>>
> >>> Reverting this patch from v4.9 fixes the issue...
> >>
> >> This should help:
> >>
> >> diff --git a/drivers/staging/octeon/ethernet.c
> >> b/drivers/staging/octeon/ethernet.c
> >> index 8130dfe89745..12ebc4d800c3 100644
> >> --- a/drivers/staging/octeon/ethernet.c
> >> +++ b/drivers/staging/octeon/ethernet.c
> >> @@ -770,6 +770,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
> >> /* Initialize the device private structure. */
> >> struct octeon_ethernet *priv = netdev_priv(dev);
> >>
> >> + SET_NETDEV_DEV(dev, &pdev->dev);
> >> dev->netdev_ops = &cvm_oct_pow_netdev_ops;
> >> priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
> >> priv->port = CVMX_PIP_NUM_INPUT_PORTS;
> >
> > No, it's still crashing.
>
> How about this:
>
> diff --git a/drivers/staging/octeon/ethernet.c
> b/drivers/staging/octeon/ethernet.c
> index 12ebc4d800c3..4971aa54756a 100644
> --- a/drivers/staging/octeon/ethernet.c
> +++ b/drivers/staging/octeon/ethernet.c
> @@ -817,6 +817,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
> }
>
> /* Initialize the device private structure. */
> + SET_NETDEV_DEV(dev, &pdev->dev);
> priv = netdev_priv(dev);
> priv->netdev = dev;
> priv->of_node = cvm_oct_node_for_port(pip,
> interface,
Yeah, that seems to work - thanks! Could you send this to
devel@driverdev.osuosl.org as a formal patch?
A.
^ permalink raw reply
* [PATCH] staging: octeon: Call SET_NETDEV_DEV()
From: Florian Fainelli @ 2016-12-15 1:13 UTC (permalink / raw)
To: netdev
Cc: open list:STAGING SUBSYSTEM, Asbjoern Sloth Toennesen,
Florian Fainelli, Aaro Koskinen, Greg Kroah-Hartman,
Laura Garcia Liebana, open list, Jarod Wilson,
Bhaktipriya Shridhar, davem, Philippe Reynes
The Octeon driver calls into PHYLIB which now checks for
net_device->dev.parent, so make sure we do set it before calling into
any MDIO/PHYLIB related function.
Fixes: ec988ad78ed6 ("phy: Don't increment MDIO bus refcount unless it's a different owner")
Reported-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/staging/octeon/ethernet.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 8130dfe89745..4971aa54756a 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -770,6 +770,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
/* Initialize the device private structure. */
struct octeon_ethernet *priv = netdev_priv(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
dev->netdev_ops = &cvm_oct_pow_netdev_ops;
priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
priv->port = CVMX_PIP_NUM_INPUT_PORTS;
@@ -816,6 +817,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
}
/* Initialize the device private structure. */
+ SET_NETDEV_DEV(dev, &pdev->dev);
priv = netdev_priv(dev);
priv->netdev = dev;
priv->of_node = cvm_oct_node_for_port(pip, interface,
--
2.9.3
^ permalink raw reply related
* Re: [BISECTED] v4.9: OCTEON ethernet crash
From: Florian Fainelli @ 2016-12-15 1:14 UTC (permalink / raw)
To: Aaro Koskinen; +Cc: David S. Miller, David Daney, netdev
In-Reply-To: <20161215011203.nyyl5izlzkqtium5@raspberrypi-2.musicnaut.iki.fi>
On 12/14/2016 05:12 PM, Aaro Koskinen wrote:
> Hi,
>
> On Wed, Dec 14, 2016 at 05:00:59PM -0800, Florian Fainelli wrote:
>> On 12/14/2016 04:57 PM, Aaro Koskinen wrote:
>>> On Wed, Dec 14, 2016 at 04:41:13PM -0800, Florian Fainelli wrote:
>>>> On 12/14/2016 04:32 PM, Aaro Koskinen wrote:
>>>>> Git bisect points to:
>>>>>
>>>>> commit ec988ad78ed6d184a7f4ca6b8e962b0e8f1de461
>>>>> Author: Florian Fainelli <f.fainelli@gmail.com>
>>>>> Date: Tue Dec 6 20:54:43 2016 -0800
>>>>>
>>>>> phy: Don't increment MDIO bus refcount unless it's a different owner
>>>>>
>>>>> Reverting this patch from v4.9 fixes the issue...
>>>>
>>>> This should help:
>>>>
>>>> diff --git a/drivers/staging/octeon/ethernet.c
>>>> b/drivers/staging/octeon/ethernet.c
>>>> index 8130dfe89745..12ebc4d800c3 100644
>>>> --- a/drivers/staging/octeon/ethernet.c
>>>> +++ b/drivers/staging/octeon/ethernet.c
>>>> @@ -770,6 +770,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
>>>> /* Initialize the device private structure. */
>>>> struct octeon_ethernet *priv = netdev_priv(dev);
>>>>
>>>> + SET_NETDEV_DEV(dev, &pdev->dev);
>>>> dev->netdev_ops = &cvm_oct_pow_netdev_ops;
>>>> priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
>>>> priv->port = CVMX_PIP_NUM_INPUT_PORTS;
>>>
>>> No, it's still crashing.
>>
>> How about this:
>>
>> diff --git a/drivers/staging/octeon/ethernet.c
>> b/drivers/staging/octeon/ethernet.c
>> index 12ebc4d800c3..4971aa54756a 100644
>> --- a/drivers/staging/octeon/ethernet.c
>> +++ b/drivers/staging/octeon/ethernet.c
>> @@ -817,6 +817,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
>> }
>>
>> /* Initialize the device private structure. */
>> + SET_NETDEV_DEV(dev, &pdev->dev);
>> priv = netdev_priv(dev);
>> priv->netdev = dev;
>> priv->of_node = cvm_oct_node_for_port(pip,
>> interface,
>
> Yeah, that seems to work - thanks! Could you send this to
> devel@driverdev.osuosl.org as a formal patch?
Sure thing, thanks for verifying it. Sent.
--
Florian
^ permalink raw reply
* Re: Re: [PATCH 4/3] random: use siphash24 instead of md5 for get_random_int/long
From: Jason A. Donenfeld @ 2016-12-15 1:19 UTC (permalink / raw)
To: kernel-hardening, Theodore Ts'o, Jason A. Donenfeld, Netdev,
David Miller, Linus Torvalds, LKML, George Spelvin, Scott Bauer,
Andi Kleen, Andy Lutomirski, Greg KH, Eric Biggers,
Linux Crypto Mailing List, Jean-Philippe Aumasson
In-Reply-To: <CAHmME9o3uQoi5h=YTKB=5yN1yzz=d3=GFjGiXv_Sf12kAsjx3A@mail.gmail.com>
Hey Ted,
On Wed, Dec 14, 2016 at 8:12 PM, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
> I think this opens up a big window for optimizing it even
> further.
I optimized it a bit further and siphash is now the clear winner over chacha:
[ 1.784801] random benchmark!!
[ 1.785161] get_random_long # cycles: 415983
[ 1.785595] get_random_long_chacha # cycles: 242047
[ 1.785997] get_random_long_siphash # cycles: 137130
[ 1.787450] get_random_bytes # cycles: 1452985
[ 1.787947] get_random_int # cycles: 343323
[ 1.788282] get_random_int_chacha # cycles: 170767
[ 1.788656] get_random_int_siphash # cycles: 86384
[ 1.789764] get_random_bytes # cycles: 2279519
And even still, there is more that could be optimized. Therefore, I'll
continue to keep this patch in the series and will CC you on the next
patch set that goes out.
Jason
^ permalink raw reply
* [PATCH v4 1/4] siphash: add cryptographically secure hashtable function
From: Jason A. Donenfeld @ 2016-12-15 1:46 UTC (permalink / raw)
To: Netdev, kernel-hardening, LKML, linux-crypto
Cc: Jason A. Donenfeld, Jean-Philippe Aumasson, Daniel J . Bernstein,
Linus Torvalds, Eric Biggers, David Laight
In-Reply-To: <20161214184605.24006-1-Jason@zx2c4.com>
SipHash is a 64-bit keyed hash function that is actually a
cryptographically secure PRF, like HMAC. Except SipHash is super fast,
and is meant to be used as a hashtable keyed lookup function.
There are a variety of attacks known as "hashtable poisoning" in which an
attacker forms some data such that the hash of that data will be the
same, and then preceeds to fill up all entries of a hashbucket. This is
a realistic and well-known denial-of-service vector.
Linux developers already seem to be aware that this is an issue, and
various places that use hash tables in, say, a network context, use a
non-cryptographically secure function (usually jhash) and then try to
twiddle with the key on a time basis (or in many cases just do nothing
and hope that nobody notices). While this is an admirable attempt at
solving the problem, it doesn't actually fix it. SipHash fixes it.
(It fixes it in such a sound way that you could even build a stream
cipher out of SipHash that would resist the modern cryptanalysis.)
There are a modicum of places in the kernel that are vulnerable to
hashtable poisoning attacks, either via userspace vectors or network
vectors, and there's not a reliable mechanism inside the kernel at the
moment to fix it. The first step toward fixing these issues is actually
getting a secure primitive into the kernel for developers to use. Then
we can, bit by bit, port things over to it as deemed appropriate.
Secondly, a few places are using MD5 for creating secure sequence
numbers, port numbers, or fast random numbers. Siphash is a faster, more
fitting, and more secure replacement for MD5 in those situations.
Dozens of languages are already using this internally for their hash
tables. Some of the BSDs already use this in their kernels. SipHash is
a widely known high-speed solution to a widely known problem, and it's
time we catch-up.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
Cc: Daniel J. Bernstein <djb@cr.yp.to>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Eric Biggers <ebiggers3@gmail.com>
Cc: David Laight <David.Laight@aculab.com>
---
Changes from v3->v4:
- Renamed from siphash24 to siphash.
- Using macros instead of enums for old gcc.
- Keys must now always be aligned, even for the unaligned data
one, since generally these keys are just long term secrets
which are easy to ensure are aligned anyway.
include/linux/siphash.h | 30 ++++++++++
lib/Kconfig.debug | 6 +-
lib/Makefile | 5 +-
lib/siphash.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/test_siphash.c | 84 ++++++++++++++++++++++++++
5 files changed, 273 insertions(+), 5 deletions(-)
create mode 100644 include/linux/siphash.h
create mode 100644 lib/siphash.c
create mode 100644 lib/test_siphash.c
diff --git a/include/linux/siphash.h b/include/linux/siphash.h
new file mode 100644
index 000000000000..d0bcca7b992b
--- /dev/null
+++ b/include/linux/siphash.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.
+ *
+ * SipHash: a fast short-input PRF
+ * https://131002.net/siphash/
+ *
+ * This implementation is specifically for SipHash2-4.
+ */
+
+#ifndef _LINUX_SIPHASH_H
+#define _LINUX_SIPHASH_H
+
+#include <linux/types.h>
+
+#define SIPHASH_KEY_LEN 16
+#define SIPHASH_ALIGNMENT 8
+
+u64 siphash(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN]);
+
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+static inline u64 siphash_unaligned(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN])
+{
+ return siphash(data, len, key);
+}
+#else
+u64 siphash_unaligned(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN]);
+#endif
+
+#endif /* _LINUX_SIPHASH_H */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index e6327d102184..32bbf689fc46 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1843,9 +1843,9 @@ config TEST_HASH
tristate "Perform selftest on hash functions"
default n
help
- Enable this option to test the kernel's integer (<linux/hash,h>)
- and string (<linux/stringhash.h>) hash functions on boot
- (or module load).
+ Enable this option to test the kernel's integer (<linux/hash.h>),
+ string (<linux/stringhash.h>), and siphash (<linux/siphash.h>)
+ hash functions on boot (or module load).
This is intended to help people writing architecture-specific
optimized versions. If unsure, say N.
diff --git a/lib/Makefile b/lib/Makefile
index 50144a3aeebd..71d398b04a74 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -22,7 +22,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
sha1.o chacha20.o md5.o irq_regs.o argv_split.o \
flex_proportions.o ratelimit.o show_mem.o \
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
- earlycpio.o seq_buf.o nmi_backtrace.o nodemask.o win_minmax.o
+ earlycpio.o seq_buf.o siphash.o \
+ nmi_backtrace.o nodemask.o win_minmax.o
lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
@@ -44,7 +45,7 @@ obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
obj-y += kstrtox.o
obj-$(CONFIG_TEST_BPF) += test_bpf.o
obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
-obj-$(CONFIG_TEST_HASH) += test_hash.o
+obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o
obj-$(CONFIG_TEST_KASAN) += test_kasan.o
obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
obj-$(CONFIG_TEST_LKM) += test_module.o
diff --git a/lib/siphash.c b/lib/siphash.c
new file mode 100644
index 000000000000..b500231f61cd
--- /dev/null
+++ b/lib/siphash.c
@@ -0,0 +1,153 @@
+/* Copyright (C) 2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.
+ *
+ * SipHash: a fast short-input PRF
+ * https://131002.net/siphash/
+ *
+ * This implementation is specifically for SipHash2-4.
+ */
+
+#include <linux/siphash.h>
+#include <linux/kernel.h>
+#include <asm/unaligned.h>
+
+#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
+#include <linux/dcache.h>
+#include <asm/word-at-a-time.h>
+#endif
+
+static inline u16 le16_to_cpuvp(const void *p)
+{
+ return le16_to_cpup(p);
+}
+static inline u32 le32_to_cpuvp(const void *p)
+{
+ return le32_to_cpup(p);
+}
+static inline u64 le64_to_cpuvp(const void *p)
+{
+ return le64_to_cpup(p);
+}
+
+#define SIPROUND \
+ do { \
+ v0 += v1; v1 = rol64(v1, 13); v1 ^= v0; v0 = rol64(v0, 32); \
+ v2 += v3; v3 = rol64(v3, 16); v3 ^= v2; \
+ v0 += v3; v3 = rol64(v3, 21); v3 ^= v0; \
+ v2 += v1; v1 = rol64(v1, 17); v1 ^= v2; v2 = rol64(v2, 32); \
+ } while(0)
+
+/**
+ * siphash - compute 64-bit siphash PRF value
+ * @data: buffer to hash, must be aligned to SIPHASH_ALIGNMENT
+ * @size: size of @data
+ * @key: key buffer of size SIPHASH_KEY_LEN, must be aligned to SIPHASH_ALIGNMENT
+ */
+u64 siphash(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN])
+{
+ u64 v0 = 0x736f6d6570736575ULL;
+ u64 v1 = 0x646f72616e646f6dULL;
+ u64 v2 = 0x6c7967656e657261ULL;
+ u64 v3 = 0x7465646279746573ULL;
+ u64 b = ((u64)len) << 56;
+ u64 k0 = le64_to_cpuvp(key);
+ u64 k1 = le64_to_cpuvp(key + sizeof(u64));
+ u64 m;
+ const u8 *end = data + len - (len % sizeof(u64));
+ const u8 left = len & (sizeof(u64) - 1);
+ v3 ^= k1;
+ v2 ^= k0;
+ v1 ^= k1;
+ v0 ^= k0;
+ for (; data != end; data += sizeof(u64)) {
+ m = le64_to_cpuvp(data);
+ v3 ^= m;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= m;
+ }
+#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
+ if (left)
+ b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) & bytemask_from_count(left)));
+#else
+ switch (left) {
+ case 7: b |= ((u64)data[6]) << 48;
+ case 6: b |= ((u64)data[5]) << 40;
+ case 5: b |= ((u64)data[4]) << 32;
+ case 4: b |= le32_to_cpuvp(data); break;
+ case 3: b |= ((u64)data[2]) << 16;
+ case 2: b |= le16_to_cpuvp(data); break;
+ case 1: b |= data[0];
+ }
+#endif
+ v3 ^= b;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= b;
+ v2 ^= 0xff;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ return (v0 ^ v1) ^ (v2 ^ v3);
+}
+EXPORT_SYMBOL(siphash);
+
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+/**
+ * siphash - compute 64-bit siphash PRF value, without alignment requirements
+ * @data: buffer to hash
+ * @size: size of @data
+ * @key: key buffer of size SIPHASH_KEY_LEN, must be aligned to SIPHASH_ALIGNMENT
+ */
+u64 siphash_unaligned(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN])
+{
+ u64 v0 = 0x736f6d6570736575ULL;
+ u64 v1 = 0x646f72616e646f6dULL;
+ u64 v2 = 0x6c7967656e657261ULL;
+ u64 v3 = 0x7465646279746573ULL;
+ u64 b = ((u64)len) << 56;
+ u64 k0 = le64_to_cpuvp(key);
+ u64 k1 = le64_to_cpuvp(key + sizeof(u64));
+ u64 m;
+ const u8 *end = data + len - (len % sizeof(u64));
+ const u8 left = len & (sizeof(u64) - 1);
+ v3 ^= k1;
+ v2 ^= k0;
+ v1 ^= k1;
+ v0 ^= k0;
+ for (; data != end; data += sizeof(u64)) {
+ m = get_unaligned_le64(data);
+ v3 ^= m;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= m;
+ }
+#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
+ if (left)
+ b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) & bytemask_from_count(left)));
+#else
+ switch (left) {
+ case 7: b |= ((u64)data[6]) << 48;
+ case 6: b |= ((u64)data[5]) << 40;
+ case 5: b |= ((u64)data[4]) << 32;
+ case 4: b |= get_unaligned_le32(data); break;
+ case 3: b |= ((u64)data[2]) << 16;
+ case 2: b |= get_unaligned_le16(data); break;
+ case 1: b |= data[0];
+ }
+#endif
+ v3 ^= b;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= b;
+ v2 ^= 0xff;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ SIPROUND;
+ return (v0 ^ v1) ^ (v2 ^ v3);
+}
+EXPORT_SYMBOL(siphash24_unaligned);
+#endif
diff --git a/lib/test_siphash.c b/lib/test_siphash.c
new file mode 100644
index 000000000000..444725c7834f
--- /dev/null
+++ b/lib/test_siphash.c
@@ -0,0 +1,84 @@
+/* Test cases for siphash.c
+ *
+ * Copyright (C) 2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.
+ *
+ * SipHash: a fast short-input PRF
+ * https://131002.net/siphash/
+ *
+ * This implementation is specifically for SipHash2-4.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/siphash.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+/* Test vectors taken from official reference source available at:
+ * https://131002.net/siphash/siphash24.c
+ */
+static const u64 test_vectors[64] = {
+ 0x726fdb47dd0e0e31ULL, 0x74f839c593dc67fdULL, 0x0d6c8009d9a94f5aULL,
+ 0x85676696d7fb7e2dULL, 0xcf2794e0277187b7ULL, 0x18765564cd99a68dULL,
+ 0xcbc9466e58fee3ceULL, 0xab0200f58b01d137ULL, 0x93f5f5799a932462ULL,
+ 0x9e0082df0ba9e4b0ULL, 0x7a5dbbc594ddb9f3ULL, 0xf4b32f46226bada7ULL,
+ 0x751e8fbc860ee5fbULL, 0x14ea5627c0843d90ULL, 0xf723ca908e7af2eeULL,
+ 0xa129ca6149be45e5ULL, 0x3f2acc7f57c29bdbULL, 0x699ae9f52cbe4794ULL,
+ 0x4bc1b3f0968dd39cULL, 0xbb6dc91da77961bdULL, 0xbed65cf21aa2ee98ULL,
+ 0xd0f2cbb02e3b67c7ULL, 0x93536795e3a33e88ULL, 0xa80c038ccd5ccec8ULL,
+ 0xb8ad50c6f649af94ULL, 0xbce192de8a85b8eaULL, 0x17d835b85bbb15f3ULL,
+ 0x2f2e6163076bcfadULL, 0xde4daaaca71dc9a5ULL, 0xa6a2506687956571ULL,
+ 0xad87a3535c49ef28ULL, 0x32d892fad841c342ULL, 0x7127512f72f27cceULL,
+ 0xa7f32346f95978e3ULL, 0x12e0b01abb051238ULL, 0x15e034d40fa197aeULL,
+ 0x314dffbe0815a3b4ULL, 0x027990f029623981ULL, 0xcadcd4e59ef40c4dULL,
+ 0x9abfd8766a33735cULL, 0x0e3ea96b5304a7d0ULL, 0xad0c42d6fc585992ULL,
+ 0x187306c89bc215a9ULL, 0xd4a60abcf3792b95ULL, 0xf935451de4f21df2ULL,
+ 0xa9538f0419755787ULL, 0xdb9acddff56ca510ULL, 0xd06c98cd5c0975ebULL,
+ 0xe612a3cb9ecba951ULL, 0xc766e62cfcadaf96ULL, 0xee64435a9752fe72ULL,
+ 0xa192d576b245165aULL, 0x0a8787bf8ecb74b2ULL, 0x81b3e73d20b49b6fULL,
+ 0x7fa8220ba3b2eceaULL, 0x245731c13ca42499ULL, 0xb78dbfaf3a8d83bdULL,
+ 0xea1ad565322a1a0bULL, 0x60e61c23a3795013ULL, 0x6606d7e446282b93ULL,
+ 0x6ca4ecb15c5f91e1ULL, 0x9f626da15c9625f3ULL, 0xe51b38608ef25f57ULL,
+ 0x958a324ceb064572ULL
+};
+
+static int __init siphash_test_init(void)
+{
+ u8 in[64] __aligned(SIPHASH_ALIGNMENT);
+ u8 k[16] __aligned(SIPHASH_ALIGNMENT);
+ u8 in_unaligned[65];
+ u8 i;
+ int ret = 0;
+
+ for (i = 0; i < 16; ++i)
+ k[i] = i;
+ for (i = 0; i < 64; ++i) {
+ in[i] = i;
+ in_unaligned[i + 1] = i;
+ if (siphash(in, i, k) != test_vectors[i]) {
+ pr_info("self-test aligned %u: FAIL\n", i + 1);
+ ret = -EINVAL;
+ }
+ if (siphash_unaligned(in_unaligned + 1, i, k) != test_vectors[i]) {
+ pr_info("self-test unaligned %u: FAIL\n", i + 1);
+ ret = -EINVAL;
+ }
+ }
+ if (!ret)
+ pr_info("self-tests: pass\n");
+ return ret;
+}
+
+static void __exit siphash_test_exit(void)
+{
+}
+
+module_init(siphash_test_init);
+module_exit(siphash_test_exit);
+
+MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>");
+MODULE_LICENSE("Dual BSD/GPL");
--
2.11.0
^ permalink raw reply related
* [PATCH v4 2/4] siphash: add N[qd]word helpers
From: Jason A. Donenfeld @ 2016-12-15 1:46 UTC (permalink / raw)
To: Netdev, kernel-hardening, LKML, linux-crypto
Cc: Jason A. Donenfeld, Tom Herbert
In-Reply-To: <20161215014649.20068-1-Jason@zx2c4.com>
These restore parity with the jhash interface by providing high
performance helpers for common input sizes.
Linus doesn't like the use of "qword" and "dword", but I haven't been
able to come up with another name for these that fits as well.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Tom Herbert <tom@herbertland.com>
---
Changes from v2->v4:
- Rather than just wrapping siphash(), we actually implement the
fully optimized and manually unrolled version, so that lengths
don't need to be checked and loops don't need to branch.
- We now provide both 32-bit and 64-bit versions, both of which
are quite useful for different circumstances.
include/linux/siphash.h | 31 ++++++++++
lib/siphash.c | 161 ++++++++++++++++++++++++++++++++++++------------
lib/test_siphash.c | 18 ++++++
3 files changed, 170 insertions(+), 40 deletions(-)
diff --git a/include/linux/siphash.h b/include/linux/siphash.h
index d0bcca7b992b..6e7c2a421bd9 100644
--- a/include/linux/siphash.h
+++ b/include/linux/siphash.h
@@ -27,4 +27,35 @@ static inline u64 siphash_unaligned(const u8 *data, size_t len, const u8 key[SIP
u64 siphash_unaligned(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN]);
#endif
+u64 siphash_1qword(const u64 a, const u8 key[SIPHASH_KEY_LEN]);
+u64 siphash_2qwords(const u64 a, const u64 b, const u8 key[SIPHASH_KEY_LEN]);
+u64 siphash_3qwords(const u64 a, const u64 b, const u64 c, const u8 key[SIPHASH_KEY_LEN]);
+u64 siphash_4qwords(const u64 a, const u64 b, const u64 c, const u64 d, const u8 key[SIPHASH_KEY_LEN]);
+
+static inline u64 siphash_2dwords(const u32 a, const u32 b, const u8 key[SIPHASH_KEY_LEN])
+{
+ return siphash_1qword((u64)b << 32 | a, key);
+}
+
+static inline u64 siphash_4dwords(const u32 a, const u32 b, const u32 c, const u32 d,
+ const u8 key[SIPHASH_KEY_LEN])
+{
+ return siphash_2qwords((u64)b << 32 | a, (u64)d << 32 | c, key);
+}
+
+static inline u64 siphash_6dwords(const u32 a, const u32 b, const u32 c, const u32 d,
+ const u32 e, const u32 f, const u8 key[SIPHASH_KEY_LEN])
+{
+ return siphash_3qwords((u64)b << 32 | a, (u64)d << 32 | c, (u64)f << 32 | e,
+ key);
+}
+
+static inline u64 siphash_8dwords(const u32 a, const u32 b, const u32 c, const u32 d,
+ const u32 e, const u32 f, const u32 g, const u32 h,
+ const u8 key[SIPHASH_KEY_LEN])
+{
+ return siphash_4qwords((u64)b << 32 | a, (u64)d << 32 | c, (u64)f << 32 | e,
+ (u64)h << 32 | g, key);
+}
+
#endif /* _LINUX_SIPHASH_H */
diff --git a/lib/siphash.c b/lib/siphash.c
index b500231f61cd..c13d2b2bb76e 100644
--- a/lib/siphash.c
+++ b/lib/siphash.c
@@ -38,6 +38,31 @@ static inline u64 le64_to_cpuvp(const void *p)
v2 += v1; v1 = rol64(v1, 17); v1 ^= v2; v2 = rol64(v2, 32); \
} while(0)
+#define PREAMBLE(len) \
+ u64 v0 = 0x736f6d6570736575ULL; \
+ u64 v1 = 0x646f72616e646f6dULL; \
+ u64 v2 = 0x6c7967656e657261ULL; \
+ u64 v3 = 0x7465646279746573ULL; \
+ u64 b = ((u64)len) << 56; \
+ u64 k0 = le64_to_cpuvp(key); \
+ u64 k1 = le64_to_cpuvp(key + sizeof(u64)); \
+ v3 ^= k1; \
+ v2 ^= k0; \
+ v1 ^= k1; \
+ v0 ^= k0;
+
+#define POSTAMBLE \
+ v3 ^= b; \
+ SIPROUND; \
+ SIPROUND; \
+ v0 ^= b; \
+ v2 ^= 0xff; \
+ SIPROUND; \
+ SIPROUND; \
+ SIPROUND; \
+ SIPROUND; \
+ return (v0 ^ v1) ^ (v2 ^ v3);
+
/**
* siphash - compute 64-bit siphash PRF value
* @data: buffer to hash, must be aligned to SIPHASH_ALIGNMENT
@@ -46,20 +71,10 @@ static inline u64 le64_to_cpuvp(const void *p)
*/
u64 siphash(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN])
{
- u64 v0 = 0x736f6d6570736575ULL;
- u64 v1 = 0x646f72616e646f6dULL;
- u64 v2 = 0x6c7967656e657261ULL;
- u64 v3 = 0x7465646279746573ULL;
- u64 b = ((u64)len) << 56;
- u64 k0 = le64_to_cpuvp(key);
- u64 k1 = le64_to_cpuvp(key + sizeof(u64));
- u64 m;
const u8 *end = data + len - (len % sizeof(u64));
const u8 left = len & (sizeof(u64) - 1);
- v3 ^= k1;
- v2 ^= k0;
- v1 ^= k1;
- v0 ^= k0;
+ u64 m;
+ PREAMBLE(len)
for (; data != end; data += sizeof(u64)) {
m = le64_to_cpuvp(data);
v3 ^= m;
@@ -81,16 +96,7 @@ u64 siphash(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN])
case 1: b |= data[0];
}
#endif
- v3 ^= b;
- SIPROUND;
- SIPROUND;
- v0 ^= b;
- v2 ^= 0xff;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- SIPROUND;
- return (v0 ^ v1) ^ (v2 ^ v3);
+ POSTAMBLE
}
EXPORT_SYMBOL(siphash);
@@ -103,20 +109,10 @@ EXPORT_SYMBOL(siphash);
*/
u64 siphash_unaligned(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN])
{
- u64 v0 = 0x736f6d6570736575ULL;
- u64 v1 = 0x646f72616e646f6dULL;
- u64 v2 = 0x6c7967656e657261ULL;
- u64 v3 = 0x7465646279746573ULL;
- u64 b = ((u64)len) << 56;
- u64 k0 = le64_to_cpuvp(key);
- u64 k1 = le64_to_cpuvp(key + sizeof(u64));
- u64 m;
const u8 *end = data + len - (len % sizeof(u64));
const u8 left = len & (sizeof(u64) - 1);
- v3 ^= k1;
- v2 ^= k0;
- v1 ^= k1;
- v0 ^= k0;
+ u64 m;
+ PREAMBLE(len)
for (; data != end; data += sizeof(u64)) {
m = get_unaligned_le64(data);
v3 ^= m;
@@ -138,16 +134,101 @@ u64 siphash_unaligned(const u8 *data, size_t len, const u8 key[SIPHASH_KEY_LEN])
case 1: b |= data[0];
}
#endif
- v3 ^= b;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_unaligned);
+#endif
+
+/**
+ * siphash_1qword - compute 64-bit siphash PRF value of 1 quad-word
+ * @first: first quadword
+ * @key: key buffer of size SIPHASH_KEY_LEN, must be aligned to SIPHASH_ALIGNMENT
+ */
+u64 siphash_1qword(const u64 first, const u8 key[SIPHASH_KEY_LEN])
+{
+ PREAMBLE(8)
+ v3 ^= first;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= first;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_1qword);
+
+/**
+ * siphash_2qwords - compute 64-bit siphash PRF value of 2 quad-words
+ * @first: first quadword
+ * @second: second quadword
+ * @key: key buffer of size SIPHASH_KEY_LEN, must be aligned to SIPHASH_ALIGNMENT
+ */
+u64 siphash_2qwords(const u64 first, const u64 second, const u8 key[SIPHASH_KEY_LEN])
+{
+ PREAMBLE(16)
+ v3 ^= first;
SIPROUND;
SIPROUND;
- v0 ^= b;
- v2 ^= 0xff;
+ v0 ^= first;
+ v3 ^= second;
SIPROUND;
SIPROUND;
+ v0 ^= second;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_2qwords);
+
+/**
+ * siphash_3qwords - compute 64-bit siphash PRF value of 3 quad-words
+ * @first: first quadword
+ * @second: second quadword
+ * @third: third quadword
+ * @key: key buffer of size SIPHASH_KEY_LEN, must be aligned to SIPHASH_ALIGNMENT
+ */
+u64 siphash_3qwords(const u64 first, const u64 second, const u64 third, const u8 key[SIPHASH_KEY_LEN])
+{
+ PREAMBLE(24)
+ v3 ^= first;
SIPROUND;
SIPROUND;
- return (v0 ^ v1) ^ (v2 ^ v3);
+ v0 ^= first;
+ v3 ^= second;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= second;
+ v3 ^= third;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= third;
+ POSTAMBLE
}
-EXPORT_SYMBOL(siphash24_unaligned);
-#endif
+EXPORT_SYMBOL(siphash_3qwords);
+
+/**
+ * siphash_4qwords - compute 64-bit siphash PRF value of 4 quad-words
+ * @first: first quadword
+ * @second: second quadword
+ * @third: third quadword
+ * @forth: forth quadword
+ * @key: key buffer of size SIPHASH_KEY_LEN, must be aligned to SIPHASH_ALIGNMENT
+ */
+u64 siphash_4qwords(const u64 first, const u64 second, const u64 third, const u64 forth, const u8 key[SIPHASH_KEY_LEN])
+{
+ PREAMBLE(32)
+ v3 ^= first;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= first;
+ v3 ^= second;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= second;
+ v3 ^= third;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= third;
+ v3 ^= forth;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= forth;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_4qwords);
diff --git a/lib/test_siphash.c b/lib/test_siphash.c
index 444725c7834f..9925a325af35 100644
--- a/lib/test_siphash.c
+++ b/lib/test_siphash.c
@@ -68,6 +68,24 @@ static int __init siphash_test_init(void)
ret = -EINVAL;
}
}
+ if (siphash_1qword(0x0706050403020100ULL, k) != test_vectors[8]) {
+ pr_info("self-test 1qword: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_2qwords(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL, k) != test_vectors[16]) {
+ pr_info("self-test 2qwords: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_3qwords(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL,
+ 0x1716151413121110ULL, k) != test_vectors[24]) {
+ pr_info("self-test 3qwords: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_4qwords(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL,
+ 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL, k) != test_vectors[32]) {
+ pr_info("self-test 4qwords: FAIL\n");
+ ret = -EINVAL;
+ }
if (!ret)
pr_info("self-tests: pass\n");
return ret;
--
2.11.0
^ permalink raw reply related
* [PATCH v4 3/4] secure_seq: use siphash instead of md5_transform
From: Jason A. Donenfeld @ 2016-12-15 1:46 UTC (permalink / raw)
To: Netdev, kernel-hardening, LKML, linux-crypto
Cc: Jason A. Donenfeld, Andi Kleen, David Miller, David Laight,
Tom Herbert, Hannes Frederic Sowa
In-Reply-To: <20161215014649.20068-1-Jason@zx2c4.com>
This gives a clear speed and security improvement. Siphash is both
faster and is more solid crypto than the aging MD5.
Rather than manually filling MD5 buffers, for IPv6, we simply create
a layout by a simple anonymous struct, for which gcc generates
rather efficient code. For IPv4, we pass the values directly to the
short input convenience functions.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Miller <davem@davemloft.net>
Cc: David Laight <David.Laight@aculab.com>
Cc: Tom Herbert <tom@herbertland.com>
Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
Changes from v3->v4:
- For the IPv4 cases, we can now use the Ndwords helper functions,
which make the calculation simpler and faster.
- For the IPv6 cases, which still use the struct, we no longer pack
the struct and instead simply pad until the nearest 64-bit size, so
that it also avoids the slow branch for left-overs in siphash().
net/core/secure_seq.c | 133 ++++++++++++++++++++------------------------------
1 file changed, 52 insertions(+), 81 deletions(-)
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index 88a8e429fc3e..8fed79932ec4 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -1,3 +1,5 @@
+/* Copyright (C) 2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/cryptohash.h>
@@ -8,14 +10,14 @@
#include <linux/ktime.h>
#include <linux/string.h>
#include <linux/net.h>
-
+#include <linux/siphash.h>
#include <net/secure_seq.h>
#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
+#include <linux/in6.h>
#include <net/tcp.h>
-#define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
-static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
+static u8 net_secret[SIPHASH_KEY_LEN] __aligned(SIPHASH_ALIGNMENT);
static __always_inline void net_secret_init(void)
{
@@ -44,44 +46,42 @@ static u32 seq_scale(u32 seq)
u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
__be16 sport, __be16 dport, u32 *tsoff)
{
- u32 secret[MD5_MESSAGE_BYTES / 4];
- u32 hash[MD5_DIGEST_WORDS];
- u32 i;
-
+ const struct {
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+ __be16 sport;
+ __be16 dport;
+ u32 padding;
+ } __aligned(SIPHASH_ALIGNMENT) combined = {
+ .saddr = *(struct in6_addr *)saddr,
+ .daddr = *(struct in6_addr *)daddr,
+ .sport = sport,
+ .dport = dport
+ };
+ u64 hash;
net_secret_init();
- memcpy(hash, saddr, 16);
- for (i = 0; i < 4; i++)
- secret[i] = net_secret[i] + (__force u32)daddr[i];
- secret[4] = net_secret[4] +
- (((__force u16)sport << 16) + (__force u16)dport);
- for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
- secret[i] = net_secret[i];
-
- md5_transform(hash, secret);
-
- *tsoff = sysctl_tcp_timestamps == 1 ? hash[1] : 0;
- return seq_scale(hash[0]);
+ hash = siphash((const u8 *)&combined, sizeof(combined), net_secret);
+ *tsoff = sysctl_tcp_timestamps == 1 ? (hash >> 32) : 0;
+ return seq_scale(hash);
}
EXPORT_SYMBOL(secure_tcpv6_sequence_number);
u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
__be16 dport)
{
- u32 secret[MD5_MESSAGE_BYTES / 4];
- u32 hash[MD5_DIGEST_WORDS];
- u32 i;
-
+ const struct {
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+ __be16 dport;
+ u16 padding1;
+ u32 padding2;
+ } __aligned(SIPHASH_ALIGNMENT) combined = {
+ .saddr = *(struct in6_addr *)saddr,
+ .daddr = *(struct in6_addr *)daddr,
+ .dport = dport
+ };
net_secret_init();
- memcpy(hash, saddr, 16);
- for (i = 0; i < 4; i++)
- secret[i] = net_secret[i] + (__force u32) daddr[i];
- secret[4] = net_secret[4] + (__force u32)dport;
- for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
- secret[i] = net_secret[i];
-
- md5_transform(hash, secret);
-
- return hash[0];
+ return siphash((const u8 *)&combined, sizeof(combined), net_secret);
}
EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
#endif
@@ -91,33 +91,17 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
__be16 sport, __be16 dport, u32 *tsoff)
{
- u32 hash[MD5_DIGEST_WORDS];
-
+ u64 hash;
net_secret_init();
- hash[0] = (__force u32)saddr;
- hash[1] = (__force u32)daddr;
- hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
- hash[3] = net_secret[15];
-
- md5_transform(hash, net_secret);
-
- *tsoff = sysctl_tcp_timestamps == 1 ? hash[1] : 0;
- return seq_scale(hash[0]);
+ hash = siphash_4dwords(saddr, daddr, sport, dport, net_secret);
+ *tsoff = sysctl_tcp_timestamps == 1 ? (hash >> 32) : 0;
+ return seq_scale(hash);
}
u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
{
- u32 hash[MD5_DIGEST_WORDS];
-
net_secret_init();
- hash[0] = (__force u32)saddr;
- hash[1] = (__force u32)daddr;
- hash[2] = (__force u32)dport ^ net_secret[14];
- hash[3] = net_secret[15];
-
- md5_transform(hash, net_secret);
-
- return hash[0];
+ return siphash_4dwords(saddr, daddr, dport, 0, net_secret);
}
EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
#endif
@@ -126,21 +110,11 @@ EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
__be16 sport, __be16 dport)
{
- u32 hash[MD5_DIGEST_WORDS];
u64 seq;
-
net_secret_init();
- hash[0] = (__force u32)saddr;
- hash[1] = (__force u32)daddr;
- hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
- hash[3] = net_secret[15];
-
- md5_transform(hash, net_secret);
-
- seq = hash[0] | (((u64)hash[1]) << 32);
+ seq = siphash_4dwords(saddr, daddr, sport, dport, net_secret);
seq += ktime_get_real_ns();
seq &= (1ull << 48) - 1;
-
return seq;
}
EXPORT_SYMBOL(secure_dccp_sequence_number);
@@ -149,26 +123,23 @@ EXPORT_SYMBOL(secure_dccp_sequence_number);
u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
__be16 sport, __be16 dport)
{
- u32 secret[MD5_MESSAGE_BYTES / 4];
- u32 hash[MD5_DIGEST_WORDS];
+ const struct {
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+ __be16 sport;
+ __be16 dport;
+ u32 padding;
+ } __aligned(SIPHASH_ALIGNMENT) combined = {
+ .saddr = *(struct in6_addr *)saddr,
+ .daddr = *(struct in6_addr *)daddr,
+ .sport = sport,
+ .dport = dport
+ };
u64 seq;
- u32 i;
-
net_secret_init();
- memcpy(hash, saddr, 16);
- for (i = 0; i < 4; i++)
- secret[i] = net_secret[i] + (__force u32)daddr[i];
- secret[4] = net_secret[4] +
- (((__force u16)sport << 16) + (__force u16)dport);
- for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
- secret[i] = net_secret[i];
-
- md5_transform(hash, secret);
-
- seq = hash[0] | (((u64)hash[1]) << 32);
+ seq = siphash((const u8 *)&combined, sizeof(combined), net_secret);
seq += ktime_get_real_ns();
seq &= (1ull << 48) - 1;
-
return seq;
}
EXPORT_SYMBOL(secure_dccpv6_sequence_number);
--
2.11.0
^ permalink raw reply related
* [PATCH v4 4/4] random: use siphash instead of MD5 for get_random_int/long
From: Jason A. Donenfeld @ 2016-12-15 1:46 UTC (permalink / raw)
To: Netdev, kernel-hardening, LKML, linux-crypto
Cc: Jason A. Donenfeld, Jean-Philippe Aumasson, Ted Tso
In-Reply-To: <20161215014649.20068-1-Jason@zx2c4.com>
This duplicates the current algorithm for get_random_int/long, but uses
siphash instead. This comes with several benefits. It's certainly
faster and more cryptographically secure than MD5. This patch also
separates hashed fields into three values instead of one, in order to
increase diffusion.
The previous MD5 algorithm used a per-cpu MD5 state, which caused
successive calls to the function to chain upon each other. While it's
not entirely clear that this kind of chaining is absolutely necessary
when using a secure PRF like siphash, it can't hurt, and the timing of
the call chain does add a degree of natural entropy. So, in keeping with
this design, instead of the massive per-cpu 64-byte MD5 state, there is
instead a per-cpu previously returned value for chaining.
The speed benefits are substantial:
| siphash | md5 | speedup |
------------------------------
get_random_long | 137130 | 415983 | 3.03x |
get_random_int | 86384 | 343323 | 3.97x |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
Cc: Ted Tso <tytso@mit.edu>
---
Changes from v3->v4:
- Speedups by using the 3qwords function.
drivers/char/random.c | 30 +++++++++++-------------------
1 file changed, 11 insertions(+), 19 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index d6876d506220..8e1d1cfface6 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -262,6 +262,7 @@
#include <linux/syscalls.h>
#include <linux/completion.h>
#include <linux/uuid.h>
+#include <linux/siphash.h>
#include <crypto/chacha20.h>
#include <asm/processor.h>
@@ -2042,7 +2043,7 @@ struct ctl_table random_table[] = {
};
#endif /* CONFIG_SYSCTL */
-static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
+static u8 random_int_secret[SIPHASH_KEY_LEN] __aligned(SIPHASH_ALIGNMENT);
int random_int_secret_init(void)
{
@@ -2050,8 +2051,7 @@ int random_int_secret_init(void)
return 0;
}
-static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash)
- __aligned(sizeof(unsigned long));
+static DEFINE_PER_CPU(u64, get_random_int_chaining);
/*
* Get a random word for internal kernel use only. Similar to urandom but
@@ -2061,19 +2061,15 @@ static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash)
*/
unsigned int get_random_int(void)
{
- __u32 *hash;
unsigned int ret;
+ u64 *chaining;
if (arch_get_random_int(&ret))
return ret;
- hash = get_cpu_var(get_random_int_hash);
-
- hash[0] += current->pid + jiffies + random_get_entropy();
- md5_transform(hash, random_int_secret);
- ret = hash[0];
- put_cpu_var(get_random_int_hash);
-
+ chaining = &get_cpu_var(get_random_int_chaining);
+ ret = *chaining = siphash_3qwords(*chaining, jiffies, random_get_entropy() + current->pid, random_int_secret);
+ put_cpu_var(get_random_int_chaining);
return ret;
}
EXPORT_SYMBOL(get_random_int);
@@ -2083,19 +2079,15 @@ EXPORT_SYMBOL(get_random_int);
*/
unsigned long get_random_long(void)
{
- __u32 *hash;
unsigned long ret;
+ u64 *chaining;
if (arch_get_random_long(&ret))
return ret;
- hash = get_cpu_var(get_random_int_hash);
-
- hash[0] += current->pid + jiffies + random_get_entropy();
- md5_transform(hash, random_int_secret);
- ret = *(unsigned long *)hash;
- put_cpu_var(get_random_int_hash);
-
+ chaining = &get_cpu_var(get_random_int_chaining);
+ ret = *chaining = siphash_3qwords(*chaining, jiffies, random_get_entropy() + current->pid, random_int_secret);
+ put_cpu_var(get_random_int_chaining);
return ret;
}
EXPORT_SYMBOL(get_random_long);
--
2.11.0
^ permalink raw reply related
* Your response Is highly appreciated!
From: Mr. Saeed Bin Salem @ 2016-12-15 1:52 UTC (permalink / raw)
I am Mr. Saeed Bin Salem from the National Commercial Bank Libya. I have a secured business proposition for you.
^ permalink raw reply
* Re: net/arp: ARP cache aging failed.
From: YueHaibing @ 2016-12-15 2:58 UTC (permalink / raw)
To: Julian Anastasov
Cc: Hannes Frederic Sowa, Eric Dumazet, David S. Miller, netdev
In-Reply-To: <alpine.LFD.2.11.1612142151340.1681@ja.home.ssi.bg>
On 2016/12/15 4:15, Julian Anastasov wrote:
>
> Hello,
>
> On Wed, 14 Dec 2016, YueHaibing wrote:
>
>> On 2016/11/26 4:40, Julian Anastasov wrote:
>>>
>>> So, the idea is to move TCP and other similar
>>> users to the new dst_confirm_sk() method. If other
>>> dst_confirm() users are left, they should be checked
>>> if dsts with rt_gateway = 0 can be wrongly used.
>>
>> Sorry for so late.
>
> In fact, I'm late too because I almost finished
> my changes, the only remaining part is the cxgb files...
>
>> Based on your ideas, I make a patch and test it for a while.
>
> The problem is that it is valid only for TCP.
> Also, this flag should be reset sometimes, eg. when sk dst
> changes...
>
>> It works for me.
>>
>> @@ -847,7 +847,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
>> return err;
>>
>> do_confirm:
>> - dst_confirm(&rt->dst);
>> + dst_confirm_sk(sk);
>
> MSG_CONFIRM from sendmsg needs special treatment. The
> problem is that UDP sending does not lock the socket, so I also
> added a skb flag to handle this situation in ip*_append_data.
> We do not want threaded application firing at different
> destinations to confirm the wrong neighbour. MSG_PROBE is
> another issue, the XFRM dst chaining, etc...
>
> I hope, I'll be ready this weekend with few patches
> that change all dst_confirm users... There I'll explain
> everything in detail.
>
> Regards
>
> --
> Julian Anastasov <ja@ssi.bg>
>
> .
>
Great, I'll be glad to do a testing.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox