Skip to content

Commit e44c367

Browse files
authored
Merge pull request #1550 from criblio/feat/1523-filter-existing-containers
Apply rules to existing containers (#1523)
2 parents 677684c + 00cd78c commit e44c367

File tree

13 files changed

+380
-32
lines changed

13 files changed

+380
-32
lines changed

cleanup_after_start.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
#
55

66
PRELOAD_PATH="/etc/ld.so.preload"
7+
LIBSCOPE_PATH="/usr/lib/libscope.so"
78
PROFILE_SCOPE_SCRIPT="/etc/profile.d/scope.sh"
89
USR_APPSCOPE_DIR="/usr/lib/appscope/"
910
TMP_APPSCOPE_DIR="/tmp/appscope/"
1011
CRIBL_APPSCOPE_DIR="$CRIBL_HOME/appscope/"
1112

1213
echo "Following script will try to remove following files:"
1314
echo "- $PRELOAD_PATH"
15+
echo "- $LIBSCOPE_PATH"
1416
echo "- $PROFILE_SCOPE_SCRIPT"
1517
echo "- $USR_APPSCOPE_DIR"
1618
echo "- $TMP_APPSCOPE_DIR"
@@ -35,6 +37,14 @@ else
3537
echo "$PRELOAD_PATH file was missing. Continue..."
3638
fi
3739

40+
# This one is a symbolic link
41+
if [ -L $LIBSCOPE_PATH ] ; then
42+
rm $LIBSCOPE_PATH
43+
echo "$LIBSCOPE_PATH file was removed"
44+
else
45+
echo "$LIBSCOPE_PATH file was missing. Continue..."
46+
fi
47+
3848
if [ -f $PROFILE_SCOPE_SCRIPT ] ; then
3949
rm $PROFILE_SCOPE_SCRIPT
4050
echo "$PROFILE_SCOPE_SCRIPT file was removed"

cli/loader/loader.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package loader
22

33
import (
4+
"fmt"
45
"os"
56
"os/exec"
67
"strconv"
@@ -52,10 +53,12 @@ func (sL *ScopeLoader) Preload(path, rootdir string) (string, error) {
5253
}
5354

5455
// Mount Command
55-
func (sL *ScopeLoader) Mount(source, dest, rootdir string) (string, error) {
56+
func (sL *ScopeLoader) Mount(path string, cPid int, rootdir string) (string, error) {
5657
args := make([]string, 0)
5758
args = append(args, "--mount")
58-
args = append(args, source+","+dest)
59+
args = append(args, path)
60+
args = append(args, "--namespace")
61+
args = append(args, fmt.Sprint(cPid))
5962
if rootdir != "" {
6063
args = append(args, "--rootdir")
6164
args = append(args, rootdir)

cli/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,8 @@ __attribute__((constructor)) void cli_constructor() {
239239
fprintf(stderr, "error: --rules and --service/--unservice cannot be used together\n");
240240
exit(EXIT_FAILURE);
241241
}
242-
if (opt_namespace && (!opt_service && !opt_unservice)) {
243-
fprintf(stderr, "error: --namespace option requires --service/--unservice option\n");
242+
if (opt_namespace && (!opt_service && !opt_unservice && !opt_mount)) {
243+
fprintf(stderr, "error: --namespace option requires --service/--unservice or --mount option\n");
244244
exit(EXIT_FAILURE);
245245
}
246246
if (opt_passthrough && (opt_ldattach || opt_lddetach || opt_namespace ||
@@ -292,7 +292,7 @@ __attribute__((constructor)) void cli_constructor() {
292292
if (opt_install) exit(cmdInstall(arg_rootdir));
293293
if (opt_rules) exit(cmdRules(arg_rules, arg_rootdir));
294294
if (opt_preload) exit(cmdPreload(arg_preload, arg_rootdir));
295-
if (opt_mount) exit(cmdMount(arg_mount, arg_rootdir));
295+
if (opt_mount) exit(cmdMount(nspid, arg_mount, arg_rootdir));
296296
if (opt_service) exit(cmdService(arg_service, nspid));
297297
if (opt_unservice) exit(cmdUnservice(nspid));
298298
if (opt_patch) exit(patchLibrary(arg_patch, FALSE) == PATCH_FAILED);

cli/rules/rules.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package rules
22

33
import (
44
"errors"
5+
"fmt"
56
"io"
67
"os"
78
"path/filepath"
9+
"strings"
810

911
"github.com/criblio/scope/libscope"
1012
"github.com/criblio/scope/loader"
@@ -184,6 +186,78 @@ func Add(rulesFile libscope.Rules, addProc, procArg, sourceid, rootdir string, r
184186

185187
// TBC ? perform a scope detach to all processes that do not match anything in the rules file
186188

189+
////////////////////////////////////////////
190+
// Apply rules to existing containers
191+
////////////////////////////////////////////
192+
193+
// Don't do the below if (not on host AND no rootdir provided)
194+
if util.InContainer() && rootdir == "" {
195+
return nil
196+
}
197+
198+
// Only if this is the first entry in the file
199+
// Rules will be applied in future containers by another mechanism (runc interposition)
200+
if len(rulesFile.Allow) == 1 {
201+
202+
// For each existing container
203+
cPids := util.GetContainersPids(rootdir)
204+
for _, cPid := range cPids {
205+
containerRootdir := fmt.Sprintf("%s/proc/%d/root", rootdir, cPid)
206+
207+
// Note: Install must be first so we don't trample on the host's files
208+
// The install is required even though we are mounting /usr/lib/appscope
209+
// because we need the /usr/lib/libscope.so link to be created AND we need
210+
// it to point to the correct version (glibc/musl)
211+
212+
// Install the library
213+
stdoutStderr, err = ld.Install(containerRootdir)
214+
if err != nil {
215+
log.Warn().
216+
Err(err).
217+
Str("loaderDetails", stdoutStderr).
218+
Msgf("Install library in %s namespace failed.", containerRootdir)
219+
return err
220+
}
221+
222+
// Set ld.preload.so to point to the library
223+
if stdoutStderr, err := ld.Preload("auto", containerRootdir); err != nil {
224+
log.Warn().
225+
Err(err).
226+
Str("loaderDetails", stdoutStderr).
227+
Msgf("Set /etc/ld.so.preload in %s namespace failed.", containerRootdir)
228+
return err
229+
}
230+
231+
// Mount `scope_rules` from the host into the container
232+
// ? support CRIBL_HOME
233+
stdoutStderr, err := ld.Mount("/usr/lib/appscope", cPid, rootdir)
234+
if err != nil {
235+
log.Warn().
236+
Err(err).
237+
Str("loaderDetails", stdoutStderr).
238+
Msgf("Mount /usr/lib/appscope in %d namespace failed.", cPid)
239+
return err
240+
}
241+
242+
// Mount unix socket from the host into the container
243+
unixPath = filepath.Dir(unixPath) // Strip the filename. We need to mount the dir
244+
// Hack for now, don't mount /var/run/... - it won't work. Just mount /run/...
245+
unixPath = strings.TrimPrefix(unixPath, "/var")
246+
if unixPath != "" {
247+
stdoutStderr, err = ld.Mount(unixPath, cPid, rootdir)
248+
if err != nil {
249+
log.Warn().
250+
Err(err).
251+
Str("loaderDetails", stdoutStderr).
252+
Msgf("Mount /usr/lib/appscope in %d namespace failed.", cPid)
253+
return err
254+
}
255+
}
256+
257+
// Attach is already taken care of, we attached to everything in rootdir and children
258+
}
259+
}
260+
187261
return nil
188262
}
189263

@@ -285,5 +359,35 @@ func Remove(rulesFile libscope.Rules, remProc, procArg, sourceid, rootdir string
285359
}
286360
}
287361

362+
////////////////////////////////////////////
363+
// Apply rules to existing containers
364+
////////////////////////////////////////////
365+
366+
// Don't do the below if (not on host AND no rootdir provided)
367+
if util.InContainer() && rootdir == "" {
368+
return nil
369+
}
370+
371+
// Only if this is the last entry in the file
372+
if len(rulesFile.Allow) == 0 {
373+
374+
// For each existing container
375+
cPids := util.GetContainersPids(rootdir)
376+
for _, cPid := range cPids {
377+
containerRootdir := fmt.Sprintf("%s/proc/%d/root", rootdir, cPid)
378+
379+
// Unset ld.preload.so
380+
if stdoutStderr, err := ld.Preload("off", containerRootdir); err != nil {
381+
log.Warn().
382+
Err(err).
383+
Str("loaderDetails", stdoutStderr).
384+
Msgf("Unset /etc/ld.so.preload in %s namespace failed.", containerRootdir)
385+
return err
386+
}
387+
388+
// Detach is already taken care of, we detached from everything in rootdir and children
389+
}
390+
}
391+
288392
return nil
289393
}

cli/util/namespace.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ var (
1212
)
1313

1414
// Get the LXD server unix socket
15-
func getLXDServerSocket() string {
15+
func getLXDServerSocket(rootdir string) string {
1616
socketPaths := []string{"/var/lib/lxd/unix.socket", "/var/snap/lxd/common/lxd/unix.socket"}
1717
for _, path := range socketPaths {
1818
if _, err := os.Stat(path); err == nil {
@@ -23,8 +23,8 @@ func getLXDServerSocket() string {
2323
}
2424

2525
// Get the List of PID(s) related to LXC container
26-
func GetLXCPids() ([]int, error) {
27-
lxdUnixPath := getLXDServerSocket()
26+
func GetLXCPids(rootdir string) ([]int, error) {
27+
lxdUnixPath := getLXDServerSocket(rootdir)
2828
if lxdUnixPath == "" {
2929
return nil, ErrLXDSocketNotAvailable
3030
}
@@ -50,32 +50,32 @@ func GetLXCPids() ([]int, error) {
5050
}
5151

5252
// Get the List of PID(s) related to containerd container
53-
func GetContainerDPids() ([]int, error) {
54-
return getContainerRuntimePids("containerd-shim")
53+
func GetContainerDPids(rootdir string) ([]int, error) {
54+
return getContainerRuntimePids(rootdir, "containerd-shim")
5555
}
5656

5757
// Get the List of PID(s) related to Podman container
58-
func GetPodmanPids() ([]int, error) {
59-
return getContainerRuntimePids("conmon")
58+
func GetPodmanPids(rootdir string) ([]int, error) {
59+
return getContainerRuntimePids(rootdir, "conmon")
6060
}
6161

6262
// Get the List of PID(s) related to specific container runtime
63-
func getContainerRuntimePids(runtimeProc string) ([]int, error) {
64-
runtimeContPids, err := PidScopeMapByProcessName("", runtimeProc)
63+
func getContainerRuntimePids(rootdir, runtimeProc string) ([]int, error) {
64+
runtimeContPids, err := PidScopeMapByProcessName(rootdir, runtimeProc)
6565
if err != nil {
6666
return nil, err
6767
}
6868
pids := make([]int, 0, len(runtimeContPids))
6969

7070
for runtimeContPid := range runtimeContPids {
71-
childrenPids, err := PidChildren("", runtimeContPid)
71+
childrenPids, err := PidChildren(rootdir, runtimeContPid)
7272
if err != nil {
7373
return nil, err
7474
}
7575

7676
// Iterate over all the children to found container init process
7777
for _, childPid := range childrenPids {
78-
status, _ := PidInitContainer("", childPid)
78+
status, _ := PidInitContainer(rootdir, childPid)
7979
if status {
8080
pids = append(pids, childPid)
8181
}

cli/util/proc.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -475,12 +475,12 @@ func PidExists(rootdir string, pid int) bool {
475475
}
476476

477477
// containerPids returns list of PID's of currently running containers
478-
func containerPids() []int {
478+
func containerPids(rootdir string) []int {
479479
cPids := []int{}
480-
ctrFuncs := []func() ([]int, error){GetContainerDPids, GetPodmanPids, GetLXCPids}
480+
ctrFuncs := []func(string) ([]int, error){GetContainerDPids, GetPodmanPids, GetLXCPids}
481481

482482
for _, ctrFunc := range ctrFuncs {
483-
ctrPids, err := ctrFunc()
483+
ctrPids, err := ctrFunc(rootdir)
484484
if err != nil {
485485
continue
486486
}
@@ -499,7 +499,7 @@ func PidGetRefPidForMntNamespace(rootdir string, targetPid int) int {
499499
}
500500

501501
// First check if the namespace used by process is the same namespace as CLI
502-
nsInfo, err := os.Readlink(fmt.Sprintf("%s/proc/self/ns/mnt", rootdir))
502+
nsInfo, err := os.Readlink(fmt.Sprintf("/proc/self/ns/mnt"))
503503
if err != nil {
504504
return -1
505505
}
@@ -509,7 +509,7 @@ func PidGetRefPidForMntNamespace(rootdir string, targetPid int) int {
509509
}
510510

511511
// Check if the namespace used by process belongs to one of the detected containers
512-
ctrPids := containerPids()
512+
ctrPids := containerPids(rootdir)
513513
for _, nsPid := range ctrPids {
514514
nsInfo, err := os.Readlink(fmt.Sprintf("%s/proc/%d/ns/mnt", rootdir, nsPid))
515515
if err != nil {

cli/util/util.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,11 @@ func RemoveEmptyStrings(s []string) []string {
421421
}
422422

423423
// GetContainersPids gets the list of PID(s) related to containers
424-
func GetContainersPids() []int {
424+
// Only works from a container for detecting non-LXC containers
425+
func GetContainersPids(rootdir string) []int {
425426
cPids := []int{}
426427

427-
ctrDPids, err := GetContainerDPids()
428+
ctrDPids, err := GetContainerDPids(rootdir)
428429
if err != nil {
429430
log.Error().
430431
Err(err).
@@ -434,7 +435,7 @@ func GetContainersPids() []int {
434435
cPids = append(cPids, ctrDPids...)
435436
}
436437

437-
podmanPids, err := GetPodmanPids()
438+
podmanPids, err := GetPodmanPids(rootdir)
438439
if err != nil {
439440
log.Error().
440441
Err(err).
@@ -444,7 +445,7 @@ func GetContainersPids() []int {
444445
cPids = append(cPids, podmanPids...)
445446
}
446447

447-
lxcPids, err := GetLXCPids()
448+
lxcPids, err := GetLXCPids(rootdir)
448449
if err != nil {
449450
switch {
450451
case errors.Is(err, ErrLXDSocketNotAvailable):

0 commit comments

Comments
 (0)