From b877c3546f5e523df641e3d237cde34c31265c51 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 12 Oct 2023 19:07:02 +0200 Subject: targets: remove TargetSSHLXCLVM It is complex and fragile and has been replaced by idmapping/TargetSSHLVM/strip_mountpoint=True. Also drop nsmount.c, which was to be used with this target. --- lbup/targets.py | 105 +++----------------------------------------------------- 1 file changed, 5 insertions(+), 100 deletions(-) (limited to 'lbup') diff --git a/lbup/targets.py b/lbup/targets.py index 37a58f0..d6d44ff 100644 --- a/lbup/targets.py +++ b/lbup/targets.py @@ -241,11 +241,6 @@ class TargetSSHLVM(TargetSSH): """ _snapshot_size = None - """ - PID of the process whose mount namespace we use. - """ - _mntns_pid = None - _strip_mountpoint = None def __init__(self, name, dirs, excludes = None, logger = None, @@ -259,22 +254,6 @@ class TargetSSHLVM(TargetSSH): def __str__(self): return "%s{LVM:%s}" % (super().__str__(), self._snapshot_size) - def _root_remote(self): - """ - The the remote for root operations, such as manipulating LVM. - - Overridden in subclasses. - """ - return SSHRemote(self._remote.host, self._remote.port, - 'root', self._remote.proxy_remote) - - def _resolve_mntns(self, ssh): - """ - Get the PID of the process whose mount namespace we use. - Always 1 here, overridden in subclasses. - """ - return 1 - def _resolve_lv(self, ssh, devnum): """ Find the logical volume for the given device number. @@ -347,8 +326,11 @@ class TargetSSHLVM(TargetSSH): def save(self, dry_run = False): with contextlib.ExitStack() as stack: + root_remote = SSHRemote(self._remote.host, self._remote.port, + 'root', self._remote.proxy_remote) + conn_tgt = stack.enter_context(_ssh_client.SSHConnection(self._remote)) - conn_root = stack.enter_context(_ssh_client.SSHConnection(self._root_remote())) + conn_root = stack.enter_context(_ssh_client.SSHConnection(root_remote)) # resolve the remote paths bupdir = self._resolve_remote_path(conn_tgt, self._remote_bupdir) @@ -362,12 +344,9 @@ class TargetSSHLVM(TargetSSH): snapshot_mount = '%s/%s' % (bupdir, 'lbup_mount') self._paramiko_exec_cmd(conn_tgt, 'mkdir -p -m 700 ' + snapshot_mount) - self._mntns_pid = self._resolve_mntns(conn_root) - # read and parse the mountinfo table mntinfo = MountInfo( - self._paramiko_exec_cmd(conn_root, 'cat /proc/%d/mountinfo' % self._mntns_pid, - decode = False)) + self._paramiko_exec_cmd(conn_root, 'cat /proc/1/mountinfo', decode = False)) devnum, mountpoint, fstype = _resolve_mntdev(mntinfo, dirs) @@ -392,77 +371,3 @@ class TargetSSHLVM(TargetSSH): return self._do_save(bup_exec, dry_run, dirs = dirs, excludes = excludes, save_opts = save_opts, index_opts = index_opts) - -class TargetSSHLXCLVM(TargetSSHLVM): - """ - This target backs up an LXC container that lives on its own LVM logical - volume. Requires root-capable login on the container's host. - - :param SSHRemote parent_remote: - """ - # The container is treated as untrusted, so all code here needs to be - # careful to avoid giving it access to anything it would not have otherwise. - # Specifically, any information obtained by running binaries in the - # container should be assumed to have been potentially maliciously - # manipulated. No binaries from the container should be run as the (host) root. - _parent_remote = None - _lxc_username = None - _lxc_containername = None - - def __init__(self, name, dirs, excludes = None, logger = None, - target_remote = None, target_remote_bupdir = None, - parent_remote = None, - lxc_username = None, lxc_containername = None, - snapshot_size = '20G'): - if parent_remote is None: - raise ValueError('parent_remote not specified') - if lxc_username is None: - lxc_username = parent_remote.usename - - self._parent_remote = parent_remote - self._lxc_username = lxc_username - self._lxc_containername = lxc_containername - - super().__init__(name, dirs, excludes, logger, - target_remote, target_remote_bupdir, - snapshot_size) - - def __str__(self): - return "%s{LXC:%s/%s@[%s]}{LVM:%s}" % (super().__str__(), self._lxc_containername, - self._lxc_username, str(self._parent_remote), self._snapshot_size) - - def _resolve_mntns(self, ssh): - # get the PID of the container's init - cmd = 'su -s /bin/sh -c "lxc-info -H -p -n {container}" {user}'.format( - container = self._lxc_containername, user = self._lxc_username) - container_pid = self._paramiko_exec_cmd(ssh, cmd).rstrip('\n') - return int(container_pid) - - def _root_remote(self): - return self._parent_remote - - @contextlib.contextmanager - def _mount_snapshot(self, ssh, devnum, mount_path, fstype): - """ - Return a context manager that creates a read-only LVM snapshot - for the specified LV device number and mounts it at mount_path - inside the container, then unmounts and destroys it at exit. - """ - with self._snapshot_lv(ssh, devnum) as lv_path: - # we cannot trust any binaries located inside the container, since a - # compromised container could use them to execute arbitrary code - # with real root privileges, thus nullifying the point of - # unprivileged containers) - # so we ship a special tool, 'nsmount', which has to be - # installed on the parent, to mount the snapshot into the - # container mount namespace - self._paramiko_exec_cmd(ssh, - 'nsmount m {pid} {mount_path} {lv_path} {fstype}'.format( - pid = self._mntns_pid, mount_path = mount_path, - lv_path = lv_path, fstype = fstype)) - try: - yield None - finally: - self._paramiko_exec_cmd(ssh, - 'nsmount u {pid} {mount_path}'.format( - pid = self._mntns_pid, mount_path = mount_path)) -- cgit v1.2.3