mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 21:24:08 +08:00
net/sched: act_bpf: validate the control action inside init()
the following script: # tc filter add dev crash0 egress matchall \ > action bpf bytecode '1,6 0 0 4294967295' pass index 90 # tc actions replace action bpf \ > bytecode '1,6 0 0 4294967295' goto chain 42 index 90 cookie c1a0c1a0 # tc action show action bpf had the following output: Error: Failed to init TC action chain. We have an error talking to the kernel total acts 1 action order 0: bpf bytecode '1,6 0 0 4294967295' default-action goto chain 42 index 90 ref 2 bind 1 cookie c1a0c1a0 Then, the first packet transmitted by crash0 made the kernel crash: RIP: 0010:tcf_action_exec+0xb8/0x100 Code: 00 00 00 20 74 1d 83 f8 03 75 09 49 83 c4 08 4d 39 ec 75 bc 48 83 c4 10 5b 5d 41 5c 41 5d 41 5e 41 5f c3 49 8b 97 a8 00 00 00 <48> 8b 12 48 89 55 00 48 83 c4 10 5b 5d 41 5c 41 5d 41 5e 41 5f c3 RSP: 0018:ffffb3a0803dfa90 EFLAGS: 00010246 RAX: 000000002000002a RBX: ffff942b347ada00 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffb3a08034d038 RDI: ffff942b347ada00 RBP: ffffb3a0803dfb30 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: ffffb3a0803dfb0c R12: ffff942b3b682b00 R13: ffff942b3b682b08 R14: 0000000000000001 R15: ffff942b3b682f00 FS: 00007f6160a72740(0000) GS:ffff942b3da80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 00000000795a4002 CR4: 00000000001606e0 Call Trace: tcf_classify+0x58/0x120 __dev_queue_xmit+0x40a/0x890 ? ip_finish_output2+0x16f/0x430 ip_finish_output2+0x16f/0x430 ? ip_output+0x69/0xe0 ip_output+0x69/0xe0 ? ip_forward_options+0x1a0/0x1a0 ip_send_skb+0x15/0x40 raw_sendmsg+0x8e1/0xbd0 ? sched_clock+0x5/0x10 ? sched_clock_cpu+0xc/0xa0 ? try_to_wake_up+0x54/0x480 ? ldsem_down_read+0x3f/0x280 ? _cond_resched+0x15/0x40 ? down_read+0xe/0x30 ? copy_termios+0x1e/0x70 ? tty_mode_ioctl+0x1b6/0x4c0 ? sock_sendmsg+0x36/0x40 sock_sendmsg+0x36/0x40 __sys_sendto+0x10e/0x140 ? do_vfs_ioctl+0xa4/0x640 ? handle_mm_fault+0xdc/0x210 ? syscall_trace_enter+0x1df/0x2e0 ? __audit_syscall_exit+0x216/0x260 __x64_sys_sendto+0x24/0x30 do_syscall_64+0x5b/0x180 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f615f7e3c03 Code: 48 8b 0d 90 62 2c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 0f 1f 44 00 00 83 3d 9d c3 2c 00 00 75 13 49 89 ca b8 2c 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 34 c3 48 83 ec 08 e8 4b cc 00 00 48 89 04 24 RSP: 002b:00007ffee5d8cc28 EFLAGS: 00000246 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 000055a4f28f1700 RCX: 00007f615f7e3c03 RDX: 0000000000000040 RSI: 000055a4f28f1700 RDI: 0000000000000003 RBP: 00007ffee5d8e340 R08: 000055a4f28ee510 R09: 0000000000000010 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000040 R13: 000055a4f28f16c0 R14: 000055a4f28ef69c R15: 0000000000000080 Modules linked in: act_bpf veth ip6table_filter ip6_tables iptable_filter binfmt_misc ext4 mbcache crct10dif_pclmul jbd2 crc32_pclmul snd_hda_codec_generic ghash_clmulni_intel snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_seq snd_seq_device snd_pcm aesni_intel crypto_simd cryptd glue_helper pcspkr joydev virtio_balloon snd_timer snd i2c_piix4 soundcore nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs ata_generic pata_acpi qxl drm_kms_helper virtio_blk virtio_net virtio_console net_failover failover syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm crc32c_intel ata_piix serio_raw libata virtio_pci virtio_ring virtio floppy dm_mirror dm_region_hash dm_log dm_mod CR2: 0000000000000000 Validating the control action within tcf_bpf_init() proved to fix the above issue. A TDC selftest is added to verify the correct behavior. Fixes:db50514f9a
("net: sched: add termination action to allow goto chain") Fixes:97763dc0f4
("net_sched: reject unknown tcfa_action values") Signed-off-by: Davide Caratti <dcaratti@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
85d0966fa5
commit
4e1810049c
@ -17,6 +17,7 @@
|
||||
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
#include <linux/tc_act/tc_bpf.h>
|
||||
#include <net/tc_act/tc_bpf.h>
|
||||
@ -282,6 +283,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
|
||||
{
|
||||
struct tc_action_net *tn = net_generic(net, bpf_net_id);
|
||||
struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
|
||||
struct tcf_chain *goto_ch = NULL;
|
||||
struct tcf_bpf_cfg cfg, old;
|
||||
struct tc_act_bpf *parm;
|
||||
struct tcf_bpf *prog;
|
||||
@ -323,12 +325,16 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
|
||||
if (ret < 0)
|
||||
goto release_idr;
|
||||
|
||||
is_bpf = tb[TCA_ACT_BPF_OPS_LEN] && tb[TCA_ACT_BPF_OPS];
|
||||
is_ebpf = tb[TCA_ACT_BPF_FD];
|
||||
|
||||
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
goto put_chain;
|
||||
}
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
@ -336,7 +342,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
|
||||
ret = is_bpf ? tcf_bpf_init_from_ops(tb, &cfg) :
|
||||
tcf_bpf_init_from_efd(tb, &cfg);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
goto put_chain;
|
||||
|
||||
prog = to_bpf(*act);
|
||||
|
||||
@ -350,10 +356,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
|
||||
if (cfg.bpf_num_ops)
|
||||
prog->bpf_num_ops = cfg.bpf_num_ops;
|
||||
|
||||
prog->tcf_action = parm->action;
|
||||
goto_ch = tcf_action_set_ctrlact(*act, parm->action, goto_ch);
|
||||
rcu_assign_pointer(prog->filter, cfg.filter);
|
||||
spin_unlock_bh(&prog->tcf_lock);
|
||||
|
||||
if (goto_ch)
|
||||
tcf_chain_put_by_act(goto_ch);
|
||||
|
||||
if (res == ACT_P_CREATED) {
|
||||
tcf_idr_insert(tn, *act);
|
||||
} else {
|
||||
@ -363,9 +372,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
|
||||
}
|
||||
|
||||
return res;
|
||||
out:
|
||||
tcf_idr_release(*act, bind);
|
||||
|
||||
put_chain:
|
||||
if (goto_ch)
|
||||
tcf_chain_put_by_act(goto_ch);
|
||||
|
||||
release_idr:
|
||||
tcf_idr_release(*act, bind);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -286,5 +286,30 @@
|
||||
"teardown": [
|
||||
"$TC action flush action bpf"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "b8a1",
|
||||
"name": "Replace bpf action with invalid goto_chain control",
|
||||
"category": [
|
||||
"actions",
|
||||
"bpf"
|
||||
],
|
||||
"setup": [
|
||||
[
|
||||
"$TC actions flush action bpf",
|
||||
0,
|
||||
1,
|
||||
255
|
||||
],
|
||||
"$TC action add action bpf bytecode '1,6 0 0 4294967295' pass index 90"
|
||||
],
|
||||
"cmdUnderTest": "$TC action replace action bpf bytecode '1,6 0 0 4294967295' goto chain 42 index 90 cookie c1a0c1a0",
|
||||
"expExitCode": "255",
|
||||
"verifyCmd": "$TC action list action bpf",
|
||||
"matchPattern": "action order [0-9]*: bpf.* default-action pass.*index 90",
|
||||
"matchCount": "1",
|
||||
"teardown": [
|
||||
"$TC action flush action bpf"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user