From patchwork Fri Oct 11 19:12:15 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Weston Andros Adamson X-Patchwork-Id: 3025881 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 9D72ABF924 for ; Fri, 11 Oct 2013 19:12:22 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CDBB62029B for ; Fri, 11 Oct 2013 19:12:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EC25120279 for ; Fri, 11 Oct 2013 19:12:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754717Ab3JKTMS (ORCPT ); Fri, 11 Oct 2013 15:12:18 -0400 Received: from mx11.netapp.com ([216.240.18.76]:32139 "EHLO mx11.netapp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752684Ab3JKTMR convert rfc822-to-8bit (ORCPT ); Fri, 11 Oct 2013 15:12:17 -0400 X-IronPort-AV: E=Sophos;i="4.93,1082,1378882800"; d="scan'208";a="58867007" Received: from vmwexceht04-prd.hq.netapp.com ([10.106.77.34]) by mx11-out.netapp.com with ESMTP; 11 Oct 2013 12:12:16 -0700 Received: from SACEXCMBX02-PRD.hq.netapp.com ([169.254.1.86]) by vmwexceht04-prd.hq.netapp.com ([10.106.77.34]) with mapi id 14.03.0123.003; Fri, 11 Oct 2013 12:12:16 -0700 From: Weston Andros Adamson To: "Myklebust, Trond" CC: "" Subject: Re: [PATCH] NFS: Add support for multiple sec= mount options Thread-Topic: [PATCH] NFS: Add support for multiple sec= mount options Thread-Index: AQHOxrHq0YlTXpkMwkK6HG2Pmn6fxJnwU4yA Date: Fri, 11 Oct 2013 19:12:15 +0000 Message-ID: <823A0595-BF60-4519-A446-262D155A6437@netapp.com> References: <1381517062-11267-1-git-send-email-dros@netapp.com> In-Reply-To: <1381517062-11267-1-git-send-email-dros@netapp.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.106.53.51] Content-ID: <40D5A6A458FC2141BC9ACAAB4A965855@hq.netapp.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP I'm going to hold off on posting an official patch for nfs.man until this is accepted. Here's what I'm thinking: -dros On Oct 11, 2013, at 2:44 PM, Weston Andros Adamson wrote: > This patch adds support for multiple security options which can be > specified using a colon-delimited list of security flavors (the same > syntax as nfsd's exports file). > > This is useful, for instance, when NFSv4.x mounts cross SECINFO > boundaries. With this patch a user can use "sec=krb5i,krb5p" > to mount a remote filesystem using krb5i, but can still cross > into krb5p-only exports. > > New mounts will try all security options before failing. NFSv4.x > SECINFO results will be compared against the sec= flavors to > find the first flavor in both lists or if no match is found will > return EPERM. > > This patch cleans up some of the auth flavor logic by separating > the parsed mount options from the currently selected flavor and > sharing more code between the 'no sec= specified' and 'sec= specified' > code paths. > > Along with this patch I'm posting a patch to nfs-util's nfs.man to > reflect these changes. > > I wrote a script to verify that I haven't broken anything, it tests > all vers= and sec= combinations against a server with the exports: > > /export/sys *(sec=sys,rw,no_root_squash) > /export/krb5a *(sec=krb5,rw,no_root_squash) > /export/krb5i *(sec=krb5i,rw,no_root_squash) > /export/krb5p *(sec=krb5p,rw,no_root_squash) > /export/krb5ip *(sec=krb5i:krb5p,rw,no_root_squash) > /export/krb5aip *(sec=krb5:krb5i:krb5p,rw,no_root_squash) > > The script runs these tests against all exports, and the versions NFSv3, > v4.0, v4.1: > - no sec= options > - all single sec= options > - all combinations of multiple sec= options > - no sec= SECINFO (mount / then ls export dir, v4.x only) > - single sec= SECINFO (mount / then ls export dir, v4.x only) > - all combinations of multiple sec= SECINFO (mount / then ls export dir, > v4.x only) > > Signed-off-by: Weston Andros Adamson > --- > fs/nfs/client.c | 5 +- > fs/nfs/internal.h | 5 +- > fs/nfs/nfs4_fs.h | 1 - > fs/nfs/nfs4client.c | 10 ++- > fs/nfs/nfs4namespace.c | 21 +++-- > fs/nfs/nfs4proc.c | 30 +++++--- > fs/nfs/super.c | 190 +++++++++++++++++++++++++++++----------------- > include/linux/nfs_fs_sb.h | 1 + > include/linux/nfs_xdr.h | 7 ++ > 9 files changed, 176 insertions(+), 94 deletions(-) > > diff --git a/fs/nfs/client.c b/fs/nfs/client.c > index af03258..006fd52 100644 > --- a/fs/nfs/client.c > +++ b/fs/nfs/client.c > @@ -786,8 +786,10 @@ static int nfs_init_server(struct nfs_server *server, > goto error; > > server->port = data->nfs_server.port; > + server->auth_info = data->auth_info; > > - error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); > + error = nfs_init_server_rpcclient(server, &timeparms, > + data->selected_flavor); > if (error < 0) > goto error; > > @@ -928,6 +930,7 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour > target->acdirmax = source->acdirmax; > target->caps = source->caps; > target->options = source->options; > + target->auth_info = source->auth_info; > } > EXPORT_SYMBOL_GPL(nfs_server_copy_userdata); > > diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h > index 38da8c2..5c9cfe0 100644 > --- a/fs/nfs/internal.h > +++ b/fs/nfs/internal.h > @@ -88,8 +88,8 @@ struct nfs_parsed_mount_data { > unsigned int namlen; > unsigned int options; > unsigned int bsize; > - unsigned int auth_flavor_len; > - rpc_authflavor_t auth_flavors[1]; > + struct nfs_auth_info auth_info; > + rpc_authflavor_t selected_flavor; > char *client_address; > unsigned int version; > unsigned int minorversion; > @@ -323,6 +323,7 @@ extern struct file_system_type nfs_xdev_fs_type; > extern struct file_system_type nfs4_xdev_fs_type; > extern struct file_system_type nfs4_referral_fs_type; > #endif > +bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t); > struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *, > struct nfs_subversion *); > void nfs_initialise_sb(struct super_block *); > diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h > index 28842ab..cffed27 100644 > --- a/fs/nfs/nfs4_fs.h > +++ b/fs/nfs/nfs4_fs.h > @@ -213,7 +213,6 @@ int nfs_atomic_open(struct inode *, struct dentry *, struct file *, > extern struct file_system_type nfs4_fs_type; > > /* nfs4namespace.c */ > -rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); > struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); > struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *, > struct nfs_fh *, struct nfs_fattr *); > diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c > index 511cdce..b446314 100644 > --- a/fs/nfs/nfs4client.c > +++ b/fs/nfs/nfs4client.c > @@ -962,9 +962,13 @@ static int nfs4_init_server(struct nfs_server *server, > /* Initialise the client representation from the mount data */ > server->flags = data->flags; > server->options = data->options; > + server->auth_info = data->auth_info; > > - if (data->auth_flavor_len >= 1) > - pseudoflavor = data->auth_flavors[0]; > + /* Use the first specified auth flavor. If this flavor isn't > + * allowed by the server, use the SECINFO path to try the > + * other specified flavors */ > + if (data->auth_info.flavor_len >= 1) > + pseudoflavor = data->auth_info.flavors[0]; > > /* Get a client record */ > error = nfs4_set_client(server, > @@ -1019,7 +1023,7 @@ struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info, > if (!server) > return ERR_PTR(-ENOMEM); > > - auth_probe = mount_info->parsed->auth_flavor_len < 1; > + auth_probe = mount_info->parsed->auth_info.flavor_len < 1; > > /* set up the general RPC client */ > error = nfs4_init_server(server, mount_info->parsed); > diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c > index 2288cd3..caaa7aa 100644 > --- a/fs/nfs/nfs4namespace.c > +++ b/fs/nfs/nfs4namespace.c > @@ -137,15 +137,18 @@ static size_t nfs_parse_server_name(char *string, size_t len, > > /** > * nfs_find_best_sec - Find a security mechanism supported locally > + * @server: Nfs server structure > * @flavors: List of security tuples returned by SECINFO procedure > * > * Return the pseudoflavor of the first security mechanism in > - * "flavors" that is locally supported. Return RPC_AUTH_UNIX if > + * "flavors" that is locally supported and in the sec= mount > + * options if any were specified. Return RPC_AUTH_UNIX if > * no matching flavor is found in the array. The "flavors" array > * is searched in the order returned from the server, per RFC 3530 > * recommendation. > */ > -rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) > +static rpc_authflavor_t nfs_find_best_sec(struct nfs_server *server, > + struct nfs4_secinfo_flavors *flavors) > { > rpc_authflavor_t pseudoflavor; > struct nfs4_secinfo4 *secinfo; > @@ -160,12 +163,20 @@ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) > case RPC_AUTH_GSS: > pseudoflavor = rpcauth_get_pseudoflavor(secinfo->flavor, > &secinfo->flavor_info); > - if (pseudoflavor != RPC_AUTH_MAXFLAVOR) > + > + /* make sure pseudoflavor matches sec= mount opt */ > + if (pseudoflavor != RPC_AUTH_MAXFLAVOR && > + nfs_auth_info_match(&server->auth_info, > + pseudoflavor)) > return pseudoflavor; > break; > } > } > > + /* if there were any sec= options then nothing matched */ > + if (server->flags & NFS_MOUNT_SECFLAVOUR) > + return -EPERM; > + > return RPC_AUTH_UNIX; > } > > @@ -187,7 +198,7 @@ static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr > goto out; > } > > - flavor = nfs_find_best_sec(flavors); > + flavor = nfs_find_best_sec(NFS_SERVER(inode), flavors); > > out: > put_page(page); > @@ -390,7 +401,7 @@ struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry, > > if (client->cl_auth->au_flavor != flavor) > flavor = client->cl_auth->au_flavor; > - else if (!(server->flags & NFS_MOUNT_SECFLAVOUR)) { > + else { > rpc_authflavor_t new = nfs4_negotiate_security(dir, name); > if ((int)new >= 0) > flavor = new; > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c > index d2b4845..a926a39 100644 > --- a/fs/nfs/nfs4proc.c > +++ b/fs/nfs/nfs4proc.c > @@ -2864,11 +2864,22 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, > int status = -EPERM; > size_t i; > > - for (i = 0; i < ARRAY_SIZE(flav_array); i++) { > - status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); > - if (status == -NFS4ERR_WRONGSEC || status == -EACCES) > - continue; > - break; > + if (server->flags & NFS_MOUNT_SECFLAVOUR) { > + for (i = 0; i < server->auth_info.flavor_len; i++) { > + status = nfs4_lookup_root_sec(server, fhandle, info, > + server->auth_info.flavors[i]); > + if (status == -NFS4ERR_WRONGSEC || status == -EACCES) > + continue; > + break; > + } > + } else { > + for (i = 0; i < ARRAY_SIZE(flav_array); i++) { > + status = nfs4_lookup_root_sec(server, fhandle, info, > + flav_array[i]); > + if (status == -NFS4ERR_WRONGSEC || status == -EACCES) > + continue; > + break; > + } > } > > /* > @@ -2910,9 +2921,6 @@ int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, > status = nfs4_lookup_root(server, fhandle, info); > if (status != -NFS4ERR_WRONGSEC) > break; > - /* Did user force a 'sec=' mount option? */ > - if (server->flags & NFS_MOUNT_SECFLAVOUR) > - break; > default: > status = nfs4_do_find_root_sec(server, fhandle, info); > } > @@ -3165,9 +3173,6 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, > err = -EPERM; > if (client != *clnt) > goto out; > - /* No security negotiation if the user specified 'sec=' */ > - if (NFS_SERVER(dir)->flags & NFS_MOUNT_SECFLAVOUR) > - goto out; > client = nfs4_create_sec_client(client, dir, name); > if (IS_ERR(client)) > return PTR_ERR(client); > @@ -7617,6 +7622,9 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, > break; > } > > + if (!nfs_auth_info_match(&server->auth_info, flavor)) > + flavor = RPC_AUTH_MAXFLAVOR; > + > if (flavor != RPC_AUTH_MAXFLAVOR) { > err = nfs4_lookup_root_sec(server, fhandle, > info, flavor); > diff --git a/fs/nfs/super.c b/fs/nfs/super.c > index a03b9c6..84cf276 100644 > --- a/fs/nfs/super.c > +++ b/fs/nfs/super.c > @@ -497,7 +497,9 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) > static const struct { > rpc_authflavor_t flavour; > const char *str; > - } sec_flavours[] = { > + } sec_flavours[NFS_AUTH_INFO_MAX_FLAVORS] = { > + /* update NFS_AUTH_INFO_MAX_FLAVORS when this list > + * changes */ > { RPC_AUTH_NULL, "null" }, > { RPC_AUTH_UNIX, "sys" }, > { RPC_AUTH_GSS_KRB5, "krb5" }, > @@ -923,8 +925,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void) > data->mount_server.port = NFS_UNSPEC_PORT; > data->nfs_server.port = NFS_UNSPEC_PORT; > data->nfs_server.protocol = XPRT_TRANSPORT_TCP; > - data->auth_flavors[0] = RPC_AUTH_MAXFLAVOR; > - data->auth_flavor_len = 0; > + data->selected_flavor = RPC_AUTH_MAXFLAVOR; > data->minorversion = 0; > data->need_mount = true; > data->net = current->nsproxy->net_ns; > @@ -1019,13 +1020,48 @@ static void nfs_set_mount_transport_protocol(struct nfs_parsed_mount_data *mnt) > } > } > > -static void nfs_set_auth_parsed_mount_data(struct nfs_parsed_mount_data *data, > - rpc_authflavor_t pseudoflavor) > +/* > + * Add 'flavor' to 'auth_info' if not already present. > + * Returns true if 'flavor' ends up in the list, false otherwise > + */ > +static bool nfs_auth_info_add(struct nfs_auth_info *auth_info, > + rpc_authflavor_t flavor) > { > - data->auth_flavors[0] = pseudoflavor; > - data->auth_flavor_len = 1; > + unsigned int i; > + unsigned int max_flavor_len = (sizeof(auth_info->flavors) / > + sizeof(auth_info->flavors[0])); > + > + /* make sure this flavor isn't already in the list */ > + for (i = 0; i < auth_info->flavor_len; i++) { > + if (flavor == auth_info->flavors[i]) > + return true; > + } > + > + if (auth_info->flavor_len + 1 >= max_flavor_len) { > + dfprintk(MOUNT, "NFS: too many sec= flavors\n"); > + return false; > + } > + > + auth_info->flavors[auth_info->flavor_len++] = flavor; > + return true; > } > > +bool nfs_auth_info_match(const struct nfs_auth_info *auth_info, > + rpc_authflavor_t match) > +{ > + int i; > + > + if (!auth_info->flavor_len) > + return true; > + > + for (i = 0; i < auth_info->flavor_len; i++) { > + if (auth_info->flavors[i] == match) > + return true; > + } > + return false; > +} > +EXPORT_SYMBOL_GPL(nfs_auth_info_match); > + > /* > * Parse the value of the 'sec=' option. > */ > @@ -1034,49 +1070,61 @@ static int nfs_parse_security_flavors(char *value, > { > substring_t args[MAX_OPT_ARGS]; > rpc_authflavor_t pseudoflavor; > + char *p; > > dfprintk(MOUNT, "NFS: parsing sec=%s option\n", value); > > - switch (match_token(value, nfs_secflavor_tokens, args)) { > - case Opt_sec_none: > - pseudoflavor = RPC_AUTH_NULL; > - break; > - case Opt_sec_sys: > - pseudoflavor = RPC_AUTH_UNIX; > - break; > - case Opt_sec_krb5: > - pseudoflavor = RPC_AUTH_GSS_KRB5; > - break; > - case Opt_sec_krb5i: > - pseudoflavor = RPC_AUTH_GSS_KRB5I; > - break; > - case Opt_sec_krb5p: > - pseudoflavor = RPC_AUTH_GSS_KRB5P; > - break; > - case Opt_sec_lkey: > - pseudoflavor = RPC_AUTH_GSS_LKEY; > - break; > - case Opt_sec_lkeyi: > - pseudoflavor = RPC_AUTH_GSS_LKEYI; > - break; > - case Opt_sec_lkeyp: > - pseudoflavor = RPC_AUTH_GSS_LKEYP; > - break; > - case Opt_sec_spkm: > - pseudoflavor = RPC_AUTH_GSS_SPKM; > - break; > - case Opt_sec_spkmi: > - pseudoflavor = RPC_AUTH_GSS_SPKMI; > - break; > - case Opt_sec_spkmp: > - pseudoflavor = RPC_AUTH_GSS_SPKMP; > - break; > - default: > - return 0; > + while ((p = strsep(&value, ":")) != NULL) { > + switch (match_token(p, nfs_secflavor_tokens, args)) { > + case Opt_sec_none: > + pseudoflavor = RPC_AUTH_NULL; > + break; > + case Opt_sec_sys: > + pseudoflavor = RPC_AUTH_UNIX; > + break; > + case Opt_sec_krb5: > + pseudoflavor = RPC_AUTH_GSS_KRB5; > + break; > + case Opt_sec_krb5i: > + pseudoflavor = RPC_AUTH_GSS_KRB5I; > + break; > + case Opt_sec_krb5p: > + pseudoflavor = RPC_AUTH_GSS_KRB5P; > + break; > + case Opt_sec_lkey: > + pseudoflavor = RPC_AUTH_GSS_LKEY; > + break; > + case Opt_sec_lkeyi: > + pseudoflavor = RPC_AUTH_GSS_LKEYI; > + break; > + case Opt_sec_lkeyp: > + pseudoflavor = RPC_AUTH_GSS_LKEYP; > + break; > + case Opt_sec_spkm: > + pseudoflavor = RPC_AUTH_GSS_SPKM; > + break; > + case Opt_sec_spkmi: > + pseudoflavor = RPC_AUTH_GSS_SPKMI; > + break; > + case Opt_sec_spkmp: > + pseudoflavor = RPC_AUTH_GSS_SPKMP; > + break; > + default: > + dfprintk(MOUNT, > + "NFS: sec= option '%s' not recognized\n", p); > + return 0; > + } > + > + if (!nfs_auth_info_add(&mnt->auth_info, pseudoflavor)) > + return 0; > } > > - mnt->flags |= NFS_MOUNT_SECFLAVOUR; > - nfs_set_auth_parsed_mount_data(mnt, pseudoflavor); > + if (mnt->auth_info.flavor_len > 0) { > + mnt->flags |= NFS_MOUNT_SECFLAVOUR; > + mnt->selected_flavor = mnt->auth_info.flavors[0]; > + } else > + mnt->selected_flavor = RPC_AUTH_MAXFLAVOR; > + > return 1; > } > > @@ -1623,12 +1671,14 @@ out_security_failure: > } > > /* > - * Ensure that the specified authtype in args->auth_flavors[0] is supported by > - * the server. Returns 0 if it's ok, and -EACCES if not. > + * Ensure that a specified authtype in args->auth_info is supported by > + * the server. Returns 0 and sets args->selected_flavor if it's ok, and > + * -EACCES if not. > */ > -static int nfs_verify_authflavor(struct nfs_parsed_mount_data *args, > +static int nfs_verify_authflavors(struct nfs_parsed_mount_data *args, > rpc_authflavor_t *server_authlist, unsigned int count) > { > + rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR; > unsigned int i; > > /* > @@ -1640,17 +1690,20 @@ static int nfs_verify_authflavor(struct nfs_parsed_mount_data *args, > * can be used. > */ > for (i = 0; i < count; i++) { > - if (args->auth_flavors[0] == server_authlist[i] || > - server_authlist[i] == RPC_AUTH_NULL) > + flavor = server_authlist[i]; > + > + if (nfs_auth_info_match(&args->auth_info, flavor) || > + flavor == RPC_AUTH_NULL) > goto out; > } > > - dfprintk(MOUNT, "NFS: auth flavor %u not supported by server\n", > - args->auth_flavors[0]); > + dfprintk(MOUNT, > + "NFS: specified auth flavors not supported by server\n"); > return -EACCES; > > out: > - dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); > + args->selected_flavor = flavor; > + dfprintk(MOUNT, "NFS: using auth flavor %u\n", flavor); > return 0; > } > > @@ -1738,9 +1791,10 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf > * Was a sec= authflavor specified in the options? First, verify > * whether the server supports it, and then just try to use it if so. > */ > - if (args->auth_flavor_len > 0) { > - status = nfs_verify_authflavor(args, authlist, authlist_len); > - dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]); > + if (args->flags & NFS_MOUNT_SECFLAVOUR) { > + status = nfs_verify_authflavors(args, authlist, authlist_len); > + dfprintk(MOUNT, "NFS: using auth flavor %u\n", > + args->selected_flavor); > if (status) > return ERR_PTR(status); > return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); > @@ -1769,7 +1823,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf > /* Fallthrough */ > } > dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor); > - nfs_set_auth_parsed_mount_data(args, flavor); > + args->selected_flavor = flavor; > server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); > if (!IS_ERR(server)) > return server; > @@ -1785,7 +1839,7 @@ static struct nfs_server *nfs_try_mount_request(struct nfs_mount_info *mount_inf > > /* Last chance! Try AUTH_UNIX */ > dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX); > - nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); > + args->selected_flavor = RPC_AUTH_UNIX; > return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); > } > > @@ -1972,9 +2026,9 @@ static int nfs23_validate_mount_data(void *options, > args->bsize = data->bsize; > > if (data->flags & NFS_MOUNT_SECFLAVOUR) > - nfs_set_auth_parsed_mount_data(args, data->pseudoflavor); > + args->selected_flavor = data->pseudoflavor; > else > - nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); > + args->selected_flavor = RPC_AUTH_UNIX; > if (!args->nfs_server.hostname) > goto out_nomem; > > @@ -2108,9 +2162,6 @@ static int nfs_validate_text_mount_data(void *options, > > nfs_set_port(sap, &args->nfs_server.port, port); > > - if (args->auth_flavor_len > 1) > - goto out_bad_auth; > - > return nfs_parse_devname(dev_name, > &args->nfs_server.hostname, > max_namelen, > @@ -2130,10 +2181,6 @@ out_invalid_transport_udp: > out_no_address: > dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n"); > return -EINVAL; > - > -out_bad_auth: > - dfprintk(MOUNT, "NFS: Too many RPC auth flavours specified\n"); > - return -EINVAL; > } > > static int > @@ -2144,7 +2191,7 @@ nfs_compare_remount_data(struct nfs_server *nfss, > data->rsize != nfss->rsize || > data->wsize != nfss->wsize || > data->retrans != nfss->client->cl_timeout->to_retries || > - data->auth_flavors[0] != nfss->client->cl_auth->au_flavor || > + data->selected_flavor != nfss->client->cl_auth->au_flavor || > data->acregmin != nfss->acregmin / HZ || > data->acregmax != nfss->acregmax / HZ || > data->acdirmin != nfss->acdirmin / HZ || > @@ -2189,7 +2236,8 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) > data->rsize = nfss->rsize; > data->wsize = nfss->wsize; > data->retrans = nfss->client->cl_timeout->to_retries; > - nfs_set_auth_parsed_mount_data(data, nfss->client->cl_auth->au_flavor); > + data->selected_flavor = nfss->client->cl_auth->au_flavor; > + data->auth_info = nfss->auth_info; > data->acregmin = nfss->acregmin / HZ; > data->acregmax = nfss->acregmax / HZ; > data->acdirmin = nfss->acdirmin / HZ; > @@ -2713,9 +2761,9 @@ static int nfs4_validate_mount_data(void *options, > data->auth_flavours, > sizeof(pseudoflavor))) > return -EFAULT; > - nfs_set_auth_parsed_mount_data(args, pseudoflavor); > + args->selected_flavor = pseudoflavor; > } else > - nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX); > + args->selected_flavor = RPC_AUTH_UNIX; > > c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); > if (IS_ERR(c)) > diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h > index f9c0a6c..b2c3b82 100644 > --- a/include/linux/nfs_fs_sb.h > +++ b/include/linux/nfs_fs_sb.h > @@ -149,6 +149,7 @@ struct nfs_server { > struct timespec time_delta; /* smallest time granularity */ > unsigned long mount_time; /* when this fs was mounted */ > dev_t s_dev; /* superblock dev numbers */ > + struct nfs_auth_info auth_info; /* allowed auth flavors */ > > #ifdef CONFIG_NFS_FSCACHE > struct nfs_fscache_key *fscache_key; /* unique key for superblock */ > diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h > index 49f52c8..488ce9d 100644 > --- a/include/linux/nfs_xdr.h > +++ b/include/linux/nfs_xdr.h > @@ -591,6 +591,13 @@ struct nfs_renameres { > struct nfs_fattr *new_fattr; > }; > > +/* parsed sec= options */ > +#define NFS_AUTH_INFO_MAX_FLAVORS 12 /* see fs/nfs/super.c */ > +struct nfs_auth_info { > + unsigned int flavor_len; > + rpc_authflavor_t flavors[NFS_AUTH_INFO_MAX_FLAVORS]; > +}; > + > /* > * Argument struct for decode_entry function > */ > -- > 1.7.12.4 (Apple Git-37) > --- 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/utils/mount/nfs.man b/utils/mount/nfs.man index 2a42b93..17b8d88 100644 --- a/utils/mount/nfs.man +++ b/utils/mount/nfs.man @@ -380,9 +380,10 @@ If a value of zero is specified, the .BR mount (8) command exits immediately after the first failure. .TP 1.5i -.BI sec= flavor -The security flavor to use for accessing files on this mount point. -If the server does not support this flavor, the mount operation fails. +.BI sec= flavors +A colon-delimited list of security flavors to use for accessing files on +this mount point. If the server does not support any of these flavors, +the mount operation fails. If .B sec= is not specified, the client attempts to find dros@apikia% git diff ~/src/nfs-utils/utils/mount diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man index 2a42b93..17b8d88 100644 --- a/utils/mount/nfs.man +++ b/utils/mount/nfs.man @@ -380,9 +380,10 @@ If a value of zero is specified, the .BR mount (8) command exits immediately after the first failure. .TP 1.5i -.BI sec= flavor -The security flavor to use for accessing files on this mount point. -If the server does not support this flavor, the mount operation fails. +.BI sec= flavors +A colon-delimited list of security flavors to use for accessing files on +this mount point. If the server does not support any of these flavors, +the mount operation fails. If .B sec= is not specified, the client attempts to find