Package: linux-2.6 Severity: important personality(2) only works the first time it is called [in the lifetime of a process/program]. All subsequent calls return EPERM, which is not a documented return value; I can see no mention of it in kernel/execdomain.c. None of the other architectures I have tested (amd64, arm, i386, ia64, powerpc) behave this way: personality(2) is not a privileged call.
This happens no matter what the value of persona is, even if it is just 0xffffffff to query the current personality. The attached testcase demonstrates the breakage. On a working platform (powerpc), the output is like this: ------------------------ $ ./testpersona Getting personality Get returned '0' Setting personality '8' Set OK Getting personality Get returned '8' Setting personality '0' Set OK Getting personality Get returned '0' ------------------------ 0 == PER_LINUX 8 == PER_LINUX32 It successfully switched from PER_LINUX to PER_LINUX32 and back again, checking the personality before and after each change. Regards, Roger -- System Information: Debian Release: testing/unstable APT prefers unstable APT policy: (990, 'unstable') Architecture: powerpc (ppc) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6.17-1-powerpc Locale: LANG=en_GB.UTF8, LC_CTYPE=en_GB.UTF8 (charmap=UTF-8)
#include <stdio.h> #include <string.h> #include <errno.h> #include <sys/personality.h> int set_persona (unsigned long p) { fprintf (stderr, "Setting personality '%lu'\n", p); int status = personality(p); if (status == -1) fprintf(stderr, "Set failed: %s\n", strerror(errno)); fprintf(stderr, "Set OK\n"); return status; } int get_persona (void) { fprintf (stderr, "Getting personality\n"); int status = personality(0xffffffff); if (status == -1) fprintf(stderr, "Get failed: %s\n", strerror(errno)); fprintf(stderr, "Get returned '%d'\n", status); return status; } int main (void) { get_persona(); set_persona(PER_LINUX32); get_persona(); set_persona(PER_LINUX); get_persona(); return 0; }