kernel/exec_domain.c
22793 #include <linux/mm.h>
22794 #include <linux/smp_lock.h>
22795 #include <linux/module.h>
22796
22797 static asmlinkage void no_lcall7(struct pt_regs * regs);
22798
22799
22800 static unsigned long ident_map[32] = {
22801 0, 1, 2, 3, 4, 5, 6, 7,
22802 8, 9, 10, 11, 12, 13, 14, 15,
22803 16, 17, 18, 19, 20, 21, 22, 23,
22804 24, 25, 26, 27, 28, 29, 30, 31
22805 };
22806
22807 struct exec_domain default_exec_domain = {
22808 "Linux", /* name */
22809 no_lcall7, /* lcall7 causes a seg fault. */
22810 0, 0xff, /* All personalities. */
22811 ident_map, /* Identity map signals. */
22812 ident_map, /* - both ways. */
22813 NULL, /* No usage counter. */
22814 NULL /* Nothing after this in the list. */
22815 };
22816
22817 static struct exec_domain *exec_domains =
22818 &default_exec_domain;
22819
22820 static asmlinkage void no_lcall7(struct pt_regs * regs)
22821 {
22822
22823 /* This may have been a static linked SVr4 binary, so
22824 * we would have the personality set incorrectly.
22825 * Check to see whether SVr4 is available, and use it,
22826 * otherwise give the user a SEGV. */
22827 if (current->exec_domain &&
22828 current->exec_domain->module)
22829 __MOD_DEC_USE_COUNT(current->exec_domain->module);
22830
22831 current->personality = PER_SVR4;
22832 current->exec_domain =
22833 lookup_exec_domain(current->personality);
22834
22835 if (current->exec_domain &&
22836 current->exec_domain->module)
22837 __MOD_INC_USE_COUNT(current->exec_domain->module);
22838
22839 if (current->exec_domain &&
22840 current->exec_domain->handler &&
22841 current->exec_domain->handler != no_lcall7) {
22842 current->exec_domain->handler(regs);
22843 return;
22844 }
22845
22846 send_sig(SIGSEGV, current, 1);
22847 }
22848
22849 struct exec_domain *lookup_exec_domain(
22850 unsigned long personality)
22851 {
22852 unsigned long pers = personality & PER_MASK;
22853 struct exec_domain *it;
22854
22855 for (it=exec_domains; it; it=it->next)
22856 if (pers >= it->pers_low
22857 && pers <= it->pers_high)
22858 return it;
22859
22860 /* Should never get this far. */
22861 printk(KERN_ERR "No execution domain for personality "
22862 "0x%02lx\n", pers);
22863 return NULL;
22864 }
22865
22866 int register_exec_domain(struct exec_domain *it)
22867 {
22868 struct exec_domain *tmp;
22869
22870 if (!it)
22871 return -EINVAL;
22872 if (it->next)
22873 return -EBUSY;
22874 for (tmp=exec_domains; tmp; tmp=tmp->next)
22875 if (tmp == it)
22876 return -EBUSY;
22877 it->next = exec_domains;
22878 exec_domains = it;
22879 return 0;
22880 }
22881
22882 int unregister_exec_domain(struct exec_domain *it)
22883 {
22884 struct exec_domain ** tmp;
22885
22886 tmp = &exec_domains;
22887 while (*tmp) {
22888 if (it == *tmp) {
22889 *tmp = it->next;
22890 it->next = NULL;
22891 return 0;
22892 }
22893 tmp = &(*tmp)->next;
22894 }
22895 return -EINVAL;
22896 }
22897
22898 asmlinkage int sys_personality(unsigned long personality)
22899 {
22900 struct exec_domain *it;
22901 unsigned long old_personality;
22902 int ret;
22903
22904 lock_kernel();
22905 ret = current->personality;
22906 if (personality == 0xffffffff)
22907 goto out;
22908
22909 ret = -EINVAL;
22910 it = lookup_exec_domain(personality);
22911 if (!it)
22912 goto out;
22913
22914 old_personality = current->personality;
22915 if (current->exec_domain &&
22916 current->exec_domain->module)
22917 __MOD_DEC_USE_COUNT(current->exec_domain->module);
22918 current->personality = personality;
22919 current->exec_domain = it;
22920 if (current->exec_domain->module)
22921 __MOD_INC_USE_COUNT(current->exec_domain->module);
22922 ret = old_personality;
22923 out:
22924 unlock_kernel();
22925 return ret;
22926 }
Сайт управляется системой
uCoz