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 6. ** Please paste the result of `anbox system-info` below:**
** Please paste the result of `anbox system-info` below:**
``` ```
[please paste printout of `anbox system-info` here] [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:** **Additional info:**

1
.gitignore vendored
View file

@ -2,7 +2,6 @@ build*/
parts/ parts/
stage/ stage/
prime/ prime/
snap/
android-images/ android-images/
*.snap *.snap
CMakeLists.txt.user 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 Once proper confinement for the Anbox snap exists we will also start using the
candidate and stable channels. 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() endif()
# ANBOX: allow old-style casts # 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 # BACKWARD OBJECT

View file

@ -24,8 +24,8 @@ echo "Collecting anbox log files ... "
set -x set -x
# Collect several things which are of interest for bug reports # Collect several things which are of interest for bug reports
cp /var/snap/anbox/common/data/system.log $TMPDIR || true cp /var/snap/anbox/common/data/system.log $TMPDIR || true
cp /var/snap/anbox/containers/lxc-monitord.log $TMPDIR || true cp /var/snap/anbox/common/containers/lxc-monitord.log $TMPDIR || true
cp /var/snap/anbox/logs/container.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 $SNAP/command-anbox.wrapper system-info > $TMPDIR/system-info.log 2>&1 || true
if [ -e /etc/systemd/system/snap.anbox.container-manager.service ]; then 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 $SNAP/sbin/apparmor_parser -r $SNAP/apparmor/anbox-container.aa
fi fi
if [ -e "$SNAP_COMMON"/.enable_debug ]; then
export ANBOX_LOG_LEVEL=debug
fi
exec $AA_EXEC $SNAP/bin/anbox-wrapper.sh container-manager \ exec $AA_EXEC $SNAP/bin/anbox-wrapper.sh container-manager \
--data-path=$DATA_PATH \ --data-path=$DATA_PATH \
--android-image=$ANDROID_IMG \ --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. # configured but the actual EGL implementation is missing.
export __EGL_VENDOR_LIBRARY_DIRS="$SNAP/glvnd" 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 $@ 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) x86_64)
IMAGE_PATH="2018/05/23" IMAGE_PATH="2018/05/23"
IMAGE_NAME="android_amd64.img" IMAGE_NAME="android_amd64.img"
IMAGE_HASH="cbcb8c4740ed38dbc243122df2d8d87511a9c8dcc162781f2eabb5dc1ea079fe"
;; ;;
*) *)
echo "ERROR: Unknown architecture $ARCH" echo "ERROR: Unknown architecture $ARCH"
@ -83,6 +84,10 @@ parts:
# expects the downloaded file to be an archive it can extract. # expects the downloaded file to be an archive it can extract.
echo "Downloading image..." echo "Downloading image..."
wget http://build.anbox.io/android-images/$IMAGE_PATH/$IMAGE_NAME 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 mv $IMAGE_NAME $SNAPCRAFT_PART_INSTALL/android.img
fi fi

View file

@ -53,6 +53,9 @@ add_library(anbox-protobuf
${GENERATED_PROTOBUF_RPC_HDRS} ${GENERATED_PROTOBUF_RPC_HDRS}
${GENERATED_PROTOBUF_CONTAINER_SRCS} ${GENERATED_PROTOBUF_CONTAINER_SRCS}
${GENERATED_PROTOBUF_CONTAINER_HDRS} ${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) anbox/protobuf/google_protobuf_guard.cpp)
target_link_libraries(anbox-protobuf target_link_libraries(anbox-protobuf
${PROTOBUF_LITE_LIBRARIES}) ${PROTOBUF_LITE_LIBRARIES})

View file

