1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#define DEBUG_SUBSYSTEM S_SEC
42
43#include "../../include/linux/libcfs/libcfs.h"
44#include <linux/crypto.h>
45#include <linux/key.h>
46
47#include "../include/obd.h"
48#include "../include/obd_class.h"
49#include "../include/obd_support.h"
50#include "../include/lustre_net.h"
51#include "../include/lustre_import.h"
52#include "../include/lustre_dlm.h"
53#include "../include/lustre_sec.h"
54
55#include "ptlrpc_internal.h"
56
57
58
59
60
61static rwlock_t policy_lock;
62static struct ptlrpc_sec_policy *policies[SPTLRPC_POLICY_MAX] = {
63 NULL,
64};
65
66int sptlrpc_register_policy(struct ptlrpc_sec_policy *policy)
67{
68 __u16 number = policy->sp_policy;
69
70 LASSERT(policy->sp_name);
71 LASSERT(policy->sp_cops);
72 LASSERT(policy->sp_sops);
73
74 if (number >= SPTLRPC_POLICY_MAX)
75 return -EINVAL;
76
77 write_lock(&policy_lock);
78 if (unlikely(policies[number])) {
79 write_unlock(&policy_lock);
80 return -EALREADY;
81 }
82 policies[number] = policy;
83 write_unlock(&policy_lock);
84
85 CDEBUG(D_SEC, "%s: registered\n", policy->sp_name);
86 return 0;
87}
88EXPORT_SYMBOL(sptlrpc_register_policy);
89
90int sptlrpc_unregister_policy(struct ptlrpc_sec_policy *policy)
91{
92 __u16 number = policy->sp_policy;
93
94 LASSERT(number < SPTLRPC_POLICY_MAX);
95
96 write_lock(&policy_lock);
97 if (unlikely(policies[number] == NULL)) {
98 write_unlock(&policy_lock);
99 CERROR("%s: already unregistered\n", policy->sp_name);
100 return -EINVAL;
101 }
102
103 LASSERT(policies[number] == policy);
104 policies[number] = NULL;
105 write_unlock(&policy_lock);
106
107 CDEBUG(D_SEC, "%s: unregistered\n", policy->sp_name);
108 return 0;
109}
110EXPORT_SYMBOL(sptlrpc_unregister_policy);
111
112static
113struct ptlrpc_sec_policy *sptlrpc_wireflavor2policy(__u32 flavor)
114{
115 static DEFINE_MUTEX(load_mutex);
116 static atomic_t loaded = ATOMIC_INIT(0);
117 struct ptlrpc_sec_policy *policy;
118 __u16 number = SPTLRPC_FLVR_POLICY(flavor);
119 __u16 flag = 0;
120
121 if (number >= SPTLRPC_POLICY_MAX)
122 return NULL;
123
124 while (1) {
125 read_lock(&policy_lock);
126 policy = policies[number];
127 if (policy && !try_module_get(policy->sp_owner))
128 policy = NULL;
129 if (policy == NULL)
130 flag = atomic_read(&loaded);
131 read_unlock(&policy_lock);
132
133 if (policy != NULL || flag != 0 ||
134 number != SPTLRPC_POLICY_GSS)
135 break;
136
137
138 mutex_lock(&load_mutex);
139 if (atomic_read(&loaded) == 0) {
140 if (request_module("ptlrpc_gss") == 0)
141 CDEBUG(D_SEC,
142 "module ptlrpc_gss loaded on demand\n");
143 else
144 CERROR("Unable to load module ptlrpc_gss\n");
145
146 atomic_set(&loaded, 1);
147 }
148 mutex_unlock(&load_mutex);
149 }
150
151 return policy;
152}
153
154__u32 sptlrpc_name2flavor_base(const char *name)
155{
156 if (!strcmp(name, "null"))
157 return SPTLRPC_FLVR_NULL;
158 if (!strcmp(name, "plain"))
159 return SPTLRPC_FLVR_PLAIN;
160 if (!strcmp(name, "krb5n"))
161 return SPTLRPC_FLVR_KRB5N;
162 if (!strcmp(name, "krb5a"))
163 return SPTLRPC_FLVR_KRB5A;
164 if (!strcmp(name, "krb5i"))
165 return SPTLRPC_FLVR_KRB5I;
166 if (!strcmp(name, "krb5p"))
167 return SPTLRPC_FLVR_KRB5P;
168
169 return SPTLRPC_FLVR_INVALID;
170}
171EXPORT_SYMBOL(sptlrpc_name2flavor_base);
172
173const char *sptlrpc_flavor2name_base(__u32 flvr)
174{
175 __u32 base = SPTLRPC_FLVR_BASE(flvr);
176
177 if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_NULL))
178 return "null";
179 else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_PLAIN))
180 return "plain";
181 else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_KRB5N))
182 return "krb5n";
183 else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_KRB5A))
184 return "krb5a";
185 else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_KRB5I))
186 return "krb5i";
187 else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_KRB5P))
188 return "krb5p";
189
190 CERROR("invalid wire flavor 0x%x\n", flvr);
191 return "invalid";
192}
193EXPORT_SYMBOL(sptlrpc_flavor2name_base);
194
195char *sptlrpc_flavor2name_bulk(struct sptlrpc_flavor *sf,
196 char *buf, int bufsize)
197{
198 if (SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_PLAIN)
199 snprintf(buf, bufsize, "hash:%s",
200 sptlrpc_get_hash_name(sf->u_bulk.hash.hash_alg));
201 else
202 snprintf(buf, bufsize, "%s",
203 sptlrpc_flavor2name_base(sf->sf_rpc));
204
205 buf[bufsize - 1] = '\0';
206 return buf;
207}
208EXPORT_SYMBOL(sptlrpc_flavor2name_bulk);
209
210char *sptlrpc_flavor2name(struct sptlrpc_flavor *sf, char *buf, int bufsize)
211{
212 strlcpy(buf, sptlrpc_flavor2name_base(sf->sf_rpc), bufsize);
213
214
215
216
217
218 if (SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_PLAIN) {
219 char bspec[16];
220
221 bspec[0] = '-';
222 sptlrpc_flavor2name_bulk(sf, &bspec[1], sizeof(bspec) - 1);
223 strlcat(buf, bspec, bufsize);
224 }
225
226 return buf;
227}
228EXPORT_SYMBOL(sptlrpc_flavor2name);
229
230char *sptlrpc_secflags2str(__u32 flags, char *buf, int bufsize)
231{
232 buf[0] = '\0';
233
234 if (flags & PTLRPC_SEC_FL_REVERSE)
235 strlcat(buf, "reverse,", bufsize);
236 if (flags & PTLRPC_SEC_FL_ROOTONLY)
237 strlcat(buf, "rootonly,", bufsize);
238 if (flags & PTLRPC_SEC_FL_UDESC)
239 strlcat(buf, "udesc,", bufsize);
240 if (flags & PTLRPC_SEC_FL_BULK)
241 strlcat(buf, "bulk,", bufsize);
242 if (buf[0] == '\0')
243 strlcat(buf, "-,", bufsize);
244
245 return buf;
246}
247EXPORT_SYMBOL(sptlrpc_secflags2str);
248
249
250
251
252
253static
254struct ptlrpc_cli_ctx *get_my_ctx(struct ptlrpc_sec *sec)
255{
256 struct vfs_cred vcred;
257 int create = 1, remove_dead = 1;
258
259 LASSERT(sec);
260 LASSERT(sec->ps_policy->sp_cops->lookup_ctx);
261
262 if (sec->ps_flvr.sf_flags & (PTLRPC_SEC_FL_REVERSE |
263 PTLRPC_SEC_FL_ROOTONLY)) {
264 vcred.vc_uid = 0;
265 vcred.vc_gid = 0;
266 if (sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_REVERSE) {
267 create = 0;
268 remove_dead = 0;
269 }
270 } else {
271 vcred.vc_uid = from_kuid(&init_user_ns, current_uid());
272 vcred.vc_gid = from_kgid(&init_user_ns, current_gid());
273 }
274
275 return sec->ps_policy->sp_cops->lookup_ctx(sec, &vcred,
276 create, remove_dead);
277}
278
279struct ptlrpc_cli_ctx *sptlrpc_cli_ctx_get(struct ptlrpc_cli_ctx *ctx)
280{
281 atomic_inc(&ctx->cc_refcount);
282 return ctx;
283}
284EXPORT_SYMBOL(sptlrpc_cli_ctx_get);
285
286void sptlrpc_cli_ctx_put(struct ptlrpc_cli_ctx *ctx, int sync)
287{
288 struct ptlrpc_sec *sec = ctx->cc_sec;
289
290 LASSERT(sec);
291 LASSERT_ATOMIC_POS(&ctx->cc_refcount);
292
293 if (!atomic_dec_and_test(&ctx->cc_refcount))
294 return;
295
296 sec->ps_policy->sp_cops->release_ctx(sec, ctx, sync);
297}
298EXPORT_SYMBOL(sptlrpc_cli_ctx_put);
299
300
301
302
303
304
305void sptlrpc_cli_ctx_expire(struct ptlrpc_cli_ctx *ctx)
306{
307 LASSERT(ctx->cc_ops->force_die);
308 ctx->cc_ops->force_die(ctx, 0);
309}
310EXPORT_SYMBOL(sptlrpc_cli_ctx_expire);
311
312
313
314
315
316void sptlrpc_cli_ctx_wakeup(struct ptlrpc_cli_ctx *ctx)
317{
318 struct ptlrpc_request *req, *next;
319
320 spin_lock(&ctx->cc_lock);
321 list_for_each_entry_safe(req, next, &ctx->cc_req_list,
322 rq_ctx_chain) {
323 list_del_init(&req->rq_ctx_chain);
324 ptlrpc_client_wake_req(req);
325 }
326 spin_unlock(&ctx->cc_lock);
327}
328EXPORT_SYMBOL(sptlrpc_cli_ctx_wakeup);
329
330int sptlrpc_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize)
331{
332 LASSERT(ctx->cc_ops);
333
334 if (ctx->cc_ops->display == NULL)
335 return 0;
336
337 return ctx->cc_ops->display(ctx, buf, bufsize);
338}
339
340static int import_sec_check_expire(struct obd_import *imp)
341{
342 int adapt = 0;
343
344 spin_lock(&imp->imp_lock);
345 if (imp->imp_sec_expire &&
346 imp->imp_sec_expire < get_seconds()) {
347 adapt = 1;
348 imp->imp_sec_expire = 0;
349 }
350 spin_unlock(&imp->imp_lock);
351
352 if (!adapt)
353 return 0;
354
355 CDEBUG(D_SEC, "found delayed sec adapt expired, do it now\n");
356 return sptlrpc_import_sec_adapt(imp, NULL, NULL);
357}
358
359static int import_sec_validate_get(struct obd_import *imp,
360 struct ptlrpc_sec **sec)
361{
362 int rc;
363
364 if (unlikely(imp->imp_sec_expire)) {
365 rc = import_sec_check_expire(imp);
366 if (rc)
367 return rc;
368 }
369
370 *sec = sptlrpc_import_sec_ref(imp);
371 if (*sec == NULL) {
372 CERROR("import %p (%s) with no sec\n",
373 imp, ptlrpc_import_state_name(imp->imp_state));
374 return -EACCES;
375 }
376
377 if (unlikely((*sec)->ps_dying)) {
378 CERROR("attempt to use dying sec %p\n", sec);
379 sptlrpc_sec_put(*sec);
380 return -EACCES;
381 }
382
383 return 0;
384}
385
386
387
388
389
390
391
392
393int sptlrpc_req_get_ctx(struct ptlrpc_request *req)
394{
395 struct obd_import *imp = req->rq_import;
396 struct ptlrpc_sec *sec;
397 int rc;
398
399 LASSERT(!req->rq_cli_ctx);
400 LASSERT(imp);
401
402 rc = import_sec_validate_get(imp, &sec);
403 if (rc)
404 return rc;
405
406 req->rq_cli_ctx = get_my_ctx(sec);
407
408 sptlrpc_sec_put(sec);
409
410 if (!req->rq_cli_ctx) {
411 CERROR("req %p: fail to get context\n", req);
412 return -ENOMEM;
413 }
414
415 return 0;
416}
417
418
419
420
421
422
423
424
425
426
427void sptlrpc_req_put_ctx(struct ptlrpc_request *req, int sync)
428{
429 LASSERT(req);
430 LASSERT(req->rq_cli_ctx);
431
432
433
434
435 if (!list_empty(&req->rq_ctx_chain)) {
436 spin_lock(&req->rq_cli_ctx->cc_lock);
437 list_del_init(&req->rq_ctx_chain);
438 spin_unlock(&req->rq_cli_ctx->cc_lock);
439 }
440
441 sptlrpc_cli_ctx_put(req->rq_cli_ctx, sync);
442 req->rq_cli_ctx = NULL;
443}
444
445static
446int sptlrpc_req_ctx_switch(struct ptlrpc_request *req,
447 struct ptlrpc_cli_ctx *oldctx,
448 struct ptlrpc_cli_ctx *newctx)
449{
450 struct sptlrpc_flavor old_flvr;
451 char *reqmsg = NULL;
452 int reqmsg_size;
453 int rc = 0;
454
455 LASSERT(req->rq_reqmsg);
456 LASSERT(req->rq_reqlen);
457 LASSERT(req->rq_replen);
458
459 CDEBUG(D_SEC, "req %p: switch ctx %p(%u->%s) -> %p(%u->%s), switch sec %p(%s) -> %p(%s)\n",
460 req,
461 oldctx, oldctx->cc_vcred.vc_uid, sec2target_str(oldctx->cc_sec),
462 newctx, newctx->cc_vcred.vc_uid, sec2target_str(newctx->cc_sec),
463 oldctx->cc_sec, oldctx->cc_sec->ps_policy->sp_name,
464 newctx->cc_sec, newctx->cc_sec->ps_policy->sp_name);
465
466
467 old_flvr = req->rq_flvr;
468
469
470 reqmsg_size = req->rq_reqlen;
471 if (reqmsg_size != 0) {
472 reqmsg = libcfs_kvzalloc(reqmsg_size, GFP_NOFS);
473 if (reqmsg == NULL)
474 return -ENOMEM;
475 memcpy(reqmsg, req->rq_reqmsg, reqmsg_size);
476 }
477
478
479 req->rq_cli_ctx = oldctx;
480 sptlrpc_cli_free_reqbuf(req);
481 sptlrpc_cli_free_repbuf(req);
482 req->rq_cli_ctx = newctx;
483
484
485 sptlrpc_req_set_flavor(req, 0);
486
487
488
489
490 if (reqmsg_size != 0) {
491 rc = sptlrpc_cli_alloc_reqbuf(req, reqmsg_size);
492 if (!rc) {
493 LASSERT(req->rq_reqmsg);
494 memcpy(req->rq_reqmsg, reqmsg, reqmsg_size);
495 } else {
496 CWARN("failed to alloc reqbuf: %d\n", rc);
497 req->rq_flvr = old_flvr;
498 }
499
500 kvfree(reqmsg);
501 }
502 return rc;
503}
504
505
506
507
508
509
510
511
512
513int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req)
514{
515 struct ptlrpc_cli_ctx *oldctx = req->rq_cli_ctx;
516 struct ptlrpc_cli_ctx *newctx;
517 int rc;
518
519 LASSERT(oldctx);
520
521 sptlrpc_cli_ctx_get(oldctx);
522 sptlrpc_req_put_ctx(req, 0);
523
524 rc = sptlrpc_req_get_ctx(req);
525 if (unlikely(rc)) {
526 LASSERT(!req->rq_cli_ctx);
527
528
529 req->rq_cli_ctx = oldctx;
530 return rc;
531 }
532
533 newctx = req->rq_cli_ctx;
534 LASSERT(newctx);
535
536 if (unlikely(newctx == oldctx &&
537 test_bit(PTLRPC_CTX_DEAD_BIT, &oldctx->cc_flags))) {
538
539
540
541 CDEBUG(D_SEC,
542 "ctx (%p, fl %lx) doesn't switch, relax a little bit\n",
543 newctx, newctx->cc_flags);
544
545 set_current_state(TASK_INTERRUPTIBLE);
546 schedule_timeout(HZ);
547 } else {
548
549
550
551
552 rc = sptlrpc_req_ctx_switch(req, oldctx, newctx);
553 if (rc) {
554
555 sptlrpc_req_put_ctx(req, 0);
556 req->rq_cli_ctx = oldctx;
557 return rc;
558 }
559
560 LASSERT(req->rq_cli_ctx == newctx);
561 }
562
563 sptlrpc_cli_ctx_put(oldctx, 1);
564 return 0;
565}
566EXPORT_SYMBOL(sptlrpc_req_replace_dead_ctx);
567
568static
569int ctx_check_refresh(struct ptlrpc_cli_ctx *ctx)
570{
571 if (cli_ctx_is_refreshed(ctx))
572 return 1;
573 return 0;
574}
575
576static
577int ctx_refresh_timeout(void *data)
578{
579 struct ptlrpc_request *req = data;
580 int rc;
581
582
583 lustre_msg_set_conn_cnt(req->rq_reqmsg, req->rq_import->imp_conn_cnt);
584
585 rc = ptlrpc_expire_one_request(req, 1);
586
587
588
589
590
591
592 if (rc == 0)
593 req->rq_cli_ctx->cc_ops->force_die(req->rq_cli_ctx, 0);
594 return rc;
595}
596
597static
598void ctx_refresh_interrupt(void *data)
599{
600 struct ptlrpc_request *req = data;
601
602 spin_lock(&req->rq_lock);
603 req->rq_intr = 1;
604 spin_unlock(&req->rq_lock);
605}
606
607static
608void req_off_ctx_list(struct ptlrpc_request *req, struct ptlrpc_cli_ctx *ctx)
609{
610 spin_lock(&ctx->cc_lock);
611 if (!list_empty(&req->rq_ctx_chain))
612 list_del_init(&req->rq_ctx_chain);
613 spin_unlock(&ctx->cc_lock);
614}
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout)
631{
632 struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
633 struct ptlrpc_sec *sec;
634 struct l_wait_info lwi;
635 int rc;
636
637 LASSERT(ctx);
638
639 if (req->rq_ctx_init || req->rq_ctx_fini)
640 return 0;
641
642
643
644
645
646
647again:
648 rc = import_sec_validate_get(req->rq_import, &sec);
649 if (rc)
650 return rc;
651
652 if (sec->ps_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
653 CDEBUG(D_SEC, "req %p: flavor has changed %x -> %x\n",
654 req, req->rq_flvr.sf_rpc, sec->ps_flvr.sf_rpc);
655 req_off_ctx_list(req, ctx);
656 sptlrpc_req_replace_dead_ctx(req);
657 ctx = req->rq_cli_ctx;
658 }
659 sptlrpc_sec_put(sec);
660
661 if (cli_ctx_is_eternal(ctx))
662 return 0;
663
664 if (unlikely(test_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags))) {
665 LASSERT(ctx->cc_ops->refresh);
666 ctx->cc_ops->refresh(ctx);
667 }
668 LASSERT(test_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags) == 0);
669
670 LASSERT(ctx->cc_ops->validate);
671 if (ctx->cc_ops->validate(ctx) == 0) {
672 req_off_ctx_list(req, ctx);
673 return 0;
674 }
675
676 if (unlikely(test_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags))) {
677 spin_lock(&req->rq_lock);
678 req->rq_err = 1;
679 spin_unlock(&req->rq_lock);
680 req_off_ctx_list(req, ctx);
681 return -EPERM;
682 }
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711 if (test_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags) &&
712 unlikely(req->rq_reqmsg) &&
713 lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT) {
714 req_off_ctx_list(req, ctx);
715 return 0;
716 }
717
718 if (unlikely(test_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags))) {
719 req_off_ctx_list(req, ctx);
720
721
722
723 if (req->rq_import->imp_deactive) {
724 spin_lock(&req->rq_lock);
725 req->rq_err = 1;
726 spin_unlock(&req->rq_lock);
727 return -EINTR;
728 }
729
730 rc = sptlrpc_req_replace_dead_ctx(req);
731 if (rc) {
732 LASSERT(ctx == req->rq_cli_ctx);
733 CERROR("req %p: failed to replace dead ctx %p: %d\n",
734 req, ctx, rc);
735 spin_lock(&req->rq_lock);
736 req->rq_err = 1;
737 spin_unlock(&req->rq_lock);
738 return rc;
739 }
740
741 ctx = req->rq_cli_ctx;
742 goto again;
743 }
744
745
746
747
748
749 spin_lock(&ctx->cc_lock);
750 if (list_empty(&req->rq_ctx_chain))
751 list_add(&req->rq_ctx_chain, &ctx->cc_req_list);
752 spin_unlock(&ctx->cc_lock);
753
754 if (timeout < 0)
755 return -EWOULDBLOCK;
756
757
758 LASSERT(req->rq_receiving_reply == 0);
759 spin_lock(&req->rq_lock);
760 req->rq_err = 0;
761 req->rq_timedout = 0;
762 req->rq_resend = 0;
763 req->rq_restart = 0;
764 spin_unlock(&req->rq_lock);
765
766 lwi = LWI_TIMEOUT_INTR(timeout * HZ, ctx_refresh_timeout,
767 ctx_refresh_interrupt, req);
768 rc = l_wait_event(req->rq_reply_waitq, ctx_check_refresh(ctx), &lwi);
769
770
771
772
773
774
775
776
777
778
779
780 if (!cli_ctx_is_refreshed(ctx)) {
781
782 req_off_ctx_list(req, ctx);
783
784 LASSERT(rc != 0);
785 return rc;
786 }
787
788 goto again;
789}
790
791
792
793
794
795
796
797
798void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode)
799{
800 struct ptlrpc_sec *sec;
801
802 LASSERT(req->rq_import);
803 LASSERT(req->rq_cli_ctx);
804 LASSERT(req->rq_cli_ctx->cc_sec);
805 LASSERT(req->rq_bulk_read == 0 || req->rq_bulk_write == 0);
806
807
808 switch (opcode) {
809 case OST_READ:
810 case MDS_READPAGE:
811 case MGS_CONFIG_READ:
812 case OBD_IDX_READ:
813 req->rq_bulk_read = 1;
814 break;
815 case OST_WRITE:
816 case MDS_WRITEPAGE:
817 req->rq_bulk_write = 1;
818 break;
819 case SEC_CTX_INIT:
820 req->rq_ctx_init = 1;
821 break;
822 case SEC_CTX_FINI:
823 req->rq_ctx_fini = 1;
824 break;
825 case 0:
826
827 LASSERT(req->rq_ctx_init == 0);
828 LASSERT(req->rq_ctx_fini == 0);
829
830
831 req->rq_pack_udesc = 0;
832 req->rq_pack_bulk = 0;
833 break;
834 }
835
836 sec = req->rq_cli_ctx->cc_sec;
837
838 spin_lock(&sec->ps_lock);
839 req->rq_flvr = sec->ps_flvr;
840 spin_unlock(&sec->ps_lock);
841
842
843
844 if (unlikely(req->rq_ctx_init))
845 flvr_set_svc(&req->rq_flvr.sf_rpc, SPTLRPC_SVC_NULL);
846 else if (unlikely(req->rq_ctx_fini))
847 flvr_set_svc(&req->rq_flvr.sf_rpc, SPTLRPC_SVC_INTG);
848
849
850 if ((sec->ps_flvr.sf_flags & PTLRPC_SEC_FL_UDESC) &&
851 (req->rq_flvr.sf_rpc != SPTLRPC_FLVR_NULL))
852 req->rq_pack_udesc = 1;
853
854
855 if ((req->rq_bulk_read || req->rq_bulk_write) &&
856 sptlrpc_flavor_has_bulk(&req->rq_flvr))
857 req->rq_pack_bulk = 1;
858}
859
860void sptlrpc_request_out_callback(struct ptlrpc_request *req)
861{
862 if (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc) != SPTLRPC_SVC_PRIV)
863 return;
864
865 LASSERT(req->rq_clrbuf);
866 if (req->rq_pool || !req->rq_reqbuf)
867 return;
868
869 kfree(req->rq_reqbuf);
870 req->rq_reqbuf = NULL;
871 req->rq_reqbuf_len = 0;
872}
873
874
875
876
877
878
879int sptlrpc_import_check_ctx(struct obd_import *imp)
880{
881 struct ptlrpc_sec *sec;
882 struct ptlrpc_cli_ctx *ctx;
883 struct ptlrpc_request *req = NULL;
884 int rc;
885
886 might_sleep();
887
888 sec = sptlrpc_import_sec_ref(imp);
889 ctx = get_my_ctx(sec);
890 sptlrpc_sec_put(sec);
891
892 if (!ctx)
893 return -ENOMEM;
894
895 if (cli_ctx_is_eternal(ctx) ||
896 ctx->cc_ops->validate(ctx) == 0) {
897 sptlrpc_cli_ctx_put(ctx, 1);
898 return 0;
899 }
900
901 if (cli_ctx_is_error(ctx)) {
902 sptlrpc_cli_ctx_put(ctx, 1);
903 return -EACCES;
904 }
905
906 req = ptlrpc_request_cache_alloc(GFP_NOFS);
907 if (!req)
908 return -ENOMEM;
909
910 spin_lock_init(&req->rq_lock);
911 atomic_set(&req->rq_refcount, 10000);
912 INIT_LIST_HEAD(&req->rq_ctx_chain);
913 init_waitqueue_head(&req->rq_reply_waitq);
914 init_waitqueue_head(&req->rq_set_waitq);
915 req->rq_import = imp;
916 req->rq_flvr = sec->ps_flvr;
917 req->rq_cli_ctx = ctx;
918
919 rc = sptlrpc_req_refresh_ctx(req, 0);
920 LASSERT(list_empty(&req->rq_ctx_chain));
921 sptlrpc_cli_ctx_put(req->rq_cli_ctx, 1);
922 ptlrpc_request_cache_free(req);
923
924 return rc;
925}
926
927
928
929
930
931
932int sptlrpc_cli_wrap_request(struct ptlrpc_request *req)
933{
934 struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
935 int rc = 0;
936
937 LASSERT(ctx);
938 LASSERT(ctx->cc_sec);
939 LASSERT(req->rq_reqbuf || req->rq_clrbuf);
940
941
942
943
944 if (req->rq_bulk) {
945 rc = sptlrpc_cli_wrap_bulk(req, req->rq_bulk);
946 if (rc)
947 return rc;
948 }
949
950 switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
951 case SPTLRPC_SVC_NULL:
952 case SPTLRPC_SVC_AUTH:
953 case SPTLRPC_SVC_INTG:
954 LASSERT(ctx->cc_ops->sign);
955 rc = ctx->cc_ops->sign(ctx, req);
956 break;
957 case SPTLRPC_SVC_PRIV:
958 LASSERT(ctx->cc_ops->seal);
959 rc = ctx->cc_ops->seal(ctx, req);
960 break;
961 default:
962 LBUG();
963 }
964
965 if (rc == 0) {
966 LASSERT(req->rq_reqdata_len);
967 LASSERT(req->rq_reqdata_len % 8 == 0);
968 LASSERT(req->rq_reqdata_len <= req->rq_reqbuf_len);
969 }
970
971 return rc;
972}
973
974static int do_cli_unwrap_reply(struct ptlrpc_request *req)
975{
976 struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
977 int rc;
978
979 LASSERT(ctx);
980 LASSERT(ctx->cc_sec);
981 LASSERT(req->rq_repbuf);
982 LASSERT(req->rq_repdata);
983 LASSERT(req->rq_repmsg == NULL);
984
985 req->rq_rep_swab_mask = 0;
986
987 rc = __lustre_unpack_msg(req->rq_repdata, req->rq_repdata_len);
988 switch (rc) {
989 case 1:
990 lustre_set_rep_swabbed(req, MSG_PTLRPC_HEADER_OFF);
991 case 0:
992 break;
993 default:
994 CERROR("failed unpack reply: x%llu\n", req->rq_xid);
995 return -EPROTO;
996 }
997
998 if (req->rq_repdata_len < sizeof(struct lustre_msg)) {
999 CERROR("replied data length %d too small\n",
1000 req->rq_repdata_len);
1001 return -EPROTO;
1002 }
1003
1004 if (SPTLRPC_FLVR_POLICY(req->rq_repdata->lm_secflvr) !=
1005 SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc)) {
1006 CERROR("reply policy %u doesn't match request policy %u\n",
1007 SPTLRPC_FLVR_POLICY(req->rq_repdata->lm_secflvr),
1008 SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc));
1009 return -EPROTO;
1010 }
1011
1012 switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
1013 case SPTLRPC_SVC_NULL:
1014 case SPTLRPC_SVC_AUTH:
1015 case SPTLRPC_SVC_INTG:
1016 LASSERT(ctx->cc_ops->verify);
1017 rc = ctx->cc_ops->verify(ctx, req);
1018 break;
1019 case SPTLRPC_SVC_PRIV:
1020 LASSERT(ctx->cc_ops->unseal);
1021 rc = ctx->cc_ops->unseal(ctx, req);
1022 break;
1023 default:
1024 LBUG();
1025 }
1026 LASSERT(rc || req->rq_repmsg || req->rq_resend);
1027
1028 if (SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) != SPTLRPC_POLICY_NULL &&
1029 !req->rq_ctx_init)
1030 req->rq_rep_swab_mask = 0;
1031 return rc;
1032}
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042int sptlrpc_cli_unwrap_reply(struct ptlrpc_request *req)
1043{
1044 LASSERT(req->rq_repbuf);
1045 LASSERT(req->rq_repdata == NULL);
1046 LASSERT(req->rq_repmsg == NULL);
1047 LASSERT(req->rq_reply_off + req->rq_nob_received <= req->rq_repbuf_len);
1048
1049 if (req->rq_reply_off == 0 &&
1050 (lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT)) {
1051 CERROR("real reply with offset 0\n");
1052 return -EPROTO;
1053 }
1054
1055 if (req->rq_reply_off % 8 != 0) {
1056 CERROR("reply at odd offset %u\n", req->rq_reply_off);
1057 return -EPROTO;
1058 }
1059
1060 req->rq_repdata = (struct lustre_msg *)
1061 (req->rq_repbuf + req->rq_reply_off);
1062 req->rq_repdata_len = req->rq_nob_received;
1063
1064 return do_cli_unwrap_reply(req);
1065}
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req,
1083 struct ptlrpc_request **req_ret)
1084{
1085 struct ptlrpc_request *early_req;
1086 char *early_buf;
1087 int early_bufsz, early_size;
1088 int rc;
1089
1090 early_req = ptlrpc_request_cache_alloc(GFP_NOFS);
1091 if (early_req == NULL)
1092 return -ENOMEM;
1093
1094 early_size = req->rq_nob_received;
1095 early_bufsz = size_roundup_power2(early_size);
1096 early_buf = libcfs_kvzalloc(early_bufsz, GFP_NOFS);
1097 if (early_buf == NULL) {
1098 rc = -ENOMEM;
1099 goto err_req;
1100 }
1101
1102
1103 spin_lock(&req->rq_lock);
1104
1105 if (req->rq_replied) {
1106 spin_unlock(&req->rq_lock);
1107 rc = -EALREADY;
1108 goto err_buf;
1109 }
1110
1111 LASSERT(req->rq_repbuf);
1112 LASSERT(req->rq_repdata == NULL);
1113 LASSERT(req->rq_repmsg == NULL);
1114
1115 if (req->rq_reply_off != 0) {
1116 CERROR("early reply with offset %u\n", req->rq_reply_off);
1117 spin_unlock(&req->rq_lock);
1118 rc = -EPROTO;
1119 goto err_buf;
1120 }
1121
1122 if (req->rq_nob_received != early_size) {
1123
1124 CERROR("data size has changed from %u to %u\n",
1125 early_size, req->rq_nob_received);
1126 spin_unlock(&req->rq_lock);
1127 rc = -EINVAL;
1128 goto err_buf;
1129 }
1130
1131 if (req->rq_nob_received < sizeof(struct lustre_msg)) {
1132 CERROR("early reply length %d too small\n",
1133 req->rq_nob_received);
1134 spin_unlock(&req->rq_lock);
1135 rc = -EALREADY;
1136 goto err_buf;
1137 }
1138
1139 memcpy(early_buf, req->rq_repbuf, early_size);
1140 spin_unlock(&req->rq_lock);
1141
1142 spin_lock_init(&early_req->rq_lock);
1143 early_req->rq_cli_ctx = sptlrpc_cli_ctx_get(req->rq_cli_ctx);
1144 early_req->rq_flvr = req->rq_flvr;
1145 early_req->rq_repbuf = early_buf;
1146 early_req->rq_repbuf_len = early_bufsz;
1147 early_req->rq_repdata = (struct lustre_msg *) early_buf;
1148 early_req->rq_repdata_len = early_size;
1149 early_req->rq_early = 1;
1150 early_req->rq_reqmsg = req->rq_reqmsg;
1151
1152 rc = do_cli_unwrap_reply(early_req);
1153 if (rc) {
1154 DEBUG_REQ(D_ADAPTTO, early_req,
1155 "error %d unwrap early reply", rc);
1156 goto err_ctx;
1157 }
1158
1159 LASSERT(early_req->rq_repmsg);
1160 *req_ret = early_req;
1161 return 0;
1162
1163err_ctx:
1164 sptlrpc_cli_ctx_put(early_req->rq_cli_ctx, 1);
1165err_buf:
1166 kvfree(early_buf);
1167err_req:
1168 ptlrpc_request_cache_free(early_req);
1169 return rc;
1170}
1171
1172
1173
1174
1175
1176
1177void sptlrpc_cli_finish_early_reply(struct ptlrpc_request *early_req)
1178{
1179 LASSERT(early_req->rq_repbuf);
1180 LASSERT(early_req->rq_repdata);
1181 LASSERT(early_req->rq_repmsg);
1182
1183 sptlrpc_cli_ctx_put(early_req->rq_cli_ctx, 1);
1184 kvfree(early_req->rq_repbuf);
1185 ptlrpc_request_cache_free(early_req);
1186}
1187
1188
1189
1190
1191
1192
1193
1194
1195static atomic_t sptlrpc_sec_id = ATOMIC_INIT(1);
1196
1197int sptlrpc_get_next_secid(void)
1198{
1199 return atomic_inc_return(&sptlrpc_sec_id);
1200}
1201EXPORT_SYMBOL(sptlrpc_get_next_secid);
1202
1203
1204
1205
1206
1207static int sec_cop_flush_ctx_cache(struct ptlrpc_sec *sec, uid_t uid,
1208 int grace, int force)
1209{
1210 struct ptlrpc_sec_policy *policy = sec->ps_policy;
1211
1212 LASSERT(policy->sp_cops);
1213 LASSERT(policy->sp_cops->flush_ctx_cache);
1214
1215 return policy->sp_cops->flush_ctx_cache(sec, uid, grace, force);
1216}
1217
1218static void sec_cop_destroy_sec(struct ptlrpc_sec *sec)
1219{
1220 struct ptlrpc_sec_policy *policy = sec->ps_policy;
1221
1222 LASSERT_ATOMIC_ZERO(&sec->ps_refcount);
1223 LASSERT_ATOMIC_ZERO(&sec->ps_nctx);
1224 LASSERT(policy->sp_cops->destroy_sec);
1225
1226 CDEBUG(D_SEC, "%s@%p: being destroyed\n", sec->ps_policy->sp_name, sec);
1227
1228 policy->sp_cops->destroy_sec(sec);
1229 sptlrpc_policy_put(policy);
1230}
1231
1232void sptlrpc_sec_destroy(struct ptlrpc_sec *sec)
1233{
1234 sec_cop_destroy_sec(sec);
1235}
1236EXPORT_SYMBOL(sptlrpc_sec_destroy);
1237
1238static void sptlrpc_sec_kill(struct ptlrpc_sec *sec)
1239{
1240 LASSERT_ATOMIC_POS(&sec->ps_refcount);
1241
1242 if (sec->ps_policy->sp_cops->kill_sec) {
1243 sec->ps_policy->sp_cops->kill_sec(sec);
1244
1245 sec_cop_flush_ctx_cache(sec, -1, 1, 1);
1246 }
1247}
1248
1249struct ptlrpc_sec *sptlrpc_sec_get(struct ptlrpc_sec *sec)
1250{
1251 if (sec)
1252 atomic_inc(&sec->ps_refcount);
1253
1254 return sec;
1255}
1256EXPORT_SYMBOL(sptlrpc_sec_get);
1257
1258void sptlrpc_sec_put(struct ptlrpc_sec *sec)
1259{
1260 if (sec) {
1261 LASSERT_ATOMIC_POS(&sec->ps_refcount);
1262
1263 if (atomic_dec_and_test(&sec->ps_refcount)) {
1264 sptlrpc_gc_del_sec(sec);
1265 sec_cop_destroy_sec(sec);
1266 }
1267 }
1268}
1269EXPORT_SYMBOL(sptlrpc_sec_put);
1270
1271
1272
1273
1274static
1275struct ptlrpc_sec *sptlrpc_sec_create(struct obd_import *imp,
1276 struct ptlrpc_svc_ctx *svc_ctx,
1277 struct sptlrpc_flavor *sf,
1278 enum lustre_sec_part sp)
1279{
1280 struct ptlrpc_sec_policy *policy;
1281 struct ptlrpc_sec *sec;
1282 char str[32];
1283
1284 if (svc_ctx) {
1285 LASSERT(imp->imp_dlm_fake == 1);
1286
1287 CDEBUG(D_SEC, "%s %s: reverse sec using flavor %s\n",
1288 imp->imp_obd->obd_type->typ_name,
1289 imp->imp_obd->obd_name,
1290 sptlrpc_flavor2name(sf, str, sizeof(str)));
1291
1292 policy = sptlrpc_policy_get(svc_ctx->sc_policy);
1293 sf->sf_flags |= PTLRPC_SEC_FL_REVERSE | PTLRPC_SEC_FL_ROOTONLY;
1294 } else {
1295 LASSERT(imp->imp_dlm_fake == 0);
1296
1297 CDEBUG(D_SEC, "%s %s: select security flavor %s\n",
1298 imp->imp_obd->obd_type->typ_name,
1299 imp->imp_obd->obd_name,
1300 sptlrpc_flavor2name(sf, str, sizeof(str)));
1301
1302 policy = sptlrpc_wireflavor2policy(sf->sf_rpc);
1303 if (!policy) {
1304 CERROR("invalid flavor 0x%x\n", sf->sf_rpc);
1305 return NULL;
1306 }
1307 }
1308
1309 sec = policy->sp_cops->create_sec(imp, svc_ctx, sf);
1310 if (sec) {
1311 atomic_inc(&sec->ps_refcount);
1312
1313 sec->ps_part = sp;
1314
1315 if (sec->ps_gc_interval && policy->sp_cops->gc_ctx)
1316 sptlrpc_gc_add_sec(sec);
1317 } else {
1318 sptlrpc_policy_put(policy);
1319 }
1320
1321 return sec;
1322}
1323
1324struct ptlrpc_sec *sptlrpc_import_sec_ref(struct obd_import *imp)
1325{
1326 struct ptlrpc_sec *sec;
1327
1328 spin_lock(&imp->imp_lock);
1329 sec = sptlrpc_sec_get(imp->imp_sec);
1330 spin_unlock(&imp->imp_lock);
1331
1332 return sec;
1333}
1334EXPORT_SYMBOL(sptlrpc_import_sec_ref);
1335
1336static void sptlrpc_import_sec_install(struct obd_import *imp,
1337 struct ptlrpc_sec *sec)
1338{
1339 struct ptlrpc_sec *old_sec;
1340
1341 LASSERT_ATOMIC_POS(&sec->ps_refcount);
1342
1343 spin_lock(&imp->imp_lock);
1344 old_sec = imp->imp_sec;
1345 imp->imp_sec = sec;
1346 spin_unlock(&imp->imp_lock);
1347
1348 if (old_sec) {
1349 sptlrpc_sec_kill(old_sec);
1350
1351
1352 sptlrpc_sec_put(old_sec);
1353 }
1354}
1355
1356static inline
1357int flavor_equal(struct sptlrpc_flavor *sf1, struct sptlrpc_flavor *sf2)
1358{
1359 return (memcmp(sf1, sf2, sizeof(*sf1)) == 0);
1360}
1361
1362static inline
1363void flavor_copy(struct sptlrpc_flavor *dst, struct sptlrpc_flavor *src)
1364{
1365 *dst = *src;
1366}
1367
1368static void sptlrpc_import_sec_adapt_inplace(struct obd_import *imp,
1369 struct ptlrpc_sec *sec,
1370 struct sptlrpc_flavor *sf)
1371{
1372 char str1[32], str2[32];
1373
1374 if (sec->ps_flvr.sf_flags != sf->sf_flags)
1375 CDEBUG(D_SEC, "changing sec flags: %s -> %s\n",
1376 sptlrpc_secflags2str(sec->ps_flvr.sf_flags,
1377 str1, sizeof(str1)),
1378 sptlrpc_secflags2str(sf->sf_flags,
1379 str2, sizeof(str2)));
1380
1381 spin_lock(&sec->ps_lock);
1382 flavor_copy(&sec->ps_flvr, sf);
1383 spin_unlock(&sec->ps_lock);
1384}
1385
1386
1387
1388
1389
1390
1391
1392
1393int sptlrpc_import_sec_adapt(struct obd_import *imp,
1394 struct ptlrpc_svc_ctx *svc_ctx,
1395 struct sptlrpc_flavor *flvr)
1396{
1397 struct ptlrpc_connection *conn;
1398 struct sptlrpc_flavor sf;
1399 struct ptlrpc_sec *sec, *newsec;
1400 enum lustre_sec_part sp;
1401 char str[24];
1402 int rc = 0;
1403
1404 might_sleep();
1405
1406 if (imp == NULL)
1407 return 0;
1408
1409 conn = imp->imp_connection;
1410
1411 if (svc_ctx == NULL) {
1412 struct client_obd *cliobd = &imp->imp_obd->u.cli;
1413
1414
1415
1416
1417 if (cliobd->cl_sp_me == LUSTRE_SP_MGC)
1418 sf = cliobd->cl_flvr_mgc;
1419 else
1420 sptlrpc_conf_choose_flavor(cliobd->cl_sp_me,
1421 cliobd->cl_sp_to,
1422 &cliobd->cl_target_uuid,
1423 conn->c_self, &sf);
1424
1425 sp = imp->imp_obd->u.cli.cl_sp_me;
1426 } else {
1427
1428 sf = *flvr;
1429
1430 if (sf.sf_rpc != SPTLRPC_FLVR_NULL)
1431 sf.sf_flags = PTLRPC_SEC_FL_REVERSE |
1432 PTLRPC_SEC_FL_ROOTONLY;
1433
1434 sp = sptlrpc_target_sec_part(imp->imp_obd);
1435 }
1436
1437 sec = sptlrpc_import_sec_ref(imp);
1438 if (sec) {
1439 char str2[24];
1440
1441 if (flavor_equal(&sf, &sec->ps_flvr))
1442 goto out;
1443
1444 CDEBUG(D_SEC, "import %s->%s: changing flavor %s -> %s\n",
1445 imp->imp_obd->obd_name,
1446 obd_uuid2str(&conn->c_remote_uuid),
1447 sptlrpc_flavor2name(&sec->ps_flvr, str, sizeof(str)),
1448 sptlrpc_flavor2name(&sf, str2, sizeof(str2)));
1449
1450 if (SPTLRPC_FLVR_POLICY(sf.sf_rpc) ==
1451 SPTLRPC_FLVR_POLICY(sec->ps_flvr.sf_rpc) &&
1452 SPTLRPC_FLVR_MECH(sf.sf_rpc) ==
1453 SPTLRPC_FLVR_MECH(sec->ps_flvr.sf_rpc)) {
1454 sptlrpc_import_sec_adapt_inplace(imp, sec, &sf);
1455 goto out;
1456 }
1457 } else if (SPTLRPC_FLVR_BASE(sf.sf_rpc) !=
1458 SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_NULL)) {
1459 CDEBUG(D_SEC, "import %s->%s netid %x: select flavor %s\n",
1460 imp->imp_obd->obd_name,
1461 obd_uuid2str(&conn->c_remote_uuid),
1462 LNET_NIDNET(conn->c_self),
1463 sptlrpc_flavor2name(&sf, str, sizeof(str)));
1464 }
1465
1466 mutex_lock(&imp->imp_sec_mutex);
1467
1468 newsec = sptlrpc_sec_create(imp, svc_ctx, &sf, sp);
1469 if (newsec) {
1470 sptlrpc_import_sec_install(imp, newsec);
1471 } else {
1472 CERROR("import %s->%s: failed to create new sec\n",
1473 imp->imp_obd->obd_name,
1474 obd_uuid2str(&conn->c_remote_uuid));
1475 rc = -EPERM;
1476 }
1477
1478 mutex_unlock(&imp->imp_sec_mutex);
1479out:
1480 sptlrpc_sec_put(sec);
1481 return rc;
1482}
1483
1484void sptlrpc_import_sec_put(struct obd_import *imp)
1485{
1486 if (imp->imp_sec) {
1487 sptlrpc_sec_kill(imp->imp_sec);
1488
1489 sptlrpc_sec_put(imp->imp_sec);
1490 imp->imp_sec = NULL;
1491 }
1492}
1493
1494static void import_flush_ctx_common(struct obd_import *imp,
1495 uid_t uid, int grace, int force)
1496{
1497 struct ptlrpc_sec *sec;
1498
1499 if (imp == NULL)
1500 return;
1501
1502 sec = sptlrpc_import_sec_ref(imp);
1503 if (sec == NULL)
1504 return;
1505
1506 sec_cop_flush_ctx_cache(sec, uid, grace, force);
1507 sptlrpc_sec_put(sec);
1508}
1509
1510void sptlrpc_import_flush_root_ctx(struct obd_import *imp)
1511{
1512
1513
1514 import_flush_ctx_common(imp, 0, 1, 1);
1515}
1516
1517void sptlrpc_import_flush_my_ctx(struct obd_import *imp)
1518{
1519 import_flush_ctx_common(imp, from_kuid(&init_user_ns, current_uid()),
1520 1, 1);
1521}
1522EXPORT_SYMBOL(sptlrpc_import_flush_my_ctx);
1523
1524void sptlrpc_import_flush_all_ctx(struct obd_import *imp)
1525{
1526 import_flush_ctx_common(imp, -1, 1, 1);
1527}
1528EXPORT_SYMBOL(sptlrpc_import_flush_all_ctx);
1529
1530
1531
1532
1533
1534int sptlrpc_cli_alloc_reqbuf(struct ptlrpc_request *req, int msgsize)
1535{
1536 struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
1537 struct ptlrpc_sec_policy *policy;
1538 int rc;
1539
1540 LASSERT(ctx);
1541 LASSERT(ctx->cc_sec);
1542 LASSERT(ctx->cc_sec->ps_policy);
1543 LASSERT(req->rq_reqmsg == NULL);
1544 LASSERT_ATOMIC_POS(&ctx->cc_refcount);
1545
1546 policy = ctx->cc_sec->ps_policy;
1547 rc = policy->sp_cops->alloc_reqbuf(ctx->cc_sec, req, msgsize);
1548 if (!rc) {
1549 LASSERT(req->rq_reqmsg);
1550 LASSERT(req->rq_reqbuf || req->rq_clrbuf);
1551
1552
1553 if (req->rq_pool)
1554 memset(req->rq_reqmsg, 0, msgsize);
1555 }
1556
1557 return rc;
1558}
1559
1560
1561
1562
1563
1564void sptlrpc_cli_free_reqbuf(struct ptlrpc_request *req)
1565{
1566 struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
1567 struct ptlrpc_sec_policy *policy;
1568
1569 LASSERT(ctx);
1570 LASSERT(ctx->cc_sec);
1571 LASSERT(ctx->cc_sec->ps_policy);
1572 LASSERT_ATOMIC_POS(&ctx->cc_refcount);
1573
1574 if (req->rq_reqbuf == NULL && req->rq_clrbuf == NULL)
1575 return;
1576
1577 policy = ctx->cc_sec->ps_policy;
1578 policy->sp_cops->free_reqbuf(ctx->cc_sec, req);
1579 req->rq_reqmsg = NULL;
1580}
1581
1582
1583
1584
1585void _sptlrpc_enlarge_msg_inplace(struct lustre_msg *msg,
1586 int segment, int newsize)
1587{
1588 void *src, *dst;
1589 int oldsize, oldmsg_size, movesize;
1590
1591 LASSERT(segment < msg->lm_bufcount);
1592 LASSERT(msg->lm_buflens[segment] <= newsize);
1593
1594 if (msg->lm_buflens[segment] == newsize)
1595 return;
1596
1597
1598 if (segment == msg->lm_bufcount - 1) {
1599 msg->lm_buflens[segment] = newsize;
1600 return;
1601 }
1602
1603 oldsize = msg->lm_buflens[segment];
1604
1605 src = lustre_msg_buf(msg, segment + 1, 0);
1606 msg->lm_buflens[segment] = newsize;
1607 dst = lustre_msg_buf(msg, segment + 1, 0);
1608 msg->lm_buflens[segment] = oldsize;
1609
1610
1611 LASSERT(msg->lm_magic == LUSTRE_MSG_MAGIC_V2);
1612 oldmsg_size = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
1613 movesize = oldmsg_size - ((unsigned long) src - (unsigned long) msg);
1614 LASSERT(movesize >= 0);
1615
1616 if (movesize)
1617 memmove(dst, src, movesize);
1618
1619
1620
1621
1622 msg->lm_buflens[segment] = newsize;
1623}
1624EXPORT_SYMBOL(_sptlrpc_enlarge_msg_inplace);
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635int sptlrpc_cli_enlarge_reqbuf(struct ptlrpc_request *req,
1636 int segment, int newsize)
1637{
1638 struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
1639 struct ptlrpc_sec_cops *cops;
1640 struct lustre_msg *msg = req->rq_reqmsg;
1641
1642 LASSERT(ctx);
1643 LASSERT(msg);
1644 LASSERT(msg->lm_bufcount > segment);
1645 LASSERT(msg->lm_buflens[segment] <= newsize);
1646
1647 if (msg->lm_buflens[segment] == newsize)
1648 return 0;
1649
1650 cops = ctx->cc_sec->ps_policy->sp_cops;
1651 LASSERT(cops->enlarge_reqbuf);
1652 return cops->enlarge_reqbuf(ctx->cc_sec, req, segment, newsize);
1653}
1654EXPORT_SYMBOL(sptlrpc_cli_enlarge_reqbuf);
1655
1656
1657
1658
1659
1660
1661int sptlrpc_cli_alloc_repbuf(struct ptlrpc_request *req, int msgsize)
1662{
1663 struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
1664 struct ptlrpc_sec_policy *policy;
1665
1666 LASSERT(ctx);
1667 LASSERT(ctx->cc_sec);
1668 LASSERT(ctx->cc_sec->ps_policy);
1669
1670 if (req->rq_repbuf)
1671 return 0;
1672
1673 policy = ctx->cc_sec->ps_policy;
1674 return policy->sp_cops->alloc_repbuf(ctx->cc_sec, req, msgsize);
1675}
1676
1677
1678
1679
1680
1681void sptlrpc_cli_free_repbuf(struct ptlrpc_request *req)
1682{
1683 struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
1684 struct ptlrpc_sec_policy *policy;
1685
1686 LASSERT(ctx);
1687 LASSERT(ctx->cc_sec);
1688 LASSERT(ctx->cc_sec->ps_policy);
1689 LASSERT_ATOMIC_POS(&ctx->cc_refcount);
1690
1691 if (req->rq_repbuf == NULL)
1692 return;
1693 LASSERT(req->rq_repbuf_len);
1694
1695 policy = ctx->cc_sec->ps_policy;
1696 policy->sp_cops->free_repbuf(ctx->cc_sec, req);
1697 req->rq_repmsg = NULL;
1698}
1699
1700int sptlrpc_cli_install_rvs_ctx(struct obd_import *imp,
1701 struct ptlrpc_cli_ctx *ctx)
1702{
1703 struct ptlrpc_sec_policy *policy = ctx->cc_sec->ps_policy;
1704
1705 if (!policy->sp_cops->install_rctx)
1706 return 0;
1707 return policy->sp_cops->install_rctx(imp, ctx->cc_sec, ctx);
1708}
1709
1710int sptlrpc_svc_install_rvs_ctx(struct obd_import *imp,
1711 struct ptlrpc_svc_ctx *ctx)
1712{
1713 struct ptlrpc_sec_policy *policy = ctx->sc_policy;
1714
1715 if (!policy->sp_sops->install_rctx)
1716 return 0;
1717 return policy->sp_sops->install_rctx(imp, ctx);
1718}
1719
1720
1721
1722
1723
1724static int flavor_allowed(struct sptlrpc_flavor *exp,
1725 struct ptlrpc_request *req)
1726{
1727 struct sptlrpc_flavor *flvr = &req->rq_flvr;
1728
1729 if (exp->sf_rpc == SPTLRPC_FLVR_ANY || exp->sf_rpc == flvr->sf_rpc)
1730 return 1;
1731
1732 if ((req->rq_ctx_init || req->rq_ctx_fini) &&
1733 SPTLRPC_FLVR_POLICY(exp->sf_rpc) ==
1734 SPTLRPC_FLVR_POLICY(flvr->sf_rpc) &&
1735 SPTLRPC_FLVR_MECH(exp->sf_rpc) == SPTLRPC_FLVR_MECH(flvr->sf_rpc))
1736 return 1;
1737
1738 return 0;
1739}
1740
1741#define EXP_FLVR_UPDATE_EXPIRE (OBD_TIMEOUT_DEFAULT + 10)
1742
1743
1744
1745
1746
1747
1748int sptlrpc_target_export_check(struct obd_export *exp,
1749 struct ptlrpc_request *req)
1750{
1751 struct sptlrpc_flavor flavor;
1752
1753 if (exp == NULL)
1754 return 0;
1755
1756
1757
1758 if (exp->exp_imp_reverse == NULL)
1759 return 0;
1760
1761
1762 if (req->rq_ctx_fini)
1763 return 0;
1764
1765 spin_lock(&exp->exp_lock);
1766
1767
1768
1769
1770
1771
1772 if (unlikely(exp->exp_flvr_changed) &&
1773 flavor_allowed(&exp->exp_flvr_old[1], req)) {
1774
1775
1776 CDEBUG(D_SEC, "exp %p: just changed: %x->%x\n", exp,
1777 exp->exp_flvr.sf_rpc, exp->exp_flvr_old[1].sf_rpc);
1778 flavor = exp->exp_flvr_old[1];
1779 exp->exp_flvr_old[1] = exp->exp_flvr_old[0];
1780 exp->exp_flvr_expire[1] = exp->exp_flvr_expire[0];
1781 exp->exp_flvr_old[0] = exp->exp_flvr;
1782 exp->exp_flvr_expire[0] = get_seconds() +
1783 EXP_FLVR_UPDATE_EXPIRE;
1784 exp->exp_flvr = flavor;
1785
1786
1787 exp->exp_flvr_changed = 0;
1788 LASSERT(exp->exp_flvr_adapt == 1);
1789
1790
1791 if (req->rq_auth_gss &&
1792 !(req->rq_ctx_init &&
1793 (req->rq_auth_usr_root || req->rq_auth_usr_mdt ||
1794 req->rq_auth_usr_ost))) {
1795 spin_unlock(&exp->exp_lock);
1796 CDEBUG(D_SEC, "is good but not root(%d:%d:%d:%d:%d)\n",
1797 req->rq_auth_gss, req->rq_ctx_init,
1798 req->rq_auth_usr_root, req->rq_auth_usr_mdt,
1799 req->rq_auth_usr_ost);
1800 return 0;
1801 }
1802
1803 exp->exp_flvr_adapt = 0;
1804 spin_unlock(&exp->exp_lock);
1805
1806 return sptlrpc_import_sec_adapt(exp->exp_imp_reverse,
1807 req->rq_svc_ctx, &flavor);
1808 }
1809
1810
1811
1812 if (likely(flavor_allowed(&exp->exp_flvr, req))) {
1813
1814
1815 if (!req->rq_auth_gss || !req->rq_ctx_init ||
1816 (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt &&
1817 !req->rq_auth_usr_ost)) {
1818 spin_unlock(&exp->exp_lock);
1819 return 0;
1820 }
1821
1822
1823
1824
1825 if (exp->exp_flvr_changed) {
1826 LASSERT(exp->exp_flvr_adapt);
1827 spin_unlock(&exp->exp_lock);
1828 return 0;
1829 }
1830
1831 if (exp->exp_flvr_adapt) {
1832 exp->exp_flvr_adapt = 0;
1833 CDEBUG(D_SEC, "exp %p (%x|%x|%x): do delayed adapt\n",
1834 exp, exp->exp_flvr.sf_rpc,
1835 exp->exp_flvr_old[0].sf_rpc,
1836 exp->exp_flvr_old[1].sf_rpc);
1837 flavor = exp->exp_flvr;
1838 spin_unlock(&exp->exp_lock);
1839
1840 return sptlrpc_import_sec_adapt(exp->exp_imp_reverse,
1841 req->rq_svc_ctx,
1842 &flavor);
1843 } else {
1844 CDEBUG(D_SEC, "exp %p (%x|%x|%x): is current flavor, install rvs ctx\n",
1845 exp, exp->exp_flvr.sf_rpc,
1846 exp->exp_flvr_old[0].sf_rpc,
1847 exp->exp_flvr_old[1].sf_rpc);
1848 spin_unlock(&exp->exp_lock);
1849
1850 return sptlrpc_svc_install_rvs_ctx(exp->exp_imp_reverse,
1851 req->rq_svc_ctx);
1852 }
1853 }
1854
1855 if (exp->exp_flvr_expire[0]) {
1856 if (exp->exp_flvr_expire[0] >= get_seconds()) {
1857 if (flavor_allowed(&exp->exp_flvr_old[0], req)) {
1858 CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the middle one (" CFS_DURATION_T ")\n", exp,
1859 exp->exp_flvr.sf_rpc,
1860 exp->exp_flvr_old[0].sf_rpc,
1861 exp->exp_flvr_old[1].sf_rpc,
1862 exp->exp_flvr_expire[0] -
1863 get_seconds());
1864 spin_unlock(&exp->exp_lock);
1865 return 0;
1866 }
1867 } else {
1868 CDEBUG(D_SEC, "mark middle expired\n");
1869 exp->exp_flvr_expire[0] = 0;
1870 }
1871 CDEBUG(D_SEC, "exp %p (%x|%x|%x): %x not match middle\n", exp,
1872 exp->exp_flvr.sf_rpc,
1873 exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc,
1874 req->rq_flvr.sf_rpc);
1875 }
1876
1877
1878
1879 if (exp->exp_flvr_changed == 0 && exp->exp_flvr_expire[1]) {
1880 if (exp->exp_flvr_expire[1] >= get_seconds()) {
1881 if (flavor_allowed(&exp->exp_flvr_old[1], req)) {
1882 CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the oldest one (" CFS_DURATION_T ")\n",
1883 exp,
1884 exp->exp_flvr.sf_rpc,
1885 exp->exp_flvr_old[0].sf_rpc,
1886 exp->exp_flvr_old[1].sf_rpc,
1887 exp->exp_flvr_expire[1] -
1888 get_seconds());
1889 spin_unlock(&exp->exp_lock);
1890 return 0;
1891 }
1892 } else {
1893 CDEBUG(D_SEC, "mark oldest expired\n");
1894 exp->exp_flvr_expire[1] = 0;
1895 }
1896 CDEBUG(D_SEC, "exp %p (%x|%x|%x): %x not match found\n",
1897 exp, exp->exp_flvr.sf_rpc,
1898 exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc,
1899 req->rq_flvr.sf_rpc);
1900 } else {
1901 CDEBUG(D_SEC, "exp %p (%x|%x|%x): skip the last one\n",
1902 exp, exp->exp_flvr.sf_rpc, exp->exp_flvr_old[0].sf_rpc,
1903 exp->exp_flvr_old[1].sf_rpc);
1904 }
1905
1906 spin_unlock(&exp->exp_lock);
1907
1908 CWARN("exp %p(%s): req %p (%u|%u|%u|%u|%u|%u) with unauthorized flavor %x, expect %x|%x(%+ld)|%x(%+ld)\n",
1909 exp, exp->exp_obd->obd_name,
1910 req, req->rq_auth_gss, req->rq_ctx_init, req->rq_ctx_fini,
1911 req->rq_auth_usr_root, req->rq_auth_usr_mdt, req->rq_auth_usr_ost,
1912 req->rq_flvr.sf_rpc,
1913 exp->exp_flvr.sf_rpc,
1914 exp->exp_flvr_old[0].sf_rpc,
1915 exp->exp_flvr_expire[0] ?
1916 (unsigned long) (exp->exp_flvr_expire[0] -
1917 get_seconds()) : 0,
1918 exp->exp_flvr_old[1].sf_rpc,
1919 exp->exp_flvr_expire[1] ?
1920 (unsigned long) (exp->exp_flvr_expire[1] -
1921 get_seconds()) : 0);
1922 return -EACCES;
1923}
1924EXPORT_SYMBOL(sptlrpc_target_export_check);
1925
1926void sptlrpc_target_update_exp_flavor(struct obd_device *obd,
1927 struct sptlrpc_rule_set *rset)
1928{
1929 struct obd_export *exp;
1930 struct sptlrpc_flavor new_flvr;
1931
1932 LASSERT(obd);
1933
1934 spin_lock(&obd->obd_dev_lock);
1935
1936 list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain) {
1937 if (exp->exp_connection == NULL)
1938 continue;
1939
1940
1941
1942
1943 spin_lock(&exp->exp_lock);
1944 sptlrpc_target_choose_flavor(rset, exp->exp_sp_peer,
1945 exp->exp_connection->c_peer.nid,
1946 &new_flvr);
1947 if (exp->exp_flvr_changed ||
1948 !flavor_equal(&new_flvr, &exp->exp_flvr)) {
1949 exp->exp_flvr_old[1] = new_flvr;
1950 exp->exp_flvr_expire[1] = 0;
1951 exp->exp_flvr_changed = 1;
1952 exp->exp_flvr_adapt = 1;
1953
1954 CDEBUG(D_SEC, "exp %p (%s): updated flavor %x->%x\n",
1955 exp, sptlrpc_part2name(exp->exp_sp_peer),
1956 exp->exp_flvr.sf_rpc,
1957 exp->exp_flvr_old[1].sf_rpc);
1958 }
1959 spin_unlock(&exp->exp_lock);
1960 }
1961
1962 spin_unlock(&obd->obd_dev_lock);
1963}
1964EXPORT_SYMBOL(sptlrpc_target_update_exp_flavor);
1965
1966static int sptlrpc_svc_check_from(struct ptlrpc_request *req, int svc_rc)
1967{
1968
1969 if (!req->rq_auth_gss || svc_rc == SECSVC_DROP)
1970 return svc_rc;
1971
1972 switch (req->rq_sp_from) {
1973 case LUSTRE_SP_CLI:
1974 if (req->rq_auth_usr_mdt || req->rq_auth_usr_ost) {
1975 DEBUG_REQ(D_ERROR, req, "faked source CLI");
1976 svc_rc = SECSVC_DROP;
1977 }
1978 break;
1979 case LUSTRE_SP_MDT:
1980 if (!req->rq_auth_usr_mdt) {
1981 DEBUG_REQ(D_ERROR, req, "faked source MDT");
1982 svc_rc = SECSVC_DROP;
1983 }
1984 break;
1985 case LUSTRE_SP_OST:
1986 if (!req->rq_auth_usr_ost) {
1987 DEBUG_REQ(D_ERROR, req, "faked source OST");
1988 svc_rc = SECSVC_DROP;
1989 }
1990 break;
1991 case LUSTRE_SP_MGS:
1992 case LUSTRE_SP_MGC:
1993 if (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt &&
1994 !req->rq_auth_usr_ost) {
1995 DEBUG_REQ(D_ERROR, req, "faked source MGC/MGS");
1996 svc_rc = SECSVC_DROP;
1997 }
1998 break;
1999 case LUSTRE_SP_ANY:
2000 default:
2001 DEBUG_REQ(D_ERROR, req, "invalid source %u", req->rq_sp_from);
2002 svc_rc = SECSVC_DROP;
2003 }
2004
2005 return svc_rc;
2006}
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req)
2020{
2021 struct ptlrpc_sec_policy *policy;
2022 struct lustre_msg *msg = req->rq_reqbuf;
2023 int rc;
2024
2025 LASSERT(msg);
2026 LASSERT(req->rq_reqmsg == NULL);
2027 LASSERT(req->rq_repmsg == NULL);
2028 LASSERT(req->rq_svc_ctx == NULL);
2029
2030 req->rq_req_swab_mask = 0;
2031
2032 rc = __lustre_unpack_msg(msg, req->rq_reqdata_len);
2033 switch (rc) {
2034 case 1:
2035 lustre_set_req_swabbed(req, MSG_PTLRPC_HEADER_OFF);
2036 case 0:
2037 break;
2038 default:
2039 CERROR("error unpacking request from %s x%llu\n",
2040 libcfs_id2str(req->rq_peer), req->rq_xid);
2041 return SECSVC_DROP;
2042 }
2043
2044 req->rq_flvr.sf_rpc = WIRE_FLVR(msg->lm_secflvr);
2045 req->rq_sp_from = LUSTRE_SP_ANY;
2046 req->rq_auth_uid = -1;
2047 req->rq_auth_mapped_uid = -1;
2048
2049 policy = sptlrpc_wireflavor2policy(req->rq_flvr.sf_rpc);
2050 if (!policy) {
2051 CERROR("unsupported rpc flavor %x\n", req->rq_flvr.sf_rpc);
2052 return SECSVC_DROP;
2053 }
2054
2055 LASSERT(policy->sp_sops->accept);
2056 rc = policy->sp_sops->accept(req);
2057 sptlrpc_policy_put(policy);
2058 LASSERT(req->rq_reqmsg || rc != SECSVC_OK);
2059 LASSERT(req->rq_svc_ctx || rc == SECSVC_DROP);
2060
2061
2062
2063
2064
2065 if (SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) != SPTLRPC_POLICY_NULL)
2066 req->rq_req_swab_mask = 0;
2067
2068
2069 rc = sptlrpc_svc_check_from(req, rc);
2070 return rc;
2071}
2072
2073
2074
2075
2076
2077
2078int sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
2079{
2080 struct ptlrpc_sec_policy *policy;
2081 struct ptlrpc_reply_state *rs;
2082 int rc;
2083
2084 LASSERT(req->rq_svc_ctx);
2085 LASSERT(req->rq_svc_ctx->sc_policy);
2086
2087 policy = req->rq_svc_ctx->sc_policy;
2088 LASSERT(policy->sp_sops->alloc_rs);
2089
2090 rc = policy->sp_sops->alloc_rs(req, msglen);
2091 if (unlikely(rc == -ENOMEM)) {
2092 struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt;
2093 if (svcpt->scp_service->srv_max_reply_size <
2094 msglen + sizeof(struct ptlrpc_reply_state)) {
2095
2096 CERROR("size of message is too big (%zd), %d allowed",
2097 msglen + sizeof(struct ptlrpc_reply_state),
2098 svcpt->scp_service->srv_max_reply_size);
2099 return -ENOMEM;
2100 }
2101
2102
2103 rs = lustre_get_emerg_rs(svcpt);
2104 if (rs == NULL)
2105 return -ENOMEM;
2106
2107 req->rq_reply_state = rs;
2108 rc = policy->sp_sops->alloc_rs(req, msglen);
2109 if (rc) {
2110 lustre_put_emerg_rs(rs);
2111 req->rq_reply_state = NULL;
2112 }
2113 }
2114
2115 LASSERT(rc != 0 ||
2116 (req->rq_reply_state && req->rq_reply_state->rs_msg));
2117
2118 return rc;
2119}
2120
2121
2122
2123
2124
2125
2126
2127int sptlrpc_svc_wrap_reply(struct ptlrpc_request *req)
2128{
2129 struct ptlrpc_sec_policy *policy;
2130 int rc;
2131
2132 LASSERT(req->rq_svc_ctx);
2133 LASSERT(req->rq_svc_ctx->sc_policy);
2134
2135 policy = req->rq_svc_ctx->sc_policy;
2136 LASSERT(policy->sp_sops->authorize);
2137
2138 rc = policy->sp_sops->authorize(req);
2139 LASSERT(rc || req->rq_reply_state->rs_repdata_len);
2140
2141 return rc;
2142}
2143
2144
2145
2146
2147void sptlrpc_svc_free_rs(struct ptlrpc_reply_state *rs)
2148{
2149 struct ptlrpc_sec_policy *policy;
2150 unsigned int prealloc;
2151
2152 LASSERT(rs->rs_svc_ctx);
2153 LASSERT(rs->rs_svc_ctx->sc_policy);
2154
2155 policy = rs->rs_svc_ctx->sc_policy;
2156 LASSERT(policy->sp_sops->free_rs);
2157
2158 prealloc = rs->rs_prealloc;
2159 policy->sp_sops->free_rs(rs);
2160
2161 if (prealloc)
2162 lustre_put_emerg_rs(rs);
2163}
2164
2165void sptlrpc_svc_ctx_addref(struct ptlrpc_request *req)
2166{
2167 struct ptlrpc_svc_ctx *ctx = req->rq_svc_ctx;
2168
2169 if (ctx != NULL)
2170 atomic_inc(&ctx->sc_refcount);
2171}
2172
2173void sptlrpc_svc_ctx_decref(struct ptlrpc_request *req)
2174{
2175 struct ptlrpc_svc_ctx *ctx = req->rq_svc_ctx;
2176
2177 if (ctx == NULL)
2178 return;
2179
2180 LASSERT_ATOMIC_POS(&ctx->sc_refcount);
2181 if (atomic_dec_and_test(&ctx->sc_refcount)) {
2182 if (ctx->sc_policy->sp_sops->free_ctx)
2183 ctx->sc_policy->sp_sops->free_ctx(ctx);
2184 }
2185 req->rq_svc_ctx = NULL;
2186}
2187
2188void sptlrpc_svc_ctx_invalidate(struct ptlrpc_request *req)
2189{
2190 struct ptlrpc_svc_ctx *ctx = req->rq_svc_ctx;
2191
2192 if (ctx == NULL)
2193 return;
2194
2195 LASSERT_ATOMIC_POS(&ctx->sc_refcount);
2196 if (ctx->sc_policy->sp_sops->invalidate_ctx)
2197 ctx->sc_policy->sp_sops->invalidate_ctx(ctx);
2198}
2199EXPORT_SYMBOL(sptlrpc_svc_ctx_invalidate);
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209int sptlrpc_cli_wrap_bulk(struct ptlrpc_request *req,
2210 struct ptlrpc_bulk_desc *desc)
2211{
2212 struct ptlrpc_cli_ctx *ctx;
2213
2214 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
2215
2216 if (!req->rq_pack_bulk)
2217 return 0;
2218
2219 ctx = req->rq_cli_ctx;
2220 if (ctx->cc_ops->wrap_bulk)
2221 return ctx->cc_ops->wrap_bulk(ctx, req, desc);
2222 return 0;
2223}
2224EXPORT_SYMBOL(sptlrpc_cli_wrap_bulk);
2225
2226
2227
2228
2229
2230int sptlrpc_cli_unwrap_bulk_read(struct ptlrpc_request *req,
2231 struct ptlrpc_bulk_desc *desc,
2232 int nob)
2233{
2234 struct ptlrpc_cli_ctx *ctx;
2235 int rc;
2236
2237 LASSERT(req->rq_bulk_read && !req->rq_bulk_write);
2238
2239 if (!req->rq_pack_bulk)
2240 return desc->bd_nob_transferred;
2241
2242 ctx = req->rq_cli_ctx;
2243 if (ctx->cc_ops->unwrap_bulk) {
2244 rc = ctx->cc_ops->unwrap_bulk(ctx, req, desc);
2245 if (rc < 0)
2246 return rc;
2247 }
2248 return desc->bd_nob_transferred;
2249}
2250EXPORT_SYMBOL(sptlrpc_cli_unwrap_bulk_read);
2251
2252
2253
2254
2255
2256int sptlrpc_cli_unwrap_bulk_write(struct ptlrpc_request *req,
2257 struct ptlrpc_bulk_desc *desc)
2258{
2259 struct ptlrpc_cli_ctx *ctx;
2260 int rc;
2261
2262 LASSERT(!req->rq_bulk_read && req->rq_bulk_write);
2263
2264 if (!req->rq_pack_bulk)
2265 return 0;
2266
2267 ctx = req->rq_cli_ctx;
2268 if (ctx->cc_ops->unwrap_bulk) {
2269 rc = ctx->cc_ops->unwrap_bulk(ctx, req, desc);
2270 if (rc < 0)
2271 return rc;
2272 }
2273
2274
2275
2276
2277
2278 if (desc->bd_nob != desc->bd_nob_transferred) {
2279 CERROR("nob %d doesn't match transferred nob %d",
2280 desc->bd_nob, desc->bd_nob_transferred);
2281 return -EPROTO;
2282 }
2283
2284 return 0;
2285}
2286EXPORT_SYMBOL(sptlrpc_cli_unwrap_bulk_write);
2287
2288
2289
2290
2291
2292
2293int sptlrpc_current_user_desc_size(void)
2294{
2295 int ngroups;
2296
2297 ngroups = current_ngroups;
2298
2299 if (ngroups > LUSTRE_MAX_GROUPS)
2300 ngroups = LUSTRE_MAX_GROUPS;
2301 return sptlrpc_user_desc_size(ngroups);
2302}
2303EXPORT_SYMBOL(sptlrpc_current_user_desc_size);
2304
2305int sptlrpc_pack_user_desc(struct lustre_msg *msg, int offset)
2306{
2307 struct ptlrpc_user_desc *pud;
2308
2309 pud = lustre_msg_buf(msg, offset, 0);
2310
2311 pud->pud_uid = from_kuid(&init_user_ns, current_uid());
2312 pud->pud_gid = from_kgid(&init_user_ns, current_gid());
2313 pud->pud_fsuid = from_kuid(&init_user_ns, current_fsuid());
2314 pud->pud_fsgid = from_kgid(&init_user_ns, current_fsgid());
2315 pud->pud_cap = cfs_curproc_cap_pack();
2316 pud->pud_ngroups = (msg->lm_buflens[offset] - sizeof(*pud)) / 4;
2317
2318 task_lock(current);
2319 if (pud->pud_ngroups > current_ngroups)
2320 pud->pud_ngroups = current_ngroups;
2321 memcpy(pud->pud_groups, current_cred()->group_info->blocks[0],
2322 pud->pud_ngroups * sizeof(__u32));
2323 task_unlock(current);
2324
2325 return 0;
2326}
2327EXPORT_SYMBOL(sptlrpc_pack_user_desc);
2328
2329int sptlrpc_unpack_user_desc(struct lustre_msg *msg, int offset, int swabbed)
2330{
2331 struct ptlrpc_user_desc *pud;
2332 int i;
2333
2334 pud = lustre_msg_buf(msg, offset, sizeof(*pud));
2335 if (!pud)
2336 return -EINVAL;
2337
2338 if (swabbed) {
2339 __swab32s(&pud->pud_uid);
2340 __swab32s(&pud->pud_gid);
2341 __swab32s(&pud->pud_fsuid);
2342 __swab32s(&pud->pud_fsgid);
2343 __swab32s(&pud->pud_cap);
2344 __swab32s(&pud->pud_ngroups);
2345 }
2346
2347 if (pud->pud_ngroups > LUSTRE_MAX_GROUPS) {
2348 CERROR("%u groups is too large\n", pud->pud_ngroups);
2349 return -EINVAL;
2350 }
2351
2352 if (sizeof(*pud) + pud->pud_ngroups * sizeof(__u32) >
2353 msg->lm_buflens[offset]) {
2354 CERROR("%u groups are claimed but bufsize only %u\n",
2355 pud->pud_ngroups, msg->lm_buflens[offset]);
2356 return -EINVAL;
2357 }
2358
2359 if (swabbed) {
2360 for (i = 0; i < pud->pud_ngroups; i++)
2361 __swab32s(&pud->pud_groups[i]);
2362 }
2363
2364 return 0;
2365}
2366EXPORT_SYMBOL(sptlrpc_unpack_user_desc);
2367
2368
2369
2370
2371
2372const char *sec2target_str(struct ptlrpc_sec *sec)
2373{
2374 if (!sec || !sec->ps_import || !sec->ps_import->imp_obd)
2375 return "*";
2376 if (sec_is_reverse(sec))
2377 return "c";
2378 return obd_uuid2str(&sec->ps_import->imp_obd->u.cli.cl_target_uuid);
2379}
2380EXPORT_SYMBOL(sec2target_str);
2381
2382
2383
2384
2385int sptlrpc_flavor_has_bulk(struct sptlrpc_flavor *flvr)
2386{
2387 switch (SPTLRPC_FLVR_BULK_SVC(flvr->sf_rpc)) {
2388 case SPTLRPC_BULK_SVC_INTG:
2389 case SPTLRPC_BULK_SVC_PRIV:
2390 return 1;
2391 default:
2392 return 0;
2393 }
2394}
2395EXPORT_SYMBOL(sptlrpc_flavor_has_bulk);
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405int sptlrpc_init(void)
2406{
2407 int rc;
2408
2409 rwlock_init(&policy_lock);
2410
2411 rc = sptlrpc_gc_init();
2412 if (rc)
2413 goto out;
2414
2415 rc = sptlrpc_conf_init();
2416 if (rc)
2417 goto out_gc;
2418
2419 rc = sptlrpc_enc_pool_init();
2420 if (rc)
2421 goto out_conf;
2422
2423 rc = sptlrpc_null_init();
2424 if (rc)
2425 goto out_pool;
2426
2427 rc = sptlrpc_plain_init();
2428 if (rc)
2429 goto out_null;
2430
2431 rc = sptlrpc_lproc_init();
2432 if (rc)
2433 goto out_plain;
2434
2435 return 0;
2436
2437out_plain:
2438 sptlrpc_plain_fini();
2439out_null:
2440 sptlrpc_null_fini();
2441out_pool:
2442 sptlrpc_enc_pool_fini();
2443out_conf:
2444 sptlrpc_conf_fini();
2445out_gc:
2446 sptlrpc_gc_fini();
2447out:
2448 return rc;
2449}
2450
2451void sptlrpc_fini(void)
2452{
2453 sptlrpc_lproc_fini();
2454 sptlrpc_plain_fini();
2455 sptlrpc_null_fini();
2456 sptlrpc_enc_pool_fini();
2457 sptlrpc_conf_fini();
2458 sptlrpc_gc_fini();
2459}
2460