@@ -1935,7 +1935,8 @@ static int acct_stack_growth(struct vm_area_struct *vma,
1935
1935
* PA-RISC uses this for its stack; IA64 for its Register Backing Store.
1936
1936
* vma is the last one with address > vma->vm_end. Have to extend vma.
1937
1937
*/
1938
- int expand_upwards (struct vm_area_struct * vma , unsigned long address )
1938
+ int expand_upwards (struct vm_area_struct * vma , unsigned long address ,
1939
+ bool write_locked )
1939
1940
{
1940
1941
struct mm_struct * mm = vma -> vm_mm ;
1941
1942
struct vm_area_struct * next ;
@@ -1959,6 +1960,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
1959
1960
if (gap_addr < address || gap_addr > TASK_SIZE )
1960
1961
gap_addr = TASK_SIZE ;
1961
1962
1963
+ if (!write_locked )
1964
+ return - EAGAIN ;
1962
1965
next = find_vma_intersection (mm , vma -> vm_end , gap_addr );
1963
1966
if (next && vma_is_accessible (next )) {
1964
1967
if (!(next -> vm_flags & VM_GROWSUP ))
@@ -2028,7 +2031,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
2028
2031
/*
2029
2032
* vma is the first one with address < vma->vm_start. Have to extend vma.
2030
2033
*/
2031
- int expand_downwards (struct vm_area_struct * vma , unsigned long address )
2034
+ int expand_downwards (struct vm_area_struct * vma , unsigned long address ,
2035
+ bool write_locked )
2032
2036
{
2033
2037
struct mm_struct * mm = vma -> vm_mm ;
2034
2038
MA_STATE (mas , & mm -> mm_mt , vma -> vm_start , vma -> vm_start );
@@ -2042,10 +2046,13 @@ int expand_downwards(struct vm_area_struct *vma, unsigned long address)
2042
2046
/* Enforce stack_guard_gap */
2043
2047
prev = mas_prev (& mas , 0 );
2044
2048
/* Check that both stack segments have the same anon_vma? */
2045
- if (prev && !(prev -> vm_flags & VM_GROWSDOWN ) &&
2046
- vma_is_accessible (prev )) {
2047
- if (address - prev -> vm_end < stack_guard_gap )
2049
+ if (prev ) {
2050
+ if (!(prev -> vm_flags & VM_GROWSDOWN ) &&
2051
+ vma_is_accessible (prev ) &&
2052
+ (address - prev -> vm_end < stack_guard_gap ))
2048
2053
return - ENOMEM ;
2054
+ if (!write_locked && (prev -> vm_end == address ))
2055
+ return - EAGAIN ;
2049
2056
}
2050
2057
2051
2058
if (mas_preallocate (& mas , GFP_KERNEL ))
@@ -2124,34 +2131,40 @@ static int __init cmdline_parse_stack_guard_gap(char *p)
2124
2131
__setup ("stack_guard_gap=" , cmdline_parse_stack_guard_gap );
2125
2132
2126
2133
#ifdef CONFIG_STACK_GROWSUP
2127
- int expand_stack (struct vm_area_struct * vma , unsigned long address )
2134
+ int expand_stack_locked (struct vm_area_struct * vma , unsigned long address ,
2135
+ bool write_locked )
2128
2136
{
2129
- return expand_upwards (vma , address );
2137
+ return expand_upwards (vma , address , write_locked );
2130
2138
}
2131
2139
2132
- struct vm_area_struct *
2133
- find_extend_vma ( struct mm_struct * mm , unsigned long addr )
2140
+ struct vm_area_struct * find_extend_vma_locked ( struct mm_struct * mm ,
2141
+ unsigned long addr , bool write_locked )
2134
2142
{
2135
2143
struct vm_area_struct * vma , * prev ;
2136
2144
2137
2145
addr &= PAGE_MASK ;
2138
2146
vma = find_vma_prev (mm , addr , & prev );
2139
2147
if (vma && (vma -> vm_start <= addr ))
2140
2148
return vma ;
2141
- if (!prev || expand_stack (prev , addr ))
2149
+ if (!prev )
2150
+ return NULL ;
2151
+ if (expand_stack_locked (prev , addr , write_locked ))
2142
2152
return NULL ;
2143
2153
if (prev -> vm_flags & VM_LOCKED )
2144
2154
populate_vma_page_range (prev , addr , prev -> vm_end , NULL );
2145
2155
return prev ;
2146
2156
}
2147
2157
#else
2148
- int expand_stack (struct vm_area_struct * vma , unsigned long address )
2158
+ int expand_stack_locked (struct vm_area_struct * vma , unsigned long address ,
2159
+ bool write_locked )
2149
2160
{
2150
- return expand_downwards (vma , address );
2161
+ if (unlikely (!(vma -> vm_flags & VM_GROWSDOWN )))
2162
+ return - EINVAL ;
2163
+ return expand_downwards (vma , address , write_locked );
2151
2164
}
2152
2165
2153
- struct vm_area_struct *
2154
- find_extend_vma ( struct mm_struct * mm , unsigned long addr )
2166
+ struct vm_area_struct * find_extend_vma_locked ( struct mm_struct * mm ,
2167
+ unsigned long addr , bool write_locked )
2155
2168
{
2156
2169
struct vm_area_struct * vma ;
2157
2170
unsigned long start ;
@@ -2162,17 +2175,20 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
2162
2175
return NULL ;
2163
2176
if (vma -> vm_start <= addr )
2164
2177
return vma ;
2165
- if (!(vma -> vm_flags & VM_GROWSDOWN ))
2166
- return NULL ;
2167
2178
start = vma -> vm_start ;
2168
- if (expand_stack (vma , addr ))
2179
+ if (expand_stack_locked (vma , addr , write_locked ))
2169
2180
return NULL ;
2170
2181
if (vma -> vm_flags & VM_LOCKED )
2171
2182
populate_vma_page_range (vma , addr , start , NULL );
2172
2183
return vma ;
2173
2184
}
2174
2185
#endif
2175
2186
2187
+ struct vm_area_struct * find_extend_vma (struct mm_struct * mm ,
2188
+ unsigned long addr )
2189
+ {
2190
+ return find_extend_vma_locked (mm , addr , false);
2191
+ }
2176
2192
EXPORT_SYMBOL_GPL (find_extend_vma );
2177
2193
2178
2194
/*
0 commit comments