From 1fa61728b96e61889af962bdbbf01c1324ddff36 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Dec 2021 19:16:34 -0600 Subject: [PATCH 1/5] exit: Use the correct exit_code in /proc//stat mainline inclusion from mainline-v5.17-rc1 commit 2d18f7f456209ed8a8fc138b8bc535dbdaf84695 category: bugfix issue: NA CVE: NA Signed-off-by: wanxiaoqing --------------------------------------- Since do_proc_statt was modified to return process wide values instead of per task values the exit_code calculation has never been updated. Update it now to return the process wide exit_code when it is requested and available. History-Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git Fixes: bf719d26a5c1 ("[PATCH] distinct tgid/tid CPU usage") Link: https://lkml.kernel.org/r/20220103213312.9144-4-ebiederm@xmission.com Signed-off-by: "Eric W. Biederman" Signed-off-by: wanxiaoqing --- fs/proc/array.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index 18a4588c35be..ee90a14aa24c 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -449,6 +449,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, u64 cgtime, gtime; unsigned long rsslim = 0; unsigned long flags; + int exit_code = task->exit_code; state = *get_task_state(task); vsize = eip = esp = 0; @@ -512,6 +513,9 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, maj_flt += sig->maj_flt; thread_group_cputime_adjusted(task, &utime, &stime); gtime += sig->gtime; + + if (sig->flags & (SIGNAL_GROUP_EXIT | SIGNAL_STOP_STOPPED)) + exit_code = sig->group_exit_code; } sid = task_session_nr_ns(task, ns); @@ -613,7 +617,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, seq_puts(m, " 0 0 0 0 0 0 0"); if (permitted) - seq_put_decimal_ll(m, " ", task->exit_code); + seq_put_decimal_ll(m, " ", exit_code); else seq_puts(m, " 0"); -- Gitee From 13cbaeb75ce28aaced66943ec0d4a7fa153afcaa Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sat, 9 Sep 2023 18:45:01 +0200 Subject: [PATCH 2/5] fs/proc: do_task_stat: use __for_each_thread() mainline inclusion from mainline-v6.7-rc1 commit 7904e53ed5a20fc678c01d5d1b07ec486425bb6a category: bugfix issue: NA CVE: NA Signed-off-by: wanxiaoqing --------------------------------------- do/while_each_thread should be avoided when possible. Link: https://lkml.kernel.org/r/20230909164501.GA11581@redhat.com Signed-off-by: Oleg Nesterov Cc: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: wanxiaoqing --- fs/proc/array.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index ee90a14aa24c..e594d28a8304 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -502,12 +502,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, /* add up live thread stats at the group level */ if (whole) { - struct task_struct *t = task; - do { + struct task_struct *t; + + __for_each_thread(sig, t) { min_flt += t->min_flt; maj_flt += t->maj_flt; gtime += task_gtime(t); - } while_each_thread(task, t); + } min_flt += sig->min_flt; maj_flt += sig->maj_flt; -- Gitee From 532f4ba7b415e8d2afe8a98b2e5f948e858692bd Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 23 Jan 2024 16:33:57 +0100 Subject: [PATCH 3/5] fs/proc: do_task_stat: use sig->stats_lock to gather the threads/children stats mainline inclusion from mainline-v6.8-rc4 commit 7601df8031fd67310af891897ef6cc0df4209305 category: bugfix issue: #I9IJ2R CVE: CVE-2024-26686 Signed-off-by: wanxiaoqing --------------------------------------- lock_task_sighand() can trigger a hard lockup. If NR_CPUS threads call do_task_stat() at the same time and the process has NR_THREADS, it will spin with irqs disabled O(NR_CPUS * NR_THREADS) time. Change do_task_stat() to use sig->stats_lock to gather the statistics outside of ->siglock protected section, in the likely case this code will run lockless. Link: https://lkml.kernel.org/r/20240123153357.GA21857@redhat.com Signed-off-by: Oleg Nesterov Signed-off-by: Dylan Hatch Cc: Eric W. Biederman Cc: Signed-off-by: Andrew Morton Signed-off-by: wanxiaoqing --- fs/proc/array.c | 60 +++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index e594d28a8304..e0eb4c74825b 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -443,13 +443,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, int permitted; struct mm_struct *mm; unsigned long long start_time; - unsigned long cmin_flt = 0, cmaj_flt = 0; - unsigned long min_flt = 0, maj_flt = 0; - u64 cutime, cstime, utime, stime; - u64 cgtime, gtime; + unsigned long cmin_flt, cmaj_flt, min_flt, maj_flt; + u64 cutime, cstime, cgtime, utime, stime, gtime; unsigned long rsslim = 0; unsigned long flags; int exit_code = task->exit_code; + struct signal_struct *sig = task->signal; + unsigned int seq = 1; state = *get_task_state(task); vsize = eip = esp = 0; @@ -477,12 +477,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, sigemptyset(&sigign); sigemptyset(&sigcatch); - cutime = cstime = utime = stime = 0; - cgtime = gtime = 0; if (lock_task_sighand(task, &flags)) { - struct signal_struct *sig = task->signal; - if (sig->tty) { struct pid *pgrp = tty_get_pgrp(sig->tty); tty_pgrp = pid_nr_ns(pgrp, ns); @@ -493,28 +489,9 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, num_threads = get_nr_threads(task); collect_sigign_sigcatch(task, &sigign, &sigcatch); - cmin_flt = sig->cmin_flt; - cmaj_flt = sig->cmaj_flt; - cutime = sig->cutime; - cstime = sig->cstime; - cgtime = sig->cgtime; rsslim = READ_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur); - /* add up live thread stats at the group level */ if (whole) { - struct task_struct *t; - - __for_each_thread(sig, t) { - min_flt += t->min_flt; - maj_flt += t->maj_flt; - gtime += task_gtime(t); - } - - min_flt += sig->min_flt; - maj_flt += sig->maj_flt; - thread_group_cputime_adjusted(task, &utime, &stime); - gtime += sig->gtime; - if (sig->flags & (SIGNAL_GROUP_EXIT | SIGNAL_STOP_STOPPED)) exit_code = sig->group_exit_code; } @@ -528,6 +505,35 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, if (permitted && (!whole || num_threads < 2)) wchan = get_wchan(task); + + do { + seq++; /* 2 on the 1st/lockless path, otherwise odd */ + flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq); + + cmin_flt = sig->cmin_flt; + cmaj_flt = sig->cmaj_flt; + cutime = sig->cutime; + cstime = sig->cstime; + cgtime = sig->cgtime; + + if (whole) { + struct task_struct *t; + + min_flt = sig->min_flt; + maj_flt = sig->maj_flt; + gtime = sig->gtime; + + rcu_read_lock(); + __for_each_thread(sig, t) { + min_flt += t->min_flt; + maj_flt += t->maj_flt; + gtime += task_gtime(t); + } + rcu_read_unlock(); + } + } while (need_seqretry(&sig->stats_lock, seq)); + done_seqretry_irqrestore(&sig->stats_lock, seq, flags); + if (!whole) { min_flt = task->min_flt; maj_flt = task->maj_flt; -- Gitee From 0b28a66a6755b8541c9e04f48c3be02c9da81bf2 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 20 Aug 2021 16:02:53 +0900 Subject: [PATCH 4/5] scsi: core: Fix scsi_mode_sense() buffer length handling mainline inclusion from mainline-v5.16-rc1 commit 17b49bcbf8351d3dbe57204468ac34f033ed60bc category: bugfix issue: #I9P3ES CVE: CVE-2021-47182 Signed-off-by: wanxiaoqing --------------------------------------- Several problems exist with scsi_mode_sense() buffer length handling: 1) The allocation length field of the MODE SENSE(10) command is 16-bits, occupying bytes 7 and 8 of the CDB. With this command, access to mode pages larger than 255 bytes is thus possible. However, the CDB allocation length field is set by assigning len to byte 8 only, thus truncating buffer length larger than 255. 2) If scsi_mode_sense() is called with len smaller than 8 with sdev->use_10_for_ms set, or smaller than 4 otherwise, the buffer length is increased to 8 and 4 respectively, and the buffer is zero filled with these increased values, thus corrupting the memory following the buffer. Fix these 2 problems by using put_unaligned_be16() to set the allocation length field of MODE SENSE(10) CDB and by returning an error when len is too small. Furthermore, if len is larger than 255B, always try MODE SENSE(10) first, even if the device driver did not set sdev->use_10_for_ms. In case of invalid opcode error for MODE SENSE(10), access to mode pages larger than 255 bytes are not retried using MODE SENSE(6). To avoid buffer length overflows for the MODE_SENSE(10) case, check that len is smaller than 65535 bytes. While at it, also fix the folowing: * Use get_unaligned_be16() to retrieve the mode data length and block descriptor length fields of the mode sense reply header instead of using an open coded calculation. * Fix the kdoc dbd argument explanation: the DBD bit stands for Disable Block Descriptor, which is the opposite of what the dbd argument description was. Link: https://lore.kernel.org/r/20210820070255.682775-2-damien.lemoal@wdc.com Signed-off-by: Damien Le Moal Signed-off-by: Martin K. Petersen Signed-off-by: wanxiaoqing --- drivers/scsi/scsi_lib.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index dbeadca45b8d..702e04597c7f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2062,7 +2062,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); /** * scsi_mode_sense - issue a mode sense, falling back from 10 to six bytes if necessary. * @sdev: SCSI device to be queried - * @dbd: set if mode sense will allow block descriptors to be returned + * @dbd: set to prevent mode sense from returning block descriptors * @modepage: mode page being requested * @buffer: request buffer (may not be smaller than eight bytes) * @len: length of request buffer. @@ -2097,18 +2097,18 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, sshdr = &my_sshdr; retry: - use_10_for_ms = sdev->use_10_for_ms; + use_10_for_ms = sdev->use_10_for_ms || len > 255; if (use_10_for_ms) { - if (len < 8) - len = 8; + if (len < 8 || len > 65535) + return -EINVAL; cmd[0] = MODE_SENSE_10; - cmd[8] = len; + put_unaligned_be16(len, &cmd[7]); header_length = 8; } else { if (len < 4) - len = 4; + return -EINVAL; cmd[0] = MODE_SENSE; cmd[4] = len; @@ -2133,7 +2133,11 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, if ((sshdr->sense_key == ILLEGAL_REQUEST) && (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { /* - * Invalid command operation code + * Invalid command operation code: retry using + * MODE SENSE(6) if this was a MODE SENSE(10) + * request, except if the request mode page is + * too large for MODE SENSE single byte + * allocation length field. */ sdev->use_10_for_ms = 0; goto retry; @@ -2152,12 +2156,11 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, data->longlba = 0; data->block_descriptor_length = 0; } else if (use_10_for_ms) { - data->length = buffer[0]*256 + buffer[1] + 2; + data->length = get_unaligned_be16(&buffer[0]) + 2; data->medium_type = buffer[2]; data->device_specific = buffer[3]; data->longlba = buffer[4] & 0x01; - data->block_descriptor_length = buffer[6]*256 - + buffer[7]; + data->block_descriptor_length = get_unaligned_be16(&buffer[6]); } else { data->length = buffer[0] + 1; data->medium_type = buffer[1]; -- Gitee From 627ba40ac8371f5872e102403938bebae21cf1d5 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 6 Feb 2024 17:18:20 -0800 Subject: [PATCH 5/5] tls: fix race between tx work scheduling and socket close mainline inclusion from mainline-v6.8-rc5 commit e01e3934a1b2d122919f73bc6ddbe1cdafc4bbdb category: bugfix issue: #I94PW7 CVE: CVE-2024-26585 Signed-off-by: wanxiaoqing --------------------------------------- Similarly to previous commit, the submitting thread (recvmsg/sendmsg) may exit as soon as the async crypto handler calls complete(). Reorder scheduling the work before calling complete(). This seems more logical in the first place, as it's the inverse order of what the submitting thread will do. Reported-by: valis Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption of records for performance") Signed-off-by: Jakub Kicinski Reviewed-by: Simon Horman Reviewed-by: Sabrina Dubroca Signed-off-by: David S. Miller Signed-off-by: wanxiaoqing --- net/tls/tls_sw.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index dd980438f201..21e940b61931 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -443,7 +443,6 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err) struct scatterlist *sge; struct sk_msg *msg_en; struct tls_rec *rec; - bool ready = false; int pending; rec = container_of(aead_req, struct tls_rec, aead_req); @@ -475,8 +474,12 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err) /* If received record is at head of tx_list, schedule tx */ first_rec = list_first_entry(&ctx->tx_list, struct tls_rec, list); - if (rec == first_rec) - ready = true; + if (rec == first_rec) { + /* Schedule the transmission */ + if (!test_and_set_bit(BIT_TX_SCHEDULED, + &ctx->tx_bitmask)) + schedule_delayed_work(&ctx->tx_work.work, 1); + } } spin_lock_bh(&ctx->encrypt_compl_lock); @@ -485,13 +488,6 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err) if (!pending && ctx->async_notify) complete(&ctx->async_wait.completion); spin_unlock_bh(&ctx->encrypt_compl_lock); - - if (!ready) - return; - - /* Schedule the transmission */ - if (!test_and_set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) - schedule_delayed_work(&ctx->tx_work.work, 1); } static int tls_do_encryption(struct sock *sk, -- Gitee