Commit af4e9ef3 authored by David Laight's avatar David Laight Committed by Linus Torvalds
Browse files

uaccess: Fix scoped_user_read_access() for 'pointer to const'



If a 'const struct foo __user *ptr' is used for the address passed to
scoped_user_read_access() then you get a warning/error

  uaccess.h:691:1: error: initialization discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]

for the

  void __user *_tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl)

assignment.

Fix by using 'auto' for both _tmpptr and the redeclaration of uptr.
Replace the CLASS() with explicit __cleanup() functions on uptr.

Fixes: e497310b ("uaccess: Provide scoped user access regions")
Signed-off-by: default avatarDavid Laight <david.laight.linux@gmail.com>
Reviewed-and-tested-by: default avatarChristophe Leroy (CS GROUP) <chleroy@kernel.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1b37ac21
Loading
Loading
Loading
Loading
+20 −34
Original line number Diff line number Diff line
@@ -647,36 +647,22 @@ static inline void user_access_restore(unsigned long flags) { }
/* Define RW variant so the below _mode macro expansion works */
#define masked_user_rw_access_begin(u)	masked_user_access_begin(u)
#define user_rw_access_begin(u, s)	user_access_begin(u, s)
#define user_rw_access_end()		user_access_end()

/* Scoped user access */
#define USER_ACCESS_GUARD(_mode)				\
static __always_inline void __user *				\
class_user_##_mode##_begin(void __user *ptr)			\
{								\
	return ptr;						\
}								\
								\
static __always_inline void					\
class_user_##_mode##_end(void __user *ptr)			\
{								\
	user_##_mode##_access_end();				\
}								\
								\
DEFINE_CLASS(user_ ##_mode## _access, void __user *,		\
	     class_user_##_mode##_end(_T),			\
	     class_user_##_mode##_begin(ptr), void __user *ptr)	\
								\
static __always_inline class_user_##_mode##_access_t		\
class_user_##_mode##_access_ptr(void __user *scope)		\
{								\
	return scope;						\
}

USER_ACCESS_GUARD(read)
USER_ACCESS_GUARD(write)
USER_ACCESS_GUARD(rw)
#undef USER_ACCESS_GUARD
/* Cleanup wrapper functions */
static __always_inline void __scoped_user_read_access_end(const void *p)
{
	user_read_access_end();
};
static __always_inline void __scoped_user_write_access_end(const void *p)
{
	user_write_access_end();
};
static __always_inline void __scoped_user_rw_access_end(const void *p)
{
	user_access_end();
};

/**
 * __scoped_user_access_begin - Start a scoped user access
@@ -752,11 +738,11 @@ USER_ACCESS_GUARD(rw)
 */
#define __scoped_user_access(mode, uptr, size, elbl)				\
for (bool done = false; !done; done = true)					\
	for (void __user *_tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl); \
	for (auto _tmpptr = __scoped_user_access_begin(mode, uptr, size, elbl);	\
	     !done; done = true)						\
		for (CLASS(user_##mode##_access, scope)(_tmpptr); !done; done = true)	\
		/* Force modified pointer usage within the scope */		\
			for (const typeof(uptr) uptr = _tmpptr; !done; done = true)
		for (const auto uptr  __cleanup(__scoped_user_##mode##_access_end) = \
		     _tmpptr; !done; done = true)

/**
 * scoped_user_read_access_size - Start a scoped user read access with given size