Merge branch 'master' into fix-spell

This commit is contained in:
Simon Fels 2018-06-08 17:36:27 +02:00 committed by GitHub
commit 2b5dd3ff4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 186 additions and 42 deletions

View file

@ -1,8 +1,12 @@
Make sure you are running the latest version of Anbox before reporting an issue.
1. Please check that no similar bug is already reported. Have a look on the list of open bugs at https://github.com/anbox/anbox/issues
2. Make sure you are running the latest version of Anbox before reporting an issue. Update snap to latest: `snap refresh --devmode --edge anbox`
3. Make sure you have debug logs enabled:
`sudo snap set anbox debug.enable=true`
4. Reproduce the error while debug logs enabled.
5. Run the anbox logs collection utility and attach the tar file.
`sudo /snap/bin/anbox.collect-bug-info `
Please also check that no similar bug is already reported. Have a look on the list of open bugs at https://github.com/anbox/anbox/issues
** Please paste the result of `anbox system-info` below:**
6. ** Please paste the result of `anbox system-info` below:**
```
[please paste printout of `anbox system-info` here]
```
@ -14,3 +18,4 @@ Please also check that no similar bug is already reported. Have a look on the li
**Additional info:**

1
.gitignore vendored
View file

@ -2,7 +2,6 @@ build*/
parts/
stage/
prime/
snap/
android-images/
*.snap
CMakeLists.txt.user

View file

@ -104,3 +104,23 @@ a more stable and bug free experience.
Once proper confinement for the Anbox snap exists we will also start using the
candidate and stable channels.
# Uninstall Anbox
If you want to remove Anbox from your system you first have to remove the snap:
**NOTE:** By removing the snap you remove all data you stored within the snap
from your system. There is no way to bring it back.
```
$ snap remove anbox
```
Once the snap is removed you have to remove the installed kernel modules as well:
```
$ sudo apt install ppa-purge
$ sudo ppa-purge ppa:morphis/anbox-support
```
Once done Anbox is removed from your system.

View file

@ -38,7 +38,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCXX)
endif()
# ANBOX: allow old-style casts
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=old-style-cast")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=old-style-cast -Wno-error=switch-default")
###############################################################################
# BACKWARD OBJECT

View file

@ -24,8 +24,8 @@ echo "Collecting anbox log files ... "
set -x
# Collect several things which are of interest for bug reports
cp /var/snap/anbox/common/data/system.log $TMPDIR || true
cp /var/snap/anbox/containers/lxc-monitord.log $TMPDIR || true
cp /var/snap/anbox/logs/container.log $TMPDIR || true
cp /var/snap/anbox/common/containers/lxc-monitord.log $TMPDIR || true
cp /var/snap/anbox/common/logs/container.log $TMPDIR || true
$SNAP/command-anbox.wrapper system-info > $TMPDIR/system-info.log 2>&1 || true
if [ -e /etc/systemd/system/snap.anbox.container-manager.service ]; then

View file

@ -43,6 +43,10 @@ start() {
$SNAP/sbin/apparmor_parser -r $SNAP/apparmor/anbox-container.aa
fi
if [ -e "$SNAP_COMMON"/.enable_debug ]; then
export ANBOX_LOG_LEVEL=debug
fi
exec $AA_EXEC $SNAP/bin/anbox-wrapper.sh container-manager \
--data-path=$DATA_PATH \
--android-image=$ANDROID_IMG \

View file

@ -29,4 +29,8 @@ export XDG_DATA_HOME="$SNAP_USER_COMMON/app-data"
# configured but the actual EGL implementation is missing.
export __EGL_VENDOR_LIBRARY_DIRS="$SNAP/glvnd"
if [ -e "$SNAP_COMMON"/.enable_debug ]; then
export ANBOX_LOG_LEVEL=debug
fi
exec $SNAP/usr/bin/anbox $@

9
snap/hooks/configure vendored Executable file
View file

@ -0,0 +1,9 @@
#!/bin/sh
if [ "$(snapctl get debug.enable)" = true ]; then
touch "$SNAP_COMMON"/.enable_debug
else
rm -f "$SNAP_COMMON"/.enable_debug
fi
exit 0

View file

@ -72,6 +72,7 @@ parts:
x86_64)
IMAGE_PATH="2018/05/23"
IMAGE_NAME="android_amd64.img"
IMAGE_HASH="cbcb8c4740ed38dbc243122df2d8d87511a9c8dcc162781f2eabb5dc1ea079fe"
;;
*)
echo "ERROR: Unknown architecture $ARCH"
@ -83,6 +84,10 @@ parts:
# expects the downloaded file to be an archive it can extract.
echo "Downloading image..."
wget http://build.anbox.io/android-images/$IMAGE_PATH/$IMAGE_NAME
echo "$IMAGE_HASH $IMAGE_NAME" > image-hash
sha256sum -c image-hash
mv $IMAGE_NAME $SNAPCRAFT_PART_INSTALL/android.img
fi

View file

