Merge 4.9.101 into android-4.9

Changes in 4.9.101
	8139too: Use disable_irq_nosync() in rtl8139_poll_controller()
	bridge: check iface upper dev when setting master via ioctl
	dccp: fix tasklet usage
	ipv4: fix memory leaks in udp_sendmsg, ping_v4_sendmsg
	llc: better deal with too small mtu
	net: ethernet: sun: niu set correct packet size in skb
	net: ethernet: ti: cpsw: fix packet leaking in dual_mac mode
	net/mlx4_en: Verify coalescing parameters are in range
	net/mlx5: E-Switch, Include VF RDMA stats in vport statistics
	net_sched: fq: take care of throttled flows before reuse
	net: support compat 64-bit time in {s,g}etsockopt
	openvswitch: Don't swap table in nlattr_set() after OVS_ATTR_NESTED is found
	qmi_wwan: do not steal interfaces from class drivers
	r8169: fix powering up RTL8168h
	sctp: handle two v4 addrs comparison in sctp_inet6_cmp_addr
	sctp: remove sctp_chunk_put from fail_mark err path in sctp_ulpevent_make_rcvmsg
	sctp: use the old asoc when making the cookie-ack chunk in dupcook_d
	tcp_bbr: fix to zero idle_restart only upon S/ACKed data
	tg3: Fix vunmap() BUG_ON() triggered from tg3_free_consistent().
	bonding: do not allow rlb updates to invalid mac
	net/mlx5: Avoid cleaning flow steering table twice during error flow
	bonding: send learning packets for vlans on slave
	tcp: ignore Fast Open on repair mode
	sctp: fix the issue that the cookie-ack with auth can't get processed
	sctp: delay the authentication for the duplicated cookie-echo chunk
	serial: sccnxp: Fix error handling in sccnxp_probe()
	futex: Remove duplicated code and fix undefined behaviour
	xfrm: fix xfrm_do_migrate() with AEAD e.g(AES-GCM)
	lockd: lost rollback of set_grace_period() in lockd_down_net()
	Revert "ARM: dts: imx6qdl-wandboard: Fix audio channel swap"
	l2tp: revert "l2tp: fix missing print session offset info"
	nfp: TX time stamp packets before HW doorbell is rung
	proc: do not access cmdline nor environ from file-backed areas
	futex: futex_wake_op, fix sign_extend32 sign bits
	kernel/exit.c: avoid undefined behaviour when calling wait4()
	Linux 4.9.101

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2018-05-19 14:06:17 +02:00
60 changed files with 384 additions and 584 deletions

View File

@@ -1,6 +1,6 @@
VERSION = 4 VERSION = 4
PATCHLEVEL = 9 PATCHLEVEL = 9
SUBLEVEL = 100 SUBLEVEL = 101
EXTRAVERSION = EXTRAVERSION =
NAME = Roaring Lionus NAME = Roaring Lionus

View File

@@ -29,18 +29,10 @@
: "r" (uaddr), "r"(oparg) \ : "r" (uaddr), "r"(oparg) \
: "memory") : "memory")
static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -73,20 +73,11 @@
#endif #endif
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
return -EFAULT;
#ifndef CONFIG_ARC_HAS_LLSC #ifndef CONFIG_ARC_HAS_LLSC
preempt_disable(); /* to guarantee atomic r-m-w of futex op */ preempt_disable(); /* to guarantee atomic r-m-w of futex op */
#endif #endif
@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
preempt_enable(); preempt_enable();
#endif #endif
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ:
ret = (oldval == cmparg);
break;
case FUTEX_OP_CMP_NE:
ret = (oldval != cmparg);
break;
case FUTEX_OP_CMP_LT:
ret = (oldval < cmparg);
break;
case FUTEX_OP_CMP_GE:
ret = (oldval >= cmparg);
break;
case FUTEX_OP_CMP_LE:
ret = (oldval <= cmparg);
break;
case FUTEX_OP_CMP_GT:
ret = (oldval > cmparg);
break;
default:
ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -88,7 +88,6 @@
clocks = <&clks IMX6QDL_CLK_CKO>; clocks = <&clks IMX6QDL_CLK_CKO>;
VDDA-supply = <&reg_2p5v>; VDDA-supply = <&reg_2p5v>;
VDDIO-supply = <&reg_3p3v>; VDDIO-supply = <&reg_3p3v>;
lrclk-strength = <3>;
}; };
}; };

View File

@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
#endif /* !SMP */ #endif /* !SMP */
static inline int static inline int
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret, tmp; int oldval = 0, ret, tmp;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
preempt_disable(); preempt_disable();
#endif #endif
@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
preempt_enable(); preempt_enable();
#endif #endif
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -48,20 +48,9 @@ do { \
} while (0) } while (0)
static inline int static inline int
futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *_uaddr) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (int)(encoded_op << 8) >> 20;
int cmparg = (int)(encoded_op << 20) >> 20;
int oldval = 0, ret, tmp; int oldval = 0, ret, tmp;
u32 __user *uaddr = __uaccess_mask_ptr(_uaddr);
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1U << (oparg & 0x1f);
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
@@ -92,17 +81,9 @@ futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *_uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -7,7 +7,8 @@
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr); extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr);
static inline int static inline int
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,

View File

@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_o
/* /*
* do the futex operations * do the futex operations
*/ */
int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
switch (op) { switch (op) {
@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS; break;
}
}
return ret; return ret;
} /* end futex_atomic_op_inuser() */ } /* end arch_futex_atomic_op_inuser() */

View File

