Only check directory xattr on ENOENT
[zfs.git] / module / zfs / zpl_xattr.c
index 9117b7b..eb2c00d 100644 (file)
@@ -225,6 +225,11 @@ zpl_xattr_get_dir(struct inode *ip, const char *name, void *value,
                goto out;
        }
 
+       if (size < i_size_read(xip)) {
+               error = -ERANGE;
+               goto out;
+       }
+
        error = zpl_read_common(xip, value, size, 0, UIO_SYSSPACE, 0, cr);
 out:
        if (xip)
@@ -263,9 +268,12 @@ zpl_xattr_get_sa(struct inode *ip, const char *name, void *value, size_t size)
        if (!size)
                return (nv_size);
 
-       memcpy(value, nv_value, MIN(size, nv_size));
+       if (size < nv_size)
+               return (-ERANGE);
 
-       return (MIN(size, nv_size));
+       memcpy(value, nv_value, nv_size);
+
+       return (nv_size);
 }
 
 static int
@@ -280,7 +288,7 @@ __zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size,
 
        if (zsb->z_use_sa && zp->z_is_sa) {
                error = zpl_xattr_get_sa(ip, name, value, size);
-               if (error >= 0)
+               if (error != -ENOENT)
                        goto out;
        }
 
@@ -606,31 +614,59 @@ __zpl_xattr_security_set(struct inode *ip, const char *name,
 }
 ZPL_XATTR_SET_WRAPPER(zpl_xattr_security_set);
 
+#ifdef HAVE_CALLBACK_SECURITY_INODE_INIT_SECURITY
+static int
+__zpl_xattr_security_init(struct inode *ip, const struct xattr *xattrs,
+    void *fs_info)
+{
+       const struct xattr *xattr;
+       int error = 0;
+
+       for (xattr = xattrs; xattr->name != NULL; xattr++) {
+               error = __zpl_xattr_security_set(ip,
+                   xattr->name, xattr->value, xattr->value_len, 0);
+
+               if (error < 0)
+                       break;
+       }
+
+       return (error);
+}
+
 int
 zpl_xattr_security_init(struct inode *ip, struct inode *dip,
     const struct qstr *qstr)
 {
-        int error;
-        size_t len;
-        void *value;
-        char *name;
+       return security_inode_init_security(ip, dip, qstr,
+           &__zpl_xattr_security_init, NULL);
+}
 
-        error = zpl_security_inode_init_security(ip, dip, qstr,
-           &name, &value, &len);
-        if (error) {
-                if (error == -EOPNOTSUPP)
-                        return 0;
+#else
+int
+zpl_xattr_security_init(struct inode *ip, struct inode *dip,
+    const struct qstr *qstr)
+{
+       int error;
+       size_t len;
+       void *value;
+       char *name;
 
-                return (error);
-        }
+       error = zpl_security_inode_init_security(ip, dip, qstr,
+         &name, &value, &len);
+       if (error) {
+               if (error == -EOPNOTSUPP)
+                       return 0;
+               return (error);
+       }
 
        error = __zpl_xattr_security_set(ip, name, value, len, 0);
 
-        kfree(name);
-        kfree(value);
+       kfree(name);
+       kfree(value);
 
-        return (error);
+       return (error);
 }
+#endif /* HAVE_CALLBACK_SECURITY_INODE_INIT_SECURITY */
 
 xattr_handler_t zpl_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
@@ -644,6 +680,7 @@ xattr_handler_t *zpl_xattr_handlers[] = {
        &zpl_xattr_user_handler,
 #ifdef HAVE_POSIX_ACLS
        &zpl_xattr_acl_access_handler,
-        &zpl_xattr_acl_default_handler,
+       &zpl_xattr_acl_default_handler,
 #endif /* HAVE_POSIX_ACLS */
+       NULL
 };