Skip to contentSkip to conversation

syscalls/cma: add errno tests

PATCH Superseded Jan Stancek 2 participants 3 messages May 22, 2012 – Jun 6, 2012 1 message not in the archive

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 3/3 syscalls/cma: add errno tests

Based on proposed man page:
http://ozlabs.org/~cyeoh/cma/process_vm_readv.txt

---
 runtest/syscalls                                   |    3 +
 testcases/kernel/syscalls/cma/cma01.c              |  421 ++++++++++++++++++++
 .../kernel/syscalls/cma/process_vm_readv/Makefile  |    7 +
 .../kernel/syscalls/cma/process_vm_writev/Makefile |    7 +
 4 files changed, 438 insertions(+), 0 deletions(-)
 create mode 100644 testcases/kernel/syscalls/cma/cma01.c
runtest/syscalls +3 -0
index e203d5e..38ac631 100644
@@ -732,6 +732,9 @@ pread03_64 pread03_64
 
 profil01 profil01
 
+process_vm_readv01 process_vm_readv01
+process_vm_writev01 process_vm_writev01
+
 pselect01 pselect01
 pselect01_64 pselect01_64
 
testcases/kernel/syscalls/cma/cma01.c new file +421 -0

421 lines not on this page · raw message

testcases/kernel/syscalls/cma/process_vm_readv/Makefile +7 -0
index f10cac2..4e4633c 100644
@@ -19,4 +19,11 @@
 top_srcdir              ?= ../../../../..
 
 include $(top_srcdir)/include/mk/testcases.mk
+
+MAKE_DEPS               := ../cma01
+MAKE_TARGETS            += process_vm_readv01
+
+process_vm_readv01: ../cma01.c
+	cp -f ../cma01 ./process_vm_readv01
+
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
testcases/kernel/syscalls/cma/process_vm_writev/Makefile +7 -0
index f10cac2..6f255ec 100644
@@ -19,4 +19,11 @@
 top_srcdir              ?= ../../../../..
 
 include $(top_srcdir)/include/mk/testcases.mk
+
+MAKE_DEPS               := ../cma01
+MAKE_TARGETS            += process_vm_writev01
+
+process_vm_writev01: ../cma01.c
+	cp -f ../cma01 ./process_vm_writev01
+
 include $(top_srcdir)/include/mk/generic_leaf_target.mk

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/

_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

#1 lore raw

Hi!

Quoted 8 lines
(quoted diff) +5 -0
+process_vm_readv01 process_vm_readv01
+process_vm_writev01 process_vm_writev01
+
 pselect01 pselect01
 pselect01_64 pselect01_64
 
+static char TCID_readv[] = "process_vm_readv";
+static char TCID_writev[] = "process_vm_writev";

Review

Quoted 10 lines
(quoted diff) +10 -0
+char *TCID = "cma01";
+int  TST_TOTAL = 1;
+static void (*cma_test_params)(struct process_vm_params *params) = NULL;
+
+static void setup(char *argv[]);
+static void cleanup(void);
+
+static void cma_test_params_read(struct process_vm_params *params);
+static void cma_test_params_write(struct process_vm_params *params);
+static void cma_test_errnos();

Forgotten void in the cma_test_errnos() parameters.

testcases/kernel/syscalls/cma/cma01.c line 81

