2011-10-28 18:03:27

by Eryu Guan

[permalink] [raw]
Subject: [PATCH] ext3: Avoid creating new file in append-only dir when open(2) return error

Newly created file on ext3 inherits inode flags from parent directory,
so new inode created in append-only directory has S_APPEND flag set,
may_open() called by do_last() checks that flag then returns -EPERM,
but at that time the new inode is already created.

This can be reproduced by:
# mkdir -p /mnt/ext3/append-only
# chattr +a /mnt/ext3/append-only
# ./opentest /mnt/ext3/append-only/newtestfile
# ls -l /mnt/ext3/append-only/newtestfile

opentest will return 'Operation not permitted', but the ls shows that
newtestfile is already created.

# cat opentest.c
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
int fd;
fd = open(argv[1], O_RDWR|O_CREAT, 0666);
if (fd == -1)
perror("open failed");
return 0;
}

To avoid this, check EXT3_APPEND_FL flag first in ext3_create before
really allocating new inode.

Cc: Jan Kara <[email protected]>
Signed-off-by: Eryu Guan <[email protected]>
---
fs/ext3/namei.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 0629e09..323cf2f 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -36,6 +36,7 @@
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
#include <linux/bio.h>
+#include <linux/namei.h>
#include <trace/events/ext3.h>

#include "namei.h"
@@ -1704,6 +1705,15 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
handle_t *handle;
struct inode * inode;
int err, retries = 0;
+ int open_flag = nd->intent.open.file->f_flags;
+
+ if ((EXT3_I(dir)->i_flags & EXT3_FL_INHERITED) & EXT3_APPEND_FL) {
+ if ((open_flag & O_ACCMODE) != O_RDONLY &&
+ !(open_flag & O_APPEND))
+ return -EPERM;
+ if (open_flag & O_TRUNC)
+ return -EPERM;
+ }

dquot_initialize(dir);

--
1.7.7.1



2011-11-01 23:10:36

by Jan Kara

[permalink] [raw]
Subject: Re: [PATCH] ext3: Avoid creating new file in append-only dir when open(2) return error

On Sat 29-10-11 02:03:07, Eryu Guan wrote:
> Newly created file on ext3 inherits inode flags from parent directory,
> so new inode created in append-only directory has S_APPEND flag set,
> may_open() called by do_last() checks that flag then returns -EPERM,
> but at that time the new inode is already created.
>
> This can be reproduced by:
> # mkdir -p /mnt/ext3/append-only
> # chattr +a /mnt/ext3/append-only
> # ./opentest /mnt/ext3/append-only/newtestfile
> # ls -l /mnt/ext3/append-only/newtestfile
>
> opentest will return 'Operation not permitted', but the ls shows that
> newtestfile is already created.
>
> # cat opentest.c
> #include <stdio.h>
> #include <sys/types.h>
> #include <fcntl.h>
> #include <sys/stat.h>
>
> int main(int argc, char *argv[])
> {
> int fd;
> fd = open(argv[1], O_RDWR|O_CREAT, 0666);
> if (fd == -1)
> perror("open failed");
> return 0;
> }
>
> To avoid this, check EXT3_APPEND_FL flag first in ext3_create before
> really allocating new inode.
Yes, it is nicer to not create any file when open(2) fails in the end.
BTW, how have you spotted this? I've taken your ext2 and ext3 patches into
my tree.

Honza
>
> Cc: Jan Kara <[email protected]>
> Signed-off-by: Eryu Guan <[email protected]>
> ---
> fs/ext3/namei.c | 10 ++++++++++
> 1 files changed, 10 insertions(+), 0 deletions(-)
>
> diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
> index 0629e09..323cf2f 100644
> --- a/fs/ext3/namei.c
> +++ b/fs/ext3/namei.c
> @@ -36,6 +36,7 @@
> #include <linux/quotaops.h>
> #include <linux/buffer_head.h>
> #include <linux/bio.h>
> +#include <linux/namei.h>
> #include <trace/events/ext3.h>
>
> #include "namei.h"
> @@ -1704,6 +1705,15 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
> handle_t *handle;
> struct inode * inode;
> int err, retries = 0;
> + int open_flag = nd->intent.open.file->f_flags;
> +
> + if ((EXT3_I(dir)->i_flags & EXT3_FL_INHERITED) & EXT3_APPEND_FL) {
> + if ((open_flag & O_ACCMODE) != O_RDONLY &&
> + !(open_flag & O_APPEND))
> + return -EPERM;
> + if (open_flag & O_TRUNC)
> + return -EPERM;
> + }
>
> dquot_initialize(dir);
>
> --
> 1.7.7.1
>
--
Jan Kara <[email protected]>
SUSE Labs, CR

2011-11-01 23:27:28

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH] ext3: Avoid creating new file in append-only dir when open(2) return error

On Wed, Nov 02, 2011 at 12:10:34AM +0100, Jan Kara wrote:
> >
> > To avoid this, check EXT3_APPEND_FL flag first in ext3_create before
> > really allocating new inode.
> Yes, it is nicer to not create any file when open(2) fails in the end.
> BTW, how have you spotted this? I've taken your ext2 and ext3 patches into
> my tree.

Note: I have a fix in my tree which removes EXTx_APPEND_FL from the
set of flags that can be inherited from the containing directory in
ext2, ext3, and ext4. That addresses this issue without needing to
make the change in this patch.

