clnt4xdr.c 13 KB

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