[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#380531: linux-2.6: mips and mipsel personality(2) support is broken



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;
}

Reply to: