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