aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/fs/locks.c b/fs/locks.c
index f7daa5f48949..a1e8b2248014 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -316,21 +316,22 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
316 /* POSIX-1996 leaves the case l->l_len < 0 undefined; 316 /* POSIX-1996 leaves the case l->l_len < 0 undefined;
317 POSIX-2001 defines it. */ 317 POSIX-2001 defines it. */
318 start += l->l_start; 318 start += l->l_start;
319 end = start + l->l_len - 1; 319 if (start < 0)
320 if (l->l_len < 0) { 320 return -EINVAL;
321 fl->fl_end = OFFSET_MAX;
322 if (l->l_len > 0) {
323 end = start + l->l_len - 1;
324 fl->fl_end = end;
325 } else if (l->l_len < 0) {
321 end = start - 1; 326 end = start - 1;
327 fl->fl_end = end;
322 start += l->l_len; 328 start += l->l_len;
329 if (start < 0)
330 return -EINVAL;
323 } 331 }
324
325 if (start < 0)
326 return -EINVAL;
327 if (l->l_len > 0 && end < 0)
328 return -EOVERFLOW;
329
330 fl->fl_start = start; /* we record the absolute position */ 332 fl->fl_start = start; /* we record the absolute position */
331 fl->fl_end = end; 333 if (fl->fl_end < fl->fl_start)
332 if (l->l_len == 0) 334 return -EOVERFLOW;
333 fl->fl_end = OFFSET_MAX;
334 335
335 fl->fl_owner = current->files; 336 fl->fl_owner = current->files;
336 fl->fl_pid = current->tgid; 337 fl->fl_pid = current->tgid;
@@ -362,14 +363,21 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
362 return -EINVAL; 363 return -EINVAL;
363 } 364 }
364 365
365 if (((start += l->l_start) < 0) || (l->l_len < 0)) 366 start += l->l_start;
367 if (start < 0)
366 return -EINVAL; 368 return -EINVAL;
367 fl->fl_end = start + l->l_len - 1; 369 fl->fl_end = OFFSET_MAX;
368 if (l->l_len > 0 && fl->fl_end < 0) 370 if (l->l_len > 0) {
369 return -EOVERFLOW; 371 fl->fl_end = start + l->l_len - 1;
372 } else if (l->l_len < 0) {
373 fl->fl_end = start - 1;
374 start += l->l_len;
375 if (start < 0)
376 return -EINVAL;
377 }
370 fl->fl_start = start; /* we record the absolute position */ 378 fl->fl_start = start; /* we record the absolute position */
371 if (l->l_len == 0) 379 if (fl->fl_end < fl->fl_start)
372 fl->fl_end = OFFSET_MAX; 380 return -EOVERFLOW;
373 381
374 fl->fl_owner = current->files; 382 fl->fl_owner = current->files;
375 fl->fl_pid = current->tgid; 383 fl->fl_pid = current->tgid;
@@ -829,12 +837,16 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
829 /* Detect adjacent or overlapping regions (if same lock type) 837 /* Detect adjacent or overlapping regions (if same lock type)
830 */ 838 */
831 if (request->fl_type == fl->fl_type) { 839 if (request->fl_type == fl->fl_type) {
840 /* In all comparisons of start vs end, use
841 * "start - 1" rather than "end + 1". If end
842 * is OFFSET_MAX, end + 1 will become negative.
843 */
832 if (fl->fl_end < request->fl_start - 1) 844 if (fl->fl_end < request->fl_start - 1)
833 goto next_lock; 845 goto next_lock;
834 /* If the next lock in the list has entirely bigger 846 /* If the next lock in the list has entirely bigger
835 * addresses than the new one, insert the lock here. 847 * addresses than the new one, insert the lock here.
836 */ 848 */
837 if (fl->fl_start > request->fl_end + 1) 849 if (fl->fl_start - 1 > request->fl_end)
838 break; 850 break;
839 851
840 /* If we come here, the new and old lock are of the 852 /* If we come here, the new and old lock are of the