Fix to VMAP virtual address leak

Fujitsu: POSTK_DEBUG_TEMP_FIX_51
Refs: #1024
Change-Id: I1692ee4f004cb4d1f725baf47a8ed31fce1bf42a
This commit is contained in:
Tomoki Shirasawa
2018-07-11 10:34:12 +09:00
committed by Masamichi Takagi
parent 3d365b0d7a
commit 67ebcca74d
16 changed files with 631 additions and 29 deletions

74
test/issues/1024/C1024.sh Executable file
View File

@ -0,0 +1,74 @@
#!/bin/sh
BIN=
SBIN=
LTP=
BOOTPARAM="-c 1-7,17-23,9-15,25-31 -m 10G@0,10G@1"
if [ -f ../../../config.h ]; then
str=`grep "^#define BINDIR " ../../../config.h | head -1 | sed 's/^#define BINDIR /BINDIR=/'`
eval $str
fi
if [ "x$BINDIR" = x ];then
BINDIR="$BIN"
fi
if [ -f ../../../Makefile ]; then
str=`grep ^SBINDIR ../../../Makefile | head -1 | sed 's/ //g'`
eval $str
fi
if [ "x$SBINDIR" = x ];then
SBINDIR="$SBIN"
fi
if [ -f $HOME/ltp/testcases/bin/fork01 ]; then
LTPDIR=$HOME/ltp/testcases
fi
if [ "x$LTPDIR" = x ]; then
LTPDIR="$LTP"
fi
if [ ! -x $SBINDIR/mcreboot.sh ]; then
echo no mcreboot found >&2
exit 1
fi
if lsmod | grep mcctrl > /dev/null 2>&1; then
sudo $SBINDIR/mcstop+release.sh
if lsmod | grep mcctrl > /dev/null 2>&1; then
echo shutdown failed >&2
exit 1
fi
fi
sudo $SBINDIR/mcreboot.sh $BOOTPARAM
if ! lsmod | grep mcctrl > /dev/null 2>&1; then
echo reboot failed >&2
exit 1
fi
if [ ! -x $BINDIR/mcexec ]; then
echo no mcexec found >&2
exit 1
fi
################################################################################
rm -f mcexec
ln -s $BINDIR/mcexec
./C1024T01
./mcexec ./C1024T02
if [ x$LTPDIR = x ]; then
echo no LTP found >&2
exit 1
fi
for i in process_vm_readv02:03 process_vm_readv03:04 process_vm_writev02:05; do
tp=`echo $i|sed 's/:.*//'`
id=`echo $i|sed 's/.*://'`
sudo $BINDIR/mcexec $LTPDIR/bin/$tp 2>&1 | tee $tp.txt
ok=`grep TPASS $tp.txt | wc -l`
ng=`grep TFAIL $tp.txt | wc -l`
if [ $ng = 0 ]; then
echo "*** C1024T$id: $tp OK ($ok)"
else
echo "*** C1024T$id: $tp NG (ok=$ok ng=%ng)"
fi
done

147
test/issues/1024/C1024.txt Normal file
View File

