diff mbox series

[1/2] pipe: fix potential use-after-free in pipe_read()

Message ID 20211115035721.1909-2-thunder.leizhen@huawei.com (mailing list archive)
State New, archived
Headers show
Series pipe: Fix a potential UAF and delete a duplicate line of code | expand

Commit Message

Zhen Lei Nov. 15, 2021, 3:57 a.m. UTC
Accessing buf->flags after pipe_buf_release(pipe, buf) is unsafe, because
the 'buf' memory maybe freed.

Fixes: e7d553d69cf6 ("pipe: Add notification lossage handling")
Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
---
 fs/pipe.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Matthew Wilcox Nov. 15, 2021, 4:25 a.m. UTC | #1
On Mon, Nov 15, 2021 at 11:57:20AM +0800, Zhen Lei wrote:
>  			if (!buf->len) {
> +				unsigned int __maybe_unused flags = buf->flags;

Why __maybe_unused?
Zhen Lei Nov. 15, 2021, 6:13 a.m. UTC | #2
On 2021/11/15 12:25, Matthew Wilcox wrote:
> On Mon, Nov 15, 2021 at 11:57:20AM +0800, Zhen Lei wrote:
>>  			if (!buf->len) {
>> +				unsigned int __maybe_unused flags = buf->flags;
> 
> Why __maybe_unused?

It's used only if "#ifdef CONFIG_WATCH_QUEUE". Otherwise, a warning will be reported.

> .
>
Matthew Wilcox Nov. 15, 2021, 1:05 p.m. UTC | #3
On Mon, Nov 15, 2021 at 02:13:44PM +0800, Leizhen (ThunderTown) wrote:
> 
> 
> On 2021/11/15 12:25, Matthew Wilcox wrote:
> > On Mon, Nov 15, 2021 at 11:57:20AM +0800, Zhen Lei wrote:
> >>  			if (!buf->len) {
> >> +				unsigned int __maybe_unused flags = buf->flags;
> > 
> > Why __maybe_unused?
> 
> It's used only if "#ifdef CONFIG_WATCH_QUEUE". Otherwise, a warning will be reported.

Better to turn the #ifdef into if (IS_ENABLED())
Zhen Lei Nov. 23, 2021, 1:09 a.m. UTC | #4
On 2021/11/15 21:05, Matthew Wilcox wrote:
> On Mon, Nov 15, 2021 at 02:13:44PM +0800, Leizhen (ThunderTown) wrote:
>>
>>
>> On 2021/11/15 12:25, Matthew Wilcox wrote:
>>> On Mon, Nov 15, 2021 at 11:57:20AM +0800, Zhen Lei wrote:
>>>>  			if (!buf->len) {
>>>> +				unsigned int __maybe_unused flags = buf->flags;
>>>
>>> Why __maybe_unused?
>>
>> It's used only if "#ifdef CONFIG_WATCH_QUEUE". Otherwise, a warning will be reported.
> 
> Better to turn the #ifdef into if (IS_ENABLED())

Hi, Matthew:
  Thank you for your advice. IS_ENABLED() is a good idea, but when I tried it, I found that
the macro 'PIPE_BUF_FLAG_LOSS' and the structure member 'note_loss' were also separated by
"ifdef CONFIG_WATCH_QUEUE", so this method is not suitable here.

#ifdef CONFIG_WATCH_QUEUE
#define PIPE_BUF_FLAG_LOSS     0x40    /* Message loss happened after this buffer */
#endif

@@ -62,9 +60,7 @@ struct pipe_inode_info {
        unsigned int tail;
        unsigned int max_usage;
        unsigned int ring_size;
#ifdef CONFIG_WATCH_QUEUE
        bool note_loss;
#endif



> .
>
diff mbox series

Patch

diff --git a/fs/pipe.c b/fs/pipe.c
index 6d4342bad9f15b2..302f1e50ce3be1d 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -319,10 +319,12 @@  pipe_read(struct kiocb *iocb, struct iov_iter *to)
 			}
 
 			if (!buf->len) {
+				unsigned int __maybe_unused flags = buf->flags;
+
 				pipe_buf_release(pipe, buf);
 				spin_lock_irq(&pipe->rd_wait.lock);
 #ifdef CONFIG_WATCH_QUEUE
-				if (buf->flags & PIPE_BUF_FLAG_LOSS)
+				if (flags & PIPE_BUF_FLAG_LOSS)
 					pipe->note_loss = true;
 #endif
 				tail++;