From patchwork Fri Oct 28 18:02:41 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eryu Guan X-Patchwork-Id: 122469 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 826431007DB for ; Sat, 29 Oct 2011 05:03:01 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753668Ab1J1SDA (ORCPT ); Fri, 28 Oct 2011 14:03:00 -0400 Received: from mail-yw0-f46.google.com ([209.85.213.46]:64795 "EHLO mail-yw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753552Ab1J1SC7 (ORCPT ); Fri, 28 Oct 2011 14:02:59 -0400 Received: by ywm3 with SMTP id 3so3889361ywm.19 for ; Fri, 28 Oct 2011 11:02:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; bh=93NgFHhqX8uMKl81VPTrvsACdsScn9l8Tu9/xmt3/OE=; b=G9yhnYhEeVeXE9PLRtHx35liGA+GN+TmAk6Smsdxhp/mI8XBMKJnZBomaBnsRchk8i hOi7ugvqHzWiulvX6k2fN5mbGVWzdY1C9Z+oHrRCIHmaUa2h2OFpzQfPDXDGtkxDeILT 7ypTfr1+sVS2mn1d5Nl2N/i++yx5dUNyvDjJA= Received: by 10.236.192.132 with SMTP id i4mr5483236yhn.80.1319824979201; Fri, 28 Oct 2011 11:02:59 -0700 (PDT) Received: from localhost ([123.116.132.248]) by mx.google.com with ESMTPS id q57sm13476959yhi.22.2011.10.28.11.02.56 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 28 Oct 2011 11:02:58 -0700 (PDT) From: Eryu Guan To: linux-ext4@vger.kernel.org Cc: Eryu Guan , "Theodore Ts'o" Subject: [PATCH] ext4: Avoid creating new file in append-only dir when open(2) return error Date: Sat, 29 Oct 2011 02:02:41 +0800 Message-Id: <1319824961-5587-1-git-send-email-guaneryu@gmail.com> X-Mailer: git-send-email 1.7.7.1 Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Newly created file on ext4 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/ext4/append-only # chattr +a /mnt/ext4/append-only # ./opentest /mnt/ext4/append-only/newtestfile # ls -l /mnt/ext4/append-only/newtestfile opentest will return 'Operation not permitted', but the ls shows that newtestfile is already created. # cat opentest.c #include #include #include #include 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 EXT4_APPEND_FL flag first in ext4_create before really allocating new inode. Besides this fix, remove comments about 'extent' mount option in ext4_new_inode(), it's no longer existed. Cc: "Theodore Ts'o" Signed-off-by: Eryu Guan --- fs/ext4/ialloc.c | 6 +----- fs/ext4/namei.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 9c63f27..c25b9e5 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -1005,11 +1005,7 @@ got: ei->i_dir_start_lookup = 0; ei->i_disksize = 0; - /* - * Don't inherit extent flag from directory, amongst others. We set - * extent flag on newly created directory and file only if -o extent - * mount option is specified - */ + /* Don't inherit extent flag from directory, amongst others. */ ei->i_flags = ext4_mask_flags(mode, EXT4_I(dir)->i_flags & EXT4_FL_INHERITED); ei->i_file_acl = 0; diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 1c924fa..b58be5d 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "ext4.h" #include "ext4_jbd2.h" @@ -1743,6 +1744,15 @@ static int ext4_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 ((EXT4_I(dir)->i_flags & EXT4_FL_INHERITED) & EXT4_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);