mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-31 06:14:39 +01:00
tpacket_req3.tp_sizeof_priv is an unsigned int, and packet_set_ring() validates the full value against the block size. init_prb_bdqc() then stores it in the unsigned short blk_sizeof_priv field. Commit2b6867c2ce("net/packet: fix overflow in check for priv area size") fixed the validation arithmetic, but an accepted value above USHRT_MAX still narrows when it is stored. For a 131072-byte block, tp_sizeof_priv=65536 is valid. The narrowing makes offset_to_first_pkt 48 instead of 65584, so packet records can be placed in the private area that userspace asked the kernel to preserve. blk_sizeof_priv is internal state, so widen it to hold the validated UAPI value. Fixes:f6fb8f100b("af-packet: TPACKET_V3 flexible buffer implementation.") Cc: [email protected] Signed-off-by: Mark Amirkan <[email protected]> Reviewed-by: Willem de Bruijn <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
160 lines
3.4 KiB
C
160 lines
3.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __PACKET_INTERNAL_H__
|
|
#define __PACKET_INTERNAL_H__
|
|
|
|
#include <linux/refcount.h>
|
|
|
|
struct packet_mclist {
|
|
struct packet_mclist *next;
|
|
int ifindex;
|
|
int count;
|
|
unsigned short type;
|
|
unsigned short alen;
|
|
unsigned char addr[MAX_ADDR_LEN];
|
|
struct list_head remove_list;
|
|
};
|
|
|
|
/* kbdq - kernel block descriptor queue */
|
|
struct tpacket_kbdq_core {
|
|
struct pgv *pkbdq;
|
|
unsigned int feature_req_word;
|
|
unsigned int hdrlen;
|
|
unsigned char reset_pending_on_curr_blk;
|
|
unsigned short kactive_blk_num;
|
|
unsigned int blk_sizeof_priv;
|
|
|
|
unsigned short version;
|
|
|
|
char *pkblk_start;
|
|
char *pkblk_end;
|
|
int kblk_size;
|
|
unsigned int max_frame_len;
|
|
unsigned int knum_blocks;
|
|
uint64_t knxt_seq_num;
|
|
char *prev;
|
|
char *nxt_offset;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
rwlock_t blk_fill_in_prog_lock;
|
|
|
|
/* Default is set to 8ms */
|
|
#define DEFAULT_PRB_RETIRE_TOV (8)
|
|
|
|
ktime_t interval_ktime;
|
|
|
|
/* timer to retire an outstanding block */
|
|
struct hrtimer retire_blk_timer;
|
|
};
|
|
|
|
struct pgv {
|
|
char *buffer;
|
|
};
|
|
|
|
struct packet_ring_buffer {
|
|
struct pgv *pg_vec;
|
|
|
|
unsigned int head;
|
|
unsigned int frames_per_block;
|
|
unsigned int frame_size;
|
|
unsigned int frame_max;
|
|
|
|
unsigned int pg_vec_order;
|
|
unsigned int pg_vec_pages;
|
|
unsigned int pg_vec_len;
|
|
|
|
unsigned int __percpu *pending_refcnt;
|
|
|
|
union {
|
|
unsigned long *rx_owner_map;
|
|
struct tpacket_kbdq_core prb_bdqc;
|
|
};
|
|
};
|
|
|
|
extern struct mutex fanout_mutex;
|
|
#define PACKET_FANOUT_MAX (1 << 16)
|
|
|
|
struct packet_fanout {
|
|
possible_net_t net;
|
|
unsigned int num_members;
|
|
u32 max_num_members;
|
|
u16 id;
|
|
u8 type;
|
|
u8 flags;
|
|
union {
|
|
atomic_t rr_cur;
|
|
struct bpf_prog __rcu *bpf_prog;
|
|
};
|
|
struct list_head list;
|
|
spinlock_t lock;
|
|
refcount_t sk_ref;
|
|
struct packet_type prot_hook ____cacheline_aligned_in_smp;
|
|
struct sock __rcu *arr[] __counted_by(max_num_members);
|
|
};
|
|
|
|
struct packet_rollover {
|
|
int sock;
|
|
atomic_long_t num;
|
|
atomic_long_t num_huge;
|
|
atomic_long_t num_failed;
|
|
#define ROLLOVER_HLEN (L1_CACHE_BYTES / sizeof(u32))
|
|
u32 history[ROLLOVER_HLEN] ____cacheline_aligned;
|
|
} ____cacheline_aligned_in_smp;
|
|
|
|
struct packet_sock {
|
|
/* struct sock has to be the first member of packet_sock */
|
|
struct sock sk;
|
|
struct packet_fanout *fanout;
|
|
union tpacket_stats_u stats;
|
|
struct packet_ring_buffer rx_ring;
|
|
struct packet_ring_buffer tx_ring;
|
|
int copy_thresh;
|
|
spinlock_t bind_lock;
|
|
struct mutex pg_vec_lock;
|
|
unsigned long flags;
|
|
int ifindex; /* bound device */
|
|
u8 vnet_hdr_sz;
|
|
__be16 num;
|
|
struct packet_rollover *rollover;
|
|
struct packet_mclist *mclist;
|
|
atomic_long_t mapped;
|
|
enum tpacket_versions tp_version;
|
|
unsigned int tp_hdrlen;
|
|
unsigned int tp_reserve;
|
|
unsigned int tp_tstamp;
|
|
struct completion skb_completion;
|
|
struct net_device __rcu *cached_dev;
|
|
struct packet_type prot_hook ____cacheline_aligned_in_smp;
|
|
atomic_t tp_drops ____cacheline_aligned_in_smp;
|
|
};
|
|
|
|
#define pkt_sk(ptr) container_of_const(ptr, struct packet_sock, sk)
|
|
|
|
enum packet_sock_flags {
|
|
PACKET_SOCK_ORIGDEV,
|
|
PACKET_SOCK_AUXDATA,
|
|
PACKET_SOCK_TX_HAS_OFF,
|
|
PACKET_SOCK_TP_LOSS,
|
|
PACKET_SOCK_RUNNING,
|
|
PACKET_SOCK_PRESSURE,
|
|
PACKET_SOCK_QDISC_BYPASS,
|
|
};
|
|
|
|
static inline void packet_sock_flag_set(struct packet_sock *po,
|
|
enum packet_sock_flags flag,
|
|
bool val)
|
|
{
|
|
if (val)
|
|
set_bit(flag, &po->flags);
|
|
else
|
|
clear_bit(flag, &po->flags);
|
|
}
|
|
|
|
static inline bool packet_sock_flag(const struct packet_sock *po,
|
|
enum packet_sock_flags flag)
|
|
{
|
|
return test_bit(flag, &po->flags);
|
|
}
|
|
|
|
#endif
|