| /* IBM Corporation */ |
| /* 01/02/2003 Port to LTP avenkat@us.ibm.com */ |
| /* 06/30/2001 Port to Linux nsharoff@us.ibm.com */ |
| |
| /* |
| * Copyright (c) International Business Machines Corp., 2003 |
| * |
| * |
| * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* uiomove_phys_fail: |
| * Test a copyout/copyin failure in the kernel primitive uiomove_phys by |
| * reading into or writing from a mmaped regular file which lacks the |
| * needed permissions. |
| */ |
| |
| #include <sys/types.h> |
| #include <sys/mman.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <signal.h> |
| #include <errno.h> |
| #include <stdio.h> |
| |
| extern time_t time(time_t *); |
| extern char *ctime(const time_t *); |
| extern void exit(int); |
| |
| #define ERROR(M) (void)fprintf(stderr, "%s: errno = %d; " M "\n", \ |
| argv[0], errno) |
| #define CLEANERROR(M) (void)unlink(tmpname); ERROR(M) |
| #define CATCH_SIG(SIG) \ |
| if (sigaction(SIG, &sa, 0) == -1) { \ |
| ERROR("couldn't catch signal " #SIG); \ |
| exit(1); \ |
| } |
| |
| static char tmpname[] = "fileXXXXXX"; |
| static int fd; |
| /***** LTP Port *****/ |
| #include "test.h" |
| #include "usctest.h" |
| #define FAILED 0 |
| #define PASSED 1 |
| |
| int local_flag = PASSED; |
| char *TCID = "mmapstress02"; //uiomove_phys_fail |
| FILE *temp; |
| int TST_TOTAL = 1; |
| |
| int anyfail(); |
| void ok_exit(); |
| /***** ** ** *****/ |
| |
| /*ARGSUSED*/ static |
| void cleanup(int sig) |
| { |
| /* |
| * Don't check error codes - we could be signaled before the file is |
| * created. |
| */ |
| (void)close(fd); |
| (void)unlink(tmpname); |
| tst_rmdir(); |
| tst_exit(); |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| caddr_t mmapaddr; |
| size_t pagesize = sysconf(_SC_PAGE_SIZE); |
| time_t t; |
| int i; |
| struct sigaction sa; |
| |
| tst_tmpdir(); |
| if (!argc) { |
| (void)fprintf(stderr, "argc == 0\n"); |
| return 1; |
| } |
| if (argc != 1) { |
| (void)fprintf(stderr, "usage: %s\n", argv[0]); |
| return 1; |
| } |
| (void)time(&t); |
| if ((fd = mkstemp(tmpname)) == -1) { |
| ERROR("mkstemp failed"); |
| anyfail(); |
| } |
| sa.sa_handler = cleanup; |
| sa.sa_flags = 0; |
| if (sigemptyset(&sa.sa_mask)) { |
| ERROR("sigemptyset failed"); |
| anyfail(); |
| } |
| CATCH_SIG(SIGINT); |
| CATCH_SIG(SIGQUIT); |
| CATCH_SIG(SIGTERM); |
| if (sbrk(2 * pagesize - ((ulong) sbrk(0) & (pagesize - 1))) == |
| (char *)-1) { |
| CLEANERROR("couldn't round up brk"); |
| anyfail(); |
| } |
| if ((mmapaddr = sbrk(0)) == (caddr_t) - 1) { |
| CLEANERROR("couldn't find top of brk"); |
| anyfail(); |
| } |
| /* Write a page of garbage into the file, so we can mmap it without |
| * asking for PROT_WRITE. |
| */ |
| for (i = pagesize; i; i--) |
| *(mmapaddr - i) = 'a'; |
| if (write(fd, (char *)mmapaddr - pagesize, pagesize) != pagesize) { |
| CLEANERROR("write failed"); |
| anyfail(); |
| } |
| if (mmap(mmapaddr, pagesize, PROT_NONE, |
| MAP_FIXED | MAP_PRIVATE | MAP_FILE, fd, 0) != mmapaddr) { |
| CLEANERROR("couldn't mmap file"); |
| anyfail(); |
| } |
| /* |
| * Since the file is mmapped, mmreg_new and uiomove_phys handle all |
| * I/O |
| */ |
| if (lseek(fd, 0, SEEK_SET) != 0) { |
| CLEANERROR("lseek failed"); |
| anyfail(); |
| } |
| if (read(fd, (char *)mmapaddr, pagesize) != -1) { |
| CLEANERROR("read succeded"); |
| anyfail(); |
| } |
| if (errno != EFAULT) { |
| CLEANERROR("read didn't set errno = EFAULT"); |
| anyfail(); |
| } |
| if (write(fd, (char *)mmapaddr, pagesize) != -1) { |
| CLEANERROR("write succeded"); |
| anyfail(); |
| } |
| if (errno != EFAULT) { |
| CLEANERROR("write didn't set errno = EFAULT"); |
| anyfail(); |
| } |
| if (close(fd) == -1) { |
| CLEANERROR("close failed"); |
| anyfail(); |
| } |
| if (munmap(mmapaddr, pagesize) == -1) { |
| CLEANERROR("munmap failed"); |
| anyfail(); |
| } |
| if (unlink(tmpname) == -1) { |
| ERROR("unlink failed"); |
| anyfail(); |
| } |
| (void)time(&t); |
| // (void)printf("%s: Finished %s", argv[0], ctime(&t)); |
| ok_exit(); /* LTP Port */ |
| tst_exit(); |
| } |
| |
| /***** LTP Port *****/ |
| void ok_exit() |
| { |
| tst_resm(TPASS, "Test passed\n"); |
| tst_rmdir(); |
| tst_exit(); |
| } |
| |
| int anyfail() |
| { |
| tst_brkm(TFAIL, tst_rmdir, "Test failed"); |
| } |
| |
| /***** ** ** *****/ |