aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChangwei Ge <ge.changwei@h3c.com>2018-11-02 18:48:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-11-03 13:09:37 -0400
commitcf76c78595ca87548ca5e45c862ac9e0949c4687 (patch)
tree76c0ddd9b37fd5f3546d5963af21d428138f4771
parent29aa30167a0a2e6045a0d6d2e89d8168132333d5 (diff)
ocfs2: don't put and assigning null to bh allocated outside
ocfs2_read_blocks() and ocfs2_read_blocks_sync() are both used to read several blocks from disk. Currently, the input argument *bhs* can be NULL or NOT. It depends on the caller's behavior. If the function fails in reading blocks from disk, the corresponding bh will be assigned to NULL and put. Obviously, above process for non-NULL input bh is not appropriate. Because the caller doesn't even know its bhs are put and re-assigned. If buffer head is managed by caller, ocfs2_read_blocks and ocfs2_read_blocks_sync() should not evaluate it to NULL. It will cause caller accessing illegal memory, thus crash. Link: http://lkml.kernel.org/r/HK2PR06MB045285E0F4FBB561F9F2F9B3D5680@HK2PR06MB0452.apcprd06.prod.outlook.com Signed-off-by: Changwei Ge <ge.changwei@h3c.com> Reviewed-by: Guozhonghua <guozhonghua@h3c.com> Cc: Mark Fasheh <mark@fasheh.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Junxiao Bi <junxiao.bi@oracle.com> Cc: Joseph Qi <jiangqi903@gmail.com> Cc: Changwei Ge <ge.changwei@h3c.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ocfs2/buffer_head_io.c77
1 files changed, 59 insertions, 18 deletions
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
index 1d098c3c00e0..4ebbd57cbf84 100644
--- a/fs/ocfs2/buffer_head_io.c
+++ b/fs/ocfs2/buffer_head_io.c
@@ -99,25 +99,34 @@ out:
99 return ret; 99 return ret;
100} 100}
101 101
102/* Caller must provide a bhs[] with all NULL or non-NULL entries, so it
103 * will be easier to handle read failure.
104 */
102int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, 105int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
103 unsigned int nr, struct buffer_head *bhs[]) 106 unsigned int nr, struct buffer_head *bhs[])
104{ 107{
105 int status = 0; 108 int status = 0;
106 unsigned int i; 109 unsigned int i;
107 struct buffer_head *bh; 110 struct buffer_head *bh;
111 int new_bh = 0;
108 112
109 trace_ocfs2_read_blocks_sync((unsigned long long)block, nr); 113 trace_ocfs2_read_blocks_sync((unsigned long long)block, nr);
110 114
111 if (!nr) 115 if (!nr)
112 goto bail; 116 goto bail;
113 117
118 /* Don't put buffer head and re-assign it to NULL if it is allocated
119 * outside since the caller can't be aware of this alternation!
120 */
121 new_bh = (bhs[0] == NULL);
122
114 for (i = 0 ; i < nr ; i++) { 123 for (i = 0 ; i < nr ; i++) {
115 if (bhs[i] == NULL) { 124 if (bhs[i] == NULL) {
116 bhs[i] = sb_getblk(osb->sb, block++); 125 bhs[i] = sb_getblk(osb->sb, block++);
117 if (bhs[i] == NULL) { 126 if (bhs[i] == NULL) {
118 status = -ENOMEM; 127 status = -ENOMEM;
119 mlog_errno(status); 128 mlog_errno(status);
120 goto bail; 129 break;
121 } 130 }
122 } 131 }
123 bh = bhs[i]; 132 bh = bhs[i];
@@ -158,9 +167,26 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
158 submit_bh(REQ_OP_READ, 0, bh); 167 submit_bh(REQ_OP_READ, 0, bh);
159 } 168 }
160 169
170read_failure:
161 for (i = nr; i > 0; i--) { 171 for (i = nr; i > 0; i--) {
162 bh = bhs[i - 1]; 172 bh = bhs[i - 1];
163 173
174 if (unlikely(status)) {
175 if (new_bh && bh) {
176 /* If middle bh fails, let previous bh
177 * finish its read and then put it to
178 * aovoid bh leak
179 */
180 if (!buffer_jbd(bh))
181 wait_on_buffer(bh);
182 put_bh(bh);
183 bhs[i - 1] = NULL;
184 } else if (bh && buffer_uptodate(bh)) {
185 clear_buffer_uptodate(bh);
186 }
187 continue;
188 }
189
164 /* No need to wait on the buffer if it's managed by JBD. */ 190 /* No need to wait on the buffer if it's managed by JBD. */
165 if (!buffer_jbd(bh)) 191 if (!buffer_jbd(bh))
166 wait_on_buffer(bh); 192 wait_on_buffer(bh);
@@ -170,8 +196,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
170 * so we can safely record this and loop back 196 * so we can safely record this and loop back
171 * to cleanup the other buffers. */ 197 * to cleanup the other buffers. */
172 status = -EIO; 198 status = -EIO;
173 put_bh(bh); 199 goto read_failure;
174 bhs[i - 1] = NULL;
175 } 200 }
176 } 201 }
177 202
@@ -179,6 +204,9 @@ bail:
179 return status; 204 return status;
180} 205}
181 206
207/* Caller must provide a bhs[] with all NULL or non-NULL entries, so it
208 * will be easier to handle read failure.
209 */
182int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, 210int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
183 struct buffer_head *bhs[], int flags, 211 struct buffer_head *bhs[], int flags,
184 int (*validate)(struct super_block *sb, 212 int (*validate)(struct super_block *sb,
@@ -188,6 +216,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
188 int i, ignore_cache = 0; 216 int i, ignore_cache = 0;
189 struct buffer_head *bh; 217 struct buffer_head *bh;
190 struct super_block *sb = ocfs2_metadata_cache_get_super(ci); 218 struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
219 int new_bh = 0;
191 220
192 trace_ocfs2_read_blocks_begin(ci, (unsigned long long)block, nr, flags); 221 trace_ocfs2_read_blocks_begin(ci, (unsigned long long)block, nr, flags);
193 222
@@ -213,6 +242,11 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
213 goto bail; 242 goto bail;
214 } 243 }
215 244
245 /* Don't put buffer head and re-assign it to NULL if it is allocated
246 * outside since the caller can't be aware of this alternation!
247 */
248 new_bh = (bhs[0] == NULL);
249
216 ocfs2_metadata_cache_io_lock(ci); 250 ocfs2_metadata_cache_io_lock(ci);
217 for (i = 0 ; i < nr ; i++) { 251 for (i = 0 ; i < nr ; i++) {
218 if (bhs[i] == NULL) { 252 if (bhs[i] == NULL) {
@@ -221,7 +255,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
221 ocfs2_metadata_cache_io_unlock(ci); 255 ocfs2_metadata_cache_io_unlock(ci);
222 status = -ENOMEM; 256 status = -ENOMEM;
223 mlog_errno(status); 257 mlog_errno(status);
224 goto bail; 258 /* Don't forget to put previous bh! */
259 break;
225 } 260 }
226 } 261 }
227 bh = bhs[i]; 262 bh = bhs[i];
@@ -316,16 +351,27 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
316 } 351 }
317 } 352 }
318 353
319 status = 0; 354read_failure:
320
321 for (i = (nr - 1); i >= 0; i--) { 355 for (i = (nr - 1); i >= 0; i--) {
322 bh = bhs[i]; 356 bh = bhs[i];
323 357
324 if (!(flags & OCFS2_BH_READAHEAD)) { 358 if (!(flags & OCFS2_BH_READAHEAD)) {
325 if (status) { 359 if (unlikely(status)) {
326 /* Clear the rest of the buffers on error */ 360 /* Clear the buffers on error including those
327 put_bh(bh); 361 * ever succeeded in reading
328 bhs[i] = NULL; 362 */
363 if (new_bh && bh) {
364 /* If middle bh fails, let previous bh
365 * finish its read and then put it to
366 * aovoid bh leak
367 */
368 if (!buffer_jbd(bh))
369 wait_on_buffer(bh);
370 put_bh(bh);
371 bhs[i] = NULL;
372 } else if (bh && buffer_uptodate(bh)) {
373 clear_buffer_uptodate(bh);
374 }
329 continue; 375 continue;
330 } 376 }
331 /* We know this can't have changed as we hold the 377 /* We know this can't have changed as we hold the
@@ -343,9 +389,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
343 * uptodate. */ 389 * uptodate. */
344 status = -EIO; 390 status = -EIO;
345 clear_buffer_needs_validate(bh); 391 clear_buffer_needs_validate(bh);
346 put_bh(bh); 392 goto read_failure;
347 bhs[i] = NULL;
348 continue;
349 } 393 }
350 394
351 if (buffer_needs_validate(bh)) { 395 if (buffer_needs_validate(bh)) {
@@ -355,11 +399,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
355 BUG_ON(buffer_jbd(bh)); 399 BUG_ON(buffer_jbd(bh));
356 clear_buffer_needs_validate(bh); 400 clear_buffer_needs_validate(bh);
357 status = validate(sb, bh); 401 status = validate(sb, bh);
358 if (status) { 402 if (status)
359 put_bh(bh); 403 goto read_failure;
360 bhs[i] = NULL;
361 continue;
362 }
363 } 404 }
364 } 405 }
365 406