Эх сурвалжийг харах

[PATCH] _proc_do_string(): fix short reads

If you try to read things like /proc/sys/kernel/osrelease with single-byte
reads, you get just one byte and then EOF.  This is because _proc_do_string()
assumes that the caller is read()ing into a buffer which is large enough to
fit the whole string in a single hit.

Fix.

Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Oleg Nesterov 18 жил өмнө
parent
commit
8d06087714
1 өөрчлөгдсөн 12 нэмэгдсэн , 4 устгасан
  1. 12 4
      kernel/sysctl.c

+ 12 - 4
kernel/sysctl.c

@@ -1686,13 +1686,12 @@ static int _proc_do_string(void* data, int maxlen, int write,
 	size_t len;
 	size_t len;
 	char __user *p;
 	char __user *p;
 	char c;
 	char c;
-	
-	if (!data || !maxlen || !*lenp ||
-	    (*ppos && !write)) {
+
+	if (!data || !maxlen || !*lenp) {
 		*lenp = 0;
 		*lenp = 0;
 		return 0;
 		return 0;
 	}
 	}
-	
+
 	if (write) {
 	if (write) {
 		len = 0;
 		len = 0;
 		p = buffer;
 		p = buffer;
@@ -1713,6 +1712,15 @@ static int _proc_do_string(void* data, int maxlen, int write,
 		len = strlen(data);
 		len = strlen(data);
 		if (len > maxlen)
 		if (len > maxlen)
 			len = maxlen;
 			len = maxlen;
+
+		if (*ppos > len) {
+			*lenp = 0;
+			return 0;
+		}
+
+		data += *ppos;
+		len  -= *ppos;
+
 		if (len > *lenp)
 		if (len > *lenp)
 			len = *lenp;
 			len = *lenp;
 		if (len)
 		if (len)