ソースを参照

disp: msm: sde: ensure string buffer is properly terminated

Give snprintf the max size posssible to store in buffer or
copy_to_user instead of just truncating in order to ensure
the output string is properly terminated.

Change-Id: Id387e99cd035e39530b2c7de9484c0288efff605
Signed-off-by: Steve Cohen <[email protected]>
Steve Cohen 5 年 前
コミット
1b7e54c362
2 ファイル変更16 行追加17 行削除
  1. 12 10
      msm/sde_rsc.c
  2. 4 7
      msm/sde_rsc_hw.c

+ 12 - 10
msm/sde_rsc.c

@@ -1357,6 +1357,7 @@ static ssize_t _sde_debugfs_mode_ctrl_read(struct file *file, char __user *buf,
 	struct sde_rsc_priv *rsc = file->private_data;
 	char buffer[MAX_BUFFER_SIZE];
 	int blen = 0;
+	size_t max_size = min_t(size_t, count, MAX_BUFFER_SIZE);
 
 	if (*ppos || !rsc || !rsc->hw_ops.mode_ctrl)
 		return 0;
@@ -1364,23 +1365,23 @@ static ssize_t _sde_debugfs_mode_ctrl_read(struct file *file, char __user *buf,
 	mutex_lock(&rsc->client_lock);
 	if (rsc->current_state == SDE_RSC_IDLE_STATE) {
 		pr_debug("debug node is not supported during idle state\n");
-		blen = snprintf(buffer, MAX_BUFFER_SIZE,
+		blen = scnprintf(buffer, max_size,
 				"hw state is not supported during idle pc\n");
 		goto end;
 	}
 
-	blen = rsc->hw_ops.mode_ctrl(rsc, MODE_READ, buffer,
-							MAX_BUFFER_SIZE, 0);
+	blen = rsc->hw_ops.mode_ctrl(rsc, MODE_READ, buffer, max_size, 0);
 
 end:
 	mutex_unlock(&rsc->client_lock);
 	if (blen <= 0)
 		return 0;
 
-	if (blen > count)
+	if (blen > count) {
 		blen = count;
+		buffer[count - 1] = '\0';
+	}
 
-	blen = min_t(size_t, blen, MAX_BUFFER_SIZE);
 	if (copy_to_user(buf, buffer, blen))
 		return -EFAULT;
 
@@ -1447,6 +1448,7 @@ static ssize_t _sde_debugfs_vsync_mode_read(struct file *file, char __user *buf,
 	struct sde_rsc_priv *rsc = file->private_data;
 	char buffer[MAX_BUFFER_SIZE];
 	int blen = 0;
+	size_t max_size = min_t(size_t, count, MAX_BUFFER_SIZE);
 
 	if (*ppos || !rsc || !rsc->hw_ops.hw_vsync)
 		return 0;
@@ -1454,23 +1456,23 @@ static ssize_t _sde_debugfs_vsync_mode_read(struct file *file, char __user *buf,
 	mutex_lock(&rsc->client_lock);
 	if (rsc->current_state == SDE_RSC_IDLE_STATE) {
 		pr_debug("debug node is not supported during idle state\n");
-		blen = snprintf(buffer, MAX_BUFFER_SIZE,
+		blen = scnprintf(buffer, max_size,
 				"hw state is not supported during idle pc\n");
 		goto end;
 	}
 
-	blen = rsc->hw_ops.hw_vsync(rsc, VSYNC_READ, buffer,
-						MAX_BUFFER_SIZE, 0);
+	blen = rsc->hw_ops.hw_vsync(rsc, VSYNC_READ, buffer, max_size, 0);
 
 end:
 	mutex_unlock(&rsc->client_lock);
 	if (blen <= 0)
 		return 0;
 
-	if (blen > count)
+	if (blen > count) {
 		blen = count;
+		buffer[count - 1] = '\0';
+	}
 
-	blen = min_t(size_t, blen, MAX_BUFFER_SIZE);
 	if (copy_to_user(buf, buffer, blen))
 		return -EFAULT;
 

+ 4 - 7
msm/sde_rsc_hw.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
  */
 
 #define pr_fmt(fmt)	"[sde_rsc_hw:%s:%d]: " fmt, __func__, __LINE__
@@ -717,8 +717,7 @@ int rsc_hw_mode_ctrl(struct sde_rsc_priv *rsc, enum rsc_mode_req request,
 		if (!buffer || !buffer_size)
 			return blen;
 
-		blen = snprintf(buffer, buffer_size - blen,
-			"mode_status:0x%x\n",
+		blen = scnprintf(buffer, buffer_size, "mode_status:0x%x\n",
 			dss_reg_r(&rsc->drv_io, SDE_RSCC_SOLVER_STATUS2_DRV0,
 			rsc->debug_mode));
 		break;
@@ -798,14 +797,12 @@ int rsc_hw_vsync(struct sde_rsc_priv *rsc, enum rsc_vsync_req request,
 		if (!buffer || !buffer_size)
 			return blen;
 
-		blen = snprintf(buffer, buffer_size - blen, "vsync0:0x%x\n",
+		blen = scnprintf(buffer, buffer_size, "vsync0:0x%x\n",
 			 dss_reg_r(&rsc->wrapper_io,
 				SDE_RSCC_WRAPPER_VSYNC_TIMESTAMP0,
 				rsc->debug_mode));
-		if (blen >= buffer_size)
-			return blen;
 
-		blen += snprintf(buffer + blen, buffer_size - blen,
+		blen += scnprintf(buffer + blen, buffer_size - blen,
 			"vsync1:0x%x\n",
 			 dss_reg_r(&rsc->wrapper_io,
 				SDE_RSCC_WRAPPER_VSYNC_TIMESTAMP1,