diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-14 20:13:28 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-01-14 20:13:28 -0500 |
commit | f4d3935e4f4884ba80561db5549394afb8eef8f7 (patch) | |
tree | c9bfd0dc1ffdfbcb7f34870eea4848240775e086 | |
parent | 34241af77b8696120a9735bb2579ec7044199a8b (diff) | |
parent | b9dc6f65bc5e232d1c05fe34b5daadc7e8bbf1fb (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.c | 6 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 1 | ||||
-rw-r--r-- | fs/coredump.c | 18 | ||||
-rw-r--r-- | fs/posix_acl.c | 9 | ||||
-rw-r--r-- | include/linux/coredump.h | 1 | ||||
-rw-r--r-- | lib/iov_iter.c | 54 |
6 files changed, 59 insertions, 30 deletions
@@ -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 | } |
835 | EXPORT_SYMBOL(dump_align); | 835 | EXPORT_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 | */ | ||
842 | void 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 | } | ||
853 | EXPORT_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; | |||
14 | extern int dump_skip(struct coredump_params *cprm, size_t nr); | 14 | extern int dump_skip(struct coredump_params *cprm, size_t nr); |
15 | extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); | 15 | extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); |
16 | extern int dump_align(struct coredump_params *cprm, int align); | 16 | extern int dump_align(struct coredump_params *cprm, int align); |
17 | extern void dump_truncate(struct coredump_params *cprm); | ||
17 | #ifdef CONFIG_COREDUMP | 18 | #ifdef CONFIG_COREDUMP |
18 | extern void do_coredump(const siginfo_t *siginfo); | 19 | extern 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 | } |
731 | EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); | 731 | EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); |
732 | 732 | ||
733 | static 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 | |||
733 | static void pipe_advance(struct iov_iter *i, size_t size) | 753 | static 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 | ||
772 | void iov_iter_advance(struct iov_iter *i, size_t size) | 779 | void 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); |