From patchwork Fri Nov 16 23:28:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 1757581 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id E8694DF288 for ; Fri, 16 Nov 2012 23:28:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753817Ab2KPX24 (ORCPT ); Fri, 16 Nov 2012 18:28:56 -0500 Received: from mail-ia0-f174.google.com ([209.85.210.174]:35852 "EHLO mail-ia0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753769Ab2KPX2z (ORCPT ); Fri, 16 Nov 2012 18:28:55 -0500 Received: by mail-ia0-f174.google.com with SMTP id y25so2063184iay.19 for ; Fri, 16 Nov 2012 15:28:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:subject:to:date:message-id:user-agent:mime-version :content-type:content-transfer-encoding; bh=yHwRXONXd3VXcQcSc4G54lz1+1ekGAGNJwP/6y0WzI8=; b=S9rddpqvsy1I7bzzY9tRKwhZvYnderdEmisk7NWPjVwjDcbPBRESqkwpiOOKvHV5we 9t5PHnYXQy0iEQaD/W5IMZwwx5/PD8rETsmUEfsbDjqgXWJU7EaYu4+6m4P2Q0p2NSU3 X/LjtQi+yaaJOAiYjUtKv/zZPSuW8gUfRihrcHVUTP5241t8sRgNHSYjmLGDuv8Ul40B ZyazkWpC7Pl6DL1dCORnvUeMPChGsfKSU0CwNqFhIQI1e1NWpkufp6P1XXfnLpdpZXs1 lF/QRrs43O1kFE85KUsFGZi2QRbnFOBYdbe4SjL3YlRoednplkSLEwBj2y+1OxVIU0Yw bD/A== Received: by 10.50.214.68 with SMTP id ny4mr196042igc.65.1353108535043; Fri, 16 Nov 2012 15:28:55 -0800 (PST) Received: from seurat.1015granger.net (adsl-99-26-161-222.dsl.sfldmi.sbcglobal.net. [99.26.161.222]) by mx.google.com with ESMTPS id yf6sm1536260igb.0.2012.11.16.15.28.52 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 16 Nov 2012 15:28:54 -0800 (PST) From: Chuck Lever Subject: [PATCH] SUNRPC: Allow rpc_clone_client() to share rpc_auth objects To: linux-nfs@vger.kernel.org Date: Fri, 16 Nov 2012 18:28:51 -0500 Message-ID: <20121116232846.4931.88675.stgit@seurat.1015granger.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org J. Bruce Fields reports: > On 3.7-rc1: > > client# mount -tnfs -osec=krb5,vers=3 server:/exports/ext4 /mnt/ > > server# ls -l /exports/ext4|grep TMP > server# > > # mkdir /mnt/TMP > mkdir: cannot create directory `/mnt/TMP': Permission denied > > server# ls -l /exports/ext4|grep TMP > drwxr-xr-x 2 nfsnobody nfsnobody 4096 Oct 16 08:56 TMP > server# > > Wireshark also shows that the create succeeds. The NFS3 MKDIR operation succeeds but the mkdir(2) system call fails because the NFS client attempts to retrieve the ACL on the new directory, but encounters a problem that appears to have been introduced by commit 1b63a751 "SUNRPC: Refactor rpc_clone_client()", Sep 14 17:23:52 2012. NFSv3 ACL requests are part of a side-band protocol called NFSACL. Unlike the MNT or NLM side-band protocols, an NFS client sends NFSACL protocol requests on the same transport as it sends NFS protocol requests. The Linux NFS client clones the rpc_clnt for the NFS protocol to make an rpc_clnt for NFSACL protocol requests, but they share the underlying transport (rpc_xprt). Normally the original rpc_clnt's rpc_auth object should also be shared by both rpc_clnt's. See rpc_bind_new_program() and rpc_clone_client(). Thanks to 1b63a751, however, rpc_clone_client() create a _new_ rpc_auth object for the NFSACL rpc_clnt. With AUTH_GSS, this means a fresh GSS context must be created for the new rpc_auth object. rpc.gssd tries to create the context with the service name "nfsacl@servername". The NFS server does not recognize that service name. The solution is to restore the original pre-1b63a751 behavior of rpc_clone_client(). This behavior is to share an rpc_auth object between the original rpc_clnt and the cloned rpc_clnt. A fresh GSS context for the NFSACL rpc_clnt is then no longer required. It simply uses the one that is already established for the NFS rpc_clnt. Reported-by: J. Bruce Fields Signed-off-by: Chuck Lever --- include/linux/sunrpc/clnt.h | 1 + net/sunrpc/clnt.c | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 34206b8..2931952 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -112,6 +112,7 @@ struct rpc_create_args { u32 prognumber; /* overrides program->number */ u32 version; rpc_authflavor_t authflavor; + struct rpc_auth *auth; unsigned long flags; char *client_name; struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */ diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index cdc7564..c75630a 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -356,12 +356,17 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru if (err < 0) goto out_no_path; - auth = rpcauth_create(args->authflavor, clnt); - if (IS_ERR(auth)) { - printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", - args->authflavor); - err = PTR_ERR(auth); - goto out_no_auth; + if (args->auth == NULL) { + auth = rpcauth_create(args->authflavor, clnt); + if (IS_ERR(auth)) { + printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", + args->authflavor); + err = PTR_ERR(auth); + goto out_no_auth; + } + } else { + atomic_inc(&args->auth->au_count); + clnt->cl_auth = args->auth; } /* save the nodename */ @@ -542,6 +547,7 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt) .prognumber = clnt->cl_prog, .version = clnt->cl_vers, .authflavor = clnt->cl_auth->au_flavor, + .auth = clnt->cl_auth, .client_name = clnt->cl_principal, }; return __rpc_clone_client(&args, clnt); @@ -566,6 +572,9 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor) .authflavor = flavor, .client_name = clnt->cl_principal, }; + + if (flavor == clnt->cl_auth->au_flavor) + args.auth = clnt->cl_auth; return __rpc_clone_client(&args, clnt); } EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth);