lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220508100630.2642320-1-keescook@chromium.org>
Date:   Sun,  8 May 2022 03:06:30 -0700
From:   Kees Cook <keescook@...omium.org>
To:     Bob Peterson <rpeterso@...hat.com>
Cc:     Kees Cook <keescook@...omium.org>,
        kernel test robot <lkp@...el.com>,
        Andreas Gruenbacher <agruenba@...hat.com>,
        Bill Wendling <morbo@...gle.com>, cluster-devel@...hat.com,
        Nathan Chancellor <nathan@...nel.org>,
        Nick Desaulniers <ndesaulniers@...gle.com>,
        Tom Rix <trix@...hat.com>,
        Steven Whitehouse <swhiteho@...hat.com>,
        linux-kernel@...r.kernel.org
Subject: [PATCH] gfs2: Use container_of() for gfs2_glock(aspace)

Clang's structure layout randomization feature gets upset when it sees
struct address_space (which is randomized) cast to struct gfs2_glock.
This is due to seeing the mapping pointer as being treated as an array
of gfs2_glock, rather than "something else, before struct address_space":

In file included from fs/gfs2/acl.c:23:
fs/gfs2/meta_io.h:44:12: error: casting from randomized structure pointer type 'struct address_space *' to 'struct gfs2_glock *'
	return (((struct gfs2_glock *)mapping) - 1)->gl_name.ln_sbd;
		^

Replace the instances of open-coded pointer math with container_of()
usage, and update the allocator to match.

Reported-by: kernel test robot <lkp@...el.com>
Link: https://lore.kernel.org/lkml/202205041550.naKxwCBj-lkp@intel.com
Cc: Bob Peterson <rpeterso@...hat.com>
Cc: Andreas Gruenbacher <agruenba@...hat.com>
Cc: Bill Wendling <morbo@...gle.com>
Cc: cluster-devel@...hat.com
Signed-off-by: Kees Cook <keescook@...omium.org>
---
This another fix uncovered by the Clang randstruct series[1], so it'd
probably make more sense to land via my tree. Do you have a preference?
[1] https://lore.kernel.org/all/20220503205503.3054173-1-keescook@chromium.org/
---
 fs/gfs2/glock.h   |  8 +++++++-
 fs/gfs2/main.c    | 10 ++++------
 fs/gfs2/meta_io.h |  2 +-
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 4f8642301801..2607c7d26640 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -138,6 +138,12 @@ struct lm_lockops {
 	const match_table_t *lm_tokens;
 };
 
+/* gfs2_glock_get(), "glock" must be first. */
+struct glock_aspace {
+	struct gfs2_glock	glock;
+	struct address_space	mapping;
+};
+
 extern struct workqueue_struct *gfs2_delete_workqueue;
 static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
 {
@@ -180,7 +186,7 @@ static inline int gfs2_glock_is_held_shrd(struct gfs2_glock *gl)
 static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
 {
 	if (gl->gl_ops->go_flags & GLOF_ASPACE)
-		return (struct address_space *)(gl + 1);
+		return &(container_of(gl, struct glock_aspace, glock)->mapping);
 	return NULL;
 }
 
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 28d0eb23e18e..984bd60d01db 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -62,11 +62,10 @@ static void gfs2_init_glock_once(void *foo)
 
 static void gfs2_init_gl_aspace_once(void *foo)
 {
-	struct gfs2_glock *gl = foo;
-	struct address_space *mapping = (struct address_space *)(gl + 1);
+	struct glock_aspace *gl_aspace = foo;
 
-	gfs2_init_glock_once(gl);
-	address_space_init_once(mapping);
+	gfs2_init_glock_once(&gl_aspace->glock);
+	address_space_init_once(&gl_aspace->mapping);
 }
 
 /**
@@ -104,8 +103,7 @@ static int __init init_gfs2_fs(void)
 		goto fail_cachep1;
 
 	gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock(aspace)",
-					sizeof(struct gfs2_glock) +
-					sizeof(struct address_space),
+					sizeof(struct glock_aspace),
 					0, 0, gfs2_init_gl_aspace_once);
 
 	if (!gfs2_glock_aspace_cachep)
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index 21880d72081a..2e2f88cfb7ad 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -41,7 +41,7 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
 {
 	struct inode *inode = mapping->host;
 	if (mapping->a_ops == &gfs2_meta_aops)
-		return (((struct gfs2_glock *)mapping) - 1)->gl_name.ln_sbd;
+		return container_of(mapping, struct glock_aspace, mapping)->glock.gl_name.ln_sbd;
 	else if (mapping->a_ops == &gfs2_rgrp_aops)
 		return container_of(mapping, struct gfs2_sbd, sd_aspace);
 	else
-- 
2.32.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