1bbb1e54dSMiklos Szeredi /* 2bbb1e54dSMiklos Szeredi * Copyright (C) 2011 Novell Inc. 3bbb1e54dSMiklos Szeredi * Copyright (C) 2016 Red Hat, Inc. 4bbb1e54dSMiklos Szeredi * 5bbb1e54dSMiklos Szeredi * This program is free software; you can redistribute it and/or modify it 6bbb1e54dSMiklos Szeredi * under the terms of the GNU General Public License version 2 as published by 7bbb1e54dSMiklos Szeredi * the Free Software Foundation. 8bbb1e54dSMiklos Szeredi */ 9bbb1e54dSMiklos Szeredi 10bbb1e54dSMiklos Szeredi #include <linux/fs.h> 11bbb1e54dSMiklos Szeredi #include <linux/namei.h> 12bbb1e54dSMiklos Szeredi #include <linux/xattr.h> 13bbb1e54dSMiklos Szeredi #include "overlayfs.h" 14bbb1e54dSMiklos Szeredi #include "ovl_entry.h" 15bbb1e54dSMiklos Szeredi 16bbb1e54dSMiklos Szeredi static struct dentry *ovl_lookup_real(struct dentry *dir, 17bbb1e54dSMiklos Szeredi const struct qstr *name) 18bbb1e54dSMiklos Szeredi { 19bbb1e54dSMiklos Szeredi struct dentry *dentry; 20bbb1e54dSMiklos Szeredi 21bbb1e54dSMiklos Szeredi dentry = lookup_one_len_unlocked(name->name, dir, name->len); 22bbb1e54dSMiklos Szeredi if (IS_ERR(dentry)) { 23bbb1e54dSMiklos Szeredi if (PTR_ERR(dentry) == -ENOENT) 24bbb1e54dSMiklos Szeredi dentry = NULL; 25bbb1e54dSMiklos Szeredi } else if (!dentry->d_inode) { 26bbb1e54dSMiklos Szeredi dput(dentry); 27bbb1e54dSMiklos Szeredi dentry = NULL; 28bbb1e54dSMiklos Szeredi } else if (ovl_dentry_weird(dentry)) { 29bbb1e54dSMiklos Szeredi dput(dentry); 30bbb1e54dSMiklos Szeredi /* Don't support traversing automounts and other weirdness */ 31bbb1e54dSMiklos Szeredi dentry = ERR_PTR(-EREMOTE); 32bbb1e54dSMiklos Szeredi } 33bbb1e54dSMiklos Szeredi return dentry; 34bbb1e54dSMiklos Szeredi } 35bbb1e54dSMiklos Szeredi 36bbb1e54dSMiklos Szeredi static bool ovl_is_opaquedir(struct dentry *dentry) 37bbb1e54dSMiklos Szeredi { 38bbb1e54dSMiklos Szeredi int res; 39bbb1e54dSMiklos Szeredi char val; 40bbb1e54dSMiklos Szeredi 41bbb1e54dSMiklos Szeredi if (!d_is_dir(dentry)) 42bbb1e54dSMiklos Szeredi return false; 43bbb1e54dSMiklos Szeredi 44bbb1e54dSMiklos Szeredi res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1); 45bbb1e54dSMiklos Szeredi if (res == 1 && val == 'y') 46bbb1e54dSMiklos Szeredi return true; 47bbb1e54dSMiklos Szeredi 48bbb1e54dSMiklos Szeredi return false; 49bbb1e54dSMiklos Szeredi } 50bbb1e54dSMiklos Szeredi 51bbb1e54dSMiklos Szeredi /* 52bbb1e54dSMiklos Szeredi * Returns next layer in stack starting from top. 53bbb1e54dSMiklos Szeredi * Returns -1 if this is the last layer. 54bbb1e54dSMiklos Szeredi */ 55bbb1e54dSMiklos Szeredi int ovl_path_next(int idx, struct dentry *dentry, struct path *path) 56bbb1e54dSMiklos Szeredi { 57bbb1e54dSMiklos Szeredi struct ovl_entry *oe = dentry->d_fsdata; 58bbb1e54dSMiklos Szeredi 59bbb1e54dSMiklos Szeredi BUG_ON(idx < 0); 60bbb1e54dSMiklos Szeredi if (idx == 0) { 61bbb1e54dSMiklos Szeredi ovl_path_upper(dentry, path); 62bbb1e54dSMiklos Szeredi if (path->dentry) 63bbb1e54dSMiklos Szeredi return oe->numlower ? 1 : -1; 64bbb1e54dSMiklos Szeredi idx++; 65bbb1e54dSMiklos Szeredi } 66bbb1e54dSMiklos Szeredi BUG_ON(idx > oe->numlower); 67bbb1e54dSMiklos Szeredi *path = oe->lowerstack[idx - 1]; 68bbb1e54dSMiklos Szeredi 69bbb1e54dSMiklos Szeredi return (idx < oe->numlower) ? idx + 1 : -1; 70bbb1e54dSMiklos Szeredi } 71bbb1e54dSMiklos Szeredi 72bbb1e54dSMiklos Szeredi struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, 73bbb1e54dSMiklos Szeredi unsigned int flags) 74bbb1e54dSMiklos Szeredi { 75bbb1e54dSMiklos Szeredi struct ovl_entry *oe; 76bbb1e54dSMiklos Szeredi const struct cred *old_cred; 77bbb1e54dSMiklos Szeredi struct ovl_entry *poe = dentry->d_parent->d_fsdata; 78bbb1e54dSMiklos Szeredi struct path *stack = NULL; 79bbb1e54dSMiklos Szeredi struct dentry *upperdir, *upperdentry = NULL; 80bbb1e54dSMiklos Szeredi unsigned int ctr = 0; 81bbb1e54dSMiklos Szeredi struct inode *inode = NULL; 82bbb1e54dSMiklos Szeredi bool upperopaque = false; 83bbb1e54dSMiklos Szeredi bool stop = false; 84bbb1e54dSMiklos Szeredi bool isdir = false; 85bbb1e54dSMiklos Szeredi struct dentry *this; 86bbb1e54dSMiklos Szeredi unsigned int i; 87bbb1e54dSMiklos Szeredi int err; 88bbb1e54dSMiklos Szeredi 89bbb1e54dSMiklos Szeredi old_cred = ovl_override_creds(dentry->d_sb); 90bbb1e54dSMiklos Szeredi upperdir = ovl_upperdentry_dereference(poe); 91bbb1e54dSMiklos Szeredi if (upperdir) { 92bbb1e54dSMiklos Szeredi this = ovl_lookup_real(upperdir, &dentry->d_name); 93bbb1e54dSMiklos Szeredi err = PTR_ERR(this); 94bbb1e54dSMiklos Szeredi if (IS_ERR(this)) 95bbb1e54dSMiklos Szeredi goto out; 96bbb1e54dSMiklos Szeredi 97bbb1e54dSMiklos Szeredi if (this) { 98bbb1e54dSMiklos Szeredi if (unlikely(ovl_dentry_remote(this))) { 99bbb1e54dSMiklos Szeredi dput(this); 100bbb1e54dSMiklos Szeredi err = -EREMOTE; 101bbb1e54dSMiklos Szeredi goto out; 102bbb1e54dSMiklos Szeredi } 103bbb1e54dSMiklos Szeredi if (ovl_is_whiteout(this)) { 104bbb1e54dSMiklos Szeredi dput(this); 105bbb1e54dSMiklos Szeredi this = NULL; 106bbb1e54dSMiklos Szeredi stop = upperopaque = true; 107bbb1e54dSMiklos Szeredi } else if (!d_is_dir(this)) { 108bbb1e54dSMiklos Szeredi stop = true; 109bbb1e54dSMiklos Szeredi } else { 110bbb1e54dSMiklos Szeredi isdir = true; 111bbb1e54dSMiklos Szeredi if (poe->numlower && ovl_is_opaquedir(this)) 112bbb1e54dSMiklos Szeredi stop = upperopaque = true; 113bbb1e54dSMiklos Szeredi } 114bbb1e54dSMiklos Szeredi } 115bbb1e54dSMiklos Szeredi upperdentry = this; 116bbb1e54dSMiklos Szeredi } 117bbb1e54dSMiklos Szeredi 118bbb1e54dSMiklos Szeredi if (!stop && poe->numlower) { 119bbb1e54dSMiklos Szeredi err = -ENOMEM; 120bbb1e54dSMiklos Szeredi stack = kcalloc(poe->numlower, sizeof(struct path), GFP_KERNEL); 121bbb1e54dSMiklos Szeredi if (!stack) 122bbb1e54dSMiklos Szeredi goto out_put_upper; 123bbb1e54dSMiklos Szeredi } 124bbb1e54dSMiklos Szeredi 125bbb1e54dSMiklos Szeredi for (i = 0; !stop && i < poe->numlower; i++) { 126bbb1e54dSMiklos Szeredi struct path lowerpath = poe->lowerstack[i]; 127bbb1e54dSMiklos Szeredi 128bbb1e54dSMiklos Szeredi this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name); 129bbb1e54dSMiklos Szeredi err = PTR_ERR(this); 130bbb1e54dSMiklos Szeredi if (IS_ERR(this)) { 131bbb1e54dSMiklos Szeredi /* 132bbb1e54dSMiklos Szeredi * If it's positive, then treat ENAMETOOLONG as ENOENT. 133bbb1e54dSMiklos Szeredi */ 134bbb1e54dSMiklos Szeredi if (err == -ENAMETOOLONG && (upperdentry || ctr)) 135bbb1e54dSMiklos Szeredi continue; 136bbb1e54dSMiklos Szeredi goto out_put; 137bbb1e54dSMiklos Szeredi } 138bbb1e54dSMiklos Szeredi if (!this) 139bbb1e54dSMiklos Szeredi continue; 140bbb1e54dSMiklos Szeredi if (ovl_is_whiteout(this)) { 141bbb1e54dSMiklos Szeredi dput(this); 142bbb1e54dSMiklos Szeredi break; 143bbb1e54dSMiklos Szeredi } 144bbb1e54dSMiklos Szeredi /* 145bbb1e54dSMiklos Szeredi * If this is a non-directory then stop here. 146bbb1e54dSMiklos Szeredi */ 147bbb1e54dSMiklos Szeredi if (!d_is_dir(this)) { 148bbb1e54dSMiklos Szeredi if (isdir) { 149bbb1e54dSMiklos Szeredi dput(this); 150bbb1e54dSMiklos Szeredi break; 151bbb1e54dSMiklos Szeredi } 152bbb1e54dSMiklos Szeredi stop = true; 153bbb1e54dSMiklos Szeredi } else { 154bbb1e54dSMiklos Szeredi /* 155bbb1e54dSMiklos Szeredi * Only makes sense to check opaque dir if this is not 156bbb1e54dSMiklos Szeredi * the lowermost layer. 157bbb1e54dSMiklos Szeredi */ 158bbb1e54dSMiklos Szeredi if (i < poe->numlower - 1 && ovl_is_opaquedir(this)) 159bbb1e54dSMiklos Szeredi stop = true; 160bbb1e54dSMiklos Szeredi } 161bbb1e54dSMiklos Szeredi 162bbb1e54dSMiklos Szeredi stack[ctr].dentry = this; 163bbb1e54dSMiklos Szeredi stack[ctr].mnt = lowerpath.mnt; 164bbb1e54dSMiklos Szeredi ctr++; 165bbb1e54dSMiklos Szeredi } 166bbb1e54dSMiklos Szeredi 167bbb1e54dSMiklos Szeredi oe = ovl_alloc_entry(ctr); 168bbb1e54dSMiklos Szeredi err = -ENOMEM; 169bbb1e54dSMiklos Szeredi if (!oe) 170bbb1e54dSMiklos Szeredi goto out_put; 171bbb1e54dSMiklos Szeredi 172bbb1e54dSMiklos Szeredi if (upperdentry || ctr) { 173bbb1e54dSMiklos Szeredi struct dentry *realdentry; 174bbb1e54dSMiklos Szeredi struct inode *realinode; 175bbb1e54dSMiklos Szeredi 176bbb1e54dSMiklos Szeredi realdentry = upperdentry ? upperdentry : stack[0].dentry; 177bbb1e54dSMiklos Szeredi realinode = d_inode(realdentry); 178bbb1e54dSMiklos Szeredi 179bbb1e54dSMiklos Szeredi err = -ENOMEM; 180bbb1e54dSMiklos Szeredi if (upperdentry && !d_is_dir(upperdentry)) { 181bbb1e54dSMiklos Szeredi inode = ovl_get_inode(dentry->d_sb, realinode); 182bbb1e54dSMiklos Szeredi } else { 183bbb1e54dSMiklos Szeredi inode = ovl_new_inode(dentry->d_sb, realinode->i_mode, 184bbb1e54dSMiklos Szeredi realinode->i_rdev); 185bbb1e54dSMiklos Szeredi if (inode) 186bbb1e54dSMiklos Szeredi ovl_inode_init(inode, realinode, !!upperdentry); 187bbb1e54dSMiklos Szeredi } 188bbb1e54dSMiklos Szeredi if (!inode) 189bbb1e54dSMiklos Szeredi goto out_free_oe; 190bbb1e54dSMiklos Szeredi ovl_copyattr(realdentry->d_inode, inode); 191bbb1e54dSMiklos Szeredi } 192bbb1e54dSMiklos Szeredi 193bbb1e54dSMiklos Szeredi revert_creds(old_cred); 194bbb1e54dSMiklos Szeredi oe->opaque = upperopaque; 195bbb1e54dSMiklos Szeredi oe->__upperdentry = upperdentry; 196bbb1e54dSMiklos Szeredi memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); 197bbb1e54dSMiklos Szeredi kfree(stack); 198bbb1e54dSMiklos Szeredi dentry->d_fsdata = oe; 199bbb1e54dSMiklos Szeredi d_add(dentry, inode); 200bbb1e54dSMiklos Szeredi 201bbb1e54dSMiklos Szeredi return NULL; 202bbb1e54dSMiklos Szeredi 203bbb1e54dSMiklos Szeredi out_free_oe: 204bbb1e54dSMiklos Szeredi kfree(oe); 205bbb1e54dSMiklos Szeredi out_put: 206bbb1e54dSMiklos Szeredi for (i = 0; i < ctr; i++) 207bbb1e54dSMiklos Szeredi dput(stack[i].dentry); 208bbb1e54dSMiklos Szeredi kfree(stack); 209bbb1e54dSMiklos Szeredi out_put_upper: 210bbb1e54dSMiklos Szeredi dput(upperdentry); 211bbb1e54dSMiklos Szeredi out: 212bbb1e54dSMiklos Szeredi revert_creds(old_cred); 213bbb1e54dSMiklos Szeredi return ERR_PTR(err); 214bbb1e54dSMiklos Szeredi } 215bbb1e54dSMiklos Szeredi 216bbb1e54dSMiklos Szeredi bool ovl_lower_positive(struct dentry *dentry) 217bbb1e54dSMiklos Szeredi { 218bbb1e54dSMiklos Szeredi struct ovl_entry *oe = dentry->d_fsdata; 219bbb1e54dSMiklos Szeredi struct ovl_entry *poe = dentry->d_parent->d_fsdata; 220bbb1e54dSMiklos Szeredi const struct qstr *name = &dentry->d_name; 221bbb1e54dSMiklos Szeredi unsigned int i; 222bbb1e54dSMiklos Szeredi bool positive = false; 223bbb1e54dSMiklos Szeredi bool done = false; 224bbb1e54dSMiklos Szeredi 225bbb1e54dSMiklos Szeredi /* 226bbb1e54dSMiklos Szeredi * If dentry is negative, then lower is positive iff this is a 227bbb1e54dSMiklos Szeredi * whiteout. 228bbb1e54dSMiklos Szeredi */ 229bbb1e54dSMiklos Szeredi if (!dentry->d_inode) 230bbb1e54dSMiklos Szeredi return oe->opaque; 231bbb1e54dSMiklos Szeredi 232bbb1e54dSMiklos Szeredi /* Negative upper -> positive lower */ 233bbb1e54dSMiklos Szeredi if (!oe->__upperdentry) 234bbb1e54dSMiklos Szeredi return true; 235bbb1e54dSMiklos Szeredi 236bbb1e54dSMiklos Szeredi /* Positive upper -> have to look up lower to see whether it exists */ 237bbb1e54dSMiklos Szeredi for (i = 0; !done && !positive && i < poe->numlower; i++) { 238bbb1e54dSMiklos Szeredi struct dentry *this; 239bbb1e54dSMiklos Szeredi struct dentry *lowerdir = poe->lowerstack[i].dentry; 240bbb1e54dSMiklos Szeredi 241bbb1e54dSMiklos Szeredi this = lookup_one_len_unlocked(name->name, lowerdir, 242bbb1e54dSMiklos Szeredi name->len); 243bbb1e54dSMiklos Szeredi if (IS_ERR(this)) { 244bbb1e54dSMiklos Szeredi switch (PTR_ERR(this)) { 245bbb1e54dSMiklos Szeredi case -ENOENT: 246bbb1e54dSMiklos Szeredi case -ENAMETOOLONG: 247bbb1e54dSMiklos Szeredi break; 248bbb1e54dSMiklos Szeredi 249bbb1e54dSMiklos Szeredi default: 250bbb1e54dSMiklos Szeredi /* 251bbb1e54dSMiklos Szeredi * Assume something is there, we just couldn't 252bbb1e54dSMiklos Szeredi * access it. 253bbb1e54dSMiklos Szeredi */ 254bbb1e54dSMiklos Szeredi positive = true; 255bbb1e54dSMiklos Szeredi break; 256bbb1e54dSMiklos Szeredi } 257bbb1e54dSMiklos Szeredi } else { 258bbb1e54dSMiklos Szeredi if (this->d_inode) { 259bbb1e54dSMiklos Szeredi positive = !ovl_is_whiteout(this); 260bbb1e54dSMiklos Szeredi done = true; 261bbb1e54dSMiklos Szeredi } 262bbb1e54dSMiklos Szeredi dput(this); 263bbb1e54dSMiklos Szeredi } 264bbb1e54dSMiklos Szeredi } 265bbb1e54dSMiklos Szeredi 266bbb1e54dSMiklos Szeredi return positive; 267bbb1e54dSMiklos Szeredi } 268