⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_parisc32.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 2000-2001 Hewlett Packard Company * Copyright (C) 2000 John Marvin * Copyright (C) 2001 Matthew Wilcox * * These routines maintain argument size conversion between 32bit and 64bit * environment. Based heavily on sys_ia32.c and sys_sparc32.c. */#include <linux/config.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h> #include <linux/mm.h> #include <linux/file.h> #include <linux/signal.h>#include <linux/utime.h>#include <linux/resource.h>#include <linux/times.h>#include <linux/utsname.h>#include <linux/timex.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/sem.h>#include <linux/msg.h>#include <linux/shm.h>#include <linux/slab.h>#include <linux/uio.h>#include <linux/nfs_fs.h>#include <linux/smb_fs.h>#include <linux/smb_mount.h>#include <linux/ncp_fs.h>#include <linux/quota.h>#include <linux/module.h>#include <linux/sunrpc/svc.h>#include <linux/nfsd/nfsd.h>#include <linux/nfsd/cache.h>#include <linux/nfsd/xdr.h>#include <linux/nfsd/syscall.h>#include <linux/poll.h>#include <linux/personality.h>#include <linux/stat.h>#include <linux/filter.h>			/* for setsockopt() */#include <linux/icmpv6.h>			/* for setsockopt() */#include <linux/netfilter_ipv4/ip_queue.h>	/* for setsockopt() */#include <linux/netfilter_ipv4/ip_tables.h>	/* for setsockopt() */#include <linux/netfilter_ipv6/ip6_tables.h>	/* for setsockopt() */#include <linux/highmem.h>#include <linux/highuid.h>#include <linux/mman.h>#include <asm/types.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#include "sys32.h"#define A(__x) ((unsigned long)(__x))#undef DEBUG#ifdef DEBUG#define DBG(x)	printk x#else#define DBG(x)#endif/* * count32() counts the number of arguments/envelopes. It is basically *           a copy of count() from fs/exec.c, except that it works *           with 32 bit argv and envp pointers. */static int count32(u32 *argv, int max){	int i = 0;	if (argv != NULL) {		for (;;) {			u32 p;			int error;			error = get_user(p,argv);			if (error)				return error;			if (!p)				break;			argv++;			if(++i > max)				return -E2BIG;		}	}	return i;}/* * copy_strings32() is basically a copy of copy_strings() from fs/exec.c *                  except that it works with 32 bit argv and envp pointers. */static int copy_strings32(int argc, u32 *argv, struct linux_binprm *bprm){	while (argc-- > 0) {		u32 str;		int len;		unsigned long pos;		if (get_user(str, argv + argc) ||		    !str ||		    !(len = strnlen_user((char *)A(str), bprm->p)))			return -EFAULT;		if (bprm->p < len) 			return -E2BIG; 		bprm->p -= len;		pos = bprm->p;		while (len > 0) {			char *kaddr;			int i, new, err;			struct page *page;			int offset, bytes_to_copy;			offset = pos % PAGE_SIZE;			i = pos/PAGE_SIZE;			page = bprm->page[i];			new = 0;			if (!page) {				page = alloc_page(GFP_HIGHUSER);				bprm->page[i] = page;				if (!page)					return -ENOMEM;				new = 1;			}			kaddr = (char *)kmap(page);			if (new && offset)				memset(kaddr, 0, offset);			bytes_to_copy = PAGE_SIZE - offset;			if (bytes_to_copy > len) {				bytes_to_copy = len;				if (new)					memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len);			}			err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy);			flush_dcache_page(page);			flush_page_to_ram(page);			kunmap(page);			if (err)				return -EFAULT; 			pos += bytes_to_copy;			str += bytes_to_copy;			len -= bytes_to_copy;		}	}	return 0;}/* * do_execve32() is mostly a copy of do_execve(), with the exception * that it processes 32 bit argv and envp pointers. */static inline int do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs){	struct linux_binprm bprm;	struct file *file;	int retval;	int i;	file = open_exec(filename);	retval = PTR_ERR(file);	if (IS_ERR(file))		return retval;	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));	DBG(("do_execve32(%s, %p, %p, %p)\n", filename, argv, envp, regs));	bprm.file = file;	bprm.filename = filename;	bprm.sh_bang = 0;	bprm.loader = 0;	bprm.exec = 0;	if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {		allow_write_access(file);		fput(file);		return bprm.argc;	}	if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {		allow_write_access(file);		fput(file);		return bprm.envc;	}	retval = prepare_binprm(&bprm);	if (retval < 0)		goto out;		retval = copy_strings_kernel(1, &bprm.filename, &bprm);	if (retval < 0)		goto out;	bprm.exec = bprm.p;	retval = copy_strings32(bprm.envc, envp, &bprm);	if (retval < 0)		goto out;	retval = copy_strings32(bprm.argc, argv, &bprm);	if (retval < 0)		goto out;	retval = search_binary_handler(&bprm,regs);	if (retval >= 0)		/* execve success */		return retval;out:	/* Something went wrong, return the inode and free the argument pages*/	allow_write_access(bprm.file);	if (bprm.file)		fput(bprm.file);	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {		struct page * page = bprm.page[i];		if (page)			__free_page(page);	}	return retval;}/* * sys32_execve() executes a new program. */asmlinkage int sys32_execve(struct pt_regs *regs){	int error;	char *filename;	DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));	filename = getname((char *) regs->gr[26]);	error = PTR_ERR(filename);	if (IS_ERR(filename))		goto out;	error = do_execve32(filename, (u32 *) regs->gr[25],		(u32 *) regs->gr[24], regs);	if (error == 0)		current->ptrace &= ~PT_DTRACE;	putname(filename);out:	return error;}asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,	int r22, int r21, int r20){    printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n",     	current->comm, current->pid, r20);    return -ENOSYS;}/* 32-bit user apps use struct statfs which uses 'long's */struct statfs32 {	__s32 f_type;	__s32 f_bsize;	__s32 f_blocks;	__s32 f_bfree;	__s32 f_bavail;	__s32 f_files;	__s32 f_ffree;	__kernel_fsid_t f_fsid;	__s32 f_namelen;	__s32 f_spare[6];};/* convert statfs struct to statfs32 struct and copy result to user */static unsigned long statfs32_to_user(struct statfs32 *ust32, struct statfs *st){    struct statfs32 st32;#undef CP#define CP(a) st32.a = st->a    CP(f_type);    CP(f_bsize);    CP(f_blocks);    CP(f_bfree);    CP(f_bavail);    CP(f_files);    CP(f_ffree);    CP(f_fsid);    CP(f_namelen);    return copy_to_user(ust32, &st32, sizeof st32);}/* The following statfs calls are copies of code from linux/fs/open.c and * should be checked against those from time to time */asmlinkage long sys32_statfs(const char * path, struct statfs32 * buf){	struct nameidata nd;	int error;	error = user_path_walk(path, &nd);	if (!error) {		struct statfs tmp;		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);		if (!error && statfs32_to_user(buf, &tmp))			error = -EFAULT;		path_release(&nd);	}	return error;}asmlinkage long sys32_fstatfs(unsigned int fd, struct statfs32 * buf){	struct file * file;	struct statfs tmp;	int error;	error = -EBADF;	file = fget(fd);	if (!file)		goto out;	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);	if (!error && statfs32_to_user(buf, &tmp))		error = -EFAULT;	fput(file);out:	return error;}/* These may not work without my local types changes, but I wanted the * code available in case it's useful to others. -PB *//* from utime.h */struct utimbuf32 {	__kernel_time_t32 actime;	__kernel_time_t32 modtime;};asmlinkage long sys32_utime(char *filename, struct utimbuf32 *times){    struct utimbuf32 times32;    struct utimbuf times64;    extern long sys_utime(char *filename, struct utimbuf *times);    char *fname;    long ret;    if (!times)    	return sys_utime(filename, NULL);    /* get the 32-bit struct from user space */    if (copy_from_user(&times32, times, sizeof times32))    	return -EFAULT;    /* convert it into the 64-bit one */    times64.actime = times32.actime;    times64.modtime = times32.modtime;    /* grab the file name */    fname = getname(filename);    KERNEL_SYSCALL(ret, sys_utime, fname, &times64);    /* free the file name */    putname(fname);    return ret;}struct tms32 {	__kernel_clock_t32 tms_utime;	__kernel_clock_t32 tms_stime;	__kernel_clock_t32 tms_cutime;	__kernel_clock_t32 tms_cstime;};                                asmlinkage long sys32_times(struct tms32 *tbuf){	struct tms t;	long ret;	extern asmlinkage long sys_times(struct tms * tbuf);int err;		KERNEL_SYSCALL(ret, sys_times, tbuf ? &t : NULL);	if (tbuf) {		err = put_user (t.tms_utime, &tbuf->tms_utime);		err |= __put_user (t.tms_stime, &tbuf->tms_stime);		err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);		err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);		if (err)			ret = -EFAULT;	}	return ret;}struct flock32 {	short l_type;	short l_whence;	__kernel_off_t32 l_start;	__kernel_off_t32 l_len;	__kernel_pid_t32 l_pid;};static inline int get_flock(struct flock *kfl, struct flock32 *ufl){	int err;		err = get_user(kfl->l_type, &ufl->l_type);	err |= __get_user(kfl->l_whence, &ufl->l_whence);	err |= __get_user(kfl->l_start, &ufl->l_start);	err |= __get_user(kfl->l_len, &ufl->l_len);	err |= __get_user(kfl->l_pid, &ufl->l_pid);	return err;}static inline int put_flock(struct flock *kfl, struct flock32 *ufl){	int err;		err = __put_user(kfl->l_type, &ufl->l_type);	err |= __put_user(kfl->l_whence, &ufl->l_whence);	err |= __put_user(kfl->l_start, &ufl->l_start);	err |= __put_user(kfl->l_len, &ufl->l_len);	err |= __put_user(kfl->l_pid, &ufl->l_pid);	return err;}extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg){	switch (cmd) {	case F_GETLK:	case F_SETLK:	case F_SETLKW:		{			struct flock f;			long ret;						if(get_flock(&f, (struct flock32 *)arg))				return -EFAULT;			KERNEL_SYSCALL(ret, sys_fcntl, fd, cmd, (unsigned long)&f);			if (ret) return ret;			if (f.l_start >= 0x7fffffffUL ||			    f.l_len >= 0x7fffffffUL ||			    f.l_start + f.l_len >= 0x7fffffffUL)				return -EOVERFLOW;			if(put_flock(&f, (struct flock32 *)arg))				return -EFAULT;			return 0;		}	default:		return sys_fcntl(fd, cmd, (unsigned long)arg);	}}#ifdef CONFIG_SYSCTLstruct __sysctl_args32 {	u32 name;	int nlen;	u32 oldval;	u32 oldlenp;	u32 newval;	u32 newlen;	u32 __unused[4];};asmlinkage long sys32_sysctl(struct __sysctl_args32 *args){	struct __sysctl_args32 tmp;	int error;	unsigned int oldlen32;	size_t oldlen, *oldlenp = NULL;	unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;	extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,	       void *newval, size_t newlen);	DBG(("sysctl32(%p)\n", args));	if (copy_from_user(&tmp, args, sizeof(tmp)))		return -EFAULT;	if (tmp.oldval && tmp.oldlenp) {		/* Duh, this is ugly and might not work if sysctl_args		   is in read-only memory, but do_sysctl does indirectly		   a lot of uaccess in both directions and we'd have to		   basically copy the whole sysctl.c here, and		   glibc's __sysctl uses rw memory for the structure		   anyway.  */		/* a possibly better hack than this, which will avoid the		 * problem if the struct is read only, is to push the		 * 'oldlen' value out to the user's stack instead. -PB		 */		if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp))			return -EFAULT;		oldlen = oldlen32;		if (put_user(oldlen, (size_t *)addr))			return -EFAULT;		oldlenp = (size_t *)addr;	}	lock_kernel();	error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval,			  oldlenp, (void *)(u64)tmp.newval, tmp.newlen);	unlock_kernel();	if (oldlenp) {		if (!error) {			if (get_user(oldlen, (size_t *)addr)) {				error = -EFAULT;			} else {				oldlen32 = oldlen;				if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp))					error = -EFAULT;			}		}		if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))			error = -EFAULT;	}	return error;}#else /* CONFIG_SYSCTL */asmlinkage long sys32_sysctl(struct __sysctl_args *args){	return -ENOSYS;}#endif /* CONFIG_SYSCTL */struct timespec32 {	s32    tv_sec;	s32    tv_nsec;};                static intput_timespec32(struct timespec32 *u, struct timespec *t){	struct timespec32 t32;	t32.tv_sec = t->tv_sec;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -