From: "J. Bruce Fields" <bfields@fieldses.org>
To: Chuck Lever <chuck.lever@oracle.com>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [PATCH] nfs: Fix misparsing of nfsv4 fs_locations attribute
Date: Wed, 20 Aug 2008 16:08:27 -0400 [thread overview]
Message-ID: <20080820200827.GC21226@fieldses.org> (raw)
In-Reply-To: <52C9C44B-750E-437C-B3E8-380DB7371629@oracle.com>
On Fri, Aug 15, 2008 at 12:59:09PM -0400, Chuck Lever wrote:
> On Aug 14, 2008, at 6:30 PM, J. Bruce Fields wrote:
>> I was looking back at this bug with the misparsing of
>> (non-mull-terminated) fs_locations attributes. Thanks to the work on
>> nfs_parse_server_address, etc., we can now also more easily support
>> ipv6
>> addresses here. But I got lost in the usual maze of twisty struct
>> sockaddr_*'s, all alike. Is this right? Does any of it need to be
>> under CONFIG_IPV6? Is there a simpler way?
>
> The use of the new address parser looks correct, but your string
> handling needs work. :-)
>
> Comments below...
Pffft. My hope that someone else would pick this up for me was
obviously fantasy. OK, thanks for comments:
>> diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
>> index b112857..c0f5191 100644
...
>> + if (memchr(buf->data, '%', buf->len))
>> + goto next;
>
> Why are you looking for a '%' ?
Would it have been clearer if I'd moved the IPV6_SCOPE_DELIMITER define
to a common header? I don't think that has any place in the nfs
protocol. And we've got less trust in the address we're parsing here
(which came across the wire) then we would in a mount commandline.
>
>> + nfs_parse_ip_address(buf->data, buf->len,
>> + mountdata.addr, &mountdata.addrlen);
>
> Now what's so hard about that? :-)
Yeah, yeah....
>>
>> + switch (mountdata.addr->sa_family) {
>> + case AF_UNSPEC:
>> + goto next;
>> + case AF_INET:
>> + ((struct sockaddr_in *)&addr)->sin_port =
>> + htons(NFS_PORT);
>> + break;
>> + case AF_INET6:
>> + ((struct sockaddr_in6 *)&addr)->sin6_port =
>> + htons(NFS_PORT);
>> + break;
>> + }
>
> It might be cleaner to pull the whole while {} loop into a separate
> function. I didn't look closely enough to see if this would be easy.
Yup, done.
>
> At least here, you could set the port in a small helper function, and
> then put an "if (unlikely(family == AF_UNSPEC)) goto next;" just after
> the call to nfs_parse_ip_address, to save all the crazy indenting. If
> we ever create a global helper to manage AF-agnostic port setting, that
> would make it easier to use here if the AF_UNSPEC check were separate.
>
> In fact, as part of this patch you could add a static inline helper in
> fs/nfs/internal.h to do the port setting. That can be shared between
> fs/nfs/super.c and fs/nfs/nfs4namespace.c.
>
> Arguably the addition of the AF_UNSPEC check in the switch statement is
> an optimization that is slightly confusing. You are checking for
> AF_UNSPEC to see if you should continue the loop, but the other cases
> are for setting a port; two entirely different purposes.
>
> It would be more precise structuring to keep these two separate, even
> though it might add an extra conditional branch. This makes it easier
> to spot the loop condition expressions.
Agreed, done.
>
>> +
>> + mountdata.hostname = kmalloc(buf->len + 1, GFP_KERNEL);
>> + mountdata.hostname[buf->len] = 0;
>
> The usual practice is to use '\0' here since it is a character array; 0
> is an int, not a character, so this does an implicit cast. Harmless, but
> using a character constant is more precise.
OK, done.
> But I'm not sure why you are not using location->servers[s].data (or
> buf->data).
The mountdata->hostname field needs a null terminated string.
> You kmalloc a buffer for hostname, but aren't setting it to
> anything. Did you mean kstrndup?
Whoops. Actually, since the code tries to allocate memory for us at the
start, it probably makes more sense just to use a piece of that memory;
done.
>> snprintf(page, PAGE_SIZE, "%s:%s",
>> mountdata.hostname,
>> mountdata.mnt_path);
>
> For snprintf, you can specify the length of the string with a "%.*s"
> format. Then you pass buf->len and buf->data (in that order) to it.
> That way you can print a non-NUL-terminated string safely. That should
> make any memory allocation or string copying unnecessary here.
No, mountdata.hostname independently still needs to be null terminated.
>
>> mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, &mountdata);
>> + kfree(mountdata.hostname);
>
> mountdata.hostname is used in other places... I don't think you can just
> free it here. Another reason to use a pointer to location-
> >servers[s].data.
That memory will go away soon, too. The previous code is actually just
pointing to data on the stack. So it's the callee's responsibility to
make any copies it needs before returning.
> If location->servers[s].data isn't always NUL-terminated, you might make
> mountdata.hostname an nfs4_string so it carries the string length with
> it; the other users of mountdata.hostname can then see the length.
That's passed around a lot and the assumption that it's null terminated
appears to be common (and convenient).
>> --- a/include/linux/nfs_fs.h
>> +++ b/include/linux/nfs_fs.h
>> @@ -444,6 +444,8 @@ extern const struct inode_operations
>> nfs_referral_inode_operations;
>> extern int nfs_mountpoint_expiry_timeout;
>> extern void nfs_release_automount_timer(void);
>>
>> +void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t
>> *);
>> +
>
> Perhaps a better place for this would be fs/nfs/internal.h. This
> function is used only internally in fs/nfs; no need to expose it to user
> space.
Yep, done.
--b.
next prev parent reply other threads:[~2008-08-20 20:08 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-14 22:30 [PATCH] nfs: Fix misparsing of nfsv4 fs_locations attribute J. Bruce Fields
2008-08-15 16:59 ` Chuck Lever
2008-08-15 22:00 ` Chuck Lever
2008-08-20 20:08 ` J. Bruce Fields [this message]
2008-08-20 20:10 ` [PATCH 1/4] nfs: break up nfs_follow_referral J. Bruce Fields
2008-08-20 20:10 ` [PATCH 2/4] nfs: replace while loop by for loops in nfs_follow_referral J. Bruce Fields
2008-08-20 20:10 ` [PATCH 3/4] nfs: prepare to share nfs_set_port J. Bruce Fields
2008-08-20 20:10 ` [PATCH 4/4] nfs: Fix misparsing of nfsv4 fs_locations attribute J. Bruce Fields
2008-08-20 20:23 ` [PATCH 3/4] nfs: prepare to share nfs_set_port Chuck Lever
[not found] ` <76bd70e30808201323h32debdeaj31577cd19b87612e-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-20 21:03 ` J. Bruce Fields
2008-08-20 20:19 ` [PATCH] nfs: Fix misparsing of nfsv4 fs_locations attribute Chuck Lever
[not found] ` <76bd70e30808201319j7b59de5gc912fcd01594e8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-20 20:47 ` J. Bruce Fields
2008-08-20 21:19 ` Chuck Lever
[not found] ` <76bd70e30808201419g5171d7eob7e6b57dd735e07d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-20 21:29 ` J. Bruce Fields
2008-08-20 22:07 ` Chuck Lever
[not found] ` <76bd70e30808201507l44c85d08o3ec4e8eeb7edda5e-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-20 23:30 ` J. Bruce Fields
2008-08-21 2:00 ` Chuck Lever
[not found] ` <76bd70e30808201900r699ca044o884584ecedc6a799-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-21 20:46 ` J. Bruce Fields
2008-08-21 22:22 ` Chuck Lever
[not found] ` <76bd70e30808211522k7cb6846fs4e371c8003320fe7-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-21 22:54 ` J. Bruce Fields
2008-08-21 23:05 ` Chuck Lever
[not found] ` <76bd70e30808211605j3c32cc44v440c19e5fe81bdc9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-22 18:25 ` Chuck Lever
-- strict thread matches above, loose matches on Subject: below --
2008-05-09 1:19 referrals J. Bruce Fields
2008-05-09 5:10 ` referrals Trond Myklebust
2008-05-09 15:27 ` referrals J. Bruce Fields
2008-05-09 16:52 ` referrals J. Bruce Fields
2008-05-09 17:12 ` referrals J. Bruce Fields
2008-05-09 23:59 ` [PATCH] nfs: Fix misparsing of nfsv4 fs_locations attribute J. Bruce Fields
2008-05-10 0:15 ` Benny Halevy
2008-05-10 1:06 ` J. Bruce Fields
2008-05-10 2:29 ` Chuck Lever
2008-05-10 17:32 ` Trond Myklebust
2008-05-10 23:50 ` Chuck Lever
2008-05-11 1:07 ` david m. richter
[not found] ` <1d07ca700805101807s7c034b08sc531993aa81010b2-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-16 19:53 ` J. Bruce Fields
2008-05-17 2:25 ` Chuck Lever
2008-05-18 15:22 ` Chuck Lever
2008-05-20 2:47 ` J. Bruce Fields
2008-05-20 16:54 ` Chuck Lever
2008-05-20 19:32 ` Trond Myklebust
2008-05-20 19:38 ` Chuck Lever
2008-05-20 19:42 ` Trond Myklebust
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080820200827.GC21226@fieldses.org \
--to=bfields@fieldses.org \
--cc=chuck.lever@oracle.com \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox