[LTP] [PATCH 1/2] syscalls/faccessat201: Add new testcase
Yang Xu (Fujitsu)
xuyang2018.jy@fujitsu.com
Tue Aug 22 11:45:56 CEST 2023
Hi Cyril
> Hi!
>> diff --git a/include/lapi/faccessat2.h b/include/lapi/faccessat2.h
>> new file mode 100644
>> index 000000000..e8b27d6b1
>> --- /dev/null
>> +++ b/include/lapi/faccessat2.h
>> @@ -0,0 +1,20 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
>> + * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
>> + */
>> +
>> +#ifndef LAPI_FACCESSAT2_H__
>> +#define LAPI_FACCESSAT2_H__
>> +
>> +#include "tst_test.h"
>> +#include "lapi/syscalls.h"
>> +
>> +#ifndef HAVE_FACCESSAT2
>> +int faccessat2(int dirfd, const char *pathname, int mode, int flags)
>> +{
>> + return tst_syscall(__NR_faccessat2, dirfd, pathname, mode, flags);
>> +}
>> +#endif
>> +
>> +#endif /* LAPI_FACCESSAT2_H__ */
> This one needs the configure check, and I would call the header just
> faccessat.h.
i will update it.
>> diff --git a/testcases/kernel/syscalls/faccessat2/faccessat201.c b/testcases/kernel/syscalls/faccessat2/faccessat201.c
>> new file mode 100644
>> index 000000000..658d1dd81
>> --- /dev/null
>> +++ b/testcases/kernel/syscalls/faccessat2/faccessat201.c
>> @@ -0,0 +1,115 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (c) 2023 FUJITSU LIMITED. All rights reserved.
>> + * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
>> + */
>> +
>> +/*\
>> + * [Description]
>> + *
>> + * Check the basic functionality of faccessat2().
>> + *
>> + * Minimum Linux version required is v5.8.
>> + */
>> +
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <pwd.h>
>> +
>> +#include "tst_test.h"
>> +#include "lapi/syscalls.h"
>> +#include "lapi/faccessat2.h"
>> +
>> +#define TESTUSER "nobody"
>> +#define TESTDIR "faccessat2dir"
>> +#define TESTFILE "faccessat2file"
>> +#define RELPATH "faccessat2dir/faccessat2file"
>> +#define TESTSYMLINK "faccessat2symlink"
> There is a mix of tabs and spaces in this part that should be cleaned
> up.
My mistake, I will correct it.
>> +static int dir_fd = -1, bad_fd = -1;
>> +static int atcwd_fd = AT_FDCWD;
>> +static char *filepaths[4];
>> +static char abs_path[128];
>> +static struct passwd *ltpuser;
>> +
>> +static struct tcase {
>> + int *fd;
>> + char **filename;
>> + int flags;
>> + int exp_errno;
>> +} tcases[] = {
>> + {&dir_fd, &filepaths[0], 0, 0},
>> + {&bad_fd, &filepaths[1], 0, 0},
>> + {&atcwd_fd, &filepaths[2], 0, 0},
>> + {&dir_fd, &filepaths[0], AT_EACCESS, 0},
>> + {&bad_fd, &filepaths[1], AT_EACCESS, 0},
>> + {&atcwd_fd, &filepaths[2], AT_EACCESS, 0},
>> + {&dir_fd, &filepaths[0], AT_EACCESS, EACCES},
>> + {&bad_fd, &filepaths[1], AT_EACCESS, EACCES},
>> + {&atcwd_fd, &filepaths[2], AT_EACCESS, EACCES},
>> + {&atcwd_fd, &filepaths[3], AT_SYMLINK_NOFOLLOW, 0},
>> +};
>> +
>> +static void verify_faccessat2(unsigned int i)
>> +{
>> + struct tcase *tc = &tcases[i];
>> +
>> + if (tc->exp_errno == EACCES) {
>> + if (SAFE_FORK() == 0) {
>> + SAFE_SETUID(ltpuser->pw_uid);
>> + TST_EXP_FAIL(faccessat2(*tc->fd, *tc->filename, R_OK, tc->flags),
>> + tc->exp_errno, "faccessat2(%d, %s, R_OK, %d) as %s",
>> + *tc->fd, *tc->filename, tc->flags, TESTUSER);
>> + }
>> +
>> + tst_reap_children();
> I would just put the EACCESS tests to a separate testcase, which would
> make the test more straightforward and easier to read.
ok.
>> + } else {
>> + TST_EXP_PASS(faccessat2(*tc->fd, *tc->filename, R_OK, tc->flags),
>> + "faccessat2(%d, %s, R_OK, %d) as root",
>> + *tc->fd, *tc->filename, tc->flags);
>> + }
>> +}
>> +
>> +static void setup(void)
>> +{
>> + char *tmpdir_path = tst_get_tmpdir();
>> +
>> + sprintf(abs_path, "%s/%s", tmpdir_path, RELPATH);
>> + free(tmpdir_path);
>> +
>> + SAFE_MKDIR(TESTDIR, 0666);
>> + dir_fd = SAFE_OPEN(TESTDIR, O_DIRECTORY);
>> + SAFE_TOUCH(abs_path, 0444, NULL);
>> + SAFE_SYMLINK(abs_path, TESTSYMLINK);
>> +
>> + filepaths[0] = TESTFILE;
>> + filepaths[1] = abs_path;
>> + filepaths[2] = RELPATH;
>> + filepaths[3] = TESTSYMLINK;
>> +
>> + ltpuser = SAFE_GETPWNAM(TESTUSER);
>> +}
>> +
>> +static void cleanup(void)
>> +{
>> + if (dir_fd > 0)
>> + SAFE_CLOSE(dir_fd);
>> +}
>> +
>> +static struct tst_test test = {
>> + .test = verify_faccessat2,
>> + .tcnt = ARRAY_SIZE(tcases),
>> + .setup = setup,
>> + .cleanup = cleanup,
>> + .bufs = (struct tst_buffers []) {
>> + {&filepaths[0], .size = sizeof(*filepaths[0])},
>> + {&filepaths[1], .size = sizeof(*filepaths[1])},
>> + {&filepaths[2], .size = sizeof(*filepaths[2])},
>> + {&filepaths[3], .size = sizeof(*filepaths[3])},
>> + {<puser, .size = sizeof(ltpuser)},
> Why do we allocate anything here when we replace the pointers in the
> test setup anyways?
>
> If anything it would make sense to allocate the buffers in the test
> setup instead of using static strings there. Also filepath[x] way less
> readable than actually giving the variables proper names such as
> abs_path.
>
> I guess that we can as well add a helper to the buffer library such as:
>
> diff --git a/include/tst_buffers.h b/include/tst_buffers.h
> index d19ac8cf0..a12d70a62 100644
> --- a/include/tst_buffers.h
> +++ b/include/tst_buffers.h
> @@ -46,6 +46,11 @@ char *tst_strdup(const char *str);
> */
> void *tst_alloc(size_t size);
>
> +/*
> + * Strdup into a guarded buffer.
> + */
> +char *tst_strdup(const char *str);
> +
> /*
> * Allocates iovec structure including the buffers.
> *
> diff --git a/lib/tst_buffers.c b/lib/tst_buffers.c
> index b8b597a12..4488f458e 100644
> --- a/lib/tst_buffers.c
> +++ b/lib/tst_buffers.c
> @@ -76,6 +76,13 @@ void *tst_alloc(size_t size)
> return ret + map->buf_shift;
> }
>
> +char *tst_strup(const char *str)
> +{
> + char *ret = tst_alloc(strlen(str) + 1);
> +
> + return strcpy(ret, str);
> +}
> +
> static int count_iovec(int *sizes)
> {
> int ret = 0;
>
>
> And slightly more complicated would be addition of tst_aprintf() that
> would printf into buffer allocated by tst_alloc(). I will send a patch
> that adds this tomorrow.
>
> Once that is done we can use these in the test setup such as:
>
> static char *abs_path;
> static char *testfile;
>
> static struct tcase {
> int *fd;
> char **filename;
> int flags;
> int exp_errno;
> } tcases[] = {
> {..., &abs_path, ...},
> {..., &testfile, ...},
> }
>
> static void setup(void)
> {
> ...
>
> testfile = tst_strdup(TESTFILE);
> abs_path = tst_aprintf(abs_path, "%s/%s", tmpdir_path, TESTFILE);
>
> ...
> }
>
> Which allocates the exact sized guarded buffers so that the canaries are
> exaclty after end of the data, not at the end of the rather large
> buffer.
>
> We can't pre-allocate buffers in the tst_test structure for data whose
> size is not known in advance, which is the case for the tmpdir_path.
I have overlooked these issues and will make modifications based on your
suggestions.
More information about the ltp
mailing list