Linux-libre 5.4.49-gnu
[librecmc/linux-libre.git] / fs / nfs / mount_clnt.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * In-kernel MOUNT protocol client
4  *
5  * Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de>
6  */
7
8 #include <linux/types.h>
9 #include <linux/socket.h>
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/uio.h>
13 #include <linux/net.h>
14 #include <linux/in.h>
15 #include <linux/sunrpc/clnt.h>
16 #include <linux/sunrpc/sched.h>
17 #include <linux/nfs_fs.h>
18 #include "internal.h"
19
20 #define NFSDBG_FACILITY NFSDBG_MOUNT
21
22 /*
23  * Defined by RFC 1094, section A.3; and RFC 1813, section 5.1.4
24  */
25 #define MNTPATHLEN              (1024)
26
27 /*
28  * XDR data type sizes
29  */
30 #define encode_dirpath_sz       (1 + XDR_QUADLEN(MNTPATHLEN))
31 #define MNT_status_sz           (1)
32 #define MNT_fhs_status_sz       (1)
33 #define MNT_fhandle_sz          XDR_QUADLEN(NFS2_FHSIZE)
34 #define MNT_fhandle3_sz         (1 + XDR_QUADLEN(NFS3_FHSIZE))
35 #define MNT_fhandlev3_sz        XDR_QUADLEN(NFS3_FHSIZE)
36 #define MNT_authflav3_sz        (1 + NFS_MAX_SECFLAVORS)
37
38 /*
39  * XDR argument and result sizes
40  */
41 #define MNT_enc_dirpath_sz      encode_dirpath_sz
42 #define MNT_dec_mountres_sz     (MNT_status_sz + MNT_fhandle_sz)
43 #define MNT_dec_mountres3_sz    (MNT_status_sz + MNT_fhandlev3_sz + \
44                                  MNT_authflav3_sz)
45
46 /*
47  * Defined by RFC 1094, section A.5
48  */
49 enum {
50         MOUNTPROC_NULL          = 0,
51         MOUNTPROC_MNT           = 1,
52         MOUNTPROC_DUMP          = 2,
53         MOUNTPROC_UMNT          = 3,
54         MOUNTPROC_UMNTALL       = 4,
55         MOUNTPROC_EXPORT        = 5,
56 };
57
58 /*
59  * Defined by RFC 1813, section 5.2
60  */
61 enum {
62         MOUNTPROC3_NULL         = 0,
63         MOUNTPROC3_MNT          = 1,
64         MOUNTPROC3_DUMP         = 2,
65         MOUNTPROC3_UMNT         = 3,
66         MOUNTPROC3_UMNTALL      = 4,
67         MOUNTPROC3_EXPORT       = 5,
68 };
69
70 static const struct rpc_program mnt_program;
71
72 /*
73  * Defined by OpenGroup XNFS Version 3W, chapter 8
74  */
75 enum mountstat {
76         MNT_OK                  = 0,
77         MNT_EPERM               = 1,
78         MNT_ENOENT              = 2,
79         MNT_EACCES              = 13,
80         MNT_EINVAL              = 22,
81 };
82
83 static struct {
84         u32 status;
85         int errno;
86 } mnt_errtbl[] = {
87         { .status = MNT_OK,                     .errno = 0,             },
88         { .status = MNT_EPERM,                  .errno = -EPERM,        },
89         { .status = MNT_ENOENT,                 .errno = -ENOENT,       },
90         { .status = MNT_EACCES,                 .errno = -EACCES,       },
91         { .status = MNT_EINVAL,                 .errno = -EINVAL,       },
92 };
93
94 /*
95  * Defined by RFC 1813, section 5.1.5
96  */
97 enum mountstat3 {
98         MNT3_OK                 = 0,            /* no error */
99         MNT3ERR_PERM            = 1,            /* Not owner */
100         MNT3ERR_NOENT           = 2,            /* No such file or directory */
101         MNT3ERR_IO              = 5,            /* I/O error */
102         MNT3ERR_ACCES           = 13,           /* Permission denied */
103         MNT3ERR_NOTDIR          = 20,           /* Not a directory */
104         MNT3ERR_INVAL           = 22,           /* Invalid argument */
105         MNT3ERR_NAMETOOLONG     = 63,           /* Filename too long */
106         MNT3ERR_NOTSUPP         = 10004,        /* Operation not supported */
107         MNT3ERR_SERVERFAULT     = 10006,        /* A failure on the server */
108 };
109
110 static struct {
111         u32 status;
112         int errno;
113 } mnt3_errtbl[] = {
114         { .status = MNT3_OK,                    .errno = 0,             },
115         { .status = MNT3ERR_PERM,               .errno = -EPERM,        },
116         { .status = MNT3ERR_NOENT,              .errno = -ENOENT,       },
117         { .status = MNT3ERR_IO,                 .errno = -EIO,          },
118         { .status = MNT3ERR_ACCES,              .errno = -EACCES,       },
119         { .status = MNT3ERR_NOTDIR,             .errno = -ENOTDIR,      },
120         { .status = MNT3ERR_INVAL,              .errno = -EINVAL,       },
121         { .status = MNT3ERR_NAMETOOLONG,        .errno = -ENAMETOOLONG, },
122         { .status = MNT3ERR_NOTSUPP,            .errno = -ENOTSUPP,     },
123         { .status = MNT3ERR_SERVERFAULT,        .errno = -EREMOTEIO,    },
124 };
125
126 struct mountres {
127         int errno;
128         struct nfs_fh *fh;
129         unsigned int *auth_count;
130         rpc_authflavor_t *auth_flavors;
131 };
132
133 struct mnt_fhstatus {
134         u32 status;
135         struct nfs_fh *fh;
136 };
137
138 /**
139  * nfs_mount - Obtain an NFS file handle for the given host and path
140  * @info: pointer to mount request arguments
141  *
142  * Uses default timeout parameters specified by underlying transport. On
143  * successful return, the auth_flavs list and auth_flav_len will be populated
144  * with the list from the server or a faked-up list if the server didn't
145  * provide one.
146  */
147 int nfs_mount(struct nfs_mount_request *info)
148 {
149         struct mountres result = {
150                 .fh             = info->fh,
151                 .auth_count     = info->auth_flav_len,
152                 .auth_flavors   = info->auth_flavs,
153         };
154         struct rpc_message msg  = {
155                 .rpc_argp       = info->dirpath,
156                 .rpc_resp       = &result,
157         };
158         struct rpc_create_args args = {
159                 .net            = info->net,
160                 .protocol       = info->protocol,
161                 .address        = info->sap,
162                 .addrsize       = info->salen,
163                 .servername     = info->hostname,
164                 .program        = &mnt_program,
165                 .version        = info->version,
166                 .authflavor     = RPC_AUTH_UNIX,
167                 .cred           = current_cred(),
168         };
169         struct rpc_clnt         *mnt_clnt;
170         int                     status;
171
172         dprintk("NFS: sending MNT request for %s:%s\n",
173                 (info->hostname ? info->hostname : "server"),
174                         info->dirpath);
175
176         if (strlen(info->dirpath) > MNTPATHLEN)
177                 return -ENAMETOOLONG;
178
179         if (info->noresvport)
180                 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
181
182         mnt_clnt = rpc_create(&args);
183         if (IS_ERR(mnt_clnt))
184                 goto out_clnt_err;
185
186         if (info->version == NFS_MNT3_VERSION)
187                 msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
188         else
189                 msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
190
191         status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);
192         rpc_shutdown_client(mnt_clnt);
193
194         if (status < 0)
195                 goto out_call_err;
196         if (result.errno != 0)
197                 goto out_mnt_err;
198
199         dprintk("NFS: MNT request succeeded\n");
200         status = 0;
201
202         /*
203          * If the server didn't provide a flavor list, allow the
204          * client to try any flavor.
205          */
206         if (info->version != NFS_MNT3_VERSION || *info->auth_flav_len == 0) {
207                 dprintk("NFS: Faking up auth_flavs list\n");
208                 info->auth_flavs[0] = RPC_AUTH_NULL;
209                 *info->auth_flav_len = 1;
210         }
211 out:
212         return status;
213
214 out_clnt_err:
215         status = PTR_ERR(mnt_clnt);
216         dprintk("NFS: failed to create MNT RPC client, status=%d\n", status);
217         goto out;
218
219 out_call_err:
220         dprintk("NFS: MNT request failed, status=%d\n", status);
221         goto out;
222
223 out_mnt_err:
224         dprintk("NFS: MNT server returned result %d\n", result.errno);
225         status = result.errno;
226         goto out;
227 }
228
229 /**
230  * nfs_umount - Notify a server that we have unmounted this export
231  * @info: pointer to umount request arguments
232  *
233  * MOUNTPROC_UMNT is advisory, so we set a short timeout, and always
234  * use UDP.
235  */
236 void nfs_umount(const struct nfs_mount_request *info)
237 {
238         static const struct rpc_timeout nfs_umnt_timeout = {
239                 .to_initval = 1 * HZ,
240                 .to_maxval = 3 * HZ,
241                 .to_retries = 2,
242         };
243         struct rpc_create_args args = {
244                 .net            = info->net,
245                 .protocol       = IPPROTO_UDP,
246                 .address        = info->sap,
247                 .addrsize       = info->salen,
248                 .timeout        = &nfs_umnt_timeout,
249                 .servername     = info->hostname,
250                 .program        = &mnt_program,
251                 .version        = info->version,
252                 .authflavor     = RPC_AUTH_UNIX,
253                 .flags          = RPC_CLNT_CREATE_NOPING,
254                 .cred           = current_cred(),
255         };
256         struct rpc_message msg  = {
257                 .rpc_argp       = info->dirpath,
258         };
259         struct rpc_clnt *clnt;
260         int status;
261
262         if (strlen(info->dirpath) > MNTPATHLEN)
263                 return;
264
265         if (info->noresvport)
266                 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
267
268         clnt = rpc_create(&args);
269         if (IS_ERR(clnt))
270                 goto out_clnt_err;
271
272         dprintk("NFS: sending UMNT request for %s:%s\n",
273                 (info->hostname ? info->hostname : "server"), info->dirpath);
274
275         if (info->version == NFS_MNT3_VERSION)
276                 msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC3_UMNT];
277         else
278                 msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC_UMNT];
279
280         status = rpc_call_sync(clnt, &msg, 0);
281         rpc_shutdown_client(clnt);
282
283         if (unlikely(status < 0))
284                 goto out_call_err;
285
286         return;
287
288 out_clnt_err:
289         dprintk("NFS: failed to create UMNT RPC client, status=%ld\n",
290                         PTR_ERR(clnt));
291         return;
292
293 out_call_err:
294         dprintk("NFS: UMNT request failed, status=%d\n", status);
295 }
296
297 /*
298  * XDR encode/decode functions for MOUNT
299  */
300
301 static void encode_mntdirpath(struct xdr_stream *xdr, const char *pathname)
302 {
303         const u32 pathname_len = strlen(pathname);
304         __be32 *p;
305
306         p = xdr_reserve_space(xdr, 4 + pathname_len);
307         xdr_encode_opaque(p, pathname, pathname_len);
308 }
309
310 static void mnt_xdr_enc_dirpath(struct rpc_rqst *req, struct xdr_stream *xdr,
311                                 const void *dirpath)
312 {
313         encode_mntdirpath(xdr, dirpath);
314 }
315
316 /*
317  * RFC 1094: "A non-zero status indicates some sort of error.  In this
318  * case, the status is a UNIX error number."  This can be problematic
319  * if the server and client use different errno values for the same
320  * error.
321  *
322  * However, the OpenGroup XNFS spec provides a simple mapping that is
323  * independent of local errno values on the server and the client.
324  */
325 static int decode_status(struct xdr_stream *xdr, struct mountres *res)
326 {
327         unsigned int i;
328         u32 status;
329         __be32 *p;
330
331         p = xdr_inline_decode(xdr, 4);
332         if (unlikely(p == NULL))
333                 return -EIO;
334         status = be32_to_cpup(p);
335
336         for (i = 0; i < ARRAY_SIZE(mnt_errtbl); i++) {
337                 if (mnt_errtbl[i].status == status) {
338                         res->errno = mnt_errtbl[i].errno;
339                         return 0;
340                 }
341         }
342
343         dprintk("NFS: unrecognized MNT status code: %u\n", status);
344         res->errno = -EACCES;
345         return 0;
346 }
347
348 static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res)
349 {
350         struct nfs_fh *fh = res->fh;
351         __be32 *p;
352
353         p = xdr_inline_decode(xdr, NFS2_FHSIZE);
354         if (unlikely(p == NULL))
355                 return -EIO;
356
357         fh->size = NFS2_FHSIZE;
358         memcpy(fh->data, p, NFS2_FHSIZE);
359         return 0;
360 }
361
362 static int mnt_xdr_dec_mountres(struct rpc_rqst *req,
363                                 struct xdr_stream *xdr,
364                                 void *data)
365 {
366         struct mountres *res = data;
367         int status;
368
369         status = decode_status(xdr, res);
370         if (unlikely(status != 0 || res->errno != 0))
371                 return status;
372         return decode_fhandle(xdr, res);
373 }
374
375 static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res)
376 {
377         unsigned int i;
378         u32 status;
379         __be32 *p;
380
381         p = xdr_inline_decode(xdr, 4);
382         if (unlikely(p == NULL))
383                 return -EIO;
384         status = be32_to_cpup(p);
385
386         for (i = 0; i < ARRAY_SIZE(mnt3_errtbl); i++) {
387                 if (mnt3_errtbl[i].status == status) {
388                         res->errno = mnt3_errtbl[i].errno;
389                         return 0;
390                 }
391         }
392
393         dprintk("NFS: unrecognized MNT3 status code: %u\n", status);
394         res->errno = -EACCES;
395         return 0;
396 }
397
398 static int decode_fhandle3(struct xdr_stream *xdr, struct mountres *res)
399 {
400         struct nfs_fh *fh = res->fh;
401         u32 size;
402         __be32 *p;
403
404         p = xdr_inline_decode(xdr, 4);
405         if (unlikely(p == NULL))
406                 return -EIO;
407
408         size = be32_to_cpup(p);
409         if (size > NFS3_FHSIZE || size == 0)
410                 return -EIO;
411
412         p = xdr_inline_decode(xdr, size);
413         if (unlikely(p == NULL))
414                 return -EIO;
415
416         fh->size = size;
417         memcpy(fh->data, p, size);
418         return 0;
419 }
420
421 static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res)
422 {
423         rpc_authflavor_t *flavors = res->auth_flavors;
424         unsigned int *count = res->auth_count;
425         u32 entries, i;
426         __be32 *p;
427
428         if (*count == 0)
429                 return 0;
430
431         p = xdr_inline_decode(xdr, 4);
432         if (unlikely(p == NULL))
433                 return -EIO;
434         entries = be32_to_cpup(p);
435         dprintk("NFS: received %u auth flavors\n", entries);
436         if (entries > NFS_MAX_SECFLAVORS)
437                 entries = NFS_MAX_SECFLAVORS;
438
439         p = xdr_inline_decode(xdr, 4 * entries);
440         if (unlikely(p == NULL))
441                 return -EIO;
442
443         if (entries > *count)
444                 entries = *count;
445
446         for (i = 0; i < entries; i++) {
447                 flavors[i] = be32_to_cpup(p++);
448                 dprintk("NFS:   auth flavor[%u]: %d\n", i, flavors[i]);
449         }
450         *count = i;
451
452         return 0;
453 }
454
455 static int mnt_xdr_dec_mountres3(struct rpc_rqst *req,
456                                  struct xdr_stream *xdr,
457                                  void *data)
458 {
459         struct mountres *res = data;
460         int status;
461
462         status = decode_fhs_status(xdr, res);
463         if (unlikely(status != 0 || res->errno != 0))
464                 return status;
465         status = decode_fhandle3(xdr, res);
466         if (unlikely(status != 0)) {
467                 res->errno = -EBADHANDLE;
468                 return 0;
469         }
470         return decode_auth_flavors(xdr, res);
471 }
472
473 static const struct rpc_procinfo mnt_procedures[] = {
474         [MOUNTPROC_MNT] = {
475                 .p_proc         = MOUNTPROC_MNT,
476                 .p_encode       = mnt_xdr_enc_dirpath,
477                 .p_decode       = mnt_xdr_dec_mountres,
478                 .p_arglen       = MNT_enc_dirpath_sz,
479                 .p_replen       = MNT_dec_mountres_sz,
480                 .p_statidx      = MOUNTPROC_MNT,
481                 .p_name         = "MOUNT",
482         },
483         [MOUNTPROC_UMNT] = {
484                 .p_proc         = MOUNTPROC_UMNT,
485                 .p_encode       = mnt_xdr_enc_dirpath,
486                 .p_arglen       = MNT_enc_dirpath_sz,
487                 .p_statidx      = MOUNTPROC_UMNT,
488                 .p_name         = "UMOUNT",
489         },
490 };
491
492 static const struct rpc_procinfo mnt3_procedures[] = {
493         [MOUNTPROC3_MNT] = {
494                 .p_proc         = MOUNTPROC3_MNT,
495                 .p_encode       = mnt_xdr_enc_dirpath,
496                 .p_decode       = mnt_xdr_dec_mountres3,
497                 .p_arglen       = MNT_enc_dirpath_sz,
498                 .p_replen       = MNT_dec_mountres3_sz,
499                 .p_statidx      = MOUNTPROC3_MNT,
500                 .p_name         = "MOUNT",
501         },
502         [MOUNTPROC3_UMNT] = {
503                 .p_proc         = MOUNTPROC3_UMNT,
504                 .p_encode       = mnt_xdr_enc_dirpath,
505                 .p_arglen       = MNT_enc_dirpath_sz,
506                 .p_statidx      = MOUNTPROC3_UMNT,
507                 .p_name         = "UMOUNT",
508         },
509 };
510
511 static unsigned int mnt_counts[ARRAY_SIZE(mnt_procedures)];
512 static const struct rpc_version mnt_version1 = {
513         .number         = 1,
514         .nrprocs        = ARRAY_SIZE(mnt_procedures),
515         .procs          = mnt_procedures,
516         .counts         = mnt_counts,
517 };
518
519 static unsigned int mnt3_counts[ARRAY_SIZE(mnt3_procedures)];
520 static const struct rpc_version mnt_version3 = {
521         .number         = 3,
522         .nrprocs        = ARRAY_SIZE(mnt3_procedures),
523         .procs          = mnt3_procedures,
524         .counts         = mnt3_counts,
525 };
526
527 static const struct rpc_version *mnt_version[] = {
528         NULL,
529         &mnt_version1,
530         NULL,
531         &mnt_version3,
532 };
533
534 static struct rpc_stat mnt_stats;
535
536 static const struct rpc_program mnt_program = {
537         .name           = "mount",
538         .number         = NFS_MNT_PROGRAM,
539         .nrvers         = ARRAY_SIZE(mnt_version),
540         .version        = mnt_version,
541         .stats          = &mnt_stats,
542 };