initial commit
This commit is contained in:
commit
420789dbbb
20 changed files with 1789 additions and 0 deletions
47
CMakeLists.txt
Normal file
47
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# pflask CMakeLists.txt
|
||||
# Copyright (C) 2013 Alessandro Ghedini <alessandro@ghedini.me>
|
||||
# This file is released under the 2 clause BSD license, see COPYING
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(pflask C)
|
||||
|
||||
SET(VERSION_MAJOR 0)
|
||||
SET(VERSION_MINOR 1)
|
||||
|
||||
SET(PFLASK_VERSION ${VERSION_MAJOR}.${VERSION_MINOR})
|
||||
|
||||
SET(INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
INCLUDE(FindPkgConfig)
|
||||
|
||||
PKG_CHECK_MODULES(NL libnl-3.0 REQUIRED)
|
||||
PKG_CHECK_MODULES(NL_ROUTE libnl-route-3.0 REQUIRED)
|
||||
|
||||
FILE(GLOB SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "src/*.c")
|
||||
|
||||
ADD_EXECUTABLE(pflask ${SOURCES})
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.h)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${NL_INCLUDE_DIRS}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(pflask
|
||||
${NL_LIBRARIES}
|
||||
${NL_ROUTE_LIBRARIES}
|
||||
)
|
||||
|
||||
SET_TARGET_PROPERTIES(pflask PROPERTIES
|
||||
COMPILE_FLAGS "-Wall -pedantic -g -std=gnu99 -D_GNU_SOURCE"
|
||||
)
|
||||
|
||||
INSTALL(TARGETS pflask DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
INSTALL(FILES
|
||||
${PROJECT_SOURCE_DIR}/docs/pflask.1
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1
|
||||
)
|
||||
23
COPYING
Normal file
23
COPYING
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Copyright (c) 2013, Alessandro Ghedini <alessandro@ghedini.me>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
87
README.md
Normal file
87
README.md
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
pflask
|
||||
======
|
||||
|
||||

|
||||
|
||||
**pflask** is a simple tool for creating Linux namespace containers. It can be
|
||||
used for running a command or even booting an OS inside an isolated container,
|
||||
created with the help of Linux namespaces. It is similar in functionality to
|
||||
`chroot(8)`, altough pflask provides better isolation thanks to the use of
|
||||
namespaces.
|
||||
|
||||
Compared to [LXC] [LXC], pflask is easier to use since it doesn't require any
|
||||
pre-configuration (all the options can be passed via the command-line), but LXC
|
||||
is better suited for production, or generally security-sensitive environments.
|
||||
|
||||
Compared to [systemd-nspawn] [systemd], pflask doesn't require the use of
|
||||
systemd on the host system and provides additional features such as a more
|
||||
comprehensive handling of mounts and network interfaces inside the container.
|
||||
|
||||
[LXC]: http://linuxcontainers.org
|
||||
[systemd]: http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html
|
||||
|
||||
## FEATURES
|
||||
|
||||
### User namespace
|
||||
|
||||
When the host system allows it, pflask creates a new user namespace inside the
|
||||
container, and automatically maps the user running pflask to the root user
|
||||
inside the container. This means that a user could create and have full root
|
||||
privileges inside a container, while having none on the host system.
|
||||
|
||||
Note that this has been the cause of security vulnerabilities in the past, so
|
||||
that most OS vendors (reasonably) decided to either disable user namespace
|
||||
support altogether, or restrict the functionality to root.
|
||||
|
||||
pflask can disable the relevant functionality when it detects that support for
|
||||
user namespaces is not available.
|
||||
|
||||
### Mount namespace
|
||||
|
||||
By default, pflask creates a new mount namespace inside the container, so that
|
||||
filesystems mounted inside it won't affect the host system. pflask can also be
|
||||
told to create new mount points before the execution of the supplied command,
|
||||
by using the `--mount` option. Supported mount point types are:
|
||||
|
||||
* `bind` -- bind mount a directory/file to another directory/file
|
||||
* `aufs` -- stack a directory on top of another directory using AuFS
|
||||
* `loop` -- mount a loop device (TODO)
|
||||
* `tmp` -- mount a tmpfs on a directory
|
||||
|
||||
### Network namespace
|
||||
|
||||
When supplied the `--netif` option, pflask will create a new network namespace
|
||||
and move/rename the supplied network interface inside the container.
|
||||
|
||||
### PID, IPC and UTS namespaces
|
||||
|
||||
By default, pflask creates new PID, IPC and UTS namespaces inside the container,
|
||||
in order to isolate processes, IPC resources and the node/domain name of the
|
||||
container from the host system.
|
||||
|
||||
## GETTING STARTED
|
||||
|
||||
See the [man page](http://ghedo.github.io/pflask/) for more information.
|
||||
|
||||
## DEPENDENCIES
|
||||
|
||||
* `linux`
|
||||
* `libnl`
|
||||
* `libnl-route`
|
||||
|
||||
## BUILDING
|
||||
|
||||
pflask is distributed as source code. Install with:
|
||||
|
||||
```bash
|
||||
$ mkdir build && cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ [sudo] make install
|
||||
```
|
||||
|
||||
## COPYRIGHT
|
||||
|
||||
Copyright (C) 2013 Alessandro Ghedini <alessandro@ghedini.me>
|
||||
|
||||
See COPYING for the license.
|
||||
66
src/dev.c
Normal file
66
src/dev.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "printf.h"
|
||||
#include "util.h"
|
||||
|
||||
void make_ptmx(char *dest) {
|
||||
int rc;
|
||||
|
||||
_free_ char *ptmx_dst = NULL;
|
||||
|
||||
rc = asprintf(&ptmx_dst, "%s/dev/ptmx", dest);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
rc = symlink("/dev/pts/ptmx", ptmx_dst);
|
||||
if (rc < 0) sysf_printf("symlink()");
|
||||
}
|
||||
|
||||
void make_console(char *dest, char *console) {
|
||||
int rc;
|
||||
struct stat sb;
|
||||
_free_ char *target = NULL;
|
||||
|
||||
rc = stat(console, &sb);
|
||||
if (rc < 0) sysf_printf("stat()");
|
||||
|
||||
rc = asprintf(&target, "%s/dev/console", dest);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
rc = mknod(target, (sb.st_mode & ~07777) | 0600, sb.st_rdev);
|
||||
if (rc < 0) sysf_printf("mknod()");
|
||||
|
||||
rc = mount(console, target, NULL, MS_BIND, NULL);
|
||||
if (rc < 0) sysf_printf("mount()");
|
||||
}
|
||||
|
||||
void copy_nodes(char *dest) {
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
const char *nodes[] = {
|
||||
"/dev/tty",
|
||||
"/dev/null",
|
||||
"/dev/zero",
|
||||
"/dev/random",
|
||||
"/dev/urandom"
|
||||
};
|
||||
|
||||
for (i = 0; i < sizeof(nodes) / sizeof(*nodes); i++) {
|
||||
struct stat sb;
|
||||
_free_ char *target = NULL;
|
||||
|
||||
rc = asprintf(&target, "%s%s", dest, nodes[i]);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
rc = stat(nodes[i], &sb);
|
||||
if (rc < 0) sysf_printf("stat()");
|
||||
|
||||
rc = mknod(target, sb.st_mode, sb.st_rdev);
|
||||
if (rc < 0) sysf_printf("mknod()");
|
||||
}
|
||||
}
|
||||
3
src/dev.h
Normal file
3
src/dev.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
extern void make_ptmx(char *dest);
|
||||
extern void make_console(char *dest, char *console);
|
||||
extern void copy_nodes(char *dest);
|
||||
198
src/mount.c
Normal file
198
src/mount.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "printf.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef struct MOUNT_LIST {
|
||||
char *src;
|
||||
char *dst;
|
||||
char *type;
|
||||
unsigned long flags;
|
||||
void *data;
|
||||
|
||||
struct MOUNT_LIST *next;
|
||||
} mount_list;
|
||||
|
||||
static mount_list *mounts = NULL;
|
||||
|
||||
void add_mount(char *src, char *dst, char *type, unsigned long f, void *d) {
|
||||
mount_list *mnt = malloc(sizeof(mount_list));
|
||||
if (mnt == NULL) fail_printf("OOM");
|
||||
|
||||
mnt -> src = src ? strdup(src) : NULL;
|
||||
mnt -> dst = dst ? strdup(dst) : NULL;
|
||||
mnt -> type = type ? strdup(type) : NULL;
|
||||
mnt -> flags = f;
|
||||
mnt -> data = d ? strdup(d) : NULL;
|
||||
|
||||
mnt -> next = NULL;
|
||||
|
||||
if (mounts)
|
||||
mnt -> next = mounts;
|
||||
|
||||
mounts = mnt;
|
||||
}
|
||||
|
||||
void add_mount_inside(char *base, char *src, char *dst, char *type,
|
||||
unsigned long f, void *d) {
|
||||
int rc;
|
||||
|
||||
_free_ char *target = NULL;
|
||||
|
||||
rc = asprintf(&target, "%s%s", base, dst);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
add_mount(src, target, type, f, d);
|
||||
}
|
||||
|
||||
void add_mount_from_spec(char *spec) {
|
||||
int rc;
|
||||
_free_ char **opts = NULL;
|
||||
|
||||
_free_ char *tmp = strdup(spec);
|
||||
if (tmp == NULL) fail_printf("OOM");
|
||||
|
||||
size_t c = split_str(tmp, &opts, ",");
|
||||
if (c == 0) fail_printf("Invalid mount spec '%s'", spec);
|
||||
|
||||
if (strncmp(opts[0], "bind", 5) == 0) {
|
||||
char *src, *dst;
|
||||
|
||||
if (c < 3) fail_printf("Invalid mount spec '%s'", spec);
|
||||
|
||||
src = realpath(opts[1], NULL);
|
||||
if (src == NULL) sysf_printf("realpath()");
|
||||
|
||||
dst = realpath(opts[2], NULL);
|
||||
if (dst == NULL) sysf_printf("realpath()");
|
||||
|
||||
add_mount(src, dst, NULL, MS_BIND, NULL);
|
||||
} else if (strncmp(opts[0], "aufs", 4) == 0) {
|
||||
char *dst, *overlay;
|
||||
_free_ char *aufs_opts = NULL;
|
||||
|
||||
if (c < 3) fail_printf("Invalid mount spec '%s'", spec);
|
||||
|
||||
overlay = realpath(opts[1], NULL);
|
||||
if (overlay == NULL) sysf_printf("realpath()");
|
||||
|
||||
dst = realpath(opts[2], NULL);
|
||||
if (dst == NULL) sysf_printf("realpath()");
|
||||
|
||||
rc = asprintf(&aufs_opts, "br:%s=rw:%s=ro", overlay, dst);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
add_mount(NULL, dst, "aufs", 0, aufs_opts);
|
||||
} else if (strncmp(opts[0], "loop", 5) == 0) {
|
||||
/* TODO: loop device support */
|
||||
} else if (strncmp(opts[0], "tmp", 4) == 0) {
|
||||
char *dst;
|
||||
|
||||
if (c < 2) fail_printf("Invalid mount spec '%s'", spec);
|
||||
|
||||
dst = realpath(opts[1], NULL);
|
||||
if (dst == NULL) sysf_printf("realpath()");
|
||||
|
||||
add_mount("tmpfs", dst, "tmpfs", 0, NULL);
|
||||
} else {
|
||||
fail_printf("Invalid mount type '%s'", opts[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void do_mount(char *dest) {
|
||||
int rc;
|
||||
|
||||
mount_list *i = NULL;
|
||||
|
||||
rc = mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL);
|
||||
if (rc < 0) sysf_printf("mount(MS_SLAVE)");
|
||||
|
||||
if (dest != NULL) {
|
||||
add_mount(dest, dest, NULL, MS_BIND, NULL);
|
||||
|
||||
add_mount_inside(dest, "proc", "/proc", "proc",
|
||||
MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL);
|
||||
|
||||
add_mount_inside(dest, "/proc/sys", "/proc/sys", NULL,
|
||||
MS_BIND, NULL);
|
||||
|
||||
add_mount_inside(dest, NULL, "/proc/sys", NULL,
|
||||
MS_BIND | MS_RDONLY | MS_REMOUNT, NULL);
|
||||
|
||||
add_mount_inside(dest, "sysfs", "/sys", "sysfs",
|
||||
MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_RDONLY, NULL);
|
||||
|
||||
add_mount_inside(dest, "tmpfs", "/dev", "tmpfs",
|
||||
MS_NOSUID | MS_STRICTATIME, "mode=755");
|
||||
|
||||
add_mount_inside(dest, "devpts", "/dev/pts", "devpts",
|
||||
MS_NOSUID | MS_NOEXEC,
|
||||
"newinstance,ptmxmode=000,mode=620,gid=5");
|
||||
|
||||
add_mount_inside(dest, "tmpfs", "/dev/shm", "tmpfs",
|
||||
MS_NOSUID | MS_STRICTATIME | MS_NODEV, "mode=1777");
|
||||
|
||||
add_mount_inside(dest, "tmpfs", "/run", "tmpfs",
|
||||
MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755");
|
||||
|
||||
/* add_mount(dest, "/", NULL, MS_MOVE, NULL); */
|
||||
}
|
||||
|
||||
while (mounts) {
|
||||
mount_list *next = mounts -> next;
|
||||
mounts -> next = i;
|
||||
i = mounts;
|
||||
mounts = next;
|
||||
}
|
||||
|
||||
while (i != NULL) {
|
||||
struct stat sb;
|
||||
|
||||
if (stat(i -> dst, &sb) < 0) {
|
||||
rc = mkdir(i -> dst, 0755);
|
||||
if (rc < 0) sysf_printf("mkdir(%s)", i -> dst);
|
||||
}
|
||||
|
||||
rc = mount(i->src, i -> dst, i -> type, i -> flags, i -> data);
|
||||
if (rc < 0) sysf_printf("mount(%s)", i -> type);
|
||||
|
||||
i = i -> next;
|
||||
}
|
||||
}
|
||||
37
src/mount.h
Normal file
37
src/mount.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
extern void add_mount(char *src, char *dst, char *type,
|
||||
unsigned long f, void *d);
|
||||
extern void add_mount_inside(char *base, char *src, char *dst, char *type,
|
||||
unsigned long f, void *d);
|
||||
extern void add_mount_from_spec(char *spec);
|
||||
|
||||
extern void do_mount(char *dest);
|
||||
136
src/netif.c
Normal file
136
src/netif.c
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <netlink/msg.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/errno.h>
|
||||
#include <netlink/socket.h>
|
||||
#include <netlink/route/link.h>
|
||||
|
||||
#include "netif.h"
|
||||
#include "printf.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef struct NETIF_LIST {
|
||||
char *dev;
|
||||
char *name;
|
||||
|
||||
struct NETIF_LIST *next;
|
||||
} netif_list;
|
||||
|
||||
static netif_list *netifs = NULL;
|
||||
|
||||
void add_netif(char *dev, char *name) {
|
||||
netif_list *nif = malloc(sizeof(netif_list));
|
||||
if (nif == NULL) fail_printf("OOM");
|
||||
|
||||
nif -> dev = strdup(dev);
|
||||
nif -> name = strdup(name);
|
||||
|
||||
nif -> next = NULL;
|
||||
|
||||
if (netifs)
|
||||
nif -> next = netifs;
|
||||
|
||||
netifs = nif;
|
||||
}
|
||||
|
||||
void add_netif_from_spec(char *spec) {
|
||||
_free_ char **opts = NULL;
|
||||
|
||||
_free_ char *tmp = strdup(spec);
|
||||
if (tmp == NULL) fail_printf("OOM");
|
||||
|
||||
size_t c = split_str(tmp, &opts, ",");
|
||||
if (c == 0) fail_printf("Invalid netif spec '%s'", spec);
|
||||
|
||||
if (c < 2) fail_printf("Invalid netif spec '%s'", spec);
|
||||
|
||||
add_netif(opts[0], opts[1]);
|
||||
}
|
||||
|
||||
void do_netif(pid_t pid) {
|
||||
int rc;
|
||||
netif_list *i = NULL;
|
||||
|
||||
struct nl_sock *sock;
|
||||
struct nl_cache *cache;
|
||||
|
||||
sock = nl_socket_alloc();
|
||||
if (sock == NULL) fail_printf("OOM");
|
||||
|
||||
rc = nl_connect(sock, NETLINK_ROUTE);
|
||||
if (rc < 0) fail_printf("Error creating netlink connection: %s",
|
||||
nl_geterror(rc));
|
||||
|
||||
rc = rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache);
|
||||
if (rc < 0) fail_printf("Error creating netlink cache: %s",
|
||||
nl_geterror(rc));
|
||||
|
||||
while (netifs) {
|
||||
netif_list *next = netifs -> next;
|
||||
netifs -> next = i;
|
||||
i = netifs;
|
||||
netifs = next;
|
||||
}
|
||||
|
||||
while (i != NULL) {
|
||||
struct nl_msg *msg;
|
||||
struct rtnl_link *new_link;
|
||||
|
||||
struct rtnl_link *link = rtnl_link_get_by_name(cache, i->dev);
|
||||
if (link == NULL) fail_printf("Invalid netif '%s'", i -> dev);
|
||||
|
||||
new_link = rtnl_link_alloc();
|
||||
if (new_link == NULL) fail_printf("OOM");
|
||||
|
||||
rtnl_link_set_name(new_link, i -> name);
|
||||
|
||||
rc = rtnl_link_build_change_request(link, new_link, 0, &msg);
|
||||
if (rc < 0) fail_printf("Error creating netlink request: '%s'",
|
||||
nl_geterror(rc));
|
||||
|
||||
nla_put_u32(msg, IFLA_NET_NS_PID, pid);
|
||||
|
||||
rc = nl_send_auto(sock, msg);
|
||||
if (rc < 0) fail_printf("Error sending netlink request: %s",
|
||||
nl_geterror(rc));
|
||||
|
||||
i = i -> next;
|
||||
|
||||
rtnl_link_put(new_link);
|
||||
rtnl_link_put(link);
|
||||
}
|
||||
|
||||
nl_cache_put(cache);
|
||||
|
||||
nl_close(sock);
|
||||
nl_socket_free(sock);
|
||||
}
|
||||
34
src/netif.h
Normal file
34
src/netif.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
extern void add_netif(char *dev, char *name);
|
||||
extern void add_netif_from_spec(char *spec);
|
||||
|
||||
extern void do_netif(pid_t pid);
|
||||
296
src/pflask.c
Normal file
296
src/pflask.c
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <sched.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "dev.h"
|
||||
#include "pty.h"
|
||||
#include "user.h"
|
||||
#include "mount.h"
|
||||
#include "netif.h"
|
||||
#include "printf.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
|
||||
static int clone_flags = SIGCHLD |
|
||||
CLONE_NEWNS |
|
||||
CLONE_NEWIPC |
|
||||
CLONE_NEWPID |
|
||||
/* CLONE_NEWUSER| */
|
||||
CLONE_NEWUTS;
|
||||
|
||||
static inline void help(void);
|
||||
static inline void version(void);
|
||||
|
||||
void do_chroot(char *dest) {
|
||||
int rc;
|
||||
|
||||
rc = chdir(dest);
|
||||
if (rc < 0) sysf_printf("chdir()");
|
||||
|
||||
rc = chroot(".");
|
||||
if (rc < 0) sysf_printf("chroot()");
|
||||
|
||||
rc = chdir("/");
|
||||
if (rc < 0) sysf_printf("chdir(/)");
|
||||
}
|
||||
|
||||
pid_t do_clone(void) {
|
||||
pid_t pid;
|
||||
|
||||
pid = syscall(__NR_clone, clone_flags, NULL);
|
||||
if (pid < 0) {
|
||||
if (errno == EINVAL) {
|
||||
clone_flags &= ~(CLONE_NEWUSER);
|
||||
pid = syscall(__NR_clone, clone_flags, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (pid < 0) sysf_printf("clone()");
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
static struct option long_opts[] = {
|
||||
{ "mount", required_argument, NULL, 'm' },
|
||||
{ "netif", required_argument, NULL, 'n' },
|
||||
{ "user", required_argument, NULL, 'u' },
|
||||
{ "root", required_argument, NULL, 'r' },
|
||||
{ "chdir", required_argument, NULL, 'c' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int rc, i;
|
||||
|
||||
pid_t pid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
_free_ char *user = NULL;
|
||||
_free_ char *dest = NULL;
|
||||
_free_ char *change = NULL;
|
||||
|
||||
int master_fd;
|
||||
char *master_name;
|
||||
|
||||
siginfo_t status;
|
||||
|
||||
const char *short_opts = "+m:n:u:r:h";
|
||||
|
||||
if (argc < 2) {
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((rc = getopt_long(argc, argv, short_opts, long_opts, &i)) !=-1) {
|
||||
switch (rc) {
|
||||
case 'm':
|
||||
add_mount_from_spec(optarg);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
clone_flags |= CLONE_NEWNET;
|
||||
add_netif_from_spec(optarg);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
user = strdup(optarg);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
dest = realpath(optarg, NULL);
|
||||
if (dest == NULL) sysf_printf("realpath()");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
change = strdup(optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case 'h':
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (user == NULL) {
|
||||
user = strdup("root");
|
||||
if (user == NULL) fail_printf("OOM");
|
||||
}
|
||||
|
||||
open_master_pty(&master_fd, &master_name);
|
||||
|
||||
uid = getuid();
|
||||
gid = getgid();
|
||||
|
||||
pid = do_clone();
|
||||
|
||||
if (pid == 0) {
|
||||
_free_ char *env_term = NULL;
|
||||
_free_ char *env_user = NULL;
|
||||
_free_ char *env_name = NULL;
|
||||
|
||||
char **env = NULL;
|
||||
|
||||
rc = asprintf(&env_user, "USER=%s", user);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
rc = asprintf(&env_name, "LOGNAME=%s", user);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
if (getenv("TERM")) {
|
||||
rc = asprintf(&env_term, "TERM=%s", getenv("TERM"));
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
}
|
||||
|
||||
const char *envp[] = {
|
||||
"container=pflask",
|
||||
"PATH=/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
env_user,
|
||||
env_name,
|
||||
env_term,
|
||||
NULL
|
||||
};
|
||||
|
||||
rc = setsid();
|
||||
if (rc < 0) sysf_printf("setsid()");
|
||||
|
||||
open_slave_pty(master_name);
|
||||
|
||||
rc = close(master_fd);
|
||||
if (rc < 0) sysf_printf("close()");
|
||||
|
||||
if (clone_flags & CLONE_NEWUSER)
|
||||
map_user_to_root(uid, gid);
|
||||
|
||||
do_mount(dest);
|
||||
|
||||
if (dest != NULL) {
|
||||
make_ptmx(dest);
|
||||
make_console(dest, master_name);
|
||||
|
||||
copy_nodes(dest);
|
||||
|
||||
do_chroot(dest);
|
||||
}
|
||||
|
||||
umask(0022);
|
||||
|
||||
/* TODO: drop capabilities */
|
||||
|
||||
do_user(user);
|
||||
|
||||
if (change) {
|
||||
rc = chdir(change);
|
||||
if (rc < 0) sysf_printf("chdir()");
|
||||
}
|
||||
|
||||
env = dest == NULL ? environ : envp;
|
||||
|
||||
if (argc > optind)
|
||||
rc = execvpe(argv[optind], argv + optind, env);
|
||||
else
|
||||
rc = execle("/bin/bash", "-bash", NULL, env);
|
||||
|
||||
if (rc < 0) sysf_printf("exec()");
|
||||
}
|
||||
|
||||
do_netif(pid);
|
||||
|
||||
/* TODO: attach/detach */
|
||||
process_pty(master_fd);
|
||||
|
||||
rc = waitid(P_PID, pid, &status, WEXITED);
|
||||
if (rc < 0) sysf_printf("waitid()");
|
||||
|
||||
switch (status.si_code) {
|
||||
case CLD_EXITED:
|
||||
if (status.si_status != 0)
|
||||
err_printf("Child failed with code '%d'",
|
||||
status.si_status);
|
||||
else
|
||||
ok_printf("Child exited");
|
||||
break;
|
||||
|
||||
case CLD_KILLED:
|
||||
err_printf("Child was terminated");
|
||||
break;
|
||||
|
||||
default:
|
||||
err_printf("Child failed");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void version(void) {
|
||||
printf("pflask v%s\n", PFLASK_VERSION);
|
||||
}
|
||||
|
||||
static inline void help(void) {
|
||||
#define CMD_HELP(CMDL, CMDS, MSG) printf(" %s, %s \t%s.\n", COLOR_YELLOW CMDS, CMDL COLOR_OFF, MSG);
|
||||
|
||||
printf(COLOR_RED "Usage: " COLOR_OFF);
|
||||
printf(COLOR_GREEN "pflask " COLOR_OFF);
|
||||
puts("[OPTIONS] [COMMAND [ARGS...]]\n");
|
||||
|
||||
puts(COLOR_RED " Options:" COLOR_OFF);
|
||||
|
||||
CMD_HELP("--mount", "-m",
|
||||
"Create a new mount point inside the container");
|
||||
CMD_HELP("--netif", "-n",
|
||||
"Move a network interface inside the container");
|
||||
CMD_HELP("--user", "-u",
|
||||
"Run the command as the specified user");
|
||||
CMD_HELP("--root", "-r",
|
||||
"Use the specified directory as root inside the container");
|
||||
CMD_HELP("--chdir", "-c",
|
||||
"Change to the specified directory inside the namespace");
|
||||
|
||||
puts("");
|
||||
}
|
||||
101
src/printf.c
Normal file
101
src/printf.c
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "printf.h"
|
||||
|
||||
void ok_printf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
/* if (cfg.silent || cfg.quiet) */
|
||||
/* return; */
|
||||
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, "[" COLOR_GREEN "✔" COLOR_OFF "] ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void debug_printf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
/* if (!cfg.verbose || cfg.silent || cfg.quiet) */
|
||||
/* return; */
|
||||
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, "[" COLOR_YELLOW "¡" COLOR_OFF "] ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void err_printf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
/* if (cfg.silent) */
|
||||
/* return; */
|
||||
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, "[" COLOR_RED "✘" COLOR_OFF "] ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void fail_printf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, "[" COLOR_RED "✘" COLOR_OFF "] ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
_exit(-1);
|
||||
}
|
||||
|
||||
void sysf_printf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, "[" COLOR_RED "✘" COLOR_OFF "] ");
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, ": %s\n", strerror(errno));
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
41
src/printf.h
Normal file
41
src/printf.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define COLOR_GREEN "[1;32m"
|
||||
#define COLOR_YELLOW "[1;33m"
|
||||
#define COLOR_RED "[1;31m"
|
||||
#define COLOR_BGRED "[1;41m"
|
||||
#define COLOR_OFF "[0m"
|
||||
|
||||
extern void ok_printf(const char *fmt, ...);
|
||||
extern void debug_printf(const char *fmt, ...);
|
||||
extern void err_printf(const char *fmt, ...);
|
||||
extern void fail_printf(const char *fmt, ...);
|
||||
extern void sysf_printf(const char *fmt, ...);
|
||||
343
src/pty.c
Normal file
343
src/pty.c
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signalfd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "printf.h"
|
||||
|
||||
#define SOCKET_PATH "/tmp/fuck-security"
|
||||
|
||||
static struct termios stdin_attr;
|
||||
static struct winsize stdin_ws;
|
||||
|
||||
static void recv_fd(int sock);
|
||||
static void send_fd(int sock, int fd);
|
||||
|
||||
void open_master_pty(int *master_fd, char **master_name) {
|
||||
int rc;
|
||||
|
||||
rc = tcgetattr(STDIN_FILENO, &stdin_attr);
|
||||
if (rc < 0) sysf_printf("tcgetattr()");
|
||||
|
||||
rc = ioctl(STDIN_FILENO, TIOCGWINSZ, &stdin_ws);
|
||||
if (rc < 0) sysf_printf("ioctl(TIOCGWINSZ)");
|
||||
|
||||
*master_fd = posix_openpt(O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (*master_fd < 0) sysf_printf("posix_openpt()");
|
||||
|
||||
*master_name = ptsname(*master_fd);
|
||||
if (*master_name == NULL) sysf_printf("ptsname()");
|
||||
|
||||
rc = unlockpt(*master_fd);
|
||||
if (rc < 0) sysf_printf("unlckpt()");
|
||||
}
|
||||
|
||||
void open_slave_pty(char *master_name) {
|
||||
int rc, slave_fd;
|
||||
|
||||
slave_fd = open(master_name, O_RDWR, 0);
|
||||
if (slave_fd < 0) sysf_printf("open()");
|
||||
|
||||
if (!isatty(slave_fd)) fail_printf("Not a TTY");
|
||||
|
||||
rc = dup2(slave_fd, STDIN_FILENO);
|
||||
if (rc < 0) sysf_printf("dup2(STDIN)");
|
||||
|
||||
rc = dup2(slave_fd, STDOUT_FILENO);
|
||||
if (rc < 0) sysf_printf("dup2(STDOUT)");
|
||||
|
||||
rc = dup2(slave_fd, STDERR_FILENO);
|
||||
if (rc < 0) sysf_printf("dup2(STDERR)");
|
||||
|
||||
rc = tcsetattr(slave_fd, TCSANOW, &stdin_attr);
|
||||
if (rc < 0) sysf_printf("tcsetattr()");
|
||||
|
||||
rc = ioctl(slave_fd, TIOCSWINSZ, &stdin_ws);
|
||||
if (rc < 0) sysf_printf("ioctl(TIOCWINSZ)");
|
||||
|
||||
rc = close(slave_fd);
|
||||
if (rc < 0) sysf_printf("close()");
|
||||
}
|
||||
|
||||
void process_pty(int master_fd) {
|
||||
int rc;
|
||||
|
||||
fd_set rfds;
|
||||
|
||||
sigset_t mask;
|
||||
int signal_fd;
|
||||
|
||||
struct termios raw_attr;
|
||||
|
||||
int line_max = sysconf(_SC_LINE_MAX);
|
||||
if (line_max < 0) sysf_printf("sysconf()");
|
||||
|
||||
memcpy(&raw_attr, &stdin_attr, sizeof(stdin_attr));
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigaddset(&mask, SIGWINCH);
|
||||
|
||||
rc = sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
if (rc < 0) sysf_printf("sigprocmask()");
|
||||
|
||||
signal_fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
|
||||
if (signal_fd < 0) sysf_printf("signalfd()");
|
||||
|
||||
cfmakeraw(&raw_attr);
|
||||
raw_attr.c_lflag &= ~ECHO;
|
||||
|
||||
rc = tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr);
|
||||
if (rc < 0) sysf_printf("tcsetattr()");
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
|
||||
FD_SET(STDIN_FILENO, &rfds);
|
||||
FD_SET(master_fd, &rfds);
|
||||
FD_SET(signal_fd, &rfds);
|
||||
|
||||
while ((rc = select(master_fd + 1, &rfds, NULL, NULL, NULL)) > 0) {
|
||||
char buf[line_max];
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &rfds)) {
|
||||
int rc = read(STDIN_FILENO, buf, line_max);
|
||||
|
||||
if (rc == 0)
|
||||
goto finish;
|
||||
else if (rc < 0)
|
||||
goto finish;
|
||||
|
||||
rc = write(master_fd, buf, rc);
|
||||
if (rc < 0) sysf_printf("write()");
|
||||
}
|
||||
|
||||
if (FD_ISSET(master_fd, &rfds)) {
|
||||
rc = read(master_fd, buf, line_max);
|
||||
|
||||
if (rc == 0)
|
||||
goto finish;
|
||||
else if (rc < 0)
|
||||
goto finish;
|
||||
|
||||
rc = write(STDOUT_FILENO, buf, rc);
|
||||
if (rc < 0) sysf_printf("write()");
|
||||
}
|
||||
|
||||
if (FD_ISSET(signal_fd, &rfds)) {
|
||||
struct signalfd_siginfo fdsi;
|
||||
|
||||
rc = read(signal_fd, &fdsi, sizeof(fdsi));
|
||||
if (rc != sizeof(fdsi)) sysf_printf("read()");
|
||||
|
||||
switch (fdsi.ssi_signo) {
|
||||
case SIGWINCH: {
|
||||
struct winsize ws;
|
||||
|
||||
rc = ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
|
||||
if (rc < 0) sysf_printf("ioctl()");
|
||||
|
||||
rc = ioctl(master_fd, TIOCSWINSZ, &ws);
|
||||
if (rc < 0) sysf_printf("ioctl()");
|
||||
}
|
||||
|
||||
case SIGCHLD:
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
FD_SET(STDIN_FILENO, &rfds);
|
||||
FD_SET(master_fd, &rfds);
|
||||
FD_SET(signal_fd, &rfds);
|
||||
}
|
||||
if (rc < 0) sysf_printf("select()");
|
||||
|
||||
finish:
|
||||
rc = tcsetattr(STDIN_FILENO, TCSANOW, &stdin_attr);
|
||||
if (rc < 0) sysf_printf("tcsetattr()");
|
||||
}
|
||||
|
||||
void serve_pty(int fd) {
|
||||
int rc;
|
||||
int sock;
|
||||
|
||||
struct sockaddr *servaddr;
|
||||
struct sockaddr_un servaddr_un;
|
||||
int servaddr_len;
|
||||
|
||||
memset(&servaddr_un, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
servaddr_un.sun_family = AF_UNIX;
|
||||
strcpy(servaddr_un.sun_path, SOCKET_PATH);
|
||||
|
||||
servaddr = (struct sockaddr *) &servaddr_un;
|
||||
servaddr_len = sizeof(struct sockaddr_un) -
|
||||
sizeof(servaddr_un.sun_path) +
|
||||
strlen(SOCKET_PATH);
|
||||
|
||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock < 0) sysf_printf("socket()");
|
||||
|
||||
rc = bind(sock, servaddr, servaddr_len);
|
||||
if (rc < 0) sysf_printf("bind()");
|
||||
|
||||
rc = listen(sock, 1);
|
||||
if (rc < 0) sysf_printf("listen()");
|
||||
|
||||
while (1) {
|
||||
int send_sock = accept(sock, (struct sockaddr *) NULL, NULL);
|
||||
if (send_sock < 0) sysf_printf("accept()");
|
||||
|
||||
send_fd(send_sock, fd);
|
||||
}
|
||||
}
|
||||
|
||||
void recv_pty(void) {
|
||||
int rc;
|
||||
int sock;
|
||||
|
||||
struct sockaddr *servaddr;
|
||||
struct sockaddr_un servaddr_un;
|
||||
int servaddr_len;
|
||||
|
||||
memset(&servaddr_un, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
servaddr_un.sun_family = AF_UNIX;
|
||||
strcpy(servaddr_un.sun_path, SOCKET_PATH);
|
||||
|
||||
servaddr = (struct sockaddr *) &servaddr_un;
|
||||
servaddr_len = sizeof(struct sockaddr_un) -
|
||||
sizeof(servaddr_un.sun_path) +
|
||||
strlen(SOCKET_PATH);
|
||||
|
||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock < 0) sysf_printf("socket()");
|
||||
|
||||
rc = connect(sock, servaddr, servaddr_len);
|
||||
if (rc < 0) sysf_printf("connect()");
|
||||
|
||||
recv_fd(sock);
|
||||
}
|
||||
|
||||
static void send_fd(int sock, int fd) {
|
||||
int rc;
|
||||
|
||||
union {
|
||||
struct cmsghdr cmsg;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} msg_control;
|
||||
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
iov [0].iov_base = "x";
|
||||
iov [0].iov_len = 1;
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_flags = 0;
|
||||
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
cmsg -> cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmsg -> cmsg_level = SOL_SOCKET;
|
||||
cmsg -> cmsg_type = SCM_RIGHTS;
|
||||
|
||||
*((int *) CMSG_DATA(cmsg)) = fd;
|
||||
|
||||
rc = sendmsg(sock, &msg, 0);
|
||||
if (rc < 0) sysf_printf("sendmsg()");
|
||||
}
|
||||
|
||||
static void recv_fd(int sock) {
|
||||
int rc;
|
||||
|
||||
union {
|
||||
struct cmsghdr cmsg;
|
||||
char control [CMSG_SPACE(sizeof(int))];
|
||||
} msg_control;
|
||||
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
struct cmsghdr *cmsg;
|
||||
char buf[192];
|
||||
|
||||
iov [0].iov_base = buf;
|
||||
iov [0].iov_len = sizeof(buf);
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
msg.msg_flags = 0;
|
||||
|
||||
rc = recvmsg(sock, &msg, 0);
|
||||
if (rc < 0) sysf_printf("recvmsg()");
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
int fd;
|
||||
|
||||
if (cmsg -> cmsg_len != CMSG_LEN(sizeof(int)) ||
|
||||
cmsg -> cmsg_level != SOL_SOCKET ||
|
||||
cmsg -> cmsg_type != SCM_RIGHTS)
|
||||
continue;
|
||||
|
||||
fd = *((int *) CMSG_DATA(cmsg));
|
||||
process_pty(fd);
|
||||
|
||||
rc = close(fd);
|
||||
if (rc < 0) sysf_printf("close()");
|
||||
}
|
||||
}
|
||||
37
src/pty.h
Normal file
37
src/pty.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
extern void open_master_pty(int *master_fd, char **master_name);
|
||||
extern void open_slave_pty(char *master_name);
|
||||
|
||||
extern void process_pty(int master_fd);
|
||||
|
||||
extern void serve_pty(int fd);
|
||||
extern void recv_pty(void);
|
||||
98
src/user.c
Normal file
98
src/user.c
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include "printf.h"
|
||||
#include "util.h"
|
||||
|
||||
void map_user_to_root(uid_t uid, gid_t gid) {
|
||||
int rc;
|
||||
int map_fd;
|
||||
|
||||
_free_ char *uid_map = NULL;
|
||||
_free_ char *gid_map = NULL;
|
||||
|
||||
rc = asprintf(&uid_map, "0 %d 1", uid);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
map_fd = open("/proc/self/uid_map", O_RDWR);
|
||||
if (map_fd < 0) sysf_printf("open(uid_map)");
|
||||
|
||||
rc = write(map_fd, uid_map, strlen(uid_map));
|
||||
if (rc < 0) sysf_printf("write(uid_map)");
|
||||
|
||||
rc = close(map_fd);
|
||||
if (rc < 0) sysf_printf("close(uid_map)");
|
||||
|
||||
rc = asprintf(&gid_map, "0 %d 1", gid);
|
||||
if (rc < 0) fail_printf("OOM");
|
||||
|
||||
map_fd = open("/proc/self/gid_map", O_RDWR);
|
||||
if (map_fd < 0) sysf_printf("open(gid_map)");
|
||||
|
||||
rc = write(map_fd, gid_map, strlen(gid_map));
|
||||
if (rc < 0) sysf_printf("write(gid_map)");
|
||||
|
||||
rc = close(map_fd);
|
||||
if (rc < 0) sysf_printf("close(gid_map)");
|
||||
}
|
||||
|
||||
void do_user(char *user) {
|
||||
int rc;
|
||||
|
||||
struct passwd *pwd;
|
||||
|
||||
errno = 0;
|
||||
pwd = getpwnam(user);
|
||||
if (pwd == NULL) {
|
||||
if (errno) sysf_printf("getpwnam()");
|
||||
else fail_printf("Invalid user '%s'", user);
|
||||
}
|
||||
|
||||
rc = initgroups(user, pwd -> pw_gid);
|
||||
if (rc < 0) sysf_printf("initgroups()");
|
||||
|
||||
rc = setresgid(pwd -> pw_gid, pwd -> pw_gid, pwd -> pw_gid);
|
||||
if (rc < 0) sysf_printf("setresgid()");
|
||||
|
||||
rc = setresuid(pwd -> pw_uid, pwd -> pw_uid, pwd -> pw_uid);
|
||||
if (rc < 0) sysf_printf("setresuid()");
|
||||
|
||||
rc = chdir(pwd -> pw_dir);
|
||||
if (rc < 0) sysf_printf("chdir(HOME)");
|
||||
}
|
||||
33
src/user.h
Normal file
33
src/user.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
extern void map_user_to_root(uid_t uid, gid_t gid);
|
||||
|
||||
extern void do_user(char *user);
|
||||
58
src/util.c
Normal file
58
src/util.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
size_t split_str(char *orig, char ***dest, char *needle) {
|
||||
size_t size = 0;
|
||||
char *token;
|
||||
|
||||
if (orig == NULL || dest == NULL)
|
||||
return 0;
|
||||
|
||||
token = strtok(orig, needle);
|
||||
|
||||
do {
|
||||
char **tmp = realloc(*dest, sizeof(char *) * (size + 1));
|
||||
|
||||
if (tmp == NULL) {
|
||||
if (*dest != NULL)
|
||||
free(*dest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
*dest = tmp;
|
||||
(*dest)[size++] = token;
|
||||
} while ((token = strtok(NULL, needle)) != NULL);
|
||||
|
||||
return size;
|
||||
}
|
||||
42
src/util.h
Normal file
42
src/util.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _free_ __attribute__((cleanup(freep)))
|
||||
|
||||
static inline void freep(void *p) {
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
free(*(void **) p);
|
||||
}
|
||||
|
||||
extern size_t split_str(char *orig, char ***dest, char *needle);
|
||||
31
src/version.h.in
Normal file
31
src/version.h.in
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* The process in the flask.
|
||||
*
|
||||
* Copyright (c) 2013, Alessandro Ghedini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#cmakedefine PFLASK_VERSION "${PFLASK_VERSION}"
|
||||
78
tools/pflask-debuild
Executable file
78
tools/pflask-debuild
Executable file
|
|
@ -0,0 +1,78 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Build Debian packages inside Linux namespaces.
|
||||
#
|
||||
# Copyright (c) 2013, Alessandro Ghedini
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -e
|
||||
|
||||
umask 022
|
||||
|
||||
DIST=unstable
|
||||
ARCH=amd64
|
||||
|
||||
PFLASK="$HOME/devel/projs/pflask/build/pflask"
|
||||
|
||||
BASE_DIR="$HOME/local/base-$DIST-$ARCH"
|
||||
|
||||
PKG_DIR=$(pwd)
|
||||
|
||||
PKG=$(basename $PKG_DIR)
|
||||
DIR=$(dirname $PKG_DIR)
|
||||
|
||||
OVERLAY="$DIR/$PKG-XXXX"
|
||||
|
||||
OVERLAY=$(mktemp -d $OVERLAY)
|
||||
|
||||
USER=$(whoami)
|
||||
|
||||
APT='apt-get --no-install-recommends -y'
|
||||
|
||||
$PFLASK --user $USER --root $BASE_DIR \
|
||||
--mount "aufs,$OVERLAY,$BASE_DIR" \
|
||||
--mount "bind,$DIR,$BASE_DIR/tmp" \
|
||||
--chdir "/tmp/$PKG" \
|
||||
-- \
|
||||
mk-build-deps -r -i debian/control -t $APT
|
||||
|
||||
$PFLASK --user $USER --root $BASE_DIR \
|
||||
--mount "aufs,$OVERLAY,$BASE_DIR" \
|
||||
--mount "bind,$DIR,$BASE_DIR/tmp" \
|
||||
--chdir "/tmp/$PKG" \
|
||||
-- \
|
||||
debuild
|
||||
|
||||
$PFLASK --user $USER --root $BASE_DIR \
|
||||
--mount "aufs,$OVERLAY,$BASE_DIR" \
|
||||
--mount "bind,$DIR,$BASE_DIR/tmp" \
|
||||
--chdir "/tmp/$PKG" \
|
||||
-- \
|
||||
debclean
|
||||
|
||||
rm -rf $OVERLAY
|
||||
|
||||
exit 0
|
||||
Loading…
Reference in a new issue