summaryrefslogtreecommitdiff
path: root/patches/source/squashfs-tools/0006-uptream-fix-race.patch
blob: 3cefbe5b71730e56730be6885896c593d3e2476b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
commit de03266983ceb62e5365aac84fcd3b2fd4d16e6f
Author: Phillip Lougher <phillip@squashfs.org.uk>
Date:   Thu Sep 18 01:28:11 2014 +0100

    mksquashfs: fix rare race in fragment waiting in filesystem finalisation
    
    Fix a rare race condition in fragment waiting when finalising the
    filesystem.  This is a race condition that was initially fixed in 2009,
    but inadvertantly re-introduced in the latest release when the code
    was rewritten.
    
    Background:
    
    When finalising the filesystem, the main control thread needs to ensure
    all the in-flight fragments have been queued to the writer thread before
    asking the writer thread to finish, and then writing the metadata.
    
    It does this by waiting on the fragments_outstanding counter.  Once this
    counter reaches 0, it synchronises with the writer thread, waiting until
    the writer thread reports no outstanding data to be written.
    
    However, the main thread can race with the fragment deflator thread(s)
    because the fragment deflator thread(s) decrement the fragments_outstanding
    counter and release the mutex before queueing the compressed fragment
    to the writer thread, i.e. the offending code is:
    
                            fragments_outstanding --;
                            pthread_mutex_unlock(&fragment_mutex);
                            queue_put(to_writer, write_buffer);
    
    In extremely rare circumstances, the main thread may see the
    fragments_outstanding counter is zero before the fragment
    deflator sends the fragment buffer to the writer thread, and synchronise
    with the writer thread, and finalise before the fragment has been written.
    
    The fix is to ensure the fragment is queued to the writer thread
    before releasing the mutex.
    
    Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>

diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c
index 87b7d86..f1fcff1 100644
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
@@ -2445,8 +2445,8 @@ void *frag_deflator(void *arg)
 			write_buffer->block = bytes;
 			bytes += compressed_size;
 			fragments_outstanding --;
-			pthread_mutex_unlock(&fragment_mutex);
 			queue_put(to_writer, write_buffer);
+			pthread_mutex_unlock(&fragment_mutex);
 			TRACE("Writing fragment %lld, uncompressed size %d, "
 				"compressed size %d\n", file_buffer->block,
 				file_buffer->size, compressed_size);