diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index c301e4cb37cacc3b77645afb265871242abac37a..d5991ac46ab0f456227f006f9c1f2c9fa5514313 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -721,7 +721,7 @@ static inline u16 exts_chan_to_edata(int ch) } static int decode_evnt(struct dp83640_private *dp83640, - void *data, u16 ests) + void *data, int len, u16 ests) { struct phy_txts *phy_txts; struct ptp_clock_event event; @@ -729,6 +729,16 @@ static int decode_evnt(struct dp83640_private *dp83640, int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK; u16 ext_status = 0; + /* calculate length of the event timestamp status message */ + if (ests & MULT_EVNT) + parsed = (words + 2) * sizeof(u16); + else + parsed = (words + 1) * sizeof(u16); + + /* check if enough data is available */ + if (len < parsed) + return len; + if (ests & MULT_EVNT) { ext_status = *(u16 *) data; data += sizeof(ext_status); @@ -747,10 +757,7 @@ static int decode_evnt(struct dp83640_private *dp83640, dp83640->edata.ns_lo = phy_txts->ns_lo; } - if (ext_status) { - parsed = words + 2; - } else { - parsed = words + 1; + if (!ext_status) { i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK) - EXT_EVENT; ext_status = exts_chan_to_edata(i); } @@ -768,7 +775,7 @@ static int decode_evnt(struct dp83640_private *dp83640, } } - return parsed * sizeof(u16); + return parsed; } static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) @@ -905,9 +912,9 @@ static void decode_status_frame(struct dp83640_private *dp83640, decode_txts(dp83640, phy_txts); size = sizeof(*phy_txts); - } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) { + } else if (PSF_EVNT == type) { - size = decode_evnt(dp83640, ptr, ests); + size = decode_evnt(dp83640, ptr, len, ests); } else { size = 0;