* [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.
@ 2006-10-27 21:16 Jesper Juhl
2006-10-27 21:46 ` David Rientjes
0 siblings, 1 reply; 9+ messages in thread
From: Jesper Juhl @ 2006-10-27 21:16 UTC (permalink / raw)
To: linux-kernel
Cc: Andreas Gruenbacher, Neil Brown, nfs, Andrew Morton, Jesper Juhl
In fs/nfsd/nfs2acl.c::nfsaclsvc_encode_getaclres() I see a few issues.
1) At the top of the function we assign to the 'inode' variable by
dereferencing 'dentry', but further down we test 'dentry' for NULL. So, if
'dentry' (which is really 'resp->fh.fh_dentry') can be NULL, then either
we have a potential NULL pointer deref bug or we have a superflous test.
2) In the case of resp->fh.fh_dentry != NULL we have a duplicate
assignment to 'inode' - just one would do.
3) There are two locations in the function where we may return before we
use the value of the variable 'w', but we compute it at the very top of the
function. So in the case where we return early we have wasted a few cycles
computing a value that was never used.
This patch solves these issues by :
1) Moving the computation of 'w' to just before it is used, after the two
potential returns.
2) Remove the initial assignment of 'dentry->d_inode'
(aka resp->fh.fh_dentry->d_inode) to 'inode' so that the assignment only
happens once and happens after the NULL test.
So we get 3 benefits from this patch :
1) We avoid a potential NULL pointer deref.
2) We save a few CPU cycles from not computing 'w' in the case of an early
return as well as saving the assignment to 'inode' in the dentry == NULL
case, and there's only a single assignment to 'inode' ever.
3) We save a few bytes of .text in the object file.
before:
text data bss dec hex filename
2502 204 0 2706 a92 fs/nfsd/nfs2acl.o
after:
text data bss dec hex filename
2489 204 0 2693 a85 fs/nfsd/nfs2acl.o
Patch is compile tested only since I don't currently have a setup where I
can meaningfully test it further.
Please comment and/or apply.
Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
---
fs/nfsd/nfs2acl.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index e3eca08..d89d63f 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -221,12 +221,10 @@ static int nfsaclsvc_encode_getaclres(st
struct nfsd3_getaclres *resp)
{
struct dentry *dentry = resp->fh.fh_dentry;
- struct inode *inode = dentry->d_inode;
- int w = nfsacl_size(
- (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
- (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
struct kvec *head = rqstp->rq_res.head;
+ struct inode *inode;
unsigned int base;
+ int w;
int n;
if (dentry == NULL || dentry->d_inode == NULL)
@@ -239,6 +237,9 @@ static int nfsaclsvc_encode_getaclres(st
return 0;
base = (char *)p - (char *)head->iov_base;
+ w = nfsacl_size(
+ (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
+ (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
rqstp->rq_res.page_len = w;
while (w > 0) {
if (!rqstp->rq_respages[rqstp->rq_resused++])
--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.
2006-10-27 21:16 [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization Jesper Juhl
@ 2006-10-27 21:46 ` David Rientjes
2006-10-27 22:01 ` Jesper Juhl
0 siblings, 1 reply; 9+ messages in thread
From: David Rientjes @ 2006-10-27 21:46 UTC (permalink / raw)
To: Jesper Juhl
Cc: linux-kernel, Andreas Gruenbacher, Neil Brown, nfs, Andrew Morton
On Fri, 27 Oct 2006, Jesper Juhl wrote:
> In fs/nfsd/nfs2acl.c::nfsaclsvc_encode_getaclres() I see a few issues.
>
> 1) At the top of the function we assign to the 'inode' variable by
> dereferencing 'dentry', but further down we test 'dentry' for NULL. So, if
> 'dentry' (which is really 'resp->fh.fh_dentry') can be NULL, then either
> we have a potential NULL pointer deref bug or we have a superflous test.
>
resp->fh.fh_dentry cannot be NULL on nfsaclsvc_encode_getaclres so the
early assignment is appropriate for both *dentry and *inode. *inode will
need to be checked for NULL in the conditional, however, and return 0 on
true.
> 3) There are two locations in the function where we may return before we
> use the value of the variable 'w', but we compute it at the very top of the
> function. So in the case where we return early we have wasted a few cycles
> computing a value that was never used.
>
w should be an unsigned int.
David
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.
2006-10-27 21:46 ` David Rientjes
@ 2006-10-27 22:01 ` Jesper Juhl
2006-10-31 16:26 ` Andreas Gruenbacher
0 siblings, 1 reply; 9+ messages in thread
From: Jesper Juhl @ 2006-10-27 22:01 UTC (permalink / raw)
To: David Rientjes
Cc: linux-kernel, Andreas Gruenbacher, Neil Brown, nfs, Andrew Morton,
Jesper Juhl
On Friday 27 October 2006 23:46, David Rientjes wrote:
> On Fri, 27 Oct 2006, Jesper Juhl wrote:
>
> > In fs/nfsd/nfs2acl.c::nfsaclsvc_encode_getaclres() I see a few issues.
> >
> > 1) At the top of the function we assign to the 'inode' variable by
> > dereferencing 'dentry', but further down we test 'dentry' for NULL. So, if
> > 'dentry' (which is really 'resp->fh.fh_dentry') can be NULL, then either
> > we have a potential NULL pointer deref bug or we have a superflous test.
> >
>
> resp->fh.fh_dentry cannot be NULL on nfsaclsvc_encode_getaclres so the
> early assignment is appropriate for both *dentry and *inode.
I didn't convince myself of that on my first scan of the code, that's why
I opted to keep the NULL check.
> *inode will
> need to be checked for NULL in the conditional, however, and return 0 on
> true.
>
Right, that agrees with my reading as well.
> > 3) There are two locations in the function where we may return before we
> > use the value of the variable 'w', but we compute it at the very top of the
> > function. So in the case where we return early we have wasted a few cycles
> > computing a value that was never used.
> >
>
> w should be an unsigned int.
>
Makes sense.
Thank you for commenting.
Here's a patch, on top of the previous one, to address you comments.
Feedback welcome.
Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
---
fs/nfsd/nfs2acl.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index d89d63f..069d7d0 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -222,14 +222,13 @@ static int nfsaclsvc_encode_getaclres(st
{
struct dentry *dentry = resp->fh.fh_dentry;
struct kvec *head = rqstp->rq_res.head;
- struct inode *inode;
+ struct inode *inode = dentry->d_inode;
unsigned int base;
- int w;
+ unsigned int w;
int n;
- if (dentry == NULL || dentry->d_inode == NULL)
+ if (!inode)
return 0;
- inode = dentry->d_inode;
p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
*p++ = htonl(resp->mask);
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.
2006-10-27 22:01 ` Jesper Juhl
@ 2006-10-31 16:26 ` Andreas Gruenbacher
2006-10-31 16:40 ` Jesper Juhl
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Andreas Gruenbacher @ 2006-10-31 16:26 UTC (permalink / raw)
To: Jesper Juhl; +Cc: David Rientjes, linux-kernel, Neil Brown, nfs, Andrew Morton
On Saturday 28 October 2006 00:01, Jesper Juhl wrote:
> > > 3) There are two locations in the function where we may return before
> > > we use the value of the variable 'w', but we compute it at the very top
> > > of the function. So in the case where we return early we have wasted a
> > > few cycles computing a value that was never used.
Computing w later in the function is fine.
> > w should be an unsigned int.
>
> Makes sense.
No, this breaks the while loop further below: with an unsigned int, the loop
counter underflows and wraps.
Please fix this identically in fs/nfsd/nfs2acl.c and fs/nfsd/nfs3acl.c.
Thanks,
Andreas
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.
2006-10-31 16:26 ` Andreas Gruenbacher
@ 2006-10-31 16:40 ` Jesper Juhl
2006-10-31 20:39 ` David Rientjes
2006-10-31 20:39 ` Small optimization for nfs3acl. (was: Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.) Jesper Juhl
2 siblings, 0 replies; 9+ messages in thread
From: Jesper Juhl @ 2006-10-31 16:40 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: David Rientjes, linux-kernel, Neil Brown, nfs, Andrew Morton
On 31/10/06, Andreas Gruenbacher <agruen@suse.de> wrote:
> On Saturday 28 October 2006 00:01, Jesper Juhl wrote:
> > > > 3) There are two locations in the function where we may return before
> > > > we use the value of the variable 'w', but we compute it at the very top
> > > > of the function. So in the case where we return early we have wasted a
> > > > few cycles computing a value that was never used.
>
> Computing w later in the function is fine.
>
> > > w should be an unsigned int.
> >
> > Makes sense.
>
> No, this breaks the while loop further below: with an unsigned int, the loop
> counter underflows and wraps.
>
Whoops. OK.
> Please fix this identically in fs/nfsd/nfs2acl.c and fs/nfsd/nfs3acl.c.
>
Sure thing, expect patches later this evening.
BTW: I posted an add-on patch on top of my first one - apart from the
"make w unsigned" bit, is the rest of that OK?
--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please http://www.expita.com/nomime.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.
2006-10-31 16:26 ` Andreas Gruenbacher
2006-10-31 16:40 ` Jesper Juhl
@ 2006-10-31 20:39 ` David Rientjes
2006-11-02 15:07 ` Andreas Gruenbacher
2006-10-31 20:39 ` Small optimization for nfs3acl. (was: Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.) Jesper Juhl
2 siblings, 1 reply; 9+ messages in thread
From: David Rientjes @ 2006-10-31 20:39 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: Jesper Juhl, linux-kernel, Neil Brown, nfs, Andrew Morton
On Tue, 31 Oct 2006, Andreas Gruenbacher wrote:
> > > w should be an unsigned int.
> >
> > Makes sense.
>
> No, this breaks the while loop further below: with an unsigned int, the loop
> counter underflows and wraps.
>
This is not a problem with w being an unsigned int, it's a problem with
the while loop. nfsacl_size() returns unsigned int as it should and the
while loop can be written to respect that since integer division in C
truncates:
for (n = w / PAGE_SIZE; n > 0; n--)
if (!rqstp->rq_respages[rqstp->rq_resused++];
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.
2006-10-31 20:39 ` David Rientjes
@ 2006-11-02 15:07 ` Andreas Gruenbacher
0 siblings, 0 replies; 9+ messages in thread
From: Andreas Gruenbacher @ 2006-11-02 15:07 UTC (permalink / raw)
To: David Rientjes; +Cc: Jesper Juhl, linux-kernel, Neil Brown, nfs, Andrew Morton
On Tuesday 31 October 2006 21:39, David Rientjes wrote:
> On Tue, 31 Oct 2006, Andreas Gruenbacher wrote:
> > > > w should be an unsigned int.
> > >
> > > Makes sense.
> >
> > No, this breaks the while loop further below: with an unsigned int, the
> > loop counter underflows and wraps.
>
> This is not a problem with w being an unsigned int, it's a problem with
> the while loop. nfsacl_size() returns unsigned int as it should and the
> while loop can be written to respect that since integer division in C
> truncates:
>
> for (n = w / PAGE_SIZE; n > 0; n--)
> if (!rqstp->rq_respages[rqstp->rq_resused++];
Assuming that PAGE_SIZE = 4096 and w = 100, the original loop iterates once,
while your proposed version iterates zero times -- the current code does the
right thing. So the proposed change is still bad, sorry.
Andreas
^ permalink raw reply [flat|nested] 9+ messages in thread
* Small optimization for nfs3acl. (was: Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.)
2006-10-31 16:26 ` Andreas Gruenbacher
2006-10-31 16:40 ` Jesper Juhl
2006-10-31 20:39 ` David Rientjes
@ 2006-10-31 20:39 ` Jesper Juhl
2006-11-02 15:06 ` Andreas Gruenbacher
2 siblings, 1 reply; 9+ messages in thread
From: Jesper Juhl @ 2006-10-31 20:39 UTC (permalink / raw)
To: Andreas Gruenbacher
Cc: David Rientjes, linux-kernel, Neil Brown, nfs, Andrew Morton
On Tuesday 31 October 2006 17:26, Andreas Gruenbacher wrote:
> On Saturday 28 October 2006 00:01, Jesper Juhl wrote:
> > > > 3) There are two locations in the function where we may return before
> > > > we use the value of the variable 'w', but we compute it at the very top
> > > > of the function. So in the case where we return early we have wasted a
> > > > few cycles computing a value that was never used.
>
> Computing w later in the function is fine.
>
...
>
> Please fix this identically in fs/nfsd/nfs2acl.c and fs/nfsd/nfs3acl.c.
>
Here's a patch for nfs3. Hope it's OK.
Saves a few bytes of .text and avoids calculating 'w' in
nfs3svc_encode_getaclres() in case we return before it's needed.
text data bss dec hex filename
1688 132 0 1820 71c fs/nfsd/nfs3acl.o
Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
---
fs/nfsd/nfs3acl.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index fcad289..eb1cf22 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -171,11 +171,9 @@ static int nfs3svc_encode_getaclres(stru
p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
if (resp->status == 0 && dentry && dentry->d_inode) {
struct inode *inode = dentry->d_inode;
- int w = nfsacl_size(
- (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
- (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
struct kvec *head = rqstp->rq_res.head;
unsigned int base;
+ int w;
int n;
*p++ = htonl(resp->mask);
@@ -183,6 +181,9 @@ static int nfs3svc_encode_getaclres(stru
return 0;
base = (char *)p - (char *)head->iov_base;
+ w = nfsacl_size(
+ (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
+ (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
rqstp->rq_res.page_len = w;
while (w > 0) {
if (!rqstp->rq_respages[rqstp->rq_resused++])
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2006-11-02 15:07 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-27 21:16 [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization Jesper Juhl
2006-10-27 21:46 ` David Rientjes
2006-10-27 22:01 ` Jesper Juhl
2006-10-31 16:26 ` Andreas Gruenbacher
2006-10-31 16:40 ` Jesper Juhl
2006-10-31 20:39 ` David Rientjes
2006-11-02 15:07 ` Andreas Gruenbacher
2006-10-31 20:39 ` Small optimization for nfs3acl. (was: Re: [PATCH] NFS: nfsaclsvc_encode_getaclres() - Fix potential NULL deref and tiny optimization.) Jesper Juhl
2006-11-02 15:06 ` Andreas Gruenbacher
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox