Exemplo n.º 1
0
    def _unmount_as_user_fstab_fail(self, pipe, uid, gid, device):
        """ Try to unmount @device as user with given @uid and @gid.
            @device shouldn't be listed in /etc/fstab when running this, so
            this is expected to fail.
        """
        os.setresgid(gid, gid, gid)
        os.setresuid(uid, uid, uid)

        # try to mount the device -- it should fail
        try:
            safe_dbus.call_sync(self.iface_prefix,
                                self.path_prefix + '/block_devices/' + os.path.basename(device),
                                self.iface_prefix + '.Filesystem',
                                'Unmount',
                                GLib.Variant('(a{sv})', ({},)))
        except Exception as e:
            msg = 'GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain: Not authorized to perform operation'
            if msg in str(e):
                pipe.send([True, ''])
                pipe.close()
                return
            else:
                pipe.send([False, 'Unmount DBus call failed with unexpected exception: %s' % str(e)])
                pipe.close()
                return

        ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device)
        if ret == 0:
            pipe.send([False, 'Unmount DBus call didn\'t fail but %s seems to be still mounted.' % device])
            pipe.close()
            return
        else:
            pipe.send([False, '%s was unmounted for UID %d without proper record in fstab' % (device, uid)])
            pipe.close()
            return
Exemplo n.º 2
0
    def _unmount_as_user_fstab_fail(self, pipe, uid, gid, device):
        """ Try to unmount @device as user with given @uid and @gid.
            @device shouldn't be listed in /etc/fstab when running this, so
            this is expected to fail.
        """
        os.setresgid(gid, gid, gid)
        os.setresuid(uid, uid, uid)

        # try to mount the device -- it should fail
        try:
            safe_dbus.call_sync(self.iface_prefix,
                                self.path_prefix + '/block_devices/' + os.path.basename(device),
                                self.iface_prefix + '.Filesystem',
                                'Unmount',
                                GLib.Variant('(a{sv})', ({},)))
        except Exception as e:
            msg = 'GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain: Not authorized to perform operation'
            if msg in str(e):
                pipe.send([True, ''])
                pipe.close()
                return
            else:
                pipe.send([False, 'Unmount DBus call failed with unexpected exception: %s' % str(e)])
                pipe.close()
                return

        ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device)
        if ret == 0:
            pipe.send([False, 'Unmount DBus call didn\'t fail but %s seems to be still mounted.' % device])
            pipe.close()
            return
        else:
            pipe.send([False, '%s was unmounted for UID %d without proper record in fstab' % (device, uid)])
            pipe.close()
            return
Exemplo n.º 3
0
    def _mount_as_user_fstab(self, pipe, uid, gid, device):
        """ Try to mount and then unmount @device as user with given @uid and
            @gid.
            @device should be listed in /etc/fstab with proper options so user
            is able to run these operations and this shouldn't fail.
        """
        os.setresgid(gid, gid, gid)
        os.setresuid(uid, uid, uid)

        # try to mount the device
        try:
            safe_dbus.call_sync(self.iface_prefix,
                                self.path_prefix + '/block_devices/' + os.path.basename(device),
                                self.iface_prefix + '.Filesystem',
                                'Mount',
                                GLib.Variant('(a{sv})', ({},)))
        except Exception as e:
            pipe.send([False, 'Mount DBus call failed: %s' % str(e)])
            pipe.close()
            return

        ret, out = self.run_command('grep \"%s\" /proc/mounts' % device)
        if ret != 0:
            pipe.send([False, '%s not mounted' % device])
            pipe.close()
            return

        if 'uid=%s,gid=%s' % (uid, gid) not in out:
            pipe.send([False, '%s not mounted with given uid/gid.\nMount info: %s' % (device, out)])
            pipe.close()
            return

        pipe.send([True, ''])
        pipe.close()
        return
Exemplo n.º 4
0
    def _unmount_as_user_fstab(self, pipe, uid, gid, device):
        """ Try to unmount @device as user with given @uid and @gid.
            @device should be listed in /etc/fstab with "users" option when running this, so
            this is expected to succeed.
        """
        os.setresgid(gid, gid, gid)
        os.setresuid(uid, uid, uid)

        # try to unmount the device
        try:
            safe_dbus.call_sync(self.iface_prefix,
                                self.path_prefix + '/block_devices/' + os.path.basename(device),
                                self.iface_prefix + '.Filesystem',
                                'Unmount',
                                GLib.Variant('(a{sv})', ({},)))
        except Exception as e:
            pipe.send([False, 'Unmount DBus call failed: %s' % str(e)])
            pipe.close()
            return

        ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device)
        if ret == 0:
            pipe.send([False, 'Unmount DBus call didn\'t fail but %s seems to be still mounted.' % device])
            pipe.close()
            return
        else:
            pipe.send([True, ''])
            pipe.close()
            return
