From: Ben Dooks <ben.dooks@codethink.co.uk>
To: "Clément Léger" <cleger@rivosinc.com>,
"Paul Walmsley" <paul.walmsley@sifive.com>,
"Palmer Dabbelt" <palmer@dabbelt.com>,
"Albert Ou" <aou@eecs.berkeley.edu>,
linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org
Cc: Christoph Hellwig <hch@infradead.org>, kernel test robot <lkp@intel.com>
Subject: Re: [PATCH v2] riscv: fix incorrect use of __user pointer
Date: Mon, 27 Nov 2023 12:02:27 +0000 [thread overview]
Message-ID: <b4ee0ab3-9772-439c-bc9c-474f6f2862ba@codethink.co.uk> (raw)
In-Reply-To: <20231124113803.165431-1-cleger@rivosinc.com>
On 24/11/2023 11:38, Clément Léger wrote:
> These warnings were reported by sparse and were due to lack of __user
> annotation as well as dereferencing such pointer:
>
> arch/riscv/kernel/traps_misaligned.c:361:21: warning: dereference of noderef expression
> arch/riscv/kernel/traps_misaligned.c:373:21: warning: dereference of noderef expression
> arch/riscv/kernel/traps_misaligned.c:381:21: warning: dereference of noderef expression
> arch/riscv/kernel/traps_misaligned.c:322:24: warning: incorrect type in initializer (different address spaces)
> arch/riscv/kernel/traps_misaligned.c:322:24: expected unsigned char const [noderef] __user *__gu_ptr
> arch/riscv/kernel/traps_misaligned.c:322:24: got unsigned char const [usertype] *addr
> arch/riscv/kernel/traps_misaligned.c:361:21: warning: dereference of noderef expression
> arch/riscv/kernel/traps_misaligned.c:373:21: warning: dereference of noderef expression
> arch/riscv/kernel/traps_misaligned.c:381:21: warning: dereference of noderef expression
> arch/riscv/kernel/traps_misaligned.c:332:24: warning: incorrect type in initializer (different address spaces)
> arch/riscv/kernel/traps_misaligned.c:332:24: expected unsigned char [noderef] __user *__gu_ptr
> arch/riscv/kernel/traps_misaligned.c:332:24: got unsigned char [usertype] *addr
>
> As suggested by Christoph Hellwig, casting pointers from an address
> space to another is not a good idea and we should rather cast the
> untyped unsigned long to their final address space. Fix the ones in
> load_u8()/store_u8()/__read_insn() by passing a unsigned long and then
> casting it to the appropriate type (__user of not) depending if used in
> kernel/ user mode. Also remove unneeded else construct in store_u8()/
> load_u8().
>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202311160606.obGOOwB3-lkp@intel.com/
> Signed-off-by: Clément Léger <cleger@rivosinc.com>
> ---
> arch/riscv/kernel/traps_misaligned.c | 55 +++++++++++++---------------
> 1 file changed, 25 insertions(+), 30 deletions(-)
>
> diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
> index 5eba37147caa..a92b88af855a 100644
> --- a/arch/riscv/kernel/traps_misaligned.c
> +++ b/arch/riscv/kernel/traps_misaligned.c
> @@ -265,19 +265,19 @@ static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset,
> #define GET_F32_RS2S(insn, regs) (get_f32_rs(RVC_RS2S(insn), 0, regs))
>
> #ifdef CONFIG_RISCV_M_MODE
> -static inline int load_u8(struct pt_regs *regs, const u8 *addr, u8 *r_val)
> +static inline int load_u8(struct pt_regs *regs, const unsigned long addr, u8 *r_val)
> {
> u8 val;
>
> - asm volatile("lbu %0, %1" : "=&r" (val) : "m" (*addr));
> + asm volatile("lbu %0, %1" : "=&r" (val) : "m" (*(const u8 *)addr));
> *r_val = val;
>
> return 0;
> }
>
> -static inline int store_u8(struct pt_regs *regs, u8 *addr, u8 val)
> +static inline int store_u8(struct pt_regs *regs, unsigned long addr, u8 val)
> {
> - asm volatile ("sb %0, %1\n" : : "r" (val), "m" (*addr));
> + asm volatile ("sb %0, %1\n" : : "r" (val), "m" (*(u8 *)addr));
>
> return 0;
> }
> @@ -316,34 +316,32 @@ static inline int get_insn(struct pt_regs *regs, ulong mepc, ulong *r_insn)
> return 0;
> }
> #else
> -static inline int load_u8(struct pt_regs *regs, const u8 *addr, u8 *r_val)
> +static inline int load_u8(struct pt_regs *regs, const unsigned long addr, u8 *r_val)
> {
> - if (user_mode(regs)) {
> - return __get_user(*r_val, addr);
> - } else {
> - *r_val = *addr;
> - return 0;
> - }
> + if (user_mode(regs))
> + return __get_user(*r_val, (u8 __user *)addr);
> +
> + *r_val = *(const u8 *)addr;
> + return 0;
> }
>
> -static inline int store_u8(struct pt_regs *regs, u8 *addr, u8 val)
> +static inline int store_u8(struct pt_regs *regs, unsigned long addr, u8 val)
> {
> - if (user_mode(regs)) {
> - return __put_user(val, addr);
> - } else {
> - *addr = val;
> - return 0;
> - }
> + if (user_mode(regs))
> + return __put_user(val, (u8 __user *)addr);
> +
> + *(u8 *)addr = val;
> + return 0;
> }
>
> -#define __read_insn(regs, insn, insn_addr) \
> +#define __read_insn(regs, insn, insn_addr, type) \
> ({ \
> int __ret; \
> \
> if (user_mode(regs)) { \
> - __ret = __get_user(insn, insn_addr); \
> + __ret = __get_user(insn, (type __user *) insn_addr); \
> } else { \
> - insn = *insn_addr; \
> + insn = *(type *)insn_addr; \
> __ret = 0; \
> } \
> \
> @@ -356,9 +354,8 @@ static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn)
>
> if (epc & 0x2) {
> ulong tmp = 0;
> - u16 __user *insn_addr = (u16 __user *)epc;
>
> - if (__read_insn(regs, insn, insn_addr))
> + if (__read_insn(regs, insn, epc, u16))
> return -EFAULT;
> /* __get_user() uses regular "lw" which sign extend the loaded
> * value make sure to clear higher order bits in case we "or" it
> @@ -369,16 +366,14 @@ static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn)
> *r_insn = insn;
> return 0;
> }
> - insn_addr++;
> - if (__read_insn(regs, tmp, insn_addr))
> + epc += sizeof(u16);
> + if (__read_insn(regs, tmp, epc, u16))
> return -EFAULT;
> *r_insn = (tmp << 16) | insn;
>
> return 0;
> } else {
> - u32 __user *insn_addr = (u32 __user *)epc;
> -
> - if (__read_insn(regs, insn, insn_addr))
> + if (__read_insn(regs, insn, epc, u32))
> return -EFAULT;
> if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) {
> *r_insn = insn;
> @@ -491,7 +486,7 @@ int handle_misaligned_load(struct pt_regs *regs)
>
> val.data_u64 = 0;
> for (i = 0; i < len; i++) {
> - if (load_u8(regs, (void *)(addr + i), &val.data_bytes[i]))
> + if (load_u8(regs, addr + i, &val.data_bytes[i]))
> return -1;
> }
>
> @@ -589,7 +584,7 @@ int handle_misaligned_store(struct pt_regs *regs)
> return -EOPNOTSUPP;
>
> for (i = 0; i < len; i++) {
> - if (store_u8(regs, (void *)(addr + i), val.data_bytes[i]))
> + if (store_u8(regs, addr + i, val.data_bytes[i]))
>
Would it not be easier to have a switch here for memcpy or copy_to_user?
return -1;
> }
>
--
Ben Dooks http://www.codethink.co.uk/
Senior Engineer Codethink - Providing Genius
https://www.codethink.co.uk/privacy.html
next prev parent reply other threads:[~2023-11-27 12:02 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-24 11:38 [PATCH v2] riscv: fix incorrect use of __user pointer Clément Léger
2023-11-25 6:22 ` Christoph Hellwig
2023-11-25 15:37 ` David Laight
2023-11-27 10:24 ` Clément Léger
2023-11-27 10:35 ` David Laight
2023-11-27 10:37 ` Clément Léger
2023-11-27 10:51 ` David Laight
2023-11-27 12:02 ` Ben Dooks [this message]
2023-11-27 12:46 ` Clément Léger
2023-11-27 12:57 ` Clément Léger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b4ee0ab3-9772-439c-bc9c-474f6f2862ba@codethink.co.uk \
--to=ben.dooks@codethink.co.uk \
--cc=aou@eecs.berkeley.edu \
--cc=cleger@rivosinc.com \
--cc=hch@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=lkp@intel.com \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox