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

Commit 95b72eb0 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4: Ensure we do not reuse open owner names



The NFSv4 spec is ambiguous about whether or not it is permissible
to reuse open owner names, so play it safe. This patch adds a timestamp
to the state_owner structure, and combines that with the IDA based
uniquifier.
Fixes a regression whereby the Linux server returns NFS4ERR_BAD_SEQID.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 98a2139f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ struct nfs_unique_id {

#define NFS_SEQID_CONFIRMED 1
struct nfs_seqid_counter {
	ktime_t create_time;
	int owner_id;
	int flags;
	u32 counter;
+3 −3
Original line number Diff line number Diff line
@@ -838,7 +838,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
	p->o_arg.open_flags = flags;
	p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
	p->o_arg.clientid = server->nfs_client->cl_clientid;
	p->o_arg.id = sp->so_seqid.owner_id;
	p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
	p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
	p->o_arg.name = &dentry->d_name;
	p->o_arg.server = server;
	p->o_arg.bitmask = server->attr_bitmask;
@@ -1466,8 +1467,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
			goto unlock_no_action;
		rcu_read_unlock();
	}
	/* Update sequence id. */
	data->o_arg.id = sp->so_seqid.owner_id;
	/* Update client id. */
	data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
	if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
+1 −0
Original line number Diff line number Diff line
@@ -393,6 +393,7 @@ nfs4_remove_state_owner_locked(struct nfs4_state_owner *sp)
static void
nfs4_init_seqid_counter(struct nfs_seqid_counter *sc)
{
	sc->create_time = ktime_get();
	sc->flags = 0;
	sc->counter = 0;
	spin_lock_init(&sc->lock);
+5 −4
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ static int nfs4_stat_to_errno(int);
/* lock,open owner id:
 * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT  >> 2)
 */
#define open_owner_id_maxsz	(1 + 1 + 4)
#define open_owner_id_maxsz	(1 + 2 + 1 + 1 + 2)
#define lock_owner_id_maxsz	(1 + 1 + 4)
#define decode_lockowner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
#define compound_encode_hdr_maxsz	(3 + (NFS4_MAXTAGLEN >> 2))
@@ -1340,12 +1340,13 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
 */
	encode_nfs4_seqid(xdr, arg->seqid);
	encode_share_access(xdr, arg->fmode);
	p = reserve_space(xdr, 32);
	p = reserve_space(xdr, 36);
	p = xdr_encode_hyper(p, arg->clientid);
	*p++ = cpu_to_be32(20);
	*p++ = cpu_to_be32(24);
	p = xdr_encode_opaque_fixed(p, "open id:", 8);
	*p++ = cpu_to_be32(arg->server->s_dev);
	xdr_encode_hyper(p, arg->id);
	*p++ = cpu_to_be32(arg->id.uniquifier);
	xdr_encode_hyper(p, arg->id.create_time);
}

static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+6 −1
Original line number Diff line number Diff line
@@ -312,6 +312,11 @@ struct nfs4_layoutreturn {
	int rpc_status;
};

struct stateowner_id {
	__u64	create_time;
	__u32	uniquifier;
};

/*
 * Arguments to the open call.
 */
@@ -321,7 +326,7 @@ struct nfs_openargs {
	int			open_flags;
	fmode_t			fmode;
	__u64                   clientid;
	__u64                   id;
	struct stateowner_id	id;
	union {
		struct {
			struct iattr *  attrs;    /* UNCHECKED, GUARDED */