static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
                            struct dentry **ret)
 {
-       const char *s = d->name.name;
+       /* Counting down from the end, since the prefix can change */
+       size_t rem = d->name.len - 1;
        struct dentry *dentry = NULL;
        int err;
 
-       if (*s != '/')
+       if (d->name.name[0] != '/')
                return ovl_lookup_single(base, d, d->name.name, d->name.len,
                                         0, "", ret);
 
-       while (*s++ == '/' && !IS_ERR_OR_NULL(base) && d_can_lookup(base)) {
+       while (!IS_ERR_OR_NULL(base) && d_can_lookup(base)) {
+               const char *s = d->name.name + d->name.len - rem;
                const char *next = strchrnul(s, '/');
-               size_t slen = strlen(s);
+               size_t thislen = next - s;
+               bool end = !next[0];
 
-               if (WARN_ON(slen > d->name.len) ||
-                   WARN_ON(strcmp(d->name.name + d->name.len - slen, s)))
+               /* Verify we did not go off the rails */
+               if (WARN_ON(s[-1] != '/'))
                        return -EIO;
 
-               err = ovl_lookup_single(base, d, s, next - s,
-                                       d->name.len - slen, next, &base);
+               err = ovl_lookup_single(base, d, s, thislen,
+                                       d->name.len - rem, next, &base);
                dput(dentry);
                if (err)
                        return err;
                dentry = base;
-               s = next;
+               if (end)
+                       break;
+
+               rem -= thislen + 1;
+
+               if (WARN_ON(rem >= d->name.len))
+                       return -EIO;
        }
        *ret = dentry;
        return 0;