[PATCH openEuler-1.0-LTS 0/3] CVE-2022-49755

CVE-2022-49755 Udipto Goswami (2): usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait usb: gadget: f_fs: Fix unbalanced spinlock in __ffs_ep0_queue_wait Uttkarsh Aggarwal (1): usb: gadget: f_fs: Add unbind event before functionfs_unbind drivers/usb/gadget/function/f_fs.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) -- 2.22.0

From: Udipto Goswami <quic_ugoswami@quicinc.com> stable inclusion from stable-v4.19.272 commit e9036e951f93fb8d7b5e9d6e2c7f94a4da312ae4 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBWVWG CVE: CVE-2022-49755 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit 6a19da111057f69214b97c62fb0ac59023970850 ] While performing fast composition switch, there is a possibility that the process of ffs_ep0_write/ffs_ep0_read get into a race condition due to ep0req being freed up from functionfs_unbind. Consider the scenario that the ffs_ep0_write calls the ffs_ep0_queue_wait by taking a lock &ffs->ev.waitq.lock. However, the functionfs_unbind isn't bounded so it can go ahead and mark the ep0req to NULL, and since there is no NULL check in ffs_ep0_queue_wait we will end up in use-after-free. Fix this by making a serialized execution between the two functions using a mutex_lock(ffs->mutex). Fixes: ddf8abd25994 ("USB: f_fs: the FunctionFS driver") Signed-off-by: Udipto Goswami <quic_ugoswami@quicinc.com> Tested-by: Krishna Kurapati <quic_kriskura@quicinc.com> Link: https://lore.kernel.org/r/20221215052906.8993-2-quic_ugoswami@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Guo Mengqi <guomengqi3@huawei.com> --- drivers/usb/gadget/function/f_fs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 4ec3f27a0aea..5c1d797b5bcb 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -271,6 +271,9 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) struct usb_request *req = ffs->ep0req; int ret; + if (!req) + return -EINVAL; + req->zero = len < le16_to_cpu(ffs->ev.setup.wLength); spin_unlock_irq(&ffs->ev.waitq.lock); @@ -1807,10 +1810,12 @@ static void functionfs_unbind(struct ffs_data *ffs) ENTER(); if (!WARN_ON(!ffs->gadget)) { + mutex_lock(&ffs->mutex); usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req); ffs->ep0req = NULL; ffs->gadget = NULL; clear_bit(FFS_FL_BOUND, &ffs->flags); + mutex_unlock(&ffs->mutex); ffs_data_put(ffs); } } -- 2.22.0

From: Udipto Goswami <quic_ugoswami@quicinc.com> stable inclusion from stable-v4.19.273 commit 554177f3157bb70aab6cbcfdabb4f4ede8bedcbb category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBWVWG CVE: CVE-2022-49755 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit 921deb9da15851425ccbb6ee409dc2fd8fbdfe6b ] __ffs_ep0_queue_wait executes holding the spinlock of &ffs->ev.waitq.lock and unlocks it after the assignments to usb_request are done. However in the code if the request is already NULL we bail out returning -EINVAL but never unlocked the spinlock. Fix this by adding spin_unlock_irq &ffs->ev.waitq.lock before returning. Fixes: 6a19da111057 ("usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait") Reviewed-by: John Keeping <john@metanate.com> Signed-off-by: Udipto Goswami <quic_ugoswami@quicinc.com> Link: https://lore.kernel.org/r/20230124091149.18647-1-quic_ugoswami@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Guo Mengqi <guomengqi3@huawei.com> --- drivers/usb/gadget/function/f_fs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 5c1d797b5bcb..7cb32257307b 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -271,8 +271,10 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) struct usb_request *req = ffs->ep0req; int ret; - if (!req) + if (!req) { + spin_unlock_irq(&ffs->ev.waitq.lock); return -EINVAL; + } req->zero = len < le16_to_cpu(ffs->ev.setup.wLength); -- 2.22.0

From: Uttkarsh Aggarwal <quic_uaggarwa@quicinc.com> stable inclusion from stable-v4.19.285 commit 9a95fba9362a161127673e29243ca5cfea48defe category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBWVWG CVE: CVE-2022-49755 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- commit efb6b535207395a5c7317993602e2503ca8cb4b3 upstream. While exercising the unbind path, with the current implementation the functionfs_unbind would be calling which waits for the ffs->mutex to be available, however within the same time ffs_ep0_read is invoked & if no setup packets are pending, it will invoke function wait_event_interruptible_exclusive_locked_irq which by definition waits for the ev.count to be increased inside the same mutex for which functionfs_unbind is waiting. This creates deadlock situation because the functionfs_unbind won't get the lock until ev.count is increased which can only happen if the caller ffs_func_unbind can proceed further. Following is the illustration: CPU1 CPU2 ffs_func_unbind() ffs_ep0_read() mutex_lock(ffs->mutex) wait_event(ffs->ev.count) functionfs_unbind() mutex_lock(ffs->mutex) mutex_unlock(ffs->mutex) ffs_event_add() <deadlock> Fix this by moving the event unbind before functionfs_unbind to ensure the ev.count is incrased properly. Fixes: 6a19da111057 ("usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait") Cc: stable <stable@kernel.org> Signed-off-by: Uttkarsh Aggarwal <quic_uaggarwa@quicinc.com> Link: https://lore.kernel.org/r/20230525092854.7992-1-quic_uaggarwa@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Conflicts: drivers/usb/gadget/function/f_fs.c [context conflict] Signed-off-by: Guo Mengqi <guomengqi3@huawei.com> --- drivers/usb/gadget/function/f_fs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 7cb32257307b..04b2d6ca9d43 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -3500,6 +3500,7 @@ static void ffs_func_unbind(struct usb_configuration *c, ffs->func = NULL; } + ffs_event_add(ffs, FUNCTIONFS_UNBIND); if (!--opts->refcnt) functionfs_unbind(ffs); @@ -3522,8 +3523,6 @@ static void ffs_func_unbind(struct usb_configuration *c, func->function.hs_descriptors = NULL; func->function.ss_descriptors = NULL; func->interfaces_nums = NULL; - - ffs_event_add(ffs, FUNCTIONFS_UNBIND); } static struct usb_function *ffs_alloc(struct usb_function_instance *fi) -- 2.22.0

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/16145 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/LTI... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/16145 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/LTI...
participants (2)
-
Guo Mengqi
-
patchwork bot