#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/prctl.h>
#include "util.h"
-#include "kdbus.h"
+#include "bus-label.h"
+#include "missing.h"
#include "sd-memfd.h"
+#include "sd-bus.h"
struct sd_memfd {
int fd;
FILE *f;
};
-_public_ int sd_memfd_new(sd_memfd **m) {
- struct kdbus_cmd_memfd_make cmd = {
- .size = sizeof(struct kdbus_cmd_memfd_make),
- };
+_public_ int sd_memfd_new(sd_memfd **m, const char *name) {
+
_cleanup_close_ int kdbus = -1;
+ _cleanup_free_ char *g = NULL;
sd_memfd *n;
assert_return(m, -EINVAL);
if (kdbus < 0)
return -errno;
- if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, &cmd) < 0)
- return -errno;
+ if (name) {
+ /* The kernel side is pretty picky about the character
+ * set here, let's do the usual bus escaping to deal
+ * with that. */
+
+ g = bus_label_escape(name);
+ if (!g)
+ return -ENOMEM;
+
+ name = g;
+
+ } else {
+ char pr[17] = {};
+
+ /* If no name is specified we generate one. We include
+ * a hint indicating our library implementation, and
+ * add the thread name to it */
+
+ assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
+
+ if (isempty(pr))
+ name = "sd";
+ else {
+ _cleanup_free_ char *e = NULL;
+
+ e = bus_label_escape(pr);
+ if (!e)
+ return -ENOMEM;
+
+ g = strappend("sd-", e);
+ if (!g)
+ return -ENOMEM;
+
+ name = g;
+ }
+ }
n = new0(struct sd_memfd, 1);
- if (!n) {
- close_nointr_nofail(cmd.fd);
+ if (!n)
return -ENOMEM;
+
+ n->fd = memfd_create(name, 0, MFD_ALLOW_SEALING);
+ if (n->fd < 0) {
+ free(n);
+ return -errno;
}
- n->fd = cmd.fd;
*m = n;
return 0;
}
-_public_ int sd_memfd_make(int fd, sd_memfd **m) {
+_public_ int sd_memfd_new_from_fd(sd_memfd **m, int fd) {
sd_memfd *n;
- uint64_t sz;
assert_return(m, -EINVAL);
assert_return(fd >= 0, -EINVAL);
- /* Check if this is a valid memfd */
- if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 0)
+ /* Check if this is a sealable fd */
+ if (fcntl(fd, F_GET_SEALS) < 0)
return -ENOTTY;
n = new0(struct sd_memfd, 1);
if (m->f)
fclose(m->f);
else
- close_nointr_nofail(m->fd);
+ safe_close(m->fd);
free(m);
}
if (sealed < 0)
return sealed;
- q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset);
+ q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_PRIVATE, m->fd, offset);
if (q == MAP_FAILED)
return -errno;
return 0;
}
-_public_ int sd_memfd_set_sealed(sd_memfd *m, int b) {
+_public_ int sd_memfd_set_sealed(sd_memfd *m) {
int r;
assert_return(m, -EINVAL);
- r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b);
+ r = fcntl(m->fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
if (r < 0)
return -errno;
}
_public_ int sd_memfd_get_sealed(sd_memfd *m) {
- int r, b;
+ int r;
assert_return(m, -EINVAL);
- r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b);
+ r = fcntl(m->fd, F_GET_SEALS);
if (r < 0)
return -errno;
- return !!b;
+ return (r & (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)) ==
+ (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
}
_public_ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
int r;
+ struct stat stat;
assert_return(m, -EINVAL);
assert_return(sz, -EINVAL);
- r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz);
+ r = fstat(m->fd, &stat);
if (r < 0)
return -errno;
+ *sz = stat.st_size;
return r;
}
assert_return(m, -EINVAL);
- r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
+ r = ftruncate(m->fd, sz);
if (r < 0)
return -errno;
return r;
}
-_public_ int sd_memfd_new_and_map(sd_memfd **m, size_t sz, void **p) {
+_public_ int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p) {
sd_memfd *n;
int r;
- r = sd_memfd_new(&n);
+ r = sd_memfd_new(&n, name);
if (r < 0)
return r;
*m = n;
return 0;
}
+
+_public_ int sd_memfd_get_name(sd_memfd *m, char **name) {
+ char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e;
+ const char *delim, *end;
+ _cleanup_free_ char *n = NULL;
+ ssize_t k;
+
+ assert_return(m, -EINVAL);
+ assert_return(name, -EINVAL);
+
+ sprintf(path, "/proc/self/fd/%i", m->fd);
+
+ k = readlink(path, buf, sizeof(buf));
+ if (k < 0)
+ return -errno;
+
+ if ((size_t) k >= sizeof(buf))
+ return -E2BIG;
+
+ buf[k] = 0;
+
+ delim = strstr(buf, ":[");
+ if (!delim)
+ return -EIO;
+
+ delim = strchr(delim + 2, ':');
+ if (!delim)
+ return -EIO;
+
+ delim++;
+
+ end = strchr(delim, ']');
+ if (!end)
+ return -EIO;
+
+ n = strndup(delim, end - delim);
+ if (!n)
+ return -ENOMEM;
+
+ e = bus_label_unescape(n);
+ if (!e)
+ return -ENOMEM;
+
+ *name = e;
+
+ return 0;
+}