@ -0,0 +1,147 @@
Script started on Wed Jul 11 19:17:51 2018
bash-4.2$ make test
gcc -o C1024T01 C1024T01.c -Wall -g
gcc -o C1024T02 C1024T02.c -Wall -g
sh ./C1024.sh
*** C1024T01 START
19:17:54 c=0
19:22:54 c=9817
19:27:54 c=18527
19:32:55 c=27856
19:37:55 c=37483
19:42:55 c=45813
19:47:55 c=55300
19:52:55 c=64887
19:57:55 c=73167
20:02:55 c=82642
20:07:55 c=92207
20:12:55 c=100535
20:17:55 c=109965
20:22:56 c=119554
20:27:56 c=127708
20:32:56 c=137094
20:37:56 c=146592
20:42:56 c=154906
20:47:56 c=164316
20:52:56 c=173823
20:57:56 c=181913
21:02:56 c=191485
21:07:56 c=201029
21:12:57 c=209331
21:17:57 c=218691
21:22:57 c=228263
21:27:57 c=236463
21:32:57 c=245879
21:37:57 c=255435
21:42:57 c=263831
21:47:57 c=273045
21:52:57 c=282637
21:57:57 c=290994
22:02:58 c=300088
22:07:58 c=309593
22:12:58 c=318283
22:17:58 c=327215
22:22:58 c=336790
22:27:58 c=345148
22:32:58 c=354190
22:37:58 c=363723
22:42:58 c=372165
22:47:58 c=381241
22:52:59 c=390780
22:57:59 c=399701
23:02:59 c=408179
23:07:59 c=417728
23:12:59 c=426767
23:17:59 c=435111
23:22:59 c=444696
23:27:59 c=454153
23:32:59 c=462305
23:37:59 c=471544
23:43:00 c=481128
23:48:00 c=489413
23:53:00 c=498511
23:58:00 c=508002
00:03:00 c=516321
00:08:00 c=525240
00:13:00 c=534764
00:18:00 c=543425
00:23:00 c=552119
00:28:00 c=561668
00:33:01 c=570540
00:38:01 c=578954
00:43:01 c=588458
00:48:01 c=597499
00:53:01 c=605647
00:58:01 c=615083
01:03:01 c=624466
01:08:01 c=632584
01:13:01 c=641645
01:18:02 c=651150
01:23:02 c=659685
01:28:02 c=668129
01:33:02 c=677555
01:38:02 c=686246
01:43:02 c=694575
01:48:02 c=704131
01:53:02 c=713330
01:58:02 c=721354
02:03:02 c=730718
02:08:03 c=740192
02:13:03 c=748106
02:18:03 c=757081
02:23:03 c=766548
02:28:03 c=775053
02:33:03 c=783508
02:38:03 c=793041
02:43:03 c=802198
02:48:03 c=810191
02:53:03 c=819405
02:58:04 c=828856
03:03:04 c=836987
03:08:04 c=845733
03:13:04 c=855234
03:18:04 c=863744
03:23:04 c=872016
03:28:04 c=881451
03:33:04 c=890508
03:38:04 c=898634
03:43:04 c=907499
03:48:05 c=916825
03:53:05 c=924778
03:58:05 c=933039
04:03:05 c=942260
04:08:05 c=950914
04:13:05 c=958693
04:18:05 c=967690
04:23:05 c=976997
04:28:05 c=984635
04:33:05 c=993041
04:38:06 c=1002233
04:43:06 c=1010732
04:48:06 c=1018751
04:53:06 c=1027635
04:58:06 c=1036889
05:03:06 c=1044866
05:05:39 c=1048600
*** C1024T01 OK
*** C1024T02 START
05:05:42 c=0
05:06:21 c=1048600
*** C1024T02 OK
process_vm_readv02 0 TINFO : child 0: memory allocated and initialized.
process_vm_readv02 0 TINFO : child 1: reading string from same memory location.
process_vm_readv02 1 TPASS : expected string received.
*** C1024T03: process_vm_readv02 OK (1)
process_vm_readv03 0 TINFO : child 0: 10 iovecs allocated and initialized.
process_vm_readv03 0 TINFO : child 1: 10 remote iovecs received.
process_vm_readv03 0 TINFO : child 1: 4 local iovecs initialized.
process_vm_readv03 1 TPASS : child 1: all bytes are correctly received.
*** C1024T04: process_vm_readv03 OK (1)
process_vm_writev02 0 TINFO : child 0: memory allocated.
process_vm_writev02 0 TINFO : child 2: write to the same memory location.
process_vm_writev02 1 TPASS : child 0: all bytes are expected.
*** C1024T05: process_vm_writev02 OK (1)
bash-4.2$ exit
exit
Script done on Thu Jul 12 05:43:43 2018

171
test/issues/1024/C1024T01.c Normal file
View File