Exemplo n.º 5
0
 def _secure_erase(self, devname):
     try:
         safe_dbus.call_sync(self.iface_prefix,
                             self.path_prefix + '/block_devices/' + devname,
                             self.iface_prefix + '.Block',
                             'Format',
                             GLib.Variant('(sa{sv})', ('empty', {'erase': GLib.Variant("s", 'zero')})))
     except Exception as e:
         self.exception = e
Exemplo n.º 6
0
    def test_job(self):
        '''Test basic Job functionality and properties'''

        disk_name = os.path.basename(self.vdevs[0])
        obj_path = self.path_prefix + '/block_devices/' + disk_name

        start_time = time.time()

        watch_thread = threading.Thread(target=self._wait_for_job_thread,
                                        args=('format-erase', obj_path))
        watch_thread.start()

        erase_thread = threading.Thread(target=self._secure_erase,
                                        args=(disk_name, ))
        erase_thread.start()
        erase_thread.join()

        # erase thread finished, stop job searching
        watch_thread.run = False
        watch_thread.join()

        # unexpected exception occured in erase thread -- raise it
        # timeout reached is actually ok -- zeroing the device may take a long
        # time, but we just want to check the job object
        if self.exception is not None and not str(
                self.exception).endswith('Timeout was reached'):
            raise self.exception

        # we should have the job dict now
        self.assertIsNotNone(self.job)

        # get all the properties from the dict
        properties = self.job[1][self.iface_prefix + '.Job']

        _ret, disk_size = self.run_command(
            'lsblk -d -b -no SIZE %s' %
            self.vdevs[0])  # get size of the device
        self.assertEqual(properties['Bytes'], int(disk_size))

        self.assertEqual(properties['StartedByUID'], os.getuid())

        # test start time -- should be less than ~0.5s after thread started
        # (dbus property is in micro seconds)
        self.assertLessEqual(abs(properties['StartTime'] - start_time * 10**6),
                             0.5 * 10**6)

        self.assertTrue(properties['Cancelable'])

        # job still exists -- erase call timed out -- try to cancel it
        if safe_dbus.check_object_available(self.iface_prefix, self.job[0],
                                            self.iface_prefix + '.Job'):
            try:
                safe_dbus.call_sync(self.iface_prefix, self.job[0],
                                    self.iface_prefix + '.Job', 'Cancel',
                                    GLib.Variant('(a{sv})', ({}, )))
            except safe_dbus.DBusCallError:
                pass
Exemplo n.º 7
0
 def _secure_erase(self, devname):
     try:
         safe_dbus.call_sync(self.iface_prefix,
                             self.path_prefix + '/block_devices/' + devname,
                             self.iface_prefix + '.Block',
                             'Format',
                             GLib.Variant('(sa{sv})', ('empty', {'erase': GLib.Variant("s", 'zero')})))
     except Exception as e:
         self.exception = e
Exemplo n.º 8
0
    def _mount_as_user_fstab(self, pipe, uid, gid, device):
        """ Try to mount and then unmount @device as user with given @uid and
            @gid.
            @device should be listed in /etc/fstab with proper options so user
            is able to run these operations and this shouldn't fail.
        """
        os.setresgid(gid, gid, gid)
        os.setresuid(uid, uid, uid)

        # try to mount the device
        try:
            safe_dbus.call_sync(self.iface_prefix,
                                self.path_prefix + '/block_devices/' + os.path.basename(device),
                                self.iface_prefix + '.Filesystem',
                                'Mount',
                                GLib.Variant('(a{sv})', ({},)))
        except Exception as e:
            pipe.send([False, 'Mount DBus call failed: %s' % str(e)])
            pipe.close()
            return

        ret, out = self.run_command('grep \"%s\" /proc/mounts' % device)
        if ret != 0:
            pipe.send([False, '%s not mounted' % device])
            pipe.close()
            return

        if 'uid=%s,gid=%s' % (uid, gid) not in out:
            pipe.send([False, '%s not mounted with given uid/gid.\nMount info: %s' % (device, out)])
            pipe.close()
            return

        # and now try to unmount it
        try:
            safe_dbus.call_sync(self.iface_prefix,
                                self.path_prefix + '/block_devices/' + os.path.basename(device),
                                self.iface_prefix + '.Filesystem',
                                'Unmount',
                                GLib.Variant('(a{sv})', ({},)))
        except Exception as e:
            pipe.send([False, 'Unmount DBus call failed: %s' % str(e)])
            pipe.close()
            return

        ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device)
        if ret == 0:
            pipe.send([False, '%s mounted after unmount called' % device])
            pipe.close()
            return

        pipe.send([True, ''])
        pipe.close()
        return
