aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/locks.c100
-rw-r--r--include/uapi/asm-generic/fcntl.h3
2 files changed, 32 insertions, 71 deletions
diff --git a/fs/locks.c b/fs/locks.c
index dd309333afc9..b49e853a9c7b 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -344,48 +344,43 @@ static int assign_type(struct file_lock *fl, long type)
344 return 0; 344 return 0;
345} 345}
346 346
347/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX 347static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
348 * style lock. 348 struct flock64 *l)
349 */
350static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
351 struct flock *l)
352{ 349{
353 off_t start, end;
354
355 switch (l->l_whence) { 350 switch (l->l_whence) {
356 case SEEK_SET: 351 case SEEK_SET:
357 start = 0; 352 fl->fl_start = 0;
358 break; 353 break;
359 case SEEK_CUR: 354 case SEEK_CUR:
360 start = filp->f_pos; 355 fl->fl_start = filp->f_pos;
361 break; 356 break;
362 case SEEK_END: 357 case SEEK_END:
363 start = i_size_read(file_inode(filp)); 358 fl->fl_start = i_size_read(file_inode(filp));
364 break; 359 break;
365 default: 360 default:
366 return -EINVAL; 361 return -EINVAL;
367 } 362 }
363 if (l->l_start > OFFSET_MAX - fl->fl_start)
364 return -EOVERFLOW;
365 fl->fl_start += l->l_start;
366 if (fl->fl_start < 0)
367 return -EINVAL;
368 368
369 /* POSIX-1996 leaves the case l->l_len < 0 undefined; 369 /* POSIX-1996 leaves the case l->l_len < 0 undefined;
370 POSIX-2001 defines it. */ 370 POSIX-2001 defines it. */
371 start += l->l_start;
372 if (start < 0)
373 return -EINVAL;
374 fl->fl_end = OFFSET_MAX;
375 if (l->l_len > 0) { 371 if (l->l_len > 0) {
376 end = start + l->l_len - 1; 372 if (l->l_len - 1 > OFFSET_MAX - fl->fl_start)
377 fl->fl_end = end; 373 return -EOVERFLOW;
374 fl->fl_end = fl->fl_start + l->l_len - 1;
375
378 } else if (l->l_len < 0) { 376 } else if (l->l_len < 0) {
379 end = start - 1; 377 if (fl->fl_start + l->l_len < 0)
380 fl->fl_end = end;
381 start += l->l_len;
382 if (start < 0)
383 return -EINVAL; 378 return -EINVAL;
384 } 379 fl->fl_end = fl->fl_start - 1;
385 fl->fl_start = start; /* we record the absolute position */ 380 fl->fl_start += l->l_len;
386 if (fl->fl_end < fl->fl_start) 381 } else
387 return -EOVERFLOW; 382 fl->fl_end = OFFSET_MAX;
388 383
389 fl->fl_owner = current->files; 384 fl->fl_owner = current->files;
390 fl->fl_pid = current->tgid; 385 fl->fl_pid = current->tgid;
391 fl->fl_file = filp; 386 fl->fl_file = filp;
@@ -396,52 +391,21 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
396 return assign_type(fl, l->l_type); 391 return assign_type(fl, l->l_type);
397} 392}
398 393
399#if BITS_PER_LONG == 32 394/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
400static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, 395 * style lock.
401 struct flock64 *l) 396 */
397static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
398 struct flock *l)
402{ 399{
403 loff_t start; 400 struct flock64 ll = {
404 401 .l_type = l->l_type,
405 switch (l->l_whence) { 402 .l_whence = l->l_whence,
406 case SEEK_SET: 403 .l_start = l->l_start,
407 start = 0; 404 .l_len = l->l_len,
408 break; 405 };
409 case SEEK_CUR:
410 start = filp->f_pos;
411 break;
412 case SEEK_END:
413 start = i_size_read(file_inode(filp));
414 break;
415 default:
416 return -EINVAL;
417 }
418 406
419 start += l->l_start; 407 return flock64_to_posix_lock(filp, fl, &ll);
420 if (start < 0)
421 return -EINVAL;
422 fl->fl_end = OFFSET_MAX;
423 if (l->l_len > 0) {
424 fl->fl_end = start + l->l_len - 1;
425 } else if (l->l_len < 0) {
426 fl->fl_end = start - 1;
427 start += l->l_len;
428 if (start < 0)
429 return -EINVAL;
430 }
431 fl->fl_start = start; /* we record the absolute position */
432 if (fl->fl_end < fl->fl_start)
433 return -EOVERFLOW;
434
435 fl->fl_owner = current->files;
436 fl->fl_pid = current->tgid;
437 fl->fl_file = filp;
438 fl->fl_flags = FL_POSIX;
439 fl->fl_ops = NULL;
440 fl->fl_lmops = NULL;
441
442 return assign_type(fl, l->l_type);
443} 408}
444#endif
445 409
446/* default lease lock manager operations */ 410/* default lease lock manager operations */
447static void lease_break_callback(struct file_lock *fl) 411static void lease_break_callback(struct file_lock *fl)
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
index 95e46c8e05f9..36025f77c6ed 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -186,8 +186,6 @@ struct flock {
186}; 186};
187#endif 187#endif
188 188
189#ifndef CONFIG_64BIT
190
191#ifndef HAVE_ARCH_STRUCT_FLOCK64 189#ifndef HAVE_ARCH_STRUCT_FLOCK64
192#ifndef __ARCH_FLOCK64_PAD 190#ifndef __ARCH_FLOCK64_PAD
193#define __ARCH_FLOCK64_PAD 191#define __ARCH_FLOCK64_PAD
@@ -202,6 +200,5 @@ struct flock64 {
202 __ARCH_FLOCK64_PAD 200 __ARCH_FLOCK64_PAD
203}; 201};
204#endif 202#endif
205#endif /* !CONFIG_64BIT */
206 203
207#endif /* _ASM_GENERIC_FCNTL_H */ 204#endif /* _ASM_GENERIC_FCNTL_H */