clnt4xdr.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  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. ssize_t ret;
  109. ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data,
  110. XDR_MAX_NETOBJ);
  111. if (unlikely(ret < 0))
  112. return -EIO;
  113. obj->len = ret;
  114. return 0;
  115. }
  116. /*
  117. * netobj cookie;
  118. */
  119. static void encode_cookie(struct xdr_stream *xdr,
  120. const struct nlm_cookie *cookie)
  121. {
  122. encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
  123. }
  124. static int decode_cookie(struct xdr_stream *xdr,
  125. struct nlm_cookie *cookie)
  126. {
  127. u32 length;
  128. __be32 *p;
  129. p = xdr_inline_decode(xdr, 4);
  130. if (unlikely(p == NULL))
  131. goto out_overflow;
  132. length = be32_to_cpup(p++);
  133. /* apparently HPUX can return empty cookies */
  134. if (length == 0)
  135. goto out_hpux;
  136. if (length > NLM_MAXCOOKIELEN)
  137. goto out_size;
  138. p = xdr_inline_decode(xdr, length);
  139. if (unlikely(p == NULL))
  140. goto out_overflow;
  141. cookie->len = length;
  142. memcpy(cookie->data, p, length);
  143. return 0;
  144. out_hpux:
  145. cookie->len = 4;
  146. memset(cookie->data, 0, 4);
  147. return 0;
  148. out_size:
  149. dprintk("NFS: returned cookie was too long: %u\n", length);
  150. return -EIO;
  151. out_overflow:
  152. print_overflow_msg(__func__, xdr);
  153. return -EIO;
  154. }
  155. /*
  156. * netobj fh;
  157. */
  158. static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
  159. {
  160. encode_netobj(xdr, (u8 *)&fh->data, fh->size);
  161. }
  162. /*
  163. * enum nlm4_stats {
  164. * NLM4_GRANTED = 0,
  165. * NLM4_DENIED = 1,
  166. * NLM4_DENIED_NOLOCKS = 2,
  167. * NLM4_BLOCKED = 3,
  168. * NLM4_DENIED_GRACE_PERIOD = 4,
  169. * NLM4_DEADLCK = 5,
  170. * NLM4_ROFS = 6,
  171. * NLM4_STALE_FH = 7,
  172. * NLM4_FBIG = 8,
  173. * NLM4_FAILED = 9
  174. * };
  175. *
  176. * struct nlm4_stat {
  177. * nlm4_stats stat;
  178. * };
  179. *
  180. * NB: we don't swap bytes for the NLM status values. The upper
  181. * layers deal directly with the status value in network byte
  182. * order.
  183. */
  184. static void encode_nlm4_stat(struct xdr_stream *xdr,
  185. const __be32 stat)
  186. {
  187. __be32 *p;
  188. BUG_ON(be32_to_cpu(stat) > NLM_FAILED);
  189. p = xdr_reserve_space(xdr, 4);
  190. *p = stat;
  191. }
  192. static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat)
  193. {
  194. __be32 *p;
  195. p = xdr_inline_decode(xdr, 4);
  196. if (unlikely(p == NULL))
  197. goto out_overflow;
  198. if (unlikely(ntohl(*p) > ntohl(nlm4_failed)))
  199. goto out_bad_xdr;
  200. *stat = *p;
  201. return 0;
  202. out_bad_xdr:
  203. dprintk("%s: server returned invalid nlm4_stats value: %u\n",
  204. __func__, be32_to_cpup(p));
  205. return -EIO;
  206. out_overflow:
  207. print_overflow_msg(__func__, xdr);
  208. return -EIO;
  209. }
  210. /*
  211. * struct nlm4_holder {
  212. * bool exclusive;
  213. * int32 svid;
  214. * netobj oh;
  215. * uint64 l_offset;
  216. * uint64 l_len;
  217. * };
  218. */
  219. static void encode_nlm4_holder(struct xdr_stream *xdr,
  220. const struct nlm_res *result)
  221. {
  222. const struct nlm_lock *lock = &result->lock;
  223. u64 l_offset, l_len;
  224. __be32 *p;
  225. encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
  226. encode_int32(xdr, lock->svid);
  227. encode_netobj(xdr, lock->oh.data, lock->oh.len);
  228. p = xdr_reserve_space(xdr, 4 + 4);
  229. nlm4_compute_offsets(lock, &l_offset, &l_len);
  230. p = xdr_encode_hyper(p, l_offset);
  231. xdr_encode_hyper(p, l_len);
  232. }
  233. static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
  234. {
  235. struct nlm_lock *lock = &result->lock;
  236. struct file_lock *fl = &lock->fl;
  237. u64 l_offset, l_len;
  238. u32 exclusive;
  239. int error;
  240. __be32 *p;
  241. s32 end;
  242. memset(lock, 0, sizeof(*lock));
  243. locks_init_lock(fl);
  244. p = xdr_inline_decode(xdr, 4 + 4);
  245. if (unlikely(p == NULL))
  246. goto out_overflow;
  247. exclusive = be32_to_cpup(p++);
  248. lock->svid = be32_to_cpup(p);
  249. fl->fl_pid = (pid_t)lock->svid;
  250. error = decode_netobj(xdr, &lock->oh);
  251. if (unlikely(error))
  252. goto out;
  253. p = xdr_inline_decode(xdr, 8 + 8);
  254. if (unlikely(p == NULL))
  255. goto out_overflow;
  256. fl->fl_flags = FL_POSIX;
  257. fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK;
  258. p = xdr_decode_hyper(p, &l_offset);
  259. xdr_decode_hyper(p, &l_len);
  260. end = l_offset + l_len - 1;
  261. fl->fl_start = (loff_t)l_offset;
  262. if (l_len == 0 || end < 0)
  263. fl->fl_end = OFFSET_MAX;
  264. else
  265. fl->fl_end = (loff_t)end;
  266. error = 0;
  267. out:
  268. return error;
  269. out_overflow:
  270. print_overflow_msg(__func__, xdr);
  271. return -EIO;
  272. }
  273. /*
  274. * string caller_name<LM_MAXSTRLEN>;
  275. */
  276. static void encode_caller_name(struct xdr_stream *xdr, const char *name)
  277. {
  278. /* NB: client-side does not set lock->len */
  279. u32 length = strlen(name);
  280. __be32 *p;
  281. p = xdr_reserve_space(xdr, 4 + length);
  282. xdr_encode_opaque(p, name, length);
  283. }
  284. /*
  285. * struct nlm4_lock {
  286. * string caller_name<LM_MAXSTRLEN>;
  287. * netobj fh;
  288. * netobj oh;
  289. * int32 svid;
  290. * uint64 l_offset;
  291. * uint64 l_len;
  292. * };
  293. */
  294. static void encode_nlm4_lock(struct xdr_stream *xdr,
  295. const struct nlm_lock *lock)
  296. {
  297. u64 l_offset, l_len;
  298. __be32 *p;
  299. encode_caller_name(xdr, lock->caller);
  300. encode_fh(xdr, &lock->fh);
  301. encode_netobj(xdr, lock->oh.data, lock->oh.len);
  302. p = xdr_reserve_space(xdr, 4 + 8 + 8);
  303. *p++ = cpu_to_be32(lock->svid);
  304. nlm4_compute_offsets(lock, &l_offset, &l_len);
  305. p = xdr_encode_hyper(p, l_offset);
  306. xdr_encode_hyper(p, l_len);
  307. }
  308. /*
  309. * NLMv4 XDR encode functions
  310. *
  311. * NLMv4 argument types are defined in Appendix II of RFC 1813:
  312. * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's
  313. * "Protocols for Interworking: XNFS, Version 3W".
  314. */
  315. /*
  316. * struct nlm4_testargs {
  317. * netobj cookie;
  318. * bool exclusive;
  319. * struct nlm4_lock alock;
  320. * };
  321. */
  322. static void nlm4_xdr_enc_testargs(struct rpc_rqst *req,
  323. struct xdr_stream *xdr,
  324. const void *data)
  325. {
  326. const struct nlm_args *args = data;
  327. const struct nlm_lock *lock = &args->lock;
  328. encode_cookie(xdr, &args->cookie);
  329. encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
  330. encode_nlm4_lock(xdr, lock);
  331. }
  332. /*
  333. * struct nlm4_lockargs {
  334. * netobj cookie;
  335. * bool block;
  336. * bool exclusive;
  337. * struct nlm4_lock alock;
  338. * bool reclaim;
  339. * int state;
  340. * };
  341. */
  342. static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req,
  343. struct xdr_stream *xdr,
  344. const void *data)
  345. {
  346. const struct nlm_args *args = data;
  347. const struct nlm_lock *lock = &args->lock;
  348. encode_cookie(xdr, &args->cookie);
  349. encode_bool(xdr, args->block);
  350. encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
  351. encode_nlm4_lock(xdr, lock);
  352. encode_bool(xdr, args->reclaim);
  353. encode_int32(xdr, args->state);
  354. }
  355. /*
  356. * struct nlm4_cancargs {
  357. * netobj cookie;
  358. * bool block;
  359. * bool exclusive;
  360. * struct nlm4_lock alock;
  361. * };
  362. */
  363. static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req,
  364. struct xdr_stream *xdr,
  365. const void *data)
  366. {
  367. const struct nlm_args *args = data;
  368. const struct nlm_lock *lock = &args->lock;
  369. encode_cookie(xdr, &args->cookie);
  370. encode_bool(xdr, args->block);
  371. encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
  372. encode_nlm4_lock(xdr, lock);
  373. }
  374. /*
  375. * struct nlm4_unlockargs {
  376. * netobj cookie;
  377. * struct nlm4_lock alock;
  378. * };
  379. */
  380. static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req,
  381. struct xdr_stream *xdr,
  382. const void *data)
  383. {
  384. const struct nlm_args *args = data;
  385. const struct nlm_lock *lock = &args->lock;
  386. encode_cookie(xdr, &args->cookie);
  387. encode_nlm4_lock(xdr, lock);
  388. }
  389. /*
  390. * struct nlm4_res {
  391. * netobj cookie;
  392. * nlm4_stat stat;
  393. * };
  394. */
  395. static void nlm4_xdr_enc_res(struct rpc_rqst *req,
  396. struct xdr_stream *xdr,
  397. const void *data)
  398. {
  399. const struct nlm_res *result = data;
  400. encode_cookie(xdr, &result->cookie);
  401. encode_nlm4_stat(xdr, result->status);
  402. }
  403. /*
  404. * union nlm4_testrply switch (nlm4_stats stat) {
  405. * case NLM4_DENIED:
  406. * struct nlm4_holder holder;
  407. * default:
  408. * void;
  409. * };
  410. *
  411. * struct nlm4_testres {
  412. * netobj cookie;
  413. * nlm4_testrply test_stat;
  414. * };
  415. */
  416. static void nlm4_xdr_enc_testres(struct rpc_rqst *req,
  417. struct xdr_stream *xdr,
  418. const void *data)
  419. {
  420. const struct nlm_res *result = data;
  421. encode_cookie(xdr, &result->cookie);
  422. encode_nlm4_stat(xdr, result->status);
  423. if (result->status == nlm_lck_denied)
  424. encode_nlm4_holder(xdr, result);
  425. }
  426. /*
  427. * NLMv4 XDR decode functions
  428. *
  429. * NLMv4 argument types are defined in Appendix II of RFC 1813:
  430. * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's
  431. * "Protocols for Interworking: XNFS, Version 3W".
  432. */
  433. /*
  434. * union nlm4_testrply switch (nlm4_stats stat) {
  435. * case NLM4_DENIED:
  436. * struct nlm4_holder holder;
  437. * default:
  438. * void;
  439. * };
  440. *
  441. * struct nlm4_testres {
  442. * netobj cookie;
  443. * nlm4_testrply test_stat;
  444. * };
  445. */
  446. static int decode_nlm4_testrply(struct xdr_stream *xdr,
  447. struct nlm_res *result)
  448. {
  449. int error;
  450. error = decode_nlm4_stat(xdr, &result->status);
  451. if (unlikely(error))
  452. goto out;
  453. if (result->status == nlm_lck_denied)
  454. error = decode_nlm4_holder(xdr, result);
  455. out:
  456. return error;
  457. }
  458. static int nlm4_xdr_dec_testres(struct rpc_rqst *req,
  459. struct xdr_stream *xdr,
  460. void *data)
  461. {
  462. struct nlm_res *result = data;
  463. int error;
  464. error = decode_cookie(xdr, &result->cookie);
  465. if (unlikely(error))
  466. goto out;
  467. error = decode_nlm4_testrply(xdr, result);
  468. out:
  469. return error;
  470. }
  471. /*
  472. * struct nlm4_res {
  473. * netobj cookie;
  474. * nlm4_stat stat;
  475. * };
  476. */
  477. static int nlm4_xdr_dec_res(struct rpc_rqst *req,
  478. struct xdr_stream *xdr,
  479. void *data)
  480. {
  481. struct nlm_res *result = data;
  482. int error;
  483. error = decode_cookie(xdr, &result->cookie);
  484. if (unlikely(error))
  485. goto out;
  486. error = decode_nlm4_stat(xdr, &result->status);
  487. out:
  488. return error;
  489. }
  490. /*
  491. * For NLM, a void procedure really returns nothing
  492. */
  493. #define nlm4_xdr_dec_norep NULL
  494. #define PROC(proc, argtype, restype) \
  495. [NLMPROC_##proc] = { \
  496. .p_proc = NLMPROC_##proc, \
  497. .p_encode = nlm4_xdr_enc_##argtype, \
  498. .p_decode = nlm4_xdr_dec_##restype, \
  499. .p_arglen = NLM4_##argtype##_sz, \
  500. .p_replen = NLM4_##restype##_sz, \
  501. .p_statidx = NLMPROC_##proc, \
  502. .p_name = #proc, \
  503. }
  504. static const struct rpc_procinfo nlm4_procedures[] = {
  505. PROC(TEST, testargs, testres),
  506. PROC(LOCK, lockargs, res),
  507. PROC(CANCEL, cancargs, res),
  508. PROC(UNLOCK, unlockargs, res),
  509. PROC(GRANTED, testargs, res),
  510. PROC(TEST_MSG, testargs, norep),
  511. PROC(LOCK_MSG, lockargs, norep),
  512. PROC(CANCEL_MSG, cancargs, norep),
  513. PROC(UNLOCK_MSG, unlockargs, norep),
  514. PROC(GRANTED_MSG, testargs, norep),
  515. PROC(TEST_RES, testres, norep),
  516. PROC(LOCK_RES, res, norep),
  517. PROC(CANCEL_RES, res, norep),
  518. PROC(UNLOCK_RES, res, norep),
  519. PROC(GRANTED_RES, res, norep),
  520. };
  521. static unsigned int nlm_version4_counts[ARRAY_SIZE(nlm4_procedures)];
  522. const struct rpc_version nlm_version4 = {
  523. .number = 4,
  524. .nrprocs = ARRAY_SIZE(nlm4_procedures),
  525. .procs = nlm4_procedures,
  526. .counts = nlm_version4_counts,
  527. };