Skip to content

Commit

Permalink
Merge branch 'generic-string-functions'
Browse files Browse the repository at this point in the history
This makes <asm/word-at-a-time.h> actually live up to its promise of
allowing architectures to help tune the string functions that do their
work a word at a time.

David had already taken the x86 strncpy_from_user() function, modified
it to work on sparc, and then done the extra work to make it generically
useful.  This then expands on that work by making x86 use that generic
version, completing the circle.

But more importantly, it fixes up the word-at-a-time interfaces so that
it's now easy to also support things like strnlen_user(), and pretty
much most random string functions.

David reports that it all works fine on sparc, and Jonas Bonn reported
that an earlier version of this worked on OpenRISC too.  It's pretty
easy for architectures to add support for this and just replace their
private versions with the generic code.

* generic-string-functions:
  sparc: use the new generic strnlen_user() function
  x86: use the new generic strnlen_user() function
  lib: add generic strnlen_user() function
  word-at-a-time: make the interfaces truly generic
  x86: use generic strncpy_from_user routine
  • Loading branch information
torvalds committed May 26, 2012
2 parents ae32adc + 2c66f62 commit 1e2aec8
Show file tree
Hide file tree
Showing 23 changed files with 259 additions and 490 deletions.
1 change: 1 addition & 0 deletions arch/openrisc/include/asm/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ generic-y += topology.h
generic-y += types.h
generic-y += ucontext.h
generic-y += user.h
generic-y += word-at-a-time.h
1 change: 1 addition & 0 deletions arch/sparc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ config SPARC
select GENERIC_CMOS_UPDATE
select GENERIC_CLOCKEVENTS
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER

config SPARC32
def_bool !64BIT
Expand Down
1 change: 1 addition & 0 deletions arch/sparc/include/asm/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ generic-y += div64.h
generic-y += local64.h
generic-y += irq_regs.h
generic-y += local.h
generic-y += word-at-a-time.h
22 changes: 4 additions & 18 deletions arch/sparc/include/asm/uaccess_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#ifndef __ASSEMBLY__

#include <asm/processor.h>

#define ARCH_HAS_SORT_EXTABLE
#define ARCH_HAS_SEARCH_EXTABLE

Expand Down Expand Up @@ -304,24 +306,8 @@ static inline unsigned long clear_user(void __user *addr, unsigned long n)
return n;
}

extern long __strlen_user(const char __user *);
extern long __strnlen_user(const char __user *, long len);

static inline long strlen_user(const char __user *str)
{
if (!access_ok(VERIFY_READ, str, 0))
return 0;
else
return __strlen_user(str);
}

static inline long strnlen_user(const char __user *str, long len)
{
if (!access_ok(VERIFY_READ, str, 0))
return 0;
else
return __strnlen_user(str, len);
}
extern __must_check long strlen_user(const char __user *str);
extern __must_check long strnlen_user(const char __user *str, long n);

#endif /* __ASSEMBLY__ */

Expand Down
8 changes: 4 additions & 4 deletions arch/sparc/include/asm/uaccess_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

#ifndef __ASSEMBLY__

#include <asm/processor.h>

/*
* Sparc64 is segmented, though more like the M68K than the I386.
* We use the secondary ASI to address user memory, which references a
Expand Down Expand Up @@ -257,11 +259,9 @@ extern unsigned long __must_check __clear_user(void __user *, unsigned long);

#define clear_user __clear_user

extern long __strlen_user(const char __user *);
extern long __strnlen_user(const char __user *, long len);
extern __must_check long strlen_user(const char __user *str);
extern __must_check long strnlen_user(const char __user *str, long n);

#define strlen_user __strlen_user
#define strnlen_user __strnlen_user
#define __copy_to_user_inatomic ___copy_to_user
#define __copy_from_user_inatomic ___copy_from_user

Expand Down
1 change: 0 additions & 1 deletion arch/sparc/lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ lib-y += strlen.o
lib-y += checksum_$(BITS).o
lib-$(CONFIG_SPARC32) += blockops.o
lib-y += memscan_$(BITS).o memcmp.o strncmp_$(BITS).o
lib-y += strlen_user_$(BITS).o
lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o
lib-$(CONFIG_SPARC32) += copy_user.o locks.o
lib-$(CONFIG_SPARC64) += atomic_64.o
Expand Down
2 changes: 0 additions & 2 deletions arch/sparc/lib/ksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

/* string functions */
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(__strlen_user);
EXPORT_SYMBOL(__strnlen_user);
EXPORT_SYMBOL(strncmp);

/* mem* functions */
Expand Down
109 changes: 0 additions & 109 deletions arch/sparc/lib/strlen_user_32.S

This file was deleted.

97 changes: 0 additions & 97 deletions arch/sparc/lib/strlen_user_64.S

This file was deleted.

2 changes: 2 additions & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ config X86
select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
select GENERIC_TIME_VSYSCALL if X86_64
select KTIME_SCALAR if X86_32
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER

config INSTRUCTION_DECODER
def_bool (KPROBES || PERF_EVENTS || UPROBES)
Expand Down
4 changes: 4 additions & 0 deletions arch/x86/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#define segment_eq(a, b) ((a).seg == (b).seg)

#define user_addr_max() (current_thread_info()->addr_limit.seg)
#define __addr_ok(addr) \
((unsigned long __force)(addr) < \
(current_thread_info()->addr_limit.seg))
Expand Down Expand Up @@ -565,6 +566,9 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n);
extern __must_check long
strncpy_from_user(char *dst, const char __user *src, long count);

extern __must_check long strlen_user(const char __user *str);
extern __must_check long strnlen_user(const char __user *str, long n);

/*
* movsl can be slow when source and dest are not both 8-byte aligned
*/
Expand Down
17 changes: 0 additions & 17 deletions arch/x86/include/asm/uaccess_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,23 +213,6 @@ static inline unsigned long __must_check copy_from_user(void *to,
return n;
}

/**
* strlen_user: - Get the size of a string in user space.
* @str: The string to measure.
*
* Context: User context only. This function may sleep.
*
* Get the size of a NUL-terminated string in user space.
*
* Returns the size of the string INCLUDING the terminating NUL.
* On exception, returns 0.
*
* If there is a limit on the length of a valid string, you may wish to
* consider using strnlen_user() instead.
*/
#define strlen_user(str) strnlen_user(str, LONG_MAX)

long strnlen_user(const char __user *str, long n);
unsigned long __must_check clear_user(void __user *mem, unsigned long len);
unsigned long __must_check __clear_user(void __user *mem, unsigned long len);

Expand Down
3 changes: 0 additions & 3 deletions arch/x86/include/asm/uaccess_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,6 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
}
}

__must_check long strnlen_user(const char __user *str, long n);
__must_check long __strnlen_user(const char __user *str, long n);
__must_check long strlen_user(const char __user *str);
__must_check unsigned long clear_user(void __user *mem, unsigned long len);
__must_check unsigned long __clear_user(void __user *mem, unsigned long len);

Expand Down
Loading

0 comments on commit 1e2aec8

Please sign in to comment.