nfsd: Return EPERM on utime/utimes/lutimes calls instead of EACCESS in some cases
diff mbox series

Message ID 1543564290-147370-1-git-send-email-zhengbin13@huawei.com
State New
Headers show
Series
  • nfsd: Return EPERM on utime/utimes/lutimes calls instead of EACCESS in some cases
Related show

Commit Message

zhengbin Nov. 30, 2018, 7:51 a.m. UTC
As the man(3) page for utime/utimes/lutimes, EPERM is returned
when the second parameter of utime/utimes/lutimes is not NULL,
the caller's effective UID does not match the owner of the file,
and the caller is not privileged.

However, in a NFS directory, it will return EACCESS(nfsd_setattr->
fh_verify->nfsd_permission), This patch fix this.

Signed-off-by: zhengbin <zhengbin13@huawei.com>
---
 fs/nfsd/vfs.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

--
2.7.4

Comments

zhengbin Dec. 3, 2018, 8:36 a.m. UTC | #1
hi, J. Bruce Fields, Jeff Layton

 When you have time, confirm it? thanks

On 2018/11/30 15:51, zhengbin wrote:
> As the man(3) page for utime/utimes/lutimes, EPERM is returned
> when the second parameter of utime/utimes/lutimes is not NULL,
> the caller's effective UID does not match the owner of the file,
> and the caller is not privileged.
> 
> However, in a NFS directory, it will return EACCESS(nfsd_setattr->
> fh_verify->nfsd_permission), This patch fix this.
> 
> Signed-off-by: zhengbin <zhengbin13@huawei.com>
> ---
>  fs/nfsd/vfs.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index eb67098..9824e32 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -396,10 +396,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
>  	bool		get_write_count;
>  	bool		size_change = (iap->ia_valid & ATTR_SIZE);
> 
> -	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
> +	if (iap->ia_valid & ATTR_SIZE) {
>  		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
> -	if (iap->ia_valid & ATTR_SIZE)
>  		ftype = S_IFREG;
> +	}
> +
> +	/*
> +	 * If utimes(2) and friends are called with times not NULL, we should
> +	 * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
> +	 * will return EACCESS, when the caller's effective UID does not match
> +	 * the owner of the file, and the caller is not privileged. In this
> +	 * situation, we should return EPERM(notify_change will return this).
> +	 */
> +	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
> +		accmode |= NFSD_MAY_OWNER_OVERRIDE;
> +		if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
> +			accmode |= NFSD_MAY_WRITE;
> +	}
> 
>  	/* Callers that do fh_verify should do the fh_want_write: */
>  	get_write_count = !fhp->fh_dentry;
> --
> 2.7.4
> 
> 
> .
>
Bruce Fields Dec. 4, 2018, 8:13 p.m. UTC | #2
On Mon, Dec 03, 2018 at 04:36:27PM +0800, zhengbin (A) wrote:
> hi, J. Bruce Fields, Jeff Layton
> 
>  When you have time, confirm it? thanks

Sorry for the delay.

The patch looks good to me.

As far as I can tell, we've done this forever.  And I'm a little worried
about changing such long-standing behavior, but I think you're right.

So, applying for for 4.21.

--b.

