Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions criu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ $(obj)/criu: $(PROGRAM-BUILTINS)
$(Q) $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LIBS) $(WRAPFLAGS) $(GMONLDOPT) -rdynamic -o $@

UNIT-BUILTINS += $(obj)/util.o
UNIT-BUILTINS += $(obj)/bfd.o
UNIT-BUILTINS += $(obj)/config.o
UNIT-BUILTINS += $(obj)/log.o
UNIT-BUILTINS += $(obj)/string.o
Expand Down
68 changes: 57 additions & 11 deletions criu/bfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
*/
#define BUFSIZE (PAGE_SIZE)

#define BFD_MAX_DYNAMIC_SIZE (2 * 1024 * 1024)

struct bfd_buf {
char *mem;
struct list_head l;
Expand Down Expand Up @@ -70,18 +72,24 @@ static int buf_get(struct xbuf *xb)

xb->mem = b->mem;
xb->data = xb->mem;
xb->bsize = BUFSIZE;
xb->sz = 0;
xb->buf = b;
return 0;
}

static void buf_put(struct xbuf *xb)
{
/*
* Don't unmap buffer back, it will get reused
* by next bfdopen call
*/
list_add(&xb->buf->l, &bufs);
if (xb->buf) {
/*
* Don't unmap standard buffer back, it will get reused
* by next bfdopen call
*/
list_add(&xb->buf->l, &bufs);
} else {
/* This buffer was dynamically extended, unmap it */
munmap(xb->mem, xb->bsize);
}
xb->buf = NULL;
xb->mem = NULL;
xb->data = NULL;
Expand Down Expand Up @@ -144,7 +152,7 @@ static int brefill(struct bfd *f)
memmove(b->mem, b->data, b->sz);
b->data = b->mem;

ret = read_all(f->fd, b->mem + b->sz, BUFSIZE - b->sz);
ret = read_all(f->fd, b->mem + b->sz, b->bsize - b->sz);
if (ret < 0) {
pr_perror("Error reading file");
return -1;
Expand Down Expand Up @@ -172,6 +180,40 @@ char *breadline(struct bfd *f)
return breadchr(f, '\n');
}

static int bextend(struct bfd *f)
{
struct xbuf *b = &f->b;
void *newbuf;
long newsize = b->bsize * 2;

if (newsize > BFD_MAX_DYNAMIC_SIZE) {
pr_err("Line too long to fit in BFD_MAX_DYNAMIC_SIZE\n");
return -1;
}

if (b->buf) {
newbuf = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (newbuf == MAP_FAILED) {
pr_perror("Error allocating buffer");
return -1;
}
memcpy(newbuf, b->mem, b->sz);
list_add(&b->buf->l, &bufs);
b->buf = NULL;
} else {
newbuf = mremap(b->mem, b->bsize, newsize, MREMAP_MAYMOVE);
if (newbuf == MAP_FAILED) {
pr_perror("Error allocating buffer");
return -1;
}
}
b->mem = newbuf;
b->data = newbuf;
b->bsize = newsize;
return 0;
}

char *breadchr(struct bfd *f, char c)
{
struct xbuf *b = &f->b;
Expand All @@ -195,9 +237,12 @@ char *breadchr(struct bfd *f, char c)
if (!b->sz)
return NULL;

if (b->sz == BUFSIZE) {
pr_err("The bfd buffer is too small\n");
return ERR_PTR(-EIO);
if (b->sz == b->bsize) {
if (bextend(f)) {
pr_err("The bfd buffer is too small\n");
return ERR_PTR(-EIO);
}
goto refill;
}
/*
* Last bytes may lack the \n at the
Expand All @@ -216,6 +261,7 @@ char *breadchr(struct bfd *f, char c)
return b->data;
}

refill:
/*
* small optimization -- we've scanned b->sz
* symbols already, no need to re-scan them after
Expand Down Expand Up @@ -252,14 +298,14 @@ static int __bwrite(struct bfd *bfd, const void *buf, int size)
{
struct xbuf *b = &bfd->b;

if (b->sz + size > BUFSIZE) {
if (b->sz + size > b->bsize) {
int ret;
ret = bflush(bfd);
if (ret < 0)
return ret;
}

if (size > BUFSIZE)
if (size > b->bsize)
return write_all(bfd->fd, buf, size);

memcpy(b->data + b->sz, buf, size);
Expand Down
1 change: 1 addition & 0 deletions criu/include/bfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct xbuf {
char *mem; /* buffer */
char *data; /* position we see bytes at */
unsigned int sz; /* bytes sitting after b->pos */
unsigned int bsize;
struct bfd_buf *buf;
};

Expand Down
87 changes: 87 additions & 0 deletions criu/unittest/unit.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,97 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#include "log.h"
#include "util.h"
#include "criu-log.h"
#include "bfd.h"

int parse_statement(int i, char *line, char **configuration);

static void test_bfd(void)
{
struct bfd f;
char *str;
const int lines = 5;
char *long_line[lines];
int size = 1024 * 1024;
int i, fd;

fd = memfd_create("criu-bfd-test", 0);
assert(fd >= 0);

for (i = 0; i < lines; i++) {
int j;

long_line[i] = malloc(size + 2);
assert(long_line[i]);
long_line[i][0] = 'A' + (i % 26);
for (j = 1; j < size; j++)
long_line[i][j] = 'a' + (j % 26);
long_line[i][size] = '\n';
long_line[i][size + 1] = '\0';

assert(write(fd, long_line[i], size + 1) == size + 1);
}
assert(lseek(fd, 0, SEEK_SET) == 0);

f.fd = fd;
assert(bfdopenr(&f) == 0);

for (i = 0; i < lines; i++) {
str = breadline(&f);
assert(str);
assert(strlen(str) == size);
/* long_line has \n, str hasn't */
assert(strcmp(str, long_line[i]) != 0);
str[size] = '\n';
assert(memcmp(str, long_line[i], size + 1) == 0);
}

bclose(&f);
for (i = 0; i < lines; i++)
free(long_line[i]);
}

static void test_bwrite(void)
{
struct bfd f;
char *buf;
int size = 1024 * 1024;
int i;
int fd;
char *read_buf;

fd = memfd_create("criu-bfd-test", 0);
assert(fd >= 0);

buf = malloc(size);
assert(buf);
for (i = 0; i < size; i++)
buf[i] = 'z' - (i % 26);

f.fd = dup(fd);
assert(f.fd >= 0);
assert(bfdopenw(&f) == 0);

assert(bwrite(&f, buf, size) == size);
bclose(&f);

assert(lseek(fd, 0, SEEK_SET) == 0);
read_buf = malloc(size);
assert(read_buf);
assert(read(fd, read_buf, size) == size);
assert(memcmp(buf, read_buf, size) == 0);

close(fd);
free(buf);
free(read_buf);
}

int main(int argc, char *argv[], char *envp[])
{
char **configuration;
Expand All @@ -16,6 +100,9 @@ int main(int argc, char *argv[], char *envp[])
configuration = malloc(10 * sizeof(char *));
log_init(NULL);

test_bfd();
test_bwrite();

i = parse_statement(0, "", configuration);
assert(i == 0);

Expand Down
4 changes: 4 additions & 0 deletions test/zdtm.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,10 @@ def start(self):
else:
print("Test is SUID")

if test_flag(self.__desc, 'ext-uid-map'):
env['ZDTM_UID_MAP'] = "0 0 4294967295"
env['ZDTM_GID_MAP'] = "0 0 4294967295"

if self.__flavor.ns:
env['ZDTM_NEWNS'] = "1"
env['ZDTM_ROOT'] = self.__flavor.root
Expand Down
19 changes: 13 additions & 6 deletions test/zdtm/lib/ns.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,15 +492,20 @@ void ns_create(int argc, char **argv)
char pname[PATH_MAX];
int fd;

char *ext_uid_map = getenv("ZDTM_UID_MAP");
char *ext_gid_map = getenv("ZDTM_GID_MAP");

snprintf(pname, sizeof(pname), "/proc/%d/uid_map", pid);
fd = open(pname, O_WRONLY);
if (fd < 0) {
fprintf(stderr, "open(%s): %m\n", pname);
exit(1);
}
if (write(fd, UID_MAP, sizeof(UID_MAP)) < 0) {
fprintf(stderr, "write(" UID_MAP "): %m\n");
exit(1);

if (ext_uid_map) {
dprintf(fd, "%s", ext_uid_map);
} else {
write(fd, UID_MAP, sizeof(UID_MAP) - 1);
}
close(fd);

Expand All @@ -510,9 +515,11 @@ void ns_create(int argc, char **argv)
fprintf(stderr, "open(%s): %m\n", pname);
exit(1);
}
if (write(fd, GID_MAP, sizeof(GID_MAP)) < 0) {
fprintf(stderr, "write(" GID_MAP "): %m\n");
exit(1);

if (ext_gid_map) {
dprintf(fd, "%s", ext_gid_map);
} else {
write(fd, GID_MAP, sizeof(GID_MAP) - 1);
}
close(fd);
}
Expand Down
3 changes: 3 additions & 0 deletions test/zdtm/static/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ TST_NOFILE := \
sigtrap01 \
change_mnt_context \
fd_offset \
massive_groups \
# jobctl00 \

PKG_CONFIG ?= pkg-config
Expand Down Expand Up @@ -736,6 +737,8 @@ cgroupv2_01: LDLIBS += -pthread
uprobes: CFLAGS += $(call pkg-cflags, libtracefs libtraceevent)
uprobes: LDLIBS += $(call pkg-libs, libtracefs libelf)

massive_groups: LDLIBS += -lrt -pthread

$(LIB): force
$(Q) $(MAKE) -C $(LIBDIR)

Expand Down
Loading
Loading