* [PATCH] fs/vfs: Release allocated dentry on failure in do_last()
@ 2017-12-07 2:46 穆阿浩(姜弋)
2017-12-07 5:30 ` Matthew Wilcox
2017-12-07 12:39 ` Al Viro
0 siblings, 2 replies; 5+ messages in thread
From: 穆阿浩(姜弋) @ 2017-12-07 2:46 UTC (permalink / raw)
To: linux-fsdevel
Cc: viro, 渡波,
穆阿浩(姜弋),
张礼广(乱石)
This issue is found when creating /dev/sdtest with flags (O_CREAT |
O_DIRECT). The file still can be retrieved even after system reports
failure (-EINVAL) for it. Reporting error on creating the file is
correct behaviour because either devtmpfs or tmpfs doesn't support
O_DIRECT for regular file. However, it's incorrect that the file is
still existing. The cause is the newly allocated dentry and inode
aren't released on failure in do_last().
# rm /dev/sdtest
# dd if=/dev/urandom of=/dev/sdtest bs=4k count=1 oflag=direct
<-EINVAL is returned>
# ls /dev/sdtest
<File is still existing>
This fixes the issue by releasing the dentry, thus the inode on failure
in do_last(). With this applied, the file (/dev/sdtest) isn't seen
in this scenario.
Reported-by: YouYou <youyou.wy.huang@foxconn.com>
Signed-off-by: Gavin Shan <dubo.sgw@alibaba-inc.com>
Signed-off-by: Liguang Zhang <liguang.zlg@alibaba-inc.com>
Signed-off-by: Ahao Mu <ahao.mah@alibaba-inc.com>
---
fs/namei.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/namei.c b/fs/namei.c
index 9cc91fb..607c357 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3382,6 +3382,8 @@ static int do_last(struct nameidata *nd,
*opened |= FILE_OPENED;
opened:
error = open_check_o_direct(file);
+ if (error && (*opened & FILE_OPENED))
+ dput(path.dentry);
if (!error)
error = ima_file_check(file, op->acc_mode, *opened);
if (!error && will_truncate)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] fs/vfs: Release allocated dentry on failure in do_last()
2017-12-07 2:46 [PATCH] fs/vfs: Release allocated dentry on failure in do_last() 穆阿浩(姜弋)
@ 2017-12-07 5:30 ` Matthew Wilcox
2017-12-08 3:14 ` 渡波
2017-12-07 12:39 ` Al Viro
1 sibling, 1 reply; 5+ messages in thread
From: Matthew Wilcox @ 2017-12-07 5:30 UTC (permalink / raw)
To: 穆阿浩(姜弋)
Cc: linux-fsdevel, viro, 渡波,
张礼广(乱石)
On Thu, Dec 07, 2017 at 10:46:22AM +0800, 穆阿浩(姜弋) wrote:
> This issue is found when creating /dev/sdtest with flags (O_CREAT |
> O_DIRECT). The file still can be retrieved even after system reports
> failure (-EINVAL) for it. Reporting error on creating the file is
> correct behaviour because either devtmpfs or tmpfs doesn't support
> O_DIRECT for regular file. However, it's incorrect that the file is
> still existing. The cause is the newly allocated dentry and inode
> aren't released on failure in do_last().
Previously reported:
https://www.spinics.net/lists/linux-fsdevel/msg89317.html
https://www.spinics.net/lists/linux-fsdevel/msg113680.html
http://lkml.iu.edu/hypermail/linux/kernel/1609.0/04556.html
> +++ b/fs/namei.c
> @@ -3382,6 +3382,8 @@ static int do_last(struct nameidata *nd,
> *opened |= FILE_OPENED;
> opened:
> error = open_check_o_direct(file);
> + if (error && (*opened & FILE_OPENED))
> + dput(path.dentry);
> if (!error)
> error = ima_file_check(file, op->acc_mode, *opened);
> if (!error && will_truncate)
Umm ... I think it's too late. This will work well enough for in-memory
filesystems, but if you have a real filesystem, there's no call back to
the filesystem to remove the directory entry, right?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs/vfs: Release allocated dentry on failure in do_last()
2017-12-07 5:30 ` Matthew Wilcox
@ 2017-12-08 3:14 ` 渡波
0 siblings, 0 replies; 5+ messages in thread
From: 渡波 @ 2017-12-08 3:14 UTC (permalink / raw)
To: Matthew Wilcox
Cc: 穆阿浩(姜弋), linux-fsdevel, viro,
张礼广(乱石)
On Thu, Dec 07, 2017 at 01:30:03PM +0800, Matthew Wilcox wrote:
> On Thu, Dec 07, 2017 at 10:46:22AM +0800, 锟铰帮拷锟斤拷(锟斤拷弋) wrote:
> > This issue is found when creating /dev/sdtest with flags (O_CREAT |
> > O_DIRECT). The file still can be retrieved even after system reports
> > failure (-EINVAL) for it. Reporting error on creating the file is
> > correct behaviour because either devtmpfs or tmpfs doesn't support
> > O_DIRECT for regular file. However, it's incorrect that the file is
> > still existing. The cause is the newly allocated dentry and inode
> > aren't released on failure in do_last().
>
> Previously reported:
>
> https://www.spinics.net/lists/linux-fsdevel/msg89317.html
> https://www.spinics.net/lists/linux-fsdevel/msg113680.html
> http://lkml.iu.edu/hypermail/linux/kernel/1609.0/04556.html
>
Thanks, Matthew. I start to realize it's a long-standing issue :)
> > +++ b/fs/namei.c
> > @@ -3382,6 +3382,8 @@ static int do_last(struct nameidata *nd,
> > *opened |= FILE_OPENED;
> > opened:
> > error = open_check_o_direct(file);
> > + if (error && (*opened & FILE_OPENED))
> > + dput(path.dentry);
> > if (!error)
> > error = ima_file_check(file, op->acc_mode, *opened);
> > if (!error && will_truncate)
>
> Umm ... I think it's too late. This will work well enough for in-memory
> filesystems, but if you have a real filesystem, there's no call back to
> the filesystem to remove the directory entry, right?
Yeah, it's late to roll back on real filesystem like ext4. As I replied
to Al Viro in another thread, the doable fix would be pass O_DIRECT down
to struct inode_operations::create() and the specific filesystem rejects
creating inode if O_DIRECT isn't supported there.
Cheers,
Gavin
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs/vfs: Release allocated dentry on failure in do_last()
2017-12-07 2:46 [PATCH] fs/vfs: Release allocated dentry on failure in do_last() 穆阿浩(姜弋)
2017-12-07 5:30 ` Matthew Wilcox
@ 2017-12-07 12:39 ` Al Viro
2017-12-08 3:11 ` 渡波
1 sibling, 1 reply; 5+ messages in thread
From: Al Viro @ 2017-12-07 12:39 UTC (permalink / raw)
To: 穆阿浩(姜弋)
Cc: linux-fsdevel, 渡波,
张礼广(乱石)
On Thu, Dec 07, 2017 at 10:46:22AM +0800, 穆阿浩(姜弋) wrote:
> This issue is found when creating /dev/sdtest with flags (O_CREAT |
> O_DIRECT). The file still can be retrieved even after system reports
> failure (-EINVAL) for it. Reporting error on creating the file is
> correct behaviour because either devtmpfs or tmpfs doesn't support
> O_DIRECT for regular file. However, it's incorrect that the file is
> still existing. The cause is the newly allocated dentry and inode
> aren't released on failure in do_last().
> # rm /dev/sdtest
> # dd if=/dev/urandom of=/dev/sdtest bs=4k count=1 oflag=direct
> <-EINVAL is returned>
> # ls /dev/sdtest
> <File is still existing>
>
> This fixes the issue by releasing the dentry, thus the inode on failure
> in do_last(). With this applied, the file (/dev/sdtest) isn't seen
> in this scenario.
> + if (error && (*opened & FILE_OPENED))
> + dput(path.dentry);
NAK. For one thing, it's racy as hell even on tmpfs - plain open()
from another process would've succeeded in that window. For another,
it's outright exploitable on filesystems where dentry tree does not
contain all the existing directory tree (anything disk-based, for
starters).
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs/vfs: Release allocated dentry on failure in do_last()
2017-12-07 12:39 ` Al Viro
@ 2017-12-08 3:11 ` 渡波
0 siblings, 0 replies; 5+ messages in thread
From: 渡波 @ 2017-12-08 3:11 UTC (permalink / raw)
To: Al Viro
Cc: 穆阿浩(姜弋), linux-fsdevel,
张礼广(乱石)
On Thu, Dec 07, 2017 at 08:39:37PM +0800, Al Viro wrote:
> On Thu, Dec 07, 2017 at 10:46:22AM +0800, 锟铰帮拷锟斤拷(锟斤拷弋) wrote:
> > This issue is found when creating /dev/sdtest with flags (O_CREAT |
> > O_DIRECT). The file still can be retrieved even after system reports
> > failure (-EINVAL) for it. Reporting error on creating the file is
> > correct behaviour because either devtmpfs or tmpfs doesn't support
> > O_DIRECT for regular file. However, it's incorrect that the file is
> > still existing. The cause is the newly allocated dentry and inode
> > aren't released on failure in do_last().
>
> > # rm /dev/sdtest
> > # dd if=/dev/urandom of=/dev/sdtest bs=4k count=1 oflag=direct
> > <-EINVAL is returned>
> > # ls /dev/sdtest
> > <File is still existing>
> >
> > This fixes the issue by releasing the dentry, thus the inode on failure
> > in do_last(). With this applied, the file (/dev/sdtest) isn't seen
> > in this scenario.
>
> > + if (error && (*opened & FILE_OPENED))
> > + dput(path.dentry);
>
> NAK. For one thing, it's racy as hell even on tmpfs - plain open()
> from another process would've succeeded in that window. For another,
> it's outright exploitable on filesystems where dentry tree does not
> contain all the existing directory tree (anything disk-based, for
> starters).
Al, thanks for your reply. Another approach would be passing the flag
O_DIRECT to struct inode_operations::create(). The specific filesystem
rejects to create the inode if O_DIRECT isn't supported there. I can
send patches for review if you think it's reasonable.
Cheers,
Gavin
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-12-08 3:14 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-07 2:46 [PATCH] fs/vfs: Release allocated dentry on failure in do_last() 穆阿浩(姜弋)
2017-12-07 5:30 ` Matthew Wilcox
2017-12-08 3:14 ` 渡波
2017-12-07 12:39 ` Al Viro
2017-12-08 3:11 ` 渡波
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).