Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fd08c55 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
  NFS: NFSv4 readdir loses entries
  NFS: Micro-optimize nfs4_decode_dirent()
  NFS: Fix an NFS client lockdep issue
  NFS construct consistent co_ownerid for v4.1
  NFS: nfs_wcc_update_inode() should set nfsi->attr_gencount
  NFS improve pnfs_put_deviceid_cache debug print
  NFS fix cb_sequence error processing
  NFS do not find client in NFSv4 pg_authenticate
  NLM: Fix "kernel BUG at fs/lockd/host.c:417!" or ".../host.c:283!"
  NFS: Prevent memory allocation failure in nfsacl_encode()
  NFS: nfsacl_{encode,decode} should return signed integer
  NFS: Fix "kernel BUG at fs/nfs/nfs3xdr.c:1338!"
  NFS: Fix "kernel BUG at fs/aio.c:554!"
  NFS4: Avoid potential NULL pointer dereference in decode_and_add_ds().
  NFS: fix handling of malloc failure during nfs_flush_multi()
parents 7921127e d1205f87
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -520,7 +520,7 @@ static struct nlm_host *next_host_state(struct hlist_head *cache,
					struct nsm_handle *nsm,
					const struct nlm_reboot *info)
{
	struct nlm_host *host = NULL;
	struct nlm_host *host;
	struct hlist_head *chain;
	struct hlist_node *pos;

@@ -532,12 +532,13 @@ static struct nlm_host *next_host_state(struct hlist_head *cache,
			host->h_state++;

			nlm_get_host(host);
			goto out;
			mutex_unlock(&nlm_host_mutex);
			return host;
		}
	}
out:

	mutex_unlock(&nlm_host_mutex);
	return host;
	return NULL;
}

/**
+29 −80
Original line number Diff line number Diff line
@@ -134,33 +134,6 @@ out_err:
}

#if defined(CONFIG_NFS_V4_1)
/*
 *  * CB_SEQUENCE operations will fail until the callback sessionid is set.
 *   */
int nfs4_set_callback_sessionid(struct nfs_client *clp)
{
	struct svc_serv *serv = clp->cl_rpcclient->cl_xprt->bc_serv;
	struct nfs4_sessionid *bc_sid;

	if (!serv->sv_bc_xprt)
		return -EINVAL;

	/* on success freed in xprt_free */
	bc_sid = kmalloc(sizeof(struct nfs4_sessionid), GFP_KERNEL);
	if (!bc_sid)
		return -ENOMEM;
	memcpy(bc_sid->data, &clp->cl_session->sess_id.data,
		NFS4_MAX_SESSIONID_LEN);
	spin_lock_bh(&serv->sv_cb_lock);
	serv->sv_bc_xprt->xpt_bc_sid = bc_sid;
	spin_unlock_bh(&serv->sv_cb_lock);
	dprintk("%s set xpt_bc_sid=%u:%u:%u:%u for sv_bc_xprt %p\n", __func__,
		((u32 *)bc_sid->data)[0], ((u32 *)bc_sid->data)[1],
		((u32 *)bc_sid->data)[2], ((u32 *)bc_sid->data)[3],
		serv->sv_bc_xprt);
	return 0;
}

/*
 * The callback service for NFSv4.1 callbacks
 */
@@ -266,10 +239,6 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
		struct nfs_callback_data *cb_info)
{
}
int nfs4_set_callback_sessionid(struct nfs_client *clp)
{
	return 0;
}
#endif /* CONFIG_NFS_V4_1 */

/*
@@ -359,78 +328,58 @@ void nfs_callback_down(int minorversion)
	mutex_unlock(&nfs_callback_mutex);
}

static int check_gss_callback_principal(struct nfs_client *clp,
					struct svc_rqst *rqstp)
/* Boolean check of RPC_AUTH_GSS principal */
int
check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
{
	struct rpc_clnt *r = clp->cl_rpcclient;
	char *p = svc_gss_principal(rqstp);

	if (rqstp->rq_authop->flavour != RPC_AUTH_GSS)
		return 1;

	/* No RPC_AUTH_GSS on NFSv4.1 back channel yet */
	if (clp->cl_minorversion != 0)
		return SVC_DROP;
		return 0;
	/*
	 * It might just be a normal user principal, in which case
	 * userspace won't bother to tell us the name at all.
	 */
	if (p == NULL)
		return SVC_DENIED;
		return 0;

	/* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */

	if (memcmp(p, "nfs@", 4) != 0)
		return SVC_DENIED;
		return 0;
	p += 4;
	if (strcmp(p, r->cl_server) != 0)
		return SVC_DENIED;
	return SVC_OK;
}

