diff --git a/patch/kernel/sunxi-legacy/patch-5.4.56-57.patch b/patch/kernel/sunxi-legacy/patch-5.4.56-57.patch new file mode 100644 index 000000000..44ed76b8e --- /dev/null +++ b/patch/kernel/sunxi-legacy/patch-5.4.56-57.patch @@ -0,0 +1,494 @@ +diff --git a/Makefile b/Makefile +index c33fb4eebd4d..dd753ef637fd 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 4 +-SUBLEVEL = 56 ++SUBLEVEL = 57 + EXTRAVERSION = + NAME = Kleptomaniac Octopus + +diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h +index f44f448537f2..1a3eedbac4a2 100644 +--- a/arch/arm/include/asm/percpu.h ++++ b/arch/arm/include/asm/percpu.h +@@ -5,6 +5,8 @@ + #ifndef _ASM_ARM_PERCPU_H_ + #define _ASM_ARM_PERCPU_H_ + ++#include ++ + /* + * Same as asm-generic/percpu.h, except that we store the per cpu offset + * in the TPIDRPRW. TPIDRPRW only exists on V6K and V7 +diff --git a/arch/arm64/include/asm/pointer_auth.h b/arch/arm64/include/asm/pointer_auth.h +index 7a24bad1a58b..076a4157a74f 100644 +--- a/arch/arm64/include/asm/pointer_auth.h ++++ b/arch/arm64/include/asm/pointer_auth.h +@@ -3,7 +3,6 @@ + #define __ASM_POINTER_AUTH_H + + #include +-#include + + #include + #include +@@ -30,6 +29,13 @@ struct ptrauth_keys { + struct ptrauth_key apga; + }; + ++/* ++ * Only include random.h once ptrauth_keys_* structures are defined ++ * to avoid yet another circular include hell (random.h * ends up ++ * including asm/smp.h, which requires ptrauth_keys_kernel). ++ */ ++#include ++ + static inline void ptrauth_keys_init(struct ptrauth_keys *keys) + { + if (system_supports_address_auth()) { +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 8ff28c14af7e..e877c20e0ee0 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -1330,6 +1330,7 @@ void add_interrupt_randomness(int irq, int irq_flags) + + fast_mix(fast_pool); + add_interrupt_bench(cycles); ++ this_cpu_add(net_rand_state.s1, fast_pool->pool[cycles & 3]); + + if (unlikely(crng_init == 0)) { + if ((fast_pool->count >= 64) && +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 7e0c77de551b..a284d99a1ee5 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3836,6 +3836,11 @@ static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter) + struct inode *inode = mapping->host; + size_t count = iov_iter_count(iter); + ssize_t ret; ++ loff_t offset = iocb->ki_pos; ++ loff_t size = i_size_read(inode); ++ ++ if (offset >= size) ++ return 0; + + /* + * Shared inode_lock is enough for us - it protects against concurrent +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index 3bf3835d0e86..7aa0d8b5aaf0 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -956,11 +956,14 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map) + #endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */ + + #if defined(CONFIG_BPF_STREAM_PARSER) +-int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which); ++int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, ++ struct bpf_prog *old, u32 which); + int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog); ++int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype); + #else + static inline int sock_map_prog_update(struct bpf_map *map, +- struct bpf_prog *prog, u32 which) ++ struct bpf_prog *prog, ++ struct bpf_prog *old, u32 which) + { + return -EOPNOTSUPP; + } +@@ -970,6 +973,12 @@ static inline int sock_map_get_from_fd(const union bpf_attr *attr, + { + return -EINVAL; + } ++ ++static inline int sock_map_prog_detach(const union bpf_attr *attr, ++ enum bpf_prog_type ptype) ++{ ++ return -EOPNOTSUPP; ++} + #endif + + #if defined(CONFIG_XDP_SOCKETS) +diff --git a/include/linux/prandom.h b/include/linux/prandom.h +new file mode 100644 +index 000000000000..aa16e6468f91 +--- /dev/null ++++ b/include/linux/prandom.h +@@ -0,0 +1,78 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * include/linux/prandom.h ++ * ++ * Include file for the fast pseudo-random 32-bit ++ * generation. ++ */ ++#ifndef _LINUX_PRANDOM_H ++#define _LINUX_PRANDOM_H ++ ++#include ++#include ++ ++u32 prandom_u32(void); ++void prandom_bytes(void *buf, size_t nbytes); ++void prandom_seed(u32 seed); ++void prandom_reseed_late(void); ++ ++struct rnd_state { ++ __u32 s1, s2, s3, s4; ++}; ++ ++DECLARE_PER_CPU(struct rnd_state, net_rand_state); ++ ++u32 prandom_u32_state(struct rnd_state *state); ++void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); ++void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); ++ ++#define prandom_init_once(pcpu_state) \ ++ DO_ONCE(prandom_seed_full_state, (pcpu_state)) ++ ++/** ++ * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) ++ * @ep_ro: right open interval endpoint ++ * ++ * Returns a pseudo-random number that is in interval [0, ep_ro). Note ++ * that the result depends on PRNG being well distributed in [0, ~0U] ++ * u32 space. Here we use maximally equidistributed combined Tausworthe ++ * generator, that is, prandom_u32(). This is useful when requesting a ++ * random index of an array containing ep_ro elements, for example. ++ * ++ * Returns: pseudo-random number in interval [0, ep_ro) ++ */ ++static inline u32 prandom_u32_max(u32 ep_ro) ++{ ++ return (u32)(((u64) prandom_u32() * ep_ro) >> 32); ++} ++ ++/* ++ * Handle minimum values for seeds ++ */ ++static inline u32 __seed(u32 x, u32 m) ++{ ++ return (x < m) ? x + m : x; ++} ++ ++/** ++ * prandom_seed_state - set seed for prandom_u32_state(). ++ * @state: pointer to state structure to receive the seed. ++ * @seed: arbitrary 64-bit value to use as a seed. ++ */ ++static inline void prandom_seed_state(struct rnd_state *state, u64 seed) ++{ ++ u32 i = (seed >> 32) ^ (seed << 10) ^ seed; ++ ++ state->s1 = __seed(i, 2U); ++ state->s2 = __seed(i, 8U); ++ state->s3 = __seed(i, 16U); ++ state->s4 = __seed(i, 128U); ++} ++ ++/* Pseudo random number generator from numerical recipes. */ ++static inline u32 next_pseudo_random32(u32 seed) ++{ ++ return seed * 1664525 + 1013904223; ++} ++ ++#endif +diff --git a/include/linux/random.h b/include/linux/random.h +index f189c927fdea..5b3ec7d2791f 100644 +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -108,61 +108,12 @@ declare_get_random_var_wait(long) + + unsigned long randomize_page(unsigned long start, unsigned long range); + +-u32 prandom_u32(void); +-void prandom_bytes(void *buf, size_t nbytes); +-void prandom_seed(u32 seed); +-void prandom_reseed_late(void); +- +-struct rnd_state { +- __u32 s1, s2, s3, s4; +-}; +- +-u32 prandom_u32_state(struct rnd_state *state); +-void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); +-void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); +- +-#define prandom_init_once(pcpu_state) \ +- DO_ONCE(prandom_seed_full_state, (pcpu_state)) +- +-/** +- * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) +- * @ep_ro: right open interval endpoint +- * +- * Returns a pseudo-random number that is in interval [0, ep_ro). Note +- * that the result depends on PRNG being well distributed in [0, ~0U] +- * u32 space. Here we use maximally equidistributed combined Tausworthe +- * generator, that is, prandom_u32(). This is useful when requesting a +- * random index of an array containing ep_ro elements, for example. +- * +- * Returns: pseudo-random number in interval [0, ep_ro) +- */ +-static inline u32 prandom_u32_max(u32 ep_ro) +-{ +- return (u32)(((u64) prandom_u32() * ep_ro) >> 32); +-} +- + /* +- * Handle minimum values for seeds ++ * This is designed to be standalone for just prandom ++ * users, but for now we include it from ++ * for legacy reasons. + */ +-static inline u32 __seed(u32 x, u32 m) +-{ +- return (x < m) ? x + m : x; +-} +- +-/** +- * prandom_seed_state - set seed for prandom_u32_state(). +- * @state: pointer to state structure to receive the seed. +- * @seed: arbitrary 64-bit value to use as a seed. +- */ +-static inline void prandom_seed_state(struct rnd_state *state, u64 seed) +-{ +- u32 i = (seed >> 32) ^ (seed << 10) ^ seed; +- +- state->s1 = __seed(i, 2U); +- state->s2 = __seed(i, 8U); +- state->s3 = __seed(i, 16U); +- state->s4 = __seed(i, 128U); +-} ++#include + + #ifdef CONFIG_ARCH_RANDOM + # include +@@ -193,10 +144,4 @@ static inline bool arch_has_random_seed(void) + } + #endif + +-/* Pseudo random number generator from numerical recipes. */ +-static inline u32 next_pseudo_random32(u32 seed) +-{ +- return seed * 1664525 + 1013904223; +-} +- + #endif /* _LINUX_RANDOM_H */ +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 4bdb5e4bbd6a..20f3550b0b11 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -450,6 +450,19 @@ static inline void psock_set_prog(struct bpf_prog **pprog, + bpf_prog_put(prog); + } + ++static inline int psock_replace_prog(struct bpf_prog **pprog, ++ struct bpf_prog *prog, ++ struct bpf_prog *old) ++{ ++ if (cmpxchg(pprog, old, prog) != old) ++ return -ENOENT; ++ ++ if (old) ++ bpf_prog_put(old); ++ ++ return 0; ++} ++ + static inline void psock_progs_drop(struct sk_psock_progs *progs) + { + psock_set_prog(&progs->msg_parser, NULL); +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 8bc904f9badb..bf03d04a9e2f 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -2029,10 +2029,10 @@ static int bpf_prog_detach(const union bpf_attr *attr) + ptype = BPF_PROG_TYPE_CGROUP_DEVICE; + break; + case BPF_SK_MSG_VERDICT: +- return sock_map_get_from_fd(attr, NULL); ++ return sock_map_prog_detach(attr, BPF_PROG_TYPE_SK_MSG); + case BPF_SK_SKB_STREAM_PARSER: + case BPF_SK_SKB_STREAM_VERDICT: +- return sock_map_get_from_fd(attr, NULL); ++ return sock_map_prog_detach(attr, BPF_PROG_TYPE_SK_SKB); + case BPF_LIRC_MODE2: + return lirc_prog_detach(attr); + case BPF_FLOW_DISSECTOR: +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index 1e9b81a930c0..a3ae244b1bcd 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -1742,6 +1743,13 @@ void update_process_times(int user_tick) + scheduler_tick(); + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) + run_posix_cpu_timers(); ++ ++ /* The current CPU might make use of net randoms without receiving IRQs ++ * to renew them often enough. Let's update the net_rand_state from a ++ * non-constant value that's not affine to the number of calls to make ++ * sure it's updated when there's some activity (we don't care in idle). ++ */ ++ this_cpu_add(net_rand_state.s1, rol32(jiffies, 24) + user_tick); + } + + /** +diff --git a/lib/random32.c b/lib/random32.c +index 763b920a6206..3d749abb9e80 100644 +--- a/lib/random32.c ++++ b/lib/random32.c +@@ -48,7 +48,7 @@ static inline void prandom_state_selftest(void) + } + #endif + +-static DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; ++DEFINE_PER_CPU(struct rnd_state, net_rand_state); + + /** + * prandom_u32_state - seeded pseudo-random number generator. +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index 6bbc118bf00e..df52061f99f7 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -71,7 +71,42 @@ int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog) + map = __bpf_map_get(f); + if (IS_ERR(map)) + return PTR_ERR(map); +- ret = sock_map_prog_update(map, prog, attr->attach_type); ++ ret = sock_map_prog_update(map, prog, NULL, attr->attach_type); ++ fdput(f); ++ return ret; ++} ++ ++int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype) ++{ ++ u32 ufd = attr->target_fd; ++ struct bpf_prog *prog; ++ struct bpf_map *map; ++ struct fd f; ++ int ret; ++ ++ if (attr->attach_flags) ++ return -EINVAL; ++ ++ f = fdget(ufd); ++ map = __bpf_map_get(f); ++ if (IS_ERR(map)) ++ return PTR_ERR(map); ++ ++ prog = bpf_prog_get(attr->attach_bpf_fd); ++ if (IS_ERR(prog)) { ++ ret = PTR_ERR(prog); ++ goto put_map; ++ } ++ ++ if (prog->type != ptype) { ++ ret = -EINVAL; ++ goto put_prog; ++ } ++ ++ ret = sock_map_prog_update(map, NULL, prog, attr->attach_type); ++put_prog: ++ bpf_prog_put(prog); ++put_map: + fdput(f); + return ret; + } +@@ -1015,27 +1050,32 @@ static struct sk_psock_progs *sock_map_progs(struct bpf_map *map) + } + + int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, +- u32 which) ++ struct bpf_prog *old, u32 which) + { + struct sk_psock_progs *progs = sock_map_progs(map); ++ struct bpf_prog **pprog; + + if (!progs) + return -EOPNOTSUPP; + + switch (which) { + case BPF_SK_MSG_VERDICT: +- psock_set_prog(&progs->msg_parser, prog); ++ pprog = &progs->msg_parser; + break; + case BPF_SK_SKB_STREAM_PARSER: +- psock_set_prog(&progs->skb_parser, prog); ++ pprog = &progs->skb_parser; + break; + case BPF_SK_SKB_STREAM_VERDICT: +- psock_set_prog(&progs->skb_verdict, prog); ++ pprog = &progs->skb_verdict; + break; + default: + return -EOPNOTSUPP; + } + ++ if (old) ++ return psock_replace_prog(pprog, prog, old); ++ ++ psock_set_prog(pprog, prog); + return 0; + } + +diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c +index e1f1becda529..c812f0178b64 100644 +--- a/tools/testing/selftests/bpf/test_maps.c ++++ b/tools/testing/selftests/bpf/test_maps.c +@@ -793,19 +793,19 @@ static void test_sockmap(unsigned int tasks, void *data) + } + + err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER); +- if (err) { ++ if (!err) { + printf("Failed empty parser prog detach\n"); + goto out_sockmap; + } + + err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT); +- if (err) { ++ if (!err) { + printf("Failed empty verdict prog detach\n"); + goto out_sockmap; + } + + err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT); +- if (err) { ++ if (!err) { + printf("Failed empty msg verdict prog detach\n"); + goto out_sockmap; + } +@@ -1094,19 +1094,19 @@ static void test_sockmap(unsigned int tasks, void *data) + assert(status == 0); + } + +- err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE); ++ err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE); + if (!err) { + printf("Detached an invalid prog type.\n"); + goto out_sockmap; + } + +- err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER); ++ err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER); + if (err) { + printf("Failed parser prog detach\n"); + goto out_sockmap; + } + +- err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT); ++ err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT); + if (err) { + printf("Failed parser prog detach\n"); + goto out_sockmap;