Commit 13322f2e authored by Christian Riesch's avatar Christian Riesch Committed by David S. Miller

dp83640: Fix length check for event timestamp status messages

Event timestamp status messages have a variable length, ranging from
1 to 5 words (16 bit words). The current code however requires
a minimum message length of sizeof(*phy_txts). In most cases this
condition is fulfilled due to padding bytes. However, if several events
are signaled in a single message, padding bytes may not be present.
For short event timestamp status messages, the length check will fail,
and the event timestamp will be dropped.
Signed-off-by: default avatarChristian Riesch <christian.riesch@omicron.at>
Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b4834c86
...@@ -721,7 +721,7 @@ static inline u16 exts_chan_to_edata(int ch) ...@@ -721,7 +721,7 @@ static inline u16 exts_chan_to_edata(int ch)
} }
static int decode_evnt(struct dp83640_private *dp83640, static int decode_evnt(struct dp83640_private *dp83640,
void *data, u16 ests) void *data, int len, u16 ests)
{ {
struct phy_txts *phy_txts; struct phy_txts *phy_txts;
struct ptp_clock_event event; struct ptp_clock_event event;
...@@ -729,6 +729,16 @@ static int decode_evnt(struct dp83640_private *dp83640, ...@@ -729,6 +729,16 @@ static int decode_evnt(struct dp83640_private *dp83640,
int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK; int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK;
u16 ext_status = 0; 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) { if (ests & MULT_EVNT) {
ext_status = *(u16 *) data; ext_status = *(u16 *) data;
data += sizeof(ext_status); data += sizeof(ext_status);
...@@ -747,10 +757,7 @@ static int decode_evnt(struct dp83640_private *dp83640, ...@@ -747,10 +757,7 @@ static int decode_evnt(struct dp83640_private *dp83640,
dp83640->edata.ns_lo = phy_txts->ns_lo; dp83640->edata.ns_lo = phy_txts->ns_lo;
} }
if (ext_status) { if (!ext_status) {
parsed = words + 2;
} else {
parsed = words + 1;
i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK) - EXT_EVENT; i = ((ests >> EVNT_NUM_SHIFT) & EVNT_NUM_MASK) - EXT_EVENT;
ext_status = exts_chan_to_edata(i); ext_status = exts_chan_to_edata(i);
} }
...@@ -768,7 +775,7 @@ static int decode_evnt(struct dp83640_private *dp83640, ...@@ -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) 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, ...@@ -905,9 +912,9 @@ static void decode_status_frame(struct dp83640_private *dp83640,
decode_txts(dp83640, phy_txts); decode_txts(dp83640, phy_txts);
size = sizeof(*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 { } else {
size = 0; size = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment