1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) Zilogic Systems Pvt. Ltd., 2018
4 * Email: code@zilogic.com
5 */
6
7/*\
8 * [Description]
9 *
10 * Test statx syscall with STATX_ATTR_ENCRYPTED flag, setting a key is required
11 * for the file to be encrypted by the filesystem.
12 *
13 * e4crypt is used to set the encrypt flag (currently supported only by ext4).
14 *
15 * Two directories are tested.
16 * First directory has all flags set.
17 * Second directory has no flags set.
18 *
19 * Minimum e2fsprogs version required is 1.43.
20 */
21
22#define _GNU_SOURCE
23#include <stdlib.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <sys/wait.h>
27#include "tst_test.h"
28#include "lapi/fs.h"
29#include "lapi/stat.h"
30#include "lapi/fcntl.h"
31
32#define MNTPOINT "mnt_point"
33#define TESTDIR_FLAGGED MNTPOINT"/test_dir1"
34#define TESTDIR_UNFLAGGED MNTPOINT"/test_dir2"
35
36static int mount_flag;
37
38static void test_flagged(void)
39{
40	struct statx buf;
41
42	TEST(statx(AT_FDCWD, TESTDIR_FLAGGED, 0, 0, &buf));
43	if (TST_RET == 0)
44		tst_res(TPASS,
45			"sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_FLAGGED);
46	else
47		tst_brk(TFAIL | TTERRNO,
48			"sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_FLAGGED);
49
50	if (buf.stx_attributes & STATX_ATTR_ENCRYPTED)
51		tst_res(TPASS, "STATX_ATTR_ENCRYPTED flag is set");
52	else
53		tst_res(TFAIL, "STATX_ATTR_ENCRYPTED flag is not set");
54}
55
56static void test_unflagged(void)
57{
58	struct statx buf;
59
60	TEST(statx(AT_FDCWD, TESTDIR_UNFLAGGED, 0, 0, &buf));
61	if (TST_RET == 0)
62		tst_res(TPASS,
63			"sys_statx(AT_FDCWD, %s, 0, 0, &buf)",
64			TESTDIR_UNFLAGGED);
65	else
66		tst_brk(TFAIL | TTERRNO,
67			"sys_statx(AT_FDCWD, %s, 0, 0, &buf)",
68			TESTDIR_UNFLAGGED);
69
70	if ((buf.stx_attributes & STATX_ATTR_ENCRYPTED) == 0)
71		tst_res(TPASS, "STATX_ATTR_ENCRYPTED flag is not set");
72	else
73		tst_res(TFAIL, "STATX_ATTR_ENCRYPTED flag is set");
74}
75
76static struct test_cases {
77	void (*tfunc)(void);
78} tcases[] = {
79	{&test_flagged},
80	{&test_unflagged},
81};
82
83static void run(unsigned int i)
84{
85	tcases[i].tfunc();
86}
87
88static void setup(void)
89{
90	char opt_bsize[32];
91	const char *const fs_opts[] = {"-O encrypt", opt_bsize, NULL};
92	int ret;
93
94	snprintf(opt_bsize, sizeof(opt_bsize), "-b %i", getpagesize());
95
96	SAFE_MKFS(tst_device->dev, tst_device->fs_type, fs_opts, NULL);
97	SAFE_MOUNT(tst_device->dev, MNTPOINT, tst_device->fs_type, 0, 0);
98	mount_flag = 1;
99
100	SAFE_MKDIR(TESTDIR_FLAGGED, 0777);
101	SAFE_MKDIR(TESTDIR_UNFLAGGED, 0777);
102
103	ret = tst_system("echo qwery | e4crypt add_key "TESTDIR_FLAGGED);
104
105	if (ret)
106		tst_brk(TCONF, "e4crypt failed (CONFIG_EXT4_ENCRYPTION not set?)");
107}
108
109static void cleanup(void)
110{
111	if (mount_flag)
112		tst_umount(MNTPOINT);
113}
114
115static struct tst_test test = {
116	.test = run,
117	.tcnt = ARRAY_SIZE(tcases),
118	.setup = setup,
119	.cleanup = cleanup,
120	.min_kver = "4.11",
121	.needs_root = 1,
122	.needs_device = 1,
123	.mntpoint = MNTPOINT,
124	.dev_fs_type = "ext4",
125	.needs_cmds = (const char *[]) {
126		"mkfs.ext4 >= 1.43.0",
127		"e4crypt",
128		NULL
129	}
130};
131