Gavriel State gav@transgaming.com writes:
Looking at the kernel sources, it appears to be page-alignment, not filesystem block size that mmap needs to match. Rereading old wine-devel archives, it appears that the notion that the filesystem block size is involved is either from a very old kernel, or a misreading of some kernel comments.
Page alignment is needed for the address in memory, not for the offset inside the file on disk; since section virtual addresses in PE files are always page-aligned the memory address is never a problem. The only problem comes from the alignment of the data inside the PE file, and this is where we only need block-size alignment to make mmap possible.
Page alignment is needed for the address in memory, not for the offset inside the file on disk; since section virtual addresses in PE files are always page-aligned the memory address is never a problem. The only problem comes from the alignment of the data inside the PE file, and this is where we only need block-size alignment to make mmap possible.
Not so... The file offset must also be page aligned!
Try the following program:
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h>
int main(int argc, char **argv) { void *addr; int fd;
fd = open("/bin/sh",O_RDONLY); if (fd<0) { perror("mmap"); return 1; }
addr = mmap(NULL,512,PROT_READ,MAP_PRIVATE,fd,argc==1?512:4096); if (addr==MAP_FAILED) { perror("mmap"); return 1; }
return 0; }
If you don't run it with an argument, it fails (Invalid Argument), and if you do give it an argument, it works.
If you look at the kernel:
[arch/i386/kernel/sys_i386.c] asmlinkage int old_mmap(struct mmap_arg_struct *arg) { struct mmap_arg_struct a; int err = -EFAULT;
if (copy_from_user(&a, arg, sizeof(a))) goto out;
err = -EINVAL; if (a.offset & ~PAGE_MASK) goto out;
err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return err; }
Note that "a.offset" (the file offset) is checked for page alignment. Note also that the internal kernel routine do_mmap2() deals with the offset in terms of pages, not bytes.
David