Skip to content

Commit

Permalink
Merge branch 'master' of github.com:snapcore/snapd into tweak/refacto…
Browse files Browse the repository at this point in the history
…r-sc-main-4
  • Loading branch information
zyga committed Mar 12, 2019
2 parents 3dadda8 + f7b2233 commit 2e29bf0
Show file tree
Hide file tree
Showing 20 changed files with 645 additions and 438 deletions.
18 changes: 4 additions & 14 deletions cmd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ snap_confine_snap_confine_SOURCES = \
snap-confine/mount-support.h \
snap-confine/ns-support.c \
snap-confine/ns-support.h \
snap-confine/seccomp-support-ext.c \
snap-confine/seccomp-support-ext.h \
snap-confine/seccomp-support.c \
snap-confine/seccomp-support.h \
snap-confine/snap-confine-args.c \
snap-confine/snap-confine-args.h \
snap-confine/snap-confine-invocation.c \
Expand Down Expand Up @@ -267,20 +271,6 @@ snap-confine/snap-confine$(EXEEXT): LIBS += -Wl,-Bstatic $(snap_confine_snap_con
snap_confine_snap_confine_CFLAGS += $(SUID_CFLAGS)
snap_confine_snap_confine_LDFLAGS += $(SUID_LDFLAGS)

if SECCOMP
snap_confine_snap_confine_SOURCES += \
snap-confine/seccomp-support-ext.c \
snap-confine/seccomp-support-ext.h \
snap-confine/seccomp-support.c \
snap-confine/seccomp-support.h
snap_confine_snap_confine_CFLAGS += $(SECCOMP_CFLAGS)
if STATIC_LIBSECCOMP
snap_confine_snap_confine_STATIC += $(shell $(PKG_CONFIG) --static --libs libseccomp)
else
snap_confine_snap_confine_extra_libs += $(SECCOMP_LIBS)
endif # STATIC_LIBSECCOMP
endif # SECCOMP

if APPARMOR
snap_confine_snap_confine_CFLAGS += $(APPARMOR_CFLAGS)
if STATIC_LIBAPPARMOR
Expand Down
2 changes: 1 addition & 1 deletion cmd/autogen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ case "$ID" in
extra_opts="--libexecdir=/usr/lib/snapd"
;;
ubuntu)
extra_opts="--libexecdir=/usr/lib/snapd --enable-nvidia-multiarch --enable-static-libcap --enable-static-libapparmor --enable-static-libseccomp --with-host-arch-triplet=$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
extra_opts="--libexecdir=/usr/lib/snapd --enable-nvidia-multiarch --enable-static-libcap --enable-static-libapparmor --with-host-arch-triplet=$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
if [ "$(dpkg-architecture -qDEB_HOST_ARCH)" = "amd64" ]; then
extra_opts="$extra_opts --with-host-arch-32bit-triplet=$(dpkg-architecture -ai386 -qDEB_HOST_MULTIARCH)"
fi
Expand Down
30 changes: 1 addition & 29 deletions cmd/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -64,34 +64,15 @@ AC_ARG_ENABLE([apparmor],
esac], [enable_apparmor=yes])
AM_CONDITIONAL([APPARMOR], [test "x$enable_apparmor" = "xyes"])

# Allow to build without seccomp support by calling:
# ./configure --disable-seccomp
# This is separate because seccomp support is generally very good and it
# provides useful confinement for unsafe system calls.
AC_ARG_ENABLE([seccomp],
AS_HELP_STRING([--disable-seccomp], [Disable seccomp support]),
[case "${enableval}" in
yes) enable_seccomp=yes ;;
no) enable_seccomp=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --disable-seccomp])
esac], [enable_seccomp=yes])
AM_CONDITIONAL([SECCOMP], [test "x$enable_seccomp" = "xyes"])

# Enable older tests only when confinement is enabled and we're building for PC
# The tests are of smaller value as we port more and more tests to spread.
AM_CONDITIONAL([CONFINEMENT_TESTS], [test "x$enable_apparmor" = "xyes" && test "x$enable_seccomp" = "xyes" && ((test "x$host_cpu" = "xx86_64" && test "x$build_cpu" = "xx86_64") || (test "x$host_cpu" = "xi686" && test "x$build_cpu" = "xi686"))])
AM_CONDITIONAL([CONFINEMENT_TESTS], [test "x$enable_apparmor" = "xyes" && ((test "x$host_cpu" = "xx86_64" && test "x$build_cpu" = "xx86_64") || (test "x$host_cpu" = "xi686" && test "x$build_cpu" = "xi686"))])

# Check for glib that we use for unit testing
AS_IF([test "x$with_unit_tests" = "xyes"], [
PKG_CHECK_MODULES([GLIB], [glib-2.0])
])

