xdr.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * linux/fs/lockd/xdr.c
  4. *
  5. * XDR support for lockd and the lock client.
  6. *
  7. * Copyright (C) 1995, 1996 Olaf Kirch <[email protected]>
  8. */
  9. #include <linux/types.h>
  10. #include <linux/sched.h>
  11. #include <linux/nfs.h>
  12. #include <linux/sunrpc/xdr.h>
  13. #include <linux/sunrpc/clnt.h>
  14. #include <linux/sunrpc/svc.h>
  15. #include <linux/sunrpc/stats.h>
  16. #include <linux/lockd/lockd.h>
  17. #include <uapi/linux/nfs2.h>
  18. #include "svcxdr.h"
  19. static inline loff_t
  20. s32_to_loff_t(__s32 offset)
  21. {
  22. return (loff_t)offset;
  23. }
  24. static inline __s32
  25. loff_t_to_s32(loff_t offset)
  26. {
  27. __s32 res;
  28. if (offset >= NLM_OFFSET_MAX)
  29. res = NLM_OFFSET_MAX;
  30. else if (offset <= -NLM_OFFSET_MAX)
  31. res = -NLM_OFFSET_MAX;
  32. else
  33. res = offset;
  34. return res;
  35. }
  36. /*
  37. * NLM file handles are defined by specification to be a variable-length
  38. * XDR opaque no longer than 1024 bytes. However, this implementation
  39. * constrains their length to exactly the length of an NFSv2 file
  40. * handle.
  41. */
  42. static bool
  43. svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
  44. {
  45. __be32 *p;
  46. u32 len;
  47. if (xdr_stream_decode_u32(xdr, &len) < 0)
  48. return false;
  49. if (len != NFS2_FHSIZE)
  50. return false;
  51. p = xdr_inline_decode(xdr, len);
  52. if (!p)
  53. return false;
  54. fh->size = NFS2_FHSIZE;
  55. memcpy(fh->data, p, len);
  56. memset(fh->data + NFS2_FHSIZE, 0, sizeof(fh->data) - NFS2_FHSIZE);
  57. return true;
  58. }
  59. static bool
  60. svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
  61. {
  62. struct file_lock *fl = &lock->fl;
  63. s32 start, len, end;
  64. if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
  65. return false;
  66. if (!svcxdr_decode_fhandle(xdr, &lock->fh))
  67. return false;
  68. if (!svcxdr_decode_owner(xdr, &lock->oh))
  69. return false;
  70. if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
  71. return false;
  72. if (xdr_stream_decode_u32(xdr, &start) < 0)
  73. return false;
  74. if (xdr_stream_decode_u32(xdr, &len) < 0)
  75. return false;
  76. locks_init_lock(fl);
  77. fl->fl_flags = FL_POSIX;
  78. fl->fl_type = F_RDLCK;
  79. end = start + len - 1;
  80. fl->fl_start = s32_to_loff_t(start);
  81. if (len == 0 || end < 0)
  82. fl->fl_end = OFFSET_MAX;
  83. else
  84. fl->fl_end = s32_to_loff_t(end);
  85. return true;
  86. }
  87. static bool
  88. svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
  89. {
  90. const struct file_lock *fl = &lock->fl;
  91. s32 start, len;
  92. /* exclusive */
  93. if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0)
  94. return false;
  95. if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
  96. return false;
  97. if (!svcxdr_encode_owner(xdr, &lock->oh))
  98. return false;
  99. start = loff_t_to_s32(fl->fl_start);
  100. if (fl->fl_end == OFFSET_MAX)
  101. len = 0;
  102. else
  103. len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
  104. if (xdr_stream_encode_u32(xdr, start) < 0)
  105. return false;
  106. if (xdr_stream_encode_u32(xdr, len) < 0)
  107. return false;
  108. return true;
  109. }
  110. static bool
  111. svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
  112. {
  113. if (!svcxdr_encode_stats(xdr, resp->status))
  114. return false;
  115. switch (resp->status) {
  116. case nlm_lck_denied:
  117. if (!svcxdr_encode_holder(xdr, &resp->lock))
  118. return false;
  119. }
  120. return true;
  121. }
  122. /*
  123. * Decode Call arguments
  124. */
  125. bool
  126. nlmsvc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  127. {
  128. return true;
  129. }
  130. bool
  131. nlmsvc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  132. {
  133. struct nlm_args *argp = rqstp->rq_argp;
  134. u32 exclusive;
  135. if (!svcxdr_decode_cookie(xdr, &argp->cookie))
  136. return false;
  137. if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
  138. return false;
  139. if (!svcxdr_decode_lock(xdr, &argp->lock))
  140. return false;
  141. if (exclusive)
  142. argp->lock.fl.fl_type = F_WRLCK;
  143. return true;
  144. }
  145. bool
  146. nlmsvc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  147. {
  148. struct nlm_args *argp = rqstp->rq_argp;
  149. u32 exclusive;
  150. if (!svcxdr_decode_cookie(xdr, &argp->cookie))
  151. return false;
  152. if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
  153. return false;
  154. if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
  155. return false;
  156. if (!svcxdr_decode_lock(xdr, &argp->lock))
  157. return false;
  158. if (exclusive)
  159. argp->lock.fl.fl_type = F_WRLCK;
  160. if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
  161. return false;
  162. if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
  163. return false;
  164. argp->monitor = 1; /* monitor client by default */
  165. return true;
  166. }
  167. bool
  168. nlmsvc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  169. {
  170. struct nlm_args *argp = rqstp->rq_argp;
  171. u32 exclusive;
  172. if (!svcxdr_decode_cookie(xdr, &argp->cookie))
  173. return false;
  174. if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
  175. return false;
  176. if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
  177. return false;
  178. if (!svcxdr_decode_lock(xdr, &argp->lock))
  179. return false;
  180. if (exclusive)
  181. argp->lock.fl.fl_type = F_WRLCK;
  182. return true;
  183. }
  184. bool
  185. nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  186. {
  187. struct nlm_args *argp = rqstp->rq_argp;
  188. if (!svcxdr_decode_cookie(xdr, &argp->cookie))
  189. return false;
  190. if (!svcxdr_decode_lock(xdr, &argp->lock))
  191. return false;
  192. argp->lock.fl.fl_type = F_UNLCK;
  193. return true;
  194. }
  195. bool
  196. nlmsvc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  197. {
  198. struct nlm_res *resp = rqstp->rq_argp;
  199. if (!svcxdr_decode_cookie(xdr, &resp->cookie))
  200. return false;
  201. if (!svcxdr_decode_stats(xdr, &resp->status))
  202. return false;
  203. return true;
  204. }
  205. bool
  206. nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  207. {
  208. struct nlm_reboot *argp = rqstp->rq_argp;
  209. __be32 *p;
  210. u32 len;
  211. if (xdr_stream_decode_u32(xdr, &len) < 0)
  212. return false;
  213. if (len > SM_MAXSTRLEN)
  214. return false;
  215. p = xdr_inline_decode(xdr, len);
  216. if (!p)
  217. return false;
  218. argp->len = len;
  219. argp->mon = (char *)p;
  220. if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
  221. return false;
  222. p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
  223. if (!p)
  224. return false;
  225. memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
  226. return true;
  227. }
  228. bool
  229. nlmsvc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  230. {
  231. struct nlm_args *argp = rqstp->rq_argp;
  232. struct nlm_lock *lock = &argp->lock;
  233. memset(lock, 0, sizeof(*lock));
  234. locks_init_lock(&lock->fl);
  235. lock->svid = ~(u32)0;
  236. if (!svcxdr_decode_cookie(xdr, &argp->cookie))
  237. return false;
  238. if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
  239. return false;
  240. if (!svcxdr_decode_fhandle(xdr, &lock->fh))
  241. return false;
  242. if (!svcxdr_decode_owner(xdr, &lock->oh))
  243. return false;
  244. /* XXX: Range checks are missing in the original code */
  245. if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
  246. return false;
  247. if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
  248. return false;
  249. return true;
  250. }
  251. bool
  252. nlmsvc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  253. {
  254. struct nlm_args *argp = rqstp->rq_argp;
  255. struct nlm_lock *lock = &argp->lock;
  256. if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
  257. return false;
  258. if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
  259. return false;
  260. return true;
  261. }
  262. /*
  263. * Encode Reply results
  264. */
  265. bool
  266. nlmsvc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  267. {
  268. return true;
  269. }
  270. bool
  271. nlmsvc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  272. {
  273. struct nlm_res *resp = rqstp->rq_resp;
  274. return svcxdr_encode_cookie(xdr, &resp->cookie) &&
  275. svcxdr_encode_testrply(xdr, resp);
  276. }
  277. bool
  278. nlmsvc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  279. {
  280. struct nlm_res *resp = rqstp->rq_resp;
  281. return svcxdr_encode_cookie(xdr, &resp->cookie) &&
  282. svcxdr_encode_stats(xdr, resp->status);
  283. }
  284. bool
  285. nlmsvc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
  286. {
  287. struct nlm_res *resp = rqstp->rq_resp;
  288. if (!svcxdr_encode_cookie(xdr, &resp->cookie))
  289. return false;
  290. if (!svcxdr_encode_stats(xdr, resp->status))
  291. return false;
  292. /* sequence */
  293. if (xdr_stream_encode_u32(xdr, 0) < 0)
  294. return false;
  295. return true;
  296. }