From 9844813f226f6d07e1544e915529cb88f4fcb868 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 14 Jun 2009 02:00:02 -0400 Subject: [PATCH 1/7] asm-generic: uaccess: add missing access_ok() check to strnlen_user() The strnlen_user() function was missing a access_ok() check on the pointer given. We've had cases on Blackfin systems where test programs caused kernel crashes here because userspace passed up a NULL/-1 pointer and the kernel gladly attempted to run strlen() on it. Signed-off-by: Mike Frysinger Signed-off-by: Arnd Bergmann --- include/asm-generic/uaccess.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h index 6d8cab22e29..5dd511b62ce 100644 --- a/include/asm-generic/uaccess.h +++ b/include/asm-generic/uaccess.h @@ -291,6 +291,8 @@ strncpy_from_user(char *dst, const char __user *src, long count) #ifndef strnlen_user static inline long strnlen_user(const char __user *src, long n) { + if (!access_ok(VERIFY_READ, src, 1)) + return 0; return strlen((void * __force)src) + 1; } #endif From a9ede5b355aabd667ed690f858c925a23927027b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 14 Jun 2009 02:00:03 -0400 Subject: [PATCH 2/7] asm-generic: uaccess: fix up local access_ok() usage There's no reason that I can see to use the short __access_ok() form directly when the access_ok() is clearer in intent and for most people, expands to the same C code (i.e. always specify the first field -- access type). Not all no-mmu systems lack memory protection, so the read/write could feasibly be checked. Signed-off-by: Mike Frysinger Signed-off-by: Arnd Bergmann --- include/asm-generic/uaccess.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h index 5dd511b62ce..b218b8513d0 100644 --- a/include/asm-generic/uaccess.h +++ b/include/asm-generic/uaccess.h @@ -163,7 +163,7 @@ static inline __must_check long __copy_to_user(void __user *to, #define put_user(x, ptr) \ ({ \ might_sleep(); \ - __access_ok(ptr, sizeof (*ptr)) ? \ + access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)) ? \ __put_user(x, ptr) : \ -EFAULT; \ }) @@ -219,7 +219,7 @@ extern int __put_user_bad(void) __attribute__((noreturn)); #define get_user(x, ptr) \ ({ \ might_sleep(); \ - __access_ok(ptr, sizeof (*ptr)) ? \ + access_ok(VERIFY_READ, ptr, sizeof(*ptr)) ? \ __get_user(x, ptr) : \ -EFAULT; \ }) @@ -244,7 +244,7 @@ static inline long copy_from_user(void *to, const void __user * from, unsigned long n) { might_sleep(); - if (__access_ok(from, n)) + if (access_ok(VERIFY_READ, from, n)) return __copy_from_user(to, from, n); else return n; @@ -254,7 +254,7 @@ static inline long copy_to_user(void __user *to, const void *from, unsigned long n) { might_sleep(); - if (__access_ok(to, n)) + if (access_ok(VERIFY_WRITE, to, n)) return __copy_to_user(to, from, n); else return n; @@ -278,7 +278,7 @@ __strncpy_from_user(char *dst, const char __user *src, long count) static inline long strncpy_from_user(char *dst, const char __user *src, long count) { - if (!__access_ok(src, 1)) + if (!access_ok(VERIFY_READ, src, 1)) return -EFAULT; return __strncpy_from_user(dst, src, count); } @@ -318,7 +318,7 @@ static inline __must_check unsigned long clear_user(void __user *to, unsigned long n) { might_sleep(); - if (!__access_ok(to, n)) + if (!access_ok(VERIFY_WRITE, to, n)) return n; return __clear_user(to, n); From 804387a1af87f66a4b93eee230ba98f8b906b088 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 14 Jun 2009 22:38:11 +0200 Subject: [PATCH 3/7] asm-generic: drop HARDIRQ_BITS definition from hardirq.h Architechtures normally don't need to set a HARDIRQ_BITS unless they have hardcoded a specific value in assembly. This drops the definition from asm-generic/hardirq.h, which results in linux/hardirq.h setting its default of 10. Both the old default of 8 and the linux/hardirq.h default of 10 are sufficient because they only limit the number of nested hardirqs, and we normally run out of stack space much earlier than exceeding 256 or even 1024 nested interrupts. Reported-by: Mike Frysinger Acked-by: Steven Rostedt Signed-off-by: Arnd Bergmann --- include/asm-generic/hardirq.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/include/asm-generic/hardirq.h b/include/asm-generic/hardirq.h index 3d5d2c906ab..23bb4dad496 100644 --- a/include/asm-generic/hardirq.h +++ b/include/asm-generic/hardirq.h @@ -11,19 +11,6 @@ typedef struct { #include /* Standard mappings for irq_cpustat_t above */ -#ifndef HARDIRQ_BITS -#define HARDIRQ_BITS 8 -#endif - -/* - * The hardirq mask has to be large enough to have - * space for potentially all IRQ sources in the system - * nesting on a single CPU: - */ -#if (1 << HARDIRQ_BITS) < NR_IRQS -# error HARDIRQ_BITS is too low! -#endif - #ifndef ack_bad_irq static inline void ack_bad_irq(unsigned int irq) { From 1527aab617af87f2d2121fa3ff5aa79d96e7ad2f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 14 Jun 2009 22:46:16 +0200 Subject: [PATCH 4/7] asm-generic: list Arnd as asm-generic maintainer I've modified about half the code in include/asm-generic now, and people start sending me patches for it, so I should probably take the formal responsibility for it. Signed-off-by: Arnd Bergmann --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 035df9d2660..acf11052cb7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2453,6 +2453,14 @@ F: drivers/net/wan/pc300too.c F: drivers/net/wan/pci200syn.c F: drivers/net/wan/wanxl* +GENERIC INCLUDE/ASM HEADER FILES +P: Arnd Bergmann +M: arnd@arndb.de +L: linux-arch@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git +S: Maintained +F: include/asm-generic + GFS2 FILE SYSTEM P: Steven Whitehouse M: swhiteho@redhat.com From fcec9bf12442d0cd50d6cee125d168cfc3f37c5e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 19 Jun 2009 10:30:29 +0200 Subject: [PATCH 5/7] asm-generic: hook up new system calls sys_rt_tgsigqueueinfo and sys_perf_counter_open have been added in 2.6.31, so hook them up in the generic unistd.h file. Since the file is now in the mainline kernel, we are no longer reordering the numbers but just add system calls at the end. Signed-off-by: Arnd Bergmann --- include/asm-generic/unistd.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index 5b34b6233d6..1125e5a1ee5 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -618,8 +618,13 @@ __SYSCALL(__NR_migrate_pages, sys_migrate_pages) __SYSCALL(__NR_move_pages, sys_move_pages) #endif +#define __NR_rt_tgsigqueueinfo 240 +__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) +#define __NR_perf_counter_open 241 +__SYSCALL(__NR_perf_counter_open, sys_perf_counter_open) + #undef __NR_syscalls -#define __NR_syscalls 240 +#define __NR_syscalls 242 /* * All syscalls below here should go away really, From 32a9ff9cc55b42543a84bca90b070df92af72671 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 19 Jun 2009 10:41:19 +0200 Subject: [PATCH 6/7] lib/checksum.c: fix endianess bug The new generic checksum code has a small dependency on endianess and worked only on big-endian systems. I could not find a nice efficient way to express this, so I added an #ifdef. Using 'result += le16_to_cpu(*buff);' would have worked as well, but would be slightly less efficient on big-endian systems and IMHO would not be clearer. Also fix a bug that prevents this from working on 64-bit machines. If you have a 64-bit CPU and want to use the generic checksum code, you should probably do some more optimizations anyway, but at least the code should not break. Reported-by: Mike Frysinger Signed-off-by: Arnd Bergmann --- lib/checksum.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/checksum.c b/lib/checksum.c index 12e5a1c91cd..b2e2fd46846 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -55,7 +55,11 @@ static unsigned int do_csum(const unsigned char *buff, int len) goto out; odd = 1 & (unsigned long) buff; if (odd) { +#ifdef __LITTLE_ENDIAN result = *buff; +#else + result += (*buff << 8); +#endif len--; buff++; } @@ -71,7 +75,7 @@ static unsigned int do_csum(const unsigned char *buff, int len) if (count) { unsigned long carry = 0; do { - unsigned long w = *(unsigned long *) buff; + unsigned long w = *(unsigned int *) buff; count--; buff += 4; result += carry; @@ -87,7 +91,11 @@ static unsigned int do_csum(const unsigned char *buff, int len) } } if (len & 1) +#ifdef __LITTLE_ENDIAN + result += *buff; +#else result += (*buff << 8); +#endif result = from32to16(result); if (odd) result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); From 0634a632f5dea8281ae7c9a96800582ff9eb1475 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 23 Jun 2009 13:51:19 +0200 Subject: [PATCH 7/7] asm-generic: add dummy pgprot_noncached() Most architectures now provide a pgprot_noncached(), the remaining ones can simply use an dummy default implementation, except for cris and xtensa, which should override the default appropriately. Signed-off-by: Arnd Bergmann Cc: Jesper Nilsson Cc: Chris Zankel Cc: Magnus Damm --- include/asm-generic/pgtable.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index e410f602cab..e2bd73e8f9c 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -129,6 +129,10 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres #define move_pte(pte, prot, old_addr, new_addr) (pte) #endif +#ifndef pgprot_noncached +#define pgprot_noncached(prot) (prot) +#endif + #ifndef pgprot_writecombine #define pgprot_writecombine pgprot_noncached #endif