# Check if seccomp userspace library is available
AS_IF([test "x$enable_seccomp" = "xyes"], [
PKG_CHECK_MODULES([SECCOMP], [libseccomp], [
AC_DEFINE([HAVE_SECCOMP], [1], [Build with seccomp support])])
])

# Check if apparmor userspace library is available.
AS_IF([test "x$enable_apparmor" = "xyes"], [
PKG_CHECK_MODULES([APPARMOR], [libapparmor], [
Expand Down Expand Up @@ -200,15 +181,6 @@ AC_ARG_ENABLE([static-libapparmor],
esac], [enable_static_libapparmor=no])
AM_CONDITIONAL([STATIC_LIBAPPARMOR], [test "x$enable_static_libapparmor" = "xyes"])

AC_ARG_ENABLE([static-libseccomp],
AS_HELP_STRING([--enable-static-libseccomp], [Link libseccomp statically]),
[case "${enableval}" in
yes) enable_static_libseccomp=yes ;;
no) enable_static_libseccomp=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-static-libseccomp])
esac], [enable_static_libseccomp=no])
AM_CONDITIONAL([STATIC_LIBSECCOMP], [test "x$enable_static_libseccomp" = "xyes"])

LIB32_DIR="${prefix}/lib32"
AC_ARG_WITH([32bit-libdir],
AS_HELP_STRING([--with-32bit-libdir=DIR], [Use an alternate lib32 directory]),
Expand Down
1 change: 0 additions & 1 deletion cmd/snap-confine/seccomp-support.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#ifndef SNAP_CONFINE_SECCOMP_SUPPORT_H
#define SNAP_CONFINE_SECCOMP_SUPPORT_H

#include <seccomp.h>
#include <stdbool.h>

/**
Expand Down
25 changes: 15 additions & 10 deletions cmd/snap-confine/snap-confine.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,22 @@

#include "../libsnap-confine-private/apparmor-support.h"
#include "../libsnap-confine-private/cgroup-freezer-support.h"
#include "../libsnap-confine-private/cgroup-pids-support.h"
#include "../libsnap-confine-private/classic.h"
#include "../libsnap-confine-private/cleanup-funcs.h"
#include "../libsnap-confine-private/feature.h"
#include "../libsnap-confine-private/locking.h"
#include "../libsnap-confine-private/secure-getenv.h"
#include "../libsnap-confine-private/snap.h"
#include "../libsnap-confine-private/utils.h"
#include "cookie-support.h"
#include "mount-support.h"
#include "ns-support.h"
#include "udev-support.h"
#include "user-support.h"
#include "cookie-support.h"
#include "seccomp-support.h"
#include "snap-confine-args.h"
#include "snap-confine-invocation.h"
#ifdef HAVE_SECCOMP
#include "seccomp-support.h"
#endif // ifdef HAVE_SECCOMP
#include "udev-support.h"
#include "user-support.h"

// sc_maybe_fixup_permissions fixes incorrect permissions
// inside the mount namespace for /var/lib. Before 1ccce4
Expand Down Expand Up @@ -204,13 +203,11 @@ int main(int argc, char **argv)
#endif
// https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement
sc_maybe_aa_change_onexec(&apparmor, invocation.security_tag);
#ifdef HAVE_SECCOMP
if (sc_apply_seccomp_profile_for_security_tag(invocation.security_tag)) {
/* If the process is not explicitly unconfined then load the global
* profile as well. */
sc_apply_global_seccomp_profile();
}
#endif // ifdef HAVE_SECCOMP
if (snap_context != NULL) {
setenv("SNAP_COOKIE", snap_context, 1);
// for compatibility, if facing older snapd.
Expand Down Expand Up @@ -352,16 +349,24 @@ static void enter_non_classic_execution_environment(sc_invocation * inv,
}
}
}
// Associate each snap process with a dedicated snap freezer control group.
// Associate each snap process with a dedicated snap freezer cgroup and
// snap pids cgroup. All snap processes belonging to one snap share the
// freezer cgroup. All snap processes belonging to one app or one hook
// share the pids cgroup.
//
// This simplifies testing if any processes belonging to a given snap are
// still alive. See the documentation of the function for details.
// still alive as well as to properly account for each application and
// service.
if (getegid() != 0 && saved_gid == 0) {
// Temporarily raise egid so we can chown the freezer cgroup under LXD.
if (setegid(0) != 0) {
die("cannot set effective group id to root");
}
}
sc_cgroup_freezer_join(inv->snap_instance, getpid());
if (sc_feature_enabled(SC_FEATURE_REFRESH_APP_AWARENESS)) {
sc_cgroup_pids_join(inv->security_tag, getpid());
}
if (geteuid() == 0 && real_gid != 0) {
if (setegid(real_gid) != 0) {
die("cannot set effective group id to %d", real_gid);
Expand Down
67 changes: 0 additions & 67 deletions daemon/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,20 +183,6 @@ var (
POST: changeInterfaces,
}

// TODO: allow to post assertions for UserOK? they are verified anyway
assertsCmd = &Command{
Path: "/v2/assertions",
UserOK: true,
GET: getAssertTypeNames,
POST: doAssert,
}

assertsFindManyCmd = &Command{
Path: "/v2/assertions/{assertType}",
UserOK: true,
GET: assertsFindMany,
}

stateChangeCmd = &Command{
Path: "/v2/changes/{id}",
UserOK: true,
Expand Down Expand Up @@ -1908,59 +1894,6 @@ func changeInterfaces(c *Command, r *http.Request, user *auth.UserState) Respons
return AsyncResponse(nil, &Meta{Change: change.ID()})
}

func getAssertTypeNames(c *Command, r *http.Request, user *auth.UserState) Response {
return SyncResponse(map[string][]string{
"types": asserts.TypeNames(),
}, nil)
}

func doAssert(c *Command, r *http.Request, user *auth.UserState) Response {
batch := assertstate.NewBatch()
_, err := batch.AddStream(r.Body)
if err != nil {
return BadRequest("cannot decode request body into assertions: %v", err)
}

state := c.d.overlord.State()
state.Lock()
defer state.Unlock()

if err := batch.Commit(state); err != nil {
return BadRequest("assert failed: %v", err)
}
// TODO: what more info do we want to return on success?
return &resp{
Type: ResponseTypeSync,
Status: 200,
}
}

func assertsFindMany(c *Command, r *http.Request, user *auth.UserState) Response {
assertTypeName := muxVars(r)["assertType"]
assertType := asserts.Type(assertTypeName)
if assertType == nil {
return BadRequest("invalid assert type: %q", assertTypeName)
}
headers := map[string]string{}
q := r.URL.Query()
for k := range q {
headers[k] = q.Get(k)
}

state := c.d.overlord.State()
state.Lock()
db := assertstate.DB(state)
state.Unlock()

assertions, err := db.FindMany(assertType, headers)
if asserts.IsNotFound(err) {
return AssertResponse(nil, true)
} else if err != nil {
return InternalError("searching assertions failed: %v", err)
}
return AssertResponse(assertions, true)
}

type changeInfo struct {
ID string `json:"id"`
Kind string `json:"kind"`
Expand Down
97 changes: 97 additions & 0 deletions daemon/api_asserts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2016-2019 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package daemon

import (
"net/http"

"github.com/snapcore/snapd/asserts"
"github.com/snapcore/snapd/overlord/assertstate"
"github.com/snapcore/snapd/overlord/auth"
)

var (
// TODO: allow to post assertions for UserOK? they are verified anyway
assertsCmd = &Command{
Path: "/v2/assertions",
UserOK: true,
GET: getAssertTypeNames,
POST: doAssert,
}

assertsFindManyCmd = &Command{
Path: "/v2/assertions/{assertType}",
UserOK: true,
GET: assertsFindMany,
}
)

func getAssertTypeNames(c *Command, r *http.Request, user *auth.UserState) Response {
return SyncResponse(map[string][]string{
"types": asserts.TypeNames(),
}, nil)
}

func doAssert(c *Command, r *http.Request, user *auth.UserState) Response {
batch := assertstate.NewBatch()
_, err := batch.AddStream(r.Body)
if err != nil {
return BadRequest("cannot decode request body into assertions: %v", err)
}

state := c.d.overlord.State()
state.Lock()
defer state.Unlock()

if err := batch.Commit(state); err != nil {
return BadRequest("assert failed: %v", err)
}
// TODO: what more info do we want to return on success?
return &resp{
Type: ResponseTypeSync,
Status: 200,
}
}

func assertsFindMany(c *Command, r *http.Request, user *auth.UserState) Response {
assertTypeName := muxVars(r)["assertType"]
assertType := asserts.Type(assertTypeName)
if assertType == nil {
return BadRequest("invalid assert type: %q", assertTypeName)
}
headers := map[string]string{}
q := r.URL.Query()
for k := range q {
headers[k] = q.Get(k)
}

state := c.d.overlord.State()
state.Lock()
db := assertstate.DB(state)
state.Unlock()

assertions, err := db.FindMany(assertType, headers)
if asserts.IsNotFound(err) {
return AssertResponse(nil, true)
} else if err != nil {
return InternalError("searching assertions failed: %v", err)
}
return AssertResponse(assertions, true)
}

0 comments on commit 2e29bf0

Please sign in to comment.