From nobody Thu Dec 18 08:13:34 2025 Received: from mr85p00im-ztdg06011201.me.com (mr85p00im-ztdg06011201.me.com [17.58.23.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 02E551F75A0 for ; Tue, 17 Dec 2024 13:08:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=17.58.23.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734440893; cv=none; b=gGVyWDYEGUmzWNyT0h9KivvR7g/Fl13v6kkjxNNqkD7SObRimihVhHrQR+CjtxAwm3W0CrYuYfUXjeeLy49Zsq+tNVf9w0n7iehiwM5JUYpYdpeURZ60J8Ta5/jUd3fBrKMKRSuEMobbMaHZWtN6rKJ+mm/hcam4M6KBOGu10/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734440893; c=relaxed/simple; bh=VZavQ++21q2uPUZ1FUNPyQJnRNl6BcSboy0lOQqrykI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PlvMgZQD3A0sHuvFuU4/M7OC9eynQL4DMnSU3zE/wfxIZLXm5audsj9i3nzlFYUR3TaPbeqlQbh+B9wNmb7bbgSvpXAofdmd8pTDatrvf3F6GdFIJb8KuoegJ7vOT6pRm0BOEdJ2xfxIoY4I1M9xyj/FpytUNZFVbrJtQVUOcfs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com; spf=pass smtp.mailfrom=icloud.com; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b=yL+E8R+A; arc=none smtp.client-ip=17.58.23.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=icloud.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b="yL+E8R+A" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1734440889; bh=xQkfDGL0XIq7y1IU6Bhqw+rN458Q+Hz+5g2SVbEqwoU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To: x-icloud-hme; b=yL+E8R+A/oJ/fSmUCF+22x7yo61F5LN7YNkPGBJ23O0kz2dwoQiUuSwwVmGjlpKvc +yY5BMTMs/6KOnInDzUbGdHo5rb/YeKBSQGbhsfPW8iCc9JUorAIWi/4hcYPjsNrFy EGYA5VMXSizyHicoQ0PbQ/+5Zu+i6nIZMLWay/OxZXm1bBVlVJOmxu41FV8eLS0hqe HaFIxks4x4xmHi6RmxbuyywGDLR0nMLbe/Gxfe1nMbxJUFLy/tOGUkyNGR6vanZ5Ha 9z60T0Ap/cTYwO/8w/rAnS7DG62DbdQEfo7TS3vFxL5dITb8SHoMMv04FkadV3aKvI hnRaMe/C5f7Gg== Received: from [192.168.1.26] (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id 7C271960252; Tue, 17 Dec 2024 13:08:06 +0000 (UTC) From: Zijun Hu Date: Tue, 17 Dec 2024 21:07:30 +0800 Subject: [PATCH v3 6/7] of: Fix potential wrong MODALIAS uevent value 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="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241217-of_core_fix-v3-6-3bc49a2e8bda@quicinc.com> References: <20241217-of_core_fix-v3-0-3bc49a2e8bda@quicinc.com> In-Reply-To: <20241217-of_core_fix-v3-0-3bc49a2e8bda@quicinc.com> To: Rob Herring , Saravana Kannan , Maxime Ripard , Robin Murphy , Grant Likely Cc: Zijun Hu , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Zijun Hu X-Mailer: b4 0.14.2 X-Proofpoint-GUID: ehRZmWmdSfAKaTCii1oPUctISHaj8Mgj X-Proofpoint-ORIG-GUID: ehRZmWmdSfAKaTCii1oPUctISHaj8Mgj X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2024-12-17_07,2024-12-17_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 adultscore=0 clxscore=1015 malwarescore=0 suspectscore=0 mlxlogscore=944 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2308100000 definitions=main-2412170105 X-Apple-Remote-Links: v=1;h=KCk=;charset=UTF-8 From: Zijun Hu API of_device_uevent_modalias() makes uevent "MODALIAS=3DITS_VALUE" in two steps, namely, produces "MODALIAS=3D" with add_uevent_var() fistly, then remainning "ITS_VALUE" with of_modalias() finally, and that may result in various wrong uevents as explained below: "MODALIAS=3D\0" // @env->buf is full after the 1st step. "MODALIAS=3DITS_\0" // @env->buf is not enough during 2nd step. "MODALIAS=3DITS_VAR=3DVAR_VALUE\0" // another uevent "VAR=3DVAR_VALUE" come= s. The API depends on uevent internal design, so is not good practice as well. Fix by: 1) Respin the callee of_modalias() with new prototype which is friendly with its callers. 2) Invoke add_uevent_var() to make the whole MODALIAS uevent. 3) Adapt new of_modalias() for its other callers. BTW, there are no external callers of of_modalias() now. Closes: https://lore.kernel.org/all/CAL_JsqL+CRmCQMzcF4-A-PRBrCsfK8nduJtOO= =3DRrsDtCUUR7og@mail.gmail.com Signed-off-by: Zijun Hu --- drivers/of/device.c | 39 +++++++------------- drivers/of/module.c | 103 +++++++++++++++++++++++++++++++-----------------= ---- include/linux/of.h | 7 ++-- 3 files changed, 79 insertions(+), 70 deletions(-) diff --git a/drivers/of/device.c b/drivers/of/device.c index f24c19e7aba8e01656f503ae328a4e08aab5a5f3..6355707c200da9ced354132528a= dbcce24121247 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -195,19 +195,18 @@ EXPORT_SYMBOL(of_device_get_match_data); ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) { ssize_t sl; + char *ptr __free(kfree) =3D NULL; =20 if (!dev || !dev->of_node || dev->of_node_reused) return -ENODEV; =20 - sl =3D of_modalias(dev->of_node, str, len - 2); - if (sl < 0) - return sl; - if (sl > len - 2) + ptr =3D of_modalias(dev->of_node, &sl); + if (IS_ERR(ptr)) + return PTR_ERR(no_free_ptr(ptr)); + if (sl + 2 > len) return -ENOMEM; =20 - str[sl++] =3D '\n'; - str[sl] =3D 0; - return sl; + return snprintf(str, len, "%s\n", ptr); } EXPORT_SYMBOL_GPL(of_device_modalias); =20 @@ -256,30 +255,20 @@ EXPORT_SYMBOL_GPL(of_device_uevent); =20 int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent= _env *env) { - int sl; - int pos; + int ret; + char *ptr; =20 if ((!dev) || (!dev->of_node) || dev->of_node_reused) return -ENODEV; =20 - /* Devicetree modalias is tricky, we add it in 2 steps */ - if (add_uevent_var(env, "MODALIAS=3D")) - return -ENOMEM; + ptr =3D of_modalias(dev->of_node, NULL); + if (IS_ERR(ptr)) + return PTR_ERR(ptr); =20 - /* - * @env->buflen is pointing to the char after '\0' now - * override the '\0' to save MODALIAS value. - */ - pos =3D env->buflen - 1; - sl =3D of_modalias(dev->of_node, &env->buf[pos], - sizeof(env->buf) - pos); - if (sl < 0) - return sl; - if (sl >=3D (sizeof(env->buf) - pos)) - return -ENOMEM; - env->buflen =3D pos + sl + 1; + ret =3D add_uevent_var(env, "MODALIAS=3D%s", ptr); =20 - return 0; + kfree(ptr); + return ret; } EXPORT_SYMBOL_GPL(of_device_uevent_modalias); =20 diff --git a/drivers/of/module.c b/drivers/of/module.c index 1e735fc130ad3ea9046f08bfab2cc9a07914e633..03a2b1b381e5b353b6699dac183= c03186afb0486 100644 --- a/drivers/of/module.c +++ b/drivers/of/module.c @@ -8,71 +8,92 @@ #include #include =20 -ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) +/* + * of_modalias - get MODALIAS string value for a OF device node + * @np: the OF device node + * @lenp: MODALIAS string length returned if set, exclude '\0' + * + * This function gets MODALIAS value for a device node. + * + * Returns MODALIAS string on success, or ERR_PTR() on error. + * + * Note: please kfree successful return value afer using it. + */ +char *of_modalias(const struct device_node *np, ssize_t *lenp) { const char *compat; char *c; struct property *p; ssize_t csize; ssize_t tsize; + char *str =3D NULL; + ssize_t len =3D 0; + ssize_t pos =3D 0; + int counting =3D 1; + + if (lenp) + *lenp =3D 0; =20 /* - * Prevent a kernel oops in vsnprintf() -- it only allows passing a - * NULL ptr when the length is also 0. Also filter out the negative - * lengths... + * Two cycles controlled by @counting, the fist cycle counts + * chars, the second saves chars. */ - if ((len > 0 && !str) || len < 0) - return -EINVAL; + do { + /* Name & Type */ + /* %p eats all alphanum characters, so %c must be used here */ + csize =3D snprintf(str + pos, len - pos, "of:N%pOFn%c%s", np, 'T', + of_node_get_device_type(np)); + if (counting) + tsize =3D csize; + else + pos +=3D csize; =20 - /* Name & Type */ - /* %p eats all alphanum characters, so %c must be used here */ - csize =3D snprintf(str, len, "of:N%pOFn%c%s", np, 'T', - of_node_get_device_type(np)); - tsize =3D csize; - if (csize >=3D len) - csize =3D len > 0 ? len - 1 : 0; - len -=3D csize; - str +=3D csize; + of_property_for_each_string(np, "compatible", p, compat) { + csize =3D snprintf(str + pos, len - pos, "C%s", compat); + if (counting) { + tsize +=3D csize; + continue; + } =20 - of_property_for_each_string(np, "compatible", p, compat) { - csize =3D snprintf(str, len, "C%s", compat); - tsize +=3D csize; - if (csize >=3D len) - continue; - for (c =3D str; c; ) { - c =3D strchr(c, ' '); - if (c) - *c++ =3D '_'; + for (c =3D str + pos; c; ) { + c =3D strchr(c, ' '); + if (c) + *c++ =3D '_'; + } + pos +=3D csize; } - len -=3D csize; - str +=3D csize; - } =20 - return tsize; + if (counting) { + /* Include '\0' of MODALIAS string. */ + len =3D tsize + 1; + /* MODALIAS value is too long */ + if (unlikely(len > 2048)) + return ERR_PTR(-EINVAL); + + str =3D kmalloc(len, GFP_KERNEL); + if (!str) + return ERR_PTR(-ENOMEM); + } + + } while (counting--); + + if (lenp) + *lenp =3D tsize; + return str; } =20 int of_request_module(const struct device_node *np) { char *str; - ssize_t size; int ret; =20 if (!np) return -ENODEV; =20 - size =3D of_modalias(np, NULL, 0); - if (size < 0) - return size; - - /* Reserve an additional byte for the trailing '\0' */ - size++; - - str =3D kmalloc(size, GFP_KERNEL); - if (!str) - return -ENOMEM; + str =3D of_modalias(np, NULL); + if (IS_ERR(str)) + return PTR_ERR(str); =20 - of_modalias(np, str, size); - str[size - 1] =3D '\0'; ret =3D request_module(str); kfree(str); =20 diff --git a/include/linux/of.h b/include/linux/of.h index fe5d7b74c23b9701743f5debc3d030b765bc914f..f36bab2caa8ccffbd43593d8b67= 20946e19503e0 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -382,7 +382,7 @@ extern int of_count_phandle_with_args(const struct devi= ce_node *np, const char *list_name, const char *cells_name); =20 /* module functions */ -extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_= t len); +char *of_modalias(const struct device_node *np, ssize_t *lenp); extern int of_request_module(const struct device_node *np); =20 /* phandle iterator functions */ @@ -761,10 +761,9 @@ static inline int of_count_phandle_with_args(const str= uct device_node *np, return -ENOSYS; } =20 -static inline ssize_t of_modalias(const struct device_node *np, char *str, - ssize_t len) +static inline char *of_modalias(const struct device_node *np, ssize_t *len= p) { - return -ENODEV; + return ERR_PTR(-ENODEV); } =20 static inline int of_request_module(const struct device_node *np) --=20 2.34.1