nvmem: layouts: onie-tlv: Add new layout driver
[linux-2.6-microblaze.git] / fs / open.c
index 8038cf6..4401a73 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -368,7 +368,37 @@ COMPAT_SYSCALL_DEFINE6(fallocate, int, fd, int, mode, compat_arg_u64_dual(offset
  * access() needs to use the real uid/gid, not the effective uid/gid.
  * We do this by temporarily clearing all FS-related capabilities and
  * switching the fsuid/fsgid around to the real ones.
+ *
+ * Creating new credentials is expensive, so we try to skip doing it,
+ * which we can if the result would match what we already got.
  */
+static bool access_need_override_creds(int flags)
+{
+       const struct cred *cred;
+
+       if (flags & AT_EACCESS)
+               return false;
+
+       cred = current_cred();
+       if (!uid_eq(cred->fsuid, cred->uid) ||
+           !gid_eq(cred->fsgid, cred->gid))
+               return true;
+
+       if (!issecure(SECURE_NO_SETUID_FIXUP)) {
+               kuid_t root_uid = make_kuid(cred->user_ns, 0);
+               if (!uid_eq(cred->uid, root_uid)) {
+                       if (!cap_isclear(cred->cap_effective))
+                               return true;
+               } else {
+                       if (!cap_isidentical(cred->cap_effective,
+                           cred->cap_permitted))
+                               return true;
+               }
+       }
+
+       return false;
+}
+
 static const struct cred *access_override_creds(void)
 {
        const struct cred *old_cred;
@@ -378,6 +408,12 @@ static const struct cred *access_override_creds(void)
        if (!override_cred)
                return NULL;
 
+       /*
+        * XXX access_need_override_creds performs checks in hopes of skipping
+        * this work. Make sure it stays in sync if making any changes in this
+        * routine.
+        */
+
        override_cred->fsuid = override_cred->uid;
        override_cred->fsgid = override_cred->gid;
 
@@ -437,7 +473,7 @@ static long do_faccessat(int dfd, const char __user *filename, int mode, int fla
        if (flags & AT_EMPTY_PATH)
                lookup_flags |= LOOKUP_EMPTY;
 
-       if (!(flags & AT_EACCESS)) {
+       if (access_need_override_creds(flags)) {
                old_cred = access_override_creds();
                if (!old_cred)
                        return -ENOMEM;