Esempio n. 1
0
asmlinkage long sys_chroot(const char __user * filename)
{
	struct nameidata nd;
	struct fs_struct *fs;
	int error;

	error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
	if (error)
		goto out;

	error = vfs_permission(d_get_inode_ro(nd.dentry), &nd, MAY_EXEC);
	if (error)
		goto dput_and_out;

	error = -EPERM;
	if (!capable(CAP_SYS_CHROOT))
		goto dput_and_out;

	fs = tx_cache_get_fs(current);

	set_fs_root(fs, nd.mnt, parent(nd.dentry));
	set_fs_altroot();
	error = 0;
dput_and_out:
	path_release(&nd);
out:
	return error;
}
Esempio n. 2
0
/*
 * Note that a shared library must be both readable and executable due to
 * security reasons.
 *
 * Also note that we take the address to load from from the file itself.
 */
asmlinkage long sys_uselib(const char __user * library)
{
	struct file * file;
	struct nameidata nd;
	const struct _inode *inode;
	int error;

	error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
	if (error)
		goto out;

	error = -EACCES;
	if (nd.mnt->mnt_flags & MNT_NOEXEC)
		goto exit;
	error = -EINVAL;
	inode = d_get_inode_ro(nd.dentry);
	if (!S_ISREG(inode->i_mode))
		goto exit;

	error = vfs_permission(inode, &nd, MAY_READ | MAY_EXEC);
	if (error)
		goto exit;

	file = nameidata_to_filp(&nd, O_RDONLY);
	error = PTR_ERR(file);
	if (IS_ERR(file))
		goto out;

	error = -ENOEXEC;
	if(file->f_op) {
		struct linux_binfmt * fmt;

		read_lock(&binfmt_lock);
		for (fmt = formats ; fmt ; fmt = fmt->next) {
			if (!fmt->load_shlib)
				continue;
			if (!try_module_get(fmt->module))
				continue;
			read_unlock(&binfmt_lock);
			error = fmt->load_shlib(file);
			read_lock(&binfmt_lock);
			put_binfmt(fmt);
			if (error != -ENOEXEC)
				break;
		}
		read_unlock(&binfmt_lock);
	}
	fput(file);
out:
  	return error;
exit:
	release_open_intent(&nd);
	path_release(&nd);
	goto out;
}
Esempio n. 3
0
/*
 * access() needs to use the real uid/gid, not the effective uid/gid.
 * We do this by temporarily clearing all FS-related capabilities and
 * switching the fsuid/fsgid around to the real ones.
 */
asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
{
	struct nameidata nd;
	int old_fsuid, old_fsgid;
	kernel_cap_t old_cap;
	int res;
	const struct _inode *inode;

	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
		return -EINVAL;

	old_fsuid = current->fsuid;
	old_fsgid = current->fsgid;
	old_cap = current->cap_effective;

	current->fsuid = current->uid;
	current->fsgid = current->gid;

	/*
	 * Clear the capabilities if we switch to a non-root user
	 *
	 * FIXME: There is a race here against sys_capset.  The
	 * capabilities can change yet we will restore the old
	 * value below.  We should hold task_capabilities_lock,
	 * but we cannot because user_path_walk can sleep.
	 */
	if (current->uid)
		cap_clear(current->cap_effective);
	else
		current->cap_effective = current->cap_permitted;
	
	res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
	if (res)
		goto out;

	inode = d_get_inode_ro(nd.dentry);
	res = vfs_permission(inode, &nd, mode);
	/* SuS v2 requires we report a read only fs too */
	if(res || !(mode & S_IWOTH) ||
	   special_file(inode->i_mode))
		goto out_path_release;

	if(IS_RDONLY(inode))
		res = -EROFS;

out_path_release:
	path_release(&nd);
out:
	current->fsuid = old_fsuid;
	current->fsgid = old_fsgid;
	current->cap_effective = old_cap;
	
	return res;
}
Esempio n. 4
0
asmlinkage long sys_chdir(const char __user * filename)
{
	struct nameidata nd;
	int error;
	struct fs_struct *fs;

	error = __user_walk(filename,
			    LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd);
	if (error)
		goto out;

	error = vfs_permission(d_get_inode_ro(nd.dentry), &nd, MAY_EXEC);
	if (error)
		goto dput_and_out;
	
	fs = tx_cache_get_fs(current);
	
	set_fs_pwd(fs, nd.mnt, parent(nd.dentry));

dput_and_out:
	path_release(&nd);
out:
	return error;
}
Esempio n. 5
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg)
{
	unsigned int flag;
	int on, error = 0;
	umode_t mode;
	
	struct _file *_filp = tx_cache_get_file(filp);
	/* Patch up ioctl for bad tx cases*/
	if((!_filp) || !_filp->f_dentry ){
#ifdef CONFIG_TX_KSTM_WARNINGS
		printk(KERN_ERR "Fixing up ioctl\n");
#endif
		return 0;
	}
	mode = d_get_inode_ro(f_get_dentry(_filp))->i_mode;

	switch (cmd) {
		case FIOCLEX:
			set_close_on_exec(fd, 1);
			break;

		case FIONCLEX:
			set_close_on_exec(fd, 0);
			break;

		case FIONBIO:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = O_NONBLOCK;
#ifdef __sparc__
			/* SunOS compatibility item. */
			if(O_NONBLOCK != O_NDELAY)
				flag |= O_NDELAY;
#endif
			if (on)
				_filp->f_flags |= flag;
			else
				_filp->f_flags &= ~flag;
			break;

		case FIOASYNC:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = on ? FASYNC : 0;

			/* Did FASYNC state change ? */
			if ((flag ^ _filp->f_flags) & FASYNC) {
				if (filp->f_op && filp->f_op->fasync) {
					lock_kernel();
					error = filp->f_op->fasync(fd, filp, on);
					unlock_kernel();
				}
				else error = -ENOTTY;
			}
			if (error != 0)
				break;

			if (on)
				_filp->f_flags |= FASYNC;
			else
				_filp->f_flags &= ~FASYNC;
			break;

		case FIOQSIZE:
			if (S_ISDIR(mode) ||
			    S_ISREG(mode) ||
			    S_ISLNK(mode)) {
				loff_t res = inode_get_bytes(f_get_dentry(_filp)->d_inode);
				error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
			}
			else
				error = -ENOTTY;
			break;
		default:
			if(live_transaction()){
				/* Short circuit this stupid ioctl */
				if(cmd == TIOCGWINSZ){
#ifdef CONFIG_TX_KSTM_WARNINGS
					printk(KERN_ERR "Warning: some bozo wants to know the terminal width in a transaction.\n");
#endif
					error = -EINVAL;
					break;
				} else if(cmd != TCGETS)
					BUG();
			}

			if (S_ISREG(mode))
				error = file_ioctl(filp, cmd, arg);
			else
				error = do_ioctl(filp, cmd, arg);
			break;
	}
	return error;
}