summaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-07 16:48:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-07 16:48:18 -0400
commitb59eea554f57befa2aa3172fcb63e521bdd850dd (patch)
tree7b68bd0bd6666dfd5e377b0999d99d74c1396736 /fs/fcntl.c
parent6481352082e8c373a005387c4fc7258b197f0bc9 (diff)
vfs: fix flock compat thinko
Michael Ellerman reported that commit 8c6657cb50cb ("Switch flock copyin/copyout primitives to copy_{from,to}_user()") broke his networking on a bunch of PPC machines (64-bit kernel, 32-bit userspace). The reason is a brown-paper bug by that commit, which had the arguments to "copy_flock_fields()" in the wrong order, breaking the compat handling for file locking. Apparently very few people run 32-bit user space on x86 any more, so the PPC people got the honor of noticing this "feature". Michael also sent a minimal diff that just changed the order of the arguments in that macro. This is not that minimal diff. This not only changes the order of the arguments in the macro, it also changes them to be pointers (to be consistent with all the other uses of those pointers), and makes the functions that do all of this also have the proper "const" attribution on the source pointers in order to make issues like that (using the source as a destination) be really obvious. Reported-by: Michael Ellerman <mpe@ellerman.id.au> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index b6bd89628025..3b01b646e528 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -520,50 +520,50 @@ out:
520 520
521#ifdef CONFIG_COMPAT 521#ifdef CONFIG_COMPAT
522/* careful - don't use anywhere else */ 522/* careful - don't use anywhere else */
523#define copy_flock_fields(from, to) \ 523#define copy_flock_fields(dst, src) \
524 (to).l_type = (from).l_type; \ 524 (dst)->l_type = (src)->l_type; \
525 (to).l_whence = (from).l_whence; \ 525 (dst)->l_whence = (src)->l_whence; \
526 (to).l_start = (from).l_start; \ 526 (dst)->l_start = (src)->l_start; \
527 (to).l_len = (from).l_len; \ 527 (dst)->l_len = (src)->l_len; \
528 (to).l_pid = (from).l_pid; 528 (dst)->l_pid = (src)->l_pid;
529 529
530static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) 530static int get_compat_flock(struct flock *kfl, const struct compat_flock __user *ufl)
531{ 531{
532 struct compat_flock fl; 532 struct compat_flock fl;
533 533
534 if (copy_from_user(&fl, ufl, sizeof(struct compat_flock))) 534 if (copy_from_user(&fl, ufl, sizeof(struct compat_flock)))
535 return -EFAULT; 535 return -EFAULT;
536 copy_flock_fields(*kfl, fl); 536 copy_flock_fields(kfl, &fl);
537 return 0; 537 return 0;
538} 538}
539 539
540static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl) 540static int get_compat_flock64(struct flock *kfl, const struct compat_flock64 __user *ufl)
541{ 541{
542 struct compat_flock64 fl; 542 struct compat_flock64 fl;
543 543
544 if (copy_from_user(&fl, ufl, sizeof(struct compat_flock64))) 544 if (copy_from_user(&fl, ufl, sizeof(struct compat_flock64)))
545 return -EFAULT; 545 return -EFAULT;
546 copy_flock_fields(*kfl, fl); 546 copy_flock_fields(kfl, &fl);
547 return 0; 547 return 0;
548} 548}
549 549
550static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) 550static int put_compat_flock(const struct flock *kfl, struct compat_flock __user *ufl)
551{ 551{
552 struct compat_flock fl; 552 struct compat_flock fl;
553 553
554 memset(&fl, 0, sizeof(struct compat_flock)); 554 memset(&fl, 0, sizeof(struct compat_flock));
555 copy_flock_fields(fl, *kfl); 555 copy_flock_fields(&fl, kfl);
556 if (copy_to_user(ufl, &fl, sizeof(struct compat_flock))) 556 if (copy_to_user(ufl, &fl, sizeof(struct compat_flock)))
557 return -EFAULT; 557 return -EFAULT;
558 return 0; 558 return 0;
559} 559}
560 560
561static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl) 561static int put_compat_flock64(const struct flock *kfl, struct compat_flock64 __user *ufl)
562{ 562{
563 struct compat_flock64 fl; 563 struct compat_flock64 fl;
564 564
565 memset(&fl, 0, sizeof(struct compat_flock64)); 565 memset(&fl, 0, sizeof(struct compat_flock64));
566 copy_flock_fields(fl, *kfl); 566 copy_flock_fields(&fl, kfl);
567 if (copy_to_user(ufl, &fl, sizeof(struct compat_flock64))) 567 if (copy_to_user(ufl, &fl, sizeof(struct compat_flock64)))
568 return -EFAULT; 568 return -EFAULT;
569 return 0; 569 return 0;