cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clnt4xdr.c (13162B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * linux/fs/lockd/clnt4xdr.c
      4 *
      5 * XDR functions to encode/decode NLM version 4 RPC arguments and results.
      6 *
      7 * NLM client-side only.
      8 *
      9 * Copyright (C) 2010, Oracle.  All rights reserved.
     10 */
     11
     12#include <linux/types.h>
     13#include <linux/sunrpc/xdr.h>
     14#include <linux/sunrpc/clnt.h>
     15#include <linux/sunrpc/stats.h>
     16#include <linux/lockd/lockd.h>
     17
     18#include <uapi/linux/nfs3.h>
     19
     20#define NLMDBG_FACILITY		NLMDBG_XDR
     21
     22#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
     23#  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
     24#endif
     25
     26#if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN)
     27#  error "NLM host name cannot be larger than NLM's maximum string length!"
     28#endif
     29
     30/*
     31 * Declare the space requirements for NLM arguments and replies as
     32 * number of 32bit-words
     33 */
     34#define NLM4_void_sz		(0)
     35#define NLM4_cookie_sz		(1+(NLM_MAXCOOKIELEN>>2))
     36#define NLM4_caller_sz		(1+(NLMCLNT_OHSIZE>>2))
     37#define NLM4_owner_sz		(1+(NLMCLNT_OHSIZE>>2))
     38#define NLM4_fhandle_sz		(1+(NFS3_FHSIZE>>2))
     39#define NLM4_lock_sz		(5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz)
     40#define NLM4_holder_sz		(6+NLM4_owner_sz)
     41
     42#define NLM4_testargs_sz	(NLM4_cookie_sz+1+NLM4_lock_sz)
     43#define NLM4_lockargs_sz	(NLM4_cookie_sz+4+NLM4_lock_sz)
     44#define NLM4_cancargs_sz	(NLM4_cookie_sz+2+NLM4_lock_sz)
     45#define NLM4_unlockargs_sz	(NLM4_cookie_sz+NLM4_lock_sz)
     46
     47#define NLM4_testres_sz		(NLM4_cookie_sz+1+NLM4_holder_sz)
     48#define NLM4_res_sz		(NLM4_cookie_sz+1)
     49#define NLM4_norep_sz		(0)
     50
     51
     52static s64 loff_t_to_s64(loff_t offset)
     53{
     54	s64 res;
     55
     56	if (offset >= NLM4_OFFSET_MAX)
     57		res = NLM4_OFFSET_MAX;
     58	else if (offset <= -NLM4_OFFSET_MAX)
     59		res = -NLM4_OFFSET_MAX;
     60	else
     61		res = offset;
     62	return res;
     63}
     64
     65static void nlm4_compute_offsets(const struct nlm_lock *lock,
     66				 u64 *l_offset, u64 *l_len)
     67{
     68	const struct file_lock *fl = &lock->fl;
     69
     70	*l_offset = loff_t_to_s64(fl->fl_start);
     71	if (fl->fl_end == OFFSET_MAX)
     72		*l_len = 0;
     73	else
     74		*l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
     75}
     76
     77/*
     78 * Encode/decode NLMv4 basic data types
     79 *
     80 * Basic NLMv4 data types are defined in Appendix II, section 6.1.4
     81 * of RFC 1813: "NFS Version 3 Protocol Specification" and in Chapter
     82 * 10 of X/Open's "Protocols for Interworking: XNFS, Version 3W".
     83 *
     84 * Not all basic data types have their own encoding and decoding
     85 * functions.  For run-time efficiency, some data types are encoded
     86 * or decoded inline.
     87 */
     88
     89static void encode_bool(struct xdr_stream *xdr, const int value)
     90{
     91	__be32 *p;
     92
     93	p = xdr_reserve_space(xdr, 4);
     94	*p = value ? xdr_one : xdr_zero;
     95}
     96
     97static void encode_int32(struct xdr_stream *xdr, const s32 value)
     98{
     99	__be32 *p;
    100
    101	p = xdr_reserve_space(xdr, 4);
    102	*p = cpu_to_be32(value);
    103}
    104
    105/*
    106 *	typedef opaque netobj<MAXNETOBJ_SZ>
    107 */
    108static void encode_netobj(struct xdr_stream *xdr,
    109			  const u8 *data, const unsigned int length)
    110{
    111	__be32 *p;
    112
    113	p = xdr_reserve_space(xdr, 4 + length);
    114	xdr_encode_opaque(p, data, length);
    115}
    116
    117static int decode_netobj(struct xdr_stream *xdr,
    118			 struct xdr_netobj *obj)
    119{
    120	ssize_t ret;
    121
    122	ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data,
    123						XDR_MAX_NETOBJ);
    124	if (unlikely(ret < 0))
    125		return -EIO;
    126	obj->len = ret;
    127	return 0;
    128}
    129
    130/*
    131 *	netobj cookie;
    132 */
    133static void encode_cookie(struct xdr_stream *xdr,
    134			  const struct nlm_cookie *cookie)
    135{
    136	encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
    137}
    138
    139static int decode_cookie(struct xdr_stream *xdr,
    140			     struct nlm_cookie *cookie)
    141{
    142	u32 length;
    143	__be32 *p;
    144
    145	p = xdr_inline_decode(xdr, 4);
    146	if (unlikely(p == NULL))
    147		goto out_overflow;
    148	length = be32_to_cpup(p++);
    149	/* apparently HPUX can return empty cookies */
    150	if (length == 0)
    151		goto out_hpux;
    152	if (length > NLM_MAXCOOKIELEN)
    153		goto out_size;
    154	p = xdr_inline_decode(xdr, length);
    155	if (unlikely(p == NULL))
    156		goto out_overflow;
    157	cookie->len = length;
    158	memcpy(cookie->data, p, length);
    159	return 0;
    160out_hpux:
    161	cookie->len = 4;
    162	memset(cookie->data, 0, 4);
    163	return 0;
    164out_size:
    165	dprintk("NFS: returned cookie was too long: %u\n", length);
    166	return -EIO;
    167out_overflow:
    168	return -EIO;
    169}
    170
    171/*
    172 *	netobj fh;
    173 */
    174static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
    175{
    176	encode_netobj(xdr, (u8 *)&fh->data, fh->size);
    177}
    178
    179/*
    180 *	enum nlm4_stats {
    181 *		NLM4_GRANTED = 0,
    182 *		NLM4_DENIED = 1,
    183 *		NLM4_DENIED_NOLOCKS = 2,
    184 *		NLM4_BLOCKED = 3,
    185 *		NLM4_DENIED_GRACE_PERIOD = 4,
    186 *		NLM4_DEADLCK = 5,
    187 *		NLM4_ROFS = 6,
    188 *		NLM4_STALE_FH = 7,
    189 *		NLM4_FBIG = 8,
    190 *		NLM4_FAILED = 9
    191 *	};
    192 *
    193 *	struct nlm4_stat {
    194 *		nlm4_stats stat;
    195 *	};
    196 *
    197 * NB: we don't swap bytes for the NLM status values.  The upper
    198 * layers deal directly with the status value in network byte
    199 * order.
    200 */
    201static void encode_nlm4_stat(struct xdr_stream *xdr,
    202			     const __be32 stat)
    203{
    204	__be32 *p;
    205
    206	BUG_ON(be32_to_cpu(stat) > NLM_FAILED);
    207	p = xdr_reserve_space(xdr, 4);
    208	*p = stat;
    209}
    210
    211static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat)
    212{
    213	__be32 *p;
    214
    215	p = xdr_inline_decode(xdr, 4);
    216	if (unlikely(p == NULL))
    217		goto out_overflow;
    218	if (unlikely(ntohl(*p) > ntohl(nlm4_failed)))
    219		goto out_bad_xdr;
    220	*stat = *p;
    221	return 0;
    222out_bad_xdr:
    223	dprintk("%s: server returned invalid nlm4_stats value: %u\n",
    224			__func__, be32_to_cpup(p));
    225	return -EIO;
    226out_overflow:
    227	return -EIO;
    228}
    229
    230/*
    231 *	struct nlm4_holder {
    232 *		bool	exclusive;
    233 *		int32	svid;
    234 *		netobj	oh;
    235 *		uint64	l_offset;
    236 *		uint64	l_len;
    237 *	};
    238 */
    239static void encode_nlm4_holder(struct xdr_stream *xdr,
    240			       const struct nlm_res *result)
    241{
    242	const struct nlm_lock *lock = &result->lock;
    243	u64 l_offset, l_len;
    244	__be32 *p;
    245
    246	encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
    247	encode_int32(xdr, lock->svid);
    248	encode_netobj(xdr, lock->oh.data, lock->oh.len);
    249
    250	p = xdr_reserve_space(xdr, 4 + 4);
    251	nlm4_compute_offsets(lock, &l_offset, &l_len);
    252	p = xdr_encode_hyper(p, l_offset);
    253	xdr_encode_hyper(p, l_len);
    254}
    255
    256static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
    257{
    258	struct nlm_lock *lock = &result->lock;
    259	struct file_lock *fl = &lock->fl;
    260	u64 l_offset, l_len;
    261	u32 exclusive;
    262	int error;
    263	__be32 *p;
    264	s32 end;
    265
    266	memset(lock, 0, sizeof(*lock));
    267	locks_init_lock(fl);
    268
    269	p = xdr_inline_decode(xdr, 4 + 4);
    270	if (unlikely(p == NULL))
    271		goto out_overflow;
    272	exclusive = be32_to_cpup(p++);
    273	lock->svid = be32_to_cpup(p);
    274	fl->fl_pid = (pid_t)lock->svid;
    275
    276	error = decode_netobj(xdr, &lock->oh);
    277	if (unlikely(error))
    278		goto out;
    279
    280	p = xdr_inline_decode(xdr, 8 + 8);
    281	if (unlikely(p == NULL))
    282		goto out_overflow;
    283
    284	fl->fl_flags = FL_POSIX;
    285	fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
    286	p = xdr_decode_hyper(p, &l_offset);
    287	xdr_decode_hyper(p, &l_len);
    288	end = l_offset + l_len - 1;
    289
    290	fl->fl_start = (loff_t)l_offset;
    291	if (l_len == 0 || end < 0)
    292		fl->fl_end = OFFSET_MAX;
    293	else
    294		fl->fl_end = (loff_t)end;
    295	error = 0;
    296out:
    297	return error;
    298out_overflow:
    299	return -EIO;
    300}
    301
    302/*
    303 *	string caller_name<LM_MAXSTRLEN>;
    304 */
    305static void encode_caller_name(struct xdr_stream *xdr, const char *name)
    306{
    307	/* NB: client-side does not set lock->len */
    308	u32 length = strlen(name);
    309	__be32 *p;
    310
    311	p = xdr_reserve_space(xdr, 4 + length);
    312	xdr_encode_opaque(p, name, length);
    313}
    314
    315/*
    316 *	struct nlm4_lock {
    317 *		string	caller_name<LM_MAXSTRLEN>;
    318 *		netobj	fh;
    319 *		netobj	oh;
    320 *		int32	svid;
    321 *		uint64	l_offset;
    322 *		uint64	l_len;
    323 *	};
    324 */
    325static void encode_nlm4_lock(struct xdr_stream *xdr,
    326			     const struct nlm_lock *lock)
    327{
    328	u64 l_offset, l_len;
    329	__be32 *p;
    330
    331	encode_caller_name(xdr, lock->caller);
    332	encode_fh(xdr, &lock->fh);
    333	encode_netobj(xdr, lock->oh.data, lock->oh.len);
    334
    335	p = xdr_reserve_space(xdr, 4 + 8 + 8);
    336	*p++ = cpu_to_be32(lock->svid);
    337
    338	nlm4_compute_offsets(lock, &l_offset, &l_len);
    339	p = xdr_encode_hyper(p, l_offset);
    340	xdr_encode_hyper(p, l_len);
    341}
    342
    343
    344/*
    345 * NLMv4 XDR encode functions
    346 *
    347 * NLMv4 argument types are defined in Appendix II of RFC 1813:
    348 * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's
    349 * "Protocols for Interworking: XNFS, Version 3W".
    350 */
    351
    352/*
    353 *	struct nlm4_testargs {
    354 *		netobj cookie;
    355 *		bool exclusive;
    356 *		struct nlm4_lock alock;
    357 *	};
    358 */
    359static void nlm4_xdr_enc_testargs(struct rpc_rqst *req,
    360				  struct xdr_stream *xdr,
    361				  const void *data)
    362{
    363	const struct nlm_args *args = data;
    364	const struct nlm_lock *lock = &args->lock;
    365
    366	encode_cookie(xdr, &args->cookie);
    367	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
    368	encode_nlm4_lock(xdr, lock);
    369}
    370
    371/*
    372 *	struct nlm4_lockargs {
    373 *		netobj cookie;
    374 *		bool block;
    375 *		bool exclusive;
    376 *		struct nlm4_lock alock;
    377 *		bool reclaim;
    378 *		int state;
    379 *	};
    380 */
    381static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req,
    382				  struct xdr_stream *xdr,
    383				  const void *data)
    384{
    385	const struct nlm_args *args = data;
    386	const struct nlm_lock *lock = &args->lock;
    387
    388	encode_cookie(xdr, &args->cookie);
    389	encode_bool(xdr, args->block);
    390	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
    391	encode_nlm4_lock(xdr, lock);
    392	encode_bool(xdr, args->reclaim);
    393	encode_int32(xdr, args->state);
    394}
    395
    396/*
    397 *	struct nlm4_cancargs {
    398 *		netobj cookie;
    399 *		bool block;
    400 *		bool exclusive;
    401 *		struct nlm4_lock alock;
    402 *	};
    403 */
    404static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req,
    405				  struct xdr_stream *xdr,
    406				  const void *data)
    407{
    408	const struct nlm_args *args = data;
    409	const struct nlm_lock *lock = &args->lock;
    410
    411	encode_cookie(xdr, &args->cookie);
    412	encode_bool(xdr, args->block);
    413	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
    414	encode_nlm4_lock(xdr, lock);
    415}
    416
    417/*
    418 *	struct nlm4_unlockargs {
    419 *		netobj cookie;
    420 *		struct nlm4_lock alock;
    421 *	};
    422 */
    423static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req,
    424				    struct xdr_stream *xdr,
    425				    const void *data)
    426{
    427	const struct nlm_args *args = data;
    428	const struct nlm_lock *lock = &args->lock;
    429
    430	encode_cookie(xdr, &args->cookie);
    431	encode_nlm4_lock(xdr, lock);
    432}
    433
    434/*
    435 *	struct nlm4_res {
    436 *		netobj cookie;
    437 *		nlm4_stat stat;
    438 *	};
    439 */
    440static void nlm4_xdr_enc_res(struct rpc_rqst *req,
    441			     struct xdr_stream *xdr,
    442			     const void *data)
    443{
    444	const struct nlm_res *result = data;
    445
    446	encode_cookie(xdr, &result->cookie);
    447	encode_nlm4_stat(xdr, result->status);
    448}
    449
    450/*
    451 *	union nlm4_testrply switch (nlm4_stats stat) {
    452 *	case NLM4_DENIED:
    453 *		struct nlm4_holder holder;
    454 *	default:
    455 *		void;
    456 *	};
    457 *
    458 *	struct nlm4_testres {
    459 *		netobj cookie;
    460 *		nlm4_testrply test_stat;
    461 *	};
    462 */
    463static void nlm4_xdr_enc_testres(struct rpc_rqst *req,
    464				 struct xdr_stream *xdr,
    465				 const void *data)
    466{
    467	const struct nlm_res *result = data;
    468
    469	encode_cookie(xdr, &result->cookie);
    470	encode_nlm4_stat(xdr, result->status);
    471	if (result->status == nlm_lck_denied)
    472		encode_nlm4_holder(xdr, result);
    473}
    474
    475
    476/*
    477 * NLMv4 XDR decode functions
    478 *
    479 * NLMv4 argument types are defined in Appendix II of RFC 1813:
    480 * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's
    481 * "Protocols for Interworking: XNFS, Version 3W".
    482 */
    483
    484/*
    485 *	union nlm4_testrply switch (nlm4_stats stat) {
    486 *	case NLM4_DENIED:
    487 *		struct nlm4_holder holder;
    488 *	default:
    489 *		void;
    490 *	};
    491 *
    492 *	struct nlm4_testres {
    493 *		netobj cookie;
    494 *		nlm4_testrply test_stat;
    495 *	};
    496 */
    497static int decode_nlm4_testrply(struct xdr_stream *xdr,
    498				struct nlm_res *result)
    499{
    500	int error;
    501
    502	error = decode_nlm4_stat(xdr, &result->status);
    503	if (unlikely(error))
    504		goto out;
    505	if (result->status == nlm_lck_denied)
    506		error = decode_nlm4_holder(xdr, result);
    507out:
    508	return error;
    509}
    510
    511static int nlm4_xdr_dec_testres(struct rpc_rqst *req,
    512				struct xdr_stream *xdr,
    513				void *data)
    514{
    515	struct nlm_res *result = data;
    516	int error;
    517
    518	error = decode_cookie(xdr, &result->cookie);
    519	if (unlikely(error))
    520		goto out;
    521	error = decode_nlm4_testrply(xdr, result);
    522out:
    523	return error;
    524}
    525
    526/*
    527 *	struct nlm4_res {
    528 *		netobj cookie;
    529 *		nlm4_stat stat;
    530 *	};
    531 */
    532static int nlm4_xdr_dec_res(struct rpc_rqst *req,
    533			    struct xdr_stream *xdr,
    534			    void *data)
    535{
    536	struct nlm_res *result = data;
    537	int error;
    538
    539	error = decode_cookie(xdr, &result->cookie);
    540	if (unlikely(error))
    541		goto out;
    542	error = decode_nlm4_stat(xdr, &result->status);
    543out:
    544	return error;
    545}
    546
    547
    548/*
    549 * For NLM, a void procedure really returns nothing
    550 */
    551#define nlm4_xdr_dec_norep	NULL
    552
    553#define PROC(proc, argtype, restype)					\
    554[NLMPROC_##proc] = {							\
    555	.p_proc      = NLMPROC_##proc,					\
    556	.p_encode    = nlm4_xdr_enc_##argtype,				\
    557	.p_decode    = nlm4_xdr_dec_##restype,				\
    558	.p_arglen    = NLM4_##argtype##_sz,				\
    559	.p_replen    = NLM4_##restype##_sz,				\
    560	.p_statidx   = NLMPROC_##proc,					\
    561	.p_name      = #proc,						\
    562	}
    563
    564static const struct rpc_procinfo nlm4_procedures[] = {
    565	PROC(TEST,		testargs,	testres),
    566	PROC(LOCK,		lockargs,	res),
    567	PROC(CANCEL,		cancargs,	res),
    568	PROC(UNLOCK,		unlockargs,	res),
    569	PROC(GRANTED,		testargs,	res),
    570	PROC(TEST_MSG,		testargs,	norep),
    571	PROC(LOCK_MSG,		lockargs,	norep),
    572	PROC(CANCEL_MSG,	cancargs,	norep),
    573	PROC(UNLOCK_MSG,	unlockargs,	norep),
    574	PROC(GRANTED_MSG,	testargs,	norep),
    575	PROC(TEST_RES,		testres,	norep),
    576	PROC(LOCK_RES,		res,		norep),
    577	PROC(CANCEL_RES,	res,		norep),
    578	PROC(UNLOCK_RES,	res,		norep),
    579	PROC(GRANTED_RES,	res,		norep),
    580};
    581
    582static unsigned int nlm_version4_counts[ARRAY_SIZE(nlm4_procedures)];
    583const struct rpc_version nlm_version4 = {
    584	.number		= 4,
    585	.nrprocs	= ARRAY_SIZE(nlm4_procedures),
    586	.procs		= nlm4_procedures,
    587	.counts		= nlm_version4_counts,
    588};