^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/sunrpc/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/sunrpc/xdr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/sunrpc/svcsock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/sunrpc/svcauth.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/sunrpc/gss_api.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sunrpc/addr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/hash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/string.h>
^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 <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/user_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define RPCDBG_FACILITY RPCDBG_AUTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "netns.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * AUTHUNIX and AUTHNULL credentials are both handled here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * AUTHNULL is treated just like AUTHUNIX except that the uid/gid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * are always nobody (-2). i.e. we do the same IP address checks for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * AUTHNULL as for AUTHUNIX, and that is done here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct unix_domain {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct auth_domain h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* other stuff later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) extern struct auth_ops svcauth_null;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) extern struct auth_ops svcauth_unix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static void svcauth_unix_domain_release_rcu(struct rcu_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct unix_domain *ud = container_of(dom, struct unix_domain, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) kfree(dom->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) kfree(ud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static void svcauth_unix_domain_release(struct auth_domain *dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) call_rcu(&dom->rcu_head, svcauth_unix_domain_release_rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct auth_domain *unix_domain_find(char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct auth_domain *rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct unix_domain *new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) rv = auth_domain_find(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) while(1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (new && rv != &new->h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) svcauth_unix_domain_release(&new->h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (rv->flavour != &svcauth_unix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) auth_domain_put(rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) new = kmalloc(sizeof(*new), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (new == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) kref_init(&new->h.ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) new->h.name = kstrdup(name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (new->h.name == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) new->h.flavour = &svcauth_unix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) rv = auth_domain_lookup(name, &new->h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) EXPORT_SYMBOL_GPL(unix_domain_find);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /**************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * cache for IP address to unix_domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * as needed by AUTH_UNIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define IP_HASHBITS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define IP_HASHMAX (1<<IP_HASHBITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct ip_map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct cache_head h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) char m_class[8]; /* e.g. "nfsd" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct in6_addr m_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct unix_domain *m_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct rcu_head m_rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void ip_map_put(struct kref *kref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct cache_head *item = container_of(kref, struct cache_head, ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct ip_map *im = container_of(item, struct ip_map,h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (test_bit(CACHE_VALID, &item->flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) !test_bit(CACHE_NEGATIVE, &item->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) auth_domain_put(&im->m_client->h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) kfree_rcu(im, m_rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static inline int hash_ip6(const struct in6_addr *ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return hash_32(ipv6_addr_hash(ip), IP_HASHBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct ip_map *orig = container_of(corig, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct ip_map *new = container_of(cnew, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return strcmp(orig->m_class, new->m_class) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ipv6_addr_equal(&orig->m_addr, &new->m_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct ip_map *new = container_of(cnew, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct ip_map *item = container_of(citem, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) strcpy(new->m_class, item->m_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) new->m_addr = item->m_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void update(struct cache_head *cnew, struct cache_head *citem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct ip_map *new = container_of(cnew, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct ip_map *item = container_of(citem, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) kref_get(&item->m_client->h.ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) new->m_client = item->m_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct cache_head *ip_map_alloc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return &i->h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return sunrpc_cache_pipe_upcall(cd, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static void ip_map_request(struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct cache_head *h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) char **bpp, int *blen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) char text_addr[40];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct ip_map *im = container_of(h, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (ipv6_addr_v4mapped(&(im->m_addr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) snprintf(text_addr, 20, "%pI4", &im->m_addr.s6_addr32[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) snprintf(text_addr, 40, "%pI6", &im->m_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) qword_add(bpp, blen, im->m_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) qword_add(bpp, blen, text_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) (*bpp)[-1] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time64_t expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static int ip_map_parse(struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) char *mesg, int mlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* class ipaddress [domainname] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* should be safe just to use the start of the input buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * for scratch: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) char *buf = mesg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) char class[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct sockaddr sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct sockaddr_in s4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct sockaddr_in6 s6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) } address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct sockaddr_in6 sin6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct ip_map *ipmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct auth_domain *dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) time64_t expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (mesg[mlen-1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) mesg[mlen-1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* class */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) len = qword_get(&mesg, class, sizeof(class));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (len <= 0) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* ip address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) len = qword_get(&mesg, buf, mlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (len <= 0) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (rpc_pton(cd->net, buf, len, &address.sa, sizeof(address)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) switch (address.sa.sa_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Form a mapped IPv4 address in sin6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) sin6.sin6_family = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) &sin6.sin6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) memcpy(&sin6, &address.s6, sizeof(sin6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return -EINVAL;
^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) expiry = get_expiry(&mesg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (expiry ==0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* domainname, or empty for NEGATIVE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) len = qword_get(&mesg, buf, mlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (len < 0) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) dom = unix_domain_find(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (dom == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* IPv6 scope IDs are ignored for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (ipmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) err = __ip_map_update(cd, ipmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) container_of(dom, struct unix_domain, h),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) auth_domain_put(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) cache_flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int ip_map_show(struct seq_file *m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct cache_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct ip_map *im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct in6_addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) char *dom = "-no-domain-";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (h == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) seq_puts(m, "#class IP domain\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) im = container_of(h, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* class addr domain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) addr = im->m_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (test_bit(CACHE_VALID, &h->flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) !test_bit(CACHE_NEGATIVE, &h->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dom = im->m_client->h.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (ipv6_addr_v4mapped(&addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) seq_printf(m, "%s %pI4 %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) im->m_class, &addr.s6_addr32[3], dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) seq_printf(m, "%s %pI6 %s\n", im->m_class, &addr, dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct in6_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct ip_map ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct cache_head *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) strcpy(ip.m_class, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ip.m_addr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ch = sunrpc_cache_lookup_rcu(cd, &ip.h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) hash_str(class, IP_HASHBITS) ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) hash_ip6(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return container_of(ch, struct ip_map, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static inline struct ip_map *ip_map_lookup(struct net *net, char *class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct in6_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct sunrpc_net *sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) sn = net_generic(net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return __ip_map_lookup(sn->ip_map_cache, class, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct unix_domain *udom, time64_t expiry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct ip_map ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct cache_head *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ip.m_client = udom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ip.h.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (!udom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) set_bit(CACHE_NEGATIVE, &ip.h.flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ip.h.expiry_time = expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) hash_str(ipm->m_class, IP_HASHBITS) ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) hash_ip6(&ipm->m_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) cache_put(ch, cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) void svcauth_unix_purge(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct sunrpc_net *sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) sn = net_generic(net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) cache_purge(sn->ip_map_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) EXPORT_SYMBOL_GPL(svcauth_unix_purge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static inline struct ip_map *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ip_map_cached_get(struct svc_xprt *xprt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct ip_map *ipm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct sunrpc_net *sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) spin_lock(&xprt->xpt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ipm = xprt->xpt_auth_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (ipm != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) sn = net_generic(xprt->xpt_net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (cache_is_expired(sn->ip_map_cache, &ipm->h)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * The entry has been invalidated since it was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * remembered, e.g. by a second mount from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * same IP address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) xprt->xpt_auth_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) spin_unlock(&xprt->xpt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) cache_put(&ipm->h, sn->ip_map_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) cache_get(&ipm->h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) spin_unlock(&xprt->xpt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return ipm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) spin_lock(&xprt->xpt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (xprt->xpt_auth_cache == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* newly cached, keep the reference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) xprt->xpt_auth_cache = ipm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) ipm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) spin_unlock(&xprt->xpt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (ipm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct sunrpc_net *sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) sn = net_generic(xprt->xpt_net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) cache_put(&ipm->h, sn->ip_map_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) svcauth_unix_info_release(struct svc_xprt *xpt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct ip_map *ipm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ipm = xpt->xpt_auth_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (ipm != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct sunrpc_net *sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) sn = net_generic(xpt->xpt_net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) cache_put(&ipm->h, sn->ip_map_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /****************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * auth.unix.gid cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * simple cache to map a UID to a list of GIDs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * because AUTH_UNIX aka AUTH_SYS has a max of UNX_NGROUPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #define GID_HASHBITS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) #define GID_HASHMAX (1<<GID_HASHBITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct unix_gid {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct cache_head h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) kuid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct group_info *gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct rcu_head rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static int unix_gid_hash(kuid_t uid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static void unix_gid_put(struct kref *kref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct cache_head *item = container_of(kref, struct cache_head, ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct unix_gid *ug = container_of(item, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (test_bit(CACHE_VALID, &item->flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) !test_bit(CACHE_NEGATIVE, &item->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) put_group_info(ug->gi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) kfree_rcu(ug, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct unix_gid *orig = container_of(corig, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct unix_gid *new = container_of(cnew, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return uid_eq(orig->uid, new->uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct unix_gid *new = container_of(cnew, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct unix_gid *item = container_of(citem, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) new->uid = item->uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static void unix_gid_update(struct cache_head *cnew, struct cache_head *citem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct unix_gid *new = container_of(cnew, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct unix_gid *item = container_of(citem, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) get_group_info(item->gi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) new->gi = item->gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static struct cache_head *unix_gid_alloc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct unix_gid *g = kmalloc(sizeof(*g), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (g)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return &g->h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return sunrpc_cache_pipe_upcall_timeout(cd, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static void unix_gid_request(struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct cache_head *h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) char **bpp, int *blen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) char tuid[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct unix_gid *ug = container_of(h, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) qword_add(bpp, blen, tuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) (*bpp)[-1] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int unix_gid_parse(struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) char *mesg, int mlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /* uid expiry Ngid gid0 gid1 ... gidN-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) kuid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) int gids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) time64_t expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct unix_gid ug, *ugp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (mesg[mlen - 1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) mesg[mlen-1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) rv = get_int(&mesg, &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) uid = make_kuid(current_user_ns(), id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ug.uid = uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) expiry = get_expiry(&mesg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (expiry == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) rv = get_int(&mesg, &gids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (rv || gids < 0 || gids > 8192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ug.gi = groups_alloc(gids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (!ug.gi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) for (i = 0 ; i < gids ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) int gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) kgid_t kgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) rv = get_int(&mesg, &gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) kgid = make_kgid(current_user_ns(), gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (!gid_valid(kgid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ug.gi->gid[i] = kgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) groups_sort(ug.gi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ugp = unix_gid_lookup(cd, uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (ugp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct cache_head *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ug.h.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ug.h.expiry_time = expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) ch = sunrpc_cache_update(cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) &ug.h, &ugp->h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) unix_gid_hash(uid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (!ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) cache_put(ch, cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (ug.gi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) put_group_info(ug.gi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static int unix_gid_show(struct seq_file *m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct cache_detail *cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct cache_head *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct user_namespace *user_ns = m->file->f_cred->user_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct unix_gid *ug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int glen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (h == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) seq_puts(m, "#uid cnt: gids...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) ug = container_of(h, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (test_bit(CACHE_VALID, &h->flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) !test_bit(CACHE_NEGATIVE, &h->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) glen = ug->gi->ngroups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) glen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) for (i = 0; i < glen; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) seq_printf(m, " %d", from_kgid_munged(user_ns, ug->gi->gid[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) seq_printf(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static const struct cache_detail unix_gid_cache_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .hash_size = GID_HASHMAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) .name = "auth.unix.gid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .cache_put = unix_gid_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .cache_upcall = unix_gid_upcall,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .cache_request = unix_gid_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .cache_parse = unix_gid_parse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .cache_show = unix_gid_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .match = unix_gid_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .init = unix_gid_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .update = unix_gid_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) .alloc = unix_gid_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) int unix_gid_cache_create(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct cache_detail *cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) cd = cache_create_net(&unix_gid_cache_template, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (IS_ERR(cd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return PTR_ERR(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) err = cache_register_net(cd, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) cache_destroy_net(cd, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) sn->unix_gid_cache = cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) void unix_gid_cache_destroy(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct cache_detail *cd = sn->unix_gid_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) sn->unix_gid_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) cache_purge(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) cache_unregister_net(cd, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) cache_destroy_net(cd, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct unix_gid ug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct cache_head *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ug.uid = uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ch = sunrpc_cache_lookup_rcu(cd, &ug.h, unix_gid_hash(uid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return container_of(ch, struct unix_gid, h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct unix_gid *ug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct group_info *gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) ug = unix_gid_lookup(sn->unix_gid_cache, uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (!ug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return ERR_PTR(-EAGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ret = cache_check(sn->unix_gid_cache, &ug->h, &rqstp->rq_chandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) case -ETIMEDOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return ERR_PTR(-ESHUTDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) gi = get_group_info(ug->gi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) cache_put(&ug->h, sn->unix_gid_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return ERR_PTR(-EAGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) svcauth_unix_set_client(struct svc_rqst *rqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct sockaddr_in *sin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct sockaddr_in6 *sin6, sin6_storage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct ip_map *ipm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct group_info *gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct svc_cred *cred = &rqstp->rq_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct svc_xprt *xprt = rqstp->rq_xprt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct net *net = xprt->xpt_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) switch (rqstp->rq_addr.ss_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) sin = svc_addr_in(rqstp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) sin6 = &sin6_storage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) sin6 = svc_addr_in6(rqstp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) rqstp->rq_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (rqstp->rq_proc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return SVC_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) ipm = ip_map_cached_get(xprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (ipm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) &sin6->sin6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (ipm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return SVC_DENIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) case -ETIMEDOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return SVC_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case -EAGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return SVC_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return SVC_DENIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) rqstp->rq_client = &ipm->m_client->h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) kref_get(&rqstp->rq_client->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ip_map_cached_put(xprt, ipm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) gi = unix_gid_find(cred->cr_uid, rqstp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) switch (PTR_ERR(gi)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) case -EAGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return SVC_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return SVC_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) put_group_info(cred->cr_group_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) cred->cr_group_info = gi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return SVC_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) EXPORT_SYMBOL_GPL(svcauth_unix_set_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct kvec *argv = &rqstp->rq_arg.head[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct kvec *resv = &rqstp->rq_res.head[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct svc_cred *cred = &rqstp->rq_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (argv->iov_len < 3*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return SVC_GARBAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (svc_getu32(argv) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) dprintk("svc: bad null cred\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) *authp = rpc_autherr_badcred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return SVC_DENIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) dprintk("svc: bad null verf\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) *authp = rpc_autherr_badverf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return SVC_DENIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /* Signal that mapping to nobody uid/gid is required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) cred->cr_uid = INVALID_UID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) cred->cr_gid = INVALID_GID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) cred->cr_group_info = groups_alloc(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (cred->cr_group_info == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return SVC_CLOSE; /* kmalloc failure - client must retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* Put NULL verifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) svc_putnl(resv, RPC_AUTH_NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) svc_putnl(resv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) rqstp->rq_cred.cr_flavor = RPC_AUTH_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return SVC_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) svcauth_null_release(struct svc_rqst *rqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (rqstp->rq_client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) auth_domain_put(rqstp->rq_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) rqstp->rq_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (rqstp->rq_cred.cr_group_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) put_group_info(rqstp->rq_cred.cr_group_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) rqstp->rq_cred.cr_group_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return 0; /* don't drop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) struct auth_ops svcauth_null = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) .name = "null",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .flavour = RPC_AUTH_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .accept = svcauth_null_accept,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .release = svcauth_null_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .set_client = svcauth_unix_set_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct kvec *argv = &rqstp->rq_arg.head[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) struct kvec *resv = &rqstp->rq_res.head[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) struct svc_cred *cred = &rqstp->rq_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct user_namespace *userns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) u32 slen, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) int len = argv->iov_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if ((len -= 3*4) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return SVC_GARBAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) svc_getu32(argv); /* length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) svc_getu32(argv); /* time stamp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) slen = XDR_QUADLEN(svc_getnl(argv)); /* machname length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (slen > 64 || (len -= (slen + 3)*4) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) goto badcred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) argv->iov_len -= slen*4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * Note: we skip uid_valid()/gid_valid() checks here for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * backwards compatibility with clients that use -1 id's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * Instead, -1 uid or gid is later mapped to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * (export-specific) anonymous id by nfsd_setuser.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * Supplementary gid's will be left alone.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) userns = (rqstp->rq_xprt && rqstp->rq_xprt->xpt_cred) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) rqstp->rq_xprt->xpt_cred->user_ns : &init_user_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) cred->cr_uid = make_kuid(userns, svc_getnl(argv)); /* uid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) cred->cr_gid = make_kgid(userns, svc_getnl(argv)); /* gid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) slen = svc_getnl(argv); /* gids length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (slen > UNX_NGROUPS || (len -= (slen + 2)*4) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) goto badcred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) cred->cr_group_info = groups_alloc(slen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (cred->cr_group_info == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return SVC_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) for (i = 0; i < slen; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) kgid_t kgid = make_kgid(userns, svc_getnl(argv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) cred->cr_group_info->gid[i] = kgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) groups_sort(cred->cr_group_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) *authp = rpc_autherr_badverf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return SVC_DENIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* Put NULL verifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) svc_putnl(resv, RPC_AUTH_NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) svc_putnl(resv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) rqstp->rq_cred.cr_flavor = RPC_AUTH_UNIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return SVC_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) badcred:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) *authp = rpc_autherr_badcred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return SVC_DENIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) svcauth_unix_release(struct svc_rqst *rqstp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /* Verifier (such as it is) is already in place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (rqstp->rq_client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) auth_domain_put(rqstp->rq_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) rqstp->rq_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (rqstp->rq_cred.cr_group_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) put_group_info(rqstp->rq_cred.cr_group_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) rqstp->rq_cred.cr_group_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct auth_ops svcauth_unix = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .name = "unix",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .flavour = RPC_AUTH_UNIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .accept = svcauth_unix_accept,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .release = svcauth_unix_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .domain_release = svcauth_unix_domain_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .set_client = svcauth_unix_set_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static const struct cache_detail ip_map_cache_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) .hash_size = IP_HASHMAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) .name = "auth.unix.ip",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) .cache_put = ip_map_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) .cache_upcall = ip_map_upcall,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .cache_request = ip_map_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .cache_parse = ip_map_parse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) .cache_show = ip_map_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) .match = ip_map_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) .init = ip_map_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .update = update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) .alloc = ip_map_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int ip_map_cache_create(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) struct cache_detail *cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) cd = cache_create_net(&ip_map_cache_template, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (IS_ERR(cd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return PTR_ERR(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) err = cache_register_net(cd, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) cache_destroy_net(cd, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) sn->ip_map_cache = cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) void ip_map_cache_destroy(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct cache_detail *cd = sn->ip_map_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) sn->ip_map_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) cache_purge(cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) cache_unregister_net(cd, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) cache_destroy_net(cd, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }