[PATCH] ipv6: Fix idev->addr_list corruption

2017-04-10 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

addrconf_ifdown() removes elements from the idev->addr_list without
holding the idev->lock.

If this happens while the loop in __ipv6_dev_get_saddr() is handling the
same element, that function ends up in an infinite loop:

  NMI watchdog: BUG: soft lockup - CPU#1 stuck for 23s! [test:1719]
  Call Trace:
   ipv6_get_saddr_eval+0x13c/0x3a0
   __ipv6_dev_get_saddr+0xe4/0x1f0
   ipv6_dev_get_saddr+0x1b4/0x204
   ip6_dst_lookup_tail+0xcc/0x27c
   ip6_dst_lookup_flow+0x38/0x80
   udpv6_sendmsg+0x708/0xba8
   sock_sendmsg+0x18/0x30
   SyS_sendto+0xb8/0xf8
   syscall_common+0x34/0x58

Fixes: 6a923934c33 (Revert "ipv6: Revert optional address flusing on ifdown.")
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 net/ipv6/addrconf.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3631725..80ce478 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3626,14 +3626,19 @@ static int addrconf_ifdown(struct net_device *dev, int 
how)
INIT_LIST_HEAD(_list);
list_for_each_entry_safe(ifa, tmp, >addr_list, if_list) {
struct rt6_info *rt = NULL;
+   bool keep;
 
addrconf_del_dad_work(ifa);
 
+   keep = keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
+   !addr_is_local(>addr);
+   if (!keep)
+   list_move(>if_list, _list);
+
write_unlock_bh(>lock);
spin_lock_bh(>lock);
 
-   if (keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
-   !addr_is_local(>addr)) {
+   if (keep) {
/* set state to skip the notifier below */
state = INET6_IFADDR_STATE_DEAD;
ifa->state = 0;
@@ -3645,8 +3650,6 @@ static int addrconf_ifdown(struct net_device *dev, int 
how)
} else {
state = ifa->state;
ifa->state = INET6_IFADDR_STATE_DEAD;
-
-   list_move(>if_list, _list);
}
 
spin_unlock_bh(>lock);
-- 
2.7.0



Re: Synopsys Ethernet QoS Driver

2016-11-19 Thread Rabin Vincent
On Fri, Nov 18, 2016 at 02:20:27PM +, Joao Pinto wrote:
> For now we are interesting in improving the synopsys QoS driver under
> /nect/ethernet/synopsys. For now the driver structure consists of a single 
> file
> called dwc_eth_qos.c, containing synopsys ethernet qos common ops and platform
> related stuff.
> 
> Our strategy would be:
> 
> a) Implement a platform glue driver (dwc_eth_qos_pltfm.c)
> b) Implement a pci glue driver (dwc_eth_qos_pci.c)
> c) Implement a "core driver" (dwc_eth_qos.c) that would only have Ethernet QoS
> related stuff to be reused by the platform / pci drivers
> d) Add a set of features to the "core driver" that we have available 
> internally

Note that there are actually two drivers in mainline for this hardware:

 drivers/net/ethernet/synopsis/
 drivers/net/ethernet/stmicro/stmmac/