@ -53,6 +53,9 @@ add_library(anbox-protobuf
${GENERATED_PROTOBUF_RPC_HDRS}
${GENERATED_PROTOBUF_CONTAINER_SRCS}
${GENERATED_PROTOBUF_CONTAINER_HDRS}
anbox/protobuf/anbox_rpc.proto
anbox/protobuf/anbox_bridge.proto
anbox/protobuf/anbox_container.proto
anbox/protobuf/google_protobuf_guard.cpp)
target_link_libraries(anbox-protobuf
${PROTOBUF_LITE_LIBRARIES})

View file

@ -244,9 +244,13 @@ anbox::cmds::SessionManager::SessionManager()
{bridge_connector->socket_file(), "/dev/anbox_bridge"},
{audio_server->socket_file(), "/dev/anbox_audio"},
{SystemConfiguration::instance().input_device_dir(), "/dev/input"},
{"/dev/binder", "/dev/binder"},
{"/dev/ashmem", "/dev/ashmem"},
{"/dev/fuse", "/dev/fuse"},
};
container_configuration.devices = {
{"/dev/binder"},
{"/dev/ashmem"},
{"/dev/fuse"},
};
dispatcher->dispatch([&]() {

View file

@ -18,13 +18,15 @@
#ifndef ANBOX_CONTAINER_CONFIGURATION_H_
#define ANBOX_CONTAINER_CONFIGURATION_H_
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
namespace anbox {
namespace container {
struct Configuration {
std::map<std::string, std::string> bind_mounts;
std::unordered_map<std::string, std::string> bind_mounts;
std::vector<std::string> devices;
};
} // namespace container
} // namespace anbox

View file

@ -44,6 +44,14 @@ constexpr const char *default_container_ip_address{"192.168.250.2"};
constexpr const std::uint32_t default_container_ip_prefix_length{24};
constexpr const char *default_host_ip_address{"192.168.250.1"};
constexpr const char *default_dns_server{"8.8.8.8"};
constexpr int device_major(__dev_t dev) {
return int(((dev >> 8) & 0xfff) | ((dev >> 32) & (0xfffff000)));
}
constexpr int device_minor(__dev_t dev) {
return int((dev & 0xff) | ((dev >> 12) & (0xffffff00)));
}
} // namespace
namespace anbox {
@ -157,9 +165,63 @@ void LxcContainer::setup_network() {
}
}
void LxcContainer::add_device(const std::string& device) {
struct stat st;
int r = stat(device.c_str(), &st);
if (r < 0) {
const auto msg = utils::string_format("Failed to retrieve information about device %s", device);
throw std::runtime_error(msg);
}
const auto major = device_major(st.st_rdev);
const auto minor = device_minor(st.st_rdev);
const auto mode = st.st_mode;
const auto new_device_name = fs::basename(device);
const auto devices_path = fs::path(SystemConfiguration::instance().container_devices_dir());
const auto new_device_path = (devices_path / new_device_name).string();
const auto encoded_device_number = (minor & 0xff) | (major << 8) | ((minor & !0xff) << 12);
r = mknod(new_device_path.c_str(), mode, encoded_device_number);
if (r < 0) {
auto msg = utils::string_format("Failed to create node for device %s: %s",
device, strerror(errno));
throw std::runtime_error(msg);
}
auto base_uid = unprivileged_user_id;
if (privileged_)
base_uid = 0;
const auto shifted_uid = base_uid + st.st_uid;
const auto shifted_gid = base_uid + st.st_gid;
r = chown(new_device_path.c_str(), shifted_uid, shifted_gid);
if (r < 0) {
auto msg = utils::string_format("Failed to change ownership of new node for %s: %s",
device, strerror(errno));
throw std::runtime_error(msg);
}
// Needed as mknod respects the umask
r = chmod(new_device_path.c_str(), mode);
if (r < 0) {
auto msg = utils::string_format("Failed to change mode of new node for %s: %s",
device, strerror(errno));
throw::std::runtime_error(msg);
}
auto target_path = device;
// Strip a leading slash as LXC doesn't like that
if (utils::string_starts_with(device, "/"))
target_path = device.substr(1, device.length() - 1);
const auto entry = utils::string_format("%s %s none bind,create=file,optional 0 0",
new_device_path, target_path);
set_config_item("lxc.mount.entry", entry);
}
void LxcContainer::start(const Configuration &configuration) {
if (getuid() != 0)
BOOST_THROW_EXCEPTION(std::runtime_error("You have to start the container as root"));
throw std::runtime_error("You have to start the container as root");
if (container_ && container_->is_running(container_)) {
WARNING("Container already started, stopping it now");
@ -175,7 +237,7 @@ void LxcContainer::start(const Configuration &configuration) {
container_ = lxc_container_new("default", container_config_dir.c_str());
if (!container_)
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create LXC container instance"));
throw std::runtime_error("Failed to create LXC container instance");
// If container is still running (for example after a crash) we stop it here
// to ensure its configuration is synchronized.
@ -220,20 +282,11 @@ void LxcContainer::start(const Configuration &configuration) {
setup_id_maps();
auto bind_mounts = configuration.bind_mounts;
// Extra bind-mounts for user-namespace setup
bind_mounts.insert({"/dev/console", "dev/console"});
bind_mounts.insert({"/dev/full", "dev/full"});
bind_mounts.insert({"/dev/null", "dev/null"});
bind_mounts.insert({"/dev/random", "dev/random"});
bind_mounts.insert({"/dev/tty", "dev/tty"});
bind_mounts.insert({"/dev/urandom", "dev/urandom"});
bind_mounts.insert({"/dev/zero", "dev/zero"});
for (const auto &bind_mount : bind_mounts) {
std::string create_type = "file";
if (fs::is_directory(bind_mount.first)) create_type = "dir";
if (fs::is_directory(bind_mount.first))
create_type = "dir";
auto target_path = bind_mount.second;
// The target path needs to be absolute and pointing to the right
@ -243,18 +296,36 @@ void LxcContainer::start(const Configuration &configuration) {
target_path = std::string("/") + target_path;
target_path = rootfs_path + target_path;
set_config_item(
"lxc.mount.entry",
utils::string_format("%s %s none bind,create=%s,optional 0 0",
bind_mount.first, target_path, create_type));
const auto entry = utils::string_format("%s %s none bind,create=%s,optional 0 0",
bind_mount.first, target_path, create_type);
set_config_item("lxc.mount.entry", entry);
}
if (!container_->save_config(container_, nullptr))
BOOST_THROW_EXCEPTION(
std::runtime_error("Failed to save container configuration"));
auto devices = configuration.devices;
if (not container_->start(container_, 0, nullptr))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to start container"));
// Additional devices we need in our container
devices.push_back("/dev/console");
devices.push_back("/dev/full");
devices.push_back("/dev/null");
devices.push_back("/dev/random");
devices.push_back("/dev/tty");
devices.push_back("/dev/urandom");
devices.push_back("/dev/zero");
// Remove all left over devices from last time first before
// creating any new ones
const auto devices_dir = SystemConfiguration::instance().container_devices_dir();
fs::remove_all(devices_dir);
fs::create_directories(devices_dir);
for (const auto& device : devices)
add_device(device);
if (!container_->save_config(container_, nullptr))
throw std::runtime_error("Failed to save container configuration");
if (!container_->start(container_, 0, nullptr))
throw std::runtime_error("Failed to start container");
state_ = Container::State::running;
@ -262,11 +333,11 @@ void LxcContainer::start(const Configuration &configuration) {
}
void LxcContainer::stop() {
if (not container_ || not container_->is_running(container_))
if (!container_ || !container_->is_running(container_))
return;
if (not container_->stop(container_))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to stop container"));
if (!container_->stop(container_))
throw std::runtime_error("Failed to stop container");
state_ = Container::State::inactive;
@ -275,8 +346,10 @@ void LxcContainer::stop() {
void LxcContainer::set_config_item(const std::string &key,
const std::string &value) {
if (!container_->set_config_item(container_, key.c_str(), value.c_str()))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to configure LXC container"));
if (!container_->set_config_item(container_, key.c_str(), value.c_str())) {
const auto msg = utils::string_format("Failed to set config item %s", key);
throw std::runtime_error(msg);
}
}
Container::State LxcContainer::state() { return state_; }

View file

@ -40,6 +40,7 @@ class LxcContainer : public Container {
void set_config_item(const std::string &key, const std::string &value);
void setup_id_maps();
void setup_network();
void add_device(const std::string& device);
State state_;
lxc_container *container_;

View file

@ -50,8 +50,12 @@ void ManagementApiSkeleton::start_container(
const auto configuration = request->configuration();
for (int n = 0; n < configuration.bind_mounts_size(); n++) {
const auto bind_mount = configuration.bind_mounts(n);
container_configuration.bind_mounts.insert(
{bind_mount.source(), bind_mount.target()});
container_configuration.bind_mounts.insert({bind_mount.source(), bind_mount.target()});
}
for (int n = 0; n < configuration.devices_size(); n++) {
const auto device = configuration.devices(n);
container_configuration.devices.push_back(device);
}
try {

View file

@ -47,6 +47,11 @@ void ManagementApiStub::start_container(const Configuration &configuration) {
message.set_allocated_configuration(message_configuration);
for (const auto &device : configuration.devices) {
auto d = message_configuration->add_devices();
*d = device;
}
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
c->wh.expect_result();

View file

@ -8,6 +8,7 @@ message Configuration {
required string target = 2;
}
repeated BindMount bind_mounts = 1;
repeated string devices = 2;
}
message StartContainer {

View file

@ -75,6 +75,10 @@ std::string anbox::SystemConfiguration::container_socket_path() const {
return path;
}
std::string anbox::SystemConfiguration::container_devices_dir() const {
return (data_path / "devices").string();
}
std::string anbox::SystemConfiguration::socket_dir() const {
static std::string dir = anbox::utils::string_format("%s/anbox/sockets", runtime_dir());
return dir;

View file

@ -38,6 +38,7 @@ class SystemConfiguration {
std::string socket_dir() const;
std::string container_config_dir() const;
std::string container_socket_path() const;
std::string container_devices_dir() const;
std::string input_device_dir() const;
std::string application_item_dir() const;
std::string resource_dir() const;