> On 2018/11/30 15:51, zhengbin wrote:
> > As the man(3) page for utime/utimes/lutimes, EPERM is returned
> > when the second parameter of utime/utimes/lutimes is not NULL,
> > the caller's effective UID does not match the owner of the file,
> > and the caller is not privileged.
> > 
> > However, in a NFS directory, it will return EACCESS(nfsd_setattr->
> > fh_verify->nfsd_permission), This patch fix this.
> > 
> > Signed-off-by: zhengbin <zhengbin13@huawei.com>
> > ---
> >  fs/nfsd/vfs.c | 17 +++++++++++++++--
> >  1 file changed, 15 insertions(+), 2 deletions(-)
> > 
> > diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> > index eb67098..9824e32 100644
> > --- a/fs/nfsd/vfs.c
> > +++ b/fs/nfsd/vfs.c
> > @@ -396,10 +396,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
> >  	bool		get_write_count;
> >  	bool		size_change = (iap->ia_valid & ATTR_SIZE);
> > 
> > -	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
> > +	if (iap->ia_valid & ATTR_SIZE) {
> >  		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
> > -	if (iap->ia_valid & ATTR_SIZE)
> >  		ftype = S_IFREG;
> > +	}
> > +
> > +	/*
> > +	 * If utimes(2) and friends are called with times not NULL, we should
> > +	 * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
> > +	 * will return EACCESS, when the caller's effective UID does not match
> > +	 * the owner of the file, and the caller is not privileged. In this
> > +	 * situation, we should return EPERM(notify_change will return this).
> > +	 */
> > +	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
> > +		accmode |= NFSD_MAY_OWNER_OVERRIDE;
> > +		if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
> > +			accmode |= NFSD_MAY_WRITE;
> > +	}
> > 
> >  	/* Callers that do fh_verify should do the fh_want_write: */
> >  	get_write_count = !fhp->fh_dentry;
> > --
> > 2.7.4
> > 
> > 
> > .
> >
zhengbin Dec. 5, 2018, 1:04 a.m. UTC | #3
thanks,
>>> As the man(3) page for utime/utimes/lutimes, EPERM is returned

-------->this should be As the man page for utime/utimes/lutimes, my little mistake. utime/utimes are man(2), lutimes is man(3)

I send v2 patch?Or when you apply, help modify it?

On 2018/12/5 4:13, J. Bruce Fields wrote:
> On Mon, Dec 03, 2018 at 04:36:27PM +0800, zhengbin (A) wrote:
>> hi, J. Bruce Fields, Jeff Layton
>>
>>  When you have time, confirm it? thanks
> 
> Sorry for the delay.
> 
> The patch looks good to me.
> 
> As far as I can tell, we've done this forever.  And I'm a little worried
> about changing such long-standing behavior, but I think you're right.
> 
> So, applying for for 4.21.
> 
> --b.
> 
>> On 2018/11/30 15:51, zhengbin wrote:
>>> As the man(3) page for utime/utimes/lutimes, EPERM is returned
>>> when the second parameter of utime/utimes/lutimes is not NULL,
>>> the caller's effective UID does not match the owner of the file,
>>> and the caller is not privileged.
>>>
>>> However, in a NFS directory, it will return EACCESS(nfsd_setattr->
>>> fh_verify->nfsd_permission), This patch fix this.
>>>
>>> Signed-off-by: zhengbin <zhengbin13@huawei.com>
>>> ---
>>>  fs/nfsd/vfs.c | 17 +++++++++++++++--
>>>  1 file changed, 15 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
>>> index eb67098..9824e32 100644
>>> --- a/fs/nfsd/vfs.c
>>> +++ b/fs/nfsd/vfs.c
>>> @@ -396,10 +396,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
>>>  	bool		get_write_count;
>>>  	bool		size_change = (iap->ia_valid & ATTR_SIZE);
>>>
>>> -	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
>>> +	if (iap->ia_valid & ATTR_SIZE) {
>>>  		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
>>> -	if (iap->ia_valid & ATTR_SIZE)
>>>  		ftype = S_IFREG;
>>> +	}
>>> +
>>> +	/*
>>> +	 * If utimes(2) and friends are called with times not NULL, we should
>>> +	 * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
>>> +	 * will return EACCESS, when the caller's effective UID does not match
>>> +	 * the owner of the file, and the caller is not privileged. In this
>>> +	 * situation, we should return EPERM(notify_change will return this).
>>> +	 */
>>> +	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
>>> +		accmode |= NFSD_MAY_OWNER_OVERRIDE;
>>> +		if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
>>> +			accmode |= NFSD_MAY_WRITE;
>>> +	}
>>>
>>>  	/* Callers that do fh_verify should do the fh_want_write: */
>>>  	get_write_count = !fhp->fh_dentry;
>>> --
>>> 2.7.4
>>>
>>>
>>> .
>>>
> 
> .
>
Bruce Fields Dec. 5, 2018, 1:37 a.m. UTC | #4
On Wed, Dec 05, 2018 at 09:04:22AM +0800, zhengbin (A) wrote:
> thanks,
> >>> As the man(3) page for utime/utimes/lutimes, EPERM is returned
> 
> -------->this should be As the man page for utime/utimes/lutimes, my little mistake. utime/utimes are man(2), lutimes is man(3)
> 
> I send v2 patch?Or when you apply, help modify it?

