sd-memfd.c revision ddeb424198649c3993a54efc81652325b6e3bfa5
337eebb936be1da1215535e866965ce54c82d755Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
652e737517bbbae692923246aeb687e2d1f314efZbigniew Jędrzejewski-Szmek
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering/***
652e737517bbbae692923246aeb687e2d1f314efZbigniew Jędrzejewski-Szmek This file is part of systemd.
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering Copyright 2013 Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering systemd is free software; you can redistribute it and/or modify it
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering under the terms of the GNU Lesser General Public License as published by
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering (at your option) any later version.
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering systemd is distributed in the hope that it will be useful, but
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering Lesser General Public License for more details.
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering You should have received a copy of the GNU Lesser General Public License
652e737517bbbae692923246aeb687e2d1f314efZbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering***/
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering#include <stdio.h>
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering#include <fcntl.h>
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering#include <sys/ioctl.h>
15e913230c652ace36abfbf2b6fed0c1f56b8711Lennart Poettering#include <sys/mman.h>
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
93a1d735aca5584a005d851f12cb0b8c7bb5e5caLennart Poettering#include "util.h"
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering#include "kdbus.h"
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering#include "sd-memfd.h"
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poetteringstruct sd_memfd {
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering int fd;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering FILE *f;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering};
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poetteringint sd_memfd_new(sd_memfd **m) {
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering _cleanup_close_ int kdbus = -1;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering sd_memfd *n;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering int fd;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering if (!m)
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering return -EINVAL;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering if (fd < 0)
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering return -errno;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, &fd) < 0)
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering return -errno;
2b93b027d3a68b5d7ae26d0c2cd487eb5019d2a9Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering n = new0(struct sd_memfd, 1);
0e0320e04500d1e68630b3973714f14cfb7b3450Lennart Poettering if (!n)
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering return -ENOMEM;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering n->fd = fd;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering *m = n;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering return 0;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering}
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
f13b388f97bc3ba8db844bd3413d510e2466a0b6Kay Sieversint sd_memfd_make(int fd, sd_memfd **m) {
f13b388f97bc3ba8db844bd3413d510e2466a0b6Kay Sievers sd_memfd *n;
51dfddc2cceb345ffc994014e4a4b3f2d2d3a3aaColin Guthrie uint64_t sz;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering if (!m)
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering return -EINVAL;
7c9a6f906308a6474f1ebb98058c4a33a02c33f1Lennart Poettering if (fd < 0)
4acbce79798347cddf1e1d42e9be571e0a041873Zbigniew Jędrzejewski-Szmek return -EINVAL;
08c51903fb895e836866b8e7a09f0523b72b9aafMarc-Antoine Perennou
/* Check if this is a valid memfd */
if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 0)
return -ENOTTY;
n = new0(struct sd_memfd, 1);
if (!n)
return -ENOMEM;
n->fd = fd;
*m = n;
return 0;
}
void sd_memfd_free(sd_memfd *m) {
if (!m)
return;
if (m->f)
fclose(m->f);
else
close_nointr_nofail(m->fd);
free(m);
}
int sd_memfd_get_fd(sd_memfd *m) {
if (!m)
return -EINVAL;
return m->fd;
}
int sd_memfd_get_file(sd_memfd *m, FILE **f) {
if (!m)
return -EINVAL;
if (!f)
return -EINVAL;
if (!m->fd) {
m->f = fdopen(m->fd, "r+");
if (!m->f)
return -errno;
}
*f = m->f;
return 0;
}
int sd_memfd_dup_fd(sd_memfd *m) {
int fd;
if (!m)
return -EINVAL;
fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3);
if (fd < 0)
return -errno;
return fd;
}
int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) {
void *q;
int sealed;
if (!m)
return -EINVAL;
if (size <= 0)
return -EINVAL;
if (!p)
return -EINVAL;
sealed = sd_memfd_get_sealed(m);
if (sealed < 0)
return sealed;
q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset);
if (q == MAP_FAILED)
return -errno;
*p = q;
return 0;
}
int sd_memfd_set_sealed(sd_memfd *m, int b) {
int r;
if (!m)
return -EINVAL;
r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b);
if (r < 0)
return -errno;
return 0;
}
int sd_memfd_get_sealed(sd_memfd *m) {
int r, b;
if (!m)
return -EINVAL;
r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b);
if (r < 0)
return -errno;
return !!b;
}
int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
int r;
if (!m)
return -EINVAL;
if (!sz)
return -EINVAL;
r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz);
if (r < 0)
return -errno;
return r;
}
int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
int r;
if (!m)
return -EINVAL;
r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
if (r < 0)
return -errno;
return r;
}