.ia_size = stat->size,
        };
 
-       return notify_change(&init_user_ns, upperdentry, &attr, NULL);
+       return ovl_do_notify_change(ofs, upperdentry, &attr);
 }
 
 static int ovl_set_timestamps(struct ovl_fs *ofs, struct dentry *upperdentry,
                .ia_mtime = stat->mtime,
        };
 
-       return notify_change(&init_user_ns, upperdentry, &attr, NULL);
+       return ovl_do_notify_change(ofs, upperdentry, &attr);
 }
 
 int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry,
                        .ia_valid = ATTR_MODE,
                        .ia_mode = stat->mode,
                };
-               err = notify_change(&init_user_ns, upperdentry, &attr, NULL);
+               err = ovl_do_notify_change(ofs, upperdentry, &attr);
        }
        if (!err) {
                struct iattr attr = {
                        .ia_uid = stat->uid,
                        .ia_gid = stat->gid,
                };
-               err = notify_change(&init_user_ns, upperdentry, &attr, NULL);
+               err = ovl_do_notify_change(ofs, upperdentry, &attr);
        }
        if (!err)
                ovl_set_timestamps(ofs, upperdentry, stat);
 
                        .ia_mode = cattr->mode,
                };
                inode_lock(newdentry->d_inode);
-               err = notify_change(&init_user_ns, newdentry, &attr, NULL);
+               err = ovl_do_notify_change(ofs, newdentry, &attr);
                inode_unlock(newdentry->d_inode);
                if (err)
                        goto out_cleanup;
 
                struct iattr *attr)
 {
        int err;
+       struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
        bool full_copy_up = false;
        struct dentry *upperdentry;
        const struct cred *old_cred;
 
                inode_lock(upperdentry->d_inode);
                old_cred = ovl_override_creds(dentry->d_sb);
-               err = notify_change(&init_user_ns, upperdentry, attr, NULL);
+               err = ovl_do_notify_change(ofs, upperdentry, attr);
                revert_creds(old_cred);
                if (!err)
                        ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
 
        return ovl_xattr_table[ox][ofs->config.userxattr];
 }
 
+/*
+ * When changing ownership of an upper object map the intended ownership
+ * according to the upper layer's idmapping. When an upper mount idmaps files
+ * that are stored on-disk as owned by id 1001 to id 1000 this means stat on
+ * this object will report it as being owned by id 1000 when calling stat via
+ * the upper mount.
+ * In order to change ownership of an object so stat reports id 1000 when
+ * called on an idmapped upper mount the value written to disk - i.e., the
+ * value stored in ia_*id - must 1001. The mount mapping helper will thus take
+ * care to map 1000 to 1001.
+ * The mnt idmapping helpers are nops if the upper layer isn't idmapped.
+ */
+static inline int ovl_do_notify_change(struct ovl_fs *ofs,
+                                      struct dentry *upperdentry,
+                                      struct iattr *attr)
+{
+       struct user_namespace *upper_mnt_userns = ovl_upper_mnt_userns(ofs);
+       struct user_namespace *fs_userns = i_user_ns(d_inode(upperdentry));
+
+       if (attr->ia_valid & ATTR_UID)
+               attr->ia_uid = mapped_kuid_user(upper_mnt_userns,
+                                               fs_userns, attr->ia_uid);
+       if (attr->ia_valid & ATTR_GID)
+               attr->ia_gid = mapped_kgid_user(upper_mnt_userns,
+                                               fs_userns, attr->ia_gid);
+
+       return notify_change(upper_mnt_userns, upperdentry, attr, NULL);
+}
+
 static inline int ovl_do_rmdir(struct ovl_fs *ofs,
                               struct inode *dir, struct dentry *dentry)
 {
 
 
                /* Clear any inherited mode bits */
                inode_lock(work->d_inode);
-               err = notify_change(&init_user_ns, work, &attr, NULL);
+               err = ovl_do_notify_change(ofs, work, &attr);
                inode_unlock(work->d_inode);
                if (err)
                        goto out_dput;