aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2013-04-29 14:03:30 -0400
committerJ. Bruce Fields <bfields@redhat.com>2013-04-29 16:23:34 -0400
commitb1df7637232927ac69ed1a32e9c6b768f635b7d4 (patch)
treecf5fdd96cccb3a89f4e0dea895775eb7c428c533 /net/sunrpc
parentdd30333cf5a2f9dfecda5c6f4523133f13847aae (diff)
parent721ccfb79b6f74f4052de70236d24047e73682d4 (diff)
Merge branch 'nfs-for-next' of git://linux-nfs.org/~trondmy/nfs-2.6 into for-3.10
Note conflict: Chuck's patches modified (and made static) gss_mech_get_by_OID, which is still needed by gss-proxy patches. The conflict resolution is a bit minimal; we may want some more cleanup.
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/Kconfig1
-rw-r--r--net/sunrpc/auth.c75
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c3
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c6
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c119
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.c7
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.h3
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c4
-rw-r--r--net/sunrpc/clnt.c11
9 files changed, 185 insertions, 44 deletions
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 262caf03bd5f..241b54f30204 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -3,6 +3,7 @@ config SUNRPC
3 3
4config SUNRPC_GSS 4config SUNRPC_GSS
5 tristate 5 tristate
6 select OID_REGISTRY
6 7
7config SUNRPC_BACKCHANNEL 8config SUNRPC_BACKCHANNEL
8 bool 9 bool
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index f5294047df77..ed2fdd210c0b 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -82,7 +82,7 @@ MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
82 82
83static u32 83static u32
84pseudoflavor_to_flavor(u32 flavor) { 84pseudoflavor_to_flavor(u32 flavor) {
85 if (flavor >= RPC_AUTH_MAXFLAVOR) 85 if (flavor > RPC_AUTH_MAXFLAVOR)
86 return RPC_AUTH_GSS; 86 return RPC_AUTH_GSS;
87 return flavor; 87 return flavor;
88} 88}
@@ -124,6 +124,79 @@ rpcauth_unregister(const struct rpc_authops *ops)
124EXPORT_SYMBOL_GPL(rpcauth_unregister); 124EXPORT_SYMBOL_GPL(rpcauth_unregister);
125 125
126/** 126/**
127 * rpcauth_get_pseudoflavor - check if security flavor is supported
128 * @flavor: a security flavor
129 * @info: a GSS mech OID, quality of protection, and service value
130 *
131 * Verifies that an appropriate kernel module is available or already loaded.
132 * Returns an equivalent pseudoflavor, or RPC_AUTH_MAXFLAVOR if "flavor" is
133 * not supported locally.
134 */
135rpc_authflavor_t
136rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
137{
138 const struct rpc_authops *ops;
139 rpc_authflavor_t pseudoflavor;
140
141 ops = auth_flavors[flavor];
142 if (ops == NULL)
143 request_module("rpc-auth-%u", flavor);
144 spin_lock(&rpc_authflavor_lock);
145 ops = auth_flavors[flavor];
146 if (ops == NULL || !try_module_get(ops->owner)) {
147 spin_unlock(&rpc_authflavor_lock);
148 return RPC_AUTH_MAXFLAVOR;
149 }
150 spin_unlock(&rpc_authflavor_lock);
151
152 pseudoflavor = flavor;
153 if (ops->info2flavor != NULL)
154 pseudoflavor = ops->info2flavor(info);
155
156 module_put(ops->owner);
157 return pseudoflavor;
158}
159EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor);
160
161/**
162 * rpcauth_get_gssinfo - find GSS tuple matching a GSS pseudoflavor
163 * @pseudoflavor: GSS pseudoflavor to match
164 * @info: rpcsec_gss_info structure to fill in
165 *
166 * Returns zero and fills in "info" if pseudoflavor matches a
167 * supported mechanism.
168 */
169int
170rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
171{
172 rpc_authflavor_t flavor = pseudoflavor_to_flavor(pseudoflavor);
173 const struct rpc_authops *ops;
174 int result;
175
176 if (flavor >= RPC_AUTH_MAXFLAVOR)
177 return -EINVAL;
178
179 ops = auth_flavors[flavor];
180 if (ops == NULL)
181 request_module("rpc-auth-%u", flavor);
182 spin_lock(&rpc_authflavor_lock);
183 ops = auth_flavors[flavor];
184 if (ops == NULL || !try_module_get(ops->owner)) {
185 spin_unlock(&rpc_authflavor_lock);
186 return -ENOENT;
187 }
188 spin_unlock(&rpc_authflavor_lock);
189
190 result = -ENOENT;
191 if (ops->flavor2info != NULL)
192 result = ops->flavor2info(pseudoflavor, info);
193
194 module_put(ops->owner);
195 return result;
196}
197EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
198
199/**
127 * rpcauth_list_flavors - discover registered flavors and pseudoflavors 200 * rpcauth_list_flavors - discover registered flavors and pseudoflavors
128 * @array: array to fill in 201 * @array: array to fill in
129 * @size: size of "array" 202 * @size: size of "array"
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 23563e783ec2..a764e227fdde 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1641,6 +1641,8 @@ static const struct rpc_authops authgss_ops = {
1641 .pipes_create = gss_pipes_dentries_create, 1641 .pipes_create = gss_pipes_dentries_create,
1642 .pipes_destroy = gss_pipes_dentries_destroy, 1642 .pipes_destroy = gss_pipes_dentries_destroy,
1643 .list_pseudoflavors = gss_mech_list_pseudoflavors, 1643 .list_pseudoflavors = gss_mech_list_pseudoflavors,
1644 .info2flavor = gss_mech_info2flavor,
1645 .flavor2info = gss_mech_flavor2info,
1644}; 1646};
1645 1647
1646static const struct rpc_credops gss_credops = { 1648static const struct rpc_credops gss_credops = {
@@ -1733,6 +1735,7 @@ static void __exit exit_rpcsec_gss(void)
1733 rcu_barrier(); /* Wait for completion of call_rcu()'s */ 1735 rcu_barrier(); /* Wait for completion of call_rcu()'s */
1734} 1736}
1735 1737
1738MODULE_ALIAS("rpc-auth-6");
1736MODULE_LICENSE("GPL"); 1739MODULE_LICENSE("GPL");
1737module_param_named(expired_cred_retry_delay, 1740module_param_named(expired_cred_retry_delay,
1738 gss_expired_cred_retry_delay, 1741 gss_expired_cred_retry_delay,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 3bc4a23938ea..0d3c158ef8fa 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -732,16 +732,19 @@ static const struct gss_api_ops gss_kerberos_ops = {
732static struct pf_desc gss_kerberos_pfs[] = { 732static struct pf_desc gss_kerberos_pfs[] = {
733 [0] = { 733 [0] = {
734 .pseudoflavor = RPC_AUTH_GSS_KRB5, 734 .pseudoflavor = RPC_AUTH_GSS_KRB5,
735 .qop = GSS_C_QOP_DEFAULT,
735 .service = RPC_GSS_SVC_NONE, 736 .service = RPC_GSS_SVC_NONE,
736 .name = "krb5", 737 .name = "krb5",
737 }, 738 },
738 [1] = { 739 [1] = {
739 .pseudoflavor = RPC_AUTH_GSS_KRB5I, 740 .pseudoflavor = RPC_AUTH_GSS_KRB5I,
741 .qop = GSS_C_QOP_DEFAULT,
740 .service = RPC_GSS_SVC_INTEGRITY, 742 .service = RPC_GSS_SVC_INTEGRITY,
741 .name = "krb5i", 743 .name = "krb5i",
742 }, 744 },
743 [2] = { 745 [2] = {
744 .pseudoflavor = RPC_AUTH_GSS_KRB5P, 746 .pseudoflavor = RPC_AUTH_GSS_KRB5P,
747 .qop = GSS_C_QOP_DEFAULT,
745 .service = RPC_GSS_SVC_PRIVACY, 748 .service = RPC_GSS_SVC_PRIVACY,
746 .name = "krb5p", 749 .name = "krb5p",
747 }, 750 },
@@ -753,11 +756,12 @@ MODULE_ALIAS("rpc-auth-gss-krb5p");
753MODULE_ALIAS("rpc-auth-gss-390003"); 756MODULE_ALIAS("rpc-auth-gss-390003");
754MODULE_ALIAS("rpc-auth-gss-390004"); 757MODULE_ALIAS("rpc-auth-gss-390004");
755MODULE_ALIAS("rpc-auth-gss-390005"); 758MODULE_ALIAS("rpc-auth-gss-390005");
759MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
756 760
757static struct gss_api_mech gss_kerberos_mech = { 761static struct gss_api_mech gss_kerberos_mech = {
758 .gm_name = "krb5", 762 .gm_name = "krb5",
759 .gm_owner = THIS_MODULE, 763 .gm_owner = THIS_MODULE,
760 .gm_oid = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}, 764 .gm_oid = { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
761 .gm_ops = &gss_kerberos_ops, 765 .gm_ops = &gss_kerberos_ops,
762 .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs), 766 .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),
763 .gm_pfs = gss_kerberos_pfs, 767 .gm_pfs = gss_kerberos_pfs,
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 43fd5bbf92c6..defa9d33925c 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -36,6 +36,7 @@
36#include <linux/types.h> 36#include <linux/types.h>
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/module.h> 38#include <linux/module.h>
39#include <linux/oid_registry.h>
39#include <linux/sunrpc/msg_prot.h> 40#include <linux/sunrpc/msg_prot.h>
40#include <linux/sunrpc/gss_asn1.h> 41#include <linux/sunrpc/gss_asn1.h>
41#include <linux/sunrpc/auth_gss.h> 42#include <linux/sunrpc/auth_gss.h>
@@ -102,8 +103,13 @@ out:
102 return status; 103 return status;
103} 104}
104 105
105int 106/**
106gss_mech_register(struct gss_api_mech *gm) 107 * gss_mech_register - register a GSS mechanism
108 * @gm: GSS mechanism handle
109 *
110 * Returns zero if successful, or a negative errno.
111 */
112int gss_mech_register(struct gss_api_mech *gm)
107{ 113{
108 int status; 114 int status;
109 115
@@ -116,11 +122,14 @@ gss_mech_register(struct gss_api_mech *gm)
116 dprintk("RPC: registered gss mechanism %s\n", gm->gm_name); 122 dprintk("RPC: registered gss mechanism %s\n", gm->gm_name);
117 return 0; 123 return 0;
118} 124}
119
120EXPORT_SYMBOL_GPL(gss_mech_register); 125EXPORT_SYMBOL_GPL(gss_mech_register);
121 126
122void 127/**
123gss_mech_unregister(struct gss_api_mech *gm) 128 * gss_mech_unregister - release a GSS mechanism
129 * @gm: GSS mechanism handle
130 *
131 */
132void gss_mech_unregister(struct gss_api_mech *gm)
124{ 133{
125 spin_lock(&registered_mechs_lock); 134 spin_lock(&registered_mechs_lock);
126 list_del(&gm->gm_list); 135 list_del(&gm->gm_list);
@@ -128,18 +137,14 @@ gss_mech_unregister(struct gss_api_mech *gm)
128 dprintk("RPC: unregistered gss mechanism %s\n", gm->gm_name); 137 dprintk("RPC: unregistered gss mechanism %s\n", gm->gm_name);
129 gss_mech_free(gm); 138 gss_mech_free(gm);
130} 139}
131
132EXPORT_SYMBOL_GPL(gss_mech_unregister); 140EXPORT_SYMBOL_GPL(gss_mech_unregister);
133 141
134struct gss_api_mech * 142static struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm)
135gss_mech_get(struct gss_api_mech *gm)
136{ 143{
137 __module_get(gm->gm_owner); 144 __module_get(gm->gm_owner);
138 return gm; 145 return gm;
139} 146}
140 147
141EXPORT_SYMBOL_GPL(gss_mech_get);
142
143static struct gss_api_mech * 148static struct gss_api_mech *
144_gss_mech_get_by_name(const char *name) 149_gss_mech_get_by_name(const char *name)
145{ 150{
@@ -169,12 +174,16 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name)
169 } 174 }
170 return gm; 175 return gm;
171} 176}
172EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
173 177
174struct gss_api_mech * 178struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
175gss_mech_get_by_OID(struct xdr_netobj *obj)
176{ 179{
177 struct gss_api_mech *pos, *gm = NULL; 180 struct gss_api_mech *pos, *gm = NULL;
181 char buf[32];
182
183 if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0)
184 return NULL;
185 dprintk("RPC: %s(%s)\n", __func__, buf);
186 request_module("rpc-auth-gss-%s", buf);
178 187
179 spin_lock(&registered_mechs_lock); 188 spin_lock(&registered_mechs_lock);
180 list_for_each_entry(pos, &registered_mechs, gm_list) { 189 list_for_each_entry(pos, &registered_mechs, gm_list) {
@@ -188,11 +197,8 @@ gss_mech_get_by_OID(struct xdr_netobj *obj)
188 } 197 }
189 spin_unlock(&registered_mechs_lock); 198 spin_unlock(&registered_mechs_lock);
190 return gm; 199 return gm;
191
192} 200}
193 201
194EXPORT_SYMBOL_GPL(gss_mech_get_by_OID);
195
196static inline int 202static inline int
197mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) 203mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)
198{ 204{
@@ -237,8 +243,6 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
237 return gm; 243 return gm;
238} 244}
239 245
240EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
241
242/** 246/**
243 * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors 247 * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors
244 * @array: array to fill in 248 * @array: array to fill in
@@ -268,19 +272,82 @@ int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size)
268 return i; 272 return i;
269} 273}
270 274
271u32 275/**
272gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) 276 * gss_svc_to_pseudoflavor - map a GSS service number to a pseudoflavor
277 * @gm: GSS mechanism handle
278 * @qop: GSS quality-of-protection value
279 * @service: GSS service value
280 *
281 * Returns a matching security flavor, or RPC_AUTH_MAXFLAVOR if none is found.
282 */
283rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 qop,
284 u32 service)
273{ 285{
274 int i; 286 int i;
275 287
276 for (i = 0; i < gm->gm_pf_num; i++) { 288 for (i = 0; i < gm->gm_pf_num; i++) {
277 if (gm->gm_pfs[i].service == service) { 289 if (gm->gm_pfs[i].qop == qop &&
290 gm->gm_pfs[i].service == service) {
278 return gm->gm_pfs[i].pseudoflavor; 291 return gm->gm_pfs[i].pseudoflavor;
279 } 292 }
280 } 293 }
281 return RPC_AUTH_MAXFLAVOR; /* illegal value */ 294 return RPC_AUTH_MAXFLAVOR;
295}
296
297/**
298 * gss_mech_info2flavor - look up a pseudoflavor given a GSS tuple
299 * @info: a GSS mech OID, quality of protection, and service value
300 *
301 * Returns a matching pseudoflavor, or RPC_AUTH_MAXFLAVOR if the tuple is
302 * not supported.
303 */
304rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info)
305{
306 rpc_authflavor_t pseudoflavor;
307 struct gss_api_mech *gm;
308
309 gm = gss_mech_get_by_OID(&info->oid);
310 if (gm == NULL)
311 return RPC_AUTH_MAXFLAVOR;
312
313 pseudoflavor = gss_svc_to_pseudoflavor(gm, info->qop, info->service);
314
315 gss_mech_put(gm);
316 return pseudoflavor;
317}
318
319/**
320 * gss_mech_flavor2info - look up a GSS tuple for a given pseudoflavor
321 * @pseudoflavor: GSS pseudoflavor to match
322 * @info: rpcsec_gss_info structure to fill in
323 *
324 * Returns zero and fills in "info" if pseudoflavor matches a
325 * supported mechanism. Otherwise a negative errno is returned.
326 */
327int gss_mech_flavor2info(rpc_authflavor_t pseudoflavor,
328 struct rpcsec_gss_info *info)
329{
330 struct gss_api_mech *gm;
331 int i;
332
333 gm = gss_mech_get_by_pseudoflavor(pseudoflavor);
334 if (gm == NULL)
335 return -ENOENT;
336
337 for (i = 0; i < gm->gm_pf_num; i++) {
338 if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) {
339 memcpy(info->oid.data, gm->gm_oid.data, gm->gm_oid.len);
340 info->oid.len = gm->gm_oid.len;
341 info->qop = gm->gm_pfs[i].qop;
342 info->service = gm->gm_pfs[i].service;
343 gss_mech_put(gm);
344 return 0;
345 }
346 }
347
348 gss_mech_put(gm);
349 return -ENOENT;
282} 350}
283EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor);
284 351
285u32 352u32
286gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) 353gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
@@ -294,8 +361,6 @@ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
294 return 0; 361 return 0;
295} 362}
296 363
297EXPORT_SYMBOL_GPL(gss_pseudoflavor_to_service);
298
299char * 364char *
300gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) 365gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
301{ 366{
@@ -308,8 +373,6 @@ gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
308 return NULL; 373 return NULL;
309} 374}
310 375
311EXPORT_SYMBOL_GPL(gss_service_to_auth_domain_name);
312
313void 376void
314gss_mech_put(struct gss_api_mech * gm) 377gss_mech_put(struct gss_api_mech * gm)
315{ 378{
@@ -317,8 +380,6 @@ gss_mech_put(struct gss_api_mech * gm)
317 module_put(gm->gm_owner); 380 module_put(gm->gm_owner);
318} 381}
319 382
320EXPORT_SYMBOL_GPL(gss_mech_put);
321
322/* The mech could probably be determined from the token instead, but it's just 383/* The mech could probably be determined from the token instead, but it's just
323 * as easy for now to pass it in. */ 384 * as easy for now to pass it in. */
324int 385int
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
index 3f874d704859..c63273604ddc 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
@@ -220,7 +220,6 @@ static int gssp_call(struct net *net, struct rpc_message *msg)
220 220
221/* numbers somewhat arbitrary but large enough for current needs */ 221/* numbers somewhat arbitrary but large enough for current needs */
222#define GSSX_MAX_OUT_HANDLE 128 222#define GSSX_MAX_OUT_HANDLE 128
223#define GSSX_MAX_MECH_OID 16
224#define GSSX_MAX_SRC_PRINC 256 223#define GSSX_MAX_SRC_PRINC 256
225#define GSSX_KMEMBUF (GSSX_max_output_handle_sz + \ 224#define GSSX_KMEMBUF (GSSX_max_output_handle_sz + \
226 GSSX_max_oid_sz + \ 225 GSSX_max_oid_sz + \
@@ -242,7 +241,7 @@ int gssp_accept_sec_context_upcall(struct net *net,
242 * buffers but let the xdr code kmalloc them: 241 * buffers but let the xdr code kmalloc them:
243 */ 242 */
244 .exported_context_token.len = GSSX_max_output_handle_sz, 243 .exported_context_token.len = GSSX_max_output_handle_sz,
245 .mech.len = GSSX_max_oid_sz, 244 .mech.len = GSS_OID_MAX_LEN,
246 .src_name.display_name.len = GSSX_max_princ_sz 245 .src_name.display_name.len = GSSX_max_princ_sz
247 }; 246 };
248 struct gssx_res_accept_sec_context res = { 247 struct gssx_res_accept_sec_context res = {
@@ -272,7 +271,9 @@ int gssp_accept_sec_context_upcall(struct net *net,
272 data->minor_status = res.status.minor_status; 271 data->minor_status = res.status.minor_status;
273 if (res.context_handle) { 272 if (res.context_handle) {
274 data->out_handle = rctxh.exported_context_token; 273 data->out_handle = rctxh.exported_context_token;
275 data->mech_oid = rctxh.mech; 274 data->mech_oid.len = rctxh.mech.len;
275 memcpy(data->mech_oid.data, rctxh.mech.data,
276 data->mech_oid.len);
276 client_name = rctxh.src_name.display_name; 277 client_name = rctxh.src_name.display_name;
277 } 278 }
278 279
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.h b/net/sunrpc/auth_gss/gss_rpc_upcall.h
index 4c2caaa7e84e..1e542aded90a 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.h
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.h
@@ -21,6 +21,7 @@
21#ifndef _GSS_RPC_UPCALL_H 21#ifndef _GSS_RPC_UPCALL_H
22#define _GSS_RPC_UPCALL_H 22#define _GSS_RPC_UPCALL_H
23 23
24#include <linux/sunrpc/gss_api.h>
24#include <linux/sunrpc/auth_gss.h> 25#include <linux/sunrpc/auth_gss.h>
25#include "gss_rpc_xdr.h" 26#include "gss_rpc_xdr.h"
26#include "../netns.h" 27#include "../netns.h"
@@ -30,7 +31,7 @@ struct gssp_upcall_data {
30 struct gssp_in_token in_token; 31 struct gssp_in_token in_token;
31 struct xdr_netobj out_handle; 32 struct xdr_netobj out_handle;
32 struct xdr_netobj out_token; 33 struct xdr_netobj out_token;
33 struct xdr_netobj mech_oid; 34 struct rpcsec_gss_oid mech_oid;
34 struct svc_cred creds; 35 struct svc_cred creds;
35 int found_creds; 36 int found_creds;
36 int major_status; 37 int major_status;
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 58f5bc329408..1c66a3b78329 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1544,7 +1544,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
1544 svcdata->rsci = rsci; 1544 svcdata->rsci = rsci;
1545 cache_get(&rsci->h); 1545 cache_get(&rsci->h);
1546 rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor( 1546 rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor(
1547 rsci->mechctx->mech_type, gc->gc_svc); 1547 rsci->mechctx->mech_type,
1548 GSS_C_QOP_DEFAULT,
1549 gc->gc_svc);
1548 ret = SVC_OK; 1550 ret = SVC_OK;
1549 goto out; 1551 goto out;
1550 } 1552 }
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index ac74399e8899..3f7930f938cc 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -304,10 +304,8 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
304 err = rpciod_up(); 304 err = rpciod_up();
305 if (err) 305 if (err)
306 goto out_no_rpciod; 306 goto out_no_rpciod;
307 err = -EINVAL;
308 if (!xprt)
309 goto out_no_xprt;
310 307
308 err = -EINVAL;
311 if (args->version >= program->nrvers) 309 if (args->version >= program->nrvers)
312 goto out_err; 310 goto out_err;
313 version = program->version[args->version]; 311 version = program->version[args->version];
@@ -382,10 +380,9 @@ out_no_principal:
382out_no_stats: 380out_no_stats:
383 kfree(clnt); 381 kfree(clnt);
384out_err: 382out_err:
385 xprt_put(xprt);
386out_no_xprt:
387 rpciod_down(); 383 rpciod_down();
388out_no_rpciod: 384out_no_rpciod:
385 xprt_put(xprt);
389 return ERR_PTR(err); 386 return ERR_PTR(err);
390} 387}
391 388
@@ -516,7 +513,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
516 new = rpc_new_client(args, xprt); 513 new = rpc_new_client(args, xprt);
517 if (IS_ERR(new)) { 514 if (IS_ERR(new)) {
518 err = PTR_ERR(new); 515 err = PTR_ERR(new);
519 goto out_put; 516 goto out_err;
520 } 517 }
521 518
522 atomic_inc(&clnt->cl_count); 519 atomic_inc(&clnt->cl_count);
@@ -529,8 +526,6 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
529 new->cl_chatty = clnt->cl_chatty; 526 new->cl_chatty = clnt->cl_chatty;
530 return new; 527 return new;
531 528
532out_put:
533 xprt_put(xprt);
534out_err: 529out_err:
535 dprintk("RPC: %s: returned error %d\n", __func__, err); 530 dprintk("RPC: %s: returned error %d\n", __func__, err);
536 return ERR_PTR(err); 531 return ERR_PTR(err);