- Ted

2011-11-02 02:05:57

by Eryu Guan

[permalink] [raw]
Subject: Re: [PATCH] ext3: Avoid creating new file in append-only dir when open(2) return error

On Wed, Nov 2, 2011 at 7:10 AM, Jan Kara <[email protected]> wrote:
> On Sat 29-10-11 02:03:07, Eryu Guan wrote:
>> Newly created file on ext3 inherits inode flags from parent directory,
>> so new inode created in append-only directory has S_APPEND flag set,
>> may_open() called by do_last() checks that flag then returns -EPERM,
>> but at that time the new inode is already created.
>>
>> This can be reproduced by:
>> ? ? ? # mkdir -p /mnt/ext3/append-only
>> ? ? ? # chattr +a /mnt/ext3/append-only
>> ? ? ? # ./opentest /mnt/ext3/append-only/newtestfile
>> ? ? ? # ls -l /mnt/ext3/append-only/newtestfile
>>
>> opentest will return 'Operation not permitted', but the ls shows that
>> newtestfile is already created.
>>
>> ? ? ? # cat opentest.c
>> ? ? ? #include <stdio.h>
>> ? ? ? #include <sys/types.h>
>> ? ? ? #include <fcntl.h>
>> ? ? ? #include <sys/stat.h>
>>
>> ? ? ? int main(int argc, char *argv[])
>> ? ? ? {
>> ? ? ? ? ? ? ? int fd;
>> ? ? ? ? ? ? ? fd = open(argv[1], O_RDWR|O_CREAT, 0666);
>> ? ? ? ? ? ? ? if (fd == -1)
>> ? ? ? ? ? ? ? ? ? ? ? perror("open failed");
>> ? ? ? ? ? ? ? return 0;
>> ? ? ? }
>>
>> To avoid this, check EXT3_APPEND_FL flag first in ext3_create before
>> really allocating new inode.
> ?Yes, it is nicer to not create any file when open(2) fails in the end.
> BTW, how have you spotted this? I've taken your ext2 and ext3 patches into
> my tree.

I found this by xfstests 079, since it's no longer xfs specific and
fails on extN.
After applying my patch, 079 still fails on extN, but not leave
unwanted file there.

As Ted said, the other way to fix this is to remove EXTx_APPEND_FL from
EXTx_FL_INHERITED, so new inode will not inherit the append-only flag. This fix
will also make 079 pass on extN.

Though I prefer the later way, I still sent out my patch for review,
because it's
not a behavior-changer.

Thanks.
Eryu Guan
>
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Honza
>>
>> Cc: Jan Kara <[email protected]>
>> Signed-off-by: Eryu Guan <[email protected]>
>> ---
>> ?fs/ext3/namei.c | ? 10 ++++++++++
>> ?1 files changed, 10 insertions(+), 0 deletions(-)
>>
>> diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
>> index 0629e09..323cf2f 100644
>> --- a/fs/ext3/namei.c
>> +++ b/fs/ext3/namei.c
>> @@ -36,6 +36,7 @@
>> ?#include <linux/quotaops.h>
>> ?#include <linux/buffer_head.h>
>> ?#include <linux/bio.h>
>> +#include <linux/namei.h>
>> ?#include <trace/events/ext3.h>
>>
>> ?#include "namei.h"
>> @@ -1704,6 +1705,15 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
>> ? ? ? handle_t *handle;
>> ? ? ? struct inode * inode;
>> ? ? ? int err, retries = 0;
>> + ? ? int open_flag = nd->intent.open.file->f_flags;
>> +
>> + ? ? if ((EXT3_I(dir)->i_flags & EXT3_FL_INHERITED) & EXT3_APPEND_FL) {
>> + ? ? ? ? ? ? if ((open_flag & O_ACCMODE) != O_RDONLY &&
>> + ? ? ? ? ? ? ? ? !(open_flag & O_APPEND))
>> + ? ? ? ? ? ? ? ? ? ? return -EPERM;
>> + ? ? ? ? ? ? if (open_flag & O_TRUNC)
>> + ? ? ? ? ? ? ? ? ? ? return -EPERM;
>> + ? ? }
>>
>> ? ? ? dquot_initialize(dir);
>>
>> --
>> 1.7.7.1
>>
> --
> Jan Kara <[email protected]>
> SUSE Labs, CR
>

2011-11-02 14:23:17

by Jan Kara

[permalink] [raw]
Subject: Re: [PATCH] ext3: Avoid creating new file in append-only dir when open(2) return error

On Tue 01-11-11 19:27:25, Ted Tso wrote:
> On Wed, Nov 02, 2011 at 12:10:34AM +0100, Jan Kara wrote:
> > >
> > > To avoid this, check EXT3_APPEND_FL flag first in ext3_create before
> > > really allocating new inode.
> > Yes, it is nicer to not create any file when open(2) fails in the end.
> > BTW, how have you spotted this? I've taken your ext2 and ext3 patches into
> > my tree.
>
> Note: I have a fix in my tree which removes EXTx_APPEND_FL from the
> set of flags that can be inherited from the containing directory in
> ext2, ext3, and ext4. That addresses this issue without needing to
> make the change in this patch.
Ah, OK. I forgot about it. I've removed the two patches from my queue.
Thanks for letting me know.

Honza
--
Jan Kara <[email protected]>
SUSE Labs, CR