Skip to content

Commit 70cf3dc

Browse files
Shmulik Ladkanidavem330
authored andcommitted
net/sched: act_mirred: Pull mac prior redir to non mac_header_xmit device
There's no skb_pull performed when a mirred action is set at egress of a mac device, with a target device/action that expects skb->data to point at the network header. As a result, either the target device is errornously given an skb with data pointing to the mac (egress case), or the net stack receives the skb with data pointing to the mac (ingress case). E.g: # tc qdisc add dev eth9 root handle 1: prio # tc filter add dev eth9 parent 1: prio 9 protocol ip handle 9 basic \ action mirred egress redirect dev tun0 (tun0 is a tun device. result: tun0 errornously gets the eth header instead of the iph) Revise the push/pull logic of tcf_mirred_act() to not rely on the skb_at_tc_ingress() vs tcf_mirred_act_wants_ingress() comparison, as it does not cover all "pull" cases. Instead, calculate whether the required action on the target device requires the data to point at the network header, and compare this to whether skb->data points to network header - and make the push/pull adjustments as necessary. Fixes: 1da177e ("Linux-2.6.12-rc2") Signed-off-by: Shmulik Ladkani <[email protected]> Tested-by: Jamal Hadi Salim <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bb3d0b8 commit 70cf3dc

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

net/sched/act_mirred.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,10 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
219219
bool use_reinsert;
220220
bool want_ingress;
221221
bool is_redirect;
222+
bool expects_nh;
222223
int m_eaction;
223224
int mac_len;
225+
bool at_nh;
224226

225227
rec_level = __this_cpu_inc_return(mirred_rec_level);
226228
if (unlikely(rec_level > MIRRED_RECURSION_LIMIT)) {
@@ -261,19 +263,19 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
261263
goto out;
262264
}
263265

264-
/* If action's target direction differs than filter's direction,
265-
* and devices expect a mac header on xmit, then mac push/pull is
266-
* needed.
267-
*/
268266
want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
269-
if (skb_at_tc_ingress(skb) != want_ingress && m_mac_header_xmit) {
270-
if (!skb_at_tc_ingress(skb)) {
271-
/* caught at egress, act ingress: pull mac */
272-
mac_len = skb_network_header(skb) - skb_mac_header(skb);
267+
268+
expects_nh = want_ingress || !m_mac_header_xmit;
269+
at_nh = skb->data == skb_network_header(skb);
270+
if (at_nh != expects_nh) {
271+
mac_len = skb_at_tc_ingress(skb) ? skb->mac_len :
272+
skb_network_header(skb) - skb_mac_header(skb);
273+
if (expects_nh) {
274+
/* target device/action expect data at nh */
273275
skb_pull_rcsum(skb2, mac_len);
274276
} else {
275-
/* caught at ingress, act egress: push mac */
276-
skb_push_rcsum(skb2, skb->mac_len);
277+
/* target device/action expect data at mac */
278+
skb_push_rcsum(skb2, mac_len);
277279
}
278280
}
279281

0 commit comments

Comments
 (0)