summaryrefslogtreecommitdiff
path: root/netdissect.c
diff options
context:
space:
mode:
authorGuy Harris <gharris@sonic.net>2022-03-29 00:51:21 -0700
committerGuy Harris <gharris@sonic.net>2022-03-29 00:51:21 -0700
commitbe43281053727d9a32c479813fd0ec79bdaf2dda (patch)
treee054f7f33cd3a898f5610800015c24fb276e9bcc /netdissect.c
parent518e1bf60b5a72f29593e00a535f0a563d5d077b (diff)
downloadtcpdump-be43281053727d9a32c479813fd0ec79bdaf2dda.tar.gz
Make sure we don't set the snapend before the beginning of the packet.
If a caller attempts to set it after the current snapend, just silently ignore the attempt. If they try to set it before the beginning of the packet, report it as a bug and quit dissection. Add a new setjmp() return value meaning "bug" rather than "truncated packet", add an "nd_bug_longjmp()" routine for reporting bugs where we should quit dissecting, and use that in this case.
Diffstat (limited to 'netdissect.c')
-rw-r--r--netdissect.c61
1 files changed, 53 insertions, 8 deletions
diff --git a/netdissect.c b/netdissect.c
index 7e46d6aa..a706a6a0 100644
--- a/netdissect.c
+++ b/netdissect.c
@@ -185,9 +185,31 @@ nd_push_snapend(netdissect_options *ndo, const u_char *new_snapend)
ndspi->ndspi_snapend = ndo->ndo_snapend;
ndspi->ndspi_prev = ndo->ndo_packet_info_stack;
- /* No new packet pointer, either */
- if (new_snapend < ndo->ndo_snapend)
- ndo->ndo_snapend = new_snapend;
+ /*
+ * Make sure the new snapend is sane.
+ *
+ * If it's after the current snapend, it's not valid. We
+ * silently ignore the new setting; that means that our callers
+ * don't have to do this check themselves, and also means that
+ * if the new length is used when dissecting, we'll go past the
+ * snapend and report an error.
+ *
+ * If it's before the beginning of the packet, it's not valid.
+ * That "should not happen", but might happen with a *very*
+ * large adjustment to the snapend; our callers *should* check
+ * for that, so we fail if they haven't done so.
+ */
+ if (new_snapend <= ndo->ndo_snapend) {
+ /* Snapend isn't past the previous snapend */
+ if (new_snapend >= ndo->ndo_packetp) {
+ /* And it isn't before the beginning of the packet */
+ ndo->ndo_snapend = new_snapend;
+ } else {
+ /* But it's before the beginning of the packet */
+ ND_PRINT(" [new snapend before beginning of packet in nd_push_snapend]");
+ nd_bug_longjmp(ndo);
+ }
+ }
ndo->ndo_packet_info_stack = ndspi;
return (1); /* success */
@@ -203,14 +225,37 @@ void
nd_change_snapend(netdissect_options *ndo, const u_char *new_snapend)
{
struct netdissect_saved_packet_info *ndspi;
+ const u_char *previous_snapend;
ndspi = ndo->ndo_packet_info_stack;
- if (ndspi->ndspi_prev != NULL) {
- if (new_snapend <= ndspi->ndspi_prev->ndspi_snapend)
- ndo->ndo_snapend = new_snapend;
- } else {
- if (new_snapend < ndo->ndo_snapend)
+ if (ndspi->ndspi_prev != NULL)
+ previous_snapend = ndspi->ndspi_prev->ndspi_snapend;
+ else
+ previous_snapend = ndo->ndo_snapend;
+ /*
+ * Make sure the new snapend is sane.
+ *
+ * If it's after the current snapend, it's not valid. We
+ * silently ignore the new setting; that means that our callers
+ * don't have to do this check themselves, and also means that
+ * if the new length is used when dissecting, we'll go past the
+ * snapend and report an error.
+ *
+ * If it's before the beginning of the packet, it's not valid.
+ * That "should not happen", but might happen with a *very*
+ * large adjustment to the snapend; our callers *should* check
+ * for that, so we fail if they haven't done so.
+ */
+ if (new_snapend <= previous_snapend) {
+ /* Snapend isn't past the previous snapend */
+ if (new_snapend >= ndo->ndo_packetp) {
+ /* And it isn't before the beginning of the packet */
ndo->ndo_snapend = new_snapend;
+ } else {
+ /* But it's before the beginning of the packet */
+ ND_PRINT(" [new snapend before beginning of packet in nd_push_snapend]");
+ nd_bug_longjmp(ndo);
+ }
}
}