@@ -31,18 +31,9 @@
static inline int static inline int
futex_atomic_op_inuser(int encoded_op, int __user *uaddr) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ:
ret = (oldval == cmparg);
break;
case FUTEX_OP_CMP_NE:
ret = (oldval != cmparg);
break;
case FUTEX_OP_CMP_LT:
ret = (oldval < cmparg);
break;
case FUTEX_OP_CMP_GE:
ret = (oldval >= cmparg);
break;
case FUTEX_OP_CMP_LE:
ret = (oldval <= cmparg);
break;
case FUTEX_OP_CMP_GT:
ret = (oldval > cmparg);
break;
default:
ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -45,18 +45,9 @@ do { \
} while (0) } while (0)
static inline int static inline int
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -29,18 +29,9 @@
}) })
static inline int static inline int
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ:
ret = (oldval == cmparg);
break;
case FUTEX_OP_CMP_NE:
ret = (oldval != cmparg);
break;
case FUTEX_OP_CMP_LT:
ret = (oldval < cmparg);
break;
case FUTEX_OP_CMP_GE:
ret = (oldval >= cmparg);
break;
case FUTEX_OP_CMP_LE:
ret = (oldval <= cmparg);
break;
case FUTEX_OP_CMP_GT:
ret = (oldval > cmparg);
break;
default:
ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -83,18 +83,9 @@
} }
static inline int static inline int
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -32,22 +32,12 @@ _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
} }
static inline int static inline int
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ {
unsigned long int flags; unsigned long int flags;
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval, ret; int oldval, ret;
u32 tmp; u32 tmp;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))
return -EFAULT;
_futex_spin_lock_irqsave(uaddr, &flags); _futex_spin_lock_irqsave(uaddr, &flags);
pagefault_disable(); pagefault_disable();
@@ -85,17 +75,9 @@ out_pagefault_enable:
pagefault_enable(); pagefault_enable();
_futex_spin_unlock_irqrestore(uaddr, &flags); _futex_spin_unlock_irqrestore(uaddr, &flags);
if (ret == 0) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -31,18 +31,10 @@
: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
: "cr0", "memory") : "cr0", "memory")
static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -21,17 +21,12 @@
: "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
"m" (*uaddr) : "cc"); "m" (*uaddr) : "cc");
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, newval, ret; int oldval = 0, newval, ret;
load_kernel_asce(); load_kernel_asce();
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
pagefault_disable(); pagefault_disable();
switch (op) { switch (op) {
@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
} }
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -27,21 +27,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval); return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
} }
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
u32 oparg = (encoded_op << 8) >> 20;
u32 cmparg = (encoded_op << 20) >> 20;
u32 oldval, newval, prev; u32 oldval, newval, prev;
int ret; int ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
do { do {
@@ -80,17 +71,8 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = ((int)oldval < (int)cmparg); break;
case FUTEX_OP_CMP_GE: ret = ((int)oldval >= (int)cmparg); break;
case FUTEX_OP_CMP_LE: ret = ((int)oldval <= (int)cmparg); break;
case FUTEX_OP_CMP_GT: ret = ((int)oldval > (int)cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -29,22 +29,14 @@
: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
: "memory") : "memory")
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret, tem; int oldval = 0, ret, tem;
if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
return -EFAULT;
if (unlikely((((unsigned long) uaddr) & 0x3UL))) if (unlikely((((unsigned long) uaddr) & 0x3UL)))
return -EINVAL; return -EINVAL;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
pagefault_disable(); pagefault_disable();
switch (op) { switch (op) {
@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -106,12 +106,9 @@
lock = __atomic_hashed_lock((int __force *)uaddr) lock = __atomic_hashed_lock((int __force *)uaddr)
#endif #endif
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int uninitialized_var(val), ret; int uninitialized_var(val), ret;
__futex_prolog(); __futex_prolog();
@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
/* The 32-bit futex code makes this assumption, so validate it here. */ /* The 32-bit futex code makes this assumption, so validate it here. */
BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int)); BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
switch (op) { switch (op) {
case FUTEX_OP_SET: case FUTEX_OP_SET:
@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
} }
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = val;
case FUTEX_OP_CMP_EQ:
ret = (val == cmparg);
break;
case FUTEX_OP_CMP_NE:
ret = (val != cmparg);
break;
case FUTEX_OP_CMP_LT:
ret = (val < cmparg);
break;
case FUTEX_OP_CMP_GE:
ret = (val >= cmparg);
break;
case FUTEX_OP_CMP_LE:
ret = (val <= cmparg);
break;
case FUTEX_OP_CMP_GT:
ret = (val > cmparg);
break;
default:
ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -41,20 +41,11 @@
"+m" (*uaddr), "=&r" (tem) \ "+m" (*uaddr), "=&r" (tem) \
: "r" (oparg), "i" (-EFAULT), "1" (0)) : "r" (oparg), "i" (-EFAULT), "1" (0))
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret, tem; int oldval = 0, ret, tem;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
switch (op) { switch (op) {
@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ:
ret = (oldval == cmparg);
break;
case FUTEX_OP_CMP_NE:
ret = (oldval != cmparg);
break;
case FUTEX_OP_CMP_LT:
ret = (oldval < cmparg);
break;
case FUTEX_OP_CMP_GE:
ret = (oldval >= cmparg);
break;
case FUTEX_OP_CMP_LE:
ret = (oldval <= cmparg);
break;
case FUTEX_OP_CMP_GT:
ret = (oldval > cmparg);
break;
default:
ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -44,18 +44,10 @@
: "r" (uaddr), "I" (-EFAULT), "r" (oparg) \ : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \
: "memory") : "memory")
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
#if !XCHAL_HAVE_S32C1I #if !XCHAL_HAVE_S32C1I
return -ENOSYS; return -ENOSYS;
@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (ret) if (!ret)
return ret; *oval = oldval;
switch (cmp) { return ret;
case FUTEX_OP_CMP_EQ: return (oldval == cmparg);
case FUTEX_OP_CMP_NE: return (oldval != cmparg);
case FUTEX_OP_CMP_LT: return (oldval < cmparg);
case FUTEX_OP_CMP_GE: return (oldval >= cmparg);
case FUTEX_OP_CMP_LE: return (oldval <= cmparg);
case FUTEX_OP_CMP_GT: return (oldval > cmparg);
}
return -ENOSYS;
} }
static inline int static inline int

View File

@@ -450,7 +450,7 @@ static void rlb_update_client(struct rlb_client_info *client_info)
{ {
int i; int i;
if (!client_info->slave) if (!client_info->slave || !is_valid_ether_addr(client_info->mac_dst))
return; return;
for (i = 0; i < RLB_ARP_BURST_SIZE; i++) { for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
@@ -944,6 +944,10 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
skb->priority = TC_PRIO_CONTROL; skb->priority = TC_PRIO_CONTROL;
skb->dev = slave->dev; skb->dev = slave->dev;
netdev_dbg(slave->bond->dev,
"Send learning packet: dev %s mac %pM vlan %d\n",
slave->dev->name, mac_addr, vid);
if (vid) if (vid)
__vlan_hwaccel_put_tag(skb, vlan_proto, vid); __vlan_hwaccel_put_tag(skb, vlan_proto, vid);
@@ -966,14 +970,13 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
*/ */
rcu_read_lock(); rcu_read_lock();
netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) { netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) { if (is_vlan_dev(upper) &&
if (strict_match && bond->nest_level == vlan_get_encap_level(upper) - 1) {
ether_addr_equal_64bits(mac_addr, if (upper->addr_assign_type == NET_ADDR_STOLEN) {
upper->dev_addr)) {
alb_send_lp_vid(slave, mac_addr, alb_send_lp_vid(slave, mac_addr,
vlan_dev_vlan_proto(upper), vlan_dev_vlan_proto(upper),
vlan_dev_vlan_id(upper)); vlan_dev_vlan_id(upper));
} else if (!strict_match) { } else {
alb_send_lp_vid(slave, upper->dev_addr, alb_send_lp_vid(slave, upper->dev_addr,
vlan_dev_vlan_proto(upper), vlan_dev_vlan_proto(upper),
vlan_dev_vlan_id(upper)); vlan_dev_vlan_id(upper));

View File

@@ -1732,6 +1732,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (bond_mode_uses_xmit_hash(bond)) if (bond_mode_uses_xmit_hash(bond))
bond_update_slave_arr(bond, NULL); bond_update_slave_arr(bond, NULL);
bond->nest_level = dev_get_nest_level(bond_dev);
netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n", netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n",
slave_dev->name, slave_dev->name,
bond_is_active_slave(new_slave) ? "an active" : "a backup", bond_is_active_slave(new_slave) ? "an active" : "a backup",

View File

@@ -8720,14 +8720,15 @@ static void tg3_free_consistent(struct tg3 *tp)
tg3_mem_rx_release(tp); tg3_mem_rx_release(tp);
tg3_mem_tx_release(tp); tg3_mem_tx_release(tp);
/* Protect tg3_get_stats64() from reading freed tp->hw_stats. */ /* tp->hw_stats can be referenced safely:
tg3_full_lock(tp, 0); * 1. under rtnl_lock
* 2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set.
*/
if (tp->hw_stats) { if (tp->hw_stats) {
dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
tp->hw_stats, tp->stats_mapping); tp->hw_stats, tp->stats_mapping);
tp->hw_stats = NULL; tp->hw_stats = NULL;
} }
tg3_full_unlock(tp);
} }
/* /*
@@ -14161,7 +14162,7 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
struct tg3 *tp = netdev_priv(dev); struct tg3 *tp = netdev_priv(dev);
spin_lock_bh(&tp->lock); spin_lock_bh(&tp->lock);
if (!tp->hw_stats) { if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) {
*stats = tp->net_stats_prev; *stats = tp->net_stats_prev;
spin_unlock_bh(&tp->lock); spin_unlock_bh(&tp->lock);
return stats; return stats;

View File

@@ -970,6 +970,22 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
if (!coal->tx_max_coalesced_frames_irq) if (!coal->tx_max_coalesced_frames_irq)
return -EINVAL; return -EINVAL;
if (coal->tx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||
coal->rx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||
coal->rx_coalesce_usecs_low > MLX4_EN_MAX_COAL_TIME ||
coal->rx_coalesce_usecs_high > MLX4_EN_MAX_COAL_TIME) {
netdev_info(dev, "%s: maximum coalesce time supported is %d usecs\n",
__func__, MLX4_EN_MAX_COAL_TIME);
return -ERANGE;
}
if (coal->tx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS ||
coal->rx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS) {
netdev_info(dev, "%s: maximum coalesced frames supported is %d\n",
__func__, MLX4_EN_MAX_COAL_PKTS);
return -ERANGE;
}
priv->rx_frames = (coal->rx_max_coalesced_frames == priv->rx_frames = (coal->rx_max_coalesced_frames ==
MLX4_EN_AUTO_CONF) ? MLX4_EN_AUTO_CONF) ?
MLX4_EN_RX_COAL_TARGET : MLX4_EN_RX_COAL_TARGET :

View File

@@ -141,6 +141,9 @@ enum {
#define MLX4_EN_TX_COAL_PKTS 16 #define MLX4_EN_TX_COAL_PKTS 16
#define MLX4_EN_TX_COAL_TIME 0x10 #define MLX4_EN_TX_COAL_TIME 0x10
#define MLX4_EN_MAX_COAL_PKTS U16_MAX
#define MLX4_EN_MAX_COAL_TIME U16_MAX
#define MLX4_EN_RX_RATE_LOW 400000 #define MLX4_EN_RX_RATE_LOW 400000
#define MLX4_EN_RX_COAL_TIME_LOW 0 #define MLX4_EN_RX_COAL_TIME_LOW 0
#define MLX4_EN_RX_RATE_HIGH 450000 #define MLX4_EN_RX_RATE_HIGH 450000
@@ -543,8 +546,8 @@ struct mlx4_en_priv {
u16 rx_usecs_low; u16 rx_usecs_low;
u32 pkt_rate_high; u32 pkt_rate_high;
u16 rx_usecs_high; u16 rx_usecs_high;
u16 sample_interval; u32 sample_interval;
u16 adaptive_rx_coal; u32 adaptive_rx_coal;
u32 msg_enable; u32 msg_enable;
u32 loopback_ok; u32 loopback_ok;
u32 validate_loopback; u32 validate_loopback;

View File

@@ -1924,26 +1924,35 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
memset(vf_stats, 0, sizeof(*vf_stats)); memset(vf_stats, 0, sizeof(*vf_stats));
vf_stats->rx_packets = vf_stats->rx_packets =
MLX5_GET_CTR(out, received_eth_unicast.packets) + MLX5_GET_CTR(out, received_eth_unicast.packets) +
MLX5_GET_CTR(out, received_ib_unicast.packets) +
MLX5_GET_CTR(out, received_eth_multicast.packets) + MLX5_GET_CTR(out, received_eth_multicast.packets) +
MLX5_GET_CTR(out, received_ib_multicast.packets) +
MLX5_GET_CTR(out, received_eth_broadcast.packets); MLX5_GET_CTR(out, received_eth_broadcast.packets);
vf_stats->rx_bytes = vf_stats->rx_bytes =
MLX5_GET_CTR(out, received_eth_unicast.octets) + MLX5_GET_CTR(out, received_eth_unicast.octets) +
MLX5_GET_CTR(out, received_ib_unicast.octets) +
MLX5_GET_CTR(out, received_eth_multicast.octets) + MLX5_GET_CTR(out, received_eth_multicast.octets) +
MLX5_GET_CTR(out, received_ib_multicast.octets) +
MLX5_GET_CTR(out, received_eth_broadcast.octets); MLX5_GET_CTR(out, received_eth_broadcast.octets);
vf_stats->tx_packets = vf_stats->tx_packets =
MLX5_GET_CTR(out, transmitted_eth_unicast.packets) + MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
MLX5_GET_CTR(out, transmitted_eth_multicast.packets) + MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
MLX5_GET_CTR(out, transmitted_eth_broadcast.packets); MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
vf_stats->tx_bytes = vf_stats->tx_bytes =
MLX5_GET_CTR(out, transmitted_eth_unicast.octets) + MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
MLX5_GET_CTR(out, transmitted_eth_multicast.octets) + MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
MLX5_GET_CTR(out, transmitted_eth_broadcast.octets); MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
vf_stats->multicast = vf_stats->multicast =
MLX5_GET_CTR(out, received_eth_multicast.packets); MLX5_GET_CTR(out, received_eth_multicast.packets) +
MLX5_GET_CTR(out, received_ib_multicast.packets);
vf_stats->broadcast = vf_stats->broadcast =
MLX5_GET_CTR(out, received_eth_broadcast.packets); MLX5_GET_CTR(out, received_eth_broadcast.packets);

View File

@@ -153,6 +153,7 @@ static void del_rule(struct fs_node *node);
static void del_flow_table(struct fs_node *node); static void del_flow_table(struct fs_node *node);
static void del_flow_group(struct fs_node *node); static void del_flow_group(struct fs_node *node);
static void del_fte(struct fs_node *node); static void del_fte(struct fs_node *node);
static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns);
static void tree_init_node(struct fs_node *node, static void tree_init_node(struct fs_node *node,
unsigned int refcount, unsigned int refcount,
@@ -1690,24 +1691,28 @@ static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
static int init_root_ns(struct mlx5_flow_steering *steering) static int init_root_ns(struct mlx5_flow_steering *steering)
{ {
int err;
steering->root_ns = create_root_ns(steering, FS_FT_NIC_RX); steering->root_ns = create_root_ns(steering, FS_FT_NIC_RX);
if (!steering->root_ns) if (!steering->root_ns)
goto cleanup; return -ENOMEM;
if (init_root_tree(steering, &root_fs, &steering->root_ns->ns.node)) err = init_root_tree(steering, &root_fs, &steering->root_ns->ns.node);
goto cleanup; if (err)
goto out_err;
set_prio_attrs(steering->root_ns); set_prio_attrs(steering->root_ns);
if (create_anchor_flow_table(steering)) err = create_anchor_flow_table(steering);
goto cleanup; if (err)
goto out_err;
return 0; return 0;
cleanup: out_err:
mlx5_cleanup_fs(steering->dev); cleanup_root_ns(steering->root_ns);
return -ENOMEM; steering->root_ns = NULL;
return err;
} }
static void clean_tree(struct fs_node *node) static void clean_tree(struct fs_node *node)

View File

@@ -854,6 +854,8 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
netdev_tx_sent_queue(nd_q, txbuf->real_len); netdev_tx_sent_queue(nd_q, txbuf->real_len);
skb_tx_timestamp(skb);
tx_ring->wr_p += nr_frags + 1; tx_ring->wr_p += nr_frags + 1;
if (nfp_net_tx_ring_should_stop(tx_ring)) if (nfp_net_tx_ring_should_stop(tx_ring))
nfp_net_tx_ring_stop(nd_q, tx_ring); nfp_net_tx_ring_stop(nd_q, tx_ring);
@@ -866,8 +868,6 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
tx_ring->wr_ptr_add = 0; tx_ring->wr_ptr_add = 0;
} }
skb_tx_timestamp(skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
err_unmap: err_unmap:

View File

@@ -2233,7 +2233,7 @@ static void rtl8139_poll_controller(struct net_device *dev)
struct rtl8139_private *tp = netdev_priv(dev); struct rtl8139_private *tp = netdev_priv(dev);
const int irq = tp->pci_dev->irq; const int irq = tp->pci_dev->irq;
disable_irq(irq); disable_irq_nosync(irq);
rtl8139_interrupt(irq, dev); rtl8139_interrupt(irq, dev);
enable_irq(irq); enable_irq(irq);
} }

View File

@@ -4861,6 +4861,9 @@ static void rtl_pll_power_down(struct rtl8169_private *tp)
static void rtl_pll_power_up(struct rtl8169_private *tp) static void rtl_pll_power_up(struct rtl8169_private *tp)
{ {
rtl_generic_op(tp, tp->pll_power_ops.up); rtl_generic_op(tp, tp->pll_power_ops.up);
/* give MAC/PHY some time to resume */
msleep(20);
} }
static void rtl_init_pll_power_ops(struct rtl8169_private *tp) static void rtl_init_pll_power_ops(struct rtl8169_private *tp)

