aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/act_nat.c23
-rw-r--r--net/sched/cls_flow.c96
-rw-r--r--net/sched/cls_rsvp.h12
-rw-r--r--net/sched/sch_sfq.c36
4 files changed, 106 insertions, 61 deletions
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index d0386a413e8d..509a2d53a99d 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -114,6 +114,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
114 int egress; 114 int egress;
115 int action; 115 int action;
116 int ihl; 116 int ihl;
117 int noff;
117 118
118 spin_lock(&p->tcf_lock); 119 spin_lock(&p->tcf_lock);
119 120
@@ -132,7 +133,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
132 if (unlikely(action == TC_ACT_SHOT)) 133 if (unlikely(action == TC_ACT_SHOT))
133 goto drop; 134 goto drop;
134 135
135 if (!pskb_may_pull(skb, sizeof(*iph))) 136 noff = skb_network_offset(skb);
137 if (!pskb_may_pull(skb, sizeof(*iph) + noff))
136 goto drop; 138 goto drop;
137 139
138 iph = ip_hdr(skb); 140 iph = ip_hdr(skb);
@@ -144,7 +146,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
144 146
145 if (!((old_addr ^ addr) & mask)) { 147 if (!((old_addr ^ addr) & mask)) {
146 if (skb_cloned(skb) && 148 if (skb_cloned(skb) &&
147 !skb_clone_writable(skb, sizeof(*iph)) && 149 !skb_clone_writable(skb, sizeof(*iph) + noff) &&
148 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 150 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
149 goto drop; 151 goto drop;
150 152
@@ -172,9 +174,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
172 { 174 {
173 struct tcphdr *tcph; 175 struct tcphdr *tcph;
174 176
175 if (!pskb_may_pull(skb, ihl + sizeof(*tcph)) || 177 if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) ||
176 (skb_cloned(skb) && 178 (skb_cloned(skb) &&
177 !skb_clone_writable(skb, ihl + sizeof(*tcph)) && 179 !skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) &&
178 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) 180 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
179 goto drop; 181 goto drop;
180 182
@@ -186,9 +188,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
186 { 188 {
187 struct udphdr *udph; 189 struct udphdr *udph;
188 190
189 if (!pskb_may_pull(skb, ihl + sizeof(*udph)) || 191 if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) ||
190 (skb_cloned(skb) && 192 (skb_cloned(skb) &&
191 !skb_clone_writable(skb, ihl + sizeof(*udph)) && 193 !skb_clone_writable(skb, ihl + sizeof(*udph) + noff) &&
192 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) 194 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
193 goto drop; 195 goto drop;
194 196
@@ -205,7 +207,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
205 { 207 {
206 struct icmphdr *icmph; 208 struct icmphdr *icmph;
207 209
208 if (!pskb_may_pull(skb, ihl + sizeof(*icmph))) 210 if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + noff))
209 goto drop; 211 goto drop;
210 212
211 icmph = (void *)(skb_network_header(skb) + ihl); 213 icmph = (void *)(skb_network_header(skb) + ihl);
@@ -215,7 +217,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
215 (icmph->type != ICMP_PARAMETERPROB)) 217 (icmph->type != ICMP_PARAMETERPROB))
216 break; 218 break;
217 219
218 if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph))) 220 if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph) +
221 noff))
219 goto drop; 222 goto drop;
220 223
221 icmph = (void *)(skb_network_header(skb) + ihl); 224 icmph = (void *)(skb_network_header(skb) + ihl);
@@ -229,8 +232,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
229 break; 232 break;
230 233
231 if (skb_cloned(skb) && 234 if (skb_cloned(skb) &&
232 !skb_clone_writable(skb, 235 !skb_clone_writable(skb, ihl + sizeof(*icmph) +
233 ihl + sizeof(*icmph) + sizeof(*iph)) && 236 sizeof(*iph) + noff) &&
234 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 237 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
235 goto drop; 238 goto drop;
236 239
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index f73542d2cdd0..e17096e3913c 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -65,37 +65,47 @@ static inline u32 addr_fold(void *addr)
65 return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0); 65 return (a & 0xFFFFFFFF) ^ (BITS_PER_LONG > 32 ? a >> 32 : 0);
66} 66}
67 67
68static u32 flow_get_src(const struct sk_buff *skb) 68static u32 flow_get_src(struct sk_buff *skb)
69{ 69{
70 switch (skb->protocol) { 70 switch (skb->protocol) {
71 case htons(ETH_P_IP): 71 case htons(ETH_P_IP):
72 return ntohl(ip_hdr(skb)->saddr); 72 if (pskb_network_may_pull(skb, sizeof(struct iphdr)))
73 return ntohl(ip_hdr(skb)->saddr);
74 break;
73 case htons(ETH_P_IPV6): 75 case htons(ETH_P_IPV6):
74 return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]); 76 if (pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
75 default: 77 return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]);
76 return addr_fold(skb->sk); 78 break;
77 } 79 }
80
81 return addr_fold(skb->sk);
78} 82}
79 83
80static u32 flow_get_dst(const struct sk_buff *skb) 84static u32 flow_get_dst(struct sk_buff *skb)
81{ 85{
82 switch (skb->protocol) { 86 switch (skb->protocol) {
83 case htons(ETH_P_IP): 87 case htons(ETH_P_IP):
84 return ntohl(ip_hdr(skb)->daddr); 88 if (pskb_network_may_pull(skb, sizeof(struct iphdr)))
89 return ntohl(ip_hdr(skb)->daddr);
90 break;
85 case htons(ETH_P_IPV6): 91 case htons(ETH_P_IPV6):
86 return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]); 92 if (pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
87 default: 93 return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]);
88 return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol; 94 break;
89 } 95 }
96
97 return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
90} 98}
91 99
92static u32 flow_get_proto(const struct sk_buff *skb) 100static u32 flow_get_proto(struct sk_buff *skb)
93{ 101{
94 switch (skb->protocol) { 102 switch (skb->protocol) {
95 case htons(ETH_P_IP): 103 case htons(ETH_P_IP):
96 return ip_hdr(skb)->protocol; 104 return pskb_network_may_pull(skb, sizeof(struct iphdr)) ?
105 ip_hdr(skb)->protocol : 0;
97 case htons(ETH_P_IPV6): 106 case htons(ETH_P_IPV6):
98 return ipv6_hdr(skb)->nexthdr; 107 return pskb_network_may_pull(skb, sizeof(struct ipv6hdr)) ?
108 ipv6_hdr(skb)->nexthdr : 0;
99 default: 109 default:
100 return 0; 110 return 0;
101 } 111 }
@@ -116,58 +126,64 @@ static int has_ports(u8 protocol)
116 } 126 }
117} 127}
118 128
119static u32 flow_get_proto_src(const struct sk_buff *skb) 129static u32 flow_get_proto_src(struct sk_buff *skb)
120{ 130{
121 u32 res = 0;
122
123 switch (skb->protocol) { 131 switch (skb->protocol) {
124 case htons(ETH_P_IP): { 132 case htons(ETH_P_IP): {
125 struct iphdr *iph = ip_hdr(skb); 133 struct iphdr *iph;
126 134
135 if (!pskb_network_may_pull(skb, sizeof(*iph)))
136 break;
137 iph = ip_hdr(skb);
127 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && 138 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
128 has_ports(iph->protocol)) 139 has_ports(iph->protocol) &&
129 res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4)); 140 pskb_network_may_pull(skb, iph->ihl * 4 + 2))
141 return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4));
130 break; 142 break;
131 } 143 }
132 case htons(ETH_P_IPV6): { 144 case htons(ETH_P_IPV6): {
133 struct ipv6hdr *iph = ipv6_hdr(skb); 145 struct ipv6hdr *iph;
134 146
147 if (!pskb_network_may_pull(skb, sizeof(*iph) + 2))
148 break;
149 iph = ipv6_hdr(skb);
135 if (has_ports(iph->nexthdr)) 150 if (has_ports(iph->nexthdr))
136 res = ntohs(*(__be16 *)&iph[1]); 151 return ntohs(*(__be16 *)&iph[1]);
137 break; 152 break;
138 } 153 }
139 default:
140 res = addr_fold(skb->sk);
141 } 154 }
142 155
143 return res; 156 return addr_fold(skb->sk);
144} 157}
145 158
146static u32 flow_get_proto_dst(const struct sk_buff *skb) 159static u32 flow_get_proto_dst(struct sk_buff *skb)
147{ 160{
148 u32 res = 0;
149
150 switch (skb->protocol) { 161 switch (skb->protocol) {
151 case htons(ETH_P_IP): { 162 case htons(ETH_P_IP): {
152 struct iphdr *iph = ip_hdr(skb); 163 struct iphdr *iph;
153 164
165 if (!pskb_network_may_pull(skb, sizeof(*iph)))
166 break;
167 iph = ip_hdr(skb);
154 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && 168 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
155 has_ports(iph->protocol)) 169 has_ports(iph->protocol) &&
156 res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2)); 170 pskb_network_may_pull(skb, iph->ihl * 4 + 4))
171 return ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2));
157 break; 172 break;
158 } 173 }
159 case htons(ETH_P_IPV6): { 174 case htons(ETH_P_IPV6): {
160 struct ipv6hdr *iph = ipv6_hdr(skb); 175 struct ipv6hdr *iph;
161 176
177 if (!pskb_network_may_pull(skb, sizeof(*iph) + 4))
178 break;
179 iph = ipv6_hdr(skb);
162 if (has_ports(iph->nexthdr)) 180 if (has_ports(iph->nexthdr))
163 res = ntohs(*(__be16 *)((void *)&iph[1] + 2)); 181 return ntohs(*(__be16 *)((void *)&iph[1] + 2));
164 break; 182 break;
165 } 183 }
166 default:
167 res = addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
168 } 184 }
169 185
170 return res; 186 return addr_fold(skb_dst(skb)) ^ (__force u16)skb->protocol;
171} 187}
172 188
173static u32 flow_get_iif(const struct sk_buff *skb) 189static u32 flow_get_iif(const struct sk_buff *skb)
@@ -211,7 +227,7 @@ static u32 flow_get_nfct(const struct sk_buff *skb)
211}) 227})
212#endif 228#endif
213 229
214static u32 flow_get_nfct_src(const struct sk_buff *skb) 230static u32 flow_get_nfct_src(struct sk_buff *skb)
215{ 231{
216 switch (skb->protocol) { 232 switch (skb->protocol) {
217 case htons(ETH_P_IP): 233 case htons(ETH_P_IP):
@@ -223,7 +239,7 @@ fallback:
223 return flow_get_src(skb); 239 return flow_get_src(skb);
224} 240}
225 241
226static u32 flow_get_nfct_dst(const struct sk_buff *skb) 242static u32 flow_get_nfct_dst(struct sk_buff *skb)
227{ 243{
228 switch (skb->protocol) { 244 switch (skb->protocol) {
229 case htons(ETH_P_IP): 245 case htons(ETH_P_IP):
@@ -235,14 +251,14 @@ fallback:
235 return flow_get_dst(skb); 251 return flow_get_dst(skb);
236} 252}
237 253
238static u32 flow_get_nfct_proto_src(const struct sk_buff *skb) 254static u32 flow_get_nfct_proto_src(struct sk_buff *skb)
239{ 255{
240 return ntohs(CTTUPLE(skb, src.u.all)); 256 return ntohs(CTTUPLE(skb, src.u.all));
241fallback: 257fallback:
242 return flow_get_proto_src(skb); 258 return flow_get_proto_src(skb);
243} 259}
244 260
245static u32 flow_get_nfct_proto_dst(const struct sk_buff *skb) 261static u32 flow_get_nfct_proto_dst(struct sk_buff *skb)
246{ 262{
247 return ntohs(CTTUPLE(skb, dst.u.all)); 263 return ntohs(CTTUPLE(skb, dst.u.all));
248fallback: 264fallback:
@@ -281,7 +297,7 @@ static u32 flow_get_vlan_tag(const struct sk_buff *skb)
281 return tag & VLAN_VID_MASK; 297 return tag & VLAN_VID_MASK;
282} 298}
283 299
284static u32 flow_key_get(const struct sk_buff *skb, int key) 300static u32 flow_key_get(struct sk_buff *skb, int key)
285{ 301{
286 switch (key) { 302 switch (key) {
287 case FLOW_KEY_SRC: 303 case FLOW_KEY_SRC:
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index dd9414e44200..425a1790b048 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -143,9 +143,17 @@ static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
143 u8 tunnelid = 0; 143 u8 tunnelid = 0;
144 u8 *xprt; 144 u8 *xprt;
145#if RSVP_DST_LEN == 4 145#if RSVP_DST_LEN == 4
146 struct ipv6hdr *nhptr = ipv6_hdr(skb); 146 struct ipv6hdr *nhptr;
147
148 if (!pskb_network_may_pull(skb, sizeof(*nhptr)))
149 return -1;
150 nhptr = ipv6_hdr(skb);
147#else 151#else
148 struct iphdr *nhptr = ip_hdr(skb); 152 struct iphdr *nhptr;
153
154 if (!pskb_network_may_pull(skb, sizeof(*nhptr)))
155 return -1;
156 nhptr = ip_hdr(skb);
149#endif 157#endif
150 158
151restart: 159restart:
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index c65762823f5e..534f33231c17 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -122,7 +122,11 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
122 switch (skb->protocol) { 122 switch (skb->protocol) {
123 case htons(ETH_P_IP): 123 case htons(ETH_P_IP):
124 { 124 {
125 const struct iphdr *iph = ip_hdr(skb); 125 const struct iphdr *iph;
126
127 if (!pskb_network_may_pull(skb, sizeof(*iph)))
128 goto err;
129 iph = ip_hdr(skb);
126 h = (__force u32)iph->daddr; 130 h = (__force u32)iph->daddr;
127 h2 = (__force u32)iph->saddr ^ iph->protocol; 131 h2 = (__force u32)iph->saddr ^ iph->protocol;
128 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && 132 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
@@ -131,25 +135,32 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
131 iph->protocol == IPPROTO_UDPLITE || 135 iph->protocol == IPPROTO_UDPLITE ||
132 iph->protocol == IPPROTO_SCTP || 136 iph->protocol == IPPROTO_SCTP ||
133 iph->protocol == IPPROTO_DCCP || 137 iph->protocol == IPPROTO_DCCP ||
134 iph->protocol == IPPROTO_ESP)) 138 iph->protocol == IPPROTO_ESP) &&
139 pskb_network_may_pull(skb, iph->ihl * 4 + 4))
135 h2 ^= *(((u32*)iph) + iph->ihl); 140 h2 ^= *(((u32*)iph) + iph->ihl);
136 break; 141 break;
137 } 142 }
138 case htons(ETH_P_IPV6): 143 case htons(ETH_P_IPV6):
139 { 144 {
140 struct ipv6hdr *iph = ipv6_hdr(skb); 145 struct ipv6hdr *iph;
146
147 if (!pskb_network_may_pull(skb, sizeof(*iph)))
148 goto err;
149 iph = ipv6_hdr(skb);
141 h = (__force u32)iph->daddr.s6_addr32[3]; 150 h = (__force u32)iph->daddr.s6_addr32[3];
142 h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr; 151 h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr;
143 if (iph->nexthdr == IPPROTO_TCP || 152 if ((iph->nexthdr == IPPROTO_TCP ||
144 iph->nexthdr == IPPROTO_UDP || 153 iph->nexthdr == IPPROTO_UDP ||
145 iph->nexthdr == IPPROTO_UDPLITE || 154 iph->nexthdr == IPPROTO_UDPLITE ||
146 iph->nexthdr == IPPROTO_SCTP || 155 iph->nexthdr == IPPROTO_SCTP ||
147 iph->nexthdr == IPPROTO_DCCP || 156 iph->nexthdr == IPPROTO_DCCP ||
148 iph->nexthdr == IPPROTO_ESP) 157 iph->nexthdr == IPPROTO_ESP) &&
158 pskb_network_may_pull(skb, sizeof(*iph) + 4))
149 h2 ^= *(u32*)&iph[1]; 159 h2 ^= *(u32*)&iph[1];
150 break; 160 break;
151 } 161 }
152 default: 162 default:
163err:
153 h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol; 164 h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol;
154 h2 = (unsigned long)skb->sk; 165 h2 = (unsigned long)skb->sk;
155 } 166 }
@@ -502,6 +513,12 @@ static unsigned long sfq_get(struct Qdisc *sch, u32 classid)
502 return 0; 513 return 0;
503} 514}
504 515
516static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent,
517 u32 classid)
518{
519 return 0;
520}
521
505static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl) 522static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl)
506{ 523{
507 struct sfq_sched_data *q = qdisc_priv(sch); 524 struct sfq_sched_data *q = qdisc_priv(sch);
@@ -556,6 +573,7 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
556static const struct Qdisc_class_ops sfq_class_ops = { 573static const struct Qdisc_class_ops sfq_class_ops = {
557 .get = sfq_get, 574 .get = sfq_get,
558 .tcf_chain = sfq_find_tcf, 575 .tcf_chain = sfq_find_tcf,
576 .bind_tcf = sfq_bind,
559 .dump = sfq_dump_class, 577 .dump = sfq_dump_class,
560 .dump_stats = sfq_dump_class_stats, 578 .dump_stats = sfq_dump_class_stats,
561 .walk = sfq_walk, 579 .walk = sfq_walk,