From: Greg KH <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: torvalds@linux-foundation.org, akpm@linux-foundation.org,
alan@lxorguk.ukuu.org.uk, Christoph Hellwig <hch@lst.de>,
Dustin Kirkland <kirkland@canonical.com>,
ecryptfs-devel@lists.launchpad.net,
linux-fsdevel@vger.kernel.org,
Tyler Hicks <tyhicks@linux.vnet.ibm.com>,
Colin Ian King <colin.king@canonical.com>,
Tim Gardner <tim.gardner@canonical.com>
Subject: [ 24/34] eCryptfs: Use notify_change for truncating lower inodes
Date: Thu, 01 Mar 2012 13:39:46 -0800 [thread overview]
Message-ID: <20120301213926.126802364@linuxfoundation.org> (raw)
In-Reply-To: <20120301214654.GA13231@kroah.com>
2.6.32-longterm review patch. If anyone has any objections, please let me know.
------------------
From: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
commit 5f3ef64f4da1c587cdcfaaac72311225b7df094c upstream.
When truncating inodes in the lower filesystem, eCryptfs directly
invoked vmtruncate(). As Christoph Hellwig pointed out, vmtruncate() is
a filesystem helper function, but filesystems may need to do more than
just a call to vmtruncate().
This patch moves the lower inode truncation out of ecryptfs_truncate()
and renames the function to truncate_upper(). truncate_upper() updates
an iattr for the lower inode to indicate if the lower inode needs to be
truncated upon return. ecryptfs_setattr() then calls notify_change(),
using the updated iattr for the lower inode, to complete the truncation.
For eCryptfs functions needing to truncate, ecryptfs_truncate() is
reintroduced as a simple way to truncate the upper inode to a specified
size and then truncate the lower inode accordingly.
https://bugs.launchpad.net/bugs/451368
Reported-by: Christoph Hellwig <hch@lst.de>
Acked-by: Dustin Kirkland <kirkland@canonical.com>
Cc: ecryptfs-devel@lists.launchpad.net
Cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
Signed-off-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ecryptfs/inode.c | 99 +++++++++++++++++++++++++++++++++++-----------------
1 file changed, 67 insertions(+), 32 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -758,18 +758,23 @@ upper_size_to_lower_size(struct ecryptfs
}
/**
- * ecryptfs_truncate
+ * truncate_upper
* @dentry: The ecryptfs layer dentry
- * @new_length: The length to expand the file to
+ * @ia: Address of the ecryptfs inode's attributes
+ * @lower_ia: Address of the lower inode's attributes
*
* Function to handle truncations modifying the size of the file. Note
* that the file sizes are interpolated. When expanding, we are simply
- * writing strings of 0's out. When truncating, we need to modify the
- * underlying file size according to the page index interpolations.
+ * writing strings of 0's out. When truncating, we truncate the upper
+ * inode and update the lower_ia according to the page index
+ * interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return,
+ * the caller must use lower_ia in a call to notify_change() to perform
+ * the truncation of the lower inode.
*
* Returns zero on success; non-zero otherwise
*/
-int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
+static int truncate_upper(struct dentry *dentry, struct iattr *ia,
+ struct iattr *lower_ia)
{
int rc = 0;
struct inode *inode = dentry->d_inode;
@@ -780,8 +785,10 @@ int ecryptfs_truncate(struct dentry *den
loff_t lower_size_before_truncate;
loff_t lower_size_after_truncate;
- if (unlikely((new_length == i_size)))
+ if (unlikely((ia->ia_size == i_size))) {
+ lower_ia->ia_valid &= ~ATTR_SIZE;
goto out;
+ }
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
/* Set up a fake ecryptfs file, this is used to interface with
* the file in the underlying filesystem so that the
@@ -801,28 +808,30 @@ int ecryptfs_truncate(struct dentry *den
&fake_ecryptfs_file,
ecryptfs_inode_to_private(dentry->d_inode)->lower_file);
/* Switch on growing or shrinking file */
- if (new_length > i_size) {
+ if (ia->ia_size > i_size) {
char zero[] = { 0x00 };
+ lower_ia->ia_valid &= ~ATTR_SIZE;
/* Write a single 0 at the last position of the file;
* this triggers code that will fill in 0's throughout
* the intermediate portion of the previous end of the
* file and the new and of the file */
rc = ecryptfs_write(&fake_ecryptfs_file, zero,
- (new_length - 1), 1);
- } else { /* new_length < i_size_read(inode) */
- /* We're chopping off all the pages down do the page
- * in which new_length is located. Fill in the end of
- * that page from (new_length & ~PAGE_CACHE_MASK) to
+ (ia->ia_size - 1), 1);
+ } else { /* ia->ia_size < i_size_read(inode) */
+ /* We're chopping off all the pages down to the page
+ * in which ia->ia_size is located. Fill in the end of
+ * that page from (ia->ia_size & ~PAGE_CACHE_MASK) to
* PAGE_CACHE_SIZE with zeros. */
size_t num_zeros = (PAGE_CACHE_SIZE
- - (new_length & ~PAGE_CACHE_MASK));
+ - (ia->ia_size & ~PAGE_CACHE_MASK));
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
- rc = vmtruncate(inode, new_length);
+ rc = vmtruncate(inode, ia->ia_size);
if (rc)
goto out_free;
- rc = vmtruncate(lower_dentry->d_inode, new_length);
+ lower_ia->ia_size = ia->ia_size;
+ lower_ia->ia_valid |= ATTR_SIZE;
goto out_free;
}
if (num_zeros) {
@@ -834,7 +843,7 @@ int ecryptfs_truncate(struct dentry *den
goto out_free;
}
rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt,
- new_length, num_zeros);
+ ia->ia_size, num_zeros);
kfree(zeros_virt);
if (rc) {
printk(KERN_ERR "Error attempting to zero out "
@@ -843,7 +852,7 @@ int ecryptfs_truncate(struct dentry *den
goto out_free;
}
}
- vmtruncate(inode, new_length);
+ vmtruncate(inode, ia->ia_size);
rc = ecryptfs_write_inode_size_to_metadata(inode);
if (rc) {
printk(KERN_ERR "Problem with "
@@ -856,10 +865,12 @@ int ecryptfs_truncate(struct dentry *den
lower_size_before_truncate =
upper_size_to_lower_size(crypt_stat, i_size);
lower_size_after_truncate =
- upper_size_to_lower_size(crypt_stat, new_length);
- if (lower_size_after_truncate < lower_size_before_truncate)
- vmtruncate(lower_dentry->d_inode,
- lower_size_after_truncate);
+ upper_size_to_lower_size(crypt_stat, ia->ia_size);
+ if (lower_size_after_truncate < lower_size_before_truncate) {
+ lower_ia->ia_size = lower_size_after_truncate;
+ lower_ia->ia_valid |= ATTR_SIZE;
+ } else
+ lower_ia->ia_valid &= ~ATTR_SIZE;
}
out_free:
if (ecryptfs_file_to_private(&fake_ecryptfs_file))
@@ -869,6 +880,33 @@ out:
return rc;
}
+/**
+ * ecryptfs_truncate
+ * @dentry: The ecryptfs layer dentry
+ * @new_length: The length to expand the file to
+ *
+ * Simple function that handles the truncation of an eCryptfs inode and
+ * its corresponding lower inode.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
+{
+ struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length };
+ struct iattr lower_ia = { .ia_valid = 0 };
+ int rc;
+
+ rc = truncate_upper(dentry, &ia, &lower_ia);
+ if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
+ struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+
+ mutex_lock(&lower_dentry->d_inode->i_mutex);
+ rc = notify_change(lower_dentry, &lower_ia);
+ mutex_unlock(&lower_dentry->d_inode->i_mutex);
+ }
+ return rc;
+}
+
static int
ecryptfs_permission(struct inode *inode, int mask)
{
@@ -891,6 +929,7 @@ static int ecryptfs_setattr(struct dentr
{
int rc = 0;
struct dentry *lower_dentry;
+ struct iattr lower_ia;
struct inode *inode;
struct inode *lower_inode;
struct ecryptfs_crypt_stat *crypt_stat;
@@ -929,15 +968,11 @@ static int ecryptfs_setattr(struct dentr
}
}
mutex_unlock(&crypt_stat->cs_mutex);
+ memcpy(&lower_ia, ia, sizeof(lower_ia));
+ if (ia->ia_valid & ATTR_FILE)
+ lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
if (ia->ia_valid & ATTR_SIZE) {
- ecryptfs_printk(KERN_DEBUG,
- "ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n",
- ia->ia_valid, ATTR_SIZE);
- rc = ecryptfs_truncate(dentry, ia->ia_size);
- /* ecryptfs_truncate handles resizing of the lower file */
- ia->ia_valid &= ~ATTR_SIZE;
- ecryptfs_printk(KERN_DEBUG, "ia->ia_valid = [%x]\n",
- ia->ia_valid);
+ rc = truncate_upper(dentry, ia, &lower_ia);
if (rc < 0)
goto out;
}
@@ -946,11 +981,11 @@ static int ecryptfs_setattr(struct dentr
* mode change is for clearing setuid/setgid bits. Allow lower fs
* to interpret this in its own way.
*/
- if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
- ia->ia_valid &= ~ATTR_MODE;
+ if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
+ lower_ia.ia_valid &= ~ATTR_MODE;
mutex_lock(&lower_dentry->d_inode->i_mutex);
- rc = notify_change(lower_dentry, ia);
+ rc = notify_change(lower_dentry, &lower_ia);
mutex_unlock(&lower_dentry->d_inode->i_mutex);
out:
fsstack_copy_attr_all(inode, lower_inode, NULL);
next prev parent reply other threads:[~2012-03-01 21:39 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-01 21:46 [ 00/34] 2.6.32.58-longterm review Greg KH
2012-03-01 21:39 ` [ 01/34] drm/i915: no lvds quirk for AOpen MP45 Greg KH
2012-03-01 21:39 ` [ 02/34] hwmon: (f75375s) Fix bit shifting in f75375_write16 Greg KH
2012-03-01 21:39 ` [ 03/34] lib: proportion: lower PROP_MAX_SHIFT to 32 on 64-bit kernel Greg KH
2012-03-05 15:06 ` Jan Kara
2012-03-05 21:31 ` Fengguang Wu
2012-03-06 20:35 ` Jan Kara
2012-03-07 5:14 ` Fengguang Wu
2012-03-01 21:39 ` [ 04/34] relay: prevent integer overflow in relay_open() Greg KH
2012-03-01 21:39 ` [ 05/34] mac80211: timeout a single frame in the rx reorder buffer Greg KH
2012-03-01 21:39 ` [ 06/34] kernel.h: fix wrong usage of __ratelimit() Greg KH
2012-03-01 21:39 ` [ 07/34] printk_ratelimited(): fix uninitialized spinlock Greg KH
2012-03-01 21:39 ` [ 08/34] hwmon: (f75375s) Fix automatic pwm mode setting for F75373 & F75375 Greg KH
2012-03-01 21:39 ` [ 09/34] crypto: sha512 - Use binary and instead of modulus Greg KH
2012-03-01 21:39 ` [ 10/34] crypto: sha512 - Avoid stack bloat on i386 Greg KH
2012-03-01 21:39 ` [ 11/34] eCryptfs: Remove mmap from directory operations Greg KH
2012-03-01 21:39 ` [ 12/34] Ban ecryptfs over ecryptfs Greg KH
2012-03-01 21:39 ` [ 13/34] Add mount option to check uid of device being mounted = expect uid, CVE-2011-1833 Greg KH
2012-03-01 21:39 ` [ 14/34] crypto: sha512 - use standard ror64() Greg KH
2012-03-01 21:39 ` [ 15/34] drm/radeon/kms: fix MSI re-arm on rv370+ Greg KH
2012-03-01 21:39 ` [ 16/34] ecryptfs: read on a directory should return EISDIR if not supported Greg KH
2012-03-01 21:39 ` [ 17/34] SCSI: 3w-9xxx fix bug in sgl loading Greg KH
2012-03-01 21:39 ` [ 18/34] ARM: 7321/1: cache-v7: Disable preemption when reading CCSIDR Greg KH
2012-03-01 21:39 ` [ 19/34] ARM: 7325/1: fix v7 boot with lockdep enabled Greg KH
2012-03-01 21:39 ` [ 20/34] USB: Added Kamstrup VID/PIDs to cp210x serial driver Greg KH
2012-03-01 21:39 ` [ 21/34] USB: Fix handoff when BIOS disables host PCI device Greg KH
2012-03-01 21:39 ` [ 22/34] xhci: Fix encoding for HS bulk/control NAK rate Greg KH
2012-03-01 21:39 ` [ 23/34] [media] hdpvr: fix race conditon during start of streaming Greg KH
2012-03-01 21:39 ` Greg KH [this message]
2012-03-01 21:39 ` [ 25/34] eCryptfs: Remove extra d_delete in ecryptfs_rmdir Greg KH
2012-03-01 21:39 ` [ 26/34] eCryptfs: Clear i_nlink in rmdir Greg KH
2012-03-01 21:39 ` [ 27/34] cdrom: use copy_to_user() without the underscores Greg KH
2012-03-01 21:39 ` [ 28/34] autofs: work around unhappy compat problem on x86-64 Greg KH
2012-03-01 21:39 ` [ 29/34] Fix autofs compile without CONFIG_COMPAT Greg KH
2012-03-01 21:39 ` [ 30/34] compat: fix compile breakage on s390 Greg KH
2012-03-01 21:39 ` [ 31/34] PM: Print a warning if firmware is requested when tasks are frozen Greg KH
2012-03-01 21:39 ` [ 32/34] firmware loader: allow builtin firmware load even if usermodehelper is disabled Greg KH
2012-03-01 21:39 ` [ 33/34] PM / Sleep: Fix freezer failures due to racy usermodehelper_is_disabled() Greg KH
2012-03-01 21:39 ` [ 34/34] PM / Sleep: Fix read_unlock_usermodehelper() call Greg KH
2012-03-02 7:19 ` [ 00/34] 2.6.32.58-longterm review Willy Tarreau
2012-03-02 13:51 ` Stefan Bader
2012-03-02 15:37 ` Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120301213926.126802364@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=colin.king@canonical.com \
--cc=ecryptfs-devel@lists.launchpad.net \
--cc=hch@lst.de \
--cc=kirkland@canonical.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tim.gardner@canonical.com \
--cc=torvalds@linux-foundation.org \
--cc=tyhicks@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).