]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
i2c: atr: Fix end of loop test in i2c_atr_find_mapping_by_addr()
authorDan Carpenter <dan.carpenter@linaro.org>
Wed, 23 Apr 2025 08:21:18 +0000 (11:21 +0300)
committerWolfram Sang <wsa+renesas@sang-engineering.com>
Fri, 2 May 2025 14:39:54 +0000 (16:39 +0200)
When the list_for_each_entry_reverse() exits without hitting a break
then the list cursor points to invalid memory.  So this check for
if (c2a->fixed) is checking bogus memory.  Fix it by using a "found"
variable to track if we found what we were looking for or not.

The list head (i2c_atr_chan.alias_pairs) is not a full entry, it's just
a struct list_head. When the for loop runs to completion, c2a doesn't
point to a struct i2c_atr_alias_pair, so you can't access c2a->fixed.

Fixes: c3f55241882b ("i2c: Support dynamic address translation")
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Romain Gantois <romain.gantois@bootlin.com>
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
drivers/i2c/i2c-atr.c

index 8a5d9247fd29b9dd638319bdaec0052361720854..4f78e75b63a05a2ea574b431cec4daa51634b398 100644 (file)
@@ -240,6 +240,7 @@ i2c_atr_find_mapping_by_addr(struct i2c_atr_chan *chan, u16 addr)
        struct i2c_atr *atr = chan->atr;
        struct i2c_atr_alias_pair *c2a;
        struct list_head *alias_pairs;
+       bool found = false;
        u16 alias;
        int ret;
 
@@ -258,11 +259,14 @@ i2c_atr_find_mapping_by_addr(struct i2c_atr_chan *chan, u16 addr)
                if (unlikely(list_empty(alias_pairs)))
                        return NULL;
 
-               list_for_each_entry_reverse(c2a, alias_pairs, node)
-                       if (!c2a->fixed)
+               list_for_each_entry_reverse(c2a, alias_pairs, node) {
+                       if (!c2a->fixed) {
+                               found = true;
                                break;
+                       }
+               }
 
-               if (c2a->fixed)
+               if (!found)
                        return NULL;
 
                atr->ops->detach_addr(atr, chan->chan_id, c2a->addr);