View File

@@ -3442,7 +3442,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
len = (val & RCR_ENTRY_L2_LEN) >> len = (val & RCR_ENTRY_L2_LEN) >>
RCR_ENTRY_L2_LEN_SHIFT; RCR_ENTRY_L2_LEN_SHIFT;
len -= ETH_FCS_LEN; append_size = len + ETH_HLEN + ETH_FCS_LEN;
addr = (val & RCR_ENTRY_PKT_BUF_ADDR) << addr = (val & RCR_ENTRY_PKT_BUF_ADDR) <<
RCR_ENTRY_PKT_BUF_ADDR_SHIFT; RCR_ENTRY_PKT_BUF_ADDR_SHIFT;
@@ -3452,7 +3452,6 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
RCR_ENTRY_PKTBUFSZ_SHIFT]; RCR_ENTRY_PKTBUFSZ_SHIFT];
off = addr & ~PAGE_MASK; off = addr & ~PAGE_MASK;
append_size = rcr_size;
if (num_rcr == 1) { if (num_rcr == 1) {
int ptype; int ptype;
@@ -3465,7 +3464,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
else else
skb_checksum_none_assert(skb); skb_checksum_none_assert(skb);
} else if (!(val & RCR_ENTRY_MULTI)) } else if (!(val & RCR_ENTRY_MULTI))
append_size = len - skb->len; append_size = append_size - skb->len;
niu_rx_skb_append(skb, page, off, append_size, rcr_size); niu_rx_skb_append(skb, page, off, append_size, rcr_size);
if ((page->index + rp->rbr_block_size) - rcr_size == addr) { if ((page->index + rp->rbr_block_size) - rcr_size == addr) {

View File

@@ -1141,6 +1141,8 @@ static inline void cpsw_add_dual_emac_def_ale_entries(
cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr, cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr,
HOST_PORT_NUM, ALE_VLAN | HOST_PORT_NUM, ALE_VLAN |
ALE_SECURE, slave->port_vlan); ALE_SECURE, slave->port_vlan);
cpsw_ale_control_set(cpsw->ale, slave_port,
ALE_PORT_DROP_UNKNOWN_VLAN, 1);
} }
static void soft_reset_slave(struct cpsw_slave *slave) static void soft_reset_slave(struct cpsw_slave *slave)

View File

@@ -1039,6 +1039,18 @@ static int qmi_wwan_probe(struct usb_interface *intf,
id->driver_info = (unsigned long)&qmi_wwan_info; id->driver_info = (unsigned long)&qmi_wwan_info;
} }
/* There are devices where the same interface number can be
* configured as different functions. We should only bind to
* vendor specific functions when matching on interface number
*/
if (id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER &&
desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) {
dev_dbg(&intf->dev,
"Rejecting interface number match for class %02x\n",
desc->bInterfaceClass);
return -ENODEV;
}
/* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */ /* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */
if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) { if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) {
dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n"); dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n");

