clntxdr.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * linux/fs/lockd/clntxdr.c
  4. *
  5. * XDR functions to encode/decode NLM version 3 RPC arguments and results.
  6. * NLM version 3 is backwards compatible with NLM versions 1 and 2.
  7. *
  8. * NLM client-side only.
  9. *
  10. * Copyright (C) 2010, Oracle. All rights reserved.
  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. #include <uapi/linux/nfs2.h>
  18. #define NLMDBG_FACILITY NLMDBG_XDR
  19. #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
  20. # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
  21. #endif
  22. /*
  23. * Declare the space requirements for NLM arguments and replies as
  24. * number of 32bit-words
  25. */
  26. #define NLM_cookie_sz (1+(NLM_MAXCOOKIELEN>>2))
  27. #define NLM_caller_sz (1+(NLMCLNT_OHSIZE>>2))
  28. #define NLM_owner_sz (1+(NLMCLNT_OHSIZE>>2))
  29. #define NLM_fhandle_sz (1+(NFS2_FHSIZE>>2))
  30. #define NLM_lock_sz (3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz)
  31. #define NLM_holder_sz (4+NLM_owner_sz)
  32. #define NLM_testargs_sz (NLM_cookie_sz+1+NLM_lock_sz)
  33. #define NLM_lockargs_sz (NLM_cookie_sz+4+NLM_lock_sz)
  34. #define NLM_cancargs_sz (NLM_cookie_sz+2+NLM_lock_sz)
  35. #define NLM_unlockargs_sz (NLM_cookie_sz+NLM_lock_sz)
  36. #define NLM_testres_sz (NLM_cookie_sz+1+NLM_holder_sz)
  37. #define NLM_res_sz (NLM_cookie_sz+1)
  38. #define NLM_norep_sz (0)
  39. static s32 loff_t_to_s32(loff_t offset)
  40. {
  41. s32 res;
  42. if (offset >= NLM_OFFSET_MAX)
  43. res = NLM_OFFSET_MAX;
  44. else if (offset <= -NLM_OFFSET_MAX)
  45. res = -NLM_OFFSET_MAX;
  46. else
  47. res = offset;
  48. return res;
  49. }
  50. static void nlm_compute_offsets(const struct nlm_lock *lock,
  51. u32 *l_offset, u32 *l_len)
  52. {
  53. const struct file_lock *fl = &lock->fl;
  54. *l_offset = loff_t_to_s32(fl->fl_start);
  55. if (fl->fl_end == OFFSET_MAX)
  56. *l_len = 0;
  57. else
  58. *l_len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
  59. }
  60. /*
  61. * Handle decode buffer overflows out-of-line.
  62. */
  63. static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
  64. {
  65. dprintk("lockd: %s prematurely hit the end of our receive buffer. "
  66. "Remaining buffer length is %tu words.\n",
  67. func, xdr->end - xdr->p);
  68. }
  69. /*
  70. * Encode/decode NLMv3 basic data types
  71. *
  72. * Basic NLMv3 data types are not defined in an IETF standards
  73. * document. X/Open has a description of these data types that
  74. * is useful. See Chapter 10 of "Protocols for Interworking:
  75. * XNFS, Version 3W".
  76. *
  77. * Not all basic data types have their own encoding and decoding
  78. * functions. For run-time efficiency, some data types are encoded
  79. * or decoded inline.
  80. */
  81. static void encode_bool(struct xdr_stream *xdr, const int value)
  82. {
  83. __be32 *p;
  84. p = xdr_reserve_space(xdr, 4);
  85. *p = value ? xdr_one : xdr_zero;
  86. }
  87. static void encode_int32(struct xdr_stream *xdr, const s32 value)
  88. {
  89. __be32 *p;
  90. p = xdr_reserve_space(xdr, 4);
  91. *p = cpu_to_be32(value);
  92. }
  93. /*
  94. * typedef opaque netobj<MAXNETOBJ_SZ>
  95. */
  96. static void encode_netobj(struct xdr_stream *xdr,
  97. const u8 *data, const unsigned int length)
  98. {
  99. __be32 *p;
  100. p = xdr_reserve_space(xdr, 4 + length);
  101. xdr_encode_opaque(p, data, length);
  102. }
  103. static int decode_netobj(struct xdr_stream *xdr,
  104. struct xdr_netobj *obj)
  105. {
  106. u32 length;
  107. __be32 *p;
  108. p = xdr_inline_decode(xdr, 4);
  109. if (unlikely(p == NULL))
  110. goto out_overflow;
  111. length = be32_to_cpup(p++);
  112. if (unlikely(length > XDR_MAX_NETOBJ))
  113. goto out_size;
  114. obj->len = length;
  115. obj->data = (u8 *)p;
  116. return 0;
  117. out_size:
  118. dprintk("NFS: returned netobj was too long: %u\n", length);
  119. return -EIO;
  120. out_overflow:
  121. print_overflow_msg(__func__, xdr);
  122. return -EIO;
  123. }
  124. /*
  125. * netobj cookie;
  126. */
  127. static void encode_cookie(struct xdr_stream *xdr,
  128. const struct nlm_cookie *cookie)
  129. {
  130. encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
  131. }
  132. static int decode_cookie(struct xdr_stream *xdr,
  133. struct nlm_cookie *cookie)
  134. {
  135. u32 length;
  136. __be32 *p;
  137. p = xdr_inline_decode(xdr, 4);
  138. if (unlikely(p == NULL))
  139. goto out_overflow;
  140. length = be32_to_cpup(p++);
  141. /* apparently HPUX can return empty cookies */
  142. if (length == 0)
  143. goto out_hpux;
  144. if (length > NLM_MAXCOOKIELEN)
  145. goto out_size;
  146. p = xdr_inline_decode(xdr, length);
  147. if (unlikely(p == NULL))
  148. goto out_overflow;
  149. cookie->len = length;
  150. memcpy(cookie->data, p, length);
  151. return 0;
  152. out_hpux:
  153. cookie->len = 4;
  154. memset(cookie->data, 0, 4);
  155. return 0;
  156. out_size:
  157. dprintk("NFS: returned cookie was too long: %u\n", length);
  158. return -EIO;
  159. out_overflow:
  160. print_overflow_msg(__func__, xdr);
  161. return -EIO;
  162. }
  163. /*
  164. * netobj fh;
  165. */
  166. static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
  167. {
  168. encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE);
  169. }
  170. /*
  171. * enum nlm_stats {
  172. * LCK_GRANTED = 0,
  173. * LCK_DENIED = 1,
  174. * LCK_DENIED_NOLOCKS = 2,
  175. * LCK_BLOCKED = 3,
  176. * LCK_DENIED_GRACE_PERIOD = 4
  177. * };
  178. *
  179. *
  180. * struct nlm_stat {
  181. * nlm_stats stat;
  182. * };
  183. *
  184. * NB: we don't swap bytes for the NLM status values. The upper
  185. * layers deal directly with the status value in network byte
  186. * order.
  187. */
  188. static void encode_nlm_stat(struct xdr_stream *xdr,
  189. const __be32 stat)
  190. {
  191. __be32 *p;
  192. WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
  193. p = xdr_reserve_space(xdr, 4);
  194. *p = stat;
  195. }
  196. static int decode_nlm_stat(struct xdr_stream *xdr,
  197. __be32 *stat)
  198. {
  199. __be32 *p;
  200. p = xdr_inline_decode(xdr, 4);
  201. if (unlikely(p == NULL))
  202. goto out_overflow;
  203. if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period)))
  204. goto out_enum;
  205. *stat = *p;
  206. return 0;
  207. out_enum:
  208. dprintk("%s: server returned invalid nlm_stats value: %u\n",
  209. __func__, be32_to_cpup(p));
  210. return -EIO;
  211. out_overflow:
  212. print_overflow_msg(__func__, xdr);
  213. return -EIO;
  214. }
  215. /*
  216. * struct nlm_holder {
  217. * bool exclusive;
  218. * int uppid;
  219. * netobj oh;
  220. * unsigned l_offset;
  221. * unsigned l_len;
  222. * };
  223. */
  224. static void encode_nlm_holder(struct xdr_stream *xdr,
  225. const struct nlm_res *result)
  226. {
  227. const struct nlm_lock *lock = &result->lock;
  228. u32 l_offset, l_len;
  229. __be32 *p;
  230. encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
  231. encode_int32(xdr, lock->svid);
  232. encode_netobj(xdr, lock->oh.data, lock->oh.len);
  233. p = xdr_reserve_space(xdr, 4 + 4);
  234. nlm_compute_offsets(lock, &l_offset, &l_len);
  235. *p++ = cpu_to_be32(l_offset);
  236. *p = cpu_to_be32(l_len);
  237. }
  238. static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result)
  239. {
  240. struct nlm_lock *lock = &result->lock;
  241. struct file_lock *fl = &lock->fl;
  242. u32 exclusive, l_offset, l_len;
  243. int error;
  244. __be32 *p;
  245. s32 end;
  246. memset(lock, 0, sizeof(*lock));
  247. locks_init_lock(fl);
  248. p = xdr_inline_decode(xdr, 4 + 4);
  249. if (unlikely(p == NULL))
  250. goto out_overflow;
  251. exclusive = be32_to_cpup(p++);
  252. lock->svid = be32_to_cpup(p);
  253. fl->fl_pid = (pid_t)lock->svid;
  254. error = decode_netobj(xdr, &lock->oh);
  255. if (unlikely(error))
  256. goto out;
  257. p = xdr_inline_decode(xdr, 4 + 4);
  258. if (unlikely(p == NULL))
  259. goto out_overflow;
  260. fl->fl_flags = FL_POSIX;
  261. fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK;
  262. l_offset = be32_to_cpup(p++);
  263. l_len = be32_to_cpup(p);
  264. end = l_offset + l_len - 1;
  265. fl->fl_start = (loff_t)l_offset;
  266. if (l_len == 0 || end < 0)
  267. fl->fl_end = OFFSET_MAX;
  268. else
  269. fl->fl_end = (loff_t)end;
  270. error = 0;
  271. out:
  272. return error;
  273. out_overflow:
  274. print_overflow_msg(__func__, xdr);
  275. return -EIO;
  276. }
  277. /*
  278. * string caller_name<LM_MAXSTRLEN>;
  279. */
  280. static void encode_caller_name(struct xdr_stream *xdr, const char *name)
  281. {
  282. /* NB: client-side does not set lock->len */
  283. u32 length = strlen(name);
  284. __be32 *p;
  285. p = xdr_reserve_space(xdr, 4 + length);
  286. xdr_encode_opaque(p, name, length);
  287. }
  288. /*
  289. * struct nlm_lock {
  290. * string caller_name<LM_MAXSTRLEN>;
  291. * netobj fh;
  292. * netobj oh;
  293. * int uppid;
  294. * unsigned l_offset;
  295. * unsigned l_len;
  296. * };
  297. */
  298. static void encode_nlm_lock(struct xdr_stream *xdr,
  299. const struct nlm_lock *lock)
  300. {
  301. u32 l_offset, l_len;
  302. __be32 *p;
  303. encode_caller_name(xdr, lock->caller);
  304. encode_fh(xdr, &lock->fh);
  305. encode_netobj(xdr, lock->oh.data, lock->oh.len);
  306. p = xdr_reserve_space(xdr, 4 + 4 + 4);
  307. *p++ = cpu_to_be32(lock->svid);
  308. nlm_compute_offsets(lock, &l_offset, &l_len);
  309. *p++ = cpu_to_be32(l_offset);
  310. *p = cpu_to_be32(l_len);
  311. }
  312. /*
  313. * NLMv3 XDR encode functions
  314. *
  315. * NLMv3 argument types are defined in Chapter 10 of The Open Group's
  316. * "Protocols for Interworking: XNFS, Version 3W".
  317. */
  318. /*
  319. * struct nlm_testargs {
  320. * netobj cookie;
  321. * bool exclusive;
  322. * struct nlm_lock alock;
  323. * };
  324. */
  325. static void nlm_xdr_enc_testargs(struct rpc_rqst *req,
  326. struct xdr_stream *xdr,
  327. const void *data)
  328. {
  329. const struct nlm_args *args = data;
  330. const struct nlm_lock *lock = &args->lock;
  331. encode_cookie(xdr, &args->cookie);
  332. encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
  333. encode_nlm_lock(xdr, lock);
  334. }
  335. /*
  336. * struct nlm_lockargs {
  337. * netobj cookie;
  338. * bool block;
  339. * bool exclusive;
  340. * struct nlm_lock alock;
  341. * bool reclaim;
  342. * int state;
  343. * };
  344. */
  345. static void nlm_xdr_enc_lockargs(struct rpc_rqst *req,
  346. struct xdr_stream *xdr,
  347. const void *data)
  348. {
  349. const struct nlm_args *args = data;
  350. const struct nlm_lock *lock = &args->lock;
  351. encode_cookie(xdr, &args->cookie);
  352. encode_bool(xdr, args->block);
  353. encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
  354. encode_nlm_lock(xdr, lock);
  355. encode_bool(xdr, args->reclaim);
  356. encode_int32(xdr, args->state);
  357. }
  358. /*
  359. * struct nlm_cancargs {
  360. * netobj cookie;
  361. * bool block;
  362. * bool exclusive;
  363. * struct nlm_lock alock;
  364. * };
  365. */
  366. static void nlm_xdr_enc_cancargs(struct rpc_rqst *req,
  367. struct xdr_stream *xdr,
  368. const void *data)
  369. {
  370. const struct nlm_args *args = data;
  371. const struct nlm_lock *lock = &args->lock;
  372. encode_cookie(xdr, &args->cookie);
  373. encode_bool(xdr, args->block);
  374. encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
  375. encode_nlm_lock(xdr, lock);
  376. }
  377. /*
  378. * struct nlm_unlockargs {
  379. * netobj cookie;
  380. * struct nlm_lock alock;
  381. * };
  382. */
  383. static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req,
  384. struct xdr_stream *xdr,
  385. const void *data)
  386. {
  387. const struct nlm_args *args = data;
  388. const struct nlm_lock *lock = &args->lock;
  389. encode_cookie(xdr, &args->cookie);
  390. encode_nlm_lock(xdr, lock);
  391. }
  392. /*
  393. * struct nlm_res {
  394. * netobj cookie;
  395. * nlm_stat stat;
  396. * };
  397. */
  398. static void nlm_xdr_enc_res(struct rpc_rqst *req,
  399. struct xdr_stream *xdr,
  400. const void *data)
  401. {
  402. const struct nlm_res *result = data;
  403. encode_cookie(xdr, &result->cookie);
  404. encode_nlm_stat(xdr, result->status);
  405. }
  406. /*
  407. * union nlm_testrply switch (nlm_stats stat) {
  408. * case LCK_DENIED:
  409. * struct nlm_holder holder;
  410. * default:
  411. * void;
  412. * };
  413. *
  414. * struct nlm_testres {
  415. * netobj cookie;
  416. * nlm_testrply test_stat;
  417. * };
  418. */
  419. static void encode_nlm_testrply(struct xdr_stream *xdr,
  420. const struct nlm_res *result)
  421. {
  422. if (result->status == nlm_lck_denied)
  423. encode_nlm_holder(xdr, result);
  424. }
  425. static void nlm_xdr_enc_testres(struct rpc_rqst *req,
  426. struct xdr_stream *xdr,
  427. const void *data)
  428. {
  429. const struct nlm_res *result = data;
  430. encode_cookie(xdr, &result->cookie);
  431. encode_nlm_stat(xdr, result->status);
  432. encode_nlm_testrply(xdr, result);
  433. }
  434. /*
  435. * NLMv3 XDR decode functions
  436. *
  437. * NLMv3 result types are defined in Chapter 10 of The Open Group's
  438. * "Protocols for Interworking: XNFS, Version 3W".
  439. */
  440. /*
  441. * union nlm_testrply switch (nlm_stats stat) {
  442. * case LCK_DENIED:
  443. * struct nlm_holder holder;
  444. * default:
  445. * void;
  446. * };
  447. *
  448. * struct nlm_testres {
  449. * netobj cookie;
  450. * nlm_testrply test_stat;
  451. * };
  452. */
  453. static int decode_nlm_testrply(struct xdr_stream *xdr,
  454. struct nlm_res *result)
  455. {
  456. int error;
  457. error = decode_nlm_stat(xdr, &result->status);
  458. if (unlikely(error))
  459. goto out;
  460. if (result->status == nlm_lck_denied)
  461. error = decode_nlm_holder(xdr, result);
  462. out:
  463. return error;
  464. }
  465. static int nlm_xdr_dec_testres(struct rpc_rqst *req,
  466. struct xdr_stream *xdr,
  467. void *data)
  468. {
  469. struct nlm_res *result = data;
  470. int error;
  471. error = decode_cookie(xdr, &result->cookie);
  472. if (unlikely(error))
  473. goto out;
  474. error = decode_nlm_testrply(xdr, result);
  475. out:
  476. return error;
  477. }
  478. /*
  479. * struct nlm_res {
  480. * netobj cookie;
  481. * nlm_stat stat;
  482. * };
  483. */
  484. static int nlm_xdr_dec_res(struct rpc_rqst *req,
  485. struct xdr_stream *xdr,
  486. void *data)
  487. {
  488. struct nlm_res *result = data;
  489. int error;
  490. error = decode_cookie(xdr, &result->cookie);
  491. if (unlikely(error))
  492. goto out;
  493. error = decode_nlm_stat(xdr, &result->status);
  494. out:
  495. return error;
  496. }
  497. /*
  498. * For NLM, a void procedure really returns nothing
  499. */
  500. #define nlm_xdr_dec_norep NULL
  501. #define PROC(proc, argtype, restype) \
  502. [NLMPROC_##proc] = { \
  503. .p_proc = NLMPROC_##proc, \
  504. .p_encode = nlm_xdr_enc_##argtype, \
  505. .p_decode = nlm_xdr_dec_##restype, \
  506. .p_arglen = NLM_##argtype##_sz, \
  507. .p_replen = NLM_##restype##_sz, \
  508. .p_statidx = NLMPROC_##proc, \
  509. .p_name = #proc, \
  510. }
  511. static const struct rpc_procinfo nlm_procedures[] = {
  512. PROC(TEST, testargs, testres),
  513. PROC(LOCK, lockargs, res),
  514. PROC(CANCEL, cancargs, res),
  515. PROC(UNLOCK, unlockargs, res),
  516. PROC(GRANTED, testargs, res),
  517. PROC(TEST_MSG, testargs, norep),
  518. PROC(LOCK_MSG, lockargs, norep),
  519. PROC(CANCEL_MSG, cancargs, norep),
  520. PROC(UNLOCK_MSG, unlockargs, norep),
  521. PROC(GRANTED_MSG, testargs, norep),
  522. PROC(TEST_RES, testres, norep),
  523. PROC(LOCK_RES, res, norep),
  524. PROC(CANCEL_RES, res, norep),
  525. PROC(UNLOCK_RES, res, norep),
  526. PROC(GRANTED_RES, res, norep),
  527. };
  528. static unsigned int nlm_version1_counts[ARRAY_SIZE(nlm_procedures)];
  529. static const struct rpc_version nlm_version1 = {
  530. .number = 1,
  531. .nrprocs = ARRAY_SIZE(nlm_procedures),
  532. .procs = nlm_procedures,
  533. .counts = nlm_version1_counts,
  534. };
  535. static unsigned int nlm_version3_counts[ARRAY_SIZE(nlm_procedures)];
  536. static const struct rpc_version nlm_version3 = {
  537. .number = 3,
  538. .nrprocs = ARRAY_SIZE(nlm_procedures),
  539. .procs = nlm_procedures,
  540. .counts = nlm_version3_counts,
  541. };
  542. static const struct rpc_version *nlm_versions[] = {
  543. [1] = &nlm_version1,
  544. [3] = &nlm_version3,
  545. #ifdef CONFIG_LOCKD_V4
  546. [4] = &nlm_version4,
  547. #endif
  548. };
  549. static struct rpc_stat nlm_rpc_stats;
  550. const struct rpc_program nlm_program = {
  551. .name = "lockd",
  552. .number = NLM_PROGRAM,
  553. .nrvers = ARRAY_SIZE(nlm_versions),
  554. .version = nlm_versions,
  555. .stats = &nlm_rpc_stats,
  556. };