forked from Minki/linux
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: Christian Riesch <christian.riesch@omicron.at> Cc: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b4834c86e1
commit
13322f2e66
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user