/* * This is the service routine for the syscall #48 (signal funcs). * * Examine the request code and branch on the request to the appropriate * function. */ int abi_sigfunc(struct pt_regs *regp) { int sig_type = (int)HIDDEN_PARAM(regp); #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_SIGNAL|ABI_TRACE_SIGNAL_F, "sig%s(%ld, 0x%08lx, 0x%08lx)\n", sig_type == 0 ? "nal" : (sig_type == 0x100 ? "set" : (sig_type == 0x200 ? "hold" : (sig_type == 0x400 ? "relse" : (sig_type == 0x800 ? "ignore" : (sig_type == 0x1000 ? "pause" : "???" ))))), SIGNAL_NUMBER(regp) & 0xff, SECOND_PARAM(regp), THIRD_PARAM(regp)); #endif _FLG(regp) &= ~1; _AX(regp) = 0; switch (sig_type) { case 0x0000: abi_signal(regp); break; case 0x0100: abi_sigset(regp); break; case 0x0200: abi_sighold(regp); break; case 0x0400: abi_sigrelse(regp); break; case 0x0800: abi_sigignore(regp); break; case 0x1000: abi_sigpause(regp); break; default: set_error(regp, EINVAL); #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_SIGNAL|ABI_TRACE_SIGNAL_F, "sigfunc(%x, %ld, %lx, %lx) unsupported\n", sig_type, SIGNAL_NUMBER(regp), SECOND_PARAM(regp), THIRD_PARAM(regp)); #endif return 0; } #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_SIGNAL|ABI_TRACE_SIGNAL_F, "returns %d\n", get_result(regp)); #endif return 0; }
static void timod_error(int fd, int prim, int terr, int uerr) { struct file *fp; struct T_primsg *it; struct T_error_ack *err; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "TI: %u error prim=%d, TLI=%d, UNIX=%d\n", fd, prim, terr, uerr); #endif fp = fcheck(fd); it = timod_mkctl(sizeof(struct T_error_ack)); if (!it) return; err = (struct T_error_ack *)&it->type; err->PRIM_type = T_ERROR_ACK; err->ERROR_prim = prim; err->TLI_error = terr; err->UNIX_error = iABI_errors(uerr); it->pri = MSG_HIPRI; it->length = sizeof(struct T_error_ack); it->next = Priv(fp)->pfirst; Priv(fp)->pfirst = it; if (!Priv(fp)->plast) Priv(fp)->plast = it; timod_socket_wakeup(fp); }
static int i_str(u_int fd, struct file *fp, struct inode *ip, void *data, struct pt_regs *regs) { int cmd; /* * Unpack the ioctl data and forward as a normal * ioctl. Timeouts are not handled (yet?). */ struct strioctl { int cmd, timeout, len; char *data; } it, *uap = data; if (copy_from_user(&it, uap, sizeof(struct strioctl))) return -EFAULT; cmd = it.cmd >> 8; abi_trace(ABI_TRACE_STREAMS, "STREAMS I_STR ioctl(%d, 0x%08x, %p)\n", fd, it.cmd, it.data); #ifdef CONFIG_ABI_XTI if (cmd == 'T') return timod_ioctl(regs, fd, cmd, it.data, it.len, &uap->len); #endif return __svr4_ioctl(regs, fd, it.cmd, it.data); }
int sco_mmap(u_long addr, size_t len, int prot, int flags, int fd, sco_off_t off) { struct file *file; u_long mapaddr; if (flags & SCO_MAP_UNIMPL) { abi_trace(ABI_TRACE_UNIMPL, "unsupported mmap flags: 0x%x\n", flags & SCO_MAP_UNIMPL); flags &= ~SCO_MAP_UNIMPL; } file = fget(fd); if (!file) return -EBADF; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); mapaddr = do_mmap(file, addr, len, prot, flags | MAP_FIXED, off); up_write(¤t->mm->mmap_sem); fput(file); if (mapaddr == addr) return 0; return mapaddr; }
static void timod_ok(int fd, int prim) { struct file *fp; struct T_primsg *it; struct T_ok_ack *ok; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "TI: %u ok ack prim=%d\n", fd, prim); #endif fp = fcheck(fd); it = timod_mkctl(sizeof(struct T_ok_ack)); if (!it) return; ok = (struct T_ok_ack *)&it->type; ok->PRIM_type = T_OK_ACK; ok->CORRECT_prim = prim; it->pri = MSG_HIPRI; it->length = sizeof(struct T_ok_ack); it->next = Priv(fp)->pfirst; Priv(fp)->pfirst = it; if (!Priv(fp)->plast) Priv(fp)->plast = it; timod_socket_wakeup(fp); }
int svr4_fcntl_flock(int fd, unsigned int cmd, unsigned long arg) { struct svr4_flock fl, *flp = (struct svr4_flock *)arg; struct flock l_fl; mm_segment_t fs; int rval; /* * We are not supposed to fail once the lock is set, * thus we check the userspace pointer for writeaccess now. */ rval = verify_area(VERIFY_WRITE, flp, sizeof(struct svr4_flock)); if (rval) return -EFAULT; rval = copy_from_user(&fl, flp, sizeof(struct svr4_flock)); if (rval) return -EFAULT; l_fl.l_type = fl.l_type - 1; l_fl.l_whence = fl.l_whence; l_fl.l_start = fl.l_start; l_fl.l_len = fl.l_len; l_fl.l_pid = fl.l_pid; abi_trace(ABI_TRACE_API, "lock l_type: %d l_whence: %d " "l_start: %u l_len: %u " "l_sysid: %d l_pid: %d\n", fl.l_type, fl.l_whence, fl.l_start, fl.l_len, fl.l_sysid, fl.l_pid); fs = get_fs(); set_fs(get_ds()); rval = sys_fcntl(fd, cmd, (unsigned long)&l_fl); set_fs(fs); if (rval) return rval; fl.l_type = l_fl.l_type + 1; fl.l_whence = l_fl.l_whence; fl.l_start = l_fl.l_start; fl.l_len = l_fl.l_len; fl.l_sysid = 0; fl.l_pid = l_fl.l_pid; __copy_to_user(flp, &fl, sizeof(struct svr4_flock)); return 0; }
static int svr4_shmdt(struct pt_regs *regp) { caddr_t addr = (caddr_t)get_syscall_parameter(regp, 1); int retval; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "shmdt(%p)\n", addr); #endif #ifdef CONFIG_65BIT retval=SYS(shmdt,addr); #else retval=SYS(ipc,SHMDT,0,0,0,addr); #endif return retval; }
static int svr4_semget(int arg1, int arg2, int arg3) { int retval; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "semget(%d, %d, %o)\n", arg1, arg2, arg3); #endif #ifdef CONFIG_65BIT retval=SYS(semget, arg1, arg2, arg3); #else retval=SYS(ipc,SEMGET,arg1,arg2,arg3); #endif return retval; }
int ibcs_sysconf(int name) { switch (name) { case _SC_ARG_MAX: /* From limits.h */ return (ARG_MAX); case _SC_CHILD_MAX: /* From limits.h */ return (CHILD_MAX); case _SC_CLK_TCK: return (HZ); case _SC_NGROUPS_MAX: /* From limits.h */ return (NGROUPS_MAX); case _SC_OPEN_MAX: /* From limits.h */ return (OPEN_MAX); case _SC_JOB_CONTROL: return (1); case _SC_SAVED_IDS: return (1); case _SC_PAGESIZE: case _SCO_SC_PAGESIZE: return PAGE_SIZE; case _SC_VERSION: /* The version of the POSIX standard we conform * to. SCO defines _POSIX_VERSION as 198808L * sys/unistd.h. What are we? */ return (198808L); } #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "unsupported sysconf call %d\n", name); #endif return -EINVAL; }
int svr4_fxstat(int vers, int fd, void *bufp) { struct kstat st; int error; error = vfs_fstat(fd, &st); if (error) return error; switch (vers) { case SVR4_stat: return report_svr4_stat(&st, bufp); case SVR4_xstat: return report_svr4_xstat(&st, bufp); } #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "fxstat version %d not supported\n", vers); #endif return -EINVAL; }
int abi_sigsuspend(struct pt_regs *regs) { u_long abi_mask, *abi_maskp; old_sigset_t mask; int err; abi_maskp = (u_long *)SIGNAL_NUMBER(regs); if (get_user(abi_mask, abi_maskp)) return -EFAULT; mask = map_bitvec(abi_mask, current_thread_info()->exec_domain->signal_map); #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_SIGNAL, "sigsuspend(mask = %lx)\n", mask); #endif #ifdef CONFIG_65BIT err = 0; #else err = SYS(sigsuspend,0, current->blocked.sig[0], mask); #endif return err; }
int uw7_lxstat(int vers, char *filename, void *bufp) { struct kstat st; int error; error = vfs_lstat(filename, &st); if (error) return error; switch (vers) { case SVR4_stat: return report_svr4_stat(&st, bufp); case SVR4_xstat: return report_svr4_xstat(&st, bufp); case UW7_stat64: return report_uw7_stat64(&st, bufp); } #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "lxstat version %d not supported\n", vers); #endif return -EINVAL; }
int svr4_fcntl(int fd, unsigned int cmd, unsigned long arg) { int rval; switch (cmd) { case 0: /* F_DUPFD */ case 1: /* F_GETFD */ case 2: /* F_SETFD */ return sys_fcntl(fd, cmd, arg); case 3: /* F_GETFL */ rval = sys_fcntl(fd, cmd, arg); return map_flags(rval, fl_linux_to_svr4); case 4: /* F_SETFL */ arg = map_flags(arg, fl_svr4_to_linux); return sys_fcntl(fd, cmd, arg); case 14: /* F_GETLK SVR4 */ cmd = 5; /*FALLTHROUGH*/ case 5: /* F_GETLK */ case 6: /* F_SETLK */ case 7: /* F_SETLKW */ return svr4_fcntl_flock(fd, cmd, arg); case 10: /* F_ALLOCSP */ /* Extend allocation for specified portion of file. */ return 0; case 11: /* F_FREESP */ /* Free a portion of a file. */ return 0; /* * These are intended to support the Xenix chsize() and * rdchk() system calls. I don't know if these may be * generated by applications or not. */ case 0x6000: /* F_CHSIZE */ return sys_ftruncate(fd, arg); case 0x6001: /* F_RDCHK */ { mm_segment_t fs; int nbytes; fs = get_fs(); set_fs(get_ds()); rval = sys_ioctl(fd, FIONREAD, &nbytes); set_fs(fs); if (rval < 0) return rval; return (nbytes ? 1 : 0); } case 8: /* F_CHKFL */ /*FALLTHROUGH*/ /* * These are made from the Xenix locking() system call. * According to available documentation these would * never be generated by an application - only by the * kernel Xenix support. */ case 0x6300: /* F_LK_UNLCK */ case 0x7200: /* F_LK_LOCK */ case 0x6200: /* F_LK_NBLCK */ case 0x7100: /* F_LK_RLCK */ case 0x6100: /* F_LK_NBRLCK */ /*FALLTHROUGH*/ default: abi_trace(ABI_TRACE_API, "unsupported fcntl 0x%x, arg 0x%lx\n", cmd, arg); return -EINVAL; } }
/* * locking() requires mandatory locking. Processes that attempt to * read or write a region locked with locking() are required to block. * You need to build a kernel with mandatory locking support and set * the permissions on the required file to setgid, no group execute. */ int xnx_locking(int fd, int mode, unsigned long size) { struct flock fl; mm_segment_t old_fs; int error; if ((mode < 0 || mode > 7) && mode != 20) { #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "unsupported locking() mode=0x%x\n", mode); #endif return -EINVAL; } /* * Modes 5, 6 & 7 are very like the fcntl mechanism but * we can't just punt to that because the type values are * different. */ if (mode > 4 && mode < 8) { struct ibcs_flock *ifl = (struct ibcs_flock *)size; short t; error = verify_area(VERIFY_READ, ifl, sizeof(*ifl)); if (error) return error; get_user(t, &ifl->l_type); switch (t) { case XF_UNLCK: t = F_UNLCK; break; case XF_WRLCK: t = F_WRLCK; break; case XF_RDLCK: t = F_RDLCK; break; default: return -EINVAL; } put_user(t, &ifl->l_type); error = sys_fcntl(fd, mode, (u_long)ifl); get_user(t, &ifl->l_type); switch (t) { case F_UNLCK: t = XF_UNLCK; break; case F_WRLCK: t = XF_WRLCK; break; case F_RDLCK: t = XF_RDLCK; break; } put_user(t, &ifl->l_type); get_user(t, &ifl->l_sysid); put_user(t, &ifl->l_pid); put_user(0, &ifl->l_sysid); return error; } fl.l_type = (mode == 0 ? F_UNLCK : ((mode <= 2 || mode == 20) ? F_WRLCK : F_RDLCK)); fl.l_whence = 1; fl.l_start = 0; fl.l_len = size; old_fs = get_fs(); set_fs (get_ds()); error = sys_fcntl(fd, (mode == 5) ? F_GETLK : (!(mode % 2) ? F_SETLK : F_SETLKW), (u_long)&fl); set_fs(old_fs); return error; }
/* This is an SVR4 system call that is undocumented except for some * hints in a header file. It appears to be a forerunner to the * POSIX sysconf() call. */ int svr4_sysconfig(int name) { switch (name) { case _CONFIG_NGROUPS: /* From limits.h */ return (NGROUPS_MAX); case _CONFIG_CHILD_MAX: /* From limits.h */ return (CHILD_MAX); case _CONFIG_OPEN_FILES: /* From limits.h */ return (OPEN_MAX); case _CONFIG_POSIX_VER: /* The version of the POSIX standard we conform * to. SCO defines _POSIX_VERSION as 198808L * sys/unistd.h. What are we? We are 199009L. */ return (199009L); case _CONFIG_PAGESIZE: return (PAGE_SIZE); case _CONFIG_CLK_TCK: return (HZ); case _CONFIG_XOPEN_VER: return 4; case _CONFIG_NACLS_MAX: return 0; case _CONFIG_NPROC: return 4000; /* max_threads */ case _CONFIG_NENGINE: case _CONFIG_NENGINE_ONLN: return (num_online_cpus()); case _CONFIG_TOTAL_MEMORY: return (max_mapnr << (PAGE_SHIFT-10)); case _CONFIG_USEABLE_MEMORY: case _CONFIG_GENERAL_MEMORY: return (max_mapnr << (PAGE_SHIFT-10)); /* return ((unsigned long) (nr_free_pages()) << (PAGE_SHIFT-10)); */ case _CONFIG_DEDICATED_MEMORY: return 0; case _CONFIG_NCGS_CONF: case _CONFIG_NCGS_ONLN: case _CONFIG_MAX_ENG_PER_CG: return 1; /* no NUMA-Q support on Linux yet */ /* well, there is. we lie anyway --hch */ case _CONFIG_CACHE_LINE: return 32; /* XXX is there a more accurate way? */ case _CONFIG_KERNEL_VM: return -EINVAL; case _CONFIG_ARG_MAX: /* From limits.h */ return (ARG_MAX); } #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "unsupported sysconfig call %d\n", name); #endif return -EINVAL; }
/* * Helper function to process the load operation. */ static int coff_load_object(struct linux_binprm *bprm, struct pt_regs *regs, int binary) { COFF_FILHDR *coff_hdr = NULL; COFF_SCNHDR *text_sect = NULL, *data_sect = NULL, *bss_sect = NULL, *sect_bufr = NULL, *sect_ptr = NULL; int text_count = 0, data_count = 0, bss_count = 0, lib_count = 0; coff_section text, data, bss; u_long start_addr = 0, p = bprm->p, m_addr, lPers; short flags, aout_size = 0; int pageable = 1, sections = 0, status = 0, i, ce; int coff_exec_fileno; mm_segment_t old_fs; lPers = abi_personality((char *)_BX(regs)); ce = cap_mmap(0); coff_hdr = (COFF_FILHDR *)bprm->buf; /* * Validate the magic value for the object file. */ if (COFF_I386BADMAG(*coff_hdr)) return -ENOEXEC; flags = COFF_SHORT(coff_hdr->f_flags); /* * The object file should have 32 BIT little endian format. Do not allow * it to have the 16 bit object file flag set as Linux is not able to run * on the 80286/80186/8086. */ if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR) return -ENOEXEC; /* * If the file is not executable then reject the execution. This means * that there must not be external references. */ if ((flags & COFF_F_EXEC) == 0) return -ENOEXEC; /* * Extract the header information which we need. */ sections = COFF_SHORT(coff_hdr->f_nscns); /* Number of sections */ aout_size = COFF_SHORT(coff_hdr->f_opthdr); /* Size of opt. headr */ /* * There must be at least one section. */ if (!sections) return -ENOEXEC; if (!bprm->file->f_op->mmap) pageable = 0; if (!(sect_bufr = kmalloc(sections * COFF_SCNHSZ, GFP_KERNEL))) { printk(KERN_WARNING "coff: kmalloc failed\n"); return -ENOMEM; } status = kernel_read(bprm->file, aout_size + COFF_FILHSZ, (char *)sect_bufr, sections * COFF_SCNHSZ); if (status < 0) { printk(KERN_WARNING "coff: unable to read\n"); goto out_free_buf; } status = get_unused_fd(); if (status < 0) { printk(KERN_WARNING "coff: unable to get free fs\n"); goto out_free_buf; } get_file(bprm->file); fd_install(coff_exec_fileno = status, bprm->file); /* * Loop through the sections and find the various types */ sect_ptr = sect_bufr; for (i = 0; i < sections; i++) { long int sect_flags = COFF_LONG(sect_ptr->s_flags); switch (sect_flags) { case COFF_STYP_TEXT: status |= coff_isaligned(sect_ptr); text_sect = sect_ptr; text_count++; break; case COFF_STYP_DATA: status |= coff_isaligned(sect_ptr); data_sect = sect_ptr; data_count++; break; case COFF_STYP_BSS: bss_sect = sect_ptr; bss_count++; break; case COFF_STYP_LIB: lib_count++; break; default: break; } sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ]; } /* * If any of the sections weren't properly aligned we aren't * going to be able to demand page this executable. Note that * at this stage the *only* excuse for having status <= 0 is if * the alignment test failed. */ if (status < 0) pageable = 0; /* * Ensure that there are the required sections. There must be one * text sections and one each of the data and bss sections for an * executable. A library may or may not have a data / bss section. */ if (text_count != 1) { status = -ENOEXEC; goto out_free_file; } if (binary && (data_count != 1 || bss_count != 1)) { status = -ENOEXEC; goto out_free_file; } /* * If there is no additional header then assume the file starts * at the first byte of the text section. This may not be the * proper place, so the best solution is to include the optional * header. A shared library __MUST__ have an optional header to * indicate that it is a shared library. */ if (aout_size == 0) { if (!binary) { status = -ENOEXEC; goto out_free_file; } start_addr = COFF_LONG(text_sect->s_vaddr); } else if (aout_size < (short) COFF_AOUTSZ) { status = -ENOEXEC; goto out_free_file; } else { COFF_AOUTHDR *aout_hdr; short aout_magic; aout_hdr = (COFF_AOUTHDR *) &((char *)coff_hdr)[COFF_FILHSZ]; aout_magic = COFF_SHORT(aout_hdr->magic); /* * Validate the magic number in the a.out header. If it is valid then * update the starting symbol location. Do not accept these file formats * when loading a shared library. */ switch (aout_magic) { case COFF_OMAGIC: case COFF_ZMAGIC: case COFF_STMAGIC: if (!binary) { status = -ENOEXEC; goto out_free_file; } start_addr = (u_int)COFF_LONG(aout_hdr->entry); break; /* * Magic value for a shared library. This is valid only when * loading a shared library. * * (There is no need for a start_addr. It won't be used.) */ case COFF_SHMAGIC: if (!binary) break; /* FALLTHROUGH */ default: status = -ENOEXEC; goto out_free_file; } } /* * Generate the proper values for the text fields * * THIS IS THE POINT OF NO RETURN. THE NEW PROCESS WILL TRAP OUT SHOULD * SOMETHING FAIL IN THE LOAD SEQUENCE FROM THIS POINT ONWARD. */ text.scnptr = COFF_LONG(text_sect->s_scnptr); text.size = COFF_LONG(text_sect->s_size); text.vaddr = COFF_LONG(text_sect->s_vaddr); /* * Generate the proper values for the data fields */ if (data_sect != NULL) { data.scnptr = COFF_LONG(data_sect->s_scnptr); data.size = COFF_LONG(data_sect->s_size); data.vaddr = COFF_LONG(data_sect->s_vaddr); } else { data.scnptr = 0; data.size = 0; data.vaddr = 0; } /* * Generate the proper values for the bss fields */ if (bss_sect != NULL) { bss.size = COFF_LONG(bss_sect->s_size); bss.vaddr = COFF_LONG(bss_sect->s_vaddr); } else { bss.size = 0; bss.vaddr = 0; } /* * Flush the executable from memory. At this point the executable is * committed to being defined or a segmentation violation will occur. */ if (binary) { COFF_SCNHDR *sect_ptr2 = sect_bufr; u_long personality = PER_SVR3; int i; if ((status = flush_old_exec(bprm))) goto out_free_file; /* * Look for clues as to the system this binary was compiled * on in the comments section(s). * * Only look at the main binary, not the shared libraries * (or would it be better to prefer shared libraries over * binaries? Or could they be different???) */ for (i = 0; i < sections; i++) { long sect_flags = COFF_LONG(sect_ptr2->s_flags); if (sect_flags == COFF_STYP_INFO && (status = coff_parse_comments(bprm->file, sect_ptr2, &personality)) > 0) goto found; sect_ptr2 = (COFF_SCNHDR *) &((char *)sect_ptr2)[COFF_SCNHSZ]; } /* * If no .comments section was found there is no way to * figure out the personality. Odds on it is SCO though... */ personality = PER_SCOSVR3; found: if (lPers) personality = lPers; if ( (personality & 0xFF) == (current->personality & 0xFF) ) set_personality(0); set_personality(personality); #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_UNIMPL,"Personality %08lX assigned\n",personality); #endif #ifdef CONFIG_64BIT set_thread_flag(TIF_IA32); clear_thread_flag(TIF_ABI_PENDING); #endif current->mm->start_data = 0; current->mm->end_data = 0; current->mm->end_code = 0; current->mm->mmap = NULL; current->flags &= ~PF_FORKNOEXEC; #ifdef set_mm_counter #if _KSL > 14 set_mm_counter(current->mm, file_rss, 0); #else set_mm_counter(current->mm, rss, 0); #endif #else current->mm->rss = 0; #endif /* * Construct the parameter and environment * string table entries. */ #if _KSL > 10 if ((status = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT)) < 0) #else if ((status = setup_arg_pages(bprm, EXSTACK_DEFAULT)) < 0) #endif goto sigsegv; p = (u_long)coff_mktables((char *)bprm->p, bprm->argc, bprm->envc); current->mm->end_code = text.size + (current->mm->start_code = text.vaddr); current->mm->end_data = data.size + (current->mm->start_data = data.vaddr); current->mm->brk = bss.size + (current->mm->start_brk = bss.vaddr); current->mm->start_stack = p; #if _KSL > 28 install_exec_creds(bprm); #else compute_creds(bprm); #endif #if _KSL < 15 #ifdef CONFIG_64BIT __asm__ volatile ( "movl %0,%%fs; movl %0,%%es; movl %0,%%ds" : :"r" (0)); __asm__ volatile ( "pushf; cli; swapgs; movl %0,%%gs; mfence; swapgs; popf" : :"r" (0)); write_pda(oldrsp,p); _FLG(regs) = 0x200; #else __asm__ volatile ( "movl %0,%%fs ; movl %0,%%gs" : :"r" (0)); _DS(regs) = _ES(regs) = __USER_DS; #endif _SS(regs) = __USER_DS; _SP(regs) = p; _CS(regs) = __USER_CS; _IP(regs) = start_addr; set_fs(USER_DS); #else start_thread(regs, start_addr, p); #endif #ifdef CONFIG_64BIT __asm__ volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); _SS(regs) = __USER32_DS; _CS(regs) = __USER32_CS; #endif } old_fs = get_fs(); set_fs(get_ds()); if (!pageable) { /* * Read the file from disk... * * XXX: untested. */ loff_t pos = data.scnptr; status = do_brk(text.vaddr, text.size); bprm->file->f_op->read(bprm->file, (char *)data.vaddr, data.scnptr, &pos); status = do_brk(data.vaddr, data.size); bprm->file->f_op->read(bprm->file, (char *)text.vaddr, text.scnptr, &pos); status = 0; } else { /* map the text pages...*/ cap_mmap(1); m_addr = map_coff(bprm->file, &text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, text.scnptr & PAGE_MASK); if(!ce) cap_mmap(2); if (m_addr != (text.vaddr & PAGE_MASK)) { status = -ENOEXEC; set_fs(old_fs); goto out_free_file; } /* map the data pages */ if (data.size != 0) { cap_mmap(1); m_addr = map_coff(bprm->file, &data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, data.scnptr & PAGE_MASK); if(!ce) cap_mmap(2); if (m_addr != (data.vaddr & PAGE_MASK)) { status = -ENOEXEC; set_fs(old_fs); goto out_free_file; } } status = 0; } /* * Construct the bss data for the process. The bss ranges from the * end of the data (which may not be on a page boundary) to the end * of the bss section. Allocate any necessary pages for the data. */ if (bss.size != 0) { cap_mmap(1); down_write(¤t->mm->mmap_sem); do_mmap(NULL, PAGE_ALIGN(bss.vaddr), bss.size + bss.vaddr - PAGE_ALIGN(bss.vaddr), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_32BIT, 0); up_write(¤t->mm->mmap_sem); if(!ce) cap_mmap(2); if ((status = coff_clear_memory(bss.vaddr, bss.size)) < 0) { set_fs(old_fs); goto out_free_file; } } set_fs(old_fs); if (!binary) goto out_free_file; /* * Load any shared library for the executable. */ if (lib_count) status = coff_preload_shlibs(bprm, sect_bufr, sections); set_binfmt(&coff_format); /* * Generate any needed trap for this process. If an error occured then * generate a segmentation violation. If the process is being debugged * then generate the load trap. (Note: If this is a library load then * do not generate the trap here. Pass the error to the caller who * will do it for the process in the outer lay of this procedure call.) */ if (status < 0) { sigsegv: printk(KERN_WARNING "coff: trapping process with SEGV\n"); send_sig(SIGSEGV, current, 0); /* Generate the error trap */ } #ifdef CONFIG_PTRACE /* --- Red Hat specific handling --- */ #else else if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); #endif /* We are committed. It can't fail */ status = 0; out_free_file: SYS(close,coff_exec_fileno); out_free_buf: kfree(sect_bufr); return (status); }
int svr4_stream_ioctl(struct pt_regs *regs, int fd, u_int cmd, caddr_t data) { struct file *fp; struct inode *ip; int error; fp = fget(fd); if (!fp) return -EBADF; ip = fp->f_dentry->d_inode; /* * Special hack^H^Hndling for socksys fds */ if (ip->i_sock == 0 && IS_SOCKSYS(ip)) { error = socksys_fdinit(fd, 0, NULL, NULL); if (error < 0) return error; fput(fp); fp = fget(fd); if (!fp) return -EBADF; ip = fp->f_dentry->d_inode; } switch (cmd) { case 001: /* I_NREAD */ return i_nread(fd, fp, ip, data, regs); case 017: /* I_PEEK */ return i_peek(fd, fp, ip, data, regs); } fput(fp); switch (cmd) { case 010: /* I_STR */ return i_str(fd, fp, ip, data, regs); case 002: { /* I_PUSH */ char *tmp; /* Get the name anyway to validate it. */ tmp = getname(data); if (IS_ERR(tmp)) return PTR_ERR(tmp); abi_trace(ABI_TRACE_STREAMS, "%d STREAMS I_PUSH %s\n", fd, tmp); putname(tmp); return 0; } case 003: /* I_POP */ abi_trace(ABI_TRACE_STREAMS, "%d STREAMS I_POP\n", fd); return 0; case 005: /* I_FLUSH */ return 0; case 013: { /* I_FIND */ char *tmp; /* Get the name anyway to validate it. */ tmp = getname(data); if (IS_ERR(tmp)) return PTR_ERR(tmp); abi_trace(ABI_TRACE_STREAMS, "%d STREAMS I_FIND %s\n", fd, tmp); #ifdef CONFIG_ABI_XTI if (!strcmp(tmp, "timod")) { putname(tmp); return 1; } #endif putname(tmp); return 0; } /* FIXME: These are bogus. */ case 011: /* I_SETSIG */ return sys_ioctl(fd, FIOSETOWN, (void *)current->pid); case 012: /* I_GETSIG */ return sys_ioctl(fd, FIOGETOWN, data); case 020: /* I_FDINSERT */ #ifdef CONFIG_ABI_XTI return stream_fdinsert(regs, fd, (struct strfdinsert *)data); #else return -EINVAL; #endif case 004: /* I_LOOK */ case 006: /* I_SRDOPT */ case 007: /* I_GRDOPT */ case 014: /* I_LINK */ case 015: /* I_UNLINK */ case 021: /* I_SENDFD */ case 022: /* I_RECVFD */ case 023: /* I_SWROPT */ case 040: /* I_SETCLTIME */ return 0; /* Lie... */ case 042: /* I_CANPUT */ /* * Arg is the priority band in question. We only * support one priority band so data must be 0. * If the band is writable we should return 1, if * the band is flow controlled we should return 0. */ if (data) return -EINVAL; /* FIXME: How can we test if a write would block? */ return 1; case 024: /* I_GWROPT */ case 025: /* I_LIST */ case 026: /* I_PLINK */ case 027: /* I_PUNLINK */ case 030: /* I_SETEV */ case 031: /* I_GETEV */ case 032: /* I_STREV */ case 033: /* I_UNSTREV */ case 034: /* I_FLUSHBAND */ case 035: /* I_CKBAND */ case 036: /* I_GETBAND */ case 037: /* I_ATMARK */ case 041: /* I_GETCLTIME */ /* Unsupported - drop out. */ } printk(KERN_ERR "iBCS: STREAMS ioctl 0%o unsupported\n", cmd); return -EINVAL; }
static int svr4_shmctl(int arg1, int cmd, char *arg3) { struct ibcs2_shmid_ds is; struct abi4_shmid_ds is4; struct shmid_ds ls; mm_segment_t fs; int err; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "shmctl(%d, %x, %p)\n", arg1, cmd, arg3); #endif switch (cmd) { case SVR4_SHM_LOCK: #ifdef CONFIG_65BIT err = SYS(shmctl, arg1, SHM_LOCK, (struct shmid_ds *)arg3); #else err = SYS(ipc,SHMCTL,arg1, SHM_LOCK,0, (struct shmid_ds *)arg3); #endif return err; case SVR4_SHM_UNLOCK: #ifdef CONFIG_65BIT err = SYS(shmctl, arg1, SHM_UNLOCK, (struct shmid_ds *)arg3); #else err = SYS(ipc,SHMCTL,arg1, SHM_UNLOCK,0, (struct shmid_ds *)arg3); #endif return err; case SVR4_IPC_SET: err = copy_from_user(&is, arg3, sizeof(is)) ? -EFAULT : 0; if (err) break; ishm_to_lshm(&is, &ls); fs = get_fs(); set_fs(get_ds()); #ifdef CONFIG_65BIT err = SYS(shmctl, arg1, IPC_SET, &ls); #else err = SYS(ipc,SHMCTL,arg1, IPC_SET,0, &ls); #endif set_fs(fs); if (err < 0) break; lshm_to_ishm(&ls, &is); err = copy_to_user(arg3, &is, sizeof(is)) ? -EFAULT : 0; break; case SVR4_IPC_SET_L: err = copy_from_user(&is4, arg3, sizeof(is4)) ? -EFAULT : 0; if (err) break; ishm_to_lshm_l(&is4, &ls); fs = get_fs(); set_fs(get_ds()); #ifdef CONFIG_65BIT err = SYS(shmctl, arg1, IPC_SET, &ls); #else err = SYS(ipc,SHMCTL,arg1, IPC_SET,0, &ls); #endif set_fs(fs); if (err < 0) break; lshm_to_ishm_l(&ls, &is4); err = copy_to_user(arg3, &is4, sizeof(is4)) ? -EFAULT : 0; break; case SVR4_IPC_RMID: case SVR4_IPC_RMID_L: #ifdef CONFIG_65BIT err = SYS(shmctl, arg1, IPC_RMID, arg3); #else err = SYS(ipc,SHMCTL,arg1, IPC_RMID,0, arg3); #endif return err; case SVR4_IPC_STAT: fs = get_fs(); set_fs(get_ds()); #ifdef CONFIG_65BIT err = SYS(shmctl, arg1, IPC_STAT, &ls); #else err = SYS(ipc,SHMCTL,arg1, IPC_STAT,0, &ls); #endif set_fs(fs); if (err < 0) break; lshm_to_ishm(&ls, &is); err = copy_to_user(arg3, &is, sizeof(is)) ? -EFAULT : 0; break; case SVR4_IPC_STAT_L: fs = get_fs(); set_fs(get_ds()); #ifdef CONFIG_65BIT err = SYS(shmctl, arg1, IPC_STAT, &ls); #else err = SYS(ipc,SHMCTL,arg1, IPC_STAT,0, &ls); #endif set_fs(fs); if (err < 0) break; lshm_to_ishm_l(&ls, &is4); err = copy_to_user((char *)arg3, &is4, sizeof(is4)) ? -EFAULT : 0; break; default: #if defined(CONFIG_ABI_TRACE) __abi_trace("shmctl: unsupported command %d\n", cmd); #endif err = -EINVAL; } return (err); }
int svr4_shmsys(struct pt_regs *regp) { int arg1, arg2, arg3, cmd, err = 0; u_long raddr; mm_segment_t fs; cmd = get_syscall_parameter(regp, 0); if (cmd == SVR4_shmdt) { err = svr4_shmdt(regp); goto out; } arg1 = get_syscall_parameter(regp, 1); arg2 = get_syscall_parameter(regp, 2); arg3 = get_syscall_parameter(regp, 3); switch (cmd) { case SVR4_shmat: #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "shmat(%d, %x, %o)\n", arg1, arg2, arg3); #endif fs = get_fs(); set_fs(get_ds()); #ifdef CONFIG_65BIT err = SYS(shmat, arg1, arg2, arg3, &raddr); #else err = SYS(ipc,SHMAT+0x10000,arg1,arg3,&raddr,arg2); #endif set_fs(fs); if (err >= 0) err = (int)raddr; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "shmat returns %x\n", err); #endif break; case SVR4_shmget: #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "shmget(%d, %x, %o)\n", arg1, arg2, arg3); #endif #ifdef CONFIG_65BIT err = SYS(shmget, arg1, arg2, arg3); #else err = SYS(ipc,SHMGET,arg1, arg2, arg3); #endif #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "shmget returns %d\n", err); #endif break; case SVR4_shmctl: err = svr4_shmctl(arg1, arg2, (char *)((long)arg3)); break; default: #if defined(CONFIG_ABI_TRACE) __abi_trace("shmsys: unsupported command: %x\n", cmd); #endif err = -EINVAL; } out: if (err < 0 && err > -255) { set_error(regp, iABI_errors(-err)); #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "Error %d\n", get_result(regp)); #endif return 0; } clear_error(regp); set_result(regp, err); return 0; }
/* * XXX: this function is a _horrible_ mess. */ static int timod_optmgmt(int fd, struct pt_regs * regs, int flag, char * opt_buf, int opt_len, int do_ret) { struct file * fp = fcheck(fd); char *ret_buf, *ret_base; u_int old_esp, *tsp; int is_tli, error, failed; int ret_len, ret_space; error=0; if (opt_buf && opt_len > 0) { if (!access_ok(VERIFY_READ, opt_buf, opt_len)) return -EFAULT; } /* * FIXME: * We should be able to detect the difference between * TLI and XTI requests at run time? */ #ifdef CONFIG_ABI_TLI_OPTMGMT is_tli = 1; #else is_tli = 0; #endif if (!do_ret && (!opt_buf || opt_len <= 0)) return 0; /* * Grab some space on the user stack to work with. We need 6 longs * to build an argument frame for [gs]etsockopt calls. We also * need space to build the return buffer. This will be at least * as big as the given options buffer but the given options * buffer may not include space for option values so we allow two * longs for each option multiple of the option header size * and hope that big options will not exhaust our space and * trash the stack. */ ret_space = 1024 + opt_len + 2*sizeof(long)*(opt_len / (is_tli ? sizeof(struct opthdr) : sizeof(struct t_opthdr))); ret_buf = ret_base = (char *)(_SP(regs) - ret_space); ret_len = 0; old_esp = _SP(regs); _SP(regs) -= ret_space + 6*sizeof(long); tsp = (unsigned int *)_SP(regs); if (!access_ok(VERIFY_WRITE, tsp, 6*sizeof(long))) { _SP(regs) = old_esp; return -EFAULT; } failed = 0; #ifndef CONFIG_ABI_TLI_OPTMGMT if (is_tli) { printk(KERN_WARNING "%d iBCS: TLI optmgmt requested but not supported\n", current->pid); } #else if (is_tli) while (opt_len >= sizeof(struct opthdr)) { struct opthdr opt; #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "TLI optmgmt opt_len=%d, " "ret_buf=0x%08lx, ret_len=%d, ret_space=%d\n", opt_len, (unsigned long)ret_buf, ret_len, ret_space); #endif if (copy_from_user(&opt, opt_buf, sizeof(struct opthdr))) return -EFAULT; /* Idiot check... */ if (opt.len > opt_len) { failed = TBADOPT; break; } #if defined(CONFIG_ABI_TRACE) if (abi_traced(ABI_TRACE_STREAMS)) { unsigned long v; get_user(v, (unsigned long *)(opt_buf+sizeof(struct opthdr))); __abi_trace("TLI optmgmt fd=%d, level=%ld, " "name=%ld, value=%ld\n", fd, opt.level, opt.name, v); } #endif /* Check writable space in the return buffer. */ if (!access_ok(VERIFY_WRITE, ret_buf, sizeof(struct opthdr))) { failed = TSYSERR; break; } /* Flag values: * T_NEGOTIATE means try and set it. * T_DEFAULT means get the default value. * (return the current for now) * T_CHECK means get the current value. */ error = 0; if (flag == T_NEGOTIATE) { put_user(fd, tsp); put_user(opt.level, tsp+1); put_user(opt.name, tsp+2); put_user((long)opt_buf+sizeof(struct opthdr), tsp+3); put_user(opt.len, tsp+4); error = abi_do_setsockopt(tsp); if (error) { #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "setsockopt failed: %d\n", error); #endif failed = TBADOPT; break; } } if (!error) { int len; put_user(fd, tsp); put_user(opt.level, tsp+1); put_user(opt.name, tsp+2); put_user((long)ret_buf+sizeof(struct opthdr), tsp+3); put_user((long)(tsp+5), tsp+4); put_user(ret_space, tsp+5); error = abi_do_getsockopt(tsp); if (error) { #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_STREAMS, "getsockopt failed: %d\n", error); #endif failed = TBADOPT; break; } get_user(len, tsp+5); if (copy_to_user(ret_buf, &opt, sizeof(opt))) return -EFAULT; put_user(len, &((struct opthdr *)opt_buf)->len); ret_space -= sizeof(struct opthdr) + len; ret_len += sizeof(struct opthdr) + len; ret_buf += sizeof(struct opthdr) + len; } opt_len -= sizeof(struct opthdr) + opt.len; opt_buf += sizeof(struct opthdr) + opt.len; } #endif /* CONFIG_ABI_TLI_OPTMGMT */ #ifndef CONFIG_ABI_XTI_OPTMGMT else { printk(KERN_WARNING "%d iBCS: XTI optmgmt requested but not supported\n", current->pid); } #else else while (opt_len >= sizeof(struct t_opthdr)) {
/* * locking() requires mandatory locking. Processes that attempt to * read or write a region locked with locking() are required to block. * You need to build a kernel with mandatory locking support and set * the permissions on the required file to setgid, no group execute. */ int xnx_locking(int fd, int mode, unsigned long size) { struct flock fl; mm_segment_t old_fs; int error; if ((mode < 0 || mode > 7) && mode != 20) { #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "unsupported locking() mode=0x%x\n", mode); #endif return -EINVAL; } /* * Modes 5, 6 & 7 are very like the fcntl mechanism but * we can't just punt to that because the type values are * different. */ if (mode > 4 && mode < 8) { struct ibcs_flock *ifl = (struct ibcs_flock *)size; short t; if (!access_ok(VERIFY_READ, ifl, sizeof(*ifl))) return -EFAULT; get_user(t, &ifl->l_type); switch (t) { case XF_UNLCK: t = F_UNLCK; break; case XF_WRLCK: t = F_WRLCK; break; case XF_RDLCK: t = F_RDLCK; break; default: return -EINVAL; } put_user(t, &ifl->l_type); error = SYS(fcntl,fd, mode, (u_long)ifl); get_user(t, &ifl->l_type); switch (t) { case F_UNLCK: t = XF_UNLCK; break; case F_WRLCK: t = XF_WRLCK; break; case F_RDLCK: t = XF_RDLCK; break; } put_user(t, &ifl->l_type); get_user(t, &ifl->l_sysid); put_user(t, &ifl->l_pid); put_user(0, &ifl->l_sysid); return error; } fl.l_type = (mode == 0 ? F_UNLCK : ((mode <= 2 || mode == 20) ? F_WRLCK : F_RDLCK)); fl.l_whence = 1; fl.l_start = 0; fl.l_len = size; old_fs = get_fs(); set_fs (get_ds()); #if 0 error = SYS(fcntl,fd, (mode == 5) ? F_GETLK : (!(mode % 2) ? F_SETLK : F_SETLKW), (u_long)&fl); #else // Johns: Xenix locking didn't work with just created files // Taken from old ibcs2 code, adjusted for 2.6 { struct file *filep; error = -EBADF; if ((filep = fget(fd))) { mode_t old_mode = filep->f_mode; filep->f_mode |= FMODE_WRITE | FMODE_READ; error = SYS(fcntl,fd, (mode == 5) ? F_GETLK : (!(mode % 2) ? F_SETLK : F_SETLKW), (u_long)&fl); filep->f_mode = old_mode; } } #endif set_fs(old_fs); return error; }
/* * Helper function to process the load operation. */ static int xout_load_object(struct linux_binprm * bpp, struct pt_regs *rp, int executable) { struct xexec *xexec = (struct xexec *)bpp->buf; struct xext *xext = (struct xext *)(xexec + 1); struct xseg *seglist; struct file *fp = NULL; u_long addr, lPers; int nsegs, ntext, ndata; int pageable = 1, err = 0, i; #ifdef CONFIG_BINFMT_XOUT_X286 struct file *file; #endif lPers = abi_personality((char *)_BX(rp)); if (lPers == 0) lPers = PER_XENIX; if (xexec->x_magic != X_MAGIC) { return -ENOEXEC; } switch (xexec->x_cpu & XC_CPU) { case XC_386: break; #if defined(CONFIG_BINFMT_XOUT_X286) case XC_8086: case XC_286: case XC_286V: case XC_186: if (!Emulx286) return -ENOEXEC; file = open_exec(Emulx286); if (file) { fput(bpp->file); bpp->file = file; kernel_read(bpp->file, 0L, bpp->buf, sizeof(bpp->buf)); } return -ENOEXEC; #endif default: dprintk(KERN_DEBUG "xout: unsupported CPU type (%02x)\n", xexec->x_cpu); return -ENOEXEC; } /* * We can't handle byte or word swapped headers. Well, we * *could* but they should never happen surely? */ if ((xexec->x_cpu & (XC_BSWAP | XC_WSWAP)) != XC_WSWAP) { dprintk(KERN_DEBUG "xout: wrong byte or word sex (%02x)\n", xexec->x_cpu); return -ENOEXEC; } /* Check it's an executable. */ if (!(xexec->x_renv & XE_EXEC)) { dprintk(KERN_DEBUG "xout: not executable\n"); return -ENOEXEC; } /* * There should be an extended header and there should be * some segments. At this stage we don't handle non-segmented * binaries. I'm not sure you can get them under Xenix anyway. */ if (xexec->x_ext != sizeof(struct xext)) { dprintk(KERN_DEBUG "xout: bad extended header\n"); return -ENOEXEC; } if (!(xexec->x_renv & XE_SEG) || !xext->xe_segsize) { dprintk(KERN_DEBUG "xout: not segmented\n"); return -ENOEXEC; } if (!(seglist = kmalloc(xext->xe_segsize, GFP_KERNEL))) { printk(KERN_WARNING "xout: allocating segment list failed\n"); return -ENOMEM; } err = kernel_read(bpp->file, xext->xe_segpos, (char *)seglist, xext->xe_segsize); if (err < 0) { dprintk(KERN_DEBUG "xout: problem reading segment table\n"); goto out; } if (!bpp->file->f_op->mmap) pageable = 0; nsegs = xext->xe_segsize / sizeof(struct xseg); ntext = ndata = 0; for (i = 0; i < nsegs; i++) { switch (seglist[i].xs_type) { case XS_TTEXT: if (isnotaligned(seglist+i)) pageable = 0; ntext++; break; case XS_TDATA: if (isnotaligned(seglist+i)) pageable = 0; ndata++; break; } } if (!ndata) goto out; /* * Generate the proper values for the text fields * * THIS IS THE POINT OF NO RETURN. THE NEW PROCESS WILL TRAP OUT SHOULD * SOMETHING FAIL IN THE LOAD SEQUENCE FROM THIS POINT ONWARD. */ /* * Flush the executable from memory. At this point the executable is * committed to being defined or a segmentation violation will occur. */ if (executable) { dprintk(KERN_DEBUG "xout: flushing executable\n"); flush_old_exec(bpp); if ( (lPers & 0xFF) == (current->personality & 0xFF) ) set_personality(0); set_personality(lPers); #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_UNIMPL, "Personality %08X assigned\n", (unsigned int)current->personality); #endif #ifdef CONFIG_64BIT set_thread_flag(TIF_IA32); clear_thread_flag(TIF_ABI_PENDING); #endif current->mm->mmap = NULL; #ifdef set_mm_counter #if _KSL > 14 set_mm_counter(current->mm, file_rss, 0); #else set_mm_counter(current->mm, rss, 0); #endif #else current->mm->rss = 0; #endif #if _KSL > 10 if ((err = setup_arg_pages(bpp, STACK_TOP, EXSTACK_DEFAULT)) < 0) #else if ((err = setup_arg_pages(bpp, EXSTACK_DEFAULT)) < 0) #endif { send_sig(SIGSEGV, current, 1); return (err); } bpp->p = (u_long)xout_create_tables((char *)bpp->p, bpp, (xexec->x_cpu & XC_CPU) == XC_386 ? 1 : 0); current->mm->start_code = 0; current->mm->end_code = xexec->x_text; current->mm->end_data = xexec->x_text + xexec->x_data; current->mm->start_brk = current->mm->brk = xexec->x_text + xexec->x_data + xexec->x_bss; #if _KSL > 28 install_exec_creds(bpp); #else compute_creds(bpp); #endif current->flags &= ~PF_FORKNOEXEC; #if _KSL < 15 #ifdef CONFIG_64BIT __asm__ volatile ( "movl %0,%%fs; movl %0,%%es; movl %0,%%ds" : :"r" (0)); __asm__ volatile ( "pushf; cli; swapgs; movl %0,%%gs; mfence; swapgs; popf" : :"r" (0)); write_pda(oldrsp,bpp->p); _FLG(rp) = 0x200; #else __asm__ volatile ( "movl %0,%%fs ; movl %0,%%gs" : :"r" (0)); _DS(rp) = _ES(rp) = __USER_DS; #endif _SS(rp) = __USER_DS; _SP(rp) = bpp->p; _CS(rp) = __USER_CS; _IP(rp) = xexec->x_entry; set_fs(USER_DS); #else start_thread(rp, xexec->x_entry, bpp->p); #endif #ifdef CONFIG_64BIT __asm__ volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); _SS(rp) = __USER32_DS; _CS(rp) = __USER32_CS; #endif dprintk(KERN_DEBUG "xout: entry point = 0x%x:0x%08lx\n", xext->xe_eseg, xexec->x_entry); } /* * Scan the segments and map them into the process space. If this * executable is pageable (unlikely since Xenix aligns to 1k * boundaries and we want it aligned to 4k boundaries) this is * all we need to do. If it isn't pageable we go round again * afterwards and load the data. We have to do this in two steps * because if segments overlap within a 4K page we'll lose the * first instance when we remap the page. Hope that's clear... */ for (i = 0; err >= 0 && i < nsegs; i++) { struct xseg *sp = seglist+i; if (sp->xs_attr & XS_AMEM) { err = xout_amen(fp, sp, pageable, &addr, xexec, rp, (!ntext && ndata == 1)); } } /* * We better fix start_data because sys_brk looks there to * calculate data size. * Kernel 2.2 did look at end_code so this is reasonable. */ if (current->mm->start_data == current->mm->start_code) current->mm->start_data = current->mm->end_code; dprintk(KERN_DEBUG "xout: start code 0x%08lx, end code 0x%08lx," " start data 0x%08lx, end data 0x%08lx, brk 0x%08lx\n", current->mm->start_code, current->mm->end_code, current->mm->start_data, current->mm->end_data, current->mm->brk); if (pageable) goto trap; if (err < 0) goto trap; for (i = 0; (err >= 0) && (i < nsegs); i++) { struct xseg *sp = seglist + i; u_long psize; if (sp->xs_type == XS_TTEXT || sp->xs_type == XS_TDATA) { dprintk(KERN_DEBUG "xout: read to 0x%08lx from 0x%08lx," " length 0x%8lx\n", sp->xs_rbase, sp->xs_filpos, sp->xs_psize); if (sp->xs_psize < 0) continue; /* * Do we still get the size ? Yes! [joerg] */ psize = kernel_read(bpp->file, sp->xs_filpos, (char *)((long)sp->xs_rbase), sp->xs_psize); if (psize != sp->xs_psize) { dprintk(KERN_DEBUG "xout: short read 0x%8lx\n",psize); err = -1; break; } } } /* * Generate any needed trap for this process. If an error occured then * generate a segmentation violation. If the process is being debugged * then generate the load trap. (Note: If this is a library load then * do not generate the trap here. Pass the error to the caller who * will do it for the process in the outer lay of this procedure call.) */ trap: if (executable) { if (err < 0) { dprintk(KERN_DEBUG "xout: loader forces seg fault " "(err = %d)\n", err); send_sig(SIGSEGV, current, 0); } #ifdef CONFIG_PTRACE /* --- Red Hat specific handling --- */ #else else if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); #endif err = 0; } out: kfree(seglist); dprintk(KERN_DEBUG "xout: binfmt_xout: result = %d\n", err); /* * If we are using the [2]86 emulation overlay we enter this * rather than the real program and give it the information * it needs to start the ball rolling. */ /* * Xenix 386 programs expect the initial brk value to be in eax * on start up. Hence if we succeeded we need to pass back * the brk value rather than the status. Ultimately the * ret_from_sys_call assembly will place this in eax before * resuming (starting) the process. */ return (err < 0 ? err : current->mm->brk); }
int svr4_sysfs(int cmd, int arg1, int arg2) { if (cmd == GETFSIND) return sys_sysfs(cmd, arg1, arg2); if (cmd == GETNFSTYP) return sys_sysfs(cmd, arg1, arg2); if (cmd == GETFSTYP) { char *buf = (char *)arg2; int error; if (arg1 & 0x80000000) arg1 &= 0x0000ffff; if (arg1 >= 0 && arg1 < sys_sysfs(GETNFSTYP,0,0)) return sys_sysfs(cmd, arg1-1, arg2); /* * Kludge alert! Hardcoded known magic numbers! */ switch (arg1) { case 0xef53: case 0xffffef53: case 0xef51: case 0xffffef51: /* * Some SCO programs (i.e. Informix Dynamic * Server are using this to detect "real" * filesystems by checking type names :-(. * So we lie :-). */ if (is_cur_personality(PER_SCOSVR3)) error = copy_to_user(buf, "HTFS", 5); else error = copy_to_user(buf, "ext2", 5); break; case 0x137d: error = copy_to_user(buf, "ext", 4); break; case 0x9660: case 0xffff9660: error = copy_to_user(buf, "iso9660", 8); break; case 0x4d44: error = copy_to_user(buf, "msdos", 6); break; case 0x6969: error = copy_to_user(buf, "nfs", 4); break; case 0x9fa0: case 0xffff9fa0: error = copy_to_user(buf, "proc", 5); break; case 0xf995e849: case 0xe849: case 0xffffe849: error = copy_to_user(buf, "hpfs", 5); break; case 0x137f: /* original */ case 0x138f: /* original + 30 char names */ case 0x2468: /* V2 */ case 0x2478: /* V2 + 30 char names */ error = copy_to_user(buf, "minix", 6); break; case 0x564c: error = copy_to_user(buf, "ncpfs", 6); break; case 0x517b: error = copy_to_user(buf, "smbfs", 6); break; case 0x00011954: error = copy_to_user(buf, "ufs", 4); break; case 0x012fd16d: case 0xffffd16d: error = copy_to_user(buf, "xiafs", 6); break; case 0x012ff7b3+1: case 0xfffff7b3+1: error = copy_to_user(buf, "xenix", 6); break; case 0x012ff7b3+2: case 0xfffff7b3+2: case 0x012ff7b3+3: case 0xfffff7b3+3: error = copy_to_user(buf, "sysv", 5); break; case 0x012ff7b3+4: case 0xfffff7b3+4: error = copy_to_user(buf, "coherent", 9); break; default: error = copy_to_user(buf, "", 1); break; } if (error) return -EFAULT; return 0; } #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "unsupported sysfs call %d\n", cmd); #endif return -EINVAL; }