^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * NFS exporting and validation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * We maintain a list of clients, each of which has a list of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * exports. To export an fs to a given client, you first have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * to create the client entry with NFSCTL_ADDCLIENT, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * creates a client control block and adds it to the hash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * table. Then, you call NFSCTL_EXPORT for each fs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/exportfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sunrpc/svc_xprt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "nfsd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "nfsfh.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "netns.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "pnfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "filecache.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define NFSDDBG_FACILITY NFSDDBG_EXPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * We have two caches.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * One maps client+vfsmnt+dentry to export options - the export map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * The other maps client+filehandle-fragment to export options. - the expkey map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * The export options are actually stored in the first map, and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * second map contains a reference to the entry in the first map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define EXPKEY_HASHBITS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static void expkey_put(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (test_bit(CACHE_VALID, &key->h.flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) !test_bit(CACHE_NEGATIVE, &key->h.flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) path_put(&key->ek_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) auth_domain_put(key->ek_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) kfree_rcu(key, ek_rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return sunrpc_cache_pipe_upcall(cd, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void expkey_request(struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct cache_head *h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) char **bpp, int *blen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* client fsidtype \xfsid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) char type[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) qword_add(bpp, blen, ek->ek_client->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) snprintf(type, 5, "%d", ek->ek_fsidtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) qword_add(bpp, blen, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) qword_addhex(bpp, blen, (char*)ek->ek_fsid, key_len(ek->ek_fsidtype));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) (*bpp)[-1] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct svc_expkey *old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* client fsidtype fsid expiry [path] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct auth_domain *dom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int fsidtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) char *ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct svc_expkey key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct svc_expkey *ek = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (mesg[mlen - 1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mesg[mlen-1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) dom = auth_domain_find(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) dprintk("found domain %s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) fsidtype = simple_strtoul(buf, &ep, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (*ep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dprintk("found fsidtype %d\n", fsidtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (key_len(fsidtype)==0) /* invalid type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dprintk("found fsid length %d\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (len != key_len(fsidtype))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* OK, we seem to have a valid key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) key.h.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) key.h.expiry_time = get_expiry(&mesg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (key.h.expiry_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) key.ek_client = dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) key.ek_fsidtype = fsidtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) memcpy(key.ek_fsid, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ek = svc_expkey_lookup(cd, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!ek)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* now we want a pathname, or empty meaning NEGATIVE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) len = qword_get(&mesg, buf, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) dprintk("Path seems to be <%s>\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) set_bit(CACHE_NEGATIVE, &key.h.flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ek = svc_expkey_update(cd, &key, ek);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (ek)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) trace_nfsd_expkey_update(ek, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) err = kern_path(buf, 0, &key.ek_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) dprintk("Found the path %s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ek = svc_expkey_update(cd, &key, ek);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (ek)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) trace_nfsd_expkey_update(ek, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) path_put(&key.ek_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) cache_flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (ek)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) cache_put(&ek->h, cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) auth_domain_put(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static int expkey_show(struct seq_file *m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct cache_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct svc_expkey *ek ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (h ==NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) seq_puts(m, "#domain fsidtype fsid [path]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ek = container_of(h, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) seq_printf(m, "%s %d 0x", ek->ek_client->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ek->ek_fsidtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) for (i=0; i < key_len(ek->ek_fsidtype)/4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) seq_printf(m, "%08x", ek->ek_fsid[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (test_bit(CACHE_VALID, &h->flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) !test_bit(CACHE_NEGATIVE, &h->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) seq_printf(m, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) seq_path(m, &ek->ek_path, "\\ \t\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) seq_printf(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static inline int expkey_match (struct cache_head *a, struct cache_head *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct svc_expkey *new = container_of(b, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (orig->ek_fsidtype != new->ek_fsidtype ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) orig->ek_client != new->ek_client ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static inline void expkey_init(struct cache_head *cnew,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct cache_head *citem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) kref_get(&item->ek_client->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) new->ek_client = item->ek_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) new->ek_fsidtype = item->ek_fsidtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static inline void expkey_update(struct cache_head *cnew,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct cache_head *citem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) new->ek_path = item->ek_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) path_get(&item->ek_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static struct cache_head *expkey_alloc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return &i->h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static void expkey_flush(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * Take the nfsd_mutex here to ensure that the file cache is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * destroyed while we're in the middle of flushing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) mutex_lock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) nfsd_file_cache_purge(current->nsproxy->net_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static const struct cache_detail svc_expkey_cache_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .hash_size = EXPKEY_HASHMAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .name = "nfsd.fh",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .cache_put = expkey_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .cache_upcall = expkey_upcall,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .cache_request = expkey_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .cache_parse = expkey_parse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .cache_show = expkey_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .match = expkey_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .init = expkey_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .update = expkey_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .alloc = expkey_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .flush = expkey_flush,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) svc_expkey_hash(struct svc_expkey *item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int hash = item->ek_fsidtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) char * cp = (char*)item->ek_fsid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int len = key_len(item->ek_fsidtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) hash &= EXPKEY_HASHMASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static struct svc_expkey *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct cache_head *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int hash = svc_expkey_hash(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return container_of(ch, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static struct svc_expkey *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct svc_expkey *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct cache_head *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int hash = svc_expkey_hash(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ch = sunrpc_cache_update(cd, &new->h, &old->h, hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return container_of(ch, struct svc_expkey, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) #define EXPORT_HASHBITS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct nfsd4_fs_location *locations = fsloc->locations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (!locations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) for (i = 0; i < fsloc->locations_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) kfree(locations[i].path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) kfree(locations[i].hosts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) kfree(locations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) fsloc->locations = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static void svc_export_put(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) path_put(&exp->ex_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) auth_domain_put(exp->ex_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) nfsd4_fslocs_free(&exp->ex_fslocs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) kfree(exp->ex_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) kfree_rcu(exp, ex_rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return sunrpc_cache_pipe_upcall(cd, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static void svc_export_request(struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct cache_head *h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) char **bpp, int *blen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* client path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct svc_export *exp = container_of(h, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) char *pth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) qword_add(bpp, blen, exp->ex_client->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) pth = d_path(&exp->ex_path, *bpp, *blen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (IS_ERR(pth)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /* is this correct? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) (*bpp)[0] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) qword_add(bpp, blen, pth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) (*bpp)[-1] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static struct svc_export *svc_export_update(struct svc_export *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct svc_export *old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static struct svc_export *svc_export_lookup(struct svc_export *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static int check_export(struct inode *inode, int *flags, unsigned char *uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * We currently export only dirs, regular files, and (for v4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * pseudoroot) symlinks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (!S_ISDIR(inode->i_mode) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) !S_ISLNK(inode->i_mode) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) !S_ISREG(inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return -ENOTDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * Mountd should never pass down a writeable V4ROOT export, but,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * just to make sure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (*flags & NFSEXP_V4ROOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) *flags |= NFSEXP_READONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* There are two requirements on a filesystem to be exportable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * 1: We must be able to identify the filesystem from a number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * either a device number (so FS_REQUIRES_DEV needed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * or an FSID number (so NFSEXP_FSID or ->uuid is needed).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * 2: We must be able to find an inode from a filehandle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * This means that s_export_op must be set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) !(*flags & NFSEXP_FSID) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) uuid == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) dprintk("exp_export: export of non-dev fs without fsid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!inode->i_sb->s_export_op ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) !inode->i_sb->s_export_op->fh_to_dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) dprintk("exp_export: export of invalid fs type.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) #ifdef CONFIG_NFSD_V4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int migrated, i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* more than one fsloc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (fsloc->locations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* listsize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) err = get_uint(mesg, &fsloc->locations_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (fsloc->locations_count > MAX_FS_LOCATIONS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (fsloc->locations_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) fsloc->locations = kcalloc(fsloc->locations_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) sizeof(struct nfsd4_fs_location),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (!fsloc->locations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) for (i=0; i < fsloc->locations_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /* colon separated host list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) len = qword_get(mesg, buf, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) goto out_free_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) fsloc->locations[i].hosts = kstrdup(buf, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (!fsloc->locations[i].hosts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) goto out_free_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /* slash separated path component list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) len = qword_get(mesg, buf, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) goto out_free_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) fsloc->locations[i].path = kstrdup(buf, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!fsloc->locations[i].path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) goto out_free_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* migrated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) err = get_int(mesg, &migrated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) goto out_free_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (migrated < 0 || migrated > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) goto out_free_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) fsloc->migrated = migrated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) out_free_all:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) nfsd4_fslocs_free(fsloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct exp_flavor_info *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) u32 listsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* more than one secinfo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (exp->ex_nflavors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) err = get_uint(mesg, &listsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (listsize > MAX_SECINFO_LIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) err = get_uint(mesg, &f->pseudoflavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * XXX: It would be nice to also check whether this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * pseudoflavor is supported, so we can discover the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * problem at export time instead of when a client fails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * to authenticate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) err = get_uint(mesg, &f->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* Only some flags are allowed to differ between flavors: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) exp->ex_nflavors = listsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) #else /* CONFIG_NFSD_V4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* more than one uuid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (*puuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /* expect a 16 byte uuid encoded as \xXXXX... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) len = qword_get(mesg, buf, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (len != EX_UUID_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) *puuid = kmemdup(buf, EX_UUID_LEN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (*puuid == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* client path expiry [flags anonuid anongid fsid] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct auth_domain *dom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct svc_export exp = {}, *expp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int an_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (mesg[mlen-1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) mesg[mlen-1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* client */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) len = qword_get(&mesg, buf, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) dom = auth_domain_find(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if ((len = qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) err = kern_path(buf, 0, &exp.ex_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) exp.ex_client = dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) exp.cd = cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) exp.ex_devid_map = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /* expiry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) exp.h.expiry_time = get_expiry(&mesg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (exp.h.expiry_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) goto out3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) err = get_int(&mesg, &an_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (err == -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) set_bit(CACHE_NEGATIVE, &exp.h.flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (err || an_int < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) goto out3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) exp.ex_flags= an_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* anon uid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) err = get_int(&mesg, &an_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) goto out3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) exp.ex_anon_uid= make_kuid(current_user_ns(), an_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* anon gid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) err = get_int(&mesg, &an_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) goto out3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) exp.ex_anon_gid= make_kgid(current_user_ns(), an_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* fsid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) err = get_int(&mesg, &an_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) goto out3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) exp.ex_fsid = an_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (strcmp(buf, "fsloc") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) else if (strcmp(buf, "uuid") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) else if (strcmp(buf, "secinfo") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) err = secinfo_parse(&mesg, buf, &exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /* quietly ignore unknown words and anything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * following. Newer user-space can try to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * new values, then see what the result was.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) goto out4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) err = check_export(d_inode(exp.ex_path.dentry), &exp.ex_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) exp.ex_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) goto out4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * No point caching this if it would immediately expire.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * Also, this protects exportfs's dummy export from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * anon_uid/anon_gid checks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (exp.h.expiry_time < seconds_since_boot())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) goto out4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * For some reason exportfs has been passing down an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * invalid (-1) uid & gid on the "dummy" export which it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * uses to test export support. To make sure exportfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * sees errors from check_export we therefore need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * delay these checks till after check_export:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (!uid_valid(exp.ex_anon_uid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) goto out4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (!gid_valid(exp.ex_anon_gid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) goto out4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) nfsd4_setup_layout_type(&exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) expp = svc_export_lookup(&exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (!expp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) goto out4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) expp = svc_export_update(&exp, expp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (expp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) trace_nfsd_export_update(expp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) cache_flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) exp_put(expp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) out4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) nfsd4_fslocs_free(&exp.ex_fslocs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) kfree(exp.ex_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) out3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) path_put(&exp.ex_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) auth_domain_put(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static void exp_flags(struct seq_file *m, int flag, int fsid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fslocs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static void show_secinfo(struct seq_file *m, struct svc_export *exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static int svc_export_show(struct seq_file *m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) struct cache_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct svc_export *exp ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (h ==NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) seq_puts(m, "#path domain(flags)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) exp = container_of(h, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) seq_path(m, &exp->ex_path, " \t\n\\");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) seq_putc(m, '\t');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) seq_escape(m, exp->ex_client->name, " \t\n\\");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) seq_putc(m, '(');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (test_bit(CACHE_VALID, &h->flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) !test_bit(CACHE_NEGATIVE, &h->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) exp_flags(m, exp->ex_flags, exp->ex_fsid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (exp->ex_uuid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) seq_puts(m, ",uuid=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) for (i = 0; i < EX_UUID_LEN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if ((i&3) == 0 && i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) seq_putc(m, ':');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) seq_printf(m, "%02x", exp->ex_uuid[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) show_secinfo(m, exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) seq_puts(m, ")\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static int svc_export_match(struct cache_head *a, struct cache_head *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct svc_export *orig = container_of(a, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct svc_export *new = container_of(b, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return orig->ex_client == new->ex_client &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) path_equal(&orig->ex_path, &new->ex_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct svc_export *new = container_of(cnew, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) struct svc_export *item = container_of(citem, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) kref_get(&item->ex_client->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) new->ex_client = item->ex_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) new->ex_path = item->ex_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) path_get(&item->ex_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) new->ex_fslocs.locations = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) new->ex_fslocs.locations_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) new->ex_fslocs.migrated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) new->ex_layout_types = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) new->ex_uuid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) new->cd = item->cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static void export_update(struct cache_head *cnew, struct cache_head *citem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct svc_export *new = container_of(cnew, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct svc_export *item = container_of(citem, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) new->ex_flags = item->ex_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) new->ex_anon_uid = item->ex_anon_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) new->ex_anon_gid = item->ex_anon_gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) new->ex_fsid = item->ex_fsid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) new->ex_devid_map = item->ex_devid_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) item->ex_devid_map = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) new->ex_uuid = item->ex_uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) item->ex_uuid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) new->ex_fslocs.locations = item->ex_fslocs.locations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) item->ex_fslocs.locations = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) new->ex_fslocs.locations_count = item->ex_fslocs.locations_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) item->ex_fslocs.locations_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) new->ex_fslocs.migrated = item->ex_fslocs.migrated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) item->ex_fslocs.migrated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) new->ex_layout_types = item->ex_layout_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) new->ex_nflavors = item->ex_nflavors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) for (i = 0; i < MAX_SECINFO_LIST; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) new->ex_flavors[i] = item->ex_flavors[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static struct cache_head *svc_export_alloc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return &i->h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static const struct cache_detail svc_export_cache_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .hash_size = EXPORT_HASHMAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .name = "nfsd.export",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) .cache_put = svc_export_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .cache_upcall = svc_export_upcall,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .cache_request = svc_export_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .cache_parse = svc_export_parse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .cache_show = svc_export_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .match = svc_export_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .init = svc_export_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .update = export_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .alloc = svc_export_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) svc_export_hash(struct svc_export *exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) int hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) hash ^= hash_ptr(exp->ex_path.dentry, EXPORT_HASHBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) hash ^= hash_ptr(exp->ex_path.mnt, EXPORT_HASHBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static struct svc_export *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) svc_export_lookup(struct svc_export *exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct cache_head *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) int hash = svc_export_hash(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) ch = sunrpc_cache_lookup_rcu(exp->cd, &exp->h, hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return container_of(ch, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static struct svc_export *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) svc_export_update(struct svc_export *new, struct svc_export *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct cache_head *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) int hash = svc_export_hash(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) ch = sunrpc_cache_update(old->cd, &new->h, &old->h, hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return container_of(ch, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static struct svc_expkey *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) exp_find_key(struct cache_detail *cd, struct auth_domain *clp, int fsid_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) u32 *fsidv, struct cache_req *reqp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct svc_expkey key, *ek;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (!clp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) key.ek_client = clp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) key.ek_fsidtype = fsid_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) ek = svc_expkey_lookup(cd, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (ek == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) err = cache_check(cd, &ek->h, reqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) trace_nfsd_exp_find_key(&key, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return ek;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static struct svc_export *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) exp_get_by_name(struct cache_detail *cd, struct auth_domain *clp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) const struct path *path, struct cache_req *reqp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct svc_export *exp, key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (!clp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) key.ex_client = clp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) key.ex_path = *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) key.cd = cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) exp = svc_export_lookup(&key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (exp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) err = cache_check(cd, &exp->h, reqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) trace_nfsd_exp_get_by_name(&key, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * Find the export entry for a given dentry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) static struct svc_export *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) exp_parent(struct cache_detail *cd, struct auth_domain *clp, struct path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct dentry *saved = dget(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct svc_export *exp = exp_get_by_name(cd, clp, path, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) struct dentry *parent = dget_parent(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) dput(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) path->dentry = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) exp = exp_get_by_name(cd, clp, path, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) dput(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) path->dentry = saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * Obtain the root fh on behalf of a client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * This could be done in user space, but I feel that it adds some safety
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * since its harder to fool a kernel module than a user space program.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) exp_rootfh(struct net *net, struct auth_domain *clp, char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct knfsd_fh *f, int maxsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct svc_export *exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct svc_fh fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct cache_detail *cd = nn->svc_export_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) err = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /* NB: we probably ought to check that it's NUL-terminated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (kern_path(name, 0, &path)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) printk("nfsd: exp_rootfh path not found %s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) inode = d_inode(path.dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) name, path.dentry, clp->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) inode->i_sb->s_id, inode->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) exp = exp_parent(cd, clp, &path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (IS_ERR(exp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) err = PTR_ERR(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * fh must be initialized before calling fh_compose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) fh_init(&fh, maxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (fh_compose(&fh, exp, path.dentry, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) fh_put(&fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) exp_put(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) path_put(&path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) static struct svc_export *exp_find(struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct auth_domain *clp, int fsid_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) u32 *fsidv, struct cache_req *reqp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) struct svc_export *exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct nfsd_net *nn = net_generic(cd->net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct svc_expkey *ek = exp_find_key(nn->svc_expkey_cache, clp, fsid_type, fsidv, reqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (IS_ERR(ek))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return ERR_CAST(ek);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) exp = exp_get_by_name(cd, clp, &ek->ek_path, reqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) cache_put(&ek->h, nn->svc_expkey_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (IS_ERR(exp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return ERR_CAST(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct exp_flavor_info *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) /* legacy gss-only clients are always OK: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (exp->ex_client == rqstp->rq_gssclient)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /* ip-address based client; check sec= export option: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) for (f = exp->ex_flavors; f < end; f++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (f->pseudoflavor == rqstp->rq_cred.cr_flavor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* defaults in absence of sec= options: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (exp->ex_nflavors == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (rqstp->rq_cred.cr_flavor == RPC_AUTH_NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) /* If the compound op contains a spo_must_allowed op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * it will be sent with integrity/protection which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * will have to be expressly allowed on mounts that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * don't support it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (nfsd4_spo_must_allow(rqstp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * auth_unix client) if it's available and has secinfo information;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * otherwise, will try to use rq_gssclient.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * Called from functions that handle requests; functions that do work on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * behalf of mountd are passed a single client name to use, and should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * use exp_get_by_name() or exp_find().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct svc_export *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) struct cache_detail *cd = nn->svc_export_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (rqstp->rq_client == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) goto gss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /* First try the auth_unix client: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) exp = exp_get_by_name(cd, rqstp->rq_client, path, &rqstp->rq_chandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (PTR_ERR(exp) == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) goto gss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (IS_ERR(exp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) /* If it has secinfo, assume there are no gss/... clients */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (exp->ex_nflavors > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) gss:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /* Otherwise, try falling back on gss client */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (rqstp->rq_gssclient == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) gssexp = exp_get_by_name(cd, rqstp->rq_gssclient, path, &rqstp->rq_chandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (PTR_ERR(gssexp) == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (!IS_ERR(exp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) exp_put(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return gssexp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) struct svc_export *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) struct cache_detail *cd = nn->svc_export_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (rqstp->rq_client == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) goto gss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /* First try the auth_unix client: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) exp = exp_find(cd, rqstp->rq_client, fsid_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) fsidv, &rqstp->rq_chandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (PTR_ERR(exp) == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) goto gss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (IS_ERR(exp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /* If it has secinfo, assume there are no gss/... clients */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (exp->ex_nflavors > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) gss:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /* Otherwise, try falling back on gss client */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (rqstp->rq_gssclient == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) gssexp = exp_find(cd, rqstp->rq_gssclient, fsid_type, fsidv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) &rqstp->rq_chandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (PTR_ERR(gssexp) == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (!IS_ERR(exp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) exp_put(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) return gssexp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct svc_export *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct dentry *saved = dget(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) struct svc_export *exp = rqst_exp_get_by_name(rqstp, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct dentry *parent = dget_parent(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) dput(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) path->dentry = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) exp = rqst_exp_get_by_name(rqstp, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) dput(path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) path->dentry = saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) struct svc_export *rqst_find_fsidzero_export(struct svc_rqst *rqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) u32 fsidv[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) return rqst_exp_find(rqstp, FSID_NUM, fsidv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * Called when we need the filehandle for the root of the pseudofs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) * for a given NFSv4 client. The root is defined to be the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * export point with fsid==0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) __be32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) struct svc_export *exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) __be32 rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) exp = rqst_find_fsidzero_export(rqstp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (IS_ERR(exp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) return nfserrno(PTR_ERR(exp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) exp_put(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) static struct flags {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) int flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) char *name[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) } expflags[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) { NFSEXP_READONLY, {"ro", "rw"}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) { NFSEXP_INSECURE_PORT, {"insecure", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) { NFSEXP_ALLSQUASH, {"all_squash", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) { NFSEXP_ASYNC, {"async", "sync"}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) { NFSEXP_NOREADDIRPLUS, {"nordirplus", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) { NFSEXP_NOHIDE, {"nohide", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) { NFSEXP_V4ROOT, {"v4root", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) { NFSEXP_PNFS, {"pnfs", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) { NFSEXP_SECURITY_LABEL, {"security_label", ""}},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) { 0, {"", ""}}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) static void show_expflags(struct seq_file *m, int flags, int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) struct flags *flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) int state, first = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) for (flg = expflags; flg->flag; flg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if (flg->flag & ~mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) state = (flg->flag & flags) ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (*flg->name[state])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) static void show_secinfo_flags(struct seq_file *m, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) seq_printf(m, ",");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) static bool secinfo_flags_equal(int f, int g)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) f &= NFSEXP_SECINFO_FLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) g &= NFSEXP_SECINFO_FLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return f == g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) static int show_secinfo_run(struct seq_file *m, struct exp_flavor_info **fp, struct exp_flavor_info *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) flags = (*fp)->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) seq_printf(m, ",sec=%d", (*fp)->pseudoflavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) (*fp)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) while (*fp != end && secinfo_flags_equal(flags, (*fp)->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) seq_printf(m, ":%d", (*fp)->pseudoflavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) (*fp)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) static void show_secinfo(struct seq_file *m, struct svc_export *exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct exp_flavor_info *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (exp->ex_nflavors == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) f = exp->ex_flavors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) flags = show_secinfo_run(m, &f, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (!secinfo_flags_equal(flags, exp->ex_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) show_secinfo_flags(m, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) while (f != end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) flags = show_secinfo_run(m, &f, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) show_secinfo_flags(m, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) static void exp_flags(struct seq_file *m, int flag, int fsid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fsloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct user_namespace *userns = m->file->f_cred->user_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) show_expflags(m, flag, NFSEXP_ALLFLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) if (flag & NFSEXP_FSID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) seq_printf(m, ",fsid=%d", fsid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (!uid_eq(anonu, make_kuid(userns, (uid_t)-2)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) !uid_eq(anonu, make_kuid(userns, 0x10000-2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) seq_printf(m, ",anonuid=%u", from_kuid_munged(userns, anonu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (!gid_eq(anong, make_kgid(userns, (gid_t)-2)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) !gid_eq(anong, make_kgid(userns, 0x10000-2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) seq_printf(m, ",anongid=%u", from_kgid_munged(userns, anong));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (fsloc && fsloc->locations_count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) char *loctype = (fsloc->migrated) ? "refer" : "replicas";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) seq_printf(m, ",%s=", loctype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) seq_putc(m, '@');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) for (i = 1; i < fsloc->locations_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) seq_putc(m, ';');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) seq_escape(m, fsloc->locations[i].path, ",;@ \t\n\\");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) seq_putc(m, '@');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) seq_escape(m, fsloc->locations[i].hosts, ",;@ \t\n\\");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) static int e_show(struct seq_file *m, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) struct cache_head *cp = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) struct svc_export *exp = container_of(cp, struct svc_export, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) struct cache_detail *cd = m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (p == SEQ_START_TOKEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) seq_puts(m, "# Version 1.1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) seq_puts(m, "# Path Client(Flags) # IPs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) exp_get(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (cache_check(cd, &exp->h, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) exp_put(exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) return svc_export_show(m, cd, cp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) const struct seq_operations nfs_exports_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) .start = cache_seq_start_rcu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) .next = cache_seq_next_rcu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) .stop = cache_seq_stop_rcu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) .show = e_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * Initialize the exports module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) nfsd_export_init(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) dprintk("nfsd: initializing export module (net: %x).\n", net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (IS_ERR(nn->svc_export_cache))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return PTR_ERR(nn->svc_export_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) rv = cache_register_net(nn->svc_export_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) goto destroy_export_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) nn->svc_expkey_cache = cache_create_net(&svc_expkey_cache_template, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (IS_ERR(nn->svc_expkey_cache)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) rv = PTR_ERR(nn->svc_expkey_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) goto unregister_export_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) rv = cache_register_net(nn->svc_expkey_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) goto destroy_expkey_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) destroy_expkey_cache:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) cache_destroy_net(nn->svc_expkey_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) unregister_export_cache:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) cache_unregister_net(nn->svc_export_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) destroy_export_cache:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) cache_destroy_net(nn->svc_export_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * Flush exports table - called when last nfsd thread is killed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) nfsd_export_flush(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) cache_purge(nn->svc_expkey_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) cache_purge(nn->svc_export_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) * Shutdown the exports module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) nfsd_export_shutdown(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) dprintk("nfsd: shutting down export module (net: %x).\n", net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) cache_unregister_net(nn->svc_expkey_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) cache_unregister_net(nn->svc_export_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) cache_destroy_net(nn->svc_expkey_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) cache_destroy_net(nn->svc_export_cache, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) svcauth_unix_purge(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) dprintk("nfsd: export shutdown complete (net: %x).\n", net->ns.inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) }