From patchwork Wed Apr 13 07:31:59 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Oops when calling fsync on read-only file-system Date: Tue, 12 Apr 2011 21:31:59 -0000 From: Artem Bityutskiy X-Patchwork-Id: 90964 Message-Id: <1302679919.2768.9.camel@localhost> To: Reuben Dowle Cc: linux-mtd@lists.infradead.org Hi, thanks a lot for reporting this! On Tue, 2011-04-12 at 13:32 +1200, Reuben Dowle wrote: > On my system, calling the fsync system call on any file in a UBI > file-system that is mounted read-only leads to a kernel oops. Our > system is running a customise version of 2.6.31, but as far as I can > see (without testing which is not possible due to extensive vendor > customisation of .31 kernel version), the current git branch also > contains this bug. > > I have created a patch against 2.6.31 that fixes the problem in my > system. Perhaps someone could test on latest kernel version. > > Signed-off-by: Reuben Dowle Wow! Shame on me for this bug! And it is funny that it is there for several years already and there are product with this bug! Here is the fix which I will merge upstream soon: From: Artem Bityutskiy Subject: [PATCH] UBIFS: fix oops when R/O file-system is fsync'ed This patch fixes severe UBIFS bug: UBIFS oopses when we 'fsync()' an file on R/O-mounter file-system. We (the UBIFS authors) incorrectly thought that VFS would not propagate 'fsync()' down to the file-system if it is read-only, but this is not the case. It is easy to exploit this bug using the following simple perl script: use strict; use File::Sync qw(fsync sync); die "File path is not specified" if not defined $ARGV[0]; my $path = $ARGV[0]; open FILE, "<", "$path" or die "Cannot open $path: $!"; fsync(\*FILE) or die "cannot fsync $path: $!"; close FILE or die "Cannot close $path: $!"; Thanks to Reuben Dowle for reporting about this issue. Signed-off-by: Artem Bityutskiy Reported-by: Reuben Dowle Cc: stable@kernel.org --- fs/ubifs/file.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index a2b5012..3594aae 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1312,6 +1312,9 @@ int ubifs_fsync(struct file *file, int datasync) dbg_gen("syncing inode %lu", inode->i_ino); + if (inode->i_sb->s_flags & MS_RDONLY) + return 0; + /* * VFS has already synchronized dirty pages for this inode. Synchronize * the inode unless this is a 'datasync()' call.