1 #include <linux/errno.h>
2 #include <linux/sched.h>
3 #include <linux/syscalls.h>
10 #include <linux/stat.h>
11 #include <linux/mman.h>
12 #include <linux/file.h>
13 #include <linux/utsname.h>
14 #include <linux/personality.h>
15 #include <linux/random.h>
16 #include <linux/uaccess.h>
19 #include <asm/syscalls.h>
21 asmlinkage
long sys_mmap(unsigned long addr
, unsigned long len
,
22 unsigned long prot
, unsigned long flags
,
23 unsigned long fd
, unsigned long off
)
34 flags
&= ~(MAP_EXECUTABLE
| MAP_DENYWRITE
);
35 if (!(flags
& MAP_ANONYMOUS
)) {
40 down_write(¤t
->mm
->mmap_sem
);
41 error
= do_mmap_pgoff(file
, addr
, len
, prot
, flags
, off
>> PAGE_SHIFT
);
42 up_write(¤t
->mm
->mmap_sem
);
50 static void find_start_end(unsigned long flags
, unsigned long *begin
,
53 if (!test_thread_flag(TIF_IA32
) && (flags
& MAP_32BIT
)) {
54 unsigned long new_begin
;
55 /* This is usually used needed to map code in small
56 model, so it needs to be in the first 31bit. Limit
57 it to that. This means we need to move the
58 unmapped base down for this case. This can give
59 conflicts with the heap, but we assume that glibc
60 malloc knows how to fall back to mmap. Give it 1GB
61 of playground for now. -AK */
64 if (current
->flags
& PF_RANDOMIZE
) {
65 new_begin
= randomize_range(*begin
, *begin
+ 0x02000000, 0);
70 *begin
= TASK_UNMAPPED_BASE
;
76 arch_get_unmapped_area(struct file
*filp
, unsigned long addr
,
77 unsigned long len
, unsigned long pgoff
, unsigned long flags
)
79 struct mm_struct
*mm
= current
->mm
;
80 struct vm_area_struct
*vma
;
81 unsigned long start_addr
;
82 unsigned long begin
, end
;
84 if (flags
& MAP_FIXED
)
87 find_start_end(flags
, &begin
, &end
);
93 addr
= PAGE_ALIGN(addr
);
94 vma
= find_vma(mm
, addr
);
95 if (end
- len
>= addr
&&
96 (!vma
|| addr
+ len
<= vma
->vm_start
))
99 if (((flags
& MAP_32BIT
) || test_thread_flag(TIF_IA32
))
100 && len
<= mm
->cached_hole_size
) {
101 mm
->cached_hole_size
= 0;
102 mm
->free_area_cache
= begin
;
104 addr
= mm
->free_area_cache
;
110 for (vma
= find_vma(mm
, addr
); ; vma
= vma
->vm_next
) {
111 /* At this point: (!vma || addr < vma->vm_end). */
112 if (end
- len
< addr
) {
114 * Start a new search - just in case we missed
117 if (start_addr
!= begin
) {
118 start_addr
= addr
= begin
;
119 mm
->cached_hole_size
= 0;
124 if (!vma
|| addr
+ len
<= vma
->vm_start
) {
126 * Remember the place where we stopped the search:
128 mm
->free_area_cache
= addr
+ len
;
131 if (addr
+ mm
->cached_hole_size
< vma
->vm_start
)
132 mm
->cached_hole_size
= vma
->vm_start
- addr
;
140 arch_get_unmapped_area_topdown(struct file
*filp
, const unsigned long addr0
,
141 const unsigned long len
, const unsigned long pgoff
,
142 const unsigned long flags
)
144 struct vm_area_struct
*vma
;
145 struct mm_struct
*mm
= current
->mm
;
146 unsigned long addr
= addr0
;
148 /* requested length too big for entire address space */
152 if (flags
& MAP_FIXED
)
155 /* for MAP_32BIT mappings we force the legact mmap base */
156 if (!test_thread_flag(TIF_IA32
) && (flags
& MAP_32BIT
))
159 /* requesting a specific address */
161 addr
= PAGE_ALIGN(addr
);
162 vma
= find_vma(mm
, addr
);
163 if (TASK_SIZE
- len
>= addr
&&
164 (!vma
|| addr
+ len
<= vma
->vm_start
))
168 /* check if free_area_cache is useful for us */
169 if (len
<= mm
->cached_hole_size
) {
170 mm
->cached_hole_size
= 0;
171 mm
->free_area_cache
= mm
->mmap_base
;
174 /* either no address requested or can't fit in requested address hole */
175 addr
= mm
->free_area_cache
;
177 /* make sure it can fit in the remaining address space */
179 vma
= find_vma(mm
, addr
-len
);
180 if (!vma
|| addr
<= vma
->vm_start
)
181 /* remember the address as a hint for next time */
182 return mm
->free_area_cache
= addr
-len
;
185 if (mm
->mmap_base
< len
)
188 addr
= mm
->mmap_base
-len
;
192 * Lookup failure means no vma is above this address,
193 * else if new region fits below vma->vm_start,
194 * return with success:
196 vma
= find_vma(mm
, addr
);
197 if (!vma
|| addr
+len
<= vma
->vm_start
)
198 /* remember the address as a hint for next time */
199 return mm
->free_area_cache
= addr
;
201 /* remember the largest hole we saw so far */
202 if (addr
+ mm
->cached_hole_size
< vma
->vm_start
)
203 mm
->cached_hole_size
= vma
->vm_start
- addr
;
205 /* try just below the current vma->vm_start */
206 addr
= vma
->vm_start
-len
;
207 } while (len
< vma
->vm_start
);
211 * A failed mmap() very likely causes application failure,
212 * so fall back to the bottom-up function here. This scenario
213 * can happen with large stack limits and large mmap()
216 mm
->cached_hole_size
= ~0UL;
217 mm
->free_area_cache
= TASK_UNMAPPED_BASE
;
218 addr
= arch_get_unmapped_area(filp
, addr0
, len
, pgoff
, flags
);
220 * Restore the topdown base:
222 mm
->free_area_cache
= mm
->mmap_base
;
223 mm
->cached_hole_size
= ~0UL;
229 asmlinkage
long sys_uname(struct new_utsname __user
*name
)
233 err
= copy_to_user(name
, utsname(), sizeof(*name
));
235 if (personality(current
->personality
) == PER_LINUX32
)
236 err
|= copy_to_user(&name
->machine
, "i686", 5);
237 return err
? -EFAULT
: 0;