diff options
-rw-r--r-- | MAINTAINERS | 3 | ||||
-rw-r--r-- | arch/arm/kernel/sys_oabi-compat.c | 3 | ||||
-rw-r--r-- | fs/compat.c | 35 | ||||
-rw-r--r-- | fs/fcntl.c | 37 | ||||
-rw-r--r-- | fs/file_table.c | 2 | ||||
-rw-r--r-- | fs/locks.c | 389 | ||||
-rw-r--r-- | fs/namei.c | 2 | ||||
-rw-r--r-- | include/linux/fs.h | 43 | ||||
-rw-r--r-- | include/uapi/asm-generic/fcntl.h | 19 | ||||
-rw-r--r-- | mm/mmap.c | 2 | ||||
-rw-r--r-- | mm/nommu.c | 2 | ||||
-rw-r--r-- | security/selinux/hooks.c | 3 |
12 files changed, 356 insertions, 184 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8774f7974d69..f728ac2b298a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3521,7 +3521,8 @@ F: include/scsi/libfcoe.h | |||
3521 | F: include/uapi/scsi/fc/ | 3521 | F: include/uapi/scsi/fc/ |
3522 | 3522 | ||
3523 | FILE LOCKING (flock() and fcntl()/lockf()) | 3523 | FILE LOCKING (flock() and fcntl()/lockf()) |
3524 | M: Matthew Wilcox <matthew@wil.cx> | 3524 | M: Jeff Layton <jlayton@redhat.com> |
3525 | M: J. Bruce Fields <bfields@fieldses.org> | ||
3525 | L: linux-fsdevel@vger.kernel.org | 3526 | L: linux-fsdevel@vger.kernel.org |
3526 | S: Maintained | 3527 | S: Maintained |
3527 | F: include/linux/fcntl.h | 3528 | F: include/linux/fcntl.h |
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index 3e94811690ce..702bd329d9d0 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c | |||
@@ -203,6 +203,9 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, | |||
203 | int ret; | 203 | int ret; |
204 | 204 | ||
205 | switch (cmd) { | 205 | switch (cmd) { |
206 | case F_GETLKP: | ||
207 | case F_SETLKP: | ||
208 | case F_SETLKPW: | ||
206 | case F_GETLK64: | 209 | case F_GETLK64: |
207 | case F_SETLK64: | 210 | case F_SETLK64: |
208 | case F_SETLKW64: | 211 | case F_SETLKW64: |
diff --git a/fs/compat.c b/fs/compat.c index f86df85dff61..ca926ad0430c 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -399,12 +399,28 @@ static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *u | |||
399 | } | 399 | } |
400 | #endif | 400 | #endif |
401 | 401 | ||
402 | static unsigned int | ||
403 | convert_fcntl_cmd(unsigned int cmd) | ||
404 | { | ||
405 | switch (cmd) { | ||
406 | case F_GETLK64: | ||
407 | return F_GETLK; | ||
408 | case F_SETLK64: | ||
409 | return F_SETLK; | ||
410 | case F_SETLKW64: | ||
411 | return F_SETLKW; | ||
412 | } | ||
413 | |||
414 | return cmd; | ||
415 | } | ||
416 | |||
402 | COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | 417 | COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, |
403 | compat_ulong_t, arg) | 418 | compat_ulong_t, arg) |
404 | { | 419 | { |
405 | mm_segment_t old_fs; | 420 | mm_segment_t old_fs; |
406 | struct flock f; | 421 | struct flock f; |
407 | long ret; | 422 | long ret; |
423 | unsigned int conv_cmd; | ||
408 | 424 | ||
409 | switch (cmd) { | 425 | switch (cmd) { |
410 | case F_GETLK: | 426 | case F_GETLK: |
@@ -441,16 +457,18 @@ COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | |||
441 | case F_GETLK64: | 457 | case F_GETLK64: |
442 | case F_SETLK64: | 458 | case F_SETLK64: |
443 | case F_SETLKW64: | 459 | case F_SETLKW64: |
460 | case F_GETLKP: | ||
461 | case F_SETLKP: | ||
462 | case F_SETLKPW: | ||
444 | ret = get_compat_flock64(&f, compat_ptr(arg)); | 463 | ret = get_compat_flock64(&f, compat_ptr(arg)); |
445 | if (ret != 0) | 464 | if (ret != 0) |
446 | break; | 465 | break; |
447 | old_fs = get_fs(); | 466 | old_fs = get_fs(); |
448 | set_fs(KERNEL_DS); | 467 | set_fs(KERNEL_DS); |
449 | ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK : | 468 | conv_cmd = convert_fcntl_cmd(cmd); |
450 | ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW), | 469 | ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f); |
451 | (unsigned long)&f); | ||
452 | set_fs(old_fs); | 470 | set_fs(old_fs); |
453 | if (cmd == F_GETLK64 && ret == 0) { | 471 | if ((conv_cmd == F_GETLK || conv_cmd == F_GETLKP) && ret == 0) { |
454 | /* need to return lock information - see above for commentary */ | 472 | /* need to return lock information - see above for commentary */ |
455 | if (f.l_start > COMPAT_LOFF_T_MAX) | 473 | if (f.l_start > COMPAT_LOFF_T_MAX) |
456 | ret = -EOVERFLOW; | 474 | ret = -EOVERFLOW; |
@@ -471,8 +489,15 @@ COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | |||
471 | COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, | 489 | COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, |
472 | compat_ulong_t, arg) | 490 | compat_ulong_t, arg) |
473 | { | 491 | { |
474 | if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64)) | 492 | switch (cmd) { |
493 | case F_GETLK64: | ||
494 | case F_SETLK64: | ||
495 | case F_SETLKW64: | ||
496 | case F_GETLKP: | ||
497 | case F_SETLKP: | ||
498 | case F_SETLKPW: | ||
475 | return -EINVAL; | 499 | return -EINVAL; |
500 | } | ||
476 | return compat_sys_fcntl64(fd, cmd, arg); | 501 | return compat_sys_fcntl64(fd, cmd, arg); |
477 | } | 502 | } |
478 | 503 | ||
diff --git a/fs/fcntl.c b/fs/fcntl.c index ef6866592a0f..9ead1596399a 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -272,9 +272,19 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
272 | case F_SETFL: | 272 | case F_SETFL: |
273 | err = setfl(fd, filp, arg); | 273 | err = setfl(fd, filp, arg); |
274 | break; | 274 | break; |
275 | #if BITS_PER_LONG != 32 | ||
276 | /* 32-bit arches must use fcntl64() */ | ||
277 | case F_GETLKP: | ||
278 | #endif | ||
275 | case F_GETLK: | 279 | case F_GETLK: |
276 | err = fcntl_getlk(filp, (struct flock __user *) arg); | 280 | err = fcntl_getlk(filp, cmd, (struct flock __user *) arg); |
277 | break; | 281 | break; |
282 | #if BITS_PER_LONG != 32 | ||
283 | /* 32-bit arches must use fcntl64() */ | ||
284 | case F_SETLKP: | ||
285 | case F_SETLKPW: | ||
286 | #endif | ||
287 | /* Fallthrough */ | ||
278 | case F_SETLK: | 288 | case F_SETLK: |
279 | case F_SETLKW: | 289 | case F_SETLKW: |
280 | err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg); | 290 | err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg); |
@@ -388,17 +398,20 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | |||
388 | goto out1; | 398 | goto out1; |
389 | 399 | ||
390 | switch (cmd) { | 400 | switch (cmd) { |
391 | case F_GETLK64: | 401 | case F_GETLK64: |
392 | err = fcntl_getlk64(f.file, (struct flock64 __user *) arg); | 402 | case F_GETLKP: |
393 | break; | 403 | err = fcntl_getlk64(f.file, cmd, (struct flock64 __user *) arg); |
394 | case F_SETLK64: | 404 | break; |
395 | case F_SETLKW64: | 405 | case F_SETLK64: |
396 | err = fcntl_setlk64(fd, f.file, cmd, | 406 | case F_SETLKW64: |
397 | (struct flock64 __user *) arg); | 407 | case F_SETLKP: |
398 | break; | 408 | case F_SETLKPW: |
399 | default: | 409 | err = fcntl_setlk64(fd, f.file, cmd, |
400 | err = do_fcntl(fd, cmd, arg, f.file); | 410 | (struct flock64 __user *) arg); |
401 | break; | 411 | break; |
412 | default: | ||
413 | err = do_fcntl(fd, cmd, arg, f.file); | ||
414 | break; | ||
402 | } | 415 | } |
403 | out1: | 416 | out1: |
404 | fdput(f); | 417 | fdput(f); |
diff --git a/fs/file_table.c b/fs/file_table.c index 5b24008ea4f6..01071c4d752e 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -235,7 +235,7 @@ static void __fput(struct file *file) | |||
235 | * in the file cleanup chain. | 235 | * in the file cleanup chain. |
236 | */ | 236 | */ |
237 | eventpoll_release(file); | 237 | eventpoll_release(file); |
238 | locks_remove_flock(file); | 238 | locks_remove_file(file); |
239 | 239 | ||
240 | if (unlikely(file->f_flags & FASYNC)) { | 240 | if (unlikely(file->f_flags & FASYNC)) { |
241 | if (file->f_op->fasync) | 241 | if (file->f_op->fasync) |
diff --git a/fs/locks.c b/fs/locks.c index 92a0f0a52b06..13fc7a6d380a 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -135,6 +135,7 @@ | |||
135 | #define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) | 135 | #define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) |
136 | #define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK) | 136 | #define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK) |
137 | #define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG)) | 137 | #define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG)) |
138 | #define IS_FILE_PVT(fl) (fl->fl_flags & FL_FILE_PVT) | ||
138 | 139 | ||
139 | static bool lease_breaking(struct file_lock *fl) | 140 | static bool lease_breaking(struct file_lock *fl) |
140 | { | 141 | { |
@@ -344,48 +345,43 @@ static int assign_type(struct file_lock *fl, long type) | |||
344 | return 0; | 345 | return 0; |
345 | } | 346 | } |
346 | 347 | ||
347 | /* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX | 348 | static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, |
348 | * style lock. | 349 | struct flock64 *l) |
349 | */ | ||
350 | static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, | ||
351 | struct flock *l) | ||
352 | { | 350 | { |
353 | off_t start, end; | ||
354 | |||
355 | switch (l->l_whence) { | 351 | switch (l->l_whence) { |
356 | case SEEK_SET: | 352 | case SEEK_SET: |
357 | start = 0; | 353 | fl->fl_start = 0; |
358 | break; | 354 | break; |
359 | case SEEK_CUR: | 355 | case SEEK_CUR: |
360 | start = filp->f_pos; | 356 | fl->fl_start = filp->f_pos; |
361 | break; | 357 | break; |
362 | case SEEK_END: | 358 | case SEEK_END: |
363 | start = i_size_read(file_inode(filp)); | 359 | fl->fl_start = i_size_read(file_inode(filp)); |
364 | break; | 360 | break; |
365 | default: | 361 | default: |
366 | return -EINVAL; | 362 | return -EINVAL; |
367 | } | 363 | } |
364 | if (l->l_start > OFFSET_MAX - fl->fl_start) | ||
365 | return -EOVERFLOW; | ||
366 | fl->fl_start += l->l_start; | ||
367 | if (fl->fl_start < 0) | ||
368 | return -EINVAL; | ||
368 | 369 | ||
369 | /* POSIX-1996 leaves the case l->l_len < 0 undefined; | 370 | /* POSIX-1996 leaves the case l->l_len < 0 undefined; |
370 | POSIX-2001 defines it. */ | 371 | 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) { | 372 | if (l->l_len > 0) { |
376 | end = start + l->l_len - 1; | 373 | if (l->l_len - 1 > OFFSET_MAX - fl->fl_start) |
377 | fl->fl_end = end; | 374 | return -EOVERFLOW; |
375 | fl->fl_end = fl->fl_start + l->l_len - 1; | ||
376 | |||
378 | } else if (l->l_len < 0) { | 377 | } else if (l->l_len < 0) { |
379 | end = start - 1; | 378 | 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; | 379 | return -EINVAL; |
384 | } | 380 | fl->fl_end = fl->fl_start - 1; |
385 | fl->fl_start = start; /* we record the absolute position */ | 381 | fl->fl_start += l->l_len; |
386 | if (fl->fl_end < fl->fl_start) | 382 | } else |
387 | return -EOVERFLOW; | 383 | fl->fl_end = OFFSET_MAX; |
388 | 384 | ||
389 | fl->fl_owner = current->files; | 385 | fl->fl_owner = current->files; |
390 | fl->fl_pid = current->tgid; | 386 | fl->fl_pid = current->tgid; |
391 | fl->fl_file = filp; | 387 | fl->fl_file = filp; |
@@ -393,55 +389,36 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, | |||
393 | fl->fl_ops = NULL; | 389 | fl->fl_ops = NULL; |
394 | fl->fl_lmops = NULL; | 390 | fl->fl_lmops = NULL; |
395 | 391 | ||
396 | return assign_type(fl, l->l_type); | 392 | /* Ensure that fl->fl_filp has compatible f_mode */ |
397 | } | 393 | switch (l->l_type) { |
398 | 394 | case F_RDLCK: | |
399 | #if BITS_PER_LONG == 32 | 395 | if (!(filp->f_mode & FMODE_READ)) |
400 | static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, | 396 | return -EBADF; |
401 | struct flock64 *l) | ||
402 | { | ||
403 | loff_t start; | ||
404 | |||
405 | switch (l->l_whence) { | ||
406 | case SEEK_SET: | ||
407 | start = 0; | ||
408 | break; | ||
409 | case SEEK_CUR: | ||
410 | start = filp->f_pos; | ||
411 | break; | 397 | break; |
412 | case SEEK_END: | 398 | case F_WRLCK: |
413 | start = i_size_read(file_inode(filp)); | 399 | if (!(filp->f_mode & FMODE_WRITE)) |
400 | return -EBADF; | ||
414 | break; | 401 | break; |
415 | default: | ||
416 | return -EINVAL; | ||
417 | } | 402 | } |
418 | 403 | ||
419 | start += l->l_start; | ||
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); | 404 | return assign_type(fl, l->l_type); |
443 | } | 405 | } |
444 | #endif | 406 | |
407 | /* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX | ||
408 | * style lock. | ||
409 | */ | ||
410 | static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, | ||
411 | struct flock *l) | ||
412 | { | ||
413 | struct flock64 ll = { | ||
414 | .l_type = l->l_type, | ||
415 | .l_whence = l->l_whence, | ||
416 | .l_start = l->l_start, | ||
417 | .l_len = l->l_len, | ||
418 | }; | ||
419 | |||
420 | return flock64_to_posix_lock(filp, fl, &ll); | ||
421 | } | ||
445 | 422 | ||
446 | /* default lease lock manager operations */ | 423 | /* default lease lock manager operations */ |
447 | static void lease_break_callback(struct file_lock *fl) | 424 | static void lease_break_callback(struct file_lock *fl) |
@@ -511,8 +488,7 @@ static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2) | |||
511 | } | 488 | } |
512 | 489 | ||
513 | /* Must be called with the i_lock held! */ | 490 | /* Must be called with the i_lock held! */ |
514 | static inline void | 491 | static void locks_insert_global_locks(struct file_lock *fl) |
515 | locks_insert_global_locks(struct file_lock *fl) | ||
516 | { | 492 | { |
517 | lg_local_lock(&file_lock_lglock); | 493 | lg_local_lock(&file_lock_lglock); |
518 | fl->fl_link_cpu = smp_processor_id(); | 494 | fl->fl_link_cpu = smp_processor_id(); |
@@ -521,8 +497,7 @@ locks_insert_global_locks(struct file_lock *fl) | |||
521 | } | 497 | } |
522 | 498 | ||
523 | /* Must be called with the i_lock held! */ | 499 | /* Must be called with the i_lock held! */ |
524 | static inline void | 500 | static void locks_delete_global_locks(struct file_lock *fl) |
525 | locks_delete_global_locks(struct file_lock *fl) | ||
526 | { | 501 | { |
527 | /* | 502 | /* |
528 | * Avoid taking lock if already unhashed. This is safe since this check | 503 | * Avoid taking lock if already unhashed. This is safe since this check |
@@ -544,14 +519,12 @@ posix_owner_key(struct file_lock *fl) | |||
544 | return (unsigned long)fl->fl_owner; | 519 | return (unsigned long)fl->fl_owner; |
545 | } | 520 | } |
546 | 521 | ||
547 | static inline void | 522 | static void locks_insert_global_blocked(struct file_lock *waiter) |
548 | locks_insert_global_blocked(struct file_lock *waiter) | ||
549 | { | 523 | { |
550 | hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter)); | 524 | hash_add(blocked_hash, &waiter->fl_link, posix_owner_key(waiter)); |
551 | } | 525 | } |
552 | 526 | ||
553 | static inline void | 527 | static void locks_delete_global_blocked(struct file_lock *waiter) |
554 | locks_delete_global_blocked(struct file_lock *waiter) | ||
555 | { | 528 | { |
556 | hash_del(&waiter->fl_link); | 529 | hash_del(&waiter->fl_link); |
557 | } | 530 | } |
@@ -581,7 +554,7 @@ static void locks_delete_block(struct file_lock *waiter) | |||
581 | * it seems like the reasonable thing to do. | 554 | * it seems like the reasonable thing to do. |
582 | * | 555 | * |
583 | * Must be called with both the i_lock and blocked_lock_lock held. The fl_block | 556 | * Must be called with both the i_lock and blocked_lock_lock held. The fl_block |
584 | * list itself is protected by the file_lock_list, but by ensuring that the | 557 | * list itself is protected by the blocked_lock_lock, but by ensuring that the |
585 | * i_lock is also held on insertions we can avoid taking the blocked_lock_lock | 558 | * i_lock is also held on insertions we can avoid taking the blocked_lock_lock |
586 | * in some cases when we see that the fl_block list is empty. | 559 | * in some cases when we see that the fl_block list is empty. |
587 | */ | 560 | */ |
@@ -591,7 +564,7 @@ static void __locks_insert_block(struct file_lock *blocker, | |||
591 | BUG_ON(!list_empty(&waiter->fl_block)); | 564 | BUG_ON(!list_empty(&waiter->fl_block)); |
592 | waiter->fl_next = blocker; | 565 | waiter->fl_next = blocker; |
593 | list_add_tail(&waiter->fl_block, &blocker->fl_block); | 566 | list_add_tail(&waiter->fl_block, &blocker->fl_block); |
594 | if (IS_POSIX(blocker)) | 567 | if (IS_POSIX(blocker) && !IS_FILE_PVT(blocker)) |
595 | locks_insert_global_blocked(waiter); | 568 | locks_insert_global_blocked(waiter); |
596 | } | 569 | } |
597 | 570 | ||
@@ -652,15 +625,18 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) | |||
652 | locks_insert_global_locks(fl); | 625 | locks_insert_global_locks(fl); |
653 | } | 626 | } |
654 | 627 | ||
655 | /* | 628 | /** |
656 | * Delete a lock and then free it. | 629 | * locks_delete_lock - Delete a lock and then free it. |
657 | * Wake up processes that are blocked waiting for this lock, | 630 | * @thisfl_p: pointer that points to the fl_next field of the previous |
658 | * notify the FS that the lock has been cleared and | 631 | * inode->i_flock list entry |
659 | * finally free the lock. | 632 | * |
633 | * Unlink a lock from all lists and free the namespace reference, but don't | ||
634 | * free it yet. Wake up processes that are blocked waiting for this lock and | ||
635 | * notify the FS that the lock has been cleared. | ||
660 | * | 636 | * |
661 | * Must be called with the i_lock held! | 637 | * Must be called with the i_lock held! |
662 | */ | 638 | */ |
663 | static void locks_delete_lock(struct file_lock **thisfl_p) | 639 | static void locks_unlink_lock(struct file_lock **thisfl_p) |
664 | { | 640 | { |
665 | struct file_lock *fl = *thisfl_p; | 641 | struct file_lock *fl = *thisfl_p; |
666 | 642 | ||
@@ -675,6 +651,18 @@ static void locks_delete_lock(struct file_lock **thisfl_p) | |||
675 | } | 651 | } |
676 | 652 | ||
677 | locks_wake_up_blocks(fl); | 653 | locks_wake_up_blocks(fl); |
654 | } | ||
655 | |||
656 | /* | ||
657 | * Unlink a lock from all lists and free it. | ||
658 | * | ||
659 | * Must be called with i_lock held! | ||
660 | */ | ||
661 | static void locks_delete_lock(struct file_lock **thisfl_p) | ||
662 | { | ||
663 | struct file_lock *fl = *thisfl_p; | ||
664 | |||
665 | locks_unlink_lock(thisfl_p); | ||
678 | locks_free_lock(fl); | 666 | locks_free_lock(fl); |
679 | } | 667 | } |
680 | 668 | ||
@@ -769,8 +757,16 @@ EXPORT_SYMBOL(posix_test_lock); | |||
769 | * Note: the above assumption may not be true when handling lock | 757 | * Note: the above assumption may not be true when handling lock |
770 | * requests from a broken NFS client. It may also fail in the presence | 758 | * requests from a broken NFS client. It may also fail in the presence |
771 | * of tasks (such as posix threads) sharing the same open file table. | 759 | * of tasks (such as posix threads) sharing the same open file table. |
772 | * | ||
773 | * To handle those cases, we just bail out after a few iterations. | 760 | * To handle those cases, we just bail out after a few iterations. |
761 | * | ||
762 | * For FL_FILE_PVT locks, the owner is the filp, not the files_struct. | ||
763 | * Because the owner is not even nominally tied to a thread of | ||
764 | * execution, the deadlock detection below can't reasonably work well. Just | ||
765 | * skip it for those. | ||
766 | * | ||
767 | * In principle, we could do a more limited deadlock detection on FL_FILE_PVT | ||
768 | * locks that just checks for the case where two tasks are attempting to | ||
769 | * upgrade from read to write locks on the same inode. | ||
774 | */ | 770 | */ |
775 | 771 | ||
776 | #define MAX_DEADLK_ITERATIONS 10 | 772 | #define MAX_DEADLK_ITERATIONS 10 |
@@ -793,6 +789,13 @@ static int posix_locks_deadlock(struct file_lock *caller_fl, | |||
793 | { | 789 | { |
794 | int i = 0; | 790 | int i = 0; |
795 | 791 | ||
792 | /* | ||
793 | * This deadlock detector can't reasonably detect deadlocks with | ||
794 | * FL_FILE_PVT locks, since they aren't owned by a process, per-se. | ||
795 | */ | ||
796 | if (IS_FILE_PVT(caller_fl)) | ||
797 | return 0; | ||
798 | |||
796 | while ((block_fl = what_owner_is_waiting_for(block_fl))) { | 799 | while ((block_fl = what_owner_is_waiting_for(block_fl))) { |
797 | if (i++ > MAX_DEADLK_ITERATIONS) | 800 | if (i++ > MAX_DEADLK_ITERATIONS) |
798 | return 0; | 801 | return 0; |
@@ -1152,13 +1155,14 @@ EXPORT_SYMBOL(posix_lock_file_wait); | |||
1152 | 1155 | ||
1153 | /** | 1156 | /** |
1154 | * locks_mandatory_locked - Check for an active lock | 1157 | * locks_mandatory_locked - Check for an active lock |
1155 | * @inode: the file to check | 1158 | * @file: the file to check |
1156 | * | 1159 | * |
1157 | * Searches the inode's list of locks to find any POSIX locks which conflict. | 1160 | * Searches the inode's list of locks to find any POSIX locks which conflict. |
1158 | * This function is called from locks_verify_locked() only. | 1161 | * This function is called from locks_verify_locked() only. |
1159 | */ | 1162 | */ |
1160 | int locks_mandatory_locked(struct inode *inode) | 1163 | int locks_mandatory_locked(struct file *file) |
1161 | { | 1164 | { |
1165 | struct inode *inode = file_inode(file); | ||
1162 | fl_owner_t owner = current->files; | 1166 | fl_owner_t owner = current->files; |
1163 | struct file_lock *fl; | 1167 | struct file_lock *fl; |
1164 | 1168 | ||
@@ -1169,7 +1173,7 @@ int locks_mandatory_locked(struct inode *inode) | |||
1169 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 1173 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
1170 | if (!IS_POSIX(fl)) | 1174 | if (!IS_POSIX(fl)) |
1171 | continue; | 1175 | continue; |
1172 | if (fl->fl_owner != owner) | 1176 | if (fl->fl_owner != owner && fl->fl_owner != (fl_owner_t)file) |
1173 | break; | 1177 | break; |
1174 | } | 1178 | } |
1175 | spin_unlock(&inode->i_lock); | 1179 | spin_unlock(&inode->i_lock); |
@@ -1195,19 +1199,30 @@ int locks_mandatory_area(int read_write, struct inode *inode, | |||
1195 | { | 1199 | { |
1196 | struct file_lock fl; | 1200 | struct file_lock fl; |
1197 | int error; | 1201 | int error; |
1202 | bool sleep = false; | ||
1198 | 1203 | ||
1199 | locks_init_lock(&fl); | 1204 | locks_init_lock(&fl); |
1200 | fl.fl_owner = current->files; | ||
1201 | fl.fl_pid = current->tgid; | 1205 | fl.fl_pid = current->tgid; |
1202 | fl.fl_file = filp; | 1206 | fl.fl_file = filp; |
1203 | fl.fl_flags = FL_POSIX | FL_ACCESS; | 1207 | fl.fl_flags = FL_POSIX | FL_ACCESS; |
1204 | if (filp && !(filp->f_flags & O_NONBLOCK)) | 1208 | if (filp && !(filp->f_flags & O_NONBLOCK)) |
1205 | fl.fl_flags |= FL_SLEEP; | 1209 | sleep = true; |
1206 | fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; | 1210 | fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; |
1207 | fl.fl_start = offset; | 1211 | fl.fl_start = offset; |
1208 | fl.fl_end = offset + count - 1; | 1212 | fl.fl_end = offset + count - 1; |
1209 | 1213 | ||
1210 | for (;;) { | 1214 | for (;;) { |
1215 | if (filp) { | ||
1216 | fl.fl_owner = (fl_owner_t)filp; | ||
1217 | fl.fl_flags &= ~FL_SLEEP; | ||
1218 | error = __posix_lock_file(inode, &fl, NULL); | ||
1219 | if (!error) | ||
1220 | break; | ||
1221 | } | ||
1222 | |||
1223 | if (sleep) | ||
1224 | fl.fl_flags |= FL_SLEEP; | ||
1225 | fl.fl_owner = current->files; | ||
1211 | error = __posix_lock_file(inode, &fl, NULL); | 1226 | error = __posix_lock_file(inode, &fl, NULL); |
1212 | if (error != FILE_LOCK_DEFERRED) | 1227 | if (error != FILE_LOCK_DEFERRED) |
1213 | break; | 1228 | break; |
@@ -1472,6 +1487,32 @@ int fcntl_getlease(struct file *filp) | |||
1472 | return type; | 1487 | return type; |
1473 | } | 1488 | } |
1474 | 1489 | ||
1490 | /** | ||
1491 | * check_conflicting_open - see if the given dentry points to a file that has | ||
1492 | * an existing open that would conflict with the | ||
1493 | * desired lease. | ||
1494 | * @dentry: dentry to check | ||
1495 | * @arg: type of lease that we're trying to acquire | ||
1496 | * | ||
1497 | * Check to see if there's an existing open fd on this file that would | ||
1498 | * conflict with the lease we're trying to set. | ||
1499 | */ | ||
1500 | static int | ||
1501 | check_conflicting_open(const struct dentry *dentry, const long arg) | ||
1502 | { | ||
1503 | int ret = 0; | ||
1504 | struct inode *inode = dentry->d_inode; | ||
1505 | |||
1506 | if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) | ||
1507 | return -EAGAIN; | ||
1508 | |||
1509 | if ((arg == F_WRLCK) && ((d_count(dentry) > 1) || | ||
1510 | (atomic_read(&inode->i_count) > 1))) | ||
1511 | ret = -EAGAIN; | ||
1512 | |||
1513 | return ret; | ||
1514 | } | ||
1515 | |||
1475 | static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp) | 1516 | static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp) |
1476 | { | 1517 | { |
1477 | struct file_lock *fl, **before, **my_before = NULL, *lease; | 1518 | struct file_lock *fl, **before, **my_before = NULL, *lease; |
@@ -1499,12 +1540,8 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp | |||
1499 | return -EINVAL; | 1540 | return -EINVAL; |
1500 | } | 1541 | } |
1501 | 1542 | ||
1502 | error = -EAGAIN; | 1543 | error = check_conflicting_open(dentry, arg); |
1503 | if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) | 1544 | if (error) |
1504 | goto out; | ||
1505 | if ((arg == F_WRLCK) | ||
1506 | && ((d_count(dentry) > 1) | ||
1507 | || (atomic_read(&inode->i_count) > 1))) | ||
1508 | goto out; | 1545 | goto out; |
1509 | 1546 | ||
1510 | /* | 1547 | /* |
@@ -1549,7 +1586,19 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp | |||
1549 | goto out; | 1586 | goto out; |
1550 | 1587 | ||
1551 | locks_insert_lock(before, lease); | 1588 | locks_insert_lock(before, lease); |
1552 | error = 0; | 1589 | /* |
1590 | * The check in break_lease() is lockless. It's possible for another | ||
1591 | * open to race in after we did the earlier check for a conflicting | ||
1592 | * open but before the lease was inserted. Check again for a | ||
1593 | * conflicting open and cancel the lease if there is one. | ||
1594 | * | ||
1595 | * We also add a barrier here to ensure that the insertion of the lock | ||
1596 | * precedes these checks. | ||
1597 | */ | ||
1598 | smp_mb(); | ||
1599 | error = check_conflicting_open(dentry, arg); | ||
1600 | if (error) | ||
1601 | locks_unlink_lock(flp); | ||
1553 | out: | 1602 | out: |
1554 | if (is_deleg) | 1603 | if (is_deleg) |
1555 | mutex_unlock(&inode->i_mutex); | 1604 | mutex_unlock(&inode->i_mutex); |
@@ -1842,7 +1891,7 @@ EXPORT_SYMBOL_GPL(vfs_test_lock); | |||
1842 | 1891 | ||
1843 | static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) | 1892 | static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) |
1844 | { | 1893 | { |
1845 | flock->l_pid = fl->fl_pid; | 1894 | flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid; |
1846 | #if BITS_PER_LONG == 32 | 1895 | #if BITS_PER_LONG == 32 |
1847 | /* | 1896 | /* |
1848 | * Make sure we can represent the posix lock via | 1897 | * Make sure we can represent the posix lock via |
@@ -1864,7 +1913,7 @@ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl) | |||
1864 | #if BITS_PER_LONG == 32 | 1913 | #if BITS_PER_LONG == 32 |
1865 | static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) | 1914 | static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) |
1866 | { | 1915 | { |
1867 | flock->l_pid = fl->fl_pid; | 1916 | flock->l_pid = IS_FILE_PVT(fl) ? -1 : fl->fl_pid; |
1868 | flock->l_start = fl->fl_start; | 1917 | flock->l_start = fl->fl_start; |
1869 | flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : | 1918 | flock->l_len = fl->fl_end == OFFSET_MAX ? 0 : |
1870 | fl->fl_end - fl->fl_start + 1; | 1919 | fl->fl_end - fl->fl_start + 1; |
@@ -1876,7 +1925,7 @@ static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) | |||
1876 | /* Report the first existing lock that would conflict with l. | 1925 | /* Report the first existing lock that would conflict with l. |
1877 | * This implements the F_GETLK command of fcntl(). | 1926 | * This implements the F_GETLK command of fcntl(). |
1878 | */ | 1927 | */ |
1879 | int fcntl_getlk(struct file *filp, struct flock __user *l) | 1928 | int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l) |
1880 | { | 1929 | { |
1881 | struct file_lock file_lock; | 1930 | struct file_lock file_lock; |
1882 | struct flock flock; | 1931 | struct flock flock; |
@@ -1893,6 +1942,16 @@ int fcntl_getlk(struct file *filp, struct flock __user *l) | |||
1893 | if (error) | 1942 | if (error) |
1894 | goto out; | 1943 | goto out; |
1895 | 1944 | ||
1945 | if (cmd == F_GETLKP) { | ||
1946 | error = -EINVAL; | ||
1947 | if (flock.l_pid != 0) | ||
1948 | goto out; | ||
1949 | |||
1950 | cmd = F_GETLK; | ||
1951 | file_lock.fl_flags |= FL_FILE_PVT; | ||
1952 | file_lock.fl_owner = (fl_owner_t)filp; | ||
1953 | } | ||
1954 | |||
1896 | error = vfs_test_lock(filp, &file_lock); | 1955 | error = vfs_test_lock(filp, &file_lock); |
1897 | if (error) | 1956 | if (error) |
1898 | goto out; | 1957 | goto out; |
@@ -2012,25 +2071,32 @@ again: | |||
2012 | error = flock_to_posix_lock(filp, file_lock, &flock); | 2071 | error = flock_to_posix_lock(filp, file_lock, &flock); |
2013 | if (error) | 2072 | if (error) |
2014 | goto out; | 2073 | goto out; |
2015 | if (cmd == F_SETLKW) { | 2074 | |
2016 | file_lock->fl_flags |= FL_SLEEP; | 2075 | /* |
2017 | } | 2076 | * If the cmd is requesting file-private locks, then set the |
2018 | 2077 | * FL_FILE_PVT flag and override the owner. | |
2019 | error = -EBADF; | 2078 | */ |
2020 | switch (flock.l_type) { | 2079 | switch (cmd) { |
2021 | case F_RDLCK: | 2080 | case F_SETLKP: |
2022 | if (!(filp->f_mode & FMODE_READ)) | 2081 | error = -EINVAL; |
2023 | goto out; | 2082 | if (flock.l_pid != 0) |
2024 | break; | ||
2025 | case F_WRLCK: | ||
2026 | if (!(filp->f_mode & FMODE_WRITE)) | ||
2027 | goto out; | 2083 | goto out; |
2084 | |||
2085 | cmd = F_SETLK; | ||
2086 | file_lock->fl_flags |= FL_FILE_PVT; | ||
2087 | file_lock->fl_owner = (fl_owner_t)filp; | ||
2028 | break; | 2088 | break; |
2029 | case F_UNLCK: | 2089 | case F_SETLKPW: |
2030 | break; | ||
2031 | default: | ||
2032 | error = -EINVAL; | 2090 | error = -EINVAL; |
2033 | goto out; | 2091 | if (flock.l_pid != 0) |
2092 | goto out; | ||
2093 | |||
2094 | cmd = F_SETLKW; | ||
2095 | file_lock->fl_flags |= FL_FILE_PVT; | ||
2096 | file_lock->fl_owner = (fl_owner_t)filp; | ||
2097 | /* Fallthrough */ | ||
2098 | case F_SETLKW: | ||
2099 | file_lock->fl_flags |= FL_SLEEP; | ||
2034 | } | 2100 | } |
2035 | 2101 | ||
2036 | error = do_lock_file_wait(filp, cmd, file_lock); | 2102 | error = do_lock_file_wait(filp, cmd, file_lock); |
@@ -2061,7 +2127,7 @@ out: | |||
2061 | /* Report the first existing lock that would conflict with l. | 2127 | /* Report the first existing lock that would conflict with l. |
2062 | * This implements the F_GETLK command of fcntl(). | 2128 | * This implements the F_GETLK command of fcntl(). |
2063 | */ | 2129 | */ |
2064 | int fcntl_getlk64(struct file *filp, struct flock64 __user *l) | 2130 | int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) |
2065 | { | 2131 | { |
2066 | struct file_lock file_lock; | 2132 | struct file_lock file_lock; |
2067 | struct flock64 flock; | 2133 | struct flock64 flock; |
@@ -2078,6 +2144,16 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l) | |||
2078 | if (error) | 2144 | if (error) |
2079 | goto out; | 2145 | goto out; |
2080 | 2146 | ||
2147 | if (cmd == F_GETLKP) { | ||
2148 | error = -EINVAL; | ||
2149 | if (flock.l_pid != 0) | ||
2150 | goto out; | ||
2151 | |||
2152 | cmd = F_GETLK64; | ||
2153 | file_lock.fl_flags |= FL_FILE_PVT; | ||
2154 | file_lock.fl_owner = (fl_owner_t)filp; | ||
2155 | } | ||
2156 | |||
2081 | error = vfs_test_lock(filp, &file_lock); | 2157 | error = vfs_test_lock(filp, &file_lock); |
2082 | if (error) | 2158 | if (error) |
2083 | goto out; | 2159 | goto out; |
@@ -2130,25 +2206,32 @@ again: | |||
2130 | error = flock64_to_posix_lock(filp, file_lock, &flock); | 2206 | error = flock64_to_posix_lock(filp, file_lock, &flock); |
2131 | if (error) | 2207 | if (error) |
2132 | goto out; | 2208 | goto out; |
2133 | if (cmd == F_SETLKW64) { | 2209 | |
2134 | file_lock->fl_flags |= FL_SLEEP; | 2210 | /* |
2135 | } | 2211 | * If the cmd is requesting file-private locks, then set the |
2136 | 2212 | * FL_FILE_PVT flag and override the owner. | |
2137 | error = -EBADF; | 2213 | */ |
2138 | switch (flock.l_type) { | 2214 | switch (cmd) { |
2139 | case F_RDLCK: | 2215 | case F_SETLKP: |
2140 | if (!(filp->f_mode & FMODE_READ)) | 2216 | error = -EINVAL; |
2141 | goto out; | 2217 | if (flock.l_pid != 0) |
2142 | break; | ||
2143 | case F_WRLCK: | ||
2144 | if (!(filp->f_mode & FMODE_WRITE)) | ||
2145 | goto out; | 2218 | goto out; |
2219 | |||
2220 | cmd = F_SETLK64; | ||
2221 | file_lock->fl_flags |= FL_FILE_PVT; | ||
2222 | file_lock->fl_owner = (fl_owner_t)filp; | ||
2146 | break; | 2223 | break; |
2147 | case F_UNLCK: | 2224 | case F_SETLKPW: |
2148 | break; | ||
2149 | default: | ||
2150 | error = -EINVAL; | 2225 | error = -EINVAL; |
2151 | goto out; | 2226 | if (flock.l_pid != 0) |
2227 | goto out; | ||
2228 | |||
2229 | cmd = F_SETLKW64; | ||
2230 | file_lock->fl_flags |= FL_FILE_PVT; | ||
2231 | file_lock->fl_owner = (fl_owner_t)filp; | ||
2232 | /* Fallthrough */ | ||
2233 | case F_SETLKW64: | ||
2234 | file_lock->fl_flags |= FL_SLEEP; | ||
2152 | } | 2235 | } |
2153 | 2236 | ||
2154 | error = do_lock_file_wait(filp, cmd, file_lock); | 2237 | error = do_lock_file_wait(filp, cmd, file_lock); |
@@ -2209,7 +2292,7 @@ EXPORT_SYMBOL(locks_remove_posix); | |||
2209 | /* | 2292 | /* |
2210 | * This function is called on the last close of an open file. | 2293 | * This function is called on the last close of an open file. |
2211 | */ | 2294 | */ |
2212 | void locks_remove_flock(struct file *filp) | 2295 | void locks_remove_file(struct file *filp) |
2213 | { | 2296 | { |
2214 | struct inode * inode = file_inode(filp); | 2297 | struct inode * inode = file_inode(filp); |
2215 | struct file_lock *fl; | 2298 | struct file_lock *fl; |
@@ -2218,6 +2301,8 @@ void locks_remove_flock(struct file *filp) | |||
2218 | if (!inode->i_flock) | 2301 | if (!inode->i_flock) |
2219 | return; | 2302 | return; |
2220 | 2303 | ||
2304 | locks_remove_posix(filp, (fl_owner_t)filp); | ||
2305 | |||
2221 | if (filp->f_op->flock) { | 2306 | if (filp->f_op->flock) { |
2222 | struct file_lock fl = { | 2307 | struct file_lock fl = { |
2223 | .fl_pid = current->tgid, | 2308 | .fl_pid = current->tgid, |
@@ -2236,16 +2321,28 @@ void locks_remove_flock(struct file *filp) | |||
2236 | 2321 | ||
2237 | while ((fl = *before) != NULL) { | 2322 | while ((fl = *before) != NULL) { |
2238 | if (fl->fl_file == filp) { | 2323 | if (fl->fl_file == filp) { |
2239 | if (IS_FLOCK(fl)) { | ||
2240 | locks_delete_lock(before); | ||
2241 | continue; | ||
2242 | } | ||
2243 | if (IS_LEASE(fl)) { | 2324 | if (IS_LEASE(fl)) { |
2244 | lease_modify(before, F_UNLCK); | 2325 | lease_modify(before, F_UNLCK); |
2245 | continue; | 2326 | continue; |
2246 | } | 2327 | } |
2247 | /* What? */ | 2328 | |
2248 | BUG(); | 2329 | /* |
2330 | * There's a leftover lock on the list of a type that | ||
2331 | * we didn't expect to see. Most likely a classic | ||
2332 | * POSIX lock that ended up not getting released | ||
2333 | * properly, or that raced onto the list somehow. Log | ||
2334 | * some info about it and then just remove it from | ||
2335 | * the list. | ||
2336 | */ | ||
2337 | WARN(!IS_FLOCK(fl), | ||
2338 | "leftover lock: dev=%u:%u ino=%lu type=%hhd flags=0x%x start=%lld end=%lld\n", | ||
2339 | MAJOR(inode->i_sb->s_dev), | ||
2340 | MINOR(inode->i_sb->s_dev), inode->i_ino, | ||
2341 | fl->fl_type, fl->fl_flags, | ||
2342 | fl->fl_start, fl->fl_end); | ||
2343 | |||
2344 | locks_delete_lock(before); | ||
2345 | continue; | ||
2249 | } | 2346 | } |
2250 | before = &fl->fl_next; | 2347 | before = &fl->fl_next; |
2251 | } | 2348 | } |
@@ -2314,8 +2411,14 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, | |||
2314 | 2411 | ||
2315 | seq_printf(f, "%lld:%s ", id, pfx); | 2412 | seq_printf(f, "%lld:%s ", id, pfx); |
2316 | if (IS_POSIX(fl)) { | 2413 | if (IS_POSIX(fl)) { |
2317 | seq_printf(f, "%6s %s ", | 2414 | if (fl->fl_flags & FL_ACCESS) |
2318 | (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ", | 2415 | seq_printf(f, "ACCESS"); |
2416 | else if (IS_FILE_PVT(fl)) | ||
2417 | seq_printf(f, "FLPVT "); | ||
2418 | else | ||
2419 | seq_printf(f, "POSIX "); | ||
2420 | |||
2421 | seq_printf(f, " %s ", | ||
2319 | (inode == NULL) ? "*NOINODE*" : | 2422 | (inode == NULL) ? "*NOINODE*" : |
2320 | mandatory_lock(inode) ? "MANDATORY" : "ADVISORY "); | 2423 | mandatory_lock(inode) ? "MANDATORY" : "ADVISORY "); |
2321 | } else if (IS_FLOCK(fl)) { | 2424 | } else if (IS_FLOCK(fl)) { |
@@ -2385,6 +2488,7 @@ static int locks_show(struct seq_file *f, void *v) | |||
2385 | } | 2488 | } |
2386 | 2489 | ||
2387 | static void *locks_start(struct seq_file *f, loff_t *pos) | 2490 | static void *locks_start(struct seq_file *f, loff_t *pos) |
2491 | __acquires(&blocked_lock_lock) | ||
2388 | { | 2492 | { |
2389 | struct locks_iterator *iter = f->private; | 2493 | struct locks_iterator *iter = f->private; |
2390 | 2494 | ||
@@ -2403,6 +2507,7 @@ static void *locks_next(struct seq_file *f, void *v, loff_t *pos) | |||
2403 | } | 2507 | } |
2404 | 2508 | ||
2405 | static void locks_stop(struct seq_file *f, void *v) | 2509 | static void locks_stop(struct seq_file *f, void *v) |
2510 | __releases(&blocked_lock_lock) | ||
2406 | { | 2511 | { |
2407 | spin_unlock(&blocked_lock_lock); | 2512 | spin_unlock(&blocked_lock_lock); |
2408 | lg_global_unlock(&file_lock_lglock); | 2513 | lg_global_unlock(&file_lock_lglock); |
diff --git a/fs/namei.c b/fs/namei.c index c1178880f23c..88339f59efb5 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2569,7 +2569,7 @@ static int handle_truncate(struct file *filp) | |||
2569 | /* | 2569 | /* |
2570 | * Refuse to truncate files with mandatory locks held on them. | 2570 | * Refuse to truncate files with mandatory locks held on them. |
2571 | */ | 2571 | */ |
2572 | error = locks_verify_locked(inode); | 2572 | error = locks_verify_locked(filp); |
2573 | if (!error) | 2573 | if (!error) |
2574 | error = security_path_truncate(path); | 2574 | error = security_path_truncate(path); |
2575 | if (!error) { | 2575 | if (!error) { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 215cb1b09f47..a877ed3f389f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -893,6 +893,7 @@ static inline int file_check_writeable(struct file *filp) | |||
893 | #define FL_SLEEP 128 /* A blocking lock */ | 893 | #define FL_SLEEP 128 /* A blocking lock */ |
894 | #define FL_DOWNGRADE_PENDING 256 /* Lease is being downgraded */ | 894 | #define FL_DOWNGRADE_PENDING 256 /* Lease is being downgraded */ |
895 | #define FL_UNLOCK_PENDING 512 /* Lease is being broken */ | 895 | #define FL_UNLOCK_PENDING 512 /* Lease is being broken */ |
896 | #define FL_FILE_PVT 1024 /* lock is private to the file */ | ||
896 | 897 | ||
897 | /* | 898 | /* |
898 | * Special return value from posix_lock_file() and vfs_lock_file() for | 899 | * Special return value from posix_lock_file() and vfs_lock_file() for |
@@ -997,12 +998,12 @@ struct file_lock { | |||
997 | extern void send_sigio(struct fown_struct *fown, int fd, int band); | 998 | extern void send_sigio(struct fown_struct *fown, int fd, int band); |
998 | 999 | ||
999 | #ifdef CONFIG_FILE_LOCKING | 1000 | #ifdef CONFIG_FILE_LOCKING |
1000 | extern int fcntl_getlk(struct file *, struct flock __user *); | 1001 | extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *); |
1001 | extern int fcntl_setlk(unsigned int, struct file *, unsigned int, | 1002 | extern int fcntl_setlk(unsigned int, struct file *, unsigned int, |
1002 | struct flock __user *); | 1003 | struct flock __user *); |
1003 | 1004 | ||
1004 | #if BITS_PER_LONG == 32 | 1005 | #if BITS_PER_LONG == 32 |
1005 | extern int fcntl_getlk64(struct file *, struct flock64 __user *); | 1006 | extern int fcntl_getlk64(struct file *, unsigned int, struct flock64 __user *); |
1006 | extern int fcntl_setlk64(unsigned int, struct file *, unsigned int, | 1007 | extern int fcntl_setlk64(unsigned int, struct file *, unsigned int, |
1007 | struct flock64 __user *); | 1008 | struct flock64 __user *); |
1008 | #endif | 1009 | #endif |
@@ -1017,7 +1018,7 @@ extern struct file_lock * locks_alloc_lock(void); | |||
1017 | extern void locks_copy_lock(struct file_lock *, struct file_lock *); | 1018 | extern void locks_copy_lock(struct file_lock *, struct file_lock *); |
1018 | extern void __locks_copy_lock(struct file_lock *, const struct file_lock *); | 1019 | extern void __locks_copy_lock(struct file_lock *, const struct file_lock *); |
1019 | extern void locks_remove_posix(struct file *, fl_owner_t); | 1020 | extern void locks_remove_posix(struct file *, fl_owner_t); |
1020 | extern void locks_remove_flock(struct file *); | 1021 | extern void locks_remove_file(struct file *); |
1021 | extern void locks_release_private(struct file_lock *); | 1022 | extern void locks_release_private(struct file_lock *); |
1022 | extern void posix_test_lock(struct file *, struct file_lock *); | 1023 | extern void posix_test_lock(struct file *, struct file_lock *); |
1023 | extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *); | 1024 | extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *); |
@@ -1035,7 +1036,8 @@ extern int lease_modify(struct file_lock **, int); | |||
1035 | extern int lock_may_read(struct inode *, loff_t start, unsigned long count); | 1036 | extern int lock_may_read(struct inode *, loff_t start, unsigned long count); |
1036 | extern int lock_may_write(struct inode *, loff_t start, unsigned long count); | 1037 | extern int lock_may_write(struct inode *, loff_t start, unsigned long count); |
1037 | #else /* !CONFIG_FILE_LOCKING */ | 1038 | #else /* !CONFIG_FILE_LOCKING */ |
1038 | static inline int fcntl_getlk(struct file *file, struct flock __user *user) | 1039 | static inline int fcntl_getlk(struct file *file, unsigned int cmd, |
1040 | struct flock __user *user) | ||
1039 | { | 1041 | { |
1040 | return -EINVAL; | 1042 | return -EINVAL; |
1041 | } | 1043 | } |
@@ -1047,7 +1049,8 @@ static inline int fcntl_setlk(unsigned int fd, struct file *file, | |||
1047 | } | 1049 | } |
1048 | 1050 | ||
1049 | #if BITS_PER_LONG == 32 | 1051 | #if BITS_PER_LONG == 32 |
1050 | static inline int fcntl_getlk64(struct file *file, struct flock64 __user *user) | 1052 | static inline int fcntl_getlk64(struct file *file, unsigned int cmd, |
1053 | struct flock64 __user *user) | ||
1051 | { | 1054 | { |
1052 | return -EINVAL; | 1055 | return -EINVAL; |
1053 | } | 1056 | } |
@@ -1088,7 +1091,7 @@ static inline void locks_remove_posix(struct file *filp, fl_owner_t owner) | |||
1088 | return; | 1091 | return; |
1089 | } | 1092 | } |
1090 | 1093 | ||
1091 | static inline void locks_remove_flock(struct file *filp) | 1094 | static inline void locks_remove_file(struct file *filp) |
1092 | { | 1095 | { |
1093 | return; | 1096 | return; |
1094 | } | 1097 | } |
@@ -1916,6 +1919,11 @@ extern int current_umask(void); | |||
1916 | extern void ihold(struct inode * inode); | 1919 | extern void ihold(struct inode * inode); |
1917 | extern void iput(struct inode *); | 1920 | extern void iput(struct inode *); |
1918 | 1921 | ||
1922 | static inline struct inode *file_inode(struct file *f) | ||
1923 | { | ||
1924 | return f->f_inode; | ||
1925 | } | ||
1926 | |||
1919 | /* /sys/fs */ | 1927 | /* /sys/fs */ |
1920 | extern struct kobject *fs_kobj; | 1928 | extern struct kobject *fs_kobj; |
1921 | 1929 | ||
@@ -1925,7 +1933,7 @@ extern struct kobject *fs_kobj; | |||
1925 | #define FLOCK_VERIFY_WRITE 2 | 1933 | #define FLOCK_VERIFY_WRITE 2 |
1926 | 1934 | ||
1927 | #ifdef CONFIG_FILE_LOCKING | 1935 | #ifdef CONFIG_FILE_LOCKING |
1928 | extern int locks_mandatory_locked(struct inode *); | 1936 | extern int locks_mandatory_locked(struct file *); |
1929 | extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t); | 1937 | extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t); |
1930 | 1938 | ||
1931 | /* | 1939 | /* |
@@ -1948,10 +1956,10 @@ static inline int mandatory_lock(struct inode *ino) | |||
1948 | return IS_MANDLOCK(ino) && __mandatory_lock(ino); | 1956 | return IS_MANDLOCK(ino) && __mandatory_lock(ino); |
1949 | } | 1957 | } |
1950 | 1958 | ||
1951 | static inline int locks_verify_locked(struct inode *inode) | 1959 | static inline int locks_verify_locked(struct file *file) |
1952 | { | 1960 | { |
1953 | if (mandatory_lock(inode)) | 1961 | if (mandatory_lock(file_inode(file))) |
1954 | return locks_mandatory_locked(inode); | 1962 | return locks_mandatory_locked(file); |
1955 | return 0; | 1963 | return 0; |
1956 | } | 1964 | } |
1957 | 1965 | ||
@@ -1971,6 +1979,12 @@ static inline int locks_verify_truncate(struct inode *inode, | |||
1971 | 1979 | ||
1972 | static inline int break_lease(struct inode *inode, unsigned int mode) | 1980 | static inline int break_lease(struct inode *inode, unsigned int mode) |
1973 | { | 1981 | { |
1982 | /* | ||
1983 | * Since this check is lockless, we must ensure that any refcounts | ||
1984 | * taken are done before checking inode->i_flock. Otherwise, we could | ||
1985 | * end up racing with tasks trying to set a new lease on this file. | ||
1986 | */ | ||
1987 | smp_mb(); | ||
1974 | if (inode->i_flock) | 1988 | if (inode->i_flock) |
1975 | return __break_lease(inode, mode, FL_LEASE); | 1989 | return __break_lease(inode, mode, FL_LEASE); |
1976 | return 0; | 1990 | return 0; |
@@ -2006,7 +2020,7 @@ static inline int break_deleg_wait(struct inode **delegated_inode) | |||
2006 | } | 2020 | } |
2007 | 2021 | ||
2008 | #else /* !CONFIG_FILE_LOCKING */ | 2022 | #else /* !CONFIG_FILE_LOCKING */ |
2009 | static inline int locks_mandatory_locked(struct inode *inode) | 2023 | static inline int locks_mandatory_locked(struct file *file) |
2010 | { | 2024 | { |
2011 | return 0; | 2025 | return 0; |
2012 | } | 2026 | } |
@@ -2028,7 +2042,7 @@ static inline int mandatory_lock(struct inode *inode) | |||
2028 | return 0; | 2042 | return 0; |
2029 | } | 2043 | } |
2030 | 2044 | ||
2031 | static inline int locks_verify_locked(struct inode *inode) | 2045 | static inline int locks_verify_locked(struct file *file) |
2032 | { | 2046 | { |
2033 | return 0; | 2047 | return 0; |
2034 | } | 2048 | } |
@@ -2302,11 +2316,6 @@ static inline bool execute_ok(struct inode *inode) | |||
2302 | return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode); | 2316 | return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode); |
2303 | } | 2317 | } |
2304 | 2318 | ||
2305 | static inline struct inode *file_inode(struct file *f) | ||
2306 | { | ||
2307 | return f->f_inode; | ||
2308 | } | ||
2309 | |||
2310 | static inline void file_start_write(struct file *file) | 2319 | static inline void file_start_write(struct file *file) |
2311 | { | 2320 | { |
2312 | if (!S_ISREG(file_inode(file)->i_mode)) | 2321 | if (!S_ISREG(file_inode(file)->i_mode)) |
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h index 95e46c8e05f9..a9b13f8b3595 100644 --- a/include/uapi/asm-generic/fcntl.h +++ b/include/uapi/asm-generic/fcntl.h | |||
@@ -132,6 +132,22 @@ | |||
132 | #define F_GETOWNER_UIDS 17 | 132 | #define F_GETOWNER_UIDS 17 |
133 | #endif | 133 | #endif |
134 | 134 | ||
135 | /* | ||
136 | * fd "private" POSIX locks. | ||
137 | * | ||
138 | * Usually POSIX locks held by a process are released on *any* close and are | ||
139 | * not inherited across a fork(). | ||
140 | * | ||
141 | * These cmd values will set locks that conflict with normal POSIX locks, but | ||
142 | * are "owned" by the opened file, not the process. This means that they are | ||
143 | * inherited across fork() like BSD (flock) locks, and they are only released | ||
144 | * automatically when the last reference to the the open file against which | ||
145 | * they were acquired is put. | ||
146 | */ | ||
147 | #define F_GETLKP 36 | ||
148 | #define F_SETLKP 37 | ||
149 | #define F_SETLKPW 38 | ||
150 | |||
135 | #define F_OWNER_TID 0 | 151 | #define F_OWNER_TID 0 |
136 | #define F_OWNER_PID 1 | 152 | #define F_OWNER_PID 1 |
137 | #define F_OWNER_PGRP 2 | 153 | #define F_OWNER_PGRP 2 |
@@ -186,8 +202,6 @@ struct flock { | |||
186 | }; | 202 | }; |
187 | #endif | 203 | #endif |
188 | 204 | ||
189 | #ifndef CONFIG_64BIT | ||
190 | |||
191 | #ifndef HAVE_ARCH_STRUCT_FLOCK64 | 205 | #ifndef HAVE_ARCH_STRUCT_FLOCK64 |
192 | #ifndef __ARCH_FLOCK64_PAD | 206 | #ifndef __ARCH_FLOCK64_PAD |
193 | #define __ARCH_FLOCK64_PAD | 207 | #define __ARCH_FLOCK64_PAD |
@@ -202,6 +216,5 @@ struct flock64 { | |||
202 | __ARCH_FLOCK64_PAD | 216 | __ARCH_FLOCK64_PAD |
203 | }; | 217 | }; |
204 | #endif | 218 | #endif |
205 | #endif /* !CONFIG_64BIT */ | ||
206 | 219 | ||
207 | #endif /* _ASM_GENERIC_FCNTL_H */ | 220 | #endif /* _ASM_GENERIC_FCNTL_H */ |
@@ -1299,7 +1299,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
1299 | /* | 1299 | /* |
1300 | * Make sure there are no mandatory locks on the file. | 1300 | * Make sure there are no mandatory locks on the file. |
1301 | */ | 1301 | */ |
1302 | if (locks_verify_locked(inode)) | 1302 | if (locks_verify_locked(file)) |
1303 | return -EAGAIN; | 1303 | return -EAGAIN; |
1304 | 1304 | ||
1305 | vm_flags |= VM_SHARED | VM_MAYSHARE; | 1305 | vm_flags |= VM_SHARED | VM_MAYSHARE; |
diff --git a/mm/nommu.c b/mm/nommu.c index 8740213b1647..a554e5a451cd 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -995,7 +995,7 @@ static int validate_mmap_request(struct file *file, | |||
995 | (file->f_mode & FMODE_WRITE)) | 995 | (file->f_mode & FMODE_WRITE)) |
996 | return -EACCES; | 996 | return -EACCES; |
997 | 997 | ||
998 | if (locks_verify_locked(file_inode(file))) | 998 | if (locks_verify_locked(file)) |
999 | return -EAGAIN; | 999 | return -EAGAIN; |
1000 | 1000 | ||
1001 | if (!(capabilities & BDI_CAP_MAP_DIRECT)) | 1001 | if (!(capabilities & BDI_CAP_MAP_DIRECT)) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 869c2f1e0da1..b4beb77967b1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -3317,6 +3317,9 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, | |||
3317 | case F_GETLK: | 3317 | case F_GETLK: |
3318 | case F_SETLK: | 3318 | case F_SETLK: |
3319 | case F_SETLKW: | 3319 | case F_SETLKW: |
3320 | case F_GETLKP: | ||
3321 | case F_SETLKP: | ||
3322 | case F_SETLKPW: | ||
3320 | #if BITS_PER_LONG == 32 | 3323 | #if BITS_PER_LONG == 32 |
3321 | case F_GETLK64: | 3324 | case F_GETLK64: |
3322 | case F_SETLK64: | 3325 | case F_SETLK64: |