diff mbox series

[v4] getcwd01: Use syscall directly check invalid argument

Message ID 20231201031512.27513-1-wegao@suse.com
State Accepted
Headers show
Series [v4] getcwd01: Use syscall directly check invalid argument | expand

Commit Message

Wei Gao Dec. 1, 2023, 3:15 a.m. UTC
Fixes: #1084

User space wrap getcwd with different implementation, for example
glibc will directly input parameter into kernel in normal situation
but uclibc-ng and musl will malloc buffer when buffer is NULL, so for
uclibc and musl the parameter size will be ignored. Use system call
directly check invalid argument can be a solution.

Signed-off-by: Wei Gao <wegao@suse.com>
---
 testcases/kernel/syscalls/getcwd/getcwd01.c | 27 ++++++---------------
 1 file changed, 7 insertions(+), 20 deletions(-)

Comments

Petr Vorel Dec. 1, 2023, 10:14 a.m. UTC | #1
Hi Wei,

> Fixes: #1084

> User space wrap getcwd with different implementation, for example
> glibc will directly input parameter into kernel in normal situation
> but uclibc-ng and musl will malloc buffer when buffer is NULL, so for
> uclibc and musl the parameter size will be ignored. Use system call
> directly check invalid argument can be a solution.

For the sake of the correctness: there is no malloc() in musl [1] (nor in the
mirror source you posted to #1084), that's only in uclibc-ng [2] and glibc [3].

The reason why musl failed was already described by Richie and Cyril in #1084:
musl ignores the size parameter when buffer is NULL and allocates it with PATH_MAX
and passes this size to kernel.

Therefore I reword the commit message.

[1] https://git.musl-libc.org/cgit/musl/tree/src/unistd/getcwd.c
[2] https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/libc/sysdeps/linux/common/getcwd.c#n38
[3] https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getcwd.c;h=5b0b6879ed28f278f07ce494f9be30f504757daa;hb=HEAD#l47

...
> -	tst_res(TPASS | TTERRNO, "getcwd() failed as expected");
> +	TST_EXP_FAIL2(syscall(__NR_getcwd, tc->buf, tc->size), tc->exp_err);
While syscalls() would work everywhere, it's better is LTP wrapper tst_syscall()
(it TCONF in case when syscall is not implemented which is I admit nearly
impossible).

I used that and merged.
Thank you!

NOTE: we should implement .test_variants, where you just skip affected NULL
buffer test (it's enough to test it with raw syscall). Please send a patch or
let me know that you don't plan to do it and I'll do it.

Kind regards,
Petr
Wei Gao Dec. 4, 2023, 12:06 a.m. UTC | #2
On Fri, Dec 01, 2023 at 11:14:15AM +0100, Petr Vorel wrote:
> Hi Wei,
> 
> > Fixes: #1084
> 
> > User space wrap getcwd with different implementation, for example
> > glibc will directly input parameter into kernel in normal situation
> > but uclibc-ng and musl will malloc buffer when buffer is NULL, so for
> > uclibc and musl the parameter size will be ignored. Use system call
> > directly check invalid argument can be a solution.
> 
> For the sake of the correctness: there is no malloc() in musl [1] (nor in the
> mirror source you posted to #1084), that's only in uclibc-ng [2] and glibc [3].
> 
> The reason why musl failed was already described by Richie and Cyril in #1084:
> musl ignores the size parameter when buffer is NULL and allocates it with PATH_MAX
> and passes this size to kernel.
> 
> Therefore I reword the commit message.
> 
> [1] https://git.musl-libc.org/cgit/musl/tree/src/unistd/getcwd.c
> [2] https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/libc/sysdeps/linux/common/getcwd.c#n38
> [3] https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getcwd.c;h=5b0b6879ed28f278f07ce494f9be30f504757daa;hb=HEAD#l47
> 
> ...
> > -	tst_res(TPASS | TTERRNO, "getcwd() failed as expected");
> > +	TST_EXP_FAIL2(syscall(__NR_getcwd, tc->buf, tc->size), tc->exp_err);
> While syscalls() would work everywhere, it's better is LTP wrapper tst_syscall()
> (it TCONF in case when syscall is not implemented which is I admit nearly
> impossible).
> 
> I used that and merged.
> Thank you!
> 
> NOTE: we should implement .test_variants, where you just skip affected NULL
> buffer test (it's enough to test it with raw syscall). Please send a patch or
> let me know that you don't plan to do it and I'll do it.

I will try to send patch later.
Thanks you very much for fix my issue :) Will more carefull next time.

> 
> Kind regards,
> Petr
diff mbox series

Patch

diff --git a/testcases/kernel/syscalls/getcwd/getcwd01.c b/testcases/kernel/syscalls/getcwd/getcwd01.c
index 65d827873..ac35383a4 100644
--- a/testcases/kernel/syscalls/getcwd/getcwd01.c
+++ b/testcases/kernel/syscalls/getcwd/getcwd01.c
@@ -14,8 +14,8 @@ 
  *
  * Expected Result:
  * 1) getcwd(2) should return NULL and set errno to EFAULT.
- * 2) getcwd(2) should return NULL and set errno to ENOMEM.
- * 3) getcwd(2) should return NULL and set errno to EINVAL.
+ * 2) getcwd(2) should return NULL and set errno to EFAULT.
+ * 3) getcwd(2) should return NULL and set errno to ERANGE.
  * 4) getcwd(2) should return NULL and set errno to ERANGE.
  * 5) getcwd(2) should return NULL and set errno to ERANGE.
  *
@@ -24,6 +24,7 @@ 
 #include <errno.h>
 #include <unistd.h>
 #include <limits.h>
+#include "lapi/syscalls.h"
 #include "tst_test.h"
 
 static char buffer[5];
@@ -34,32 +35,18 @@  static struct t_case {
 	int exp_err;
 } tcases[] = {
 	{(void *)-1, PATH_MAX, EFAULT},
-	{NULL, (size_t)-1, ENOMEM},
-	{buffer, 0, EINVAL},
+	{NULL, (size_t)-1, EFAULT},
+	{buffer, 0, ERANGE},
 	{buffer, 1, ERANGE},
 	{NULL, 1, ERANGE}
 };
 
+
 static void verify_getcwd(unsigned int n)
 {
 	struct t_case *tc = &tcases[n];
-	char *res;
-
-	errno = 0;
-	res = getcwd(tc->buf, tc->size);
-	TST_ERR = errno;
-	if (res) {
-		tst_res(TFAIL, "getcwd() succeeded unexpectedly");
-		return;
-	}
-
-	if (TST_ERR != tc->exp_err) {
-		tst_res(TFAIL | TTERRNO, "getcwd() failed unexpectedly, expected %s",
-			tst_strerrno(tc->exp_err));
-		return;
-	}
 
-	tst_res(TPASS | TTERRNO, "getcwd() failed as expected");
+	TST_EXP_FAIL2(syscall(__NR_getcwd, tc->buf, tc->size), tc->exp_err);
 }
 
 static struct tst_test test = {