do_mmap () 함수
7654 단어 mmap
do_mmap () 함수
do_mmap는 주로 가상 메모리와 물리 메모리를 직접 비추는 데 쓰인다
그 핵심은 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
그 핵심 함수는 바로 이do_mmap_pgoff 함수
do_mmap_pgoff
unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff);
unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff);
unsigned long do_mmap_pgoff(struct file *file,
unsigned long addr,
unsigned long len,
unsigned long prot,
unsigned long flags,
unsigned long pgoff);
if (flags & MAP_FIXED || addr) {
printk(KERN_DEBUG "%d: Can't do fixed-address/overlay mmap of RAM
",
current->pid);
return -EINVAL;
}
if (PAGE_ALIGN(len) == 0)
return addr;
if (len > TASK_SIZE)
return -EINVAL; if (flags & MAP_FIXED || addr) {
printk(KERN_DEBUG "%d: Can't do fixed-address/overlay mmap of RAM
",
current->pid);
return -EINVAL;
}
if (PAGE_ALIGN(len) == 0)
return addr;
if (len > TASK_SIZE)
return -EINVAL;
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
return -EINVAL;
/* validate file mapping requests */
membacked = 0;
if (file) {
/* files must support mmap */
// mmap;
if (!file->f_op || !file->f_op->mmap)
return -ENODEV;
if ((prot & PROT_EXEC) &&
(file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
return -EPERM;
// ??
// memory backed , , ?
if (S_ISCHR(file->f_dentry->d_inode->i_mode)) {
membacked = 1;
}
else {
struct address_space *mapping = file->f_mapping;
if (!mapping)
mapping = file->f_dentry->d_inode->i_mapping;
if (mapping && mapping->backing_dev_info)
membacked = mapping->backing_dev_info->memory_backed;
}
// ,
if (flags & MAP_SHARED) {
/* do checks for writing, appending and locking */
if ((prot & PROT_WRITE) && !(file->f_mode & FMODE_WRITE))
return -EACCES;
if (IS_APPEND(file->f_dentry->d_inode) &&
(file->f_mode & FMODE_WRITE))
return -EACCES;
if (locks_verify_locked(file->f_dentry->d_inode))
return -EAGAIN;
if (!membacked) {
printk("MAP_SHARED not completely supported on !MMU
");
return -EINVAL;
}
if (!file->f_op->get_unmapped_area)
return -ENODEV;
}
//
else {
/* we read private files into memory we allocate */
if (!file->f_op->read)
return -ENODEV;
}
}
/* handle PROT_EXEC implication by PROT_READ */
if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
prot |= PROT_EXEC;
/* do simple checking here so the lower-level routines won't have
* to. we assume access permissions have been handled by the open
* of the memory object, so we don't do any here. */
vm_flags = calc_vm_flags(prot,flags) /* | mm->def_flags */
| VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
if (!membacked) {
/* share any file segment that's mapped read-only */
if (((flags & MAP_PRIVATE) && !(prot & PROT_WRITE) && file) ||
((flags & MAP_SHARED) && !(prot & PROT_WRITE) && file))
vm_flags |= VM_MAYSHARE;
/* refuse to let anyone share files with this process if it's being traced -
* otherwise breakpoints set in it may interfere with another untraced process
*/
if (current->ptrace & PT_PTRACED)
vm_flags &= ~(VM_SHARED | VM_MAYSHARE);
}
else {
/* permit sharing of character devices and ramfs files at any time for
* anything other than a privately writable mapping */
if (!(flags & MAP_PRIVATE) || !(prot & PROT_WRITE)) {
vm_flags |= VM_MAYSHARE;
if (flags & MAP_SHARED)
vm_flags |= VM_SHARED;
}
/* allow the security API to have its say API */
ret = _file_mmap(file, prot, flags);
if (ret)
return ret;
/* we're going to need to record the mapping if it works */
vml = kmalloc(sizeof(struct vm_list_struct), GFP_KERNEL);
if (!vml)
goto error_getting_vml;
memset(vml, 0, sizeof(*vml));
down_write(&nommu_vma_sem);
/* if we want to share, we need to search for VMAs created by another
* mmap() call that overlap with our proposed mapping
* - we can only share with an exact match on most regular files
* - shared mappings on character devices and memory backed files are
* permitted to overlap inexactly as far as we are concerned for in
* these cases, sharing is handled in the driver or filesystem rather
* than here
*/
if (vm_flags & VM_MAYSHARE) {
unsigned long pglen = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long vmpglen;
for (rb = rb_first(&nommu_vma_tree); rb; rb = rb_next(rb)) {
vma = rb_entry(rb, struct vm_area_struct, vm_rb);
if (!(vma->vm_flags & VM_MAYSHARE))
continue;
/* search for overlapping mappings on the same file */
if (vma->vm_file->f_dentry->d_inode != file->f_dentry->d_inode)
continue;
if (vma->vm_pgoff >= pgoff + pglen)
continue;
vmpglen = (vma->vm_end - vma->vm_start + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (pgoff >= vma->vm_pgoff + vmpglen)
continue;
/* handle inexact matches between mappings */
if (vmpglen != pglen || vma->vm_pgoff != pgoff) {
if (!membacked)
goto sharing_violation;
continue;
}
/* we've found a VMA we can share */
atomic_inc(&vma->vm_usage);
vml->vma = vma;
result = (void *) vma->vm_start;
goto shared;
}
}
어쨌든 기존의 권한 아래 파일을 비추도록 최선을 다하겠다고 말했다.