Quoted 9 lines
testcases/kernel/syscalls/cma/cma01.c new file +9 -0
+int main(int argc, char *argv[])
+{
+	int lc;
+	char *msg;
+
+	msg = parse_opts(argc, argv, NULL, NULL);
+	if (msg != NULL)
+		tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
+	setup(argv);

Ah, branching on program name is not really clean solution. I would add switch that would do basically the same, but that would be explicit behavior. That is the reason why we do have a testcase name followed by the testcase command line in runtest files. You can then have following lines in the runtest file:

process_vm_read01 process_vm -r
process_vm_write01 process_vm -w

Or something similar.

Quoted 80 lines
testcases/kernel/syscalls/cma/cma01.c new file +80 -0
+	for (lc = 0; TEST_LOOPING(lc); lc++) {
+		Tst_count = 0;
+		cma_test_errnos();
+	}
+	cleanup();
+	tst_exit();
+}
+
+static void setup(char *argv[])
+{
+	tst_require_root(NULL);
+
+	if (strstr(argv[0], "read") != NULL) {
+		TCID = TCID_readv;
+#if defined(__NR_process_vm_readv)
+		cma_test_params = cma_test_params_read;
+#else
+		tst_brkm(TCONF, NULL, "process_vm_readv does not"
+		    "exist on your system");
+#endif
+	} else if (strstr(argv[0], "write") != NULL) {
+		TCID = TCID_writev;
+#if defined(__NR_process_vm_writev)
+		cma_test_params = cma_test_params_write;
+#else
+		tst_brkm(TCONF, NULL, "process_vm_writev does not"
+		    "exist on your system");
+#endif
+	} else
+		tst_brkm(TBROK, NULL, "executable name expected"
+				" to contain either 'read' or 'write'");
+	TEST_PAUSE;
+}
+
+static void cleanup(void)
+{
+	TEST_CLEANUP;
+}
+
+static void cma_test_params_read(struct process_vm_params *params)
+{
+	TEST(test_process_vm_readv(params->pid,
+	    params->lvec, params->liovcnt,
+	    params->rvec, params->riovcnt,
+	    params->flags));
+}
+
+static void cma_test_params_write(struct process_vm_params *params)
+{
+	TEST(test_process_vm_writev(params->pid,
+	    params->lvec, params->liovcnt,
+	    params->rvec, params->riovcnt,
+	    params->flags));
+}
+
+static int cma_check_ret(long expected_ret, long act_ret)
+{
+	int ret = 0;
+	if (expected_ret == act_ret) {
+		tst_resm(TPASS, "expected ret success - "
+		    "returned value = %ld", act_ret);
+	} else {
+		tst_resm(TFAIL, "unexpected failure - "
+		    "returned value = %ld, expected: %ld",
+		    act_ret, expected_ret);
+		ret = 1;
+	}
+	return ret;
+}
+
+static int cma_check_errno(long expected_errno, long act_errno)
+{
+	int ret = 0;
+	if (act_errno == expected_errno)
+		tst_resm(TPASS, "expected failure - "
+		    "returned value = %ld : %s",
+		    act_errno, strerror(act_errno));
+	else if (act_errno == 0) {
+		tst_resm(TFAIL, "call succeeded unexpectedly");
+		ret = 1;

testcases/kernel/syscalls/cma/cma01.c line 171

Quoted 10 lines
testcases/kernel/syscalls/cma/cma01.c new file +10 -0
+	} else {
+		tst_resm(TFAIL, "unexpected failure - "
+		    "returned value = %ld : %s, "
+		    "expected value = %ld : %s",
+		    act_errno, strerror(act_errno),
+		    expected_errno, strerror(expected_errno));
+		ret = 2;
+	}
+	return ret;
+}

This part is a little confusing. Doing return right in place instead of setting ret variable and returning at the end of the function would make it a little better.

Also you don't need to pass TEST_ERRNO as a parameter and it's better printed by adding TTERRNO flag to tst_*().

Quoted 16 lines
testcases/kernel/syscalls/cma/cma01.c new file +16 -0
+static struct process_vm_params *cma_alloc_sane_params()
+{
+	struct process_vm_params *sane_params = NULL;
+	int len;
+
+	len = getpagesize();
+	sane_params = SAFE_MALLOC(tst_exit, sizeof(struct process_vm_params));
+	sane_params->len = len;
+	sane_params->ldummy = SAFE_MALLOC(tst_exit, len);
+	sane_params->rdummy = SAFE_MALLOC(tst_exit, len);
+
+	sane_params->lvec = SAFE_MALLOC(tst_exit, sizeof(struct iovec));
+	sane_params->lvec->iov_base = sane_params->ldummy;
+	sane_params->lvec->iov_len = len;
+	sane_params->liovcnt = 1;
+

testcases/kernel/syscalls/cma/cma01.c line 198

Quoted 10 lines
testcases/kernel/syscalls/cma/cma01.c new file +10 -0
+	sane_params->rvec = SAFE_MALLOC(tst_exit, sizeof(struct iovec));
+	sane_params->rvec->iov_base = sane_params->rdummy;
+	sane_params->rvec->iov_len = len;
+	sane_params->riovcnt = 1;
+
+	sane_params->flags = 0;
+	sane_params->pid = getpid();
+
+	return sane_params;
+}

There is no need to pass tst_exit as cleanup fn to SAFE_*() macros.