View File

@@ -889,7 +889,16 @@ static int sccnxp_probe(struct platform_device *pdev)
goto err_out; goto err_out;
uartclk = 0; uartclk = 0;
} else { } else {
clk_prepare_enable(clk); ret = clk_prepare_enable(clk);
if (ret)
goto err_out;
ret = devm_add_action_or_reset(&pdev->dev,
(void(*)(void *))clk_disable_unprepare,
clk);
if (ret)
goto err_out;
uartclk = clk_get_rate(clk); uartclk = clk_get_rate(clk);
} }
@@ -988,7 +997,7 @@ static int sccnxp_probe(struct platform_device *pdev)
uart_unregister_driver(&s->uart); uart_unregister_driver(&s->uart);
err_out: err_out:
if (!IS_ERR(s->regulator)) if (!IS_ERR(s->regulator))
return regulator_disable(s->regulator); regulator_disable(s->regulator);
return ret; return ret;
} }

View File

@@ -274,6 +274,8 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
if (ln->nlmsvc_users) { if (ln->nlmsvc_users) {
if (--ln->nlmsvc_users == 0) { if (--ln->nlmsvc_users == 0) {
nlm_shutdown_hosts_net(net); nlm_shutdown_hosts_net(net);
cancel_delayed_work_sync(&ln->grace_period_end);
locks_end_grace(&ln->lockd_manager);
svc_shutdown_net(serv, net); svc_shutdown_net(serv, net);
dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net); dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net);
} }

View File

@@ -253,7 +253,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
* Inherently racy -- command line shares address space * Inherently racy -- command line shares address space
* with code and data. * with code and data.
*/ */
rv = access_remote_vm(mm, arg_end - 1, &c, 1, 0); rv = access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON);
if (rv <= 0) if (rv <= 0)
goto out_free_page; goto out_free_page;
@@ -271,7 +271,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
int nr_read; int nr_read;
_count = min3(count, len, PAGE_SIZE); _count = min3(count, len, PAGE_SIZE);
nr_read = access_remote_vm(mm, p, page, _count, 0); nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
if (nr_read < 0) if (nr_read < 0)
rv = nr_read; rv = nr_read;
if (nr_read <= 0) if (nr_read <= 0)
@@ -306,7 +306,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
bool final; bool final;
_count = min3(count, len, PAGE_SIZE); _count = min3(count, len, PAGE_SIZE);
nr_read = access_remote_vm(mm, p, page, _count, 0); nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
if (nr_read < 0) if (nr_read < 0)
rv = nr_read; rv = nr_read;
if (nr_read <= 0) if (nr_read <= 0)
@@ -355,7 +355,7 @@ skip_argv:
bool final; bool final;
_count = min3(count, len, PAGE_SIZE); _count = min3(count, len, PAGE_SIZE);
nr_read = access_remote_vm(mm, p, page, _count, 0); nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
if (nr_read < 0) if (nr_read < 0)
rv = nr_read; rv = nr_read;
if (nr_read <= 0) if (nr_read <= 0)
@@ -971,7 +971,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
max_len = min_t(size_t, PAGE_SIZE, count); max_len = min_t(size_t, PAGE_SIZE, count);
this_len = min(max_len, this_len); this_len = min(max_len, this_len);
retval = access_remote_vm(mm, (env_start + src), page, this_len, 0); retval = access_remote_vm(mm, (env_start + src), page, this_len, FOLL_ANON);
if (retval <= 0) { if (retval <= 0) {
ret = retval; ret = retval;

View File

@@ -13,7 +13,7 @@
*/ */
/** /**
* futex_atomic_op_inuser() - Atomic arithmetic operation with constant * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant
* argument and comparison of the previous * argument and comparison of the previous
* futex value with another constant. * futex value with another constant.
* *
@@ -25,18 +25,11 @@
* <0 - On error * <0 - On error
*/ */
static inline int static inline int
futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval, ret; int oldval, ret;
u32 tmp; u32 tmp;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
preempt_disable(); preempt_disable();
pagefault_disable(); pagefault_disable();
@@ -74,17 +67,9 @@ out_pagefault_enable:
pagefault_enable(); pagefault_enable();
preempt_enable(); preempt_enable();
if (ret == 0) { if (ret == 0)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }
@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
#else #else
static inline int static inline int
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
{ {
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
int oparg = (encoded_op << 8) >> 20;
int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret; int oldval = 0, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
pagefault_disable(); pagefault_disable();
@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
pagefault_enable(); pagefault_enable();
if (!ret) { if (!ret)
switch (cmp) { *oval = oldval;
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
default: ret = -ENOSYS;
}
}
return ret; return ret;
} }

View File

@@ -2247,6 +2247,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
#define FOLL_MLOCK 0x1000 /* lock present pages */ #define FOLL_MLOCK 0x1000 /* lock present pages */
#define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */ #define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */
#define FOLL_COW 0x4000 /* internal GUP flag */ #define FOLL_COW 0x4000 /* internal GUP flag */
#define FOLL_ANON 0x8000 /* don't do file mappings */
typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
void *data); void *data);

View File

@@ -197,6 +197,7 @@ struct bonding {
struct slave __rcu *primary_slave; struct slave __rcu *primary_slave;
struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */ struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
bool force_primary; bool force_primary;
u32 nest_level;
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */ s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
int (*recv_probe)(const struct sk_buff *, struct bonding *, int (*recv_probe)(const struct sk_buff *, struct bonding *,
struct slave *); struct slave *);

View File

@@ -1671,6 +1671,10 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
__WNOTHREAD|__WCLONE|__WALL)) __WNOTHREAD|__WCLONE|__WALL))
return -EINVAL; return -EINVAL;
/* -INT_MIN is not defined */
if (upid == INT_MIN)
return -ESRCH;
if (upid == -1) if (upid == -1)
type = PIDTYPE_MAX; type = PIDTYPE_MAX;
else if (upid < 0) { else if (upid < 0) {

View File

@@ -1458,6 +1458,45 @@ out:
return ret; return ret;
} }
static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
{
unsigned int op = (encoded_op & 0x70000000) >> 28;
unsigned int cmp = (encoded_op & 0x0f000000) >> 24;
int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 11);
int cmparg = sign_extend32(encoded_op & 0x00000fff, 11);
int oldval, ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {
if (oparg < 0 || oparg > 31)
return -EINVAL;
oparg = 1 << oparg;
}
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);
if (ret)
return ret;
switch (cmp) {
case FUTEX_OP_CMP_EQ:
return oldval == cmparg;
case FUTEX_OP_CMP_NE:
return oldval != cmparg;
case FUTEX_OP_CMP_LT:
return oldval < cmparg;
case FUTEX_OP_CMP_GE:
return oldval >= cmparg;
case FUTEX_OP_CMP_LE:
return oldval <= cmparg;
case FUTEX_OP_CMP_GT:
return oldval > cmparg;
default:
return -ENOSYS;
}
}
/* /*
* Wake up all waiters hashed on the physical page that is mapped * Wake up all waiters hashed on the physical page that is mapped
* to this virtual address: * to this virtual address:

View File

@@ -430,6 +430,9 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
if (vm_flags & (VM_IO | VM_PFNMAP)) if (vm_flags & (VM_IO | VM_PFNMAP))
return -EFAULT; return -EFAULT;
if (gup_flags & FOLL_ANON && !vma_is_anonymous(vma))
return -EFAULT;
if (write) { if (write) {
if (!(vm_flags & VM_WRITE)) { if (!(vm_flags & VM_WRITE)) {
if (!(gup_flags & FOLL_FORCE)) if (!(gup_flags & FOLL_FORCE))

View File

@@ -504,8 +504,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit)
return -ELOOP; return -ELOOP;
/* Device is already being bridged */ /* Device has master upper dev */
if (br_port_exists(dev)) if (netdev_master_upper_dev_get(dev))
return -EBUSY; return -EBUSY;
/* No bridging devices that dislike that (e.g. wireless) */ /* No bridging devices that dislike that (e.g. wireless) */

