From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f180.google.com (mail-pg1-f180.google.com [209.85.215.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B52DC2D73B6 for ; Tue, 14 Jul 2026 02:46:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.180 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783997164; cv=none; b=Cq23oTCXqHFN/Zj03PfLqUgEHauAlI5CbRP5yxsUehUdAiiY96u2qJogec3+xltbymKuYVJv9TD1A/wA+YuhKL5d9VZLimgSctr5WR1zpKhvjo1QaAa9uiNgQiMpperTNaV+fZgNM5AwAyWuxFZCWPLTX+aIwQj1oMIUbRs8EY0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783997164; c=relaxed/simple; bh=EeaJNaqRnue1bgIzFqPqf0kMfERKEhuD4YNZ2h33bCA=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition; b=Yd6/B3j1uWa0FfM5T+0sj+htB6NK6Z1SjhKKJ9Zvh1w6nqWBVovi49FhE/cPKwDz5s6znAsC8qszP7xzSkMrX8/Pwh2m0VCCIBnCfvDl7K8ik7x0ULEkIIbcpNzFBCZI7DriGvnFBexFi7AUKp1bjeyZnStwxMae2eSaSqRYwrc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=AwOiqE3u; arc=none smtp.client-ip=209.85.215.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AwOiqE3u" Received: by mail-pg1-f180.google.com with SMTP id 41be03b00d2f7-ca12086c06eso3193157a12.0 for ; Mon, 13 Jul 2026 19:46:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783997160; x=1784601960; darn=vger.kernel.org; h=content-disposition:content-type:mime-version:message-id:subject:cc :to:from:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=z5Xzqovkf4r6l1cNh02uht94WcMA18Xgy8viIdBKimo=; b=AwOiqE3uAW95SWf0K6zWOR++kb0R040aS3O/Nxo74N7sdlOa3H8nqXyl3WsE2u/2+Y iJMU1suPdWUyIEt90spV9+KtXG2PGBVX1tNwHGveNBvI2hKhopGMf7S2BNeATAdSgzvh 8a5UmbWkuK9HdTMzrmM54stp0YTIrL9E4ADYsD0m0awaSDJy3wwvC64iIGWqz9VBwafd Zh1yLx1+63y5xNnN0NtxaCvZwSkdJWbV/bZ6cLS+kseq3ALnFykP7oJ4sSn4apL/F/RF TUpsX7fMexGz+bn1f4DhUtGRlVDgtqBSNZFX8CfdP4u5f105s8rDLRamM/7gD9MteP9q j2hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783997160; x=1784601960; h=content-disposition:content-type:mime-version:message-id:subject:cc :to:from:date:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=z5Xzqovkf4r6l1cNh02uht94WcMA18Xgy8viIdBKimo=; b=S8hee8Xm1sm5KBLpb01jKXJLAxymo9gD9dl1H6HtagaTTAo4UQvx4DfcvHjDktQ79n YbQ+bsuQUMw5wBHZnpnPQzn7X2vmFnDHRLC0/SqVfsWuCt9OikMftwaZAgUfLaHju5g2 kl3TKZc6Ssi3XbtGUJ6SClydOwaLj/Tgi0CIEi07+eznGnRGCmO5Bafn9zkIm9GOc7nF fbDw55Z+Qkmpx/PplVRn1DZpSl8l7g8OMDH5yrJPEOR+x6z3332JCSZ90pQ73aRX0pBj 1qxREJfqfuE5wALSx7qofG0IgG+lv4W53ef+8/eTNyDt2Vk89SF6FiEzXNibH4AZtjQn r8EQ== X-Forwarded-Encrypted: i=1; AHgh+Rpucgy8T+PHBd8qWbJxAHtm5BnTMYuIAYgf0ky2UjjU805U+jqoXWQMUlEHpeRXuIFQBOUM6w+AYnXCKMI=@vger.kernel.org X-Gm-Message-State: AOJu0Yw9L0UojvG9ND0D15cvgKNcTBFbGwwW/IHeZS2cF7dh9aTi0yfS 53YfVmCFidOsxdMEQ+bIyaNx8vdlzWLqw+twRaMDaC52ake2xU6nxTOa X-Gm-Gg: AfdE7cmqEuldC5QV2eyrueDn6EzI0I9pV9YgTy9ZNwHy3RKiCb5fMsIbOSu1VGejORx WkgVCXE6AWL5Eo8k6Z1YyBbB+J1Aq822tevQNIaC9GlPnRW3SjCN8s/GodB+1Oxii/HDGuvwg1q 0qE1ZxmI03WqJeWMisFPVLtJaVniRehe9KA4lpjVlhhObnf0l21Ry/FcBaYlflsjcIA9GU9GxIG qjWGBYbO+aZPwXc2X1FjxfpVN3HJxRGetM/HIC1Z64+2PmaNKLHQQNmCbHtYisgba9DC1MQljIl K72wzyE5NYY6NBUnqXMCkWhXTQmg0gVu+fjLaOdkTqew9o+/8WzXE0DEkyWB1lPjk+8jgYHe/ze 7Pr1V8/97xs7Zb9U599razFycNG3L8WAYL/4tBF38CmKczjOcEYr1ENECA5GWqjvCrzmztfLqsW oSGKGzN+vjkSx4l273+J62nRslms3IBljP8cAcbwz+KTzJxX0U76gNBeG9lKbI8Tb5 X-Received: by 2002:a05:6a21:178a:b0:3c0:9c19:65bc with SMTP id adf61e73a8af0-3c110a6f523mr10997986637.68.1783997160047; Mon, 13 Jul 2026 19:46:00 -0700 (PDT) Received: from google.com ([2a00:79e0:2ebe:8:e15f:5d5f:580b:f2e9]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3120c8e41fcsm40985785eec.15.2026.07.13.19.45.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jul 2026 19:45:59 -0700 (PDT) Date: Mon, 13 Jul 2026 19:45:56 -0700 From: Dmitry Torokhov To: Andi Shyti Cc: Wolfram Sang , Bryam Vargas , linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RESEND PATCH] i2c: smbus: make i2c_smbus_read_block_data() safer Message-ID: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline i2c_smbus_read_block_data() is dangerous to use because it may deliver up to I2C_SMBUS_BLOCK_MAX (32) bytes, which may be surprising to the caller. Callers tend to allocate buffers of sizes big enough to hold data from a well-behaving device and do not expect that i2c_smbus_read_block_data() may attempt to write more data than expected. To make i2c_smbus_read_block_data() safer to use, change it so that it accepts size of the supplied buffer as another argument and ensure that it will not copy more data than the size of the buffer. To allow users to gradually transition to the new API employ some macro trickery allowing calling i2c_smbus_read_block_data() with either 3 or 4 arguments. When called with 3 arguments it is assumed that the buffer size is I2C_SMBUS_BLOCK_MAX bytes. Once everyone is transitioned to the 4 argument form the macros should be removed. Signed-off-by: Dmitry Torokhov --- This was sent out in October of '24 but unfortunately I did not get a reply from Wolfram... Documentation/i2c/dev-interface.rst | 5 +++-- drivers/i2c/i2c-core-smbus.c | 21 +++++++++++++-------- include/linux/i2c.h | 19 +++++++++++++++++-- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/Documentation/i2c/dev-interface.rst b/Documentation/i2c/dev-interface.rst index c277a8e1202b..4df5330aca00 100644 --- a/Documentation/i2c/dev-interface.rst +++ b/Documentation/i2c/dev-interface.rst @@ -161,9 +161,10 @@ for details) through the following functions:: __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value); __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length, __u8 *values); - __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values); + __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 length, + __u8 *values); __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, - __u8 *values); + const __u8 *values); All these transactions return -1 on failure; you can read errno to see what happened. The 'write' transactions return 0 on success; the diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index fa63bee0b345..1be0a47c6b30 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -208,11 +208,11 @@ s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command, EXPORT_SYMBOL(i2c_smbus_write_word_data); /** - * i2c_smbus_read_block_data - SMBus "block read" protocol + * __i2c_smbus_read_block_data - SMBus "block read" protocol * @client: Handle to slave device * @command: Byte interpreted by slave - * @values: Byte array into which data will be read; big enough to hold - * the data returned by the slave. SMBus allows at most 32 bytes. + * @length: size of the @values array. SMBus allows at most 32 bytes + * @values: Byte array into which data will be read * * This executes the SMBus "block read" protocol, returning negative errno * else the number of data bytes in the slave's response. @@ -222,22 +222,27 @@ EXPORT_SYMBOL(i2c_smbus_write_word_data); * support this; its emulation through I2C messaging relies on a specific * mechanism (I2C_M_RECV_LEN) which may not be implemented. */ -s32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command, - u8 *values) +s32 __i2c_smbus_read_block_data(const struct i2c_client *client, u8 command, + u8 length, u8 *values) { union i2c_smbus_data data; + int ret_len; int status; + if (length > I2C_SMBUS_BLOCK_MAX) + return -EINVAL; + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, I2C_SMBUS_READ, command, I2C_SMBUS_BLOCK_DATA, &data); if (status) return status; - memcpy(values, &data.block[1], data.block[0]); - return data.block[0]; + ret_len = min(length, data.block[0]); + memcpy(values, &data.block[1], ret_len); + return ret_len; } -EXPORT_SYMBOL(i2c_smbus_read_block_data); +EXPORT_SYMBOL(__i2c_smbus_read_block_data); /** * i2c_smbus_write_block_data - SMBus "block write" protocol diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 14ab4d3055af..3e685476fa15 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -174,8 +174,23 @@ i2c_smbus_write_word_swapped(const struct i2c_client *client, } /* Returns the number of read bytes */ -s32 i2c_smbus_read_block_data(const struct i2c_client *client, - u8 command, u8 *values); +s32 __i2c_smbus_read_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values); +/* + * This monstrosity allows to call i2c_smbus_read_block_data() with either + * 3 or 4 arguments and will be removed once all users have been switched + * to the 4 argument version. + */ +#define __i2c_smbus_read_block_data_3arg(client, cmd, values) \ + __i2c_smbus_read_block_data(client, cmd, I2C_SMBUS_BLOCK_MAX, values) +#define __i2c_smbus_read_block_data_4arg(client, cmd, length, values) \ + __i2c_smbus_read_block_data(client, cmd, length, values) +#define __i2c_smbus_read_block_data_impl(_1, _2, _3, _4, impl, ...) impl +#define i2c_smbus_read_block_data(client, cmd, varargs...) \ + __i2c_smbus_read_block_data_impl(client, cmd, varargs, \ + __i2c_smbus_read_block_data_4arg, \ + __i2c_smbus_read_block_data_3arg) \ + (client, cmd, varargs) s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values); /* Returns the number of read bytes */ -- 2.55.0.795.g602f6c329a-goog -- Dmitry