Beispiel #1
0
/*
 * New rpc_call implementation
 */
int
rpc_do_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
				int flags, rpc_action func, void *data)
{
	struct rpc_task	my_task, *task = &my_task;
	sigset_t	oldset;
	int		async, status;

	/* If this client is slain all further I/O fails */
	if (clnt->cl_dead) 
		return -EIO;

	rpc_clnt_sigmask(clnt, &oldset);		

	/* Create/initialize a new RPC task */
	if ((async = (flags & RPC_TASK_ASYNC)) != 0) {
		if (!func)
			func = rpc_default_callback;
		status = -ENOMEM;
		if (!(task = rpc_new_task(clnt, func, flags)))
			goto out;
		task->tk_calldata = data;
	} else {
		rpc_init_task(task, clnt, NULL, flags);
	}

	/* Bind the user cred, set up the call info struct and
	 * execute the task */
	if (rpcauth_lookupcred(task) != NULL) {
		rpc_call_setup(task, proc, argp, resp, 0);
		rpc_execute(task);
	} else
		async = 0;

	status = 0;
	if (!async) {
		status = task->tk_status;
		rpc_release_task(task);
	}

out:
	rpc_clnt_sigunmask(clnt, &oldset);		

	return status;
}
int
nfs_permission(struct inode *inode, int mask)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
	struct rpc_cred *cred;
	int mode = inode->i_mode;
	int error;

	if (mask & MAY_WRITE) {
		/*
		 *
		 * Nobody gets write access to a read-only fs.
		 *
		 */
		if (IS_RDONLY(inode) &&
		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
			return -EROFS;

		/*
		 *
		 * Nobody gets write access to an immutable file.
		 *
		 */
		if (IS_IMMUTABLE(inode))
			return -EACCES;
	}

	if ((server->flags & NFS_MOUNT_NOACL) || !NFS_PROTO(inode)->access)
		goto out_notsup;
	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
	if (cache->cred == cred
	    && time_before(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) {
		if (!cache->err) {
			/* Is the mask a subset of an accepted mask? */
			if ((cache->mask & mask) == mask)
				goto out_cached;
	       	} else {
			/* ...or is it a superset of a rejected mask? */
			if ((cache->mask & mask) == cache->mask)
				goto out_cached;
		}
	}
	error = NFS_PROTO(inode)->access(inode, cred, mask);
	if (!error || error == -EACCES) {
		cache->jiffies = jiffies;
		if (cache->cred)
			put_rpccred(cache->cred);
		cache->cred = cred;
		cache->mask = mask;
		cache->err = error;
		return error;
	}
	put_rpccred(cred);
out_notsup:
	nfs_revalidate_inode(NFS_SERVER(inode), inode);
	return vfs_permission(inode, mask);
out_cached:
	put_rpccred(cred);
	return cache->err;
}
Beispiel #3
0
struct rpc_cred *rpc_lookup_cred_nonblock(void)
{
	return rpcauth_lookupcred(&generic_auth, RPCAUTH_LOOKUP_RCU);
}
struct rpc_cred *rpc_lookup_cred(void)
{
	return rpcauth_lookupcred(&generic_auth, 0);
}
int
nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
{
	struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
	struct rpc_cred *cred;
	int mode = inode->i_mode;
	int res;

	if (mask == 0)
		return 0;
	if (mask & MAY_WRITE) {
		/*
		 *
		 * Nobody gets write access to a read-only fs.
		 *
		 */
		if (IS_RDONLY(inode) &&
		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
			return -EROFS;

		/*
		 *
		 * Nobody gets write access to an immutable file.
		 *
		 */
		if (IS_IMMUTABLE(inode))
			return -EACCES;
	}
	/* Are we checking permissions on anything other than lookup/execute? */
	if ((mask & MAY_EXEC) == 0) {
		/* We only need to check permissions on file open() and access() */
		if (!nd || !(nd->flags & (LOOKUP_OPEN|LOOKUP_ACCESS)))
			return 0;
		/* NFSv4 has atomic_open... */
		if (NFS_PROTO(inode)->version > 3 && (nd->flags & LOOKUP_OPEN))
			return 0;
	}

	lock_kernel();

	if (!NFS_PROTO(inode)->access)
		goto out_notsup;

	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
	if (cache->cred == cred
	    && time_before(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))
	    && !(NFS_FLAGS(inode) & NFS_INO_INVALID_ATTR)) {
		if (!(res = cache->err)) {
			/* Is the mask a subset of an accepted mask? */
			if ((cache->mask & mask) == mask)
				goto out;
		} else {
			/* ...or is it a superset of a rejected mask? */
			if ((cache->mask & mask) == cache->mask)
				goto out;
		}
	}

	res = NFS_PROTO(inode)->access(inode, cred, mask);
	if (!res || res == -EACCES)
		goto add_cache;
out:
	put_rpccred(cred);
	unlock_kernel();
	return res;
out_notsup:
	nfs_revalidate_inode(NFS_SERVER(inode), inode);
	res = vfs_permission(inode, mask);
	unlock_kernel();
	return res;
add_cache:
	cache->jiffies = jiffies;
	if (cache->cred)
		put_rpccred(cache->cred);
	cache->cred = cred;
	cache->mask = mask;
	cache->err = res;
	unlock_kernel();
	return res;
}