From 3977a4ceff8b58dbf2257b636bb9c1cb20189315 Mon Sep 17 00:00:00 2001 From: ansharma Date: Fri, 20 Jan 2017 18:16:18 +0530 Subject: [PATCH] qcom: fg-util: Fix possible race condition in debugfs There is a possible race condition when debugfs files are concurrently accessed by multiple threads. Fix this. CRs-Fixed: 1105395 Change-Id: Iea5a8d659da231a81630d8f2302714e69d35de61 Signed-off-by: ansharma --- drivers/power/supply/qcom/fg-core.h | 1 + drivers/power/supply/qcom/fg-util.c | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 07bde30524ac..d71e3afd8d42 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -369,6 +369,7 @@ struct fg_log_buffer { /* transaction parameters */ struct fg_trans { struct fg_chip *chip; + struct mutex fg_dfs_lock; /* Prevent thread concurrency */ struct fg_log_buffer *log; u32 cnt; u16 addr; diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c index 41d2af0fbdc6..d5c4f8ffaac3 100644 --- a/drivers/power/supply/qcom/fg-util.c +++ b/drivers/power/supply/qcom/fg-util.c @@ -486,6 +486,7 @@ static int fg_sram_dfs_open(struct inode *inode, struct file *file) trans->addr = dbgfs_data.addr; trans->chip = dbgfs_data.chip; trans->offset = trans->addr; + mutex_init(&trans->fg_dfs_lock); file->private_data = trans; return 0; @@ -497,6 +498,7 @@ static int fg_sram_dfs_close(struct inode *inode, struct file *file) if (trans && trans->log && trans->data) { file->private_data = NULL; + mutex_destroy(&trans->fg_dfs_lock); devm_kfree(trans->chip->dev, trans->log); devm_kfree(trans->chip->dev, trans->data); devm_kfree(trans->chip->dev, trans); @@ -648,10 +650,13 @@ static ssize_t fg_sram_dfs_reg_read(struct file *file, char __user *buf, size_t ret; size_t len; + mutex_lock(&trans->fg_dfs_lock); /* Is the the log buffer empty */ if (log->rpos >= log->wpos) { - if (get_log_data(trans) <= 0) - return 0; + if (get_log_data(trans) <= 0) { + len = 0; + goto unlock_mutex; + } } len = min(count, log->wpos - log->rpos); @@ -659,7 +664,8 @@ static ssize_t fg_sram_dfs_reg_read(struct file *file, char __user *buf, ret = copy_to_user(buf, &log->data[log->rpos], len); if (ret == len) { pr_err("error copy sram register values to user\n"); - return -EFAULT; + len = -EFAULT; + goto unlock_mutex; } /* 'ret' is the number of bytes not copied */ @@ -667,6 +673,9 @@ static ssize_t fg_sram_dfs_reg_read(struct file *file, char __user *buf, *ppos += len; log->rpos += len; + +unlock_mutex: + mutex_unlock(&trans->fg_dfs_lock); return len; } @@ -691,10 +700,13 @@ static ssize_t fg_sram_dfs_reg_write(struct file *file, const char __user *buf, struct fg_trans *trans = file->private_data; u32 address = trans->addr; + mutex_lock(&trans->fg_dfs_lock); /* Make a copy of the user data */ kbuf = kmalloc(count + 1, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } ret = copy_from_user(kbuf, buf, count); if (ret == count) { @@ -744,6 +756,8 @@ static ssize_t fg_sram_dfs_reg_write(struct file *file, const char __user *buf, free_buf: kfree(kbuf); +unlock_mutex: + mutex_unlock(&trans->fg_dfs_lock); return ret; }