From: Zijun Hu <quic_zijuhu@xxxxxxxxxxx> class_dev_iter_init(struct class_dev_iter *iter, struct class *class, ...) has return type void, but it does not initialize its output parameter @iter when suffers class_to_subsys(@class) error, so caller can not detect the error and call API class_dev_iter_next(@iter) which will dereference wild pointers of @iter's members as shown by below typical usage: // @iter's members are wild pointers struct class_dev_iter iter; // No change in @iter when the error happens. class_dev_iter_init(&iter, ...); // dereference these wild member pointers here. while (dev = class_dev_iter_next(&iter)) { ... }. Actually, all callers of the API have such usage pattern in kernel tree. Fix by memset() @iter in API *_init() and error checking @iter in *_next(). Fixes: 7b884b7f24b4 ("driver core: class.c: convert to only use class_to_subsys") Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Zijun Hu <quic_zijuhu@xxxxxxxxxxx> --- Alternative fix solutions ever thought about: 1) Use BUG_ON(!sp) instead of error return in class_dev_iter_init(). 2) Change class_dev_iter_init()'s type to int, lots of jobs to do. --- drivers/base/class.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index cb5359235c70..b331dda002e3 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -323,8 +323,11 @@ void class_dev_iter_init(struct class_dev_iter *iter, const struct class *class, struct subsys_private *sp = class_to_subsys(class); struct klist_node *start_knode = NULL; - if (!sp) + memset(iter, 0, sizeof(*iter)); + if (!sp) { + pr_crit("%s: the class was not registered yet\n", __func__); return; + } if (start) start_knode = &start->p->knode_class; @@ -351,6 +354,9 @@ struct device *class_dev_iter_next(struct class_dev_iter *iter) struct klist_node *knode; struct device *dev; + if (!iter->sp) + return NULL; + while (1) { knode = klist_next(&iter->ki); if (!knode) -- 2.34.1