svcauth_unix.c 21 KB

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