16f906eab90659aa74fbd44d545e276c56362f43frobbiew/*
26f906eab90659aa74fbd44d545e276c56362f43frobbiew * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
36f906eab90659aa74fbd44d545e276c56362f43frobbiew *
46f906eab90659aa74fbd44d545e276c56362f43frobbiew * This program is free software; you can redistribute it and/or modify it
56f906eab90659aa74fbd44d545e276c56362f43frobbiew * under the terms of version 2 of the GNU General Public License as
66f906eab90659aa74fbd44d545e276c56362f43frobbiew * published by the Free Software Foundation.
76f906eab90659aa74fbd44d545e276c56362f43frobbiew *
86f906eab90659aa74fbd44d545e276c56362f43frobbiew * This program is distributed in the hope that it would be useful, but
96f906eab90659aa74fbd44d545e276c56362f43frobbiew * WITHOUT ANY WARRANTY; without even the implied warranty of
106f906eab90659aa74fbd44d545e276c56362f43frobbiew * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
116f906eab90659aa74fbd44d545e276c56362f43frobbiew *
126f906eab90659aa74fbd44d545e276c56362f43frobbiew * You should have received a copy of the GNU General Public License along
13fed9641096e27f79a0f2d9adfe9839dd8d11dc0fWanlong Gao * with this program; if not, write the Free Software Foundation, Inc.,
14fed9641096e27f79a0f2d9adfe9839dd8d11dc0fWanlong Gao * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
156f906eab90659aa74fbd44d545e276c56362f43frobbiew *
166f906eab90659aa74fbd44d545e276c56362f43frobbiew */
176f906eab90659aa74fbd44d545e276c56362f43frobbiew/**********************************************************
184bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
196f906eab90659aa74fbd44d545e276c56362f43frobbiew *    TEST IDENTIFIER   : setresgid03
204bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
216f906eab90659aa74fbd44d545e276c56362f43frobbiew *    EXECUTED BY       : root / superuser
224bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
236f906eab90659aa74fbd44d545e276c56362f43frobbiew *    TEST TITLE        : Checking error conditions for setresgid(2)
244bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
256f906eab90659aa74fbd44d545e276c56362f43frobbiew *    TEST CASE TOTAL   : 4
264bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
276f906eab90659aa74fbd44d545e276c56362f43frobbiew *    AUTHOR            : Madhu T L <madhu.tarikere@wipro.com>
284bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
296f906eab90659aa74fbd44d545e276c56362f43frobbiew *    SIGNALS
306f906eab90659aa74fbd44d545e276c56362f43frobbiew *      Uses SIGUSR1 to pause before test if option set.
316f906eab90659aa74fbd44d545e276c56362f43frobbiew *      (See the parse_opts(3) man page).
326f906eab90659aa74fbd44d545e276c56362f43frobbiew *
336f906eab90659aa74fbd44d545e276c56362f43frobbiew *    DESCRIPTION
346f906eab90659aa74fbd44d545e276c56362f43frobbiew *      Verify that,
356f906eab90659aa74fbd44d545e276c56362f43frobbiew *	1. setresgid(2) fails with EPERM for unprivileged user in setting
366f906eab90659aa74fbd44d545e276c56362f43frobbiew *	   saved group id.
376f906eab90659aa74fbd44d545e276c56362f43frobbiew *	2. setresgid(2) fails with EPERM for unprivileged user in setting
386f906eab90659aa74fbd44d545e276c56362f43frobbiew *	   effective group id.
396f906eab90659aa74fbd44d545e276c56362f43frobbiew *	3. setresgid(2) fails with EPERM for unprivileged user in setting
406f906eab90659aa74fbd44d545e276c56362f43frobbiew *	   real group id.
416f906eab90659aa74fbd44d545e276c56362f43frobbiew *	4. setresgid(2) fails with EPERM for unprivileged user in setting
426f906eab90659aa74fbd44d545e276c56362f43frobbiew *	   real/effective/saved group id.
434bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
446f906eab90659aa74fbd44d545e276c56362f43frobbiew *      Setup:
456f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Setup signal handling.
466f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Test caller is superuser
476f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Check existence of user id's root/bin/nobody
486f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Set real/effective/saved gid to nobody
496f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Set effective uid to nobody
506f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Pause for SIGUSR1 if option specified.
514bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
526f906eab90659aa74fbd44d545e276c56362f43frobbiew *	Test:
536f906eab90659aa74fbd44d545e276c56362f43frobbiew *	 Loop if the proper options are given.
546f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Execute system call
556f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Check return value, errno and functionality, if success,
566f906eab90659aa74fbd44d545e276c56362f43frobbiew *		 Issue PASS message
576f906eab90659aa74fbd44d545e276c56362f43frobbiew *	Otherwise,
586f906eab90659aa74fbd44d545e276c56362f43frobbiew *		Issue FAIL message
594bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
606f906eab90659aa74fbd44d545e276c56362f43frobbiew *	Cleanup:
616f906eab90659aa74fbd44d545e276c56362f43frobbiew *	  Print errno log and/or timing stats if options given
624bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
636f906eab90659aa74fbd44d545e276c56362f43frobbiew * USAGE:  <for command-line>
646f906eab90659aa74fbd44d545e276c56362f43frobbiew *  setresgid03 [-c n] [-e] [-f] [-h] [-i n] [-I x] [-p] [-P x] [-t]
656f906eab90659aa74fbd44d545e276c56362f43frobbiew *		where,  -c n : Run n copies concurrently.
666f906eab90659aa74fbd44d545e276c56362f43frobbiew *			-e   : Turn on errno logging.
676f906eab90659aa74fbd44d545e276c56362f43frobbiew *			-f   : Turn off functional testing
686f906eab90659aa74fbd44d545e276c56362f43frobbiew *			-h   : Show help screen
696f906eab90659aa74fbd44d545e276c56362f43frobbiew *			-i n : Execute test n times.
706f906eab90659aa74fbd44d545e276c56362f43frobbiew *			-I x : Execute test for x seconds.
716f906eab90659aa74fbd44d545e276c56362f43frobbiew *			-p   : Pause for SIGUSR1 before starting
726f906eab90659aa74fbd44d545e276c56362f43frobbiew *			-P x : Pause for x seconds between iterations.
736f906eab90659aa74fbd44d545e276c56362f43frobbiew *			-t   : Turn on syscall timing.
744bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
756f906eab90659aa74fbd44d545e276c56362f43frobbiew ****************************************************************/
766f906eab90659aa74fbd44d545e276c56362f43frobbiew
77bed036a06374f3abca1c7cc3d246b1ed141c1a84vapier#define _GNU_SOURCE 1
786f906eab90659aa74fbd44d545e276c56362f43frobbiew#include <errno.h>
796f906eab90659aa74fbd44d545e276c56362f43frobbiew#include <pwd.h>
806f906eab90659aa74fbd44d545e276c56362f43frobbiew#include <sys/types.h>
816f906eab90659aa74fbd44d545e276c56362f43frobbiew#include <unistd.h>
826f906eab90659aa74fbd44d545e276c56362f43frobbiew#include "test.h"
8375fb057ebd66c8d8012ec5a53f1a187551296b00Han Pingtian#include "compat_16.h"
846f906eab90659aa74fbd44d545e276c56362f43frobbiew
856f906eab90659aa74fbd44d545e276c56362f43frobbiew#define EXP_RET_VAL	-1
866f906eab90659aa74fbd44d545e276c56362f43frobbiew#define EXP_ERRNO	EPERM
876f906eab90659aa74fbd44d545e276c56362f43frobbiew#define TEST_DESC	"unprivileged user"
886f906eab90659aa74fbd44d545e276c56362f43frobbiew
8956207cec7732e09c216c751c0b5f88a242bacae6subrata_modakstruct test_case_t {		/* test case structure */
9056207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	uid_t *rgid;		/* real GID */
9156207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	uid_t *egid;		/* effective GID */
9256207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	uid_t *sgid;		/* saved GID */
936f906eab90659aa74fbd44d545e276c56362f43frobbiew	struct passwd *exp_rgid;	/* Expected real GID */
946f906eab90659aa74fbd44d545e276c56362f43frobbiew	struct passwd *exp_egid;	/* Expected effective GID */
956f906eab90659aa74fbd44d545e276c56362f43frobbiew	struct passwd *exp_sgid;	/* Expected saved GID */
966f906eab90659aa74fbd44d545e276c56362f43frobbiew};
976f906eab90659aa74fbd44d545e276c56362f43frobbiew
9875fb057ebd66c8d8012ec5a53f1a187551296b00Han PingtianTCID_DEFINE(setresgid03);
996f906eab90659aa74fbd44d545e276c56362f43frobbiewstatic int testno;
1006f906eab90659aa74fbd44d545e276c56362f43frobbiewstatic struct passwd nobody, bin, root;
1016f906eab90659aa74fbd44d545e276c56362f43frobbiewstatic uid_t nobody_gid, bin_gid, neg = -1;
1026f906eab90659aa74fbd44d545e276c56362f43frobbiew
1036f906eab90659aa74fbd44d545e276c56362f43frobbiewstatic int test_functionality(uid_t, uid_t, uid_t);
1046f906eab90659aa74fbd44d545e276c56362f43frobbiewstatic void setup(void);
1056f906eab90659aa74fbd44d545e276c56362f43frobbiewstatic void cleanup(void);
1066f906eab90659aa74fbd44d545e276c56362f43frobbiew
10756207cec7732e09c216c751c0b5f88a242bacae6subrata_modakstatic struct test_case_t tdat[] = {
10856207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	{&neg, &neg, &bin.pw_gid, &nobody, &nobody, &nobody},
10956207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	{&neg, &bin.pw_gid, &neg, &nobody, &nobody, &nobody},
11056207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	{&bin.pw_gid, &neg, &neg, &nobody, &nobody, &nobody},
11156207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	{&bin.pw_gid, &bin.pw_gid, &bin.pw_gid, &nobody, &nobody, &nobody},
1126f906eab90659aa74fbd44d545e276c56362f43frobbiew};
1136f906eab90659aa74fbd44d545e276c56362f43frobbiew
1146f906eab90659aa74fbd44d545e276c56362f43frobbiewint TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
1156f906eab90659aa74fbd44d545e276c56362f43frobbiew
11656207cec7732e09c216c751c0b5f88a242bacae6subrata_modakint main(int argc, char **argv)
1176f906eab90659aa74fbd44d545e276c56362f43frobbiew{
11889af32a63ce8a780ea39337339e14caae244b5a4Cyril Hrubis	int lc;
1196f906eab90659aa74fbd44d545e276c56362f43frobbiew
120d6d11d08678aac1ed2c370ea8e42e5f45aea07beCyril Hrubis	tst_parse_opts(argc, argv, NULL, NULL);
1216f906eab90659aa74fbd44d545e276c56362f43frobbiew
1226f906eab90659aa74fbd44d545e276c56362f43frobbiew	setup();
1236f906eab90659aa74fbd44d545e276c56362f43frobbiew
1246f906eab90659aa74fbd44d545e276c56362f43frobbiew	for (lc = 0; TEST_LOOPING(lc); lc++) {
125d59a659cd639ca2780b00049d102acd2a783d585Caspar Zhang		/* reset tst_count in case we are looping */
126d59a659cd639ca2780b00049d102acd2a783d585Caspar Zhang		tst_count = 0;
1276f906eab90659aa74fbd44d545e276c56362f43frobbiew
1286f906eab90659aa74fbd44d545e276c56362f43frobbiew		for (testno = 0; testno < TST_TOTAL; ++testno) {
1296f906eab90659aa74fbd44d545e276c56362f43frobbiew
13075fb057ebd66c8d8012ec5a53f1a187551296b00Han Pingtian			TEST(SETRESGID(cleanup, *tdat[testno].rgid, *tdat[testno].egid,
13156207cec7732e09c216c751c0b5f88a242bacae6subrata_modak				       *tdat[testno].sgid));
1326f906eab90659aa74fbd44d545e276c56362f43frobbiew
13356207cec7732e09c216c751c0b5f88a242bacae6subrata_modak			if ((TEST_RETURN == EXP_RET_VAL) &&
13456207cec7732e09c216c751c0b5f88a242bacae6subrata_modak			    (TEST_ERRNO == EXP_ERRNO)) {
1356f906eab90659aa74fbd44d545e276c56362f43frobbiew
13656207cec7732e09c216c751c0b5f88a242bacae6subrata_modak				if (!test_functionality
13756207cec7732e09c216c751c0b5f88a242bacae6subrata_modak				    (tdat[testno].exp_rgid->pw_gid,
13856207cec7732e09c216c751c0b5f88a242bacae6subrata_modak				     tdat[testno].exp_egid->pw_gid,
13956207cec7732e09c216c751c0b5f88a242bacae6subrata_modak				     tdat[testno].exp_sgid->pw_gid)) {
1406f906eab90659aa74fbd44d545e276c56362f43frobbiew
1416f906eab90659aa74fbd44d545e276c56362f43frobbiew					tst_resm(TPASS, "setresgid() failed as "
14256207cec7732e09c216c751c0b5f88a242bacae6subrata_modak						 "expected for %s : errno %d",
14356207cec7732e09c216c751c0b5f88a242bacae6subrata_modak						 TEST_DESC, TEST_ERRNO);
1446f906eab90659aa74fbd44d545e276c56362f43frobbiew				} else {
1456f906eab90659aa74fbd44d545e276c56362f43frobbiew					tst_resm(TFAIL, "Functionality test "
14656207cec7732e09c216c751c0b5f88a242bacae6subrata_modak						 "for setresgid() for %s failed",
14756207cec7732e09c216c751c0b5f88a242bacae6subrata_modak						 TEST_DESC);
1486f906eab90659aa74fbd44d545e276c56362f43frobbiew				}
1496f906eab90659aa74fbd44d545e276c56362f43frobbiew
1506f906eab90659aa74fbd44d545e276c56362f43frobbiew			} else {
1516f906eab90659aa74fbd44d545e276c56362f43frobbiew				tst_resm(TFAIL, "setresgid() returned "
15256207cec7732e09c216c751c0b5f88a242bacae6subrata_modak					 "unexpected results for %s ; returned"
153b0b6f454a93242fc457249b6a22b7118c5479bf3vapier					 " %ld (expected %d), errno %d (expected"
154b0b6f454a93242fc457249b6a22b7118c5479bf3vapier					 " %d)", TEST_DESC,
15556207cec7732e09c216c751c0b5f88a242bacae6subrata_modak					 TEST_RETURN, EXP_RET_VAL, TEST_ERRNO,
15656207cec7732e09c216c751c0b5f88a242bacae6subrata_modak					 EXP_ERRNO);
1576f906eab90659aa74fbd44d545e276c56362f43frobbiew			}
1586f906eab90659aa74fbd44d545e276c56362f43frobbiew		}
1596f906eab90659aa74fbd44d545e276c56362f43frobbiew	}
1606f906eab90659aa74fbd44d545e276c56362f43frobbiew	cleanup();
1616f906eab90659aa74fbd44d545e276c56362f43frobbiew
16253740500924f6439623a8ac256b5be2d6c59ed1fGarrett Cooper	tst_exit();
1636f906eab90659aa74fbd44d545e276c56362f43frobbiew}
1646f906eab90659aa74fbd44d545e276c56362f43frobbiew
16556207cec7732e09c216c751c0b5f88a242bacae6subrata_modakstatic int test_functionality(uid_t exp_rgid, uid_t exp_egid, uid_t exp_sgid)
1666f906eab90659aa74fbd44d545e276c56362f43frobbiew{
1676f906eab90659aa74fbd44d545e276c56362f43frobbiew	uid_t cur_rgid, cur_egid, cur_sgid;
1686f906eab90659aa74fbd44d545e276c56362f43frobbiew
1696f906eab90659aa74fbd44d545e276c56362f43frobbiew	/* Get current real, effective and saved group id */
17056207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	if (getresgid(&cur_rgid, &cur_egid, &cur_sgid) == -1) {
1716f906eab90659aa74fbd44d545e276c56362f43frobbiew		tst_brkm(TBROK, cleanup, "getresgid() failed");
1722c28215423293e443469a07ae7011135d058b671Garrett Cooper
1736f906eab90659aa74fbd44d545e276c56362f43frobbiew	}
1746f906eab90659aa74fbd44d545e276c56362f43frobbiew
17556207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	if ((cur_rgid == exp_rgid) && (cur_egid == exp_egid)
17656207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	    && (cur_sgid == exp_sgid)) {
1776f906eab90659aa74fbd44d545e276c56362f43frobbiew		return 0;
1786f906eab90659aa74fbd44d545e276c56362f43frobbiew	}
1796f906eab90659aa74fbd44d545e276c56362f43frobbiew	return 1;
1806f906eab90659aa74fbd44d545e276c56362f43frobbiew}
1816f906eab90659aa74fbd44d545e276c56362f43frobbiew
1826f906eab90659aa74fbd44d545e276c56362f43frobbiew/*
1836f906eab90659aa74fbd44d545e276c56362f43frobbiew * setup()
1846f906eab90659aa74fbd44d545e276c56362f43frobbiew *	performs all ONE TIME setup for this test
1856f906eab90659aa74fbd44d545e276c56362f43frobbiew */
18656207cec7732e09c216c751c0b5f88a242bacae6subrata_modakvoid setup(void)
1876f906eab90659aa74fbd44d545e276c56362f43frobbiew{
1886f906eab90659aa74fbd44d545e276c56362f43frobbiew	struct passwd *passwd_p;
1896f906eab90659aa74fbd44d545e276c56362f43frobbiew
190d1e794d62b1bf619df8390535e4c2a58899b1145Cyril Hrubis	tst_require_root();
1916f906eab90659aa74fbd44d545e276c56362f43frobbiew
192d4ceb37d3ab506483612ef0ad74c88e5828a9779Nicolas Joly	tst_sig(NOFORK, DEF_HANDLER, cleanup);
1936f906eab90659aa74fbd44d545e276c56362f43frobbiew
19456207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	if ((passwd_p = getpwnam("root")) == NULL) {
19553740500924f6439623a8ac256b5be2d6c59ed1fGarrett Cooper		tst_brkm(TBROK, NULL, "getpwnam() failed for root");
1962c28215423293e443469a07ae7011135d058b671Garrett Cooper
1976f906eab90659aa74fbd44d545e276c56362f43frobbiew	}
1986f906eab90659aa74fbd44d545e276c56362f43frobbiew	root = *passwd_p;
1996f906eab90659aa74fbd44d545e276c56362f43frobbiew
20056207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	if ((passwd_p = getpwnam("bin")) == NULL) {
20153740500924f6439623a8ac256b5be2d6c59ed1fGarrett Cooper		tst_brkm(TBROK, NULL, "bin user id doesn't exist");
2022c28215423293e443469a07ae7011135d058b671Garrett Cooper
2036f906eab90659aa74fbd44d545e276c56362f43frobbiew	}
2046f906eab90659aa74fbd44d545e276c56362f43frobbiew	bin = *passwd_p;
20575fb057ebd66c8d8012ec5a53f1a187551296b00Han Pingtian	GID16_CHECK((bin_gid = bin.pw_gid), "setresgid", cleanup)
2066f906eab90659aa74fbd44d545e276c56362f43frobbiew
20756207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	if ((passwd_p = getpwnam("nobody")) == NULL) {
20853740500924f6439623a8ac256b5be2d6c59ed1fGarrett Cooper		tst_brkm(TBROK, NULL, "nobody user id doesn't exist");
2092c28215423293e443469a07ae7011135d058b671Garrett Cooper
2106f906eab90659aa74fbd44d545e276c56362f43frobbiew	}
2116f906eab90659aa74fbd44d545e276c56362f43frobbiew	nobody = *passwd_p;
21275fb057ebd66c8d8012ec5a53f1a187551296b00Han Pingtian	GID16_CHECK((nobody_gid = nobody.pw_gid), "setresgid", cleanup)
2136f906eab90659aa74fbd44d545e276c56362f43frobbiew
2146f906eab90659aa74fbd44d545e276c56362f43frobbiew	/* Set real/effective/saved gid to nobody */
21556207cec7732e09c216c751c0b5f88a242bacae6subrata_modak	if (setresgid(nobody_gid, nobody_gid, nobody_gid) == -1) {
21653740500924f6439623a8ac256b5be2d6c59ed1fGarrett Cooper		tst_brkm(TBROK, NULL, "setup() failed for setting while"
21756207cec7732e09c216c751c0b5f88a242bacae6subrata_modak			 " setting real/effective/saved gid");
2186f906eab90659aa74fbd44d545e276c56362f43frobbiew	}
2196f906eab90659aa74fbd44d545e276c56362f43frobbiew	/* Set euid to nobody */
2206f906eab90659aa74fbd44d545e276c56362f43frobbiew	if (setuid(nobody.pw_uid) == -1) {
22153740500924f6439623a8ac256b5be2d6c59ed1fGarrett Cooper		tst_brkm(TBROK, NULL, "setuid failed to "
22256207cec7732e09c216c751c0b5f88a242bacae6subrata_modak			 "to set the effective uid to nodody");
2232c28215423293e443469a07ae7011135d058b671Garrett Cooper
2246f906eab90659aa74fbd44d545e276c56362f43frobbiew	}
2256f906eab90659aa74fbd44d545e276c56362f43frobbiew	/* Pause if that option was specified
2266f906eab90659aa74fbd44d545e276c56362f43frobbiew	 * TEST_PAUSE contains the code to fork the test with the -c option.
2276f906eab90659aa74fbd44d545e276c56362f43frobbiew	 */
2286f906eab90659aa74fbd44d545e276c56362f43frobbiew	TEST_PAUSE;
2296f906eab90659aa74fbd44d545e276c56362f43frobbiew}
2306f906eab90659aa74fbd44d545e276c56362f43frobbiew
2316f906eab90659aa74fbd44d545e276c56362f43frobbiew/*
2326f906eab90659aa74fbd44d545e276c56362f43frobbiew * cleanup()
2336f906eab90659aa74fbd44d545e276c56362f43frobbiew *	performs all ONE TIME cleanup for this test at
2346f906eab90659aa74fbd44d545e276c56362f43frobbiew *	completion or premature exit
2356f906eab90659aa74fbd44d545e276c56362f43frobbiew */
23656207cec7732e09c216c751c0b5f88a242bacae6subrata_modakvoid cleanup(void)
2376f906eab90659aa74fbd44d545e276c56362f43frobbiew{
2386f906eab90659aa74fbd44d545e276c56362f43frobbiew
239354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao}
240