Add cheatmounting
This commit is contained in:
parent
dcd73ec05e
commit
24089d19e2
4 changed files with 166 additions and 40 deletions
|
@ -25,6 +25,15 @@
|
||||||
#include <grub/crypto.h>
|
#include <grub/crypto.h>
|
||||||
#include <grub/extcmd.h>
|
#include <grub/extcmd.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <grub/emu/hostdisk.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -80,6 +89,10 @@ struct grub_luks
|
||||||
unsigned long id, source_id;
|
unsigned long id, source_id;
|
||||||
enum grub_disk_dev_id source_dev_id;
|
enum grub_disk_dev_id source_dev_id;
|
||||||
char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1];
|
char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1];
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
char *cheat;
|
||||||
|
int cheat_fd;
|
||||||
|
#endif
|
||||||
struct grub_luks *next;
|
struct grub_luks *next;
|
||||||
};
|
};
|
||||||
typedef struct grub_luks *grub_luks_t;
|
typedef struct grub_luks *grub_luks_t;
|
||||||
|
@ -497,6 +510,12 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source)
|
||||||
}
|
}
|
||||||
|
|
||||||
newdev->source = grub_strdup (name);
|
newdev->source = grub_strdup (name);
|
||||||
|
if (!newdev->source)
|
||||||
|
{
|
||||||
|
grub_free (newdev);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
newdev->source_id = source->id;
|
newdev->source_id = source->id;
|
||||||
newdev->source_dev_id = source->dev->id;
|
newdev->source_dev_id = source->dev->id;
|
||||||
newdev->next = luks_list;
|
newdev->next = luks_list;
|
||||||
|
@ -507,6 +526,48 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source)
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
grub_err_t
|
||||||
|
grub_luks_cheat_mount (const char *sourcedev, const char *cheat)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
struct grub_luks_phdr header;
|
||||||
|
grub_luks_t newdev;
|
||||||
|
grub_disk_t source;
|
||||||
|
|
||||||
|
/* Try to open disk. */
|
||||||
|
source = grub_disk_open (sourcedev);
|
||||||
|
if (!source)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
/* Read the LUKS header. */
|
||||||
|
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
newdev = configure_ciphers (&header);
|
||||||
|
grub_disk_close (source);
|
||||||
|
if (!newdev)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
newdev->cheat = grub_strdup (cheat);
|
||||||
|
newdev->source = grub_strdup (sourcedev);
|
||||||
|
if (!newdev->source || !newdev->cheat)
|
||||||
|
{
|
||||||
|
grub_free (newdev->source);
|
||||||
|
grub_free (newdev->cheat);
|
||||||
|
grub_free (newdev);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
newdev->cheat_fd = -1;
|
||||||
|
newdev->source_id = source->id;
|
||||||
|
newdev->source_dev_id = source->dev->id;
|
||||||
|
newdev->next = luks_list;
|
||||||
|
luks_list = newdev;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_luks_scan_device (const char *name)
|
grub_luks_scan_device (const char *name)
|
||||||
{
|
{
|
||||||
|
@ -575,6 +636,17 @@ grub_luks_open (const char *name, grub_disk_t disk,
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
|
||||||
|
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
if (dev->cheat)
|
||||||
|
{
|
||||||
|
if (dev->cheat_fd == -1)
|
||||||
|
dev->cheat_fd = open (dev->cheat, O_RDONLY);
|
||||||
|
if (dev->cheat_fd == -1)
|
||||||
|
return grub_error (GRUB_ERR_IO, "couldn't open %s: %s",
|
||||||
|
dev->cheat, strerror (errno));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!dev->source_disk)
|
if (!dev->source_disk)
|
||||||
{
|
{
|
||||||
grub_dprintf ("luks", "Opening device %s\n", name);
|
grub_dprintf ("luks", "Opening device %s\n", name);
|
||||||
|
@ -599,11 +671,17 @@ grub_luks_close (grub_disk_t disk)
|
||||||
|
|
||||||
dev->ref--;
|
dev->ref--;
|
||||||
|
|
||||||
if (dev->ref == 0)
|
if (dev->ref != 0)
|
||||||
|
return;
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
if (dev->cheat)
|
||||||
{
|
{
|
||||||
grub_disk_close (dev->source_disk);
|
close (dev->cheat_fd);
|
||||||
dev->source_disk = NULL;
|
dev->cheat_fd = -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
grub_disk_close (dev->source_disk);
|
||||||
|
dev->source_disk = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -612,6 +690,21 @@ grub_luks_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
{
|
{
|
||||||
grub_luks_t dev = (grub_luks_t) disk->data;
|
grub_luks_t dev = (grub_luks_t) disk->data;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
if (dev->cheat)
|
||||||
|
{
|
||||||
|
err = grub_util_fd_sector_seek (dev->cheat_fd, dev->cheat, sector);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
if (grub_util_fd_read (dev->cheat_fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
||||||
|
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||||
|
return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'",
|
||||||
|
dev->cheat);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
grub_dprintf ("luks",
|
grub_dprintf ("luks",
|
||||||
"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
|
"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
|
||||||
PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT32_T "\n",
|
PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT32_T "\n",
|
||||||
|
|
|
@ -865,7 +865,9 @@ out:
|
||||||
void
|
void
|
||||||
grub_util_pull_device (const char *os_dev)
|
grub_util_pull_device (const char *os_dev)
|
||||||
{
|
{
|
||||||
switch (grub_util_get_dev_abstraction (os_dev))
|
int ab;
|
||||||
|
ab = grub_util_get_dev_abstraction (os_dev);
|
||||||
|
switch (ab)
|
||||||
{
|
{
|
||||||
case GRUB_DEV_ABSTRACTION_LVM:
|
case GRUB_DEV_ABSTRACTION_LVM:
|
||||||
case GRUB_DEV_ABSTRACTION_LUKS:
|
case GRUB_DEV_ABSTRACTION_LUKS:
|
||||||
|
@ -875,6 +877,7 @@ grub_util_pull_device (const char *os_dev)
|
||||||
struct dm_tree_node *node;
|
struct dm_tree_node *node;
|
||||||
struct dm_tree_node *child;
|
struct dm_tree_node *child;
|
||||||
void *handle = NULL;
|
void *handle = NULL;
|
||||||
|
char *lastsubdev = NULL;
|
||||||
|
|
||||||
if (!grub_util_open_dm (os_dev, &tree, &node))
|
if (!grub_util_open_dm (os_dev, &tree, &node))
|
||||||
return;
|
return;
|
||||||
|
@ -887,9 +890,26 @@ grub_util_pull_device (const char *os_dev)
|
||||||
continue;
|
continue;
|
||||||
subdev = grub_find_device ("/dev", makedev (dm->major, dm->minor));
|
subdev = grub_find_device ("/dev", makedev (dm->major, dm->minor));
|
||||||
if (subdev)
|
if (subdev)
|
||||||
grub_util_pull_device (subdev);
|
{
|
||||||
|
lastsubdev = subdev;
|
||||||
|
grub_util_pull_device (subdev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dm_tree_free (tree);
|
if (ab == GRUB_DEV_ABSTRACTION_LUKS && lastsubdev)
|
||||||
|
{
|
||||||
|
char *grdev = grub_util_get_grub_dev (lastsubdev);
|
||||||
|
dm_tree_free (tree);
|
||||||
|
if (grdev)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
err = grub_luks_cheat_mount (grdev, os_dev);
|
||||||
|
if (err)
|
||||||
|
grub_util_error ("Can't mount LUKS: %s", grub_errmsg);
|
||||||
|
}
|
||||||
|
grub_free (grdev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dm_tree_free (tree);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -631,6 +631,37 @@ linux_find_partition (char *dev, unsigned long sector)
|
||||||
}
|
}
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
|
#if defined(__linux__) && (!defined(__GLIBC__) || \
|
||||||
|
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
|
||||||
|
/* Maybe libc doesn't have large file support. */
|
||||||
|
grub_err_t
|
||||||
|
grub_util_fd_sector_seek (int fd, const char *name, grub_disk_addr_t sector)
|
||||||
|
{
|
||||||
|
loff_t offset, result;
|
||||||
|
static int _llseek (uint filedes, ulong hi, ulong lo,
|
||||||
|
loff_t *res, uint wh);
|
||||||
|
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
|
||||||
|
loff_t *, res, uint, wh);
|
||||||
|
|
||||||
|
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
|
||||||
|
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
|
||||||
|
{
|
||||||
|
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name);
|
||||||
|
}
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
grub_err_t
|
||||||
|
grub_util_fd_sector_seek (int fd, const char *name, grub_disk_addr_t sector)
|
||||||
|
{
|
||||||
|
off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
|
||||||
|
|
||||||
|
if (lseek (fd, offset, SEEK_SET) != offset)
|
||||||
|
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
{
|
{
|
||||||
|
@ -781,44 +812,19 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
configure_device_driver (fd);
|
configure_device_driver (fd);
|
||||||
#endif /* defined(__NetBSD__) */
|
#endif /* defined(__NetBSD__) */
|
||||||
|
|
||||||
#if defined(__linux__) && (!defined(__GLIBC__) || \
|
if (grub_util_fd_sector_seek (fd, map[disk->id].device, sector))
|
||||||
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
|
{
|
||||||
/* Maybe libc doesn't have large file support. */
|
close (fd);
|
||||||
{
|
return -1;
|
||||||
loff_t offset, result;
|
}
|
||||||
static int _llseek (uint filedes, ulong hi, ulong lo,
|
|
||||||
loff_t *res, uint wh);
|
|
||||||
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
|
|
||||||
loff_t *, res, uint, wh);
|
|
||||||
|
|
||||||
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
|
|
||||||
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
|
|
||||||
{
|
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
|
|
||||||
close (fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
|
|
||||||
|
|
||||||
if (lseek (fd, offset, SEEK_SET) != offset)
|
|
||||||
{
|
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
|
|
||||||
close (fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
|
/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
|
||||||
error occurs, otherwise return LEN. */
|
error occurs, otherwise return LEN. */
|
||||||
static ssize_t
|
ssize_t
|
||||||
nread (int fd, char *buf, size_t len)
|
grub_util_fd_read (int fd, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
ssize_t size = len;
|
ssize_t size = len;
|
||||||
|
|
||||||
|
@ -901,7 +907,8 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
sectors that are read together with the MBR in one read. It
|
sectors that are read together with the MBR in one read. It
|
||||||
should only remap the MBR, so we split the read in two
|
should only remap the MBR, so we split the read in two
|
||||||
parts. -jochen */
|
parts. -jochen */
|
||||||
if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
|
if (grub_util_fd_read (fd, buf, GRUB_DISK_SECTOR_SIZE)
|
||||||
|
!= GRUB_DISK_SECTOR_SIZE)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
|
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -912,7 +919,7 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
}
|
}
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
if (grub_util_fd_read (fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
||||||
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
|
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER 1
|
#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER 1
|
||||||
|
|
||||||
#include <grub/disk.h>
|
#include <grub/disk.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
void grub_util_biosdisk_init (const char *dev_map);
|
void grub_util_biosdisk_init (const char *dev_map);
|
||||||
void grub_util_biosdisk_fini (void);
|
void grub_util_biosdisk_fini (void);
|
||||||
|
@ -30,5 +31,10 @@ int grub_util_biosdisk_is_present (const char *name);
|
||||||
int grub_util_biosdisk_is_floppy (grub_disk_t disk);
|
int grub_util_biosdisk_is_floppy (grub_disk_t disk);
|
||||||
grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk);
|
grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk);
|
||||||
void grub_util_pull_device (const char *osname);
|
void grub_util_pull_device (const char *osname);
|
||||||
|
grub_err_t
|
||||||
|
grub_util_fd_sector_seek (int fd, const char *name, grub_disk_addr_t sector);
|
||||||
|
ssize_t grub_util_fd_read (int fd, char *buf, size_t len);
|
||||||
|
grub_err_t
|
||||||
|
grub_luks_cheat_mount (const char *sourcedev, const char *cheat);
|
||||||
|
|
||||||
#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
|
#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
|
||||||
|
|
Loading…
Reference in a new issue