aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-01-14 20:13:28 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-01-14 20:13:28 -0500
commitf4d3935e4f4884ba80561db5549394afb8eef8f7 (patch)
treec9bfd0dc1ffdfbcb7f34870eea4848240775e086
parent34241af77b8696120a9735bb2579ec7044199a8b (diff)
parentb9dc6f65bc5e232d1c05fe34b5daadc7e8bbf1fb (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro. The most notable fix here is probably the fix for a splice regression ("fix a fencepost error in pipe_advance()") noticed by Alan Wylie. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fix a fencepost error in pipe_advance() coredump: Ensure proper size of sparse core files aio: fix lock dep warning tmpfs: clear S_ISGID when setting posix ACLs
-rw-r--r--fs/aio.c6
-rw-r--r--fs/binfmt_elf.c1
-rw-r--r--fs/coredump.c18
-rw-r--r--fs/posix_acl.c9
-rw-r--r--include/linux/coredump.h1
-rw-r--r--lib/iov_iter.c54
6 files changed, 59 insertions, 30 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 4ab67e8cb776..873b4ca82ccb 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1085,7 +1085,8 @@ static void aio_complete(struct kiocb *kiocb, long res, long res2)
1085 * Tell lockdep we inherited freeze protection from submission 1085 * Tell lockdep we inherited freeze protection from submission
1086 * thread. 1086 * thread.
1087 */ 1087 */
1088 __sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE); 1088 if (S_ISREG(file_inode(file)->i_mode))
1089 __sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE);
1089 file_end_write(file); 1090 file_end_write(file);
1090 } 1091 }
1091 1092
@@ -1525,7 +1526,8 @@ static ssize_t aio_write(struct kiocb *req, struct iocb *iocb, bool vectored,
1525 * by telling it the lock got released so that it doesn't 1526 * by telling it the lock got released so that it doesn't
1526 * complain about held lock when we return to userspace. 1527 * complain about held lock when we return to userspace.
1527 */ 1528 */
1528 __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE); 1529 if (S_ISREG(file_inode(file)->i_mode))
1530 __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
1529 } 1531 }
1530 kfree(iovec); 1532 kfree(iovec);
1531 return ret; 1533 return ret;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 29a02daf08a9..422370293cfd 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -2298,6 +2298,7 @@ static int elf_core_dump(struct coredump_params *cprm)
2298 goto end_coredump; 2298 goto end_coredump;
2299 } 2299 }
2300 } 2300 }
2301 dump_truncate(cprm);
2301 2302
2302 if (!elf_core_write_extra_data(cprm)) 2303 if (!elf_core_write_extra_data(cprm))
2303 goto end_coredump; 2304 goto end_coredump;
diff --git a/fs/coredump.c b/fs/coredump.c
index e525b6017cdf..ae6b05629ca1 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -833,3 +833,21 @@ int dump_align(struct coredump_params *cprm, int align)
833 return mod ? dump_skip(cprm, align - mod) : 1; 833 return mod ? dump_skip(cprm, align - mod) : 1;
834} 834}
835EXPORT_SYMBOL(dump_align); 835EXPORT_SYMBOL(dump_align);
836
837/*
838 * Ensures that file size is big enough to contain the current file
839 * postion. This prevents gdb from complaining about a truncated file
840 * if the last "write" to the file was dump_skip.
841 */
842void dump_truncate(struct coredump_params *cprm)
843{
844 struct file *file = cprm->file;
845 loff_t offset;
846
847 if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
848 offset = file->f_op->llseek(file, 0, SEEK_CUR);
849 if (i_size_read(file->f_mapping->host) < offset)
850 do_truncate(file->f_path.dentry, offset, 0, file);
851 }
852}
853EXPORT_SYMBOL(dump_truncate);
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 595522022aca..c9d48dc78495 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -922,11 +922,10 @@ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
922 int error; 922 int error;
923 923
924 if (type == ACL_TYPE_ACCESS) { 924 if (type == ACL_TYPE_ACCESS) {
925 error = posix_acl_equiv_mode(acl, &inode->i_mode); 925 error = posix_acl_update_mode(inode,
926 if (error < 0) 926 &inode->i_mode, &acl);
927 return 0; 927 if (error)
928 if (error == 0) 928 return error;
929 acl = NULL;
930 } 929 }
931 930
932 inode->i_ctime = current_time(inode); 931 inode->i_ctime = current_time(inode);
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
index d016a121a8c4..28ffa94aed6b 100644
--- a/include/linux/coredump.h
+++ b/include/linux/coredump.h
@@ -14,6 +14,7 @@ struct coredump_params;
14extern int dump_skip(struct coredump_params *cprm, size_t nr); 14extern int dump_skip(struct coredump_params *cprm, size_t nr);
15extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); 15extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
16extern int dump_align(struct coredump_params *cprm, int align); 16extern int dump_align(struct coredump_params *cprm, int align);
17extern void dump_truncate(struct coredump_params *cprm);
17#ifdef CONFIG_COREDUMP 18#ifdef CONFIG_COREDUMP
18extern void do_coredump(const siginfo_t *siginfo); 19extern void do_coredump(const siginfo_t *siginfo);
19#else 20#else
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 25f572303801..e68604ae3ced 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -730,43 +730,50 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
730} 730}
731EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); 731EXPORT_SYMBOL(iov_iter_copy_from_user_atomic);
732 732
733static inline void pipe_truncate(struct iov_iter *i)
734{
735 struct pipe_inode_info *pipe = i->pipe;
736 if (pipe->nrbufs) {
737 size_t off = i->iov_offset;
738 int idx = i->idx;
739 int nrbufs = (idx - pipe->curbuf) & (pipe->buffers - 1);
740 if (off) {
741 pipe->bufs[idx].len = off - pipe->bufs[idx].offset;
742 idx = next_idx(idx, pipe);
743 nrbufs++;
744 }
745 while (pipe->nrbufs > nrbufs) {
746 pipe_buf_release(pipe, &pipe->bufs[idx]);
747 idx = next_idx(idx, pipe);
748 pipe->nrbufs--;
749 }
750 }
751}
752
733static void pipe_advance(struct iov_iter *i, size_t size) 753static void pipe_advance(struct iov_iter *i, size_t size)
734{ 754{
735 struct pipe_inode_info *pipe = i->pipe; 755 struct pipe_inode_info *pipe = i->pipe;
736 struct pipe_buffer *buf;
737 int idx = i->idx;
738 size_t off = i->iov_offset, orig_sz;
739
740 if (unlikely(i->count < size)) 756 if (unlikely(i->count < size))
741 size = i->count; 757 size = i->count;
742 orig_sz = size;
743
744 if (size) { 758 if (size) {
759 struct pipe_buffer *buf;
760 size_t off = i->iov_offset, left = size;
761 int idx = i->idx;
745 if (off) /* make it relative to the beginning of buffer */ 762 if (off) /* make it relative to the beginning of buffer */
746 size += off - pipe->bufs[idx].offset; 763 left += off - pipe->bufs[idx].offset;
747 while (1) { 764 while (1) {
748 buf = &pipe->bufs[idx]; 765 buf = &pipe->bufs[idx];
749 if (size <= buf->len) 766 if (left <= buf->len)
750 break; 767 break;
751 size -= buf->len; 768 left -= buf->len;
752 idx = next_idx(idx, pipe); 769 idx = next_idx(idx, pipe);
753 } 770 }
754 buf->len = size;
755 i->idx = idx; 771 i->idx = idx;
756 off = i->iov_offset = buf->offset + size; 772 i->iov_offset = buf->offset + left;
757 }
758 if (off)
759 idx = next_idx(idx, pipe);
760 if (pipe->nrbufs) {
761 int unused = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
762 /* [curbuf,unused) is in use. Free [idx,unused) */
763 while (idx != unused) {
764 pipe_buf_release(pipe, &pipe->bufs[idx]);
765 idx = next_idx(idx, pipe);
766 pipe->nrbufs--;
767 }
768 } 773 }
769 i->count -= orig_sz; 774 i->count -= size;
775 /* ... and discard everything past that point */
776 pipe_truncate(i);
770} 777}
771 778
772void iov_iter_advance(struct iov_iter *i, size_t size) 779void iov_iter_advance(struct iov_iter *i, size_t size)
@@ -826,6 +833,7 @@ void iov_iter_pipe(struct iov_iter *i, int direction,
826 size_t count) 833 size_t count)
827{ 834{
828 BUG_ON(direction != ITER_PIPE); 835 BUG_ON(direction != ITER_PIPE);
836 WARN_ON(pipe->nrbufs == pipe->buffers);
829 i->type = direction; 837 i->type = direction;
830 i->pipe = pipe; 838 i->pipe = pipe;
831 i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1); 839 i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);