Skip to content

Commit 8c7ae38

Browse files
dhowellstorvalds
authored andcommitted
afs: Fix StoreData op marshalling
The marshalling of AFS.StoreData, AFS.StoreData64 and YFS.StoreData64 calls generated by ->setattr() ops for the purpose of expanding a file is incorrect due to older documentation incorrectly describing the way the RPC 'FileLength' parameter is meant to work. The older documentation says that this is the length the file is meant to end up at the end of the operation; however, it was never implemented this way in any of the servers, but rather the file is truncated down to this before the write operation is effected, and never expanded to it (and, indeed, it was renamed to 'TruncPos' in 2014). Fix this by setting the position parameter to the new file length and doing a zero-lengh write there. The bug causes Xwayland to SIGBUS due to unexpected non-expansion of a file it then mmaps. This can be tested by giving the following test program a filename in an AFS directory: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> int main(int argc, char *argv[]) { char *p; int fd; if (argc != 2) { fprintf(stderr, "Format: test-trunc-mmap <file>\n"); exit(2); } fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC); if (fd < 0) { perror(argv[1]); exit(1); } if (ftruncate(fd, 0x140008) == -1) { perror("ftruncate"); exit(1); } p = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (p == MAP_FAILED) { perror("mmap"); exit(1); } p[0] = 'a'; if (munmap(p, 4096) < 0) { perror("munmap"); exit(1); } if (close(fd) < 0) { perror("close"); exit(1); } exit(0); } Fixes: 31143d5 ("AFS: implement basic file write support") Reported-by: Jonathan Billings <jsbillin@umich.edu> Tested-by: Jonathan Billings <jsbillin@umich.edu> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 7d6ab82 commit 8c7ae38

File tree

2 files changed

+4
-4
lines changed

2 files changed

+4
-4
lines changed

fs/afs/fsclient.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,8 +1515,8 @@ static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr)
15151515

15161516
xdr_encode_AFS_StoreStatus(&bp, attr);
15171517

1518-
*bp++ = 0; /* position of start of write */
1519-
*bp++ = 0;
1518+
*bp++ = htonl(attr->ia_size >> 32); /* position of start of write */
1519+
*bp++ = htonl((u32) attr->ia_size);
15201520
*bp++ = 0; /* size of write */
15211521
*bp++ = 0;
15221522
*bp++ = htonl(attr->ia_size >> 32); /* new file length */
@@ -1564,7 +1564,7 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
15641564

15651565
xdr_encode_AFS_StoreStatus(&bp, attr);
15661566

1567-
*bp++ = 0; /* position of start of write */
1567+
*bp++ = htonl(attr->ia_size); /* position of start of write */
15681568
*bp++ = 0; /* size of write */
15691569
*bp++ = htonl(attr->ia_size); /* new file length */
15701570

fs/afs/yfsclient.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1514,7 +1514,7 @@ static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr)
15141514
bp = xdr_encode_u32(bp, 0); /* RPC flags */
15151515
bp = xdr_encode_YFSFid(bp, &vnode->fid);
15161516
bp = xdr_encode_YFS_StoreStatus(bp, attr);
1517-
bp = xdr_encode_u64(bp, 0); /* position of start of write */
1517+
bp = xdr_encode_u64(bp, attr->ia_size); /* position of start of write */
15181518
bp = xdr_encode_u64(bp, 0); /* size of write */
15191519
bp = xdr_encode_u64(bp, attr->ia_size); /* new file length */
15201520
yfs_check_req(call, bp);

0 commit comments

Comments
 (0)