@ -244,9 +244,13 @@ anbox::cmds::SessionManager::SessionManager()
{bridge_connector->socket_file(), "/dev/anbox_bridge"}, {bridge_connector->socket_file(), "/dev/anbox_bridge"},
{audio_server->socket_file(), "/dev/anbox_audio"}, {audio_server->socket_file(), "/dev/anbox_audio"},
{SystemConfiguration::instance().input_device_dir(), "/dev/input"}, {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([&]() { dispatcher->dispatch([&]() {

View file

@ -18,13 +18,15 @@
#ifndef ANBOX_CONTAINER_CONFIGURATION_H_ #ifndef ANBOX_CONTAINER_CONFIGURATION_H_
#define ANBOX_CONTAINER_CONFIGURATION_H_ #define ANBOX_CONTAINER_CONFIGURATION_H_
#include <map>
#include <string> #include <string>
#include <unordered_map>
#include <vector>
namespace anbox { namespace anbox {
namespace container { namespace container {
struct Configuration { 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 container
} // namespace anbox } // 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 std::uint32_t default_container_ip_prefix_length{24};
constexpr const char *default_host_ip_address{"192.168.250.1"}; constexpr const char *default_host_ip_address{"192.168.250.1"};
constexpr const char *default_dns_server{"8.8.8.8"}; 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
namespace anbox { 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) { void LxcContainer::start(const Configuration &configuration) {
if (getuid() != 0) 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_)) { if (container_ && container_->is_running(container_)) {
WARNING("Container already started, stopping it now"); 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()); container_ = lxc_container_new("default", container_config_dir.c_str());
if (!container_) 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 // If container is still running (for example after a crash) we stop it here
// to ensure its configuration is synchronized. // to ensure its configuration is synchronized.
@ -220,20 +282,11 @@ void LxcContainer::start(const Configuration &configuration) {
setup_id_maps(); setup_id_maps();
auto bind_mounts = configuration.bind_mounts; 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) { for (const auto &bind_mount : bind_mounts) {
std::string create_type = "file"; 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; auto target_path = bind_mount.second;
// The target path needs to be absolute and pointing to the right // 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 = std::string("/") + target_path;
target_path = rootfs_path + target_path; target_path = rootfs_path + target_path;
set_config_item( const auto entry = utils::string_format("%s %s none bind,create=%s,optional 0 0",
"lxc.mount.entry", bind_mount.first, target_path, create_type);
utils::string_format("%s %s none bind,create=%s,optional 0 0", set_config_item("lxc.mount.entry", entry);
bind_mount.first, target_path, create_type));
} }
if (!container_->save_config(container_, nullptr)) auto devices = configuration.devices;
BOOST_THROW_EXCEPTION(
std::runtime_error("Failed to save container configuration"));
if (not container_->start(container_, 0, nullptr)) // Additional devices we need in our container
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to start 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; state_ = Container::State::running;
@ -262,11 +333,11 @@ void LxcContainer::start(const Configuration &configuration) {
} }
void LxcContainer::stop() { void LxcContainer::stop() {
if (not container_ || not container_->is_running(container_)) if (!container_ || !container_->is_running(container_))
return; return;
if (not container_->stop(container_)) if (!container_->stop(container_))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to stop container")); throw std::runtime_error("Failed to stop container");
state_ = Container::State::inactive; state_ = Container::State::inactive;
@ -275,8 +346,10 @@ void LxcContainer::stop() {
void LxcContainer::set_config_item(const std::string &key, void LxcContainer::set_config_item(const std::string &key,
const std::string &value) { const std::string &value) {
if (!container_->set_config_item(container_, key.c_str(), value.c_str())) if (!container_->set_config_item(container_, key.c_str(), value.c_str())) {
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to configure LXC container")); const auto msg = utils::string_format("Failed to set config item %s", key);
throw std::runtime_error(msg);
}
} }
Container::State LxcContainer::state() { return state_; } 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 set_config_item(const std::string &key, const std::string &value);
void setup_id_maps(); void setup_id_maps();
void setup_network(); void setup_network();
void add_device(const std::string& device);
State state_; State state_;
lxc_container *container_; lxc_container *container_;

View file

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

View file

@ -47,6 +47,11 @@ void ManagementApiStub::start_container(const Configuration &configuration) {
message.set_allocated_configuration(message_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_); std::lock_guard<decltype(mutex_)> lock(mutex_);
c->wh.expect_result(); c->wh.expect_result();

View file

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

View file

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

View file

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