Does this look OK?

--b.

commit eb6d67589750
Author: zhengbin <zhengbin13@huawei.com>
Date:   Fri Nov 30 16:04:25 2018 +0800

    nfsd: Return EPERM, not EACCES, in some SETATTR cases
    
    As the man(2) page for utime/utimes states, EPERM is returned when the
    second parameter of utime/utimes/lutimes is not NULL, the caller's
    effective UID does not match the owner of the file, and the caller is
    not privileged.
    
    However, in a NFS directory mounted from knfsd, it will return EACCES
    (from nfsd_setattr-> fh_verify->nfsd_permission).  This patch fixes
    that.
    
    Signed-off-by: zhengbin <zhengbin13@huawei.com>
    Signed-off-by: J. Bruce Fields <bfields@redhat.com>

diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index eb67098117b4..9824e32b2f23 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -396,10 +396,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
 	bool		get_write_count;
 	bool		size_change = (iap->ia_valid & ATTR_SIZE);
 
-	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
+	if (iap->ia_valid & ATTR_SIZE) {
 		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
-	if (iap->ia_valid & ATTR_SIZE)
 		ftype = S_IFREG;
+	}
+
+	/*
+	 * If utimes(2) and friends are called with times not NULL, we should
+	 * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
+	 * will return EACCESS, when the caller's effective UID does not match
+	 * the owner of the file, and the caller is not privileged. In this
+	 * situation, we should return EPERM(notify_change will return this).
+	 */
+	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
+		accmode |= NFSD_MAY_OWNER_OVERRIDE;
+		if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
+			accmode |= NFSD_MAY_WRITE;
+	}
 
 	/* Callers that do fh_verify should do the fh_want_write: */
 	get_write_count = !fhp->fh_dentry;
zhengbin Dec. 5, 2018, 1:43 a.m. UTC | #5
second parameter of utime/utimes/lutimes is not NULL   -------> maybe lutimes should be removed? I think "second parameter of utime/utimes is not NULL" would be better

On 2018/12/5 9:37, J. Bruce Fields wrote:
> On Wed, Dec 05, 2018 at 09:04:22AM +0800, zhengbin (A) wrote:
>> thanks,
>>>>> As the man(3) page for utime/utimes/lutimes, EPERM is returned
>>
>> -------->this should be As the man page for utime/utimes/lutimes, my little mistake. utime/utimes are man(2), lutimes is man(3)
>>
>> I send v2 patch?Or when you apply, help modify it?
> 
> Does this look OK?
> 
> --b.
> 
> commit eb6d67589750
> Author: zhengbin <zhengbin13@huawei.com>
> Date:   Fri Nov 30 16:04:25 2018 +0800
> 
>     nfsd: Return EPERM, not EACCES, in some SETATTR cases
>     
>     As the man(2) page for utime/utimes states, EPERM is returned when the
>     second parameter of utime/utimes/lutimes is not NULL, the caller's
>     effective UID does not match the owner of the file, and the caller is
>     not privileged.
>     
>     However, in a NFS directory mounted from knfsd, it will return EACCES
>     (from nfsd_setattr-> fh_verify->nfsd_permission).  This patch fixes
>     that.
>     
>     Signed-off-by: zhengbin <zhengbin13@huawei.com>
>     Signed-off-by: J. Bruce Fields <bfields@redhat.com>
> 
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index eb67098117b4..9824e32b2f23 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -396,10 +396,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
>  	bool		get_write_count;
>  	bool		size_change = (iap->ia_valid & ATTR_SIZE);
>  
> -	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
> +	if (iap->ia_valid & ATTR_SIZE) {
>  		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
> -	if (iap->ia_valid & ATTR_SIZE)
>  		ftype = S_IFREG;
> +	}
> +
> +	/*
> +	 * If utimes(2) and friends are called with times not NULL, we should
> +	 * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
> +	 * will return EACCESS, when the caller's effective UID does not match
> +	 * the owner of the file, and the caller is not privileged. In this
> +	 * situation, we should return EPERM(notify_change will return this).
> +	 */
> +	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
> +		accmode |= NFSD_MAY_OWNER_OVERRIDE;
> +		if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
> +			accmode |= NFSD_MAY_WRITE;
> +	}
>  
>  	/* Callers that do fh_verify should do the fh_want_write: */
>  	get_write_count = !fhp->fh_dentry;
> 
> .
>
Bruce Fields Dec. 5, 2018, 1:49 a.m. UTC | #6
On Wed, Dec 05, 2018 at 09:43:06AM +0800, zhengbin (A) wrote:
>  second parameter of utime/utimes/lutimes is not NULL   -------> maybe lutimes should be removed? I think "second parameter of utime/utimes is not NULL" would be better

