summaryrefslogtreecommitdiff
path: root/test/gvfs-testbed
blob: 5e36783a4a6cbd46239fdae144a56aca90f0b362 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/bin/bash
# Build an "unshared tmpfs" sandbox for gvfs-test to safely run tests which
# need root privileges.
#
# (C) 2012-2013 Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.

set -e
if [ "`id -u`" != 0 ]; then
    echo "Error: this test suite wrapper needs to be called as root" >&2
    exit 1
fi

if ! type smbd >/dev/null 2>&1; then
    echo "Error: this test suite wrapper needs samba installed" >&2
    exit 1
fi

# find out the user who calls us
pid=$$
while [ "`stat -c '%u' /proc/$pid`" = "0" ]; do
    pid=`awk '/^PPid:/ {print $2}' /proc/$pid/status`
    if [ -z "$pid" -o "$pid" = "1" ]; then
        echo "Error: Did not find a parent process that runs as non-root" >&2
        exit 1
    fi
done
CALLING_UID="`stat -c '%u' /proc/$pid`"
CALLING_USER="`stat -c '%U' /proc/$pid`"

# sanity check
[ "$CALLING_UID" -gt 0 ] && [ -n "$CALLING_USER" ]
CALLING_GROUP="`id -gn $CALLING_USER`"

# find udisks daemon
UDISKSD=`sed -n '/^Exec=/ { s/^[^=]*=//; p }' /usr/share/dbus-1/system-services/*UDisks2*.service | cut -f1 -d' '`
if [ ! -x "$UDISKSD" ]; then
    echo "Error: Did not find udisksd path" >&2
    exit 1
fi

# smbd needs to be restarted in the sandbox
(service smbd stop || service smb stop) && smbd_running=1 || :
(service nmbd stop || service nmb stop) && nmbd_running=1 || :

MNT=`mktemp -d`

# work around scsi_debug not implementing CD-ROM SCSI commands
# see https://launchpad.net/bugs/1043182 for details
if [ -d /run/udev/ -a ! -e /run/udev/rules.d/60-persistent-storage-scsi_debug.rules ]; then
    mkdir -p /run/udev/rules.d
    cat <<EOF > /run/udev/rules.d/60-persistent-storage-scsi_debug.rules
KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ATTRS{model}=="scsi_debug*", ENV{ID_CDROM_MEDIA}=="?*", IMPORT{program}="/sbin/blkid -o udev -p -u noraid \$tempnode"
EOF
    sync
    pkill -HUP udevd || pkill -HUP systemd-udevd
fi

# prevent nautilus popups for temporary drives in running sessions
pkill -STOP -f gvfs-udisks2-volume-monitor || :

cat <<EOF | unshare -m sh
set -e
mount --make-rprivate /
mount -n -t tmpfs tmpfs $MNT

# prepare overlay directories and copy essential configuration
mkdir -p $MNT/etc/samba $MNT/var/lib/samba/private $MNT/var/cache/samba $MNT/var/log/samba $MNT/home/$CALLING_USER/run $MNT/run_samba $MNT/media
touch $MNT/etc/fstab $MNT/home/gvfs_sandbox_marker
cp -a /etc/passwd /etc/shadow /etc/group /etc/hosts /etc/pam* /etc/nsswitch.conf /etc/security/ /etc/init.d /etc/systemd /etc/login.defs /etc/dbus-1 /etc/polkit-1 $MNT/etc/
if [ -d /etc/selinux ]; then
    cp -a /etc/selinux $MNT/etc/
fi
if [ -d /etc/init ]; then
    cp -a /etc/init $MNT/etc/
fi
chown -R $CALLING_USER:$CALLING_GROUP $MNT/home/$CALLING_USER
# ensure we can resolve our hostname
echo "127.0.0.1 `uname -n`" >> $MNT/etc/hosts

# copy our local mock polkitd into testbed
cp `dirname $0`/test_polkitd.py $MNT/home/

# Debianisms
if [ -d /etc/alternatives ]; then
    cp -a /etc/alternatives $MNT/etc/
fi
if [ -L /var/run ]; then
    cp -a /var/run $MNT/var
fi

# if we run a script, we need to copy it into the sandbox as it might be in
# a directory that we overlay
if [ -f "$1" ]; then
    cp -a "$1" $MNT/home/gvfs-testbed-script
    ARGS="/home/gvfs-testbed-script ${@:2}"

    # we need to copy our test files as well, if we run gvfs-test
    if [ -d "`dirname $1`/files" ]; then
        cp -a "`dirname $1`/files" $MNT/home
    fi
else
    ARGS="$@"
fi

# realize our overlays
mount -n --bind $MNT/etc/ /etc/
mount -n --bind $MNT/home/ /home/
mount -n --bind $MNT/var/ /var/
mount -n --bind $MNT/media/ /media
mkdir -p /run/samba
mount -n --bind $MNT/run_samba/ /run/samba

# run Samba with local configuration/state
cat <<SMBEOF >/etc/samba/smb.conf
[global]
workgroup = TESTGROUP
interfaces = 127.0.0.0/8
map to guest = Bad User

[public]
path = /home/$CALLING_USER/public
guest ok = yes

[private]
path = /home/$CALLING_USER/private
read only = no
SMBEOF
nmbd -D -l /var/log/samba
smbd -D -l /var/log/samba

# we need a predictable password for the smb:// authenticated test, so change
# it to "foo" in the sandbox
/bin/echo -e 'foo\\nfoo\\n' | smbpasswd -a $CALLING_USER -s

# set up SSH key for test user
su -lc "mkdir ~/.ssh; ssh-keygen -q -f ~/.ssh/id_rsa -N ''" $CALLING_USER

# create a root shell that the user can call to control scsi_debug and
# similar
cp /bin/sh /home/$CALLING_USER/rootsh
chown root:$CALLING_USER /home/$CALLING_USER/rootsh
chmod 4550 /home/$CALLING_USER/rootsh

# we must start udisksd in our private mount environment, so that gvfs and
# udisks agree to the same view of mounts
$UDISKSD --no-debug --replace &
UDISKS_PID=\$!

echo "Running commmand in testbed: \$ARGS"
su -lc "export PATH=$PATH; export XDG_RUNTIME_DIR=/home/$CALLING_USER/run; \$ARGS" $CALLING_USER || {
    RC=\$?
    echo "=== command failed, showing Samba log files ==="
    for f in /var/log/samba/log.*; do
        echo "--- \$f ---"
        cat \$f
    done
}
(cat /var/run/samba/*.pid | xargs kill ) || ( cat /var/run/[sn]mbd.pid | xargs kill )
kill \$UDISKS_PID || :
exit \$RC
EOF
RC=$?

pkill -CONT -f gvfs-udisks2-volume-monitor || :

[ -n "$smbd_running" ] && service smbd start || service smb start || :
[ -n "$nmbd_running" ] && service nmbd start || service nmb start || :

rmdir "$MNT" || :
exit $RC