Distribution: SLES 9 beta4 Hardware Environment: x-370 , 8way Problem Description: On executing msync system call on unmapped memory it should return a EFAULT error indicating memory (or part of it) was not mapped. The msync system call passes while synching parts of unmapped memory. Steps to reproduce: 1]Create a file test.txt of 99 bytes 2]run the program below: /*************************************************************************** * msync2.c * * Mon May 17 18:18:30 2004 * Copyright 2004 Rajeev Tiwari * rajeevti@in.ibm.com ****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <stdio.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> /* Uncomment the following line in DEBUG mode */ #define MM_DEBUG 1 void main(int argc, char * argv[]){ int file,status; char * fd; struct stat bf; char *temp; //open a file in read write mode if((file=open(argv[1],O_RDWR))==-1) { perror("error opening the file"); } //we need to get the size of the file... use fstat if((status = fstat(file,&bf))==-1) { perror("the fstat system call failed\n\n"); } //map the file to memory and get a pointer to it if((fd=(char *)mmap(NULL,bf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,file,0))==-1) { perror("mmap has failed \n\n"); } #ifdef MM_DEBUG printf("The file size is : %d\n\n",bf.st_size); #endif //write to the mapped file using memset if((temp = (char *)memset((void *)fd,'0',bf.st_size/2))==NULL) { perror("memset failed"); } else { printf("Temp first half :: %x\n", temp); } temp = temp + bf.st_size/2; if((temp = (char *)memset((void *)temp,'1',bf.st_size/2))==NULL) { perror("memset failed"); } else { printf("Temp second half :: %x\n", temp); } //call the msync call now if((status = msync((void *)fd,bf.st_size/2+OFFSET,MS_SYNC))==-1) { perror("msych has failed"); }; }//end of main -------------------------------------------------------------------------- 3]How to execute program: Expected Output: P2H8-235b:/home/test/Testing # gcc -g msync.c -o sum_test -DOFFSET=6000 sum_test.c: In function `main': sum_test.c:58: warning: comparison between pointer and integer sum_test.c:35: warning: return type of `main' is not `int' P2H8-235b:/home/test/Testing # ./msync test.txt The file size is : 99 Temp first half :: 40015000 Temp second half :: 40015031 P2H8-235b:/home/test/Testing # The above program should give a error since the OFFSET variable points to a area which lies in bss section of memory.
Created attachment 2926 [details] silly (len > vma->vm_end - start) check
the 2.6.6 code says the following- /* * If the interval [start,end) covers some unmapped address ranges, * just ignore them, but return -ENOMEM at the end. */ For a process there can be more than one vma structure in the linked list (eg a couple of mmap's , a few mallocs each will create a seperate vma structure and append it to the linked list). If the length covers more than one vma structure... then in that case msync needs to traverse all the vma structures in that range. your patch will not synch vma structures in the length range (your check is only for the first vma structure). check the for loop which traverses all the vma structures in the length range. After traversing all the vma structures the function should return a error code !
Here's another one where the test case expects failure when writing out of bounds from an existing area, but it doesn't make sure that the area it expects to fail doesn't contain something else. Here's /proc/<pid>/maps just before the msync() call. There's a valid VMA right after the "test.txt" area, so the call corectly succeeds. 08048000-08049000 r-xp 00000000 08:02 895877 /root/bugs/2728/sum_test 08049000-0804a000 rwxp 00000000 08:02 895877 /root/bugs/2728/sum_test b7ea4000-b7ea5000 rwxp b7ea4000 00:00 0 b7ea5000-b7fd5000 r-xp 00000000 08:02 410361 /lib/tls/libc-2.3.2.so b7fd5000-b7fde000 rwxp 0012f000 08:02 410361 /lib/tls/libc-2.3.2.so b7fde000-b7fe0000 rwxp b7fde000 00:00 0 b7fe7000-b7fe8000 rwxs 00000000 08:02 895879 /root/bugs/2728/test.txt b7fe8000-b7fea000 rwxp b7fe8000 00:00 0 b7fea000-b8000000 r-xp 00000000 08:02 814607 /lib/ld-2.3.2.so b8000000-b8001000 rwxp 00015000 08:02 814607 /lib/ld-2.3.2.so bffeb000-c0000000 rwxp bffeb000 00:00 0 ffffe000-fffff000 ---p 00000000 00:00 0