From: Mike F. <su...@li...> - 2013-06-25 16:31:28
|
The branch, master, has been updated via b88fa5b6ec5a29834a0e52df7b22b9bb47fe0379 (commit) via bcf24e6a97d2ec69249b399704053ed9b0ec2415 (commit) via a0e618c0f2acabc001a2268b4a44dcab48f4ba9a (commit) via 60c6ce29cfaf357cfcd629995d559d41030e96d2 (commit) via ed69cd589d61257be8319800b91e6eeef555d507 (commit) via 8329ed8a449efe34672eabfe6ab44bf7116cc661 (commit) via d2085cafe3c1363150c0338b5c09bc7ed7f35e07 (commit) via 208669109e427ee358285eba4073b5b07d475560 (commit) via e0cbe7aaee097cf1b5e8c53906de42e4b6d61aeb (commit) from 8a575d291217d366b6d1f04b5608d3258ebde9cf (commit) - Log ----------------------------------------------------------------- commit b88fa5b6ec5a29834a0e52df7b22b9bb47fe0379 Author: Cyril Hrubis <ch...@su...> Date: Tue Jun 25 15:50:08 2013 +0200 runltp: Fix bashism Remove several occurences of '&> /dev/null' that breaks the script execution under dash. Signed-off-by: Cyril Hrubis <ch...@su...> Signed-off-by: Sedat Dilek <sed...@gm...> commit bcf24e6a97d2ec69249b399704053ed9b0ec2415 Author: Wanlong Gao <gao...@cn...> Date: Tue Jun 25 09:33:50 2013 +0800 getrusage03: disable the test when kernel before 2.6.32 Kernel commit 1f10206c is first introduced in 2.6.32, this ru_maxrss behaviors will not be supported before kernel 2.6.32, so disable the test when kernel version is before 2.6.32. Signed-off-by: Wanlong Gao <gao...@cn...> Reviewed-by: Jan Stancek <jst...@re...> Acked-by: Cyril Hrubis <ch...@su...> commit a0e618c0f2acabc001a2268b4a44dcab48f4ba9a Author: Jan Stancek <jst...@re...> Date: Fri Jun 7 11:09:26 2013 +0200 new testcase: kmsg01 Test /dev/kmsg based on kernel doc: Documentation/ABI/testing/dev-kmsg - read() blocks - non-blocking read() fails with EAGAIN - partial read fails (buffer smaller than message) - can write to /dev/kmsg and message seqno grows - first read() after open() returns same message - if messages get overwritten, read() returns -EPIPE - device supports SEEK_SET, SEEK_END, SEEK_DATA Signed-off-by: Jan Stancek <jst...@re...> Acked-by: Mike Frysinger <va...@ge...> Acked-by: Cyril Hrubis <ch...@su...> commit 60c6ce29cfaf357cfcd629995d559d41030e96d2 Author: Eryu Guan <eg...@re...> Date: Mon Jun 24 23:49:43 2013 +0800 dup2/dup205: close all fds before tst_rmdir() Close all open fds before calling tst_rmdir() to avoid TWARN caused by NFS silly rename when removing temp dir. dup205 0 TWARN : tst_rmdir: rmobj(/mnt/nfs/dupbA5J5i) failed: unlink(/mnt/nfs/dupbA5J5i/.nfs0000000000f4805b00000005) failed; errno=16: Device or resource busy Signed-off-by: Eryu Guan <eg...@re...> Acked-by: Mike Frysinger <va...@ge...> Acked-by: Caspar Zhang <ca...@ca...> commit ed69cd589d61257be8319800b91e6eeef555d507 Author: Cyril Hrubis <ch...@su...> Date: Mon Jun 24 17:51:00 2013 +0200 lib: Add lib/ltp_priv.h header for internal API. Signed-off-by: Cyril Hrubis <ch...@su...> commit 8329ed8a449efe34672eabfe6ab44bf7116cc661 Author: DAN LI <li...@cn...> Date: Mon Jun 24 16:03:57 2013 +0800 mmap/mmap13.c: new case to test SIGBUS error of mmap Test SIGBUS error by accessing to a portion of the buffer that does not correspond to the file. Signed-off-by: DAN LI <li...@cn...> commit d2085cafe3c1363150c0338b5c09bc7ed7f35e07 Author: Cyril Hrubis <ch...@su...> Date: Tue Jun 18 14:47:19 2013 +0200 lib: safe_macros: Add SAFE_FOPEN(), SAFE_FCLOSE() Signed-off-by: Cyril Hrubis <ch...@su...> commit 208669109e427ee358285eba4073b5b07d475560 Author: Alexey Kodanev <ale...@or...> Date: Tue Jun 11 13:56:10 2013 +0400 prot_hsymlinks & cgroup_xattr: fix copyright header Signed-off-by: Alexey Kodanev <ale...@or...> commit e0cbe7aaee097cf1b5e8c53906de42e4b6d61aeb Author: Jungsoo Son <jun...@lg...> Date: Sat Jun 8 11:54:26 2013 +0900 syscalls/chown01: Fix test file creation There is a bug in the code to create the file and the code is very intricate. So replace it with SAFE_FILE_PRINTF(). Signed-off-by: jungsoo.son <jun...@lg...> Reviewed-by: Jan Stancek <jst...@re...> Signed-off-by: Wanlong Gao <gao...@cn...> ----------------------------------------------------------------------- Summary of changes: include/safe_macros.h | 11 + lib/Makefile | 2 + lib/ltp_priv.h | 28 + lib/safe_macros.c | 29 + lib/tst_resource.c | 4 +- lib/tst_tmpdir.c | 1 + runltp | 8 +- runtest/kernel_misc | 1 + runtest/syscalls | 1 + testcases/kernel/controllers/cgroup_xattr/Makefile | 3 +- .../kernel/controllers/cgroup_xattr/cgroup_xattr.c | 3 +- testcases/kernel/logging/.gitignore | 1 + testcases/kernel/logging/Makefile | 22 + testcases/kernel/logging/kmsg/Makefile | 22 + testcases/kernel/logging/kmsg/kmsg01.c | 595 ++++++++++++++++++++ testcases/kernel/security/prot_hsymlinks/Makefile | 5 +- .../security/prot_hsymlinks/prot_hsymlinks.c | 3 +- testcases/kernel/syscalls/chown/chown01.c | 24 +- testcases/kernel/syscalls/dup2/dup205.c | 4 +- testcases/kernel/syscalls/getrusage/getrusage03.c | 7 + testcases/kernel/syscalls/mmap/mmap13.c | 152 +++++ 21 files changed, 897 insertions(+), 29 deletions(-) create mode 100644 lib/ltp_priv.h create mode 100644 runtest/kernel_misc create mode 100644 testcases/kernel/logging/.gitignore create mode 100644 testcases/kernel/logging/Makefile create mode 100644 testcases/kernel/logging/kmsg/Makefile create mode 100644 testcases/kernel/logging/kmsg/kmsg01.c create mode 100644 testcases/kernel/syscalls/mmap/mmap13.c diff --git a/include/safe_macros.h b/include/safe_macros.h index 1047437..3a26df6 100644 --- a/include/safe_macros.h +++ b/include/safe_macros.h @@ -23,6 +23,7 @@ #include <libgen.h> #include <stdarg.h> #include <unistd.h> +#include <stdio.h> char* safe_basename(const char *file, const int lineno, void (*cleanup_fn)(void), char *path); @@ -173,5 +174,15 @@ long safe_sysconf(const char *file, const int lineno, #define SAFE_SYSCONF(cleanup_fn, name) \ safe_sysconf(__FILE__, __LINE__, cleanup_fn, name) +FILE *safe_fopen(const char *file, const int lineno, void (cleanup_fn)(void), + const char *path, const char *mode); +#define SAFE_FOPEN(cleanup_fn, path, mode) \ + safe_fopen(__FILE__, __LINE__, cleanup_fn, path, mode) + +int safe_fclose(const char *file, const int lineno, void (cleanup_fn)(void), + FILE *f); +#define SAFE_FCLOSE(cleanup_fn, f) \ + safe_fclose(__FILE__, __LINE__, cleanup_fn, f) + #endif /* __SAFE_MACROS_H__ */ #endif /* __TEST_H__ */ diff --git a/lib/Makefile b/lib/Makefile index 453cf95..4199520 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -28,6 +28,8 @@ ifeq ($(UCLINUX),1) CFLAGS += -D_USC_LIB_ endif +CFLAGS += -I. + #CPPFLAGS += -DGARRETT_IS_A_PEDANTIC_BASTARD FILTER_OUT_LIBSRCS := mount_utils.c diff --git a/lib/ltp_priv.h b/lib/ltp_priv.h new file mode 100644 index 0000000..6a6a8bb --- /dev/null +++ b/lib/ltp_priv.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Cyril Hrubis ch...@su... + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + */ + +#ifndef __LTP_PRIV_H__ +#define __LTP_PRIV_H__ + +/* declared in tst_tmpdir.c */ +const char *tst_get_startwd(void); + +#endif /* __LTP_PRIV_H__ */ diff --git a/lib/safe_macros.c b/lib/safe_macros.c index 4da9914..fb02796 100644 --- a/lib/safe_macros.c +++ b/lib/safe_macros.c @@ -438,3 +438,32 @@ long safe_sysconf(const char *file, const int lineno, return rval; } + +FILE *safe_fopen(const char *file, const int lineno, void (cleanup_fn)(void), + const char *path, const char *mode) +{ + FILE *f = fopen(path, mode); + + if (f == NULL) { + tst_brkm(TBROK | TERRNO, cleanup_fn, + "fopen(%s) failed at %s:%d", path, file, lineno); + return NULL; + } + + return f; +} + +int safe_fclose(const char *file, const int lineno, void (cleanup_fn)(void), + FILE *f) +{ + int ret; + + ret = fclose(f); + + if (ret) { + tst_brkm(TBROK | TERRNO, cleanup_fn, + "fclose failed at %s:%d", file, lineno); + } + + return ret; +} diff --git a/lib/tst_resource.c b/lib/tst_resource.c index 61fc322..54d4795 100644 --- a/lib/tst_resource.c +++ b/lib/tst_resource.c @@ -22,6 +22,7 @@ */ #include "tst_resource.h" +#include "ltp_priv.h" static int file_copy(const char *file, const int lineno, void (*cleanup_fn)(void), const char *path, @@ -41,9 +42,6 @@ static int file_copy(const char *file, const int lineno, return 1; } -/* declared in tst_tmpdir.c */ -const char *tst_get_startwd(void); - void tst_resource_copy(const char *file, const int lineno, void (*cleanup_fn)(void), const char *filename, const char *dest) diff --git a/lib/tst_tmpdir.c b/lib/tst_tmpdir.c index cf671a0..4029276 100644 --- a/lib/tst_tmpdir.c +++ b/lib/tst_tmpdir.c @@ -74,6 +74,7 @@ #include "test.h" #include "rmobj.h" +#include "ltp_priv.h" /* * Define some useful macros. diff --git a/runltp b/runltp index a8bf404..1309d0a 100755 --- a/runltp +++ b/runltp @@ -663,7 +663,7 @@ main() fi # check for required users and groups - ${LTPROOT}/IDcheck.sh &>/dev/null || \ + ${LTPROOT}/IDcheck.sh || \ { echo "WARNING: required users and groups not present" echo "WARNING: some test cases may fail" @@ -984,7 +984,7 @@ main() create_block() { #create a block device with ext4 filesystem. - dd if=/dev/zero of=${TMP}/test.img bs=1kB count=10240 &>/dev/null + dd if=/dev/zero of=${TMP}/test.img bs=1kB count=10240 if [ $? -ne 0 ]; then echo "Failed to create loopback device image, please check disk space and re-run" return 1 @@ -996,12 +996,12 @@ create_block() return 1 else ##attach the created file to loop dev. - losetup $LOOP_DEV ${TMP}/test.img &>/dev/null + losetup $LOOP_DEV ${TMP}/test.img if [ $? -ne 0 ]; then echo "losetup failed to create block device" return 1 else - mkfs.ext4 $LOOP_DEV &>/dev/null + mkfs.ext4 $LOOP_DEV [ $? -ne 0 ] && (echo "creating a ext4 block device failed" && return 1) #set the values in alltests which require block device. DEVICE=$LOOP_DEV diff --git a/runtest/kernel_misc b/runtest/kernel_misc new file mode 100644 index 0000000..47a667e --- /dev/null +++ b/runtest/kernel_misc @@ -0,0 +1 @@ +kmsg01 kmsg01 diff --git a/runtest/syscalls b/runtest/syscalls index e6ce29c..eba0200 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -561,6 +561,7 @@ mmap06 mmap06 mmap07 mmap07 mmap08 mmap08 mmap09 mmap09 +mmap13 mmap13 # test is broken, mask it for now. #mmap11 mmap11 -i 30000 diff --git a/testcases/kernel/controllers/cgroup_xattr/Makefile b/testcases/kernel/controllers/cgroup_xattr/Makefile index 2d75069..effd5da 100644 --- a/testcases/kernel/controllers/cgroup_xattr/Makefile +++ b/testcases/kernel/controllers/cgroup_xattr/Makefile @@ -2,7 +2,8 @@ # # 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. +# 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 would be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c index 20473d4..512d505 100644 --- a/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c +++ b/testcases/kernel/controllers/cgroup_xattr/cgroup_xattr.c @@ -3,7 +3,8 @@ * * 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. + * 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 would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/testcases/kernel/logging/.gitignore b/testcases/kernel/logging/.gitignore new file mode 100644 index 0000000..4236df0 --- /dev/null +++ b/testcases/kernel/logging/.gitignore @@ -0,0 +1 @@ +/kmsg/kmsg01 diff --git a/testcases/kernel/logging/Makefile b/testcases/kernel/logging/Makefile new file mode 100644 index 0000000..bd32f70 --- /dev/null +++ b/testcases/kernel/logging/Makefile @@ -0,0 +1,22 @@ +# +# Copyright (C) 2013 Linux Test Project +# +# 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/env_pre.mk +include $(top_srcdir)/include/mk/generic_trunk_target.mk diff --git a/testcases/kernel/logging/kmsg/Makefile b/testcases/kernel/logging/kmsg/Makefile new file mode 100644 index 0000000..67b29d6 --- /dev/null +++ b/testcases/kernel/logging/kmsg/Makefile @@ -0,0 +1,22 @@ +# +# Copyright (C) 2013 Linux Test Project +# +# 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 $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/logging/kmsg/kmsg01.c b/testcases/kernel/logging/kmsg/kmsg01.c new file mode 100644 index 0000000..83498ee --- /dev/null +++ b/testcases/kernel/logging/kmsg/kmsg01.c @@ -0,0 +1,595 @@ +/* + * Copyright (C) 2013 Linux Test Project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * Test /dev/kmsg based on kernel doc: Documentation/ABI/testing/dev-kmsg + * - read() blocks + * - non-blocking read() fails with EAGAIN + * - partial read fails (buffer smaller than message) + * - can write to /dev/kmsg and message seqno grows + * - first read() after open() returns same message + * - if messages get overwritten, read() returns -EPIPE + * - device supports SEEK_SET, SEEK_END, SEEK_DATA + */ +#define _GNU_SOURCE +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "config.h" +#include "test.h" +#include "usctest.h" +#include "safe_macros.h" +#include "linux_syscall_numbers.h" + +#define MSG_PREFIX "LTP kmsg01 " +#define MAX_MSGSIZE 4096 +#define NUM_READ_MSGS 3 +#define NUM_READ_RETRY 10 +#define NUM_OVERWRITE_MSGS 1024 +#define READ_TIMEOUT 5 + +char *TCID = "kmsg01"; +static void setup(void); +static void cleanup(void); + +/* + * inject_msg - write message to /dev/kmsg + * @msg: null-terminated message to inject, should end with \n + * + * RETURNS: + * 0 on success + * -1 on failure, errno reflects write() errno + */ +static int inject_msg(const char *msg) +{ + int f; + f = open("/dev/kmsg", O_WRONLY); + if (f < 0) + tst_brkm(TBROK | TERRNO, cleanup, "failed to open /dev/kmsg"); + TEST(write(f, msg, strlen(msg))); + SAFE_CLOSE(cleanup, f); + errno = TEST_ERRNO; + return TEST_RETURN; +} + +/* + * find_msg - find message in kernel ring buffer + * @fd: fd to use, if < 0 function opens /dev/kmsg itself + * @text_to_find: substring to look for in messages + * @buf: buf to store found message + * @bufsize: size of 'buf' + * @first: 1 - return first matching message + * 0 - return last matching message + * RETURNS: + * 0 on success + * -1 on failure + */ +static int find_msg(int fd, const char *text_to_find, char *buf, int bufsize, + int first) +{ + int f, msg_found = 0; + char msg[MAX_MSGSIZE + 1]; + + if (fd < 0) { + f = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + if (f < 0) + tst_brkm(TBROK, cleanup, "failed to open /dev/kmsg"); + } else { + f = fd; + } + + while (1) { + TEST(read(f, msg, sizeof(msg))); + if (TEST_RETURN < 0) { + if (TEST_ERRNO == EAGAIN) + /* there are no more messages */ + break; + else if (TEST_ERRNO == EPIPE) + /* current message was overwritten */ + continue; + else + tst_brkm(TBROK|TTERRNO, cleanup, + "failed to read /dev/kmsg"); + } else if (TEST_RETURN < bufsize) { + /* lines from kmsg are not NULL terminated */ + msg[TEST_RETURN] = '\0'; + if (strstr(msg, text_to_find) != NULL) { + strncpy(buf, msg, bufsize); + msg_found = 1; + if (first) + break; + } + } + } + if (fd < 0) + SAFE_CLOSE(cleanup, f); + + if (msg_found) + return 0; + else + return -1; +} + +static int get_msg_fields(const char *msg, unsigned long *prio, + unsigned long *seqno) +{ + unsigned long s, p; + if (sscanf(msg, "%lu,%lu,", &p, &s) == 2) { + if (prio) + *prio = p; + if (seqno) + *seqno = s; + return 0; + } else { + return 1; + } +} + +/* + * timed_read - if possible reads from fd or times out + * @fd: fd to read from + * @timeout_sec: timeout in seconds + * + * RETURNS: + * read bytes on successful read + * -1 on read() error, errno reflects read() errno + * -2 on timeout + */ +static int timed_read(int fd, int timeout_sec) +{ + int ret, tmp; + struct timeval timeout; + fd_set read_fds; + + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + timeout.tv_sec = timeout_sec; + timeout.tv_usec = 0; + + ret = select(fd + 1, &read_fds, 0, 0, &timeout); + switch (ret) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "select failed"); + case 0: + /* select timed out */ + return -2; + } + + return read(fd, &tmp, 1); +} + +/* + * timed_read_kmsg - reads file until it reaches end of file, + * read fails or times out. This ignores any + * EPIPE errors. + * @fd: fd to read from + * @timeout_sec: timeout in seconds for every read attempt + * + * RETURNS: + * 0 on read reaching eof + * -1 on read error, errno reflects read() errno + * -2 on timeout + */ +static int timed_read_kmsg(int fd, int timeout_sec) +{ + int child, status, ret = 0; + int pipefd[2]; + char msg[MAX_MSGSIZE]; + + if (pipe(pipefd) != 0) + tst_brkm(TBROK|TERRNO, cleanup, "pipe failed"); + + child = fork(); + switch (child) { + case -1: + tst_brkm(TBROK|TERRNO, cleanup, "failed to fork"); + case 0: + /* child does all the reading and keeps writing to + * pipe to let parent know that it didn't block */ + close(pipefd[0]); + while (1) { + write(pipefd[1], "", 1); + TEST(read(fd, msg, MAX_MSGSIZE)); + if (TEST_RETURN == 0) + break; + if (TEST_RETURN == -1 && TEST_ERRNO != EPIPE) { + ret = TEST_ERRNO; + break; + } + } + + close(pipefd[1]); + exit(ret); + } + SAFE_CLOSE(cleanup, pipefd[1]); + + /* parent reads pipe until it reaches eof or until read times out */ + do { + TEST(timed_read(pipefd[0], timeout_sec)); + } while (TEST_RETURN > 0); + SAFE_CLOSE(cleanup, pipefd[0]); + + /* child is blocked, kill it */ + if (TEST_RETURN == -2) + kill(child, SIGTERM); + if (waitpid(child, &status, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid"); + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) { + return 0; + } else { + errno = WEXITSTATUS(status); + return -1; + } + } + return -2; +} + +static void test_read_nonblock(void) +{ + int fd; + + tst_resm(TINFO, "TEST: nonblock read"); + fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + if (fd < 0) + tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg"); + + TEST(timed_read_kmsg(fd, READ_TIMEOUT)); + if (TEST_RETURN == -1 && TEST_ERRNO == EAGAIN) + tst_resm(TPASS, "non-block read returned EAGAIN"); + else + tst_resm(TFAIL|TTERRNO, "non-block read returned: %ld", + TEST_RETURN); + SAFE_CLOSE(cleanup, fd); +} + +static void test_read_block(void) +{ + int fd; + + tst_resm(TINFO, "TEST: blocking read"); + fd = open("/dev/kmsg", O_RDONLY); + if (fd < 0) + tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg"); + + TEST(timed_read_kmsg(fd, READ_TIMEOUT)); + if (TEST_RETURN == -2) + tst_resm(TPASS, "read blocked"); + else + tst_resm(TFAIL|TTERRNO, "read returned: %ld", TEST_RETURN); + SAFE_CLOSE(cleanup, fd); +} + +static void test_partial_read(void) +{ + char msg[MAX_MSGSIZE]; + int fd; + + tst_resm(TINFO, "TEST: partial read"); + fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + if (fd < 0) + tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg"); + + TEST(read(fd, msg, 1)); + if (TEST_RETURN < 0) + tst_resm(TPASS|TTERRNO, "read failed as expected"); + else + tst_resm(TFAIL, "read returned: %ld", TEST_RETURN); + SAFE_CLOSE(cleanup, fd); +} + +static void test_inject(void) +{ + char imsg[MAX_MSGSIZE], imsg_prefixed[MAX_MSGSIZE]; + char tmp[MAX_MSGSIZE]; + unsigned long prefix, seqno, seqno_last = 0; + int i, facility, prio; + + tst_resm(TINFO, "TEST: injected messages appear in /dev/kmsg"); + + /* test all combinations of prio 0-7, facility 0-15 */ + for (i = 0; i < 127; i++) { + prio = (i & 7); + facility = (i >> 3); + sprintf(imsg, MSG_PREFIX"TEST MESSAGE %ld prio: %d, " + "facility: %d\n", random(), prio, facility); + sprintf(imsg_prefixed, "<%d>%s", i, imsg); + + if (inject_msg(imsg_prefixed) == -1) { + tst_resm(TFAIL|TERRNO, "inject failed"); + return; + } + + /* check that message appears in log */ + if (find_msg(-1, imsg, tmp, sizeof(tmp), 0) == -1) { + tst_resm(TFAIL, "failed to find: %s", imsg); + return; + } + + /* check that facility is not 0 (LOG_KERN). */ + if (get_msg_fields(tmp, &prefix, &seqno) != 0) { + tst_resm(TFAIL, "failed to parse seqid: %s", tmp); + return; + } + if (prefix >> 3 == 0) { + tst_resm(TFAIL, "facility 0 found: %s", tmp); + return; + } + + /* check that seq. number grows */ + if (seqno > seqno_last) { + seqno_last = seqno; + } else { + tst_resm(TFAIL, "seqno doesn't grow: %lu, " + "last: %lu", seqno, seqno_last); + return; + } + } + + tst_resm(TPASS, "injected messages found in log"); + tst_resm(TPASS, "sequence numbers grow as expected"); +} + +static void test_read_returns_first_message(void) +{ + unsigned long seqno[NUM_READ_MSGS + 1]; + char msg[MAX_MSGSIZE]; + int msgs_match = 1; + int i, fd, j = NUM_READ_RETRY; + + /* Open extra fd, which we try to read after reading NUM_READ_MSGS. + * If this read fails with EPIPE, first message was overwritten and + * we should retry the whole test. If it still fails after + * NUM_READ_RETRY attempts, report TWARN */ + tst_resm(TINFO, "TEST: mult. readers will get same first message"); + while (j) { + fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + if (fd < 0) + tst_brkm(TBROK|TERRNO, cleanup, + "failed to open /dev/kmsg"); + + for (i = 0; i < NUM_READ_MSGS; i++) { + if (find_msg(-1, "", msg, sizeof(msg), 1) != 0) + tst_resm(TFAIL, "failed to find any message"); + if (get_msg_fields(msg, NULL, &seqno[i]) != 0) + tst_resm(TFAIL, "failed to parse seqid: %s", + msg); + } + + TEST(read(fd, msg, sizeof(msg))); + SAFE_CLOSE(cleanup, fd); + if (TEST_RETURN != -1) + break; + + if (TEST_ERRNO == EPIPE) + tst_resm(TINFO, "msg overwritten, retrying"); + else + tst_resm(TFAIL|TTERRNO, "read failed"); + + /* give a second to whoever overwrote first message to finish */ + sleep(1); + j--; + } + + if (!j) { + tst_resm(TWARN, "exceeded: %d attempts", NUM_READ_RETRY); + return; + } + + for (i = 0; i < NUM_READ_MSGS - 1; i++) + if (seqno[i] != seqno[i + 1]) + msgs_match = 0; + if (msgs_match) { + tst_resm(TPASS, "all readers got same message on first read"); + } else { + tst_resm(TFAIL, "readers got different messages"); + for (i = 0; i < NUM_READ_MSGS; i++) + tst_resm(TINFO, "msg%d: %lu\n", i, seqno[i]); + } +} + +static void test_messages_overwritten(void) +{ + int i, fd; + char msg[MAX_MSGSIZE]; + unsigned long first_seqno, seqno; + char filler_str[] = MSG_PREFIX"FILLER MESSAGE TO OVERWRITE OTHERS\n"; + + /* Keep injecting messages until we overwrite first one. + * We know first message is overwritten when its seqno changes */ + tst_resm(TINFO, "TEST: read returns EPIPE when messages get " + "overwritten"); + fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + if (fd < 0) + tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg"); + + if (find_msg(-1, "", msg, sizeof(msg), 1) == 0 + && get_msg_fields(msg, NULL, &first_seqno) == 0) { + tst_resm(TINFO, "first seqno: %lu", first_seqno); + } else { + tst_brkm(TBROK, cleanup, "failed to get first seq. number"); + } + + while (1) { + if (find_msg(-1, "", msg, sizeof(msg), 1) != 0 + || get_msg_fields(msg, NULL, &seqno) != 0) { + tst_resm(TFAIL, "failed to get first seq. number"); + break; + } + if (first_seqno != seqno) { + /* first message was overwritten */ + tst_resm(TINFO, "first seqno now: %lu", seqno); + break; + } + for (i = 0; i < NUM_OVERWRITE_MSGS; i++) { + if (inject_msg(filler_str) == -1) + tst_brkm(TBROK|TERRNO, cleanup, + "failed write to /dev/kmsg"); + } + } + + /* first message is overwritten, so this next read should fail */ + TEST(read(fd, msg, sizeof(msg))); + if (TEST_RETURN == -1 && TEST_ERRNO == EPIPE) + tst_resm(TPASS, "read failed with EPIPE as expected"); + else + tst_resm(TFAIL|TTERRNO, "read returned: %ld", TEST_RETURN); + + /* seek position is updated to the next available record */ + tst_resm(TINFO, "TEST: Subsequent reads() will return available " + "records again"); + if (find_msg(fd, "", msg, sizeof(msg), 1) != 0) + tst_resm(TFAIL|TTERRNO, "read returned: %ld", TEST_RETURN); + else + tst_resm(TPASS, "after EPIPE read returned next record"); + + SAFE_CLOSE(cleanup, fd); +} + +static void test_seek(void) +{ + int k, j = NUM_READ_RETRY, fd; + char msg[MAX_MSGSIZE]; + unsigned long seqno[2]; + + /* 1. read() after SEEK_SET 0 returns same (first) message */ + tst_resm(TINFO, "TEST: seek SEEK_SET 0"); + + fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + if (fd < 0) + tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg"); + + while (j) { + for (k = 0; k < 2; k++) { + TEST(read(fd, msg, sizeof(msg))); + if (TEST_RETURN == -1) { + if (errno == EPIPE) + break; + else + tst_brkm(TBROK|TTERRNO, cleanup, + "failed to read /dev/kmsg"); + } + if (get_msg_fields(msg, NULL, &seqno[k]) != 0) + tst_resm(TFAIL, "failed to parse seqid: %s", + msg); + if (k == 0) + if (lseek(fd, 0, SEEK_SET) == -1) + tst_resm(TFAIL|TERRNO, + "SEEK_SET 0 failed"); + } + + if (TEST_RETURN != -1) + break; + + /* give a second to whoever overwrote first message to finish */ + sleep(1); + j--; + + /* read above has returned EPIPE, reopen fd and try again */ + SAFE_CLOSE(cleanup, fd); + fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + if (fd < 0) + tst_brkm(TBROK|TERRNO, cleanup, + "failed to open /dev/kmsg"); + } + + if (!j) { + tst_resm(TWARN, "exceeded: %d attempts", NUM_READ_RETRY); + } else { + if (seqno[0] != seqno[1]) + tst_resm(TFAIL, "SEEK_SET 0"); + else + tst_resm(TPASS, "SEEK_SET 0"); + } + + /* 2. messages after SEEK_END 0 shouldn't contain MSG_PREFIX */ + tst_resm(TINFO, "TEST: seek SEEK_END 0"); + if (lseek(fd, 0, SEEK_END) == -1) + tst_resm(TFAIL|TERRNO, "lseek SEEK_END 0 failed"); + if (find_msg(fd, MSG_PREFIX, msg, sizeof(msg), 0) != 0) + tst_resm(TPASS, "SEEK_END 0"); + else + tst_resm(TFAIL, "SEEK_END 0 found: %s", msg); + +#ifdef SEEK_DATA + /* 3. messages after SEEK_DATA 0 shouldn't contain MSG_PREFIX */ + tst_resm(TINFO, "TEST: seek SEEK_DATA 0"); + + /* clear ring buffer */ + if (ltp_syscall(__NR_syslog, 5, NULL, 0) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "syslog clear failed"); + if (lseek(fd, 0, SEEK_DATA) == -1) + tst_resm(TFAIL|TERRNO, "lseek SEEK_DATA 0 failed"); + if (find_msg(fd, MSG_PREFIX, msg, sizeof(msg), 0) != 0) + tst_resm(TPASS, "SEEK_DATA 0"); + else + tst_resm(TFAIL, "SEEK_DATA 0 found: %s", msg); +#endif + SAFE_CLOSE(cleanup, fd); +} + +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(); + for (lc = 0; TEST_LOOPING(lc); lc++) { + /* run test_inject first so log isn't empty for other tests */ + test_inject(); + test_read_nonblock(); + test_read_block(); + test_partial_read(); + test_read_returns_first_message(); + test_messages_overwritten(); + test_seek(); + } + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_require_root(NULL); + if (tst_kvercmp(3, 5, 0) < 0) + tst_brkm(TCONF, NULL, "This test requires kernel" + " >= 3.5.0"); + srand(getpid()); + TEST_PAUSE; +} + +static void cleanup(void) +{ + TEST_CLEANUP; +} diff --git a/testcases/kernel/security/prot_hsymlinks/Makefile b/testcases/kernel/security/prot_hsymlinks/Makefile index cd49588..effd5da 100644 --- a/testcases/kernel/security/prot_hsymlinks/Makefile +++ b/testcases/kernel/security/prot_hsymlinks/Makefile @@ -2,7 +2,8 @@ # # 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. +# 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 would be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -11,7 +12,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA top_srcdir ?= ../../../.. diff --git a/testcases/kernel/security/prot_hsymlinks/prot_hsymlinks.c b/testcases/kernel/security/prot_hsymlinks/prot_hsymlinks.c index 82bc770..558681a 100644 --- a/testcases/kernel/security/prot_hsymlinks/prot_hsymlinks.c +++ b/testcases/kernel/security/prot_hsymlinks/prot_hsymlinks.c @@ -3,7 +3,8 @@ * * 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. + * 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 would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/testcases/kernel/syscalls/chown/chown01.c b/testcases/kernel/syscalls/chown/chown01.c index 50b9ea5..d95564e 100644 --- a/testcases/kernel/syscalls/chown/chown01.c +++ b/testcases/kernel/syscalls/chown/chown01.c @@ -116,9 +116,7 @@ #include <signal.h> #include "test.h" #include "usctest.h" - -void setup(); -void cleanup(); +#include "safe_macros.h" char *TCID = "chown01"; int TST_TOTAL = 1; @@ -126,8 +124,10 @@ int TST_TOTAL = 1; int exp_enos[] = { 0, 0 }; char fname[255]; -int fd, uid, gid; -char *buf = "davef"; +int uid, gid; + +static void setup(void); +static void cleanup(void); int main(int ac, char **av) { @@ -163,7 +163,7 @@ int main(int ac, char **av) } -void setup() +static void setup(void) { tst_sig(NOFORK, DEF_HANDLER, cleanup); @@ -176,17 +176,11 @@ void setup() gid = getegid(); sprintf(fname, "t_%d", getpid()); - if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) - tst_brkm(TBROK | TERRNO, cleanup, - "open(%s, O_RDWR|O_CREAT,0700) failed", fname); - else if (write(fd, &buf, strlen(buf)) == -1) - tst_brkm(TBROK | TERRNO, cleanup, - "write(%s, &buf, strlen(buf)) failed", fname); - else if (close(fd) == -1) - tst_brkm(TBROK | TERRNO, cleanup, "close(%s) failed", fname); + + SAFE_FILE_PRINTF(cleanup, fname, "davef"); } -void cleanup() +static void cleanup(void) { TEST_CLEANUP; diff --git a/testcases/kernel/syscalls/dup2/dup205.c b/testcases/kernel/syscalls/dup2/dup205.c index c728fcc..0528beb 100644 --- a/testcases/kernel/syscalls/dup2/dup205.c +++ b/testcases/kernel/syscalls/dup2/dup205.c @@ -112,8 +112,8 @@ int main(int ac, char *av[]) } } unlink(pfilname); - if (ifile > 0) - close(fildes[ifile - 1]); + for (ifile = fildes[0]; ifile < min + 10; ifile++) + close(fildes[ifile]); if (local_flag == PASSED) { tst_resm(TPASS, "Test passed."); } else { diff --git a/testcases/kernel/syscalls/getrusage/getrusage03.c b/testcases/kernel/syscalls/getrusage/getrusage03.c index 202356c..5d82a94 100644 --- a/testcases/kernel/syscalls/getrusage/getrusage03.c +++ b/testcases/kernel/syscalls/getrusage/getrusage03.c @@ -346,6 +346,13 @@ static void consume(int mega) static void setup(void) { + /* Disable test if the version of the kernel is less than 2.6.32 */ + if ((tst_kvercmp(2, 6, 32)) < 0) { + tst_resm(TCONF, "This ru_maxrss field is not supported"); + tst_resm(TCONF, "before kernel 2.6.32"); + tst_exit(); + } + tst_sig(FORK, DEF_HANDLER, cleanup); TEST_PAUSE; diff --git a/testcases/kernel/syscalls/mmap/mmap13.c b/testcases/kernel/syscalls/mmap/mmap13.c new file mode 100644 index 0000000..e0e13b4 --- /dev/null +++ b/testcases/kernel/syscalls/mmap/mmap13.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2013 FNST, DAN LI <li...@cn...> + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Test Description: + * Verify error signal SIGBUS. + * "Attempted access to a portion of the buffer that does not correspond + * to the file." + * + * Expected Result: + * mmap() should succeed returning the address of the mapped region, + * and an attempt to access the memory which does not correspond to the file + * should rise the signal SIGBUS. + */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <signal.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <setjmp.h> + +#include "test.h" +#include "usctest.h" + +#define TEMPFILE "mmapfile" + +char *TCID = "mmap13"; +int TST_TOTAL = 1; + +static size_t page_sz; +static char *addr; +static int fildes; +static volatile sig_atomic_t pass; +static sigjmp_buf env; + +static void setup(void); +static void cleanup(void); +static void sig_handler(int sig); + +int main(int argc, char *argv[]) +{ + int lc; + char *ch; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + addr = mmap(NULL, page_sz * 2, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, fildes, 0); + + if (addr == MAP_FAILED) { + tst_resm(TFAIL | TERRNO, "mmap() failed on %s", + TEMPFILE); + continue; + } + + if (STD_FUNCTIONAL_TEST) { + + if (sigsetjmp(env, 1) == 0) { + ch = addr + page_sz + 1; + *ch = 0; + } + + if (pass) + tst_resm(TPASS, "Got SIGBUS " + "as expected"); + else + tst_resm(TFAIL, "Invalid access not " + "rise SIGBUS"); + } else { + tst_resm(TPASS, "call succeeded"); + } + + if (munmap(addr, page_sz * 2) != 0) + tst_brkm(TFAIL | TERRNO, cleanup, + "failed to unmap the mmapped pages"); + + pass = 0; + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_sig(NOFORK, sig_handler, cleanup); + + TEST_PAUSE; + + page_sz = getpagesize(); + + tst_tmpdir(); + + fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0766); + if (fildes < 0) + tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed", + TEMPFILE); + + if (ftruncate(fildes, page_sz / 2) == -1) + tst_brkm(TFAIL | TERRNO, cleanup, "ftruncate %s failed", + TEMPFILE); +} + +/* + * This function gets executed when the test process receives + * the signal SIGBUS while trying to access the memory which + * does not correspond to the file. + */ +static void sig_handler(int sig) +{ + if (sig == SIGBUS) { + pass = 1; + siglongjmp(env, 1); + } else { + tst_brkm(TBROK, cleanup, "received an unexpected signal"); + } +} + +static void cleanup(void) +{ + close(fildes); + TEST_CLEANUP; + tst_rmdir(); +} hooks/post-receive -- ltp |