mnt_idmapping: return false when comparing two invalid ids
authorSeth Forshee <sforshee@digitalocean.com>
Mon, 27 Jun 2022 13:01:58 +0000 (08:01 -0500)
committerChristian Brauner (Microsoft) <brauner@kernel.org>
Mon, 27 Jun 2022 14:09:56 +0000 (16:09 +0200)
INVALID_VFS{U,G}ID represent ids which have no mapping in the target
mnt_usersns. This can happen for a couple of different reasons -- the
source id might be valid but has no mapping in mnt_userns, or the source
id might have been invalid (either due to a failed mapping or because it
was set to invalid to indicate it is uninitialized).

This means that two arbitrary vfs{u,g}ids which are both invalid could
represent two different underlying ids, or they could represent a failed
mapping and an uninitialized value. In these situation the vfs{u,g}id
equality functions evaluate these ids as equal, and care must be taken
when comparing ids to avoid problems. It would be less error prone to
always evaluate two invalid ids as not equal to each other, and to check
explicitly for vfs{u,g}id validity when that is needed.

Change all vfs{u,g}id equality functions to return false when both ids
are invalid. Functions for checking whether an id is valid exist and are
already being used by code which needs to check this.

Link: https://lore.kernel.org/linux-fsdevel/YrIMZirGoE0VIO45@do-x1extreme
Signed-off-by: Seth Forshee <sforshee@digitalocean.com>
Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
include/linux/mnt_idmapping.h

index 6a752b6..21bd22a 100644 (file)
@@ -60,12 +60,12 @@ static inline bool vfsgid_valid(vfsgid_t gid)
 
 static inline bool vfsuid_eq(vfsuid_t left, vfsuid_t right)
 {
-       return __vfsuid_val(left) == __vfsuid_val(right);
+       return vfsuid_valid(left) && __vfsuid_val(left) == __vfsuid_val(right);
 }
 
 static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right)
 {
-       return __vfsgid_val(left) == __vfsgid_val(right);
+       return vfsgid_valid(left) && __vfsgid_val(left) == __vfsgid_val(right);
 }
 
 /**
@@ -76,10 +76,11 @@ static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right)
  * Check whether @kuid and @vfsuid have the same values.
  *
  * Return: true if @kuid and @vfsuid have the same value, false if not.
+ * Comparison between two invalid uids returns false.
  */
 static inline bool vfsuid_eq_kuid(vfsuid_t vfsuid, kuid_t kuid)
 {
-       return __vfsuid_val(vfsuid) == __kuid_val(kuid);
+       return vfsuid_valid(vfsuid) && __vfsuid_val(vfsuid) == __kuid_val(kuid);
 }
 
 /**
@@ -90,10 +91,11 @@ static inline bool vfsuid_eq_kuid(vfsuid_t vfsuid, kuid_t kuid)
  * Check whether @kgid and @vfsgid have the same values.
  *
  * Return: true if @kgid and @vfsgid have the same value, false if not.
+ * Comparison between two invalid gids returns false.
  */
 static inline bool vfsgid_eq_kgid(kgid_t kgid, vfsgid_t vfsgid)
 {
-       return __vfsgid_val(vfsgid) == __kgid_val(kgid);
+       return vfsgid_valid(vfsgid) && __vfsgid_val(vfsgid) == __kgid_val(kgid);
 }
 
 /*