nfs2acl.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Process version 2 NFSACL requests.
  4. *
  5. * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
  6. */
  7. #include "nfsd.h"
  8. /* FIXME: nfsacl.h is a broken header */
  9. #include <linux/nfsacl.h>
  10. #include <linux/gfp.h>
  11. #include "cache.h"
  12. #include "xdr3.h"
  13. #include "vfs.h"
  14. #define NFSDDBG_FACILITY NFSDDBG_PROC
  15. #define RETURN_STATUS(st) { resp->status = (st); return (st); }
  16. /*
  17. * NULL call.
  18. */
  19. static __be32
  20. nfsacld_proc_null(struct svc_rqst *rqstp)
  21. {
  22. return nfs_ok;
  23. }
  24. /*
  25. * Get the Access and/or Default ACL of a file.
  26. */
  27. static __be32 nfsacld_proc_getacl(struct svc_rqst *rqstp)
  28. {
  29. struct nfsd3_getaclargs *argp = rqstp->rq_argp;
  30. struct nfsd3_getaclres *resp = rqstp->rq_resp;
  31. struct posix_acl *acl;
  32. struct inode *inode;
  33. svc_fh *fh;
  34. __be32 nfserr = 0;
  35. dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
  36. fh = fh_copy(&resp->fh, &argp->fh);
  37. nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
  38. if (nfserr)
  39. RETURN_STATUS(nfserr);
  40. inode = d_inode(fh->fh_dentry);
  41. if (argp->mask & ~NFS_ACL_MASK)
  42. RETURN_STATUS(nfserr_inval);
  43. resp->mask = argp->mask;
  44. nfserr = fh_getattr(fh, &resp->stat);
  45. if (nfserr)
  46. RETURN_STATUS(nfserr);
  47. if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
  48. acl = get_acl(inode, ACL_TYPE_ACCESS);
  49. if (acl == NULL) {
  50. /* Solaris returns the inode's minimum ACL. */
  51. acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
  52. }
  53. if (IS_ERR(acl)) {
  54. nfserr = nfserrno(PTR_ERR(acl));
  55. goto fail;
  56. }
  57. resp->acl_access = acl;
  58. }
  59. if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
  60. /* Check how Solaris handles requests for the Default ACL
  61. of a non-directory! */
  62. acl = get_acl(inode, ACL_TYPE_DEFAULT);
  63. if (IS_ERR(acl)) {
  64. nfserr = nfserrno(PTR_ERR(acl));
  65. goto fail;
  66. }
  67. resp->acl_default = acl;
  68. }
  69. /* resp->acl_{access,default} are released in nfssvc_release_getacl. */
  70. RETURN_STATUS(0);
  71. fail:
  72. posix_acl_release(resp->acl_access);
  73. posix_acl_release(resp->acl_default);
  74. RETURN_STATUS(nfserr);
  75. }
  76. /*
  77. * Set the Access and/or Default ACL of a file.
  78. */
  79. static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)
  80. {
  81. struct nfsd3_setaclargs *argp = rqstp->rq_argp;
  82. struct nfsd_attrstat *resp = rqstp->rq_resp;
  83. struct inode *inode;
  84. svc_fh *fh;
  85. __be32 nfserr = 0;
  86. int error;
  87. dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
  88. fh = fh_copy(&resp->fh, &argp->fh);
  89. nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
  90. if (nfserr)
  91. goto out;
  92. inode = d_inode(fh->fh_dentry);
  93. error = fh_want_write(fh);
  94. if (error)
  95. goto out_errno;
  96. fh_lock(fh);
  97. error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
  98. if (error)
  99. goto out_drop_lock;
  100. error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
  101. if (error)
  102. goto out_drop_lock;
  103. fh_unlock(fh);
  104. fh_drop_write(fh);
  105. nfserr = fh_getattr(fh, &resp->stat);
  106. out:
  107. /* argp->acl_{access,default} may have been allocated in
  108. nfssvc_decode_setaclargs. */
  109. posix_acl_release(argp->acl_access);
  110. posix_acl_release(argp->acl_default);
  111. return nfserr;
  112. out_drop_lock:
  113. fh_unlock(fh);
  114. fh_drop_write(fh);
  115. out_errno:
  116. nfserr = nfserrno(error);
  117. goto out;
  118. }
  119. /*
  120. * Check file attributes
  121. */
  122. static __be32 nfsacld_proc_getattr(struct svc_rqst *rqstp)
  123. {
  124. struct nfsd_fhandle *argp = rqstp->rq_argp;
  125. struct nfsd_attrstat *resp = rqstp->rq_resp;
  126. __be32 nfserr;
  127. dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
  128. fh_copy(&resp->fh, &argp->fh);
  129. nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
  130. if (nfserr)
  131. return nfserr;
  132. nfserr = fh_getattr(&resp->fh, &resp->stat);
  133. return nfserr;
  134. }
  135. /*
  136. * Check file access
  137. */
  138. static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)
  139. {
  140. struct nfsd3_accessargs *argp = rqstp->rq_argp;
  141. struct nfsd3_accessres *resp = rqstp->rq_resp;
  142. __be32 nfserr;
  143. dprintk("nfsd: ACCESS(2acl) %s 0x%x\n",
  144. SVCFH_fmt(&argp->fh),
  145. argp->access);
  146. fh_copy(&resp->fh, &argp->fh);
  147. resp->access = argp->access;
  148. nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
  149. if (nfserr)
  150. return nfserr;
  151. nfserr = fh_getattr(&resp->fh, &resp->stat);
  152. return nfserr;
  153. }
  154. /*
  155. * XDR decode functions
  156. */
  157. static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)
  158. {
  159. struct nfsd3_getaclargs *argp = rqstp->rq_argp;
  160. p = nfs2svc_decode_fh(p, &argp->fh);
  161. if (!p)
  162. return 0;
  163. argp->mask = ntohl(*p); p++;
  164. return xdr_argsize_check(rqstp, p);
  165. }
  166. static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)
  167. {
  168. struct nfsd3_setaclargs *argp = rqstp->rq_argp;
  169. struct kvec *head = rqstp->rq_arg.head;
  170. unsigned int base;
  171. int n;
  172. p = nfs2svc_decode_fh(p, &argp->fh);
  173. if (!p)
  174. return 0;
  175. argp->mask = ntohl(*p++);
  176. if (argp->mask & ~NFS_ACL_MASK ||
  177. !xdr_argsize_check(rqstp, p))
  178. return 0;
  179. base = (char *)p - (char *)head->iov_base;
  180. n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
  181. (argp->mask & NFS_ACL) ?
  182. &argp->acl_access : NULL);
  183. if (n > 0)
  184. n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
  185. (argp->mask & NFS_DFACL) ?
  186. &argp->acl_default : NULL);
  187. return (n > 0);
  188. }
  189. static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
  190. {
  191. struct nfsd_fhandle *argp = rqstp->rq_argp;
  192. p = nfs2svc_decode_fh(p, &argp->fh);
  193. if (!p)
  194. return 0;
  195. return xdr_argsize_check(rqstp, p);
  196. }
  197. static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
  198. {
  199. struct nfsd3_accessargs *argp = rqstp->rq_argp;
  200. p = nfs2svc_decode_fh(p, &argp->fh);
  201. if (!p)
  202. return 0;
  203. argp->access = ntohl(*p++);
  204. return xdr_argsize_check(rqstp, p);
  205. }
  206. /*
  207. * XDR encode functions
  208. */
  209. /*
  210. * There must be an encoding function for void results so svc_process
  211. * will work properly.
  212. */
  213. static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
  214. {
  215. return xdr_ressize_check(rqstp, p);
  216. }
  217. /* GETACL */
  218. static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)
  219. {
  220. struct nfsd3_getaclres *resp = rqstp->rq_resp;
  221. struct dentry *dentry = resp->fh.fh_dentry;
  222. struct inode *inode;
  223. struct kvec *head = rqstp->rq_res.head;
  224. unsigned int base;
  225. int n;
  226. int w;
  227. /*
  228. * Since this is version 2, the check for nfserr in
  229. * nfsd_dispatch actually ensures the following cannot happen.
  230. * However, it seems fragile to depend on that.
  231. */
  232. if (dentry == NULL || d_really_is_negative(dentry))
  233. return 0;
  234. inode = d_inode(dentry);
  235. p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
  236. *p++ = htonl(resp->mask);
  237. if (!xdr_ressize_check(rqstp, p))
  238. return 0;
  239. base = (char *)p - (char *)head->iov_base;
  240. rqstp->rq_res.page_len = w = nfsacl_size(
  241. (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
  242. (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
  243. while (w > 0) {
  244. if (!*(rqstp->rq_next_page++))
  245. return 0;
  246. w -= PAGE_SIZE;
  247. }
  248. n = nfsacl_encode(&rqstp->rq_res, base, inode,
  249. resp->acl_access,
  250. resp->mask & NFS_ACL, 0);
  251. if (n > 0)
  252. n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
  253. resp->acl_default,
  254. resp->mask & NFS_DFACL,
  255. NFS_ACL_DEFAULT);
  256. return (n > 0);
  257. }
  258. static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p)
  259. {
  260. struct nfsd_attrstat *resp = rqstp->rq_resp;
  261. p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
  262. return xdr_ressize_check(rqstp, p);
  263. }
  264. /* ACCESS */
  265. static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
  266. {
  267. struct nfsd3_accessres *resp = rqstp->rq_resp;
  268. p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
  269. *p++ = htonl(resp->access);
  270. return xdr_ressize_check(rqstp, p);
  271. }
  272. /*
  273. * XDR release functions
  274. */
  275. static void nfsaclsvc_release_getacl(struct svc_rqst *rqstp)
  276. {
  277. struct nfsd3_getaclres *resp = rqstp->rq_resp;
  278. fh_put(&resp->fh);
  279. posix_acl_release(resp->acl_access);
  280. posix_acl_release(resp->acl_default);
  281. }
  282. static void nfsaclsvc_release_attrstat(struct svc_rqst *rqstp)
  283. {
  284. struct nfsd_attrstat *resp = rqstp->rq_resp;
  285. fh_put(&resp->fh);
  286. }
  287. static void nfsaclsvc_release_access(struct svc_rqst *rqstp)
  288. {
  289. struct nfsd3_accessres *resp = rqstp->rq_resp;
  290. fh_put(&resp->fh);
  291. }
  292. #define nfsaclsvc_decode_voidargs NULL
  293. #define nfsaclsvc_release_void NULL
  294. #define nfsd3_fhandleargs nfsd_fhandle
  295. #define nfsd3_attrstatres nfsd_attrstat
  296. #define nfsd3_voidres nfsd3_voidargs
  297. struct nfsd3_voidargs { int dummy; };
  298. #define PROC(name, argt, rest, relt, cache, respsize) \
  299. { \
  300. .pc_func = nfsacld_proc_##name, \
  301. .pc_decode = nfsaclsvc_decode_##argt##args, \
  302. .pc_encode = nfsaclsvc_encode_##rest##res, \
  303. .pc_release = nfsaclsvc_release_##relt, \
  304. .pc_argsize = sizeof(struct nfsd3_##argt##args), \
  305. .pc_ressize = sizeof(struct nfsd3_##rest##res), \
  306. .pc_cachetype = cache, \
  307. .pc_xdrressize = respsize, \
  308. }
  309. #define ST 1 /* status*/
  310. #define AT 21 /* attributes */
  311. #define pAT (1+AT) /* post attributes - conditional */
  312. #define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
  313. static const struct svc_procedure nfsd_acl_procedures2[] = {
  314. PROC(null, void, void, void, RC_NOCACHE, ST),
  315. PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
  316. PROC(setacl, setacl, attrstat, attrstat, RC_NOCACHE, ST+AT),
  317. PROC(getattr, fhandle, attrstat, attrstat, RC_NOCACHE, ST+AT),
  318. PROC(access, access, access, access, RC_NOCACHE, ST+AT+1),
  319. };
  320. static unsigned int nfsd_acl_count2[ARRAY_SIZE(nfsd_acl_procedures2)];
  321. const struct svc_version nfsd_acl_version2 = {
  322. .vs_vers = 2,
  323. .vs_nproc = 5,
  324. .vs_proc = nfsd_acl_procedures2,
  325. .vs_count = nfsd_acl_count2,
  326. .vs_dispatch = nfsd_dispatch,
  327. .vs_xdrsize = NFS3_SVC_XDRSIZE,
  328. };