diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-15 11:16:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-15 11:16:53 -0400 |
commit | 37ca506adc395a028cd12760eca419dd0dc14b5c (patch) | |
tree | bab6f2644ef6bda4df1518f7063852012b69f458 /net | |
parent | b9090071a57185707c27b9d61b81bf941dbdf122 (diff) | |
parent | a16e92edcd0a2846455a30823e1bac964e743baa (diff) |
Merge branch 'nfs-server-stable' of git://linux-nfs.org/~bfields/linux
* 'nfs-server-stable' of git://linux-nfs.org/~bfields/linux:
knfsd: query filesystem for NFSv4 getattr of FATTR4_MAXNAME
knfsd: nfsv4 delegation recall should take reference on client
knfsd: don't shutdown callbacks until nfsv4 client is freed
knfsd: let nfsd manage timing out its own leases
knfsd: Add source address to sunrpc svc errors
knfsd: 64 bit ino support for NFS server
svcgss: move init code into separate function
knfsd: remove code duplication in nfsd4_setclientid()
nfsd warning fix
knfsd: fix callback rpc cred
knfsd: move nfsv4 slab creation/destruction to module init/exit
knfsd: spawn kernel thread to probe callback channel
knfsd: nfs4 name->id mapping not correctly parsing negative downcall
knfsd: demote some printk()s to dprintk()s
knfsd: cleanup of nfsd4 cmp_* functions
knfsd: delete code made redundant by map_new_errors
nfsd: fix horrible indentation in nfsd_setattr
nfsd: remove unused cache_for_each macro
nfsd: tone down inaccurate dprintk
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 144 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 40 |
2 files changed, 107 insertions, 77 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 7da7050f06c3..73940df6c460 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -631,7 +631,8 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o) | |||
631 | return 0; | 631 | return 0; |
632 | } | 632 | } |
633 | 633 | ||
634 | /* Verify the checksum on the header and return SVC_OK on success. | 634 | /* |
635 | * Verify the checksum on the header and return SVC_OK on success. | ||
635 | * Otherwise, return SVC_DROP (in the case of a bad sequence number) | 636 | * Otherwise, return SVC_DROP (in the case of a bad sequence number) |
636 | * or return SVC_DENIED and indicate error in authp. | 637 | * or return SVC_DENIED and indicate error in authp. |
637 | */ | 638 | */ |
@@ -961,6 +962,78 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) | |||
961 | } | 962 | } |
962 | 963 | ||
963 | /* | 964 | /* |
965 | * Having read the cred already and found we're in the context | ||
966 | * initiation case, read the verifier and initiate (or check the results | ||
967 | * of) upcalls to userspace for help with context initiation. If | ||
968 | * the upcall results are available, write the verifier and result. | ||
969 | * Otherwise, drop the request pending an answer to the upcall. | ||
970 | */ | ||
971 | static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | ||
972 | struct rpc_gss_wire_cred *gc, __be32 *authp) | ||
973 | { | ||
974 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
975 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
976 | struct xdr_netobj tmpobj; | ||
977 | struct rsi *rsip, rsikey; | ||
978 | |||
979 | /* Read the verifier; should be NULL: */ | ||
980 | *authp = rpc_autherr_badverf; | ||
981 | if (argv->iov_len < 2 * 4) | ||
982 | return SVC_DENIED; | ||
983 | if (svc_getnl(argv) != RPC_AUTH_NULL) | ||
984 | return SVC_DENIED; | ||
985 | if (svc_getnl(argv) != 0) | ||
986 | return SVC_DENIED; | ||
987 | |||
988 | /* Martial context handle and token for upcall: */ | ||
989 | *authp = rpc_autherr_badcred; | ||
990 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | ||
991 | return SVC_DENIED; | ||
992 | memset(&rsikey, 0, sizeof(rsikey)); | ||
993 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
994 | return SVC_DROP; | ||
995 | *authp = rpc_autherr_badverf; | ||
996 | if (svc_safe_getnetobj(argv, &tmpobj)) { | ||
997 | kfree(rsikey.in_handle.data); | ||
998 | return SVC_DENIED; | ||
999 | } | ||
1000 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { | ||
1001 | kfree(rsikey.in_handle.data); | ||
1002 | return SVC_DROP; | ||
1003 | } | ||
1004 | |||
1005 | /* Perform upcall, or find upcall result: */ | ||
1006 | rsip = rsi_lookup(&rsikey); | ||
1007 | rsi_free(&rsikey); | ||
1008 | if (!rsip) | ||
1009 | return SVC_DROP; | ||
1010 | switch (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { | ||
1011 | case -EAGAIN: | ||
1012 | case -ETIMEDOUT: | ||
1013 | case -ENOENT: | ||
1014 | /* No upcall result: */ | ||
1015 | return SVC_DROP; | ||
1016 | case 0: | ||
1017 | /* Got an answer to the upcall; use it: */ | ||
1018 | if (gss_write_init_verf(rqstp, rsip)) | ||
1019 | return SVC_DROP; | ||
1020 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
1021 | return SVC_DROP; | ||
1022 | svc_putnl(resv, RPC_SUCCESS); | ||
1023 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
1024 | return SVC_DROP; | ||
1025 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) | ||
1026 | return SVC_DROP; | ||
1027 | svc_putnl(resv, rsip->major_status); | ||
1028 | svc_putnl(resv, rsip->minor_status); | ||
1029 | svc_putnl(resv, GSS_SEQ_WIN); | ||
1030 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
1031 | return SVC_DROP; | ||
1032 | } | ||
1033 | return SVC_COMPLETE; | ||
1034 | } | ||
1035 | |||
1036 | /* | ||
964 | * Accept an rpcsec packet. | 1037 | * Accept an rpcsec packet. |
965 | * If context establishment, punt to user space | 1038 | * If context establishment, punt to user space |
966 | * If data exchange, verify/decrypt | 1039 | * If data exchange, verify/decrypt |
@@ -974,11 +1047,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
974 | struct kvec *argv = &rqstp->rq_arg.head[0]; | 1047 | struct kvec *argv = &rqstp->rq_arg.head[0]; |
975 | struct kvec *resv = &rqstp->rq_res.head[0]; | 1048 | struct kvec *resv = &rqstp->rq_res.head[0]; |
976 | u32 crlen; | 1049 | u32 crlen; |
977 | struct xdr_netobj tmpobj; | ||
978 | struct gss_svc_data *svcdata = rqstp->rq_auth_data; | 1050 | struct gss_svc_data *svcdata = rqstp->rq_auth_data; |
979 | struct rpc_gss_wire_cred *gc; | 1051 | struct rpc_gss_wire_cred *gc; |
980 | struct rsc *rsci = NULL; | 1052 | struct rsc *rsci = NULL; |
981 | struct rsi *rsip, rsikey; | ||
982 | __be32 *rpcstart; | 1053 | __be32 *rpcstart; |
983 | __be32 *reject_stat = resv->iov_base + resv->iov_len; | 1054 | __be32 *reject_stat = resv->iov_base + resv->iov_len; |
984 | int ret; | 1055 | int ret; |
@@ -1023,30 +1094,14 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1023 | if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) | 1094 | if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) |
1024 | goto auth_err; | 1095 | goto auth_err; |
1025 | 1096 | ||
1026 | /* | ||
1027 | * We've successfully parsed the credential. Let's check out the | ||
1028 | * verifier. An AUTH_NULL verifier is allowed (and required) for | ||
1029 | * INIT and CONTINUE_INIT requests. AUTH_RPCSEC_GSS is required for | ||
1030 | * PROC_DATA and PROC_DESTROY. | ||
1031 | * | ||
1032 | * AUTH_NULL verifier is 0 (AUTH_NULL), 0 (length). | ||
1033 | * AUTH_RPCSEC_GSS verifier is: | ||
1034 | * 6 (AUTH_RPCSEC_GSS), length, checksum. | ||
1035 | * checksum is calculated over rpcheader from xid up to here. | ||
1036 | */ | ||
1037 | *authp = rpc_autherr_badverf; | 1097 | *authp = rpc_autherr_badverf; |
1038 | switch (gc->gc_proc) { | 1098 | switch (gc->gc_proc) { |
1039 | case RPC_GSS_PROC_INIT: | 1099 | case RPC_GSS_PROC_INIT: |
1040 | case RPC_GSS_PROC_CONTINUE_INIT: | 1100 | case RPC_GSS_PROC_CONTINUE_INIT: |
1041 | if (argv->iov_len < 2 * 4) | 1101 | return svcauth_gss_handle_init(rqstp, gc, authp); |
1042 | goto auth_err; | ||
1043 | if (svc_getnl(argv) != RPC_AUTH_NULL) | ||
1044 | goto auth_err; | ||
1045 | if (svc_getnl(argv) != 0) | ||
1046 | goto auth_err; | ||
1047 | break; | ||
1048 | case RPC_GSS_PROC_DATA: | 1102 | case RPC_GSS_PROC_DATA: |
1049 | case RPC_GSS_PROC_DESTROY: | 1103 | case RPC_GSS_PROC_DESTROY: |
1104 | /* Look up the context, and check the verifier: */ | ||
1050 | *authp = rpcsec_gsserr_credproblem; | 1105 | *authp = rpcsec_gsserr_credproblem; |
1051 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); | 1106 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); |
1052 | if (!rsci) | 1107 | if (!rsci) |
@@ -1067,51 +1122,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1067 | 1122 | ||
1068 | /* now act upon the command: */ | 1123 | /* now act upon the command: */ |
1069 | switch (gc->gc_proc) { | 1124 | switch (gc->gc_proc) { |
1070 | case RPC_GSS_PROC_INIT: | ||
1071 | case RPC_GSS_PROC_CONTINUE_INIT: | ||
1072 | *authp = rpc_autherr_badcred; | ||
1073 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | ||
1074 | goto auth_err; | ||
1075 | memset(&rsikey, 0, sizeof(rsikey)); | ||
1076 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
1077 | goto drop; | ||
1078 | *authp = rpc_autherr_badverf; | ||
1079 | if (svc_safe_getnetobj(argv, &tmpobj)) { | ||
1080 | kfree(rsikey.in_handle.data); | ||
1081 | goto auth_err; | ||
1082 | } | ||
1083 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { | ||
1084 | kfree(rsikey.in_handle.data); | ||
1085 | goto drop; | ||
1086 | } | ||
1087 | |||
1088 | rsip = rsi_lookup(&rsikey); | ||
1089 | rsi_free(&rsikey); | ||
1090 | if (!rsip) { | ||
1091 | goto drop; | ||
1092 | } | ||
1093 | switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { | ||
1094 | case -EAGAIN: | ||
1095 | case -ETIMEDOUT: | ||
1096 | case -ENOENT: | ||
1097 | goto drop; | ||
1098 | case 0: | ||
1099 | if (gss_write_init_verf(rqstp, rsip)) | ||
1100 | goto drop; | ||
1101 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
1102 | goto drop; | ||
1103 | svc_putnl(resv, RPC_SUCCESS); | ||
1104 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
1105 | goto drop; | ||
1106 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) | ||
1107 | goto drop; | ||
1108 | svc_putnl(resv, rsip->major_status); | ||
1109 | svc_putnl(resv, rsip->minor_status); | ||
1110 | svc_putnl(resv, GSS_SEQ_WIN); | ||
1111 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
1112 | goto drop; | ||
1113 | } | ||
1114 | goto complete; | ||
1115 | case RPC_GSS_PROC_DESTROY: | 1125 | case RPC_GSS_PROC_DESTROY: |
1116 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) | 1126 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) |
1117 | goto auth_err; | 1127 | goto auth_err; |
@@ -1158,7 +1168,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1158 | goto out; | 1168 | goto out; |
1159 | } | 1169 | } |
1160 | auth_err: | 1170 | auth_err: |
1161 | /* Restore write pointer to original value: */ | 1171 | /* Restore write pointer to its original value: */ |
1162 | xdr_ressize_check(rqstp, reject_stat); | 1172 | xdr_ressize_check(rqstp, reject_stat); |
1163 | ret = SVC_DENIED; | 1173 | ret = SVC_DENIED; |
1164 | goto out; | 1174 | goto out; |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 55ea6df069de..a4a6bf7deaa4 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -777,6 +777,30 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) | |||
777 | } | 777 | } |
778 | 778 | ||
779 | /* | 779 | /* |
780 | * Printk the given error with the address of the client that caused it. | ||
781 | */ | ||
782 | static int | ||
783 | __attribute__ ((format (printf, 2, 3))) | ||
784 | svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) | ||
785 | { | ||
786 | va_list args; | ||
787 | int r; | ||
788 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
789 | |||
790 | if (!net_ratelimit()) | ||
791 | return 0; | ||
792 | |||
793 | printk(KERN_WARNING "svc: %s: ", | ||
794 | svc_print_addr(rqstp, buf, sizeof(buf))); | ||
795 | |||
796 | va_start(args, fmt); | ||
797 | r = vprintk(fmt, args); | ||
798 | va_end(args); | ||
799 | |||
800 | return r; | ||
801 | } | ||
802 | |||
803 | /* | ||
780 | * Process the RPC request. | 804 | * Process the RPC request. |
781 | */ | 805 | */ |
782 | int | 806 | int |
@@ -963,14 +987,13 @@ svc_process(struct svc_rqst *rqstp) | |||
963 | return 0; | 987 | return 0; |
964 | 988 | ||
965 | err_short_len: | 989 | err_short_len: |
966 | if (net_ratelimit()) | 990 | svc_printk(rqstp, "short len %Zd, dropping request\n", |
967 | printk("svc: short len %Zd, dropping request\n", argv->iov_len); | 991 | argv->iov_len); |
968 | 992 | ||
969 | goto dropit; /* drop request */ | 993 | goto dropit; /* drop request */ |
970 | 994 | ||
971 | err_bad_dir: | 995 | err_bad_dir: |
972 | if (net_ratelimit()) | 996 | svc_printk(rqstp, "bad direction %d, dropping request\n", dir); |
973 | printk("svc: bad direction %d, dropping request\n", dir); | ||
974 | 997 | ||
975 | serv->sv_stats->rpcbadfmt++; | 998 | serv->sv_stats->rpcbadfmt++; |
976 | goto dropit; /* drop request */ | 999 | goto dropit; /* drop request */ |
@@ -1000,8 +1023,7 @@ err_bad_prog: | |||
1000 | goto sendit; | 1023 | goto sendit; |
1001 | 1024 | ||
1002 | err_bad_vers: | 1025 | err_bad_vers: |
1003 | if (net_ratelimit()) | 1026 | svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", |
1004 | printk("svc: unknown version (%d for prog %d, %s)\n", | ||
1005 | vers, prog, progp->pg_name); | 1027 | vers, prog, progp->pg_name); |
1006 | 1028 | ||
1007 | serv->sv_stats->rpcbadfmt++; | 1029 | serv->sv_stats->rpcbadfmt++; |
@@ -1011,16 +1033,14 @@ err_bad_vers: | |||
1011 | goto sendit; | 1033 | goto sendit; |
1012 | 1034 | ||
1013 | err_bad_proc: | 1035 | err_bad_proc: |
1014 | if (net_ratelimit()) | 1036 | svc_printk(rqstp, "unknown procedure (%d)\n", proc); |
1015 | printk("svc: unknown procedure (%d)\n", proc); | ||
1016 | 1037 | ||
1017 | serv->sv_stats->rpcbadfmt++; | 1038 | serv->sv_stats->rpcbadfmt++; |
1018 | svc_putnl(resv, RPC_PROC_UNAVAIL); | 1039 | svc_putnl(resv, RPC_PROC_UNAVAIL); |
1019 | goto sendit; | 1040 | goto sendit; |
1020 | 1041 | ||
1021 | err_garbage: | 1042 | err_garbage: |
1022 | if (net_ratelimit()) | 1043 | svc_printk(rqstp, "failed to decode args\n"); |
1023 | printk("svc: failed to decode args\n"); | ||
1024 | 1044 | ||
1025 | rpc_stat = rpc_garbage_args; | 1045 | rpc_stat = rpc_garbage_args; |
1026 | err_bad: | 1046 | err_bad: |