mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-05 19:31:57 -04:00
Merge remote-tracking branch 'sm8350/lineage-20' into lineage-23.2
* sm8350/lineage-20: (60 commits) dsp-kernel: Avoid overflow in ALIGN macro usage fixup! BACKPORT: treewide: Use fallthrough pseudo-keyword Revert "net, sctp, filter: remap copy_from_user failure error" UPSTREAM: bpf: Fix L4 csum update on IPv6 in CHECKSUM_COMPLETE UPSTREAM: net: Fix checksum update for ILA adj-transport UPSTREAM: lwt_bpf: Replace preempt_disable() with migrate_disable() ANDROID: add kabi padding for bpf_verifier structure UPSTREAM: net/bpfilter: Initialize pos in __bpfilter_process_sockopt UPSTREAM: bpfilter: switch bpfilter_ip_set_sockopt to sockptr_t UPSTREAM: bpfilter: reject kernel addresses UPSTREAM: net/bpfilter: split __bpfilter_process_sockopt UPSTREAM: bpfilter: fix up a sparse annotation UPSTREAM: bpfilter: Allow to build bpfilter_umh as a module without static library UPSTREAM: bpfilter: Initialize pos variable UPSTREAM: bpfilter: switch to kernel_write UPSTREAM: bpfilter: Take advantage of the facilities of struct pid UPSTREAM: bpfilter: Move bpfilter_umh back into init data UPSTREAM: bpfilter: document build requirements for bpfilter_umh UPSTREAM: bpfilter: use 'userprogs' syntax to build bpfilter_umh UPSTREAM: exit: Factor thread_group_exited out of pidfd_poll ... Change-Id: Ia34a9cf685cbded88f9b0463ca77d3cca36a2053
This commit is contained in:
commit
ee679763c2
61 changed files with 831 additions and 465 deletions
|
|
@ -9140,6 +9140,7 @@ F: include/linux/skmsg.h
|
|||
F: net/core/skmsg.c
|
||||
F: net/core/sock_map.c
|
||||
F: net/ipv4/tcp_bpf.c
|
||||
F: net/ipv4/udp_bpf.c
|
||||
|
||||
LANTIQ / INTEL Ethernet drivers
|
||||
M: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
|
|
|
|||
|
|
@ -3495,7 +3495,7 @@ static int cdrom_print_info(const char *header, int val, char *info,
|
|||
}
|
||||
|
||||
static int cdrom_sysctl_info(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int pos;
|
||||
char *info = cdrom_sysctl_settings.info;
|
||||
|
|
|
|||
|
|
@ -1477,7 +1477,7 @@ static int proc_do_uuid(struct ctl_table *table, int write, void *buf,
|
|||
}
|
||||
|
||||
/* The same as proc_dointvec, but writes don't change anything. */
|
||||
static int proc_do_rointvec(struct ctl_table *table, int write, void __user *buf,
|
||||
static int proc_do_rointvec(struct ctl_table *table, int write, void *buf,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
return write ? 0 : proc_dointvec(table, 0, buf, lenp, ppos);
|
||||
|
|
|
|||
|
|
@ -710,8 +710,12 @@ static u64 fastrpc_get_payload_size(struct fastrpc_invoke_ctx *ctx, int metalen)
|
|||
|
||||
if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1) {
|
||||
|
||||
if (ctx->olaps[oix].offset == 0)
|
||||
if (ctx->olaps[oix].offset == 0) {
|
||||
/* Check for overflow before align. */
|
||||
if (size > (ULLONG_MAX - (FASTRPC_ALIGN - 1)))
|
||||
return 0;
|
||||
size = ALIGN(size, FASTRPC_ALIGN);
|
||||
}
|
||||
|
||||
size += (ctx->olaps[oix].mend - ctx->olaps[oix].mstart);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2195,7 +2195,7 @@ static int __init start_dirtytime_writeback(void)
|
|||
__initcall(start_dirtytime_writeback);
|
||||
|
||||
int dirtytime_interval_handler(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter,
|
|||
error = -ENOMEM;
|
||||
if (count >= KMALLOC_MAX_SIZE)
|
||||
goto out;
|
||||
kbuf = kzalloc(count + 1, GFP_KERNEL);
|
||||
kbuf = kvzalloc(count + 1, GFP_KERNEL);
|
||||
if (!kbuf)
|
||||
goto out;
|
||||
|
||||
|
|
@ -633,7 +633,7 @@ static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter,
|
|||
|
||||
error = count;
|
||||
out_free_buf:
|
||||
kfree(kbuf);
|
||||
kvfree(kbuf);
|
||||
out:
|
||||
sysctl_head_finish(head);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/kallsyms.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/percpu-refcount.h>
|
||||
#include <linux/android_kabi.h>
|
||||
|
||||
struct bpf_verifier_env;
|
||||
struct bpf_verifier_log;
|
||||
|
|
@ -132,6 +133,9 @@ struct bpf_map_ops {
|
|||
|
||||
/* bpf_iter info used to open a seq_file */
|
||||
const struct bpf_iter_seq_info *iter_seq_info;
|
||||
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
ANDROID_KABI_RESERVE(2);
|
||||
};
|
||||
|
||||
struct bpf_map_memory {
|
||||
|
|
@ -218,6 +222,8 @@ struct bpf_map_dev_ops {
|
|||
int (*map_update_elem)(struct bpf_offloaded_map *map,
|
||||
void *key, void *value, u64 flags);
|
||||
int (*map_delete_elem)(struct bpf_offloaded_map *map, void *key);
|
||||
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
};
|
||||
|
||||
struct bpf_offloaded_map {
|
||||
|
|
@ -459,6 +465,7 @@ struct bpf_verifier_ops {
|
|||
const struct btf_type *t, int off, int size,
|
||||
enum bpf_access_type atype,
|
||||
u32 *next_btf_id);
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
};
|
||||
|
||||
struct bpf_prog_offload_ops {
|
||||
|
|
@ -474,6 +481,7 @@ struct bpf_prog_offload_ops {
|
|||
int (*prepare)(struct bpf_prog *prog);
|
||||
int (*translate)(struct bpf_prog *prog);
|
||||
void (*destroy)(struct bpf_prog *prog);
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
};
|
||||
|
||||
struct bpf_prog_offload {
|
||||
|
|
@ -855,6 +863,7 @@ struct bpf_prog_aux {
|
|||
struct work_struct work;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
};
|
||||
|
||||
struct bpf_array_aux {
|
||||
|
|
@ -1774,7 +1783,7 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map)
|
|||
}
|
||||
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
|
||||
|
||||
#if defined(CONFIG_BPF_STREAM_PARSER)
|
||||
#if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL)
|
||||
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);
|
||||
|
|
@ -1783,7 +1792,18 @@ int sock_map_update_elem_sys(struct bpf_map *map, void *key, void *value, u64 fl
|
|||
void sock_map_unhash(struct sock *sk);
|
||||
void sock_map_destroy(struct sock *sk);
|
||||
void sock_map_close(struct sock *sk, long timeout);
|
||||
|
||||
void bpf_sk_reuseport_detach(struct sock *sk);
|
||||
int bpf_fd_reuseport_array_lookup_elem(struct bpf_map *map, void *key,
|
||||
void *value);
|
||||
int bpf_fd_reuseport_array_update_elem(struct bpf_map *map, void *key,
|
||||
void *value, u64 map_flags);
|
||||
#else
|
||||
static inline void bpf_sk_reuseport_detach(struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
static inline int sock_map_prog_update(struct bpf_map *map,
|
||||
struct bpf_prog *prog,
|
||||
struct bpf_prog *old, u32 which)
|
||||
|
|
@ -1808,20 +1828,7 @@ static inline int sock_map_update_elem_sys(struct bpf_map *map, void *key, void
|
|||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* CONFIG_BPF_STREAM_PARSER */
|
||||
|
||||
#if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL)
|
||||
void bpf_sk_reuseport_detach(struct sock *sk);
|
||||
int bpf_fd_reuseport_array_lookup_elem(struct bpf_map *map, void *key,
|
||||
void *value);
|
||||
int bpf_fd_reuseport_array_update_elem(struct bpf_map *map, void *key,
|
||||
void *value, u64 map_flags);
|
||||
#else
|
||||
static inline void bpf_sk_reuseport_detach(struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
static inline int bpf_fd_reuseport_array_lookup_elem(struct bpf_map *map,
|
||||
void *key, void *value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -103,10 +103,6 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_HASH_OF_MAPS, htab_of_maps_map_ops)
|
|||
BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops)
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP_HASH, dev_map_hash_ops)
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_SK_STORAGE, sk_storage_map_ops)
|
||||
#if defined(CONFIG_BPF_STREAM_PARSER)
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops)
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKHASH, sock_hash_ops)
|
||||
#endif
|
||||
#ifdef CONFIG_BPF_LSM
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_INODE_STORAGE, inode_storage_map_ops)
|
||||
#endif
|
||||
|
|
@ -115,6 +111,8 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_CPUMAP, cpu_map_ops)
|
|||
BPF_MAP_TYPE(BPF_MAP_TYPE_XSKMAP, xsk_map_ops)
|
||||
#endif
|
||||
#ifdef CONFIG_INET
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops)
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKHASH, sock_hash_ops)
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, reuseport_array_ops)
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/bpf.h> /* for enum bpf_reg_type */
|
||||
#include <linux/filter.h> /* for MAX_BPF_STACK */
|
||||
#include <linux/tnum.h>
|
||||
#include <linux/android_kabi.h>
|
||||
|
||||
/* Maximum variable offset umax_value permitted when resolving memory accesses.
|
||||
* In practice this is far bigger than any realistic pointer offset; this limit
|
||||
|
|
@ -347,7 +348,7 @@ struct bpf_insn_aux_data {
|
|||
};
|
||||
u64 map_key_state; /* constant (32 bit) key tracking for maps */
|
||||
int ctx_field_size; /* the ctx field size for load insn, maybe 0 */
|
||||
u32 seen; /* this insn was processed by the verifier */
|
||||
u32 seen; /* this insn was processed by the verifier at env->pass_cnt */
|
||||
bool sanitize_stack_spill; /* subject to Spectre v4 sanitation */
|
||||
bool zext_dst; /* this insn zero extends dst reg */
|
||||
u8 alu_state; /* used in combination with alu_limit */
|
||||
|
|
@ -405,6 +406,8 @@ struct bpf_subprog_info {
|
|||
bool has_tail_call;
|
||||
bool tail_call_reachable;
|
||||
bool has_ld_abs;
|
||||
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
};
|
||||
|
||||
/* single container for all structs
|
||||
|
|
@ -462,6 +465,9 @@ struct bpf_verifier_env {
|
|||
u32 peak_states;
|
||||
/* longest register parentage chain walked for liveness marking */
|
||||
u32 longest_mark_read_walk;
|
||||
|
||||
ANDROID_KABI_RESERVE(1);
|
||||
ANDROID_KABI_RESERVE(2);
|
||||
};
|
||||
|
||||
__printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,
|
||||
|
|
|
|||
|
|
@ -4,21 +4,22 @@
|
|||
|
||||
#include <uapi/linux/bpfilter.h>
|
||||
#include <linux/usermode_driver.h>
|
||||
#include <linux/sockptr.h>
|
||||
|
||||
struct sock;
|
||||
int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
|
||||
int bpfilter_ip_set_sockopt(struct sock *sk, int optname, sockptr_t optval,
|
||||
unsigned int optlen);
|
||||
int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
|
||||
int __user *optlen);
|
||||
void bpfilter_umh_cleanup(struct umd_info *info);
|
||||
|
||||
struct bpfilter_umh_ops {
|
||||
struct umd_info info;
|
||||
/* since ip_getsockopt() can run in parallel, serialize access to umh */
|
||||
struct mutex lock;
|
||||
int (*sockopt)(struct sock *sk, int optname,
|
||||
char __user *optval,
|
||||
int (*sockopt)(struct sock *sk, int optname, sockptr_t optval,
|
||||
unsigned int optlen, bool is_set);
|
||||
int (*start)(void);
|
||||
bool stop;
|
||||
};
|
||||
extern struct bpfilter_umh_ops bpfilter_ops;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -81,8 +81,7 @@ static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *val
|
|||
extern int ftrace_enabled;
|
||||
extern int
|
||||
ftrace_enable_sysctl(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos);
|
||||
void *buffer, size_t *lenp, loff_t *ppos);
|
||||
|
||||
struct ftrace_ops;
|
||||
|
||||
|
|
@ -281,9 +280,8 @@ static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs,
|
|||
|
||||
extern int stack_tracer_enabled;
|
||||
|
||||
int stack_trace_sysctl(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos);
|
||||
int stack_trace_sysctl(struct ctl_table *table, int write, void *buffer,
|
||||
size_t *lenp, loff_t *ppos);
|
||||
|
||||
/* DO NOT MODIFY THIS VARIABLE DIRECTLY! */
|
||||
DECLARE_PER_CPU(int, disable_stack_tracer);
|
||||
|
|
|
|||
|
|
@ -691,6 +691,8 @@ static inline int thread_group_empty(struct task_struct *p)
|
|||
extern struct sighand_struct *__lock_task_sighand(struct task_struct *task,
|
||||
unsigned long *flags);
|
||||
|
||||
extern bool thread_group_exited(struct pid *pid);
|
||||
|
||||
static inline struct sighand_struct *lock_task_sighand(struct task_struct *task,
|
||||
unsigned long *flags)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ enum lockdown_reason {
|
|||
LOCKDOWN_MMIOTRACE,
|
||||
LOCKDOWN_DEBUGFS,
|
||||
LOCKDOWN_XMON_WR,
|
||||
LOCKDOWN_BPF_WRITE_USER,
|
||||
LOCKDOWN_DBG_WRITE_KERNEL,
|
||||
LOCKDOWN_INTEGRITY_MAX,
|
||||
LOCKDOWN_KCORE,
|
||||
|
|
|
|||
|
|
@ -71,7 +71,9 @@ struct sk_psock_link {
|
|||
};
|
||||
|
||||
struct sk_psock_parser {
|
||||
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
||||
struct strparser strp;
|
||||
#endif
|
||||
bool enabled;
|
||||
void (*saved_data_ready)(struct sock *sk);
|
||||
};
|
||||
|
|
@ -306,9 +308,27 @@ static inline void sk_psock_report_error(struct sk_psock *psock, int err)
|
|||
|
||||
struct sk_psock *sk_psock_init(struct sock *sk, int node);
|
||||
|
||||
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
||||
int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock);
|
||||
void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock);
|
||||
void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock);
|
||||
#else
|
||||
static inline int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock);
|
||||
void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock);
|
||||
|
||||
int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock,
|
||||
struct sk_msg *msg);
|
||||
|
|
@ -341,23 +361,6 @@ static inline void sk_psock_update_proto(struct sock *sk,
|
|||
struct sk_psock *psock,
|
||||
struct proto *ops)
|
||||
{
|
||||
/* Initialize saved callbacks and original proto only once, since this
|
||||
* function may be called multiple times for a psock, e.g. when
|
||||
* psock->progs.msg_parser is updated.
|
||||
*
|
||||
* Since we've not installed the new proto, psock is not yet in use and
|
||||
* we can initialize it without synchronization.
|
||||
*/
|
||||
if (!psock->sk_proto) {
|
||||
struct proto *orig = READ_ONCE(sk->sk_prot);
|
||||
|
||||
psock->saved_unhash = orig->unhash;
|
||||
psock->saved_close = orig->close;
|
||||
psock->saved_write_space = sk->sk_write_space;
|
||||
|
||||
psock->sk_proto = orig;
|
||||
}
|
||||
|
||||
/* Pairs with lockless read in sk_clone_lock() */
|
||||
WRITE_ONCE(sk->sk_prot, ops);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ static inline void stackleak_task_init(struct task_struct *t)
|
|||
|
||||
#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
|
||||
int stack_erasing_sysctl(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
void *buffer, size_t *lenp, loff_t *ppos);
|
||||
#endif
|
||||
|
||||
#else /* !CONFIG_GCC_PLUGIN_STACKLEAK */
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
|||
const __be32 *from, const __be32 *to,
|
||||
bool pseudohdr);
|
||||
void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
|
||||
__wsum diff, bool pseudohdr);
|
||||
__wsum diff, bool pseudohdr, bool ipv6);
|
||||
|
||||
static __always_inline
|
||||
void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
|
||||
|
|
|
|||
|
|
@ -359,4 +359,9 @@ static inline void inet_csk_inc_pingpong_cnt(struct sock *sk)
|
|||
if (icsk->icsk_ack.pingpong < U8_MAX)
|
||||
icsk->icsk_ack.pingpong++;
|
||||
}
|
||||
|
||||
static inline bool inet_csk_has_ulp(struct sock *sk)
|
||||
{
|
||||
return inet_sk(sk)->is_icsk && !!inet_csk(sk)->icsk_ulp_ops;
|
||||
}
|
||||
#endif /* _INET_CONNECTION_SOCK_H */
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ int igmp6_event_report(struct sk_buff *skb);
|
|||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
void *buffer, size_t *lenp, loff_t *ppos);
|
||||
int ndisc_ifinfo_sysctl_strategy(struct ctl_table *ctl,
|
||||
void __user *oldval, size_t __user *oldlenp,
|
||||
void __user *newval, size_t newlen);
|
||||
|
|
|
|||
|
|
@ -387,13 +387,12 @@ void *neigh_seq_next(struct seq_file *, void *, loff_t *);
|
|||
void neigh_seq_stop(struct seq_file *, void *);
|
||||
|
||||
int neigh_proc_dointvec(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
void *buffer, size_t *lenp, loff_t *ppos);
|
||||
int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
|
||||
void __user *buffer,
|
||||
void *buffer,
|
||||
size_t *lenp, loff_t *ppos);
|
||||
int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
|
||||
void __user *buffer,
|
||||
size_t *lenp, loff_t *ppos);
|
||||
void *buffer, size_t *lenp, loff_t *ppos);
|
||||
|
||||
int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
|
||||
proc_handler *proc_handler);
|
||||
|
|
|
|||
|
|
@ -2243,27 +2243,27 @@ void tcp_update_ulp(struct sock *sk, struct proto *p,
|
|||
__MODULE_INFO(alias, alias_userspace, name); \
|
||||
__MODULE_INFO(alias, alias_tcp_ulp, "tcp-ulp-" name)
|
||||
|
||||
#ifdef CONFIG_NET_SOCK_MSG
|
||||
struct sk_msg;
|
||||
struct sk_psock;
|
||||
|
||||
#ifdef CONFIG_BPF_STREAM_PARSER
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
struct proto *tcp_bpf_get_proto(struct sock *sk, struct sk_psock *psock);
|
||||
void tcp_bpf_clone(const struct sock *sk, struct sock *newsk);
|
||||
#else
|
||||
static inline void tcp_bpf_clone(const struct sock *sk, struct sock *newsk)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_BPF_STREAM_PARSER */
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
|
||||
#ifdef CONFIG_NET_SOCK_MSG
|
||||
int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, u32 bytes,
|
||||
int flags);
|
||||
int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
int nonblock, int flags, int *addr_len);
|
||||
int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock,
|
||||
struct msghdr *msg, int len, int flags);
|
||||
#endif /* CONFIG_NET_SOCK_MSG */
|
||||
|
||||
#if !defined(CONFIG_BPF_SYSCALL) || !defined(CONFIG_NET_SOCK_MSG)
|
||||
static inline void tcp_bpf_clone(const struct sock *sk, struct sock *newsk)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CGROUP_BPF
|
||||
/* Copy the listen sk's HDR_OPT_CB flags to its child.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -519,4 +519,9 @@ drop:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
struct sk_psock;
|
||||
struct proto *udp_bpf_get_proto(struct sock *sk, struct sk_psock *psock);
|
||||
#endif
|
||||
|
||||
#endif /* _UDP_H */
|
||||
|
|
|
|||
|
|
@ -909,6 +909,7 @@ union bpf_attr {
|
|||
* for updates resulting in a null checksum the value is set to
|
||||
* **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
|
||||
* the checksum is to be computed against a pseudo-header.
|
||||
* Flag **BPF_F_IPV6** should be set for IPv6 packets.
|
||||
*
|
||||
* This helper works in combination with **bpf_csum_diff**\ (),
|
||||
* which does not update the checksum in-place, but offers more
|
||||
|
|
@ -3945,6 +3946,7 @@ enum {
|
|||
BPF_F_PSEUDO_HDR = (1ULL << 4),
|
||||
BPF_F_MARK_MANGLED_0 = (1ULL << 5),
|
||||
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
||||
BPF_F_IPV6 = (1ULL << 7),
|
||||
};
|
||||
|
||||
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
||||
|
|
|
|||
|
|
@ -1686,6 +1686,7 @@ config BPF_SYSCALL
|
|||
select BPF
|
||||
select IRQ_WORK
|
||||
select TASKS_TRACE_RCU
|
||||
select NET_SOCK_MSG if INET
|
||||
default n
|
||||
help
|
||||
Enable the bpf() system call that allows to manipulate eBPF
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
|
|||
}
|
||||
|
||||
static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret, semmni;
|
||||
struct ipc_namespace *ns = current->nsproxy->ipc_ns;
|
||||
|
|
|
|||
|
|
@ -1777,6 +1777,30 @@ Efault:
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* thread_group_exited - check that a thread group has exited
|
||||
* @pid: tgid of thread group to be checked.
|
||||
*
|
||||
* Test if the thread group represented by tgid has exited (all
|
||||
* threads are zombies, dead or completely gone).
|
||||
*
|
||||
* Return: true if the thread group has exited. false otherwise.
|
||||
*/
|
||||
bool thread_group_exited(struct pid *pid)
|
||||
{
|
||||
struct task_struct *task;
|
||||
bool exited;
|
||||
|
||||
rcu_read_lock();
|
||||
task = pid_task(pid, PIDTYPE_PID);
|
||||
exited = !task ||
|
||||
(READ_ONCE(task->exit_state) && thread_group_empty(task));
|
||||
rcu_read_unlock();
|
||||
|
||||
return exited;
|
||||
}
|
||||
EXPORT_SYMBOL(thread_group_exited);
|
||||
|
||||
__weak void abort(void)
|
||||
{
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -1744,22 +1744,18 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f)
|
|||
*/
|
||||
static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts)
|
||||
{
|
||||
struct task_struct *task;
|
||||
struct pid *pid = file->private_data;
|
||||
__poll_t poll_flags = 0;
|
||||
|
||||
poll_wait(file, &pid->wait_pidfd, pts);
|
||||
|
||||
rcu_read_lock();
|
||||
task = pid_task(pid, PIDTYPE_PID);
|
||||
/*
|
||||
* Inform pollers only when the whole thread group exits.
|
||||
* If the thread group leader exits before all other threads in the
|
||||
* group, then poll(2) should block, similar to the wait(2) family.
|
||||
*/
|
||||
if (!task || (task->exit_state && thread_group_empty(task)))
|
||||
if (thread_group_exited(pid))
|
||||
poll_flags = EPOLLIN | EPOLLRDNORM;
|
||||
rcu_read_unlock();
|
||||
|
||||
return poll_flags;
|
||||
}
|
||||
|
|
@ -3090,7 +3086,7 @@ int unshare_files(struct files_struct **displaced)
|
|||
}
|
||||
|
||||
int sysctl_max_threads(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct ctl_table t;
|
||||
int ret;
|
||||
|
|
|
|||
|
|
@ -231,8 +231,7 @@ static long hung_timeout_jiffies(unsigned long last_checked,
|
|||
* Process updating of timeout sysctl
|
||||
*/
|
||||
int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
|
||||
void __user *buffer,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -1720,7 +1720,7 @@ static bool seccomp_actions_logged_from_names(u32 *actions_logged, char *names)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int read_actions_logged(struct ctl_table *ro_table, void __user *buffer,
|
||||
static int read_actions_logged(struct ctl_table *ro_table, void *buffer,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
char names[sizeof(seccomp_actions_avail)];
|
||||
|
|
@ -1738,7 +1738,7 @@ static int read_actions_logged(struct ctl_table *ro_table, void __user *buffer,
|
|||
return proc_dostring(&table, 0, buffer, lenp, ppos);
|
||||
}
|
||||
|
||||
static int write_actions_logged(struct ctl_table *ro_table, void __user *buffer,
|
||||
static int write_actions_logged(struct ctl_table *ro_table, void *buffer,
|
||||
size_t *lenp, loff_t *ppos, u32 *actions_logged)
|
||||
{
|
||||
char names[sizeof(seccomp_actions_avail)];
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
static DEFINE_STATIC_KEY_FALSE(stack_erasing_bypass);
|
||||
|
||||
int stack_erasing_sysctl(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret = 0;
|
||||
int state = !static_branch_unlikely(&stack_erasing_bypass);
|
||||
|
|
|
|||
|
|
@ -375,8 +375,7 @@ static int max_extfrag_threshold = 1000;
|
|||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
static int bpf_stats_handler(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct static_key *key = (struct static_key *)table->data;
|
||||
static int saved_val;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ ifdef CONFIG_GCOV_PROFILE_FTRACE
|
|||
GCOV_PROFILE := y
|
||||
endif
|
||||
|
||||
CFLAGS_bpf_trace.o := -I$(src)
|
||||
|
||||
CFLAGS_trace_benchmark.o := -I$(src)
|
||||
CFLAGS_trace_events_filter.o := -I$(src)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/error-injection.h>
|
||||
#include <linux/btf_ids.h>
|
||||
|
|
@ -24,6 +25,9 @@
|
|||
#include "trace_probe.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "bpf_trace.h"
|
||||
|
||||
#define bpf_event_rcu_dereference(p) \
|
||||
rcu_dereference_protected(p, lockdep_is_held(&bpf_event_mutex))
|
||||
|
||||
|
|
@ -89,10 +93,7 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
|
|||
{
|
||||
unsigned int ret;
|
||||
|
||||
if (in_nmi()) /* not supported yet */
|
||||
return 1;
|
||||
|
||||
preempt_disable();
|
||||
cant_sleep();
|
||||
|
||||
if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1)) {
|
||||
/*
|
||||
|
|
@ -124,7 +125,6 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
|
|||
|
||||
out:
|
||||
__this_cpu_dec(bpf_prog_active);
|
||||
preempt_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -178,6 +178,16 @@ bpf_probe_read_user_str_common(void *dst, u32 size,
|
|||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* NB: We rely on strncpy_from_user() not copying junk past the NUL
|
||||
* terminator into `dst`.
|
||||
*
|
||||
* strncpy_from_user() does long-sized strides in the fast path. If the
|
||||
* strncpy does not mask out the bytes after the NUL in `unsafe_ptr`,
|
||||
* then there could be junk after the NUL in `dst`. If user takes `dst`
|
||||
* and keys a hash map with it, then semantically identical strings can
|
||||
* occupy multiple entries in the map.
|
||||
*/
|
||||
ret = strncpy_from_user_nofault(dst, unsafe_ptr, size);
|
||||
if (unlikely(ret < 0))
|
||||
memset(dst, 0, size);
|
||||
|
|
@ -384,9 +394,33 @@ static void bpf_trace_copy_string(char *buf, void *unsafe_ptr, char fmt_ptype,
|
|||
}
|
||||
}
|
||||
|
||||
static DEFINE_RAW_SPINLOCK(trace_printk_lock);
|
||||
|
||||
#define BPF_TRACE_PRINTK_SIZE 1024
|
||||
|
||||
static __printf(1, 0) int bpf_do_trace_printk(const char *fmt, ...)
|
||||
{
|
||||
static char buf[BPF_TRACE_PRINTK_SIZE];
|
||||
unsigned long flags;
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
raw_spin_lock_irqsave(&trace_printk_lock, flags);
|
||||
va_start(ap, fmt);
|
||||
ret = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
/* vsnprintf() will not append null for zero-length strings */
|
||||
if (ret == 0)
|
||||
buf[0] = '\0';
|
||||
trace_bpf_trace_printk(buf);
|
||||
raw_spin_unlock_irqrestore(&trace_printk_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only limited trace_printk() conversion specifiers allowed:
|
||||
* %d %i %u %x %ld %li %lu %lx %lld %lli %llu %llx %p %pks %pus %s
|
||||
* %d %i %u %x %ld %li %lu %lx %lld %lli %llu %llx %p %pB %pks %pus %s
|
||||
*/
|
||||
BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
|
||||
u64, arg2, u64, arg3)
|
||||
|
|
@ -430,6 +464,11 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
|
|||
goto fmt_str;
|
||||
}
|
||||
|
||||
if (fmt[i + 1] == 'B') {
|
||||
i++;
|
||||
goto fmt_next;
|
||||
}
|
||||
|
||||
/* disallow any further format extensions */
|
||||
if (fmt[i + 1] != 0 &&
|
||||
!isspace(fmt[i + 1]) &&
|
||||
|
|
@ -488,8 +527,7 @@ fmt_next:
|
|||
*/
|
||||
#define __BPF_TP_EMIT() __BPF_ARG3_TP()
|
||||
#define __BPF_TP(...) \
|
||||
__trace_printk(0 /* Fake ip */, \
|
||||
fmt, ##__VA_ARGS__)
|
||||
bpf_do_trace_printk(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define __BPF_ARG1_TP(...) \
|
||||
((mod[0] == 2 || (mod[0] == 1 && __BITS_PER_LONG == 64)) \
|
||||
|
|
@ -526,10 +564,15 @@ static const struct bpf_func_proto bpf_trace_printk_proto = {
|
|||
const struct bpf_func_proto *bpf_get_trace_printk_proto(void)
|
||||
{
|
||||
/*
|
||||
* this program might be calling bpf_trace_printk,
|
||||
* so allocate per-cpu printk buffers
|
||||
* This program might be calling bpf_trace_printk,
|
||||
* so enable the associated bpf_trace/bpf_trace_printk event.
|
||||
* Repeat this each time as it is possible a user has
|
||||
* disabled bpf_trace_printk events. By loading a program
|
||||
* calling bpf_trace_printk() however the user has expressed
|
||||
* the intent to see such events.
|
||||
*/
|
||||
trace_printk_init_buffers();
|
||||
if (trace_set_clr_event("bpf_trace", "bpf_trace_printk", 1))
|
||||
pr_warn_ratelimited("could not enable bpf_trace_printk events");
|
||||
|
||||
return &bpf_trace_printk_proto;
|
||||
}
|
||||
|
|
@ -646,7 +689,8 @@ BPF_CALL_5(bpf_seq_printf, struct seq_file *, m, char *, fmt, u32, fmt_size,
|
|||
if (fmt[i] == 'p') {
|
||||
if (fmt[i + 1] == 0 ||
|
||||
fmt[i + 1] == 'K' ||
|
||||
fmt[i + 1] == 'x') {
|
||||
fmt[i + 1] == 'x' ||
|
||||
fmt[i + 1] == 'B') {
|
||||
/* just kernel pointers */
|
||||
params[fmt_cnt] = args[fmt_cnt];
|
||||
fmt_cnt++;
|
||||
|
|
@ -691,7 +735,8 @@ BPF_CALL_5(bpf_seq_printf, struct seq_file *, m, char *, fmt, u32, fmt_size,
|
|||
}
|
||||
|
||||
if (fmt[i] != 'i' && fmt[i] != 'd' &&
|
||||
fmt[i] != 'u' && fmt[i] != 'x') {
|
||||
fmt[i] != 'u' && fmt[i] != 'x' &&
|
||||
fmt[i] != 'X') {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -937,7 +982,6 @@ static DEFINE_PER_CPU(struct bpf_trace_sample_data, bpf_misc_sds);
|
|||
u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
|
||||
void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy)
|
||||
{
|
||||
int nest_level = this_cpu_inc_return(bpf_event_output_nest_level);
|
||||
struct perf_raw_frag frag = {
|
||||
.copy = ctx_copy,
|
||||
.size = ctx_size,
|
||||
|
|
@ -954,8 +998,12 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
|
|||
};
|
||||
struct perf_sample_data *sd;
|
||||
struct pt_regs *regs;
|
||||
int nest_level;
|
||||
u64 ret;
|
||||
|
||||
preempt_disable();
|
||||
nest_level = this_cpu_inc_return(bpf_event_output_nest_level);
|
||||
|
||||
if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(bpf_misc_sds.sds))) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
|
|
@ -970,6 +1018,7 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
|
|||
ret = __bpf_perf_event_output(regs, map, flags, sd);
|
||||
out:
|
||||
this_cpu_dec(bpf_event_output_nest_level);
|
||||
preempt_enable();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1022,6 +1071,7 @@ static void do_bpf_send_signal(struct irq_work *entry)
|
|||
|
||||
work = container_of(entry, struct send_signal_irq_work, irq_work);
|
||||
group_send_sig_info(work->sig, SEND_SIG_PRIV, work->task, work->type);
|
||||
put_task_struct(work->task);
|
||||
}
|
||||
|
||||
static int bpf_send_signal_common(u32 sig, enum pid_type type)
|
||||
|
|
@ -1058,7 +1108,7 @@ static int bpf_send_signal_common(u32 sig, enum pid_type type)
|
|||
* to the irq_work. The current task may change when queued
|
||||
* irq works get executed.
|
||||
*/
|
||||
work->task = current;
|
||||
work->task = get_task_struct(current);
|
||||
work->sig = sig;
|
||||
work->type = type;
|
||||
irq_work_queue(&work->irq_work);
|
||||
|
|
@ -1094,13 +1144,23 @@ static const struct bpf_func_proto bpf_send_signal_thread_proto = {
|
|||
|
||||
BPF_CALL_3(bpf_d_path, struct path *, path, char *, buf, u32, sz)
|
||||
{
|
||||
struct path copy;
|
||||
long len;
|
||||
char *p;
|
||||
|
||||
if (!sz)
|
||||
return 0;
|
||||
|
||||
p = d_path(path, buf, sz);
|
||||
/*
|
||||
* The path pointer is verified as trusted and safe to use,
|
||||
* but let's double check it's valid anyway to workaround
|
||||
* potentially broken verifier.
|
||||
*/
|
||||
len = copy_from_kernel_nofault(©, path, sizeof(*path));
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
p = d_path(©, buf, sz);
|
||||
if (IS_ERR(p)) {
|
||||
len = PTR_ERR(p);
|
||||
} else {
|
||||
|
|
@ -1163,7 +1223,7 @@ static int bpf_btf_printf_prepare(struct btf_ptr *ptr, u32 btf_ptr_size,
|
|||
*btf = bpf_get_btf_vmlinux();
|
||||
|
||||
if (IS_ERR_OR_NULL(*btf))
|
||||
return PTR_ERR(*btf);
|
||||
return IS_ERR(*btf) ? PTR_ERR(*btf) : -EINVAL;
|
||||
|
||||
if (ptr->type_id > 0)
|
||||
*btf_id = ptr->type_id;
|
||||
|
|
@ -1242,12 +1302,13 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|||
return &bpf_get_numa_node_id_proto;
|
||||
case BPF_FUNC_perf_event_read:
|
||||
return &bpf_perf_event_read_proto;
|
||||
case BPF_FUNC_probe_write_user:
|
||||
return bpf_get_probe_write_proto();
|
||||
case BPF_FUNC_current_task_under_cgroup:
|
||||
return &bpf_current_task_under_cgroup_proto;
|
||||
case BPF_FUNC_get_prandom_u32:
|
||||
return &bpf_get_prandom_u32_proto;
|
||||
case BPF_FUNC_probe_write_user:
|
||||
return security_locked_down(LOCKDOWN_BPF_WRITE_USER) < 0 ?
|
||||
NULL : bpf_get_probe_write_proto();
|
||||
case BPF_FUNC_probe_read_user:
|
||||
return &bpf_probe_read_user_proto;
|
||||
case BPF_FUNC_probe_read_kernel:
|
||||
|
|
@ -1482,9 +1543,6 @@ static const struct bpf_func_proto bpf_perf_prog_read_value_proto = {
|
|||
BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx,
|
||||
void *, buf, u32, size, u64, flags)
|
||||
{
|
||||
#ifndef CONFIG_X86
|
||||
return -ENOENT;
|
||||
#else
|
||||
static const u32 br_entry_size = sizeof(struct perf_branch_entry);
|
||||
struct perf_branch_stack *br_stack = ctx->data->br_stack;
|
||||
u32 to_copy;
|
||||
|
|
@ -1493,7 +1551,7 @@ BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx,
|
|||
return -EINVAL;
|
||||
|
||||
if (unlikely(!br_stack))
|
||||
return -EINVAL;
|
||||
return -ENOENT;
|
||||
|
||||
if (flags & BPF_F_GET_BRANCH_RECORDS_SIZE)
|
||||
return br_stack->nr * br_entry_size;
|
||||
|
|
@ -1505,7 +1563,6 @@ BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx,
|
|||
memcpy(buf, br_stack->entries, to_copy);
|
||||
|
||||
return to_copy;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_read_branch_records_proto = {
|
||||
|
|
@ -1732,13 +1789,22 @@ static bool tracing_prog_is_valid_access(int off, int size,
|
|||
return btf_ctx_access(off, size, type, prog, info);
|
||||
}
|
||||
|
||||
int __weak bpf_prog_test_run_tracing(struct bpf_prog *prog,
|
||||
const union bpf_attr *kattr,
|
||||
union bpf_attr __user *uattr)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
const struct bpf_verifier_ops raw_tracepoint_verifier_ops = {
|
||||
.get_func_proto = raw_tp_prog_func_proto,
|
||||
.is_valid_access = raw_tp_prog_is_valid_access,
|
||||
};
|
||||
|
||||
const struct bpf_prog_ops raw_tracepoint_prog_ops = {
|
||||
#ifdef CONFIG_NET
|
||||
.test_run = bpf_prog_test_run_raw_tp,
|
||||
#endif
|
||||
};
|
||||
|
||||
const struct bpf_verifier_ops tracing_verifier_ops = {
|
||||
|
|
|
|||
34
kernel/trace/bpf_trace.h
Normal file
34
kernel/trace/bpf_trace.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM bpf_trace
|
||||
|
||||
#if !defined(_TRACE_BPF_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
|
||||
#define _TRACE_BPF_TRACE_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
TRACE_EVENT(bpf_trace_printk,
|
||||
|
||||
TP_PROTO(const char *bpf_string),
|
||||
|
||||
TP_ARGS(bpf_string),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(bpf_string, bpf_string)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(bpf_string, bpf_string);
|
||||
),
|
||||
|
||||
TP_printk("%s", __get_str(bpf_string))
|
||||
);
|
||||
|
||||
#endif /* _TRACE_BPF_TRACE_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#define TRACE_INCLUDE_FILE bpf_trace
|
||||
|
||||
#include <trace/define_trace.h>
|
||||
|
|
@ -7212,8 +7212,7 @@ static bool is_permanent_ops_registered(void)
|
|||
|
||||
int
|
||||
ftrace_enable_sysctl(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
|
||||
|
|
|
|||
|
|
@ -515,9 +515,8 @@ static const struct file_operations stack_trace_filter_fops = {
|
|||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
int
|
||||
stack_trace_sysctl(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
stack_trace_sysctl(struct ctl_table *table, int write, void *buffer,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int was_enabled;
|
||||
int ret;
|
||||
|
|
|
|||
|
|
@ -34,17 +34,32 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src,
|
|||
goto byte_at_a_time;
|
||||
|
||||
while (max >= sizeof(unsigned long)) {
|
||||
unsigned long c, data;
|
||||
unsigned long c, data, mask;
|
||||
|
||||
/* Fall back to byte-at-a-time if we get a page fault */
|
||||
unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time);
|
||||
|
||||
*(unsigned long *)(dst+res) = c;
|
||||
/*
|
||||
* Note that we mask out the bytes following the NUL. This is
|
||||
* important to do because string oblivious code may read past
|
||||
* the NUL. For those routines, we don't want to give them
|
||||
* potentially random bytes after the NUL in `src`.
|
||||
*
|
||||
* One example of such code is BPF map keys. BPF treats map keys
|
||||
* as an opaque set of bytes. Without the post-NUL mask, any BPF
|
||||
* maps keyed by strings returned from strncpy_from_user() may
|
||||
* have multiple entries for semantically identical strings.
|
||||
*/
|
||||
if (has_zero(c, &data, &constants)) {
|
||||
data = prep_zero_mask(c, data, &constants);
|
||||
data = create_zero_mask(data);
|
||||
mask = zero_bytemask(data);
|
||||
*(unsigned long *)(dst+res) = c & mask;
|
||||
return res + find_zero(data);
|
||||
}
|
||||
|
||||
*(unsigned long *)(dst+res) = c;
|
||||
|
||||
res += sizeof(unsigned long);
|
||||
max -= sizeof(unsigned long);
|
||||
}
|
||||
|
|
|
|||
24
net/Kconfig
24
net/Kconfig
|
|
@ -258,7 +258,7 @@ config XPS
|
|||
default y
|
||||
|
||||
config HWBM
|
||||
bool
|
||||
bool
|
||||
|
||||
config CGROUP_NET_PRIO
|
||||
bool "Network priority cgroup"
|
||||
|
|
@ -309,12 +309,8 @@ config BPF_STREAM_PARSER
|
|||
select STREAM_PARSER
|
||||
select NET_SOCK_MSG
|
||||
---help---
|
||||
Enabling this allows a stream parser to be used with
|
||||
BPF_MAP_TYPE_SOCKMAP.
|
||||
|
||||
BPF_MAP_TYPE_SOCKMAP provides a map type to use with network sockets.
|
||||
It can be used to enforce socket policy, implement socket redirects,
|
||||
etc.
|
||||
Enabling this allows a stream parser to be used with
|
||||
BPF_MAP_TYPE_SOCKMAP.
|
||||
|
||||
config NET_FLOW_LIMIT
|
||||
bool
|
||||
|
|
@ -349,12 +345,12 @@ config NET_DROP_MONITOR
|
|||
tristate "Network packet drop alerting service"
|
||||
depends on INET && TRACEPOINTS
|
||||
---help---
|
||||
This feature provides an alerting service to userspace in the
|
||||
event that packets are discarded in the network stack. Alerts
|
||||
are broadcast via netlink socket to any listening user space
|
||||
process. If you don't need network drop alerts, or if you are ok
|
||||
just checking the various proc files and other utilities for
|
||||
drop statistics, say N here.
|
||||
This feature provides an alerting service to userspace in the
|
||||
event that packets are discarded in the network stack. Alerts
|
||||
are broadcast via netlink socket to any listening user space
|
||||
process. If you don't need network drop alerts, or if you are ok
|
||||
just checking the various proc files and other utilities for
|
||||
drop statistics, say N here.
|
||||
|
||||
endmenu
|
||||
|
||||
|
|
@ -434,7 +430,7 @@ config NET_DEVLINK
|
|||
imply NET_DROP_MONITOR
|
||||
|
||||
config PAGE_POOL
|
||||
bool
|
||||
bool
|
||||
|
||||
config FAILOVER
|
||||
tristate "Generic failover module"
|
||||
|
|
|
|||
|
|
@ -10,8 +10,14 @@ menuconfig BPFILTER
|
|||
if BPFILTER
|
||||
config BPFILTER_UMH
|
||||
tristate "bpfilter kernel module with user mode helper"
|
||||
depends on CC_CAN_LINK_STATIC
|
||||
depends on CC_CAN_LINK
|
||||
depends on m || CC_CAN_LINK_STATIC
|
||||
default m
|
||||
help
|
||||
This builds bpfilter kernel module with embedded user mode helper
|
||||
|
||||
Note: To compile this as built-in, your toolchain must support
|
||||
building static binaries, since rootfs isn't mounted at the time
|
||||
when __init functions are called and do_execv won't be able to find
|
||||
the elf interpreter.
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -3,17 +3,15 @@
|
|||
# Makefile for the Linux BPFILTER layer.
|
||||
#
|
||||
|
||||
hostprogs-y := bpfilter_umh
|
||||
userprogs := bpfilter_umh
|
||||
bpfilter_umh-objs := main.o
|
||||
KBUILD_HOSTCFLAGS += -I $(srctree)/tools/include/ -I $(srctree)/tools/include/uapi \
|
||||
$(filter -m32 -m64, $(KBUILD_CFLAGS))
|
||||
HOSTCC := $(CC)
|
||||
userccflags += -I $(srctree)/tools/include/ -I $(srctree)/tools/include/uapi
|
||||
|
||||
ifeq ($(CONFIG_BPFILTER_UMH), y)
|
||||
# builtin bpfilter_umh should be compiled with -static
|
||||
# builtin bpfilter_umh should be linked with -static
|
||||
# since rootfs isn't mounted at the time of __init
|
||||
# function is called and do_execv won't find elf interpreter
|
||||
KBUILD_HOSTLDFLAGS += -static $(filter -m32 -m64, $(KBUILD_CFLAGS))
|
||||
userldflags += -static
|
||||
endif
|
||||
|
||||
$(obj)/bpfilter_umh_blob.o: $(obj)/bpfilter_umh
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@ static void shutdown_umh(void)
|
|||
struct umd_info *info = &bpfilter_ops.info;
|
||||
struct pid *tgid = info->tgid;
|
||||
|
||||
if (bpfilter_ops.stop)
|
||||
return;
|
||||
|
||||
kill_pid(tgid, SIGKILL, 1);
|
||||
if (tgid) {
|
||||
kill_pid(tgid, SIGKILL, 1);
|
||||
wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
|
||||
bpfilter_umh_cleanup(info);
|
||||
}
|
||||
}
|
||||
|
||||
static void __stop_umh(void)
|
||||
|
|
@ -30,58 +31,65 @@ static void __stop_umh(void)
|
|||
shutdown_umh();
|
||||
}
|
||||
|
||||
static int __bpfilter_process_sockopt(struct sock *sk, int optname,
|
||||
char __user *optval,
|
||||
unsigned int optlen, bool is_set)
|
||||
static int bpfilter_send_req(struct mbox_request *req)
|
||||
{
|
||||
struct mbox_request req;
|
||||
struct mbox_reply reply;
|
||||
loff_t pos;
|
||||
loff_t pos = 0;
|
||||
ssize_t n;
|
||||
int ret = -EFAULT;
|
||||
|
||||
req.is_set = is_set;
|
||||
req.pid = current->pid;
|
||||
req.cmd = optname;
|
||||
req.addr = (long __force __user)optval;
|
||||
req.len = optlen;
|
||||
if (!bpfilter_ops.info.tgid)
|
||||
goto out;
|
||||
n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
|
||||
return -EFAULT;
|
||||
pos = 0;
|
||||
n = kernel_write(bpfilter_ops.info.pipe_to_umh, req, sizeof(*req),
|
||||
&pos);
|
||||
if (n != sizeof(req)) {
|
||||
if (n != sizeof(*req)) {
|
||||
pr_err("write fail %zd\n", n);
|
||||
__stop_umh();
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
goto stop;
|
||||
}
|
||||
pos = 0;
|
||||
n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply),
|
||||
&pos);
|
||||
if (n != sizeof(reply)) {
|
||||
pr_err("read fail %zd\n", n);
|
||||
__stop_umh();
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
goto stop;
|
||||
}
|
||||
ret = reply.status;
|
||||
out:
|
||||
return ret;
|
||||
return reply.status;
|
||||
stop:
|
||||
__stop_umh();
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int bpfilter_process_sockopt(struct sock *sk, int optname,
|
||||
sockptr_t optval, unsigned int optlen,
|
||||
bool is_set)
|
||||
{
|
||||
struct mbox_request req = {
|
||||
.is_set = is_set,
|
||||
.pid = current->pid,
|
||||
.cmd = optname,
|
||||
.addr = (uintptr_t)optval.user,
|
||||
.len = optlen,
|
||||
};
|
||||
if (uaccess_kernel() || sockptr_is_kernel(optval)) {
|
||||
pr_err("kernel access not supported\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
return bpfilter_send_req(&req);
|
||||
}
|
||||
|
||||
static int start_umh(void)
|
||||
{
|
||||
struct mbox_request req = { .pid = current->pid };
|
||||
int err;
|
||||
|
||||
/* fork usermode process */
|
||||
err = fork_usermode_driver(&bpfilter_ops.info);
|
||||
if (err)
|
||||
return err;
|
||||
bpfilter_ops.stop = false;
|
||||
pr_info("Loaded bpfilter_umh pid %d\n", pid_nr(bpfilter_ops.info.tgid));
|
||||
|
||||
/* health check that usermode process started correctly */
|
||||
if (__bpfilter_process_sockopt(NULL, 0, NULL, 0, 0) != 0) {
|
||||
if (bpfilter_send_req(&req) != 0) {
|
||||
shutdown_umh();
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
@ -100,16 +108,11 @@ static int __init load_umh(void)
|
|||
return err;
|
||||
|
||||
mutex_lock(&bpfilter_ops.lock);
|
||||
if (!bpfilter_ops.stop) {
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
err = start_umh();
|
||||
if (!err && IS_ENABLED(CONFIG_INET)) {
|
||||
bpfilter_ops.sockopt = &__bpfilter_process_sockopt;
|
||||
bpfilter_ops.sockopt = &bpfilter_process_sockopt;
|
||||
bpfilter_ops.start = &start_umh;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&bpfilter_ops.lock);
|
||||
if (err)
|
||||
umd_unload_blob(&bpfilter_ops.info);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
.section .rodata, "a"
|
||||
.section .init.rodata, "a"
|
||||
.global bpfilter_umh_start
|
||||
bpfilter_umh_start:
|
||||
.incbin "net/bpfilter/bpfilter_umh"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \
|
|||
obj-y += net-sysfs.o
|
||||
obj-$(CONFIG_PAGE_POOL) += page_pool.o
|
||||
obj-$(CONFIG_PROC_FS) += net-procfs.o
|
||||
obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o
|
||||
obj-$(CONFIG_NET_PKTGEN) += pktgen.o
|
||||
obj-$(CONFIG_NETPOLL) += netpoll.o
|
||||
obj-$(CONFIG_FIB_RULES) += fib_rules.o
|
||||
|
|
@ -28,10 +27,13 @@ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
|
|||
obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
|
||||
obj-$(CONFIG_LWTUNNEL) += lwtunnel.o
|
||||
obj-$(CONFIG_LWTUNNEL_BPF) += lwt_bpf.o
|
||||
obj-$(CONFIG_BPF_STREAM_PARSER) += sock_map.o
|
||||
obj-$(CONFIG_DST_CACHE) += dst_cache.o
|
||||
obj-$(CONFIG_HWBM) += hwbm.o
|
||||
obj-$(CONFIG_NET_DEVLINK) += devlink.o
|
||||
obj-$(CONFIG_GRO_CELLS) += gro_cells.o
|
||||
obj-$(CONFIG_FAILOVER) += failover.o
|
||||
ifeq ($(CONFIG_INET),y)
|
||||
obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o
|
||||
obj-$(CONFIG_BPF_SYSCALL) += sock_map.o
|
||||
endif
|
||||
obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o
|
||||
|
|
|
|||
|
|
@ -1505,7 +1505,7 @@ struct bpf_prog *__get_filter(struct sock_fprog *fprog, struct sock *sk)
|
|||
|
||||
if (copy_from_user(prog->insns, fprog->filter, fsize)) {
|
||||
__bpf_prog_free(prog);
|
||||
return ERR_PTR(-EINVAL);
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
|
||||
prog->len = fprog->len;
|
||||
|
|
@ -1952,10 +1952,11 @@ BPF_CALL_5(bpf_l4_csum_replace, struct sk_buff *, skb, u32, offset,
|
|||
bool is_pseudo = flags & BPF_F_PSEUDO_HDR;
|
||||
bool is_mmzero = flags & BPF_F_MARK_MANGLED_0;
|
||||
bool do_mforce = flags & BPF_F_MARK_ENFORCE;
|
||||
bool is_ipv6 = flags & BPF_F_IPV6;
|
||||
__sum16 *ptr;
|
||||
|
||||
if (unlikely(flags & ~(BPF_F_MARK_MANGLED_0 | BPF_F_MARK_ENFORCE |
|
||||
BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK)))
|
||||
BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK | BPF_F_IPV6)))
|
||||
return -EINVAL;
|
||||
if (unlikely(offset > 0xffff || offset & 1))
|
||||
return -EFAULT;
|
||||
|
|
@ -1971,7 +1972,7 @@ BPF_CALL_5(bpf_l4_csum_replace, struct sk_buff *, skb, u32, offset,
|
|||
if (unlikely(from != 0))
|
||||
return -EINVAL;
|
||||
|
||||
inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo);
|
||||
inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo, is_ipv6);
|
||||
break;
|
||||
case 2:
|
||||
inet_proto_csum_replace2(ptr, skb, from, to, is_pseudo);
|
||||
|
|
@ -10150,7 +10151,7 @@ sk_reuseport_is_valid_access(int off, int size,
|
|||
case bpf_ctx_range(struct sk_reuseport_md, eth_protocol):
|
||||
if (size < FIELD_SIZEOF(struct sk_buff, protocol))
|
||||
return false;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case bpf_ctx_range(struct sk_reuseport_md, ip_protocol):
|
||||
case bpf_ctx_range(struct sk_reuseport_md, bind_inany):
|
||||
case bpf_ctx_range(struct sk_reuseport_md, len):
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
|
|||
{
|
||||
int ret;
|
||||
|
||||
/* Preempt disable and BH disable are needed to protect per-cpu
|
||||
/* Migration disable and BH disable are needed to protect per-cpu
|
||||
* redirect_info between BPF prog and skb_do_redirect().
|
||||
*/
|
||||
preempt_disable();
|
||||
migrate_disable();
|
||||
local_bh_disable();
|
||||
bpf_compute_data_pointers(skb);
|
||||
ret = bpf_prog_run_save_cb(lwt->prog, skb);
|
||||
|
|
@ -77,7 +77,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
|
|||
}
|
||||
|
||||
local_bh_enable();
|
||||
preempt_enable();
|
||||
migrate_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
181
net/core/skmsg.c
181
net/core/skmsg.c
|
|
@ -549,15 +549,35 @@ end:
|
|||
|
||||
struct sk_psock *sk_psock_init(struct sock *sk, int node)
|
||||
{
|
||||
struct sk_psock *psock = kzalloc_node(sizeof(*psock),
|
||||
GFP_ATOMIC | __GFP_NOWARN,
|
||||
node);
|
||||
if (!psock)
|
||||
return NULL;
|
||||
struct sk_psock *psock;
|
||||
struct proto *prot;
|
||||
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
|
||||
if (inet_csk_has_ulp(sk)) {
|
||||
psock = ERR_PTR(-EINVAL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sk->sk_user_data) {
|
||||
psock = ERR_PTR(-EBUSY);
|
||||
goto out;
|
||||
}
|
||||
|
||||
psock = kzalloc_node(sizeof(*psock), GFP_ATOMIC | __GFP_NOWARN, node);
|
||||
if (!psock) {
|
||||
psock = ERR_PTR(-ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
prot = READ_ONCE(sk->sk_prot);
|
||||
psock->sk = sk;
|
||||
psock->eval = __SK_NONE;
|
||||
psock->eval = __SK_NONE;
|
||||
psock->sk_proto = prot;
|
||||
psock->saved_destroy = prot->destroy;
|
||||
psock->saved_unhash = prot->unhash;
|
||||
psock->saved_close = prot->close;
|
||||
psock->saved_write_space = sk->sk_write_space;
|
||||
|
||||
INIT_LIST_HEAD(&psock->link);
|
||||
spin_lock_init(&psock->link_lock);
|
||||
|
|
@ -572,6 +592,8 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node)
|
|||
rcu_assign_sk_user_data_nocopy(sk, psock);
|
||||
sock_hold(sk);
|
||||
|
||||
out:
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
return psock;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sk_psock_init);
|
||||
|
|
@ -616,15 +638,15 @@ static void sk_psock_link_destroy(struct sk_psock *psock)
|
|||
}
|
||||
}
|
||||
|
||||
static void sk_psock_done_strp(struct sk_psock *psock);
|
||||
|
||||
static void sk_psock_destroy_deferred(struct work_struct *gc)
|
||||
{
|
||||
struct sk_psock *psock = container_of(gc, struct sk_psock, gc);
|
||||
|
||||
/* No sk_callback_lock since already detached. */
|
||||
|
||||
/* Parser has been stopped */
|
||||
if (psock->progs.skb_parser)
|
||||
strp_done(&psock->parser.strp);
|
||||
sk_psock_done_strp(psock);
|
||||
|
||||
cancel_work_sync(&psock->work);
|
||||
|
||||
|
|
@ -659,6 +681,8 @@ void sk_psock_drop(struct sock *sk, struct sk_psock *psock)
|
|||
rcu_assign_sk_user_data(sk, NULL);
|
||||
if (psock->progs.skb_parser)
|
||||
sk_psock_stop_strp(sk, psock);
|
||||
else if (psock->progs.skb_verdict)
|
||||
sk_psock_stop_verdict(sk, psock);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);
|
||||
|
||||
|
|
@ -735,14 +759,6 @@ static int sk_psock_bpf_run(struct sk_psock *psock, struct bpf_prog *prog,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct sk_psock *sk_psock_from_strp(struct strparser *strp)
|
||||
{
|
||||
struct sk_psock_parser *parser;
|
||||
|
||||
parser = container_of(strp, struct sk_psock_parser, strp);
|
||||
return container_of(parser, struct sk_psock, parser);
|
||||
}
|
||||
|
||||
static void sk_psock_skb_redirect(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_psock *psock_other;
|
||||
|
|
@ -849,6 +865,24 @@ out_free:
|
|||
}
|
||||
}
|
||||
|
||||
static void sk_psock_write_space(struct sock *sk)
|
||||
{
|
||||
struct sk_psock *psock;
|
||||
void (*write_space)(struct sock *sk) = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (likely(psock)) {
|
||||
if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
|
||||
schedule_work(&psock->work);
|
||||
write_space = psock->saved_write_space;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
if (write_space)
|
||||
write_space(sk);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
||||
static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_psock *psock;
|
||||
|
|
@ -880,6 +914,14 @@ static int sk_psock_strp_read_done(struct strparser *strp, int err)
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct sk_psock *sk_psock_from_strp(struct strparser *strp)
|
||||
{
|
||||
struct sk_psock_parser *parser;
|
||||
|
||||
parser = container_of(strp, struct sk_psock_parser, strp);
|
||||
return container_of(parser, struct sk_psock, parser);
|
||||
}
|
||||
|
||||
static int sk_psock_strp_parse(struct strparser *strp, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_psock *psock = sk_psock_from_strp(strp);
|
||||
|
|
@ -913,23 +955,6 @@ static void sk_psock_strp_data_ready(struct sock *sk)
|
|||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void sk_psock_write_space(struct sock *sk)
|
||||
{
|
||||
struct sk_psock *psock;
|
||||
void (*write_space)(struct sock *sk) = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (likely(psock)) {
|
||||
if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
|
||||
schedule_work(&psock->work);
|
||||
write_space = psock->saved_write_space;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
if (write_space)
|
||||
write_space(sk);
|
||||
}
|
||||
|
||||
int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)
|
||||
{
|
||||
static const struct strp_callbacks cb = {
|
||||
|
|
@ -967,3 +992,91 @@ void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)
|
|||
strp_stop(&parser->strp);
|
||||
parser->enabled = false;
|
||||
}
|
||||
|
||||
static void sk_psock_done_strp(struct sk_psock *psock)
|
||||
{
|
||||
/* Parser has been stopped */
|
||||
if (psock->progs.skb_parser)
|
||||
strp_done(&psock->parser.strp);
|
||||
}
|
||||
#else
|
||||
static void sk_psock_done_strp(struct sk_psock *psock)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_BPF_STREAM_PARSER */
|
||||
|
||||
static int sk_psock_verdict_recv(read_descriptor_t *desc, struct sk_buff *skb,
|
||||
unsigned int offset, size_t orig_len)
|
||||
{
|
||||
struct sock *sk = (struct sock *)desc->arg.data;
|
||||
struct sk_psock *psock;
|
||||
struct bpf_prog *prog;
|
||||
int ret = __SK_DROP;
|
||||
int len = skb->len;
|
||||
|
||||
/* clone here so sk_eat_skb() in tcp_read_sock does not drop our data */
|
||||
skb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
desc->error = -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (unlikely(!psock)) {
|
||||
len = 0;
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
skb_set_owner_r(skb, sk);
|
||||
prog = READ_ONCE(psock->progs.skb_verdict);
|
||||
if (likely(prog)) {
|
||||
tcp_skb_bpf_redirect_clear(skb);
|
||||
ret = sk_psock_bpf_run(psock, prog, skb);
|
||||
ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb));
|
||||
}
|
||||
sk_psock_verdict_apply(psock, skb, ret);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return len;
|
||||
}
|
||||
|
||||
static void sk_psock_verdict_data_ready(struct sock *sk)
|
||||
{
|
||||
struct socket *sock = sk->sk_socket;
|
||||
read_descriptor_t desc;
|
||||
|
||||
if (unlikely(!sock || !sock->ops || !sock->ops->read_sock))
|
||||
return;
|
||||
|
||||
desc.arg.data = sk;
|
||||
desc.error = 0;
|
||||
desc.count = 1;
|
||||
|
||||
sock->ops->read_sock(sk, &desc, sk_psock_verdict_recv);
|
||||
}
|
||||
|
||||
void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)
|
||||
{
|
||||
struct sk_psock_parser *parser = &psock->parser;
|
||||
|
||||
if (parser->enabled)
|
||||
return;
|
||||
|
||||
parser->saved_data_ready = sk->sk_data_ready;
|
||||
sk->sk_data_ready = sk_psock_verdict_data_ready;
|
||||
sk->sk_write_space = sk_psock_write_space;
|
||||
parser->enabled = true;
|
||||
}
|
||||
|
||||
void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock)
|
||||
{
|
||||
struct sk_psock_parser *parser = &psock->parser;
|
||||
|
||||
if (!parser->enabled)
|
||||
return;
|
||||
|
||||
sk->sk_data_ready = parser->saved_data_ready;
|
||||
parser->saved_data_ready = NULL;
|
||||
parser->enabled = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/sock_diag.h>
|
||||
#include <net/udp.h>
|
||||
|
||||
struct bpf_stab {
|
||||
struct bpf_map map;
|
||||
|
|
@ -141,8 +142,8 @@ static void sock_map_add_link(struct sk_psock *psock,
|
|||
static void sock_map_del_link(struct sock *sk,
|
||||
struct sk_psock *psock, void *link_raw)
|
||||
{
|
||||
bool strp_stop = false, verdict_stop = false;
|
||||
struct sk_psock_link *link, *tmp;
|
||||
bool strp_stop = false;
|
||||
|
||||
spin_lock_bh(&psock->link_lock);
|
||||
list_for_each_entry_safe(link, tmp, &psock->link, list) {
|
||||
|
|
@ -152,15 +153,20 @@ static void sock_map_del_link(struct sock *sk,
|
|||
map);
|
||||
if (psock->parser.enabled && stab->progs.skb_parser)
|
||||
strp_stop = true;
|
||||
if (psock->parser.enabled && stab->progs.skb_verdict)
|
||||
verdict_stop = true;
|
||||
list_del(&link->list);
|
||||
sk_psock_free_link(link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&psock->link_lock);
|
||||
if (strp_stop) {
|
||||
if (strp_stop || verdict_stop) {
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
sk_psock_stop_strp(sk, psock);
|
||||
if (strp_stop)
|
||||
sk_psock_stop_strp(sk, psock);
|
||||
else
|
||||
sk_psock_stop_verdict(sk, psock);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
}
|
||||
|
|
@ -175,28 +181,27 @@ static void sock_map_unref(struct sock *sk, void *link_raw)
|
|||
}
|
||||
}
|
||||
|
||||
static int sock_map_init_proto(struct sock *sk)
|
||||
static int sock_map_init_proto(struct sock *sk, struct sk_psock *psock)
|
||||
{
|
||||
struct sk_psock *psock;
|
||||
struct proto *prot;
|
||||
|
||||
sock_owned_by_me(sk);
|
||||
switch (sk->sk_type) {
|
||||
case SOCK_STREAM:
|
||||
prot = tcp_bpf_get_proto(sk, psock);
|
||||
break;
|
||||
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (unlikely(!psock)) {
|
||||
rcu_read_unlock();
|
||||
case SOCK_DGRAM:
|
||||
prot = udp_bpf_get_proto(sk, psock);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
prot = tcp_bpf_get_proto(sk, psock);
|
||||
if (IS_ERR(prot)) {
|
||||
rcu_read_unlock();
|
||||
if (IS_ERR(prot))
|
||||
return PTR_ERR(prot);
|
||||
}
|
||||
|
||||
sk_psock_update_proto(sk, psock, prot);
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -207,7 +212,7 @@ static struct sk_psock *sock_map_psock_get_checked(struct sock *sk)
|
|||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (psock) {
|
||||
if (sk->sk_prot->recvmsg != tcp_bpf_recvmsg) {
|
||||
if (sk->sk_prot->close != sock_map_close) {
|
||||
psock = ERR_PTR(-EBUSY);
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -266,8 +271,8 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs,
|
|||
}
|
||||
} else {
|
||||
psock = sk_psock_init(sk, map->numa_node);
|
||||
if (!psock) {
|
||||
ret = -ENOMEM;
|
||||
if (IS_ERR(psock)) {
|
||||
ret = PTR_ERR(psock);
|
||||
goto out_progs;
|
||||
}
|
||||
}
|
||||
|
|
@ -275,23 +280,26 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs,
|
|||
if (msg_parser)
|
||||
psock_set_prog(&psock->progs.msg_parser, msg_parser);
|
||||
|
||||
ret = sock_map_init_proto(sk);
|
||||
ret = sock_map_init_proto(sk, psock);
|
||||
if (ret < 0)
|
||||
goto out_drop;
|
||||
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
if (skb_progs && !psock->parser.enabled) {
|
||||
ret = sk_psock_init_strp(sk, psock);
|
||||
if (ret) {
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
goto out_drop;
|
||||
}
|
||||
if (ret)
|
||||
goto out_unlock_drop;
|
||||
psock_set_prog(&psock->progs.skb_verdict, skb_verdict);
|
||||
psock_set_prog(&psock->progs.skb_parser, skb_parser);
|
||||
sk_psock_start_strp(sk, psock);
|
||||
} else if (!skb_parser && skb_verdict && !psock->parser.enabled) {
|
||||
psock_set_prog(&psock->progs.skb_verdict, skb_verdict);
|
||||
sk_psock_start_verdict(sk,psock);
|
||||
}
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
return 0;
|
||||
out_unlock_drop:
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
out_drop:
|
||||
sk_psock_put(sk, psock);
|
||||
out_progs:
|
||||
|
|
@ -316,11 +324,11 @@ static int sock_map_link_no_progs(struct bpf_map *map, struct sock *sk)
|
|||
|
||||
if (!psock) {
|
||||
psock = sk_psock_init(sk, map->numa_node);
|
||||
if (!psock)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(psock))
|
||||
return PTR_ERR(psock);
|
||||
}
|
||||
|
||||
ret = sock_map_init_proto(sk);
|
||||
ret = sock_map_init_proto(sk, psock);
|
||||
if (ret < 0)
|
||||
sk_psock_put(sk, psock);
|
||||
return ret;
|
||||
|
|
@ -534,15 +542,31 @@ static bool sock_map_op_okay(const struct bpf_sock_ops_kern *ops)
|
|||
ops->op == BPF_SOCK_OPS_TCP_LISTEN_CB;
|
||||
}
|
||||
|
||||
static bool sock_map_sk_is_suitable(const struct sock *sk)
|
||||
static bool sk_is_tcp(const struct sock *sk)
|
||||
{
|
||||
return sk->sk_type == SOCK_STREAM &&
|
||||
sk->sk_protocol == IPPROTO_TCP;
|
||||
}
|
||||
|
||||
static bool sk_is_udp(const struct sock *sk)
|
||||
{
|
||||
return sk->sk_type == SOCK_DGRAM &&
|
||||
sk->sk_protocol == IPPROTO_UDP;
|
||||
}
|
||||
|
||||
static bool sock_map_sk_is_suitable(const struct sock *sk)
|
||||
{
|
||||
return sk_is_tcp(sk) || sk_is_udp(sk);
|
||||
}
|
||||
|
||||
static bool sock_map_sk_state_allowed(const struct sock *sk)
|
||||
{
|
||||
return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN);
|
||||
if (sk_is_tcp(sk))
|
||||
return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN);
|
||||
else if (sk_is_udp(sk))
|
||||
return sk_hashed(sk);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int sock_hash_update_common(struct bpf_map *map, void *key,
|
||||
|
|
@ -1241,9 +1265,11 @@ int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
|
|||
case BPF_SK_MSG_VERDICT:
|
||||
pprog = &progs->msg_parser;
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
||||
case BPF_SK_SKB_STREAM_PARSER:
|
||||
pprog = &progs->skb_parser;
|
||||
break;
|
||||
#endif
|
||||
case BPF_SK_SKB_STREAM_VERDICT:
|
||||
pprog = &progs->skb_verdict;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ static int flow_limit_cpu_sysctl(struct ctl_table *table, int write,
|
|||
return -ENOMEM;
|
||||
|
||||
if (write) {
|
||||
ret = cpumask_parse_user(buffer, *lenp, mask);
|
||||
ret = cpumask_parse(buffer, mask);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
|
|
|||
|
|
@ -473,11 +473,11 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
|||
EXPORT_SYMBOL(inet_proto_csum_replace16);
|
||||
|
||||
void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
|
||||
__wsum diff, bool pseudohdr)
|
||||
__wsum diff, bool pseudohdr, bool ipv6)
|
||||
{
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||
*sum = csum_fold(csum_add(diff, ~csum_unfold(*sum)));
|
||||
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
|
||||
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr && !ipv6)
|
||||
skb->csum = ~csum_add(diff, ~skb->csum);
|
||||
} else if (pseudohdr) {
|
||||
*sum = ~csum_fold(csum_add(diff, csum_unfold(*sum)));
|
||||
|
|
|
|||
200
net/ipv4/Kconfig
200
net/ipv4/Kconfig
|
|
@ -180,8 +180,8 @@ config NET_IPIP
|
|||
config NET_IPGRE_DEMUX
|
||||
tristate "IP: GRE demultiplexer"
|
||||
help
|
||||
This is helper module to demultiplex GRE packets on GRE version field criteria.
|
||||
Required by ip_gre and pptp modules.
|
||||
This is helper module to demultiplex GRE packets on GRE version field criteria.
|
||||
Required by ip_gre and pptp modules.
|
||||
|
||||
config NET_IP_TUNNEL
|
||||
tristate
|
||||
|
|
@ -470,185 +470,185 @@ config TCP_CONG_BIC
|
|||
tristate "Binary Increase Congestion (BIC) control"
|
||||
default m
|
||||
---help---
|
||||
BIC-TCP is a sender-side only change that ensures a linear RTT
|
||||
fairness under large windows while offering both scalability and
|
||||
bounded TCP-friendliness. The protocol combines two schemes
|
||||
called additive increase and binary search increase. When the
|
||||
congestion window is large, additive increase with a large
|
||||
increment ensures linear RTT fairness as well as good
|
||||
scalability. Under small congestion windows, binary search
|
||||
increase provides TCP friendliness.
|
||||
See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/
|
||||
BIC-TCP is a sender-side only change that ensures a linear RTT
|
||||
fairness under large windows while offering both scalability and
|
||||
bounded TCP-friendliness. The protocol combines two schemes
|
||||
called additive increase and binary search increase. When the
|
||||
congestion window is large, additive increase with a large
|
||||
increment ensures linear RTT fairness as well as good
|
||||
scalability. Under small congestion windows, binary search
|
||||
increase provides TCP friendliness.
|
||||
See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/
|
||||
|
||||
config TCP_CONG_CUBIC
|
||||
tristate "CUBIC TCP"
|
||||
default y
|
||||
---help---
|
||||
This is version 2.0 of BIC-TCP which uses a cubic growth function
|
||||
among other techniques.
|
||||
See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf
|
||||
This is version 2.0 of BIC-TCP which uses a cubic growth function
|
||||
among other techniques.
|
||||
See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf
|
||||
|
||||
config TCP_CONG_WESTWOOD
|
||||
tristate "TCP Westwood+"
|
||||
default m
|
||||
---help---
|
||||
TCP Westwood+ is a sender-side only modification of the TCP Reno
|
||||
protocol stack that optimizes the performance of TCP congestion
|
||||
control. It is based on end-to-end bandwidth estimation to set
|
||||
congestion window and slow start threshold after a congestion
|
||||
episode. Using this estimation, TCP Westwood+ adaptively sets a
|
||||
slow start threshold and a congestion window which takes into
|
||||
account the bandwidth used at the time congestion is experienced.
|
||||
TCP Westwood+ significantly increases fairness wrt TCP Reno in
|
||||
wired networks and throughput over wireless links.
|
||||
TCP Westwood+ is a sender-side only modification of the TCP Reno
|
||||
protocol stack that optimizes the performance of TCP congestion
|
||||
control. It is based on end-to-end bandwidth estimation to set
|
||||
congestion window and slow start threshold after a congestion
|
||||
episode. Using this estimation, TCP Westwood+ adaptively sets a
|
||||
slow start threshold and a congestion window which takes into
|
||||
account the bandwidth used at the time congestion is experienced.
|
||||
TCP Westwood+ significantly increases fairness wrt TCP Reno in
|
||||
wired networks and throughput over wireless links.
|
||||
|
||||
config TCP_CONG_HTCP
|
||||
tristate "H-TCP"
|
||||
default m
|
||||
---help---
|
||||
H-TCP is a send-side only modifications of the TCP Reno
|
||||
protocol stack that optimizes the performance of TCP
|
||||
congestion control for high speed network links. It uses a
|
||||
modeswitch to change the alpha and beta parameters of TCP Reno
|
||||
based on network conditions and in a way so as to be fair with
|
||||
other Reno and H-TCP flows.
|
||||
H-TCP is a send-side only modifications of the TCP Reno
|
||||
protocol stack that optimizes the performance of TCP
|
||||
congestion control for high speed network links. It uses a
|
||||
modeswitch to change the alpha and beta parameters of TCP Reno
|
||||
based on network conditions and in a way so as to be fair with
|
||||
other Reno and H-TCP flows.
|
||||
|
||||
config TCP_CONG_HSTCP
|
||||
tristate "High Speed TCP"
|
||||
default n
|
||||
---help---
|
||||
Sally Floyd's High Speed TCP (RFC 3649) congestion control.
|
||||
A modification to TCP's congestion control mechanism for use
|
||||
with large congestion windows. A table indicates how much to
|
||||
increase the congestion window by when an ACK is received.
|
||||
For more detail see http://www.icir.org/floyd/hstcp.html
|
||||
Sally Floyd's High Speed TCP (RFC 3649) congestion control.
|
||||
A modification to TCP's congestion control mechanism for use
|
||||
with large congestion windows. A table indicates how much to
|
||||
increase the congestion window by when an ACK is received.
|
||||
For more detail see http://www.icir.org/floyd/hstcp.html
|
||||
|
||||
config TCP_CONG_HYBLA
|
||||
tristate "TCP-Hybla congestion control algorithm"
|
||||
default n
|
||||
---help---
|
||||
TCP-Hybla is a sender-side only change that eliminates penalization of
|
||||
long-RTT, large-bandwidth connections, like when satellite legs are
|
||||
involved, especially when sharing a common bottleneck with normal
|
||||
terrestrial connections.
|
||||
TCP-Hybla is a sender-side only change that eliminates penalization of
|
||||
long-RTT, large-bandwidth connections, like when satellite legs are
|
||||
involved, especially when sharing a common bottleneck with normal
|
||||
terrestrial connections.
|
||||
|
||||
config TCP_CONG_VEGAS
|
||||
tristate "TCP Vegas"
|
||||
default n
|
||||
---help---
|
||||
TCP Vegas is a sender-side only change to TCP that anticipates
|
||||
the onset of congestion by estimating the bandwidth. TCP Vegas
|
||||
adjusts the sending rate by modifying the congestion
|
||||
window. TCP Vegas should provide less packet loss, but it is
|
||||
not as aggressive as TCP Reno.
|
||||
TCP Vegas is a sender-side only change to TCP that anticipates
|
||||
the onset of congestion by estimating the bandwidth. TCP Vegas
|
||||
adjusts the sending rate by modifying the congestion
|
||||
window. TCP Vegas should provide less packet loss, but it is
|
||||
not as aggressive as TCP Reno.
|
||||
|
||||
config TCP_CONG_NV
|
||||
tristate "TCP NV"
|
||||
default n
|
||||
---help---
|
||||
TCP NV is a follow up to TCP Vegas. It has been modified to deal with
|
||||
10G networks, measurement noise introduced by LRO, GRO and interrupt
|
||||
coalescence. In addition, it will decrease its cwnd multiplicatively
|
||||
instead of linearly.
|
||||
tristate "TCP NV"
|
||||
default n
|
||||
---help---
|
||||
TCP NV is a follow up to TCP Vegas. It has been modified to deal with
|
||||
10G networks, measurement noise introduced by LRO, GRO and interrupt
|
||||
coalescence. In addition, it will decrease its cwnd multiplicatively
|
||||
instead of linearly.
|
||||
|
||||
Note that in general congestion avoidance (cwnd decreased when # packets
|
||||
queued grows) cannot coexist with congestion control (cwnd decreased only
|
||||
when there is packet loss) due to fairness issues. One scenario when they
|
||||
can coexist safely is when the CA flows have RTTs << CC flows RTTs.
|
||||
Note that in general congestion avoidance (cwnd decreased when # packets
|
||||
queued grows) cannot coexist with congestion control (cwnd decreased only
|
||||
when there is packet loss) due to fairness issues. One scenario when they
|
||||
can coexist safely is when the CA flows have RTTs << CC flows RTTs.
|
||||
|
||||
For further details see http://www.brakmo.org/networking/tcp-nv/
|
||||
For further details see http://www.brakmo.org/networking/tcp-nv/
|
||||
|
||||
config TCP_CONG_SCALABLE
|
||||
tristate "Scalable TCP"
|
||||
default n
|
||||
---help---
|
||||
Scalable TCP is a sender-side only change to TCP which uses a
|
||||
MIMD congestion control algorithm which has some nice scaling
|
||||
properties, though is known to have fairness issues.
|
||||
See http://www.deneholme.net/tom/scalable/
|
||||
Scalable TCP is a sender-side only change to TCP which uses a
|
||||
MIMD congestion control algorithm which has some nice scaling
|
||||
properties, though is known to have fairness issues.
|
||||
See http://www.deneholme.net/tom/scalable/
|
||||
|
||||
config TCP_CONG_LP
|
||||
tristate "TCP Low Priority"
|
||||
default n
|
||||
---help---
|
||||
TCP Low Priority (TCP-LP), a distributed algorithm whose goal is
|
||||
to utilize only the excess network bandwidth as compared to the
|
||||
``fair share`` of bandwidth as targeted by TCP.
|
||||
See http://www-ece.rice.edu/networks/TCP-LP/
|
||||
TCP Low Priority (TCP-LP), a distributed algorithm whose goal is
|
||||
to utilize only the excess network bandwidth as compared to the
|
||||
``fair share`` of bandwidth as targeted by TCP.
|
||||
See http://www-ece.rice.edu/networks/TCP-LP/
|
||||
|
||||
config TCP_CONG_VENO
|
||||
tristate "TCP Veno"
|
||||
default n
|
||||
---help---
|
||||
TCP Veno is a sender-side only enhancement of TCP to obtain better
|
||||
throughput over wireless networks. TCP Veno makes use of state
|
||||
distinguishing to circumvent the difficult judgment of the packet loss
|
||||
type. TCP Veno cuts down less congestion window in response to random
|
||||
loss packets.
|
||||
See <http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=1177186>
|
||||
TCP Veno is a sender-side only enhancement of TCP to obtain better
|
||||
throughput over wireless networks. TCP Veno makes use of state
|
||||
distinguishing to circumvent the difficult judgment of the packet loss
|
||||
type. TCP Veno cuts down less congestion window in response to random
|
||||
loss packets.
|
||||
See <http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=1177186>
|
||||
|
||||
config TCP_CONG_YEAH
|
||||
tristate "YeAH TCP"
|
||||
select TCP_CONG_VEGAS
|
||||
default n
|
||||
---help---
|
||||
YeAH-TCP is a sender-side high-speed enabled TCP congestion control
|
||||
algorithm, which uses a mixed loss/delay approach to compute the
|
||||
congestion window. It's design goals target high efficiency,
|
||||
internal, RTT and Reno fairness, resilience to link loss while
|
||||
keeping network elements load as low as possible.
|
||||
YeAH-TCP is a sender-side high-speed enabled TCP congestion control
|
||||
algorithm, which uses a mixed loss/delay approach to compute the
|
||||
congestion window. It's design goals target high efficiency,
|
||||
internal, RTT and Reno fairness, resilience to link loss while
|
||||
keeping network elements load as low as possible.
|
||||
|
||||
For further details look here:
|
||||
http://wil.cs.caltech.edu/pfldnet2007/paper/YeAH_TCP.pdf
|
||||
For further details look here:
|
||||
http://wil.cs.caltech.edu/pfldnet2007/paper/YeAH_TCP.pdf
|
||||
|
||||
config TCP_CONG_ILLINOIS
|
||||
tristate "TCP Illinois"
|
||||
default n
|
||||
---help---
|
||||
TCP-Illinois is a sender-side modification of TCP Reno for
|
||||
high speed long delay links. It uses round-trip-time to
|
||||
adjust the alpha and beta parameters to achieve a higher average
|
||||
throughput and maintain fairness.
|
||||
TCP-Illinois is a sender-side modification of TCP Reno for
|
||||
high speed long delay links. It uses round-trip-time to
|
||||
adjust the alpha and beta parameters to achieve a higher average
|
||||
throughput and maintain fairness.
|
||||
|
||||
For further details see:
|
||||
http://www.ews.uiuc.edu/~shaoliu/tcpillinois/index.html
|
||||
For further details see:
|
||||
http://www.ews.uiuc.edu/~shaoliu/tcpillinois/index.html
|
||||
|
||||
config TCP_CONG_DCTCP
|
||||
tristate "DataCenter TCP (DCTCP)"
|
||||
default n
|
||||
---help---
|
||||
DCTCP leverages Explicit Congestion Notification (ECN) in the network to
|
||||
provide multi-bit feedback to the end hosts. It is designed to provide:
|
||||
DCTCP leverages Explicit Congestion Notification (ECN) in the network to
|
||||
provide multi-bit feedback to the end hosts. It is designed to provide:
|
||||
|
||||
- High burst tolerance (incast due to partition/aggregate),
|
||||
- Low latency (short flows, queries),
|
||||
- High throughput (continuous data updates, large file transfers) with
|
||||
commodity, shallow-buffered switches.
|
||||
- High burst tolerance (incast due to partition/aggregate),
|
||||
- Low latency (short flows, queries),
|
||||
- High throughput (continuous data updates, large file transfers) with
|
||||
commodity, shallow-buffered switches.
|
||||
|
||||
All switches in the data center network running DCTCP must support
|
||||
ECN marking and be configured for marking when reaching defined switch
|
||||
buffer thresholds. The default ECN marking threshold heuristic for
|
||||
DCTCP on switches is 20 packets (30KB) at 1Gbps, and 65 packets
|
||||
(~100KB) at 10Gbps, but might need further careful tweaking.
|
||||
All switches in the data center network running DCTCP must support
|
||||
ECN marking and be configured for marking when reaching defined switch
|
||||
buffer thresholds. The default ECN marking threshold heuristic for
|
||||
DCTCP on switches is 20 packets (30KB) at 1Gbps, and 65 packets
|
||||
(~100KB) at 10Gbps, but might need further careful tweaking.
|
||||
|
||||
For further details see:
|
||||
http://simula.stanford.edu/~alizade/Site/DCTCP_files/dctcp-final.pdf
|
||||
For further details see:
|
||||
http://simula.stanford.edu/~alizade/Site/DCTCP_files/dctcp-final.pdf
|
||||
|
||||
config TCP_CONG_CDG
|
||||
tristate "CAIA Delay-Gradient (CDG)"
|
||||
default n
|
||||
---help---
|
||||
CAIA Delay-Gradient (CDG) is a TCP congestion control that modifies
|
||||
the TCP sender in order to:
|
||||
CAIA Delay-Gradient (CDG) is a TCP congestion control that modifies
|
||||
the TCP sender in order to:
|
||||
|
||||
o Use the delay gradient as a congestion signal.
|
||||
o Back off with an average probability that is independent of the RTT.
|
||||
o Coexist with flows that use loss-based congestion control.
|
||||
o Tolerate packet loss unrelated to congestion.
|
||||
|
||||
For further details see:
|
||||
D.A. Hayes and G. Armitage. "Revisiting TCP congestion control using
|
||||
delay gradients." In Networking 2011. Preprint: http://goo.gl/No3vdg
|
||||
For further details see:
|
||||
D.A. Hayes and G. Armitage. "Revisiting TCP congestion control using
|
||||
delay gradients." In Networking 2011. Preprint: http://goo.gl/No3vdg
|
||||
|
||||
config TCP_CONG_BBR
|
||||
tristate "BBR TCP"
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
|
|||
obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
|
||||
obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
|
||||
obj-$(CONFIG_NET_SOCK_MSG) += tcp_bpf.o
|
||||
obj-$(CONFIG_BPF_SYSCALL) += udp_bpf.o
|
||||
obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
|
||||
|
||||
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
|
||||
|
|
|
|||
|
|
@ -12,19 +12,16 @@
|
|||
struct bpfilter_umh_ops bpfilter_ops;
|
||||
EXPORT_SYMBOL_GPL(bpfilter_ops);
|
||||
|
||||
static void bpfilter_umh_cleanup(struct umd_info *info)
|
||||
void bpfilter_umh_cleanup(struct umd_info *info)
|
||||
{
|
||||
mutex_lock(&bpfilter_ops.lock);
|
||||
bpfilter_ops.stop = true;
|
||||
fput(info->pipe_to_umh);
|
||||
fput(info->pipe_from_umh);
|
||||
put_pid(info->tgid);
|
||||
info->tgid = NULL;
|
||||
mutex_unlock(&bpfilter_ops.lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bpfilter_umh_cleanup);
|
||||
|
||||
static int bpfilter_mbox_request(struct sock *sk, int optname,
|
||||
char __user *optval,
|
||||
static int bpfilter_mbox_request(struct sock *sk, int optname, sockptr_t optval,
|
||||
unsigned int optlen, bool is_set)
|
||||
{
|
||||
int err;
|
||||
|
|
@ -39,7 +36,11 @@ static int bpfilter_mbox_request(struct sock *sk, int optname,
|
|||
goto out;
|
||||
}
|
||||
}
|
||||
if (bpfilter_ops.stop) {
|
||||
if (bpfilter_ops.info.tgid &&
|
||||
thread_group_exited(bpfilter_ops.info.tgid))
|
||||
bpfilter_umh_cleanup(&bpfilter_ops.info);
|
||||
|
||||
if (!bpfilter_ops.info.tgid) {
|
||||
err = bpfilter_ops.start();
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
@ -50,7 +51,7 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
|
||||
int bpfilter_ip_set_sockopt(struct sock *sk, int optname, sockptr_t optval,
|
||||
unsigned int optlen)
|
||||
{
|
||||
return bpfilter_mbox_request(sk, optname, optval, optlen, true);
|
||||
|
|
@ -64,15 +65,15 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
|
|||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
return bpfilter_mbox_request(sk, optname, optval, len, false);
|
||||
return bpfilter_mbox_request(sk, optname, USER_SOCKPTR(optval), len,
|
||||
false);
|
||||
}
|
||||
|
||||
static int __init bpfilter_sockopt_init(void)
|
||||
{
|
||||
mutex_init(&bpfilter_ops.lock);
|
||||
bpfilter_ops.stop = true;
|
||||
bpfilter_ops.info.tgid = NULL;
|
||||
bpfilter_ops.info.driver_name = "bpfilter_umh";
|
||||
bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1256,7 +1256,8 @@ int ip_setsockopt(struct sock *sk, int level,
|
|||
#if IS_ENABLED(CONFIG_BPFILTER_UMH)
|
||||
if (optname >= BPFILTER_IPT_SO_SET_REPLACE &&
|
||||
optname < BPFILTER_IPT_SET_MAX)
|
||||
err = bpfilter_ip_set_sockopt(sk, optname, optval, optlen);
|
||||
err = bpfilter_ip_set_sockopt(sk, optname, USER_SOCKPTR(optval),
|
||||
optlen);
|
||||
#endif
|
||||
#ifdef CONFIG_NETFILTER
|
||||
/* we need to exclude all possible ENOPROTOOPTs except default case */
|
||||
|
|
|
|||
|
|
@ -10,38 +10,6 @@
|
|||
#include <net/inet_common.h>
|
||||
#include <net/tls.h>
|
||||
|
||||
static bool tcp_bpf_stream_read(const struct sock *sk)
|
||||
{
|
||||
struct sk_psock *psock;
|
||||
bool empty = true;
|
||||
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (likely(psock))
|
||||
empty = list_empty(&psock->ingress_msg);
|
||||
rcu_read_unlock();
|
||||
return !empty;
|
||||
}
|
||||
|
||||
static int tcp_bpf_wait_data(struct sock *sk, struct sk_psock *psock,
|
||||
int flags, long timeo, int *err)
|
||||
{
|
||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||
int ret = 0;
|
||||
|
||||
if (!timeo)
|
||||
return ret;
|
||||
|
||||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
||||
ret = sk_wait_event(sk, &timeo,
|
||||
!list_empty(&psock->ingress_msg) ||
|
||||
!skb_queue_empty(&sk->sk_receive_queue), &wait);
|
||||
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock,
|
||||
struct msghdr *msg, int len, int flags)
|
||||
{
|
||||
|
|
@ -122,52 +90,6 @@ int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(__tcp_bpf_recvmsg);
|
||||
|
||||
int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
int nonblock, int flags, int *addr_len)
|
||||
{
|
||||
struct sk_psock *psock;
|
||||
int copied, ret;
|
||||
|
||||
if (unlikely(flags & MSG_ERRQUEUE))
|
||||
return inet_recv_error(sk, msg, len, addr_len);
|
||||
|
||||
psock = sk_psock_get(sk);
|
||||
if (unlikely(!psock))
|
||||
return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
|
||||
if (!skb_queue_empty(&sk->sk_receive_queue) &&
|
||||
sk_psock_queue_empty(psock)) {
|
||||
sk_psock_put(sk, psock);
|
||||
return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
|
||||
}
|
||||
lock_sock(sk);
|
||||
msg_bytes_ready:
|
||||
copied = __tcp_bpf_recvmsg(sk, psock, msg, len, flags);
|
||||
if (!copied) {
|
||||
int data, err = 0;
|
||||
long timeo;
|
||||
|
||||
timeo = sock_rcvtimeo(sk, nonblock);
|
||||
data = tcp_bpf_wait_data(sk, psock, flags, timeo, &err);
|
||||
if (data) {
|
||||
if (!sk_psock_queue_empty(psock))
|
||||
goto msg_bytes_ready;
|
||||
release_sock(sk);
|
||||
sk_psock_put(sk, psock);
|
||||
return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
|
||||
}
|
||||
if (err) {
|
||||
ret = err;
|
||||
goto out;
|
||||
}
|
||||
copied = -EAGAIN;
|
||||
}
|
||||
ret = copied;
|
||||
out:
|
||||
release_sock(sk);
|
||||
sk_psock_put(sk, psock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock,
|
||||
struct sk_msg *msg, u32 apply_bytes, int flags)
|
||||
{
|
||||
|
|
@ -309,6 +231,85 @@ int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(tcp_bpf_sendmsg_redir);
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
static bool tcp_bpf_stream_read(const struct sock *sk)
|
||||
{
|
||||
struct sk_psock *psock;
|
||||
bool empty = true;
|
||||
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (likely(psock))
|
||||
empty = list_empty(&psock->ingress_msg);
|
||||
rcu_read_unlock();
|
||||
return !empty;
|
||||
}
|
||||
|
||||
static int tcp_bpf_wait_data(struct sock *sk, struct sk_psock *psock,
|
||||
int flags, long timeo, int *err)
|
||||
{
|
||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||
int ret = 0;
|
||||
|
||||
if (!timeo)
|
||||
return ret;
|
||||
|
||||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
||||
ret = sk_wait_event(sk, &timeo,
|
||||
!list_empty(&psock->ingress_msg) ||
|
||||
!skb_queue_empty(&sk->sk_receive_queue), &wait);
|
||||
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
int nonblock, int flags, int *addr_len)
|
||||
{
|
||||
struct sk_psock *psock;
|
||||
int copied, ret;
|
||||
|
||||
if (unlikely(flags & MSG_ERRQUEUE))
|
||||
return inet_recv_error(sk, msg, len, addr_len);
|
||||
|
||||
psock = sk_psock_get(sk);
|
||||
if (unlikely(!psock))
|
||||
return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
|
||||
if (!skb_queue_empty(&sk->sk_receive_queue) &&
|
||||
sk_psock_queue_empty(psock)) {
|
||||
sk_psock_put(sk, psock);
|
||||
return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
|
||||
}
|
||||
lock_sock(sk);
|
||||
msg_bytes_ready:
|
||||
copied = __tcp_bpf_recvmsg(sk, psock, msg, len, flags);
|
||||
if (!copied) {
|
||||
int data, err = 0;
|
||||
long timeo;
|
||||
|
||||
timeo = sock_rcvtimeo(sk, nonblock);
|
||||
data = tcp_bpf_wait_data(sk, psock, flags, timeo, &err);
|
||||
if (data) {
|
||||
if (!sk_psock_queue_empty(psock))
|
||||
goto msg_bytes_ready;
|
||||
release_sock(sk);
|
||||
sk_psock_put(sk, psock);
|
||||
return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
|
||||
}
|
||||
if (err) {
|
||||
ret = err;
|
||||
goto out;
|
||||
}
|
||||
copied = -EAGAIN;
|
||||
}
|
||||
ret = copied;
|
||||
out:
|
||||
release_sock(sk);
|
||||
sk_psock_put(sk, psock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock,
|
||||
struct sk_msg *msg, int *copied, int flags)
|
||||
{
|
||||
|
|
@ -557,7 +558,6 @@ out_err:
|
|||
return copied ? copied : err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BPF_STREAM_PARSER
|
||||
enum {
|
||||
TCP_BPF_IPV4,
|
||||
TCP_BPF_IPV6,
|
||||
|
|
@ -589,10 +589,9 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS],
|
|||
prot[TCP_BPF_TX].sendpage = tcp_bpf_sendpage;
|
||||
}
|
||||
|
||||
static void tcp_bpf_check_v6_needs_rebuild(struct sock *sk, struct proto *ops)
|
||||
static void tcp_bpf_check_v6_needs_rebuild(struct proto *ops)
|
||||
{
|
||||
if (sk->sk_family == AF_INET6 &&
|
||||
unlikely(ops != smp_load_acquire(&tcpv6_prot_saved))) {
|
||||
if (unlikely(ops != smp_load_acquire(&tcpv6_prot_saved))) {
|
||||
spin_lock_bh(&tcpv6_prot_lock);
|
||||
if (likely(ops != tcpv6_prot_saved)) {
|
||||
tcp_bpf_rebuild_protos(tcp_bpf_prots[TCP_BPF_IPV6], ops);
|
||||
|
|
@ -625,13 +624,11 @@ struct proto *tcp_bpf_get_proto(struct sock *sk, struct sk_psock *psock)
|
|||
int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4;
|
||||
int config = psock->progs.msg_parser ? TCP_BPF_TX : TCP_BPF_BASE;
|
||||
|
||||
if (!psock->sk_proto) {
|
||||
struct proto *ops = READ_ONCE(sk->sk_prot);
|
||||
|
||||
if (tcp_bpf_assert_proto_ops(ops))
|
||||
if (sk->sk_family == AF_INET6) {
|
||||
if (tcp_bpf_assert_proto_ops(psock->sk_proto))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
tcp_bpf_check_v6_needs_rebuild(sk, ops);
|
||||
tcp_bpf_check_v6_needs_rebuild(psock->sk_proto);
|
||||
}
|
||||
|
||||
return &tcp_bpf_prots[family][config];
|
||||
|
|
@ -650,4 +647,4 @@ void tcp_bpf_clone(const struct sock *sk, struct sock *newsk)
|
|||
if (prot == &tcp_bpf_prots[family][TCP_BPF_BASE])
|
||||
newsk->sk_prot = sk->sk_prot_creator;
|
||||
}
|
||||
#endif /* CONFIG_BPF_STREAM_PARSER */
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
|
|
|
|||
52
net/ipv4/udp_bpf.c
Normal file
52
net/ipv4/udp_bpf.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2020 Cloudflare Ltd https://cloudflare.com */
|
||||
|
||||
#include <linux/skmsg.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/udp.h>
|
||||
|
||||
enum {
|
||||
UDP_BPF_IPV4,
|
||||
UDP_BPF_IPV6,
|
||||
UDP_BPF_NUM_PROTS,
|
||||
};
|
||||
|
||||
static struct proto *udpv6_prot_saved __read_mostly;
|
||||
static DEFINE_SPINLOCK(udpv6_prot_lock);
|
||||
static struct proto udp_bpf_prots[UDP_BPF_NUM_PROTS];
|
||||
|
||||
static void udp_bpf_rebuild_protos(struct proto *prot, const struct proto *base)
|
||||
{
|
||||
*prot = *base;
|
||||
prot->unhash = sock_map_unhash;
|
||||
prot->close = sock_map_close;
|
||||
}
|
||||
|
||||
static void udp_bpf_check_v6_needs_rebuild(struct proto *ops)
|
||||
{
|
||||
if (unlikely(ops != smp_load_acquire(&udpv6_prot_saved))) {
|
||||
spin_lock_bh(&udpv6_prot_lock);
|
||||
if (likely(ops != udpv6_prot_saved)) {
|
||||
udp_bpf_rebuild_protos(&udp_bpf_prots[UDP_BPF_IPV6], ops);
|
||||
smp_store_release(&udpv6_prot_saved, ops);
|
||||
}
|
||||
spin_unlock_bh(&udpv6_prot_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init udp_bpf_v4_build_proto(void)
|
||||
{
|
||||
udp_bpf_rebuild_protos(&udp_bpf_prots[UDP_BPF_IPV4], &udp_prot);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(udp_bpf_v4_build_proto);
|
||||
|
||||
struct proto *udp_bpf_get_proto(struct sock *sk, struct sk_psock *psock)
|
||||
{
|
||||
int family = sk->sk_family == AF_INET ? UDP_BPF_IPV4 : UDP_BPF_IPV6;
|
||||
|
||||
if (sk->sk_family == AF_INET6)
|
||||
udp_bpf_check_v6_needs_rebuild(psock->sk_proto);
|
||||
|
||||
return &udp_bpf_prots[family];
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ static void ila_csum_adjust_transport(struct sk_buff *skb,
|
|||
|
||||
diff = get_csum_diff(ip6h, p);
|
||||
inet_proto_csum_replace_by_diff(&th->check, skb,
|
||||
diff, true);
|
||||
diff, true, true);
|
||||
}
|
||||
break;
|
||||
case NEXTHDR_UDP:
|
||||
|
|
@ -97,7 +97,7 @@ static void ila_csum_adjust_transport(struct sk_buff *skb,
|
|||
if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
diff = get_csum_diff(ip6h, p);
|
||||
inet_proto_csum_replace_by_diff(&uh->check, skb,
|
||||
diff, true);
|
||||
diff, true, true);
|
||||
if (!uh->check)
|
||||
uh->check = CSUM_MANGLED_0;
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ static void ila_csum_adjust_transport(struct sk_buff *skb,
|
|||
|
||||
diff = get_csum_diff(ip6h, p);
|
||||
inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb,
|
||||
diff, true);
|
||||
diff, true, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,9 +128,9 @@ config IP6_NF_MATCH_HL
|
|||
depends on NETFILTER_ADVANCED
|
||||
select NETFILTER_XT_MATCH_HL
|
||||
---help---
|
||||
This is a backwards-compat option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_MATCH_HL.
|
||||
This is a backwards-compat option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_MATCH_HL.
|
||||
|
||||
config IP6_NF_MATCH_IPV6HEADER
|
||||
tristate '"ipv6header" IPv6 Extension Headers Match'
|
||||
|
|
@ -184,9 +184,9 @@ config IP6_NF_TARGET_HL
|
|||
depends on NETFILTER_ADVANCED && IP6_NF_MANGLE
|
||||
select NETFILTER_XT_TARGET_HL
|
||||
---help---
|
||||
This is a backwards-compatible option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_TARGET_HL.
|
||||
This is a backwards-compatible option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_TARGET_HL.
|
||||
|
||||
config IP6_NF_FILTER
|
||||
tristate "Packet filtering"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config NFC_HCI
|
||||
depends on NFC
|
||||
tristate "NFC HCI implementation"
|
||||
default n
|
||||
help
|
||||
Say Y here if you want to build support for a kernel NFC HCI
|
||||
implementation. This is mostly needed for devices that only process
|
||||
HCI frames, like for example the NXP pn544.
|
||||
depends on NFC
|
||||
tristate "NFC HCI implementation"
|
||||
default n
|
||||
help
|
||||
Say Y here if you want to build support for a kernel NFC HCI
|
||||
implementation. This is mostly needed for devices that only process
|
||||
HCI frames, like for example the NXP pn544.
|
||||
|
||||
config NFC_SHDLC
|
||||
depends on NFC_HCI
|
||||
|
|
|
|||
|
|
@ -1338,7 +1338,7 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
|
|||
|
||||
kaddrs = memdup_user(addrs, addrs_size);
|
||||
if (IS_ERR(kaddrs))
|
||||
return PTR_ERR(kaddrs) == -EFAULT ? -EINVAL : PTR_ERR(kaddrs);
|
||||
return PTR_ERR(kaddrs);
|
||||
|
||||
/* Allow security module to validate connectx addresses. */
|
||||
err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX,
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
# XFRM configuration
|
||||
#
|
||||
config XFRM
|
||||
bool
|
||||
depends on INET
|
||||
select GRO_CELLS
|
||||
select SKB_EXTENSIONS
|
||||
bool
|
||||
depends on INET
|
||||
select GRO_CELLS
|
||||
select SKB_EXTENSIONS
|
||||
|
||||
config XFRM_OFFLOAD
|
||||
bool
|
||||
bool
|
||||
|
||||
config XFRM_ALGO
|
||||
tristate
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
|
|||
[LOCKDOWN_MMIOTRACE] = "unsafe mmio",
|
||||
[LOCKDOWN_DEBUGFS] = "debugfs access",
|
||||
[LOCKDOWN_XMON_WR] = "xmon write access",
|
||||
[LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
|
||||
[LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
|
||||
[LOCKDOWN_INTEGRITY_MAX] = "integrity",
|
||||
[LOCKDOWN_KCORE] = "/proc/kcore access",
|
||||
|
|
|
|||
|
|
@ -886,6 +886,7 @@ union bpf_attr {
|
|||
* for updates resulting in a null checksum the value is set to
|
||||
* **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
|
||||
* the checksum is to be computed against a pseudo-header.
|
||||
* Flag **BPF_F_IPV6** should be set for IPv6 packets.
|
||||
*
|
||||
* This helper works in combination with **bpf_csum_diff**\ (),
|
||||
* which does not update the checksum in-place, but offers more
|
||||
|
|
@ -3904,6 +3905,7 @@ enum {
|
|||
BPF_F_PSEUDO_HDR = (1ULL << 4),
|
||||
BPF_F_MARK_MANGLED_0 = (1ULL << 5),
|
||||
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
||||
BPF_F_IPV6 = (1ULL << 7),
|
||||
};
|
||||
|
||||
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
||||
|
|
|
|||
Loading…
Reference in a new issue