rue/net: avoid wrong memory access to struct net_device
It assigns the net_device pointer of network interface to sock->in_dev in cls_tc_rx_hook() in the receiving process. The use of a sock->in_dev pointer can potentially lead to wrong memory access if the memory of struct net_device is freed after network interface is unregistered, which may cause kernel crash. The above use after free issue causes a crash as follows: BUG: unable to handle page fault for address: ffffffed698999c8 CPU: 50 PID: 1290732 Comm: kubelet Kdump: loaded Tainted: G O K 5.4.119-1-tlinux4-0009.1 #1 RIP: 0010:cls_cgroup_tx_accept+0x5e/0x120 Call Trace: <IRQ> cls_tc_tx_hook+0x10d/0x1a0 nf_hook_slow+0x43/0xc0 __ip_local_out+0xcb/0x130 ? ip_forward_options+0x190/0x190 ip_local_out+0x1c/0x40 __ip_queue_xmit+0x162/0x3d0 ? rx_cgroup_throttle.isra.4+0x2b0/0x2b0 ip_queue_xmit+0x10/0x20 __tcp_transmit_skb+0x57f/0xbe0 __tcp_retransmit_skb+0x1b0/0x8a0 tcp_retransmit_skb+0x19/0xd0 tcp_retransmit_timer+0x367/0xa80 ? kvm_clock_get_cycles+0x11/0x20 ? ktime_get+0x34/0x90 tcp_write_timer_handler+0x93/0x1f0 tcp_write_timer+0x7c/0x80 ? tcp_write_timer_handler+0x1f0/0x1f0 call_timer_fn+0x35/0x130 run_timer_softirq+0x1a8/0x420 ? ktime_get+0x34/0x90 ? clockevents_program_event+0x85/0xe0 __do_softirq+0x8c/0x2d7 ? hrtimer_interrupt+0x12a/0x210 irq_exit+0xa3/0xb0 smp_apic_timer_interrupt+0x77/0x130 apic_timer_interrupt+0xf/0x20 </IRQ> We introduce indev_ifindex as a new struct filed to record the ifindex of net_device, and then indev_ifindex can be used for obtaining an index to avoid direct memory access to struct members of in_dev pointer. Fixes: f8829546f3b3 ("rue/net: init netcls traffic controller") Signed-off-by: Honglin Li <honglinli@tencent.com> Reviewed-by: Ze Gao <zegao@tencent.com>
This commit is contained in:
parent
68a7910a16
commit
26941c0f5e
|
@ -1595,8 +1595,10 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
|
|||
}
|
||||
|
||||
skb->dev = bond->dev;
|
||||
if (skb->in_dev == orig_dev)
|
||||
skb->in_dev = skb->dev;
|
||||
if (skb->in_dev == (u64)orig_dev) {
|
||||
skb->in_dev = (u64)skb->dev;
|
||||
skb->indev_ifindex = skb->dev->ifindex;
|
||||
}
|
||||
|
||||
if (BOND_MODE(bond) == BOND_MODE_ALB &&
|
||||
netif_is_bridge_port(bond->dev) &&
|
||||
|
|
|
@ -854,7 +854,8 @@ struct sk_buff {
|
|||
*/
|
||||
unsigned long dev_scratch;
|
||||
};
|
||||
struct net_device *in_dev;
|
||||
u64 in_dev;
|
||||
int indev_ifindex;
|
||||
};
|
||||
struct rb_node rbnode; /* used in netem, ip4 defrag, and tcp stack */
|
||||
struct list_head list;
|
||||
|
|
|
@ -555,8 +555,9 @@ struct sock {
|
|||
struct rcu_head sk_rcu;
|
||||
netns_tracker ns_tracker;
|
||||
struct hlist_node sk_bind2_node;
|
||||
struct net_device *in_dev;
|
||||
pid_t pid;
|
||||
pid_t pid;
|
||||
u64 in_dev;
|
||||
int indev_ifindex;
|
||||
|
||||
/*VPC INFO*/
|
||||
struct tvpc_info sk_tvpc_info;
|
||||
|
|
|
@ -5357,8 +5357,9 @@ static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,
|
|||
trace_netif_receive_skb(skb);
|
||||
|
||||
orig_dev = skb->dev;
|
||||
if (orig_dev->dev.parent && !skb->in_dev) {
|
||||
skb->in_dev = orig_dev;
|
||||
if (orig_dev->dev.parent && skb->in_dev != (u64)orig_dev) {
|
||||
skb->in_dev = (u64)orig_dev;
|
||||
skb->indev_ifindex = orig_dev->ifindex;
|
||||
skb->physical_flag = NETDEV_PHYSICAL_MAGIC;
|
||||
}
|
||||
|
||||
|
|
|
@ -1375,6 +1375,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
|||
/* We do not copy old->sk */
|
||||
new->dev = old->dev;
|
||||
new->in_dev = old->in_dev;
|
||||
new->indev_ifindex = old->indev_ifindex;
|
||||
new->physical_flag = old->physical_flag;
|
||||
memcpy(new->cb, old->cb, sizeof(old->cb));
|
||||
skb_dst_copy(new, old);
|
||||
|
|
Loading…
Reference in New Issue