View File

@@ -372,7 +372,8 @@ static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
optname == SO_ATTACH_REUSEPORT_CBPF) optname == SO_ATTACH_REUSEPORT_CBPF)
return do_set_attach_filter(sock, level, optname, return do_set_attach_filter(sock, level, optname,
optval, optlen); optval, optlen);
if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) if (!COMPAT_USE_64BIT_TIME &&
(optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
return do_set_sock_timeout(sock, level, optname, optval, optlen); return do_set_sock_timeout(sock, level, optname, optval, optlen);
return sock_setsockopt(sock, level, optname, optval, optlen); return sock_setsockopt(sock, level, optname, optval, optlen);
@@ -437,7 +438,8 @@ static int do_get_sock_timeout(struct socket *sock, int level, int optname,
static int compat_sock_getsockopt(struct socket *sock, int level, int optname, static int compat_sock_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen) char __user *optval, int __user *optlen)
{ {
if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) if (!COMPAT_USE_64BIT_TIME &&
(optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
return do_get_sock_timeout(sock, level, optname, optval, optlen); return do_get_sock_timeout(sock, level, optname, optval, optlen);
return sock_getsockopt(sock, level, optname, optval, optlen); return sock_getsockopt(sock, level, optname, optval, optlen);
} }

View File

@@ -126,6 +126,16 @@ static void ccid2_change_l_seq_window(struct sock *sk, u64 val)
DCCPF_SEQ_WMAX)); DCCPF_SEQ_WMAX));
} }
static void dccp_tasklet_schedule(struct sock *sk)
{
struct tasklet_struct *t = &dccp_sk(sk)->dccps_xmitlet;
if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
sock_hold(sk);
__tasklet_schedule(t);
}
}
static void ccid2_hc_tx_rto_expire(unsigned long data) static void ccid2_hc_tx_rto_expire(unsigned long data)
{ {
struct sock *sk = (struct sock *)data; struct sock *sk = (struct sock *)data;
@@ -166,7 +176,7 @@ static void ccid2_hc_tx_rto_expire(unsigned long data)
/* if we were blocked before, we may now send cwnd=1 packet */ /* if we were blocked before, we may now send cwnd=1 packet */
if (sender_was_blocked) if (sender_was_blocked)
tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); dccp_tasklet_schedule(sk);
/* restart backed-off timer */ /* restart backed-off timer */
sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
out: out:
@@ -706,7 +716,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
done: done:
/* check if incoming Acks allow pending packets to be sent */ /* check if incoming Acks allow pending packets to be sent */
if (sender_was_blocked && !ccid2_cwnd_network_limited(hc)) if (sender_was_blocked && !ccid2_cwnd_network_limited(hc))
tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); dccp_tasklet_schedule(sk);
dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks); dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
} }

View File

@@ -230,12 +230,12 @@ static void dccp_write_xmitlet(unsigned long data)
else else
dccp_write_xmit(sk); dccp_write_xmit(sk);
bh_unlock_sock(sk); bh_unlock_sock(sk);
sock_put(sk);
} }
static void dccp_write_xmit_timer(unsigned long data) static void dccp_write_xmit_timer(unsigned long data)
{ {
dccp_write_xmitlet(data); dccp_write_xmitlet(data);
sock_put((struct sock *)data);
} }
void dccp_init_xmit_timers(struct sock *sk) void dccp_init_xmit_timers(struct sock *sk)

View File

@@ -775,8 +775,10 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
ipc.addr = faddr = daddr; ipc.addr = faddr = daddr;
if (ipc.opt && ipc.opt->opt.srr) { if (ipc.opt && ipc.opt->opt.srr) {
if (!daddr) if (!daddr) {
return -EINVAL; err = -EINVAL;
goto out_free;
}
faddr = ipc.opt->opt.faddr; faddr = ipc.opt->opt.faddr;
} }
tos = get_rttos(&ipc, inet); tos = get_rttos(&ipc, inet);
@@ -842,6 +844,7 @@ back_from_confirm:
out: out:
ip_rt_put(rt); ip_rt_put(rt);
out_free:
if (free) if (free)
kfree(ipc.opt); kfree(ipc.opt);
if (!err) { if (!err) {

View File

@@ -1140,7 +1140,8 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
lock_sock(sk); lock_sock(sk);
flags = msg->msg_flags; flags = msg->msg_flags;
if (unlikely(flags & MSG_FASTOPEN || inet_sk(sk)->defer_connect)) { if (unlikely(flags & MSG_FASTOPEN || inet_sk(sk)->defer_connect) &&
!tp->repair) {
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size); err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
if (err == -EINPROGRESS && copied_syn > 0) if (err == -EINPROGRESS && copied_syn > 0)
goto out; goto out;

View File

@@ -773,7 +773,9 @@ static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs)
} }
} }
} }
bbr->idle_restart = 0; /* Restart after idle ends only once we process a new S/ACK for data */
if (rs->delivered > 0)
bbr->idle_restart = 0;
} }
static void bbr_update_model(struct sock *sk, const struct rate_sample *rs) static void bbr_update_model(struct sock *sk, const struct rate_sample *rs)

View File

