While debugging an unrelated problem, I noticed these two cases fdput()
is called after failed fdget() while reviewing at all the fdget() and
fdput() paths in the kernel.
Changes since v1:
Patch 1:
Changed to address review comments to refine the code for improved
readability in addition to the change to avoid fdput() on failed
fdget()
Patch 2:
No change to v1. Including it in the series to keep the patches
together.
Shuah Khan (2):
fs: avoid fdput() after failed fdget() in ksys_sync_file_range()
fs: avoid fdput() after failed fdget() in kernel_read_file_from_fd()
fs/exec.c | 2 +-
fs/sync.c | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
--
2.25.1
Fix ksys_sync_file_range() to avoid fdput() after a failed fdget().
fdput() doesn't do fput() on this file since FDPUT_FPUT isn't set
in fd.flags.
Change it anyway since failed fdget() doesn't require a fdput(). Refine
the code path a bit for it to read more clearly.
Reference: commit 22f96b3808c1 ("fs: add sync_file_range() helper")
Signed-off-by: Shuah Khan <[email protected]>
---
fs/sync.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/sync.c b/fs/sync.c
index 4d1ff010bc5a..300ca73ec87c 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -364,15 +364,15 @@ int sync_file_range(struct file *file, loff_t offset, loff_t nbytes,
int ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
unsigned int flags)
{
- int ret;
- struct fd f;
+ int ret = -EBADF;
+ struct fd f = fdget(fd);
- ret = -EBADF;
- f = fdget(fd);
- if (f.file)
- ret = sync_file_range(f.file, offset, nbytes, flags);
+ if (!f.file)
+ goto out;
+ ret = sync_file_range(f.file, offset, nbytes, flags);
fdput(f);
+out:
return ret;
}
--
2.25.1
Fix kernel_read_file_from_fd() to avoid fdput() after a failed fdget().
fdput() doesn't do fput() on this file since FDPUT_FPUT isn't set
in fd.flags. Fix it anyway since failed fdget() doesn't require
a fdput().
This was introduced in a commit that added kernel_read_file_from_fd() as
a wrapper for the VFS common kernel_read_file().
Fixes: b844f0ecbc56 ("vfs: define kernel_copy_file_from_fd()")
Signed-off-by: Shuah Khan <[email protected]>
---
fs/exec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/exec.c b/fs/exec.c
index 06b4c550af5d..ea24bdce939d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1021,8 +1021,8 @@ int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
goto out;
ret = kernel_read_file(f.file, buf, size, max_size, id);
-out:
fdput(f);
+out:
return ret;
}
EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
--
2.25.1
On Tue, May 12, 2020 at 01:43:04PM -0600, Shuah Khan wrote:
> @@ -364,15 +364,15 @@ int sync_file_range(struct file *file, loff_t offset, loff_t nbytes,
> int ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
> unsigned int flags)
> {
> - int ret;
> - struct fd f;
> + int ret = -EBADF;
> + struct fd f = fdget(fd);
>
> - ret = -EBADF;
> - f = fdget(fd);
> - if (f.file)
> - ret = sync_file_range(f.file, offset, nbytes, flags);
> + if (!f.file)
> + goto out;
>
> + ret = sync_file_range(f.file, offset, nbytes, flags);
> fdput(f);
> +out:
> return ret;
IDGI... What's the point of that goto out, when it leads straight to return?
On Tue, May 12, 2020 at 01:43:05PM -0600, Shuah Khan wrote:
> Fix kernel_read_file_from_fd() to avoid fdput() after a failed fdget().
> fdput() doesn't do fput() on this file since FDPUT_FPUT isn't set
> in fd.flags. Fix it anyway since failed fdget() doesn't require
> a fdput().
>
> This was introduced in a commit that added kernel_read_file_from_fd() as
> a wrapper for the VFS common kernel_read_file().
>
> Fixes: b844f0ecbc56 ("vfs: define kernel_copy_file_from_fd()")
> Signed-off-by: Shuah Khan <[email protected]>
> ---
> fs/exec.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/exec.c b/fs/exec.c
> index 06b4c550af5d..ea24bdce939d 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -1021,8 +1021,8 @@ int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
> goto out;
>
> ret = kernel_read_file(f.file, buf, size, max_size, id);
> -out:
> fdput(f);
> +out:
> return ret;
Again, that goto is a pointless obfuscation; just return -EBADF
and be done with that.
Incidentally, why is that thing exported?
On Wed, May 13, 2020 at 06:49:50AM +0100, Al Viro wrote:
> On Tue, May 12, 2020 at 01:43:05PM -0600, Shuah Khan wrote:
> > diff --git a/fs/exec.c b/fs/exec.c
> > index 06b4c550af5d..ea24bdce939d 100644
> > --- a/fs/exec.c
> > +++ b/fs/exec.c
> > @@ -1021,8 +1021,8 @@ int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
> > goto out;
> >
> > ret = kernel_read_file(f.file, buf, size, max_size, id);
> > -out:
> > fdput(f);
> > +out:
> > return ret;
>
> Incidentally, why is that thing exported?
Both kernel_read_file_from_fd() and kernel_read_file() are exported
because they have users, however kernel_read_file() only has security
stuff as a user. Do we want to get rid of the lsm hook for it?
I also have some non-posted patches which tucks away these kernel_read*()
exports under a symbol namespace, to avoid wide-spread use / abuse on
areas in the kernel, so I'd be happy to take this on if we want to
remove it export / lsm hook as part of my series. I did this as there
is another series of patches for a new driver which extend these family
of functions with a now pread() variant....
Luis
On Wed, May 13, 2020 at 7:13 AM Luis Chamberlain <[email protected]> wrote:
>
> On Wed, May 13, 2020 at 06:49:50AM +0100, Al Viro wrote:
> > On Tue, May 12, 2020 at 01:43:05PM -0600, Shuah Khan wrote:
> > > diff --git a/fs/exec.c b/fs/exec.c
> > > index 06b4c550af5d..ea24bdce939d 100644
> > > --- a/fs/exec.c
> > > +++ b/fs/exec.c
> > > @@ -1021,8 +1021,8 @@ int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
> > > goto out;
> > >
> > > ret = kernel_read_file(f.file, buf, size, max_size, id);
> > > -out:
> > > fdput(f);
> > > +out:
> > > return ret;
> >
> > Incidentally, why is that thing exported?
>
> Both kernel_read_file_from_fd() and kernel_read_file() are exported
> because they have users, however kernel_read_file() only has security
> stuff as a user. Do we want to get rid of the lsm hook for it?
Alright, yeah just the export needs to be removed. I have a patch
series dealing with these callers so will add it to my queue.
Luis
On 5/12/20 11:49 PM, Al Viro wrote:
> On Tue, May 12, 2020 at 01:43:05PM -0600, Shuah Khan wrote:
>> Fix kernel_read_file_from_fd() to avoid fdput() after a failed fdget().
>> fdput() doesn't do fput() on this file since FDPUT_FPUT isn't set
>> in fd.flags. Fix it anyway since failed fdget() doesn't require
>> a fdput().
>>
>> This was introduced in a commit that added kernel_read_file_from_fd() as
>> a wrapper for the VFS common kernel_read_file().
>>
>> Fixes: b844f0ecbc56 ("vfs: define kernel_copy_file_from_fd()")
>> Signed-off-by: Shuah Khan <[email protected]>
>> ---
>> fs/exec.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/fs/exec.c b/fs/exec.c
>> index 06b4c550af5d..ea24bdce939d 100644
>> --- a/fs/exec.c
>> +++ b/fs/exec.c
>> @@ -1021,8 +1021,8 @@ int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
>> goto out;
>>
>> ret = kernel_read_file(f.file, buf, size, max_size, id);
>> -out:
>> fdput(f);
>> +out:
>> return ret;
>
> Again, that goto is a pointless obfuscation; just return -EBADF
> and be done with that.
>
My reasoning is if this routine ends up growing it might be useful
to handle the return this way.
In any case, I will send v3 for both of these patches.
thanks,
-- Shuah
Hi Luis,
On 2020-05-13 7:19 a.m., Luis Chamberlain wrote:
> On Wed, May 13, 2020 at 7:13 AM Luis Chamberlain <[email protected]> wrote:
>> On Wed, May 13, 2020 at 06:49:50AM +0100, Al Viro wrote:
>>> On Tue, May 12, 2020 at 01:43:05PM -0600, Shuah Khan wrote:
>>>> diff --git a/fs/exec.c b/fs/exec.c
>>>> index 06b4c550af5d..ea24bdce939d 100644
>>>> --- a/fs/exec.c
>>>> +++ b/fs/exec.c
>>>> @@ -1021,8 +1021,8 @@ int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
>>>> goto out;
>>>>
>>>> ret = kernel_read_file(f.file, buf, size, max_size, id);
>>>> -out:
>>>> fdput(f);
>>>> +out:
>>>> return ret;
>>> Incidentally, why is that thing exported?
>> Both kernel_read_file_from_fd() and kernel_read_file() are exported
>> because they have users, however kernel_read_file() only has security
>> stuff as a user. Do we want to get rid of the lsm hook for it?
> Alright, yeah just the export needs to be removed. I have a patch
> series dealing with these callers so will add it to my queue.
When will these changes make it into linux-next?
It is difficult for me to complete my patch series without these other
misc. changes in place.
>
> Luis
Regards,
Scott
On 2020-05-22 2:59 p.m., Scott Branden wrote:
> Hi Luis,
>
> On 2020-05-13 7:19 a.m., Luis Chamberlain wrote:
>> On Wed, May 13, 2020 at 7:13 AM Luis Chamberlain <[email protected]>
>> wrote:
>>> On Wed, May 13, 2020 at 06:49:50AM +0100, Al Viro wrote:
>>>> On Tue, May 12, 2020 at 01:43:05PM -0600, Shuah Khan wrote:
>>>>> diff --git a/fs/exec.c b/fs/exec.c
>>>>> index 06b4c550af5d..ea24bdce939d 100644
>>>>> --- a/fs/exec.c
>>>>> +++ b/fs/exec.c
>>>>> @@ -1021,8 +1021,8 @@ int kernel_read_file_from_fd(int fd, void
>>>>> **buf, loff_t *size, loff_t max_size,
>>>>> goto out;
>>>>>
>>>>> ret = kernel_read_file(f.file, buf, size, max_size, id);
>>>>> -out:
>>>>> fdput(f);
>>>>> +out:
>>>>> return ret;
>>>> Incidentally, why is that thing exported?
>>> Both kernel_read_file_from_fd() and kernel_read_file() are exported
>>> because they have users, however kernel_read_file() only has security
>>> stuff as a user. Do we want to get rid of the lsm hook for it?
>> Alright, yeah just the export needs to be removed. I have a patch
>> series dealing with these callers so will add it to my queue.
> When will these changes make it into linux-next?
> It is difficult for me to complete my patch series without these other
> misc. changes in place.
Sorry, I see the patch series is still being worked on (missing
changelog, comments, etc).
Hopefully the patches stabilize so I can apply my changes on top fairly
soon.
>>
>> Luis
> Regards,
> Scott
On Fri, May 22, 2020 at 03:14:59PM -0700, Scott Branden wrote:
>
>
> On 2020-05-22 2:59 p.m., Scott Branden wrote:
> > Hi Luis,
> >
> > On 2020-05-13 7:19 a.m., Luis Chamberlain wrote:
> > > On Wed, May 13, 2020 at 7:13 AM Luis Chamberlain <[email protected]>
> > > wrote:
> > > > On Wed, May 13, 2020 at 06:49:50AM +0100, Al Viro wrote:
> > > > > On Tue, May 12, 2020 at 01:43:05PM -0600, Shuah Khan wrote:
> > > > > > diff --git a/fs/exec.c b/fs/exec.c
> > > > > > index 06b4c550af5d..ea24bdce939d 100644
> > > > > > --- a/fs/exec.c
> > > > > > +++ b/fs/exec.c
> > > > > > @@ -1021,8 +1021,8 @@ int kernel_read_file_from_fd(int
> > > > > > fd, void **buf, loff_t *size, loff_t max_size,
> > > > > > ???????????? goto out;
> > > > > >
> > > > > > ???? ret = kernel_read_file(f.file, buf, size, max_size, id);
> > > > > > -out:
> > > > > > ???? fdput(f);
> > > > > > +out:
> > > > > > ???? return ret;
> > > > > Incidentally, why is that thing exported?
> > > > Both kernel_read_file_from_fd() and kernel_read_file() are exported
> > > > because they have users, however kernel_read_file() only has security
> > > > stuff as a user. Do we want to get rid of the lsm hook for it?
> > > Alright, yeah just the export needs to be removed. I have a patch
> > > series dealing with these callers so will add it to my queue.
> > When will these changes make it into linux-next?
> > It is difficult for me to complete my patch series without these other
> > misc. changes in place.
> Sorry, I see the patch series is still being worked on (missing changelog,
> comments, etc).
> Hopefully the patches stabilize so I can apply my changes on top fairly
> soon.
Yeah I have to redo that series to take into account feedback. I'll be
sure cc you on that. I have a few other series to attend to before that,
so I think this will take a week.
Luis