lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <AANLkTikmw=Hoa_R94dKwy432Wm3XfMwuDvkqoT9xmJRY@mail.gmail.com>
Date:	Sat, 22 Jan 2011 02:09:04 +0100
From:	Andrea Merello <andrea.merello@...il.com>
To:	Antti Palosaari <crope@....fi>
Cc:	linux-kernel@...r.kernel.org
Subject: DVB TDA18218 tuner driver BUG in I2C write

Hello.

I'm looking at tda18218.c file from 2.6.37 kernel.
I think the tda18218_wr_regs function has a bug:

I think it works as long as priv->cfg->i2c_wr_max is > than len parameter,
but let's assume that priv->cfg->i2c_wr_max is set to 2.

If tda18218_wr_regs is called with len = 1 it is easy to see it does
not perform the write. In this case:

msg_len_max is priv->cfg->i2c_wr_max -1, thus it is 1
remainder is len % msg_len_max, thus it is 0

the 'for loop' condition (i <= quotient && remainder) is thus false
and no write is performed at all.

I changed the function so it writes correctly now for me. Maybe you
prefer to fix the original algo rather than heavily changing it as I
did. Anyway I attach the patch I produced to make it working here.

Please note that I tested this only with priv->cfg->i2c_wr_max set to
2 and with the AF9035 driver that is not even in the kernel (any plan
to include ?) and I couldn't try this with any other in-kernel driver
due to lack of HW. So the patch need to be eventually checked and
tested more.

Thank you
Andrea

--- drivers/media/common/tuners/tda18218_orig.c 2011-01-22
22:44:59.323333347 +0100
+++ drivers/media/common/tuners/tda18218.c      2011-01-22
22:46:36.846666668 +0100
@@ -28,8 +28,9 @@ MODULE_PARM_DESC(debug, "Turn on/off deb
 /* write multiple registers */
 static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8
*val, u8 len)
 {
-       int ret;
-       u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
+       int ret=0;
+       u8 buf[1+len], msg_len, msg_len_max;
+       int remaining;
        struct i2c_msg msg[1] = {
                {
                        .addr = priv->cfg->i2c_address,
@@ -39,18 +40,21 @@ static int tda18218_wr_regs(struct tda18
        };

        msg_len_max = priv->cfg->i2c_wr_max - 1;
-       quotient = len / msg_len_max;
-       remainder = len % msg_len_max;
-       msg_len = msg_len_max;
-       for (i = 0; (i <= quotient && remainder); i++) {
-               if (i == quotient)  /* set len of the last msg */
-                       msg_len = remainder;
-
-               msg[0].len = msg_len + 1;
-               buf[0] = reg + i * msg_len_max;
-               memcpy(&buf[1], &val[i * msg_len_max], msg_len);
+
+       remaining = len;
+       for (; remaining > 0;remaining -= msg_len_max) {
+
+               msg_len = remaining;
+
+               if (msg_len > msg_len_max)  /* set len of the last msg */
+                       msg_len = msg_len_max;
+
+               msg[0].len = msg_len +1;
+               buf[0] = reg + (len - remaining);
+               memcpy(&buf[1], &val[(len - remaining)], msg_len);

                ret = i2c_transfer(priv->i2c, msg, 1);
+
                if (ret != 1)
                        break;
        }
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