svcauth_unix.c 22 KB

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