/* pg_authenticate method helper */
static struct nfs_client *nfs_cb_find_client(struct svc_rqst *rqstp)
{
	struct nfs4_sessionid *sessionid = bc_xprt_sid(rqstp);
	int is_cb_compound = rqstp->rq_proc == CB_COMPOUND ? 1 : 0;

	dprintk("--> %s rq_proc %d\n", __func__, rqstp->rq_proc);
	if (svc_is_backchannel(rqstp))
		/* Sessionid (usually) set after CB_NULL ping */
		return nfs4_find_client_sessionid(svc_addr(rqstp), sessionid,
						  is_cb_compound);
	else
		/* No callback identifier in pg_authenticate */
		return nfs4_find_client_no_ident(svc_addr(rqstp));
		return 0;
	return 1;
}

/* pg_authenticate method for nfsv4 callback threads. */
/*
 * pg_authenticate method for nfsv4 callback threads.
 *
 * The authflavor has been negotiated, so an incorrect flavor is a server
 * bug. Drop packets with incorrect authflavor.
 *
 * All other checking done after NFS decoding where the nfs_client can be
 * found in nfs4_callback_compound
 */
static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
	struct nfs_client *clp;
	RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
	int ret = SVC_OK;

	/* Don't talk to strangers */
	clp = nfs_cb_find_client(rqstp);
	if (clp == NULL)
		return SVC_DROP;

	dprintk("%s: %s NFSv4 callback!\n", __func__,
			svc_print_addr(rqstp, buf, sizeof(buf)));

	switch (rqstp->rq_authop->flavour) {
	case RPC_AUTH_NULL:
		if (rqstp->rq_proc != CB_NULL)
				ret = SVC_DENIED;
			break;
		case RPC_AUTH_UNIX:
			return SVC_DROP;
		break;
	case RPC_AUTH_GSS:
			ret = check_gss_callback_principal(clp, rqstp);
			break;
		default:
			ret = SVC_DENIED;
		/* No RPC_AUTH_GSS support yet in NFSv4.1 */
		 if (svc_is_backchannel(rqstp))
			return SVC_DROP;
	}
	nfs_put_client(clp);
	return ret;
	return SVC_OK;
}

/*
+2 −2
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 */
#ifndef __LINUX_FS_NFS_CALLBACK_H
#define __LINUX_FS_NFS_CALLBACK_H
#include <linux/sunrpc/svc.h>

#define NFS4_CALLBACK 0x40000000
#define NFS4_CALLBACK_XDRSIZE 2048
@@ -37,7 +38,6 @@ enum nfs4_callback_opnum {
struct cb_process_state {
	__be32			drc_status;
	struct nfs_client	*clp;
	struct nfs4_sessionid	*svc_sid; /* v4.1 callback service sessionid */
};

struct cb_compound_hdr_arg {
@@ -168,7 +168,7 @@ extern unsigned nfs4_callback_layoutrecall(
extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses);
extern void nfs4_cb_take_slot(struct nfs_client *clp);
#endif /* CONFIG_NFS_V4_1 */

extern int check_gss_callback_principal(struct nfs_client *, struct svc_rqst *);
extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args,
				    struct cb_getattrres *res,
				    struct cb_process_state *cps);
+3 −9
Original line number Diff line number Diff line
@@ -373,17 +373,11 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
{
	struct nfs_client *clp;
	int i;
	__be32 status;
	__be32 status = htonl(NFS4ERR_BADSESSION);

	cps->clp = NULL;

	status = htonl(NFS4ERR_BADSESSION);
	/* Incoming session must match the callback session */
	if (memcmp(&args->csa_sessionid, cps->svc_sid, NFS4_MAX_SESSIONID_LEN))
		goto out;

	clp = nfs4_find_client_sessionid(args->csa_addr,
					 &args->csa_sessionid, 1);
	clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid);
	if (clp == NULL)
		goto out;

@@ -414,9 +408,9 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
	res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
	res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
	nfs4_cb_take_slot(clp);
	cps->clp = clp; /* put in nfs4_callback_compound */

out:
	cps->clp = clp; /* put in nfs4_callback_compound */
	for (i = 0; i < args->csa_nrclists; i++)
		kfree(args->csa_rclists[i].rcl_refcalls);
	kfree(args->csa_rclists);
+2 −3
Original line number Diff line number Diff line
@@ -794,10 +794,9 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r

	if (hdr_arg.minorversion == 0) {
		cps.clp = nfs4_find_client_ident(hdr_arg.cb_ident);
		if (!cps.clp)
		if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp))
			return rpc_drop_reply;
	} else
		cps.svc_sid = bc_xprt_sid(rqstp);
	}

	hdr_res.taglen = hdr_arg.taglen;
	hdr_res.tag = hdr_arg.tag;
Loading