From patchwork Mon May 30 13:59:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Gruenbacher X-Patchwork-Id: 9141525 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D4E9660759 for ; Mon, 30 May 2016 13:59:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C679A27D17 for ; Mon, 30 May 2016 13:59:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B6FE52819E; Mon, 30 May 2016 13:59:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F89327D17 for ; Mon, 30 May 2016 13:59:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932930AbcE3N7P (ORCPT ); Mon, 30 May 2016 09:59:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48524 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932192AbcE3N7P (ORCPT ); Mon, 30 May 2016 09:59:15 -0400 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C990D7F340; Mon, 30 May 2016 13:59:14 +0000 (UTC) Received: from nux.redhat.com (vpn1-6-85.ams2.redhat.com [10.36.6.85]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u4UDx3ae014420; Mon, 30 May 2016 09:59:11 -0400 From: Andreas Gruenbacher To: Alexander Viro , Paul Moore , Stephen Smalley , Eric Paris Cc: Andreas Gruenbacher , linux-fsdevel@vger.kernel.org, selinux@tycho.nsa.gov Subject: [RFC 2/2] overlayfs: Make getxattr work with inode only Date: Mon, 30 May 2016 15:59:02 +0200 Message-Id: <1464616742-29271-3-git-send-email-agruenba@redhat.com> In-Reply-To: <1464616742-29271-1-git-send-email-agruenba@redhat.com> References: <1464616742-29271-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 30 May 2016 13:59:15 +0000 (UTC) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Change the getxattr inode operation to only use its inode argument, and ignore the dentry. This is possible because on overlayfs, each dentry has a separate inode and inodes are not shared among dentries. Allows SELinux to work on top of overlayfs. Signed-off-by: Andreas Gruenbacher --- fs/overlayfs/inode.c | 26 +++++++++++++++----------- fs/overlayfs/overlayfs.h | 1 + fs/overlayfs/super.c | 10 +++++++--- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 8c3f985..7acc145 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -238,29 +238,32 @@ out: return err; } -static bool ovl_need_xattr_filter(struct dentry *dentry, +static bool ovl_need_xattr_filter(struct inode *inode, enum ovl_path_type type) { if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER) - return S_ISDIR(dentry->d_inode->i_mode); + return S_ISDIR(inode->i_mode); else return false; } -ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, +ssize_t ovl_getxattr(struct dentry *unused, struct inode *inode, const char *name, void *value, size_t size) { - struct path realpath; + struct ovl_entry *oe = inode->i_private; enum ovl_path_type type; + struct dentry *realdentry; + bool is_upper; - if (!dentry) - return -ECHILD; + realdentry = ovl_entry_real(oe, &is_upper); + if (!realdentry->d_inode) + return -ENOENT; - type = ovl_path_real(dentry, &realpath); - if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) + type = __ovl_path_type(oe, inode->i_mode); + if (ovl_need_xattr_filter(inode, type) && ovl_is_private_xattr(name)) return -ENODATA; - return vfs_getxattr(realpath.dentry, name, value, size); + return vfs_getxattr(realdentry, name, value, size); } ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) @@ -274,7 +277,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) if (res <= 0 || size == 0) return res; - if (!ovl_need_xattr_filter(dentry, type)) + if (!ovl_need_xattr_filter(dentry->d_inode, type)) return res; /* filter out private xattrs */ @@ -306,7 +309,8 @@ int ovl_removexattr(struct dentry *dentry, const char *name) goto out; err = -ENODATA; - if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) + if (ovl_need_xattr_filter(dentry->d_inode, type) && + ovl_is_private_xattr(name)) goto out_drop_write; if (!OVL_TYPE_UPPER(type)) { diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 4bd9b5b..0d1430f 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -131,6 +131,7 @@ static inline int ovl_do_whiteout(struct inode *dir, struct dentry *dentry) return err; } +enum ovl_path_type __ovl_path_type(struct ovl_entry *oe, umode_t mode); enum ovl_path_type ovl_path_type(struct dentry *dentry); u64 ovl_dentry_version_get(struct dentry *dentry); void ovl_dentry_version_inc(struct dentry *dentry); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index ce02f46..d04546e 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -70,9 +70,8 @@ static struct dentry *__ovl_dentry_lower(struct ovl_entry *oe) return oe->numlower ? oe->lowerstack[0].dentry : NULL; } -enum ovl_path_type ovl_path_type(struct dentry *dentry) +enum ovl_path_type __ovl_path_type(struct ovl_entry *oe, umode_t mode) { - struct ovl_entry *oe = dentry->d_fsdata; enum ovl_path_type type = 0; if (oe->__upperdentry) { @@ -82,7 +81,7 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry) * Non-dir dentry can hold lower dentry from previous * location. Its purity depends only on opaque flag. */ - if (oe->numlower && S_ISDIR(dentry->d_inode->i_mode)) + if (oe->numlower && S_ISDIR(mode)) type |= __OVL_PATH_MERGE; else if (!oe->opaque) type |= __OVL_PATH_PURE; @@ -93,6 +92,11 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry) return type; } +enum ovl_path_type ovl_path_type(struct dentry *dentry) +{ + return __ovl_path_type(dentry->d_fsdata, dentry->d_inode->i_mode); +} + static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) { return lockless_dereference(oe->__upperdentry);