Move the little "libcontainer" code into libglnx
I want to share it with ostree, and potentially xdg-app.
This commit is contained in:
parent
deef74e7a0
commit
4b19dd1266
@ -28,8 +28,6 @@ librpmostree_la_SOURCES = \
|
||||
src/rpmostree-util.h \
|
||||
src/rpmostree-passwd-util.c \
|
||||
src/rpmostree-passwd-util.h \
|
||||
src/rpmostree-libcontainer.c \
|
||||
src/rpmostree-libcontainer.h \
|
||||
src/rpmostree-cleanup.h \
|
||||
src/rpmostree-treepkgdiff.c \
|
||||
src/rpmostree-treepkgdiff.h \
|
||||
|
2
libglnx
2
libglnx
@ -1 +1 @@
|
||||
Subproject commit 08d68d16ccd464854bc329e5d75fc6d2a38f7878
|
||||
Subproject commit a11b2eb20aa20db8076eb5fc86848d50cb6b6477
|
@ -35,7 +35,6 @@
|
||||
#include "rpmostree-json-parsing.h"
|
||||
#include "rpmostree-cleanup.h"
|
||||
#include "rpmostree-treepkgdiff.h"
|
||||
#include "rpmostree-libcontainer.h"
|
||||
#include "rpmostree-postprocess.h"
|
||||
#include "rpmostree-passwd-util.h"
|
||||
|
||||
@ -645,7 +644,7 @@ rpmostree_compose_builtin_tree (int argc,
|
||||
{
|
||||
/* This happens on RHEL6, not going to debug it further right now... */
|
||||
if (errno == EINVAL)
|
||||
_rpmostree_libcontainer_set_not_available ();
|
||||
glnx_libcontainer_set_not_available ();
|
||||
else
|
||||
{
|
||||
_rpmostree_set_prefix_error_from_errno (error, errno, "mount(/, MS_PRIVATE): ");
|
||||
@ -656,7 +655,7 @@ rpmostree_compose_builtin_tree (int argc,
|
||||
/* Mount several directories read only for protection from librpm
|
||||
* and any stray code in yum/hawkey.
|
||||
*/
|
||||
if (_rpmostree_libcontainer_get_available ())
|
||||
if (glnx_libcontainer_get_available ())
|
||||
{
|
||||
struct stat stbuf;
|
||||
/* Protect /var/lib/rpm if (and only if) it's a regular directory.
|
||||
@ -666,14 +665,14 @@ rpmostree_compose_builtin_tree (int argc,
|
||||
bind mount. */
|
||||
if (lstat ("/var/lib/rpm", &stbuf) == 0 && S_ISDIR (stbuf.st_mode))
|
||||
{
|
||||
if (!_rpmostree_libcontainer_bind_mount_readonly ("/var/lib/rpm", error))
|
||||
if (!glnx_libcontainer_bind_mount_readonly ("/var/lib/rpm", error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Protect the system's /etc and /usr */
|
||||
if (!_rpmostree_libcontainer_bind_mount_readonly ("/etc", error))
|
||||
if (!glnx_libcontainer_bind_mount_readonly ("/etc", error))
|
||||
goto out;
|
||||
if (!_rpmostree_libcontainer_bind_mount_readonly ("/usr", error))
|
||||
if (!glnx_libcontainer_bind_mount_readonly ("/usr", error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1,234 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2014 Colin Walters <walters@verbum.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <glib-unix.h>
|
||||
#include <sys/mount.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
|
||||
#include "rpmostree-util.h"
|
||||
#include "rpmostree-cleanup.h"
|
||||
#include "rpmostree-libcontainer.h"
|
||||
#include "libgsystem.h"
|
||||
|
||||
static gboolean container_available = TRUE;
|
||||
|
||||
void
|
||||
_rpmostree_libcontainer_set_not_available (void)
|
||||
{
|
||||
container_available = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_rpmostree_libcontainer_get_available (void)
|
||||
{
|
||||
return container_available;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_rpmostree_libcontainer_bind_mount_readonly (const char *path, GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (mount (path, path, NULL, MS_BIND | MS_PRIVATE, NULL) != 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"mount(%s, MS_BIND): %s",
|
||||
path,
|
||||
g_strerror (errsv));
|
||||
goto out;
|
||||
}
|
||||
if (mount (path, path, NULL, MS_BIND | MS_PRIVATE | MS_REMOUNT | MS_RDONLY, NULL) != 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"mount(%s, MS_BIND | MS_RDONLY): %s",
|
||||
path,
|
||||
g_strerror (errsv));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Based on code from nspawn.c */
|
||||
int
|
||||
_rpmostree_libcontainer_make_api_mounts (const char *dest)
|
||||
{
|
||||
typedef struct MountPoint {
|
||||
const char *what;
|
||||
const char *where;
|
||||
const char *type;
|
||||
const char *options;
|
||||
unsigned long flags;
|
||||
gboolean fatal;
|
||||
} MountPoint;
|
||||
|
||||
static const MountPoint mount_table[] = {
|
||||
{ "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, TRUE },
|
||||
{ "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, TRUE }, /* Bind mount first */
|
||||
{ NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, TRUE }, /* Then, make it r/o */
|
||||
{ "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, TRUE },
|
||||
{ "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, TRUE },
|
||||
{ "devpts", "/dev/pts", "devpts","newinstance,ptmxmode=0666,mode=620,gid=5", MS_NOSUID|MS_NOEXEC, TRUE },
|
||||
{ "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, TRUE },
|
||||
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, TRUE },
|
||||
{ "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, FALSE }, /* Bind mount first */
|
||||
{ NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, FALSE }, /* Then, make it r/o */
|
||||
};
|
||||
|
||||
unsigned k;
|
||||
|
||||
for (k = 0; k < G_N_ELEMENTS(mount_table); k++)
|
||||
{
|
||||
gs_free char *where = NULL;
|
||||
int t;
|
||||
|
||||
where = g_build_filename (dest, mount_table[k].where, NULL);
|
||||
|
||||
t = mkdir (where, 0755);
|
||||
if (t < 0 && errno != EEXIST)
|
||||
{
|
||||
if (!mount_table[k].fatal)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount (mount_table[k].what,
|
||||
where,
|
||||
mount_table[k].type,
|
||||
mount_table[k].flags,
|
||||
mount_table[k].options) < 0)
|
||||
{
|
||||
if (errno == ENOENT && !mount_table[k].fatal)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_rpmostree_libcontainer_prep_dev (const char *dest_devdir)
|
||||
{
|
||||
gs_fd_close int src_fd = -1;
|
||||
gs_fd_close int dest_fd = -1;
|
||||
struct stat stbuf;
|
||||
guint i;
|
||||
static const char *const devnodes[] = { "null", "zero", "full", "random", "urandom", "tty" };
|
||||
|
||||
src_fd = openat (AT_FDCWD, "/dev", O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
|
||||
if (src_fd == -1)
|
||||
return -1;
|
||||
|
||||
dest_fd = openat (AT_FDCWD, dest_devdir, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
|
||||
if (dest_fd == -1)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (devnodes); i++)
|
||||
{
|
||||
const char *nodename = devnodes[i];
|
||||
|
||||
if (fstatat (src_fd, nodename, &stbuf, 0) == -1)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
continue;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mknodat (dest_fd, nodename, stbuf.st_mode, stbuf.st_rdev) != 0)
|
||||
return -1;
|
||||
if (fchmodat (dest_fd, nodename, stbuf.st_mode, 0) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid_t
|
||||
_rpmostree_libcontainer_run_in_root (const char *dest,
|
||||
const char *binary,
|
||||
char **argv)
|
||||
{
|
||||
const int cloneflags =
|
||||
SIGCHLD | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET | CLONE_SYSVSEM | CLONE_NEWUTS;
|
||||
pid_t child;
|
||||
|
||||
if (container_available)
|
||||
{
|
||||
if ((child = syscall (__NR_clone, cloneflags, NULL)) < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((child = fork ()) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (child != 0)
|
||||
return child;
|
||||
|
||||
if (container_available)
|
||||
{
|
||||
if (mount (NULL, "/", "none", MS_PRIVATE | MS_REC, NULL) != 0)
|
||||
_rpmostree_perror_fatal ("mount: ");
|
||||
|
||||
if (mount (NULL, "/", "none", MS_PRIVATE | MS_REMOUNT | MS_NOSUID, NULL) != 0)
|
||||
_rpmostree_perror_fatal ("mount (MS_NOSUID): ");
|
||||
}
|
||||
|
||||
if (chdir (dest) != 0)
|
||||
_rpmostree_perror_fatal ("chdir: ");
|
||||
|
||||
if (container_available)
|
||||
{
|
||||
if (_rpmostree_libcontainer_make_api_mounts (dest) != 0)
|
||||
_rpmostree_perror_fatal ("preparing api mounts: ");
|
||||
|
||||
if (_rpmostree_libcontainer_prep_dev ("dev") != 0)
|
||||
_rpmostree_perror_fatal ("preparing /dev: ");
|
||||
|
||||
if (mount (".", ".", NULL, MS_BIND | MS_PRIVATE, NULL) != 0)
|
||||
_rpmostree_perror_fatal ("mount (MS_BIND)");
|
||||
|
||||
if (mount (dest, "/", NULL, MS_MOVE, NULL) != 0)
|
||||
_rpmostree_perror_fatal ("mount (MS_MOVE)");
|
||||
}
|
||||
|
||||
if (chroot (".") != 0)
|
||||
_rpmostree_perror_fatal ("chroot: ");
|
||||
|
||||
if (chdir ("/") != 0)
|
||||
_rpmostree_perror_fatal ("chdir: ");
|
||||
|
||||
if (execv (binary, argv) != 0)
|
||||
_rpmostree_perror_fatal ("execl: ");
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2014 Colin Walters <walters@verbum.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <sched.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/fsuid.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/capability.h>
|
||||
#include <sched.h>
|
||||
|
||||
void _rpmostree_libcontainer_set_not_available (void);
|
||||
gboolean _rpmostree_libcontainer_get_available (void);
|
||||
|
||||
gboolean _rpmostree_libcontainer_bind_mount_readonly (const char *path, GError **error);
|
||||
|
||||
int _rpmostree_libcontainer_make_api_mounts (const char *dest);
|
||||
int _rpmostree_libcontainer_prep_dev (const char *dest);
|
||||
|
||||
pid_t _rpmostree_libcontainer_run_in_root (const char *dest,
|
||||
const char *binary,
|
||||
char **argv);
|
@ -31,11 +31,11 @@
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <unistd.h>
|
||||
#include <libglnx.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rpmostree-postprocess.h"
|
||||
#include "rpmostree-passwd-util.h"
|
||||
#include "rpmostree-libcontainer.h"
|
||||
#include "rpmostree-cleanup.h"
|
||||
#include "rpmostree-json-parsing.h"
|
||||
#include "rpmostree-util.h"
|
||||
@ -67,7 +67,7 @@ run_sync_in_root (GFile *yumroot,
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
const char *yumroot_path = gs_file_get_path_cached (yumroot);
|
||||
pid_t child = _rpmostree_libcontainer_run_in_root (yumroot_path, binpath, child_argv);
|
||||
pid_t child = glnx_libcontainer_run_in_root (yumroot_path, binpath, child_argv);
|
||||
|
||||
if (child == -1)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user