(See http://lists.openwall.net/netdev/2016/02/29/127)

The former only supports 4.x of the hardware.

The later supports 4.x and 3.x and already has a platform glue driver
with support for several platforms, a PCI glue driver, and a core driver
with several features not present in the former (for example: TX/RX
interrupt coalescing, EEE, PTP).

Have you evaluated both drivers?  Why have you decided to work on the
former rather than the latter?


[PATCHv3] phy: fix crash in fixed_phy_add()

2016-05-18 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

Since e7f4dc3536a ("mdio: Move allocation of interrupts into core"),
platforms which call fixed_phy_add() before fixed_mdio_bus_init() is
called (for example, because the platform code and the fixed_phy driver
use the same initcall level) crash in fixed_phy_add() since the
->mii_bus is not allocated.

Also since e7f4dc3536a, these interrupts are initalized to polling by
default.  The few (old) platforms which directly use fixed_phy_add()
from their platform code all pass PHY_POLL for the irq argument, so we
can keep these platforms not crashing by simply not attempting to set
the irq if PHY_POLL is passed.

Also, even if problems have not been reported on more modern platforms
which used fixed_phy_register() from drivers' probe functions, we return
-EPROBE_DEFER if the MDIO bus is not yet registered so that the probe is
retried later.

Fixes: e7f4dc3536a400 ("mdio: Move allocation of interrupts into core")
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
v3: One more suggestion from Andrew: check mii bus state

 drivers/net/phy/fixed_phy.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index fc07a88..e7dcda6 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -255,7 +255,8 @@ int fixed_phy_add(unsigned int irq, int phy_addr,
 
memset(fp->regs, 0xFF,  sizeof(fp->regs[0]) * MII_REGS_NUM);
 
-   fmb->mii_bus->irq[phy_addr] = irq;
+   if (irq != PHY_POLL)
+   fmb->mii_bus->irq[phy_addr] = irq;
 
fp->addr = phy_addr;
fp->status = *status;
@@ -314,6 +315,9 @@ struct phy_device *fixed_phy_register(unsigned int irq,
int phy_addr;
int ret;
 
+   if (!fmb->mii_bus || fmb->mii_bus->state != MDIOBUS_REGISTERED)
+   return ERR_PTR(-EPROBE_DEFER);
+
/* Get the next available PHY address, up to PHY_MAX_ADDR */
spin_lock(_fixed_addr_lock);
if (phy_fixed_addr == PHY_MAX_ADDR) {
-- 
2.1.4



[PATCHv2] phy: fix crash in fixed_phy_add()

2016-05-17 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

Since e7f4dc3536a ("mdio: Move allocation of interrupts into core"),
platforms which call fixed_phy_add() before fixed_mdio_bus_init() is
called (for example, because the platform code and the fixed_phy driver
use the same initcall level) crash in fixed_phy_add() since the
->mii_bus is not allocated.

Also since e7f4dc3536a, these interrupts are initalized to polling by
default.  The few (old) platforms which directly use fixed_phy_add()
from their platform code all pass PHY_POLL for the irq argument, so we
can keep these platforms not crashing by simply not attempting to set
the irq if PHY_POLL is passed.

Also, even if problems have not been reported on more modern platforms
which used fixed_phy_register() from drivers' probe functions, we return
-EPROBE_DEFER if the MDIO bus is not yet registered so that the probe is
retried later.

Fixes: e7f4dc3536a400 ("mdio: Move allocation of interrupts into core")
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
v2: rewrite according to Andrew's suggestions

 drivers/net/phy/fixed_phy.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index fc07a88..d9dc1f5 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -255,7 +255,8 @@ int fixed_phy_add(unsigned int irq, int phy_addr,
 
memset(fp->regs, 0xFF,  sizeof(fp->regs[0]) * MII_REGS_NUM);
 
-   fmb->mii_bus->irq[phy_addr] = irq;
+   if (irq != PHY_POLL)
+   fmb->mii_bus->irq[phy_addr] = irq;
 
fp->addr = phy_addr;
fp->status = *status;
@@ -314,6 +315,9 @@ struct phy_device *fixed_phy_register(unsigned int irq,
int phy_addr;
int ret;
 
+   if (!fmb->mii_bus)
+   return ERR_PTR(-EPROBE_DEFER);
+
/* Get the next available PHY address, up to PHY_MAX_ADDR */
spin_lock(_fixed_addr_lock);
if (phy_fixed_addr == PHY_MAX_ADDR) {
-- 
2.1.4



Re: [PATCH] phy: remove irq param to fix crash in fixed_phy_add()

2016-05-16 Thread Rabin Vincent
On Mon, May 16, 2016 at 02:29:03PM +0200, Andrew Lunn wrote:
> What i think is better is to make fixed_phy_add() return -EPROBE_DEFER
> if it is called before fixed_mdio_bus_init().

I don't see how this will work for platforms such as ar7 and bcm47xx
which call fixed_phy_add() from platform code.  There is no probe to
retry there so while the EPROBE_DEFER will certainly fix the crash it
will also leave the platforms without a phy.


[PATCH] phy: remove irq param to fix crash in fixed_phy_add()

2016-05-16 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

Since e7f4dc3536a ("mdio: Move allocation of interrupts into core"),
platforms which call fixed_phy_add() before fixed_mdio_bus_init() is
called (for example, because the platform code and the fixed_phy driver
use the same initcall level) crash in fixed_phy_add() since the
->mii_bus is not allocated.

Also since e7f4dc3536a, these interrupts are initalized to polling by
default.  All callers of both fixed_phy_register() and fixed_phy_add()
pass PHY_POLL for the irq argument, so we can fix these crashes by
simply removing the irq parameter, since the default is correct for all
users.

Fixes: e7f4dc3536a400 ("mdio: Move allocation of interrupts into core")
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 arch/m68k/coldfire/m5272.c   |  2 +-
 arch/mips/ar7/platform.c |  5 ++---
 arch/mips/bcm47xx/setup.c|  2 +-
 drivers/net/ethernet/broadcom/bgmac.c|  2 +-
 drivers/net/ethernet/broadcom/genet/bcmmii.c |  2 +-
 drivers/net/phy/fixed_phy.c  | 10 +++---
 drivers/of/of_mdio.c |  6 +++---
 include/linux/phy_fixed.h| 16 ++--
 8 files changed, 18 insertions(+), 27 deletions(-)

diff --git a/arch/m68k/coldfire/m5272.c b/arch/m68k/coldfire/m5272.c
index c525e4c..217e2e0 100644
--- a/arch/m68k/coldfire/m5272.c
+++ b/arch/m68k/coldfire/m5272.c
@@ -126,7 +126,7 @@ static struct fixed_phy_status nettel_fixed_phy_status 
__initdata = {
 static int __init init_BSP(void)
 {
m5272_uarts_init();
-   fixed_phy_add(PHY_POLL, 0, _fixed_phy_status, -1);
+   fixed_phy_add(0, _fixed_phy_status, -1);
return 0;
 }
 
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 58fca9a..0a024b0 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -678,8 +678,7 @@ static int __init ar7_register_devices(void)
}
 
if (ar7_has_high_cpmac()) {
-   res = fixed_phy_add(PHY_POLL, cpmac_high.id,
-   _phy_status, -1);
+   res = fixed_phy_add(cpmac_high.id, _phy_status, -1);
if (!res) {
cpmac_get_mac(1, cpmac_high_data.dev_addr);
 
@@ -692,7 +691,7 @@ static int __init ar7_register_devices(void)
} else
cpmac_low_data.phy_mask = 0x;
 
-   res = fixed_phy_add(PHY_POLL, cpmac_low.id, _phy_status, -1);
+   res = fixed_phy_add(cpmac_low.id, _phy_status, -1);
if (!res) {
cpmac_get_mac(0, cpmac_low_data.dev_addr);
res = platform_device_register(_low);
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index c807e32..ca3fbd1 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -243,7 +243,7 @@ static int __init bcm47xx_register_bus_complete(void)
bcm47xx_leds_register();
bcm47xx_workarounds();
 
-   fixed_phy_add(PHY_POLL, 0, _fixed_phy_status, -1);
+   fixed_phy_add(0, _fixed_phy_status, -1);
return 0;
 }
 device_initcall(bcm47xx_register_bus_complete);
diff --git a/drivers/net/ethernet/broadcom/bgmac.c 
b/drivers/net/ethernet/broadcom/bgmac.c
index 38db2e4..0c8f467 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1460,7 +1460,7 @@ static int bgmac_fixed_phy_register(struct bgmac *bgmac)
struct phy_device *phy_dev;
int err;
 
-   phy_dev = fixed_phy_register(PHY_POLL, _status, -1, NULL);
+   phy_dev = fixed_phy_register(_status, -1, NULL);
if (!phy_dev || IS_ERR(phy_dev)) {
bgmac_err(bgmac, "Failed to register fixed PHY device\n");
return -ENODEV;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c 
b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index 457c3bc..f181fd1 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -595,7 +595,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
.asym_pause = 0,
};
 
-   phydev = fixed_phy_register(PHY_POLL, _status, -1, NULL);
+   phydev = fixed_phy_register(_status, -1, NULL);
if (!phydev || IS_ERR(phydev)) {
dev_err(kdev, "failed to register fixed PHY device\n");
return -ENODEV;
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index fc07a88..295e6bd 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -241,8 +241,7 @@ int fixed_phy_update_state(struct phy_device *phydev,
 }
 EXPORT_SYMBOL(fixed_phy_update_state);
 
-int fixed_phy_add(unsigned int irq, int phy_addr,
- struct fixed_phy_status *status,
+int fixed_phy_add(int phy_addr, struct fixed_phy_status *status,
  int

[PATCH] dwc_eth_qos: Reset hardware before PHY start

2016-02-02 Thread Rabin Vincent
From: Rabin Vincent <rab...@axis.com>

The hardware reset is currently done after phy_start() is called,
leading to a race where we can lose the link status if the phy state
machine calls dwceqos_adjust_link() before we reset the MAC registers.

Acked-by: Lars Persson <lar...@axis.com>
Signed-off-by: Rabin Vincent <rab...@axis.com>
---
 drivers/net/ethernet/synopsys/dwc_eth_qos.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c 
b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
index 70814b7..fc8bbff 100644
--- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c
+++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c
@@ -1880,9 +1880,9 @@ static int dwceqos_open(struct net_device *ndev)
}
netdev_reset_queue(ndev);
 
+   dwceqos_init_hw(lp);
napi_enable(>napi);
phy_start(lp->phy_dev);
-   dwceqos_init_hw(lp);
 
netif_start_queue(ndev);
tasklet_enable(>tx_bdreclaim_tasklet);
-- 
2.7.0



Re: [PATCH] arm64: net: bpf: don't BUG() on large shifts

2016-01-06 Thread Rabin Vincent
On Tue, Jan 05, 2016 at 09:55:58AM -0800, Alexei Starovoitov wrote:
> this one is better to be addressed in verifier instead of eBPF JITs.
> Please reject it in check_alu_op() instead.

AFAICS the eBPF verifier is not called on the eBPF filters generated by
the BPF->eBPF conversion in net/core/filter.c, so performing this check
only in check_alu_op() will be insufficient.  So I think we'd need to
add this check to bpf_check_classic() too.  Or am I missing something?
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] net: filter: make JITs zero A for SKF_AD_ALU_XOR_X

2016-01-05 Thread Rabin Vincent
The SKF_AD_ALU_XOR_X ancillary is not like the other ancillary data
instructions since it XORs A with X while all the others replace A with
some loaded value.  All the BPF JITs fail to clear A if this is used as
the first instruction in a filter.  This was found using american fuzzy
lop.

Add a helper to determine if A needs to be cleared given the first
instruction in a filter, and use this in the JITs.  Except for ARM, the
rest have only been compile-tested.

Fixes: 3480593131e0 ("net: filter: get rid of BPF_S_* enum")
Signed-off-by: Rabin Vincent <ra...@rab.in>
---
 arch/arm/net/bpf_jit_32.c   | 16 +---
 arch/mips/net/bpf_jit.c | 16 +---
 arch/powerpc/net/bpf_jit_comp.c | 13 ++---
 arch/sparc/net/bpf_jit_comp.c   | 17 ++---
 include/linux/filter.h  | 19 +++
 5 files changed, 25 insertions(+), 56 deletions(-)

diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 591f9db3bf40..e153eb065fe4 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -187,19 +187,6 @@ static inline int mem_words_used(struct jit_ctx *ctx)
return fls(ctx->seen & SEEN_MEM);
 }
 
-static inline bool is_load_to_a(u16 inst)
-{
-   switch (inst) {
-   case BPF_LD | BPF_W | BPF_LEN:
-   case BPF_LD | BPF_W | BPF_ABS:
-   case BPF_LD | BPF_H | BPF_ABS:
-   case BPF_LD | BPF_B | BPF_ABS:
-   return true;
-   default:
-   return false;
-   }
-}
-
 static void jit_fill_hole(void *area, unsigned int size)
 {
u32 *ptr;
@@ -211,7 +198,6 @@ static void jit_fill_hole(void *area, unsigned int size)
 static void build_prologue(struct jit_ctx *ctx)
 {
u16 reg_set = saved_regs(ctx);
-   u16 first_inst = ctx->skf->insns[0].code;
u16 off;
 
 #ifdef CONFIG_FRAME_POINTER
@@ -241,7 +227,7 @@ static void build_prologue(struct jit_ctx *ctx)
emit(ARM_MOV_I(r_X, 0), ctx);
 
/* do not leak kernel data to userspace */
-   if ((first_inst != (BPF_RET | BPF_K)) && !(is_load_to_a(first_inst)))
+   if (bpf_needs_clear_a(>skf->insns[0]))
emit(ARM_MOV_I(r_A, 0), ctx);
 
/* stack space for the BPF_MEM words */
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 77cb27309db2..1a8c96035716 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -521,19 +521,6 @@ static inline u16 align_sp(unsigned int num)
return num;
 }
 
-static bool is_load_to_a(u16 inst)
-{
-   switch (inst) {
-   case BPF_LD | BPF_W | BPF_LEN:
-   case BPF_LD | BPF_W | BPF_ABS:
-   case BPF_LD | BPF_H | BPF_ABS:
-   case BPF_LD | BPF_B | BPF_ABS:
-   return true;
-   default:
-   return false;
-   }
-}
-
 static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset)
 {
int i = 0, real_off = 0;
@@ -614,7 +601,6 @@ static unsigned int get_stack_depth(struct jit_ctx *ctx)
 
 static void build_prologue(struct jit_ctx *ctx)
 {
-   u16 first_inst = ctx->skf->insns[0].code;
int sp_off;
 
/* Calculate the total offset for the stack pointer */
@@ -641,7 +627,7 @@ static void build_prologue(struct jit_ctx *ctx)
emit_jit_reg_move(r_X, r_zero, ctx);
 
/* Do not leak kernel data to userspace */
-   if ((first_inst != (BPF_RET | BPF_K)) && !(is_load_to_a(first_inst)))
+   if (bpf_needs_clear_a(>skf->insns[0]))
emit_jit_reg_move(r_A, r_zero, ctx);
 }
 
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 04782164ee67..2d66a8446198 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -78,18 +78,9 @@ static void bpf_jit_build_prologue(struct bpf_prog *fp, u32 
*image,
PPC_LI(r_X, 0);
}
 
-   switch (filter[0].code) {
-   case BPF_RET | BPF_K:
-   case BPF_LD | BPF_W | BPF_LEN:
-   case BPF_LD | BPF_W | BPF_ABS:
-   case BPF_LD | BPF_H | BPF_ABS:
-   case BPF_LD | BPF_B | BPF_ABS:
-   /* first instruction sets A register (or is RET 'constant') */
-   break;
-   default:
-   /* make sure we dont leak kernel information to user */
+   /* make sure we dont leak kernel information to user */
+   if (bpf_needs_clear_a([0]))
PPC_LI(r_A, 0);
-   }
 }
 
 static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 22564f5f2364..3e6e05a7c4c2 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -420,22 +420,9 @@ void bpf_jit_compile(struct bpf_prog *fp)
}
emit_reg_move(O7, r_saved_O7);
 
-   switch (filter[0].code) {
-   case BPF_RET | BPF_K:
-   case BPF_LD |

[PATCH] ARM: net: bpf: fix zero right shift

2016-01-05 Thread Rabin Vincent
The LSR instruction cannot be used to perform a zero right shift since a
0 as the immediate value (imm5) in the LSR instruction encoding means
that a shift of 32 is perfomed.  See DecodeIMMShift() in the ARM ARM.

Make the JIT skip generation of the LSR if a zero-shift is requested.

This was found using american fuzzy lop.

Signed-off-by: Rabin Vincent <ra...@rab.in>
---
 arch/arm/net/bpf_jit_32.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index e153eb065fe4..93d0b6d0b63e 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -756,7 +756,8 @@ load_ind:
case BPF_ALU | BPF_RSH | BPF_K:
if (unlikely(k > 31))
return -1;
-   emit(ARM_LSR_I(r_A, r_A, k), ctx);
+   if (k)
+   emit(ARM_LSR_I(r_A, r_A, k), ctx);
break;
case BPF_ALU | BPF_RSH | BPF_X:
update_on_xread(ctx);
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] arm64: net: bpf: don't BUG() on large shifts

2016-01-05 Thread Rabin Vincent
Attempting to generate UBFM/SBFM instructions with shifts that can't be
encoded in the immediate fields of the opcodes leads to a trigger of a
BUG() in the instruction generation code.  As the ARMv8 ARM says: "The
shift amounts must be in the range 0 to one less than the register width
of the instruction, inclusive."  Make the JIT reject unencodable shifts
instead of crashing.

 [ cut here ]
 kernel BUG at arch/arm64/kernel/insn.c:766!
 Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
 CPU: 0 PID: 669 Comm: insmod Not tainted 4.4.0-rc8+ #4
 PC is at aarch64_insn_gen_bitfield+0xcc/0xd4
 LR is at build_body+0x1000/0x2914
 ..
 Call trace:
 [] aarch64_insn_gen_bitfield+0xcc/0xd4
 [] build_body+0x1000/0x2914
 [] bpf_int_jit_compile+0x7c/0x1b4
 [] bpf_prog_select_runtime+0x20/0xcc
 [] bpf_prepare_filter+0x3d8/0x3e8
 [] bpf_prog_create+0x74/0xa4
 [] test_bpf_init+0x1d4/0x748 [test_bpf]
 [] do_one_initcall+0x90/0x1a8
 [] do_init_module+0x60/0x1c8
 [] load_module+0x1554/0x1c98
 [] SyS_init_module+0x11c/0x140
 [] el0_svc_naked+0x24/0x28

Signed-off-by: Rabin Vincent <ra...@rab.in>
---
 arch/arm64/net/bpf_jit_comp.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index b162ad70effc..3f4f089a85c0 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -255,6 +255,7 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
const s32 imm = insn->imm;
const int i = insn - ctx->prog->insnsi;
const bool is64 = BPF_CLASS(code) == BPF_ALU64;
+   const int bits = is64 ? 64 : 32;
u8 jmp_cond;
s32 jmp_offset;
 
@@ -444,14 +445,20 @@ emit_bswap_uxt:
break;
case BPF_ALU | BPF_LSH | BPF_K:
case BPF_ALU64 | BPF_LSH | BPF_K:
+   if (imm < 0 || imm >= bits)
+   return -EINVAL;
emit(A64_LSL(is64, dst, dst, imm), ctx);
break;
case BPF_ALU | BPF_RSH | BPF_K:
case BPF_ALU64 | BPF_RSH | BPF_K:
+   if (imm < 0 || imm >= bits)
+   return -EINVAL;
emit(A64_LSR(is64, dst, dst, imm), ctx);
break;
case BPF_ALU | BPF_ARSH | BPF_K:
case BPF_ALU64 | BPF_ARSH | BPF_K:
+   if (imm < 0 || imm >= bits)
+   return -EINVAL;
emit(A64_ASR(is64, dst, dst, imm), ctx);
break;
 
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] net: filter: make JITs zero A for SKF_AD_ALU_XOR_X

2016-01-05 Thread Rabin Vincent
On Tue, Jan 05, 2016 at 08:00:45AM -0800, Eric Dumazet wrote:
> On Tue, 2016-01-05 at 16:23 +0100, Rabin Vincent wrote:
> > The SKF_AD_ALU_XOR_X ancillary is not like the other ancillary data
> > instructions since it XORs A with X while all the others replace A with
> > some loaded value.  All the BPF JITs fail to clear A if this is used as
> > the first instruction in a filter.
> 
> Is x86_64 part of this 'All' subset ? ;)

No, because it's an eBPF JIT.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html