diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-11-02 14:41:43 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-11-02 14:41:43 -0700 |
| commit | 8a4f90bd10a5326c8da6e1750d041f7befb10eb1 (patch) | |
| tree | 9386e1ac1c85522e99c309bdc006361a62d4d755 | |
| parent | 1057dedd4006f10d4143ebe75dcc2cffbe830bc4 (diff) | |
| parent | 01b2c9a5d728ff6f2f1f28a5d4e927aaeabf56ed (diff) | |
Merge "soc: qcom: scm: add check to avoid buffer overflow"
| -rw-r--r-- | drivers/soc/qcom/scm.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c index 714c848ec9c0..b4713ac1b68b 100644 --- a/drivers/soc/qcom/scm.c +++ b/drivers/soc/qcom/scm.c @@ -56,9 +56,16 @@ DEFINE_MUTEX(scm_lmh_lock); #define SMC_ATOMIC_MASK 0x80000000 #define IS_CALL_AVAIL_CMD 1 -#define SCM_BUF_LEN(__cmd_size, __resp_size) \ - (sizeof(struct scm_command) + sizeof(struct scm_response) + \ - __cmd_size + __resp_size) +#define SCM_BUF_LEN(__cmd_size, __resp_size) ({ \ + size_t x = __cmd_size + __resp_size; \ + size_t y = sizeof(struct scm_command) + sizeof(struct scm_response); \ + size_t result; \ + if (x < __cmd_size || (x + y) < x) \ + result = 0; \ + else \ + result = x + y; \ + result; \ + }) /** * struct scm_command - one SCM command buffer * @len: total available memory for command and response @@ -356,8 +363,7 @@ int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf, int ret; size_t len = SCM_BUF_LEN(cmd_len, resp_len); - if (cmd_len > scm_buf_len || resp_len > scm_buf_len || - len > scm_buf_len) + if (len == 0) return -EINVAL; if (!IS_ALIGNED((unsigned long)scm_buf, PAGE_SIZE)) @@ -780,7 +786,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, int ret; size_t len = SCM_BUF_LEN(cmd_len, resp_len); - if (cmd_len > len || resp_len > len) + if (len == 0 || PAGE_ALIGN(len) < len) return -EINVAL; cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); |