Exemplo n.º 9
0
 def _get_objects(self):
     objects = safe_dbus.call_sync(self.iface_prefix,
                                   self.path_prefix,
                                   'org.freedesktop.DBus.ObjectManager',
                                   'GetManagedObjects',
                                   None)
     return objects
Exemplo n.º 10
0
 def _get_objects(self):
     objects = safe_dbus.call_sync(self.iface_prefix,
                                   self.path_prefix,
                                   'org.freedesktop.DBus.ObjectManager',
                                   'GetManagedObjects',
                                   None)
     return objects
Exemplo n.º 11
0
    def test_cancel(self):
        '''Test if it's possible to cancel the Job'''

        disk_name = os.path.basename(self.vdevs[0])
        obj_path = self.path_prefix + '/block_devices/' + disk_name

        watch_thread = threading.Thread(target=self._wait_for_job_thread,
                                        args=('format-erase', obj_path))
        watch_thread.start()

        erase_thread = threading.Thread(target=self._secure_erase,
                                        args=(disk_name, ))
        erase_thread.start()

        # watch thread should end first -- we need the job before erase finishes
        watch_thread.join(timeout=10)
        if not self.job:
            watch_thread.run = False  # stop the watch thread now
            if self.exception:  # exception in erase thread -- just raise it
                raise self.exception
            else:  # didn't find the job but no exception
                self.fail('Failed to find the job objects.')

        job_path = self.job[0]

        # cancel the job
        safe_dbus.call_sync(self.iface_prefix, job_path,
                            self.iface_prefix + '.Job', 'Cancel',
                            GLib.Variant('(a{sv})', ({}, )))

        # job shouldn't be in managed objects
        objects = self._get_objects()
        self.assertNotIn(job_path, objects[0].items())

        erase_thread.join()

        # erase thread should raise exception (it's stored in self.exception)
        self.assertIsNotNone(self.exception)
        self.assertTrue(isinstance(self.exception, safe_dbus.DBusCallError))
        self.assertIn('Error erasing device: Job was canceled',
                      str(self.exception))
Exemplo n.º 12
0
    def test_cancel(self):
        '''Test if it's possible to cancel the Job'''

        disk_name = os.path.basename(self.vdevs[0])
        obj_path = self.path_prefix + '/block_devices/' + disk_name

        watch_thread = threading.Thread(target=self._wait_for_job_thread, args=('format-erase', obj_path))
        watch_thread.start()

        erase_thread = threading.Thread(target=self._secure_erase, args=(disk_name,))
        erase_thread.start()

        # watch thread should end first -- we need the job before erase finishes
        watch_thread.join(timeout=10)
        if not self.job:
            watch_thread.run = False  # stop the watch thread now
            if self.exception:  # exception in erase thread -- just raise it
                raise self.exception
            else:  # didn't find the job but no exception
                self.fail('Failed to find the job objects.')

        job_path = self.job[0]

        # cancel the job
        safe_dbus.call_sync(self.iface_prefix,
                            job_path,
                            self.iface_prefix + '.Job',
                            'Cancel',
                            GLib.Variant('(a{sv})', ({},)))

        # job shouldn't be in managed objects
        objects = self._get_objects()
        self.assertNotIn(job_path, objects[0].items())

        erase_thread.join()

        # erase thread should raise exception (it's stored in self.exception)
        self.assertIsNotNone(self.exception)
        self.assertTrue(isinstance(self.exception, safe_dbus.DBusCallError))
        self.assertIn('Error erasing device: Job was canceled', str(self.exception))