示例#1
0
/*
 * 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;
}
示例#2
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);
}
示例#3
0
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);
}
示例#4
0
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(&current->mm->mmap_sem);
	mapaddr = do_mmap(file, addr, len, prot, flags | MAP_FIXED, off);
	up_write(&current->mm->mmap_sem);

	fput(file);

	if (mapaddr == addr)
		return 0;
	return mapaddr;
}
示例#5
0
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);
}
示例#6
0
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;
}
示例#7
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;
}
示例#8
0
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;

}
示例#9
0
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;
}
示例#10
0
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;
}
示例#11
0
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;
}
示例#12
0
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;
}
示例#13
0
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;
	}
}
示例#14
0
/*
 * 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;
}
示例#15
0
/* 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;
}
示例#16
0
/*
 * 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(&current->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(&current->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);
}
示例#17
0
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;
}
示例#18
0
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);
}
示例#19
0
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;
}
示例#20
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)) {
示例#21
0
/*
 * 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;
}
示例#22
0
/*
 * 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);
}
示例#23
0
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;
}