#include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/xattr.h>
+#include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
         * filesystem  or on an immutable / append-only inode.
         */
        if (mask & MAY_WRITE) {
-               if (IS_RDONLY(inode))
-                       return -EROFS;
                if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                        return -EPERM;
        }
        error = user_path_walk(path, &nd);
        if (error)
                return error;
-       error = setxattr(nd.path.dentry, name, value, size, flags);
+       error = mnt_want_write(nd.path.mnt);
+       if (!error) {
+               error = setxattr(nd.path.dentry, name, value, size, flags);
+               mnt_drop_write(nd.path.mnt);
+       }
        path_put(&nd.path);
        return error;
 }
        error = user_path_walk_link(path, &nd);
        if (error)
                return error;
-       error = setxattr(nd.path.dentry, name, value, size, flags);
+       error = mnt_want_write(nd.path.mnt);
+       if (!error) {
+               error = setxattr(nd.path.dentry, name, value, size, flags);
+               mnt_drop_write(nd.path.mnt);
+       }
        path_put(&nd.path);
        return error;
 }
                return error;
        dentry = f->f_path.dentry;
        audit_inode(NULL, dentry);
-       error = setxattr(dentry, name, value, size, flags);
+       error = mnt_want_write(f->f_path.mnt);
+       if (!error) {
+               error = setxattr(dentry, name, value, size, flags);
+               mnt_drop_write(f->f_path.mnt);
+       }
+out_fput:
        fput(f);
        return error;
 }
        error = user_path_walk(path, &nd);
        if (error)
                return error;
-       error = removexattr(nd.path.dentry, name);
+       error = mnt_want_write(nd.path.mnt);
+       if (!error) {
+               error = removexattr(nd.path.dentry, name);
+               mnt_drop_write(nd.path.mnt);
+       }
        path_put(&nd.path);
        return error;
 }
        error = user_path_walk_link(path, &nd);
        if (error)
                return error;
-       error = removexattr(nd.path.dentry, name);
+       error = mnt_want_write(nd.path.mnt);
+       if (!error) {
+               error = removexattr(nd.path.dentry, name);
+               mnt_drop_write(nd.path.mnt);
+       }
        path_put(&nd.path);
        return error;
 }
                return error;
        dentry = f->f_path.dentry;
        audit_inode(NULL, dentry);
-       error = removexattr(dentry, name);
+       error = mnt_want_write(f->f_path.mnt);
+       if (!error) {
+               error = removexattr(dentry, name);
+               mnt_drop_write(f->f_path.mnt);
+       }
        fput(f);
        return error;
 }