Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7b788cd authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

s390/uaccess: shorten strncpy_from_user/strnlen_user



Always stay within page boundaries when copying from user within
strlen_user_mvcos()/strncpy_from_user_mvcos(). This allows to
shorten the code a bit and may prevent unnecessary faults, since
we copy quite large amounts of memory to kernel space.

Also directly call the mvcos variants of copy_from_user() to
avoid indirect branches.

Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent ea4da6ea
Loading
Loading
Loading
Loading
+12 −12
Original line number Original line Diff line number Diff line
@@ -162,19 +162,19 @@ static size_t clear_user_mvcos(size_t size, void __user *to)


static size_t strnlen_user_mvcos(size_t count, const char __user *src)
static size_t strnlen_user_mvcos(size_t count, const char __user *src)
{
{
	size_t done, len, offset, len_str;
	char buf[256];
	char buf[256];
	int rc;
	size_t done, len, len_str;


	done = 0;
	done = 0;
	do {
	do {
		len = min(count - done, (size_t) 256);
		offset = (size_t)src & ~PAGE_MASK;
		rc = uaccess.copy_from_user(len, src + done, buf);
		len = min(256UL, PAGE_SIZE - offset);
		if (unlikely(rc == len))
		len = min(count - done, len);
		if (copy_from_user_mvcos(len, src, buf))
			return 0;
			return 0;
		len -= rc;
		len_str = strnlen(buf, len);
		len_str = strnlen(buf, len);
		done += len_str;
		done += len_str;
		src += len_str;
	} while ((len_str == len) && (done < count));
	} while ((len_str == len) && (done < count));
	return done + 1;
	return done + 1;
}
}
@@ -182,18 +182,18 @@ static size_t strnlen_user_mvcos(size_t count, const char __user *src)
static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
				      char *dst)
				      char *dst)
{
{
	int rc;
	size_t done, len, offset, len_str;
	size_t done, len, len_str;


	done = 0;
	done = 0;
	do {
	do {
		len = min(count - done, (size_t) 4096);
		offset = (size_t)src & ~PAGE_MASK;
		rc = uaccess.copy_from_user(len, src + done, dst);
		len = min(count - done, PAGE_SIZE - offset);
		if (unlikely(rc == len))
		if (copy_from_user_mvcos(len, src, dst))
			return -EFAULT;
			return -EFAULT;
		len -= rc;
		len_str = strnlen(dst, len);
		len_str = strnlen(dst, len);
		done += len_str;
		done += len_str;
		src += len_str;
		dst += len_str;
	} while ((len_str == len) && (done < count));
	} while ((len_str == len) && (done < count));
	return done;
	return done;
}
}