tpm_i2c_stm_st33: fix oops when i2c client is unavailable
authorKent Yoder <key@linux.vnet.ibm.com>
Fri, 18 Jan 2013 23:42:25 +0000 (17:42 -0600)
committerKent Yoder <key@linux.vnet.ibm.com>
Tue, 5 Feb 2013 15:38:24 +0000 (09:38 -0600)
When no i2c bus exists, user-space can cause an oops by triggering a
device probe through a message sent to an i2c "new_device" sysfs entry.
Adding a check for a NULL i2c client structure in the probe function
closes the hole.

This patch also fixes accessing the NULL client struct in the print
function call reporting the error.

Reported-by: Peter Hüwe <PeterHuewe@gmx.de>
Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
drivers/char/tpm/tpm_i2c_stm_st33.c
drivers/char/tpm/tpm_i2c_stm_st33.h

index 24a33e08d0c6732516d581b3d06c2865951f571e..36524ed8ada9b0fdf5ab5a4ab98ae4348e3a5f25 100644 (file)
@@ -658,7 +658,8 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
        err = 0;
 
        if (client == NULL) {
-               dev_info(&client->dev, "client is NULL. exiting.\n");
+               pr_info("%s: i2c client is NULL. Device not accessible.\n",
+                       __func__);
                err = -ENODEV;
                goto end;
        }
@@ -677,6 +678,13 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
        }
 
        platform_data = client->dev.platform_data;
+
+       if (!platform_data) {
+               dev_info(&client->dev, "chip not available\n");
+               err = -ENODEV;
+               goto _tpm_clean_answer;
+       }
+
        platform_data->tpm_i2c_buffer[0] =
            kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
        if (platform_data->tpm_i2c_buffer[0] == NULL) {
@@ -759,7 +767,6 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
        tpm_get_timeouts(chip);
 
        i2c_set_clientdata(client, chip);
-       platform_data->bChipF = false;
 
        dev_info(chip->dev, "TPM I2C Initialized\n");
        return 0;
@@ -779,7 +786,6 @@ _tpm_clean_response1:
        platform_data->tpm_i2c_buffer[0] = NULL;
 _tpm_clean_answer:
        tpm_remove_hardware(chip->dev);
-       platform_data->bChipF = true;
 end:
        pr_info("TPM I2C initialisation fail\n");
        return err;
@@ -803,8 +809,8 @@ static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
                gpio_free(pin_infos->io_serirq);
                gpio_free(pin_infos->io_lpcpd);
 
-               if (pin_infos->bChipF != true)
-                       tpm_remove_hardware(chip->dev);
+               tpm_remove_hardware(chip->dev);
+
                if (pin_infos->tpm_i2c_buffer[1] != NULL) {
                        kzfree(pin_infos->tpm_i2c_buffer[1]);
                        pin_infos->tpm_i2c_buffer[1] = NULL;
index 5862d0376bd8aabe9d66e6eafc09d001c8aeee09..439a43249aa65052003fac83ccdcc8c160a1753f 100644 (file)
@@ -53,7 +53,6 @@ struct st33zp24_platform_data {
        int io_serirq;
        int io_lpcpd;
        struct i2c_client *client;
-       bool bChipF;
        u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
        struct completion irq_detection;
        struct mutex lock;