{"id":2222815,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2222815/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260413190713.283939-1-ematsumiya@suse.de/","project":{"id":12,"url":"http://patchwork.ozlabs.org/api/1.2/projects/12/?format=json","name":"Linux CIFS Client","link_name":"linux-cifs-client","list_id":"linux-cifs.vger.kernel.org","list_email":"linux-cifs@vger.kernel.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260413190713.283939-1-ematsumiya@suse.de>","list_archive_url":null,"date":"2026-04-13T19:07:06","name":"[1/8] smb: client: compress: fix buffer overrun in lz77_compress()","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"9c898c3c9905cfd5c6ad8bb447100eac5caf39e5","submitter":{"id":78375,"url":"http://patchwork.ozlabs.org/api/1.2/people/78375/?format=json","name":"Enzo Matsumiya","email":"ematsumiya@suse.de"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260413190713.283939-1-ematsumiya@suse.de/mbox/","series":[{"id":499741,"url":"http://patchwork.ozlabs.org/api/1.2/series/499741/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=499741","date":"2026-04-13T19:07:09","name":"[1/8] smb: client: compress: fix buffer overrun in lz77_compress()","version":1,"mbox":"http://patchwork.ozlabs.org/series/499741/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2222815/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2222815/checks/","tags":{},"related":[],"headers":{"Return-Path":"\n <linux-cifs+bounces-10775-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-cifs@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256\n header.s=susede2_rsa header.b=MUuNso+B;\n\tdkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256\n header.s=susede2_ed25519 header.b=mOmE7m5I;\n\tdkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de\n header.a=rsa-sha256 header.s=susede2_rsa header.b=MUuNso+B;\n\tdkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256\n header.s=susede2_ed25519 header.b=mOmE7m5I;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.105.105.114; helo=tor.lore.kernel.org;\n envelope-from=linux-cifs+bounces-10775-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de\n header.b=\"MUuNso+B\";\n\tdkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de\n header.b=\"mOmE7m5I\";\n\tdkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de\n header.b=\"MUuNso+B\";\n\tdkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de\n header.b=\"mOmE7m5I\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=195.135.223.130","smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=suse.de","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=suse.de","smtp-out1.suse.de;\n\tnone"],"Received":["from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fvcQv5xnkz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 05:09:27 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id B9EB7301D325\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 13 Apr 2026 19:07:30 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 16CB37262F;\n\tMon, 13 Apr 2026 19:07:30 +0000 (UTC)","from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 947FD38B7BC\n\tfor <linux-cifs@vger.kernel.org>; Mon, 13 Apr 2026 19:07:28 +0000 (UTC)","from imap1.dmz-prg2.suse.org (unknown [10.150.64.97])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby smtp-out1.suse.de (Postfix) with ESMTPS id CB1B36A8B4;\n\tMon, 13 Apr 2026 19:07:26 +0000 (UTC)","from imap1.dmz-prg2.suse.org (localhost [127.0.0.1])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 52A004B038;\n\tMon, 13 Apr 2026 19:07:26 +0000 (UTC)","from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167])\n\tby imap1.dmz-prg2.suse.org with ESMTPSA\n\tid QS4YBu4+3WkXEAAAD6G6ig\n\t(envelope-from <ematsumiya@suse.de>); Mon, 13 Apr 2026 19:07:26 +0000"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776107250; cv=none;\n b=VnFRJqCWVPkHXCqXqfGeG9OQk01P5kOgPBATgEBqd+8oXJz098oHs/oZo1FbOqWHIB2r8zjgGkd8kLpFZ5mh1CdSxzk0MwP9HlnLv7fV6f4MoROYAKNy1WVmJrBohw3nw77n6RMKnQAYdMTBFaagTBoPI/lolaCKGUY15SgTGzw=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776107250; c=relaxed/simple;\n\tbh=j91SzjZ2g9OpHX3ROrRd/Y6k480sxPDbnrwKL41AW+Q=;\n\th=From:To:Cc:Subject:Date:Message-ID:MIME-Version;\n b=dq2Kb9sSxvcdPRTOpr+cXNeQ5XFLy+bcoYgn6Pt/AWkpISE1dQwCVD3f5lFmq4+AZOrkFGs4Y9RMNhx4h22AwTsCjvYZqRdz3bX574Lq4IYz860Pf8EKrxxCWEMvgaPFf60XKUR4dlfaACI0AXqtMovmazSvvPZDxQM4bMIe4KI=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=suse.de;\n spf=pass smtp.mailfrom=suse.de;\n dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de\n header.b=MUuNso+B;\n dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de\n header.b=mOmE7m5I;\n dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de\n header.b=MUuNso+B;\n dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de\n header.b=mOmE7m5I; arc=none smtp.client-ip=195.135.223.130","DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de;\n s=susede2_rsa;\n\tt=1776107246;\n h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc:\n\t mime-version:mime-version:\n  content-transfer-encoding:content-transfer-encoding;\n\tbh=iNOE1chA0D7Yhs9M0bldWcMEAIZ98RbaBTci4JlK7oE=;\n\tb=MUuNso+BerNr2ufYtfVNj/3AxjTE9DMJxNDvoLGVh4hhQVkzGC43dgy6jAih2aoZPxKHPW\n\tUewrkRqdvwEaETIhuJVu3tBUY9hty8w9UkuLkL8r9ysIH7V0ZIKo/T/nKos9tZ863W2PeC\n\tOJcn7hrf50T2p95+BtAT2J3Rbib6eY4=","v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de;\n\ts=susede2_ed25519; t=1776107246;\n\th=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc:\n\t mime-version:mime-version:\n  content-transfer-encoding:content-transfer-encoding;\n\tbh=iNOE1chA0D7Yhs9M0bldWcMEAIZ98RbaBTci4JlK7oE=;\n\tb=mOmE7m5IuAU3D8p16zB2pb0Q3kBwjzc/rerUFqabGu8uB8/K21ZIaw/9ggSEesrRNzwtSl\n\t7ZHiim+g4IKGzkDw==","v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de;\n s=susede2_rsa;\n\tt=1776107246;\n h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc:\n\t mime-version:mime-version:\n  content-transfer-encoding:content-transfer-encoding;\n\tbh=iNOE1chA0D7Yhs9M0bldWcMEAIZ98RbaBTci4JlK7oE=;\n\tb=MUuNso+BerNr2ufYtfVNj/3AxjTE9DMJxNDvoLGVh4hhQVkzGC43dgy6jAih2aoZPxKHPW\n\tUewrkRqdvwEaETIhuJVu3tBUY9hty8w9UkuLkL8r9ysIH7V0ZIKo/T/nKos9tZ863W2PeC\n\tOJcn7hrf50T2p95+BtAT2J3Rbib6eY4=","v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de;\n\ts=susede2_ed25519; t=1776107246;\n\th=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc:\n\t mime-version:mime-version:\n  content-transfer-encoding:content-transfer-encoding;\n\tbh=iNOE1chA0D7Yhs9M0bldWcMEAIZ98RbaBTci4JlK7oE=;\n\tb=mOmE7m5IuAU3D8p16zB2pb0Q3kBwjzc/rerUFqabGu8uB8/K21ZIaw/9ggSEesrRNzwtSl\n\t7ZHiim+g4IKGzkDw=="],"From":"Enzo Matsumiya <ematsumiya@suse.de>","To":"linux-cifs@vger.kernel.org","Cc":"smfrench@gmail.com,\n\tpc@manguebit.com,\n\tronniesahlberg@gmail.com,\n\tsprasad@microsoft.com,\n\ttom@talpey.com,\n\tbharathsm@microsoft.com,\n\thenrique.carvalho@suse.com","Subject":"[PATCH 1/8] smb: client: compress: fix buffer overrun in\n lz77_compress()","Date":"Mon, 13 Apr 2026 16:07:06 -0300","Message-ID":"<20260413190713.283939-1-ematsumiya@suse.de>","X-Mailer":"git-send-email 2.53.0","Precedence":"bulk","X-Mailing-List":"linux-cifs@vger.kernel.org","List-Id":"<linux-cifs.vger.kernel.org>","List-Subscribe":"<mailto:linux-cifs+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-cifs+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-Spamd-Result":"default: False [-2.80 / 50.00];\n\tBAYES_HAM(-3.00)[100.00%];\n\tNEURAL_HAM_LONG(-1.00)[-1.000];\n\tMID_CONTAINS_FROM(1.00)[];\n\tR_MISSING_CHARSET(0.50)[];\n\tNEURAL_HAM_SHORT(-0.20)[-0.999];\n\tMIME_GOOD(-0.10)[text/plain];\n\tTO_MATCH_ENVRCPT_ALL(0.00)[];\n\tFUZZY_RATELIMITED(0.00)[rspamd.com];\n\tFROM_HAS_DN(0.00)[];\n\tRCVD_VIA_SMTP_AUTH(0.00)[];\n\tFREEMAIL_CC(0.00)[gmail.com,manguebit.com,microsoft.com,talpey.com,suse.com];\n\tARC_NA(0.00)[];\n\tTO_DN_NONE(0.00)[];\n\tRCVD_TLS_ALL(0.00)[];\n\tFROM_EQ_ENVFROM(0.00)[];\n\tRCVD_COUNT_TWO(0.00)[2];\n\tRCPT_COUNT_SEVEN(0.00)[8];\n\tDBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:mid,suse.de:email];\n\tMIME_TRACE(0.00)[0:+];\n\tDKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519];\n\tFREEMAIL_ENVRCPT(0.00)[gmail.com]","X-Spam-Flag":"NO","X-Spam-Score":"-2.80","X-Spam-Level":""},"content":"@dst buffer is allocated with same size as @src, which, for good\ncompression cases, works fine.\n\nHowever, when compression goes bad (e.g. random bytes payloads), the\ncompressed size can increase significantly, and even by stopping the\nmain loop at 7/8 of @slen, writing leftover literals could write past\nthe end of @dst because of LZ77 metadata.\n\nTo fix this, add lz77_compressed_alloc_size() helper to compute the\ncorrect allocation size for @dst, accounting for metadata and worst\ncast scenario (all literals).\n\nWhile this is overprovisioning memory, it's not only correct, but also\nallows lz77_compress() main loop to run without ever checking @dst\nlimits (i.e. a perf improvement).\n\nSigned-off-by: Enzo Matsumiya <ematsumiya@suse.de>\n---\n fs/smb/client/compress.c      |  6 +-----\n fs/smb/client/compress/lz77.c | 14 ++++----------\n fs/smb/client/compress/lz77.h | 28 ++++++++++++++++++++++++++++\n 3 files changed, 33 insertions(+), 15 deletions(-)","diff":"diff --git a/fs/smb/client/compress.c b/fs/smb/client/compress.c\nindex 3d1e73f5d9af..be9023f841e6 100644\n--- a/fs/smb/client/compress.c\n+++ b/fs/smb/client/compress.c\n@@ -329,11 +329,7 @@ int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, compress_s\n \t\tgoto err_free;\n \t}\n \n-\t/*\n-\t * This is just overprovisioning, as the algorithm will error out if @dst reaches 7/8\n-\t * of @slen.\n-\t */\n-\tdlen = slen;\n+\tdlen = lz77_compressed_alloc_size(slen);\n \tdst = kvzalloc(dlen, GFP_KERNEL);\n \tif (!dst) {\n \t\tret = -ENOMEM;\ndiff --git a/fs/smb/client/compress/lz77.c b/fs/smb/client/compress/lz77.c\nindex 96e8a8057a77..16c7d8f3ef17 100644\n--- a/fs/smb/client/compress/lz77.c\n+++ b/fs/smb/client/compress/lz77.c\n@@ -137,6 +137,10 @@ noinline int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen)\n \tlong flag = 0;\n \tu64 *htable;\n \n+\t/* This is probably a bug, so throw a warning. */\n+\tif (WARN_ON_ONCE(*dlen < lz77_compressed_alloc_size(slen)))\n+\t\treturn -EINVAL;\n+\n \tsrcp = src;\n \tend = src + slen;\n \tdstp = dst;\n@@ -180,15 +184,6 @@ noinline int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen)\n \t\t\tcontinue;\n \t\t}\n \n-\t\t/*\n-\t\t * Bail out if @dstp reached >= 7/8 of @slen -- already compressed badly, not worth\n-\t\t * going further.\n-\t\t */\n-\t\tif (unlikely(dstp - dst >= slen - (slen >> 3))) {\n-\t\t\t*dlen = slen;\n-\t\t\tgoto out;\n-\t\t}\n-\n \t\tdstp = lz77_write_match(dstp, &nib, dist, len);\n \t\tsrcp += len;\n \n@@ -225,7 +220,6 @@ noinline int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen)\n \tlz77_write32(flag_pos, flag);\n \n \t*dlen = dstp - dst;\n-out:\n \tkvfree(htable);\n \n \tif (*dlen < slen)\ndiff --git a/fs/smb/client/compress/lz77.h b/fs/smb/client/compress/lz77.h\nindex cdcb191b48a2..2603eab9e071 100644\n--- a/fs/smb/client/compress/lz77.h\n+++ b/fs/smb/client/compress/lz77.h\n@@ -11,5 +11,33 @@\n \n #include <linux/kernel.h>\n \n+/**\n+ * lz77_compressed_alloc_size() - Compute compressed buffer size.\n+ * @size:\tuncompressed (src) size\n+ *\n+ * Compute allocation size for the compressed buffer based on uncompressed size.\n+ * Accounts for metadata and overprovision for the worst case scenario.\n+ *\n+ * LZ77 metadata is a 4-byte flag that is written:\n+ * - on dst begin (pos 0)\n+ * - every 32 literals or matches\n+ * - on end-of-stream (possibly, if last write was another flag)\n+ *\n+ * Worst case scenario is an all-literal compression, which means:\n+ * metadata bytes = 4 + ((@size / 32) * 4) + 4, or, simplified, (@size >> 3) + 8\n+ *\n+ * The worst case scenario rarely happens, but such overprovisioning also allows lz77_compress()\n+ * main loop to run without ever bound checking dst, which is a huge perf improvement, while also\n+ * being safe when compression goes bad.\n+ *\n+ * Return: required (*) allocation size for compressed buffer.\n+ *\n+ * (*) checked once in the beginning of lz77_compress()\n+ */\n+static __always_inline u32 lz77_compressed_alloc_size(const u32 size)\n+{\n+\treturn size + (size >> 3) + 8;\n+}\n+\n int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen);\n #endif /* _SMB_COMPRESS_LZ77_H */\n","prefixes":["1/8"]}