Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dw-axi-dmac-platform: Avoid trampling with zero length buffer #6118

Merged
merged 2 commits into from
Apr 23, 2024

Conversation

popcornmix
Copy link
Collaborator

This code:

for_each_sg(sgl, sg, sg_len, i)
  num_sgs += DIV_ROUND_UP(sg_dma_len(sg), axi_block_len);

determines how many hw_desc are allocated.
If sg_dma_len(sg)=0 we don't allocate for this sgl.

However in the next loop, we will increment loop
for this case, and loop gets higher than num_sgs
and we trample memory.

@popcornmix
Copy link
Collaborator Author

popcornmix commented Apr 19, 2024

This is the forum bug report:

Let me test this at home.

In the office the TV signal is very low, so I wasn't able to run for long,
but I did have some seconds of playback, using 16k pagesize kernel with this PR,
compared to usual kernel panic and need to reboot.

@popcornmix popcornmix marked this pull request as ready for review April 21, 2024 11:01
@popcornmix
Copy link
Collaborator Author

Testing at home is positive.
Running on Pi5 with 16k pagesize kernel and its recording the snooker just fine.

@pelwell do you agree with my logic?

@@ -918,6 +918,9 @@ dw_axi_dma_chan_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
num_segments = DIV_ROUND_UP(sg_dma_len(sg), axi_block_len);
segment_len = DIV_ROUND_UP(sg_dma_len(sg), num_segments);
Copy link
Contributor

@pelwell pelwell Apr 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If num_segments can be zero on the next line, why didn't we get a division-by-zero error here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at a disassembly of the output, the compiler seems to have moved the (num_segments == 0) test (which should by (!num_segments) BTW) between the two DIV_ROUND_UP calls, hence the lack of an exception.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was no divide by zero exception before this PR where the num_segments == 0 protection wasn't present, nor with logging added which printed the result of the divide by zero (which was 0).
For interest, @pelwell did find:

  ARM Architecture Reference Manual, ARMv8 [ARM DDI 0487B.b]
      http://infocenter.arm.com/help/topic/com.arm.doc.ddi0487b.b/DDI0487B_b_armv8_arm.pdf
      1) aarch64 instruction set: section C3.4.7 and C6.2.279 (UDIV)
         "A division by zero results in a zero being written to
          the destination register, without any indication that
          the division by zero occurred."
      2) aarch32 instruction set: section F1.4.8 and F5.1.263 (UDIV)
         "For the SDIV and UDIV instructions, division by zero
          always returns a zero result."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The !num_segments test should go before the segment_len calculation, if only for appearances, but otherwise I agree with this commit and the reasoning behind it.

This code:
for_each_sg(sgl, sg, sg_len, i)
  num_sgs += DIV_ROUND_UP(sg_dma_len(sg), axi_block_len);

determines how many hw_desc are allocated.
If sg_dma_len(sg)=0 we don't allocate for this sgl.

However in the next loop, we will increment loop
for this case, and loop gets higher than num_sgs
and we trample memory.

Signed-off-by: Dom Cobley <popcornmix@gmail.com>
@popcornmix
Copy link
Collaborator Author

Moved the test up a line to avoid the potential divide by zero.

@pelwell pelwell merged commit 5b3c219 into raspberrypi:rpi-6.6.y Apr 23, 2024
11 of 12 checks passed
popcornmix added a commit to raspberrypi/firmware that referenced this pull request Apr 26, 2024
See: raspberrypi/linux#6113

kernel: DRM: rp1: rp1-dsi: Fix escape clock divider and timeouts
See: raspberrypi/linux#6120

kernel: vc4/hdmi: Ignore hotplug interrupt with force_hotplug
See: raspberrypi/linux#6123

kernel: drivers: media: cfe: Add remap entries for mono formats
See: raspberrypi/linux#6122

kernel: dw-axi-dmac-platform: Avoid trampling with zero length buffer
See: raspberrypi/linux#6118

kernel: Add a strict_gpiod option
See: raspberrypi/linux#6117

kernel: Unicam FS/FE timing GPIO
See: raspberrypi/linux#6088
popcornmix added a commit to raspberrypi/rpi-firmware that referenced this pull request Apr 26, 2024
See: raspberrypi/linux#6113

kernel: DRM: rp1: rp1-dsi: Fix escape clock divider and timeouts
See: raspberrypi/linux#6120

kernel: vc4/hdmi: Ignore hotplug interrupt with force_hotplug
See: raspberrypi/linux#6123

kernel: drivers: media: cfe: Add remap entries for mono formats
See: raspberrypi/linux#6122

kernel: dw-axi-dmac-platform: Avoid trampling with zero length buffer
See: raspberrypi/linux#6118

kernel: Add a strict_gpiod option
See: raspberrypi/linux#6117

kernel: Unicam FS/FE timing GPIO
See: raspberrypi/linux#6088
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants