diff options
author | Matthew Wilcox <willy@infradead.org> | 2019-04-05 17:02:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-04-14 13:00:04 -0400 |
commit | 15fab63e1e57be9fdb5eec1bbc5916e9825e9acb (patch) | |
tree | 1353971310401012cf4b108a375e525065d8bec0 /include | |
parent | 8fde12ca79aff9b5ba951fce1a2641901b8d8e64 (diff) |
fs: prevent page refcount overflow in pipe_buf_get
Change pipe_buf_get() to return a bool indicating whether it succeeded
in raising the refcount of the page (if the thing in the pipe is a page).
This removes another mechanism for overflowing the page refcount. All
callers converted to handle a failure.
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/pipe_fs_i.h | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 5a3bb3b7c9ad..3f2a42c11e20 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h | |||
@@ -108,18 +108,20 @@ struct pipe_buf_operations { | |||
108 | /* | 108 | /* |
109 | * Get a reference to the pipe buffer. | 109 | * Get a reference to the pipe buffer. |
110 | */ | 110 | */ |
111 | void (*get)(struct pipe_inode_info *, struct pipe_buffer *); | 111 | bool (*get)(struct pipe_inode_info *, struct pipe_buffer *); |
112 | }; | 112 | }; |
113 | 113 | ||
114 | /** | 114 | /** |
115 | * pipe_buf_get - get a reference to a pipe_buffer | 115 | * pipe_buf_get - get a reference to a pipe_buffer |
116 | * @pipe: the pipe that the buffer belongs to | 116 | * @pipe: the pipe that the buffer belongs to |
117 | * @buf: the buffer to get a reference to | 117 | * @buf: the buffer to get a reference to |
118 | * | ||
119 | * Return: %true if the reference was successfully obtained. | ||
118 | */ | 120 | */ |
119 | static inline void pipe_buf_get(struct pipe_inode_info *pipe, | 121 | static inline __must_check bool pipe_buf_get(struct pipe_inode_info *pipe, |
120 | struct pipe_buffer *buf) | 122 | struct pipe_buffer *buf) |
121 | { | 123 | { |
122 | buf->ops->get(pipe, buf); | 124 | return buf->ops->get(pipe, buf); |
123 | } | 125 | } |
124 | 126 | ||
125 | /** | 127 | /** |
@@ -178,7 +180,7 @@ struct pipe_inode_info *alloc_pipe_info(void); | |||
178 | void free_pipe_info(struct pipe_inode_info *); | 180 | void free_pipe_info(struct pipe_inode_info *); |
179 | 181 | ||
180 | /* Generic pipe buffer ops functions */ | 182 | /* Generic pipe buffer ops functions */ |
181 | void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *); | 183 | bool generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *); |
182 | int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *); | 184 | int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *); |
183 | int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *); | 185 | int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *); |
184 | void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); | 186 | void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); |