1e9be9d5eSMiklos Szeredi /* 2e9be9d5eSMiklos Szeredi * 3e9be9d5eSMiklos Szeredi * Copyright (C) 2011 Novell Inc. 4e9be9d5eSMiklos Szeredi * 5e9be9d5eSMiklos Szeredi * This program is free software; you can redistribute it and/or modify it 6e9be9d5eSMiklos Szeredi * under the terms of the GNU General Public License version 2 as published by 7e9be9d5eSMiklos Szeredi * the Free Software Foundation. 8e9be9d5eSMiklos Szeredi */ 9e9be9d5eSMiklos Szeredi 10fb5bb2c3SDavid Howells #include <linux/module.h> 11e9be9d5eSMiklos Szeredi #include <linux/fs.h> 12e9be9d5eSMiklos Szeredi #include <linux/slab.h> 13e9be9d5eSMiklos Szeredi #include <linux/file.h> 14e9be9d5eSMiklos Szeredi #include <linux/splice.h> 15e9be9d5eSMiklos Szeredi #include <linux/xattr.h> 16e9be9d5eSMiklos Szeredi #include <linux/security.h> 17e9be9d5eSMiklos Szeredi #include <linux/uaccess.h> 18e9be9d5eSMiklos Szeredi #include <linux/sched.h> 19e9be9d5eSMiklos Szeredi #include <linux/namei.h> 20fb5bb2c3SDavid Howells #include <linux/fdtable.h> 21fb5bb2c3SDavid Howells #include <linux/ratelimit.h> 22e9be9d5eSMiklos Szeredi #include "overlayfs.h" 23e9be9d5eSMiklos Szeredi 24e9be9d5eSMiklos Szeredi #define OVL_COPY_UP_CHUNK_SIZE (1 << 20) 25e9be9d5eSMiklos Szeredi 26fb5bb2c3SDavid Howells static bool __read_mostly ovl_check_copy_up; 27fb5bb2c3SDavid Howells module_param_named(check_copy_up, ovl_check_copy_up, bool, 28fb5bb2c3SDavid Howells S_IWUSR | S_IRUGO); 29fb5bb2c3SDavid Howells MODULE_PARM_DESC(ovl_check_copy_up, 30fb5bb2c3SDavid Howells "Warn on copy-up when causing process also has a R/O fd open"); 31fb5bb2c3SDavid Howells 32fb5bb2c3SDavid Howells static int ovl_check_fd(const void *data, struct file *f, unsigned int fd) 33fb5bb2c3SDavid Howells { 34fb5bb2c3SDavid Howells const struct dentry *dentry = data; 35fb5bb2c3SDavid Howells 36fb5bb2c3SDavid Howells if (f->f_inode == d_inode(dentry)) 37fb5bb2c3SDavid Howells pr_warn_ratelimited("overlayfs: Warning: Copying up %pD, but open R/O on fd %u which will cease to be coherent [pid=%d %s]\n", 38fb5bb2c3SDavid Howells f, fd, current->pid, current->comm); 39fb5bb2c3SDavid Howells return 0; 40fb5bb2c3SDavid Howells } 41fb5bb2c3SDavid Howells 42fb5bb2c3SDavid Howells /* 43fb5bb2c3SDavid Howells * Check the fds open by this process and warn if something like the following 44fb5bb2c3SDavid Howells * scenario is about to occur: 45fb5bb2c3SDavid Howells * 46fb5bb2c3SDavid Howells * fd1 = open("foo", O_RDONLY); 47fb5bb2c3SDavid Howells * fd2 = open("foo", O_RDWR); 48fb5bb2c3SDavid Howells */ 49fb5bb2c3SDavid Howells static void ovl_do_check_copy_up(struct dentry *dentry) 50fb5bb2c3SDavid Howells { 51fb5bb2c3SDavid Howells if (ovl_check_copy_up) 52fb5bb2c3SDavid Howells iterate_fd(current->files, 0, ovl_check_fd, dentry); 53fb5bb2c3SDavid Howells } 54fb5bb2c3SDavid Howells 55e9be9d5eSMiklos Szeredi int ovl_copy_xattr(struct dentry *old, struct dentry *new) 56e9be9d5eSMiklos Szeredi { 57e4ad29faSVito Caputo ssize_t list_size, size, value_size = 0; 58e4ad29faSVito Caputo char *buf, *name, *value = NULL; 59e4ad29faSVito Caputo int uninitialized_var(error); 60e9be9d5eSMiklos Szeredi 61e9be9d5eSMiklos Szeredi if (!old->d_inode->i_op->getxattr || 62e9be9d5eSMiklos Szeredi !new->d_inode->i_op->getxattr) 63e9be9d5eSMiklos Szeredi return 0; 64e9be9d5eSMiklos Szeredi 65e9be9d5eSMiklos Szeredi list_size = vfs_listxattr(old, NULL, 0); 66e9be9d5eSMiklos Szeredi if (list_size <= 0) { 67e9be9d5eSMiklos Szeredi if (list_size == -EOPNOTSUPP) 68e9be9d5eSMiklos Szeredi return 0; 69e9be9d5eSMiklos Szeredi return list_size; 70e9be9d5eSMiklos Szeredi } 71e9be9d5eSMiklos Szeredi 72e9be9d5eSMiklos Szeredi buf = kzalloc(list_size, GFP_KERNEL); 73e9be9d5eSMiklos Szeredi if (!buf) 74e9be9d5eSMiklos Szeredi return -ENOMEM; 75e9be9d5eSMiklos Szeredi 76e9be9d5eSMiklos Szeredi list_size = vfs_listxattr(old, buf, list_size); 77e9be9d5eSMiklos Szeredi if (list_size <= 0) { 78e9be9d5eSMiklos Szeredi error = list_size; 79e4ad29faSVito Caputo goto out; 80e9be9d5eSMiklos Szeredi } 81e9be9d5eSMiklos Szeredi 82e9be9d5eSMiklos Szeredi for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { 83e4ad29faSVito Caputo retry: 84e4ad29faSVito Caputo size = vfs_getxattr(old, name, value, value_size); 85e4ad29faSVito Caputo if (size == -ERANGE) 86e4ad29faSVito Caputo size = vfs_getxattr(old, name, NULL, 0); 87e4ad29faSVito Caputo 8897daf8b9SMiklos Szeredi if (size < 0) { 89e9be9d5eSMiklos Szeredi error = size; 90e4ad29faSVito Caputo break; 91e9be9d5eSMiklos Szeredi } 92e9be9d5eSMiklos Szeredi 93e4ad29faSVito Caputo if (size > value_size) { 94e4ad29faSVito Caputo void *new; 95e4ad29faSVito Caputo 96e4ad29faSVito Caputo new = krealloc(value, size, GFP_KERNEL); 97e4ad29faSVito Caputo if (!new) { 98e4ad29faSVito Caputo error = -ENOMEM; 99e4ad29faSVito Caputo break; 100e4ad29faSVito Caputo } 101e4ad29faSVito Caputo value = new; 102e4ad29faSVito Caputo value_size = size; 103e4ad29faSVito Caputo goto retry; 104e4ad29faSVito Caputo } 105e4ad29faSVito Caputo 106e4ad29faSVito Caputo error = vfs_setxattr(new, name, value, size, 0); 107e4ad29faSVito Caputo if (error) 108e4ad29faSVito Caputo break; 109e4ad29faSVito Caputo } 110e9be9d5eSMiklos Szeredi kfree(value); 111e9be9d5eSMiklos Szeredi out: 112e9be9d5eSMiklos Szeredi kfree(buf); 113e9be9d5eSMiklos Szeredi return error; 114e9be9d5eSMiklos Szeredi } 115e9be9d5eSMiklos Szeredi 116e9be9d5eSMiklos Szeredi static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) 117e9be9d5eSMiklos Szeredi { 118e9be9d5eSMiklos Szeredi struct file *old_file; 119e9be9d5eSMiklos Szeredi struct file *new_file; 120e9be9d5eSMiklos Szeredi loff_t old_pos = 0; 121e9be9d5eSMiklos Szeredi loff_t new_pos = 0; 122e9be9d5eSMiklos Szeredi int error = 0; 123e9be9d5eSMiklos Szeredi 124e9be9d5eSMiklos Szeredi if (len == 0) 125e9be9d5eSMiklos Szeredi return 0; 126e9be9d5eSMiklos Szeredi 1270480334fSDavid Howells old_file = ovl_path_open(old, O_LARGEFILE | O_RDONLY); 128e9be9d5eSMiklos Szeredi if (IS_ERR(old_file)) 129e9be9d5eSMiklos Szeredi return PTR_ERR(old_file); 130e9be9d5eSMiklos Szeredi 1310480334fSDavid Howells new_file = ovl_path_open(new, O_LARGEFILE | O_WRONLY); 132e9be9d5eSMiklos Szeredi if (IS_ERR(new_file)) { 133e9be9d5eSMiklos Szeredi error = PTR_ERR(new_file); 134e9be9d5eSMiklos Szeredi goto out_fput; 135e9be9d5eSMiklos Szeredi } 136e9be9d5eSMiklos Szeredi 137e9be9d5eSMiklos Szeredi /* FIXME: copy up sparse files efficiently */ 138e9be9d5eSMiklos Szeredi while (len) { 139e9be9d5eSMiklos Szeredi size_t this_len = OVL_COPY_UP_CHUNK_SIZE; 140e9be9d5eSMiklos Szeredi long bytes; 141e9be9d5eSMiklos Szeredi 142e9be9d5eSMiklos Szeredi if (len < this_len) 143e9be9d5eSMiklos Szeredi this_len = len; 144e9be9d5eSMiklos Szeredi 145e9be9d5eSMiklos Szeredi if (signal_pending_state(TASK_KILLABLE, current)) { 146e9be9d5eSMiklos Szeredi error = -EINTR; 147e9be9d5eSMiklos Szeredi break; 148e9be9d5eSMiklos Szeredi } 149e9be9d5eSMiklos Szeredi 150e9be9d5eSMiklos Szeredi bytes = do_splice_direct(old_file, &old_pos, 151e9be9d5eSMiklos Szeredi new_file, &new_pos, 152e9be9d5eSMiklos Szeredi this_len, SPLICE_F_MOVE); 153e9be9d5eSMiklos Szeredi if (bytes <= 0) { 154e9be9d5eSMiklos Szeredi error = bytes; 155e9be9d5eSMiklos Szeredi break; 156e9be9d5eSMiklos Szeredi } 157e9be9d5eSMiklos Szeredi WARN_ON(old_pos != new_pos); 158e9be9d5eSMiklos Szeredi 159e9be9d5eSMiklos Szeredi len -= bytes; 160e9be9d5eSMiklos Szeredi } 161e9be9d5eSMiklos Szeredi 162e9be9d5eSMiklos Szeredi fput(new_file); 163e9be9d5eSMiklos Szeredi out_fput: 164e9be9d5eSMiklos Szeredi fput(old_file); 165e9be9d5eSMiklos Szeredi return error; 166e9be9d5eSMiklos Szeredi } 167e9be9d5eSMiklos Szeredi 168e9be9d5eSMiklos Szeredi static char *ovl_read_symlink(struct dentry *realdentry) 169e9be9d5eSMiklos Szeredi { 170e9be9d5eSMiklos Szeredi int res; 171e9be9d5eSMiklos Szeredi char *buf; 172e9be9d5eSMiklos Szeredi struct inode *inode = realdentry->d_inode; 173e9be9d5eSMiklos Szeredi mm_segment_t old_fs; 174e9be9d5eSMiklos Szeredi 175e9be9d5eSMiklos Szeredi res = -EINVAL; 176e9be9d5eSMiklos Szeredi if (!inode->i_op->readlink) 177e9be9d5eSMiklos Szeredi goto err; 178e9be9d5eSMiklos Szeredi 179e9be9d5eSMiklos Szeredi res = -ENOMEM; 180e9be9d5eSMiklos Szeredi buf = (char *) __get_free_page(GFP_KERNEL); 181e9be9d5eSMiklos Szeredi if (!buf) 182e9be9d5eSMiklos Szeredi goto err; 183e9be9d5eSMiklos Szeredi 184e9be9d5eSMiklos Szeredi old_fs = get_fs(); 185e9be9d5eSMiklos Szeredi set_fs(get_ds()); 186e9be9d5eSMiklos Szeredi /* The cast to a user pointer is valid due to the set_fs() */ 187e9be9d5eSMiklos Szeredi res = inode->i_op->readlink(realdentry, 188e9be9d5eSMiklos Szeredi (char __user *)buf, PAGE_SIZE - 1); 189e9be9d5eSMiklos Szeredi set_fs(old_fs); 190e9be9d5eSMiklos Szeredi if (res < 0) { 191e9be9d5eSMiklos Szeredi free_page((unsigned long) buf); 192e9be9d5eSMiklos Szeredi goto err; 193e9be9d5eSMiklos Szeredi } 194e9be9d5eSMiklos Szeredi buf[res] = '\0'; 195e9be9d5eSMiklos Szeredi 196e9be9d5eSMiklos Szeredi return buf; 197e9be9d5eSMiklos Szeredi 198e9be9d5eSMiklos Szeredi err: 199e9be9d5eSMiklos Szeredi return ERR_PTR(res); 200e9be9d5eSMiklos Szeredi } 201e9be9d5eSMiklos Szeredi 202e9be9d5eSMiklos Szeredi static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) 203e9be9d5eSMiklos Szeredi { 204e9be9d5eSMiklos Szeredi struct iattr attr = { 205e9be9d5eSMiklos Szeredi .ia_valid = 206e9be9d5eSMiklos Szeredi ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET, 207e9be9d5eSMiklos Szeredi .ia_atime = stat->atime, 208e9be9d5eSMiklos Szeredi .ia_mtime = stat->mtime, 209e9be9d5eSMiklos Szeredi }; 210e9be9d5eSMiklos Szeredi 211e9be9d5eSMiklos Szeredi return notify_change(upperdentry, &attr, NULL); 212e9be9d5eSMiklos Szeredi } 213e9be9d5eSMiklos Szeredi 214e9be9d5eSMiklos Szeredi int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) 215e9be9d5eSMiklos Szeredi { 216e9be9d5eSMiklos Szeredi int err = 0; 217e9be9d5eSMiklos Szeredi 218e9be9d5eSMiklos Szeredi if (!S_ISLNK(stat->mode)) { 219e9be9d5eSMiklos Szeredi struct iattr attr = { 220e9be9d5eSMiklos Szeredi .ia_valid = ATTR_MODE, 221e9be9d5eSMiklos Szeredi .ia_mode = stat->mode, 222e9be9d5eSMiklos Szeredi }; 223e9be9d5eSMiklos Szeredi err = notify_change(upperdentry, &attr, NULL); 224e9be9d5eSMiklos Szeredi } 225e9be9d5eSMiklos Szeredi if (!err) { 226e9be9d5eSMiklos Szeredi struct iattr attr = { 227e9be9d5eSMiklos Szeredi .ia_valid = ATTR_UID | ATTR_GID, 228e9be9d5eSMiklos Szeredi .ia_uid = stat->uid, 229e9be9d5eSMiklos Szeredi .ia_gid = stat->gid, 230e9be9d5eSMiklos Szeredi }; 231e9be9d5eSMiklos Szeredi err = notify_change(upperdentry, &attr, NULL); 232e9be9d5eSMiklos Szeredi } 233e9be9d5eSMiklos Szeredi if (!err) 234e9be9d5eSMiklos Szeredi ovl_set_timestamps(upperdentry, stat); 235e9be9d5eSMiklos Szeredi 236e9be9d5eSMiklos Szeredi return err; 237e9be9d5eSMiklos Szeredi } 238e9be9d5eSMiklos Szeredi 239e9be9d5eSMiklos Szeredi static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, 240e9be9d5eSMiklos Szeredi struct dentry *dentry, struct path *lowerpath, 2410f7ff2daSAl Viro struct kstat *stat, const char *link) 242e9be9d5eSMiklos Szeredi { 243e9be9d5eSMiklos Szeredi struct inode *wdir = workdir->d_inode; 244e9be9d5eSMiklos Szeredi struct inode *udir = upperdir->d_inode; 245e9be9d5eSMiklos Szeredi struct dentry *newdentry = NULL; 246e9be9d5eSMiklos Szeredi struct dentry *upper = NULL; 247e9be9d5eSMiklos Szeredi umode_t mode = stat->mode; 248e9be9d5eSMiklos Szeredi int err; 249e9be9d5eSMiklos Szeredi 250e9be9d5eSMiklos Szeredi newdentry = ovl_lookup_temp(workdir, dentry); 251e9be9d5eSMiklos Szeredi err = PTR_ERR(newdentry); 252e9be9d5eSMiklos Szeredi if (IS_ERR(newdentry)) 253e9be9d5eSMiklos Szeredi goto out; 254e9be9d5eSMiklos Szeredi 255e9be9d5eSMiklos Szeredi upper = lookup_one_len(dentry->d_name.name, upperdir, 256e9be9d5eSMiklos Szeredi dentry->d_name.len); 257e9be9d5eSMiklos Szeredi err = PTR_ERR(upper); 258e9be9d5eSMiklos Szeredi if (IS_ERR(upper)) 259e9be9d5eSMiklos Szeredi goto out1; 260e9be9d5eSMiklos Szeredi 261e9be9d5eSMiklos Szeredi /* Can't properly set mode on creation because of the umask */ 262e9be9d5eSMiklos Szeredi stat->mode &= S_IFMT; 263e9be9d5eSMiklos Szeredi err = ovl_create_real(wdir, newdentry, stat, link, NULL, true); 264e9be9d5eSMiklos Szeredi stat->mode = mode; 265e9be9d5eSMiklos Szeredi if (err) 266e9be9d5eSMiklos Szeredi goto out2; 267e9be9d5eSMiklos Szeredi 268e9be9d5eSMiklos Szeredi if (S_ISREG(stat->mode)) { 269e9be9d5eSMiklos Szeredi struct path upperpath; 270e9be9d5eSMiklos Szeredi ovl_path_upper(dentry, &upperpath); 271e9be9d5eSMiklos Szeredi BUG_ON(upperpath.dentry != NULL); 272e9be9d5eSMiklos Szeredi upperpath.dentry = newdentry; 273e9be9d5eSMiklos Szeredi 274e9be9d5eSMiklos Szeredi err = ovl_copy_up_data(lowerpath, &upperpath, stat->size); 275e9be9d5eSMiklos Szeredi if (err) 276e9be9d5eSMiklos Szeredi goto out_cleanup; 277e9be9d5eSMiklos Szeredi } 278e9be9d5eSMiklos Szeredi 279e9be9d5eSMiklos Szeredi err = ovl_copy_xattr(lowerpath->dentry, newdentry); 280e9be9d5eSMiklos Szeredi if (err) 281e9be9d5eSMiklos Szeredi goto out_cleanup; 282e9be9d5eSMiklos Szeredi 2835955102cSAl Viro inode_lock(newdentry->d_inode); 284e9be9d5eSMiklos Szeredi err = ovl_set_attr(newdentry, stat); 2855955102cSAl Viro inode_unlock(newdentry->d_inode); 286e9be9d5eSMiklos Szeredi if (err) 287e9be9d5eSMiklos Szeredi goto out_cleanup; 288e9be9d5eSMiklos Szeredi 289e9be9d5eSMiklos Szeredi err = ovl_do_rename(wdir, newdentry, udir, upper, 0); 290e9be9d5eSMiklos Szeredi if (err) 291e9be9d5eSMiklos Szeredi goto out_cleanup; 292e9be9d5eSMiklos Szeredi 293e9be9d5eSMiklos Szeredi ovl_dentry_update(dentry, newdentry); 294e9be9d5eSMiklos Szeredi newdentry = NULL; 295e9be9d5eSMiklos Szeredi 296e9be9d5eSMiklos Szeredi /* 297e9be9d5eSMiklos Szeredi * Non-directores become opaque when copied up. 298e9be9d5eSMiklos Szeredi */ 299e9be9d5eSMiklos Szeredi if (!S_ISDIR(stat->mode)) 300e9be9d5eSMiklos Szeredi ovl_dentry_set_opaque(dentry, true); 301e9be9d5eSMiklos Szeredi out2: 302e9be9d5eSMiklos Szeredi dput(upper); 303e9be9d5eSMiklos Szeredi out1: 304e9be9d5eSMiklos Szeredi dput(newdentry); 305e9be9d5eSMiklos Szeredi out: 306e9be9d5eSMiklos Szeredi return err; 307e9be9d5eSMiklos Szeredi 308e9be9d5eSMiklos Szeredi out_cleanup: 309e9be9d5eSMiklos Szeredi ovl_cleanup(wdir, newdentry); 310ab79efabSDavid Howells goto out2; 311e9be9d5eSMiklos Szeredi } 312e9be9d5eSMiklos Szeredi 313e9be9d5eSMiklos Szeredi /* 314e9be9d5eSMiklos Szeredi * Copy up a single dentry 315e9be9d5eSMiklos Szeredi * 316e9be9d5eSMiklos Szeredi * Directory renames only allowed on "pure upper" (already created on 317e9be9d5eSMiklos Szeredi * upper filesystem, never copied up). Directories which are on lower or 318e9be9d5eSMiklos Szeredi * are merged may not be renamed. For these -EXDEV is returned and 319e9be9d5eSMiklos Szeredi * userspace has to deal with it. This means, when copying up a 320e9be9d5eSMiklos Szeredi * directory we can rely on it and ancestors being stable. 321e9be9d5eSMiklos Szeredi * 322e9be9d5eSMiklos Szeredi * Non-directory renames start with copy up of source if necessary. The 323e9be9d5eSMiklos Szeredi * actual rename will only proceed once the copy up was successful. Copy 324e9be9d5eSMiklos Szeredi * up uses upper parent i_mutex for exclusion. Since rename can change 325e9be9d5eSMiklos Szeredi * d_parent it is possible that the copy up will lock the old parent. At 326e9be9d5eSMiklos Szeredi * that point the file will have already been copied up anyway. 327e9be9d5eSMiklos Szeredi */ 328e9be9d5eSMiklos Szeredi int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, 3290f7ff2daSAl Viro struct path *lowerpath, struct kstat *stat) 330e9be9d5eSMiklos Szeredi { 331e9be9d5eSMiklos Szeredi struct dentry *workdir = ovl_workdir(dentry); 332e9be9d5eSMiklos Szeredi int err; 333e9be9d5eSMiklos Szeredi struct kstat pstat; 334e9be9d5eSMiklos Szeredi struct path parentpath; 335e9be9d5eSMiklos Szeredi struct dentry *upperdir; 336e9be9d5eSMiklos Szeredi struct dentry *upperdentry; 337e9be9d5eSMiklos Szeredi const struct cred *old_cred; 338e9be9d5eSMiklos Szeredi struct cred *override_cred; 339e9be9d5eSMiklos Szeredi char *link = NULL; 340e9be9d5eSMiklos Szeredi 341cc6f67bcSMiklos Szeredi if (WARN_ON(!workdir)) 342cc6f67bcSMiklos Szeredi return -EROFS; 343cc6f67bcSMiklos Szeredi 344fb5bb2c3SDavid Howells ovl_do_check_copy_up(lowerpath->dentry); 345fb5bb2c3SDavid Howells 346e9be9d5eSMiklos Szeredi ovl_path_upper(parent, &parentpath); 347e9be9d5eSMiklos Szeredi upperdir = parentpath.dentry; 348e9be9d5eSMiklos Szeredi 349e9be9d5eSMiklos Szeredi err = vfs_getattr(&parentpath, &pstat); 350e9be9d5eSMiklos Szeredi if (err) 351e9be9d5eSMiklos Szeredi return err; 352e9be9d5eSMiklos Szeredi 353e9be9d5eSMiklos Szeredi if (S_ISLNK(stat->mode)) { 354e9be9d5eSMiklos Szeredi link = ovl_read_symlink(lowerpath->dentry); 355e9be9d5eSMiklos Szeredi if (IS_ERR(link)) 356e9be9d5eSMiklos Szeredi return PTR_ERR(link); 357e9be9d5eSMiklos Szeredi } 358e9be9d5eSMiklos Szeredi 359e9be9d5eSMiklos Szeredi err = -ENOMEM; 360e9be9d5eSMiklos Szeredi override_cred = prepare_creds(); 361e9be9d5eSMiklos Szeredi if (!override_cred) 362e9be9d5eSMiklos Szeredi goto out_free_link; 363e9be9d5eSMiklos Szeredi 364e9be9d5eSMiklos Szeredi override_cred->fsuid = stat->uid; 365e9be9d5eSMiklos Szeredi override_cred->fsgid = stat->gid; 366e9be9d5eSMiklos Szeredi /* 367e9be9d5eSMiklos Szeredi * CAP_SYS_ADMIN for copying up extended attributes 368e9be9d5eSMiklos Szeredi * CAP_DAC_OVERRIDE for create 369e9be9d5eSMiklos Szeredi * CAP_FOWNER for chmod, timestamp update 370e9be9d5eSMiklos Szeredi * CAP_FSETID for chmod 371e9be9d5eSMiklos Szeredi * CAP_CHOWN for chown 372e9be9d5eSMiklos Szeredi * CAP_MKNOD for mknod 373e9be9d5eSMiklos Szeredi */ 374e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); 375e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); 376e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_FOWNER); 377e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_FSETID); 378e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_CHOWN); 379e9be9d5eSMiklos Szeredi cap_raise(override_cred->cap_effective, CAP_MKNOD); 380e9be9d5eSMiklos Szeredi old_cred = override_creds(override_cred); 381e9be9d5eSMiklos Szeredi 382e9be9d5eSMiklos Szeredi err = -EIO; 383e9be9d5eSMiklos Szeredi if (lock_rename(workdir, upperdir) != NULL) { 384e9be9d5eSMiklos Szeredi pr_err("overlayfs: failed to lock workdir+upperdir\n"); 385e9be9d5eSMiklos Szeredi goto out_unlock; 386e9be9d5eSMiklos Szeredi } 387e9be9d5eSMiklos Szeredi upperdentry = ovl_dentry_upper(dentry); 388e9be9d5eSMiklos Szeredi if (upperdentry) { 3890f7ff2daSAl Viro /* Raced with another copy-up? Nothing to do, then... */ 390e9be9d5eSMiklos Szeredi err = 0; 3910f7ff2daSAl Viro goto out_unlock; 392e9be9d5eSMiklos Szeredi } 393e9be9d5eSMiklos Szeredi 394e9be9d5eSMiklos Szeredi err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath, 3950f7ff2daSAl Viro stat, link); 396e9be9d5eSMiklos Szeredi if (!err) { 397e9be9d5eSMiklos Szeredi /* Restore timestamps on parent (best effort) */ 398e9be9d5eSMiklos Szeredi ovl_set_timestamps(upperdir, &pstat); 399e9be9d5eSMiklos Szeredi } 400e9be9d5eSMiklos Szeredi out_unlock: 401e9be9d5eSMiklos Szeredi unlock_rename(workdir, upperdir); 402e9be9d5eSMiklos Szeredi revert_creds(old_cred); 403e9be9d5eSMiklos Szeredi put_cred(override_cred); 404e9be9d5eSMiklos Szeredi 405e9be9d5eSMiklos Szeredi out_free_link: 406e9be9d5eSMiklos Szeredi if (link) 407e9be9d5eSMiklos Szeredi free_page((unsigned long) link); 408e9be9d5eSMiklos Szeredi 409e9be9d5eSMiklos Szeredi return err; 410e9be9d5eSMiklos Szeredi } 411e9be9d5eSMiklos Szeredi 412e9be9d5eSMiklos Szeredi int ovl_copy_up(struct dentry *dentry) 413e9be9d5eSMiklos Szeredi { 414e9be9d5eSMiklos Szeredi int err; 415e9be9d5eSMiklos Szeredi 416e9be9d5eSMiklos Szeredi err = 0; 417e9be9d5eSMiklos Szeredi while (!err) { 418e9be9d5eSMiklos Szeredi struct dentry *next; 419e9be9d5eSMiklos Szeredi struct dentry *parent; 420e9be9d5eSMiklos Szeredi struct path lowerpath; 421e9be9d5eSMiklos Szeredi struct kstat stat; 422e9be9d5eSMiklos Szeredi enum ovl_path_type type = ovl_path_type(dentry); 423e9be9d5eSMiklos Szeredi 4241afaba1eSMiklos Szeredi if (OVL_TYPE_UPPER(type)) 425e9be9d5eSMiklos Szeredi break; 426e9be9d5eSMiklos Szeredi 427e9be9d5eSMiklos Szeredi next = dget(dentry); 428e9be9d5eSMiklos Szeredi /* find the topmost dentry not yet copied up */ 429e9be9d5eSMiklos Szeredi for (;;) { 430e9be9d5eSMiklos Szeredi parent = dget_parent(next); 431e9be9d5eSMiklos Szeredi 432e9be9d5eSMiklos Szeredi type = ovl_path_type(parent); 4331afaba1eSMiklos Szeredi if (OVL_TYPE_UPPER(type)) 434e9be9d5eSMiklos Szeredi break; 435e9be9d5eSMiklos Szeredi 436e9be9d5eSMiklos Szeredi dput(next); 437e9be9d5eSMiklos Szeredi next = parent; 438e9be9d5eSMiklos Szeredi } 439e9be9d5eSMiklos Szeredi 440e9be9d5eSMiklos Szeredi ovl_path_lower(next, &lowerpath); 441e9be9d5eSMiklos Szeredi err = vfs_getattr(&lowerpath, &stat); 442e9be9d5eSMiklos Szeredi if (!err) 4430f7ff2daSAl Viro err = ovl_copy_up_one(parent, next, &lowerpath, &stat); 444e9be9d5eSMiklos Szeredi 445e9be9d5eSMiklos Szeredi dput(parent); 446e9be9d5eSMiklos Szeredi dput(next); 447e9be9d5eSMiklos Szeredi } 448e9be9d5eSMiklos Szeredi 449e9be9d5eSMiklos Szeredi return err; 450e9be9d5eSMiklos Szeredi } 451