|
|
1.1 ! root 1: /* ! 2: * linux/mm/mmap.c ! 3: * ! 4: * Written by obz. ! 5: */ ! 6: #include <sys/stat.h> ! 7: #include <linux/sched.h> ! 8: #include <linux/kernel.h> ! 9: #include <asm/segment.h> ! 10: #include <asm/system.h> ! 11: #include <errno.h> ! 12: #include <sys/mman.h> ! 13: ! 14: /* ! 15: * description of effects of mapping type and prot in current implementation. ! 16: * this is due to the current handling of page faults in memory.c. the expected ! 17: * behavior is in parens: ! 18: * ! 19: * map_type prot ! 20: * PROT_NONE PROT_READ PROT_WRITE PROT_EXEC ! 21: * MAP_SHARED r: (no) yes r: (yes) yes r: (no) yes r: (no) no ! 22: * w: (no) yes w: (no) copy w: (yes) yes w: (no) no ! 23: * x: (no) no x: (no) no x: (no) no x: (yes) no ! 24: * ! 25: * MAP_PRIVATE r: (no) yes r: (yes) yes r: (no) yes r: (no) no ! 26: * w: (no) copy w: (no) copy w: (copy) copy w: (no) no ! 27: * x: (no) no x: (no) no x: (no) no x: (yes) no ! 28: * ! 29: * the permissions are encoded as cxwr (copy,exec,write,read) ! 30: */ ! 31: #define MTYP(T) ((T) & MAP_TYPE) ! 32: #define PREAD(T,P) (((P) & PROT_READ) ? 1 : 0) ! 33: #define PWRITE(T,P) (((P) & PROT_WRITE) ? (MTYP(T) == MAP_SHARED ? 2 : 10) : 0) ! 34: #define PEXEC(T,P) (((P) & PROT_EXEC) ? 4 : 0) ! 35: #define PERMISS(T,P) (PREAD(T,P)|PWRITE(T,P)|PEXEC(T,P)) ! 36: ! 37: #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \ ! 38: current->start_code + current->end_code) ! 39: ! 40: extern int remap_page_range(unsigned long from, unsigned long to, ! 41: unsigned long size, int permiss); ! 42: extern int unmap_page_range(unsigned long from, unsigned long size); ! 43: ! 44: static caddr_t ! 45: mmap_chr(unsigned long addr, size_t len, int prot, int flags, ! 46: struct inode *inode, unsigned long off) ! 47: { ! 48: int major, minor; ! 49: extern unsigned long HIGH_MEMORY; ! 50: ! 51: major = MAJOR(inode->i_rdev); ! 52: minor = MINOR(inode->i_rdev); ! 53: ! 54: /* ! 55: * for character devices, only /dev/mem may be mapped. when the ! 56: * swapping code is modified to allow arbitrary sources of pages, ! 57: * then we can open it up to regular files. ! 58: */ ! 59: ! 60: if (major != 1 || minor != 1) ! 61: return (caddr_t)-ENODEV; ! 62: ! 63: /* ! 64: * we only allow mappings from address 0 to HIGH_MEMORY, since thats ! 65: * the range of our memory [actually this is a lie. the buffer cache ! 66: * and ramdisk occupy higher memory, but the paging stuff won't ! 67: * let us map to it anyway, so we break it here]. ! 68: * ! 69: * this call is very dangerous! because of the lack of adequate ! 70: * tagging of frames, it is possible to mmap over a frame belonging ! 71: * to another (innocent) process. with MAP_SHARED|MAP_WRITE, this ! 72: * rogue process can trample over the other's data! we ignore this :{ ! 73: * for now, we hope people will malloc the required amount of space, ! 74: * then mmap over it. the mm needs serious work before this can be ! 75: * truly useful. ! 76: */ ! 77: ! 78: if (len > HIGH_MEMORY || off > HIGH_MEMORY - len) /* avoid overflow */ ! 79: return (caddr_t)-ENXIO; ! 80: ! 81: if (remap_page_range(addr, off, len, PERMISS(flags, prot))) ! 82: return (caddr_t)-EAGAIN; ! 83: ! 84: return (caddr_t)addr; ! 85: } ! 86: ! 87: caddr_t ! 88: sys_mmap(unsigned long *buffer) ! 89: { ! 90: unsigned long base, addr; ! 91: unsigned long len, limit, off; ! 92: int prot, flags, fd; ! 93: struct file *file; ! 94: struct inode *inode; ! 95: ! 96: addr = (unsigned long) get_fs_long(buffer); /* user address space*/ ! 97: len = (size_t) get_fs_long(buffer+1); /* nbytes of mapping */ ! 98: prot = (int) get_fs_long(buffer+2); /* protection */ ! 99: flags = (int) get_fs_long(buffer+3); /* mapping type */ ! 100: fd = (int) get_fs_long(buffer+4); /* object to map */ ! 101: off = (unsigned long) get_fs_long(buffer+5); /* offset in object */ ! 102: ! 103: if (fd >= NR_OPEN || fd < 0 || !(file = current->filp[fd])) ! 104: return (caddr_t) -EBADF; ! 105: if (addr > TASK_SIZE || (addr+(unsigned long) len) > TASK_SIZE) ! 106: return (caddr_t) -EINVAL; ! 107: inode = file->f_inode; ! 108: ! 109: /* ! 110: * do simple checking here so the lower-level routines won't have ! 111: * to. we assume access permissions have been handled by the open ! 112: * of the memory object, so we don't do any here. ! 113: */ ! 114: ! 115: switch (flags & MAP_TYPE) { ! 116: case MAP_SHARED: ! 117: if ((prot & PROT_WRITE) && !(file->f_mode & 2)) ! 118: return (caddr_t)-EINVAL; ! 119: /* fall through */ ! 120: case MAP_PRIVATE: ! 121: if (!(file->f_mode & 1)) ! 122: return (caddr_t)-EINVAL; ! 123: break; ! 124: ! 125: default: ! 126: return (caddr_t)-EINVAL; ! 127: } ! 128: ! 129: /* ! 130: * obtain the address to map to. we verify (or select) it and ensure ! 131: * that it represents a valid section of the address space. we assume ! 132: * that if PROT_EXEC is specified this should be in the code segment. ! 133: */ ! 134: if (prot & PROT_EXEC) { ! 135: base = get_base(current->ldt[1]); /* cs */ ! 136: limit = get_limit(0x0f); /* cs limit */ ! 137: } else { ! 138: base = get_base(current->ldt[2]); /* ds */ ! 139: limit = get_limit(0x17); /* ds limit */ ! 140: } ! 141: ! 142: if (flags & MAP_FIXED) { ! 143: /* ! 144: * if MAP_FIXED is specified, we have to map exactly at this ! 145: * address. it must be page aligned and not ambiguous. ! 146: */ ! 147: if ((addr & 0xfff) || addr > 0x7fffffff || addr == 0 || ! 148: (off & 0xfff)) ! 149: return (caddr_t)-EINVAL; ! 150: if (addr + len > limit) ! 151: return (caddr_t)-ENOMEM; ! 152: } else { ! 153: /* ! 154: * we're given a hint as to where to put the address. ! 155: * that we still need to search for a range of pages which ! 156: * are not mapped and which won't impact the stack or data ! 157: * segment. ! 158: * in linux, we only have a code segment and data segment. ! 159: * since data grows up and stack grows down, we're sort of ! 160: * stuck. placing above the data will break malloc, below ! 161: * the stack will cause stack overflow. because of this ! 162: * we don't allow nonspecified mappings... ! 163: */ ! 164: return (caddr_t)-ENOMEM; ! 165: } ! 166: ! 167: /* ! 168: * determine the object being mapped and call the appropriate ! 169: * specific mapper. the address has already been validated, but ! 170: * not unmapped ! 171: */ ! 172: if (S_ISCHR(inode->i_mode)) ! 173: addr = (unsigned long)mmap_chr(base + addr, len, prot, flags, ! 174: inode, off); ! 175: else ! 176: addr = (unsigned long)-ENODEV; ! 177: if ((long)addr > 0) ! 178: addr -= base; ! 179: ! 180: return (caddr_t)addr; ! 181: } ! 182: ! 183: int sys_munmap(unsigned long addr, size_t len) ! 184: { ! 185: unsigned long base, limit; ! 186: ! 187: base = get_base(current->ldt[2]); /* map into ds */ ! 188: limit = get_limit(0x17); /* ds limit */ ! 189: ! 190: if ((addr & 0xfff) || addr > 0x7fffffff || addr == 0 || ! 191: addr + len > limit) ! 192: return -EINVAL; ! 193: if (unmap_page_range(base + addr, len)) ! 194: return -EAGAIN; /* should never happen */ ! 195: return 0; ! 196: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.