Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1979527pxb; Fri, 5 Mar 2021 04:40:01 -0800 (PST) X-Google-Smtp-Source: ABdhPJzhcfRGdbVAyToTzZRe8LfoP5kKpdWkhtl7R44JkiAU640w+Uwf4sS7wxs7u7yg9DXHQGbx X-Received: by 2002:a17:907:d8a:: with SMTP id go10mr2112009ejc.46.1614948000826; Fri, 05 Mar 2021 04:40:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614948000; cv=none; d=google.com; s=arc-20160816; b=ikS6SpGYOFU/9bo2EM8LtJNmPuzf3iW6gmLGbcChc9dYH9GFnvF3HboYT3e+Dgnqn4 sBqHK6qbyDzVuTM8ZCxLbA7/RRXVEQHq20VqVEfzjcV7LGYS2oyqlmBjmge0ayOh7qb9 4Ap40iVBMl44agJwLcFYK/qyCiGpXy5/6uAA9YpjDZmIw+hXnUKQIQq8k8EdQggM66ul utHtgLzSRntYfiUno+F7nOQawsDoQLqMHutpqNp9phVFL3vOlqSyZlsvptyOPWIIOX6f uMU0Yw10XplED1gPxoqXQcwirSuSnJQKBGfCy4AR7pLP1yyN3BZKFoL4aPh86aSwoFl6 cCaQ== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=eSw0s9/NaH/P7whbHMyQ1j5d3MzopQBFTM9Jw1FDByg=; b=bML61B+Uk06++FVZWcrsPxjDr1KXtBvJjbhB27Ow8nDG+VIqYzOv/L9pi7YdOxdVaj q/i0mWmoYumGBpFGyVnFu5xu3cW1s6AiKU8858bn/c/nDibbd+zAVKm4bbsAytesdZY2 qF9HO3jX5CPoOoriPFAHVG55lZkq/fi3tXIBw6Ph8CX1u7kF9v6956/5nNDtYivcY5ul Pqa0urS48mlvF6t9pdlq1ixuEG8YrMKT1V28BfxB1wWZd+VH2LNW9Q8iK1U3oxFFiTs1 Lpw6YhamwtLyt6LsPp70TwekHSxV20VX7JbogPRo5jpGkXOF4w3CVhujH457/RkUB6bd eTsg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=z4jRbGG8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id g17si1441239eds.403.2021.03.05.04.39.37; Fri, 05 Mar 2021 04:40:00 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=z4jRbGG8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233080AbhCEMih (ORCPT + 99 others); Fri, 5 Mar 2021 07:38:37 -0500 Received: from mail.kernel.org ([198.145.29.99]:51052 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232544AbhCEMhx (ORCPT ); Fri, 5 Mar 2021 07:37:53 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id D25FD64FF0; Fri, 5 Mar 2021 12:37:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1614947873; bh=6b7ws9VccgdXAqfLQQjsFSU4aoTLP5wS01AjGKj+Xrc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=z4jRbGG8mEkuCYWjsYa00fee1uOB6hcX6aopq0MnCv4DZeM8woW8V6iuputVQ0D5S CBIO7wFSeBevfpMKvgUyJHi0HP6gwZDMiIvb0MWOlm+Qlv/z0vde/ZoDWbGsvqzUBA 6mnOrUxbXWt1dSeYNnDkJsK2JkIl1KBY8d8vVXds= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Joe Perches Subject: [PATCH 4.19 43/52] sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output Date: Fri, 5 Mar 2021 13:22:14 +0100 Message-Id: <20210305120855.762259636@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210305120853.659441428@linuxfoundation.org> References: <20210305120853.659441428@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Joe Perches commit 2efc459d06f1630001e3984854848a5647086232 upstream. Output defects can exist in sysfs content using sprintf and snprintf. sprintf does not know the PAGE_SIZE maximum of the temporary buffer used for outputting sysfs content and it's possible to overrun the PAGE_SIZE buffer length. Add a generic sysfs_emit function that knows that the size of the temporary buffer and ensures that no overrun is done. Add a generic sysfs_emit_at function that can be used in multiple call situations that also ensures that no overrun is done. Validate the output buffer argument to be page aligned. Validate the offset len argument to be within the PAGE_SIZE buf. Signed-off-by: Joe Perches Link: https://lore.kernel.org/r/884235202216d464d61ee975f7465332c86f76b2.1600285923.git.joe@perches.com Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/sysfs.txt | 8 +---- fs/sysfs/file.c | 55 ++++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 16 ++++++++++ 3 files changed, 74 insertions(+), 5 deletions(-) --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -211,12 +211,10 @@ Other notes: is 4096. - show() methods should return the number of bytes printed into the - buffer. This is the return value of scnprintf(). + buffer. -- show() must not use snprintf() when formatting the value to be - returned to user space. If you can guarantee that an overflow - will never happen you can use sprintf() otherwise you must use - scnprintf(). +- show() should only use sysfs_emit() or sysfs_emit_at() when formatting + the value to be returned to user space. - store() should return the number of bytes used from the buffer. If the entire buffer has been used, just return the count argument. --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "sysfs.h" #include "../kernfs/kernfs-internal.h" @@ -556,3 +557,57 @@ void sysfs_remove_bin_file(struct kobjec kernfs_remove_by_name(kobj->sd, attr->attr.name); } EXPORT_SYMBOL_GPL(sysfs_remove_bin_file); + +/** + * sysfs_emit - scnprintf equivalent, aware of PAGE_SIZE buffer. + * @buf: start of PAGE_SIZE buffer. + * @fmt: format + * @...: optional arguments to @format + * + * + * Returns number of characters written to @buf. + */ +int sysfs_emit(char *buf, const char *fmt, ...) +{ + va_list args; + int len; + + if (WARN(!buf || offset_in_page(buf), + "invalid sysfs_emit: buf:%p\n", buf)) + return 0; + + va_start(args, fmt); + len = vscnprintf(buf, PAGE_SIZE, fmt, args); + va_end(args); + + return len; +} +EXPORT_SYMBOL_GPL(sysfs_emit); + +/** + * sysfs_emit_at - scnprintf equivalent, aware of PAGE_SIZE buffer. + * @buf: start of PAGE_SIZE buffer. + * @at: offset in @buf to start write in bytes + * @at must be >= 0 && < PAGE_SIZE + * @fmt: format + * @...: optional arguments to @fmt + * + * + * Returns number of characters written starting at &@buf[@at]. + */ +int sysfs_emit_at(char *buf, int at, const char *fmt, ...) +{ + va_list args; + int len; + + if (WARN(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE, + "invalid sysfs_emit_at: buf:%p at:%d\n", buf, at)) + return 0; + + va_start(args, fmt); + len = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args); + va_end(args); + + return len; +} +EXPORT_SYMBOL_GPL(sysfs_emit_at); --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -299,6 +299,11 @@ static inline void sysfs_enable_ns(struc return kernfs_enable_ns(kn); } +__printf(2, 3) +int sysfs_emit(char *buf, const char *fmt, ...); +__printf(3, 4) +int sysfs_emit_at(char *buf, int at, const char *fmt, ...); + #else /* CONFIG_SYSFS */ static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) @@ -505,6 +510,17 @@ static inline void sysfs_enable_ns(struc { } +__printf(2, 3) +static inline int sysfs_emit(char *buf, const char *fmt, ...) +{ + return 0; +} + +__printf(3, 4) +static inline int sysfs_emit_at(char *buf, int at, const char *fmt, ...) +{ + return 0; +} #endif /* CONFIG_SYSFS */ static inline int __must_check sysfs_create_file(struct kobject *kobj,