@ -0,0 +1,171 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/syscall.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#define EXEC_CNT (1024 * 1024)
#define FORK_CNT 24
void
killall()
{
fprintf(stderr, "*** C1024T01 NG\n");
fflush(stderr);
kill(-getpid(), SIGKILL);
exit(1);
}
void
print(int c)
{
time_t t;
char tbuf[16];
time(&t);
strftime(tbuf, 16, "%H:%M:%S", localtime(&t));
fprintf(stderr, "%s c=%d\n", tbuf, c);
fflush(stderr);
}
int
main(int argc, char **argv)
{
int *c;
pid_t pids[FORK_CNT];
int pfd[FORK_CNT];
int i;
int st;
int maxfd = -1;
int rc;
char buf[1024];
fprintf(stderr, "*** C1024T01 START\n");
c = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
if (c == (void *)-1) {
perror("mmap");
exit(1);
}
*c = 0;
print(*c);
setpgid(0, 0);
for (i = 0; i < FORK_CNT; i++) {
int fds[2];
if (pipe(fds) == -1) {
perror("pipe");
exit(1);
}
fflush(stderr);
if ((pids[i] = fork()) == 0) {
close(fds[0]);
close(0);
close(1);
close(2);
open("/dev/null", O_RDONLY);
dup(fds[1]);
dup(fds[1]);
while (*c <= EXEC_CNT) {
pid_t pid;
if ((pid = fork()) == 0) {
execl("./mcexec", "./mcexec",
"/bin/sleep", "0", NULL);
perror("execve");
exit(1);
}
if (pid == -1) {
perror("fork");
exit(1);
}
while ((rc = waitpid(pid, &st, 0)) == -1 &&
errno == EINTR);
if (rc == -1) {
perror("wait");
exit(1);
}
if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
sprintf(buf, "exit: %08x\n", st);
write(2, buf, strlen(buf));
exit(1);
}
__sync_fetch_and_add(c, 1);
}
exit(0);
}
close(fds[1]);
pfd[i] = fds[0];
if (pfd[i] > maxfd)
maxfd = pfd[i];
if (pids[i] == -1) {
perror("fork");
killall();
}
}
for (;;) {
fd_set readfds;
int e = 0;
struct timeval to;
FD_ZERO(&readfds);
for (i = 0; i < FORK_CNT; i++) {
if (pfd[i] != -1) {
FD_SET(pfd[i], &readfds);
e++;
}
}
if (!e)
break;
to.tv_sec = 300;
to.tv_usec = 0;
rc = select(maxfd + 1, &readfds, NULL, NULL, &to);
if (rc == 0) {
print(*c);
continue;
}
for (i = 0; i < FORK_CNT; i++) {
if (pfd[i] != -1 && FD_ISSET(pfd[i], &readfds)) {
if ((rc = read(pfd[i], buf, 1024)) == -1) {
perror("read");
killall();
}
if (rc == 0) {
close(pfd[i]);
pfd[i] = -1;
}
else {
write(2, buf, rc);
killall();
}
}
}
}
for (i = 0; i < FORK_CNT; i++) {
while ((rc = waitpid(pids[i], &st, 0)) == -1 && errno == EINTR);
if (rc == -1) {
perror("wait");
killall();
}
if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
sprintf(buf, "%d: exit: %08x\n", pids[i], st);
killall();
}
}
print(*c);
if (*c <= EXEC_CNT) {
fprintf(stderr, "*** C1024T01 NG\n");
}
fprintf(stderr, "*** C1024T01 OK\n");
exit(0);
}

177
test/issues/1024/C1024T02.c Normal file
View File

