Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp4737596iob; Sun, 8 May 2022 23:47:10 -0700 (PDT) X-Google-Smtp-Source: ABdhPJynqjeakXeUk5O5mW/U69h5MmueGregMpbGILs0N4DVjM54HUCuZbwNG9jEGJ90+lCpJBOg X-Received: by 2002:a05:6a00:170a:b0:50d:3e40:9e0 with SMTP id h10-20020a056a00170a00b0050d3e4009e0mr14943955pfc.48.1652078829934; Sun, 08 May 2022 23:47:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652078829; cv=none; d=google.com; s=arc-20160816; b=GjNbTOASlSI5Z9DYMoi06L+lARyABX1ifooR6fUITBY/Xby17Vl0qCEN9TtwFUk53X 19dSD25VS1kzkSW8VGQdBIDTRqiB41qmA1PElO5LllvanRaINt6OIGIeg7/rmss1IB2g 2FGQhYaQ2NiUoVOSgTa+CZunUeibDWN8l9WqiRqxA2a/rqYATB1vTKXwL+ANT4HHqXQq D7tv2XCZkX/CUN0gkEag6HQoOaqsGZpfcfDy2ugkZ6Cu/7P7Ms1OM43WfcPFFN97xolK ggQCPDA7Mk/0QvuvKRBj+oKRz0+9fCI16g9+efJGI/WmPY33Cj/OhWRWKmM/wNaqgzgQ sKYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=cUhBtZ1z6u24outcsIBKI7njf2lIPwPqpQUoBKX+exo=; b=HYnulFViLr0/CyotgHSXSsRlyNIA5jsEhx0xvCUbLYOUp74KgLNPtOu2Y09HJspBph YLuNykIZeKzhUJQ4qVJo5fTpovKtkO6Zzmh+L2Y5eyS/J4Eeqmz2rRfmZ2+3Oz84If3z KvrmzyOey/m1KF3NLUwIFgE5ix43a3R9i/KpKl+cZwPpu2xrBMuOjDgeLXm8yzYeBwzF NtGI1/T60yEYOCOCAaeb0DFJY6BjpwO6MCMEK9CTq3Q46gUYfWzJPsz7cwoeWtxujOLz WkOVfvy5sdz5bLJyltU5tGRZYciIkkP14gFlEq2xxA3g6BA6vTJGdg7jGNjaTrlN7J0y nusA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=A2KJ+PN6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id 128-20020a630386000000b003ab1a2b7944si12782338pgd.61.2022.05.08.23.47.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 May 2022 23:47:09 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=A2KJ+PN6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 52E8918AA8C; Sun, 8 May 2022 23:43:33 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1446305AbiEGMAD (ORCPT + 99 others); Sat, 7 May 2022 08:00:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47468 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230521AbiEGMAA (ORCPT ); Sat, 7 May 2022 08:00:00 -0400 Received: from mail-pj1-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 13F473BBD1; Sat, 7 May 2022 04:56:14 -0700 (PDT) Received: by mail-pj1-x1035.google.com with SMTP id c1-20020a17090a558100b001dca2694f23so8864963pji.3; Sat, 07 May 2022 04:56:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=cUhBtZ1z6u24outcsIBKI7njf2lIPwPqpQUoBKX+exo=; b=A2KJ+PN6DYLs1t0hpBuHHSMbwI+z4fVlpHC50LZI8ehz7YeDkwKEWv17pBTcumgKVa oGSXosR8/5jU6NcrYbZfzaim82H39GX/VA/A7KNb+9QuuhIE7/HqsnxfNm/HDl6Gx49P bhosUislytDUupmKNHJSS5/W1oLIixjLPLN8uzaF4OkbIO6dQkYmJL643woabEsEThJg 0al5qLZTIXcKGEH4f2s5Ekgn7c7SQWUFZe7xYqjZRgckrihwlqNLlQhANMp77kPuTPgg PVuo7geS9t0A3vZR1tcUqOEIGWtNitxSPp6Wt26Tuh+QYeLhrxL6TpKK/ZPiunEiYqt6 dftA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=cUhBtZ1z6u24outcsIBKI7njf2lIPwPqpQUoBKX+exo=; b=l1NnrPcOuVOc7CknvYvxhYxjGpymbsi1G8oHo+wM4kAF5bqvbnIjEdKECqevkgOaNe dXWHwZNLsCQudQEYR0CpOa5JeP6VvN0tqRmsWygBJfSoxO8c2H2+3RV+LXrqGd4vn7aj aE2g6vnRdlPBdMe1scBdWuL7acW9hDRMzrepJcuopT70QOwpaLl3CU2ijjv4Vd5170VS FlnMgncGgXekdLeVcRMAzhne/+6GVpbg0RUMKCa5fr8QxWQwq5SDclL3cG0kzDYtY1rr uMDR2HPDABFYniTbiHClb9GQG3Ob5w/F9Abu1osK9pIeYkVJKoumpzAwm2d3EUUsNhP7 a+Cg== X-Gm-Message-State: AOAM533GFuUSUHbxEyxK4pZpDzwKlb4pxbU0ifMd5sVBjKnKK0eGuh/4 WE8HnWt4jGaC3cl8Q25DIojg0MVKn7I= X-Received: by 2002:a17:902:da85:b0:15e:8e05:6963 with SMTP id j5-20020a170902da8500b0015e8e056963mr8077177plx.94.1651924573540; Sat, 07 May 2022 04:56:13 -0700 (PDT) Received: from ELIJAHBAI-MB0.tencent.com ([203.205.141.115]) by smtp.gmail.com with ESMTPSA id a11-20020a170902eccb00b0015e8d4eb221sm3557750plh.107.2022.05.07.04.56.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 May 2022 04:56:13 -0700 (PDT) From: Haimin Zhang To: Alexander Viro , David Howells , "Fabio M. De Francesco" , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Cc: Haimin Zhang , TCS Robot Subject: [PATCH] fs/pipe: Deinitialize the watch_queue when pipe is freed Date: Sat, 7 May 2022 19:56:05 +0800 Message-Id: <20220507115605.96775-1-tcs.kernel@gmail.com> X-Mailer: git-send-email 2.32.0 (Apple Git-132) MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RDNS_NONE, SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Haimin Zhang Add a new function call to deinitialize the watch_queue of a freed pipe. When a pipe node is freed, it doesn't make pipe->watch_queue->pipe null. Later when function post_one_notification is called, it will use this field, but it has been freed and watch_queue->pipe is a dangling pointer. It makes a uaf issue. Reported-by: TCS Robot Signed-off-by: Haimin Zhang --- The following is the callstacks: 1. The pipe was created as follows: ``` kmalloc build/../include/linux/slab.h:581 [inline] kzalloc build/../include/linux/slab.h:714 [inline] alloc_pipe_info+0x105/0x590 build/../fs/pipe.c:790 get_pipe_inode build/../fs/pipe.c:881 [inline] create_pipe_files+0x8d/0x880 build/../fs/pipe.c:913 __do_pipe_flags build/../fs/pipe.c:962 [inline] do_pipe2+0x96/0x1b0 build/../fs/pipe.c:1010 __do_sys_pipe2 build/../fs/pipe.c:1028 [inline] __se_sys_pipe2 build/../fs/pipe.c:1026 [inline] __x64_sys_pipe2+0x50/0x70 build/../fs/pipe.c:1026 do_syscall_x64 build/../arch/x86/entry/common.c:50 [inline] do_syscall_64+0x35/0x80 build/../arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x44/0xae ``` 2. The pipe was freed as follows: ``` kfree+0xd6/0x4d0 build/../mm/slub.c:4552 put_pipe_info build/../fs/pipe.c:711 [inline] pipe_release+0x2b6/0x310 build/../fs/pipe.c:734 __fput+0x277/0x9d0 build/../fs/file_table.c:317 task_work_run+0xdd/0x1a0 build/../kernel/task_work.c:164 resume_user_mode_work build/../include/linux/resume_user_mode.h: 49 [inline] exit_to_user_mode_loop build/../kernel/entry/common.c:169 [inline] exit_to_user_mode_prepare+0x23c/0x250 build/../kernel/entry/common.c:201 __syscall_exit_to_user_mode_work build/../kernel/entry/common.c:283 [inline] syscall_exit_to_user_mode+0x19/0x60 build/../kernel/entry/common.c:294 do_syscall_64+0x42/0x80 build/../arch/x86/entry/common.c:86 entry_SYSCALL_64_after_hwframe+0x44/0xae ``` 3. The dangling pointer was used: ``` __lock_acquire+0x3eb0/0x56c0 build/../kernel/locking/lockdep.c:4899 lock_acquire build/../kernel/locking/lockdep.c:5641 [inline] lock_acquire+0x1ab/0x510 build/../kernel/locking/lockdep.c:5606 __raw_spin_lock_irq build/../include/linux/spinlock_api_smp.h:119 [inline] _raw_spin_lock_irq+0x32/0x50 build/../kernel/locking/spinlock.c:170 spin_lock_irq build/../include/linux/spinlock.h:374 [inline] post_one_notification.isra.0+0x59/0x990 build/../kernel/watch_queue.c:86 remove_watch_from_object+0x35a/0x9d0 build/../kernel/watch_queue.c:527 remove_watch_list build/../include/linux/watch_queue.h:115 [inline] key_gc_unused_keys.constprop.0+0x2e5/0x600 build/../security/keys/gc.c:135 key_garbage_collector+0x3d7/0x920 build/../security/keys/gc.c:297 process_one_work+0x996/0x1610 build/../kernel/workqueue.c:2289 worker_thread+0x665/0x1080 build/../kernel/workqueue.c:2436 kthread+0x2e9/0x3a0 build/../kernel/kthread.c:376 ret_from_fork+0x1f/0x30 build/../arch/x86/entry/entry_64.S:298 ``` fs/pipe.c | 4 +++- include/linux/watch_queue.h | 5 +++++ kernel/watch_queue.c | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/fs/pipe.c b/fs/pipe.c index e140ea150bbb..7e3f4df87c28 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -844,8 +844,10 @@ void free_pipe_info(struct pipe_inode_info *pipe) pipe_buf_release(pipe, buf); } #ifdef CONFIG_WATCH_QUEUE - if (pipe->watch_queue) + if (pipe->watch_queue) { put_watch_queue(pipe->watch_queue); + watch_queue_deinit(pipe); + } #endif if (pipe->tmp_page) __free_page(pipe->tmp_page); diff --git a/include/linux/watch_queue.h b/include/linux/watch_queue.h index 3b9a40ae8bdb..e5086b195fb7 100644 --- a/include/linux/watch_queue.h +++ b/include/linux/watch_queue.h @@ -90,6 +90,7 @@ extern long watch_queue_set_size(struct pipe_inode_info *, unsigned int); extern long watch_queue_set_filter(struct pipe_inode_info *, struct watch_notification_filter __user *); extern int watch_queue_init(struct pipe_inode_info *); +extern int watch_queue_deinit(struct pipe_inode_info *); extern void watch_queue_clear(struct watch_queue *); static inline void init_watch_list(struct watch_list *wlist, @@ -129,6 +130,10 @@ static inline int watch_queue_init(struct pipe_inode_info *pipe) return -ENOPKG; } +static inline int watch_queue_deinit(struct pipe_inode_info *pipe) +{ + return -ENOPKG; +} #endif #endif /* _LINUX_WATCH_QUEUE_H */ diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c index 230038d4f908..3396e60f14e8 100644 --- a/kernel/watch_queue.c +++ b/kernel/watch_queue.c @@ -663,3 +663,19 @@ int watch_queue_init(struct pipe_inode_info *pipe) pipe->watch_queue = wqueue; return 0; } + +/* + * Deinitialise a watch queue + */ +int watch_queue_deinit(struct pipe_inode_info *pipe) +{ + struct watch_queue *wqueue; + + if (pipe) { + wqueue = pipe->watch_queue; + if (wqueue) + wqueue->pipe = NULL; + pipe->watch_queue = NULL; + } + return 0; +} -- 2.27.0