162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#define _GNU_SOURCE
362306a36Sopenharmony_ci#include <sched.h>
462306a36Sopenharmony_ci#include <stdio.h>
562306a36Sopenharmony_ci#include <errno.h>
662306a36Sopenharmony_ci#include <string.h>
762306a36Sopenharmony_ci#include <sys/types.h>
862306a36Sopenharmony_ci#include <sys/mount.h>
962306a36Sopenharmony_ci#include <sys/wait.h>
1062306a36Sopenharmony_ci#include <sys/vfs.h>
1162306a36Sopenharmony_ci#include <sys/statvfs.h>
1262306a36Sopenharmony_ci#include <stdlib.h>
1362306a36Sopenharmony_ci#include <unistd.h>
1462306a36Sopenharmony_ci#include <fcntl.h>
1562306a36Sopenharmony_ci#include <grp.h>
1662306a36Sopenharmony_ci#include <stdbool.h>
1762306a36Sopenharmony_ci#include <stdarg.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#ifndef CLONE_NEWNS
2062306a36Sopenharmony_ci# define CLONE_NEWNS 0x00020000
2162306a36Sopenharmony_ci#endif
2262306a36Sopenharmony_ci#ifndef CLONE_NEWUTS
2362306a36Sopenharmony_ci# define CLONE_NEWUTS 0x04000000
2462306a36Sopenharmony_ci#endif
2562306a36Sopenharmony_ci#ifndef CLONE_NEWIPC
2662306a36Sopenharmony_ci# define CLONE_NEWIPC 0x08000000
2762306a36Sopenharmony_ci#endif
2862306a36Sopenharmony_ci#ifndef CLONE_NEWNET
2962306a36Sopenharmony_ci# define CLONE_NEWNET 0x40000000
3062306a36Sopenharmony_ci#endif
3162306a36Sopenharmony_ci#ifndef CLONE_NEWUSER
3262306a36Sopenharmony_ci# define CLONE_NEWUSER 0x10000000
3362306a36Sopenharmony_ci#endif
3462306a36Sopenharmony_ci#ifndef CLONE_NEWPID
3562306a36Sopenharmony_ci# define CLONE_NEWPID 0x20000000
3662306a36Sopenharmony_ci#endif
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#ifndef MS_REC
3962306a36Sopenharmony_ci# define MS_REC 16384
4062306a36Sopenharmony_ci#endif
4162306a36Sopenharmony_ci#ifndef MS_RELATIME
4262306a36Sopenharmony_ci# define MS_RELATIME (1 << 21)
4362306a36Sopenharmony_ci#endif
4462306a36Sopenharmony_ci#ifndef MS_STRICTATIME
4562306a36Sopenharmony_ci# define MS_STRICTATIME (1 << 24)
4662306a36Sopenharmony_ci#endif
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic void die(char *fmt, ...)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	va_list ap;
5162306a36Sopenharmony_ci	va_start(ap, fmt);
5262306a36Sopenharmony_ci	vfprintf(stderr, fmt, ap);
5362306a36Sopenharmony_ci	va_end(ap);
5462306a36Sopenharmony_ci	exit(EXIT_FAILURE);
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	char buf[4096];
6062306a36Sopenharmony_ci	int fd;
6162306a36Sopenharmony_ci	ssize_t written;
6262306a36Sopenharmony_ci	int buf_len;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
6562306a36Sopenharmony_ci	if (buf_len < 0) {
6662306a36Sopenharmony_ci		die("vsnprintf failed: %s\n",
6762306a36Sopenharmony_ci		    strerror(errno));
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci	if (buf_len >= sizeof(buf)) {
7062306a36Sopenharmony_ci		die("vsnprintf output truncated\n");
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	fd = open(filename, O_WRONLY);
7462306a36Sopenharmony_ci	if (fd < 0) {
7562306a36Sopenharmony_ci		if ((errno == ENOENT) && enoent_ok)
7662306a36Sopenharmony_ci			return;
7762306a36Sopenharmony_ci		die("open of %s failed: %s\n",
7862306a36Sopenharmony_ci		    filename, strerror(errno));
7962306a36Sopenharmony_ci	}
8062306a36Sopenharmony_ci	written = write(fd, buf, buf_len);
8162306a36Sopenharmony_ci	if (written != buf_len) {
8262306a36Sopenharmony_ci		if (written >= 0) {
8362306a36Sopenharmony_ci			die("short write to %s\n", filename);
8462306a36Sopenharmony_ci		} else {
8562306a36Sopenharmony_ci			die("write to %s failed: %s\n",
8662306a36Sopenharmony_ci				filename, strerror(errno));
8762306a36Sopenharmony_ci		}
8862306a36Sopenharmony_ci	}
8962306a36Sopenharmony_ci	if (close(fd) != 0) {
9062306a36Sopenharmony_ci		die("close of %s failed: %s\n",
9162306a36Sopenharmony_ci			filename, strerror(errno));
9262306a36Sopenharmony_ci	}
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic void maybe_write_file(char *filename, char *fmt, ...)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	va_list ap;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	va_start(ap, fmt);
10062306a36Sopenharmony_ci	vmaybe_write_file(true, filename, fmt, ap);
10162306a36Sopenharmony_ci	va_end(ap);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic void write_file(char *filename, char *fmt, ...)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	va_list ap;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	va_start(ap, fmt);
11062306a36Sopenharmony_ci	vmaybe_write_file(false, filename, fmt, ap);
11162306a36Sopenharmony_ci	va_end(ap);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic int read_mnt_flags(const char *path)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	int ret;
11862306a36Sopenharmony_ci	struct statvfs stat;
11962306a36Sopenharmony_ci	int mnt_flags;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	ret = statvfs(path, &stat);
12262306a36Sopenharmony_ci	if (ret != 0) {
12362306a36Sopenharmony_ci		die("statvfs of %s failed: %s\n",
12462306a36Sopenharmony_ci			path, strerror(errno));
12562306a36Sopenharmony_ci	}
12662306a36Sopenharmony_ci	if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | \
12762306a36Sopenharmony_ci			ST_NOEXEC | ST_NOATIME | ST_NODIRATIME | ST_RELATIME | \
12862306a36Sopenharmony_ci			ST_SYNCHRONOUS | ST_MANDLOCK)) {
12962306a36Sopenharmony_ci		die("Unrecognized mount flags\n");
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci	mnt_flags = 0;
13262306a36Sopenharmony_ci	if (stat.f_flag & ST_RDONLY)
13362306a36Sopenharmony_ci		mnt_flags |= MS_RDONLY;
13462306a36Sopenharmony_ci	if (stat.f_flag & ST_NOSUID)
13562306a36Sopenharmony_ci		mnt_flags |= MS_NOSUID;
13662306a36Sopenharmony_ci	if (stat.f_flag & ST_NODEV)
13762306a36Sopenharmony_ci		mnt_flags |= MS_NODEV;
13862306a36Sopenharmony_ci	if (stat.f_flag & ST_NOEXEC)
13962306a36Sopenharmony_ci		mnt_flags |= MS_NOEXEC;
14062306a36Sopenharmony_ci	if (stat.f_flag & ST_NOATIME)
14162306a36Sopenharmony_ci		mnt_flags |= MS_NOATIME;
14262306a36Sopenharmony_ci	if (stat.f_flag & ST_NODIRATIME)
14362306a36Sopenharmony_ci		mnt_flags |= MS_NODIRATIME;
14462306a36Sopenharmony_ci	if (stat.f_flag & ST_RELATIME)
14562306a36Sopenharmony_ci		mnt_flags |= MS_RELATIME;
14662306a36Sopenharmony_ci	if (stat.f_flag & ST_SYNCHRONOUS)
14762306a36Sopenharmony_ci		mnt_flags |= MS_SYNCHRONOUS;
14862306a36Sopenharmony_ci	if (stat.f_flag & ST_MANDLOCK)
14962306a36Sopenharmony_ci		mnt_flags |= ST_MANDLOCK;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	return mnt_flags;
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic void create_and_enter_userns(void)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	uid_t uid;
15762306a36Sopenharmony_ci	gid_t gid;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	uid = getuid();
16062306a36Sopenharmony_ci	gid = getgid();
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	if (unshare(CLONE_NEWUSER) !=0) {
16362306a36Sopenharmony_ci		die("unshare(CLONE_NEWUSER) failed: %s\n",
16462306a36Sopenharmony_ci			strerror(errno));
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	maybe_write_file("/proc/self/setgroups", "deny");
16862306a36Sopenharmony_ci	write_file("/proc/self/uid_map", "0 %d 1", uid);
16962306a36Sopenharmony_ci	write_file("/proc/self/gid_map", "0 %d 1", gid);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	if (setgid(0) != 0) {
17262306a36Sopenharmony_ci		die ("setgid(0) failed %s\n",
17362306a36Sopenharmony_ci			strerror(errno));
17462306a36Sopenharmony_ci	}
17562306a36Sopenharmony_ci	if (setuid(0) != 0) {
17662306a36Sopenharmony_ci		die("setuid(0) failed %s\n",
17762306a36Sopenharmony_ci			strerror(errno));
17862306a36Sopenharmony_ci	}
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic
18262306a36Sopenharmony_cibool test_unpriv_remount(const char *fstype, const char *mount_options,
18362306a36Sopenharmony_ci			 int mount_flags, int remount_flags, int invalid_flags)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	pid_t child;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	child = fork();
18862306a36Sopenharmony_ci	if (child == -1) {
18962306a36Sopenharmony_ci		die("fork failed: %s\n",
19062306a36Sopenharmony_ci			strerror(errno));
19162306a36Sopenharmony_ci	}
19262306a36Sopenharmony_ci	if (child != 0) { /* parent */
19362306a36Sopenharmony_ci		pid_t pid;
19462306a36Sopenharmony_ci		int status;
19562306a36Sopenharmony_ci		pid = waitpid(child, &status, 0);
19662306a36Sopenharmony_ci		if (pid == -1) {
19762306a36Sopenharmony_ci			die("waitpid failed: %s\n",
19862306a36Sopenharmony_ci				strerror(errno));
19962306a36Sopenharmony_ci		}
20062306a36Sopenharmony_ci		if (pid != child) {
20162306a36Sopenharmony_ci			die("waited for %d got %d\n",
20262306a36Sopenharmony_ci				child, pid);
20362306a36Sopenharmony_ci		}
20462306a36Sopenharmony_ci		if (!WIFEXITED(status)) {
20562306a36Sopenharmony_ci			die("child did not terminate cleanly\n");
20662306a36Sopenharmony_ci		}
20762306a36Sopenharmony_ci		return WEXITSTATUS(status) == EXIT_SUCCESS;
20862306a36Sopenharmony_ci	}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	create_and_enter_userns();
21162306a36Sopenharmony_ci	if (unshare(CLONE_NEWNS) != 0) {
21262306a36Sopenharmony_ci		die("unshare(CLONE_NEWNS) failed: %s\n",
21362306a36Sopenharmony_ci			strerror(errno));
21462306a36Sopenharmony_ci	}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	if (mount("testing", "/tmp", fstype, mount_flags, mount_options) != 0) {
21762306a36Sopenharmony_ci		die("mount of %s with options '%s' on /tmp failed: %s\n",
21862306a36Sopenharmony_ci		    fstype,
21962306a36Sopenharmony_ci		    mount_options? mount_options : "",
22062306a36Sopenharmony_ci		    strerror(errno));
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	create_and_enter_userns();
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	if (unshare(CLONE_NEWNS) != 0) {
22662306a36Sopenharmony_ci		die("unshare(CLONE_NEWNS) failed: %s\n",
22762306a36Sopenharmony_ci			strerror(errno));
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	if (mount("/tmp", "/tmp", "none",
23162306a36Sopenharmony_ci		  MS_REMOUNT | MS_BIND | remount_flags, NULL) != 0) {
23262306a36Sopenharmony_ci		/* system("cat /proc/self/mounts"); */
23362306a36Sopenharmony_ci		die("remount of /tmp failed: %s\n",
23462306a36Sopenharmony_ci		    strerror(errno));
23562306a36Sopenharmony_ci	}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	if (mount("/tmp", "/tmp", "none",
23862306a36Sopenharmony_ci		  MS_REMOUNT | MS_BIND | invalid_flags, NULL) == 0) {
23962306a36Sopenharmony_ci		/* system("cat /proc/self/mounts"); */
24062306a36Sopenharmony_ci		die("remount of /tmp with invalid flags "
24162306a36Sopenharmony_ci		    "succeeded unexpectedly\n");
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci	exit(EXIT_SUCCESS);
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic bool test_unpriv_remount_simple(int mount_flags)
24762306a36Sopenharmony_ci{
24862306a36Sopenharmony_ci	return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, 0);
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic bool test_unpriv_remount_atime(int mount_flags, int invalid_flags)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags,
25462306a36Sopenharmony_ci				   invalid_flags);
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistatic bool test_priv_mount_unpriv_remount(void)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	pid_t child;
26062306a36Sopenharmony_ci	int ret;
26162306a36Sopenharmony_ci	const char *orig_path = "/dev";
26262306a36Sopenharmony_ci	const char *dest_path = "/tmp";
26362306a36Sopenharmony_ci	int orig_mnt_flags, remount_mnt_flags;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	child = fork();
26662306a36Sopenharmony_ci	if (child == -1) {
26762306a36Sopenharmony_ci		die("fork failed: %s\n",
26862306a36Sopenharmony_ci			strerror(errno));
26962306a36Sopenharmony_ci	}
27062306a36Sopenharmony_ci	if (child != 0) { /* parent */
27162306a36Sopenharmony_ci		pid_t pid;
27262306a36Sopenharmony_ci		int status;
27362306a36Sopenharmony_ci		pid = waitpid(child, &status, 0);
27462306a36Sopenharmony_ci		if (pid == -1) {
27562306a36Sopenharmony_ci			die("waitpid failed: %s\n",
27662306a36Sopenharmony_ci				strerror(errno));
27762306a36Sopenharmony_ci		}
27862306a36Sopenharmony_ci		if (pid != child) {
27962306a36Sopenharmony_ci			die("waited for %d got %d\n",
28062306a36Sopenharmony_ci				child, pid);
28162306a36Sopenharmony_ci		}
28262306a36Sopenharmony_ci		if (!WIFEXITED(status)) {
28362306a36Sopenharmony_ci			die("child did not terminate cleanly\n");
28462306a36Sopenharmony_ci		}
28562306a36Sopenharmony_ci		return WEXITSTATUS(status) == EXIT_SUCCESS;
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	orig_mnt_flags = read_mnt_flags(orig_path);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	create_and_enter_userns();
29162306a36Sopenharmony_ci	ret = unshare(CLONE_NEWNS);
29262306a36Sopenharmony_ci	if (ret != 0) {
29362306a36Sopenharmony_ci		die("unshare(CLONE_NEWNS) failed: %s\n",
29462306a36Sopenharmony_ci			strerror(errno));
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	ret = mount(orig_path, dest_path, "bind", MS_BIND | MS_REC, NULL);
29862306a36Sopenharmony_ci	if (ret != 0) {
29962306a36Sopenharmony_ci		die("recursive bind mount of %s onto %s failed: %s\n",
30062306a36Sopenharmony_ci			orig_path, dest_path, strerror(errno));
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	ret = mount(dest_path, dest_path, "none",
30462306a36Sopenharmony_ci		    MS_REMOUNT | MS_BIND | orig_mnt_flags , NULL);
30562306a36Sopenharmony_ci	if (ret != 0) {
30662306a36Sopenharmony_ci		/* system("cat /proc/self/mounts"); */
30762306a36Sopenharmony_ci		die("remount of /tmp failed: %s\n",
30862306a36Sopenharmony_ci		    strerror(errno));
30962306a36Sopenharmony_ci	}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	remount_mnt_flags = read_mnt_flags(dest_path);
31262306a36Sopenharmony_ci	if (orig_mnt_flags != remount_mnt_flags) {
31362306a36Sopenharmony_ci		die("Mount flags unexpectedly changed during remount of %s originally mounted on %s\n",
31462306a36Sopenharmony_ci			dest_path, orig_path);
31562306a36Sopenharmony_ci	}
31662306a36Sopenharmony_ci	exit(EXIT_SUCCESS);
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ciint main(int argc, char **argv)
32062306a36Sopenharmony_ci{
32162306a36Sopenharmony_ci	if (!test_unpriv_remount_simple(MS_RDONLY)) {
32262306a36Sopenharmony_ci		die("MS_RDONLY malfunctions\n");
32362306a36Sopenharmony_ci	}
32462306a36Sopenharmony_ci	if (!test_unpriv_remount("devpts", "newinstance", MS_NODEV, MS_NODEV, 0)) {
32562306a36Sopenharmony_ci		die("MS_NODEV malfunctions\n");
32662306a36Sopenharmony_ci	}
32762306a36Sopenharmony_ci	if (!test_unpriv_remount_simple(MS_NOSUID)) {
32862306a36Sopenharmony_ci		die("MS_NOSUID malfunctions\n");
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci	if (!test_unpriv_remount_simple(MS_NOEXEC)) {
33162306a36Sopenharmony_ci		die("MS_NOEXEC malfunctions\n");
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci	if (!test_unpriv_remount_atime(MS_RELATIME,
33462306a36Sopenharmony_ci				       MS_NOATIME))
33562306a36Sopenharmony_ci	{
33662306a36Sopenharmony_ci		die("MS_RELATIME malfunctions\n");
33762306a36Sopenharmony_ci	}
33862306a36Sopenharmony_ci	if (!test_unpriv_remount_atime(MS_STRICTATIME,
33962306a36Sopenharmony_ci				       MS_NOATIME))
34062306a36Sopenharmony_ci	{
34162306a36Sopenharmony_ci		die("MS_STRICTATIME malfunctions\n");
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci	if (!test_unpriv_remount_atime(MS_NOATIME,
34462306a36Sopenharmony_ci				       MS_STRICTATIME))
34562306a36Sopenharmony_ci	{
34662306a36Sopenharmony_ci		die("MS_NOATIME malfunctions\n");
34762306a36Sopenharmony_ci	}
34862306a36Sopenharmony_ci	if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME,
34962306a36Sopenharmony_ci				       MS_NOATIME))
35062306a36Sopenharmony_ci	{
35162306a36Sopenharmony_ci		die("MS_RELATIME|MS_NODIRATIME malfunctions\n");
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci	if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME,
35462306a36Sopenharmony_ci				       MS_NOATIME))
35562306a36Sopenharmony_ci	{
35662306a36Sopenharmony_ci		die("MS_STRICTATIME|MS_NODIRATIME malfunctions\n");
35762306a36Sopenharmony_ci	}
35862306a36Sopenharmony_ci	if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME,
35962306a36Sopenharmony_ci				       MS_STRICTATIME))
36062306a36Sopenharmony_ci	{
36162306a36Sopenharmony_ci		die("MS_NOATIME|MS_DIRATIME malfunctions\n");
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci	if (!test_unpriv_remount("ramfs", NULL, MS_STRICTATIME, 0, MS_NOATIME))
36462306a36Sopenharmony_ci	{
36562306a36Sopenharmony_ci		die("Default atime malfunctions\n");
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci	if (!test_priv_mount_unpriv_remount()) {
36862306a36Sopenharmony_ci		die("Mount flags unexpectedly changed after remount\n");
36962306a36Sopenharmony_ci	}
37062306a36Sopenharmony_ci	return EXIT_SUCCESS;
37162306a36Sopenharmony_ci}
372