Quoted 35 lines
testcases/kernel/syscalls/cma/cma01.c new file +35 -0
+static void cma_free_params(struct process_vm_params *params)
+{
+	if (params) {
+		free(params->ldummy);
+		free(params->rdummy);
+		free(params->lvec);
+		free(params->rvec);
+		free(params);
+	}
+}
+
+static void cma_test_sane_params(void)
+{
+	struct process_vm_params *sane_params = NULL;
+
+	sane_params = cma_alloc_sane_params();
+	tst_resm(TINFO, "test_sane_params");
+	cma_test_params(sane_params);
+	cma_check_ret(sane_params->len, TEST_RETURN);
+	cma_free_params(sane_params);
+}
+
+static void cma_test_flags(void)
+{
+	struct process_vm_params *params = NULL;
+	long flags[] = { -INT_MAX, -1, 1, INT_MAX, 0 };
+	int flags_size = sizeof(flags)/sizeof(flags[0]);
+	int i;
+
+	params = cma_alloc_sane_params();
+	for (i = 0; i < flags_size; i++) {
+		params->flags = flags[i];
+		tst_resm(TINFO, "test_flags, flags=%ld", flags[i]);
+		cma_test_params(params);
+		/* atm. only flags == 0 is allowed, everything else

testcases/kernel/syscalls/cma/cma01.c line 244

Quoted 10 lines
testcases/kernel/syscalls/cma/cma01.c new file +10 -0
+		 * should fail with EINVAL */
+		if (flags[i] != 0) {
+			cma_check_ret(-1, TEST_RETURN);
+			cma_check_errno(EINVAL, TEST_ERRNO);
+		} else {
+			cma_check_ret(params->len, TEST_RETURN);
+		}
+	}
+	cma_free_params(params);
+}

If I understand this correctly, this test may break in the future, once somebody makes use of the flags?

testcases/kernel/syscalls/cma/cma01.c line 248

Quoted 3 lines
testcases/kernel/syscalls/cma/cma01.c new file +3 -0
+static void cma_test_iov_len_overflow(void)
+{
+	struct process_vm_params *params = NULL;

Why are you initalizing something that gets assigned two lines of code later? (which gets repeated in most of the tests).

Quoted 13 lines
testcases/kernel/syscalls/cma/cma01.c new file +13 -0
+	ssize_t maxlen = -1;
+	params = cma_alloc_sane_params();
+
+	params->lvec->iov_len = maxlen;
+	params->rvec->iov_len = maxlen;
+	tst_resm(TINFO, "test_iov_len_overflow");
+	cma_test_params(params);
+	cma_check_ret(-1, TEST_RETURN);
+	cma_check_errno(EINVAL, TEST_ERRNO);
+	cma_free_params(params);
+}
+
+static void cma_test_iov_invalid(void)

testcases/kernel/syscalls/cma/cma01.c line 271

