linux-old/kernel/exec_domain.c
<<
>>
Prefs
   1#include <linux/personality.h>
   2#include <linux/ptrace.h>
   3#include <linux/sched.h>
   4#include <linux/mm.h>
   5#include <linux/smp.h>
   6#include <linux/smp_lock.h>
   7#include <linux/module.h>
   8
   9static asmlinkage void no_lcall7(struct pt_regs * regs);
  10
  11
  12static unsigned long ident_map[32] = {
  13        0,      1,      2,      3,      4,      5,      6,      7,
  14        8,      9,      10,     11,     12,     13,     14,     15,
  15        16,     17,     18,     19,     20,     21,     22,     23,
  16        24,     25,     26,     27,     28,     29,     30,     31
  17};
  18
  19struct exec_domain default_exec_domain = {
  20        "Linux",        /* name */
  21        no_lcall7,      /* lcall7 causes a seg fault. */
  22        0, 0xff,        /* All personalities. */
  23        ident_map,      /* Identity map signals. */
  24        ident_map,      /*  - both ways. */
  25        NULL,           /* No usage counter. */
  26        NULL            /* Nothing after this in the list. */
  27};
  28
  29static struct exec_domain *exec_domains = &default_exec_domain;
  30
  31
  32static asmlinkage void no_lcall7(struct pt_regs * regs)
  33{
  34
  35  /*
  36   * This may have been a static linked SVr4 binary, so we would have the
  37   * personality set incorrectly.  Check to see whether SVr4 is available,
  38   * and use it, otherwise give the user a SEGV.
  39   */
  40        if (current->exec_domain && current->exec_domain->module)
  41                __MOD_DEC_USE_COUNT(current->exec_domain->module);
  42
  43        current->personality = PER_SVR4;
  44        current->exec_domain = lookup_exec_domain(current->personality);
  45
  46        if (current->exec_domain && current->exec_domain->module)
  47                __MOD_INC_USE_COUNT(current->exec_domain->module);
  48
  49        if (current->exec_domain && current->exec_domain->handler
  50        && current->exec_domain->handler != no_lcall7) {
  51                current->exec_domain->handler(regs);
  52                return;
  53        }
  54
  55        send_sig(SIGSEGV, current, 1);
  56}
  57
  58struct exec_domain *lookup_exec_domain(unsigned long personality)
  59{
  60        unsigned long pers = personality & PER_MASK;
  61        struct exec_domain *it;
  62
  63        for (it=exec_domains; it; it=it->next)
  64                if (pers >= it->pers_low
  65                && pers <= it->pers_high)
  66                        return it;
  67
  68        /* Should never get this far. */
  69        printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
  70        return NULL;
  71}
  72
  73int register_exec_domain(struct exec_domain *it)
  74{
  75        struct exec_domain *tmp;
  76
  77        if (!it)
  78                return -EINVAL;
  79        if (it->next)
  80                return -EBUSY;
  81        for (tmp=exec_domains; tmp; tmp=tmp->next)
  82                if (tmp == it)
  83                        return -EBUSY;
  84        it->next = exec_domains;
  85        exec_domains = it;
  86        return 0;
  87}
  88
  89int unregister_exec_domain(struct exec_domain *it)
  90{
  91        struct exec_domain ** tmp;
  92
  93        tmp = &exec_domains;
  94        while (*tmp) {
  95                if (it == *tmp) {
  96                        *tmp = it->next;
  97                        it->next = NULL;
  98                        return 0;
  99                }
 100                tmp = &(*tmp)->next;
 101        }
 102        return -EINVAL;
 103}
 104
 105asmlinkage int sys_personality(unsigned long personality)
 106{
 107        struct exec_domain *it;
 108        unsigned long old_personality;
 109        int ret;
 110
 111        lock_kernel();
 112        ret = current->personality;
 113        if (personality == 0xffffffff)
 114                goto out;
 115
 116        ret = -EINVAL;
 117        it = lookup_exec_domain(personality);
 118        if (!it)
 119                goto out;
 120
 121        old_personality = current->personality;
 122        if (current->exec_domain && current->exec_domain->module)
 123                __MOD_DEC_USE_COUNT(current->exec_domain->module);
 124        current->personality = personality;
 125        current->exec_domain = it;
 126        if (current->exec_domain->module)
 127                __MOD_INC_USE_COUNT(current->exec_domain->module);
 128        ret = old_personality;
 129out:
 130        unlock_kernel();
 131        return ret;
 132}
 133
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.