The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/exec_domain.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Handling of different ABIs (personalities).
    3  *
    4  * We group personalities into execution domains which have their
    5  * own handlers for kernel entry points, signal mapping, etc...
    6  *
    7  * 2001-05-06   Complete rewrite,  Christoph Hellwig (hch@infradead.org)
    8  */
    9 
   10 #include <linux/init.h>
   11 #include <linux/kernel.h>
   12 #include <linux/kmod.h>
   13 #include <linux/module.h>
   14 #include <linux/personality.h>
   15 #include <linux/proc_fs.h>
   16 #include <linux/sched.h>
   17 #include <linux/seq_file.h>
   18 #include <linux/syscalls.h>
   19 #include <linux/sysctl.h>
   20 #include <linux/types.h>
   21 #include <linux/fs_struct.h>
   22 
   23 
   24 static void default_handler(int, struct pt_regs *);
   25 
   26 static struct exec_domain *exec_domains = &default_exec_domain;
   27 static DEFINE_RWLOCK(exec_domains_lock);
   28 
   29 
   30 static unsigned long ident_map[32] = {
   31         0,      1,      2,      3,      4,      5,      6,      7,
   32         8,      9,      10,     11,     12,     13,     14,     15,
   33         16,     17,     18,     19,     20,     21,     22,     23,
   34         24,     25,     26,     27,     28,     29,     30,     31
   35 };
   36 
   37 struct exec_domain default_exec_domain = {
   38         .name           = "Linux",              /* name */
   39         .handler        = default_handler,      /* lcall7 causes a seg fault. */
   40         .pers_low       = 0,                    /* PER_LINUX personality. */
   41         .pers_high      = 0,                    /* PER_LINUX personality. */
   42         .signal_map     = ident_map,            /* Identity map signals. */
   43         .signal_invmap  = ident_map,            /*  - both ways. */
   44 };
   45 
   46 
   47 static void
   48 default_handler(int segment, struct pt_regs *regp)
   49 {
   50         set_personality(0);
   51 
   52         if (current_thread_info()->exec_domain->handler != default_handler)
   53                 current_thread_info()->exec_domain->handler(segment, regp);
   54         else
   55                 send_sig(SIGSEGV, current, 1);
   56 }
   57 
   58 static struct exec_domain *
   59 lookup_exec_domain(unsigned int personality)
   60 {
   61         unsigned int pers = personality(personality);
   62         struct exec_domain *ep;
   63 
   64         read_lock(&exec_domains_lock);
   65         for (ep = exec_domains; ep; ep = ep->next) {
   66                 if (pers >= ep->pers_low && pers <= ep->pers_high)
   67                         if (try_module_get(ep->module))
   68                                 goto out;
   69         }
   70 
   71 #ifdef CONFIG_MODULES
   72         read_unlock(&exec_domains_lock);
   73         request_module("personality-%d", pers);
   74         read_lock(&exec_domains_lock);
   75 
   76         for (ep = exec_domains; ep; ep = ep->next) {
   77                 if (pers >= ep->pers_low && pers <= ep->pers_high)
   78                         if (try_module_get(ep->module))
   79                                 goto out;
   80         }
   81 #endif
   82 
   83         ep = &default_exec_domain;
   84 out:
   85         read_unlock(&exec_domains_lock);
   86         return (ep);
   87 }
   88 
   89 int
   90 register_exec_domain(struct exec_domain *ep)
   91 {
   92         struct exec_domain      *tmp;
   93         int                     err = -EBUSY;
   94 
   95         if (ep == NULL)
   96                 return -EINVAL;
   97 
   98         if (ep->next != NULL)
   99                 return -EBUSY;
  100 
  101         write_lock(&exec_domains_lock);
  102         for (tmp = exec_domains; tmp; tmp = tmp->next) {
  103                 if (tmp == ep)
  104                         goto out;
  105         }
  106 
  107         ep->next = exec_domains;
  108         exec_domains = ep;
  109         err = 0;
  110 
  111 out:
  112         write_unlock(&exec_domains_lock);
  113         return (err);
  114 }
  115 
  116 int
  117 unregister_exec_domain(struct exec_domain *ep)
  118 {
  119         struct exec_domain      **epp;
  120 
  121         epp = &exec_domains;
  122         write_lock(&exec_domains_lock);
  123         for (epp = &exec_domains; *epp; epp = &(*epp)->next) {
  124                 if (ep == *epp)
  125                         goto unregister;
  126         }
  127         write_unlock(&exec_domains_lock);
  128         return -EINVAL;
  129 
  130 unregister:
  131         *epp = ep->next;
  132         ep->next = NULL;
  133         write_unlock(&exec_domains_lock);
  134         return 0;
  135 }
  136 
  137 int __set_personality(unsigned int personality)
  138 {
  139         struct exec_domain *oep = current_thread_info()->exec_domain;
  140 
  141         current_thread_info()->exec_domain = lookup_exec_domain(personality);
  142         current->personality = personality;
  143         module_put(oep->module);
  144 
  145         return 0;
  146 }
  147 
  148 #ifdef CONFIG_PROC_FS
  149 static int execdomains_proc_show(struct seq_file *m, void *v)
  150 {
  151         struct exec_domain      *ep;
  152 
  153         read_lock(&exec_domains_lock);
  154         for (ep = exec_domains; ep; ep = ep->next)
  155                 seq_printf(m, "%d-%d\t%-16s\t[%s]\n",
  156                                ep->pers_low, ep->pers_high, ep->name,
  157                                module_name(ep->module));
  158         read_unlock(&exec_domains_lock);
  159         return 0;
  160 }
  161 
  162 static int execdomains_proc_open(struct inode *inode, struct file *file)
  163 {
  164         return single_open(file, execdomains_proc_show, NULL);
  165 }
  166 
  167 static const struct file_operations execdomains_proc_fops = {
  168         .open           = execdomains_proc_open,
  169         .read           = seq_read,
  170         .llseek         = seq_lseek,
  171         .release        = single_release,
  172 };
  173 
  174 static int __init proc_execdomains_init(void)
  175 {
  176         proc_create("execdomains", 0, NULL, &execdomains_proc_fops);
  177         return 0;
  178 }
  179 module_init(proc_execdomains_init);
  180 #endif
  181 
  182 SYSCALL_DEFINE1(personality, unsigned int, personality)
  183 {
  184         unsigned int old = current->personality;
  185 
  186         if (personality != 0xffffffff)
  187                 set_personality(personality);
  188 
  189         return old;
  190 }
  191 
  192 
  193 EXPORT_SYMBOL(register_exec_domain);
  194 EXPORT_SYMBOL(unregister_exec_domain);
  195 EXPORT_SYMBOL(__set_personality);

Cache object: 2ea91fc76490add0a9b05a86f36f3326


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.