Quoted 10 lines
testcases/kernel/syscalls/cma/cma01.c new file +10 -0
+{
+	struct process_vm_params *sane_params = NULL;
+	struct process_vm_params *params;
+	struct process_vm_params params_copy;
+
+	sane_params = cma_alloc_sane_params();
+	/* make a shallow copy we can 'damage' */
+	params = &params_copy;
+
+	*params = *sane_params;

Ufff, this indirection shouldn't be needed. You could do:

params_copy = *sane_params;

And then pass &params_copy to the fuctions.

Quoted 53 lines
testcases/kernel/syscalls/cma/cma01.c new file +53 -0
+	tst_resm(TINFO, "test_iov_invalid - lvec->iov_base");
+	params->lvec->iov_base = (void *)-1;
+	cma_test_params(params);
+	cma_check_ret(-1, TEST_RETURN);
+	cma_check_errno(EFAULT, TEST_ERRNO);
+
+	*params = *sane_params;
+	tst_resm(TINFO, "test_iov_invalid - rvec->iov_base");
+	params->rvec->iov_base = (void *)-1;
+	cma_test_params(params);
+	cma_check_ret(-1, TEST_RETURN);
+	cma_check_errno(EFAULT, TEST_ERRNO);
+
+	*params = *sane_params;
+	tst_resm(TINFO, "test_iov_invalid - lvec");
+	params->lvec = (void *)-1;
+	cma_test_params(params);
+	cma_check_ret(-1, TEST_RETURN);
+	cma_check_errno(EFAULT, TEST_ERRNO);
+
+	*params = *sane_params;
+	tst_resm(TINFO, "test_iov_invalid - rvec");
+	params->rvec = (void *)-1;
+	cma_test_params(params);
+	cma_check_ret(-1, TEST_RETURN);
+	cma_check_errno(EFAULT, TEST_ERRNO);
+
+	cma_free_params(sane_params);
+}
+
+static void cma_test_invalid_pid(void)
+{
+	int status;
+	struct process_vm_params *params = NULL;
+	pid_t child_pid;
+
+	params = cma_alloc_sane_params();
+	tst_resm(TINFO, "test_invalid_pid");
+	params->pid = -1;
+	cma_test_params(params);
+	cma_check_ret(-1, TEST_RETURN);
+	cma_check_errno(ESRCH, TEST_ERRNO);
+	cma_free_params(params);
+
+	child_pid = fork();
+	switch (child_pid) {
+		case -1:
+			tst_brkm(TBROK|TERRNO, cleanup, "fork");
+			break;
+		case 0:
+			exit(0);
+		default:
+			if (waitpid(child_pid, &status, 0) == -1)

testcases/kernel/syscalls/cma/cma01.c line 334

Quoted 10 lines
testcases/kernel/syscalls/cma/cma01.c new file +10 -0
+				tst_brkm(TBROK|TERRNO, cleanup, "waitpid");
+			if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+				tst_resm(TFAIL, "child returns %d", status);
+
+			params = cma_alloc_sane_params();
+			params->pid = child_pid;
+			cma_test_params(params);
+			cma_check_ret(-1, TEST_RETURN);
+			cma_check_errno(ESRCH, TEST_ERRNO);
+			cma_free_params(params);

So you expect that pid is not reused right after child has exited?

While not guaranteed, this would probably work.

Maybe even better would be to read /proc/sys/kernel/pid_max and try value greater that that.

Quoted 66 lines
testcases/kernel/syscalls/cma/cma01.c new file +66 -0
+	}
+}
+
+static void cma_test_invalid_perm(void)
+{
+	char nobody_uid[] = "nobody";
+	struct passwd *ltpuser;
+	int status;
+	struct process_vm_params *params = NULL;
+	pid_t child_pid;
+	pid_t parent_pid;
+	int ret = 0;
+
+	tst_resm(TINFO, "test_invalid_perm");
+	parent_pid = getpid();
+	child_pid = fork();
+	switch (child_pid) {
+		case -1:
+			tst_brkm(TBROK|TERRNO, cleanup, "fork");
+			break;
+		case 0:
+			ltpuser = getpwnam(nobody_uid);
+			if (ltpuser == NULL)
+				tst_brkm(TBROK|TERRNO, NULL,
+				    "getpwnam failed");
+			if (setuid(ltpuser->pw_uid) == -1)
+				tst_brkm(TBROK|TERRNO, NULL,
+				    "setuid(%u) failed", ltpuser->pw_uid);
+
+			params = cma_alloc_sane_params();
+			params->pid = parent_pid;
+			cma_test_params(params);
+			ret |= cma_check_ret(-1, TEST_RETURN);
+			ret |= cma_check_errno(EPERM, TEST_ERRNO);
+			cma_free_params(params);
+			exit(ret);
+		default:
+			if (waitpid(child_pid, &status, 0) == -1)
+				tst_brkm(TBROK|TERRNO, cleanup, "waitpid");
+			if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+				tst_resm(TFAIL, "child returns %d", status);
+	}
+}
+
+static void cma_test_invalid_protection(void)
+{
+	struct process_vm_params *sane_params = NULL;
+	struct process_vm_params *params;
+	struct process_vm_params params_copy;
+	void *p;
+
+	sane_params = cma_alloc_sane_params();
+	/* make a shallow copy we can 'damage' */
+	params = &params_copy;
+
+	p = mmap(NULL, getpagesize(), PROT_NONE,
+			MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+	if (p == MAP_FAILED)
+		tst_brkm(TBROK|TERRNO, cleanup, "mmap");
+
+	*params = *sane_params;
+	params->lvec->iov_base = p;
+	tst_resm(TINFO, "test_invalid_protection lvec");
+	cma_test_params(params);
+	cma_check_ret(-1, TEST_RETURN);
+	cma_check_errno(EFAULT, TEST_ERRNO);

testcases/kernel/syscalls/cma/cma01.c line 410

Quoted 10 lines
testcases/kernel/syscalls/cma/cma01.c new file +10 -0
+
+	*params = *sane_params;
+	params->rvec->iov_base = p;
+	tst_resm(TINFO, "test_invalid_protection rvec");
+	cma_test_params(params);
+	cma_check_ret(-1, TEST_RETURN);
+	cma_check_errno(EFAULT, TEST_ERRNO);
+
+	cma_free_params(sane_params);
+}

Once again the indirection, and you aren't unmapping the memory, which is a minor issue...

Quoted 32 lines
testcases/kernel/syscalls/cma/cma01.c new file +10 -0
+static void cma_test_errnos()
+{
+	cma_test_sane_params();
+	cma_test_flags();
+	cma_test_iov_len_overflow();
+	cma_test_iov_invalid();
+	cma_test_invalid_pid();
+	cma_test_invalid_perm();
+	cma_test_invalid_protection();
+}
testcases/kernel/syscalls/cma/process_vm_readv/Makefile +7 -0
index f10cac2..4e4633c 100644
@@ -19,4 +19,11 @@
 top_srcdir              ?= ../../../../..
 
 include $(top_srcdir)/include/mk/testcases.mk
+
+MAKE_DEPS               := ../cma01
+MAKE_TARGETS            += process_vm_readv01
+
+process_vm_readv01: ../cma01.c
+	cp -f ../cma01 ./process_vm_readv01
+
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
testcases/kernel/syscalls/cma/process_vm_writev/Makefile +0 -0
index f10cac2..6f255ec 100644
@@ -19,4 +19,11 @@
 top_srcdir              ?= ../../../../..

testcases/kernel/syscalls/cma/process_vm_writev/Makefile line 29

Quoted 10 lines
testcases/kernel/syscalls/cma/process_vm_writev/Makefile +7 -0
 
 include $(top_srcdir)/include/mk/testcases.mk
+
+MAKE_DEPS               := ../cma01
+MAKE_TARGETS            += process_vm_writev01
+
+process_vm_writev01: ../cma01.c
+	cp -f ../cma01 ./process_vm_writev01
+
 include $(top_srcdir)/include/mk/generic_leaf_target.mk

And that is exactly thing I don't like to see, directories only with Makefiles and binaries magically created somewhere else.

Either create one test that does different thigs when given different parameters or split the tests in several files (and put most of the common code in file included in both tests).

Signature · 13 lines
Cyril Hrubis
[email protected]

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

A message that is not in the archive (sent off-list or not yet received): 30c7e6b8-ab70-4c48-bd9c-0271a852f060@zmail17.collab.prod.int.phx2.redhat.com

#3 lore raw

Hi!

Quoted 29 lines
Quoted 19 lines
Quoted 19 lines
testcases/kernel/syscalls/cma/cma01.c new file +19 -0
+static void cma_test_flags(void)
+{
+	struct process_vm_params *params = NULL;
+	long flags[] = { -INT_MAX, -1, 1, INT_MAX, 0 };
+	int flags_size = sizeof(flags)/sizeof(flags[0]);
+	int i;
+
+	params = cma_alloc_sane_params();
+	for (i = 0; i < flags_size; i++) {
+		params->flags = flags[i];
+		tst_resm(TINFO, "test_flags, flags=%ld", flags[i]);
+		cma_test_params(params);
+		/* atm. only flags == 0 is allowed, everything else
+		 * should fail with EINVAL */
+		if (flags[i] != 0) {
+			cma_check_ret(-1, TEST_RETURN);
+			cma_check_errno(EINVAL, TEST_ERRNO);
+		} else {
+			cma_check_ret(params->len, TEST_RETURN);
Quoted 9 lines

testcases/kernel/syscalls/cma/cma01.c line 244

Quoted 4 lines
testcases/kernel/syscalls/cma/cma01.c new file +4 -0
+		}
+	}
+	cma_free_params(params);
+}

If I understand this correctly, this test may break in the future, once
somebody makes use of the flags?

Quoted 2 lines

That is correct, but it matches documentation. I'm OK with removing it to have it more future proof.

Well, there is no obvious solution to this. Lets have it for now, we can remove it (or add tst_kvercmp()) later once it breaks.

Signature · 13 lines
Cyril Hrubis
[email protected]

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list