@@ -982,8 +982,10 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags); sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags);
if (ipc.opt && ipc.opt->opt.srr) { if (ipc.opt && ipc.opt->opt.srr) {
if (!daddr) if (!daddr) {
return -EINVAL; err = -EINVAL;
goto out_free;
}
faddr = ipc.opt->opt.faddr; faddr = ipc.opt->opt.faddr;
connected = 0; connected = 0;
} }
@@ -1091,6 +1093,7 @@ do_append_data:
out: out:
ip_rt_put(rt); ip_rt_put(rt);
out_free:
if (free) if (free)
kfree(ipc.opt); kfree(ipc.opt);
if (!err) if (!err)

View File

@@ -750,8 +750,6 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl
if ((session->ifname[0] && if ((session->ifname[0] &&
nla_put_string(skb, L2TP_ATTR_IFNAME, session->ifname)) || nla_put_string(skb, L2TP_ATTR_IFNAME, session->ifname)) ||
(session->offset &&
nla_put_u16(skb, L2TP_ATTR_OFFSET, session->offset)) ||
(session->cookie_len && (session->cookie_len &&
nla_put(skb, L2TP_ATTR_COOKIE, session->cookie_len, nla_put(skb, L2TP_ATTR_COOKIE, session->cookie_len,
&session->cookie[0])) || &session->cookie[0])) ||

View File

@@ -926,6 +926,9 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
if (size > llc->dev->mtu) if (size > llc->dev->mtu)
size = llc->dev->mtu; size = llc->dev->mtu;
copied = size - hdrlen; copied = size - hdrlen;
rc = -EINVAL;
if (copied < 0)
goto release;
release_sock(sk); release_sock(sk);
skb = sock_alloc_send_skb(sk, size, noblock, &rc); skb = sock_alloc_send_skb(sk, size, noblock, &rc);
lock_sock(sk); lock_sock(sk);

View File

@@ -1296,13 +1296,10 @@ static void nlattr_set(struct nlattr *attr, u8 val,
/* The nlattr stream should already have been validated */ /* The nlattr stream should already have been validated */
nla_for_each_nested(nla, attr, rem) { nla_for_each_nested(nla, attr, rem) {
if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) { if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED)
if (tbl[nla_type(nla)].next) nlattr_set(nla, val, tbl[nla_type(nla)].next ? : tbl);
tbl = tbl[nla_type(nla)].next; else
nlattr_set(nla, val, tbl);
} else {
memset(nla_data(nla), val, nla_len(nla)); memset(nla_data(nla), val, nla_len(nla));
}
if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE) if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
*(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK; *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;

View File

@@ -128,6 +128,28 @@ static bool fq_flow_is_detached(const struct fq_flow *f)
return f->next == &detached; return f->next == &detached;
} }
static bool fq_flow_is_throttled(const struct fq_flow *f)
{
return f->next == &throttled;
}
static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow)
{
if (head->first)
head->last->next = flow;
else
head->first = flow;
head->last = flow;
flow->next = NULL;
}
static void fq_flow_unset_throttled(struct fq_sched_data *q, struct fq_flow *f)
{
rb_erase(&f->rate_node, &q->delayed);
q->throttled_flows--;
fq_flow_add_tail(&q->old_flows, f);
}
static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f) static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f)
{ {
struct rb_node **p = &q->delayed.rb_node, *parent = NULL; struct rb_node **p = &q->delayed.rb_node, *parent = NULL;
@@ -155,15 +177,6 @@ static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f)
static struct kmem_cache *fq_flow_cachep __read_mostly; static struct kmem_cache *fq_flow_cachep __read_mostly;
static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow)
{
if (head->first)
head->last->next = flow;
else
head->first = flow;
head->last = flow;
flow->next = NULL;
}
/* limit number of collected flows per round */ /* limit number of collected flows per round */
#define FQ_GC_MAX 8 #define FQ_GC_MAX 8
@@ -267,6 +280,8 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
f->socket_hash != sk->sk_hash)) { f->socket_hash != sk->sk_hash)) {
f->credit = q->initial_quantum; f->credit = q->initial_quantum;
f->socket_hash = sk->sk_hash; f->socket_hash = sk->sk_hash;
if (fq_flow_is_throttled(f))
fq_flow_unset_throttled(q, f);
f->time_next_packet = 0ULL; f->time_next_packet = 0ULL;
} }
return f; return f;
@@ -430,9 +445,7 @@ static void fq_check_throttled(struct fq_sched_data *q, u64 now)
q->time_next_delayed_flow = f->time_next_packet; q->time_next_delayed_flow = f->time_next_packet;
break; break;
} }
rb_erase(p, &q->delayed); fq_flow_unset_throttled(q, f);
q->throttled_flows--;
fq_flow_add_tail(&q->old_flows, f);
} }
} }

View File

@@ -1006,9 +1006,10 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
struct sctp_chunk *chunk; struct sctp_chunk *chunk;
struct sctp_inq *inqueue; struct sctp_inq *inqueue;
int state;
sctp_subtype_t subtype; sctp_subtype_t subtype;
int first_time = 1; /* is this the first time through the loop */
int error = 0; int error = 0;
int state;
/* The association should be held so we should be safe. */ /* The association should be held so we should be safe. */
ep = asoc->ep; ep = asoc->ep;
@@ -1019,6 +1020,30 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
state = asoc->state; state = asoc->state;
subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
/* If the first chunk in the packet is AUTH, do special
* processing specified in Section 6.3 of SCTP-AUTH spec
*/
if (first_time && subtype.chunk == SCTP_CID_AUTH) {
struct sctp_chunkhdr *next_hdr;
next_hdr = sctp_inq_peek(inqueue);
if (!next_hdr)
goto normal;
/* If the next chunk is COOKIE-ECHO, skip the AUTH
* chunk while saving a pointer to it so we can do
* Authentication later (during cookie-echo
* processing).
*/
if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
chunk->auth_chunk = skb_clone(chunk->skb,
GFP_ATOMIC);
chunk->auth = 1;
continue;
}
}
normal:
/* SCTP-AUTH, Section 6.3: /* SCTP-AUTH, Section 6.3:
* The receiver has a list of chunk types which it expects * The receiver has a list of chunk types which it expects
* to be received only after an AUTH-chunk. This list has * to be received only after an AUTH-chunk. This list has
@@ -1057,6 +1082,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
/* If there is an error on chunk, discard this packet. */ /* If there is an error on chunk, discard this packet. */
if (error && chunk) if (error && chunk)
chunk->pdiscard = 1; chunk->pdiscard = 1;
if (first_time)
first_time = 0;
} }
sctp_association_put(asoc); sctp_association_put(asoc);
} }

View File

@@ -217,7 +217,7 @@ new_skb:
skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
chunk->subh.v = NULL; /* Subheader is no longer valid. */ chunk->subh.v = NULL; /* Subheader is no longer valid. */
if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) < if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) <=
skb_tail_pointer(chunk->skb)) { skb_tail_pointer(chunk->skb)) {
/* This is not a singleton */ /* This is not a singleton */
chunk->singleton = 0; chunk->singleton = 0;

View File

@@ -864,6 +864,9 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2)) if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2))
return 1; return 1;
if (addr1->sa.sa_family == AF_INET && addr2->sa.sa_family == AF_INET)
return addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr;
return __sctp_v6_cmp_addr(addr1, addr2); return __sctp_v6_cmp_addr(addr1, addr2);
} }

View File

@@ -144,10 +144,8 @@ static sctp_disposition_t sctp_sf_violation_chunk(
void *arg, void *arg,
sctp_cmd_seq_t *commands); sctp_cmd_seq_t *commands);
static sctp_ierror_t sctp_sf_authenticate(struct net *net, static sctp_ierror_t sctp_sf_authenticate(
const struct sctp_endpoint *ep,
const struct sctp_association *asoc, const struct sctp_association *asoc,
const sctp_subtype_t type,
struct sctp_chunk *chunk); struct sctp_chunk *chunk);
static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net, static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net,
@@ -615,6 +613,38 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net,
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
} }
static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk,
const struct sctp_association *asoc)
{
struct sctp_chunk auth;
if (!chunk->auth_chunk)
return true;
/* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo
* is supposed to be authenticated and we have to do delayed
* authentication. We've just recreated the association using
* the information in the cookie and now it's much easier to
* do the authentication.
*/
/* Make sure that we and the peer are AUTH capable */
if (!net->sctp.auth_enable || !asoc->peer.auth_capable)
return false;
/* set-up our fake chunk so that we can process it */
auth.skb = chunk->auth_chunk;
auth.asoc = chunk->asoc;
auth.sctp_hdr = chunk->sctp_hdr;
auth.chunk_hdr = (struct sctp_chunkhdr *)
skb_push(chunk->auth_chunk,
sizeof(struct sctp_chunkhdr));
skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr));
auth.transport = chunk->transport;
return sctp_sf_authenticate(asoc, &auth) == SCTP_IERROR_NO_ERROR;
}
/* /*
* Respond to a normal COOKIE ECHO chunk. * Respond to a normal COOKIE ECHO chunk.
* We are the side that is being asked for an association. * We are the side that is being asked for an association.
@@ -751,36 +781,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
if (error) if (error)
goto nomem_init; goto nomem_init;
/* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) {
* is supposed to be authenticated and we have to do delayed sctp_association_free(new_asoc);
* authentication. We've just recreated the association using return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
* the information in the cookie and now it's much easier to
* do the authentication.
*/
if (chunk->auth_chunk) {
struct sctp_chunk auth;
sctp_ierror_t ret;
/* Make sure that we and the peer are AUTH capable */
if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) {
sctp_association_free(new_asoc);
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
/* set-up our fake chunk so that we can process it */
auth.skb = chunk->auth_chunk;
auth.asoc = chunk->asoc;
auth.sctp_hdr = chunk->sctp_hdr;
auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk,
sizeof(sctp_chunkhdr_t));
skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t));
auth.transport = chunk->transport;
ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth);
if (ret != SCTP_IERROR_NO_ERROR) {
sctp_association_free(new_asoc);
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
}
} }
repl = sctp_make_cookie_ack(new_asoc, chunk); repl = sctp_make_cookie_ack(new_asoc, chunk);
@@ -1717,13 +1720,15 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net,
GFP_ATOMIC)) GFP_ATOMIC))
goto nomem; goto nomem;
if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
return SCTP_DISPOSITION_DISCARD;
/* Make sure no new addresses are being added during the /* Make sure no new addresses are being added during the
* restart. Though this is a pretty complicated attack * restart. Though this is a pretty complicated attack
* since you'd have to get inside the cookie. * since you'd have to get inside the cookie.
*/ */
if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) { if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands))
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
}
/* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes /* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
* the peer has restarted (Action A), it MUST NOT setup a new * the peer has restarted (Action A), it MUST NOT setup a new
@@ -1828,6 +1833,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(struct net *net,
GFP_ATOMIC)) GFP_ATOMIC))
goto nomem; goto nomem;
if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
return SCTP_DISPOSITION_DISCARD;
/* Update the content of current association. */ /* Update the content of current association. */
sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -1920,6 +1928,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net,
* a COOKIE ACK. * a COOKIE ACK.
*/ */
if (!sctp_auth_chunk_verify(net, chunk, asoc))
return SCTP_DISPOSITION_DISCARD;
/* Don't accidentally move back into established state. */ /* Don't accidentally move back into established state. */
if (asoc->state < SCTP_STATE_ESTABLISHED) { if (asoc->state < SCTP_STATE_ESTABLISHED) {
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -1959,7 +1970,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net,
} }
} }
repl = sctp_make_cookie_ack(new_asoc, chunk); repl = sctp_make_cookie_ack(asoc, chunk);
if (!repl) if (!repl)
goto nomem; goto nomem;
@@ -3981,10 +3992,8 @@ gen_shutdown:
* *
* The return value is the disposition of the chunk. * The return value is the disposition of the chunk.
*/ */
static sctp_ierror_t sctp_sf_authenticate(struct net *net, static sctp_ierror_t sctp_sf_authenticate(
const struct sctp_endpoint *ep,
const struct sctp_association *asoc, const struct sctp_association *asoc,
const sctp_subtype_t type,
struct sctp_chunk *chunk) struct sctp_chunk *chunk)
{ {
struct sctp_authhdr *auth_hdr; struct sctp_authhdr *auth_hdr;
@@ -4083,7 +4092,7 @@ sctp_disposition_t sctp_sf_eat_auth(struct net *net,
commands); commands);
auth_hdr = (struct sctp_authhdr *)chunk->skb->data; auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
error = sctp_sf_authenticate(net, ep, asoc, type, chunk); error = sctp_sf_authenticate(asoc, chunk);
switch (error) { switch (error) {
case SCTP_IERROR_AUTH_BAD_HMAC: case SCTP_IERROR_AUTH_BAD_HMAC:
/* Generate the ERROR chunk and discard the rest /* Generate the ERROR chunk and discard the rest

View File

@@ -723,7 +723,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
return event; return event;
fail_mark: fail_mark:
sctp_chunk_put(chunk);
kfree_skb(skb); kfree_skb(skb);
fail: fail:
return NULL; return NULL;

View File

@@ -1197,6 +1197,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
if (orig->aead) { if (orig->aead) {
x->aead = xfrm_algo_aead_clone(orig->aead); x->aead = xfrm_algo_aead_clone(orig->aead);
x->geniv = orig->geniv;
if (!x->aead) if (!x->aead)
goto error; goto error;
} }