[alsa-devel] [PATCH] aplay: fix lurking capture file overwrite bug
If -d was given to arecord while commit 8aa13eec80eac312e4b99423909387660fb99b8f (now reverted) was in effect, the last read would be shorter than the chunk size, but pcm_read would read and return the chunk size, the samples were discarded, and capture() continued in a loop because count never reached 0. arecord opens a new file each loop iteration, if arecord is dynamically naming files, --use-strftime option or beyond the wave 2GB limit, this will generate a series of header only wave files. If the file is unique the originally recorded data is lost and it will continue overwriting the same file with a header only wave file.
While the current pcm_read can't fail (it can exit), it is better to just fix this lurking bug in case it is "fixed" again. --- In my case I wanted to record for 16 hours, I did get the audio, but I also found I had 3.1 million 44 byte files, which took the system 3 hours to unlink, I'm glad I at least discovered this problem the next day.. Debian has the effectively broken pcm_read, after figuring out what was going wrong, and that the current arecord doesn't exhibit the problem I wanted to fix it anyway. There are remaining problems, pcm_read will read chunk_size, but if the requested size is smaller samples are lost, I'm not trying to fix that here. This will at least gracefully close a wave file (update the counts) if read or write returns a size different from requested.
aplay/aplay.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/aplay/aplay.c b/aplay/aplay.c index 7acaa83..2da7dda 100644 --- a/aplay/aplay.c +++ b/aplay/aplay.c @@ -3067,11 +3067,14 @@ static void capture(char *orig_name) size_t c = (rest <= (off64_t)chunk_bytes) ? (size_t)rest : chunk_bytes; size_t f = c * 8 / bits_per_frame; - if (pcm_read(audiobuf, f) != f) + if (pcm_read(audiobuf, f) != f) { + in_aborting = 1; break; + } if (write(fd, audiobuf, c) != c) { perror(name); - prg_exit(EXIT_FAILURE); + in_aborting = 1; + break; } count -= c; rest -= c; @@ -3091,7 +3094,7 @@ static void capture(char *orig_name) }
if (in_aborting) - break; + prg_exit(EXIT_FAILURE);
/* repeat the loop when format is raw without timelimit or * requested counts of data are recorded
On Thu, 14 Apr 2016 06:32:46 +0200, David Fries wrote:
If -d was given to arecord while commit 8aa13eec80eac312e4b99423909387660fb99b8f (now reverted) was in effect, the last read would be shorter than the chunk size, but pcm_read would read and return the chunk size, the samples were discarded, and capture() continued in a loop because count never reached 0. arecord opens a new file each loop iteration, if arecord is dynamically naming files, --use-strftime option or beyond the wave 2GB limit, this will generate a series of header only wave files. If the file is unique the originally recorded data is lost and it will continue overwriting the same file with a header only wave file.
While the current pcm_read can't fail (it can exit), it is better to just fix this lurking bug in case it is "fixed" again.
In my case I wanted to record for 16 hours, I did get the audio, but I also found I had 3.1 million 44 byte files, which took the system 3 hours to unlink, I'm glad I at least discovered this problem the next day.. Debian has the effectively broken pcm_read, after figuring out what was going wrong, and that the current arecord doesn't exhibit the problem I wanted to fix it anyway. There are remaining problems, pcm_read will read chunk_size, but if the requested size is smaller samples are lost, I'm not trying to fix that here. This will at least gracefully close a wave file (update the counts) if read or write returns a size different from requested.
Applied, thanks.
Takashi
aplay/aplay.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/aplay/aplay.c b/aplay/aplay.c index 7acaa83..2da7dda 100644 --- a/aplay/aplay.c +++ b/aplay/aplay.c @@ -3067,11 +3067,14 @@ static void capture(char *orig_name) size_t c = (rest <= (off64_t)chunk_bytes) ? (size_t)rest : chunk_bytes; size_t f = c * 8 / bits_per_frame;
if (pcm_read(audiobuf, f) != f)
if (pcm_read(audiobuf, f) != f) {
in_aborting = 1; break;
} if (write(fd, audiobuf, c) != c) { perror(name);
prg_exit(EXIT_FAILURE);
in_aborting = 1;
break; } count -= c; rest -= c;
@@ -3091,7 +3094,7 @@ static void capture(char *orig_name) }
if (in_aborting)
break;
prg_exit(EXIT_FAILURE);
/* repeat the loop when format is raw without timelimit or
- requested counts of data are recorded
-- 2.1.4
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
On Thursday 14 April 2016 05:32, David Fries wrote:
If -d was given to arecord while commit 8aa13eec80eac312e4b99423909387660fb99b8f (now reverted) was in effect, the last read would be shorter than the chunk size, but pcm_read would read and return the chunk size, the samples were discarded, and capture() continued in a loop because count never reached 0. arecord opens a new file each loop iteration, if arecord is dynamically naming files, --use-strftime option or beyond the wave 2GB limit, this will generate a series of header only wave files.
<snip>
Debian has the effectively broken pcm_read,
It is fortunate for me that you mentioned those details as I have just been bitten by exactly that, using arecord whilst tracking down a Portaudio issue in Debian Jessie! I was gearing up to report the bug, assuming it was in the capture system.
It seems a pity that Debian Jessie stable doesn't have a backport of the fix/revert.
Now back to tracing the original issue...
Regards
Alan
On Fri, Apr 15, 2016 at 09:25:37PM +0100, Alan Horstmann wrote:
On Thursday 14 April 2016 05:32, David Fries wrote:
If -d was given to arecord while commit 8aa13eec80eac312e4b99423909387660fb99b8f (now reverted) was in effect, the last read would be shorter than the chunk size, but pcm_read would read and return the chunk size, the samples were discarded, and capture() continued in a loop because count never reached 0. arecord opens a new file each loop iteration, if arecord is dynamically naming files, --use-strftime option or beyond the wave 2GB limit, this will generate a series of header only wave files.
<snip>
Debian has the effectively broken pcm_read,
It is fortunate for me that you mentioned those details as I have just been bitten by exactly that, using arecord whilst tracking down a Portaudio issue in Debian Jessie! I was gearing up to report the bug, assuming it was in the capture system.
It seems a pity that Debian Jessie stable doesn't have a backport of the fix/revert.
Glad to hear I helped.
I filed a Debian bug report with the two patches that would avoid it as Bug#821048, but it isn't going to be fixed. Denial of service is usually seen as a security issue, and this bug could run the system out of inodes, I guess it isn't seen as a high enough priority. I was able to download and compile 1.1.0-2 on Jessie which doesn't have this problem.
---------------- Please update to alsa-utils 1.1.0-2 first. In stable there will be only security patches accepted. Bug closed herewith. Backports are not maintained from us.
Elimar ----------------
Now back to tracing the original issue...
Regards
Alan _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (3)
-
Alan Horstmann
-
David Fries
-
Takashi Iwai