patch-2.3.21 linux/arch/alpha/lib/strlen_user.S

Next file: linux/arch/i386/boot/Makefile
Previous file: linux/arch/alpha/kernel/alpha_ksyms.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.20/linux/arch/alpha/lib/strlen_user.S linux/arch/alpha/lib/strlen_user.S
@@ -3,6 +3,13 @@
  *
  * Return the length of the string including the NUL terminator
  * (strlen+1) or zero if an error occurred.
+ *
+ * In places where it is critical to limit the processing time,
+ * and the data is not trusted, strnlen_user() should be used.
+ * It will return a value greater than its second argument if
+ * that limit would be exceeded. This implementation is allowed
+ * to access memory beyond the limit, but will not cross a page
+ * boundary when doing so.
  */
 
 #include <alpha/regdef.h>
@@ -27,6 +34,14 @@
 
 	.align 3
 __strlen_user:
+	ldah	a1, 32767(zero)	# do not use plain strlen_user() for strings
+				# that might be almost 2 GB long; you should
+				# be using strnlen_user() instead
+
+	.globl __strnlen_user
+
+	.align 3
+__strnlen_user:
 	ldgp	$29,0($27)	# we do exceptions -- we need the gp.
 	.prologue 1
 
@@ -37,9 +52,17 @@
 	or      t1, t0, t0
 	subq	a0, 1, a0	# get our +1 for the return 
 	cmpbge  zero, t0, t1	# t1 <- bitmask: bit i == 1 <==> i-th byte == 0
+	subq	a1, 7, t2
+	subq	a0, v0, t0
 	bne     t1, $found
 
-$loop:	EX( ldq t0, 8(v0) )
+	addq	t2, t0, t2
+	addq	a1, 1, a1
+
+	.align 3
+$loop:	ble	t2, $limit
+	EX( ldq t0, 8(v0) )
+	subq	t2, 8, t2
 	addq    v0, 8, v0	# addr += 8
 	cmpbge  zero, t0, t1
 	beq     t1, $loop
@@ -59,6 +82,11 @@
 	nop			# dual issue next two on ev4 and ev5
 	subq    v0, a0, v0
 $exception:
+	ret
+
+	.align 3		# currently redundant
+$limit:
+	subq	a1, t2, v0
 	ret
 
 	.end __strlen_user

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)