test/zdtmp: add a test to C/R shared memory file descriptors

Any shared memory region can be openned via /proc/self/map_files.

Signed-off-by: Andrei Vagin <avagin@gmail.com>
This commit is contained in:
Andrei Vagin 2020-03-15 10:53:51 +03:00
parent 10b1d46f67
commit c40c09cbbf
5 changed files with 195 additions and 0 deletions

View file

@ -224,6 +224,8 @@ TST_NOFILE := \
memfd01 \
memfd02 \
memfd03 \
shmemfd \
shmemfd-priv \
# jobctl00 \
ifneq ($(ARCH),arm)

View file

@ -0,0 +1,84 @@
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/vfs.h>
#include <fcntl.h>
#include "zdtmtst.h"
const char *test_doc = "Test C/R of shared memory file descriptors";
const char *test_author = "Andrei Vagin <avagin@gmail.com>";
#define err(exitcode, msg, ...) ({ pr_perror(msg, ##__VA_ARGS__); exit(exitcode); })
int main(int argc, char *argv[])
{
void *addr, *priv_addr, *addr2;
char path[4096];
int fd;
test_init(argc, argv);
addr = mmap(NULL, 5 * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if (addr == MAP_FAILED) {
pr_perror("mmap");
return 1;
}
*(int *) addr = 1;
*(int *) (addr + PAGE_SIZE) = 11;
*(int *) (addr + 2 * PAGE_SIZE) = 111;
snprintf(path, sizeof(path), "/proc/self/map_files/%lx-%lx",
(long)addr, (long)addr + 5 * PAGE_SIZE);
fd = open(path, O_RDWR | O_LARGEFILE);
if (fd < 0)
err(1, "Can't open %s", path);
priv_addr = mmap(NULL, 5 * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, PAGE_SIZE);
if (priv_addr == MAP_FAILED) {
pr_perror("mmap");
return 1;
}
addr2 = mmap(NULL, 5 * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 2 * PAGE_SIZE);
if (addr2 == MAP_FAILED) {
pr_perror("mmap");
return 1;
}
*(int *) (priv_addr + PAGE_SIZE) = 22;
test_daemon();
test_waitsig();
if (*(int *) (priv_addr + PAGE_SIZE) != 22) {
fail("the second page of the private mapping is corrupted");
return 1;
}
if (*(int *) (priv_addr) != 11) {
fail("the first page of the private mapping is corrupted");
return 1;
}
if (*(int *) (addr2) != 111) {
fail("the first page of the second shared mapping is corrupted");
return 1;
}
*(int *) (addr2) = 333;
if (*(int *) (addr + 2 * PAGE_SIZE) != 333) {
fail("the first page of the second shared mapping isn't shared");
return 1;
}
*(int *) (addr + 3 * PAGE_SIZE) = 444;
if (*(int *) (priv_addr + 2 * PAGE_SIZE) != 444) {
fail("the third page of the private mapping is corrupted");
return 1;
}
pass();
return 0;
}

View file

@ -0,0 +1 @@
{'flavor': 'h ns', 'flags': 'suid'}

107
test/zdtm/static/shmemfd.c Normal file
View file

@ -0,0 +1,107 @@
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/vfs.h>
#include <fcntl.h>
#include "zdtmtst.h"
const char *test_doc = "Test C/R of shared memory file descriptors";
const char *test_author = "Andrei Vagin <avagin@gmail.com>";
#define err(exitcode, msg, ...) ({ pr_perror(msg, ##__VA_ARGS__); exit(exitcode); })
int main(int argc, char *argv[])
{
int fd, fl_flags1, fl_flags2, fd_flags1, fd_flags2;
struct statfs statfs1, statfs2;
off_t pos1, pos2;
char path[4096];
char buf[5];
void *addr;
test_init(argc, argv);
addr = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if (addr == MAP_FAILED) {
pr_perror("mmap");
return 1;
}
snprintf(path, sizeof(path), "/proc/self/map_files/%lx-%lx",
(long)addr, (long)addr + PAGE_SIZE);
fd = open(path, O_RDWR | O_LARGEFILE);
if (fd < 0)
err(1, "Can't open %s", path);
ftruncate(fd, 0);
munmap(addr, PAGE_SIZE);
if (fcntl(fd, F_SETFL, O_APPEND) < 0)
err(1, "Can't get fl flags");
if ((fl_flags1 = fcntl(fd, F_GETFL)) == -1)
err(1, "Can't get fl flags");
if ((fd_flags1 = fcntl(fd, F_GETFD)) == -1)
err(1, "Can't get fd flags");
if (fstatfs(fd, &statfs1) < 0)
err(1, "statfs issue");
if (write(fd, "hello", 5) != 5)
err(1, "write error");
pos1 = 3;
if (lseek(fd, pos1, SEEK_SET) < 0)
err(1, "seek error");
test_daemon();
test_waitsig();
if ((fl_flags2 = fcntl(fd, F_GETFL)) == -1)
err(1, "Can't get fl flags");
if (fl_flags1 != fl_flags2) {
fail("fl flags differs %x %x", fl_flags1, fl_flags2);
return 1;
}
if ((fd_flags2 = fcntl(fd, F_GETFD)) == -1)
err(1, "Can't get fd flags");
if (fd_flags1 != fd_flags2) {
fail("fd flags differs");
return 1;
}
if (fstatfs(fd, &statfs2) < 0)
err(1, "statfs issue");
if (statfs1.f_type != statfs2.f_type) {
fail("statfs.f_type differs");
return 1;
}
pos2 = lseek(fd, 0, SEEK_CUR);
if (pos1 != pos2) {
fail("position differs");
return 1;
}
if (pread(fd, buf, sizeof(buf), 0) != sizeof(buf)) {
fail("read problem");
return 1;
}
if (memcmp(buf, "hello", sizeof(buf))) {
fail("content mismatch");
return 1;
}
pass();
return 0;
}

View file

@ -0,0 +1 @@
{'flavor': 'h ns', 'flags': 'suid'}