]> granicus.if.org Git - zfs/commitdiff
Safely handle security / ACL failures
authorDavid Lamparter <equinox@diac24.net>
Wed, 2 Jul 2014 21:47:02 +0000 (23:47 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 11 May 2015 21:35:14 +0000 (14:35 -0700)
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 <behlendorf1@llnl.gov>
Closes #2445

module/zfs/zpl_inode.c

index d722714592b9a564669b46889bbd408077f8f8c2..31251e7305cd8aa95b321bca9aa782f04811a2b2 100644 (file)
@@ -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);