@@ -209,6 +209,72 @@ static inline void nf_bridge_update_protocol(struct sk_buff *skb)
209209 skb -> protocol = htons (ETH_P_PPP_SES );
210210}
211211
212+ /* When handing a packet over to the IP layer
213+ * check whether we have a skb that is in the
214+ * expected format
215+ */
216+
217+ int br_parse_ip_options (struct sk_buff * skb )
218+ {
219+ struct ip_options * opt ;
220+ struct iphdr * iph ;
221+ struct net_device * dev = skb -> dev ;
222+ u32 len ;
223+
224+ iph = ip_hdr (skb );
225+ opt = & (IPCB (skb )-> opt );
226+
227+ /* Basic sanity checks */
228+ if (iph -> ihl < 5 || iph -> version != 4 )
229+ goto inhdr_error ;
230+
231+ if (!pskb_may_pull (skb , iph -> ihl * 4 ))
232+ goto inhdr_error ;
233+
234+ iph = ip_hdr (skb );
235+ if (unlikely (ip_fast_csum ((u8 * )iph , iph -> ihl )))
236+ goto inhdr_error ;
237+
238+ len = ntohs (iph -> tot_len );
239+ if (skb -> len < len ) {
240+ IP_INC_STATS_BH (dev_net (dev ), IPSTATS_MIB_INTRUNCATEDPKTS );
241+ goto drop ;
242+ } else if (len < (iph -> ihl * 4 ))
243+ goto inhdr_error ;
244+
245+ if (pskb_trim_rcsum (skb , len )) {
246+ IP_INC_STATS_BH (dev_net (dev ), IPSTATS_MIB_INDISCARDS );
247+ goto drop ;
248+ }
249+
250+ /* Zero out the CB buffer if no options present */
251+ if (iph -> ihl == 5 ) {
252+ memset (IPCB (skb ), 0 , sizeof (struct inet_skb_parm ));
253+ return 0 ;
254+ }
255+
256+ opt -> optlen = iph -> ihl * 4 - sizeof (struct iphdr );
257+ if (ip_options_compile (dev_net (dev ), opt , skb ))
258+ goto inhdr_error ;
259+
260+ /* Check correct handling of SRR option */
261+ if (unlikely (opt -> srr )) {
262+ struct in_device * in_dev = __in_dev_get_rcu (dev );
263+ if (in_dev && !IN_DEV_SOURCE_ROUTE (in_dev ))
264+ goto drop ;
265+
266+ if (ip_options_rcv_srr (skb ))
267+ goto drop ;
268+ }
269+
270+ return 0 ;
271+
272+ inhdr_error :
273+ IP_INC_STATS_BH (dev_net (dev ), IPSTATS_MIB_INHDRERRORS );
274+ drop :
275+ return -1 ;
276+ }
277+
212278/* Fill in the header for fragmented IP packets handled by
213279 * the IPv4 connection tracking code.
214280 */
@@ -549,7 +615,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
549615{
550616 struct net_bridge_port * p ;
551617 struct net_bridge * br ;
552- struct iphdr * iph ;
553618 __u32 len = nf_bridge_encap_header_len (skb );
554619
555620 if (unlikely (!pskb_may_pull (skb , len )))
@@ -578,28 +643,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
578643
579644 nf_bridge_pull_encap_header_rcsum (skb );
580645
581- if (!pskb_may_pull (skb , sizeof (struct iphdr )))
582- goto inhdr_error ;
583-
584- iph = ip_hdr (skb );
585- if (iph -> ihl < 5 || iph -> version != 4 )
586- goto inhdr_error ;
587-
588- if (!pskb_may_pull (skb , 4 * iph -> ihl ))
589- goto inhdr_error ;
590-
591- iph = ip_hdr (skb );
592- if (ip_fast_csum ((__u8 * ) iph , iph -> ihl ) != 0 )
593- goto inhdr_error ;
594-
595- len = ntohs (iph -> tot_len );
596- if (skb -> len < len || len < 4 * iph -> ihl )
597- goto inhdr_error ;
598-
599- pskb_trim_rcsum (skb , len );
600-
601- /* BUG: Should really parse the IP options here. */
602- memset (IPCB (skb ), 0 , sizeof (struct inet_skb_parm ));
646+ if (br_parse_ip_options (skb ))
647+ /* Drop invalid packet */
648+ goto out ;
603649
604650 nf_bridge_put (skb -> nf_bridge );
605651 if (!nf_bridge_alloc (skb ))
@@ -614,8 +660,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
614660
615661 return NF_STOLEN ;
616662
617- inhdr_error :
618- // IP_INC_STATS_BH(IpInHdrErrors);
619663out :
620664 return NF_DROP ;
621665}
@@ -759,14 +803,19 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb,
759803#if defined(CONFIG_NF_CONNTRACK_IPV4 ) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE )
760804static int br_nf_dev_queue_xmit (struct sk_buff * skb )
761805{
806+ int ret ;
807+
762808 if (skb -> nfct != NULL && skb -> protocol == htons (ETH_P_IP ) &&
763809 skb -> len + nf_bridge_mtu_reduction (skb ) > skb -> dev -> mtu &&
764810 !skb_is_gso (skb )) {
765- /* BUG: Should really parse the IP options here. */
766- memset (IPCB (skb ), 0 , sizeof (struct inet_skb_parm ));
767- return ip_fragment (skb , br_dev_queue_push_xmit );
811+ if (br_parse_ip_options (skb ))
812+ /* Drop invalid packet */
813+ return NF_DROP ;
814+ ret = ip_fragment (skb , br_dev_queue_push_xmit );
768815 } else
769- return br_dev_queue_push_xmit (skb );
816+ ret = br_dev_queue_push_xmit (skb );
817+
818+ return ret ;
770819}
771820#else
772821static int br_nf_dev_queue_xmit (struct sk_buff * skb )
0 commit comments