From patchwork Sun Jul 29 08:16:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "vaishnavi.d" X-Patchwork-Id: 950534 X-Patchwork-Delegate: petr.vorel@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=zilogic.com Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41dbCp0qpbz9s0R for ; Sun, 29 Jul 2018 18:17:23 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 540AA3E73A8 for ; Sun, 29 Jul 2018 10:17:18 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-5.smtp.seeweb.it (in-5.smtp.seeweb.it [217.194.8.5]) by picard.linux.it (Postfix) with ESMTP id F3D8A3E602A for ; Sun, 29 Jul 2018 10:17:15 +0200 (CEST) Received: from mail.zilogic.com (mail.zilogic.com [45.33.14.236]) by in-5.smtp.seeweb.it (Postfix) with ESMTP id 3C9646010B4 for ; Sun, 29 Jul 2018 10:17:12 +0200 (CEST) Date: Sun, 29 Jul 2018 08:16:07 -0000 To: ltp@lists.linux.it Message-ID: <20180729081607.27044-1-vaishnavi.d@zilogic.com> From: "vaishnavid" Received: from osboxes.domain.name (117.247.199.22 [117.247.199.22]) by mail.zilogic.com; Sun, 29 Jul 2018 08:16:33 -0000 X-Mailer: git-send-email 2.11.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-5.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.0 required=7.0 tests=MSGID_FROM_MTA_HEADER, SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-5.smtp.seeweb.it Subject: [LTP] [PATCH v4] Testing statx syscall X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" * statx01.c: This file will check metadata of files like uid, gid, size, blocks, mode for normal file(1) and rdev_major, rdev_minor number for device file(2) * statx02.c: This file will check flag like AT_EMPTY_PATH, AT_SYMLINK_NOFOLLOW * AT_EMPTY_PATH: If pathname is an empty string, operate on the file referred to by dirfd. * AT_SYMLINK_NOFOLLOW:If pathname is a symbolic link, do not dereference it: instead return information about the link itself. * stat03.c: This file will check error code(errno) by providing required input in statx argument syscall. The following errno are checked: EBADF, EBADF, ENAMETOOLONG, ENOENT, ENOTDIR, EFAULT. * statx04.sh: This script will check attribute flag by defining flag to that directory and checks another directory no flags. It contains helper c file to get attribute status Changes from V3 to V4: * Added fs.h header file. * Renamed statx wrapper function. * Handled command_not_found for e4crypt in statx04.c. * used tst_get_bad_addr() to simulate EFAULT scenario. * Modified log messages in tst_res. Signed-off-by: Tarun.T.U Signed-off-by: Vaishnavi.D --- include/lapi/fs.h | 47 +++++ include/lapi/sys_statx.h | 264 +++++++++++++++++++++++++++++ include/lapi/syscalls/arm.in | 1 + include/lapi/syscalls/i386.in | 1 + include/lapi/syscalls/powerpc.in | 1 + include/lapi/syscalls/powerpc64.in | 1 + include/lapi/syscalls/s390.in | 1 + include/lapi/syscalls/sparc.in | 1 + include/lapi/syscalls/sparc64.in | 1 + include/lapi/syscalls/x86_64.in | 1 + m4/ltp-statx.m4 | 25 +++ runtest/syscalls | 9 + testcases/kernel/syscalls/statx/.gitignore | 8 + testcases/kernel/syscalls/statx/Makefile | 26 +++ testcases/kernel/syscalls/statx/statx01.c | 200 ++++++++++++++++++++++ testcases/kernel/syscalls/statx/statx02.c | 144 ++++++++++++++++ testcases/kernel/syscalls/statx/statx03.c | 135 +++++++++++++++ testcases/kernel/syscalls/statx/statx04.c | 217 ++++++++++++++++++++++++ 18 files changed, 1083 insertions(+) create mode 100644 include/lapi/fs.h create mode 100644 include/lapi/sys_statx.h create mode 100644 m4/ltp-statx.m4 create mode 100644 testcases/kernel/syscalls/statx/.gitignore create mode 100644 testcases/kernel/syscalls/statx/Makefile create mode 100644 testcases/kernel/syscalls/statx/statx01.c create mode 100644 testcases/kernel/syscalls/statx/statx02.c create mode 100644 testcases/kernel/syscalls/statx/statx03.c create mode 100644 testcases/kernel/syscalls/statx/statx04.c diff --git a/include/lapi/fs.h b/include/lapi/fs.h new file mode 100644 index 000000000..e3cf2673e --- /dev/null +++ b/include/lapi/fs.h @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 or later +/* + * Referred from linux kernel -github/torvalds/linux + * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 + * Email: code@zilogic.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef FS_H +#define FS_H + +#ifndef FS_IOC_GETFLAGS +#define FS_IOC_GETFLAGS _IOR('f', 1, long) +#endif + +#ifndef FS_IOC_SETFLAGS +#define FS_IOC_SETFLAGS _IOW('f', 2, long) +#endif + +#ifndef FS_COMPR_FL +#define FS_COMPR_FL 0x00000004 /* Compress file */ +#endif + +#ifndef FS_IMMUTABLE_FL +#define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */ +#endif + +#ifndef FS_APPEND_FL +#define FS_APPEND_FL 0x00000020 /* writes to file may only append */ +#endif + +#ifndef FS_NODUMP_FL +#define FS_NODUMP_FL 0x00000040 /* do not dump file */ +#endif + +#endif diff --git a/include/lapi/sys_statx.h b/include/lapi/sys_statx.h new file mode 100644 index 000000000..d1f29a3fa --- /dev/null +++ b/include/lapi/sys_statx.h @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0 or later +/* + * Referred from linux kernel -github/torvalds/linux + * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 + * Email: code@zilogic.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef STATX_H +#define STATX_H + +#include +#include "lapi/syscalls.h" + +/* + * Timestamp structure for the timestamps in struct statx. + * + * tv_sec holds the number of seconds before (negative) or after (positive) + * 00:00:00 1st January 1970 UTC. + * + * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time. + * + * __reserved is held in case we need a yet finer resolution. + */ +struct statx_timestamp { + int64_t tv_sec; + uint32_t tv_nsec; + int32_t __reserved; +}; + +/* + * Structures for the extended file attribute retrieval system call + * (statx()). + * + * The caller passes a mask of what they're specifically interested in as a + * parameter to statx(). What statx() actually got will be indicated in + * st_mask upon return. + * + * For each bit in the mask argument: + * + * - if the datum is not supported: + * + * - the bit will be cleared, and + * + * - the datum will be set to an appropriate fabricated value if one is + * available (eg. CIFS can take a default uid and gid), otherwise + * + * - the field will be cleared; + * + * - otherwise, if explicitly requested: + * + * - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is + * set or if the datum is considered out of date, and + * + * - the field will be filled in and the bit will be set; + * + * - otherwise, if not requested, but available in approximate form without any + * effort, it will be filled in anyway, and the bit will be set upon return + * (it might not be up to date, however, and no attempt will be made to + * synchronise the internal state first); + * + * - otherwise the field and the bit will be cleared before returning. + * + * Items in STATX_BASIC_STATS may be marked unavailable on return, but they + * will have values installed for compatibility purposes so that stat() and + * co. can be emulated in userspace. + */ +struct statx { + /* 0x00 */ + uint32_t stx_mask; + uint32_t stx_blksize; + uint64_t stx_attributes; + /* 0x10 */ + uint32_t stx_nlink; + uint32_t stx_uid; + uint32_t stx_gid; + uint16_t stx_mode; + uint16_t __spare0[1]; + /* 0x20 */ + uint64_t stx_ino; + uint64_t stx_size; + uint64_t stx_blocks; + uint64_t stx_attributes_mask; + /* 0x40 */ + const struct statx_timestamp stx_atime; + const struct statx_timestamp stx_btime; + const struct statx_timestamp stx_ctime; + const struct statx_timestamp stx_mtime; + /* 0x80 */ + uint32_t stx_rdev_major; + uint32_t stx_rdev_minor; + uint32_t stx_dev_major; + uint32_t stx_dev_minor; + /* 0x90 */ + uint64_t __spare2[14]; + /* 0x100 */ +}; + +#if !defined(HAVE_STATX) + +/* + * statx: wrapper function of statx + * + * Returns: It returns status of statx syscall + */ +static inline int statx(int dirfd, const char *pathname, unsigned int flags, + unsigned int mask, struct statx *statxbuf) +{ + return tst_syscall(__NR_statx, dirfd, pathname, flags, mask, statxbuf); +} + +#endif + +/* + * Flags to be stx_mask + * + * Query request/result mask for statx() and struct statx::stx_mask. + * + * These bits should be set in the mask argument of statx() to request + * particular items when calling statx(). + */ +#ifndef STATX_TYPE +# define STATX_TYPE 0x00000001U +#endif + +#ifndef STATX_MODE +# define STATX_MODE 0x00000002U +#endif + +#ifndef STATX_NLINK +# define STATX_NLINK 0x00000004U +#endif + +#ifndef STATX_UID +# define STATX_UID 0x00000008U +#endif + +#ifndef STATX_GID +# define STATX_GID 0x00000010U +#endif + +#ifndef STATX_ATIME +# define STATX_ATIME 0x00000020U +#endif + +#ifndef STATX_MTIME +# define STATX_MTIME 0x00000040U +#endif + +#ifndef STATX_CTIME +# define STATX_CTIME 0x00000080U +#endif + +#ifndef STATX_INO +# define STATX_INO 0x00000100U +#endif + +#ifndef STATX_SIZE +# define STATX_SIZE 0x00000200U +#endif + +#ifndef STATX_BLOCKS +# define STATX_BLOCKS 0x00000400U +#endif + +#ifndef STATX_BASIC_STATS +# define STATX_BASIC_STATS 0x000007ffU +#endif + +#ifndef STATX_BTIME +# define STATX_BTIME 0x00000800U +#endif + +#ifndef STATX_ALL +# define STATX_ALL 0x00000fffU +#endif + +#ifndef STATX__RESERVED +# define STATX__RESERVED 0x80000000U +#endif + +/* + * Attributes to be found in stx_attributes and masked in stx_attributes_mask. + * + * These give information about the features or the state of a file that might + * be of use to ordinary userspace programs such as GUIs or ls rather than + * specialised tools. + * + * Note that the flags marked [I] correspond to generic FS_IOC_FLAGS + * semantically. Where possible, the numerical value is picked to correspond + * also. + */ +#ifndef STATX_ATTR_COMPRESSED +# define STATX_ATTR_COMPRESSED 0x00000004 +#endif + +#ifndef STATX_ATTR_IMMUTABLE +# define STATX_ATTR_IMMUTABLE 0x00000010 +#endif + +#ifndef STATX_ATTR_APPEND +# define STATX_ATTR_APPEND 0x00000020 +#endif + +#ifndef STATX_ATTR_NODUMP +# define STATX_ATTR_NODUMP 0x00000040 +#endif + +#ifndef STATX_ATTR_ENCRYPTED +# define STATX_ATTR_ENCRYPTED 0x00000800 +#endif + +#ifndef STATX_ATTR_AUTOMOUNT +# define STATX_ATTR_AUTOMOUNT 0x00001000 +#endif + +#ifndef AT_SYMLINK_NOFOLLOW +# define AT_SYMLINK_NOFOLLOW 0x100 +#endif + +#ifndef AT_REMOVEDIR +# define AT_REMOVEDIR 0x200 +#endif + +#ifndef AT_SYMLINK_FOLLOW +# define AT_SYMLINK_FOLLOW 0x400 +#endif + +#ifndef AT_NO_AUTOMOUNT +# define AT_NO_AUTOMOUNT 0x800 +#endif + +#ifndef AT_EMPTY_PATH +# define AT_EMPTY_PATH 0x1000 +#endif + +#ifndef AT_STATX_SYNC_TYPE +# define AT_STATX_SYNC_TYPE 0x6000 +#endif + +#ifndef AT_STATX_SYNC_AS_STAT +# define AT_STATX_SYNC_AS_STAT 0x0000 +#endif + +#ifndef AT_STATX_FORCE_SYNC +# define AT_STATX_FORCE_SYNC 0x2000 +#endif + +#ifndef AT_STATX_DONT_SYNC +# define AT_STATX_DONT_SYNC 0x4000 +#endif + +#endif diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in index 71a4b713d..784b64004 100644 --- a/include/lapi/syscalls/arm.in +++ b/include/lapi/syscalls/arm.in @@ -341,3 +341,4 @@ renameat2 (__NR_SYSCALL_BASE+382) getrandom (__NR_SYSCALL_BASE+384) memfd_create (__NR_SYSCALL_BASE+385) copy_file_range (__NR_SYSCALL_BASE+391) +statx (__NR_SYSCALL+397) diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/i386.in index 0f9601472..453ac3e4e 100644 --- a/include/lapi/syscalls/i386.in +++ b/include/lapi/syscalls/i386.in @@ -341,3 +341,4 @@ renameat2 354 getrandom 355 memfd_create 356 copy_file_range 377 +statx 383 diff --git a/include/lapi/syscalls/powerpc.in b/include/lapi/syscalls/powerpc.in index 11ddca34e..10fb238bf 100644 --- a/include/lapi/syscalls/powerpc.in +++ b/include/lapi/syscalls/powerpc.in @@ -348,3 +348,4 @@ renameat2 357 getrandom 359 memfd_create 360 copy_file_range 379 +statx 383 diff --git a/include/lapi/syscalls/powerpc64.in b/include/lapi/syscalls/powerpc64.in index 11ddca34e..10fb238bf 100644 --- a/include/lapi/syscalls/powerpc64.in +++ b/include/lapi/syscalls/powerpc64.in @@ -348,3 +348,4 @@ renameat2 357 getrandom 359 memfd_create 360 copy_file_range 379 +statx 383 diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/s390.in index 98c861f36..486205030 100644 --- a/include/lapi/syscalls/s390.in +++ b/include/lapi/syscalls/s390.in @@ -332,3 +332,4 @@ renameat2 347 getrandom 349 memfd_create 350 copy_file_range 375 +statx 379 \ No newline at end of file diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/sparc.in index 296d694a8..bbab51b72 100644 --- a/include/lapi/syscalls/sparc.in +++ b/include/lapi/syscalls/sparc.in @@ -337,3 +337,4 @@ renameat2 345 getrandom 347 memfd_create 348 copy_file_range 357 +statx 360 diff --git a/include/lapi/syscalls/sparc64.in b/include/lapi/syscalls/sparc64.in index 169347a6a..ebff38265 100644 --- a/include/lapi/syscalls/sparc64.in +++ b/include/lapi/syscalls/sparc64.in @@ -313,3 +313,4 @@ renameat2 345 getrandom 347 memfd_create 348 copy_file_range 357 +statx 360 diff --git a/include/lapi/syscalls/x86_64.in b/include/lapi/syscalls/x86_64.in index 89db79404..11a7b74ca 100644 --- a/include/lapi/syscalls/x86_64.in +++ b/include/lapi/syscalls/x86_64.in @@ -308,3 +308,4 @@ renameat2 316 getrandom 318 memfd_create 319 copy_file_range 326 +statx 332 diff --git a/m4/ltp-statx.m4 b/m4/ltp-statx.m4 new file mode 100644 index 000000000..52823b5ed --- /dev/null +++ b/m4/ltp-statx.m4 @@ -0,0 +1,25 @@ +dnl +dnl Copyright (c) Linux Test Project, 2014 +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +dnl the GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +dnl + +dnl +dnl LTP_CHECK_STATX +dnl ---------------------------- +dnl +AC_DEFUN([LTP_CHECK_STATX],[ +AC_CHECK_FUNCS(statx,,) +]) diff --git a/runtest/syscalls b/runtest/syscalls index dc72484cb..bc84c0df7 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -1277,6 +1277,15 @@ statfs03_64 statfs03_64 statvfs01 statvfs01 statvfs02 statvfs02 +statx01 statx01 +statx01_64 statx01_64 +statx02 statx02 +statx02_64 statx02_64 +statx03 statx03 +statx03_64 statx03_64 +statx04 statx04 +statx04_64 statx04_64 + stime01 stime01 stime02 stime02 diff --git a/testcases/kernel/syscalls/statx/.gitignore b/testcases/kernel/syscalls/statx/.gitignore new file mode 100644 index 000000000..474871dd1 --- /dev/null +++ b/testcases/kernel/syscalls/statx/.gitignore @@ -0,0 +1,8 @@ +/statx01 +/statx01_64 +/statx02 +/statx02_64 +/statx03 +/statx03_64 +/statx04 +/statx04_64 diff --git a/testcases/kernel/syscalls/statx/Makefile b/testcases/kernel/syscalls/statx/Makefile new file mode 100644 index 000000000..bf1201019 --- /dev/null +++ b/testcases/kernel/syscalls/statx/Makefile @@ -0,0 +1,26 @@ +# +# Copyright (c) International Business Machines Corp., 2001 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk +include $(abs_srcdir)/../utils/newer_64.mk + +%_64: CPPFLAGS += -D_FILE_OFFSET_BITS=64 + +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/statx/statx01.c b/testcases/kernel/syscalls/statx/statx01.c new file mode 100644 index 000000000..24dce1adc --- /dev/null +++ b/testcases/kernel/syscalls/statx/statx01.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0 or later +/* + * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 + * Email: code@zilogic.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Test statx + * + * This code tests the functionality of statx system call. + * + * TESTCASE 1: + * The metadata for normal file are tested against predefined values: + * 1) gid + * 2) uid + * 3) mode + * 4) blocks + * 5) size + * + * A file is created and metadata values are set with + * predefined values. + * Then the values obtained using statx is checked against + * the predefined values. + * + * TESTCASE 2: + * The metadata for device file are tested against predefined values: + * 1) MAJOR number + * 2) MINOR number + * + * A device file is created seperately using mknod(must be a root user). + * The major number and minor number are set while creation. + * Major and minor numbers obtained using statx is checked against + * predefined values. + * Minimum kernel version required is 4.11. + */ +#include +#include +#include +#include +#include +#include "tst_test.h" +#include "tst_safe_macros.h" +#include "lapi/sys_statx.h" +#include + +#define TESTFILE "test_file" +#define DEVICEFILE "blk_dev" +#define MODE 0644 + +static int file_fd; +#define SIZE 256 +#define MAJOR 8 +#define MINOR 1 + +static void test_normal_file(void) +{ + struct statx buff; + uint32_t blocks; + + TEST(statx(AT_FDCWD, TESTFILE, 0, 0, &buff)); + if (TST_RET == 0) + tst_res(TPASS, + "statx(AT_FDCWD, %s, 0, 0, &buff)", TESTFILE); + else + tst_brk(TFAIL | TTERRNO, + "statx(AT_FDCWD, %s, 0, 0, &buff)", TESTFILE); + + if (geteuid() == buff.stx_uid) + tst_res(TPASS, + "stx_uid(%u) obtained is correct", buff.stx_uid); + else + tst_res(TFAIL, + "stx_uid(%u) obtained is different from euid(%u)", + buff.stx_uid, geteuid()); + + if (getegid() == buff.stx_gid) + tst_res(TPASS, + "stx_gid(%u) obtained is correct", buff.stx_gid); + else + tst_res(TFAIL, + "stx_gid(%u) obtained is different from egid(%u)", + buff.stx_gid, getegid()); + + if (buff.stx_size == SIZE) + tst_res(TPASS, + "stx_size(%llu) obtained is correct", buff.stx_size); + else + tst_res(TFAIL, + "stx_size(%llu) obtained is different from expected(%u)", + buff.stx_size, SIZE); + + if ((buff.stx_mode & ~(S_IFMT)) == MODE) + tst_res(TPASS, + "stx_mode(%u) obtained is correct", buff.stx_mode); + else + tst_res(TFAIL, + "stx_mode(%u) obtained is different from expected(%u)", + buff.stx_mode, MODE); + + blocks = (((SIZE + buff.stx_blksize - 1) / buff.stx_blksize) + * (buff.stx_blksize / 512)); + + if (blocks == buff.stx_blocks) + tst_res(TPASS, + "stx_blocks(%llu) obtained is correct", + buff.stx_blocks); + else + tst_res(TFAIL, + "stx_blocks(%llu) obtained is different from expected(%u)", + buff.stx_blocks, blocks); + +} + +static void test_device_file(void) +{ + struct statx buff; + + TEST(statx(AT_FDCWD, DEVICEFILE, 0, 0, &buff)); + if (TST_RET == 0) + tst_res(TPASS, + "statx(AT_FDCWD, %s, 0, 0, &buff)", DEVICEFILE); + else + tst_brk(TFAIL | TTERRNO, + "statx(AT_FDCWD, %s, 0, 0, &buff)", DEVICEFILE); + + if (buff.stx_rdev_major == MAJOR) + tst_res(TPASS, + "stx_rdev_major(%u) obtained is correct", + buff.stx_rdev_major); + else + tst_res(TFAIL, + "stx_rdev_major(%u) obtained is different from expected(%u)", + buff.stx_rdev_major, MAJOR); + + if (buff.stx_rdev_minor == MINOR) + tst_res(TPASS, + "stx_rdev_minor(%u) obtained is correct", + buff.stx_rdev_minor); + else + tst_res(TFAIL, + "stx_rdev_minor(%u) obtained is different from expected(%u)", + buff.stx_rdev_minor, MINOR); +} + + +struct tcase { + void (*tfunc)(void); +} tcases[] = { + {&test_normal_file}, + {&test_device_file} +}; + +static void run(unsigned int i) +{ + struct tcase *t; + + t = &tcases[i]; + t->tfunc(); +} + +static void setup(void) +{ + char data_buff[SIZE]; + + memset(data_buff, '@', sizeof(data_buff)); + + file_fd = SAFE_OPEN(TESTFILE, O_RDWR|O_CREAT, MODE); + SAFE_WRITE(0, file_fd, data_buff, sizeof(data_buff)); + + SAFE_MKNOD(DEVICEFILE, S_IFBLK | 0777, makedev(MAJOR, MINOR)); +} + +static void cleanup(void) +{ + if (file_fd > 0) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .cleanup = cleanup, + .min_kver = "4.11", + .needs_root = 1, + .needs_tmpdir = 1, +}; diff --git a/testcases/kernel/syscalls/statx/statx02.c b/testcases/kernel/syscalls/statx/statx02.c new file mode 100644 index 000000000..72394387b --- /dev/null +++ b/testcases/kernel/syscalls/statx/statx02.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0 or later +/* + * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 + * Email: code@zilogic.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Test statx + * + * This code tests the following flags: + * 1) AT_EMPTY_PATH + * 2) AT_SYMLINK_NOFOLLOW + * + * A test file and a link for it is created. + * + * To check empty path flag, test file fd alone is passed. + * Predefined size of testfile is checked against obtained value. + * + * To check symlink no follow flag, the linkname is statxed. + * To ensure that link is not dereferenced, obtained inode is compared + * with test file inode. + * Minimum kernel version required is 4.11. + */ + +#include +#include +#include +#include "tst_test.h" +#include "tst_safe_macros.h" +#include "lapi/sys_statx.h" + +#define TESTFILE "test_temp" +#define LINK_FILE "test_temp_ln" +#define MODE 0644 +#define SIZE 14 + +static int file_fd; + +static void test_empty_path(void) +{ + struct statx buf; + + TEST(statx(file_fd, "", AT_EMPTY_PATH, 0, &buf)); + if (TST_RET == 0) + tst_res(TPASS, + "statx(file_fd, \" \", AT_EMPTY_PATH, 0, &buf)"); + else + tst_brk(TFAIL | TTERRNO, + "statx(file_fd, \" \", AT_EMPTY_PATH, 0, &buff)"); + + if (buf.stx_size == SIZE) + tst_res(TPASS, + "stx_size(%llu) obtained is correct", buf.stx_size); + else + tst_res(TFAIL, + "stx_size(%llu) obtained is not same as expected(%u)", + buf.stx_size, SIZE); + +} + +static void test_sym_link(void) +{ + struct statx fbuf; + struct statx lbuf; + + TEST(statx(AT_FDCWD, TESTFILE, 0, 0, &fbuf)); + + if (TST_RET == 0) + tst_res(TPASS, + "statx(AT_FDCWD, %s, 0, 0, &fbuf)", TESTFILE); + else + tst_brk(TFAIL | TTERRNO, + "statx(AT_FDCWD, %s, 0, 0, &fbuf)", TESTFILE); + + TEST(statx(AT_FDCWD, LINK_FILE, AT_SYMLINK_NOFOLLOW, 0, &lbuf)); + + if (TST_RET == 0) + tst_res(TPASS, + "statx(AT_FDCWD, %s, AT_SYMLINK_NOFOLLOW, 0,&lbuf)", + LINK_FILE); + else + tst_brk(TFAIL | TTERRNO, + "statx(AT_FDCWD, %s, AT_SYMLINK_NOFOLLOW, 0,&lbuf)", + LINK_FILE); + + if (fbuf.stx_ino != lbuf.stx_ino) + tst_res(TPASS, "Statx symlink flag worked as expected"); + else + tst_res(TFAIL, + "Statx symlink flag failed to work as expected"); +} + +struct tcase { + void (*tfunc)(void); +} tcases[] = { + {&test_empty_path}, + {&test_sym_link} +}; + +static void run(unsigned int i) +{ + struct tcase *t; + + t = &tcases[i]; + t->tfunc(); +} + +static void setup(void) +{ + char data_buf[SIZE] = "LinusTorvalds"; + + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, MODE); + SAFE_WRITE(0, file_fd, data_buf, sizeof(data_buf)); + + SAFE_SYMLINK(TESTFILE, LINK_FILE); +} + +static void cleanup(void) +{ + if (file_fd > 0) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .cleanup = cleanup, + .min_kver = "4.11", + .needs_tmpdir = 1, +}; diff --git a/testcases/kernel/syscalls/statx/statx03.c b/testcases/kernel/syscalls/statx/statx03.c new file mode 100644 index 000000000..9b36afe5d --- /dev/null +++ b/testcases/kernel/syscalls/statx/statx03.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0 or later +/* + * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 + * Email: code@zilogic.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Test statx + * + * This code tests if expected error values are returned for specific cases by + * statx. + * The error cases are simulated and the return value is checked against + * expected error number value. + * The following error values are tested: + * 1) EBADF - Bad file descriptor + * 2) EFAULT - Bad address + * 3) EINVAL - Invalid argument + * 4) ENOENT - No such file or directory + * 5) ENOTDIR - Not a directory + * 6) ENAMETOOLONG - Filename too long + * + * Error scenario is simulated for each listed flag by passing + * respective arguments. + * The obtained error flag is checked against the expected + * flag value for that scenario. + * + * Minimum Kernel version required is 4.11. + */ +#include +#include +#include +#include "tst_test.h" +#include "tst_safe_macros.h" +#include "lapi/sys_statx.h" +#include "tst_get_bad_addr.h" + +#define TESTFILE "test_file" +#define MODE 0644 + +static int file_fd; +static char long_pathname[257]; + +static char *test_fname = TESTFILE; +static char *efault_fname; +static char *empty_fname = ""; +static char *etoolong_fname = long_pathname; + +static struct test_case { + uint32_t dfd; + char **filename; + uint32_t flag; + uint32_t mask; + int32_t errnum; +} tcases[] = { + {.dfd = -1, .filename = &test_fname, .flag = 0, + .mask = 0, .errnum = EBADF}, + + {.dfd = AT_FDCWD, .filename = &efault_fname, .flag = 0, + .mask = 0, .errnum = EFAULT}, + + {.dfd = AT_FDCWD, .filename = &test_fname, .flag = -1, + .mask = 0, .errnum = EINVAL}, + + {.dfd = AT_FDCWD, .filename = &test_fname, .flag = 0, + .mask = -1, .errnum = EINVAL}, + + {.dfd = AT_FDCWD, .filename = &empty_fname, .flag = 0, + .mask = 0, .errnum = ENOENT}, + + {.dfd = 1, .filename = &test_fname, .flag = 0, + .mask = 0, .errnum = ENOTDIR}, + + {.dfd = AT_FDCWD, .filename = &etoolong_fname, .flag = 0, + .mask = 0, .errnum = ENAMETOOLONG}, +}; + +static void run_test(unsigned int i) +{ + struct statx buf; + struct test_case *tc = &tcases[i]; + + TEST(statx(tc->dfd, *(tc->filename), tc->flag, + tc->mask, &buf)); + + if (TST_RET != -1) { + tst_res(TFAIL, "statx() returned with %ld", TST_RET); + return; + } + + if (tc->errnum == TST_ERR) { + tst_res(TPASS | TTERRNO, "statx() failed with"); + return; + } + + tst_res(TFAIL | TTERRNO, + "statx() should fail with %s", tst_strerrno(tc->errnum)); +} + +static void setup(void) +{ + file_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, MODE); + + memset(long_pathname, '@', sizeof(long_pathname)); + long_pathname[sizeof(long_pathname) - 1] = 0; + + efault_fname = tst_get_bad_addr(NULL); +} + +static void cleanup(void) +{ + if (file_fd > 0) + SAFE_CLOSE(file_fd); +} + +static struct tst_test test = { + .tcnt = ARRAY_SIZE(tcases), + .test = run_test, + .setup = setup, + .cleanup = cleanup, + .min_kver = "4.11", + .needs_tmpdir = 1, +}; diff --git a/testcases/kernel/syscalls/statx/statx04.c b/testcases/kernel/syscalls/statx/statx04.c new file mode 100644 index 000000000..9ffdb92f3 --- /dev/null +++ b/testcases/kernel/syscalls/statx/statx04.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0 or later +/* + * Copyright (c) Zilogic Systems Pvt. Ltd., 2018 + * Email: code@zilogic.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Test statx + * + * This code tests the functionality of statx system call. + * This code tests if the attributes field of statx received expected value. + * File set with following flags by using SAFE_IOCTL and e4crypt: + * 1) STATX_ATTR_COMPRESSED - The file is compressed by the filesystem. + * 2) STATX_ATTR_IMMUTABLE - The file cannot be modified. + * 3) STATX_ATTR_APPEND - The file can only be opened in append mode for + * writing. + * 4) STATX_ATTR_NODUMP - File is not a candidate for backup when a backup + * program such as dump(8) is run. + * 5) STATX_ATTR_ENCRYPTED - A key is required for the file to be encrypted by + * the filesystem. + * + * A test directory is created with flags added to it. + * + * SAFE_IOCTL() is used to modify the atttributes of the directory such as + * compressed, append, nodump and immutable. + * + * e4crypt is used to set the encrypt flag. + * + * Two directory are tested. + * First directory has all flags set. + * Second directory has no flags set. + * + * Minimum kernel version required is 4.11. + */ + +#include "tst_test.h" +#include "lapi/sys_statx.h" +#include "lapi/fs.h" +#include + +#define MOUNT_POINT "mnt_point" +#define TESTDIR_FLAGGED MOUNT_POINT"/test_dir1" +#define TESTDIR_UNFLAGGED MOUNT_POINT"/test_dir2" +#define COMMAND_NOT_FOUND 127 + +static int encrypt_flag; + +static void test_flagged(void) +{ + struct statx buf; + + TEST(statx(AT_FDCWD, TESTDIR_FLAGGED, 0, 0, &buf)); + if (TST_RET == 0) + tst_res(TPASS, + "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_FLAGGED); + else + tst_brk(TFAIL | TTERRNO, + "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_FLAGGED); + + if (buf.stx_attributes & STATX_ATTR_COMPRESSED) + tst_res(TPASS, "STATX_ATTR_COMPRESSED flag is set"); + else + tst_res(TFAIL, + "STATX_ATTR_COMPRESSED flag is not set"); + + if (buf.stx_attributes & STATX_ATTR_APPEND) + tst_res(TPASS, "STATX_ATTR_APPEND flag is set"); + else + tst_res(TFAIL, + "STATX_ATTR_APPEND flag is not set"); + + if (buf.stx_attributes & STATX_ATTR_IMMUTABLE) + tst_res(TPASS, "STATX_ATTR_IMMUTABLE flag is set"); + else + tst_res(TFAIL, + "STATX_ATTR_IMMUTABLE flag is not set"); + + if (buf.stx_attributes & STATX_ATTR_NODUMP) + tst_res(TPASS, "STATX_ATTR_NODUMP flag is set"); + else + tst_res(TFAIL, + "STATX_ATTR_NODUMP flag is not set"); + + if (buf.stx_attributes & STATX_ATTR_ENCRYPTED) + tst_res(TPASS, "STATX_ATTR_ENCRYPTED flag is set"); + else if (encrypt_flag == 1) + tst_res(TCONF, "e4crypt tool not available"); + else + tst_res(TFAIL, + "STATX_ATTR_ENCRYPTED flag is not set"); +} + +static void test_unflagged(void) +{ + struct statx buf; + + TEST(statx(AT_FDCWD, TESTDIR_UNFLAGGED, 0, 0, &buf)); + if (TST_RET == 0) + tst_res(TPASS, + "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", + TESTDIR_UNFLAGGED); + else + tst_brk(TFAIL | TTERRNO, + "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", + TESTDIR_UNFLAGGED); + + if ((buf.stx_attributes & STATX_ATTR_COMPRESSED) == 0) + tst_res(TPASS, "STATX_ATTR_COMPRESSED flag is not set"); + else + tst_res(TFAIL, + "STATX_ATTR_COMPRESSED flag is set"); + + if ((buf.stx_attributes & STATX_ATTR_APPEND) == 0) + tst_res(TPASS, "STATX_ATTR_APPEND flag is not set"); + else + tst_res(TFAIL, + "STATX_ATTR_APPEND flag is set"); + + if ((buf.stx_attributes & STATX_ATTR_IMMUTABLE) == 0) + tst_res(TPASS, "STATX_ATTR_IMMUTABLE flag is not set"); + else + tst_res(TFAIL, + "STATX_ATTR_IMMUTABLE flag is set"); + + if ((buf.stx_attributes & STATX_ATTR_NODUMP) == 0) + tst_res(TPASS, "STATX_ATTR_NODUMP flag is not set"); + else + tst_res(TFAIL, + "STATX_ATTR_NODUMP flag is set"); + + if ((buf.stx_attributes & STATX_ATTR_ENCRYPTED) == 0) + tst_res(TPASS, "STATX_ATTR_ENCRYPTED flag is not set"); + else + tst_res(TFAIL, + "STATX_ATTR_ENCRYPTED flag is set"); +} + +struct test_cases { + void (*tfunc)(void); +} tcases[] = { + {&test_flagged}, + {&test_unflagged}, +}; + +static void run(unsigned int i) +{ + struct test_cases *tc = &tcases[i]; + + tc->tfunc(); +} + +static void caid_flags_setup(void) +{ + int fd; + int attr; + + fd = SAFE_OPEN(TESTDIR_FLAGGED, O_RDONLY | O_DIRECTORY); + + SAFE_IOCTL(fd, FS_IOC_GETFLAGS, &attr); + + attr |= FS_COMPR_FL | FS_APPEND_FL | FS_IMMUTABLE_FL | FS_NODUMP_FL; + + SAFE_IOCTL(fd, FS_IOC_SETFLAGS, &attr); + + SAFE_CLOSE(fd); +} + +static void encrypt_flag_setup(void) +{ + TEST(tst_system("echo qwery | e4crypt add_key "TESTDIR_FLAGGED)); + + if (TST_RET == 0) + tst_res(TINFO, "Encryption flag is added to %s", + TESTDIR_FLAGGED); + else + tst_res(TFAIL | TERRNO, + "Encryption flag failed to add to %s", TESTDIR_FLAGGED); + + if (WEXITSTATUS(TST_RET) == COMMAND_NOT_FOUND) + encrypt_flag = 1; +} + +static void setup(void) +{ + SAFE_MKDIR(TESTDIR_FLAGGED, 0777); + SAFE_MKDIR(TESTDIR_UNFLAGGED, 0777); + + encrypt_flag_setup(); + caid_flags_setup(); +} + +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .min_kver = "4.11", + .needs_root = 1, + .needs_device = 1, + .mntpoint = MOUNT_POINT, + .mount_device = 1, + .dev_fs_type = "ext4", + .dev_extra_opt = "-O encrypt", + .dev_min_size = 512, +};