87 Commits

Author SHA1 Message Date
Andrew Phelps
90c2e4c534 many: modify snap run to understand component hooks (#13976)
* snap, s/snaptest: add function for reading the ComponentInfo of the current revision of a component for a snap revision

* s/snapenv, c/snap: add support for component hooks to ExtendEnvForRun

* c/snap: update run to be able to run component hooks

* c/snap: refactor runSnapConfine to operate on a runnable that can represent snap hooks, component hooks, and apps

This commit doesn't need to be here, and things will work without it.
But things were getting a bit complicated in runSnapConfine with
arguments that represented different things based on what we were
running.

* c/snap-exec: handle running component hooks in snap-exec

* c/snap-exec: move parsing of snap-exec target into execHook and execApp

* snap: make error message when failing to parse current component revision a bit better

* c/snap: add IsHook method to runnable type for easier checking

* s/snaptest: use os.Symlink rather than atomic variant in test code

* snap, s/snapdir, c/snap: fix import cycle issue with hook from snapdir into snap

* c/snap, c/snap-exec: docs and panicking default for NewContainerFromDir

* c/snap, c/snap-exec: set up hook for snap.NewContainerFromDir

* c/snap: remove TODO about getting component revision

* c/snap, c/snap-exec: use _ imports rather than initializing hook manually

* s/naming: add ParseComponentRef function

* snap, o/s/backend, daemon: replace ComponentLinkPath and ComponentInstallDate param with naming.ComponentRef

* snap: use ComponentLinkPath helper in ComponentLinkPath

* s/snapdir: add doc comment for NewContainerForDir

* Revert "snap: use ComponentLinkPath helper in ComponentLinkPath"

This reverts commit 9a56c379779490f798613db31aa66b2b177ddd3d.

* Revert "snap, o/s/backend, daemon: replace ComponentLinkPath and ComponentInstallDate param with naming.ComponentRef"

This reverts commit ca39dc1e60174d769ef2345f1e4b58d63f0f7528.

* Revert "s/naming: add ParseComponentRef function"

This reverts commit a3a9130f6d617bc817a76d884a84c1b83282bb46.

* snap: use ComponentLinkPath helper in ComponentLinkPath

* snap: remove whitespace

* snap: update doc comment on ComponentLinkPath to mention usage constraints of the ContainerPlaceInfo param

* snap: replace NOTE with TODO
2024-06-26 16:49:38 +01:00
Alfonso Sánchez-Beato
56f64edaf7 many: add options to the logger to be able to enable internally debug traces 2024-05-10 19:20:03 +02:00
Miguel Pires
29c9752d66 many: s/ioutil.WriteFile/os.WriteFile (#13217)
Replace ioutil.WriteFile with os.WriteFile since the former has been
deprecated since go1.16 and simply calls the latter.

Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
2023-09-26 11:38:46 +01:00
Maciej Borzecki
ba67ec44fa cmd/snap, cmd/snap-exec: use the helper from logger
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2022-05-23 14:01:55 +02:00
Maciej Borzecki
2c77765bfe cmd/snap-exec: startup timing message
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2022-05-16 12:20:42 +02:00
Michael Vogt
0275484761 snap-exec: fix detection if cups interface is connected
* snap-exec: fix detection if `cups` interface is connected

The cups interface needs a way to set the environment variable
`CUPS_SERVER` if the `cups` interface is connected. However we
have no mechanism for setting environment vars based on interface
connections currently. To workaround this, the cups work added
a workaround in `snap-exec` that tried to detect if `cups` is
connected and when it is set the environment. Unfortunately the
code in there was too simplistic because it just checked if
the directory `/var/cups` exists. However ths dir now always
exists because it's needed as the mount point.

This commit fixes the detection by checking if `/var/cups` is
a bind mount. This is checked by looking at the `stat()` data
and the `dev_t` field in there. If they differ it means the
bind mount exists and the only thing that creates this bind
mount is the `cups` `MountConnectedPlug()` code.

This is not great but it fixes the spread failure we see
in the `cups-control` test (which is a real bug) and should
be good enough until we have a proper interface backend that
can set environment variables.

* tests: re-enable interfaces-cups-control test

For unclear reasons the error message on unplug changes when I
run this on my 20.04 system so I updated the tests - it most likely
because the test-snapd-cups-control-consumer snap moved from
core16 to core20 a week ago but that is not 100% confirmed.

* snap-exec: fix unit test for CUPS_SERVER workaround
2022-04-04 13:17:50 +02:00
Ian Johnson
a2169a490b interfaces/cups: add cups-socket-directory attr, use to specify mount rules in backend (#10427)
interfaces/cups: add cups-socket-directory attr, use to specify mount rules in backend

Make the cups interface slot have an optional attribute, cups-socket-directory, which
is used to specify the directory where the cups socket that the slotting snap
is going to share with client snaps.

This directory then is mounted into client snap's mount namespaces via the
mount backend at /var/cups/, such that client applications wishing to
print need to adjust the location of where they expect the cups socket to
be at all, but then will always end up sending print requests to the cups snap,
which will mediate requests to print based on whether or not the client snap
has a connected cups plug or not.

The primary advantage of this is that it means we don't need to make the cups
interface implictly slotted by the system snap, and it can always be provided
by the cups snap, and we can then make any snap with a cups interface plug
auto-connect to the slot from the cups snap unambiguously, providing all snap
clients the ability to print without any extra connections necessary,
regardless of their distro or what the client snap is.
2022-02-07 09:12:58 -06:00
Samuele Pedroni
c2c8f2489c cmd: fix imports order (according to gci)
gci needed cmd/snap-seccomp/main.go import comment to made one long line
otherwise it keeps only the last line :(

cmd/snap/color_test.go need some manual cleanup of commented out imports
2021-06-15 10:25:05 +02:00
Michael Vogt
50fe4a9ec0 snap: add new snap run --gdbserver option
This will run a snap app with an attached gdbserver from the host.
The app can run inside the confinement as a regular user and it can be
debugged by running a gdb (or frontend) and attaching it to the
running gdbserver.

The app is run as the normal user and only the gdbserver is run
as root. This allows debugging confined apps as well and it
avoids the downside of the current "snap run --gdb" that requires
to be run as root. It also allows attaching gdb frontends that
can talk gdbserver.

The setup is slightly involved:
1. snap run/snap-confine/snap-exec run normally
2. a new snap-gdbserver-shim is run that triggers "SIGSTOP"
3. gdbserver is attached once `snap run` got the SIGSTOP
   from the app. Note that at this point no application code
   was run yet so it does not matter if the app is using any
   of these signals
4. The attached gdbserver will interrupt the running app now.
   We can not do anything smart inside snap-gdbserver-shim.c
   (like waiting for an attached ptracer) because that would
   leak into the debug session.
5. Now gdb can get attached must send "cont", "signal SIGCONT"
6. With that setup gdb is right before the real app is exec()ed
   (just like with `snap run --gdb` today)

There are some XXX inside this commit with ideas/questions about
the UX but it should be usable and an improvement over the current
`snap run --gdb`. If this looks good we could deprecate, remove
or replace the existing `snap run --gdbserver`.

The approach of attaching gdbserver from the outside instead of
running gdbserver from snap-exec was taken to avoid having to
open the ptrace syscall inside the confined app. This is what
we would have to do if we just run gdbserver inside the sandbox
that snap-confine setup for us.
2020-06-02 17:38:16 +02:00
Zygmunt Krynicki
913d765818 many: improve environment handling, fixing duplicate entries (#8242)
* strutil: add Environment, EnvironmentDelta and RawEnvironment

This patch adds three new types and supporting methods.

Environment is an unordered map representing environment entries that is
convenient to modify.  EnvironmentDelta is an ordered map representing
changes to an environment that also supports variable substitution and
expansion. Finally RawEnvironment is a slice representing key=value
pairs that is useful for low-level system interfaces.

Environment and EnvironmentDelta can be modified with simple map-like
methods Get, Set, Del. RawEnvironment can only be parsed to an
Environment.

The patch also contains Environment.ApplyDelta function, which correctly
applies a single delta to a given environment.

The types are designed to avoid the mistake of appending two slices
representing environment strings together. This was the original cause
of bug https://bugs.launchpad.net/snapd/+bug/1860369

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: use Environment, EnvironmentDelta and RawEnvironment

This patch replaces all ad-hoc environment handling with the three
aforementioned types. Environment is used whenever we are working
with the real complete environment (starting from OSEnvironment).
EnvironmentDelta is used to modify it according to snap-level and
application-level or hook-level overrides. Finally RawEnvironment
is only used by snap run and snap-exec, immediately before calling
execve.

This fixes incorrect handling of environment in snap-exec and also
avoids this class of bugs by making it hard, due to type system,
to express mistakes again.

Fixes: https://bugs.launchpad.net/snapd/+bug/1860369
Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* osutil/env: import all symbols from check.v1

This style is shorter and we use it nearly everywhere else.
I'm about to combine more tests into this file and I don't want
to invert their style over to the verbose one.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: move new environment code to osutil

There's a lot of churn but that's unavoidable in such a move.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: remove RawEnvironment type

The raw environment is necessary only for executing programs. We can
remove the type and replace it with []string in tests (where it has most
of the usage) and a few call sites.

The corresponding method from Environment was renamed to ForExec().

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: make Environment a map[string]string

Some extra methods such as Get, Set and Delete are retained but they
are all arguably unnecessarily and will be removed in another pass.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: remove most map-like methods from Environment

This includes Get, Delete and Contains but not Set. Set has extra
semantics that will be removed in another pass.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: remove Environment.Set

This patch removes the leftover map-like method from the Environment
type. Some extra care was applied to ensure we don't try to write
through a nil map, something that Set protected against.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* cmd/snap-exec: use NewEnvironment in test code

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: rename EnvironmentDelta to ExpandableEnv

The main feature of what was called EnvironmentDelta is the fact it
could expand expressions in variable definitions. This makes it more
obvious.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: make ExpandableEnv an immutable *strutil.OrderedMap

There's a lot of extra changes to make the journey more complete.

First of all both snap.AppInfo and snap.HookInfo provide a method
EnvStack() []osutil.ExpandableEnv which replaces the earlier
EnvironmentOverrides. Instead of merging environment entries the
entire chain is modeled. This will be relevant when we want to expand
values.

This also means that support code to make EnvStack mutable is gone.

Second of all, snap/snapenv.ExecEnv has reverted to using plain
Environment (aka map[string]string) for basicEnv and userEnv. The
values never had expressions so using the more sophisticated code
there is not really necessary.

Delta from master could be reduced further but I went for clarity
of the progression over the clarity of the end-to-end diff.

Lastly, a small but important change, snap-exec now expands each
ExpandableEnv in sequence. First for the snap-level and then for the
app or hook level. This should fix the issue that each level wanted
to expand but not completely erase the value set previously.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* osutil: remove NewEnvironment

With the current type it's not any better than just defining a map
locally.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* osutil: make ParseRawEnvironment private

It is only required for OSEnvironment and is not used anywhere outside
of the package.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: rename ApplyDelta to SetExpandableEnv

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* osutil: update stale documentation referring to delta

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* osutil: weaken SetExpandableEnv

When initially implemented as a part of this branch, SetExpandableEnv
(nee ApplyDelta) behaved in somewhat unusual and "strong" way, where
forward references _were_ expanded. This was not previously so and
arguably is not needed.

As the code stands now, we have proper chaining starting from system
environment, to snap-level environment declarations (that can expand
variables) and all the way down to application or hook-level environment
declarations (also with variable expansions). Since such declarations
are ordered this provides the equivalence of shell execution performing
the same expansions.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: special-case Environment.Transform

Instead of offering specialized environment transformation functions
offer just the things we need: escaping and un-escaping of unsafe
variables removed by the dynamic linker when loading binaries with
AT_SECURE flag.

Various bits move from snap/snapenv to osutil.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

* many: EnvStack to EnvChain, SetExpandableEnv to ExtendWithExpanded

also adjust doc comments and cover ExtendWithExpanded for the nil
initial env case

* cmd/snap,snap/snapenv: change snapenv.ExecEnv into ExtendEnvForRun

* many: make preserving ld.so setuid unsafe vars a boundary concern

support the escaping/unescaping that we use for preserving vars
stripped out by ld.so for snap-confine, via variants of
OSEnvironment/ForExec so that is happens at the process boundaries,
loading os env and setting env for exec

add/change some tests related to this

adjust comments/doc comments or add

Co-authored-by: Samuele Pedroni <pedronis@lucediurna.net>
Co-authored-by: Michael Vogt <mvo@ubuntu.com>
2020-03-20 11:58:19 +01:00
Zygmunt Krynicki
56ebedb503 cmd/snap-exec: add test case for LP:#1860369
It was noticed that snap-exec's handling of environment is incorrect.
Under certain circumstances the environment block contains more than one
entry for the given key (environment variable). In addition, though this
is not illustrated in this patch, the internal expansion code (built
into parts of snapd) uses only one of those values when expanding
environment variables ahead of forwarding their values to snap
applications.

This patch contains only the test case showing the problem.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
2020-03-09 10:49:23 +01:00
Maciej Borzecki
b20451b651 cmd/snap-exec: tweak test data to make it less confusing
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2019-06-18 16:04:04 +02:00
Maciej Borzecki
8709aed1f2 cmd/snap-exec: tweak how completion helper is looked up
Implement a finer lookup for the completion helper, under the assumption that
the helper always exists in the same directory as snap-exec.

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2019-06-18 12:22:43 +02:00
Maciej Borzecki
d3b375fe74 cmd/snap-exec: fix snap completion for classic snaps with non /usr/lib/snapd libexecdir
Fix completion for classic snaps on systems where snapd libexecdir is not
/usr/lib/snapd. These are for instance Fedora and CentOS, where libexecdir is
set to /usr/libexec/snapd.

When run for completions, snap-exec would always attempt to run the completer
from the path which is correct given the snap gets a mount namespace (i.e. is
not classic).

This worked by accident on systems that use /usr/lib/snapd (eg. Ubuntu, Debian,
Arch), but failed on those using /usr/libexec/snapd.

For instance, on CentOS, one would see:

$ cmake -G Ni<tab>
/bin/bash: /usr/lib/snapd/etelpmoc.sh: No such file or directory

Fixes: https://bugs.launchpad.net/snapd/+bug/1833043

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2019-06-17 12:08:40 +02:00
Zygmunt Krynicki
e1a0ee17c6 snap: use Lstat to determine snap size, remove ReadSnapInfoExceptSize
Since we can os.Lstat any symlink safely we can determine that it is
actually a symbolic link and then decide not to follow it or use any
information about it.

This simplifies the API, keeping the fix to LP: #1800004 fixed.
Thanks to Chipaca for the idea.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
2018-10-29 13:12:43 +01:00
Zygmunt Krynicki
c3286da172 cmd/snap-exec: use ReadInfoExceptSize
A try-mode snap is represented by a bind mount from whatever the original
location was, to /snap/$SNAP_NAME/$SNAP_REVISION as well as a symlink
from /var/lib/snapd/snap/$SNAP_NAME_$SNAP_REVISION.snap to whatever
the original location was.

In the execution environment the symlink cannot work, in general. The
code loading snap.Info was using the fully generic snap.ReadInfo which,
as one of the features, tried to stat and compute the size of the snap.

Since reading the size of a snap is not very useful for snap-exec and
since it can fail if the symlink is not reachable in the execution
environment, switch to the more limited helper.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
2018-10-25 21:26:27 +02:00
Kyle Fazzari
2d8fa4e89d cmd: remove --skip-command-chain from snap run and snap-exec (#5723) 2018-08-27 10:51:07 +01:00
Kyle Fazzari
602ecfdd7f snap,snap-exec: support command-chain for hooks
When a snap is created by the snapcraft CLI, each hook potentially has
an associated chunk of environment variables defined as well as scripts
that may be run before the hook itself. Currently, this is done by
generating a shell script wrapper for each hook, but this is opaque and
confusing.

Snapd supports an `environment` keyword for apps and hooks as well as a
`command-chain` for apps. Add the last item needed before the shell
wrappers can go away completely: `command-chain` support in hooks.

See forum topic https://forum.snapcraft.io/t/6112 for more details.

Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2018-08-14 10:45:50 -07:00
Kyle Fazzari
62634dfcd0 snap-exec: prepend command-chain in execApp
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2018-08-13 10:42:49 -07:00
Kyle Fazzari
3faa64414d snap-exec: stop re-calling MountDir
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2018-08-13 09:29:04 -07:00
Kyle Fazzari
58c7dea1f3 Another round of reviews
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2018-08-08 07:59:26 -07:00
Kyle Fazzari
7e7bd1c09f Fix review feedback
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2018-08-06 10:00:08 -07:00
Kyle Fazzari
734c5b52c7 Add ability to skip command chain
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2018-07-30 11:30:35 -07:00
Kyle Fazzari
22b819cdf1 Review fixes
Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2018-07-30 10:05:01 -07:00
Kyle Fazzari
565b8590d4 snap,snap-exec: support command-chain for app
When a snap is created by the snapcraft CLI, each app has an associated
chunk of environment variables defined as well as scripts that may be
run before the app's command. Currently, this is done by generating a
shell script wrapper for each app, but this is opaque and confusing, and
makes `snap run --shell` not actually provide a representative
environment for the app.

Snapd supports an `environment` keyword for apps and hooks, but the last
item needed before the shell wrappers can go away is the ability to run
scripts before the app command. Add support for this to apps. Hook
support will be a follow-up.

See forum topic https://forum.snapcraft.io/t/6112 for more details.

Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2018-07-27 09:21:18 -07:00