@@ -1945,7 +1945,8 @@ static int acct_stack_growth(struct vm_area_struct *vma,
1945
1945
* PA-RISC uses this for its stack; IA64 for its Register Backing Store.
1946
1946
* vma is the last one with address > vma->vm_end. Have to extend vma.
1947
1947
*/
1948
- int expand_upwards (struct vm_area_struct * vma , unsigned long address )
1948
+ int expand_upwards (struct vm_area_struct * vma , unsigned long address ,
1949
+ bool write_locked )
1949
1950
{
1950
1951
struct mm_struct * mm = vma -> vm_mm ;
1951
1952
struct vm_area_struct * next ;
@@ -1969,6 +1970,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
1969
1970
if (gap_addr < address || gap_addr > TASK_SIZE )
1970
1971
gap_addr = TASK_SIZE ;
1971
1972
1973
+ if (!write_locked )
1974
+ return - EAGAIN ;
1972
1975
next = find_vma_intersection (mm , vma -> vm_end , gap_addr );
1973
1976
if (next && vma_is_accessible (next )) {
1974
1977
if (!(next -> vm_flags & VM_GROWSUP ))
@@ -2037,7 +2040,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
2037
2040
/*
2038
2041
* vma is the first one with address < vma->vm_start. Have to extend vma.
2039
2042
*/
2040
- int expand_downwards (struct vm_area_struct * vma , unsigned long address )
2043
+ int expand_downwards (struct vm_area_struct * vma , unsigned long address ,
2044
+ bool write_locked )
2041
2045
{
2042
2046
struct mm_struct * mm = vma -> vm_mm ;
2043
2047
MA_STATE (mas , & mm -> mm_mt , vma -> vm_start , vma -> vm_start );
@@ -2051,10 +2055,13 @@ int expand_downwards(struct vm_area_struct *vma, unsigned long address)
2051
2055
/* Enforce stack_guard_gap */
2052
2056
prev = mas_prev (& mas , 0 );
2053
2057
/* Check that both stack segments have the same anon_vma? */
2054
- if (prev && !(prev -> vm_flags & VM_GROWSDOWN ) &&
2055
- vma_is_accessible (prev )) {
2056
- if (address - prev -> vm_end < stack_guard_gap )
2058
+ if (prev ) {
2059
+ if (!(prev -> vm_flags & VM_GROWSDOWN ) &&
2060
+ vma_is_accessible (prev ) &&
2061
+ (address - prev -> vm_end < stack_guard_gap ))
2057
2062
return - ENOMEM ;
2063
+ if (!write_locked && (prev -> vm_end == address ))
2064
+ return - EAGAIN ;
2058
2065
}
2059
2066
2060
2067
if (mas_preallocate (& mas , vma , GFP_KERNEL ))
@@ -2132,34 +2139,40 @@ static int __init cmdline_parse_stack_guard_gap(char *p)
2132
2139
__setup ("stack_guard_gap=" , cmdline_parse_stack_guard_gap );
2133
2140
2134
2141
#ifdef CONFIG_STACK_GROWSUP
2135
- int expand_stack (struct vm_area_struct * vma , unsigned long address )
2142
+ int expand_stack_locked (struct vm_area_struct * vma , unsigned long address ,
2143
+ bool write_locked )
2136
2144
{
2137
- return expand_upwards (vma , address );
2145
+ return expand_upwards (vma , address , write_locked );
2138
2146
}
2139
2147
2140
- struct vm_area_struct *
2141
- find_extend_vma ( struct mm_struct * mm , unsigned long addr )
2148
+ struct vm_area_struct * find_extend_vma_locked ( struct mm_struct * mm ,
2149
+ unsigned long addr , bool write_locked )
2142
2150
{
2143
2151
struct vm_area_struct * vma , * prev ;
2144
2152
2145
2153
addr &= PAGE_MASK ;
2146
2154
vma = find_vma_prev (mm , addr , & prev );
2147
2155
if (vma && (vma -> vm_start <= addr ))
2148
2156
return vma ;
2149
- if (!prev || expand_stack (prev , addr ))
2157
+ if (!prev )
2158
+ return NULL ;
2159
+ if (expand_stack_locked (prev , addr , write_locked ))
2150
2160
return NULL ;
2151
2161
if (prev -> vm_flags & VM_LOCKED )
2152
2162
populate_vma_page_range (prev , addr , prev -> vm_end , NULL );
2153
2163
return prev ;
2154
2164
}
2155
2165
#else
2156
- int expand_stack (struct vm_area_struct * vma , unsigned long address )
2166
+ int expand_stack_locked (struct vm_area_struct * vma , unsigned long address ,
2167
+ bool write_locked )
2157
2168
{
2158
- return expand_downwards (vma , address );
2169
+ if (unlikely (!(vma -> vm_flags & VM_GROWSDOWN )))
2170
+ return - EINVAL ;
2171
+ return expand_downwards (vma , address , write_locked );
2159
2172
}
2160
2173
2161
- struct vm_area_struct *
2162
- find_extend_vma ( struct mm_struct * mm , unsigned long addr )
2174
+ struct vm_area_struct * find_extend_vma_locked ( struct mm_struct * mm ,
2175
+ unsigned long addr , bool write_locked )
2163
2176
{
2164
2177
struct vm_area_struct * vma ;
2165
2178
unsigned long start ;
@@ -2170,17 +2183,20 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
2170
2183
return NULL ;
2171
2184
if (vma -> vm_start <= addr )
2172
2185
return vma ;
2173
- if (!(vma -> vm_flags & VM_GROWSDOWN ))
2174
- return NULL ;
2175
2186
start = vma -> vm_start ;
2176
- if (expand_stack (vma , addr ))
2187
+ if (expand_stack_locked (vma , addr , write_locked ))
2177
2188
return NULL ;
2178
2189
if (vma -> vm_flags & VM_LOCKED )
2179
2190
populate_vma_page_range (vma , addr , start , NULL );
2180
2191
return vma ;
2181
2192
}
2182
2193
#endif
2183
2194
2195
+ struct vm_area_struct * find_extend_vma (struct mm_struct * mm ,
2196
+ unsigned long addr )
2197
+ {
2198
+ return find_extend_vma_locked (mm , addr , false);
2199
+ }
2184
2200
EXPORT_SYMBOL_GPL (find_extend_vma );
2185
2201
2186
2202
/*
0 commit comments