Also fixed, thanks.--b.

> 
> On 2018/12/5 9:37, J. Bruce Fields wrote:
> > On Wed, Dec 05, 2018 at 09:04:22AM +0800, zhengbin (A) wrote:
> >> thanks,
> >>>>> As the man(3) page for utime/utimes/lutimes, EPERM is returned
> >>
> >> -------->this should be As the man page for utime/utimes/lutimes, my little mistake. utime/utimes are man(2), lutimes is man(3)
> >>
> >> I send v2 patch?Or when you apply, help modify it?
> > 
> > Does this look OK?
> > 
> > --b.
> > 
> > commit eb6d67589750
> > Author: zhengbin <zhengbin13@huawei.com>
> > Date:   Fri Nov 30 16:04:25 2018 +0800
> > 
> >     nfsd: Return EPERM, not EACCES, in some SETATTR cases
> >     
> >     As the man(2) page for utime/utimes states, EPERM is returned when the
> >     second parameter of utime/utimes/lutimes is not NULL, the caller's
> >     effective UID does not match the owner of the file, and the caller is
> >     not privileged.
> >     
> >     However, in a NFS directory mounted from knfsd, it will return EACCES
> >     (from nfsd_setattr-> fh_verify->nfsd_permission).  This patch fixes
> >     that.
> >     
> >     Signed-off-by: zhengbin <zhengbin13@huawei.com>
> >     Signed-off-by: J. Bruce Fields <bfields@redhat.com>
> > 
> > diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> > index eb67098117b4..9824e32b2f23 100644
> > --- a/fs/nfsd/vfs.c
> > +++ b/fs/nfsd/vfs.c
> > @@ -396,10 +396,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
> >  	bool		get_write_count;
> >  	bool		size_change = (iap->ia_valid & ATTR_SIZE);
> >  
> > -	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
> > +	if (iap->ia_valid & ATTR_SIZE) {
> >  		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
> > -	if (iap->ia_valid & ATTR_SIZE)
> >  		ftype = S_IFREG;
> > +	}
> > +
> > +	/*
> > +	 * If utimes(2) and friends are called with times not NULL, we should
> > +	 * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
> > +	 * will return EACCESS, when the caller's effective UID does not match
> > +	 * the owner of the file, and the caller is not privileged. In this
> > +	 * situation, we should return EPERM(notify_change will return this).
> > +	 */
> > +	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
> > +		accmode |= NFSD_MAY_OWNER_OVERRIDE;
> > +		if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
> > +			accmode |= NFSD_MAY_WRITE;
> > +	}
> >  
> >  	/* Callers that do fh_verify should do the fh_want_write: */
> >  	get_write_count = !fhp->fh_dentry;
> > 
> > .
> >

Patch
diff mbox series

diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index eb67098..9824e32 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -396,10 +396,23 @@  nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
 	bool		get_write_count;
 	bool		size_change = (iap->ia_valid & ATTR_SIZE);

-	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
+	if (iap->ia_valid & ATTR_SIZE) {
 		accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
-	if (iap->ia_valid & ATTR_SIZE)
 		ftype = S_IFREG;
+	}
+
+	/*
+	 * If utimes(2) and friends are called with times not NULL, we should
+	 * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
+	 * will return EACCESS, when the caller's effective UID does not match
+	 * the owner of the file, and the caller is not privileged. In this
+	 * situation, we should return EPERM(notify_change will return this).
+	 */
+	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
+		accmode |= NFSD_MAY_OWNER_OVERRIDE;
+		if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
+			accmode |= NFSD_MAY_WRITE;
+	}

 	/* Callers that do fh_verify should do the fh_want_write: */
 	get_write_count = !fhp->fh_dentry;