strlen_user & 2.1.10

Richard Henderson (richard@atheist.tamu.edu)
Fri, 15 Nov 1996 11:20:40 -0600 (CST)

As is, the access_ok for strlen_user is done too late -- the user has
already gotten the kernel to read from e.g. memory mapped i/o ports.
The solution, as with strcpy_from_user, is to access check one byte
and trust the exception handler to trigger when we leave user space.

And on the i386, while it is pretty cool to let gcc know about the
zero that results in ax, you've got to arrange for one to be there
on an exception as well.

r~

--- arch/alpha/lib/strlen_user.S.orig Fri Nov 15 10:47:24 1996
+++ arch/alpha/lib/strlen_user.S Fri Nov 15 10:49:26 1996
@@ -1,8 +1,8 @@
/*
- * arch/alpha/lib/__strlen_user.S
+ * arch/alpha/lib/strlen_user.S
*
- * Just like strlen except returns -EFAULT if an exception occurs
- * before the terminator is found.
+ * Return the length of the string including the NUL terminator
+ * (strlen+1) or zero if an error occured.
*/

#include <alpha/regdef.h>
@@ -13,7 +13,7 @@
99: x,##y; \
.section __ex_table,"a"; \
.gprel32 99b; \
- lda zero, $exception-99b(zero); \
+ lda v0, $exception-99b(zero); \
.text


@@ -34,7 +34,7 @@
insqh t1, a0, t1
andnot a0, 7, v0
or t1, t0, t0
- subq a0, 1, a0 # return "1+strlen" (0 for exception)
+ subq a0, 1, a0 # get our +1 for the return
cmpbge zero, t0, t1 # t1 <- bitmask: bit i == 1 <==> i-th byte == 0
bne t1, $found

@@ -56,12 +56,8 @@
addq v0, t4, v0
addq v0, t2, v0
nop # dual issue next two on ev4 and ev5
-
subq v0, a0, v0
- ret
-
$exception:
- mov zero, v0
ret

.end __strlen_user
--- include/asm-alpha/uaccess.h.orig Fri Nov 15 10:49:39 1996
+++ include/asm-alpha/uaccess.h Fri Nov 15 10:52:30 1996
@@ -377,14 +377,14 @@

extern long __strncpy_from_user(char *__to, const char *__from, long __to_len);

-#define strncpy_from_user(to,from,n) \
-({ \
- char * __sfu_to = (to); \
- const char * __sfu_from = (from); \
- long __sfu_len = (n), __sfu_ret = -EFAULT; \
- if (__access_ok(((long)__sfu_from),__sfu_len,__access_mask)) \
- __sfu_ret=__strncpy_from_user(__sfu_to,__sfu_from,__sfu_len); \
- __sfu_ret; \
+#define strncpy_from_user(to,from,n) \
+({ \
+ char * __sfu_to = (to); \
+ const char * __sfu_from = (from); \
+ long __sfu_ret = -EFAULT; \
+ if (__access_ok(((long)__sfu_from),1,__access_mask)) \
+ __sfu_ret = __strncpy_from_user(__sfu_to,__sfu_from,(n)); \
+ __sfu_ret; \
})

/* Returns: 0 if bad, string length+1 (memory size) of string if ok */
@@ -392,10 +392,7 @@

extern inline long strlen_user(const char *str)
{
- long len = __strlen_user(str);
- if (!access_ok(VERIFY_READ, str, len))
- len = 0;
- return len;
+ return access_ok(VERIFY_READ, str, 1) ? __strlen_user(str) : 0;
}

/*
--- include/asm-i386/uaccess.h.orig Fri Nov 15 10:52:40 1996
+++ include/asm-i386/uaccess.h Fri Nov 15 10:57:57 1996
@@ -412,27 +412,30 @@
*
* Return 0 for error
*/
-extern inline long strlen_user(const char * s)
+extern inline long __strlen_user(const char *s)
{
long res;
__asm__ __volatile__(
- "\n"
- "0:\trepne ; scasb\n\t"
- "notl %0\n"
+ "0: repne; scasb\n"
+ " notl %0\n"
"1:\n"
".section .fixup,\"ax\"\n"
- "2:\txorl %0,%0\n\t"
- "jmp 1b\n"
- ".section __ex_table,\"a\"\n\t"
- ".align 4\n\t"
- ".long 0b,2b\n"
+ "2: xorl %0,%0\n"
+ " xorl %2,%2\n"
+ " jmp 1b\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,2b\n"
".text"
- :"=c" (res)
- :"D" (s),"a" (0),"0" (0xffffffff)
- :"di");
- if (!access_ok(VERIFY_READ, s, res))
- res = 0;
+ : "=c"(res)
+ : "D"(s), "a"(0), "0"(0xffffffff)
+ : "di");
return res;
+}
+
+extern inline long strlen_user(const char * s)
+{
+ return access_ok(VERIFY_READ, s, 1) ? __strlen_user(s) : 0;
}


--
To unsubscribe: send e-mail to axp-list-request@redhat.com with
'unsubscribe' as the subject.  Do not send it to axp-list@redhat.com



Feedback | Store | News | Support | Product Errata | About Us | Linux Info | Search | JumpWords
No Frames | Show Frames

Copyright © 1995-1997 Red Hat Software. Legal notices