tegra: camera: validate PCLLK_IOCTL_SEQ_XX params
Greg Hackmann [Fri, 19 Feb 2016 23:04:23 +0000 (15:04 -0800)]
The driver expects the userspace-provided table to be terminated with
addr == CAMERA_TABLE_END.  Reject tables that aren't.

(back ported from Nexus N9 project)

Bug 1832830

Change-Id: Id1e168e02fbf323d094fe8c36c6e4bd90cceee4f
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Reviewed-on: http://git-master/r/1271368
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Frank Chen <frankc@nvidia.com>
Tested-by: Frank Chen <frankc@nvidia.com>
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>

drivers/media/platform/tegra/camera.c

index f54a3c0..a8bba03 100644 (file)
@@ -178,6 +178,20 @@ int __camera_get_params(
        return 0;
 }
 
+static int camera_validate_p_i2c_table(struct camera_info *cam,
+               const struct nvc_param *params,
+               const struct camera_reg *p_i2c_table, const char *caller)
+{
+       u32 idx, last_idx = params->sizeofvalue / sizeof(p_i2c_table[0]);
+
+       for (idx = 0; idx < last_idx; idx++)
+               if (p_i2c_table[idx].addr == CAMERA_TABLE_END)
+                       return 0;
+
+       dev_err(cam->dev, "%s: table is not properly terminated\n", caller);
+       return -EINVAL;
+}
+
 static int camera_seq_rd(struct camera_info *cam, unsigned long arg)
 {
        struct nvc_param params;
@@ -189,6 +203,10 @@ static int camera_seq_rd(struct camera_info *cam, unsigned long arg)
        if (err)
                return err;
 
+       err = camera_validate_p_i2c_table(cam, &params, p_i2c_table, __func__);
+       if (err)
+               goto seq_rd_end;
+
        err = camera_dev_rd_table(cam->cdev, p_i2c_table);
        if (!err && copy_to_user(MAKE_USER_PTR(params.p_value),
                p_i2c_table, params.sizeofvalue)) {
@@ -197,6 +215,7 @@ static int camera_seq_rd(struct camera_info *cam, unsigned long arg)
                err = -EINVAL;
        }
 
+seq_rd_end:
        kfree(p_i2c_table);
        return err;
 }
@@ -251,6 +270,10 @@ static int camera_seq_wr(struct camera_info *cam, unsigned long arg)
                goto seq_wr_end;
        }
 
+       err = camera_validate_p_i2c_table(cam, &params, p_i2c_table, __func__);
+       if (err)
+               goto seq_wr_end;
+
        switch (params.param) {
        case CAMERA_SEQ_REGISTER_EXEC:
        case CAMERA_SEQ_REGISTER_ONLY: