On Mon, Jan 10, 2022 at 10:29 PM Arnd Bergmann <arnd@xxxxxxxx> wrote: > > On Tue, Dec 28, 2021 at 3:39 PM <guoren@xxxxxxxxxx> wrote: > > > > From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> > > > > Implement necessary type and macro for compat elf. See the code > > comment for detail. > > > > Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> > > Signed-off-by: Guo Ren <guoren@xxxxxxxxxx> > > Cc: Arnd Bergmann <arnd@xxxxxxxx> > > This looks mostly correct, > > > +/* > > + * FIXME: not sure SET_PERSONALITY for compat process is right! > > + */ > > +#define SET_PERSONALITY(ex) \ > > +do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ > > + set_thread_flag(TIF_32BIT); \ > > + else \ > > + clear_thread_flag(TIF_32BIT); \ > > + set_personality(PER_LINUX | (current->personality & (~PER_MASK))); \ > > +} while (0) > > This means the personality after exec is always set to PER_LINUX, not > PER_LINUX32, which I think is wrong: you want the PER_LINUX32 > setting to stick, just like the upper bits do in the default implementation. > > What the other ones do is: > > | arch/parisc/include/asm/elf.h- > set_personality((current->personality & ~PER_MASK) | PER_LINUX); \ > > This looks like the same problem you introduce here: always forcing PER_LINUX > instead of PER_LINUX32 makes it impossible to use PER_LINUX32. > > | arch/alpha/include/asm/elf.h:#define SET_PERSONALITY(EX) > \ > | arch/alpha/include/asm/elf.h- set_personality(((EX).e_flags & > EF_ALPHA_32BIT) \ > | arch/alpha/include/asm/elf.h- ? PER_LINUX_32BIT : PER_LINUX) > | arch/csky/include/asm/elf.h:#define SET_PERSONALITY(ex) > set_personality(PER_LINUX) > | arch/nds32/include/asm/elf.h:#define SET_PERSONALITY(ex) > set_personality(PER_LINUX) > > These look even worse: instead of forcing the lower bits to > PER_LINUX/PER_LINUX32 and > leaving the upper bits untouched, these also clear the upper bits > unconditionally. > > | arch/arm64/include/asm/elf.h:#define SET_PERSONALITY(ex) > \ > | arch/arm64/include/asm/elf.h- current->personality &= > ~READ_IMPLIES_EXEC; \ > | arch/x86/um/asm/elf.h:#define SET_PERSONALITY(ex) do {} while(0) > | arch/x86/include/asm/elf.h:#define set_personality_64bit() do { > } while (0) > | arch/x86/kernel/process_64.c:static void __set_personality_ia32(void) > | current->personality |= force_personality32; > > Inconsistent: does not enforce PER_LINUX/PER_LINUX32 as the default > implementation > does, but just leaves the value untouched (other than (re)setting > READ_IMPLIES_EXEC). > I think this is harmless otherwise, as we generally ignore the lower > bits, except for the > bit of code that checks for PER_LINUX32 in override_architecture() to mangle the > output of sys_newuname() or in /proc/cpuinfo. > > | arch/s390/include/asm/elf.h- if > (personality(current->personality) != PER_LINUX32) \ > | arch/s390/include/asm/elf.h- set_personality(PER_LINUX | > \ > | arch/s390/include/asm/elf.h- > (current->personality & ~PER_MASK)); \ > | arch/powerpc/include/asm/elf.h- if > (personality(current->personality) != PER_LINUX32) \ > | arch/powerpc/include/asm/elf.h- set_personality(PER_LINUX | > \ > | arch/powerpc/include/asm/elf.h- > (current->personality & (~PER_MASK))); \ > | arch/sparc/include/asm/elf_64.h- if > (personality(current->personality) != PER_LINUX32) \ > | arch/sparc/include/asm/elf_64.h- > set_personality(PER_LINUX | \ > | arch/sparc/include/asm/elf_64.h- > (current->personality & (~PER_MASK))); \ > > This is probably the behavior you want to copy. Thank you very much for your detailed explanation. Here is my modification. +#define SET_PERSONALITY(ex) \ +do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ + set_thread_flag(TIF_32BIT); \ + else \ + clear_thread_flag(TIF_32BIT); \ + if (personality(current->personality) != PER_LINUX32) \ + set_personality(PER_LINUX | \ + (current->personality & (~PER_MASK))); \ +} while (0) > > Arnd -- Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/