@ -0,0 +1,177 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/syscall.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define READ_CNT (1024 *1024)
#define FORK_CNT 24
void
killall()
{
fprintf(stderr, "*** C1024T02 NG\n");
fflush(stderr);
kill(-getpid(), SIGKILL);
exit(1);
}
void
print(int c)
{
time_t t;
char tbuf[16];
time(&t);
strftime(tbuf, 16, "%H:%M:%S", localtime(&t));
fprintf(stderr, "%s c=%d\n", tbuf, c);
fflush(stderr);
}
int
main(int argc, char **argv)
{
key_t key;
int shmid;
int *c;
pid_t pids[FORK_CNT];
int pfd[FORK_CNT];
int i;
int st;
int maxfd = -1;
int rc;
char buf[1024];
struct shmid_ds shmbuf;
fprintf(stderr, "*** C1024T02 START\n");
key = ftok("C1024T02", 1);
if ((shmid = shmget(key, 4096, IPC_CREAT | 0660)) == -1) {
perror("shmget");
exit(1);
}
if ((c = shmat(shmid, NULL, 0)) == (void *)-1) {
perror("shmget");
exit(1);
}
if (shmctl(shmid, IPC_RMID, &shmbuf) == -1) {
perror("RMID");
exit(1);
}
*c = 0;
print(*c);
setpgid(0, 0);
for (i = 0; i < FORK_CNT; i++) {
int fds[2];
if (pipe(fds) == -1) {
perror("pipe");
exit(1);
}
fflush(stderr);
if ((pids[i] = fork()) == 0) {
int fd;
close(fds[0]);
close(0);
close(1);
close(2);
open("/dev/null", O_RDONLY);
dup(fds[1]);
dup(fds[1]);
if ((fd = open("/proc/self/maps", O_RDONLY)) == -1) {
perror("open");
exit(1);
}
while (*c <= READ_CNT) {
lseek(fd, 0L, SEEK_SET);
if ((rc = read(fd, buf, 1024)) <= 0) {
if (rc == 0) {
fprintf(stderr, "EOF\n");
}
else {
perror("read");
}
exit(1);
}
__sync_fetch_and_add(c, 1);
}
exit(0);
}
close(fds[1]);
pfd[i] = fds[0];
if (pfd[i] > maxfd)
maxfd = pfd[i];
if (pids[i] == -1) {
perror("fork");
killall();
}
}
for (;;) {
fd_set readfds;
int e = 0;
struct timeval to;
FD_ZERO(&readfds);
for (i = 0; i < FORK_CNT; i++) {
if (pfd[i] != -1) {
FD_SET(pfd[i], &readfds);
e++;
}
}
if (!e)
break;
to.tv_sec = 300;
to.tv_usec = 0;
rc = select(maxfd + 1, &readfds, NULL, NULL, &to);
if (rc == 0) {
print(*c);
continue;
}
for (i = 0; i < FORK_CNT; i++) {
if (pfd[i] != -1 && FD_ISSET(pfd[i], &readfds)) {
if ((rc = read(pfd[i], buf, 1024)) == -1) {
perror("read");
killall();
}
if (rc == 0) {
close(pfd[i]);
pfd[i] = -1;
}
else {
write(2, buf, rc);
print(*c);
killall();
}
}
}
}
for (i = 0; i < FORK_CNT; i++) {
while ((rc = waitpid(pids[i], &st, 0)) == -1 && errno == EINTR);
if (rc == -1) {
perror("wait");
killall();
}
if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
sprintf(buf, "%d: exit: %08x\n", pids[i], st);
killall();
}
}
print(*c);
if (*c <= READ_CNT) {
fprintf(stderr, "*** C1024T02 NG\n");
}
fprintf(stderr, "*** C1024T02 OK\n");
exit(0);
}

16
test/issues/1024/Makefile Normal file
View File

@ -0,0 +1,16 @@
CC=gcc
TARGET=C1024T01 C1024T02
all:: $(TARGET)
C1024T01: C1024T01.c
$(CC) -o C1024T01 C1024T01.c -Wall -g
C1024T02: C1024T02.c
$(CC) -o C1024T02 C1024T02.c -Wall -g
test:: $(TARGET)
sh ./C1024.sh
clean::
rm -f *.o $(TARGET) mcexec

24
test/issues/1024/README Normal file
View File

@ -0,0 +1,24 @@
【Issue#1024 動作確認】
□ テスト内容
1. VMAP領域の仮想アドレス回収漏れはプログラム起動時、および、procfsアクセス時
に存在する。VMAP領域は1M(1024×1024)ページ分の仮想アドレスが割り当て可能
なので、以下を1M回以上繰り返しても問題が発生しないことを確認する。
C1024T01 mcexec sleep 0を1M回以上行う
C1024T02 /proc/self/mapsのreadを1M回以上行う
2. 変更がVMAP領域を使用する他の処理に影響ないことをLTPを用いて確認する。
C1024T03 process_vm_readv02 (process_vm_readvの処理でVMAPを使用)
C1024T04 process_vm_readv03 (process_vm_readvの処理でVMAPを使用)
C1024T05 process_vm_writev02 (process_vm_writevの処理でVMAPを使用)
□ 実行手順
$ make test
実行できない場合は、C1024.shの以下の行を適切に書き換えた後に実行。
BIN= mcexec が存在するパス
SBIN= mcreboot.sh が存在するパス
LTP= LTP が存在するパス
□ 実行結果
C1024.txt 参照。
全ての項目が OK となっていることを確認。