From 214806c7e9833fb525a78a335b56fff5e863942e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 2 Jul 2014 23:47:02 +0200 Subject: [PATCH] Safely handle security / ACL failures The security and ACL operations should all be performed atomically. To accomplish this there would need to significant invasive changes made to the common code base. For the moment it's desirable for compatibility reasons to avoid this. Therefore the code has been updated to attempt to unwind the operation in case of failure rather than panic. Signed-off-by: Brian Behlendorf Closes #2445 --- module/zfs/zpl_inode.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c index d72271459..31251e730 100644 --- a/module/zfs/zpl_inode.c +++ b/module/zfs/zpl_inode.c @@ -107,9 +107,14 @@ zpl_create(struct inode *dir, struct dentry *dentry, zpl_umode_t mode, cookie = spl_fstrans_mark(); error = -zfs_create(dir, dname(dentry), vap, 0, mode, &ip, cr, 0, NULL); if (error == 0) { - VERIFY0(zpl_xattr_security_init(ip, dir, &dentry->d_name)); - VERIFY0(zpl_init_acl(ip, dir)); d_instantiate(dentry, ip); + + error = zpl_xattr_security_init(ip, dir, &dentry->d_name); + if (error == 0) + error = zpl_init_acl(ip, dir); + + if (error) + (void) zfs_remove(dir, dname(dentry), cr); } spl_fstrans_unmark(cookie); @@ -145,9 +150,14 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, zpl_umode_t mode, cookie = spl_fstrans_mark(); error = -zfs_create(dir, dname(dentry), vap, 0, mode, &ip, cr, 0, NULL); if (error == 0) { - VERIFY0(zpl_xattr_security_init(ip, dir, &dentry->d_name)); - VERIFY0(zpl_init_acl(ip, dir)); d_instantiate(dentry, ip); + + error = zpl_xattr_security_init(ip, dir, &dentry->d_name); + if (error == 0) + error = zpl_init_acl(ip, dir); + + if (error) + (void) zfs_remove(dir, dname(dentry), cr); } spl_fstrans_unmark(cookie); @@ -191,9 +201,14 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, zpl_umode_t mode) cookie = spl_fstrans_mark(); error = -zfs_mkdir(dir, dname(dentry), vap, &ip, cr, 0, NULL); if (error == 0) { - VERIFY0(zpl_xattr_security_init(ip, dir, &dentry->d_name)); - VERIFY0(zpl_init_acl(ip, dir)); d_instantiate(dentry, ip); + + error = zpl_xattr_security_init(ip, dir, &dentry->d_name); + if (error == 0) + error = zpl_init_acl(ip, dir); + + if (error) + (void) zfs_rmdir(dir, dname(dentry), NULL, cr, 0); } spl_fstrans_unmark(cookie); @@ -318,8 +333,11 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) cookie = spl_fstrans_mark(); error = -zfs_symlink(dir, dname(dentry), vap, (char *)name, &ip, cr, 0); if (error == 0) { - VERIFY0(zpl_xattr_security_init(ip, dir, &dentry->d_name)); d_instantiate(dentry, ip); + + error = zpl_xattr_security_init(ip, dir, &dentry->d_name); + if (error) + (void) zfs_remove(dir, dname(dentry), cr); } spl_fstrans_unmark(cookie);