Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f70ee5ec8fc59ba2d905e6daf0d395edf6fb461d
Commit:     f70ee5ec8fc59ba2d905e6daf0d395edf6fb461d
Parent:     5851fadce8824d5d4b8fd02c22ae098401f6489e
Author:     J. Bruce Fields <[EMAIL PROTECTED]>
AuthorDate: Wed Mar 21 08:50:12 2007 +1100
Committer:  Herbert Xu <[EMAIL PROTECTED]>
CommitDate: Wed Mar 21 08:50:12 2007 +1100

    [CRYPTO] api: scatterwalk_copychunks() fails to advance through scatterlist
    
    In the loop in scatterwalk_copychunks(), if walk->offset is zero,
    then scatterwalk_pagedone rounds that up to the nearest page boundary:
    
                walk->offset += PAGE_SIZE - 1;
                walk->offset &= PAGE_MASK;
    
    which is a no-op in this case, so we don't advance to the next element
    of the scatterlist array:
    
                if (walk->offset >= walk->sg->offset + walk->sg->length)
                        scatterwalk_start(walk, sg_next(walk->sg));
    
    and we end up copying the same data twice.
    
    It appears that other callers of scatterwalk_{page}done first advance
    walk->offset, so I believe that's the correct thing to do here.
    
    This caused a bug in NFS when run with krb5p security, which would
    cause some writes to fail with permissions errors--for example, writes
    of less than 8 bytes (the des blocksize) at the start of a file.
    
    A git-bisect shows the bug was originally introduced by
    5c64097aa0f6dc4f27718ef47ca9a12538d62860, first in 2.6.19-rc1.
    
    Signed-off-by: "J. Bruce Fields" <[EMAIL PROTECTED]>
    Signed-off-by: Herbert Xu <[EMAIL PROTECTED]>
---
 crypto/scatterwalk.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index 35172d3..a664231 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -91,6 +91,8 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk 
*walk,
                memcpy_dir(buf, vaddr, len_this_page, out);
                scatterwalk_unmap(vaddr, out);
 
+               scatterwalk_advance(walk, nbytes);
+
                if (nbytes == len_this_page)
                        break;
 
@@ -99,7 +101,5 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk 
*walk,
 
                scatterwalk_pagedone(walk, out, 1);
        }
-
-       scatterwalk_advance(walk, nbytes);
 }
 EXPORT_SYMBOL_GPL(scatterwalk_copychunks);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to