From nobody Wed Dec 17 19:39:38 2025 Received: from pv50p00im-ztdg10021101.me.com (pv50p00im-ztdg10021101.me.com [17.58.6.44]) (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 06C358F49 for ; Mon, 16 Dec 2024 00:42:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=17.58.6.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734309725; cv=none; b=fJb8kSoeaA+9TqOixUulaTDKuSXMFKskMAg84E7WFlU/w3WqCMi6ac3hSiAxzZQ7NYQSlWWKKR3x2VAbfcaVwiEaAa3YpGHeVsnggFeobN8puVVXGI4rFgLCFt+FxT5KENzc79QnHpaQcbbLa3HOO0S1n+ah866Z2LBk9cACnQA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734309725; c=relaxed/simple; bh=nSYXCv7Z/bKVTSvJE3MUbp8NkYW76YNJJBAJAlkRWY4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tD5McTiCk3OqFG9ZRn5oBw8ueo00RtRIgthy60vTNiWJSsX8SjZOH5/LbVNqbvtDuPKKFjoAaRtavR/a8JMjGKXwjHspsHW1DubsT3/QjQyxHnizSf/ynZBPQQ/jsxWCMID4zCASFr15nMDCrw4jP8JuhYgj67oeA5IFdtRFDk0= 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=EdnHadMU; arc=none smtp.client-ip=17.58.6.44 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="EdnHadMU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1734309723; bh=Ak4E137BxRWwHua7Mm4mhu/aSYLHuL/rTY58sloG2vo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To: x-icloud-hme; b=EdnHadMUmgr7r4hIOT4FUgy7fRvgdd16kUhJv2os4pjD+CqUWxucoGbcFPsT7OzYf THM78NPM80HSMy2SHayB1Nut6wFpbHvIgxnyXvxuoCGM9dwoUIlM4Gp5k0YXBZ7G/t YoSaXyyOUbDacKCefMoUApi0+HKHopMSh9Inqfz4cIUaO+lT5L0Ld+95E9t7zl6D22 AFRzEHS8ZA4+hOqdHRKSNzhktrAXDSBMV2E8qD+oYJRJd4NWqwEg4cQJgQ50CYIP+H C1negPcaY8S59P2+wQMKssu1+ZR2dw090h67vUZos955bA1KCLZ/MZgj3T2AXQFu67 LWFdcc4ocDnNg== Received: from [192.168.1.26] (pv50p00im-dlb-asmtp-mailmevip.me.com [17.56.9.10]) by pv50p00im-ztdg10021101.me.com (Postfix) with ESMTPSA id 3F7F5D0015A; Mon, 16 Dec 2024 00:41:29 +0000 (UTC) From: Zijun Hu Date: Mon, 16 Dec 2024 08:40:45 +0800 Subject: [PATCH v2 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: <20241216-of_core_fix-v2-6-e69b8f60da63@quicinc.com> References: <20241216-of_core_fix-v2-0-e69b8f60da63@quicinc.com> In-Reply-To: <20241216-of_core_fix-v2-0-e69b8f60da63@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-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 | 5 +-- 3 files changed, 78 insertions(+), 69 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 7b0da8d352dffd8b872998903282119b6164a5bc..2fcc12de4a9178276a24cd4d6c9= 75495b9eb04a2 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 */ @@ -762,8 +762,7 @@ static inline int of_count_phandle_with_args(const stru= ct 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; } --=20 2.34.1